Snap for 5132890 from 18d90eaf05d8b3a21a68d84ebf23ea2326067aad to qt-release
Change-Id: I6fcfc0492ea9a6574f78f69a21b277d826f4db17
diff --git a/libs/input/VelocityTracker.cpp b/libs/input/VelocityTracker.cpp
index 1bbd82b..42d774e 100644
--- a/libs/input/VelocityTracker.cpp
+++ b/libs/input/VelocityTracker.cpp
@@ -327,8 +327,8 @@
eventTime = event->getHistoricalEventTime(h);
for (size_t i = 0; i < pointerCount; i++) {
uint32_t index = pointerIndex[i];
- positions[index].x = event->getHistoricalRawX(i, h);
- positions[index].y = event->getHistoricalRawY(i, h);
+ positions[index].x = event->getHistoricalX(i, h);
+ positions[index].y = event->getHistoricalY(i, h);
}
addMovement(eventTime, idBits, positions);
}
@@ -336,8 +336,8 @@
eventTime = event->getEventTime();
for (size_t i = 0; i < pointerCount; i++) {
uint32_t index = pointerIndex[i];
- positions[index].x = event->getRawX(i);
- positions[index].y = event->getRawY(i);
+ positions[index].x = event->getX(i);
+ positions[index].y = event->getY(i);
}
addMovement(eventTime, idBits, positions);
}
diff --git a/libs/nativewindow/Android.bp b/libs/nativewindow/Android.bp
index 647fe86..fba319d 100644
--- a/libs/nativewindow/Android.bp
+++ b/libs/nativewindow/Android.bp
@@ -47,6 +47,7 @@
cflags: [
"-Wall",
"-Werror",
+ "-Wno-enum-compare",
"-Wno-unused-function",
],
diff --git a/libs/nativewindow/include/android/hardware_buffer.h b/libs/nativewindow/include/android/hardware_buffer.h
index 9ca4941..23ac60b 100644
--- a/libs/nativewindow/include/android/hardware_buffer.h
+++ b/libs/nativewindow/include/android/hardware_buffer.h
@@ -15,12 +15,31 @@
*/
/**
- * @addtogroup NativeActivity Native Activity
- * @{
- */
-
-/**
* @file hardware_buffer.h
+ * @brief API for native hardware buffers.
+ */
+/**
+ * @defgroup AHardwareBuffer Native Hardware Buffer
+ *
+ * AHardwareBuffer objects represent chunks of memory that can be
+ * accessed by various hardware components in the system. It can be
+ * easily converted to the Java counterpart
+ * android.hardware.HardwareBuffer and passed between processes using
+ * Binder. All operations involving AHardwareBuffer and HardwareBuffer
+ * are zero-copy, i.e., passing AHardwareBuffer to another process
+ * creates a shared view of the same region of memory.
+ *
+ * AHardwareBuffers can be bound to EGL/OpenGL and Vulkan primitives.
+ * For EGL, use the extension function eglGetNativeClientBufferANDROID
+ * to obtain an EGLClientBuffer and pass it directly to
+ * eglCreateImageKHR. Refer to the EGL extensions
+ * EGL_ANDROID_get_native_client_buffer and
+ * EGL_ANDROID_image_native_buffer for more information. In Vulkan,
+ * the contents of the AHardwareBuffer can be accessed as external
+ * memory. See the VK_ANDROID_external_memory_android_hardware_buffer
+ * extension for details.
+ *
+ * @{
*/
#ifndef ANDROID_HARDWARE_BUFFER_H
@@ -37,7 +56,7 @@
/**
* Buffer pixel formats.
*/
-enum {
+enum AHardwareBuffer_Format {
/**
* Corresponding formats:
* Vulkan: VK_FORMAT_R8G8B8A8_UNORM
@@ -134,27 +153,47 @@
/**
* Buffer usage flags, specifying how the buffer will be accessed.
*/
-enum {
- /// The buffer will never be read by the CPU.
+enum AHardwareBuffer_UsageFlags {
+ /// The buffer will never be locked for direct CPU reads using the
+ /// AHardwareBuffer_lock() function. Note that reading the buffer
+ /// using OpenGL or Vulkan functions or memory mappings is still
+ /// allowed.
AHARDWAREBUFFER_USAGE_CPU_READ_NEVER = 0UL,
- /// The buffer will sometimes be read by the CPU.
+ /// The buffer will sometimes be locked for direct CPU reads using
+ /// the AHardwareBuffer_lock() function. Note that reading the
+ /// buffer using OpenGL or Vulkan functions or memory mappings
+ /// does not require the presence of this flag.
AHARDWAREBUFFER_USAGE_CPU_READ_RARELY = 2UL,
- /// The buffer will often be read by the CPU.
+ /// The buffer will often be locked for direct CPU reads using
+ /// the AHardwareBuffer_lock() function. Note that reading the
+ /// buffer using OpenGL or Vulkan functions or memory mappings
+ /// does not require the presence of this flag.
AHARDWAREBUFFER_USAGE_CPU_READ_OFTEN = 3UL,
/// CPU read value mask.
AHARDWAREBUFFER_USAGE_CPU_READ_MASK = 0xFUL,
- /// The buffer will never be written by the CPU.
+ /// The buffer will never be locked for direct CPU writes using the
+ /// AHardwareBuffer_lock() function. Note that writing the buffer
+ /// using OpenGL or Vulkan functions or memory mappings is still
+ /// allowed.
AHARDWAREBUFFER_USAGE_CPU_WRITE_NEVER = 0UL << 4,
- /// The buffer will sometimes be written to by the CPU.
+ /// The buffer will sometimes be locked for direct CPU writes using
+ /// the AHardwareBuffer_lock() function. Note that writing the
+ /// buffer using OpenGL or Vulkan functions or memory mappings
+ /// does not require the presence of this flag.
AHARDWAREBUFFER_USAGE_CPU_WRITE_RARELY = 2UL << 4,
- /// The buffer will often be written to by the CPU.
+ /// The buffer will often be locked for direct CPU writes using
+ /// the AHardwareBuffer_lock() function. Note that writing the
+ /// buffer using OpenGL or Vulkan functions or memory mappings
+ /// does not require the presence of this flag.
AHARDWAREBUFFER_USAGE_CPU_WRITE_OFTEN = 3UL << 4,
/// CPU write value mask.
AHARDWAREBUFFER_USAGE_CPU_WRITE_MASK = 0xFUL << 4,
/// The buffer will be read from by the GPU as a texture.
AHARDWAREBUFFER_USAGE_GPU_SAMPLED_IMAGE = 1UL << 8,
+ /// The buffer will be written to by the GPU as a framebuffer attachment.
+ AHARDWAREBUFFER_USAGE_GPU_FRAMEBUFFER = 1UL << 9,
/**
* The buffer will be written to by the GPU as a framebuffer attachment.
* Note that the name of this flag is somewhat misleading: it does not imply
@@ -162,16 +201,33 @@
* format that will be used as a framebuffer attachment should also have
* this flag.
*/
- AHARDWAREBUFFER_USAGE_GPU_COLOR_OUTPUT = 1UL << 9,
- /// The buffer must not be used outside of a protected hardware path.
+ AHARDWAREBUFFER_USAGE_GPU_COLOR_OUTPUT = AHARDWAREBUFFER_USAGE_GPU_FRAMEBUFFER,
+ /**
+ * The buffer is protected from direct CPU access or being read by non-secure
+ * hardware, such as video encoders. This flag is incompatible with CPU
+ * read and write flags. It is mainly used when handling DRM video.
+ * Refer to the EGL extension EGL_EXT_protected_content and GL extension
+ * EXT_protected_textures for more information on how these buffers are expected
+ * to behave.
+ */
AHARDWAREBUFFER_USAGE_PROTECTED_CONTENT = 1UL << 14,
/// The buffer will be read by a hardware video encoder.
AHARDWAREBUFFER_USAGE_VIDEO_ENCODE = 1UL << 16,
- /// The buffer will be used for direct writes from sensors.
+ /**
+ * The buffer will be used for direct writes from sensors.
+ * When this flag is present, the format must be AHARDWAREBUFFER_FORMAT_BLOB.
+ */
AHARDWAREBUFFER_USAGE_SENSOR_DIRECT_DATA = 1UL << 23,
- /// The buffer will be used as a shader storage or uniform buffer object.
+ /**
+ * The buffer will be used as a shader storage or uniform buffer object.
+ * When this flag is present, the format must be AHARDWAREBUFFER_FORMAT_BLOB.
+ */
AHARDWAREBUFFER_USAGE_GPU_DATA_BUFFER = 1UL << 24,
- /// The buffer will be used as a cube map texture.
+ /**
+ * The buffer will be used as a cube map texture.
+ * When this flag is present, the buffer must have a layer count that is
+ * a multiple of 6.
+ */
AHARDWAREBUFFER_USAGE_GPU_CUBE_MAP = 1UL << 25,
/// The buffer contains a complete mipmap hierarchy.
AHARDWAREBUFFER_USAGE_GPU_MIPMAP_COMPLETE = 1UL << 26,
@@ -206,20 +262,27 @@
uint32_t width; ///< Width in pixels.
uint32_t height; ///< Height in pixels.
uint32_t layers; ///< Number of images in an image array.
- uint32_t format; ///< One of AHARDWAREBUFFER_FORMAT_*
- uint64_t usage; ///< Combination of AHARDWAREBUFFER_USAGE_*
+ uint32_t format; ///< One of AHardwareBuffer_Format.
+ uint64_t usage; ///< Combination of AHardwareBuffer_UsageFlags.
uint32_t stride; ///< Row stride in pixels, ignored for AHardwareBuffer_allocate()
uint32_t rfu0; ///< Initialize to zero, reserved for future use.
uint64_t rfu1; ///< Initialize to zero, reserved for future use.
} AHardwareBuffer_Desc;
+/**
+ * Opaque handle for a native hardware buffer.
+ */
typedef struct AHardwareBuffer AHardwareBuffer;
#if __ANDROID_API__ >= 26
/**
- * Allocates a buffer that backs an AHardwareBuffer using the passed
- * AHardwareBuffer_Desc.
+ * Allocates a buffer that matches the passed AHardwareBuffer_Desc.
+ *
+ * If allocation succeeds, the buffer can be used according to the
+ * usage flags specified in its description. If a buffer is used in ways
+ * not compatible with its usage flags, the results are undefined and
+ * may include program termination.
*
* \return 0 on success, or an error number of the allocation fails for
* any reason. The returned buffer has a reference count of 1.
@@ -234,7 +297,7 @@
/**
* Remove a reference that was previously acquired with
- * AHardwareBuffer_acquire().
+ * AHardwareBuffer_acquire() or AHardwareBuffer_allocate().
*/
void AHardwareBuffer_release(AHardwareBuffer* buffer) __INTRODUCED_IN(26);
diff --git a/libs/nativewindow/include/android/native_window.h b/libs/nativewindow/include/android/native_window.h
index 6831f91..6730596 100644
--- a/libs/nativewindow/include/android/native_window.h
+++ b/libs/nativewindow/include/android/native_window.h
@@ -15,7 +15,13 @@
*/
/**
- * @addtogroup NativeActivity Native Activity
+ * @defgroup ANativeWindow Native Window
+ *
+ * ANativeWindow represents the producer end of an image queue.
+ * It is the C counterpart of the android.view.Surface object in Java,
+ * and can be converted both ways. Depending on the consumer, images
+ * submitted to ANativeWindow can be shown on the display or sent to
+ * other consumers, such as video encoders.
* @{
*/
@@ -41,7 +47,7 @@
* Legacy window pixel format names, kept for backwards compatibility.
* New code and APIs should use AHARDWAREBUFFER_FORMAT_*.
*/
-enum {
+enum ANativeWindow_LegacyFormat {
// NOTE: these values must match the values from graphics/common/x.x/types.hal
/** Red: 8 bits, Green: 8 bits, Blue: 8 bits, Alpha: 8 bits. **/
@@ -95,7 +101,7 @@
/// memory. This may be >= width.
int32_t stride;
- /// The format of the buffer. One of AHARDWAREBUFFER_FORMAT_*
+ /// The format of the buffer. One of AHardwareBuffer_Format.
int32_t format;
/// The actual bits.
@@ -151,7 +157,7 @@
*
* \param width width of the buffers in pixels.
* \param height height of the buffers in pixels.
- * \param format one of AHARDWAREBUFFER_FORMAT_* constants.
+ * \param format one of the AHardwareBuffer_Format constants.
* \return 0 for success, or a negative value on error.
*/
int32_t ANativeWindow_setBuffersGeometry(ANativeWindow* window,
diff --git a/libs/renderengine/Android.bp b/libs/renderengine/Android.bp
index 7efc8bd..beaf9ee 100644
--- a/libs/renderengine/Android.bp
+++ b/libs/renderengine/Android.bp
@@ -50,7 +50,6 @@
"gl/GLExtensions.cpp",
"gl/GLFramebuffer.cpp",
"gl/GLImage.cpp",
- "gl/GLSurface.cpp",
"gl/Program.cpp",
"gl/ProgramCache.cpp",
],
diff --git a/libs/renderengine/gl/GLES20RenderEngine.cpp b/libs/renderengine/gl/GLES20RenderEngine.cpp
index e244a83..d35762d 100644
--- a/libs/renderengine/gl/GLES20RenderEngine.cpp
+++ b/libs/renderengine/gl/GLES20RenderEngine.cpp
@@ -41,7 +41,6 @@
#include "GLExtensions.h"
#include "GLFramebuffer.h"
#include "GLImage.h"
-#include "GLSurface.h"
#include "Program.h"
#include "ProgramCache.h"
@@ -423,10 +422,6 @@
return std::make_unique<GLFramebuffer>(*this);
}
-std::unique_ptr<Surface> GLES20RenderEngine::createSurface() {
- return std::make_unique<GLSurface>(*this);
-}
-
std::unique_ptr<Image> GLES20RenderEngine::createImage() {
return std::make_unique<GLImage>(*this);
}
@@ -439,31 +434,6 @@
return mEGLDisplay == eglGetCurrentDisplay() && mEGLContext == eglGetCurrentContext();
}
-bool GLES20RenderEngine::setCurrentSurface(const Surface& surface) {
- // Surface is an abstract interface. GLES20RenderEngine only ever
- // creates GLSurface's, so it is safe to just cast to the actual
- // type.
- bool success = true;
- const GLSurface& glSurface = static_cast<const GLSurface&>(surface);
- EGLSurface eglSurface = glSurface.getEGLSurface();
- if (eglSurface != eglGetCurrentSurface(EGL_DRAW)) {
- success = eglMakeCurrent(mEGLDisplay, eglSurface, eglSurface, mEGLContext) == EGL_TRUE;
- if (success && glSurface.getAsync()) {
- eglSwapInterval(mEGLDisplay, 0);
- }
- if (success) {
- mSurfaceHeight = glSurface.getHeight();
- }
- }
-
- return success;
-}
-
-void GLES20RenderEngine::resetCurrentSurface() {
- eglMakeCurrent(mEGLDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
- mSurfaceHeight = 0;
-}
-
base::unique_fd GLES20RenderEngine::flush() {
if (!GLExtensions::getInstance().hasNativeFenceSync()) {
return base::unique_fd();
@@ -577,7 +547,7 @@
void GLES20RenderEngine::setScissor(const Rect& region) {
// Invert y-coordinate to map to GL-space.
- int32_t canvasHeight = mRenderToFbo ? mFboHeight : mSurfaceHeight;
+ int32_t canvasHeight = mFboHeight;
int32_t glBottom = canvasHeight - region.bottom;
glScissor(region.left, glBottom, region.getWidth(), region.getHeight());
@@ -620,7 +590,6 @@
glBindFramebuffer(GL_FRAMEBUFFER, framebufferName);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, textureName, 0);
- mRenderToFbo = true;
mFboHeight = glFramebuffer->getBufferHeight();
uint32_t glStatus = glCheckFramebufferStatus(GL_FRAMEBUFFER);
@@ -632,7 +601,6 @@
}
void GLES20RenderEngine::unbindFrameBuffer(Framebuffer* /* framebuffer */) {
- mRenderToFbo = false;
mFboHeight = 0;
// back to main framebuffer
@@ -661,9 +629,7 @@
int32_t r = sourceCrop.right;
int32_t b = sourceCrop.bottom;
int32_t t = sourceCrop.top;
- if (mRenderToFbo) {
- std::swap(t, b);
- }
+ std::swap(t, b);
mat4 m = mat4::ortho(l, r, b, t, 0, 1);
// Apply custom rotation to the projection.
diff --git a/libs/renderengine/gl/GLES20RenderEngine.h b/libs/renderengine/gl/GLES20RenderEngine.h
index aebb319..6c50938 100644
--- a/libs/renderengine/gl/GLES20RenderEngine.h
+++ b/libs/renderengine/gl/GLES20RenderEngine.h
@@ -40,7 +40,6 @@
namespace gl {
class GLImage;
-class GLSurface;
class GLES20RenderEngine : public impl::RenderEngine {
public:
@@ -52,13 +51,10 @@
~GLES20RenderEngine() override;
std::unique_ptr<Framebuffer> createFramebuffer() override;
- std::unique_ptr<Surface> createSurface() override;
std::unique_ptr<Image> createImage() override;
void primeCache() const override;
bool isCurrent() const override;
- bool setCurrentSurface(const Surface& surface) override;
- void resetCurrentSurface() override;
base::unique_fd flush() override;
bool finish() override;
bool waitFence(base::unique_fd fenceFd) override;
@@ -147,8 +143,6 @@
mat4 mBt2020ToSrgb;
mat4 mBt2020ToDisplayP3;
- bool mRenderToFbo = false;
- int32_t mSurfaceHeight = 0;
int32_t mFboHeight = 0;
// Current dataspace of layer being rendered
diff --git a/libs/renderengine/gl/GLSurface.cpp b/libs/renderengine/gl/GLSurface.cpp
deleted file mode 100644
index 2d694e9..0000000
--- a/libs/renderengine/gl/GLSurface.cpp
+++ /dev/null
@@ -1,105 +0,0 @@
-/*
- * Copyright 2018 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include "GLSurface.h"
-
-#include <android/native_window.h>
-#include <log/log.h>
-#include <ui/PixelFormat.h>
-#include "GLES20RenderEngine.h"
-
-namespace android {
-namespace renderengine {
-namespace gl {
-
-GLSurface::GLSurface(const GLES20RenderEngine& engine)
- : mEGLDisplay(engine.getEGLDisplay()), mEGLConfig(engine.getEGLConfig()) {
- // RE does not assume any config when EGL_KHR_no_config_context is supported
- if (mEGLConfig == EGL_NO_CONFIG_KHR) {
- mEGLConfig =
- GLES20RenderEngine::chooseEglConfig(mEGLDisplay, PIXEL_FORMAT_RGBA_8888, false);
- }
-}
-
-GLSurface::~GLSurface() {
- setNativeWindow(nullptr);
-}
-
-void GLSurface::setNativeWindow(ANativeWindow* window) {
- if (mEGLSurface != EGL_NO_SURFACE) {
- eglDestroySurface(mEGLDisplay, mEGLSurface);
- mEGLSurface = EGL_NO_SURFACE;
- mSurfaceWidth = 0;
- mSurfaceHeight = 0;
- }
-
- mWindow = window;
- if (mWindow) {
- mEGLSurface = eglCreateWindowSurface(mEGLDisplay, mEGLConfig, mWindow, nullptr);
- mSurfaceWidth = ANativeWindow_getWidth(window);
- mSurfaceHeight = ANativeWindow_getHeight(window);
- }
-}
-
-void GLSurface::swapBuffers() const {
- if (!eglSwapBuffers(mEGLDisplay, mEGLSurface)) {
- EGLint error = eglGetError();
-
- const char format[] = "eglSwapBuffers(%p, %p) failed with 0x%08x";
- if (mCritical || error == EGL_CONTEXT_LOST) {
- LOG_ALWAYS_FATAL(format, mEGLDisplay, mEGLSurface, error);
- } else {
- ALOGE(format, mEGLDisplay, mEGLSurface, error);
- }
- }
-}
-
-EGLint GLSurface::queryConfig(EGLint attrib) const {
- EGLint value;
- if (!eglGetConfigAttrib(mEGLDisplay, mEGLConfig, attrib, &value)) {
- value = 0;
- }
-
- return value;
-}
-
-int32_t GLSurface::queryRedSize() const {
- return queryConfig(EGL_RED_SIZE);
-}
-
-int32_t GLSurface::queryGreenSize() const {
- return queryConfig(EGL_GREEN_SIZE);
-}
-
-int32_t GLSurface::queryBlueSize() const {
- return queryConfig(EGL_BLUE_SIZE);
-}
-
-int32_t GLSurface::queryAlphaSize() const {
- return queryConfig(EGL_ALPHA_SIZE);
-}
-
-int32_t GLSurface::getWidth() const {
- return mSurfaceWidth;
-}
-
-int32_t GLSurface::getHeight() const {
- return mSurfaceHeight;
-}
-
-} // namespace gl
-} // namespace renderengine
-} // namespace android
diff --git a/libs/renderengine/gl/GLSurface.h b/libs/renderengine/gl/GLSurface.h
deleted file mode 100644
index 092d371..0000000
--- a/libs/renderengine/gl/GLSurface.h
+++ /dev/null
@@ -1,76 +0,0 @@
-/*
- * Copyright 2018 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#pragma once
-
-#include <cstdint>
-
-#include <EGL/egl.h>
-#include <android-base/macros.h>
-#include <renderengine/Surface.h>
-
-struct ANativeWindow;
-
-namespace android {
-namespace renderengine {
-namespace gl {
-
-class GLES20RenderEngine;
-
-class GLSurface final : public renderengine::Surface {
-public:
- GLSurface(const GLES20RenderEngine& engine);
- ~GLSurface() override;
-
- // renderengine::Surface implementation
- void setCritical(bool enable) override { mCritical = enable; }
- void setAsync(bool enable) override { mAsync = enable; }
-
- void setNativeWindow(ANativeWindow* window) override;
- void swapBuffers() const override;
-
- int32_t queryRedSize() const override;
- int32_t queryGreenSize() const override;
- int32_t queryBlueSize() const override;
- int32_t queryAlphaSize() const override;
-
- bool getAsync() const { return mAsync; }
- EGLSurface getEGLSurface() const { return mEGLSurface; }
-
- int32_t getWidth() const override;
- int32_t getHeight() const override;
-
-private:
- EGLint queryConfig(EGLint attrib) const;
-
- EGLDisplay mEGLDisplay;
- EGLConfig mEGLConfig;
-
- bool mCritical = false;
- bool mAsync = false;
-
- int32_t mSurfaceWidth = 0;
- int32_t mSurfaceHeight = 0;
-
- ANativeWindow* mWindow = nullptr;
- EGLSurface mEGLSurface = EGL_NO_SURFACE;
-
- DISALLOW_COPY_AND_ASSIGN(GLSurface);
-};
-
-} // namespace gl
-} // namespace renderengine
-} // namespace android
diff --git a/libs/renderengine/include/renderengine/RenderEngine.h b/libs/renderengine/include/renderengine/RenderEngine.h
index becb3c3..22891c4 100644
--- a/libs/renderengine/include/renderengine/RenderEngine.h
+++ b/libs/renderengine/include/renderengine/RenderEngine.h
@@ -48,7 +48,6 @@
class BindNativeBufferAsFramebuffer;
class Image;
class Mesh;
-class Surface;
class Texture;
namespace impl {
@@ -72,7 +71,6 @@
// used to support legacy behavior.
virtual std::unique_ptr<Framebuffer> createFramebuffer() = 0;
- virtual std::unique_ptr<Surface> createSurface() = 0;
virtual std::unique_ptr<Image> createImage() = 0;
virtual void primeCache() const = 0;
@@ -84,8 +82,6 @@
virtual bool useWaitSync() const = 0;
virtual bool isCurrent() const = 0;
- virtual bool setCurrentSurface(const Surface& surface) = 0;
- virtual void resetCurrentSurface() = 0;
// helpers
// flush submits RenderEngine command stream for execution and returns a
diff --git a/libs/renderengine/include/renderengine/Surface.h b/libs/renderengine/include/renderengine/Surface.h
deleted file mode 100644
index ba7331d..0000000
--- a/libs/renderengine/include/renderengine/Surface.h
+++ /dev/null
@@ -1,46 +0,0 @@
-/*
- * Copyright 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#pragma once
-
-#include <cstdint>
-
-struct ANativeWindow;
-
-namespace android {
-namespace renderengine {
-
-class Surface {
-public:
- virtual ~Surface() = default;
-
- virtual void setCritical(bool enable) = 0;
- virtual void setAsync(bool enable) = 0;
-
- virtual void setNativeWindow(ANativeWindow* window) = 0;
- virtual void swapBuffers() const = 0;
-
- virtual int32_t queryRedSize() const = 0;
- virtual int32_t queryGreenSize() const = 0;
- virtual int32_t queryBlueSize() const = 0;
- virtual int32_t queryAlphaSize() const = 0;
-
- virtual int32_t getWidth() const = 0;
- virtual int32_t getHeight() const = 0;
-};
-
-} // namespace renderengine
-} // namespace android
diff --git a/libs/ui/GraphicBuffer.cpp b/libs/ui/GraphicBuffer.cpp
index 5a1ddee..29deb01 100644
--- a/libs/ui/GraphicBuffer.cpp
+++ b/libs/ui/GraphicBuffer.cpp
@@ -64,12 +64,11 @@
{
}
-GraphicBuffer::GraphicBuffer(uint32_t inWidth, uint32_t inHeight,
- PixelFormat inFormat, uint32_t inLayerCount, uint64_t usage, std::string requestorName)
- : GraphicBuffer()
-{
- mInitCheck = initWithSize(inWidth, inHeight, inFormat, inLayerCount,
- usage, std::move(requestorName));
+GraphicBuffer::GraphicBuffer(uint32_t inWidth, uint32_t inHeight, PixelFormat inFormat,
+ uint32_t inLayerCount, uint64_t inUsage, std::string requestorName)
+ : GraphicBuffer() {
+ mInitCheck = initWithSize(inWidth, inHeight, inFormat, inLayerCount, inUsage,
+ std::move(requestorName));
}
// deprecated
@@ -82,15 +81,12 @@
{
}
-GraphicBuffer::GraphicBuffer(const native_handle_t* handle,
- HandleWrapMethod method, uint32_t width, uint32_t height,
- PixelFormat format, uint32_t layerCount,
- uint64_t usage,
- uint32_t stride)
- : GraphicBuffer()
-{
- mInitCheck = initWithHandle(handle, method, width, height, format,
- layerCount, usage, stride);
+GraphicBuffer::GraphicBuffer(const native_handle_t* inHandle, HandleWrapMethod method,
+ uint32_t inWidth, uint32_t inHeight, PixelFormat inFormat,
+ uint32_t inLayerCount, uint64_t inUsage, uint32_t inStride)
+ : GraphicBuffer() {
+ mInitCheck = initWithHandle(inHandle, method, inWidth, inHeight, inFormat, inLayerCount,
+ inUsage, inStride);
}
GraphicBuffer::~GraphicBuffer()
@@ -182,26 +178,24 @@
return err;
}
-status_t GraphicBuffer::initWithHandle(const native_handle_t* handle,
- HandleWrapMethod method, uint32_t width, uint32_t height,
- PixelFormat format, uint32_t layerCount, uint64_t usage,
- uint32_t stride)
-{
- ANativeWindowBuffer::width = static_cast<int>(width);
- ANativeWindowBuffer::height = static_cast<int>(height);
- ANativeWindowBuffer::stride = static_cast<int>(stride);
- ANativeWindowBuffer::format = format;
- ANativeWindowBuffer::usage = usage;
- ANativeWindowBuffer::usage_deprecated = int(usage);
+status_t GraphicBuffer::initWithHandle(const native_handle_t* inHandle, HandleWrapMethod method,
+ uint32_t inWidth, uint32_t inHeight, PixelFormat inFormat,
+ uint32_t inLayerCount, uint64_t inUsage, uint32_t inStride) {
+ ANativeWindowBuffer::width = static_cast<int>(inWidth);
+ ANativeWindowBuffer::height = static_cast<int>(inHeight);
+ ANativeWindowBuffer::stride = static_cast<int>(inStride);
+ ANativeWindowBuffer::format = inFormat;
+ ANativeWindowBuffer::usage = inUsage;
+ ANativeWindowBuffer::usage_deprecated = int(inUsage);
- ANativeWindowBuffer::layerCount = layerCount;
+ ANativeWindowBuffer::layerCount = inLayerCount;
mOwner = (method == WRAP_HANDLE) ? ownNone : ownHandle;
if (method == TAKE_UNREGISTERED_HANDLE || method == CLONE_HANDLE) {
buffer_handle_t importedHandle;
- status_t err = mBufferMapper.importBuffer(handle, width, height,
- layerCount, format, usage, stride, &importedHandle);
+ status_t err = mBufferMapper.importBuffer(inHandle, inWidth, inHeight, inLayerCount,
+ inFormat, inUsage, inStride, &importedHandle);
if (err != NO_ERROR) {
initWithHandle(nullptr, WRAP_HANDLE, 0, 0, 0, 0, 0, 0);
@@ -209,15 +203,15 @@
}
if (method == TAKE_UNREGISTERED_HANDLE) {
- native_handle_close(handle);
- native_handle_delete(const_cast<native_handle_t*>(handle));
+ native_handle_close(inHandle);
+ native_handle_delete(const_cast<native_handle_t*>(inHandle));
}
- handle = importedHandle;
- mBufferMapper.getTransportSize(handle, &mTransportNumFds, &mTransportNumInts);
+ inHandle = importedHandle;
+ mBufferMapper.getTransportSize(inHandle, &mTransportNumFds, &mTransportNumInts);
}
- ANativeWindowBuffer::handle = handle;
+ ANativeWindowBuffer::handle = inHandle;
return NO_ERROR;
}
diff --git a/libs/ui/include/ui/GraphicBuffer.h b/libs/ui/include/ui/GraphicBuffer.h
index e794462..fe6229a 100644
--- a/libs/ui/include/ui/GraphicBuffer.h
+++ b/libs/ui/include/ui/GraphicBuffer.h
@@ -117,18 +117,16 @@
// cannot be used directly, such as one from hidl_handle.
CLONE_HANDLE,
};
- GraphicBuffer(const native_handle_t* handle, HandleWrapMethod method,
- uint32_t width, uint32_t height,
- PixelFormat format, uint32_t layerCount,
- uint64_t usage, uint32_t stride);
+ GraphicBuffer(const native_handle_t* inHandle, HandleWrapMethod method, uint32_t inWidth,
+ uint32_t inHeight, PixelFormat inFormat, uint32_t inLayerCount, uint64_t inUsage,
+ uint32_t inStride);
// These functions are deprecated because they only take 32 bits of usage
- GraphicBuffer(const native_handle_t* handle, HandleWrapMethod method,
- uint32_t width, uint32_t height,
- PixelFormat format, uint32_t layerCount,
- uint32_t usage, uint32_t stride)
- : GraphicBuffer(handle, method, width, height, format, layerCount,
- static_cast<uint64_t>(usage), stride) {}
+ GraphicBuffer(const native_handle_t* inHandle, HandleWrapMethod method, uint32_t inWidth,
+ uint32_t inHeight, PixelFormat inFormat, uint32_t inLayerCount, uint32_t inUsage,
+ uint32_t inStride)
+ : GraphicBuffer(inHandle, method, inWidth, inHeight, inFormat, inLayerCount,
+ static_cast<uint64_t>(inUsage), inStride) {}
GraphicBuffer(uint32_t inWidth, uint32_t inHeight, PixelFormat inFormat,
uint32_t inLayerCount, uint32_t inUsage, uint32_t inStride,
native_handle_t* inHandle, bool keepOwnership);
@@ -220,10 +218,9 @@
PixelFormat inFormat, uint32_t inLayerCount,
uint64_t inUsage, std::string requestorName);
- status_t initWithHandle(const native_handle_t* handle,
- HandleWrapMethod method, uint32_t width, uint32_t height,
- PixelFormat format, uint32_t layerCount,
- uint64_t usage, uint32_t stride);
+ status_t initWithHandle(const native_handle_t* inHandle, HandleWrapMethod method,
+ uint32_t inWidth, uint32_t inHeight, PixelFormat inFormat,
+ uint32_t inLayerCount, uint64_t inUsage, uint32_t inStride);
void free_handle();
diff --git a/libs/ui/tests/Android.bp b/libs/ui/tests/Android.bp
index 1521e1d..4c9c176 100644
--- a/libs/ui/tests/Android.bp
+++ b/libs/ui/tests/Android.bp
@@ -32,7 +32,8 @@
name: "BufferHubBuffer_test",
header_libs: [
"libbufferhub_headers",
- "libdvr_headers"
+ "libdvr_headers",
+ "libnativewindow_headers",
],
shared_libs: [
"android.frameworks.bufferhub@1.0",
diff --git a/libs/ui/tests/BufferHubBuffer_test.cpp b/libs/ui/tests/BufferHubBuffer_test.cpp
index 606aee60..6af8033 100644
--- a/libs/ui/tests/BufferHubBuffer_test.cpp
+++ b/libs/ui/tests/BufferHubBuffer_test.cpp
@@ -18,6 +18,7 @@
#include <android/frameworks/bufferhub/1.0/IBufferClient.h>
#include <android/frameworks/bufferhub/1.0/IBufferHub.h>
+#include <android/hardware_buffer.h>
#include <gtest/gtest.h>
#include <hidl/ServiceManagement.h>
#include <hwbinder/IPCThreadState.h>
@@ -41,6 +42,7 @@
using frameworks::bufferhub::V1_0::IBufferClient;
using frameworks::bufferhub::V1_0::IBufferHub;
using hardware::hidl_handle;
+using hardware::graphics::common::V1_2::HardwareBufferDescription;
using hidl::base::V1_0::IBase;
using pdx::LocalChannelHandle;
@@ -124,19 +126,50 @@
return;
}
-TEST_F(BufferHubBufferTest, ConnectHidlServer) {
+TEST_F(BufferHubBufferTest, AllocateBuffer) {
+ // TODO(b/116681016): directly test on BufferHubBuffer instead of the service.
+ sp<IBufferHub> bufferHub = IBufferHub::getService();
+ ASSERT_NE(nullptr, bufferHub.get());
+
+ // Stride is an output, rfu0 and rfu1 are reserved data slot for future use.
+ AHardwareBuffer_Desc aDesc = {kWidth, kHeight, kLayerCount, kFormat,
+ kUsage, /*stride=*/0UL, /*rfu0=*/0UL, /*rfu1=*/0ULL};
+ HardwareBufferDescription desc;
+ memcpy(&desc, &aDesc, sizeof(HardwareBufferDescription));
+
+ IBufferHub::allocateBuffer_cb callback = [](const auto& client, const auto& status) {
+ EXPECT_EQ(status, BufferHubStatus::NO_ERROR);
+ EXPECT_NE(nullptr, client.get());
+ };
+ EXPECT_TRUE(bufferHub->allocateBuffer(desc, kUserMetadataSize, callback).isOk());
+}
+
+TEST_F(BufferHubBufferTest, DuplicateBuffer) {
+ // TODO(b/116681016): directly test on BufferHubBuffer instead of the service.
sp<IBufferHub> bufferhub = IBufferHub::getService();
ASSERT_NE(nullptr, bufferhub.get());
- // TODO(b/116681016): Fill in real test once the interface gets implemented..
- hidl_handle handle;
- EXPECT_TRUE(bufferhub
- ->importBuffer(handle,
- [](const auto& client, const auto& ret) {
- EXPECT_EQ(client, nullptr);
- EXPECT_EQ(ret, BufferHubStatus::NO_ERROR);
- })
- .isOk());
+ // Stride is an output, rfu0 and rfu1 are reserved data slot for future use.
+ AHardwareBuffer_Desc aDesc = {kWidth, kHeight, kLayerCount, kFormat,
+ kUsage, /*stride=*/0UL, /*rfu0=*/0UL, /*rfu1=*/0ULL};
+ HardwareBufferDescription desc;
+ memcpy(&desc, &aDesc, sizeof(HardwareBufferDescription));
+
+ sp<IBufferClient> client;
+ IBufferHub::allocateBuffer_cb alloc_cb = [&](const auto& outClient, const auto& status) {
+ ASSERT_EQ(status, BufferHubStatus::NO_ERROR);
+ ASSERT_NE(nullptr, outClient.get());
+ client = outClient;
+ };
+ ASSERT_TRUE(bufferhub->allocateBuffer(desc, kUserMetadataSize, alloc_cb).isOk());
+
+ IBufferClient::duplicate_cb dup_cb = [](const auto& token, const auto& status) {
+ ASSERT_EQ(status, BufferHubStatus::NO_ERROR);
+ ASSERT_NE(token.getNativeHandle(), nullptr);
+ EXPECT_EQ(token->numInts, 1);
+ EXPECT_EQ(token->numFds, 0);
+ };
+ EXPECT_TRUE(client->duplicate(dup_cb).isOk());
}
} // namespace
diff --git a/services/bufferhub/Android.bp b/services/bufferhub/Android.bp
index ca65e02..8b43333 100644
--- a/services/bufferhub/Android.bp
+++ b/services/bufferhub/Android.bp
@@ -34,6 +34,7 @@
],
shared_libs: [
"android.frameworks.bufferhub@1.0",
+ "libcutils",
"libhidlbase",
"libhidltransport",
"libhwbinder",
@@ -52,9 +53,16 @@
srcs: [
"main_bufferhub.cpp"
],
+ header_libs: [
+ "libbufferhub_headers",
+ "libdvr_headers",
+ "libnativewindow_headers",
+ "libpdx_headers",
+ ],
shared_libs: [
"android.frameworks.bufferhub@1.0",
"libbufferhubservice",
+ "libcutils",
"libhidltransport",
"libhwbinder",
"liblog",
diff --git a/services/bufferhub/BufferClient.cpp b/services/bufferhub/BufferClient.cpp
index b3662b2..37fd75f 100644
--- a/services/bufferhub/BufferClient.cpp
+++ b/services/bufferhub/BufferClient.cpp
@@ -15,6 +15,7 @@
*/
#include <bufferhub/BufferClient.h>
+#include <bufferhub/BufferHubService.h>
#include <hidl/HidlSupport.h>
namespace android {
@@ -26,9 +27,34 @@
using hardware::hidl_handle;
using hardware::Void;
+BufferClient* BufferClient::create(BufferHubService* service,
+ const std::shared_ptr<BufferNode>& node) {
+ if (!service) {
+ ALOGE("%s: service cannot be nullptr.", __FUNCTION__);
+ return nullptr;
+ } else if (!node) {
+ ALOGE("%s: node cannot be nullptr.", __FUNCTION__);
+ return nullptr;
+ }
+ return new BufferClient(service, node);
+}
+
Return<void> BufferClient::duplicate(duplicate_cb _hidl_cb) {
- // TODO(b/118614157): implement token generation and registration
- _hidl_cb(/*token=*/hidl_handle(), /*status=*/BufferHubStatus::NO_ERROR);
+ if (!mBufferNode) {
+ // Should never happen
+ ALOGE("%s: node is missing.", __FUNCTION__);
+ _hidl_cb(/*token=*/hidl_handle(), /*status=*/BufferHubStatus::BUFFER_FREED);
+ return Void();
+ }
+
+ sp<BufferHubService> service = mService.promote();
+ if (service == nullptr) {
+ // Should never happen. Kill the process.
+ LOG_FATAL("%s: service died.", __FUNCTION__);
+ }
+
+ const hidl_handle token = service->registerToken(this);
+ _hidl_cb(/*token=*/token, /*status=*/BufferHubStatus::NO_ERROR);
return Void();
}
diff --git a/services/bufferhub/BufferHubService.cpp b/services/bufferhub/BufferHubService.cpp
index 86598e0..3bfd9cb 100644
--- a/services/bufferhub/BufferHubService.cpp
+++ b/services/bufferhub/BufferHubService.cpp
@@ -14,7 +14,10 @@
* limitations under the License.
*/
+#include <android/hardware_buffer.h>
#include <bufferhub/BufferHubService.h>
+#include <cutils/native_handle.h>
+#include <log/log.h>
namespace android {
namespace frameworks {
@@ -24,11 +27,27 @@
using hardware::Void;
-Return<void> BufferHubService::allocateBuffer(const HardwareBufferDescription& /*description*/,
- const uint32_t /*userMetadataSize*/,
+Return<void> BufferHubService::allocateBuffer(const HardwareBufferDescription& description,
+ const uint32_t userMetadataSize,
allocateBuffer_cb _hidl_cb) {
- // TODO(b/118614333): implement buffer allocation
- _hidl_cb(/*bufferClient=*/nullptr, /*status=*/BufferHubStatus::NO_ERROR);
+ AHardwareBuffer_Desc desc;
+ memcpy(&desc, &description, sizeof(AHardwareBuffer_Desc));
+
+ std::shared_ptr<BufferNode> node =
+ std::make_shared<BufferNode>(desc.width, desc.height, desc.layers, desc.format,
+ desc.usage, userMetadataSize);
+ if (node == nullptr || !node->IsValid()) {
+ ALOGE("%s: creating BufferNode failed.", __FUNCTION__);
+ _hidl_cb(/*bufferClient=*/nullptr, /*status=*/BufferHubStatus::ALLOCATION_FAILED);
+ return Void();
+ }
+
+ sp<BufferClient> client = BufferClient::create(this, node);
+ // Add it to list for bookkeeping and dumpsys.
+ std::lock_guard<std::mutex> lock(mClientListMutex);
+ mClientList.push_back(client);
+
+ _hidl_cb(/*bufferClient=*/client, /*status=*/BufferHubStatus::NO_ERROR);
return Void();
}
@@ -39,6 +58,25 @@
return Void();
}
+hidl_handle BufferHubService::registerToken(const BufferClient* client) {
+ uint32_t token;
+ std::lock_guard<std::mutex> lock(mTokenMapMutex);
+ do {
+ token = mTokenEngine();
+ } while (mTokenMap.find(token) != mTokenMap.end());
+
+ // native_handle_t use int[], so here need one slots to fit in uint32_t
+ native_handle_t* handle = native_handle_create(/*numFds=*/0, /*numInts=*/1);
+ handle->data[0] = token;
+
+ // returnToken owns the native_handle_t* thus doing lifecycle management
+ hidl_handle returnToken;
+ returnToken.setTo(handle, /*shoudOwn=*/true);
+
+ mTokenMap.emplace(token, client);
+ return returnToken;
+}
+
} // namespace implementation
} // namespace V1_0
} // namespace bufferhub
diff --git a/services/bufferhub/include/bufferhub/BufferClient.h b/services/bufferhub/include/bufferhub/BufferClient.h
index 14ea95c..5456ec3 100644
--- a/services/bufferhub/include/bufferhub/BufferClient.h
+++ b/services/bufferhub/include/bufferhub/BufferClient.h
@@ -17,7 +17,10 @@
#ifndef ANDROID_FRAMEWORKS_BUFFERHUB_V1_0_BUFFER_CLIENT_H
#define ANDROID_FRAMEWORKS_BUFFERHUB_V1_0_BUFFER_CLIENT_H
+#include <mutex>
+
#include <android/frameworks/bufferhub/1.0/IBufferClient.h>
+#include <bufferhub/BufferNode.h>
namespace android {
namespace frameworks {
@@ -25,11 +28,27 @@
namespace V1_0 {
namespace implementation {
+using hardware::hidl_handle;
using hardware::Return;
+// Forward declaration to avoid circular dependency
+class BufferHubService;
+
class BufferClient : public IBufferClient {
public:
+ // Creates a server-side buffer client from an existing BufferNode. Note that
+ // this funciton takes ownership of the shared_ptr.
+ // Returns a raw pointer to the BufferClient on success, nullptr on failure.
+ static BufferClient* create(BufferHubService* service, const std::shared_ptr<BufferNode>& node);
+
Return<void> duplicate(duplicate_cb _hidl_cb) override;
+
+private:
+ BufferClient(wp<BufferHubService> service, const std::shared_ptr<BufferNode>& node)
+ : mService(service), mBufferNode(node){};
+
+ wp<BufferHubService> mService;
+ std::shared_ptr<BufferNode> mBufferNode;
};
} // namespace implementation
diff --git a/services/bufferhub/include/bufferhub/BufferHubService.h b/services/bufferhub/include/bufferhub/BufferHubService.h
index 5e0cff0..dbbee8f 100644
--- a/services/bufferhub/include/bufferhub/BufferHubService.h
+++ b/services/bufferhub/include/bufferhub/BufferHubService.h
@@ -17,8 +17,12 @@
#ifndef ANDROID_FRAMEWORKS_BUFFERHUB_V1_0_BUFFER_HUB_SERVICE_H
#define ANDROID_FRAMEWORKS_BUFFERHUB_V1_0_BUFFER_HUB_SERVICE_H
-#include <android/frameworks/bufferhub/1.0/IBufferClient.h>
+#include <mutex>
+#include <random>
+
#include <android/frameworks/bufferhub/1.0/IBufferHub.h>
+#include <bufferhub/BufferClient.h>
+#include <utils/Mutex.h>
namespace android {
namespace frameworks {
@@ -26,9 +30,9 @@
namespace V1_0 {
namespace implementation {
-using ::android::hardware::hidl_handle;
-using ::android::hardware::Return;
-using ::android::hardware::graphics::common::V1_2::HardwareBufferDescription;
+using hardware::hidl_handle;
+using hardware::Return;
+using hardware::graphics::common::V1_2::HardwareBufferDescription;
class BufferHubService : public IBufferHub {
public:
@@ -36,6 +40,21 @@
const uint32_t userMetadataSize,
allocateBuffer_cb _hidl_cb) override;
Return<void> importBuffer(const hidl_handle& nativeHandle, importBuffer_cb _hidl_cb) override;
+
+ // Non-binder functions
+ // Internal help function for IBufferClient::duplicate.
+ hidl_handle registerToken(const BufferClient* client);
+
+private:
+ // List of active BufferClient for bookkeeping.
+ std::mutex mClientListMutex;
+ std::vector<sp<BufferClient>> mClientList GUARDED_BY(mClientListMutex);
+
+ // TODO(b/118180214): use a more secure implementation
+ std::mt19937 mTokenEngine;
+ // The mapping from token to the client creates it.
+ std::mutex mTokenMapMutex;
+ std::map<uint32_t, const BufferClient*> mTokenMap GUARDED_BY(mTokenMapMutex);
};
} // namespace implementation
diff --git a/services/inputflinger/EventHub.cpp b/services/inputflinger/EventHub.cpp
index 1a1dabb..31057f6 100644
--- a/services/inputflinger/EventHub.cpp
+++ b/services/inputflinger/EventHub.cpp
@@ -192,8 +192,6 @@
// --- EventHub ---
-const uint32_t EventHub::EPOLL_ID_INOTIFY;
-const uint32_t EventHub::EPOLL_ID_WAKE;
const int EventHub::EPOLL_SIZE_HINT;
const int EventHub::EPOLL_MAX_EVENTS;
@@ -216,7 +214,7 @@
struct epoll_event eventItem;
memset(&eventItem, 0, sizeof(eventItem));
eventItem.events = EPOLLIN;
- eventItem.data.u32 = EPOLL_ID_INOTIFY;
+ eventItem.data.fd = mINotifyFd;
result = epoll_ctl(mEpollFd, EPOLL_CTL_ADD, mINotifyFd, &eventItem);
LOG_ALWAYS_FATAL_IF(result != 0, "Could not add INotify to epoll instance. errno=%d", errno);
@@ -235,7 +233,7 @@
LOG_ALWAYS_FATAL_IF(result != 0, "Could not make wake write pipe non-blocking. errno=%d",
errno);
- eventItem.data.u32 = EPOLL_ID_WAKE;
+ eventItem.data.fd = mWakeReadPipeFd;
result = epoll_ctl(mEpollFd, EPOLL_CTL_ADD, mWakeReadPipeFd, &eventItem);
LOG_ALWAYS_FATAL_IF(result != 0, "Could not add wake read pipe to epoll instance. errno=%d",
errno);
@@ -734,6 +732,16 @@
return nullptr;
}
+EventHub::Device* EventHub::getDeviceByFdLocked(int fd) const {
+ for (size_t i = 0; i < mDevices.size(); i++) {
+ Device* device = mDevices.valueAt(i);
+ if (device->fd == fd) {
+ return device;
+ }
+ }
+ return nullptr;
+}
+
size_t EventHub::getEvents(int timeoutMillis, RawEvent* buffer, size_t bufferSize) {
ALOG_ASSERT(bufferSize >= 1);
@@ -810,7 +818,7 @@
bool deviceChanged = false;
while (mPendingEventIndex < mPendingEventCount) {
const struct epoll_event& eventItem = mPendingEventItems[mPendingEventIndex++];
- if (eventItem.data.u32 == EPOLL_ID_INOTIFY) {
+ if (eventItem.data.fd == mINotifyFd) {
if (eventItem.events & EPOLLIN) {
mPendingINotify = true;
} else {
@@ -819,7 +827,7 @@
continue;
}
- if (eventItem.data.u32 == EPOLL_ID_WAKE) {
+ if (eventItem.data.fd == mWakeReadPipeFd) {
if (eventItem.events & EPOLLIN) {
ALOGV("awoken after wake()");
awoken = true;
@@ -835,14 +843,13 @@
continue;
}
- ssize_t deviceIndex = mDevices.indexOfKey(eventItem.data.u32);
- if (deviceIndex < 0) {
- ALOGW("Received unexpected epoll event 0x%08x for unknown device id %d.",
- eventItem.events, eventItem.data.u32);
+ Device* device = getDeviceByFdLocked(eventItem.data.fd);
+ if (device == nullptr) {
+ ALOGW("Received unexpected epoll event 0x%08x for unknown device fd %d.",
+ eventItem.events, eventItem.data.fd);
continue;
}
- Device* device = mDevices.valueAt(deviceIndex);
if (eventItem.events & EPOLLIN) {
int32_t readSize = read(device->fd, readBuffer,
sizeof(struct input_event) * capacity);
@@ -1063,7 +1070,7 @@
if (mUsingEpollWakeup) {
eventItem.events |= EPOLLWAKEUP;
}
- eventItem.data.u32 = device->id;
+ eventItem.data.fd = device->fd;
if (epoll_ctl(mEpollFd, EPOLL_CTL_ADD, device->fd, &eventItem)) {
ALOGE("Could not add device fd to epoll instance. errno=%d", errno);
return -errno;
diff --git a/services/inputflinger/EventHub.h b/services/inputflinger/EventHub.h
index 62ce47c..e2c7e82 100644
--- a/services/inputflinger/EventHub.h
+++ b/services/inputflinger/EventHub.h
@@ -401,6 +401,7 @@
Device* getDeviceByDescriptorLocked(const std::string& descriptor) const;
Device* getDeviceLocked(int32_t deviceId) const;
Device* getDeviceByPathLocked(const char* devicePath) const;
+ Device* getDeviceByFdLocked(int fd) const;
bool hasKeycodeLocked(Device* device, int keycode) const;
@@ -449,10 +450,6 @@
int mWakeReadPipeFd;
int mWakeWritePipeFd;
- // Ids used for epoll notifications not associated with devices.
- static const uint32_t EPOLL_ID_INOTIFY = 0x80000001;
- static const uint32_t EPOLL_ID_WAKE = 0x80000002;
-
// Epoll FD list size hint.
static const int EPOLL_SIZE_HINT = 8;
diff --git a/services/inputflinger/InputReader.cpp b/services/inputflinger/InputReader.cpp
index 869bd71..e85e6ef 100644
--- a/services/inputflinger/InputReader.cpp
+++ b/services/inputflinger/InputReader.cpp
@@ -3480,8 +3480,8 @@
}
// Raw width and height in the natural orientation.
- int32_t rawWidth = mRawPointerAxes.x.maxValue - mRawPointerAxes.x.minValue + 1;
- int32_t rawHeight = mRawPointerAxes.y.maxValue - mRawPointerAxes.y.minValue + 1;
+ int32_t rawWidth = mRawPointerAxes.getRawWidth();
+ int32_t rawHeight = mRawPointerAxes.getRawHeight();
// Get associated display dimensions.
DisplayViewport newViewport;
@@ -3913,8 +3913,8 @@
int32_t touchScreenLeft = mRawPointerAxes.x.minValue;
int32_t touchScreenTop = mRawPointerAxes.y.minValue;
- int32_t touchScreenWidth = mRawPointerAxes.x.maxValue - mRawPointerAxes.x.minValue + 1;
- int32_t touchScreenHeight = mRawPointerAxes.y.maxValue - mRawPointerAxes.y.minValue + 1;
+ int32_t touchScreenWidth = mRawPointerAxes.getRawWidth();
+ int32_t touchScreenHeight = mRawPointerAxes.getRawHeight();
for (size_t i = 0; i < virtualKeyDefinitions.size(); i++) {
const VirtualKeyDefinition& virtualKeyDefinition =
diff --git a/services/inputflinger/InputReader.h b/services/inputflinger/InputReader.h
index 3410bc9..9b0007a 100644
--- a/services/inputflinger/InputReader.h
+++ b/services/inputflinger/InputReader.h
@@ -772,6 +772,8 @@
RawAbsoluteAxisInfo slot;
RawPointerAxes();
+ inline int32_t getRawWidth() const { return x.maxValue - x.minValue + 1; }
+ inline int32_t getRawHeight() const { return y.maxValue - y.minValue + 1; }
void clear();
};
diff --git a/services/surfaceflinger/BufferLayer.cpp b/services/surfaceflinger/BufferLayer.cpp
index c2f15dd..ade62bf 100644
--- a/services/surfaceflinger/BufferLayer.cpp
+++ b/services/surfaceflinger/BufferLayer.cpp
@@ -231,15 +231,12 @@
void BufferLayer::setPerFrameData(DisplayId displayId, const ui::Transform& transform,
const Rect& viewport, int32_t supportedPerFrameMetadata) {
+ RETURN_IF_NO_HWC_LAYER(displayId);
+
// Apply this display's projection's viewport to the visible region
// before giving it to the HWC HAL.
Region visible = transform.transform(visibleRegion.intersect(viewport));
- if (!hasHwcLayer(displayId)) {
- ALOGE("[%s] failed to setPerFrameData: no HWC layer found for display %" PRIu64,
- mName.string(), displayId);
- return;
- }
auto& hwcInfo = getBE().mHwcLayers[displayId];
auto& hwcLayer = hwcInfo.layer;
auto error = hwcLayer->setVisibleRegion(visible);
@@ -665,6 +662,36 @@
}
}
+Rect BufferLayer::getBufferSize(const State& s) const {
+ // If we have a sideband stream, or we are scaling the buffer then return the layer size since
+ // we cannot determine the buffer size.
+ if ((s.sidebandStream != nullptr) ||
+ (getEffectiveScalingMode() != NATIVE_WINDOW_SCALING_MODE_FREEZE)) {
+ return Rect(getActiveWidth(s), getActiveHeight(s));
+ }
+
+ if (mActiveBuffer == nullptr) {
+ return Rect::INVALID_RECT;
+ }
+
+ uint32_t bufWidth = mActiveBuffer->getWidth();
+ uint32_t bufHeight = mActiveBuffer->getHeight();
+
+ // Undo any transformations on the buffer and return the result.
+ if (mCurrentTransform & ui::Transform::ROT_90) {
+ std::swap(bufWidth, bufHeight);
+ }
+
+ if (getTransformToDisplayInverse()) {
+ uint32_t invTransform = DisplayDevice::getPrimaryDisplayOrientationTransform();
+ if (invTransform & ui::Transform::ROT_90) {
+ std::swap(bufWidth, bufHeight);
+ }
+ }
+
+ return Rect(bufWidth, bufHeight);
+}
+
} // namespace android
#if defined(__gl_h_)
diff --git a/services/surfaceflinger/BufferLayer.h b/services/surfaceflinger/BufferLayer.h
index f352256..690a4e5 100644
--- a/services/surfaceflinger/BufferLayer.h
+++ b/services/surfaceflinger/BufferLayer.h
@@ -188,6 +188,8 @@
mutable renderengine::Texture mTexture;
bool mRefreshPending{false};
+
+ Rect getBufferSize(const State& s) const override;
};
} // namespace android
diff --git a/services/surfaceflinger/BufferStateLayer.cpp b/services/surfaceflinger/BufferStateLayer.cpp
index ea64ca7..425f5c7 100644
--- a/services/surfaceflinger/BufferStateLayer.cpp
+++ b/services/surfaceflinger/BufferStateLayer.cpp
@@ -35,7 +35,9 @@
};
// clang-format on
-BufferStateLayer::BufferStateLayer(const LayerCreationArgs& args) : BufferLayer(args) {}
+BufferStateLayer::BufferStateLayer(const LayerCreationArgs& args) : BufferLayer(args) {
+ mOverrideScalingMode = NATIVE_WINDOW_SCALING_MODE_SCALE_TO_WINDOW;
+}
BufferStateLayer::~BufferStateLayer() = default;
// -----------------------------------------------------------------------
@@ -447,7 +449,7 @@
}
}
- if (mOverrideScalingMode == NATIVE_WINDOW_SCALING_MODE_FREEZE &&
+ if (getEffectiveScalingMode() == NATIVE_WINDOW_SCALING_MODE_FREEZE &&
(s.active.w != bufferWidth || s.active.h != bufferHeight)) {
ALOGE("[%s] rejecting buffer: "
"bufferWidth=%d, bufferHeight=%d, front.active.{w=%d, h=%d}",
diff --git a/services/surfaceflinger/ColorLayer.cpp b/services/surfaceflinger/ColorLayer.cpp
index ad716ef..9c34308 100644
--- a/services/surfaceflinger/ColorLayer.cpp
+++ b/services/surfaceflinger/ColorLayer.cpp
@@ -59,13 +59,10 @@
void ColorLayer::setPerFrameData(DisplayId displayId, const ui::Transform& transform,
const Rect& viewport, int32_t /* supportedPerFrameMetadata */) {
+ RETURN_IF_NO_HWC_LAYER(displayId);
+
Region visible = transform.transform(visibleRegion.intersect(viewport));
- if (!hasHwcLayer(displayId)) {
- ALOGE("[%s] failed to setPerFrameData: no HWC layer found for display %" PRIu64,
- mName.string(), displayId);
- return;
- }
auto& hwcInfo = getBE().mHwcLayers[displayId];
auto& hwcLayer = hwcInfo.layer;
auto error = hwcLayer->setVisibleRegion(visible);
diff --git a/services/surfaceflinger/DisplayDevice.cpp b/services/surfaceflinger/DisplayDevice.cpp
index f51daf3..d16febf 100644
--- a/services/surfaceflinger/DisplayDevice.cpp
+++ b/services/surfaceflinger/DisplayDevice.cpp
@@ -705,7 +705,7 @@
}
std::string DisplayDevice::getDebugName() const {
- const auto id = mId ? base::StringPrintf("%" PRIu64 ", ", *mId) : std::string();
+ const auto id = mId ? to_string(*mId) + ", " : std::string();
return base::StringPrintf("DisplayDevice{%s%s%s\"%s\"}", id.c_str(),
isPrimary() ? "primary, " : "", isVirtual() ? "virtual, " : "",
mDisplayName.c_str());
diff --git a/services/surfaceflinger/DisplayHardware/DisplayIdentification.cpp b/services/surfaceflinger/DisplayHardware/DisplayIdentification.cpp
index ec240f3..ba7818d 100644
--- a/services/surfaceflinger/DisplayHardware/DisplayIdentification.cpp
+++ b/services/surfaceflinger/DisplayHardware/DisplayIdentification.cpp
@@ -64,12 +64,16 @@
return letter < 'A' || letter > 'Z' ? '\0' : letter;
}
-DisplayId getEdidDisplayId(uint8_t port, uint16_t manufacturerId, uint32_t displayNameHash) {
- return (static_cast<DisplayId>(manufacturerId) << 40) |
- (static_cast<DisplayId>(displayNameHash) << 8) | port;
+} // namespace
+
+uint16_t DisplayId::manufacturerId() const {
+ return static_cast<uint16_t>(value >> 40);
}
-} // namespace
+DisplayId DisplayId::fromEdid(uint8_t port, uint16_t manufacturerId, uint32_t displayNameHash) {
+ return {(static_cast<Type>(manufacturerId) << 40) | (static_cast<Type>(displayNameHash) << 8) |
+ port};
+}
bool isEdid(const DisplayIdentificationData& data) {
const uint8_t kMagic[] = {0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0};
@@ -168,6 +172,10 @@
return a && b && c ? std::make_optional(PnpId{a, b, c}) : std::nullopt;
}
+std::optional<PnpId> getPnpId(DisplayId displayId) {
+ return getPnpId(displayId.manufacturerId());
+}
+
std::optional<DisplayIdentificationInfo> parseDisplayIdentificationData(
uint8_t port, const DisplayIdentificationData& data) {
if (!isEdid(data)) {
@@ -183,16 +191,16 @@
// Hash display name instead of using product code or serial number, since the latter have been
// observed to change on some displays with multiple inputs.
const auto hash = static_cast<uint32_t>(std::hash<std::string_view>()(edid->displayName));
- return DisplayIdentificationInfo{getEdidDisplayId(port, edid->manufacturerId, hash),
+ return DisplayIdentificationInfo{DisplayId::fromEdid(port, edid->manufacturerId, hash),
std::string(edid->displayName)};
}
DisplayId getFallbackDisplayId(uint8_t port) {
- return getEdidDisplayId(port, kFallbackEdidManufacturerId, 0);
+ return DisplayId::fromEdid(port, kFallbackEdidManufacturerId, 0);
}
DisplayId getVirtualDisplayId(uint32_t id) {
- return getEdidDisplayId(0, kVirtualEdidManufacturerId, id);
+ return DisplayId::fromEdid(0, kVirtualEdidManufacturerId, id);
}
} // namespace android
diff --git a/services/surfaceflinger/DisplayHardware/DisplayIdentification.h b/services/surfaceflinger/DisplayHardware/DisplayIdentification.h
index 1f2e789..1599995 100644
--- a/services/surfaceflinger/DisplayHardware/DisplayIdentification.h
+++ b/services/surfaceflinger/DisplayHardware/DisplayIdentification.h
@@ -25,7 +25,27 @@
namespace android {
-using DisplayId = uint64_t;
+struct DisplayId {
+ using Type = uint64_t;
+ Type value;
+
+ uint16_t manufacturerId() const;
+
+ static DisplayId fromEdid(uint8_t port, uint16_t manufacturerId, uint32_t displayNameHash);
+};
+
+inline bool operator==(DisplayId lhs, DisplayId rhs) {
+ return lhs.value == rhs.value;
+}
+
+inline bool operator!=(DisplayId lhs, DisplayId rhs) {
+ return !(lhs == rhs);
+}
+
+inline std::string to_string(DisplayId displayId) {
+ return std::to_string(displayId.value);
+}
+
using DisplayIdentificationData = std::vector<uint8_t>;
struct DisplayIdentificationInfo {
@@ -45,6 +65,7 @@
bool isEdid(const DisplayIdentificationData&);
std::optional<Edid> parseEdid(const DisplayIdentificationData&);
std::optional<PnpId> getPnpId(uint16_t manufacturerId);
+std::optional<PnpId> getPnpId(DisplayId);
std::optional<DisplayIdentificationInfo> parseDisplayIdentificationData(
uint8_t port, const DisplayIdentificationData&);
@@ -53,3 +74,14 @@
DisplayId getVirtualDisplayId(uint32_t id);
} // namespace android
+
+namespace std {
+
+template <>
+struct hash<android::DisplayId> {
+ size_t operator()(android::DisplayId displayId) const {
+ return hash<android::DisplayId::Type>()(displayId.value);
+ }
+};
+
+} // namespace std
diff --git a/services/surfaceflinger/DisplayHardware/FramebufferSurface.cpp b/services/surfaceflinger/DisplayHardware/FramebufferSurface.cpp
index f3f8d9d..27812f7 100644
--- a/services/surfaceflinger/DisplayHardware/FramebufferSurface.cpp
+++ b/services/surfaceflinger/DisplayHardware/FramebufferSurface.cpp
@@ -63,7 +63,7 @@
mHasPendingRelease(false),
mPreviousBufferSlot(BufferQueue::INVALID_BUFFER_SLOT),
mPreviousBuffer() {
- ALOGV("Creating for display %" PRIu64, displayId);
+ ALOGV("Creating for display %s", to_string(displayId).c_str());
mName = "FramebufferSurface";
mConsumer->setConsumerName(mName);
diff --git a/services/surfaceflinger/DisplayHardware/HWComposer.cpp b/services/surfaceflinger/DisplayHardware/HWComposer.cpp
index 4c472b8..0f25b52 100644
--- a/services/surfaceflinger/DisplayHardware/HWComposer.cpp
+++ b/services/surfaceflinger/DisplayHardware/HWComposer.cpp
@@ -58,11 +58,11 @@
ALOGE("%s failed for HWC display %" PRIu64 ": %s", __FUNCTION__, hwcDisplayId, msg)
#define LOG_DISPLAY_ERROR(displayId, msg) \
- ALOGE("%s failed for display %" PRIu64 ": %s", __FUNCTION__, displayId, msg)
+ ALOGE("%s failed for display %s: %s", __FUNCTION__, to_string(displayId).c_str(), msg)
-#define LOG_HWC_ERROR(what, error, displayId) \
- ALOGE("%s: %s failed for display %" PRIu64 ": %s (%d)", __FUNCTION__, what, displayId, \
- to_string(error).c_str(), static_cast<int32_t>(error))
+#define LOG_HWC_ERROR(what, error, displayId) \
+ ALOGE("%s: %s failed for display %s: %s (%d)", __FUNCTION__, what, \
+ to_string(displayId).c_str(), to_string(error).c_str(), static_cast<int32_t>(error))
#define RETURN_IF_INVALID_DISPLAY(displayId, ...) \
do { \
@@ -159,9 +159,9 @@
if (!info) return {};
}
- ALOGV("%s: %s %s display %" PRIu64 " with HWC ID %" PRIu64, __FUNCTION__,
- to_string(connection).c_str(),
- hwcDisplayId == mInternalHwcDisplayId ? "internal" : "external", info->id, hwcDisplayId);
+ ALOGV("%s: %s %s display %s with HWC ID %" PRIu64, __FUNCTION__, to_string(connection).c_str(),
+ hwcDisplayId == mInternalHwcDisplayId ? "internal" : "external",
+ to_string(info->id).c_str(), hwcDisplayId);
mHwcDevice->onHotplug(hwcDisplayId, connection);
@@ -198,15 +198,15 @@
// is a bug in the HWC implementation, but filter the extra events
// out here so they don't cause havoc downstream.
if (timestamp == mLastHwVSync[*displayId]) {
- ALOGW("Ignoring duplicate VSYNC event from HWC for display %" PRIu64 " (t=%" PRId64 ")",
- *displayId, timestamp);
+ ALOGW("Ignoring duplicate VSYNC event from HWC for display %s (t=%" PRId64 ")",
+ to_string(*displayId).c_str(), timestamp);
return false;
}
mLastHwVSync[*displayId] = timestamp;
}
- const auto tag = "HW_VSYNC_" + std::to_string(*displayId);
+ const auto tag = "HW_VSYNC_" + to_string(*displayId);
ATRACE_INT(tag.c_str(), ++mVSyncCounts[*displayId] & 1);
return true;
@@ -383,7 +383,7 @@
displayData.vsyncEnabled = enabled;
- const auto tag = "HW_VSYNC_ON_" + std::to_string(displayId);
+ const auto tag = "HW_VSYNC_ON_" + to_string(displayId);
ATRACE_INT(tag.c_str(), enabled == HWC2::Vsync::Enable ? 1 : 0);
}
}
@@ -393,7 +393,7 @@
ui::Dataspace dataspace) {
RETURN_IF_INVALID_DISPLAY(displayId, BAD_INDEX);
- ALOGV("setClientTarget for display %" PRIu64, displayId);
+ ALOGV("%s for display %s", __FUNCTION__, to_string(displayId).c_str());
auto& hwcDisplay = mDisplayData[displayId].hwcDisplay;
auto error = hwcDisplay->setClientTarget(slot, target, acquireFence, dataspace);
RETURN_IF_HWC_ERROR(error, displayId, BAD_VALUE);
diff --git a/services/surfaceflinger/DisplayHardware/HWComposer.h b/services/surfaceflinger/DisplayHardware/HWComposer.h
index 5074c2c..b78433d 100644
--- a/services/surfaceflinger/DisplayHardware/HWComposer.h
+++ b/services/surfaceflinger/DisplayHardware/HWComposer.h
@@ -233,7 +233,7 @@
cb_context* mCBContext = nullptr;
std::unordered_map<DisplayId, size_t> mVSyncCounts;
- std::unordered_set<uint32_t> mFreeVirtualDisplayIds;
+ std::unordered_set<DisplayId> mFreeVirtualDisplayIds;
uint32_t mNextVirtualDisplayId = 0;
uint32_t mRemainingHwcVirtualDisplays{mHwcDevice->getMaxVirtualDisplayCount()};
diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp
index 421c9d0..038bc58 100644
--- a/services/surfaceflinger/Layer.cpp
+++ b/services/surfaceflinger/Layer.cpp
@@ -197,8 +197,8 @@
// ---------------------------------------------------------------------------
bool Layer::createHwcLayer(HWComposer* hwc, DisplayId displayId) {
- LOG_ALWAYS_FATAL_IF(getBE().mHwcLayers.count(displayId) != 0,
- "Already have a layer for display %" PRIu64, displayId);
+ LOG_ALWAYS_FATAL_IF(hasHwcLayer(displayId), "Already have a layer for display %s",
+ to_string(displayId).c_str());
auto layer = std::shared_ptr<HWC2::Layer>(
hwc->createLayer(displayId),
[hwc, displayId](HWC2::Layer* layer) {
@@ -215,7 +215,7 @@
}
bool Layer::destroyHwcLayer(DisplayId displayId) {
- if (getBE().mHwcLayers.count(displayId) == 0) {
+ if (!hasHwcLayer(displayId)) {
return false;
}
auto& hwcInfo = getBE().mHwcLayers[displayId];
@@ -275,39 +275,12 @@
return Region(Rect{win}).subtract(exclude).getBounds().toFloatRect();
}
-Rect Layer::computeScreenBounds(bool reduceTransparentRegion) const {
- const State& s(getDrawingState());
- Rect win(getActiveWidth(s), getActiveHeight(s));
-
- Rect crop = getCrop(s);
- if (!crop.isEmpty()) {
- win.intersect(crop, &win);
- }
-
+Rect Layer::computeScreenBounds() const {
+ FloatRect bounds = computeBounds();
ui::Transform t = getTransform();
- win = t.transform(win);
-
- const sp<Layer>& p = mDrawingParent.promote();
- // Now we need to calculate the parent bounds, so we can clip ourselves to those.
- // When calculating the parent bounds for purposes of clipping,
- // we don't need to constrain the parent to its transparent region.
- // The transparent region is an optimization based on the
- // buffer contents of the layer, but does not affect the space allocated to
- // it by policy, and thus children should be allowed to extend into the
- // parent's transparent region. In fact one of the main uses, is to reduce
- // buffer allocation size in cases where a child window sits behind a main window
- // (by marking the hole in the parent window as a transparent region)
- if (p != nullptr) {
- Rect bounds = p->computeScreenBounds(false);
- bounds.intersect(win, &win);
- }
-
- if (reduceTransparentRegion) {
- auto const screenTransparentRegion = t.transform(getActiveTransparentRegion(s));
- win = reduce(win, screenTransparentRegion);
- }
-
- return win;
+ // Transform to screen space.
+ bounds = t.transform(bounds);
+ return Rect{bounds};
}
FloatRect Layer::computeBounds() const {
@@ -317,32 +290,72 @@
FloatRect Layer::computeBounds(const Region& activeTransparentRegion) const {
const State& s(getDrawingState());
- Rect win(getActiveWidth(s), getActiveHeight(s));
+ Rect bounds = getCroppedBufferSize(s);
+ FloatRect floatBounds = bounds.toFloatRect();
+ if (bounds.isValid()) {
+ // Layer has bounds. Pass in our bounds as a special case. Then pass on to our parents so
+ // that they can clip it.
+ floatBounds = cropChildBounds(floatBounds);
+ } else {
+ // Layer does not have bounds, so we fill to our parent bounds. This is done by getting our
+ // parent bounds and inverting the transform to get the maximum bounds we can have that
+ // will fit within our parent bounds.
+ const auto& p = mDrawingParent.promote();
+ if (p != nullptr) {
+ ui::Transform t = s.active_legacy.transform;
+ // When calculating the parent bounds for purposes of clipping, we don't need to
+ // constrain the parent to its transparent region. The transparent region is an
+ // optimization based on the buffer contents of the layer, but does not affect the
+ // space allocated to it by policy, and thus children should be allowed to extend into
+ // the parent's transparent region.
+ // One of the main uses is a parent window with a child sitting behind the parent
+ // window, marked by a transparent region. When computing the parent bounds from the
+ // parent's perspective we pass in the transparent region to reduce buffer allocation
+ // size. When computing the parent bounds from the child's perspective, we pass in an
+ // empty transparent region in order to extend into the the parent bounds.
+ floatBounds = p->computeBounds(Region());
+ // Transform back to layer space.
+ floatBounds = t.inverse().transform(floatBounds);
+ }
+ }
- Rect crop = getCrop(s);
- if (!crop.isEmpty()) {
- win.intersect(crop, &win);
+ // Subtract the transparent region and snap to the bounds.
+ return reduce(floatBounds, activeTransparentRegion);
+}
+
+FloatRect Layer::cropChildBounds(const FloatRect& childBounds) const {
+ const State& s(getDrawingState());
+ Rect bounds = getCroppedBufferSize(s);
+ FloatRect croppedBounds = childBounds;
+
+ // If the layer has bounds, then crop the passed in child bounds and pass
+ // it to our parents so they can crop it as well. If the layer has no bounds,
+ // then pass on the child bounds.
+ if (bounds.isValid()) {
+ croppedBounds = croppedBounds.intersect(bounds.toFloatRect());
}
const auto& p = mDrawingParent.promote();
- FloatRect floatWin = win.toFloatRect();
- FloatRect parentBounds = floatWin;
if (p != nullptr) {
- // We pass an empty Region here for reasons mirroring that of the case described in
- // the computeScreenBounds reduceTransparentRegion=false case.
- parentBounds = p->computeBounds(Region());
+ // Transform to parent space and allow parent layer to crop the
+ // child bounds as well.
+ ui::Transform t = s.active_legacy.transform;
+ croppedBounds = t.transform(croppedBounds);
+ croppedBounds = p->cropChildBounds(croppedBounds);
+ croppedBounds = t.inverse().transform(croppedBounds);
}
+ return croppedBounds;
+}
- ui::Transform t = s.active_legacy.transform;
-
- if (p != nullptr) {
- floatWin = t.transform(floatWin);
- floatWin = floatWin.intersect(parentBounds);
- floatWin = t.inverse().transform(floatWin);
+Rect Layer::getCroppedBufferSize(const State& s) const {
+ Rect size = getBufferSize(s);
+ Rect crop = getCrop(s);
+ if (!crop.isEmpty() && size.isValid()) {
+ size.intersect(crop, &size);
+ } else if (!crop.isEmpty()) {
+ size = crop;
}
-
- // subtract the transparent region and snap to the bounds
- return reduce(floatWin, activeTransparentRegion);
+ return size;
}
Rect Layer::computeInitialCrop(const sp<const DisplayDevice>& display) const {
@@ -462,11 +475,7 @@
void Layer::setGeometry(const sp<const DisplayDevice>& display, uint32_t z) {
const auto displayId = display->getId();
LOG_ALWAYS_FATAL_IF(!displayId);
- if (!hasHwcLayer(*displayId)) {
- ALOGE("[%s] failed to setGeometry: no HWC layer found for display %" PRIu64, mName.string(),
- *displayId);
- return;
- }
+ RETURN_IF_NO_HWC_LAYER(*displayId);
auto& hwcInfo = getBE().mHwcLayers[*displayId];
// enable this layer
@@ -634,27 +643,19 @@
}
void Layer::forceClientComposition(DisplayId displayId) {
- if (getBE().mHwcLayers.count(displayId) == 0) {
- ALOGE("forceClientComposition: no HWC layer found (display %" PRIu64 ")", displayId);
- return;
- }
-
+ RETURN_IF_NO_HWC_LAYER(displayId);
getBE().mHwcLayers[displayId].forceClientComposition = true;
}
bool Layer::getForceClientComposition(DisplayId displayId) {
- if (getBE().mHwcLayers.count(displayId) == 0) {
- ALOGE("getForceClientComposition: no HWC layer found (display %" PRIu64 ")", displayId);
- return false;
- }
-
+ RETURN_IF_NO_HWC_LAYER(displayId, false);
return getBE().mHwcLayers[displayId].forceClientComposition;
}
void Layer::updateCursorPosition(const sp<const DisplayDevice>& display) {
const auto displayId = display->getId();
- if (getBE().mHwcLayers.count(*displayId) == 0 ||
- getCompositionType(displayId) != HWC2::Composition::Cursor) {
+ LOG_ALWAYS_FATAL_IF(!displayId);
+ if (!hasHwcLayer(*displayId) || getCompositionType(displayId) != HWC2::Composition::Cursor) {
return;
}
@@ -1423,7 +1424,7 @@
}
void Layer::miniDump(String8& result, DisplayId displayId) const {
- if (getBE().mHwcLayers.count(displayId) == 0) {
+ if (!hasHwcLayer(displayId)) {
return;
}
diff --git a/services/surfaceflinger/Layer.h b/services/surfaceflinger/Layer.h
index e829a03..40ebe1e 100644
--- a/services/surfaceflinger/Layer.h
+++ b/services/surfaceflinger/Layer.h
@@ -508,7 +508,7 @@
bool destroyHwcLayer(DisplayId displayId);
void destroyAllHwcLayers();
- bool hasHwcLayer(DisplayId displayId) { return getBE().mHwcLayers.count(displayId) > 0; }
+ bool hasHwcLayer(DisplayId displayId) const { return getBE().mHwcLayers.count(displayId) > 0; }
HWC2::Layer* getHwcLayer(DisplayId displayId) {
if (!hasHwcLayer(displayId)) {
@@ -579,7 +579,7 @@
ssize_t removeChild(const sp<Layer>& layer);
sp<Layer> getParent() const { return mCurrentParent.promote(); }
bool hasParent() const { return getParent() != nullptr; }
- Rect computeScreenBounds(bool reduceTransparentRegion = true) const;
+ Rect computeScreenBounds() const;
bool setChildLayer(const sp<Layer>& childLayer, int32_t z);
bool setChildRelativeLayer(const sp<Layer>& childLayer,
const sp<IBinder>& relativeToHandle, int32_t relativeZ);
@@ -791,10 +791,38 @@
const LayerVector::Visitor& visitor);
LayerVector makeChildrenTraversalList(LayerVector::StateSet stateSet,
const std::vector<Layer*>& layersInTree);
+
+ /**
+ * Retuns the child bounds in layer space cropped to its bounds as well all its parent bounds.
+ * The cropped bounds must be transformed back from parent layer space to child layer space by
+ * applying the inverse of the child's transformation.
+ */
+ FloatRect cropChildBounds(const FloatRect& childBounds) const;
+
+ /**
+ * Returns the cropped buffer size or the layer crop if the layer has no buffer. Return
+ * INVALID_RECT if the layer has no buffer and no crop.
+ * A layer with an invalid buffer size and no crop is considered to be boundless. The layer
+ * bounds are constrained by its parent bounds.
+ */
+ Rect getCroppedBufferSize(const Layer::State& s) const;
+
+ /**
+ * Returns active buffer size in the correct orientation. Buffer size is determined by undoing
+ * any buffer transformations. If the layer has no buffer then return INVALID_RECT.
+ */
+ virtual Rect getBufferSize(const Layer::State&) const { return Rect::INVALID_RECT; }
};
-// ---------------------------------------------------------------------------
+} // namespace android
-}; // namespace android
+#define RETURN_IF_NO_HWC_LAYER(displayId, ...) \
+ do { \
+ if (!hasHwcLayer(displayId)) { \
+ ALOGE("[%s] %s failed: no HWC layer found for display %s", mName.string(), \
+ __FUNCTION__, to_string(displayId).c_str()); \
+ return __VA_ARGS__; \
+ } \
+ } while (false)
#endif // ANDROID_LAYER_H
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp
index ce3fb2d..e84e21a 100644
--- a/services/surfaceflinger/SurfaceFlinger.cpp
+++ b/services/surfaceflinger/SurfaceFlinger.cpp
@@ -1040,9 +1040,9 @@
LOG_ALWAYS_FATAL_IF(!displayId);
getHwComposer().setActiveColorMode(*displayId, mode, renderIntent);
- ALOGV("Set active color mode: %s (%d), active render intent: %s (%d), display=%" PRIu64,
+ ALOGV("Set active color mode: %s (%d), active render intent: %s (%d), display=%s",
decodeColorMode(mode).c_str(), mode, decodeRenderIntent(renderIntent).c_str(),
- renderIntent, *displayId);
+ renderIntent, to_string(*displayId).c_str());
}
status_t SurfaceFlinger::setActiveColorMode(const sp<IBinder>& displayToken, ColorMode mode) {
@@ -1636,8 +1636,8 @@
display->setColorTransform(mDrawingState.colorMatrix);
status_t result =
getHwComposer().setColorTransform(*displayId, mDrawingState.colorMatrix);
- ALOGE_IF(result != NO_ERROR, "Failed to set color transform on display %" PRIu64 ": %d",
- *displayId, result);
+ ALOGE_IF(result != NO_ERROR, "Failed to set color transform on display %s: %d",
+ to_string(*displayId).c_str(), result);
}
for (auto& layer : display->getVisibleLayersSortedByZ()) {
if (layer->isHdrY410()) {
@@ -2273,7 +2273,7 @@
if (event.connection == HWC2::Connection::Connected) {
if (!mPhysicalDisplayTokens.count(info->id)) {
- ALOGV("Creating display %" PRIu64, info->id);
+ ALOGV("Creating display %s", to_string(info->id).c_str());
mPhysicalDisplayTokens[info->id] = new BBinder();
DisplayDeviceState state;
state.displayId = info->id;
@@ -2283,7 +2283,7 @@
mInterceptor->saveDisplayCreation(state);
}
} else {
- ALOGV("Removing display %" PRIu64, info->id);
+ ALOGV("Removing display %s", to_string(info->id).c_str());
ssize_t index = mCurrentState.displays.indexOfKey(mPhysicalDisplayTokens[info->id]);
if (index >= 0) {
@@ -2955,8 +2955,7 @@
// 1) It is being handled by hardware composer, which may need this to
// keep its virtual display state machine in sync, or
// 2) There is work to be done (the dirty region isn't empty)
- bool isHwcDisplay = display->getId() >= 0;
- if (!isHwcDisplay && inDirtyRegion.isEmpty()) {
+ if (!display->getId() && inDirtyRegion.isEmpty()) {
ALOGV("Skipping display composition");
return;
}
@@ -3863,7 +3862,7 @@
const auto displayId = display->getId();
LOG_ALWAYS_FATAL_IF(!displayId);
- ALOGD("Setting power mode %d on display %" PRIu64, mode, *displayId);
+ ALOGD("Setting power mode %d on display %s", mode, to_string(*displayId).c_str());
int currentMode = display->getPowerMode();
if (mode == currentMode) {
@@ -3962,7 +3961,7 @@
mTimeStats.setPowerMode(mode);
}
- ALOGD("Finished setting power mode %d on display %" PRIu64, mode, *displayId);
+ ALOGD("Finished setting power mode %d on display %s", mode, to_string(*displayId).c_str());
}
void SurfaceFlinger::setPowerMode(const sp<IBinder>& displayToken, int mode) {
@@ -4293,7 +4292,7 @@
continue;
}
- result.appendFormat("Display %" PRIu64 " (HWC display %" PRIu64 "): ", *displayId,
+ result.appendFormat("Display %s (HWC display %" PRIu64 "): ", to_string(*displayId).c_str(),
*hwcDisplayId);
uint8_t port;
DisplayIdentificationData data;
@@ -4341,7 +4340,7 @@
continue;
}
- result.appendFormat("Display %" PRIu64 " color modes:\n", *displayId);
+ result.appendFormat("Display %s color modes:\n", to_string(*displayId).c_str());
std::vector<ColorMode> modes = getHwComposer().getColorModes(*displayId);
for (auto&& mode : modes) {
result.appendFormat(" %s (%d)\n", decodeColorMode(mode).c_str(), mode);
@@ -4460,15 +4459,15 @@
if (const auto displayId = getInternalDisplayId();
displayId && getHwComposer().isConnected(*displayId)) {
const auto activeConfig = getHwComposer().getActiveConfig(*displayId);
- result.appendFormat("Display %" PRIu64 ": app phase %" PRId64 " ns, "
+ result.appendFormat("Display %s: app phase %" PRId64 " ns, "
"sf phase %" PRId64 " ns, "
"early app phase %" PRId64 " ns, "
"early sf phase %" PRId64 " ns, "
"early app gl phase %" PRId64 " ns, "
"early sf gl phase %" PRId64 " ns, "
"present offset %" PRId64 " ns (refresh %" PRId64 " ns)",
- *displayId, vsyncPhaseOffsetNs, sfVsyncPhaseOffsetNs, appEarlyOffset,
- sfEarlyOffset, appEarlyGlOffset, sfEarlyGlOffset,
+ to_string(*displayId).c_str(), vsyncPhaseOffsetNs, sfVsyncPhaseOffsetNs,
+ appEarlyOffset, sfEarlyOffset, appEarlyGlOffset, sfEarlyGlOffset,
dispSyncPresentTimeOffset, activeConfig->getVsyncPeriod());
}
result.append("\n");
@@ -4572,7 +4571,7 @@
continue;
}
- result.appendFormat("Display %" PRIu64 " HWC layers:\n", *displayId);
+ result.appendFormat("Display %s HWC layers:\n", to_string(*displayId).c_str());
Layer::miniDumpHeader(result);
mCurrentState.traverseInZOrder([&](Layer* layer) { layer->miniDump(result, *displayId); });
result.append("\n");
@@ -4613,7 +4612,7 @@
}
}
- ALOGE("%s: Invalid display %" PRIu64, __FUNCTION__, displayId);
+ ALOGE("%s: Invalid display %s", __FUNCTION__, to_string(displayId).c_str());
static const Vector<sp<Layer>> empty;
return empty;
}
diff --git a/services/surfaceflinger/SurfaceInterceptor.cpp b/services/surfaceflinger/SurfaceInterceptor.cpp
index 7faaff6..55cfa4b 100644
--- a/services/surfaceflinger/SurfaceInterceptor.cpp
+++ b/services/surfaceflinger/SurfaceInterceptor.cpp
@@ -497,7 +497,7 @@
creation->set_name(info.displayName);
creation->set_is_secure(info.isSecure);
if (info.displayId) {
- creation->set_display_id(*info.displayId);
+ creation->set_display_id(info.displayId->value);
}
}
diff --git a/services/surfaceflinger/tests/SurfaceFlinger_test.filter b/services/surfaceflinger/tests/SurfaceFlinger_test.filter
index 8bd5fcb..91999ae 100644
--- a/services/surfaceflinger/tests/SurfaceFlinger_test.filter
+++ b/services/surfaceflinger/tests/SurfaceFlinger_test.filter
@@ -1,5 +1,5 @@
{
"presubmit": {
- "filter": "CredentialsTest.*:SurfaceFlingerStress.*:SurfaceInterceptorTest.*:LayerTransactionTest.*:LayerTypeTransactionTest.*:LayerUpdateTest.*:GeometryLatchingTest.*:CropLatchingTest.*:ChildLayerTest.*:ScreenCaptureTest.*:ScreenCaptureChildOnlyTest.*:DereferenceSurfaceControlTest.*"
+ "filter": "CredentialsTest.*:SurfaceFlingerStress.*:SurfaceInterceptorTest.*:LayerTransactionTest.*:LayerTypeTransactionTest.*:LayerUpdateTest.*:GeometryLatchingTest.*:CropLatchingTest.*:ChildLayerTest.*:ScreenCaptureTest.*:ScreenCaptureChildOnlyTest.*:DereferenceSurfaceControlTest.*:BoundlessLayerTest.*"
}
}
diff --git a/services/surfaceflinger/tests/Transaction_test.cpp b/services/surfaceflinger/tests/Transaction_test.cpp
index be8d939..988454a 100644
--- a/services/surfaceflinger/tests/Transaction_test.cpp
+++ b/services/surfaceflinger/tests/Transaction_test.cpp
@@ -338,10 +338,14 @@
client->createSurface(String8(name), width, height, PIXEL_FORMAT_RGBA_8888, flags);
EXPECT_NE(nullptr, layer.get()) << "failed to create SurfaceControl";
- status_t error = Transaction()
- .setLayerStack(layer, mDisplayLayerStack)
- .setLayer(layer, mLayerZBase)
- .apply();
+ Transaction t;
+ t.setLayerStack(layer, mDisplayLayerStack).setLayer(layer, mLayerZBase);
+ // If we are creating a color layer, set its crop since its size will be ignored.
+ if (flags == ISurfaceComposerClient::eFXSurfaceColor) {
+ t.setCrop_legacy(layer, Rect(0, 0, width, height));
+ }
+
+ status_t error = t.apply();
if (error != NO_ERROR) {
ADD_FAILURE() << "failed to initialize SurfaceControl";
layer.clear();
@@ -512,6 +516,7 @@
// set layer stack (b/68888219)
Transaction t;
t.setDisplayLayerStack(mDisplay, mDisplayLayerStack);
+ t.setCrop_legacy(mBlackBgSurface, Rect(0, 0, mDisplayWidth, mDisplayHeight));
t.setLayerStack(mBlackBgSurface, mDisplayLayerStack);
t.setColor(mBlackBgSurface, half3{0, 0, 0});
t.setLayer(mBlackBgSurface, mLayerZBase);
@@ -3025,17 +3030,19 @@
mClient->createSurface(String8("Buffered child"), 20, 20,
PIXEL_FORMAT_RGBA_8888, 0, childNoBuffer.get());
fillSurfaceRGBA8(childBuffer, 200, 200, 200);
-
- SurfaceComposerClient::Transaction{}.show(childNoBuffer).show(childBuffer).apply(true);
-
+ SurfaceComposerClient::Transaction{}
+ .setCrop_legacy(childNoBuffer, Rect(0, 0, 10, 10))
+ .show(childNoBuffer)
+ .show(childBuffer)
+ .apply(true);
{
ScreenCapture::captureScreen(&sc);
sc->expectChildColor(73, 73);
sc->expectFGColor(74, 74);
}
-
- SurfaceComposerClient::Transaction{}.setSize(childNoBuffer, 20, 20).apply(true);
-
+ SurfaceComposerClient::Transaction{}
+ .setCrop_legacy(childNoBuffer, Rect(0, 0, 20, 20))
+ .apply(true);
{
ScreenCapture::captureScreen(&sc);
sc->expectChildColor(73, 73);
@@ -3570,6 +3577,221 @@
mCapture->checkPixel(10, 10, 255, 255, 255);
}
}
+class BoundlessLayerTest : public LayerUpdateTest {
+protected:
+ std::unique_ptr<ScreenCapture> mCapture;
+};
+
+// Verify setting a size on a buffer layer has no effect.
+TEST_F(BoundlessLayerTest, BufferLayerIgnoresSize) {
+ sp<SurfaceControl> bufferLayer =
+ mClient->createSurface(String8("BufferLayer"), 45, 45, PIXEL_FORMAT_RGBA_8888, 0,
+ mFGSurfaceControl.get());
+ ASSERT_TRUE(bufferLayer != nullptr);
+ ASSERT_TRUE(bufferLayer->isValid());
+ ASSERT_NO_FATAL_FAILURE(fillBufferQueueLayerColor(bufferLayer, Color::BLACK, 30, 30));
+ asTransaction([&](Transaction& t) { t.show(bufferLayer); });
+ {
+ mCapture = screenshot();
+ // Top left of background must now be visible
+ mCapture->expectBGColor(0, 0);
+ // Foreground Surface bounds must be color layer
+ mCapture->expectColor(Rect(64, 64, 94, 94), Color::BLACK);
+ // Buffer layer should not extend past buffer bounds
+ mCapture->expectFGColor(95, 95);
+ }
+}
+
+// Verify a boundless color layer will fill its parent bounds. The parent has a buffer size
+// which will crop the color layer.
+TEST_F(BoundlessLayerTest, BoundlessColorLayerFillsParentBufferBounds) {
+ sp<SurfaceControl> colorLayer =
+ mClient->createSurface(String8("ColorLayer"), 0, 0, PIXEL_FORMAT_RGBA_8888,
+ ISurfaceComposerClient::eFXSurfaceColor,
+ mFGSurfaceControl.get());
+ ASSERT_TRUE(colorLayer != nullptr);
+ ASSERT_TRUE(colorLayer->isValid());
+ asTransaction([&](Transaction& t) {
+ t.setColor(colorLayer, half3{0, 0, 0});
+ t.show(colorLayer);
+ });
+ {
+ mCapture = screenshot();
+ // Top left of background must now be visible
+ mCapture->expectBGColor(0, 0);
+ // Foreground Surface bounds must be color layer
+ mCapture->expectColor(Rect(64, 64, 128, 128), Color::BLACK);
+ // Color layer should not extend past foreground bounds
+ mCapture->expectBGColor(129, 129);
+ }
+}
+
+// Verify a boundless color layer will fill its parent bounds. The parent has no buffer but has
+// a crop which will be used to crop the color layer.
+TEST_F(BoundlessLayerTest, BoundlessColorLayerFillsParentCropBounds) {
+ sp<SurfaceControl> cropLayer =
+ mClient->createSurface(String8("CropLayer"), 0, 0, PIXEL_FORMAT_RGBA_8888,
+ 0 /* flags */, mFGSurfaceControl.get());
+ ASSERT_TRUE(cropLayer != nullptr);
+ ASSERT_TRUE(cropLayer->isValid());
+ sp<SurfaceControl> colorLayer =
+ mClient->createSurface(String8("ColorLayer"), 0, 0, PIXEL_FORMAT_RGBA_8888,
+ ISurfaceComposerClient::eFXSurfaceColor, cropLayer.get());
+ ASSERT_TRUE(colorLayer != nullptr);
+ ASSERT_TRUE(colorLayer->isValid());
+ asTransaction([&](Transaction& t) {
+ t.setCrop_legacy(cropLayer, Rect(5, 5, 10, 10));
+ t.setColor(colorLayer, half3{0, 0, 0});
+ t.show(cropLayer);
+ t.show(colorLayer);
+ });
+ {
+ mCapture = screenshot();
+ // Top left of background must now be visible
+ mCapture->expectBGColor(0, 0);
+ // Top left of foreground must now be visible
+ mCapture->expectFGColor(64, 64);
+ // 5 pixels from the foreground we should see the child surface
+ mCapture->expectColor(Rect(69, 69, 74, 74), Color::BLACK);
+ // 10 pixels from the foreground we should be back to the foreground surface
+ mCapture->expectFGColor(74, 74);
+ }
+}
+
+// Verify for boundless layer with no children, their transforms have no effect.
+TEST_F(BoundlessLayerTest, BoundlessColorLayerTransformHasNoEffect) {
+ sp<SurfaceControl> colorLayer =
+ mClient->createSurface(String8("ColorLayer"), 0, 0, PIXEL_FORMAT_RGBA_8888,
+ ISurfaceComposerClient::eFXSurfaceColor,
+ mFGSurfaceControl.get());
+ ASSERT_TRUE(colorLayer != nullptr);
+ ASSERT_TRUE(colorLayer->isValid());
+ asTransaction([&](Transaction& t) {
+ t.setPosition(colorLayer, 320, 320);
+ t.setMatrix(colorLayer, 2, 0, 0, 2);
+ t.setColor(colorLayer, half3{0, 0, 0});
+ t.show(colorLayer);
+ });
+ {
+ mCapture = screenshot();
+ // Top left of background must now be visible
+ mCapture->expectBGColor(0, 0);
+ // Foreground Surface bounds must be color layer
+ mCapture->expectColor(Rect(64, 64, 128, 128), Color::BLACK);
+ // Color layer should not extend past foreground bounds
+ mCapture->expectBGColor(129, 129);
+ }
+}
+
+// Verify for boundless layer with children, their transforms have an effect.
+TEST_F(BoundlessLayerTest, IntermediateBoundlessLayerCanSetTransform) {
+ sp<SurfaceControl> boundlessLayerRightShift =
+ mClient->createSurface(String8("BoundlessLayerRightShift"), 0, 0,
+ PIXEL_FORMAT_RGBA_8888, 0 /* flags */, mFGSurfaceControl.get());
+ ASSERT_TRUE(boundlessLayerRightShift != nullptr);
+ ASSERT_TRUE(boundlessLayerRightShift->isValid());
+ sp<SurfaceControl> boundlessLayerDownShift =
+ mClient->createSurface(String8("BoundlessLayerLeftShift"), 0, 0, PIXEL_FORMAT_RGBA_8888,
+ 0 /* flags */, boundlessLayerRightShift.get());
+ ASSERT_TRUE(boundlessLayerDownShift != nullptr);
+ ASSERT_TRUE(boundlessLayerDownShift->isValid());
+ sp<SurfaceControl> colorLayer =
+ mClient->createSurface(String8("ColorLayer"), 0, 0, PIXEL_FORMAT_RGBA_8888,
+ ISurfaceComposerClient::eFXSurfaceColor,
+ boundlessLayerDownShift.get());
+ ASSERT_TRUE(colorLayer != nullptr);
+ ASSERT_TRUE(colorLayer->isValid());
+ asTransaction([&](Transaction& t) {
+ t.setPosition(boundlessLayerRightShift, 32, 0);
+ t.show(boundlessLayerRightShift);
+ t.setPosition(boundlessLayerDownShift, 0, 32);
+ t.show(boundlessLayerDownShift);
+ t.setCrop_legacy(colorLayer, Rect(0, 0, 64, 64));
+ t.setColor(colorLayer, half3{0, 0, 0});
+ t.show(colorLayer);
+ });
+ {
+ mCapture = screenshot();
+ // Top left of background must now be visible
+ mCapture->expectBGColor(0, 0);
+ // Top left of foreground must now be visible
+ mCapture->expectFGColor(64, 64);
+ // Foreground Surface bounds must be color layer
+ mCapture->expectColor(Rect(96, 96, 128, 128), Color::BLACK);
+ // Color layer should not extend past foreground bounds
+ mCapture->expectBGColor(129, 129);
+ }
+}
+
+// Verify child layers do not get clipped if they temporarily move into the negative
+// coordinate space as the result of an intermediate transformation.
+TEST_F(BoundlessLayerTest, IntermediateBoundlessLayerDoNotCrop) {
+ sp<SurfaceControl> boundlessLayer =
+ mClient->createSurface(String8("BoundlessLayer"), 0, 0, PIXEL_FORMAT_RGBA_8888,
+ 0 /* flags */, mFGSurfaceControl.get());
+ ASSERT_TRUE(boundlessLayer != nullptr);
+ ASSERT_TRUE(boundlessLayer->isValid());
+ sp<SurfaceControl> colorLayer =
+ mClient->createSurface(String8("ColorLayer"), 0, 0, PIXEL_FORMAT_RGBA_8888,
+ ISurfaceComposerClient::eFXSurfaceColor, boundlessLayer.get());
+ ASSERT_TRUE(colorLayer != nullptr);
+ ASSERT_TRUE(colorLayer->isValid());
+ asTransaction([&](Transaction& t) {
+ // shift child layer off bounds. If this layer was not boundless, we will
+ // expect the child layer to be cropped.
+ t.setPosition(boundlessLayer, 32, 32);
+ t.show(boundlessLayer);
+ t.setCrop_legacy(colorLayer, Rect(0, 0, 64, 64));
+ // undo shift by parent
+ t.setPosition(colorLayer, -32, -32);
+ t.setColor(colorLayer, half3{0, 0, 0});
+ t.show(colorLayer);
+ });
+ {
+ mCapture = screenshot();
+ // Top left of background must now be visible
+ mCapture->expectBGColor(0, 0);
+ // Foreground Surface bounds must be color layer
+ mCapture->expectColor(Rect(64, 64, 128, 128), Color::BLACK);
+ // Color layer should not extend past foreground bounds
+ mCapture->expectBGColor(129, 129);
+ }
+}
+
+// Verify for boundless root layers with children, their transforms have an effect.
+TEST_F(BoundlessLayerTest, RootBoundlessLayerCanSetTransform) {
+ sp<SurfaceControl> rootBoundlessLayer =
+ mClient->createSurface(String8("RootBoundlessLayer"), 0, 0, PIXEL_FORMAT_RGBA_8888,
+ 0 /* flags */);
+ ASSERT_TRUE(rootBoundlessLayer != nullptr);
+ ASSERT_TRUE(rootBoundlessLayer->isValid());
+ sp<SurfaceControl> colorLayer =
+ mClient->createSurface(String8("ColorLayer"), 0, 0, PIXEL_FORMAT_RGBA_8888,
+ ISurfaceComposerClient::eFXSurfaceColor,
+ rootBoundlessLayer.get());
+ ASSERT_TRUE(colorLayer != nullptr);
+ ASSERT_TRUE(colorLayer->isValid());
+ asTransaction([&](Transaction& t) {
+ t.setLayer(rootBoundlessLayer, INT32_MAX - 1);
+ t.setPosition(rootBoundlessLayer, 32, 32);
+ t.show(rootBoundlessLayer);
+ t.setCrop_legacy(colorLayer, Rect(0, 0, 64, 64));
+ t.setColor(colorLayer, half3{0, 0, 0});
+ t.show(colorLayer);
+ t.hide(mFGSurfaceControl);
+ });
+ {
+ mCapture = screenshot();
+ // Top left of background must now be visible
+ mCapture->expectBGColor(0, 0);
+ // Top left of foreground must now be visible
+ mCapture->expectBGColor(31, 31);
+ // Foreground Surface bounds must be color layer
+ mCapture->expectColor(Rect(32, 32, 96, 96), Color::BLACK);
+ // Color layer should not extend past foreground bounds
+ mCapture->expectBGColor(97, 97);
+ }
+}
class ScreenCaptureTest : public LayerUpdateTest {
protected:
diff --git a/services/surfaceflinger/tests/unittests/CompositionTest.cpp b/services/surfaceflinger/tests/unittests/CompositionTest.cpp
index f0f1d3d..cfaf495 100644
--- a/services/surfaceflinger/tests/unittests/CompositionTest.cpp
+++ b/services/surfaceflinger/tests/unittests/CompositionTest.cpp
@@ -67,7 +67,7 @@
constexpr hwc2_layer_t HWC_LAYER = 5000;
constexpr Transform DEFAULT_TRANSFORM = static_cast<Transform>(0);
-constexpr DisplayId DEFAULT_DISPLAY_ID = 42;
+constexpr DisplayId DEFAULT_DISPLAY_ID = DisplayId{42};
constexpr int DEFAULT_DISPLAY_WIDTH = 1920;
constexpr int DEFAULT_DISPLAY_HEIGHT = 1024;
@@ -795,6 +795,9 @@
LayerProperties::HEIGHT,
LayerProperties::LAYER_FLAGS));
});
+
+ auto& layerDrawingState = test->mFlinger.mutableLayerDrawingState(layer);
+ layerDrawingState.crop_legacy = Rect(0, 0, LayerProperties::HEIGHT, LayerProperties::WIDTH);
return layer;
}
diff --git a/services/surfaceflinger/tests/unittests/DisplayTransactionTest.cpp b/services/surfaceflinger/tests/unittests/DisplayTransactionTest.cpp
index aa1fc1a..ac6a78b 100644
--- a/services/surfaceflinger/tests/unittests/DisplayTransactionTest.cpp
+++ b/services/surfaceflinger/tests/unittests/DisplayTransactionTest.cpp
@@ -248,8 +248,8 @@
template <typename PhysicalDisplay>
struct PhysicalDisplayId {};
-template <DisplayId displayId>
-using VirtualDisplayId = std::integral_constant<DisplayId, displayId>;
+template <DisplayId::Type displayId>
+using VirtualDisplayId = std::integral_constant<DisplayId::Type, displayId>;
struct NoDisplayId {};
@@ -278,9 +278,9 @@
}
};
-template <DisplayId displayId>
+template <DisplayId::Type displayId>
struct DisplayIdGetter<VirtualDisplayId<displayId>> {
- static std::optional<DisplayId> get() { return displayId; }
+ static std::optional<DisplayId> get() { return DisplayId{displayId}; }
};
template <>
@@ -1085,7 +1085,7 @@
*/
class GetBestColorModeTest : public DisplayTransactionTest {
public:
- static constexpr DisplayId DEFAULT_DISPLAY_ID = 777;
+ static constexpr DisplayId DEFAULT_DISPLAY_ID = DisplayId{777};
GetBestColorModeTest()
: DisplayTransactionTest(),
diff --git a/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h b/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h
index dc42414..85c835e 100644
--- a/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h
+++ b/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h
@@ -175,6 +175,7 @@
auto& mutableLayerDrawingState(sp<Layer> layer) { return layer->mDrawingState; }
void setLayerSidebandStream(sp<Layer> layer, sp<NativeHandle> sidebandStream) {
+ layer->mDrawingState.sidebandStream = sidebandStream;
layer->getBE().compositionInfo.hwc.sidebandStream = sidebandStream;
}
diff --git a/services/surfaceflinger/tests/unittests/mock/RenderEngine/MockRenderEngine.cpp b/services/surfaceflinger/tests/unittests/mock/RenderEngine/MockRenderEngine.cpp
index af54df6..fbfbc3f 100644
--- a/services/surfaceflinger/tests/unittests/mock/RenderEngine/MockRenderEngine.cpp
+++ b/services/surfaceflinger/tests/unittests/mock/RenderEngine/MockRenderEngine.cpp
@@ -26,9 +26,6 @@
RenderEngine::RenderEngine() = default;
RenderEngine::~RenderEngine() = default;
-Surface::Surface() = default;
-Surface::~Surface() = default;
-
Image::Image() = default;
Image::~Image() = default;
diff --git a/services/surfaceflinger/tests/unittests/mock/RenderEngine/MockRenderEngine.h b/services/surfaceflinger/tests/unittests/mock/RenderEngine/MockRenderEngine.h
index afca63a..90c3c20 100644
--- a/services/surfaceflinger/tests/unittests/mock/RenderEngine/MockRenderEngine.h
+++ b/services/surfaceflinger/tests/unittests/mock/RenderEngine/MockRenderEngine.h
@@ -23,7 +23,6 @@
#include <renderengine/LayerSettings.h>
#include <renderengine/Mesh.h>
#include <renderengine/RenderEngine.h>
-#include <renderengine/Surface.h>
#include <renderengine/Texture.h>
#include <ui/GraphicBuffer.h>
@@ -37,15 +36,12 @@
~RenderEngine() override;
MOCK_METHOD0(createFramebuffer, std::unique_ptr<Framebuffer>());
- MOCK_METHOD0(createSurface, std::unique_ptr<renderengine::Surface>());
MOCK_METHOD0(createImage, std::unique_ptr<renderengine::Image>());
MOCK_CONST_METHOD0(primeCache, void());
MOCK_METHOD1(dump, void(String8&));
MOCK_CONST_METHOD0(useNativeFenceSync, bool());
MOCK_CONST_METHOD0(useWaitSync, bool());
MOCK_CONST_METHOD0(isCurrent, bool());
- MOCK_METHOD1(setCurrentSurface, bool(const renderengine::Surface&));
- MOCK_METHOD0(resetCurrentSurface, void());
MOCK_METHOD0(flush, base::unique_fd());
MOCK_METHOD0(finish, bool());
MOCK_METHOD1(waitFence, bool(base::unique_fd*));
@@ -82,23 +78,6 @@
ANativeWindowBuffer* const, base::unique_fd*));
};
-class Surface : public renderengine::Surface {
-public:
- Surface();
- ~Surface() override;
-
- MOCK_METHOD1(setCritical, void(bool));
- MOCK_METHOD1(setAsync, void(bool));
- MOCK_METHOD1(setNativeWindow, void(ANativeWindow*));
- MOCK_CONST_METHOD0(swapBuffers, void());
- MOCK_CONST_METHOD0(queryRedSize, int32_t());
- MOCK_CONST_METHOD0(queryGreenSize, int32_t());
- MOCK_CONST_METHOD0(queryBlueSize, int32_t());
- MOCK_CONST_METHOD0(queryAlphaSize, int32_t());
- MOCK_CONST_METHOD0(getWidth, int32_t());
- MOCK_CONST_METHOD0(getHeight, int32_t());
-};
-
class Image : public renderengine::Image {
public:
Image();