Add a TexturePool class into layer caching

In order to reduce the risk of buffer allocations burning cycles during
rendering, add a texture pool which preallocates a set of screen-sized
buffers available for use for layer caching.

This texture pool has some properties to ease implementation details:
1. Textures are allocated synchronously. It's not very hard to add
asynchronous support, but that does add a bit of complexity and Android
12 is almost finalized. It's also not yet clear if asynchronous
allocation is needed since we can just tune the min texture pool size so
that more buffers are preallocated; although it is certainly more
flexible if we're able to defer allocations off-thread.
2. The texture pool is soft-bounded. If needed additional textures may
be allocated to allow for complex geometries, but beyond an upper bound
any additional textures may be deallocated.
3. The texture pool only supports screen-sized buffers, so we don't
allocate smaller scratch buffers to save on memory. However, typically
layer caching only caches screen-sized buffers. This also means that if
the display size changes, then the texture pool must be reallocated.
Note that the "display size" really refers to the framebuffer size, not
necessarily the app-visible display.

Bug: 184860700
Test: builds, boots
Test: libcompositionengine_test
Change-Id: Ic084310bae2b41be49c2cfe9f8c5a20ff683d1ad
diff --git a/services/surfaceflinger/CompositionEngine/tests/OutputTest.cpp b/services/surfaceflinger/CompositionEngine/tests/OutputTest.cpp
index 52e0428..c381081 100644
--- a/services/surfaceflinger/CompositionEngine/tests/OutputTest.cpp
+++ b/services/surfaceflinger/CompositionEngine/tests/OutputTest.cpp
@@ -143,6 +143,7 @@
         mOutput->setRenderSurfaceForTest(std::unique_ptr<RenderSurface>(mRenderSurface));
 
         mOutput->editState().displaySpace.bounds = kDefaultDisplaySize;
