summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChavi Weingarten <chaviw@google.com>2022-10-25 19:18:49 +0000
committerAndroid (Google) Code Review <android-gerrit@google.com>2022-10-25 19:18:49 +0000
commit80dfdb8783701cda2439921fe9074dd73a8e6356 (patch)
tree2624eb286f78a0323e6f56cd1d962497ee852e63
parent6c7fd13ce96e00ce5e860a005ce046dec7e1ecee (diff)
parenta722b8165fc48c44cfebd2f3fb0ca038eb53baeb (diff)
downloadnative-80dfdb8783701cda2439921fe9074dd73a8e6356.tar.gz
Merge "Don't queue buffer if nothing new to draw in Display" into tm-qpr-dev
-rw-r--r--services/surfaceflinger/CompositionEngine/include/compositionengine/impl/Output.h5
-rw-r--r--services/surfaceflinger/CompositionEngine/src/Display.cpp2
-rw-r--r--services/surfaceflinger/CompositionEngine/src/Output.cpp16
-rw-r--r--services/surfaceflinger/CompositionEngine/tests/DisplayTest.cpp30
4 files changed, 45 insertions, 8 deletions
diff --git a/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/Output.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/Output.h
index df721cdc89..428c19fe02 100644
--- a/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/Output.h
+++ b/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/Output.h
@@ -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;
@@ -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
diff --git a/services/surfaceflinger/CompositionEngine/src/Display.cpp b/services/surfaceflinger/CompositionEngine/src/Display.cpp
index 1ec6449ed0..163d9a3748 100644
--- a/services/surfaceflinger/CompositionEngine/src/Display.cpp
+++ b/services/surfaceflinger/CompositionEngine/src/Display.cpp
@@ -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;
}
diff --git a/services/surfaceflinger/CompositionEngine/src/Output.cpp b/services/surfaceflinger/CompositionEngine/src/Output.cpp
index b724daa8ce..d0c5803d42 100644
--- a/services/surfaceflinger/CompositionEngine/src/Output.cpp
+++ b/services/surfaceflinger/CompositionEngine/src/Output.cpp
@@ -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],
- flagPrefix[empty], flagPrefix[wasEmpty]);
+ 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;
}
}
@@ -1590,5 +1590,9 @@ void Output::finishPrepareFrame() {
mRenderSurface->prepareFrame(state.usesClientComposition, state.usesDeviceComposition);
}
+bool Output::mustRecompose() const {
+ return mMustRecompose;
+}
+
} // namespace impl
} // namespace android::compositionengine
diff --git a/services/surfaceflinger/CompositionEngine/tests/DisplayTest.cpp b/services/surfaceflinger/CompositionEngine/tests/DisplayTest.cpp
index 344fea3331..5369642a1b 100644
--- a/services/surfaceflinger/CompositionEngine/tests/DisplayTest.cpp
+++ b/services/surfaceflinger/CompositionEngine/tests/DisplayTest.cpp
@@ -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);
@@ -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));
}