From 5b2e12130020a3ac570aa0f928ae6b8dad5df088 Mon Sep 17 00:00:00 2001 From: Nikita Ioffe Date: Wed, 7 Apr 2021 16:25:49 +0100 Subject: Call apexd --unmount-all at the end of otapreopt_chroot run We don't really care for the umount part, but we do care about freeing up loop and dm block devices so that next run of otapreopt_chroot can re-use them. Note that we must run `apexd --unmount-all` inside otapreopt_chroot itself. This is because otapreopt_chroot runs in /postintall namespace. Test: install an OTA, check number of loop devices Test: Install an OTA, cancel during finalization, Restart OTA Test: forrest test -l remote --test_bench_config asit/crosshatch --extra_args '--delegated-tf ab://tradefed/tradefed/P21446393/.*google-tradefed.zip?unzip=true' ab::P21523880:aosp_crosshatch-userdebug:git_master asit/dexoptota/self_full Bug: 184716804 Change-Id: I4f01cb9082f90fd40fba4a1864e8d6b548f5a274 (cherry picked from commit 2a42aee981c6d53282a7d0e23232d32e886e30e7) --- cmds/installd/otapreopt_chroot.cpp | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) diff --git a/cmds/installd/otapreopt_chroot.cpp b/cmds/installd/otapreopt_chroot.cpp index c04b558e2d..3a87776162 100644 --- a/cmds/installd/otapreopt_chroot.cpp +++ b/cmds/installd/otapreopt_chroot.cpp @@ -27,6 +27,7 @@ #include #include #include +#include #include #include #include @@ -72,6 +73,15 @@ static void ActivateApexPackages() { } } +static void DeactivateApexPackages() { + std::vector apexd_cmd{"/system/bin/apexd", "--unmount-all"}; + std::string apexd_error_msg; + bool exec_result = Exec(apexd_cmd, &apexd_error_msg); + if (!exec_result) { + PLOG(ERROR) << "Running /system/bin/apexd --unmount-all failed: " << apexd_error_msg; + } +} + static void TryExtraMount(const char* name, const char* slot, const char* target) { std::string partition_name = StringPrintf("%s%s", name, slot); @@ -231,10 +241,30 @@ static int otapreopt_chroot(const int argc, char **arg) { exit(205); } + // Call apexd --unmount-all to free up loop and dm block devices, so that we can re-use + // them during the next invocation. Since otapreopt_chroot calls exit in case something goes + // wrong we need to register our own atexit handler. + // We want to register this handler before actually activating apex packages. This is mostly + // due to the fact that if fail to unmount apexes, then on the next run of otapreopt_chroot + // we will ask for new loop devices instead of re-using existing ones, and we really don't want + // to do that. :) + if (atexit(DeactivateApexPackages) != 0) { + LOG(ERROR) << "Failed to register atexit hander"; + exit(206); + } + // Try to mount APEX packages in "/apex" in the chroot dir. We need at least // the ART APEX, as it is required by otapreopt to run dex2oat. ActivateApexPackages(); + auto cleanup = android::base::make_scope_guard([](){ + std::vector apexd_cmd{"/system/bin/apexd", "--unmount-all"}; + std::string apexd_error_msg; + bool exec_result = Exec(apexd_cmd, &apexd_error_msg); + if (!exec_result) { + PLOG(ERROR) << "Running /system/bin/apexd --unmount-all failed: " << apexd_error_msg; + } + }); // Check that an ART APEX has been activated; clean up and exit // early otherwise. static constexpr const std::string_view kRequiredApexs[] = { -- cgit v1.2.3-59-g8ed1b From c6f2d01128322a4a0f07a3ca4f2bd54c05fbf018 Mon Sep 17 00:00:00 2001 From: Nikita Ioffe Date: Wed, 7 Apr 2021 16:25:49 +0100 Subject: Call apexd --unmount-all at the end of otapreopt_chroot run We don't really care for the umount part, but we do care about freeing up loop and dm block devices so that next run of otapreopt_chroot can re-use them. Note that we must run `apexd --unmount-all` inside otapreopt_chroot itself. This is because otapreopt_chroot runs in /postintall namespace. Test: install an OTA, check number of loop devices Test: Install an OTA, cancel during finalization, Restart OTA Test: forrest test -l remote --test_bench_config asit/crosshatch --extra_args '--delegated-tf ab://tradefed/tradefed/P21446393/.*google-tradefed.zip?unzip=true' ab::P21523880:aosp_crosshatch-userdebug:git_master asit/dexoptota/self_full Bug: 184716804 Change-Id: I4f01cb9082f90fd40fba4a1864e8d6b548f5a274 (cherry picked from commit 2a42aee981c6d53282a7d0e23232d32e886e30e7) --- cmds/installd/otapreopt_chroot.cpp | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) diff --git a/cmds/installd/otapreopt_chroot.cpp b/cmds/installd/otapreopt_chroot.cpp index c04b558e2d..3a87776162 100644 --- a/cmds/installd/otapreopt_chroot.cpp +++ b/cmds/installd/otapreopt_chroot.cpp @@ -27,6 +27,7 @@ #include #include #include +#include #include #include #include @@ -72,6 +73,15 @@ static void ActivateApexPackages() { } } +static void DeactivateApexPackages() { + std::vector apexd_cmd{"/system/bin/apexd", "--unmount-all"}; + std::string apexd_error_msg; + bool exec_result = Exec(apexd_cmd, &apexd_error_msg); + if (!exec_result) { + PLOG(ERROR) << "Running /system/bin/apexd --unmount-all failed: " << apexd_error_msg; + } +} + static void TryExtraMount(const char* name, const char* slot, const char* target) { std::string partition_name = StringPrintf("%s%s", name, slot); @@ -231,10 +241,30 @@ static int otapreopt_chroot(const int argc, char **arg) { exit(205); } + // Call apexd --unmount-all to free up loop and dm block devices, so that we can re-use + // them during the next invocation. Since otapreopt_chroot calls exit in case something goes + // wrong we need to register our own atexit handler. + // We want to register this handler before actually activating apex packages. This is mostly + // due to the fact that if fail to unmount apexes, then on the next run of otapreopt_chroot + // we will ask for new loop devices instead of re-using existing ones, and we really don't want + // to do that. :) + if (atexit(DeactivateApexPackages) != 0) { + LOG(ERROR) << "Failed to register atexit hander"; + exit(206); + } + // Try to mount APEX packages in "/apex" in the chroot dir. We need at least // the ART APEX, as it is required by otapreopt to run dex2oat. ActivateApexPackages(); + auto cleanup = android::base::make_scope_guard([](){ + std::vector apexd_cmd{"/system/bin/apexd", "--unmount-all"}; + std::string apexd_error_msg; + bool exec_result = Exec(apexd_cmd, &apexd_error_msg); + if (!exec_result) { + PLOG(ERROR) << "Running /system/bin/apexd --unmount-all failed: " << apexd_error_msg; + } + }); // Check that an ART APEX has been activated; clean up and exit // early otherwise. static constexpr const std::string_view kRequiredApexs[] = { -- cgit v1.2.3-59-g8ed1b From e9a9a9e2ea8a654489ae95b7f76aa447ed8a8576 Mon Sep 17 00:00:00 2001 From: Orion Hodson Date: Thu, 8 Apr 2021 12:30:21 +0000 Subject: Revert "Remove setFrame from BufferStateLayer" Revert "Update tests to reflect the new behavior for setGeometry" Revert submission 13843937-sc_remove_set_frame Reason for revert: Candidate CL for b/184807094 Reverted Changes: Iffbd955a3:Remove setFrame I27f17bc61:Update tests to reflect the new behavior for setGe... I5720276c1:Remove setFrame from surface_control setGeometry I32ee0e3e4:Remove setFrame from BufferStateLayer Bug: 184807094 Change-Id: I8330f374c50c76d8c2e70b79815bc2bc32b89480 (cherry picked from commit 1014c4bf14f5c250b78d7e917fb59aaa9b0d9b0a) --- libs/gui/BLASTBufferQueue.cpp | 29 +--- libs/gui/LayerState.cpp | 4 + libs/gui/SurfaceComposerClient.cpp | 14 ++ libs/gui/include/gui/BLASTBufferQueue.h | 32 +--- libs/gui/include/gui/LayerState.h | 2 +- libs/gui/include/gui/SurfaceComposerClient.h | 1 + libs/gui/tests/BLASTBufferQueue_test.cpp | 34 ++-- services/surfaceflinger/BufferStateLayer.cpp | 98 +++++++----- services/surfaceflinger/BufferStateLayer.h | 10 +- services/surfaceflinger/Layer.cpp | 4 +- services/surfaceflinger/Layer.h | 1 + services/surfaceflinger/RefreshRateOverlay.cpp | 8 +- services/surfaceflinger/SurfaceFlinger.cpp | 3 + services/surfaceflinger/tests/BufferGenerator.cpp | 14 +- services/surfaceflinger/tests/BufferGenerator.h | 2 - services/surfaceflinger/tests/EffectLayer_test.cpp | 1 + services/surfaceflinger/tests/IPC_test.cpp | 1 + .../surfaceflinger/tests/LayerCallback_test.cpp | 131 +++------------- .../tests/LayerRenderTypeTransaction_test.cpp | 174 +++++++++++---------- .../surfaceflinger/tests/LayerTransactionTest.h | 5 - .../LayerTypeAndRenderTypeTransaction_test.cpp | 60 +++++-- services/surfaceflinger/tests/MirrorLayer_test.cpp | 2 +- .../surfaceflinger/tests/utils/TransactionUtils.h | 18 +-- 23 files changed, 295 insertions(+), 353 deletions(-) diff --git a/libs/gui/BLASTBufferQueue.cpp b/libs/gui/BLASTBufferQueue.cpp index e5afd408a9..bcdd06b6c8 100644 --- a/libs/gui/BLASTBufferQueue.cpp +++ b/libs/gui/BLASTBufferQueue.cpp @@ -204,16 +204,13 @@ void BLASTBufferQueue::update(const sp& surface, uint32_t width, if (mRequestedSize != newSize) { mRequestedSize.set(newSize); mBufferItemConsumer->setDefaultBufferSize(mRequestedSize.width, mRequestedSize.height); - if (mLastBufferInfo.scalingMode != NATIVE_WINDOW_SCALING_MODE_FREEZE) { + if (mLastBufferScalingMode != NATIVE_WINDOW_SCALING_MODE_FREEZE) { // If the buffer supports scaling, update the frame immediately since the client may // want to scale the existing buffer to the new size. mSize = mRequestedSize; - // We only need to update the scale if we've received at least one buffer. The reason - // for this is the scale is calculated based on the requested size and buffer size. - // If there's no buffer, the scale will always be 1. - if (mLastBufferInfo.hasBuffer) { - setMatrix(&t, mLastBufferInfo); - } + t.setFrame(mSurfaceControl, + {0, 0, static_cast(mSize.width), + static_cast(mSize.height)}); applyTransaction = true; } } @@ -377,10 +374,8 @@ void BLASTBufferQueue::processNextBufferLocked(bool useNextTransaction) { // Ensure BLASTBufferQueue stays alive until we receive the transaction complete callback. incStrong((void*)transactionCallbackThunk); + mLastBufferScalingMode = bufferItem.mScalingMode; mLastAcquiredFrameNumber = bufferItem.mFrameNumber; - mLastBufferInfo.update(true /* hasBuffer */, bufferItem.mGraphicBuffer->getWidth(), - bufferItem.mGraphicBuffer->getHeight(), bufferItem.mTransform, - bufferItem.mScalingMode); auto releaseBufferCallback = std::bind(releaseBufferCallbackThunk, wp(this) /* callbackContext */, @@ -393,7 +388,8 @@ void BLASTBufferQueue::processNextBufferLocked(bool useNextTransaction) { bufferItem.mFence ? new Fence(bufferItem.mFence->dup()) : Fence::NO_FENCE); t->addTransactionCompletedCallback(transactionCallbackThunk, static_cast(this)); - setMatrix(t, mLastBufferInfo); + t->setFrame(mSurfaceControl, + {0, 0, static_cast(mSize.width), static_cast(mSize.height)}); t->setCrop(mSurfaceControl, computeCrop(bufferItem)); t->setTransform(mSurfaceControl, bufferItem.mTransform); t->setTransformToDisplayInverse(mSurfaceControl, bufferItem.mTransformToDisplayInverse); @@ -519,17 +515,6 @@ bool BLASTBufferQueue::rejectBuffer(const BufferItem& item) { return mSize != bufferSize; } -void BLASTBufferQueue::setMatrix(SurfaceComposerClient::Transaction* t, - const BufferInfo& bufferInfo) { - uint32_t bufWidth = bufferInfo.width; - uint32_t bufHeight = bufferInfo.height; - - float dsdx = mSize.width / static_cast(bufWidth); - float dsdy = mSize.height / static_cast(bufHeight); - - t->setMatrix(mSurfaceControl, dsdx, 0, 0, dsdy); -} - void BLASTBufferQueue::setTransactionCompleteCallback( uint64_t frameNumber, std::function&& transactionCompleteCallback) { std::lock_guard _lock{mMutex}; diff --git a/libs/gui/LayerState.cpp b/libs/gui/LayerState.cpp index 0ca497795b..2a9a97ed13 100644 --- a/libs/gui/LayerState.cpp +++ b/libs/gui/LayerState.cpp @@ -459,6 +459,10 @@ void layer_state_t::merge(const layer_state_t& other) { what |= eCropChanged; crop = other.crop; } + if (other.what & eFrameChanged) { + what |= eFrameChanged; + orientedDisplaySpaceRect = other.orientedDisplaySpaceRect; + } if (other.what & eBufferChanged) { what |= eBufferChanged; buffer = other.buffer; diff --git a/libs/gui/SurfaceComposerClient.cpp b/libs/gui/SurfaceComposerClient.cpp index c888312184..879955b7d7 100644 --- a/libs/gui/SurfaceComposerClient.cpp +++ b/libs/gui/SurfaceComposerClient.cpp @@ -1246,6 +1246,20 @@ SurfaceComposerClient::Transaction::setTransformToDisplayInverse(const sp& sc, const Rect& frame) { + layer_state_t* s = getLayerState(sc); + if (!s) { + mStatus = BAD_INDEX; + return *this; + } + s->what |= layer_state_t::eFrameChanged; + s->orientedDisplaySpaceRect = frame; + + registerSurfaceControlForCallback(sc); + return *this; +} + SurfaceComposerClient::Transaction& SurfaceComposerClient::Transaction::setBuffer( const sp& sc, const sp& buffer, ReleaseBufferCallback callback) { diff --git a/libs/gui/include/gui/BLASTBufferQueue.h b/libs/gui/include/gui/BLASTBufferQueue.h index a48f95ae73..fbd16f4ea2 100644 --- a/libs/gui/include/gui/BLASTBufferQueue.h +++ b/libs/gui/include/gui/BLASTBufferQueue.h @@ -142,33 +142,6 @@ private: ui::Size mRequestedSize GUARDED_BY(mMutex); int32_t mFormat GUARDED_BY(mMutex); - struct BufferInfo { - bool hasBuffer = false; - uint32_t width; - uint32_t height; - uint32_t transform; - // This is used to check if we should update the blast layer size immediately or wait until - // we get the next buffer. This will support scenarios where the layer can change sizes - // and the buffer will scale to fit the new size. - uint32_t scalingMode = NATIVE_WINDOW_SCALING_MODE_SCALE_TO_WINDOW; - - void update(bool hasBuffer, uint32_t width, uint32_t height, uint32_t transform, - uint32_t scalingMode) { - this->hasBuffer = hasBuffer; - this->width = width; - this->height = height; - this->transform = transform; - this->scalingMode = scalingMode; - } - }; - - // Last acquired buffer's info. This is used to calculate the correct scale when size change is - // requested. We need to use the old buffer's info to determine what scale we need to apply to - // ensure the correct size. - BufferInfo mLastBufferInfo GUARDED_BY(mMutex); - void setMatrix(SurfaceComposerClient::Transaction* t, const BufferInfo& bufferInfo) - REQUIRES(mMutex); - uint32_t mTransformHint GUARDED_BY(mMutex); sp mConsumer; @@ -186,6 +159,11 @@ private: std::queue mNextFrameTimelineInfoQueue GUARDED_BY(mMutex); + // Last acquired buffer's scaling mode. This is used to check if we should update the blast + // layer size immediately or wait until we get the next buffer. This will support scenarios + // where the layer can change sizes and the buffer will scale to fit the new size. + uint32_t mLastBufferScalingMode = NATIVE_WINDOW_SCALING_MODE_SCALE_TO_WINDOW; + // Tracks the last acquired frame number uint64_t mLastAcquiredFrameNumber GUARDED_BY(mMutex) = 0; diff --git a/libs/gui/include/gui/LayerState.h b/libs/gui/include/gui/LayerState.h index 706a09c3c7..6c265c898a 100644 --- a/libs/gui/include/gui/LayerState.h +++ b/libs/gui/include/gui/LayerState.h @@ -106,7 +106,7 @@ struct layer_state_t { eHasListenerCallbacksChanged = 0x20000000, eInputInfoChanged = 0x40000000, eCornerRadiusChanged = 0x80000000, - /* was eFrameChanged, now available 0x1'00000000, */ + eFrameChanged = 0x1'00000000, eCachedBufferChanged = 0x2'00000000, eBackgroundColorChanged = 0x4'00000000, eMetadataChanged = 0x8'00000000, diff --git a/libs/gui/include/gui/SurfaceComposerClient.h b/libs/gui/include/gui/SurfaceComposerClient.h index 731af58e85..7ec5d8df83 100644 --- a/libs/gui/include/gui/SurfaceComposerClient.h +++ b/libs/gui/include/gui/SurfaceComposerClient.h @@ -479,6 +479,7 @@ public: Transaction& setTransform(const sp& sc, uint32_t transform); Transaction& setTransformToDisplayInverse(const sp& sc, bool transformToDisplayInverse); + Transaction& setFrame(const sp& sc, const Rect& frame); Transaction& setBuffer(const sp& sc, const sp& buffer, ReleaseBufferCallback callback = nullptr); Transaction& setCachedBuffer(const sp& sc, int32_t bufferId); diff --git a/libs/gui/tests/BLASTBufferQueue_test.cpp b/libs/gui/tests/BLASTBufferQueue_test.cpp index 9b1f0db83b..fe48d88376 100644 --- a/libs/gui/tests/BLASTBufferQueue_test.cpp +++ b/libs/gui/tests/BLASTBufferQueue_test.cpp @@ -140,6 +140,7 @@ protected: /*parent*/ nullptr); t.setLayerStack(mSurfaceControl, 0) .setLayer(mSurfaceControl, std::numeric_limits::max()) + .setFrame(mSurfaceControl, Rect(resolution)) .show(mSurfaceControl) .setDataspace(mSurfaceControl, ui::Dataspace::V0_SRGB) .apply(); @@ -217,13 +218,13 @@ protected: col >= region.left - border && col < region.right + border; } if (!outsideRegion && inRegion) { - ASSERT_GE(epsilon, abs(r - *(pixel))); - ASSERT_GE(epsilon, abs(g - *(pixel + 1))); - ASSERT_GE(epsilon, abs(b - *(pixel + 2))); + EXPECT_GE(epsilon, abs(r - *(pixel))); + EXPECT_GE(epsilon, abs(g - *(pixel + 1))); + EXPECT_GE(epsilon, abs(b - *(pixel + 2))); } else if (outsideRegion && !inRegion) { - ASSERT_GE(epsilon, abs(r - *(pixel))); - ASSERT_GE(epsilon, abs(g - *(pixel + 1))); - ASSERT_GE(epsilon, abs(b - *(pixel + 2))); + EXPECT_GE(epsilon, abs(r - *(pixel))); + EXPECT_GE(epsilon, abs(g - *(pixel + 1))); + EXPECT_GE(epsilon, abs(b - *(pixel + 2))); } ASSERT_EQ(false, ::testing::Test::HasFailure()); } @@ -465,8 +466,7 @@ TEST_F(BLASTBufferQueueTest, SetCrop_Item) { ASSERT_EQ(NO_ERROR, captureDisplay(mCaptureArgs, mCaptureResults)); ASSERT_NO_FATAL_FAILURE( - checkScreenCapture(r, g, b, - {0, 0, (int32_t)mDisplayWidth, (int32_t)mDisplayHeight / 2})); + checkScreenCapture(r, g, b, {0, 0, (int32_t)mDisplayWidth, (int32_t)mDisplayHeight})); } TEST_F(BLASTBufferQueueTest, SetCrop_ScalingModeScaleCrop) { @@ -523,15 +523,13 @@ TEST_F(BLASTBufferQueueTest, SetCrop_ScalingModeScaleCrop) { // capture screen and verify that it is red ASSERT_EQ(NO_ERROR, captureDisplay(mCaptureArgs, mCaptureResults)); - Rect bounds; - bounds.left = finalCropSideLength / 2; - bounds.top = 0; - bounds.right = bounds.left + finalCropSideLength; - bounds.bottom = finalCropSideLength; - - ASSERT_NO_FATAL_FAILURE(checkScreenCapture(r, g, b, bounds)); ASSERT_NO_FATAL_FAILURE( - checkScreenCapture(0, 0, 0, bounds, /*border*/ 0, /*outsideRegion*/ true)); + checkScreenCapture(r, g, b, + {0, 0, (int32_t)bufferSideLength, (int32_t)bufferSideLength})); + ASSERT_NO_FATAL_FAILURE( + checkScreenCapture(0, 0, 0, + {0, 0, (int32_t)bufferSideLength, (int32_t)bufferSideLength}, + /*border*/ 0, /*outsideRegion*/ true)); } class TestProducerListener : public BnProducerListener { @@ -598,6 +596,7 @@ TEST_F(BLASTBufferQueueTest, OutOfOrderTransactionTest) { t.setLayerStack(bgSurface, 0) .show(bgSurface) .setDataspace(bgSurface, ui::Dataspace::V0_SRGB) + .setFrame(bgSurface, Rect(0, 0, mDisplayWidth, mDisplayHeight)) .setLayer(bgSurface, std::numeric_limits::max() - 1) .apply(); @@ -620,8 +619,7 @@ TEST_F(BLASTBufferQueueTest, OutOfOrderTransactionTest) { ASSERT_EQ(NO_ERROR, captureDisplay(mCaptureArgs, mCaptureResults)); ASSERT_NO_FATAL_FAILURE( - checkScreenCapture(r, g, b, - {0, 0, (int32_t)mDisplayWidth, (int32_t)mDisplayHeight / 2})); + checkScreenCapture(r, g, b, {0, 0, (int32_t)mDisplayWidth, (int32_t)mDisplayHeight})); } class BLASTBufferQueueTransformTest : public BLASTBufferQueueTest { diff --git a/services/surfaceflinger/BufferStateLayer.cpp b/services/surfaceflinger/BufferStateLayer.cpp index 09e3cd969c..d6becbf213 100644 --- a/services/surfaceflinger/BufferStateLayer.cpp +++ b/services/surfaceflinger/BufferStateLayer.cpp @@ -278,8 +278,9 @@ bool BufferStateLayer::applyPendingStates(Layer::State* stateToCommit) { return stateUpdateAvailable; } -Rect BufferStateLayer::getCrop(const Layer::State& s) const { - return s.crop; +// Crop that applies to the window +Rect BufferStateLayer::getCrop(const Layer::State& /*s*/) const { + return Rect::INVALID_RECT; } bool BufferStateLayer::setTransform(uint32_t transform) { @@ -300,53 +301,57 @@ bool BufferStateLayer::setTransformToDisplayInverse(bool transformToDisplayInver } bool BufferStateLayer::setCrop(const Rect& crop) { - if (mCurrentState.crop == crop) return false; - mCurrentState.sequence++; - mCurrentState.crop = crop; + Rect c = crop; + if (c.left < 0) { + c.left = 0; + } + if (c.top < 0) { + c.top = 0; + } + // If the width and/or height are < 0, make it [0, 0, -1, -1] so the equality comparision below + // treats all invalid rectangles the same. + if (!c.isValid()) { + c.makeInvalid(); + } + if (mCurrentState.crop == c) return false; + mCurrentState.crop = c; mCurrentState.modified = true; setTransactionFlags(eTransactionNeeded); return true; } -bool BufferStateLayer::setMatrix(const layer_state_t::matrix22_t& matrix, - bool allowNonRectPreservingTransforms) { - if (mCurrentState.transform.dsdx() == matrix.dsdx && - mCurrentState.transform.dtdy() == matrix.dtdy && - mCurrentState.transform.dtdx() == matrix.dtdx && - mCurrentState.transform.dsdy() == matrix.dsdy) { - return false; - } +bool BufferStateLayer::setFrame(const Rect& frame) { + int x = frame.left; + int y = frame.top; + int w = frame.getWidth(); + int h = frame.getHeight(); - ui::Transform t; - t.set(matrix.dsdx, matrix.dtdy, matrix.dtdx, matrix.dsdy); - - if (!allowNonRectPreservingTransforms && !t.preserveRects()) { - ALOGW("Attempt to set rotation matrix without permission ACCESS_SURFACE_FLINGER nor " - "ROTATE_SURFACE_FLINGER ignored"); - return false; + if (x < 0) { + x = 0; + w = frame.right; } - mCurrentState.transform.set(matrix.dsdx, matrix.dtdy, matrix.dtdx, matrix.dsdy); - - mCurrentState.sequence++; - mCurrentState.modified = true; - setTransactionFlags(eTransactionNeeded); - - return true; -} + if (y < 0) { + y = 0; + h = frame.bottom; + } -bool BufferStateLayer::setPosition(float x, float y) { - if (mCurrentState.transform.tx() == x && mCurrentState.transform.ty() == y) { + if (mCurrentState.transform.tx() == x && mCurrentState.transform.ty() == y && + mCurrentState.width == w && mCurrentState.height == h) { return false; } + if (!frame.isValid()) { + x = y = w = h = 0; + } mCurrentState.transform.set(x, y); + mCurrentState.width = w; + mCurrentState.height = h; mCurrentState.sequence++; mCurrentState.modified = true; setTransactionFlags(eTransactionNeeded); - return true; } @@ -423,10 +428,6 @@ bool BufferStateLayer::setBuffer(const sp& buffer, const spmFrameTracer->traceTimestamp(layerId, bufferId, frameNumber, postTime, FrameTracer::FrameEvent::QUEUE); } - - mCurrentState.width = mCurrentState.buffer->width; - mCurrentState.height = mCurrentState.buffer->height; - return true; } @@ -857,6 +858,33 @@ sp BufferStateLayer::createClone() { return layer; } +Layer::RoundedCornerState BufferStateLayer::getRoundedCornerState() const { + const auto& p = mDrawingParent.promote(); + if (p != nullptr) { + RoundedCornerState parentState = p->getRoundedCornerState(); + if (parentState.radius > 0) { + ui::Transform t = getActiveTransform(getDrawingState()); + t = t.inverse(); + parentState.cropRect = t.transform(parentState.cropRect); + // The rounded corners shader only accepts 1 corner radius for performance reasons, + // but a transform matrix can define horizontal and vertical scales. + // Let's take the average between both of them and pass into the shader, practically we + // never do this type of transformation on windows anyway. + parentState.radius *= (t[0][0] + t[1][1]) / 2.0f; + return parentState; + } + } + const float radius = getDrawingState().cornerRadius; + const State& s(getDrawingState()); + if (radius <= 0 || (getActiveWidth(s) == UINT32_MAX && getActiveHeight(s) == UINT32_MAX)) + return RoundedCornerState(); + return RoundedCornerState(FloatRect(static_cast(s.transform.tx()), + static_cast(s.transform.ty()), + static_cast(s.transform.tx() + s.width), + static_cast(s.transform.ty() + s.height)), + radius); +} + bool BufferStateLayer::bufferNeedsFiltering() const { const State& s(getDrawingState()); if (!s.buffer) { diff --git a/services/surfaceflinger/BufferStateLayer.h b/services/surfaceflinger/BufferStateLayer.h index af2819eac7..7a3da6fec1 100644 --- a/services/surfaceflinger/BufferStateLayer.h +++ b/services/surfaceflinger/BufferStateLayer.h @@ -66,6 +66,7 @@ public: bool setTransform(uint32_t transform) override; bool setTransformToDisplayInverse(bool transformToDisplayInverse) override; bool setCrop(const Rect& crop) override; + bool setFrame(const Rect& frame) override; bool setBuffer(const sp& buffer, const sp& acquireFence, nsecs_t postTime, nsecs_t desiredPresentTime, bool isAutoTimestamp, const client_cache_t& clientCacheId, uint64_t frameNumber, @@ -80,13 +81,15 @@ public: bool setTransactionCompletedListeners(const std::vector>& handles) override; bool addFrameEvent(const sp& acquireFence, nsecs_t postedTime, nsecs_t requestedPresentTime) override; - bool setPosition(float /*x*/, float /*y*/) override; - bool setMatrix(const layer_state_t::matrix22_t& /*matrix*/, - bool /*allowNonRectPreservingTransforms*/); // 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*/) override { return false; } bool setTransparentRegionHint(const Region& transparent) override; + bool setMatrix(const layer_state_t::matrix22_t& /*matrix*/, + bool /*allowNonRectPreservingTransforms*/) override { + return false; + } void deferTransactionUntil_legacy(const sp& /*barrierHandle*/, uint64_t /*frameNumber*/) override {} void deferTransactionUntil_legacy(const sp& /*barrierLayer*/, @@ -94,6 +97,7 @@ public: Rect getBufferSize(const State& s) const override; FloatRect computeSourceBounds(const FloatRect& parentBounds) const override; + Layer::RoundedCornerState getRoundedCornerState() const override; void setAutoRefresh(bool autoRefresh) override; // ----------------------------------------------------------------------- diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp index 2fcd8215eb..dbd6b32656 100644 --- a/services/surfaceflinger/Layer.cpp +++ b/services/surfaceflinger/Layer.cpp @@ -2313,8 +2313,8 @@ Layer::RoundedCornerState Layer::getRoundedCornerState() const { } } const float radius = getDrawingState().cornerRadius; - return radius > 0 && getCroppedBufferSize(getDrawingState()).isValid() - ? RoundedCornerState(getCroppedBufferSize(getDrawingState()).toFloatRect(), radius) + return radius > 0 && getCrop(getDrawingState()).isValid() + ? RoundedCornerState(getCrop(getDrawingState()).toFloatRect(), radius) : RoundedCornerState(); } diff --git a/services/surfaceflinger/Layer.h b/services/surfaceflinger/Layer.h index 4a105ebeda..aafe41cea0 100644 --- a/services/surfaceflinger/Layer.h +++ b/services/surfaceflinger/Layer.h @@ -412,6 +412,7 @@ public: // Used only to set BufferStateLayer state virtual bool setTransform(uint32_t /*transform*/) { return false; }; virtual bool setTransformToDisplayInverse(bool /*transformToDisplayInverse*/) { return false; }; + virtual bool setFrame(const Rect& /*frame*/) { return false; }; virtual bool setBuffer(const sp& /*buffer*/, const sp& /*acquireFence*/, nsecs_t /*postTime*/, nsecs_t /*desiredPresentTime*/, bool /*isAutoTimestamp*/, const client_cache_t& /*clientCacheId*/, diff --git a/services/surfaceflinger/RefreshRateOverlay.cpp b/services/surfaceflinger/RefreshRateOverlay.cpp index 7a3e433660..1d00cc38f2 100644 --- a/services/surfaceflinger/RefreshRateOverlay.cpp +++ b/services/surfaceflinger/RefreshRateOverlay.cpp @@ -231,14 +231,8 @@ const std::vector>& RefreshRateOverlay::getOrCreateBuffers(uin void RefreshRateOverlay::setViewport(ui::Size viewport) { Rect frame((3 * viewport.width) >> 4, viewport.height >> 5); frame.offsetBy(viewport.width >> 5, viewport.height >> 4); + mLayer->setFrame(frame); - layer_state_t::matrix22_t matrix; - matrix.dsdx = frame.getWidth() / static_cast(SevenSegmentDrawer::getWidth()); - matrix.dtdx = 0; - matrix.dtdy = 0; - matrix.dsdy = frame.getHeight() / static_cast(SevenSegmentDrawer::getHeight()); - mLayer->setMatrix(matrix, true); - mLayer->setPosition(frame.left, frame.top); mFlinger.mTransactionFlags.fetch_or(eTransactionMask); } diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp index 8d592a38f9..cbf8db8b15 100644 --- a/services/surfaceflinger/SurfaceFlinger.cpp +++ b/services/surfaceflinger/SurfaceFlinger.cpp @@ -4034,6 +4034,9 @@ uint32_t SurfaceFlinger::setClientStateLocked( if (what & layer_state_t::eCropChanged) { if (layer->setCrop(s.crop)) flags |= eTraversalNeeded; } + if (what & layer_state_t::eFrameChanged) { + if (layer->setFrame(s.orientedDisplaySpaceRect)) flags |= eTraversalNeeded; + } if (what & layer_state_t::eAcquireFenceChanged) { if (layer->setAcquireFence(s.acquireFence)) flags |= eTraversalNeeded; } diff --git a/services/surfaceflinger/tests/BufferGenerator.cpp b/services/surfaceflinger/tests/BufferGenerator.cpp index 47a150dd35..03f8e1afba 100644 --- a/services/surfaceflinger/tests/BufferGenerator.cpp +++ b/services/surfaceflinger/tests/BufferGenerator.cpp @@ -296,12 +296,12 @@ private: BufferGenerator::BufferGenerator() : mSurfaceManager(new SurfaceManager), mEglManager(new EglManager), mProgram(new Program) { - mBufferSize.set(1000.0, 1000.0); + const float width = 1000.0; + const float height = 1000.0; auto setBufferWithContext = std::bind(setBuffer, std::placeholders::_1, std::placeholders::_2, this); - mSurfaceManager->initialize(mBufferSize.width, mBufferSize.height, HAL_PIXEL_FORMAT_RGBA_8888, - setBufferWithContext); + mSurfaceManager->initialize(width, height, HAL_PIXEL_FORMAT_RGBA_8888, setBufferWithContext); if (!mEglManager->initialize(mSurfaceManager->getSurface())) return; @@ -309,9 +309,7 @@ BufferGenerator::BufferGenerator() if (!mProgram->initialize(VERTEX_SHADER, FRAGMENT_SHADER)) return; mProgram->use(); - mProgram->bindVec4(0, - vec4{mBufferSize.width, mBufferSize.height, 1.0f / mBufferSize.width, - 1.0f / mBufferSize.height}); + mProgram->bindVec4(0, vec4{width, height, 1.0f / width, 1.0f / height}); mProgram->bindVec3(2, &SPHERICAL_HARMONICS[0], 4); glEnableVertexAttribArray(0); @@ -374,10 +372,6 @@ status_t BufferGenerator::get(sp* outBuffer, sp* outFence) return NO_ERROR; } -ui::Size BufferGenerator::getSize() { - return mBufferSize; -} - // static void BufferGenerator::setBuffer(const sp& buffer, int32_t fence, void* bufferGenerator) { diff --git a/services/surfaceflinger/tests/BufferGenerator.h b/services/surfaceflinger/tests/BufferGenerator.h index f7d548b6bf..a3ffe86572 100644 --- a/services/surfaceflinger/tests/BufferGenerator.h +++ b/services/surfaceflinger/tests/BufferGenerator.h @@ -37,7 +37,6 @@ public: /* Static callback that sets the fence on a particular instance */ static void setBuffer(const sp& buffer, int32_t fence, void* fenceGenerator); - ui::Size getSize(); private: bool mInitialized = false; @@ -54,7 +53,6 @@ private: using Epoch = std::chrono::time_point; Epoch mEpoch = std::chrono::steady_clock::now(); - ui::Size mBufferSize; }; } // namespace android diff --git a/services/surfaceflinger/tests/EffectLayer_test.cpp b/services/surfaceflinger/tests/EffectLayer_test.cpp index af00ec7fc9..f470eda7d3 100644 --- a/services/surfaceflinger/tests/EffectLayer_test.cpp +++ b/services/surfaceflinger/tests/EffectLayer_test.cpp @@ -149,6 +149,7 @@ TEST_F(EffectLayerTest, BlurEffectLayerIsVisible) { t.reparent(blurLayer, mParentLayer); t.setBackgroundBlurRadius(blurLayer, blurRadius); t.setCrop(blurLayer, blurRect); + t.setFrame(blurLayer, blurRect); t.setAlpha(blurLayer, 0.0f); t.show(blurLayer); }); diff --git a/services/surfaceflinger/tests/IPC_test.cpp b/services/surfaceflinger/tests/IPC_test.cpp index 9fa3d4c417..a8647c3e50 100644 --- a/services/surfaceflinger/tests/IPC_test.cpp +++ b/services/surfaceflinger/tests/IPC_test.cpp @@ -161,6 +161,7 @@ public: Color::RED); transaction->setLayerStack(mSurfaceControl, 0) .setLayer(mSurfaceControl, std::numeric_limits::max()) + .setFrame(mSurfaceControl, Rect(0, 0, width, height)) .setBuffer(mSurfaceControl, gb) .setAcquireFence(mSurfaceControl, fence) .show(mSurfaceControl) diff --git a/services/surfaceflinger/tests/LayerCallback_test.cpp b/services/surfaceflinger/tests/LayerCallback_test.cpp index 011ff70409..158801a705 100644 --- a/services/surfaceflinger/tests/LayerCallback_test.cpp +++ b/services/surfaceflinger/tests/LayerCallback_test.cpp @@ -164,10 +164,7 @@ TEST_F(LayerCallbackTest, NoBufferNoColor) { return; } - ui::Size bufferSize = getBufferSize(); - TransactionUtils::setFrame(transaction, layer, Rect(0, 0, bufferSize.width, bufferSize.height), - Rect(0, 0, 32, 32)); - transaction.apply(); + transaction.setFrame(layer, Rect(0, 0, 32, 32)).apply(); ExpectedResult expected; expected.addSurface(ExpectedResult::Transaction::NOT_PRESENTED, layer, @@ -187,10 +184,7 @@ TEST_F(LayerCallbackTest, BufferNoColor) { return; } - ui::Size bufferSize = getBufferSize(); - TransactionUtils::setFrame(transaction, layer, Rect(0, 0, bufferSize.width, bufferSize.height), - Rect(0, 0, 32, 32)); - transaction.apply(); + transaction.setFrame(layer, Rect(0, 0, 32, 32)).apply(); ExpectedResult expected; expected.addSurface(ExpectedResult::Transaction::PRESENTED, layer); @@ -209,10 +203,7 @@ TEST_F(LayerCallbackTest, NoBufferColor) { return; } - ui::Size bufferSize = getBufferSize(); - TransactionUtils::setFrame(transaction, layer, Rect(0, 0, bufferSize.width, bufferSize.height), - Rect(0, 0, 32, 32)); - transaction.apply(); + transaction.setFrame(layer, Rect(0, 0, 32, 32)).apply(); ExpectedResult expected; expected.addSurface(ExpectedResult::Transaction::PRESENTED, layer, @@ -247,10 +238,7 @@ TEST_F(LayerCallbackTest, OffScreen) { return; } - ui::Size bufferSize = getBufferSize(); - TransactionUtils::setFrame(transaction, layer, Rect(0, 0, bufferSize.width, bufferSize.height), - Rect(-100, -100, 100, 100)); - transaction.apply(); + transaction.setFrame(layer, Rect(-100, -100, 100, 100)).apply(); ExpectedResult expected; expected.addSurface(ExpectedResult::Transaction::PRESENTED, layer); @@ -275,15 +263,8 @@ TEST_F(LayerCallbackTest, MergeBufferNoColor) { return; } - ui::Size bufferSize = getBufferSize(); - - TransactionUtils::setFrame(transaction1, layer1, - Rect(0, 0, bufferSize.width, bufferSize.height), Rect(0, 0, 32, 32)); - TransactionUtils::setFrame(transaction2, layer2, - Rect(0, 0, bufferSize.width, bufferSize.height), - Rect(32, 32, 64, 64)); - - transaction2.merge(std::move(transaction1)).apply(); + transaction1.setFrame(layer1, Rect(0, 0, 32, 32)); + transaction2.setFrame(layer2, Rect(32, 32, 64, 64)).merge(std::move(transaction1)).apply(); ExpectedResult expected; expected.addSurfaces(ExpectedResult::Transaction::PRESENTED, {layer1, layer2}); @@ -309,15 +290,8 @@ TEST_F(LayerCallbackTest, MergeNoBufferColor) { return; } - ui::Size bufferSize = getBufferSize(); - - TransactionUtils::setFrame(transaction1, layer1, - Rect(0, 0, bufferSize.width, bufferSize.height), Rect(0, 0, 32, 32)); - TransactionUtils::setFrame(transaction2, layer2, - Rect(0, 0, bufferSize.width, bufferSize.height), - Rect(32, 32, 64, 64)); - - transaction2.merge(std::move(transaction1)).apply(); + transaction1.setFrame(layer1, Rect(0, 0, 32, 32)); + transaction2.setFrame(layer2, Rect(32, 32, 64, 64)).merge(std::move(transaction1)).apply(); ExpectedResult expected; expected.addSurfaces(ExpectedResult::Transaction::PRESENTED, {layer1, layer2}, @@ -344,15 +318,8 @@ TEST_F(LayerCallbackTest, MergeOneBufferOneColor) { return; } - ui::Size bufferSize = getBufferSize(); - - TransactionUtils::setFrame(transaction1, layer1, - Rect(0, 0, bufferSize.width, bufferSize.height), Rect(0, 0, 32, 32)); - TransactionUtils::setFrame(transaction2, layer2, - Rect(0, 0, bufferSize.width, bufferSize.height), - Rect(32, 32, 64, 64)); - - transaction2.merge(std::move(transaction1)).apply(); + transaction1.setFrame(layer1, Rect(0, 0, 32, 32)); + transaction2.setFrame(layer2, Rect(32, 32, 64, 64)).merge(std::move(transaction1)).apply(); ExpectedResult expected; expected.addSurface(ExpectedResult::Transaction::PRESENTED, layer1); @@ -438,15 +405,8 @@ TEST_F(LayerCallbackTest, Merge_DifferentClients) { return; } - ui::Size bufferSize = getBufferSize(); - - TransactionUtils::setFrame(transaction1, layer1, - Rect(0, 0, bufferSize.width, bufferSize.height), Rect(0, 0, 32, 32)); - TransactionUtils::setFrame(transaction2, layer2, - Rect(0, 0, bufferSize.width, bufferSize.height), - Rect(32, 32, 64, 64)); - - transaction2.merge(std::move(transaction1)).apply(); + transaction1.setFrame(layer1, Rect(0, 0, 32, 32)); + transaction2.setFrame(layer2, Rect(32, 32, 64, 64)).merge(std::move(transaction1)).apply(); ExpectedResult expected; expected.addSurfaces(ExpectedResult::Transaction::PRESENTED, {layer1, layer2}); @@ -531,11 +491,7 @@ TEST_F(LayerCallbackTest, MultipleTransactions_SameStateChange) { } } - ui::Size bufferSize = getBufferSize(); - TransactionUtils::setFrame(transaction, layer, - Rect(0, 0, bufferSize.width, bufferSize.height), - Rect(0, 0, 32, 32)); - transaction.apply(); + transaction.setFrame(layer, Rect(0, 0, 32, 32)).apply(); ExpectedResult expected; expected.addSurface((i == 0) ? ExpectedResult::Transaction::PRESENTED @@ -567,16 +523,8 @@ TEST_F(LayerCallbackTest, MultipleTransactions_Merge) { return; } - ui::Size bufferSize = getBufferSize(); - - TransactionUtils::setFrame(transaction1, layer1, - Rect(0, 0, bufferSize.width, bufferSize.height), - Rect(0, 0, 32, 32)); - TransactionUtils::setFrame(transaction2, layer2, - Rect(0, 0, bufferSize.width, bufferSize.height), - Rect(32, 32, 64, 64)); - - transaction2.merge(std::move(transaction1)).apply(); + transaction1.setFrame(layer1, Rect(0, 0, 32, 32)); + transaction2.setFrame(layer2, Rect(32, 32, 64, 64)).merge(std::move(transaction1)).apply(); ExpectedResult expected; expected.addSurfaces(ExpectedResult::Transaction::PRESENTED, {layer1, layer2}, @@ -616,16 +564,8 @@ TEST_F(LayerCallbackTest, MultipleTransactions_Merge_DifferentClients) { return; } - ui::Size bufferSize = getBufferSize(); - - TransactionUtils::setFrame(transaction1, layer1, - Rect(0, 0, bufferSize.width, bufferSize.height), - Rect(0, 0, 32, 32)); - TransactionUtils::setFrame(transaction2, layer2, - Rect(0, 0, bufferSize.width, bufferSize.height), - Rect(32, 32, 64, 64)); - - transaction2.merge(std::move(transaction1)).apply(); + transaction1.setFrame(layer1, Rect(0, 0, 32, 32)); + transaction2.setFrame(layer2, Rect(32, 32, 64, 64)).merge(std::move(transaction1)).apply(); ExpectedResult expected; expected.addSurfaces(ExpectedResult::Transaction::PRESENTED, {layer1, layer2}, @@ -666,15 +606,8 @@ TEST_F(LayerCallbackTest, MultipleTransactions_Merge_DifferentClients_NoStateCha return; } - ui::Size bufferSize = getBufferSize(); - - TransactionUtils::setFrame(transaction1, layer1, - Rect(0, 0, bufferSize.width, bufferSize.height), Rect(0, 0, 32, 32)); - TransactionUtils::setFrame(transaction2, layer2, - Rect(0, 0, bufferSize.width, bufferSize.height), - Rect(32, 32, 64, 64)); - - transaction2.merge(std::move(transaction1)).apply(); + transaction1.setFrame(layer1, Rect(0, 0, 32, 32)); + transaction2.setFrame(layer2, Rect(32, 32, 64, 64)).merge(std::move(transaction1)).apply(); ExpectedResult expected; expected.addSurfaces(ExpectedResult::Transaction::PRESENTED, {layer1, layer2}); @@ -728,15 +661,8 @@ TEST_F(LayerCallbackTest, MultipleTransactions_Merge_DifferentClients_SameStateC return; } - ui::Size bufferSize = getBufferSize(); - - TransactionUtils::setFrame(transaction1, layer1, - Rect(0, 0, bufferSize.width, bufferSize.height), Rect(0, 0, 32, 32)); - TransactionUtils::setFrame(transaction2, layer2, - Rect(0, 0, bufferSize.width, bufferSize.height), - Rect(32, 32, 64, 64)); - - transaction2.merge(std::move(transaction1)).apply(); + transaction1.setFrame(layer1, Rect(0, 0, 32, 32)); + transaction2.setFrame(layer2, Rect(32, 32, 64, 64)).merge(std::move(transaction1)).apply(); ExpectedResult expected; expected.addSurfaces(ExpectedResult::Transaction::PRESENTED, {layer1, layer2}); @@ -756,10 +682,7 @@ TEST_F(LayerCallbackTest, MultipleTransactions_Merge_DifferentClients_SameStateC return; } - TransactionUtils::setFrame(transaction2, layer2, - Rect(0, 0, bufferSize.width, bufferSize.height), - Rect(32, 32, 64, 64)); - transaction2.merge(std::move(transaction1)).apply(); + transaction2.setFrame(layer2, Rect(32, 32, 64, 64)).merge(std::move(transaction1)).apply(); expected.addSurface(ExpectedResult::Transaction::NOT_PRESENTED, layer2, ExpectedResult::Buffer::NOT_ACQUIRED); @@ -839,10 +762,7 @@ TEST_F(LayerCallbackTest, MultipleTransactions_SingleFrame_SameStateChange) { return; } - ui::Size bufferSize = getBufferSize(); - TransactionUtils::setFrame(transaction, layer, Rect(0, 0, bufferSize.width, bufferSize.height), - Rect(0, 0, 32, 32)); - transaction.apply(); + transaction.setFrame(layer, Rect(0, 0, 32, 32)).apply(); ExpectedResult expectedResult; expectedResult.addSurface(ExpectedResult::Transaction::PRESENTED, layer); @@ -861,10 +781,7 @@ TEST_F(LayerCallbackTest, MultipleTransactions_SingleFrame_SameStateChange) { return; } - TransactionUtils::setFrame(transaction, layer, - Rect(0, 0, bufferSize.width, bufferSize.height), - Rect(0, 0, 32, 32)); - transaction.apply(); + transaction.setFrame(layer, Rect(0, 0, 32, 32)).apply(); } EXPECT_NO_FATAL_FAILURE(waitForCallbacks(callback, expectedResults, true)); } diff --git a/services/surfaceflinger/tests/LayerRenderTypeTransaction_test.cpp b/services/surfaceflinger/tests/LayerRenderTypeTransaction_test.cpp index 53d230abe7..7505e6ea9b 100644 --- a/services/surfaceflinger/tests/LayerRenderTypeTransaction_test.cpp +++ b/services/surfaceflinger/tests/LayerRenderTypeTransaction_test.cpp @@ -204,7 +204,11 @@ void LayerRenderTypeTransactionTest::setRelativeZBasicHelper(uint32_t layerType) Transaction().setPosition(layerG, 16, 16).setRelativeLayer(layerG, layerR, 1).apply(); break; case ISurfaceComposerClient::eFXSurfaceBufferState: - Transaction().setPosition(layerG, 16, 16).setRelativeLayer(layerG, layerR, 1).apply(); + Transaction() + .setFrame(layerR, Rect(0, 0, 32, 32)) + .setFrame(layerG, Rect(16, 16, 48, 48)) + .setRelativeLayer(layerG, layerR, 1) + .apply(); break; default: ASSERT_FALSE(true) << "Unsupported layer type"; @@ -256,9 +260,10 @@ void LayerRenderTypeTransactionTest::setRelativeZGroupHelper(uint32_t layerType) break; case ISurfaceComposerClient::eFXSurfaceBufferState: Transaction() - .setPosition(layerG, 8, 8) + .setFrame(layerR, Rect(0, 0, 32, 32)) + .setFrame(layerG, Rect(8, 8, 40, 40)) .setRelativeLayer(layerG, layerR, 3) - .setPosition(layerB, 16, 16) + .setFrame(layerB, Rect(16, 16, 48, 48)) .setLayer(layerB, mLayerZBase + 2) .apply(); break; @@ -383,6 +388,7 @@ TEST_P(LayerRenderTypeTransactionTest, SetTransparentRegionHintBasic_BufferState Transaction() .setTransparentRegionHint(layer, Region(top)) .setBuffer(layer, buffer) + .setFrame(layer, Rect(0, 0, 32, 32)) .apply(); { SCOPED_TRACE("top transparent"); @@ -441,7 +447,7 @@ TEST_P(LayerRenderTypeTransactionTest, SetTransparentRegionHintOutOfBounds_Buffe // check that transparent region hint is bound by the layer size Transaction() .setTransparentRegionHint(layerTransparent, Region(mDisplayRect)) - .setPosition(layerR, 16, 16) + .setFrame(layerR, Rect(16, 16, 48, 48)) .setLayer(layerR, mLayerZBase + 1) .apply(); ASSERT_NO_FATAL_FAILURE( @@ -471,7 +477,8 @@ void LayerRenderTypeTransactionTest::setAlphaBasicHelper(uint32_t layerType) { Transaction() .setAlpha(layer1, 0.25f) .setAlpha(layer2, 0.75f) - .setPosition(layer2, 16, 0) + .setFrame(layer1, Rect(0, 0, 32, 32)) + .setFrame(layer2, Rect(16, 0, 48, 32)) .setLayer(layer2, mLayerZBase + 1) .apply(); break; @@ -566,7 +573,7 @@ void LayerRenderTypeTransactionTest::setBackgroundColorHelper(uint32_t layerType ASSERT_NO_FATAL_FAILURE(fillBufferStateLayerColor(layer, fillColor, width, height)); expectedColor = fillColor; } - Transaction().setCrop(layer, Rect(0, 0, width, height)).apply(); + Transaction().setFrame(layer, Rect(0, 0, width, height)).apply(); break; default: GTEST_FAIL() << "Unknown layer type in setBackgroundColorHelper"; @@ -842,39 +849,42 @@ TEST_P(LayerRenderTypeTransactionTest, SetMatrixBasic_BufferState) { ASSERT_NO_FATAL_FAILURE(fillBufferStateLayerQuadrant(layer, 32, 32, Color::RED, Color::GREEN, Color::BLUE, Color::WHITE)); - Transaction().setPosition(layer, 32, 32).setMatrix(layer, 1.0f, 0.0f, 0.0f, 1.0f).apply(); + Transaction() + .setMatrix(layer, 1.0f, 0.0f, 0.0f, 1.0f) + .setFrame(layer, Rect(0, 0, 32, 32)) + .apply(); { SCOPED_TRACE("IDENTITY"); - getScreenCapture()->expectQuadrant(Rect(32, 32, 64, 64), Color::RED, Color::GREEN, + getScreenCapture()->expectQuadrant(Rect(0, 0, 32, 32), Color::RED, Color::GREEN, Color::BLUE, Color::WHITE); } Transaction().setMatrix(layer, -1.0f, 0.0f, 0.0f, 1.0f).apply(); { SCOPED_TRACE("FLIP_H"); - getScreenCapture()->expectQuadrant(Rect(0, 32, 32, 64), Color::GREEN, Color::RED, - Color::WHITE, Color::BLUE); + getScreenCapture()->expectQuadrant(Rect(0, 0, 32, 32), Color::RED, Color::GREEN, + Color::BLUE, Color::WHITE); } Transaction().setMatrix(layer, 1.0f, 0.0f, 0.0f, -1.0f).apply(); { SCOPED_TRACE("FLIP_V"); - getScreenCapture()->expectQuadrant(Rect(32, 0, 64, 32), Color::BLUE, Color::WHITE, - Color::RED, Color::GREEN); + getScreenCapture()->expectQuadrant(Rect(0, 0, 32, 32), Color::RED, Color::GREEN, + Color::BLUE, Color::WHITE); } Transaction().setMatrix(layer, 0.0f, 1.0f, -1.0f, 0.0f).apply(); { SCOPED_TRACE("ROT_90"); - getScreenCapture()->expectQuadrant(Rect(0, 32, 32, 64), Color::BLUE, Color::RED, - Color::WHITE, Color::GREEN); + getScreenCapture()->expectQuadrant(Rect(0, 0, 32, 32), Color::RED, Color::GREEN, + Color::BLUE, Color::WHITE); } Transaction().setMatrix(layer, 2.0f, 0.0f, 0.0f, 2.0f).apply(); { SCOPED_TRACE("SCALE"); - getScreenCapture()->expectQuadrant(Rect(32, 32, 96, 96), Color::RED, Color::GREEN, - Color::BLUE, Color::WHITE, 1 /* tolerance */); + getScreenCapture()->expectQuadrant(Rect(0, 0, 32, 32), Color::RED, Color::GREEN, + Color::BLUE, Color::WHITE); } } @@ -945,8 +955,8 @@ TEST_P(LayerRenderTypeTransactionTest, SetCropBasic_BufferState) { Transaction().setCrop(layer, crop).apply(); auto shot = getScreenCapture(); - shot->expectColor(crop, Color::RED); - shot->expectBorder(crop, Color::BLACK); + shot->expectColor(Rect(0, 0, mDisplayWidth, mDisplayHeight), Color::RED); + shot->expectBorder(Rect(0, 0, mDisplayWidth, mDisplayHeight), Color::BLACK); } TEST_P(LayerRenderTypeTransactionTest, SetCropEmpty_BufferQueue) { @@ -976,13 +986,13 @@ TEST_P(LayerRenderTypeTransactionTest, SetCropEmpty_BufferState) { { SCOPED_TRACE("empty rect"); Transaction().setCrop(layer, Rect(8, 8, 8, 8)).apply(); - getScreenCapture()->expectColor(Rect(0, 0, 32, 32), Color::RED); + getScreenCapture()->expectColor(Rect(0, 0, mDisplayWidth, mDisplayHeight), Color::RED); } { SCOPED_TRACE("negative rect"); Transaction().setCrop(layer, Rect(8, 8, 0, 0)).apply(); - getScreenCapture()->expectColor(Rect(0, 0, 32, 32), Color::RED); + getScreenCapture()->expectColor(Rect(0, 0, mDisplayWidth, mDisplayHeight), Color::RED); } } @@ -1006,6 +1016,8 @@ TEST_P(LayerRenderTypeTransactionTest, SetCropOutOfBounds_BufferState) { TransactionUtils::fillGraphicBufferColor(buffer, Rect(0, 0, 32, 16), Color::BLUE); TransactionUtils::fillGraphicBufferColor(buffer, Rect(0, 16, 32, 64), Color::RED); + Transaction().setFrame(layer, Rect(0, 0, 64, 64)).apply(); + Transaction().setBuffer(layer, buffer).apply(); // Partially out of bounds in the negative (upper left) direction @@ -1013,8 +1025,8 @@ TEST_P(LayerRenderTypeTransactionTest, SetCropOutOfBounds_BufferState) { { SCOPED_TRACE("out of bounds, negative (upper left) direction"); auto shot = getScreenCapture(); - shot->expectColor(Rect(0, 0, 32, 16), Color::BLUE); - shot->expectBorder(Rect(0, 0, 32, 16), Color::BLACK); + shot->expectColor(Rect(0, 0, 64, 64), Color::BLUE); + shot->expectBorder(Rect(0, 0, 64, 64), Color::BLACK); } // Partially out of bounds in the positive (lower right) direction @@ -1022,8 +1034,8 @@ TEST_P(LayerRenderTypeTransactionTest, SetCropOutOfBounds_BufferState) { { SCOPED_TRACE("out of bounds, positive (lower right) direction"); auto shot = getScreenCapture(); - shot->expectColor(Rect(0, 16, 32, 64), Color::RED); - shot->expectBorder(Rect(0, 16, 32, 64), Color::BLACK); + shot->expectColor(Rect(0, 0, 64, 64), Color::RED); + shot->expectBorder(Rect(0, 0, 64, 64), Color::BLACK); } // Fully out of buffer space bounds @@ -1031,7 +1043,9 @@ TEST_P(LayerRenderTypeTransactionTest, SetCropOutOfBounds_BufferState) { { SCOPED_TRACE("Fully out of bounds"); auto shot = getScreenCapture(); - shot->expectColor(Rect(0, 0, 64, 64), Color::BLACK); + shot->expectColor(Rect(0, 0, 64, 16), Color::BLUE); + shot->expectColor(Rect(0, 16, 64, 64), Color::RED); + shot->expectBorder(Rect(0, 0, 64, 64), Color::BLACK); } } @@ -1054,11 +1068,12 @@ TEST_P(LayerRenderTypeTransactionTest, SetCropWithTranslation_BufferState) { layer = createLayer("test", 32, 32, ISurfaceComposerClient::eFXSurfaceBufferState)); ASSERT_NO_FATAL_FAILURE(fillBufferStateLayerColor(layer, Color::RED, 32, 32)); + const Rect frame(32, 32, 64, 64); const Rect crop(8, 8, 24, 24); - Transaction().setPosition(layer, 32, 32).setCrop(layer, crop).apply(); + Transaction().setFrame(layer, frame).setCrop(layer, crop).apply(); auto shot = getScreenCapture(); - shot->expectColor(Rect(40, 40, 56, 56), Color::RED); - shot->expectBorder(Rect(40, 40, 56, 56), Color::BLACK); + shot->expectColor(frame, Color::RED); + shot->expectBorder(frame, Color::BLACK); } TEST_P(LayerRenderTypeTransactionTest, SetCropWithScale_BufferQueue) { @@ -1106,10 +1121,7 @@ TEST_P(LayerRenderTypeTransactionTest, SetFrameBasic_BufferState) { ASSERT_NO_FATAL_FAILURE(fillBufferStateLayerColor(layer, Color::RED, 32, 32)); const Rect frame(8, 8, 24, 24); - Transaction t; - TransactionUtils::setFrame(t, layer, Rect(0, 0, 32, 32), frame); - t.apply(); - + Transaction().setFrame(layer, frame).apply(); auto shot = getScreenCapture(); shot->expectColor(frame, Color::RED); shot->expectBorder(frame, Color::BLACK); @@ -1121,23 +1133,16 @@ TEST_P(LayerRenderTypeTransactionTest, SetFrameEmpty_BufferState) { layer = createLayer("test", 32, 32, ISurfaceComposerClient::eFXSurfaceBufferState)); ASSERT_NO_FATAL_FAILURE(fillBufferStateLayerColor(layer, Color::RED, 32, 32)); - Transaction t; { SCOPED_TRACE("empty rect"); - TransactionUtils::setFrame(t, layer, Rect(0, 0, 32, 32), Rect(8, 8, 8, 8)); - t.apply(); - + Transaction().setFrame(layer, Rect(8, 8, 8, 8)).apply(); getScreenCapture()->expectColor(Rect(0, 0, 32, 32), Color::BLACK); } { SCOPED_TRACE("negative rect"); - TransactionUtils::setFrame(t, layer, Rect(0, 0, 32, 32), Rect(8, 8, 0, 0)); - t.apply(); - - auto shot = getScreenCapture(); - shot->expectColor(Rect(0, 0, 8, 8), Color::RED); - shot->expectBorder(Rect(0, 0, 8, 8), Color::BLACK); + Transaction().setFrame(layer, Rect(8, 8, 0, 0)).apply(); + getScreenCapture()->expectColor(Rect(0, 0, 32, 32), Color::BLACK); } } @@ -1147,10 +1152,10 @@ TEST_P(LayerRenderTypeTransactionTest, SetFrameDefaultParentless_BufferState) { layer = createLayer("test", 32, 32, ISurfaceComposerClient::eFXSurfaceBufferState)); ASSERT_NO_FATAL_FAILURE(fillBufferStateLayerColor(layer, Color::RED, 10, 10)); - // A layer with a buffer will have a computed size that matches the buffer size. + // A parentless layer will default to a frame with the same size as the buffer auto shot = getScreenCapture(); - shot->expectColor(Rect(0, 0, 10, 10), Color::RED); - shot->expectBorder(Rect(0, 0, 10, 10), Color::BLACK); + shot->expectColor(Rect(0, 0, mDisplayWidth, mDisplayHeight), Color::RED); + shot->expectBorder(Rect(0, 0, mDisplayWidth, mDisplayHeight), Color::BLACK); } TEST_P(LayerRenderTypeTransactionTest, SetFrameDefaultBSParent_BufferState) { @@ -1158,16 +1163,17 @@ TEST_P(LayerRenderTypeTransactionTest, SetFrameDefaultBSParent_BufferState) { ASSERT_NO_FATAL_FAILURE( parent = createLayer("test", 32, 32, ISurfaceComposerClient::eFXSurfaceBufferState)); ASSERT_NO_FATAL_FAILURE(fillBufferStateLayerColor(parent, Color::RED, 32, 32)); + Transaction().setFrame(parent, Rect(0, 0, 32, 32)).apply(); ASSERT_NO_FATAL_FAILURE( - child = createLayer("test", 10, 10, ISurfaceComposerClient::eFXSurfaceBufferState)); + child = createLayer("test", 32, 32, ISurfaceComposerClient::eFXSurfaceBufferState)); ASSERT_NO_FATAL_FAILURE(fillBufferStateLayerColor(child, Color::BLUE, 10, 10)); Transaction().reparent(child, parent).apply(); - // A layer with a buffer will have a computed size that matches the buffer size. + // A layer will default to the frame of its parent auto shot = getScreenCapture(); - shot->expectColor(Rect(0, 0, 10, 10), Color::BLUE); + shot->expectColor(Rect(0, 0, 32, 32), Color::BLUE); shot->expectBorder(Rect(0, 0, 32, 32), Color::BLACK); } @@ -1177,14 +1183,14 @@ TEST_P(LayerRenderTypeTransactionTest, SetFrameDefaultBQParent_BufferState) { ASSERT_NO_FATAL_FAILURE(fillBufferQueueLayerColor(parent, Color::RED, 32, 32)); ASSERT_NO_FATAL_FAILURE( - child = createLayer("test", 10, 10, ISurfaceComposerClient::eFXSurfaceBufferState)); + child = createLayer("test", 32, 32, ISurfaceComposerClient::eFXSurfaceBufferState)); ASSERT_NO_FATAL_FAILURE(fillBufferStateLayerColor(child, Color::BLUE, 10, 10)); Transaction().reparent(child, parent).apply(); - // A layer with a buffer will have a computed size that matches the buffer size. + // A layer will default to the frame of its parent auto shot = getScreenCapture(); - shot->expectColor(Rect(0, 0, 10, 10), Color::BLUE); + shot->expectColor(Rect(0, 0, 32, 32), Color::BLUE); shot->expectBorder(Rect(0, 0, 32, 32), Color::BLACK); } @@ -1193,10 +1199,11 @@ TEST_P(LayerRenderTypeTransactionTest, SetFrameUpdate_BufferState) { ASSERT_NO_FATAL_FAILURE( layer = createLayer("test", 32, 32, ISurfaceComposerClient::eFXSurfaceBufferState)); ASSERT_NO_FATAL_FAILURE(fillBufferStateLayerColor(layer, Color::RED, 32, 32)); + Transaction().setFrame(layer, Rect(0, 0, 32, 32)).apply(); std::this_thread::sleep_for(500ms); - Transaction().setPosition(layer, 16, 16).apply(); + Transaction().setFrame(layer, Rect(16, 16, 48, 48)).apply(); auto shot = getScreenCapture(); shot->expectColor(Rect(16, 16, 48, 48), Color::RED); @@ -1208,20 +1215,18 @@ TEST_P(LayerRenderTypeTransactionTest, SetFrameOutsideBounds_BufferState) { ASSERT_NO_FATAL_FAILURE( parent = createLayer("test", 32, 32, ISurfaceComposerClient::eFXSurfaceBufferState)); ASSERT_NO_FATAL_FAILURE( - child = createLayer("test", 10, 10, ISurfaceComposerClient::eFXSurfaceBufferState)); + child = createLayer("test", 32, 32, ISurfaceComposerClient::eFXSurfaceBufferState)); Transaction().reparent(child, parent).apply(); ASSERT_NO_FATAL_FAILURE(fillBufferStateLayerColor(parent, Color::RED, 32, 32)); + Transaction().setFrame(parent, Rect(0, 0, 32, 32)).apply(); ASSERT_NO_FATAL_FAILURE(fillBufferStateLayerColor(child, Color::BLUE, 10, 10)); - Rect childDst(0, 16, 32, 32); - Transaction t; - TransactionUtils::setFrame(t, child, Rect(0, 0, 10, 10), childDst); - t.apply(); + Transaction().setFrame(child, Rect(0, 16, 32, 32)).apply(); auto shot = getScreenCapture(); shot->expectColor(Rect(0, 0, 32, 16), Color::RED); - shot->expectColor(childDst, Color::BLUE); + shot->expectColor(Rect(0, 16, 32, 32), Color::BLUE); shot->expectBorder(Rect(0, 0, 32, 32), Color::BLACK); } @@ -1233,8 +1238,8 @@ TEST_P(LayerRenderTypeTransactionTest, SetBufferBasic_BufferState) { ASSERT_NO_FATAL_FAILURE(fillBufferStateLayerColor(layer, Color::RED, 32, 32)); auto shot = getScreenCapture(); - shot->expectColor(Rect(0, 0, 32, 32), Color::RED); - shot->expectBorder(Rect(0, 0, 32, 32), Color::BLACK); + shot->expectColor(Rect(0, 0, mDisplayWidth, mDisplayHeight), Color::RED); + shot->expectBorder(Rect(0, 0, mDisplayWidth, mDisplayHeight), Color::BLACK); } TEST_P(LayerRenderTypeTransactionTest, SetBufferMultipleBuffers_BufferState) { @@ -1247,8 +1252,8 @@ TEST_P(LayerRenderTypeTransactionTest, SetBufferMultipleBuffers_BufferState) { { SCOPED_TRACE("set buffer 1"); auto shot = getScreenCapture(); - shot->expectColor(Rect(0, 0, 32, 32), Color::RED); - shot->expectBorder(Rect(0, 0, 32, 32), Color::BLACK); + shot->expectColor(Rect(0, 0, mDisplayWidth, mDisplayHeight), Color::RED); + shot->expectBorder(Rect(0, 0, mDisplayWidth, mDisplayHeight), Color::BLACK); } ASSERT_NO_FATAL_FAILURE(fillBufferStateLayerColor(layer, Color::BLUE, 32, 32)); @@ -1256,8 +1261,8 @@ TEST_P(LayerRenderTypeTransactionTest, SetBufferMultipleBuffers_BufferState) { { SCOPED_TRACE("set buffer 2"); auto shot = getScreenCapture(); - shot->expectColor(Rect(0, 0, 32, 32), Color::BLUE); - shot->expectBorder(Rect(0, 0, 32, 32), Color::BLACK); + shot->expectColor(Rect(0, 0, mDisplayWidth, mDisplayHeight), Color::BLUE); + shot->expectBorder(Rect(0, 0, mDisplayWidth, mDisplayHeight), Color::BLACK); } ASSERT_NO_FATAL_FAILURE(fillBufferStateLayerColor(layer, Color::RED, 32, 32)); @@ -1265,8 +1270,8 @@ TEST_P(LayerRenderTypeTransactionTest, SetBufferMultipleBuffers_BufferState) { { SCOPED_TRACE("set buffer 3"); auto shot = getScreenCapture(); - shot->expectColor(Rect(0, 0, 32, 32), Color::RED); - shot->expectBorder(Rect(0, 0, 32, 32), Color::BLACK); + shot->expectColor(Rect(0, 0, mDisplayWidth, mDisplayHeight), Color::RED); + shot->expectBorder(Rect(0, 0, mDisplayWidth, mDisplayHeight), Color::BLACK); } } @@ -1281,6 +1286,7 @@ TEST_P(LayerRenderTypeTransactionTest, SetBufferMultipleLayers_BufferState) { ASSERT_NO_FATAL_FAILURE(fillBufferStateLayerColor(layer1, Color::RED, 64, 64)); + Transaction().setFrame(layer1, Rect(0, 0, 64, 64)).apply(); { SCOPED_TRACE("set layer 1 buffer red"); auto shot = getScreenCapture(); @@ -1289,6 +1295,7 @@ TEST_P(LayerRenderTypeTransactionTest, SetBufferMultipleLayers_BufferState) { ASSERT_NO_FATAL_FAILURE(fillBufferStateLayerColor(layer2, Color::BLUE, 32, 32)); + Transaction().setFrame(layer2, Rect(0, 0, 32, 32)).apply(); { SCOPED_TRACE("set layer 2 buffer blue"); auto shot = getScreenCapture(); @@ -1343,8 +1350,8 @@ TEST_P(LayerRenderTypeTransactionTest, SetBufferCaching_BufferState) { Color color = colors[idx % colors.size()]; auto shot = screenshot(); - shot->expectColor(Rect(0, 0, 32, 32), color); - shot->expectBorder(Rect(0, 0, 32, 32), Color::BLACK); + shot->expectColor(Rect(0, 0, mDisplayWidth, mDisplayHeight), color); + shot->expectBorder(Rect(0, 0, mDisplayWidth, mDisplayHeight), Color::BLACK); } idx++; } @@ -1376,8 +1383,8 @@ TEST_P(LayerRenderTypeTransactionTest, SetBufferCaching_LeastRecentlyUsed_Buffer Color color = colors[idx % colors.size()]; auto shot = screenshot(); - shot->expectColor(Rect(0, 0, 32, 32), color); - shot->expectBorder(Rect(0, 0, 32, 32), Color::BLACK); + shot->expectColor(Rect(0, 0, mDisplayWidth, mDisplayHeight), color); + shot->expectBorder(Rect(0, 0, mDisplayWidth, mDisplayHeight), Color::BLACK); } idx++; } @@ -1409,8 +1416,8 @@ TEST_P(LayerRenderTypeTransactionTest, SetBufferCaching_DestroyedBuffer_BufferSt Color color = colors[idx % colors.size()]; auto shot = screenshot(); - shot->expectColor(Rect(0, 0, 32, 32), color); - shot->expectBorder(Rect(0, 0, 32, 32), Color::BLACK); + shot->expectColor(Rect(0, 0, mDisplayWidth, mDisplayHeight), color); + shot->expectBorder(Rect(0, 0, mDisplayWidth, mDisplayHeight), Color::BLACK); } if (idx == 0) { buffers[0].clear(); @@ -1428,6 +1435,7 @@ TEST_P(LayerRenderTypeTransactionTest, SetTransformRotate90_BufferState) { Color::BLUE, Color::WHITE)); Transaction() + .setFrame(layer, Rect(0, 0, 32, 32)) .setTransform(layer, NATIVE_WINDOW_TRANSFORM_ROT_90) .apply(); @@ -1444,6 +1452,7 @@ TEST_P(LayerRenderTypeTransactionTest, SetTransformFlipH_BufferState) { Color::BLUE, Color::WHITE)); Transaction() + .setFrame(layer, Rect(0, 0, 32, 32)) .setTransform(layer, NATIVE_WINDOW_TRANSFORM_FLIP_H) .apply(); @@ -1460,6 +1469,7 @@ TEST_P(LayerRenderTypeTransactionTest, SetTransformFlipV_BufferState) { Color::BLUE, Color::WHITE)); Transaction() + .setFrame(layer, Rect(0, 0, 32, 32)) .setTransform(layer, NATIVE_WINDOW_TRANSFORM_FLIP_V) .apply(); @@ -1508,8 +1518,8 @@ TEST_P(LayerRenderTypeTransactionTest, SetFenceNull_BufferState) { Transaction().setBuffer(layer, buffer).setAcquireFence(layer, fence).apply(); auto shot = getScreenCapture(); - shot->expectColor(Rect(0, 0, 32, 32), Color::RED); - shot->expectBorder(Rect(0, 0, 32, 32), Color::BLACK); + shot->expectColor(Rect(0, 0, mDisplayWidth, mDisplayHeight), Color::RED); + shot->expectBorder(Rect(0, 0, mDisplayWidth, mDisplayHeight), Color::BLACK); } TEST_P(LayerRenderTypeTransactionTest, SetDataspaceBasic_BufferState) { @@ -1524,8 +1534,8 @@ TEST_P(LayerRenderTypeTransactionTest, SetDataspaceBasic_BufferState) { Transaction().setBuffer(layer, buffer).setDataspace(layer, ui::Dataspace::UNKNOWN).apply(); auto shot = getScreenCapture(); - shot->expectColor(Rect(0, 0, 32, 32), Color::RED); - shot->expectBorder(Rect(0, 0, 32, 32), Color::BLACK); + shot->expectColor(Rect(0, 0, mDisplayWidth, mDisplayHeight), Color::RED); + shot->expectBorder(Rect(0, 0, mDisplayWidth, mDisplayHeight), Color::BLACK); } TEST_P(LayerRenderTypeTransactionTest, SetHdrMetadataBasic_BufferState) { @@ -1542,8 +1552,8 @@ TEST_P(LayerRenderTypeTransactionTest, SetHdrMetadataBasic_BufferState) { Transaction().setBuffer(layer, buffer).setHdrMetadata(layer, hdrMetadata).apply(); auto shot = getScreenCapture(); - shot->expectColor(Rect(0, 0, 32, 32), Color::RED); - shot->expectBorder(Rect(0, 0, 32, 32), Color::BLACK); + shot->expectColor(Rect(0, 0, mDisplayWidth, mDisplayHeight), Color::RED); + shot->expectBorder(Rect(0, 0, mDisplayWidth, mDisplayHeight), Color::BLACK); } TEST_P(LayerRenderTypeTransactionTest, SetSurfaceDamageRegionBasic_BufferState) { @@ -1560,8 +1570,8 @@ TEST_P(LayerRenderTypeTransactionTest, SetSurfaceDamageRegionBasic_BufferState) Transaction().setBuffer(layer, buffer).setSurfaceDamageRegion(layer, region).apply(); auto shot = getScreenCapture(); - shot->expectColor(Rect(0, 0, 32, 32), Color::RED); - shot->expectBorder(Rect(0, 0, 32, 32), Color::BLACK); + shot->expectColor(Rect(0, 0, mDisplayWidth, mDisplayHeight), Color::RED); + shot->expectBorder(Rect(0, 0, mDisplayWidth, mDisplayHeight), Color::BLACK); } TEST_P(LayerRenderTypeTransactionTest, SetApiBasic_BufferState) { @@ -1576,8 +1586,8 @@ TEST_P(LayerRenderTypeTransactionTest, SetApiBasic_BufferState) { Transaction().setBuffer(layer, buffer).setApi(layer, NATIVE_WINDOW_API_CPU).apply(); auto shot = getScreenCapture(); - shot->expectColor(Rect(0, 0, 32, 32), Color::RED); - shot->expectBorder(Rect(0, 0, 32, 32), Color::BLACK); + shot->expectColor(Rect(0, 0, mDisplayWidth, mDisplayHeight), Color::RED); + shot->expectBorder(Rect(0, 0, mDisplayWidth, mDisplayHeight), Color::BLACK); } TEST_P(LayerRenderTypeTransactionTest, SetColorTransformBasic) { diff --git a/services/surfaceflinger/tests/LayerTransactionTest.h b/services/surfaceflinger/tests/LayerTransactionTest.h index 0bc8fe7aa0..87c7b7d829 100644 --- a/services/surfaceflinger/tests/LayerTransactionTest.h +++ b/services/surfaceflinger/tests/LayerTransactionTest.h @@ -244,11 +244,6 @@ protected: return bufferGenerator.get(outBuffer, outFence); } - static ui::Size getBufferSize() { - static BufferGenerator bufferGenerator; - return bufferGenerator.getSize(); - } - sp mClient; bool deviceSupportsBlurs() { diff --git a/services/surfaceflinger/tests/LayerTypeAndRenderTypeTransaction_test.cpp b/services/surfaceflinger/tests/LayerTypeAndRenderTypeTransaction_test.cpp index edf55ea6ef..ac5e297e43 100644 --- a/services/surfaceflinger/tests/LayerTypeAndRenderTypeTransaction_test.cpp +++ b/services/surfaceflinger/tests/LayerTypeAndRenderTypeTransaction_test.cpp @@ -196,7 +196,17 @@ TEST_P(LayerTypeAndRenderTypeTransactionTest, SetCornerRadius) { ASSERT_NO_FATAL_FAILURE(layer = createLayer("test", size, size)); ASSERT_NO_FATAL_FAILURE(fillLayerColor(layer, Color::RED, size, size)); - Transaction().setCornerRadius(layer, cornerRadius).apply(); + if (mLayerType == ISurfaceComposerClient::eFXSurfaceBufferQueue) { + Transaction() + .setCornerRadius(layer, cornerRadius) + .setCrop(layer, Rect(0, 0, size, size)) + .apply(); + } else { + Transaction() + .setCornerRadius(layer, cornerRadius) + .setFrame(layer, Rect(0, 0, size, size)) + .apply(); + } { const uint8_t bottom = size - 1; const uint8_t right = size - 1; @@ -224,13 +234,19 @@ TEST_P(LayerTypeAndRenderTypeTransactionTest, SetCornerRadiusRotated) { ASSERT_NO_FATAL_FAILURE(child = createLayer("child", size, size)); ASSERT_NO_FATAL_FAILURE(fillLayerColor(child, Color::GREEN, size, size)); - Transaction() - .setCornerRadius(parent, cornerRadius) - .reparent(child, parent) - .setPosition(child, 0, size) - // Rotate by half PI - .setMatrix(child, 0.0f, -1.0f, 1.0f, 0.0f) - .apply(); + auto transaction = Transaction() + .setCornerRadius(parent, cornerRadius) + .setCrop(parent, Rect(0, 0, size, size)) + .reparent(child, parent) + .setPosition(child, 0, size) + // Rotate by half PI + .setMatrix(child, 0.0f, -1.0f, 1.0f, 0.0f); + if (mLayerType == ISurfaceComposerClient::eFXSurfaceBufferQueue) { + transaction.setCrop(parent, Rect(0, 0, size, size)); + } else { + transaction.setFrame(parent, Rect(0, 0, size, size)); + } + transaction.apply(); { const uint8_t bottom = size - 1; @@ -259,12 +275,21 @@ TEST_P(LayerTypeAndRenderTypeTransactionTest, SetCornerRadiusChildCrop) { ASSERT_NO_FATAL_FAILURE(child = createLayer("child", size, size / 2)); ASSERT_NO_FATAL_FAILURE(fillLayerColor(child, Color::GREEN, size, size / 2)); - Transaction() - .setCornerRadius(parent, cornerRadius) - .reparent(child, parent) - .setPosition(child, 0, size / 2) - .apply(); - + if (mLayerType == ISurfaceComposerClient::eFXSurfaceBufferQueue) { + Transaction() + .setCornerRadius(parent, cornerRadius) + .setCrop(parent, Rect(0, 0, size, size)) + .reparent(child, parent) + .setPosition(child, 0, size / 2) + .apply(); + } else { + Transaction() + .setCornerRadius(parent, cornerRadius) + .setFrame(parent, Rect(0, 0, size, size)) + .reparent(child, parent) + .setFrame(child, Rect(0, size / 2, size, size)) + .apply(); + } { const uint8_t bottom = size - 1; const uint8_t right = size - 1; @@ -306,9 +331,12 @@ TEST_P(LayerTypeAndRenderTypeTransactionTest, SetBackgroundBlurRadiusSimple) { Transaction() .setLayer(greenLayer, mLayerZBase) + .setFrame(leftLayer, {0, 0, canvasSize * 2, canvasSize * 2}) .setLayer(leftLayer, mLayerZBase + 1) + .setFrame(leftLayer, leftRect) .setLayer(rightLayer, mLayerZBase + 2) .setPosition(rightLayer, rightRect.left, rightRect.top) + .setFrame(rightLayer, rightRect) .apply(); { @@ -324,6 +352,7 @@ TEST_P(LayerTypeAndRenderTypeTransactionTest, SetBackgroundBlurRadiusSimple) { .setLayer(blurLayer, mLayerZBase + 3) .setBackgroundBlurRadius(blurLayer, blurRadius) .setCrop(blurLayer, blurRect) + .setFrame(blurLayer, blurRect) .setSize(blurLayer, blurRect.getWidth(), blurRect.getHeight()) .setAlpha(blurLayer, 0.0f) .apply(); @@ -406,8 +435,10 @@ TEST_P(LayerTypeAndRenderTypeTransactionTest, SetBackgroundBlurAffectedByParentA Transaction() .setLayer(left, mLayerZBase + 1) + .setFrame(left, {0, 0, size, size}) .setLayer(right, mLayerZBase + 2) .setPosition(right, size, 0) + .setFrame(right, {size, 0, size * 2, size}) .apply(); { @@ -426,6 +457,7 @@ TEST_P(LayerTypeAndRenderTypeTransactionTest, SetBackgroundBlurAffectedByParentA .setAlpha(blurParent, 0.5) .setLayer(blur, mLayerZBase + 4) .setBackgroundBlurRadius(blur, size) // set the blur radius to the size of one rect + .setFrame(blur, {0, 0, size * 2, size}) .reparent(blur, blurParent) .apply(); diff --git a/services/surfaceflinger/tests/MirrorLayer_test.cpp b/services/surfaceflinger/tests/MirrorLayer_test.cpp index ccf434d63a..613b21ef04 100644 --- a/services/surfaceflinger/tests/MirrorLayer_test.cpp +++ b/services/surfaceflinger/tests/MirrorLayer_test.cpp @@ -195,7 +195,7 @@ TEST_F(MirrorLayerTest, MirrorBufferLayer) { createLayer("BufferStateLayer", 200, 200, ISurfaceComposerClient::eFXSurfaceBufferState, mChildLayer.get()); fillBufferStateLayerColor(bufferStateLayer, Color::BLUE, 200, 200); - Transaction().show(bufferStateLayer).apply(); + Transaction().setFrame(bufferStateLayer, Rect(0, 0, 200, 200)).show(bufferStateLayer).apply(); { SCOPED_TRACE("Initial Mirror BufferStateLayer"); diff --git a/services/surfaceflinger/tests/utils/TransactionUtils.h b/services/surfaceflinger/tests/utils/TransactionUtils.h index 8c448e2f96..3cbfed98f5 100644 --- a/services/surfaceflinger/tests/utils/TransactionUtils.h +++ b/services/surfaceflinger/tests/utils/TransactionUtils.h @@ -126,7 +126,7 @@ public: const uint8_t* src = pixels + (outBuffer->getStride() * (y + j) + x) * 4; for (int32_t i = 0; i < width; i++) { const uint8_t expected[4] = {color.r, color.g, color.b, color.a}; - ASSERT_TRUE(std::equal(src, src + 4, expected, colorCompare)) + EXPECT_TRUE(std::equal(src, src + 4, expected, colorCompare)) << "pixel @ (" << x + i << ", " << y + j << "): " << "expected (" << color << "), " << "got (" << Color{src[0], src[1], src[2], src[3]} << ")"; @@ -161,22 +161,6 @@ public: ASSERT_EQ(NO_ERROR, s->unlockAndPost()); } } - - static void setFrame(Transaction& t, const sp& sc, Rect source, Rect dest, - int32_t transform = 0) { - uint32_t sourceWidth = source.getWidth(); - uint32_t sourceHeight = source.getHeight(); - - if (transform & ui::Transform::ROT_90) { - std::swap(sourceWidth, sourceHeight); - } - - float dsdx = dest.getWidth() / static_cast(sourceWidth); - float dsdy = dest.getHeight() / static_cast(sourceHeight); - - t.setMatrix(sc, dsdx, 0, 0, dsdy); - t.setPosition(sc, dest.left, dest.top); - } }; enum class RenderPath { SCREENSHOT, VIRTUAL_DISPLAY }; -- cgit v1.2.3-59-g8ed1b From 6bbb6861085bf7bc61173a5a0d61d74c876a7017 Mon Sep 17 00:00:00 2001 From: Orion Hodson Date: Thu, 8 Apr 2021 12:30:21 +0000 Subject: Revert "Remove setFrame from BufferStateLayer" Revert "Update tests to reflect the new behavior for setGeometry" Revert submission 13843937-sc_remove_set_frame Reason for revert: Candidate CL for b/184807094 Reverted Changes: Iffbd955a3:Remove setFrame I27f17bc61:Update tests to reflect the new behavior for setGe... I5720276c1:Remove setFrame from surface_control setGeometry I32ee0e3e4:Remove setFrame from BufferStateLayer Bug: 184807094 Change-Id: I8330f374c50c76d8c2e70b79815bc2bc32b89480 (cherry picked from commit 1014c4bf14f5c250b78d7e917fb59aaa9b0d9b0a) --- libs/gui/BLASTBufferQueue.cpp | 29 +--- libs/gui/LayerState.cpp | 4 + libs/gui/SurfaceComposerClient.cpp | 14 ++ libs/gui/include/gui/BLASTBufferQueue.h | 32 +--- libs/gui/include/gui/LayerState.h | 2 +- libs/gui/include/gui/SurfaceComposerClient.h | 1 + libs/gui/tests/BLASTBufferQueue_test.cpp | 34 ++-- services/surfaceflinger/BufferStateLayer.cpp | 98 +++++++----- services/surfaceflinger/BufferStateLayer.h | 10 +- services/surfaceflinger/Layer.cpp | 4 +- services/surfaceflinger/Layer.h | 1 + services/surfaceflinger/RefreshRateOverlay.cpp | 8 +- services/surfaceflinger/SurfaceFlinger.cpp | 3 + services/surfaceflinger/tests/BufferGenerator.cpp | 14 +- services/surfaceflinger/tests/BufferGenerator.h | 2 - services/surfaceflinger/tests/EffectLayer_test.cpp | 1 + services/surfaceflinger/tests/IPC_test.cpp | 1 + .../surfaceflinger/tests/LayerCallback_test.cpp | 131 +++------------- .../tests/LayerRenderTypeTransaction_test.cpp | 174 +++++++++++---------- .../surfaceflinger/tests/LayerTransactionTest.h | 5 - .../LayerTypeAndRenderTypeTransaction_test.cpp | 60 +++++-- services/surfaceflinger/tests/MirrorLayer_test.cpp | 2 +- .../surfaceflinger/tests/utils/TransactionUtils.h | 18 +-- 23 files changed, 295 insertions(+), 353 deletions(-) diff --git a/libs/gui/BLASTBufferQueue.cpp b/libs/gui/BLASTBufferQueue.cpp index e5afd408a9..bcdd06b6c8 100644 --- a/libs/gui/BLASTBufferQueue.cpp +++ b/libs/gui/BLASTBufferQueue.cpp @@ -204,16 +204,13 @@ void BLASTBufferQueue::update(const sp& surface, uint32_t width, if (mRequestedSize != newSize) { mRequestedSize.set(newSize); mBufferItemConsumer->setDefaultBufferSize(mRequestedSize.width, mRequestedSize.height); - if (mLastBufferInfo.scalingMode != NATIVE_WINDOW_SCALING_MODE_FREEZE) { + if (mLastBufferScalingMode != NATIVE_WINDOW_SCALING_MODE_FREEZE) { // If the buffer supports scaling, update the frame immediately since the client may // want to scale the existing buffer to the new size. mSize = mRequestedSize; - // We only need to update the scale if we've received at least one buffer. The reason - // for this is the scale is calculated based on the requested size and buffer size. - // If there's no buffer, the scale will always be 1. - if (mLastBufferInfo.hasBuffer) { - setMatrix(&t, mLastBufferInfo); - } + t.setFrame(mSurfaceControl, + {0, 0, static_cast(mSize.width), + static_cast(mSize.height)}); applyTransaction = true; } } @@ -377,10 +374,8 @@ void BLASTBufferQueue::processNextBufferLocked(bool useNextTransaction) { // Ensure BLASTBufferQueue stays alive until we receive the transaction complete callback. incStrong((void*)transactionCallbackThunk); + mLastBufferScalingMode = bufferItem.mScalingMode; mLastAcquiredFrameNumber = bufferItem.mFrameNumber; - mLastBufferInfo.update(true /* hasBuffer */, bufferItem.mGraphicBuffer->getWidth(), - bufferItem.mGraphicBuffer->getHeight(), bufferItem.mTransform, - bufferItem.mScalingMode); auto releaseBufferCallback = std::bind(releaseBufferCallbackThunk, wp(this) /* callbackContext */, @@ -393,7 +388,8 @@ void BLASTBufferQueue::processNextBufferLocked(bool useNextTransaction) { bufferItem.mFence ? new Fence(bufferItem.mFence->dup()) : Fence::NO_FENCE); t->addTransactionCompletedCallback(transactionCallbackThunk, static_cast(this)); - setMatrix(t, mLastBufferInfo); + t->setFrame(mSurfaceControl, + {0, 0, static_cast(mSize.width), static_cast(mSize.height)}); t->setCrop(mSurfaceControl, computeCrop(bufferItem)); t->setTransform(mSurfaceControl, bufferItem.mTransform); t->setTransformToDisplayInverse(mSurfaceControl, bufferItem.mTransformToDisplayInverse); @@ -519,17 +515,6 @@ bool BLASTBufferQueue::rejectBuffer(const BufferItem& item) { return mSize != bufferSize; } -void BLASTBufferQueue::setMatrix(SurfaceComposerClient::Transaction* t, - const BufferInfo& bufferInfo) { - uint32_t bufWidth = bufferInfo.width; - uint32_t bufHeight = bufferInfo.height; - - float dsdx = mSize.width / static_cast(bufWidth); - float dsdy = mSize.height / static_cast(bufHeight); - - t->setMatrix(mSurfaceControl, dsdx, 0, 0, dsdy); -} - void BLASTBufferQueue::setTransactionCompleteCallback( uint64_t frameNumber, std::function&& transactionCompleteCallback) { std::lock_guard _lock{mMutex}; diff --git a/libs/gui/LayerState.cpp b/libs/gui/LayerState.cpp index 0ca497795b..2a9a97ed13 100644 --- a/libs/gui/LayerState.cpp +++ b/libs/gui/LayerState.cpp @@ -459,6 +459,10 @@ void layer_state_t::merge(const layer_state_t& other) { what |= eCropChanged; crop = other.crop; } + if (other.what & eFrameChanged) { + what |= eFrameChanged; + orientedDisplaySpaceRect = other.orientedDisplaySpaceRect; + } if (other.what & eBufferChanged) { what |= eBufferChanged; buffer = other.buffer; diff --git a/libs/gui/SurfaceComposerClient.cpp b/libs/gui/SurfaceComposerClient.cpp index c888312184..879955b7d7 100644 --- a/libs/gui/SurfaceComposerClient.cpp +++ b/libs/gui/SurfaceComposerClient.cpp @@ -1246,6 +1246,20 @@ SurfaceComposerClient::Transaction::setTransformToDisplayInverse(const sp& sc, const Rect& frame) { + layer_state_t* s = getLayerState(sc); + if (!s) { + mStatus = BAD_INDEX; + return *this; + } + s->what |= layer_state_t::eFrameChanged; + s->orientedDisplaySpaceRect = frame; + + registerSurfaceControlForCallback(sc); + return *this; +} + SurfaceComposerClient::Transaction& SurfaceComposerClient::Transaction::setBuffer( const sp& sc, const sp& buffer, ReleaseBufferCallback callback) { diff --git a/libs/gui/include/gui/BLASTBufferQueue.h b/libs/gui/include/gui/BLASTBufferQueue.h index a48f95ae73..fbd16f4ea2 100644 --- a/libs/gui/include/gui/BLASTBufferQueue.h +++ b/libs/gui/include/gui/BLASTBufferQueue.h @@ -142,33 +142,6 @@ private: ui::Size mRequestedSize GUARDED_BY(mMutex); int32_t mFormat GUARDED_BY(mMutex); - struct BufferInfo { - bool hasBuffer = false; - uint32_t width; - uint32_t height; - uint32_t transform; - // This is used to check if we should update the blast layer size immediately or wait until - // we get the next buffer. This will support scenarios where the layer can change sizes - // and the buffer will scale to fit the new size. - uint32_t scalingMode = NATIVE_WINDOW_SCALING_MODE_SCALE_TO_WINDOW; - - void update(bool hasBuffer, uint32_t width, uint32_t height, uint32_t transform, - uint32_t scalingMode) { - this->hasBuffer = hasBuffer; - this->width = width; - this->height = height; - this->transform = transform; - this->scalingMode = scalingMode; - } - }; - - // Last acquired buffer's info. This is used to calculate the correct scale when size change is - // requested. We need to use the old buffer's info to determine what scale we need to apply to - // ensure the correct size. - BufferInfo mLastBufferInfo GUARDED_BY(mMutex); - void setMatrix(SurfaceComposerClient::Transaction* t, const BufferInfo& bufferInfo) - REQUIRES(mMutex); - uint32_t mTransformHint GUARDED_BY(mMutex); sp mConsumer; @@ -186,6 +159,11 @@ private: std::queue mNextFrameTimelineInfoQueue GUARDED_BY(mMutex); + // Last acquired buffer's scaling mode. This is used to check if we should update the blast + // layer size immediately or wait until we get the next buffer. This will support scenarios + // where the layer can change sizes and the buffer will scale to fit the new size. + uint32_t mLastBufferScalingMode = NATIVE_WINDOW_SCALING_MODE_SCALE_TO_WINDOW; + // Tracks the last acquired frame number uint64_t mLastAcquiredFrameNumber GUARDED_BY(mMutex) = 0; diff --git a/libs/gui/include/gui/LayerState.h b/libs/gui/include/gui/LayerState.h index 706a09c3c7..6c265c898a 100644 --- a/libs/gui/include/gui/LayerState.h +++ b/libs/gui/include/gui/LayerState.h @@ -106,7 +106,7 @@ struct layer_state_t { eHasListenerCallbacksChanged = 0x20000000, eInputInfoChanged = 0x40000000, eCornerRadiusChanged = 0x80000000, - /* was eFrameChanged, now available 0x1'00000000, */ + eFrameChanged = 0x1'00000000, eCachedBufferChanged = 0x2'00000000, eBackgroundColorChanged = 0x4'00000000, eMetadataChanged = 0x8'00000000, diff --git a/libs/gui/include/gui/SurfaceComposerClient.h b/libs/gui/include/gui/SurfaceComposerClient.h index 731af58e85..7ec5d8df83 100644 --- a/libs/gui/include/gui/SurfaceComposerClient.h +++ b/libs/gui/include/gui/SurfaceComposerClient.h @@ -479,6 +479,7 @@ public: Transaction& setTransform(const sp& sc, uint32_t transform); Transaction& setTransformToDisplayInverse(const sp& sc, bool transformToDisplayInverse); + Transaction& setFrame(const sp& sc, const Rect& frame); Transaction& setBuffer(const sp& sc, const sp& buffer, ReleaseBufferCallback callback = nullptr); Transaction& setCachedBuffer(const sp& sc, int32_t bufferId); diff --git a/libs/gui/tests/BLASTBufferQueue_test.cpp b/libs/gui/tests/BLASTBufferQueue_test.cpp index 9b1f0db83b..fe48d88376 100644 --- a/libs/gui/tests/BLASTBufferQueue_test.cpp +++ b/libs/gui/tests/BLASTBufferQueue_test.cpp @@ -140,6 +140,7 @@ protected: /*parent*/ nullptr); t.setLayerStack(mSurfaceControl, 0) .setLayer(mSurfaceControl, std::numeric_limits::max()) + .setFrame(mSurfaceControl, Rect(resolution)) .show(mSurfaceControl) .setDataspace(mSurfaceControl, ui::Dataspace::V0_SRGB) .apply(); @@ -217,13 +218,13 @@ protected: col >= region.left - border && col < region.right + border; } if (!outsideRegion && inRegion) { - ASSERT_GE(epsilon, abs(r - *(pixel))); - ASSERT_GE(epsilon, abs(g - *(pixel + 1))); - ASSERT_GE(epsilon, abs(b - *(pixel + 2))); + EXPECT_GE(epsilon, abs(r - *(pixel))); + EXPECT_GE(epsilon, abs(g - *(pixel + 1))); + EXPECT_GE(epsilon, abs(b - *(pixel + 2))); } else if (outsideRegion && !inRegion) { - ASSERT_GE(epsilon, abs(r - *(pixel))); - ASSERT_GE(epsilon, abs(g - *(pixel + 1))); - ASSERT_GE(epsilon, abs(b - *(pixel + 2))); + EXPECT_GE(epsilon, abs(r - *(pixel))); + EXPECT_GE(epsilon, abs(g - *(pixel + 1))); + EXPECT_GE(epsilon, abs(b - *(pixel + 2))); } ASSERT_EQ(false, ::testing::Test::HasFailure()); } @@ -465,8 +466,7 @@ TEST_F(BLASTBufferQueueTest, SetCrop_Item) { ASSERT_EQ(NO_ERROR, captureDisplay(mCaptureArgs, mCaptureResults)); ASSERT_NO_FATAL_FAILURE( - checkScreenCapture(r, g, b, - {0, 0, (int32_t)mDisplayWidth, (int32_t)mDisplayHeight / 2})); + checkScreenCapture(r, g, b, {0, 0, (int32_t)mDisplayWidth, (int32_t)mDisplayHeight})); } TEST_F(BLASTBufferQueueTest, SetCrop_ScalingModeScaleCrop) { @@ -523,15 +523,13 @@ TEST_F(BLASTBufferQueueTest, SetCrop_ScalingModeScaleCrop) { // capture screen and verify that it is red ASSERT_EQ(NO_ERROR, captureDisplay(mCaptureArgs, mCaptureResults)); - Rect bounds; - bounds.left = finalCropSideLength / 2; - bounds.top = 0; - bounds.right = bounds.left + finalCropSideLength; - bounds.bottom = finalCropSideLength; - - ASSERT_NO_FATAL_FAILURE(checkScreenCapture(r, g, b, bounds)); ASSERT_NO_FATAL_FAILURE( - checkScreenCapture(0, 0, 0, bounds, /*border*/ 0, /*outsideRegion*/ true)); + checkScreenCapture(r, g, b, + {0, 0, (int32_t)bufferSideLength, (int32_t)bufferSideLength})); + ASSERT_NO_FATAL_FAILURE( + checkScreenCapture(0, 0, 0, + {0, 0, (int32_t)bufferSideLength, (int32_t)bufferSideLength}, + /*border*/ 0, /*outsideRegion*/ true)); } class TestProducerListener : public BnProducerListener { @@ -598,6 +596,7 @@ TEST_F(BLASTBufferQueueTest, OutOfOrderTransactionTest) { t.setLayerStack(bgSurface, 0) .show(bgSurface) .setDataspace(bgSurface, ui::Dataspace::V0_SRGB) + .setFrame(bgSurface, Rect(0, 0, mDisplayWidth, mDisplayHeight)) .setLayer(bgSurface, std::numeric_limits::max() - 1) .apply(); @@ -620,8 +619,7 @@ TEST_F(BLASTBufferQueueTest, OutOfOrderTransactionTest) { ASSERT_EQ(NO_ERROR, captureDisplay(mCaptureArgs, mCaptureResults)); ASSERT_NO_FATAL_FAILURE( - checkScreenCapture(r, g, b, - {0, 0, (int32_t)mDisplayWidth, (int32_t)mDisplayHeight / 2})); + checkScreenCapture(r, g, b, {0, 0, (int32_t)mDisplayWidth, (int32_t)mDisplayHeight})); } class BLASTBufferQueueTransformTest : public BLASTBufferQueueTest { diff --git a/services/surfaceflinger/BufferStateLayer.cpp b/services/surfaceflinger/BufferStateLayer.cpp index 09e3cd969c..d6becbf213 100644 --- a/services/surfaceflinger/BufferStateLayer.cpp +++ b/services/surfaceflinger/BufferStateLayer.cpp @@ -278,8 +278,9 @@ bool BufferStateLayer::applyPendingStates(Layer::State* stateToCommit) { return stateUpdateAvailable; } -Rect BufferStateLayer::getCrop(const Layer::State& s) const { - return s.crop; +// Crop that applies to the window +Rect BufferStateLayer::getCrop(const Layer::State& /*s*/) const { + return Rect::INVALID_RECT; } bool BufferStateLayer::setTransform(uint32_t transform) { @@ -300,53 +301,57 @@ bool BufferStateLayer::setTransformToDisplayInverse(bool transformToDisplayInver } bool BufferStateLayer::setCrop(const Rect& crop) { - if (mCurrentState.crop == crop) return false; - mCurrentState.sequence++; - mCurrentState.crop = crop; + Rect c = crop; + if (c.left < 0) { + c.left = 0; + } + if (c.top < 0) { + c.top = 0; + } + // If the width and/or height are < 0, make it [0, 0, -1, -1] so the equality comparision below + // treats all invalid rectangles the same. + if (!c.isValid()) { + c.makeInvalid(); + } + if (mCurrentState.crop == c) return false; + mCurrentState.crop = c; mCurrentState.modified = true; setTransactionFlags(eTransactionNeeded); return true; } -bool BufferStateLayer::setMatrix(const layer_state_t::matrix22_t& matrix, - bool allowNonRectPreservingTransforms) { - if (mCurrentState.transform.dsdx() == matrix.dsdx && - mCurrentState.transform.dtdy() == matrix.dtdy && - mCurrentState.transform.dtdx() == matrix.dtdx && - mCurrentState.transform.dsdy() == matrix.dsdy) { - return false; - } +bool BufferStateLayer::setFrame(const Rect& frame) { + int x = frame.left; + int y = frame.top; + int w = frame.getWidth(); + int h = frame.getHeight(); - ui::Transform t; - t.set(matrix.dsdx, matrix.dtdy, matrix.dtdx, matrix.dsdy); - - if (!allowNonRectPreservingTransforms && !t.preserveRects()) { - ALOGW("Attempt to set rotation matrix without permission ACCESS_SURFACE_FLINGER nor " - "ROTATE_SURFACE_FLINGER ignored"); - return false; + if (x < 0) { + x = 0; + w = frame.right; } - mCurrentState.transform.set(matrix.dsdx, matrix.dtdy, matrix.dtdx, matrix.dsdy); - - mCurrentState.sequence++; - mCurrentState.modified = true; - setTransactionFlags(eTransactionNeeded); - - return true; -} + if (y < 0) { + y = 0; + h = frame.bottom; + } -bool BufferStateLayer::setPosition(float x, float y) { - if (mCurrentState.transform.tx() == x && mCurrentState.transform.ty() == y) { + if (mCurrentState.transform.tx() == x && mCurrentState.transform.ty() == y && + mCurrentState.width == w && mCurrentState.height == h) { return false; } + if (!frame.isValid()) { + x = y = w = h = 0; + } mCurrentState.transform.set(x, y); + mCurrentState.width = w; + mCurrentState.height = h; mCurrentState.sequence++; mCurrentState.modified = true; setTransactionFlags(eTransactionNeeded); - return true; } @@ -423,10 +428,6 @@ bool BufferStateLayer::setBuffer(const sp& buffer, const spmFrameTracer->traceTimestamp(layerId, bufferId, frameNumber, postTime, FrameTracer::FrameEvent::QUEUE); } - - mCurrentState.width = mCurrentState.buffer->width; - mCurrentState.height = mCurrentState.buffer->height; - return true; } @@ -857,6 +858,33 @@ sp BufferStateLayer::createClone() { return layer; } +Layer::RoundedCornerState BufferStateLayer::getRoundedCornerState() const { + const auto& p = mDrawingParent.promote(); + if (p != nullptr) { + RoundedCornerState parentState = p->getRoundedCornerState(); + if (parentState.radius > 0) { + ui::Transform t = getActiveTransform(getDrawingState()); + t = t.inverse(); + parentState.cropRect = t.transform(parentState.cropRect); + // The rounded corners shader only accepts 1 corner radius for performance reasons, + // but a transform matrix can define horizontal and vertical scales. + // Let's take the average between both of them and pass into the shader, practically we + // never do this type of transformation on windows anyway. + parentState.radius *= (t[0][0] + t[1][1]) / 2.0f; + return parentState; + } + } + const float radius = getDrawingState().cornerRadius; + const State& s(getDrawingState()); + if (radius <= 0 || (getActiveWidth(s) == UINT32_MAX && getActiveHeight(s) == UINT32_MAX)) + return RoundedCornerState(); + return RoundedCornerState(FloatRect(static_cast(s.transform.tx()), + static_cast(s.transform.ty()), + static_cast(s.transform.tx() + s.width), + static_cast(s.transform.ty() + s.height)), + radius); +} + bool BufferStateLayer::bufferNeedsFiltering() const { const State& s(getDrawingState()); if (!s.buffer) { diff --git a/services/surfaceflinger/BufferStateLayer.h b/services/surfaceflinger/BufferStateLayer.h index af2819eac7..7a3da6fec1 100644 --- a/services/surfaceflinger/BufferStateLayer.h +++ b/services/surfaceflinger/BufferStateLayer.h @@ -66,6 +66,7 @@ public: bool setTransform(uint32_t transform) override; bool setTransformToDisplayInverse(bool transformToDisplayInverse) override; bool setCrop(const Rect& crop) override; + bool setFrame(const Rect& frame) override; bool setBuffer(const sp& buffer, const sp& acquireFence, nsecs_t postTime, nsecs_t desiredPresentTime, bool isAutoTimestamp, const client_cache_t& clientCacheId, uint64_t frameNumber, @@ -80,13 +81,15 @@ public: bool setTransactionCompletedListeners(const std::vector>& handles) override; bool addFrameEvent(const sp& acquireFence, nsecs_t postedTime, nsecs_t requestedPresentTime) override; - bool setPosition(float /*x*/, float /*y*/) override; - bool setMatrix(const layer_state_t::matrix22_t& /*matrix*/, - bool /*allowNonRectPreservingTransforms*/); // 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*/) override { return false; } bool setTransparentRegionHint(const Region& transparent) override; + bool setMatrix(const layer_state_t::matrix22_t& /*matrix*/, + bool /*allowNonRectPreservingTransforms*/) override { + return false; + } void deferTransactionUntil_legacy(const sp& /*barrierHandle*/, uint64_t /*frameNumber*/) override {} void deferTransactionUntil_legacy(const sp& /*barrierLayer*/, @@ -94,6 +97,7 @@ public: Rect getBufferSize(const State& s) const override; FloatRect computeSourceBounds(const FloatRect& parentBounds) const override; + Layer::RoundedCornerState getRoundedCornerState() const override; void setAutoRefresh(bool autoRefresh) override; // ----------------------------------------------------------------------- diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp index 2fcd8215eb..dbd6b32656 100644 --- a/services/surfaceflinger/Layer.cpp +++ b/services/surfaceflinger/Layer.cpp @@ -2313,8 +2313,8 @@ Layer::RoundedCornerState Layer::getRoundedCornerState() const { } } const float radius = getDrawingState().cornerRadius; - return radius > 0 && getCroppedBufferSize(getDrawingState()).isValid() - ? RoundedCornerState(getCroppedBufferSize(getDrawingState()).toFloatRect(), radius) + return radius > 0 && getCrop(getDrawingState()).isValid() + ? RoundedCornerState(getCrop(getDrawingState()).toFloatRect(), radius) : RoundedCornerState(); } diff --git a/services/surfaceflinger/Layer.h b/services/surfaceflinger/Layer.h index 4a105ebeda..aafe41cea0 100644 --- a/services/surfaceflinger/Layer.h +++ b/services/surfaceflinger/Layer.h @@ -412,6 +412,7 @@ public: // Used only to set BufferStateLayer state virtual bool setTransform(uint32_t /*transform*/) { return false; }; virtual bool setTransformToDisplayInverse(bool /*transformToDisplayInverse*/) { return false; }; + virtual bool setFrame(const Rect& /*frame*/) { return false; }; virtual bool setBuffer(const sp& /*buffer*/, const sp& /*acquireFence*/, nsecs_t /*postTime*/, nsecs_t /*desiredPresentTime*/, bool /*isAutoTimestamp*/, const client_cache_t& /*clientCacheId*/, diff --git a/services/surfaceflinger/RefreshRateOverlay.cpp b/services/surfaceflinger/RefreshRateOverlay.cpp index 7a3e433660..1d00cc38f2 100644 --- a/services/surfaceflinger/RefreshRateOverlay.cpp +++ b/services/surfaceflinger/RefreshRateOverlay.cpp @@ -231,14 +231,8 @@ const std::vector>& RefreshRateOverlay::getOrCreateBuffers(uin void RefreshRateOverlay::setViewport(ui::Size viewport) { Rect frame((3 * viewport.width) >> 4, viewport.height >> 5); frame.offsetBy(viewport.width >> 5, viewport.height >> 4); + mLayer->setFrame(frame); - layer_state_t::matrix22_t matrix; - matrix.dsdx = frame.getWidth() / static_cast(SevenSegmentDrawer::getWidth()); - matrix.dtdx = 0; - matrix.dtdy = 0; - matrix.dsdy = frame.getHeight() / static_cast(SevenSegmentDrawer::getHeight()); - mLayer->setMatrix(matrix, true); - mLayer->setPosition(frame.left, frame.top); mFlinger.mTransactionFlags.fetch_or(eTransactionMask); } diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp index b33eca94d5..e72fad07dc 100644 --- a/services/surfaceflinger/SurfaceFlinger.cpp +++ b/services/surfaceflinger/SurfaceFlinger.cpp @@ -4038,6 +4038,9 @@ uint32_t SurfaceFlinger::setClientStateLocked( if (what & layer_state_t::eCropChanged) { if (layer->setCrop(s.crop)) flags |= eTraversalNeeded; } + if (what & layer_state_t::eFrameChanged) { + if (layer->setFrame(s.orientedDisplaySpaceRect)) flags |= eTraversalNeeded; + } if (what & layer_state_t::eAcquireFenceChanged) { if (layer->setAcquireFence(s.acquireFence)) flags |= eTraversalNeeded; } diff --git a/services/surfaceflinger/tests/BufferGenerator.cpp b/services/surfaceflinger/tests/BufferGenerator.cpp index 47a150dd35..03f8e1afba 100644 --- a/services/surfaceflinger/tests/BufferGenerator.cpp +++ b/services/surfaceflinger/tests/BufferGenerator.cpp @@ -296,12 +296,12 @@ private: BufferGenerator::BufferGenerator() : mSurfaceManager(new SurfaceManager), mEglManager(new EglManager), mProgram(new Program) { - mBufferSize.set(1000.0, 1000.0); + const float width = 1000.0; + const float height = 1000.0; auto setBufferWithContext = std::bind(setBuffer, std::placeholders::_1, std::placeholders::_2, this); - mSurfaceManager->initialize(mBufferSize.width, mBufferSize.height, HAL_PIXEL_FORMAT_RGBA_8888, - setBufferWithContext); + mSurfaceManager->initialize(width, height, HAL_PIXEL_FORMAT_RGBA_8888, setBufferWithContext); if (!mEglManager->initialize(mSurfaceManager->getSurface())) return; @@ -309,9 +309,7 @@ BufferGenerator::BufferGenerator() if (!mProgram->initialize(VERTEX_SHADER, FRAGMENT_SHADER)) return; mProgram->use(); - mProgram->bindVec4(0, - vec4{mBufferSize.width, mBufferSize.height, 1.0f / mBufferSize.width, - 1.0f / mBufferSize.height}); + mProgram->bindVec4(0, vec4{width, height, 1.0f / width, 1.0f / height}); mProgram->bindVec3(2, &SPHERICAL_HARMONICS[0], 4); glEnableVertexAttribArray(0); @@ -374,10 +372,6 @@ status_t BufferGenerator::get(sp* outBuffer, sp* outFence) return NO_ERROR; } -ui::Size BufferGenerator::getSize() { - return mBufferSize; -} - // static void BufferGenerator::setBuffer(const sp& buffer, int32_t fence, void* bufferGenerator) { diff --git a/services/surfaceflinger/tests/BufferGenerator.h b/services/surfaceflinger/tests/BufferGenerator.h index f7d548b6bf..a3ffe86572 100644 --- a/services/surfaceflinger/tests/BufferGenerator.h +++ b/services/surfaceflinger/tests/BufferGenerator.h @@ -37,7 +37,6 @@ public: /* Static callback that sets the fence on a particular instance */ static void setBuffer(const sp& buffer, int32_t fence, void* fenceGenerator); - ui::Size getSize(); private: bool mInitialized = false; @@ -54,7 +53,6 @@ private: using Epoch = std::chrono::time_point; Epoch mEpoch = std::chrono::steady_clock::now(); - ui::Size mBufferSize; }; } // namespace android diff --git a/services/surfaceflinger/tests/EffectLayer_test.cpp b/services/surfaceflinger/tests/EffectLayer_test.cpp index af00ec7fc9..f470eda7d3 100644 --- a/services/surfaceflinger/tests/EffectLayer_test.cpp +++ b/services/surfaceflinger/tests/EffectLayer_test.cpp @@ -149,6 +149,7 @@ TEST_F(EffectLayerTest, BlurEffectLayerIsVisible) { t.reparent(blurLayer, mParentLayer); t.setBackgroundBlurRadius(blurLayer, blurRadius); t.setCrop(blurLayer, blurRect); + t.setFrame(blurLayer, blurRect); t.setAlpha(blurLayer, 0.0f); t.show(blurLayer); }); diff --git a/services/surfaceflinger/tests/IPC_test.cpp b/services/surfaceflinger/tests/IPC_test.cpp index 9fa3d4c417..a8647c3e50 100644 --- a/services/surfaceflinger/tests/IPC_test.cpp +++ b/services/surfaceflinger/tests/IPC_test.cpp @@ -161,6 +161,7 @@ public: Color::RED); transaction->setLayerStack(mSurfaceControl, 0) .setLayer(mSurfaceControl, std::numeric_limits::max()) + .setFrame(mSurfaceControl, Rect(0, 0, width, height)) .setBuffer(mSurfaceControl, gb) .setAcquireFence(mSurfaceControl, fence) .show(mSurfaceControl) diff --git a/services/surfaceflinger/tests/LayerCallback_test.cpp b/services/surfaceflinger/tests/LayerCallback_test.cpp index 011ff70409..158801a705 100644 --- a/services/surfaceflinger/tests/LayerCallback_test.cpp +++ b/services/surfaceflinger/tests/LayerCallback_test.cpp @@ -164,10 +164,7 @@ TEST_F(LayerCallbackTest, NoBufferNoColor) { return; } - ui::Size bufferSize = getBufferSize(); - TransactionUtils::setFrame(transaction, layer, Rect(0, 0, bufferSize.width, bufferSize.height), - Rect(0, 0, 32, 32)); - transaction.apply(); + transaction.setFrame(layer, Rect(0, 0, 32, 32)).apply(); ExpectedResult expected; expected.addSurface(ExpectedResult::Transaction::NOT_PRESENTED, layer, @@ -187,10 +184,7 @@ TEST_F(LayerCallbackTest, BufferNoColor) { return; } - ui::Size bufferSize = getBufferSize(); - TransactionUtils::setFrame(transaction, layer, Rect(0, 0, bufferSize.width, bufferSize.height), - Rect(0, 0, 32, 32)); - transaction.apply(); + transaction.setFrame(layer, Rect(0, 0, 32, 32)).apply(); ExpectedResult expected; expected.addSurface(ExpectedResult::Transaction::PRESENTED, layer); @@ -209,10 +203,7 @@ TEST_F(LayerCallbackTest, NoBufferColor) { return; } - ui::Size bufferSize = getBufferSize(); - TransactionUtils::setFrame(transaction, layer, Rect(0, 0, bufferSize.width, bufferSize.height), - Rect(0, 0, 32, 32)); - transaction.apply(); + transaction.setFrame(layer, Rect(0, 0, 32, 32)).apply(); ExpectedResult expected; expected.addSurface(ExpectedResult::Transaction::PRESENTED, layer, @@ -247,10 +238,7 @@ TEST_F(LayerCallbackTest, OffScreen) { return; } - ui::Size bufferSize = getBufferSize(); - TransactionUtils::setFrame(transaction, layer, Rect(0, 0, bufferSize.width, bufferSize.height), - Rect(-100, -100, 100, 100)); - transaction.apply(); + transaction.setFrame(layer, Rect(-100, -100, 100, 100)).apply(); ExpectedResult expected; expected.addSurface(ExpectedResult::Transaction::PRESENTED, layer); @@ -275,15 +263,8 @@ TEST_F(LayerCallbackTest, MergeBufferNoColor) { return; } - ui::Size bufferSize = getBufferSize(); - - TransactionUtils::setFrame(transaction1, layer1, - Rect(0, 0, bufferSize.width, bufferSize.height), Rect(0, 0, 32, 32)); - TransactionUtils::setFrame(transaction2, layer2, - Rect(0, 0, bufferSize.width, bufferSize.height), - Rect(32, 32, 64, 64)); - - transaction2.merge(std::move(transaction1)).apply(); + transaction1.setFrame(layer1, Rect(0, 0, 32, 32)); + transaction2.setFrame(layer2, Rect(32, 32, 64, 64)).merge(std::move(transaction1)).apply(); ExpectedResult expected; expected.addSurfaces(ExpectedResult::Transaction::PRESENTED, {layer1, layer2}); @@ -309,15 +290,8 @@ TEST_F(LayerCallbackTest, MergeNoBufferColor) { return; } - ui::Size bufferSize = getBufferSize(); - - TransactionUtils::setFrame(transaction1, layer1, - Rect(0, 0, bufferSize.width, bufferSize.height), Rect(0, 0, 32, 32)); - TransactionUtils::setFrame(transaction2, layer2, - Rect(0, 0, bufferSize.width, bufferSize.height), - Rect(32, 32, 64, 64)); - - transaction2.merge(std::move(transaction1)).apply(); + transaction1.setFrame(layer1, Rect(0, 0, 32, 32)); + transaction2.setFrame(layer2, Rect(32, 32, 64, 64)).merge(std::move(transaction1)).apply(); ExpectedResult expected; expected.addSurfaces(ExpectedResult::Transaction::PRESENTED, {layer1, layer2}, @@ -344,15 +318,8 @@ TEST_F(LayerCallbackTest, MergeOneBufferOneColor) { return; } - ui::Size bufferSize = getBufferSize(); - - TransactionUtils::setFrame(transaction1, layer1, - Rect(0, 0, bufferSize.width, bufferSize.height), Rect(0, 0, 32, 32)); - TransactionUtils::setFrame(transaction2, layer2, - Rect(0, 0, bufferSize.width, bufferSize.height), - Rect(32, 32, 64, 64)); - - transaction2.merge(std::move(transaction1)).apply(); + transaction1.setFrame(layer1, Rect(0, 0, 32, 32)); + transaction2.setFrame(layer2, Rect(32, 32, 64, 64)).merge(std::move(transaction1)).apply(); ExpectedResult expected; expected.addSurface(ExpectedResult::Transaction::PRESENTED, layer1); @@ -438,15 +405,8 @@ TEST_F(LayerCallbackTest, Merge_DifferentClients) { return; } - ui::Size bufferSize = getBufferSize(); - - TransactionUtils::setFrame(transaction1, layer1, - Rect(0, 0, bufferSize.width, bufferSize.height), Rect(0, 0, 32, 32)); - TransactionUtils::setFrame(transaction2, layer2, - Rect(0, 0, bufferSize.width, bufferSize.height), - Rect(32, 32, 64, 64)); - - transaction2.merge(std::move(transaction1)).apply(); + transaction1.setFrame(layer1, Rect(0, 0, 32, 32)); + transaction2.setFrame(layer2, Rect(32, 32, 64, 64)).merge(std::move(transaction1)).apply(); ExpectedResult expected; expected.addSurfaces(ExpectedResult::Transaction::PRESENTED, {layer1, layer2}); @@ -531,11 +491,7 @@ TEST_F(LayerCallbackTest, MultipleTransactions_SameStateChange) { } } - ui::Size bufferSize = getBufferSize(); - TransactionUtils::setFrame(transaction, layer, - Rect(0, 0, bufferSize.width, bufferSize.height), - Rect(0, 0, 32, 32)); - transaction.apply(); + transaction.setFrame(layer, Rect(0, 0, 32, 32)).apply(); ExpectedResult expected; expected.addSurface((i == 0) ? ExpectedResult::Transaction::PRESENTED @@ -567,16 +523,8 @@ TEST_F(LayerCallbackTest, MultipleTransactions_Merge) { return; } - ui::Size bufferSize = getBufferSize(); - - TransactionUtils::setFrame(transaction1, layer1, - Rect(0, 0, bufferSize.width, bufferSize.height), - Rect(0, 0, 32, 32)); - TransactionUtils::setFrame(transaction2, layer2, - Rect(0, 0, bufferSize.width, bufferSize.height), - Rect(32, 32, 64, 64)); - - transaction2.merge(std::move(transaction1)).apply(); + transaction1.setFrame(layer1, Rect(0, 0, 32, 32)); + transaction2.setFrame(layer2, Rect(32, 32, 64, 64)).merge(std::move(transaction1)).apply(); ExpectedResult expected; expected.addSurfaces(ExpectedResult::Transaction::PRESENTED, {layer1, layer2}, @@ -616,16 +564,8 @@ TEST_F(LayerCallbackTest, MultipleTransactions_Merge_DifferentClients) { return; } - ui::Size bufferSize = getBufferSize(); - - TransactionUtils::setFrame(transaction1, layer1, - Rect(0, 0, bufferSize.width, bufferSize.height), - Rect(0, 0, 32, 32)); - TransactionUtils::setFrame(transaction2, layer2, - Rect(0, 0, bufferSize.width, bufferSize.height), - Rect(32, 32, 64, 64)); - - transaction2.merge(std::move(transaction1)).apply(); + transaction1.setFrame(layer1, Rect(0, 0, 32, 32)); + transaction2.setFrame(layer2, Rect(32, 32, 64, 64)).merge(std::move(transaction1)).apply(); ExpectedResult expected; expected.addSurfaces(ExpectedResult::Transaction::PRESENTED, {layer1, layer2}, @@ -666,15 +606,8 @@ TEST_F(LayerCallbackTest, MultipleTransactions_Merge_DifferentClients_NoStateCha return; } - ui::Size bufferSize = getBufferSize(); - - TransactionUtils::setFrame(transaction1, layer1, - Rect(0, 0, bufferSize.width, bufferSize.height), Rect(0, 0, 32, 32)); - TransactionUtils::setFrame(transaction2, layer2, - Rect(0, 0, bufferSize.width, bufferSize.height), - Rect(32, 32, 64, 64)); - - transaction2.merge(std::move(transaction1)).apply(); + transaction1.setFrame(layer1, Rect(0, 0, 32, 32)); + transaction2.setFrame(layer2, Rect(32, 32, 64, 64)).merge(std::move(transaction1)).apply(); ExpectedResult expected; expected.addSurfaces(ExpectedResult::Transaction::PRESENTED, {layer1, layer2}); @@ -728,15 +661,8 @@ TEST_F(LayerCallbackTest, MultipleTransactions_Merge_DifferentClients_SameStateC return; } - ui::Size bufferSize = getBufferSize(); - - TransactionUtils::setFrame(transaction1, layer1, - Rect(0, 0, bufferSize.width, bufferSize.height), Rect(0, 0, 32, 32)); - TransactionUtils::setFrame(transaction2, layer2, - Rect(0, 0, bufferSize.width, bufferSize.height), - Rect(32, 32, 64, 64)); - - transaction2.merge(std::move(transaction1)).apply(); + transaction1.setFrame(layer1, Rect(0, 0, 32, 32)); + transaction2.setFrame(layer2, Rect(32, 32, 64, 64)).merge(std::move(transaction1)).apply(); ExpectedResult expected; expected.addSurfaces(ExpectedResult::Transaction::PRESENTED, {layer1, layer2}); @@ -756,10 +682,7 @@ TEST_F(LayerCallbackTest, MultipleTransactions_Merge_DifferentClients_SameStateC return; } - TransactionUtils::setFrame(transaction2, layer2, - Rect(0, 0, bufferSize.width, bufferSize.height), - Rect(32, 32, 64, 64)); - transaction2.merge(std::move(transaction1)).apply(); + transaction2.setFrame(layer2, Rect(32, 32, 64, 64)).merge(std::move(transaction1)).apply(); expected.addSurface(ExpectedResult::Transaction::NOT_PRESENTED, layer2, ExpectedResult::Buffer::NOT_ACQUIRED); @@ -839,10 +762,7 @@ TEST_F(LayerCallbackTest, MultipleTransactions_SingleFrame_SameStateChange) { return; } - ui::Size bufferSize = getBufferSize(); - TransactionUtils::setFrame(transaction, layer, Rect(0, 0, bufferSize.width, bufferSize.height), - Rect(0, 0, 32, 32)); - transaction.apply(); + transaction.setFrame(layer, Rect(0, 0, 32, 32)).apply(); ExpectedResult expectedResult; expectedResult.addSurface(ExpectedResult::Transaction::PRESENTED, layer); @@ -861,10 +781,7 @@ TEST_F(LayerCallbackTest, MultipleTransactions_SingleFrame_SameStateChange) { return; } - TransactionUtils::setFrame(transaction, layer, - Rect(0, 0, bufferSize.width, bufferSize.height), - Rect(0, 0, 32, 32)); - transaction.apply(); + transaction.setFrame(layer, Rect(0, 0, 32, 32)).apply(); } EXPECT_NO_FATAL_FAILURE(waitForCallbacks(callback, expectedResults, true)); } diff --git a/services/surfaceflinger/tests/LayerRenderTypeTransaction_test.cpp b/services/surfaceflinger/tests/LayerRenderTypeTransaction_test.cpp index 53d230abe7..7505e6ea9b 100644 --- a/services/surfaceflinger/tests/LayerRenderTypeTransaction_test.cpp +++ b/services/surfaceflinger/tests/LayerRenderTypeTransaction_test.cpp @@ -204,7 +204,11 @@ void LayerRenderTypeTransactionTest::setRelativeZBasicHelper(uint32_t layerType) Transaction().setPosition(layerG, 16, 16).setRelativeLayer(layerG, layerR, 1).apply(); break; case ISurfaceComposerClient::eFXSurfaceBufferState: - Transaction().setPosition(layerG, 16, 16).setRelativeLayer(layerG, layerR, 1).apply(); + Transaction() + .setFrame(layerR, Rect(0, 0, 32, 32)) + .setFrame(layerG, Rect(16, 16, 48, 48)) + .setRelativeLayer(layerG, layerR, 1) + .apply(); break; default: ASSERT_FALSE(true) << "Unsupported layer type"; @@ -256,9 +260,10 @@ void LayerRenderTypeTransactionTest::setRelativeZGroupHelper(uint32_t layerType) break; case ISurfaceComposerClient::eFXSurfaceBufferState: Transaction() - .setPosition(layerG, 8, 8) + .setFrame(layerR, Rect(0, 0, 32, 32)) + .setFrame(layerG, Rect(8, 8, 40, 40)) .setRelativeLayer(layerG, layerR, 3) - .setPosition(layerB, 16, 16) + .setFrame(layerB, Rect(16, 16, 48, 48)) .setLayer(layerB, mLayerZBase + 2) .apply(); break; @@ -383,6 +388,7 @@ TEST_P(LayerRenderTypeTransactionTest, SetTransparentRegionHintBasic_BufferState Transaction() .setTransparentRegionHint(layer, Region(top)) .setBuffer(layer, buffer) + .setFrame(layer, Rect(0, 0, 32, 32)) .apply(); { SCOPED_TRACE("top transparent"); @@ -441,7 +447,7 @@ TEST_P(LayerRenderTypeTransactionTest, SetTransparentRegionHintOutOfBounds_Buffe // check that transparent region hint is bound by the layer size Transaction() .setTransparentRegionHint(layerTransparent, Region(mDisplayRect)) - .setPosition(layerR, 16, 16) + .setFrame(layerR, Rect(16, 16, 48, 48)) .setLayer(layerR, mLayerZBase + 1) .apply(); ASSERT_NO_FATAL_FAILURE( @@ -471,7 +477,8 @@ void LayerRenderTypeTransactionTest::setAlphaBasicHelper(uint32_t layerType) { Transaction() .setAlpha(layer1, 0.25f) .setAlpha(layer2, 0.75f) - .setPosition(layer2, 16, 0) + .setFrame(layer1, Rect(0, 0, 32, 32)) + .setFrame(layer2, Rect(16, 0, 48, 32)) .setLayer(layer2, mLayerZBase + 1) .apply(); break; @@ -566,7 +573,7 @@ void LayerRenderTypeTransactionTest::setBackgroundColorHelper(uint32_t layerType ASSERT_NO_FATAL_FAILURE(fillBufferStateLayerColor(layer, fillColor, width, height)); expectedColor = fillColor; } - Transaction().setCrop(layer, Rect(0, 0, width, height)).apply(); + Transaction().setFrame(layer, Rect(0, 0, width, height)).apply(); break; default: GTEST_FAIL() << "Unknown layer type in setBackgroundColorHelper"; @@ -842,39 +849,42 @@ TEST_P(LayerRenderTypeTransactionTest, SetMatrixBasic_BufferState) { ASSERT_NO_FATAL_FAILURE(fillBufferStateLayerQuadrant(layer, 32, 32, Color::RED, Color::GREEN, Color::BLUE, Color::WHITE)); - Transaction().setPosition(layer, 32, 32).setMatrix(layer, 1.0f, 0.0f, 0.0f, 1.0f).apply(); + Transaction() + .setMatrix(layer, 1.0f, 0.0f, 0.0f, 1.0f) + .setFrame(layer, Rect(0, 0, 32, 32)) + .apply(); { SCOPED_TRACE("IDENTITY"); - getScreenCapture()->expectQuadrant(Rect(32, 32, 64, 64), Color::RED, Color::GREEN, + getScreenCapture()->expectQuadrant(Rect(0, 0, 32, 32), Color::RED, Color::GREEN, Color::BLUE, Color::WHITE); } Transaction().setMatrix(layer, -1.0f, 0.0f, 0.0f, 1.0f).apply(); { SCOPED_TRACE("FLIP_H"); - getScreenCapture()->expectQuadrant(Rect(0, 32, 32, 64), Color::GREEN, Color::RED, - Color::WHITE, Color::BLUE); + getScreenCapture()->expectQuadrant(Rect(0, 0, 32, 32), Color::RED, Color::GREEN, + Color::BLUE, Color::WHITE); } Transaction().setMatrix(layer, 1.0f, 0.0f, 0.0f, -1.0f).apply(); { SCOPED_TRACE("FLIP_V"); - getScreenCapture()->expectQuadrant(Rect(32, 0, 64, 32), Color::BLUE, Color::WHITE, - Color::RED, Color::GREEN); + getScreenCapture()->expectQuadrant(Rect(0, 0, 32, 32), Color::RED, Color::GREEN, + Color::BLUE, Color::WHITE); } Transaction().setMatrix(layer, 0.0f, 1.0f, -1.0f, 0.0f).apply(); { SCOPED_TRACE("ROT_90"); - getScreenCapture()->expectQuadrant(Rect(0, 32, 32, 64), Color::BLUE, Color::RED, - Color::WHITE, Color::GREEN); + getScreenCapture()->expectQuadrant(Rect(0, 0, 32, 32), Color::RED, Color::GREEN, + Color::BLUE, Color::WHITE); } Transaction().setMatrix(layer, 2.0f, 0.0f, 0.0f, 2.0f).apply(); { SCOPED_TRACE("SCALE"); - getScreenCapture()->expectQuadrant(Rect(32, 32, 96, 96), Color::RED, Color::GREEN, - Color::BLUE, Color::WHITE, 1 /* tolerance */); + getScreenCapture()->expectQuadrant(Rect(0, 0, 32, 32), Color::RED, Color::GREEN, + Color::BLUE, Color::WHITE); } } @@ -945,8 +955,8 @@ TEST_P(LayerRenderTypeTransactionTest, SetCropBasic_BufferState) { Transaction().setCrop(layer, crop).apply(); auto shot = getScreenCapture(); - shot->expectColor(crop, Color::RED); - shot->expectBorder(crop, Color::BLACK); + shot->expectColor(Rect(0, 0, mDisplayWidth, mDisplayHeight), Color::RED); + shot->expectBorder(Rect(0, 0, mDisplayWidth, mDisplayHeight), Color::BLACK); } TEST_P(LayerRenderTypeTransactionTest, SetCropEmpty_BufferQueue) { @@ -976,13 +986,13 @@ TEST_P(LayerRenderTypeTransactionTest, SetCropEmpty_BufferState) { { SCOPED_TRACE("empty rect"); Transaction().setCrop(layer, Rect(8, 8, 8, 8)).apply(); - getScreenCapture()->expectColor(Rect(0, 0, 32, 32), Color::RED); + getScreenCapture()->expectColor(Rect(0, 0, mDisplayWidth, mDisplayHeight), Color::RED); } { SCOPED_TRACE("negative rect"); Transaction().setCrop(layer, Rect(8, 8, 0, 0)).apply(); - getScreenCapture()->expectColor(Rect(0, 0, 32, 32), Color::RED); + getScreenCapture()->expectColor(Rect(0, 0, mDisplayWidth, mDisplayHeight), Color::RED); } } @@ -1006,6 +1016,8 @@ TEST_P(LayerRenderTypeTransactionTest, SetCropOutOfBounds_BufferState) { TransactionUtils::fillGraphicBufferColor(buffer, Rect(0, 0, 32, 16), Color::BLUE); TransactionUtils::fillGraphicBufferColor(buffer, Rect(0, 16, 32, 64), Color::RED); + Transaction().setFrame(layer, Rect(0, 0, 64, 64)).apply(); + Transaction().setBuffer(layer, buffer).apply(); // Partially out of bounds in the negative (upper left) direction @@ -1013,8 +1025,8 @@ TEST_P(LayerRenderTypeTransactionTest, SetCropOutOfBounds_BufferState) { { SCOPED_TRACE("out of bounds, negative (upper left) direction"); auto shot = getScreenCapture(); - shot->expectColor(Rect(0, 0, 32, 16), Color::BLUE); - shot->expectBorder(Rect(0, 0, 32, 16), Color::BLACK); + shot->expectColor(Rect(0, 0, 64, 64), Color::BLUE); + shot->expectBorder(Rect(0, 0, 64, 64), Color::BLACK); } // Partially out of bounds in the positive (lower right) direction @@ -1022,8 +1034,8 @@ TEST_P(LayerRenderTypeTransactionTest, SetCropOutOfBounds_BufferState) { { SCOPED_TRACE("out of bounds, positive (lower right) direction"); auto shot = getScreenCapture(); - shot->expectColor(Rect(0, 16, 32, 64), Color::RED); - shot->expectBorder(Rect(0, 16, 32, 64), Color::BLACK); + shot->expectColor(Rect(0, 0, 64, 64), Color::RED); + shot->expectBorder(Rect(0, 0, 64, 64), Color::BLACK); } // Fully out of buffer space bounds @@ -1031,7 +1043,9 @@ TEST_P(LayerRenderTypeTransactionTest, SetCropOutOfBounds_BufferState) { { SCOPED_TRACE("Fully out of bounds"); auto shot = getScreenCapture(); - shot->expectColor(Rect(0, 0, 64, 64), Color::BLACK); + shot->expectColor(Rect(0, 0, 64, 16), Color::BLUE); + shot->expectColor(Rect(0, 16, 64, 64), Color::RED); + shot->expectBorder(Rect(0, 0, 64, 64), Color::BLACK); } } @@ -1054,11 +1068,12 @@ TEST_P(LayerRenderTypeTransactionTest, SetCropWithTranslation_BufferState) { layer = createLayer("test", 32, 32, ISurfaceComposerClient::eFXSurfaceBufferState)); ASSERT_NO_FATAL_FAILURE(fillBufferStateLayerColor(layer, Color::RED, 32, 32)); + const Rect frame(32, 32, 64, 64); const Rect crop(8, 8, 24, 24); - Transaction().setPosition(layer, 32, 32).setCrop(layer, crop).apply(); + Transaction().setFrame(layer, frame).setCrop(layer, crop).apply(); auto shot = getScreenCapture(); - shot->expectColor(Rect(40, 40, 56, 56), Color::RED); - shot->expectBorder(Rect(40, 40, 56, 56), Color::BLACK); + shot->expectColor(frame, Color::RED); + shot->expectBorder(frame, Color::BLACK); } TEST_P(LayerRenderTypeTransactionTest, SetCropWithScale_BufferQueue) { @@ -1106,10 +1121,7 @@ TEST_P(LayerRenderTypeTransactionTest, SetFrameBasic_BufferState) { ASSERT_NO_FATAL_FAILURE(fillBufferStateLayerColor(layer, Color::RED, 32, 32)); const Rect frame(8, 8, 24, 24); - Transaction t; - TransactionUtils::setFrame(t, layer, Rect(0, 0, 32, 32), frame); - t.apply(); - + Transaction().setFrame(layer, frame).apply(); auto shot = getScreenCapture(); shot->expectColor(frame, Color::RED); shot->expectBorder(frame, Color::BLACK); @@ -1121,23 +1133,16 @@ TEST_P(LayerRenderTypeTransactionTest, SetFrameEmpty_BufferState) { layer = createLayer("test", 32, 32, ISurfaceComposerClient::eFXSurfaceBufferState)); ASSERT_NO_FATAL_FAILURE(fillBufferStateLayerColor(layer, Color::RED, 32, 32)); - Transaction t; { SCOPED_TRACE("empty rect"); - TransactionUtils::setFrame(t, layer, Rect(0, 0, 32, 32), Rect(8, 8, 8, 8)); - t.apply(); - + Transaction().setFrame(layer, Rect(8, 8, 8, 8)).apply(); getScreenCapture()->expectColor(Rect(0, 0, 32, 32), Color::BLACK); } { SCOPED_TRACE("negative rect"); - TransactionUtils::setFrame(t, layer, Rect(0, 0, 32, 32), Rect(8, 8, 0, 0)); - t.apply(); - - auto shot = getScreenCapture(); - shot->expectColor(Rect(0, 0, 8, 8), Color::RED); - shot->expectBorder(Rect(0, 0, 8, 8), Color::BLACK); + Transaction().setFrame(layer, Rect(8, 8, 0, 0)).apply(); + getScreenCapture()->expectColor(Rect(0, 0, 32, 32), Color::BLACK); } } @@ -1147,10 +1152,10 @@ TEST_P(LayerRenderTypeTransactionTest, SetFrameDefaultParentless_BufferState) { layer = createLayer("test", 32, 32, ISurfaceComposerClient::eFXSurfaceBufferState)); ASSERT_NO_FATAL_FAILURE(fillBufferStateLayerColor(layer, Color::RED, 10, 10)); - // A layer with a buffer will have a computed size that matches the buffer size. + // A parentless layer will default to a frame with the same size as the buffer auto shot = getScreenCapture(); - shot->expectColor(Rect(0, 0, 10, 10), Color::RED); - shot->expectBorder(Rect(0, 0, 10, 10), Color::BLACK); + shot->expectColor(Rect(0, 0, mDisplayWidth, mDisplayHeight), Color::RED); + shot->expectBorder(Rect(0, 0, mDisplayWidth, mDisplayHeight), Color::BLACK); } TEST_P(LayerRenderTypeTransactionTest, SetFrameDefaultBSParent_BufferState) { @@ -1158,16 +1163,17 @@ TEST_P(LayerRenderTypeTransactionTest, SetFrameDefaultBSParent_BufferState) { ASSERT_NO_FATAL_FAILURE( parent = createLayer("test", 32, 32, ISurfaceComposerClient::eFXSurfaceBufferState)); ASSERT_NO_FATAL_FAILURE(fillBufferStateLayerColor(parent, Color::RED, 32, 32)); + Transaction().setFrame(parent, Rect(0, 0, 32, 32)).apply(); ASSERT_NO_FATAL_FAILURE( - child = createLayer("test", 10, 10, ISurfaceComposerClient::eFXSurfaceBufferState)); + child = createLayer("test", 32, 32, ISurfaceComposerClient::eFXSurfaceBufferState)); ASSERT_NO_FATAL_FAILURE(fillBufferStateLayerColor(child, Color::BLUE, 10, 10)); Transaction().reparent(child, parent).apply(); - // A layer with a buffer will have a computed size that matches the buffer size. + // A layer will default to the frame of its parent auto shot = getScreenCapture(); - shot->expectColor(Rect(0, 0, 10, 10), Color::BLUE); + shot->expectColor(Rect(0, 0, 32, 32), Color::BLUE); shot->expectBorder(Rect(0, 0, 32, 32), Color::BLACK); } @@ -1177,14 +1183,14 @@ TEST_P(LayerRenderTypeTransactionTest, SetFrameDefaultBQParent_BufferState) { ASSERT_NO_FATAL_FAILURE(fillBufferQueueLayerColor(parent, Color::RED, 32, 32)); ASSERT_NO_FATAL_FAILURE( - child = createLayer("test", 10, 10, ISurfaceComposerClient::eFXSurfaceBufferState)); + child = createLayer("test", 32, 32, ISurfaceComposerClient::eFXSurfaceBufferState)); ASSERT_NO_FATAL_FAILURE(fillBufferStateLayerColor(child, Color::BLUE, 10, 10)); Transaction().reparent(child, parent).apply(); - // A layer with a buffer will have a computed size that matches the buffer size. + // A layer will default to the frame of its parent auto shot = getScreenCapture(); - shot->expectColor(Rect(0, 0, 10, 10), Color::BLUE); + shot->expectColor(Rect(0, 0, 32, 32), Color::BLUE); shot->expectBorder(Rect(0, 0, 32, 32), Color::BLACK); } @@ -1193,10 +1199,11 @@ TEST_P(LayerRenderTypeTransactionTest, SetFrameUpdate_BufferState) { ASSERT_NO_FATAL_FAILURE( layer = createLayer("test", 32, 32, ISurfaceComposerClient::eFXSurfaceBufferState)); ASSERT_NO_FATAL_FAILURE(fillBufferStateLayerColor(layer, Color::RED, 32, 32)); + Transaction().setFrame(layer, Rect(0, 0, 32, 32)).apply(); std::this_thread::sleep_for(500ms); - Transaction().setPosition(layer, 16, 16).apply(); + Transaction().setFrame(layer, Rect(16, 16, 48, 48)).apply(); auto shot = getScreenCapture(); shot->expectColor(Rect(16, 16, 48, 48), Color::RED); @@ -1208,20 +1215,18 @@ TEST_P(LayerRenderTypeTransactionTest, SetFrameOutsideBounds_BufferState) { ASSERT_NO_FATAL_FAILURE( parent = createLayer("test", 32, 32, ISurfaceComposerClient::eFXSurfaceBufferState)); ASSERT_NO_FATAL_FAILURE( - child = createLayer("test", 10, 10, ISurfaceComposerClient::eFXSurfaceBufferState)); + child = createLayer("test", 32, 32, ISurfaceComposerClient::eFXSurfaceBufferState)); Transaction().reparent(child, parent).apply(); ASSERT_NO_FATAL_FAILURE(fillBufferStateLayerColor(parent, Color::RED, 32, 32)); + Transaction().setFrame(parent, Rect(0, 0, 32, 32)).apply(); ASSERT_NO_FATAL_FAILURE(fillBufferStateLayerColor(child, Color::BLUE, 10, 10)); - Rect childDst(0, 16, 32, 32); - Transaction t; - TransactionUtils::setFrame(t, child, Rect(0, 0, 10, 10), childDst); - t.apply(); + Transaction().setFrame(child, Rect(0, 16, 32, 32)).apply(); auto shot = getScreenCapture(); shot->expectColor(Rect(0, 0, 32, 16), Color::RED); - shot->expectColor(childDst, Color::BLUE); + shot->expectColor(Rect(0, 16, 32, 32), Color::BLUE); shot->expectBorder(Rect(0, 0, 32, 32), Color::BLACK); } @@ -1233,8 +1238,8 @@ TEST_P(LayerRenderTypeTransactionTest, SetBufferBasic_BufferState) { ASSERT_NO_FATAL_FAILURE(fillBufferStateLayerColor(layer, Color::RED, 32, 32)); auto shot = getScreenCapture(); - shot->expectColor(Rect(0, 0, 32, 32), Color::RED); - shot->expectBorder(Rect(0, 0, 32, 32), Color::BLACK); + shot->expectColor(Rect(0, 0, mDisplayWidth, mDisplayHeight), Color::RED); + shot->expectBorder(Rect(0, 0, mDisplayWidth, mDisplayHeight), Color::BLACK); } TEST_P(LayerRenderTypeTransactionTest, SetBufferMultipleBuffers_BufferState) { @@ -1247,8 +1252,8 @@ TEST_P(LayerRenderTypeTransactionTest, SetBufferMultipleBuffers_BufferState) { { SCOPED_TRACE("set buffer 1"); auto shot = getScreenCapture(); - shot->expectColor(Rect(0, 0, 32, 32), Color::RED); - shot->expectBorder(Rect(0, 0, 32, 32), Color::BLACK); + shot->expectColor(Rect(0, 0, mDisplayWidth, mDisplayHeight), Color::RED); + shot->expectBorder(Rect(0, 0, mDisplayWidth, mDisplayHeight), Color::BLACK); } ASSERT_NO_FATAL_FAILURE(fillBufferStateLayerColor(layer, Color::BLUE, 32, 32)); @@ -1256,8 +1261,8 @@ TEST_P(LayerRenderTypeTransactionTest, SetBufferMultipleBuffers_BufferState) { { SCOPED_TRACE("set buffer 2"); auto shot = getScreenCapture(); - shot->expectColor(Rect(0, 0, 32, 32), Color::BLUE); - shot->expectBorder(Rect(0, 0, 32, 32), Color::BLACK); + shot->expectColor(Rect(0, 0, mDisplayWidth, mDisplayHeight), Color::BLUE); + shot->expectBorder(Rect(0, 0, mDisplayWidth, mDisplayHeight), Color::BLACK); } ASSERT_NO_FATAL_FAILURE(fillBufferStateLayerColor(layer, Color::RED, 32, 32)); @@ -1265,8 +1270,8 @@ TEST_P(LayerRenderTypeTransactionTest, SetBufferMultipleBuffers_BufferState) { { SCOPED_TRACE("set buffer 3"); auto shot = getScreenCapture(); - shot->expectColor(Rect(0, 0, 32, 32), Color::RED); - shot->expectBorder(Rect(0, 0, 32, 32), Color::BLACK); + shot->expectColor(Rect(0, 0, mDisplayWidth, mDisplayHeight), Color::RED); + shot->expectBorder(Rect(0, 0, mDisplayWidth, mDisplayHeight), Color::BLACK); } } @@ -1281,6 +1286,7 @@ TEST_P(LayerRenderTypeTransactionTest, SetBufferMultipleLayers_BufferState) { ASSERT_NO_FATAL_FAILURE(fillBufferStateLayerColor(layer1, Color::RED, 64, 64)); + Transaction().setFrame(layer1, Rect(0, 0, 64, 64)).apply(); { SCOPED_TRACE("set layer 1 buffer red"); auto shot = getScreenCapture(); @@ -1289,6 +1295,7 @@ TEST_P(LayerRenderTypeTransactionTest, SetBufferMultipleLayers_BufferState) { ASSERT_NO_FATAL_FAILURE(fillBufferStateLayerColor(layer2, Color::BLUE, 32, 32)); + Transaction().setFrame(layer2, Rect(0, 0, 32, 32)).apply(); { SCOPED_TRACE("set layer 2 buffer blue"); auto shot = getScreenCapture(); @@ -1343,8 +1350,8 @@ TEST_P(LayerRenderTypeTransactionTest, SetBufferCaching_BufferState) { Color color = colors[idx % colors.size()]; auto shot = screenshot(); - shot->expectColor(Rect(0, 0, 32, 32), color); - shot->expectBorder(Rect(0, 0, 32, 32), Color::BLACK); + shot->expectColor(Rect(0, 0, mDisplayWidth, mDisplayHeight), color); + shot->expectBorder(Rect(0, 0, mDisplayWidth, mDisplayHeight), Color::BLACK); } idx++; } @@ -1376,8 +1383,8 @@ TEST_P(LayerRenderTypeTransactionTest, SetBufferCaching_LeastRecentlyUsed_Buffer Color color = colors[idx % colors.size()]; auto shot = screenshot(); - shot->expectColor(Rect(0, 0, 32, 32), color); - shot->expectBorder(Rect(0, 0, 32, 32), Color::BLACK); + shot->expectColor(Rect(0, 0, mDisplayWidth, mDisplayHeight), color); + shot->expectBorder(Rect(0, 0, mDisplayWidth, mDisplayHeight), Color::BLACK); } idx++; } @@ -1409,8 +1416,8 @@ TEST_P(LayerRenderTypeTransactionTest, SetBufferCaching_DestroyedBuffer_BufferSt Color color = colors[idx % colors.size()]; auto shot = screenshot(); - shot->expectColor(Rect(0, 0, 32, 32), color); - shot->expectBorder(Rect(0, 0, 32, 32), Color::BLACK); + shot->expectColor(Rect(0, 0, mDisplayWidth, mDisplayHeight), color); + shot->expectBorder(Rect(0, 0, mDisplayWidth, mDisplayHeight), Color::BLACK); } if (idx == 0) { buffers[0].clear(); @@ -1428,6 +1435,7 @@ TEST_P(LayerRenderTypeTransactionTest, SetTransformRotate90_BufferState) { Color::BLUE, Color::WHITE)); Transaction() + .setFrame(layer, Rect(0, 0, 32, 32)) .setTransform(layer, NATIVE_WINDOW_TRANSFORM_ROT_90) .apply(); @@ -1444,6 +1452,7 @@ TEST_P(LayerRenderTypeTransactionTest, SetTransformFlipH_BufferState) { Color::BLUE, Color::WHITE)); Transaction() + .setFrame(layer, Rect(0, 0, 32, 32)) .setTransform(layer, NATIVE_WINDOW_TRANSFORM_FLIP_H) .apply(); @@ -1460,6 +1469,7 @@ TEST_P(LayerRenderTypeTransactionTest, SetTransformFlipV_BufferState) { Color::BLUE, Color::WHITE)); Transaction() + .setFrame(layer, Rect(0, 0, 32, 32)) .setTransform(layer, NATIVE_WINDOW_TRANSFORM_FLIP_V) .apply(); @@ -1508,8 +1518,8 @@ TEST_P(LayerRenderTypeTransactionTest, SetFenceNull_BufferState) { Transaction().setBuffer(layer, buffer).setAcquireFence(layer, fence).apply(); auto shot = getScreenCapture(); - shot->expectColor(Rect(0, 0, 32, 32), Color::RED); - shot->expectBorder(Rect(0, 0, 32, 32), Color::BLACK); + shot->expectColor(Rect(0, 0, mDisplayWidth, mDisplayHeight), Color::RED); + shot->expectBorder(Rect(0, 0, mDisplayWidth, mDisplayHeight), Color::BLACK); } TEST_P(LayerRenderTypeTransactionTest, SetDataspaceBasic_BufferState) { @@ -1524,8 +1534,8 @@ TEST_P(LayerRenderTypeTransactionTest, SetDataspaceBasic_BufferState) { Transaction().setBuffer(layer, buffer).setDataspace(layer, ui::Dataspace::UNKNOWN).apply(); auto shot = getScreenCapture(); - shot->expectColor(Rect(0, 0, 32, 32), Color::RED); - shot->expectBorder(Rect(0, 0, 32, 32), Color::BLACK); + shot->expectColor(Rect(0, 0, mDisplayWidth, mDisplayHeight), Color::RED); + shot->expectBorder(Rect(0, 0, mDisplayWidth, mDisplayHeight), Color::BLACK); } TEST_P(LayerRenderTypeTransactionTest, SetHdrMetadataBasic_BufferState) { @@ -1542,8 +1552,8 @@ TEST_P(LayerRenderTypeTransactionTest, SetHdrMetadataBasic_BufferState) { Transaction().setBuffer(layer, buffer).setHdrMetadata(layer, hdrMetadata).apply(); auto shot = getScreenCapture(); - shot->expectColor(Rect(0, 0, 32, 32), Color::RED); - shot->expectBorder(Rect(0, 0, 32, 32), Color::BLACK); + shot->expectColor(Rect(0, 0, mDisplayWidth, mDisplayHeight), Color::RED); + shot->expectBorder(Rect(0, 0, mDisplayWidth, mDisplayHeight), Color::BLACK); } TEST_P(LayerRenderTypeTransactionTest, SetSurfaceDamageRegionBasic_BufferState) { @@ -1560,8 +1570,8 @@ TEST_P(LayerRenderTypeTransactionTest, SetSurfaceDamageRegionBasic_BufferState) Transaction().setBuffer(layer, buffer).setSurfaceDamageRegion(layer, region).apply(); auto shot = getScreenCapture(); - shot->expectColor(Rect(0, 0, 32, 32), Color::RED); - shot->expectBorder(Rect(0, 0, 32, 32), Color::BLACK); + shot->expectColor(Rect(0, 0, mDisplayWidth, mDisplayHeight), Color::RED); + shot->expectBorder(Rect(0, 0, mDisplayWidth, mDisplayHeight), Color::BLACK); } TEST_P(LayerRenderTypeTransactionTest, SetApiBasic_BufferState) { @@ -1576,8 +1586,8 @@ TEST_P(LayerRenderTypeTransactionTest, SetApiBasic_BufferState) { Transaction().setBuffer(layer, buffer).setApi(layer, NATIVE_WINDOW_API_CPU).apply(); auto shot = getScreenCapture(); - shot->expectColor(Rect(0, 0, 32, 32), Color::RED); - shot->expectBorder(Rect(0, 0, 32, 32), Color::BLACK); + shot->expectColor(Rect(0, 0, mDisplayWidth, mDisplayHeight), Color::RED); + shot->expectBorder(Rect(0, 0, mDisplayWidth, mDisplayHeight), Color::BLACK); } TEST_P(LayerRenderTypeTransactionTest, SetColorTransformBasic) { diff --git a/services/surfaceflinger/tests/LayerTransactionTest.h b/services/surfaceflinger/tests/LayerTransactionTest.h index 0bc8fe7aa0..87c7b7d829 100644 --- a/services/surfaceflinger/tests/LayerTransactionTest.h +++ b/services/surfaceflinger/tests/LayerTransactionTest.h @@ -244,11 +244,6 @@ protected: return bufferGenerator.get(outBuffer, outFence); } - static ui::Size getBufferSize() { - static BufferGenerator bufferGenerator; - return bufferGenerator.getSize(); - } - sp mClient; bool deviceSupportsBlurs() { diff --git a/services/surfaceflinger/tests/LayerTypeAndRenderTypeTransaction_test.cpp b/services/surfaceflinger/tests/LayerTypeAndRenderTypeTransaction_test.cpp index edf55ea6ef..ac5e297e43 100644 --- a/services/surfaceflinger/tests/LayerTypeAndRenderTypeTransaction_test.cpp +++ b/services/surfaceflinger/tests/LayerTypeAndRenderTypeTransaction_test.cpp @@ -196,7 +196,17 @@ TEST_P(LayerTypeAndRenderTypeTransactionTest, SetCornerRadius) { ASSERT_NO_FATAL_FAILURE(layer = createLayer("test", size, size)); ASSERT_NO_FATAL_FAILURE(fillLayerColor(layer, Color::RED, size, size)); - Transaction().setCornerRadius(layer, cornerRadius).apply(); + if (mLayerType == ISurfaceComposerClient::eFXSurfaceBufferQueue) { + Transaction() + .setCornerRadius(layer, cornerRadius) + .setCrop(layer, Rect(0, 0, size, size)) + .apply(); + } else { + Transaction() + .setCornerRadius(layer, cornerRadius) + .setFrame(layer, Rect(0, 0, size, size)) + .apply(); + } { const uint8_t bottom = size - 1; const uint8_t right = size - 1; @@ -224,13 +234,19 @@ TEST_P(LayerTypeAndRenderTypeTransactionTest, SetCornerRadiusRotated) { ASSERT_NO_FATAL_FAILURE(child = createLayer("child", size, size)); ASSERT_NO_FATAL_FAILURE(fillLayerColor(child, Color::GREEN, size, size)); - Transaction() - .setCornerRadius(parent, cornerRadius) - .reparent(child, parent) - .setPosition(child, 0, size) - // Rotate by half PI - .setMatrix(child, 0.0f, -1.0f, 1.0f, 0.0f) - .apply(); + auto transaction = Transaction() + .setCornerRadius(parent, cornerRadius) + .setCrop(parent, Rect(0, 0, size, size)) + .reparent(child, parent) + .setPosition(child, 0, size) + // Rotate by half PI + .setMatrix(child, 0.0f, -1.0f, 1.0f, 0.0f); + if (mLayerType == ISurfaceComposerClient::eFXSurfaceBufferQueue) { + transaction.setCrop(parent, Rect(0, 0, size, size)); + } else { + transaction.setFrame(parent, Rect(0, 0, size, size)); + } + transaction.apply(); { const uint8_t bottom = size - 1; @@ -259,12 +275,21 @@ TEST_P(LayerTypeAndRenderTypeTransactionTest, SetCornerRadiusChildCrop) { ASSERT_NO_FATAL_FAILURE(child = createLayer("child", size, size / 2)); ASSERT_NO_FATAL_FAILURE(fillLayerColor(child, Color::GREEN, size, size / 2)); - Transaction() - .setCornerRadius(parent, cornerRadius) - .reparent(child, parent) - .setPosition(child, 0, size / 2) - .apply(); - + if (mLayerType == ISurfaceComposerClient::eFXSurfaceBufferQueue) { + Transaction() + .setCornerRadius(parent, cornerRadius) + .setCrop(parent, Rect(0, 0, size, size)) + .reparent(child, parent) + .setPosition(child, 0, size / 2) + .apply(); + } else { + Transaction() + .setCornerRadius(parent, cornerRadius) + .setFrame(parent, Rect(0, 0, size, size)) + .reparent(child, parent) + .setFrame(child, Rect(0, size / 2, size, size)) + .apply(); + } { const uint8_t bottom = size - 1; const uint8_t right = size - 1; @@ -306,9 +331,12 @@ TEST_P(LayerTypeAndRenderTypeTransactionTest, SetBackgroundBlurRadiusSimple) { Transaction() .setLayer(greenLayer, mLayerZBase) + .setFrame(leftLayer, {0, 0, canvasSize * 2, canvasSize * 2}) .setLayer(leftLayer, mLayerZBase + 1) + .setFrame(leftLayer, leftRect) .setLayer(rightLayer, mLayerZBase + 2) .setPosition(rightLayer, rightRect.left, rightRect.top) + .setFrame(rightLayer, rightRect) .apply(); { @@ -324,6 +352,7 @@ TEST_P(LayerTypeAndRenderTypeTransactionTest, SetBackgroundBlurRadiusSimple) { .setLayer(blurLayer, mLayerZBase + 3) .setBackgroundBlurRadius(blurLayer, blurRadius) .setCrop(blurLayer, blurRect) + .setFrame(blurLayer, blurRect) .setSize(blurLayer, blurRect.getWidth(), blurRect.getHeight()) .setAlpha(blurLayer, 0.0f) .apply(); @@ -406,8 +435,10 @@ TEST_P(LayerTypeAndRenderTypeTransactionTest, SetBackgroundBlurAffectedByParentA Transaction() .setLayer(left, mLayerZBase + 1) + .setFrame(left, {0, 0, size, size}) .setLayer(right, mLayerZBase + 2) .setPosition(right, size, 0) + .setFrame(right, {size, 0, size * 2, size}) .apply(); { @@ -426,6 +457,7 @@ TEST_P(LayerTypeAndRenderTypeTransactionTest, SetBackgroundBlurAffectedByParentA .setAlpha(blurParent, 0.5) .setLayer(blur, mLayerZBase + 4) .setBackgroundBlurRadius(blur, size) // set the blur radius to the size of one rect + .setFrame(blur, {0, 0, size * 2, size}) .reparent(blur, blurParent) .apply(); diff --git a/services/surfaceflinger/tests/MirrorLayer_test.cpp b/services/surfaceflinger/tests/MirrorLayer_test.cpp index ccf434d63a..613b21ef04 100644 --- a/services/surfaceflinger/tests/MirrorLayer_test.cpp +++ b/services/surfaceflinger/tests/MirrorLayer_test.cpp @@ -195,7 +195,7 @@ TEST_F(MirrorLayerTest, MirrorBufferLayer) { createLayer("BufferStateLayer", 200, 200, ISurfaceComposerClient::eFXSurfaceBufferState, mChildLayer.get()); fillBufferStateLayerColor(bufferStateLayer, Color::BLUE, 200, 200); - Transaction().show(bufferStateLayer).apply(); + Transaction().setFrame(bufferStateLayer, Rect(0, 0, 200, 200)).show(bufferStateLayer).apply(); { SCOPED_TRACE("Initial Mirror BufferStateLayer"); diff --git a/services/surfaceflinger/tests/utils/TransactionUtils.h b/services/surfaceflinger/tests/utils/TransactionUtils.h index 8c448e2f96..3cbfed98f5 100644 --- a/services/surfaceflinger/tests/utils/TransactionUtils.h +++ b/services/surfaceflinger/tests/utils/TransactionUtils.h @@ -126,7 +126,7 @@ public: const uint8_t* src = pixels + (outBuffer->getStride() * (y + j) + x) * 4; for (int32_t i = 0; i < width; i++) { const uint8_t expected[4] = {color.r, color.g, color.b, color.a}; - ASSERT_TRUE(std::equal(src, src + 4, expected, colorCompare)) + EXPECT_TRUE(std::equal(src, src + 4, expected, colorCompare)) << "pixel @ (" << x + i << ", " << y + j << "): " << "expected (" << color << "), " << "got (" << Color{src[0], src[1], src[2], src[3]} << ")"; @@ -161,22 +161,6 @@ public: ASSERT_EQ(NO_ERROR, s->unlockAndPost()); } } - - static void setFrame(Transaction& t, const sp& sc, Rect source, Rect dest, - int32_t transform = 0) { - uint32_t sourceWidth = source.getWidth(); - uint32_t sourceHeight = source.getHeight(); - - if (transform & ui::Transform::ROT_90) { - std::swap(sourceWidth, sourceHeight); - } - - float dsdx = dest.getWidth() / static_cast(sourceWidth); - float dsdy = dest.getHeight() / static_cast(sourceHeight); - - t.setMatrix(sc, dsdx, 0, 0, dsdy); - t.setPosition(sc, dest.left, dest.top); - } }; enum class RenderPath { SCREENSHOT, VIRTUAL_DISPLAY }; -- cgit v1.2.3-59-g8ed1b From a65f61093e48b61cd5b91a0e2086df6044181387 Mon Sep 17 00:00:00 2001 From: Alec Mouri Date: Thu, 15 Apr 2021 16:27:01 +0000 Subject: Revert "Add ExternalTexture class into RenderEngine interface" Revert submission 14086921-renderengine-external-tex Reason for revert: Potential culprit for b/185361988 Reverted Changes: I7796764e2:Update WaylandRenderSurface to accomodate interfac... I13904eec4:Update Readback VTS to align with RenderEngine int... I222c71e6e:Add ExternalTexture class into RenderEngine interf... Change-Id: I1501890f4861a3df7ce273f1fe2ccdb275e2632c (cherry picked from commit 617752fa9590d39930f7bcf46abaea8f2e1e1032) --- libs/renderengine/Android.bp | 1 - libs/renderengine/ExternalTexture.cpp | 43 ---- libs/renderengine/gl/GLESRenderEngine.cpp | 30 ++- libs/renderengine/gl/GLESRenderEngine.h | 11 +- .../include/renderengine/ExternalTexture.h | 61 ------ .../include/renderengine/LayerSettings.h | 8 +- .../include/renderengine/RenderEngine.h | 57 +++--- .../include/renderengine/mock/RenderEngine.h | 9 +- libs/renderengine/skia/AutoBackendTexture.h | 15 +- libs/renderengine/skia/Cache.cpp | 47 ++--- libs/renderengine/skia/SkiaGLRenderEngine.cpp | 110 +++++----- libs/renderengine/skia/SkiaGLRenderEngine.h | 16 +- libs/renderengine/skia/SkiaRenderEngine.h | 10 +- libs/renderengine/tests/RenderEngineTest.cpp | 228 ++++++++++++++------- .../tests/RenderEngineThreadedTest.cpp | 9 +- .../renderengine/threaded/RenderEngineThreaded.cpp | 15 +- libs/renderengine/threaded/RenderEngineThreaded.h | 11 +- services/surfaceflinger/BufferLayer.cpp | 38 ++-- services/surfaceflinger/BufferLayer.h | 2 +- services/surfaceflinger/BufferLayerConsumer.cpp | 56 +++-- services/surfaceflinger/BufferLayerConsumer.h | 12 +- services/surfaceflinger/BufferStateLayer.cpp | 57 +++--- services/surfaceflinger/BufferStateLayer.h | 8 +- services/surfaceflinger/ClientCache.cpp | 13 +- services/surfaceflinger/ClientCache.h | 10 +- .../include/compositionengine/RenderSurface.h | 10 +- .../compositionengine/RenderSurfaceCreationArgs.h | 7 - .../impl/OutputLayerCompositionState.h | 4 +- .../include/compositionengine/impl/RenderSurface.h | 20 +- .../compositionengine/impl/planner/CachedSet.h | 30 ++- .../include/compositionengine/mock/RenderSurface.h | 2 +- .../CompositionEngine/src/Output.cpp | 31 ++- .../CompositionEngine/src/OutputLayer.cpp | 4 +- .../CompositionEngine/src/RenderSurface.cpp | 64 ++---- .../CompositionEngine/src/planner/CachedSet.cpp | 14 +- .../CompositionEngine/src/planner/Planner.cpp | 7 +- .../CompositionEngine/tests/OutputLayerTest.cpp | 12 +- .../CompositionEngine/tests/OutputTest.cpp | 15 +- .../CompositionEngine/tests/RenderSurfaceTest.cpp | 46 ++--- .../tests/planner/CachedSetTest.cpp | 6 +- services/surfaceflinger/DisplayDevice.cpp | 12 +- services/surfaceflinger/Layer.cpp | 8 +- services/surfaceflinger/Layer.h | 13 +- services/surfaceflinger/RefreshRateOverlay.cpp | 15 +- services/surfaceflinger/RefreshRateOverlay.h | 11 +- services/surfaceflinger/RegionSamplingThread.cpp | 30 +-- services/surfaceflinger/RegionSamplingThread.h | 15 +- services/surfaceflinger/SurfaceFlinger.cpp | 67 +++--- services/surfaceflinger/SurfaceFlinger.h | 12 +- .../tests/unittests/CompositionTest.cpp | 33 ++- .../tests/unittests/TestableSurfaceFlinger.h | 4 +- .../tests/unittests/TransactionFrameTracerTest.cpp | 10 +- .../unittests/TransactionSurfaceFrameTest.cpp | 67 ++---- 53 files changed, 643 insertions(+), 803 deletions(-) delete mode 100644 libs/renderengine/ExternalTexture.cpp delete mode 100644 libs/renderengine/include/renderengine/ExternalTexture.h diff --git a/libs/renderengine/Android.bp b/libs/renderengine/Android.bp index f395ab43d8..ec39137e24 100644 --- a/libs/renderengine/Android.bp +++ b/libs/renderengine/Android.bp @@ -48,7 +48,6 @@ filegroup { name: "librenderengine_sources", srcs: [ "Description.cpp", - "ExternalTexture.cpp", "Mesh.cpp", "RenderEngine.cpp", "Texture.cpp", diff --git a/libs/renderengine/ExternalTexture.cpp b/libs/renderengine/ExternalTexture.cpp deleted file mode 100644 index eabff58eba..0000000000 --- a/libs/renderengine/ExternalTexture.cpp +++ /dev/null @@ -1,43 +0,0 @@ -/* - * Copyright 2021 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 - -#include "log/log_main.h" - -namespace android::renderengine { - -ExternalTexture::ExternalTexture(const sp& buffer, RenderEngine& renderEngine, - uint32_t usage) - : mBuffer(buffer), mRenderEngine(renderEngine) { - LOG_ALWAYS_FATAL_IF(buffer == nullptr, - "Attempted to bind a null buffer to an external texture!"); - // GLESRenderEngine has a separate texture cache for output buffers, - if (usage == Usage::WRITEABLE && - (mRenderEngine.getRenderEngineType() == RenderEngine::RenderEngineType::GLES || - mRenderEngine.getRenderEngineType() == RenderEngine::RenderEngineType::THREADED)) { - return; - } - mRenderEngine.mapExternalTextureBuffer(mBuffer, usage & Usage::WRITEABLE); -} - -ExternalTexture::~ExternalTexture() { - mRenderEngine.unmapExternalTextureBuffer(mBuffer); -} - -} // namespace android::renderengine diff --git a/libs/renderengine/gl/GLESRenderEngine.cpp b/libs/renderengine/gl/GLESRenderEngine.cpp index d87315fdc2..a2963a7c33 100644 --- a/libs/renderengine/gl/GLESRenderEngine.cpp +++ b/libs/renderengine/gl/GLESRenderEngine.cpp @@ -746,8 +746,7 @@ void GLESRenderEngine::bindExternalTextureBuffer(uint32_t texName, const sp& buffer, - bool /*isRenderable*/) { +void GLESRenderEngine::cacheExternalTextureBuffer(const sp& buffer) { ATRACE_CALL(); mImageManager->cacheAsync(buffer, nullptr); } @@ -798,8 +797,8 @@ status_t GLESRenderEngine::cacheExternalTextureBufferInternal(const sp& buffer) { - mImageManager->releaseAsync(buffer->getId(), nullptr); +void GLESRenderEngine::unbindExternalTextureBuffer(uint64_t bufferId) { + mImageManager->releaseAsync(bufferId, nullptr); } std::shared_ptr GLESRenderEngine::unbindExternalTextureBufferForTesting( @@ -1103,7 +1102,7 @@ EGLImageKHR GLESRenderEngine::createFramebufferImageIfNeeded(ANativeWindowBuffer status_t GLESRenderEngine::drawLayers(const DisplaySettings& display, const std::vector& layers, - const std::shared_ptr& buffer, + const sp& buffer, const bool useFramebufferCache, base::unique_fd&& bufferFence, base::unique_fd* drawFence) { ATRACE_CALL(); @@ -1126,7 +1125,7 @@ status_t GLESRenderEngine::drawLayers(const DisplaySettings& display, return BAD_VALUE; } - validateOutputBufferUsage(buffer->getBuffer()); + validateOutputBufferUsage(buffer); std::unique_ptr fbo; // Gathering layers that requested blur, we'll need them to decide when to render to an @@ -1143,13 +1142,11 @@ status_t GLESRenderEngine::drawLayers(const DisplaySettings& display, if (blurLayersSize == 0) { fbo = std::make_unique(*this, - buffer->getBuffer() - .get() - ->getNativeBuffer(), + buffer.get()->getNativeBuffer(), useFramebufferCache); if (fbo->getStatus() != NO_ERROR) { ALOGE("Failed to bind framebuffer! Aborting GPU composition for buffer (%p).", - buffer->getBuffer()->handle); + buffer->handle); checkErrors(); return fbo->getStatus(); } @@ -1160,7 +1157,7 @@ status_t GLESRenderEngine::drawLayers(const DisplaySettings& display, mBlurFilter->setAsDrawTarget(display, blurLayers.front()->backgroundBlurRadius); if (status != NO_ERROR) { ALOGE("Failed to prepare blur filter! Aborting GPU composition for buffer (%p).", - buffer->getBuffer()->handle); + buffer->handle); checkErrors(); return status; } @@ -1197,7 +1194,7 @@ status_t GLESRenderEngine::drawLayers(const DisplaySettings& display, auto status = mBlurFilter->prepare(); if (status != NO_ERROR) { ALOGE("Failed to render blur effect! Aborting GPU composition for buffer (%p).", - buffer->getBuffer()->handle); + buffer->handle); checkErrors("Can't render first blur pass"); return status; } @@ -1206,7 +1203,6 @@ status_t GLESRenderEngine::drawLayers(const DisplaySettings& display, // Done blurring, time to bind the native FBO and render our blur onto it. fbo = std::make_unique(*this, buffer.get() - ->getBuffer() ->getNativeBuffer(), useFramebufferCache); status = fbo->getStatus(); @@ -1219,7 +1215,7 @@ status_t GLESRenderEngine::drawLayers(const DisplaySettings& display, } if (status != NO_ERROR) { ALOGE("Failed to bind framebuffer! Aborting GPU composition for buffer (%p).", - buffer->getBuffer()->handle); + buffer->handle); checkErrors("Can't bind native framebuffer"); return status; } @@ -1227,7 +1223,7 @@ status_t GLESRenderEngine::drawLayers(const DisplaySettings& display, status = mBlurFilter->render(blurLayersSize > 1); if (status != NO_ERROR) { ALOGE("Failed to render blur effect! Aborting GPU composition for buffer (%p).", - buffer->getBuffer()->handle); + buffer->handle); checkErrors("Can't render blur filter"); return status; } @@ -1254,7 +1250,7 @@ status_t GLESRenderEngine::drawLayers(const DisplaySettings& display, disableTexture = false; isOpaque = layer->source.buffer.isOpaque; - sp gBuf = layer->source.buffer.buffer->getBuffer(); + sp gBuf = layer->source.buffer.buffer; validateInputBufferUsage(gBuf); bindExternalTextureBuffer(layer->source.buffer.textureName, gBuf, layer->source.buffer.fence); @@ -1278,7 +1274,7 @@ status_t GLESRenderEngine::drawLayers(const DisplaySettings& display, // Do not cache protected EGLImage, protected memory is limited. if (gBuf->getUsage() & GRALLOC_USAGE_PROTECTED) { - unmapExternalTextureBuffer(gBuf); + unbindExternalTextureBuffer(gBuf->getId()); } } diff --git a/libs/renderengine/gl/GLESRenderEngine.h b/libs/renderengine/gl/GLESRenderEngine.h index e7ed9c01fa..cd7a86bb0e 100644 --- a/libs/renderengine/gl/GLESRenderEngine.h +++ b/libs/renderengine/gl/GLESRenderEngine.h @@ -60,14 +60,16 @@ public: void primeCache() override; void genTextures(size_t count, uint32_t* names) override; void deleteTextures(size_t count, uint32_t const* names) override; + void cacheExternalTextureBuffer(const sp& buffer) EXCLUDES(mRenderingMutex); + void unbindExternalTextureBuffer(uint64_t bufferId) EXCLUDES(mRenderingMutex); + bool isProtected() const override { return mInProtectedContext; } bool supportsProtectedContent() const override; bool useProtectedContext(bool useProtectedContext) override; status_t drawLayers(const DisplaySettings& display, const std::vector& layers, - const std::shared_ptr& buffer, - const bool useFramebufferCache, base::unique_fd&& bufferFence, - base::unique_fd* drawFence) override; + const sp& buffer, const bool useFramebufferCache, + base::unique_fd&& bufferFence, base::unique_fd* drawFence) override; bool cleanupPostRender(CleanupMode mode) override; int getContextPriority() override; bool supportsBackgroundBlur() override { return mBlurFilter != nullptr; } @@ -103,9 +105,6 @@ protected: EXCLUDES(mFramebufferImageCacheMutex); size_t getMaxTextureSize() const override; size_t getMaxViewportDims() const override; - void mapExternalTextureBuffer(const sp& buffer, bool isRenderable) - EXCLUDES(mRenderingMutex); - void unmapExternalTextureBuffer(const sp& buffer) EXCLUDES(mRenderingMutex); private: friend class BindNativeBufferAsFramebuffer; diff --git a/libs/renderengine/include/renderengine/ExternalTexture.h b/libs/renderengine/include/renderengine/ExternalTexture.h deleted file mode 100644 index 07f0833d4a..0000000000 --- a/libs/renderengine/include/renderengine/ExternalTexture.h +++ /dev/null @@ -1,61 +0,0 @@ -/* - * Copyright 2021 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 - -namespace android::renderengine { - -class RenderEngine; - -/** - * Manages GPU image resources on behalf of clients using RenderEngine. - * - * Clients of RenderEngine are required to wrap their GraphicBuffer objects as an ExternalTexture, - * which is then mapped into GPU resources required by RenderEngine. When a client no longer needs - * to use the GraphicBuffer as input into RenderEngine::drawLayers, then the client should delete - * their ExternalTexture so that resources may be freed. - */ -class ExternalTexture { -public: - // Usage specifies the rendering intent for the buffer. - enum Usage : uint32_t { - // When a buffer is not READABLE but is WRITEABLE, then GLESRenderEngine will use that as a - // hint to load the buffer into a separate cache - READABLE = 1 << 0, - - // The buffer needs to be mapped as a 2D texture if set, otherwise must be mapped as an - // external texture - WRITEABLE = 1 << 1, - }; - // Creates an ExternalTexture for the provided buffer and RenderEngine instance, with the given - // usage hint of type Usage. - ExternalTexture(const sp& buffer, RenderEngine& renderEngine, uint32_t usage); - - ~ExternalTexture(); - - // Retrieves the buffer that is bound to this texture. - const sp& getBuffer() const { return mBuffer; } - -private: - sp mBuffer; - RenderEngine& mRenderEngine; - DISALLOW_COPY_AND_ASSIGN(ExternalTexture); -}; - -} // namespace android::renderengine diff --git a/libs/renderengine/include/renderengine/LayerSettings.h b/libs/renderengine/include/renderengine/LayerSettings.h index c54c5ba047..7661233967 100644 --- a/libs/renderengine/include/renderengine/LayerSettings.h +++ b/libs/renderengine/include/renderengine/LayerSettings.h @@ -16,9 +16,11 @@ #pragma once +#include + #include #include -#include +#include #include #include #include @@ -29,8 +31,6 @@ #include #include -#include - namespace android { namespace renderengine { @@ -39,7 +39,7 @@ struct Buffer { // Buffer containing the image that we will render. // If buffer == nullptr, then the rest of the fields in this struct will be // ignored. - std::shared_ptr buffer = nullptr; + sp buffer = nullptr; // Fence that will fire when the buffer is ready to be bound. sp fence = nullptr; diff --git a/libs/renderengine/include/renderengine/RenderEngine.h b/libs/renderengine/include/renderengine/RenderEngine.h index c8a0f0a034..8dd98c3ba3 100644 --- a/libs/renderengine/include/renderengine/RenderEngine.h +++ b/libs/renderengine/include/renderengine/RenderEngine.h @@ -17,20 +17,19 @@ #ifndef SF_RENDERENGINE_H_ #define SF_RENDERENGINE_H_ +#include +#include +#include + #include #include #include -#include #include #include #include -#include -#include #include #include -#include - /** * Allows to set RenderEngine backend to GLES (default) or SkiaGL (NOT yet supported). */ @@ -52,7 +51,6 @@ class Region; namespace renderengine { -class ExternalTexture; class Image; class Mesh; class Texture; @@ -106,6 +104,23 @@ public: virtual void genTextures(size_t count, uint32_t* names) = 0; virtual void deleteTextures(size_t count, uint32_t const* names) = 0; + // Caches Image resources for this buffer, but does not bind the buffer to + // a particular texture. + // Note that work is deferred to an additional thread, i.e. this call + // is made asynchronously, but the caller can expect that cache/unbind calls + // are performed in a manner that's conflict serializable, i.e. unbinding + // a buffer should never occur before binding the buffer if the caller + // called {bind, cache}ExternalTextureBuffer before calling unbind. + virtual void cacheExternalTextureBuffer(const sp& buffer) = 0; + // Removes internal resources referenced by the bufferId. This method should be + // invoked when the caller will no longer hold a reference to a GraphicBuffer + // and needs to clean up its resources. + // Note that work is deferred to an additional thread, i.e. this call + // is made asynchronously, but the caller can expect that cache/unbind calls + // are performed in a manner that's conflict serializable, i.e. unbinding + // a buffer should never occur before binding the buffer if the caller + // called {bind, cache}ExternalTextureBuffer before calling unbind. + virtual void unbindExternalTextureBuffer(uint64_t bufferId) = 0; enum class CleanupMode { CLEAN_OUTPUT_RESOURCES, @@ -176,9 +191,8 @@ public: // now, this always returns NO_ERROR. virtual status_t drawLayers(const DisplaySettings& display, const std::vector& layers, - const std::shared_ptr& buffer, - const bool useFramebufferCache, base::unique_fd&& bufferFence, - base::unique_fd* drawFence) = 0; + const sp& buffer, const bool useFramebufferCache, + base::unique_fd&& bufferFence, base::unique_fd* drawFence) = 0; virtual void cleanFramebufferCache() = 0; // Returns the priority this context was actually created with. Note: this may not be // the same as specified at context creation time, due to implementation limits on the @@ -199,31 +213,6 @@ public: static void validateOutputBufferUsage(const sp&); protected: - // Maps GPU resources for this buffer. - // Note that work may be deferred to an additional thread, i.e. this call - // is made asynchronously, but the caller can expect that map/unmap calls - // are performed in a manner that's conflict serializable, i.e. unmapping - // a buffer should never occur before binding the buffer if the caller - // called mapExternalTextureBuffer before calling unmap. - // Note also that if the buffer contains protected content, then mapping those GPU resources may - // be deferred until the buffer is really used for drawing. This is because typical SoCs that - // support protected memory only support a limited amount, so optimisitically mapping protected - // memory may be too burdensome. If a buffer contains protected content and the RenderEngine - // implementation supports protected context, then GPU resources may be mapped into both the - // protected and unprotected contexts. - // If the buffer may ever be written to by RenderEngine, then isRenderable must be true. - virtual void mapExternalTextureBuffer(const sp& buffer, bool isRenderable) = 0; - // Unmaps GPU resources used by this buffer. This method should be - // invoked when the caller will no longer hold a reference to a GraphicBuffer - // and needs to clean up its resources. - // Note that if there are multiple callers holding onto the same buffer, then the buffer's - // resources may be internally ref-counted to guard against use-after-free errors. Note that - // work may be deferred to an additional thread, i.e. this call is expected to be made - // asynchronously, but the caller can expect that map/unmap calls are performed in a manner - // that's conflict serializable, i.e. unmap a buffer should never occur before binding the - // buffer if the caller called mapExternalTextureBuffer before calling unmap. - virtual void unmapExternalTextureBuffer(const sp& buffer) = 0; - friend class ExternalTexture; friend class threaded::RenderEngineThreaded; const RenderEngineType mRenderEngineType; }; diff --git a/libs/renderengine/include/renderengine/mock/RenderEngine.h b/libs/renderengine/include/renderengine/mock/RenderEngine.h index 27dbd1ecf3..228553d643 100644 --- a/libs/renderengine/include/renderengine/mock/RenderEngine.h +++ b/libs/renderengine/include/renderengine/mock/RenderEngine.h @@ -39,6 +39,8 @@ public: MOCK_METHOD1(dump, void(std::string&)); MOCK_METHOD2(genTextures, void(size_t, uint32_t*)); MOCK_METHOD2(deleteTextures, void(size_t, uint32_t const*)); + MOCK_METHOD1(cacheExternalTextureBuffer, void(const sp&)); + MOCK_METHOD1(unbindExternalTextureBuffer, void(uint64_t)); MOCK_METHOD1(drawMesh, void(const renderengine::Mesh&)); MOCK_CONST_METHOD0(getMaxTextureSize, size_t()); MOCK_CONST_METHOD0(getMaxViewportDims, size_t()); @@ -48,17 +50,12 @@ public: MOCK_METHOD1(cleanupPostRender, bool(CleanupMode mode)); MOCK_METHOD6(drawLayers, status_t(const DisplaySettings&, const std::vector&, - const std::shared_ptr&, const bool, base::unique_fd&&, + const sp&, const bool, base::unique_fd&&, base::unique_fd*)); MOCK_METHOD0(cleanFramebufferCache, void()); MOCK_METHOD0(getContextPriority, int()); MOCK_METHOD0(supportsBackgroundBlur, bool()); MOCK_METHOD1(onPrimaryDisplaySizeChanged, void(ui::Size)); - -protected: - // mock renderengine still needs to implement these, but callers should never need to call them. - void mapExternalTextureBuffer(const sp&, bool) {} - void unmapExternalTextureBuffer(const sp&) {} }; } // namespace mock diff --git a/libs/renderengine/skia/AutoBackendTexture.h b/libs/renderengine/skia/AutoBackendTexture.h index 2d61cf854b..bb758780e1 100644 --- a/libs/renderengine/skia/AutoBackendTexture.h +++ b/libs/renderengine/skia/AutoBackendTexture.h @@ -21,9 +21,9 @@ #include #include #include -#include #include "android-base/macros.h" +#include "ui/GraphicTypes.h" namespace android { namespace renderengine { @@ -41,18 +41,13 @@ public: // of shared ownership with Skia objects, so we wrap it here instead. class LocalRef { public: - LocalRef(AutoBackendTexture* texture) { setTexture(texture); } + LocalRef() {} ~LocalRef() { // Destroying the texture is the same as setting it to null setTexture(nullptr); } - AutoBackendTexture* getTexture() const { return mTexture; } - - DISALLOW_COPY_AND_ASSIGN(LocalRef); - - private: // Sets the texture to locally ref-track. void setTexture(AutoBackendTexture* texture) { if (mTexture != nullptr) { @@ -64,6 +59,12 @@ public: mTexture->ref(); } } + + AutoBackendTexture* getTexture() const { return mTexture; } + + DISALLOW_COPY_AND_ASSIGN(LocalRef); + + private: AutoBackendTexture* mTexture = nullptr; }; diff --git a/libs/renderengine/skia/Cache.cpp b/libs/renderengine/skia/Cache.cpp index 1c2b2fc3ca..1db20c0be0 100644 --- a/libs/renderengine/skia/Cache.cpp +++ b/libs/renderengine/skia/Cache.cpp @@ -46,7 +46,7 @@ constexpr auto kDestDataSpace = ui::Dataspace::SRGB; } // namespace static void drawShadowLayers(SkiaRenderEngine* renderengine, const DisplaySettings& display, - const std::shared_ptr& dstTexture) { + sp dstBuffer) { // Somewhat arbitrary dimensions, but on screen and slightly shorter, based // on actual use. FloatRect rect(0, 0, display.physicalDisplay.width(), display.physicalDisplay.height() - 30); @@ -73,7 +73,7 @@ static void drawShadowLayers(SkiaRenderEngine* renderengine, const DisplaySettin auto layers = std::vector{&layer}; // The identity matrix will generate the fast shader - renderengine->drawLayers(display, layers, dstTexture, kUseFrameBufferCache, base::unique_fd(), + renderengine->drawLayers(display, layers, dstBuffer, kUseFrameBufferCache, base::unique_fd(), nullptr); // This matrix, which has different scales for x and y, will // generate the slower (more general case) version, which has variants for translucent @@ -86,14 +86,13 @@ static void drawShadowLayers(SkiaRenderEngine* renderengine, const DisplaySettin // clang-format on for (auto translucent : {false, true}) { layer.shadow.casterIsTranslucent = translucent; - renderengine->drawLayers(display, layers, dstTexture, kUseFrameBufferCache, + renderengine->drawLayers(display, layers, dstBuffer, kUseFrameBufferCache, base::unique_fd(), nullptr); } } static void drawImageLayers(SkiaRenderEngine* renderengine, const DisplaySettings& display, - const std::shared_ptr& dstTexture, - const std::shared_ptr& srcTexture) { + sp dstBuffer, sp srcBuffer) { const Rect& displayRect = display.physicalDisplay; FloatRect rect(0, 0, displayRect.width(), displayRect.height()); LayerSettings layer{ @@ -104,7 +103,7 @@ static void drawImageLayers(SkiaRenderEngine* renderengine, const DisplaySetting }, .source = PixelSource{.buffer = Buffer{ - .buffer = srcTexture, + .buffer = srcBuffer, .maxMasteringLuminance = 1000.f, .maxContentLuminance = 1000.f, }}, @@ -127,7 +126,7 @@ static void drawImageLayers(SkiaRenderEngine* renderengine, const DisplaySetting layer.source.buffer.isOpaque = isOpaque; for (auto alpha : {half(.23999f), half(1.0f)}) { layer.alpha = alpha; - renderengine->drawLayers(display, layers, dstTexture, kUseFrameBufferCache, + renderengine->drawLayers(display, layers, dstBuffer, kUseFrameBufferCache, base::unique_fd(), nullptr); } } @@ -136,7 +135,7 @@ static void drawImageLayers(SkiaRenderEngine* renderengine, const DisplaySetting } static void drawSolidLayers(SkiaRenderEngine* renderengine, const DisplaySettings& display, - const std::shared_ptr& dstTexture) { + sp dstBuffer) { const Rect& displayRect = display.physicalDisplay; FloatRect rect(0, 0, displayRect.width(), displayRect.height()); LayerSettings layer{ @@ -144,11 +143,11 @@ static void drawSolidLayers(SkiaRenderEngine* renderengine, const DisplaySetting Geometry{ .boundaries = rect, }, + .alpha = 1, .source = PixelSource{ .solidColor = half3(0.1f, 0.2f, 0.3f), }, - .alpha = 1, }; auto layers = std::vector{&layer}; @@ -156,14 +155,14 @@ static void drawSolidLayers(SkiaRenderEngine* renderengine, const DisplaySetting layer.geometry.positionTransform = transform; for (float roundedCornersRadius : {0.0f, 0.05f, 50.f}) { layer.geometry.roundedCornersRadius = roundedCornersRadius; - renderengine->drawLayers(display, layers, dstTexture, kUseFrameBufferCache, + renderengine->drawLayers(display, layers, dstBuffer, kUseFrameBufferCache, base::unique_fd(), nullptr); } } } static void drawBlurLayers(SkiaRenderEngine* renderengine, const DisplaySettings& display, - const std::shared_ptr& dstTexture) { + sp dstBuffer) { const Rect& displayRect = display.physicalDisplay; FloatRect rect(0, 0, displayRect.width(), displayRect.height()); LayerSettings layer{ @@ -177,7 +176,7 @@ static void drawBlurLayers(SkiaRenderEngine* renderengine, const DisplaySettings auto layers = std::vector{&layer}; for (int radius : {9, 60}) { layer.backgroundBlurRadius = radius; - renderengine->drawLayers(display, layers, dstTexture, kUseFrameBufferCache, + renderengine->drawLayers(display, layers, dstBuffer, kUseFrameBufferCache, base::unique_fd(), nullptr); } } @@ -215,9 +214,6 @@ void Cache::primeShaderCache(SkiaRenderEngine* renderengine) { sp dstBuffer = new GraphicBuffer(displayRect.width(), displayRect.height(), PIXEL_FORMAT_RGBA_8888, 1, usage, "primeShaderCache_dst"); - - const auto dstTexture = std::make_shared(dstBuffer, *renderengine, - ExternalTexture::Usage::WRITEABLE); // This buffer will be the source for the call to drawImageLayers. Draw // something to it as a placeholder for what an app draws. We should draw // something, but the details are not important. Make use of the shadow layer drawing step @@ -226,16 +222,11 @@ void Cache::primeShaderCache(SkiaRenderEngine* renderengine) { new GraphicBuffer(displayRect.width(), displayRect.height(), PIXEL_FORMAT_RGBA_8888, 1, usage, "drawImageLayer_src"); - const auto srcTexture = - std::make_shared(srcBuffer, *renderengine, - ExternalTexture::Usage::READABLE | - ExternalTexture::Usage::WRITEABLE); - - drawSolidLayers(renderengine, display, dstTexture); - drawShadowLayers(renderengine, display, srcTexture); - drawBlurLayers(renderengine, display, dstTexture); + drawSolidLayers(renderengine, display, dstBuffer); + drawShadowLayers(renderengine, display, srcBuffer); + drawBlurLayers(renderengine, display, dstBuffer); // The majority of shaders are related to sampling images. - drawImageLayers(renderengine, display, dstTexture, srcTexture); + drawImageLayers(renderengine, display, dstBuffer, srcBuffer); // should be the same as AHARDWAREBUFFER_USAGE_GPU_SAMPLED_IMAGE; const int64_t usageExternal = GRALLOC_USAGE_HW_TEXTURE; @@ -243,12 +234,12 @@ void Cache::primeShaderCache(SkiaRenderEngine* renderengine) { sp externalBuffer = new GraphicBuffer(displayRect.width(), displayRect.height(), PIXEL_FORMAT_RGBA_8888, 1, usageExternal, "primeShaderCache_external"); - const auto externalTexture = - std::make_shared(externalBuffer, *renderengine, - ExternalTexture::Usage::READABLE); // TODO(b/184665179) doubles number of image shader compilations, but only somewhere // between 6 and 8 will occur in real uses. - drawImageLayers(renderengine, display, dstTexture, externalTexture); + drawImageLayers(renderengine, display, dstBuffer, externalBuffer); + renderengine->unbindExternalTextureBuffer(externalBuffer->getId()); + + renderengine->unbindExternalTextureBuffer(srcBuffer->getId()); const nsecs_t timeAfter = systemTime(); const float compileTimeMs = static_cast(timeAfter - timeBefore) / 1.0E6; diff --git a/libs/renderengine/skia/SkiaGLRenderEngine.cpp b/libs/renderengine/skia/SkiaGLRenderEngine.cpp index 37d98a3a8f..df40dd9c2d 100644 --- a/libs/renderengine/skia/SkiaGLRenderEngine.cpp +++ b/libs/renderengine/skia/SkiaGLRenderEngine.cpp @@ -329,6 +329,8 @@ SkiaGLRenderEngine::SkiaGLRenderEngine(const RenderEngineCreationArgs& args, EGL } SkiaGLRenderEngine::~SkiaGLRenderEngine() { + cleanFramebufferCache(); + std::lock_guard lock(mRenderingMutex); if (mBlurFilter) { delete mBlurFilter; @@ -482,8 +484,7 @@ static bool needsToneMapping(ui::Dataspace sourceDataspace, ui::Dataspace destin sourceTransfer != destTransfer; } -void SkiaGLRenderEngine::mapExternalTextureBuffer(const sp& buffer, - bool isRenderable) { +void SkiaGLRenderEngine::cacheExternalTextureBuffer(const sp& buffer) { // Only run this if RE is running on its own thread. This way the access to GL // operations is guaranteed to be happening on the same thread. if (mRenderEngineType != RenderEngineType::SKIA_GL_THREADED) { @@ -504,41 +505,25 @@ void SkiaGLRenderEngine::mapExternalTextureBuffer(const sp& buffe auto& cache = mInProtectedContext ? mProtectedTextureCache : mTextureCache; std::lock_guard lock(mRenderingMutex); - mGraphicBufferExternalRefs[buffer->getId()]++; - - if (const auto& iter = cache.find(buffer->getId()); iter == cache.end()) { + auto iter = cache.find(buffer->getId()); + if (iter != cache.end()) { + ALOGV("Texture already exists in cache."); + } else { std::shared_ptr imageTextureRef = - std::make_shared( - new AutoBackendTexture(grContext.get(), buffer->toAHardwareBuffer(), - isRenderable)); + std::make_shared(); + imageTextureRef->setTexture( + new AutoBackendTexture(grContext.get(), buffer->toAHardwareBuffer(), false)); cache.insert({buffer->getId(), imageTextureRef}); } // restore the original state of the protected context if necessary useProtectedContext(protectedContextState); } -void SkiaGLRenderEngine::unmapExternalTextureBuffer(const sp& buffer) { +void SkiaGLRenderEngine::unbindExternalTextureBuffer(uint64_t bufferId) { ATRACE_CALL(); std::lock_guard lock(mRenderingMutex); - if (const auto& iter = mGraphicBufferExternalRefs.find(buffer->getId()); - iter != mGraphicBufferExternalRefs.end()) { - if (iter->second == 0) { - ALOGW("Attempted to unmap GraphicBuffer from RenderEngine texture, but the " - "ref count was already zero!", - buffer->getId()); - mGraphicBufferExternalRefs.erase(buffer->getId()); - return; - } - - iter->second--; - - if (iter->second == 0) { - mTextureCache.erase(buffer->getId()); - mProtectedTextureCache.erase(buffer->getId()); - mGraphicBufferExternalRefs.erase(buffer->getId()); - } - } + mTextureCache.erase(bufferId); + mProtectedTextureCache.erase(bufferId); } sk_sp SkiaGLRenderEngine::createRuntimeEffectShader(sk_sp shader, @@ -636,8 +621,8 @@ private: status_t SkiaGLRenderEngine::drawLayers(const DisplaySettings& display, const std::vector& layers, - const std::shared_ptr& buffer, - const bool /*useFramebufferCache*/, + const sp& buffer, + const bool useFramebufferCache, base::unique_fd&& bufferFence, base::unique_fd* drawFence) { ATRACE_NAME("SkiaGL::drawLayers"); @@ -660,18 +645,32 @@ status_t SkiaGLRenderEngine::drawLayers(const DisplaySettings& display, return BAD_VALUE; } - validateOutputBufferUsage(buffer->getBuffer()); + validateOutputBufferUsage(buffer); auto grContext = mInProtectedContext ? mProtectedGrContext : mGrContext; auto& cache = mInProtectedContext ? mProtectedTextureCache : mTextureCache; + AHardwareBuffer_Desc bufferDesc; + AHardwareBuffer_describe(buffer->toAHardwareBuffer(), &bufferDesc); + + std::shared_ptr surfaceTextureRef = nullptr; + if (useFramebufferCache) { + auto iter = cache.find(buffer->getId()); + if (iter != cache.end()) { + ALOGV("Cache hit!"); + ATRACE_NAME("Cache hit"); + surfaceTextureRef = iter->second; + } + } - std::shared_ptr surfaceTextureRef; - if (const auto& it = cache.find(buffer->getBuffer()->getId()); it != cache.end()) { - surfaceTextureRef = it->second; - } else { - surfaceTextureRef = std::make_shared( - new AutoBackendTexture(grContext.get(), buffer->getBuffer()->toAHardwareBuffer(), - true)); + if (surfaceTextureRef == nullptr || surfaceTextureRef->getTexture() == nullptr) { + ATRACE_NAME("Cache miss"); + surfaceTextureRef = std::make_shared(); + surfaceTextureRef->setTexture( + new AutoBackendTexture(grContext.get(), buffer->toAHardwareBuffer(), true)); + if (useFramebufferCache) { + ALOGD("Adding to cache"); + cache.insert({buffer->getId(), surfaceTextureRef}); + } } const ui::Dataspace dstDataspace = @@ -877,22 +876,18 @@ status_t SkiaGLRenderEngine::drawLayers(const DisplaySettings& display, SkPaint paint; if (layer->source.buffer.buffer) { ATRACE_NAME("DrawImage"); - validateInputBufferUsage(layer->source.buffer.buffer->getBuffer()); + validateInputBufferUsage(layer->source.buffer.buffer); const auto& item = layer->source.buffer; std::shared_ptr imageTextureRef = nullptr; - - if (const auto& iter = cache.find(item.buffer->getBuffer()->getId()); - iter != cache.end()) { + auto iter = cache.find(item.buffer->getId()); + if (iter != cache.end()) { imageTextureRef = iter->second; } else { - // If we didn't find the image in the cache, then create a local ref but don't cache - // it. If we're using skia, we're guaranteed to run on a dedicated GPU thread so if - // we didn't find anything in the cache then we intentionally did not cache this - // buffer's resources. - imageTextureRef = std::make_shared( - new AutoBackendTexture(grContext.get(), - item.buffer->getBuffer()->toAHardwareBuffer(), - false)); + imageTextureRef = std::make_shared(); + imageTextureRef->setTexture(new AutoBackendTexture(grContext.get(), + item.buffer->toAHardwareBuffer(), + false)); + cache.insert({item.buffer->getId(), imageTextureRef}); } sk_sp image = @@ -1205,6 +1200,15 @@ EGLSurface SkiaGLRenderEngine::createPlaceholderEglPbufferSurface(EGLDisplay dis return eglCreatePbufferSurface(display, placeholderConfig, attributes.data()); } +void SkiaGLRenderEngine::cleanFramebufferCache() { + // TODO(b/180767535) Remove this method and use b/180767535 instead, which would allow + // SF to control texture lifecycle more tightly rather than through custom hooks into RE. + std::lock_guard lock(mRenderingMutex); + mRuntimeEffects.clear(); + mProtectedTextureCache.clear(); + mTextureCache.clear(); +} + int SkiaGLRenderEngine::getContextPriority() { int value; eglQueryContext(mEGLDisplay, mEGLContext, EGL_CONTEXT_PRIORITY_LEVEL_IMG, &value); @@ -1277,12 +1281,6 @@ void SkiaGLRenderEngine::dump(std::string& result) { StringAppendF(&result, "Skia's Wrapped Objects:\n"); gpuReporter.logOutput(result, true); - StringAppendF(&result, "RenderEngine tracked buffers: %zu\n", - mGraphicBufferExternalRefs.size()); - StringAppendF(&result, "Dumping buffer ids...\n"); - for (const auto& [id, refCounts] : mGraphicBufferExternalRefs) { - StringAppendF(&result, "- 0x%" PRIx64 " - %d refs \n", id, refCounts); - } StringAppendF(&result, "RenderEngine AHB/BackendTexture cache size: %zu\n", mTextureCache.size()); StringAppendF(&result, "Dumping buffer ids...\n"); diff --git a/libs/renderengine/skia/SkiaGLRenderEngine.h b/libs/renderengine/skia/SkiaGLRenderEngine.h index e71c560a1f..8e77c16b40 100644 --- a/libs/renderengine/skia/SkiaGLRenderEngine.h +++ b/libs/renderengine/skia/SkiaGLRenderEngine.h @@ -23,7 +23,6 @@ #include #include #include -#include #include #include @@ -53,12 +52,13 @@ public: ~SkiaGLRenderEngine() override EXCLUDES(mRenderingMutex); void primeCache() override; + void cacheExternalTextureBuffer(const sp& buffer) override; + void unbindExternalTextureBuffer(uint64_t bufferId) override; status_t drawLayers(const DisplaySettings& display, const std::vector& layers, - const std::shared_ptr& buffer, - const bool useFramebufferCache, base::unique_fd&& bufferFence, - base::unique_fd* drawFence) override; - void cleanFramebufferCache() override {} + const sp& buffer, const bool useFramebufferCache, + base::unique_fd&& bufferFence, base::unique_fd* drawFence) override; + void cleanFramebufferCache() override; int getContextPriority() override; bool isProtected() const override { return mInProtectedContext; } bool supportsProtectedContent() const override; @@ -72,8 +72,6 @@ protected: void dump(std::string& result) override; size_t getMaxTextureSize() const override; size_t getMaxViewportDims() const override; - void mapExternalTextureBuffer(const sp& buffer, bool isRenderable) override; - void unmapExternalTextureBuffer(const sp& buffer) override; private: static EGLConfig chooseEglConfig(EGLDisplay display, int format, bool logConfig); @@ -116,9 +114,7 @@ private: const PixelFormat mDefaultPixelFormat; const bool mUseColorManagement; - // Number of external holders of ExternalTexture references, per GraphicBuffer ID. - std::unordered_map mGraphicBufferExternalRefs GUARDED_BY(mRenderingMutex); - // Cache of GL textures that we'll store per GraphicBuffer ID, sliced by GPU context. + // Cache of GL textures that we'll store per GraphicBuffer ID std::unordered_map> mTextureCache GUARDED_BY(mRenderingMutex); std::unordered_map> diff --git a/libs/renderengine/skia/SkiaRenderEngine.h b/libs/renderengine/skia/SkiaRenderEngine.h index 308c5ffa9f..51ef088a25 100644 --- a/libs/renderengine/skia/SkiaRenderEngine.h +++ b/libs/renderengine/skia/SkiaRenderEngine.h @@ -42,12 +42,15 @@ public: virtual void primeCache() override{}; virtual void genTextures(size_t /*count*/, uint32_t* /*names*/) override{}; virtual void deleteTextures(size_t /*count*/, uint32_t const* /*names*/) override{}; + virtual void cacheExternalTextureBuffer(const sp& /*buffer*/){}; + virtual void unbindExternalTextureBuffer(uint64_t /*bufferId*/){}; + virtual bool isProtected() const override { return false; } // mInProtectedContext; } virtual bool supportsProtectedContent() const override { return false; }; virtual bool useProtectedContext(bool /*useProtectedContext*/) override { return false; }; virtual status_t drawLayers(const DisplaySettings& /*display*/, const std::vector& /*layers*/, - const std::shared_ptr& /*buffer*/, + const sp& /*buffer*/, const bool /*useFramebufferCache*/, base::unique_fd&& /*bufferFence*/, base::unique_fd* /*drawFence*/) override { @@ -57,11 +60,6 @@ public: virtual int getContextPriority() override { return 0; } virtual void assertShadersCompiled(int numShaders) {} virtual int reportShadersCompiled() { return 0; } - -protected: - virtual void mapExternalTextureBuffer(const sp& /*buffer*/, - bool /*isRenderable*/) override; - virtual void unmapExternalTextureBuffer(const sp& /*buffer*/) override; }; } // namespace skia diff --git a/libs/renderengine/tests/RenderEngineTest.cpp b/libs/renderengine/tests/RenderEngineTest.cpp index d63c88bc02..7846156383 100644 --- a/libs/renderengine/tests/RenderEngineTest.cpp +++ b/libs/renderengine/tests/RenderEngineTest.cpp @@ -24,7 +24,6 @@ #include #include -#include #include #include #include @@ -161,42 +160,27 @@ public: class RenderEngineTest : public ::testing::TestWithParam> { public: - std::shared_ptr allocateDefaultBuffer() { - return std::make_shared< - renderengine:: - ExternalTexture>(new GraphicBuffer(DEFAULT_DISPLAY_WIDTH, - DEFAULT_DISPLAY_HEIGHT, - HAL_PIXEL_FORMAT_RGBA_8888, 1, - GRALLOC_USAGE_SW_READ_OFTEN | - GRALLOC_USAGE_SW_WRITE_OFTEN | - GRALLOC_USAGE_HW_RENDER | - GRALLOC_USAGE_HW_TEXTURE, - "output"), - *mRE, - renderengine::ExternalTexture::Usage::READABLE | - renderengine::ExternalTexture::Usage::WRITEABLE); + static sp allocateDefaultBuffer() { + return new GraphicBuffer(DEFAULT_DISPLAY_WIDTH, DEFAULT_DISPLAY_HEIGHT, + HAL_PIXEL_FORMAT_RGBA_8888, 1, + GRALLOC_USAGE_SW_READ_OFTEN | GRALLOC_USAGE_SW_WRITE_OFTEN | + GRALLOC_USAGE_HW_RENDER | GRALLOC_USAGE_HW_TEXTURE, + "output"); } // Allocates a 1x1 buffer to fill with a solid color - std::shared_ptr allocateSourceBuffer(uint32_t width, - uint32_t height) { - return std::make_shared< - renderengine:: - ExternalTexture>(new GraphicBuffer(width, height, - HAL_PIXEL_FORMAT_RGBA_8888, 1, - GRALLOC_USAGE_SW_READ_OFTEN | - GRALLOC_USAGE_SW_WRITE_OFTEN | - GRALLOC_USAGE_HW_TEXTURE, - "input"), - *mRE, - renderengine::ExternalTexture::Usage::READABLE | - renderengine::ExternalTexture::Usage::WRITEABLE); + static sp allocateSourceBuffer(uint32_t width, uint32_t height) { + return new GraphicBuffer(width, height, HAL_PIXEL_FORMAT_RGBA_8888, 1, + GRALLOC_USAGE_SW_READ_OFTEN | GRALLOC_USAGE_SW_WRITE_OFTEN | + GRALLOC_USAGE_HW_TEXTURE, + "input"); } RenderEngineTest() { 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()); + mBuffer = allocateDefaultBuffer(); } ~RenderEngineTest() { @@ -227,21 +211,20 @@ public: } uint8_t* pixels; - mBuffer->getBuffer()->lock(GRALLOC_USAGE_SW_READ_OFTEN | GRALLOC_USAGE_SW_WRITE_OFTEN, - reinterpret_cast(&pixels)); + mBuffer->lock(GRALLOC_USAGE_SW_READ_OFTEN | GRALLOC_USAGE_SW_WRITE_OFTEN, + reinterpret_cast(&pixels)); file << "P6\n"; - file << mBuffer->getBuffer()->getWidth() << "\n"; - file << mBuffer->getBuffer()->getHeight() << "\n"; + file << mBuffer->getWidth() << "\n"; + file << mBuffer->getHeight() << "\n"; file << 255 << "\n"; - std::vector outBuffer(mBuffer->getBuffer()->getWidth() * - mBuffer->getBuffer()->getHeight() * 3); + std::vector outBuffer(mBuffer->getWidth() * mBuffer->getHeight() * 3); auto outPtr = reinterpret_cast(outBuffer.data()); - for (int32_t j = 0; j < mBuffer->getBuffer()->getHeight(); j++) { - const uint8_t* src = pixels + (mBuffer->getBuffer()->getStride() * j) * 4; - for (int32_t i = 0; i < mBuffer->getBuffer()->getWidth(); i++) { + for (int32_t j = 0; j < mBuffer->getHeight(); j++) { + const uint8_t* src = pixels + (mBuffer->getStride() * j) * 4; + for (int32_t i = 0; i < mBuffer->getWidth(); i++) { // Only copy R, G and B components outPtr[0] = src[0]; outPtr[1] = src[1]; @@ -252,7 +235,7 @@ public: } } file.write(reinterpret_cast(outBuffer.data()), outBuffer.size()); - mBuffer->getBuffer()->unlock(); + mBuffer->unlock(); } void expectBufferColor(const Region& region, uint8_t r, uint8_t g, uint8_t b, uint8_t a) { @@ -279,13 +262,13 @@ public: void expectBufferColor(const Rect& region, uint8_t r, uint8_t g, uint8_t b, uint8_t a, std::function colorCompare) { uint8_t* pixels; - mBuffer->getBuffer()->lock(GRALLOC_USAGE_SW_READ_OFTEN | GRALLOC_USAGE_SW_WRITE_OFTEN, - reinterpret_cast(&pixels)); + mBuffer->lock(GRALLOC_USAGE_SW_READ_OFTEN | GRALLOC_USAGE_SW_WRITE_OFTEN, + reinterpret_cast(&pixels)); int32_t maxFails = 10; int32_t fails = 0; for (int32_t j = 0; j < region.getHeight(); j++) { - const uint8_t* src = pixels + - (mBuffer->getBuffer()->getStride() * (region.top + j) + region.left) * 4; + const uint8_t* src = + pixels + (mBuffer->getStride() * (region.top + j) + region.left) * 4; for (int32_t i = 0; i < region.getWidth(); i++) { const uint8_t expected[4] = {r, g, b, a}; bool equal = colorCompare(src, expected); @@ -306,7 +289,7 @@ public: break; } } - mBuffer->getBuffer()->unlock(); + mBuffer->unlock(); } void expectAlpha(const Rect& rect, uint8_t a) { @@ -404,6 +387,7 @@ public: base::unique_fd fence; status_t status = mRE->drawLayers(settings, layers, mBuffer, true, base::unique_fd(), &fence); + mCurrentBuffer = mBuffer; int fd = fence.release(); if (fd >= 0) { @@ -413,7 +397,7 @@ public: ASSERT_EQ(NO_ERROR, status); if (layers.size() > 0 && mGLESRE != nullptr) { - ASSERT_TRUE(mGLESRE->isFramebufferImageCachedForTesting(mBuffer->getBuffer()->getId())); + ASSERT_TRUE(mGLESRE->isFramebufferImageCachedForTesting(mBuffer->getId())); } } @@ -519,11 +503,17 @@ public: void initializeRenderEngine(); std::unique_ptr mRE; - std::shared_ptr mBuffer; // GLESRenderEngine for testing GLES-specific behavior. // Owened by mRE, but this is downcasted. renderengine::gl::GLESRenderEngine* mGLESRE = nullptr; + // Dumb hack to avoid NPE in the EGL driver: the GraphicBuffer needs to + // be freed *after* RenderEngine is destroyed, so that the EGL image is + // destroyed first. + sp mCurrentBuffer; + + sp mBuffer; + std::vector mTexNames; }; @@ -540,7 +530,6 @@ void RenderEngineTest::initializeRenderEngine() { } else { mRE = renderEngineFactory->createRenderEngine(); } - mBuffer = allocateDefaultBuffer(); } struct ColorSourceVariant { @@ -577,18 +566,18 @@ template struct BufferSourceVariant { static void fillColor(renderengine::LayerSettings& layer, half r, half g, half b, RenderEngineTest* fixture) { - const auto buf = fixture->allocateSourceBuffer(1, 1); + sp buf = RenderEngineTest::allocateSourceBuffer(1, 1); uint32_t texName; fixture->mRE->genTextures(1, &texName); fixture->mTexNames.push_back(texName); uint8_t* pixels; - buf->getBuffer()->lock(GRALLOC_USAGE_SW_READ_OFTEN | GRALLOC_USAGE_SW_WRITE_OFTEN, - reinterpret_cast(&pixels)); + buf->lock(GRALLOC_USAGE_SW_READ_OFTEN | GRALLOC_USAGE_SW_WRITE_OFTEN, + reinterpret_cast(&pixels)); - for (int32_t j = 0; j < buf->getBuffer()->getHeight(); j++) { - uint8_t* iter = pixels + (buf->getBuffer()->getStride() * j) * 4; - for (int32_t i = 0; i < buf->getBuffer()->getWidth(); i++) { + for (int32_t j = 0; j < buf->getHeight(); j++) { + uint8_t* iter = pixels + (buf->getStride() * j) * 4; + for (int32_t i = 0; i < buf->getWidth(); i++) { iter[0] = uint8_t(r * 255); iter[1] = uint8_t(g * 255); iter[2] = uint8_t(b * 255); @@ -597,7 +586,7 @@ struct BufferSourceVariant { } } - buf->getBuffer()->unlock(); + buf->unlock(); layer.source.buffer.buffer = buf; layer.source.buffer.textureName = texName; @@ -1023,14 +1012,14 @@ void RenderEngineTest::fillRedBufferTextureTransform() { layer.sourceDataspace = ui::Dataspace::V0_SRGB_LINEAR; // Here will allocate a checker board texture, but transform texture // coordinates so that only the upper left is applied. - const auto buf = allocateSourceBuffer(2, 2); + sp buf = allocateSourceBuffer(2, 2); uint32_t texName; RenderEngineTest::mRE->genTextures(1, &texName); this->mTexNames.push_back(texName); uint8_t* pixels; - buf->getBuffer()->lock(GRALLOC_USAGE_SW_READ_OFTEN | GRALLOC_USAGE_SW_WRITE_OFTEN, - reinterpret_cast(&pixels)); + buf->lock(GRALLOC_USAGE_SW_READ_OFTEN | GRALLOC_USAGE_SW_WRITE_OFTEN, + reinterpret_cast(&pixels)); // Red top left, Green top right, Blue bottom left, Black bottom right pixels[0] = 255; pixels[1] = 0; @@ -1044,7 +1033,7 @@ void RenderEngineTest::fillRedBufferTextureTransform() { pixels[9] = 0; pixels[10] = 255; pixels[11] = 255; - buf->getBuffer()->unlock(); + buf->unlock(); layer.source.buffer.buffer = buf; layer.source.buffer.textureName = texName; @@ -1072,19 +1061,19 @@ void RenderEngineTest::fillRedBufferWithPremultiplyAlpha() { std::vector layers; renderengine::LayerSettings layer; - const auto buf = allocateSourceBuffer(1, 1); + sp buf = allocateSourceBuffer(1, 1); uint32_t texName; RenderEngineTest::mRE->genTextures(1, &texName); this->mTexNames.push_back(texName); uint8_t* pixels; - buf->getBuffer()->lock(GRALLOC_USAGE_SW_READ_OFTEN | GRALLOC_USAGE_SW_WRITE_OFTEN, - reinterpret_cast(&pixels)); + buf->lock(GRALLOC_USAGE_SW_READ_OFTEN | GRALLOC_USAGE_SW_WRITE_OFTEN, + reinterpret_cast(&pixels)); pixels[0] = 255; pixels[1] = 0; pixels[2] = 0; pixels[3] = 255; - buf->getBuffer()->unlock(); + buf->unlock(); layer.source.buffer.buffer = buf; layer.source.buffer.textureName = texName; @@ -1111,19 +1100,19 @@ void RenderEngineTest::fillRedBufferWithoutPremultiplyAlpha() { std::vector layers; renderengine::LayerSettings layer; - const auto buf = allocateSourceBuffer(1, 1); + sp buf = allocateSourceBuffer(1, 1); uint32_t texName; RenderEngineTest::mRE->genTextures(1, &texName); this->mTexNames.push_back(texName); uint8_t* pixels; - buf->getBuffer()->lock(GRALLOC_USAGE_SW_READ_OFTEN | GRALLOC_USAGE_SW_WRITE_OFTEN, - reinterpret_cast(&pixels)); + buf->lock(GRALLOC_USAGE_SW_READ_OFTEN | GRALLOC_USAGE_SW_WRITE_OFTEN, + reinterpret_cast(&pixels)); pixels[0] = 255; pixels[1] = 0; pixels[2] = 0; pixels[3] = 255; - buf->getBuffer()->unlock(); + buf->unlock(); layer.source.buffer.buffer = buf; layer.source.buffer.textureName = texName; @@ -1244,7 +1233,8 @@ TEST_P(RenderEngineTest, drawLayers_noLayersToDraw) { } TEST_P(RenderEngineTest, drawLayers_withoutBuffers_withColorTransform) { - initializeRenderEngine(); + const auto& renderEngineFactory = GetParam(); + mRE = renderEngineFactory->createRenderEngine(); renderengine::DisplaySettings settings; settings.outputDataspace = ui::Dataspace::V0_SRGB_LINEAR; @@ -1305,6 +1295,7 @@ TEST_P(RenderEngineTest, drawLayers_nullOutputFence) { layers.push_back(&layer); status_t status = mRE->drawLayers(settings, layers, mBuffer, true, base::unique_fd(), nullptr); + mCurrentBuffer = mBuffer; ASSERT_EQ(NO_ERROR, status); expectBufferColor(fullscreenRect(), 255, 0, 0, 255); } @@ -1332,8 +1323,9 @@ TEST_P(RenderEngineTest, drawLayers_doesNotCacheFramebuffer) { layers.push_back(&layer); status_t status = mRE->drawLayers(settings, layers, mBuffer, false, base::unique_fd(), nullptr); + mCurrentBuffer = mBuffer; ASSERT_EQ(NO_ERROR, status); - ASSERT_FALSE(mGLESRE->isFramebufferImageCachedForTesting(mBuffer->getBuffer()->getId())); + ASSERT_FALSE(mGLESRE->isFramebufferImageCachedForTesting(mBuffer->getId())); expectBufferColor(fullscreenRect(), 255, 0, 0, 255); } @@ -1582,6 +1574,98 @@ TEST_P(RenderEngineTest, drawLayers_clearRegion) { clearRegion(); } +TEST_P(RenderEngineTest, drawLayers_fillsBufferAndCachesImages) { + const auto& renderEngineFactory = GetParam(); + + if (renderEngineFactory->type() != renderengine::RenderEngine::RenderEngineType::GLES) { + // GLES-specific test + return; + } + + initializeRenderEngine(); + + renderengine::DisplaySettings settings; + settings.outputDataspace = ui::Dataspace::V0_SRGB_LINEAR; + settings.physicalDisplay = fullscreenRect(); + settings.clip = fullscreenRect(); + + std::vector layers; + + renderengine::LayerSettings layer; + layer.geometry.boundaries = fullscreenRect().toFloatRect(); + BufferSourceVariant::fillColor(layer, 1.0f, 0.0f, 0.0f, this); + + layers.push_back(&layer); + invokeDraw(settings, layers); + uint64_t bufferId = layer.source.buffer.buffer->getId(); + EXPECT_TRUE(mGLESRE->isImageCachedForTesting(bufferId)); + std::shared_ptr barrier = + mGLESRE->unbindExternalTextureBufferForTesting(bufferId); + std::lock_guard lock(barrier->mutex); + ASSERT_TRUE(barrier->condition.wait_for(barrier->mutex, std::chrono::seconds(5), + [&]() REQUIRES(barrier->mutex) { + return barrier->isOpen; + })); + EXPECT_FALSE(mGLESRE->isImageCachedForTesting(bufferId)); + EXPECT_EQ(NO_ERROR, barrier->result); +} + +TEST_P(RenderEngineTest, cacheExternalBuffer_withNullBuffer) { + const auto& renderEngineFactory = GetParam(); + + if (renderEngineFactory->type() != renderengine::RenderEngine::RenderEngineType::GLES) { + // GLES-specific test + return; + } + + initializeRenderEngine(); + + std::shared_ptr barrier = + mGLESRE->cacheExternalTextureBufferForTesting(nullptr); + std::lock_guard lock(barrier->mutex); + ASSERT_TRUE(barrier->condition.wait_for(barrier->mutex, std::chrono::seconds(5), + [&]() REQUIRES(barrier->mutex) { + return barrier->isOpen; + })); + EXPECT_TRUE(barrier->isOpen); + EXPECT_EQ(BAD_VALUE, barrier->result); +} + +TEST_P(RenderEngineTest, cacheExternalBuffer_cachesImages) { + const auto& renderEngineFactory = GetParam(); + + if (renderEngineFactory->type() != renderengine::RenderEngine::RenderEngineType::GLES) { + // GLES-specific test + return; + } + + initializeRenderEngine(); + + sp buf = allocateSourceBuffer(1, 1); + uint64_t bufferId = buf->getId(); + std::shared_ptr barrier = + mGLESRE->cacheExternalTextureBufferForTesting(buf); + { + std::lock_guard lock(barrier->mutex); + ASSERT_TRUE(barrier->condition.wait_for(barrier->mutex, std::chrono::seconds(5), + [&]() REQUIRES(barrier->mutex) { + return barrier->isOpen; + })); + EXPECT_EQ(NO_ERROR, barrier->result); + } + EXPECT_TRUE(mGLESRE->isImageCachedForTesting(bufferId)); + barrier = mGLESRE->unbindExternalTextureBufferForTesting(bufferId); + { + std::lock_guard lock(barrier->mutex); + ASSERT_TRUE(barrier->condition.wait_for(barrier->mutex, std::chrono::seconds(5), + [&]() REQUIRES(barrier->mutex) { + return barrier->isOpen; + })); + EXPECT_EQ(NO_ERROR, barrier->result); + } + EXPECT_FALSE(mGLESRE->isImageCachedForTesting(bufferId)); +} + TEST_P(RenderEngineTest, drawLayers_fillShadow_castsWithoutCasterLayer) { initializeRenderEngine(); @@ -1774,7 +1858,7 @@ TEST_P(RenderEngineTest, cleanupPostRender_whenCleaningAll_replacesTextureMemory sync_wait(fd, -1); } - uint64_t bufferId = layer.source.buffer.buffer->getBuffer()->getId(); + uint64_t bufferId = layer.source.buffer.buffer->getId(); uint32_t texName = layer.source.buffer.textureName; EXPECT_TRUE(mGLESRE->isImageCachedForTesting(bufferId)); EXPECT_EQ(bufferId, mGLESRE->getBufferIdForTextureNameForTesting(texName)); @@ -1882,16 +1966,16 @@ TEST_P(RenderEngineTest, testDisableBlendingBuffer) { // The next layer will overwrite redLayer with a GraphicBuffer that is green // applied with a translucent alpha. - const auto buf = allocateSourceBuffer(1, 1); + auto buf = allocateSourceBuffer(1, 1); { uint8_t* pixels; - buf->getBuffer()->lock(GRALLOC_USAGE_SW_READ_OFTEN | GRALLOC_USAGE_SW_WRITE_OFTEN, - reinterpret_cast(&pixels)); + buf->lock(GRALLOC_USAGE_SW_READ_OFTEN | GRALLOC_USAGE_SW_WRITE_OFTEN, + reinterpret_cast(&pixels)); pixels[0] = 0; pixels[1] = 255; pixels[2] = 0; pixels[3] = 255; - buf->getBuffer()->unlock(); + buf->unlock(); } const renderengine::LayerSettings greenLayer{ diff --git a/libs/renderengine/tests/RenderEngineThreadedTest.cpp b/libs/renderengine/tests/RenderEngineThreadedTest.cpp index e3917cce09..b093e88d4f 100644 --- a/libs/renderengine/tests/RenderEngineThreadedTest.cpp +++ b/libs/renderengine/tests/RenderEngineThreadedTest.cpp @@ -162,18 +162,15 @@ TEST_F(RenderEngineThreadedTest, supportsBackgroundBlur_returnsTrue) { TEST_F(RenderEngineThreadedTest, drawLayers) { renderengine::DisplaySettings settings; std::vector layers; - std::shared_ptr buffer = std::make_shared< - renderengine::ExternalTexture>(new GraphicBuffer(), *mRenderEngine, - renderengine::ExternalTexture::Usage::READABLE | - renderengine::ExternalTexture::Usage::WRITEABLE); + sp buffer = new GraphicBuffer(); base::unique_fd bufferFence; base::unique_fd drawFence; EXPECT_CALL(*mRenderEngine, drawLayers) .WillOnce([](const renderengine::DisplaySettings&, const std::vector&, - const std::shared_ptr&, const bool, - base::unique_fd&&, base::unique_fd*) -> status_t { return NO_ERROR; }); + const sp&, const bool, base::unique_fd&&, + base::unique_fd*) -> status_t { return NO_ERROR; }); status_t result = mThreadedRE->drawLayers(settings, layers, buffer, false, std::move(bufferFence), &drawFence); diff --git a/libs/renderengine/threaded/RenderEngineThreaded.cpp b/libs/renderengine/threaded/RenderEngineThreaded.cpp index c87a836de1..190662be16 100644 --- a/libs/renderengine/threaded/RenderEngineThreaded.cpp +++ b/libs/renderengine/threaded/RenderEngineThreaded.cpp @@ -160,28 +160,27 @@ void RenderEngineThreaded::deleteTextures(size_t count, uint32_t const* names) { resultFuture.wait(); } -void RenderEngineThreaded::mapExternalTextureBuffer(const sp& buffer, - bool isRenderable) { +void RenderEngineThreaded::cacheExternalTextureBuffer(const sp& buffer) { // This function is designed so it can run asynchronously, so we do not need to wait // for the futures. { std::lock_guard lock(mThreadMutex); mFunctionCalls.push([=](renderengine::RenderEngine& instance) { - ATRACE_NAME("REThreaded::mapExternalTextureBuffer"); - instance.mapExternalTextureBuffer(buffer, isRenderable); + ATRACE_NAME("REThreaded::cacheExternalTextureBuffer"); + instance.cacheExternalTextureBuffer(buffer); }); } mCondition.notify_one(); } -void RenderEngineThreaded::unmapExternalTextureBuffer(const sp& buffer) { +void RenderEngineThreaded::unbindExternalTextureBuffer(uint64_t bufferId) { // This function is designed so it can run asynchronously, so we do not need to wait // for the futures. { std::lock_guard lock(mThreadMutex); mFunctionCalls.push([=](renderengine::RenderEngine& instance) { - ATRACE_NAME("REThreaded::unmapExternalTextureBuffer"); - instance.unmapExternalTextureBuffer(buffer); + ATRACE_NAME("REThreaded::unbindExternalTextureBuffer"); + instance.unbindExternalTextureBuffer(bufferId); }); } mCondition.notify_one(); @@ -243,7 +242,7 @@ bool RenderEngineThreaded::cleanupPostRender(CleanupMode mode) { status_t RenderEngineThreaded::drawLayers(const DisplaySettings& display, const std::vector& layers, - const std::shared_ptr& buffer, + const sp& buffer, const bool useFramebufferCache, base::unique_fd&& bufferFence, base::unique_fd* drawFence) { diff --git a/libs/renderengine/threaded/RenderEngineThreaded.h b/libs/renderengine/threaded/RenderEngineThreaded.h index eb6098ed8d..61ae9b8cf8 100644 --- a/libs/renderengine/threaded/RenderEngineThreaded.h +++ b/libs/renderengine/threaded/RenderEngineThreaded.h @@ -48,6 +48,8 @@ public: void genTextures(size_t count, uint32_t* names) override; void deleteTextures(size_t count, uint32_t const* names) override; + void cacheExternalTextureBuffer(const sp& buffer) override; + void unbindExternalTextureBuffer(uint64_t bufferId) override; size_t getMaxTextureSize() const override; size_t getMaxViewportDims() const override; @@ -58,19 +60,14 @@ public: status_t drawLayers(const DisplaySettings& display, const std::vector& layers, - const std::shared_ptr& buffer, - const bool useFramebufferCache, base::unique_fd&& bufferFence, - base::unique_fd* drawFence) override; + const sp& buffer, const bool useFramebufferCache, + base::unique_fd&& bufferFence, base::unique_fd* drawFence) override; void cleanFramebufferCache() override; int getContextPriority() override; bool supportsBackgroundBlur() override; void onPrimaryDisplaySizeChanged(ui::Size size) override; -protected: - void mapExternalTextureBuffer(const sp& buffer, bool isRenderable) override; - void unmapExternalTextureBuffer(const sp& buffer) override; - private: void threadMain(CreateInstanceFactory factory); void waitUntilInitialized() const; diff --git a/services/surfaceflinger/BufferLayer.cpp b/services/surfaceflinger/BufferLayer.cpp index d243989a34..12f63dbbf1 100644 --- a/services/surfaceflinger/BufferLayer.cpp +++ b/services/surfaceflinger/BufferLayer.cpp @@ -188,7 +188,7 @@ std::optional BufferLayer::prepareCli const bool blackOutLayer = (isProtected() && !targetSettings.supportsProtectedContent) || (isSecure() && !targetSettings.isSecure); const bool bufferCanBeUsedAsHwTexture = - mBufferInfo.mBuffer->getBuffer()->getUsage() & GraphicBuffer::USAGE_HW_TEXTURE; + mBufferInfo.mBuffer->getUsage() & GraphicBuffer::USAGE_HW_TEXTURE; compositionengine::LayerFE::LayerSettings& layer = *result; if (blackOutLayer || !bufferCanBeUsedAsHwTexture) { ALOGE_IF(!bufferCanBeUsedAsHwTexture, "%s is blacked out as buffer is not gpu readable", @@ -213,7 +213,7 @@ std::optional BufferLayer::prepareCli ? mBufferInfo.mHdrMetadata.cta8613.maxContentLightLevel : defaultMaxContentLuminance; layer.frameNumber = mCurrentFrameNumber; - layer.bufferId = mBufferInfo.mBuffer ? mBufferInfo.mBuffer->getBuffer()->getId() : 0; + layer.bufferId = mBufferInfo.mBuffer ? mBufferInfo.mBuffer->getId() : 0; const bool useFiltering = targetSettings.needsFiltering || mNeedsFiltering || bufferNeedsFiltering(); @@ -314,7 +314,7 @@ void BufferLayer::preparePerFrameCompositionState() { : Hwc2::IComposerClient::Composition::DEVICE; } - compositionState->buffer = mBufferInfo.mBuffer->getBuffer(); + compositionState->buffer = mBufferInfo.mBuffer; compositionState->bufferSlot = (mBufferInfo.mBufferSlot == BufferQueue::INVALID_BUFFER_SLOT) ? 0 : mBufferInfo.mBufferSlot; @@ -442,7 +442,7 @@ bool BufferLayer::onPostComposition(const DisplayDevice* display, void BufferLayer::gatherBufferInfo() { mBufferInfo.mPixelFormat = - !mBufferInfo.mBuffer ? PIXEL_FORMAT_NONE : mBufferInfo.mBuffer->getBuffer()->format; + !mBufferInfo.mBuffer ? PIXEL_FORMAT_NONE : mBufferInfo.mBuffer->format; mBufferInfo.mFrameLatencyNeeded = true; } @@ -539,10 +539,10 @@ bool BufferLayer::latchBuffer(bool& recomputeVisibleRegions, nsecs_t latchTime, } if (oldBufferInfo.mBuffer != nullptr) { - uint32_t bufWidth = mBufferInfo.mBuffer->getBuffer()->getWidth(); - uint32_t bufHeight = mBufferInfo.mBuffer->getBuffer()->getHeight(); - if (bufWidth != uint32_t(oldBufferInfo.mBuffer->getBuffer()->width) || - bufHeight != uint32_t(oldBufferInfo.mBuffer->getBuffer()->height)) { + 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; } } @@ -563,8 +563,8 @@ uint32_t BufferLayer::getEffectiveScalingMode() const { } bool BufferLayer::isProtected() const { - return (mBufferInfo.mBuffer != nullptr) && - (mBufferInfo.mBuffer->getBuffer()->getUsage() & GRALLOC_USAGE_PROTECTED); + const sp& buffer(mBufferInfo.mBuffer); + return (buffer != 0) && (buffer->getUsage() & GRALLOC_USAGE_PROTECTED); } // As documented in libhardware header, formats in the range @@ -651,8 +651,8 @@ Rect BufferLayer::getBufferSize(const State& s) const { return Rect::INVALID_RECT; } - uint32_t bufWidth = mBufferInfo.mBuffer->getBuffer()->getWidth(); - uint32_t bufHeight = mBufferInfo.mBuffer->getBuffer()->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) { @@ -683,8 +683,8 @@ FloatRect BufferLayer::computeSourceBounds(const FloatRect& parentBounds) const return parentBounds; } - uint32_t bufWidth = mBufferInfo.mBuffer->getBuffer()->getWidth(); - uint32_t bufHeight = mBufferInfo.mBuffer->getBuffer()->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) { @@ -726,7 +726,7 @@ Rect BufferLayer::getBufferCrop() const { return mBufferInfo.mCrop; } else if (mBufferInfo.mBuffer != nullptr) { // otherwise we use the whole buffer - return mBufferInfo.mBuffer->getBuffer()->getBounds(); + return mBufferInfo.mBuffer->getBounds(); } else { // if we don't have a buffer yet, we use an empty/invalid crop return Rect(); @@ -771,14 +771,12 @@ ui::Dataspace BufferLayer::translateDataspace(ui::Dataspace dataspace) { } sp BufferLayer::getBuffer() const { - return mBufferInfo.mBuffer ? mBufferInfo.mBuffer->getBuffer() : nullptr; + return mBufferInfo.mBuffer; } void BufferLayer::getDrawingTransformMatrix(bool filteringEnabled, float outMatrix[16]) { - GLConsumer::computeTransformMatrix(outMatrix, - mBufferInfo.mBuffer ? mBufferInfo.mBuffer->getBuffer() - : nullptr, - mBufferInfo.mCrop, mBufferInfo.mTransform, filteringEnabled); + GLConsumer::computeTransformMatrix(outMatrix, mBufferInfo.mBuffer, mBufferInfo.mCrop, + mBufferInfo.mTransform, filteringEnabled); } void BufferLayer::setInitialValuesForClone(const sp& clonedFrom) { diff --git a/services/surfaceflinger/BufferLayer.h b/services/surfaceflinger/BufferLayer.h index cd3d80e809..0a5235aa08 100644 --- a/services/surfaceflinger/BufferLayer.h +++ b/services/surfaceflinger/BufferLayer.h @@ -132,7 +132,7 @@ protected: PixelFormat mPixelFormat{PIXEL_FORMAT_NONE}; bool mTransformToDisplayInverse{false}; - std::shared_ptr mBuffer; + sp mBuffer; int mBufferSlot{BufferQueue::INVALID_BUFFER_SLOT}; bool mFrameLatencyNeeded{false}; diff --git a/services/surfaceflinger/BufferLayerConsumer.cpp b/services/surfaceflinger/BufferLayerConsumer.cpp index 96b22478ab..69d2d11a4d 100644 --- a/services/surfaceflinger/BufferLayerConsumer.cpp +++ b/services/surfaceflinger/BufferLayerConsumer.cpp @@ -40,6 +40,7 @@ #include #include #include +#include #include #include #include @@ -166,7 +167,7 @@ void BufferLayerConsumer::setReleaseFence(const sp& fence) { } auto buffer = mPendingRelease.isPending ? mPendingRelease.graphicBuffer - : mCurrentTextureBuffer->getBuffer(); + : mCurrentTextureBuffer->graphicBuffer(); auto err = addReleaseFence(slot, buffer, fence); if (err != OK) { BLC_LOGE("setReleaseFence: failed to add the fence: %s (%d)", strerror(-err), err); @@ -205,11 +206,9 @@ status_t BufferLayerConsumer::acquireBufferLocked(BufferItem* item, nsecs_t pres // before, so we need to clean up old references. if (item->mGraphicBuffer != nullptr) { std::lock_guard lock(mImagesMutex); - if (mImages[item->mSlot] == nullptr || mImages[item->mSlot]->getBuffer() == nullptr || - mImages[item->mSlot]->getBuffer()->getId() != item->mGraphicBuffer->getId()) { - mImages[item->mSlot] = std::make_shared< - renderengine::ExternalTexture>(item->mGraphicBuffer, mRE, - renderengine::ExternalTexture::Usage::READABLE); + if (mImages[item->mSlot] == nullptr || mImages[item->mSlot]->graphicBuffer() == nullptr || + mImages[item->mSlot]->graphicBuffer()->getId() != item->mGraphicBuffer->getId()) { + mImages[item->mSlot] = std::make_shared(item->mGraphicBuffer, mRE); } } @@ -223,8 +222,8 @@ status_t BufferLayerConsumer::updateAndReleaseLocked(const BufferItem& item, int slot = item.mSlot; BLC_LOGV("updateAndRelease: (slot=%d buf=%p) -> (slot=%d buf=%p)", mCurrentTexture, - (mCurrentTextureBuffer != nullptr && mCurrentTextureBuffer->getBuffer() != nullptr) - ? mCurrentTextureBuffer->getBuffer()->handle + (mCurrentTextureBuffer != nullptr && mCurrentTextureBuffer->graphicBuffer() != nullptr) + ? mCurrentTextureBuffer->graphicBuffer()->handle : 0, slot, mSlots[slot].mGraphicBuffer->handle); @@ -232,7 +231,7 @@ status_t BufferLayerConsumer::updateAndReleaseLocked(const BufferItem& item, // releaseBufferLocked() if we're in shared buffer mode and both buffers are // the same. - std::shared_ptr nextTextureBuffer; + std::shared_ptr nextTextureBuffer; { std::lock_guard lock(mImagesMutex); nextTextureBuffer = mImages[slot]; @@ -242,7 +241,7 @@ status_t BufferLayerConsumer::updateAndReleaseLocked(const BufferItem& item, if (mCurrentTexture != BufferQueue::INVALID_BUFFER_SLOT) { if (pendingRelease == nullptr) { status_t status = - releaseBufferLocked(mCurrentTexture, mCurrentTextureBuffer->getBuffer()); + releaseBufferLocked(mCurrentTexture, mCurrentTextureBuffer->graphicBuffer()); if (status < NO_ERROR) { BLC_LOGE("updateAndRelease: failed to release buffer: %s (%d)", strerror(-status), status); @@ -251,7 +250,7 @@ status_t BufferLayerConsumer::updateAndReleaseLocked(const BufferItem& item, } } else { pendingRelease->currentTexture = mCurrentTexture; - pendingRelease->graphicBuffer = mCurrentTextureBuffer->getBuffer(); + pendingRelease->graphicBuffer = mCurrentTextureBuffer->graphicBuffer(); pendingRelease->isPending = true; } } @@ -302,14 +301,14 @@ void BufferLayerConsumer::setFilteringEnabled(bool enabled) { void BufferLayerConsumer::computeCurrentTransformMatrixLocked() { BLC_LOGV("computeCurrentTransformMatrixLocked"); - if (mCurrentTextureBuffer == nullptr || mCurrentTextureBuffer->getBuffer() == nullptr) { + if (mCurrentTextureBuffer == nullptr || mCurrentTextureBuffer->graphicBuffer() == nullptr) { BLC_LOGD("computeCurrentTransformMatrixLocked: " "mCurrentTextureBuffer is nullptr"); } GLConsumer::computeTransformMatrix(mCurrentTransformMatrix, mCurrentTextureBuffer == nullptr ? nullptr - : mCurrentTextureBuffer->getBuffer(), + : mCurrentTextureBuffer->graphicBuffer(), getCurrentCropLocked(), mCurrentTransform, mFilteringEnabled); } @@ -361,8 +360,7 @@ int BufferLayerConsumer::getCurrentApi() const { return mCurrentApi; } -std::shared_ptr BufferLayerConsumer::getCurrentBuffer( - int* outSlot, sp* outFence) const { +sp BufferLayerConsumer::getCurrentBuffer(int* outSlot, sp* outFence) const { Mutex::Autolock lock(mMutex); if (outSlot != nullptr) { @@ -373,7 +371,7 @@ std::shared_ptr BufferLayerConsumer::getCurrentBu *outFence = mCurrentFence; } - return mCurrentTextureBuffer == nullptr ? nullptr : mCurrentTextureBuffer; + return mCurrentTextureBuffer == nullptr ? nullptr : mCurrentTextureBuffer->graphicBuffer(); } Rect BufferLayerConsumer::getCurrentCrop() const { @@ -458,12 +456,10 @@ void BufferLayerConsumer::onSidebandStreamChanged() { void BufferLayerConsumer::onBufferAvailable(const BufferItem& item) { if (item.mGraphicBuffer != nullptr && item.mSlot != BufferQueue::INVALID_BUFFER_SLOT) { std::lock_guard lock(mImagesMutex); - const std::shared_ptr& oldImage = mImages[item.mSlot]; - if (oldImage == nullptr || oldImage->getBuffer() == nullptr || - oldImage->getBuffer()->getId() != item.mGraphicBuffer->getId()) { - mImages[item.mSlot] = std::make_shared< - renderengine::ExternalTexture>(item.mGraphicBuffer, mRE, - renderengine::ExternalTexture::Usage::READABLE); + const std::shared_ptr& oldImage = mImages[item.mSlot]; + if (oldImage == nullptr || oldImage->graphicBuffer() == nullptr || + oldImage->graphicBuffer()->getId() != item.mGraphicBuffer->getId()) { + mImages[item.mSlot] = std::make_shared(item.mGraphicBuffer, mRE); } } } @@ -503,6 +499,22 @@ void BufferLayerConsumer::dumpLocked(String8& result, const char* prefix) const ConsumerBase::dumpLocked(result, prefix); } + +BufferLayerConsumer::Image::Image(const sp& graphicBuffer, + renderengine::RenderEngine& engine) + : mGraphicBuffer(graphicBuffer), mRE(engine) { + if (graphicBuffer != nullptr && (graphicBuffer->getUsage() & GRALLOC_USAGE_PROTECTED)) { + return; + } + mRE.cacheExternalTextureBuffer(mGraphicBuffer); +} + +BufferLayerConsumer::Image::~Image() { + if (mGraphicBuffer != nullptr) { + ALOGV("Destroying buffer: %" PRId64, mGraphicBuffer->getId()); + mRE.unbindExternalTextureBuffer(mGraphicBuffer->getId()); + } +} }; // namespace android // TODO(b/129481165): remove the #pragma below and fix conversion issues diff --git a/services/surfaceflinger/BufferLayerConsumer.h b/services/surfaceflinger/BufferLayerConsumer.h index 9ed80b46bd..dd39214aff 100644 --- a/services/surfaceflinger/BufferLayerConsumer.h +++ b/services/surfaceflinger/BufferLayerConsumer.h @@ -21,11 +21,12 @@ #include #include #include -#include + #include #include #include #include + #include #include #include @@ -38,6 +39,7 @@ class String8; namespace renderengine { class RenderEngine; +class Image; } // namespace renderengine /* @@ -151,8 +153,7 @@ public: // When outSlot is not nullptr, the current buffer slot index is also // returned. Simiarly, when outFence is not nullptr, the current output // fence is returned. - std::shared_ptr getCurrentBuffer( - int* outSlot = nullptr, sp* outFence = nullptr) const; + sp getCurrentBuffer(int* outSlot = nullptr, sp* outFence = nullptr) const; // getCurrentCrop returns the cropping rectangle of the current buffer. Rect getCurrentCrop() const; @@ -257,7 +258,7 @@ private: // mCurrentTextureBuffer is the buffer containing the current texture. It's // possible that this buffer is not associated with any buffer slot, so we // must track it separately in order to support the getCurrentBuffer method. - std::shared_ptr mCurrentTextureBuffer; + std::shared_ptr mCurrentTextureBuffer; // mCurrentCrop is the crop rectangle that applies to the current texture. // It gets set each time updateTexImage is called. @@ -336,8 +337,7 @@ private: int mCurrentTexture; // Shadow buffer cache for cleaning up renderengine references. - std::shared_ptr - mImages[BufferQueueDefs::NUM_BUFFER_SLOTS] GUARDED_BY(mImagesMutex); + std::shared_ptr mImages[BufferQueueDefs::NUM_BUFFER_SLOTS] GUARDED_BY(mImagesMutex); // Separate mutex guarding the shadow buffer cache. // mImagesMutex can be manipulated with binder threads (e.g. onBuffersAllocated) diff --git a/services/surfaceflinger/BufferStateLayer.cpp b/services/surfaceflinger/BufferStateLayer.cpp index ac2edbe717..fa9cecf787 100644 --- a/services/surfaceflinger/BufferStateLayer.cpp +++ b/services/surfaceflinger/BufferStateLayer.cpp @@ -71,8 +71,14 @@ BufferStateLayer::~BufferStateLayer() { // 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()) { - callReleaseBufferCallback(mDrawingState.releaseBufferListener, - mBufferInfo.mBuffer->getBuffer(), mBufferInfo.mFence); + // 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()); + const uint64_t bufferId = mBufferInfo.mBuffer->getId(); + engine.unbindExternalTextureBuffer(bufferId); + callReleaseBufferCallback(mDrawingState.releaseBufferListener, mBufferInfo.mBuffer, + mBufferInfo.mFence); } } @@ -338,9 +344,8 @@ bool BufferStateLayer::addFrameEvent(const sp& acquireFence, nsecs_t post return true; } -bool BufferStateLayer::setBuffer(const std::shared_ptr& buffer, - const sp& acquireFence, nsecs_t postTime, - nsecs_t desiredPresentTime, bool isAutoTimestamp, +bool BufferStateLayer::setBuffer(const sp& buffer, const sp& acquireFence, + nsecs_t postTime, nsecs_t desiredPresentTime, bool isAutoTimestamp, const client_cache_t& clientCacheId, uint64_t frameNumber, std::optional dequeueTime, const FrameTimelineInfo& info, const sp& releaseBufferListener) { @@ -348,14 +353,12 @@ bool BufferStateLayer::setBuffer(const std::shared_ptrgetBuffer() != mDrawingState.buffer->getBuffer()) { + if (mCurrentState.buffer != mDrawingState.buffer) { // If mCurrentState has a buffer, and we are about to update again // before swapping to drawing state, then the first buffer will be // dropped and we should decrement the pending buffer count and // call any release buffer callbacks if set. - callReleaseBufferCallback(mCurrentState.releaseBufferListener, - mCurrentState.buffer->getBuffer(), + callReleaseBufferCallback(mCurrentState.releaseBufferListener, mCurrentState.buffer, mCurrentState.acquireFence); decrementPendingBufferCount(); if (mCurrentState.bufferSurfaceFrameTX != nullptr) { @@ -393,8 +396,8 @@ bool BufferStateLayer::setBuffer(const std::shared_ptrgetBuffer()->getId(); + if (dequeueTime && *dequeueTime != 0) { + const uint64_t bufferId = buffer->getId(); mFlinger->mFrameTracer->traceNewLayer(layerId, getName().c_str()); mFlinger->mFrameTracer->traceTimestamp(layerId, bufferId, frameNumber, *dequeueTime, FrameTracer::FrameEvent::DEQUEUE); @@ -402,8 +405,8 @@ bool BufferStateLayer::setBuffer(const std::shared_ptrgetBuffer()->getWidth(); - mCurrentState.height = mCurrentState.buffer->getBuffer()->getHeight(); + mCurrentState.width = mCurrentState.buffer->width; + mCurrentState.height = mCurrentState.buffer->height; return true; } @@ -652,7 +655,7 @@ status_t BufferStateLayer::updateTexImage(bool& /*recomputeVisibleRegions*/, nse } const int32_t layerId = getSequence(); - const uint64_t bufferId = mDrawingState.buffer->getBuffer()->getId(); + const uint64_t bufferId = mDrawingState.buffer->getId(); const uint64_t frameNumber = mDrawingState.frameNumber; const auto acquireFence = std::make_shared(mDrawingState.acquireFence); mFlinger->mTimeStats->setAcquireFence(layerId, frameNumber, acquireFence); @@ -686,7 +689,7 @@ status_t BufferStateLayer::updateActiveBuffer() { return BAD_VALUE; } - if (!mBufferInfo.mBuffer || s.buffer->getBuffer() != mBufferInfo.mBuffer->getBuffer()) { + if (s.buffer != mBufferInfo.mBuffer) { decrementPendingBufferCount(); } @@ -805,13 +808,13 @@ uint32_t BufferStateLayer::getEffectiveScalingMode() const { Rect BufferStateLayer::computeCrop(const State& s) { if (s.crop.isEmpty() && s.buffer) { - return s.buffer->getBuffer()->getBounds(); + 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->getBuffer()->getWidth(); - uint32_t bufferHeight = s.buffer->getBuffer()->getHeight(); + 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)); @@ -819,7 +822,7 @@ Rect BufferStateLayer::computeCrop(const State& s) { } if (!crop.isValid()) { // Crop rect is out of bounds, return whole buffer - return s.buffer->getBuffer()->getBounds(); + return s.buffer->getBounds(); } return crop; } @@ -841,8 +844,8 @@ bool BufferStateLayer::bufferNeedsFiltering() const { return false; } - uint32_t bufferWidth = s.buffer->getBuffer()->width; - uint32_t bufferHeight = s.buffer->getBuffer()->height; + uint32_t bufferWidth = s.buffer->width; + uint32_t bufferHeight = s.buffer->height; // Undo any transformations on the buffer and return the result. if (s.bufferTransform & ui::Transform::ROT_90) { @@ -869,16 +872,14 @@ void BufferStateLayer::tracePendingBufferCount(int32_t pendingBuffers) { ATRACE_INT(mBlastTransactionName.c_str(), pendingBuffers); } -void BufferStateLayer::bufferMayChange(const sp& newBuffer) { - if (mDrawingState.buffer != nullptr && - (!mBufferInfo.mBuffer || - mDrawingState.buffer->getBuffer() != mBufferInfo.mBuffer->getBuffer()) && - newBuffer != mDrawingState.buffer->getBuffer()) { +void BufferStateLayer::bufferMayChange(sp& newBuffer) { + if (mDrawingState.buffer != nullptr && mDrawingState.buffer != mBufferInfo.mBuffer && + newBuffer != mDrawingState.buffer) { // If we are about to update mDrawingState.buffer but it has not yet latched // then we will drop a buffer and should decrement the pending buffer count and // call any release buffer callbacks if set. - callReleaseBufferCallback(mDrawingState.releaseBufferListener, - mDrawingState.buffer->getBuffer(), mDrawingState.acquireFence); + callReleaseBufferCallback(mDrawingState.releaseBufferListener, mDrawingState.buffer, + mDrawingState.acquireFence); decrementPendingBufferCount(); } } diff --git a/services/surfaceflinger/BufferStateLayer.h b/services/surfaceflinger/BufferStateLayer.h index 4171092b58..24e0ad290f 100644 --- a/services/surfaceflinger/BufferStateLayer.h +++ b/services/surfaceflinger/BufferStateLayer.h @@ -62,9 +62,9 @@ public: bool setTransform(uint32_t transform) override; bool setTransformToDisplayInverse(bool transformToDisplayInverse) override; bool setCrop(const Rect& crop) override; - bool setBuffer(const std::shared_ptr& buffer, - const sp& acquireFence, nsecs_t postTime, nsecs_t desiredPresentTime, - bool isAutoTimestamp, const client_cache_t& clientCacheId, uint64_t frameNumber, + bool setBuffer(const sp& buffer, const sp& acquireFence, nsecs_t postTime, + nsecs_t desiredPresentTime, bool isAutoTimestamp, + const client_cache_t& clientCacheId, uint64_t frameNumber, std::optional dequeueTime, const FrameTimelineInfo& info, const sp& transactionListener) override; bool setAcquireFence(const sp& fence) override; @@ -100,7 +100,7 @@ public: // See mPendingBufferTransactions void decrementPendingBufferCount(); - void bufferMayChange(const sp& newBuffer) override; + void bufferMayChange(sp& newBuffer) override; std::atomic* getPendingBufferCounter() override { return &mPendingBufferTransactions; } std::string getPendingBufferCounterName() override { return mBlastTransactionName; } diff --git a/services/surfaceflinger/ClientCache.cpp b/services/surfaceflinger/ClientCache.cpp index f310738423..44b33ef43d 100644 --- a/services/surfaceflinger/ClientCache.cpp +++ b/services/surfaceflinger/ClientCache.cpp @@ -102,12 +102,7 @@ bool ClientCache::add(const client_cache_t& cacheId, const sp& bu return false; } - LOG_ALWAYS_FATAL_IF(mRenderEngine == nullptr, - "Attempted to build the ClientCache before a RenderEngine instance was " - "ready!"); - processBuffers[id].buffer = std::make_shared< - renderengine::ExternalTexture>(buffer, *mRenderEngine, - renderengine::ExternalTexture::Usage::READABLE); + processBuffers[id].buffer = buffer; return true; } @@ -137,7 +132,7 @@ void ClientCache::erase(const client_cache_t& cacheId) { } } -std::shared_ptr ClientCache::get(const client_cache_t& cacheId) { +sp ClientCache::get(const client_cache_t& cacheId) { std::lock_guard lock(mMutex); ClientCacheBuffer* buf = nullptr; @@ -218,8 +213,8 @@ void ClientCache::dump(std::string& result) { auto &buffers = i.second.second; for (auto& [id, clientCacheBuffer] : buffers) { StringAppendF(&result, "\t ID: %d, Width/Height: %d,%d\n", (int)id, - (int)clientCacheBuffer.buffer->getBuffer()->getWidth(), - (int)clientCacheBuffer.buffer->getBuffer()->getHeight()); + (int)clientCacheBuffer.buffer->getWidth(), + (int)clientCacheBuffer.buffer->getHeight()); } } } diff --git a/services/surfaceflinger/ClientCache.h b/services/surfaceflinger/ClientCache.h index a9b8177d70..0d597c8e05 100644 --- a/services/surfaceflinger/ClientCache.h +++ b/services/surfaceflinger/ClientCache.h @@ -19,7 +19,6 @@ #include #include #include -#include #include #include #include @@ -40,11 +39,7 @@ public: bool add(const client_cache_t& cacheId, const sp& buffer); void erase(const client_cache_t& cacheId); - std::shared_ptr get(const client_cache_t& cacheId); - - // Always called immediately after setup. Will be set to non-null, and then should never be - // called again. - void setRenderEngine(renderengine::RenderEngine* renderEngine) { mRenderEngine = renderEngine; } + sp get(const client_cache_t& cacheId); void removeProcess(const wp& processToken); @@ -64,7 +59,7 @@ private: std::mutex mMutex; struct ClientCacheBuffer { - std::shared_ptr buffer; + sp buffer; std::set> recipients; }; std::map /*caching process*/, @@ -78,7 +73,6 @@ private: }; sp mDeathRecipient; - renderengine::RenderEngine* mRenderEngine = nullptr; bool getBuffer(const client_cache_t& cacheId, ClientCacheBuffer** outClientCacheBuffer) REQUIRES(mMutex); diff --git a/services/surfaceflinger/CompositionEngine/include/compositionengine/RenderSurface.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/RenderSurface.h index daee83bd2c..f680460242 100644 --- a/services/surfaceflinger/CompositionEngine/include/compositionengine/RenderSurface.h +++ b/services/surfaceflinger/CompositionEngine/include/compositionengine/RenderSurface.h @@ -16,16 +16,15 @@ #pragma once -#include +#include +#include + #include #include #include #include #include -#include -#include - namespace android { class GraphicBuffer; @@ -81,8 +80,7 @@ public: virtual void prepareFrame(bool usesClientComposition, bool usesDeviceComposition) = 0; // Allocates a buffer as scratch space for GPU composition - virtual std::shared_ptr dequeueBuffer( - base::unique_fd* bufferFence) = 0; + virtual sp dequeueBuffer(base::unique_fd* bufferFence) = 0; // Queues the drawn buffer for consumption by HWC. readyFence is the fence // which will fire when the buffer is ready for consumption. diff --git a/services/surfaceflinger/CompositionEngine/include/compositionengine/RenderSurfaceCreationArgs.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/RenderSurfaceCreationArgs.h index a8d372c562..a1230b3c4d 100644 --- a/services/surfaceflinger/CompositionEngine/include/compositionengine/RenderSurfaceCreationArgs.h +++ b/services/surfaceflinger/CompositionEngine/include/compositionengine/RenderSurfaceCreationArgs.h @@ -45,8 +45,6 @@ struct RenderSurfaceCreationArgs { // The DisplaySurface for this surface sp displaySurface; - - size_t maxTextureCacheSize; }; /** @@ -83,11 +81,6 @@ public: return *this; } - RenderSurfaceCreationArgsBuilder& setMaxTextureCacheSize(size_t maxTextureCacheSize) { - mArgs.maxTextureCacheSize = maxTextureCacheSize; - return *this; - } - private: RenderSurfaceCreationArgs mArgs; }; diff --git a/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/OutputLayerCompositionState.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/OutputLayerCompositionState.h index c61ec5991b..48a54d6c66 100644 --- a/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/OutputLayerCompositionState.h +++ b/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/OutputLayerCompositionState.h @@ -18,7 +18,7 @@ #include #include -#include +#include #include #include #include @@ -89,7 +89,7 @@ struct OutputLayerCompositionState { // Overrides the buffer, acquire fence, and display frame stored in LayerFECompositionState struct { - std::shared_ptr buffer = nullptr; + sp buffer = nullptr; sp acquireFence = nullptr; Rect displayFrame = {}; ui::Dataspace dataspace{ui::Dataspace::UNKNOWN}; diff --git a/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/RenderSurface.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/RenderSurface.h index a8a538003e..5127a6f314 100644 --- a/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/RenderSurface.h +++ b/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/RenderSurface.h @@ -16,16 +16,12 @@ #pragma once +#include + #include #include #include -#include -#include - -#include "renderengine/ExternalTexture.h" -#include "renderengine/RenderEngine.h" - struct ANativeWindow; namespace android { @@ -58,8 +54,7 @@ public: void setProtected(bool useProtected) override; status_t beginFrame(bool mustRecompose) override; void prepareFrame(bool usesClientComposition, bool usesDeviceComposition) override; - std::shared_ptr dequeueBuffer( - base::unique_fd* bufferFence) override; + sp dequeueBuffer(base::unique_fd* bufferFence) override; void queueBuffer(base::unique_fd readyFence) override; void onPresentDisplayCompleted() override; void flip() override; @@ -71,7 +66,7 @@ public: // Testing void setPageFlipCountForTest(std::uint32_t); void setSizeForTest(const ui::Size&); - std::shared_ptr& mutableTextureForTest(); + sp& mutableGraphicBufferForTest(); base::unique_fd& mutableBufferReadyForTest(); private: @@ -80,13 +75,10 @@ private: // ANativeWindow being rendered into const sp mNativeWindow; - - std::vector> mTextureCache; - // Current texture being rendered into - std::shared_ptr mTexture; + // Current buffer being rendered into + sp mGraphicBuffer; const sp mDisplaySurface; ui::Size mSize; - const size_t mMaxTextureCacheSize; bool mProtected{false}; std::uint32_t mPageFlipCount{0}; }; diff --git a/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/planner/CachedSet.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/planner/CachedSet.h index 53f4a30fb8..c5d03a7218 100644 --- a/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/planner/CachedSet.h +++ b/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/planner/CachedSet.h @@ -66,7 +66,7 @@ public: const Rect& getBounds() const { return mBounds; } const Region& getVisibleRegion() const { return mVisibleRegion; } size_t getAge() const { return mAge; } - const std::shared_ptr& getBuffer() const { return mTexture; } + const sp& getBuffer() const { return mTexture.getBuffer(); } const sp& getDrawFence() const { return mDrawFence; } const ProjectionSpace& getOutputSpace() const { return mOutputSpace; } ui::Dataspace getOutputDataspace() const { return mOutputDataspace; } @@ -87,7 +87,7 @@ public: void setLastUpdate(std::chrono::steady_clock::time_point now) { mLastUpdate = now; } void append(const CachedSet& other) { - mTexture = nullptr; + mTexture.setBuffer(nullptr, nullptr); mOutputDataspace = ui::Dataspace::UNKNOWN; mDrawFence = nullptr; @@ -115,7 +115,31 @@ private: Region mVisibleRegion; size_t mAge = 0; - std::shared_ptr mTexture; + class Texture { + public: + ~Texture() { setBuffer(nullptr, nullptr); } + + void setBuffer(const sp& buffer, renderengine::RenderEngine* re) { + if (mRE && mBuffer) { + mRE->unbindExternalTextureBuffer(mBuffer->getId()); + } + + mBuffer = buffer; + mRE = re; + + if (mRE && mBuffer) { + mRE->cacheExternalTextureBuffer(mBuffer); + } + } + + const sp& getBuffer() const { return mBuffer; } + + private: + sp mBuffer = nullptr; + renderengine::RenderEngine* mRE = nullptr; + }; + + Texture mTexture; sp mDrawFence; ProjectionSpace mOutputSpace; ui::Dataspace mOutputDataspace; diff --git a/services/surfaceflinger/CompositionEngine/include/compositionengine/mock/RenderSurface.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/mock/RenderSurface.h index fe858c2817..a0cae6fcbb 100644 --- a/services/surfaceflinger/CompositionEngine/include/compositionengine/mock/RenderSurface.h +++ b/services/surfaceflinger/CompositionEngine/include/compositionengine/mock/RenderSurface.h @@ -39,7 +39,7 @@ public: MOCK_METHOD1(setBufferPixelFormat, void(ui::PixelFormat)); MOCK_METHOD1(beginFrame, status_t(bool mustRecompose)); MOCK_METHOD2(prepareFrame, void(bool, bool)); - MOCK_METHOD1(dequeueBuffer, std::shared_ptr(base::unique_fd*)); + MOCK_METHOD1(dequeueBuffer, sp(base::unique_fd*)); MOCK_METHOD1(queueBuffer, void(base::unique_fd)); MOCK_METHOD0(onPresentDisplayCompleted, void()); MOCK_METHOD0(flip, void()); diff --git a/services/surfaceflinger/CompositionEngine/src/Output.cpp b/services/surfaceflinger/CompositionEngine/src/Output.cpp index 3468b204fc..3ac5433457 100644 --- a/services/surfaceflinger/CompositionEngine/src/Output.cpp +++ b/services/surfaceflinger/CompositionEngine/src/Output.cpp @@ -14,7 +14,8 @@ * limitations under the License. */ -#include +#include + #include #include #include @@ -28,9 +29,7 @@ #include #include -#include - -#include "renderengine/ExternalTexture.h" +#include // TODO(b/129481165): remove the #pragma below and fix conversion issues #pragma clang diagnostic push @@ -716,11 +715,11 @@ void Output::writeCompositionState(const compositionengine::CompositionRefreshAr bool skipLayer = false; if (layer->getState().overrideInfo.buffer != nullptr) { if (previousOverride != nullptr && - layer->getState().overrideInfo.buffer->getBuffer() == previousOverride) { + layer->getState().overrideInfo.buffer == previousOverride) { ALOGV("Skipping redundant buffer"); skipLayer = true; } - previousOverride = layer->getState().overrideInfo.buffer->getBuffer(); + previousOverride = layer->getState().overrideInfo.buffer; } const bool includeGeometry = refreshArgs.updatingGeometryThisFrame; @@ -979,15 +978,14 @@ std::optional Output::composeSurfaces( } base::unique_fd fd; - - std::shared_ptr tex; + sp buf; // If we aren't doing client composition on this output, but do have a // flipClientTarget request for this frame on this output, we still need to // dequeue a buffer. if (hasClientComposition || outputState.flipClientTarget) { - tex = mRenderSurface->dequeueBuffer(&fd); - if (tex == nullptr) { + 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()); @@ -1032,14 +1030,13 @@ std::optional Output::composeSurfaces( // Check if the client composition requests were rendered into the provided graphic buffer. If // so, we can reuse the buffer and avoid client composition. if (mClientCompositionRequestCache) { - if (mClientCompositionRequestCache->exists(tex->getBuffer()->getId(), - clientCompositionDisplay, + if (mClientCompositionRequestCache->exists(buf->getId(), clientCompositionDisplay, clientCompositionLayers)) { outputCompositionState.reusedClientComposition = true; setExpensiveRenderingExpected(false); return readyFence; } - mClientCompositionRequestCache->add(tex->getBuffer()->getId(), clientCompositionDisplay, + mClientCompositionRequestCache->add(buf->getId(), clientCompositionDisplay, clientCompositionLayers); } @@ -1072,12 +1069,12 @@ std::optional Output::composeSurfaces( // over to RenderEngine, in which case this flag can be removed from the drawLayers interface. const bool useFramebufferCache = outputState.layerStackInternal; status_t status = - renderEngine.drawLayers(clientCompositionDisplay, clientCompositionLayerPointers, tex, + renderEngine.drawLayers(clientCompositionDisplay, clientCompositionLayerPointers, buf, useFramebufferCache, std::move(fd), &readyFence); if (status != NO_ERROR && mClientCompositionRequestCache) { // If rendering was not successful, remove the request from the cache. - mClientCompositionRequestCache->remove(tex->getBuffer()->getId()); + mClientCompositionRequestCache->remove(buf->getId()); } auto& timeStats = getCompositionEngine().getTimeStats(); @@ -1154,9 +1151,9 @@ std::vector Output::generateClientCompositionRequests( std::vector results; if (layer->getState().overrideInfo.buffer != nullptr) { - if (layer->getState().overrideInfo.buffer->getBuffer() != previousOverrideBuffer) { + if (layer->getState().overrideInfo.buffer != previousOverrideBuffer) { results = layer->getOverrideCompositionList(); - previousOverrideBuffer = layer->getState().overrideInfo.buffer->getBuffer(); + previousOverrideBuffer = layer->getState().overrideInfo.buffer; ALOGV("Replacing [%s] with override in RE", layer->getLayerFE().getDebugName()); } else { ALOGV("Skipping redundant override buffer for [%s] in RE", diff --git a/services/surfaceflinger/CompositionEngine/src/OutputLayer.cpp b/services/surfaceflinger/CompositionEngine/src/OutputLayer.cpp index 9ca8914deb..f640f85bca 100644 --- a/services/surfaceflinger/CompositionEngine/src/OutputLayer.cpp +++ b/services/surfaceflinger/CompositionEngine/src/OutputLayer.cpp @@ -537,7 +537,7 @@ void OutputLayer::writeBufferStateToHWC(HWC2::Layer* hwcLayer, sp buffer = outputIndependentState.buffer; sp acquireFence = outputIndependentState.acquireFence; if (getState().overrideInfo.buffer != nullptr) { - buffer = getState().overrideInfo.buffer->getBuffer(); + buffer = getState().overrideInfo.buffer; acquireFence = getState().overrideInfo.acquireFence; } @@ -699,7 +699,7 @@ std::vector OutputLayer::getOverrideCompositionList() co settings.geometry = renderengine::Geometry{ .boundaries = boundaries.toFloatRect(), }; - settings.bufferId = getState().overrideInfo.buffer->getBuffer()->getId(); + settings.bufferId = getState().overrideInfo.buffer->getId(); settings.source = renderengine::PixelSource{ .buffer = renderengine::Buffer{ .buffer = getState().overrideInfo.buffer, diff --git a/services/surfaceflinger/CompositionEngine/src/RenderSurface.cpp b/services/surfaceflinger/CompositionEngine/src/RenderSurface.cpp index ef50870615..3bef77dde1 100644 --- a/services/surfaceflinger/CompositionEngine/src/RenderSurface.cpp +++ b/services/surfaceflinger/CompositionEngine/src/RenderSurface.cpp @@ -25,8 +25,8 @@ #include #include #include + #include -#include #include #include #include @@ -63,8 +63,7 @@ RenderSurface::RenderSurface(const CompositionEngine& compositionEngine, Display mDisplay(display), mNativeWindow(args.nativeWindow), mDisplaySurface(args.displaySurface), - mSize(args.displayWidth, args.displayHeight), - mMaxTextureCacheSize(args.maxTextureCacheSize) { + mSize(args.displayWidth, args.displayHeight) { LOG_ALWAYS_FATAL_IF(!mNativeWindow); } @@ -147,8 +146,7 @@ void RenderSurface::prepareFrame(bool usesClientComposition, bool usesDeviceComp } } -std::shared_ptr RenderSurface::dequeueBuffer( - base::unique_fd* bufferFence) { +sp RenderSurface::dequeueBuffer(base::unique_fd* bufferFence) { ATRACE_CALL(); int fd = -1; ANativeWindowBuffer* buffer = nullptr; @@ -160,41 +158,16 @@ std::shared_ptr RenderSurface::dequeueBuffer( mDisplay.getName().c_str(), result); // Return fast here as we can't do much more - any rendering we do // now will just be wrong. - return mTexture; - } - - ALOGW_IF(mTexture != nullptr, "Clobbering a non-null pointer to a buffer [%p].", - mTexture->getBuffer()->getNativeBuffer()->handle); - - sp newBuffer = GraphicBuffer::from(buffer); - - std::shared_ptr texture; - - for (auto it = mTextureCache.begin(); it != mTextureCache.end(); it++) { - const auto& cachedTexture = *it; - if (cachedTexture->getBuffer()->getId() == newBuffer->getId()) { - texture = cachedTexture; - mTextureCache.erase(it); - break; - } + return mGraphicBuffer; } - if (texture) { - mTexture = texture; - } else { - mTexture = std::make_shared< - renderengine::ExternalTexture>(GraphicBuffer::from(buffer), - mCompositionEngine.getRenderEngine(), - renderengine::ExternalTexture::Usage::WRITEABLE); - } - mTextureCache.push_back(mTexture); - if (mTextureCache.size() > mMaxTextureCacheSize) { - mTextureCache.erase(mTextureCache.begin()); - } + ALOGW_IF(mGraphicBuffer != nullptr, "Clobbering a non-null pointer to a buffer [%p].", + mGraphicBuffer->getNativeBuffer()->handle); + mGraphicBuffer = GraphicBuffer::from(buffer); *bufferFence = base::unique_fd(fd); - return mTexture; + return mGraphicBuffer; } void RenderSurface::queueBuffer(base::unique_fd readyFence) { @@ -204,24 +177,24 @@ void RenderSurface::queueBuffer(base::unique_fd readyFence) { // hasFlipClientTargetRequest could return true even if we haven't // dequeued a buffer before. Try dequeueing one if we don't have a // buffer ready. - if (mTexture == nullptr) { + if (mGraphicBuffer == nullptr) { ALOGI("Attempting to queue a client composited buffer without one " "previously dequeued for display [%s]. Attempting to dequeue " "a scratch buffer now", mDisplay.getName().c_str()); - // We shouldn't deadlock here, since mTexture == nullptr only + // We shouldn't deadlock here, since mGraphicBuffer == nullptr only // after a successful call to queueBuffer, or if dequeueBuffer has // never been called. base::unique_fd unused; dequeueBuffer(&unused); } - if (mTexture == nullptr) { + if (mGraphicBuffer == nullptr) { ALOGE("No buffer is ready for display [%s]", mDisplay.getName().c_str()); } else { - status_t result = mNativeWindow->queueBuffer(mNativeWindow.get(), - mTexture->getBuffer()->getNativeBuffer(), - dup(readyFence)); + status_t result = + mNativeWindow->queueBuffer(mNativeWindow.get(), + mGraphicBuffer->getNativeBuffer(), dup(readyFence)); if (result != NO_ERROR) { ALOGE("Error when queueing buffer for display [%s]: %d", mDisplay.getName().c_str(), result); @@ -231,12 +204,11 @@ void RenderSurface::queueBuffer(base::unique_fd readyFence) { LOG_ALWAYS_FATAL("ANativeWindow::queueBuffer failed with error: %d", result); } else { mNativeWindow->cancelBuffer(mNativeWindow.get(), - mTexture->getBuffer()->getNativeBuffer(), - dup(readyFence)); + mGraphicBuffer->getNativeBuffer(), dup(readyFence)); } } - mTexture = nullptr; + mGraphicBuffer = nullptr; } } @@ -284,8 +256,8 @@ void RenderSurface::setSizeForTest(const ui::Size& size) { mSize = size; } -std::shared_ptr& RenderSurface::mutableTextureForTest() { - return mTexture; +sp& RenderSurface::mutableGraphicBufferForTest() { + return mGraphicBuffer; } } // namespace impl diff --git a/services/surfaceflinger/CompositionEngine/src/planner/CachedSet.cpp b/services/surfaceflinger/CompositionEngine/src/planner/CachedSet.cpp index 53557bbb9f..dcb75556e3 100644 --- a/services/surfaceflinger/CompositionEngine/src/planner/CachedSet.cpp +++ b/services/surfaceflinger/CompositionEngine/src/planner/CachedSet.cpp @@ -130,7 +130,7 @@ bool CachedSet::hasBufferUpdate() const { } bool CachedSet::hasReadyBuffer() const { - return mTexture != nullptr && mDrawFence->getStatus() == Fence::Status::Signaled; + return mTexture.getBuffer() != nullptr && mDrawFence->getStatus() == Fence::Status::Signaled; } std::vector CachedSet::decompose() const { @@ -217,27 +217,21 @@ void CachedSet::render(renderengine::RenderEngine& renderEngine, sp buffer = new GraphicBuffer(static_cast(mBounds.getWidth()), static_cast(mBounds.getHeight()), HAL_PIXEL_FORMAT_RGBA_8888, 1, usageFlags); - const auto texture = std::make_shared< - renderengine::ExternalTexture>(buffer, renderEngine, - renderengine::ExternalTexture::Usage::READABLE | - renderengine::ExternalTexture::Usage::WRITEABLE); LOG_ALWAYS_FATAL_IF(buffer->initCheck() != OK); base::unique_fd drawFence; - status_t result = renderEngine.drawLayers(displaySettings, layerSettingsPointers, mTexture, - false, base::unique_fd(), &drawFence); + status_t result = renderEngine.drawLayers(displaySettings, layerSettingsPointers, buffer, false, + base::unique_fd(), &drawFence); if (result == NO_ERROR) { + mTexture.setBuffer(buffer, &renderEngine); mDrawFence = new Fence(drawFence.release()); mOutputSpace = ProjectionSpace(ui::Size(outputState.framebufferSpace.bounds.getWidth(), outputState.framebufferSpace.bounds.getHeight()), mBounds); - mTexture = std::move(texture); mOutputSpace.orientation = outputState.framebufferSpace.orientation; mOutputDataspace = outputDataspace; mOrientation = orientation; - } else { - mTexture = nullptr; } } diff --git a/services/surfaceflinger/CompositionEngine/src/planner/Planner.cpp b/services/surfaceflinger/CompositionEngine/src/planner/Planner.cpp index 3a2534b847..ad7555730d 100644 --- a/services/surfaceflinger/CompositionEngine/src/planner/Planner.cpp +++ b/services/surfaceflinger/CompositionEngine/src/planner/Planner.cpp @@ -111,12 +111,7 @@ void Planner::reportFinalPlan( const GraphicBuffer* currentOverrideBuffer = nullptr; bool hasSkippedLayers = false; for (auto layer : layers) { - if (!layer->getState().overrideInfo.buffer) { - continue; - } - - const GraphicBuffer* overrideBuffer = - layer->getState().overrideInfo.buffer->getBuffer().get(); + const GraphicBuffer* overrideBuffer = layer->getState().overrideInfo.buffer.get(); if (overrideBuffer != nullptr && overrideBuffer == currentOverrideBuffer) { // Skip this layer since it is part of a previous cached set hasSkippedLayers = true; diff --git a/services/surfaceflinger/CompositionEngine/tests/OutputLayerTest.cpp b/services/surfaceflinger/CompositionEngine/tests/OutputLayerTest.cpp index 4c3f4940cc..8a4d161289 100644 --- a/services/surfaceflinger/CompositionEngine/tests/OutputLayerTest.cpp +++ b/services/surfaceflinger/CompositionEngine/tests/OutputLayerTest.cpp @@ -26,7 +26,6 @@ #include "MockHWC2.h" #include "MockHWComposer.h" #include "RegionMatcher.h" -#include "renderengine/mock/RenderEngine.h" namespace android::compositionengine { namespace { @@ -716,7 +715,7 @@ struct OutputLayerWriteStateToHWCTest : public OutputLayerTest { static const HdrMetadata kHdrMetadata; static native_handle_t* kSidebandStreamHandle; static const sp kBuffer; - std::shared_ptr kOverrideBuffer; + static const sp kOverrideBuffer; static const sp kFence; static const sp kOverrideFence; static const std::string kLayerGenericMetadata1Key; @@ -725,11 +724,6 @@ struct OutputLayerWriteStateToHWCTest : public OutputLayerTest { static const std::vector kLayerGenericMetadata2Value; OutputLayerWriteStateToHWCTest() { - kOverrideBuffer = std::make_shared< - renderengine::ExternalTexture>(new GraphicBuffer(), mRenderEngine, - renderengine::ExternalTexture::Usage::READABLE | - renderengine::ExternalTexture::Usage:: - WRITEABLE); auto& outputLayerState = mOutputLayer.editState(); outputLayerState.hwc = impl::OutputLayerCompositionState::Hwc(mHwcLayer); @@ -845,7 +839,6 @@ struct OutputLayerWriteStateToHWCTest : public OutputLayerTest { std::shared_ptr mHwcLayer{std::make_shared>()}; StrictMock mDisplayColorProfile; - renderengine::mock::RenderEngine mRenderEngine; }; const half4 OutputLayerWriteStateToHWCTest::kColor{81.f / 255.f, 82.f / 255.f, 83.f / 255.f, @@ -865,6 +858,7 @@ const HdrMetadata OutputLayerWriteStateToHWCTest::kHdrMetadata{{/* LightFlattena native_handle_t* OutputLayerWriteStateToHWCTest::kSidebandStreamHandle = reinterpret_cast(1031); const sp OutputLayerWriteStateToHWCTest::kBuffer; +const sp OutputLayerWriteStateToHWCTest::kOverrideBuffer = new GraphicBuffer(); const sp OutputLayerWriteStateToHWCTest::kFence; const sp OutputLayerWriteStateToHWCTest::kOverrideFence = new Fence(); const std::string OutputLayerWriteStateToHWCTest::kLayerGenericMetadata1Key = @@ -1029,7 +1023,7 @@ TEST_F(OutputLayerWriteStateToHWCTest, includesOverrideInfoIfPresent) { kOverrideBufferTransform, kOverrideBlendMode, kOverrideAlpha); expectPerFrameCommonCalls(SimulateUnsupported::None, kOverrideDataspace, kOverrideVisibleRegion, kOverrideSurfaceDamage); - expectSetHdrMetadataAndBufferCalls(kOverrideBuffer->getBuffer(), kOverrideFence); + expectSetHdrMetadataAndBufferCalls(kOverrideBuffer, kOverrideFence); expectSetCompositionTypeCall(Hwc2::IComposerClient::Composition::DEVICE); mOutputLayer.writeStateToHWC(/*includeGeometry*/ true, /*skipLayer*/ false); diff --git a/services/surfaceflinger/CompositionEngine/tests/OutputTest.cpp b/services/surfaceflinger/CompositionEngine/tests/OutputTest.cpp index e80100cc6e..5f0b0eea15 100644 --- a/services/surfaceflinger/CompositionEngine/tests/OutputTest.cpp +++ b/services/surfaceflinger/CompositionEngine/tests/OutputTest.cpp @@ -14,6 +14,8 @@ * limitations under the License. */ +#include + #include #include #include @@ -29,12 +31,9 @@ #include #include -#include - #include "CallOrderStateMachineHelper.h" #include "MockHWC2.h" #include "RegionMatcher.h" -#include "renderengine/ExternalTexture.h" namespace android::compositionengine { namespace { @@ -2961,10 +2960,7 @@ struct OutputComposeSurfacesTest : public testing::Test { mock::DisplayColorProfile* mDisplayColorProfile = new StrictMock(); mock::RenderSurface* mRenderSurface = new StrictMock(); StrictMock mOutput; - std::shared_ptr mOutputBuffer = std::make_shared< - renderengine::ExternalTexture>(new GraphicBuffer(), mRenderEngine, - renderengine::ExternalTexture::Usage::READABLE | - renderengine::ExternalTexture::Usage::WRITEABLE); + sp mOutputBuffer = new GraphicBuffer(); std::optional mReadyFence; }; @@ -3177,10 +3173,7 @@ TEST_F(OutputComposeSurfacesTest, clientCompositionIfBufferChanges) { EXPECT_CALL(mOutput, appendRegionFlashRequests(RegionEq(kDebugRegion), _)) .WillRepeatedly(Return()); - const auto otherOutputBuffer = std::make_shared< - renderengine::ExternalTexture>(new GraphicBuffer(), mRenderEngine, - renderengine::ExternalTexture::Usage::READABLE | - renderengine::ExternalTexture::Usage::WRITEABLE); + sp otherOutputBuffer = new GraphicBuffer(); EXPECT_CALL(*mRenderSurface, dequeueBuffer(_)) .WillOnce(Return(mOutputBuffer)) .WillOnce(Return(otherOutputBuffer)); diff --git a/services/surfaceflinger/CompositionEngine/tests/RenderSurfaceTest.cpp b/services/surfaceflinger/CompositionEngine/tests/RenderSurfaceTest.cpp index 9aeb290eb5..5ef5d7b5cb 100644 --- a/services/surfaceflinger/CompositionEngine/tests/RenderSurfaceTest.cpp +++ b/services/surfaceflinger/CompositionEngine/tests/RenderSurfaceTest.cpp @@ -15,8 +15,6 @@ */ // TODO(b/129481165): remove the #pragma below and fix conversion issues -#include "renderengine/ExternalTexture.h" -#include "ui/GraphicBuffer.h" #pragma clang diagnostic push #pragma clang diagnostic ignored "-Wextra" @@ -241,9 +239,9 @@ TEST_F(RenderSurfaceTest, dequeueBufferObtainsABuffer) { DoAll(SetArgPointee<0>(buffer.get()), SetArgPointee<1>(-1), Return(NO_ERROR))); base::unique_fd fence; - EXPECT_EQ(buffer.get(), mSurface.dequeueBuffer(&fence)->getBuffer().get()); + EXPECT_EQ(buffer.get(), mSurface.dequeueBuffer(&fence).get()); - EXPECT_EQ(buffer.get(), mSurface.mutableTextureForTest()->getBuffer().get()); + EXPECT_EQ(buffer.get(), mSurface.mutableGraphicBufferForTest().get()); } /* @@ -251,11 +249,8 @@ TEST_F(RenderSurfaceTest, dequeueBufferObtainsABuffer) { */ TEST_F(RenderSurfaceTest, queueBufferHandlesNoClientComposition) { - const auto buffer = std::make_shared< - renderengine::ExternalTexture>(new GraphicBuffer(), mRenderEngine, - renderengine::ExternalTexture::Usage::READABLE | - renderengine::ExternalTexture::Usage::WRITEABLE); - mSurface.mutableTextureForTest() = buffer; + sp buffer = new GraphicBuffer(); + mSurface.mutableGraphicBufferForTest() = buffer; impl::OutputCompositionState state; state.usesClientComposition = false; @@ -266,45 +261,43 @@ TEST_F(RenderSurfaceTest, queueBufferHandlesNoClientComposition) { mSurface.queueBuffer(base::unique_fd()); - EXPECT_EQ(buffer.get(), mSurface.mutableTextureForTest().get()); + EXPECT_EQ(buffer.get(), mSurface.mutableGraphicBufferForTest().get()); } TEST_F(RenderSurfaceTest, queueBufferHandlesClientComposition) { - const auto buffer = std::make_shared(new GraphicBuffer(), - mRenderEngine, false); - mSurface.mutableTextureForTest() = buffer; + sp buffer = new GraphicBuffer(); + mSurface.mutableGraphicBufferForTest() = buffer; impl::OutputCompositionState state; state.usesClientComposition = true; state.flipClientTarget = false; EXPECT_CALL(mDisplay, getState()).WillOnce(ReturnRef(state)); - EXPECT_CALL(*mNativeWindow, queueBuffer(buffer->getBuffer()->getNativeBuffer(), -1)) + EXPECT_CALL(*mNativeWindow, queueBuffer(buffer->getNativeBuffer(), -1)) .WillOnce(Return(NO_ERROR)); EXPECT_CALL(*mDisplaySurface, advanceFrame()).Times(1); mSurface.queueBuffer(base::unique_fd()); - EXPECT_EQ(nullptr, mSurface.mutableTextureForTest().get()); + EXPECT_EQ(nullptr, mSurface.mutableGraphicBufferForTest().get()); } TEST_F(RenderSurfaceTest, queueBufferHandlesFlipClientTargetRequest) { - const auto buffer = std::make_shared(new GraphicBuffer(), - mRenderEngine, false); - mSurface.mutableTextureForTest() = buffer; + sp buffer = new GraphicBuffer(); + mSurface.mutableGraphicBufferForTest() = buffer; impl::OutputCompositionState state; state.usesClientComposition = false; state.flipClientTarget = true; EXPECT_CALL(mDisplay, getState()).WillOnce(ReturnRef(state)); - EXPECT_CALL(*mNativeWindow, queueBuffer(buffer->getBuffer()->getNativeBuffer(), -1)) + EXPECT_CALL(*mNativeWindow, queueBuffer(buffer->getNativeBuffer(), -1)) .WillOnce(Return(NO_ERROR)); EXPECT_CALL(*mDisplaySurface, advanceFrame()).Times(1); mSurface.queueBuffer(base::unique_fd()); - EXPECT_EQ(nullptr, mSurface.mutableTextureForTest().get()); + EXPECT_EQ(nullptr, mSurface.mutableGraphicBufferForTest().get()); } TEST_F(RenderSurfaceTest, queueBufferHandlesFlipClientTargetRequestWithNoBufferYetDequeued) { @@ -324,28 +317,27 @@ TEST_F(RenderSurfaceTest, queueBufferHandlesFlipClientTargetRequestWithNoBufferY mSurface.queueBuffer(base::unique_fd()); - EXPECT_EQ(nullptr, mSurface.mutableTextureForTest().get()); + EXPECT_EQ(nullptr, mSurface.mutableGraphicBufferForTest().get()); } TEST_F(RenderSurfaceTest, queueBufferHandlesNativeWindowQueueBufferFailureOnVirtualDisplay) { - const auto buffer = std::make_shared(new GraphicBuffer(), - mRenderEngine, false); - mSurface.mutableTextureForTest() = buffer; + sp buffer = new GraphicBuffer(); + mSurface.mutableGraphicBufferForTest() = buffer; impl::OutputCompositionState state; state.usesClientComposition = true; EXPECT_CALL(mDisplay, getState()).WillOnce(ReturnRef(state)); - EXPECT_CALL(*mNativeWindow, queueBuffer(buffer->getBuffer()->getNativeBuffer(), -1)) + EXPECT_CALL(*mNativeWindow, queueBuffer(buffer->getNativeBuffer(), -1)) .WillOnce(Return(INVALID_OPERATION)); EXPECT_CALL(mDisplay, isVirtual()).WillOnce(Return(true)); - EXPECT_CALL(*mNativeWindow, cancelBuffer(buffer->getBuffer()->getNativeBuffer(), -1)) + EXPECT_CALL(*mNativeWindow, cancelBuffer(buffer->getNativeBuffer(), -1)) .WillOnce(Return(NO_ERROR)); EXPECT_CALL(*mDisplaySurface, advanceFrame()).Times(1); mSurface.queueBuffer(base::unique_fd()); - EXPECT_EQ(nullptr, mSurface.mutableTextureForTest().get()); + EXPECT_EQ(nullptr, mSurface.mutableGraphicBufferForTest().get()); } /* diff --git a/services/surfaceflinger/CompositionEngine/tests/planner/CachedSetTest.cpp b/services/surfaceflinger/CompositionEngine/tests/planner/CachedSetTest.cpp index 283c69270f..f01fe27b38 100644 --- a/services/surfaceflinger/CompositionEngine/tests/planner/CachedSetTest.cpp +++ b/services/surfaceflinger/CompositionEngine/tests/planner/CachedSetTest.cpp @@ -305,8 +305,8 @@ TEST_F(CachedSetTest, render) { const auto drawLayers = [&](const renderengine::DisplaySettings& displaySettings, const std::vector& layers, - const std::shared_ptr&, const bool, - base::unique_fd&&, base::unique_fd*) -> size_t { + const sp&, const bool, base::unique_fd&&, + base::unique_fd*) -> size_t { EXPECT_EQ(Rect(0, 0, 2, 2), displaySettings.physicalDisplay); EXPECT_EQ(mOutputState.layerStackSpace.content, displaySettings.clip); EXPECT_EQ(ui::Transform::toRotationFlags(mOutputState.framebufferSpace.orientation), @@ -321,6 +321,7 @@ TEST_F(CachedSetTest, render) { EXPECT_CALL(*layerFE1, prepareClientCompositionList(_)).WillOnce(Return(clientCompList1)); EXPECT_CALL(*layerFE2, prepareClientCompositionList(_)).WillOnce(Return(clientCompList2)); EXPECT_CALL(mRenderEngine, drawLayers(_, _, _, _, _, _)).WillOnce(Invoke(drawLayers)); + EXPECT_CALL(mRenderEngine, cacheExternalTextureBuffer(_)); cachedSet.render(mRenderEngine, mOutputState); expectReadyBuffer(cachedSet); @@ -330,6 +331,7 @@ TEST_F(CachedSetTest, render) { cachedSet.getOutputSpace().bounds); // Now check that appending a new cached set properly cleans up RenderEngine resources. + EXPECT_CALL(mRenderEngine, unbindExternalTextureBuffer(_)); CachedSet::Layer& layer3 = *mTestLayers[2]->cachedSetLayer.get(); cachedSet.append(CachedSet(layer3)); } diff --git a/services/surfaceflinger/DisplayDevice.cpp b/services/surfaceflinger/DisplayDevice.cpp index 8692ee60dc..b7b2cc691b 100644 --- a/services/surfaceflinger/DisplayDevice.cpp +++ b/services/surfaceflinger/DisplayDevice.cpp @@ -70,13 +70,11 @@ DisplayDevice::DisplayDevice(DisplayDeviceCreationArgs& args) mIsPrimary(args.isPrimary) { mCompositionDisplay->editState().isSecure = args.isSecure; mCompositionDisplay->createRenderSurface( - compositionengine:: - RenderSurfaceCreationArgs{ANativeWindow_getWidth(args.nativeWindow.get()), - ANativeWindow_getHeight(args.nativeWindow.get()), - args.nativeWindow, args.displaySurface, - static_cast( - SurfaceFlinger:: - maxFrameBufferAcquiredBuffers)}); + compositionengine::RenderSurfaceCreationArgs{ANativeWindow_getWidth( + args.nativeWindow.get()), + ANativeWindow_getHeight( + args.nativeWindow.get()), + args.nativeWindow, args.displaySurface}); if (!mFlinger->mDisableClientCompositionCache && SurfaceFlinger::maxFrameBufferAcquiredBuffers > 0) { diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp index cf215adba2..b45f2bcd92 100644 --- a/services/surfaceflinger/Layer.cpp +++ b/services/surfaceflinger/Layer.cpp @@ -880,7 +880,7 @@ uint32_t Layer::doTransaction(uint32_t flags) { } // Allow BufferStateLayer to release any unlatched buffers in drawing state. - bufferMayChange(c.buffer->getBuffer()); + bufferMayChange(c.buffer); // Commit the transaction commitTransaction(c); @@ -891,11 +891,7 @@ uint32_t Layer::doTransaction(uint32_t flags) { void Layer::commitTransaction(State& stateToCommit) { if (auto& bufferSurfaceFrame = mDrawingState.bufferSurfaceFrameTX; - ((mDrawingState.buffer && stateToCommit.buffer && - mDrawingState.buffer->getBuffer() != stateToCommit.buffer->getBuffer()) || - (mDrawingState.buffer && !stateToCommit.buffer) || - (!mDrawingState.buffer && stateToCommit.buffer)) && - bufferSurfaceFrame != nullptr && + mDrawingState.buffer != stateToCommit.buffer && bufferSurfaceFrame != nullptr && bufferSurfaceFrame->getPresentState() != PresentState::Presented) { // If the previous buffer was committed but not latched (refreshPending - happens during // back to back invalidates), it gets silently dropped here. Mark the corresponding diff --git a/services/surfaceflinger/Layer.h b/services/surfaceflinger/Layer.h index 9f3ea9ab39..5379d7490d 100644 --- a/services/surfaceflinger/Layer.h +++ b/services/surfaceflinger/Layer.h @@ -203,7 +203,7 @@ public: Region transparentRegionHint; - std::shared_ptr buffer; + sp buffer; client_cache_t clientCacheId; sp acquireFence; std::shared_ptr acquireFenceTime; @@ -404,11 +404,10 @@ public: // Used only to set BufferStateLayer state virtual bool setTransform(uint32_t /*transform*/) { return false; }; virtual bool setTransformToDisplayInverse(bool /*transformToDisplayInverse*/) { return false; }; - virtual bool setBuffer(const std::shared_ptr& /*buffer*/, - const sp& /*acquireFence*/, nsecs_t /*postTime*/, - nsecs_t /*desiredPresentTime*/, bool /*isAutoTimestamp*/, - const client_cache_t& /*clientCacheId*/, uint64_t /* frameNumber */, - std::optional /* dequeueTime */, + virtual bool setBuffer(const sp& /*buffer*/, const sp& /*acquireFence*/, + nsecs_t /*postTime*/, nsecs_t /*desiredPresentTime*/, + bool /*isAutoTimestamp*/, const client_cache_t& /*clientCacheId*/, + uint64_t /* frameNumber */, std::optional /* dequeueTime */, const FrameTimelineInfo& /*info*/, const sp& /* releaseBufferListener */) { return false; @@ -710,7 +709,7 @@ public: * Called before updating the drawing state buffer. Used by BufferStateLayer to release any * unlatched buffers in the drawing state. */ - virtual void bufferMayChange(const sp& /* newBuffer */){}; + virtual void bufferMayChange(sp& /* newBuffer */){}; /* * Remove relative z for the layer if its relative parent is not part of the diff --git a/services/surfaceflinger/RefreshRateOverlay.cpp b/services/surfaceflinger/RefreshRateOverlay.cpp index a9fd16cb75..7a3e433660 100644 --- a/services/surfaceflinger/RefreshRateOverlay.cpp +++ b/services/surfaceflinger/RefreshRateOverlay.cpp @@ -208,8 +208,7 @@ bool RefreshRateOverlay::createLayer() { return true; } -const std::vector>& -RefreshRateOverlay::getOrCreateBuffers(uint32_t fps) { +const std::vector>& RefreshRateOverlay::getOrCreateBuffers(uint32_t fps) { if (mBufferCache.find(fps) == mBufferCache.end()) { // Ensure the range is > 0, so we don't divide by 0. const auto rangeLength = std::max(1u, mHighFps - mLowFps); @@ -223,17 +222,7 @@ RefreshRateOverlay::getOrCreateBuffers(uint32_t fps) { color.g = HIGH_FPS_COLOR.g * fpsScale + LOW_FPS_COLOR.g * (1 - fpsScale); color.b = HIGH_FPS_COLOR.b * fpsScale + LOW_FPS_COLOR.b * (1 - fpsScale); color.a = ALPHA; - auto buffers = SevenSegmentDrawer::drawNumber(fps, color, mShowSpinner); - std::vector> textures; - std::transform(buffers.begin(), buffers.end(), std::back_inserter(textures), - [&](const auto& buffer) -> std::shared_ptr { - return std::make_shared< - renderengine::ExternalTexture>(buffer, - mFlinger.getRenderEngine(), - renderengine::ExternalTexture:: - Usage::READABLE); - }); - mBufferCache.emplace(fps, textures); + mBufferCache.emplace(fps, SevenSegmentDrawer::drawNumber(fps, color, mShowSpinner)); } return mBufferCache[fps]; diff --git a/services/surfaceflinger/RefreshRateOverlay.h b/services/surfaceflinger/RefreshRateOverlay.h index aa8329c46a..c16cfa07a4 100644 --- a/services/surfaceflinger/RefreshRateOverlay.h +++ b/services/surfaceflinger/RefreshRateOverlay.h @@ -16,14 +16,13 @@ #pragma once +#include + #include -#include #include #include #include -#include - #include "Fps.h" namespace android { @@ -71,8 +70,7 @@ private: }; bool createLayer(); - const std::vector>& getOrCreateBuffers( - uint32_t fps); + const std::vector>& getOrCreateBuffers(uint32_t fps); SurfaceFlinger& mFlinger; const sp mClient; @@ -80,8 +78,7 @@ private: sp mIBinder; sp mGbp; - std::unordered_map>> - mBufferCache; + std::unordered_map>> mBufferCache; std::optional mCurrentFps; int mFrame = 0; static constexpr float ALPHA = 0.8f; diff --git a/services/surfaceflinger/RegionSamplingThread.cpp b/services/surfaceflinger/RegionSamplingThread.cpp index 00090d948a..d0032ac7fd 100644 --- a/services/surfaceflinger/RegionSamplingThread.cpp +++ b/services/surfaceflinger/RegionSamplingThread.cpp @@ -438,22 +438,18 @@ void RegionSamplingThread::captureSample() { mFlinger.traverseLayersInLayerStack(layerStack, CaptureArgs::UNSET_UID, filterVisitor); }; - std::shared_ptr buffer = nullptr; - if (mCachedBuffer && mCachedBuffer->getBuffer()->getWidth() == sampledBounds.getWidth() && - mCachedBuffer->getBuffer()->getHeight() == sampledBounds.getHeight()) { + sp buffer = nullptr; + if (mCachedBuffer && mCachedBuffer->getWidth() == sampledBounds.getWidth() && + mCachedBuffer->getHeight() == sampledBounds.getHeight()) { buffer = mCachedBuffer; } else { const uint32_t usage = GRALLOC_USAGE_SW_READ_OFTEN | GRALLOC_USAGE_HW_RENDER | GRALLOC_USAGE_HW_TEXTURE; - sp graphicBuffer = - new GraphicBuffer(sampledBounds.getWidth(), sampledBounds.getHeight(), - PIXEL_FORMAT_RGBA_8888, 1, usage, "RegionSamplingThread"); - const status_t bufferStatus = graphicBuffer->initCheck(); + buffer = new GraphicBuffer(sampledBounds.getWidth(), sampledBounds.getHeight(), + PIXEL_FORMAT_RGBA_8888, 1, usage, "RegionSamplingThread"); + const status_t bufferStatus = buffer->initCheck(); LOG_ALWAYS_FATAL_IF(bufferStatus != OK, "captureSample: Buffer failed to allocate: %d", bufferStatus); - buffer = std::make_shared< - renderengine::ExternalTexture>(graphicBuffer, mFlinger.getRenderEngine(), - renderengine::ExternalTexture::Usage::WRITEABLE); } const sp captureListener = new SyncScreenCaptureListener(); @@ -469,8 +465,8 @@ void RegionSamplingThread::captureSample() { } ALOGV("Sampling %zu descriptors", activeDescriptors.size()); - std::vector lumas = sampleBuffer(buffer->getBuffer(), sampledBounds.leftTop(), - activeDescriptors, orientation); + std::vector lumas = + sampleBuffer(buffer, sampledBounds.leftTop(), activeDescriptors, orientation); if (lumas.size() != activeDescriptors.size()) { ALOGW("collected %zu median luma values for %zu descriptors", lumas.size(), activeDescriptors.size()); @@ -481,6 +477,16 @@ void RegionSamplingThread::captureSample() { activeDescriptors[d].listener->onSampleCollected(lumas[d]); } + // Extend the lifetime of mCachedBuffer from the previous frame to here to ensure that: + // 1) The region sampling thread is the last owner of the buffer, and the freeing of the buffer + // happens in this thread, as opposed to the main thread. + // 2) The listener(s) receive their notifications prior to freeing the buffer. + if (mCachedBuffer != nullptr && mCachedBuffer != buffer) { + if (mFlinger.getRenderEngine().getRenderEngineType() == + renderengine::RenderEngine::RenderEngineType::SKIA_GL_THREADED) { + mFlinger.getRenderEngine().unbindExternalTextureBuffer(mCachedBuffer->getId()); + } + } mCachedBuffer = buffer; ATRACE_INT(lumaSamplingStepTag, static_cast(samplingStep::noWorkNeeded)); } diff --git a/services/surfaceflinger/RegionSamplingThread.h b/services/surfaceflinger/RegionSamplingThread.h index 86632db490..0defdb3fcb 100644 --- a/services/surfaceflinger/RegionSamplingThread.h +++ b/services/surfaceflinger/RegionSamplingThread.h @@ -16,19 +16,17 @@ #pragma once -#include -#include -#include -#include -#include -#include - #include #include #include #include #include +#include +#include +#include +#include +#include #include "Scheduler/OneShotTimer.h" namespace android { @@ -124,8 +122,7 @@ private: std::mutex mSamplingMutex; std::unordered_map, Descriptor, WpHash> mDescriptors GUARDED_BY(mSamplingMutex); - std::shared_ptr mCachedBuffer GUARDED_BY(mSamplingMutex) = - nullptr; + sp mCachedBuffer GUARDED_BY(mSamplingMutex) = nullptr; }; } // namespace android diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp index 828543f938..89ce9d285e 100644 --- a/services/surfaceflinger/SurfaceFlinger.cpp +++ b/services/surfaceflinger/SurfaceFlinger.cpp @@ -739,7 +739,6 @@ void SurfaceFlinger::init() { mCompositionEngine->setTimeStats(mTimeStats); mCompositionEngine->setHwComposer(getFactory().createHWComposer(getBE().mHwcServiceName)); mCompositionEngine->getHwComposer().setConfiguration(this, getBE().mComposerSequenceId); - ClientCache::getInstance().setRenderEngine(&getRenderEngine()); // Process any initial hotplug and resulting display changes. processDisplayHotplugEventsLocked(); const auto display = getDefaultDisplayDeviceLocked(); @@ -3705,6 +3704,7 @@ void SurfaceFlinger::applyTransactionState(const FrameTimelineInfo& frameTimelin if (uncacheBuffer.isValid()) { ClientCache::getInstance().erase(uncacheBuffer); + getRenderEngine().unbindExternalTextureBuffer(uncacheBuffer.id); } // If a synchronous transaction is explicitly requested without any changes, force a transaction @@ -4068,16 +4068,23 @@ uint32_t SurfaceFlinger::setClientStateLocked( } bool bufferChanged = what & layer_state_t::eBufferChanged; bool cacheIdChanged = what & layer_state_t::eCachedBufferChanged; - std::shared_ptr buffer; + sp buffer; if (bufferChanged && cacheIdChanged && s.buffer != nullptr) { - ClientCache::getInstance().add(s.cachedBuffer, s.buffer); - buffer = ClientCache::getInstance().get(s.cachedBuffer); + buffer = s.buffer; + bool success = ClientCache::getInstance().add(s.cachedBuffer, s.buffer); + if (success) { + getRenderEngine().cacheExternalTextureBuffer(s.buffer); + success = ClientCache::getInstance() + .registerErasedRecipient(s.cachedBuffer, + wp(this)); + if (!success) { + getRenderEngine().unbindExternalTextureBuffer(s.buffer->getId()); + } + } } else if (cacheIdChanged) { buffer = ClientCache::getInstance().get(s.cachedBuffer); } else if (bufferChanged) { - buffer = std::make_shared< - renderengine::ExternalTexture>(s.buffer, getRenderEngine(), - renderengine::ExternalTexture::Usage::READABLE); + buffer = s.buffer; } if (buffer) { const bool frameNumberChanged = what & layer_state_t::eFrameNumberChanged; @@ -5996,17 +6003,15 @@ status_t SurfaceFlinger::captureScreenCommon(RenderAreaFuture renderAreaFuture, const status_t bufferStatus = buffer->initCheck(); LOG_ALWAYS_FATAL_IF(bufferStatus != OK, "captureScreenCommon: Buffer failed to allocate: %d", bufferStatus); - const auto texture = std::make_shared< - renderengine::ExternalTexture>(buffer, getRenderEngine(), - renderengine::ExternalTexture::Usage::WRITEABLE); - return captureScreenCommon(std::move(renderAreaFuture), traverseLayers, texture, + return captureScreenCommon(std::move(renderAreaFuture), traverseLayers, buffer, false /* regionSampling */, grayscale, captureListener); } -status_t SurfaceFlinger::captureScreenCommon( - RenderAreaFuture renderAreaFuture, TraverseLayersFunction traverseLayers, - const std::shared_ptr& buffer, bool regionSampling, - bool grayscale, const sp& captureListener) { +status_t SurfaceFlinger::captureScreenCommon(RenderAreaFuture renderAreaFuture, + TraverseLayersFunction traverseLayers, + sp& buffer, bool regionSampling, + bool grayscale, + const sp& captureListener) { ATRACE_CALL(); if (captureListener == nullptr) { @@ -6039,6 +6044,15 @@ status_t SurfaceFlinger::captureScreenCommon( regionSampling, grayscale, captureResults); }); + // TODO(b/180767535): Remove this once we optimize buffer lifecycle for RenderEngine + // Only do this when we're not doing region sampling, to allow the region sampling thread to + // manage buffer lifecycle itself. + if (!regionSampling && + getRenderEngine().getRenderEngineType() == + renderengine::RenderEngine::RenderEngineType::SKIA_GL_THREADED) { + getRenderEngine().unbindExternalTextureBuffer(buffer->getId()); + } + captureResults.result = result; captureListener->onScreenCaptureCompleted(captureResults); })); @@ -6046,10 +6060,11 @@ status_t SurfaceFlinger::captureScreenCommon( return NO_ERROR; } -status_t SurfaceFlinger::renderScreenImplLocked( - const RenderArea& renderArea, TraverseLayersFunction traverseLayers, - const std::shared_ptr& buffer, bool forSystem, - bool regionSampling, bool grayscale, ScreenCaptureResults& captureResults) { +status_t SurfaceFlinger::renderScreenImplLocked(const RenderArea& renderArea, + TraverseLayersFunction traverseLayers, + const sp& buffer, bool forSystem, + bool regionSampling, bool grayscale, + ScreenCaptureResults& captureResults) { ATRACE_CALL(); traverseLayers([&](Layer* layer) { @@ -6057,7 +6072,7 @@ status_t SurfaceFlinger::renderScreenImplLocked( captureResults.capturedSecureLayers || (layer->isVisible() && layer->isSecure()); }); - const bool useProtected = buffer->getBuffer()->getUsage() & GRALLOC_USAGE_PROTECTED; + const bool useProtected = buffer->getUsage() & GRALLOC_USAGE_PROTECTED; // We allow the system server to take screenshots of secure layers for // use in situations like the Screen-rotation animation and place @@ -6067,7 +6082,7 @@ status_t SurfaceFlinger::renderScreenImplLocked( return PERMISSION_DENIED; } - captureResults.buffer = buffer->getBuffer(); + captureResults.buffer = buffer; captureResults.capturedDataspace = renderArea.getReqDataSpace(); const auto reqWidth = renderArea.getReqWidth(); @@ -6158,9 +6173,11 @@ status_t SurfaceFlinger::renderScreenImplLocked( base::unique_fd drawFence; getRenderEngine().useProtectedContext(useProtected); - const constexpr bool kUseFramebufferCache = false; + // TODO(b/180767535): Remove this once we optimize buffer lifecycle for RenderEngine + const bool useFramebufferCache = getRenderEngine().getRenderEngineType() == + renderengine::RenderEngine::RenderEngineType::SKIA_GL_THREADED; getRenderEngine().drawLayers(clientCompositionDisplay, clientCompositionLayerPointers, buffer, - kUseFramebufferCache, std::move(bufferFence), &drawFence); + useFramebufferCache, std::move(bufferFence), &drawFence); if (drawFence >= 0) { sp releaseFence = new Fence(dup(drawFence)); @@ -6425,6 +6442,10 @@ void SurfaceFlinger::removeFromOffscreenLayers(Layer* layer) { mOffscreenLayers.erase(layer); } +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) { diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h index a242d8a876..b3da61e810 100644 --- a/services/surfaceflinger/SurfaceFlinger.h +++ b/services/surfaceflinger/SurfaceFlinger.h @@ -184,6 +184,7 @@ public: class SurfaceFlinger : public BnSurfaceComposer, public PriorityDumper, + public ClientCache::ErasedRecipient, private IBinder::DeathRecipient, private HWC2::ComposerCallback, private ISchedulerCallback { @@ -331,6 +332,9 @@ public: wp fromHandle(const sp& handle); wp fromHandleLocked(const sp& handle) const REQUIRES(mStateLock); + // Inherit from ClientCache::ErasedRecipient + void bufferErased(const client_cache_t& clientCacheId) override; + // If set, disables reusing client composition buffers. This can be set by // debug.sf.disable_client_composition_cache bool mDisableClientCompositionCache = false; @@ -903,14 +907,12 @@ private: status_t captureScreenCommon(RenderAreaFuture, TraverseLayersFunction, ui::Size bufferSize, ui::PixelFormat, bool allowProtected, bool grayscale, const sp&); - status_t captureScreenCommon(RenderAreaFuture, TraverseLayersFunction, - const std::shared_ptr&, + status_t captureScreenCommon(RenderAreaFuture, TraverseLayersFunction, sp&, bool regionSampling, bool grayscale, const sp&); status_t renderScreenImplLocked(const RenderArea&, TraverseLayersFunction, - const std::shared_ptr&, - bool forSystem, bool regionSampling, bool grayscale, - ScreenCaptureResults&); + const sp&, bool forSystem, bool regionSampling, + bool grayscale, ScreenCaptureResults&); sp getDisplayByIdOrLayerStack(uint64_t displayOrLayerStack) REQUIRES(mStateLock); sp getDisplayById(DisplayId displayId) const REQUIRES(mStateLock); diff --git a/services/surfaceflinger/tests/unittests/CompositionTest.cpp b/services/surfaceflinger/tests/unittests/CompositionTest.cpp index 3042450f29..4e1c0c77ea 100644 --- a/services/surfaceflinger/tests/unittests/CompositionTest.cpp +++ b/services/surfaceflinger/tests/unittests/CompositionTest.cpp @@ -15,7 +15,6 @@ */ // TODO(b/129481165): remove the #pragma below and fix conversion issues -#include "renderengine/ExternalTexture.h" #pragma clang diagnostic push #pragma clang diagnostic ignored "-Wconversion" #pragma clang diagnostic ignored "-Wextra" @@ -195,7 +194,7 @@ public: sp mClientTargetAcquireFence = Fence::NO_FENCE; - std::shared_ptr mCaptureScreenBuffer; + sp mCaptureScreenBuffer; }; template @@ -244,15 +243,11 @@ void CompositionTest::captureScreenComposition() { // TODO: Eliminate expensive/real allocation if possible. const uint32_t usage = GRALLOC_USAGE_SW_READ_OFTEN | GRALLOC_USAGE_SW_WRITE_OFTEN | GRALLOC_USAGE_HW_RENDER | GRALLOC_USAGE_HW_TEXTURE; - mCaptureScreenBuffer = std::make_shared< - renderengine::ExternalTexture>(new GraphicBuffer(renderArea->getReqWidth(), - renderArea->getReqHeight(), - HAL_PIXEL_FORMAT_RGBA_8888, 1, usage, - "screenshot"), - *mRenderEngine, true); + mCaptureScreenBuffer = new GraphicBuffer(renderArea->getReqWidth(), renderArea->getReqHeight(), + HAL_PIXEL_FORMAT_RGBA_8888, 1, usage, "screenshot"); status_t result = - mFlinger.renderScreenImplLocked(*renderArea, traverseLayers, mCaptureScreenBuffer, + mFlinger.renderScreenImplLocked(*renderArea, traverseLayers, mCaptureScreenBuffer.get(), forSystem, regionSampling); EXPECT_EQ(NO_ERROR, result); @@ -345,8 +340,8 @@ struct BaseDisplayVariant { EXPECT_CALL(*test->mRenderEngine, drawLayers) .WillRepeatedly([](const renderengine::DisplaySettings& displaySettings, const std::vector&, - const std::shared_ptr&, - const bool, base::unique_fd&&, base::unique_fd*) -> status_t { + const sp&, const bool, base::unique_fd&&, + base::unique_fd*) -> status_t { EXPECT_EQ(DEFAULT_DISPLAY_MAX_LUMINANCE, displaySettings.maxLuminance); EXPECT_EQ(Rect(DEFAULT_DISPLAY_WIDTH, DEFAULT_DISPLAY_HEIGHT), displaySettings.physicalDisplay); @@ -394,8 +389,8 @@ struct BaseDisplayVariant { EXPECT_CALL(*test->mRenderEngine, drawLayers) .WillRepeatedly([](const renderengine::DisplaySettings& displaySettings, const std::vector&, - const std::shared_ptr&, - const bool, base::unique_fd&&, base::unique_fd*) -> status_t { + const sp&, const bool, base::unique_fd&&, + base::unique_fd*) -> status_t { EXPECT_EQ(DEFAULT_DISPLAY_MAX_LUMINANCE, displaySettings.maxLuminance); EXPECT_EQ(Rect(DEFAULT_DISPLAY_WIDTH, DEFAULT_DISPLAY_HEIGHT), displaySettings.physicalDisplay); @@ -630,8 +625,8 @@ struct BaseLayerProperties { EXPECT_CALL(*test->mRenderEngine, drawLayers) .WillOnce([](const renderengine::DisplaySettings& displaySettings, const std::vector& layerSettings, - const std::shared_ptr&, const bool, - base::unique_fd&&, base::unique_fd*) -> status_t { + const sp&, const bool, base::unique_fd&&, + base::unique_fd*) -> status_t { EXPECT_EQ(DEFAULT_DISPLAY_MAX_LUMINANCE, displaySettings.maxLuminance); EXPECT_EQ(Rect(DEFAULT_DISPLAY_WIDTH, DEFAULT_DISPLAY_HEIGHT), displaySettings.physicalDisplay); @@ -679,8 +674,8 @@ struct BaseLayerProperties { EXPECT_CALL(*test->mRenderEngine, drawLayers) .WillOnce([](const renderengine::DisplaySettings& displaySettings, const std::vector& layerSettings, - const std::shared_ptr&, const bool, - base::unique_fd&&, base::unique_fd*) -> status_t { + const sp&, const bool, base::unique_fd&&, + base::unique_fd*) -> status_t { EXPECT_EQ(DEFAULT_DISPLAY_MAX_LUMINANCE, displaySettings.maxLuminance); EXPECT_EQ(Rect(DEFAULT_DISPLAY_WIDTH, DEFAULT_DISPLAY_HEIGHT), displaySettings.physicalDisplay); @@ -756,8 +751,8 @@ struct CommonSecureLayerProperties : public BaseLayerProperties EXPECT_CALL(*test->mRenderEngine, drawLayers) .WillOnce([](const renderengine::DisplaySettings& displaySettings, const std::vector& layerSettings, - const std::shared_ptr&, const bool, - base::unique_fd&&, base::unique_fd*) -> status_t { + const sp&, const bool, base::unique_fd&&, + base::unique_fd*) -> status_t { EXPECT_EQ(DEFAULT_DISPLAY_MAX_LUMINANCE, displaySettings.maxLuminance); EXPECT_EQ(Rect(DEFAULT_DISPLAY_WIDTH, DEFAULT_DISPLAY_HEIGHT), displaySettings.physicalDisplay); diff --git a/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h b/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h index d004b9d9eb..63baf7dee2 100644 --- a/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h +++ b/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h @@ -352,8 +352,8 @@ public: auto renderScreenImplLocked(const RenderArea& renderArea, SurfaceFlinger::TraverseLayersFunction traverseLayers, - const std::shared_ptr& buffer, - bool forSystem, bool regionSampling) { + const sp& buffer, bool forSystem, + bool regionSampling) { ScreenCaptureResults captureResults; return mFlinger->renderScreenImplLocked(renderArea, traverseLayers, buffer, forSystem, regionSampling, false /* grayscale */, diff --git a/services/surfaceflinger/tests/unittests/TransactionFrameTracerTest.cpp b/services/surfaceflinger/tests/unittests/TransactionFrameTracerTest.cpp index 25001d3890..ea1ce47b70 100644 --- a/services/surfaceflinger/tests/unittests/TransactionFrameTracerTest.cpp +++ b/services/surfaceflinger/tests/unittests/TransactionFrameTracerTest.cpp @@ -21,8 +21,6 @@ #include #include #include -#include -#include #include #include "TestableSurfaceFlinger.h" @@ -101,7 +99,6 @@ public: TestableSurfaceFlinger mFlinger; Hwc2::mock::Composer* mComposer = nullptr; - renderengine::mock::RenderEngine mRenderEngine; FenceToFenceTimeMap fenceFactory; client_cache_t mClientCache; @@ -109,12 +106,9 @@ public: sp layer = createBufferStateLayer(); sp fence(new Fence()); - const auto buffer = std::make_shared< - renderengine::ExternalTexture>(new GraphicBuffer(1, 1, HAL_PIXEL_FORMAT_RGBA_8888, - 1, 0), - mRenderEngine, false); + sp buffer{new GraphicBuffer(1, 1, HAL_PIXEL_FORMAT_RGBA_8888, 1, 0)}; int32_t layerId = layer->getSequence(); - uint64_t bufferId = buffer->getBuffer()->getId(); + uint64_t bufferId = buffer->getId(); uint64_t frameNumber = 5; nsecs_t dequeueTime = 10; nsecs_t postTime = 20; diff --git a/services/surfaceflinger/tests/unittests/TransactionSurfaceFrameTest.cpp b/services/surfaceflinger/tests/unittests/TransactionSurfaceFrameTest.cpp index b7917aa00e..09a1c2af75 100644 --- a/services/surfaceflinger/tests/unittests/TransactionSurfaceFrameTest.cpp +++ b/services/surfaceflinger/tests/unittests/TransactionSurfaceFrameTest.cpp @@ -21,8 +21,6 @@ #include #include #include -#include -#include #include #include "TestableSurfaceFlinger.h" @@ -101,7 +99,6 @@ public: TestableSurfaceFlinger mFlinger; Hwc2::mock::Composer* mComposer = nullptr; - renderengine::mock::RenderEngine mRenderEngine; FenceToFenceTimeMap fenceFactory; client_cache_t mClientCache; @@ -122,10 +119,7 @@ public: sp layer = createBufferStateLayer(); sp fence(new Fence()); auto acquireFence = fenceFactory.createFenceTimeForTest(fence); - const auto buffer = std::make_shared< - renderengine::ExternalTexture>(new GraphicBuffer(1, 1, HAL_PIXEL_FORMAT_RGBA_8888, - 1, 0), - mRenderEngine, false); + sp buffer{new GraphicBuffer(1, 1, HAL_PIXEL_FORMAT_RGBA_8888, 1, 0)}; layer->setBuffer(buffer, fence, 10, 20, false, mClientCache, 1, std::nullopt, {/*vsyncId*/ 1, /*inputEventId*/ 0}, nullptr /* releaseBufferCallback */); acquireFence->signalForTest(12); @@ -150,10 +144,7 @@ public: sp fence1(new Fence()); auto acquireFence1 = fenceFactory.createFenceTimeForTest(fence1); - const auto buffer1 = std::make_shared< - renderengine::ExternalTexture>(new GraphicBuffer(1, 1, HAL_PIXEL_FORMAT_RGBA_8888, - 1, 0), - mRenderEngine, false); + sp buffer1{new GraphicBuffer(1, 1, HAL_PIXEL_FORMAT_RGBA_8888, 1, 0)}; layer->setBuffer(buffer1, fence1, 10, 20, false, mClientCache, 1, std::nullopt, {/*vsyncId*/ 1, /*inputEventId*/ 0}, nullptr /* releaseBufferCallback */); EXPECT_EQ(0u, layer->mCurrentState.bufferlessSurfaceFramesTX.size()); @@ -162,10 +153,7 @@ public: sp fence2(new Fence()); auto acquireFence2 = fenceFactory.createFenceTimeForTest(fence2); - const auto buffer2 = std::make_shared< - renderengine::ExternalTexture>(new GraphicBuffer(1, 1, HAL_PIXEL_FORMAT_RGBA_8888, - 1, 0), - mRenderEngine, false); + sp buffer2{new GraphicBuffer(1, 1, HAL_PIXEL_FORMAT_RGBA_8888, 1, 0)}; nsecs_t start = systemTime(); layer->setBuffer(buffer2, fence2, 10, 20, false, mClientCache, 1, std::nullopt, {/*vsyncId*/ 1, /*inputEventId*/ 0}, nullptr /* releaseBufferCallback */); @@ -203,10 +191,8 @@ public: sp fence(new Fence()); auto acquireFence = fenceFactory.createFenceTimeForTest(fence); - const auto buffer = std::make_shared< - renderengine::ExternalTexture>(new GraphicBuffer(1, 1, HAL_PIXEL_FORMAT_RGBA_8888, - 1, 0), - mRenderEngine, false); + sp buffer{new GraphicBuffer(1, 1, HAL_PIXEL_FORMAT_RGBA_8888, 1, 0)}; + layer->setBuffer(buffer, fence, 10, 20, false, mClientCache, 1, std::nullopt, {/*vsyncId*/ 1, /*inputEventId*/ 0}, nullptr /* releaseBufferCallback */); acquireFence->signalForTest(12); @@ -231,10 +217,8 @@ public: sp layer = createBufferStateLayer(); sp fence(new Fence()); auto acquireFence = fenceFactory.createFenceTimeForTest(fence); - const auto buffer = std::make_shared< - renderengine::ExternalTexture>(new GraphicBuffer(1, 1, HAL_PIXEL_FORMAT_RGBA_8888, - 1, 0), - mRenderEngine, false); + sp buffer{new GraphicBuffer(1, 1, HAL_PIXEL_FORMAT_RGBA_8888, 1, 0)}; + layer->setBuffer(buffer, fence, 10, 20, false, mClientCache, 1, std::nullopt, {/*vsyncId*/ 1, /*inputEventId*/ 0}, nullptr /* releaseBufferCallback */); EXPECT_EQ(0u, layer->mCurrentState.bufferlessSurfaceFramesTX.size()); @@ -263,10 +247,8 @@ public: sp fence(new Fence()); auto acquireFence = fenceFactory.createFenceTimeForTest(fence); - const auto buffer = std::make_shared< - renderengine::ExternalTexture>(new GraphicBuffer(1, 1, HAL_PIXEL_FORMAT_RGBA_8888, - 1, 0), - mRenderEngine, false); + sp buffer{new GraphicBuffer(1, 1, HAL_PIXEL_FORMAT_RGBA_8888, 1, 0)}; + layer->setBuffer(buffer, fence, 10, 20, false, mClientCache, 1, std::nullopt, {/*vsyncId*/ 3, /*inputEventId*/ 0}, nullptr /* releaseBufferCallback */); EXPECT_EQ(2u, layer->mCurrentState.bufferlessSurfaceFramesTX.size()); @@ -301,10 +283,7 @@ public: sp fence1(new Fence()); auto acquireFence1 = fenceFactory.createFenceTimeForTest(fence1); - const auto buffer1 = std::make_shared< - renderengine::ExternalTexture>(new GraphicBuffer(1, 1, HAL_PIXEL_FORMAT_RGBA_8888, - 1, 0), - mRenderEngine, false); + sp buffer1{new GraphicBuffer(1, 1, HAL_PIXEL_FORMAT_RGBA_8888, 1, 0)}; layer->setBuffer(buffer1, fence1, 10, 20, false, mClientCache, 1, std::nullopt, {/*vsyncId*/ 1, /*inputEventId*/ 0}, nullptr /* releaseBufferCallback */); ASSERT_NE(nullptr, layer->mCurrentState.bufferSurfaceFrameTX); @@ -312,10 +291,7 @@ public: sp fence2(new Fence()); auto acquireFence2 = fenceFactory.createFenceTimeForTest(fence2); - const auto buffer2 = std::make_shared< - renderengine::ExternalTexture>(new GraphicBuffer(1, 1, HAL_PIXEL_FORMAT_RGBA_8888, - 1, 0), - mRenderEngine, false); + sp buffer2{new GraphicBuffer(1, 1, HAL_PIXEL_FORMAT_RGBA_8888, 1, 0)}; layer->setBuffer(buffer2, fence2, 10, 20, false, mClientCache, 1, std::nullopt, {/*vsyncId*/ 1, /*inputEventId*/ 0}, nullptr /* releaseBufferCallback */); acquireFence2->signalForTest(12); @@ -342,10 +318,7 @@ public: sp fence1(new Fence()); auto acquireFence1 = fenceFactory.createFenceTimeForTest(fence1); - const auto buffer1 = std::make_shared< - renderengine::ExternalTexture>(new GraphicBuffer(1, 1, HAL_PIXEL_FORMAT_RGBA_8888, - 1, 0), - mRenderEngine, false); + sp buffer1{new GraphicBuffer(1, 1, HAL_PIXEL_FORMAT_RGBA_8888, 1, 0)}; layer->setBuffer(buffer1, fence1, 10, 20, false, mClientCache, 1, std::nullopt, {/*vsyncId*/ 1, /*inputEventId*/ 0}, nullptr /* releaseBufferCallback */); EXPECT_EQ(0u, layer->mCurrentState.bufferlessSurfaceFramesTX.size()); @@ -354,10 +327,7 @@ public: sp fence2(new Fence()); auto acquireFence2 = fenceFactory.createFenceTimeForTest(fence2); - const auto buffer2 = std::make_shared< - renderengine::ExternalTexture>(new GraphicBuffer(1, 1, HAL_PIXEL_FORMAT_RGBA_8888, - 1, 0), - mRenderEngine, false); + sp buffer2{new GraphicBuffer(1, 1, HAL_PIXEL_FORMAT_RGBA_8888, 1, 0)}; auto dropStartTime1 = systemTime(); layer->setBuffer(buffer2, fence2, 10, 20, false, mClientCache, 1, std::nullopt, {/*vsyncId*/ FrameTimelineInfo::INVALID_VSYNC_ID, /*inputEventId*/ 0}, @@ -369,10 +339,7 @@ public: sp fence3(new Fence()); auto acquireFence3 = fenceFactory.createFenceTimeForTest(fence3); - const auto buffer3 = std::make_shared< - renderengine::ExternalTexture>(new GraphicBuffer(1, 1, HAL_PIXEL_FORMAT_RGBA_8888, - 1, 0), - mRenderEngine, false); + sp buffer3{new GraphicBuffer(1, 1, HAL_PIXEL_FORMAT_RGBA_8888, 1, 0)}; auto dropStartTime2 = systemTime(); layer->setBuffer(buffer3, fence3, 10, 20, false, mClientCache, 1, std::nullopt, {/*vsyncId*/ 2, /*inputEventId*/ 0}, nullptr /* releaseBufferCallback */); @@ -412,11 +379,7 @@ public: std::vector> bufferlessSurfaceFrames; for (int i = 0; i < 10; i += 2) { sp fence1(new Fence()); - const auto buffer1 = std::make_shared< - renderengine::ExternalTexture>(new GraphicBuffer(1, 1, - HAL_PIXEL_FORMAT_RGBA_8888, 1, - 0), - mRenderEngine, false); + sp buffer1{new GraphicBuffer(1, 1, HAL_PIXEL_FORMAT_RGBA_8888, 1, 0)}; layer->setBuffer(buffer1, fence1, 10, 20, false, mClientCache, 1, std::nullopt, {/*vsyncId*/ 1, /*inputEventId*/ 0}, nullptr /* releaseBufferCallback */); -- cgit v1.2.3-59-g8ed1b From 1fb518c8fd5297111d127a19e94524f35b70e73b Mon Sep 17 00:00:00 2001 From: bsears Date: Fri, 6 Aug 2021 15:18:26 +0000 Subject: Revert "Adds out parameters for crop rectangle and transform" Revert "Add test to crop TextureView and verify if outer edge ha..." Revert submission 15339442-1texelcrop Reason for revert: Bisection identified these CLs as the likely cause of Droidfood blocking bugs b/195620803 and b/195637414 Bug: 195637414 Bug: 195620803 Reverted Changes: If1f448a94:Added crop rect to LayerDrawable to not crop Textu... Iefde6bdf7:Add test to crop TextureView and verify if outer e... Icf0ee20e8:Adds out parameters for crop rectangle and transfo... Change-Id: Ibf58514e70c15470b17a64a8182614dc42c1bc71 (cherry picked from commit 619eea3087b957c464ba1c076d8284b839460e0c) --- libs/nativedisplay/include/surfacetexture/SurfaceTexture.h | 5 ++--- .../include/surfacetexture/surface_texture_platform.h | 6 +++--- libs/nativedisplay/surfacetexture/SurfaceTexture.cpp | 8 +++----- libs/nativedisplay/surfacetexture/surface_texture.cpp | 10 +++++----- 4 files changed, 13 insertions(+), 16 deletions(-) diff --git a/libs/nativedisplay/include/surfacetexture/SurfaceTexture.h b/libs/nativedisplay/include/surfacetexture/SurfaceTexture.h index b8b5a7d221..6eaa84e225 100644 --- a/libs/nativedisplay/include/surfacetexture/SurfaceTexture.h +++ b/libs/nativedisplay/include/surfacetexture/SurfaceTexture.h @@ -272,11 +272,10 @@ public: status_t attachToContext(uint32_t tex); sp dequeueBuffer(int* outSlotid, android_dataspace* outDataspace, - bool* outQueueEmpty, + float* outTransformMatrix, bool* outQueueEmpty, SurfaceTexture_createReleaseFence createFence, SurfaceTexture_fenceWait fenceWait, - void* fencePassThroughHandle, ARect* cropRect, - uint32_t* transform); + void* fencePassThroughHandle); /** * takeConsumerOwnership attaches a SurfaceTexture that is currently in the diff --git a/libs/nativedisplay/include/surfacetexture/surface_texture_platform.h b/libs/nativedisplay/include/surfacetexture/surface_texture_platform.h index 5ae526ff0a..85fe42f6fd 100644 --- a/libs/nativedisplay/include/surfacetexture/surface_texture_platform.h +++ b/libs/nativedisplay/include/surfacetexture/surface_texture_platform.h @@ -83,11 +83,11 @@ typedef int (*ASurfaceTexture_fenceWait)(int fence, void* fencePassThroughHandle * AHardwareBuffer_release. */ AHardwareBuffer* ASurfaceTexture_dequeueBuffer(ASurfaceTexture* st, int* outSlotid, - android_dataspace* outDataspace, bool* outNewContent, + android_dataspace* outDataspace, + float* outTransformMatrix, bool* outNewContent, ASurfaceTexture_createReleaseFence createFence, ASurfaceTexture_fenceWait fenceWait, - void* fencePassThroughHandle, ARect* cropRect, - uint32_t* transform); + void* fencePassThroughHandle); } // namespace android diff --git a/libs/nativedisplay/surfacetexture/SurfaceTexture.cpp b/libs/nativedisplay/surfacetexture/SurfaceTexture.cpp index 06c0f74591..62db6d069f 100644 --- a/libs/nativedisplay/surfacetexture/SurfaceTexture.cpp +++ b/libs/nativedisplay/surfacetexture/SurfaceTexture.cpp @@ -464,11 +464,10 @@ void SurfaceTexture::dumpLocked(String8& result, const char* prefix) const { } sp SurfaceTexture::dequeueBuffer(int* outSlotid, android_dataspace* outDataspace, - bool* outQueueEmpty, + float* outTransformMatrix, bool* outQueueEmpty, SurfaceTexture_createReleaseFence createFence, SurfaceTexture_fenceWait fenceWait, - void* fencePassThroughHandle, ARect* cropRect, - uint32_t* transform) { + void* fencePassThroughHandle) { Mutex::Autolock _l(mMutex); sp buffer; @@ -484,8 +483,7 @@ sp SurfaceTexture::dequeueBuffer(int* outSlotid, android_dataspac buffer = mImageConsumer.dequeueBuffer(outSlotid, outDataspace, outQueueEmpty, *this, createFence, fenceWait, fencePassThroughHandle); - *transform = mCurrentTransform; - *cropRect = mCurrentCrop; + memcpy(outTransformMatrix, mCurrentTransformMatrix, sizeof(mCurrentTransformMatrix)); return buffer; } diff --git a/libs/nativedisplay/surfacetexture/surface_texture.cpp b/libs/nativedisplay/surfacetexture/surface_texture.cpp index 43e7d03f56..c214ab7718 100644 --- a/libs/nativedisplay/surfacetexture/surface_texture.cpp +++ b/libs/nativedisplay/surfacetexture/surface_texture.cpp @@ -193,16 +193,16 @@ void ASurfaceTexture_releaseConsumerOwnership(ASurfaceTexture* texture) { } AHardwareBuffer* ASurfaceTexture_dequeueBuffer(ASurfaceTexture* st, int* outSlotid, - android_dataspace* outDataspace, bool* outNewContent, + android_dataspace* outDataspace, + float* outTransformMatrix, bool* outNewContent, ASurfaceTexture_createReleaseFence createFence, - ASurfaceTexture_fenceWait fenceWait, void* handle, - ARect* cropRect, uint32_t* transform) { + ASurfaceTexture_fenceWait fenceWait, void* handle) { sp buffer; *outNewContent = false; bool queueEmpty; do { - buffer = st->consumer->dequeueBuffer(outSlotid, outDataspace, &queueEmpty, createFence, - fenceWait, handle, cropRect, transform); + buffer = st->consumer->dequeueBuffer(outSlotid, outDataspace, outTransformMatrix, + &queueEmpty, createFence, fenceWait, handle); if (!queueEmpty) { *outNewContent = true; } -- cgit v1.2.3-59-g8ed1b From ffb977f38937087ede800cef30b3ebf3b91d155a Mon Sep 17 00:00:00 2001 From: Jiakai Zhang Date: Tue, 9 Nov 2021 11:46:30 +0000 Subject: Revert "SurfaceFlinger: Emit callbacks for non-buffer layer transactions" This reverts commit da1fd1508c914c7f0849e4e00a5fae5412433337. Reason for revert: Potential culprit CL for broken test b/205501709 Change-Id: Iece745e0690f4d31b93918697b306ded3abfd0d0 (cherry picked from commit a5505cb8fa988023685e8d67fcc8117ee7c63b1e) --- services/surfaceflinger/BufferStateLayer.cpp | 15 ++------ services/surfaceflinger/BufferStateLayer.h | 3 +- services/surfaceflinger/Layer.cpp | 11 ------ services/surfaceflinger/Layer.h | 6 ++- services/surfaceflinger/SurfaceFlinger.cpp | 21 +++++----- .../surfaceflinger/TransactionCallbackInvoker.cpp | 8 ++-- .../surfaceflinger/TransactionCallbackInvoker.h | 12 +++--- .../surfaceflinger/tests/LayerCallback_test.cpp | 45 +--------------------- 8 files changed, 32 insertions(+), 89 deletions(-) diff --git a/services/surfaceflinger/BufferStateLayer.cpp b/services/surfaceflinger/BufferStateLayer.cpp index b6cbbb658f..4f0bbd243b 100644 --- a/services/surfaceflinger/BufferStateLayer.cpp +++ b/services/surfaceflinger/BufferStateLayer.cpp @@ -549,19 +549,13 @@ bool BufferStateLayer::setSidebandStream(const sp& sidebandStream) } bool BufferStateLayer::setTransactionCompletedListeners( - const std::vector& listenerCallbacks, const sp& layerHandle) { + const std::vector>& handles) { // If there is no handle, we will not send a callback so reset mReleasePreviousBuffer and return - if (listenerCallbacks.empty()) { + if (handles.empty()) { mReleasePreviousBuffer = false; return false; } - std::vector> handles; - handles.reserve(listenerCallbacks.size()); - for (auto& [listener, callbackIds] : listenerCallbacks) { - handles.emplace_back(new CallbackHandle(listener, callbackIds, layerHandle)); - } - const bool willPresent = willPresentCurrentTransaction(); for (const auto& handle : handles) { @@ -577,10 +571,9 @@ bool BufferStateLayer::setTransactionCompletedListeners( // Store so latched time and release fence can be set mDrawingState.callbackHandles.push_back(handle); - } else { - // If this layer will NOT need to be relatched and presented this frame + } else { // If this layer will NOT need to be relatched and presented this frame // Notify the transaction completed thread this handle is done - mFlinger->getTransactionCallbackInvoker().addUnpresentedCallbackHandle(handle); + mFlinger->getTransactionCallbackInvoker().registerUnpresentedCallbackHandle(handle); } } diff --git a/services/surfaceflinger/BufferStateLayer.h b/services/surfaceflinger/BufferStateLayer.h index ceed188f0e..eea700cf7b 100644 --- a/services/surfaceflinger/BufferStateLayer.h +++ b/services/surfaceflinger/BufferStateLayer.h @@ -65,8 +65,7 @@ public: bool setSurfaceDamageRegion(const Region& surfaceDamage) override; bool setApi(int32_t api) override; bool setSidebandStream(const sp& sidebandStream) override; - bool setTransactionCompletedListeners(const std::vector& handles, - const sp& layerHandle) override; + bool setTransactionCompletedListeners(const std::vector>& handles) override; bool addFrameEvent(const sp& acquireFence, nsecs_t postedTime, nsecs_t requestedPresentTime) override; bool setPosition(float /*x*/, float /*y*/) override; diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp index d85e843d83..a27c487822 100644 --- a/services/surfaceflinger/Layer.cpp +++ b/services/surfaceflinger/Layer.cpp @@ -2640,17 +2640,6 @@ bool Layer::setDropInputMode(gui::DropInputMode mode) { return true; } -bool Layer::setTransactionCompletedListeners( - const std::vector& listenerCallbacks, const sp&) { - if (listenerCallbacks.empty()) { - return false; - } - for (auto& listener : listenerCallbacks) { - mFlinger->getTransactionCallbackInvoker().addEmptyCallback(listener); - } - return false; -} - // --------------------------------------------------------------------------- std::ostream& operator<<(std::ostream& stream, const Layer::FrameRate& rate) { diff --git a/services/surfaceflinger/Layer.h b/services/surfaceflinger/Layer.h index b79903d11b..297ded043f 100644 --- a/services/surfaceflinger/Layer.h +++ b/services/surfaceflinger/Layer.h @@ -428,8 +428,10 @@ public: virtual bool setSurfaceDamageRegion(const Region& /*surfaceDamage*/) { return false; }; virtual bool setApi(int32_t /*api*/) { return false; }; virtual bool setSidebandStream(const sp& /*sidebandStream*/) { return false; }; - virtual bool setTransactionCompletedListeners(const std::vector& /*handles*/, - const sp& /* layerHandle */); + virtual bool setTransactionCompletedListeners( + const std::vector>& /*handles*/) { + return false; + }; virtual bool addFrameEvent(const sp& /*acquireFence*/, nsecs_t /*postedTime*/, nsecs_t /*requestedPresentTime*/) { return false; diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp index c2dcd70166..6ed9e5fb3e 100644 --- a/services/surfaceflinger/SurfaceFlinger.cpp +++ b/services/surfaceflinger/SurfaceFlinger.cpp @@ -3803,10 +3803,11 @@ bool SurfaceFlinger::applyTransactionState(const FrameTimelineInfo& frameTimelin transactionFlags |= setDisplayStateLocked(display); } - // Add listeners w/ surfaces so they can get their callback. Note that listeners with - // SurfaceControls will start registration during setClientStateLocked below. + // start and end registration for listeners w/ no surface so they can get their callback. Note + // that listeners with SurfaceControls will start registration during setClientStateLocked + // below. for (const auto& listener : listenerCallbacks) { - mTransactionCallbackInvoker.addEmptyCallback(listener); + mTransactionCallbackInvoker.addEmptyTransaction(listener); } uint32_t clientStateFlags = 0; @@ -3978,7 +3979,7 @@ uint32_t SurfaceFlinger::setClientStateLocked(const FrameTimelineInfo& frameTime } if (layer == nullptr) { for (auto& [listener, callbackIds] : s.listeners) { - mTransactionCallbackInvoker.addUnpresentedCallbackHandle( + mTransactionCallbackInvoker.registerUnpresentedCallbackHandle( new CallbackHandle(listener, callbackIds, s.surface)); } return 0; @@ -4249,6 +4250,12 @@ uint32_t SurfaceFlinger::setClientStateLocked(const FrameTimelineInfo& frameTime flags |= eTransactionNeeded | eTraversalNeeded; } } + std::vector> callbackHandles; + if ((what & layer_state_t::eHasListenerCallbacksChanged) && (!filteredListeners.empty())) { + for (auto& [listener, callbackIds] : filteredListeners) { + callbackHandles.emplace_back(new CallbackHandle(listener, callbackIds, s.surface)); + } + } if (what & layer_state_t::eBufferChanged && layer->setBuffer(s.bufferData, postTime, desiredPresentTime, isAutoTimestamp, @@ -4258,11 +4265,7 @@ uint32_t SurfaceFlinger::setClientStateLocked(const FrameTimelineInfo& frameTime layer->setFrameTimelineVsyncForBufferlessTransaction(frameTimelineInfo, postTime); } - if ((what & layer_state_t::eHasListenerCallbacksChanged) && (!filteredListeners.empty())) { - if (layer->setTransactionCompletedListeners(filteredListeners, s.surface)) { - flags |= eTraversalNeeded; - } - } + if (layer->setTransactionCompletedListeners(callbackHandles)) flags |= eTraversalNeeded; // Do not put anything that updates layer state or modifies flags after // setTransactionCompletedListener return flags; diff --git a/services/surfaceflinger/TransactionCallbackInvoker.cpp b/services/surfaceflinger/TransactionCallbackInvoker.cpp index 418fbc5c44..f3d46ea061 100644 --- a/services/surfaceflinger/TransactionCallbackInvoker.cpp +++ b/services/surfaceflinger/TransactionCallbackInvoker.cpp @@ -74,10 +74,10 @@ TransactionCallbackInvoker::~TransactionCallbackInvoker() { } } -void TransactionCallbackInvoker::addEmptyCallback(const ListenerCallbacks& listenerCallbacks) { +void TransactionCallbackInvoker::addEmptyTransaction(const ListenerCallbacks& listenerCallbacks) { auto& [listener, callbackIds] = listenerCallbacks; - TransactionStats* transactionStats; - findOrCreateTransactionStats(listener, callbackIds, &transactionStats); + auto& transactionStatsDeque = mCompletedTransactions[listener]; + transactionStatsDeque.emplace_back(callbackIds); } status_t TransactionCallbackInvoker::addOnCommitCallbackHandles( @@ -116,7 +116,7 @@ status_t TransactionCallbackInvoker::addCallbackHandles( return NO_ERROR; } -status_t TransactionCallbackInvoker::addUnpresentedCallbackHandle( +status_t TransactionCallbackInvoker::registerUnpresentedCallbackHandle( const sp& handle) { return addCallbackHandle(handle, std::vector()); } diff --git a/services/surfaceflinger/TransactionCallbackInvoker.h b/services/surfaceflinger/TransactionCallbackInvoker.h index 6f67947081..e203d41bd9 100644 --- a/services/surfaceflinger/TransactionCallbackInvoker.h +++ b/services/surfaceflinger/TransactionCallbackInvoker.h @@ -71,10 +71,8 @@ public: // Adds the Transaction CallbackHandle from a layer that does not need to be relatched and // presented this frame. - status_t addUnpresentedCallbackHandle(const sp& handle); - // Adds the callback handles for empty transactions or for non-buffer layer updates which do not - // include layer stats. - void addEmptyCallback(const ListenerCallbacks& listenerCallbacks); + status_t registerUnpresentedCallbackHandle(const sp& handle); + void addEmptyTransaction(const ListenerCallbacks& listenerCallbacks); void addPresentFence(const sp& presentFence); @@ -83,12 +81,14 @@ public: mCompletedTransactions.clear(); } + status_t addCallbackHandle(const sp& handle, + const std::vector& jankData); + + private: status_t findOrCreateTransactionStats(const sp& listener, const std::vector& callbackIds, TransactionStats** outTransactionStats); - status_t addCallbackHandle(const sp& handle, - const std::vector& jankData); std::unordered_map, std::deque, IListenerHash> mCompletedTransactions; diff --git a/services/surfaceflinger/tests/LayerCallback_test.cpp b/services/surfaceflinger/tests/LayerCallback_test.cpp index 7beba15062..91a5b528f8 100644 --- a/services/surfaceflinger/tests/LayerCallback_test.cpp +++ b/services/surfaceflinger/tests/LayerCallback_test.cpp @@ -1067,7 +1067,7 @@ TEST_F(LayerCallbackTest, EmptyBufferStateChanges) { } // b202394221 -TEST_F(LayerCallbackTest, NonBufferLayerStateChanges) { +TEST_F(LayerCallbackTest, DISABLED_NonBufferLayerStateChanges) { sp layer; ASSERT_NO_FATAL_FAILURE(layer = createColorLayer("ColorLayer", Color::RED)); @@ -1085,47 +1085,4 @@ TEST_F(LayerCallbackTest, NonBufferLayerStateChanges) { EXPECT_NO_FATAL_FAILURE(waitForCallback(callback, expected, true)); } -class TimedCallbackHelper { -public: - static void function(void* callbackContext, nsecs_t, const sp&, - const std::vector&) { - if (!callbackContext) { - ALOGE("failed to get callback context"); - } - TimedCallbackHelper* helper = static_cast(callbackContext); - std::lock_guard lock(helper->mMutex); - helper->mInvokedTime = systemTime(); - helper->mCv.notify_all(); - } - - void waitForCallback() { - std::unique_lock lock(mMutex); - ASSERT_TRUE(mCv.wait_for(lock, std::chrono::seconds(3), [&] { return mInvokedTime != -1; })) - << "did not receive callback"; - } - void* getContext() { return static_cast(this); } - - std::mutex mMutex; - std::condition_variable mCv; - nsecs_t mInvokedTime = -1; -}; - -TEST_F(LayerCallbackTest, EmptyTransactionCallbackOrder) { - TimedCallbackHelper onCommitCallback; - TimedCallbackHelper onCompleteCallback; - - // Add transaction callback before on commit callback - Transaction() - .addTransactionCompletedCallback(onCompleteCallback.function, - onCompleteCallback.getContext()) - .addTransactionCommittedCallback(onCommitCallback.function, - onCommitCallback.getContext()) - .apply(); - - EXPECT_NO_FATAL_FAILURE(onCompleteCallback.waitForCallback()); - EXPECT_NO_FATAL_FAILURE(onCommitCallback.waitForCallback()); - // verify we get the oncomplete at the same time or after the oncommit callback. - EXPECT_GE(onCompleteCallback.mInvokedTime, onCommitCallback.mInvokedTime); -} - } // namespace android -- cgit v1.2.3-59-g8ed1b From b7abade61054d95592b7b5e482d84d5fa2ea927b Mon Sep 17 00:00:00 2001 From: Daniel Chapin Date: Thu, 9 Dec 2021 18:04:20 +0000 Subject: Revert "Allow for solid color layers to start some candidate cached sets." This reverts commit 028676ae8621c7860f036ec05238a1019f14023b. Reason for revert: Droidfood blocking bug: 209930535 Change-Id: I9e8b4d3c4f61a080d85401aa4a503a7436930a3b (cherry picked from commit d486bdf92f80a068ee35a4e4155811b1238750cf) Merged-In:I9e8b4d3c4f61a080d85401aa4a503a7436930a3b --- .../include/compositionengine/impl/OutputLayer.h | 5 +- .../compositionengine/impl/planner/Flattener.h | 40 ++----- .../CompositionEngine/src/OutputLayer.cpp | 20 ++-- .../CompositionEngine/src/planner/Flattener.cpp | 15 ++- .../CompositionEngine/tests/OutputLayerTest.cpp | 16 --- .../tests/planner/FlattenerTest.cpp | 126 --------------------- 6 files changed, 32 insertions(+), 190 deletions(-) diff --git a/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/OutputLayer.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/OutputLayer.h index c15249d297..244f8ab88b 100644 --- a/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/OutputLayer.h +++ b/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/OutputLayer.h @@ -73,9 +73,8 @@ private: void writeOutputIndependentGeometryStateToHWC(HWC2::Layer*, const LayerFECompositionState&, bool skipLayer); void writeOutputDependentPerFrameStateToHWC(HWC2::Layer*); - void writeOutputIndependentPerFrameStateToHWC( - HWC2::Layer*, const LayerFECompositionState&, - Hwc2::IComposerClient::Composition compositionType, bool skipLayer); + void writeOutputIndependentPerFrameStateToHWC(HWC2::Layer*, const LayerFECompositionState&, + bool skipLayer); void writeSolidColorStateToHWC(HWC2::Layer*, const LayerFECompositionState&); void writeSidebandStateToHWC(HWC2::Layer*, const LayerFECompositionState&); void writeBufferStateToHWC(HWC2::Layer*, const LayerFECompositionState&, bool skipLayer); diff --git a/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/planner/Flattener.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/planner/Flattener.h index 92cc484211..c13204115d 100644 --- a/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/planner/Flattener.h +++ b/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/planner/Flattener.h @@ -134,22 +134,21 @@ private: class Builder { private: std::vector::const_iterator mStart; - int32_t mNumSets = 0; + std::vector mLengths; const CachedSet* mHolePunchCandidate = nullptr; const CachedSet* mBlurringLayer = nullptr; - bool mBuilt = false; public: // Initializes a Builder a CachedSet to start from. // This start iterator must be an iterator for mLayers void init(const std::vector::const_iterator& start) { mStart = start; - mNumSets = 1; + mLengths.push_back(start->getLayerCount()); } // Appends a new CachedSet to the end of the run // The provided length must be the size of the next sequential CachedSet in layers - void increment() { mNumSets++; } + void append(size_t length) { mLengths.push_back(length); } // Sets the hole punch candidate for the Run. void setHolePunchCandidate(const CachedSet* holePunchCandidate) { @@ -162,36 +161,19 @@ private: // Builds a Run instance, if a valid Run may be built. std::optional validateAndBuild() { - const bool built = mBuilt; - mBuilt = true; - if (mNumSets <= 0 || built) { + if (mLengths.size() == 0) { return std::nullopt; } - - const bool requiresHolePunch = - mHolePunchCandidate && mHolePunchCandidate->requiresHolePunch(); - - if (!requiresHolePunch) { - // If we don't require a hole punch, then treat solid color layers at the front - // to be "cheap", so remove them from the candidate cached set. - while (mNumSets > 1 && mStart->getLayerCount() == 1 && - mStart->getFirstLayer().getBuffer() == nullptr) { - mStart++; - mNumSets--; - } - - // Only allow for single cached sets if a hole punch is required. If we're here, - // then we don't require a hole punch, so don't build a run. - if (mNumSets <= 1) { - return std::nullopt; - } + // Runs of length 1 which are hole punch candidates are allowed if the candidate is + // going to be used. + if (mLengths.size() == 1 && + (!mHolePunchCandidate || !(mHolePunchCandidate->requiresHolePunch()))) { + return std::nullopt; } return Run(mStart, - std::reduce(mStart, mStart + mNumSets, 0u, - [](size_t length, const CachedSet& set) { - return length + set.getLayerCount(); - }), + std::reduce(mLengths.cbegin(), mLengths.cend(), 0u, + [](size_t left, size_t right) { return left + right; }), mHolePunchCandidate, mBlurringLayer); } diff --git a/services/surfaceflinger/CompositionEngine/src/OutputLayer.cpp b/services/surfaceflinger/CompositionEngine/src/OutputLayer.cpp index cf761835a6..e958549569 100644 --- a/services/surfaceflinger/CompositionEngine/src/OutputLayer.cpp +++ b/services/surfaceflinger/CompositionEngine/src/OutputLayer.cpp @@ -347,10 +347,6 @@ void OutputLayer::writeStateToHWC(bool includeGeometry, bool skipLayer, uint32_t auto requestedCompositionType = outputIndependentState->compositionType; - if (requestedCompositionType == hal::Composition::SOLID_COLOR && state.overrideInfo.buffer) { - requestedCompositionType = hal::Composition::DEVICE; - } - // TODO(b/181172795): We now update geometry for all flattened layers. We should update it // only when the geometry actually changes const bool isOverridden = @@ -363,15 +359,13 @@ void OutputLayer::writeStateToHWC(bool includeGeometry, bool skipLayer, uint32_t } writeOutputDependentPerFrameStateToHWC(hwcLayer.get()); - writeOutputIndependentPerFrameStateToHWC(hwcLayer.get(), *outputIndependentState, - requestedCompositionType, skipLayer); + writeOutputIndependentPerFrameStateToHWC(hwcLayer.get(), *outputIndependentState, skipLayer); writeCompositionTypeToHWC(hwcLayer.get(), requestedCompositionType, isPeekingThrough, skipLayer); - if (requestedCompositionType == hal::Composition::SOLID_COLOR) { - writeSolidColorStateToHWC(hwcLayer.get(), *outputIndependentState); - } + // Always set the layer color after setting the composition type. + writeSolidColorStateToHWC(hwcLayer.get(), *outputIndependentState); editState().hwc->stateOverridden = isOverridden; editState().hwc->layerSkipped = skipLayer; @@ -483,7 +477,7 @@ void OutputLayer::writeOutputDependentPerFrameStateToHWC(HWC2::Layer* hwcLayer) void OutputLayer::writeOutputIndependentPerFrameStateToHWC( HWC2::Layer* hwcLayer, const LayerFECompositionState& outputIndependentState, - hal::Composition compositionType, bool skipLayer) { + bool skipLayer) { switch (auto error = hwcLayer->setColorTransform(outputIndependentState.colorTransform)) { case hal::Error::NONE: break; @@ -507,7 +501,7 @@ void OutputLayer::writeOutputIndependentPerFrameStateToHWC( } // Content-specific per-frame state - switch (compositionType) { + switch (outputIndependentState.compositionType) { case hal::Composition::SOLID_COLOR: // For compatibility, should be written AFTER the composition type. break; @@ -527,6 +521,10 @@ void OutputLayer::writeOutputIndependentPerFrameStateToHWC( void OutputLayer::writeSolidColorStateToHWC(HWC2::Layer* hwcLayer, const LayerFECompositionState& outputIndependentState) { + if (outputIndependentState.compositionType != hal::Composition::SOLID_COLOR) { + return; + } + hal::Color 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)), diff --git a/services/surfaceflinger/CompositionEngine/src/planner/Flattener.cpp b/services/surfaceflinger/CompositionEngine/src/planner/Flattener.cpp index c14effccc3..8a476c5ec6 100644 --- a/services/surfaceflinger/CompositionEngine/src/planner/Flattener.cpp +++ b/services/surfaceflinger/CompositionEngine/src/planner/Flattener.cpp @@ -425,13 +425,18 @@ std::vector Flattener::findCandidateRuns(time_point now) const { if (layerIsInactive && (firstLayer || runHasFirstLayer || !layerHasBlur) && !currentSet->hasUnsupportedDataspace()) { if (isPartOfRun) { - builder.increment(); + builder.append(currentSet->getLayerCount()); } else { - builder.init(currentSet); - if (firstLayer) { - runHasFirstLayer = true; + // Runs can't start with a non-buffer layer + if (currentSet->getFirstLayer().getBuffer() == nullptr) { + ALOGV("[%s] Skipping initial non-buffer layer", __func__); + } else { + builder.init(currentSet); + if (firstLayer) { + runHasFirstLayer = true; + } + isPartOfRun = true; } - isPartOfRun = true; } } else if (isPartOfRun) { builder.setHolePunchCandidate(&(*currentSet)); diff --git a/services/surfaceflinger/CompositionEngine/tests/OutputLayerTest.cpp b/services/surfaceflinger/CompositionEngine/tests/OutputLayerTest.cpp index 31b131ad74..fbc20898ec 100644 --- a/services/surfaceflinger/CompositionEngine/tests/OutputLayerTest.cpp +++ b/services/surfaceflinger/CompositionEngine/tests/OutputLayerTest.cpp @@ -1109,22 +1109,6 @@ TEST_F(OutputLayerWriteStateToHWCTest, includesOverrideInfoIfPresent) { /*zIsOverridden*/ false, /*isPeekingThrough*/ false); } -TEST_F(OutputLayerWriteStateToHWCTest, includesOverrideInfoForSolidColorIfPresent) { - mLayerFEState.compositionType = Hwc2::IComposerClient::Composition::SOLID_COLOR; - includeOverrideInfo(); - - expectGeometryCommonCalls(kOverrideDisplayFrame, kOverrideSourceCrop, kOverrideBufferTransform, - kOverrideBlendMode, kOverrideAlpha); - expectPerFrameCommonCalls(SimulateUnsupported::None, kOverrideDataspace, kOverrideVisibleRegion, - kOverrideSurfaceDamage); - expectSetHdrMetadataAndBufferCalls(kOverrideHwcSlot, kOverrideBuffer, kOverrideFence); - expectSetCompositionTypeCall(Hwc2::IComposerClient::Composition::DEVICE); - EXPECT_CALL(*mLayerFE, hasRoundedCorners()).WillRepeatedly(Return(false)); - - mOutputLayer.writeStateToHWC(/*includeGeometry*/ true, /*skipLayer*/ false, 0, - /*zIsOverridden*/ false, /*isPeekingThrough*/ false); -} - TEST_F(OutputLayerWriteStateToHWCTest, previousOverriddenLayerSendsSurfaceDamage) { mLayerFEState.compositionType = Hwc2::IComposerClient::Composition::DEVICE; mOutputLayer.editState().hwc->stateOverridden = true; diff --git a/services/surfaceflinger/CompositionEngine/tests/planner/FlattenerTest.cpp b/services/surfaceflinger/CompositionEngine/tests/planner/FlattenerTest.cpp index 35d051ebea..6fbcc759c2 100644 --- a/services/surfaceflinger/CompositionEngine/tests/planner/FlattenerTest.cpp +++ b/services/surfaceflinger/CompositionEngine/tests/planner/FlattenerTest.cpp @@ -762,76 +762,6 @@ TEST_F(FlattenerTest, flattenLayers_holePunchSingleLayer) { EXPECT_EQ(nullptr, peekThroughLayer1); } -TEST_F(FlattenerTest, flattenLayers_holePunchSingleColorLayer) { - mTestLayers[0]->outputLayerCompositionState.displayFrame = Rect(0, 0, 5, 5); - mTestLayers[0]->layerFECompositionState.color = half4(255.f, 0.f, 0.f, 255.f); - mTestLayers[0]->layerFECompositionState.buffer = nullptr; - - // An opaque static background - auto& layerState0 = mTestLayers[0]->layerState; - const auto& overrideBuffer0 = layerState0->getOutputLayer()->getState().overrideInfo.buffer; - - // a rounded updating layer - auto& layerState1 = mTestLayers[1]->layerState; - const auto& overrideBuffer1 = layerState1->getOutputLayer()->getState().overrideInfo.buffer; - - EXPECT_CALL(*mTestLayers[1]->layerFE, hasRoundedCorners()).WillRepeatedly(Return(true)); - - std::vector clientCompositionList = { - LayerFE::LayerSettings{}, - }; - clientCompositionList[0].source.buffer.buffer = std::make_shared< - renderengine::ExternalTexture>(mTestLayers[1]->layerFECompositionState.buffer, - mRenderEngine, - renderengine::ExternalTexture::Usage::READABLE); - EXPECT_CALL(*mTestLayers[1]->layerFE, prepareClientCompositionList(_)) - .WillOnce(Return(clientCompositionList)); - - const std::vector layers = { - layerState0.get(), - layerState1.get(), - }; - - initializeFlattener(layers); - - // layer 1 satisfies every condition in CachedSet::requiresHolePunch() - mTime += 200ms; - layerState1->resetFramesSinceBufferUpdate(); // it is updating - - initializeOverrideBuffer(layers); - // Expect no cache invalidation the first time (there's no cache yet) - EXPECT_EQ(getNonBufferHash(layers), - mFlattener->flattenLayers(layers, getNonBufferHash(layers), mTime)); - - // This will render a CachedSet of layer 0. Though it is just one layer, it satisfies the - // exception that there would be a hole punch above it. - EXPECT_CALL(mRenderEngine, drawLayers(_, _, _, _, _)) - .WillOnce(Return(ByMove( - futureOf({NO_ERROR, base::unique_fd()})))); - mFlattener->renderCachedSets(mOutputState, std::nullopt); - - // We've rendered a CachedSet, but we haven't merged it in. - EXPECT_EQ(nullptr, overrideBuffer0); - - // This time we merge the CachedSet in and we should still have only two sets. - EXPECT_CALL(mRenderEngine, drawLayers(_, _, _, _, _)).Times(0); - initializeOverrideBuffer(layers); - EXPECT_EQ(getNonBufferHash(layers), - mFlattener->flattenLayers(layers, getNonBufferHash(layers), mTime)); - mFlattener->renderCachedSets(mOutputState, std::nullopt); - - EXPECT_NE(nullptr, overrideBuffer0); // got overridden - EXPECT_EQ(nullptr, overrideBuffer1); // did not - - // expect 0's peek though layer to be 1's output layer - const auto* peekThroughLayer0 = - layerState0->getOutputLayer()->getState().overrideInfo.peekThroughLayer; - const auto* peekThroughLayer1 = - layerState1->getOutputLayer()->getState().overrideInfo.peekThroughLayer; - EXPECT_EQ(&mTestLayers[1]->outputLayer, peekThroughLayer0); - EXPECT_EQ(nullptr, peekThroughLayer1); -} - TEST_F(FlattenerTest, flattenLayers_flattensBlurBehindRunIfFirstRun) { auto& layerState1 = mTestLayers[0]->layerState; @@ -1277,61 +1207,5 @@ TEST_F(FlattenerTest, flattenLayers_skipsHDR2) { EXPECT_EQ(nullptr, overrideBuffer3); } -TEST_F(FlattenerTest, flattenLayers_skipsColorLayers) { - auto& layerState1 = mTestLayers[0]->layerState; - const auto& overrideBuffer1 = layerState1->getOutputLayer()->getState().overrideInfo.buffer; - auto& layerState2 = mTestLayers[1]->layerState; - const auto& overrideBuffer2 = layerState2->getOutputLayer()->getState().overrideInfo.buffer; - auto& layerState3 = mTestLayers[2]->layerState; - const auto& overrideBuffer3 = layerState3->getOutputLayer()->getState().overrideInfo.buffer; - auto& layerState4 = mTestLayers[3]->layerState; - const auto& overrideBuffer4 = layerState4->getOutputLayer()->getState().overrideInfo.buffer; - - // Rewrite the first two layers to just be a solid color. - mTestLayers[0]->layerFECompositionState.color = half4(255.f, 0.f, 0.f, 255.f); - mTestLayers[0]->layerFECompositionState.buffer = nullptr; - mTestLayers[1]->layerFECompositionState.color = half4(0.f, 255.f, 0.f, 255.f); - mTestLayers[1]->layerFECompositionState.buffer = nullptr; - - const std::vector layers = { - layerState1.get(), - layerState2.get(), - layerState3.get(), - layerState4.get(), - }; - - initializeFlattener(layers); - - mTime += 200ms; - initializeOverrideBuffer(layers); - EXPECT_EQ(getNonBufferHash(layers), - mFlattener->flattenLayers(layers, getNonBufferHash(layers), mTime)); - - // This will render a CachedSet. - EXPECT_CALL(mRenderEngine, drawLayers(_, _, _, _, _)) - .WillOnce(Return(ByMove( - futureOf({NO_ERROR, base::unique_fd()})))); - mFlattener->renderCachedSets(mOutputState, std::nullopt); - - // We've rendered a CachedSet, but we haven't merged it in. - EXPECT_EQ(nullptr, overrideBuffer1); - EXPECT_EQ(nullptr, overrideBuffer2); - EXPECT_EQ(nullptr, overrideBuffer3); - EXPECT_EQ(nullptr, overrideBuffer4); - - // This time we merge the CachedSet in, so we have a new hash, and we should - // only have two sets. - EXPECT_CALL(mRenderEngine, drawLayers(_, _, _, _, _)).Times(0); - initializeOverrideBuffer(layers); - EXPECT_NE(getNonBufferHash(layers), - mFlattener->flattenLayers(layers, getNonBufferHash(layers), mTime)); - mFlattener->renderCachedSets(mOutputState, std::nullopt); - - EXPECT_EQ(nullptr, overrideBuffer1); - EXPECT_EQ(nullptr, overrideBuffer2); - EXPECT_EQ(overrideBuffer3, overrideBuffer4); - EXPECT_NE(nullptr, overrideBuffer4); -} - } // namespace } // namespace android::compositionengine -- cgit v1.2.3-59-g8ed1b From ef5a6a8e3dd85f42cd59f3c2409eeeac2c76c31f Mon Sep 17 00:00:00 2001 From: Leon Scroggins Date: Thu, 23 Dec 2021 15:28:46 +0000 Subject: Revert "Allow changing composition from DISPLAY_DECORATION to DEVICE" Revert submission 16511727-wm_DISPLAY_DECORATION Reason for revert: b/211835607 Reverted Changes: I1da3199ba:Allow changing composition from DISPLAY_DECORATION... I1fae74b36:Update documentation for DISPLAY_DECORATION I1da03a88f:Add eLayerIsDisplayDecoration flag I7f22dfd03:Add/plumb SurfaceControl.DISPLAY_DECORATION Change-Id: Ifa4d06453b5707626c614aad203c727681e23fed (cherry picked from commit c3e9a90b93f05a12bd3e0c1ec57d3a3cd103c0ab) Merged-In:Ifa4d06453b5707626c614aad203c727681e23fed --- services/surfaceflinger/CompositionEngine/src/OutputLayer.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/services/surfaceflinger/CompositionEngine/src/OutputLayer.cpp b/services/surfaceflinger/CompositionEngine/src/OutputLayer.cpp index 545e2a2fba..94ad6c3a12 100644 --- a/services/surfaceflinger/CompositionEngine/src/OutputLayer.cpp +++ b/services/surfaceflinger/CompositionEngine/src/OutputLayer.cpp @@ -685,12 +685,12 @@ void OutputLayer::detectDisallowedCompositionTypeChange(Composition from, Compos case Composition::DEVICE: case Composition::SOLID_COLOR: + case Composition::DISPLAY_DECORATION: result = (to == Composition::CLIENT); break; case Composition::CURSOR: case Composition::SIDEBAND: - case Composition::DISPLAY_DECORATION: result = (to == Composition::CLIENT || to == Composition::DEVICE); break; } -- cgit v1.2.3-59-g8ed1b From d4fd86496022af942d52ff54539b5fb4908434b8 Mon Sep 17 00:00:00 2001 From: Leon Scroggins Date: Thu, 23 Dec 2021 15:28:46 +0000 Subject: Revert "Add eLayerIsDisplayDecoration flag" Revert submission 16511727-wm_DISPLAY_DECORATION Reason for revert: b/211835607 Reverted Changes: I1da3199ba:Allow changing composition from DISPLAY_DECORATION... I1fae74b36:Update documentation for DISPLAY_DECORATION I1da03a88f:Add eLayerIsDisplayDecoration flag I7f22dfd03:Add/plumb SurfaceControl.DISPLAY_DECORATION Change-Id: I449e1bb74e0d197661033bf114a25ae6ec04e418 (cherry picked from commit 27609c37d83abfb52b7f448e9cbcce627af93416) Merged-In:I449e1bb74e0d197661033bf114a25ae6ec04e418 --- libs/gui/SurfaceComposerClient.cpp | 3 +-- libs/gui/include/gui/LayerState.h | 1 - services/surfaceflinger/BufferLayer.cpp | 3 --- services/surfaceflinger/SurfaceFlinger.cpp | 24 ++---------------------- 4 files changed, 3 insertions(+), 28 deletions(-) diff --git a/libs/gui/SurfaceComposerClient.cpp b/libs/gui/SurfaceComposerClient.cpp index cf04ec8051..aafa5e470d 100644 --- a/libs/gui/SurfaceComposerClient.cpp +++ b/libs/gui/SurfaceComposerClient.cpp @@ -1104,8 +1104,7 @@ SurfaceComposerClient::Transaction& SurfaceComposerClient::Transaction::setFlags } if ((mask & layer_state_t::eLayerOpaque) || (mask & layer_state_t::eLayerHidden) || (mask & layer_state_t::eLayerSecure) || (mask & layer_state_t::eLayerSkipScreenshot) || - (mask & layer_state_t::eEnableBackpressure) || - (mask & layer_state_t::eLayerIsDisplayDecoration)) { + (mask & layer_state_t::eEnableBackpressure)) { s->what |= layer_state_t::eFlagsChanged; } s->flags &= ~mask; diff --git a/libs/gui/include/gui/LayerState.h b/libs/gui/include/gui/LayerState.h index a0d3162afe..b01eed4d3c 100644 --- a/libs/gui/include/gui/LayerState.h +++ b/libs/gui/include/gui/LayerState.h @@ -109,7 +109,6 @@ struct layer_state_t { // set. This blocks the client until all the buffers have been presented. If the buffers // have presentation timestamps, then we may drop buffers. eEnableBackpressure = 0x100, // ENABLE_BACKPRESSURE - eLayerIsDisplayDecoration = 0x200, // DISPLAY_DECORATION }; enum { diff --git a/services/surfaceflinger/BufferLayer.cpp b/services/surfaceflinger/BufferLayer.cpp index d61a4cbd01..e26c763f4e 100644 --- a/services/surfaceflinger/BufferLayer.cpp +++ b/services/surfaceflinger/BufferLayer.cpp @@ -295,9 +295,6 @@ void BufferLayer::preparePerFrameCompositionState() { compositionState->compositionType = aidl::android::hardware::graphics::composer3::Composition::SIDEBAND; return; - } else if ((mDrawingState.flags & layer_state_t::eLayerIsDisplayDecoration) != 0) { - compositionState->compositionType = - aidl::android::hardware::graphics::composer3::Composition::DISPLAY_DECORATION; } else { // Normal buffer layers compositionState->hdrMetadata = mBufferInfo.mHdrMetadata; diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp index 2fc3dde469..80ca8a3cda 100644 --- a/services/surfaceflinger/SurfaceFlinger.cpp +++ b/services/surfaceflinger/SurfaceFlinger.cpp @@ -269,7 +269,6 @@ bool validateCompositionDataspace(Dataspace dataspace) { enum Permission { ACCESS_SURFACE_FLINGER = 0x1, ROTATE_SURFACE_FLINGER = 0x2, - INTERNAL_SYSTEM_WINDOW = 0x4, }; struct IdleTimerConfig { @@ -317,7 +316,6 @@ const String16 sReadFramebuffer("android.permission.READ_FRAME_BUFFER"); const String16 sControlDisplayBrightness("android.permission.CONTROL_DISPLAY_BRIGHTNESS"); const String16 sDump("android.permission.DUMP"); const String16 sCaptureBlackoutContent("android.permission.CAPTURE_BLACKOUT_CONTENT"); -const String16 sInternalSystemWindow("android.permission.INTERNAL_SYSTEM_WINDOW"); const char* KERNEL_IDLE_TIMER_PROP = "graphics.display.kernel_idle_timer.enabled"; @@ -360,13 +358,6 @@ bool callingThreadHasRotateSurfaceFlingerAccess() { PermissionCache::checkPermission(sRotateSurfaceFlinger, pid, uid); } -bool callingThreadHasInternalSystemWindowAccess() { - IPCThreadState* ipc = IPCThreadState::self(); - const int pid = ipc->getCallingPid(); - const int uid = ipc->getCallingUid(); - return PermissionCache::checkPermission(sInternalSystemWindow, pid, uid); -} - SurfaceFlinger::SurfaceFlinger(Factory& factory, SkipInitializationTag) : mFactory(factory), mPid(getpid()), @@ -3819,10 +3810,6 @@ status_t SurfaceFlinger::setTransactionState( permissions |= Permission::ROTATE_SURFACE_FLINGER; } - if (callingThreadHasInternalSystemWindowAccess()) { - permissions |= Permission::INTERNAL_SYSTEM_WINDOW; - } - if (!(permissions & Permission::ACCESS_SURFACE_FLINGER) && (flags & (eEarlyWakeupStart | eEarlyWakeupEnd))) { ALOGE("Only WindowManager is allowed to use eEarlyWakeup[Start|End] flags"); @@ -4160,15 +4147,8 @@ uint32_t SurfaceFlinger::setClientStateLocked(const FrameTimelineInfo& frameTime flags |= eTraversalNeeded; } if (what & layer_state_t::eFlagsChanged) { - auto changedFlags = s.flags; - if (changedFlags & layer_state_t::eLayerIsDisplayDecoration) { - if ((permissions & Permission::INTERNAL_SYSTEM_WINDOW) == 0) { - changedFlags &= ~layer_state_t::eLayerIsDisplayDecoration; - ALOGE("Attempt to use eLayerIsDisplayDecoration without permission " - "INTERNAL_SYSTEM_WINDOW!"); - } - } - if (layer->setFlags(changedFlags, s.mask)) flags |= eTraversalNeeded; + if (layer->setFlags(s.flags, s.mask)) + flags |= eTraversalNeeded; } if (what & layer_state_t::eCornerRadiusChanged) { if (layer->setCornerRadius(s.cornerRadius)) -- cgit v1.2.3-59-g8ed1b From aab9f95b058d508d962ec726fd862068ce70e0f3 Mon Sep 17 00:00:00 2001 From: Robert Carr Date: Wed, 9 Mar 2022 13:49:13 -0800 Subject: Revert "SF: Enable HWC composition strategy prediction" This reverts commit f0b2b014eb025d0d889ca2d68bd0ff5d95ee6e40. Change-Id: Idee6c3cac6cadf15e7042243c706c640b70ce3e9 Bug:223543469 (cherry picked from commit 279209ba77fed81d81a378266659e4de22124de1) Merged-In: Idee6c3cac6cadf15e7042243c706c640b70ce3e9 --- services/surfaceflinger/SurfaceFlinger.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp index d4979e8b86..53ac95bb2b 100644 --- a/services/surfaceflinger/SurfaceFlinger.cpp +++ b/services/surfaceflinger/SurfaceFlinger.cpp @@ -482,7 +482,7 @@ SurfaceFlinger::SurfaceFlinger(Factory& factory) : SurfaceFlinger(factory, SkipI property_get("debug.sf.disable_client_composition_cache", value, "0"); mDisableClientCompositionCache = atoi(value); - property_get("debug.sf.predict_hwc_composition_strategy", value, "1"); + property_get("debug.sf.predict_hwc_composition_strategy", value, "0"); mPredictCompositionStrategy = atoi(value); // We should be reading 'persist.sys.sf.color_saturation' here -- cgit v1.2.3-59-g8ed1b From cf6eb0370ecf19dff9b1e438a8c3784c0891081f Mon Sep 17 00:00:00 2001 From: Robert Carr Date: Wed, 9 Mar 2022 13:49:30 -0800 Subject: Revert "SF: Add composition strategy prediction stats" This reverts commit 47183ae01af735473ec636e16aa8293da839efac. Change-Id: I92f9f0e7fdd56a8749207a88887e1f23e25ee924 Bug: 223543469 (cherry picked from commit 779ca498203d3c7e6f9555952b4a1ba8c0363010) Merged-In: I92f9f0e7fdd56a8749207a88887e1f23e25ee924 --- .../compositionengine/impl/GpuCompositionResult.h | 3 + .../impl/OutputCompositionState.h | 12 ---- .../CompositionEngine/src/Output.cpp | 13 ++-- .../src/OutputCompositionState.cpp | 14 ----- .../CompositionEngine/tests/OutputTest.cpp | 18 +++--- services/surfaceflinger/SurfaceFlinger.cpp | 41 ++++++------ services/surfaceflinger/TimeStats/TimeStats.cpp | 34 ++++++---- services/surfaceflinger/TimeStats/TimeStats.h | 32 +++------- .../TimeStats/timestatsproto/TimeStatsHelper.cpp | 8 --- .../include/timestatsproto/TimeStatsHelper.h | 2 - .../tests/unittests/TimeStatsTest.cpp | 73 ++++++++-------------- .../tests/unittests/mock/MockTimeStats.h | 5 +- 12 files changed, 100 insertions(+), 155 deletions(-) diff --git a/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/GpuCompositionResult.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/GpuCompositionResult.h index 2b1f50ff57..ed1ddc172c 100644 --- a/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/GpuCompositionResult.h +++ b/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/GpuCompositionResult.h @@ -22,6 +22,9 @@ namespace android::compositionengine::impl { struct GpuCompositionResult { + // True if composition strategy was predicted successfully. + bool succeeded = false; + // Composition ready fence. base::unique_fd fence{}; diff --git a/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/OutputCompositionState.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/OutputCompositionState.h index ade9b25b63..92f22b6a16 100644 --- a/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/OutputCompositionState.h +++ b/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/OutputCompositionState.h @@ -141,18 +141,6 @@ struct OutputCompositionState { // This is slightly distinct from nits, in that nits cannot be passed to hw composer. std::optional displayBrightness = std::nullopt; - enum class CompositionStrategyPredictionState : uint32_t { - // Composition strategy prediction did not run for this frame. - DISABLED = 0, - // Composition strategy predicted successfully for this frame. - SUCCESS = 1, - // Composition strategy prediction failed for this frame. - FAIL = 2, - }; - - CompositionStrategyPredictionState strategyPrediction = - CompositionStrategyPredictionState::DISABLED; - // Debugging void dump(std::string& result) const; }; diff --git a/services/surfaceflinger/CompositionEngine/src/Output.cpp b/services/surfaceflinger/CompositionEngine/src/Output.cpp index e4bd325f99..8d560d732c 100644 --- a/services/surfaceflinger/CompositionEngine/src/Output.cpp +++ b/services/surfaceflinger/CompositionEngine/src/Output.cpp @@ -58,8 +58,7 @@ namespace android::compositionengine { Output::~Output() = default; namespace impl { -using CompositionStrategyPredictionState = - OutputCompositionState::CompositionStrategyPredictionState; + namespace { template @@ -967,7 +966,6 @@ void Output::prepareFrame() { } auto changes = chooseCompositionStrategy(); - outputState.strategyPrediction = CompositionStrategyPredictionState::DISABLED; outputState.previousDeviceRequestedChanges = changes; if (changes) { applyCompositionStrategy(changes); @@ -1004,8 +1002,7 @@ GpuCompositionResult Output::prepareFrameAsync(const CompositionRefreshArgs& ref auto changes = hwcResult.valid() ? hwcResult.get() : std::nullopt; const bool predictionSucceeded = dequeueSucceeded && changes == previousChanges; - state.strategyPrediction = predictionSucceeded ? CompositionStrategyPredictionState::SUCCESS - : CompositionStrategyPredictionState::FAIL; + compositionResult.succeeded = predictionSucceeded; if (!predictionSucceeded) { ATRACE_NAME("CompositionStrategyPredictionMiss"); if (changes) { @@ -1047,15 +1044,15 @@ void Output::devOptRepaintFlash(const compositionengine::CompositionRefreshArgs& void Output::finishFrame(const CompositionRefreshArgs& refreshArgs, GpuCompositionResult&& result) { ATRACE_CALL(); ALOGV(__FUNCTION__); - const auto& outputState = getState(); - if (!outputState.isEnabled) { + + if (!getState().isEnabled) { return; } std::optional optReadyFence; std::shared_ptr buffer; base::unique_fd bufferFence; - if (outputState.strategyPrediction == CompositionStrategyPredictionState::SUCCESS) { + if (result.succeeded) { optReadyFence = std::move(result.fence); } else { if (result.bufferAvailable()) { diff --git a/services/surfaceflinger/CompositionEngine/src/OutputCompositionState.cpp b/services/surfaceflinger/CompositionEngine/src/OutputCompositionState.cpp index 7188281974..482250a165 100644 --- a/services/surfaceflinger/CompositionEngine/src/OutputCompositionState.cpp +++ b/services/surfaceflinger/CompositionEngine/src/OutputCompositionState.cpp @@ -18,19 +18,6 @@ #include namespace android::compositionengine::impl { -using CompositionStrategyPredictionState = - OutputCompositionState::CompositionStrategyPredictionState; - -std::string toString(CompositionStrategyPredictionState state) { - switch (state) { - case CompositionStrategyPredictionState::DISABLED: - return "Disabled"; - case CompositionStrategyPredictionState::SUCCESS: - return "Success"; - case CompositionStrategyPredictionState::FAIL: - return "Fail"; - } -} void OutputCompositionState::dump(std::string& out) const { out.append(" "); @@ -69,7 +56,6 @@ void OutputCompositionState::dump(std::string& out) const { dumpVal(out, "sdrWhitePointNits", sdrWhitePointNits); dumpVal(out, "clientTargetBrightness", clientTargetBrightness); dumpVal(out, "displayBrightness", displayBrightness); - dumpVal(out, "compositionStrategyPredictionState", toString(strategyPrediction)); out.append("\n"); } diff --git a/services/surfaceflinger/CompositionEngine/tests/OutputTest.cpp b/services/surfaceflinger/CompositionEngine/tests/OutputTest.cpp index 0c5ea79350..4e875c8a25 100644 --- a/services/surfaceflinger/CompositionEngine/tests/OutputTest.cpp +++ b/services/surfaceflinger/CompositionEngine/tests/OutputTest.cpp @@ -74,9 +74,6 @@ const mat4 kNonIdentityQuarter = mat4() * 0.25f; constexpr OutputColorSetting kVendorSpecifiedOutputColorSetting = static_cast(0x100); -using CompositionStrategyPredictionState = android::compositionengine::impl:: - OutputCompositionState::CompositionStrategyPredictionState; - struct OutputPartialMockBase : public impl::Output { // compositionengine::Output overrides const OutputCompositionState& getState() const override { return mState; } @@ -1024,7 +1021,6 @@ TEST_F(OutputPrepareFrameTest, delegatesToChooseCompositionStrategyAndRenderSurf EXPECT_CALL(*mRenderSurface, prepareFrame(false, true)); mOutput.prepareFrame(); - EXPECT_EQ(mOutput.getState().strategyPrediction, CompositionStrategyPredictionState::DISABLED); } // Note: Use OutputTest and not OutputPrepareFrameTest, so the real @@ -1040,7 +1036,6 @@ TEST_F(OutputTest, prepareFrameSetsClientCompositionOnlyByDefault) { EXPECT_TRUE(mOutput->getState().usesClientComposition); EXPECT_FALSE(mOutput->getState().usesDeviceComposition); - EXPECT_EQ(mOutput->getState().strategyPrediction, CompositionStrategyPredictionState::DISABLED); } struct OutputPrepareFrameAsyncTest : public testing::Test { @@ -1089,7 +1084,7 @@ TEST_F(OutputPrepareFrameAsyncTest, delegatesToChooseCompositionStrategyAndRende EXPECT_CALL(mOutput, composeSurfaces(_, Ref(mRefreshArgs), _, _)); impl::GpuCompositionResult result = mOutput.prepareFrameAsync(mRefreshArgs); - EXPECT_EQ(mOutput.getState().strategyPrediction, CompositionStrategyPredictionState::SUCCESS); + EXPECT_TRUE(result.succeeded); EXPECT_FALSE(result.bufferAvailable()); } @@ -1109,7 +1104,7 @@ TEST_F(OutputPrepareFrameAsyncTest, skipCompositionOnDequeueFailure) { EXPECT_CALL(mOutput, chooseCompositionStrategyAsync()).WillOnce([&] { return p.get_future(); }); impl::GpuCompositionResult result = mOutput.prepareFrameAsync(mRefreshArgs); - EXPECT_EQ(mOutput.getState().strategyPrediction, CompositionStrategyPredictionState::FAIL); + EXPECT_FALSE(result.succeeded); EXPECT_FALSE(result.bufferAvailable()); } @@ -1137,7 +1132,7 @@ TEST_F(OutputPrepareFrameAsyncTest, chooseCompositionStrategyFailureCallsPrepare EXPECT_CALL(mOutput, composeSurfaces(_, Ref(mRefreshArgs), _, _)); impl::GpuCompositionResult result = mOutput.prepareFrameAsync(mRefreshArgs); - EXPECT_EQ(mOutput.getState().strategyPrediction, CompositionStrategyPredictionState::FAIL); + EXPECT_FALSE(result.succeeded); EXPECT_TRUE(result.bufferAvailable()); } @@ -1166,7 +1161,7 @@ TEST_F(OutputPrepareFrameAsyncTest, predictionMiss) { EXPECT_CALL(mOutput, composeSurfaces(_, Ref(mRefreshArgs), _, _)); impl::GpuCompositionResult result = mOutput.prepareFrameAsync(mRefreshArgs); - EXPECT_EQ(mOutput.getState().strategyPrediction, CompositionStrategyPredictionState::FAIL); + EXPECT_FALSE(result.succeeded); EXPECT_TRUE(result.bufferAvailable()); } @@ -3010,21 +3005,22 @@ TEST_F(OutputFinishFrameTest, queuesBufferIfComposeSurfacesReturnsAFence) { TEST_F(OutputFinishFrameTest, predictionSucceeded) { mOutput.mState.isEnabled = true; - mOutput.mState.strategyPrediction = CompositionStrategyPredictionState::SUCCESS; + InSequence seq; EXPECT_CALL(*mRenderSurface, queueBuffer(_)); impl::GpuCompositionResult result; + result.succeeded = true; mOutput.finishFrame(mRefreshArgs, std::move(result)); } TEST_F(OutputFinishFrameTest, predictionFailedAndBufferIsReused) { mOutput.mState.isEnabled = true; - mOutput.mState.strategyPrediction = CompositionStrategyPredictionState::FAIL; InSequence seq; impl::GpuCompositionResult result; + result.succeeded = false; result.buffer = std::make_shared(1, 1, HAL_PIXEL_FORMAT_RGBA_8888, 1, diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp index 53ac95bb2b..b47611c149 100644 --- a/services/surfaceflinger/SurfaceFlinger.cpp +++ b/services/surfaceflinger/SurfaceFlinger.cpp @@ -169,8 +169,6 @@ using aidl::android::hardware::graphics::common::DisplayDecorationSupport; using aidl::android::hardware::graphics::composer3::Capability; using aidl::android::hardware::graphics::composer3::DisplayCapability; -using CompositionStrategyPredictionState = android::compositionengine::impl:: - OutputCompositionState::CompositionStrategyPredictionState; namespace android { @@ -2272,24 +2270,24 @@ void SurfaceFlinger::composite(nsecs_t frameTime) { const bool prevFrameHadClientComposition = mHadClientComposition; - mHadClientComposition = mHadDeviceComposition = mReusedClientComposition = false; - TimeStats::ClientCompositionRecord clientCompositionRecord; - for (const auto& [_, display] : displays) { - const auto& state = display->getCompositionDisplay()->getState(); - mHadClientComposition |= state.usesClientComposition && !state.reusedClientComposition; - mHadDeviceComposition |= state.usesDeviceComposition; - mReusedClientComposition |= state.reusedClientComposition; - clientCompositionRecord.predicted |= - (state.strategyPrediction != CompositionStrategyPredictionState::DISABLED); - clientCompositionRecord.predictionSucceeded |= - (state.strategyPrediction == CompositionStrategyPredictionState::SUCCESS); + mHadClientComposition = std::any_of(displays.cbegin(), displays.cend(), [](const auto& pair) { + const auto& state = pair.second->getCompositionDisplay()->getState(); + return state.usesClientComposition && !state.reusedClientComposition; + }); + mHadDeviceComposition = std::any_of(displays.cbegin(), displays.cend(), [](const auto& pair) { + const auto& state = pair.second->getCompositionDisplay()->getState(); + return state.usesDeviceComposition; + }); + mReusedClientComposition = + std::any_of(displays.cbegin(), displays.cend(), [](const auto& pair) { + const auto& state = pair.second->getCompositionDisplay()->getState(); + return state.reusedClientComposition; + }); + // Only report a strategy change if we move in and out of client composition + if (prevFrameHadClientComposition != mHadClientComposition) { + mTimeStats->incrementCompositionStrategyChanges(); } - clientCompositionRecord.hadClientComposition = mHadClientComposition; - clientCompositionRecord.reused = mReusedClientComposition; - clientCompositionRecord.changed = prevFrameHadClientComposition != mHadClientComposition; - mTimeStats->pushCompositionStrategyState(clientCompositionRecord); - // TODO: b/160583065 Enable skip validation when SF caches all client composition layers const bool usedGpuComposition = mHadClientComposition || mReusedClientComposition; modulateVsync(&VsyncModulator::onDisplayRefresh, usedGpuComposition); @@ -2544,6 +2542,13 @@ void SurfaceFlinger::postComposition() { } mTimeStats->incrementTotalFrames(); + if (mHadClientComposition) { + mTimeStats->incrementClientCompositionFrames(); + } + + if (mReusedClientComposition) { + mTimeStats->incrementClientCompositionReusedFrames(); + } mTimeStats->setPresentFenceGlobal(mPreviousPresentFences[0].fenceTime); diff --git a/services/surfaceflinger/TimeStats/TimeStats.cpp b/services/surfaceflinger/TimeStats/TimeStats.cpp index e5a9dd47c3..b1a2bdaa91 100644 --- a/services/surfaceflinger/TimeStats/TimeStats.cpp +++ b/services/surfaceflinger/TimeStats/TimeStats.cpp @@ -321,19 +321,22 @@ void TimeStats::incrementMissedFrames() { mTimeStats.missedFramesLegacy++; } -void TimeStats::pushCompositionStrategyState(const TimeStats::ClientCompositionRecord& record) { - if (!mEnabled.load() || !record.hasInterestingData()) { - return; - } +void TimeStats::incrementClientCompositionFrames() { + if (!mEnabled.load()) return; + + ATRACE_CALL(); + + std::lock_guard lock(mMutex); + mTimeStats.clientCompositionFramesLegacy++; +} + +void TimeStats::incrementClientCompositionReusedFrames() { + if (!mEnabled.load()) return; ATRACE_CALL(); std::lock_guard lock(mMutex); - if (record.changed) mTimeStats.compositionStrategyChangesLegacy++; - if (record.hadClientComposition) mTimeStats.clientCompositionFramesLegacy++; - if (record.reused) mTimeStats.clientCompositionReusedFramesLegacy++; - if (record.predicted) mTimeStats.compositionStrategyPredictedLegacy++; - if (record.predictionSucceeded) mTimeStats.compositionStrategyPredictionSucceededLegacy++; + mTimeStats.clientCompositionReusedFramesLegacy++; } void TimeStats::incrementRefreshRateSwitches() { @@ -345,6 +348,15 @@ void TimeStats::incrementRefreshRateSwitches() { mTimeStats.refreshRateSwitchesLegacy++; } +void TimeStats::incrementCompositionStrategyChanges() { + if (!mEnabled.load()) return; + + ATRACE_CALL(); + + std::lock_guard lock(mMutex); + mTimeStats.compositionStrategyChangesLegacy++; +} + void TimeStats::recordDisplayEventConnectionCount(int32_t count) { if (!mEnabled.load()) return; @@ -1050,10 +1062,8 @@ void TimeStats::clearGlobalLocked() { mTimeStats.missedFramesLegacy = 0; mTimeStats.clientCompositionFramesLegacy = 0; mTimeStats.clientCompositionReusedFramesLegacy = 0; - mTimeStats.compositionStrategyChangesLegacy = 0; - mTimeStats.compositionStrategyPredictedLegacy = 0; - mTimeStats.compositionStrategyPredictionSucceededLegacy = 0; mTimeStats.refreshRateSwitchesLegacy = 0; + mTimeStats.compositionStrategyChangesLegacy = 0; mTimeStats.displayEventConnectionsCountLegacy = 0; mTimeStats.displayOnTimeLegacy = 0; mTimeStats.presentToPresentLegacy.hist.clear(); diff --git a/services/surfaceflinger/TimeStats/TimeStats.h b/services/surfaceflinger/TimeStats/TimeStats.h index 7a159b8eb7..77c7973532 100644 --- a/services/surfaceflinger/TimeStats/TimeStats.h +++ b/services/surfaceflinger/TimeStats/TimeStats.h @@ -45,7 +45,7 @@ public: virtual ~TimeStats() = default; // Process a pull request from statsd. - virtual bool onPullAtom(const int atomId, std::string* pulledData) = 0; + virtual bool onPullAtom(const int atomId, std::string* pulledData); virtual void parseArgs(bool asProto, const Vector& args, std::string& result) = 0; virtual bool isEnabled() = 0; @@ -53,8 +53,14 @@ public: virtual void incrementTotalFrames() = 0; virtual void incrementMissedFrames() = 0; + virtual void incrementClientCompositionFrames() = 0; + virtual void incrementClientCompositionReusedFrames() = 0; // Increments the number of times the display refresh rate changed. virtual void incrementRefreshRateSwitches() = 0; + // Increments the number of changes in composition strategy + // The intention is to reflect the number of changes between hwc and gpu + // composition, where "gpu composition" may also include mixed composition. + virtual void incrementCompositionStrategyChanges() = 0; // Records the most up-to-date count of display event connections. // The stored count will be the maximum ever recoded. virtual void recordDisplayEventConnectionCount(int32_t count) = 0; @@ -152,24 +158,6 @@ public: } }; - struct ClientCompositionRecord { - // Frame had client composition or mixed composition - bool hadClientComposition = false; - // Composition changed between hw composition and mixed/client composition - bool changed = false; - // Frame reused the client composition result from a previous frame - bool reused = false; - // Composition strategy predicted for frame - bool predicted = false; - // Composition strategy prediction succeeded - bool predictionSucceeded = false; - - // Whether there is data we want to record. - bool hasInterestingData() const { - return hadClientComposition || changed || reused || predicted; - } - }; - virtual void incrementJankyFrames(const JankyFramesInfo& info) = 0; // Clean up the layer record virtual void onDestroy(int32_t layerId) = 0; @@ -181,7 +169,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; - virtual void pushCompositionStrategyState(const ClientCompositionRecord&) = 0; }; namespace impl { @@ -249,7 +236,10 @@ public: void incrementTotalFrames() override; void incrementMissedFrames() override; + void incrementClientCompositionFrames() override; + void incrementClientCompositionReusedFrames() override; void incrementRefreshRateSwitches() override; + void incrementCompositionStrategyChanges() override; void recordDisplayEventConnectionCount(int32_t count) override; void recordFrameDuration(nsecs_t startTime, nsecs_t endTime) override; @@ -285,8 +275,6 @@ public: void recordRefreshRate(uint32_t fps, nsecs_t duration) override; void setPresentFenceGlobal(const std::shared_ptr& presentFence) override; - void pushCompositionStrategyState(const ClientCompositionRecord&) override; - static const size_t MAX_NUM_TIME_RECORDS = 64; private: diff --git a/services/surfaceflinger/TimeStats/timestatsproto/TimeStatsHelper.cpp b/services/surfaceflinger/TimeStats/timestatsproto/TimeStatsHelper.cpp index cf1ca65972..69afa2a7a1 100644 --- a/services/surfaceflinger/TimeStats/timestatsproto/TimeStatsHelper.cpp +++ b/services/surfaceflinger/TimeStats/timestatsproto/TimeStatsHelper.cpp @@ -143,14 +143,6 @@ std::string TimeStatsHelper::TimeStatsGlobal::toString(std::optional m clientCompositionReusedFramesLegacy); StringAppendF(&result, "refreshRateSwitches = %d\n", refreshRateSwitchesLegacy); StringAppendF(&result, "compositionStrategyChanges = %d\n", compositionStrategyChangesLegacy); - StringAppendF(&result, "compositionStrategyPredicted = %d\n", - compositionStrategyPredictedLegacy); - StringAppendF(&result, "compositionStrategyPredictionSucceeded = %d\n", - compositionStrategyPredictionSucceededLegacy); - StringAppendF(&result, "compositionStrategyPredictionFailed = %d\n", - compositionStrategyPredictedLegacy - - compositionStrategyPredictionSucceededLegacy); - StringAppendF(&result, "displayOnTime = %" PRId64 " ms\n", displayOnTimeLegacy); StringAppendF(&result, "displayConfigStats is as below:\n"); for (const auto& [fps, duration] : refreshRateStatsLegacy) { diff --git a/services/surfaceflinger/TimeStats/timestatsproto/include/timestatsproto/TimeStatsHelper.h b/services/surfaceflinger/TimeStats/timestatsproto/include/timestatsproto/TimeStatsHelper.h index 237ae8d761..438561cc05 100644 --- a/services/surfaceflinger/TimeStats/timestatsproto/include/timestatsproto/TimeStatsHelper.h +++ b/services/surfaceflinger/TimeStats/timestatsproto/include/timestatsproto/TimeStatsHelper.h @@ -178,8 +178,6 @@ public: Histogram frameDurationLegacy; Histogram renderEngineTimingLegacy; std::unordered_map refreshRateStatsLegacy; - int32_t compositionStrategyPredictedLegacy = 0; - int32_t compositionStrategyPredictionSucceededLegacy = 0; std::unordered_map stats; diff --git a/services/surfaceflinger/tests/unittests/TimeStatsTest.cpp b/services/surfaceflinger/tests/unittests/TimeStatsTest.cpp index 6ffc0396d7..0ef8456739 100644 --- a/services/surfaceflinger/tests/unittests/TimeStatsTest.cpp +++ b/services/surfaceflinger/tests/unittests/TimeStatsTest.cpp @@ -268,11 +268,8 @@ TEST_F(TimeStatsTest, canIncreaseGlobalStats) { for (size_t i = 0; i < MISSED_FRAMES; i++) { ASSERT_NO_FATAL_FAILURE(mTimeStats->incrementMissedFrames()); } - TimeStats::ClientCompositionRecord record; - record.hadClientComposition = true; - for (size_t i = 0; i < CLIENT_COMPOSITION_FRAMES; i++) { - ASSERT_NO_FATAL_FAILURE(mTimeStats->pushCompositionStrategyState(record)); + ASSERT_NO_FATAL_FAILURE(mTimeStats->incrementClientCompositionFrames()); } SFTimeStatsGlobalProto globalProto; @@ -462,49 +459,19 @@ TEST_F(TimeStatsTest, canCaptureSetFrameRateVoteAfterZeroForLayer) { EXPECT_THAT(result, HasSubstr(expectedResult)); } -TEST_F(TimeStatsTest, canIncreaseClientCompositionStats) { +TEST_F(TimeStatsTest, canIncreaseClientCompositionReusedFrames) { // this stat is not in the proto so verify by checking the string dump - constexpr size_t COMPOSITION_STRATEGY_CHANGED_FRAMES = 1; - constexpr size_t HAD_CLIENT_COMPOSITION_FRAMES = 2; - constexpr size_t REUSED_CLIENT_COMPOSITION_FRAMES = 3; - constexpr size_t COMPOSITION_STRATEGY_PREDICTION_SUCCEEDED_FRAMES = 4; - constexpr size_t COMPOSITION_STRATEGY_PREDICTED_FRAMES = 5; + constexpr size_t CLIENT_COMPOSITION_REUSED_FRAMES = 2; EXPECT_TRUE(inputCommand(InputCommand::ENABLE, FMT_STRING).empty()); - for (size_t i = 0; i <= COMPOSITION_STRATEGY_PREDICTED_FRAMES; i++) { - TimeStats::ClientCompositionRecord record; - record.hadClientComposition = i < HAD_CLIENT_COMPOSITION_FRAMES; - record.changed = i < COMPOSITION_STRATEGY_CHANGED_FRAMES; - record.reused = i < REUSED_CLIENT_COMPOSITION_FRAMES; - record.predicted = i < COMPOSITION_STRATEGY_PREDICTED_FRAMES; - record.predictionSucceeded = i < COMPOSITION_STRATEGY_PREDICTION_SUCCEEDED_FRAMES; - mTimeStats->pushCompositionStrategyState(record); + for (size_t i = 0; i < CLIENT_COMPOSITION_REUSED_FRAMES; i++) { + ASSERT_NO_FATAL_FAILURE(mTimeStats->incrementClientCompositionReusedFrames()); } const std::string result(inputCommand(InputCommand::DUMP_ALL, FMT_STRING)); - std::string expected = - "compositionStrategyChanges = " + std::to_string(COMPOSITION_STRATEGY_CHANGED_FRAMES); - EXPECT_THAT(result, HasSubstr(expected)); - - expected = "clientCompositionFrames = " + std::to_string(HAD_CLIENT_COMPOSITION_FRAMES); - EXPECT_THAT(result, HasSubstr(expected)); - - expected = - "clientCompositionReusedFrames = " + std::to_string(REUSED_CLIENT_COMPOSITION_FRAMES); - EXPECT_THAT(result, HasSubstr(expected)); - - expected = "compositionStrategyPredicted = " + - std::to_string(COMPOSITION_STRATEGY_PREDICTED_FRAMES); - EXPECT_THAT(result, HasSubstr(expected)); - - expected = "compositionStrategyPredictionSucceeded = " + - std::to_string(COMPOSITION_STRATEGY_PREDICTION_SUCCEEDED_FRAMES); - EXPECT_THAT(result, HasSubstr(expected)); - - expected = "compositionStrategyPredictionFailed = " + - std::to_string(COMPOSITION_STRATEGY_PREDICTED_FRAMES - - COMPOSITION_STRATEGY_PREDICTION_SUCCEEDED_FRAMES); - EXPECT_THAT(result, HasSubstr(expected)); + const std::string expectedResult = + "clientCompositionReusedFrames = " + std::to_string(CLIENT_COMPOSITION_REUSED_FRAMES); + EXPECT_THAT(result, HasSubstr(expectedResult)); } TEST_F(TimeStatsTest, canIncreaseRefreshRateSwitches) { @@ -522,6 +489,21 @@ TEST_F(TimeStatsTest, canIncreaseRefreshRateSwitches) { EXPECT_THAT(result, HasSubstr(expectedResult)); } +TEST_F(TimeStatsTest, canIncreaseCompositionStrategyChanges) { + // this stat is not in the proto so verify by checking the string dump + constexpr size_t COMPOSITION_STRATEGY_CHANGES = 2; + + EXPECT_TRUE(inputCommand(InputCommand::ENABLE, FMT_STRING).empty()); + for (size_t i = 0; i < COMPOSITION_STRATEGY_CHANGES; i++) { + ASSERT_NO_FATAL_FAILURE(mTimeStats->incrementCompositionStrategyChanges()); + } + + const std::string result(inputCommand(InputCommand::DUMP_ALL, FMT_STRING)); + const std::string expectedResult = + "compositionStrategyChanges = " + std::to_string(COMPOSITION_STRATEGY_CHANGES); + EXPECT_THAT(result, HasSubstr(expectedResult)); +} + TEST_F(TimeStatsTest, canAverageFrameDuration) { EXPECT_TRUE(inputCommand(InputCommand::ENABLE, FMT_STRING).empty()); mTimeStats->setPowerMode(PowerMode::ON); @@ -854,7 +836,7 @@ TEST_F(TimeStatsTest, canClearTimeStats) { ASSERT_NO_FATAL_FAILURE(mTimeStats->incrementTotalFrames()); ASSERT_NO_FATAL_FAILURE(mTimeStats->incrementMissedFrames()); - ASSERT_NO_FATAL_FAILURE(mTimeStats->pushCompositionStrategyState({})); + ASSERT_NO_FATAL_FAILURE(mTimeStats->incrementClientCompositionFrames()); ASSERT_NO_FATAL_FAILURE(mTimeStats->setPowerMode(PowerMode::ON)); mTimeStats->recordFrameDuration(std::chrono::nanoseconds(3ms).count(), @@ -885,8 +867,9 @@ TEST_F(TimeStatsTest, canClearTimeStats) { TEST_F(TimeStatsTest, canClearDumpOnlyTimeStats) { // These stats are not in the proto so verify by checking the string dump. EXPECT_TRUE(inputCommand(InputCommand::ENABLE, FMT_STRING).empty()); - ASSERT_NO_FATAL_FAILURE(mTimeStats->pushCompositionStrategyState({})); + ASSERT_NO_FATAL_FAILURE(mTimeStats->incrementClientCompositionReusedFrames()); ASSERT_NO_FATAL_FAILURE(mTimeStats->incrementRefreshRateSwitches()); + ASSERT_NO_FATAL_FAILURE(mTimeStats->incrementCompositionStrategyChanges()); mTimeStats->setPowerMode(PowerMode::ON); mTimeStats->recordFrameDuration(std::chrono::nanoseconds(1ms).count(), std::chrono::nanoseconds(5ms).count()); @@ -1049,10 +1032,8 @@ TEST_F(TimeStatsTest, globalStatsCallback) { for (size_t i = 0; i < MISSED_FRAMES; i++) { mTimeStats->incrementMissedFrames(); } - TimeStats::ClientCompositionRecord record; - record.hadClientComposition = true; for (size_t i = 0; i < CLIENT_COMPOSITION_FRAMES; i++) { - mTimeStats->pushCompositionStrategyState(record); + mTimeStats->incrementClientCompositionFrames(); } insertTimeRecord(NORMAL_SEQUENCE, LAYER_ID_0, 1, 1000000); diff --git a/services/surfaceflinger/tests/unittests/mock/MockTimeStats.h b/services/surfaceflinger/tests/unittests/mock/MockTimeStats.h index 0dee800558..0a69b562ab 100644 --- a/services/surfaceflinger/tests/unittests/mock/MockTimeStats.h +++ b/services/surfaceflinger/tests/unittests/mock/MockTimeStats.h @@ -33,7 +33,10 @@ public: MOCK_METHOD0(miniDump, std::string()); MOCK_METHOD0(incrementTotalFrames, void()); MOCK_METHOD0(incrementMissedFrames, void()); + MOCK_METHOD0(incrementClientCompositionFrames, void()); + MOCK_METHOD0(incrementClientCompositionReusedFrames, void()); MOCK_METHOD0(incrementRefreshRateSwitches, void()); + MOCK_METHOD0(incrementCompositionStrategyChanges, void()); MOCK_METHOD1(recordDisplayEventConnectionCount, void(int32_t)); MOCK_METHOD2(recordFrameDuration, void(nsecs_t, nsecs_t)); MOCK_METHOD2(recordRenderEngineDuration, void(nsecs_t, nsecs_t)); @@ -60,8 +63,6 @@ public: void(hardware::graphics::composer::V2_4::IComposerClient::PowerMode)); MOCK_METHOD2(recordRefreshRate, void(uint32_t, nsecs_t)); MOCK_METHOD1(setPresentFenceGlobal, void(const std::shared_ptr&)); - MOCK_METHOD(void, pushCompositionStrategyState, - (const android::TimeStats::ClientCompositionRecord&), (override)); }; } // namespace android::mock -- cgit v1.2.3-59-g8ed1b From cab268d95d99577aed0ef9dddc34aceafbf213c7 Mon Sep 17 00:00:00 2001 From: Robert Carr Date: Wed, 9 Mar 2022 13:49:41 -0800 Subject: Revert "SF: Predict HWC composition strategy" This reverts commit 7234fa59245e20b934a15ebbd27d4e189ad224d0. Change-Id: I908f9c279bb91ce2ee654a05eb8ac8d0057caa47 Bug: 223543469 (cherry picked from commit 294ef6138196e0e8ccc2d41dfbf7595937891449) Merged-In: I908f9c279bb91ce2ee654a05eb8ac8d0057caa47 --- .../surfaceflinger/CompositionEngine/Android.bp | 5 - .../include/compositionengine/DisplaySurface.h | 3 - .../include/compositionengine/Output.h | 21 +- .../include/compositionengine/RenderSurface.h | 3 - .../include/compositionengine/impl/Display.h | 9 +- .../compositionengine/impl/GpuCompositionResult.h | 38 --- .../compositionengine/impl/HwcAsyncWorker.h | 57 ---- .../include/compositionengine/impl/Output.h | 27 +- .../impl/OutputCompositionState.h | 4 - .../include/compositionengine/impl/RenderSurface.h | 1 - .../include/compositionengine/mock/Display.h | 1 - .../include/compositionengine/mock/Output.h | 17 +- .../include/compositionengine/mock/RenderSurface.h | 1 - .../CompositionEngine/src/Display.cpp | 24 +- .../CompositionEngine/src/DisplaySurface.cpp | 4 - .../CompositionEngine/src/HwcAsyncWorker.cpp | 73 ----- .../CompositionEngine/src/Output.cpp | 207 ++------------ .../CompositionEngine/src/RenderSurface.cpp | 4 - .../CompositionEngine/tests/DisplayTest.cpp | 76 ++--- .../CompositionEngine/tests/OutputTest.cpp | 308 ++------------------- services/surfaceflinger/DisplayDevice.cpp | 1 - .../surfaceflinger/DisplayHardware/HWComposer.h | 8 - .../DisplayHardware/VirtualDisplaySurface.h | 3 - services/surfaceflinger/SurfaceFlinger.cpp | 3 - services/surfaceflinger/SurfaceFlinger.h | 5 - 25 files changed, 106 insertions(+), 797 deletions(-) delete mode 100644 services/surfaceflinger/CompositionEngine/include/compositionengine/impl/GpuCompositionResult.h delete mode 100644 services/surfaceflinger/CompositionEngine/include/compositionengine/impl/HwcAsyncWorker.h delete mode 100644 services/surfaceflinger/CompositionEngine/src/HwcAsyncWorker.cpp diff --git a/services/surfaceflinger/CompositionEngine/Android.bp b/services/surfaceflinger/CompositionEngine/Android.bp index 9302b7bc37..aefc014062 100644 --- a/services/surfaceflinger/CompositionEngine/Android.bp +++ b/services/surfaceflinger/CompositionEngine/Android.bp @@ -41,10 +41,6 @@ cc_defaults { "libtonemap", "libtrace_proto", "libaidlcommonsupport", - "libprocessgroup", - "libcgrouprc", - "libjsoncpp", - "libcgrouprc_format", ], header_libs: [ "android.hardware.graphics.composer@2.1-command-buffer", @@ -72,7 +68,6 @@ cc_library { "src/DisplayColorProfile.cpp", "src/DisplaySurface.cpp", "src/DumpHelpers.cpp", - "src/HwcAsyncWorker.cpp", "src/HwcBufferCache.cpp", "src/LayerFECompositionState.cpp", "src/Output.cpp", diff --git a/services/surfaceflinger/CompositionEngine/include/compositionengine/DisplaySurface.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/DisplaySurface.h index ca86f4c604..c553fce85d 100644 --- a/services/surfaceflinger/CompositionEngine/include/compositionengine/DisplaySurface.h +++ b/services/surfaceflinger/CompositionEngine/include/compositionengine/DisplaySurface.h @@ -72,9 +72,6 @@ public: virtual void resizeBuffers(const ui::Size&) = 0; virtual const sp& getClientTargetAcquireFence() const = 0; - - // Returns true if the render surface supports client composition prediction. - virtual bool supportsCompositionStrategyPrediction() const; }; } // namespace compositionengine diff --git a/services/surfaceflinger/CompositionEngine/include/compositionengine/Output.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/Output.h index 15551029b3..d8644a428d 100644 --- a/services/surfaceflinger/CompositionEngine/include/compositionengine/Output.h +++ b/services/surfaceflinger/CompositionEngine/include/compositionengine/Output.h @@ -35,7 +35,6 @@ #include #include -#include "DisplayHardware/HWComposer.h" namespace android { @@ -55,7 +54,6 @@ struct LayerFECompositionState; namespace impl { struct OutputCompositionState; -struct GpuCompositionResult; } // namespace impl /** @@ -264,9 +262,6 @@ public: // Latches the front-end layer state for each output layer virtual void updateLayerStateFromFE(const CompositionRefreshArgs&) const = 0; - // Enables predicting composition strategy to run client composition earlier - virtual void setPredictCompositionStrategy(bool) = 0; - protected: virtual void setDisplayColorProfile(std::unique_ptr) = 0; virtual void setRenderSurface(std::unique_ptr) = 0; @@ -283,22 +278,13 @@ protected: virtual void updateColorProfile(const CompositionRefreshArgs&) = 0; virtual void beginFrame() = 0; virtual void prepareFrame() = 0; - - using GpuCompositionResult = compositionengine::impl::GpuCompositionResult; - // Runs prepare frame in another thread while running client composition using - // the previous frame's composition strategy. - virtual GpuCompositionResult prepareFrameAsync(const CompositionRefreshArgs&) = 0; virtual void devOptRepaintFlash(const CompositionRefreshArgs&) = 0; - virtual void finishFrame(const CompositionRefreshArgs&, GpuCompositionResult&&) = 0; + virtual void finishFrame(const CompositionRefreshArgs&) = 0; virtual std::optional composeSurfaces( - const Region&, const compositionengine::CompositionRefreshArgs&, - std::shared_ptr, base::unique_fd&) = 0; + const Region&, const compositionengine::CompositionRefreshArgs& refreshArgs) = 0; virtual void postFramebuffer() = 0; virtual void renderCachedSets(const CompositionRefreshArgs&) = 0; - virtual std::optional - chooseCompositionStrategy() = 0; - virtual void applyCompositionStrategy( - const std::optional& changes) = 0; + virtual void chooseCompositionStrategy() = 0; virtual bool getSkipColorTransform() const = 0; virtual FrameFences presentAndGetFrameFences() = 0; virtual std::vector generateClientCompositionRequests( @@ -309,7 +295,6 @@ protected: std::vector& clientCompositionLayers) = 0; virtual void setExpensiveRenderingExpected(bool enabled) = 0; virtual void cacheClientCompositionRequests(uint32_t cacheSize) = 0; - virtual bool canPredictCompositionStrategy(const CompositionRefreshArgs&) = 0; }; } // namespace compositionengine diff --git a/services/surfaceflinger/CompositionEngine/include/compositionengine/RenderSurface.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/RenderSurface.h index 9ee779cca1..daee83bd2c 100644 --- a/services/surfaceflinger/CompositionEngine/include/compositionengine/RenderSurface.h +++ b/services/surfaceflinger/CompositionEngine/include/compositionengine/RenderSurface.h @@ -100,9 +100,6 @@ public: // Debugging - gets the page flip count for the RenderSurface virtual std::uint32_t getPageFlipCount() const = 0; - - // Returns true if the render surface supports client composition prediction. - virtual bool supportsCompositionStrategyPrediction() const = 0; }; } // namespace compositionengine diff --git a/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/Display.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/Display.h index 3b8b06fc2f..58d2530877 100644 --- a/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/Display.h +++ b/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/Display.h @@ -22,7 +22,6 @@ #include #include #include -#include #include #include #include @@ -52,14 +51,11 @@ public: void setReleasedLayers(const CompositionRefreshArgs&) override; void setColorTransform(const CompositionRefreshArgs&) override; void setColorProfile(const ColorProfile&) override; - - using DeviceRequestedChanges = android::HWComposer::DeviceRequestedChanges; - std::optional chooseCompositionStrategy() override; - void applyCompositionStrategy(const std::optional&) override; + void chooseCompositionStrategy() override; bool getSkipColorTransform() const override; compositionengine::Output::FrameFences presentAndGetFrameFences() override; void setExpensiveRenderingExpected(bool) override; - void finishFrame(const CompositionRefreshArgs&, GpuCompositionResult&&) override; + void finishFrame(const CompositionRefreshArgs&) override; // compositionengine::Display overrides DisplayId getId() const override; @@ -77,6 +73,7 @@ public: using DisplayRequests = android::HWComposer::DeviceRequestedChanges::DisplayRequests; using LayerRequests = android::HWComposer::DeviceRequestedChanges::LayerRequests; using ClientTargetProperty = android::HWComposer::DeviceRequestedChanges::ClientTargetProperty; + virtual bool anyLayersRequireClientComposition() const; virtual bool allLayersRequireClientComposition() const; virtual void applyChangedTypesToLayers(const ChangedTypes&); virtual void applyDisplayRequests(const DisplayRequests&); diff --git a/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/GpuCompositionResult.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/GpuCompositionResult.h deleted file mode 100644 index ed1ddc172c..0000000000 --- a/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/GpuCompositionResult.h +++ /dev/null @@ -1,38 +0,0 @@ -/* - * Copyright 2022 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 - -namespace android::compositionengine::impl { - -struct GpuCompositionResult { - // True if composition strategy was predicted successfully. - bool succeeded = false; - - // Composition ready fence. - base::unique_fd fence{}; - - // Buffer to be used for gpu composition. If gpu composition was not successful, - // then we want to reuse the buffer instead of dequeuing another buffer. - std::shared_ptr buffer = nullptr; - - bool bufferAvailable() const { return buffer != nullptr; }; -}; - -} // namespace android::compositionengine::impl diff --git a/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/HwcAsyncWorker.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/HwcAsyncWorker.h deleted file mode 100644 index 11c0054089..0000000000 --- a/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/HwcAsyncWorker.h +++ /dev/null @@ -1,57 +0,0 @@ -/* - * Copyright 2022 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 "DisplayHardware/HWComposer.h" - -namespace android::compositionengine::impl { - -// HWC Validate call may take multiple milliseconds to complete and can account for -// a signification amount of time in the display hotpath. This helper class allows -// us to run the hwc validate function on a real time thread if we can predict what -// the composition strategy will be and if composition includes client composition. -// While the hwc validate runs, client composition is kicked off with the prediction. -// When the worker returns with a value, the composition continues if the prediction -// was successful otherwise the client composition is re-executed. -// -// Note: This does not alter the sequence between HWC and surfaceflinger. -class HwcAsyncWorker final { -public: - HwcAsyncWorker(); - ~HwcAsyncWorker(); - // Runs the provided function which calls hwc validate and returns the requested - // device changes as a future. - std::future> send( - std::function()>); - -private: - std::mutex mMutex; - std::condition_variable mCv GUARDED_BY(mMutex); - bool mDone GUARDED_BY(mMutex) = false; - bool mTaskRequested GUARDED_BY(mMutex) = false; - std::packaged_task()> mTask - GUARDED_BY(mMutex); - std::thread mThread; - void run(); -}; - -} // namespace android::compositionengine::impl diff --git a/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/Output.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/Output.h index 0be5d018f6..a7a8e97be5 100644 --- a/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/Output.h +++ b/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/Output.h @@ -17,13 +17,9 @@ #pragma once #include -#include #include #include -#include -#include #include -#include #include #include #include @@ -96,38 +92,25 @@ public: void updateColorProfile(const compositionengine::CompositionRefreshArgs&) override; void beginFrame() override; void prepareFrame() override; - GpuCompositionResult prepareFrameAsync(const CompositionRefreshArgs&) override; void devOptRepaintFlash(const CompositionRefreshArgs&) override; - void finishFrame(const CompositionRefreshArgs&, GpuCompositionResult&&) override; - std::optional composeSurfaces(const Region&, - const compositionengine::CompositionRefreshArgs&, - std::shared_ptr, - base::unique_fd&) override; + void finishFrame(const CompositionRefreshArgs&) override; + std::optional composeSurfaces( + const Region&, const compositionengine::CompositionRefreshArgs& refreshArgs) override; void postFramebuffer() override; void renderCachedSets(const CompositionRefreshArgs&) override; void cacheClientCompositionRequests(uint32_t) override; - bool canPredictCompositionStrategy(const CompositionRefreshArgs&) override; - void setPredictCompositionStrategy(bool) override; // Testing const ReleasedLayers& getReleasedLayersForTest() const; void setDisplayColorProfileForTest(std::unique_ptr); void setRenderSurfaceForTest(std::unique_ptr); bool plannerEnabled() const { return mPlanner != nullptr; } - virtual bool anyLayersRequireClientComposition() const; - virtual void updateProtectedContentState(); - virtual bool dequeueRenderBuffer(base::unique_fd*, - std::shared_ptr*); - virtual std::future> - chooseCompositionStrategyAsync(); protected: std::unique_ptr createOutputLayer(const sp&) const; std::optional findCurrentOutputLayerForLayer( const sp&) const; - using DeviceRequestedChanges = android::HWComposer::DeviceRequestedChanges; - std::optional chooseCompositionStrategy() override; - void applyCompositionStrategy(const std::optional&) override{}; + void chooseCompositionStrategy() override; bool getSkipColorTransform() const override; compositionengine::Output::FrameFences presentAndGetFrameFences() override; std::vector generateClientCompositionRequests( @@ -148,7 +131,6 @@ protected: private: void dirtyEntireOutput(); compositionengine::OutputLayer* findLayerRequestingBackgroundComposition() const; - void finishPrepareFrame(); ui::Dataspace getBestDataspace(ui::Dataspace*, bool*) const; compositionengine::Output::ColorProfile pickColorProfile( const compositionengine::CompositionRefreshArgs&) const; @@ -162,7 +144,6 @@ private: OutputLayer* mLayerRequestingBackgroundBlur = nullptr; std::unique_ptr mClientCompositionRequestCache; std::unique_ptr mPlanner; - std::unique_ptr mHwComposerAsyncWorker; }; // This template factory function standardizes the implementation details of the diff --git a/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/OutputCompositionState.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/OutputCompositionState.h index 92f22b6a16..66dd825e5b 100644 --- a/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/OutputCompositionState.h +++ b/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/OutputCompositionState.h @@ -37,8 +37,6 @@ #include #include -#include "DisplayHardware/HWComposer.h" - namespace android { namespace compositionengine::impl { @@ -116,8 +114,6 @@ struct OutputCompositionState { // Current target dataspace ui::Dataspace targetDataspace{ui::Dataspace::UNKNOWN}; - std::optional previousDeviceRequestedChanges{}; - // The earliest time to send the present command to the HAL std::chrono::steady_clock::time_point earliestPresentTime; diff --git a/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/RenderSurface.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/RenderSurface.h index e4cb113645..a8a538003e 100644 --- a/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/RenderSurface.h +++ b/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/RenderSurface.h @@ -63,7 +63,6 @@ public: void queueBuffer(base::unique_fd readyFence) override; void onPresentDisplayCompleted() override; void flip() override; - bool supportsCompositionStrategyPrediction() const override; // Debugging void dump(std::string& result) const override; diff --git a/services/surfaceflinger/CompositionEngine/include/compositionengine/mock/Display.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/mock/Display.h index 72e6f3bdbb..d90cc909ba 100644 --- a/services/surfaceflinger/CompositionEngine/include/compositionengine/mock/Display.h +++ b/services/surfaceflinger/CompositionEngine/include/compositionengine/mock/Display.h @@ -41,7 +41,6 @@ public: MOCK_METHOD1(createDisplayColorProfile, void(const DisplayColorProfileCreationArgs&)); MOCK_METHOD1(createRenderSurface, void(const RenderSurfaceCreationArgs&)); MOCK_METHOD1(createClientCompositionCache, void(uint32_t)); - MOCK_METHOD1(setPredictCompositionStrategy, void(bool)); }; } // namespace android::compositionengine::mock diff --git a/services/surfaceflinger/CompositionEngine/include/compositionengine/mock/Output.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/mock/Output.h index 27303a82be..b68b95d07b 100644 --- a/services/surfaceflinger/CompositionEngine/include/compositionengine/mock/Output.h +++ b/services/surfaceflinger/CompositionEngine/include/compositionengine/mock/Output.h @@ -22,7 +22,6 @@ #include #include #include -#include #include #include @@ -100,22 +99,16 @@ public: MOCK_METHOD0(beginFrame, void()); MOCK_METHOD0(prepareFrame, void()); - MOCK_METHOD1(prepareFrameAsync, GpuCompositionResult(const CompositionRefreshArgs&)); - MOCK_METHOD0(chooseCompositionStrategy, - std::optional()); - MOCK_METHOD1(applyCompositionStrategy, - void(const std::optional&)); + MOCK_METHOD0(chooseCompositionStrategy, void()); MOCK_METHOD1(devOptRepaintFlash, void(const compositionengine::CompositionRefreshArgs&)); - MOCK_METHOD2(finishFrame, - void(const compositionengine::CompositionRefreshArgs&, GpuCompositionResult&&)); + MOCK_METHOD1(finishFrame, void(const compositionengine::CompositionRefreshArgs&)); - MOCK_METHOD4(composeSurfaces, + MOCK_METHOD2(composeSurfaces, std::optional( const Region&, - const compositionengine::CompositionRefreshArgs& refreshArgs, - std::shared_ptr, base::unique_fd&)); + const compositionengine::CompositionRefreshArgs& refreshArgs)); MOCK_CONST_METHOD0(getSkipColorTransform, bool()); MOCK_METHOD0(postFramebuffer, void()); @@ -128,8 +121,6 @@ public: void(const Region&, std::vector&)); MOCK_METHOD1(setExpensiveRenderingExpected, void(bool)); MOCK_METHOD1(cacheClientCompositionRequests, void(uint32_t)); - MOCK_METHOD1(canPredictCompositionStrategy, bool(const CompositionRefreshArgs&)); - MOCK_METHOD1(setPredictCompositionStrategy, void(bool)); }; } // namespace android::compositionengine::mock diff --git a/services/surfaceflinger/CompositionEngine/include/compositionengine/mock/RenderSurface.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/mock/RenderSurface.h index e12aebb50c..fe858c2817 100644 --- a/services/surfaceflinger/CompositionEngine/include/compositionengine/mock/RenderSurface.h +++ b/services/surfaceflinger/CompositionEngine/include/compositionengine/mock/RenderSurface.h @@ -45,7 +45,6 @@ public: MOCK_METHOD0(flip, void()); MOCK_CONST_METHOD1(dump, void(std::string& result)); MOCK_CONST_METHOD0(getPageFlipCount, std::uint32_t()); - MOCK_CONST_METHOD0(supportsCompositionStrategyPrediction, bool()); }; } // namespace android::compositionengine::mock diff --git a/services/surfaceflinger/CompositionEngine/src/Display.cpp b/services/surfaceflinger/CompositionEngine/src/Display.cpp index 09648c356d..6a75283f7b 100644 --- a/services/surfaceflinger/CompositionEngine/src/Display.cpp +++ b/services/surfaceflinger/CompositionEngine/src/Display.cpp @@ -221,12 +221,12 @@ void Display::setReleasedLayers(const compositionengine::CompositionRefreshArgs& setReleasedLayers(std::move(releasedLayers)); } -std::optional Display::chooseCompositionStrategy() { +void Display::chooseCompositionStrategy() { ATRACE_CALL(); ALOGV(__FUNCTION__); if (mIsDisconnected) { - return {}; + return; } // Default to the base settings -- client composition only. @@ -235,7 +235,7 @@ std::optional Display::chooseCompos // If we don't have a HWC display, then we are done. const auto halDisplayId = HalDisplayId::tryCast(mId); if (!halDisplayId) { - return {}; + return; } // Get any composition changes requested by the HWC device, and apply them. @@ -260,13 +260,8 @@ std::optional Display::chooseCompos result != NO_ERROR) { ALOGE("chooseCompositionStrategy failed for %s: %d (%s)", getName().c_str(), result, strerror(-result)); - return {}; + return; } - - return changes; -} - -void Display::applyCompositionStrategy(const std::optional& changes) { if (changes) { applyChangedTypesToLayers(changes->changedTypes); applyDisplayRequests(changes->displayRequests); @@ -292,6 +287,12 @@ bool Display::getSkipColorTransform() const { return hwc.hasCapability(Capability::SKIP_CLIENT_COLOR_TRANSFORM); } +bool Display::anyLayersRequireClientComposition() const { + const auto layers = getOutputLayersOrderedByZ(); + return std::any_of(layers.begin(), layers.end(), + [](const auto& layer) { return layer->requiresClientComposition(); }); +} + bool Display::allLayersRequireClientComposition() const { const auto layers = getOutputLayersOrderedByZ(); return std::all_of(layers.begin(), layers.end(), @@ -389,8 +390,7 @@ void Display::setExpensiveRenderingExpected(bool enabled) { } } -void Display::finishFrame(const compositionengine::CompositionRefreshArgs& refreshArgs, - GpuCompositionResult&& result) { +void Display::finishFrame(const compositionengine::CompositionRefreshArgs& refreshArgs) { // We only need to actually compose the display if: // 1) It is being handled by hardware composer, which may need this to // keep its virtual display state machine in sync, or @@ -400,7 +400,7 @@ void Display::finishFrame(const compositionengine::CompositionRefreshArgs& refre return; } - impl::Output::finishFrame(refreshArgs, std::move(result)); + impl::Output::finishFrame(refreshArgs); } } // namespace android::compositionengine::impl diff --git a/services/surfaceflinger/CompositionEngine/src/DisplaySurface.cpp b/services/surfaceflinger/CompositionEngine/src/DisplaySurface.cpp index 28900af162..db6d4f2fed 100644 --- a/services/surfaceflinger/CompositionEngine/src/DisplaySurface.cpp +++ b/services/surfaceflinger/CompositionEngine/src/DisplaySurface.cpp @@ -20,8 +20,4 @@ namespace android::compositionengine { DisplaySurface::~DisplaySurface() = default; -bool DisplaySurface::supportsCompositionStrategyPrediction() const { - return true; -} - } // namespace android::compositionengine diff --git a/services/surfaceflinger/CompositionEngine/src/HwcAsyncWorker.cpp b/services/surfaceflinger/CompositionEngine/src/HwcAsyncWorker.cpp deleted file mode 100644 index 497424a327..0000000000 --- a/services/surfaceflinger/CompositionEngine/src/HwcAsyncWorker.cpp +++ /dev/null @@ -1,73 +0,0 @@ -/* - * Copyright 2022 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 -#include -#include -#include -#include - -#include -#include - -namespace android::compositionengine::impl { - -HwcAsyncWorker::HwcAsyncWorker() { - mThread = std::thread(&HwcAsyncWorker::run, this); - pthread_setname_np(mThread.native_handle(), "HwcAsyncWorker"); -} - -HwcAsyncWorker::~HwcAsyncWorker() { - { - std::scoped_lock lock(mMutex); - mDone = true; - mCv.notify_all(); - } - if (mThread.joinable()) { - mThread.join(); - } -} -std::future> HwcAsyncWorker::send( - std::function()> task) { - std::unique_lock lock(mMutex); - android::base::ScopedLockAssertion assumeLock(mMutex); - mTask = std::packaged_task()>( - [task = std::move(task)]() { return task(); }); - mTaskRequested = true; - mCv.notify_one(); - return mTask.get_future(); -} - -void HwcAsyncWorker::run() { - set_sched_policy(0, SP_FOREGROUND); - struct sched_param param = {0}; - param.sched_priority = 2; - sched_setscheduler(gettid(), SCHED_FIFO, ¶m); - - std::unique_lock lock(mMutex); - android::base::ScopedLockAssertion assumeLock(mMutex); - while (!mDone) { - mCv.wait(lock); - if (mTaskRequested && mTask.valid()) { - mTask(); - mTaskRequested = false; - } - } -} - -} // namespace android::compositionengine::impl diff --git a/services/surfaceflinger/CompositionEngine/src/Output.cpp b/services/surfaceflinger/CompositionEngine/src/Output.cpp index 8d560d732c..ff332ebe2c 100644 --- a/services/surfaceflinger/CompositionEngine/src/Output.cpp +++ b/services/surfaceflinger/CompositionEngine/src/Output.cpp @@ -22,7 +22,6 @@ #include #include #include -#include #include #include #include @@ -435,17 +434,9 @@ void Output::present(const compositionengine::CompositionRefreshArgs& refreshArg writeCompositionState(refreshArgs); setColorTransform(refreshArgs); beginFrame(); - - GpuCompositionResult result; - const bool predictCompositionStrategy = canPredictCompositionStrategy(refreshArgs); - if (predictCompositionStrategy) { - result = prepareFrameAsync(refreshArgs); - } else { - prepareFrame(); - } - + prepareFrame(); devOptRepaintFlash(refreshArgs); - finishFrame(refreshArgs, std::move(result)); + finishFrame(refreshArgs); postFramebuffer(); renderCachedSets(refreshArgs); } @@ -960,62 +951,19 @@ void Output::prepareFrame() { ATRACE_CALL(); ALOGV(__FUNCTION__); - auto& outputState = editState(); + const auto& outputState = getState(); if (!outputState.isEnabled) { return; } - auto changes = chooseCompositionStrategy(); - outputState.previousDeviceRequestedChanges = changes; - if (changes) { - applyCompositionStrategy(changes); - } - finishPrepareFrame(); -} + chooseCompositionStrategy(); -std::future> -Output::chooseCompositionStrategyAsync() { - return mHwComposerAsyncWorker->send([&]() { return chooseCompositionStrategy(); }); -} - -GpuCompositionResult Output::prepareFrameAsync(const CompositionRefreshArgs& refreshArgs) { - ATRACE_CALL(); - ALOGV(__FUNCTION__); - auto& state = editState(); - const auto& previousChanges = state.previousDeviceRequestedChanges; - auto hwcResult = chooseCompositionStrategyAsync(); - applyCompositionStrategy(previousChanges); - finishPrepareFrame(); - - base::unique_fd bufferFence; - std::shared_ptr buffer; - updateProtectedContentState(); - const bool dequeueSucceeded = dequeueRenderBuffer(&bufferFence, &buffer); - GpuCompositionResult compositionResult; - if (dequeueSucceeded) { - std::optional optFd = - composeSurfaces(Region::INVALID_REGION, refreshArgs, buffer, bufferFence); - if (optFd) { - compositionResult.fence = std::move(*optFd); - } + if (mPlanner) { + mPlanner->reportFinalPlan(getOutputLayersOrderedByZ()); } - auto changes = hwcResult.valid() ? hwcResult.get() : std::nullopt; - const bool predictionSucceeded = dequeueSucceeded && changes == previousChanges; - compositionResult.succeeded = predictionSucceeded; - if (!predictionSucceeded) { - ATRACE_NAME("CompositionStrategyPredictionMiss"); - if (changes) { - applyCompositionStrategy(changes); - } - finishPrepareFrame(); - // Track the dequeued buffer to reuse so we don't need to dequeue another one. - compositionResult.buffer = buffer; - } else { - ATRACE_NAME("CompositionStrategyPredictionHit"); - } - state.previousDeviceRequestedChanges = std::move(changes); - return compositionResult; + mRenderSurface->prepareFrame(outputState.usesClientComposition, + outputState.usesDeviceComposition); } void Output::devOptRepaintFlash(const compositionengine::CompositionRefreshArgs& refreshArgs) { @@ -1025,11 +973,7 @@ void Output::devOptRepaintFlash(const compositionengine::CompositionRefreshArgs& if (getState().isEnabled) { if (const auto dirtyRegion = getDirtyRegion(); !dirtyRegion.isEmpty()) { - base::unique_fd bufferFence; - std::shared_ptr buffer; - updateProtectedContentState(); - dequeueRenderBuffer(&bufferFence, &buffer); - static_cast(composeSurfaces(dirtyRegion, refreshArgs, buffer, bufferFence)); + static_cast(composeSurfaces(dirtyRegion, refreshArgs)); mRenderSurface->queueBuffer(base::unique_fd()); } } @@ -1041,7 +985,7 @@ void Output::devOptRepaintFlash(const compositionengine::CompositionRefreshArgs& prepareFrame(); } -void Output::finishFrame(const CompositionRefreshArgs& refreshArgs, GpuCompositionResult&& result) { +void Output::finishFrame(const compositionengine::CompositionRefreshArgs& refreshArgs) { ATRACE_CALL(); ALOGV(__FUNCTION__); @@ -1049,25 +993,9 @@ void Output::finishFrame(const CompositionRefreshArgs& refreshArgs, GpuCompositi return; } - std::optional optReadyFence; - std::shared_ptr buffer; - base::unique_fd bufferFence; - if (result.succeeded) { - optReadyFence = std::move(result.fence); - } else { - if (result.bufferAvailable()) { - buffer = std::move(result.buffer); - bufferFence = std::move(result.fence); - } else { - updateProtectedContentState(); - if (!dequeueRenderBuffer(&bufferFence, &buffer)) { - return; - } - } - // Repaint the framebuffer (if needed), getting the optional fence for when - // the composition completes. - optReadyFence = composeSurfaces(Region::INVALID_REGION, refreshArgs, buffer, bufferFence); - } + // Repaint the framebuffer (if needed), getting the optional fence for when + // the composition completes. + auto optReadyFence = composeSurfaces(Region::INVALID_REGION, refreshArgs); if (!optReadyFence) { return; } @@ -1076,8 +1004,16 @@ void Output::finishFrame(const CompositionRefreshArgs& refreshArgs, GpuCompositi mRenderSurface->queueBuffer(std::move(*optReadyFence)); } -void Output::updateProtectedContentState() { +std::optional Output::composeSurfaces( + const Region& debugRegion, const compositionengine::CompositionRefreshArgs& refreshArgs) { + ATRACE_CALL(); + ALOGV(__FUNCTION__); + const auto& outputState = getState(); + OutputCompositionState& outputCompositionState = editState(); + const TracedOrdinal hasClientComposition = {"hasClientComposition", + outputState.usesClientComposition}; + auto& renderEngine = getCompositionEngine().getRenderEngine(); const bool supportsProtectedContent = renderEngine.supportsProtectedContent(); @@ -1099,48 +1035,29 @@ void Output::updateProtectedContentState() { } else if (!outputState.isSecure && renderEngine.isProtected()) { renderEngine.useProtectedContext(false); } -} -bool Output::dequeueRenderBuffer(base::unique_fd* bufferFence, - std::shared_ptr* tex) { - const auto& outputState = getState(); + base::unique_fd fd; + + std::shared_ptr tex; // If we aren't doing client composition on this output, but do have a // flipClientTarget request for this frame on this output, we still need to // dequeue a buffer. - if (outputState.usesClientComposition || outputState.flipClientTarget) { - *tex = mRenderSurface->dequeueBuffer(bufferFence); - if (*tex == nullptr) { + if (hasClientComposition || outputState.flipClientTarget) { + tex = mRenderSurface->dequeueBuffer(&fd); + if (tex == nullptr) { ALOGW("Dequeuing buffer for display [%s] failed, bailing out of " "client composition for this frame", mName.c_str()); - return false; + return {}; } } - return true; -} -std::optional Output::composeSurfaces( - const Region& debugRegion, const compositionengine::CompositionRefreshArgs& refreshArgs, - std::shared_ptr tex, base::unique_fd& fd) { - ATRACE_CALL(); - ALOGV(__FUNCTION__); - - const auto& outputState = getState(); - const TracedOrdinal hasClientComposition = {"hasClientComposition", - outputState.usesClientComposition}; if (!hasClientComposition) { setExpensiveRenderingExpected(false); return base::unique_fd(); } - if (tex == nullptr) { - ALOGW("Buffer not valid for display [%s], bailing out of " - "client composition for this frame", - mName.c_str()); - return {}; - } - ALOGV("hasClientComposition"); renderengine::DisplaySettings clientCompositionDisplay; @@ -1168,8 +1085,6 @@ std::optional Output::composeSurfaces( outputState.usesDeviceComposition || getSkipColorTransform(); // Generate the client composition requests for the layers on this output. - auto& renderEngine = getCompositionEngine().getRenderEngine(); - const bool supportsProtectedContent = renderEngine.supportsProtectedContent(); std::vector clientCompositionLayersFE; std::vector clientCompositionLayers = generateClientCompositionRequests(supportsProtectedContent, @@ -1177,19 +1092,16 @@ std::optional Output::composeSurfaces( clientCompositionLayersFE); appendRegionFlashRequests(debugRegion, clientCompositionLayers); - OutputCompositionState& outputCompositionState = editState(); // Check if the client composition requests were rendered into the provided graphic buffer. If // so, we can reuse the buffer and avoid client composition. if (mClientCompositionRequestCache) { if (mClientCompositionRequestCache->exists(tex->getBuffer()->getId(), clientCompositionDisplay, clientCompositionLayers)) { - ATRACE_NAME("ClientCompositionCacheHit"); outputCompositionState.reusedClientComposition = true; setExpensiveRenderingExpected(false); return base::unique_fd(); } - ATRACE_NAME("ClientCompositionCacheMiss"); mClientCompositionRequestCache->add(tex->getBuffer()->getId(), clientCompositionDisplay, clientCompositionLayers); } @@ -1437,13 +1349,12 @@ void Output::dirtyEntireOutput() { outputState.dirtyRegion.set(outputState.displaySpace.getBoundsAsRect()); } -std::optional Output::chooseCompositionStrategy() { +void Output::chooseCompositionStrategy() { // The base output implementation can only do client composition auto& outputState = editState(); outputState.usesClientComposition = true; outputState.usesDeviceComposition = false; outputState.reusedClientComposition = false; - return {}; } bool Output::getSkipColorTransform() const { @@ -1458,63 +1369,5 @@ compositionengine::Output::FrameFences Output::presentAndGetFrameFences() { return result; } -void Output::setPredictCompositionStrategy(bool predict) { - if (predict) { - mHwComposerAsyncWorker = std::make_unique(); - } else { - mHwComposerAsyncWorker.reset(nullptr); - } -} - -bool Output::canPredictCompositionStrategy(const CompositionRefreshArgs& refreshArgs) { - if (!getState().isEnabled || !mHwComposerAsyncWorker) { - ALOGV("canPredictCompositionStrategy disabled"); - return false; - } - - if (!getState().previousDeviceRequestedChanges) { - ALOGV("canPredictCompositionStrategy previous changes not available"); - return false; - } - - if (!mRenderSurface->supportsCompositionStrategyPrediction()) { - ALOGV("canPredictCompositionStrategy surface does not support"); - return false; - } - - if (refreshArgs.devOptFlashDirtyRegionsDelay) { - ALOGV("canPredictCompositionStrategy devOptFlashDirtyRegionsDelay"); - return false; - } - - // If no layer uses clientComposition, then don't predict composition strategy - // because we have less work to do in parallel. - if (!anyLayersRequireClientComposition()) { - ALOGV("canPredictCompositionStrategy no layer uses clientComposition"); - return false; - } - - if (!refreshArgs.updatingOutputGeometryThisFrame) { - return true; - } - - ALOGV("canPredictCompositionStrategy updatingOutputGeometryThisFrame"); - return false; -} - -bool Output::anyLayersRequireClientComposition() const { - const auto layers = getOutputLayersOrderedByZ(); - return std::any_of(layers.begin(), layers.end(), - [](const auto& layer) { return layer->requiresClientComposition(); }); -} - -void Output::finishPrepareFrame() { - const auto& state = getState(); - if (mPlanner) { - mPlanner->reportFinalPlan(getOutputLayersOrderedByZ()); - } - mRenderSurface->prepareFrame(state.usesClientComposition, state.usesDeviceComposition); -} - } // namespace impl } // namespace android::compositionengine diff --git a/services/surfaceflinger/CompositionEngine/src/RenderSurface.cpp b/services/surfaceflinger/CompositionEngine/src/RenderSurface.cpp index 5a3af7bfea..12c2c8eb38 100644 --- a/services/surfaceflinger/CompositionEngine/src/RenderSurface.cpp +++ b/services/surfaceflinger/CompositionEngine/src/RenderSurface.cpp @@ -289,9 +289,5 @@ std::shared_ptr& RenderSurface::mutableTextureFor return mTexture; } -bool RenderSurface::supportsCompositionStrategyPrediction() const { - return mDisplaySurface->supportsCompositionStrategyPrediction(); -} - } // namespace impl } // namespace android::compositionengine diff --git a/services/surfaceflinger/CompositionEngine/tests/DisplayTest.cpp b/services/surfaceflinger/CompositionEngine/tests/DisplayTest.cpp index 36b04d909f..cd0323555c 100644 --- a/services/surfaceflinger/CompositionEngine/tests/DisplayTest.cpp +++ b/services/surfaceflinger/CompositionEngine/tests/DisplayTest.cpp @@ -30,9 +30,7 @@ #include #include #include -#include #include - #include #include @@ -200,22 +198,6 @@ struct PartialMockDisplayTestCommon : public DisplayTestCommon { std::shared_ptr mDisplay = createPartialMockDisplay(mCompositionEngine, getDisplayCreationArgsForPhysicalDisplay()); - - android::HWComposer::DeviceRequestedChanges mDeviceRequestedChanges{ - {{nullptr, Composition::CLIENT}}, - hal::DisplayRequest::FLIP_CLIENT_TARGET, - {{nullptr, hal::LayerRequest::CLEAR_CLIENT_TARGET}}, - {hal::PixelFormat::RGBA_8888, hal::Dataspace::UNKNOWN}, - -1.f, - }; - - void chooseCompositionStrategy(Display* display) { - std::optional changes = - display->chooseCompositionStrategy(); - if (changes) { - display->applyCompositionStrategy(changes); - } - } }; struct FullDisplayImplTestCommon : public DisplayTestCommon { @@ -232,11 +214,6 @@ struct DisplayWithLayersTestCommon : public FullDisplayImplTestCommon { std::unique_ptr(mLayer2.outputLayer)); mDisplay->injectOutputLayerForTest( std::unique_ptr(mLayer3.outputLayer)); - mResultWithBuffer.buffer = std::make_shared< - renderengine::mock::FakeExternalTexture>(1U /*width*/, 1U /*height*/, - 1ULL /* bufferId */, - HAL_PIXEL_FORMAT_RGBA_8888, - 0ULL /*usage*/); } Layer mLayer1; @@ -245,8 +222,6 @@ struct DisplayWithLayersTestCommon : public FullDisplayImplTestCommon { StrictMock hwc2LayerUnknown; std::shared_ptr mDisplay = createDisplay(mCompositionEngine, getDisplayCreationArgsForPhysicalDisplay()); - impl::GpuCompositionResult mResultWithBuffer; - impl::GpuCompositionResult mResultWithoutBuffer; }; /* @@ -579,7 +554,7 @@ TEST_F(DisplayChooseCompositionStrategyTest, takesEarlyOutIfGpuDisplay) { createPartialMockDisplay(mCompositionEngine, args); EXPECT_TRUE(GpuVirtualDisplayId::tryCast(gpuDisplay->getId())); - chooseCompositionStrategy(gpuDisplay.get()); + gpuDisplay->chooseCompositionStrategy(); auto& state = gpuDisplay->getState(); EXPECT_TRUE(state.usesClientComposition); @@ -592,12 +567,11 @@ TEST_F(DisplayChooseCompositionStrategyTest, takesEarlyOutOnHwcError) { getDeviceCompositionChanges(HalDisplayId(DEFAULT_DISPLAY_ID), false, _, _, _, _)) .WillOnce(Return(INVALID_OPERATION)); - chooseCompositionStrategy(mDisplay.get()); + mDisplay->chooseCompositionStrategy(); auto& state = mDisplay->getState(); EXPECT_TRUE(state.usesClientComposition); EXPECT_FALSE(state.usesDeviceComposition); - EXPECT_FALSE(state.previousDeviceRequestedChanges.has_value()); } TEST_F(DisplayChooseCompositionStrategyTest, normalOperation) { @@ -614,16 +588,10 @@ TEST_F(DisplayChooseCompositionStrategyTest, normalOperation) { EXPECT_CALL(mHwComposer, getDeviceCompositionChanges(HalDisplayId(DEFAULT_DISPLAY_ID), true, _, _, _, _)) - .WillOnce(testing::DoAll(testing::SetArgPointee<5>(mDeviceRequestedChanges), - Return(NO_ERROR))); - EXPECT_CALL(*mDisplay, applyChangedTypesToLayers(mDeviceRequestedChanges.changedTypes)) - .Times(1); - EXPECT_CALL(*mDisplay, applyDisplayRequests(mDeviceRequestedChanges.displayRequests)).Times(1); - EXPECT_CALL(*mDisplay, applyLayerRequestsToLayers(mDeviceRequestedChanges.layerRequests)) - .Times(1); + .WillOnce(Return(NO_ERROR)); EXPECT_CALL(*mDisplay, allLayersRequireClientComposition()).WillOnce(Return(false)); - chooseCompositionStrategy(mDisplay.get()); + mDisplay->chooseCompositionStrategy(); auto& state = mDisplay->getState(); EXPECT_FALSE(state.usesClientComposition); @@ -650,17 +618,11 @@ TEST_F(DisplayChooseCompositionStrategyTest, normalOperationWithDisplayBrightnes EXPECT_CALL(mHwComposer, getDeviceCompositionChanges(HalDisplayId(DEFAULT_DISPLAY_ID), true, _, _, _, _)) - .WillOnce(testing::DoAll(testing::SetArgPointee<5>(mDeviceRequestedChanges), - Return(NO_ERROR))); - EXPECT_CALL(*mDisplay, applyChangedTypesToLayers(mDeviceRequestedChanges.changedTypes)) - .Times(1); - EXPECT_CALL(*mDisplay, applyDisplayRequests(mDeviceRequestedChanges.displayRequests)).Times(1); - EXPECT_CALL(*mDisplay, applyLayerRequestsToLayers(mDeviceRequestedChanges.layerRequests)) - .Times(1); + .WillOnce(Return(NO_ERROR)); EXPECT_CALL(*mDisplay, allLayersRequireClientComposition()).WillOnce(Return(false)); mDisplay->setNextBrightness(kDisplayBrightness); - chooseCompositionStrategy(mDisplay.get()); + mDisplay->chooseCompositionStrategy(); auto& state = mDisplay->getState(); EXPECT_FALSE(state.usesClientComposition); @@ -669,6 +631,14 @@ TEST_F(DisplayChooseCompositionStrategyTest, normalOperationWithDisplayBrightnes } TEST_F(DisplayChooseCompositionStrategyTest, normalOperationWithChanges) { + android::HWComposer::DeviceRequestedChanges changes{ + {{nullptr, Composition::CLIENT}}, + hal::DisplayRequest::FLIP_CLIENT_TARGET, + {{nullptr, hal::LayerRequest::CLEAR_CLIENT_TARGET}}, + {hal::PixelFormat::RGBA_8888, hal::Dataspace::UNKNOWN}, + -1.f, + }; + // Since two calls are made to anyLayersRequireClientComposition with different return // values, use a Sequence to control the matching so the values are returned in a known // order. @@ -682,15 +652,13 @@ TEST_F(DisplayChooseCompositionStrategyTest, normalOperationWithChanges) { EXPECT_CALL(mHwComposer, getDeviceCompositionChanges(HalDisplayId(DEFAULT_DISPLAY_ID), true, _, _, _, _)) - .WillOnce(DoAll(SetArgPointee<5>(mDeviceRequestedChanges), Return(NO_ERROR))); - EXPECT_CALL(*mDisplay, applyChangedTypesToLayers(mDeviceRequestedChanges.changedTypes)) - .Times(1); - EXPECT_CALL(*mDisplay, applyDisplayRequests(mDeviceRequestedChanges.displayRequests)).Times(1); - EXPECT_CALL(*mDisplay, applyLayerRequestsToLayers(mDeviceRequestedChanges.layerRequests)) - .Times(1); + .WillOnce(DoAll(SetArgPointee<5>(changes), Return(NO_ERROR))); + EXPECT_CALL(*mDisplay, applyChangedTypesToLayers(changes.changedTypes)).Times(1); + EXPECT_CALL(*mDisplay, applyDisplayRequests(changes.displayRequests)).Times(1); + EXPECT_CALL(*mDisplay, applyLayerRequestsToLayers(changes.layerRequests)).Times(1); EXPECT_CALL(*mDisplay, allLayersRequireClientComposition()).WillOnce(Return(false)); - chooseCompositionStrategy(mDisplay.get()); + mDisplay->chooseCompositionStrategy(); auto& state = mDisplay->getState(); EXPECT_FALSE(state.usesClientComposition); @@ -954,7 +922,7 @@ TEST_F(DisplayFinishFrameTest, doesNotSkipCompositionIfNotDirtyOnHwcDisplay) { mDisplay->editState().layerStackSpace.setContent(Rect(0, 0, 1, 1)); mDisplay->editState().dirtyRegion = Region::INVALID_REGION; - mDisplay->finishFrame({}, std::move(mResultWithBuffer)); + mDisplay->finishFrame({}); } TEST_F(DisplayFinishFrameTest, skipsCompositionIfNotDirty) { @@ -972,7 +940,7 @@ TEST_F(DisplayFinishFrameTest, skipsCompositionIfNotDirty) { gpuDisplay->editState().layerStackSpace.setContent(Rect(0, 0, 1, 1)); gpuDisplay->editState().dirtyRegion = Region::INVALID_REGION; - gpuDisplay->finishFrame({}, std::move(mResultWithoutBuffer)); + gpuDisplay->finishFrame({}); } TEST_F(DisplayFinishFrameTest, performsCompositionIfDirty) { @@ -989,7 +957,7 @@ TEST_F(DisplayFinishFrameTest, performsCompositionIfDirty) { gpuDisplay->editState().usesClientComposition = false; gpuDisplay->editState().layerStackSpace.setContent(Rect(0, 0, 1, 1)); gpuDisplay->editState().dirtyRegion = Region(Rect(0, 0, 1, 1)); - gpuDisplay->finishFrame({}, std::move(mResultWithBuffer)); + gpuDisplay->finishFrame({}); } /* diff --git a/services/surfaceflinger/CompositionEngine/tests/OutputTest.cpp b/services/surfaceflinger/CompositionEngine/tests/OutputTest.cpp index 4e875c8a25..c2521b2fc2 100644 --- a/services/surfaceflinger/CompositionEngine/tests/OutputTest.cpp +++ b/services/surfaceflinger/CompositionEngine/tests/OutputTest.cpp @@ -28,7 +28,6 @@ #include #include #include -#include #include #include #include @@ -990,7 +989,7 @@ struct OutputPrepareFrameTest : public testing::Test { struct OutputPartialMock : public OutputPartialMockBase { // Sets up the helper functions called by the function under test to use // mock implementations. - MOCK_METHOD0(chooseCompositionStrategy, std::optional()); + MOCK_METHOD0(chooseCompositionStrategy, void()); }; OutputPrepareFrameTest() { @@ -1038,133 +1037,6 @@ TEST_F(OutputTest, prepareFrameSetsClientCompositionOnlyByDefault) { EXPECT_FALSE(mOutput->getState().usesDeviceComposition); } -struct OutputPrepareFrameAsyncTest : public testing::Test { - struct OutputPartialMock : public OutputPartialMockBase { - // Sets up the helper functions called by the function under test to use - // mock implementations. - MOCK_METHOD0(chooseCompositionStrategy, std::optional()); - MOCK_METHOD0(updateProtectedContentState, void()); - MOCK_METHOD2(dequeueRenderBuffer, - bool(base::unique_fd*, std::shared_ptr*)); - MOCK_METHOD0(chooseCompositionStrategyAsync, - std::future>()); - MOCK_METHOD4(composeSurfaces, - std::optional( - const Region&, const compositionengine::CompositionRefreshArgs&, - std::shared_ptr, base::unique_fd&)); - }; - - OutputPrepareFrameAsyncTest() { - mOutput.setDisplayColorProfileForTest( - std::unique_ptr(mDisplayColorProfile)); - mOutput.setRenderSurfaceForTest(std::unique_ptr(mRenderSurface)); - } - - StrictMock mCompositionEngine; - mock::DisplayColorProfile* mDisplayColorProfile = new StrictMock(); - mock::RenderSurface* mRenderSurface = new StrictMock(); - StrictMock mOutput; - CompositionRefreshArgs mRefreshArgs; -}; - -TEST_F(OutputPrepareFrameAsyncTest, delegatesToChooseCompositionStrategyAndRenderSurface) { - mOutput.editState().isEnabled = true; - mOutput.editState().usesClientComposition = false; - mOutput.editState().usesDeviceComposition = true; - mOutput.editState().previousDeviceRequestedChanges = - std::make_optional({}); - std::promise> p; - p.set_value(mOutput.editState().previousDeviceRequestedChanges); - - EXPECT_CALL(mOutput, getOutputLayerCount()).WillRepeatedly(Return(0u)); - EXPECT_CALL(mOutput, updateProtectedContentState()); - EXPECT_CALL(mOutput, dequeueRenderBuffer(_, _)).WillOnce(Return(true)); - EXPECT_CALL(*mRenderSurface, prepareFrame(false, true)); - EXPECT_CALL(mOutput, chooseCompositionStrategyAsync()).WillOnce([&] { return p.get_future(); }); - EXPECT_CALL(mOutput, composeSurfaces(_, Ref(mRefreshArgs), _, _)); - - impl::GpuCompositionResult result = mOutput.prepareFrameAsync(mRefreshArgs); - EXPECT_TRUE(result.succeeded); - EXPECT_FALSE(result.bufferAvailable()); -} - -TEST_F(OutputPrepareFrameAsyncTest, skipCompositionOnDequeueFailure) { - mOutput.editState().isEnabled = true; - mOutput.editState().usesClientComposition = false; - mOutput.editState().usesDeviceComposition = true; - mOutput.editState().previousDeviceRequestedChanges = - std::make_optional({}); - std::promise> p; - p.set_value(mOutput.editState().previousDeviceRequestedChanges); - - EXPECT_CALL(mOutput, getOutputLayerCount()).WillRepeatedly(Return(0u)); - EXPECT_CALL(mOutput, updateProtectedContentState()); - EXPECT_CALL(mOutput, dequeueRenderBuffer(_, _)).WillOnce(Return(false)); - EXPECT_CALL(*mRenderSurface, prepareFrame(false, true)).Times(2); - EXPECT_CALL(mOutput, chooseCompositionStrategyAsync()).WillOnce([&] { return p.get_future(); }); - - impl::GpuCompositionResult result = mOutput.prepareFrameAsync(mRefreshArgs); - EXPECT_FALSE(result.succeeded); - EXPECT_FALSE(result.bufferAvailable()); -} - -// Tests that in the event of hwc error when choosing composition strategy, we would fall back -// client composition -TEST_F(OutputPrepareFrameAsyncTest, chooseCompositionStrategyFailureCallsPrepareFrame) { - mOutput.editState().isEnabled = true; - mOutput.editState().usesClientComposition = false; - mOutput.editState().usesDeviceComposition = true; - mOutput.editState().previousDeviceRequestedChanges = - std::make_optional({}); - std::promise> p; - p.set_value({}); - std::shared_ptr tex = - std::make_shared(1, 1, - HAL_PIXEL_FORMAT_RGBA_8888, 1, - 2); - - EXPECT_CALL(mOutput, getOutputLayerCount()).WillRepeatedly(Return(0u)); - EXPECT_CALL(mOutput, updateProtectedContentState()); - EXPECT_CALL(mOutput, dequeueRenderBuffer(_, _)) - .WillOnce(DoAll(SetArgPointee<1>(tex), Return(true))); - EXPECT_CALL(*mRenderSurface, prepareFrame(false, true)).Times(2); - EXPECT_CALL(mOutput, chooseCompositionStrategyAsync()).WillOnce([&] { return p.get_future(); }); - EXPECT_CALL(mOutput, composeSurfaces(_, Ref(mRefreshArgs), _, _)); - - impl::GpuCompositionResult result = mOutput.prepareFrameAsync(mRefreshArgs); - EXPECT_FALSE(result.succeeded); - EXPECT_TRUE(result.bufferAvailable()); -} - -TEST_F(OutputPrepareFrameAsyncTest, predictionMiss) { - mOutput.editState().isEnabled = true; - mOutput.editState().usesClientComposition = false; - mOutput.editState().usesDeviceComposition = true; - mOutput.editState().previousDeviceRequestedChanges = - std::make_optional({}); - auto newDeviceRequestedChanges = - std::make_optional({}); - newDeviceRequestedChanges->clientTargetBrightness = 5.f; - std::promise> p; - p.set_value(newDeviceRequestedChanges); - std::shared_ptr tex = - std::make_shared(1, 1, - HAL_PIXEL_FORMAT_RGBA_8888, 1, - 2); - - EXPECT_CALL(mOutput, getOutputLayerCount()).WillRepeatedly(Return(0u)); - EXPECT_CALL(mOutput, updateProtectedContentState()); - EXPECT_CALL(mOutput, dequeueRenderBuffer(_, _)) - .WillOnce(DoAll(SetArgPointee<1>(tex), Return(true))); - EXPECT_CALL(*mRenderSurface, prepareFrame(false, true)).Times(2); - EXPECT_CALL(mOutput, chooseCompositionStrategyAsync()).WillOnce([&] { return p.get_future(); }); - EXPECT_CALL(mOutput, composeSurfaces(_, Ref(mRefreshArgs), _, _)); - - impl::GpuCompositionResult result = mOutput.prepareFrameAsync(mRefreshArgs); - EXPECT_FALSE(result.succeeded); - EXPECT_TRUE(result.bufferAvailable()); -} - /* * Output::prepare() */ @@ -1923,14 +1795,10 @@ struct OutputPresentTest : public testing::Test { MOCK_METHOD1(setColorTransform, void(const compositionengine::CompositionRefreshArgs&)); MOCK_METHOD0(beginFrame, void()); MOCK_METHOD0(prepareFrame, void()); - MOCK_METHOD1(prepareFrameAsync, GpuCompositionResult(const CompositionRefreshArgs&)); MOCK_METHOD1(devOptRepaintFlash, void(const compositionengine::CompositionRefreshArgs&)); - MOCK_METHOD2(finishFrame, - void(const compositionengine::CompositionRefreshArgs&, - GpuCompositionResult&&)); + MOCK_METHOD1(finishFrame, void(const compositionengine::CompositionRefreshArgs&)); MOCK_METHOD0(postFramebuffer, void()); MOCK_METHOD1(renderCachedSets, void(const compositionengine::CompositionRefreshArgs&)); - MOCK_METHOD1(canPredictCompositionStrategy, bool(const CompositionRefreshArgs&)); }; StrictMock mOutput; @@ -1946,30 +1814,9 @@ TEST_F(OutputPresentTest, justInvokesChildFunctionsInSequence) { EXPECT_CALL(mOutput, writeCompositionState(Ref(args))); EXPECT_CALL(mOutput, setColorTransform(Ref(args))); EXPECT_CALL(mOutput, beginFrame()); - EXPECT_CALL(mOutput, canPredictCompositionStrategy(Ref(args))).WillOnce(Return(false)); EXPECT_CALL(mOutput, prepareFrame()); EXPECT_CALL(mOutput, devOptRepaintFlash(Ref(args))); - EXPECT_CALL(mOutput, finishFrame(Ref(args), _)); - EXPECT_CALL(mOutput, postFramebuffer()); - EXPECT_CALL(mOutput, renderCachedSets(Ref(args))); - - mOutput.present(args); -} - -TEST_F(OutputPresentTest, predictingCompositionStrategyInvokesPrepareFrameAsync) { - CompositionRefreshArgs args; - - InSequence seq; - EXPECT_CALL(mOutput, updateColorProfile(Ref(args))); - EXPECT_CALL(mOutput, updateCompositionState(Ref(args))); - EXPECT_CALL(mOutput, planComposition()); - EXPECT_CALL(mOutput, writeCompositionState(Ref(args))); - EXPECT_CALL(mOutput, setColorTransform(Ref(args))); - EXPECT_CALL(mOutput, beginFrame()); - EXPECT_CALL(mOutput, canPredictCompositionStrategy(Ref(args))).WillOnce(Return(true)); - EXPECT_CALL(mOutput, prepareFrameAsync(Ref(args))); - EXPECT_CALL(mOutput, devOptRepaintFlash(Ref(args))); - EXPECT_CALL(mOutput, finishFrame(Ref(args), _)); + EXPECT_CALL(mOutput, finishFrame(Ref(args))); EXPECT_CALL(mOutput, postFramebuffer()); EXPECT_CALL(mOutput, renderCachedSets(Ref(args))); @@ -2867,15 +2714,11 @@ struct OutputDevOptRepaintFlashTest : public testing::Test { // Sets up the helper functions called by the function under test to use // mock implementations. MOCK_METHOD(Region, getDirtyRegion, (), (const)); - MOCK_METHOD4(composeSurfaces, + MOCK_METHOD2(composeSurfaces, std::optional( - const Region&, const compositionengine::CompositionRefreshArgs&, - std::shared_ptr, base::unique_fd&)); + const Region&, const compositionengine::CompositionRefreshArgs&)); MOCK_METHOD0(postFramebuffer, void()); MOCK_METHOD0(prepareFrame, void()); - MOCK_METHOD0(updateProtectedContentState, void()); - MOCK_METHOD2(dequeueRenderBuffer, - bool(base::unique_fd*, std::shared_ptr*)); }; OutputDevOptRepaintFlashTest() { @@ -2932,9 +2775,7 @@ TEST_F(OutputDevOptRepaintFlashTest, alsoComposesSurfacesAndQueuesABufferIfDirty InSequence seq; EXPECT_CALL(mOutput, getDirtyRegion()).WillOnce(Return(kNotEmptyRegion)); - EXPECT_CALL(mOutput, updateProtectedContentState()); - EXPECT_CALL(mOutput, dequeueRenderBuffer(_, _)); - EXPECT_CALL(mOutput, composeSurfaces(RegionEq(kNotEmptyRegion), Ref(mRefreshArgs), _, _)); + EXPECT_CALL(mOutput, composeSurfaces(RegionEq(kNotEmptyRegion), Ref(mRefreshArgs))); EXPECT_CALL(*mRenderSurface, queueBuffer(_)); EXPECT_CALL(mOutput, postFramebuffer()); EXPECT_CALL(mOutput, prepareFrame()); @@ -2950,14 +2791,10 @@ struct OutputFinishFrameTest : public testing::Test { struct OutputPartialMock : public OutputPartialMockBase { // Sets up the helper functions called by the function under test to use // mock implementations. - MOCK_METHOD4(composeSurfaces, + MOCK_METHOD2(composeSurfaces, std::optional( - const Region&, const compositionengine::CompositionRefreshArgs&, - std::shared_ptr, base::unique_fd&)); + const Region&, const compositionengine::CompositionRefreshArgs&)); MOCK_METHOD0(postFramebuffer, void()); - MOCK_METHOD0(updateProtectedContentState, void()); - MOCK_METHOD2(dequeueRenderBuffer, - bool(base::unique_fd*, std::shared_ptr*)); }; OutputFinishFrameTest() { @@ -2975,63 +2812,27 @@ struct OutputFinishFrameTest : public testing::Test { TEST_F(OutputFinishFrameTest, ifNotEnabledDoesNothing) { mOutput.mState.isEnabled = false; - impl::GpuCompositionResult result; - mOutput.finishFrame(mRefreshArgs, std::move(result)); + mOutput.finishFrame(mRefreshArgs); } TEST_F(OutputFinishFrameTest, takesEarlyOutifComposeSurfacesReturnsNoFence) { mOutput.mState.isEnabled = true; - EXPECT_CALL(mOutput, updateProtectedContentState()); - EXPECT_CALL(mOutput, dequeueRenderBuffer(_, _)).WillOnce(Return(true)); - EXPECT_CALL(mOutput, composeSurfaces(RegionEq(Region::INVALID_REGION), _, _, _)); - - impl::GpuCompositionResult result; - mOutput.finishFrame(mRefreshArgs, std::move(result)); -} - -TEST_F(OutputFinishFrameTest, queuesBufferIfComposeSurfacesReturnsAFence) { - mOutput.mState.isEnabled = true; - - InSequence seq; - EXPECT_CALL(mOutput, updateProtectedContentState()); - EXPECT_CALL(mOutput, dequeueRenderBuffer(_, _)).WillOnce(Return(true)); - EXPECT_CALL(mOutput, composeSurfaces(RegionEq(Region::INVALID_REGION), _, _, _)) - .WillOnce(Return(ByMove(base::unique_fd()))); - EXPECT_CALL(*mRenderSurface, queueBuffer(_)); - - impl::GpuCompositionResult result; - mOutput.finishFrame(mRefreshArgs, std::move(result)); -} - -TEST_F(OutputFinishFrameTest, predictionSucceeded) { - mOutput.mState.isEnabled = true; InSequence seq; - EXPECT_CALL(*mRenderSurface, queueBuffer(_)); + EXPECT_CALL(mOutput, composeSurfaces(RegionEq(Region::INVALID_REGION), _)); - impl::GpuCompositionResult result; - result.succeeded = true; - mOutput.finishFrame(mRefreshArgs, std::move(result)); + mOutput.finishFrame(mRefreshArgs); } -TEST_F(OutputFinishFrameTest, predictionFailedAndBufferIsReused) { +TEST_F(OutputFinishFrameTest, queuesBufferIfComposeSurfacesReturnsAFence) { mOutput.mState.isEnabled = true; InSequence seq; - - impl::GpuCompositionResult result; - result.succeeded = false; - result.buffer = - std::make_shared(1, 1, - HAL_PIXEL_FORMAT_RGBA_8888, 1, - 2); - - EXPECT_CALL(mOutput, - composeSurfaces(RegionEq(Region::INVALID_REGION), _, result.buffer, - Eq(ByRef(result.fence)))) + EXPECT_CALL(mOutput, composeSurfaces(RegionEq(Region::INVALID_REGION), _)) .WillOnce(Return(ByMove(base::unique_fd()))); EXPECT_CALL(*mRenderSurface, queueBuffer(_)); - mOutput.finishFrame(mRefreshArgs, std::move(result)); + + mOutput.finishFrame(mRefreshArgs); } /* @@ -3278,15 +3079,8 @@ struct OutputComposeSurfacesTest : public testing::Test { struct ExecuteState : public CallOrderStateMachineHelper { auto execute() { - base::unique_fd fence; - std::shared_ptr externalTexture; - const bool success = - getInstance()->mOutput.dequeueRenderBuffer(&fence, &externalTexture); - if (success) { - getInstance()->mReadyFence = - getInstance()->mOutput.composeSurfaces(kDebugRegion, kDefaultRefreshArgs, - externalTexture, fence); - } + getInstance()->mReadyFence = + getInstance()->mOutput.composeSurfaces(kDebugRegion, kDefaultRefreshArgs); return nextState(); } }; @@ -3847,11 +3641,7 @@ TEST_F(OutputComposeSurfacesTest_HandlesProtectedContent, ifDisplayIsNotSecure) EXPECT_CALL(mRenderEngine, isProtected).WillOnce(Return(true)); EXPECT_CALL(mRenderEngine, useProtectedContext(false)); - base::unique_fd fd; - std::shared_ptr tex; - mOutput.updateProtectedContentState(); - mOutput.dequeueRenderBuffer(&fd, &tex); - mOutput.composeSurfaces(kDebugRegion, kDefaultRefreshArgs, tex, fd); + mOutput.composeSurfaces(kDebugRegion, kDefaultRefreshArgs); } TEST_F(OutputComposeSurfacesTest_HandlesProtectedContent, ifRenderEngineDoesNotSupportIt) { @@ -3859,11 +3649,7 @@ TEST_F(OutputComposeSurfacesTest_HandlesProtectedContent, ifRenderEngineDoesNotS mLayer2.mLayerFEState.hasProtectedContent = true; EXPECT_CALL(mRenderEngine, supportsProtectedContent()).WillRepeatedly(Return(false)); - base::unique_fd fd; - std::shared_ptr tex; - mOutput.updateProtectedContentState(); - mOutput.dequeueRenderBuffer(&fd, &tex); - mOutput.composeSurfaces(kDebugRegion, kDefaultRefreshArgs, tex, fd); + mOutput.composeSurfaces(kDebugRegion, kDefaultRefreshArgs); } TEST_F(OutputComposeSurfacesTest_HandlesProtectedContent, ifNoProtectedContentLayers) { @@ -3875,11 +3661,7 @@ TEST_F(OutputComposeSurfacesTest_HandlesProtectedContent, ifNoProtectedContentLa EXPECT_CALL(mRenderEngine, useProtectedContext(false)); EXPECT_CALL(*mRenderSurface, setProtected(false)); - base::unique_fd fd; - std::shared_ptr tex; - mOutput.updateProtectedContentState(); - mOutput.dequeueRenderBuffer(&fd, &tex); - mOutput.composeSurfaces(kDebugRegion, kDefaultRefreshArgs, tex, fd); + mOutput.composeSurfaces(kDebugRegion, kDefaultRefreshArgs); } TEST_F(OutputComposeSurfacesTest_HandlesProtectedContent, ifNotEnabled) { @@ -3901,11 +3683,7 @@ TEST_F(OutputComposeSurfacesTest_HandlesProtectedContent, ifNotEnabled) { .WillOnce(Return(ByMove( futureOf({NO_ERROR, base::unique_fd()})))); - base::unique_fd fd; - std::shared_ptr tex; - mOutput.updateProtectedContentState(); - mOutput.dequeueRenderBuffer(&fd, &tex); - mOutput.composeSurfaces(kDebugRegion, kDefaultRefreshArgs, tex, fd); + mOutput.composeSurfaces(kDebugRegion, kDefaultRefreshArgs); } TEST_F(OutputComposeSurfacesTest_HandlesProtectedContent, ifAlreadyEnabledEverywhere) { @@ -3915,11 +3693,7 @@ TEST_F(OutputComposeSurfacesTest_HandlesProtectedContent, ifAlreadyEnabledEveryw EXPECT_CALL(mRenderEngine, isProtected).WillOnce(Return(true)); EXPECT_CALL(*mRenderSurface, isProtected).WillOnce(Return(true)); - base::unique_fd fd; - std::shared_ptr tex; - mOutput.updateProtectedContentState(); - mOutput.dequeueRenderBuffer(&fd, &tex); - mOutput.composeSurfaces(kDebugRegion, kDefaultRefreshArgs, tex, fd); + mOutput.composeSurfaces(kDebugRegion, kDefaultRefreshArgs); } TEST_F(OutputComposeSurfacesTest_HandlesProtectedContent, ifFailsToEnableInRenderEngine) { @@ -3930,11 +3704,7 @@ TEST_F(OutputComposeSurfacesTest_HandlesProtectedContent, ifFailsToEnableInRende EXPECT_CALL(*mRenderSurface, isProtected).WillOnce(Return(false)); EXPECT_CALL(mRenderEngine, useProtectedContext(true)); - base::unique_fd fd; - std::shared_ptr tex; - mOutput.updateProtectedContentState(); - mOutput.dequeueRenderBuffer(&fd, &tex); - mOutput.composeSurfaces(kDebugRegion, kDefaultRefreshArgs, tex, fd); + mOutput.composeSurfaces(kDebugRegion, kDefaultRefreshArgs); } TEST_F(OutputComposeSurfacesTest_HandlesProtectedContent, ifAlreadyEnabledInRenderEngine) { @@ -3945,11 +3715,7 @@ TEST_F(OutputComposeSurfacesTest_HandlesProtectedContent, ifAlreadyEnabledInRend EXPECT_CALL(*mRenderSurface, isProtected).WillOnce(Return(false)); EXPECT_CALL(*mRenderSurface, setProtected(true)); - base::unique_fd fd; - std::shared_ptr tex; - mOutput.updateProtectedContentState(); - mOutput.dequeueRenderBuffer(&fd, &tex); - mOutput.composeSurfaces(kDebugRegion, kDefaultRefreshArgs, tex, fd); + mOutput.composeSurfaces(kDebugRegion, kDefaultRefreshArgs); } TEST_F(OutputComposeSurfacesTest_HandlesProtectedContent, ifAlreadyEnabledInRenderSurface) { @@ -3960,11 +3726,7 @@ TEST_F(OutputComposeSurfacesTest_HandlesProtectedContent, ifAlreadyEnabledInRend EXPECT_CALL(*mRenderSurface, isProtected).WillOnce(Return(true)); EXPECT_CALL(mRenderEngine, useProtectedContext(true)); - base::unique_fd fd; - std::shared_ptr tex; - mOutput.updateProtectedContentState(); - mOutput.dequeueRenderBuffer(&fd, &tex); - mOutput.composeSurfaces(kDebugRegion, kDefaultRefreshArgs, tex, fd); + mOutput.composeSurfaces(kDebugRegion, kDefaultRefreshArgs); } struct OutputComposeSurfacesTest_SetsExpensiveRendering : public OutputComposeSurfacesTest { @@ -3993,11 +3755,7 @@ TEST_F(OutputComposeSurfacesTest_SetsExpensiveRendering, IfExepensiveOutputDatas .WillOnce(Return(ByMove( futureOf({NO_ERROR, base::unique_fd()})))); - base::unique_fd fd; - std::shared_ptr tex; - mOutput.updateProtectedContentState(); - mOutput.dequeueRenderBuffer(&fd, &tex); - mOutput.composeSurfaces(kDebugRegion, kDefaultRefreshArgs, tex, fd); + mOutput.composeSurfaces(kDebugRegion, kDefaultRefreshArgs); } struct OutputComposeSurfacesTest_SetsExpensiveRendering_ForBlur @@ -4032,12 +3790,7 @@ TEST_F(OutputComposeSurfacesTest_SetsExpensiveRendering_ForBlur, IfBlursAreExpen mOutput.writeCompositionState(mRefreshArgs); EXPECT_CALL(mOutput, setExpensiveRenderingExpected(true)); - - base::unique_fd fd; - std::shared_ptr tex; - mOutput.updateProtectedContentState(); - mOutput.dequeueRenderBuffer(&fd, &tex); - mOutput.composeSurfaces(kDebugRegion, mRefreshArgs, tex, fd); + mOutput.composeSurfaces(kDebugRegion, mRefreshArgs); } TEST_F(OutputComposeSurfacesTest_SetsExpensiveRendering_ForBlur, IfBlursAreNotExpensive) { @@ -4047,12 +3800,7 @@ TEST_F(OutputComposeSurfacesTest_SetsExpensiveRendering_ForBlur, IfBlursAreNotEx mOutput.writeCompositionState(mRefreshArgs); EXPECT_CALL(mOutput, setExpensiveRenderingExpected(true)).Times(0); - - base::unique_fd fd; - std::shared_ptr tex; - mOutput.updateProtectedContentState(); - mOutput.dequeueRenderBuffer(&fd, &tex); - mOutput.composeSurfaces(kDebugRegion, mRefreshArgs, tex, fd); + mOutput.composeSurfaces(kDebugRegion, mRefreshArgs); } /* diff --git a/services/surfaceflinger/DisplayDevice.cpp b/services/surfaceflinger/DisplayDevice.cpp index 610d86f29a..45b98bb3d3 100644 --- a/services/surfaceflinger/DisplayDevice.cpp +++ b/services/surfaceflinger/DisplayDevice.cpp @@ -91,7 +91,6 @@ DisplayDevice::DisplayDevice(DisplayDeviceCreationArgs& args) static_cast(SurfaceFlinger::maxFrameBufferAcquiredBuffers)); } - mCompositionDisplay->setPredictCompositionStrategy(mFlinger->mPredictCompositionStrategy); mCompositionDisplay->createDisplayColorProfile( compositionengine::DisplayColorProfileCreationArgsBuilder() .setHasWideColorGamut(args.hasWideColorGamut) diff --git a/services/surfaceflinger/DisplayHardware/HWComposer.h b/services/surfaceflinger/DisplayHardware/HWComposer.h index a8d439b7e0..5b2e265eb6 100644 --- a/services/surfaceflinger/DisplayHardware/HWComposer.h +++ b/services/surfaceflinger/DisplayHardware/HWComposer.h @@ -269,14 +269,6 @@ public: support) = 0; }; -static inline bool operator==(const android::HWComposer::DeviceRequestedChanges& lhs, - const android::HWComposer::DeviceRequestedChanges& rhs) { - return lhs.changedTypes == rhs.changedTypes && lhs.displayRequests == rhs.displayRequests && - lhs.layerRequests == rhs.layerRequests && - lhs.clientTargetProperty == rhs.clientTargetProperty && - lhs.clientTargetBrightness == rhs.clientTargetBrightness; -} - namespace impl { class HWComposer final : public android::HWComposer { diff --git a/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.h b/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.h index e21095aa88..307da41667 100644 --- a/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.h +++ b/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.h @@ -89,9 +89,6 @@ public: virtual void dumpAsString(String8& result) const; virtual void resizeBuffers(const ui::Size&) override; virtual const sp& getClientTargetAcquireFence() const override; - // Virtual display surface needs to prepare the frame based on composition type. Skip - // any client composition prediction. - virtual bool supportsCompositionStrategyPrediction() const override { return false; }; private: enum Source : size_t { diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp index b47611c149..ecf94b1786 100644 --- a/services/surfaceflinger/SurfaceFlinger.cpp +++ b/services/surfaceflinger/SurfaceFlinger.cpp @@ -480,9 +480,6 @@ SurfaceFlinger::SurfaceFlinger(Factory& factory) : SurfaceFlinger(factory, SkipI property_get("debug.sf.disable_client_composition_cache", value, "0"); mDisableClientCompositionCache = atoi(value); - property_get("debug.sf.predict_hwc_composition_strategy", value, "0"); - mPredictCompositionStrategy = atoi(value); - // We should be reading 'persist.sys.sf.color_saturation' here // but since /data may be encrypted, we need to wait until after vold // comes online to attempt to read the property. The property is diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h index 0365b3744c..7effd1550e 100644 --- a/services/surfaceflinger/SurfaceFlinger.h +++ b/services/surfaceflinger/SurfaceFlinger.h @@ -344,11 +344,6 @@ public: void disableExpensiveRendering(); FloatRect getMaxDisplayBounds(); - // If set, composition engine tries to predict the composition strategy provided by HWC - // based on the previous frame. If the strategy can be predicted, gpu composition will - // run parallel to the hwc validateDisplay call and re-run if the predition is incorrect. - bool mPredictCompositionStrategy = false; - protected: // We're reference counted, never destroy SurfaceFlinger directly virtual ~SurfaceFlinger(); -- cgit v1.2.3-59-g8ed1b From 3afe17bb2531bd0ec085edcdf1044d12ebcb34fa Mon Sep 17 00:00:00 2001 From: Robert Carr Date: Wed, 9 Mar 2022 13:49:13 -0800 Subject: Revert "SF: Enable HWC composition strategy prediction" This reverts commit f0b2b014eb025d0d889ca2d68bd0ff5d95ee6e40. Change-Id: Idee6c3cac6cadf15e7042243c706c640b70ce3e9 Bug:223543469 (cherry picked from commit 279209ba77fed81d81a378266659e4de22124de1) Merged-In: Idee6c3cac6cadf15e7042243c706c640b70ce3e9 --- services/surfaceflinger/SurfaceFlinger.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp index d1ac1d3497..4fe656d027 100644 --- a/services/surfaceflinger/SurfaceFlinger.cpp +++ b/services/surfaceflinger/SurfaceFlinger.cpp @@ -482,7 +482,7 @@ SurfaceFlinger::SurfaceFlinger(Factory& factory) : SurfaceFlinger(factory, SkipI property_get("debug.sf.disable_client_composition_cache", value, "0"); mDisableClientCompositionCache = atoi(value); - property_get("debug.sf.predict_hwc_composition_strategy", value, "1"); + property_get("debug.sf.predict_hwc_composition_strategy", value, "0"); mPredictCompositionStrategy = atoi(value); // We should be reading 'persist.sys.sf.color_saturation' here -- cgit v1.2.3-59-g8ed1b From 578a060d3221d8309b8406453c4ef682f9f1f957 Mon Sep 17 00:00:00 2001 From: Robert Carr Date: Wed, 9 Mar 2022 13:49:30 -0800 Subject: Revert "SF: Add composition strategy prediction stats" This reverts commit 47183ae01af735473ec636e16aa8293da839efac. Change-Id: I92f9f0e7fdd56a8749207a88887e1f23e25ee924 Bug: 223543469 (cherry picked from commit a00eb14c5e8a95413b4f72b99a09b6acc5f5a374) Merged-In: I92f9f0e7fdd56a8749207a88887e1f23e25ee924 --- .../compositionengine/impl/GpuCompositionResult.h | 3 + .../impl/OutputCompositionState.h | 12 ---- .../CompositionEngine/src/Output.cpp | 13 ++-- .../src/OutputCompositionState.cpp | 14 ----- .../CompositionEngine/tests/OutputTest.cpp | 18 +++--- services/surfaceflinger/SurfaceFlinger.cpp | 41 ++++++------ services/surfaceflinger/TimeStats/TimeStats.cpp | 34 ++++++---- services/surfaceflinger/TimeStats/TimeStats.h | 32 +++------- .../TimeStats/timestatsproto/TimeStatsHelper.cpp | 8 --- .../include/timestatsproto/TimeStatsHelper.h | 2 - .../tests/unittests/TimeStatsTest.cpp | 73 ++++++++-------------- .../tests/unittests/mock/MockTimeStats.h | 5 +- 12 files changed, 100 insertions(+), 155 deletions(-) diff --git a/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/GpuCompositionResult.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/GpuCompositionResult.h index 2b1f50ff57..ed1ddc172c 100644 --- a/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/GpuCompositionResult.h +++ b/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/GpuCompositionResult.h @@ -22,6 +22,9 @@ namespace android::compositionengine::impl { struct GpuCompositionResult { + // True if composition strategy was predicted successfully. + bool succeeded = false; + // Composition ready fence. base::unique_fd fence{}; diff --git a/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/OutputCompositionState.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/OutputCompositionState.h index ade9b25b63..92f22b6a16 100644 --- a/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/OutputCompositionState.h +++ b/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/OutputCompositionState.h @@ -141,18 +141,6 @@ struct OutputCompositionState { // This is slightly distinct from nits, in that nits cannot be passed to hw composer. std::optional displayBrightness = std::nullopt; - enum class CompositionStrategyPredictionState : uint32_t { - // Composition strategy prediction did not run for this frame. - DISABLED = 0, - // Composition strategy predicted successfully for this frame. - SUCCESS = 1, - // Composition strategy prediction failed for this frame. - FAIL = 2, - }; - - CompositionStrategyPredictionState strategyPrediction = - CompositionStrategyPredictionState::DISABLED; - // Debugging void dump(std::string& result) const; }; diff --git a/services/surfaceflinger/CompositionEngine/src/Output.cpp b/services/surfaceflinger/CompositionEngine/src/Output.cpp index 7e650a19f9..cd10bc10b5 100644 --- a/services/surfaceflinger/CompositionEngine/src/Output.cpp +++ b/services/surfaceflinger/CompositionEngine/src/Output.cpp @@ -58,8 +58,7 @@ namespace android::compositionengine { Output::~Output() = default; namespace impl { -using CompositionStrategyPredictionState = - OutputCompositionState::CompositionStrategyPredictionState; + namespace { template @@ -967,7 +966,6 @@ void Output::prepareFrame() { } auto changes = chooseCompositionStrategy(); - outputState.strategyPrediction = CompositionStrategyPredictionState::DISABLED; outputState.previousDeviceRequestedChanges = changes; if (changes) { applyCompositionStrategy(changes); @@ -1004,8 +1002,7 @@ GpuCompositionResult Output::prepareFrameAsync(const CompositionRefreshArgs& ref auto changes = hwcResult.valid() ? hwcResult.get() : std::nullopt; const bool predictionSucceeded = dequeueSucceeded && changes == previousChanges; - state.strategyPrediction = predictionSucceeded ? CompositionStrategyPredictionState::SUCCESS - : CompositionStrategyPredictionState::FAIL; + compositionResult.succeeded = predictionSucceeded; if (!predictionSucceeded) { ATRACE_NAME("CompositionStrategyPredictionMiss"); if (changes) { @@ -1047,15 +1044,15 @@ void Output::devOptRepaintFlash(const compositionengine::CompositionRefreshArgs& void Output::finishFrame(const CompositionRefreshArgs& refreshArgs, GpuCompositionResult&& result) { ATRACE_CALL(); ALOGV(__FUNCTION__); - const auto& outputState = getState(); - if (!outputState.isEnabled) { + + if (!getState().isEnabled) { return; } std::optional optReadyFence; std::shared_ptr buffer; base::unique_fd bufferFence; - if (outputState.strategyPrediction == CompositionStrategyPredictionState::SUCCESS) { + if (result.succeeded) { optReadyFence = std::move(result.fence); } else { if (result.bufferAvailable()) { diff --git a/services/surfaceflinger/CompositionEngine/src/OutputCompositionState.cpp b/services/surfaceflinger/CompositionEngine/src/OutputCompositionState.cpp index 7188281974..482250a165 100644 --- a/services/surfaceflinger/CompositionEngine/src/OutputCompositionState.cpp +++ b/services/surfaceflinger/CompositionEngine/src/OutputCompositionState.cpp @@ -18,19 +18,6 @@ #include namespace android::compositionengine::impl { -using CompositionStrategyPredictionState = - OutputCompositionState::CompositionStrategyPredictionState; - -std::string toString(CompositionStrategyPredictionState state) { - switch (state) { - case CompositionStrategyPredictionState::DISABLED: - return "Disabled"; - case CompositionStrategyPredictionState::SUCCESS: - return "Success"; - case CompositionStrategyPredictionState::FAIL: - return "Fail"; - } -} void OutputCompositionState::dump(std::string& out) const { out.append(" "); @@ -69,7 +56,6 @@ void OutputCompositionState::dump(std::string& out) const { dumpVal(out, "sdrWhitePointNits", sdrWhitePointNits); dumpVal(out, "clientTargetBrightness", clientTargetBrightness); dumpVal(out, "displayBrightness", displayBrightness); - dumpVal(out, "compositionStrategyPredictionState", toString(strategyPrediction)); out.append("\n"); } diff --git a/services/surfaceflinger/CompositionEngine/tests/OutputTest.cpp b/services/surfaceflinger/CompositionEngine/tests/OutputTest.cpp index 8bbb73c0ce..af172d8997 100644 --- a/services/surfaceflinger/CompositionEngine/tests/OutputTest.cpp +++ b/services/surfaceflinger/CompositionEngine/tests/OutputTest.cpp @@ -74,9 +74,6 @@ const mat4 kNonIdentityQuarter = mat4() * 0.25f; constexpr OutputColorSetting kVendorSpecifiedOutputColorSetting = static_cast(0x100); -using CompositionStrategyPredictionState = android::compositionengine::impl:: - OutputCompositionState::CompositionStrategyPredictionState; - struct OutputPartialMockBase : public impl::Output { // compositionengine::Output overrides const OutputCompositionState& getState() const override { return mState; } @@ -1024,7 +1021,6 @@ TEST_F(OutputPrepareFrameTest, delegatesToChooseCompositionStrategyAndRenderSurf EXPECT_CALL(*mRenderSurface, prepareFrame(false, true)); mOutput.prepareFrame(); - EXPECT_EQ(mOutput.getState().strategyPrediction, CompositionStrategyPredictionState::DISABLED); } // Note: Use OutputTest and not OutputPrepareFrameTest, so the real @@ -1040,7 +1036,6 @@ TEST_F(OutputTest, prepareFrameSetsClientCompositionOnlyByDefault) { EXPECT_TRUE(mOutput->getState().usesClientComposition); EXPECT_FALSE(mOutput->getState().usesDeviceComposition); - EXPECT_EQ(mOutput->getState().strategyPrediction, CompositionStrategyPredictionState::DISABLED); } struct OutputPrepareFrameAsyncTest : public testing::Test { @@ -1089,7 +1084,7 @@ TEST_F(OutputPrepareFrameAsyncTest, delegatesToChooseCompositionStrategyAndRende EXPECT_CALL(mOutput, composeSurfaces(_, Ref(mRefreshArgs), _, _)); impl::GpuCompositionResult result = mOutput.prepareFrameAsync(mRefreshArgs); - EXPECT_EQ(mOutput.getState().strategyPrediction, CompositionStrategyPredictionState::SUCCESS); + EXPECT_TRUE(result.succeeded); EXPECT_FALSE(result.bufferAvailable()); } @@ -1109,7 +1104,7 @@ TEST_F(OutputPrepareFrameAsyncTest, skipCompositionOnDequeueFailure) { EXPECT_CALL(mOutput, chooseCompositionStrategyAsync()).WillOnce([&] { return p.get_future(); }); impl::GpuCompositionResult result = mOutput.prepareFrameAsync(mRefreshArgs); - EXPECT_EQ(mOutput.getState().strategyPrediction, CompositionStrategyPredictionState::FAIL); + EXPECT_FALSE(result.succeeded); EXPECT_FALSE(result.bufferAvailable()); } @@ -1137,7 +1132,7 @@ TEST_F(OutputPrepareFrameAsyncTest, chooseCompositionStrategyFailureCallsPrepare EXPECT_CALL(mOutput, composeSurfaces(_, Ref(mRefreshArgs), _, _)); impl::GpuCompositionResult result = mOutput.prepareFrameAsync(mRefreshArgs); - EXPECT_EQ(mOutput.getState().strategyPrediction, CompositionStrategyPredictionState::FAIL); + EXPECT_FALSE(result.succeeded); EXPECT_TRUE(result.bufferAvailable()); } @@ -1166,7 +1161,7 @@ TEST_F(OutputPrepareFrameAsyncTest, predictionMiss) { EXPECT_CALL(mOutput, composeSurfaces(_, Ref(mRefreshArgs), _, _)); impl::GpuCompositionResult result = mOutput.prepareFrameAsync(mRefreshArgs); - EXPECT_EQ(mOutput.getState().strategyPrediction, CompositionStrategyPredictionState::FAIL); + EXPECT_FALSE(result.succeeded); EXPECT_TRUE(result.bufferAvailable()); } @@ -3010,21 +3005,22 @@ TEST_F(OutputFinishFrameTest, queuesBufferIfComposeSurfacesReturnsAFence) { TEST_F(OutputFinishFrameTest, predictionSucceeded) { mOutput.mState.isEnabled = true; - mOutput.mState.strategyPrediction = CompositionStrategyPredictionState::SUCCESS; + InSequence seq; EXPECT_CALL(*mRenderSurface, queueBuffer(_)); impl::GpuCompositionResult result; + result.succeeded = true; mOutput.finishFrame(mRefreshArgs, std::move(result)); } TEST_F(OutputFinishFrameTest, predictionFailedAndBufferIsReused) { mOutput.mState.isEnabled = true; - mOutput.mState.strategyPrediction = CompositionStrategyPredictionState::FAIL; InSequence seq; impl::GpuCompositionResult result; + result.succeeded = false; result.buffer = std::make_shared(1, 1, HAL_PIXEL_FORMAT_RGBA_8888, 1, diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp index 4fe656d027..efaa975ff2 100644 --- a/services/surfaceflinger/SurfaceFlinger.cpp +++ b/services/surfaceflinger/SurfaceFlinger.cpp @@ -169,8 +169,6 @@ using aidl::android::hardware::graphics::common::DisplayDecorationSupport; using aidl::android::hardware::graphics::composer3::Capability; using aidl::android::hardware::graphics::composer3::DisplayCapability; -using CompositionStrategyPredictionState = android::compositionengine::impl:: - OutputCompositionState::CompositionStrategyPredictionState; namespace android { @@ -2272,24 +2270,24 @@ void SurfaceFlinger::composite(nsecs_t frameTime, int64_t vsyncId) { const bool prevFrameHadClientComposition = mHadClientComposition; - mHadClientComposition = mHadDeviceComposition = mReusedClientComposition = false; - TimeStats::ClientCompositionRecord clientCompositionRecord; - for (const auto& [_, display] : displays) { - const auto& state = display->getCompositionDisplay()->getState(); - mHadClientComposition |= state.usesClientComposition && !state.reusedClientComposition; - mHadDeviceComposition |= state.usesDeviceComposition; - mReusedClientComposition |= state.reusedClientComposition; - clientCompositionRecord.predicted |= - (state.strategyPrediction != CompositionStrategyPredictionState::DISABLED); - clientCompositionRecord.predictionSucceeded |= - (state.strategyPrediction == CompositionStrategyPredictionState::SUCCESS); + mHadClientComposition = std::any_of(displays.cbegin(), displays.cend(), [](const auto& pair) { + const auto& state = pair.second->getCompositionDisplay()->getState(); + return state.usesClientComposition && !state.reusedClientComposition; + }); + mHadDeviceComposition = std::any_of(displays.cbegin(), displays.cend(), [](const auto& pair) { + const auto& state = pair.second->getCompositionDisplay()->getState(); + return state.usesDeviceComposition; + }); + mReusedClientComposition = + std::any_of(displays.cbegin(), displays.cend(), [](const auto& pair) { + const auto& state = pair.second->getCompositionDisplay()->getState(); + return state.reusedClientComposition; + }); + // Only report a strategy change if we move in and out of client composition + if (prevFrameHadClientComposition != mHadClientComposition) { + mTimeStats->incrementCompositionStrategyChanges(); } - clientCompositionRecord.hadClientComposition = mHadClientComposition; - clientCompositionRecord.reused = mReusedClientComposition; - clientCompositionRecord.changed = prevFrameHadClientComposition != mHadClientComposition; - mTimeStats->pushCompositionStrategyState(clientCompositionRecord); - // TODO: b/160583065 Enable skip validation when SF caches all client composition layers const bool usedGpuComposition = mHadClientComposition || mReusedClientComposition; modulateVsync(&VsyncModulator::onDisplayRefresh, usedGpuComposition); @@ -2544,6 +2542,13 @@ void SurfaceFlinger::postComposition() { } mTimeStats->incrementTotalFrames(); + if (mHadClientComposition) { + mTimeStats->incrementClientCompositionFrames(); + } + + if (mReusedClientComposition) { + mTimeStats->incrementClientCompositionReusedFrames(); + } mTimeStats->setPresentFenceGlobal(mPreviousPresentFences[0].fenceTime); diff --git a/services/surfaceflinger/TimeStats/TimeStats.cpp b/services/surfaceflinger/TimeStats/TimeStats.cpp index e5a9dd47c3..b1a2bdaa91 100644 --- a/services/surfaceflinger/TimeStats/TimeStats.cpp +++ b/services/surfaceflinger/TimeStats/TimeStats.cpp @@ -321,19 +321,22 @@ void TimeStats::incrementMissedFrames() { mTimeStats.missedFramesLegacy++; } -void TimeStats::pushCompositionStrategyState(const TimeStats::ClientCompositionRecord& record) { - if (!mEnabled.load() || !record.hasInterestingData()) { - return; - } +void TimeStats::incrementClientCompositionFrames() { + if (!mEnabled.load()) return; + + ATRACE_CALL(); + + std::lock_guard lock(mMutex); + mTimeStats.clientCompositionFramesLegacy++; +} + +void TimeStats::incrementClientCompositionReusedFrames() { + if (!mEnabled.load()) return; ATRACE_CALL(); std::lock_guard lock(mMutex); - if (record.changed) mTimeStats.compositionStrategyChangesLegacy++; - if (record.hadClientComposition) mTimeStats.clientCompositionFramesLegacy++; - if (record.reused) mTimeStats.clientCompositionReusedFramesLegacy++; - if (record.predicted) mTimeStats.compositionStrategyPredictedLegacy++; - if (record.predictionSucceeded) mTimeStats.compositionStrategyPredictionSucceededLegacy++; + mTimeStats.clientCompositionReusedFramesLegacy++; } void TimeStats::incrementRefreshRateSwitches() { @@ -345,6 +348,15 @@ void TimeStats::incrementRefreshRateSwitches() { mTimeStats.refreshRateSwitchesLegacy++; } +void TimeStats::incrementCompositionStrategyChanges() { + if (!mEnabled.load()) return; + + ATRACE_CALL(); + + std::lock_guard lock(mMutex); + mTimeStats.compositionStrategyChangesLegacy++; +} + void TimeStats::recordDisplayEventConnectionCount(int32_t count) { if (!mEnabled.load()) return; @@ -1050,10 +1062,8 @@ void TimeStats::clearGlobalLocked() { mTimeStats.missedFramesLegacy = 0; mTimeStats.clientCompositionFramesLegacy = 0; mTimeStats.clientCompositionReusedFramesLegacy = 0; - mTimeStats.compositionStrategyChangesLegacy = 0; - mTimeStats.compositionStrategyPredictedLegacy = 0; - mTimeStats.compositionStrategyPredictionSucceededLegacy = 0; mTimeStats.refreshRateSwitchesLegacy = 0; + mTimeStats.compositionStrategyChangesLegacy = 0; mTimeStats.displayEventConnectionsCountLegacy = 0; mTimeStats.displayOnTimeLegacy = 0; mTimeStats.presentToPresentLegacy.hist.clear(); diff --git a/services/surfaceflinger/TimeStats/TimeStats.h b/services/surfaceflinger/TimeStats/TimeStats.h index 7a159b8eb7..77c7973532 100644 --- a/services/surfaceflinger/TimeStats/TimeStats.h +++ b/services/surfaceflinger/TimeStats/TimeStats.h @@ -45,7 +45,7 @@ public: virtual ~TimeStats() = default; // Process a pull request from statsd. - virtual bool onPullAtom(const int atomId, std::string* pulledData) = 0; + virtual bool onPullAtom(const int atomId, std::string* pulledData); virtual void parseArgs(bool asProto, const Vector& args, std::string& result) = 0; virtual bool isEnabled() = 0; @@ -53,8 +53,14 @@ public: virtual void incrementTotalFrames() = 0; virtual void incrementMissedFrames() = 0; + virtual void incrementClientCompositionFrames() = 0; + virtual void incrementClientCompositionReusedFrames() = 0; // Increments the number of times the display refresh rate changed. virtual void incrementRefreshRateSwitches() = 0; + // Increments the number of changes in composition strategy + // The intention is to reflect the number of changes between hwc and gpu + // composition, where "gpu composition" may also include mixed composition. + virtual void incrementCompositionStrategyChanges() = 0; // Records the most up-to-date count of display event connections. // The stored count will be the maximum ever recoded. virtual void recordDisplayEventConnectionCount(int32_t count) = 0; @@ -152,24 +158,6 @@ public: } }; - struct ClientCompositionRecord { - // Frame had client composition or mixed composition - bool hadClientComposition = false; - // Composition changed between hw composition and mixed/client composition - bool changed = false; - // Frame reused the client composition result from a previous frame - bool reused = false; - // Composition strategy predicted for frame - bool predicted = false; - // Composition strategy prediction succeeded - bool predictionSucceeded = false; - - // Whether there is data we want to record. - bool hasInterestingData() const { - return hadClientComposition || changed || reused || predicted; - } - }; - virtual void incrementJankyFrames(const JankyFramesInfo& info) = 0; // Clean up the layer record virtual void onDestroy(int32_t layerId) = 0; @@ -181,7 +169,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; - virtual void pushCompositionStrategyState(const ClientCompositionRecord&) = 0; }; namespace impl { @@ -249,7 +236,10 @@ public: void incrementTotalFrames() override; void incrementMissedFrames() override; + void incrementClientCompositionFrames() override; + void incrementClientCompositionReusedFrames() override; void incrementRefreshRateSwitches() override; + void incrementCompositionStrategyChanges() override; void recordDisplayEventConnectionCount(int32_t count) override; void recordFrameDuration(nsecs_t startTime, nsecs_t endTime) override; @@ -285,8 +275,6 @@ public: void recordRefreshRate(uint32_t fps, nsecs_t duration) override; void setPresentFenceGlobal(const std::shared_ptr& presentFence) override; - void pushCompositionStrategyState(const ClientCompositionRecord&) override; - static const size_t MAX_NUM_TIME_RECORDS = 64; private: diff --git a/services/surfaceflinger/TimeStats/timestatsproto/TimeStatsHelper.cpp b/services/surfaceflinger/TimeStats/timestatsproto/TimeStatsHelper.cpp index cf1ca65972..69afa2a7a1 100644 --- a/services/surfaceflinger/TimeStats/timestatsproto/TimeStatsHelper.cpp +++ b/services/surfaceflinger/TimeStats/timestatsproto/TimeStatsHelper.cpp @@ -143,14 +143,6 @@ std::string TimeStatsHelper::TimeStatsGlobal::toString(std::optional m clientCompositionReusedFramesLegacy); StringAppendF(&result, "refreshRateSwitches = %d\n", refreshRateSwitchesLegacy); StringAppendF(&result, "compositionStrategyChanges = %d\n", compositionStrategyChangesLegacy); - StringAppendF(&result, "compositionStrategyPredicted = %d\n", - compositionStrategyPredictedLegacy); - StringAppendF(&result, "compositionStrategyPredictionSucceeded = %d\n", - compositionStrategyPredictionSucceededLegacy); - StringAppendF(&result, "compositionStrategyPredictionFailed = %d\n", - compositionStrategyPredictedLegacy - - compositionStrategyPredictionSucceededLegacy); - StringAppendF(&result, "displayOnTime = %" PRId64 " ms\n", displayOnTimeLegacy); StringAppendF(&result, "displayConfigStats is as below:\n"); for (const auto& [fps, duration] : refreshRateStatsLegacy) { diff --git a/services/surfaceflinger/TimeStats/timestatsproto/include/timestatsproto/TimeStatsHelper.h b/services/surfaceflinger/TimeStats/timestatsproto/include/timestatsproto/TimeStatsHelper.h index 237ae8d761..438561cc05 100644 --- a/services/surfaceflinger/TimeStats/timestatsproto/include/timestatsproto/TimeStatsHelper.h +++ b/services/surfaceflinger/TimeStats/timestatsproto/include/timestatsproto/TimeStatsHelper.h @@ -178,8 +178,6 @@ public: Histogram frameDurationLegacy; Histogram renderEngineTimingLegacy; std::unordered_map refreshRateStatsLegacy; - int32_t compositionStrategyPredictedLegacy = 0; - int32_t compositionStrategyPredictionSucceededLegacy = 0; std::unordered_map stats; diff --git a/services/surfaceflinger/tests/unittests/TimeStatsTest.cpp b/services/surfaceflinger/tests/unittests/TimeStatsTest.cpp index 6ffc0396d7..0ef8456739 100644 --- a/services/surfaceflinger/tests/unittests/TimeStatsTest.cpp +++ b/services/surfaceflinger/tests/unittests/TimeStatsTest.cpp @@ -268,11 +268,8 @@ TEST_F(TimeStatsTest, canIncreaseGlobalStats) { for (size_t i = 0; i < MISSED_FRAMES; i++) { ASSERT_NO_FATAL_FAILURE(mTimeStats->incrementMissedFrames()); } - TimeStats::ClientCompositionRecord record; - record.hadClientComposition = true; - for (size_t i = 0; i < CLIENT_COMPOSITION_FRAMES; i++) { - ASSERT_NO_FATAL_FAILURE(mTimeStats->pushCompositionStrategyState(record)); + ASSERT_NO_FATAL_FAILURE(mTimeStats->incrementClientCompositionFrames()); } SFTimeStatsGlobalProto globalProto; @@ -462,49 +459,19 @@ TEST_F(TimeStatsTest, canCaptureSetFrameRateVoteAfterZeroForLayer) { EXPECT_THAT(result, HasSubstr(expectedResult)); } -TEST_F(TimeStatsTest, canIncreaseClientCompositionStats) { +TEST_F(TimeStatsTest, canIncreaseClientCompositionReusedFrames) { // this stat is not in the proto so verify by checking the string dump - constexpr size_t COMPOSITION_STRATEGY_CHANGED_FRAMES = 1; - constexpr size_t HAD_CLIENT_COMPOSITION_FRAMES = 2; - constexpr size_t REUSED_CLIENT_COMPOSITION_FRAMES = 3; - constexpr size_t COMPOSITION_STRATEGY_PREDICTION_SUCCEEDED_FRAMES = 4; - constexpr size_t COMPOSITION_STRATEGY_PREDICTED_FRAMES = 5; + constexpr size_t CLIENT_COMPOSITION_REUSED_FRAMES = 2; EXPECT_TRUE(inputCommand(InputCommand::ENABLE, FMT_STRING).empty()); - for (size_t i = 0; i <= COMPOSITION_STRATEGY_PREDICTED_FRAMES; i++) { - TimeStats::ClientCompositionRecord record; - record.hadClientComposition = i < HAD_CLIENT_COMPOSITION_FRAMES; - record.changed = i < COMPOSITION_STRATEGY_CHANGED_FRAMES; - record.reused = i < REUSED_CLIENT_COMPOSITION_FRAMES; - record.predicted = i < COMPOSITION_STRATEGY_PREDICTED_FRAMES; - record.predictionSucceeded = i < COMPOSITION_STRATEGY_PREDICTION_SUCCEEDED_FRAMES; - mTimeStats->pushCompositionStrategyState(record); + for (size_t i = 0; i < CLIENT_COMPOSITION_REUSED_FRAMES; i++) { + ASSERT_NO_FATAL_FAILURE(mTimeStats->incrementClientCompositionReusedFrames()); } const std::string result(inputCommand(InputCommand::DUMP_ALL, FMT_STRING)); - std::string expected = - "compositionStrategyChanges = " + std::to_string(COMPOSITION_STRATEGY_CHANGED_FRAMES); - EXPECT_THAT(result, HasSubstr(expected)); - - expected = "clientCompositionFrames = " + std::to_string(HAD_CLIENT_COMPOSITION_FRAMES); - EXPECT_THAT(result, HasSubstr(expected)); - - expected = - "clientCompositionReusedFrames = " + std::to_string(REUSED_CLIENT_COMPOSITION_FRAMES); - EXPECT_THAT(result, HasSubstr(expected)); - - expected = "compositionStrategyPredicted = " + - std::to_string(COMPOSITION_STRATEGY_PREDICTED_FRAMES); - EXPECT_THAT(result, HasSubstr(expected)); - - expected = "compositionStrategyPredictionSucceeded = " + - std::to_string(COMPOSITION_STRATEGY_PREDICTION_SUCCEEDED_FRAMES); - EXPECT_THAT(result, HasSubstr(expected)); - - expected = "compositionStrategyPredictionFailed = " + - std::to_string(COMPOSITION_STRATEGY_PREDICTED_FRAMES - - COMPOSITION_STRATEGY_PREDICTION_SUCCEEDED_FRAMES); - EXPECT_THAT(result, HasSubstr(expected)); + const std::string expectedResult = + "clientCompositionReusedFrames = " + std::to_string(CLIENT_COMPOSITION_REUSED_FRAMES); + EXPECT_THAT(result, HasSubstr(expectedResult)); } TEST_F(TimeStatsTest, canIncreaseRefreshRateSwitches) { @@ -522,6 +489,21 @@ TEST_F(TimeStatsTest, canIncreaseRefreshRateSwitches) { EXPECT_THAT(result, HasSubstr(expectedResult)); } +TEST_F(TimeStatsTest, canIncreaseCompositionStrategyChanges) { + // this stat is not in the proto so verify by checking the string dump + constexpr size_t COMPOSITION_STRATEGY_CHANGES = 2; + + EXPECT_TRUE(inputCommand(InputCommand::ENABLE, FMT_STRING).empty()); + for (size_t i = 0; i < COMPOSITION_STRATEGY_CHANGES; i++) { + ASSERT_NO_FATAL_FAILURE(mTimeStats->incrementCompositionStrategyChanges()); + } + + const std::string result(inputCommand(InputCommand::DUMP_ALL, FMT_STRING)); + const std::string expectedResult = + "compositionStrategyChanges = " + std::to_string(COMPOSITION_STRATEGY_CHANGES); + EXPECT_THAT(result, HasSubstr(expectedResult)); +} + TEST_F(TimeStatsTest, canAverageFrameDuration) { EXPECT_TRUE(inputCommand(InputCommand::ENABLE, FMT_STRING).empty()); mTimeStats->setPowerMode(PowerMode::ON); @@ -854,7 +836,7 @@ TEST_F(TimeStatsTest, canClearTimeStats) { ASSERT_NO_FATAL_FAILURE(mTimeStats->incrementTotalFrames()); ASSERT_NO_FATAL_FAILURE(mTimeStats->incrementMissedFrames()); - ASSERT_NO_FATAL_FAILURE(mTimeStats->pushCompositionStrategyState({})); + ASSERT_NO_FATAL_FAILURE(mTimeStats->incrementClientCompositionFrames()); ASSERT_NO_FATAL_FAILURE(mTimeStats->setPowerMode(PowerMode::ON)); mTimeStats->recordFrameDuration(std::chrono::nanoseconds(3ms).count(), @@ -885,8 +867,9 @@ TEST_F(TimeStatsTest, canClearTimeStats) { TEST_F(TimeStatsTest, canClearDumpOnlyTimeStats) { // These stats are not in the proto so verify by checking the string dump. EXPECT_TRUE(inputCommand(InputCommand::ENABLE, FMT_STRING).empty()); - ASSERT_NO_FATAL_FAILURE(mTimeStats->pushCompositionStrategyState({})); + ASSERT_NO_FATAL_FAILURE(mTimeStats->incrementClientCompositionReusedFrames()); ASSERT_NO_FATAL_FAILURE(mTimeStats->incrementRefreshRateSwitches()); + ASSERT_NO_FATAL_FAILURE(mTimeStats->incrementCompositionStrategyChanges()); mTimeStats->setPowerMode(PowerMode::ON); mTimeStats->recordFrameDuration(std::chrono::nanoseconds(1ms).count(), std::chrono::nanoseconds(5ms).count()); @@ -1049,10 +1032,8 @@ TEST_F(TimeStatsTest, globalStatsCallback) { for (size_t i = 0; i < MISSED_FRAMES; i++) { mTimeStats->incrementMissedFrames(); } - TimeStats::ClientCompositionRecord record; - record.hadClientComposition = true; for (size_t i = 0; i < CLIENT_COMPOSITION_FRAMES; i++) { - mTimeStats->pushCompositionStrategyState(record); + mTimeStats->incrementClientCompositionFrames(); } insertTimeRecord(NORMAL_SEQUENCE, LAYER_ID_0, 1, 1000000); diff --git a/services/surfaceflinger/tests/unittests/mock/MockTimeStats.h b/services/surfaceflinger/tests/unittests/mock/MockTimeStats.h index 0dee800558..0a69b562ab 100644 --- a/services/surfaceflinger/tests/unittests/mock/MockTimeStats.h +++ b/services/surfaceflinger/tests/unittests/mock/MockTimeStats.h @@ -33,7 +33,10 @@ public: MOCK_METHOD0(miniDump, std::string()); MOCK_METHOD0(incrementTotalFrames, void()); MOCK_METHOD0(incrementMissedFrames, void()); + MOCK_METHOD0(incrementClientCompositionFrames, void()); + MOCK_METHOD0(incrementClientCompositionReusedFrames, void()); MOCK_METHOD0(incrementRefreshRateSwitches, void()); + MOCK_METHOD0(incrementCompositionStrategyChanges, void()); MOCK_METHOD1(recordDisplayEventConnectionCount, void(int32_t)); MOCK_METHOD2(recordFrameDuration, void(nsecs_t, nsecs_t)); MOCK_METHOD2(recordRenderEngineDuration, void(nsecs_t, nsecs_t)); @@ -60,8 +63,6 @@ public: void(hardware::graphics::composer::V2_4::IComposerClient::PowerMode)); MOCK_METHOD2(recordRefreshRate, void(uint32_t, nsecs_t)); MOCK_METHOD1(setPresentFenceGlobal, void(const std::shared_ptr&)); - MOCK_METHOD(void, pushCompositionStrategyState, - (const android::TimeStats::ClientCompositionRecord&), (override)); }; } // namespace android::mock -- cgit v1.2.3-59-g8ed1b From 4c8e8e3c877662b986f75b6c6a764c9d0d5ff191 Mon Sep 17 00:00:00 2001 From: Robert Carr Date: Wed, 9 Mar 2022 13:49:41 -0800 Subject: Revert "SF: Predict HWC composition strategy" This reverts commit 7234fa59245e20b934a15ebbd27d4e189ad224d0. Change-Id: I908f9c279bb91ce2ee654a05eb8ac8d0057caa47 Bug: 223543469 (cherry picked from commit 6fe2befa82f1f54c07891f33706e1b1d6672f927) Merged-In: I908f9c279bb91ce2ee654a05eb8ac8d0057caa47 --- .../surfaceflinger/CompositionEngine/Android.bp | 5 - .../include/compositionengine/DisplaySurface.h | 3 - .../include/compositionengine/Output.h | 21 +- .../include/compositionengine/RenderSurface.h | 3 - .../include/compositionengine/impl/Display.h | 9 +- .../compositionengine/impl/GpuCompositionResult.h | 38 --- .../compositionengine/impl/HwcAsyncWorker.h | 57 ---- .../include/compositionengine/impl/Output.h | 27 +- .../impl/OutputCompositionState.h | 4 - .../include/compositionengine/impl/RenderSurface.h | 1 - .../include/compositionengine/mock/Display.h | 1 - .../include/compositionengine/mock/Output.h | 17 +- .../include/compositionengine/mock/RenderSurface.h | 1 - .../CompositionEngine/src/Display.cpp | 24 +- .../CompositionEngine/src/DisplaySurface.cpp | 4 - .../CompositionEngine/src/HwcAsyncWorker.cpp | 73 ----- .../CompositionEngine/src/Output.cpp | 207 ++------------ .../CompositionEngine/src/RenderSurface.cpp | 4 - .../CompositionEngine/tests/DisplayTest.cpp | 76 ++--- .../CompositionEngine/tests/OutputTest.cpp | 308 ++------------------- services/surfaceflinger/DisplayDevice.cpp | 1 - .../surfaceflinger/DisplayHardware/HWComposer.h | 8 - .../DisplayHardware/VirtualDisplaySurface.h | 3 - services/surfaceflinger/SurfaceFlinger.cpp | 3 - services/surfaceflinger/SurfaceFlinger.h | 5 - 25 files changed, 106 insertions(+), 797 deletions(-) delete mode 100644 services/surfaceflinger/CompositionEngine/include/compositionengine/impl/GpuCompositionResult.h delete mode 100644 services/surfaceflinger/CompositionEngine/include/compositionengine/impl/HwcAsyncWorker.h delete mode 100644 services/surfaceflinger/CompositionEngine/src/HwcAsyncWorker.cpp diff --git a/services/surfaceflinger/CompositionEngine/Android.bp b/services/surfaceflinger/CompositionEngine/Android.bp index 9302b7bc37..aefc014062 100644 --- a/services/surfaceflinger/CompositionEngine/Android.bp +++ b/services/surfaceflinger/CompositionEngine/Android.bp @@ -41,10 +41,6 @@ cc_defaults { "libtonemap", "libtrace_proto", "libaidlcommonsupport", - "libprocessgroup", - "libcgrouprc", - "libjsoncpp", - "libcgrouprc_format", ], header_libs: [ "android.hardware.graphics.composer@2.1-command-buffer", @@ -72,7 +68,6 @@ cc_library { "src/DisplayColorProfile.cpp", "src/DisplaySurface.cpp", "src/DumpHelpers.cpp", - "src/HwcAsyncWorker.cpp", "src/HwcBufferCache.cpp", "src/LayerFECompositionState.cpp", "src/Output.cpp", diff --git a/services/surfaceflinger/CompositionEngine/include/compositionengine/DisplaySurface.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/DisplaySurface.h index ca86f4c604..c553fce85d 100644 --- a/services/surfaceflinger/CompositionEngine/include/compositionengine/DisplaySurface.h +++ b/services/surfaceflinger/CompositionEngine/include/compositionengine/DisplaySurface.h @@ -72,9 +72,6 @@ public: virtual void resizeBuffers(const ui::Size&) = 0; virtual const sp& getClientTargetAcquireFence() const = 0; - - // Returns true if the render surface supports client composition prediction. - virtual bool supportsCompositionStrategyPrediction() const; }; } // namespace compositionengine diff --git a/services/surfaceflinger/CompositionEngine/include/compositionengine/Output.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/Output.h index 15551029b3..d8644a428d 100644 --- a/services/surfaceflinger/CompositionEngine/include/compositionengine/Output.h +++ b/services/surfaceflinger/CompositionEngine/include/compositionengine/Output.h @@ -35,7 +35,6 @@ #include #include -#include "DisplayHardware/HWComposer.h" namespace android { @@ -55,7 +54,6 @@ struct LayerFECompositionState; namespace impl { struct OutputCompositionState; -struct GpuCompositionResult; } // namespace impl /** @@ -264,9 +262,6 @@ public: // Latches the front-end layer state for each output layer virtual void updateLayerStateFromFE(const CompositionRefreshArgs&) const = 0; - // Enables predicting composition strategy to run client composition earlier - virtual void setPredictCompositionStrategy(bool) = 0; - protected: virtual void setDisplayColorProfile(std::unique_ptr) = 0; virtual void setRenderSurface(std::unique_ptr) = 0; @@ -283,22 +278,13 @@ protected: virtual void updateColorProfile(const CompositionRefreshArgs&) = 0; virtual void beginFrame() = 0; virtual void prepareFrame() = 0; - - using GpuCompositionResult = compositionengine::impl::GpuCompositionResult; - // Runs prepare frame in another thread while running client composition using - // the previous frame's composition strategy. - virtual GpuCompositionResult prepareFrameAsync(const CompositionRefreshArgs&) = 0; virtual void devOptRepaintFlash(const CompositionRefreshArgs&) = 0; - virtual void finishFrame(const CompositionRefreshArgs&, GpuCompositionResult&&) = 0; + virtual void finishFrame(const CompositionRefreshArgs&) = 0; virtual std::optional composeSurfaces( - const Region&, const compositionengine::CompositionRefreshArgs&, - std::shared_ptr, base::unique_fd&) = 0; + const Region&, const compositionengine::CompositionRefreshArgs& refreshArgs) = 0; virtual void postFramebuffer() = 0; virtual void renderCachedSets(const CompositionRefreshArgs&) = 0; - virtual std::optional - chooseCompositionStrategy() = 0; - virtual void applyCompositionStrategy( - const std::optional& changes) = 0; + virtual void chooseCompositionStrategy() = 0; virtual bool getSkipColorTransform() const = 0; virtual FrameFences presentAndGetFrameFences() = 0; virtual std::vector generateClientCompositionRequests( @@ -309,7 +295,6 @@ protected: std::vector& clientCompositionLayers) = 0; virtual void setExpensiveRenderingExpected(bool enabled) = 0; virtual void cacheClientCompositionRequests(uint32_t cacheSize) = 0; - virtual bool canPredictCompositionStrategy(const CompositionRefreshArgs&) = 0; }; } // namespace compositionengine diff --git a/services/surfaceflinger/CompositionEngine/include/compositionengine/RenderSurface.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/RenderSurface.h index 9ee779cca1..daee83bd2c 100644 --- a/services/surfaceflinger/CompositionEngine/include/compositionengine/RenderSurface.h +++ b/services/surfaceflinger/CompositionEngine/include/compositionengine/RenderSurface.h @@ -100,9 +100,6 @@ public: // Debugging - gets the page flip count for the RenderSurface virtual std::uint32_t getPageFlipCount() const = 0; - - // Returns true if the render surface supports client composition prediction. - virtual bool supportsCompositionStrategyPrediction() const = 0; }; } // namespace compositionengine diff --git a/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/Display.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/Display.h index 3b8b06fc2f..58d2530877 100644 --- a/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/Display.h +++ b/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/Display.h @@ -22,7 +22,6 @@ #include #include #include -#include #include #include #include @@ -52,14 +51,11 @@ public: void setReleasedLayers(const CompositionRefreshArgs&) override; void setColorTransform(const CompositionRefreshArgs&) override; void setColorProfile(const ColorProfile&) override; - - using DeviceRequestedChanges = android::HWComposer::DeviceRequestedChanges; - std::optional chooseCompositionStrategy() override; - void applyCompositionStrategy(const std::optional&) override; + void chooseCompositionStrategy() override; bool getSkipColorTransform() const override; compositionengine::Output::FrameFences presentAndGetFrameFences() override; void setExpensiveRenderingExpected(bool) override; - void finishFrame(const CompositionRefreshArgs&, GpuCompositionResult&&) override; + void finishFrame(const CompositionRefreshArgs&) override; // compositionengine::Display overrides DisplayId getId() const override; @@ -77,6 +73,7 @@ public: using DisplayRequests = android::HWComposer::DeviceRequestedChanges::DisplayRequests; using LayerRequests = android::HWComposer::DeviceRequestedChanges::LayerRequests; using ClientTargetProperty = android::HWComposer::DeviceRequestedChanges::ClientTargetProperty; + virtual bool anyLayersRequireClientComposition() const; virtual bool allLayersRequireClientComposition() const; virtual void applyChangedTypesToLayers(const ChangedTypes&); virtual void applyDisplayRequests(const DisplayRequests&); diff --git a/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/GpuCompositionResult.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/GpuCompositionResult.h deleted file mode 100644 index ed1ddc172c..0000000000 --- a/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/GpuCompositionResult.h +++ /dev/null @@ -1,38 +0,0 @@ -/* - * Copyright 2022 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 - -namespace android::compositionengine::impl { - -struct GpuCompositionResult { - // True if composition strategy was predicted successfully. - bool succeeded = false; - - // Composition ready fence. - base::unique_fd fence{}; - - // Buffer to be used for gpu composition. If gpu composition was not successful, - // then we want to reuse the buffer instead of dequeuing another buffer. - std::shared_ptr buffer = nullptr; - - bool bufferAvailable() const { return buffer != nullptr; }; -}; - -} // namespace android::compositionengine::impl diff --git a/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/HwcAsyncWorker.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/HwcAsyncWorker.h deleted file mode 100644 index 11c0054089..0000000000 --- a/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/HwcAsyncWorker.h +++ /dev/null @@ -1,57 +0,0 @@ -/* - * Copyright 2022 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 "DisplayHardware/HWComposer.h" - -namespace android::compositionengine::impl { - -// HWC Validate call may take multiple milliseconds to complete and can account for -// a signification amount of time in the display hotpath. This helper class allows -// us to run the hwc validate function on a real time thread if we can predict what -// the composition strategy will be and if composition includes client composition. -// While the hwc validate runs, client composition is kicked off with the prediction. -// When the worker returns with a value, the composition continues if the prediction -// was successful otherwise the client composition is re-executed. -// -// Note: This does not alter the sequence between HWC and surfaceflinger. -class HwcAsyncWorker final { -public: - HwcAsyncWorker(); - ~HwcAsyncWorker(); - // Runs the provided function which calls hwc validate and returns the requested - // device changes as a future. - std::future> send( - std::function()>); - -private: - std::mutex mMutex; - std::condition_variable mCv GUARDED_BY(mMutex); - bool mDone GUARDED_BY(mMutex) = false; - bool mTaskRequested GUARDED_BY(mMutex) = false; - std::packaged_task()> mTask - GUARDED_BY(mMutex); - std::thread mThread; - void run(); -}; - -} // namespace android::compositionengine::impl diff --git a/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/Output.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/Output.h index 0be5d018f6..a7a8e97be5 100644 --- a/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/Output.h +++ b/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/Output.h @@ -17,13 +17,9 @@ #pragma once #include -#include #include #include -#include -#include #include -#include #include #include #include @@ -96,38 +92,25 @@ public: void updateColorProfile(const compositionengine::CompositionRefreshArgs&) override; void beginFrame() override; void prepareFrame() override; - GpuCompositionResult prepareFrameAsync(const CompositionRefreshArgs&) override; void devOptRepaintFlash(const CompositionRefreshArgs&) override; - void finishFrame(const CompositionRefreshArgs&, GpuCompositionResult&&) override; - std::optional composeSurfaces(const Region&, - const compositionengine::CompositionRefreshArgs&, - std::shared_ptr, - base::unique_fd&) override; + void finishFrame(const CompositionRefreshArgs&) override; + std::optional composeSurfaces( + const Region&, const compositionengine::CompositionRefreshArgs& refreshArgs) override; void postFramebuffer() override; void renderCachedSets(const CompositionRefreshArgs&) override; void cacheClientCompositionRequests(uint32_t) override; - bool canPredictCompositionStrategy(const CompositionRefreshArgs&) override; - void setPredictCompositionStrategy(bool) override; // Testing const ReleasedLayers& getReleasedLayersForTest() const; void setDisplayColorProfileForTest(std::unique_ptr); void setRenderSurfaceForTest(std::unique_ptr); bool plannerEnabled() const { return mPlanner != nullptr; } - virtual bool anyLayersRequireClientComposition() const; - virtual void updateProtectedContentState(); - virtual bool dequeueRenderBuffer(base::unique_fd*, - std::shared_ptr*); - virtual std::future> - chooseCompositionStrategyAsync(); protected: std::unique_ptr createOutputLayer(const sp&) const; std::optional findCurrentOutputLayerForLayer( const sp&) const; - using DeviceRequestedChanges = android::HWComposer::DeviceRequestedChanges; - std::optional chooseCompositionStrategy() override; - void applyCompositionStrategy(const std::optional&) override{}; + void chooseCompositionStrategy() override; bool getSkipColorTransform() const override; compositionengine::Output::FrameFences presentAndGetFrameFences() override; std::vector generateClientCompositionRequests( @@ -148,7 +131,6 @@ protected: private: void dirtyEntireOutput(); compositionengine::OutputLayer* findLayerRequestingBackgroundComposition() const; - void finishPrepareFrame(); ui::Dataspace getBestDataspace(ui::Dataspace*, bool*) const; compositionengine::Output::ColorProfile pickColorProfile( const compositionengine::CompositionRefreshArgs&) const; @@ -162,7 +144,6 @@ private: OutputLayer* mLayerRequestingBackgroundBlur = nullptr; std::unique_ptr mClientCompositionRequestCache; std::unique_ptr mPlanner; - std::unique_ptr mHwComposerAsyncWorker; }; // This template factory function standardizes the implementation details of the diff --git a/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/OutputCompositionState.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/OutputCompositionState.h index 92f22b6a16..66dd825e5b 100644 --- a/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/OutputCompositionState.h +++ b/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/OutputCompositionState.h @@ -37,8 +37,6 @@ #include #include -#include "DisplayHardware/HWComposer.h" - namespace android { namespace compositionengine::impl { @@ -116,8 +114,6 @@ struct OutputCompositionState { // Current target dataspace ui::Dataspace targetDataspace{ui::Dataspace::UNKNOWN}; - std::optional previousDeviceRequestedChanges{}; - // The earliest time to send the present command to the HAL std::chrono::steady_clock::time_point earliestPresentTime; diff --git a/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/RenderSurface.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/RenderSurface.h index e4cb113645..a8a538003e 100644 --- a/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/RenderSurface.h +++ b/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/RenderSurface.h @@ -63,7 +63,6 @@ public: void queueBuffer(base::unique_fd readyFence) override; void onPresentDisplayCompleted() override; void flip() override; - bool supportsCompositionStrategyPrediction() const override; // Debugging void dump(std::string& result) const override; diff --git a/services/surfaceflinger/CompositionEngine/include/compositionengine/mock/Display.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/mock/Display.h index 72e6f3bdbb..d90cc909ba 100644 --- a/services/surfaceflinger/CompositionEngine/include/compositionengine/mock/Display.h +++ b/services/surfaceflinger/CompositionEngine/include/compositionengine/mock/Display.h @@ -41,7 +41,6 @@ public: MOCK_METHOD1(createDisplayColorProfile, void(const DisplayColorProfileCreationArgs&)); MOCK_METHOD1(createRenderSurface, void(const RenderSurfaceCreationArgs&)); MOCK_METHOD1(createClientCompositionCache, void(uint32_t)); - MOCK_METHOD1(setPredictCompositionStrategy, void(bool)); }; } // namespace android::compositionengine::mock diff --git a/services/surfaceflinger/CompositionEngine/include/compositionengine/mock/Output.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/mock/Output.h index 27303a82be..b68b95d07b 100644 --- a/services/surfaceflinger/CompositionEngine/include/compositionengine/mock/Output.h +++ b/services/surfaceflinger/CompositionEngine/include/compositionengine/mock/Output.h @@ -22,7 +22,6 @@ #include #include #include -#include #include #include @@ -100,22 +99,16 @@ public: MOCK_METHOD0(beginFrame, void()); MOCK_METHOD0(prepareFrame, void()); - MOCK_METHOD1(prepareFrameAsync, GpuCompositionResult(const CompositionRefreshArgs&)); - MOCK_METHOD0(chooseCompositionStrategy, - std::optional()); - MOCK_METHOD1(applyCompositionStrategy, - void(const std::optional&)); + MOCK_METHOD0(chooseCompositionStrategy, void()); MOCK_METHOD1(devOptRepaintFlash, void(const compositionengine::CompositionRefreshArgs&)); - MOCK_METHOD2(finishFrame, - void(const compositionengine::CompositionRefreshArgs&, GpuCompositionResult&&)); + MOCK_METHOD1(finishFrame, void(const compositionengine::CompositionRefreshArgs&)); - MOCK_METHOD4(composeSurfaces, + MOCK_METHOD2(composeSurfaces, std::optional( const Region&, - const compositionengine::CompositionRefreshArgs& refreshArgs, - std::shared_ptr, base::unique_fd&)); + const compositionengine::CompositionRefreshArgs& refreshArgs)); MOCK_CONST_METHOD0(getSkipColorTransform, bool()); MOCK_METHOD0(postFramebuffer, void()); @@ -128,8 +121,6 @@ public: void(const Region&, std::vector&)); MOCK_METHOD1(setExpensiveRenderingExpected, void(bool)); MOCK_METHOD1(cacheClientCompositionRequests, void(uint32_t)); - MOCK_METHOD1(canPredictCompositionStrategy, bool(const CompositionRefreshArgs&)); - MOCK_METHOD1(setPredictCompositionStrategy, void(bool)); }; } // namespace android::compositionengine::mock diff --git a/services/surfaceflinger/CompositionEngine/include/compositionengine/mock/RenderSurface.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/mock/RenderSurface.h index e12aebb50c..fe858c2817 100644 --- a/services/surfaceflinger/CompositionEngine/include/compositionengine/mock/RenderSurface.h +++ b/services/surfaceflinger/CompositionEngine/include/compositionengine/mock/RenderSurface.h @@ -45,7 +45,6 @@ public: MOCK_METHOD0(flip, void()); MOCK_CONST_METHOD1(dump, void(std::string& result)); MOCK_CONST_METHOD0(getPageFlipCount, std::uint32_t()); - MOCK_CONST_METHOD0(supportsCompositionStrategyPrediction, bool()); }; } // namespace android::compositionengine::mock diff --git a/services/surfaceflinger/CompositionEngine/src/Display.cpp b/services/surfaceflinger/CompositionEngine/src/Display.cpp index 09648c356d..6a75283f7b 100644 --- a/services/surfaceflinger/CompositionEngine/src/Display.cpp +++ b/services/surfaceflinger/CompositionEngine/src/Display.cpp @@ -221,12 +221,12 @@ void Display::setReleasedLayers(const compositionengine::CompositionRefreshArgs& setReleasedLayers(std::move(releasedLayers)); } -std::optional Display::chooseCompositionStrategy() { +void Display::chooseCompositionStrategy() { ATRACE_CALL(); ALOGV(__FUNCTION__); if (mIsDisconnected) { - return {}; + return; } // Default to the base settings -- client composition only. @@ -235,7 +235,7 @@ std::optional Display::chooseCompos // If we don't have a HWC display, then we are done. const auto halDisplayId = HalDisplayId::tryCast(mId); if (!halDisplayId) { - return {}; + return; } // Get any composition changes requested by the HWC device, and apply them. @@ -260,13 +260,8 @@ std::optional Display::chooseCompos result != NO_ERROR) { ALOGE("chooseCompositionStrategy failed for %s: %d (%s)", getName().c_str(), result, strerror(-result)); - return {}; + return; } - - return changes; -} - -void Display::applyCompositionStrategy(const std::optional& changes) { if (changes) { applyChangedTypesToLayers(changes->changedTypes); applyDisplayRequests(changes->displayRequests); @@ -292,6 +287,12 @@ bool Display::getSkipColorTransform() const { return hwc.hasCapability(Capability::SKIP_CLIENT_COLOR_TRANSFORM); } +bool Display::anyLayersRequireClientComposition() const { + const auto layers = getOutputLayersOrderedByZ(); + return std::any_of(layers.begin(), layers.end(), + [](const auto& layer) { return layer->requiresClientComposition(); }); +} + bool Display::allLayersRequireClientComposition() const { const auto layers = getOutputLayersOrderedByZ(); return std::all_of(layers.begin(), layers.end(), @@ -389,8 +390,7 @@ void Display::setExpensiveRenderingExpected(bool enabled) { } } -void Display::finishFrame(const compositionengine::CompositionRefreshArgs& refreshArgs, - GpuCompositionResult&& result) { +void Display::finishFrame(const compositionengine::CompositionRefreshArgs& refreshArgs) { // We only need to actually compose the display if: // 1) It is being handled by hardware composer, which may need this to // keep its virtual display state machine in sync, or @@ -400,7 +400,7 @@ void Display::finishFrame(const compositionengine::CompositionRefreshArgs& refre return; } - impl::Output::finishFrame(refreshArgs, std::move(result)); + impl::Output::finishFrame(refreshArgs); } } // namespace android::compositionengine::impl diff --git a/services/surfaceflinger/CompositionEngine/src/DisplaySurface.cpp b/services/surfaceflinger/CompositionEngine/src/DisplaySurface.cpp index 28900af162..db6d4f2fed 100644 --- a/services/surfaceflinger/CompositionEngine/src/DisplaySurface.cpp +++ b/services/surfaceflinger/CompositionEngine/src/DisplaySurface.cpp @@ -20,8 +20,4 @@ namespace android::compositionengine { DisplaySurface::~DisplaySurface() = default; -bool DisplaySurface::supportsCompositionStrategyPrediction() const { - return true; -} - } // namespace android::compositionengine diff --git a/services/surfaceflinger/CompositionEngine/src/HwcAsyncWorker.cpp b/services/surfaceflinger/CompositionEngine/src/HwcAsyncWorker.cpp deleted file mode 100644 index 497424a327..0000000000 --- a/services/surfaceflinger/CompositionEngine/src/HwcAsyncWorker.cpp +++ /dev/null @@ -1,73 +0,0 @@ -/* - * Copyright 2022 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 -#include -#include -#include -#include - -#include -#include - -namespace android::compositionengine::impl { - -HwcAsyncWorker::HwcAsyncWorker() { - mThread = std::thread(&HwcAsyncWorker::run, this); - pthread_setname_np(mThread.native_handle(), "HwcAsyncWorker"); -} - -HwcAsyncWorker::~HwcAsyncWorker() { - { - std::scoped_lock lock(mMutex); - mDone = true; - mCv.notify_all(); - } - if (mThread.joinable()) { - mThread.join(); - } -} -std::future> HwcAsyncWorker::send( - std::function()> task) { - std::unique_lock lock(mMutex); - android::base::ScopedLockAssertion assumeLock(mMutex); - mTask = std::packaged_task()>( - [task = std::move(task)]() { return task(); }); - mTaskRequested = true; - mCv.notify_one(); - return mTask.get_future(); -} - -void HwcAsyncWorker::run() { - set_sched_policy(0, SP_FOREGROUND); - struct sched_param param = {0}; - param.sched_priority = 2; - sched_setscheduler(gettid(), SCHED_FIFO, ¶m); - - std::unique_lock lock(mMutex); - android::base::ScopedLockAssertion assumeLock(mMutex); - while (!mDone) { - mCv.wait(lock); - if (mTaskRequested && mTask.valid()) { - mTask(); - mTaskRequested = false; - } - } -} - -} // namespace android::compositionengine::impl diff --git a/services/surfaceflinger/CompositionEngine/src/Output.cpp b/services/surfaceflinger/CompositionEngine/src/Output.cpp index cd10bc10b5..aef55d49fe 100644 --- a/services/surfaceflinger/CompositionEngine/src/Output.cpp +++ b/services/surfaceflinger/CompositionEngine/src/Output.cpp @@ -22,7 +22,6 @@ #include #include #include -#include #include #include #include @@ -435,17 +434,9 @@ void Output::present(const compositionengine::CompositionRefreshArgs& refreshArg writeCompositionState(refreshArgs); setColorTransform(refreshArgs); beginFrame(); - - GpuCompositionResult result; - const bool predictCompositionStrategy = canPredictCompositionStrategy(refreshArgs); - if (predictCompositionStrategy) { - result = prepareFrameAsync(refreshArgs); - } else { - prepareFrame(); - } - + prepareFrame(); devOptRepaintFlash(refreshArgs); - finishFrame(refreshArgs, std::move(result)); + finishFrame(refreshArgs); postFramebuffer(); renderCachedSets(refreshArgs); } @@ -960,62 +951,19 @@ void Output::prepareFrame() { ATRACE_CALL(); ALOGV(__FUNCTION__); - auto& outputState = editState(); + const auto& outputState = getState(); if (!outputState.isEnabled) { return; } - auto changes = chooseCompositionStrategy(); - outputState.previousDeviceRequestedChanges = changes; - if (changes) { - applyCompositionStrategy(changes); - } - finishPrepareFrame(); -} + chooseCompositionStrategy(); -std::future> -Output::chooseCompositionStrategyAsync() { - return mHwComposerAsyncWorker->send([&]() { return chooseCompositionStrategy(); }); -} - -GpuCompositionResult Output::prepareFrameAsync(const CompositionRefreshArgs& refreshArgs) { - ATRACE_CALL(); - ALOGV(__FUNCTION__); - auto& state = editState(); - const auto& previousChanges = state.previousDeviceRequestedChanges; - auto hwcResult = chooseCompositionStrategyAsync(); - applyCompositionStrategy(previousChanges); - finishPrepareFrame(); - - base::unique_fd bufferFence; - std::shared_ptr buffer; - updateProtectedContentState(); - const bool dequeueSucceeded = dequeueRenderBuffer(&bufferFence, &buffer); - GpuCompositionResult compositionResult; - if (dequeueSucceeded) { - std::optional optFd = - composeSurfaces(Region::INVALID_REGION, refreshArgs, buffer, bufferFence); - if (optFd) { - compositionResult.fence = std::move(*optFd); - } + if (mPlanner) { + mPlanner->reportFinalPlan(getOutputLayersOrderedByZ()); } - auto changes = hwcResult.valid() ? hwcResult.get() : std::nullopt; - const bool predictionSucceeded = dequeueSucceeded && changes == previousChanges; - compositionResult.succeeded = predictionSucceeded; - if (!predictionSucceeded) { - ATRACE_NAME("CompositionStrategyPredictionMiss"); - if (changes) { - applyCompositionStrategy(changes); - } - finishPrepareFrame(); - // Track the dequeued buffer to reuse so we don't need to dequeue another one. - compositionResult.buffer = buffer; - } else { - ATRACE_NAME("CompositionStrategyPredictionHit"); - } - state.previousDeviceRequestedChanges = std::move(changes); - return compositionResult; + mRenderSurface->prepareFrame(outputState.usesClientComposition, + outputState.usesDeviceComposition); } void Output::devOptRepaintFlash(const compositionengine::CompositionRefreshArgs& refreshArgs) { @@ -1025,11 +973,7 @@ void Output::devOptRepaintFlash(const compositionengine::CompositionRefreshArgs& if (getState().isEnabled) { if (const auto dirtyRegion = getDirtyRegion(); !dirtyRegion.isEmpty()) { - base::unique_fd bufferFence; - std::shared_ptr buffer; - updateProtectedContentState(); - dequeueRenderBuffer(&bufferFence, &buffer); - static_cast(composeSurfaces(dirtyRegion, refreshArgs, buffer, bufferFence)); + static_cast(composeSurfaces(dirtyRegion, refreshArgs)); mRenderSurface->queueBuffer(base::unique_fd()); } } @@ -1041,7 +985,7 @@ void Output::devOptRepaintFlash(const compositionengine::CompositionRefreshArgs& prepareFrame(); } -void Output::finishFrame(const CompositionRefreshArgs& refreshArgs, GpuCompositionResult&& result) { +void Output::finishFrame(const compositionengine::CompositionRefreshArgs& refreshArgs) { ATRACE_CALL(); ALOGV(__FUNCTION__); @@ -1049,25 +993,9 @@ void Output::finishFrame(const CompositionRefreshArgs& refreshArgs, GpuCompositi return; } - std::optional optReadyFence; - std::shared_ptr buffer; - base::unique_fd bufferFence; - if (result.succeeded) { - optReadyFence = std::move(result.fence); - } else { - if (result.bufferAvailable()) { - buffer = std::move(result.buffer); - bufferFence = std::move(result.fence); - } else { - updateProtectedContentState(); - if (!dequeueRenderBuffer(&bufferFence, &buffer)) { - return; - } - } - // Repaint the framebuffer (if needed), getting the optional fence for when - // the composition completes. - optReadyFence = composeSurfaces(Region::INVALID_REGION, refreshArgs, buffer, bufferFence); - } + // Repaint the framebuffer (if needed), getting the optional fence for when + // the composition completes. + auto optReadyFence = composeSurfaces(Region::INVALID_REGION, refreshArgs); if (!optReadyFence) { return; } @@ -1076,8 +1004,16 @@ void Output::finishFrame(const CompositionRefreshArgs& refreshArgs, GpuCompositi mRenderSurface->queueBuffer(std::move(*optReadyFence)); } -void Output::updateProtectedContentState() { +std::optional Output::composeSurfaces( + const Region& debugRegion, const compositionengine::CompositionRefreshArgs& refreshArgs) { + ATRACE_CALL(); + ALOGV(__FUNCTION__); + const auto& outputState = getState(); + OutputCompositionState& outputCompositionState = editState(); + const TracedOrdinal hasClientComposition = {"hasClientComposition", + outputState.usesClientComposition}; + auto& renderEngine = getCompositionEngine().getRenderEngine(); const bool supportsProtectedContent = renderEngine.supportsProtectedContent(); @@ -1099,48 +1035,29 @@ void Output::updateProtectedContentState() { } else if (!outputState.isSecure && renderEngine.isProtected()) { renderEngine.useProtectedContext(false); } -} -bool Output::dequeueRenderBuffer(base::unique_fd* bufferFence, - std::shared_ptr* tex) { - const auto& outputState = getState(); + base::unique_fd fd; + + std::shared_ptr tex; // If we aren't doing client composition on this output, but do have a // flipClientTarget request for this frame on this output, we still need to // dequeue a buffer. - if (outputState.usesClientComposition || outputState.flipClientTarget) { - *tex = mRenderSurface->dequeueBuffer(bufferFence); - if (*tex == nullptr) { + if (hasClientComposition || outputState.flipClientTarget) { + tex = mRenderSurface->dequeueBuffer(&fd); + if (tex == nullptr) { ALOGW("Dequeuing buffer for display [%s] failed, bailing out of " "client composition for this frame", mName.c_str()); - return false; + return {}; } } - return true; -} -std::optional Output::composeSurfaces( - const Region& debugRegion, const compositionengine::CompositionRefreshArgs& refreshArgs, - std::shared_ptr tex, base::unique_fd& fd) { - ATRACE_CALL(); - ALOGV(__FUNCTION__); - - const auto& outputState = getState(); - const TracedOrdinal hasClientComposition = {"hasClientComposition", - outputState.usesClientComposition}; if (!hasClientComposition) { setExpensiveRenderingExpected(false); return base::unique_fd(); } - if (tex == nullptr) { - ALOGW("Buffer not valid for display [%s], bailing out of " - "client composition for this frame", - mName.c_str()); - return {}; - } - ALOGV("hasClientComposition"); renderengine::DisplaySettings clientCompositionDisplay; @@ -1168,8 +1085,6 @@ std::optional Output::composeSurfaces( outputState.usesDeviceComposition || getSkipColorTransform(); // Generate the client composition requests for the layers on this output. - auto& renderEngine = getCompositionEngine().getRenderEngine(); - const bool supportsProtectedContent = renderEngine.supportsProtectedContent(); std::vector clientCompositionLayersFE; std::vector clientCompositionLayers = generateClientCompositionRequests(supportsProtectedContent, @@ -1177,19 +1092,16 @@ std::optional Output::composeSurfaces( clientCompositionLayersFE); appendRegionFlashRequests(debugRegion, clientCompositionLayers); - OutputCompositionState& outputCompositionState = editState(); // Check if the client composition requests were rendered into the provided graphic buffer. If // so, we can reuse the buffer and avoid client composition. if (mClientCompositionRequestCache) { if (mClientCompositionRequestCache->exists(tex->getBuffer()->getId(), clientCompositionDisplay, clientCompositionLayers)) { - ATRACE_NAME("ClientCompositionCacheHit"); outputCompositionState.reusedClientComposition = true; setExpensiveRenderingExpected(false); return base::unique_fd(); } - ATRACE_NAME("ClientCompositionCacheMiss"); mClientCompositionRequestCache->add(tex->getBuffer()->getId(), clientCompositionDisplay, clientCompositionLayers); } @@ -1441,13 +1353,12 @@ void Output::dirtyEntireOutput() { outputState.dirtyRegion.set(outputState.displaySpace.getBoundsAsRect()); } -std::optional Output::chooseCompositionStrategy() { +void Output::chooseCompositionStrategy() { // The base output implementation can only do client composition auto& outputState = editState(); outputState.usesClientComposition = true; outputState.usesDeviceComposition = false; outputState.reusedClientComposition = false; - return {}; } bool Output::getSkipColorTransform() const { @@ -1462,63 +1373,5 @@ compositionengine::Output::FrameFences Output::presentAndGetFrameFences() { return result; } -void Output::setPredictCompositionStrategy(bool predict) { - if (predict) { - mHwComposerAsyncWorker = std::make_unique(); - } else { - mHwComposerAsyncWorker.reset(nullptr); - } -} - -bool Output::canPredictCompositionStrategy(const CompositionRefreshArgs& refreshArgs) { - if (!getState().isEnabled || !mHwComposerAsyncWorker) { - ALOGV("canPredictCompositionStrategy disabled"); - return false; - } - - if (!getState().previousDeviceRequestedChanges) { - ALOGV("canPredictCompositionStrategy previous changes not available"); - return false; - } - - if (!mRenderSurface->supportsCompositionStrategyPrediction()) { - ALOGV("canPredictCompositionStrategy surface does not support"); - return false; - } - - if (refreshArgs.devOptFlashDirtyRegionsDelay) { - ALOGV("canPredictCompositionStrategy devOptFlashDirtyRegionsDelay"); - return false; - } - - // If no layer uses clientComposition, then don't predict composition strategy - // because we have less work to do in parallel. - if (!anyLayersRequireClientComposition()) { - ALOGV("canPredictCompositionStrategy no layer uses clientComposition"); - return false; - } - - if (!refreshArgs.updatingOutputGeometryThisFrame) { - return true; - } - - ALOGV("canPredictCompositionStrategy updatingOutputGeometryThisFrame"); - return false; -} - -bool Output::anyLayersRequireClientComposition() const { - const auto layers = getOutputLayersOrderedByZ(); - return std::any_of(layers.begin(), layers.end(), - [](const auto& layer) { return layer->requiresClientComposition(); }); -} - -void Output::finishPrepareFrame() { - const auto& state = getState(); - if (mPlanner) { - mPlanner->reportFinalPlan(getOutputLayersOrderedByZ()); - } - mRenderSurface->prepareFrame(state.usesClientComposition, state.usesDeviceComposition); -} - } // namespace impl } // namespace android::compositionengine diff --git a/services/surfaceflinger/CompositionEngine/src/RenderSurface.cpp b/services/surfaceflinger/CompositionEngine/src/RenderSurface.cpp index 5a3af7bfea..12c2c8eb38 100644 --- a/services/surfaceflinger/CompositionEngine/src/RenderSurface.cpp +++ b/services/surfaceflinger/CompositionEngine/src/RenderSurface.cpp @@ -289,9 +289,5 @@ std::shared_ptr& RenderSurface::mutableTextureFor return mTexture; } -bool RenderSurface::supportsCompositionStrategyPrediction() const { - return mDisplaySurface->supportsCompositionStrategyPrediction(); -} - } // namespace impl } // namespace android::compositionengine diff --git a/services/surfaceflinger/CompositionEngine/tests/DisplayTest.cpp b/services/surfaceflinger/CompositionEngine/tests/DisplayTest.cpp index 36b04d909f..cd0323555c 100644 --- a/services/surfaceflinger/CompositionEngine/tests/DisplayTest.cpp +++ b/services/surfaceflinger/CompositionEngine/tests/DisplayTest.cpp @@ -30,9 +30,7 @@ #include #include #include -#include #include - #include #include @@ -200,22 +198,6 @@ struct PartialMockDisplayTestCommon : public DisplayTestCommon { std::shared_ptr mDisplay = createPartialMockDisplay(mCompositionEngine, getDisplayCreationArgsForPhysicalDisplay()); - - android::HWComposer::DeviceRequestedChanges mDeviceRequestedChanges{ - {{nullptr, Composition::CLIENT}}, - hal::DisplayRequest::FLIP_CLIENT_TARGET, - {{nullptr, hal::LayerRequest::CLEAR_CLIENT_TARGET}}, - {hal::PixelFormat::RGBA_8888, hal::Dataspace::UNKNOWN}, - -1.f, - }; - - void chooseCompositionStrategy(Display* display) { - std::optional changes = - display->chooseCompositionStrategy(); - if (changes) { - display->applyCompositionStrategy(changes); - } - } }; struct FullDisplayImplTestCommon : public DisplayTestCommon { @@ -232,11 +214,6 @@ struct DisplayWithLayersTestCommon : public FullDisplayImplTestCommon { std::unique_ptr(mLayer2.outputLayer)); mDisplay->injectOutputLayerForTest( std::unique_ptr(mLayer3.outputLayer)); - mResultWithBuffer.buffer = std::make_shared< - renderengine::mock::FakeExternalTexture>(1U /*width*/, 1U /*height*/, - 1ULL /* bufferId */, - HAL_PIXEL_FORMAT_RGBA_8888, - 0ULL /*usage*/); } Layer mLayer1; @@ -245,8 +222,6 @@ struct DisplayWithLayersTestCommon : public FullDisplayImplTestCommon { StrictMock hwc2LayerUnknown; std::shared_ptr mDisplay = createDisplay(mCompositionEngine, getDisplayCreationArgsForPhysicalDisplay()); - impl::GpuCompositionResult mResultWithBuffer; - impl::GpuCompositionResult mResultWithoutBuffer; }; /* @@ -579,7 +554,7 @@ TEST_F(DisplayChooseCompositionStrategyTest, takesEarlyOutIfGpuDisplay) { createPartialMockDisplay(mCompositionEngine, args); EXPECT_TRUE(GpuVirtualDisplayId::tryCast(gpuDisplay->getId())); - chooseCompositionStrategy(gpuDisplay.get()); + gpuDisplay->chooseCompositionStrategy(); auto& state = gpuDisplay->getState(); EXPECT_TRUE(state.usesClientComposition); @@ -592,12 +567,11 @@ TEST_F(DisplayChooseCompositionStrategyTest, takesEarlyOutOnHwcError) { getDeviceCompositionChanges(HalDisplayId(DEFAULT_DISPLAY_ID), false, _, _, _, _)) .WillOnce(Return(INVALID_OPERATION)); - chooseCompositionStrategy(mDisplay.get()); + mDisplay->chooseCompositionStrategy(); auto& state = mDisplay->getState(); EXPECT_TRUE(state.usesClientComposition); EXPECT_FALSE(state.usesDeviceComposition); - EXPECT_FALSE(state.previousDeviceRequestedChanges.has_value()); } TEST_F(DisplayChooseCompositionStrategyTest, normalOperation) { @@ -614,16 +588,10 @@ TEST_F(DisplayChooseCompositionStrategyTest, normalOperation) { EXPECT_CALL(mHwComposer, getDeviceCompositionChanges(HalDisplayId(DEFAULT_DISPLAY_ID), true, _, _, _, _)) - .WillOnce(testing::DoAll(testing::SetArgPointee<5>(mDeviceRequestedChanges), - Return(NO_ERROR))); - EXPECT_CALL(*mDisplay, applyChangedTypesToLayers(mDeviceRequestedChanges.changedTypes)) - .Times(1); - EXPECT_CALL(*mDisplay, applyDisplayRequests(mDeviceRequestedChanges.displayRequests)).Times(1); - EXPECT_CALL(*mDisplay, applyLayerRequestsToLayers(mDeviceRequestedChanges.layerRequests)) - .Times(1); + .WillOnce(Return(NO_ERROR)); EXPECT_CALL(*mDisplay, allLayersRequireClientComposition()).WillOnce(Return(false)); - chooseCompositionStrategy(mDisplay.get()); + mDisplay->chooseCompositionStrategy(); auto& state = mDisplay->getState(); EXPECT_FALSE(state.usesClientComposition); @@ -650,17 +618,11 @@ TEST_F(DisplayChooseCompositionStrategyTest, normalOperationWithDisplayBrightnes EXPECT_CALL(mHwComposer, getDeviceCompositionChanges(HalDisplayId(DEFAULT_DISPLAY_ID), true, _, _, _, _)) - .WillOnce(testing::DoAll(testing::SetArgPointee<5>(mDeviceRequestedChanges), - Return(NO_ERROR))); - EXPECT_CALL(*mDisplay, applyChangedTypesToLayers(mDeviceRequestedChanges.changedTypes)) - .Times(1); - EXPECT_CALL(*mDisplay, applyDisplayRequests(mDeviceRequestedChanges.displayRequests)).Times(1); - EXPECT_CALL(*mDisplay, applyLayerRequestsToLayers(mDeviceRequestedChanges.layerRequests)) - .Times(1); + .WillOnce(Return(NO_ERROR)); EXPECT_CALL(*mDisplay, allLayersRequireClientComposition()).WillOnce(Return(false)); mDisplay->setNextBrightness(kDisplayBrightness); - chooseCompositionStrategy(mDisplay.get()); + mDisplay->chooseCompositionStrategy(); auto& state = mDisplay->getState(); EXPECT_FALSE(state.usesClientComposition); @@ -669,6 +631,14 @@ TEST_F(DisplayChooseCompositionStrategyTest, normalOperationWithDisplayBrightnes } TEST_F(DisplayChooseCompositionStrategyTest, normalOperationWithChanges) { + android::HWComposer::DeviceRequestedChanges changes{ + {{nullptr, Composition::CLIENT}}, + hal::DisplayRequest::FLIP_CLIENT_TARGET, + {{nullptr, hal::LayerRequest::CLEAR_CLIENT_TARGET}}, + {hal::PixelFormat::RGBA_8888, hal::Dataspace::UNKNOWN}, + -1.f, + }; + // Since two calls are made to anyLayersRequireClientComposition with different return // values, use a Sequence to control the matching so the values are returned in a known // order. @@ -682,15 +652,13 @@ TEST_F(DisplayChooseCompositionStrategyTest, normalOperationWithChanges) { EXPECT_CALL(mHwComposer, getDeviceCompositionChanges(HalDisplayId(DEFAULT_DISPLAY_ID), true, _, _, _, _)) - .WillOnce(DoAll(SetArgPointee<5>(mDeviceRequestedChanges), Return(NO_ERROR))); - EXPECT_CALL(*mDisplay, applyChangedTypesToLayers(mDeviceRequestedChanges.changedTypes)) - .Times(1); - EXPECT_CALL(*mDisplay, applyDisplayRequests(mDeviceRequestedChanges.displayRequests)).Times(1); - EXPECT_CALL(*mDisplay, applyLayerRequestsToLayers(mDeviceRequestedChanges.layerRequests)) - .Times(1); + .WillOnce(DoAll(SetArgPointee<5>(changes), Return(NO_ERROR))); + EXPECT_CALL(*mDisplay, applyChangedTypesToLayers(changes.changedTypes)).Times(1); + EXPECT_CALL(*mDisplay, applyDisplayRequests(changes.displayRequests)).Times(1); + EXPECT_CALL(*mDisplay, applyLayerRequestsToLayers(changes.layerRequests)).Times(1); EXPECT_CALL(*mDisplay, allLayersRequireClientComposition()).WillOnce(Return(false)); - chooseCompositionStrategy(mDisplay.get()); + mDisplay->chooseCompositionStrategy(); auto& state = mDisplay->getState(); EXPECT_FALSE(state.usesClientComposition); @@ -954,7 +922,7 @@ TEST_F(DisplayFinishFrameTest, doesNotSkipCompositionIfNotDirtyOnHwcDisplay) { mDisplay->editState().layerStackSpace.setContent(Rect(0, 0, 1, 1)); mDisplay->editState().dirtyRegion = Region::INVALID_REGION; - mDisplay->finishFrame({}, std::move(mResultWithBuffer)); + mDisplay->finishFrame({}); } TEST_F(DisplayFinishFrameTest, skipsCompositionIfNotDirty) { @@ -972,7 +940,7 @@ TEST_F(DisplayFinishFrameTest, skipsCompositionIfNotDirty) { gpuDisplay->editState().layerStackSpace.setContent(Rect(0, 0, 1, 1)); gpuDisplay->editState().dirtyRegion = Region::INVALID_REGION; - gpuDisplay->finishFrame({}, std::move(mResultWithoutBuffer)); + gpuDisplay->finishFrame({}); } TEST_F(DisplayFinishFrameTest, performsCompositionIfDirty) { @@ -989,7 +957,7 @@ TEST_F(DisplayFinishFrameTest, performsCompositionIfDirty) { gpuDisplay->editState().usesClientComposition = false; gpuDisplay->editState().layerStackSpace.setContent(Rect(0, 0, 1, 1)); gpuDisplay->editState().dirtyRegion = Region(Rect(0, 0, 1, 1)); - gpuDisplay->finishFrame({}, std::move(mResultWithBuffer)); + gpuDisplay->finishFrame({}); } /* diff --git a/services/surfaceflinger/CompositionEngine/tests/OutputTest.cpp b/services/surfaceflinger/CompositionEngine/tests/OutputTest.cpp index af172d8997..54eb8f8465 100644 --- a/services/surfaceflinger/CompositionEngine/tests/OutputTest.cpp +++ b/services/surfaceflinger/CompositionEngine/tests/OutputTest.cpp @@ -28,7 +28,6 @@ #include #include #include -#include #include #include #include @@ -990,7 +989,7 @@ struct OutputPrepareFrameTest : public testing::Test { struct OutputPartialMock : public OutputPartialMockBase { // Sets up the helper functions called by the function under test to use // mock implementations. - MOCK_METHOD0(chooseCompositionStrategy, std::optional()); + MOCK_METHOD0(chooseCompositionStrategy, void()); }; OutputPrepareFrameTest() { @@ -1038,133 +1037,6 @@ TEST_F(OutputTest, prepareFrameSetsClientCompositionOnlyByDefault) { EXPECT_FALSE(mOutput->getState().usesDeviceComposition); } -struct OutputPrepareFrameAsyncTest : public testing::Test { - struct OutputPartialMock : public OutputPartialMockBase { - // Sets up the helper functions called by the function under test to use - // mock implementations. - MOCK_METHOD0(chooseCompositionStrategy, std::optional()); - MOCK_METHOD0(updateProtectedContentState, void()); - MOCK_METHOD2(dequeueRenderBuffer, - bool(base::unique_fd*, std::shared_ptr*)); - MOCK_METHOD0(chooseCompositionStrategyAsync, - std::future>()); - MOCK_METHOD4(composeSurfaces, - std::optional( - const Region&, const compositionengine::CompositionRefreshArgs&, - std::shared_ptr, base::unique_fd&)); - }; - - OutputPrepareFrameAsyncTest() { - mOutput.setDisplayColorProfileForTest( - std::unique_ptr(mDisplayColorProfile)); - mOutput.setRenderSurfaceForTest(std::unique_ptr(mRenderSurface)); - } - - StrictMock mCompositionEngine; - mock::DisplayColorProfile* mDisplayColorProfile = new StrictMock(); - mock::RenderSurface* mRenderSurface = new StrictMock(); - StrictMock mOutput; - CompositionRefreshArgs mRefreshArgs; -}; - -TEST_F(OutputPrepareFrameAsyncTest, delegatesToChooseCompositionStrategyAndRenderSurface) { - mOutput.editState().isEnabled = true; - mOutput.editState().usesClientComposition = false; - mOutput.editState().usesDeviceComposition = true; - mOutput.editState().previousDeviceRequestedChanges = - std::make_optional({}); - std::promise> p; - p.set_value(mOutput.editState().previousDeviceRequestedChanges); - - EXPECT_CALL(mOutput, getOutputLayerCount()).WillRepeatedly(Return(0u)); - EXPECT_CALL(mOutput, updateProtectedContentState()); - EXPECT_CALL(mOutput, dequeueRenderBuffer(_, _)).WillOnce(Return(true)); - EXPECT_CALL(*mRenderSurface, prepareFrame(false, true)); - EXPECT_CALL(mOutput, chooseCompositionStrategyAsync()).WillOnce([&] { return p.get_future(); }); - EXPECT_CALL(mOutput, composeSurfaces(_, Ref(mRefreshArgs), _, _)); - - impl::GpuCompositionResult result = mOutput.prepareFrameAsync(mRefreshArgs); - EXPECT_TRUE(result.succeeded); - EXPECT_FALSE(result.bufferAvailable()); -} - -TEST_F(OutputPrepareFrameAsyncTest, skipCompositionOnDequeueFailure) { - mOutput.editState().isEnabled = true; - mOutput.editState().usesClientComposition = false; - mOutput.editState().usesDeviceComposition = true; - mOutput.editState().previousDeviceRequestedChanges = - std::make_optional({}); - std::promise> p; - p.set_value(mOutput.editState().previousDeviceRequestedChanges); - - EXPECT_CALL(mOutput, getOutputLayerCount()).WillRepeatedly(Return(0u)); - EXPECT_CALL(mOutput, updateProtectedContentState()); - EXPECT_CALL(mOutput, dequeueRenderBuffer(_, _)).WillOnce(Return(false)); - EXPECT_CALL(*mRenderSurface, prepareFrame(false, true)).Times(2); - EXPECT_CALL(mOutput, chooseCompositionStrategyAsync()).WillOnce([&] { return p.get_future(); }); - - impl::GpuCompositionResult result = mOutput.prepareFrameAsync(mRefreshArgs); - EXPECT_FALSE(result.succeeded); - EXPECT_FALSE(result.bufferAvailable()); -} - -// Tests that in the event of hwc error when choosing composition strategy, we would fall back -// client composition -TEST_F(OutputPrepareFrameAsyncTest, chooseCompositionStrategyFailureCallsPrepareFrame) { - mOutput.editState().isEnabled = true; - mOutput.editState().usesClientComposition = false; - mOutput.editState().usesDeviceComposition = true; - mOutput.editState().previousDeviceRequestedChanges = - std::make_optional({}); - std::promise> p; - p.set_value({}); - std::shared_ptr tex = - std::make_shared(1, 1, - HAL_PIXEL_FORMAT_RGBA_8888, 1, - 2); - - EXPECT_CALL(mOutput, getOutputLayerCount()).WillRepeatedly(Return(0u)); - EXPECT_CALL(mOutput, updateProtectedContentState()); - EXPECT_CALL(mOutput, dequeueRenderBuffer(_, _)) - .WillOnce(DoAll(SetArgPointee<1>(tex), Return(true))); - EXPECT_CALL(*mRenderSurface, prepareFrame(false, true)).Times(2); - EXPECT_CALL(mOutput, chooseCompositionStrategyAsync()).WillOnce([&] { return p.get_future(); }); - EXPECT_CALL(mOutput, composeSurfaces(_, Ref(mRefreshArgs), _, _)); - - impl::GpuCompositionResult result = mOutput.prepareFrameAsync(mRefreshArgs); - EXPECT_FALSE(result.succeeded); - EXPECT_TRUE(result.bufferAvailable()); -} - -TEST_F(OutputPrepareFrameAsyncTest, predictionMiss) { - mOutput.editState().isEnabled = true; - mOutput.editState().usesClientComposition = false; - mOutput.editState().usesDeviceComposition = true; - mOutput.editState().previousDeviceRequestedChanges = - std::make_optional({}); - auto newDeviceRequestedChanges = - std::make_optional({}); - newDeviceRequestedChanges->clientTargetBrightness = 5.f; - std::promise> p; - p.set_value(newDeviceRequestedChanges); - std::shared_ptr tex = - std::make_shared(1, 1, - HAL_PIXEL_FORMAT_RGBA_8888, 1, - 2); - - EXPECT_CALL(mOutput, getOutputLayerCount()).WillRepeatedly(Return(0u)); - EXPECT_CALL(mOutput, updateProtectedContentState()); - EXPECT_CALL(mOutput, dequeueRenderBuffer(_, _)) - .WillOnce(DoAll(SetArgPointee<1>(tex), Return(true))); - EXPECT_CALL(*mRenderSurface, prepareFrame(false, true)).Times(2); - EXPECT_CALL(mOutput, chooseCompositionStrategyAsync()).WillOnce([&] { return p.get_future(); }); - EXPECT_CALL(mOutput, composeSurfaces(_, Ref(mRefreshArgs), _, _)); - - impl::GpuCompositionResult result = mOutput.prepareFrameAsync(mRefreshArgs); - EXPECT_FALSE(result.succeeded); - EXPECT_TRUE(result.bufferAvailable()); -} - /* * Output::prepare() */ @@ -1923,14 +1795,10 @@ struct OutputPresentTest : public testing::Test { MOCK_METHOD1(setColorTransform, void(const compositionengine::CompositionRefreshArgs&)); MOCK_METHOD0(beginFrame, void()); MOCK_METHOD0(prepareFrame, void()); - MOCK_METHOD1(prepareFrameAsync, GpuCompositionResult(const CompositionRefreshArgs&)); MOCK_METHOD1(devOptRepaintFlash, void(const compositionengine::CompositionRefreshArgs&)); - MOCK_METHOD2(finishFrame, - void(const compositionengine::CompositionRefreshArgs&, - GpuCompositionResult&&)); + MOCK_METHOD1(finishFrame, void(const compositionengine::CompositionRefreshArgs&)); MOCK_METHOD0(postFramebuffer, void()); MOCK_METHOD1(renderCachedSets, void(const compositionengine::CompositionRefreshArgs&)); - MOCK_METHOD1(canPredictCompositionStrategy, bool(const CompositionRefreshArgs&)); }; StrictMock mOutput; @@ -1946,30 +1814,9 @@ TEST_F(OutputPresentTest, justInvokesChildFunctionsInSequence) { EXPECT_CALL(mOutput, writeCompositionState(Ref(args))); EXPECT_CALL(mOutput, setColorTransform(Ref(args))); EXPECT_CALL(mOutput, beginFrame()); - EXPECT_CALL(mOutput, canPredictCompositionStrategy(Ref(args))).WillOnce(Return(false)); EXPECT_CALL(mOutput, prepareFrame()); EXPECT_CALL(mOutput, devOptRepaintFlash(Ref(args))); - EXPECT_CALL(mOutput, finishFrame(Ref(args), _)); - EXPECT_CALL(mOutput, postFramebuffer()); - EXPECT_CALL(mOutput, renderCachedSets(Ref(args))); - - mOutput.present(args); -} - -TEST_F(OutputPresentTest, predictingCompositionStrategyInvokesPrepareFrameAsync) { - CompositionRefreshArgs args; - - InSequence seq; - EXPECT_CALL(mOutput, updateColorProfile(Ref(args))); - EXPECT_CALL(mOutput, updateCompositionState(Ref(args))); - EXPECT_CALL(mOutput, planComposition()); - EXPECT_CALL(mOutput, writeCompositionState(Ref(args))); - EXPECT_CALL(mOutput, setColorTransform(Ref(args))); - EXPECT_CALL(mOutput, beginFrame()); - EXPECT_CALL(mOutput, canPredictCompositionStrategy(Ref(args))).WillOnce(Return(true)); - EXPECT_CALL(mOutput, prepareFrameAsync(Ref(args))); - EXPECT_CALL(mOutput, devOptRepaintFlash(Ref(args))); - EXPECT_CALL(mOutput, finishFrame(Ref(args), _)); + EXPECT_CALL(mOutput, finishFrame(Ref(args))); EXPECT_CALL(mOutput, postFramebuffer()); EXPECT_CALL(mOutput, renderCachedSets(Ref(args))); @@ -2867,15 +2714,11 @@ struct OutputDevOptRepaintFlashTest : public testing::Test { // Sets up the helper functions called by the function under test to use // mock implementations. MOCK_METHOD(Region, getDirtyRegion, (), (const)); - MOCK_METHOD4(composeSurfaces, + MOCK_METHOD2(composeSurfaces, std::optional( - const Region&, const compositionengine::CompositionRefreshArgs&, - std::shared_ptr, base::unique_fd&)); + const Region&, const compositionengine::CompositionRefreshArgs&)); MOCK_METHOD0(postFramebuffer, void()); MOCK_METHOD0(prepareFrame, void()); - MOCK_METHOD0(updateProtectedContentState, void()); - MOCK_METHOD2(dequeueRenderBuffer, - bool(base::unique_fd*, std::shared_ptr*)); }; OutputDevOptRepaintFlashTest() { @@ -2932,9 +2775,7 @@ TEST_F(OutputDevOptRepaintFlashTest, alsoComposesSurfacesAndQueuesABufferIfDirty InSequence seq; EXPECT_CALL(mOutput, getDirtyRegion()).WillOnce(Return(kNotEmptyRegion)); - EXPECT_CALL(mOutput, updateProtectedContentState()); - EXPECT_CALL(mOutput, dequeueRenderBuffer(_, _)); - EXPECT_CALL(mOutput, composeSurfaces(RegionEq(kNotEmptyRegion), Ref(mRefreshArgs), _, _)); + EXPECT_CALL(mOutput, composeSurfaces(RegionEq(kNotEmptyRegion), Ref(mRefreshArgs))); EXPECT_CALL(*mRenderSurface, queueBuffer(_)); EXPECT_CALL(mOutput, postFramebuffer()); EXPECT_CALL(mOutput, prepareFrame()); @@ -2950,14 +2791,10 @@ struct OutputFinishFrameTest : public testing::Test { struct OutputPartialMock : public OutputPartialMockBase { // Sets up the helper functions called by the function under test to use // mock implementations. - MOCK_METHOD4(composeSurfaces, + MOCK_METHOD2(composeSurfaces, std::optional( - const Region&, const compositionengine::CompositionRefreshArgs&, - std::shared_ptr, base::unique_fd&)); + const Region&, const compositionengine::CompositionRefreshArgs&)); MOCK_METHOD0(postFramebuffer, void()); - MOCK_METHOD0(updateProtectedContentState, void()); - MOCK_METHOD2(dequeueRenderBuffer, - bool(base::unique_fd*, std::shared_ptr*)); }; OutputFinishFrameTest() { @@ -2975,63 +2812,27 @@ struct OutputFinishFrameTest : public testing::Test { TEST_F(OutputFinishFrameTest, ifNotEnabledDoesNothing) { mOutput.mState.isEnabled = false; - impl::GpuCompositionResult result; - mOutput.finishFrame(mRefreshArgs, std::move(result)); + mOutput.finishFrame(mRefreshArgs); } TEST_F(OutputFinishFrameTest, takesEarlyOutifComposeSurfacesReturnsNoFence) { mOutput.mState.isEnabled = true; - EXPECT_CALL(mOutput, updateProtectedContentState()); - EXPECT_CALL(mOutput, dequeueRenderBuffer(_, _)).WillOnce(Return(true)); - EXPECT_CALL(mOutput, composeSurfaces(RegionEq(Region::INVALID_REGION), _, _, _)); - - impl::GpuCompositionResult result; - mOutput.finishFrame(mRefreshArgs, std::move(result)); -} - -TEST_F(OutputFinishFrameTest, queuesBufferIfComposeSurfacesReturnsAFence) { - mOutput.mState.isEnabled = true; - - InSequence seq; - EXPECT_CALL(mOutput, updateProtectedContentState()); - EXPECT_CALL(mOutput, dequeueRenderBuffer(_, _)).WillOnce(Return(true)); - EXPECT_CALL(mOutput, composeSurfaces(RegionEq(Region::INVALID_REGION), _, _, _)) - .WillOnce(Return(ByMove(base::unique_fd()))); - EXPECT_CALL(*mRenderSurface, queueBuffer(_)); - - impl::GpuCompositionResult result; - mOutput.finishFrame(mRefreshArgs, std::move(result)); -} - -TEST_F(OutputFinishFrameTest, predictionSucceeded) { - mOutput.mState.isEnabled = true; InSequence seq; - EXPECT_CALL(*mRenderSurface, queueBuffer(_)); + EXPECT_CALL(mOutput, composeSurfaces(RegionEq(Region::INVALID_REGION), _)); - impl::GpuCompositionResult result; - result.succeeded = true; - mOutput.finishFrame(mRefreshArgs, std::move(result)); + mOutput.finishFrame(mRefreshArgs); } -TEST_F(OutputFinishFrameTest, predictionFailedAndBufferIsReused) { +TEST_F(OutputFinishFrameTest, queuesBufferIfComposeSurfacesReturnsAFence) { mOutput.mState.isEnabled = true; InSequence seq; - - impl::GpuCompositionResult result; - result.succeeded = false; - result.buffer = - std::make_shared(1, 1, - HAL_PIXEL_FORMAT_RGBA_8888, 1, - 2); - - EXPECT_CALL(mOutput, - composeSurfaces(RegionEq(Region::INVALID_REGION), _, result.buffer, - Eq(ByRef(result.fence)))) + EXPECT_CALL(mOutput, composeSurfaces(RegionEq(Region::INVALID_REGION), _)) .WillOnce(Return(ByMove(base::unique_fd()))); EXPECT_CALL(*mRenderSurface, queueBuffer(_)); - mOutput.finishFrame(mRefreshArgs, std::move(result)); + + mOutput.finishFrame(mRefreshArgs); } /* @@ -3278,15 +3079,8 @@ struct OutputComposeSurfacesTest : public testing::Test { struct ExecuteState : public CallOrderStateMachineHelper { auto execute() { - base::unique_fd fence; - std::shared_ptr externalTexture; - const bool success = - getInstance()->mOutput.dequeueRenderBuffer(&fence, &externalTexture); - if (success) { - getInstance()->mReadyFence = - getInstance()->mOutput.composeSurfaces(kDebugRegion, kDefaultRefreshArgs, - externalTexture, fence); - } + getInstance()->mReadyFence = + getInstance()->mOutput.composeSurfaces(kDebugRegion, kDefaultRefreshArgs); return nextState(); } }; @@ -3847,11 +3641,7 @@ TEST_F(OutputComposeSurfacesTest_HandlesProtectedContent, ifDisplayIsNotSecure) EXPECT_CALL(mRenderEngine, isProtected).WillOnce(Return(true)); EXPECT_CALL(mRenderEngine, useProtectedContext(false)); - base::unique_fd fd; - std::shared_ptr tex; - mOutput.updateProtectedContentState(); - mOutput.dequeueRenderBuffer(&fd, &tex); - mOutput.composeSurfaces(kDebugRegion, kDefaultRefreshArgs, tex, fd); + mOutput.composeSurfaces(kDebugRegion, kDefaultRefreshArgs); } TEST_F(OutputComposeSurfacesTest_HandlesProtectedContent, ifRenderEngineDoesNotSupportIt) { @@ -3859,11 +3649,7 @@ TEST_F(OutputComposeSurfacesTest_HandlesProtectedContent, ifRenderEngineDoesNotS mLayer2.mLayerFEState.hasProtectedContent = true; EXPECT_CALL(mRenderEngine, supportsProtectedContent()).WillRepeatedly(Return(false)); - base::unique_fd fd; - std::shared_ptr tex; - mOutput.updateProtectedContentState(); - mOutput.dequeueRenderBuffer(&fd, &tex); - mOutput.composeSurfaces(kDebugRegion, kDefaultRefreshArgs, tex, fd); + mOutput.composeSurfaces(kDebugRegion, kDefaultRefreshArgs); } TEST_F(OutputComposeSurfacesTest_HandlesProtectedContent, ifNoProtectedContentLayers) { @@ -3875,11 +3661,7 @@ TEST_F(OutputComposeSurfacesTest_HandlesProtectedContent, ifNoProtectedContentLa EXPECT_CALL(mRenderEngine, useProtectedContext(false)); EXPECT_CALL(*mRenderSurface, setProtected(false)); - base::unique_fd fd; - std::shared_ptr tex; - mOutput.updateProtectedContentState(); - mOutput.dequeueRenderBuffer(&fd, &tex); - mOutput.composeSurfaces(kDebugRegion, kDefaultRefreshArgs, tex, fd); + mOutput.composeSurfaces(kDebugRegion, kDefaultRefreshArgs); } TEST_F(OutputComposeSurfacesTest_HandlesProtectedContent, ifNotEnabled) { @@ -3901,11 +3683,7 @@ TEST_F(OutputComposeSurfacesTest_HandlesProtectedContent, ifNotEnabled) { .WillOnce(Return(ByMove( futureOf({NO_ERROR, base::unique_fd()})))); - base::unique_fd fd; - std::shared_ptr tex; - mOutput.updateProtectedContentState(); - mOutput.dequeueRenderBuffer(&fd, &tex); - mOutput.composeSurfaces(kDebugRegion, kDefaultRefreshArgs, tex, fd); + mOutput.composeSurfaces(kDebugRegion, kDefaultRefreshArgs); } TEST_F(OutputComposeSurfacesTest_HandlesProtectedContent, ifAlreadyEnabledEverywhere) { @@ -3915,11 +3693,7 @@ TEST_F(OutputComposeSurfacesTest_HandlesProtectedContent, ifAlreadyEnabledEveryw EXPECT_CALL(mRenderEngine, isProtected).WillOnce(Return(true)); EXPECT_CALL(*mRenderSurface, isProtected).WillOnce(Return(true)); - base::unique_fd fd; - std::shared_ptr tex; - mOutput.updateProtectedContentState(); - mOutput.dequeueRenderBuffer(&fd, &tex); - mOutput.composeSurfaces(kDebugRegion, kDefaultRefreshArgs, tex, fd); + mOutput.composeSurfaces(kDebugRegion, kDefaultRefreshArgs); } TEST_F(OutputComposeSurfacesTest_HandlesProtectedContent, ifFailsToEnableInRenderEngine) { @@ -3930,11 +3704,7 @@ TEST_F(OutputComposeSurfacesTest_HandlesProtectedContent, ifFailsToEnableInRende EXPECT_CALL(*mRenderSurface, isProtected).WillOnce(Return(false)); EXPECT_CALL(mRenderEngine, useProtectedContext(true)); - base::unique_fd fd; - std::shared_ptr tex; - mOutput.updateProtectedContentState(); - mOutput.dequeueRenderBuffer(&fd, &tex); - mOutput.composeSurfaces(kDebugRegion, kDefaultRefreshArgs, tex, fd); + mOutput.composeSurfaces(kDebugRegion, kDefaultRefreshArgs); } TEST_F(OutputComposeSurfacesTest_HandlesProtectedContent, ifAlreadyEnabledInRenderEngine) { @@ -3945,11 +3715,7 @@ TEST_F(OutputComposeSurfacesTest_HandlesProtectedContent, ifAlreadyEnabledInRend EXPECT_CALL(*mRenderSurface, isProtected).WillOnce(Return(false)); EXPECT_CALL(*mRenderSurface, setProtected(true)); - base::unique_fd fd; - std::shared_ptr tex; - mOutput.updateProtectedContentState(); - mOutput.dequeueRenderBuffer(&fd, &tex); - mOutput.composeSurfaces(kDebugRegion, kDefaultRefreshArgs, tex, fd); + mOutput.composeSurfaces(kDebugRegion, kDefaultRefreshArgs); } TEST_F(OutputComposeSurfacesTest_HandlesProtectedContent, ifAlreadyEnabledInRenderSurface) { @@ -3960,11 +3726,7 @@ TEST_F(OutputComposeSurfacesTest_HandlesProtectedContent, ifAlreadyEnabledInRend EXPECT_CALL(*mRenderSurface, isProtected).WillOnce(Return(true)); EXPECT_CALL(mRenderEngine, useProtectedContext(true)); - base::unique_fd fd; - std::shared_ptr tex; - mOutput.updateProtectedContentState(); - mOutput.dequeueRenderBuffer(&fd, &tex); - mOutput.composeSurfaces(kDebugRegion, kDefaultRefreshArgs, tex, fd); + mOutput.composeSurfaces(kDebugRegion, kDefaultRefreshArgs); } struct OutputComposeSurfacesTest_SetsExpensiveRendering : public OutputComposeSurfacesTest { @@ -3994,11 +3756,7 @@ TEST_F(OutputComposeSurfacesTest_SetsExpensiveRendering, IfExepensiveOutputDatas .WillOnce(Return(ByMove( futureOf({NO_ERROR, base::unique_fd()})))); - base::unique_fd fd; - std::shared_ptr tex; - mOutput.updateProtectedContentState(); - mOutput.dequeueRenderBuffer(&fd, &tex); - mOutput.composeSurfaces(kDebugRegion, kDefaultRefreshArgs, tex, fd); + mOutput.composeSurfaces(kDebugRegion, kDefaultRefreshArgs); } struct OutputComposeSurfacesTest_SetsExpensiveRendering_ForBlur @@ -4033,12 +3791,7 @@ TEST_F(OutputComposeSurfacesTest_SetsExpensiveRendering_ForBlur, IfBlursAreExpen mOutput.writeCompositionState(mRefreshArgs); EXPECT_CALL(mOutput, setExpensiveRenderingExpected(true)); - - base::unique_fd fd; - std::shared_ptr tex; - mOutput.updateProtectedContentState(); - mOutput.dequeueRenderBuffer(&fd, &tex); - mOutput.composeSurfaces(kDebugRegion, mRefreshArgs, tex, fd); + mOutput.composeSurfaces(kDebugRegion, mRefreshArgs); } TEST_F(OutputComposeSurfacesTest_SetsExpensiveRendering_ForBlur, IfBlursAreNotExpensive) { @@ -4048,12 +3801,7 @@ TEST_F(OutputComposeSurfacesTest_SetsExpensiveRendering_ForBlur, IfBlursAreNotEx mOutput.writeCompositionState(mRefreshArgs); EXPECT_CALL(mOutput, setExpensiveRenderingExpected(true)).Times(0); - - base::unique_fd fd; - std::shared_ptr tex; - mOutput.updateProtectedContentState(); - mOutput.dequeueRenderBuffer(&fd, &tex); - mOutput.composeSurfaces(kDebugRegion, mRefreshArgs, tex, fd); + mOutput.composeSurfaces(kDebugRegion, mRefreshArgs); } /* diff --git a/services/surfaceflinger/DisplayDevice.cpp b/services/surfaceflinger/DisplayDevice.cpp index 610d86f29a..45b98bb3d3 100644 --- a/services/surfaceflinger/DisplayDevice.cpp +++ b/services/surfaceflinger/DisplayDevice.cpp @@ -91,7 +91,6 @@ DisplayDevice::DisplayDevice(DisplayDeviceCreationArgs& args) static_cast(SurfaceFlinger::maxFrameBufferAcquiredBuffers)); } - mCompositionDisplay->setPredictCompositionStrategy(mFlinger->mPredictCompositionStrategy); mCompositionDisplay->createDisplayColorProfile( compositionengine::DisplayColorProfileCreationArgsBuilder() .setHasWideColorGamut(args.hasWideColorGamut) diff --git a/services/surfaceflinger/DisplayHardware/HWComposer.h b/services/surfaceflinger/DisplayHardware/HWComposer.h index a8d439b7e0..5b2e265eb6 100644 --- a/services/surfaceflinger/DisplayHardware/HWComposer.h +++ b/services/surfaceflinger/DisplayHardware/HWComposer.h @@ -269,14 +269,6 @@ public: support) = 0; }; -static inline bool operator==(const android::HWComposer::DeviceRequestedChanges& lhs, - const android::HWComposer::DeviceRequestedChanges& rhs) { - return lhs.changedTypes == rhs.changedTypes && lhs.displayRequests == rhs.displayRequests && - lhs.layerRequests == rhs.layerRequests && - lhs.clientTargetProperty == rhs.clientTargetProperty && - lhs.clientTargetBrightness == rhs.clientTargetBrightness; -} - namespace impl { class HWComposer final : public android::HWComposer { diff --git a/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.h b/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.h index e21095aa88..307da41667 100644 --- a/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.h +++ b/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.h @@ -89,9 +89,6 @@ public: virtual void dumpAsString(String8& result) const; virtual void resizeBuffers(const ui::Size&) override; virtual const sp& getClientTargetAcquireFence() const override; - // Virtual display surface needs to prepare the frame based on composition type. Skip - // any client composition prediction. - virtual bool supportsCompositionStrategyPrediction() const override { return false; }; private: enum Source : size_t { diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp index efaa975ff2..089875c91b 100644 --- a/services/surfaceflinger/SurfaceFlinger.cpp +++ b/services/surfaceflinger/SurfaceFlinger.cpp @@ -480,9 +480,6 @@ SurfaceFlinger::SurfaceFlinger(Factory& factory) : SurfaceFlinger(factory, SkipI property_get("debug.sf.disable_client_composition_cache", value, "0"); mDisableClientCompositionCache = atoi(value); - property_get("debug.sf.predict_hwc_composition_strategy", value, "0"); - mPredictCompositionStrategy = atoi(value); - // We should be reading 'persist.sys.sf.color_saturation' here // but since /data may be encrypted, we need to wait until after vold // comes online to attempt to read the property. The property is diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h index 86c83338ff..f5a695b07c 100644 --- a/services/surfaceflinger/SurfaceFlinger.h +++ b/services/surfaceflinger/SurfaceFlinger.h @@ -344,11 +344,6 @@ public: void disableExpensiveRendering(); FloatRect getMaxDisplayBounds(); - // If set, composition engine tries to predict the composition strategy provided by HWC - // based on the previous frame. If the strategy can be predicted, gpu composition will - // run parallel to the hwc validateDisplay call and re-run if the predition is incorrect. - bool mPredictCompositionStrategy = false; - protected: // We're reference counted, never destroy SurfaceFlinger directly virtual ~SurfaceFlinger(); -- cgit v1.2.3-59-g8ed1b From d7a694c65f39d7225005187b238fcb7447964b05 Mon Sep 17 00:00:00 2001 From: chaviw Date: Mon, 21 Mar 2022 17:54:23 -0500 Subject: Use CacheId when buffer is null. It's likely the buffer is null even if eBufferChanged is set because we already cached the buffer. This can happen when the transaction is sent over IPC and we automatically cache the buffer. This change uses the cacheId if the buffer is null Test: Hard to repro Bug: 225815507 Change-Id: Ic95bfc179cc86e494943e9bd6e15cb9afd69f1df (cherry picked from commit dcba9e07976c20bb98a3e92aca149eacc6e59d2d) Merged-In: Ic95bfc179cc86e494943e9bd6e15cb9afd69f1df --- libs/gui/LayerState.cpp | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/libs/gui/LayerState.cpp b/libs/gui/LayerState.cpp index 49b669eb3f..34db5b1626 100644 --- a/libs/gui/LayerState.cpp +++ b/libs/gui/LayerState.cpp @@ -774,7 +774,13 @@ status_t LayerCaptureArgs::readFromParcel(const Parcel* input) { }; // namespace gui ReleaseCallbackId BufferData::generateReleaseCallbackId() const { - return {buffer->getId(), frameNumber}; + uint64_t bufferId; + if (buffer) { + bufferId = buffer->getId(); + } else { + bufferId = cachedBuffer.id; + } + return {bufferId, frameNumber}; } status_t BufferData::writeToParcel(Parcel* output) const { -- cgit v1.2.3-59-g8ed1b From db06ecf8ff98d9e161b1876fb3af828fff79ae12 Mon Sep 17 00:00:00 2001 From: Robert Carr Date: Thu, 23 Jun 2022 11:17:16 -0700 Subject: SurfaceFlinger: Disable early release optimization Starting a few weeks ago a crop of issues started showing up on a subset of devices, related to the early release optimization (which landed much earlier). Attempts to fix them unfortunately introduced another regression. The fact that the optimization is only triggering visible errors on a subset of devices is somewhat of a mystery. A CL is prepared which fixes all issues observed to date. Howeverthis mystery about device specific behavior implies the full implications of the optimization are not yet understood. It's better to disable the optimization for the current release and take time to fully understand what is happening. Removing the optimization may have some impact on jank, but I expect it's unlikely to be large. I only expect the optimization to reduce jank in cases where: 1. The app is backpressured 2. SurfaceFlinger is repeatedly missing frames producing long dequeues 3. The app has UI + RenderThread time >= vsync interval and is only able to achieve steady production with render ahead and pipelining. If SurfaceFlinger were to begin regular frame production again, early release could help the steady production pipeline recover faster by unblocking the app sooner. This represents a small amount of edge cases. Continued work on preventing SF from missing frames, makes this probably even a smaller amount than when the early release optimization first landed. Bug: 236120925 Bug: 234753489 Test: Existing tests pass. Verify that early release is disabled. Change-Id: I6a9a34331edb752d51c9d2d0b6826942d0545e3d (cherry picked from commit b645049d01ef72653dc8fc363b9af18f4678f1e8) Merged-In: I6a9a34331edb752d51c9d2d0b6826942d0545e3d --- services/surfaceflinger/BufferStateLayer.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/services/surfaceflinger/BufferStateLayer.cpp b/services/surfaceflinger/BufferStateLayer.cpp index fecf5ae059..3875f151cb 100644 --- a/services/surfaceflinger/BufferStateLayer.cpp +++ b/services/surfaceflinger/BufferStateLayer.cpp @@ -34,6 +34,8 @@ #include "FrameTracer/FrameTracer.h" #include "TimeStats/TimeStats.h" +#define EARLY_RELEASE_ENABLED false + namespace android { using PresentState = frametimeline::SurfaceFrame::PresentState; @@ -373,7 +375,7 @@ bool BufferStateLayer::setBuffer(std::shared_ptr& addSurfaceFrameDroppedForBuffer(mDrawingState.bufferSurfaceFrameTX); mDrawingState.bufferSurfaceFrameTX.reset(); } - } else if (mLastClientCompositionFence != nullptr) { + } else if (EARLY_RELEASE_ENABLED && mLastClientCompositionFence != nullptr) { callReleaseBufferCallback(mDrawingState.releaseBufferListener, mDrawingState.buffer->getBuffer(), mDrawingState.frameNumber, mLastClientCompositionFence, -- cgit v1.2.3-59-g8ed1b