Merge "Output::presentFrameAndReleaseLayers: flush pending commands for OFF displays" into main
diff --git a/services/surfaceflinger/CompositionEngine/include/compositionengine/Output.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/Output.h
index d420838..191d475 100644
--- a/services/surfaceflinger/CompositionEngine/include/compositionengine/Output.h
+++ b/services/surfaceflinger/CompositionEngine/include/compositionengine/Output.h
@@ -306,7 +306,7 @@
virtual void finishFrame(GpuCompositionResult&&) = 0;
virtual std::optional<base::unique_fd> composeSurfaces(
const Region&, std::shared_ptr<renderengine::ExternalTexture>, base::unique_fd&) = 0;
- virtual void presentFrameAndReleaseLayers() = 0;
+ virtual void presentFrameAndReleaseLayers(bool flushEvenWhenDisabled) = 0;
virtual void renderCachedSets(const CompositionRefreshArgs&) = 0;
virtual bool chooseCompositionStrategy(
std::optional<android::HWComposer::DeviceRequestedChanges>*) = 0;
@@ -314,6 +314,7 @@
const std::optional<android::HWComposer::DeviceRequestedChanges>& changes) = 0;
virtual bool getSkipColorTransform() const = 0;
virtual FrameFences presentFrame() = 0;
+ virtual void executeCommands() = 0;
virtual std::vector<LayerFE::LayerSettings> generateClientCompositionRequests(
bool supportsProtectedContent, ui::Dataspace outputDataspace,
std::vector<LayerFE*> &outLayerRef) = 0;
diff --git a/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/Display.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/Display.h
index d87968f..d1eff24 100644
--- a/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/Display.h
+++ b/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/Display.h
@@ -60,6 +60,7 @@
void applyCompositionStrategy(const std::optional<DeviceRequestedChanges>&) override;
bool getSkipColorTransform() const override;
compositionengine::Output::FrameFences presentFrame() override;
+ void executeCommands() override;
void setExpensiveRenderingExpected(bool) override;
void finishFrame(GpuCompositionResult&&) override;
bool supportsOffloadPresent() const override;
diff --git a/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/Output.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/Output.h
index adcbbb9..9990a74 100644
--- a/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/Output.h
+++ b/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/Output.h
@@ -104,7 +104,7 @@
std::optional<base::unique_fd> composeSurfaces(const Region&,
std::shared_ptr<renderengine::ExternalTexture>,
base::unique_fd&) override;
- void presentFrameAndReleaseLayers() override;
+ void presentFrameAndReleaseLayers(bool flushEvenWhenDisabled) override;
void renderCachedSets(const CompositionRefreshArgs&) override;
void cacheClientCompositionRequests(uint32_t) override;
bool canPredictCompositionStrategy(const CompositionRefreshArgs&) override;
@@ -123,7 +123,8 @@
virtual std::future<bool> chooseCompositionStrategyAsync(
std::optional<android::HWComposer::DeviceRequestedChanges>*);
virtual void resetCompositionStrategy();
- virtual ftl::Future<std::monostate> presentFrameAndReleaseLayersAsync();
+ virtual ftl::Future<std::monostate> presentFrameAndReleaseLayersAsync(
+ bool flushEvenWhenDisabled);
protected:
std::unique_ptr<compositionengine::OutputLayer> createOutputLayer(const sp<LayerFE>&) const;
@@ -137,6 +138,7 @@
void applyCompositionStrategy(const std::optional<DeviceRequestedChanges>&) override{};
bool getSkipColorTransform() const override;
compositionengine::Output::FrameFences presentFrame() override;
+ void executeCommands() override {}
virtual renderengine::DisplaySettings generateClientCompositionDisplaySettings(
const std::shared_ptr<renderengine::ExternalTexture>& buffer) const;
std::vector<LayerFE::LayerSettings> generateClientCompositionRequests(
diff --git a/services/surfaceflinger/CompositionEngine/include/compositionengine/mock/Output.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/mock/Output.h
index 3f3deae..d5bf2b5 100644
--- a/services/surfaceflinger/CompositionEngine/include/compositionengine/mock/Output.h
+++ b/services/surfaceflinger/CompositionEngine/include/compositionengine/mock/Output.h
@@ -121,9 +121,10 @@
base::unique_fd&));
MOCK_CONST_METHOD0(getSkipColorTransform, bool());
- MOCK_METHOD0(presentFrameAndReleaseLayers, void());
+ MOCK_METHOD(void, presentFrameAndReleaseLayers, (bool flushEvenWhenDisabled));
MOCK_METHOD1(renderCachedSets, void(const CompositionRefreshArgs&));
MOCK_METHOD0(presentFrame, compositionengine::Output::FrameFences());
+ MOCK_METHOD(void, executeCommands, ());
MOCK_METHOD3(generateClientCompositionRequests,
std::vector<LayerFE::LayerSettings>(bool, ui::Dataspace, std::vector<compositionengine::LayerFE*>&));
diff --git a/services/surfaceflinger/CompositionEngine/src/Display.cpp b/services/surfaceflinger/CompositionEngine/src/Display.cpp
index 83b1b68..c1617d7 100644
--- a/services/surfaceflinger/CompositionEngine/src/Display.cpp
+++ b/services/surfaceflinger/CompositionEngine/src/Display.cpp
@@ -361,6 +361,15 @@
static_cast<ui::PixelFormat>(clientTargetProperty.clientTargetProperty.pixelFormat));
}
+void Display::executeCommands() {
+ const auto halDisplayIdOpt = HalDisplayId::tryCast(mId);
+ if (mIsDisconnected || !halDisplayIdOpt) {
+ return;
+ }
+
+ getCompositionEngine().getHwComposer().executeCommands(*halDisplayIdOpt);
+}
+
compositionengine::Output::FrameFences Display::presentFrame() {
auto fences = impl::Output::presentFrame();
diff --git a/services/surfaceflinger/CompositionEngine/src/Output.cpp b/services/surfaceflinger/CompositionEngine/src/Output.cpp
index 84f3f25..5b9a102 100644
--- a/services/surfaceflinger/CompositionEngine/src/Output.cpp
+++ b/services/surfaceflinger/CompositionEngine/src/Output.cpp
@@ -479,8 +479,9 @@
devOptRepaintFlash(refreshArgs);
finishFrame(std::move(result));
ftl::Future<std::monostate> future;
+ const bool flushEvenWhenDisabled = !refreshArgs.bufferIdsToUncache.empty();
if (mOffloadPresent) {
- future = presentFrameAndReleaseLayersAsync();
+ future = presentFrameAndReleaseLayersAsync(flushEvenWhenDisabled);
// Only offload for this frame. The next frame will determine whether it
// needs to be offloaded. Leave the HwcAsyncWorker in place. For one thing,
@@ -488,7 +489,7 @@
// we don't want to churn.
mOffloadPresent = false;
} else {
- presentFrameAndReleaseLayers();
+ presentFrameAndReleaseLayers(flushEvenWhenDisabled);
future = ftl::yield<std::monostate>({});
}
renderCachedSets(refreshArgs);
@@ -1100,9 +1101,9 @@
finishPrepareFrame();
}
-ftl::Future<std::monostate> Output::presentFrameAndReleaseLayersAsync() {
+ftl::Future<std::monostate> Output::presentFrameAndReleaseLayersAsync(bool flushEvenWhenDisabled) {
return ftl::Future<bool>(std::move(mHwComposerAsyncWorker->send([&]() {
- presentFrameAndReleaseLayers();
+ presentFrameAndReleaseLayers(flushEvenWhenDisabled);
return true;
})))
.then([](bool) { return std::monostate{}; });
@@ -1177,7 +1178,8 @@
}
}
- presentFrameAndReleaseLayers();
+ constexpr bool kFlushEvenWhenDisabled = false;
+ presentFrameAndReleaseLayers(kFlushEvenWhenDisabled);
std::this_thread::sleep_for(*refreshArgs.devOptFlashDirtyRegionsDelay);
@@ -1567,11 +1569,16 @@
return false;
}
-void Output::presentFrameAndReleaseLayers() {
+void Output::presentFrameAndReleaseLayers(bool flushEvenWhenDisabled) {
ATRACE_FORMAT("%s for %s", __func__, mNamePlusId.c_str());
ALOGV(__FUNCTION__);
if (!getState().isEnabled) {
+ if (flushEvenWhenDisabled && FlagManager::getInstance().flush_buffer_slots_to_uncache()) {
+ // Some commands, like clearing buffer slots, should still be executed
+ // even if the display is not enabled.
+ executeCommands();
+ }
return;
}
diff --git a/services/surfaceflinger/CompositionEngine/tests/DisplayTest.cpp b/services/surfaceflinger/CompositionEngine/tests/DisplayTest.cpp
index a95a5c6..39163ea 100644
--- a/services/surfaceflinger/CompositionEngine/tests/DisplayTest.cpp
+++ b/services/surfaceflinger/CompositionEngine/tests/DisplayTest.cpp
@@ -1067,8 +1067,8 @@
EXPECT_CALL(mHwComposer, presentAndGetReleaseFences(_, _));
EXPECT_CALL(*mDisplaySurface, onFrameCommitted());
-
- mDisplay->presentFrameAndReleaseLayers();
+ constexpr bool kFlushEvenWhenDisabled = false;
+ mDisplay->presentFrameAndReleaseLayers(kFlushEvenWhenDisabled);
}
} // namespace
diff --git a/services/surfaceflinger/CompositionEngine/tests/MockHWComposer.h b/services/surfaceflinger/CompositionEngine/tests/MockHWComposer.h
index 4612117..629d9f2 100644
--- a/services/surfaceflinger/CompositionEngine/tests/MockHWComposer.h
+++ b/services/surfaceflinger/CompositionEngine/tests/MockHWComposer.h
@@ -63,6 +63,7 @@
(override));
MOCK_METHOD2(presentAndGetReleaseFences,
status_t(HalDisplayId, std::optional<std::chrono::steady_clock::time_point>));
+ MOCK_METHOD(status_t, executeCommands, (HalDisplayId));
MOCK_METHOD2(setPowerMode, status_t(PhysicalDisplayId, hal::PowerMode));
MOCK_METHOD2(setActiveConfig, status_t(HalDisplayId, size_t));
MOCK_METHOD2(setColorTransform, status_t(HalDisplayId, const mat4&));
diff --git a/services/surfaceflinger/CompositionEngine/tests/OutputTest.cpp b/services/surfaceflinger/CompositionEngine/tests/OutputTest.cpp
index 0dc3c9f..c34168d 100644
--- a/services/surfaceflinger/CompositionEngine/tests/OutputTest.cpp
+++ b/services/surfaceflinger/CompositionEngine/tests/OutputTest.cpp
@@ -2014,7 +2014,7 @@
MOCK_METHOD0(prepareFrameAsync, GpuCompositionResult());
MOCK_METHOD1(devOptRepaintFlash, void(const compositionengine::CompositionRefreshArgs&));
MOCK_METHOD1(finishFrame, void(GpuCompositionResult&&));
- MOCK_METHOD0(presentFrameAndReleaseLayers, void());
+ MOCK_METHOD(void, presentFrameAndReleaseLayers, (bool flushEvenWhenDisabled), (override));
MOCK_METHOD1(renderCachedSets, void(const compositionengine::CompositionRefreshArgs&));
MOCK_METHOD1(canPredictCompositionStrategy, bool(const CompositionRefreshArgs&));
MOCK_METHOD(void, setHintSessionRequiresRenderEngine, (bool requiresRenderEngine),
@@ -2046,7 +2046,7 @@
EXPECT_CALL(mOutput, prepareFrame());
EXPECT_CALL(mOutput, devOptRepaintFlash(Ref(args)));
EXPECT_CALL(mOutput, finishFrame(_));
- EXPECT_CALL(mOutput, presentFrameAndReleaseLayers());
+ EXPECT_CALL(mOutput, presentFrameAndReleaseLayers(false));
EXPECT_CALL(mOutput, renderCachedSets(Ref(args)));
mOutput.present(args);
@@ -2067,7 +2067,7 @@
EXPECT_CALL(mOutput, prepareFrameAsync());
EXPECT_CALL(mOutput, devOptRepaintFlash(Ref(args)));
EXPECT_CALL(mOutput, finishFrame(_));
- EXPECT_CALL(mOutput, presentFrameAndReleaseLayers());
+ EXPECT_CALL(mOutput, presentFrameAndReleaseLayers(false));
EXPECT_CALL(mOutput, renderCachedSets(Ref(args)));
mOutput.present(args);
@@ -2913,7 +2913,7 @@
std::optional<base::unique_fd>(const Region&,
std::shared_ptr<renderengine::ExternalTexture>,
base::unique_fd&));
- MOCK_METHOD0(presentFrameAndReleaseLayers, void());
+ MOCK_METHOD(void, presentFrameAndReleaseLayers, (bool flushEvenWhenDisabled));
MOCK_METHOD0(prepareFrame, void());
MOCK_METHOD0(updateProtectedContentState, void());
MOCK_METHOD2(dequeueRenderBuffer,
@@ -2950,7 +2950,8 @@
mOutput.mState.isEnabled = false;
InSequence seq;
- EXPECT_CALL(mOutput, presentFrameAndReleaseLayers());
+ constexpr bool kFlushEvenWhenDisabled = false;
+ EXPECT_CALL(mOutput, presentFrameAndReleaseLayers(kFlushEvenWhenDisabled));
EXPECT_CALL(mOutput, prepareFrame());
mOutput.devOptRepaintFlash(mRefreshArgs);
@@ -2962,7 +2963,8 @@
InSequence seq;
EXPECT_CALL(mOutput, getDirtyRegion()).WillOnce(Return(kEmptyRegion));
- EXPECT_CALL(mOutput, presentFrameAndReleaseLayers());
+ constexpr bool kFlushEvenWhenDisabled = false;
+ EXPECT_CALL(mOutput, presentFrameAndReleaseLayers(kFlushEvenWhenDisabled));
EXPECT_CALL(mOutput, prepareFrame());
mOutput.devOptRepaintFlash(mRefreshArgs);
@@ -2978,7 +2980,8 @@
EXPECT_CALL(mOutput, dequeueRenderBuffer(_, _));
EXPECT_CALL(mOutput, composeSurfaces(RegionEq(kNotEmptyRegion), _, _));
EXPECT_CALL(*mRenderSurface, queueBuffer(_, 1.f));
- EXPECT_CALL(mOutput, presentFrameAndReleaseLayers());
+ constexpr bool kFlushEvenWhenDisabled = false;
+ EXPECT_CALL(mOutput, presentFrameAndReleaseLayers(kFlushEvenWhenDisabled));
EXPECT_CALL(mOutput, prepareFrame());
mOutput.devOptRepaintFlash(mRefreshArgs);
@@ -2996,7 +2999,7 @@
std::optional<base::unique_fd>(const Region&,
std::shared_ptr<renderengine::ExternalTexture>,
base::unique_fd&));
- MOCK_METHOD0(presentFrameAndReleaseLayers, void());
+ MOCK_METHOD(void, presentFrameAndReleaseLayers, (bool flushEvenWhenDisabled), (override));
MOCK_METHOD0(updateProtectedContentState, void());
MOCK_METHOD2(dequeueRenderBuffer,
bool(base::unique_fd*, std::shared_ptr<renderengine::ExternalTexture>*));
@@ -3139,7 +3142,8 @@
struct OutputPartialMock : public OutputPartialMockBase {
// Sets up the helper functions called by the function under test to use
// mock implementations.
- MOCK_METHOD0(presentFrame, compositionengine::Output::FrameFences());
+ MOCK_METHOD(compositionengine::Output::FrameFences, presentFrame, ());
+ MOCK_METHOD(void, executeCommands, ());
};
struct Layer {
@@ -3177,9 +3181,67 @@
};
TEST_F(OutputPostFramebufferTest, ifNotEnabledDoesNothing) {
+ SET_FLAG_FOR_TEST(com::android::graphics::surfaceflinger::flags::flush_buffer_slots_to_uncache,
+ true);
mOutput.mState.isEnabled = false;
+ EXPECT_CALL(mOutput, executeCommands()).Times(0);
+ EXPECT_CALL(mOutput, presentFrame()).Times(0);
- mOutput.presentFrameAndReleaseLayers();
+ constexpr bool kFlushEvenWhenDisabled = false;
+ mOutput.presentFrameAndReleaseLayers(kFlushEvenWhenDisabled);
+}
+
+TEST_F(OutputPostFramebufferTest, ifNotEnabledExecutesCommandsIfFlush) {
+ SET_FLAG_FOR_TEST(com::android::graphics::surfaceflinger::flags::flush_buffer_slots_to_uncache,
+ true);
+ mOutput.mState.isEnabled = false;
+ EXPECT_CALL(mOutput, executeCommands());
+ EXPECT_CALL(mOutput, presentFrame()).Times(0);
+
+ constexpr bool kFlushEvenWhenDisabled = true;
+ mOutput.presentFrameAndReleaseLayers(kFlushEvenWhenDisabled);
+}
+
+TEST_F(OutputPostFramebufferTest, ifEnabledDoNotExecuteCommands) {
+ SET_FLAG_FOR_TEST(com::android::graphics::surfaceflinger::flags::flush_buffer_slots_to_uncache,
+ true);
+ mOutput.mState.isEnabled = true;
+
+ compositionengine::Output::FrameFences frameFences;
+
+ EXPECT_CALL(mOutput, getOutputLayerCount()).WillOnce(Return(0u));
+
+ // This should only be called for disabled outputs. This test's goal is to verify this line;
+ // the other expectations help satisfy the StrictMocks.
+ EXPECT_CALL(mOutput, executeCommands()).Times(0);
+
+ EXPECT_CALL(mOutput, presentFrame()).WillOnce(Return(frameFences));
+ EXPECT_CALL(*mRenderSurface, onPresentDisplayCompleted());
+
+ constexpr bool kFlushEvenWhenDisabled = true;
+ mOutput.presentFrameAndReleaseLayers(kFlushEvenWhenDisabled);
+}
+
+TEST_F(OutputPostFramebufferTest, ifEnabledDoNotExecuteCommands2) {
+ // Same test as ifEnabledDoNotExecuteCommands, but with this variable set to false.
+ constexpr bool kFlushEvenWhenDisabled = false;
+
+ SET_FLAG_FOR_TEST(com::android::graphics::surfaceflinger::flags::flush_buffer_slots_to_uncache,
+ true);
+ mOutput.mState.isEnabled = true;
+
+ compositionengine::Output::FrameFences frameFences;
+
+ EXPECT_CALL(mOutput, getOutputLayerCount()).WillOnce(Return(0u));
+
+ // This should only be called for disabled outputs. This test's goal is to verify this line;
+ // the other expectations help satisfy the StrictMocks.
+ EXPECT_CALL(mOutput, executeCommands()).Times(0);
+
+ EXPECT_CALL(mOutput, presentFrame()).WillOnce(Return(frameFences));
+ EXPECT_CALL(*mRenderSurface, onPresentDisplayCompleted());
+
+ mOutput.presentFrameAndReleaseLayers(kFlushEvenWhenDisabled);
}
TEST_F(OutputPostFramebufferTest, ifEnabledMustFlipThenPresentThenSendPresentCompleted) {
@@ -3197,7 +3259,8 @@
EXPECT_CALL(mOutput, presentFrame()).WillOnce(Return(frameFences));
EXPECT_CALL(*mRenderSurface, onPresentDisplayCompleted());
- mOutput.presentFrameAndReleaseLayers();
+ constexpr bool kFlushEvenWhenDisabled = true;
+ mOutput.presentFrameAndReleaseLayers(kFlushEvenWhenDisabled);
}
TEST_F(OutputPostFramebufferTest, releaseFencesAreSentToLayerFE) {
@@ -3241,7 +3304,8 @@
EXPECT_EQ(FenceResult(layer3Fence), futureFenceResult.get());
});
- mOutput.presentFrameAndReleaseLayers();
+ constexpr bool kFlushEvenWhenDisabled = false;
+ mOutput.presentFrameAndReleaseLayers(kFlushEvenWhenDisabled);
}
TEST_F(OutputPostFramebufferTest, releaseFencesAreSetInLayerFE) {
@@ -3282,7 +3346,8 @@
EXPECT_EQ(FenceResult(layer3Fence), releaseFence);
});
- mOutput.presentFrameAndReleaseLayers();
+ constexpr bool kFlushEvenWhenDisabled = false;
+ mOutput.presentFrameAndReleaseLayers(kFlushEvenWhenDisabled);
}
TEST_F(OutputPostFramebufferTest, releaseFencesIncludeClientTargetAcquireFence) {
@@ -3308,7 +3373,8 @@
EXPECT_CALL(*mLayer2.layerFE, onLayerDisplayed).WillOnce(Return());
EXPECT_CALL(*mLayer3.layerFE, onLayerDisplayed).WillOnce(Return());
- mOutput.presentFrameAndReleaseLayers();
+ constexpr bool kFlushEvenWhenDisabled = false;
+ mOutput.presentFrameAndReleaseLayers(kFlushEvenWhenDisabled);
}
TEST_F(OutputPostFramebufferTest, setReleaseFencesIncludeClientTargetAcquireFence) {
@@ -3333,7 +3399,8 @@
EXPECT_CALL(*mLayer1.layerFE, setReleaseFence).WillOnce(Return());
EXPECT_CALL(*mLayer2.layerFE, setReleaseFence).WillOnce(Return());
EXPECT_CALL(*mLayer3.layerFE, setReleaseFence).WillOnce(Return());
- mOutput.presentFrameAndReleaseLayers();
+ constexpr bool kFlushEvenWhenDisabled = false;
+ mOutput.presentFrameAndReleaseLayers(kFlushEvenWhenDisabled);
}
TEST_F(OutputPostFramebufferTest, releasedLayersSentPresentFence) {
@@ -3381,7 +3448,8 @@
EXPECT_EQ(FenceResult(presentFence), futureFenceResult.get());
});
- mOutput.presentFrameAndReleaseLayers();
+ constexpr bool kFlushEvenWhenDisabled = false;
+ mOutput.presentFrameAndReleaseLayers(kFlushEvenWhenDisabled);
// After the call the list of released layers should have been cleared.
EXPECT_TRUE(mOutput.getReleasedLayersForTest().empty());
@@ -3429,7 +3497,8 @@
EXPECT_EQ(FenceResult(presentFence), fenceResult);
});
- mOutput.presentFrameAndReleaseLayers();
+ constexpr bool kFlushEvenWhenDisabled = false;
+ mOutput.presentFrameAndReleaseLayers(kFlushEvenWhenDisabled);
// After the call the list of released layers should have been cleared.
EXPECT_TRUE(mOutput.getReleasedLayersForTest().empty());
@@ -5272,8 +5341,9 @@
struct OutputPartialMock : public OutputPrepareFrameAsyncTest::OutputPartialMock {
// Set up the helper functions called by the function under test to use
// mock implementations.
- MOCK_METHOD0(presentFrameAndReleaseLayers, void());
- MOCK_METHOD0(presentFrameAndReleaseLayersAsync, ftl::Future<std::monostate>());
+ MOCK_METHOD(void, presentFrameAndReleaseLayers, (bool flushEvenWhenDisabled));
+ MOCK_METHOD(ftl::Future<std::monostate>, presentFrameAndReleaseLayersAsync,
+ (bool flushEvenWhenDisabled));
};
OutputPresentFrameAndReleaseLayersAsyncTest() {
mOutput->setDisplayColorProfileForTest(
@@ -5290,16 +5360,16 @@
};
TEST_F(OutputPresentFrameAndReleaseLayersAsyncTest, notCalledWhenNotRequested) {
- EXPECT_CALL(*mOutput, presentFrameAndReleaseLayersAsync()).Times(0);
- EXPECT_CALL(*mOutput, presentFrameAndReleaseLayers()).Times(1);
+ EXPECT_CALL(*mOutput, presentFrameAndReleaseLayersAsync(_)).Times(0);
+ EXPECT_CALL(*mOutput, presentFrameAndReleaseLayers(_)).Times(1);
mOutput->present(mRefreshArgs);
}
TEST_F(OutputPresentFrameAndReleaseLayersAsyncTest, calledWhenRequested) {
- EXPECT_CALL(*mOutput, presentFrameAndReleaseLayersAsync())
+ EXPECT_CALL(*mOutput, presentFrameAndReleaseLayersAsync(false))
.WillOnce(Return(ftl::yield<std::monostate>({})));
- EXPECT_CALL(*mOutput, presentFrameAndReleaseLayers()).Times(0);
+ EXPECT_CALL(*mOutput, presentFrameAndReleaseLayers(_)).Times(0);
mOutput->offloadPresentNextFrame();
mOutput->present(mRefreshArgs);
@@ -5307,9 +5377,10 @@
TEST_F(OutputPresentFrameAndReleaseLayersAsyncTest, calledForOneFrame) {
::testing::InSequence inseq;
- EXPECT_CALL(*mOutput, presentFrameAndReleaseLayersAsync())
+ constexpr bool kFlushEvenWhenDisabled = false;
+ EXPECT_CALL(*mOutput, presentFrameAndReleaseLayersAsync(kFlushEvenWhenDisabled))
.WillOnce(Return(ftl::yield<std::monostate>({})));
- EXPECT_CALL(*mOutput, presentFrameAndReleaseLayers()).Times(1);
+ EXPECT_CALL(*mOutput, presentFrameAndReleaseLayers(kFlushEvenWhenDisabled)).Times(1);
mOutput->offloadPresentNextFrame();
mOutput->present(mRefreshArgs);
@@ -5390,5 +5461,59 @@
mOutput.updateProtectedContentState();
}
+struct OutputPresentFrameAndReleaseLayersTest : public testing::Test {
+ struct OutputPartialMock : public OutputPartialMockBase {
+ // Sets up the helper functions called by the function under test (and functions we can
+ // ignore) to use mock implementations.
+ MOCK_METHOD1(updateColorProfile, void(const compositionengine::CompositionRefreshArgs&));
+ MOCK_METHOD1(updateCompositionState,
+ void(const compositionengine::CompositionRefreshArgs&));
+ MOCK_METHOD0(planComposition, void());
+ MOCK_METHOD1(writeCompositionState, void(const compositionengine::CompositionRefreshArgs&));
+ MOCK_METHOD1(setColorTransform, void(const compositionengine::CompositionRefreshArgs&));
+ MOCK_METHOD0(beginFrame, void());
+ MOCK_METHOD0(prepareFrame, void());
+ MOCK_METHOD0(prepareFrameAsync, GpuCompositionResult());
+ MOCK_METHOD1(devOptRepaintFlash, void(const compositionengine::CompositionRefreshArgs&));
+ MOCK_METHOD1(finishFrame, void(GpuCompositionResult&&));
+ MOCK_METHOD(void, presentFrameAndReleaseLayers, (bool flushEvenWhenDisabled), (override));
+ MOCK_METHOD1(renderCachedSets, void(const compositionengine::CompositionRefreshArgs&));
+ MOCK_METHOD1(canPredictCompositionStrategy, bool(const CompositionRefreshArgs&));
+ MOCK_METHOD(void, setHintSessionRequiresRenderEngine, (bool requiresRenderEngine),
+ (override));
+ MOCK_METHOD(bool, isPowerHintSessionEnabled, (), (override));
+ MOCK_METHOD(bool, isPowerHintSessionGpuReportingEnabled, (), (override));
+ };
+
+ OutputPresentFrameAndReleaseLayersTest() {
+ EXPECT_CALL(mOutput, isPowerHintSessionEnabled()).WillRepeatedly(Return(true));
+ EXPECT_CALL(mOutput, isPowerHintSessionGpuReportingEnabled()).WillRepeatedly(Return(true));
+ }
+
+ NiceMock<OutputPartialMock> mOutput;
+};
+
+TEST_F(OutputPresentFrameAndReleaseLayersTest, noBuffersToUncache) {
+ CompositionRefreshArgs args;
+ ASSERT_TRUE(args.bufferIdsToUncache.empty());
+ mOutput.editState().isEnabled = false;
+
+ constexpr bool kFlushEvenWhenDisabled = false;
+ EXPECT_CALL(mOutput, presentFrameAndReleaseLayers(kFlushEvenWhenDisabled));
+
+ mOutput.present(args);
+}
+
+TEST_F(OutputPresentFrameAndReleaseLayersTest, buffersToUncache) {
+ CompositionRefreshArgs args;
+ args.bufferIdsToUncache.push_back(1);
+ mOutput.editState().isEnabled = false;
+
+ constexpr bool kFlushEvenWhenDisabled = true;
+ EXPECT_CALL(mOutput, presentFrameAndReleaseLayers(kFlushEvenWhenDisabled));
+
+ mOutput.present(args);
+}
+
} // namespace
} // namespace android::compositionengine
diff --git a/services/surfaceflinger/DisplayHardware/HWComposer.cpp b/services/surfaceflinger/DisplayHardware/HWComposer.cpp
index 3cfb9ca..3d285a8 100644
--- a/services/surfaceflinger/DisplayHardware/HWComposer.cpp
+++ b/services/surfaceflinger/DisplayHardware/HWComposer.cpp
@@ -600,6 +600,13 @@
return NO_ERROR;
}
+status_t HWComposer::executeCommands(HalDisplayId displayId) {
+ auto& hwcDisplay = mDisplayData[displayId].hwcDisplay;
+ auto error = static_cast<hal::Error>(mComposer->executeCommands(hwcDisplay->getId()));
+ RETURN_IF_HWC_ERROR_FOR("executeCommands", error, displayId, UNKNOWN_ERROR);
+ return NO_ERROR;
+}
+
status_t HWComposer::setPowerMode(PhysicalDisplayId displayId, hal::PowerMode mode) {
RETURN_IF_INVALID_DISPLAY(displayId, BAD_INDEX);
diff --git a/services/surfaceflinger/DisplayHardware/HWComposer.h b/services/surfaceflinger/DisplayHardware/HWComposer.h
index bc32cda..9368b7b 100644
--- a/services/surfaceflinger/DisplayHardware/HWComposer.h
+++ b/services/surfaceflinger/DisplayHardware/HWComposer.h
@@ -160,6 +160,8 @@
HalDisplayId,
std::optional<std::chrono::steady_clock::time_point> earliestPresentTime) = 0;
+ virtual status_t executeCommands(HalDisplayId) = 0;
+
// set power mode
virtual status_t setPowerMode(PhysicalDisplayId, hal::PowerMode) = 0;
@@ -361,6 +363,8 @@
HalDisplayId,
std::optional<std::chrono::steady_clock::time_point> earliestPresentTime) override;
+ status_t executeCommands(HalDisplayId) override;
+
// set power mode
status_t setPowerMode(PhysicalDisplayId, hal::PowerMode mode) override;
diff --git a/services/surfaceflinger/common/FlagManager.cpp b/services/surfaceflinger/common/FlagManager.cpp
index 57b170f..b78809a 100644
--- a/services/surfaceflinger/common/FlagManager.cpp
+++ b/services/surfaceflinger/common/FlagManager.cpp
@@ -148,6 +148,7 @@
DUMP_READ_ONLY_FLAG(commit_not_composited);
DUMP_READ_ONLY_FLAG(local_tonemap_screenshots);
DUMP_READ_ONLY_FLAG(override_trusted_overlay);
+ DUMP_READ_ONLY_FLAG(flush_buffer_slots_to_uncache);
#undef DUMP_READ_ONLY_FLAG
#undef DUMP_SERVER_FLAG
@@ -246,6 +247,7 @@
FLAG_MANAGER_READ_ONLY_FLAG(commit_not_composited, "");
FLAG_MANAGER_READ_ONLY_FLAG(local_tonemap_screenshots, "debug.sf.local_tonemap_screenshots");
FLAG_MANAGER_READ_ONLY_FLAG(override_trusted_overlay, "");
+FLAG_MANAGER_READ_ONLY_FLAG(flush_buffer_slots_to_uncache, "");
/// Trunk stable server flags ///
FLAG_MANAGER_SERVER_FLAG(refresh_rate_overlay_on_external_display, "")
diff --git a/services/surfaceflinger/common/include/common/FlagManager.h b/services/surfaceflinger/common/include/common/FlagManager.h
index 9517ff7..302d311 100644
--- a/services/surfaceflinger/common/include/common/FlagManager.h
+++ b/services/surfaceflinger/common/include/common/FlagManager.h
@@ -87,6 +87,7 @@
bool commit_not_composited() const;
bool local_tonemap_screenshots() const;
bool override_trusted_overlay() const;
+ bool flush_buffer_slots_to_uncache() const;
protected:
// overridden for unit tests
diff --git a/services/surfaceflinger/surfaceflinger_flags_new.aconfig b/services/surfaceflinger/surfaceflinger_flags_new.aconfig
index 02d8819..0772891 100644
--- a/services/surfaceflinger/surfaceflinger_flags_new.aconfig
+++ b/services/surfaceflinger/surfaceflinger_flags_new.aconfig
@@ -55,6 +55,17 @@
} # detached_mirror
flag {
+ name: "flush_buffer_slots_to_uncache"
+ namespace: "core_graphics"
+ description: "Flush DisplayCommands for disabled displays in order to uncache requested buffers."
+ bug: "330806421"
+ is_fixed_read_only: true
+ metadata {
+ purpose: PURPOSE_BUGFIX
+ }
+} # flush_buffer_slots_to_uncache
+
+flag {
name: "frame_rate_category_mrr"
namespace: "core_graphics"
description: "Enable to use frame rate category and newer frame rate votes such as GTE in SurfaceFlinger scheduler, to guard dVRR changes from MRR devices"