SF: Enable Layer Caching Texture Pool only for the active display
Limit the memory consuption of the Texture Pool to a single display
Test: atest libcompositionengine_test
Bug: 188839446
Change-Id: I61d73a72bc25e776ef18f4e3fbf2c3373e0257e4
diff --git a/services/surfaceflinger/CompositionEngine/include/compositionengine/Output.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/Output.h
index 1416b1e..0ef0b99 100644
--- a/services/surfaceflinger/CompositionEngine/include/compositionengine/Output.h
+++ b/services/surfaceflinger/CompositionEngine/include/compositionengine/Output.h
@@ -166,6 +166,9 @@
// Enables (or disables) layer caching on this output
virtual void setLayerCachingEnabled(bool) = 0;
+ // Enables (or disables) layer caching texture pool on this output
+ virtual void setLayerCachingTexturePoolEnabled(bool) = 0;
+
// Sets the projection state to use
virtual void setProjection(ui::Rotation orientation, const Rect& layerStackSpaceRect,
const Rect& orientedDisplaySpaceRect) = 0;
diff --git a/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/Output.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/Output.h
index f832084..ddcc907 100644
--- a/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/Output.h
+++ b/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/Output.h
@@ -41,6 +41,7 @@
std::optional<DisplayId> getDisplayId() const override;
void setCompositionEnabled(bool) override;
void setLayerCachingEnabled(bool) override;
+ void setLayerCachingTexturePoolEnabled(bool) override;
void setProjection(ui::Rotation orientation, const Rect& layerStackSpaceRect,
const Rect& orientedDisplaySpaceRect) override;
void setDisplaySize(const ui::Size&) override;
diff --git a/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/planner/Flattener.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/planner/Flattener.h
index 7534548..8ec15ed 100644
--- a/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/planner/Flattener.h
+++ b/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/planner/Flattener.h
@@ -80,6 +80,8 @@
void renderCachedSets(const OutputCompositionState& outputState,
std::optional<std::chrono::steady_clock::time_point> renderDeadline);
+ void setTexturePoolEnabled(bool enabled) { mTexturePool.setEnabled(enabled); }
+
void dump(std::string& result) const;
void dumpLayers(std::string& result) const;
diff --git a/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/planner/Planner.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/planner/Planner.h
index be34153..76d5e81 100644
--- a/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/planner/Planner.h
+++ b/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/planner/Planner.h
@@ -64,6 +64,8 @@
void renderCachedSets(const OutputCompositionState& outputState,
std::optional<std::chrono::steady_clock::time_point> renderDeadline);
+ void setTexturePoolEnabled(bool enabled) { mFlattener.setTexturePoolEnabled(enabled); }
+
void dump(const Vector<String16>& args, std::string&);
private:
diff --git a/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/planner/TexturePool.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/planner/TexturePool.h
index fb53ee0..d607c75 100644
--- a/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/planner/TexturePool.h
+++ b/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/planner/TexturePool.h
@@ -63,7 +63,8 @@
sp<Fence> mFence;
};
- TexturePool(renderengine::RenderEngine& renderEngine) : mRenderEngine(renderEngine) {}
+ TexturePool(renderengine::RenderEngine& renderEngine)
+ : mRenderEngine(renderEngine), mEnabled(false) {}
virtual ~TexturePool() = default;
@@ -78,6 +79,12 @@
// to the pool.
std::shared_ptr<AutoTexture> borrowTexture();
+ // Enables or disables the pool. When the pool is disabled, no buffers will
+ // be held by the pool. This is useful when the active display changes.
+ void setEnabled(bool enable);
+
+ void dump(std::string& out) const;
+
protected:
// Proteted visibility so that they can be used for testing
const static constexpr size_t kMinPoolSize = 3;
@@ -95,8 +102,10 @@
// Returns a previously borrowed texture to the pool.
void returnTexture(std::shared_ptr<renderengine::ExternalTexture>&& texture,
const sp<Fence>& fence);
+ void allocatePool();
renderengine::RenderEngine& mRenderEngine;
ui::Size mSize;
+ bool mEnabled;
};
} // namespace android::compositionengine::impl::planner
diff --git a/services/surfaceflinger/CompositionEngine/include/compositionengine/mock/Output.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/mock/Output.h
index 8e777e3..8fdf3ae 100644
--- a/services/surfaceflinger/CompositionEngine/include/compositionengine/mock/Output.h
+++ b/services/surfaceflinger/CompositionEngine/include/compositionengine/mock/Output.h
@@ -37,6 +37,7 @@
MOCK_METHOD1(setCompositionEnabled, void(bool));
MOCK_METHOD1(setLayerCachingEnabled, void(bool));
+ MOCK_METHOD1(setLayerCachingTexturePoolEnabled, void(bool));
MOCK_METHOD3(setProjection, void(ui::Rotation, const Rect&, const Rect&));
MOCK_METHOD1(setDisplaySize, void(const ui::Size&));
MOCK_METHOD2(setLayerStackFilter, void(uint32_t, bool));
diff --git a/services/surfaceflinger/CompositionEngine/src/Output.cpp b/services/surfaceflinger/CompositionEngine/src/Output.cpp
index cafcb40..3310a71 100644
--- a/services/surfaceflinger/CompositionEngine/src/Output.cpp
+++ b/services/surfaceflinger/CompositionEngine/src/Output.cpp
@@ -146,6 +146,12 @@
}
}
+void Output::setLayerCachingTexturePoolEnabled(bool enabled) {
+ if (mPlanner) {
+ mPlanner->setTexturePoolEnabled(enabled);
+ }
+}
+
void Output::setProjection(ui::Rotation orientation, const Rect& layerStackSpaceRect,
const Rect& orientedDisplaySpaceRect) {
auto& outputState = editState();
diff --git a/services/surfaceflinger/CompositionEngine/src/planner/Flattener.cpp b/services/surfaceflinger/CompositionEngine/src/planner/Flattener.cpp
index f033279..8e2c182 100644
--- a/services/surfaceflinger/CompositionEngine/src/planner/Flattener.cpp
+++ b/services/surfaceflinger/CompositionEngine/src/planner/Flattener.cpp
@@ -205,6 +205,9 @@
durationString(lastUpdate).c_str());
dumpLayers(result);
+
+ base::StringAppendF(&result, "\n");
+ mTexturePool.dump(result);
}
size_t Flattener::calculateDisplayCost(const std::vector<const LayerState*>& layers) const {
diff --git a/services/surfaceflinger/CompositionEngine/src/planner/TexturePool.cpp b/services/surfaceflinger/CompositionEngine/src/planner/TexturePool.cpp
index e3772a2..497c433 100644
--- a/services/surfaceflinger/CompositionEngine/src/planner/TexturePool.cpp
+++ b/services/surfaceflinger/CompositionEngine/src/planner/TexturePool.cpp
@@ -24,14 +24,22 @@
namespace android::compositionengine::impl::planner {
+void TexturePool::allocatePool() {
+ mPool.clear();
+ if (mEnabled && mSize.isValid()) {
+ mPool.resize(kMinPoolSize);
+ std::generate_n(mPool.begin(), kMinPoolSize, [&]() {
+ return Entry{genTexture(), nullptr};
+ });
+ }
+}
+
void TexturePool::setDisplaySize(ui::Size size) {
if (mSize == size) {
return;
}
mSize = size;
- mPool.clear();
- mPool.resize(kMinPoolSize);
- std::generate_n(mPool.begin(), kMinPoolSize, [&]() { return Entry{genTexture(), nullptr}; });
+ allocatePool();
}
std::shared_ptr<TexturePool::AutoTexture> TexturePool::borrowTexture() {
@@ -46,7 +54,12 @@
void TexturePool::returnTexture(std::shared_ptr<renderengine::ExternalTexture>&& texture,
const sp<Fence>& fence) {
- // Drop the texture on the floor if the pool is no longer tracking textures of the same size.
+ // Drop the texture on the floor if the pool is not enabled
+ if (!mEnabled) {
+ return;
+ }
+
+ // Or the texture on the floor if the pool is no longer tracking textures of the same size.
if (static_cast<int32_t>(texture->getBuffer()->getWidth()) != mSize.getWidth() ||
static_cast<int32_t>(texture->getBuffer()->getHeight()) != mSize.getHeight()) {
ALOGV("Deallocating texture from Planner's pool - display size changed (previous: (%dx%d), "
@@ -81,4 +94,15 @@
renderengine::ExternalTexture::Usage::WRITEABLE);
}
+void TexturePool::setEnabled(bool enabled) {
+ mEnabled = enabled;
+ allocatePool();
+}
+
+void TexturePool::dump(std::string& out) const {
+ base::StringAppendF(&out,
+ "TexturePool (%s) has %zu buffers of size [%" PRId32 ", %" PRId32 "]\n",
+ mEnabled ? "enabled" : "disabled", mPool.size(), mSize.width, mSize.height);
+}
+
} // namespace android::compositionengine::impl::planner
\ No newline at end of file
diff --git a/services/surfaceflinger/CompositionEngine/tests/planner/TexturePoolTest.cpp b/services/surfaceflinger/CompositionEngine/tests/planner/TexturePoolTest.cpp
index b802e51..6fc90fe 100644
--- a/services/surfaceflinger/CompositionEngine/tests/planner/TexturePoolTest.cpp
+++ b/services/surfaceflinger/CompositionEngine/tests/planner/TexturePoolTest.cpp
@@ -42,6 +42,7 @@
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());
+ mTexturePool.setEnabled(true);
mTexturePool.setDisplaySize(kDisplaySize);
}
@@ -130,5 +131,44 @@
static_cast<int32_t>(texture->get()->getBuffer()->getHeight()));
}
+TEST_F(TexturePoolTest, freesBuffersWhenDisabled) {
+ EXPECT_EQ(mTexturePool.getPoolSize(), mTexturePool.getMinPoolSize());
+
+ std::deque<std::shared_ptr<TexturePool::AutoTexture>> textures;
+ for (size_t i = 0; i < mTexturePool.getMinPoolSize() - 1; i++) {
+ textures.emplace_back(mTexturePool.borrowTexture());
+ }
+
+ EXPECT_EQ(mTexturePool.getPoolSize(), 1u);
+ mTexturePool.setEnabled(false);
+ EXPECT_EQ(mTexturePool.getPoolSize(), 0u);
+
+ textures.clear();
+ EXPECT_EQ(mTexturePool.getPoolSize(), 0u);
+}
+
+TEST_F(TexturePoolTest, doesNotHoldBuffersWhenDisabled) {
+ EXPECT_EQ(mTexturePool.getPoolSize(), mTexturePool.getMinPoolSize());
+ mTexturePool.setEnabled(false);
+ EXPECT_EQ(mTexturePool.getPoolSize(), 0u);
+
+ std::deque<std::shared_ptr<TexturePool::AutoTexture>> textures;
+ for (size_t i = 0; i < mTexturePool.getMinPoolSize() - 1; i++) {
+ textures.emplace_back(mTexturePool.borrowTexture());
+ }
+
+ EXPECT_EQ(mTexturePool.getPoolSize(), 0u);
+ textures.clear();
+ EXPECT_EQ(mTexturePool.getPoolSize(), 0u);
+}
+
+TEST_F(TexturePoolTest, reallocatesWhenReEnabled) {
+ EXPECT_EQ(mTexturePool.getPoolSize(), mTexturePool.getMinPoolSize());
+ mTexturePool.setEnabled(false);
+ EXPECT_EQ(mTexturePool.getPoolSize(), 0u);
+ mTexturePool.setEnabled(true);
+ EXPECT_EQ(mTexturePool.getPoolSize(), mTexturePool.getMinPoolSize());
+}
+
} // namespace
} // namespace android::compositionengine::impl::planner