Loading services/surfaceflinger/CompositionEngine/src/CompositionEngine.cpp +15 −17 Original line number Diff line number Diff line Loading @@ -198,7 +198,6 @@ void CompositionEngine::preComposition(CompositionRefreshArgs& args) { // these buffers and fire a NO_FENCE to release it. This ensures that all // promises for buffer releases are fulfilled at the end of composition. void CompositionEngine::postComposition(CompositionRefreshArgs& args) { if (FlagManager::getInstance().ce_fence_promise()) { SFTRACE_CALL(); ALOGV(__FUNCTION__); Loading @@ -219,7 +218,6 @@ void CompositionEngine::postComposition(CompositionRefreshArgs& args) { } } } } FeatureFlags CompositionEngine::getFeatureFlags() const { return {}; Loading services/surfaceflinger/CompositionEngine/src/Output.cpp +2 −13 Original line number Diff line number Diff line Loading @@ -1610,13 +1610,7 @@ void Output::presentFrameAndReleaseLayers(bool flushEvenWhenDisabled) { releaseFence = Fence::merge("LayerRelease", releaseFence, frame.clientTargetAcquireFence); } if (FlagManager::getInstance().ce_fence_promise()) { layer->getLayerFE().setReleaseFence(releaseFence); } else { layer->getLayerFE() .onLayerDisplayed(ftl::yield<FenceResult>(std::move(releaseFence)).share(), outputState.layerFilter.layerStack); } } // We've got a list of layers needing fences, that are disjoint with Loading @@ -1624,12 +1618,7 @@ void Output::presentFrameAndReleaseLayers(bool flushEvenWhenDisabled) { // supply them with the present fence. for (auto& weakLayer : mReleasedLayers) { if (const auto layer = weakLayer.promote()) { if (FlagManager::getInstance().ce_fence_promise()) { layer->setReleaseFence(frame.presentFence); } else { layer->onLayerDisplayed(ftl::yield<FenceResult>(frame.presentFence).share(), outputState.layerFilter.layerStack); } } } Loading services/surfaceflinger/CompositionEngine/tests/CompositionEngineTest.cpp +0 −5 Original line number Diff line number Diff line Loading @@ -30,8 +30,6 @@ #include "TimeStats/TimeStats.h" #include "gmock/gmock.h" #include <variant> using namespace com::android::graphics::surfaceflinger; namespace android::compositionengine { Loading Loading @@ -494,9 +492,6 @@ struct CompositionEnginePostCompositionTest : public CompositionEngineTest { }; TEST_F(CompositionEnginePostCompositionTest, postCompositionReleasesAllFences) { SET_FLAG_FOR_TEST(com::android::graphics::surfaceflinger::flags::ce_fence_promise, true); ASSERT_TRUE(FlagManager::getInstance().ce_fence_promise()); EXPECT_CALL(*mLayer1FE, getReleaseFencePromiseStatus) .WillOnce(Return(LayerFE::ReleaseFencePromiseStatus::FULFILLED)); EXPECT_CALL(*mLayer2FE, getReleaseFencePromiseStatus) Loading services/surfaceflinger/CompositionEngine/tests/OutputTest.cpp +0 −134 Original line number Diff line number Diff line Loading @@ -34,7 +34,6 @@ #include <ui/Rect.h> #include <ui/Region.h> #include <cmath> #include <cstdint> #include <variant> Loading Loading @@ -3263,57 +3262,9 @@ TEST_F(OutputPostFramebufferTest, ifEnabledMustFlipThenPresentThenSendPresentCom mOutput.presentFrameAndReleaseLayers(kFlushEvenWhenDisabled); } TEST_F(OutputPostFramebufferTest, releaseFencesAreSentToLayerFE) { SET_FLAG_FOR_TEST(com::android::graphics::surfaceflinger::flags::ce_fence_promise, false); ASSERT_FALSE(FlagManager::getInstance().ce_fence_promise()); // Simulate getting release fences from each layer, and ensure they are passed to the // front-end layer interface for each layer correctly. mOutput.mState.isEnabled = true; // Create three unique fence instances sp<Fence> layer1Fence = sp<Fence>::make(); sp<Fence> layer2Fence = sp<Fence>::make(); sp<Fence> layer3Fence = sp<Fence>::make(); Output::FrameFences frameFences; frameFences.layerFences.emplace(&mLayer1.hwc2Layer, layer1Fence); frameFences.layerFences.emplace(&mLayer2.hwc2Layer, layer2Fence); frameFences.layerFences.emplace(&mLayer3.hwc2Layer, layer3Fence); EXPECT_CALL(mOutput, presentFrame()).WillOnce(Return(frameFences)); EXPECT_CALL(*mRenderSurface, onPresentDisplayCompleted()); // Compare the pointers values of each fence to make sure the correct ones // are passed. This happens to work with the current implementation, but // would not survive certain calls like Fence::merge() which would return a // new instance. EXPECT_CALL(*mLayer1.layerFE, onLayerDisplayed(_, _)) .WillOnce([&layer1Fence](ftl::SharedFuture<FenceResult> futureFenceResult, ui::LayerStack) { EXPECT_EQ(FenceResult(layer1Fence), futureFenceResult.get()); }); EXPECT_CALL(*mLayer2.layerFE, onLayerDisplayed(_, _)) .WillOnce([&layer2Fence](ftl::SharedFuture<FenceResult> futureFenceResult, ui::LayerStack) { EXPECT_EQ(FenceResult(layer2Fence), futureFenceResult.get()); }); EXPECT_CALL(*mLayer3.layerFE, onLayerDisplayed(_, _)) .WillOnce([&layer3Fence](ftl::SharedFuture<FenceResult> futureFenceResult, ui::LayerStack) { EXPECT_EQ(FenceResult(layer3Fence), futureFenceResult.get()); }); constexpr bool kFlushEvenWhenDisabled = false; mOutput.presentFrameAndReleaseLayers(kFlushEvenWhenDisabled); } TEST_F(OutputPostFramebufferTest, releaseFencesAreSetInLayerFE) { SET_FLAG_FOR_TEST(com::android::graphics::surfaceflinger::flags::ce_fence_promise, true); ASSERT_TRUE(FlagManager::getInstance().ce_fence_promise()); // Simulate getting release fences from each layer, and ensure they are passed to the // front-end layer interface for each layer correctly. mOutput.mState.isEnabled = true; // Create three unique fence instances Loading Loading @@ -3350,37 +3301,7 @@ TEST_F(OutputPostFramebufferTest, releaseFencesAreSetInLayerFE) { mOutput.presentFrameAndReleaseLayers(kFlushEvenWhenDisabled); } TEST_F(OutputPostFramebufferTest, releaseFencesIncludeClientTargetAcquireFence) { SET_FLAG_FOR_TEST(com::android::graphics::surfaceflinger::flags::ce_fence_promise, false); ASSERT_FALSE(FlagManager::getInstance().ce_fence_promise()); mOutput.mState.isEnabled = true; mOutput.mState.usesClientComposition = true; Output::FrameFences frameFences; frameFences.clientTargetAcquireFence = sp<Fence>::make(); frameFences.layerFences.emplace(&mLayer1.hwc2Layer, sp<Fence>::make()); frameFences.layerFences.emplace(&mLayer2.hwc2Layer, sp<Fence>::make()); frameFences.layerFences.emplace(&mLayer3.hwc2Layer, sp<Fence>::make()); EXPECT_CALL(mOutput, presentFrame()).WillOnce(Return(frameFences)); EXPECT_CALL(*mRenderSurface, onPresentDisplayCompleted()); // Fence::merge is called, and since none of the fences are actually valid, // Fence::NO_FENCE is returned and passed to each onLayerDisplayed() call. // This is the best we can do without creating a real kernel fence object. EXPECT_CALL(*mLayer1.layerFE, onLayerDisplayed).WillOnce(Return()); EXPECT_CALL(*mLayer2.layerFE, onLayerDisplayed).WillOnce(Return()); EXPECT_CALL(*mLayer3.layerFE, onLayerDisplayed).WillOnce(Return()); constexpr bool kFlushEvenWhenDisabled = false; mOutput.presentFrameAndReleaseLayers(kFlushEvenWhenDisabled); } TEST_F(OutputPostFramebufferTest, setReleaseFencesIncludeClientTargetAcquireFence) { SET_FLAG_FOR_TEST(com::android::graphics::surfaceflinger::flags::ce_fence_promise, true); ASSERT_TRUE(FlagManager::getInstance().ce_fence_promise()); mOutput.mState.isEnabled = true; mOutput.mState.usesClientComposition = true; Loading @@ -3403,62 +3324,7 @@ TEST_F(OutputPostFramebufferTest, setReleaseFencesIncludeClientTargetAcquireFenc mOutput.presentFrameAndReleaseLayers(kFlushEvenWhenDisabled); } TEST_F(OutputPostFramebufferTest, releasedLayersSentPresentFence) { SET_FLAG_FOR_TEST(com::android::graphics::surfaceflinger::flags::ce_fence_promise, false); ASSERT_FALSE(FlagManager::getInstance().ce_fence_promise()); mOutput.mState.isEnabled = true; mOutput.mState.usesClientComposition = true; // This should happen even if there are no (current) output layers. EXPECT_CALL(mOutput, getOutputLayerCount()).WillOnce(Return(0u)); // Load up the released layers with some mock instances sp<StrictMock<mock::LayerFE>> releasedLayer1 = sp<StrictMock<mock::LayerFE>>::make(); sp<StrictMock<mock::LayerFE>> releasedLayer2 = sp<StrictMock<mock::LayerFE>>::make(); sp<StrictMock<mock::LayerFE>> releasedLayer3 = sp<StrictMock<mock::LayerFE>>::make(); Output::ReleasedLayers layers; layers.push_back(releasedLayer1); layers.push_back(releasedLayer2); layers.push_back(releasedLayer3); mOutput.setReleasedLayers(std::move(layers)); // Set up a fake present fence sp<Fence> presentFence = sp<Fence>::make(); Output::FrameFences frameFences; frameFences.presentFence = presentFence; EXPECT_CALL(mOutput, presentFrame()).WillOnce(Return(frameFences)); EXPECT_CALL(*mRenderSurface, onPresentDisplayCompleted()); // Each released layer should be given the presentFence. EXPECT_CALL(*releasedLayer1, onLayerDisplayed(_, _)) .WillOnce([&presentFence](ftl::SharedFuture<FenceResult> futureFenceResult, ui::LayerStack) { EXPECT_EQ(FenceResult(presentFence), futureFenceResult.get()); }); EXPECT_CALL(*releasedLayer2, onLayerDisplayed(_, _)) .WillOnce([&presentFence](ftl::SharedFuture<FenceResult> futureFenceResult, ui::LayerStack) { EXPECT_EQ(FenceResult(presentFence), futureFenceResult.get()); }); EXPECT_CALL(*releasedLayer3, onLayerDisplayed(_, _)) .WillOnce([&presentFence](ftl::SharedFuture<FenceResult> futureFenceResult, ui::LayerStack) { EXPECT_EQ(FenceResult(presentFence), futureFenceResult.get()); }); constexpr bool kFlushEvenWhenDisabled = false; mOutput.presentFrameAndReleaseLayers(kFlushEvenWhenDisabled); // After the call the list of released layers should have been cleared. EXPECT_TRUE(mOutput.getReleasedLayersForTest().empty()); } TEST_F(OutputPostFramebufferTest, setReleasedLayersSentPresentFence) { SET_FLAG_FOR_TEST(com::android::graphics::surfaceflinger::flags::ce_fence_promise, true); ASSERT_TRUE(FlagManager::getInstance().ce_fence_promise()); mOutput.mState.isEnabled = true; mOutput.mState.usesClientComposition = true; Loading services/surfaceflinger/Layer.cpp +1 −58 Original line number Diff line number Diff line Loading @@ -751,54 +751,6 @@ void Layer::prepareReleaseCallbacks(ftl::Future<FenceResult> futureFenceResult, } } void Layer::onLayerDisplayed(ftl::SharedFuture<FenceResult> futureFenceResult, ui::LayerStack layerStack, std::function<FenceResult(FenceResult)>&& continuation) { sp<CallbackHandle> ch = findCallbackHandle(); if (!FlagManager::getInstance().screenshot_fence_preservation() && continuation) { futureFenceResult = ftl::Future(futureFenceResult).then(std::move(continuation)).share(); } if (ch != nullptr) { ch->previousReleaseCallbackId = mPreviousReleaseCallbackId; ch->previousSharedReleaseFences.emplace_back(std::move(futureFenceResult)); ch->name = mName; } else if (FlagManager::getInstance().screenshot_fence_preservation()) { // If we didn't get a release callback yet, e.g. some scenarios when capturing screenshots // asynchronously, then make sure we don't drop the fence. mPreviousReleaseFenceAndContinuations.emplace_back(std::move(futureFenceResult), std::move(continuation)); std::vector<FenceAndContinuation> mergedFences; sp<Fence> prevFence = nullptr; // For a layer that's frequently screenshotted, try to merge fences to make sure we don't // grow unbounded. for (const auto& futureAndContinuation : mPreviousReleaseFenceAndContinuations) { auto result = futureAndContinuation.future.wait_for(0s); if (result != std::future_status::ready) { mergedFences.emplace_back(futureAndContinuation); continue; } mergeFence(getDebugName(), futureAndContinuation.chain().get().value_or(Fence::NO_FENCE), prevFence); } if (prevFence != nullptr) { mergedFences.emplace_back(ftl::yield(FenceResult(std::move(prevFence))).share()); } mPreviousReleaseFenceAndContinuations.swap(mergedFences); } if (mBufferInfo.mBuffer) { mPreviouslyPresentedLayerStacks.push_back(layerStack); } if (mDrawingState.frameNumber > 0) { mDrawingState.previousFrameNumber = mDrawingState.frameNumber; } } void Layer::releasePendingBuffer(nsecs_t dequeueReadyTime) { for (const auto& handle : mDrawingState.callbackHandles) { handle->bufferReleaseChannel = mBufferReleaseChannel; Loading Loading @@ -1111,22 +1063,13 @@ bool Layer::setTransactionCompletedListeners(const std::vector<sp<CallbackHandle handle->acquireTimeOrFence = mCallbackHandleAcquireTimeOrFence; handle->frameNumber = mDrawingState.frameNumber; handle->previousFrameNumber = mDrawingState.previousFrameNumber; if (FlagManager::getInstance().ce_fence_promise() && mPreviousReleaseBufferEndpoint == handle->listener) { if (mPreviousReleaseBufferEndpoint == handle->listener) { // Add fence from previous screenshot now so that it can be dispatched to the // client. for (auto& [_, future] : mAdditionalPreviousReleaseFences) { handle->previousReleaseFences.emplace_back(std::move(future)); } mAdditionalPreviousReleaseFences.clear(); } else if (FlagManager::getInstance().screenshot_fence_preservation() && mPreviousReleaseBufferEndpoint == handle->listener) { // Add fences from previous screenshots now so that they can be dispatched to the // client. for (const auto& futureAndContinution : mPreviousReleaseFenceAndContinuations) { handle->previousSharedReleaseFences.emplace_back(futureAndContinution.chain()); } mPreviousReleaseFenceAndContinuations.clear(); } // Store so latched time and release fence can be set mDrawingState.callbackHandles.push_back(handle); Loading Loading
services/surfaceflinger/CompositionEngine/src/CompositionEngine.cpp +15 −17 Original line number Diff line number Diff line Loading @@ -198,7 +198,6 @@ void CompositionEngine::preComposition(CompositionRefreshArgs& args) { // these buffers and fire a NO_FENCE to release it. This ensures that all // promises for buffer releases are fulfilled at the end of composition. void CompositionEngine::postComposition(CompositionRefreshArgs& args) { if (FlagManager::getInstance().ce_fence_promise()) { SFTRACE_CALL(); ALOGV(__FUNCTION__); Loading @@ -219,7 +218,6 @@ void CompositionEngine::postComposition(CompositionRefreshArgs& args) { } } } } FeatureFlags CompositionEngine::getFeatureFlags() const { return {}; Loading
services/surfaceflinger/CompositionEngine/src/Output.cpp +2 −13 Original line number Diff line number Diff line Loading @@ -1610,13 +1610,7 @@ void Output::presentFrameAndReleaseLayers(bool flushEvenWhenDisabled) { releaseFence = Fence::merge("LayerRelease", releaseFence, frame.clientTargetAcquireFence); } if (FlagManager::getInstance().ce_fence_promise()) { layer->getLayerFE().setReleaseFence(releaseFence); } else { layer->getLayerFE() .onLayerDisplayed(ftl::yield<FenceResult>(std::move(releaseFence)).share(), outputState.layerFilter.layerStack); } } // We've got a list of layers needing fences, that are disjoint with Loading @@ -1624,12 +1618,7 @@ void Output::presentFrameAndReleaseLayers(bool flushEvenWhenDisabled) { // supply them with the present fence. for (auto& weakLayer : mReleasedLayers) { if (const auto layer = weakLayer.promote()) { if (FlagManager::getInstance().ce_fence_promise()) { layer->setReleaseFence(frame.presentFence); } else { layer->onLayerDisplayed(ftl::yield<FenceResult>(frame.presentFence).share(), outputState.layerFilter.layerStack); } } } Loading
services/surfaceflinger/CompositionEngine/tests/CompositionEngineTest.cpp +0 −5 Original line number Diff line number Diff line Loading @@ -30,8 +30,6 @@ #include "TimeStats/TimeStats.h" #include "gmock/gmock.h" #include <variant> using namespace com::android::graphics::surfaceflinger; namespace android::compositionengine { Loading Loading @@ -494,9 +492,6 @@ struct CompositionEnginePostCompositionTest : public CompositionEngineTest { }; TEST_F(CompositionEnginePostCompositionTest, postCompositionReleasesAllFences) { SET_FLAG_FOR_TEST(com::android::graphics::surfaceflinger::flags::ce_fence_promise, true); ASSERT_TRUE(FlagManager::getInstance().ce_fence_promise()); EXPECT_CALL(*mLayer1FE, getReleaseFencePromiseStatus) .WillOnce(Return(LayerFE::ReleaseFencePromiseStatus::FULFILLED)); EXPECT_CALL(*mLayer2FE, getReleaseFencePromiseStatus) Loading
services/surfaceflinger/CompositionEngine/tests/OutputTest.cpp +0 −134 Original line number Diff line number Diff line Loading @@ -34,7 +34,6 @@ #include <ui/Rect.h> #include <ui/Region.h> #include <cmath> #include <cstdint> #include <variant> Loading Loading @@ -3263,57 +3262,9 @@ TEST_F(OutputPostFramebufferTest, ifEnabledMustFlipThenPresentThenSendPresentCom mOutput.presentFrameAndReleaseLayers(kFlushEvenWhenDisabled); } TEST_F(OutputPostFramebufferTest, releaseFencesAreSentToLayerFE) { SET_FLAG_FOR_TEST(com::android::graphics::surfaceflinger::flags::ce_fence_promise, false); ASSERT_FALSE(FlagManager::getInstance().ce_fence_promise()); // Simulate getting release fences from each layer, and ensure they are passed to the // front-end layer interface for each layer correctly. mOutput.mState.isEnabled = true; // Create three unique fence instances sp<Fence> layer1Fence = sp<Fence>::make(); sp<Fence> layer2Fence = sp<Fence>::make(); sp<Fence> layer3Fence = sp<Fence>::make(); Output::FrameFences frameFences; frameFences.layerFences.emplace(&mLayer1.hwc2Layer, layer1Fence); frameFences.layerFences.emplace(&mLayer2.hwc2Layer, layer2Fence); frameFences.layerFences.emplace(&mLayer3.hwc2Layer, layer3Fence); EXPECT_CALL(mOutput, presentFrame()).WillOnce(Return(frameFences)); EXPECT_CALL(*mRenderSurface, onPresentDisplayCompleted()); // Compare the pointers values of each fence to make sure the correct ones // are passed. This happens to work with the current implementation, but // would not survive certain calls like Fence::merge() which would return a // new instance. EXPECT_CALL(*mLayer1.layerFE, onLayerDisplayed(_, _)) .WillOnce([&layer1Fence](ftl::SharedFuture<FenceResult> futureFenceResult, ui::LayerStack) { EXPECT_EQ(FenceResult(layer1Fence), futureFenceResult.get()); }); EXPECT_CALL(*mLayer2.layerFE, onLayerDisplayed(_, _)) .WillOnce([&layer2Fence](ftl::SharedFuture<FenceResult> futureFenceResult, ui::LayerStack) { EXPECT_EQ(FenceResult(layer2Fence), futureFenceResult.get()); }); EXPECT_CALL(*mLayer3.layerFE, onLayerDisplayed(_, _)) .WillOnce([&layer3Fence](ftl::SharedFuture<FenceResult> futureFenceResult, ui::LayerStack) { EXPECT_EQ(FenceResult(layer3Fence), futureFenceResult.get()); }); constexpr bool kFlushEvenWhenDisabled = false; mOutput.presentFrameAndReleaseLayers(kFlushEvenWhenDisabled); } TEST_F(OutputPostFramebufferTest, releaseFencesAreSetInLayerFE) { SET_FLAG_FOR_TEST(com::android::graphics::surfaceflinger::flags::ce_fence_promise, true); ASSERT_TRUE(FlagManager::getInstance().ce_fence_promise()); // Simulate getting release fences from each layer, and ensure they are passed to the // front-end layer interface for each layer correctly. mOutput.mState.isEnabled = true; // Create three unique fence instances Loading Loading @@ -3350,37 +3301,7 @@ TEST_F(OutputPostFramebufferTest, releaseFencesAreSetInLayerFE) { mOutput.presentFrameAndReleaseLayers(kFlushEvenWhenDisabled); } TEST_F(OutputPostFramebufferTest, releaseFencesIncludeClientTargetAcquireFence) { SET_FLAG_FOR_TEST(com::android::graphics::surfaceflinger::flags::ce_fence_promise, false); ASSERT_FALSE(FlagManager::getInstance().ce_fence_promise()); mOutput.mState.isEnabled = true; mOutput.mState.usesClientComposition = true; Output::FrameFences frameFences; frameFences.clientTargetAcquireFence = sp<Fence>::make(); frameFences.layerFences.emplace(&mLayer1.hwc2Layer, sp<Fence>::make()); frameFences.layerFences.emplace(&mLayer2.hwc2Layer, sp<Fence>::make()); frameFences.layerFences.emplace(&mLayer3.hwc2Layer, sp<Fence>::make()); EXPECT_CALL(mOutput, presentFrame()).WillOnce(Return(frameFences)); EXPECT_CALL(*mRenderSurface, onPresentDisplayCompleted()); // Fence::merge is called, and since none of the fences are actually valid, // Fence::NO_FENCE is returned and passed to each onLayerDisplayed() call. // This is the best we can do without creating a real kernel fence object. EXPECT_CALL(*mLayer1.layerFE, onLayerDisplayed).WillOnce(Return()); EXPECT_CALL(*mLayer2.layerFE, onLayerDisplayed).WillOnce(Return()); EXPECT_CALL(*mLayer3.layerFE, onLayerDisplayed).WillOnce(Return()); constexpr bool kFlushEvenWhenDisabled = false; mOutput.presentFrameAndReleaseLayers(kFlushEvenWhenDisabled); } TEST_F(OutputPostFramebufferTest, setReleaseFencesIncludeClientTargetAcquireFence) { SET_FLAG_FOR_TEST(com::android::graphics::surfaceflinger::flags::ce_fence_promise, true); ASSERT_TRUE(FlagManager::getInstance().ce_fence_promise()); mOutput.mState.isEnabled = true; mOutput.mState.usesClientComposition = true; Loading @@ -3403,62 +3324,7 @@ TEST_F(OutputPostFramebufferTest, setReleaseFencesIncludeClientTargetAcquireFenc mOutput.presentFrameAndReleaseLayers(kFlushEvenWhenDisabled); } TEST_F(OutputPostFramebufferTest, releasedLayersSentPresentFence) { SET_FLAG_FOR_TEST(com::android::graphics::surfaceflinger::flags::ce_fence_promise, false); ASSERT_FALSE(FlagManager::getInstance().ce_fence_promise()); mOutput.mState.isEnabled = true; mOutput.mState.usesClientComposition = true; // This should happen even if there are no (current) output layers. EXPECT_CALL(mOutput, getOutputLayerCount()).WillOnce(Return(0u)); // Load up the released layers with some mock instances sp<StrictMock<mock::LayerFE>> releasedLayer1 = sp<StrictMock<mock::LayerFE>>::make(); sp<StrictMock<mock::LayerFE>> releasedLayer2 = sp<StrictMock<mock::LayerFE>>::make(); sp<StrictMock<mock::LayerFE>> releasedLayer3 = sp<StrictMock<mock::LayerFE>>::make(); Output::ReleasedLayers layers; layers.push_back(releasedLayer1); layers.push_back(releasedLayer2); layers.push_back(releasedLayer3); mOutput.setReleasedLayers(std::move(layers)); // Set up a fake present fence sp<Fence> presentFence = sp<Fence>::make(); Output::FrameFences frameFences; frameFences.presentFence = presentFence; EXPECT_CALL(mOutput, presentFrame()).WillOnce(Return(frameFences)); EXPECT_CALL(*mRenderSurface, onPresentDisplayCompleted()); // Each released layer should be given the presentFence. EXPECT_CALL(*releasedLayer1, onLayerDisplayed(_, _)) .WillOnce([&presentFence](ftl::SharedFuture<FenceResult> futureFenceResult, ui::LayerStack) { EXPECT_EQ(FenceResult(presentFence), futureFenceResult.get()); }); EXPECT_CALL(*releasedLayer2, onLayerDisplayed(_, _)) .WillOnce([&presentFence](ftl::SharedFuture<FenceResult> futureFenceResult, ui::LayerStack) { EXPECT_EQ(FenceResult(presentFence), futureFenceResult.get()); }); EXPECT_CALL(*releasedLayer3, onLayerDisplayed(_, _)) .WillOnce([&presentFence](ftl::SharedFuture<FenceResult> futureFenceResult, ui::LayerStack) { EXPECT_EQ(FenceResult(presentFence), futureFenceResult.get()); }); constexpr bool kFlushEvenWhenDisabled = false; mOutput.presentFrameAndReleaseLayers(kFlushEvenWhenDisabled); // After the call the list of released layers should have been cleared. EXPECT_TRUE(mOutput.getReleasedLayersForTest().empty()); } TEST_F(OutputPostFramebufferTest, setReleasedLayersSentPresentFence) { SET_FLAG_FOR_TEST(com::android::graphics::surfaceflinger::flags::ce_fence_promise, true); ASSERT_TRUE(FlagManager::getInstance().ce_fence_promise()); mOutput.mState.isEnabled = true; mOutput.mState.usesClientComposition = true; Loading
services/surfaceflinger/Layer.cpp +1 −58 Original line number Diff line number Diff line Loading @@ -751,54 +751,6 @@ void Layer::prepareReleaseCallbacks(ftl::Future<FenceResult> futureFenceResult, } } void Layer::onLayerDisplayed(ftl::SharedFuture<FenceResult> futureFenceResult, ui::LayerStack layerStack, std::function<FenceResult(FenceResult)>&& continuation) { sp<CallbackHandle> ch = findCallbackHandle(); if (!FlagManager::getInstance().screenshot_fence_preservation() && continuation) { futureFenceResult = ftl::Future(futureFenceResult).then(std::move(continuation)).share(); } if (ch != nullptr) { ch->previousReleaseCallbackId = mPreviousReleaseCallbackId; ch->previousSharedReleaseFences.emplace_back(std::move(futureFenceResult)); ch->name = mName; } else if (FlagManager::getInstance().screenshot_fence_preservation()) { // If we didn't get a release callback yet, e.g. some scenarios when capturing screenshots // asynchronously, then make sure we don't drop the fence. mPreviousReleaseFenceAndContinuations.emplace_back(std::move(futureFenceResult), std::move(continuation)); std::vector<FenceAndContinuation> mergedFences; sp<Fence> prevFence = nullptr; // For a layer that's frequently screenshotted, try to merge fences to make sure we don't // grow unbounded. for (const auto& futureAndContinuation : mPreviousReleaseFenceAndContinuations) { auto result = futureAndContinuation.future.wait_for(0s); if (result != std::future_status::ready) { mergedFences.emplace_back(futureAndContinuation); continue; } mergeFence(getDebugName(), futureAndContinuation.chain().get().value_or(Fence::NO_FENCE), prevFence); } if (prevFence != nullptr) { mergedFences.emplace_back(ftl::yield(FenceResult(std::move(prevFence))).share()); } mPreviousReleaseFenceAndContinuations.swap(mergedFences); } if (mBufferInfo.mBuffer) { mPreviouslyPresentedLayerStacks.push_back(layerStack); } if (mDrawingState.frameNumber > 0) { mDrawingState.previousFrameNumber = mDrawingState.frameNumber; } } void Layer::releasePendingBuffer(nsecs_t dequeueReadyTime) { for (const auto& handle : mDrawingState.callbackHandles) { handle->bufferReleaseChannel = mBufferReleaseChannel; Loading Loading @@ -1111,22 +1063,13 @@ bool Layer::setTransactionCompletedListeners(const std::vector<sp<CallbackHandle handle->acquireTimeOrFence = mCallbackHandleAcquireTimeOrFence; handle->frameNumber = mDrawingState.frameNumber; handle->previousFrameNumber = mDrawingState.previousFrameNumber; if (FlagManager::getInstance().ce_fence_promise() && mPreviousReleaseBufferEndpoint == handle->listener) { if (mPreviousReleaseBufferEndpoint == handle->listener) { // Add fence from previous screenshot now so that it can be dispatched to the // client. for (auto& [_, future] : mAdditionalPreviousReleaseFences) { handle->previousReleaseFences.emplace_back(std::move(future)); } mAdditionalPreviousReleaseFences.clear(); } else if (FlagManager::getInstance().screenshot_fence_preservation() && mPreviousReleaseBufferEndpoint == handle->listener) { // Add fences from previous screenshots now so that they can be dispatched to the // client. for (const auto& futureAndContinution : mPreviousReleaseFenceAndContinuations) { handle->previousSharedReleaseFences.emplace_back(futureAndContinution.chain()); } mPreviousReleaseFenceAndContinuations.clear(); } // Store so latched time and release fence can be set mDrawingState.callbackHandles.push_back(handle); Loading