From 736c74eac3cfb2f9b35c66a8948a04e343a4eff8 Mon Sep 17 00:00:00 2001 From: Jiwen 'Steve' Cai Date: Tue, 28 May 2019 18:33:22 -0700 Subject: Update the how we propogate parent type and appId SurfaceFlinger sends each layer's metadata (i.e. type and appId) to the hardware composer. The feature was introduced in Android Q for the 2D-in-VR feature that Daydream uses. The logic was introduced in ag/3738015. When sending layer information to hal, layers also inherit type and app id from parent node when parent node has valid type/appId. However, there are some descendents about what is the invalid type and appId. The original CL ag/3738015 assumes -1 is invalid, while newer CLs ag/6072974 and unittests assumes 0 as default value. Actually, the current unittests is correct, for two reasons: 1/ window type comes from WindowManager.LayoutParams and all values defined here are non-zero. 2/ appId is basically app's UID, which should not be zero (i.e. app never runs under root). Thus, I now have enough reason to conclude that the parent type and appId should be tested with "type > 0 && appId > 0". In another word, the parent is only valid when the type and appId are both non-zero. Bug: 133452166 Test: Inspect the output of "adb shell lshal debug android.hardware.graphics.composer@2.1::IComposer/vr" and verify that each layer's type and app_id are correctly populated. Test: atest libsurfaceflinger_unittest Change-Id: Ib039a54bba241839f49e0be6d87c021001b470e9 --- services/surfaceflinger/Layer.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'services/surfaceflinger/Layer.cpp') diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp index 3ca6ef500d..832067b708 100644 --- a/services/surfaceflinger/Layer.cpp +++ b/services/surfaceflinger/Layer.cpp @@ -415,7 +415,7 @@ void Layer::latchGeometry(compositionengine::LayerFECompositionState& compositio auto& parentState = parent->getDrawingState(); const int parentType = parentState.metadata.getInt32(METADATA_WINDOW_TYPE, 0); const int parentAppId = parentState.metadata.getInt32(METADATA_OWNER_UID, 0); - if (parentType >= 0 || parentAppId >= 0) { + if (parentType > 0 && parentAppId > 0) { type = parentType; appId = parentAppId; } -- cgit v1.2.3-59-g8ed1b From 8002fcab8445bf52b178691a13a67936c69c8035 Mon Sep 17 00:00:00 2001 From: Alec Mouri Date: Fri, 28 Jun 2019 15:24:13 -0700 Subject: [SurfaceFlinger] Clean-up dead code * Remove methods that are no longer used. * Downgrade visibility of public RenderEngine methods that are currently unused. Test: builds Change-Id: I27d4e1cd7e88b1404d20149e9d0bc89f6cf1bde6 --- libs/renderengine/gl/GLESRenderEngine.cpp | 40 -------------- libs/renderengine/gl/GLESRenderEngine.h | 61 +++++++++------------- .../include/renderengine/RenderEngine.h | 56 -------------------- .../include/renderengine/mock/RenderEngine.h | 24 --------- services/surfaceflinger/BufferLayerConsumer.cpp | 24 --------- services/surfaceflinger/BufferLayerConsumer.h | 5 -- .../include/compositionengine/RenderSurface.h | 4 -- .../include/compositionengine/impl/RenderSurface.h | 1 - .../include/compositionengine/mock/RenderSurface.h | 1 - .../CompositionEngine/src/RenderSurface.cpp | 7 --- .../CompositionEngine/tests/RenderSurfaceTest.cpp | 14 ----- services/surfaceflinger/Layer.cpp | 26 --------- services/surfaceflinger/Layer.h | 2 - services/surfaceflinger/SurfaceFlinger.cpp | 5 -- services/surfaceflinger/SurfaceFlinger.h | 1 - .../tests/unittests/CompositionTest.cpp | 5 -- 16 files changed, 26 insertions(+), 250 deletions(-) (limited to 'services/surfaceflinger/Layer.cpp') diff --git a/libs/renderengine/gl/GLESRenderEngine.cpp b/libs/renderengine/gl/GLESRenderEngine.cpp index 46a8e9eecf..6e7ec336e9 100644 --- a/libs/renderengine/gl/GLESRenderEngine.cpp +++ b/libs/renderengine/gl/GLESRenderEngine.cpp @@ -456,10 +456,6 @@ void GLESRenderEngine::primeCache() const { mFeatureFlags & USE_COLOR_MANAGEMENT); } -bool GLESRenderEngine::isCurrent() const { - return mEGLDisplay == eglGetCurrentDisplay() && mEGLContext == eglGetCurrentContext(); -} - base::unique_fd GLESRenderEngine::flush() { ATRACE_CALL(); if (!GLExtensions::getInstance().hasNativeFenceSync()) { @@ -795,7 +791,6 @@ status_t GLESRenderEngine::bindFrameBuffer(Framebuffer* framebuffer) { glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, textureName, 0); uint32_t glStatus = glCheckFramebufferStatus(GL_FRAMEBUFFER); - ALOGE_IF(glStatus != GL_FRAMEBUFFER_COMPLETE_OES, "glCheckFramebufferStatusOES error %d", glStatus); @@ -1013,33 +1008,6 @@ status_t GLESRenderEngine::drawLayers(const DisplaySettings& display, return NO_ERROR; } -void GLESRenderEngine::setViewportAndProjection(size_t vpw, size_t vph, Rect sourceCrop, - ui::Transform::orientation_flags rotation) { - setViewportAndProjection(Rect(vpw, vph), sourceCrop); - - if (rotation == ui::Transform::ROT_0) { - return; - } - - // Apply custom rotation to the projection. - float rot90InRadians = 2.0f * static_cast(M_PI) / 4.0f; - mat4 m = mState.projectionMatrix; - switch (rotation) { - case ui::Transform::ROT_90: - m = mat4::rotate(rot90InRadians, vec3(0, 0, 1)) * m; - break; - case ui::Transform::ROT_180: - m = mat4::rotate(rot90InRadians * 2.0f, vec3(0, 0, 1)) * m; - break; - case ui::Transform::ROT_270: - m = mat4::rotate(rot90InRadians * 3.0f, vec3(0, 0, 1)) * m; - break; - default: - break; - } - mState.projectionMatrix = m; -} - void GLESRenderEngine::setViewportAndProjection(Rect viewport, Rect clip) { ATRACE_CALL(); mVpWidth = viewport.getWidth(); @@ -1103,14 +1071,6 @@ void GLESRenderEngine::setupLayerTexturing(const Texture& texture) { mState.textureEnabled = true; } -void GLESRenderEngine::setupLayerBlackedOut() { - glBindTexture(GL_TEXTURE_2D, mProtectedTexName); - Texture texture(Texture::TEXTURE_2D, mProtectedTexName); - texture.setDimensions(1, 1); // FIXME: we should get that from somewhere - mState.texture = texture; - mState.textureEnabled = true; -} - void GLESRenderEngine::setColorTransform(const mat4& colorTransform) { mState.colorMatrix = colorTransform; } diff --git a/libs/renderengine/gl/GLESRenderEngine.h b/libs/renderengine/gl/GLESRenderEngine.h index de793c2142..70b704abce 100644 --- a/libs/renderengine/gl/GLESRenderEngine.h +++ b/libs/renderengine/gl/GLESRenderEngine.h @@ -50,7 +50,6 @@ class GLESRenderEngine : public impl::RenderEngine { public: static std::unique_ptr create(int hwcFormat, uint32_t featureFlags, uint32_t imageCacheSize); - static EGLConfig chooseEglConfig(EGLDisplay display, int format, bool logConfig); GLESRenderEngine(uint32_t featureFlags, // See RenderEngine::FeatureFlag EGLDisplay display, EGLConfig config, EGLContext ctxt, EGLSurface dummy, @@ -58,17 +57,7 @@ public: uint32_t imageCacheSize); ~GLESRenderEngine() override EXCLUDES(mRenderingMutex); - std::unique_ptr createFramebuffer() override; - std::unique_ptr createImage() override; - void primeCache() const override; - bool isCurrent() const override; - base::unique_fd flush() override; - bool finish() override; - bool waitFence(base::unique_fd fenceFd) override; - void clearWithColor(float red, float green, float blue, float alpha) override; - void fillRegionWithColor(const Region& region, float red, float green, float blue, - float alpha) override; void genTextures(size_t count, uint32_t* names) override; void deleteTextures(size_t count, uint32_t const* names) override; void bindExternalTextureImage(uint32_t texName, const Image& image) override; @@ -78,7 +67,6 @@ public: void unbindExternalTextureBuffer(uint64_t bufferId) EXCLUDES(mRenderingMutex); status_t bindFrameBuffer(Framebuffer* framebuffer) override; void unbindFrameBuffer(Framebuffer* framebuffer) override; - void checkErrors() const override; bool isProtected() const override { return mInProtectedContext; } bool supportsProtectedContent() const override; @@ -88,9 +76,7 @@ public: base::unique_fd&& bufferFence, base::unique_fd* drawFence) EXCLUDES(mRenderingMutex) override; - // internal to RenderEngine EGLDisplay getEGLDisplay() const { return mEGLDisplay; } - EGLConfig getEGLConfig() const { return mEGLConfig; } // Creates an output image for rendering to EGLImageKHR createFramebufferImageIfNeeded(ANativeWindowBuffer* nativeBuffer, bool isProtected, bool useFramebufferCache); @@ -104,27 +90,6 @@ public: protected: Framebuffer* getFramebufferForDrawing() override; void dump(std::string& result) override; - void setViewportAndProjection(size_t vpw, size_t vph, Rect sourceCrop, - ui::Transform::orientation_flags rotation) override; - void setupLayerBlending(bool premultipliedAlpha, bool opaque, bool disableTexture, - const half4& color, float cornerRadius) override; - void setupLayerTexturing(const Texture& texture) override; - void setupLayerBlackedOut() override; - void setupFillWithColor(float r, float g, float b, float a) override; - void setColorTransform(const mat4& colorTransform) override; - void disableTexturing() override; - void disableBlending() override; - void setupCornerRadiusCropSize(float width, float height) override; - - // HDR and color management related functions and state - void setSourceY410BT2020(bool enable) override; - void setSourceDataSpace(ui::Dataspace source) override; - void setOutputDataSpace(ui::Dataspace dataspace) override; - void setDisplayMaxLuminance(const float maxLuminance) override; - - // drawing - void drawMesh(const Mesh& mesh) override; - size_t getMaxTextureSize() const override; size_t getMaxViewportDims() const override; @@ -136,12 +101,16 @@ private: GLES_VERSION_3_0 = 0x30000, }; + static EGLConfig chooseEglConfig(EGLDisplay display, int format, bool logConfig); static GlesVersion parseGlesVersion(const char* str); static EGLContext createEglContext(EGLDisplay display, EGLConfig config, EGLContext shareContext, bool useContextPriority, Protection protection); static EGLSurface createDummyEglPbufferSurface(EGLDisplay display, EGLConfig config, int hwcFormat, Protection protection); + std::unique_ptr createFramebuffer(); + std::unique_ptr createImage(); + void checkErrors() const; void setScissor(const Rect& region); void disableScissor(); bool waitSync(EGLSyncKHR sync, EGLint flags); @@ -165,6 +134,28 @@ private: // blending is an expensive operation, we want to turn off blending when it's not necessary. void handleRoundedCorners(const DisplaySettings& display, const LayerSettings& layer, const Mesh& mesh); + base::unique_fd flush(); + bool finish(); + bool waitFence(base::unique_fd fenceFd); + void clearWithColor(float red, float green, float blue, float alpha); + void fillRegionWithColor(const Region& region, float red, float green, float blue, float alpha); + void setupLayerBlending(bool premultipliedAlpha, bool opaque, bool disableTexture, + const half4& color, float cornerRadius); + void setupLayerTexturing(const Texture& texture); + void setupFillWithColor(float r, float g, float b, float a); + void setColorTransform(const mat4& colorTransform); + void disableTexturing(); + void disableBlending(); + void setupCornerRadiusCropSize(float width, float height); + + // HDR and color management related functions and state + void setSourceY410BT2020(bool enable); + void setSourceDataSpace(ui::Dataspace source); + void setOutputDataSpace(ui::Dataspace dataspace); + void setDisplayMaxLuminance(const float maxLuminance); + + // drawing + void drawMesh(const Mesh& mesh); EGLDisplay mEGLDisplay; EGLConfig mEGLConfig; diff --git a/libs/renderengine/include/renderengine/RenderEngine.h b/libs/renderengine/include/renderengine/RenderEngine.h index e7070041f2..8a798eefd1 100644 --- a/libs/renderengine/include/renderengine/RenderEngine.h +++ b/libs/renderengine/include/renderengine/RenderEngine.h @@ -77,10 +77,6 @@ public: // This interface, while still in use until a suitable replacement is built, // should be considered deprecated, minus some methods which still may be // used to support legacy behavior. - - virtual std::unique_ptr createFramebuffer() = 0; - virtual std::unique_ptr createImage() = 0; - virtual void primeCache() const = 0; // dump the extension strings. always call the base class. @@ -88,24 +84,6 @@ public: virtual bool useNativeFenceSync() const = 0; virtual bool useWaitSync() const = 0; - - virtual bool isCurrent() const = 0; - - // helpers - // flush submits RenderEngine command stream for execution and returns a - // native fence fd that is signaled when the execution has completed. It - // returns -1 on errors. - virtual base::unique_fd flush() = 0; - // finish waits until RenderEngine command stream has been executed. It - // returns false on errors. - virtual bool finish() = 0; - // waitFence inserts a wait on an external fence fd to RenderEngine - // command stream. It returns false on errors. - virtual bool waitFence(base::unique_fd fenceFd) = 0; - - virtual void clearWithColor(float red, float green, float blue, float alpha) = 0; - virtual void fillRegionWithColor(const Region& region, float red, float green, float blue, - float alpha) = 0; virtual void genTextures(size_t count, uint32_t* names) = 0; virtual void deleteTextures(size_t count, uint32_t const* names) = 0; virtual void bindExternalTextureImage(uint32_t texName, const Image& image) = 0; @@ -126,40 +104,6 @@ public: virtual status_t bindFrameBuffer(Framebuffer* framebuffer) = 0; virtual void unbindFrameBuffer(Framebuffer* framebuffer) = 0; - // set-up - virtual void checkErrors() const = 0; - virtual void setViewportAndProjection(size_t vpw, size_t vph, Rect sourceCrop, - ui::Transform::orientation_flags rotation) = 0; - virtual void setupLayerBlending(bool premultipliedAlpha, bool opaque, bool disableTexture, - const half4& color, float cornerRadius) = 0; - virtual void setupLayerTexturing(const Texture& texture) = 0; - virtual void setupLayerBlackedOut() = 0; - virtual void setupFillWithColor(float r, float g, float b, float a) = 0; - // Sets up the crop size for corner radius clipping. - // - // Having corner radius will force GPU composition on the layer and its children, drawing it - // with a special shader. The shader will receive the radius and the crop rectangle as input, - // modifying the opacity of the destination texture, multiplying it by a number between 0 and 1. - // We query Layer#getRoundedCornerState() to retrieve the radius as well as the rounded crop - // rectangle to figure out how to apply the radius for this layer. The crop rectangle will be - // in local layer coordinate space, so we have to take the layer transform into account when - // walking up the tree. - virtual void setupCornerRadiusCropSize(float width, float height) = 0; - - // Set a color transform matrix that is applied in linear space right before OETF. - virtual void setColorTransform(const mat4& /* colorTransform */) = 0; - virtual void disableTexturing() = 0; - virtual void disableBlending() = 0; - - // HDR and color management support - virtual void setSourceY410BT2020(bool enable) = 0; - virtual void setSourceDataSpace(ui::Dataspace source) = 0; - virtual void setOutputDataSpace(ui::Dataspace dataspace) = 0; - virtual void setDisplayMaxLuminance(const float maxLuminance) = 0; - - // drawing - virtual void drawMesh(const Mesh& mesh) = 0; - // queries virtual size_t getMaxTextureSize() const = 0; virtual size_t getMaxViewportDims() const = 0; diff --git a/libs/renderengine/include/renderengine/mock/RenderEngine.h b/libs/renderengine/include/renderengine/mock/RenderEngine.h index e33bcfd994..f099cd2455 100644 --- a/libs/renderengine/include/renderengine/mock/RenderEngine.h +++ b/libs/renderengine/include/renderengine/mock/RenderEngine.h @@ -34,20 +34,12 @@ public: RenderEngine(); ~RenderEngine() override; - MOCK_METHOD0(createFramebuffer, std::unique_ptr()); - MOCK_METHOD0(createImage, std::unique_ptr()); MOCK_METHOD0(getFramebufferForDrawing, Framebuffer*()); MOCK_CONST_METHOD0(primeCache, void()); MOCK_METHOD1(dump, void(std::string&)); MOCK_CONST_METHOD0(useNativeFenceSync, bool()); MOCK_CONST_METHOD0(useWaitSync, bool()); MOCK_CONST_METHOD0(isCurrent, bool()); - MOCK_METHOD0(flush, base::unique_fd()); - MOCK_METHOD0(finish, bool()); - MOCK_METHOD1(waitFence, bool(base::unique_fd*)); - bool waitFence(base::unique_fd fd) override { return waitFence(&fd); }; - MOCK_METHOD4(clearWithColor, void(float, float, float, float)); - MOCK_METHOD5(fillRegionWithColor, void(const Region&, float, float, float, float)); MOCK_METHOD2(genTextures, void(size_t, uint32_t*)); MOCK_METHOD2(deleteTextures, void(size_t, uint32_t const*)); MOCK_METHOD2(bindExternalTextureImage, void(uint32_t, const renderengine::Image&)); @@ -55,22 +47,6 @@ public: MOCK_METHOD3(bindExternalTextureBuffer, status_t(uint32_t, const sp&, const sp&)); MOCK_METHOD1(unbindExternalTextureBuffer, void(uint64_t)); - MOCK_CONST_METHOD0(checkErrors, void()); - MOCK_METHOD4(setViewportAndProjection, - void(size_t, size_t, Rect, ui::Transform::orientation_flags)); - MOCK_METHOD5(setupLayerBlending, void(bool, bool, bool, const half4&, float)); - MOCK_METHOD1(setupLayerTexturing, void(const Texture&)); - MOCK_METHOD0(setupLayerBlackedOut, void()); - MOCK_METHOD4(setupFillWithColor, void(float, float, float, float)); - MOCK_METHOD2(setupCornerRadiusCropSize, void(float, float)); - MOCK_METHOD1(setColorTransform, void(const mat4&)); - MOCK_METHOD1(setSaturationMatrix, void(const mat4&)); - MOCK_METHOD0(disableTexturing, void()); - MOCK_METHOD0(disableBlending, void()); - MOCK_METHOD1(setSourceY410BT2020, void(bool)); - MOCK_METHOD1(setSourceDataSpace, void(ui::Dataspace)); - MOCK_METHOD1(setOutputDataSpace, void(ui::Dataspace)); - MOCK_METHOD1(setDisplayMaxLuminance, void(const float)); MOCK_METHOD1(bindFrameBuffer, status_t(renderengine::Framebuffer*)); MOCK_METHOD1(unbindFrameBuffer, void(renderengine::Framebuffer*)); MOCK_METHOD1(drawMesh, void(const renderengine::Mesh&)); diff --git a/services/surfaceflinger/BufferLayerConsumer.cpp b/services/surfaceflinger/BufferLayerConsumer.cpp index 6709fb4b48..096cd1a9cc 100644 --- a/services/surfaceflinger/BufferLayerConsumer.cpp +++ b/services/surfaceflinger/BufferLayerConsumer.cpp @@ -419,30 +419,6 @@ std::shared_ptr BufferLayerConsumer::getCurrentFenceTime() const { return mCurrentFenceTime; } -status_t BufferLayerConsumer::doFenceWaitLocked() const { - if (mCurrentFence->isValid()) { - if (mRE.useWaitSync()) { - base::unique_fd fenceFd(mCurrentFence->dup()); - if (fenceFd == -1) { - BLC_LOGE("doFenceWait: error dup'ing fence fd: %d", errno); - return -errno; - } - if (!mRE.waitFence(std::move(fenceFd))) { - BLC_LOGE("doFenceWait: failed to wait on fence fd"); - return UNKNOWN_ERROR; - } - } else { - status_t err = mCurrentFence->waitForever("BufferLayerConsumer::doFenceWaitLocked"); - if (err != NO_ERROR) { - BLC_LOGE("doFenceWait: error waiting for fence: %d", err); - return err; - } - } - } - - return NO_ERROR; -} - void BufferLayerConsumer::freeBufferLocked(int slotIndex) { BLC_LOGV("freeBufferLocked: slotIndex=%d", slotIndex); std::lock_guard lock(mImagesMutex); diff --git a/services/surfaceflinger/BufferLayerConsumer.h b/services/surfaceflinger/BufferLayerConsumer.h index e3f6100c35..144686c83d 100644 --- a/services/surfaceflinger/BufferLayerConsumer.h +++ b/services/surfaceflinger/BufferLayerConsumer.h @@ -252,11 +252,6 @@ private: // mCurrentTextureImage must not be nullptr. void computeCurrentTransformMatrixLocked(); - // doFenceWaitLocked inserts a wait command into the RenderEngine command - // stream to ensure that it is safe for future RenderEngine commands to - // access the current texture buffer. - status_t doFenceWaitLocked() const; - // getCurrentCropLocked returns the cropping rectangle of the current buffer. Rect getCurrentCropLocked() const; diff --git a/services/surfaceflinger/CompositionEngine/include/compositionengine/RenderSurface.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/RenderSurface.h index e21128ca81..9bff73e950 100644 --- a/services/surfaceflinger/CompositionEngine/include/compositionengine/RenderSurface.h +++ b/services/surfaceflinger/CompositionEngine/include/compositionengine/RenderSurface.h @@ -83,10 +83,6 @@ public: // Called after the HWC calls are made to present the display virtual void onPresentDisplayCompleted() = 0; - // Called to set the viewport and projection state for rendering into this - // surface - virtual void setViewportAndProjection() = 0; - // Called after the surface has been rendering to signal the surface should // be made ready for displaying virtual void flip() = 0; diff --git a/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/RenderSurface.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/RenderSurface.h index 0f57315eb6..e4c9c80429 100644 --- a/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/RenderSurface.h +++ b/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/RenderSurface.h @@ -56,7 +56,6 @@ public: sp dequeueBuffer(base::unique_fd* bufferFence) override; void queueBuffer(base::unique_fd&& readyFence) override; void onPresentDisplayCompleted() override; - void setViewportAndProjection() override; void flip() override; // Debugging diff --git a/services/surfaceflinger/CompositionEngine/include/compositionengine/mock/RenderSurface.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/mock/RenderSurface.h index ca2299aa26..146a2eae64 100644 --- a/services/surfaceflinger/CompositionEngine/include/compositionengine/mock/RenderSurface.h +++ b/services/surfaceflinger/CompositionEngine/include/compositionengine/mock/RenderSurface.h @@ -41,7 +41,6 @@ public: MOCK_METHOD1(dequeueBuffer, sp(base::unique_fd*)); MOCK_METHOD1(queueBuffer, void(base::unique_fd&&)); MOCK_METHOD0(onPresentDisplayCompleted, void()); - MOCK_METHOD0(setViewportAndProjection, void()); MOCK_METHOD0(flip, void()); MOCK_CONST_METHOD1(dump, void(std::string& result)); MOCK_CONST_METHOD0(getPageFlipCount, std::uint32_t()); diff --git a/services/surfaceflinger/CompositionEngine/src/RenderSurface.cpp b/services/surfaceflinger/CompositionEngine/src/RenderSurface.cpp index 3fcd9d155d..8a91316e65 100644 --- a/services/surfaceflinger/CompositionEngine/src/RenderSurface.cpp +++ b/services/surfaceflinger/CompositionEngine/src/RenderSurface.cpp @@ -215,13 +215,6 @@ void RenderSurface::onPresentDisplayCompleted() { mDisplaySurface->onFrameCommitted(); } -void RenderSurface::setViewportAndProjection() { - auto& renderEngine = mCompositionEngine.getRenderEngine(); - Rect sourceCrop = Rect(mSize); - renderEngine.setViewportAndProjection(mSize.width, mSize.height, sourceCrop, - ui::Transform::ROT_0); -} - void RenderSurface::flip() { mPageFlipCount++; } diff --git a/services/surfaceflinger/CompositionEngine/tests/RenderSurfaceTest.cpp b/services/surfaceflinger/CompositionEngine/tests/RenderSurfaceTest.cpp index f75a4dcb85..87419ea6a8 100644 --- a/services/surfaceflinger/CompositionEngine/tests/RenderSurfaceTest.cpp +++ b/services/surfaceflinger/CompositionEngine/tests/RenderSurfaceTest.cpp @@ -363,20 +363,6 @@ TEST_F(RenderSurfaceTest, onPresentDisplayCompletedForwardsSignal) { mSurface.onPresentDisplayCompleted(); } -/* ------------------------------------------------------------------------ - * RenderSurface::setViewportAndProjection() - */ - -TEST_F(RenderSurfaceTest, setViewportAndProjectionAppliesChang) { - mSurface.setSizeForTest(ui::Size(100, 200)); - - EXPECT_CALL(mRenderEngine, - setViewportAndProjection(100, 200, Rect(100, 200), ui::Transform::ROT_0)) - .Times(1); - - mSurface.setViewportAndProjection(); -} - /* ------------------------------------------------------------------------ * RenderSurface::flip() */ diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp index b2df91d4ea..83ab5cfce2 100644 --- a/services/surfaceflinger/Layer.cpp +++ b/services/surfaceflinger/Layer.cpp @@ -619,32 +619,6 @@ bool Layer::addSyncPoint(const std::shared_ptr& point) { // local state // ---------------------------------------------------------------------------- -void Layer::computeGeometry(const RenderArea& renderArea, - renderengine::Mesh& mesh, - bool useIdentityTransform) const { - const ui::Transform renderAreaTransform(renderArea.getTransform()); - FloatRect win = getBounds(); - - vec2 lt = vec2(win.left, win.top); - vec2 lb = vec2(win.left, win.bottom); - vec2 rb = vec2(win.right, win.bottom); - vec2 rt = vec2(win.right, win.top); - - ui::Transform layerTransform = getTransform(); - if (!useIdentityTransform) { - lt = layerTransform.transform(lt); - lb = layerTransform.transform(lb); - rb = layerTransform.transform(rb); - rt = layerTransform.transform(rt); - } - - renderengine::Mesh::VertexArray position(mesh.getPositionArray()); - position[0] = renderAreaTransform.transform(lt); - position[1] = renderAreaTransform.transform(lb); - position[2] = renderAreaTransform.transform(rb); - position[3] = renderAreaTransform.transform(rt); -} - bool Layer::isSecure() const { const State& s(mDrawingState); return (s.flags & layer_state_t::eLayerSecure); diff --git a/services/surfaceflinger/Layer.h b/services/surfaceflinger/Layer.h index 6db6beb4f6..8a4d87f889 100644 --- a/services/surfaceflinger/Layer.h +++ b/services/surfaceflinger/Layer.h @@ -357,8 +357,6 @@ public: return getLayerStack() == layerStack && (!mPrimaryDisplayOnly || isPrimaryDisplay); } - void computeGeometry(const RenderArea& renderArea, renderengine::Mesh& mesh, - bool useIdentityTransform) const; FloatRect getBounds(const Region& activeTransparentRegion) const; FloatRect getBounds() const; diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp index e5896f9985..2cb2544448 100644 --- a/services/surfaceflinger/SurfaceFlinger.cpp +++ b/services/surfaceflinger/SurfaceFlinger.cpp @@ -3534,11 +3534,6 @@ bool SurfaceFlinger::doComposeSurfaces(const sp& displayDevice, return true; } -void SurfaceFlinger::drawWormhole(const Region& region) const { - auto& engine(getRenderEngine()); - engine.fillRegionWithColor(region, 0, 0, 0, 0); -} - status_t SurfaceFlinger::addClientLayer(const sp& client, const sp& handle, const sp& gbc, const sp& lbc, const sp& parentHandle, diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h index 6d4b2d755c..1a9dcdd2ef 100644 --- a/services/surfaceflinger/SurfaceFlinger.h +++ b/services/surfaceflinger/SurfaceFlinger.h @@ -790,7 +790,6 @@ private: void postFramebuffer(const sp& display); void postFrame(); - void drawWormhole(const Region& region) const; /* ------------------------------------------------------------------------ * Display management diff --git a/services/surfaceflinger/tests/unittests/CompositionTest.cpp b/services/surfaceflinger/tests/unittests/CompositionTest.cpp index 4f8ed1ae1c..e6211c488e 100644 --- a/services/surfaceflinger/tests/unittests/CompositionTest.cpp +++ b/services/surfaceflinger/tests/unittests/CompositionTest.cpp @@ -303,11 +303,6 @@ struct BaseDisplayVariant { EXPECT_CALL(*test->mComposer, getReleaseFences(HWC_DISPLAY, _, _)).Times(1); EXPECT_CALL(*test->mRenderEngine, useNativeFenceSync()).WillRepeatedly(Return(true)); - // TODO: remove once we verify that we can just grab the fence from the - // FramebufferSurface. - EXPECT_CALL(*test->mRenderEngine, flush()).WillRepeatedly(Invoke([]() { - return base::unique_fd(); - })); EXPECT_CALL(*test->mDisplaySurface, onFrameCommitted()).Times(1); EXPECT_CALL(*test->mDisplaySurface, advanceFrame()).Times(1); -- cgit v1.2.3-59-g8ed1b From f527548dd751bd62b1302cf357fdb4840bc115a9 Mon Sep 17 00:00:00 2001 From: Lloyd Pique Date: Tue, 29 Jan 2019 18:42:42 -0800 Subject: SF: Move/Refactor Layer::setPerFrameData Moves functionality out of ColorLayer, BufferLayer, BufferStateLayer and BufferQueueLayer related to setting the per-frame data. Instead each of the front-end classes now implements a minimal function to set the per-frame state into the LayerFECompositionState structure. compositionengine::OutputLayer now takes care of sending the state to the HWC, and in particular with detecting when client composition needs to be forced due to lack of HWC support (though the front-end can also set a flag to force client composition for a few things it knows about). SurfaceFlinger::calculateWorkingSet is also refactored to work with the changes made, and prepare it to be moved over to CompositionEngine. Test: atest libsurfaceflinger_unittest libcompositionengine_test Test: atest CtsColorModeTestCases Test: atest CtsDisplayTestCases Test: atest CtsGraphicsTestCases Test: atest CtsUiRenderingTestCases Test: atest CtsViewTestCases Test: atest android.media.cts.EncodeVirtualDisplayWithCompositionTest Bug: 121291683 Change-Id: I2cb0442f68ec5c5f65f5b4cb418dda4c42e5dc39 --- services/surfaceflinger/BufferLayer.cpp | 91 +------ services/surfaceflinger/BufferLayer.h | 8 +- services/surfaceflinger/BufferQueueLayer.cpp | 34 +-- services/surfaceflinger/BufferQueueLayer.h | 2 +- services/surfaceflinger/BufferStateLayer.cpp | 25 +- services/surfaceflinger/BufferStateLayer.h | 6 +- services/surfaceflinger/ColorLayer.cpp | 77 +----- services/surfaceflinger/ColorLayer.h | 6 +- .../compositionengine/DisplayColorProfile.h | 8 + .../compositionengine/LayerFECompositionState.h | 17 +- .../include/compositionengine/Output.h | 3 +- .../include/compositionengine/OutputLayer.h | 2 +- .../include/compositionengine/impl/Display.h | 2 +- .../compositionengine/impl/DisplayColorProfile.h | 2 + .../include/compositionengine/impl/Output.h | 2 +- .../impl/OutputCompositionState.h | 5 +- .../include/compositionengine/impl/OutputLayer.h | 19 +- .../impl/OutputLayerCompositionState.h | 6 +- .../compositionengine/mock/DisplayColorProfile.h | 3 + .../include/compositionengine/mock/Output.h | 11 +- .../include/compositionengine/mock/OutputLayer.h | 2 +- .../CompositionEngine/src/Display.cpp | 11 +- .../CompositionEngine/src/DisplayColorProfile.cpp | 40 +++- .../src/LayerCompositionState.cpp | 8 +- .../CompositionEngine/src/Output.cpp | 10 +- .../src/OutputCompositionState.cpp | 1 + .../CompositionEngine/src/OutputLayer.cpp | 266 +++++++++++++++++---- .../src/OutputLayerCompositionState.cpp | 1 + .../tests/DisplayColorProfileTest.cpp | 61 +++++ .../CompositionEngine/tests/DisplayTest.cpp | 27 ++- .../CompositionEngine/tests/OutputLayerTest.cpp | 214 ++++++++++++++++- .../CompositionEngine/tests/OutputTest.cpp | 16 +- services/surfaceflinger/ContainerLayer.cpp | 3 - services/surfaceflinger/ContainerLayer.h | 4 - services/surfaceflinger/Layer.cpp | 70 ++---- services/surfaceflinger/Layer.h | 16 +- services/surfaceflinger/SurfaceFlinger.cpp | 156 +++++------- .../tests/unittests/CompositionTest.cpp | 4 +- 38 files changed, 776 insertions(+), 463 deletions(-) (limited to 'services/surfaceflinger/Layer.cpp') diff --git a/services/surfaceflinger/BufferLayer.cpp b/services/surfaceflinger/BufferLayer.cpp index f51fbb45f6..c3b171847c 100644 --- a/services/surfaceflinger/BufferLayer.cpp +++ b/services/surfaceflinger/BufferLayer.cpp @@ -25,6 +25,7 @@ #include #include #include +#include #include #include #include @@ -253,90 +254,20 @@ bool BufferLayer::isHdrY410() const { mActiveBuffer->getPixelFormat() == HAL_PIXEL_FORMAT_RGBA_1010102); } -void BufferLayer::setPerFrameData(const sp& displayDevice, - const ui::Transform& transform, const Rect& viewport, - int32_t supportedPerFrameMetadata, - const ui::Dataspace targetDataspace) { - RETURN_IF_NO_HWC_LAYER(displayDevice); - - // 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)); - - const auto outputLayer = findOutputLayerForDisplay(displayDevice); - LOG_FATAL_IF(!outputLayer || !outputLayer->getState().hwc); - - auto& hwcLayer = (*outputLayer->getState().hwc).hwcLayer; - auto error = hwcLayer->setVisibleRegion(visible); - if (error != HWC2::Error::None) { - ALOGE("[%s] Failed to set visible region: %s (%d)", mName.string(), - to_string(error).c_str(), static_cast(error)); - visible.dump(LOG_TAG); - } - outputLayer->editState().visibleRegion = visible; - - auto& layerCompositionState = getCompositionLayer()->editState().frontEnd; - - error = hwcLayer->setSurfaceDamage(surfaceDamageRegion); - if (error != HWC2::Error::None) { - ALOGE("[%s] Failed to set surface damage: %s (%d)", mName.string(), - to_string(error).c_str(), static_cast(error)); - surfaceDamageRegion.dump(LOG_TAG); - } - layerCompositionState.surfaceDamage = surfaceDamageRegion; +void BufferLayer::latchPerFrameState( + compositionengine::LayerFECompositionState& compositionState) const { + Layer::latchPerFrameState(compositionState); // Sideband layers - if (layerCompositionState.sidebandStream.get()) { - setCompositionType(displayDevice, Hwc2::IComposerClient::Composition::SIDEBAND); - ALOGV("[%s] Requesting Sideband composition", mName.string()); - error = hwcLayer->setSidebandStream(layerCompositionState.sidebandStream->handle()); - if (error != HWC2::Error::None) { - ALOGE("[%s] Failed to set sideband stream %p: %s (%d)", mName.string(), - layerCompositionState.sidebandStream->handle(), to_string(error).c_str(), - static_cast(error)); - } - layerCompositionState.compositionType = Hwc2::IComposerClient::Composition::SIDEBAND; - return; - } - - // Device or Cursor layers - if (mPotentialCursor) { - ALOGV("[%s] Requesting Cursor composition", mName.string()); - setCompositionType(displayDevice, Hwc2::IComposerClient::Composition::CURSOR); + if (compositionState.sidebandStream.get()) { + compositionState.compositionType = Hwc2::IComposerClient::Composition::SIDEBAND; } else { - ALOGV("[%s] Requesting Device composition", mName.string()); - setCompositionType(displayDevice, Hwc2::IComposerClient::Composition::DEVICE); + // Normal buffer layers + compositionState.hdrMetadata = getDrawingHdrMetadata(); + compositionState.compositionType = mPotentialCursor + ? Hwc2::IComposerClient::Composition::CURSOR + : Hwc2::IComposerClient::Composition::DEVICE; } - - ui::Dataspace dataspace = isColorSpaceAgnostic() && targetDataspace != ui::Dataspace::UNKNOWN - ? targetDataspace - : mCurrentDataSpace; - error = hwcLayer->setDataspace(dataspace); - if (error != HWC2::Error::None) { - ALOGE("[%s] Failed to set dataspace %d: %s (%d)", mName.string(), dataspace, - to_string(error).c_str(), static_cast(error)); - } - - const HdrMetadata& metadata = getDrawingHdrMetadata(); - error = hwcLayer->setPerFrameMetadata(supportedPerFrameMetadata, metadata); - if (error != HWC2::Error::None && error != HWC2::Error::Unsupported) { - ALOGE("[%s] Failed to set hdrMetadata: %s (%d)", mName.string(), - to_string(error).c_str(), static_cast(error)); - } - - error = hwcLayer->setColorTransform(getColorTransform()); - if (error == HWC2::Error::Unsupported) { - // If per layer color transform is not supported, we use GPU composition. - setCompositionType(displayDevice, Hwc2::IComposerClient::Composition::CLIENT); - } else if (error != HWC2::Error::None) { - ALOGE("[%s] Failed to setColorTransform: %s (%d)", mName.string(), - to_string(error).c_str(), static_cast(error)); - } - layerCompositionState.dataspace = mCurrentDataSpace; - layerCompositionState.colorTransform = getColorTransform(); - layerCompositionState.hdrMetadata = metadata; - - setHwcLayerBuffer(displayDevice); } bool BufferLayer::onPreComposition(nsecs_t refreshStartTime) { diff --git a/services/surfaceflinger/BufferLayer.h b/services/surfaceflinger/BufferLayer.h index b679380b79..6bde7b45fd 100644 --- a/services/surfaceflinger/BufferLayer.h +++ b/services/surfaceflinger/BufferLayer.h @@ -82,10 +82,6 @@ public: bool isHdrY410() const override; - void setPerFrameData(const sp& display, const ui::Transform& transform, - const Rect& viewport, int32_t supportedPerFrameMetadata, - const ui::Dataspace targetDataspace) override; - bool onPreComposition(nsecs_t refreshStartTime) override; bool onPostComposition(const std::optional& displayId, const std::shared_ptr& glDoneFence, @@ -147,9 +143,9 @@ private: virtual status_t updateActiveBuffer() = 0; virtual status_t updateFrameNumber(nsecs_t latchTime) = 0; - virtual void setHwcLayerBuffer(const sp& displayDevice) = 0; - protected: + void latchPerFrameState(compositionengine::LayerFECompositionState& outState) const override; + // Loads the corresponding system property once per process static bool latchUnsignaledBuffers(); diff --git a/services/surfaceflinger/BufferQueueLayer.cpp b/services/surfaceflinger/BufferQueueLayer.cpp index d6853661a5..2c3da1aa21 100644 --- a/services/surfaceflinger/BufferQueueLayer.cpp +++ b/services/surfaceflinger/BufferQueueLayer.cpp @@ -377,7 +377,6 @@ status_t BufferQueueLayer::updateActiveBuffer() { mActiveBuffer = mConsumer->getCurrentBuffer(&mActiveBufferSlot, &mActiveBufferFence); auto& layerCompositionState = getCompositionLayer()->editState().frontEnd; layerCompositionState.buffer = mActiveBuffer; - layerCompositionState.bufferSlot = mActiveBufferSlot; if (mActiveBuffer == nullptr) { // this can only happen if the very first buffer was rejected. @@ -397,32 +396,17 @@ status_t BufferQueueLayer::updateFrameNumber(nsecs_t latchTime) { return NO_ERROR; } -void BufferQueueLayer::setHwcLayerBuffer(const sp& display) { - const auto outputLayer = findOutputLayerForDisplay(display); - LOG_FATAL_IF(!outputLayer); - LOG_FATAL_IF(!outputLayer->getState.hwc); - auto& hwcLayer = (*outputLayer->getState().hwc).hwcLayer; - - uint32_t hwcSlot = 0; - sp hwcBuffer; - - // INVALID_BUFFER_SLOT is used to identify BufferStateLayers. Default to 0 - // for BufferQueueLayers - int slot = (mActiveBufferSlot == BufferQueue::INVALID_BUFFER_SLOT) ? 0 : mActiveBufferSlot; - (*outputLayer->editState().hwc) - .hwcBufferCache.getHwcBuffer(slot, mActiveBuffer, &hwcSlot, &hwcBuffer); - - auto acquireFence = mConsumer->getCurrentFence(); - auto error = hwcLayer->setBuffer(hwcSlot, hwcBuffer, acquireFence); - if (error != HWC2::Error::None) { - ALOGE("[%s] Failed to set buffer %p: %s (%d)", mName.string(), mActiveBuffer->handle, - to_string(error).c_str(), static_cast(error)); +void BufferQueueLayer::latchPerFrameState( + compositionengine::LayerFECompositionState& compositionState) const { + BufferLayer::latchPerFrameState(compositionState); + if (compositionState.compositionType == Hwc2::IComposerClient::Composition::SIDEBAND) { + return; } - auto& layerCompositionState = getCompositionLayer()->editState().frontEnd; - layerCompositionState.bufferSlot = mActiveBufferSlot; - layerCompositionState.buffer = mActiveBuffer; - layerCompositionState.acquireFence = acquireFence; + compositionState.buffer = mActiveBuffer; + compositionState.bufferSlot = + (mActiveBufferSlot == BufferQueue::INVALID_BUFFER_SLOT) ? 0 : mActiveBufferSlot; + compositionState.acquireFence = mConsumer->getCurrentFence(); } // ----------------------------------------------------------------------- diff --git a/services/surfaceflinger/BufferQueueLayer.h b/services/surfaceflinger/BufferQueueLayer.h index 7def33ad78..9c537ad689 100644 --- a/services/surfaceflinger/BufferQueueLayer.h +++ b/services/surfaceflinger/BufferQueueLayer.h @@ -94,7 +94,7 @@ private: status_t updateActiveBuffer() override; status_t updateFrameNumber(nsecs_t latchTime) override; - void setHwcLayerBuffer(const sp& displayDevice) override; + void latchPerFrameState(compositionengine::LayerFECompositionState&) const override; // ----------------------------------------------------------------------- // Interface implementation for BufferLayerConsumer::ContentsChangedListener diff --git a/services/surfaceflinger/BufferStateLayer.cpp b/services/surfaceflinger/BufferStateLayer.cpp index 4b01301467..d0fa2e0088 100644 --- a/services/surfaceflinger/BufferStateLayer.cpp +++ b/services/surfaceflinger/BufferStateLayer.cpp @@ -569,7 +569,6 @@ status_t BufferStateLayer::updateActiveBuffer() { mActiveBufferFence = s.acquireFence; auto& layerCompositionState = getCompositionLayer()->editState().frontEnd; layerCompositionState.buffer = mActiveBuffer; - layerCompositionState.bufferSlot = 0; return NO_ERROR; } @@ -580,24 +579,18 @@ status_t BufferStateLayer::updateFrameNumber(nsecs_t /*latchTime*/) { return NO_ERROR; } -void BufferStateLayer::setHwcLayerBuffer(const sp& display) { - const auto outputLayer = findOutputLayerForDisplay(display); - LOG_FATAL_IF(!outputLayer || !outputLayer->getState().hwc); - auto& hwcInfo = *outputLayer->editState().hwc; - auto& hwcLayer = hwcInfo.hwcLayer; +void BufferStateLayer::latchPerFrameState( + compositionengine::LayerFECompositionState& compositionState) const { + BufferLayer::latchPerFrameState(compositionState); + if (compositionState.compositionType == Hwc2::IComposerClient::Composition::SIDEBAND) { + return; + } const State& s(getDrawingState()); - uint32_t hwcSlot; - sp buffer; - hwcInfo.hwcBufferCache.getHwcBuffer(mHwcSlotGenerator->getHwcCacheSlot(s.clientCacheId), - s.buffer, &hwcSlot, &buffer); - - auto error = hwcLayer->setBuffer(hwcSlot, buffer, s.acquireFence); - if (error != HWC2::Error::None) { - ALOGE("[%s] Failed to set buffer %p: %s (%d)", mName.string(), - s.buffer->handle, to_string(error).c_str(), static_cast(error)); - } + compositionState.buffer = s.buffer; + compositionState.bufferSlot = mHwcSlotGenerator->getHwcCacheSlot(s.clientCacheId); + compositionState.acquireFence = s.acquireFence; mFrameNumber++; } diff --git a/services/surfaceflinger/BufferStateLayer.h b/services/surfaceflinger/BufferStateLayer.h index db8ae0d337..75c855200b 100644 --- a/services/surfaceflinger/BufferStateLayer.h +++ b/services/surfaceflinger/BufferStateLayer.h @@ -136,7 +136,7 @@ private: status_t updateActiveBuffer() override; status_t updateFrameNumber(nsecs_t latchTime) override; - void setHwcLayerBuffer(const sp& display) override; + void latchPerFrameState(compositionengine::LayerFECompositionState&) const override; private: friend class SlotGenerationTest; @@ -151,11 +151,11 @@ private: std::atomic mSidebandStreamChanged{false}; - uint32_t mFrameNumber{0}; + mutable uint32_t mFrameNumber{0}; sp mPreviousReleaseFence; - bool mCurrentStateModified = false; + mutable bool mCurrentStateModified = false; bool mReleasePreviousBuffer = false; nsecs_t mCallbackHandleAcquireTime = -1; diff --git a/services/surfaceflinger/ColorLayer.cpp b/services/surfaceflinger/ColorLayer.cpp index fcc2d97ca3..f15957adf9 100644 --- a/services/surfaceflinger/ColorLayer.cpp +++ b/services/surfaceflinger/ColorLayer.cpp @@ -18,6 +18,8 @@ #undef LOG_TAG #define LOG_TAG "ColorLayer" +#include "ColorLayer.h" + #include #include #include @@ -26,6 +28,7 @@ #include #include #include +#include #include #include #include @@ -34,7 +37,6 @@ #include #include -#include "ColorLayer.h" #include "DisplayDevice.h" #include "SurfaceFlinger.h" @@ -91,75 +93,12 @@ bool ColorLayer::setDataspace(ui::Dataspace dataspace) { return true; } -void ColorLayer::setPerFrameData(const sp& display, - const ui::Transform& transform, const Rect& viewport, - int32_t /* supportedPerFrameMetadata */, - const ui::Dataspace targetDataspace) { - RETURN_IF_NO_HWC_LAYER(display); - - Region visible = transform.transform(visibleRegion.intersect(viewport)); - - const auto outputLayer = findOutputLayerForDisplay(display); - LOG_FATAL_IF(!outputLayer || !outputLayer->getState().hwc); - - auto& hwcLayer = (*outputLayer->getState().hwc).hwcLayer; - - auto error = hwcLayer->setVisibleRegion(visible); - if (error != HWC2::Error::None) { - ALOGE("[%s] Failed to set visible region: %s (%d)", mName.string(), - to_string(error).c_str(), static_cast(error)); - visible.dump(LOG_TAG); - } - outputLayer->editState().visibleRegion = visible; - - setCompositionType(display, Hwc2::IComposerClient::Composition::SOLID_COLOR); +void ColorLayer::latchPerFrameState( + compositionengine::LayerFECompositionState& compositionState) const { + Layer::latchPerFrameState(compositionState); - const ui::Dataspace dataspace = - isColorSpaceAgnostic() && targetDataspace != ui::Dataspace::UNKNOWN ? targetDataspace - : mCurrentDataSpace; - error = hwcLayer->setDataspace(dataspace); - if (error != HWC2::Error::None) { - ALOGE("[%s] Failed to set dataspace %d: %s (%d)", mName.string(), dataspace, - to_string(error).c_str(), static_cast(error)); - } - - auto& layerCompositionState = getCompositionLayer()->editState().frontEnd; - layerCompositionState.dataspace = mCurrentDataSpace; - - half4 color = getColor(); - error = hwcLayer->setColor({static_cast(std::round(255.0f * color.r)), - static_cast(std::round(255.0f * color.g)), - static_cast(std::round(255.0f * color.b)), 255}); - if (error != HWC2::Error::None) { - ALOGE("[%s] Failed to set color: %s (%d)", mName.string(), to_string(error).c_str(), - static_cast(error)); - } - layerCompositionState.color = {static_cast(std::round(255.0f * color.r)), - static_cast(std::round(255.0f * color.g)), - static_cast(std::round(255.0f * color.b)), 255}; - - // Clear out the transform, because it doesn't make sense absent a source buffer - error = hwcLayer->setTransform(HWC2::Transform::None); - if (error != HWC2::Error::None) { - ALOGE("[%s] Failed to clear transform: %s (%d)", mName.string(), to_string(error).c_str(), - static_cast(error)); - } - outputLayer->editState().bufferTransform = static_cast(0); - - error = hwcLayer->setColorTransform(getColorTransform()); - if (error != HWC2::Error::None) { - ALOGE("[%s] Failed to setColorTransform: %s (%d)", mName.string(), - to_string(error).c_str(), static_cast(error)); - } - layerCompositionState.colorTransform = getColorTransform(); - - error = hwcLayer->setSurfaceDamage(surfaceDamageRegion); - if (error != HWC2::Error::None) { - ALOGE("[%s] Failed to set surface damage: %s (%d)", mName.string(), - to_string(error).c_str(), static_cast(error)); - surfaceDamageRegion.dump(LOG_TAG); - } - layerCompositionState.surfaceDamage = surfaceDamageRegion; + compositionState.color = getColor(); + compositionState.compositionType = Hwc2::IComposerClient::Composition::SOLID_COLOR; } void ColorLayer::commitTransaction(const State& stateToCommit) { diff --git a/services/surfaceflinger/ColorLayer.h b/services/surfaceflinger/ColorLayer.h index 53d5b5b605..2483ff0bfb 100644 --- a/services/surfaceflinger/ColorLayer.h +++ b/services/surfaceflinger/ColorLayer.h @@ -37,10 +37,6 @@ public: bool setDataspace(ui::Dataspace dataspace) override; - void setPerFrameData(const sp& display, const ui::Transform& transform, - const Rect& viewport, int32_t supportedPerFrameMetadata, - const ui::Dataspace targetDataspace) override; - void commitTransaction(const State& stateToCommit) override; bool onPreComposition(nsecs_t /*refreshStartTime*/) override { return false; } @@ -52,6 +48,8 @@ protected: renderengine::LayerSettings& layer); private: + void latchPerFrameState(compositionengine::LayerFECompositionState&) const override; + std::shared_ptr mCompositionLayer; }; diff --git a/services/surfaceflinger/CompositionEngine/include/compositionengine/DisplayColorProfile.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/DisplayColorProfile.h index e2a0d42640..d93bfa30cc 100644 --- a/services/surfaceflinger/CompositionEngine/include/compositionengine/DisplayColorProfile.h +++ b/services/surfaceflinger/CompositionEngine/include/compositionengine/DisplayColorProfile.h @@ -17,6 +17,7 @@ #pragma once #include +#include #include @@ -75,6 +76,13 @@ public: // Gets the supported HDR capabilities for the profile virtual const HdrCapabilities& getHdrCapabilities() const = 0; + // Returns true if HWC for this profile supports the dataspace + virtual bool isDataspaceSupported(ui::Dataspace) const = 0; + + // Returns the target dataspace for picked color mode and dataspace + virtual ui::Dataspace getTargetDataspace(ui::ColorMode, ui::Dataspace, + ui::Dataspace colorSpaceAgnosticDataspace) const = 0; + // Debugging virtual void dump(std::string&) const = 0; }; diff --git a/services/surfaceflinger/CompositionEngine/include/compositionengine/LayerFECompositionState.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/LayerFECompositionState.h index e6ee078624..d96d58c1fa 100644 --- a/services/surfaceflinger/CompositionEngine/include/compositionengine/LayerFECompositionState.h +++ b/services/surfaceflinger/CompositionEngine/include/compositionengine/LayerFECompositionState.h @@ -36,9 +36,9 @@ namespace android::compositionengine { * Used by LayerFE::getCompositionState */ struct LayerFECompositionState { - // TODO(lpique): b/121291683 Remove this one we are sure we don't need the - // value recomputed / set every frame. - Region geomVisibleRegion; + // If set to true, forces client composition on all output layers until + // the next geometry change. + bool forceClientComposition{false}; /* * Geometry state @@ -56,6 +56,10 @@ struct LayerFECompositionState { Region geomActiveTransparentRegion; FloatRect geomLayerBounds; + // TODO(lpique): b/121291683 Remove this one we are sure we don't need the + // value recomputed / set every frame. + Region geomVisibleRegion; + /* * Presentation */ @@ -93,12 +97,16 @@ struct LayerFECompositionState { sp sidebandStream; // The color for this layer - Hwc2::IComposerClient::Color color; + half4 color; /* * Per-frame presentation state */ + // If true, this layer will use the dataspace chosen for the output and + // ignore the dataspace value just below + bool isColorspaceAgnostic{false}; + // The dataspace for this layer ui::Dataspace dataspace{ui::Dataspace::UNKNOWN}; @@ -107,6 +115,7 @@ struct LayerFECompositionState { // The color transform mat4 colorTransform; + bool colorTransformIsIdentity{true}; }; } // namespace android::compositionengine diff --git a/services/surfaceflinger/CompositionEngine/include/compositionengine/Output.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/Output.h index 54e6bd6af7..591382dcd9 100644 --- a/services/surfaceflinger/CompositionEngine/include/compositionengine/Output.h +++ b/services/surfaceflinger/CompositionEngine/include/compositionengine/Output.h @@ -71,7 +71,8 @@ public: virtual void setColorTransform(const mat4&) = 0; // Sets the output color mode - virtual void setColorMode(ui::ColorMode, ui::Dataspace, ui::RenderIntent) = 0; + virtual void setColorMode(ui::ColorMode, ui::Dataspace, ui::RenderIntent, + ui::Dataspace colorSpaceAgnosticDataspace) = 0; // Outputs a string with a state dump virtual void dump(std::string&) const = 0; diff --git a/services/surfaceflinger/CompositionEngine/include/compositionengine/OutputLayer.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/OutputLayer.h index cd63b57d86..d3a4e09ec7 100644 --- a/services/surfaceflinger/CompositionEngine/include/compositionengine/OutputLayer.h +++ b/services/surfaceflinger/CompositionEngine/include/compositionengine/OutputLayer.h @@ -71,7 +71,7 @@ public: // Writes the geometry state to the HWC, or does nothing if this layer does // not use the HWC. If includeGeometry is false, the geometry state can be // skipped. - virtual void writeStateToHWC(bool includeGeometry) const = 0; + virtual void writeStateToHWC(bool includeGeometry) = 0; // Debugging virtual void dump(std::string& result) const = 0; diff --git a/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/Display.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/Display.h index 0e20c43321..1265533449 100644 --- a/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/Display.h +++ b/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/Display.h @@ -39,7 +39,7 @@ public: // compositionengine::Output overrides void dump(std::string&) const override; void setColorTransform(const mat4&) override; - void setColorMode(ui::ColorMode, ui::Dataspace, ui::RenderIntent) override; + void setColorMode(ui::ColorMode, ui::Dataspace, ui::RenderIntent, ui::Dataspace) override; // compositionengine::Display overrides const std::optional& getId() const override; diff --git a/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/DisplayColorProfile.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/DisplayColorProfile.h index 49c2d2c0ea..e84a36ee67 100644 --- a/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/DisplayColorProfile.h +++ b/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/DisplayColorProfile.h @@ -54,6 +54,8 @@ public: bool hasDolbyVisionSupport() const override; const HdrCapabilities& getHdrCapabilities() const override; + bool isDataspaceSupported(ui::Dataspace) const override; + ui::Dataspace getTargetDataspace(ui::ColorMode, ui::Dataspace, ui::Dataspace) const override; void dump(std::string&) const override; diff --git a/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/Output.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/Output.h index b1d1f42f46..f245936744 100644 --- a/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/Output.h +++ b/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/Output.h @@ -45,7 +45,7 @@ public: void setLayerStackFilter(uint32_t layerStackId, bool isInternal) override; void setColorTransform(const mat4&) override; - void setColorMode(ui::ColorMode, ui::Dataspace, ui::RenderIntent) override; + void setColorMode(ui::ColorMode, ui::Dataspace, ui::RenderIntent, ui::Dataspace) override; void dump(std::string&) const override; diff --git a/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/OutputCompositionState.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/OutputCompositionState.h index 0c47eb5a01..45b8308f44 100644 --- a/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/OutputCompositionState.h +++ b/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/OutputCompositionState.h @@ -88,9 +88,12 @@ struct OutputCompositionState { // Current active render intent ui::RenderIntent renderIntent{ui::RenderIntent::COLORIMETRIC}; - // Current active dstaspace + // Current active dataspace ui::Dataspace dataspace{ui::Dataspace::UNKNOWN}; + // Current target dataspace + ui::Dataspace targetDataspace{ui::Dataspace::UNKNOWN}; + // Debugging void dump(std::string& result) const; }; diff --git a/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/OutputLayer.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/OutputLayer.h index 6a4818f10f..708f3a1b3e 100644 --- a/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/OutputLayer.h +++ b/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/OutputLayer.h @@ -26,7 +26,11 @@ #include "DisplayHardware/DisplayIdentification.h" -namespace android::compositionengine::impl { +namespace android::compositionengine { + +struct LayerFECompositionState; + +namespace impl { class OutputLayer : public compositionengine::OutputLayer { public: @@ -44,7 +48,7 @@ public: OutputLayerCompositionState& editState() override; void updateCompositionState(bool) override; - void writeStateToHWC(bool) const override; + void writeStateToHWC(bool) override; void dump(std::string& result) const override; @@ -54,6 +58,14 @@ public: private: Rect calculateInitialCrop() const; + void writeOutputDependentGeometryStateToHWC(HWC2::Layer*, Hwc2::IComposerClient::Composition); + void writeOutputIndependentGeometryStateToHWC(HWC2::Layer*, const LayerFECompositionState&); + void writeOutputDependentPerFrameStateToHWC(HWC2::Layer*); + void writeOutputIndependentPerFrameStateToHWC(HWC2::Layer*, const LayerFECompositionState&); + void writeSolidColorStateToHWC(HWC2::Layer*, const LayerFECompositionState&); + void writeSidebandStateToHWC(HWC2::Layer*, const LayerFECompositionState&); + void writeBufferStateToHWC(HWC2::Layer*, const LayerFECompositionState&); + void writeCompositionTypeToHWC(HWC2::Layer*, Hwc2::IComposerClient::Composition); const compositionengine::Output& mOutput; std::shared_ptr mLayer; @@ -66,4 +78,5 @@ std::unique_ptr createOutputLayer( const CompositionEngine&, std::optional, const compositionengine::Output&, std::shared_ptr, sp); -} // namespace android::compositionengine::impl +} // namespace impl +} // namespace android::compositionengine \ No newline at end of file diff --git a/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/OutputLayerCompositionState.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/OutputLayerCompositionState.h index b78e9e0076..de0f08ace8 100644 --- a/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/OutputLayerCompositionState.h +++ b/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/OutputLayerCompositionState.h @@ -23,6 +23,7 @@ #include #include #include +#include #include #include @@ -57,6 +58,9 @@ struct OutputLayerCompositionState { // The buffer transform to use for this layer o on this output. Hwc2::Transform bufferTransform{static_cast(0)}; + // The dataspace for this layer + ui::Dataspace dataspace{ui::Dataspace::UNKNOWN}; + // The Z order index of this layer on this output uint32_t z; @@ -70,7 +74,7 @@ struct OutputLayerCompositionState { // The HWC Layer backing this layer std::shared_ptr hwcLayer; - // The HWC composition type for this layer + // The most recently set HWC composition type for this layer Hwc2::IComposerClient::Composition hwcCompositionType{ Hwc2::IComposerClient::Composition::INVALID}; diff --git a/services/surfaceflinger/CompositionEngine/include/compositionengine/mock/DisplayColorProfile.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/mock/DisplayColorProfile.h index 8056c9d290..1aaebea295 100644 --- a/services/surfaceflinger/CompositionEngine/include/compositionengine/mock/DisplayColorProfile.h +++ b/services/surfaceflinger/CompositionEngine/include/compositionengine/mock/DisplayColorProfile.h @@ -42,6 +42,9 @@ public: MOCK_CONST_METHOD0(hasDolbyVisionSupport, bool()); MOCK_CONST_METHOD0(getHdrCapabilities, const HdrCapabilities&()); + MOCK_CONST_METHOD1(isDataspaceSupported, bool(ui::Dataspace)); + MOCK_CONST_METHOD3(getTargetDataspace, + ui::Dataspace(ui::ColorMode, ui::Dataspace, ui::Dataspace)); MOCK_CONST_METHOD1(dump, void(std::string&)); }; diff --git a/services/surfaceflinger/CompositionEngine/include/compositionengine/mock/Output.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/mock/Output.h index d0e7b195a8..cf82107194 100644 --- a/services/surfaceflinger/CompositionEngine/include/compositionengine/mock/Output.h +++ b/services/surfaceflinger/CompositionEngine/include/compositionengine/mock/Output.h @@ -41,17 +41,18 @@ public: MOCK_METHOD2(setLayerStackFilter, void(uint32_t, bool)); MOCK_METHOD1(setColorTransform, void(const mat4&)); - MOCK_METHOD3(setColorMode, void(ui::ColorMode, ui::Dataspace, ui::RenderIntent)); + MOCK_METHOD4(setColorMode, void(ui::ColorMode, ui::Dataspace, ui::RenderIntent, ui::Dataspace)); MOCK_CONST_METHOD1(dump, void(std::string&)); MOCK_CONST_METHOD0(getName, const std::string&()); MOCK_METHOD1(setName, void(const std::string&)); - MOCK_CONST_METHOD0(getDisplayColorProfile, DisplayColorProfile*()); - MOCK_METHOD1(setDisplayColorProfile, void(std::unique_ptr)); + MOCK_CONST_METHOD0(getDisplayColorProfile, compositionengine::DisplayColorProfile*()); + MOCK_METHOD1(setDisplayColorProfile, + void(std::unique_ptr)); - MOCK_CONST_METHOD0(getRenderSurface, RenderSurface*()); - MOCK_METHOD1(setRenderSurface, void(std::unique_ptr)); + MOCK_CONST_METHOD0(getRenderSurface, compositionengine::RenderSurface*()); + MOCK_METHOD1(setRenderSurface, void(std::unique_ptr)); MOCK_CONST_METHOD0(getState, const OutputCompositionState&()); MOCK_METHOD0(editState, OutputCompositionState&()); diff --git a/services/surfaceflinger/CompositionEngine/include/compositionengine/mock/OutputLayer.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/mock/OutputLayer.h index 29cd08a681..dab8b9da0e 100644 --- a/services/surfaceflinger/CompositionEngine/include/compositionengine/mock/OutputLayer.h +++ b/services/surfaceflinger/CompositionEngine/include/compositionengine/mock/OutputLayer.h @@ -39,7 +39,7 @@ public: MOCK_METHOD0(editState, impl::OutputLayerCompositionState&()); MOCK_METHOD1(updateCompositionState, void(bool)); - MOCK_CONST_METHOD1(writeStateToHWC, void(bool)); + MOCK_METHOD1(writeStateToHWC, void(bool)); MOCK_CONST_METHOD1(dump, void(std::string&)); }; diff --git a/services/surfaceflinger/CompositionEngine/src/Display.cpp b/services/surfaceflinger/CompositionEngine/src/Display.cpp index f9d70e3c91..8520d70c71 100644 --- a/services/surfaceflinger/CompositionEngine/src/Display.cpp +++ b/services/surfaceflinger/CompositionEngine/src/Display.cpp @@ -74,9 +74,14 @@ void Display::setColorTransform(const mat4& transform) { } void Display::setColorMode(ui::ColorMode mode, ui::Dataspace dataspace, - ui::RenderIntent renderIntent) { + ui::RenderIntent renderIntent, + ui::Dataspace colorSpaceAgnosticDataspace) { + ui::Dataspace targetDataspace = + getDisplayColorProfile()->getTargetDataspace(mode, dataspace, + colorSpaceAgnosticDataspace); + if (mode == getState().colorMode && dataspace == getState().dataspace && - renderIntent == getState().renderIntent) { + renderIntent == getState().renderIntent && targetDataspace == getState().targetDataspace) { return; } @@ -85,7 +90,7 @@ void Display::setColorMode(ui::ColorMode mode, ui::Dataspace dataspace, return; } - Output::setColorMode(mode, dataspace, renderIntent); + Output::setColorMode(mode, dataspace, renderIntent, colorSpaceAgnosticDataspace); auto& hwc = getCompositionEngine().getHwComposer(); hwc.setActiveColorMode(*mId, mode, renderIntent); diff --git a/services/surfaceflinger/CompositionEngine/src/DisplayColorProfile.cpp b/services/surfaceflinger/CompositionEngine/src/DisplayColorProfile.cpp index 130ab1dd54..5ef9097bff 100644 --- a/services/surfaceflinger/CompositionEngine/src/DisplayColorProfile.cpp +++ b/services/surfaceflinger/CompositionEngine/src/DisplayColorProfile.cpp @@ -64,6 +64,12 @@ const std::array sHdrRenderIntents = { RenderIntent::TONE_MAP_COLORIMETRIC, }; +// Returns true if the given colorMode is considered an HDR color mode +bool isHdrColorMode(const ColorMode colorMode) { + return std::any_of(std::begin(sHdrColorModes), std::end(sHdrColorModes), + [colorMode](ColorMode hdrColorMode) { return hdrColorMode == colorMode; }); +} + // map known color mode to dataspace Dataspace colorModeToDataspace(ColorMode mode) { switch (mode) { @@ -90,13 +96,7 @@ std::vector getColorModeCandidates(ColorMode mode) { candidates.push_back(mode); // check if mode is HDR - bool isHdr = false; - for (auto hdrMode : sHdrColorModes) { - if (hdrMode == mode) { - isHdr = true; - break; - } - } + bool isHdr = isHdrColorMode(mode); // add other HDR candidates when mode is HDR if (isHdr) { @@ -376,6 +376,32 @@ void DisplayColorProfile::getBestColorMode(Dataspace dataspace, RenderIntent int } } +bool DisplayColorProfile::isDataspaceSupported(Dataspace dataspace) const { + switch (dataspace) { + case Dataspace::BT2020_PQ: + case Dataspace::BT2020_ITU_PQ: + return hasHDR10Support(); + + case Dataspace::BT2020_HLG: + case Dataspace::BT2020_ITU_HLG: + return hasHLGSupport(); + + default: + return true; + } +} + +ui::Dataspace DisplayColorProfile::getTargetDataspace(ColorMode mode, Dataspace dataspace, + Dataspace colorSpaceAgnosticDataspace) const { + if (isHdrColorMode(mode)) { + return Dataspace::UNKNOWN; + } + if (colorSpaceAgnosticDataspace != ui::Dataspace::UNKNOWN) { + return colorSpaceAgnosticDataspace; + } + return dataspace; +} + void DisplayColorProfile::dump(std::string& out) const { out.append(" Composition Display Color State:"); diff --git a/services/surfaceflinger/CompositionEngine/src/LayerCompositionState.cpp b/services/surfaceflinger/CompositionEngine/src/LayerCompositionState.cpp index 40c4da97a8..37d6eaa2f2 100644 --- a/services/surfaceflinger/CompositionEngine/src/LayerCompositionState.cpp +++ b/services/surfaceflinger/CompositionEngine/src/LayerCompositionState.cpp @@ -24,9 +24,10 @@ namespace { using android::compositionengine::impl::dumpVal; -void dumpVal(std::string& out, const char* name, Hwc2::IComposerClient::Color value) { +void dumpVal(std::string& out, const char* name, half4 value) { using android::base::StringAppendF; - StringAppendF(&out, "%s=[%d %d %d] ", name, value.r, value.g, value.b); + StringAppendF(&out, "%s=[%f %f %f] ", name, static_cast(value.r), + static_cast(value.g), static_cast(value.b)); } void dumpFrontEnd(std::string& out, const LayerFECompositionState& state) { @@ -60,8 +61,8 @@ void dumpFrontEnd(std::string& out, const LayerFECompositionState& state) { dumpVal(out, "composition type", toString(state.compositionType), state.compositionType); out.append("\n buffer: "); + dumpVal(out, "bufferSlot", state.bufferSlot); dumpVal(out, "buffer", state.buffer.get()); - dumpVal(out, "slot", state.bufferSlot); out.append("\n "); dumpVal(out, "sideband stream", state.sidebandStream.get()); @@ -70,6 +71,7 @@ void dumpFrontEnd(std::string& out, const LayerFECompositionState& state) { dumpVal(out, "color", state.color); out.append("\n "); + dumpVal(out, "isColorspaceAgnostic", state.isColorspaceAgnostic); dumpVal(out, "dataspace", toString(state.dataspace), state.dataspace); dumpVal(out, "hdr metadata types", state.hdrMetadata.validTypes); dumpVal(out, "colorTransform", state.colorTransform); diff --git a/services/surfaceflinger/CompositionEngine/src/Output.cpp b/services/surfaceflinger/CompositionEngine/src/Output.cpp index 01b5781987..0725926be4 100644 --- a/services/surfaceflinger/CompositionEngine/src/Output.cpp +++ b/services/surfaceflinger/CompositionEngine/src/Output.cpp @@ -104,15 +104,21 @@ void Output::setColorTransform(const mat4& transform) { } void Output::setColorMode(ui::ColorMode mode, ui::Dataspace dataspace, - ui::RenderIntent renderIntent) { + ui::RenderIntent renderIntent, + ui::Dataspace colorSpaceAgnosticDataspace) { + ui::Dataspace targetDataspace = + getDisplayColorProfile()->getTargetDataspace(mode, dataspace, + colorSpaceAgnosticDataspace); + if (mState.colorMode == mode && mState.dataspace == dataspace && - mState.renderIntent == renderIntent) { + mState.renderIntent == renderIntent && mState.targetDataspace == targetDataspace) { return; } mState.colorMode = mode; mState.dataspace = dataspace; mState.renderIntent = renderIntent; + mState.targetDataspace = targetDataspace; mRenderSurface->setBufferDataspace(dataspace); diff --git a/services/surfaceflinger/CompositionEngine/src/OutputCompositionState.cpp b/services/surfaceflinger/CompositionEngine/src/OutputCompositionState.cpp index 9549054bd6..0b15dad6cd 100644 --- a/services/surfaceflinger/CompositionEngine/src/OutputCompositionState.cpp +++ b/services/surfaceflinger/CompositionEngine/src/OutputCompositionState.cpp @@ -44,6 +44,7 @@ void OutputCompositionState::dump(std::string& out) const { dumpVal(out, "renderIntent", toString(renderIntent), renderIntent); dumpVal(out, "dataspace", toString(dataspace), dataspace); dumpVal(out, "colorTransform", colorTransform); + dumpVal(out, "target dataspace", toString(targetDataspace), targetDataspace); out.append("\n"); } diff --git a/services/surfaceflinger/CompositionEngine/src/OutputLayer.cpp b/services/surfaceflinger/CompositionEngine/src/OutputLayer.cpp index 5ce72b0879..ebfc70489e 100644 --- a/services/surfaceflinger/CompositionEngine/src/OutputLayer.cpp +++ b/services/surfaceflinger/CompositionEngine/src/OutputLayer.cpp @@ -16,6 +16,7 @@ #include #include +#include #include #include #include @@ -290,20 +291,43 @@ uint32_t OutputLayer::calculateOutputRelativeBufferTransform() const { } // namespace impl void OutputLayer::updateCompositionState(bool includeGeometry) { + const auto& layerFEState = mLayer->getState().frontEnd; + const auto& outputState = mOutput.getState(); + const auto& profile = *mOutput.getDisplayColorProfile(); + if (includeGeometry) { mState.displayFrame = calculateOutputDisplayFrame(); mState.sourceCrop = calculateOutputSourceCrop(); mState.bufferTransform = static_cast(calculateOutputRelativeBufferTransform()); - if ((mLayer->getState().frontEnd.isSecure && !mOutput.getState().isSecure) || + if ((layerFEState.isSecure && !outputState.isSecure) || (mState.bufferTransform & ui::Transform::ROT_INVALID)) { mState.forceClientComposition = true; } } + + // Determine the output dependent dataspace for this layer. If it is + // colorspace agnostic, it just uses the dataspace chosen for the output to + // avoid the need for color conversion. + mState.dataspace = layerFEState.isColorspaceAgnostic && + outputState.targetDataspace != ui::Dataspace::UNKNOWN + ? outputState.targetDataspace + : layerFEState.dataspace; + + // TODO(lpique): b/121291683 Remove this one we are sure we don't need the + // value recomputed / set every frame. + mState.visibleRegion = outputState.transform.transform( + layerFEState.geomVisibleRegion.intersect(outputState.viewport)); + + // These are evaluated every frame as they can potentially change at any + // time. + if (layerFEState.forceClientComposition || !profile.isDataspaceSupported(mState.dataspace)) { + mState.forceClientComposition = true; + } } -void OutputLayer::writeStateToHWC(bool includeGeometry) const { +void OutputLayer::writeStateToHWC(bool includeGeometry) { // Skip doing this if there is no HWC interface if (!mState.hwc) { return; @@ -316,62 +340,212 @@ void OutputLayer::writeStateToHWC(bool includeGeometry) const { return; } + const auto& outputIndependentState = mLayer->getState().frontEnd; + auto requestedCompositionType = outputIndependentState.compositionType; + if (includeGeometry) { - // Output dependent state + writeOutputDependentGeometryStateToHWC(hwcLayer.get(), requestedCompositionType); + writeOutputIndependentGeometryStateToHWC(hwcLayer.get(), outputIndependentState); + } - if (auto error = hwcLayer->setDisplayFrame(mState.displayFrame); - error != HWC2::Error::None) { - ALOGE("[%s] Failed to set display frame [%d, %d, %d, %d]: %s (%d)", - mLayerFE->getDebugName(), mState.displayFrame.left, mState.displayFrame.top, - mState.displayFrame.right, mState.displayFrame.bottom, to_string(error).c_str(), - static_cast(error)); - } + writeOutputDependentPerFrameStateToHWC(hwcLayer.get()); + writeOutputIndependentPerFrameStateToHWC(hwcLayer.get(), outputIndependentState); - if (auto error = hwcLayer->setSourceCrop(mState.sourceCrop); error != HWC2::Error::None) { - ALOGE("[%s] Failed to set source crop [%.3f, %.3f, %.3f, %.3f]: " - "%s (%d)", - mLayerFE->getDebugName(), mState.sourceCrop.left, mState.sourceCrop.top, - mState.sourceCrop.right, mState.sourceCrop.bottom, to_string(error).c_str(), - static_cast(error)); - } + writeCompositionTypeToHWC(hwcLayer.get(), requestedCompositionType); +} + +void OutputLayer::writeOutputDependentGeometryStateToHWC( + HWC2::Layer* hwcLayer, Hwc2::IComposerClient::Composition requestedCompositionType) { + const auto& outputDependentState = getState(); + + if (auto error = hwcLayer->setDisplayFrame(outputDependentState.displayFrame); + error != HWC2::Error::None) { + ALOGE("[%s] Failed to set display frame [%d, %d, %d, %d]: %s (%d)", + mLayerFE->getDebugName(), outputDependentState.displayFrame.left, + outputDependentState.displayFrame.top, outputDependentState.displayFrame.right, + outputDependentState.displayFrame.bottom, to_string(error).c_str(), + static_cast(error)); + } + + if (auto error = hwcLayer->setSourceCrop(outputDependentState.sourceCrop); + error != HWC2::Error::None) { + ALOGE("[%s] Failed to set source crop [%.3f, %.3f, %.3f, %.3f]: " + "%s (%d)", + mLayerFE->getDebugName(), outputDependentState.sourceCrop.left, + outputDependentState.sourceCrop.top, outputDependentState.sourceCrop.right, + outputDependentState.sourceCrop.bottom, to_string(error).c_str(), + static_cast(error)); + } - if (auto error = hwcLayer->setZOrder(mState.z); error != HWC2::Error::None) { - ALOGE("[%s] Failed to set Z %u: %s (%d)", mLayerFE->getDebugName(), mState.z, + if (auto error = hwcLayer->setZOrder(outputDependentState.z); error != HWC2::Error::None) { + ALOGE("[%s] Failed to set Z %u: %s (%d)", mLayerFE->getDebugName(), outputDependentState.z, + to_string(error).c_str(), static_cast(error)); + } + + // Solid-color layers should always use an identity transform. + const auto bufferTransform = + requestedCompositionType != Hwc2::IComposerClient::Composition::SOLID_COLOR + ? outputDependentState.bufferTransform + : static_cast(0); + if (auto error = hwcLayer->setTransform(static_cast(bufferTransform)); + error != HWC2::Error::None) { + ALOGE("[%s] Failed to set transform %s: %s (%d)", mLayerFE->getDebugName(), + toString(outputDependentState.bufferTransform).c_str(), to_string(error).c_str(), + static_cast(error)); + } +} + +void OutputLayer::writeOutputIndependentGeometryStateToHWC( + HWC2::Layer* hwcLayer, const LayerFECompositionState& outputIndependentState) { + if (auto error = hwcLayer->setBlendMode( + static_cast(outputIndependentState.blendMode)); + error != HWC2::Error::None) { + ALOGE("[%s] Failed to set blend mode %s: %s (%d)", mLayerFE->getDebugName(), + toString(outputIndependentState.blendMode).c_str(), to_string(error).c_str(), + static_cast(error)); + } + + if (auto error = hwcLayer->setPlaneAlpha(outputIndependentState.alpha); + error != HWC2::Error::None) { + ALOGE("[%s] Failed to set plane alpha %.3f: %s (%d)", mLayerFE->getDebugName(), + outputIndependentState.alpha, to_string(error).c_str(), static_cast(error)); + } + + if (auto error = hwcLayer->setInfo(outputIndependentState.type, outputIndependentState.appId); + error != HWC2::Error::None) { + ALOGE("[%s] Failed to set info %s (%d)", mLayerFE->getDebugName(), to_string(error).c_str(), + static_cast(error)); + } +} + +void OutputLayer::writeOutputDependentPerFrameStateToHWC(HWC2::Layer* hwcLayer) { + const auto& outputDependentState = getState(); + + // TODO(lpique): b/121291683 visibleRegion is output-dependent geometry + // state and should not change every frame. + if (auto error = hwcLayer->setVisibleRegion(outputDependentState.visibleRegion); + error != HWC2::Error::None) { + ALOGE("[%s] Failed to set visible region: %s (%d)", mLayerFE->getDebugName(), + to_string(error).c_str(), static_cast(error)); + outputDependentState.visibleRegion.dump(LOG_TAG); + } + + if (auto error = hwcLayer->setDataspace(outputDependentState.dataspace); + error != HWC2::Error::None) { + ALOGE("[%s] Failed to set dataspace %d: %s (%d)", mLayerFE->getDebugName(), + outputDependentState.dataspace, to_string(error).c_str(), + static_cast(error)); + } +} + +void OutputLayer::writeOutputIndependentPerFrameStateToHWC( + HWC2::Layer* hwcLayer, const LayerFECompositionState& outputIndependentState) { + switch (auto error = hwcLayer->setColorTransform(outputIndependentState.colorTransform)) { + case HWC2::Error::None: + break; + case HWC2::Error::Unsupported: + editState().forceClientComposition = true; + break; + default: + ALOGE("[%s] Failed to set color transform: %s (%d)", mLayerFE->getDebugName(), to_string(error).c_str(), static_cast(error)); - } + } - if (auto error = - hwcLayer->setTransform(static_cast(mState.bufferTransform)); - error != HWC2::Error::None) { - ALOGE("[%s] Failed to set transform %s: %s (%d)", mLayerFE->getDebugName(), - toString(mState.bufferTransform).c_str(), to_string(error).c_str(), - static_cast(error)); - } + if (auto error = hwcLayer->setSurfaceDamage(outputIndependentState.surfaceDamage); + error != HWC2::Error::None) { + ALOGE("[%s] Failed to set surface damage: %s (%d)", mLayerFE->getDebugName(), + to_string(error).c_str(), static_cast(error)); + outputIndependentState.surfaceDamage.dump(LOG_TAG); + } - // Output independent state + // Content-specific per-frame state + switch (outputIndependentState.compositionType) { + case Hwc2::IComposerClient::Composition::SOLID_COLOR: + writeSolidColorStateToHWC(hwcLayer, outputIndependentState); + break; + case Hwc2::IComposerClient::Composition::SIDEBAND: + writeSidebandStateToHWC(hwcLayer, outputIndependentState); + break; + case Hwc2::IComposerClient::Composition::CURSOR: + case Hwc2::IComposerClient::Composition::DEVICE: + writeBufferStateToHWC(hwcLayer, outputIndependentState); + break; + case Hwc2::IComposerClient::Composition::INVALID: + case Hwc2::IComposerClient::Composition::CLIENT: + // Ignored + break; + } +} - const auto& outputIndependentState = mLayer->getState().frontEnd; +void OutputLayer::writeSolidColorStateToHWC(HWC2::Layer* hwcLayer, + const LayerFECompositionState& outputIndependentState) { + hwc_color_t color = {static_cast(std::round(255.0f * outputIndependentState.color.r)), + static_cast(std::round(255.0f * outputIndependentState.color.g)), + static_cast(std::round(255.0f * outputIndependentState.color.b)), + 255}; - if (auto error = hwcLayer->setBlendMode( - static_cast(outputIndependentState.blendMode)); - error != HWC2::Error::None) { - ALOGE("[%s] Failed to set blend mode %s: %s (%d)", mLayerFE->getDebugName(), - toString(outputIndependentState.blendMode).c_str(), to_string(error).c_str(), - static_cast(error)); - } + if (auto error = hwcLayer->setColor(color); error != HWC2::Error::None) { + ALOGE("[%s] Failed to set color: %s (%d)", mLayerFE->getDebugName(), + to_string(error).c_str(), static_cast(error)); + } +} - if (auto error = hwcLayer->setPlaneAlpha(outputIndependentState.alpha); - error != HWC2::Error::None) { - ALOGE("[%s] Failed to set plane alpha %.3f: %s (%d)", mLayerFE->getDebugName(), - outputIndependentState.alpha, to_string(error).c_str(), - static_cast(error)); - } +void OutputLayer::writeSidebandStateToHWC(HWC2::Layer* hwcLayer, + const LayerFECompositionState& outputIndependentState) { + if (auto error = hwcLayer->setSidebandStream(outputIndependentState.sidebandStream->handle()); + error != HWC2::Error::None) { + ALOGE("[%s] Failed to set sideband stream %p: %s (%d)", mLayerFE->getDebugName(), + outputIndependentState.sidebandStream->handle(), to_string(error).c_str(), + static_cast(error)); + } +} - if (auto error = - hwcLayer->setInfo(outputIndependentState.type, outputIndependentState.appId); +void OutputLayer::writeBufferStateToHWC(HWC2::Layer* hwcLayer, + const LayerFECompositionState& outputIndependentState) { + auto supportedPerFrameMetadata = + mOutput.getDisplayColorProfile()->getSupportedPerFrameMetadata(); + if (auto error = hwcLayer->setPerFrameMetadata(supportedPerFrameMetadata, + outputIndependentState.hdrMetadata); + error != HWC2::Error::None && error != HWC2::Error::Unsupported) { + ALOGE("[%s] Failed to set hdrMetadata: %s (%d)", mLayerFE->getDebugName(), + to_string(error).c_str(), static_cast(error)); + } + + uint32_t hwcSlot = 0; + sp hwcBuffer; + // We need access to the output-dependent state for the buffer cache there, + // though otherwise the buffer is not output-dependent. + editState().hwc->hwcBufferCache.getHwcBuffer(outputIndependentState.bufferSlot, + outputIndependentState.buffer, &hwcSlot, + &hwcBuffer); + + if (auto error = hwcLayer->setBuffer(hwcSlot, hwcBuffer, outputIndependentState.acquireFence); + error != HWC2::Error::None) { + ALOGE("[%s] Failed to set buffer %p: %s (%d)", mLayerFE->getDebugName(), + outputIndependentState.buffer->handle, to_string(error).c_str(), + static_cast(error)); + } +} + +void OutputLayer::writeCompositionTypeToHWC( + HWC2::Layer* hwcLayer, Hwc2::IComposerClient::Composition requestedCompositionType) { + auto& outputDependentState = editState(); + + // If we are forcing client composition, we need to tell the HWC + if (outputDependentState.forceClientComposition) { + requestedCompositionType = Hwc2::IComposerClient::Composition::CLIENT; + } + + // Set the requested composition type with the HWC whenever it changes + if (outputDependentState.hwc->hwcCompositionType != requestedCompositionType) { + outputDependentState.hwc->hwcCompositionType = requestedCompositionType; + + if (auto error = hwcLayer->setCompositionType( + static_cast(requestedCompositionType)); error != HWC2::Error::None) { - ALOGE("[%s] Failed to set info %s (%d)", mLayerFE->getDebugName(), - to_string(error).c_str(), static_cast(error)); + ALOGE("[%s] Failed to set composition type %s: %s (%d)", mLayerFE->getDebugName(), + toString(requestedCompositionType).c_str(), to_string(error).c_str(), + static_cast(error)); } } } diff --git a/services/surfaceflinger/CompositionEngine/src/OutputLayerCompositionState.cpp b/services/surfaceflinger/CompositionEngine/src/OutputLayerCompositionState.cpp index 861ea5757b..e320bee4e1 100644 --- a/services/surfaceflinger/CompositionEngine/src/OutputLayerCompositionState.cpp +++ b/services/surfaceflinger/CompositionEngine/src/OutputLayerCompositionState.cpp @@ -47,6 +47,7 @@ void OutputLayerCompositionState::dump(std::string& out) const { dumpVal(out, "displayFrame", displayFrame); dumpVal(out, "sourceCrop", sourceCrop); dumpVal(out, "bufferTransform", toString(bufferTransform), bufferTransform); + dumpVal(out, "dataspace", toString(dataspace), dataspace); dumpVal(out, "z-index", z); if (hwc) { diff --git a/services/surfaceflinger/CompositionEngine/tests/DisplayColorProfileTest.cpp b/services/surfaceflinger/CompositionEngine/tests/DisplayColorProfileTest.cpp index 9215884f58..c07dfbb38d 100644 --- a/services/surfaceflinger/CompositionEngine/tests/DisplayColorProfileTest.cpp +++ b/services/surfaceflinger/CompositionEngine/tests/DisplayColorProfileTest.cpp @@ -638,5 +638,66 @@ TEST_F(DisplayColorProfileTest, getBestColorModeReturnsExpectedModesWhenOutputHa checkGetBestColorMode(profile, expectedResults); } +/* + * RenderSurface::isDataspaceSupported() + */ + +TEST_F(DisplayColorProfileTest, isDataspaceSupportedWorksForProfileWithNoHdrSupport) { + auto profile = ProfileFactory::createProfileWithNoColorModeSupport(); + + EXPECT_TRUE(profile.isDataspaceSupported(Dataspace::UNKNOWN)); + EXPECT_TRUE(profile.isDataspaceSupported(Dataspace::V0_SRGB)); + EXPECT_FALSE(profile.isDataspaceSupported(Dataspace::BT2020_PQ)); + EXPECT_FALSE(profile.isDataspaceSupported(Dataspace::BT2020_ITU_PQ)); + EXPECT_FALSE(profile.isDataspaceSupported(Dataspace::BT2020_HLG)); + EXPECT_FALSE(profile.isDataspaceSupported(Dataspace::BT2020_ITU_HLG)); +} + +TEST_F(DisplayColorProfileTest, isDataspaceSupportedWorksForProfileWithHdr10Support) { + auto profile = ProfileFactory::createProfileWithSRGBColorModeSupport(); + + EXPECT_TRUE(profile.isDataspaceSupported(Dataspace::UNKNOWN)); + EXPECT_TRUE(profile.isDataspaceSupported(Dataspace::V0_SRGB)); + EXPECT_TRUE(profile.isDataspaceSupported(Dataspace::BT2020_PQ)); + EXPECT_TRUE(profile.isDataspaceSupported(Dataspace::BT2020_ITU_PQ)); + EXPECT_FALSE(profile.isDataspaceSupported(Dataspace::BT2020_HLG)); + EXPECT_FALSE(profile.isDataspaceSupported(Dataspace::BT2020_ITU_HLG)); +} + +TEST_F(DisplayColorProfileTest, isDataspaceSupportedWorksForProfileWithHlgSupport) { + auto profile = ProfileFactory::createProfileWithBT2100PQSupport(); + + EXPECT_TRUE(profile.isDataspaceSupported(Dataspace::UNKNOWN)); + EXPECT_TRUE(profile.isDataspaceSupported(Dataspace::V0_SRGB)); + EXPECT_FALSE(profile.isDataspaceSupported(Dataspace::BT2020_PQ)); + EXPECT_FALSE(profile.isDataspaceSupported(Dataspace::BT2020_ITU_PQ)); + EXPECT_TRUE(profile.isDataspaceSupported(Dataspace::BT2020_HLG)); + EXPECT_TRUE(profile.isDataspaceSupported(Dataspace::BT2020_ITU_HLG)); +} + +/* + * RenderSurface::getTargetDataspace() + */ + +TEST_F(DisplayColorProfileTest, getTargetDataspaceWorks) { + auto profile = ProfileFactory::createProfileWithNoColorModeSupport(); + + // For a non-HDR colorspace with no colorSpaceAgnosticDataspace override, + // the input dataspace should be returned. + EXPECT_EQ(Dataspace::DISPLAY_P3, + profile.getTargetDataspace(ColorMode::DISPLAY_P3, Dataspace::DISPLAY_P3, + Dataspace::UNKNOWN)); + + // If colorSpaceAgnosticDataspace is set, its value should be returned + EXPECT_EQ(Dataspace::V0_SRGB, + profile.getTargetDataspace(ColorMode::DISPLAY_P3, Dataspace::DISPLAY_P3, + Dataspace::V0_SRGB)); + + // For an HDR colorspace, Dataspace::UNKNOWN should be returned. + EXPECT_EQ(Dataspace::UNKNOWN, + profile.getTargetDataspace(ColorMode::BT2100_PQ, Dataspace::BT2020_PQ, + Dataspace::UNKNOWN)); +} + } // namespace } // namespace android::compositionengine diff --git a/services/surfaceflinger/CompositionEngine/tests/DisplayTest.cpp b/services/surfaceflinger/CompositionEngine/tests/DisplayTest.cpp index 33444a5df1..f0aea25566 100644 --- a/services/surfaceflinger/CompositionEngine/tests/DisplayTest.cpp +++ b/services/surfaceflinger/CompositionEngine/tests/DisplayTest.cpp @@ -22,6 +22,7 @@ #include #include #include +#include #include #include #include @@ -31,6 +32,7 @@ namespace android::compositionengine { namespace { +using testing::_; using testing::Return; using testing::ReturnRef; using testing::StrictMock; @@ -140,21 +142,27 @@ TEST_F(DisplayTest, setColorTransformSetsTransform) { TEST_F(DisplayTest, setColorModeSetsModeUnlessNoChange) { mock::RenderSurface* renderSurface = new StrictMock(); mDisplay.setRenderSurfaceForTest(std::unique_ptr(renderSurface)); + mock::DisplayColorProfile* colorProfile = new StrictMock(); + mDisplay.setDisplayColorProfileForTest(std::unique_ptr(colorProfile)); EXPECT_CALL(mCompositionEngine, getHwComposer()).WillRepeatedly(ReturnRef(mHwComposer)); + EXPECT_CALL(*colorProfile, getTargetDataspace(_, _, _)) + .WillRepeatedly(Return(ui::Dataspace::UNKNOWN)); // These values are expected to be the initial state. ASSERT_EQ(ui::ColorMode::NATIVE, mDisplay.getState().colorMode); ASSERT_EQ(ui::Dataspace::UNKNOWN, mDisplay.getState().dataspace); ASSERT_EQ(ui::RenderIntent::COLORIMETRIC, mDisplay.getState().renderIntent); + ASSERT_EQ(ui::Dataspace::UNKNOWN, mDisplay.getState().targetDataspace); - // Otherwise if the values are unchanged, nothing happens + // If the set values are unchanged, nothing happens mDisplay.setColorMode(ui::ColorMode::NATIVE, ui::Dataspace::UNKNOWN, - ui::RenderIntent::COLORIMETRIC); + ui::RenderIntent::COLORIMETRIC, ui::Dataspace::UNKNOWN); EXPECT_EQ(ui::ColorMode::NATIVE, mDisplay.getState().colorMode); EXPECT_EQ(ui::Dataspace::UNKNOWN, mDisplay.getState().dataspace); EXPECT_EQ(ui::RenderIntent::COLORIMETRIC, mDisplay.getState().renderIntent); + EXPECT_EQ(ui::Dataspace::UNKNOWN, mDisplay.getState().targetDataspace); // Otherwise if the values are different, updates happen EXPECT_CALL(*renderSurface, setBufferDataspace(ui::Dataspace::DISPLAY_P3)).Times(1); @@ -164,23 +172,34 @@ TEST_F(DisplayTest, setColorModeSetsModeUnlessNoChange) { .Times(1); mDisplay.setColorMode(ui::ColorMode::DISPLAY_P3, ui::Dataspace::DISPLAY_P3, - ui::RenderIntent::TONE_MAP_COLORIMETRIC); + ui::RenderIntent::TONE_MAP_COLORIMETRIC, ui::Dataspace::UNKNOWN); EXPECT_EQ(ui::ColorMode::DISPLAY_P3, mDisplay.getState().colorMode); EXPECT_EQ(ui::Dataspace::DISPLAY_P3, mDisplay.getState().dataspace); EXPECT_EQ(ui::RenderIntent::TONE_MAP_COLORIMETRIC, mDisplay.getState().renderIntent); + EXPECT_EQ(ui::Dataspace::UNKNOWN, mDisplay.getState().targetDataspace); } TEST_F(DisplayTest, setColorModeDoesNothingForVirtualDisplay) { impl::Display virtualDisplay{mCompositionEngine, DisplayCreationArgs{false, true, DEFAULT_DISPLAY_ID}}; + mock::DisplayColorProfile* colorProfile = new StrictMock(); + virtualDisplay.setDisplayColorProfileForTest( + std::unique_ptr(colorProfile)); + + EXPECT_CALL(*colorProfile, + getTargetDataspace(ui::ColorMode::DISPLAY_P3, ui::Dataspace::DISPLAY_P3, + ui::Dataspace::UNKNOWN)) + .WillOnce(Return(ui::Dataspace::UNKNOWN)); + virtualDisplay.setColorMode(ui::ColorMode::DISPLAY_P3, ui::Dataspace::DISPLAY_P3, - ui::RenderIntent::TONE_MAP_COLORIMETRIC); + ui::RenderIntent::TONE_MAP_COLORIMETRIC, ui::Dataspace::UNKNOWN); EXPECT_EQ(ui::ColorMode::NATIVE, virtualDisplay.getState().colorMode); EXPECT_EQ(ui::Dataspace::UNKNOWN, virtualDisplay.getState().dataspace); EXPECT_EQ(ui::RenderIntent::COLORIMETRIC, virtualDisplay.getState().renderIntent); + EXPECT_EQ(ui::Dataspace::UNKNOWN, mDisplay.getState().targetDataspace); } /* ------------------------------------------------------------------------ diff --git a/services/surfaceflinger/CompositionEngine/tests/OutputLayerTest.cpp b/services/surfaceflinger/CompositionEngine/tests/OutputLayerTest.cpp index ae906cd525..7b9528be9c 100644 --- a/services/surfaceflinger/CompositionEngine/tests/OutputLayerTest.cpp +++ b/services/surfaceflinger/CompositionEngine/tests/OutputLayerTest.cpp @@ -16,6 +16,7 @@ #include #include +#include #include #include #include @@ -25,6 +26,7 @@ #include "MockHWC2.h" #include "MockHWComposer.h" #include "RectMatcher.h" +#include "RegionMatcher.h" namespace android::compositionengine { namespace { @@ -45,6 +47,15 @@ constexpr auto TR_ROT_270 = TR_ROT_90 | TR_ROT_180; const std::string kOutputName{"Test Output"}; +MATCHER_P(ColorEq, expected, "") { + *result_listener << "Colors are not equal\n"; + *result_listener << "expected " << expected.r << " " << expected.g << " " << expected.b << " " + << expected.a << "\n"; + *result_listener << "actual " << arg.r << " " << arg.g << " " << arg.b << " " << arg.a << "\n"; + + return expected.r == arg.r && expected.g == arg.g && expected.b == arg.b && expected.a == arg.a; +} + class OutputLayerTest : public testing::Test { public: OutputLayerTest() { @@ -429,6 +440,9 @@ public: OutputLayerUpdateCompositionStateTest() { EXPECT_CALL(*mLayer, getState()).WillRepeatedly(ReturnRef(mLayerState)); EXPECT_CALL(mOutput, getState()).WillRepeatedly(ReturnRef(mOutputState)); + EXPECT_CALL(mOutput, getDisplayColorProfile()) + .WillRepeatedly(Return(&mDisplayColorProfile)); + EXPECT_CALL(mDisplayColorProfile, isDataspaceSupported(_)).WillRepeatedly(Return(true)); } ~OutputLayerUpdateCompositionStateTest() = default; @@ -453,6 +467,7 @@ public: using OutputLayer = OutputLayerPartialMockForUpdateCompositionState; StrictMock mOutputLayer{mOutput, mLayer, mLayerFE}; + StrictMock mDisplayColorProfile; }; TEST_F(OutputLayerUpdateCompositionStateTest, setsStateNormally) { @@ -498,12 +513,50 @@ TEST_F(OutputLayerUpdateCompositionStateTest, EXPECT_EQ(true, mOutputLayer.getState().forceClientComposition); } +TEST_F(OutputLayerUpdateCompositionStateTest, setsOutputLayerColorspaceCorrectly) { + mLayerState.frontEnd.dataspace = ui::Dataspace::DISPLAY_P3; + mOutputState.targetDataspace = ui::Dataspace::V0_SCRGB; + + // If the layer is not colorspace agnostic, the output layer dataspace + // should use the layers requested colorspace. + mLayerState.frontEnd.isColorspaceAgnostic = false; + + mOutputLayer.updateCompositionState(false); + + EXPECT_EQ(ui::Dataspace::DISPLAY_P3, mOutputLayer.getState().dataspace); + + // If the layer is colorspace agnostic, the output layer dataspace + // should use the colorspace chosen for the whole output. + mLayerState.frontEnd.isColorspaceAgnostic = true; + + mOutputLayer.updateCompositionState(false); + + EXPECT_EQ(ui::Dataspace::V0_SCRGB, mOutputLayer.getState().dataspace); +} + TEST_F(OutputLayerUpdateCompositionStateTest, doesNotRecomputeGeometryIfNotRequested) { mOutputLayer.updateCompositionState(false); EXPECT_EQ(false, mOutputLayer.getState().forceClientComposition); } +TEST_F(OutputLayerUpdateCompositionStateTest, clientCompositionForcedFromFrontEndFlagAtAnyTime) { + mLayerState.frontEnd.forceClientComposition = true; + + mOutputLayer.updateCompositionState(false); + + EXPECT_EQ(true, mOutputLayer.getState().forceClientComposition); +} + +TEST_F(OutputLayerUpdateCompositionStateTest, + clientCompositionForcedFromUnsupportedDataspaceAtAnyTime) { + EXPECT_CALL(mDisplayColorProfile, isDataspaceSupported(_)).WillRepeatedly(Return(false)); + + mOutputLayer.updateCompositionState(false); + + EXPECT_EQ(true, mOutputLayer.getState().forceClientComposition); +} + /* * OutputLayer::writeStateToHWC() */ @@ -518,8 +571,19 @@ struct OutputLayerWriteStateToHWCTest : public OutputLayerTest { static constexpr float kAlpha = 51.f; static constexpr uint32_t kType = 61u; static constexpr uint32_t kAppId = 62u; + static constexpr ui::Dataspace kDataspace = static_cast(71); + static constexpr int kSupportedPerFrameMetadata = 101; + static constexpr int kExpectedHwcSlot = 0; + static const half4 kColor; static const Rect kDisplayFrame; + static const Region kVisibleRegion; + static const mat4 kColorTransform; + static const Region kSurfaceDamage; + static const HdrMetadata kHdrMetadata; + static native_handle_t* kSidebandStreamHandle; + static const sp kBuffer; + static const sp kFence; OutputLayerWriteStateToHWCTest() { auto& outputLayerState = mOutputLayer.editState(); @@ -529,13 +593,31 @@ struct OutputLayerWriteStateToHWCTest : public OutputLayerTest { outputLayerState.sourceCrop = kSourceCrop; outputLayerState.z = kZOrder; outputLayerState.bufferTransform = static_cast(kBufferTransform); + outputLayerState.visibleRegion = kVisibleRegion; + outputLayerState.dataspace = kDataspace; mLayerState.frontEnd.blendMode = kBlendMode; mLayerState.frontEnd.alpha = kAlpha; mLayerState.frontEnd.type = kType; mLayerState.frontEnd.appId = kAppId; + mLayerState.frontEnd.colorTransform = kColorTransform; + mLayerState.frontEnd.color = kColor; + mLayerState.frontEnd.surfaceDamage = kSurfaceDamage; + mLayerState.frontEnd.hdrMetadata = kHdrMetadata; + mLayerState.frontEnd.sidebandStream = NativeHandle::create(kSidebandStreamHandle, false); + mLayerState.frontEnd.buffer = kBuffer; + mLayerState.frontEnd.bufferSlot = BufferQueue::INVALID_BUFFER_SLOT; + mLayerState.frontEnd.acquireFence = kFence; + + EXPECT_CALL(mOutput, getDisplayColorProfile()) + .WillRepeatedly(Return(&mDisplayColorProfile)); + EXPECT_CALL(mDisplayColorProfile, getSupportedPerFrameMetadata()) + .WillRepeatedly(Return(kSupportedPerFrameMetadata)); } + // Some tests may need to simulate unsupported HWC calls + enum class SimulateUnsupported { None, ColorTransform }; + void expectGeometryCommonCalls() { EXPECT_CALL(*mHwcLayer, setDisplayFrame(kDisplayFrame)).WillOnce(Return(kError)); EXPECT_CALL(*mHwcLayer, setSourceCrop(kSourceCrop)).WillOnce(Return(kError)); @@ -549,10 +631,62 @@ struct OutputLayerWriteStateToHWCTest : public OutputLayerTest { EXPECT_CALL(*mHwcLayer, setInfo(kType, kAppId)).WillOnce(Return(kError)); } + void expectPerFrameCommonCalls(SimulateUnsupported unsupported = SimulateUnsupported::None) { + EXPECT_CALL(*mHwcLayer, setVisibleRegion(RegionEq(kVisibleRegion))) + .WillOnce(Return(kError)); + EXPECT_CALL(*mHwcLayer, setDataspace(kDataspace)).WillOnce(Return(kError)); + EXPECT_CALL(*mHwcLayer, setColorTransform(kColorTransform)) + .WillOnce(Return(unsupported == SimulateUnsupported::ColorTransform + ? HWC2::Error::Unsupported + : HWC2::Error::None)); + EXPECT_CALL(*mHwcLayer, setSurfaceDamage(RegionEq(kSurfaceDamage))) + .WillOnce(Return(kError)); + } + + void expectSetCompositionTypeCall(Hwc2::IComposerClient::Composition compositionType) { + EXPECT_CALL(*mHwcLayer, setCompositionType(static_cast(compositionType))) + .WillOnce(Return(kError)); + } + + void expectNoSetCompositionTypeCall() { + EXPECT_CALL(*mHwcLayer, setCompositionType(_)).Times(0); + } + + void expectSetColorCall() { + hwc_color_t color = {static_cast(std::round(kColor.r * 255)), + static_cast(std::round(kColor.g * 255)), + static_cast(std::round(kColor.b * 255)), 255}; + + EXPECT_CALL(*mHwcLayer, setColor(ColorEq(color))).WillOnce(Return(kError)); + } + + void expectSetSidebandHandleCall() { + EXPECT_CALL(*mHwcLayer, setSidebandStream(kSidebandStreamHandle)); + } + + void expectSetHdrMetadataAndBufferCalls() { + EXPECT_CALL(*mHwcLayer, setPerFrameMetadata(kSupportedPerFrameMetadata, kHdrMetadata)); + EXPECT_CALL(*mHwcLayer, setBuffer(kExpectedHwcSlot, kBuffer, kFence)); + } + std::shared_ptr mHwcLayer{std::make_shared>()}; + StrictMock mDisplayColorProfile; }; +const half4 OutputLayerWriteStateToHWCTest::kColor{81.f / 255.f, 82.f / 255.f, 83.f / 255.f, + 84.f / 255.f}; const Rect OutputLayerWriteStateToHWCTest::kDisplayFrame{1001, 1002, 1003, 10044}; +const Region OutputLayerWriteStateToHWCTest::kVisibleRegion{Rect{1005, 1006, 1007, 1008}}; +const mat4 OutputLayerWriteStateToHWCTest::kColorTransform{ + 1009, 1010, 1011, 1012, 1013, 1014, 1015, 1016, + 1017, 1018, 1019, 1020, 1021, 1022, 1023, 1024, +}; +const Region OutputLayerWriteStateToHWCTest::kSurfaceDamage{Rect{1025, 1026, 1027, 1028}}; +const HdrMetadata OutputLayerWriteStateToHWCTest::kHdrMetadata{{/* LightFlattenable */}, 1029}; +native_handle_t* OutputLayerWriteStateToHWCTest::kSidebandStreamHandle = + reinterpret_cast(1031); +const sp OutputLayerWriteStateToHWCTest::kBuffer; +const sp OutputLayerWriteStateToHWCTest::kFence; TEST_F(OutputLayerWriteStateToHWCTest, doesNothingIfNoHWCState) { mOutputLayer.editState().hwc.reset(); @@ -566,11 +700,89 @@ TEST_F(OutputLayerWriteStateToHWCTest, doesNothingIfNoHWCLayer) { mOutputLayer.writeStateToHWC(true); } -TEST_F(OutputLayerWriteStateToHWCTest, canSetsAllState) { +TEST_F(OutputLayerWriteStateToHWCTest, canSetAllState) { expectGeometryCommonCalls(); + expectPerFrameCommonCalls(); + + expectNoSetCompositionTypeCall(); mOutputLayer.writeStateToHWC(true); } +TEST_F(OutputLayerWriteStateToHWCTest, canSetPerFrameStateForSolidColor) { + mLayerState.frontEnd.compositionType = Hwc2::IComposerClient::Composition::SOLID_COLOR; + + expectPerFrameCommonCalls(); + expectSetColorCall(); + expectSetCompositionTypeCall(Hwc2::IComposerClient::Composition::SOLID_COLOR); + + mOutputLayer.writeStateToHWC(false); +} + +TEST_F(OutputLayerWriteStateToHWCTest, canSetPerFrameStateForSideband) { + mLayerState.frontEnd.compositionType = Hwc2::IComposerClient::Composition::SIDEBAND; + + expectPerFrameCommonCalls(); + expectSetSidebandHandleCall(); + expectSetCompositionTypeCall(Hwc2::IComposerClient::Composition::SIDEBAND); + + mOutputLayer.writeStateToHWC(false); +} + +TEST_F(OutputLayerWriteStateToHWCTest, canSetPerFrameStateForCursor) { + mLayerState.frontEnd.compositionType = Hwc2::IComposerClient::Composition::CURSOR; + + expectPerFrameCommonCalls(); + expectSetHdrMetadataAndBufferCalls(); + expectSetCompositionTypeCall(Hwc2::IComposerClient::Composition::CURSOR); + + mOutputLayer.writeStateToHWC(false); +} + +TEST_F(OutputLayerWriteStateToHWCTest, canSetPerFrameStateForDevice) { + mLayerState.frontEnd.compositionType = Hwc2::IComposerClient::Composition::DEVICE; + + expectPerFrameCommonCalls(); + expectSetHdrMetadataAndBufferCalls(); + expectSetCompositionTypeCall(Hwc2::IComposerClient::Composition::DEVICE); + + mOutputLayer.writeStateToHWC(false); +} + +TEST_F(OutputLayerWriteStateToHWCTest, compositionTypeIsNotSetIfUnchanged) { + (*mOutputLayer.editState().hwc).hwcCompositionType = + Hwc2::IComposerClient::Composition::SOLID_COLOR; + + mLayerState.frontEnd.compositionType = Hwc2::IComposerClient::Composition::SOLID_COLOR; + + expectPerFrameCommonCalls(); + expectSetColorCall(); + expectNoSetCompositionTypeCall(); + + mOutputLayer.writeStateToHWC(false); +} + +TEST_F(OutputLayerWriteStateToHWCTest, compositionTypeIsSetToClientIfColorTransformNotSupported) { + mLayerState.frontEnd.compositionType = Hwc2::IComposerClient::Composition::SOLID_COLOR; + + expectPerFrameCommonCalls(SimulateUnsupported::ColorTransform); + expectSetColorCall(); + expectSetCompositionTypeCall(Hwc2::IComposerClient::Composition::CLIENT); + + mOutputLayer.writeStateToHWC(false); +} + +TEST_F(OutputLayerWriteStateToHWCTest, compositionTypeIsSetToClientIfClientCompositionForced) { + mOutputLayer.editState().forceClientComposition = true; + + mLayerState.frontEnd.compositionType = Hwc2::IComposerClient::Composition::SOLID_COLOR; + + expectPerFrameCommonCalls(); + expectSetColorCall(); + expectSetCompositionTypeCall(Hwc2::IComposerClient::Composition::CLIENT); + + mOutputLayer.writeStateToHWC(false); +} + } // namespace } // namespace android::compositionengine diff --git a/services/surfaceflinger/CompositionEngine/tests/OutputTest.cpp b/services/surfaceflinger/CompositionEngine/tests/OutputTest.cpp index fee0c11e25..6f087d9e54 100644 --- a/services/surfaceflinger/CompositionEngine/tests/OutputTest.cpp +++ b/services/surfaceflinger/CompositionEngine/tests/OutputTest.cpp @@ -205,24 +205,36 @@ TEST_F(OutputTest, setColorTransformSetsTransform) { */ TEST_F(OutputTest, setColorModeSetsStateAndDirtiesOutputIfChanged) { + EXPECT_CALL(*mDisplayColorProfile, + getTargetDataspace(ui::ColorMode::DISPLAY_P3, ui::Dataspace::DISPLAY_P3, + ui::Dataspace::UNKNOWN)) + .WillOnce(Return(ui::Dataspace::UNKNOWN)); EXPECT_CALL(*mRenderSurface, setBufferDataspace(ui::Dataspace::DISPLAY_P3)).Times(1); mOutput.setColorMode(ui::ColorMode::DISPLAY_P3, ui::Dataspace::DISPLAY_P3, - ui::RenderIntent::TONE_MAP_COLORIMETRIC); + ui::RenderIntent::TONE_MAP_COLORIMETRIC, ui::Dataspace::UNKNOWN); EXPECT_EQ(ui::ColorMode::DISPLAY_P3, mOutput.getState().colorMode); EXPECT_EQ(ui::Dataspace::DISPLAY_P3, mOutput.getState().dataspace); EXPECT_EQ(ui::RenderIntent::TONE_MAP_COLORIMETRIC, mOutput.getState().renderIntent); + EXPECT_EQ(ui::Dataspace::UNKNOWN, mOutput.getState().targetDataspace); + EXPECT_THAT(mOutput.getState().dirtyRegion, RegionEq(Region(kDefaultDisplaySize))); } TEST_F(OutputTest, setColorModeDoesNothingIfNoChange) { + EXPECT_CALL(*mDisplayColorProfile, + getTargetDataspace(ui::ColorMode::DISPLAY_P3, ui::Dataspace::DISPLAY_P3, + ui::Dataspace::UNKNOWN)) + .WillOnce(Return(ui::Dataspace::UNKNOWN)); + mOutput.editState().colorMode = ui::ColorMode::DISPLAY_P3; mOutput.editState().dataspace = ui::Dataspace::DISPLAY_P3; mOutput.editState().renderIntent = ui::RenderIntent::TONE_MAP_COLORIMETRIC; + mOutput.editState().targetDataspace = ui::Dataspace::UNKNOWN; mOutput.setColorMode(ui::ColorMode::DISPLAY_P3, ui::Dataspace::DISPLAY_P3, - ui::RenderIntent::TONE_MAP_COLORIMETRIC); + ui::RenderIntent::TONE_MAP_COLORIMETRIC, ui::Dataspace::UNKNOWN); EXPECT_THAT(mOutput.getState().dirtyRegion, RegionEq(Region())); } diff --git a/services/surfaceflinger/ContainerLayer.cpp b/services/surfaceflinger/ContainerLayer.cpp index 7927fa95b6..3a5f3faa20 100644 --- a/services/surfaceflinger/ContainerLayer.cpp +++ b/services/surfaceflinger/ContainerLayer.cpp @@ -39,7 +39,4 @@ bool ContainerLayer::canReceiveInput() const { return !isHiddenByPolicy(); } -void ContainerLayer::setPerFrameData(const sp&, const ui::Transform&, - const Rect&, int32_t, const ui::Dataspace) {} - } // namespace android diff --git a/services/surfaceflinger/ContainerLayer.h b/services/surfaceflinger/ContainerLayer.h index 7222a3e15a..57267c70c8 100644 --- a/services/surfaceflinger/ContainerLayer.h +++ b/services/surfaceflinger/ContainerLayer.h @@ -33,10 +33,6 @@ public: bool canReceiveInput() const override; - void setPerFrameData(const sp& display, const ui::Transform& transform, - const Rect& viewport, int32_t supportedPerFrameMetadata, - const ui::Dataspace targetDataspace) override; - bool isCreatedFromMainThread() const override { return true; } bool onPreComposition(nsecs_t /*refreshStartTime*/) override { return false; } diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp index 414c8dd23d..c3da65348d 100644 --- a/services/surfaceflinger/Layer.cpp +++ b/services/surfaceflinger/Layer.cpp @@ -242,20 +242,6 @@ sp Layer::getHandle() { // h/w composer set-up // --------------------------------------------------------------------------- -bool Layer::hasHwcLayer(const sp& displayDevice) { - auto outputLayer = findOutputLayerForDisplay(displayDevice); - LOG_FATAL_IF(!outputLayer); - return outputLayer->getState().hwc && (*outputLayer->getState().hwc).hwcLayer != nullptr; -} - -HWC2::Layer* Layer::getHwcLayer(const sp& displayDevice) { - auto outputLayer = findOutputLayerForDisplay(displayDevice); - if (!outputLayer || !outputLayer->getState().hwc) { - return nullptr; - } - return (*outputLayer->getState().hwc).hwcLayer.get(); -} - Rect Layer::getContentCrop() const { // this is the crop rectangle that applies to the buffer // itself (as opposed to the window) @@ -454,29 +440,38 @@ void Layer::latchGeometry(compositionengine::LayerFECompositionState& compositio compositionState.appId = appId; } +void Layer::latchPerFrameState(compositionengine::LayerFECompositionState& compositionState) const { + compositionState.forceClientComposition = false; + + // TODO(lpique): b/121291683 Remove this one we are sure we don't need the + // value recomputed / set every frame. + compositionState.geomVisibleRegion = visibleRegion; + + compositionState.isColorspaceAgnostic = isColorSpaceAgnostic(); + compositionState.dataspace = mCurrentDataSpace; + compositionState.colorTransform = getColorTransform(); + compositionState.colorTransformIsIdentity = !hasColorTransform(); + compositionState.surfaceDamage = surfaceDamageRegion; + + // Force client composition for special cases known only to the front-end. + if (isHdrY410() || getRoundedCornerState().radius > 0.0f) { + compositionState.forceClientComposition = true; + } +} + void Layer::latchCompositionState(compositionengine::LayerFECompositionState& compositionState, bool includeGeometry) const { if (includeGeometry) { latchGeometry(compositionState); } + + latchPerFrameState(compositionState); } const char* Layer::getDebugName() const { return mName.string(); } -void Layer::forceClientComposition(const sp& display) { - const auto outputLayer = findOutputLayerForDisplay(display); - LOG_FATAL_IF(!outputLayer); - outputLayer->editState().forceClientComposition = true; -} - -bool Layer::getForceClientComposition(const sp& display) { - const auto outputLayer = findOutputLayerForDisplay(display); - LOG_FATAL_IF(!outputLayer); - return outputLayer->getState().forceClientComposition; -} - void Layer::updateCursorPosition(const sp& display) { const auto outputLayer = findOutputLayerForDisplay(display); LOG_FATAL_IF(!outputLayer); @@ -563,29 +558,6 @@ bool Layer::prepareClientLayer(const RenderArea& /*renderArea*/, const Region& / return true; } -void Layer::setCompositionType(const sp& display, - Hwc2::IComposerClient::Composition type) { - const auto outputLayer = findOutputLayerForDisplay(display); - LOG_FATAL_IF(!outputLayer); - LOG_FATAL_IF(!outputLayer->getState().hwc); - auto& compositionState = outputLayer->editState(); - - ALOGV("setCompositionType(%" PRIx64 ", %s, %d)", ((*compositionState.hwc).hwcLayer)->getId(), - toString(type).c_str(), 1); - if ((*compositionState.hwc).hwcCompositionType != type) { - ALOGV(" actually setting"); - (*compositionState.hwc).hwcCompositionType = type; - - auto error = (*compositionState.hwc) - .hwcLayer->setCompositionType(static_cast(type)); - ALOGE_IF(error != HWC2::Error::None, - "[%s] Failed to set " - "composition type %s: %s (%d)", - mName.string(), toString(type).c_str(), to_string(error).c_str(), - static_cast(error)); - } -} - Hwc2::IComposerClient::Composition Layer::getCompositionType( const sp& display) const { const auto outputLayer = findOutputLayerForDisplay(display); diff --git a/services/surfaceflinger/Layer.h b/services/surfaceflinger/Layer.h index b693a47f39..b1ce86b2dc 100644 --- a/services/surfaceflinger/Layer.h +++ b/services/surfaceflinger/Layer.h @@ -469,23 +469,13 @@ public: protected: void latchGeometry(compositionengine::LayerFECompositionState& outState) const; + virtual void latchPerFrameState(compositionengine::LayerFECompositionState& outState) const; public: virtual void setDefaultBufferSize(uint32_t /*w*/, uint32_t /*h*/) {} virtual bool isHdrY410() const { return false; } - void forceClientComposition(const sp& display); - bool getForceClientComposition(const sp& display); - virtual void setPerFrameData(const sp& display, - const ui::Transform& transform, const Rect& viewport, - int32_t supportedPerFrameMetadata, - const ui::Dataspace targetDataspace) = 0; - - // callIntoHwc exists so we can update our local state and call - // acceptDisplayChanges without unnecessarily updating the device's state - void setCompositionType(const sp& display, - Hwc2::IComposerClient::Composition type); Hwc2::IComposerClient::Composition getCompositionType( const sp& display) const; bool getClearClientTarget(const sp& display) const; @@ -607,10 +597,6 @@ public: virtual int32_t getQueuedFrameCount() const { return 0; } // ----------------------------------------------------------------------- - - bool hasHwcLayer(const sp& displayDevice); - HWC2::Layer* getHwcLayer(const sp& displayDevice); - inline const State& getDrawingState() const { return mDrawingState; } inline const State& getCurrentState() const { return mCurrentState; } inline State& getCurrentState() { return mCurrentState; } diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp index 5b8255667b..7230152e1a 100644 --- a/services/surfaceflinger/SurfaceFlinger.cpp +++ b/services/surfaceflinger/SurfaceFlinger.cpp @@ -160,28 +160,6 @@ bool isWideColorMode(const ColorMode colorMode) { return false; } -bool isHdrColorMode(const ColorMode colorMode) { - switch (colorMode) { - case ColorMode::BT2100_PQ: - case ColorMode::BT2100_HLG: - return true; - case ColorMode::DISPLAY_P3: - case ColorMode::ADOBE_RGB: - case ColorMode::DCI_P3: - case ColorMode::BT2020: - case ColorMode::DISPLAY_BT2020: - case ColorMode::NATIVE: - case ColorMode::STANDARD_BT601_625: - case ColorMode::STANDARD_BT601_625_UNADJUSTED: - case ColorMode::STANDARD_BT601_525: - case ColorMode::STANDARD_BT601_525_UNADJUSTED: - case ColorMode::STANDARD_BT709: - case ColorMode::SRGB: - return false; - } - return false; -} - ui::Transform::orientation_flags fromSurfaceComposerRotation(ISurfaceComposer::Rotation rotation) { switch (rotation) { case ISurfaceComposer::eRotateNone: @@ -1153,7 +1131,8 @@ status_t SurfaceFlinger::setActiveColorMode(const sp& displayToken, Col decodeColorMode(mode).c_str(), mode); } else { display->getCompositionDisplay()->setColorMode(mode, Dataspace::UNKNOWN, - RenderIntent::COLORIMETRIC); + RenderIntent::COLORIMETRIC, + Dataspace::UNKNOWN); } })); @@ -1853,104 +1832,80 @@ void SurfaceFlinger::calculateWorkingSet() { ATRACE_CALL(); ALOGV(__FUNCTION__); - // build the h/w work list - if (CC_UNLIKELY(mGeometryInvalid)) { - mGeometryInvalid = false; - for (const auto& [token, displayDevice] : mDisplays) { - auto display = displayDevice->getCompositionDisplay(); + const bool updatingGeometryThisFrame = mGeometryInvalid; + mGeometryInvalid = false; - uint32_t zOrder = 0; + { + // Use a map so that we latch the state of each front-end layer once. + std::unordered_map + uniqueVisibleLayers; + // Figure out which frontend layers are being composed, and build the unique + // set of them (and the corresponding composition layer) + for (const auto& [token, displayDevice] : mDisplays) { + auto display = displayDevice->getCompositionDisplay(); for (auto& layer : display->getOutputLayersOrderedByZ()) { - auto& compositionState = layer->editState(); - compositionState.forceClientComposition = false; - if (!compositionState.hwc || mDebugDisableHWC || mDebugRegion) { - compositionState.forceClientComposition = true; - } - - // The output Z order is set here based on a simple counter. - compositionState.z = zOrder++; + uniqueVisibleLayers.insert(std::make_pair(&layer->getLayerFE(), + &layer->getLayer().editState().frontEnd)); + } + } - // Update the display independent composition state. This goes - // to the general composition layer state structure. - // TODO: Do this once per compositionengine::CompositionLayer. - layer->getLayerFE().latchCompositionState(layer->getLayer().editState().frontEnd, - true); + // Update the composition state from each front-end layer. + for (auto& [layerFE, state] : uniqueVisibleLayers) { + layerFE->latchCompositionState(*state, updatingGeometryThisFrame); + } + } - // Recalculate the geometry state of the output layer. - layer->updateCompositionState(true); + if (CC_UNLIKELY(updatingGeometryThisFrame)) { + for (const auto& [token, displayDevice] : mDisplays) { + auto display = displayDevice->getCompositionDisplay(); + uint32_t zOrder = 0; - // Write the updated geometry state to the HWC - layer->writeStateToHWC(true); + for (auto& layer : display->getOutputLayersOrderedByZ()) { + // Assign a simple Z order sequence to each visible layer. + layer->editState().z = zOrder++; } } } - // Set the per-frame data + // Determine the color configuration of each output for (const auto& [token, displayDevice] : mDisplays) { auto display = displayDevice->getCompositionDisplay(); - const auto displayId = display->getId(); - if (!displayId) { - continue; - } - auto* profile = display->getDisplayColorProfile(); - if (mDrawingState.colorMatrixChanged) { - display->setColorTransform(mDrawingState.colorMatrix); - } - Dataspace targetDataspace = Dataspace::UNKNOWN; + ColorMode colorMode = ColorMode::NATIVE; + Dataspace dataspace = Dataspace::UNKNOWN; + RenderIntent renderIntent = RenderIntent::COLORIMETRIC; if (useColorManagement) { - ColorMode colorMode; - RenderIntent renderIntent; - pickColorMode(displayDevice, &colorMode, &targetDataspace, &renderIntent); - display->setColorMode(colorMode, targetDataspace, renderIntent); - - if (isHdrColorMode(colorMode)) { - targetDataspace = Dataspace::UNKNOWN; - } else if (mColorSpaceAgnosticDataspace != Dataspace::UNKNOWN) { - targetDataspace = mColorSpaceAgnosticDataspace; - } + pickColorMode(displayDevice, &colorMode, &dataspace, &renderIntent); } + display->setColorMode(colorMode, dataspace, renderIntent, mColorSpaceAgnosticDataspace); + } - for (auto& layer : displayDevice->getVisibleLayersSortedByZ()) { - if (layer->isHdrY410()) { - layer->forceClientComposition(displayDevice); - } else if ((layer->getDataSpace() == Dataspace::BT2020_PQ || - layer->getDataSpace() == Dataspace::BT2020_ITU_PQ) && - !profile->hasHDR10Support()) { - layer->forceClientComposition(displayDevice); - } else if ((layer->getDataSpace() == Dataspace::BT2020_HLG || - layer->getDataSpace() == Dataspace::BT2020_ITU_HLG) && - !profile->hasHLGSupport()) { - layer->forceClientComposition(displayDevice); - } - - if (layer->getRoundedCornerState().radius > 0.0f) { - layer->forceClientComposition(displayDevice); - } - - if (layer->getForceClientComposition(displayDevice)) { - ALOGV("[%s] Requesting Client composition", layer->getName().string()); - layer->setCompositionType(displayDevice, - Hwc2::IComposerClient::Composition::CLIENT); - continue; - } + for (const auto& [token, displayDevice] : mDisplays) { + auto display = displayDevice->getCompositionDisplay(); - const auto& displayState = display->getState(); - layer->setPerFrameData(displayDevice, displayState.transform, displayState.viewport, - displayDevice->getSupportedPerFrameMetadata(), targetDataspace); + for (auto& layer : display->getOutputLayersOrderedByZ()) { + // Update the composition state of the output layer, as needed + // recomputing it from the state given by the front-end layer. + layer->updateCompositionState(updatingGeometryThisFrame); } } - mDrawingState.colorMatrixChanged = false; - for (const auto& [token, displayDevice] : mDisplays) { auto display = displayDevice->getCompositionDisplay(); - for (auto& layer : displayDevice->getVisibleLayersSortedByZ()) { - auto& layerState = layer->getCompositionLayer()->editState().frontEnd; - layerState.compositionType = static_cast( - layer->getCompositionType(displayDevice)); + + for (auto& layer : display->getOutputLayersOrderedByZ()) { + // Send the updated state to the HWC, if appropriate. + layer->writeStateToHWC(updatingGeometryThisFrame); + } + } + + if (CC_UNLIKELY(mDrawingState.colorMatrixChanged)) { + for (const auto& [token, displayDevice] : mDisplays) { + auto display = displayDevice->getCompositionDisplay(); + display->setColorTransform(mDrawingState.colorMatrix); } + mDrawingState.colorMatrixChanged = false; } } @@ -2347,7 +2302,8 @@ Dataspace SurfaceFlinger::getBestDataspace(const sp& display, case Dataspace::BT2020_ITU_PQ: bestDataSpace = Dataspace::DISPLAY_P3; *outHdrDataSpace = Dataspace::BT2020_PQ; - *outIsHdrClientComposition = layer->getForceClientComposition(display); + *outIsHdrClientComposition = + layer->getCompositionLayer()->getState().frontEnd.forceClientComposition; break; case Dataspace::BT2020_HLG: case Dataspace::BT2020_ITU_HLG: @@ -2688,7 +2644,7 @@ sp SurfaceFlinger::setupNewDisplayDeviceInternal( defaultDataSpace = Dataspace::V0_SRGB; } display->getCompositionDisplay()->setColorMode(defaultColorMode, defaultDataSpace, - RenderIntent::COLORIMETRIC); + RenderIntent::COLORIMETRIC, Dataspace::UNKNOWN); if (!state.isVirtual()) { LOG_ALWAYS_FATAL_IF(!displayId); display->setActiveConfig(getHwComposer().getActiveConfigIndex(*displayId)); diff --git a/services/surfaceflinger/tests/unittests/CompositionTest.cpp b/services/surfaceflinger/tests/unittests/CompositionTest.cpp index e6211c488e..38d70262a7 100644 --- a/services/surfaceflinger/tests/unittests/CompositionTest.cpp +++ b/services/surfaceflinger/tests/unittests/CompositionTest.cpp @@ -988,7 +988,9 @@ struct RECompositionResultVariant : public CompositionResultBaseVariant { struct ForcedClientCompositionResultVariant : public RECompositionResultVariant { static void setupLayerState(CompositionTest* test, sp layer) { - layer->forceClientComposition(test->mDisplay); + const auto outputLayer = layer->findOutputLayerForDisplay(test->mDisplay); + LOG_FATAL_IF(!outputLayer); + outputLayer->editState().forceClientComposition = true; } template -- cgit v1.2.3-59-g8ed1b From 8406fd785b80ab2fb2b7418ef6e973aace93df92 Mon Sep 17 00:00:00 2001 From: Vishnu Nair Date: Tue, 30 Jul 2019 11:29:31 -0700 Subject: Fix locking issues with proto dumps Proto dumps are generated from: - binder threads when generating bugreports or triggering dumpstate - main thread when mLayerStats is enabled - tracing thread when winscope tracing is enabled. The binder thread reads current state while the other threads reads drawing state. The writeToProto function accesses a mix of current and drawing states. mPendingState should only be accessed with the mStateLock held and the visible regions should be read from the main or tracing threads. This causes some invalid access issues. To make the locking requirements clear, this change 1. moves drawing specific data to a new function 2. copies mPendingState so we can dump the copy safely in main thread 3. dumps drawing data from binder threads by posting a message onto the main thread Bug: 138318680 Test: adb shell dumpsys SurfaceFlinger, winscope Change-Id: I8bb93e9b9f81faec59585b770eb7ba0fbcd9b51b --- services/surfaceflinger/Layer.cpp | 113 ++++++++++++++--------------- services/surfaceflinger/Layer.h | 32 +++++--- services/surfaceflinger/SurfaceFlinger.cpp | 43 +++++------ services/surfaceflinger/SurfaceFlinger.h | 8 +- services/surfaceflinger/SurfaceTracing.cpp | 2 +- 5 files changed, 106 insertions(+), 92 deletions(-) (limited to 'services/surfaceflinger/Layer.cpp') diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp index b5f080037b..8150ca7dfc 100644 --- a/services/surfaceflinger/Layer.cpp +++ b/services/surfaceflinger/Layer.cpp @@ -153,7 +153,6 @@ void Layer::removeRemoteSyncPoints() { mRemoteSyncPoints.clear(); { - Mutex::Autolock pendingStateLock(mPendingStateMutex); for (State pendingState : mPendingStates) { pendingState.barrierLayer_legacy = nullptr; } @@ -853,6 +852,7 @@ uint32_t Layer::doTransaction(uint32_t flags) { // Commit the transaction commitTransaction(c); + mPendingStatesSnapshot = mPendingStates; mCurrentState.callbackHandles = {}; return flags; } @@ -1820,14 +1820,61 @@ void Layer::setInputInfo(const InputWindowInfo& info) { setTransactionFlags(eTransactionNeeded); } -void Layer::writeToProto(LayerProto* layerInfo, LayerVector::StateSet stateSet, - uint32_t traceFlags) { +void Layer::writeToProtoDrawingState(LayerProto* layerInfo, uint32_t traceFlags) const { + ui::Transform transform = getTransform(); + + if (traceFlags & SurfaceTracing::TRACE_CRITICAL) { + for (const auto& pendingState : mPendingStatesSnapshot) { + auto barrierLayer = pendingState.barrierLayer_legacy.promote(); + if (barrierLayer != nullptr) { + BarrierLayerProto* barrierLayerProto = layerInfo->add_barrier_layer(); + barrierLayerProto->set_id(barrierLayer->sequence); + barrierLayerProto->set_frame_number(pendingState.frameNumber_legacy); + } + } + + auto buffer = mActiveBuffer; + if (buffer != nullptr) { + LayerProtoHelper::writeToProto(buffer, + [&]() { return layerInfo->mutable_active_buffer(); }); + LayerProtoHelper::writeToProto(ui::Transform(mCurrentTransform), + layerInfo->mutable_buffer_transform()); + } + layerInfo->set_invalidate(contentDirty); + layerInfo->set_is_protected(isProtected()); + layerInfo->set_dataspace( + dataspaceDetails(static_cast(mCurrentDataSpace))); + layerInfo->set_queued_frames(getQueuedFrameCount()); + layerInfo->set_refresh_pending(isBufferLatched()); + layerInfo->set_curr_frame(mCurrentFrameNumber); + layerInfo->set_effective_scaling_mode(getEffectiveScalingMode()); + + layerInfo->set_corner_radius(getRoundedCornerState().radius); + LayerProtoHelper::writeToProto(transform, layerInfo->mutable_transform()); + LayerProtoHelper::writePositionToProto(transform.tx(), transform.ty(), + [&]() { return layerInfo->mutable_position(); }); + LayerProtoHelper::writeToProto(mBounds, [&]() { return layerInfo->mutable_bounds(); }); + LayerProtoHelper::writeToProto(visibleRegion, + [&]() { return layerInfo->mutable_visible_region(); }); + LayerProtoHelper::writeToProto(surfaceDamageRegion, + [&]() { return layerInfo->mutable_damage_region(); }); + } + + if (traceFlags & SurfaceTracing::TRACE_EXTRA) { + LayerProtoHelper::writeToProto(mSourceBounds, + [&]() { return layerInfo->mutable_source_bounds(); }); + LayerProtoHelper::writeToProto(mScreenBounds, + [&]() { return layerInfo->mutable_screen_bounds(); }); + } +} + +void Layer::writeToProtoCommonState(LayerProto* layerInfo, LayerVector::StateSet stateSet, + uint32_t traceFlags) const { const bool useDrawing = stateSet == LayerVector::StateSet::Drawing; const LayerVector& children = useDrawing ? mDrawingChildren : mCurrentChildren; const State& state = useDrawing ? mDrawingState : mCurrentState; ui::Transform requestedTransform = state.active_legacy.transform; - ui::Transform transform = getTransform(); if (traceFlags & SurfaceTracing::TRACE_CRITICAL) { layerInfo->set_id(sequence); @@ -1847,17 +1894,10 @@ void Layer::writeToProto(LayerProto* layerInfo, LayerVector::StateSet stateSet, LayerProtoHelper::writeToProto(state.activeTransparentRegion_legacy, [&]() { return layerInfo->mutable_transparent_region(); }); - LayerProtoHelper::writeToProto(visibleRegion, - [&]() { return layerInfo->mutable_visible_region(); }); - LayerProtoHelper::writeToProto(surfaceDamageRegion, - [&]() { return layerInfo->mutable_damage_region(); }); layerInfo->set_layer_stack(getLayerStack()); layerInfo->set_z(state.z); - LayerProtoHelper::writePositionToProto(transform.tx(), transform.ty(), - [&]() { return layerInfo->mutable_position(); }); - LayerProtoHelper::writePositionToProto(requestedTransform.tx(), requestedTransform.ty(), [&]() { return layerInfo->mutable_requested_position(); @@ -1868,15 +1908,9 @@ void Layer::writeToProto(LayerProto* layerInfo, LayerVector::StateSet stateSet, LayerProtoHelper::writeToProto(state.crop_legacy, [&]() { return layerInfo->mutable_crop(); }); - layerInfo->set_corner_radius(getRoundedCornerState().radius); layerInfo->set_is_opaque(isOpaque(state)); - layerInfo->set_invalidate(contentDirty); - layerInfo->set_is_protected(isProtected()); - // XXX (b/79210409) mCurrentDataSpace is not protected - layerInfo->set_dataspace( - dataspaceDetails(static_cast(mCurrentDataSpace))); layerInfo->set_pixel_format(decodePixelFormat(getPixelFormat())); LayerProtoHelper::writeToProto(getColor(), [&]() { return layerInfo->mutable_color(); }); @@ -1884,7 +1918,6 @@ void Layer::writeToProto(LayerProto* layerInfo, LayerVector::StateSet stateSet, [&]() { return layerInfo->mutable_requested_color(); }); layerInfo->set_flags(state.flags); - LayerProtoHelper::writeToProto(transform, layerInfo->mutable_transform()); LayerProtoHelper::writeToProto(requestedTransform, layerInfo->mutable_requested_transform()); @@ -1901,29 +1934,6 @@ void Layer::writeToProto(LayerProto* layerInfo, LayerVector::StateSet stateSet, } else { layerInfo->set_z_order_relative_of(-1); } - - auto buffer = mActiveBuffer; - if (buffer != nullptr) { - LayerProtoHelper::writeToProto(buffer, - [&]() { return layerInfo->mutable_active_buffer(); }); - LayerProtoHelper::writeToProto(ui::Transform(mCurrentTransform), - layerInfo->mutable_buffer_transform()); - } - - layerInfo->set_queued_frames(getQueuedFrameCount()); - layerInfo->set_refresh_pending(isBufferLatched()); - layerInfo->set_curr_frame(mCurrentFrameNumber); - layerInfo->set_effective_scaling_mode(getEffectiveScalingMode()); - - for (const auto& pendingState : mPendingStates) { - auto barrierLayer = pendingState.barrierLayer_legacy.promote(); - if (barrierLayer != nullptr) { - BarrierLayerProto* barrierLayerProto = layerInfo->add_barrier_layer(); - barrierLayerProto->set_id(barrierLayer->sequence); - barrierLayerProto->set_frame_number(pendingState.frameNumber_legacy); - } - } - LayerProtoHelper::writeToProto(mBounds, [&]() { return layerInfo->mutable_bounds(); }); } if (traceFlags & SurfaceTracing::TRACE_INPUT) { @@ -1936,23 +1946,19 @@ void Layer::writeToProto(LayerProto* layerInfo, LayerVector::StateSet stateSet, for (const auto& entry : state.metadata.mMap) { (*protoMap)[entry.first] = std::string(entry.second.cbegin(), entry.second.cend()); } - LayerProtoHelper::writeToProto(mEffectiveTransform, - layerInfo->mutable_effective_transform()); - LayerProtoHelper::writeToProto(mSourceBounds, - [&]() { return layerInfo->mutable_source_bounds(); }); - LayerProtoHelper::writeToProto(mScreenBounds, - [&]() { return layerInfo->mutable_screen_bounds(); }); } } -void Layer::writeToProto(LayerProto* layerInfo, const sp& displayDevice, - uint32_t traceFlags) { +void Layer::writeToProtoCompositionState(LayerProto* layerInfo, + const sp& displayDevice, + uint32_t traceFlags) const { auto outputLayer = findOutputLayerForDisplay(displayDevice); if (!outputLayer) { return; } - writeToProto(layerInfo, LayerVector::StateSet::Drawing, traceFlags); + writeToProtoDrawingState(layerInfo, traceFlags); + writeToProtoCommonState(layerInfo, LayerVector::StateSet::Drawing, traceFlags); const auto& compositionState = outputLayer->getState(); @@ -1970,13 +1976,6 @@ void Layer::writeToProto(LayerProto* layerInfo, const sp& display static_cast(compositionState.hwc ? (*compositionState.hwc).hwcCompositionType : Hwc2::IComposerClient::Composition::CLIENT); layerInfo->set_hwc_composition_type(compositionType); - - if (std::strcmp(getTypeId(), "BufferLayer") == 0 && - static_cast(this)->isProtected()) { - layerInfo->set_is_protected(true); - } else { - layerInfo->set_is_protected(false); - } } bool Layer::isRemovedFromCurrentState() const { diff --git a/services/surfaceflinger/Layer.h b/services/surfaceflinger/Layer.h index bfc2136725..27a8ca7a73 100644 --- a/services/surfaceflinger/Layer.h +++ b/services/surfaceflinger/Layer.h @@ -435,11 +435,21 @@ public: bool isRemovedFromCurrentState() const; - void writeToProto(LayerProto* layerInfo, LayerVector::StateSet stateSet, - uint32_t traceFlags = SurfaceTracing::TRACE_ALL); - - void writeToProto(LayerProto* layerInfo, const sp& displayDevice, - uint32_t traceFlags = SurfaceTracing::TRACE_ALL); + // Write states that are modified by the main thread. This includes drawing + // state as well as buffer data. This should be called in the main or tracing + // thread. + void writeToProtoDrawingState(LayerProto* layerInfo, + uint32_t traceFlags = SurfaceTracing::TRACE_ALL) const; + // Write states that are modified by the main thread. This includes drawing + // state as well as buffer data and composition data for layers on the specified + // display. This should be called in the main or tracing thread. + void writeToProtoCompositionState(LayerProto* layerInfo, const sp& displayDevice, + uint32_t traceFlags = SurfaceTracing::TRACE_ALL) const; + // Write drawing or current state. If writing current state, the caller should hold the + // external mStateLock. If writing drawing state, this function should be called on the + // main or tracing thread. + void writeToProtoCommonState(LayerProto* layerInfo, LayerVector::StateSet stateSet, + uint32_t traceFlags = SurfaceTracing::TRACE_ALL) const; virtual Geometry getActiveGeometry(const Layer::State& s) const { return s.active_legacy; } virtual uint32_t getActiveWidth(const Layer::State& s) const { return s.active_legacy.w; } @@ -819,13 +829,15 @@ protected: bool mPrimaryDisplayOnly = false; - // these are protected by an external lock - State mCurrentState; + // These are only accessed by the main thread or the tracing thread. State mDrawingState; - std::atomic mTransactionFlags{0}; + // Store a copy of the pending state so that the drawing thread can access the + // states without a lock. + Vector mPendingStatesSnapshot; - // Accessed from main thread and binder threads - Mutex mPendingStateMutex; + // these are protected by an external lock (mStateLock) + State mCurrentState; + std::atomic mTransactionFlags{0}; Vector mPendingStates; // Timestamp history for UIAutomation. Thread safe. diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp index 8bf6b999bb..e8b39cc797 100644 --- a/services/surfaceflinger/SurfaceFlinger.cpp +++ b/services/surfaceflinger/SurfaceFlinger.cpp @@ -4578,18 +4578,22 @@ status_t SurfaceFlinger::doDump(int fd, const DumpArgs& args, if (const auto it = dumpers.find(flag); it != dumpers.end()) { (it->second)(args, asProto, result); - } else { - if (asProto) { - LayersProto layersProto = dumpProtoInfo(LayerVector::StateSet::Current); - result.append(layersProto.SerializeAsString().c_str(), layersProto.ByteSize()); - } else { - dumpAllLocked(args, result); - } + } else if (!asProto) { + dumpAllLocked(args, result); } if (locked) { mStateLock.unlock(); } + + LayersProto layersProto = dumpProtoFromMainThread(); + if (asProto) { + result.append(layersProto.SerializeAsString().c_str(), layersProto.ByteSize()); + } else { + auto layerTree = LayerProtoParser::generateLayerTree(layersProto); + result.append(LayerProtoParser::layerTreeToString(layerTree)); + result.append("\n"); + } } write(fd, result.c_str(), result.size()); return NO_ERROR; @@ -4830,19 +4834,23 @@ void SurfaceFlinger::dumpWideColorInfo(std::string& result) const { result.append("\n"); } -LayersProto SurfaceFlinger::dumpProtoInfo(LayerVector::StateSet stateSet, - uint32_t traceFlags) const { +LayersProto SurfaceFlinger::dumpDrawingStateProto(uint32_t traceFlags) const { LayersProto layersProto; - const bool useDrawing = stateSet == LayerVector::StateSet::Drawing; - const State& state = useDrawing ? mDrawingState : mCurrentState; - state.traverseInZOrder([&](Layer* layer) { + mDrawingState.traverseInZOrder([&](Layer* layer) { LayerProto* layerProto = layersProto.add_layers(); - layer->writeToProto(layerProto, stateSet, traceFlags); + layer->writeToProtoDrawingState(layerProto, traceFlags); + layer->writeToProtoCommonState(layerProto, LayerVector::StateSet::Drawing, traceFlags); }); return layersProto; } +LayersProto SurfaceFlinger::dumpProtoFromMainThread(uint32_t traceFlags) { + LayersProto layersProto; + postMessageSync(new LambdaMessage([&]() { layersProto = dumpDrawingStateProto(traceFlags); })); + return layersProto; +} + LayersProto SurfaceFlinger::dumpVisibleLayersProtoInfo( const sp& displayDevice) const { LayersProto layersProto; @@ -4863,7 +4871,7 @@ LayersProto SurfaceFlinger::dumpVisibleLayersProtoInfo( mDrawingState.traverseInZOrder([&](Layer* layer) { if (!layer->visibleRegion.isEmpty() && !display->getOutputLayersOrderedByZ().empty()) { LayerProto* layerProto = layersProto.add_layers(); - layer->writeToProto(layerProto, displayDevice); + layer->writeToProtoCompositionState(layerProto, displayDevice); } }); @@ -4927,13 +4935,6 @@ void SurfaceFlinger::dumpAllLocked(const DumpArgs& args, std::string& result) co mGraphicBufferProducerList.size(), mMaxGraphicBufferProducerListSize); colorizer.reset(result); - { - LayersProto layersProto = dumpProtoInfo(LayerVector::StateSet::Current); - auto layerTree = LayerProtoParser::generateLayerTree(layersProto); - result.append(LayerProtoParser::layerTreeToString(layerTree)); - result.append("\n"); - } - { StringAppendF(&result, "Composition layers\n"); mDrawingState.traverseInZOrder([&](Layer* layer) { diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h index b4b5b85e46..a17f6c8867 100644 --- a/services/surfaceflinger/SurfaceFlinger.h +++ b/services/surfaceflinger/SurfaceFlinger.h @@ -265,7 +265,8 @@ public: status_t postMessageAsync(const sp& msg, nsecs_t reltime = 0, uint32_t flags = 0); // post a synchronous message to the main thread - status_t postMessageSync(const sp& msg, nsecs_t reltime = 0, uint32_t flags = 0); + status_t postMessageSync(const sp& msg, nsecs_t reltime = 0, uint32_t flags = 0) + EXCLUDES(mStateLock); // force full composition on all displays void repaintEverything(); @@ -896,8 +897,9 @@ private: void dumpBufferingStats(std::string& result) const; void dumpDisplayIdentificationData(std::string& result) const; void dumpWideColorInfo(std::string& result) const; - LayersProto dumpProtoInfo(LayerVector::StateSet stateSet, - uint32_t traceFlags = SurfaceTracing::TRACE_ALL) const; + LayersProto dumpDrawingStateProto(uint32_t traceFlags = SurfaceTracing::TRACE_ALL) const; + LayersProto dumpProtoFromMainThread(uint32_t traceFlags = SurfaceTracing::TRACE_ALL) + EXCLUDES(mStateLock); void withTracingLock(std::function operation) REQUIRES(mStateLock); LayersProto dumpVisibleLayersProtoInfo(const sp& display) const; diff --git a/services/surfaceflinger/SurfaceTracing.cpp b/services/surfaceflinger/SurfaceTracing.cpp index c4ab0668e7..9053f2c7de 100644 --- a/services/surfaceflinger/SurfaceTracing.cpp +++ b/services/surfaceflinger/SurfaceTracing.cpp @@ -162,7 +162,7 @@ LayersTraceProto SurfaceTracing::traceLayersLocked(const char* where) { LayersTraceProto entry; entry.set_elapsed_realtime_nanos(elapsedRealtimeNano()); entry.set_where(where); - LayersProto layers(mFlinger.dumpProtoInfo(LayerVector::StateSet::Drawing, mTraceFlags)); + LayersProto layers(mFlinger.dumpDrawingStateProto(mTraceFlags)); entry.mutable_layers()->Swap(&layers); return entry; -- cgit v1.2.3-59-g8ed1b From f16688fcebb22193b555e24c329155f6f0a2f372 Mon Sep 17 00:00:00 2001 From: Lloyd Pique Date: Tue, 19 Feb 2019 17:47:57 -0800 Subject: SF: Introduce LayerFE::prepareClientComposition Renames Layer::prepareClientLayer, and alters it to not take a RenderArea. Test: atest libsurfaceflinger_unittest libcompositionengine_test Bug: 121291683 Change-Id: I6da6005c2e34e6e44692043cdc7adf9c4aa57cf5 --- services/surfaceflinger/BufferLayer.cpp | 42 ++++++++-------- services/surfaceflinger/BufferLayer.h | 17 +++---- services/surfaceflinger/ColorLayer.cpp | 18 +++---- services/surfaceflinger/ColorLayer.h | 13 ++--- .../include/compositionengine/LayerFE.h | 31 ++++++++++++ .../include/compositionengine/mock/LayerFE.h | 3 ++ services/surfaceflinger/ContainerLayer.cpp | 5 -- services/surfaceflinger/ContainerLayer.h | 8 --- services/surfaceflinger/Layer.cpp | 57 ++++++++-------------- services/surfaceflinger/Layer.h | 21 ++------ services/surfaceflinger/SurfaceFlinger.cpp | 56 ++++++++++++++------- 11 files changed, 141 insertions(+), 130 deletions(-) (limited to 'services/surfaceflinger/Layer.cpp') diff --git a/services/surfaceflinger/BufferLayer.cpp b/services/surfaceflinger/BufferLayer.cpp index 59ea9afa97..87bec11609 100644 --- a/services/surfaceflinger/BufferLayer.cpp +++ b/services/surfaceflinger/BufferLayer.cpp @@ -132,13 +132,15 @@ static constexpr mat4 inverseOrientation(uint32_t transform) { return inverse(tr); } -bool BufferLayer::prepareClientLayer(const RenderArea& renderArea, const Region& clip, - bool useIdentityTransform, Region& clearRegion, - const bool supportProtectedContent, - renderengine::LayerSettings& layer) { +std::optional BufferLayer::prepareClientComposition( + compositionengine::LayerFE::ClientCompositionTargetSettings& targetSettings) { ATRACE_CALL(); - Layer::prepareClientLayer(renderArea, clip, useIdentityTransform, clearRegion, - supportProtectedContent, layer); + + auto result = Layer::prepareClientComposition(targetSettings); + if (!result) { + return result; + } + if (CC_UNLIKELY(mActiveBuffer == 0)) { // the texture has not been created yet, this Layer has // in fact never been drawn into. This happens frequently with @@ -159,15 +161,16 @@ bool BufferLayer::prepareClientLayer(const RenderArea& renderArea, const Region& under.orSelf(layer->visibleRegion); }); // if not everything below us is covered, we plug the holes! - Region holes(clip.subtract(under)); + Region holes(targetSettings.clip.subtract(under)); if (!holes.isEmpty()) { - clearRegion.orSelf(holes); + targetSettings.clearRegion.orSelf(holes); } - return false; + return std::nullopt; } - bool blackOutLayer = - (isProtected() && !supportProtectedContent) || (isSecure() && !renderArea.isSecure()); + bool blackOutLayer = (isProtected() && !targetSettings.supportProtectedContent) || + (isSecure() && !targetSettings.isSecure); const State& s(getDrawingState()); + auto& layer = *result; if (!blackOutLayer) { layer.source.buffer.buffer = mActiveBuffer; layer.source.buffer.isOpaque = isOpaque(s); @@ -176,8 +179,7 @@ bool BufferLayer::prepareClientLayer(const RenderArea& renderArea, const Region& layer.source.buffer.usePremultipliedAlpha = getPremultipledAlpha(); layer.source.buffer.isY410BT2020 = isHdrY410(); // TODO: we could be more subtle with isFixedSize() - const bool useFiltering = needsFiltering(renderArea.getDisplayDevice()) || - renderArea.needsFiltering() || isFixedSize(); + const bool useFiltering = targetSettings.needsFiltering || mNeedsFiltering || isFixedSize(); // Query the texture matrix given our current filtering mode. float textureMatrix[16]; @@ -244,7 +246,7 @@ bool BufferLayer::prepareClientLayer(const RenderArea& renderArea, const Region& layer.alpha = 1.0; } - return true; + return result; } bool BufferLayer::isHdrY410() const { @@ -572,21 +574,23 @@ bool BufferLayer::getOpacityForFormat(uint32_t format) { } bool BufferLayer::needsFiltering(const sp& displayDevice) const { - // If we are not capturing based on the state of a known display device, we - // only return mNeedsFiltering + // If we are not capturing based on the state of a known display device, + // just return false. if (displayDevice == nullptr) { - return mNeedsFiltering; + return false; } const auto outputLayer = findOutputLayerForDisplay(displayDevice); if (outputLayer == nullptr) { - return mNeedsFiltering; + return false; } + // We need filtering if the sourceCrop rectangle size does not match the + // displayframe rectangle size (not a 1:1 render) const auto& compositionState = outputLayer->getState(); const auto displayFrame = compositionState.displayFrame; const auto sourceCrop = compositionState.sourceCrop; - return mNeedsFiltering || sourceCrop.getHeight() != displayFrame.getHeight() || + return sourceCrop.getHeight() != displayFrame.getHeight() || sourceCrop.getWidth() != displayFrame.getWidth(); } diff --git a/services/surfaceflinger/BufferLayer.h b/services/surfaceflinger/BufferLayer.h index bb0205de3e..c86acf08f8 100644 --- a/services/surfaceflinger/BufferLayer.h +++ b/services/surfaceflinger/BufferLayer.h @@ -82,7 +82,6 @@ public: bool isHdrY410() const override; - bool onPreComposition(nsecs_t refreshStartTime) override; bool onPostComposition(const std::optional& displayId, const std::shared_ptr& glDoneFence, const std::shared_ptr& presentFence, @@ -146,7 +145,13 @@ private: virtual status_t updateFrameNumber(nsecs_t latchTime) = 0; protected: - void latchPerFrameState(compositionengine::LayerFECompositionState& outState) const override; + /* + * compositionengine::LayerFE overrides + */ + bool onPreComposition(nsecs_t) override; + void latchPerFrameState(compositionengine::LayerFECompositionState&) const override; + std::optional prepareClientComposition( + compositionengine::LayerFE::ClientCompositionTargetSettings&) override; // Loads the corresponding system property once per process static bool latchUnsignaledBuffers(); @@ -163,15 +168,9 @@ protected: bool mRefreshPending{false}; - // prepareClientLayer - constructs a RenderEngine layer for GPU composition. - bool prepareClientLayer(const RenderArea& renderArea, const Region& clip, - bool useIdentityTransform, Region& clearRegion, - const bool supportProtectedContent, - renderengine::LayerSettings& layer) override; - private: // Returns true if this layer requires filtering - bool needsFiltering(const sp& displayDevice) const; + bool needsFiltering(const sp& displayDevice) const override; uint64_t getHeadFrameNumber(nsecs_t expectedPresentTime) const; diff --git a/services/surfaceflinger/ColorLayer.cpp b/services/surfaceflinger/ColorLayer.cpp index f15957adf9..b65d351263 100644 --- a/services/surfaceflinger/ColorLayer.cpp +++ b/services/surfaceflinger/ColorLayer.cpp @@ -50,16 +50,14 @@ ColorLayer::ColorLayer(const LayerCreationArgs& args) ColorLayer::~ColorLayer() = default; -bool ColorLayer::prepareClientLayer(const RenderArea& renderArea, const Region& clip, - bool useIdentityTransform, Region& clearRegion, - const bool supportProtectedContent, - renderengine::LayerSettings& layer) { - Layer::prepareClientLayer(renderArea, clip, useIdentityTransform, clearRegion, - supportProtectedContent, layer); - half4 color(getColor()); - half3 solidColor(color.r, color.g, color.b); - layer.source.solidColor = solidColor; - return true; +std::optional ColorLayer::prepareClientComposition( + compositionengine::LayerFE::ClientCompositionTargetSettings& targetSettings) { + auto result = Layer::prepareClientComposition(targetSettings); + if (!result) { + return result; + } + result->source.solidColor = getColor().rgb; + return result; } bool ColorLayer::isVisible() const { diff --git a/services/surfaceflinger/ColorLayer.h b/services/surfaceflinger/ColorLayer.h index 2483ff0bfb..015b939457 100644 --- a/services/surfaceflinger/ColorLayer.h +++ b/services/surfaceflinger/ColorLayer.h @@ -39,16 +39,13 @@ public: void commitTransaction(const State& stateToCommit) override; - bool onPreComposition(nsecs_t /*refreshStartTime*/) override { return false; } - protected: - virtual bool prepareClientLayer(const RenderArea& renderArea, const Region& clip, - bool useIdentityTransform, Region& clearRegion, - const bool supportProtectedContent, - renderengine::LayerSettings& layer); - -private: + /* + * compositionengine::LayerFE overrides + */ void latchPerFrameState(compositionengine::LayerFECompositionState&) const override; + std::optional prepareClientComposition( + compositionengine::LayerFE::ClientCompositionTargetSettings&) override; std::shared_ptr mCompositionLayer; }; diff --git a/services/surfaceflinger/CompositionEngine/include/compositionengine/LayerFE.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/LayerFE.h index 1f2cae9c2b..94fab1fdf6 100644 --- a/services/surfaceflinger/CompositionEngine/include/compositionengine/LayerFE.h +++ b/services/surfaceflinger/CompositionEngine/include/compositionengine/LayerFE.h @@ -16,6 +16,9 @@ #pragma once +#include + +#include #include #include @@ -40,6 +43,34 @@ public: // geometry state can be skipped. virtual void latchCompositionState(LayerFECompositionState&, bool includeGeometry) const = 0; + struct ClientCompositionTargetSettings { + // The clip region, or visible region that is being rendered to + const Region& clip; + + // If true, the layer should use an identity transform for its position + // transform. Used only by the captureScreen API call. + const bool useIdentityTransform; + + // If set to true, the layer should enable filtering when rendering. + const bool needsFiltering; + + // If set to true, the buffer is being sent to a destination that is + // expected to treat the buffer contents as secure. + const bool isSecure; + + // If set to true, the target buffer has protected content support. + const bool supportProtectedContent; + + // Modified by each call to prepareClientComposition to indicate the + // region of the target buffer that should be cleared. + Region& clearRegion; + }; + + // Returns the LayerSettings to pass to RenderEngine::drawLayers, or + // nullopt_t if the layer does not render + virtual std::optional prepareClientComposition( + ClientCompositionTargetSettings&) = 0; + // Called after the layer is displayed to update the presentation fence virtual void onLayerDisplayed(const sp&) = 0; diff --git a/services/surfaceflinger/CompositionEngine/include/compositionengine/mock/LayerFE.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/mock/LayerFE.h index 952f702e1c..48c2dbf3d6 100644 --- a/services/surfaceflinger/CompositionEngine/include/compositionengine/mock/LayerFE.h +++ b/services/surfaceflinger/CompositionEngine/include/compositionengine/mock/LayerFE.h @@ -33,6 +33,9 @@ public: MOCK_METHOD1(onPreComposition, bool(nsecs_t)); MOCK_CONST_METHOD2(latchCompositionState, void(LayerFECompositionState&, bool)); + MOCK_METHOD1(prepareClientComposition, + std::optional( + compositionengine::LayerFE::ClientCompositionTargetSettings&)); MOCK_METHOD1(onLayerDisplayed, void(const sp&)); MOCK_CONST_METHOD0(getDebugName, const char*()); diff --git a/services/surfaceflinger/ContainerLayer.cpp b/services/surfaceflinger/ContainerLayer.cpp index 3a5f3faa20..d40a38c811 100644 --- a/services/surfaceflinger/ContainerLayer.cpp +++ b/services/surfaceflinger/ContainerLayer.cpp @@ -26,11 +26,6 @@ ContainerLayer::ContainerLayer(const LayerCreationArgs& args) : Layer(args) {} ContainerLayer::~ContainerLayer() = default; -bool ContainerLayer::prepareClientLayer(const RenderArea&, const Region&, bool, Region&, const bool, - renderengine::LayerSettings&) { - return false; -} - bool ContainerLayer::isVisible() const { return false; } diff --git a/services/surfaceflinger/ContainerLayer.h b/services/surfaceflinger/ContainerLayer.h index 57267c70c8..a1607ffabb 100644 --- a/services/surfaceflinger/ContainerLayer.h +++ b/services/surfaceflinger/ContainerLayer.h @@ -34,14 +34,6 @@ public: bool canReceiveInput() const override; bool isCreatedFromMainThread() const override { return true; } - - bool onPreComposition(nsecs_t /*refreshStartTime*/) override { return false; } - -protected: - bool prepareClientLayer(const RenderArea& renderArea, const Region& clip, - bool useIdentityTransform, Region& clearRegion, - const bool supportProtectedContent, - renderengine::LayerSettings& layer) override; }; } // namespace android diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp index 8150ca7dfc..a2eeea545b 100644 --- a/services/surfaceflinger/Layer.cpp +++ b/services/surfaceflinger/Layer.cpp @@ -458,6 +458,10 @@ void Layer::latchPerFrameState(compositionengine::LayerFECompositionState& compo } } +bool Layer::onPreComposition(nsecs_t) { + return false; +} + void Layer::latchCompositionState(compositionengine::LayerFECompositionState& compositionState, bool includeGeometry) const { if (includeGeometry) { @@ -507,54 +511,33 @@ void Layer::updateCursorPosition(const sp& display) { // drawing... // --------------------------------------------------------------------------- -bool Layer::prepareClientLayer(const RenderArea& renderArea, const Region& clip, - Region& clearRegion, const bool supportProtectedContent, - renderengine::LayerSettings& layer) { - return prepareClientLayer(renderArea, clip, false, clearRegion, supportProtectedContent, layer); -} - -bool Layer::prepareClientLayer(const RenderArea& renderArea, bool useIdentityTransform, - Region& clearRegion, const bool supportProtectedContent, - renderengine::LayerSettings& layer) { - return prepareClientLayer(renderArea, Region(renderArea.getBounds()), useIdentityTransform, - clearRegion, supportProtectedContent, layer); -} +std::optional Layer::prepareClientComposition( + compositionengine::LayerFE::ClientCompositionTargetSettings& targetSettings) { + if (!getCompositionLayer()) { + return {}; + } -bool Layer::prepareClientLayer(const RenderArea& /*renderArea*/, const Region& /*clip*/, - bool useIdentityTransform, Region& /*clearRegion*/, - const bool /*supportProtectedContent*/, - renderengine::LayerSettings& layer) { FloatRect bounds = getBounds(); half alpha = getAlpha(); - layer.geometry.boundaries = bounds; - if (useIdentityTransform) { - layer.geometry.positionTransform = mat4(); + renderengine::LayerSettings layerSettings; + layerSettings.geometry.boundaries = bounds; + if (targetSettings.useIdentityTransform) { + layerSettings.geometry.positionTransform = mat4(); } else { - const ui::Transform transform = getTransform(); - mat4 m; - m[0][0] = transform[0][0]; - m[0][1] = transform[0][1]; - m[0][3] = transform[0][2]; - m[1][0] = transform[1][0]; - m[1][1] = transform[1][1]; - m[1][3] = transform[1][2]; - m[3][0] = transform[2][0]; - m[3][1] = transform[2][1]; - m[3][3] = transform[2][2]; - layer.geometry.positionTransform = m; + layerSettings.geometry.positionTransform = getTransform().asMatrix4(); } if (hasColorTransform()) { - layer.colorTransform = getColorTransform(); + layerSettings.colorTransform = getColorTransform(); } const auto roundedCornerState = getRoundedCornerState(); - layer.geometry.roundedCornersRadius = roundedCornerState.radius; - layer.geometry.roundedCornersCrop = roundedCornerState.cropRect; + layerSettings.geometry.roundedCornersRadius = roundedCornerState.radius; + layerSettings.geometry.roundedCornersCrop = roundedCornerState.cropRect; - layer.alpha = alpha; - layer.sourceDataspace = mCurrentDataSpace; - return true; + layerSettings.alpha = alpha; + layerSettings.sourceDataspace = mCurrentDataSpace; + return layerSettings; } Hwc2::IComposerClient::Composition Layer::getCompositionType( diff --git a/services/surfaceflinger/Layer.h b/services/surfaceflinger/Layer.h index aa7e2f1ec3..953f25ddf1 100644 --- a/services/surfaceflinger/Layer.h +++ b/services/surfaceflinger/Layer.h @@ -461,19 +461,17 @@ public: return s.activeTransparentRegion_legacy; } virtual Rect getCrop(const Layer::State& s) const { return s.crop_legacy; } - -protected: - virtual bool prepareClientLayer(const RenderArea& renderArea, const Region& clip, - bool useIdentityTransform, Region& clearRegion, - const bool supportProtectedContent, - renderengine::LayerSettings& layer); + virtual bool needsFiltering(const sp&) const { return false; } public: /* * compositionengine::LayerFE overrides */ + bool onPreComposition(nsecs_t) override; void latchCompositionState(compositionengine::LayerFECompositionState&, bool includeGeometry) const override; + std::optional prepareClientComposition( + compositionengine::LayerFE::ClientCompositionTargetSettings&) override; void onLayerDisplayed(const sp& releaseFence) override; const char* getDebugName() const override; @@ -508,17 +506,6 @@ public: // If a buffer was replaced this frame, release the former buffer virtual void releasePendingBuffer(nsecs_t /*dequeueReadyTime*/) { } - /* - * prepareClientLayer - populates a renderengine::LayerSettings to passed to - * RenderEngine::drawLayers. Returns true if the layer can be used, and - * false otherwise. - */ - bool prepareClientLayer(const RenderArea& renderArea, const Region& clip, Region& clearRegion, - const bool supportProtectedContent, renderengine::LayerSettings& layer); - bool prepareClientLayer(const RenderArea& renderArea, bool useIdentityTransform, - Region& clearRegion, const bool supportProtectedContent, - renderengine::LayerSettings& layer); - /* * doTransaction - process the transaction. This is a good place to figure * out which attributes of the surface have changed. diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp index 1aec0c5389..d877e77832 100644 --- a/services/surfaceflinger/SurfaceFlinger.cpp +++ b/services/surfaceflinger/SurfaceFlinger.cpp @@ -3319,6 +3319,7 @@ bool SurfaceFlinger::doComposeSurfaces(const sp& displayDevice, */ ALOGV("Rendering client layers"); + const bool useIdentityTransform = false; bool firstLayer = true; Region clearRegion = Region::INVALID_REGION; for (auto& layer : displayDevice->getVisibleLayersSortedByZ()) { @@ -3339,13 +3340,20 @@ bool SurfaceFlinger::doComposeSurfaces(const sp& displayDevice, layer->getRoundedCornerState().radius == 0.0f && hasClientComposition) { // never clear the very first layer since we're // guaranteed the FB is already cleared - renderengine::LayerSettings layerSettings; Region dummyRegion; - bool prepared = - layer->prepareClientLayer(renderArea, clip, dummyRegion, - supportProtectedContent, layerSettings); - - if (prepared) { + compositionengine::LayerFE::ClientCompositionTargetSettings targetSettings{ + clip, + useIdentityTransform, + layer->needsFiltering(renderArea.getDisplayDevice()) || + renderArea.needsFiltering(), + renderArea.isSecure(), + supportProtectedContent, + dummyRegion, + }; + auto result = layer->prepareClientComposition(targetSettings); + + if (result) { + auto& layerSettings = *result; layerSettings.source.buffer.buffer = nullptr; layerSettings.source.solidColor = half3(0.0, 0.0, 0.0); layerSettings.alpha = half(0.0); @@ -3356,12 +3364,18 @@ bool SurfaceFlinger::doComposeSurfaces(const sp& displayDevice, break; } case Hwc2::IComposerClient::Composition::CLIENT: { - renderengine::LayerSettings layerSettings; - bool prepared = - layer->prepareClientLayer(renderArea, clip, clearRegion, - supportProtectedContent, layerSettings); - if (prepared) { - clientCompositionLayers.push_back(layerSettings); + compositionengine::LayerFE::ClientCompositionTargetSettings targetSettings{ + clip, + useIdentityTransform, + layer->needsFiltering(renderArea.getDisplayDevice()) || + renderArea.needsFiltering(), + renderArea.isSecure(), + supportProtectedContent, + clearRegion, + }; + auto result = layer->prepareClientComposition(targetSettings); + if (result) { + clientCompositionLayers.push_back(*result); } break; } @@ -5902,11 +5916,19 @@ void SurfaceFlinger::renderScreenImplLocked(const RenderArea& renderArea, Region clearRegion = Region::INVALID_REGION; traverseLayers([&](Layer* layer) { - renderengine::LayerSettings layerSettings; - bool prepared = layer->prepareClientLayer(renderArea, useIdentityTransform, clearRegion, - false, layerSettings); - if (prepared) { - clientCompositionLayers.push_back(layerSettings); + const bool supportProtectedContent = false; + Region clip(renderArea.getBounds()); + compositionengine::LayerFE::ClientCompositionTargetSettings targetSettings{ + clip, + useIdentityTransform, + layer->needsFiltering(renderArea.getDisplayDevice()) || renderArea.needsFiltering(), + renderArea.isSecure(), + supportProtectedContent, + clearRegion, + }; + auto result = layer->prepareClientComposition(targetSettings); + if (result) { + clientCompositionLayers.push_back(*result); } }); -- cgit v1.2.3-59-g8ed1b From b597ce56653a562f27ebf7c6856c46e5dddd4a7d Mon Sep 17 00:00:00 2001 From: Ady Abraham Date: Wed, 24 Jul 2019 18:09:29 -0700 Subject: Revert "SurfaceFlinger: debug layer bounds inset" Revert the debug patch as layer seems to ve valid. Instead validate the input to avoid an overflow. Bug: 137560795 Test: boot This reverts commit 38172ad8cf4a3dc3ee801cb295de891050993438. --- services/surfaceflinger/Layer.cpp | 27 --------------------------- 1 file changed, 27 deletions(-) (limited to 'services/surfaceflinger/Layer.cpp') diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp index a2eeea545b..0bb08d9a89 100644 --- a/services/surfaceflinger/Layer.cpp +++ b/services/surfaceflinger/Layer.cpp @@ -1965,13 +1965,6 @@ bool Layer::isRemovedFromCurrentState() const { return mRemovedFromCurrentState; } -// Debug helper for b/137560795 -#define INT32_MIGHT_OVERFLOW(n) (((n) >= INT32_MAX / 2) || ((n) <= INT32_MIN / 2)) - -#define RECT_BOUNDS_INVALID(rect) \ - (INT32_MIGHT_OVERFLOW((rect).left) || INT32_MIGHT_OVERFLOW((rect).right) || \ - INT32_MIGHT_OVERFLOW((rect).bottom) || INT32_MIGHT_OVERFLOW((rect).top)) - InputWindowInfo Layer::fillInputInfo() { InputWindowInfo info = mDrawingState.inputInfo; @@ -2001,26 +1994,6 @@ InputWindowInfo Layer::fillInputInfo() { layerBounds = getCroppedBufferSize(getDrawingState()); } layerBounds = t.transform(layerBounds); - - // debug check for b/137560795 - { - if (RECT_BOUNDS_INVALID(layerBounds)) { - ALOGE("layer %s bounds are invalid (%" PRIi32 ", %" PRIi32 ", %" PRIi32 ", %" PRIi32 - ")", - mName.c_str(), layerBounds.left, layerBounds.top, layerBounds.right, - layerBounds.bottom); - std::string out; - getTransform().dump(out, "Transform"); - ALOGE("%s", out.c_str()); - layerBounds.left = layerBounds.top = layerBounds.right = layerBounds.bottom = 0; - } - - if (INT32_MIGHT_OVERFLOW(xSurfaceInset) || INT32_MIGHT_OVERFLOW(ySurfaceInset)) { - ALOGE("layer %s surface inset are invalid (%" PRIi32 ", %" PRIi32 ")", mName.c_str(), - int32_t(xSurfaceInset), int32_t(ySurfaceInset)); - xSurfaceInset = ySurfaceInset = 0; - } - } layerBounds.inset(xSurfaceInset, ySurfaceInset, xSurfaceInset, ySurfaceInset); // Input coordinate should match the layer bounds. -- cgit v1.2.3-59-g8ed1b From 282f1d7eb2ea7346be5ffb266b24746dfb7b3c46 Mon Sep 17 00:00:00 2001 From: Ady Abraham Date: Wed, 24 Jul 2019 18:05:56 -0700 Subject: SurfaceFlinger: prevent division by 0 in Layer::fillInputInfo Check if scale is 0 before trying to apply it on the window scale. Bug: 137560795 Test: Set Window Scale Animation to off from developer options menu Change-Id: I7ae84e2838b1562ff62cdd94484bedba954e1f33 --- libs/gui/tests/EndToEndNativeInputTest.cpp | 13 +++++++++++++ services/surfaceflinger/Layer.cpp | 17 +++++++++++------ 2 files changed, 24 insertions(+), 6 deletions(-) (limited to 'services/surfaceflinger/Layer.cpp') diff --git a/libs/gui/tests/EndToEndNativeInputTest.cpp b/libs/gui/tests/EndToEndNativeInputTest.cpp index ff1ba0ad17..386f731d23 100644 --- a/libs/gui/tests/EndToEndNativeInputTest.cpp +++ b/libs/gui/tests/EndToEndNativeInputTest.cpp @@ -410,6 +410,19 @@ TEST_F(InputSurfacesTest, input_respects_scaled_surface_insets) { bgSurface->expectTap(1, 1); } +TEST_F(InputSurfacesTest, input_respects_scaled_surface_insets_overflow) { + std::unique_ptr fgSurface = makeSurface(100, 100); + // In case we pass the very big inset without any checking. + fgSurface->mInputInfo.surfaceInset = INT32_MAX; + fgSurface->showAt(100, 100); + + fgSurface->doTransaction([&](auto &t, auto &sc) { t.setMatrix(sc, 2.0, 0, 0, 2.0); }); + + // expect no crash for overflow, and inset size to be clamped to surface size + injectTap(202, 202); + fgSurface->expectTap(1, 1); +} + // Ensure we ignore transparent region when getting screen bounds when positioning input frame. TEST_F(InputSurfacesTest, input_ignores_transparent_region) { std::unique_ptr surface = makeSurface(100, 100); diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp index 0bb08d9a89..e7fbfe936d 100644 --- a/services/surfaceflinger/Layer.cpp +++ b/services/surfaceflinger/Layer.cpp @@ -1975,14 +1975,14 @@ InputWindowInfo Layer::fillInputInfo() { ui::Transform t = getTransform(); const float xScale = t.sx(); const float yScale = t.sy(); - float xSurfaceInset = info.surfaceInset; - float ySurfaceInset = info.surfaceInset; + int32_t xSurfaceInset = info.surfaceInset; + int32_t ySurfaceInset = info.surfaceInset; if (xScale != 1.0f || yScale != 1.0f) { - info.windowXScale *= 1.0f / xScale; - info.windowYScale *= 1.0f / yScale; + info.windowXScale *= (xScale != 0.0f) ? 1.0f / xScale : 0.0f; + info.windowYScale *= (yScale != 0.0f) ? 1.0f / yScale : 0.0f; info.touchableRegion.scaleSelf(xScale, yScale); - xSurfaceInset *= xScale; - ySurfaceInset *= yScale; + xSurfaceInset = std::round(xSurfaceInset * xScale); + ySurfaceInset = std::round(ySurfaceInset * yScale); } // Transform layer size to screen space and inset it by surface insets. @@ -1994,6 +1994,11 @@ InputWindowInfo Layer::fillInputInfo() { layerBounds = getCroppedBufferSize(getDrawingState()); } layerBounds = t.transform(layerBounds); + + // clamp inset to layer bounds + xSurfaceInset = (xSurfaceInset >= 0) ? std::min(xSurfaceInset, layerBounds.getWidth() / 2) : 0; + ySurfaceInset = (ySurfaceInset >= 0) ? std::min(ySurfaceInset, layerBounds.getHeight() / 2) : 0; + layerBounds.inset(xSurfaceInset, ySurfaceInset, xSurfaceInset, ySurfaceInset); // Input coordinate should match the layer bounds. -- cgit v1.2.3-59-g8ed1b From 688abd459a80ad7ec491eae024c330265f8fcc16 Mon Sep 17 00:00:00 2001 From: Lloyd Pique Date: Fri, 15 Feb 2019 15:42:24 -0800 Subject: SF: Move doComposeSurfaces to CompositionEngine Test: atest libsurfaceflinger_unittest libcompositionengine_test Bug: 121291683 Change-Id: Iae3377a5ea018f9ec53c5a76ed6a86620f39b731 --- services/surfaceflinger/BufferLayer.cpp | 2 +- .../surfaceflinger/CompositionEngine/Android.bp | 1 + .../compositionengine/DisplayCreationArgs.h | 9 + .../include/compositionengine/LayerFE.h | 2 +- .../compositionengine/LayerFECompositionState.h | 6 + .../include/compositionengine/Output.h | 14 ++ .../include/compositionengine/OutputLayer.h | 3 + .../include/compositionengine/impl/Display.h | 5 + .../include/compositionengine/impl/Output.h | 7 + .../include/compositionengine/impl/OutputLayer.h | 1 + .../include/compositionengine/mock/Output.h | 9 + .../include/compositionengine/mock/OutputLayer.h | 1 + .../CompositionEngine/src/Display.cpp | 21 ++- .../src/LayerCompositionState.cpp | 2 + .../CompositionEngine/src/Output.cpp | 188 +++++++++++++++++++- .../CompositionEngine/src/OutputLayer.cpp | 7 + .../CompositionEngine/tests/DisplayTest.cpp | 37 +++- .../CompositionEngine/tests/MockPowerAdvisor.cpp | 34 ++++ .../CompositionEngine/tests/MockPowerAdvisor.h | 37 ++++ .../CompositionEngine/tests/OutputLayerTest.cpp | 18 ++ services/surfaceflinger/DisplayDevice.cpp | 2 +- services/surfaceflinger/DisplayDevice.h | 2 + services/surfaceflinger/Layer.cpp | 8 +- services/surfaceflinger/SurfaceFlinger.cpp | 194 +-------------------- services/surfaceflinger/SurfaceFlinger.h | 6 - 25 files changed, 411 insertions(+), 205 deletions(-) create mode 100644 services/surfaceflinger/CompositionEngine/tests/MockPowerAdvisor.cpp create mode 100644 services/surfaceflinger/CompositionEngine/tests/MockPowerAdvisor.h (limited to 'services/surfaceflinger/Layer.cpp') diff --git a/services/surfaceflinger/BufferLayer.cpp b/services/surfaceflinger/BufferLayer.cpp index 87bec11609..13c748f24c 100644 --- a/services/surfaceflinger/BufferLayer.cpp +++ b/services/surfaceflinger/BufferLayer.cpp @@ -167,7 +167,7 @@ std::optional BufferLayer::prepareClientComposition } return std::nullopt; } - bool blackOutLayer = (isProtected() && !targetSettings.supportProtectedContent) || + bool blackOutLayer = (isProtected() && !targetSettings.supportsProtectedContent) || (isSecure() && !targetSettings.isSecure); const State& s(getDrawingState()); auto& layer = *result; diff --git a/services/surfaceflinger/CompositionEngine/Android.bp b/services/surfaceflinger/CompositionEngine/Android.bp index 6f076ad11f..ae6bdbce60 100644 --- a/services/surfaceflinger/CompositionEngine/Android.bp +++ b/services/surfaceflinger/CompositionEngine/Android.bp @@ -94,6 +94,7 @@ cc_test { "tests/LayerTest.cpp", "tests/MockHWC2.cpp", "tests/MockHWComposer.cpp", + "tests/MockPowerAdvisor.cpp", "tests/OutputTest.cpp", "tests/OutputLayerTest.cpp", "tests/RenderSurfaceTest.cpp", diff --git a/services/surfaceflinger/CompositionEngine/include/compositionengine/DisplayCreationArgs.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/DisplayCreationArgs.h index 0b6b4e4f0f..0778936d24 100644 --- a/services/surfaceflinger/CompositionEngine/include/compositionengine/DisplayCreationArgs.h +++ b/services/surfaceflinger/CompositionEngine/include/compositionengine/DisplayCreationArgs.h @@ -20,6 +20,7 @@ #include #include "DisplayHardware/DisplayIdentification.h" +#include "DisplayHardware/PowerAdvisor.h" namespace android::compositionengine { @@ -37,6 +38,10 @@ struct DisplayCreationArgs { // Identifies the display to the HWC, if composition is supported by it std::optional displayId; + + // Optional pointer to the power advisor interface, if one is needed for + // this display. + Hwc2::PowerAdvisor* powerAdvisor = nullptr; }; /** @@ -68,6 +73,10 @@ public: mArgs.displayId = displayId; return *this; } + DisplayCreationArgsBuilder& setPowerAdvisor(Hwc2::PowerAdvisor* powerAdvisor) { + mArgs.powerAdvisor = powerAdvisor; + return *this; + } private: DisplayCreationArgs mArgs; diff --git a/services/surfaceflinger/CompositionEngine/include/compositionengine/LayerFE.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/LayerFE.h index 94fab1fdf6..2a901ae68b 100644 --- a/services/surfaceflinger/CompositionEngine/include/compositionengine/LayerFE.h +++ b/services/surfaceflinger/CompositionEngine/include/compositionengine/LayerFE.h @@ -59,7 +59,7 @@ public: const bool isSecure; // If set to true, the target buffer has protected content support. - const bool supportProtectedContent; + const bool supportsProtectedContent; // Modified by each call to prepareClientComposition to indicate the // region of the target buffer that should be cleared. diff --git a/services/surfaceflinger/CompositionEngine/include/compositionengine/LayerFECompositionState.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/LayerFECompositionState.h index d96d58c1fa..d5763d5611 100644 --- a/services/surfaceflinger/CompositionEngine/include/compositionengine/LayerFECompositionState.h +++ b/services/surfaceflinger/CompositionEngine/include/compositionengine/LayerFECompositionState.h @@ -116,6 +116,12 @@ struct LayerFECompositionState { // The color transform mat4 colorTransform; bool colorTransformIsIdentity{true}; + + // True if the layer is completely opaque + bool isOpaque{true}; + + // True if the layer has protected content + bool hasProtectedContent{false}; }; } // namespace android::compositionengine diff --git a/services/surfaceflinger/CompositionEngine/include/compositionengine/Output.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/Output.h index 4dfcfa4593..f73304d211 100644 --- a/services/surfaceflinger/CompositionEngine/include/compositionengine/Output.h +++ b/services/surfaceflinger/CompositionEngine/include/compositionengine/Output.h @@ -22,6 +22,7 @@ #include #include +#include #include #include #include @@ -156,6 +157,12 @@ public: // Prepares a frame for display virtual void prepareFrame() = 0; + // Performs client composition as needed for layers on the output. The + // output fence is set to a fence to signal when client composition is + // finished. + // Returns false if client composition cannot be performed. + virtual bool composeSurfaces(const Region& debugFence, base::unique_fd* outReadyFence) = 0; + // Posts the new frame, and sets release fences. virtual void postFramebuffer() = 0; @@ -163,7 +170,14 @@ protected: virtual void setDisplayColorProfile(std::unique_ptr) = 0; virtual void setRenderSurface(std::unique_ptr) = 0; virtual void chooseCompositionStrategy() = 0; + virtual bool getSkipColorTransform() const = 0; virtual FrameFences presentAndGetFrameFences() = 0; + virtual std::vector generateClientCompositionRequests( + bool supportsProtectedContent, Region& clearRegion) = 0; + virtual void appendRegionFlashRequests( + const Region& flashRegion, + std::vector& clientCompositionLayers) = 0; + virtual void setExpensiveRenderingExpected(bool enabled) = 0; }; } // namespace android::compositionengine diff --git a/services/surfaceflinger/CompositionEngine/include/compositionengine/OutputLayer.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/OutputLayer.h index d7f00a978a..5f62b32c9a 100644 --- a/services/surfaceflinger/CompositionEngine/include/compositionengine/OutputLayer.h +++ b/services/surfaceflinger/CompositionEngine/include/compositionengine/OutputLayer.h @@ -93,6 +93,9 @@ public: // Applies a HWC device layer request virtual void applyDeviceLayerRequest(Hwc2::IComposerClient::LayerRequest request) = 0; + // Returns true if the composition settings scale pixels + virtual bool needsFiltering() const = 0; + // Debugging virtual void dump(std::string& result) const = 0; }; diff --git a/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/Display.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/Display.h index 795061af28..36e4aac76e 100644 --- a/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/Display.h +++ b/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/Display.h @@ -23,6 +23,7 @@ #include "DisplayHardware/DisplayIdentification.h" #include "DisplayHardware/HWComposer.h" +#include "DisplayHardware/PowerAdvisor.h" namespace android::compositionengine { @@ -42,7 +43,9 @@ public: void setColorTransform(const mat4&) override; void setColorMode(ui::ColorMode, ui::Dataspace, ui::RenderIntent, ui::Dataspace) override; void chooseCompositionStrategy() override; + bool getSkipColorTransform() const override; compositionengine::Output::FrameFences presentAndGetFrameFences() override; + void setExpensiveRenderingExpected(bool) override; // compositionengine::Display overrides const std::optional& getId() const override; @@ -65,9 +68,11 @@ public: private: const bool mIsVirtual; std::optional mId; + Hwc2::PowerAdvisor* const mPowerAdvisor{nullptr}; }; std::shared_ptr createDisplay(const compositionengine::CompositionEngine&, compositionengine::DisplayCreationArgs&&); + } // namespace impl } // namespace android::compositionengine diff --git a/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/Output.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/Output.h index 5f4a76440c..3972f2bcf4 100644 --- a/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/Output.h +++ b/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/Output.h @@ -77,6 +77,7 @@ public: void beginFrame() override; void prepareFrame() override; + bool composeSurfaces(const Region&, base::unique_fd*) override; void postFramebuffer() override; // Testing @@ -86,7 +87,13 @@ public: protected: const CompositionEngine& getCompositionEngine() const; void chooseCompositionStrategy() override; + bool getSkipColorTransform() const override; compositionengine::Output::FrameFences presentAndGetFrameFences() override; + std::vector generateClientCompositionRequests( + bool supportsProtectedContent, Region& clearRegion) override; + void appendRegionFlashRequests(const Region&, + std::vector&) override; + void setExpensiveRenderingExpected(bool enabled) override; void dumpBase(std::string&) const; private: diff --git a/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/OutputLayer.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/OutputLayer.h index d8ad02aca3..4c3f9359b0 100644 --- a/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/OutputLayer.h +++ b/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/OutputLayer.h @@ -55,6 +55,7 @@ public: void applyDeviceCompositionTypeChange(Hwc2::IComposerClient::Composition) override; void prepareForDeviceLayerRequests() override; void applyDeviceLayerRequest(Hwc2::IComposerClient::LayerRequest request) override; + bool needsFiltering() const override; void dump(std::string& result) const override; diff --git a/services/surfaceflinger/CompositionEngine/include/compositionengine/mock/Output.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/mock/Output.h index d494413af5..c944becd22 100644 --- a/services/surfaceflinger/CompositionEngine/include/compositionengine/mock/Output.h +++ b/services/surfaceflinger/CompositionEngine/include/compositionengine/mock/Output.h @@ -77,8 +77,17 @@ public: MOCK_METHOD0(prepareFrame, void()); MOCK_METHOD0(chooseCompositionStrategy, void()); + MOCK_METHOD2(composeSurfaces, bool(const Region&, base::unique_fd*)); + MOCK_CONST_METHOD0(getSkipColorTransform, bool()); + MOCK_METHOD0(postFramebuffer, void()); MOCK_METHOD0(presentAndGetFrameFences, compositionengine::Output::FrameFences()); + + MOCK_METHOD2(generateClientCompositionRequests, + std::vector(bool, Region&)); + MOCK_METHOD2(appendRegionFlashRequests, + void(const Region&, std::vector&)); + MOCK_METHOD1(setExpensiveRenderingExpected, void(bool)); }; } // namespace android::compositionengine::mock diff --git a/services/surfaceflinger/CompositionEngine/include/compositionengine/mock/OutputLayer.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/mock/OutputLayer.h index 195648ff7c..d8d637d302 100644 --- a/services/surfaceflinger/CompositionEngine/include/compositionengine/mock/OutputLayer.h +++ b/services/surfaceflinger/CompositionEngine/include/compositionengine/mock/OutputLayer.h @@ -46,6 +46,7 @@ public: MOCK_METHOD1(applyDeviceCompositionTypeChange, void(Hwc2::IComposerClient::Composition)); MOCK_METHOD0(prepareForDeviceLayerRequests, void()); MOCK_METHOD1(applyDeviceLayerRequest, void(Hwc2::IComposerClient::LayerRequest request)); + MOCK_CONST_METHOD0(needsFiltering, bool()); MOCK_CONST_METHOD1(dump, void(std::string&)); }; diff --git a/services/surfaceflinger/CompositionEngine/src/Display.cpp b/services/surfaceflinger/CompositionEngine/src/Display.cpp index 68319013d7..6cd392eabd 100644 --- a/services/surfaceflinger/CompositionEngine/src/Display.cpp +++ b/services/surfaceflinger/CompositionEngine/src/Display.cpp @@ -26,6 +26,7 @@ #include #include "DisplayHardware/HWComposer.h" +#include "DisplayHardware/PowerAdvisor.h" namespace android::compositionengine::impl { @@ -38,7 +39,8 @@ std::shared_ptr createDisplay( Display::Display(const CompositionEngine& compositionEngine, DisplayCreationArgs&& args) : compositionengine::impl::Output(compositionEngine), mIsVirtual(args.isVirtual), - mId(args.displayId) { + mId(args.displayId), + mPowerAdvisor(args.powerAdvisor) { editState().isSecure = args.isSecure; } @@ -160,6 +162,15 @@ void Display::chooseCompositionStrategy() { state.usesDeviceComposition = !allLayersRequireClientComposition(); } +bool Display::getSkipColorTransform() const { + if (!mId) { + return false; + } + + auto& hwc = getCompositionEngine().getHwComposer(); + return hwc.hasDisplayCapability(*mId, HWC2::DisplayCapability::SkipClientColorTransform); +} + bool Display::anyLayersRequireClientComposition() const { const auto& layers = getOutputLayersOrderedByZ(); return std::any_of(layers.cbegin(), layers.cend(), @@ -240,4 +251,12 @@ compositionengine::Output::FrameFences Display::presentAndGetFrameFences() { return result; } +void Display::setExpensiveRenderingExpected(bool enabled) { + Output::setExpensiveRenderingExpected(enabled); + + if (mPowerAdvisor && mId) { + mPowerAdvisor->setExpensiveRenderingExpected(*mId, enabled); + } +} + } // namespace android::compositionengine::impl diff --git a/services/surfaceflinger/CompositionEngine/src/LayerCompositionState.cpp b/services/surfaceflinger/CompositionEngine/src/LayerCompositionState.cpp index 37d6eaa2f2..0dc4bf1559 100644 --- a/services/surfaceflinger/CompositionEngine/src/LayerCompositionState.cpp +++ b/services/surfaceflinger/CompositionEngine/src/LayerCompositionState.cpp @@ -71,6 +71,8 @@ void dumpFrontEnd(std::string& out, const LayerFECompositionState& state) { dumpVal(out, "color", state.color); out.append("\n "); + dumpVal(out, "isOpaque", state.isOpaque); + dumpVal(out, "hasProtectedContent", state.hasProtectedContent); dumpVal(out, "isColorspaceAgnostic", state.isColorspaceAgnostic); dumpVal(out, "dataspace", toString(state.dataspace), state.dataspace); dumpVal(out, "hdr metadata types", state.hdrMetadata.validTypes); diff --git a/services/surfaceflinger/CompositionEngine/src/Output.cpp b/services/surfaceflinger/CompositionEngine/src/Output.cpp index 6878e99b72..fb576e06f8 100644 --- a/services/surfaceflinger/CompositionEngine/src/Output.cpp +++ b/services/surfaceflinger/CompositionEngine/src/Output.cpp @@ -17,13 +17,20 @@ #include #include #include +#include #include #include +#include #include #include +#include +#include #include +#include #include +#include "TracedOrdinal.h" + namespace android::compositionengine { Output::~Output() = default; @@ -73,10 +80,10 @@ void Output::setProjection(const ui::Transform& transform, int32_t orientation, dirtyEntireOutput(); } -// TODO(lpique): Rename setSize() once more is moved. +// TODO(b/121291683): Rename setSize() once more is moved. void Output::setBounds(const ui::Size& size) { mRenderSurface->setDisplaySize(size); - // TODO(lpique): Rename mState.size once more is moved. + // TODO(b/121291683): Rename mState.size once more is moved. mState.bounds = Rect(mRenderSurface->getSize()); dirtyEntireOutput(); @@ -292,6 +299,179 @@ void Output::prepareFrame() { mRenderSurface->prepareFrame(mState.usesClientComposition, mState.usesDeviceComposition); } +bool Output::composeSurfaces(const Region& debugRegion, base::unique_fd* readyFence) { + ATRACE_CALL(); + ALOGV(__FUNCTION__); + + const TracedOrdinal hasClientComposition = {"hasClientComposition", + mState.usesClientComposition}; + if (!hasClientComposition) { + return true; + } + + ALOGV("hasClientComposition"); + + auto& renderEngine = mCompositionEngine.getRenderEngine(); + const bool supportsProtectedContent = renderEngine.supportsProtectedContent(); + + renderengine::DisplaySettings clientCompositionDisplay; + clientCompositionDisplay.physicalDisplay = mState.frame; + clientCompositionDisplay.clip = mState.scissor; + clientCompositionDisplay.globalTransform = mState.transform.asMatrix4(); + clientCompositionDisplay.orientation = mState.orientation; + clientCompositionDisplay.outputDataspace = + mDisplayColorProfile->hasWideColorGamut() ? mState.dataspace : ui::Dataspace::UNKNOWN; + clientCompositionDisplay.maxLuminance = + mDisplayColorProfile->getHdrCapabilities().getDesiredMaxLuminance(); + + // Compute the global color transform matrix. + if (!mState.usesDeviceComposition && !getSkipColorTransform()) { + clientCompositionDisplay.colorTransform = mState.colorTransformMat; + } + + // Note: Updated by generateClientCompositionRequests + clientCompositionDisplay.clearRegion = Region::INVALID_REGION; + + // Generate the client composition requests for the layers on this output. + std::vector clientCompositionLayers = + generateClientCompositionRequests(supportsProtectedContent, + clientCompositionDisplay.clearRegion); + appendRegionFlashRequests(debugRegion, clientCompositionLayers); + + // If we the display is secure, protected content support is enabled, and at + // least one layer has protected content, we need to use a secure back + // buffer. + if (mState.isSecure && supportsProtectedContent) { + bool needsProtected = + std::any_of(mOutputLayersOrderedByZ.begin(), mOutputLayersOrderedByZ.end(), + [](auto& layer) { + return layer->getLayer().getState().frontEnd.hasProtectedContent; + }); + if (needsProtected != renderEngine.isProtected()) { + renderEngine.useProtectedContext(needsProtected); + } + if (needsProtected != mRenderSurface->isProtected() && + needsProtected == renderEngine.isProtected()) { + mRenderSurface->setProtected(needsProtected); + } + } + + base::unique_fd fd; + sp buf = mRenderSurface->dequeueBuffer(&fd); + if (buf == nullptr) { + ALOGW("Dequeuing buffer for display [%s] failed, bailing out of " + "client composition for this frame", + mName.c_str()); + return false; + } + + // We boost GPU frequency here because there will be color spaces conversion + // and it's expensive. We boost the GPU frequency so that GPU composition can + // finish in time. We must reset GPU frequency afterwards, because high frequency + // consumes extra battery. + const bool expensiveRenderingExpected = + clientCompositionDisplay.outputDataspace == ui::Dataspace::DISPLAY_P3; + if (expensiveRenderingExpected) { + setExpensiveRenderingExpected(true); + } + + renderEngine.drawLayers(clientCompositionDisplay, clientCompositionLayers, + buf->getNativeBuffer(), /*useFramebufferCache=*/true, std::move(fd), + readyFence); + + if (expensiveRenderingExpected) { + setExpensiveRenderingExpected(false); + } + + return true; +} + +std::vector Output::generateClientCompositionRequests( + bool supportsProtectedContent, Region& clearRegion) { + std::vector clientCompositionLayers; + ALOGV("Rendering client layers"); + + const Region viewportRegion(mState.viewport); + const bool useIdentityTransform = false; + bool firstLayer = true; + // Used when a layer clears part of the buffer. + Region dummyRegion; + + for (auto& layer : mOutputLayersOrderedByZ) { + const auto& layerState = layer->getState(); + const auto& layerFEState = layer->getLayer().getState().frontEnd; + auto& layerFE = layer->getLayerFE(); + + const Region clip(viewportRegion.intersect(layer->getState().visibleRegion)); + ALOGV("Layer: %s", layerFE.getDebugName()); + if (clip.isEmpty()) { + ALOGV(" Skipping for empty clip"); + firstLayer = false; + continue; + } + + bool clientComposition = layer->requiresClientComposition(); + + // We clear the client target for non-client composed layers if + // requested by the HWC. We skip this if the layer is not an opaque + // rectangle, as by definition the layer must blend with whatever is + // underneath. We also skip the first layer as the buffer target is + // guaranteed to start out cleared. + bool clearClientComposition = + layerState.clearClientTarget && layerFEState.isOpaque && !firstLayer; + + ALOGV(" Composition type: client %d clear %d", clientComposition, clearClientComposition); + + if (clientComposition || clearClientComposition) { + compositionengine::LayerFE::ClientCompositionTargetSettings targetSettings{ + clip, + useIdentityTransform, + layer->needsFiltering() || mState.needsFiltering, + mState.isSecure, + supportsProtectedContent, + clientComposition ? clearRegion : dummyRegion, + }; + if (auto result = layerFE.prepareClientComposition(targetSettings)) { + if (clearClientComposition) { + auto& layerSettings = *result; + layerSettings.source.buffer.buffer = nullptr; + layerSettings.source.solidColor = half3(0.0, 0.0, 0.0); + layerSettings.alpha = half(0.0); + layerSettings.disableBlending = true; + } + + clientCompositionLayers.push_back(*result); + } + } + + firstLayer = false; + } + + return clientCompositionLayers; +} + +void Output::appendRegionFlashRequests( + const Region& flashRegion, + std::vector& clientCompositionLayers) { + if (flashRegion.isEmpty()) { + return; + } + + renderengine::LayerSettings layerSettings; + layerSettings.source.buffer.buffer = nullptr; + layerSettings.source.solidColor = half3(1.0, 0.0, 1.0); + layerSettings.alpha = half(1.0); + + for (const auto& rect : flashRegion) { + layerSettings.geometry.boundaries = rect.toFloatRect(); + clientCompositionLayers.push_back(layerSettings); + } +} + +void Output::setExpensiveRenderingExpected(bool) { + // The base class does nothing with this call. +} + void Output::postFramebuffer() { ATRACE_CALL(); ALOGV(__FUNCTION__); @@ -353,6 +533,10 @@ void Output::chooseCompositionStrategy() { mState.usesDeviceComposition = false; } +bool Output::getSkipColorTransform() const { + return true; +} + compositionengine::Output::FrameFences Output::presentAndGetFrameFences() { compositionengine::Output::FrameFences result; if (mState.usesClientComposition) { diff --git a/services/surfaceflinger/CompositionEngine/src/OutputLayer.cpp b/services/surfaceflinger/CompositionEngine/src/OutputLayer.cpp index 6e744b948f..e721cf5375 100644 --- a/services/surfaceflinger/CompositionEngine/src/OutputLayer.cpp +++ b/services/surfaceflinger/CompositionEngine/src/OutputLayer.cpp @@ -614,6 +614,13 @@ void OutputLayer::applyDeviceLayerRequest(Hwc2::IComposerClient::LayerRequest re } } +bool OutputLayer::needsFiltering() const { + const auto& displayFrame = mState.displayFrame; + const auto& sourceCrop = mState.sourceCrop; + return sourceCrop.getHeight() != displayFrame.getHeight() || + sourceCrop.getWidth() != displayFrame.getWidth(); +} + void OutputLayer::dump(std::string& out) const { using android::base::StringAppendF; diff --git a/services/surfaceflinger/CompositionEngine/tests/DisplayTest.cpp b/services/surfaceflinger/CompositionEngine/tests/DisplayTest.cpp index e3be0d7a9c..743da8207a 100644 --- a/services/surfaceflinger/CompositionEngine/tests/DisplayTest.cpp +++ b/services/surfaceflinger/CompositionEngine/tests/DisplayTest.cpp @@ -30,6 +30,7 @@ #include "MockHWC2.h" #include "MockHWComposer.h" +#include "MockPowerAdvisor.h" namespace android::compositionengine { namespace { @@ -59,6 +60,7 @@ struct DisplayTest : public testing::Test { } StrictMock mHwComposer; + StrictMock mPowerAdvisor; StrictMock mCompositionEngine; sp mNativeWindow = new StrictMock(); StrictMock mHWC2Layer1; @@ -68,7 +70,10 @@ struct DisplayTest : public testing::Test { mock::OutputLayer* mLayer2 = new StrictMock(); mock::OutputLayer* mLayer3 = new StrictMock(); impl::Display mDisplay{mCompositionEngine, - DisplayCreationArgsBuilder().setDisplayId(DEFAULT_DISPLAY_ID).build()}; + DisplayCreationArgsBuilder() + .setDisplayId(DEFAULT_DISPLAY_ID) + .setPowerAdvisor(&mPowerAdvisor) + .build()}; }; /* @@ -343,6 +348,24 @@ TEST_F(DisplayChooseCompositionStrategyTest, normalOperationWithChanges) { EXPECT_TRUE(state.usesDeviceComposition); } +/* + * Display::getSkipColorTransform() + */ + +TEST_F(DisplayTest, getSkipColorTransformDoesNothingIfNonHwcDisplay) { + auto nonHwcDisplay{ + impl::createDisplay(mCompositionEngine, DisplayCreationArgsBuilder().build())}; + EXPECT_FALSE(nonHwcDisplay->getSkipColorTransform()); +} + +TEST_F(DisplayTest, getSkipColorTransformChecksHwcCapability) { + EXPECT_CALL(mHwComposer, + hasDisplayCapability(std::make_optional(DEFAULT_DISPLAY_ID), + HWC2::DisplayCapability::SkipClientColorTransform)) + .WillOnce(Return(true)); + EXPECT_TRUE(mDisplay.getSkipColorTransform()); +} + /* * Display::anyLayersRequireClientComposition() */ @@ -502,5 +525,17 @@ TEST_F(DisplayTest, presentAndGetFrameFencesReturnsPresentAndLayerFences) { EXPECT_EQ(layer2Fence, result.layerFences[&mHWC2Layer2]); } +/* + * Display::setExpensiveRenderingExpected() + */ + +TEST_F(DisplayTest, setExpensiveRenderingExpectedForwardsToPowerAdvisor) { + EXPECT_CALL(mPowerAdvisor, setExpensiveRenderingExpected(DEFAULT_DISPLAY_ID, true)).Times(1); + mDisplay.setExpensiveRenderingExpected(true); + + EXPECT_CALL(mPowerAdvisor, setExpensiveRenderingExpected(DEFAULT_DISPLAY_ID, false)).Times(1); + mDisplay.setExpensiveRenderingExpected(false); +} + } // namespace } // namespace android::compositionengine diff --git a/services/surfaceflinger/CompositionEngine/tests/MockPowerAdvisor.cpp b/services/surfaceflinger/CompositionEngine/tests/MockPowerAdvisor.cpp new file mode 100644 index 0000000000..85b94031c3 --- /dev/null +++ b/services/surfaceflinger/CompositionEngine/tests/MockPowerAdvisor.cpp @@ -0,0 +1,34 @@ +/* + * Copyright 2019 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 "MockPowerAdvisor.h" + +namespace android { +namespace Hwc2 { + +// This will go away once PowerAdvisor is moved into the "backend" library +PowerAdvisor::~PowerAdvisor() = default; + +namespace mock { + +// The Google Mock documentation recommends explicit non-header instantiations +// for better compile time performance. +PowerAdvisor::PowerAdvisor() = default; +PowerAdvisor::~PowerAdvisor() = default; + +} // namespace mock +} // namespace Hwc2 +} // namespace android diff --git a/services/surfaceflinger/CompositionEngine/tests/MockPowerAdvisor.h b/services/surfaceflinger/CompositionEngine/tests/MockPowerAdvisor.h new file mode 100644 index 0000000000..c5a73f22f9 --- /dev/null +++ b/services/surfaceflinger/CompositionEngine/tests/MockPowerAdvisor.h @@ -0,0 +1,37 @@ +/* + * Copyright 2019 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 + +#include "DisplayHardware/PowerAdvisor.h" + +namespace android { +namespace Hwc2 { +namespace mock { + +class PowerAdvisor : public android::Hwc2::PowerAdvisor { +public: + PowerAdvisor(); + ~PowerAdvisor() override; + + MOCK_METHOD2(setExpensiveRenderingExpected, void(DisplayId displayId, bool expected)); +}; + +} // namespace mock +} // namespace Hwc2 +} // namespace android diff --git a/services/surfaceflinger/CompositionEngine/tests/OutputLayerTest.cpp b/services/surfaceflinger/CompositionEngine/tests/OutputLayerTest.cpp index a5428ad993..c83cae65fb 100644 --- a/services/surfaceflinger/CompositionEngine/tests/OutputLayerTest.cpp +++ b/services/surfaceflinger/CompositionEngine/tests/OutputLayerTest.cpp @@ -875,5 +875,23 @@ TEST_F(OutputLayerTest, applyDeviceLayerRequestHandlesUnknownRequest) { EXPECT_FALSE(mOutputLayer.getState().clearClientTarget); } +/* + * OutputLayer::needsFiltering() + */ + +TEST_F(OutputLayerTest, needsFilteringReturnsFalseIfDisplaySizeSameAsSourceSize) { + mOutputLayer.editState().displayFrame = Rect(100, 100, 200, 200); + mOutputLayer.editState().sourceCrop = FloatRect{0.f, 0.f, 100.f, 100.f}; + + EXPECT_FALSE(mOutputLayer.needsFiltering()); +} + +TEST_F(OutputLayerTest, needsFilteringReturnsTrueIfDisplaySizeDifferentFromSourceSize) { + mOutputLayer.editState().displayFrame = Rect(100, 100, 200, 200); + mOutputLayer.editState().sourceCrop = FloatRect{0.f, 0.f, 100.1f, 100.1f}; + + EXPECT_TRUE(mOutputLayer.needsFiltering()); +} + } // namespace } // namespace android::compositionengine diff --git a/services/surfaceflinger/DisplayDevice.cpp b/services/surfaceflinger/DisplayDevice.cpp index d1365627cf..b6d79d41f2 100644 --- a/services/surfaceflinger/DisplayDevice.cpp +++ b/services/surfaceflinger/DisplayDevice.cpp @@ -60,7 +60,7 @@ DisplayDevice::DisplayDevice(DisplayDeviceCreationArgs&& args) mDisplayInstallOrientation(args.displayInstallOrientation), mCompositionDisplay{mFlinger->getCompositionEngine().createDisplay( compositionengine::DisplayCreationArgs{args.isSecure, args.isVirtual, - args.displayId})}, + args.displayId, args.powerAdvisor})}, mIsVirtual(args.isVirtual), mOrientation(), mActiveConfig(0), diff --git a/services/surfaceflinger/DisplayDevice.h b/services/surfaceflinger/DisplayDevice.h index 8bc19d4447..4321e3dd13 100644 --- a/services/surfaceflinger/DisplayDevice.h +++ b/services/surfaceflinger/DisplayDevice.h @@ -40,6 +40,7 @@ #include #include "DisplayHardware/DisplayIdentification.h" +#include "DisplayHardware/PowerAdvisor.h" #include "RenderArea.h" namespace android { @@ -241,6 +242,7 @@ struct DisplayDeviceCreationArgs { std::unordered_map> hwcColorModes; int initialPowerMode{HWC_POWER_MODE_NORMAL}; bool isPrimary{false}; + Hwc2::PowerAdvisor* powerAdvisor{nullptr}; }; class DisplayRenderArea : public RenderArea { diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp index e7fbfe936d..a2ee763c4a 100644 --- a/services/surfaceflinger/Layer.cpp +++ b/services/surfaceflinger/Layer.cpp @@ -440,6 +440,7 @@ void Layer::latchGeometry(compositionengine::LayerFECompositionState& compositio } void Layer::latchPerFrameState(compositionengine::LayerFECompositionState& compositionState) const { + const auto& drawingState{getDrawingState()}; compositionState.forceClientComposition = false; // TODO(lpique): b/121291683 Remove this one we are sure we don't need the @@ -451,9 +452,14 @@ void Layer::latchPerFrameState(compositionengine::LayerFECompositionState& compo compositionState.colorTransform = getColorTransform(); compositionState.colorTransformIsIdentity = !hasColorTransform(); compositionState.surfaceDamage = surfaceDamageRegion; + compositionState.hasProtectedContent = isProtected(); + + const bool usesRoundedCorners = getRoundedCornerState().radius != 0.f; + compositionState.isOpaque = + isOpaque(drawingState) && !usesRoundedCorners && getAlpha() == 1.0_hf; // Force client composition for special cases known only to the front-end. - if (isHdrY410() || getRoundedCornerState().radius > 0.0f) { + if (isHdrY410() || usesRoundedCorners) { compositionState.forceClientComposition = true; } } diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp index d2d9ea5d26..af4fa98b0d 100644 --- a/services/surfaceflinger/SurfaceFlinger.cpp +++ b/services/surfaceflinger/SurfaceFlinger.cpp @@ -1943,7 +1943,7 @@ void SurfaceFlinger::doDebugFlashRegions(const sp& displayDevice, if (!dirtyRegion.isEmpty()) { base::unique_fd readyFence; // redraw the whole screen - doComposeSurfaces(displayDevice, dirtyRegion, &readyFence); + display->composeSurfaces(dirtyRegion, &readyFence); display->getRenderSurface()->queueBuffer(std::move(readyFence)); } @@ -2488,6 +2488,7 @@ sp SurfaceFlinger::setupNewDisplayDeviceInternal( creationArgs.displaySurface = dispSurface; creationArgs.hasWideColorGamut = false; creationArgs.supportedPerFrameMetadata = 0; + creationArgs.powerAdvisor = displayId ? &mPowerAdvisor : nullptr; const bool isInternalDisplay = displayId && displayId == getInternalDisplayIdLocked(); creationArgs.isPrimary = isInternalDisplay; @@ -3228,201 +3229,12 @@ void SurfaceFlinger::doDisplayComposition(const sp& displayDevice ALOGV("doDisplayComposition"); base::unique_fd readyFence; - if (!doComposeSurfaces(displayDevice, Region::INVALID_REGION, &readyFence)) return; + if (!display->composeSurfaces(Region::INVALID_REGION, &readyFence)) return; // swap buffers (presentation) display->getRenderSurface()->queueBuffer(std::move(readyFence)); } -bool SurfaceFlinger::doComposeSurfaces(const sp& displayDevice, - const Region& debugRegion, base::unique_fd* readyFence) { - ATRACE_CALL(); - ALOGV("doComposeSurfaces"); - - auto display = displayDevice->getCompositionDisplay(); - const auto& displayState = display->getState(); - const auto displayId = display->getId(); - auto& renderEngine = getRenderEngine(); - const bool supportProtectedContent = renderEngine.supportsProtectedContent(); - - const Region bounds(displayState.bounds); - const DisplayRenderArea renderArea(displayDevice); - const TracedOrdinal hasClientComposition = {"hasClientComposition", - displayState.usesClientComposition}; - bool applyColorMatrix = false; - - renderengine::DisplaySettings clientCompositionDisplay; - std::vector clientCompositionLayers; - sp buf; - base::unique_fd fd; - - if (hasClientComposition) { - ALOGV("hasClientComposition"); - - if (displayDevice->isPrimary() && supportProtectedContent) { - bool needsProtected = false; - for (auto& layer : displayDevice->getVisibleLayersSortedByZ()) { - // If the layer is a protected layer, mark protected context is needed. - if (layer->isProtected()) { - needsProtected = true; - break; - } - } - if (needsProtected != renderEngine.isProtected()) { - renderEngine.useProtectedContext(needsProtected); - } - if (needsProtected != display->getRenderSurface()->isProtected() && - needsProtected == renderEngine.isProtected()) { - display->getRenderSurface()->setProtected(needsProtected); - } - } - - buf = display->getRenderSurface()->dequeueBuffer(&fd); - - if (buf == nullptr) { - ALOGW("Dequeuing buffer for display [%s] failed, bailing out of " - "client composition for this frame", - displayDevice->getDisplayName().c_str()); - return false; - } - - clientCompositionDisplay.physicalDisplay = displayState.scissor; - clientCompositionDisplay.clip = displayState.scissor; - const ui::Transform& displayTransform = displayState.transform; - clientCompositionDisplay.globalTransform = displayTransform.asMatrix4(); - clientCompositionDisplay.orientation = displayState.orientation; - - const auto* profile = display->getDisplayColorProfile(); - Dataspace outputDataspace = Dataspace::UNKNOWN; - if (profile->hasWideColorGamut()) { - outputDataspace = displayState.dataspace; - } - clientCompositionDisplay.outputDataspace = outputDataspace; - clientCompositionDisplay.maxLuminance = - profile->getHdrCapabilities().getDesiredMaxLuminance(); - - const bool hasDeviceComposition = displayState.usesDeviceComposition; - const bool skipClientColorTransform = - getHwComposer() - .hasDisplayCapability(displayId, - HWC2::DisplayCapability::SkipClientColorTransform); - - // Compute the global color transform matrix. - applyColorMatrix = !hasDeviceComposition && !skipClientColorTransform; - if (applyColorMatrix) { - clientCompositionDisplay.colorTransform = displayState.colorTransformMat; - } - } - - /* - * and then, render the layers targeted at the framebuffer - */ - - ALOGV("Rendering client layers"); - const bool useIdentityTransform = false; - bool firstLayer = true; - Region clearRegion = Region::INVALID_REGION; - for (auto& layer : displayDevice->getVisibleLayersSortedByZ()) { - const Region viewportRegion(displayState.viewport); - const Region clip(viewportRegion.intersect(layer->visibleRegion)); - ALOGV("Layer: %s", layer->getName().string()); - ALOGV(" Composition type: %s", toString(layer->getCompositionType(displayDevice)).c_str()); - if (!clip.isEmpty()) { - switch (layer->getCompositionType(displayDevice)) { - case Hwc2::IComposerClient::Composition::CURSOR: - case Hwc2::IComposerClient::Composition::DEVICE: - case Hwc2::IComposerClient::Composition::SIDEBAND: - case Hwc2::IComposerClient::Composition::SOLID_COLOR: { - LOG_ALWAYS_FATAL_IF(!displayId); - const Layer::State& state(layer->getDrawingState()); - if (layer->getClearClientTarget(displayDevice) && !firstLayer && - layer->isOpaque(state) && (layer->getAlpha() == 1.0f) && - layer->getRoundedCornerState().radius == 0.0f && hasClientComposition) { - // never clear the very first layer since we're - // guaranteed the FB is already cleared - Region dummyRegion; - compositionengine::LayerFE::ClientCompositionTargetSettings targetSettings{ - clip, - useIdentityTransform, - layer->needsFiltering(renderArea.getDisplayDevice()) || - renderArea.needsFiltering(), - renderArea.isSecure(), - supportProtectedContent, - dummyRegion, - }; - auto result = layer->prepareClientComposition(targetSettings); - - if (result) { - auto& layerSettings = *result; - layerSettings.source.buffer.buffer = nullptr; - layerSettings.source.solidColor = half3(0.0, 0.0, 0.0); - layerSettings.alpha = half(0.0); - layerSettings.disableBlending = true; - clientCompositionLayers.push_back(layerSettings); - } - } - break; - } - case Hwc2::IComposerClient::Composition::CLIENT: { - compositionengine::LayerFE::ClientCompositionTargetSettings targetSettings{ - clip, - useIdentityTransform, - layer->needsFiltering(renderArea.getDisplayDevice()) || - renderArea.needsFiltering(), - renderArea.isSecure(), - supportProtectedContent, - clearRegion, - }; - auto result = layer->prepareClientComposition(targetSettings); - if (result) { - clientCompositionLayers.push_back(*result); - } - break; - } - default: - break; - } - } else { - ALOGV(" Skipping for empty clip"); - } - firstLayer = false; - } - - // Perform some cleanup steps if we used client composition. - if (hasClientComposition) { - clientCompositionDisplay.clearRegion = clearRegion; - - // We boost GPU frequency here because there will be color spaces conversion - // and it's expensive. We boost the GPU frequency so that GPU composition can - // finish in time. We must reset GPU frequency afterwards, because high frequency - // consumes extra battery. - const bool expensiveRenderingExpected = - clientCompositionDisplay.outputDataspace == Dataspace::DISPLAY_P3; - if (expensiveRenderingExpected && displayId) { - mPowerAdvisor.setExpensiveRenderingExpected(*displayId, true); - } - if (!debugRegion.isEmpty()) { - Region::const_iterator it = debugRegion.begin(); - Region::const_iterator end = debugRegion.end(); - while (it != end) { - const Rect& rect = *it++; - renderengine::LayerSettings layerSettings; - layerSettings.source.buffer.buffer = nullptr; - layerSettings.source.solidColor = half3(1.0, 0.0, 1.0); - layerSettings.geometry.boundaries = rect.toFloatRect(); - layerSettings.alpha = half(1.0); - clientCompositionLayers.push_back(layerSettings); - } - } - renderEngine.drawLayers(clientCompositionDisplay, clientCompositionLayers, - buf->getNativeBuffer(), /*useFramebufferCache=*/true, std::move(fd), - readyFence); - } else if (displayId) { - mPowerAdvisor.setExpensiveRenderingExpected(*displayId, false); - } - return true; -} - status_t SurfaceFlinger::addClientLayer(const sp& client, const sp& handle, const sp& gbc, const sp& lbc, const sp& parentHandle, diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h index 64e87b14ed..ef096f85a5 100644 --- a/services/surfaceflinger/SurfaceFlinger.h +++ b/services/surfaceflinger/SurfaceFlinger.h @@ -768,12 +768,6 @@ private: void logLayerStats(); void doDisplayComposition(const sp& display, const Region& dirtyRegion); - // This fails if using GL and the surface has been destroyed. readyFence - // will be populated if using GL and native fence sync is supported, to - // signal when drawing has completed. - bool doComposeSurfaces(const sp& display, const Region& debugRegionm, - base::unique_fd* readyFence); - void postFrame(); /* ------------------------------------------------------------------------ -- cgit v1.2.3-59-g8ed1b From 3a904b83ef41770d0a6d8bd03cc3857dc76caf64 Mon Sep 17 00:00:00 2001 From: Yiwei Zhang Date: Thu, 8 Aug 2019 17:51:47 -0700 Subject: SurfaceFlinger: get rid of LayerStats LayerStats is not in use, so let's just remove it. If later SurfaceTracing has been moved back to main thread, we could probably plumb HWC layer stats into SurfaceTracing. For now, if we are interested in any statistical HWC stats, we could add that into TimeStats so that we get the stats from the field as well. Test: build, flash and boot Change-Id: Iff418f60bc22d8867294f919699300cf25eee258 --- services/surfaceflinger/Android.bp | 1 - services/surfaceflinger/Layer.cpp | 29 --- services/surfaceflinger/Layer.h | 5 - services/surfaceflinger/LayerStats.cpp | 233 --------------------- services/surfaceflinger/LayerStats.h | 75 ------- services/surfaceflinger/SurfaceFlinger.cpp | 47 ----- services/surfaceflinger/SurfaceFlinger.h | 4 - .../surfaceflinger/layerproto/LayerProtoParser.cpp | 14 -- .../include/layerproto/LayerProtoParser.h | 13 -- services/surfaceflinger/layerproto/layers.proto | 4 - 10 files changed, 425 deletions(-) delete mode 100644 services/surfaceflinger/LayerStats.cpp delete mode 100644 services/surfaceflinger/LayerStats.h (limited to 'services/surfaceflinger/Layer.cpp') diff --git a/services/surfaceflinger/Android.bp b/services/surfaceflinger/Android.bp index 965d8f4f0e..afb9cec4cc 100644 --- a/services/surfaceflinger/Android.bp +++ b/services/surfaceflinger/Android.bp @@ -138,7 +138,6 @@ filegroup { "Layer.cpp", "LayerProtoHelper.cpp", "LayerRejecter.cpp", - "LayerStats.cpp", "LayerVector.cpp", "MonitoredProducer.cpp", "NativeWindowSurface.cpp", diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp index e7fbfe936d..e6b7b08c83 100644 --- a/services/surfaceflinger/Layer.cpp +++ b/services/surfaceflinger/Layer.cpp @@ -1932,35 +1932,6 @@ void Layer::writeToProtoCommonState(LayerProto* layerInfo, LayerVector::StateSet } } -void Layer::writeToProtoCompositionState(LayerProto* layerInfo, - const sp& displayDevice, - uint32_t traceFlags) const { - auto outputLayer = findOutputLayerForDisplay(displayDevice); - if (!outputLayer) { - return; - } - - writeToProtoDrawingState(layerInfo, traceFlags); - writeToProtoCommonState(layerInfo, LayerVector::StateSet::Drawing, traceFlags); - - const auto& compositionState = outputLayer->getState(); - - const Rect& frame = compositionState.displayFrame; - LayerProtoHelper::writeToProto(frame, [&]() { return layerInfo->mutable_hwc_frame(); }); - - const FloatRect& crop = compositionState.sourceCrop; - LayerProtoHelper::writeToProto(crop, [&]() { return layerInfo->mutable_hwc_crop(); }); - - const int32_t transform = - getCompositionLayer() ? static_cast(compositionState.bufferTransform) : 0; - layerInfo->set_hwc_transform(transform); - - const int32_t compositionType = - static_cast(compositionState.hwc ? (*compositionState.hwc).hwcCompositionType - : Hwc2::IComposerClient::Composition::CLIENT); - layerInfo->set_hwc_composition_type(compositionType); -} - bool Layer::isRemovedFromCurrentState() const { return mRemovedFromCurrentState; } diff --git a/services/surfaceflinger/Layer.h b/services/surfaceflinger/Layer.h index 953f25ddf1..c9cb4444db 100644 --- a/services/surfaceflinger/Layer.h +++ b/services/surfaceflinger/Layer.h @@ -440,11 +440,6 @@ public: // thread. void writeToProtoDrawingState(LayerProto* layerInfo, uint32_t traceFlags = SurfaceTracing::TRACE_ALL) const; - // Write states that are modified by the main thread. This includes drawing - // state as well as buffer data and composition data for layers on the specified - // display. This should be called in the main or tracing thread. - void writeToProtoCompositionState(LayerProto* layerInfo, const sp& displayDevice, - uint32_t traceFlags = SurfaceTracing::TRACE_ALL) const; // Write drawing or current state. If writing current state, the caller should hold the // external mStateLock. If writing drawing state, this function should be called on the // main or tracing thread. diff --git a/services/surfaceflinger/LayerStats.cpp b/services/surfaceflinger/LayerStats.cpp deleted file mode 100644 index a2d1feb40d..0000000000 --- a/services/surfaceflinger/LayerStats.cpp +++ /dev/null @@ -1,233 +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. - */ -#undef LOG_TAG -#define LOG_TAG "LayerStats" -#define ATRACE_TAG ATRACE_TAG_GRAPHICS - -#include "LayerStats.h" -#include "DisplayHardware/HWComposer.h" -#include "ui/DebugUtils.h" - -#include -#include -#include - -namespace android { - -using base::StringAppendF; -using base::StringPrintf; - -void LayerStats::enable() { - ATRACE_CALL(); - std::lock_guard lock(mMutex); - if (mEnabled) return; - mLayerShapeStatsMap.clear(); - mEnabled = true; - ALOGD("Logging enabled"); -} - -void LayerStats::disable() { - ATRACE_CALL(); - std::lock_guard lock(mMutex); - if (!mEnabled) return; - mEnabled = false; - ALOGD("Logging disabled"); -} - -void LayerStats::clear() { - ATRACE_CALL(); - std::lock_guard lock(mMutex); - mLayerShapeStatsMap.clear(); - ALOGD("Cleared current layer stats"); -} - -bool LayerStats::isEnabled() { - return mEnabled; -} - -void LayerStats::traverseLayerTreeStatsLocked( - const std::vector& layerTree, - const LayerProtoParser::LayerGlobal& layerGlobal, - std::vector* const outLayerShapeVec) { - for (const auto& layer : layerTree) { - if (!layer) continue; - traverseLayerTreeStatsLocked(layer->children, layerGlobal, outLayerShapeVec); - std::string key = ""; - StringAppendF(&key, ",%s", layer->type.c_str()); - StringAppendF(&key, ",%s", layerCompositionType(layer->hwcCompositionType)); - StringAppendF(&key, ",%d", layer->isProtected); - StringAppendF(&key, ",%s", layerTransform(layer->hwcTransform)); - StringAppendF(&key, ",%s", layerPixelFormat(layer->activeBuffer.format).c_str()); - StringAppendF(&key, ",%s", layer->dataspace.c_str()); - StringAppendF(&key, ",%s", - destinationLocation(layer->hwcFrame.left, layerGlobal.resolution[0], true)); - StringAppendF(&key, ",%s", - destinationLocation(layer->hwcFrame.top, layerGlobal.resolution[1], false)); - StringAppendF(&key, ",%s", - destinationSize(layer->hwcFrame.right - layer->hwcFrame.left, - layerGlobal.resolution[0], true)); - StringAppendF(&key, ",%s", - destinationSize(layer->hwcFrame.bottom - layer->hwcFrame.top, - layerGlobal.resolution[1], false)); - StringAppendF(&key, ",%s", scaleRatioWH(layer).c_str()); - StringAppendF(&key, ",%s", alpha(static_cast(layer->color.a))); - - outLayerShapeVec->push_back(key); - ALOGV("%s", key.c_str()); - } -} - -void LayerStats::logLayerStats(const LayersProto& layersProto) { - ATRACE_CALL(); - ALOGV("Logging"); - auto layerGlobal = LayerProtoParser::generateLayerGlobalInfo(layersProto); - auto layerTree = LayerProtoParser::generateLayerTree(layersProto); - std::vector layerShapeVec; - - std::lock_guard lock(mMutex); - traverseLayerTreeStatsLocked(layerTree.topLevelLayers, layerGlobal, &layerShapeVec); - - std::string layerShapeKey = - StringPrintf("%d,%s,%s,%s", static_cast(layerShapeVec.size()), - layerGlobal.colorMode.c_str(), layerGlobal.colorTransform.c_str(), - layerTransform(layerGlobal.globalTransform)); - ALOGV("%s", layerShapeKey.c_str()); - - std::sort(layerShapeVec.begin(), layerShapeVec.end(), std::greater()); - for (auto const& s : layerShapeVec) { - layerShapeKey += s; - } - - mLayerShapeStatsMap[layerShapeKey]++; -} - -void LayerStats::dump(std::string& result) { - ATRACE_CALL(); - ALOGD("Dumping"); - std::lock_guard lock(mMutex); - result.append("Frequency,LayerCount,ColorMode,ColorTransform,Orientation\n"); - result.append("LayerType,CompositionType,IsProtected,Transform,PixelFormat,Dataspace,"); - result.append("DstX,DstY,DstWidth,DstHeight,WScale,HScale,Alpha\n"); - for (auto& u : mLayerShapeStatsMap) { - StringAppendF(&result, "%u,%s\n", u.second, u.first.c_str()); - } -} - -const char* LayerStats::destinationLocation(int32_t location, int32_t range, bool isHorizontal) { - static const char* locationArray[8] = {"0", "1/8", "1/4", "3/8", "1/2", "5/8", "3/4", "7/8"}; - int32_t ratio = location * 8 / range; - if (ratio < 0) return "N/A"; - if (isHorizontal) { - // X location is divided into 4 buckets {"0", "1/4", "1/2", "3/4"} - if (ratio > 6) return "3/4"; - // use index 0, 2, 4, 6 - return locationArray[ratio & ~1]; - } - if (ratio > 7) return "7/8"; - return locationArray[ratio]; -} - -const char* LayerStats::destinationSize(int32_t size, int32_t range, bool isWidth) { - static const char* sizeArray[8] = {"1/8", "1/4", "3/8", "1/2", "5/8", "3/4", "7/8", "1"}; - int32_t ratio = size * 8 / range; - if (ratio < 0) return "N/A"; - if (isWidth) { - // width is divided into 4 buckets {"1/4", "1/2", "3/4", "1"} - if (ratio > 6) return "1"; - // use index 1, 3, 5, 7 - return sizeArray[ratio | 1]; - } - if (ratio > 7) return "1"; - return sizeArray[ratio]; -} - -const char* LayerStats::layerTransform(int32_t transform) { - return getTransformName(static_cast(transform)); -} - -const char* LayerStats::layerCompositionType(int32_t compositionType) { - return getCompositionName(static_cast(compositionType)); -} - -std::string LayerStats::layerPixelFormat(int32_t pixelFormat) { - return decodePixelFormat(pixelFormat); -} - -std::string LayerStats::scaleRatioWH(const LayerProtoParser::Layer* layer) { - if (!layer->type.compare("ColorLayer")) return "N/A,N/A"; - std::string ret = ""; - if (isRotated(layer->hwcTransform)) { - ret += scaleRatio(layer->hwcFrame.right - layer->hwcFrame.left, - static_cast(layer->hwcCrop.bottom - layer->hwcCrop.top)); - ret += ","; - ret += scaleRatio(layer->hwcFrame.bottom - layer->hwcFrame.top, - static_cast(layer->hwcCrop.right - layer->hwcCrop.left)); - } else { - ret += scaleRatio(layer->hwcFrame.right - layer->hwcFrame.left, - static_cast(layer->hwcCrop.right - layer->hwcCrop.left)); - ret += ","; - ret += scaleRatio(layer->hwcFrame.bottom - layer->hwcFrame.top, - static_cast(layer->hwcCrop.bottom - layer->hwcCrop.top)); - } - return ret; -} - -const char* LayerStats::scaleRatio(int32_t destinationScale, int32_t sourceScale) { - // Make scale buckets from <1/64 to >= 16, to avoid floating point - // calculation, x64 on destinationScale first - int32_t scale = destinationScale * 64 / sourceScale; - if (!scale) return "<1/64"; - if (scale < 2) return "1/64"; - if (scale < 4) return "1/32"; - if (scale < 8) return "1/16"; - if (scale < 16) return "1/8"; - if (scale < 32) return "1/4"; - if (scale < 64) return "1/2"; - if (scale < 128) return "1"; - if (scale < 256) return "2"; - if (scale < 512) return "4"; - if (scale < 1024) return "8"; - return ">=16"; -} - -const char* LayerStats::alpha(float a) { - if (a == 1.0f) return "1.0"; - if (a > 0.9f) return "0.99"; - if (a > 0.8f) return "0.9"; - if (a > 0.7f) return "0.8"; - if (a > 0.6f) return "0.7"; - if (a > 0.5f) return "0.6"; - if (a > 0.4f) return "0.5"; - if (a > 0.3f) return "0.4"; - if (a > 0.2f) return "0.3"; - if (a > 0.1f) return "0.2"; - if (a > 0.0f) return "0.1"; - return "0.0"; -} - -bool LayerStats::isRotated(int32_t transform) { - return transform & HWC_TRANSFORM_ROT_90; -} - -bool LayerStats::isVFlipped(int32_t transform) { - return transform & HWC_TRANSFORM_FLIP_V; -} - -bool LayerStats::isHFlipped(int32_t transform) { - return transform & HWC_TRANSFORM_FLIP_H; -} - -} // namespace android diff --git a/services/surfaceflinger/LayerStats.h b/services/surfaceflinger/LayerStats.h deleted file mode 100644 index 62b2688936..0000000000 --- a/services/surfaceflinger/LayerStats.h +++ /dev/null @@ -1,75 +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 -#include -#include -#include - -using namespace android::surfaceflinger; - -namespace android { - -class LayerStats { -public: - void enable(); - void disable(); - void clear(); - bool isEnabled(); - void logLayerStats(const LayersProto& layersProto); - void dump(std::string& result); - -private: - // Traverse layer tree to get all visible layers' stats - void traverseLayerTreeStatsLocked( - const std::vector& layerTree, - const LayerProtoParser::LayerGlobal& layerGlobal, - std::vector* const outLayerShapeVec); - // Convert layer's top-left position into 8x8 percentage of the display - static const char* destinationLocation(int32_t location, int32_t range, bool isHorizontal); - // Convert layer's size into 8x8 percentage of the display - static const char* destinationSize(int32_t size, int32_t range, bool isWidth); - // Return the name of the transform - static const char* layerTransform(int32_t transform); - // Return the name of the composition type - static const char* layerCompositionType(int32_t compositionType); - // Return the name of the pixel format - static std::string layerPixelFormat(int32_t pixelFormat); - // Calculate scale ratios of layer's width/height with rotation information - static std::string scaleRatioWH(const LayerProtoParser::Layer* layer); - // Calculate scale ratio from source to destination and convert to string - static const char* scaleRatio(int32_t destinationScale, int32_t sourceScale); - // Bucket the alpha into designed buckets - static const char* alpha(float a); - // Return whether the original buffer is rotated in final composition - static bool isRotated(int32_t transform); - // Return whether the original buffer is V-flipped in final composition - static bool isVFlipped(int32_t transform); - // Return whether the original buffer is H-flipped in final composition - static bool isHFlipped(int32_t transform); - - bool mEnabled = false; - // Protect mLayersStatsMap - std::mutex mMutex; - // Hashmap for tracking the frame(layer shape) stats - // KEY is a concatenation of all layers' properties within a frame - // VALUE is the number of times this particular set has been scanned out - std::unordered_map mLayerShapeStatsMap; -}; - -} // namespace android diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp index 213160de6e..f30c7d6720 100644 --- a/services/surfaceflinger/SurfaceFlinger.cpp +++ b/services/surfaceflinger/SurfaceFlinger.cpp @@ -1798,8 +1798,6 @@ void SurfaceFlinger::handleMessageRefresh() { doComposition(displayDevice, repaintEverything); } - logLayerStats(); - postFrame(); postComposition(); @@ -1958,20 +1956,6 @@ void SurfaceFlinger::doDebugFlashRegions(const sp& displayDevice, displayDevice->getCompositionDisplay()->prepareFrame(); } -void SurfaceFlinger::logLayerStats() { - ATRACE_CALL(); - if (CC_UNLIKELY(mLayerStats.isEnabled())) { - for (const auto& [token, display] : mDisplays) { - if (display->isPrimary()) { - mLayerStats.logLayerStats(dumpVisibleLayersProtoInfo(display)); - return; - } - } - - ALOGE("logLayerStats: no primary display"); - } -} - void SurfaceFlinger::updateCompositorTiming(const DisplayStatInfo& stats, nsecs_t compositeTime, std::shared_ptr& presentFenceTime) { // Update queue of past composite+present times and determine the @@ -4465,14 +4449,10 @@ status_t SurfaceFlinger::doDump(int fd, const DumpArgs& args, using namespace std::string_literals; static const std::unordered_map dumpers = { - {"--clear-layer-stats"s, dumper([this](std::string&) { mLayerStats.clear(); })}, - {"--disable-layer-stats"s, dumper([this](std::string&) { mLayerStats.disable(); })}, {"--display-id"s, dumper(&SurfaceFlinger::dumpDisplayIdentificationData)}, {"--dispsync"s, dumper([this](std::string& s) { mScheduler->dumpPrimaryDispSync(s); })}, - {"--dump-layer-stats"s, dumper([this](std::string& s) { mLayerStats.dump(s); })}, - {"--enable-layer-stats"s, dumper([this](std::string&) { mLayerStats.enable(); })}, {"--frame-events"s, dumper(&SurfaceFlinger::dumpFrameEventsLocked)}, {"--latency"s, argsDumper(&SurfaceFlinger::dumpStatsLocked)}, {"--latency-clear"s, argsDumper(&SurfaceFlinger::clearStatsLocked)}, @@ -4763,33 +4743,6 @@ LayersProto SurfaceFlinger::dumpProtoFromMainThread(uint32_t traceFlags) { return layersProto; } -LayersProto SurfaceFlinger::dumpVisibleLayersProtoInfo( - const sp& displayDevice) const { - LayersProto layersProto; - - SizeProto* resolution = layersProto.mutable_resolution(); - resolution->set_w(displayDevice->getWidth()); - resolution->set_h(displayDevice->getHeight()); - - auto display = displayDevice->getCompositionDisplay(); - const auto& displayState = display->getState(); - - layersProto.set_color_mode(decodeColorMode(displayState.colorMode)); - layersProto.set_color_transform(decodeColorTransform(displayState.colorTransform)); - layersProto.set_global_transform(displayState.orientation); - - const auto displayId = displayDevice->getId(); - LOG_ALWAYS_FATAL_IF(!displayId); - mDrawingState.traverseInZOrder([&](Layer* layer) { - if (!layer->visibleRegion.isEmpty() && !display->getOutputLayersOrderedByZ().empty()) { - LayerProto* layerProto = layersProto.add_layers(); - layer->writeToProtoCompositionState(layerProto, displayDevice); - } - }); - - return layersProto; -} - void SurfaceFlinger::dumpAllLocked(const DumpArgs& args, std::string& result) const { const bool colorize = !args.empty() && args[0] == String16("--color"); Colorizer colorizer(colorize); diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h index 3974a8cf08..677cfb55b9 100644 --- a/services/surfaceflinger/SurfaceFlinger.h +++ b/services/surfaceflinger/SurfaceFlinger.h @@ -52,7 +52,6 @@ #include "DisplayHardware/PowerAdvisor.h" #include "Effects/Daltonizer.h" #include "FrameTracker.h" -#include "LayerStats.h" #include "LayerVector.h" #include "Scheduler/RefreshRateConfigs.h" #include "Scheduler/RefreshRateStats.h" @@ -762,7 +761,6 @@ private: void calculateWorkingSet(); void doComposition(const sp& display, bool repainEverything); void doDebugFlashRegions(const sp& display, bool repaintEverything); - void logLayerStats(); void doDisplayComposition(const sp& display, const Region& dirtyRegion); // This fails if using GL and the surface has been destroyed. readyFence @@ -884,7 +882,6 @@ private: LayersProto dumpProtoFromMainThread(uint32_t traceFlags = SurfaceTracing::TRACE_ALL) EXCLUDES(mStateLock); void withTracingLock(std::function operation) REQUIRES(mStateLock); - LayersProto dumpVisibleLayersProtoInfo(const sp& display) const; bool isLayerTripleBufferingDisabled() const { return this->mLayerTripleBufferingDisabled; @@ -1001,7 +998,6 @@ private: SurfaceTracing mTracing{*this}; bool mTracingEnabled = false; bool mTracingEnabledChanged GUARDED_BY(mStateLock) = false; - LayerStats mLayerStats; const std::shared_ptr mTimeStats; bool mUseHwcVirtualDisplays = false; std::atomic mFrameMissedCount = 0; diff --git a/services/surfaceflinger/layerproto/LayerProtoParser.cpp b/services/surfaceflinger/layerproto/LayerProtoParser.cpp index d3381e5757..ef488bd881 100644 --- a/services/surfaceflinger/layerproto/LayerProtoParser.cpp +++ b/services/surfaceflinger/layerproto/LayerProtoParser.cpp @@ -37,16 +37,6 @@ bool sortLayers(LayerProtoParser::Layer* lhs, const LayerProtoParser::Layer* rhs return lhs->id < rhs->id; } -const LayerProtoParser::LayerGlobal LayerProtoParser::generateLayerGlobalInfo( - const LayersProto& layersProto) { - LayerGlobal layerGlobal; - layerGlobal.resolution = {layersProto.resolution().w(), layersProto.resolution().h()}; - layerGlobal.colorMode = layersProto.color_mode(); - layerGlobal.colorTransform = layersProto.color_transform(); - layerGlobal.globalTransform = layersProto.global_transform(); - return layerGlobal; -} - LayerProtoParser::LayerTree LayerProtoParser::generateLayerTree(const LayersProto& layersProto) { LayerTree layerTree; layerTree.allLayers = generateLayerList(layersProto); @@ -114,10 +104,6 @@ LayerProtoParser::Layer LayerProtoParser::generateLayer(const LayerProto& layerP layer.bufferTransform = generateTransform(layerProto.buffer_transform()); layer.queuedFrames = layerProto.queued_frames(); layer.refreshPending = layerProto.refresh_pending(); - layer.hwcFrame = generateRect(layerProto.hwc_frame()); - layer.hwcCrop = generateFloatRect(layerProto.hwc_crop()); - layer.hwcTransform = layerProto.hwc_transform(); - layer.hwcCompositionType = layerProto.hwc_composition_type(); layer.isProtected = layerProto.is_protected(); layer.cornerRadius = layerProto.corner_radius(); for (const auto& entry : layerProto.metadata()) { diff --git a/services/surfaceflinger/layerproto/include/layerproto/LayerProtoParser.h b/services/surfaceflinger/layerproto/include/layerproto/LayerProtoParser.h index d1b2b1ffed..54e02cadee 100644 --- a/services/surfaceflinger/layerproto/include/layerproto/LayerProtoParser.h +++ b/services/surfaceflinger/layerproto/include/layerproto/LayerProtoParser.h @@ -108,10 +108,6 @@ public: Transform bufferTransform; int32_t queuedFrames; bool refreshPending; - LayerProtoParser::Rect hwcFrame; - LayerProtoParser::FloatRect hwcCrop; - int32_t hwcTransform; - int32_t hwcCompositionType; bool isProtected; float cornerRadius; LayerMetadata metadata; @@ -119,14 +115,6 @@ public: std::string to_string() const; }; - class LayerGlobal { - public: - int2 resolution; - std::string colorMode; - std::string colorTransform; - int32_t globalTransform; - }; - class LayerTree { public: // all layers in LayersProto and in the original order @@ -136,7 +124,6 @@ public: std::vector topLevelLayers; }; - static const LayerGlobal generateLayerGlobalInfo(const LayersProto& layersProto); static LayerTree generateLayerTree(const LayersProto& layersProto); static std::string layerTreeToString(const LayerTree& layerTree); diff --git a/services/surfaceflinger/layerproto/layers.proto b/services/surfaceflinger/layerproto/layers.proto index b097505bbc..c7fbff37da 100644 --- a/services/surfaceflinger/layerproto/layers.proto +++ b/services/surfaceflinger/layerproto/layers.proto @@ -7,10 +7,6 @@ package android.surfaceflinger; // Contains a list of all layers. message LayersProto { repeated LayerProto layers = 1; - SizeProto resolution = 2; - string color_mode = 3; - string color_transform = 4; - int32 global_transform = 5; } // Information about each layer. -- cgit v1.2.3-59-g8ed1b From 7e0a01fbf4a28002aaff787a533e341606f27b31 Mon Sep 17 00:00:00 2001 From: Marissa Wall Date: Wed, 14 Aug 2019 14:29:25 -0700 Subject: blast: default to surface damage to invalid SurfaceDamage should be invalid unless set. Invalid SurfaceDamage forces HWC to assume the whole buffer is damaged. Clearing the damage tells HWC the buffer hasn't changed at all. Bug: 139311175 Test: Repro steps in https://b.corp.google.com/issues/139311175#comment1 Change-Id: Ifcb84d8a974994c8d5204c34933b4b3390f13af5 --- services/surfaceflinger/Layer.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'services/surfaceflinger/Layer.cpp') diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp index a2eeea545b..7dfc3a7864 100644 --- a/services/surfaceflinger/Layer.cpp +++ b/services/surfaceflinger/Layer.cpp @@ -105,7 +105,7 @@ Layer::Layer(const LayerCreationArgs& args) mCurrentState.acquireFence = new Fence(-1); mCurrentState.dataspace = ui::Dataspace::UNKNOWN; mCurrentState.hdrMetadata.validTypes = 0; - mCurrentState.surfaceDamageRegion.clear(); + mCurrentState.surfaceDamageRegion = Region::INVALID_REGION; mCurrentState.cornerRadius = 0.0f; mCurrentState.api = -1; mCurrentState.hasColorTransform = false; -- cgit v1.2.3-59-g8ed1b From 8a01fa4d881170628a32b2aa201b06e46c4b4eb0 Mon Sep 17 00:00:00 2001 From: chaviw Date: Mon, 19 Aug 2019 12:39:31 -0700 Subject: Update typeId for BufferQueueLayer and BufferStateLayer Currently BufferQueueLayer and BufferStateLayer have typeId BufferLayer. Changed to use more specific typeIds so they can be identified when dumping state. Also renamed getTypeId to getType since it was not returning an ID, but rather a char* name Test: adb shell dumpsys SurfaceFlinger Change-Id: Ic80e995fa37acb2a9f21ea91bae8608657bf0bf1 --- services/surfaceflinger/BufferLayer.h | 4 ---- services/surfaceflinger/BufferQueueLayer.h | 2 ++ services/surfaceflinger/BufferStateLayer.h | 2 ++ services/surfaceflinger/ColorLayer.h | 2 +- services/surfaceflinger/ContainerLayer.h | 2 +- services/surfaceflinger/Layer.cpp | 6 +++--- services/surfaceflinger/Layer.h | 4 +++- 7 files changed, 12 insertions(+), 10 deletions(-) (limited to 'services/surfaceflinger/Layer.cpp') diff --git a/services/surfaceflinger/BufferLayer.h b/services/surfaceflinger/BufferLayer.h index fb8d7d027f..ee44cbe836 100644 --- a/services/surfaceflinger/BufferLayer.h +++ b/services/surfaceflinger/BufferLayer.h @@ -62,10 +62,6 @@ public: void useSurfaceDamage() override; void useEmptyDamage() override; - // getTypeId - Provide unique string for each class type in the Layer - // hierarchy - const char* getTypeId() const override { return "BufferLayer"; } - bool isOpaque(const Layer::State& s) const override; // isVisible - true if this layer is visible, false otherwise diff --git a/services/surfaceflinger/BufferQueueLayer.h b/services/surfaceflinger/BufferQueueLayer.h index 392b706416..3bc625e462 100644 --- a/services/surfaceflinger/BufferQueueLayer.h +++ b/services/surfaceflinger/BufferQueueLayer.h @@ -38,6 +38,8 @@ public: // Interface implementation for Layer // ----------------------------------------------------------------------- public: + const char* getType() const override { return "BufferQueueLayer"; } + void onLayerDisplayed(const sp& releaseFence) override; void setTransformHint(uint32_t orientation) const override; diff --git a/services/surfaceflinger/BufferStateLayer.h b/services/surfaceflinger/BufferStateLayer.h index 0ee941e6d7..cc670087ac 100644 --- a/services/surfaceflinger/BufferStateLayer.h +++ b/services/surfaceflinger/BufferStateLayer.h @@ -40,6 +40,8 @@ public: // ----------------------------------------------------------------------- // Interface implementation for Layer // ----------------------------------------------------------------------- + const char* getType() const override { return "BufferStateLayer"; } + void onLayerDisplayed(const sp& releaseFence) override; void setTransformHint(uint32_t orientation) const override; void releasePendingBuffer(nsecs_t dequeueReadyTime) override; diff --git a/services/surfaceflinger/ColorLayer.h b/services/surfaceflinger/ColorLayer.h index c793142957..57c54c7e2c 100644 --- a/services/surfaceflinger/ColorLayer.h +++ b/services/surfaceflinger/ColorLayer.h @@ -30,7 +30,7 @@ public: std::shared_ptr getCompositionLayer() const override; - virtual const char* getTypeId() const { return "ColorLayer"; } + const char* getType() const override { return "ColorLayer"; } bool isVisible() const override; bool setColor(const half3& color) override; diff --git a/services/surfaceflinger/ContainerLayer.h b/services/surfaceflinger/ContainerLayer.h index a1607ffabb..f0fbb6104f 100644 --- a/services/surfaceflinger/ContainerLayer.h +++ b/services/surfaceflinger/ContainerLayer.h @@ -28,7 +28,7 @@ public: explicit ContainerLayer(const LayerCreationArgs&); ~ContainerLayer() override; - const char* getTypeId() const override { return "ContainerLayer"; } + const char* getType() const override { return "ContainerLayer"; } bool isVisible() const override; bool canReceiveInput() const override; diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp index db4ae41bc8..5121835cae 100644 --- a/services/surfaceflinger/Layer.cpp +++ b/services/surfaceflinger/Layer.cpp @@ -1217,7 +1217,7 @@ LayerDebugInfo Layer::getLayerDebugInfo() const { info.mName = getName(); sp parent = getParent(); info.mParentName = (parent == nullptr ? std::string("none") : parent->getName().string()); - info.mType = std::string(getTypeId()); + info.mType = getType(); info.mTransparentRegion = ds.activeTransparentRegion_legacy; info.mVisibleRegion = visibleRegion; info.mSurfaceDamageRegion = surfaceDamageRegion; @@ -1334,7 +1334,7 @@ void Layer::getFrameStats(FrameStats* outStats) const { } void Layer::dumpFrameEvents(std::string& result) { - StringAppendF(&result, "- Layer %s (%s, %p)\n", getName().string(), getTypeId(), this); + StringAppendF(&result, "- Layer %s (%s, %p)\n", getName().string(), getType(), this); Mutex::Autolock lock(mFrameEventHistoryMutex); mFrameEventHistory.checkFencesForCompletion(); mFrameEventHistory.dump(result); @@ -1868,7 +1868,7 @@ void Layer::writeToProtoCommonState(LayerProto* layerInfo, LayerVector::StateSet if (traceFlags & SurfaceTracing::TRACE_CRITICAL) { layerInfo->set_id(sequence); layerInfo->set_name(getName().c_str()); - layerInfo->set_type(String8(getTypeId())); + layerInfo->set_type(getType()); for (const auto& child : children) { layerInfo->add_children(child->sequence); diff --git a/services/surfaceflinger/Layer.h b/services/surfaceflinger/Layer.h index 53091a0392..9107189d52 100644 --- a/services/surfaceflinger/Layer.h +++ b/services/surfaceflinger/Layer.h @@ -378,7 +378,9 @@ public: // ----------------------------------------------------------------------- // Virtuals - virtual const char* getTypeId() const = 0; + + // Provide unique string for each class type in the Layer hierarchy + virtual const char* getType() const = 0; /* * isOpaque - true if this surface is opaque -- cgit v1.2.3-59-g8ed1b From c7b0c75f80c5cd5e1de1b7911981061bfd672f6e Mon Sep 17 00:00:00 2001 From: Lloyd Pique Date: Thu, 7 Mar 2019 20:59:59 -0800 Subject: SF: Move/Refactor updateCursorAsync to CompositionEngine As part of this change, the existing LayerFE::latchCompositionState is extended to allow for more state types to be fetched. Test: atest libsurfaceflinger_unittest libcompositionengine_test Bug: 121291683 Change-Id: I71e0f547440a64c1025f36741beb68e72c18e475 --- .../include/compositionengine/CompositionEngine.h | 3 + .../include/compositionengine/LayerFE.h | 4 ++ .../compositionengine/LayerFECompositionState.h | 7 ++ .../include/compositionengine/OutputLayer.h | 6 ++ .../compositionengine/impl/CompositionEngine.h | 2 + .../include/compositionengine/impl/OutputLayer.h | 2 + .../compositionengine/mock/CompositionEngine.h | 1 + .../include/compositionengine/mock/LayerFE.h | 1 + .../include/compositionengine/mock/OutputLayer.h | 2 + .../CompositionEngine/src/CompositionEngine.cpp | 17 +++++ .../CompositionEngine/src/OutputLayer.cpp | 26 +++++++ .../CompositionEngine/tests/OutputLayerTest.cpp | 79 ++++++++++++++++++++++ services/surfaceflinger/Layer.cpp | 47 ++++--------- services/surfaceflinger/Layer.h | 2 +- services/surfaceflinger/SurfaceFlinger.cpp | 13 ++-- 15 files changed, 172 insertions(+), 40 deletions(-) (limited to 'services/surfaceflinger/Layer.cpp') diff --git a/services/surfaceflinger/CompositionEngine/include/compositionengine/CompositionEngine.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/CompositionEngine.h index 31d6365bf4..298aff57a9 100644 --- a/services/surfaceflinger/CompositionEngine/include/compositionengine/CompositionEngine.h +++ b/services/surfaceflinger/CompositionEngine/include/compositionengine/CompositionEngine.h @@ -58,6 +58,9 @@ public: virtual bool needsAnotherUpdate() const = 0; virtual nsecs_t getLastFrameRefreshTimestamp() const = 0; + // Updates the cursor position for the indicated outputs. + virtual void updateCursorAsync(CompositionRefreshArgs&) = 0; + // TODO(b/121291683): These will become private/internal virtual void preComposition(CompositionRefreshArgs&) = 0; }; diff --git a/services/surfaceflinger/CompositionEngine/include/compositionengine/LayerFE.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/LayerFE.h index 2a901ae68b..db4f9698e2 100644 --- a/services/surfaceflinger/CompositionEngine/include/compositionengine/LayerFE.h +++ b/services/surfaceflinger/CompositionEngine/include/compositionengine/LayerFE.h @@ -43,6 +43,10 @@ public: // geometry state can be skipped. virtual void latchCompositionState(LayerFECompositionState&, bool includeGeometry) const = 0; + // Latches the minimal bit of state for the cursor for a fast asynchronous + // update. + virtual void latchCursorCompositionState(LayerFECompositionState&) const = 0; + struct ClientCompositionTargetSettings { // The clip region, or visible region that is being rendered to const Region& clip; diff --git a/services/surfaceflinger/CompositionEngine/include/compositionengine/LayerFECompositionState.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/LayerFECompositionState.h index d5763d5611..6a0caf0746 100644 --- a/services/surfaceflinger/CompositionEngine/include/compositionengine/LayerFECompositionState.h +++ b/services/surfaceflinger/CompositionEngine/include/compositionengine/LayerFECompositionState.h @@ -122,6 +122,13 @@ struct LayerFECompositionState { // True if the layer has protected content bool hasProtectedContent{false}; + + /* + * Cursor state + */ + + // The output-independent frame for the cursor + Rect cursorFrame; }; } // namespace android::compositionengine diff --git a/services/surfaceflinger/CompositionEngine/include/compositionengine/OutputLayer.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/OutputLayer.h index 5f62b32c9a..cedd728588 100644 --- a/services/surfaceflinger/CompositionEngine/include/compositionengine/OutputLayer.h +++ b/services/surfaceflinger/CompositionEngine/include/compositionengine/OutputLayer.h @@ -78,12 +78,18 @@ public: // skipped. virtual void writeStateToHWC(bool includeGeometry) = 0; + // Updates the cursor position with the HWC + virtual void writeCursorPositionToHWC() const = 0; + // Returns the HWC2::Layer associated with this layer, if it exists virtual HWC2::Layer* getHwcLayer() const = 0; // Returns true if the current layer state requires client composition virtual bool requiresClientComposition() const = 0; + // Returns true if the current layer should be treated as a cursor layer + virtual bool isHardwareCursor() const = 0; + // Applies a HWC device requested composition type change virtual void applyDeviceCompositionTypeChange(Hwc2::IComposerClient::Composition) = 0; diff --git a/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/CompositionEngine.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/CompositionEngine.h index 96e609d1c9..982a37604d 100644 --- a/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/CompositionEngine.h +++ b/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/CompositionEngine.h @@ -39,6 +39,8 @@ public: bool needsAnotherUpdate() const override; nsecs_t getLastFrameRefreshTimestamp() const override; + void updateCursorAsync(CompositionRefreshArgs&) override; + void preComposition(CompositionRefreshArgs&) override; // Testing diff --git a/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/OutputLayer.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/OutputLayer.h index 4c3f9359b0..fa4d8cd6db 100644 --- a/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/OutputLayer.h +++ b/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/OutputLayer.h @@ -49,9 +49,11 @@ public: void updateCompositionState(bool) override; void writeStateToHWC(bool) override; + void writeCursorPositionToHWC() const override; HWC2::Layer* getHwcLayer() const override; bool requiresClientComposition() const override; + bool isHardwareCursor() const override; void applyDeviceCompositionTypeChange(Hwc2::IComposerClient::Composition) override; void prepareForDeviceLayerRequests() override; void applyDeviceLayerRequest(Hwc2::IComposerClient::LayerRequest request) override; diff --git a/services/surfaceflinger/CompositionEngine/include/compositionengine/mock/CompositionEngine.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/mock/CompositionEngine.h index 82ecec502d..6450b222dc 100644 --- a/services/surfaceflinger/CompositionEngine/include/compositionengine/mock/CompositionEngine.h +++ b/services/surfaceflinger/CompositionEngine/include/compositionengine/mock/CompositionEngine.h @@ -44,6 +44,7 @@ public: MOCK_CONST_METHOD0(needsAnotherUpdate, bool()); MOCK_CONST_METHOD0(getLastFrameRefreshTimestamp, nsecs_t()); + MOCK_METHOD1(updateCursorAsync, void(CompositionRefreshArgs&)); MOCK_METHOD1(preComposition, void(CompositionRefreshArgs&)); }; diff --git a/services/surfaceflinger/CompositionEngine/include/compositionengine/mock/LayerFE.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/mock/LayerFE.h index 48c2dbf3d6..e2802954d6 100644 --- a/services/surfaceflinger/CompositionEngine/include/compositionengine/mock/LayerFE.h +++ b/services/surfaceflinger/CompositionEngine/include/compositionengine/mock/LayerFE.h @@ -33,6 +33,7 @@ public: MOCK_METHOD1(onPreComposition, bool(nsecs_t)); MOCK_CONST_METHOD2(latchCompositionState, void(LayerFECompositionState&, bool)); + MOCK_CONST_METHOD1(latchCursorCompositionState, void(LayerFECompositionState&)); MOCK_METHOD1(prepareClientComposition, std::optional( compositionengine::LayerFE::ClientCompositionTargetSettings&)); diff --git a/services/surfaceflinger/CompositionEngine/include/compositionengine/mock/OutputLayer.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/mock/OutputLayer.h index d8d637d302..6b2224ac60 100644 --- a/services/surfaceflinger/CompositionEngine/include/compositionengine/mock/OutputLayer.h +++ b/services/surfaceflinger/CompositionEngine/include/compositionengine/mock/OutputLayer.h @@ -40,9 +40,11 @@ public: MOCK_METHOD1(updateCompositionState, void(bool)); MOCK_METHOD1(writeStateToHWC, void(bool)); + MOCK_CONST_METHOD0(writeCursorPositionToHWC, void()); MOCK_CONST_METHOD0(getHwcLayer, HWC2::Layer*()); MOCK_CONST_METHOD0(requiresClientComposition, bool()); + MOCK_CONST_METHOD0(isHardwareCursor, bool()); MOCK_METHOD1(applyDeviceCompositionTypeChange, void(Hwc2::IComposerClient::Composition)); MOCK_METHOD0(prepareForDeviceLayerRequests, void()); MOCK_METHOD1(applyDeviceLayerRequest, void(Hwc2::IComposerClient::LayerRequest request)); diff --git a/services/surfaceflinger/CompositionEngine/src/CompositionEngine.cpp b/services/surfaceflinger/CompositionEngine/src/CompositionEngine.cpp index 9558266a34..8bc3a349ca 100644 --- a/services/surfaceflinger/CompositionEngine/src/CompositionEngine.cpp +++ b/services/surfaceflinger/CompositionEngine/src/CompositionEngine.cpp @@ -16,6 +16,7 @@ #include #include +#include #include #include #include @@ -70,6 +71,22 @@ nsecs_t CompositionEngine::getLastFrameRefreshTimestamp() const { return mRefreshStartTime; } +void CompositionEngine::updateCursorAsync(CompositionRefreshArgs& args) { + std::unordered_map + uniqueVisibleLayers; + + for (const auto& output : args.outputs) { + for (auto& layer : output->getOutputLayersOrderedByZ()) { + if (layer->isHardwareCursor()) { + // Latch the cursor composition state from each front-end layer. + layer->getLayerFE().latchCursorCompositionState( + layer->getLayer().editState().frontEnd); + layer->writeCursorPositionToHWC(); + } + } + } +} + void CompositionEngine::preComposition(CompositionRefreshArgs& args) { ATRACE_CALL(); ALOGV(__FUNCTION__); diff --git a/services/surfaceflinger/CompositionEngine/src/OutputLayer.cpp b/services/surfaceflinger/CompositionEngine/src/OutputLayer.cpp index e721cf5375..73bb03be02 100644 --- a/services/surfaceflinger/CompositionEngine/src/OutputLayer.cpp +++ b/services/surfaceflinger/CompositionEngine/src/OutputLayer.cpp @@ -550,6 +550,27 @@ void OutputLayer::writeCompositionTypeToHWC( } } +void OutputLayer::writeCursorPositionToHWC() const { + // Skip doing this if there is no HWC interface + auto hwcLayer = getHwcLayer(); + if (!hwcLayer) { + return; + } + + const auto& layerFEState = mLayer->getState().frontEnd; + const auto& outputState = mOutput.getState(); + + Rect frame = layerFEState.cursorFrame; + frame.intersect(outputState.viewport, &frame); + Rect position = outputState.transform.transform(frame); + + if (auto error = hwcLayer->setCursorPosition(position.left, position.top); + error != HWC2::Error::None) { + ALOGE("[%s] Failed to set cursor position to (%d, %d): %s (%d)", mLayerFE->getDebugName(), + position.left, position.top, to_string(error).c_str(), static_cast(error)); + } +} + HWC2::Layer* OutputLayer::getHwcLayer() const { return mState.hwc ? mState.hwc->hwcLayer.get() : nullptr; } @@ -559,6 +580,11 @@ bool OutputLayer::requiresClientComposition() const { mState.hwc->hwcCompositionType == Hwc2::IComposerClient::Composition::CLIENT; } +bool OutputLayer::isHardwareCursor() const { + return mState.hwc && + mState.hwc->hwcCompositionType == Hwc2::IComposerClient::Composition::CURSOR; +} + void OutputLayer::detectDisallowedCompositionTypeChange( Hwc2::IComposerClient::Composition from, Hwc2::IComposerClient::Composition to) const { bool result = false; diff --git a/services/surfaceflinger/CompositionEngine/tests/OutputLayerTest.cpp b/services/surfaceflinger/CompositionEngine/tests/OutputLayerTest.cpp index c83cae65fb..75e960c575 100644 --- a/services/surfaceflinger/CompositionEngine/tests/OutputLayerTest.cpp +++ b/services/surfaceflinger/CompositionEngine/tests/OutputLayerTest.cpp @@ -781,6 +781,61 @@ TEST_F(OutputLayerWriteStateToHWCTest, compositionTypeIsSetToClientIfClientCompo mOutputLayer.writeStateToHWC(false); } +/* + * OutputLayer::writeCursorPositionToHWC() + */ + +struct OutputLayerWriteCursorPositionToHWCTest : public OutputLayerTest { + static constexpr int kDefaultTransform = TR_IDENT; + static constexpr HWC2::Error kDefaultError = HWC2::Error::Unsupported; + + static const Rect kDefaultDisplayViewport; + static const Rect kDefaultCursorFrame; + + OutputLayerWriteCursorPositionToHWCTest() { + auto& outputLayerState = mOutputLayer.editState(); + outputLayerState.hwc = impl::OutputLayerCompositionState::Hwc(mHwcLayer); + + mLayerState.frontEnd.cursorFrame = kDefaultCursorFrame; + + mOutputState.viewport = kDefaultDisplayViewport; + mOutputState.transform = ui::Transform{kDefaultTransform}; + } + + std::shared_ptr mHwcLayer{std::make_shared>()}; +}; + +const Rect OutputLayerWriteCursorPositionToHWCTest::kDefaultDisplayViewport{0, 0, 1920, 1080}; +const Rect OutputLayerWriteCursorPositionToHWCTest::kDefaultCursorFrame{1, 2, 3, 4}; + +TEST_F(OutputLayerWriteCursorPositionToHWCTest, writeCursorPositionToHWCHandlesNoHwcState) { + mOutputLayer.editState().hwc.reset(); + + mOutputLayer.writeCursorPositionToHWC(); +} + +TEST_F(OutputLayerWriteCursorPositionToHWCTest, writeCursorPositionToHWCWritesStateToHWC) { + EXPECT_CALL(*mHwcLayer, setCursorPosition(1, 2)).WillOnce(Return(kDefaultError)); + + mOutputLayer.writeCursorPositionToHWC(); +} + +TEST_F(OutputLayerWriteCursorPositionToHWCTest, writeCursorPositionToHWCIntersectedWithViewport) { + mLayerState.frontEnd.cursorFrame = Rect{3000, 3000, 3016, 3016}; + + EXPECT_CALL(*mHwcLayer, setCursorPosition(1920, 1080)).WillOnce(Return(kDefaultError)); + + mOutputLayer.writeCursorPositionToHWC(); +} + +TEST_F(OutputLayerWriteCursorPositionToHWCTest, writeCursorPositionToHWCRotatedByTransform) { + mOutputState.transform = ui::Transform{TR_ROT_90}; + + EXPECT_CALL(*mHwcLayer, setCursorPosition(-4, 1)).WillOnce(Return(kDefaultError)); + + mOutputLayer.writeCursorPositionToHWC(); +} + /* * OutputLayer::getHwcLayer() */ @@ -828,6 +883,30 @@ TEST_F(OutputLayerTest, requiresClientCompositionReturnsFalseIfSetToDeviceCompos EXPECT_FALSE(mOutputLayer.requiresClientComposition()); } +/* + * OutputLayer::isHardwareCursor() + */ + +TEST_F(OutputLayerTest, isHardwareCursorReturnsFalseIfNoHWC2State) { + mOutputLayer.editState().hwc.reset(); + + EXPECT_FALSE(mOutputLayer.isHardwareCursor()); +} + +TEST_F(OutputLayerTest, isHardwareCursorReturnsTrueIfSetToCursorComposition) { + mOutputLayer.editState().hwc = impl::OutputLayerCompositionState::Hwc{nullptr}; + mOutputLayer.editState().hwc->hwcCompositionType = Hwc2::IComposerClient::Composition::CURSOR; + + EXPECT_TRUE(mOutputLayer.isHardwareCursor()); +} + +TEST_F(OutputLayerTest, isHardwareCursorReturnsFalseIfSetToDeviceComposition) { + mOutputLayer.editState().hwc = impl::OutputLayerCompositionState::Hwc{nullptr}; + mOutputLayer.editState().hwc->hwcCompositionType = Hwc2::IComposerClient::Composition::DEVICE; + + EXPECT_FALSE(mOutputLayer.isHardwareCursor()); +} + /* * OutputLayer::applyDeviceCompositionTypeChange() */ diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp index 5121835cae..557d0bba27 100644 --- a/services/surfaceflinger/Layer.cpp +++ b/services/surfaceflinger/Layer.cpp @@ -464,6 +464,21 @@ void Layer::latchPerFrameState(compositionengine::LayerFECompositionState& compo } } +void Layer::latchCursorCompositionState( + compositionengine::LayerFECompositionState& compositionState) const { + // This gives us only the "orientation" component of the transform + const State& drawingState{getDrawingState()}; + + // Apply the layer's transform, followed by the display's global transform + // Here we're guaranteed that the layer's transform preserves rects + Rect win = getCroppedBufferSize(drawingState); + // Subtract the transparent region and snap to the bounds + Rect bounds = reduce(win, getActiveTransparentRegion(drawingState)); + Rect frame(getTransform().transform(bounds)); + + compositionState.cursorFrame = frame; +} + bool Layer::onPreComposition(nsecs_t) { return false; } @@ -481,38 +496,6 @@ const char* Layer::getDebugName() const { return mName.string(); } -void Layer::updateCursorPosition(const sp& display) { - const auto outputLayer = findOutputLayerForDisplay(display); - LOG_FATAL_IF(!outputLayer); - - if (!outputLayer->getState().hwc || - (*outputLayer->getState().hwc).hwcCompositionType != - Hwc2::IComposerClient::Composition::CURSOR) { - return; - } - - // This gives us only the "orientation" component of the transform - const State& s(getDrawingState()); - - // Apply the layer's transform, followed by the display's global transform - // Here we're guaranteed that the layer's transform preserves rects - Rect win = getCroppedBufferSize(s); - // Subtract the transparent region and snap to the bounds - Rect bounds = reduce(win, getActiveTransparentRegion(s)); - Rect frame(getTransform().transform(bounds)); - frame.intersect(display->getViewport(), &frame); - auto& displayTransform = display->getTransform(); - auto position = displayTransform.transform(frame); - - auto error = - (*outputLayer->getState().hwc).hwcLayer->setCursorPosition(position.left, position.top); - ALOGE_IF(error != HWC2::Error::None, - "[%s] Failed to set cursor position " - "to (%d, %d): %s (%d)", - mName.string(), position.left, position.top, to_string(error).c_str(), - static_cast(error)); -} - // --------------------------------------------------------------------------- // drawing... // --------------------------------------------------------------------------- diff --git a/services/surfaceflinger/Layer.h b/services/surfaceflinger/Layer.h index aa3970eb3a..23763d2729 100644 --- a/services/surfaceflinger/Layer.h +++ b/services/surfaceflinger/Layer.h @@ -476,6 +476,7 @@ public: bool onPreComposition(nsecs_t) override; void latchCompositionState(compositionengine::LayerFECompositionState&, bool includeGeometry) const override; + void latchCursorCompositionState(compositionengine::LayerFECompositionState&) const override; std::optional prepareClientComposition( compositionengine::LayerFE::ClientCompositionTargetSettings&) override; void onLayerDisplayed(const sp& releaseFence) override; @@ -493,7 +494,6 @@ public: Hwc2::IComposerClient::Composition getCompositionType( const sp& display) const; bool getClearClientTarget(const sp& display) const; - void updateCursorPosition(const sp& display); virtual bool shouldPresentNow(nsecs_t /*expectedPresentTime*/) const { return false; } virtual void setTransformHint(uint32_t /*orientation*/) const { } diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp index 83f3b2cecd..8760bb0900 100644 --- a/services/surfaceflinger/SurfaceFlinger.cpp +++ b/services/surfaceflinger/SurfaceFlinger.cpp @@ -2715,15 +2715,14 @@ void SurfaceFlinger::executeInputWindowCommands() { void SurfaceFlinger::updateCursorAsync() { - for (const auto& [token, display] : mDisplays) { - if (!display->getId()) { - continue; - } - - for (auto& layer : display->getVisibleLayersSortedByZ()) { - layer->updateCursorPosition(display); + compositionengine::CompositionRefreshArgs refreshArgs; + for (const auto& [_, display] : mDisplays) { + if (display->getId()) { + refreshArgs.outputs.push_back(display->getCompositionDisplay()); } } + + mCompositionEngine->updateCursorAsync(refreshArgs); } void SurfaceFlinger::commitTransaction() -- cgit v1.2.3-59-g8ed1b From 0f085c6a3e5aa5ffa4619f612c2d3b1244420b31 Mon Sep 17 00:00:00 2001 From: Vishnu Nair Date: Fri, 30 Aug 2019 08:49:12 -0700 Subject: Dump offscreen layers in dumpsys and winscope trace Now that clients can keep layers alive by holding a reference to its handle and clients can also create layers, we need to an easier way to keep track of layers that are offscreen but not destroyed. This change keeps track of the calling pid and uid so it is easier to track the creating process. Since the tracing thread will also read from mOffscreenLayers, we want to protect access to it with the tracing lock. Bug:127687760 Test: run dumpsys check for offscreen layers Test: capture sf trace and check for offscreen layers Change-Id: I400f33b11b0a4f78f4c35027c457eb56ff12c22e --- services/surfaceflinger/Layer.cpp | 24 ++++++++- services/surfaceflinger/Layer.h | 12 +++-- services/surfaceflinger/SurfaceFlinger.cpp | 85 ++++++++++++++++++++++-------- services/surfaceflinger/SurfaceFlinger.h | 3 ++ services/surfaceflinger/SurfaceTracing.cpp | 1 + 5 files changed, 100 insertions(+), 25 deletions(-) (limited to 'services/surfaceflinger/Layer.cpp') diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp index 5121835cae..688c5ee2a7 100644 --- a/services/surfaceflinger/Layer.cpp +++ b/services/surfaceflinger/Layer.cpp @@ -22,6 +22,7 @@ #include "Layer.h" #include +#include #include #include #include @@ -121,7 +122,8 @@ Layer::Layer(const LayerCreationArgs& args) mFrameTracker.setDisplayRefreshPeriod(compositorTiming.interval); mSchedulerLayerHandle = mFlinger->mScheduler->registerLayer(mName.c_str(), mWindowType); - + mCallingPid = args.callingPid; + mCallingUid = args.callingUid; mFlinger->onLayerCreated(); } @@ -135,6 +137,21 @@ Layer::~Layer() { mFlinger->onLayerDestroyed(this); } +LayerCreationArgs::LayerCreationArgs(SurfaceFlinger* flinger, const sp& client, + const String8& name, uint32_t w, uint32_t h, uint32_t flags, + LayerMetadata metadata) + : flinger(flinger), + client(client), + name(name), + w(w), + h(h), + flags(flags), + metadata(std::move(metadata)) { + IPCThreadState* ipc = IPCThreadState::self(); + callingPid = ipc->getCallingPid(); + callingUid = ipc->getCallingUid(); +} + // --------------------------------------------------------------------------- // callbacks // --------------------------------------------------------------------------- @@ -1340,6 +1357,11 @@ void Layer::dumpFrameEvents(std::string& result) { mFrameEventHistory.dump(result); } +void Layer::dumpCallingUidPid(std::string& result) const { + StringAppendF(&result, "Layer %s (%s) pid:%d uid:%d\n", getName().string(), getType(), + mCallingPid, mCallingUid); +} + void Layer::onDisconnect() { Mutex::Autolock lock(mFrameEventHistoryMutex); mFrameEventHistory.onDisconnect(); diff --git a/services/surfaceflinger/Layer.h b/services/surfaceflinger/Layer.h index 9107189d52..49542395ee 100644 --- a/services/surfaceflinger/Layer.h +++ b/services/surfaceflinger/Layer.h @@ -80,9 +80,7 @@ class SurfaceInterceptor; struct LayerCreationArgs { LayerCreationArgs(SurfaceFlinger* flinger, const sp& client, const String8& name, - uint32_t w, uint32_t h, uint32_t flags, LayerMetadata metadata) - : flinger(flinger), client(client), name(name), w(w), h(h), flags(flags), - metadata(std::move(metadata)) {} + uint32_t w, uint32_t h, uint32_t flags, LayerMetadata metadata); SurfaceFlinger* flinger; const sp& client; @@ -91,6 +89,8 @@ struct LayerCreationArgs { uint32_t h; uint32_t flags; LayerMetadata metadata; + pid_t callingPid; + uid_t callingUid; }; class Layer : public virtual compositionengine::LayerFE { @@ -600,6 +600,7 @@ public: void miniDump(std::string& result, const sp& display) const; void dumpFrameStats(std::string& result) const; void dumpFrameEvents(std::string& result); + void dumpCallingUidPid(std::string& result) const; void clearFrameStats(); void logFrameStats(); void getFrameStats(FrameStats* outStats) const; @@ -924,6 +925,11 @@ private: bool mGetHandleCalled = false; void removeRemoteSyncPoints(); + + // Tracks the process and user id of the caller when creating this layer + // to help debugging. + pid_t mCallingPid; + uid_t mCallingUid; }; } // namespace android diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp index e8049239ba..c081ddeae6 100644 --- a/services/surfaceflinger/SurfaceFlinger.cpp +++ b/services/surfaceflinger/SurfaceFlinger.cpp @@ -2872,32 +2872,31 @@ void SurfaceFlinger::updateCursorAsync() void SurfaceFlinger::commitTransaction() { - if (!mLayersPendingRemoval.isEmpty()) { - // Notify removed layers now that they can't be drawn from - for (const auto& l : mLayersPendingRemoval) { - recordBufferingStats(l->getName().string(), - l->getOccupancyHistory(true)); - - // Ensure any buffers set to display on any children are released. - if (l->isRemovedFromCurrentState()) { - l->latchAndReleaseBuffer(); - } + withTracingLock([&]() { + if (!mLayersPendingRemoval.isEmpty()) { + // Notify removed layers now that they can't be drawn from + for (const auto& l : mLayersPendingRemoval) { + recordBufferingStats(l->getName().string(), l->getOccupancyHistory(true)); + + // Ensure any buffers set to display on any children are released. + if (l->isRemovedFromCurrentState()) { + l->latchAndReleaseBuffer(); + } - // If the layer has been removed and has no parent, then it will not be reachable - // when traversing layers on screen. Add the layer to the offscreenLayers set to - // ensure we can copy its current to drawing state. - if (!l->getParent()) { - mOffscreenLayers.emplace(l.get()); + // If the layer has been removed and has no parent, then it will not be reachable + // when traversing layers on screen. Add the layer to the offscreenLayers set to + // ensure we can copy its current to drawing state. + if (!l->getParent()) { + mOffscreenLayers.emplace(l.get()); + } } + mLayersPendingRemoval.clear(); } - mLayersPendingRemoval.clear(); - } - // If this transaction is part of a window animation then the next frame - // we composite should be considered an animation as well. - mAnimCompositionPending = mAnimTransactionPending; + // If this transaction is part of a window animation then the next frame + // we composite should be considered an animation as well. + mAnimCompositionPending = mAnimTransactionPending; - withTracingLock([&]() { mDrawingState = mCurrentState; // clear the "changed" flags in current state mCurrentState.colorMatrixChanged = false; @@ -4286,9 +4285,11 @@ status_t SurfaceFlinger::doDump(int fd, const DumpArgs& args, if (asProto) { result.append(layersProto.SerializeAsString()); } else { + // Dump info that we need to access from the main thread const auto layerTree = LayerProtoParser::generateLayerTree(layersProto); result.append(LayerProtoParser::layerTreeToString(layerTree)); result.append("\n"); + dumpOffscreenLayers(result); } } } @@ -4546,12 +4547,54 @@ LayersProto SurfaceFlinger::dumpDrawingStateProto(uint32_t traceFlags) const { return layersProto; } +void SurfaceFlinger::dumpOffscreenLayersProto(LayersProto& layersProto, uint32_t traceFlags) const { + // Add a fake invisible root layer to the proto output and parent all the offscreen layers to + // it. + LayerProto* rootProto = layersProto.add_layers(); + const int32_t offscreenRootLayerId = INT32_MAX - 2; + rootProto->set_id(offscreenRootLayerId); + rootProto->set_name("Offscreen Root"); + + for (Layer* offscreenLayer : mOffscreenLayers) { + // Add layer as child of the fake root + rootProto->add_children(offscreenLayer->sequence); + + // Add layer + LayerProto* layerProto = layersProto.add_layers(); + offscreenLayer->writeToProtoDrawingState(layerProto, traceFlags); + offscreenLayer->writeToProtoCommonState(layerProto, LayerVector::StateSet::Drawing, + traceFlags); + layerProto->set_parent(offscreenRootLayerId); + + // Add children + offscreenLayer->traverseInZOrder(LayerVector::StateSet::Drawing, [&](Layer* layer) { + if (layer == offscreenLayer) { + return; + } + LayerProto* childProto = layersProto.add_layers(); + layer->writeToProtoDrawingState(childProto, traceFlags); + layer->writeToProtoCommonState(childProto, LayerVector::StateSet::Drawing, traceFlags); + }); + } +} + LayersProto SurfaceFlinger::dumpProtoFromMainThread(uint32_t traceFlags) { LayersProto layersProto; postMessageSync(new LambdaMessage([&]() { layersProto = dumpDrawingStateProto(traceFlags); })); return layersProto; } +void SurfaceFlinger::dumpOffscreenLayers(std::string& result) { + result.append("Offscreen Layers:\n"); + postMessageSync(new LambdaMessage([&]() { + for (Layer* offscreenLayer : mOffscreenLayers) { + offscreenLayer->traverseInZOrder(LayerVector::StateSet::Drawing, [&](Layer* layer) { + layer->dumpCallingUidPid(result); + }); + } + })); +} + void SurfaceFlinger::dumpAllLocked(const DumpArgs& args, std::string& result) const { const bool colorize = !args.empty() && args[0] == String16("--color"); Colorizer colorizer(colorize); diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h index 8408ef5174..d44ff9c5f4 100644 --- a/services/surfaceflinger/SurfaceFlinger.h +++ b/services/surfaceflinger/SurfaceFlinger.h @@ -876,8 +876,11 @@ private: void dumpDisplayIdentificationData(std::string& result) const; void dumpWideColorInfo(std::string& result) const; LayersProto dumpDrawingStateProto(uint32_t traceFlags = SurfaceTracing::TRACE_ALL) const; + void dumpOffscreenLayersProto(LayersProto& layersProto, + uint32_t traceFlags = SurfaceTracing::TRACE_ALL) const; LayersProto dumpProtoFromMainThread(uint32_t traceFlags = SurfaceTracing::TRACE_ALL) EXCLUDES(mStateLock); + void dumpOffscreenLayers(std::string& result) EXCLUDES(mStateLock); void withTracingLock(std::function operation) REQUIRES(mStateLock); bool isLayerTripleBufferingDisabled() const { diff --git a/services/surfaceflinger/SurfaceTracing.cpp b/services/surfaceflinger/SurfaceTracing.cpp index 9053f2c7de..eb26cd0379 100644 --- a/services/surfaceflinger/SurfaceTracing.cpp +++ b/services/surfaceflinger/SurfaceTracing.cpp @@ -163,6 +163,7 @@ LayersTraceProto SurfaceTracing::traceLayersLocked(const char* where) { entry.set_elapsed_realtime_nanos(elapsedRealtimeNano()); entry.set_where(where); LayersProto layers(mFlinger.dumpDrawingStateProto(mTraceFlags)); + mFlinger.dumpOffscreenLayersProto(layers); entry.mutable_layers()->Swap(&layers); return entry; -- cgit v1.2.3-59-g8ed1b From 90092f4335b7360b149a57ee759df778e099ff87 Mon Sep 17 00:00:00 2001 From: Mikael Pessa Date: Mon, 26 Aug 2019 17:22:04 -0700 Subject: Refactor: Pull tracing out of TimeStats. The tracing in TimeStats ended up having no actual overlap with current TimeStats functionality. This CL pulls all tracing related code out into its own class. Test: atest libsurfaceflinger_unittest and manually inspected traces. Run trace with: { adb shell perfetto -c - --txt -o /data/misc/perfetto-traces/trace <deleteTextureAsync(mTextureName); - mFlinger->mTimeStats->onDestroy(getSequence()); + const int32_t layerID = getSequence(); + mFlinger->mTimeStats->onDestroy(layerID); + mFlinger->mFrameTracer->onDestroy(layerID); } void BufferLayer::useSurfaceDamage() { @@ -314,17 +317,17 @@ bool BufferLayer::onPostComposition(const std::optional& displayId, if (presentFence->isValid()) { mFlinger->mTimeStats->setPresentFence(layerID, mCurrentFrameNumber, presentFence); - mFlinger->mTimeStats->traceFence(layerID, getCurrentBufferId(), mCurrentFrameNumber, - presentFence, TimeStats::FrameEvent::PRESENT_FENCE); + mFlinger->mFrameTracer->traceFence(layerID, getCurrentBufferId(), mCurrentFrameNumber, + presentFence, FrameTracer::FrameEvent::PRESENT_FENCE); mFrameTracker.setActualPresentFence(std::shared_ptr(presentFence)); } else if (displayId && mFlinger->getHwComposer().isConnected(*displayId)) { // The HWC doesn't support present fences, so use the refresh // timestamp instead. const nsecs_t actualPresentTime = mFlinger->getHwComposer().getRefreshTimestamp(*displayId); mFlinger->mTimeStats->setPresentTime(layerID, mCurrentFrameNumber, actualPresentTime); - mFlinger->mTimeStats->traceTimestamp(layerID, getCurrentBufferId(), mCurrentFrameNumber, - actualPresentTime, - TimeStats::FrameEvent::PRESENT_FENCE); + mFlinger->mFrameTracer->traceTimestamp(layerID, getCurrentBufferId(), mCurrentFrameNumber, + actualPresentTime, + FrameTracer::FrameEvent::PRESENT_FENCE); mFrameTracker.setActualPresentTime(actualPresentTime); } diff --git a/services/surfaceflinger/BufferQueueLayer.cpp b/services/surfaceflinger/BufferQueueLayer.cpp index 6cad3c7d07..4da39e4d6f 100644 --- a/services/surfaceflinger/BufferQueueLayer.cpp +++ b/services/surfaceflinger/BufferQueueLayer.cpp @@ -29,6 +29,7 @@ #include "LayerRejecter.h" #include "SurfaceInterceptor.h" +#include "FrameTracer/FrameTracer.h" #include "TimeStats/TimeStats.h" namespace android { @@ -48,9 +49,9 @@ void BufferQueueLayer::onLayerDisplayed(const sp& releaseFence) { // Prevent tracing the same release multiple times. if (mPreviousFrameNumber != mPreviousReleasedFrameNumber) { - mFlinger->mTimeStats->traceFence(getSequence(), mPreviousBufferId, mPreviousFrameNumber, - std::make_shared(releaseFence), - TimeStats::FrameEvent::RELEASE_FENCE); + mFlinger->mFrameTracer->traceFence(getSequence(), mPreviousBufferId, mPreviousFrameNumber, + std::make_shared(releaseFence), + FrameTracer::FrameEvent::RELEASE_FENCE); mPreviousReleasedFrameNumber = mPreviousFrameNumber; } } @@ -337,6 +338,7 @@ status_t BufferQueueLayer::updateTexImage(bool& recomputeVisibleRegions, nsecs_t mQueueItems.clear(); mQueuedFrames = 0; mFlinger->mTimeStats->onDestroy(layerID); + mFlinger->mFrameTracer->onDestroy(layerID); } // Once we have hit this state, the shadow queue may no longer @@ -366,12 +368,12 @@ status_t BufferQueueLayer::updateTexImage(bool& recomputeVisibleRegions, nsecs_t uint64_t bufferID = mQueueItems[0].mGraphicBuffer->getId(); mFlinger->mTimeStats->setAcquireFence(layerID, currentFrameNumber, mQueueItems[0].mFenceTime); - mFlinger->mTimeStats->traceFence(layerID, bufferID, currentFrameNumber, - mQueueItems[0].mFenceTime, - TimeStats::FrameEvent::ACQUIRE_FENCE); + mFlinger->mFrameTracer->traceFence(layerID, bufferID, currentFrameNumber, + mQueueItems[0].mFenceTime, + FrameTracer::FrameEvent::ACQUIRE_FENCE); mFlinger->mTimeStats->setLatchTime(layerID, currentFrameNumber, latchTime); - mFlinger->mTimeStats->traceTimestamp(layerID, bufferID, currentFrameNumber, latchTime, - TimeStats::FrameEvent::LATCH); + mFlinger->mFrameTracer->traceTimestamp(layerID, bufferID, currentFrameNumber, latchTime, + FrameTracer::FrameEvent::LATCH); mQueueItems.removeAt(0); } @@ -429,9 +431,9 @@ void BufferQueueLayer::latchPerFrameState( void BufferQueueLayer::onFrameAvailable(const BufferItem& item) { const int32_t layerID = getSequence(); - mFlinger->mTimeStats->traceNewLayer(layerID, getName().c_str()); - mFlinger->mTimeStats->traceTimestamp(layerID, item.mGraphicBuffer->getId(), item.mFrameNumber, - systemTime(), TimeStats::FrameEvent::POST); + mFlinger->mFrameTracer->traceNewLayer(layerID, getName().c_str()); + mFlinger->mFrameTracer->traceTimestamp(layerID, item.mGraphicBuffer->getId(), item.mFrameNumber, + systemTime(), FrameTracer::FrameEvent::POST); ATRACE_CALL(); // Add this buffer from our internal queue tracker diff --git a/services/surfaceflinger/BufferStateLayer.cpp b/services/surfaceflinger/BufferStateLayer.cpp index 4a8261d99f..e7d1b63b03 100644 --- a/services/surfaceflinger/BufferStateLayer.cpp +++ b/services/surfaceflinger/BufferStateLayer.cpp @@ -32,6 +32,7 @@ #include "BufferStateLayer.h" #include "ColorLayer.h" +#include "FrameTracer/FrameTracer.h" #include "TimeStats/TimeStats.h" namespace android { @@ -90,9 +91,9 @@ void BufferStateLayer::onLayerDisplayed(const sp& releaseFence) { // Prevent tracing the same release multiple times. if (mPreviousFrameNumber != mPreviousReleasedFrameNumber) { - mFlinger->mTimeStats->traceFence(getSequence(), mPreviousBufferId, mPreviousFrameNumber, - std::make_shared(releaseFence), - TimeStats::FrameEvent::RELEASE_FENCE); + mFlinger->mFrameTracer->traceFence(getSequence(), mPreviousBufferId, mPreviousFrameNumber, + std::make_shared(releaseFence), + FrameTracer::FrameEvent::RELEASE_FENCE); mPreviousReleasedFrameNumber = mPreviousFrameNumber; } } @@ -236,9 +237,9 @@ bool BufferStateLayer::setBuffer(const sp& buffer, nsecs_t postTi const int32_t layerID = getSequence(); mFlinger->mTimeStats->setPostTime(layerID, mFrameNumber, getName().c_str(), postTime); - mFlinger->mTimeStats->traceNewLayer(layerID, getName().c_str()); - mFlinger->mTimeStats->traceTimestamp(layerID, buffer->getId(), mFrameNumber, postTime, - TimeStats::FrameEvent::POST); + mFlinger->mFrameTracer->traceNewLayer(layerID, getName().c_str()); + mFlinger->mFrameTracer->traceTimestamp(layerID, buffer->getId(), mFrameNumber, postTime, + FrameTracer::FrameEvent::POST); mCurrentState.desiredPresentTime = desiredPresentTime; if (mFlinger->mUseSmart90ForVideo) { @@ -569,17 +570,18 @@ status_t BufferStateLayer::updateTexImage(bool& /*recomputeVisibleRegions*/, nse status_t err = bindTextureImage(); if (err != NO_ERROR) { mFlinger->mTimeStats->onDestroy(layerID); + mFlinger->mFrameTracer->onDestroy(layerID); return BAD_VALUE; } } const uint64_t bufferID = getCurrentBufferId(); mFlinger->mTimeStats->setAcquireFence(layerID, mFrameNumber, getCurrentFenceTime()); - mFlinger->mTimeStats->traceFence(layerID, bufferID, mFrameNumber, getCurrentFenceTime(), - TimeStats::FrameEvent::ACQUIRE_FENCE); + mFlinger->mFrameTracer->traceFence(layerID, bufferID, mFrameNumber, getCurrentFenceTime(), + FrameTracer::FrameEvent::ACQUIRE_FENCE); mFlinger->mTimeStats->setLatchTime(layerID, mFrameNumber, latchTime); - mFlinger->mTimeStats->traceTimestamp(layerID, bufferID, mFrameNumber, latchTime, - TimeStats::FrameEvent::LATCH); + mFlinger->mFrameTracer->traceTimestamp(layerID, bufferID, mFrameNumber, latchTime, + FrameTracer::FrameEvent::LATCH); mCurrentStateModified = false; diff --git a/services/surfaceflinger/FrameTracer/FrameTracer.cpp b/services/surfaceflinger/FrameTracer/FrameTracer.cpp new file mode 100644 index 0000000000..7cbb8d8b7c --- /dev/null +++ b/services/surfaceflinger/FrameTracer/FrameTracer.cpp @@ -0,0 +1,173 @@ +/* + * Copyright 2019 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. + */ + +#undef LOG_TAG +#define LOG_TAG "FrameTracer" +#define ATRACE_TAG ATRACE_TAG_GRAPHICS + +#include "FrameTracer.h" + +#include + +#include + +PERFETTO_DEFINE_DATA_SOURCE_STATIC_MEMBERS(android::FrameTracer::FrameTracerDataSource); + +namespace android { + +void FrameTracer::initialize() { + perfetto::TracingInitArgs args; + args.backends = perfetto::kSystemBackend; + perfetto::Tracing::Initialize(args); + registerDataSource(); +} + +void FrameTracer::registerDataSource() { + perfetto::DataSourceDescriptor dsd; + dsd.set_name(kFrameTracerDataSource); + FrameTracerDataSource::Register(dsd); +} + +void FrameTracer::traceNewLayer(int32_t layerID, const std::string& layerName) { + FrameTracerDataSource::Trace([this, layerID, &layerName](FrameTracerDataSource::TraceContext) { + if (mTraceTracker.find(layerID) == mTraceTracker.end()) { + std::lock_guard lock(mTraceMutex); + mTraceTracker[layerID].layerName = layerName; + } + }); +} + +void FrameTracer::traceTimestamp(int32_t layerID, uint64_t bufferID, uint64_t frameNumber, + nsecs_t timestamp, FrameEvent::BufferEventType type, + nsecs_t duration) { + FrameTracerDataSource::Trace([this, layerID, bufferID, frameNumber, timestamp, type, + duration](FrameTracerDataSource::TraceContext ctx) { + std::lock_guard lock(mTraceMutex); + if (mTraceTracker.find(layerID) == mTraceTracker.end()) { + return; + } + + // Handle any pending fences for this buffer. + tracePendingFencesLocked(ctx, layerID, bufferID); + + // Complete current trace. + traceLocked(ctx, layerID, bufferID, frameNumber, timestamp, type, duration); + }); +} + +void FrameTracer::traceFence(int32_t layerID, uint64_t bufferID, uint64_t frameNumber, + const std::shared_ptr& fence, + FrameEvent::BufferEventType type, nsecs_t startTime) { + FrameTracerDataSource::Trace([this, layerID, bufferID, frameNumber, &fence, type, + startTime](FrameTracerDataSource::TraceContext ctx) { + const nsecs_t signalTime = fence->getSignalTime(); + if (signalTime != Fence::SIGNAL_TIME_INVALID) { + std::lock_guard lock(mTraceMutex); + if (mTraceTracker.find(layerID) == mTraceTracker.end()) { + return; + } + + // Handle any pending fences for this buffer. + tracePendingFencesLocked(ctx, layerID, bufferID); + + if (signalTime != Fence::SIGNAL_TIME_PENDING) { + traceSpanLocked(ctx, layerID, bufferID, frameNumber, type, startTime, signalTime); + } else { + mTraceTracker[layerID].pendingFences[bufferID].push_back( + {.frameNumber = frameNumber, + .type = type, + .fence = fence, + .startTime = startTime}); + } + } + }); +} + +void FrameTracer::tracePendingFencesLocked(FrameTracerDataSource::TraceContext& ctx, + int32_t layerID, uint64_t bufferID) { + if (mTraceTracker[layerID].pendingFences.count(bufferID)) { + auto& pendingFences = mTraceTracker[layerID].pendingFences[bufferID]; + for (size_t i = 0; i < pendingFences.size(); ++i) { + auto& pendingFence = pendingFences[i]; + + nsecs_t signalTime = Fence::SIGNAL_TIME_INVALID; + if (pendingFence.fence && pendingFence.fence->isValid()) { + signalTime = pendingFence.fence->getSignalTime(); + if (signalTime == Fence::SIGNAL_TIME_PENDING) { + continue; + } + } + + if (signalTime != Fence::SIGNAL_TIME_INVALID && + systemTime() - signalTime < kFenceSignallingDeadline) { + traceSpanLocked(ctx, layerID, bufferID, pendingFence.frameNumber, pendingFence.type, + pendingFence.startTime, signalTime); + } + + pendingFences.erase(pendingFences.begin() + i); + --i; + } + } +} + +void FrameTracer::traceLocked(FrameTracerDataSource::TraceContext& ctx, int32_t layerID, + uint64_t bufferID, uint64_t frameNumber, nsecs_t timestamp, + FrameEvent::BufferEventType type, nsecs_t duration) { + auto packet = ctx.NewTracePacket(); + packet->set_timestamp(timestamp); + auto* event = packet->set_graphics_frame_event()->set_buffer_event(); + event->set_buffer_id(static_cast(bufferID)); + event->set_frame_number(frameNumber); + event->set_type(type); + + if (mTraceTracker.find(layerID) != mTraceTracker.end() && + !mTraceTracker[layerID].layerName.empty()) { + const std::string& layerName = mTraceTracker[layerID].layerName; + event->set_layer_name(layerName.c_str(), layerName.size()); + } + + if (duration > 0) { + event->set_duration_ns(duration); + } +} + +void FrameTracer::traceSpanLocked(FrameTracerDataSource::TraceContext& ctx, int32_t layerID, + uint64_t bufferID, uint64_t frameNumber, + FrameEvent::BufferEventType type, nsecs_t startTime, + nsecs_t endTime) { + nsecs_t timestamp = endTime; + nsecs_t duration = 0; + if (startTime > 0 && startTime < endTime) { + timestamp = startTime; + duration = endTime - startTime; + } + traceLocked(ctx, layerID, bufferID, frameNumber, timestamp, type, duration); +} + +void FrameTracer::onDestroy(int32_t layerID) { + std::lock_guard traceLock(mTraceMutex); + mTraceTracker.erase(layerID); +} + +std::string FrameTracer::miniDump() { + std::string result = "FrameTracer miniDump:\n"; + std::lock_guard lock(mTraceMutex); + android::base::StringAppendF(&result, "Number of layers currently being traced is %zu\n", + mTraceTracker.size()); + return result; +} + +} // namespace android diff --git a/services/surfaceflinger/FrameTracer/FrameTracer.h b/services/surfaceflinger/FrameTracer/FrameTracer.h new file mode 100644 index 0000000000..d34ad81fee --- /dev/null +++ b/services/surfaceflinger/FrameTracer/FrameTracer.h @@ -0,0 +1,105 @@ +/* + * Copyright 2019 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 +#include +#include + +#include +#include + +namespace android { + +class FrameTracer { +public: + class FrameTracerDataSource : public perfetto::DataSource { + virtual void OnSetup(const SetupArgs&) override{}; + virtual void OnStart(const StartArgs&) override{}; + virtual void OnStop(const StopArgs&) override{}; + }; + + using FrameEvent = perfetto::protos::pbzero::GraphicsFrameEvent; + + ~FrameTracer() = default; + + // Sets up the perfetto tracing backend and data source. + void initialize(); + // Registers the data source with the perfetto backend. Called as part of initialize() + // and should not be called manually outside of tests. Public to allow for substituting a + // perfetto::kInProcessBackend in tests. + void registerDataSource(); + // Starts tracking a new layer for tracing. Needs to be called once before traceTimestamp() or + // traceFence() for each layer. + void traceNewLayer(int32_t layerID, const std::string& layerName); + // Creates a trace point at the timestamp provided. + void traceTimestamp(int32_t layerID, uint64_t bufferID, uint64_t frameNumber, nsecs_t timestamp, + FrameEvent::BufferEventType type, nsecs_t duration = 0); + // Creates a trace point after the provided fence has been signalled. If a startTime is provided + // the trace will have be timestamped from startTime until fence signalling time. If no + // startTime is provided, a durationless trace point will be created timestamped at fence + // signalling time. If the fence hasn't signalled yet, the trace point will be created the next + // time after signalling a trace call for this buffer occurs. + void traceFence(int32_t layerID, uint64_t bufferID, uint64_t frameNumber, + const std::shared_ptr& fence, FrameEvent::BufferEventType type, + nsecs_t startTime = 0); + + // Takes care of cleanup when a layer is destroyed. + void onDestroy(int32_t layerID); + + std::string miniDump(); + + static constexpr char kFrameTracerDataSource[] = "android.surfaceflinger.frame"; + + // The maximum amount of time a fence has to signal before it is discarded. + // Used to avoid fences from previous traces generating new trace points in later ones. + // Public for testing. + static constexpr nsecs_t kFenceSignallingDeadline = 60'000'000'000; // 60 seconds + +private: + struct PendingFence { + uint64_t frameNumber; + FrameEvent::BufferEventType type; + std::shared_ptr fence; + nsecs_t startTime; + }; + + struct TraceRecord { + std::string layerName; + using BufferID = uint64_t; + std::unordered_map> pendingFences; + }; + + // Checks if any pending fences for a layer and buffer have signalled and, if they have, creates + // trace points for them. + void tracePendingFencesLocked(FrameTracerDataSource::TraceContext& ctx, int32_t layerID, + uint64_t bufferID); + // Creates a trace point by translating a start time and an end time to a timestamp and + // duration. If startTime is later than end time it sets end time as the timestamp and the + // duration to 0. Used by traceFence(). + void traceSpanLocked(FrameTracerDataSource::TraceContext& ctx, int32_t layerID, + uint64_t bufferID, uint64_t frameNumber, FrameEvent::BufferEventType type, + nsecs_t startTime, nsecs_t endTime); + void traceLocked(FrameTracerDataSource::TraceContext& ctx, int32_t layerID, uint64_t bufferID, + uint64_t frameNumber, nsecs_t timestamp, FrameEvent::BufferEventType type, + nsecs_t duration = 0); + + std::mutex mTraceMutex; + std::unordered_map mTraceTracker; +}; + +} // namespace android diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp index 5121835cae..106d505faa 100644 --- a/services/surfaceflinger/Layer.cpp +++ b/services/surfaceflinger/Layer.cpp @@ -57,6 +57,7 @@ #include "Colorizer.h" #include "DisplayDevice.h" #include "DisplayHardware/HWComposer.h" +#include "FrameTracer/FrameTracer.h" #include "LayerProtoHelper.h" #include "LayerRejecter.h" #include "MonitoredProducer.h" @@ -1343,7 +1344,9 @@ void Layer::dumpFrameEvents(std::string& result) { void Layer::onDisconnect() { Mutex::Autolock lock(mFrameEventHistoryMutex); mFrameEventHistory.onDisconnect(); - mFlinger->mTimeStats->onDestroy(getSequence()); + const int32_t layerID = getSequence(); + mFlinger->mTimeStats->onDestroy(layerID); + mFlinger->mFrameTracer->onDestroy(layerID); } void Layer::addAndGetFrameTimestamps(const NewFrameEventsEntry* newTimestamps, diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp index 6543089101..e8902b3c62 100644 --- a/services/surfaceflinger/SurfaceFlinger.cpp +++ b/services/surfaceflinger/SurfaceFlinger.cpp @@ -98,6 +98,7 @@ #include "DisplayHardware/HWComposer.h" #include "DisplayHardware/VirtualDisplaySurface.h" #include "Effects/Daltonizer.h" +#include "FrameTracer/FrameTracer.h" #include "RegionSamplingThread.h" #include "Scheduler/DispSync.h" #include "Scheduler/DispSyncSource.h" @@ -257,6 +258,7 @@ SurfaceFlinger::SurfaceFlinger(Factory& factory, SkipInitializationTag) : mFactory(factory), mInterceptor(mFactory.createSurfaceInterceptor(this)), mTimeStats(mFactory.createTimeStats()), + mFrameTracer(std::make_unique()), mEventQueue(mFactory.createMessageQueue()), mCompositionEngine(mFactory.createCompositionEngine()), mPhaseOffsets(mFactory.createPhaseOffsets()) {} @@ -513,7 +515,7 @@ void SurfaceFlinger::bootFinished() const nsecs_t duration = now - mBootTime; ALOGI("Boot is finished (%ld ms)", long(ns2ms(duration)) ); - mTimeStats->initializeTracing(); + mFrameTracer->initialize(); // wait patiently for the window manager death const String16 name("window"); diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h index 8408ef5174..c7cc07e490 100644 --- a/services/surfaceflinger/SurfaceFlinger.h +++ b/services/surfaceflinger/SurfaceFlinger.h @@ -94,6 +94,7 @@ class MessageBase; class RefreshRateOverlay; class RegionSamplingThread; class TimeStats; +class FrameTracer; namespace compositionengine { class DisplaySurface; @@ -996,6 +997,7 @@ private: bool mTracingEnabled = false; bool mTracingEnabledChanged GUARDED_BY(mStateLock) = false; const std::shared_ptr mTimeStats; + const std::unique_ptr mFrameTracer; bool mUseHwcVirtualDisplays = false; std::atomic mFrameMissedCount = 0; std::atomic mHwcFrameMissedCount = 0; diff --git a/services/surfaceflinger/TimeStats/Android.bp b/services/surfaceflinger/TimeStats/Android.bp index 9e1d5033b2..2080a3847e 100644 --- a/services/surfaceflinger/TimeStats/Android.bp +++ b/services/surfaceflinger/TimeStats/Android.bp @@ -2,12 +2,9 @@ cc_library_static { name: "libtimestats", defaults: ["surfaceflinger_defaults"], srcs: [ - "TimeStats.cpp" + "TimeStats.cpp", ], export_include_dirs: ["."], - static_libs: [ - "libperfetto_client_experimental", - ], shared_libs: [ "libtimestats_proto", "libui", diff --git a/services/surfaceflinger/TimeStats/TimeStats.cpp b/services/surfaceflinger/TimeStats/TimeStats.cpp index b66e4cfe4f..b01fa81594 100644 --- a/services/surfaceflinger/TimeStats/TimeStats.cpp +++ b/services/surfaceflinger/TimeStats/TimeStats.cpp @@ -30,141 +30,10 @@ #include #include -PERFETTO_DEFINE_DATA_SOURCE_STATIC_MEMBERS(android::impl::TimeStats::TimeStatsDataSource); - namespace android { namespace impl { -void TimeStats::initializeTracing() { - perfetto::TracingInitArgs args; - args.backends = perfetto::kSystemBackend; - perfetto::Tracing::Initialize(args); - registerTracingDataSource(); -} - -void TimeStats::registerTracingDataSource() { - perfetto::DataSourceDescriptor dsd; - dsd.set_name(kTimeStatsDataSource); - TimeStatsDataSource::Register(dsd); -} - -void TimeStats::traceNewLayer(int32_t layerID, const std::string& layerName) { - TimeStatsDataSource::Trace([this, layerID, &layerName](TimeStatsDataSource::TraceContext) { - if (mTraceTracker.find(layerID) == mTraceTracker.end()) { - std::lock_guard lock(mTraceMutex); - mTraceTracker[layerID].layerName = layerName; - } - }); -} - -void TimeStats::traceTimestamp(int32_t layerID, uint64_t bufferID, uint64_t frameNumber, - nsecs_t timestamp, FrameEvent::BufferEventType type, - nsecs_t duration) { - TimeStatsDataSource::Trace([this, layerID, bufferID, frameNumber, timestamp, type, - duration](TimeStatsDataSource::TraceContext ctx) { - std::lock_guard lock(mTraceMutex); - if (mTraceTracker.find(layerID) == mTraceTracker.end()) { - return; - } - - // Handle any pending fences for this buffer. - tracePendingFencesLocked(ctx, layerID, bufferID); - - // Complete current trace. - traceLocked(ctx, layerID, bufferID, frameNumber, timestamp, type, duration); - }); -} - -void TimeStats::traceFence(int32_t layerID, uint64_t bufferID, uint64_t frameNumber, - const std::shared_ptr& fence, - FrameEvent::BufferEventType type, nsecs_t startTime) { - TimeStatsDataSource::Trace([this, layerID, bufferID, frameNumber, &fence, type, - startTime](TimeStatsDataSource::TraceContext ctx) { - const nsecs_t signalTime = fence->getSignalTime(); - if (signalTime != Fence::SIGNAL_TIME_INVALID) { - std::lock_guard lock(mTraceMutex); - if (mTraceTracker.find(layerID) == mTraceTracker.end()) { - return; - } - - // Handle any pending fences for this buffer. - tracePendingFencesLocked(ctx, layerID, bufferID); - - if (signalTime != Fence::SIGNAL_TIME_PENDING) { - traceSpanLocked(ctx, layerID, bufferID, frameNumber, type, startTime, signalTime); - } else { - mTraceTracker[layerID].pendingFences[bufferID].push_back( - {.frameNumber = frameNumber, - .type = type, - .fence = fence, - .startTime = startTime}); - } - } - }); -} - -void TimeStats::tracePendingFencesLocked(TimeStatsDataSource::TraceContext& ctx, int32_t layerID, - uint64_t bufferID) { - if (mTraceTracker[layerID].pendingFences.count(bufferID)) { - auto& pendingFences = mTraceTracker[layerID].pendingFences[bufferID]; - for (size_t i = 0; i < pendingFences.size(); ++i) { - auto& pendingFence = pendingFences[i]; - - nsecs_t signalTime = Fence::SIGNAL_TIME_INVALID; - if (pendingFence.fence && pendingFence.fence->isValid()) { - signalTime = pendingFence.fence->getSignalTime(); - if (signalTime == Fence::SIGNAL_TIME_PENDING) { - continue; - } - } - - if (signalTime != Fence::SIGNAL_TIME_INVALID && - systemTime() - signalTime < kFenceSignallingDeadline) { - traceSpanLocked(ctx, layerID, bufferID, pendingFence.frameNumber, pendingFence.type, - pendingFence.startTime, signalTime); - } - - pendingFences.erase(pendingFences.begin() + i); - --i; - } - } -} - -void TimeStats::traceLocked(TimeStatsDataSource::TraceContext& ctx, int32_t layerID, - uint64_t bufferID, uint64_t frameNumber, nsecs_t timestamp, - FrameEvent::BufferEventType type, nsecs_t duration) { - auto packet = ctx.NewTracePacket(); - packet->set_timestamp(timestamp); - auto* event = packet->set_graphics_frame_event()->set_buffer_event(); - event->set_buffer_id(static_cast(bufferID)); - event->set_frame_number(frameNumber); - event->set_type(type); - - if (mTraceTracker.find(layerID) != mTraceTracker.end() && - !mTraceTracker[layerID].layerName.empty()) { - const std::string& layerName = mTraceTracker[layerID].layerName; - event->set_layer_name(layerName.c_str(), layerName.size()); - } - - if (duration > 0) { - event->set_duration_ns(duration); - } -} - -void TimeStats::traceSpanLocked(TimeStatsDataSource::TraceContext& ctx, int32_t layerID, - uint64_t bufferID, uint64_t frameNumber, - FrameEvent::BufferEventType type, nsecs_t startTime, - nsecs_t endTime) { - nsecs_t timestamp = endTime; - nsecs_t duration = 0; - if (startTime > 0 && startTime < endTime) { - timestamp = startTime; - duration = endTime - startTime; - } - traceLocked(ctx, layerID, bufferID, frameNumber, timestamp, type, duration); -} - void TimeStats::parseArgs(bool asProto, const Vector& args, std::string& result) { ATRACE_CALL(); @@ -207,8 +76,6 @@ std::string TimeStats::miniDump() { mTimeStatsTracker.size()); android::base::StringAppendF(&result, "Number of layers in the stats pool is %zu\n", mTimeStats.stats.size()); - android::base::StringAppendF(&result, "Number of layers currently being traced is %zu\n", - mTraceTracker.size()); return result; } @@ -542,15 +409,8 @@ void TimeStats::setPresentFence(int32_t layerID, uint64_t frameNumber, void TimeStats::onDestroy(int32_t layerID) { ATRACE_CALL(); ALOGV("[%d]-onDestroy", layerID); - { - std::lock_guard lock(mMutex); - mTimeStatsTracker.erase(layerID); - } - - { - std::lock_guard traceLock(mTraceMutex); - mTraceTracker.erase(layerID); - } + std::lock_guard lock(mMutex); + mTimeStatsTracker.erase(layerID); } void TimeStats::removeTimeRecord(int32_t layerID, uint64_t frameNumber) { diff --git a/services/surfaceflinger/TimeStats/TimeStats.h b/services/surfaceflinger/TimeStats/TimeStats.h index 470137a431..9ebc1adc90 100644 --- a/services/surfaceflinger/TimeStats/TimeStats.h +++ b/services/surfaceflinger/TimeStats/TimeStats.h @@ -17,8 +17,6 @@ #pragma once #include -#include -#include #include #include #include @@ -36,32 +34,8 @@ namespace android { class TimeStats { public: - using FrameEvent = perfetto::protos::pbzero::GraphicsFrameEvent; - virtual ~TimeStats() = default; - // Sets up the perfetto tracing backend and data source. - virtual void initializeTracing() = 0; - // Registers the data source with the perfetto backend. Called as part of initializeTracing() - // and should not be called manually outside of tests. Public to allow for substituting a - // perfetto::kInProcessBackend in tests. - virtual void registerTracingDataSource() = 0; - // Starts tracking a new layer for tracing. Needs to be called once before traceTimestamp() or - // traceFence() for each layer. - virtual void traceNewLayer(int32_t layerID, const std::string& layerName) = 0; - // Creates a trace point at the timestamp provided. - virtual void traceTimestamp(int32_t layerID, uint64_t bufferID, uint64_t frameNumber, - nsecs_t timestamp, FrameEvent::BufferEventType type, - nsecs_t duration = 0) = 0; - // Creates a trace point after the provided fence has been signalled. If a startTime is provided - // the trace will have be timestamped from startTime until fence signalling time. If no - // startTime is provided, a durationless trace point will be created timestamped at fence - // signalling time. If the fence hasn't signalled yet, the trace point will be created the next - // time after signalling a trace call for this buffer occurs. - virtual void traceFence(int32_t layerID, uint64_t bufferID, uint64_t frameNumber, - const std::shared_ptr& fence, - FrameEvent::BufferEventType type, nsecs_t startTime = 0) = 0; - virtual void parseArgs(bool asProto, const Vector& args, std::string& result) = 0; virtual bool isEnabled() = 0; virtual std::string miniDump() = 0; @@ -89,13 +63,6 @@ public: // Source of truth is RefrehRateStats. virtual void recordRefreshRate(uint32_t fps, nsecs_t duration) = 0; virtual void setPresentFenceGlobal(const std::shared_ptr& presentFence) = 0; - - static constexpr char kTimeStatsDataSource[] = "android.surfaceflinger.timestats"; - - // The maximum amount of time a fence has to signal before it is discarded. - // Used to avoid fence's from previous traces generating new trace points in later ones. - // Public for testing. - static constexpr nsecs_t kFenceSignallingDeadline = 60'000'000'000; // 60 seconds }; namespace impl { @@ -117,13 +84,6 @@ class TimeStats : public android::TimeStats { std::shared_ptr presentFence; }; - struct PendingFence { - uint64_t frameNumber; - FrameEvent::BufferEventType type; - std::shared_ptr fence; - nsecs_t startTime; - }; - struct LayerRecord { std::string layerName; // This is the index in timeRecords, at which the timestamps for that @@ -135,12 +95,6 @@ class TimeStats : public android::TimeStats { std::deque timeRecords; }; - struct TraceRecord { - std::string layerName; - using BufferID = uint64_t; - std::unordered_map> pendingFences; - }; - struct PowerTime { int32_t powerMode = HWC_POWER_MODE_OFF; nsecs_t prevTime = 0; @@ -152,23 +106,8 @@ class TimeStats : public android::TimeStats { }; public: - class TimeStatsDataSource : public perfetto::DataSource { - virtual void OnSetup(const SetupArgs&) override{}; - virtual void OnStart(const StartArgs&) override { ALOGV("TimeStats trace started"); }; - virtual void OnStop(const StopArgs&) override { ALOGV("TimeStats trace stopped"); }; - }; - TimeStats() = default; - void initializeTracing() override; - void registerTracingDataSource() override; - void traceNewLayer(int32_t layerID, const std::string& layerName) override; - void traceTimestamp(int32_t layerID, uint64_t bufferID, uint64_t frameNumber, nsecs_t timestamp, - FrameEvent::BufferEventType type, nsecs_t duration = 0) override; - void traceFence(int32_t layerID, uint64_t bufferID, uint64_t frameNumber, - const std::shared_ptr& fence, FrameEvent::BufferEventType type, - nsecs_t startTime = 0) override; - void parseArgs(bool asProto, const Vector& args, std::string& result) override; bool isEnabled() override; std::string miniDump() override; @@ -200,20 +139,6 @@ public: static const size_t MAX_NUM_TIME_RECORDS = 64; private: - // Checks if any pending fences for a layer and buffer have signalled and, if they have, creates - // trace points for them. - void tracePendingFencesLocked(TimeStatsDataSource::TraceContext& ctx, int32_t layerID, - uint64_t bufferID); - // Creates a trace point by translating a start time and an end time to a timestamp and - // duration. If startTime is later than end time it sets end time as the timestamp and the - // duration to 0. Used by traceFence(). - void traceSpanLocked(TimeStatsDataSource::TraceContext& ctx, int32_t layerID, uint64_t bufferID, - uint64_t frameNumber, FrameEvent::BufferEventType type, nsecs_t startTime, - nsecs_t endTime); - void traceLocked(TimeStatsDataSource::TraceContext& ctx, int32_t layerID, uint64_t bufferID, - uint64_t frameNumber, nsecs_t timestamp, FrameEvent::BufferEventType type, - nsecs_t duration = 0); - bool recordReadyLocked(int32_t layerID, TimeRecord* timeRecord); void flushAvailableRecordsToStatsLocked(int32_t layerID); void flushPowerTimeLocked(); @@ -232,9 +157,6 @@ private: PowerTime mPowerTime; GlobalRecord mGlobalRecord; - std::mutex mTraceMutex; - std::unordered_map mTraceTracker; - static const size_t MAX_NUM_LAYER_RECORDS = 200; static const size_t MAX_NUM_LAYER_STATS = 200; }; diff --git a/services/surfaceflinger/tests/unittests/Android.bp b/services/surfaceflinger/tests/unittests/Android.bp index 0eedf9b7b1..8d98af6298 100644 --- a/services/surfaceflinger/tests/unittests/Android.bp +++ b/services/surfaceflinger/tests/unittests/Android.bp @@ -51,6 +51,7 @@ cc_test { "RefreshRateStatsTest.cpp", "RegionSamplingTest.cpp", "TimeStatsTest.cpp", + "FrameTracerTest.cpp", "mock/DisplayHardware/MockComposer.cpp", "mock/DisplayHardware/MockDisplay.cpp", "mock/DisplayHardware/MockPowerAdvisor.cpp", @@ -63,6 +64,7 @@ cc_test { "mock/MockNativeWindowSurface.cpp", "mock/MockSurfaceInterceptor.cpp", "mock/MockTimeStats.cpp", + "mock/MockFrameTracer.cpp", "mock/system/window/MockNativeWindow.cpp", ], static_libs: [ diff --git a/services/surfaceflinger/tests/unittests/FrameTracerTest.cpp b/services/surfaceflinger/tests/unittests/FrameTracerTest.cpp new file mode 100644 index 0000000000..b5af591e25 --- /dev/null +++ b/services/surfaceflinger/tests/unittests/FrameTracerTest.cpp @@ -0,0 +1,396 @@ +/* + * Copyright 2019 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. + */ + +#undef LOG_TAG +#define LOG_TAG "LibSurfaceFlingerUnittests" + +#include +#include +#include +#include +#include + +#include "libsurfaceflinger_unittest_main.h" + +using namespace google::protobuf; + +namespace android { +namespace { + +class FrameTracerTest : public testing::Test { +public: + FrameTracerTest() { + const ::testing::TestInfo* const test_info = + ::testing::UnitTest::GetInstance()->current_test_info(); + ALOGD("**** Setting up for %s.%s\n", test_info->test_case_name(), test_info->name()); + + // Need to initialize tracing in process for testing, and only once per test suite. + static bool wasInitialized = false; + if (!wasInitialized) { + perfetto::TracingInitArgs args; + args.backends = perfetto::kInProcessBackend; + perfetto::Tracing::Initialize(args); + wasInitialized = true; + } + } + + ~FrameTracerTest() { + const ::testing::TestInfo* const test_info = + ::testing::UnitTest::GetInstance()->current_test_info(); + ALOGD("**** Tearing down after %s.%s\n", test_info->test_case_name(), test_info->name()); + } + + void SetUp() override { + mFrameTracer = std::make_unique(); + mFrameTracer->registerDataSource(); + } + + void TearDown() override { mFrameTracer.reset(); } + + // Each tracing session can be used for a single block of Start -> Stop. + static std::unique_ptr getTracingSessionForTest() { + perfetto::TraceConfig cfg; + cfg.set_duration_ms(500); + cfg.add_buffers()->set_size_kb(1024); + auto* ds_cfg = cfg.add_data_sources()->mutable_config(); + ds_cfg->set_name(FrameTracer::kFrameTracerDataSource); + + auto tracingSession = perfetto::Tracing::NewTrace(perfetto::kInProcessBackend); + tracingSession->Setup(cfg); + return tracingSession; + } + + std::unique_ptr mFrameTracer; + FenceToFenceTimeMap fenceFactory; +}; + +TEST_F(FrameTracerTest, traceNewLayerStartsTrackingLayerWhenTracing) { + EXPECT_EQ(mFrameTracer->miniDump(), + "FrameTracer miniDump:\nNumber of layers currently being traced is 0\n"); + + const std::string layerName = "co.layername#0"; + const int32_t layerID = 5; + mFrameTracer->traceNewLayer(layerID, layerName); + + EXPECT_EQ(mFrameTracer->miniDump(), + "FrameTracer miniDump:\nNumber of layers currently being traced is 0\n"); + + auto tracingSession = getTracingSessionForTest(); + tracingSession->StartBlocking(); + EXPECT_EQ(mFrameTracer->miniDump(), + "FrameTracer miniDump:\nNumber of layers currently being traced is 0\n"); + mFrameTracer->traceNewLayer(layerID, layerName); + EXPECT_EQ(mFrameTracer->miniDump(), + "FrameTracer miniDump:\nNumber of layers currently being traced is 1\n"); + tracingSession->StopBlocking(); +} + +TEST_F(FrameTracerTest, onDestroyRemovesTheTrackedLayer) { + EXPECT_EQ(mFrameTracer->miniDump(), + "FrameTracer miniDump:\nNumber of layers currently being traced is 0\n"); + + const std::string layerName = "co.layername#0"; + const int32_t layerID = 5; + const int32_t secondLayerID = 6; + + auto tracingSession = getTracingSessionForTest(); + tracingSession->StartBlocking(); + mFrameTracer->traceNewLayer(layerID, layerName); + mFrameTracer->traceNewLayer(secondLayerID, layerName); + EXPECT_EQ(mFrameTracer->miniDump(), + "FrameTracer miniDump:\nNumber of layers currently being traced is 2\n"); + tracingSession->StopBlocking(); + + mFrameTracer->onDestroy(layerID); + EXPECT_EQ(mFrameTracer->miniDump(), + "FrameTracer miniDump:\nNumber of layers currently being traced is 1\n"); + mFrameTracer->onDestroy(layerID); + EXPECT_EQ(mFrameTracer->miniDump(), + "FrameTracer miniDump:\nNumber of layers currently being traced is 1\n"); + mFrameTracer->onDestroy(secondLayerID); + EXPECT_EQ(mFrameTracer->miniDump(), + "FrameTracer miniDump:\nNumber of layers currently being traced is 0\n"); +} + +TEST_F(FrameTracerTest, canTraceAfterAddingLayer) { + const std::string layerName = "co.layername#0"; + const int32_t layerID = 1; + const uint32_t bufferID = 2; + const uint64_t frameNumber = 3; + const nsecs_t timestamp = 4; + const nsecs_t duration = 5; + const auto type = FrameTracer::FrameEvent::POST; + + { + auto tracingSession = getTracingSessionForTest(); + + tracingSession->StartBlocking(); + // Clean up irrelevant traces. + tracingSession->ReadTraceBlocking(); + + mFrameTracer->traceTimestamp(layerID, bufferID, frameNumber, timestamp, type, duration); + // Create second trace packet to finalize the previous one. + mFrameTracer->traceTimestamp(layerID, 0, 0, 0, FrameTracer::FrameEvent::UNSPECIFIED); + tracingSession->StopBlocking(); + + std::vector raw_trace = tracingSession->ReadTraceBlocking(); + EXPECT_EQ(raw_trace.size(), 0); + } + + { + auto tracingSession = getTracingSessionForTest(); + + tracingSession->StartBlocking(); + // Clean up irrelevant traces. + tracingSession->ReadTraceBlocking(); + + mFrameTracer->traceNewLayer(layerID, layerName); + mFrameTracer->traceTimestamp(layerID, bufferID, frameNumber, timestamp, type, duration); + // Create second trace packet to finalize the previous one. + mFrameTracer->traceTimestamp(layerID, 0, 0, 0, FrameTracer::FrameEvent::UNSPECIFIED); + tracingSession->StopBlocking(); + + std::vector raw_trace = tracingSession->ReadTraceBlocking(); + ASSERT_GT(raw_trace.size(), 0); + + perfetto::protos::Trace trace; + ASSERT_TRUE(trace.ParseFromArray(raw_trace.data(), int(raw_trace.size()))); + ASSERT_FALSE(trace.packet().empty()); + EXPECT_EQ(trace.packet().size(), 1); + + const auto& packet = trace.packet().Get(0); + ASSERT_TRUE(packet.has_timestamp()); + EXPECT_EQ(packet.timestamp(), timestamp); + ASSERT_TRUE(packet.has_graphics_frame_event()); + const auto& frame_event = packet.graphics_frame_event(); + ASSERT_TRUE(frame_event.has_buffer_event()); + const auto& buffer_event = frame_event.buffer_event(); + ASSERT_TRUE(buffer_event.has_buffer_id()); + EXPECT_EQ(buffer_event.buffer_id(), bufferID); + ASSERT_TRUE(buffer_event.has_frame_number()); + EXPECT_EQ(buffer_event.frame_number(), frameNumber); + ASSERT_TRUE(buffer_event.has_type()); + EXPECT_EQ(buffer_event.type(), perfetto::protos::GraphicsFrameEvent_BufferEventType(type)); + ASSERT_TRUE(buffer_event.has_duration_ns()); + EXPECT_EQ(buffer_event.duration_ns(), duration); + } +} + +TEST_F(FrameTracerTest, traceFenceTriggersOnNextTraceAfterFenceFired) { + const std::string layerName = "co.layername#0"; + const int32_t layerID = 5; + const uint32_t bufferID = 4; + const uint64_t frameNumber = 3; + const auto type = FrameTracer::FrameEvent::ACQUIRE_FENCE; + + { + auto fenceTime = fenceFactory.createFenceTimeForTest(Fence::NO_FENCE); + fenceFactory.signalAllForTest(Fence::NO_FENCE, Fence::SIGNAL_TIME_PENDING); + auto tracingSession = getTracingSessionForTest(); + tracingSession->StartBlocking(); + // Clean up irrelevant traces. + tracingSession->ReadTraceBlocking(); + // Trace. + mFrameTracer->traceNewLayer(layerID, layerName); + mFrameTracer->traceFence(layerID, bufferID, frameNumber, fenceTime, type); + // Create extra trace packet to (hopefully not) trigger and finalize the fence packet. + mFrameTracer->traceTimestamp(layerID, bufferID, 0, 0, FrameTracer::FrameEvent::UNSPECIFIED); + tracingSession->StopBlocking(); + std::vector raw_trace = tracingSession->ReadTraceBlocking(); + EXPECT_EQ(raw_trace.size(), 0); + } + + { + auto fenceTime = fenceFactory.createFenceTimeForTest(Fence::NO_FENCE); + auto tracingSession = getTracingSessionForTest(); + tracingSession->StartBlocking(); + // Clean up irrelevant traces. + tracingSession->ReadTraceBlocking(); + mFrameTracer->traceNewLayer(layerID, layerName); + mFrameTracer->traceFence(layerID, bufferID, frameNumber, fenceTime, type); + const nsecs_t timestamp = systemTime(); + fenceFactory.signalAllForTest(Fence::NO_FENCE, timestamp); + // Create extra trace packet to trigger and finalize fence trace packets. + mFrameTracer->traceTimestamp(layerID, bufferID, 0, 0, FrameTracer::FrameEvent::UNSPECIFIED); + tracingSession->StopBlocking(); + + std::vector raw_trace = tracingSession->ReadTraceBlocking(); + ASSERT_GT(raw_trace.size(), 0); + + perfetto::protos::Trace trace; + ASSERT_TRUE(trace.ParseFromArray(raw_trace.data(), int(raw_trace.size()))); + ASSERT_FALSE(trace.packet().empty()); + EXPECT_EQ(trace.packet().size(), 2); // Two packets because of the extra trace made above. + + const auto& packet = trace.packet().Get(1); + ASSERT_TRUE(packet.has_timestamp()); + EXPECT_EQ(packet.timestamp(), timestamp); + ASSERT_TRUE(packet.has_graphics_frame_event()); + const auto& frame_event = packet.graphics_frame_event(); + ASSERT_TRUE(frame_event.has_buffer_event()); + const auto& buffer_event = frame_event.buffer_event(); + ASSERT_TRUE(buffer_event.has_buffer_id()); + EXPECT_EQ(buffer_event.buffer_id(), bufferID); + ASSERT_TRUE(buffer_event.has_frame_number()); + EXPECT_EQ(buffer_event.frame_number(), frameNumber); + ASSERT_TRUE(buffer_event.has_type()); + EXPECT_EQ(buffer_event.type(), perfetto::protos::GraphicsFrameEvent_BufferEventType(type)); + EXPECT_FALSE(buffer_event.has_duration_ns()); + } +} + +TEST_F(FrameTracerTest, traceFenceWithStartTimeAfterSignalTime_ShouldHaveNoDuration) { + const std::string layerName = "co.layername#0"; + const int32_t layerID = 5; + const uint32_t bufferID = 4; + const uint64_t frameNumber = 3; + const auto type = FrameTracer::FrameEvent::ACQUIRE_FENCE; + + auto tracingSession = getTracingSessionForTest(); + + tracingSession->StartBlocking(); + // Clean up irrelevant traces. + tracingSession->ReadTraceBlocking(); + mFrameTracer->traceNewLayer(layerID, layerName); + + // traceFence called after fence signalled. + const nsecs_t signalTime1 = systemTime(); + const nsecs_t startTime1 = signalTime1 + 100000; + auto fence1 = fenceFactory.createFenceTimeForTest(Fence::NO_FENCE); + fenceFactory.signalAllForTest(Fence::NO_FENCE, signalTime1); + mFrameTracer->traceFence(layerID, bufferID, frameNumber, fence1, type, startTime1); + + // traceFence called before fence signalled. + const nsecs_t signalTime2 = systemTime(); + const nsecs_t startTime2 = signalTime2 + 100000; + auto fence2 = fenceFactory.createFenceTimeForTest(Fence::NO_FENCE); + mFrameTracer->traceFence(layerID, bufferID, frameNumber, fence2, type, startTime2); + fenceFactory.signalAllForTest(Fence::NO_FENCE, signalTime2); + + // Create extra trace packet to trigger and finalize fence trace packets. + mFrameTracer->traceTimestamp(layerID, bufferID, 0, 0, FrameTracer::FrameEvent::UNSPECIFIED); + tracingSession->StopBlocking(); + + std::vector raw_trace = tracingSession->ReadTraceBlocking(); + ASSERT_GT(raw_trace.size(), 0); + + perfetto::protos::Trace trace; + ASSERT_TRUE(trace.ParseFromArray(raw_trace.data(), int(raw_trace.size()))); + ASSERT_FALSE(trace.packet().empty()); + EXPECT_EQ(trace.packet().size(), 2); + + const auto& packet1 = trace.packet().Get(0); + ASSERT_TRUE(packet1.has_timestamp()); + EXPECT_EQ(packet1.timestamp(), signalTime1); + ASSERT_TRUE(packet1.has_graphics_frame_event()); + ASSERT_TRUE(packet1.graphics_frame_event().has_buffer_event()); + ASSERT_FALSE(packet1.graphics_frame_event().buffer_event().has_duration_ns()); + + const auto& packet2 = trace.packet().Get(1); + ASSERT_TRUE(packet2.has_timestamp()); + EXPECT_EQ(packet2.timestamp(), signalTime2); + ASSERT_TRUE(packet2.has_graphics_frame_event()); + ASSERT_TRUE(packet2.graphics_frame_event().has_buffer_event()); + ASSERT_FALSE(packet2.graphics_frame_event().buffer_event().has_duration_ns()); +} + +TEST_F(FrameTracerTest, traceFenceOlderThanDeadline_ShouldBeIgnored) { + const std::string layerName = "co.layername#0"; + const int32_t layerID = 5; + const uint32_t bufferID = 4; + const uint64_t frameNumber = 3; + const auto type = FrameTracer::FrameEvent::ACQUIRE_FENCE; + const nsecs_t signalTime = systemTime() - FrameTracer::kFenceSignallingDeadline; + + auto tracingSession = getTracingSessionForTest(); + auto fence = fenceFactory.createFenceTimeForTest(Fence::NO_FENCE); + + tracingSession->StartBlocking(); + // Clean up irrelevant traces. + tracingSession->ReadTraceBlocking(); + mFrameTracer->traceNewLayer(layerID, layerName); + mFrameTracer->traceFence(layerID, bufferID, frameNumber, fence, type); + fenceFactory.signalAllForTest(Fence::NO_FENCE, signalTime); + // Create extra trace packet to trigger and finalize any previous fence packets. + mFrameTracer->traceTimestamp(layerID, bufferID, 0, 0, FrameTracer::FrameEvent::UNSPECIFIED); + tracingSession->StopBlocking(); + + std::vector raw_trace = tracingSession->ReadTraceBlocking(); + EXPECT_EQ(raw_trace.size(), 0); +} + +TEST_F(FrameTracerTest, traceFenceWithValidStartTime_ShouldHaveCorrectDuration) { + const std::string layerName = "co.layername#0"; + const int32_t layerID = 5; + const uint32_t bufferID = 4; + const uint64_t frameNumber = 3; + const auto type = FrameTracer::FrameEvent::ACQUIRE_FENCE; + const nsecs_t duration = 1234; + + auto tracingSession = getTracingSessionForTest(); + + tracingSession->StartBlocking(); + // Clean up irrelevant traces. + tracingSession->ReadTraceBlocking(); + mFrameTracer->traceNewLayer(layerID, layerName); + + // traceFence called after fence signalled. + const nsecs_t signalTime1 = systemTime(); + const nsecs_t startTime1 = signalTime1 - duration; + auto fence1 = fenceFactory.createFenceTimeForTest(Fence::NO_FENCE); + fenceFactory.signalAllForTest(Fence::NO_FENCE, signalTime1); + mFrameTracer->traceFence(layerID, bufferID, frameNumber, fence1, type, startTime1); + + // traceFence called before fence signalled. + const nsecs_t signalTime2 = systemTime(); + const nsecs_t startTime2 = signalTime2 - duration; + auto fence2 = fenceFactory.createFenceTimeForTest(Fence::NO_FENCE); + mFrameTracer->traceFence(layerID, bufferID, frameNumber, fence2, type, startTime2); + fenceFactory.signalAllForTest(Fence::NO_FENCE, signalTime2); + + // Create extra trace packet to trigger and finalize fence trace packets. + mFrameTracer->traceTimestamp(layerID, bufferID, 0, 0, FrameTracer::FrameEvent::UNSPECIFIED); + tracingSession->StopBlocking(); + + std::vector raw_trace = tracingSession->ReadTraceBlocking(); + ASSERT_GT(raw_trace.size(), 0); + + perfetto::protos::Trace trace; + ASSERT_TRUE(trace.ParseFromArray(raw_trace.data(), int(raw_trace.size()))); + ASSERT_FALSE(trace.packet().empty()); + EXPECT_EQ(trace.packet().size(), 2); + + const auto& packet1 = trace.packet().Get(0); + ASSERT_TRUE(packet1.has_timestamp()); + EXPECT_EQ(packet1.timestamp(), startTime1); + ASSERT_TRUE(packet1.has_graphics_frame_event()); + ASSERT_TRUE(packet1.graphics_frame_event().has_buffer_event()); + ASSERT_TRUE(packet1.graphics_frame_event().buffer_event().has_duration_ns()); + const auto& buffer_event1 = packet1.graphics_frame_event().buffer_event(); + EXPECT_EQ(buffer_event1.duration_ns(), duration); + + const auto& packet2 = trace.packet().Get(1); + ASSERT_TRUE(packet2.has_timestamp()); + EXPECT_EQ(packet2.timestamp(), startTime2); + ASSERT_TRUE(packet2.has_graphics_frame_event()); + ASSERT_TRUE(packet2.graphics_frame_event().has_buffer_event()); + ASSERT_TRUE(packet2.graphics_frame_event().buffer_event().has_duration_ns()); + const auto& buffer_event2 = packet2.graphics_frame_event().buffer_event(); + EXPECT_EQ(buffer_event2.duration_ns(), duration); +} + +} // namespace +} // namespace android diff --git a/services/surfaceflinger/tests/unittests/TimeStatsTest.cpp b/services/surfaceflinger/tests/unittests/TimeStatsTest.cpp index f01e603f20..ffacbfef16 100644 --- a/services/surfaceflinger/tests/unittests/TimeStatsTest.cpp +++ b/services/surfaceflinger/tests/unittests/TimeStatsTest.cpp @@ -20,8 +20,8 @@ #include #include #include + #include -#include #include #include @@ -109,15 +109,6 @@ public: const ::testing::TestInfo* const test_info = ::testing::UnitTest::GetInstance()->current_test_info(); ALOGD("**** Setting up for %s.%s\n", test_info->test_case_name(), test_info->name()); - - // Need to initialize tracing in process for testing, and only once per test suite. - static bool wasInitialized = false; - if (!wasInitialized) { - perfetto::TracingInitArgs args; - args.backends = perfetto::kInProcessBackend; - perfetto::Tracing::Initialize(args); - wasInitialized = true; - } } ~TimeStatsTest() { @@ -126,13 +117,6 @@ public: ALOGD("**** Tearing down after %s.%s\n", test_info->test_case_name(), test_info->name()); } - void SetUp() override { - mTimeStats = std::make_unique(); - mTimeStats->registerTracingDataSource(); - } - - void TearDown() override { mTimeStats.reset(); } - std::string inputCommand(InputCommand cmd, bool useProto); void setTimeStamp(TimeStamp type, int32_t id, uint64_t frameNumber, nsecs_t ts); @@ -147,22 +131,8 @@ public: } } - // Each tracing session can be used for a single block of Start -> Stop. - static std::unique_ptr getTracingSessionForTest() { - perfetto::TraceConfig cfg; - cfg.set_duration_ms(500); - cfg.add_buffers()->set_size_kb(1024); - auto* ds_cfg = cfg.add_data_sources()->mutable_config(); - ds_cfg->set_name(TimeStats::kTimeStatsDataSource); - - auto tracingSession = perfetto::Tracing::NewTrace(perfetto::kInProcessBackend); - tracingSession->Setup(cfg); - return tracingSession; - } - std::mt19937 mRandomEngine = std::mt19937(std::random_device()()); - std::unique_ptr mTimeStats; - FenceToFenceTimeMap fenceFactory; + std::unique_ptr mTimeStats = std::make_unique(); }; std::string TimeStatsTest::inputCommand(InputCommand cmd, bool useProto) { @@ -239,330 +209,6 @@ int32_t TimeStatsTest::genRandomInt32(int32_t begin, int32_t end) { return distr(mRandomEngine); } -TEST_F(TimeStatsTest, traceNewLayerStartsTrackingLayerWhenTracing) { - EXPECT_EQ(mTimeStats->miniDump(), - "TimeStats miniDump:\nNumber of layers currently being tracked is 0\nNumber of " - "layers in the stats pool is 0\nNumber of layers currently being traced is 0\n"); - - const std::string layerName = "co.layername#0"; - const int32_t layerID = 5; - mTimeStats->traceNewLayer(layerID, layerName); - - EXPECT_EQ(mTimeStats->miniDump(), - "TimeStats miniDump:\nNumber of layers currently being tracked is 0\nNumber of " - "layers in the stats pool is 0\nNumber of layers currently being traced is 0\n"); - - auto tracingSession = getTracingSessionForTest(); - tracingSession->StartBlocking(); - EXPECT_EQ(mTimeStats->miniDump(), - "TimeStats miniDump:\nNumber of layers currently being tracked is 0\nNumber of " - "layers in the stats pool is 0\nNumber of layers currently being traced is 0\n"); - mTimeStats->traceNewLayer(layerID, layerName); - EXPECT_EQ(mTimeStats->miniDump(), - "TimeStats miniDump:\nNumber of layers currently being tracked is 0\nNumber of " - "layers in the stats pool is 0\nNumber of layers currently being traced is 1\n"); - tracingSession->StopBlocking(); -} - -TEST_F(TimeStatsTest, onDestroyRemovesTheTrackedLayer) { - EXPECT_EQ(mTimeStats->miniDump(), - "TimeStats miniDump:\nNumber of layers currently being tracked is 0\nNumber of " - "layers in the stats pool is 0\nNumber of layers currently being traced is 0\n"); - - const std::string layerName = "co.layername#0"; - const int32_t layerID = 5; - const int32_t secondLayerID = 6; - - auto tracingSession = getTracingSessionForTest(); - tracingSession->StartBlocking(); - mTimeStats->traceNewLayer(layerID, layerName); - mTimeStats->traceNewLayer(secondLayerID, layerName); - EXPECT_EQ(mTimeStats->miniDump(), - "TimeStats miniDump:\nNumber of layers currently being tracked is 0\nNumber of " - "layers in the stats pool is 0\nNumber of layers currently being traced is 2\n"); - tracingSession->StopBlocking(); - - mTimeStats->onDestroy(layerID); - EXPECT_EQ(mTimeStats->miniDump(), - "TimeStats miniDump:\nNumber of layers currently being tracked is 0\nNumber of " - "layers in the stats pool is 0\nNumber of layers currently being traced is 1\n"); - mTimeStats->onDestroy(layerID); - EXPECT_EQ(mTimeStats->miniDump(), - "TimeStats miniDump:\nNumber of layers currently being tracked is 0\nNumber of " - "layers in the stats pool is 0\nNumber of layers currently being traced is 1\n"); - mTimeStats->onDestroy(secondLayerID); - EXPECT_EQ(mTimeStats->miniDump(), - "TimeStats miniDump:\nNumber of layers currently being tracked is 0\nNumber of " - "layers in the stats pool is 0\nNumber of layers currently being traced is 0\n"); -} - -TEST_F(TimeStatsTest, canTraceAfterAddingLayer) { - const std::string layerName = "co.layername#0"; - const int32_t layerID = 1; - const uint32_t bufferID = 2; - const uint64_t frameNumber = 3; - const nsecs_t timestamp = 4; - const nsecs_t duration = 5; - const auto type = TimeStats::FrameEvent::POST; - - { - auto tracingSession = getTracingSessionForTest(); - - tracingSession->StartBlocking(); - // Clean up irrelevant traces. - tracingSession->ReadTraceBlocking(); - - mTimeStats->traceTimestamp(layerID, bufferID, frameNumber, timestamp, type, duration); - // Create second trace packet to finalize the previous one. - mTimeStats->traceTimestamp(layerID, 0, 0, 0, TimeStats::FrameEvent::UNSPECIFIED); - tracingSession->StopBlocking(); - - std::vector raw_trace = tracingSession->ReadTraceBlocking(); - EXPECT_EQ(raw_trace.size(), 0); - } - - { - auto tracingSession = getTracingSessionForTest(); - - tracingSession->StartBlocking(); - // Clean up irrelevant traces. - tracingSession->ReadTraceBlocking(); - - mTimeStats->traceNewLayer(layerID, layerName); - mTimeStats->traceTimestamp(layerID, bufferID, frameNumber, timestamp, type, duration); - // Create second trace packet to finalize the previous one. - mTimeStats->traceTimestamp(layerID, 0, 0, 0, TimeStats::FrameEvent::UNSPECIFIED); - tracingSession->StopBlocking(); - - std::vector raw_trace = tracingSession->ReadTraceBlocking(); - ASSERT_GT(raw_trace.size(), 0); - - perfetto::protos::Trace trace; - ASSERT_TRUE(trace.ParseFromArray(raw_trace.data(), int(raw_trace.size()))); - ASSERT_FALSE(trace.packet().empty()); - EXPECT_EQ(trace.packet().size(), 1); - - const auto& packet = trace.packet().Get(0); - ASSERT_TRUE(packet.has_timestamp()); - EXPECT_EQ(packet.timestamp(), timestamp); - ASSERT_TRUE(packet.has_graphics_frame_event()); - const auto& frame_event = packet.graphics_frame_event(); - ASSERT_TRUE(frame_event.has_buffer_event()); - const auto& buffer_event = frame_event.buffer_event(); - ASSERT_TRUE(buffer_event.has_buffer_id()); - EXPECT_EQ(buffer_event.buffer_id(), bufferID); - ASSERT_TRUE(buffer_event.has_frame_number()); - EXPECT_EQ(buffer_event.frame_number(), frameNumber); - ASSERT_TRUE(buffer_event.has_type()); - EXPECT_EQ(buffer_event.type(), perfetto::protos::GraphicsFrameEvent_BufferEventType(type)); - ASSERT_TRUE(buffer_event.has_duration_ns()); - EXPECT_EQ(buffer_event.duration_ns(), duration); - } -} - -TEST_F(TimeStatsTest, traceFenceTriggersOnNextTraceAfterFenceFired) { - const std::string layerName = "co.layername#0"; - const int32_t layerID = 5; - const uint32_t bufferID = 4; - const uint64_t frameNumber = 3; - const auto type = TimeStats::FrameEvent::ACQUIRE_FENCE; - - { - auto fenceTime = fenceFactory.createFenceTimeForTest(Fence::NO_FENCE); - fenceFactory.signalAllForTest(Fence::NO_FENCE, Fence::SIGNAL_TIME_PENDING); - auto tracingSession = getTracingSessionForTest(); - tracingSession->StartBlocking(); - // Clean up irrelevant traces. - tracingSession->ReadTraceBlocking(); - // Trace. - mTimeStats->traceNewLayer(layerID, layerName); - mTimeStats->traceFence(layerID, bufferID, frameNumber, fenceTime, type); - // Create extra trace packet to (hopefully not) trigger and finalize the fence packet. - mTimeStats->traceTimestamp(layerID, bufferID, 0, 0, TimeStats::FrameEvent::UNSPECIFIED); - tracingSession->StopBlocking(); - std::vector raw_trace = tracingSession->ReadTraceBlocking(); - EXPECT_EQ(raw_trace.size(), 0); - } - - { - auto fenceTime = fenceFactory.createFenceTimeForTest(Fence::NO_FENCE); - auto tracingSession = getTracingSessionForTest(); - tracingSession->StartBlocking(); - // Clean up irrelevant traces. - tracingSession->ReadTraceBlocking(); - mTimeStats->traceNewLayer(layerID, layerName); - mTimeStats->traceFence(layerID, bufferID, frameNumber, fenceTime, type); - const nsecs_t timestamp = systemTime(); - fenceFactory.signalAllForTest(Fence::NO_FENCE, timestamp); - // Create extra trace packet to trigger and finalize fence trace packets. - mTimeStats->traceTimestamp(layerID, bufferID, 0, 0, TimeStats::FrameEvent::UNSPECIFIED); - tracingSession->StopBlocking(); - - std::vector raw_trace = tracingSession->ReadTraceBlocking(); - ASSERT_GT(raw_trace.size(), 0); - - perfetto::protos::Trace trace; - ASSERT_TRUE(trace.ParseFromArray(raw_trace.data(), int(raw_trace.size()))); - ASSERT_FALSE(trace.packet().empty()); - EXPECT_EQ(trace.packet().size(), 2); // Two packets because of the extra trace made above. - - const auto& packet = trace.packet().Get(1); - ASSERT_TRUE(packet.has_timestamp()); - EXPECT_EQ(packet.timestamp(), timestamp); - ASSERT_TRUE(packet.has_graphics_frame_event()); - const auto& frame_event = packet.graphics_frame_event(); - ASSERT_TRUE(frame_event.has_buffer_event()); - const auto& buffer_event = frame_event.buffer_event(); - ASSERT_TRUE(buffer_event.has_buffer_id()); - EXPECT_EQ(buffer_event.buffer_id(), bufferID); - ASSERT_TRUE(buffer_event.has_frame_number()); - EXPECT_EQ(buffer_event.frame_number(), frameNumber); - ASSERT_TRUE(buffer_event.has_type()); - EXPECT_EQ(buffer_event.type(), perfetto::protos::GraphicsFrameEvent_BufferEventType(type)); - EXPECT_FALSE(buffer_event.has_duration_ns()); - } -} - -TEST_F(TimeStatsTest, traceFenceWithStartTimeAfterSignalTime_ShouldHaveNoDuration) { - const std::string layerName = "co.layername#0"; - const int32_t layerID = 5; - const uint32_t bufferID = 4; - const uint64_t frameNumber = 3; - const auto type = TimeStats::FrameEvent::ACQUIRE_FENCE; - - auto tracingSession = getTracingSessionForTest(); - - tracingSession->StartBlocking(); - // Clean up irrelevant traces. - tracingSession->ReadTraceBlocking(); - mTimeStats->traceNewLayer(layerID, layerName); - - // traceFence called after fence signalled. - const nsecs_t signalTime1 = systemTime(); - const nsecs_t startTime1 = signalTime1 + 100000; - auto fence1 = fenceFactory.createFenceTimeForTest(Fence::NO_FENCE); - fenceFactory.signalAllForTest(Fence::NO_FENCE, signalTime1); - mTimeStats->traceFence(layerID, bufferID, frameNumber, fence1, type, startTime1); - - // traceFence called before fence signalled. - const nsecs_t signalTime2 = systemTime(); - const nsecs_t startTime2 = signalTime2 + 100000; - auto fence2 = fenceFactory.createFenceTimeForTest(Fence::NO_FENCE); - mTimeStats->traceFence(layerID, bufferID, frameNumber, fence2, type, startTime2); - fenceFactory.signalAllForTest(Fence::NO_FENCE, signalTime2); - - // Create extra trace packet to trigger and finalize fence trace packets. - mTimeStats->traceTimestamp(layerID, bufferID, 0, 0, TimeStats::FrameEvent::UNSPECIFIED); - tracingSession->StopBlocking(); - - std::vector raw_trace = tracingSession->ReadTraceBlocking(); - ASSERT_GT(raw_trace.size(), 0); - - perfetto::protos::Trace trace; - ASSERT_TRUE(trace.ParseFromArray(raw_trace.data(), int(raw_trace.size()))); - ASSERT_FALSE(trace.packet().empty()); - EXPECT_EQ(trace.packet().size(), 2); - - const auto& packet1 = trace.packet().Get(0); - ASSERT_TRUE(packet1.has_timestamp()); - EXPECT_EQ(packet1.timestamp(), signalTime1); - ASSERT_TRUE(packet1.has_graphics_frame_event()); - ASSERT_TRUE(packet1.graphics_frame_event().has_buffer_event()); - ASSERT_FALSE(packet1.graphics_frame_event().buffer_event().has_duration_ns()); - - const auto& packet2 = trace.packet().Get(1); - ASSERT_TRUE(packet2.has_timestamp()); - EXPECT_EQ(packet2.timestamp(), signalTime2); - ASSERT_TRUE(packet2.has_graphics_frame_event()); - ASSERT_TRUE(packet2.graphics_frame_event().has_buffer_event()); - ASSERT_FALSE(packet2.graphics_frame_event().buffer_event().has_duration_ns()); -} - -TEST_F(TimeStatsTest, traceFenceOlderThanDeadline_ShouldBeIgnored) { - const std::string layerName = "co.layername#0"; - const int32_t layerID = 5; - const uint32_t bufferID = 4; - const uint64_t frameNumber = 3; - const auto type = TimeStats::FrameEvent::ACQUIRE_FENCE; - const nsecs_t signalTime = systemTime() - TimeStats::kFenceSignallingDeadline; - - auto tracingSession = getTracingSessionForTest(); - auto fence = fenceFactory.createFenceTimeForTest(Fence::NO_FENCE); - - tracingSession->StartBlocking(); - // Clean up irrelevant traces. - tracingSession->ReadTraceBlocking(); - mTimeStats->traceNewLayer(layerID, layerName); - mTimeStats->traceFence(layerID, bufferID, frameNumber, fence, type); - fenceFactory.signalAllForTest(Fence::NO_FENCE, signalTime); - // Create extra trace packet to trigger and finalize any previous fence packets. - mTimeStats->traceTimestamp(layerID, bufferID, 0, 0, TimeStats::FrameEvent::UNSPECIFIED); - tracingSession->StopBlocking(); - - std::vector raw_trace = tracingSession->ReadTraceBlocking(); - EXPECT_EQ(raw_trace.size(), 0); -} - -TEST_F(TimeStatsTest, traceFenceWithValidStartTime_ShouldHaveCorrectDuration) { - const std::string layerName = "co.layername#0"; - const int32_t layerID = 5; - const uint32_t bufferID = 4; - const uint64_t frameNumber = 3; - const auto type = TimeStats::FrameEvent::ACQUIRE_FENCE; - const nsecs_t duration = 1234; - - auto tracingSession = getTracingSessionForTest(); - - tracingSession->StartBlocking(); - // Clean up irrelevant traces. - tracingSession->ReadTraceBlocking(); - mTimeStats->traceNewLayer(layerID, layerName); - - // traceFence called after fence signalled. - const nsecs_t signalTime1 = systemTime(); - const nsecs_t startTime1 = signalTime1 - duration; - auto fence1 = fenceFactory.createFenceTimeForTest(Fence::NO_FENCE); - fenceFactory.signalAllForTest(Fence::NO_FENCE, signalTime1); - mTimeStats->traceFence(layerID, bufferID, frameNumber, fence1, type, startTime1); - - // traceFence called before fence signalled. - const nsecs_t signalTime2 = systemTime(); - const nsecs_t startTime2 = signalTime2 - duration; - auto fence2 = fenceFactory.createFenceTimeForTest(Fence::NO_FENCE); - mTimeStats->traceFence(layerID, bufferID, frameNumber, fence2, type, startTime2); - fenceFactory.signalAllForTest(Fence::NO_FENCE, signalTime2); - - // Create extra trace packet to trigger and finalize fence trace packets. - mTimeStats->traceTimestamp(layerID, bufferID, 0, 0, TimeStats::FrameEvent::UNSPECIFIED); - tracingSession->StopBlocking(); - - std::vector raw_trace = tracingSession->ReadTraceBlocking(); - ASSERT_GT(raw_trace.size(), 0); - - perfetto::protos::Trace trace; - ASSERT_TRUE(trace.ParseFromArray(raw_trace.data(), int(raw_trace.size()))); - ASSERT_FALSE(trace.packet().empty()); - EXPECT_EQ(trace.packet().size(), 2); - - const auto& packet1 = trace.packet().Get(0); - ASSERT_TRUE(packet1.has_timestamp()); - EXPECT_EQ(packet1.timestamp(), startTime1); - ASSERT_TRUE(packet1.has_graphics_frame_event()); - ASSERT_TRUE(packet1.graphics_frame_event().has_buffer_event()); - ASSERT_TRUE(packet1.graphics_frame_event().buffer_event().has_duration_ns()); - const auto& buffer_event1 = packet1.graphics_frame_event().buffer_event(); - EXPECT_EQ(buffer_event1.duration_ns(), duration); - - const auto& packet2 = trace.packet().Get(1); - ASSERT_TRUE(packet2.has_timestamp()); - EXPECT_EQ(packet2.timestamp(), startTime2); - ASSERT_TRUE(packet2.has_graphics_frame_event()); - ASSERT_TRUE(packet2.graphics_frame_event().has_buffer_event()); - ASSERT_TRUE(packet2.graphics_frame_event().buffer_event().has_duration_ns()); - const auto& buffer_event2 = packet2.graphics_frame_event().buffer_event(); - EXPECT_EQ(buffer_event2.duration_ns(), duration); -} - TEST_F(TimeStatsTest, canEnableAndDisableTimeStats) { EXPECT_TRUE(inputCommand(InputCommand::ENABLE, FMT_STRING).empty()); ASSERT_TRUE(mTimeStats->isEnabled()); diff --git a/services/surfaceflinger/tests/unittests/mock/MockFrameTracer.cpp b/services/surfaceflinger/tests/unittests/mock/MockFrameTracer.cpp new file mode 100644 index 0000000000..358dfdb856 --- /dev/null +++ b/services/surfaceflinger/tests/unittests/mock/MockFrameTracer.cpp @@ -0,0 +1,27 @@ +/* + * Copyright 2019 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 "mock/MockFrameTracer.h" + +namespace android { +namespace mock { + +// Explicit default instantiation is recommended. +FrameTracer::FrameTracer() = default; +FrameTracer::~FrameTracer() = default; + +} // namespace mock +} // namespace android diff --git a/services/surfaceflinger/tests/unittests/mock/MockFrameTracer.h b/services/surfaceflinger/tests/unittests/mock/MockFrameTracer.h new file mode 100644 index 0000000000..f768b8114d --- /dev/null +++ b/services/surfaceflinger/tests/unittests/mock/MockFrameTracer.h @@ -0,0 +1,43 @@ +/* + * Copyright 2019 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 + +#include "FrameTracer/FrameTracer.h" + +namespace android { +namespace mock { + +class FrameTracer : public android::FrameTracer { +public: + FrameTracer(); + ~FrameTracer(); + + MOCK_METHOD0(initialize, void()); + MOCK_METHOD0(registerDataSource, void()); + MOCK_METHOD2(traceNewLayer, void(int32_t, const std::string&)); + MOCK_METHOD6(traceTimestamp, + void(int32_t, uint64_t, uint64_t, nsecs_t, FrameEvent::BufferEventType, nsecs_t)); + MOCK_METHOD6(traceFence, + void(int32_t, uint64_t, uint64_t, const std::shared_ptr&, + FrameEvent::BufferEventType, nsecs_t)); + MOCK_METHOD0(miniDump, std::string()); +}; + +} // namespace mock +} // namespace android diff --git a/services/surfaceflinger/tests/unittests/mock/MockTimeStats.h b/services/surfaceflinger/tests/unittests/mock/MockTimeStats.h index 542c70a8fb..b1634a8da7 100644 --- a/services/surfaceflinger/tests/unittests/mock/MockTimeStats.h +++ b/services/surfaceflinger/tests/unittests/mock/MockTimeStats.h @@ -28,14 +28,6 @@ public: TimeStats(); ~TimeStats() override; - MOCK_METHOD0(initializeTracing, void()); - MOCK_METHOD0(registerTracingDataSource, void()); - MOCK_METHOD2(traceNewLayer, void(int32_t, const std::string&)); - MOCK_METHOD6(traceTimestamp, - void(int32_t, uint64_t, uint64_t, nsecs_t, FrameEvent::BufferEventType, nsecs_t)); - MOCK_METHOD6(traceFence, - void(int32_t, uint64_t, uint64_t, const std::shared_ptr&, - FrameEvent::BufferEventType, nsecs_t)); MOCK_METHOD3(parseArgs, void(bool, const Vector&, std::string&)); MOCK_METHOD0(isEnabled, bool()); MOCK_METHOD0(miniDump, std::string()); -- cgit v1.2.3-59-g8ed1b From b15ea8a9b506650b44c8ac21b640114e95ec2cef Mon Sep 17 00:00:00 2001 From: chaviw Date: Tue, 3 Sep 2019 12:40:22 -0700 Subject: Use getLayerStack() instead of layerStack for input info When there's no displayId, the layerStack should be used. The current code was using mDrawingState.layerStack which is incorrect because only the layerStack for the root of the tree is correct. Instead, use getLayerStack() which traverses the hierarchy to find the root's layerStack. Test: Uses correct layerStack instead of 0 for input with unset displayIds Change-Id: Ic8a06c562e970b0f328c539edfa51e206734934f --- services/surfaceflinger/Layer.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'services/surfaceflinger/Layer.cpp') diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp index 5121835cae..964bc1d02a 100644 --- a/services/surfaceflinger/Layer.cpp +++ b/services/surfaceflinger/Layer.cpp @@ -1946,7 +1946,7 @@ InputWindowInfo Layer::fillInputInfo() { InputWindowInfo info = mDrawingState.inputInfo; if (info.displayId == ADISPLAY_ID_NONE) { - info.displayId = mDrawingState.layerStack; + info.displayId = getLayerStack(); } ui::Transform t = getTransform(); -- cgit v1.2.3-59-g8ed1b From 214c89db99f280cd67ca14357c9ee11adce0acce Mon Sep 17 00:00:00 2001 From: chaviw Date: Wed, 4 Sep 2019 16:03:53 -0700 Subject: Remove setGeometryAppliesWithResize This function is no longer used so removing the API and any logic implemented for it. Test: go/wm-smoke Change-Id: I4ae2128cd38e818fcd16dafa4ce47c9411bd61c9 --- libs/gui/LayerState.cpp | 3 - libs/gui/SurfaceComposerClient.cpp | 13 --- libs/gui/include/gui/LayerState.h | 2 +- libs/gui/include/gui/SurfaceComposerClient.h | 6 - services/surfaceflinger/BufferQueueLayer.cpp | 2 +- services/surfaceflinger/BufferStateLayer.h | 4 +- services/surfaceflinger/Layer.cpp | 39 ++----- services/surfaceflinger/Layer.h | 6 +- services/surfaceflinger/LayerRejecter.cpp | 28 ++--- services/surfaceflinger/LayerRejecter.h | 12 +- services/surfaceflinger/RefreshRateOverlay.cpp | 2 +- services/surfaceflinger/SurfaceFlinger.cpp | 7 +- services/surfaceflinger/tests/Transaction_test.cpp | 124 --------------------- .../tests/fakehwc/SFFakeHwc_test.cpp | 18 --- 14 files changed, 32 insertions(+), 234 deletions(-) (limited to 'services/surfaceflinger/Layer.cpp') diff --git a/libs/gui/LayerState.cpp b/libs/gui/LayerState.cpp index be58b853d7..523ed1d2ce 100644 --- a/libs/gui/LayerState.cpp +++ b/libs/gui/LayerState.cpp @@ -291,9 +291,6 @@ void layer_state_t::merge(const layer_state_t& other) { what |= eOverrideScalingModeChanged; overrideScalingMode = other.overrideScalingMode; } - if (other.what & eGeometryAppliesWithResize) { - what |= eGeometryAppliesWithResize; - } if (other.what & eReparentChildren) { what |= eReparentChildren; reparentHandle = other.reparentHandle; diff --git a/libs/gui/SurfaceComposerClient.cpp b/libs/gui/SurfaceComposerClient.cpp index 5faf010d72..67dd726eba 100644 --- a/libs/gui/SurfaceComposerClient.cpp +++ b/libs/gui/SurfaceComposerClient.cpp @@ -1187,19 +1187,6 @@ SurfaceComposerClient::Transaction& SurfaceComposerClient::Transaction::setOverr return *this; } -SurfaceComposerClient::Transaction& SurfaceComposerClient::Transaction::setGeometryAppliesWithResize( - const sp& sc) { - layer_state_t* s = getLayerState(sc); - if (!s) { - mStatus = BAD_INDEX; - return *this; - } - s->what |= layer_state_t::eGeometryAppliesWithResize; - - registerSurfaceControlForCallback(sc); - return *this; -} - #ifndef NO_INPUT SurfaceComposerClient::Transaction& SurfaceComposerClient::Transaction::setInputWindowInfo( const sp& sc, diff --git a/libs/gui/include/gui/LayerState.h b/libs/gui/include/gui/LayerState.h index cbd1c8553b..2eb5492558 100644 --- a/libs/gui/include/gui/LayerState.h +++ b/libs/gui/include/gui/LayerState.h @@ -71,7 +71,7 @@ struct layer_state_t { eCropChanged_legacy = 0x00000100, eDeferTransaction_legacy = 0x00000200, eOverrideScalingModeChanged = 0x00000400, - eGeometryAppliesWithResize = 0x00000800, + // AVAILABLE 0x00000800, eReparentChildren = 0x00001000, eDetachChildren = 0x00002000, eRelativeLayerChanged = 0x00004000, diff --git a/libs/gui/include/gui/SurfaceComposerClient.h b/libs/gui/include/gui/SurfaceComposerClient.h index f303a03254..d65e679e24 100644 --- a/libs/gui/include/gui/SurfaceComposerClient.h +++ b/libs/gui/include/gui/SurfaceComposerClient.h @@ -446,12 +446,6 @@ public: Transaction& setOverrideScalingMode(const sp& sc, int32_t overrideScalingMode); - // If the size changes in this transaction, all geometry updates specified - // in this transaction will not complete until a buffer of the new size - // arrives. As some elements normally apply immediately, this enables - // freezing the total geometry of a surface until a resize is completed. - Transaction& setGeometryAppliesWithResize(const sp& sc); - #ifndef NO_INPUT Transaction& setInputWindowInfo(const sp& sc, const InputWindowInfo& info); Transaction& transferTouchFocus(const sp& fromToken, const sp& toToken); diff --git a/services/surfaceflinger/BufferQueueLayer.cpp b/services/surfaceflinger/BufferQueueLayer.cpp index 5f494ff3d5..85a00fbe0d 100644 --- a/services/surfaceflinger/BufferQueueLayer.cpp +++ b/services/surfaceflinger/BufferQueueLayer.cpp @@ -276,7 +276,7 @@ status_t BufferQueueLayer::updateTexImage(bool& recomputeVisibleRegions, nsecs_t const int32_t layerID = getSequence(); LayerRejecter r(mDrawingState, getCurrentState(), recomputeVisibleRegions, getProducerStickyTransform() != 0, mName.string(), mOverrideScalingMode, - getTransformToDisplayInverse(), mFreezeGeometryUpdates); + getTransformToDisplayInverse()); if (isRemovedFromCurrentState()) { expectedPresentTime = 0; diff --git a/services/surfaceflinger/BufferStateLayer.h b/services/surfaceflinger/BufferStateLayer.h index cc670087ac..f2a5dffe7c 100644 --- a/services/surfaceflinger/BufferStateLayer.h +++ b/services/surfaceflinger/BufferStateLayer.h @@ -82,13 +82,13 @@ public: // Override to ignore legacy layer state properties that are not used by BufferStateLayer bool setSize(uint32_t /*w*/, uint32_t /*h*/) override { return false; } - bool setPosition(float /*x*/, float /*y*/, bool /*immediate*/) override { return false; } + bool setPosition(float /*x*/, float /*y*/) override { return false; } bool setTransparentRegionHint(const Region& transparent) override; bool setMatrix(const layer_state_t::matrix22_t& /*matrix*/, bool /*allowNonRectPreservingTransforms*/) override { return false; } - bool setCrop_legacy(const Rect& /*crop*/, bool /*immediate*/) override { return false; } + bool setCrop_legacy(const Rect& /*crop*/) override { return false; } bool setOverrideScalingMode(int32_t /*overrideScalingMode*/) override { return false; } void deferTransactionUntil_legacy(const sp& /*barrierHandle*/, uint64_t /*frameNumber*/) override {} diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp index 5121835cae..4c8a6bf465 100644 --- a/services/surfaceflinger/Layer.cpp +++ b/services/surfaceflinger/Layer.cpp @@ -770,11 +770,6 @@ uint32_t Layer::doTransactionResize(uint32_t flags, State* stateToCommit) { if (!(flags & eDontUpdateGeometryState)) { State& editCurrentState(getCurrentState()); - // If mFreezeGeometryUpdates is true we are in the setGeometryAppliesWithResize - // mode, which causes attributes which normally latch regardless of scaling mode, - // to be delayed. We copy the requested state to the active state making sure - // to respect these rules (again see Layer.h for a detailed discussion). - // // There is an awkward asymmetry in the handling of the crop states in the position // states, as can be seen below. Largely this arises from position and transform // being stored in the same data structure while having different latching rules. @@ -782,16 +777,8 @@ uint32_t Layer::doTransactionResize(uint32_t flags, State* stateToCommit) { // // Careful that "stateToCommit" and editCurrentState may not begin as equivalent due to // applyPendingStates in the presence of deferred transactions. - if (mFreezeGeometryUpdates) { - float tx = stateToCommit->active_legacy.transform.tx(); - float ty = stateToCommit->active_legacy.transform.ty(); - stateToCommit->active_legacy = stateToCommit->requested_legacy; - stateToCommit->active_legacy.transform.set(tx, ty); - editCurrentState.active_legacy = stateToCommit->active_legacy; - } else { - editCurrentState.active_legacy = editCurrentState.requested_legacy; - stateToCommit->active_legacy = stateToCommit->requested_legacy; - } + editCurrentState.active_legacy = editCurrentState.requested_legacy; + stateToCommit->active_legacy = stateToCommit->requested_legacy; } return flags; @@ -858,7 +845,7 @@ uint32_t Layer::setTransactionFlags(uint32_t flags) { return mTransactionFlags.fetch_or(flags); } -bool Layer::setPosition(float x, float y, bool immediate) { +bool Layer::setPosition(float x, float y) { if (mCurrentState.requested_legacy.transform.tx() == x && mCurrentState.requested_legacy.transform.ty() == y) return false; @@ -868,14 +855,11 @@ bool Layer::setPosition(float x, float y, bool immediate) { // we want to apply the position portion of the transform matrix immediately, // but still delay scaling when resizing a SCALING_MODE_FREEZE layer. mCurrentState.requested_legacy.transform.set(x, y); - if (immediate && !mFreezeGeometryUpdates) { - // Here we directly update the active state - // unlike other setters, because we store it within - // the transform, but use different latching rules. - // b/38182305 - mCurrentState.active_legacy.transform.set(x, y); - } - mFreezeGeometryUpdates = mFreezeGeometryUpdates || !immediate; + // Here we directly update the active state + // unlike other setters, because we store it within + // the transform, but use different latching rules. + // b/38182305 + mCurrentState.active_legacy.transform.set(x, y); mCurrentState.modified = true; setTransactionFlags(eTransactionNeeded); @@ -1081,14 +1065,11 @@ bool Layer::setFlags(uint8_t flags, uint8_t mask) { return true; } -bool Layer::setCrop_legacy(const Rect& crop, bool immediate) { +bool Layer::setCrop_legacy(const Rect& crop) { if (mCurrentState.requestedCrop_legacy == crop) return false; mCurrentState.sequence++; mCurrentState.requestedCrop_legacy = crop; - if (immediate && !mFreezeGeometryUpdates) { - mCurrentState.crop_legacy = crop; - } - mFreezeGeometryUpdates = mFreezeGeometryUpdates || !immediate; + mCurrentState.crop_legacy = crop; mCurrentState.modified = true; setTransactionFlags(eTransactionNeeded); diff --git a/services/surfaceflinger/Layer.h b/services/surfaceflinger/Layer.h index 9107189d52..a2409e79d2 100644 --- a/services/surfaceflinger/Layer.h +++ b/services/surfaceflinger/Layer.h @@ -268,9 +268,9 @@ public: // setPosition operates in parent buffer space (pre parent-transform) or display // space for top-level layers. - virtual bool setPosition(float x, float y, bool immediate); + virtual bool setPosition(float x, float y); // Buffer space - virtual bool setCrop_legacy(const Rect& crop, bool immediate); + virtual bool setCrop_legacy(const Rect& crop); // TODO(b/38182121): Could we eliminate the various latching modes by // using the layer hierarchy? @@ -860,8 +860,6 @@ protected: // This layer can be a cursor on some displays. bool mPotentialCursor{false}; - bool mFreezeGeometryUpdates{false}; - // Child list about to be committed/used for editing. LayerVector mCurrentChildren{LayerVector::StateSet::Current}; // Child list used for rendering. diff --git a/services/surfaceflinger/LayerRejecter.cpp b/services/surfaceflinger/LayerRejecter.cpp index 72abea8b2d..8a221837ac 100644 --- a/services/surfaceflinger/LayerRejecter.cpp +++ b/services/surfaceflinger/LayerRejecter.cpp @@ -23,22 +23,16 @@ namespace android { -LayerRejecter::LayerRejecter(Layer::State& front, - Layer::State& current, - bool& recomputeVisibleRegions, - bool stickySet, - const char* name, - int32_t overrideScalingMode, - bool transformToDisplayInverse, - bool& freezePositionUpdates) - : mFront(front), - mCurrent(current), - mRecomputeVisibleRegions(recomputeVisibleRegions), - mStickyTransformSet(stickySet), - mName(name), - mOverrideScalingMode(overrideScalingMode), - mTransformToDisplayInverse(transformToDisplayInverse), - mFreezeGeometryUpdates(freezePositionUpdates) {} +LayerRejecter::LayerRejecter(Layer::State& front, Layer::State& current, + bool& recomputeVisibleRegions, bool stickySet, const char* name, + int32_t overrideScalingMode, bool transformToDisplayInverse) + : mFront(front), + mCurrent(current), + mRecomputeVisibleRegions(recomputeVisibleRegions), + mStickyTransformSet(stickySet), + mName(name), + mOverrideScalingMode(overrideScalingMode), + mTransformToDisplayInverse(transformToDisplayInverse) {} bool LayerRejecter::reject(const sp& buf, const BufferItem& item) { if (buf == nullptr) { @@ -83,8 +77,6 @@ bool LayerRejecter::reject(const sp& buf, const BufferItem& item) // recompute visible region mRecomputeVisibleRegions = true; - mFreezeGeometryUpdates = false; - if (mFront.crop_legacy != mFront.requestedCrop_legacy) { mFront.crop_legacy = mFront.requestedCrop_legacy; mCurrent.crop_legacy = mFront.requestedCrop_legacy; diff --git a/services/surfaceflinger/LayerRejecter.h b/services/surfaceflinger/LayerRejecter.h index 63d51de0ca..1bd0c26dc6 100644 --- a/services/surfaceflinger/LayerRejecter.h +++ b/services/surfaceflinger/LayerRejecter.h @@ -23,14 +23,9 @@ namespace android { class LayerRejecter : public BufferLayerConsumer::BufferRejecter { public: - LayerRejecter(Layer::State &front, - Layer::State ¤t, - bool &recomputeVisibleRegions, - bool stickySet, - const char *name, - int32_t overrideScalingMode, - bool transformToDisplayInverse, - bool &freezePositionUpdates); + LayerRejecter(Layer::State &front, Layer::State ¤t, bool &recomputeVisibleRegions, + bool stickySet, const char *name, int32_t overrideScalingMode, + bool transformToDisplayInverse); virtual bool reject(const sp &buf, const BufferItem &item); @@ -42,7 +37,6 @@ namespace android { const char *mName; int32_t mOverrideScalingMode; bool mTransformToDisplayInverse; - bool &mFreezeGeometryUpdates; }; } // namespace android diff --git a/services/surfaceflinger/RefreshRateOverlay.cpp b/services/surfaceflinger/RefreshRateOverlay.cpp index 5b4bec96ea..976fedb58a 100644 --- a/services/surfaceflinger/RefreshRateOverlay.cpp +++ b/services/surfaceflinger/RefreshRateOverlay.cpp @@ -39,7 +39,7 @@ bool RefreshRateOverlay::createLayer() { Mutex::Autolock _l(mFlinger.mStateLock); mLayer = mClient->getLayerUser(mIBinder); - mLayer->setCrop_legacy(Rect(50, 70, 200, 100), true); + mLayer->setCrop_legacy(Rect(50, 70, 200, 100)); // setting Layer's Z requires resorting layersSortedByZ ssize_t idx = mFlinger.mCurrentState.layersSortedByZ.indexOf(mLayer); diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp index 7a8eb6b2da..c1a8f87d37 100644 --- a/services/surfaceflinger/SurfaceFlinger.cpp +++ b/services/surfaceflinger/SurfaceFlinger.cpp @@ -3597,8 +3597,6 @@ uint32_t SurfaceFlinger::setClientStateLocked( uint32_t flags = 0; const uint64_t what = s.what; - bool geometryAppliesWithResize = - what & layer_state_t::eGeometryAppliesWithResize; // If we are deferring transaction, make sure to push the pending state, as otherwise the // pending state will also be deferred. @@ -3607,7 +3605,7 @@ uint32_t SurfaceFlinger::setClientStateLocked( } if (what & layer_state_t::ePositionChanged) { - if (layer->setPosition(s.x, s.y, !geometryAppliesWithResize)) { + if (layer->setPosition(s.x, s.y)) { flags |= eTraversalNeeded; } } @@ -3698,8 +3696,7 @@ uint32_t SurfaceFlinger::setClientStateLocked( flags |= eTraversalNeeded; } if (what & layer_state_t::eCropChanged_legacy) { - if (layer->setCrop_legacy(s.crop_legacy, !geometryAppliesWithResize)) - flags |= eTraversalNeeded; + if (layer->setCrop_legacy(s.crop_legacy)) flags |= eTraversalNeeded; } if (what & layer_state_t::eCornerRadiusChanged) { if (layer->setCornerRadius(s.cornerRadius)) diff --git a/services/surfaceflinger/tests/Transaction_test.cpp b/services/surfaceflinger/tests/Transaction_test.cpp index b1fde22e0e..03c646b0bb 100644 --- a/services/surfaceflinger/tests/Transaction_test.cpp +++ b/services/surfaceflinger/tests/Transaction_test.cpp @@ -842,62 +842,6 @@ TEST_P(LayerRenderTypeTransactionTest, SetPositionWithResize_BufferQueue) { } } -TEST_P(LayerRenderTypeTransactionTest, SetPositionWithNextResize_BufferQueue) { - sp layer; - ASSERT_NO_FATAL_FAILURE(layer = createLayer("test", 32, 32)); - ASSERT_NO_FATAL_FAILURE(fillBufferQueueLayerColor(layer, Color::RED, 32, 32)); - - // request setPosition to be applied with the next resize - Transaction().setPosition(layer, 5, 10).setGeometryAppliesWithResize(layer).apply(); - { - SCOPED_TRACE("new position pending"); - getScreenCapture()->expectColor(Rect(0, 0, 32, 32), Color::RED); - } - - Transaction().setPosition(layer, 15, 20).apply(); - { - SCOPED_TRACE("pending new position modified"); - getScreenCapture()->expectColor(Rect(0, 0, 32, 32), Color::RED); - } - - Transaction().setSize(layer, 64, 64).apply(); - { - SCOPED_TRACE("resize pending"); - getScreenCapture()->expectColor(Rect(0, 0, 32, 32), Color::RED); - } - - // finally resize and latch the buffer - ASSERT_NO_FATAL_FAILURE(fillBufferQueueLayerColor(layer, Color::RED, 64, 64)); - { - SCOPED_TRACE("new position applied"); - getScreenCapture()->expectColor(Rect(15, 20, 79, 84), Color::RED); - } -} - -TEST_P(LayerRenderTypeTransactionTest, SetPositionWithNextResizeScaleToWindow_BufferQueue) { - sp layer; - ASSERT_NO_FATAL_FAILURE(layer = createLayer("test", 32, 32)); - ASSERT_NO_FATAL_FAILURE(fillBufferQueueLayerColor(layer, Color::RED, 32, 32)); - - // setPosition is not immediate even with SCALE_TO_WINDOW override - Transaction() - .setPosition(layer, 5, 10) - .setSize(layer, 64, 64) - .setOverrideScalingMode(layer, NATIVE_WINDOW_SCALING_MODE_SCALE_TO_WINDOW) - .setGeometryAppliesWithResize(layer) - .apply(); - { - SCOPED_TRACE("new position pending"); - getScreenCapture()->expectColor(Rect(0, 0, 64, 64), Color::RED); - } - - ASSERT_NO_FATAL_FAILURE(fillBufferQueueLayerColor(layer, Color::RED, 64, 64)); - { - SCOPED_TRACE("new position applied"); - getScreenCapture()->expectColor(Rect(5, 10, 69, 74), Color::RED); - } -} - TEST_P(LayerRenderTypeTransactionTest, SetSizeBasic_BufferQueue) { sp layer; ASSERT_NO_FATAL_FAILURE(layer = createLayer("test", 32, 32)); @@ -2310,74 +2254,6 @@ TEST_P(LayerRenderTypeTransactionTest, SetCropWithResize_BufferQueue) { } } -TEST_P(LayerRenderTypeTransactionTest, SetCropWithNextResize_BufferQueue) { - sp layer; - ASSERT_NO_FATAL_FAILURE(layer = createLayer("test", 32, 32)); - ASSERT_NO_FATAL_FAILURE(fillBufferQueueLayerColor(layer, Color::RED, 32, 32)); - - // request setCrop_legacy to be applied with the next resize - Transaction() - .setCrop_legacy(layer, Rect(8, 8, 24, 24)) - .setGeometryAppliesWithResize(layer) - .apply(); - { - SCOPED_TRACE("waiting for next resize"); - getScreenCapture()->expectColor(Rect(0, 0, 32, 32), Color::RED); - } - - Transaction().setCrop_legacy(layer, Rect(4, 4, 12, 12)).apply(); - { - SCOPED_TRACE("pending crop modified"); - getScreenCapture()->expectColor(Rect(0, 0, 32, 32), Color::RED); - } - - Transaction().setSize(layer, 16, 16).apply(); - { - SCOPED_TRACE("resize pending"); - getScreenCapture()->expectColor(Rect(0, 0, 32, 32), Color::RED); - } - - // finally resize - ASSERT_NO_FATAL_FAILURE(fillBufferQueueLayerColor(layer, Color::RED, 16, 16)); - { - SCOPED_TRACE("new crop applied"); - auto shot = getScreenCapture(); - shot->expectColor(Rect(4, 4, 12, 12), Color::RED); - shot->expectBorder(Rect(4, 4, 12, 12), Color::BLACK); - } -} - -TEST_P(LayerRenderTypeTransactionTest, SetCropWithNextResizeScaleToWindow_BufferQueue) { - sp layer; - ASSERT_NO_FATAL_FAILURE(layer = createLayer("test", 32, 32)); - ASSERT_NO_FATAL_FAILURE(fillBufferQueueLayerColor(layer, Color::RED, 32, 32)); - - // setCrop_legacy is not immediate even with SCALE_TO_WINDOW override - Transaction() - .setCrop_legacy(layer, Rect(4, 4, 12, 12)) - .setSize(layer, 16, 16) - .setOverrideScalingMode(layer, NATIVE_WINDOW_SCALING_MODE_SCALE_TO_WINDOW) - .setGeometryAppliesWithResize(layer) - .apply(); - { - SCOPED_TRACE("new crop pending"); - auto shot = getScreenCapture(); - shot->expectColor(Rect(0, 0, 16, 16), Color::RED); - shot->expectBorder(Rect(0, 0, 16, 16), Color::BLACK); - } - - // XXX crop is never latched without other geometry change (b/69315677) - Transaction().setPosition(layer, 1, 0).setGeometryAppliesWithResize(layer).apply(); - ASSERT_NO_FATAL_FAILURE(fillBufferQueueLayerColor(layer, Color::RED, 16, 16)); - Transaction().setPosition(layer, 0, 0).apply(); - { - SCOPED_TRACE("new crop applied"); - auto shot = getScreenCapture(); - shot->expectColor(Rect(4, 4, 12, 12), Color::RED); - shot->expectBorder(Rect(4, 4, 12, 12), Color::BLACK); - } -} - TEST_P(LayerRenderTypeTransactionTest, SetFrameBasic_BufferState) { sp layer; ASSERT_NO_FATAL_FAILURE( diff --git a/services/surfaceflinger/tests/fakehwc/SFFakeHwc_test.cpp b/services/surfaceflinger/tests/fakehwc/SFFakeHwc_test.cpp index a892a2abd0..093bcf576d 100644 --- a/services/surfaceflinger/tests/fakehwc/SFFakeHwc_test.cpp +++ b/services/surfaceflinger/tests/fakehwc/SFFakeHwc_test.cpp @@ -1331,16 +1331,6 @@ TEST_F(LatchingTest, SurfacePositionLatching) { restoreInitialState(); - // Now we repeat with setGeometryAppliesWithResize - // and verify the position DOESN'T latch. - { - TransactionScope ts(*sFakeComposer); - ts.setGeometryAppliesWithResize(mFGSurfaceControl); - ts.setSize(mFGSurfaceControl, 32, 32); - ts.setPosition(mFGSurfaceControl, 100, 100); - } - EXPECT_TRUE(framesAreSame(mBaseFrame, sFakeComposer->getLatestFrame())); - completeFGResize(); auto referenceFrame2 = mBaseFrame; @@ -1365,14 +1355,6 @@ TEST_F(LatchingTest, CropLatching) { restoreInitialState(); - { - TransactionScope ts(*sFakeComposer); - ts.setSize(mFGSurfaceControl, 128, 128); - ts.setGeometryAppliesWithResize(mFGSurfaceControl); - ts.setCrop_legacy(mFGSurfaceControl, Rect(0, 0, 63, 63)); - } - EXPECT_TRUE(framesAreSame(mBaseFrame, sFakeComposer->getLatestFrame())); - completeFGResize(); auto referenceFrame2 = mBaseFrame; -- cgit v1.2.3-59-g8ed1b From a2468669661cd9bcd1258ec908716c4b85ef007e Mon Sep 17 00:00:00 2001 From: Lloyd Pique Date: Thu, 7 Mar 2019 21:31:06 -0800 Subject: SF: Move layer visibility state to CompositionEngine The layer visibility/coverage state was the last bit of display-dependent data that had not yet been moved to OutputLayerCompositionState. This moves it, and fixes up all references to the data to get it in a display-dependent way. Test: atest libsurfaceflinger_unittest libcompositionengine_test Bug: 121291683 Change-Id: Id9f314f05b743212dba3a113df2baeb38fd19eb8 --- services/surfaceflinger/BufferLayer.cpp | 3 +- .../compositionengine/LayerFECompositionState.h | 4 -- .../compositionengine/impl/LayerCompositionState.h | 3 +- .../impl/OutputLayerCompositionState.h | 13 ++++++- .../CompositionEngine/src/Output.cpp | 2 +- .../CompositionEngine/src/OutputLayer.cpp | 11 ++---- .../src/OutputLayerCompositionState.cpp | 9 +++++ .../CompositionEngine/tests/OutputLayerTest.cpp | 9 +++-- .../CompositionEngine/tests/OutputTest.cpp | 10 ++--- services/surfaceflinger/Layer.cpp | 44 +++++++++------------- services/surfaceflinger/Layer.h | 30 +-------------- services/surfaceflinger/SurfaceFlinger.cpp | 35 +++++++++-------- .../tests/unittests/CompositionTest.cpp | 22 ++++++++++- 13 files changed, 98 insertions(+), 97 deletions(-) (limited to 'services/surfaceflinger/Layer.cpp') diff --git a/services/surfaceflinger/BufferLayer.cpp b/services/surfaceflinger/BufferLayer.cpp index a8bdb799e7..a7970db473 100644 --- a/services/surfaceflinger/BufferLayer.cpp +++ b/services/surfaceflinger/BufferLayer.cpp @@ -158,7 +158,8 @@ std::optional BufferLayer::prepareClientComposition finished = true; return; } - under.orSelf(layer->visibleRegion); + + under.orSelf(layer->getScreenBounds()); }); // if not everything below us is covered, we plug the holes! Region holes(targetSettings.clip.subtract(under)); diff --git a/services/surfaceflinger/CompositionEngine/include/compositionengine/LayerFECompositionState.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/LayerFECompositionState.h index 6a0caf0746..b066cd1bda 100644 --- a/services/surfaceflinger/CompositionEngine/include/compositionengine/LayerFECompositionState.h +++ b/services/surfaceflinger/CompositionEngine/include/compositionengine/LayerFECompositionState.h @@ -56,10 +56,6 @@ struct LayerFECompositionState { Region geomActiveTransparentRegion; FloatRect geomLayerBounds; - // TODO(lpique): b/121291683 Remove this one we are sure we don't need the - // value recomputed / set every frame. - Region geomVisibleRegion; - /* * Presentation */ diff --git a/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/LayerCompositionState.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/LayerCompositionState.h index ab01c209d1..726c850780 100644 --- a/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/LayerCompositionState.h +++ b/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/LayerCompositionState.h @@ -21,6 +21,7 @@ #include #include +#include namespace android { @@ -28,7 +29,7 @@ namespace compositionengine::impl { struct LayerCompositionState { /* - * State intended to be set by LayerFE::getCompositionState + * State set by LayerFE::getCompositionState */ LayerFECompositionState frontEnd; diff --git a/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/OutputLayerCompositionState.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/OutputLayerCompositionState.h index de0f08ace8..13474492af 100644 --- a/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/OutputLayerCompositionState.h +++ b/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/OutputLayerCompositionState.h @@ -40,9 +40,18 @@ class HWComposer; namespace compositionengine::impl { struct OutputLayerCompositionState { - // The region of this layer which is visible on this output + // The portion of the layer that is not obscured by opaque layers on top Region visibleRegion; + // The portion of the layer that is not obscured and is also opaque + Region visibleNonTransparentRegion; + + // The portion of the layer that is obscured by opaque layers on top + Region coveredRegion; + + // The visibleRegion transformed to output space + Region outputSpaceVisibleRegion; + // If true, client composition will be used on this output bool forceClientComposition{false}; @@ -62,7 +71,7 @@ struct OutputLayerCompositionState { ui::Dataspace dataspace{ui::Dataspace::UNKNOWN}; // The Z order index of this layer on this output - uint32_t z; + uint32_t z{0}; /* * HWC state diff --git a/services/surfaceflinger/CompositionEngine/src/Output.cpp b/services/surfaceflinger/CompositionEngine/src/Output.cpp index 903ca9891c..9f4f259f7c 100644 --- a/services/surfaceflinger/CompositionEngine/src/Output.cpp +++ b/services/surfaceflinger/CompositionEngine/src/Output.cpp @@ -601,7 +601,7 @@ std::vector Output::generateClientCompositionReques const auto& layerFEState = layer->getLayer().getState().frontEnd; auto& layerFE = layer->getLayerFE(); - const Region clip(viewportRegion.intersect(layerFEState.geomVisibleRegion)); + const Region clip(viewportRegion.intersect(layerState.visibleRegion)); ALOGV("Layer: %s", layerFE.getDebugName()); if (clip.isEmpty()) { ALOGV(" Skipping for empty clip"); diff --git a/services/surfaceflinger/CompositionEngine/src/OutputLayer.cpp b/services/surfaceflinger/CompositionEngine/src/OutputLayer.cpp index 73bb03be02..21f0ce8b15 100644 --- a/services/surfaceflinger/CompositionEngine/src/OutputLayer.cpp +++ b/services/surfaceflinger/CompositionEngine/src/OutputLayer.cpp @@ -315,11 +315,6 @@ void OutputLayer::updateCompositionState(bool includeGeometry) { ? outputState.targetDataspace : layerFEState.dataspace; - // TODO(lpique): b/121291683 Remove this one we are sure we don't need the - // value recomputed / set every frame. - mState.visibleRegion = outputState.transform.transform( - layerFEState.geomVisibleRegion.intersect(outputState.viewport)); - // These are evaluated every frame as they can potentially change at any // time. if (layerFEState.forceClientComposition || !profile.isDataspaceSupported(mState.dataspace)) { @@ -421,13 +416,13 @@ void OutputLayer::writeOutputIndependentGeometryStateToHWC( void OutputLayer::writeOutputDependentPerFrameStateToHWC(HWC2::Layer* hwcLayer) { const auto& outputDependentState = getState(); - // TODO(lpique): b/121291683 visibleRegion is output-dependent geometry + // TODO(lpique): b/121291683 outputSpaceVisibleRegion is output-dependent geometry // state and should not change every frame. - if (auto error = hwcLayer->setVisibleRegion(outputDependentState.visibleRegion); + if (auto error = hwcLayer->setVisibleRegion(outputDependentState.outputSpaceVisibleRegion); error != HWC2::Error::None) { ALOGE("[%s] Failed to set visible region: %s (%d)", mLayerFE->getDebugName(), to_string(error).c_str(), static_cast(error)); - outputDependentState.visibleRegion.dump(LOG_TAG); + outputDependentState.outputSpaceVisibleRegion.dump(LOG_TAG); } if (auto error = hwcLayer->setDataspace(outputDependentState.dataspace); diff --git a/services/surfaceflinger/CompositionEngine/src/OutputLayerCompositionState.cpp b/services/surfaceflinger/CompositionEngine/src/OutputLayerCompositionState.cpp index e320bee4e1..ad668b6b89 100644 --- a/services/surfaceflinger/CompositionEngine/src/OutputLayerCompositionState.cpp +++ b/services/surfaceflinger/CompositionEngine/src/OutputLayerCompositionState.cpp @@ -41,6 +41,15 @@ void OutputLayerCompositionState::dump(std::string& out) const { out.append(" "); dumpVal(out, "visibleRegion", visibleRegion); + out.append(" "); + dumpVal(out, "visibleNonTransparentRegion", visibleNonTransparentRegion); + + out.append(" "); + dumpVal(out, "coveredRegion", coveredRegion); + + out.append(" "); + dumpVal(out, "output visibleRegion", outputSpaceVisibleRegion); + out.append(" "); dumpVal(out, "forceClientComposition", forceClientComposition); dumpVal(out, "clearClientTarget", clearClientTarget); diff --git a/services/surfaceflinger/CompositionEngine/tests/OutputLayerTest.cpp b/services/surfaceflinger/CompositionEngine/tests/OutputLayerTest.cpp index 75e960c575..2276dc3691 100644 --- a/services/surfaceflinger/CompositionEngine/tests/OutputLayerTest.cpp +++ b/services/surfaceflinger/CompositionEngine/tests/OutputLayerTest.cpp @@ -574,7 +574,7 @@ struct OutputLayerWriteStateToHWCTest : public OutputLayerTest { static const half4 kColor; static const Rect kDisplayFrame; - static const Region kVisibleRegion; + static const Region kOutputSpaceVisibleRegion; static const mat4 kColorTransform; static const Region kSurfaceDamage; static const HdrMetadata kHdrMetadata; @@ -590,7 +590,7 @@ struct OutputLayerWriteStateToHWCTest : public OutputLayerTest { outputLayerState.sourceCrop = kSourceCrop; outputLayerState.z = kZOrder; outputLayerState.bufferTransform = static_cast(kBufferTransform); - outputLayerState.visibleRegion = kVisibleRegion; + outputLayerState.outputSpaceVisibleRegion = kOutputSpaceVisibleRegion; outputLayerState.dataspace = kDataspace; mLayerState.frontEnd.blendMode = kBlendMode; @@ -629,7 +629,7 @@ struct OutputLayerWriteStateToHWCTest : public OutputLayerTest { } void expectPerFrameCommonCalls(SimulateUnsupported unsupported = SimulateUnsupported::None) { - EXPECT_CALL(*mHwcLayer, setVisibleRegion(RegionEq(kVisibleRegion))) + EXPECT_CALL(*mHwcLayer, setVisibleRegion(RegionEq(kOutputSpaceVisibleRegion))) .WillOnce(Return(kError)); EXPECT_CALL(*mHwcLayer, setDataspace(kDataspace)).WillOnce(Return(kError)); EXPECT_CALL(*mHwcLayer, setColorTransform(kColorTransform)) @@ -673,7 +673,8 @@ struct OutputLayerWriteStateToHWCTest : public OutputLayerTest { const half4 OutputLayerWriteStateToHWCTest::kColor{81.f / 255.f, 82.f / 255.f, 83.f / 255.f, 84.f / 255.f}; const Rect OutputLayerWriteStateToHWCTest::kDisplayFrame{1001, 1002, 1003, 10044}; -const Region OutputLayerWriteStateToHWCTest::kVisibleRegion{Rect{1005, 1006, 1007, 1008}}; +const Region OutputLayerWriteStateToHWCTest::kOutputSpaceVisibleRegion{ + Rect{1005, 1006, 1007, 1008}}; const mat4 OutputLayerWriteStateToHWCTest::kColorTransform{ 1009, 1010, 1011, 1012, 1013, 1014, 1015, 1016, 1017, 1018, 1019, 1020, 1021, 1022, 1023, 1024, diff --git a/services/surfaceflinger/CompositionEngine/tests/OutputTest.cpp b/services/surfaceflinger/CompositionEngine/tests/OutputTest.cpp index 1d5f2f0d54..b0e8e3699c 100644 --- a/services/surfaceflinger/CompositionEngine/tests/OutputTest.cpp +++ b/services/surfaceflinger/CompositionEngine/tests/OutputTest.cpp @@ -661,9 +661,9 @@ TEST_F(GenerateClientCompositionRequestsTest, worksForLandscapeModeSplitScreen) impl::OutputLayerCompositionState leftOutputLayerState; leftOutputLayerState.clearClientTarget = false; + leftOutputLayerState.visibleRegion = Region{Rect{0, 0, 1000, 1000}}; impl::LayerCompositionState leftLayerState; - leftLayerState.frontEnd.geomVisibleRegion = Region{Rect{0, 0, 1000, 1000}}; leftLayerState.frontEnd.isOpaque = true; const half3 leftLayerColor{1.f, 0.f, 0.f}; @@ -672,9 +672,9 @@ TEST_F(GenerateClientCompositionRequestsTest, worksForLandscapeModeSplitScreen) impl::OutputLayerCompositionState rightOutputLayerState; rightOutputLayerState.clearClientTarget = false; + rightOutputLayerState.visibleRegion = Region{Rect{1000, 0, 2000, 1000}}; impl::LayerCompositionState rightLayerState; - rightLayerState.frontEnd.geomVisibleRegion = Region{Rect{1000, 0, 2000, 1000}}; rightLayerState.frontEnd.isOpaque = true; const half3 rightLayerColor{0.f, 1.f, 0.f}; @@ -735,9 +735,9 @@ TEST_F(GenerateClientCompositionRequestsTest, ignoresLayersThatDoNotIntersectWit impl::OutputLayerCompositionState outputLayerState; outputLayerState.clearClientTarget = false; + outputLayerState.visibleRegion = Region{Rect{3000, 0, 4000, 1000}}; impl::LayerCompositionState layerState; - layerState.frontEnd.geomVisibleRegion = Region{Rect{3000, 0, 4000, 1000}}; layerState.frontEnd.isOpaque = true; EXPECT_CALL(*outputLayer, getState()).WillRepeatedly(ReturnRef(outputLayerState)); @@ -790,16 +790,16 @@ TEST_F(GenerateClientCompositionRequestsTest, clearsDeviceLayesAfterFirst) { impl::OutputLayerCompositionState leftOutputLayerState; leftOutputLayerState.clearClientTarget = true; + leftOutputLayerState.visibleRegion = Region{Rect{0, 0, 1000, 1000}}; impl::LayerCompositionState leftLayerState; - leftLayerState.frontEnd.geomVisibleRegion = Region{Rect{0, 0, 1000, 1000}}; leftLayerState.frontEnd.isOpaque = true; impl::OutputLayerCompositionState rightOutputLayerState; rightOutputLayerState.clearClientTarget = true; + rightOutputLayerState.visibleRegion = Region{Rect{1000, 0, 2000, 1000}}; impl::LayerCompositionState rightLayerState; - rightLayerState.frontEnd.geomVisibleRegion = Region{Rect{1000, 0, 2000, 1000}}; rightLayerState.frontEnd.isOpaque = true; const half3 rightLayerColor{0.f, 1.f, 0.f}; diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp index 557d0bba27..b669421103 100644 --- a/services/surfaceflinger/Layer.cpp +++ b/services/surfaceflinger/Layer.cpp @@ -443,10 +443,6 @@ void Layer::latchPerFrameState(compositionengine::LayerFECompositionState& compo const auto& drawingState{getDrawingState()}; compositionState.forceClientComposition = false; - // TODO(lpique): b/121291683 Remove this one we are sure we don't need the - // value recomputed / set every frame. - compositionState.geomVisibleRegion = visibleRegion; - compositionState.isColorspaceAgnostic = isColorSpaceAgnostic(); compositionState.dataspace = mCurrentDataSpace; compositionState.colorTransform = getColorTransform(); @@ -567,27 +563,6 @@ bool Layer::isSecure() const { return (s.flags & layer_state_t::eLayerSecure); } -void Layer::setVisibleRegion(const Region& visibleRegion) { - // always called from main thread - this->visibleRegion = visibleRegion; -} - -void Layer::setCoveredRegion(const Region& coveredRegion) { - // always called from main thread - this->coveredRegion = coveredRegion; -} - -void Layer::setVisibleNonTransparentRegion(const Region& setVisibleNonTransparentRegion) { - // always called from main thread - this->visibleNonTransparentRegion = setVisibleNonTransparentRegion; -} - -void Layer::clearVisibilityRegions() { - visibleRegion.clear(); - visibleNonTransparentRegion.clear(); - coveredRegion.clear(); -} - // ---------------------------------------------------------------------------- // transaction // ---------------------------------------------------------------------------- @@ -1202,7 +1177,8 @@ LayerDebugInfo Layer::getLayerDebugInfo() const { info.mParentName = (parent == nullptr ? std::string("none") : parent->getName().string()); info.mType = getType(); info.mTransparentRegion = ds.activeTransparentRegion_legacy; - info.mVisibleRegion = visibleRegion; + + info.mVisibleRegion = debugGetVisibleRegionOnDefaultDisplay(); info.mSurfaceDamageRegion = surfaceDamageRegion; info.mLayerStack = getLayerStack(); info.mX = ds.active_legacy.transform.tx(); @@ -1826,7 +1802,7 @@ void Layer::writeToProtoDrawingState(LayerProto* layerInfo, uint32_t traceFlags) LayerProtoHelper::writePositionToProto(transform.tx(), transform.ty(), [&]() { return layerInfo->mutable_position(); }); LayerProtoHelper::writeToProto(mBounds, [&]() { return layerInfo->mutable_bounds(); }); - LayerProtoHelper::writeToProto(visibleRegion, + LayerProtoHelper::writeToProto(debugGetVisibleRegionOnDefaultDisplay(), [&]() { return layerInfo->mutable_visible_region(); }); LayerProtoHelper::writeToProto(surfaceDamageRegion, [&]() { return layerInfo->mutable_damage_region(); }); @@ -2003,6 +1979,20 @@ compositionengine::OutputLayer* Layer::findOutputLayerForDisplay( return display->getCompositionDisplay()->getOutputLayerForLayer(getCompositionLayer().get()); } +Region Layer::debugGetVisibleRegionOnDefaultDisplay() const { + sp displayDevice = mFlinger->getDefaultDisplayDeviceLocked(); + if (displayDevice == nullptr) { + return {}; + } + + auto outputLayer = findOutputLayerForDisplay(displayDevice); + if (outputLayer == nullptr) { + return {}; + } + + return outputLayer->getState().visibleRegion; +} + // --------------------------------------------------------------------------- }; // namespace android diff --git a/services/surfaceflinger/Layer.h b/services/surfaceflinger/Layer.h index 23809e85be..02a7d36b4d 100644 --- a/services/surfaceflinger/Layer.h +++ b/services/surfaceflinger/Layer.h @@ -98,10 +98,6 @@ class Layer : public compositionengine::LayerFE { public: mutable bool contentDirty{false}; - // regions below are in window-manager space - Region visibleRegion; - Region coveredRegion; - Region visibleNonTransparentRegion; Region surfaceDamageRegion; // Layer serial number. This gives layers an explicit ordering, so we @@ -518,30 +514,6 @@ public: */ uint32_t doTransaction(uint32_t transactionFlags); - /* - * setVisibleRegion - called to set the new visible region. This gives - * a chance to update the new visible region or record the fact it changed. - */ - void setVisibleRegion(const Region& visibleRegion); - - /* - * setCoveredRegion - called when the covered region changes. The covered - * region corresponds to any area of the surface that is covered - * (transparently or not) by another surface. - */ - void setCoveredRegion(const Region& coveredRegion); - - /* - * setVisibleNonTransparentRegion - called when the visible and - * non-transparent region changes. - */ - void setVisibleNonTransparentRegion(const Region& visibleNonTransparentRegion); - - /* - * Clear the visible, covered, and non-transparent regions. - */ - void clearVisibilityRegions(); - /* * latchBuffer - called each time the screen is redrawn and returns whether * the visible regions need to be recomputed (this is a fairly heavy @@ -684,6 +656,8 @@ public: compositionengine::OutputLayer* findOutputLayerForDisplay( const sp& display) const; + Region debugGetVisibleRegionOnDefaultDisplay() const; + protected: // constant sp mFlinger; diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp index 49a6800409..11e970232d 100644 --- a/services/surfaceflinger/SurfaceFlinger.cpp +++ b/services/surfaceflinger/SurfaceFlinger.cpp @@ -2793,7 +2793,6 @@ void SurfaceFlinger::computeVisibleRegions( */ Region transparentRegion; - // handle hidden surfaces by setting the visible region to empty if (CC_LIKELY(layer->isVisible())) { const bool translucent = !layer->isOpaque(s); @@ -2826,7 +2825,6 @@ void SurfaceFlinger::computeVisibleRegions( } if (visibleRegion.isEmpty()) { - layer->clearVisibilityRegions(); return; } @@ -2839,12 +2837,21 @@ void SurfaceFlinger::computeVisibleRegions( // subtract the opaque region covered by the layers above us visibleRegion.subtractSelf(aboveOpaqueLayers); + // Get coverage information for the layer as previously displayed + auto prevOutputLayer = display->getOutputLayerForLayer(compositionLayer.get()); + // TODO(b/121291683): Define this as a constant in Region.h + const Region kEmptyRegion; + const Region& oldVisibleRegion = + prevOutputLayer ? prevOutputLayer->getState().visibleRegion : kEmptyRegion; + const Region& oldCoveredRegion = + prevOutputLayer ? prevOutputLayer->getState().coveredRegion : kEmptyRegion; + // compute this layer's dirty region if (layer->contentDirty) { // we need to invalidate the whole region dirty = visibleRegion; // as well, as the old visible region - dirty.orSelf(layer->visibleRegion); + dirty.orSelf(oldVisibleRegion); layer->contentDirty = false; } else { /* compute the exposed region: @@ -2860,8 +2867,6 @@ void SurfaceFlinger::computeVisibleRegions( * exposed because of a resize. */ const Region newExposed = visibleRegion - coveredRegion; - const Region oldVisibleRegion = layer->visibleRegion; - const Region oldCoveredRegion = layer->coveredRegion; const Region oldExposed = oldVisibleRegion - oldCoveredRegion; dirty = (visibleRegion&oldCoveredRegion) | (newExposed-oldExposed); } @@ -2873,16 +2878,13 @@ void SurfaceFlinger::computeVisibleRegions( // Update aboveOpaqueLayers for next (lower) layer aboveOpaqueLayers.orSelf(opaqueRegion); - // Store the visible region in screen space - layer->setVisibleRegion(visibleRegion); - layer->setCoveredRegion(coveredRegion); - layer->setVisibleNonTransparentRegion( - visibleRegion.subtract(transparentRegion)); + // Compute the visible non-transparent region + Region visibleNonTransparentRegion = visibleRegion.subtract(transparentRegion); - // Setup an output layer for this output if the layer is - // visible on this output + // Setup an output layer for this output if the layer is visible on this + // output const auto& displayState = display->getState(); - Region drawRegion(displayState.transform.transform(layer->visibleNonTransparentRegion)); + Region drawRegion(displayState.transform.transform(visibleNonTransparentRegion)); drawRegion.andSelf(displayState.bounds); if (drawRegion.isEmpty()) { return; @@ -2895,8 +2897,11 @@ void SurfaceFlinger::computeVisibleRegions( outLayersSortedByZ.emplace_back( display->getOrCreateOutputLayer(displayId, compositionLayer, layerFE)); auto& outputLayerState = outLayersSortedByZ.back()->editState(); - outputLayerState.visibleRegion = displayState.transform.transform( - layer->visibleRegion.intersect(displayState.viewport)); + outputLayerState.visibleRegion = std::move(visibleRegion); + outputLayerState.visibleNonTransparentRegion = std::move(visibleNonTransparentRegion); + outputLayerState.coveredRegion = std::move(coveredRegion); + outputLayerState.outputSpaceVisibleRegion = displayState.transform.transform( + outputLayerState.visibleRegion.intersect(displayState.viewport)); }); outOpaqueRegion = aboveOpaqueLayers; diff --git a/services/surfaceflinger/tests/unittests/CompositionTest.cpp b/services/surfaceflinger/tests/unittests/CompositionTest.cpp index 425768e244..9e4d57e7dc 100644 --- a/services/surfaceflinger/tests/unittests/CompositionTest.cpp +++ b/services/surfaceflinger/tests/unittests/CompositionTest.cpp @@ -614,6 +614,12 @@ struct BaseLayerProperties { displaySettings.clip); // screen capture adds an additional color layer as an alpha // prefill, so gtet the back layer. + if (layerSettings.empty()) { + ADD_FAILURE() << "layerSettings was not expected to be empty in " + "setupREBufferCompositionCommonCallExpectations " + "verification lambda"; + return NO_ERROR; + } renderengine::LayerSettings layer = layerSettings.back(); EXPECT_THAT(layer.source.buffer.buffer, Not(IsNull())); EXPECT_THAT(layer.source.buffer.fence, Not(IsNull())); @@ -657,6 +663,12 @@ struct BaseLayerProperties { displaySettings.clip); // screen capture adds an additional color layer as an alpha // prefill, so get the back layer. + if (layerSettings.empty()) { + ADD_FAILURE() + << "layerSettings was not expected to be empty in " + "setupREColorCompositionCallExpectations verification lambda"; + return NO_ERROR; + } renderengine::LayerSettings layer = layerSettings.back(); EXPECT_THAT(layer.source.buffer.buffer, IsNull()); EXPECT_EQ(half3(LayerProperties::COLOR[0], LayerProperties::COLOR[1], @@ -727,6 +739,12 @@ struct SecureLayerProperties : public BaseLayerProperties displaySettings.clip); // screen capture adds an additional color layer as an alpha // prefill, so get the back layer. + if (layerSettings.empty()) { + ADD_FAILURE() << "layerSettings was not expected to be empty in " + "setupInsecureREBufferCompositionCommonCallExpectations " + "verification lambda"; + return NO_ERROR; + } renderengine::LayerSettings layer = layerSettings.back(); EXPECT_THAT(layer.source.buffer.buffer, IsNull()); EXPECT_EQ(half3(0.0f, 0.0f, 0.0f), layer.source.solidColor); @@ -786,7 +804,6 @@ struct BaseLayerVariant { layerDrawingState.color = half4(LayerProperties::COLOR[0], LayerProperties::COLOR[1], LayerProperties::COLOR[2], LayerProperties::COLOR[3]); layer->computeBounds(FloatRect(0, 0, 100, 100), ui::Transform()); - layer->setVisibleRegion(Region(Rect(0, 0, 100, 100))); return layer; } @@ -801,6 +818,9 @@ struct BaseLayerVariant { layer->getCompositionLayer(), layer)); + outputLayers.back()->editState().visibleRegion = Region(Rect(0, 0, 100, 100)); + outputLayers.back()->editState().outputSpaceVisibleRegion = Region(Rect(0, 0, 100, 100)); + test->mDisplay->getCompositionDisplay()->setOutputLayersOrderedByZ(std::move(outputLayers)); Mock::VerifyAndClear(test->mComposer); -- cgit v1.2.3-59-g8ed1b From c668734cece8d71ead434517e0a4fa9752bd79ce Mon Sep 17 00:00:00 2001 From: Lloyd Pique Date: Thu, 7 Mar 2019 21:34:57 -0800 Subject: SF: Add ability to get basic geometry For computing the layer visibility, CompositionEngine will need to get basic geometry state for every layer, without getting everything. Add a new request type for the basic geometry state, and modify the existing code in computeVisibleRegions to use it rather than accessing directly through the front-end layer pointer. Test: atest libsurfaceflinger_unittest libcompositionengine_test Test: go/wm-smoke Bug: 121291683 Change-Id: Ie286fe1986a4c383ee390c1f646c7a8a5b8c14f4 --- .../include/compositionengine/LayerFE.h | 23 +++++++- .../compositionengine/LayerFECompositionState.h | 56 ++++++++++++------ .../include/compositionengine/Output.h | 2 +- .../include/compositionengine/impl/Output.h | 2 +- .../include/compositionengine/mock/LayerFE.h | 3 +- .../include/compositionengine/mock/Output.h | 2 +- .../src/LayerCompositionState.cpp | 2 +- .../CompositionEngine/src/Output.cpp | 9 ++- .../CompositionEngine/src/OutputLayer.cpp | 4 +- .../CompositionEngine/tests/OutputLayerTest.cpp | 6 +- .../CompositionEngine/tests/OutputTest.cpp | 4 ++ services/surfaceflinger/Layer.cpp | 69 ++++++++++++++++------ services/surfaceflinger/Layer.h | 3 +- services/surfaceflinger/SurfaceFlinger.cpp | 42 +++++++------ 14 files changed, 158 insertions(+), 69 deletions(-) (limited to 'services/surfaceflinger/Layer.cpp') diff --git a/services/surfaceflinger/CompositionEngine/include/compositionengine/LayerFE.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/LayerFE.h index db4f9698e2..57cca69eb2 100644 --- a/services/surfaceflinger/CompositionEngine/include/compositionengine/LayerFE.h +++ b/services/surfaceflinger/CompositionEngine/include/compositionengine/LayerFE.h @@ -39,9 +39,26 @@ public: // process. virtual bool onPreComposition(nsecs_t refreshStartTime) = 0; - // Latches the output-independent state. If includeGeometry is false, the - // geometry state can be skipped. - virtual void latchCompositionState(LayerFECompositionState&, bool includeGeometry) const = 0; + // Used with latchCompositionState() + enum class StateSubset { + // Gets the basic geometry (bounds, transparent region, visibility, + // transforms, alpha) for the layer, for computing visibility and + // coverage. + BasicGeometry, + + // Gets the full geometry (crops, buffer transforms, metadata) and + // content (buffer or color) state for the layer. + GeometryAndContent, + + // Gets the per frame content (buffer or color) state the layer. + Content, + }; + + // Latches the output-independent composition state for the layer. The + // StateSubset argument selects what portion of the state is actually needed + // by the CompositionEngine code, since computing everything may be + // expensive. + virtual void latchCompositionState(LayerFECompositionState&, StateSubset) const = 0; // Latches the minimal bit of state for the cursor for a fast asynchronous // update. diff --git a/services/surfaceflinger/CompositionEngine/include/compositionengine/LayerFECompositionState.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/LayerFECompositionState.h index b066cd1bda..530f49a600 100644 --- a/services/surfaceflinger/CompositionEngine/include/compositionengine/LayerFECompositionState.h +++ b/services/surfaceflinger/CompositionEngine/include/compositionengine/LayerFECompositionState.h @@ -40,6 +40,45 @@ struct LayerFECompositionState { // the next geometry change. bool forceClientComposition{false}; + // TODO(b/121291683): Reorganize and rename the contents of this structure + + /* + * Visibility state + */ + // the layer stack this layer belongs to + std::optional layerStackId; + + // If true, this layer should be only visible on the internal display + bool internalOnly{false}; + + // If false, this layer should not be considered visible + bool isVisible{true}; + + // True if the layer is completely opaque + bool isOpaque{true}; + + // If true, invalidates the entire visible region + bool contentDirty{false}; + + // The alpha value for this layer + float alpha{1.f}; + + // The transform from layer local coordinates to composition coordinates + ui::Transform geomLayerTransform; + + // The inverse of the layer transform + ui::Transform geomInverseLayerTransform; + + // The hint from the layer producer as to what portion of the layer is + // transparent. + Region transparentRegionHint; + + // The blend mode for this layer + Hwc2::IComposerClient::BlendMode blendMode{Hwc2::IComposerClient::BlendMode::INVALID}; + + // The bounds of the layer in layer local coordinates + FloatRect geomLayerBounds; + /* * Geometry state */ @@ -48,23 +87,9 @@ struct LayerFECompositionState { bool geomUsesSourceCrop{false}; bool geomBufferUsesDisplayInverseTransform{false}; uint32_t geomBufferTransform{0}; - ui::Transform geomLayerTransform; - ui::Transform geomInverseLayerTransform; Rect geomBufferSize; Rect geomContentCrop; Rect geomCrop; - Region geomActiveTransparentRegion; - FloatRect geomLayerBounds; - - /* - * Presentation - */ - - // The blend mode for this layer - Hwc2::IComposerClient::BlendMode blendMode{Hwc2::IComposerClient::BlendMode::INVALID}; - - // The alpha value for this layer - float alpha{1.f}; /* * Extra metadata @@ -113,9 +138,6 @@ struct LayerFECompositionState { mat4 colorTransform; bool colorTransformIsIdentity{true}; - // True if the layer is completely opaque - bool isOpaque{true}; - // True if the layer has protected content bool hasProtectedContent{false}; diff --git a/services/surfaceflinger/CompositionEngine/include/compositionengine/Output.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/Output.h index a509ca8129..43f44af8ca 100644 --- a/services/surfaceflinger/CompositionEngine/include/compositionengine/Output.h +++ b/services/surfaceflinger/CompositionEngine/include/compositionengine/Output.h @@ -132,7 +132,7 @@ public: // A layer belongs to the output if its layerStackId matches. Additionally // if the layer should only show in the internal (primary) display only and // this output allows that. - virtual bool belongsInOutput(uint32_t layerStackId, bool internalOnly) const = 0; + virtual bool belongsInOutput(std::optional layerStackId, bool internalOnly) const = 0; // Returns a pointer to the output layer corresponding to the given layer on // this output, or nullptr if the layer does not have one diff --git a/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/Output.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/Output.h index d826161a4d..ece5b1c5ee 100644 --- a/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/Output.h +++ b/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/Output.h @@ -62,7 +62,7 @@ public: OutputCompositionState& editState() override; Region getDirtyRegion(bool repaintEverything) const override; - bool belongsInOutput(uint32_t, bool) const override; + bool belongsInOutput(std::optional, bool) const override; compositionengine::OutputLayer* getOutputLayerForLayer( compositionengine::Layer*) const override; diff --git a/services/surfaceflinger/CompositionEngine/include/compositionengine/mock/LayerFE.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/mock/LayerFE.h index e2802954d6..3eada3c6aa 100644 --- a/services/surfaceflinger/CompositionEngine/include/compositionengine/mock/LayerFE.h +++ b/services/surfaceflinger/CompositionEngine/include/compositionengine/mock/LayerFE.h @@ -32,7 +32,8 @@ public: MOCK_METHOD1(onPreComposition, bool(nsecs_t)); - MOCK_CONST_METHOD2(latchCompositionState, void(LayerFECompositionState&, bool)); + MOCK_CONST_METHOD2(latchCompositionState, + void(LayerFECompositionState&, compositionengine::LayerFE::StateSubset)); MOCK_CONST_METHOD1(latchCursorCompositionState, void(LayerFECompositionState&)); MOCK_METHOD1(prepareClientComposition, std::optional( diff --git a/services/surfaceflinger/CompositionEngine/include/compositionengine/mock/Output.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/mock/Output.h index 33925d5691..2f24c15896 100644 --- a/services/surfaceflinger/CompositionEngine/include/compositionengine/mock/Output.h +++ b/services/surfaceflinger/CompositionEngine/include/compositionengine/mock/Output.h @@ -59,7 +59,7 @@ public: MOCK_METHOD0(editState, OutputCompositionState&()); MOCK_CONST_METHOD1(getDirtyRegion, Region(bool)); - MOCK_CONST_METHOD2(belongsInOutput, bool(uint32_t, bool)); + MOCK_CONST_METHOD2(belongsInOutput, bool(std::optional, bool)); MOCK_CONST_METHOD1(getOutputLayerForLayer, compositionengine::OutputLayer*(compositionengine::Layer*)); diff --git a/services/surfaceflinger/CompositionEngine/src/LayerCompositionState.cpp b/services/surfaceflinger/CompositionEngine/src/LayerCompositionState.cpp index 0dc4bf1559..c5debf6e77 100644 --- a/services/surfaceflinger/CompositionEngine/src/LayerCompositionState.cpp +++ b/services/surfaceflinger/CompositionEngine/src/LayerCompositionState.cpp @@ -45,7 +45,7 @@ void dumpFrontEnd(std::string& out, const LayerFECompositionState& state) { dumpVal(out, "geomBufferTransform", state.geomBufferTransform); out.append("\n "); - dumpVal(out, "geomActiveTransparentRegion", state.geomActiveTransparentRegion); + dumpVal(out, "transparentRegionHint", state.transparentRegionHint); out.append(" "); dumpVal(out, "geomLayerBounds", state.geomLayerBounds); diff --git a/services/surfaceflinger/CompositionEngine/src/Output.cpp b/services/surfaceflinger/CompositionEngine/src/Output.cpp index 9f4f259f7c..4dfdebae02 100644 --- a/services/surfaceflinger/CompositionEngine/src/Output.cpp +++ b/services/surfaceflinger/CompositionEngine/src/Output.cpp @@ -212,10 +212,11 @@ Region Output::getDirtyRegion(bool repaintEverything) const { return dirty; } -bool Output::belongsInOutput(uint32_t layerStackId, bool internalOnly) const { +bool Output::belongsInOutput(std::optional layerStackId, bool internalOnly) const { // The layerStackId's must match, and also the layer must not be internal // only when not on an internal output. - return (layerStackId == mState.layerStackId) && (!internalOnly || mState.layerStackInternal); + return layerStackId && (*layerStackId == mState.layerStackId) && + (!internalOnly || mState.layerStackInternal); } compositionengine::OutputLayer* Output::getOutputLayerForLayer( @@ -281,7 +282,9 @@ void Output::present(const compositionengine::CompositionRefreshArgs& refreshArg void Output::updateLayerStateFromFE(const CompositionRefreshArgs& args) const { for (auto& layer : mOutputLayersOrderedByZ) { layer->getLayerFE().latchCompositionState(layer->getLayer().editState().frontEnd, - args.updatingGeometryThisFrame); + args.updatingGeometryThisFrame + ? LayerFE::StateSubset::GeometryAndContent + : LayerFE::StateSubset::Content); } } diff --git a/services/surfaceflinger/CompositionEngine/src/OutputLayer.cpp b/services/surfaceflinger/CompositionEngine/src/OutputLayer.cpp index 21f0ce8b15..3a0ebf8121 100644 --- a/services/surfaceflinger/CompositionEngine/src/OutputLayer.cpp +++ b/services/surfaceflinger/CompositionEngine/src/OutputLayer.cpp @@ -102,7 +102,7 @@ Rect OutputLayer::calculateInitialCrop() const { // pixels in the buffer. FloatRect activeCropFloat = - reduce(layerState.geomLayerBounds, layerState.geomActiveTransparentRegion); + reduce(layerState.geomLayerBounds, layerState.transparentRegionHint); const Rect& viewport = mOutput.getState().viewport; const ui::Transform& layerTransform = layerState.geomLayerTransform; @@ -209,7 +209,7 @@ Rect OutputLayer::calculateOutputDisplayFrame() const { // apply the layer's transform, followed by the display's global transform // here we're guaranteed that the layer's transform preserves rects - Region activeTransparentRegion = layerState.geomActiveTransparentRegion; + Region activeTransparentRegion = layerState.transparentRegionHint; const ui::Transform& layerTransform = layerState.geomLayerTransform; const ui::Transform& inverseLayerTransform = layerState.geomInverseLayerTransform; const Rect& bufferSize = layerState.geomBufferSize; diff --git a/services/surfaceflinger/CompositionEngine/tests/OutputLayerTest.cpp b/services/surfaceflinger/CompositionEngine/tests/OutputLayerTest.cpp index 2276dc3691..65691ffbc7 100644 --- a/services/surfaceflinger/CompositionEngine/tests/OutputLayerTest.cpp +++ b/services/surfaceflinger/CompositionEngine/tests/OutputLayerTest.cpp @@ -124,7 +124,7 @@ struct OutputLayerSourceCropTest : public OutputLayerTest { // set one specific value to something different. mLayerState.frontEnd.geomUsesSourceCrop = true; mLayerState.frontEnd.geomContentCrop = Rect{0, 0, 1920, 1080}; - mLayerState.frontEnd.geomActiveTransparentRegion = Region{}; + mLayerState.frontEnd.transparentRegionHint = Region{}; mLayerState.frontEnd.geomLayerBounds = FloatRect{0.f, 0.f, 1920.f, 1080.f}; mLayerState.frontEnd.geomLayerTransform = ui::Transform{TR_IDENT}; mLayerState.frontEnd.geomBufferSize = Rect{0, 0, 1920, 1080}; @@ -231,7 +231,7 @@ struct OutputLayerDisplayFrameTest : public OutputLayerTest { // Set reasonable default values for a simple case. Each test will // set one specific value to something different. - mLayerState.frontEnd.geomActiveTransparentRegion = Region{}; + mLayerState.frontEnd.transparentRegionHint = Region{}; mLayerState.frontEnd.geomLayerTransform = ui::Transform{TR_IDENT}; mLayerState.frontEnd.geomBufferSize = Rect{0, 0, 1920, 1080}; mLayerState.frontEnd.geomBufferUsesDisplayInverseTransform = false; @@ -256,7 +256,7 @@ TEST_F(OutputLayerDisplayFrameTest, correctForSimpleDefaultCase) { } TEST_F(OutputLayerDisplayFrameTest, fullActiveTransparentRegionReturnsEmptyFrame) { - mLayerState.frontEnd.geomActiveTransparentRegion = Region{Rect{0, 0, 1920, 1080}}; + mLayerState.frontEnd.transparentRegionHint = Region{Rect{0, 0, 1920, 1080}}; const Rect expected{0, 0, 0, 0}; EXPECT_THAT(calculateOutputDisplayFrame(), RectEq(expected)); } diff --git a/services/surfaceflinger/CompositionEngine/tests/OutputTest.cpp b/services/surfaceflinger/CompositionEngine/tests/OutputTest.cpp index b0e8e3699c..70d98717ae 100644 --- a/services/surfaceflinger/CompositionEngine/tests/OutputTest.cpp +++ b/services/surfaceflinger/CompositionEngine/tests/OutputTest.cpp @@ -356,6 +356,10 @@ TEST_F(OutputTest, belongsInOutputFiltersAsExpected) { // If the output accepts layerStack1 and internal-only layers.... mOutput.setLayerStackFilter(layerStack1, true); + // A layer with no layerStack does not belong to it, internal-only or not. + EXPECT_FALSE(mOutput.belongsInOutput(std::nullopt, false)); + EXPECT_FALSE(mOutput.belongsInOutput(std::nullopt, true)); + // Any layer with layerStack1 belongs to it, internal-only or not. EXPECT_TRUE(mOutput.belongsInOutput(layerStack1, false)); EXPECT_TRUE(mOutput.belongsInOutput(layerStack1, true)); diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp index 5e5302d83c..974488da62 100644 --- a/services/surfaceflinger/Layer.cpp +++ b/services/surfaceflinger/Layer.cpp @@ -417,15 +417,44 @@ void Layer::setupRoundedCornersCropCoordinates(Rect win, win.bottom -= roundedCornersCrop.top; } -void Layer::latchGeometry(compositionengine::LayerFECompositionState& compositionState) const { +void Layer::latchBasicGeometry(compositionengine::LayerFECompositionState& compositionState) const { const auto& drawingState{getDrawingState()}; - auto alpha = static_cast(getAlpha()); - auto blendMode = HWC2::BlendMode::None; - if (!isOpaque(drawingState) || alpha != 1.0f) { - blendMode = - mPremultipliedAlpha ? HWC2::BlendMode::Premultiplied : HWC2::BlendMode::Coverage; + const uint32_t layerStack = getLayerStack(); + const auto alpha = static_cast(getAlpha()); + const bool opaque = isOpaque(drawingState); + const bool usesRoundedCorners = getRoundedCornerState().radius != 0.f; + + auto blendMode = Hwc2::IComposerClient::BlendMode::NONE; + if (!opaque || alpha != 1.0f) { + blendMode = mPremultipliedAlpha ? Hwc2::IComposerClient::BlendMode::PREMULTIPLIED + : Hwc2::IComposerClient::BlendMode::COVERAGE; } + // TODO(b/121291683): Instead of filling in a passed-in compositionState + // structure, switch to Layer owning the structure and have + // CompositionEngine be able to get a reference to it. + + compositionState.layerStackId = + (layerStack != ~0u) ? std::make_optional(layerStack) : std::nullopt; + compositionState.internalOnly = getPrimaryDisplayOnly(); + compositionState.isVisible = isVisible(); + compositionState.isOpaque = opaque && !usesRoundedCorners && alpha == 1.f; + + compositionState.contentDirty = contentDirty; + contentDirty = false; + + compositionState.geomLayerBounds = mBounds; + compositionState.geomLayerTransform = getTransform(); + compositionState.geomInverseLayerTransform = compositionState.geomLayerTransform.inverse(); + compositionState.transparentRegionHint = getActiveTransparentRegion(drawingState); + + compositionState.blendMode = static_cast(blendMode); + compositionState.alpha = alpha; +} + +void Layer::latchGeometry(compositionengine::LayerFECompositionState& compositionState) const { + const auto& drawingState{getDrawingState()}; + int type = drawingState.metadata.getInt32(METADATA_WINDOW_TYPE, 0); int appId = drawingState.metadata.getInt32(METADATA_OWNER_UID, 0); sp parent = mDrawingParent.promote(); @@ -439,20 +468,14 @@ void Layer::latchGeometry(compositionengine::LayerFECompositionState& compositio } } - compositionState.geomLayerTransform = getTransform(); - compositionState.geomInverseLayerTransform = compositionState.geomLayerTransform.inverse(); compositionState.geomBufferSize = getBufferSize(drawingState); compositionState.geomContentCrop = getContentCrop(); compositionState.geomCrop = getCrop(drawingState); compositionState.geomBufferTransform = mCurrentTransform; compositionState.geomBufferUsesDisplayInverseTransform = getTransformToDisplayInverse(); - compositionState.geomActiveTransparentRegion = getActiveTransparentRegion(drawingState); - compositionState.geomLayerBounds = mBounds; compositionState.geomUsesSourceCrop = usesSourceCrop(); compositionState.isSecure = isSecure(); - compositionState.blendMode = static_cast(blendMode); - compositionState.alpha = alpha; compositionState.type = type; compositionState.appId = appId; } @@ -498,12 +521,24 @@ bool Layer::onPreComposition(nsecs_t) { } void Layer::latchCompositionState(compositionengine::LayerFECompositionState& compositionState, - bool includeGeometry) const { - if (includeGeometry) { - latchGeometry(compositionState); - } + compositionengine::LayerFE::StateSubset subset) const { + using StateSubset = compositionengine::LayerFE::StateSubset; + + switch (subset) { + case StateSubset::BasicGeometry: + latchBasicGeometry(compositionState); + break; - latchPerFrameState(compositionState); + case StateSubset::GeometryAndContent: + latchBasicGeometry(compositionState); + latchGeometry(compositionState); + latchPerFrameState(compositionState); + break; + + case StateSubset::Content: + latchPerFrameState(compositionState); + break; + } } const char* Layer::getDebugName() const { diff --git a/services/surfaceflinger/Layer.h b/services/surfaceflinger/Layer.h index 1486efe8ae..02c78c9d66 100644 --- a/services/surfaceflinger/Layer.h +++ b/services/surfaceflinger/Layer.h @@ -471,7 +471,7 @@ public: */ bool onPreComposition(nsecs_t) override; void latchCompositionState(compositionengine::LayerFECompositionState&, - bool includeGeometry) const override; + compositionengine::LayerFE::StateSubset subset) const override; void latchCursorCompositionState(compositionengine::LayerFECompositionState&) const override; std::optional prepareClientComposition( compositionengine::LayerFE::ClientCompositionTargetSettings&) override; @@ -479,6 +479,7 @@ public: const char* getDebugName() const override; protected: + void latchBasicGeometry(compositionengine::LayerFECompositionState& outState) const; void latchGeometry(compositionengine::LayerFECompositionState& outState) const; virtual void latchPerFrameState(compositionengine::LayerFECompositionState& outState) const; diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp index 3498419cdf..6d853f957a 100644 --- a/services/surfaceflinger/SurfaceFlinger.cpp +++ b/services/surfaceflinger/SurfaceFlinger.cpp @@ -2757,11 +2757,22 @@ void SurfaceFlinger::computeVisibleRegions( return; } - // start with the whole surface at its current location - const Layer::State& s(layer->getDrawingState()); + // Note: Converts a wp to a sp + auto layerFE = compositionLayer->getLayerFE(); + if (layerFE == nullptr) { + return; + } + + // Request a snapshot of the subset of state relevant to visibility + // determination + layerFE->latchCompositionState(compositionLayer->editState().frontEnd, + compositionengine::LayerFE::StateSubset::BasicGeometry); + + // Work with a read-only copy of the snapshot + const auto& layerFEState = compositionLayer->getState().frontEnd; // only consider the layers on the given layer stack - if (!display->belongsInOutput(layer->getLayerStack(), layer->getPrimaryDisplayOnly())) { + if (!display->belongsInOutput(layerFEState.layerStackId, layerFEState.internalOnly)) { return; } @@ -2795,18 +2806,17 @@ void SurfaceFlinger::computeVisibleRegions( Region transparentRegion; // handle hidden surfaces by setting the visible region to empty - if (CC_LIKELY(layer->isVisible())) { - const bool translucent = !layer->isOpaque(s); - Rect bounds(layer->getScreenBounds()); - - visibleRegion.set(bounds); - ui::Transform tr = layer->getTransform(); + if (CC_LIKELY(layerFEState.isVisible)) { + // Get the visible region + visibleRegion.set( + Rect(layerFEState.geomLayerTransform.transform(layerFEState.geomLayerBounds))); + const ui::Transform& tr = layerFEState.geomLayerTransform; if (!visibleRegion.isEmpty()) { // Remove the transparent area from the visible region - if (translucent) { + if (!layerFEState.isOpaque) { if (tr.preserveRects()) { // transform the transparent region - transparentRegion = tr.transform(layer->getActiveTransparentRegion(s)); + transparentRegion = tr.transform(layerFEState.transparentRegionHint); } else { // transformation too complex, can't do the // transparent region optimization. @@ -2816,9 +2826,8 @@ void SurfaceFlinger::computeVisibleRegions( // compute the opaque region const int32_t layerOrientation = tr.getOrientation(); - if (layer->getAlpha() == 1.0f && !translucent && - layer->getRoundedCornerState().radius == 0.0f && - ((layerOrientation & ui::Transform::ROT_INVALID) == false)) { + if (layerFEState.isOpaque && + ((layerOrientation & ui::Transform::ROT_INVALID) == false)) { // the opaque region is the layer's footprint opaqueRegion = visibleRegion; } @@ -2848,12 +2857,11 @@ void SurfaceFlinger::computeVisibleRegions( prevOutputLayer ? prevOutputLayer->getState().coveredRegion : kEmptyRegion; // compute this layer's dirty region - if (layer->contentDirty) { + if (layerFEState.contentDirty) { // we need to invalidate the whole region dirty = visibleRegion; // as well, as the old visible region dirty.orSelf(oldVisibleRegion); - layer->contentDirty = false; } else { /* compute the exposed region: * the exposed region consists of two components: @@ -2892,8 +2900,6 @@ void SurfaceFlinger::computeVisibleRegions( } const auto displayId = displayDevice->getId(); - sp layerFE = compositionLayer->getLayerFE(); - LOG_ALWAYS_FATAL_IF(layerFE.get() == nullptr); outLayersSortedByZ.emplace_back( display->getOrCreateOutputLayer(displayId, compositionLayer, layerFE)); -- cgit v1.2.3-59-g8ed1b From 4244e0356083fba0a367b9cb5422cd24d567518a Mon Sep 17 00:00:00 2001 From: chaviw Date: Wed, 4 Sep 2019 11:27:49 -0700 Subject: Created bufferInfo to track buffer data in a single place (1/2) This is in preparation for layer mirroring since mirrored buffer layers should just copy the bufferInfo instead of the entire BufferQueue or parts of BufferState Test: go/wm-smoke Change-Id: Iba1be05c4b038f0b678150deed8e673bf1e7710b --- services/surfaceflinger/BufferLayer.cpp | 124 ++++++++++++++++---------- services/surfaceflinger/BufferLayer.h | 46 ++++++---- services/surfaceflinger/BufferQueueLayer.cpp | 65 ++++---------- services/surfaceflinger/BufferQueueLayer.h | 15 +--- services/surfaceflinger/BufferStateLayer.cpp | 126 ++++++++++----------------- services/surfaceflinger/BufferStateLayer.h | 20 ++--- services/surfaceflinger/ColorLayer.cpp | 9 +- services/surfaceflinger/ColorLayer.h | 2 +- services/surfaceflinger/Layer.cpp | 42 +++------ services/surfaceflinger/Layer.h | 12 +-- 10 files changed, 204 insertions(+), 257 deletions(-) (limited to 'services/surfaceflinger/Layer.cpp') diff --git a/services/surfaceflinger/BufferLayer.cpp b/services/surfaceflinger/BufferLayer.cpp index 90a02b3ad9..bca15e6903 100644 --- a/services/surfaceflinger/BufferLayer.cpp +++ b/services/surfaceflinger/BufferLayer.cpp @@ -81,7 +81,7 @@ void BufferLayer::useSurfaceDamage() { if (mFlinger->mForceFullDamage) { surfaceDamageRegion = Region::INVALID_REGION; } else { - surfaceDamageRegion = getDrawingSurfaceDamage(); + surfaceDamageRegion = mBufferInfo.mSurfaceDamage; } } @@ -187,7 +187,7 @@ std::optional BufferLayer::prepareClientComposition // Query the texture matrix given our current filtering mode. float textureMatrix[16]; setFilteringEnabled(useFiltering); - getDrawingTransformMatrix(textureMatrix); + memcpy(textureMatrix, mBufferInfo.mTransformMatrix, sizeof(mBufferInfo.mTransformMatrix)); if (getTransformToDisplayInverse()) { /* @@ -254,8 +254,8 @@ std::optional BufferLayer::prepareClientComposition bool BufferLayer::isHdrY410() const { // pixel format is HDR Y410 masquerading as RGBA_1010102 - return (mCurrentDataSpace == ui::Dataspace::BT2020_ITU_PQ && - getDrawingApi() == NATIVE_WINDOW_API_MEDIA && + return (mBufferInfo.mDataspace == ui::Dataspace::BT2020_ITU_PQ && + mBufferInfo.mApi == NATIVE_WINDOW_API_MEDIA && mActiveBuffer->getPixelFormat() == HAL_PIXEL_FORMAT_RGBA_1010102); } @@ -268,7 +268,7 @@ void BufferLayer::latchPerFrameState( compositionState.compositionType = Hwc2::IComposerClient::Composition::SIDEBAND; } else { // Normal buffer layers - compositionState.hdrMetadata = getDrawingHdrMetadata(); + compositionState.hdrMetadata = mBufferInfo.mHdrMetadata; compositionState.compositionType = mPotentialCursor ? Hwc2::IComposerClient::Composition::CURSOR : Hwc2::IComposerClient::Composition::DEVICE; @@ -300,13 +300,13 @@ bool BufferLayer::onPostComposition(const std::optional& displayId, } // Update mFrameTracker. - nsecs_t desiredPresentTime = getDesiredPresentTime(); + nsecs_t desiredPresentTime = mBufferInfo.mDesiredPresentTime; mFrameTracker.setDesiredPresentTime(desiredPresentTime); const int32_t layerID = getSequence(); mFlinger->mTimeStats->setDesiredTime(layerID, mCurrentFrameNumber, desiredPresentTime); - std::shared_ptr frameReadyFence = getCurrentFenceTime(); + std::shared_ptr frameReadyFence = mBufferInfo.mFenceTime; if (frameReadyFence->isValid()) { mFrameTracker.setFrameReadyFence(std::move(frameReadyFence)); } else { @@ -394,6 +394,9 @@ bool BufferLayer::latchBuffer(bool& recomputeVisibleRegions, nsecs_t latchTime, return false; } + BufferInfo oldBufferInfo = mBufferInfo; + gatherBufferInfo(); + mRefreshPending = true; mFrameLatencyNeeded = true; if (oldBuffer == nullptr) { @@ -402,43 +405,10 @@ bool BufferLayer::latchBuffer(bool& recomputeVisibleRegions, nsecs_t latchTime, recomputeVisibleRegions = true; } - ui::Dataspace dataSpace = getDrawingDataSpace(); - // translate legacy dataspaces to modern dataspaces - switch (dataSpace) { - case ui::Dataspace::SRGB: - dataSpace = ui::Dataspace::V0_SRGB; - break; - case ui::Dataspace::SRGB_LINEAR: - dataSpace = ui::Dataspace::V0_SRGB_LINEAR; - break; - case ui::Dataspace::JFIF: - dataSpace = ui::Dataspace::V0_JFIF; - break; - case ui::Dataspace::BT601_625: - dataSpace = ui::Dataspace::V0_BT601_625; - break; - case ui::Dataspace::BT601_525: - dataSpace = ui::Dataspace::V0_BT601_525; - break; - case ui::Dataspace::BT709: - dataSpace = ui::Dataspace::V0_BT709; - break; - default: - break; - } - mCurrentDataSpace = dataSpace; - - Rect crop(getDrawingCrop()); - const uint32_t transform(getDrawingTransform()); - const uint32_t scalingMode(getDrawingScalingMode()); - const bool transformToDisplayInverse(getTransformToDisplayInverse()); - if ((crop != mCurrentCrop) || (transform != mCurrentTransform) || - (scalingMode != mCurrentScalingMode) || - (transformToDisplayInverse != mTransformToDisplayInverse)) { - mCurrentCrop = crop; - mCurrentTransform = transform; - mCurrentScalingMode = scalingMode; - mTransformToDisplayInverse = transformToDisplayInverse; + if ((mBufferInfo.mCrop != oldBufferInfo.mCrop) || + (mBufferInfo.mTransform != oldBufferInfo.mTransform) || + (mBufferInfo.mScaleMode != oldBufferInfo.mScaleMode) || + (mBufferInfo.mTransformToDisplayInverse != oldBufferInfo.mTransformToDisplayInverse)) { recomputeVisibleRegions = true; } @@ -510,7 +480,7 @@ uint32_t BufferLayer::getEffectiveScalingMode() const { return mOverrideScalingMode; } - return mCurrentScalingMode; + return mBufferInfo.mScaleMode; } bool BufferLayer::isProtected() const { @@ -626,7 +596,7 @@ Rect BufferLayer::getBufferSize(const State& s) const { uint32_t bufHeight = mActiveBuffer->getHeight(); // Undo any transformations on the buffer and return the result. - if (mCurrentTransform & ui::Transform::ROT_90) { + if (mBufferInfo.mTransform & ui::Transform::ROT_90) { std::swap(bufWidth, bufHeight); } @@ -662,7 +632,7 @@ FloatRect BufferLayer::computeSourceBounds(const FloatRect& parentBounds) const uint32_t bufHeight = mActiveBuffer->getHeight(); // Undo any transformations on the buffer and return the result. - if (mCurrentTransform & ui::Transform::ROT_90) { + if (mBufferInfo.mTransform & ui::Transform::ROT_90) { std::swap(bufWidth, bufHeight); } @@ -685,6 +655,66 @@ void BufferLayer::latchAndReleaseBuffer() { releasePendingBuffer(systemTime()); } +PixelFormat BufferLayer::getPixelFormat() const { + return mBufferInfo.mPixelFormat; +} + +bool BufferLayer::getTransformToDisplayInverse() const { + return mBufferInfo.mTransformToDisplayInverse; +} + +Rect BufferLayer::getBufferCrop() const { + // this is the crop rectangle that applies to the buffer + // itself (as opposed to the window) + if (!mBufferInfo.mCrop.isEmpty()) { + // if the buffer crop is defined, we use that + return mBufferInfo.mCrop; + } else if (mActiveBuffer != nullptr) { + // otherwise we use the whole buffer + return mActiveBuffer->getBounds(); + } else { + // if we don't have a buffer yet, we use an empty/invalid crop + return Rect(); + } +} + +uint32_t BufferLayer::getBufferTransform() const { + return mBufferInfo.mTransform; +} + +ui::Dataspace BufferLayer::getDataSpace() const { + return mBufferInfo.mDataspace; +} + +ui::Dataspace BufferLayer::translateDataspace(ui::Dataspace dataspace) { + ui::Dataspace updatedDataspace = dataspace; + // translate legacy dataspaces to modern dataspaces + switch (dataspace) { + case ui::Dataspace::SRGB: + updatedDataspace = ui::Dataspace::V0_SRGB; + break; + case ui::Dataspace::SRGB_LINEAR: + updatedDataspace = ui::Dataspace::V0_SRGB_LINEAR; + break; + case ui::Dataspace::JFIF: + updatedDataspace = ui::Dataspace::V0_JFIF; + break; + case ui::Dataspace::BT601_625: + updatedDataspace = ui::Dataspace::V0_BT601_625; + break; + case ui::Dataspace::BT601_525: + updatedDataspace = ui::Dataspace::V0_BT601_525; + break; + case ui::Dataspace::BT709: + updatedDataspace = ui::Dataspace::V0_BT709; + break; + default: + break; + } + + return updatedDataspace; +} + } // namespace android #if defined(__gl_h_) diff --git a/services/surfaceflinger/BufferLayer.h b/services/surfaceflinger/BufferLayer.h index ee44cbe836..e8838e812c 100644 --- a/services/surfaceflinger/BufferLayer.h +++ b/services/surfaceflinger/BufferLayer.h @@ -106,6 +106,14 @@ public: // Should only be called on the main thread. void latchAndReleaseBuffer() override; + bool getTransformToDisplayInverse() const override; + + Rect getBufferCrop() const override; + + uint32_t getBufferTransform() const override; + + ui::Dataspace getDataSpace() const override; + // ----------------------------------------------------------------------- // ----------------------------------------------------------------------- @@ -115,18 +123,7 @@ private: virtual bool fenceHasSignaled() const = 0; virtual bool framePresentTimeIsCurrent(nsecs_t expectedPresentTime) const = 0; - virtual nsecs_t getDesiredPresentTime() = 0; - virtual std::shared_ptr getCurrentFenceTime() const = 0; - - virtual void getDrawingTransformMatrix(float *matrix) = 0; - virtual uint32_t getDrawingTransform() const = 0; - virtual ui::Dataspace getDrawingDataSpace() const = 0; - virtual Rect getDrawingCrop() const = 0; - virtual uint32_t getDrawingScalingMode() const = 0; - virtual Region getDrawingSurfaceDamage() const = 0; - virtual const HdrMetadata& getDrawingHdrMetadata() const = 0; - virtual int getDrawingApi() const = 0; - virtual PixelFormat getPixelFormat() const = 0; + PixelFormat getPixelFormat() const; virtual uint64_t getFrameNumber(nsecs_t expectedPresentTime) const = 0; @@ -148,6 +145,25 @@ private: virtual status_t updateFrameNumber(nsecs_t latchTime) = 0; protected: + struct BufferInfo { + nsecs_t mDesiredPresentTime; + std::shared_ptr mFenceTime; + sp mFence; + float mTransformMatrix[16]; + uint32_t mTransform{0}; + ui::Dataspace mDataspace; + Rect mCrop; + uint32_t mScaleMode{NATIVE_WINDOW_SCALING_MODE_FREEZE}; + Region mSurfaceDamage; + HdrMetadata mHdrMetadata; + int mApi; + PixelFormat mPixelFormat; + bool mTransformToDisplayInverse{false}; + }; + + BufferInfo mBufferInfo; + virtual void gatherBufferInfo() = 0; + /* * compositionengine::LayerFE overrides */ @@ -171,16 +187,14 @@ protected: bool mRefreshPending{false}; + ui::Dataspace translateDataspace(ui::Dataspace dataspace); + private: // Returns true if this layer requires filtering bool needsFiltering(const sp& displayDevice) const override; uint64_t getHeadFrameNumber(nsecs_t expectedPresentTime) const; - uint32_t mCurrentScalingMode{NATIVE_WINDOW_SCALING_MODE_FREEZE}; - - bool mTransformToDisplayInverse{false}; - // main thread. bool mBufferLatched{false}; // TODO: Use mActiveBuffer? diff --git a/services/surfaceflinger/BufferQueueLayer.cpp b/services/surfaceflinger/BufferQueueLayer.cpp index 4da39e4d6f..e9e8e6e9dc 100644 --- a/services/surfaceflinger/BufferQueueLayer.cpp +++ b/services/surfaceflinger/BufferQueueLayer.cpp @@ -70,10 +70,6 @@ std::vector BufferQueueLayer::getOccupancyHistory(boo return history; } -bool BufferQueueLayer::getTransformToDisplayInverse() const { - return mConsumer->getTransformToDisplayInverse(); -} - void BufferQueueLayer::releasePendingBuffer(nsecs_t dequeueReadyTime) { if (!mConsumer->releasePendingBuffer()) { return; @@ -155,55 +151,12 @@ bool BufferQueueLayer::framePresentTimeIsCurrent(nsecs_t expectedPresentTime) co return mQueueItems[0].mTimestamp <= expectedPresentTime; } -nsecs_t BufferQueueLayer::getDesiredPresentTime() { - return mConsumer->getTimestamp(); -} - -std::shared_ptr BufferQueueLayer::getCurrentFenceTime() const { - return mConsumer->getCurrentFenceTime(); -} - -void BufferQueueLayer::getDrawingTransformMatrix(float *matrix) { - return mConsumer->getTransformMatrix(matrix); -} - // NOTE: SurfaceFlinger's definitions of "Current" and "Drawing" do not neatly map to BufferQueue's // These functions get the fields for the frame that is currently in SurfaceFlinger's Drawing state // so the functions start with "getDrawing". The data is retrieved from the BufferQueueConsumer's // current buffer so the consumer functions start with "getCurrent". // // This results in the rather confusing functions below. -uint32_t BufferQueueLayer::getDrawingTransform() const { - return mConsumer->getCurrentTransform(); -} - -ui::Dataspace BufferQueueLayer::getDrawingDataSpace() const { - return mConsumer->getCurrentDataSpace(); -} - -Rect BufferQueueLayer::getDrawingCrop() const { - return mConsumer->getCurrentCrop(); -} - -uint32_t BufferQueueLayer::getDrawingScalingMode() const { - return mConsumer->getCurrentScalingMode(); -} - -Region BufferQueueLayer::getDrawingSurfaceDamage() const { - return mConsumer->getSurfaceDamage(); -} - -const HdrMetadata& BufferQueueLayer::getDrawingHdrMetadata() const { - return mConsumer->getCurrentHdrMetadata(); -} - -int BufferQueueLayer::getDrawingApi() const { - return mConsumer->getCurrentApi(); -} - -PixelFormat BufferQueueLayer::getPixelFormat() const { - return mFormat; -} uint64_t BufferQueueLayer::getFrameNumber(nsecs_t expectedPresentTime) const { Mutex::Autolock lock(mQueueItemLock); @@ -422,7 +375,7 @@ void BufferQueueLayer::latchPerFrameState( compositionState.buffer = mActiveBuffer; compositionState.bufferSlot = (mActiveBufferSlot == BufferQueue::INVALID_BUFFER_SLOT) ? 0 : mActiveBufferSlot; - compositionState.acquireFence = mConsumer->getCurrentFence(); + compositionState.acquireFence = mBufferInfo.mFence; } // ----------------------------------------------------------------------- @@ -573,4 +526,20 @@ uint32_t BufferQueueLayer::getProducerStickyTransform() const { return static_cast(producerStickyTransform); } +void BufferQueueLayer::gatherBufferInfo() { + mBufferInfo.mDesiredPresentTime = mConsumer->getTimestamp(); + mBufferInfo.mFenceTime = mConsumer->getCurrentFenceTime(); + mBufferInfo.mFence = mConsumer->getCurrentFence(); + mConsumer->getTransformMatrix(mBufferInfo.mTransformMatrix); + mBufferInfo.mTransform = mConsumer->getCurrentTransform(); + mBufferInfo.mDataspace = translateDataspace(mConsumer->getCurrentDataSpace()); + mBufferInfo.mCrop = mConsumer->getCurrentCrop(); + mBufferInfo.mScaleMode = mConsumer->getCurrentScalingMode(); + mBufferInfo.mSurfaceDamage = mConsumer->getSurfaceDamage(); + mBufferInfo.mHdrMetadata = mConsumer->getCurrentHdrMetadata(); + mBufferInfo.mApi = mConsumer->getCurrentApi(); + mBufferInfo.mPixelFormat = mFormat; + mBufferInfo.mTransformToDisplayInverse = mConsumer->getTransformToDisplayInverse(); +} + } // namespace android diff --git a/services/surfaceflinger/BufferQueueLayer.h b/services/surfaceflinger/BufferQueueLayer.h index bf3f917196..6cbafb31ce 100644 --- a/services/surfaceflinger/BufferQueueLayer.h +++ b/services/surfaceflinger/BufferQueueLayer.h @@ -46,7 +46,6 @@ public: std::vector getOccupancyHistory(bool forceFlush) override; - bool getTransformToDisplayInverse() const override; // If a buffer was replaced this frame, release the former buffer void releasePendingBuffer(nsecs_t dequeueReadyTime) override; @@ -66,18 +65,6 @@ public: bool framePresentTimeIsCurrent(nsecs_t expectedPresentTime) const override; private: - nsecs_t getDesiredPresentTime() override; - std::shared_ptr getCurrentFenceTime() const override; - - void getDrawingTransformMatrix(float *matrix) override; - uint32_t getDrawingTransform() const override; - ui::Dataspace getDrawingDataSpace() const override; - Rect getDrawingCrop() const override; - uint32_t getDrawingScalingMode() const override; - Region getDrawingSurfaceDamage() const override; - const HdrMetadata& getDrawingHdrMetadata() const override; - int getDrawingApi() const override; - PixelFormat getPixelFormat() const override; uint64_t getFrameNumber(nsecs_t expectedPresentTime) const override; @@ -103,6 +90,8 @@ private: // Interface implementation for BufferLayerConsumer::ContentsChangedListener // ----------------------------------------------------------------------- protected: + void gatherBufferInfo() override; + void onFrameAvailable(const BufferItem& item) override; void onFrameReplaced(const BufferItem& item) override; void onSidebandStreamChanged() override; diff --git a/services/surfaceflinger/BufferStateLayer.cpp b/services/surfaceflinger/BufferStateLayer.cpp index e7d1b63b03..07a83b9d35 100644 --- a/services/surfaceflinger/BufferStateLayer.cpp +++ b/services/surfaceflinger/BufferStateLayer.cpp @@ -125,10 +125,6 @@ bool BufferStateLayer::willPresentCurrentTransaction() const { (mCurrentState.buffer != nullptr || mCurrentState.bgColorLayer != nullptr)); } -bool BufferStateLayer::getTransformToDisplayInverse() const { - return mCurrentState.transformToDisplayInverse; -} - void BufferStateLayer::pushPendingState() { if (!mCurrentState.modified) { return; @@ -400,75 +396,6 @@ bool BufferStateLayer::framePresentTimeIsCurrent(nsecs_t expectedPresentTime) co return mCurrentState.desiredPresentTime <= expectedPresentTime; } -nsecs_t BufferStateLayer::getDesiredPresentTime() { - return getDrawingState().desiredPresentTime; -} - -std::shared_ptr BufferStateLayer::getCurrentFenceTime() const { - return std::make_shared(getDrawingState().acquireFence); -} - -void BufferStateLayer::getDrawingTransformMatrix(float *matrix) { - std::copy(std::begin(mTransformMatrix), std::end(mTransformMatrix), matrix); -} - -uint32_t BufferStateLayer::getDrawingTransform() const { - return getDrawingState().transform; -} - -ui::Dataspace BufferStateLayer::getDrawingDataSpace() const { - return getDrawingState().dataspace; -} - -// Crop that applies to the buffer -Rect BufferStateLayer::getDrawingCrop() const { - const State& s(getDrawingState()); - - if (s.crop.isEmpty() && s.buffer) { - return s.buffer->getBounds(); - } else if (s.buffer) { - Rect crop = s.crop; - crop.left = std::max(crop.left, 0); - crop.top = std::max(crop.top, 0); - uint32_t bufferWidth = s.buffer->getWidth(); - uint32_t bufferHeight = s.buffer->getHeight(); - if (bufferHeight <= std::numeric_limits::max() && - bufferWidth <= std::numeric_limits::max()) { - crop.right = std::min(crop.right, static_cast(bufferWidth)); - crop.bottom = std::min(crop.bottom, static_cast(bufferHeight)); - } - if (!crop.isValid()) { - // Crop rect is out of bounds, return whole buffer - return s.buffer->getBounds(); - } - return crop; - } - return s.crop; -} - -uint32_t BufferStateLayer::getDrawingScalingMode() const { - return NATIVE_WINDOW_SCALING_MODE_SCALE_TO_WINDOW; -} - -Region BufferStateLayer::getDrawingSurfaceDamage() const { - return getDrawingState().surfaceDamageRegion; -} - -const HdrMetadata& BufferStateLayer::getDrawingHdrMetadata() const { - return getDrawingState().hdrMetadata; -} - -int BufferStateLayer::getDrawingApi() const { - return getDrawingState().api; -} - -PixelFormat BufferStateLayer::getPixelFormat() const { - if (!mActiveBuffer) { - return PIXEL_FORMAT_NONE; - } - return mActiveBuffer->format; -} - uint64_t BufferStateLayer::getFrameNumber(nsecs_t /*expectedPresentTime*/) const { return mFrameNumber; } @@ -506,8 +433,8 @@ bool BufferStateLayer::hasFrameUpdate() const { } void BufferStateLayer::setFilteringEnabled(bool enabled) { - GLConsumer::computeTransformMatrix(mTransformMatrix.data(), mActiveBuffer, mCurrentCrop, - mCurrentTransform, enabled); + GLConsumer::computeTransformMatrix(mTransformMatrix.data(), mActiveBuffer, mBufferInfo.mCrop, + mBufferInfo.mTransform, enabled); } status_t BufferStateLayer::bindTextureImage() { @@ -576,8 +503,8 @@ status_t BufferStateLayer::updateTexImage(bool& /*recomputeVisibleRegions*/, nse } const uint64_t bufferID = getCurrentBufferId(); - mFlinger->mTimeStats->setAcquireFence(layerID, mFrameNumber, getCurrentFenceTime()); - mFlinger->mFrameTracer->traceFence(layerID, bufferID, mFrameNumber, getCurrentFenceTime(), + mFlinger->mTimeStats->setAcquireFence(layerID, mFrameNumber, mBufferInfo.mFenceTime); + mFlinger->mFrameTracer->traceFence(layerID, bufferID, mFrameNumber, mBufferInfo.mFenceTime, FrameTracer::FrameEvent::ACQUIRE_FENCE); mFlinger->mTimeStats->setLatchTime(layerID, mFrameNumber, latchTime); mFlinger->mFrameTracer->traceTimestamp(layerID, bufferID, mFrameNumber, latchTime, @@ -622,7 +549,7 @@ void BufferStateLayer::latchPerFrameState( compositionState.buffer = s.buffer; compositionState.bufferSlot = mHwcSlotGenerator->getHwcCacheSlot(s.clientCacheId); - compositionState.acquireFence = s.acquireFence; + compositionState.acquireFence = mBufferInfo.mFence; mFrameNumber++; } @@ -707,4 +634,47 @@ void BufferStateLayer::HwcSlotGenerator::eraseBufferLocked(const client_cache_t& mFreeHwcCacheSlots.push(hwcCacheSlot); mCachedBuffers.erase(clientCacheId); } + +void BufferStateLayer::gatherBufferInfo() { + const State& s(getDrawingState()); + + mBufferInfo.mDesiredPresentTime = s.desiredPresentTime; + mBufferInfo.mFenceTime = std::make_shared(s.acquireFence); + mBufferInfo.mFence = s.acquireFence; + std::copy(std::begin(mTransformMatrix), std::end(mTransformMatrix), + mBufferInfo.mTransformMatrix); + mBufferInfo.mTransform = s.transform; + mBufferInfo.mDataspace = translateDataspace(s.dataspace); + mBufferInfo.mCrop = computeCrop(s); + mBufferInfo.mScaleMode = NATIVE_WINDOW_SCALING_MODE_SCALE_TO_WINDOW; + mBufferInfo.mSurfaceDamage = s.surfaceDamageRegion; + mBufferInfo.mHdrMetadata = s.hdrMetadata; + mBufferInfo.mApi = s.api; + mBufferInfo.mPixelFormat = !mActiveBuffer ? PIXEL_FORMAT_NONE : mActiveBuffer->format; + mBufferInfo.mTransformToDisplayInverse = s.transformToDisplayInverse; +} + +Rect BufferStateLayer::computeCrop(const State& s) { + if (s.crop.isEmpty() && s.buffer) { + return s.buffer->getBounds(); + } else if (s.buffer) { + Rect crop = s.crop; + crop.left = std::max(crop.left, 0); + crop.top = std::max(crop.top, 0); + uint32_t bufferWidth = s.buffer->getWidth(); + uint32_t bufferHeight = s.buffer->getHeight(); + if (bufferHeight <= std::numeric_limits::max() && + bufferWidth <= std::numeric_limits::max()) { + crop.right = std::min(crop.right, static_cast(bufferWidth)); + crop.bottom = std::min(crop.bottom, static_cast(bufferHeight)); + } + if (!crop.isValid()) { + // Crop rect is out of bounds, return whole buffer + return s.buffer->getBounds(); + } + return crop; + } + return s.crop; +} + } // namespace android diff --git a/services/surfaceflinger/BufferStateLayer.h b/services/surfaceflinger/BufferStateLayer.h index c060ca8e76..086fd0a6ba 100644 --- a/services/surfaceflinger/BufferStateLayer.h +++ b/services/surfaceflinger/BufferStateLayer.h @@ -48,8 +48,6 @@ public: bool shouldPresentNow(nsecs_t expectedPresentTime) const override; - bool getTransformToDisplayInverse() const override; - uint32_t doTransactionResize(uint32_t flags, Layer::State* /*stateToCommit*/) override { return flags; } @@ -106,19 +104,10 @@ public: bool fenceHasSignaled() const override; bool framePresentTimeIsCurrent(nsecs_t expectedPresentTime) const override; +protected: + void gatherBufferInfo() override; + private: - nsecs_t getDesiredPresentTime() override; - std::shared_ptr getCurrentFenceTime() const override; - - void getDrawingTransformMatrix(float *matrix) override; - uint32_t getDrawingTransform() const override; - ui::Dataspace getDrawingDataSpace() const override; - Rect getDrawingCrop() const override; - uint32_t getDrawingScalingMode() const override; - Region getDrawingSurfaceDamage() const override; - const HdrMetadata& getDrawingHdrMetadata() const override; - int getDrawingApi() const override; - PixelFormat getPixelFormat() const override; uint64_t getFrameNumber(nsecs_t expectedPresentTime) const override; @@ -140,6 +129,9 @@ private: void latchPerFrameState(compositionengine::LayerFECompositionState&) const override; + // Crop that applies to the buffer + Rect computeCrop(const State& s); + private: friend class SlotGenerationTest; void onFirstRef() override; diff --git a/services/surfaceflinger/ColorLayer.cpp b/services/surfaceflinger/ColorLayer.cpp index 2ad7591b86..49b18102c7 100644 --- a/services/surfaceflinger/ColorLayer.cpp +++ b/services/surfaceflinger/ColorLayer.cpp @@ -99,11 +99,6 @@ void ColorLayer::latchPerFrameState( compositionState.compositionType = Hwc2::IComposerClient::Composition::SOLID_COLOR; } -void ColorLayer::commitTransaction(const State& stateToCommit) { - Layer::commitTransaction(stateToCommit); - mCurrentDataSpace = mDrawingState.dataspace; -} - std::shared_ptr ColorLayer::getCompositionLayer() const { return mCompositionLayer; } @@ -112,6 +107,10 @@ bool ColorLayer::isOpaque(const Layer::State& s) const { return (s.flags & layer_state_t::eLayerOpaque) != 0; } +ui::Dataspace ColorLayer::getDataSpace() const { + return mDrawingState.dataspace; +} + // --------------------------------------------------------------------------- }; // namespace android diff --git a/services/surfaceflinger/ColorLayer.h b/services/surfaceflinger/ColorLayer.h index 57c54c7e2c..16921df356 100644 --- a/services/surfaceflinger/ColorLayer.h +++ b/services/surfaceflinger/ColorLayer.h @@ -37,7 +37,7 @@ public: bool setDataspace(ui::Dataspace dataspace) override; - void commitTransaction(const State& stateToCommit) override; + ui::Dataspace getDataSpace() const override; bool isOpaque(const Layer::State& s) const override; diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp index c916f74291..f1a5175424 100644 --- a/services/surfaceflinger/Layer.cpp +++ b/services/surfaceflinger/Layer.cpp @@ -78,7 +78,6 @@ Layer::Layer(const LayerCreationArgs& args) mName(args.name), mClientRef(args.client), mWindowType(args.metadata.getInt32(METADATA_WINDOW_TYPE, 0)) { - mCurrentCrop.makeInvalid(); uint32_t layerFlags = 0; if (args.flags & ISurfaceComposerClient::eHidden) layerFlags |= layer_state_t::eLayerHidden; @@ -259,23 +258,6 @@ sp Layer::getHandle() { // h/w composer set-up // --------------------------------------------------------------------------- -Rect Layer::getContentCrop() const { - // this is the crop rectangle that applies to the buffer - // itself (as opposed to the window) - Rect crop; - if (!mCurrentCrop.isEmpty()) { - // if the buffer crop is defined, we use that - crop = mCurrentCrop; - } else if (mActiveBuffer != nullptr) { - // otherwise we use the whole buffer - crop = mActiveBuffer->getBounds(); - } else { - // if we don't have a buffer yet, we use an empty/invalid crop - crop.makeInvalid(); - } - return crop; -} - static Rect reduce(const Rect& win, const Region& exclude) { if (CC_LIKELY(exclude.isEmpty())) { return win; @@ -335,7 +317,7 @@ ui::Transform Layer::getBufferScaleTransform() const { int bufferWidth = mActiveBuffer->getWidth(); int bufferHeight = mActiveBuffer->getHeight(); - if (mCurrentTransform & NATIVE_WINDOW_TRANSFORM_ROT_90) { + if (getBufferTransform() & NATIVE_WINDOW_TRANSFORM_ROT_90) { std::swap(bufferWidth, bufferHeight); } @@ -442,9 +424,9 @@ void Layer::latchGeometry(compositionengine::LayerFECompositionState& compositio compositionState.geomLayerTransform = getTransform(); compositionState.geomInverseLayerTransform = compositionState.geomLayerTransform.inverse(); compositionState.geomBufferSize = getBufferSize(drawingState); - compositionState.geomContentCrop = getContentCrop(); + compositionState.geomContentCrop = getBufferCrop(); compositionState.geomCrop = getCrop(drawingState); - compositionState.geomBufferTransform = mCurrentTransform; + compositionState.geomBufferTransform = getBufferTransform(); compositionState.geomBufferUsesDisplayInverseTransform = getTransformToDisplayInverse(); compositionState.geomActiveTransparentRegion = getActiveTransparentRegion(drawingState); compositionState.geomLayerBounds = mBounds; @@ -466,7 +448,7 @@ void Layer::latchPerFrameState(compositionengine::LayerFECompositionState& compo compositionState.geomVisibleRegion = visibleRegion; compositionState.isColorspaceAgnostic = isColorSpaceAgnostic(); - compositionState.dataspace = mCurrentDataSpace; + compositionState.dataspace = getDataSpace(); compositionState.colorTransform = getColorTransform(); compositionState.colorTransformIsIdentity = !hasColorTransform(); compositionState.surfaceDamage = surfaceDamageRegion; @@ -543,7 +525,7 @@ std::optional Layer::prepareClientComposition( layerSettings.geometry.roundedCornersCrop = roundedCornerState.cropRect; layerSettings.alpha = alpha; - layerSettings.sourceDataspace = mCurrentDataSpace; + layerSettings.sourceDataspace = getDataSpace(); return layerSettings; } @@ -726,7 +708,7 @@ uint32_t Layer::doTransactionResize(uint32_t flags, State* stateToCommit) { " requested={ wh={%4u,%4u} }}\n" " drawing={ active ={ wh={%4u,%4u} crop={%4d,%4d,%4d,%4d} (%4d,%4d) }\n" " requested={ wh={%4u,%4u} }}\n", - this, getName().string(), mCurrentTransform, getEffectiveScalingMode(), + this, getName().string(), getBufferTransform(), getEffectiveScalingMode(), stateToCommit->active_legacy.w, stateToCommit->active_legacy.h, stateToCommit->crop_legacy.left, stateToCommit->crop_legacy.top, stateToCommit->crop_legacy.right, stateToCommit->crop_legacy.bottom, @@ -1232,7 +1214,7 @@ LayerDebugInfo Layer::getLayerDebugInfo() const { info.mColor = ds.color; info.mFlags = ds.flags; info.mPixelFormat = getPixelFormat(); - info.mDataSpace = static_cast(mCurrentDataSpace); + info.mDataSpace = static_cast(getDataSpace()); info.mMatrix[0][0] = ds.active_legacy.transform[0][0]; info.mMatrix[0][1] = ds.active_legacy.transform[0][1]; info.mMatrix[1][0] = ds.active_legacy.transform[1][0]; @@ -1551,8 +1533,9 @@ bool Layer::hasColorTransform() const { bool Layer::isLegacyDataSpace() const { // return true when no higher bits are set - return !(mCurrentDataSpace & (ui::Dataspace::STANDARD_MASK | - ui::Dataspace::TRANSFER_MASK | ui::Dataspace::RANGE_MASK)); + return !(getDataSpace() & + (ui::Dataspace::STANDARD_MASK | ui::Dataspace::TRANSFER_MASK | + ui::Dataspace::RANGE_MASK)); } void Layer::setParent(const sp& layer) { @@ -1834,13 +1817,12 @@ void Layer::writeToProtoDrawingState(LayerProto* layerInfo, uint32_t traceFlags) if (buffer != nullptr) { LayerProtoHelper::writeToProto(buffer, [&]() { return layerInfo->mutable_active_buffer(); }); - LayerProtoHelper::writeToProto(ui::Transform(mCurrentTransform), + LayerProtoHelper::writeToProto(ui::Transform(getBufferTransform()), layerInfo->mutable_buffer_transform()); } layerInfo->set_invalidate(contentDirty); layerInfo->set_is_protected(isProtected()); - layerInfo->set_dataspace( - dataspaceDetails(static_cast(mCurrentDataSpace))); + layerInfo->set_dataspace(dataspaceDetails(static_cast(getDataSpace()))); layerInfo->set_queued_frames(getQueuedFrameCount()); layerInfo->set_refresh_pending(isBufferLatched()); layerInfo->set_curr_frame(mCurrentFrameNumber); diff --git a/services/surfaceflinger/Layer.h b/services/surfaceflinger/Layer.h index 23c1acd759..ea5b8447ad 100644 --- a/services/surfaceflinger/Layer.h +++ b/services/surfaceflinger/Layer.h @@ -330,7 +330,7 @@ public: virtual bool setBackgroundColor(const half3& color, float alpha, ui::Dataspace dataspace); virtual bool setColorSpaceAgnostic(const bool agnostic); - ui::Dataspace getDataSpace() const { return mCurrentDataSpace; } + virtual ui::Dataspace getDataSpace() const { return ui::Dataspace::UNKNOWN; } // Before color management is introduced, contents on Android have to be // desaturated in order to match what they appears like visually. @@ -587,7 +587,12 @@ public: * returns the rectangle that crops the content of the layer and scales it * to the layer's size. */ - Rect getContentCrop() const; + virtual Rect getBufferCrop() const { return Rect(); } + + /* + * Returns the transform applied to the buffer. + */ + virtual uint32_t getBufferTransform() const { return 0; } /* * Returns if a frame is ready @@ -846,9 +851,6 @@ protected: // composition, true otherwise. bool mIsActiveBufferUpdatedForGpu = true; - ui::Dataspace mCurrentDataSpace = ui::Dataspace::UNKNOWN; - Rect mCurrentCrop; - uint32_t mCurrentTransform{0}; // We encode unset as -1. int32_t mOverrideScalingMode{-1}; std::atomic mCurrentFrameNumber{0}; -- cgit v1.2.3-59-g8ed1b From d62d30645c41d703a241443de761ab9eaa0c99af Mon Sep 17 00:00:00 2001 From: chaviw Date: Wed, 4 Sep 2019 14:48:02 -0700 Subject: Moved info about activeBuffer into bufferInfo (2/2) This is in preparation for layer mirroring since mirrored buffer layers should just copy the bufferInfo instead of the entire BufferQueue or parts of BufferState Test: go/wm-smoke Change-Id: I48c34141151370d9905c312239883f8374b884b9 --- services/surfaceflinger/BufferLayer.cpp | 53 +++++++++++++++------------- services/surfaceflinger/BufferLayer.h | 8 +++-- services/surfaceflinger/BufferQueueLayer.cpp | 14 ++++---- services/surfaceflinger/BufferQueueLayer.h | 1 - services/surfaceflinger/BufferStateLayer.cpp | 19 +++++----- services/surfaceflinger/Layer.cpp | 16 ++++----- services/surfaceflinger/Layer.h | 7 ++-- 7 files changed, 62 insertions(+), 56 deletions(-) (limited to 'services/surfaceflinger/Layer.cpp') diff --git a/services/surfaceflinger/BufferLayer.cpp b/services/surfaceflinger/BufferLayer.cpp index bca15e6903..6a3d60f50c 100644 --- a/services/surfaceflinger/BufferLayer.cpp +++ b/services/surfaceflinger/BufferLayer.cpp @@ -92,7 +92,7 @@ void BufferLayer::useEmptyDamage() { bool BufferLayer::isOpaque(const Layer::State& s) const { // if we don't have a buffer or sidebandStream yet, we're translucent regardless of the // layer's opaque flag. - if ((mSidebandStream == nullptr) && (mActiveBuffer == nullptr)) { + if ((mSidebandStream == nullptr) && (mBufferInfo.mBuffer == nullptr)) { return false; } @@ -103,7 +103,7 @@ bool BufferLayer::isOpaque(const Layer::State& s) const { bool BufferLayer::isVisible() const { bool visible = !(isHiddenByPolicy()) && getAlpha() > 0.0f && - (mActiveBuffer != nullptr || mSidebandStream != nullptr); + (mBufferInfo.mBuffer != nullptr || mSidebandStream != nullptr); mFlinger->mScheduler->setLayerVisibility(mSchedulerLayerHandle, visible); return visible; @@ -144,7 +144,7 @@ std::optional BufferLayer::prepareClientComposition return result; } - if (CC_UNLIKELY(mActiveBuffer == 0)) { + if (CC_UNLIKELY(mBufferInfo.mBuffer == 0)) { // the texture has not been created yet, this Layer has // in fact never been drawn into. This happens frequently with // SurfaceView because the WindowManager can't know when the client @@ -175,9 +175,9 @@ std::optional BufferLayer::prepareClientComposition const State& s(getDrawingState()); auto& layer = *result; if (!blackOutLayer) { - layer.source.buffer.buffer = mActiveBuffer; + layer.source.buffer.buffer = mBufferInfo.mBuffer; layer.source.buffer.isOpaque = isOpaque(s); - layer.source.buffer.fence = mActiveBufferFence; + layer.source.buffer.fence = mBufferInfo.mFence; layer.source.buffer.textureName = mTextureName; layer.source.buffer.usePremultipliedAlpha = getPremultipledAlpha(); layer.source.buffer.isY410BT2020 = isHdrY410(); @@ -256,7 +256,7 @@ bool BufferLayer::isHdrY410() const { // pixel format is HDR Y410 masquerading as RGBA_1010102 return (mBufferInfo.mDataspace == ui::Dataspace::BT2020_ITU_PQ && mBufferInfo.mApi == NATIVE_WINDOW_API_MEDIA && - mActiveBuffer->getPixelFormat() == HAL_PIXEL_FORMAT_RGBA_1010102); + mBufferInfo.mBuffer->getPixelFormat() == HAL_PIXEL_FORMAT_RGBA_1010102); } void BufferLayer::latchPerFrameState( @@ -276,7 +276,7 @@ void BufferLayer::latchPerFrameState( } bool BufferLayer::onPreComposition(nsecs_t refreshStartTime) { - if (mBufferLatched) { + if (mBufferInfo.mBuffer != nullptr) { Mutex::Autolock lock(mFrameEventHistoryMutex); mFrameEventHistory.addPreComposition(mCurrentFrameNumber, refreshStartTime); } @@ -370,7 +370,8 @@ bool BufferLayer::latchBuffer(bool& recomputeVisibleRegions, nsecs_t latchTime, // Capture the old state of the layer for comparisons later const State& s(getDrawingState()); const bool oldOpacity = isOpaque(s); - sp oldBuffer = mActiveBuffer; + + BufferInfo oldBufferInfo = mBufferInfo; if (!allTransactionsSignaled(expectedPresentTime)) { mFlinger->setTransactionFlags(eTraversalNeeded); @@ -387,19 +388,16 @@ bool BufferLayer::latchBuffer(bool& recomputeVisibleRegions, nsecs_t latchTime, return false; } - mBufferLatched = true; - err = updateFrameNumber(latchTime); if (err != NO_ERROR) { return false; } - BufferInfo oldBufferInfo = mBufferInfo; gatherBufferInfo(); mRefreshPending = true; mFrameLatencyNeeded = true; - if (oldBuffer == nullptr) { + if (oldBufferInfo.mBuffer == nullptr) { // the first time we receive a buffer, we need to trigger a // geometry invalidation. recomputeVisibleRegions = true; @@ -412,10 +410,11 @@ bool BufferLayer::latchBuffer(bool& recomputeVisibleRegions, nsecs_t latchTime, recomputeVisibleRegions = true; } - if (oldBuffer != nullptr) { - uint32_t bufWidth = mActiveBuffer->getWidth(); - uint32_t bufHeight = mActiveBuffer->getHeight(); - if (bufWidth != uint32_t(oldBuffer->width) || bufHeight != uint32_t(oldBuffer->height)) { + if (oldBufferInfo.mBuffer != nullptr) { + uint32_t bufWidth = mBufferInfo.mBuffer->getWidth(); + uint32_t bufHeight = mBufferInfo.mBuffer->getHeight(); + if (bufWidth != uint32_t(oldBufferInfo.mBuffer->width) || + bufHeight != uint32_t(oldBufferInfo.mBuffer->height)) { recomputeVisibleRegions = true; } } @@ -484,7 +483,7 @@ uint32_t BufferLayer::getEffectiveScalingMode() const { } bool BufferLayer::isProtected() const { - const sp& buffer(mActiveBuffer); + const sp& buffer(mBufferInfo.mBuffer); return (buffer != 0) && (buffer->getUsage() & GRALLOC_USAGE_PROTECTED); } @@ -588,12 +587,12 @@ Rect BufferLayer::getBufferSize(const State& s) const { return Rect(getActiveWidth(s), getActiveHeight(s)); } - if (mActiveBuffer == nullptr) { + if (mBufferInfo.mBuffer == nullptr) { return Rect::INVALID_RECT; } - uint32_t bufWidth = mActiveBuffer->getWidth(); - uint32_t bufHeight = mActiveBuffer->getHeight(); + uint32_t bufWidth = mBufferInfo.mBuffer->getWidth(); + uint32_t bufHeight = mBufferInfo.mBuffer->getHeight(); // Undo any transformations on the buffer and return the result. if (mBufferInfo.mTransform & ui::Transform::ROT_90) { @@ -624,12 +623,12 @@ FloatRect BufferLayer::computeSourceBounds(const FloatRect& parentBounds) const return FloatRect(0, 0, getActiveWidth(s), getActiveHeight(s)); } - if (mActiveBuffer == nullptr) { + if (mBufferInfo.mBuffer == nullptr) { return parentBounds; } - uint32_t bufWidth = mActiveBuffer->getWidth(); - uint32_t bufHeight = mActiveBuffer->getHeight(); + uint32_t bufWidth = mBufferInfo.mBuffer->getWidth(); + uint32_t bufHeight = mBufferInfo.mBuffer->getHeight(); // Undo any transformations on the buffer and return the result. if (mBufferInfo.mTransform & ui::Transform::ROT_90) { @@ -669,9 +668,9 @@ Rect BufferLayer::getBufferCrop() const { if (!mBufferInfo.mCrop.isEmpty()) { // if the buffer crop is defined, we use that return mBufferInfo.mCrop; - } else if (mActiveBuffer != nullptr) { + } else if (mBufferInfo.mBuffer != nullptr) { // otherwise we use the whole buffer - return mActiveBuffer->getBounds(); + return mBufferInfo.mBuffer->getBounds(); } else { // if we don't have a buffer yet, we use an empty/invalid crop return Rect(); @@ -715,6 +714,10 @@ ui::Dataspace BufferLayer::translateDataspace(ui::Dataspace dataspace) { return updatedDataspace; } +sp BufferLayer::getBuffer() const { + return mBufferInfo.mBuffer; +} + } // namespace android #if defined(__gl_h_) diff --git a/services/surfaceflinger/BufferLayer.h b/services/surfaceflinger/BufferLayer.h index e8838e812c..a685ea2305 100644 --- a/services/surfaceflinger/BufferLayer.h +++ b/services/surfaceflinger/BufferLayer.h @@ -114,6 +114,8 @@ public: ui::Dataspace getDataSpace() const override; + sp getBuffer() const override; + // ----------------------------------------------------------------------- // ----------------------------------------------------------------------- @@ -159,6 +161,9 @@ protected: int mApi; PixelFormat mPixelFormat; bool mTransformToDisplayInverse{false}; + + sp mBuffer; + int mBufferSlot{BufferQueue::INVALID_BUFFER_SLOT}; }; BufferInfo mBufferInfo; @@ -195,9 +200,6 @@ private: uint64_t getHeadFrameNumber(nsecs_t expectedPresentTime) const; - // main thread. - bool mBufferLatched{false}; // TODO: Use mActiveBuffer? - // BufferStateLayers can return Rect::INVALID_RECT if the layer does not have a display frame // and its parent layer is not bounded Rect getBufferSize(const State& s) const override; diff --git a/services/surfaceflinger/BufferQueueLayer.cpp b/services/surfaceflinger/BufferQueueLayer.cpp index e9e8e6e9dc..a4f7bc23a4 100644 --- a/services/surfaceflinger/BufferQueueLayer.cpp +++ b/services/surfaceflinger/BufferQueueLayer.cpp @@ -343,11 +343,12 @@ status_t BufferQueueLayer::updateTexImage(bool& recomputeVisibleRegions, nsecs_t status_t BufferQueueLayer::updateActiveBuffer() { // update the active buffer mPreviousBufferId = getCurrentBufferId(); - mActiveBuffer = mConsumer->getCurrentBuffer(&mActiveBufferSlot, &mActiveBufferFence); + mBufferInfo.mBuffer = + mConsumer->getCurrentBuffer(&mBufferInfo.mBufferSlot, &mBufferInfo.mFence); auto& layerCompositionState = getCompositionLayer()->editState().frontEnd; - layerCompositionState.buffer = mActiveBuffer; + layerCompositionState.buffer = mBufferInfo.mBuffer; - if (mActiveBuffer == nullptr) { + if (mBufferInfo.mBuffer == nullptr) { // this can only happen if the very first buffer was rejected. return BAD_VALUE; } @@ -372,9 +373,10 @@ void BufferQueueLayer::latchPerFrameState( return; } - compositionState.buffer = mActiveBuffer; - compositionState.bufferSlot = - (mActiveBufferSlot == BufferQueue::INVALID_BUFFER_SLOT) ? 0 : mActiveBufferSlot; + compositionState.buffer = mBufferInfo.mBuffer; + compositionState.bufferSlot = (mBufferInfo.mBufferSlot == BufferQueue::INVALID_BUFFER_SLOT) + ? 0 + : mBufferInfo.mBufferSlot; compositionState.acquireFence = mBufferInfo.mFence; } diff --git a/services/surfaceflinger/BufferQueueLayer.h b/services/surfaceflinger/BufferQueueLayer.h index 6cbafb31ce..43eb3eaab8 100644 --- a/services/surfaceflinger/BufferQueueLayer.h +++ b/services/surfaceflinger/BufferQueueLayer.h @@ -127,7 +127,6 @@ private: std::atomic mLastFrameNumberReceived{0}; bool mAutoRefresh{false}; - int mActiveBufferSlot{BufferQueue::INVALID_BUFFER_SLOT}; // thread-safe std::atomic mQueuedFrames{0}; diff --git a/services/surfaceflinger/BufferStateLayer.cpp b/services/surfaceflinger/BufferStateLayer.cpp index 07a83b9d35..afbe22854f 100644 --- a/services/surfaceflinger/BufferStateLayer.cpp +++ b/services/surfaceflinger/BufferStateLayer.cpp @@ -53,12 +53,12 @@ BufferStateLayer::BufferStateLayer(const LayerCreationArgs& args) } BufferStateLayer::~BufferStateLayer() { - if (mActiveBuffer != nullptr) { - // Ensure that mActiveBuffer is uncached from RenderEngine here, as + if (mBufferInfo.mBuffer != nullptr) { + // Ensure that mBuffer is uncached from RenderEngine here, as // RenderEngine may have been using the buffer as an external texture // after the client uncached the buffer. auto& engine(mFlinger->getRenderEngine()); - engine.unbindExternalTextureBuffer(mActiveBuffer->getId()); + engine.unbindExternalTextureBuffer(mBufferInfo.mBuffer->getId()); } } @@ -433,8 +433,8 @@ bool BufferStateLayer::hasFrameUpdate() const { } void BufferStateLayer::setFilteringEnabled(bool enabled) { - GLConsumer::computeTransformMatrix(mTransformMatrix.data(), mActiveBuffer, mBufferInfo.mCrop, - mBufferInfo.mTransform, enabled); + GLConsumer::computeTransformMatrix(mTransformMatrix.data(), mBufferInfo.mBuffer, + mBufferInfo.mCrop, mBufferInfo.mTransform, enabled); } status_t BufferStateLayer::bindTextureImage() { @@ -523,10 +523,10 @@ status_t BufferStateLayer::updateActiveBuffer() { } mPreviousBufferId = getCurrentBufferId(); - mActiveBuffer = s.buffer; - mActiveBufferFence = s.acquireFence; + mBufferInfo.mBuffer = s.buffer; + mBufferInfo.mFence = s.acquireFence; auto& layerCompositionState = getCompositionLayer()->editState().frontEnd; - layerCompositionState.buffer = mActiveBuffer; + layerCompositionState.buffer = mBufferInfo.mBuffer; return NO_ERROR; } @@ -650,7 +650,8 @@ void BufferStateLayer::gatherBufferInfo() { mBufferInfo.mSurfaceDamage = s.surfaceDamageRegion; mBufferInfo.mHdrMetadata = s.hdrMetadata; mBufferInfo.mApi = s.api; - mBufferInfo.mPixelFormat = !mActiveBuffer ? PIXEL_FORMAT_NONE : mActiveBuffer->format; + mBufferInfo.mPixelFormat = + !mBufferInfo.mBuffer ? PIXEL_FORMAT_NONE : mBufferInfo.mBuffer->format; mBufferInfo.mTransformToDisplayInverse = s.transformToDisplayInverse; } diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp index f1a5175424..d0b9187d56 100644 --- a/services/surfaceflinger/Layer.cpp +++ b/services/surfaceflinger/Layer.cpp @@ -302,7 +302,7 @@ ui::Transform Layer::getBufferScaleTransform() const { // If the layer is not using NATIVE_WINDOW_SCALING_MODE_FREEZE (e.g. // it isFixedSize) then there may be additional scaling not accounted // for in the layer transform. - if (!isFixedSize() || !mActiveBuffer) { + if (!isFixedSize() || getBuffer() == nullptr) { return {}; } @@ -314,8 +314,8 @@ ui::Transform Layer::getBufferScaleTransform() const { return {}; } - int bufferWidth = mActiveBuffer->getWidth(); - int bufferHeight = mActiveBuffer->getHeight(); + int bufferWidth = getBuffer()->getWidth(); + int bufferHeight = getBuffer()->getHeight(); if (getBufferTransform() & NATIVE_WINDOW_TRANSFORM_ROT_90) { std::swap(bufferWidth, bufferHeight); @@ -332,7 +332,7 @@ ui::Transform Layer::getBufferScaleTransform() const { ui::Transform Layer::getTransformWithScale(const ui::Transform& bufferScaleTransform) const { // We need to mirror this scaling to child surfaces or we will break the contract where WM can // treat child surfaces as pixels in the parent surface. - if (!isFixedSize() || !mActiveBuffer) { + if (!isFixedSize() || getBuffer() == nullptr) { return mEffectiveTransform; } return mEffectiveTransform * bufferScaleTransform; @@ -341,7 +341,7 @@ ui::Transform Layer::getTransformWithScale(const ui::Transform& bufferScaleTrans FloatRect Layer::getBoundsPreScaling(const ui::Transform& bufferScaleTransform) const { // We need the pre scaled layer bounds when computing child bounds to make sure the child is // cropped to its parent layer after any buffer transform scaling is applied. - if (!isFixedSize() || !mActiveBuffer) { + if (!isFixedSize() || getBuffer() == nullptr) { return mBounds; } return bufferScaleTransform.inverse().transform(mBounds); @@ -740,7 +740,7 @@ uint32_t Layer::doTransactionResize(uint32_t flags, State* stateToCommit) { const bool resizePending = ((stateToCommit->requested_legacy.w != stateToCommit->active_legacy.w) || (stateToCommit->requested_legacy.h != stateToCommit->active_legacy.h)) && - (mActiveBuffer != nullptr); + (getBuffer() != nullptr); if (!isFixedSize()) { if (resizePending && mSidebandStream == nullptr) { flags |= eDontUpdateGeometryState; @@ -1220,7 +1220,7 @@ LayerDebugInfo Layer::getLayerDebugInfo() const { info.mMatrix[1][0] = ds.active_legacy.transform[1][0]; info.mMatrix[1][1] = ds.active_legacy.transform[1][1]; { - sp buffer = mActiveBuffer; + sp buffer = getBuffer(); if (buffer != 0) { info.mActiveBufferWidth = buffer->getWidth(); info.mActiveBufferHeight = buffer->getHeight(); @@ -1813,7 +1813,7 @@ void Layer::writeToProtoDrawingState(LayerProto* layerInfo, uint32_t traceFlags) } } - auto buffer = mActiveBuffer; + auto buffer = getBuffer(); if (buffer != nullptr) { LayerProtoHelper::writeToProto(buffer, [&]() { return layerInfo->mutable_active_buffer(); }); diff --git a/services/surfaceflinger/Layer.h b/services/surfaceflinger/Layer.h index ea5b8447ad..d6cc27a801 100644 --- a/services/surfaceflinger/Layer.h +++ b/services/surfaceflinger/Layer.h @@ -382,7 +382,7 @@ public: // creates its tracks by buffer id and has no way of associating a buffer back to the process // that created it, the current implementation is only sufficient for cases where a buffer is // only used within a single layer. - uint64_t getCurrentBufferId() const { return mActiveBuffer ? mActiveBuffer->getId() : 0; } + uint64_t getCurrentBufferId() const { return getBuffer() ? getBuffer()->getId() : 0; } // ----------------------------------------------------------------------- // Virtuals @@ -594,6 +594,8 @@ public: */ virtual uint32_t getBufferTransform() const { return 0; } + virtual sp getBuffer() const { return nullptr; } + /* * Returns if a frame is ready */ @@ -844,9 +846,6 @@ protected: // main thread sp mSidebandStream; - // Active buffer fields - sp mActiveBuffer; - sp mActiveBufferFence; // False if the buffer and its contents have been previously used for GPU // composition, true otherwise. bool mIsActiveBufferUpdatedForGpu = true; -- cgit v1.2.3-59-g8ed1b From 82353e993cd4889a231a0b2d243dccc98e323395 Mon Sep 17 00:00:00 2001 From: Vishnu Nair Date: Thu, 12 Sep 2019 12:38:47 -0700 Subject: Changed BufferLayer's canReceiveInput to check if its hidden by policy WM does not consider window size or alpha value when setting it as the focused window. However, SF will check if the window has a buffer and that its alpha is not 0. Because of this difference, Input Dispatcher will not be able to send input to the window while WM thinks the window is focused. This will cause apps to stop responding. While we define what the intended behavior should be, this fix reverts to previous behavior in P. Bug: 139494112 Test: adb shell monkey 10000; make sure monkey does not get stuck Test: check test app from can receive input b/140478820 Change-Id: I4160b49161dd1780713980707a5c911034f414b5 --- libs/gui/tests/EndToEndNativeInputTest.cpp | 4 ++++ services/surfaceflinger/ContainerLayer.cpp | 4 ---- services/surfaceflinger/ContainerLayer.h | 2 -- services/surfaceflinger/Layer.cpp | 2 +- 4 files changed, 5 insertions(+), 7 deletions(-) (limited to 'services/surfaceflinger/Layer.cpp') diff --git a/libs/gui/tests/EndToEndNativeInputTest.cpp b/libs/gui/tests/EndToEndNativeInputTest.cpp index 386f731d23..2ab34da5ec 100644 --- a/libs/gui/tests/EndToEndNativeInputTest.cpp +++ b/libs/gui/tests/EndToEndNativeInputTest.cpp @@ -435,6 +435,9 @@ TEST_F(InputSurfacesTest, input_ignores_transparent_region) { surface->expectTap(1, 1); } +/** + * TODO(b/139494112) fix tests once we define expected behavior + * // Ensure we send the input to the right surface when the surface visibility changes due to the // first buffer being submitted. ref: b/120839715 TEST_F(InputSurfacesTest, input_respects_buffer_layer_buffer) { @@ -486,6 +489,7 @@ TEST_F(InputSurfacesTest, input_respects_color_layer_alpha) { injectTap(11, 11); bgSurface->expectTap(1, 1); } +*/ TEST_F(InputSurfacesTest, input_respects_container_layer_visiblity) { std::unique_ptr bgSurface = makeSurface(100, 100); diff --git a/services/surfaceflinger/ContainerLayer.cpp b/services/surfaceflinger/ContainerLayer.cpp index d40a38c811..4a1130365a 100644 --- a/services/surfaceflinger/ContainerLayer.cpp +++ b/services/surfaceflinger/ContainerLayer.cpp @@ -30,8 +30,4 @@ bool ContainerLayer::isVisible() const { return false; } -bool ContainerLayer::canReceiveInput() const { - return !isHiddenByPolicy(); -} - } // namespace android diff --git a/services/surfaceflinger/ContainerLayer.h b/services/surfaceflinger/ContainerLayer.h index f0fbb6104f..c3624f6d7d 100644 --- a/services/surfaceflinger/ContainerLayer.h +++ b/services/surfaceflinger/ContainerLayer.h @@ -31,8 +31,6 @@ public: const char* getType() const override { return "ContainerLayer"; } bool isVisible() const override; - bool canReceiveInput() const override; - bool isCreatedFromMainThread() const override { return true; } }; diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp index 79ee827f0d..d117c1bb70 100644 --- a/services/surfaceflinger/Layer.cpp +++ b/services/surfaceflinger/Layer.cpp @@ -2020,7 +2020,7 @@ std::shared_ptr Layer::getCompositionLayer() const { } bool Layer::canReceiveInput() const { - return isVisible(); + return !isHiddenByPolicy(); } compositionengine::OutputLayer* Layer::findOutputLayerForDisplay( -- cgit v1.2.3-59-g8ed1b From 9755fb755c062b406ff5a9310ef6b23b9f1ce5a2 Mon Sep 17 00:00:00 2001 From: Lloyd Pique Date: Tue, 26 Mar 2019 14:44:40 -0700 Subject: CE: Layers only have FE layer state Remove the concept of having a compositionengine::Layer having internal state since it was only used to internally store a copy of the LayerFECompositionState. Instead switch the Layer interface so only the FE state can be obtained. Any internal state will from now on be private. Doing this also allows the LayerFECompostionState to be easily extended by extended versions of CompositionEngine. Test: atest libsurfaceflinger_unittest libcompositionengine_test Test: atest CtsColorModeTestCases Test: atest CtsDisplayTestCases Test: atest CtsGraphicsTestCases Test: atest CtsUiRenderingTestCases Test: atest CtsViewTestCases Test: atest android.media.cts.EncodeVirtualDisplayWithCompositionTest Test: go/wm-smoke Bug: 121291683 Change-Id: I689e8714aca46320c87e0cb5ef18fdde93eb7499 --- services/surfaceflinger/BufferLayer.cpp | 2 - services/surfaceflinger/BufferQueueLayer.cpp | 12 +- services/surfaceflinger/BufferStateLayer.cpp | 12 +- services/surfaceflinger/ColorLayer.cpp | 4 - .../surfaceflinger/CompositionEngine/Android.bp | 2 +- .../include/compositionengine/Layer.h | 16 +-- .../compositionengine/LayerFECompositionState.h | 3 + .../include/compositionengine/impl/Layer.h | 9 +- .../compositionengine/impl/LayerCompositionState.h | 42 ------- .../include/compositionengine/mock/Layer.h | 6 +- .../CompositionEngine/src/CompositionEngine.cpp | 4 +- .../surfaceflinger/CompositionEngine/src/Layer.cpp | 12 +- .../src/LayerCompositionState.cpp | 91 -------------- .../src/LayerFECompositionState.cpp | 85 +++++++++++++ .../CompositionEngine/src/Output.cpp | 19 ++- .../CompositionEngine/src/OutputLayer.cpp | 16 +-- .../CompositionEngine/tests/OutputLayerTest.cpp | 132 ++++++++++----------- .../CompositionEngine/tests/OutputTest.cpp | 76 ++++++------ services/surfaceflinger/Layer.cpp | 1 - services/surfaceflinger/SurfaceFlinger.cpp | 3 - .../tests/unittests/TestableSurfaceFlinger.h | 4 +- 21 files changed, 243 insertions(+), 308 deletions(-) delete mode 100644 services/surfaceflinger/CompositionEngine/include/compositionengine/impl/LayerCompositionState.h delete mode 100644 services/surfaceflinger/CompositionEngine/src/LayerCompositionState.cpp create mode 100644 services/surfaceflinger/CompositionEngine/src/LayerFECompositionState.cpp (limited to 'services/surfaceflinger/Layer.cpp') diff --git a/services/surfaceflinger/BufferLayer.cpp b/services/surfaceflinger/BufferLayer.cpp index b060b047af..fba235d397 100644 --- a/services/surfaceflinger/BufferLayer.cpp +++ b/services/surfaceflinger/BufferLayer.cpp @@ -22,12 +22,10 @@ #include "BufferLayer.h" #include -#include #include #include #include #include -#include #include #include #include diff --git a/services/surfaceflinger/BufferQueueLayer.cpp b/services/surfaceflinger/BufferQueueLayer.cpp index f2e861d1ce..fcabedf63e 100644 --- a/services/surfaceflinger/BufferQueueLayer.cpp +++ b/services/surfaceflinger/BufferQueueLayer.cpp @@ -17,15 +17,13 @@ #undef LOG_TAG #define LOG_TAG "BufferQueueLayer" #define ATRACE_TAG ATRACE_TAG_GRAPHICS -#include +#include "BufferQueueLayer.h" + #include -#include -#include -#include +#include #include #include -#include "BufferQueueLayer.h" #include "LayerRejecter.h" #include "SurfaceInterceptor.h" @@ -197,7 +195,7 @@ bool BufferQueueLayer::latchSidebandStream(bool& recomputeVisibleRegions) { if (mSidebandStreamChanged.compare_exchange_strong(sidebandStreamChanged, false)) { // mSidebandStreamChanged was changed to false mSidebandStream = mConsumer->getSidebandStream(); - auto& layerCompositionState = getCompositionLayer()->editState().frontEnd; + auto& layerCompositionState = getCompositionLayer()->editFEState(); layerCompositionState.sidebandStream = mSidebandStream; if (layerCompositionState.sidebandStream != nullptr) { setTransactionFlags(eTransactionNeeded); @@ -335,7 +333,7 @@ status_t BufferQueueLayer::updateActiveBuffer() { mPreviousBufferId = getCurrentBufferId(); mBufferInfo.mBuffer = mConsumer->getCurrentBuffer(&mBufferInfo.mBufferSlot, &mBufferInfo.mFence); - auto& layerCompositionState = getCompositionLayer()->editState().frontEnd; + auto& layerCompositionState = getCompositionLayer()->editFEState(); layerCompositionState.buffer = mBufferInfo.mBuffer; if (mBufferInfo.mBuffer == nullptr) { diff --git a/services/surfaceflinger/BufferStateLayer.cpp b/services/surfaceflinger/BufferStateLayer.cpp index 509deaf996..ad05bc8671 100644 --- a/services/surfaceflinger/BufferStateLayer.cpp +++ b/services/surfaceflinger/BufferStateLayer.cpp @@ -19,18 +19,16 @@ #define LOG_TAG "BufferStateLayer" #define ATRACE_TAG ATRACE_TAG_GRAPHICS +#include "BufferStateLayer.h" + #include -#include #include -#include -#include -#include +#include #include #include #include -#include "BufferStateLayer.h" #include "ColorLayer.h" #include "FrameTracer/FrameTracer.h" #include "TimeStats/TimeStats.h" @@ -415,7 +413,7 @@ bool BufferStateLayer::latchSidebandStream(bool& recomputeVisibleRegions) { // mSidebandStreamChanged was true LOG_ALWAYS_FATAL_IF(!getCompositionLayer()); mSidebandStream = s.sidebandStream; - getCompositionLayer()->editState().frontEnd.sidebandStream = mSidebandStream; + getCompositionLayer()->editFEState().sidebandStream = mSidebandStream; if (mSidebandStream != nullptr) { setTransactionFlags(eTransactionNeeded); mFlinger->setTransactionFlags(eTraversalNeeded); @@ -520,7 +518,7 @@ status_t BufferStateLayer::updateActiveBuffer() { mPreviousBufferId = getCurrentBufferId(); mBufferInfo.mBuffer = s.buffer; mBufferInfo.mFence = s.acquireFence; - auto& layerCompositionState = getCompositionLayer()->editState().frontEnd; + auto& layerCompositionState = getCompositionLayer()->editFEState(); layerCompositionState.buffer = mBufferInfo.mBuffer; return NO_ERROR; diff --git a/services/surfaceflinger/ColorLayer.cpp b/services/surfaceflinger/ColorLayer.cpp index 49b18102c7..99805d9da2 100644 --- a/services/surfaceflinger/ColorLayer.cpp +++ b/services/surfaceflinger/ColorLayer.cpp @@ -25,13 +25,9 @@ #include #include -#include #include #include #include -#include -#include -#include #include #include #include diff --git a/services/surfaceflinger/CompositionEngine/Android.bp b/services/surfaceflinger/CompositionEngine/Android.bp index e49b65ff07..fcb94fde95 100644 --- a/services/surfaceflinger/CompositionEngine/Android.bp +++ b/services/surfaceflinger/CompositionEngine/Android.bp @@ -47,7 +47,7 @@ cc_library { "src/DumpHelpers.cpp", "src/HwcBufferCache.cpp", "src/Layer.cpp", - "src/LayerCompositionState.cpp", + "src/LayerFECompositionState.cpp", "src/Output.cpp", "src/OutputCompositionState.cpp", "src/OutputLayer.cpp", diff --git a/services/surfaceflinger/CompositionEngine/include/compositionengine/Layer.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/Layer.h index 451608b2ae..1259c524b2 100644 --- a/services/surfaceflinger/CompositionEngine/include/compositionengine/Layer.h +++ b/services/surfaceflinger/CompositionEngine/include/compositionengine/Layer.h @@ -26,9 +26,7 @@ namespace android::compositionengine { class Display; class LayerFE; -namespace impl { -struct LayerCompositionState; -} // namespace impl +struct LayerFECompositionState; /** * A layer contains the output-independent composition state for a front-end @@ -42,17 +40,13 @@ public: // front-end layer no longer exists. virtual sp getLayerFE() const = 0; - using CompositionState = impl::LayerCompositionState; - - // Gets the raw composition state data for the layer + // Gets the raw front-end composition state data for the layer // TODO(lpique): Make this protected once it is only internally called. - virtual const CompositionState& getState() const = 0; + virtual const LayerFECompositionState& getFEState() const = 0; - // Allows mutable access to the raw composition state data for the layer. - // This is meant to be used by the various functions that are part of the - // composition process. + // Allows mutable access to the raw front-end composition state // TODO(lpique): Make this protected once it is only internally called. - virtual CompositionState& editState() = 0; + virtual LayerFECompositionState& editFEState() = 0; // Debugging virtual void dump(std::string& result) const = 0; diff --git a/services/surfaceflinger/CompositionEngine/include/compositionengine/LayerFECompositionState.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/LayerFECompositionState.h index 530f49a600..2ba781d924 100644 --- a/services/surfaceflinger/CompositionEngine/include/compositionengine/LayerFECompositionState.h +++ b/services/surfaceflinger/CompositionEngine/include/compositionengine/LayerFECompositionState.h @@ -147,6 +147,9 @@ struct LayerFECompositionState { // The output-independent frame for the cursor Rect cursorFrame; + + // Debugging + void dump(std::string& out) const; }; } // namespace android::compositionengine diff --git a/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/Layer.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/Layer.h index 3e56b21b18..d441c9c1b6 100644 --- a/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/Layer.h +++ b/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/Layer.h @@ -19,7 +19,7 @@ #include #include -#include +#include #include #include @@ -41,8 +41,8 @@ public: sp getLayerFE() const override; - const LayerCompositionState& getState() const override; - LayerCompositionState& editState() override; + const LayerFECompositionState& getFEState() const override; + LayerFECompositionState& editFEState() override; void dump(std::string& result) const override; @@ -50,7 +50,8 @@ private: const compositionengine::CompositionEngine& mCompositionEngine; const wp mLayerFE; - LayerCompositionState mState; + // State obtained from calls to LayerFE::getCompositionState + LayerFECompositionState mFrontEndState; }; std::shared_ptr createLayer(const compositionengine::CompositionEngine&, diff --git a/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/LayerCompositionState.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/LayerCompositionState.h deleted file mode 100644 index 726c850780..0000000000 --- a/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/LayerCompositionState.h +++ /dev/null @@ -1,42 +0,0 @@ -/* - * Copyright 2019 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 -#include - -#include -#include -#include - -namespace android { - -namespace compositionengine::impl { - -struct LayerCompositionState { - /* - * State set by LayerFE::getCompositionState - */ - - LayerFECompositionState frontEnd; - - // Debugging - void dump(std::string& result) const; -}; - -} // namespace compositionengine::impl -} // namespace android diff --git a/services/surfaceflinger/CompositionEngine/include/compositionengine/mock/Layer.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/mock/Layer.h index cce3b97bbd..4f03cb46ae 100644 --- a/services/surfaceflinger/CompositionEngine/include/compositionengine/mock/Layer.h +++ b/services/surfaceflinger/CompositionEngine/include/compositionengine/mock/Layer.h @@ -18,7 +18,7 @@ #include #include -#include +#include #include namespace android::compositionengine::mock { @@ -30,8 +30,8 @@ public: MOCK_CONST_METHOD0(getLayerFE, sp()); - MOCK_CONST_METHOD0(getState, const CompositionState&()); - MOCK_METHOD0(editState, CompositionState&()); + MOCK_CONST_METHOD0(getFEState, const LayerFECompositionState&()); + MOCK_METHOD0(editFEState, LayerFECompositionState&()); MOCK_CONST_METHOD1(dump, void(std::string&)); }; diff --git a/services/surfaceflinger/CompositionEngine/src/CompositionEngine.cpp b/services/surfaceflinger/CompositionEngine/src/CompositionEngine.cpp index 713266ff85..8391458e99 100644 --- a/services/surfaceflinger/CompositionEngine/src/CompositionEngine.cpp +++ b/services/surfaceflinger/CompositionEngine/src/CompositionEngine.cpp @@ -103,8 +103,8 @@ void CompositionEngine::updateCursorAsync(CompositionRefreshArgs& args) { for (auto& layer : output->getOutputLayersOrderedByZ()) { if (layer->isHardwareCursor()) { // Latch the cursor composition state from each front-end layer. - layer->getLayerFE().latchCursorCompositionState( - layer->getLayer().editState().frontEnd); + layer->getLayerFE().latchCursorCompositionState(layer->getLayer().editFEState()); + layer->writeCursorPositionToHWC(); } } diff --git a/services/surfaceflinger/CompositionEngine/src/Layer.cpp b/services/surfaceflinger/CompositionEngine/src/Layer.cpp index 96e9731768..8a1cbe409b 100644 --- a/services/surfaceflinger/CompositionEngine/src/Layer.cpp +++ b/services/surfaceflinger/CompositionEngine/src/Layer.cpp @@ -43,19 +43,21 @@ sp Layer::getLayerFE() const { return mLayerFE.promote(); } -const LayerCompositionState& Layer::getState() const { - return mState; +const compositionengine::LayerFECompositionState& Layer::getFEState() const { + return mFrontEndState; } -LayerCompositionState& Layer::editState() { - return mState; +compositionengine::LayerFECompositionState& Layer::editFEState() { + return mFrontEndState; } void Layer::dump(std::string& out) const { auto layerFE = getLayerFE(); android::base::StringAppendF(&out, "* compositionengine::Layer %p (%s)\n", this, layerFE ? layerFE->getDebugName() : ""); - mState.dump(out); + + out.append(" frontend:\n"); + mFrontEndState.dump(out); } } // namespace impl diff --git a/services/surfaceflinger/CompositionEngine/src/LayerCompositionState.cpp b/services/surfaceflinger/CompositionEngine/src/LayerCompositionState.cpp deleted file mode 100644 index c5debf6e77..0000000000 --- a/services/surfaceflinger/CompositionEngine/src/LayerCompositionState.cpp +++ /dev/null @@ -1,91 +0,0 @@ -/* - * Copyright 2019 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 -#include -#include - -namespace android::compositionengine::impl { - -namespace { - -using android::compositionengine::impl::dumpVal; - -void dumpVal(std::string& out, const char* name, half4 value) { - using android::base::StringAppendF; - StringAppendF(&out, "%s=[%f %f %f] ", name, static_cast(value.r), - static_cast(value.g), static_cast(value.b)); -} - -void dumpFrontEnd(std::string& out, const LayerFECompositionState& state) { - out.append(" "); - dumpVal(out, "isSecure", state.isSecure); - dumpVal(out, "geomUsesSourceCrop", state.geomUsesSourceCrop); - dumpVal(out, "geomBufferUsesDisplayInverseTransform", - state.geomBufferUsesDisplayInverseTransform); - dumpVal(out, "geomLayerTransform", state.geomLayerTransform); - - out.append("\n "); - dumpVal(out, "geomBufferSize", state.geomBufferSize); - dumpVal(out, "geomContentCrop", state.geomContentCrop); - dumpVal(out, "geomCrop", state.geomCrop); - dumpVal(out, "geomBufferTransform", state.geomBufferTransform); - - out.append("\n "); - dumpVal(out, "transparentRegionHint", state.transparentRegionHint); - - out.append(" "); - dumpVal(out, "geomLayerBounds", state.geomLayerBounds); - - out.append("\n "); - dumpVal(out, "blend", toString(state.blendMode), state.blendMode); - dumpVal(out, "alpha", state.alpha); - - out.append("\n "); - dumpVal(out, "type", state.type); - dumpVal(out, "appId", state.appId); - - dumpVal(out, "composition type", toString(state.compositionType), state.compositionType); - - out.append("\n buffer: "); - dumpVal(out, "bufferSlot", state.bufferSlot); - dumpVal(out, "buffer", state.buffer.get()); - - out.append("\n "); - dumpVal(out, "sideband stream", state.sidebandStream.get()); - - out.append("\n "); - dumpVal(out, "color", state.color); - - out.append("\n "); - dumpVal(out, "isOpaque", state.isOpaque); - dumpVal(out, "hasProtectedContent", state.hasProtectedContent); - dumpVal(out, "isColorspaceAgnostic", state.isColorspaceAgnostic); - dumpVal(out, "dataspace", toString(state.dataspace), state.dataspace); - dumpVal(out, "hdr metadata types", state.hdrMetadata.validTypes); - dumpVal(out, "colorTransform", state.colorTransform); - - out.append("\n"); -} - -} // namespace - -void LayerCompositionState::dump(std::string& out) const { - out.append(" frontend:\n"); - dumpFrontEnd(out, frontEnd); -} - -} // namespace android::compositionengine::impl diff --git a/services/surfaceflinger/CompositionEngine/src/LayerFECompositionState.cpp b/services/surfaceflinger/CompositionEngine/src/LayerFECompositionState.cpp new file mode 100644 index 0000000000..1ca03dca5f --- /dev/null +++ b/services/surfaceflinger/CompositionEngine/src/LayerFECompositionState.cpp @@ -0,0 +1,85 @@ +/* + * Copyright 2019 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 +#include +#include + +namespace android::compositionengine { + +namespace { + +using android::compositionengine::impl::dumpVal; + +void dumpVal(std::string& out, const char* name, half4 value) { + using android::base::StringAppendF; + StringAppendF(&out, "%s=[%f %f %f] ", name, static_cast(value.r), + static_cast(value.g), static_cast(value.b)); +} + +} // namespace + +void LayerFECompositionState::dump(std::string& out) const { + out.append(" "); + dumpVal(out, "isSecure", isSecure); + dumpVal(out, "geomUsesSourceCrop", geomUsesSourceCrop); + dumpVal(out, "geomBufferUsesDisplayInverseTransform", geomBufferUsesDisplayInverseTransform); + dumpVal(out, "geomLayerTransform", geomLayerTransform); + + out.append("\n "); + dumpVal(out, "geomBufferSize", geomBufferSize); + dumpVal(out, "geomContentCrop", geomContentCrop); + dumpVal(out, "geomCrop", geomCrop); + dumpVal(out, "geomBufferTransform", geomBufferTransform); + + out.append("\n "); + dumpVal(out, "transparentRegionHint", transparentRegionHint); + + out.append(" "); + dumpVal(out, "geomLayerBounds", geomLayerBounds); + + out.append("\n "); + dumpVal(out, "blend", toString(blendMode), blendMode); + dumpVal(out, "alpha", alpha); + + out.append("\n "); + dumpVal(out, "type", type); + dumpVal(out, "appId", appId); + + dumpVal(out, "composition type", toString(compositionType), compositionType); + + out.append("\n buffer: "); + dumpVal(out, "slot", bufferSlot); + dumpVal(out, "buffer", buffer.get()); + + out.append("\n "); + dumpVal(out, "sideband stream", sidebandStream.get()); + + out.append("\n "); + dumpVal(out, "color", color); + + out.append("\n "); + dumpVal(out, "isOpaque", isOpaque); + dumpVal(out, "hasProtectedContent", hasProtectedContent); + dumpVal(out, "isColorspaceAgnostic", isColorspaceAgnostic); + dumpVal(out, "dataspace", toString(dataspace), dataspace); + dumpVal(out, "hdr metadata types", hdrMetadata.validTypes); + dumpVal(out, "colorTransform", colorTransform); + + out.append("\n"); +} + +} // namespace android::compositionengine diff --git a/services/surfaceflinger/CompositionEngine/src/Output.cpp b/services/surfaceflinger/CompositionEngine/src/Output.cpp index 83df628f25..02ebc1fc4f 100644 --- a/services/surfaceflinger/CompositionEngine/src/Output.cpp +++ b/services/surfaceflinger/CompositionEngine/src/Output.cpp @@ -22,8 +22,8 @@ #include #include #include +#include #include -#include #include #include #include @@ -249,7 +249,7 @@ bool Output::belongsInOutput(const compositionengine::Layer* layer) const { return false; } - const auto& layerFEState = layer->getState().frontEnd; + const auto& layerFEState = layer->getFEState(); return belongsInOutput(layerFEState.layerStackId, layerFEState.internalOnly); } @@ -400,12 +400,12 @@ std::unique_ptr Output::getOutputLayerIfVisible( // appear on multiple outputs. if (!coverage.latchedLayers.count(layerFE)) { coverage.latchedLayers.insert(layerFE); - layerFE->latchCompositionState(layer->editState().frontEnd, + layerFE->latchCompositionState(layer->editFEState(), compositionengine::LayerFE::StateSubset::BasicGeometry); } // Obtain a read-only reference to the front-end layer state - const auto& layerFEState = layer->getState().frontEnd; + const auto& layerFEState = layer->getFEState(); // Only consider the layers on the given layer stack if (!belongsInOutput(layer.get())) { @@ -572,7 +572,7 @@ void Output::setReleasedLayers(const compositionengine::CompositionRefreshArgs&) void Output::updateLayerStateFromFE(const CompositionRefreshArgs& args) const { for (auto& layer : mOutputLayersOrderedByZ) { - layer->getLayerFE().latchCompositionState(layer->getLayer().editState().frontEnd, + layer->getLayerFE().latchCompositionState(layer->getLayer().editFEState(), args.updatingGeometryThisFrame ? LayerFE::StateSubset::GeometryAndContent : LayerFE::StateSubset::Content); @@ -615,7 +615,7 @@ ui::Dataspace Output::getBestDataspace(ui::Dataspace* outHdrDataSpace, *outHdrDataSpace = ui::Dataspace::UNKNOWN; for (const auto& layer : mOutputLayersOrderedByZ) { - switch (layer->getLayer().getState().frontEnd.dataspace) { + switch (layer->getLayer().getFEState().dataspace) { case ui::Dataspace::V0_SCRGB: case ui::Dataspace::V0_SCRGB_LINEAR: case ui::Dataspace::BT2020: @@ -631,8 +631,7 @@ ui::Dataspace Output::getBestDataspace(ui::Dataspace* outHdrDataSpace, case ui::Dataspace::BT2020_ITU_PQ: bestDataSpace = ui::Dataspace::DISPLAY_P3; *outHdrDataSpace = ui::Dataspace::BT2020_PQ; - *outIsHdrClientComposition = - layer->getLayer().getState().frontEnd.forceClientComposition; + *outIsHdrClientComposition = layer->getLayer().getFEState().forceClientComposition; break; case ui::Dataspace::BT2020_HLG: case ui::Dataspace::BT2020_ITU_HLG: @@ -838,7 +837,7 @@ std::optional Output::composeSurfaces(const Region& debugRegion bool needsProtected = std::any_of(mOutputLayersOrderedByZ.begin(), mOutputLayersOrderedByZ.end(), [](auto& layer) { - return layer->getLayer().getState().frontEnd.hasProtectedContent; + return layer->getLayer().getFEState().hasProtectedContent; }); if (needsProtected != renderEngine.isProtected()) { renderEngine.useProtectedContext(needsProtected); @@ -892,7 +891,7 @@ std::vector Output::generateClientCompositionReques for (auto& layer : mOutputLayersOrderedByZ) { const auto& layerState = layer->getState(); - const auto& layerFEState = layer->getLayer().getState().frontEnd; + const auto& layerFEState = layer->getLayer().getFEState(); auto& layerFE = layer->getLayerFE(); const Region clip(viewportRegion.intersect(layerState.visibleRegion)); diff --git a/services/surfaceflinger/CompositionEngine/src/OutputLayer.cpp b/services/surfaceflinger/CompositionEngine/src/OutputLayer.cpp index 4eb256f94c..2e45953e5f 100644 --- a/services/surfaceflinger/CompositionEngine/src/OutputLayer.cpp +++ b/services/surfaceflinger/CompositionEngine/src/OutputLayer.cpp @@ -18,8 +18,8 @@ #include #include #include +#include #include -#include #include #include #include @@ -86,7 +86,7 @@ OutputLayerCompositionState& OutputLayer::editState() { } Rect OutputLayer::calculateInitialCrop() const { - const auto& layerState = mLayer->getState().frontEnd; + const auto& layerState = mLayer->getFEState(); // apply the projection's clipping to the window crop in // layerstack space, and convert-back to layer space. @@ -119,7 +119,7 @@ Rect OutputLayer::calculateInitialCrop() const { } FloatRect OutputLayer::calculateOutputSourceCrop() const { - const auto& layerState = mLayer->getState().frontEnd; + const auto& layerState = mLayer->getFEState(); const auto& outputState = mOutput.getState(); if (!layerState.geomUsesSourceCrop) { @@ -196,7 +196,7 @@ FloatRect OutputLayer::calculateOutputSourceCrop() const { } Rect OutputLayer::calculateOutputDisplayFrame() const { - const auto& layerState = mLayer->getState().frontEnd; + const auto& layerState = mLayer->getFEState(); const auto& outputState = mOutput.getState(); // apply the layer's transform, followed by the display's global transform @@ -243,7 +243,7 @@ Rect OutputLayer::calculateOutputDisplayFrame() const { } uint32_t OutputLayer::calculateOutputRelativeBufferTransform() const { - const auto& layerState = mLayer->getState().frontEnd; + const auto& layerState = mLayer->getFEState(); const auto& outputState = mOutput.getState(); /* @@ -283,7 +283,7 @@ uint32_t OutputLayer::calculateOutputRelativeBufferTransform() const { } // namespace impl void OutputLayer::updateCompositionState(bool includeGeometry) { - const auto& layerFEState = mLayer->getState().frontEnd; + const auto& layerFEState = mLayer->getFEState(); const auto& outputState = mOutput.getState(); const auto& profile = *mOutput.getDisplayColorProfile(); @@ -327,7 +327,7 @@ void OutputLayer::writeStateToHWC(bool includeGeometry) { return; } - const auto& outputIndependentState = mLayer->getState().frontEnd; + const auto& outputIndependentState = mLayer->getFEState(); auto requestedCompositionType = outputIndependentState.compositionType; if (includeGeometry) { @@ -544,7 +544,7 @@ void OutputLayer::writeCursorPositionToHWC() const { return; } - const auto& layerFEState = mLayer->getState().frontEnd; + const auto& layerFEState = mLayer->getFEState(); const auto& outputState = mOutput.getState(); Rect frame = layerFEState.cursorFrame; diff --git a/services/surfaceflinger/CompositionEngine/tests/OutputLayerTest.cpp b/services/surfaceflinger/CompositionEngine/tests/OutputLayerTest.cpp index b73c47ba17..88cedfa7ea 100644 --- a/services/surfaceflinger/CompositionEngine/tests/OutputLayerTest.cpp +++ b/services/surfaceflinger/CompositionEngine/tests/OutputLayerTest.cpp @@ -59,7 +59,7 @@ struct OutputLayerTest : public testing::Test { EXPECT_CALL(*mLayerFE, getDebugName()).WillRepeatedly(Return("Test LayerFE")); EXPECT_CALL(mOutput, getName()).WillRepeatedly(ReturnRef(kOutputName)); - EXPECT_CALL(*mLayer, getState()).WillRepeatedly(ReturnRef(mLayerState)); + EXPECT_CALL(*mLayer, getFEState()).WillRepeatedly(ReturnRef(mLayerFEState)); EXPECT_CALL(mOutput, getState()).WillRepeatedly(ReturnRef(mOutputState)); } @@ -70,7 +70,7 @@ struct OutputLayerTest : public testing::Test { new StrictMock()}; impl::OutputLayer mOutputLayer{mOutput, mLayer, mLayerFE}; - impl::LayerCompositionState mLayerState; + LayerFECompositionState mLayerFEState; impl::OutputCompositionState mOutputState; }; @@ -112,27 +112,26 @@ struct OutputLayerSourceCropTest : public OutputLayerTest { OutputLayerSourceCropTest() { // Set reasonable default values for a simple case. Each test will // set one specific value to something different. - mLayerState.frontEnd.geomUsesSourceCrop = true; - mLayerState.frontEnd.geomContentCrop = Rect{0, 0, 1920, 1080}; - mLayerState.frontEnd.transparentRegionHint = Region{}; - mLayerState.frontEnd.geomLayerBounds = FloatRect{0.f, 0.f, 1920.f, 1080.f}; - mLayerState.frontEnd.geomLayerTransform = ui::Transform{TR_IDENT}; - mLayerState.frontEnd.geomBufferSize = Rect{0, 0, 1920, 1080}; - mLayerState.frontEnd.geomBufferTransform = TR_IDENT; + mLayerFEState.geomUsesSourceCrop = true; + mLayerFEState.geomContentCrop = Rect{0, 0, 1920, 1080}; + mLayerFEState.transparentRegionHint = Region{}; + mLayerFEState.geomLayerBounds = FloatRect{0.f, 0.f, 1920.f, 1080.f}; + mLayerFEState.geomLayerTransform = ui::Transform{TR_IDENT}; + mLayerFEState.geomBufferSize = Rect{0, 0, 1920, 1080}; + mLayerFEState.geomBufferTransform = TR_IDENT; mOutputState.viewport = Rect{0, 0, 1920, 1080}; } FloatRect calculateOutputSourceCrop() { - mLayerState.frontEnd.geomInverseLayerTransform = - mLayerState.frontEnd.geomLayerTransform.inverse(); + mLayerFEState.geomInverseLayerTransform = mLayerFEState.geomLayerTransform.inverse(); return mOutputLayer.calculateOutputSourceCrop(); } }; TEST_F(OutputLayerSourceCropTest, computesEmptyIfSourceCropNotUsed) { - mLayerState.frontEnd.geomUsesSourceCrop = false; + mLayerFEState.geomUsesSourceCrop = false; const FloatRect expected{}; EXPECT_THAT(calculateOutputSourceCrop(), FloatRectEq(expected)); @@ -144,15 +143,15 @@ TEST_F(OutputLayerSourceCropTest, correctForSimpleDefaultCase) { } TEST_F(OutputLayerSourceCropTest, handlesBoundsOutsideViewport) { - mLayerState.frontEnd.geomLayerBounds = FloatRect{-2000.f, -2000.f, 2000.f, 2000.f}; + mLayerFEState.geomLayerBounds = FloatRect{-2000.f, -2000.f, 2000.f, 2000.f}; const FloatRect expected{0.f, 0.f, 1920.f, 1080.f}; EXPECT_THAT(calculateOutputSourceCrop(), FloatRectEq(expected)); } TEST_F(OutputLayerSourceCropTest, handlesBoundsOutsideViewportRotated) { - mLayerState.frontEnd.geomLayerBounds = FloatRect{-2000.f, -2000.f, 2000.f, 2000.f}; - mLayerState.frontEnd.geomLayerTransform.set(HAL_TRANSFORM_ROT_90, 1920, 1080); + mLayerFEState.geomLayerBounds = FloatRect{-2000.f, -2000.f, 2000.f, 2000.f}; + mLayerFEState.geomLayerTransform.set(HAL_TRANSFORM_ROT_90, 1920, 1080); const FloatRect expected{0.f, 0.f, 1080.f, 1080.f}; EXPECT_THAT(calculateOutputSourceCrop(), FloatRectEq(expected)); @@ -190,8 +189,8 @@ TEST_F(OutputLayerSourceCropTest, calculateOutputSourceCropWorksWithATransformed for (size_t i = 0; i < testData.size(); i++) { const auto& entry = testData[i]; - mLayerState.frontEnd.geomBufferUsesDisplayInverseTransform = entry.bufferInvDisplay; - mLayerState.frontEnd.geomBufferTransform = entry.buffer; + mLayerFEState.geomBufferUsesDisplayInverseTransform = entry.bufferInvDisplay; + mLayerFEState.geomBufferTransform = entry.buffer; mOutputState.orientation = entry.display; EXPECT_THAT(calculateOutputSourceCrop(), FloatRectEq(entry.expected)) << "entry " << i; @@ -199,7 +198,7 @@ TEST_F(OutputLayerSourceCropTest, calculateOutputSourceCropWorksWithATransformed } TEST_F(OutputLayerSourceCropTest, geomContentCropAffectsCrop) { - mLayerState.frontEnd.geomContentCrop = Rect{0, 0, 960, 540}; + mLayerFEState.geomContentCrop = Rect{0, 0, 960, 540}; const FloatRect expected{0.f, 0.f, 960.f, 540.f}; EXPECT_THAT(calculateOutputSourceCrop(), FloatRectEq(expected)); @@ -221,20 +220,19 @@ struct OutputLayerDisplayFrameTest : public OutputLayerTest { // Set reasonable default values for a simple case. Each test will // set one specific value to something different. - mLayerState.frontEnd.transparentRegionHint = Region{}; - mLayerState.frontEnd.geomLayerTransform = ui::Transform{TR_IDENT}; - mLayerState.frontEnd.geomBufferSize = Rect{0, 0, 1920, 1080}; - mLayerState.frontEnd.geomBufferUsesDisplayInverseTransform = false; - mLayerState.frontEnd.geomCrop = Rect{0, 0, 1920, 1080}; - mLayerState.frontEnd.geomLayerBounds = FloatRect{0.f, 0.f, 1920.f, 1080.f}; + mLayerFEState.transparentRegionHint = Region{}; + mLayerFEState.geomLayerTransform = ui::Transform{TR_IDENT}; + mLayerFEState.geomBufferSize = Rect{0, 0, 1920, 1080}; + mLayerFEState.geomBufferUsesDisplayInverseTransform = false; + mLayerFEState.geomCrop = Rect{0, 0, 1920, 1080}; + mLayerFEState.geomLayerBounds = FloatRect{0.f, 0.f, 1920.f, 1080.f}; mOutputState.viewport = Rect{0, 0, 1920, 1080}; mOutputState.transform = ui::Transform{TR_IDENT}; } Rect calculateOutputDisplayFrame() { - mLayerState.frontEnd.geomInverseLayerTransform = - mLayerState.frontEnd.geomLayerTransform.inverse(); + mLayerFEState.geomInverseLayerTransform = mLayerFEState.geomLayerTransform.inverse(); return mOutputLayer.calculateOutputDisplayFrame(); } @@ -246,32 +244,32 @@ TEST_F(OutputLayerDisplayFrameTest, correctForSimpleDefaultCase) { } TEST_F(OutputLayerDisplayFrameTest, fullActiveTransparentRegionReturnsEmptyFrame) { - mLayerState.frontEnd.transparentRegionHint = Region{Rect{0, 0, 1920, 1080}}; + mLayerFEState.transparentRegionHint = Region{Rect{0, 0, 1920, 1080}}; const Rect expected{0, 0, 0, 0}; EXPECT_THAT(calculateOutputDisplayFrame(), RectEq(expected)); } TEST_F(OutputLayerDisplayFrameTest, cropAffectsDisplayFrame) { - mLayerState.frontEnd.geomCrop = Rect{100, 200, 300, 500}; + mLayerFEState.geomCrop = Rect{100, 200, 300, 500}; const Rect expected{100, 200, 300, 500}; EXPECT_THAT(calculateOutputDisplayFrame(), RectEq(expected)); } TEST_F(OutputLayerDisplayFrameTest, cropAffectsDisplayFrameRotated) { - mLayerState.frontEnd.geomCrop = Rect{100, 200, 300, 500}; - mLayerState.frontEnd.geomLayerTransform.set(HAL_TRANSFORM_ROT_90, 1920, 1080); + mLayerFEState.geomCrop = Rect{100, 200, 300, 500}; + mLayerFEState.geomLayerTransform.set(HAL_TRANSFORM_ROT_90, 1920, 1080); const Rect expected{1420, 100, 1720, 300}; EXPECT_THAT(calculateOutputDisplayFrame(), RectEq(expected)); } TEST_F(OutputLayerDisplayFrameTest, emptyGeomCropIsNotUsedToComputeFrame) { - mLayerState.frontEnd.geomCrop = Rect{}; + mLayerFEState.geomCrop = Rect{}; const Rect expected{0, 0, 1920, 1080}; EXPECT_THAT(calculateOutputDisplayFrame(), RectEq(expected)); } TEST_F(OutputLayerDisplayFrameTest, geomLayerBoundsAffectsFrame) { - mLayerState.frontEnd.geomLayerBounds = FloatRect{0.f, 0.f, 960.f, 540.f}; + mLayerFEState.geomLayerBounds = FloatRect{0.f, 0.f, 960.f, 540.f}; const Rect expected{0, 0, 960, 540}; EXPECT_THAT(calculateOutputDisplayFrame(), RectEq(expected)); } @@ -293,7 +291,7 @@ TEST_F(OutputLayerDisplayFrameTest, outputTransformAffectsDisplayFrame) { */ TEST_F(OutputLayerTest, calculateOutputRelativeBufferTransformTestsNeeded) { - mLayerState.frontEnd.geomBufferUsesDisplayInverseTransform = false; + mLayerFEState.geomBufferUsesDisplayInverseTransform = false; struct Entry { uint32_t layer; @@ -340,8 +338,8 @@ TEST_F(OutputLayerTest, calculateOutputRelativeBufferTransformTestsNeeded) { for (size_t i = 0; i < testData.size(); i++) { const auto& entry = testData[i]; - mLayerState.frontEnd.geomLayerTransform.set(entry.layer, 1920, 1080); - mLayerState.frontEnd.geomBufferTransform = entry.buffer; + mLayerFEState.geomLayerTransform.set(entry.layer, 1920, 1080); + mLayerFEState.geomBufferTransform = entry.buffer; mOutputState.orientation = entry.display; auto actual = mOutputLayer.calculateOutputRelativeBufferTransform(); @@ -351,7 +349,7 @@ TEST_F(OutputLayerTest, calculateOutputRelativeBufferTransformTestsNeeded) { TEST_F(OutputLayerTest, calculateOutputRelativeBufferTransformTestWithOfBufferUsesDisplayInverseTransform) { - mLayerState.frontEnd.geomBufferUsesDisplayInverseTransform = true; + mLayerFEState.geomBufferUsesDisplayInverseTransform = true; struct Entry { uint32_t layer; @@ -398,8 +396,8 @@ TEST_F(OutputLayerTest, for (size_t i = 0; i < testData.size(); i++) { const auto& entry = testData[i]; - mLayerState.frontEnd.geomLayerTransform = ui::Transform{entry.layer}; - mLayerState.frontEnd.geomBufferTransform = entry.buffer; + mLayerFEState.geomLayerTransform = ui::Transform{entry.layer}; + mLayerFEState.geomBufferTransform = entry.buffer; mOutputState.orientation = entry.display; auto actual = mOutputLayer.calculateOutputRelativeBufferTransform(); @@ -425,7 +423,7 @@ struct OutputLayerPartialMockForUpdateCompositionState : public impl::OutputLaye struct OutputLayerUpdateCompositionStateTest : public OutputLayerTest { public: OutputLayerUpdateCompositionStateTest() { - EXPECT_CALL(*mLayer, getState()).WillRepeatedly(ReturnRef(mLayerState)); + EXPECT_CALL(*mLayer, getFEState()).WillRepeatedly(ReturnRef(mLayerFEState)); EXPECT_CALL(mOutput, getState()).WillRepeatedly(ReturnRef(mOutputState)); EXPECT_CALL(mOutput, getDisplayColorProfile()) .WillRepeatedly(Return(&mDisplayColorProfile)); @@ -458,7 +456,7 @@ public: }; TEST_F(OutputLayerUpdateCompositionStateTest, setsStateNormally) { - mLayerState.frontEnd.isSecure = true; + mLayerFEState.isSecure = true; mOutputState.isSecure = true; setupGeometryChildCallValues(); @@ -472,7 +470,7 @@ TEST_F(OutputLayerUpdateCompositionStateTest, setsStateNormally) { TEST_F(OutputLayerUpdateCompositionStateTest, alsoSetsForceCompositionIfSecureLayerOnNonsecureOutput) { - mLayerState.frontEnd.isSecure = true; + mLayerFEState.isSecure = true; mOutputState.isSecure = false; setupGeometryChildCallValues(); @@ -486,7 +484,7 @@ TEST_F(OutputLayerUpdateCompositionStateTest, TEST_F(OutputLayerUpdateCompositionStateTest, alsoSetsForceCompositionIfUnsupportedBufferTransform) { - mLayerState.frontEnd.isSecure = true; + mLayerFEState.isSecure = true; mOutputState.isSecure = true; mBufferTransform = ui::Transform::ROT_INVALID; @@ -501,12 +499,12 @@ TEST_F(OutputLayerUpdateCompositionStateTest, } TEST_F(OutputLayerUpdateCompositionStateTest, setsOutputLayerColorspaceCorrectly) { - mLayerState.frontEnd.dataspace = ui::Dataspace::DISPLAY_P3; + mLayerFEState.dataspace = ui::Dataspace::DISPLAY_P3; mOutputState.targetDataspace = ui::Dataspace::V0_SCRGB; // If the layer is not colorspace agnostic, the output layer dataspace // should use the layers requested colorspace. - mLayerState.frontEnd.isColorspaceAgnostic = false; + mLayerFEState.isColorspaceAgnostic = false; mOutputLayer.updateCompositionState(false); @@ -514,7 +512,7 @@ TEST_F(OutputLayerUpdateCompositionStateTest, setsOutputLayerColorspaceCorrectly // If the layer is colorspace agnostic, the output layer dataspace // should use the colorspace chosen for the whole output. - mLayerState.frontEnd.isColorspaceAgnostic = true; + mLayerFEState.isColorspaceAgnostic = true; mOutputLayer.updateCompositionState(false); @@ -528,7 +526,7 @@ TEST_F(OutputLayerUpdateCompositionStateTest, doesNotRecomputeGeometryIfNotReque } TEST_F(OutputLayerUpdateCompositionStateTest, clientCompositionForcedFromFrontEndFlagAtAnyTime) { - mLayerState.frontEnd.forceClientComposition = true; + mLayerFEState.forceClientComposition = true; mOutputLayer.updateCompositionState(false); @@ -583,18 +581,18 @@ struct OutputLayerWriteStateToHWCTest : public OutputLayerTest { outputLayerState.outputSpaceVisibleRegion = kOutputSpaceVisibleRegion; outputLayerState.dataspace = kDataspace; - mLayerState.frontEnd.blendMode = kBlendMode; - mLayerState.frontEnd.alpha = kAlpha; - mLayerState.frontEnd.type = kType; - mLayerState.frontEnd.appId = kAppId; - mLayerState.frontEnd.colorTransform = kColorTransform; - mLayerState.frontEnd.color = kColor; - mLayerState.frontEnd.surfaceDamage = kSurfaceDamage; - mLayerState.frontEnd.hdrMetadata = kHdrMetadata; - mLayerState.frontEnd.sidebandStream = NativeHandle::create(kSidebandStreamHandle, false); - mLayerState.frontEnd.buffer = kBuffer; - mLayerState.frontEnd.bufferSlot = BufferQueue::INVALID_BUFFER_SLOT; - mLayerState.frontEnd.acquireFence = kFence; + mLayerFEState.blendMode = kBlendMode; + mLayerFEState.alpha = kAlpha; + mLayerFEState.type = kType; + mLayerFEState.appId = kAppId; + mLayerFEState.colorTransform = kColorTransform; + mLayerFEState.color = kColor; + mLayerFEState.surfaceDamage = kSurfaceDamage; + mLayerFEState.hdrMetadata = kHdrMetadata; + mLayerFEState.sidebandStream = NativeHandle::create(kSidebandStreamHandle, false); + mLayerFEState.buffer = kBuffer; + mLayerFEState.bufferSlot = BufferQueue::INVALID_BUFFER_SLOT; + mLayerFEState.acquireFence = kFence; EXPECT_CALL(mOutput, getDisplayColorProfile()) .WillRepeatedly(Return(&mDisplayColorProfile)); @@ -698,7 +696,7 @@ TEST_F(OutputLayerWriteStateToHWCTest, canSetAllState) { } TEST_F(OutputLayerWriteStateToHWCTest, canSetPerFrameStateForSolidColor) { - mLayerState.frontEnd.compositionType = Hwc2::IComposerClient::Composition::SOLID_COLOR; + mLayerFEState.compositionType = Hwc2::IComposerClient::Composition::SOLID_COLOR; expectPerFrameCommonCalls(); expectSetColorCall(); @@ -708,7 +706,7 @@ TEST_F(OutputLayerWriteStateToHWCTest, canSetPerFrameStateForSolidColor) { } TEST_F(OutputLayerWriteStateToHWCTest, canSetPerFrameStateForSideband) { - mLayerState.frontEnd.compositionType = Hwc2::IComposerClient::Composition::SIDEBAND; + mLayerFEState.compositionType = Hwc2::IComposerClient::Composition::SIDEBAND; expectPerFrameCommonCalls(); expectSetSidebandHandleCall(); @@ -718,7 +716,7 @@ TEST_F(OutputLayerWriteStateToHWCTest, canSetPerFrameStateForSideband) { } TEST_F(OutputLayerWriteStateToHWCTest, canSetPerFrameStateForCursor) { - mLayerState.frontEnd.compositionType = Hwc2::IComposerClient::Composition::CURSOR; + mLayerFEState.compositionType = Hwc2::IComposerClient::Composition::CURSOR; expectPerFrameCommonCalls(); expectSetHdrMetadataAndBufferCalls(); @@ -728,7 +726,7 @@ TEST_F(OutputLayerWriteStateToHWCTest, canSetPerFrameStateForCursor) { } TEST_F(OutputLayerWriteStateToHWCTest, canSetPerFrameStateForDevice) { - mLayerState.frontEnd.compositionType = Hwc2::IComposerClient::Composition::DEVICE; + mLayerFEState.compositionType = Hwc2::IComposerClient::Composition::DEVICE; expectPerFrameCommonCalls(); expectSetHdrMetadataAndBufferCalls(); @@ -741,7 +739,7 @@ TEST_F(OutputLayerWriteStateToHWCTest, compositionTypeIsNotSetIfUnchanged) { (*mOutputLayer.editState().hwc).hwcCompositionType = Hwc2::IComposerClient::Composition::SOLID_COLOR; - mLayerState.frontEnd.compositionType = Hwc2::IComposerClient::Composition::SOLID_COLOR; + mLayerFEState.compositionType = Hwc2::IComposerClient::Composition::SOLID_COLOR; expectPerFrameCommonCalls(); expectSetColorCall(); @@ -751,7 +749,7 @@ TEST_F(OutputLayerWriteStateToHWCTest, compositionTypeIsNotSetIfUnchanged) { } TEST_F(OutputLayerWriteStateToHWCTest, compositionTypeIsSetToClientIfColorTransformNotSupported) { - mLayerState.frontEnd.compositionType = Hwc2::IComposerClient::Composition::SOLID_COLOR; + mLayerFEState.compositionType = Hwc2::IComposerClient::Composition::SOLID_COLOR; expectPerFrameCommonCalls(SimulateUnsupported::ColorTransform); expectSetColorCall(); @@ -763,7 +761,7 @@ TEST_F(OutputLayerWriteStateToHWCTest, compositionTypeIsSetToClientIfColorTransf TEST_F(OutputLayerWriteStateToHWCTest, compositionTypeIsSetToClientIfClientCompositionForced) { mOutputLayer.editState().forceClientComposition = true; - mLayerState.frontEnd.compositionType = Hwc2::IComposerClient::Composition::SOLID_COLOR; + mLayerFEState.compositionType = Hwc2::IComposerClient::Composition::SOLID_COLOR; expectPerFrameCommonCalls(); expectSetColorCall(); @@ -787,7 +785,7 @@ struct OutputLayerWriteCursorPositionToHWCTest : public OutputLayerTest { auto& outputLayerState = mOutputLayer.editState(); outputLayerState.hwc = impl::OutputLayerCompositionState::Hwc(mHwcLayer); - mLayerState.frontEnd.cursorFrame = kDefaultCursorFrame; + mLayerFEState.cursorFrame = kDefaultCursorFrame; mOutputState.viewport = kDefaultDisplayViewport; mOutputState.transform = ui::Transform{kDefaultTransform}; @@ -812,7 +810,7 @@ TEST_F(OutputLayerWriteCursorPositionToHWCTest, writeCursorPositionToHWCWritesSt } TEST_F(OutputLayerWriteCursorPositionToHWCTest, writeCursorPositionToHWCIntersectedWithViewport) { - mLayerState.frontEnd.cursorFrame = Rect{3000, 3000, 3016, 3016}; + mLayerFEState.cursorFrame = Rect{3000, 3000, 3016, 3016}; EXPECT_CALL(*mHwcLayer, setCursorPosition(1920, 1080)).WillOnce(Return(kDefaultError)); diff --git a/services/surfaceflinger/CompositionEngine/tests/OutputTest.cpp b/services/surfaceflinger/CompositionEngine/tests/OutputTest.cpp index a0b8017264..70c343bba6 100644 --- a/services/surfaceflinger/CompositionEngine/tests/OutputTest.cpp +++ b/services/surfaceflinger/CompositionEngine/tests/OutputTest.cpp @@ -16,7 +16,7 @@ #include -#include +#include #include #include #include @@ -378,9 +378,9 @@ TEST_F(OutputTest, belongsInOutputFiltersAsExpected) { TEST_F(OutputTest, belongsInOutputFiltersLayersAsExpected) { StrictMock layer; - impl::LayerCompositionState layerState; + LayerFECompositionState layerFEState; - EXPECT_CALL(layer, getState()).WillRepeatedly(ReturnRef(layerState)); + EXPECT_CALL(layer, getFEState()).WillRepeatedly(ReturnRef(layerFEState)); const uint32_t layerStack1 = 123u; const uint32_t layerStack2 = 456u; @@ -392,29 +392,29 @@ TEST_F(OutputTest, belongsInOutputFiltersLayersAsExpected) { EXPECT_FALSE(mOutput.belongsInOutput(nullptr)); // A layer with no layerStack does not belong to it, internal-only or not. - layerState.frontEnd.layerStackId = std::nullopt; - layerState.frontEnd.internalOnly = false; + layerFEState.layerStackId = std::nullopt; + layerFEState.internalOnly = false; EXPECT_FALSE(mOutput.belongsInOutput(&layer)); - layerState.frontEnd.layerStackId = std::nullopt; - layerState.frontEnd.internalOnly = true; + layerFEState.layerStackId = std::nullopt; + layerFEState.internalOnly = true; EXPECT_FALSE(mOutput.belongsInOutput(&layer)); // Any layer with layerStack1 belongs to it, internal-only or not. - layerState.frontEnd.layerStackId = layerStack1; - layerState.frontEnd.internalOnly = false; + layerFEState.layerStackId = layerStack1; + layerFEState.internalOnly = false; EXPECT_TRUE(mOutput.belongsInOutput(&layer)); - layerState.frontEnd.layerStackId = layerStack1; - layerState.frontEnd.internalOnly = true; + layerFEState.layerStackId = layerStack1; + layerFEState.internalOnly = true; EXPECT_TRUE(mOutput.belongsInOutput(&layer)); - layerState.frontEnd.layerStackId = layerStack2; - layerState.frontEnd.internalOnly = true; + layerFEState.layerStackId = layerStack2; + layerFEState.internalOnly = true; EXPECT_FALSE(mOutput.belongsInOutput(&layer)); - layerState.frontEnd.layerStackId = layerStack2; - layerState.frontEnd.internalOnly = false; + layerFEState.layerStackId = layerStack2; + layerFEState.internalOnly = false; EXPECT_FALSE(mOutput.belongsInOutput(&layer)); // If the output accepts layerStack1 but not internal-only layers... @@ -424,20 +424,20 @@ TEST_F(OutputTest, belongsInOutputFiltersLayersAsExpected) { EXPECT_FALSE(mOutput.belongsInOutput(nullptr)); // Only non-internal layers with layerStack1 belong to it. - layerState.frontEnd.layerStackId = layerStack1; - layerState.frontEnd.internalOnly = false; + layerFEState.layerStackId = layerStack1; + layerFEState.internalOnly = false; EXPECT_TRUE(mOutput.belongsInOutput(&layer)); - layerState.frontEnd.layerStackId = layerStack1; - layerState.frontEnd.internalOnly = true; + layerFEState.layerStackId = layerStack1; + layerFEState.internalOnly = true; EXPECT_FALSE(mOutput.belongsInOutput(&layer)); - layerState.frontEnd.layerStackId = layerStack2; - layerState.frontEnd.internalOnly = true; + layerFEState.layerStackId = layerStack2; + layerFEState.internalOnly = true; EXPECT_FALSE(mOutput.belongsInOutput(&layer)); - layerState.frontEnd.layerStackId = layerStack2; - layerState.frontEnd.internalOnly = false; + layerFEState.layerStackId = layerStack2; + layerFEState.internalOnly = false; EXPECT_FALSE(mOutput.belongsInOutput(&layer)); } @@ -732,8 +732,8 @@ TEST_F(GenerateClientCompositionRequestsTest, worksForLandscapeModeSplitScreen) leftOutputLayerState.clearClientTarget = false; leftOutputLayerState.visibleRegion = Region{Rect{0, 0, 1000, 1000}}; - impl::LayerCompositionState leftLayerState; - leftLayerState.frontEnd.isOpaque = true; + LayerFECompositionState leftLayerFEState; + leftLayerFEState.isOpaque = true; const half3 leftLayerColor{1.f, 0.f, 0.f}; renderengine::LayerSettings leftLayerRESettings; @@ -743,8 +743,8 @@ TEST_F(GenerateClientCompositionRequestsTest, worksForLandscapeModeSplitScreen) rightOutputLayerState.clearClientTarget = false; rightOutputLayerState.visibleRegion = Region{Rect{1000, 0, 2000, 1000}}; - impl::LayerCompositionState rightLayerState; - rightLayerState.frontEnd.isOpaque = true; + LayerFECompositionState rightLayerFEState; + rightLayerFEState.isOpaque = true; const half3 rightLayerColor{0.f, 1.f, 0.f}; renderengine::LayerSettings rightLayerRESettings; @@ -755,7 +755,7 @@ TEST_F(GenerateClientCompositionRequestsTest, worksForLandscapeModeSplitScreen) EXPECT_CALL(*leftOutputLayer, getLayerFE()).WillRepeatedly(ReturnRef(leftLayerFE)); EXPECT_CALL(*leftOutputLayer, requiresClientComposition()).WillRepeatedly(Return(true)); EXPECT_CALL(*leftOutputLayer, needsFiltering()).WillRepeatedly(Return(false)); - EXPECT_CALL(leftLayer, getState()).WillRepeatedly(ReturnRef(leftLayerState)); + EXPECT_CALL(leftLayer, getFEState()).WillRepeatedly(ReturnRef(leftLayerFEState)); EXPECT_CALL(leftLayerFE, prepareClientComposition(_)).WillOnce(Return(leftLayerRESettings)); EXPECT_CALL(*rightOutputLayer, getState()).WillRepeatedly(ReturnRef(rightOutputLayerState)); @@ -763,7 +763,7 @@ TEST_F(GenerateClientCompositionRequestsTest, worksForLandscapeModeSplitScreen) EXPECT_CALL(*rightOutputLayer, getLayerFE()).WillRepeatedly(ReturnRef(rightLayerFE)); EXPECT_CALL(*rightOutputLayer, requiresClientComposition()).WillRepeatedly(Return(true)); EXPECT_CALL(*rightOutputLayer, needsFiltering()).WillRepeatedly(Return(false)); - EXPECT_CALL(rightLayer, getState()).WillRepeatedly(ReturnRef(rightLayerState)); + EXPECT_CALL(rightLayer, getFEState()).WillRepeatedly(ReturnRef(rightLayerFEState)); EXPECT_CALL(rightLayerFE, prepareClientComposition(_)).WillOnce(Return(rightLayerRESettings)); Output::OutputLayers outputLayers; @@ -806,15 +806,15 @@ TEST_F(GenerateClientCompositionRequestsTest, ignoresLayersThatDoNotIntersectWit outputLayerState.clearClientTarget = false; outputLayerState.visibleRegion = Region{Rect{3000, 0, 4000, 1000}}; - impl::LayerCompositionState layerState; - layerState.frontEnd.isOpaque = true; + LayerFECompositionState layerFEState; + layerFEState.isOpaque = true; EXPECT_CALL(*outputLayer, getState()).WillRepeatedly(ReturnRef(outputLayerState)); EXPECT_CALL(*outputLayer, getLayer()).WillRepeatedly(ReturnRef(layer)); EXPECT_CALL(*outputLayer, getLayerFE()).WillRepeatedly(ReturnRef(layerFE)); EXPECT_CALL(*outputLayer, requiresClientComposition()).WillRepeatedly(Return(true)); EXPECT_CALL(*outputLayer, needsFiltering()).WillRepeatedly(Return(false)); - EXPECT_CALL(layer, getState()).WillRepeatedly(ReturnRef(layerState)); + EXPECT_CALL(layer, getFEState()).WillRepeatedly(ReturnRef(layerFEState)); EXPECT_CALL(layerFE, prepareClientComposition(_)).Times(0); Output::OutputLayers outputLayers; @@ -861,15 +861,15 @@ TEST_F(GenerateClientCompositionRequestsTest, clearsDeviceLayesAfterFirst) { leftOutputLayerState.clearClientTarget = true; leftOutputLayerState.visibleRegion = Region{Rect{0, 0, 1000, 1000}}; - impl::LayerCompositionState leftLayerState; - leftLayerState.frontEnd.isOpaque = true; + LayerFECompositionState leftLayerFEState; + leftLayerFEState.isOpaque = true; impl::OutputLayerCompositionState rightOutputLayerState; rightOutputLayerState.clearClientTarget = true; rightOutputLayerState.visibleRegion = Region{Rect{1000, 0, 2000, 1000}}; - impl::LayerCompositionState rightLayerState; - rightLayerState.frontEnd.isOpaque = true; + LayerFECompositionState rightLayerFEState; + rightLayerFEState.isOpaque = true; const half3 rightLayerColor{0.f, 1.f, 0.f}; renderengine::LayerSettings rightLayerRESettings; @@ -881,14 +881,14 @@ TEST_F(GenerateClientCompositionRequestsTest, clearsDeviceLayesAfterFirst) { EXPECT_CALL(*leftOutputLayer, getLayerFE()).WillRepeatedly(ReturnRef(leftLayerFE)); EXPECT_CALL(*leftOutputLayer, requiresClientComposition()).WillRepeatedly(Return(false)); EXPECT_CALL(*leftOutputLayer, needsFiltering()).WillRepeatedly(Return(false)); - EXPECT_CALL(leftLayer, getState()).WillRepeatedly(ReturnRef(leftLayerState)); + EXPECT_CALL(leftLayer, getFEState()).WillRepeatedly(ReturnRef(leftLayerFEState)); EXPECT_CALL(*rightOutputLayer, getState()).WillRepeatedly(ReturnRef(rightOutputLayerState)); EXPECT_CALL(*rightOutputLayer, getLayer()).WillRepeatedly(ReturnRef(rightLayer)); EXPECT_CALL(*rightOutputLayer, getLayerFE()).WillRepeatedly(ReturnRef(rightLayerFE)); EXPECT_CALL(*rightOutputLayer, requiresClientComposition()).WillRepeatedly(Return(false)); EXPECT_CALL(*rightOutputLayer, needsFiltering()).WillRepeatedly(Return(false)); - EXPECT_CALL(rightLayer, getState()).WillRepeatedly(ReturnRef(rightLayerState)); + EXPECT_CALL(rightLayer, getFEState()).WillRepeatedly(ReturnRef(rightLayerFEState)); EXPECT_CALL(rightLayerFE, prepareClientComposition(_)).WillOnce(Return(rightLayerRESettings)); Output::OutputLayers outputLayers; diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp index bed33a71d0..7b708bccae 100644 --- a/services/surfaceflinger/Layer.cpp +++ b/services/surfaceflinger/Layer.cpp @@ -27,7 +27,6 @@ #include #include #include -#include #include #include #include diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp index cc12608e87..15550799bf 100644 --- a/services/surfaceflinger/SurfaceFlinger.cpp +++ b/services/surfaceflinger/SurfaceFlinger.cpp @@ -41,12 +41,9 @@ #include #include #include -#include #include #include -#include #include -#include #include #include #include diff --git a/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h b/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h index d0d391b679..b77f82a7f8 100644 --- a/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h +++ b/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h @@ -18,9 +18,9 @@ #include #include +#include #include #include -#include #include #include "BufferQueueLayer.h" @@ -235,7 +235,7 @@ public: void setLayerSidebandStream(sp layer, sp sidebandStream) { layer->mDrawingState.sidebandStream = sidebandStream; layer->mSidebandStream = sidebandStream; - layer->getCompositionLayer()->editState().frontEnd.sidebandStream = sidebandStream; + layer->getCompositionLayer()->editFEState().sidebandStream = sidebandStream; } void setLayerCompositionType(sp layer, HWC2::Composition type) { -- cgit v1.2.3-59-g8ed1b From 958be49bdb1a379a507cd1825680ca845fd1a7a0 Mon Sep 17 00:00:00 2001 From: Lloyd Pique Date: Thu, 28 Mar 2019 15:34:59 -0700 Subject: SF: Update Layer::setBackgroundColor to use the factory interface Rather than directly creating a ColorLayer, use the factory interface to do so. This allows an override to be created instead if desired. Test: atest CtsViewTestCases Test: go/wm-smoke Bug: 121291683 Change-Id: I53f65f482bc896cb54857d6f268c550fd173f6ff --- services/surfaceflinger/Layer.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'services/surfaceflinger/Layer.cpp') diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp index 7b708bccae..ba948cfdbc 100644 --- a/services/surfaceflinger/Layer.cpp +++ b/services/surfaceflinger/Layer.cpp @@ -989,7 +989,7 @@ bool Layer::setBackgroundColor(const half3& color, float alpha, ui::Dataspace da // create background color layer if one does not yet exist uint32_t flags = ISurfaceComposerClient::eFXSurfaceColor; const String8& name = mName + "BackgroundColorLayer"; - mCurrentState.bgColorLayer = new ColorLayer( + mCurrentState.bgColorLayer = mFlinger->getFactory().createColorLayer( LayerCreationArgs(mFlinger.get(), nullptr, name, 0, 0, flags, LayerMetadata())); // add to child list -- cgit v1.2.3-59-g8ed1b From e5ac40f470e92e8f3a3dbbf58c2f432a816f4486 Mon Sep 17 00:00:00 2001 From: chaviw Date: Tue, 24 Sep 2019 16:36:55 -0700 Subject: Added isRelativeOf instead of checking if weak pointer is not null If a layer has a relativeOf, it will continue to assume it has a relativeOf even if what it's relative to is removed. This is because the client never explicitly asked to remove the relative Z. Instead of relying on whether the weak pointer is non null, this change adds a variable isRelativeOf that's set to true when the client calls setRelativeLayer and false when the client calls setLayer. This is clearer than checking whether the weak pointer is still around. This is also needed for mirroring since we want to add this same behavior without having to clone weak referenced layers. Bug: 131622422 Test: go/wm-smoke Test: SurfaceFlinger_test Change-Id: Ia71b0f660edda9b3a63521d40ca30bfca1d456b9 --- services/surfaceflinger/Layer.cpp | 7 ++++--- services/surfaceflinger/Layer.h | 1 + services/surfaceflinger/LayerVector.cpp | 4 ++-- 3 files changed, 7 insertions(+), 5 deletions(-) (limited to 'services/surfaceflinger/Layer.cpp') diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp index ba948cfdbc..80d1e9a233 100644 --- a/services/surfaceflinger/Layer.cpp +++ b/services/surfaceflinger/Layer.cpp @@ -899,6 +899,7 @@ bool Layer::setLayer(int32_t z) { } setZOrderRelativeOf(nullptr); } + mCurrentState.isRelativeOf = false; setTransactionFlags(eTransactionNeeded); return true; } @@ -942,6 +943,7 @@ bool Layer::setRelativeLayer(const sp& relativeToHandle, int32_t relati mCurrentState.sequence++; mCurrentState.modified = true; mCurrentState.z = relativeZ; + mCurrentState.isRelativeOf = true; auto oldZOrderRelativeOf = mCurrentState.zOrderRelativeOf.promote(); if (oldZOrderRelativeOf != nullptr) { @@ -1540,7 +1542,7 @@ int32_t Layer::getZ() const { bool Layer::usingRelativeZ(LayerVector::StateSet stateSet) const { const bool useDrawing = stateSet == LayerVector::StateSet::Drawing; const State& state = useDrawing ? mDrawingState : mCurrentState; - return state.zOrderRelativeOf != nullptr; + return state.isRelativeOf; } __attribute__((no_sanitize("unsigned-integer-overflow"))) LayerVector Layer::makeTraversalList( @@ -1565,8 +1567,7 @@ __attribute__((no_sanitize("unsigned-integer-overflow"))) LayerVector Layer::mak } for (const sp& child : children) { - const State& childState = useDrawing ? child->mDrawingState : child->mCurrentState; - if (childState.zOrderRelativeOf != nullptr) { + if (child->usingRelativeZ(stateSet)) { continue; } traverse.add(child); diff --git a/services/surfaceflinger/Layer.h b/services/surfaceflinger/Layer.h index 8771ccd08e..bd192615c2 100644 --- a/services/surfaceflinger/Layer.h +++ b/services/surfaceflinger/Layer.h @@ -170,6 +170,7 @@ public: // If non-null, a Surface this Surface's Z-order is interpreted relative to. wp zOrderRelativeOf; + bool isRelativeOf{false}; // A list of surfaces whose Z-order is interpreted relative to ours. SortedVector> zOrderRelatives; diff --git a/services/surfaceflinger/LayerVector.cpp b/services/surfaceflinger/LayerVector.cpp index 84945247a6..8271fd97ea 100644 --- a/services/surfaceflinger/LayerVector.cpp +++ b/services/surfaceflinger/LayerVector.cpp @@ -64,7 +64,7 @@ void LayerVector::traverseInZOrder(StateSet stateSet, const Visitor& visitor) co const auto& layer = (*this)[i]; auto& state = (stateSet == StateSet::Current) ? layer->getCurrentState() : layer->getDrawingState(); - if (state.zOrderRelativeOf != nullptr) { + if (state.isRelativeOf) { continue; } layer->traverseInZOrder(stateSet, visitor); @@ -76,7 +76,7 @@ void LayerVector::traverseInReverseZOrder(StateSet stateSet, const Visitor& visi const auto& layer = (*this)[i]; auto& state = (stateSet == StateSet::Current) ? layer->getCurrentState() : layer->getDrawingState(); - if (state.zOrderRelativeOf != nullptr) { + if (state.isRelativeOf) { continue; } layer->traverseInReverseZOrder(stateSet, visitor); -- cgit v1.2.3-59-g8ed1b From b4c6e5850f16d045abcb4e3308b7556749a61be0 Mon Sep 17 00:00:00 2001 From: chaviw Date: Fri, 16 Aug 2019 14:35:07 -0700 Subject: [Mirror Layers] Added clone function to layers (1/4) Added a cloning function to each layer in preparation for mirroring Test: Nothing to test yet since no calls Bug: 131622422 Change-Id: Iba0692b75c4d99841de48f40ed55b3dbccf2b9b9 --- services/surfaceflinger/BufferLayer.cpp | 19 +++++++++++++-- services/surfaceflinger/BufferLayer.h | 1 + services/surfaceflinger/BufferQueueLayer.cpp | 20 ++++++++++------ services/surfaceflinger/BufferQueueLayer.h | 2 ++ services/surfaceflinger/BufferStateLayer.cpp | 27 ++++++++++++++-------- services/surfaceflinger/BufferStateLayer.h | 2 +- services/surfaceflinger/ColorLayer.cpp | 8 +++++++ services/surfaceflinger/ColorLayer.h | 2 ++ services/surfaceflinger/ContainerLayer.cpp | 7 ++++++ services/surfaceflinger/ContainerLayer.h | 3 +++ services/surfaceflinger/Layer.cpp | 9 ++++++++ services/surfaceflinger/Layer.h | 15 ++++++++++++ services/surfaceflinger/SurfaceFlinger.cpp | 21 +++++++++++++---- .../tests/unittests/CompositionTest.cpp | 13 +++++++---- 14 files changed, 121 insertions(+), 28 deletions(-) (limited to 'services/surfaceflinger/Layer.cpp') diff --git a/services/surfaceflinger/BufferLayer.cpp b/services/surfaceflinger/BufferLayer.cpp index fba235d397..d189846dd5 100644 --- a/services/surfaceflinger/BufferLayer.cpp +++ b/services/surfaceflinger/BufferLayer.cpp @@ -58,7 +58,7 @@ namespace android { BufferLayer::BufferLayer(const LayerCreationArgs& args) : Layer(args), - mTextureName(args.flinger->getNewTexture()), + mTextureName(args.textureName), mCompositionLayer{mFlinger->getCompositionEngine().createLayer( compositionengine::LayerCreationArgs{this})} { ALOGV("Creating Layer %s", args.name.string()); @@ -70,7 +70,13 @@ BufferLayer::BufferLayer(const LayerCreationArgs& args) } BufferLayer::~BufferLayer() { - mFlinger->deleteTextureAsync(mTextureName); + if (!isClone()) { + // The original layer and the clone layer share the same texture. Therefore, only one of + // the layers, in this case the original layer, needs to handle the deletion. The original + // layer and the clone should be removed at the same time so there shouldn't be any issue + // with the clone layer trying to use the deleted texture. + mFlinger->deleteTextureAsync(mTextureName); + } const int32_t layerID = getSequence(); mFlinger->mTimeStats->onDestroy(layerID); mFlinger->mFrameTracer->onDestroy(layerID); @@ -722,6 +728,15 @@ void BufferLayer::getDrawingTransformMatrix(bool filteringEnabled, float outMatr mBufferInfo.mTransform, filteringEnabled); } +void BufferLayer::setInitialValuesForClone(const sp& clonedFrom) { + Layer::setInitialValuesForClone(clonedFrom); + + sp bufferClonedFrom = static_cast(clonedFrom.get()); + mPremultipliedAlpha = bufferClonedFrom->mPremultipliedAlpha; + mPotentialCursor = bufferClonedFrom->mPotentialCursor; + mProtectedByApp = bufferClonedFrom->mProtectedByApp; +} + } // namespace android #if defined(__gl_h_) diff --git a/services/surfaceflinger/BufferLayer.h b/services/surfaceflinger/BufferLayer.h index f0a30e319a..b2c06183a6 100644 --- a/services/surfaceflinger/BufferLayer.h +++ b/services/surfaceflinger/BufferLayer.h @@ -194,6 +194,7 @@ protected: bool mRefreshPending{false}; ui::Dataspace translateDataspace(ui::Dataspace dataspace); + void setInitialValuesForClone(const sp& clonedFrom); private: // Returns true if this layer requires filtering diff --git a/services/surfaceflinger/BufferQueueLayer.cpp b/services/surfaceflinger/BufferQueueLayer.cpp index fcabedf63e..eb13f658d9 100644 --- a/services/surfaceflinger/BufferQueueLayer.cpp +++ b/services/surfaceflinger/BufferQueueLayer.cpp @@ -461,12 +461,7 @@ void BufferQueueLayer::onFirstRef() { sp consumer; BufferQueue::createBufferQueue(&producer, &consumer, true); mProducer = new MonitoredProducer(producer, mFlinger, this); - { - // Grab the SF state lock during this since it's the only safe way to access RenderEngine - Mutex::Autolock lock(mFlinger->mStateLock); - mConsumer = - new BufferLayerConsumer(consumer, mFlinger->getRenderEngine(), mTextureName, this); - } + mConsumer = new BufferLayerConsumer(consumer, mFlinger->getRenderEngine(), mTextureName, this); mConsumer->setConsumerUsageBits(getEffectiveUsage(0)); mConsumer->setContentsChangedListener(this); mConsumer->setName(mName); @@ -476,7 +471,7 @@ void BufferQueueLayer::onFirstRef() { mProducer->setMaxDequeuedBufferCount(2); } - if (const auto display = mFlinger->getDefaultDisplayDevice()) { + if (const auto display = mFlinger->getDefaultDisplayDeviceLocked()) { updateTransformHint(display); } } @@ -531,4 +526,15 @@ void BufferQueueLayer::gatherBufferInfo() { mBufferInfo.mTransformToDisplayInverse = mConsumer->getTransformToDisplayInverse(); } +sp BufferQueueLayer::createClone() { + const String8 name = mName + " (Mirror)"; + LayerCreationArgs args = + LayerCreationArgs(mFlinger.get(), nullptr, name, 0, 0, 0, LayerMetadata()); + args.textureName = mTextureName; + sp layer = new BufferQueueLayer(args); + layer->setInitialValuesForClone(this); + + return layer; +} + } // namespace android diff --git a/services/surfaceflinger/BufferQueueLayer.h b/services/surfaceflinger/BufferQueueLayer.h index 9374741ddb..36dff156e1 100644 --- a/services/surfaceflinger/BufferQueueLayer.h +++ b/services/surfaceflinger/BufferQueueLayer.h @@ -31,6 +31,7 @@ namespace android { */ class BufferQueueLayer : public BufferLayer, public BufferLayerConsumer::ContentsChangedListener { public: + // Only call while mStateLock is held explicit BufferQueueLayer(const LayerCreationArgs&); ~BufferQueueLayer() override; @@ -81,6 +82,7 @@ private: status_t updateFrameNumber(nsecs_t latchTime) override; void latchPerFrameState(compositionengine::LayerFECompositionState&) const override; + sp createClone() override; // ----------------------------------------------------------------------- // Interface implementation for BufferLayerConsumer::ContentsChangedListener diff --git a/services/surfaceflinger/BufferStateLayer.cpp b/services/surfaceflinger/BufferStateLayer.cpp index ad05bc8671..30fdbe14e8 100644 --- a/services/surfaceflinger/BufferStateLayer.cpp +++ b/services/surfaceflinger/BufferStateLayer.cpp @@ -48,10 +48,17 @@ BufferStateLayer::BufferStateLayer(const LayerCreationArgs& args) : BufferLayer(args), mHwcSlotGenerator(new HwcSlotGenerator()) { mOverrideScalingMode = NATIVE_WINDOW_SCALING_MODE_SCALE_TO_WINDOW; mCurrentState.dataspace = ui::Dataspace::V0_SRGB; + if (const auto display = args.displayDevice) { + updateTransformHint(display); + } } BufferStateLayer::~BufferStateLayer() { - if (mBufferInfo.mBuffer != nullptr) { + // The original layer and the clone layer share the same texture and buffer. Therefore, only + // one of the layers, in this case the original layer, needs to handle the deletion. The + // original layer and the clone should be removed at the same time so there shouldn't be any + // issue with the clone layer trying to use the texture. + if (mBufferInfo.mBuffer != nullptr && !isClone()) { // Ensure that mBuffer is uncached from RenderEngine here, as // RenderEngine may have been using the buffer as an external texture // after the client uncached the buffer. @@ -545,14 +552,6 @@ void BufferStateLayer::latchPerFrameState( mFrameNumber++; } -void BufferStateLayer::onFirstRef() { - BufferLayer::onFirstRef(); - - if (const auto display = mFlinger->getDefaultDisplayDevice()) { - updateTransformHint(display); - } -} - void BufferStateLayer::HwcSlotGenerator::bufferErased(const client_cache_t& clientCacheId) { std::lock_guard lock(mMutex); if (!clientCacheId.isValid()) { @@ -668,4 +667,14 @@ Rect BufferStateLayer::computeCrop(const State& s) { return s.crop; } +sp BufferStateLayer::createClone() { + const String8 name = mName + " (Mirror)"; + LayerCreationArgs args = + LayerCreationArgs(mFlinger.get(), nullptr, name, 0, 0, 0, LayerMetadata()); + args.textureName = mTextureName; + sp layer = new BufferStateLayer(args); + layer->mHwcSlotGenerator = mHwcSlotGenerator; + layer->setInitialValuesForClone(this); + return layer; +} } // namespace android diff --git a/services/surfaceflinger/BufferStateLayer.h b/services/surfaceflinger/BufferStateLayer.h index 52063fcc58..e951ccf97a 100644 --- a/services/surfaceflinger/BufferStateLayer.h +++ b/services/surfaceflinger/BufferStateLayer.h @@ -124,13 +124,13 @@ private: status_t updateFrameNumber(nsecs_t latchTime) override; void latchPerFrameState(compositionengine::LayerFECompositionState&) const override; + sp createClone() override; // Crop that applies to the buffer Rect computeCrop(const State& s); private: friend class SlotGenerationTest; - void onFirstRef() override; bool willPresentCurrentTransaction() const; static const std::array IDENTITY_MATRIX; diff --git a/services/surfaceflinger/ColorLayer.cpp b/services/surfaceflinger/ColorLayer.cpp index 99805d9da2..5b620543ac 100644 --- a/services/surfaceflinger/ColorLayer.cpp +++ b/services/surfaceflinger/ColorLayer.cpp @@ -107,6 +107,14 @@ ui::Dataspace ColorLayer::getDataSpace() const { return mDrawingState.dataspace; } +sp ColorLayer::createClone() { + String8 name = mName + " (Mirror)"; + sp layer = new ColorLayer( + LayerCreationArgs(mFlinger.get(), nullptr, name, 0, 0, 0, LayerMetadata())); + layer->setInitialValuesForClone(this); + return layer; +} + // --------------------------------------------------------------------------- }; // namespace android diff --git a/services/surfaceflinger/ColorLayer.h b/services/surfaceflinger/ColorLayer.h index 16921df356..634a80003a 100644 --- a/services/surfaceflinger/ColorLayer.h +++ b/services/surfaceflinger/ColorLayer.h @@ -50,6 +50,8 @@ protected: compositionengine::LayerFE::ClientCompositionTargetSettings&) override; std::shared_ptr mCompositionLayer; + + sp createClone() override; }; } // namespace android diff --git a/services/surfaceflinger/ContainerLayer.cpp b/services/surfaceflinger/ContainerLayer.cpp index 4a1130365a..cb50d9ff6d 100644 --- a/services/surfaceflinger/ContainerLayer.cpp +++ b/services/surfaceflinger/ContainerLayer.cpp @@ -30,4 +30,11 @@ bool ContainerLayer::isVisible() const { return false; } +sp ContainerLayer::createClone() { + String8 name = mName + " (Mirror)"; + sp layer = new ContainerLayer( + LayerCreationArgs(mFlinger.get(), nullptr, name, 0, 0, 0, LayerMetadata())); + layer->setInitialValuesForClone(this); + return layer; +} } // namespace android diff --git a/services/surfaceflinger/ContainerLayer.h b/services/surfaceflinger/ContainerLayer.h index c3624f6d7d..b48d471bde 100644 --- a/services/surfaceflinger/ContainerLayer.h +++ b/services/surfaceflinger/ContainerLayer.h @@ -32,6 +32,9 @@ public: bool isVisible() const override; bool isCreatedFromMainThread() const override { return true; } + +protected: + sp createClone() override; }; } // namespace android diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp index ba948cfdbc..52a09b35d1 100644 --- a/services/surfaceflinger/Layer.cpp +++ b/services/surfaceflinger/Layer.cpp @@ -2015,6 +2015,15 @@ Region Layer::debugGetVisibleRegionOnDefaultDisplay() const { return outputLayer->getState().visibleRegion; } +void Layer::setInitialValuesForClone(const sp& clonedFrom) { + // copy drawing state from cloned layer + mDrawingState = clonedFrom->mDrawingState; + mClonedFrom = clonedFrom; + + // TODO: (b/140756730) Ignore input for now since InputDispatcher doesn't support multiple + // InputWindows per client token yet. + mDrawingState.inputInfo.token = nullptr; +} // --------------------------------------------------------------------------- }; // namespace android diff --git a/services/surfaceflinger/Layer.h b/services/surfaceflinger/Layer.h index 8771ccd08e..96970ace89 100644 --- a/services/surfaceflinger/Layer.h +++ b/services/surfaceflinger/Layer.h @@ -91,6 +91,8 @@ struct LayerCreationArgs { LayerMetadata metadata; pid_t callingPid; uid_t callingUid; + sp displayDevice; + uint32_t textureName; }; class Layer : public compositionengine::LayerFE { @@ -465,6 +467,13 @@ public: virtual Rect getCrop(const Layer::State& s) const { return s.crop_legacy; } virtual bool needsFiltering(const sp&) const { return false; } +protected: + virtual sp createClone() = 0; + sp getClonedFrom() { return mClonedFrom != nullptr ? mClonedFrom.promote() : nullptr; } + + bool isClone() { return getClonedFrom() != nullptr; } + virtual void setInitialValuesForClone(const sp& clonedFrom); + public: /* * compositionengine::LayerFE overrides @@ -912,6 +921,12 @@ private: // to help debugging. pid_t mCallingPid; uid_t mCallingUid; + + // The current layer is a clone of mClonedFrom. This means that this layer will update it's + // properties based on mClonedFrom. When mClonedFrom latches a new buffer for BufferLayers, + // this layer will update it's buffer. When mClonedFrom updates it's drawing state, children, + // and relatives, this layer will update as well. + wp mClonedFrom; }; } // namespace android diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp index 41afb5da55..e3cf84aa1a 100644 --- a/services/surfaceflinger/SurfaceFlinger.cpp +++ b/services/surfaceflinger/SurfaceFlinger.cpp @@ -3532,8 +3532,18 @@ status_t SurfaceFlinger::createBufferQueueLayer(const sp& client, const break; } - sp layer = getFactory().createBufferQueueLayer( - LayerCreationArgs(this, client, name, w, h, flags, std::move(metadata))); + sp layer; + LayerCreationArgs args = + LayerCreationArgs(this, client, name, w, h, flags, std::move(metadata)); + args.textureName = getNewTexture(); + { + // Grab the SF state lock during this since it's the only safe way to access + // RenderEngine when creating a BufferLayerConsumer + // TODO: Check if this lock is still needed here + Mutex::Autolock lock(mStateLock); + layer = getFactory().createBufferQueueLayer(args); + } + status_t err = layer->setDefaultBufferProperties(w, h, format); if (err == NO_ERROR) { *handle = layer->getHandle(); @@ -3549,8 +3559,11 @@ status_t SurfaceFlinger::createBufferStateLayer(const sp& client, const uint32_t w, uint32_t h, uint32_t flags, LayerMetadata metadata, sp* handle, sp* outLayer) { - sp layer = getFactory().createBufferStateLayer( - LayerCreationArgs(this, client, name, w, h, flags, std::move(metadata))); + LayerCreationArgs args = + LayerCreationArgs(this, client, name, w, h, flags, std::move(metadata)); + args.displayDevice = getDefaultDisplayDevice(); + args.textureName = getNewTexture(); + sp layer = getFactory().createBufferStateLayer(args); *handle = layer->getHandle(); *outLayer = layer; diff --git a/services/surfaceflinger/tests/unittests/CompositionTest.cpp b/services/surfaceflinger/tests/unittests/CompositionTest.cpp index 20dfed65e2..f29e2ddd33 100644 --- a/services/surfaceflinger/tests/unittests/CompositionTest.cpp +++ b/services/surfaceflinger/tests/unittests/CompositionTest.cpp @@ -883,11 +883,14 @@ struct BufferLayerVariant : public BaseLayerVariant { FlingerLayerType layer = Base::template createLayerWithFactory(test, [test]() { - return new BufferQueueLayer( - LayerCreationArgs(test->mFlinger.mFlinger.get(), sp(), - String8("test-layer"), LayerProperties::WIDTH, - LayerProperties::HEIGHT, - LayerProperties::LAYER_FLAGS, LayerMetadata())); + sp client; + String8 name("test-layer"); + LayerCreationArgs args = + LayerCreationArgs(test->mFlinger.mFlinger.get(), client, name, + LayerProperties::WIDTH, LayerProperties::HEIGHT, + LayerProperties::LAYER_FLAGS, LayerMetadata()); + args.textureName = test->mFlinger.mutableTexturePool().back(); + return new BufferQueueLayer(args); }); LayerProperties::setupLayerState(test, layer); -- cgit v1.2.3-59-g8ed1b From 321e83c9d5201c36e26a1c42d3fd7e0993efab78 Mon Sep 17 00:00:00 2001 From: Robert Carr Date: Mon, 19 Aug 2019 15:49:30 -0700 Subject: BLAST: Handle detached layers. detachChildren and mLayerDetached were implemented to avoid geometry updates to layers in the cases of animation. For BufferQueue layers buffers are still consumed as normal. This is useful as otherwise the client could get hung inevitably waiting on a buffer to return. We recreate this semantic for BufferState even though it is a little in-consistent. detachChildren is shortly slated for removal by the hierarchy mirroring work so we don't need to worry about it too much. Bug: 135786080 Test: Manual Change-Id: I86c78fecc921218582918dda1ee7d8ee6c48f922 --- services/surfaceflinger/BufferStateLayer.cpp | 5 +++-- services/surfaceflinger/Layer.cpp | 9 +++++++++ 2 files changed, 12 insertions(+), 2 deletions(-) (limited to 'services/surfaceflinger/Layer.cpp') diff --git a/services/surfaceflinger/BufferStateLayer.cpp b/services/surfaceflinger/BufferStateLayer.cpp index 30fdbe14e8..fa4539ab91 100644 --- a/services/surfaceflinger/BufferStateLayer.cpp +++ b/services/surfaceflinger/BufferStateLayer.cpp @@ -125,9 +125,10 @@ bool BufferStateLayer::shouldPresentNow(nsecs_t /*expectedPresentTime*/) const { bool BufferStateLayer::willPresentCurrentTransaction() const { // Returns true if the most recent Transaction applied to CurrentState will be presented. - return getSidebandStreamChanged() || getAutoRefresh() || + return (getSidebandStreamChanged() || getAutoRefresh() || (mCurrentState.modified && - (mCurrentState.buffer != nullptr || mCurrentState.bgColorLayer != nullptr)); + (mCurrentState.buffer != nullptr || mCurrentState.bgColorLayer != nullptr))) && + !mLayerDetached; } void BufferStateLayer::pushPendingState() { diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp index 079bc66303..2efa23e2eb 100644 --- a/services/surfaceflinger/Layer.cpp +++ b/services/surfaceflinger/Layer.cpp @@ -780,6 +780,15 @@ uint32_t Layer::doTransaction(uint32_t flags) { ATRACE_CALL(); if (mLayerDetached) { + // Ensure BLAST buffer callbacks are processed. + // detachChildren and mLayerDetached were implemented to avoid geometry updates + // to layers in the cases of animation. For BufferQueue layers buffers are still + // consumed as normal. This is useful as otherwise the client could get hung + // inevitably waiting on a buffer to return. We recreate this semantic for BufferQueue + // even though it is a little consistent. detachChildren is shortly slated for removal + // by the hierarchy mirroring work so we don't need to worry about it too much. + mDrawingState.callbackHandles = mCurrentState.callbackHandles; + mCurrentState.callbackHandles = {}; return flags; } -- cgit v1.2.3-59-g8ed1b From 74b03178292a8fd1e514b8b53d425e8d9c739319 Mon Sep 17 00:00:00 2001 From: chaviw Date: Mon, 19 Aug 2019 11:09:03 -0700 Subject: [Mirror Layers] Added functions to update mirrored layers info (2/4) Added updateMirrorInfo and updateBufferInfoFromClone to ensure the state and buffer of the clones are updated properly. updateMirrorInfo is called when commitTransaction is called to update the drawing state, children, and relatives. updateBufferInfoFromClone is called in handlePageFlip after the real layer calls latchBuffer to ensure the cloned layer gets the updated buffer and buffer info. Test: No mirror request yet so everything runs normally Bug: 131622422 Change-Id: Ic2b1f66cab98175dbdccf90f2f8310c7f19d8cff --- services/surfaceflinger/BufferLayer.cpp | 35 ++++++++- services/surfaceflinger/BufferLayer.h | 4 ++ services/surfaceflinger/BufferQueueLayer.h | 2 - services/surfaceflinger/BufferStateLayer.h | 1 - services/surfaceflinger/Layer.cpp | 112 +++++++++++++++++++++++++++++ services/surfaceflinger/Layer.h | 22 +++++- services/surfaceflinger/SurfaceFlinger.cpp | 3 + 7 files changed, 170 insertions(+), 9 deletions(-) (limited to 'services/surfaceflinger/Layer.cpp') diff --git a/services/surfaceflinger/BufferLayer.cpp b/services/surfaceflinger/BufferLayer.cpp index d189846dd5..b500ad3eee 100644 --- a/services/surfaceflinger/BufferLayer.cpp +++ b/services/surfaceflinger/BufferLayer.cpp @@ -295,7 +295,7 @@ bool BufferLayer::onPostComposition(const std::optional& displayId, const CompositorTiming& compositorTiming) { // mFrameLatencyNeeded is true when a new frame was latched for the // composition. - if (!mFrameLatencyNeeded) return false; + if (!mBufferInfo.mFrameLatencyNeeded) return false; // Update mFrameEventHistory. { @@ -337,7 +337,7 @@ bool BufferLayer::onPostComposition(const std::optional& displayId, } mFrameTracker.advanceFrame(); - mFrameLatencyNeeded = false; + mBufferInfo.mFrameLatencyNeeded = false; return true; } @@ -401,7 +401,7 @@ bool BufferLayer::latchBuffer(bool& recomputeVisibleRegions, nsecs_t latchTime, gatherBufferInfo(); mRefreshPending = true; - mFrameLatencyNeeded = true; + mBufferInfo.mFrameLatencyNeeded = true; if (oldBufferInfo.mBuffer == nullptr) { // the first time we receive a buffer, we need to trigger a // geometry invalidation. @@ -735,6 +735,35 @@ void BufferLayer::setInitialValuesForClone(const sp& clonedFrom) { mPremultipliedAlpha = bufferClonedFrom->mPremultipliedAlpha; mPotentialCursor = bufferClonedFrom->mPotentialCursor; mProtectedByApp = bufferClonedFrom->mProtectedByApp; + + updateCloneBufferInfo(); +} + +void BufferLayer::updateCloneBufferInfo() { + if (!isClone() || !isClonedFromAlive()) { + return; + } + + sp clonedFrom = static_cast(getClonedFrom().get()); + mBufferInfo = clonedFrom->mBufferInfo; + mSidebandStream = clonedFrom->mSidebandStream; + surfaceDamageRegion = clonedFrom->surfaceDamageRegion; + mCurrentFrameNumber = clonedFrom->mCurrentFrameNumber.load(); + mPreviousFrameNumber = clonedFrom->mPreviousFrameNumber; + + // After buffer info is updated, the drawingState from the real layer needs to be copied into + // the cloned. This is because some properties of drawingState can change when latchBuffer is + // called. However, copying the drawingState would also overwrite the cloned layer's relatives. + // Therefore, temporarily store the relatives so they can be set in the cloned drawingState + // again. + wp tmpZOrderRelativeOf = mDrawingState.zOrderRelativeOf; + SortedVector> tmpZOrderRelatives = mDrawingState.zOrderRelatives; + mDrawingState = clonedFrom->mDrawingState; + // TODO: (b/140756730) Ignore input for now since InputDispatcher doesn't support multiple + // InputWindows per client token yet. + mDrawingState.inputInfo.token = nullptr; + mDrawingState.zOrderRelativeOf = tmpZOrderRelativeOf; + mDrawingState.zOrderRelatives = tmpZOrderRelatives; } } // namespace android diff --git a/services/surfaceflinger/BufferLayer.h b/services/surfaceflinger/BufferLayer.h index b2c06183a6..656ba12a19 100644 --- a/services/surfaceflinger/BufferLayer.h +++ b/services/surfaceflinger/BufferLayer.h @@ -165,6 +165,8 @@ protected: sp mBuffer; int mBufferSlot{BufferQueue::INVALID_BUFFER_SLOT}; + + bool mFrameLatencyNeeded{false}; }; BufferInfo mBufferInfo; @@ -195,6 +197,8 @@ protected: ui::Dataspace translateDataspace(ui::Dataspace dataspace); void setInitialValuesForClone(const sp& clonedFrom); + void updateCloneBufferInfo() override; + uint64_t mPreviousFrameNumber = 0; private: // Returns true if this layer requires filtering diff --git a/services/surfaceflinger/BufferQueueLayer.h b/services/surfaceflinger/BufferQueueLayer.h index 36dff156e1..f3e8a19a7d 100644 --- a/services/surfaceflinger/BufferQueueLayer.h +++ b/services/surfaceflinger/BufferQueueLayer.h @@ -111,8 +111,6 @@ private: PixelFormat mFormat{PIXEL_FORMAT_NONE}; - // Only accessed on the main thread. - uint64_t mPreviousFrameNumber{0}; bool mUpdateTexImageFailed{false}; uint64_t mPreviousBufferId = 0; diff --git a/services/surfaceflinger/BufferStateLayer.h b/services/surfaceflinger/BufferStateLayer.h index e951ccf97a..3dfe76cf9f 100644 --- a/services/surfaceflinger/BufferStateLayer.h +++ b/services/surfaceflinger/BufferStateLayer.h @@ -143,7 +143,6 @@ private: sp mPreviousReleaseFence; uint64_t mPreviousBufferId = 0; - uint64_t mPreviousFrameNumber = 0; uint64_t mPreviousReleasedFrameNumber = 0; mutable bool mCurrentStateModified = false; diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp index 079bc66303..f017ca07cf 100644 --- a/services/surfaceflinger/Layer.cpp +++ b/services/surfaceflinger/Layer.cpp @@ -2025,6 +2025,118 @@ void Layer::setInitialValuesForClone(const sp& clonedFrom) { // InputWindows per client token yet. mDrawingState.inputInfo.token = nullptr; } + +void Layer::updateMirrorInfo() { + if (mClonedChild == nullptr || !mClonedChild->isClonedFromAlive()) { + // If mClonedChild is null, there is nothing to mirror. If isClonedFromAlive returns false, + // it means that there is a clone, but the layer it was cloned from has been destroyed. In + // that case, we want to delete the reference to the clone since we want it to get + // destroyed. The root, this layer, will still be around since the client can continue + // to hold a reference, but no cloned layers will be displayed. + mClonedChild = nullptr; + return; + } + + std::map, sp> clonedLayersMap; + // If the real layer exists and is in current state, add the clone as a child of the root. + // There's no need to remove from drawingState when the layer is offscreen since currentState is + // copied to drawingState for the root layer. So the clonedChild is always removed from + // drawingState and then needs to be added back each traversal. + if (!mClonedChild->getClonedFrom()->isRemovedFromCurrentState()) { + addChildToDrawing(mClonedChild); + } + + mClonedChild->updateClonedDrawingState(clonedLayersMap); + mClonedChild->updateClonedChildren(this, clonedLayersMap); + mClonedChild->updateClonedRelatives(clonedLayersMap); +} + +void Layer::updateClonedDrawingState(std::map, sp>& clonedLayersMap) { + // If the layer the clone was cloned from is alive, copy the content of the drawingState + // to the clone. If the real layer is no longer alive, continue traversing the children + // since we may be able to pull out other children that are still alive. + if (isClonedFromAlive()) { + sp clonedFrom = getClonedFrom(); + mDrawingState = clonedFrom->mDrawingState; + // TODO: (b/140756730) Ignore input for now since InputDispatcher doesn't support multiple + // InputWindows per client token yet. + mDrawingState.inputInfo.token = nullptr; + clonedLayersMap.emplace(clonedFrom, this); + } + + // The clone layer may have children in drawingState since they may have been created and + // added from a previous request to updateMirorInfo. This is to ensure we don't recreate clones + // that already exist, since we can just re-use them. + // The drawingChildren will not get overwritten by the currentChildren since the clones are + // not updated in the regular traversal. They are skipped since the root will lose the + // reference to them when it copies its currentChildren to drawing. + for (sp& child : mDrawingChildren) { + child->updateClonedDrawingState(clonedLayersMap); + } +} + +void Layer::updateClonedChildren(const sp& mirrorRoot, + std::map, sp>& clonedLayersMap) { + mDrawingChildren.clear(); + + if (!isClonedFromAlive()) { + return; + } + + sp clonedFrom = getClonedFrom(); + for (sp& child : clonedFrom->mDrawingChildren) { + if (child == mirrorRoot) { + // This is to avoid cyclical mirroring. + continue; + } + sp clonedChild = clonedLayersMap[child]; + if (clonedChild == nullptr) { + clonedChild = child->createClone(); + clonedLayersMap[child] = clonedChild; + } + addChildToDrawing(clonedChild); + clonedChild->updateClonedChildren(mirrorRoot, clonedLayersMap); + } +} + +void Layer::updateClonedRelatives(std::map, sp> clonedLayersMap) { + mDrawingState.zOrderRelativeOf = nullptr; + mDrawingState.zOrderRelatives.clear(); + + if (!isClonedFromAlive()) { + return; + } + + sp clonedFrom = getClonedFrom(); + for (wp& relativeWeak : clonedFrom->mDrawingState.zOrderRelatives) { + sp relative = relativeWeak.promote(); + auto clonedRelative = clonedLayersMap[relative]; + if (clonedRelative != nullptr) { + mDrawingState.zOrderRelatives.add(clonedRelative); + } + } + + // Check if the relativeLayer for the real layer is part of the cloned hierarchy. + // It's possible that the layer it's relative to is outside the requested cloned hierarchy. + // In that case, we treat the layer as if the relativeOf has been removed. This way, it will + // still traverse the children, but the layer with the missing relativeOf will not be shown + // on screen. + sp relativeOf = clonedFrom->mDrawingState.zOrderRelativeOf.promote(); + sp clonedRelativeOf = clonedLayersMap[relativeOf]; + if (clonedRelativeOf != nullptr) { + mDrawingState.zOrderRelativeOf = clonedRelativeOf; + } + + for (sp& child : mDrawingChildren) { + child->updateClonedRelatives(clonedLayersMap); + } +} + +void Layer::addChildToDrawing(const sp& layer) { + mDrawingChildren.add(layer); + layer->mDrawingParent = this; +} + // --------------------------------------------------------------------------- }; // namespace android diff --git a/services/surfaceflinger/Layer.h b/services/surfaceflinger/Layer.h index 610df25637..3023cf5df3 100644 --- a/services/surfaceflinger/Layer.h +++ b/services/surfaceflinger/Layer.h @@ -468,13 +468,30 @@ public: virtual Rect getCrop(const Layer::State& s) const { return s.crop_legacy; } virtual bool needsFiltering(const sp&) const { return false; } -protected: + // This layer is not a clone, but it's the parent to the cloned hierarchy. The + // variable mClonedChild represents the top layer that will be cloned so this + // layer will be the parent of mClonedChild. + // The layers in the cloned hierarchy will match the lifetime of the real layers. That is + // if the real layer is destroyed, then the clone layer will also be destroyed. + sp mClonedChild; + virtual sp createClone() = 0; + void updateMirrorInfo(); + virtual void updateCloneBufferInfo(){}; + +protected: sp getClonedFrom() { return mClonedFrom != nullptr ? mClonedFrom.promote() : nullptr; } + bool isClone() { return mClonedFrom != nullptr; } + bool isClonedFromAlive() { return getClonedFrom() != nullptr; } - bool isClone() { return getClonedFrom() != nullptr; } virtual void setInitialValuesForClone(const sp& clonedFrom); + void updateClonedDrawingState(std::map, sp>& clonedLayersMap); + void updateClonedChildren(const sp& mirrorRoot, + std::map, sp>& clonedLayersMap); + void updateClonedRelatives(std::map, sp> clonedLayersMap); + void addChildToDrawing(const sp& layer); + public: /* * compositionengine::LayerFE overrides @@ -838,7 +855,6 @@ protected: // We encode unset as -1. int32_t mOverrideScalingMode{-1}; std::atomic mCurrentFrameNumber{0}; - bool mFrameLatencyNeeded{false}; // Whether filtering is needed b/c of the drawingstate bool mNeedsFiltering{false}; diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp index 86997477b3..86e73c2481 100644 --- a/services/surfaceflinger/SurfaceFlinger.cpp +++ b/services/surfaceflinger/SurfaceFlinger.cpp @@ -2600,6 +2600,7 @@ void SurfaceFlinger::commitTransactionLocked() { }); commitOffscreenLayers(); + mDrawingState.traverseInZOrder([&](Layer* layer) { layer->updateMirrorInfo(); }); } void SurfaceFlinger::withTracingLock(std::function lockedOperation) { @@ -2718,6 +2719,8 @@ bool SurfaceFlinger::handlePageFlip() mBootStage = BootStage::BOOTANIMATION; } + mDrawingState.traverseInZOrder([&](Layer* layer) { layer->updateCloneBufferInfo(); }); + // Only continue with the refresh if there is actually new work to do return !mLayersWithQueuedFrames.empty() && newDataLatched; } -- cgit v1.2.3-59-g8ed1b From bdb8b8043d0deed732182eca962657b52ccff6f3 Mon Sep 17 00:00:00 2001 From: chaviw Date: Mon, 14 Oct 2019 09:17:12 -0700 Subject: Set isRelativeOf flag when calling setZOrderRelativeOf The current code sets the isRelativeFlag to true when setRelativeLayer is called and false when setLayer is called. However, those two requests are only coming from client requests. There are places where zRelativeOf is removed for other reasons. Therefore, set isRelativeOf flag when calling setZOrderRelativeOf based on whether relativeOf is null or not. This will ensure it covers all places that zRelativeOf is updated. Fixes: 142534793 Test: RelativeZTest.LayerAndRelativeRemoved Change-Id: I338592f2e2e88598f2d8a4c0957b551da310a4bf --- services/surfaceflinger/Layer.cpp | 4 +- services/surfaceflinger/tests/RelativeZ_test.cpp | 59 ++++++++++++++++++++++++ 2 files changed, 61 insertions(+), 2 deletions(-) (limited to 'services/surfaceflinger/Layer.cpp') diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp index 6a45625c89..7065460b2c 100644 --- a/services/surfaceflinger/Layer.cpp +++ b/services/surfaceflinger/Layer.cpp @@ -908,7 +908,6 @@ bool Layer::setLayer(int32_t z) { } setZOrderRelativeOf(nullptr); } - mCurrentState.isRelativeOf = false; setTransactionFlags(eTransactionNeeded); return true; } @@ -931,6 +930,8 @@ void Layer::setZOrderRelativeOf(const wp& relativeOf) { mCurrentState.zOrderRelativeOf = relativeOf; mCurrentState.sequence++; mCurrentState.modified = true; + mCurrentState.isRelativeOf = relativeOf != nullptr; + setTransactionFlags(eTransactionNeeded); } @@ -952,7 +953,6 @@ bool Layer::setRelativeLayer(const sp& relativeToHandle, int32_t relati mCurrentState.sequence++; mCurrentState.modified = true; mCurrentState.z = relativeZ; - mCurrentState.isRelativeOf = true; auto oldZOrderRelativeOf = mCurrentState.zOrderRelativeOf.promote(); if (oldZOrderRelativeOf != nullptr) { diff --git a/services/surfaceflinger/tests/RelativeZ_test.cpp b/services/surfaceflinger/tests/RelativeZ_test.cpp index 8549db2e0b..8c56d27e8a 100644 --- a/services/surfaceflinger/tests/RelativeZ_test.cpp +++ b/services/surfaceflinger/tests/RelativeZ_test.cpp @@ -144,4 +144,63 @@ TEST_F(RelativeZTest, LayerRemovedOffscreenRelativeParent) { sc->checkPixel(1, 1, Color::GREEN.r, Color::GREEN.g, Color::GREEN.b); } } + +TEST_F(RelativeZTest, LayerAndRelativeRemoved) { + std::unique_ptr sc; + + // Background layer (RED) + // Foregroud layer (GREEN) + // Child layer (BLUE) (relative to relativeToLayer layer) + // Relative layer (WHITE) + sp childLayer = + createColorLayer("Child layer", Color::BLUE, mForegroundLayer.get()); + sp relativeToLayer = + createColorLayer("Relative layer", Color::WHITE, mForegroundLayer.get()); + + Transaction{} + .setRelativeLayer(childLayer, relativeToLayer->getHandle(), 1) + .show(childLayer) + .show(relativeToLayer) + .apply(); + + { + // The childLayer should be in front of relativeToLayer. + ScreenCapture::captureScreen(&sc); + sc->checkPixel(1, 1, Color::BLUE.r, Color::BLUE.g, Color::BLUE.b); + } + + // Remove layer that childLayer is relative to + // Background layer (RED) + // Foregroud layer (GREEN) + // Child layer (BLUE) (relative to relativeToLayer layer) + Transaction{}.reparent(relativeToLayer, nullptr).apply(); + relativeToLayer = 0; + + { + // The child layer is relative to an deleted layer so it won't be drawn. + ScreenCapture::captureScreen(&sc); + sc->checkPixel(1, 1, Color::GREEN.r, Color::GREEN.g, Color::GREEN.b); + } + + // Background layer (RED) + // Foregroud layer (GREEN) + Transaction{}.reparent(childLayer, nullptr).apply(); + + { + // The child layer is offscreen, so it won't be drawn. + ScreenCapture::captureScreen(&sc); + sc->checkPixel(1, 1, Color::GREEN.r, Color::GREEN.g, Color::GREEN.b); + } + + // Background layer (RED) + // Foregroud layer (GREEN) + // Child layer (BLUE) + Transaction{}.reparent(childLayer, mForegroundLayer->getHandle()).apply(); + + { + // The relative z info for child layer should be reset, leaving the child layer on top. + ScreenCapture::captureScreen(&sc); + sc->checkPixel(1, 1, Color::BLUE.r, Color::BLUE.g, Color::BLUE.b); + } +} } // namespace android -- cgit v1.2.3-59-g8ed1b From 87a07e42dd60a748cbf82be7e82b07b0326ea469 Mon Sep 17 00:00:00 2001 From: Dominik Laskowski Date: Thu, 10 Oct 2019 20:38:02 -0700 Subject: SF: Use std::string for layer names Bug: 130554049 Test: Build Change-Id: Id083a85fcb838da4138c39a55b12cf10ff0cdddb --- services/surfaceflinger/BufferLayer.cpp | 2 +- services/surfaceflinger/BufferQueueLayer.cpp | 16 ++-- services/surfaceflinger/BufferStateLayer.cpp | 8 +- services/surfaceflinger/ColorLayer.cpp | 8 +- services/surfaceflinger/ContainerLayer.cpp | 5 +- services/surfaceflinger/EventLog/EventLog.cpp | 27 +++--- services/surfaceflinger/EventLog/EventLog.h | 38 +++------ services/surfaceflinger/FrameTracker.cpp | 5 +- services/surfaceflinger/FrameTracker.h | 21 ++--- services/surfaceflinger/Layer.cpp | 45 +++++----- services/surfaceflinger/Layer.h | 11 ++- services/surfaceflinger/LayerRejecter.cpp | 7 +- services/surfaceflinger/LayerRejecter.h | 37 ++++---- services/surfaceflinger/RegionSamplingThread.cpp | 2 +- services/surfaceflinger/SurfaceFlinger.cpp | 98 +++++++++++----------- services/surfaceflinger/SurfaceFlinger.h | 14 ++-- services/surfaceflinger/SurfaceInterceptor.cpp | 6 +- services/surfaceflinger/SurfaceInterceptor.h | 1 - .../tests/unittests/CompositionTest.cpp | 10 +-- 19 files changed, 159 insertions(+), 202 deletions(-) (limited to 'services/surfaceflinger/Layer.cpp') diff --git a/services/surfaceflinger/BufferLayer.cpp b/services/surfaceflinger/BufferLayer.cpp index b500ad3eee..603a9f7f70 100644 --- a/services/surfaceflinger/BufferLayer.cpp +++ b/services/surfaceflinger/BufferLayer.cpp @@ -61,7 +61,7 @@ BufferLayer::BufferLayer(const LayerCreationArgs& args) mTextureName(args.textureName), mCompositionLayer{mFlinger->getCompositionEngine().createLayer( compositionengine::LayerCreationArgs{this})} { - ALOGV("Creating Layer %s", args.name.string()); + ALOGV("Creating Layer %s", getDebugName()); mPremultipliedAlpha = !(args.flags & ISurfaceComposerClient::eNonPremultiplied); diff --git a/services/surfaceflinger/BufferQueueLayer.cpp b/services/surfaceflinger/BufferQueueLayer.cpp index d80a70e4c6..cd0d87cb82 100644 --- a/services/surfaceflinger/BufferQueueLayer.cpp +++ b/services/surfaceflinger/BufferQueueLayer.cpp @@ -62,7 +62,7 @@ std::vector BufferQueueLayer::getOccupancyHistory(boo std::vector history; status_t result = mConsumer->getOccupancyHistory(forceFlush, &history); if (result != NO_ERROR) { - ALOGW("[%s] Failed to obtain occupancy history (%d)", mName.string(), result); + ALOGW("[%s] Failed to obtain occupancy history (%d)", getDebugName(), result); return {}; } return history; @@ -110,7 +110,7 @@ bool BufferQueueLayer::shouldPresentNow(nsecs_t expectedPresentTime) const { ALOGW_IF(!isPlausible, "[%s] Timestamp %" PRId64 " seems implausible " "relative to expectedPresent %" PRId64, - mName.string(), addedTime, expectedPresentTime); + getDebugName(), addedTime, expectedPresentTime); const bool isDue = addedTime < expectedPresentTime; return isDue || !isPlausible; @@ -225,7 +225,7 @@ status_t BufferQueueLayer::updateTexImage(bool& recomputeVisibleRegions, nsecs_t bool queuedBuffer = false; const int32_t layerID = getSequence(); LayerRejecter r(mDrawingState, getCurrentState(), recomputeVisibleRegions, - getProducerStickyTransform() != 0, mName.string(), mOverrideScalingMode, + getProducerStickyTransform() != 0, mName, mOverrideScalingMode, getTransformToDisplayInverse()); if (isRemovedFromCurrentState()) { @@ -398,7 +398,7 @@ void BufferQueueLayer::onFrameAvailable(const BufferItem& item) { while (item.mFrameNumber != mLastFrameNumberReceived + 1) { status_t result = mQueueItemCondition.waitRelative(mQueueItemLock, ms2ns(500)); if (result != NO_ERROR) { - ALOGE("[%s] Timed out waiting on callback", mName.string()); + ALOGE("[%s] Timed out waiting on callback", getDebugName()); } } @@ -426,7 +426,7 @@ void BufferQueueLayer::onFrameReplaced(const BufferItem& item) { while (item.mFrameNumber != mLastFrameNumberReceived + 1) { status_t result = mQueueItemCondition.waitRelative(mQueueItemLock, ms2ns(500)); if (result != NO_ERROR) { - ALOGE("[%s] Timed out waiting on callback", mName.string()); + ALOGE("[%s] Timed out waiting on callback", getDebugName()); } } @@ -464,7 +464,7 @@ void BufferQueueLayer::onFirstRef() { mConsumer = new BufferLayerConsumer(consumer, mFlinger->getRenderEngine(), mTextureName, this); mConsumer->setConsumerUsageBits(getEffectiveUsage(0)); mConsumer->setContentsChangedListener(this); - mConsumer->setName(mName); + mConsumer->setName(String8(mName.data(), mName.size())); // BufferQueueCore::mMaxDequeuedBufferCount is default to 1 if (!mFlinger->isLayerTripleBufferingDisabled()) { @@ -527,9 +527,7 @@ void BufferQueueLayer::gatherBufferInfo() { } sp BufferQueueLayer::createClone() { - const String8 name = mName + " (Mirror)"; - LayerCreationArgs args = - LayerCreationArgs(mFlinger.get(), nullptr, name, 0, 0, 0, LayerMetadata()); + LayerCreationArgs args(mFlinger.get(), nullptr, mName + " (Mirror)", 0, 0, 0, LayerMetadata()); args.textureName = mTextureName; sp layer = mFlinger->getFactory().createBufferQueueLayer(args); layer->setInitialValuesForClone(this); diff --git a/services/surfaceflinger/BufferStateLayer.cpp b/services/surfaceflinger/BufferStateLayer.cpp index 75fc0e9c06..6fe89c41b5 100644 --- a/services/surfaceflinger/BufferStateLayer.cpp +++ b/services/surfaceflinger/BufferStateLayer.cpp @@ -136,7 +136,7 @@ void BufferStateLayer::pushPendingState() { return; } mPendingStates.push_back(mCurrentState); - ATRACE_INT(mTransactionName.string(), mPendingStates.size()); + ATRACE_INT(mTransactionName.c_str(), mPendingStates.size()); } bool BufferStateLayer::applyPendingStates(Layer::State* stateToCommit) { @@ -479,7 +479,7 @@ status_t BufferStateLayer::updateTexImage(bool& /*recomputeVisibleRegions*/, nse (s.active.w != bufferWidth || s.active.h != bufferHeight)) { ALOGE("[%s] rejecting buffer: " "bufferWidth=%d, bufferHeight=%d, front.active.{w=%d, h=%d}", - mName.string(), bufferWidth, bufferHeight, s.active.w, s.active.h); + getDebugName(), bufferWidth, bufferHeight, s.active.w, s.active.h); mFlinger->mTimeStats->removeTimeRecord(layerID, mFrameNumber); return BAD_VALUE; } @@ -669,9 +669,7 @@ Rect BufferStateLayer::computeCrop(const State& s) { } sp BufferStateLayer::createClone() { - const String8 name = mName + " (Mirror)"; - LayerCreationArgs args = - LayerCreationArgs(mFlinger.get(), nullptr, name, 0, 0, 0, LayerMetadata()); + LayerCreationArgs args(mFlinger.get(), nullptr, mName + " (Mirror)", 0, 0, 0, LayerMetadata()); args.textureName = mTextureName; sp layer = mFlinger->getFactory().createBufferStateLayer(args); layer->mHwcSlotGenerator = mHwcSlotGenerator; diff --git a/services/surfaceflinger/ColorLayer.cpp b/services/surfaceflinger/ColorLayer.cpp index 172d44556a..8bfa569eeb 100644 --- a/services/surfaceflinger/ColorLayer.cpp +++ b/services/surfaceflinger/ColorLayer.cpp @@ -108,13 +108,11 @@ ui::Dataspace ColorLayer::getDataSpace() const { } sp ColorLayer::createClone() { - String8 name = mName + " (Mirror)"; sp layer = mFlinger->getFactory().createColorLayer( - LayerCreationArgs(mFlinger.get(), nullptr, name, 0, 0, 0, LayerMetadata())); + LayerCreationArgs(mFlinger.get(), nullptr, mName + " (Mirror)", 0, 0, 0, + LayerMetadata())); layer->setInitialValuesForClone(this); return layer; } -// --------------------------------------------------------------------------- - -}; // namespace android +} // namespace android diff --git a/services/surfaceflinger/ContainerLayer.cpp b/services/surfaceflinger/ContainerLayer.cpp index e58e6f425e..ab664be5e2 100644 --- a/services/surfaceflinger/ContainerLayer.cpp +++ b/services/surfaceflinger/ContainerLayer.cpp @@ -31,10 +31,11 @@ bool ContainerLayer::isVisible() const { } sp ContainerLayer::createClone() { - String8 name = mName + " (Mirror)"; sp layer = mFlinger->getFactory().createContainerLayer( - LayerCreationArgs(mFlinger.get(), nullptr, name, 0, 0, 0, LayerMetadata())); + LayerCreationArgs(mFlinger.get(), nullptr, mName + " (Mirror)", 0, 0, 0, + LayerMetadata())); layer->setInitialValuesForClone(this); return layer; } + } // namespace android diff --git a/services/surfaceflinger/EventLog/EventLog.cpp b/services/surfaceflinger/EventLog/EventLog.cpp index 365a0bd868..a532fc130f 100644 --- a/services/surfaceflinger/EventLog/EventLog.cpp +++ b/services/surfaceflinger/EventLog/EventLog.cpp @@ -17,13 +17,10 @@ #include #include #include -#include #include "EventLog.h" -// --------------------------------------------------------------------------- namespace android { -// --------------------------------------------------------------------------- ANDROID_SINGLETON_STATIC_INSTANCE(EventLog) @@ -31,11 +28,11 @@ ANDROID_SINGLETON_STATIC_INSTANCE(EventLog) EventLog::EventLog() { } -void EventLog::doLogFrameDurations(const String8& window, - const int32_t* durations, size_t numDurations) { +void EventLog::doLogFrameDurations(const std::string_view& name, const int32_t* durations, + size_t numDurations) { EventLog::TagBuffer buffer(LOGTAG_SF_FRAME_DUR); buffer.startList(1 + numDurations); - buffer.writeString8(window); + buffer.writeString(name); for (size_t i = 0; i < numDurations; i++) { buffer.writeInt32(durations[i]); } @@ -43,10 +40,9 @@ void EventLog::doLogFrameDurations(const String8& window, buffer.log(); } -void EventLog::logFrameDurations(const String8& window, - const int32_t* durations, size_t numDurations) { - EventLog::getInstance().doLogFrameDurations(window, durations, - numDurations); +void EventLog::logFrameDurations(const std::string_view& name, const int32_t* durations, + size_t numDurations) { + EventLog::getInstance().doLogFrameDurations(name, durations, numDurations); } // --------------------------------------------------------------------------- @@ -113,9 +109,9 @@ void EventLog::TagBuffer::writeInt64(int64_t value) { mPos += needed; } -void EventLog::TagBuffer::writeString8(const String8& value) { +void EventLog::TagBuffer::writeString(const std::string_view& value) { if (mOverflow) return; - const int32_t stringLen = value.length(); + const size_t stringLen = value.length(); const size_t needed = 1 + sizeof(int32_t) + stringLen; if (mPos + needed > STORAGE_MAX_SIZE) { mOverflow = true; @@ -123,11 +119,8 @@ void EventLog::TagBuffer::writeString8(const String8& value) { } mStorage[mPos + 0] = EVENT_TYPE_STRING; memcpy(&mStorage[mPos + 1], &stringLen, sizeof(int32_t)); - memcpy(&mStorage[mPos + 5], value.string(), stringLen); + memcpy(&mStorage[mPos + 5], value.data(), stringLen); mPos += needed; } -// --------------------------------------------------------------------------- -}// namespace android - -// --------------------------------------------------------------------------- +} // namespace android diff --git a/services/surfaceflinger/EventLog/EventLog.h b/services/surfaceflinger/EventLog/EventLog.h index efc5d70cd3..ee3587ef8a 100644 --- a/services/surfaceflinger/EventLog/EventLog.h +++ b/services/surfaceflinger/EventLog/EventLog.h @@ -14,24 +14,21 @@ * limitations under the License. */ -#include +#pragma once + #include #include -#ifndef ANDROID_SF_EVENTLOG_H -#define ANDROID_SF_EVENTLOG_H +#include +#include -// --------------------------------------------------------------------------- namespace android { -// --------------------------------------------------------------------------- - -class String8; class EventLog : public Singleton { public: - static void logFrameDurations(const String8& window, - const int32_t* durations, size_t numDurations); + static void logFrameDurations(const std::string_view& name, const int32_t* durations, + size_t numDurations); protected: EventLog(); @@ -54,18 +51,13 @@ private: public: explicit TagBuffer(int32_t tag); - // starts list of items void startList(int8_t count); - // terminates the list void endList(); - // write a 32-bit integer - void writeInt32(int32_t value); - // write a 64-bit integer - void writeInt64(int64_t value); - // write a C string - void writeString8(const String8& value); - // outputs the the buffer to the log + void writeInt32(int32_t); + void writeInt64(int64_t); + void writeString(const std::string_view&); + void log(); }; @@ -74,12 +66,8 @@ private: EventLog& operator =(const EventLog&); enum { LOGTAG_SF_FRAME_DUR = 60100 }; - void doLogFrameDurations(const String8& window, const int32_t* durations, - size_t numDurations); + void doLogFrameDurations(const std::string_view& name, const int32_t* durations, + size_t numDurations); }; -// --------------------------------------------------------------------------- -}// namespace android -// --------------------------------------------------------------------------- - -#endif /* ANDROID_SF_EVENTLOG_H */ +} // namespace android diff --git a/services/surfaceflinger/FrameTracker.cpp b/services/surfaceflinger/FrameTracker.cpp index f4cc49b851..a6e511e76e 100644 --- a/services/surfaceflinger/FrameTracker.cpp +++ b/services/surfaceflinger/FrameTracker.cpp @@ -21,7 +21,6 @@ #include #include -#include #include @@ -139,7 +138,7 @@ void FrameTracker::getStats(FrameStats* outStats) const { } } -void FrameTracker::logAndResetStats(const String8& name) { +void FrameTracker::logAndResetStats(const std::string_view& name) { Mutex::Autolock lock(mMutex); logStatsLocked(name); resetFrameCountersLocked(); @@ -217,7 +216,7 @@ void FrameTracker::resetFrameCountersLocked() { } } -void FrameTracker::logStatsLocked(const String8& name) const { +void FrameTracker::logStatsLocked(const std::string_view& name) const { for (int i = 0; i < NUM_FRAME_BUCKETS; i++) { if (mNumFrames[i] > 0) { EventLog::logFrameDurations(name, mNumFrames, NUM_FRAME_BUCKETS); diff --git a/services/surfaceflinger/FrameTracker.h b/services/surfaceflinger/FrameTracker.h index 555dcc1d1f..35382be1c0 100644 --- a/services/surfaceflinger/FrameTracker.h +++ b/services/surfaceflinger/FrameTracker.h @@ -14,20 +14,17 @@ * limitations under the License. */ -#ifndef ANDROID_FRAMETRACKER_H -#define ANDROID_FRAMETRACKER_H +#pragma once #include - -#include - #include -#include #include +#include -namespace android { +#include +#include -class String8; +namespace android { // FrameTracker tracks information about the most recently rendered frames. It // uses a circular buffer of frame records, and is *NOT* thread-safe - @@ -87,7 +84,7 @@ public: // logAndResetStats dumps the current statistics to the binary event log // and then resets the accumulated statistics to their initial values. - void logAndResetStats(const String8& name); + void logAndResetStats(const std::string_view& name); // dumpStats dump appends the current frame display time history to the result string. void dumpStats(std::string& result) const; @@ -123,7 +120,7 @@ private: void resetFrameCountersLocked(); // logStatsLocked dumps the current statistics to the binary event log. - void logStatsLocked(const String8& name) const; + void logStatsLocked(const std::string_view& name) const; // isFrameValidLocked returns true if the data for the given frame index is // valid and has all arrived (i.e. there are no oustanding fences). @@ -160,6 +157,4 @@ private: mutable Mutex mMutex; }; -} - -#endif // ANDROID_FRAMETRACKER_H +} // namespace android diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp index 6a45625c89..0c700a779f 100644 --- a/services/surfaceflinger/Layer.cpp +++ b/services/surfaceflinger/Layer.cpp @@ -83,8 +83,6 @@ Layer::Layer(const LayerCreationArgs& args) if (args.flags & ISurfaceComposerClient::eOpaque) layerFlags |= layer_state_t::eLayerOpaque; if (args.flags & ISurfaceComposerClient::eSecure) layerFlags |= layer_state_t::eLayerSecure; - mTransactionName = String8("TX - ") + mName; - mCurrentState.active_legacy.w = args.w; mCurrentState.active_legacy.h = args.h; mCurrentState.flags = layerFlags; @@ -137,11 +135,11 @@ Layer::~Layer() { } LayerCreationArgs::LayerCreationArgs(SurfaceFlinger* flinger, const sp& client, - const String8& name, uint32_t w, uint32_t h, uint32_t flags, + std::string name, uint32_t w, uint32_t h, uint32_t flags, LayerMetadata metadata) : flinger(flinger), client(client), - name(name), + name(std::move(name)), w(w), h(h), flags(flags), @@ -235,10 +233,6 @@ void Layer::addToCurrentState() { // set-up // --------------------------------------------------------------------------- -const String8& Layer::getName() const { - return mName; -} - bool Layer::getPremultipledAlpha() const { return mPremultipliedAlpha; } @@ -523,7 +517,7 @@ void Layer::latchCompositionState(compositionengine::LayerFECompositionState& co } const char* Layer::getDebugName() const { - return mName.string(); + return mName.c_str(); } // --------------------------------------------------------------------------- @@ -614,7 +608,7 @@ void Layer::pushPendingState() { if (mCurrentState.barrierLayer_legacy != nullptr && !isRemovedFromCurrentState()) { sp barrierLayer = mCurrentState.barrierLayer_legacy.promote(); if (barrierLayer == nullptr) { - ALOGE("[%s] Unable to promote barrier Layer.", mName.string()); + ALOGE("[%s] Unable to promote barrier Layer.", getDebugName()); // If we can't promote the layer we are intended to wait on, // then it is expired or otherwise invalid. Allow this transaction // to be applied as per normal (no synchronization). @@ -638,7 +632,7 @@ void Layer::pushPendingState() { mFlinger->setTransactionFlags(eTraversalNeeded); } mPendingStates.push_back(mCurrentState); - ATRACE_INT(mTransactionName.string(), mPendingStates.size()); + ATRACE_INT(mTransactionName.c_str(), mPendingStates.size()); } void Layer::popPendingState(State* stateToCommit) { @@ -646,7 +640,7 @@ void Layer::popPendingState(State* stateToCommit) { *stateToCommit = mPendingStates[0]; mPendingStates.removeAt(0); - ATRACE_INT(mTransactionName.string(), mPendingStates.size()); + ATRACE_INT(mTransactionName.c_str(), mPendingStates.size()); } bool Layer::applyPendingStates(State* stateToCommit) { @@ -657,7 +651,7 @@ bool Layer::applyPendingStates(State* stateToCommit) { // If we don't have a sync point for this, apply it anyway. It // will be visually wrong, but it should keep us from getting // into too much trouble. - ALOGE("[%s] No local sync point found", mName.string()); + ALOGE("[%s] No local sync point found", getDebugName()); popPendingState(stateToCommit); stateUpdateAvailable = true; continue; @@ -665,7 +659,7 @@ bool Layer::applyPendingStates(State* stateToCommit) { if (mRemoteSyncPoints.front()->getFrameNumber() != mPendingStates[0].frameNumber_legacy) { - ALOGE("[%s] Unexpected sync point frame number found", mName.string()); + ALOGE("[%s] Unexpected sync point frame number found", getDebugName()); // Signal our end of the sync point and then dispose of it mRemoteSyncPoints.front()->setTransactionApplied(); @@ -717,7 +711,7 @@ uint32_t Layer::doTransactionResize(uint32_t flags, State* stateToCommit) { " requested={ wh={%4u,%4u} }}\n" " drawing={ active ={ wh={%4u,%4u} crop={%4d,%4d,%4d,%4d} (%4d,%4d) }\n" " requested={ wh={%4u,%4u} }}\n", - this, getName().string(), getBufferTransform(), getEffectiveScalingMode(), + this, getName().c_str(), getBufferTransform(), getEffectiveScalingMode(), stateToCommit->active_legacy.w, stateToCommit->active_legacy.h, stateToCommit->crop_legacy.left, stateToCommit->crop_legacy.top, stateToCommit->crop_legacy.right, stateToCommit->crop_legacy.bottom, @@ -999,9 +993,10 @@ bool Layer::setBackgroundColor(const half3& color, float alpha, ui::Dataspace da if (!mCurrentState.bgColorLayer && alpha != 0) { // create background color layer if one does not yet exist uint32_t flags = ISurfaceComposerClient::eFXSurfaceColor; - const String8& name = mName + "BackgroundColorLayer"; + std::string name = mName + "BackgroundColorLayer"; mCurrentState.bgColorLayer = mFlinger->getFactory().createColorLayer( - LayerCreationArgs(mFlinger.get(), nullptr, name, 0, 0, flags, LayerMetadata())); + LayerCreationArgs(mFlinger.get(), nullptr, std::move(name), 0, 0, flags, + LayerMetadata())); // add to child list addChild(mCurrentState.bgColorLayer); @@ -1196,11 +1191,13 @@ void Layer::updateTransformHint(const sp& display) const { // TODO(marissaw): add new layer state info to layer debugging LayerDebugInfo Layer::getLayerDebugInfo() const { + using namespace std::string_literals; + LayerDebugInfo info; const State& ds = getDrawingState(); info.mName = getName(); sp parent = getParent(); - info.mParentName = (parent == nullptr ? std::string("none") : parent->getName().string()); + info.mParentName = parent ? parent->getName() : "none"s; info.mType = getType(); info.mTransparentRegion = ds.activeTransparentRegion_legacy; @@ -1267,12 +1264,12 @@ void Layer::miniDump(std::string& result, const sp& displayDevice std::string name; if (mName.length() > 77) { std::string shortened; - shortened.append(mName.string(), 36); + shortened.append(mName, 0, 36); shortened.append("[...]"); - shortened.append(mName.string() + (mName.length() - 36), 36); - name = shortened; + shortened.append(mName, mName.length() - 36); + name = std::move(shortened); } else { - name = std::string(mName.string(), mName.size()); + name = mName; } StringAppendF(&result, " %s\n", name.c_str()); @@ -1319,14 +1316,14 @@ void Layer::getFrameStats(FrameStats* outStats) const { } void Layer::dumpFrameEvents(std::string& result) { - StringAppendF(&result, "- Layer %s (%s, %p)\n", getName().string(), getType(), this); + StringAppendF(&result, "- Layer %s (%s, %p)\n", getName().c_str(), getType(), this); Mutex::Autolock lock(mFrameEventHistoryMutex); mFrameEventHistory.checkFencesForCompletion(); mFrameEventHistory.dump(result); } void Layer::dumpCallingUidPid(std::string& result) const { - StringAppendF(&result, "Layer %s (%s) pid:%d uid:%d\n", getName().string(), getType(), + StringAppendF(&result, "Layer %s (%s) pid:%d uid:%d\n", getName().c_str(), getType(), mCallingPid, mCallingUid); } diff --git a/services/surfaceflinger/Layer.h b/services/surfaceflinger/Layer.h index 3023cf5df3..ad81920dc9 100644 --- a/services/surfaceflinger/Layer.h +++ b/services/surfaceflinger/Layer.h @@ -34,7 +34,6 @@ #include #include #include -#include #include #include @@ -79,12 +78,12 @@ class SurfaceInterceptor; // --------------------------------------------------------------------------- struct LayerCreationArgs { - LayerCreationArgs(SurfaceFlinger* flinger, const sp& client, const String8& name, + LayerCreationArgs(SurfaceFlinger* flinger, const sp& client, std::string name, uint32_t w, uint32_t h, uint32_t flags, LayerMetadata metadata); SurfaceFlinger* flinger; const sp& client; - const String8& name; + std::string name; uint32_t w; uint32_t h; uint32_t flags; @@ -804,7 +803,7 @@ public: // Creates a new handle each time, so we only expect // this to be called once. sp getHandle(); - const String8& getName() const; + const std::string& getName() const { return mName; } virtual void notifyAvailableFrames(nsecs_t /*expectedPresentTime*/) {} virtual PixelFormat getPixelFormat() const { return PIXEL_FORMAT_NONE; } bool getPremultipledAlpha() const; @@ -820,8 +819,8 @@ protected: bool usingRelativeZ(LayerVector::StateSet stateSet) const; bool mPremultipliedAlpha{true}; - String8 mName; - String8 mTransactionName; // A cached version of "TX - " + mName for systraces + const std::string mName; + const std::string mTransactionName{"TX - " + mName}; bool mPrimaryDisplayOnly = false; diff --git a/services/surfaceflinger/LayerRejecter.cpp b/services/surfaceflinger/LayerRejecter.cpp index 8a221837ac..1a60f1ed08 100644 --- a/services/surfaceflinger/LayerRejecter.cpp +++ b/services/surfaceflinger/LayerRejecter.cpp @@ -24,7 +24,7 @@ namespace android { LayerRejecter::LayerRejecter(Layer::State& front, Layer::State& current, - bool& recomputeVisibleRegions, bool stickySet, const char* name, + bool& recomputeVisibleRegions, bool stickySet, const std::string& name, int32_t overrideScalingMode, bool transformToDisplayInverse) : mFront(front), mCurrent(current), @@ -90,7 +90,7 @@ bool LayerRejecter::reject(const sp& buf, const BufferItem& item) "(%4d,%4d) " "}\n" " requested_legacy={ wh={%4u,%4u} }}\n", - mName, bufWidth, bufHeight, item.mTransform, item.mScalingMode, + mName.c_str(), bufWidth, bufHeight, item.mTransform, item.mScalingMode, mFront.active_legacy.w, mFront.active_legacy.h, mFront.crop_legacy.left, mFront.crop_legacy.top, mFront.crop_legacy.right, mFront.crop_legacy.bottom, mFront.crop_legacy.getWidth(), mFront.crop_legacy.getHeight(), @@ -102,7 +102,8 @@ bool LayerRejecter::reject(const sp& buf, const BufferItem& item) // reject this buffer ALOGE("[%s] rejecting buffer: " "bufWidth=%d, bufHeight=%d, front.active_legacy.{w=%d, h=%d}", - mName, bufWidth, bufHeight, mFront.active_legacy.w, mFront.active_legacy.h); + mName.c_str(), bufWidth, bufHeight, mFront.active_legacy.w, + mFront.active_legacy.h); return true; } } diff --git a/services/surfaceflinger/LayerRejecter.h b/services/surfaceflinger/LayerRejecter.h index 1bd0c26dc6..fb5c750571 100644 --- a/services/surfaceflinger/LayerRejecter.h +++ b/services/surfaceflinger/LayerRejecter.h @@ -14,30 +14,29 @@ * limitations under the License. */ -#ifndef ANDROID_LAYER_REJECTER_H -#define ANDROID_LAYER_REJECTER_H +#pragma once #include "Layer.h" #include "BufferLayerConsumer.h" namespace android { - class LayerRejecter : public BufferLayerConsumer::BufferRejecter { - public: - LayerRejecter(Layer::State &front, Layer::State ¤t, bool &recomputeVisibleRegions, - bool stickySet, const char *name, int32_t overrideScalingMode, - bool transformToDisplayInverse); - virtual bool reject(const sp &buf, const BufferItem &item); +class LayerRejecter : public BufferLayerConsumer::BufferRejecter { +public: + LayerRejecter(Layer::State& front, Layer::State& current, bool& recomputeVisibleRegions, + bool stickySet, const std::string& name, int32_t overrideScalingMode, + bool transformToDisplayInverse); - private: - Layer::State &mFront; - Layer::State &mCurrent; - bool &mRecomputeVisibleRegions; - bool mStickyTransformSet; - const char *mName; - int32_t mOverrideScalingMode; - bool mTransformToDisplayInverse; - }; -} // namespace android + virtual bool reject(const sp&, const BufferItem&); -#endif // ANDROID_LAYER_REJECTER_H +private: + Layer::State& mFront; + Layer::State& mCurrent; + bool& mRecomputeVisibleRegions; + const bool mStickyTransformSet; + const std::string& mName; + const int32_t mOverrideScalingMode; + const bool mTransformToDisplayInverse; +}; + +} // namespace android diff --git a/services/surfaceflinger/RegionSamplingThread.cpp b/services/surfaceflinger/RegionSamplingThread.cpp index 1c1367c916..30027decfb 100644 --- a/services/surfaceflinger/RegionSamplingThread.cpp +++ b/services/surfaceflinger/RegionSamplingThread.cpp @@ -436,7 +436,7 @@ void RegionSamplingThread::captureSample() { } if (!intersectsAnyArea) return; - ALOGV("Traversing [%s] [%d, %d, %d, %d]", layer->getName().string(), bounds.left, + ALOGV("Traversing [%s] [%d, %d, %d, %d]", layer->getDebugName(), bounds.left, bounds.top, bounds.right, bounds.bottom); visitor(layer); }; diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp index 54e20659a7..0e33f10ab6 100644 --- a/services/surfaceflinger/SurfaceFlinger.cpp +++ b/services/surfaceflinger/SurfaceFlinger.cpp @@ -122,6 +122,8 @@ namespace android { +using namespace std::string_literals; + using namespace android::hardware::configstore; using namespace android::hardware::configstore::V1_0; using namespace android::sysprop; @@ -1911,8 +1913,7 @@ void SurfaceFlinger::postComposition() layer->onPostComposition(displayDevice->getId(), glCompositionDoneFenceTime, presentFenceTime, compositorTiming); if (frameLatched) { - recordBufferingStats(layer->getName().string(), - layer->getOccupancyHistory(false)); + recordBufferingStats(layer->getName(), layer->getOccupancyHistory(false)); } }); @@ -2574,7 +2575,7 @@ void SurfaceFlinger::commitTransactionLocked() { if (!mLayersPendingRemoval.isEmpty()) { // Notify removed layers now that they can't be drawn from for (const auto& l : mLayersPendingRemoval) { - recordBufferingStats(l->getName().string(), l->getOccupancyHistory(true)); + recordBufferingStats(l->getName(), l->getOccupancyHistory(true)); // Ensure any buffers set to display on any children are released. if (l->isRemovedFromCurrentState()) { @@ -3244,11 +3245,12 @@ uint32_t SurfaceFlinger::setClientStateLocked( // everything else inherits layer stack from its parent. if (layer->hasParent()) { ALOGE("Attempt to set layer stack on layer with parent (%s) is invalid", - layer->getName().string()); + layer->getDebugName()); } else if (idx < 0) { ALOGE("Attempt to set layer stack on layer without parent (%s) that " - "that also does not appear in the top level layer list. Something" - " has gone wrong.", layer->getName().string()); + "that also does not appear in the top level layer list. Something" + " has gone wrong.", + layer->getDebugName()); } else if (layer->setLayerStack(s.layerStack)) { mCurrentState.layersSortedByZ.removeAt(idx); mCurrentState.layersSortedByZ.add(layer); @@ -3406,7 +3408,7 @@ status_t SurfaceFlinger::mirrorLayer(const sp& client, const sp sp mirrorLayer; sp mirrorFrom; - String8 uniqueName = getUniqueLayerName(String8("MirrorRoot")); + std::string uniqueName = getUniqueLayerName("MirrorRoot"); { Mutex::Autolock _l(mStateLock); @@ -3415,8 +3417,8 @@ status_t SurfaceFlinger::mirrorLayer(const sp& client, const sp return NAME_NOT_FOUND; } - status_t result = createContainerLayer(client, uniqueName, -1, -1, 0, LayerMetadata(), - outHandle, &mirrorLayer); + status_t result = createContainerLayer(client, std::move(uniqueName), -1, -1, 0, + LayerMetadata(), outHandle, &mirrorLayer); if (result != NO_ERROR) { return result; } @@ -3447,7 +3449,7 @@ status_t SurfaceFlinger::createLayer(const String8& name, const sp& clie sp layer; - String8 uniqueName = getUniqueLayerName(name); + std::string uniqueName = getUniqueLayerName(name.string()); bool primaryDisplayOnly = false; @@ -3463,13 +3465,13 @@ status_t SurfaceFlinger::createLayer(const String8& name, const sp& clie switch (flags & ISurfaceComposerClient::eFXSurfaceMask) { case ISurfaceComposerClient::eFXSurfaceBufferQueue: - result = createBufferQueueLayer(client, uniqueName, w, h, flags, std::move(metadata), - format, handle, gbp, &layer); + result = createBufferQueueLayer(client, std::move(uniqueName), w, h, flags, + std::move(metadata), format, handle, gbp, &layer); break; case ISurfaceComposerClient::eFXSurfaceBufferState: - result = createBufferStateLayer(client, uniqueName, w, h, flags, std::move(metadata), - handle, &layer); + result = createBufferStateLayer(client, std::move(uniqueName), w, h, flags, + std::move(metadata), handle, &layer); break; case ISurfaceComposerClient::eFXSurfaceColor: // check if buffer size is set for color layer. @@ -3479,8 +3481,8 @@ status_t SurfaceFlinger::createLayer(const String8& name, const sp& clie return BAD_VALUE; } - result = createColorLayer(client, uniqueName, w, h, flags, std::move(metadata), handle, - &layer); + result = createColorLayer(client, std::move(uniqueName), w, h, flags, + std::move(metadata), handle, &layer); break; case ISurfaceComposerClient::eFXSurfaceContainer: // check if buffer size is set for container layer. @@ -3489,8 +3491,8 @@ status_t SurfaceFlinger::createLayer(const String8& name, const sp& clie int(w), int(h)); return BAD_VALUE; } - result = createContainerLayer(client, uniqueName, w, h, flags, std::move(metadata), - handle, &layer); + result = createContainerLayer(client, std::move(uniqueName), w, h, flags, + std::move(metadata), handle, &layer); break; default: result = BAD_VALUE; @@ -3517,35 +3519,32 @@ status_t SurfaceFlinger::createLayer(const String8& name, const sp& clie return result; } -String8 SurfaceFlinger::getUniqueLayerName(const String8& name) -{ - bool matchFound = true; - uint32_t dupeCounter = 0; +std::string SurfaceFlinger::getUniqueLayerName(const char* name) { + unsigned dupeCounter = 0; // Tack on our counter whether there is a hit or not, so everyone gets a tag - String8 uniqueName = name + "#" + String8(std::to_string(dupeCounter).c_str()); + std::string uniqueName = base::StringPrintf("%s#%u", name, dupeCounter); // Grab the state lock since we're accessing mCurrentState Mutex::Autolock lock(mStateLock); // Loop over layers until we're sure there is no matching name + bool matchFound = true; while (matchFound) { matchFound = false; mCurrentState.traverseInZOrder([&](Layer* layer) { if (layer->getName() == uniqueName) { matchFound = true; - uniqueName = name + "#" + String8(std::to_string(++dupeCounter).c_str()); + uniqueName = base::StringPrintf("%s#%u", name, ++dupeCounter); } }); } - ALOGV_IF(dupeCounter > 0, "duplicate layer name: changing %s to %s", name.c_str(), - uniqueName.c_str()); - + ALOGV_IF(dupeCounter > 0, "duplicate layer name: changing %s to %s", name, uniqueName.c_str()); return uniqueName; } -status_t SurfaceFlinger::createBufferQueueLayer(const sp& client, const String8& name, +status_t SurfaceFlinger::createBufferQueueLayer(const sp& client, std::string name, uint32_t w, uint32_t h, uint32_t flags, LayerMetadata metadata, PixelFormat& format, sp* handle, @@ -3563,8 +3562,7 @@ status_t SurfaceFlinger::createBufferQueueLayer(const sp& client, const } sp layer; - LayerCreationArgs args = - LayerCreationArgs(this, client, name, w, h, flags, std::move(metadata)); + LayerCreationArgs args(this, client, std::move(name), w, h, flags, std::move(metadata)); args.textureName = getNewTexture(); { // Grab the SF state lock during this since it's the only safe way to access @@ -3585,12 +3583,11 @@ status_t SurfaceFlinger::createBufferQueueLayer(const sp& client, const return err; } -status_t SurfaceFlinger::createBufferStateLayer(const sp& client, const String8& name, +status_t SurfaceFlinger::createBufferStateLayer(const sp& client, std::string name, uint32_t w, uint32_t h, uint32_t flags, LayerMetadata metadata, sp* handle, sp* outLayer) { - LayerCreationArgs args = - LayerCreationArgs(this, client, name, w, h, flags, std::move(metadata)); + LayerCreationArgs args(this, client, std::move(name), w, h, flags, std::move(metadata)); args.displayDevice = getDefaultDisplayDevice(); args.textureName = getNewTexture(); sp layer = getFactory().createBufferStateLayer(args); @@ -3600,26 +3597,25 @@ status_t SurfaceFlinger::createBufferStateLayer(const sp& client, const return NO_ERROR; } -status_t SurfaceFlinger::createColorLayer(const sp& client, const String8& name, uint32_t w, +status_t SurfaceFlinger::createColorLayer(const sp& client, std::string name, uint32_t w, uint32_t h, uint32_t flags, LayerMetadata metadata, sp* handle, sp* outLayer) { *outLayer = getFactory().createColorLayer( - LayerCreationArgs(this, client, name, w, h, flags, std::move(metadata))); + {this, client, std::move(name), w, h, flags, std::move(metadata)}); *handle = (*outLayer)->getHandle(); return NO_ERROR; } -status_t SurfaceFlinger::createContainerLayer(const sp& client, const String8& name, +status_t SurfaceFlinger::createContainerLayer(const sp& client, std::string name, uint32_t w, uint32_t h, uint32_t flags, LayerMetadata metadata, sp* handle, sp* outLayer) { *outLayer = getFactory().createContainerLayer( - LayerCreationArgs(this, client, name, w, h, flags, std::move(metadata))); + {this, client, std::move(name), w, h, flags, std::move(metadata)}); *handle = (*outLayer)->getHandle(); return NO_ERROR; } - void SurfaceFlinger::markLayerPendingRemovalLocked(const sp& layer) { mLayersPendingRemoval.add(layer); mLayersRemoved = true; @@ -3828,8 +3824,6 @@ status_t SurfaceFlinger::doDump(int fd, const DumpArgs& args, strerror(-err), err); } - using namespace std::string_literals; - static const std::unordered_map dumpers = { {"--display-id"s, dumper(&SurfaceFlinger::dumpDisplayIdentificationData)}, {"--dispsync"s, @@ -3885,7 +3879,7 @@ status_t SurfaceFlinger::dumpCritical(int fd, const DumpArgs&, bool asProto) { void SurfaceFlinger::listLayersLocked(std::string& result) const { mCurrentState.traverseInZOrder( - [&](Layer* layer) { StringAppendF(&result, "%s\n", layer->getName().string()); }); + [&](Layer* layer) { StringAppendF(&result, "%s\n", layer->getDebugName()); }); } void SurfaceFlinger::dumpStatsLocked(const DumpArgs& args, std::string& result) const { @@ -3894,7 +3888,7 @@ void SurfaceFlinger::dumpStatsLocked(const DumpArgs& args, std::string& result) if (args.size() > 1) { const auto name = String8(args[1]); mCurrentState.traverseInZOrder([&](Layer* layer) { - if (name == layer->getName()) { + if (layer->getName() == name.string()) { layer->dumpFrameStats(result); } }); @@ -3904,8 +3898,11 @@ void SurfaceFlinger::dumpStatsLocked(const DumpArgs& args, std::string& result) } void SurfaceFlinger::clearStatsLocked(const DumpArgs& args, std::string&) { + const bool clearAll = args.size() < 2; + const auto name = clearAll ? String8() : String8(args[1]); + mCurrentState.traverseInZOrder([&](Layer* layer) { - if (args.size() < 2 || String8(args[1]) == layer->getName()) { + if (clearAll || layer->getName() == name.string()) { layer->clearFrameStats(); } }); @@ -3924,7 +3921,7 @@ void SurfaceFlinger::logFrameStats() { layer->logFrameStats(); }); - mAnimFrameTracker.logAndResetStats(String8("")); + mAnimFrameTracker.logAndResetStats(""); } void SurfaceFlinger::appendSfConfigString(std::string& result) const { @@ -3982,8 +3979,8 @@ void SurfaceFlinger::dumpStaticScreenStats(std::string& result) const { bucketTimeSec, percent); } -void SurfaceFlinger::recordBufferingStats(const char* layerName, - std::vector&& history) { +void SurfaceFlinger::recordBufferingStats(const std::string& layerName, + std::vector&& history) { Mutex::Autolock lock(getBE().mBufferingStatsMutex); auto& stats = getBE().mBufferingStats[layerName]; for (const auto& segment : history) { @@ -5031,13 +5028,14 @@ status_t SurfaceFlinger::captureLayers( drawLayers(); } else { Rect bounds = getBounds(); + uint32_t w = static_cast(bounds.getWidth()); + uint32_t h = static_cast(bounds.getHeight()); // In the "childrenOnly" case we reparent the children to a screenshot // layer which has no properties set and which does not draw. sp screenshotParentLayer = - mFlinger->getFactory().createContainerLayer( - LayerCreationArgs(mFlinger, nullptr, String8("Screenshot Parent"), - bounds.getWidth(), bounds.getHeight(), 0, - LayerMetadata())); + mFlinger->getFactory().createContainerLayer({mFlinger, nullptr, + "Screenshot Parent"s, w, h, 0, + LayerMetadata()}); ReparentForDrawing reparent(mLayer, screenshotParentLayer, sourceCrop); drawLayers(); diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h index 9f3a914366..b719245caa 100644 --- a/services/surfaceflinger/SurfaceFlinger.h +++ b/services/surfaceflinger/SurfaceFlinger.h @@ -607,27 +607,27 @@ private: sp* handle, sp* gbp, const sp& parentHandle, const sp& parentLayer = nullptr); - status_t createBufferQueueLayer(const sp& client, const String8& name, uint32_t w, + status_t createBufferQueueLayer(const sp& client, std::string name, uint32_t w, uint32_t h, uint32_t flags, LayerMetadata metadata, PixelFormat& format, sp* outHandle, sp* outGbp, sp* outLayer); - status_t createBufferStateLayer(const sp& client, const String8& name, uint32_t w, + status_t createBufferStateLayer(const sp& client, std::string name, uint32_t w, uint32_t h, uint32_t flags, LayerMetadata metadata, sp* outHandle, sp* outLayer); - status_t createColorLayer(const sp& client, const String8& name, uint32_t w, uint32_t h, + status_t createColorLayer(const sp& client, std::string name, uint32_t w, uint32_t h, uint32_t flags, LayerMetadata metadata, sp* outHandle, sp* outLayer); - status_t createContainerLayer(const sp& client, const String8& name, uint32_t w, + status_t createContainerLayer(const sp& client, std::string name, uint32_t w, uint32_t h, uint32_t flags, LayerMetadata metadata, sp* outHandle, sp* outLayer); status_t mirrorLayer(const sp& client, const sp& mirrorFromHandle, sp* outHandle); - String8 getUniqueLayerName(const String8& name); + std::string getUniqueLayerName(const char* name); // called when all clients have released all their references to // this layer meaning it is entirely safe to destroy all @@ -866,8 +866,8 @@ private: // Not const because each Layer needs to query Fences and cache timestamps. void dumpFrameEventsLocked(std::string& result); - void recordBufferingStats(const char* layerName, - std::vector&& history); + void recordBufferingStats(const std::string& layerName, + std::vector&& history); void dumpBufferingStats(std::string& result) const; void dumpDisplayIdentificationData(std::string& result) const; void dumpRawDisplayIdentificationData(const DumpArgs&, std::string& result) const; diff --git a/services/surfaceflinger/SurfaceInterceptor.cpp b/services/surfaceflinger/SurfaceInterceptor.cpp index a02d14cc4d..7e6c472d7f 100644 --- a/services/surfaceflinger/SurfaceInterceptor.cpp +++ b/services/surfaceflinger/SurfaceInterceptor.cpp @@ -165,10 +165,6 @@ const sp SurfaceInterceptor::getLayer(const wp& weak return layer; } -const std::string SurfaceInterceptor::getLayerName(const sp& layer) const { - return layer->getName().string(); -} - int32_t SurfaceInterceptor::getLayerId(const sp& layer) const { return layer->sequence; } @@ -490,7 +486,7 @@ void SurfaceInterceptor::addSurfaceCreationLocked(Increment* increment, { SurfaceCreation* creation(increment->mutable_surface_creation()); creation->set_id(getLayerId(layer)); - creation->set_name(getLayerName(layer)); + creation->set_name(layer->getName()); creation->set_w(layer->mCurrentState.active_legacy.w); creation->set_h(layer->mCurrentState.active_legacy.h); } diff --git a/services/surfaceflinger/SurfaceInterceptor.h b/services/surfaceflinger/SurfaceInterceptor.h index 6858c4d5a6..72b734b8fd 100644 --- a/services/surfaceflinger/SurfaceInterceptor.h +++ b/services/surfaceflinger/SurfaceInterceptor.h @@ -123,7 +123,6 @@ private: status_t writeProtoFileLocked(); const sp getLayer(const wp& weakHandle) const; - const std::string getLayerName(const sp& layer) const; int32_t getLayerId(const sp& layer) const; int32_t getLayerIdFromWeakRef(const wp& layer) const; int32_t getLayerIdFromHandle(const sp& weakHandle) const; diff --git a/services/surfaceflinger/tests/unittests/CompositionTest.cpp b/services/surfaceflinger/tests/unittests/CompositionTest.cpp index 8aff096d5e..60da70fd25 100644 --- a/services/surfaceflinger/tests/unittests/CompositionTest.cpp +++ b/services/surfaceflinger/tests/unittests/CompositionTest.cpp @@ -839,7 +839,7 @@ struct ColorLayerVariant : public BaseLayerVariant { static FlingerLayerType createLayer(CompositionTest* test) { FlingerLayerType layer = Base::template createLayerWithFactory(test, [test]() { return new ColorLayer(LayerCreationArgs(test->mFlinger.mFlinger.get(), sp(), - String8("test-layer"), LayerProperties::WIDTH, + "test-layer", LayerProperties::WIDTH, LayerProperties::HEIGHT, LayerProperties::LAYER_FLAGS, LayerMetadata())); }); @@ -879,11 +879,9 @@ struct BufferLayerVariant : public BaseLayerVariant { FlingerLayerType layer = Base::template createLayerWithFactory(test, [test]() { sp client; - String8 name("test-layer"); - LayerCreationArgs args = - LayerCreationArgs(test->mFlinger.mFlinger.get(), client, name, - LayerProperties::WIDTH, LayerProperties::HEIGHT, - LayerProperties::LAYER_FLAGS, LayerMetadata()); + LayerCreationArgs args(test->mFlinger.mFlinger.get(), client, "test-layer", + LayerProperties::WIDTH, LayerProperties::HEIGHT, + LayerProperties::LAYER_FLAGS, LayerMetadata()); args.textureName = test->mFlinger.mutableTexturePool().back(); return new BufferQueueLayer(args); }); -- cgit v1.2.3-59-g8ed1b From f7a09ed2b7f85378e3043b1ce21617fc0a2bde12 Mon Sep 17 00:00:00 2001 From: Dominik Laskowski Date: Mon, 7 Oct 2019 13:54:18 -0700 Subject: SF: Optimize layer history in scheduler Register layers with LayerHistory by storing a weak pointer rather than allocating a LayerHandle. Query layer visibility when needed instead of synchronizing it to LayerInfo whenever Layer::isVisible is called. Store active/inactive layers in contiguous memory instead of two hash maps for cache efficiency, and minimal allocation and run time of operations like clearing history. Remove redundant ref-counting, locking, and frequency- period conversion in LayerInfo. Avoid sleeping in unit tests. This is also prework for per-display layer history. Bug: 130554049 Bug: 134772048 Test: go/wm-smoke with debug.sf.layer_history_trace Test: C2/F2 test cases from spreadsheet Test: LayerHistoryTest with new test cases Change-Id: Ibfcfe46cd76ebd93b916d4a0c737a19e837d4ff1 --- services/surfaceflinger/BufferLayer.cpp | 5 +- services/surfaceflinger/BufferQueueLayer.cpp | 4 +- services/surfaceflinger/BufferStateLayer.cpp | 4 +- services/surfaceflinger/Layer.cpp | 3 +- services/surfaceflinger/Layer.h | 5 +- services/surfaceflinger/Scheduler/LayerHistory.cpp | 217 +++++++-------- services/surfaceflinger/Scheduler/LayerHistory.h | 100 +++---- services/surfaceflinger/Scheduler/LayerInfo.cpp | 35 +-- services/surfaceflinger/Scheduler/LayerInfo.h | 170 +++++------- services/surfaceflinger/Scheduler/Scheduler.cpp | 47 ++-- services/surfaceflinger/Scheduler/Scheduler.h | 16 +- services/surfaceflinger/Scheduler/SchedulerUtils.h | 16 -- services/surfaceflinger/SurfaceFlinger.cpp | 10 + services/surfaceflinger/SurfaceFlinger.h | 7 +- .../tests/unittests/LayerHistoryTest.cpp | 291 ++++++++++++++------- .../tests/unittests/TestableScheduler.h | 1 + .../tests/unittests/TestableSurfaceFlinger.h | 6 +- .../tests/unittests/mock/MockLayer.h | 35 +++ 18 files changed, 502 insertions(+), 470 deletions(-) create mode 100644 services/surfaceflinger/tests/unittests/mock/MockLayer.h (limited to 'services/surfaceflinger/Layer.cpp') diff --git a/services/surfaceflinger/BufferLayer.cpp b/services/surfaceflinger/BufferLayer.cpp index 603a9f7f70..a25709ceee 100644 --- a/services/surfaceflinger/BufferLayer.cpp +++ b/services/surfaceflinger/BufferLayer.cpp @@ -107,11 +107,8 @@ bool BufferLayer::isOpaque(const Layer::State& s) const { } bool BufferLayer::isVisible() const { - bool visible = !(isHiddenByPolicy()) && getAlpha() > 0.0f && + return !isHiddenByPolicy() && getAlpha() > 0.0f && (mBufferInfo.mBuffer != nullptr || mSidebandStream != nullptr); - mFlinger->mScheduler->setLayerVisibility(mSchedulerLayerHandle, visible); - - return visible; } bool BufferLayer::isFixedSize() const { diff --git a/services/surfaceflinger/BufferQueueLayer.cpp b/services/surfaceflinger/BufferQueueLayer.cpp index 8cc1831d0f..c24cdaa617 100644 --- a/services/surfaceflinger/BufferQueueLayer.cpp +++ b/services/surfaceflinger/BufferQueueLayer.cpp @@ -389,8 +389,8 @@ void BufferQueueLayer::onFrameAvailable(const BufferItem& item) { { // Autolock scope if (mFlinger->mUseSmart90ForVideo) { const nsecs_t presentTime = item.mIsAutoTimestamp ? 0 : item.mTimestamp; - mFlinger->mScheduler->addLayerPresentTimeAndHDR(mSchedulerLayerHandle, presentTime, - item.mHdrMetadata.validTypes != 0); + mFlinger->mScheduler->recordLayerHistory(this, presentTime, + item.mHdrMetadata.validTypes != 0); } Mutex::Autolock lock(mQueueItemLock); diff --git a/services/surfaceflinger/BufferStateLayer.cpp b/services/surfaceflinger/BufferStateLayer.cpp index 85d2253bf5..5768edd744 100644 --- a/services/surfaceflinger/BufferStateLayer.cpp +++ b/services/surfaceflinger/BufferStateLayer.cpp @@ -249,8 +249,8 @@ bool BufferStateLayer::setBuffer(const sp& buffer, nsecs_t postTi if (mFlinger->mUseSmart90ForVideo) { const nsecs_t presentTime = (desiredPresentTime == -1) ? 0 : desiredPresentTime; - mFlinger->mScheduler->addLayerPresentTimeAndHDR(mSchedulerLayerHandle, presentTime, - mCurrentState.hdrMetadata.validTypes != 0); + mFlinger->mScheduler->recordLayerHistory(this, presentTime, + mCurrentState.hdrMetadata.validTypes != 0); } return true; diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp index 37caab2b3f..e19b79b7c5 100644 --- a/services/surfaceflinger/Layer.cpp +++ b/services/surfaceflinger/Layer.cpp @@ -118,10 +118,9 @@ Layer::Layer(const LayerCreationArgs& args) mFrameEventHistory.initializeCompositorTiming(compositorTiming); mFrameTracker.setDisplayRefreshPeriod(compositorTiming.interval); - mSchedulerLayerHandle = mFlinger->mScheduler->registerLayer(mName.c_str(), mWindowType); mCallingPid = args.callingPid; mCallingUid = args.callingUid; - mFlinger->onLayerCreated(); + mFlinger->onLayerCreated(this); } Layer::~Layer() { diff --git a/services/surfaceflinger/Layer.h b/services/surfaceflinger/Layer.h index ad81920dc9..fdac98f317 100644 --- a/services/surfaceflinger/Layer.h +++ b/services/surfaceflinger/Layer.h @@ -221,6 +221,8 @@ public: explicit Layer(const LayerCreationArgs& args); virtual ~Layer(); + int getWindowType() const { return mWindowType; } + void setPrimaryDisplayOnly() { mPrimaryDisplayOnly = true; } bool getPrimaryDisplayOnly() const { return mPrimaryDisplayOnly; } @@ -886,9 +888,6 @@ protected: // Window types from WindowManager.LayoutParams const int mWindowType; - // This is populated if the layer is registered with Scheduler for tracking purposes. - std::unique_ptr mSchedulerLayerHandle; - private: /** * Returns an unsorted vector of all layers that are part of this tree. diff --git a/services/surfaceflinger/Scheduler/LayerHistory.cpp b/services/surfaceflinger/Scheduler/LayerHistory.cpp index 5473db6974..8b717289c6 100644 --- a/services/surfaceflinger/Scheduler/LayerHistory.cpp +++ b/services/surfaceflinger/Scheduler/LayerHistory.cpp @@ -14,183 +14,150 @@ * limitations under the License. */ +#undef LOG_TAG +#define LOG_TAG "LayerHistory" #define ATRACE_TAG ATRACE_TAG_GRAPHICS #include "LayerHistory.h" -#include -#include -#include -#include -#include -#include - #include #include #include #include +#include +#include +#include +#include + +#include "../Layer.h" +#include "LayerInfo.h" #include "SchedulerUtils.h" -namespace android { -namespace scheduler { +namespace android::scheduler { -std::atomic LayerHistory::sNextId = 0; +namespace { -LayerHistory::LayerHistory() { +bool isLayerActive(const Layer& layer, const LayerInfo& info, nsecs_t threshold) { + return layer.isVisible() && (info.isHDR() || info.getLastUpdatedTime() >= threshold); +} + +bool traceEnabled() { char value[PROPERTY_VALUE_MAX]; property_get("debug.sf.layer_history_trace", value, "0"); - mTraceEnabled = static_cast(atoi(value)); + return atoi(value); } -LayerHistory::~LayerHistory() = default; +void trace(const wp& weak, int fps) { + const auto layer = weak.promote(); + if (!layer) return; + + const auto& name = layer->getName(); + const auto tag = "LFPS " + name; + ATRACE_INT(tag.c_str(), fps); + ALOGD("%s: %s @ %d Hz", __FUNCTION__, name.c_str(), fps); +} -std::unique_ptr LayerHistory::createLayer(const std::string name, - float minRefreshRate, - float maxRefreshRate) { - const int64_t id = sNextId++; +} // namespace +LayerHistory::LayerHistory() : mTraceEnabled(traceEnabled()) {} +LayerHistory::~LayerHistory() = default; + +void LayerHistory::registerLayer(Layer* layer, float lowRefreshRate, float highRefreshRate) { + auto info = std::make_unique(lowRefreshRate, highRefreshRate); std::lock_guard lock(mLock); - mInactiveLayerInfos.emplace(id, - std::make_shared(name, minRefreshRate, maxRefreshRate)); - return std::make_unique(*this, id); + mLayerInfos.emplace_back(layer, std::move(info)); } -void LayerHistory::destroyLayer(const int64_t id) { +void LayerHistory::record(Layer* layer, nsecs_t presentTime, bool isHDR, nsecs_t now) { std::lock_guard lock(mLock); - auto it = mActiveLayerInfos.find(id); - if (it != mActiveLayerInfos.end()) { - mActiveLayerInfos.erase(it); - } - it = mInactiveLayerInfos.find(id); - if (it != mInactiveLayerInfos.end()) { - mInactiveLayerInfos.erase(it); - } -} + const auto it = std::find_if(mLayerInfos.begin(), mLayerInfos.end(), + [layer](const auto& pair) { return pair.first == layer; }); + LOG_FATAL_IF(it == mLayerInfos.end(), "%s: unknown layer %p", __FUNCTION__, layer); -void LayerHistory::insert(const std::unique_ptr& layerHandle, nsecs_t presentTime, - bool isHdr) { - std::shared_ptr layerInfo; - { - std::lock_guard lock(mLock); - auto layerInfoIterator = mInactiveLayerInfos.find(layerHandle->mId); - if (layerInfoIterator != mInactiveLayerInfos.end()) { - layerInfo = layerInfoIterator->second; - mInactiveLayerInfos.erase(layerInfoIterator); - mActiveLayerInfos.insert({layerHandle->mId, layerInfo}); - } else { - layerInfoIterator = mActiveLayerInfos.find(layerHandle->mId); - if (layerInfoIterator != mActiveLayerInfos.end()) { - layerInfo = layerInfoIterator->second; - } else { - ALOGW("Inserting information about layer that is not registered: %" PRId64, - layerHandle->mId); - return; - } - } - } - layerInfo->setLastPresentTime(presentTime); - layerInfo->setHDRContent(isHdr); -} + const auto& info = it->second; + info->setLastPresentTime(presentTime, now); + info->setIsHDR(isHDR); -void LayerHistory::setVisibility(const std::unique_ptr& layerHandle, bool visible) { - std::shared_ptr layerInfo; - { - std::lock_guard lock(mLock); - auto layerInfoIterator = mInactiveLayerInfos.find(layerHandle->mId); - if (layerInfoIterator != mInactiveLayerInfos.end()) { - layerInfo = layerInfoIterator->second; - if (visible) { - mInactiveLayerInfos.erase(layerInfoIterator); - mActiveLayerInfos.insert({layerHandle->mId, layerInfo}); - } - } else { - layerInfoIterator = mActiveLayerInfos.find(layerHandle->mId); - if (layerInfoIterator != mActiveLayerInfos.end()) { - layerInfo = layerInfoIterator->second; - } else { - ALOGW("Inserting information about layer that is not registered: %" PRId64, - layerHandle->mId); - return; - } - } + // Activate layer if inactive. + if (const auto end = activeLayers().end(); it >= end) { + std::iter_swap(it, end); + mActiveLayersEnd++; } - layerInfo->setVisibility(visible); } -std::pair LayerHistory::getDesiredRefreshRateAndHDR() { +LayerHistory::Summary LayerHistory::summarize(nsecs_t now) { + float maxRefreshRate = 0; bool isHDR = false; - float newRefreshRate = 0.f; + std::lock_guard lock(mLock); - removeIrrelevantLayers(); + partitionLayers(now); - // Iterate through all layers that have been recently updated, and find the max refresh rate. - for (const auto& [layerId, layerInfo] : mActiveLayerInfos) { - const bool recent = layerInfo->isRecentlyActive(); + // Find the maximum refresh rate among recently active layers. + for (const auto& [layer, info] : activeLayers()) { + const bool recent = info->isRecentlyActive(now); if (recent || CC_UNLIKELY(mTraceEnabled)) { - const float refreshRate = layerInfo->getDesiredRefreshRate(); - if (recent && refreshRate > newRefreshRate) { - newRefreshRate = refreshRate; + const float refreshRate = info->getRefreshRate(now); + if (recent && refreshRate > maxRefreshRate) { + maxRefreshRate = refreshRate; } if (CC_UNLIKELY(mTraceEnabled)) { - std::string name = "LFPS " + layerInfo->getName(); - const float rate = std::round(refreshRate); - ATRACE_INT(name.c_str(), rate); - ALOGD("%s: %f", name.c_str(), rate); + trace(layer, std::round(refreshRate)); } } - isHDR |= layerInfo->getHDRContent(); + isHDR |= info->isHDR(); } if (CC_UNLIKELY(mTraceEnabled)) { - ALOGD("LayerHistory DesiredRefreshRate: %.2f", newRefreshRate); + ALOGD("%s: maxRefreshRate=%.2f, isHDR=%d", __FUNCTION__, maxRefreshRate, isHDR); } - return {newRefreshRate, isHDR}; + return {maxRefreshRate, isHDR}; } -void LayerHistory::removeIrrelevantLayers() { - const int64_t obsoleteEpsilon = systemTime() - scheduler::OBSOLETE_TIME_EPSILON_NS.count(); - // Iterator pointing to first element in map - auto it = mActiveLayerInfos.begin(); - while (it != mActiveLayerInfos.end()) { - // If last updated was before the obsolete time, remove it. - // Keep HDR layer around as long as they are visible. - if (!it->second->isVisible() || - (!it->second->getHDRContent() && it->second->getLastUpdatedTime() < obsoleteEpsilon)) { - // erase() function returns the iterator of the next - // to last deleted element. - if (CC_UNLIKELY(mTraceEnabled)) { - ALOGD("Layer %s obsolete", it->second->getName().c_str()); - // Make sure to update systrace to indicate that the layer was erased. - std::string layerName = "LFPS " + it->second->getName(); - ATRACE_INT(layerName.c_str(), 0); - } - auto id = it->first; - auto layerInfo = it->second; - layerInfo->clearHistory(); - mInactiveLayerInfos.insert({id, layerInfo}); - it = mActiveLayerInfos.erase(it); +void LayerHistory::partitionLayers(nsecs_t now) { + const nsecs_t threshold = getActiveLayerThreshold(now); + + // Collect expired and inactive layers after active layers. + size_t i = 0; + while (i < mActiveLayersEnd) { + auto& [weak, info] = mLayerInfos[i]; + if (const auto layer = weak.promote(); layer && isLayerActive(*layer, *info, threshold)) { + i++; + continue; + } + + if (CC_UNLIKELY(mTraceEnabled)) { + trace(weak, 0); + } + + info->clearHistory(); + std::swap(mLayerInfos[i], mLayerInfos[--mActiveLayersEnd]); + } + + // Collect expired layers after inactive layers. + size_t end = mLayerInfos.size(); + while (i < end) { + if (mLayerInfos[i].first.promote()) { + i++; } else { - ++it; + std::swap(mLayerInfos[i], mLayerInfos[--end]); } } + + mLayerInfos.erase(mLayerInfos.begin() + end, mLayerInfos.end()); } -void LayerHistory::clearHistory() { +void LayerHistory::clear() { std::lock_guard lock(mLock); - auto it = mActiveLayerInfos.begin(); - while (it != mActiveLayerInfos.end()) { - auto id = it->first; - auto layerInfo = it->second; - layerInfo->clearHistory(); - mInactiveLayerInfos.insert({id, layerInfo}); - it = mActiveLayerInfos.erase(it); + for (const auto& [layer, info] : activeLayers()) { + info->clearHistory(); } + + mActiveLayersEnd = 0; } -} // namespace scheduler -} // namespace android +} // namespace android::scheduler diff --git a/services/surfaceflinger/Scheduler/LayerHistory.h b/services/surfaceflinger/Scheduler/LayerHistory.h index 5598cc1cf5..15ac8caccb 100644 --- a/services/surfaceflinger/Scheduler/LayerHistory.h +++ b/services/surfaceflinger/Scheduler/LayerHistory.h @@ -16,76 +16,78 @@ #pragma once -#include -#include -#include -#include -#include -#include - +#include +#include #include -#include "LayerInfo.h" -#include "SchedulerUtils.h" +#include +#include +#include +#include namespace android { + +class Layer; + namespace scheduler { -/* - * This class represents information about layers that are considered current. We keep an - * unordered map between layer name and LayerInfo. - */ +class LayerInfo; + +// Records per-layer history of scheduling-related information (primarily present time), +// heuristically categorizes layers as active or inactive, and summarizes stats about +// active layers (primarily maximum refresh rate). See go/content-fps-detection-in-scheduler. class LayerHistory { public: - // Handle for each layer we keep track of. - class LayerHandle { - public: - LayerHandle(LayerHistory& lh, int64_t id) : mId(id), mLayerHistory(lh) {} - ~LayerHandle() { mLayerHistory.destroyLayer(mId); } + LayerHistory(); + ~LayerHistory(); - const int64_t mId; + // Layers are unregistered when the weak reference expires. + void registerLayer(Layer*, float lowRefreshRate, float highRefreshRate); - private: - LayerHistory& mLayerHistory; + // Marks the layer as active, and records the given state to its history. + void record(Layer*, nsecs_t presentTime, bool isHDR, nsecs_t now); + + struct Summary { + float maxRefreshRate; // Maximum refresh rate among recently active layers. + bool isHDR; // True if any recently active layer has HDR content. }; - LayerHistory(); - ~LayerHistory(); + // Rebuilds sets of active/inactive layers, and accumulates stats for active layers. + Summary summarize(nsecs_t now); - // When the layer is first created, register it. - std::unique_ptr createLayer(const std::string name, float minRefreshRate, - float maxRefreshRate); + void clear(); - // Method for inserting layers and their requested present time into the unordered map. - void insert(const std::unique_ptr& layerHandle, nsecs_t presentTime, bool isHdr); - // Method for setting layer visibility - void setVisibility(const std::unique_ptr& layerHandle, bool visible); +private: + friend class LayerHistoryTest; - // Returns the desired refresh rate, which is a max refresh rate of all the current - // layers. See go/content-fps-detection-in-scheduler for more information. - std::pair getDesiredRefreshRateAndHDR(); + using LayerPair = std::pair, std::unique_ptr>; + using LayerInfos = std::vector; - // Clears all layer history. - void clearHistory(); + struct ActiveLayers { + LayerInfos& infos; + const size_t index; - // Removes the handle and the object from the map. - void destroyLayer(const int64_t id); + auto begin() { return infos.begin(); } + auto end() { return begin() + index; } + }; -private: - // Removes the layers that have been idle for a given amount of time from mLayerInfos. - void removeIrrelevantLayers() REQUIRES(mLock); + ActiveLayers activeLayers() REQUIRES(mLock) { return {mLayerInfos, mActiveLayersEnd}; } + + // Iterates over layers in a single pass, swapping pairs such that active layers precede + // inactive layers, and inactive layers precede expired layers. Removes expired layers by + // truncating after inactive layers. + void partitionLayers(nsecs_t now) REQUIRES(mLock); - // Information about currently active layers. - std::mutex mLock; - std::unordered_map> mActiveLayerInfos GUARDED_BY(mLock); - std::unordered_map> mInactiveLayerInfos GUARDED_BY(mLock); + mutable std::mutex mLock; - // Each layer has it's own ID. This variable keeps track of the count. - static std::atomic sNextId; + // Partitioned such that active layers precede inactive layers. For fast lookup, the few active + // layers are at the front, and weak pointers are stored in contiguous memory to hit the cache. + LayerInfos mLayerInfos GUARDED_BY(mLock); + size_t mActiveLayersEnd GUARDED_BY(mLock) = 0; - // Flag whether to log layer FPS in systrace - bool mTraceEnabled = false; + // Whether to emit systrace output and debug logs. + const bool mTraceEnabled; }; } // namespace scheduler -} // namespace android \ No newline at end of file +} // namespace android diff --git a/services/surfaceflinger/Scheduler/LayerInfo.cpp b/services/surfaceflinger/Scheduler/LayerInfo.cpp index 723d71ff39..f3b0d56302 100644 --- a/services/surfaceflinger/Scheduler/LayerInfo.cpp +++ b/services/surfaceflinger/Scheduler/LayerInfo.cpp @@ -16,27 +16,17 @@ #include "LayerInfo.h" -#include -#include -#include -#include +#include +#include -namespace android { -namespace scheduler { +namespace android::scheduler { -LayerInfo::LayerInfo(const std::string name, float minRefreshRate, float maxRefreshRate) - : mName(name), - mMinRefreshDuration(1e9f / maxRefreshRate), - mLowActivityRefreshDuration(1e9f / minRefreshRate), - mRefreshRateHistory(mMinRefreshDuration) {} - -LayerInfo::~LayerInfo() = default; - -void LayerInfo::setLastPresentTime(nsecs_t lastPresentTime) { - std::lock_guard lock(mLock); +LayerInfo::LayerInfo(float lowRefreshRate, float highRefreshRate) + : mLowRefreshRate(lowRefreshRate), mHighRefreshRate(highRefreshRate) {} +void LayerInfo::setLastPresentTime(nsecs_t lastPresentTime, nsecs_t now) { // Buffers can come with a present time far in the future. That keeps them relevant. - mLastUpdatedTime = std::max(lastPresentTime, systemTime()); + mLastUpdatedTime = std::max(lastPresentTime, now); mPresentTimeHistory.insertPresentTime(mLastUpdatedTime); if (mLastPresentTime == 0) { @@ -45,14 +35,13 @@ void LayerInfo::setLastPresentTime(nsecs_t lastPresentTime) { return; } - const nsecs_t timeDiff = lastPresentTime - mLastPresentTime; + const nsecs_t period = lastPresentTime - mLastPresentTime; mLastPresentTime = lastPresentTime; // Ignore time diff that are too high - those are stale values - if (timeDiff > OBSOLETE_TIME_EPSILON_NS.count()) return; - const nsecs_t refreshDuration = std::max(timeDiff, mMinRefreshDuration); - const int fps = 1e9f / refreshDuration; + if (period > MAX_ACTIVE_LAYER_PERIOD_NS.count()) return; + + const float fps = std::min(1e9f / period, mHighRefreshRate); mRefreshRateHistory.insertRefreshRate(fps); } -} // namespace scheduler -} // namespace android +} // namespace android::scheduler diff --git a/services/surfaceflinger/Scheduler/LayerInfo.h b/services/surfaceflinger/Scheduler/LayerInfo.h index 17afddac28..b86709fc9c 100644 --- a/services/surfaceflinger/Scheduler/LayerInfo.h +++ b/services/surfaceflinger/Scheduler/LayerInfo.h @@ -16,27 +16,37 @@ #pragma once -#include -#include -#include -#include -#include -#include - -#include - -#include #include +#include +#include + #include "SchedulerUtils.h" namespace android { + +class Layer; + namespace scheduler { -/* - * This class represents information about individial layers. - */ +using namespace std::chrono_literals; + +// Maximum period between presents for a layer to be considered active. +constexpr std::chrono::nanoseconds MAX_ACTIVE_LAYER_PERIOD_NS = 1200ms; + +// Earliest present time for a layer to be considered active. +constexpr nsecs_t getActiveLayerThreshold(nsecs_t now) { + return now - MAX_ACTIVE_LAYER_PERIOD_NS.count(); +} + +// Stores history of present times and refresh rates for a layer. class LayerInfo { + // Layer is considered frequent if the earliest value in the window of most recent present times + // is within a threshold. If a layer is infrequent, its average refresh rate is disregarded in + // favor of a low refresh rate. + static constexpr size_t FREQUENT_LAYER_WINDOW_SIZE = 3; + static constexpr std::chrono::nanoseconds MAX_FREQUENT_LAYER_PERIOD_NS = 250ms; + /** * Struct that keeps the information about the refresh rate for last * HISTORY_SIZE frames. This is used to better determine the refresh rate @@ -44,9 +54,9 @@ class LayerInfo { */ class RefreshRateHistory { public: - explicit RefreshRateHistory(nsecs_t minRefreshDuration) - : mMinRefreshDuration(minRefreshDuration) {} - void insertRefreshRate(int refreshRate) { + explicit RefreshRateHistory(float highRefreshRate) : mHighRefreshRate(highRefreshRate) {} + + void insertRefreshRate(float refreshRate) { mElements.push_back(refreshRate); if (mElements.size() > HISTORY_SIZE) { mElements.pop_front(); @@ -54,19 +64,16 @@ class LayerInfo { } float getRefreshRateAvg() const { - if (mElements.empty()) { - return 1e9f / mMinRefreshDuration; - } - - return scheduler::calculate_mean(mElements); + return mElements.empty() ? mHighRefreshRate : calculate_mean(mElements); } void clearHistory() { mElements.clear(); } private: - std::deque mElements; + const float mHighRefreshRate; + static constexpr size_t HISTORY_SIZE = 30; - const nsecs_t mMinRefreshDuration; + std::deque mElements; }; /** @@ -76,6 +83,8 @@ class LayerInfo { */ class PresentTimeHistory { public: + static constexpr size_t HISTORY_SIZE = 90; + void insertPresentTime(nsecs_t presentTime) { mElements.push_back(presentTime); if (mElements.size() > HISTORY_SIZE) { @@ -83,60 +92,45 @@ class LayerInfo { } } - // Checks whether the present time that was inserted HISTORY_SIZE ago is within a - // certain threshold: TIME_EPSILON_NS. - bool isRelevant() const { + // Returns whether the earliest present time is within the active threshold. + bool isRecentlyActive(nsecs_t now) const { if (mElements.size() < 2) { return false; } // The layer had to publish at least HISTORY_SIZE or HISTORY_TIME of updates - if (mElements.size() != HISTORY_SIZE && - mElements.at(mElements.size() - 1) - mElements.at(0) < HISTORY_TIME.count()) { + if (mElements.size() < HISTORY_SIZE && + mElements.back() - mElements.front() < HISTORY_TIME.count()) { return false; } - // The last update should not be older than OBSOLETE_TIME_EPSILON_NS nanoseconds. - const int64_t obsoleteEpsilon = - systemTime() - scheduler::OBSOLETE_TIME_EPSILON_NS.count(); - if (mElements.at(mElements.size() - 1) < obsoleteEpsilon) { - return false; - } - - return true; + return mElements.back() >= getActiveLayerThreshold(now); } - bool isLowActivityLayer() const { - // We want to make sure that we received more than two frames from the layer - // in order to check low activity. - if (mElements.size() < scheduler::LOW_ACTIVITY_BUFFERS + 1) { + bool isFrequent(nsecs_t now) const { + // Assume layer is infrequent if too few present times have been recorded. + if (mElements.size() < FREQUENT_LAYER_WINDOW_SIZE) { return false; } - const int64_t obsoleteEpsilon = - systemTime() - scheduler::LOW_ACTIVITY_EPSILON_NS.count(); - // Check the frame before last to determine whether there is low activity. - // If that frame is older than LOW_ACTIVITY_EPSILON_NS, the layer is sending - // infrequent updates. - if (mElements.at(mElements.size() - (scheduler::LOW_ACTIVITY_BUFFERS + 1)) < - obsoleteEpsilon) { - return true; - } - - return false; + // Layer is frequent if the earliest value in the window of most recent present times is + // within threshold. + const auto it = mElements.end() - FREQUENT_LAYER_WINDOW_SIZE; + const nsecs_t threshold = now - MAX_FREQUENT_LAYER_PERIOD_NS.count(); + return *it >= threshold; } void clearHistory() { mElements.clear(); } private: std::deque mElements; - static constexpr size_t HISTORY_SIZE = 90; static constexpr std::chrono::nanoseconds HISTORY_TIME = 1s; }; + friend class LayerHistoryTest; + public: - LayerInfo(const std::string name, float minRefreshRate, float maxRefreshRate); - ~LayerInfo(); + LayerInfo(float lowRefreshRate, float highRefreshRate); LayerInfo(const LayerInfo&) = delete; LayerInfo& operator=(const LayerInfo&) = delete; @@ -144,71 +138,37 @@ public: // Records the last requested oresent time. It also stores information about when // the layer was last updated. If the present time is farther in the future than the // updated time, the updated time is the present time. - void setLastPresentTime(nsecs_t lastPresentTime); + void setLastPresentTime(nsecs_t lastPresentTime, nsecs_t now); - void setHDRContent(bool isHdr) { - std::lock_guard lock(mLock); - mIsHDR = isHdr; - } + bool isHDR() const { return mIsHDR; } + void setIsHDR(bool isHDR) { mIsHDR = isHDR; } - void setVisibility(bool visible) { - std::lock_guard lock(mLock); - mIsVisible = visible; - } + bool isRecentlyActive(nsecs_t now) const { return mPresentTimeHistory.isRecentlyActive(now); } + bool isFrequent(nsecs_t now) const { return mPresentTimeHistory.isFrequent(now); } - // Checks the present time history to see whether the layer is relevant. - bool isRecentlyActive() const { - std::lock_guard lock(mLock); - return mPresentTimeHistory.isRelevant(); - } - - // Calculate the average refresh rate. - float getDesiredRefreshRate() const { - std::lock_guard lock(mLock); - - if (mPresentTimeHistory.isLowActivityLayer()) { - return 1e9f / mLowActivityRefreshDuration; - } - return mRefreshRateHistory.getRefreshRateAvg(); - } - - bool getHDRContent() { - std::lock_guard lock(mLock); - return mIsHDR; - } - - bool isVisible() { - std::lock_guard lock(mLock); - return mIsVisible; + float getRefreshRate(nsecs_t now) const { + return isFrequent(now) ? mRefreshRateHistory.getRefreshRateAvg() : mLowRefreshRate; } // Return the last updated time. If the present time is farther in the future than the // updated time, the updated time is the present time. - nsecs_t getLastUpdatedTime() { - std::lock_guard lock(mLock); - return mLastUpdatedTime; - } - - std::string getName() const { return mName; } + nsecs_t getLastUpdatedTime() const { return mLastUpdatedTime; } void clearHistory() { - std::lock_guard lock(mLock); mRefreshRateHistory.clearHistory(); mPresentTimeHistory.clearHistory(); } private: - const std::string mName; - const nsecs_t mMinRefreshDuration; - const nsecs_t mLowActivityRefreshDuration; - mutable std::mutex mLock; - nsecs_t mLastUpdatedTime GUARDED_BY(mLock) = 0; - nsecs_t mLastPresentTime GUARDED_BY(mLock) = 0; - RefreshRateHistory mRefreshRateHistory GUARDED_BY(mLock); - PresentTimeHistory mPresentTimeHistory GUARDED_BY(mLock); - bool mIsHDR GUARDED_BY(mLock) = false; - bool mIsVisible GUARDED_BY(mLock) = false; + const float mLowRefreshRate; + const float mHighRefreshRate; + + nsecs_t mLastUpdatedTime = 0; + nsecs_t mLastPresentTime = 0; + RefreshRateHistory mRefreshRateHistory{mHighRefreshRate}; + PresentTimeHistory mPresentTimeHistory; + bool mIsHDR = false; }; } // namespace scheduler -} // namespace android \ No newline at end of file +} // namespace android diff --git a/services/surfaceflinger/Scheduler/Scheduler.cpp b/services/surfaceflinger/Scheduler/Scheduler.cpp index d60e101fb4..71b35001b6 100644 --- a/services/surfaceflinger/Scheduler/Scheduler.cpp +++ b/services/surfaceflinger/Scheduler/Scheduler.cpp @@ -20,13 +20,6 @@ #include "Scheduler.h" -#include -#include -#include -#include -#include -#include - #include #include #include @@ -37,6 +30,14 @@ #include #include +#include +#include +#include +#include +#include +#include + +#include "../Layer.h" #include "DispSync.h" #include "DispSyncSource.h" #include "EventControlThread.h" @@ -325,37 +326,27 @@ nsecs_t Scheduler::getDispSyncExpectedPresentTime() { return mPrimaryDispSync->expectedPresentTime(); } -std::unique_ptr Scheduler::registerLayer( - std::string const& name, int windowType) { +void Scheduler::registerLayer(Layer* layer) { uint32_t defaultFps, performanceFps; if (mRefreshRateConfigs.refreshRateSwitchingSupported()) { defaultFps = mRefreshRateConfigs.getRefreshRateFromType(RefreshRateType::DEFAULT).fps; - performanceFps = - mRefreshRateConfigs - .getRefreshRateFromType((windowType == InputWindowInfo::TYPE_WALLPAPER) - ? RefreshRateType::DEFAULT - : RefreshRateType::PERFORMANCE) - .fps; + const auto type = layer->getWindowType() == InputWindowInfo::TYPE_WALLPAPER + ? RefreshRateType::DEFAULT + : RefreshRateType::PERFORMANCE; + performanceFps = mRefreshRateConfigs.getRefreshRateFromType(type).fps; } else { defaultFps = mRefreshRateConfigs.getCurrentRefreshRate().second.fps; performanceFps = defaultFps; } - return mLayerHistory.createLayer(name, defaultFps, performanceFps); -} - -void Scheduler::addLayerPresentTimeAndHDR( - const std::unique_ptr& layerHandle, - nsecs_t presentTime, bool isHDR) { - mLayerHistory.insert(layerHandle, presentTime, isHDR); + mLayerHistory.registerLayer(layer, defaultFps, performanceFps); } -void Scheduler::setLayerVisibility( - const std::unique_ptr& layerHandle, bool visible) { - mLayerHistory.setVisibility(layerHandle, visible); +void Scheduler::recordLayerHistory(Layer* layer, nsecs_t presentTime, bool isHDR) { + mLayerHistory.record(layer, presentTime, isHDR, systemTime()); } void Scheduler::updateFpsBasedOnContent() { - auto [refreshRate, isHDR] = mLayerHistory.getDesiredRefreshRateAndHDR(); + auto [refreshRate, isHDR] = mLayerHistory.summarize(systemTime()); const uint32_t refreshRateRound = std::round(refreshRate); RefreshRateType newRefreshRateType; { @@ -402,7 +393,7 @@ void Scheduler::notifyTouchEvent() { // Touch event will boost the refresh rate to performance. // Clear Layer History to get fresh FPS detection - mLayerHistory.clearHistory(); + mLayerHistory.clear(); } void Scheduler::setDisplayPowerState(bool normal) { @@ -417,7 +408,7 @@ void Scheduler::setDisplayPowerState(bool normal) { // Display Power event will boost the refresh rate to performance. // Clear Layer History to get fresh FPS detection - mLayerHistory.clearHistory(); + mLayerHistory.clear(); } void Scheduler::kernelIdleTimerCallback(TimerState state) { diff --git a/services/surfaceflinger/Scheduler/Scheduler.h b/services/surfaceflinger/Scheduler/Scheduler.h index a5971fed23..c98347522e 100644 --- a/services/surfaceflinger/Scheduler/Scheduler.h +++ b/services/surfaceflinger/Scheduler/Scheduler.h @@ -100,17 +100,11 @@ public: void addPresentFence(const std::shared_ptr&); void setIgnorePresentFences(bool ignore); nsecs_t getDispSyncExpectedPresentTime(); - // Registers the layer in the scheduler, and returns the handle for future references. - std::unique_ptr registerLayer(std::string const& name, - int windowType); - - // Stores present time for a layer. - void addLayerPresentTimeAndHDR( - const std::unique_ptr& layerHandle, - nsecs_t presentTime, bool isHDR); - // Stores visibility for a layer. - void setLayerVisibility( - const std::unique_ptr& layerHandle, bool visible); + + // Layers are registered on creation, and unregistered when the weak reference expires. + void registerLayer(Layer*); + void recordLayerHistory(Layer*, nsecs_t presentTime, bool isHDR); + // Updates FPS based on the most content presented. void updateFpsBasedOnContent(); diff --git a/services/surfaceflinger/Scheduler/SchedulerUtils.h b/services/surfaceflinger/Scheduler/SchedulerUtils.h index 3b7567ce8b..d301b9977b 100644 --- a/services/surfaceflinger/Scheduler/SchedulerUtils.h +++ b/services/surfaceflinger/Scheduler/SchedulerUtils.h @@ -16,7 +16,6 @@ #pragma once -#include #include #include #include @@ -38,21 +37,6 @@ inline bool operator==(ConnectionHandle lhs, ConnectionHandle rhs) { return lhs.id == rhs.id; } -using namespace std::chrono_literals; - -// This number is used when we try to determine how long do we keep layer information around -// before we remove it. It is also used to determine how long the layer stays relevant. -// This time period captures infrequent updates when playing YouTube video with static image, -// or waiting idle in messaging app, when cursor is blinking. -static constexpr std::chrono::nanoseconds OBSOLETE_TIME_EPSILON_NS = 1200ms; - -// Layer is considered low activity if the LOW_ACTIVITY_BUFFERS buffers come more than -// LOW_ACTIVITY_EPSILON_NS apart. -// This is helping SF to vote for lower refresh rates when there is not activity -// in screen. -static constexpr int LOW_ACTIVITY_BUFFERS = 2; -static constexpr std::chrono::nanoseconds LOW_ACTIVITY_EPSILON_NS = 250ms; - // Calculates the statistical mean (average) in the data structure (array, vector). The // function does not modify the contents of the array. template diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp index 057669b376..1acb2da051 100644 --- a/services/surfaceflinger/SurfaceFlinger.cpp +++ b/services/surfaceflinger/SurfaceFlinger.cpp @@ -5505,6 +5505,16 @@ sp SurfaceFlinger::fromHandle(const sp& handle) { return nullptr; } +void SurfaceFlinger::onLayerCreated(Layer* layer) { + mNumLayers++; + mScheduler->registerLayer(layer); +} + +void SurfaceFlinger::onLayerDestroyed(Layer* layer) { + mNumLayers--; + mOffscreenLayers.erase(layer); +} + void SurfaceFlinger::bufferErased(const client_cache_t& clientCacheId) { getRenderEngine().unbindExternalTextureBuffer(clientCacheId.id); } diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h index b719245caa..abb8b821ba 100644 --- a/services/surfaceflinger/SurfaceFlinger.h +++ b/services/surfaceflinger/SurfaceFlinger.h @@ -310,11 +310,8 @@ public: bool authenticateSurfaceTextureLocked( const sp& bufferProducer) const; - inline void onLayerCreated() { mNumLayers++; } - inline void onLayerDestroyed(Layer* layer) { - mNumLayers--; - mOffscreenLayers.erase(layer); - } + void onLayerCreated(Layer*); + void onLayerDestroyed(Layer*); TransactionCompletedThread& getTransactionCompletedThread() { return mTransactionCompletedThread; diff --git a/services/surfaceflinger/tests/unittests/LayerHistoryTest.cpp b/services/surfaceflinger/tests/unittests/LayerHistoryTest.cpp index 8e7440c2e3..9a962bcc0c 100644 --- a/services/surfaceflinger/tests/unittests/LayerHistoryTest.cpp +++ b/services/surfaceflinger/tests/unittests/LayerHistoryTest.cpp @@ -1,140 +1,243 @@ #undef LOG_TAG -#define LOG_TAG "LayerHistoryUnittests" +#define LOG_TAG "LayerHistoryTest" #include #include - #include -#include -#include - #include "Scheduler/LayerHistory.h" +#include "Scheduler/LayerInfo.h" +#include "TestableScheduler.h" +#include "TestableSurfaceFlinger.h" +#include "mock/MockLayer.h" using testing::_; using testing::Return; -namespace android { -namespace scheduler { +namespace android::scheduler { class LayerHistoryTest : public testing::Test { -public: - LayerHistoryTest(); - ~LayerHistoryTest() override; - protected: - std::unique_ptr mLayerHistory; + static constexpr auto PRESENT_TIME_HISTORY_SIZE = LayerInfo::PresentTimeHistory::HISTORY_SIZE; + static constexpr auto MAX_FREQUENT_LAYER_PERIOD_NS = LayerInfo::MAX_FREQUENT_LAYER_PERIOD_NS; - static constexpr float MIN_REFRESH_RATE = 30.f; - static constexpr float MAX_REFRESH_RATE = 90.f; - static constexpr auto RELEVANT_FRAME_THRESHOLD = 90u; - static constexpr uint64_t THIRTY_FPS_INTERVAL = 33'333'333; + static constexpr float LO_FPS = 30.f; + static constexpr nsecs_t LO_FPS_PERIOD = 33'333'333; - void forceRelevancy(const std::unique_ptr& testLayer) { - mLayerHistory->setVisibility(testLayer, true); - for (auto i = 0u; i < RELEVANT_FRAME_THRESHOLD; i++) { - mLayerHistory->insert(testLayer, 0, false /*isHDR*/); - } - }; -}; + static constexpr float HI_FPS = 90.f; + static constexpr nsecs_t HI_FPS_PERIOD = 11'111'111; -LayerHistoryTest::LayerHistoryTest() { - mLayerHistory = std::make_unique(); -} -LayerHistoryTest::~LayerHistoryTest() {} + LayerHistoryTest() { mFlinger.resetScheduler(mScheduler); } + + LayerHistory& history() { return mScheduler->mutableLayerHistory(); } + const LayerHistory& history() const { return mScheduler->mutableLayerHistory(); } + + size_t layerCount() const NO_THREAD_SAFETY_ANALYSIS { return history().mLayerInfos.size(); } + size_t activeLayerCount() const NO_THREAD_SAFETY_ANALYSIS { return history().mActiveLayersEnd; } + + size_t frequentLayerCount(nsecs_t now) const NO_THREAD_SAFETY_ANALYSIS { + const auto& infos = history().mLayerInfos; + return std::count_if(infos.begin(), infos.begin() + history().mActiveLayersEnd, + [now](const auto& pair) { return pair.second->isFrequent(now); }); + } + + auto createLayer() { return sp(new mock::MockLayer(mFlinger.flinger())); } + + RefreshRateConfigs mConfigs{true, + {RefreshRateConfigs::InputConfig{0, LO_FPS_PERIOD}, + RefreshRateConfigs::InputConfig{1, HI_FPS_PERIOD}}, + 0}; + TestableScheduler* const mScheduler{new TestableScheduler(mConfigs)}; + TestableSurfaceFlinger mFlinger; + + const nsecs_t mTime = systemTime(); +}; namespace { + TEST_F(LayerHistoryTest, oneLayer) { - std::unique_ptr testLayer = - mLayerHistory->createLayer("TestLayer", MIN_REFRESH_RATE, MAX_REFRESH_RATE); - mLayerHistory->setVisibility(testLayer, true); - for (auto i = 0u; i < RELEVANT_FRAME_THRESHOLD; i++) { - EXPECT_FLOAT_EQ(0.f, mLayerHistory->getDesiredRefreshRateAndHDR().first); - mLayerHistory->insert(testLayer, 0, false /*isHDR*/); + const auto layer = createLayer(); + constexpr bool isHDR = false; + EXPECT_CALL(*layer, isVisible()).WillRepeatedly(Return(true)); + + EXPECT_EQ(1, layerCount()); + EXPECT_EQ(0, activeLayerCount()); + + // 0 FPS is returned if no layers are active. + EXPECT_FLOAT_EQ(0, history().summarize(mTime).maxRefreshRate); + EXPECT_EQ(0, activeLayerCount()); + + // 0 FPS is returned if active layers have insufficient history. + for (int i = 0; i < PRESENT_TIME_HISTORY_SIZE - 1; i++) { + history().record(layer.get(), 0, isHDR, mTime); + EXPECT_FLOAT_EQ(0, history().summarize(mTime).maxRefreshRate); + EXPECT_EQ(1, activeLayerCount()); } - // Add a few more. This time we should get MAX refresh rate as the layer - // becomes relevant - static constexpr auto A_FEW = 10; - for (auto i = 0u; i < A_FEW; i++) { - EXPECT_FLOAT_EQ(MAX_REFRESH_RATE, mLayerHistory->getDesiredRefreshRateAndHDR().first); - mLayerHistory->insert(testLayer, 0, false /*isHDR*/); + // High FPS is returned once enough history has been recorded. + for (int i = 0; i < 10; i++) { + history().record(layer.get(), 0, isHDR, mTime); + EXPECT_FLOAT_EQ(HI_FPS, history().summarize(mTime).maxRefreshRate); + EXPECT_EQ(1, activeLayerCount()); } } TEST_F(LayerHistoryTest, oneHDRLayer) { - std::unique_ptr testLayer = - mLayerHistory->createLayer("TestHDRLayer", MIN_REFRESH_RATE, MAX_REFRESH_RATE); - mLayerHistory->setVisibility(testLayer, true); + const auto layer = createLayer(); + constexpr bool isHDR = true; + EXPECT_CALL(*layer, isVisible()).WillRepeatedly(Return(true)); + + EXPECT_EQ(1, layerCount()); + EXPECT_EQ(0, activeLayerCount()); + + history().record(layer.get(), 0, isHDR, mTime); + auto summary = history().summarize(mTime); + EXPECT_FLOAT_EQ(0, summary.maxRefreshRate); + EXPECT_TRUE(summary.isHDR); + EXPECT_EQ(1, activeLayerCount()); - mLayerHistory->insert(testLayer, 0, true /*isHDR*/); - EXPECT_FLOAT_EQ(0.0f, mLayerHistory->getDesiredRefreshRateAndHDR().first); - EXPECT_EQ(true, mLayerHistory->getDesiredRefreshRateAndHDR().second); + EXPECT_CALL(*layer, isVisible()).WillRepeatedly(Return(false)); - mLayerHistory->setVisibility(testLayer, false); - EXPECT_FLOAT_EQ(0.0f, mLayerHistory->getDesiredRefreshRateAndHDR().first); - EXPECT_EQ(false, mLayerHistory->getDesiredRefreshRateAndHDR().second); + summary = history().summarize(mTime); + EXPECT_FLOAT_EQ(0, summary.maxRefreshRate); + EXPECT_FALSE(summary.isHDR); + EXPECT_EQ(0, activeLayerCount()); } TEST_F(LayerHistoryTest, explicitTimestamp) { - std::unique_ptr test30FpsLayer = - mLayerHistory->createLayer("30FpsLayer", MIN_REFRESH_RATE, MAX_REFRESH_RATE); - mLayerHistory->setVisibility(test30FpsLayer, true); - - nsecs_t startTime = systemTime(); - for (int i = 0; i < RELEVANT_FRAME_THRESHOLD; i++) { - mLayerHistory->insert(test30FpsLayer, startTime + (i * THIRTY_FPS_INTERVAL), - false /*isHDR*/); + const auto layer = createLayer(); + constexpr bool isHDR = false; + EXPECT_CALL(*layer, isVisible()).WillRepeatedly(Return(true)); + + EXPECT_EQ(1, layerCount()); + EXPECT_EQ(0, activeLayerCount()); + + nsecs_t time = mTime; + for (int i = 0; i < PRESENT_TIME_HISTORY_SIZE; i++) { + history().record(layer.get(), time, isHDR, time); + time += LO_FPS_PERIOD; } - EXPECT_FLOAT_EQ(30.f, mLayerHistory->getDesiredRefreshRateAndHDR().first); + EXPECT_FLOAT_EQ(LO_FPS, history().summarize(mTime).maxRefreshRate); + EXPECT_EQ(1, activeLayerCount()); + EXPECT_EQ(1, frequentLayerCount(time)); } TEST_F(LayerHistoryTest, multipleLayers) { - std::unique_ptr testLayer = - mLayerHistory->createLayer("TestLayer", MIN_REFRESH_RATE, MAX_REFRESH_RATE); - mLayerHistory->setVisibility(testLayer, true); - std::unique_ptr test30FpsLayer = - mLayerHistory->createLayer("30FpsLayer", MIN_REFRESH_RATE, MAX_REFRESH_RATE); - mLayerHistory->setVisibility(test30FpsLayer, true); - std::unique_ptr testLayer2 = - mLayerHistory->createLayer("TestLayer2", MIN_REFRESH_RATE, MAX_REFRESH_RATE); - mLayerHistory->setVisibility(testLayer2, true); - - nsecs_t startTime = systemTime(); - for (int i = 0; i < RELEVANT_FRAME_THRESHOLD; i++) { - mLayerHistory->insert(testLayer, 0, false /*isHDR*/); + auto layer1 = createLayer(); + auto layer2 = createLayer(); + auto layer3 = createLayer(); + constexpr bool isHDR = false; + + EXPECT_CALL(*layer1, isVisible()).WillRepeatedly(Return(true)); + EXPECT_CALL(*layer2, isVisible()).WillRepeatedly(Return(true)); + EXPECT_CALL(*layer3, isVisible()).WillRepeatedly(Return(true)); + + nsecs_t time = mTime; + + EXPECT_EQ(3, layerCount()); + EXPECT_EQ(0, activeLayerCount()); + EXPECT_EQ(0, frequentLayerCount(time)); + + // layer1 is active but infrequent. + for (int i = 0; i < PRESENT_TIME_HISTORY_SIZE; i++) { + history().record(layer1.get(), time, isHDR, time); + time += MAX_FREQUENT_LAYER_PERIOD_NS.count(); } - EXPECT_FLOAT_EQ(MAX_REFRESH_RATE, mLayerHistory->getDesiredRefreshRateAndHDR().first); - startTime = systemTime(); - for (int i = 0; i < RELEVANT_FRAME_THRESHOLD; i++) { - mLayerHistory->insert(test30FpsLayer, startTime + (i * THIRTY_FPS_INTERVAL), - false /*isHDR*/); + EXPECT_FLOAT_EQ(LO_FPS, history().summarize(time).maxRefreshRate); + EXPECT_EQ(1, activeLayerCount()); + EXPECT_EQ(0, frequentLayerCount(time)); + + // layer2 is frequent and has high refresh rate. + for (int i = 0; i < PRESENT_TIME_HISTORY_SIZE; i++) { + history().record(layer2.get(), time, isHDR, time); + time += HI_FPS_PERIOD; } - EXPECT_FLOAT_EQ(MAX_REFRESH_RATE, mLayerHistory->getDesiredRefreshRateAndHDR().first); - for (int i = 10; i < RELEVANT_FRAME_THRESHOLD; i++) { - mLayerHistory->insert(test30FpsLayer, startTime + (i * THIRTY_FPS_INTERVAL), - false /*isHDR*/); + // layer1 is still active but infrequent. + history().record(layer1.get(), time, isHDR, time); + + EXPECT_FLOAT_EQ(HI_FPS, history().summarize(time).maxRefreshRate); + EXPECT_EQ(2, activeLayerCount()); + EXPECT_EQ(1, frequentLayerCount(time)); + + // layer1 is no longer active. + // layer2 is frequent and has low refresh rate. + for (int i = 0; i < PRESENT_TIME_HISTORY_SIZE; i++) { + history().record(layer2.get(), time, isHDR, time); + time += LO_FPS_PERIOD; } - EXPECT_FLOAT_EQ(MAX_REFRESH_RATE, mLayerHistory->getDesiredRefreshRateAndHDR().first); - // This frame is only around for 9 occurrences, so it doesn't throw - // anything off. - for (int i = 0; i < 9; i++) { - mLayerHistory->insert(testLayer2, 0, false /*isHDR*/); + EXPECT_FLOAT_EQ(LO_FPS, history().summarize(time).maxRefreshRate); + EXPECT_EQ(1, activeLayerCount()); + EXPECT_EQ(1, frequentLayerCount(time)); + + // layer2 still has low refresh rate. + // layer3 has high refresh rate but not enough history. + constexpr int RATIO = LO_FPS_PERIOD / HI_FPS_PERIOD; + for (int i = 0; i < PRESENT_TIME_HISTORY_SIZE - 1; i++) { + if (i % RATIO == 0) { + history().record(layer2.get(), time, isHDR, time); + } + + history().record(layer3.get(), time, isHDR, time); + time += HI_FPS_PERIOD; + } + + EXPECT_FLOAT_EQ(LO_FPS, history().summarize(time).maxRefreshRate); + EXPECT_EQ(2, activeLayerCount()); + EXPECT_EQ(2, frequentLayerCount(time)); + + // layer3 becomes recently active. + history().record(layer3.get(), time, isHDR, time); + EXPECT_FLOAT_EQ(HI_FPS, history().summarize(time).maxRefreshRate); + EXPECT_EQ(2, activeLayerCount()); + EXPECT_EQ(2, frequentLayerCount(time)); + + // layer1 expires. + layer1.clear(); + EXPECT_FLOAT_EQ(HI_FPS, history().summarize(time).maxRefreshRate); + EXPECT_EQ(2, layerCount()); + EXPECT_EQ(2, activeLayerCount()); + EXPECT_EQ(2, frequentLayerCount(time)); + + // layer2 still has low refresh rate. + // layer3 becomes inactive. + for (int i = 0; i < PRESENT_TIME_HISTORY_SIZE; i++) { + history().record(layer2.get(), time, isHDR, time); + time += LO_FPS_PERIOD; + } + + EXPECT_FLOAT_EQ(LO_FPS, history().summarize(time).maxRefreshRate); + EXPECT_EQ(1, activeLayerCount()); + EXPECT_EQ(1, frequentLayerCount(time)); + + // layer2 expires. + layer2.clear(); + EXPECT_FLOAT_EQ(0, history().summarize(time).maxRefreshRate); + EXPECT_EQ(1, layerCount()); + EXPECT_EQ(0, activeLayerCount()); + EXPECT_EQ(0, frequentLayerCount(time)); + + // layer3 becomes active and has high refresh rate. + for (int i = 0; i < PRESENT_TIME_HISTORY_SIZE; i++) { + history().record(layer3.get(), time, isHDR, time); + time += HI_FPS_PERIOD; } - EXPECT_FLOAT_EQ(MAX_REFRESH_RATE, mLayerHistory->getDesiredRefreshRateAndHDR().first); - // After 1200 ms frames become obsolete. - std::this_thread::sleep_for(std::chrono::milliseconds(1500)); - - mLayerHistory->insert(test30FpsLayer, - startTime + (RELEVANT_FRAME_THRESHOLD * THIRTY_FPS_INTERVAL), - false /*isHDR*/); - EXPECT_FLOAT_EQ(30.f, mLayerHistory->getDesiredRefreshRateAndHDR().first); + + EXPECT_FLOAT_EQ(HI_FPS, history().summarize(time).maxRefreshRate); + EXPECT_EQ(1, layerCount()); + EXPECT_EQ(1, activeLayerCount()); + EXPECT_EQ(1, frequentLayerCount(time)); + + // layer3 expires. + layer3.clear(); + EXPECT_FLOAT_EQ(0, history().summarize(time).maxRefreshRate); + EXPECT_EQ(0, layerCount()); + EXPECT_EQ(0, activeLayerCount()); + EXPECT_EQ(0, frequentLayerCount(time)); } } // namespace -} // namespace scheduler -} // namespace android \ No newline at end of file +} // namespace android::scheduler diff --git a/services/surfaceflinger/tests/unittests/TestableScheduler.h b/services/surfaceflinger/tests/unittests/TestableScheduler.h index ae7246780a..ae6aa899af 100644 --- a/services/surfaceflinger/tests/unittests/TestableScheduler.h +++ b/services/surfaceflinger/tests/unittests/TestableScheduler.h @@ -48,6 +48,7 @@ public: auto& mutableEventControlThread() { return mEventControlThread; } auto& mutablePrimaryDispSync() { return mPrimaryDispSync; } auto& mutableHWVsyncAvailable() { return mHWVsyncAvailable; } + auto& mutableLayerHistory() { return mLayerHistory; } ~TestableScheduler() { // All these pointer and container clears help ensure that GMock does diff --git a/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h b/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h index c7664fb9ac..94fc5f7273 100644 --- a/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h +++ b/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h @@ -22,6 +22,7 @@ #include #include #include +#include #include "BufferQueueLayer.h" #include "BufferStateLayer.h" @@ -173,6 +174,7 @@ public: class TestableSurfaceFlinger { public: + SurfaceFlinger* flinger() { return mFlinger.get(); } TestableScheduler* scheduler() { return mScheduler; } // Extend this as needed for accessing SurfaceFlinger private (and public) @@ -207,13 +209,15 @@ public: mFlinger->mAppConnectionHandle = mScheduler->createConnection(std::move(appEventThread)); mFlinger->mSfConnectionHandle = mScheduler->createConnection(std::move(sfEventThread)); + resetScheduler(mScheduler); - mFlinger->mScheduler.reset(mScheduler); mFlinger->mVSyncModulator.emplace(*mScheduler, mFlinger->mAppConnectionHandle, mFlinger->mSfConnectionHandle, mFlinger->mPhaseOffsets->getCurrentOffsets()); } + void resetScheduler(Scheduler* scheduler) { mFlinger->mScheduler.reset(scheduler); } + using CreateBufferQueueFunction = surfaceflinger::test::Factory::CreateBufferQueueFunction; void setCreateBufferQueueFunction(CreateBufferQueueFunction f) { mFactory.mCreateBufferQueue = f; diff --git a/services/surfaceflinger/tests/unittests/mock/MockLayer.h b/services/surfaceflinger/tests/unittests/mock/MockLayer.h new file mode 100644 index 0000000000..f375e23700 --- /dev/null +++ b/services/surfaceflinger/tests/unittests/mock/MockLayer.h @@ -0,0 +1,35 @@ +/* + * Copyright 2019 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 + +#include "Layer.h" + +namespace android::mock { + +class MockLayer : public Layer { +public: + explicit MockLayer(SurfaceFlinger* flinger) + : Layer(LayerCreationArgs(flinger, nullptr, "TestLayer", 800, 600, 0, {})) {} + + MOCK_CONST_METHOD0(getType, const char*()); + MOCK_CONST_METHOD0(isVisible, bool()); + MOCK_METHOD0(createClone, sp()); +}; + +} // namespace android::mock -- cgit v1.2.3-59-g8ed1b From c97b8dbd9093c7a8cfeedcd7e417f6732cbe24c6 Mon Sep 17 00:00:00 2001 From: Vishnu Nair Date: Tue, 29 Oct 2019 18:19:35 -0700 Subject: [Shadows] Add shadow radius to sf layer state (2/n) Bug: 136561771 Test: atest SurfaceFlinger_Test Change-Id: Icafe852eaad195163b48b802db2a4b092aa30926 --- libs/gui/LayerState.cpp | 6 ++++ libs/gui/SurfaceComposerClient.cpp | 12 +++++++ libs/gui/include/gui/LayerState.h | 8 +++-- libs/gui/include/gui/SurfaceComposerClient.h | 1 + services/surfaceflinger/ContainerLayer.h | 1 + services/surfaceflinger/Layer.cpp | 37 +++++++++++++++++++--- services/surfaceflinger/Layer.h | 12 ++++++- services/surfaceflinger/SurfaceFlinger.cpp | 9 ++++-- .../tests/unittests/CompositionTest.cpp | 2 +- 9 files changed, 77 insertions(+), 11 deletions(-) (limited to 'services/surfaceflinger/Layer.cpp') diff --git a/libs/gui/LayerState.cpp b/libs/gui/LayerState.cpp index e004e9584c..e392bc597f 100644 --- a/libs/gui/LayerState.cpp +++ b/libs/gui/LayerState.cpp @@ -406,6 +406,12 @@ void layer_state_t::merge(const layer_state_t& other) { what |= eMetadataChanged; metadata.merge(other.metadata); } + + if (other.what & eShadowRadiusChanged) { + what |= eShadowRadiusChanged; + shadowRadius = other.shadowRadius; + } + if ((other.what & what) != other.what) { ALOGE("Unmerged SurfaceComposer Transaction properties. LayerState::merge needs updating? " "other.what=0x%" PRIu64 " what=0x%" PRIu64, diff --git a/libs/gui/SurfaceComposerClient.cpp b/libs/gui/SurfaceComposerClient.cpp index e9079efd29..14f47c3509 100644 --- a/libs/gui/SurfaceComposerClient.cpp +++ b/libs/gui/SurfaceComposerClient.cpp @@ -1335,6 +1335,18 @@ SurfaceComposerClient::Transaction& SurfaceComposerClient::Transaction::setGeome return *this; } +SurfaceComposerClient::Transaction& SurfaceComposerClient::Transaction::setShadowRadius( + const sp& sc, float shadowRadius) { + layer_state_t* s = getLayerState(sc); + if (!s) { + mStatus = BAD_INDEX; + return *this; + } + s->what |= layer_state_t::eShadowRadiusChanged; + s->shadowRadius = shadowRadius; + return *this; +} + // --------------------------------------------------------------------------- DisplayState& SurfaceComposerClient::Transaction::getDisplayState(const sp& token) { diff --git a/libs/gui/include/gui/LayerState.h b/libs/gui/include/gui/LayerState.h index a49ed525b6..c2b5119242 100644 --- a/libs/gui/include/gui/LayerState.h +++ b/libs/gui/include/gui/LayerState.h @@ -72,7 +72,7 @@ struct layer_state_t { eCropChanged_legacy = 0x00000100, eDeferTransaction_legacy = 0x00000200, eOverrideScalingModeChanged = 0x00000400, - // AVAILABLE 0x00000800, + eShadowRadiusChanged = 0x00000800, eReparentChildren = 0x00001000, eDetachChildren = 0x00002000, eRelativeLayerChanged = 0x00004000, @@ -126,7 +126,8 @@ struct layer_state_t { colorTransform(mat4()), bgColorAlpha(0), bgColorDataspace(ui::Dataspace::UNKNOWN), - colorSpaceAgnostic(false) { + colorSpaceAgnostic(false), + shadowRadius(0.0f) { matrix.dsdx = matrix.dtdy = 1.0f; matrix.dsdy = matrix.dtdx = 0.0f; hdrMetadata.validTypes = 0; @@ -204,6 +205,9 @@ struct layer_state_t { bool colorSpaceAgnostic; std::vector listeners; + + // Draws a shadow around the surface. + float shadowRadius; }; struct ComposerState { diff --git a/libs/gui/include/gui/SurfaceComposerClient.h b/libs/gui/include/gui/SurfaceComposerClient.h index 08f4e9e9d3..a140142b37 100644 --- a/libs/gui/include/gui/SurfaceComposerClient.h +++ b/libs/gui/include/gui/SurfaceComposerClient.h @@ -474,6 +474,7 @@ public: Transaction& setGeometry(const sp& sc, const Rect& source, const Rect& dst, int transform); + Transaction& setShadowRadius(const sp& sc, float cornerRadius); status_t setDisplaySurface(const sp& token, const sp& bufferProducer); diff --git a/services/surfaceflinger/ContainerLayer.h b/services/surfaceflinger/ContainerLayer.h index b48d471bde..9b7bab1e1d 100644 --- a/services/surfaceflinger/ContainerLayer.h +++ b/services/surfaceflinger/ContainerLayer.h @@ -34,6 +34,7 @@ public: bool isCreatedFromMainThread() const override { return true; } protected: + bool canDrawShadows() const override { return false; } sp createClone() override; }; diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp index e19b79b7c5..b51653deb8 100644 --- a/services/surfaceflinger/Layer.cpp +++ b/services/surfaceflinger/Layer.cpp @@ -339,7 +339,8 @@ FloatRect Layer::getBoundsPreScaling(const ui::Transform& bufferScaleTransform) return bufferScaleTransform.inverse().transform(mBounds); } -void Layer::computeBounds(FloatRect parentBounds, ui::Transform parentTransform) { +void Layer::computeBounds(FloatRect parentBounds, ui::Transform parentTransform, + float parentShadowRadius) { const State& s(getDrawingState()); // Calculate effective layer transform @@ -362,11 +363,23 @@ void Layer::computeBounds(FloatRect parentBounds, ui::Transform parentTransform) mBounds = bounds; mScreenBounds = mEffectiveTransform.transform(mBounds); + // Use the layer's own shadow radius if set. Otherwise get the radius from + // parent. + if (s.shadowRadius > 0.f) { + mEffectiveShadowRadius = s.shadowRadius; + } else { + mEffectiveShadowRadius = parentShadowRadius; + } + + // Shadow radius is passed down to only one layer so if the layer can draw shadows, + // don't pass it to its children. + const float childShadowRadius = canDrawShadows() ? 0.f : mEffectiveShadowRadius; + // Add any buffer scaling to the layer's children. ui::Transform bufferScaleTransform = getBufferScaleTransform(); for (const sp& child : mDrawingChildren) { child->computeBounds(getBoundsPreScaling(bufferScaleTransform), - getTransformWithScale(bufferScaleTransform)); + getTransformWithScale(bufferScaleTransform), childShadowRadius); } } @@ -466,11 +479,13 @@ void Layer::latchPerFrameState(compositionengine::LayerFECompositionState& compo compositionState.hasProtectedContent = isProtected(); const bool usesRoundedCorners = getRoundedCornerState().radius != 0.f; + const bool drawsShadows = mEffectiveShadowRadius != 0.f; + compositionState.isOpaque = isOpaque(drawingState) && !usesRoundedCorners && getAlpha() == 1.0_hf; // Force client composition for special cases known only to the front-end. - if (isHdrY410() || usesRoundedCorners) { + if (isHdrY410() || usesRoundedCorners || drawsShadows) { compositionState.forceClientComposition = true; } } @@ -1116,6 +1131,18 @@ uint32_t Layer::getLayerStack() const { return p->getLayerStack(); } +bool Layer::setShadowRadius(float shadowRadius) { + if (mCurrentState.shadowRadius == shadowRadius) { + return false; + } + + mCurrentState.sequence++; + mCurrentState.shadowRadius = shadowRadius; + mCurrentState.modified = true; + setTransactionFlags(eTransactionNeeded); + return true; +} + void Layer::deferTransactionUntil_legacy(const sp& barrierLayer, uint64_t frameNumber) { ATRACE_CALL(); mCurrentState.barrierLayer_legacy = barrierLayer; @@ -1410,8 +1437,8 @@ void Layer::setChildrenDrawingParent(const sp& newParent) { for (const sp& child : mDrawingChildren) { child->mDrawingParent = newParent; child->computeBounds(newParent->mBounds, - newParent->getTransformWithScale( - newParent->getBufferScaleTransform())); + newParent->getTransformWithScale(newParent->getBufferScaleTransform()), + newParent->mEffectiveShadowRadius); } } diff --git a/services/surfaceflinger/Layer.h b/services/surfaceflinger/Layer.h index fdac98f317..648be3e182 100644 --- a/services/surfaceflinger/Layer.h +++ b/services/surfaceflinger/Layer.h @@ -216,6 +216,7 @@ public: std::deque> callbackHandles; bool colorSpaceAgnostic; nsecs_t desiredPresentTime = -1; + float shadowRadius; }; explicit Layer(const LayerCreationArgs& args); @@ -329,6 +330,7 @@ public: }; virtual bool setBackgroundColor(const half3& color, float alpha, ui::Dataspace dataspace); virtual bool setColorSpaceAgnostic(const bool agnostic); + bool setShadowRadius(float shadowRadius); virtual ui::Dataspace getDataSpace() const { return ui::Dataspace::UNKNOWN; } @@ -362,7 +364,7 @@ public: FloatRect getBounds() const; // Compute bounds for the layer and cache the results. - void computeBounds(FloatRect parentBounds, ui::Transform parentTransform); + void computeBounds(FloatRect parentBounds, ui::Transform parentTransform, float shadowRadius); // Returns the buffer scale transform if a scaling mode is set. ui::Transform getBufferScaleTransform() const; @@ -942,6 +944,14 @@ private: // this layer will update it's buffer. When mClonedFrom updates it's drawing state, children, // and relatives, this layer will update as well. wp mClonedFrom; + + // The inherited shadow radius after taking into account the layer hierarchy. This is the + // final shadow radius for this layer. If a shadow is specified for a layer, then effective + // shadow radius is the set shadow radius, otherwise its the parent's shadow radius. + float mEffectiveShadowRadius; + + // Returns true if the layer can draw shadows on its border. + virtual bool canDrawShadows() const { return true; } }; } // namespace android diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp index 1acb2da051..953cb99c13 100644 --- a/services/surfaceflinger/SurfaceFlinger.cpp +++ b/services/surfaceflinger/SurfaceFlinger.cpp @@ -2011,7 +2011,8 @@ void SurfaceFlinger::computeLayerBounds() { continue; } - layer->computeBounds(displayDevice->getViewport().toFloatRect(), ui::Transform()); + layer->computeBounds(displayDevice->getViewport().toFloatRect(), ui::Transform(), + 0.f /* shadowRadius */); } } } @@ -3335,6 +3336,9 @@ uint32_t SurfaceFlinger::setClientStateLocked( flags |= eTraversalNeeded; } } + if (what & layer_state_t::eShadowRadiusChanged) { + if (layer->setShadowRadius(s.shadowRadius)) flags |= eTraversalNeeded; + } // This has to happen after we reparent children because when we reparent to null we remove // child layers from current state and remove its relative z. If the children are reparented in // the same transaction, then we have to make sure we reparent the children first so we do not @@ -5010,7 +5014,8 @@ status_t SurfaceFlinger::captureLayers( const Rect& drawingBounds) : oldParent(oldParent), newParent(newParent) { // Compute and cache the bounds for the new parent layer. - newParent->computeBounds(drawingBounds.toFloatRect(), ui::Transform()); + newParent->computeBounds(drawingBounds.toFloatRect(), ui::Transform(), + 0.f /* shadowRadius */); oldParent->setChildrenDrawingParent(newParent); } ~ReparentForDrawing() { oldParent->setChildrenDrawingParent(oldParent); } diff --git a/services/surfaceflinger/tests/unittests/CompositionTest.cpp b/services/surfaceflinger/tests/unittests/CompositionTest.cpp index 60da70fd25..143a7a0fb5 100644 --- a/services/surfaceflinger/tests/unittests/CompositionTest.cpp +++ b/services/surfaceflinger/tests/unittests/CompositionTest.cpp @@ -803,7 +803,7 @@ struct BaseLayerVariant { layerDrawingState.active.h = 100; layerDrawingState.color = half4(LayerProperties::COLOR[0], LayerProperties::COLOR[1], LayerProperties::COLOR[2], LayerProperties::COLOR[3]); - layer->computeBounds(FloatRect(0, 0, 100, 100), ui::Transform()); + layer->computeBounds(FloatRect(0, 0, 100, 100), ui::Transform(), 0.f /* shadowRadius */); return layer; } -- cgit v1.2.3-59-g8ed1b From 301b1d84f2d51febc71a367dd143327d77112cbd Mon Sep 17 00:00:00 2001 From: chaviw Date: Wed, 6 Nov 2019 13:15:09 -0800 Subject: Use correct state when calling getZ When calling traverseInZOrder, there's a call to getZ. Currently the code uses the drawingState but that's incorrect since sometimes we traverse the currentState. Changed the getZ function so it uses the correct state. Bug: 143200062 Test: Builds and runs Change-Id: Ifcd9bafbf0906b4f6f8f68f7d20d1a1025cef449 --- services/surfaceflinger/Layer.cpp | 12 +++++++----- services/surfaceflinger/Layer.h | 2 +- 2 files changed, 8 insertions(+), 6 deletions(-) (limited to 'services/surfaceflinger/Layer.cpp') diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp index e19b79b7c5..215e240360 100644 --- a/services/surfaceflinger/Layer.cpp +++ b/services/surfaceflinger/Layer.cpp @@ -1540,8 +1540,10 @@ void Layer::setParent(const sp& layer) { mCurrentParent = layer; } -int32_t Layer::getZ() const { - return mDrawingState.z; +int32_t Layer::getZ(LayerVector::StateSet stateSet) const { + const bool useDrawing = stateSet == LayerVector::StateSet::Drawing; + const State& state = useDrawing ? mDrawingState : mCurrentState; + return state.z; } bool Layer::usingRelativeZ(LayerVector::StateSet stateSet) const { @@ -1601,7 +1603,7 @@ void Layer::traverseInZOrder(LayerVector::StateSet stateSet, const LayerVector:: continue; } - if (relative->getZ() >= 0) { + if (relative->getZ(stateSet) >= 0) { break; } relative->traverseInZOrder(stateSet, visitor); @@ -1635,7 +1637,7 @@ void Layer::traverseInReverseZOrder(LayerVector::StateSet stateSet, continue; } - if (relative->getZ() < 0) { + if (relative->getZ(stateSet) < 0) { break; } relative->traverseInReverseZOrder(stateSet, visitor); @@ -1693,7 +1695,7 @@ void Layer::traverseChildrenInZOrderInner(const std::vector& layersInTre size_t i = 0; for (; i < list.size(); i++) { const auto& relative = list[i]; - if (relative->getZ() >= 0) { + if (relative->getZ(stateSet) >= 0) { break; } relative->traverseChildrenInZOrderInner(layersInTree, stateSet, visitor); diff --git a/services/surfaceflinger/Layer.h b/services/surfaceflinger/Layer.h index fdac98f317..cdd8d3f3c2 100644 --- a/services/surfaceflinger/Layer.h +++ b/services/surfaceflinger/Layer.h @@ -672,7 +672,7 @@ public: // Copy the current list of children to the drawing state. Called by // SurfaceFlinger to complete a transaction. void commitChildList(); - int32_t getZ() const; + int32_t getZ(LayerVector::StateSet stateSet) const; virtual void pushPendingState(); /** -- cgit v1.2.3-59-g8ed1b From 7584836d4ac4ecc0cf8166491b84533e67f300f2 Mon Sep 17 00:00:00 2001 From: Dominik Laskowski Date: Mon, 11 Nov 2019 17:57:20 -0800 Subject: SF: Register layers on first strong reference In ag/9549429, LayerHistory stores a wp on Layer construction, at which point RefBase::mStrong is not yet 1. Since wp::promote succeeds in that case, LayerHistory may concurrently create a sp with sole ownership on the main thread while checking for expired weak references, resulting in premature layer destruction. Bug: 144218964 Test: None (sporadic crash) Change-Id: Ia7c89a090920588b216b719fce36c9f64a126e81 --- services/surfaceflinger/Layer.cpp | 5 ++++- services/surfaceflinger/Layer.h | 2 ++ services/surfaceflinger/SurfaceFlinger.cpp | 2 +- services/surfaceflinger/SurfaceFlinger.h | 2 +- 4 files changed, 8 insertions(+), 3 deletions(-) (limited to 'services/surfaceflinger/Layer.cpp') diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp index 215e240360..93c0b52e8b 100644 --- a/services/surfaceflinger/Layer.cpp +++ b/services/surfaceflinger/Layer.cpp @@ -120,7 +120,10 @@ Layer::Layer(const LayerCreationArgs& args) mCallingPid = args.callingPid; mCallingUid = args.callingUid; - mFlinger->onLayerCreated(this); +} + +void Layer::onFirstRef() { + mFlinger->onLayerFirstRef(this); } Layer::~Layer() { diff --git a/services/surfaceflinger/Layer.h b/services/surfaceflinger/Layer.h index cdd8d3f3c2..8ad0116234 100644 --- a/services/surfaceflinger/Layer.h +++ b/services/surfaceflinger/Layer.h @@ -221,6 +221,8 @@ public: explicit Layer(const LayerCreationArgs& args); virtual ~Layer(); + void onFirstRef() override; + int getWindowType() const { return mWindowType; } void setPrimaryDisplayOnly() { mPrimaryDisplayOnly = true; } diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp index 96c17a10d9..a908780f8f 100644 --- a/services/surfaceflinger/SurfaceFlinger.cpp +++ b/services/surfaceflinger/SurfaceFlinger.cpp @@ -5508,7 +5508,7 @@ sp SurfaceFlinger::fromHandle(const sp& handle) { return nullptr; } -void SurfaceFlinger::onLayerCreated(Layer* layer) { +void SurfaceFlinger::onLayerFirstRef(Layer* layer) { mNumLayers++; mScheduler->registerLayer(layer); } diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h index e7ad295b2d..e6ebb3578b 100644 --- a/services/surfaceflinger/SurfaceFlinger.h +++ b/services/surfaceflinger/SurfaceFlinger.h @@ -310,7 +310,7 @@ public: bool authenticateSurfaceTextureLocked( const sp& bufferProducer) const; - void onLayerCreated(Layer*); + void onLayerFirstRef(Layer*); void onLayerDestroyed(Layer*); TransactionCompletedThread& getTransactionCompletedThread() { -- cgit v1.2.3-59-g8ed1b From f37dcfbe941bb5f0a55aa30ccb7ba9321df6aa24 Mon Sep 17 00:00:00 2001 From: Vishnu Nair Date: Sat, 16 Nov 2019 07:37:09 -0800 Subject: Initialize shadowRadius state The uninitialized var was causing the device to incorrectly going into glcomp. Fixes: b/144450732 Test: adb shell am instrument -w -e class android.platform.test.scenario.launcher.FlingAllAppsMicrobenchmark android.platform.test.scenario/androidx.test.runner.AndroidJUnitRunner and capture a systrace Change-Id: Ia33a4c8908990cd12fbd5a5ce1664ed96c112832 --- services/surfaceflinger/Layer.cpp | 1 + services/surfaceflinger/Layer.h | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) (limited to 'services/surfaceflinger/Layer.cpp') diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp index 00d932d705..1d0ce1002d 100644 --- a/services/surfaceflinger/Layer.cpp +++ b/services/surfaceflinger/Layer.cpp @@ -109,6 +109,7 @@ Layer::Layer(const LayerCreationArgs& args) mCurrentState.hasColorTransform = false; mCurrentState.colorSpaceAgnostic = false; mCurrentState.metadata = args.metadata; + mCurrentState.shadowRadius = 0.f; // drawing state & current state are identical mDrawingState = mCurrentState; diff --git a/services/surfaceflinger/Layer.h b/services/surfaceflinger/Layer.h index bed5ad3dcd..1388612b57 100644 --- a/services/surfaceflinger/Layer.h +++ b/services/surfaceflinger/Layer.h @@ -950,7 +950,7 @@ private: // The inherited shadow radius after taking into account the layer hierarchy. This is the // final shadow radius for this layer. If a shadow is specified for a layer, then effective // shadow radius is the set shadow radius, otherwise its the parent's shadow radius. - float mEffectiveShadowRadius; + float mEffectiveShadowRadius = 0.f; // Returns true if the layer can draw shadows on its border. virtual bool canDrawShadows() const { return true; } -- cgit v1.2.3-59-g8ed1b From 1a88c40d5623b61bd66338f5df0e8857d249fa79 Mon Sep 17 00:00:00 2001 From: Yiwei Zhang Date: Mon, 18 Nov 2019 10:43:58 -0800 Subject: TimeStats & FrameTracer: refactor layerID to layerId Test: build, flash and boot Test: atest libsurfaceflinger_unittest Change-Id: I297dce08dbaf625b56e1e6d47cffead1de440ab7 --- services/surfaceflinger/BufferLayer.cpp | 18 ++-- services/surfaceflinger/BufferQueueLayer.cpp | 38 +++---- services/surfaceflinger/BufferStateLayer.cpp | 24 ++--- .../surfaceflinger/FrameTracer/FrameTracer.cpp | 54 +++++----- services/surfaceflinger/FrameTracer/FrameTracer.h | 14 +-- services/surfaceflinger/Layer.cpp | 6 +- services/surfaceflinger/TimeStats/TimeStats.cpp | 110 ++++++++++----------- services/surfaceflinger/TimeStats/TimeStats.h | 42 ++++---- .../tests/unittests/FrameTracerTest.cpp | 74 +++++++------- .../tests/unittests/TimeStatsTest.cpp | 14 +-- 10 files changed, 197 insertions(+), 197 deletions(-) (limited to 'services/surfaceflinger/Layer.cpp') diff --git a/services/surfaceflinger/BufferLayer.cpp b/services/surfaceflinger/BufferLayer.cpp index a25709ceee..31462569e2 100644 --- a/services/surfaceflinger/BufferLayer.cpp +++ b/services/surfaceflinger/BufferLayer.cpp @@ -77,9 +77,9 @@ BufferLayer::~BufferLayer() { // with the clone layer trying to use the deleted texture. mFlinger->deleteTextureAsync(mTextureName); } - const int32_t layerID = getSequence(); - mFlinger->mTimeStats->onDestroy(layerID); - mFlinger->mFrameTracer->onDestroy(layerID); + const int32_t layerId = getSequence(); + mFlinger->mTimeStats->onDestroy(layerId); + mFlinger->mFrameTracer->onDestroy(layerId); } void BufferLayer::useSurfaceDamage() { @@ -305,8 +305,8 @@ bool BufferLayer::onPostComposition(const std::optional& displayId, nsecs_t desiredPresentTime = mBufferInfo.mDesiredPresentTime; mFrameTracker.setDesiredPresentTime(desiredPresentTime); - const int32_t layerID = getSequence(); - mFlinger->mTimeStats->setDesiredTime(layerID, mCurrentFrameNumber, desiredPresentTime); + const int32_t layerId = getSequence(); + mFlinger->mTimeStats->setDesiredTime(layerId, mCurrentFrameNumber, desiredPresentTime); std::shared_ptr frameReadyFence = mBufferInfo.mFenceTime; if (frameReadyFence->isValid()) { @@ -318,16 +318,16 @@ bool BufferLayer::onPostComposition(const std::optional& displayId, } if (presentFence->isValid()) { - mFlinger->mTimeStats->setPresentFence(layerID, mCurrentFrameNumber, presentFence); - mFlinger->mFrameTracer->traceFence(layerID, getCurrentBufferId(), mCurrentFrameNumber, + mFlinger->mTimeStats->setPresentFence(layerId, mCurrentFrameNumber, presentFence); + mFlinger->mFrameTracer->traceFence(layerId, getCurrentBufferId(), mCurrentFrameNumber, presentFence, FrameTracer::FrameEvent::PRESENT_FENCE); mFrameTracker.setActualPresentFence(std::shared_ptr(presentFence)); } else if (displayId && mFlinger->getHwComposer().isConnected(*displayId)) { // The HWC doesn't support present fences, so use the refresh // timestamp instead. const nsecs_t actualPresentTime = mFlinger->getHwComposer().getRefreshTimestamp(*displayId); - mFlinger->mTimeStats->setPresentTime(layerID, mCurrentFrameNumber, actualPresentTime); - mFlinger->mFrameTracer->traceTimestamp(layerID, getCurrentBufferId(), mCurrentFrameNumber, + mFlinger->mTimeStats->setPresentTime(layerId, mCurrentFrameNumber, actualPresentTime); + mFlinger->mFrameTracer->traceTimestamp(layerId, getCurrentBufferId(), mCurrentFrameNumber, actualPresentTime, FrameTracer::FrameEvent::PRESENT_FENCE); mFrameTracker.setActualPresentTime(actualPresentTime); diff --git a/services/surfaceflinger/BufferQueueLayer.cpp b/services/surfaceflinger/BufferQueueLayer.cpp index dc61e498df..37096f8024 100644 --- a/services/surfaceflinger/BufferQueueLayer.cpp +++ b/services/surfaceflinger/BufferQueueLayer.cpp @@ -223,7 +223,7 @@ status_t BufferQueueLayer::updateTexImage(bool& recomputeVisibleRegions, nsecs_t // BufferItem's that weren't actually queued. This can happen in shared // buffer mode. bool queuedBuffer = false; - const int32_t layerID = getSequence(); + const int32_t layerId = getSequence(); LayerRejecter r(mDrawingState, getCurrentState(), recomputeVisibleRegions, getProducerStickyTransform() != 0, mName, mOverrideScalingMode, getTransformToDisplayInverse()); @@ -264,7 +264,7 @@ status_t BufferQueueLayer::updateTexImage(bool& recomputeVisibleRegions, nsecs_t if (queuedBuffer) { Mutex::Autolock lock(mQueueItemLock); mConsumer->mergeSurfaceDamage(mQueueItems[0].mSurfaceDamage); - mFlinger->mTimeStats->removeTimeRecord(layerID, mQueueItems[0].mFrameNumber); + mFlinger->mTimeStats->removeTimeRecord(layerId, mQueueItems[0].mFrameNumber); mQueueItems.removeAt(0); mQueuedFrames--; } @@ -278,8 +278,8 @@ status_t BufferQueueLayer::updateTexImage(bool& recomputeVisibleRegions, nsecs_t Mutex::Autolock lock(mQueueItemLock); mQueueItems.clear(); mQueuedFrames = 0; - mFlinger->mTimeStats->onDestroy(layerID); - mFlinger->mFrameTracer->onDestroy(layerID); + mFlinger->mTimeStats->onDestroy(layerId); + mFlinger->mFrameTracer->onDestroy(layerId); } // Once we have hit this state, the shadow queue may no longer @@ -301,19 +301,19 @@ status_t BufferQueueLayer::updateTexImage(bool& recomputeVisibleRegions, nsecs_t // updateTexImage while (mQueueItems[0].mFrameNumber != currentFrameNumber) { mConsumer->mergeSurfaceDamage(mQueueItems[0].mSurfaceDamage); - mFlinger->mTimeStats->removeTimeRecord(layerID, mQueueItems[0].mFrameNumber); + mFlinger->mTimeStats->removeTimeRecord(layerId, mQueueItems[0].mFrameNumber); mQueueItems.removeAt(0); mQueuedFrames--; } uint64_t bufferID = mQueueItems[0].mGraphicBuffer->getId(); - mFlinger->mTimeStats->setAcquireFence(layerID, currentFrameNumber, + mFlinger->mTimeStats->setAcquireFence(layerId, currentFrameNumber, mQueueItems[0].mFenceTime); - mFlinger->mFrameTracer->traceFence(layerID, bufferID, currentFrameNumber, + mFlinger->mFrameTracer->traceFence(layerId, bufferID, currentFrameNumber, mQueueItems[0].mFenceTime, FrameTracer::FrameEvent::ACQUIRE_FENCE); - mFlinger->mTimeStats->setLatchTime(layerID, currentFrameNumber, latchTime); - mFlinger->mFrameTracer->traceTimestamp(layerID, bufferID, currentFrameNumber, latchTime, + mFlinger->mTimeStats->setLatchTime(layerId, currentFrameNumber, latchTime); + mFlinger->mFrameTracer->traceTimestamp(layerId, bufferID, currentFrameNumber, latchTime, FrameTracer::FrameEvent::LATCH); mQueueItems.removeAt(0); @@ -373,28 +373,28 @@ void BufferQueueLayer::latchPerFrameState( // ----------------------------------------------------------------------- void BufferQueueLayer::onFrameDequeued(const uint64_t bufferId) { - const int32_t layerID = getSequence(); - mFlinger->mFrameTracer->traceNewLayer(layerID, getName().c_str()); - mFlinger->mFrameTracer->traceTimestamp(layerID, bufferId, FrameTracer::UNSPECIFIED_FRAME_NUMBER, + const int32_t layerId = getSequence(); + mFlinger->mFrameTracer->traceNewLayer(layerId, getName().c_str()); + mFlinger->mFrameTracer->traceTimestamp(layerId, bufferId, FrameTracer::UNSPECIFIED_FRAME_NUMBER, systemTime(), FrameTracer::FrameEvent::DEQUEUE); } void BufferQueueLayer::onFrameDetached(const uint64_t bufferId) { - const int32_t layerID = getSequence(); - mFlinger->mFrameTracer->traceNewLayer(layerID, getName().c_str()); - mFlinger->mFrameTracer->traceTimestamp(layerID, bufferId, FrameTracer::UNSPECIFIED_FRAME_NUMBER, + const int32_t layerId = getSequence(); + mFlinger->mFrameTracer->traceNewLayer(layerId, getName().c_str()); + mFlinger->mFrameTracer->traceTimestamp(layerId, bufferId, FrameTracer::UNSPECIFIED_FRAME_NUMBER, systemTime(), FrameTracer::FrameEvent::DETACH); } void BufferQueueLayer::onFrameCancelled(const uint64_t bufferId) { - const int32_t layerID = getSequence(); - mFlinger->mFrameTracer->traceTimestamp(layerID, bufferId, FrameTracer::UNSPECIFIED_FRAME_NUMBER, + const int32_t layerId = getSequence(); + mFlinger->mFrameTracer->traceTimestamp(layerId, bufferId, FrameTracer::UNSPECIFIED_FRAME_NUMBER, systemTime(), FrameTracer::FrameEvent::CANCEL); } void BufferQueueLayer::onFrameAvailable(const BufferItem& item) { - const int32_t layerID = getSequence(); - mFlinger->mFrameTracer->traceTimestamp(layerID, item.mGraphicBuffer->getId(), item.mFrameNumber, + const int32_t layerId = getSequence(); + mFlinger->mFrameTracer->traceTimestamp(layerId, item.mGraphicBuffer->getId(), item.mFrameNumber, systemTime(), FrameTracer::FrameEvent::QUEUE); ATRACE_CALL(); diff --git a/services/surfaceflinger/BufferStateLayer.cpp b/services/surfaceflinger/BufferStateLayer.cpp index 5768edd744..2f3906b348 100644 --- a/services/surfaceflinger/BufferStateLayer.cpp +++ b/services/surfaceflinger/BufferStateLayer.cpp @@ -240,10 +240,10 @@ bool BufferStateLayer::setBuffer(const sp& buffer, nsecs_t postTi mCurrentState.modified = true; setTransactionFlags(eTransactionNeeded); - const int32_t layerID = getSequence(); - mFlinger->mTimeStats->setPostTime(layerID, mFrameNumber, getName().c_str(), postTime); - mFlinger->mFrameTracer->traceNewLayer(layerID, getName().c_str()); - mFlinger->mFrameTracer->traceTimestamp(layerID, buffer->getId(), mFrameNumber, postTime, + const int32_t layerId = getSequence(); + mFlinger->mTimeStats->setPostTime(layerId, mFrameNumber, getName().c_str(), postTime); + mFlinger->mFrameTracer->traceNewLayer(layerId, getName().c_str()); + mFlinger->mFrameTracer->traceTimestamp(layerId, buffer->getId(), mFrameNumber, postTime, FrameTracer::FrameEvent::POST); mCurrentState.desiredPresentTime = desiredPresentTime; @@ -461,7 +461,7 @@ status_t BufferStateLayer::updateTexImage(bool& /*recomputeVisibleRegions*/, nse return NO_ERROR; } - const int32_t layerID = getSequence(); + const int32_t layerId = getSequence(); // Reject if the layer is invalid uint32_t bufferWidth = s.buffer->width; @@ -483,7 +483,7 @@ status_t BufferStateLayer::updateTexImage(bool& /*recomputeVisibleRegions*/, nse ALOGE("[%s] rejecting buffer: " "bufferWidth=%d, bufferHeight=%d, front.active.{w=%d, h=%d}", getDebugName(), bufferWidth, bufferHeight, s.active.w, s.active.h); - mFlinger->mTimeStats->removeTimeRecord(layerID, mFrameNumber); + mFlinger->mTimeStats->removeTimeRecord(layerId, mFrameNumber); return BAD_VALUE; } @@ -500,18 +500,18 @@ status_t BufferStateLayer::updateTexImage(bool& /*recomputeVisibleRegions*/, nse // a GL-composited layer) not at all. status_t err = bindTextureImage(); if (err != NO_ERROR) { - mFlinger->mTimeStats->onDestroy(layerID); - mFlinger->mFrameTracer->onDestroy(layerID); + mFlinger->mTimeStats->onDestroy(layerId); + mFlinger->mFrameTracer->onDestroy(layerId); return BAD_VALUE; } } const uint64_t bufferID = getCurrentBufferId(); - mFlinger->mTimeStats->setAcquireFence(layerID, mFrameNumber, mBufferInfo.mFenceTime); - mFlinger->mFrameTracer->traceFence(layerID, bufferID, mFrameNumber, mBufferInfo.mFenceTime, + mFlinger->mTimeStats->setAcquireFence(layerId, mFrameNumber, mBufferInfo.mFenceTime); + mFlinger->mFrameTracer->traceFence(layerId, bufferID, mFrameNumber, mBufferInfo.mFenceTime, FrameTracer::FrameEvent::ACQUIRE_FENCE); - mFlinger->mTimeStats->setLatchTime(layerID, mFrameNumber, latchTime); - mFlinger->mFrameTracer->traceTimestamp(layerID, bufferID, mFrameNumber, latchTime, + mFlinger->mTimeStats->setLatchTime(layerId, mFrameNumber, latchTime); + mFlinger->mFrameTracer->traceTimestamp(layerId, bufferID, mFrameNumber, latchTime, FrameTracer::FrameEvent::LATCH); mCurrentStateModified = false; diff --git a/services/surfaceflinger/FrameTracer/FrameTracer.cpp b/services/surfaceflinger/FrameTracer/FrameTracer.cpp index 3a0408edbd..6f918438bc 100644 --- a/services/surfaceflinger/FrameTracer/FrameTracer.cpp +++ b/services/surfaceflinger/FrameTracer/FrameTracer.cpp @@ -44,52 +44,52 @@ void FrameTracer::registerDataSource() { FrameTracerDataSource::Register(dsd); } -void FrameTracer::traceNewLayer(int32_t layerID, const std::string& layerName) { - FrameTracerDataSource::Trace([this, layerID, &layerName](FrameTracerDataSource::TraceContext) { - if (mTraceTracker.find(layerID) == mTraceTracker.end()) { +void FrameTracer::traceNewLayer(int32_t layerId, const std::string& layerName) { + FrameTracerDataSource::Trace([this, layerId, &layerName](FrameTracerDataSource::TraceContext) { + if (mTraceTracker.find(layerId) == mTraceTracker.end()) { std::lock_guard lock(mTraceMutex); - mTraceTracker[layerID].layerName = layerName; + mTraceTracker[layerId].layerName = layerName; } }); } -void FrameTracer::traceTimestamp(int32_t layerID, uint64_t bufferID, uint64_t frameNumber, +void FrameTracer::traceTimestamp(int32_t layerId, uint64_t bufferID, uint64_t frameNumber, nsecs_t timestamp, FrameEvent::BufferEventType type, nsecs_t duration) { - FrameTracerDataSource::Trace([this, layerID, bufferID, frameNumber, timestamp, type, + FrameTracerDataSource::Trace([this, layerId, bufferID, frameNumber, timestamp, type, duration](FrameTracerDataSource::TraceContext ctx) { std::lock_guard lock(mTraceMutex); - if (mTraceTracker.find(layerID) == mTraceTracker.end()) { + if (mTraceTracker.find(layerId) == mTraceTracker.end()) { return; } // Handle any pending fences for this buffer. - tracePendingFencesLocked(ctx, layerID, bufferID); + tracePendingFencesLocked(ctx, layerId, bufferID); // Complete current trace. - traceLocked(ctx, layerID, bufferID, frameNumber, timestamp, type, duration); + traceLocked(ctx, layerId, bufferID, frameNumber, timestamp, type, duration); }); } -void FrameTracer::traceFence(int32_t layerID, uint64_t bufferID, uint64_t frameNumber, +void FrameTracer::traceFence(int32_t layerId, uint64_t bufferID, uint64_t frameNumber, const std::shared_ptr& fence, FrameEvent::BufferEventType type, nsecs_t startTime) { - FrameTracerDataSource::Trace([this, layerID, bufferID, frameNumber, &fence, type, + FrameTracerDataSource::Trace([this, layerId, bufferID, frameNumber, &fence, type, startTime](FrameTracerDataSource::TraceContext ctx) { const nsecs_t signalTime = fence->getSignalTime(); if (signalTime != Fence::SIGNAL_TIME_INVALID) { std::lock_guard lock(mTraceMutex); - if (mTraceTracker.find(layerID) == mTraceTracker.end()) { + if (mTraceTracker.find(layerId) == mTraceTracker.end()) { return; } // Handle any pending fences for this buffer. - tracePendingFencesLocked(ctx, layerID, bufferID); + tracePendingFencesLocked(ctx, layerId, bufferID); if (signalTime != Fence::SIGNAL_TIME_PENDING) { - traceSpanLocked(ctx, layerID, bufferID, frameNumber, type, startTime, signalTime); + traceSpanLocked(ctx, layerId, bufferID, frameNumber, type, startTime, signalTime); } else { - mTraceTracker[layerID].pendingFences[bufferID].push_back( + mTraceTracker[layerId].pendingFences[bufferID].push_back( {.frameNumber = frameNumber, .type = type, .fence = fence, @@ -100,9 +100,9 @@ void FrameTracer::traceFence(int32_t layerID, uint64_t bufferID, uint64_t frameN } void FrameTracer::tracePendingFencesLocked(FrameTracerDataSource::TraceContext& ctx, - int32_t layerID, uint64_t bufferID) { - if (mTraceTracker[layerID].pendingFences.count(bufferID)) { - auto& pendingFences = mTraceTracker[layerID].pendingFences[bufferID]; + int32_t layerId, uint64_t bufferID) { + if (mTraceTracker[layerId].pendingFences.count(bufferID)) { + auto& pendingFences = mTraceTracker[layerId].pendingFences[bufferID]; for (size_t i = 0; i < pendingFences.size(); ++i) { auto& pendingFence = pendingFences[i]; @@ -116,7 +116,7 @@ void FrameTracer::tracePendingFencesLocked(FrameTracerDataSource::TraceContext& if (signalTime != Fence::SIGNAL_TIME_INVALID && systemTime() - signalTime < kFenceSignallingDeadline) { - traceSpanLocked(ctx, layerID, bufferID, pendingFence.frameNumber, pendingFence.type, + traceSpanLocked(ctx, layerId, bufferID, pendingFence.frameNumber, pendingFence.type, pendingFence.startTime, signalTime); } @@ -126,7 +126,7 @@ void FrameTracer::tracePendingFencesLocked(FrameTracerDataSource::TraceContext& } } -void FrameTracer::traceLocked(FrameTracerDataSource::TraceContext& ctx, int32_t layerID, +void FrameTracer::traceLocked(FrameTracerDataSource::TraceContext& ctx, int32_t layerId, uint64_t bufferID, uint64_t frameNumber, nsecs_t timestamp, FrameEvent::BufferEventType type, nsecs_t duration) { auto packet = ctx.NewTracePacket(); @@ -138,9 +138,9 @@ void FrameTracer::traceLocked(FrameTracerDataSource::TraceContext& ctx, int32_t } event->set_type(type); - if (mTraceTracker.find(layerID) != mTraceTracker.end() && - !mTraceTracker[layerID].layerName.empty()) { - const std::string& layerName = mTraceTracker[layerID].layerName; + if (mTraceTracker.find(layerId) != mTraceTracker.end() && + !mTraceTracker[layerId].layerName.empty()) { + const std::string& layerName = mTraceTracker[layerId].layerName; event->set_layer_name(layerName.c_str(), layerName.size()); } @@ -149,7 +149,7 @@ void FrameTracer::traceLocked(FrameTracerDataSource::TraceContext& ctx, int32_t } } -void FrameTracer::traceSpanLocked(FrameTracerDataSource::TraceContext& ctx, int32_t layerID, +void FrameTracer::traceSpanLocked(FrameTracerDataSource::TraceContext& ctx, int32_t layerId, uint64_t bufferID, uint64_t frameNumber, FrameEvent::BufferEventType type, nsecs_t startTime, nsecs_t endTime) { @@ -159,12 +159,12 @@ void FrameTracer::traceSpanLocked(FrameTracerDataSource::TraceContext& ctx, int3 timestamp = startTime; duration = endTime - startTime; } - traceLocked(ctx, layerID, bufferID, frameNumber, timestamp, type, duration); + traceLocked(ctx, layerId, bufferID, frameNumber, timestamp, type, duration); } -void FrameTracer::onDestroy(int32_t layerID) { +void FrameTracer::onDestroy(int32_t layerId) { std::lock_guard traceLock(mTraceMutex); - mTraceTracker.erase(layerID); + mTraceTracker.erase(layerId); } std::string FrameTracer::miniDump() { diff --git a/services/surfaceflinger/FrameTracer/FrameTracer.h b/services/surfaceflinger/FrameTracer/FrameTracer.h index e91a7503cd..ef5df90fea 100644 --- a/services/surfaceflinger/FrameTracer/FrameTracer.h +++ b/services/surfaceflinger/FrameTracer/FrameTracer.h @@ -47,21 +47,21 @@ public: void registerDataSource(); // Starts tracking a new layer for tracing. Needs to be called once before traceTimestamp() or // traceFence() for each layer. - void traceNewLayer(int32_t layerID, const std::string& layerName); + void traceNewLayer(int32_t layerId, const std::string& layerName); // Creates a trace point at the timestamp provided. - void traceTimestamp(int32_t layerID, uint64_t bufferID, uint64_t frameNumber, nsecs_t timestamp, + void traceTimestamp(int32_t layerId, uint64_t bufferID, uint64_t frameNumber, nsecs_t timestamp, FrameEvent::BufferEventType type, nsecs_t duration = 0); // Creates a trace point after the provided fence has been signalled. If a startTime is provided // the trace will have be timestamped from startTime until fence signalling time. If no // startTime is provided, a durationless trace point will be created timestamped at fence // signalling time. If the fence hasn't signalled yet, the trace point will be created the next // time after signalling a trace call for this buffer occurs. - void traceFence(int32_t layerID, uint64_t bufferID, uint64_t frameNumber, + void traceFence(int32_t layerId, uint64_t bufferID, uint64_t frameNumber, const std::shared_ptr& fence, FrameEvent::BufferEventType type, nsecs_t startTime = 0); // Takes care of cleanup when a layer is destroyed. - void onDestroy(int32_t layerID); + void onDestroy(int32_t layerId); std::string miniDump(); @@ -88,15 +88,15 @@ private: // Checks if any pending fences for a layer and buffer have signalled and, if they have, creates // trace points for them. - void tracePendingFencesLocked(FrameTracerDataSource::TraceContext& ctx, int32_t layerID, + void tracePendingFencesLocked(FrameTracerDataSource::TraceContext& ctx, int32_t layerId, uint64_t bufferID); // Creates a trace point by translating a start time and an end time to a timestamp and // duration. If startTime is later than end time it sets end time as the timestamp and the // duration to 0. Used by traceFence(). - void traceSpanLocked(FrameTracerDataSource::TraceContext& ctx, int32_t layerID, + void traceSpanLocked(FrameTracerDataSource::TraceContext& ctx, int32_t layerId, uint64_t bufferID, uint64_t frameNumber, FrameEvent::BufferEventType type, nsecs_t startTime, nsecs_t endTime); - void traceLocked(FrameTracerDataSource::TraceContext& ctx, int32_t layerID, uint64_t bufferID, + void traceLocked(FrameTracerDataSource::TraceContext& ctx, int32_t layerId, uint64_t bufferID, uint64_t frameNumber, nsecs_t timestamp, FrameEvent::BufferEventType type, nsecs_t duration = 0); diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp index d5a9ae1b3b..3757fc7c00 100644 --- a/services/surfaceflinger/Layer.cpp +++ b/services/surfaceflinger/Layer.cpp @@ -1356,9 +1356,9 @@ void Layer::dumpCallingUidPid(std::string& result) const { void Layer::onDisconnect() { Mutex::Autolock lock(mFrameEventHistoryMutex); mFrameEventHistory.onDisconnect(); - const int32_t layerID = getSequence(); - mFlinger->mTimeStats->onDestroy(layerID); - mFlinger->mFrameTracer->onDestroy(layerID); + const int32_t layerId = getSequence(); + mFlinger->mTimeStats->onDestroy(layerId); + mFlinger->mFrameTracer->onDestroy(layerId); } void Layer::addAndGetFrameTimestamps(const NewFrameEventsEntry* newTimestamps, diff --git a/services/surfaceflinger/TimeStats/TimeStats.cpp b/services/surfaceflinger/TimeStats/TimeStats.cpp index 3e47ec6856..611afce604 100644 --- a/services/surfaceflinger/TimeStats/TimeStats.cpp +++ b/services/surfaceflinger/TimeStats/TimeStats.cpp @@ -113,9 +113,9 @@ void TimeStats::incrementClientCompositionFrames() { mTimeStats.clientCompositionFrames++; } -bool TimeStats::recordReadyLocked(int32_t layerID, TimeRecord* timeRecord) { +bool TimeStats::recordReadyLocked(int32_t layerId, TimeRecord* timeRecord) { if (!timeRecord->ready) { - ALOGV("[%d]-[%" PRIu64 "]-presentFence is still not received", layerID, + ALOGV("[%d]-[%" PRIu64 "]-presentFence is still not received", layerId, timeRecord->frameTime.frameNumber); return false; } @@ -128,7 +128,7 @@ bool TimeStats::recordReadyLocked(int32_t layerID, TimeRecord* timeRecord) { timeRecord->frameTime.acquireTime = timeRecord->acquireFence->getSignalTime(); timeRecord->acquireFence = nullptr; } else { - ALOGV("[%d]-[%" PRIu64 "]-acquireFence signal time is invalid", layerID, + ALOGV("[%d]-[%" PRIu64 "]-acquireFence signal time is invalid", layerId, timeRecord->frameTime.frameNumber); } } @@ -141,7 +141,7 @@ bool TimeStats::recordReadyLocked(int32_t layerID, TimeRecord* timeRecord) { timeRecord->frameTime.presentTime = timeRecord->presentFence->getSignalTime(); timeRecord->presentFence = nullptr; } else { - ALOGV("[%d]-[%" PRIu64 "]-presentFence signal time invalid", layerID, + ALOGV("[%d]-[%" PRIu64 "]-presentFence signal time invalid", layerId, timeRecord->frameTime.frameNumber); } } @@ -155,15 +155,15 @@ static int32_t msBetween(nsecs_t start, nsecs_t end) { return static_cast(delta); } -void TimeStats::flushAvailableRecordsToStatsLocked(int32_t layerID) { +void TimeStats::flushAvailableRecordsToStatsLocked(int32_t layerId) { ATRACE_CALL(); - LayerRecord& layerRecord = mTimeStatsTracker[layerID]; + LayerRecord& layerRecord = mTimeStatsTracker[layerId]; TimeRecord& prevTimeRecord = layerRecord.prevTimeRecord; std::deque& timeRecords = layerRecord.timeRecords; while (!timeRecords.empty()) { - if (!recordReadyLocked(layerID, &timeRecords[0])) break; - ALOGV("[%d]-[%" PRIu64 "]-presentFenceTime[%" PRId64 "]", layerID, + if (!recordReadyLocked(layerId, &timeRecords[0])) break; + ALOGV("[%d]-[%" PRIu64 "]-presentFenceTime[%" PRId64 "]", layerId, timeRecords[0].frameTime.frameNumber, timeRecords[0].frameTime.presentTime); if (prevTimeRecord.ready) { @@ -178,37 +178,37 @@ void TimeStats::flushAvailableRecordsToStatsLocked(int32_t layerID) { const int32_t postToAcquireMs = msBetween(timeRecords[0].frameTime.postTime, timeRecords[0].frameTime.acquireTime); - ALOGV("[%d]-[%" PRIu64 "]-post2acquire[%d]", layerID, + ALOGV("[%d]-[%" PRIu64 "]-post2acquire[%d]", layerId, timeRecords[0].frameTime.frameNumber, postToAcquireMs); timeStatsLayer.deltas["post2acquire"].insert(postToAcquireMs); const int32_t postToPresentMs = msBetween(timeRecords[0].frameTime.postTime, timeRecords[0].frameTime.presentTime); - ALOGV("[%d]-[%" PRIu64 "]-post2present[%d]", layerID, + ALOGV("[%d]-[%" PRIu64 "]-post2present[%d]", layerId, timeRecords[0].frameTime.frameNumber, postToPresentMs); timeStatsLayer.deltas["post2present"].insert(postToPresentMs); const int32_t acquireToPresentMs = msBetween(timeRecords[0].frameTime.acquireTime, timeRecords[0].frameTime.presentTime); - ALOGV("[%d]-[%" PRIu64 "]-acquire2present[%d]", layerID, + ALOGV("[%d]-[%" PRIu64 "]-acquire2present[%d]", layerId, timeRecords[0].frameTime.frameNumber, acquireToPresentMs); timeStatsLayer.deltas["acquire2present"].insert(acquireToPresentMs); const int32_t latchToPresentMs = msBetween(timeRecords[0].frameTime.latchTime, timeRecords[0].frameTime.presentTime); - ALOGV("[%d]-[%" PRIu64 "]-latch2present[%d]", layerID, + ALOGV("[%d]-[%" PRIu64 "]-latch2present[%d]", layerId, timeRecords[0].frameTime.frameNumber, latchToPresentMs); timeStatsLayer.deltas["latch2present"].insert(latchToPresentMs); const int32_t desiredToPresentMs = msBetween(timeRecords[0].frameTime.desiredTime, timeRecords[0].frameTime.presentTime); - ALOGV("[%d]-[%" PRIu64 "]-desired2present[%d]", layerID, + ALOGV("[%d]-[%" PRIu64 "]-desired2present[%d]", layerId, timeRecords[0].frameTime.frameNumber, desiredToPresentMs); timeStatsLayer.deltas["desired2present"].insert(desiredToPresentMs); const int32_t presentToPresentMs = msBetween(prevTimeRecord.frameTime.presentTime, timeRecords[0].frameTime.presentTime); - ALOGV("[%d]-[%" PRIu64 "]-present2present[%d]", layerID, + ALOGV("[%d]-[%" PRIu64 "]-present2present[%d]", layerId, timeRecords[0].frameTime.frameNumber, presentToPresentMs); timeStatsLayer.deltas["present2present"].insert(presentToPresentMs); } @@ -227,28 +227,28 @@ static bool layerNameIsValid(const std::string& layerName) { layerName.compare(0, kMinLenLayerName, kPopupWindowPrefix) != 0; } -void TimeStats::setPostTime(int32_t layerID, uint64_t frameNumber, const std::string& layerName, +void TimeStats::setPostTime(int32_t layerId, uint64_t frameNumber, const std::string& layerName, nsecs_t postTime) { if (!mEnabled.load()) return; ATRACE_CALL(); - ALOGV("[%d]-[%" PRIu64 "]-[%s]-PostTime[%" PRId64 "]", layerID, frameNumber, layerName.c_str(), + ALOGV("[%d]-[%" PRIu64 "]-[%s]-PostTime[%" PRId64 "]", layerId, frameNumber, layerName.c_str(), postTime); std::lock_guard lock(mMutex); if (!mTimeStats.stats.count(layerName) && mTimeStats.stats.size() >= MAX_NUM_LAYER_STATS) { return; } - if (!mTimeStatsTracker.count(layerID) && mTimeStatsTracker.size() < MAX_NUM_LAYER_RECORDS && + if (!mTimeStatsTracker.count(layerId) && mTimeStatsTracker.size() < MAX_NUM_LAYER_RECORDS && layerNameIsValid(layerName)) { - mTimeStatsTracker[layerID].layerName = layerName; + mTimeStatsTracker[layerId].layerName = layerName; } - if (!mTimeStatsTracker.count(layerID)) return; - LayerRecord& layerRecord = mTimeStatsTracker[layerID]; + if (!mTimeStatsTracker.count(layerId)) return; + LayerRecord& layerRecord = mTimeStatsTracker[layerId]; if (layerRecord.timeRecords.size() == MAX_NUM_TIME_RECORDS) { ALOGE("[%d]-[%s]-timeRecords is at its maximum size[%zu]. Ignore this when unittesting.", - layerID, layerRecord.layerName.c_str(), MAX_NUM_TIME_RECORDS); - mTimeStatsTracker.erase(layerID); + layerId, layerRecord.layerName.c_str(), MAX_NUM_TIME_RECORDS); + mTimeStatsTracker.erase(layerId); return; } // For most media content, the acquireFence is invalid because the buffer is @@ -270,15 +270,15 @@ void TimeStats::setPostTime(int32_t layerID, uint64_t frameNumber, const std::st layerRecord.waitData = layerRecord.timeRecords.size() - 1; } -void TimeStats::setLatchTime(int32_t layerID, uint64_t frameNumber, nsecs_t latchTime) { +void TimeStats::setLatchTime(int32_t layerId, uint64_t frameNumber, nsecs_t latchTime) { if (!mEnabled.load()) return; ATRACE_CALL(); - ALOGV("[%d]-[%" PRIu64 "]-LatchTime[%" PRId64 "]", layerID, frameNumber, latchTime); + ALOGV("[%d]-[%" PRIu64 "]-LatchTime[%" PRId64 "]", layerId, frameNumber, latchTime); std::lock_guard lock(mMutex); - if (!mTimeStatsTracker.count(layerID)) return; - LayerRecord& layerRecord = mTimeStatsTracker[layerID]; + if (!mTimeStatsTracker.count(layerId)) return; + LayerRecord& layerRecord = mTimeStatsTracker[layerId]; if (layerRecord.waitData < 0 || layerRecord.waitData >= static_cast(layerRecord.timeRecords.size())) return; @@ -288,15 +288,15 @@ void TimeStats::setLatchTime(int32_t layerID, uint64_t frameNumber, nsecs_t latc } } -void TimeStats::setDesiredTime(int32_t layerID, uint64_t frameNumber, nsecs_t desiredTime) { +void TimeStats::setDesiredTime(int32_t layerId, uint64_t frameNumber, nsecs_t desiredTime) { if (!mEnabled.load()) return; ATRACE_CALL(); - ALOGV("[%d]-[%" PRIu64 "]-DesiredTime[%" PRId64 "]", layerID, frameNumber, desiredTime); + ALOGV("[%d]-[%" PRIu64 "]-DesiredTime[%" PRId64 "]", layerId, frameNumber, desiredTime); std::lock_guard lock(mMutex); - if (!mTimeStatsTracker.count(layerID)) return; - LayerRecord& layerRecord = mTimeStatsTracker[layerID]; + if (!mTimeStatsTracker.count(layerId)) return; + LayerRecord& layerRecord = mTimeStatsTracker[layerId]; if (layerRecord.waitData < 0 || layerRecord.waitData >= static_cast(layerRecord.timeRecords.size())) return; @@ -306,15 +306,15 @@ void TimeStats::setDesiredTime(int32_t layerID, uint64_t frameNumber, nsecs_t de } } -void TimeStats::setAcquireTime(int32_t layerID, uint64_t frameNumber, nsecs_t acquireTime) { +void TimeStats::setAcquireTime(int32_t layerId, uint64_t frameNumber, nsecs_t acquireTime) { if (!mEnabled.load()) return; ATRACE_CALL(); - ALOGV("[%d]-[%" PRIu64 "]-AcquireTime[%" PRId64 "]", layerID, frameNumber, acquireTime); + ALOGV("[%d]-[%" PRIu64 "]-AcquireTime[%" PRId64 "]", layerId, frameNumber, acquireTime); std::lock_guard lock(mMutex); - if (!mTimeStatsTracker.count(layerID)) return; - LayerRecord& layerRecord = mTimeStatsTracker[layerID]; + if (!mTimeStatsTracker.count(layerId)) return; + LayerRecord& layerRecord = mTimeStatsTracker[layerId]; if (layerRecord.waitData < 0 || layerRecord.waitData >= static_cast(layerRecord.timeRecords.size())) return; @@ -324,17 +324,17 @@ void TimeStats::setAcquireTime(int32_t layerID, uint64_t frameNumber, nsecs_t ac } } -void TimeStats::setAcquireFence(int32_t layerID, uint64_t frameNumber, +void TimeStats::setAcquireFence(int32_t layerId, uint64_t frameNumber, const std::shared_ptr& acquireFence) { if (!mEnabled.load()) return; ATRACE_CALL(); - ALOGV("[%d]-[%" PRIu64 "]-AcquireFenceTime[%" PRId64 "]", layerID, frameNumber, + ALOGV("[%d]-[%" PRIu64 "]-AcquireFenceTime[%" PRId64 "]", layerId, frameNumber, acquireFence->getSignalTime()); std::lock_guard lock(mMutex); - if (!mTimeStatsTracker.count(layerID)) return; - LayerRecord& layerRecord = mTimeStatsTracker[layerID]; + if (!mTimeStatsTracker.count(layerId)) return; + LayerRecord& layerRecord = mTimeStatsTracker[layerId]; if (layerRecord.waitData < 0 || layerRecord.waitData >= static_cast(layerRecord.timeRecords.size())) return; @@ -344,15 +344,15 @@ void TimeStats::setAcquireFence(int32_t layerID, uint64_t frameNumber, } } -void TimeStats::setPresentTime(int32_t layerID, uint64_t frameNumber, nsecs_t presentTime) { +void TimeStats::setPresentTime(int32_t layerId, uint64_t frameNumber, nsecs_t presentTime) { if (!mEnabled.load()) return; ATRACE_CALL(); - ALOGV("[%d]-[%" PRIu64 "]-PresentTime[%" PRId64 "]", layerID, frameNumber, presentTime); + ALOGV("[%d]-[%" PRIu64 "]-PresentTime[%" PRId64 "]", layerId, frameNumber, presentTime); std::lock_guard lock(mMutex); - if (!mTimeStatsTracker.count(layerID)) return; - LayerRecord& layerRecord = mTimeStatsTracker[layerID]; + if (!mTimeStatsTracker.count(layerId)) return; + LayerRecord& layerRecord = mTimeStatsTracker[layerId]; if (layerRecord.waitData < 0 || layerRecord.waitData >= static_cast(layerRecord.timeRecords.size())) return; @@ -363,20 +363,20 @@ void TimeStats::setPresentTime(int32_t layerID, uint64_t frameNumber, nsecs_t pr layerRecord.waitData++; } - flushAvailableRecordsToStatsLocked(layerID); + flushAvailableRecordsToStatsLocked(layerId); } -void TimeStats::setPresentFence(int32_t layerID, uint64_t frameNumber, +void TimeStats::setPresentFence(int32_t layerId, uint64_t frameNumber, const std::shared_ptr& presentFence) { if (!mEnabled.load()) return; ATRACE_CALL(); - ALOGV("[%d]-[%" PRIu64 "]-PresentFenceTime[%" PRId64 "]", layerID, frameNumber, + ALOGV("[%d]-[%" PRIu64 "]-PresentFenceTime[%" PRId64 "]", layerId, frameNumber, presentFence->getSignalTime()); std::lock_guard lock(mMutex); - if (!mTimeStatsTracker.count(layerID)) return; - LayerRecord& layerRecord = mTimeStatsTracker[layerID]; + if (!mTimeStatsTracker.count(layerId)) return; + LayerRecord& layerRecord = mTimeStatsTracker[layerId]; if (layerRecord.waitData < 0 || layerRecord.waitData >= static_cast(layerRecord.timeRecords.size())) return; @@ -387,25 +387,25 @@ void TimeStats::setPresentFence(int32_t layerID, uint64_t frameNumber, layerRecord.waitData++; } - flushAvailableRecordsToStatsLocked(layerID); + flushAvailableRecordsToStatsLocked(layerId); } -void TimeStats::onDestroy(int32_t layerID) { +void TimeStats::onDestroy(int32_t layerId) { ATRACE_CALL(); - ALOGV("[%d]-onDestroy", layerID); + ALOGV("[%d]-onDestroy", layerId); std::lock_guard lock(mMutex); - mTimeStatsTracker.erase(layerID); + mTimeStatsTracker.erase(layerId); } -void TimeStats::removeTimeRecord(int32_t layerID, uint64_t frameNumber) { +void TimeStats::removeTimeRecord(int32_t layerId, uint64_t frameNumber) { if (!mEnabled.load()) return; ATRACE_CALL(); - ALOGV("[%d]-[%" PRIu64 "]-removeTimeRecord", layerID, frameNumber); + ALOGV("[%d]-[%" PRIu64 "]-removeTimeRecord", layerId, frameNumber); std::lock_guard lock(mMutex); - if (!mTimeStatsTracker.count(layerID)) return; - LayerRecord& layerRecord = mTimeStatsTracker[layerID]; + if (!mTimeStatsTracker.count(layerId)) return; + LayerRecord& layerRecord = mTimeStatsTracker[layerId]; size_t removeAt = 0; for (const TimeRecord& record : layerRecord.timeRecords) { if (record.frameTime.frameNumber == frameNumber) break; diff --git a/services/surfaceflinger/TimeStats/TimeStats.h b/services/surfaceflinger/TimeStats/TimeStats.h index 1313132920..6e71f5a14e 100644 --- a/services/surfaceflinger/TimeStats/TimeStats.h +++ b/services/surfaceflinger/TimeStats/TimeStats.h @@ -44,20 +44,20 @@ public: virtual void incrementMissedFrames() = 0; virtual void incrementClientCompositionFrames() = 0; - virtual void setPostTime(int32_t layerID, uint64_t frameNumber, const std::string& layerName, + virtual void setPostTime(int32_t layerId, uint64_t frameNumber, const std::string& layerName, nsecs_t postTime) = 0; - virtual void setLatchTime(int32_t layerID, uint64_t frameNumber, nsecs_t latchTime) = 0; - virtual void setDesiredTime(int32_t layerID, uint64_t frameNumber, nsecs_t desiredTime) = 0; - virtual void setAcquireTime(int32_t layerID, uint64_t frameNumber, nsecs_t acquireTime) = 0; - virtual void setAcquireFence(int32_t layerID, uint64_t frameNumber, + virtual void setLatchTime(int32_t layerId, uint64_t frameNumber, nsecs_t latchTime) = 0; + virtual void setDesiredTime(int32_t layerId, uint64_t frameNumber, nsecs_t desiredTime) = 0; + virtual void setAcquireTime(int32_t layerId, uint64_t frameNumber, nsecs_t acquireTime) = 0; + virtual void setAcquireFence(int32_t layerId, uint64_t frameNumber, const std::shared_ptr& acquireFence) = 0; - virtual void setPresentTime(int32_t layerID, uint64_t frameNumber, nsecs_t presentTime) = 0; - virtual void setPresentFence(int32_t layerID, uint64_t frameNumber, + virtual void setPresentTime(int32_t layerId, uint64_t frameNumber, nsecs_t presentTime) = 0; + virtual void setPresentFence(int32_t layerId, uint64_t frameNumber, const std::shared_ptr& presentFence) = 0; // Clean up the layer record - virtual void onDestroy(int32_t layerID) = 0; + virtual void onDestroy(int32_t layerId) = 0; // If SF skips or rejects a buffer, remove the corresponding TimeRecord. - virtual void removeTimeRecord(int32_t layerID, uint64_t frameNumber) = 0; + virtual void removeTimeRecord(int32_t layerId, uint64_t frameNumber) = 0; virtual void setPowerMode(int32_t powerMode) = 0; // Source of truth is RefrehRateStats. @@ -116,20 +116,20 @@ public: void incrementMissedFrames() override; void incrementClientCompositionFrames() override; - void setPostTime(int32_t layerID, uint64_t frameNumber, const std::string& layerName, + void setPostTime(int32_t layerId, uint64_t frameNumber, const std::string& layerName, nsecs_t postTime) override; - void setLatchTime(int32_t layerID, uint64_t frameNumber, nsecs_t latchTime) override; - void setDesiredTime(int32_t layerID, uint64_t frameNumber, nsecs_t desiredTime) override; - void setAcquireTime(int32_t layerID, uint64_t frameNumber, nsecs_t acquireTime) override; - void setAcquireFence(int32_t layerID, uint64_t frameNumber, + void setLatchTime(int32_t layerId, uint64_t frameNumber, nsecs_t latchTime) override; + void setDesiredTime(int32_t layerId, uint64_t frameNumber, nsecs_t desiredTime) override; + void setAcquireTime(int32_t layerId, uint64_t frameNumber, nsecs_t acquireTime) override; + void setAcquireFence(int32_t layerId, uint64_t frameNumber, const std::shared_ptr& acquireFence) override; - void setPresentTime(int32_t layerID, uint64_t frameNumber, nsecs_t presentTime) override; - void setPresentFence(int32_t layerID, uint64_t frameNumber, + void setPresentTime(int32_t layerId, uint64_t frameNumber, nsecs_t presentTime) override; + void setPresentFence(int32_t layerId, uint64_t frameNumber, const std::shared_ptr& presentFence) override; // Clean up the layer record - void onDestroy(int32_t layerID) override; + void onDestroy(int32_t layerId) override; // If SF skips or rejects a buffer, remove the corresponding TimeRecord. - void removeTimeRecord(int32_t layerID, uint64_t frameNumber) override; + void removeTimeRecord(int32_t layerId, uint64_t frameNumber) override; void setPowerMode(int32_t powerMode) override; // Source of truth is RefrehRateStats. @@ -139,8 +139,8 @@ public: static const size_t MAX_NUM_TIME_RECORDS = 64; private: - bool recordReadyLocked(int32_t layerID, TimeRecord* timeRecord); - void flushAvailableRecordsToStatsLocked(int32_t layerID); + bool recordReadyLocked(int32_t layerId, TimeRecord* timeRecord); + void flushAvailableRecordsToStatsLocked(int32_t layerId); void flushPowerTimeLocked(); void flushAvailableGlobalRecordsToStatsLocked(); @@ -152,7 +152,7 @@ private: std::atomic mEnabled = false; std::mutex mMutex; TimeStatsHelper::TimeStatsGlobal mTimeStats; - // Hashmap for LayerRecord with layerID as the hash key + // Hashmap for LayerRecord with layerId as the hash key std::unordered_map mTimeStatsTracker; PowerTime mPowerTime; GlobalRecord mGlobalRecord; diff --git a/services/surfaceflinger/tests/unittests/FrameTracerTest.cpp b/services/surfaceflinger/tests/unittests/FrameTracerTest.cpp index b5af591e25..c334bcf85d 100644 --- a/services/surfaceflinger/tests/unittests/FrameTracerTest.cpp +++ b/services/surfaceflinger/tests/unittests/FrameTracerTest.cpp @@ -82,8 +82,8 @@ TEST_F(FrameTracerTest, traceNewLayerStartsTrackingLayerWhenTracing) { "FrameTracer miniDump:\nNumber of layers currently being traced is 0\n"); const std::string layerName = "co.layername#0"; - const int32_t layerID = 5; - mFrameTracer->traceNewLayer(layerID, layerName); + const int32_t layerId = 5; + mFrameTracer->traceNewLayer(layerId, layerName); EXPECT_EQ(mFrameTracer->miniDump(), "FrameTracer miniDump:\nNumber of layers currently being traced is 0\n"); @@ -92,7 +92,7 @@ TEST_F(FrameTracerTest, traceNewLayerStartsTrackingLayerWhenTracing) { tracingSession->StartBlocking(); EXPECT_EQ(mFrameTracer->miniDump(), "FrameTracer miniDump:\nNumber of layers currently being traced is 0\n"); - mFrameTracer->traceNewLayer(layerID, layerName); + mFrameTracer->traceNewLayer(layerId, layerName); EXPECT_EQ(mFrameTracer->miniDump(), "FrameTracer miniDump:\nNumber of layers currently being traced is 1\n"); tracingSession->StopBlocking(); @@ -103,31 +103,31 @@ TEST_F(FrameTracerTest, onDestroyRemovesTheTrackedLayer) { "FrameTracer miniDump:\nNumber of layers currently being traced is 0\n"); const std::string layerName = "co.layername#0"; - const int32_t layerID = 5; - const int32_t secondLayerID = 6; + const int32_t layerId = 5; + const int32_t secondlayerId = 6; auto tracingSession = getTracingSessionForTest(); tracingSession->StartBlocking(); - mFrameTracer->traceNewLayer(layerID, layerName); - mFrameTracer->traceNewLayer(secondLayerID, layerName); + mFrameTracer->traceNewLayer(layerId, layerName); + mFrameTracer->traceNewLayer(secondlayerId, layerName); EXPECT_EQ(mFrameTracer->miniDump(), "FrameTracer miniDump:\nNumber of layers currently being traced is 2\n"); tracingSession->StopBlocking(); - mFrameTracer->onDestroy(layerID); + mFrameTracer->onDestroy(layerId); EXPECT_EQ(mFrameTracer->miniDump(), "FrameTracer miniDump:\nNumber of layers currently being traced is 1\n"); - mFrameTracer->onDestroy(layerID); + mFrameTracer->onDestroy(layerId); EXPECT_EQ(mFrameTracer->miniDump(), "FrameTracer miniDump:\nNumber of layers currently being traced is 1\n"); - mFrameTracer->onDestroy(secondLayerID); + mFrameTracer->onDestroy(secondlayerId); EXPECT_EQ(mFrameTracer->miniDump(), "FrameTracer miniDump:\nNumber of layers currently being traced is 0\n"); } TEST_F(FrameTracerTest, canTraceAfterAddingLayer) { const std::string layerName = "co.layername#0"; - const int32_t layerID = 1; + const int32_t layerId = 1; const uint32_t bufferID = 2; const uint64_t frameNumber = 3; const nsecs_t timestamp = 4; @@ -141,9 +141,9 @@ TEST_F(FrameTracerTest, canTraceAfterAddingLayer) { // Clean up irrelevant traces. tracingSession->ReadTraceBlocking(); - mFrameTracer->traceTimestamp(layerID, bufferID, frameNumber, timestamp, type, duration); + mFrameTracer->traceTimestamp(layerId, bufferID, frameNumber, timestamp, type, duration); // Create second trace packet to finalize the previous one. - mFrameTracer->traceTimestamp(layerID, 0, 0, 0, FrameTracer::FrameEvent::UNSPECIFIED); + mFrameTracer->traceTimestamp(layerId, 0, 0, 0, FrameTracer::FrameEvent::UNSPECIFIED); tracingSession->StopBlocking(); std::vector raw_trace = tracingSession->ReadTraceBlocking(); @@ -157,10 +157,10 @@ TEST_F(FrameTracerTest, canTraceAfterAddingLayer) { // Clean up irrelevant traces. tracingSession->ReadTraceBlocking(); - mFrameTracer->traceNewLayer(layerID, layerName); - mFrameTracer->traceTimestamp(layerID, bufferID, frameNumber, timestamp, type, duration); + mFrameTracer->traceNewLayer(layerId, layerName); + mFrameTracer->traceTimestamp(layerId, bufferID, frameNumber, timestamp, type, duration); // Create second trace packet to finalize the previous one. - mFrameTracer->traceTimestamp(layerID, 0, 0, 0, FrameTracer::FrameEvent::UNSPECIFIED); + mFrameTracer->traceTimestamp(layerId, 0, 0, 0, FrameTracer::FrameEvent::UNSPECIFIED); tracingSession->StopBlocking(); std::vector raw_trace = tracingSession->ReadTraceBlocking(); @@ -191,7 +191,7 @@ TEST_F(FrameTracerTest, canTraceAfterAddingLayer) { TEST_F(FrameTracerTest, traceFenceTriggersOnNextTraceAfterFenceFired) { const std::string layerName = "co.layername#0"; - const int32_t layerID = 5; + const int32_t layerId = 5; const uint32_t bufferID = 4; const uint64_t frameNumber = 3; const auto type = FrameTracer::FrameEvent::ACQUIRE_FENCE; @@ -204,10 +204,10 @@ TEST_F(FrameTracerTest, traceFenceTriggersOnNextTraceAfterFenceFired) { // Clean up irrelevant traces. tracingSession->ReadTraceBlocking(); // Trace. - mFrameTracer->traceNewLayer(layerID, layerName); - mFrameTracer->traceFence(layerID, bufferID, frameNumber, fenceTime, type); + mFrameTracer->traceNewLayer(layerId, layerName); + mFrameTracer->traceFence(layerId, bufferID, frameNumber, fenceTime, type); // Create extra trace packet to (hopefully not) trigger and finalize the fence packet. - mFrameTracer->traceTimestamp(layerID, bufferID, 0, 0, FrameTracer::FrameEvent::UNSPECIFIED); + mFrameTracer->traceTimestamp(layerId, bufferID, 0, 0, FrameTracer::FrameEvent::UNSPECIFIED); tracingSession->StopBlocking(); std::vector raw_trace = tracingSession->ReadTraceBlocking(); EXPECT_EQ(raw_trace.size(), 0); @@ -219,12 +219,12 @@ TEST_F(FrameTracerTest, traceFenceTriggersOnNextTraceAfterFenceFired) { tracingSession->StartBlocking(); // Clean up irrelevant traces. tracingSession->ReadTraceBlocking(); - mFrameTracer->traceNewLayer(layerID, layerName); - mFrameTracer->traceFence(layerID, bufferID, frameNumber, fenceTime, type); + mFrameTracer->traceNewLayer(layerId, layerName); + mFrameTracer->traceFence(layerId, bufferID, frameNumber, fenceTime, type); const nsecs_t timestamp = systemTime(); fenceFactory.signalAllForTest(Fence::NO_FENCE, timestamp); // Create extra trace packet to trigger and finalize fence trace packets. - mFrameTracer->traceTimestamp(layerID, bufferID, 0, 0, FrameTracer::FrameEvent::UNSPECIFIED); + mFrameTracer->traceTimestamp(layerId, bufferID, 0, 0, FrameTracer::FrameEvent::UNSPECIFIED); tracingSession->StopBlocking(); std::vector raw_trace = tracingSession->ReadTraceBlocking(); @@ -254,7 +254,7 @@ TEST_F(FrameTracerTest, traceFenceTriggersOnNextTraceAfterFenceFired) { TEST_F(FrameTracerTest, traceFenceWithStartTimeAfterSignalTime_ShouldHaveNoDuration) { const std::string layerName = "co.layername#0"; - const int32_t layerID = 5; + const int32_t layerId = 5; const uint32_t bufferID = 4; const uint64_t frameNumber = 3; const auto type = FrameTracer::FrameEvent::ACQUIRE_FENCE; @@ -264,24 +264,24 @@ TEST_F(FrameTracerTest, traceFenceWithStartTimeAfterSignalTime_ShouldHaveNoDurat tracingSession->StartBlocking(); // Clean up irrelevant traces. tracingSession->ReadTraceBlocking(); - mFrameTracer->traceNewLayer(layerID, layerName); + mFrameTracer->traceNewLayer(layerId, layerName); // traceFence called after fence signalled. const nsecs_t signalTime1 = systemTime(); const nsecs_t startTime1 = signalTime1 + 100000; auto fence1 = fenceFactory.createFenceTimeForTest(Fence::NO_FENCE); fenceFactory.signalAllForTest(Fence::NO_FENCE, signalTime1); - mFrameTracer->traceFence(layerID, bufferID, frameNumber, fence1, type, startTime1); + mFrameTracer->traceFence(layerId, bufferID, frameNumber, fence1, type, startTime1); // traceFence called before fence signalled. const nsecs_t signalTime2 = systemTime(); const nsecs_t startTime2 = signalTime2 + 100000; auto fence2 = fenceFactory.createFenceTimeForTest(Fence::NO_FENCE); - mFrameTracer->traceFence(layerID, bufferID, frameNumber, fence2, type, startTime2); + mFrameTracer->traceFence(layerId, bufferID, frameNumber, fence2, type, startTime2); fenceFactory.signalAllForTest(Fence::NO_FENCE, signalTime2); // Create extra trace packet to trigger and finalize fence trace packets. - mFrameTracer->traceTimestamp(layerID, bufferID, 0, 0, FrameTracer::FrameEvent::UNSPECIFIED); + mFrameTracer->traceTimestamp(layerId, bufferID, 0, 0, FrameTracer::FrameEvent::UNSPECIFIED); tracingSession->StopBlocking(); std::vector raw_trace = tracingSession->ReadTraceBlocking(); @@ -309,7 +309,7 @@ TEST_F(FrameTracerTest, traceFenceWithStartTimeAfterSignalTime_ShouldHaveNoDurat TEST_F(FrameTracerTest, traceFenceOlderThanDeadline_ShouldBeIgnored) { const std::string layerName = "co.layername#0"; - const int32_t layerID = 5; + const int32_t layerId = 5; const uint32_t bufferID = 4; const uint64_t frameNumber = 3; const auto type = FrameTracer::FrameEvent::ACQUIRE_FENCE; @@ -321,11 +321,11 @@ TEST_F(FrameTracerTest, traceFenceOlderThanDeadline_ShouldBeIgnored) { tracingSession->StartBlocking(); // Clean up irrelevant traces. tracingSession->ReadTraceBlocking(); - mFrameTracer->traceNewLayer(layerID, layerName); - mFrameTracer->traceFence(layerID, bufferID, frameNumber, fence, type); + mFrameTracer->traceNewLayer(layerId, layerName); + mFrameTracer->traceFence(layerId, bufferID, frameNumber, fence, type); fenceFactory.signalAllForTest(Fence::NO_FENCE, signalTime); // Create extra trace packet to trigger and finalize any previous fence packets. - mFrameTracer->traceTimestamp(layerID, bufferID, 0, 0, FrameTracer::FrameEvent::UNSPECIFIED); + mFrameTracer->traceTimestamp(layerId, bufferID, 0, 0, FrameTracer::FrameEvent::UNSPECIFIED); tracingSession->StopBlocking(); std::vector raw_trace = tracingSession->ReadTraceBlocking(); @@ -334,7 +334,7 @@ TEST_F(FrameTracerTest, traceFenceOlderThanDeadline_ShouldBeIgnored) { TEST_F(FrameTracerTest, traceFenceWithValidStartTime_ShouldHaveCorrectDuration) { const std::string layerName = "co.layername#0"; - const int32_t layerID = 5; + const int32_t layerId = 5; const uint32_t bufferID = 4; const uint64_t frameNumber = 3; const auto type = FrameTracer::FrameEvent::ACQUIRE_FENCE; @@ -345,24 +345,24 @@ TEST_F(FrameTracerTest, traceFenceWithValidStartTime_ShouldHaveCorrectDuration) tracingSession->StartBlocking(); // Clean up irrelevant traces. tracingSession->ReadTraceBlocking(); - mFrameTracer->traceNewLayer(layerID, layerName); + mFrameTracer->traceNewLayer(layerId, layerName); // traceFence called after fence signalled. const nsecs_t signalTime1 = systemTime(); const nsecs_t startTime1 = signalTime1 - duration; auto fence1 = fenceFactory.createFenceTimeForTest(Fence::NO_FENCE); fenceFactory.signalAllForTest(Fence::NO_FENCE, signalTime1); - mFrameTracer->traceFence(layerID, bufferID, frameNumber, fence1, type, startTime1); + mFrameTracer->traceFence(layerId, bufferID, frameNumber, fence1, type, startTime1); // traceFence called before fence signalled. const nsecs_t signalTime2 = systemTime(); const nsecs_t startTime2 = signalTime2 - duration; auto fence2 = fenceFactory.createFenceTimeForTest(Fence::NO_FENCE); - mFrameTracer->traceFence(layerID, bufferID, frameNumber, fence2, type, startTime2); + mFrameTracer->traceFence(layerId, bufferID, frameNumber, fence2, type, startTime2); fenceFactory.signalAllForTest(Fence::NO_FENCE, signalTime2); // Create extra trace packet to trigger and finalize fence trace packets. - mFrameTracer->traceTimestamp(layerID, bufferID, 0, 0, FrameTracer::FrameEvent::UNSPECIFIED); + mFrameTracer->traceTimestamp(layerId, bufferID, 0, 0, FrameTracer::FrameEvent::UNSPECIFIED); tracingSession->StopBlocking(); std::vector raw_trace = tracingSession->ReadTraceBlocking(); diff --git a/services/surfaceflinger/tests/unittests/TimeStatsTest.cpp b/services/surfaceflinger/tests/unittests/TimeStatsTest.cpp index 4eb9ec3672..7b60fa2ea6 100644 --- a/services/surfaceflinger/tests/unittests/TimeStatsTest.cpp +++ b/services/surfaceflinger/tests/unittests/TimeStatsTest.cpp @@ -170,8 +170,8 @@ std::string TimeStatsTest::inputCommand(InputCommand cmd, bool useProto) { return result; } -static std::string genLayerName(int32_t layerID) { - return (layerID < 0 ? "PopupWindow:b54fcd1#0" : "com.dummy#") + std::to_string(layerID); +static std::string genLayerName(int32_t layerId) { + return (layerId < 0 ? "PopupWindow:b54fcd1#0" : "com.dummy#") + std::to_string(layerId); } void TimeStatsTest::setTimeStamp(TimeStamp type, int32_t id, uint64_t frameNumber, nsecs_t ts) { @@ -560,22 +560,22 @@ TEST_F(TimeStatsTest, canSurviveMonkey) { EXPECT_TRUE(inputCommand(InputCommand::ENABLE, FMT_STRING).empty()); for (size_t i = 0; i < 10000000; ++i) { - const int32_t layerID = genRandomInt32(-1, 10); + const int32_t layerId = genRandomInt32(-1, 10); const int32_t frameNumber = genRandomInt32(1, 10); switch (genRandomInt32(0, 100)) { case 0: ALOGV("removeTimeRecord"); - ASSERT_NO_FATAL_FAILURE(mTimeStats->removeTimeRecord(layerID, frameNumber)); + ASSERT_NO_FATAL_FAILURE(mTimeStats->removeTimeRecord(layerId, frameNumber)); continue; case 1: ALOGV("onDestroy"); - ASSERT_NO_FATAL_FAILURE(mTimeStats->onDestroy(layerID)); + ASSERT_NO_FATAL_FAILURE(mTimeStats->onDestroy(layerId)); continue; } TimeStamp type = static_cast(genRandomInt32(TIME_STAMP_BEGIN, TIME_STAMP_END)); const int32_t ts = genRandomInt32(1, 1000000000); - ALOGV("type[%d], layerID[%d], frameNumber[%d], ts[%d]", type, layerID, frameNumber, ts); - setTimeStamp(type, layerID, frameNumber, ts); + ALOGV("type[%d], layerId[%d], frameNumber[%d], ts[%d]", type, layerId, frameNumber, ts); + setTimeStamp(type, layerId, frameNumber, ts); } } -- cgit v1.2.3-59-g8ed1b From 487340f03dd621406c0e293200d22a1c06a8c4df Mon Sep 17 00:00:00 2001 From: Yiwei Zhang Date: Mon, 18 Nov 2019 17:42:12 -0800 Subject: TimeStats: make sure acquire fence is captured Previously, if setAcquireFence happens earlier than setPostTime, the acquire fence is not recorded in TimeStats which ends up with acquire time being the same with post time. This issue is almost eliminated after a previous refactoring of the order of recording TimeStats and EGL throttling logic. Since acquire fence is already available at post time, this change just captures that by then to avoid any chance of missing the acquire fence. Bug: 140266250 Test: atest libsurfaceflinger_unittest:TimeStatsTest Change-Id: I90a5ab609afc7054c618273c3af79c9d12d85730 --- services/surfaceflinger/BufferQueueLayer.cpp | 2 -- services/surfaceflinger/Layer.cpp | 2 ++ 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'services/surfaceflinger/Layer.cpp') diff --git a/services/surfaceflinger/BufferQueueLayer.cpp b/services/surfaceflinger/BufferQueueLayer.cpp index 9580ad5515..d51d34b3c5 100644 --- a/services/surfaceflinger/BufferQueueLayer.cpp +++ b/services/surfaceflinger/BufferQueueLayer.cpp @@ -307,8 +307,6 @@ status_t BufferQueueLayer::updateTexImage(bool& recomputeVisibleRegions, nsecs_t } uint64_t bufferID = mQueueItems[0].mGraphicBuffer->getId(); - mFlinger->mTimeStats->setAcquireFence(layerId, currentFrameNumber, - mQueueItems[0].mFenceTime); mFlinger->mFrameTracer->traceFence(layerId, bufferID, currentFrameNumber, mQueueItems[0].mFenceTime, FrameTracer::FrameEvent::ACQUIRE_FENCE); diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp index 5a19d8aa51..ce9aab5c7a 100644 --- a/services/surfaceflinger/Layer.cpp +++ b/services/surfaceflinger/Layer.cpp @@ -1370,6 +1370,8 @@ void Layer::addAndGetFrameTimestamps(const NewFrameEventsEntry* newTimestamps, if (newTimestamps) { mFlinger->mTimeStats->setPostTime(getSequence(), newTimestamps->frameNumber, getName().c_str(), newTimestamps->postedTime); + mFlinger->mTimeStats->setAcquireFence(getSequence(), newTimestamps->frameNumber, + newTimestamps->acquireFence); } Mutex::Autolock lock(mFrameEventHistoryMutex); -- cgit v1.2.3-59-g8ed1b From 08f6eae01d8e0c7a77d933cf0ba2bfe70e779e8b Mon Sep 17 00:00:00 2001 From: Vishnu Nair Date: Tue, 26 Nov 2019 14:01:39 -0800 Subject: [Shadows] Set shadow settings per layer (5/n) - Save global shadow settings set by WindowManager - Add ShadowSettings to renderengine per layer rendering info Bug: 136561771 Test: go/wm-smoke Change-Id: I89cf84c7e089273ae3edea02e2ac24690055ba47 --- .../include/renderengine/LayerSettings.h | 29 ++++++++++++++++++++++ services/surfaceflinger/Layer.cpp | 12 +++++++++ services/surfaceflinger/Layer.h | 5 ++++ services/surfaceflinger/SurfaceFlinger.cpp | 16 +++++++++--- services/surfaceflinger/SurfaceFlinger.h | 5 ++++ 5 files changed, 64 insertions(+), 3 deletions(-) (limited to 'services/surfaceflinger/Layer.cpp') diff --git a/libs/renderengine/include/renderengine/LayerSettings.h b/libs/renderengine/include/renderengine/LayerSettings.h index b8bf8019de..b851d5cca8 100644 --- a/libs/renderengine/include/renderengine/LayerSettings.h +++ b/libs/renderengine/include/renderengine/LayerSettings.h @@ -96,6 +96,33 @@ struct PixelSource { half3 solidColor = half3(0.0f, 0.0f, 0.0f); }; +/* + * Contains the configuration for the shadows drawn by single layer. Shadow follows + * material design guidelines. + */ +struct ShadowSettings { + // Color to the ambient shadow. The alpha is premultiplied. + vec4 ambientColor = vec4(); + + // Color to the spot shadow. The alpha is premultiplied. The position of the spot shadow + // depends on the light position. + vec4 spotColor = vec4(); + + // Position of the light source used to cast the spot shadow. + vec3 lightPos = vec3(); + + // Radius of the spot light source. Smaller radius will have sharper edges, + // larger radius will have softer shadows + float lightRadius = 0.f; + + // Length of the cast shadow. If length is <= 0.f no shadows will be drawn. + float length = 0.f; + + // If true fill in the casting layer is translucent and the shadow needs to fill the bounds. + // Otherwise the shadow will only be drawn around the edges of the casting layer. + bool casterIsTranslucent = false; +}; + // The settings that RenderEngine requires for correctly rendering a Layer. struct LayerSettings { // Geometry information @@ -116,6 +143,8 @@ struct LayerSettings { // True if blending will be forced to be disabled. bool disableBlending = false; + + ShadowSettings shadow; }; } // namespace renderengine diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp index ce9aab5c7a..3d003524be 100644 --- a/services/surfaceflinger/Layer.cpp +++ b/services/surfaceflinger/Layer.cpp @@ -1800,6 +1800,18 @@ Layer::RoundedCornerState Layer::getRoundedCornerState() const { : RoundedCornerState(); } +renderengine::ShadowSettings Layer::getShadowSettings(const Rect& viewport) const { + renderengine::ShadowSettings state = mFlinger->mDrawingState.globalShadowSettings; + + // Shift the spot light x-position to the middle of the display and then + // offset it by casting layer's screen pos. + state.lightPos.x = (viewport.width() / 2.f) - mScreenBounds.left; + state.lightPos.y -= mScreenBounds.top; + + state.length = mEffectiveShadowRadius; + return state; +} + void Layer::commitChildList() { for (size_t i = 0; i < mCurrentChildren.size(); i++) { const auto& child = mCurrentChildren[i]; diff --git a/services/surfaceflinger/Layer.h b/services/surfaceflinger/Layer.h index 7abcd0f131..16bdb01bff 100644 --- a/services/surfaceflinger/Layer.h +++ b/services/surfaceflinger/Layer.h @@ -216,6 +216,9 @@ public: std::deque> callbackHandles; bool colorSpaceAgnostic; nsecs_t desiredPresentTime = -1; + + // Length of the cast shadow. If the radius is > 0, a shadow of length shadowRadius will + // be rendered around the layer. float shadowRadius; }; @@ -650,6 +653,8 @@ public: // ignored. RoundedCornerState getRoundedCornerState() const; + renderengine::ShadowSettings getShadowSettings(const Rect& viewport) const; + void traverseInReverseZOrder(LayerVector::StateSet stateSet, const LayerVector::Visitor& visitor); void traverseInZOrder(LayerVector::StateSet stateSet, const LayerVector::Visitor& visitor); diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp index c555f7985f..682932b7fa 100644 --- a/services/surfaceflinger/SurfaceFlinger.cpp +++ b/services/surfaceflinger/SurfaceFlinger.cpp @@ -5512,9 +5512,19 @@ void SurfaceFlinger::bufferErased(const client_cache_t& clientCacheId) { getRenderEngine().unbindExternalTextureBuffer(clientCacheId.id); } -status_t SurfaceFlinger::setGlobalShadowSettings(const half4& /*ambientColor*/, - const half4& /*spotColor*/, float /*lightPosY*/, - float /*lightPosZ*/, float /*lightRadius*/) { +status_t SurfaceFlinger::setGlobalShadowSettings(const half4& ambientColor, const half4& spotColor, + float lightPosY, float lightPosZ, + float lightRadius) { + Mutex::Autolock _l(mStateLock); + mCurrentState.globalShadowSettings.ambientColor = vec4(ambientColor); + mCurrentState.globalShadowSettings.spotColor = vec4(spotColor); + mCurrentState.globalShadowSettings.lightPos.y = lightPosY; + mCurrentState.globalShadowSettings.lightPos.z = lightPosZ; + mCurrentState.globalShadowSettings.lightRadius = lightRadius; + + // these values are overridden when calculating the shadow settings for a layer. + mCurrentState.globalShadowSettings.lightPos.x = 0.f; + mCurrentState.globalShadowSettings.length = 0.f; return NO_ERROR; } diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h index 5b1853c2d5..a5cd6894b4 100644 --- a/services/surfaceflinger/SurfaceFlinger.h +++ b/services/surfaceflinger/SurfaceFlinger.h @@ -37,6 +37,7 @@ #include