Loading services/surfaceflinger/CompositionEngine/include/compositionengine/impl/Output.h +5 −0 Original line number Diff line number Diff line Loading @@ -152,6 +152,8 @@ protected: virtual const compositionengine::CompositionEngine& getCompositionEngine() const = 0; virtual void dumpState(std::string& out) const = 0; bool mustRecompose() const; private: void dirtyEntireOutput(); compositionengine::OutputLayer* findLayerRequestingBackgroundComposition() const; Loading @@ -170,6 +172,9 @@ private: std::unique_ptr<ClientCompositionRequestCache> mClientCompositionRequestCache; std::unique_ptr<planner::Planner> mPlanner; std::unique_ptr<HwcAsyncWorker> mHwComposerAsyncWorker; // Whether the content must be recomposed this frame. bool mMustRecompose = false; }; // This template factory function standardizes the implementation details of the Loading services/surfaceflinger/CompositionEngine/src/Display.cpp +1 −1 Original line number Diff line number Diff line Loading @@ -426,7 +426,7 @@ void Display::finishFrame(const compositionengine::CompositionRefreshArgs& refre // 1) It is being handled by hardware composer, which may need this to // keep its virtual display state machine in sync, or // 2) There is work to be done (the dirty region isn't empty) if (GpuVirtualDisplayId::tryCast(mId) && getDirtyRegion().isEmpty()) { if (GpuVirtualDisplayId::tryCast(mId) && !mustRecompose()) { ALOGV("Skipping display composition"); return; } Loading services/surfaceflinger/CompositionEngine/src/Output.cpp +10 −6 Original line number Diff line number Diff line Loading @@ -977,17 +977,17 @@ void Output::beginFrame() { // frame, then nothing more until we get new layers. // - When a display is created with a private layer stack, we won't // emit any black frames until a layer is added to the layer stack. const bool mustRecompose = dirty && !(empty && wasEmpty); mMustRecompose = dirty && !(empty && wasEmpty); const char flagPrefix[] = {'-', '+'}; static_cast<void>(flagPrefix); ALOGV_IF("%s: %s composition for %s (%cdirty %cempty %cwasEmpty)", __FUNCTION__, mustRecompose ? "doing" : "skipping", getName().c_str(), flagPrefix[dirty], ALOGV("%s: %s composition for %s (%cdirty %cempty %cwasEmpty)", __func__, mMustRecompose ? "doing" : "skipping", getName().c_str(), flagPrefix[dirty], flagPrefix[empty], flagPrefix[wasEmpty]); mRenderSurface->beginFrame(mustRecompose); mRenderSurface->beginFrame(mMustRecompose); if (mustRecompose) { if (mMustRecompose) { outputState.lastCompositionHadVisibleLayers = !empty; } } Loading Loading @@ -1590,5 +1590,9 @@ void Output::finishPrepareFrame() { mRenderSurface->prepareFrame(state.usesClientComposition, state.usesDeviceComposition); } bool Output::mustRecompose() const { return mMustRecompose; } } // namespace impl } // namespace android::compositionengine services/surfaceflinger/CompositionEngine/tests/DisplayTest.cpp +29 −1 Original line number Diff line number Diff line Loading @@ -971,16 +971,40 @@ TEST_F(DisplayFinishFrameTest, skipsCompositionIfNotDirty) { // We expect no calls to queueBuffer if composition was skipped. EXPECT_CALL(*renderSurface, queueBuffer(_)).Times(0); EXPECT_CALL(*renderSurface, beginFrame(false)); gpuDisplay->editState().isEnabled = true; gpuDisplay->editState().usesClientComposition = false; gpuDisplay->editState().layerStackSpace.setContent(Rect(0, 0, 1, 1)); gpuDisplay->editState().dirtyRegion = Region::INVALID_REGION; gpuDisplay->editState().lastCompositionHadVisibleLayers = true; gpuDisplay->beginFrame(); gpuDisplay->finishFrame({}, std::move(mResultWithoutBuffer)); } TEST_F(DisplayFinishFrameTest, performsCompositionIfDirty) { TEST_F(DisplayFinishFrameTest, skipsCompositionIfEmpty) { auto args = getDisplayCreationArgsForGpuVirtualDisplay(); std::shared_ptr<impl::Display> gpuDisplay = impl::createDisplay(mCompositionEngine, args); mock::RenderSurface* renderSurface = new StrictMock<mock::RenderSurface>(); gpuDisplay->setRenderSurfaceForTest(std::unique_ptr<RenderSurface>(renderSurface)); // We expect no calls to queueBuffer if composition was skipped. EXPECT_CALL(*renderSurface, queueBuffer(_)).Times(0); EXPECT_CALL(*renderSurface, beginFrame(false)); gpuDisplay->editState().isEnabled = true; gpuDisplay->editState().usesClientComposition = false; gpuDisplay->editState().layerStackSpace.setContent(Rect(0, 0, 1, 1)); gpuDisplay->editState().dirtyRegion = Region(Rect(0, 0, 1, 1)); gpuDisplay->editState().lastCompositionHadVisibleLayers = false; gpuDisplay->beginFrame(); gpuDisplay->finishFrame({}, std::move(mResultWithoutBuffer)); } TEST_F(DisplayFinishFrameTest, performsCompositionIfDirtyAndNotEmpty) { auto args = getDisplayCreationArgsForGpuVirtualDisplay(); std::shared_ptr<impl::Display> gpuDisplay = impl::createDisplay(mCompositionEngine, args); Loading @@ -989,11 +1013,15 @@ TEST_F(DisplayFinishFrameTest, performsCompositionIfDirty) { // We expect a single call to queueBuffer when composition is not skipped. EXPECT_CALL(*renderSurface, queueBuffer(_)).Times(1); EXPECT_CALL(*renderSurface, beginFrame(true)); gpuDisplay->editState().isEnabled = true; gpuDisplay->editState().usesClientComposition = false; gpuDisplay->editState().layerStackSpace.setContent(Rect(0, 0, 1, 1)); gpuDisplay->editState().dirtyRegion = Region(Rect(0, 0, 1, 1)); gpuDisplay->editState().lastCompositionHadVisibleLayers = true; gpuDisplay->beginFrame(); gpuDisplay->finishFrame({}, std::move(mResultWithBuffer)); } Loading Loading
services/surfaceflinger/CompositionEngine/include/compositionengine/impl/Output.h +5 −0 Original line number Diff line number Diff line Loading @@ -152,6 +152,8 @@ protected: virtual const compositionengine::CompositionEngine& getCompositionEngine() const = 0; virtual void dumpState(std::string& out) const = 0; bool mustRecompose() const; private: void dirtyEntireOutput(); compositionengine::OutputLayer* findLayerRequestingBackgroundComposition() const; Loading @@ -170,6 +172,9 @@ private: std::unique_ptr<ClientCompositionRequestCache> mClientCompositionRequestCache; std::unique_ptr<planner::Planner> mPlanner; std::unique_ptr<HwcAsyncWorker> mHwComposerAsyncWorker; // Whether the content must be recomposed this frame. bool mMustRecompose = false; }; // This template factory function standardizes the implementation details of the Loading
services/surfaceflinger/CompositionEngine/src/Display.cpp +1 −1 Original line number Diff line number Diff line Loading @@ -426,7 +426,7 @@ void Display::finishFrame(const compositionengine::CompositionRefreshArgs& refre // 1) It is being handled by hardware composer, which may need this to // keep its virtual display state machine in sync, or // 2) There is work to be done (the dirty region isn't empty) if (GpuVirtualDisplayId::tryCast(mId) && getDirtyRegion().isEmpty()) { if (GpuVirtualDisplayId::tryCast(mId) && !mustRecompose()) { ALOGV("Skipping display composition"); return; } Loading
services/surfaceflinger/CompositionEngine/src/Output.cpp +10 −6 Original line number Diff line number Diff line Loading @@ -977,17 +977,17 @@ void Output::beginFrame() { // frame, then nothing more until we get new layers. // - When a display is created with a private layer stack, we won't // emit any black frames until a layer is added to the layer stack. const bool mustRecompose = dirty && !(empty && wasEmpty); mMustRecompose = dirty && !(empty && wasEmpty); const char flagPrefix[] = {'-', '+'}; static_cast<void>(flagPrefix); ALOGV_IF("%s: %s composition for %s (%cdirty %cempty %cwasEmpty)", __FUNCTION__, mustRecompose ? "doing" : "skipping", getName().c_str(), flagPrefix[dirty], ALOGV("%s: %s composition for %s (%cdirty %cempty %cwasEmpty)", __func__, mMustRecompose ? "doing" : "skipping", getName().c_str(), flagPrefix[dirty], flagPrefix[empty], flagPrefix[wasEmpty]); mRenderSurface->beginFrame(mustRecompose); mRenderSurface->beginFrame(mMustRecompose); if (mustRecompose) { if (mMustRecompose) { outputState.lastCompositionHadVisibleLayers = !empty; } } Loading Loading @@ -1590,5 +1590,9 @@ void Output::finishPrepareFrame() { mRenderSurface->prepareFrame(state.usesClientComposition, state.usesDeviceComposition); } bool Output::mustRecompose() const { return mMustRecompose; } } // namespace impl } // namespace android::compositionengine
services/surfaceflinger/CompositionEngine/tests/DisplayTest.cpp +29 −1 Original line number Diff line number Diff line Loading @@ -971,16 +971,40 @@ TEST_F(DisplayFinishFrameTest, skipsCompositionIfNotDirty) { // We expect no calls to queueBuffer if composition was skipped. EXPECT_CALL(*renderSurface, queueBuffer(_)).Times(0); EXPECT_CALL(*renderSurface, beginFrame(false)); gpuDisplay->editState().isEnabled = true; gpuDisplay->editState().usesClientComposition = false; gpuDisplay->editState().layerStackSpace.setContent(Rect(0, 0, 1, 1)); gpuDisplay->editState().dirtyRegion = Region::INVALID_REGION; gpuDisplay->editState().lastCompositionHadVisibleLayers = true; gpuDisplay->beginFrame(); gpuDisplay->finishFrame({}, std::move(mResultWithoutBuffer)); } TEST_F(DisplayFinishFrameTest, performsCompositionIfDirty) { TEST_F(DisplayFinishFrameTest, skipsCompositionIfEmpty) { auto args = getDisplayCreationArgsForGpuVirtualDisplay(); std::shared_ptr<impl::Display> gpuDisplay = impl::createDisplay(mCompositionEngine, args); mock::RenderSurface* renderSurface = new StrictMock<mock::RenderSurface>(); gpuDisplay->setRenderSurfaceForTest(std::unique_ptr<RenderSurface>(renderSurface)); // We expect no calls to queueBuffer if composition was skipped. EXPECT_CALL(*renderSurface, queueBuffer(_)).Times(0); EXPECT_CALL(*renderSurface, beginFrame(false)); gpuDisplay->editState().isEnabled = true; gpuDisplay->editState().usesClientComposition = false; gpuDisplay->editState().layerStackSpace.setContent(Rect(0, 0, 1, 1)); gpuDisplay->editState().dirtyRegion = Region(Rect(0, 0, 1, 1)); gpuDisplay->editState().lastCompositionHadVisibleLayers = false; gpuDisplay->beginFrame(); gpuDisplay->finishFrame({}, std::move(mResultWithoutBuffer)); } TEST_F(DisplayFinishFrameTest, performsCompositionIfDirtyAndNotEmpty) { auto args = getDisplayCreationArgsForGpuVirtualDisplay(); std::shared_ptr<impl::Display> gpuDisplay = impl::createDisplay(mCompositionEngine, args); Loading @@ -989,11 +1013,15 @@ TEST_F(DisplayFinishFrameTest, performsCompositionIfDirty) { // We expect a single call to queueBuffer when composition is not skipped. EXPECT_CALL(*renderSurface, queueBuffer(_)).Times(1); EXPECT_CALL(*renderSurface, beginFrame(true)); gpuDisplay->editState().isEnabled = true; gpuDisplay->editState().usesClientComposition = false; gpuDisplay->editState().layerStackSpace.setContent(Rect(0, 0, 1, 1)); gpuDisplay->editState().dirtyRegion = Region(Rect(0, 0, 1, 1)); gpuDisplay->editState().lastCompositionHadVisibleLayers = true; gpuDisplay->beginFrame(); gpuDisplay->finishFrame({}, std::move(mResultWithBuffer)); } Loading