+        EXPECT_CALL(mCompositionEngine, getRenderEngine()).WillRepeatedly(ReturnRef(mRenderEngine));
     }
 
     void injectOutputLayer(InjectedLayer& layer) {
@@ -156,6 +157,7 @@
     static const Rect kDefaultDisplaySize;
 
     StrictMock<mock::CompositionEngine> mCompositionEngine;
+    StrictMock<renderengine::mock::RenderEngine> mRenderEngine;
     mock::DisplayColorProfile* mDisplayColorProfile = new StrictMock<mock::DisplayColorProfile>();
     mock::RenderSurface* mRenderSurface = new StrictMock<mock::RenderSurface>();
     std::shared_ptr<Output> mOutput = createOutput(mCompositionEngine);
diff --git a/services/surfaceflinger/CompositionEngine/tests/planner/CachedSetTest.cpp b/services/surfaceflinger/CompositionEngine/tests/planner/CachedSetTest.cpp
index 8eeb0bf..b15e4f3 100644
--- a/services/surfaceflinger/CompositionEngine/tests/planner/CachedSetTest.cpp
+++ b/services/surfaceflinger/CompositionEngine/tests/planner/CachedSetTest.cpp
@@ -40,6 +40,7 @@
 using impl::planner::CachedSet;
 using impl::planner::LayerState;
 using impl::planner::LayerStateField;
+using impl::planner::TexturePool;
 
 namespace {
 
@@ -50,6 +51,7 @@
 
     return expectedBlurSetting == arg.blurSetting;
 }
+static const ui::Size kOutputSize = ui::Size(1, 1);
 
 class CachedSetTest : public testing::Test {
 public:
@@ -76,9 +78,11 @@
     impl::OutputCompositionState mOutputState;
 
     android::renderengine::mock::RenderEngine mRenderEngine;
+    TexturePool mTexturePool = TexturePool(mRenderEngine);
 };
 
 void CachedSetTest::SetUp() {
+    mTexturePool.setDisplaySize(kOutputSize);
     for (size_t i = 0; i < kNumLayers; i++) {
         auto testLayer = std::make_unique<TestLayer>();
         auto pos = static_cast<int32_t>(i);
@@ -319,7 +323,7 @@
                                 const std::vector<const renderengine::LayerSettings*>& layers,
                                 const std::shared_ptr<renderengine::ExternalTexture>&, const bool,
                                 base::unique_fd&&, base::unique_fd*) -> size_t {
-        EXPECT_EQ(Rect(-1, -1, 9, 4), displaySettings.physicalDisplay);
+        EXPECT_EQ(mOutputState.framebufferSpace.content, displaySettings.physicalDisplay);
         EXPECT_EQ(mOutputState.layerStackSpace.content, displaySettings.clip);
         EXPECT_EQ(ui::Transform::toRotationFlags(mOutputState.framebufferSpace.orientation),
                   displaySettings.orientation);
@@ -333,10 +337,11 @@
     EXPECT_CALL(*layerFE1, prepareClientCompositionList(_)).WillOnce(Return(clientCompList1));
     EXPECT_CALL(*layerFE2, prepareClientCompositionList(_)).WillOnce(Return(clientCompList2));
     EXPECT_CALL(mRenderEngine, drawLayers(_, _, _, _, _, _)).WillOnce(Invoke(drawLayers));
-    cachedSet.render(mRenderEngine, mOutputState);
+    cachedSet.render(mRenderEngine, mTexturePool, mOutputState);
     expectReadyBuffer(cachedSet);
 
     EXPECT_EQ(mOutputState.framebufferSpace, cachedSet.getOutputSpace());
+    EXPECT_EQ(mOutputState.framebufferSpace.content, cachedSet.getTextureBounds());
 
     // Now check that appending a new cached set properly cleans up RenderEngine resources.
     CachedSet::Layer& layer3 = *mTestLayers[2]->cachedSetLayer.get();
@@ -367,7 +372,7 @@
                                 const std::vector<const renderengine::LayerSettings*>& layers,
                                 const std::shared_ptr<renderengine::ExternalTexture>&, const bool,
                                 base::unique_fd&&, base::unique_fd*) -> size_t {
-        EXPECT_EQ(Rect(1, 2, 9, 4), displaySettings.physicalDisplay);
+        EXPECT_EQ(mOutputState.framebufferSpace.content, displaySettings.physicalDisplay);
         EXPECT_EQ(mOutputState.layerStackSpace.content, displaySettings.clip);
         EXPECT_EQ(ui::Transform::toRotationFlags(mOutputState.framebufferSpace.orientation),
                   displaySettings.orientation);
@@ -381,7 +386,7 @@
     EXPECT_CALL(*layerFE1, prepareClientCompositionList(_)).WillOnce(Return(clientCompList1));
     EXPECT_CALL(*layerFE2, prepareClientCompositionList(_)).WillOnce(Return(clientCompList2));
     EXPECT_CALL(mRenderEngine, drawLayers(_, _, _, _, _, _)).WillOnce(Invoke(drawLayers));
-    cachedSet.render(mRenderEngine, mOutputState);
+    cachedSet.render(mRenderEngine, mTexturePool, mOutputState);
     expectReadyBuffer(cachedSet);
 
     EXPECT_EQ(mOutputState.framebufferSpace, cachedSet.getOutputSpace());
@@ -554,7 +559,7 @@
     };
 
     EXPECT_CALL(mRenderEngine, drawLayers(_, _, _, _, _, _)).WillOnce(Invoke(drawLayers));
-    cachedSet.render(mRenderEngine, mOutputState);
+    cachedSet.render(mRenderEngine, mTexturePool, mOutputState);
 }
 
 TEST_F(CachedSetTest, addHolePunch_noBuffer) {
@@ -604,7 +609,7 @@
     };
 
     EXPECT_CALL(mRenderEngine, drawLayers(_, _, _, _, _, _)).WillOnce(Invoke(drawLayers));
-    cachedSet.render(mRenderEngine, mOutputState);
+    cachedSet.render(mRenderEngine, mTexturePool, mOutputState);
 }
 
 TEST_F(CachedSetTest, append_removesHolePunch) {
@@ -741,7 +746,7 @@
     };
 
     EXPECT_CALL(mRenderEngine, drawLayers(_, _, _, _, _, _)).WillOnce(Invoke(drawLayers));
-    cachedSet.render(mRenderEngine, mOutputState);
+    cachedSet.render(mRenderEngine, mTexturePool, mOutputState);
 }
 
 } // namespace
diff --git a/services/surfaceflinger/CompositionEngine/tests/planner/FlattenerTest.cpp b/services/surfaceflinger/CompositionEngine/tests/planner/FlattenerTest.cpp
index 8b03964..e176c98 100644
--- a/services/surfaceflinger/CompositionEngine/tests/planner/FlattenerTest.cpp
+++ b/services/surfaceflinger/CompositionEngine/tests/planner/FlattenerTest.cpp
@@ -46,13 +46,14 @@
 
 class TestableFlattener : public Flattener {
 public:
-    TestableFlattener(bool enableHolePunch) : Flattener(enableHolePunch) {}
+    TestableFlattener(renderengine::RenderEngine& renderEngine, bool enableHolePunch)
+          : Flattener(renderEngine, enableHolePunch) {}
     const std::optional<CachedSet>& getNewCachedSetForTesting() const { return mNewCachedSet; }
 };
 
 class FlattenerTest : public testing::Test {
 public:
-    FlattenerTest() : mFlattener(std::make_unique<TestableFlattener>(true)) {}
+    FlattenerTest() : mFlattener(std::make_unique<TestableFlattener>(mRenderEngine, true)) {}
     void SetUp() override;
 
 protected:
@@ -60,7 +61,7 @@
     void initializeFlattener(const std::vector<const LayerState*>& layers);
     void expectAllLayersFlattened(const std::vector<const LayerState*>& layers);
 
-    // mRenderEngine may be held as a pointer to mFlattener, so mFlattener must be destroyed first.
+    // mRenderEngine is held as a reference in mFlattener, so mFlattener must be destroyed first.
     renderengine::mock::RenderEngine mRenderEngine;
     std::unique_ptr<TestableFlattener> mFlattener;
 
@@ -84,6 +85,7 @@
 };
 
 void FlattenerTest::SetUp() {
+    mFlattener->setDisplaySize({1, 1});
     for (size_t i = 0; i < kNumLayers; i++) {
         auto testLayer = std::make_unique<TestLayer>();
         auto pos = static_cast<int32_t>(i);
@@ -146,13 +148,13 @@
     initializeOverrideBuffer(layers);
     EXPECT_EQ(getNonBufferHash(layers),
               mFlattener->flattenLayers(layers, getNonBufferHash(layers), mTime));
-    mFlattener->renderCachedSets(mRenderEngine, mOutputState);
+    mFlattener->renderCachedSets(mOutputState);
 
     // same geometry, update the internal layer stack
     initializeOverrideBuffer(layers);
     EXPECT_EQ(getNonBufferHash(layers),
               mFlattener->flattenLayers(layers, getNonBufferHash(layers), mTime));
-    mFlattener->renderCachedSets(mRenderEngine, mOutputState);
+    mFlattener->renderCachedSets(mOutputState);
 }
 
 void FlattenerTest::expectAllLayersFlattened(const std::vector<const LayerState*>& layers) {
@@ -162,7 +164,7 @@
     initializeOverrideBuffer(layers);
     EXPECT_EQ(getNonBufferHash(layers),
               mFlattener->flattenLayers(layers, getNonBufferHash(layers), mTime));
-    mFlattener->renderCachedSets(mRenderEngine, mOutputState);
+    mFlattener->renderCachedSets(mOutputState);
 
     for (const auto layer : layers) {
         EXPECT_EQ(nullptr, layer->getOutputLayer()->getState().overrideInfo.buffer);
@@ -172,7 +174,7 @@
     initializeOverrideBuffer(layers);
     EXPECT_NE(getNonBufferHash(layers),
               mFlattener->flattenLayers(layers, getNonBufferHash(layers), mTime));
-    mFlattener->renderCachedSets(mRenderEngine, mOutputState);
+    mFlattener->renderCachedSets(mOutputState);
 
     const auto buffer = layers[0]->getOutputLayer()->getState().overrideInfo.buffer;
     EXPECT_NE(nullptr, buffer);
@@ -207,7 +209,7 @@
     initializeOverrideBuffer(layers);
     EXPECT_EQ(getNonBufferHash(layers),
               mFlattener->flattenLayers(layers, getNonBufferHash(layers), mTime));
-    mFlattener->renderCachedSets(mRenderEngine, mOutputState);
+    mFlattener->renderCachedSets(mOutputState);
 }
 
 TEST_F(FlattenerTest, flattenLayers_basicFlatten) {
@@ -253,7 +255,7 @@
     initializeOverrideBuffer(layers);
     EXPECT_NE(getNonBufferHash(layers),
               mFlattener->flattenLayers(layers, getNonBufferHash(layers), mTime));
-    mFlattener->renderCachedSets(mRenderEngine, mOutputState);
+    mFlattener->renderCachedSets(mOutputState);
 
     EXPECT_NE(nullptr, overrideBuffer1);
     EXPECT_EQ(overrideBuffer1, overrideBuffer2);
@@ -358,7 +360,7 @@
     initializeOverrideBuffer(layers);
     EXPECT_EQ(getNonBufferHash(layers),
               mFlattener->flattenLayers(layers, getNonBufferHash(layers), mTime));
-    mFlattener->renderCachedSets(mRenderEngine, mOutputState);
+    mFlattener->renderCachedSets(mOutputState);
 
     EXPECT_EQ(nullptr, overrideBuffer1);
     EXPECT_EQ(nullptr, overrideBuffer2);
@@ -395,7 +397,7 @@
     initializeOverrideBuffer(layers);
     EXPECT_EQ(getNonBufferHash(layers),
               mFlattener->flattenLayers(layers, getNonBufferHash(layers), mTime));
-    mFlattener->renderCachedSets(mRenderEngine, mOutputState);
+    mFlattener->renderCachedSets(mOutputState);
 
     EXPECT_EQ(nullptr, overrideBuffer1);
     EXPECT_EQ(nullptr, overrideBuffer2);
@@ -404,7 +406,7 @@
     initializeOverrideBuffer(layers);
     EXPECT_NE(getNonBufferHash(layers),
               mFlattener->flattenLayers(layers, getNonBufferHash(layers), mTime));
-    mFlattener->renderCachedSets(mRenderEngine, mOutputState);
+    mFlattener->renderCachedSets(mOutputState);
 
     EXPECT_EQ(nullptr, overrideBuffer1);
     EXPECT_NE(nullptr, overrideBuffer2);
@@ -417,7 +419,7 @@
     initializeOverrideBuffer(layers);
     EXPECT_NE(getNonBufferHash(layers),
               mFlattener->flattenLayers(layers, getNonBufferHash(layers), mTime));
-    mFlattener->renderCachedSets(mRenderEngine, mOutputState);
+    mFlattener->renderCachedSets(mOutputState);
 
     EXPECT_EQ(nullptr, overrideBuffer1);
     EXPECT_NE(nullptr, overrideBuffer2);
@@ -426,7 +428,7 @@
     initializeOverrideBuffer(layers);
     EXPECT_NE(getNonBufferHash(layers),
               mFlattener->flattenLayers(layers, getNonBufferHash(layers), mTime));
-    mFlattener->renderCachedSets(mRenderEngine, mOutputState);
+    mFlattener->renderCachedSets(mOutputState);
 
     EXPECT_NE(nullptr, overrideBuffer1);
     EXPECT_EQ(overrideBuffer1, overrideBuffer2);
@@ -468,7 +470,7 @@
     initializeOverrideBuffer(layers);
     EXPECT_EQ(getNonBufferHash(layers),
               mFlattener->flattenLayers(layers, getNonBufferHash(layers), mTime));
-    mFlattener->renderCachedSets(mRenderEngine, mOutputState);
+    mFlattener->renderCachedSets(mOutputState);
 
     EXPECT_EQ(nullptr, overrideBuffer1);
     EXPECT_EQ(nullptr, overrideBuffer2);
@@ -482,7 +484,7 @@
     EXPECT_NE(getNonBufferHash(layers),
               mFlattener->flattenLayers(layers, getNonBufferHash(layers), mTime));
     mOutputState.framebufferSpace.orientation = ui::ROTATION_90;
-    mFlattener->renderCachedSets(mRenderEngine, mOutputState);
+    mFlattener->renderCachedSets(mOutputState);
 
     EXPECT_NE(nullptr, overrideBuffer1);
     EXPECT_EQ(overrideBuffer1, overrideBuffer2);
@@ -495,7 +497,7 @@
     EXPECT_NE(getNonBufferHash(layers),
               mFlattener->flattenLayers(layers, getNonBufferHash(layers), mTime));
     mOutputState.framebufferSpace.orientation = ui::ROTATION_180;
-    mFlattener->renderCachedSets(mRenderEngine, mOutputState);
+    mFlattener->renderCachedSets(mOutputState);
 
     EXPECT_NE(nullptr, overrideBuffer1);
     EXPECT_EQ(overrideBuffer1, overrideBuffer2);
@@ -510,7 +512,7 @@
     initializeOverrideBuffer(layers);
     EXPECT_NE(getNonBufferHash(layers),
               mFlattener->flattenLayers(layers, getNonBufferHash(layers), mTime));
-    mFlattener->renderCachedSets(mRenderEngine, mOutputState);
+    mFlattener->renderCachedSets(mOutputState);
 
     EXPECT_NE(nullptr, overrideBuffer1);
     EXPECT_EQ(overrideBuffer1, overrideBuffer2);
@@ -522,7 +524,7 @@
     EXPECT_NE(getNonBufferHash(layers),
               mFlattener->flattenLayers(layers, getNonBufferHash(layers), mTime));
     mOutputState.framebufferSpace.orientation = ui::ROTATION_270;
-    mFlattener->renderCachedSets(mRenderEngine, mOutputState);
+    mFlattener->renderCachedSets(mOutputState);
 
     EXPECT_NE(nullptr, overrideBuffer1);
     EXPECT_EQ(overrideBuffer1, overrideBuffer2);
@@ -561,7 +563,7 @@
 
     // This will render a CachedSet.
     EXPECT_CALL(mRenderEngine, drawLayers(_, _, _, _, _, _)).WillOnce(Return(NO_ERROR));
-    mFlattener->renderCachedSets(mRenderEngine, mOutputState);
+    mFlattener->renderCachedSets(mOutputState);
 
     // We've rendered a CachedSet, but we haven't merged it in.
     EXPECT_EQ(nullptr, overrideBuffer1);
@@ -574,7 +576,7 @@
     initializeOverrideBuffer(layers);
     EXPECT_NE(getNonBufferHash(layers),
               mFlattener->flattenLayers(layers, getNonBufferHash(layers), mTime));
-    mFlattener->renderCachedSets(mRenderEngine, mOutputState);
+    mFlattener->renderCachedSets(mOutputState);
 
     EXPECT_NE(nullptr, overrideBuffer1);
     EXPECT_EQ(overrideBuffer1, overrideBuffer2);
@@ -623,7 +625,7 @@
 
     // This will render a CachedSet.
     EXPECT_CALL(mRenderEngine, drawLayers(_, _, _, _, _, _)).WillOnce(Return(NO_ERROR));
-    mFlattener->renderCachedSets(mRenderEngine, mOutputState);
+    mFlattener->renderCachedSets(mOutputState);
 
     // We've rendered a CachedSet, but we haven't merged it in.
     EXPECT_EQ(nullptr, overrideBuffer1);
@@ -636,7 +638,7 @@
     initializeOverrideBuffer(layers);
     EXPECT_NE(getNonBufferHash(layers),
               mFlattener->flattenLayers(layers, getNonBufferHash(layers), mTime));
-    mFlattener->renderCachedSets(mRenderEngine, mOutputState);
+    mFlattener->renderCachedSets(mOutputState);
 
     EXPECT_NE(nullptr, overrideBuffer1);
     EXPECT_EQ(overrideBuffer1, overrideBuffer2);
@@ -680,7 +682,7 @@
     initializeOverrideBuffer(layers);
     EXPECT_EQ(getNonBufferHash(layers),
               mFlattener->flattenLayers(layers, getNonBufferHash(layers), mTime));
-    mFlattener->renderCachedSets(mRenderEngine, mOutputState);
+    mFlattener->renderCachedSets(mOutputState);
 
     for (const auto layer : layers) {
         EXPECT_EQ(nullptr, layer->getOutputLayer()->getState().overrideInfo.buffer);
@@ -690,7 +692,7 @@
     initializeOverrideBuffer(layers);
     EXPECT_NE(getNonBufferHash(layers),
               mFlattener->flattenLayers(layers, getNonBufferHash(layers), mTime));
-    mFlattener->renderCachedSets(mRenderEngine, mOutputState);
+    mFlattener->renderCachedSets(mOutputState);
     EXPECT_NE(nullptr, overrideBuffer1);
     EXPECT_EQ(overrideBuffer1, overrideBuffer2);
     EXPECT_EQ(nullptr, overrideBuffer3);
@@ -724,7 +726,7 @@
     initializeOverrideBuffer(layers);
     EXPECT_EQ(getNonBufferHash(layers),
               mFlattener->flattenLayers(layers, getNonBufferHash(layers), mTime));
-    mFlattener->renderCachedSets(mRenderEngine, mOutputState);
+    mFlattener->renderCachedSets(mOutputState);
 
     for (const auto layer : layers) {
         EXPECT_EQ(nullptr, layer->getOutputLayer()->getState().overrideInfo.buffer);
@@ -735,7 +737,7 @@
     initializeOverrideBuffer(layers);
     EXPECT_EQ(getNonBufferHash(layers),
               mFlattener->flattenLayers(layers, getNonBufferHash(layers), mTime));
-    mFlattener->renderCachedSets(mRenderEngine, mOutputState);
+    mFlattener->renderCachedSets(mOutputState);
     for (const auto layer : layers) {
         EXPECT_EQ(nullptr, layer->getOutputLayer()->getState().overrideInfo.buffer);
     }
@@ -776,7 +778,7 @@
     initializeOverrideBuffer(layers);
     EXPECT_EQ(getNonBufferHash(layers),
               mFlattener->flattenLayers(layers, getNonBufferHash(layers), mTime));
-    mFlattener->renderCachedSets(mRenderEngine, mOutputState);
+    mFlattener->renderCachedSets(mOutputState);
 
     for (const auto layer : layers) {
         EXPECT_EQ(nullptr, layer->getOutputLayer()->getState().overrideInfo.buffer);
@@ -786,7 +788,7 @@
     initializeOverrideBuffer(layers);
     EXPECT_NE(getNonBufferHash(layers),
               mFlattener->flattenLayers(layers, getNonBufferHash(layers), mTime));
-    mFlattener->renderCachedSets(mRenderEngine, mOutputState);
+    mFlattener->renderCachedSets(mOutputState);
     EXPECT_EQ(nullptr, overrideBuffer1);
     EXPECT_EQ(nullptr, blurOverrideBuffer);
     EXPECT_NE(nullptr, overrideBuffer3);
@@ -823,7 +825,7 @@
     initializeOverrideBuffer(layers);
     EXPECT_EQ(getNonBufferHash(layers),
               mFlattener->flattenLayers(layers, getNonBufferHash(layers), mTime));
-    mFlattener->renderCachedSets(mRenderEngine, mOutputState);
+    mFlattener->renderCachedSets(mOutputState);
 
     const auto& cachedSet = mFlattener->getNewCachedSetForTesting();
     ASSERT_NE(std::nullopt, cachedSet);
@@ -837,7 +839,7 @@
     initializeOverrideBuffer(layers);
     EXPECT_NE(getNonBufferHash(layers),
               mFlattener->flattenLayers(layers, getNonBufferHash(layers), mTime));
-    mFlattener->renderCachedSets(mRenderEngine, mOutputState);
+    mFlattener->renderCachedSets(mOutputState);
     EXPECT_NE(nullptr, overrideBuffer1);
     EXPECT_EQ(overrideBuffer2, overrideBuffer1);
     EXPECT_EQ(nullptr, blurOverrideBuffer);
@@ -864,7 +866,7 @@
     initializeOverrideBuffer(layers);
     EXPECT_EQ(getNonBufferHash(layers),
               mFlattener->flattenLayers(layers, getNonBufferHash(layers), mTime));
-    mFlattener->renderCachedSets(mRenderEngine, mOutputState);
+    mFlattener->renderCachedSets(mOutputState);
 
     EXPECT_EQ(nullptr, overrideBuffer1);
     EXPECT_EQ(nullptr, overrideBuffer2);
@@ -872,12 +874,12 @@
     // Simulate attempting to render prior to merging the new cached set with the layer stack.
     // Here we should not try to re-render.
     EXPECT_CALL(mRenderEngine, drawLayers(_, _, _, _, _, _)).Times(0);
-    mFlattener->renderCachedSets(mRenderEngine, mOutputState);
+    mFlattener->renderCachedSets(mOutputState);
 
     // We provide the override buffer now that it's rendered
     EXPECT_NE(getNonBufferHash(layers),
               mFlattener->flattenLayers(layers, getNonBufferHash(layers), mTime));
-    mFlattener->renderCachedSets(mRenderEngine, mOutputState);
+    mFlattener->renderCachedSets(mOutputState);
 
     EXPECT_NE(nullptr, overrideBuffer1);
     EXPECT_EQ(overrideBuffer2, overrideBuffer1);
diff --git a/services/surfaceflinger/CompositionEngine/tests/planner/TexturePoolTest.cpp b/services/surfaceflinger/CompositionEngine/tests/planner/TexturePoolTest.cpp
new file mode 100644
index 0000000..b802e51
--- /dev/null
+++ b/services/surfaceflinger/CompositionEngine/tests/planner/TexturePoolTest.cpp
@@ -0,0 +1,134 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#undef LOG_TAG
+#define LOG_TAG "TexturePoolTest"
+
+#include <compositionengine/impl/planner/TexturePool.h>
+#include <gtest/gtest.h>
+#include <log/log.h>
+#include <renderengine/mock/RenderEngine.h>
+
+namespace android::compositionengine::impl::planner {
+namespace {
+
+const ui::Size kDisplaySize(1, 1);
+const ui::Size kDisplaySizeTwo(2, 2);
+
+class TestableTexturePool : public TexturePool {
+public:
+    TestableTexturePool(renderengine::RenderEngine& renderEngine) : TexturePool(renderEngine) {}
+
+    size_t getMinPoolSize() const { return kMinPoolSize; }
+    size_t getMaxPoolSize() const { return kMaxPoolSize; }
+    size_t getPoolSize() const { return mPool.size(); }
+};
+
+struct TexturePoolTest : public testing::Test {
+    TexturePoolTest() {
+        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.setDisplaySize(kDisplaySize);
+    }
+
+    ~TexturePoolTest() {
+        const ::testing::TestInfo* const test_info =
+                ::testing::UnitTest::GetInstance()->current_test_info();
+        ALOGD("**** Tearing down after %s.%s\n", test_info->test_case_name(), test_info->name());
+    }
+
+    renderengine::mock::RenderEngine mRenderEngine;
+    TestableTexturePool mTexturePool = TestableTexturePool(mRenderEngine);
+};
+
+TEST_F(TexturePoolTest, preallocatesMinPool) {
+    EXPECT_EQ(mTexturePool.getMinPoolSize(), mTexturePool.getPoolSize());
+}
+
+TEST_F(TexturePoolTest, doesNotAllocateBeyondMinPool) {
+    for (size_t i = 0; i < mTexturePool.getMinPoolSize() + 1; i++) {
+        auto texture = mTexturePool.borrowTexture();
+    }
+
+    EXPECT_EQ(mTexturePool.getMinPoolSize(), mTexturePool.getPoolSize());
+}
+
+TEST_F(TexturePoolTest, cyclesUpToMaxPoolSize) {
+    std::unordered_set<uint64_t> bufferIds;
+    std::deque<std::shared_ptr<TexturePool::AutoTexture>> textures;
+    for (size_t i = 0; i < mTexturePool.getMaxPoolSize(); i++) {
+        textures.emplace_back(mTexturePool.borrowTexture());
+        bufferIds.insert(textures.back()->get()->getBuffer()->getId());
+    }
+
+    EXPECT_EQ(mTexturePool.getMaxPoolSize(), bufferIds.size());
+
+    for (size_t i = 0; i < 3; i++) {
+        textures.pop_front();
+        textures.emplace_back(mTexturePool.borrowTexture());
+        bufferIds.insert(textures.back()->get()->getBuffer()->getId());
+    }
+
+    EXPECT_EQ(mTexturePool.getMaxPoolSize(), bufferIds.size());
+}
+
+TEST_F(TexturePoolTest, goesPastMaxSizeAndRebounds) {
+    std::unordered_set<uint64_t> bufferIds;
+    std::vector<std::shared_ptr<TexturePool::AutoTexture>> textures;
+    for (size_t i = 0; i < mTexturePool.getMaxPoolSize() + 2; i++) {
+        textures.emplace_back(mTexturePool.borrowTexture());
+        bufferIds.insert(textures.back()->get()->getBuffer()->getId());
+    }
+
+    EXPECT_EQ(mTexturePool.getMaxPoolSize() + 2, bufferIds.size());
+
+    // Return the textures to the pool.
+    // Now when we cycle through the pool it's again bounded by max textures.
+    textures.clear();
+
+    std::unordered_set<uint64_t> newBufferIds;
+    for (size_t i = 0; i < 2 * mTexturePool.getMaxPoolSize(); i++) {
+        auto texture = mTexturePool.borrowTexture();
+        newBufferIds.insert(texture->get()->getBuffer()->getId());
+    }
+
+    EXPECT_EQ(mTexturePool.getMaxPoolSize(), newBufferIds.size());
+}
+
+TEST_F(TexturePoolTest, reallocatesWhenDisplaySizeChanges) {
+    auto texture = mTexturePool.borrowTexture();
+
+    EXPECT_EQ(kDisplaySize.getWidth(),
+              static_cast<int32_t>(texture->get()->getBuffer()->getWidth()));
+    EXPECT_EQ(kDisplaySize.getHeight(),
+              static_cast<int32_t>(texture->get()->getBuffer()->getHeight()));
+    mTexturePool.setDisplaySize(kDisplaySizeTwo);
+
+    EXPECT_EQ(mTexturePool.getMinPoolSize(), mTexturePool.getPoolSize());
+    texture.reset();
+    // When the texture is returned to the pool, the pool now destroys it.
+    EXPECT_EQ(mTexturePool.getMinPoolSize(), mTexturePool.getPoolSize());
+
+    texture = mTexturePool.borrowTexture();
+    EXPECT_EQ(kDisplaySizeTwo.getWidth(),
+              static_cast<int32_t>(texture->get()->getBuffer()->getWidth()));
+    EXPECT_EQ(kDisplaySizeTwo.getHeight(),
+              static_cast<int32_t>(texture->get()->getBuffer()->getHeight()));
+}
+
+} // namespace
+} // namespace android::compositionengine::impl::planner