SF: Introduce OutputLayerCompositionState

This moves the display-dependent state from LayerBE.h to a new
OutputLayerCompositionState.h header, adds some simple accessors to
get the new state, and minimally adjusts the existing SurfaceFlinger
code to use the new structure.

Test: atest libsurfaceflinger_unittest libcompositionengine_test
Bug: 121291683
Change-Id: I00370f05dc6b2a3db34094862c46084e7575dbda
diff --git a/services/surfaceflinger/BufferLayer.cpp b/services/surfaceflinger/BufferLayer.cpp
index 89eee6b..e4db6df 100644
--- a/services/surfaceflinger/BufferLayer.cpp
+++ b/services/surfaceflinger/BufferLayer.cpp
@@ -24,8 +24,11 @@
 #include <mutex>
 
 #include <compositionengine/CompositionEngine.h>
+#include <compositionengine/Display.h>
 #include <compositionengine/Layer.h>
 #include <compositionengine/LayerCreationArgs.h>
+#include <compositionengine/OutputLayer.h>
+#include <compositionengine/impl/OutputLayerCompositionState.h>
 #include <cutils/compiler.h>
 #include <cutils/native_handle.h>
 #include <cutils/properties.h>
@@ -66,11 +69,10 @@
 BufferLayer::~BufferLayer() {
     mFlinger->deleteTextureAsync(mTextureName);
 
-    if (!getBE().mHwcLayers.empty()) {
+    if (destroyAllHwcLayersPlusChildren()) {
         ALOGE("Found stale hardware composer layers when destroying "
               "surface flinger layer %s",
               mName.string());
-        destroyAllHwcLayersPlusChildren();
     }
 
     mFlinger->mTimeStats->onDestroy(getSequence());
@@ -171,7 +173,8 @@
         layer.source.buffer.usePremultipliedAlpha = getPremultipledAlpha();
         layer.source.buffer.isY410BT2020 = isHdrY410();
         // TODO: we could be more subtle with isFixedSize()
-        const bool useFiltering = needsFiltering() || renderArea.needsFiltering() || isFixedSize();
+        const bool useFiltering = needsFiltering(renderArea.getDisplayDevice()) ||
+                renderArea.needsFiltering() || isFixedSize();
 
         // Query the texture matrix given our current filtering mode.
         float textureMatrix[16];
@@ -240,23 +243,26 @@
             getBE().compositionInfo.mBuffer->getPixelFormat() == HAL_PIXEL_FORMAT_RGBA_1010102);
 }
 
-void BufferLayer::setPerFrameData(DisplayId displayId, const ui::Transform& transform,
-                                  const Rect& viewport, int32_t supportedPerFrameMetadata) {
-    RETURN_IF_NO_HWC_LAYER(displayId);
+void BufferLayer::setPerFrameData(const sp<const DisplayDevice>& displayDevice,
+                                  const ui::Transform& transform, const Rect& viewport,
+                                  int32_t supportedPerFrameMetadata) {
+    RETURN_IF_NO_HWC_LAYER(displayDevice);
 
     // Apply this display's projection's viewport to the visible region
     // before giving it to the HWC HAL.
     Region visible = transform.transform(visibleRegion.intersect(viewport));
 
-    auto& hwcInfo = getBE().mHwcLayers[displayId];
-    auto& hwcLayer = hwcInfo.layer;
+    const auto outputLayer = findOutputLayerForDisplay(displayDevice);
+    LOG_FATAL_IF(!outputLayer || !outputLayer->getState().hwc);
+
+    auto& hwcLayer = (*outputLayer->getState().hwc).hwcLayer;
     auto error = hwcLayer->setVisibleRegion(visible);
     if (error != HWC2::Error::None) {
         ALOGE("[%s] Failed to set visible region: %s (%d)", mName.string(),
               to_string(error).c_str(), static_cast<int32_t>(error));
         visible.dump(LOG_TAG);
     }
-    getBE().compositionInfo.hwc.visibleRegion = visible;
+    outputLayer->editState().visibleRegion = visible;
 
     error = hwcLayer->setSurfaceDamage(surfaceDamageRegion);
     if (error != HWC2::Error::None) {
@@ -268,7 +274,7 @@
 
     // Sideband layers
     if (getBE().compositionInfo.hwc.sidebandStream.get()) {
-        setCompositionType(displayId, HWC2::Composition::Sideband);
+        setCompositionType(displayDevice, Hwc2::IComposerClient::Composition::SIDEBAND);
         ALOGV("[%s] Requesting Sideband composition", mName.string());
         error = hwcLayer->setSidebandStream(getBE().compositionInfo.hwc.sidebandStream->handle());
         if (error != HWC2::Error::None) {
@@ -283,10 +289,10 @@
     // Device or Cursor layers
     if (mPotentialCursor) {
         ALOGV("[%s] Requesting Cursor composition", mName.string());
-        setCompositionType(displayId, HWC2::Composition::Cursor);
+        setCompositionType(displayDevice, Hwc2::IComposerClient::Composition::CURSOR);
     } else {
         ALOGV("[%s] Requesting Device composition", mName.string());
-        setCompositionType(displayId, HWC2::Composition::Device);
+        setCompositionType(displayDevice, Hwc2::IComposerClient::Composition::DEVICE);
     }
 
     ALOGV("setPerFrameData: dataspace = %d", mCurrentDataSpace);
@@ -313,7 +319,7 @@
     getBE().compositionInfo.hwc.supportedPerFrameMetadata = supportedPerFrameMetadata;
     getBE().compositionInfo.hwc.colorTransform = getColorTransform();
 
-    setHwcLayerBuffer(displayId);
+    setHwcLayerBuffer(displayDevice);
 }
 
 bool BufferLayer::onPreComposition(nsecs_t refreshStartTime) {
@@ -605,9 +611,21 @@
     return true;
 }
 
-bool BufferLayer::needsFiltering() const {
-    const auto displayFrame = getBE().compositionInfo.hwc.displayFrame;
-    const auto sourceCrop = getBE().compositionInfo.hwc.sourceCrop;
+bool BufferLayer::needsFiltering(const sp<const DisplayDevice>& displayDevice) const {
+    // If we are not capturing based on the state of a known display device, we
+    // only return mNeedsFiltering
+    if (displayDevice == nullptr) {
+        return mNeedsFiltering;
+    }
+
+    const auto outputLayer = findOutputLayerForDisplay(displayDevice);
+    if (outputLayer == nullptr) {
+        return mNeedsFiltering;
+    }
+
+    const auto& compositionState = outputLayer->getState();
+    const auto displayFrame = compositionState.displayFrame;
+    const auto sourceCrop = compositionState.sourceCrop;
     return mNeedsFiltering || sourceCrop.getHeight() != displayFrame.getHeight() ||
             sourceCrop.getWidth() != displayFrame.getWidth();
 }
diff --git a/services/surfaceflinger/BufferLayer.h b/services/surfaceflinger/BufferLayer.h
index 0f8a350..d358bae 100644
--- a/services/surfaceflinger/BufferLayer.h
+++ b/services/surfaceflinger/BufferLayer.h
@@ -80,8 +80,8 @@
 
     bool isHdrY410() const override;
 
-    void setPerFrameData(DisplayId displayId, const ui::Transform& transform, const Rect& viewport,
-                         int32_t supportedPerFrameMetadata) override;
+    void setPerFrameData(const sp<const DisplayDevice>& display, const ui::Transform& transform,
+                         const Rect& viewport, int32_t supportedPerFrameMetadata) override;
 
     bool onPreComposition(nsecs_t refreshStartTime) override;
     bool onPostComposition(const std::optional<DisplayId>& displayId,
@@ -148,7 +148,7 @@
     virtual status_t updateActiveBuffer() = 0;
     virtual status_t updateFrameNumber(nsecs_t latchTime) = 0;
 
-    virtual void setHwcLayerBuffer(DisplayId displayId) = 0;
+    virtual void setHwcLayerBuffer(const sp<const DisplayDevice>& displayDevice) = 0;
 
 protected:
     // Loads the corresponding system property once per process
@@ -177,7 +177,7 @@
 
 private:
     // Returns true if this layer requires filtering
-    bool needsFiltering() const;
+    bool needsFiltering(const sp<const DisplayDevice>& displayDevice) const;
 
     uint64_t getHeadFrameNumber() const;
 
diff --git a/services/surfaceflinger/BufferQueueLayer.cpp b/services/surfaceflinger/BufferQueueLayer.cpp
index 0313c32..b66a46a 100644
--- a/services/surfaceflinger/BufferQueueLayer.cpp
+++ b/services/surfaceflinger/BufferQueueLayer.cpp
@@ -14,13 +14,16 @@
  * limitations under the License.
  */
 
+#include <compositionengine/Display.h>
+#include <compositionengine/OutputLayer.h>
+#include <compositionengine/impl/OutputLayerCompositionState.h>
+#include <system/window.h>
+
 #include "BufferQueueLayer.h"
 #include "LayerRejecter.h"
 
 #include "TimeStats/TimeStats.h"
 
-#include <system/window.h>
-
 namespace android {
 
 BufferQueueLayer::BufferQueueLayer(const LayerCreationArgs& args) : BufferLayer(args) {}
@@ -350,13 +353,16 @@
     return NO_ERROR;
 }
 
-void BufferQueueLayer::setHwcLayerBuffer(DisplayId displayId) {
-    auto& hwcInfo = getBE().mHwcLayers[displayId];
-    auto& hwcLayer = hwcInfo.layer;
+void BufferQueueLayer::setHwcLayerBuffer(const sp<const DisplayDevice>& display) {
+    const auto outputLayer = findOutputLayerForDisplay(display);
+    LOG_FATAL_IF(!outputLayer);
+    LOG_FATAL_IF(!outputLayer->getState.hwc);
+    auto& hwcLayer = (*outputLayer->getState().hwc).hwcLayer;
 
     uint32_t hwcSlot = 0;
     sp<GraphicBuffer> hwcBuffer;
-    hwcInfo.bufferCache.getHwcBuffer(mActiveBufferSlot, mActiveBuffer, &hwcSlot, &hwcBuffer);
+    (*outputLayer->editState().hwc)
+            .hwcBufferCache.getHwcBuffer(mActiveBufferSlot, mActiveBuffer, &hwcSlot, &hwcBuffer);
 
     auto acquireFence = mConsumer->getCurrentFence();
     auto error = hwcLayer->setBuffer(hwcSlot, hwcBuffer, acquireFence);
diff --git a/services/surfaceflinger/BufferQueueLayer.h b/services/surfaceflinger/BufferQueueLayer.h
index d392a69..30107e2 100644
--- a/services/surfaceflinger/BufferQueueLayer.h
+++ b/services/surfaceflinger/BufferQueueLayer.h
@@ -97,7 +97,7 @@
     status_t updateActiveBuffer() override;
     status_t updateFrameNumber(nsecs_t latchTime) override;
 
-    void setHwcLayerBuffer(DisplayId displayId) override;
+    void setHwcLayerBuffer(const sp<const DisplayDevice>& displayDevice) override;
 
     // -----------------------------------------------------------------------
     // Interface implementation for BufferLayerConsumer::ContentsChangedListener
diff --git a/services/surfaceflinger/BufferStateLayer.cpp b/services/surfaceflinger/BufferStateLayer.cpp
index 2d6da76..369e71f 100644
--- a/services/surfaceflinger/BufferStateLayer.cpp
+++ b/services/surfaceflinger/BufferStateLayer.cpp
@@ -19,15 +19,17 @@
 #define LOG_TAG "BufferStateLayer"
 #define ATRACE_TAG ATRACE_TAG_GRAPHICS
 
-#include "BufferStateLayer.h"
-#include "ColorLayer.h"
+#include <limits>
 
-#include "TimeStats/TimeStats.h"
-
+#include <compositionengine/Display.h>
+#include <compositionengine/OutputLayer.h>
+#include <compositionengine/impl/OutputLayerCompositionState.h>
 #include <private/gui/SyncFeatures.h>
 #include <renderengine/Image.h>
 
-#include <limits>
+#include "BufferStateLayer.h"
+#include "ColorLayer.h"
+#include "TimeStats/TimeStats.h"
 
 namespace android {
 
@@ -611,9 +613,10 @@
     return NO_ERROR;
 }
 
-void BufferStateLayer::setHwcLayerBuffer(DisplayId displayId) {
-    auto& hwcInfo = getBE().mHwcLayers[displayId];
-    auto& hwcLayer = hwcInfo.layer;
+void BufferStateLayer::setHwcLayerBuffer(const sp<const DisplayDevice>& display) {
+    const auto outputLayer = findOutputLayerForDisplay(display);
+    LOG_FATAL_IF(!outputLayer || !outputLayer->getState().hwc);
+    auto& hwcLayer = (*outputLayer->getState().hwc).hwcLayer;
 
     const State& s(getDrawingState());
 
diff --git a/services/surfaceflinger/BufferStateLayer.h b/services/surfaceflinger/BufferStateLayer.h
index 3320c5b..a97f0a4 100644
--- a/services/surfaceflinger/BufferStateLayer.h
+++ b/services/surfaceflinger/BufferStateLayer.h
@@ -131,7 +131,7 @@
     status_t updateActiveBuffer() override;
     status_t updateFrameNumber(nsecs_t latchTime) override;
 
-    void setHwcLayerBuffer(DisplayId displayId) override;
+    void setHwcLayerBuffer(const sp<const DisplayDevice>& display) override;
 
 private:
     void onFirstRef() override;
diff --git a/services/surfaceflinger/ColorLayer.cpp b/services/surfaceflinger/ColorLayer.cpp
index d82ff0e..c901673 100644
--- a/services/surfaceflinger/ColorLayer.cpp
+++ b/services/surfaceflinger/ColorLayer.cpp
@@ -23,8 +23,11 @@
 #include <sys/types.h>
 
 #include <compositionengine/CompositionEngine.h>
+#include <compositionengine/Display.h>
 #include <compositionengine/Layer.h>
 #include <compositionengine/LayerCreationArgs.h>
+#include <compositionengine/OutputLayer.h>
+#include <compositionengine/impl/OutputLayerCompositionState.h>
 #include <renderengine/RenderEngine.h>
 #include <ui/GraphicBuffer.h>
 #include <utils/Errors.h>
@@ -73,23 +76,27 @@
     return true;
 }
 
-void ColorLayer::setPerFrameData(DisplayId displayId, const ui::Transform& transform,
-                                 const Rect& viewport, int32_t /* supportedPerFrameMetadata */) {
-    RETURN_IF_NO_HWC_LAYER(displayId);
+void ColorLayer::setPerFrameData(const sp<const DisplayDevice>& display,
+                                 const ui::Transform& transform, const Rect& viewport,
+                                 int32_t /* supportedPerFrameMetadata */) {
+    RETURN_IF_NO_HWC_LAYER(display);
 
     Region visible = transform.transform(visibleRegion.intersect(viewport));
 
-    auto& hwcInfo = getBE().mHwcLayers[displayId];
-    auto& hwcLayer = hwcInfo.layer;
+    const auto outputLayer = findOutputLayerForDisplay(display);
+    LOG_FATAL_IF(!outputLayer || !outputLayer->getState().hwc);
+
+    auto& hwcLayer = (*outputLayer->getState().hwc).hwcLayer;
+
     auto error = hwcLayer->setVisibleRegion(visible);
     if (error != HWC2::Error::None) {
         ALOGE("[%s] Failed to set visible region: %s (%d)", mName.string(),
               to_string(error).c_str(), static_cast<int32_t>(error));
         visible.dump(LOG_TAG);
     }
-    getBE().compositionInfo.hwc.visibleRegion = visible;
+    outputLayer->editState().visibleRegion = visible;
 
-    setCompositionType(displayId, HWC2::Composition::SolidColor);
+    setCompositionType(display, Hwc2::IComposerClient::Composition::SOLID_COLOR);
 
     error = hwcLayer->setDataspace(mCurrentDataSpace);
     if (error != HWC2::Error::None) {
@@ -116,7 +123,7 @@
         ALOGE("[%s] Failed to clear transform: %s (%d)", mName.string(), to_string(error).c_str(),
               static_cast<int32_t>(error));
     }
-    getBE().compositionInfo.hwc.transform = HWC2::Transform::None;
+    outputLayer->editState().bufferTransform = static_cast<Hwc2::Transform>(0);
 
     error = hwcLayer->setColorTransform(getColorTransform());
     if (error != HWC2::Error::None) {
diff --git a/services/surfaceflinger/ColorLayer.h b/services/surfaceflinger/ColorLayer.h
index ed4c2d8..df0adac 100644
--- a/services/surfaceflinger/ColorLayer.h
+++ b/services/surfaceflinger/ColorLayer.h
@@ -35,8 +35,8 @@
 
     bool setColor(const half3& color) override;
 
-    void setPerFrameData(DisplayId displayId, const ui::Transform& transform, const Rect& viewport,
-                         int32_t supportedPerFrameMetadata) override;
+    void setPerFrameData(const sp<const DisplayDevice>& display, const ui::Transform& transform,
+                         const Rect& viewport, int32_t supportedPerFrameMetadata) override;
 
     bool onPreComposition(nsecs_t /*refreshStartTime*/) override { return false; }
 
diff --git a/services/surfaceflinger/CompositionEngine/Android.bp b/services/surfaceflinger/CompositionEngine/Android.bp
index ce6b06c..e934f8b 100644
--- a/services/surfaceflinger/CompositionEngine/Android.bp
+++ b/services/surfaceflinger/CompositionEngine/Android.bp
@@ -5,6 +5,7 @@
         "-DLOG_TAG=\"CompositionEngine\"",
     ],
     shared_libs: [
+        "android.frameworks.vr.composer@1.0",
         "android.hardware.graphics.allocator@2.0",
         "android.hardware.graphics.composer@2.1",
         "android.hardware.graphics.composer@2.2",
@@ -28,6 +29,9 @@
         "libtrace_proto",
     ],
     header_libs: [
+        "android.hardware.graphics.composer@2.1-command-buffer",
+        "android.hardware.graphics.composer@2.2-command-buffer",
+        "android.hardware.graphics.composer@2.3-command-buffer",
         "libsurfaceflinger_headers",
     ],
 }
@@ -46,6 +50,7 @@
         "src/Output.cpp",
         "src/OutputCompositionState.cpp",
         "src/OutputLayer.cpp",
+        "src/OutputLayerCompositionState.cpp",
         "src/RenderSurface.cpp",
     ],
     local_include_dirs: ["include"],
diff --git a/services/surfaceflinger/CompositionEngine/include/compositionengine/OutputLayer.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/OutputLayer.h
index 4b8ef38..48cb581 100644
--- a/services/surfaceflinger/CompositionEngine/include/compositionengine/OutputLayer.h
+++ b/services/surfaceflinger/CompositionEngine/include/compositionengine/OutputLayer.h
@@ -16,14 +16,22 @@
 
 #pragma once
 
+#include <string>
+
 #include <utils/StrongPointer.h>
 
-namespace android::compositionengine {
+namespace android {
+
+namespace compositionengine {
 
 class Output;
 class Layer;
 class LayerFE;
 
+namespace impl {
+struct OutputLayerCompositionState;
+} // namespace impl
+
 /**
  * An output layer contains the output-dependent composition state for a layer
  */
@@ -39,6 +47,22 @@
 
     // Gets the front-end layer interface this output layer represents
     virtual LayerFE& getLayerFE() const = 0;
+
+    using CompositionState = compositionengine::impl::OutputLayerCompositionState;
+
+    // Gets the raw composition state data for the layer
+    // TODO(lpique): Make this protected once it is only internally called.
+    virtual const CompositionState& getState() const = 0;
+
+    // Allows mutable access to the raw composition state data for the layer.
+    // This is meant to be used by the various functions that are part of the
+    // composition process.
+    // TODO(lpique): Make this protected once it is only internally called.
+    virtual CompositionState& editState() = 0;
+
+    // Debugging
+    virtual void dump(std::string& result) const = 0;
 };
 
-} // namespace android::compositionengine
+} // namespace compositionengine
+} // namespace android
diff --git a/services/surfaceflinger/CompositionEngine/include/compositionengine/RenderSurface.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/RenderSurface.h
index ddeb730..2009380 100644
--- a/services/surfaceflinger/CompositionEngine/include/compositionengine/RenderSurface.h
+++ b/services/surfaceflinger/CompositionEngine/include/compositionengine/RenderSurface.h
@@ -29,8 +29,6 @@
 
 class GraphicBuffer;
 
-struct CompositionInfo;
-
 namespace compositionengine {
 
 /**
@@ -70,7 +68,7 @@
     virtual status_t beginFrame(bool mustRecompose) = 0;
 
     // Prepares the frame for rendering
-    virtual status_t prepareFrame(std::vector<CompositionInfo>& compositionData) = 0;
+    virtual status_t prepareFrame() = 0;
 
     // Allocates a buffer as scratch space for GPU composition
     virtual sp<GraphicBuffer> dequeueBuffer() = 0;
diff --git a/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/OutputLayer.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/OutputLayer.h
index f3d0258..5798540 100644
--- a/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/OutputLayer.h
+++ b/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/OutputLayer.h
@@ -17,8 +17,10 @@
 #pragma once
 
 #include <memory>
+#include <string>
 
 #include <compositionengine/OutputLayer.h>
+#include <compositionengine/impl/OutputLayerCompositionState.h>
 
 namespace android::compositionengine::impl {
 
@@ -32,10 +34,17 @@
     compositionengine::Layer& getLayer() const override;
     compositionengine::LayerFE& getLayerFE() const override;
 
+    const OutputLayerCompositionState& getState() const override;
+    OutputLayerCompositionState& editState() override;
+
+    void dump(std::string& result) const override;
+
 private:
     const compositionengine::Output& mOutput;
     std::shared_ptr<compositionengine::Layer> mLayer;
     sp<compositionengine::LayerFE> mLayerFE;
+
+    OutputLayerCompositionState mState;
 };
 
 std::unique_ptr<compositionengine::OutputLayer> createOutputLayer(
diff --git a/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/OutputLayerCompositionState.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/OutputLayerCompositionState.h
new file mode 100644
index 0000000..b78e9e0
--- /dev/null
+++ b/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/OutputLayerCompositionState.h
@@ -0,0 +1,91 @@
+/*
+ * Copyright 2019 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.
+ */
+
+#pragma once
+
+#include <cstdint>
+#include <optional>
+#include <string>
+
+#include <compositionengine/impl/HwcBufferCache.h>
+#include <renderengine/Mesh.h>
+#include <ui/FloatRect.h>
+#include <ui/Rect.h>
+#include <ui/Region.h>
+
+#include "DisplayHardware/ComposerHal.h"
+
+namespace HWC2 {
+class Layer;
+} // namespace HWC2
+
+namespace android {
+
+class HWComposer;
+
+namespace compositionengine::impl {
+
+struct OutputLayerCompositionState {
+    // The region of this layer which is visible on this output
+    Region visibleRegion;
+
+    // If true, client composition will be used on this output
+    bool forceClientComposition{false};
+
+    // If true, when doing client composition, the target may need to be cleared
+    bool clearClientTarget{false};
+
+    // The display frame for this layer on this output
+    Rect displayFrame;
+
+    // The source crop for this layer on this output
+    FloatRect sourceCrop;
+
+    // The buffer transform to use for this layer o on this output.
+    Hwc2::Transform bufferTransform{static_cast<Hwc2::Transform>(0)};
+
+    // The Z order index of this layer on this output
+    uint32_t z;
+
+    /*
+     * HWC state
+     */
+
+    struct Hwc {
+        explicit Hwc(std::shared_ptr<HWC2::Layer> hwcLayer) : hwcLayer(hwcLayer) {}
+
+        // The HWC Layer backing this layer
+        std::shared_ptr<HWC2::Layer> hwcLayer;
+
+        // The HWC composition type for this layer
+        Hwc2::IComposerClient::Composition hwcCompositionType{
+                Hwc2::IComposerClient::Composition::INVALID};
+
+        // The buffer cache for this layer. This is used to lower the
+        // cost of sending reused buffers to the HWC.
+        HwcBufferCache hwcBufferCache;
+    };
+
+    // The HWC state is optional, and is only set up if there is any potential
+    // HWC acceleration possible.
+    std::optional<Hwc> hwc;
+
+    // Debugging
+    void dump(std::string& result) const;
+};
+
+} // namespace compositionengine::impl
+} // namespace android
diff --git a/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/RenderSurface.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/RenderSurface.h
index 2f0fceb..58b13ed 100644
--- a/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/RenderSurface.h
+++ b/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/RenderSurface.h
@@ -51,7 +51,7 @@
     void setDisplaySize(const ui::Size&) override;
     void setProtected(bool useProtected) override;
     status_t beginFrame(bool mustRecompose) override;
-    status_t prepareFrame(std::vector<CompositionInfo>& compositionData) override;
+    status_t prepareFrame() override;
     sp<GraphicBuffer> dequeueBuffer() override;
     void queueBuffer(base::unique_fd&& readyFence) override;
     void onPresentDisplayCompleted() override;
diff --git a/services/surfaceflinger/CompositionEngine/include/compositionengine/mock/OutputLayer.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/mock/OutputLayer.h
index f5e5026..6bd61ee 100644
--- a/services/surfaceflinger/CompositionEngine/include/compositionengine/mock/OutputLayer.h
+++ b/services/surfaceflinger/CompositionEngine/include/compositionengine/mock/OutputLayer.h
@@ -20,6 +20,7 @@
 #include <compositionengine/LayerFE.h>
 #include <compositionengine/Output.h>
 #include <compositionengine/OutputLayer.h>
+#include <compositionengine/impl/OutputLayerCompositionState.h>
 #include <gmock/gmock.h>
 
 namespace android::compositionengine::mock {
@@ -32,6 +33,11 @@
     MOCK_CONST_METHOD0(getOutput, const compositionengine::Output&());
     MOCK_CONST_METHOD0(getLayer, compositionengine::Layer&());
     MOCK_CONST_METHOD0(getLayerFE, compositionengine::LayerFE&());
+
+    MOCK_CONST_METHOD0(getState, const impl::OutputLayerCompositionState&());
+    MOCK_METHOD0(editState, impl::OutputLayerCompositionState&());
+
+    MOCK_CONST_METHOD1(dump, void(std::string&));
 };
 
 } // namespace android::compositionengine::mock
diff --git a/services/surfaceflinger/CompositionEngine/include/compositionengine/mock/RenderSurface.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/mock/RenderSurface.h
index e9ff330..8442bef 100644
--- a/services/surfaceflinger/CompositionEngine/include/compositionengine/mock/RenderSurface.h
+++ b/services/surfaceflinger/CompositionEngine/include/compositionengine/mock/RenderSurface.h
@@ -20,7 +20,6 @@
 #include <gmock/gmock.h>
 #include <ui/GraphicBuffer.h>
 
-#include "LayerBE.h"
 
 namespace android::compositionengine::mock {
 
@@ -37,7 +36,7 @@
     MOCK_METHOD1(setProtected, void(bool));
     MOCK_METHOD1(setBufferDataspace, void(ui::Dataspace));
     MOCK_METHOD1(beginFrame, status_t(bool mustRecompose));
-    MOCK_METHOD1(prepareFrame, status_t(std::vector<CompositionInfo>& compositionData));
+    MOCK_METHOD0(prepareFrame, status_t());
     MOCK_METHOD0(dequeueBuffer, sp<GraphicBuffer>());
     MOCK_METHOD1(queueBuffer, void(base::unique_fd&&));
     MOCK_METHOD0(onPresentDisplayCompleted, void());
diff --git a/services/surfaceflinger/CompositionEngine/src/Output.cpp b/services/surfaceflinger/CompositionEngine/src/Output.cpp
index e103ebe..f97add4 100644
--- a/services/surfaceflinger/CompositionEngine/src/Output.cpp
+++ b/services/surfaceflinger/CompositionEngine/src/Output.cpp
@@ -146,6 +146,14 @@
     } else {
         out.append("    No render surface!\n");
     }
+
+    out.append("\n   %d Layers", mOutputLayersOrderedByZ.size());
+    for (const auto& outputLayer : mOutputLayersOrderedByZ) {
+        if (!outputLayer) {
+            continue;
+        }
+        outputLayer->dump(out);
+    }
 }
 
 compositionengine::DisplayColorProfile* Output::getDisplayColorProfile() const {
diff --git a/services/surfaceflinger/CompositionEngine/src/OutputLayer.cpp b/services/surfaceflinger/CompositionEngine/src/OutputLayer.cpp
index e95f3a6..78c1403 100644
--- a/services/surfaceflinger/CompositionEngine/src/OutputLayer.cpp
+++ b/services/surfaceflinger/CompositionEngine/src/OutputLayer.cpp
@@ -14,6 +14,7 @@
  * limitations under the License.
  */
 
+#include <android-base/stringprintf.h>
 #include <compositionengine/Layer.h>
 #include <compositionengine/LayerFE.h>
 #include <compositionengine/Output.h>
@@ -48,5 +49,20 @@
     return *mLayerFE;
 }
 
+const OutputLayerCompositionState& OutputLayer::getState() const {
+    return mState;
+}
+
+OutputLayerCompositionState& OutputLayer::editState() {
+    return mState;
+}
+
+void OutputLayer::dump(std::string& out) const {
+    using android::base::StringAppendF;
+
+    StringAppendF(&out, "     Output Layer %p\n", this);
+    mState.dump(out);
+}
+
 } // namespace impl
 } // namespace android::compositionengine
diff --git a/services/surfaceflinger/CompositionEngine/src/OutputLayerCompositionState.cpp b/services/surfaceflinger/CompositionEngine/src/OutputLayerCompositionState.cpp
new file mode 100644
index 0000000..10f27b8
--- /dev/null
+++ b/services/surfaceflinger/CompositionEngine/src/OutputLayerCompositionState.cpp
@@ -0,0 +1,59 @@
+/*
+ * Copyright 2019 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.
+ */
+
+#include <compositionengine/impl/DumpHelpers.h>
+#include <compositionengine/impl/OutputLayerCompositionState.h>
+
+#include "DisplayHardware/HWC2.h"
+
+namespace android::compositionengine::impl {
+
+namespace {
+
+void dumpHwc(const OutputLayerCompositionState::Hwc& hwc, std::string& out) {
+    out.append("\n      hwc: ");
+
+    if (hwc.hwcLayer == nullptr) {
+        out.append("No layer ");
+    } else {
+        dumpHex(out, "layer", hwc.hwcLayer->getId());
+    }
+
+    dumpVal(out, "composition", toString(hwc.hwcCompositionType), hwc.hwcCompositionType);
+}
+
+} // namespace
+
+void OutputLayerCompositionState::dump(std::string& out) const {
+    out.append("      ");
+    dumpVal(out, "visibleRegion", visibleRegion);
+
+    out.append("      ");
+    dumpVal(out, "forceClientComposition", forceClientComposition);
+    dumpVal(out, "clearClientTarget", clearClientTarget);
+    dumpVal(out, "displayFrame", displayFrame);
+    dumpVal(out, "sourceCrop", sourceCrop);
+    dumpVal(out, "bufferTransform%", toString(bufferTransform), bufferTransform);
+    dumpVal(out, "z-index", z);
+
+    if (hwc) {
+        dumpHwc(*hwc, out);
+    }
+
+    out.append("\n");
+}
+
+} // namespace android::compositionengine::impl
diff --git a/services/surfaceflinger/CompositionEngine/src/RenderSurface.cpp b/services/surfaceflinger/CompositionEngine/src/RenderSurface.cpp
index 3f841d2..ebb1bc2 100644
--- a/services/surfaceflinger/CompositionEngine/src/RenderSurface.cpp
+++ b/services/surfaceflinger/CompositionEngine/src/RenderSurface.cpp
@@ -99,11 +99,11 @@
     return mDisplaySurface->beginFrame(mustRecompose);
 }
 
-status_t RenderSurface::prepareFrame(std::vector<CompositionInfo>& compositionData) {
+status_t RenderSurface::prepareFrame() {
     auto& hwc = mCompositionEngine.getHwComposer();
     const auto id = mDisplay.getId();
     if (id) {
-        status_t error = hwc.prepare(*id, compositionData);
+        status_t error = hwc.prepare(*id, mDisplay);
         if (error != NO_ERROR) {
             return error;
         }
diff --git a/services/surfaceflinger/CompositionEngine/tests/MockHWComposer.h b/services/surfaceflinger/CompositionEngine/tests/MockHWComposer.h
index ece412f..885cdd4 100644
--- a/services/surfaceflinger/CompositionEngine/tests/MockHWComposer.h
+++ b/services/surfaceflinger/CompositionEngine/tests/MockHWComposer.h
@@ -16,10 +16,9 @@
 
 #pragma once
 
+#include <compositionengine/Output.h>
 #include <gmock/gmock.h>
 
-#include "LayerBE.h"
-
 #include "DisplayHardware/HWComposer.h"
 
 namespace android {
@@ -41,7 +40,7 @@
                  std::optional<DisplayId>(uint32_t, uint32_t, ui::PixelFormat*));
     MOCK_METHOD1(createLayer, HWC2::Layer*(DisplayId));
     MOCK_METHOD2(destroyLayer, void(DisplayId, HWC2::Layer*));
-    MOCK_METHOD2(prepare, status_t(DisplayId, std::vector<CompositionInfo>&));
+    MOCK_METHOD2(prepare, status_t(DisplayId, const compositionengine::Output&));
     MOCK_METHOD5(setClientTarget,
                  status_t(DisplayId, uint32_t, const sp<Fence>&, const sp<GraphicBuffer>&,
                           ui::Dataspace));
diff --git a/services/surfaceflinger/CompositionEngine/tests/RenderSurfaceTest.cpp b/services/surfaceflinger/CompositionEngine/tests/RenderSurfaceTest.cpp
index c56d92a..0a7c462 100644
--- a/services/surfaceflinger/CompositionEngine/tests/RenderSurfaceTest.cpp
+++ b/services/surfaceflinger/CompositionEngine/tests/RenderSurfaceTest.cpp
@@ -22,6 +22,7 @@
 #include <compositionengine/mock/CompositionEngine.h>
 #include <compositionengine/mock/Display.h>
 #include <compositionengine/mock/DisplaySurface.h>
+#include <compositionengine/mock/OutputLayer.h>
 #include <gtest/gtest.h>
 #include <renderengine/mock/RenderEngine.h>
 #include <system/window.h>
@@ -284,64 +285,66 @@
  * RenderSurface::prepareFrame()
  */
 
-TEST_F(RenderSurfaceTest, prepareFrameTakesEarlyOutOnHwcError) {
-    std::vector<CompositionInfo> data;
-
-    EXPECT_CALL(mHwComposer, prepare(*DEFAULT_DISPLAY_ID, Ref(data)))
+TEST_F(RenderSurfaceTest, prepareFramePassesOutputLayersToHwc) {
+    EXPECT_CALL(mHwComposer, prepare(*DEFAULT_DISPLAY_ID, Ref(mDisplay)))
             .WillOnce(Return(INVALID_OPERATION));
 
-    EXPECT_EQ(INVALID_OPERATION, mSurface.prepareFrame(data));
+    EXPECT_EQ(INVALID_OPERATION, mSurface.prepareFrame());
+}
+
+TEST_F(RenderSurfaceTest, prepareFrameTakesEarlyOutOnHwcError) {
+    EXPECT_CALL(mHwComposer, prepare(*DEFAULT_DISPLAY_ID, Ref(mDisplay)))
+            .WillOnce(Return(INVALID_OPERATION));
+
+    EXPECT_EQ(INVALID_OPERATION, mSurface.prepareFrame());
 }
 
 TEST_F(RenderSurfaceTest, prepareFrameHandlesMixedComposition) {
-    std::vector<CompositionInfo> data;
-    EXPECT_CALL(mHwComposer, prepare(*DEFAULT_DISPLAY_ID, Ref(data))).WillOnce(Return(NO_ERROR));
+    EXPECT_CALL(mHwComposer, prepare(*DEFAULT_DISPLAY_ID, Ref(mDisplay)))
+            .WillOnce(Return(NO_ERROR));
     EXPECT_CALL(mHwComposer, hasClientComposition(DEFAULT_DISPLAY_ID)).WillOnce(Return(true));
     EXPECT_CALL(mHwComposer, hasDeviceComposition(DEFAULT_DISPLAY_ID)).WillOnce(Return(true));
 
     EXPECT_CALL(*mDisplaySurface, prepareFrame(DisplaySurface::COMPOSITION_MIXED))
             .WillOnce(Return(INVALID_OPERATION));
 
-    EXPECT_EQ(INVALID_OPERATION, mSurface.prepareFrame(data));
+    EXPECT_EQ(INVALID_OPERATION, mSurface.prepareFrame());
 }
 
 TEST_F(RenderSurfaceTest, prepareFrameHandlesOnlyGlesComposition) {
-    std::vector<CompositionInfo> data;
-
-    EXPECT_CALL(mHwComposer, prepare(*DEFAULT_DISPLAY_ID, Ref(data))).WillOnce(Return(NO_ERROR));
+    EXPECT_CALL(mHwComposer, prepare(*DEFAULT_DISPLAY_ID, Ref(mDisplay)))
+            .WillOnce(Return(NO_ERROR));
     EXPECT_CALL(mHwComposer, hasClientComposition(DEFAULT_DISPLAY_ID)).WillOnce(Return(true));
     EXPECT_CALL(mHwComposer, hasDeviceComposition(DEFAULT_DISPLAY_ID)).WillOnce(Return(false));
 
     EXPECT_CALL(*mDisplaySurface, prepareFrame(DisplaySurface::COMPOSITION_GLES))
             .WillOnce(Return(NO_ERROR));
 
-    EXPECT_EQ(NO_ERROR, mSurface.prepareFrame(data));
+    EXPECT_EQ(NO_ERROR, mSurface.prepareFrame());
 }
 
 TEST_F(RenderSurfaceTest, prepareFrameHandlesOnlyHwcComposition) {
-    std::vector<CompositionInfo> data;
-
-    EXPECT_CALL(mHwComposer, prepare(*DEFAULT_DISPLAY_ID, Ref(data))).WillOnce(Return(NO_ERROR));
+    EXPECT_CALL(mHwComposer, prepare(*DEFAULT_DISPLAY_ID, Ref(mDisplay)))
+            .WillOnce(Return(NO_ERROR));
     EXPECT_CALL(mHwComposer, hasClientComposition(DEFAULT_DISPLAY_ID)).WillOnce(Return(false));
     EXPECT_CALL(mHwComposer, hasDeviceComposition(DEFAULT_DISPLAY_ID)).WillOnce(Return(true));
 
     EXPECT_CALL(*mDisplaySurface, prepareFrame(DisplaySurface::COMPOSITION_HWC))
             .WillOnce(Return(NO_ERROR));
 
-    EXPECT_EQ(NO_ERROR, mSurface.prepareFrame(data));
+    EXPECT_EQ(NO_ERROR, mSurface.prepareFrame());
 }
 
 TEST_F(RenderSurfaceTest, prepareFrameHandlesNoComposition) {
-    std::vector<CompositionInfo> data;
-
-    EXPECT_CALL(mHwComposer, prepare(*DEFAULT_DISPLAY_ID, Ref(data))).WillOnce(Return(NO_ERROR));
+    EXPECT_CALL(mHwComposer, prepare(*DEFAULT_DISPLAY_ID, Ref(mDisplay)))
+            .WillOnce(Return(NO_ERROR));
     EXPECT_CALL(mHwComposer, hasClientComposition(DEFAULT_DISPLAY_ID)).WillOnce(Return(false));
     EXPECT_CALL(mHwComposer, hasDeviceComposition(DEFAULT_DISPLAY_ID)).WillOnce(Return(false));
 
     EXPECT_CALL(*mDisplaySurface, prepareFrame(DisplaySurface::COMPOSITION_HWC))
             .WillOnce(Return(NO_ERROR));
 
-    EXPECT_EQ(NO_ERROR, mSurface.prepareFrame(data));
+    EXPECT_EQ(NO_ERROR, mSurface.prepareFrame());
 }
 
 /* ------------------------------------------------------------------------
diff --git a/services/surfaceflinger/ContainerLayer.cpp b/services/surfaceflinger/ContainerLayer.cpp
index 941b4ad..22c40d7 100644
--- a/services/surfaceflinger/ContainerLayer.cpp
+++ b/services/surfaceflinger/ContainerLayer.cpp
@@ -39,6 +39,7 @@
     return !isHiddenByPolicy();
 }
 
-void ContainerLayer::setPerFrameData(DisplayId, const ui::Transform&, const Rect&, int32_t) {}
+void ContainerLayer::setPerFrameData(const sp<const DisplayDevice>&, const ui::Transform&,
+                                     const Rect&, int32_t) {}
 
 } // namespace android
diff --git a/services/surfaceflinger/ContainerLayer.h b/services/surfaceflinger/ContainerLayer.h
index fec82d7..c69997d 100644
--- a/services/surfaceflinger/ContainerLayer.h
+++ b/services/surfaceflinger/ContainerLayer.h
@@ -33,8 +33,8 @@
 
     bool canReceiveInput() const override;
 
-    void setPerFrameData(DisplayId displayId, const ui::Transform& transform, const Rect& viewport,
-                         int32_t supportedPerFrameMetadata) override;
+    void setPerFrameData(const sp<const DisplayDevice>& display, const ui::Transform& transform,
+                         const Rect& viewport, int32_t supportedPerFrameMetadata) override;
 
     bool isCreatedFromMainThread() const override { return true; }
 
diff --git a/services/surfaceflinger/DisplayDevice.h b/services/surfaceflinger/DisplayDevice.h
index 9674f0d..a827c47 100644
--- a/services/surfaceflinger/DisplayDevice.h
+++ b/services/surfaceflinger/DisplayDevice.h
@@ -266,6 +266,7 @@
     int getHeight() const override { return mDevice->getHeight(); }
     int getWidth() const override { return mDevice->getWidth(); }
     bool isSecure() const override { return mDevice->isSecure(); }
+    const sp<const DisplayDevice> getDisplayDevice() const override { return mDevice; }
 
     bool needsFiltering() const override {
         // check if the projection from the logical display to the physical
diff --git a/services/surfaceflinger/DisplayHardware/HWComposer.cpp b/services/surfaceflinger/DisplayHardware/HWComposer.cpp
index 5b4d347..3b9e0e6 100644
--- a/services/surfaceflinger/DisplayHardware/HWComposer.cpp
+++ b/services/surfaceflinger/DisplayHardware/HWComposer.cpp
@@ -20,13 +20,14 @@
 #define LOG_TAG "HWComposer"
 #define ATRACE_TAG ATRACE_TAG_GRAPHICS
 
-#include <utils/Errors.h>
-#include <utils/Trace.h>
-
+#include <compositionengine/Output.h>
+#include <compositionengine/OutputLayer.h>
+#include <compositionengine/impl/OutputLayerCompositionState.h>
+#include <log/log.h>
 #include <ui/DebugUtils.h>
 #include <ui/GraphicBuffer.h>
-
-#include <log/log.h>
+#include <utils/Errors.h>
+#include <utils/Trace.h>
 
 #include "HWComposer.h"
 #include "HWC2.h"
@@ -398,7 +399,7 @@
     return NO_ERROR;
 }
 
-status_t HWComposer::prepare(DisplayId displayId, std::vector<CompositionInfo>& compositionData) {
+status_t HWComposer::prepare(DisplayId displayId, const compositionengine::Output& output) {
     ATRACE_CALL();
 
     RETURN_IF_INVALID_DISPLAY(displayId, BAD_INDEX);
@@ -462,47 +463,42 @@
 
     displayData.hasClientComposition = false;
     displayData.hasDeviceComposition = false;
-    for (auto& compositionInfo : compositionData) {
-        auto hwcLayer = compositionInfo.hwc.hwcLayer;
+    for (auto& outputLayer : output.getOutputLayersOrderedByZ()) {
+        auto& state = outputLayer->editState();
+        LOG_FATAL_IF(!state.hwc.);
+        auto hwcLayer = (*state.hwc).hwcLayer;
 
-        if (changedTypes.count(&*hwcLayer) != 0) {
-            // We pass false so we only update our state and don't call back
-            // into the HWC device
-            validateChange(compositionInfo.compositionType,
-                    changedTypes[&*hwcLayer]);
-            compositionInfo.compositionType = changedTypes[&*hwcLayer];
-            compositionInfo.layer->mLayer->setCompositionType(displayId,
-                                                              compositionInfo.compositionType,
-                                                              false);
+        if (auto it = changedTypes.find(hwcLayer.get()); it != changedTypes.end()) {
+            auto newCompositionType = it->second;
+            validateChange(static_cast<HWC2::Composition>((*state.hwc).hwcCompositionType),
+                           newCompositionType);
+            (*state.hwc).hwcCompositionType =
+                    static_cast<Hwc2::IComposerClient::Composition>(newCompositionType);
         }
 
-        switch (compositionInfo.compositionType) {
-            case HWC2::Composition::Client:
+        switch ((*state.hwc).hwcCompositionType) {
+            case Hwc2::IComposerClient::Composition::CLIENT:
                 displayData.hasClientComposition = true;
                 break;
-            case HWC2::Composition::Device:
-            case HWC2::Composition::SolidColor:
-            case HWC2::Composition::Cursor:
-            case HWC2::Composition::Sideband:
+            case Hwc2::IComposerClient::Composition::DEVICE:
+            case Hwc2::IComposerClient::Composition::SOLID_COLOR:
+            case Hwc2::IComposerClient::Composition::CURSOR:
+            case Hwc2::IComposerClient::Composition::SIDEBAND:
                 displayData.hasDeviceComposition = true;
                 break;
             default:
                 break;
         }
 
-        if (layerRequests.count(&*hwcLayer) != 0 &&
-                layerRequests[&*hwcLayer] ==
-                        HWC2::LayerRequest::ClearClientTarget) {
-            compositionInfo.hwc.clearClientTarget = true;
-            compositionInfo.layer->mLayer->setClearClientTarget(displayId, true);
-        } else {
-            if (layerRequests.count(&*hwcLayer) != 0) {
+        state.clearClientTarget = false;
+        if (auto it = layerRequests.find(hwcLayer.get()); it != layerRequests.end()) {
+            auto request = it->second;
+            if (request == HWC2::LayerRequest::ClearClientTarget) {
+                state.clearClientTarget = true;
+            } else {
                 LOG_DISPLAY_ERROR(displayId,
-                                  ("Unknown layer request " + to_string(layerRequests[&*hwcLayer]))
-                                          .c_str());
+                                  ("Unknown layer request " + to_string(request)).c_str());
             }
-            compositionInfo.hwc.clearClientTarget = false;
-            compositionInfo.layer->mLayer->setClearClientTarget(displayId, false);
         }
     }
 
diff --git a/services/surfaceflinger/DisplayHardware/HWComposer.h b/services/surfaceflinger/DisplayHardware/HWComposer.h
index f42f860..ca59a26 100644
--- a/services/surfaceflinger/DisplayHardware/HWComposer.h
+++ b/services/surfaceflinger/DisplayHardware/HWComposer.h
@@ -45,6 +45,10 @@
 class Composer;
 } // namespace Hwc2
 
+namespace compositionengine {
+class Output;
+} // namespace compositionengine
+
 class HWComposer {
 public:
     virtual ~HWComposer();
@@ -68,8 +72,7 @@
     virtual void destroyLayer(DisplayId displayId, HWC2::Layer* layer) = 0;
 
     // Asks the HAL what it can do
-    virtual status_t prepare(DisplayId displayId,
-                             std::vector<CompositionInfo>& compositionData) = 0;
+    virtual status_t prepare(DisplayId displayId, const compositionengine::Output&) = 0;
 
     virtual status_t setClientTarget(DisplayId displayId, uint32_t slot,
                                      const sp<Fence>& acquireFence, const sp<GraphicBuffer>& target,
@@ -205,7 +208,7 @@
     void destroyLayer(DisplayId displayId, HWC2::Layer* layer) override;
 
     // Asks the HAL what it can do
-    status_t prepare(DisplayId displayId, std::vector<CompositionInfo>& compositionData) override;
+    status_t prepare(DisplayId displayId, const compositionengine::Output&) override;
 
     status_t setClientTarget(DisplayId displayId, uint32_t slot, const sp<Fence>& acquireFence,
                              const sp<GraphicBuffer>& target, ui::Dataspace dataspace) override;
diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp
index 51e1f00..69ec638 100644
--- a/services/surfaceflinger/Layer.cpp
+++ b/services/surfaceflinger/Layer.cpp
@@ -24,44 +24,40 @@
 #include <stdlib.h>
 #include <sys/types.h>
 #include <algorithm>
+#include <mutex>
 
 #include <android-base/stringprintf.h>
-
+#include <compositionengine/Display.h>
+#include <compositionengine/OutputLayer.h>
+#include <compositionengine/impl/OutputLayerCompositionState.h>
 #include <cutils/compiler.h>
 #include <cutils/native_handle.h>
 #include <cutils/properties.h>
-
+#include <gui/BufferItem.h>
+#include <gui/LayerDebugInfo.h>
+#include <gui/Surface.h>
+#include <renderengine/RenderEngine.h>
+#include <ui/DebugUtils.h>
+#include <ui/GraphicBuffer.h>
+#include <ui/PixelFormat.h>
 #include <utils/Errors.h>
 #include <utils/Log.h>
 #include <utils/NativeHandle.h>
 #include <utils/StopWatch.h>
 #include <utils/Trace.h>
 
-#include <ui/DebugUtils.h>
-#include <ui/GraphicBuffer.h>
-#include <ui/PixelFormat.h>
-
-#include <gui/BufferItem.h>
-#include <gui/LayerDebugInfo.h>
-#include <gui/Surface.h>
-
 #include "BufferLayer.h"
 #include "ColorLayer.h"
 #include "Colorizer.h"
 #include "DisplayDevice.h"
+#include "DisplayHardware/HWComposer.h"
 #include "Layer.h"
+#include "LayerProtoHelper.h"
 #include "LayerRejecter.h"
 #include "MonitoredProducer.h"
 #include "SurfaceFlinger.h"
-
-#include "DisplayHardware/HWComposer.h"
 #include "TimeStats/TimeStats.h"
 
-#include <renderengine/RenderEngine.h>
-
-#include <mutex>
-#include "LayerProtoHelper.h"
-
 #define DEBUG_RESIZE 0
 
 namespace android {
@@ -211,9 +207,16 @@
 // h/w composer set-up
 // ---------------------------------------------------------------------------
 
-bool Layer::createHwcLayer(HWComposer* hwc, DisplayId displayId) {
-    LOG_ALWAYS_FATAL_IF(hasHwcLayer(displayId), "Already have a layer for display %s",
-                        to_string(displayId).c_str());
+bool Layer::createHwcLayer(HWComposer* hwc, const sp<DisplayDevice>& displayDevice) {
+    LOG_ALWAYS_FATAL_IF(!displayDevice->getId());
+    auto displayId = *displayDevice->getId();
+    auto outputLayer = findOutputLayerForDisplay(displayDevice);
+    LOG_ALWAYS_FATAL_IF(!outputLayer);
+
+    LOG_ALWAYS_FATAL_IF(outputLayer->getState().hwc.has_value(),
+                        "Already have a layer for display %s",
+                        displayDevice->getDisplayName().c_str());
+
     auto layer = std::shared_ptr<HWC2::Layer>(
             hwc->createLayer(displayId),
             [hwc, displayId](HWC2::Layer* layer) {
@@ -221,42 +224,56 @@
     if (!layer) {
         return false;
     }
-    LayerBE::HWCInfo& hwcInfo = getBE().mHwcLayers[displayId];
-    hwcInfo.hwc = hwc;
-    hwcInfo.layer = layer;
-    layer->setLayerDestroyedListener(
-            [this, displayId](HWC2::Layer* /*layer*/) { getBE().mHwcLayers.erase(displayId); });
+    auto& state = outputLayer->editState();
+    state.hwc.emplace(layer);
     return true;
 }
 
-bool Layer::destroyHwcLayer(DisplayId displayId) {
-    if (!hasHwcLayer(displayId)) {
+bool Layer::destroyHwcLayer(const sp<DisplayDevice>& displayDevice) {
+    auto outputLayer = findOutputLayerForDisplay(displayDevice);
+    if (outputLayer == nullptr) {
         return false;
     }
-    auto& hwcInfo = getBE().mHwcLayers[displayId];
-    LOG_ALWAYS_FATAL_IF(hwcInfo.layer == nullptr, "Attempt to destroy null layer");
-    LOG_ALWAYS_FATAL_IF(hwcInfo.hwc == nullptr, "Missing HWComposer");
-    hwcInfo.layer = nullptr;
-
-    return true;
+    auto& state = outputLayer->editState();
+    bool result = state.hwc.has_value();
+    state.hwc.reset();
+    return result;
 }
 
-void Layer::destroyHwcLayersForAllDisplays() {
-    size_t numLayers = getBE().mHwcLayers.size();
-    for (size_t i = 0; i < numLayers; ++i) {
-        LOG_ALWAYS_FATAL_IF(getBE().mHwcLayers.empty(), "destroyAllHwcLayers failed");
-        destroyHwcLayer(getBE().mHwcLayers.begin()->first);
+bool Layer::destroyHwcLayersForAllDisplays() {
+    bool destroyedAnyLayers = false;
+
+    for (const auto& [token, displayDevice] : mFlinger->mDisplays) {
+        if (destroyHwcLayer(displayDevice)) {
+            destroyedAnyLayers = true;
+        }
     }
+
+    return destroyedAnyLayers;
 }
 
-void Layer::destroyAllHwcLayersPlusChildren() {
-    destroyHwcLayersForAllDisplays();
-    LOG_ALWAYS_FATAL_IF(!getBE().mHwcLayers.empty(),
-                        "All hardware composer layers should have been destroyed");
+bool Layer::destroyAllHwcLayersPlusChildren() {
+    bool result = destroyHwcLayersForAllDisplays();
 
     for (const sp<Layer>& child : mDrawingChildren) {
-        child->destroyAllHwcLayersPlusChildren();
+        result |= child->destroyAllHwcLayersPlusChildren();
     }
+
+    return result;
+}
+
+bool Layer::hasHwcLayer(const sp<const DisplayDevice>& displayDevice) {
+    auto outputLayer = findOutputLayerForDisplay(displayDevice);
+    LOG_FATAL_IF(!outputLayer);
+    return outputLayer->getState().hwc && (*outputLayer->getState().hwc).hwcLayer != nullptr;
+}
+
+HWC2::Layer* Layer::getHwcLayer(const sp<const DisplayDevice>& displayDevice) {
+    auto outputLayer = findOutputLayerForDisplay(displayDevice);
+    if (!outputLayer || !outputLayer->getState().hwc) {
+        return nullptr;
+    }
+    return (*outputLayer->getState().hwc).hwcLayer.get();
 }
 
 Rect Layer::getContentCrop() const {
@@ -494,19 +511,25 @@
 }
 
 void Layer::setGeometry(const sp<const DisplayDevice>& display, uint32_t z) {
-    const auto displayId = display->getId();
-    LOG_ALWAYS_FATAL_IF(!displayId);
-    RETURN_IF_NO_HWC_LAYER(*displayId);
-    auto& hwcInfo = getBE().mHwcLayers[*displayId];
+    const auto outputLayer = findOutputLayerForDisplay(display);
+    LOG_FATAL_IF(!outputLayer);
+    LOG_FATAL_IF(!outputLayer->getState().hwc);
+    auto& hwcLayer = (*outputLayer->getState().hwc).hwcLayer;
 
-    // enable this layer
-    hwcInfo.forceClientComposition = false;
-
-    if (isSecure() && !display->isSecure()) {
-        hwcInfo.forceClientComposition = true;
+    if (!hasHwcLayer(display)) {
+        ALOGE("[%s] failed to setGeometry: no HWC layer found (%s)", mName.string(),
+              display->getDebugName().c_str());
+        return;
     }
 
-    auto& hwcLayer = hwcInfo.layer;
+    auto& compositionState = outputLayer->editState();
+
+    // enable this layer
+    compositionState.forceClientComposition = false;
+
+    if (isSecure() && !display->isSecure()) {
+        compositionState.forceClientComposition = true;
+    }
 
     // this gives us only the "orientation" component of the transform
     const State& s(getDrawingState());
@@ -567,9 +590,8 @@
               transformedFrame.left, transformedFrame.top, transformedFrame.right,
               transformedFrame.bottom, to_string(error).c_str(), static_cast<int32_t>(error));
     } else {
-        hwcInfo.displayFrame = transformedFrame;
+        compositionState.displayFrame = transformedFrame;
     }
-    getBE().compositionInfo.hwc.displayFrame = transformedFrame;
 
     FloatRect sourceCrop = computeCrop(display);
     error = hwcLayer->setSourceCrop(sourceCrop);
@@ -579,9 +601,8 @@
               mName.string(), sourceCrop.left, sourceCrop.top, sourceCrop.right, sourceCrop.bottom,
               to_string(error).c_str(), static_cast<int32_t>(error));
     } else {
-        hwcInfo.sourceCrop = sourceCrop;
+        compositionState.sourceCrop = sourceCrop;
     }
-    getBE().compositionInfo.hwc.sourceCrop = sourceCrop;
 
     float alpha = static_cast<float>(getAlpha());
     error = hwcLayer->setPlaneAlpha(alpha);
@@ -594,7 +615,7 @@
     error = hwcLayer->setZOrder(z);
     ALOGE_IF(error != HWC2::Error::None, "[%s] Failed to set Z %u: %s (%d)", mName.string(), z,
              to_string(error).c_str(), static_cast<int32_t>(error));
-    getBE().compositionInfo.hwc.z = z;
+    compositionState.z = z;
 
     int type = s.metadata.getInt32(METADATA_WINDOW_TYPE, 0);
     int appId = s.metadata.getInt32(METADATA_OWNER_UID, 0);
@@ -651,35 +672,39 @@
     const uint32_t orientation = transform.getOrientation();
     if (orientation & ui::Transform::ROT_INVALID) {
         // we can only handle simple transformation
-        hwcInfo.forceClientComposition = true;
-        getBE().mHwcLayers[*displayId].compositionType = HWC2::Composition::Client;
+        compositionState.forceClientComposition = true;
+        (*compositionState.hwc).hwcCompositionType = Hwc2::IComposerClient::Composition::CLIENT;
     } else {
         auto transform = static_cast<HWC2::Transform>(orientation);
-        hwcInfo.transform = transform;
         auto error = hwcLayer->setTransform(transform);
         ALOGE_IF(error != HWC2::Error::None,
                  "[%s] Failed to set transform %s: "
                  "%s (%d)",
                  mName.string(), to_string(transform).c_str(), to_string(error).c_str(),
                  static_cast<int32_t>(error));
-        getBE().compositionInfo.hwc.transform = transform;
+        compositionState.bufferTransform = static_cast<Hwc2::Transform>(transform);
     }
 }
 
-void Layer::forceClientComposition(DisplayId displayId) {
-    RETURN_IF_NO_HWC_LAYER(displayId);
-    getBE().mHwcLayers[displayId].forceClientComposition = true;
+void Layer::forceClientComposition(const sp<DisplayDevice>& display) {
+    const auto outputLayer = findOutputLayerForDisplay(display);
+    LOG_FATAL_IF(!outputLayer);
+    outputLayer->editState().forceClientComposition = true;
 }
 
-bool Layer::getForceClientComposition(DisplayId displayId) {
-    RETURN_IF_NO_HWC_LAYER(displayId, false);
-    return getBE().mHwcLayers[displayId].forceClientComposition;
+bool Layer::getForceClientComposition(const sp<DisplayDevice>& display) {
+    const auto outputLayer = findOutputLayerForDisplay(display);
+    LOG_FATAL_IF(!outputLayer);
+    return outputLayer->getState().forceClientComposition;
 }
 
 void Layer::updateCursorPosition(const sp<const DisplayDevice>& display) {
-    const auto displayId = display->getId();
-    LOG_ALWAYS_FATAL_IF(!displayId);
-    if (!hasHwcLayer(*displayId) || getCompositionType(displayId) != HWC2::Composition::Cursor) {
+    const auto outputLayer = findOutputLayerForDisplay(display);
+    LOG_FATAL_IF(!outputLayer);
+
+    if (!outputLayer->getState().hwc ||
+        (*outputLayer->getState().hwc).hwcCompositionType !=
+                Hwc2::IComposerClient::Composition::CURSOR) {
         return;
     }
 
@@ -697,8 +722,7 @@
     auto position = displayTransform.transform(frame);
 
     auto error =
-            getBE().mHwcLayers[*displayId].layer->setCursorPosition(position.left, position.top);
-
+            (*outputLayer->getState().hwc).hwcLayer->setCursorPosition(position.left, position.top);
     ALOGE_IF(error != HWC2::Error::None,
              "[%s] Failed to set cursor position "
              "to (%d, %d): %s (%d)",
@@ -769,56 +793,41 @@
     clearWithOpenGL(renderArea, 0, 0, 0, 0);
 }
 
-void Layer::setCompositionType(DisplayId displayId, HWC2::Composition type, bool callIntoHwc) {
-    if (getBE().mHwcLayers.count(displayId) == 0) {
-        ALOGE("setCompositionType called without a valid HWC layer");
-        return;
-    }
-    auto& hwcInfo = getBE().mHwcLayers[displayId];
-    auto& hwcLayer = hwcInfo.layer;
-    ALOGV("setCompositionType(%" PRIx64 ", %s, %d)", (hwcLayer)->getId(), to_string(type).c_str(),
-          static_cast<int>(callIntoHwc));
-    if (hwcInfo.compositionType != type) {
+void Layer::setCompositionType(const sp<const DisplayDevice>& display,
+                               Hwc2::IComposerClient::Composition type) {
+    const auto outputLayer = findOutputLayerForDisplay(display);
+    LOG_FATAL_IF(!outputLayer);
+    LOG_FATAL_IF(!outputLayer->getState().hwc);
+    auto& compositionState = outputLayer->editState();
+
+    ALOGV("setCompositionType(%" PRIx64 ", %s, %d)", ((*compositionState.hwc).hwcLayer)->getId(),
+          toString(type).c_str(), 1);
+    if ((*compositionState.hwc).hwcCompositionType != type) {
         ALOGV("    actually setting");
-        hwcInfo.compositionType = type;
-        if (callIntoHwc) {
-            auto error = (hwcLayer)->setCompositionType(type);
-            ALOGE_IF(error != HWC2::Error::None,
-                     "[%s] Failed to set "
-                     "composition type %s: %s (%d)",
-                     mName.string(), to_string(type).c_str(), to_string(error).c_str(),
-                     static_cast<int32_t>(error));
-        }
+        (*compositionState.hwc).hwcCompositionType = type;
+
+        auto error = (*compositionState.hwc)
+                             .hwcLayer->setCompositionType(static_cast<HWC2::Composition>(type));
+        ALOGE_IF(error != HWC2::Error::None,
+                 "[%s] Failed to set "
+                 "composition type %s: %s (%d)",
+                 mName.string(), toString(type).c_str(), to_string(error).c_str(),
+                 static_cast<int32_t>(error));
     }
 }
 
-HWC2::Composition Layer::getCompositionType(const std::optional<DisplayId>& displayId) const {
-    if (!displayId) {
-        // If we're querying the composition type for a display that does not
-        // have a HWC counterpart, then it will always be Client
-        return HWC2::Composition::Client;
-    }
-    if (getBE().mHwcLayers.count(*displayId) == 0) {
-        ALOGE("getCompositionType called with an invalid HWC layer");
-        return HWC2::Composition::Invalid;
-    }
-    return getBE().mHwcLayers.at(*displayId).compositionType;
+Hwc2::IComposerClient::Composition Layer::getCompositionType(
+        const sp<const DisplayDevice>& display) const {
+    const auto outputLayer = findOutputLayerForDisplay(display);
+    LOG_FATAL_IF(!outputLayer);
+    return outputLayer->getState().hwc ? (*outputLayer->getState().hwc).hwcCompositionType
+                                       : Hwc2::IComposerClient::Composition::CLIENT;
 }
 
-void Layer::setClearClientTarget(DisplayId displayId, bool clear) {
-    if (getBE().mHwcLayers.count(displayId) == 0) {
-        ALOGE("setClearClientTarget called without a valid HWC layer");
-        return;
-    }
-    getBE().mHwcLayers[displayId].clearClientTarget = clear;
-}
-
-bool Layer::getClearClientTarget(DisplayId displayId) const {
-    if (getBE().mHwcLayers.count(displayId) == 0) {
-        ALOGE("getClearClientTarget called without a valid HWC layer");
-        return false;
-    }
-    return getBE().mHwcLayers.at(displayId).clearClientTarget;
+bool Layer::getClearClientTarget(const sp<const DisplayDevice>& display) const {
+    const auto outputLayer = findOutputLayerForDisplay(display);
+    LOG_FATAL_IF(!outputLayer);
+    return outputLayer->getState().clearClientTarget;
 }
 
 bool Layer::addSyncPoint(const std::shared_ptr<SyncPoint>& point) {
@@ -1535,8 +1544,9 @@
     result.append("-----------------------------\n");
 }
 
-void Layer::miniDump(std::string& result, DisplayId displayId) const {
-    if (!hasHwcLayer(displayId)) {
+void Layer::miniDump(std::string& result, const sp<DisplayDevice>& displayDevice) const {
+    auto outputLayer = findOutputLayerForDisplay(displayDevice);
+    if (!outputLayer) {
         return;
     }
 
@@ -1554,17 +1564,21 @@
     StringAppendF(&result, " %s\n", name.c_str());
 
     const State& layerState(getDrawingState());
-    const LayerBE::HWCInfo& hwcInfo = getBE().mHwcLayers.at(displayId);
+    const auto& compositionState = outputLayer->getState();
+
     if (layerState.zOrderRelativeOf != nullptr || mDrawingParent != nullptr) {
         StringAppendF(&result, "  rel %6d | ", layerState.z);
     } else {
         StringAppendF(&result, "  %10d | ", layerState.z);
     }
-    StringAppendF(&result, "%10s | ", to_string(getCompositionType(displayId)).c_str());
-    StringAppendF(&result, "%10s | ", to_string(hwcInfo.transform).c_str());
-    const Rect& frame = hwcInfo.displayFrame;
+    StringAppendF(&result, "%10s | ", toString(getCompositionType(displayDevice)).c_str());
+    StringAppendF(&result, "%10s | ",
+                  toString(getCompositionLayer() ? compositionState.bufferTransform
+                                                 : static_cast<Hwc2::Transform>(0))
+                          .c_str());
+    const Rect& frame = compositionState.displayFrame;
     StringAppendF(&result, "%4d %4d %4d %4d | ", frame.left, frame.top, frame.right, frame.bottom);
-    const FloatRect& crop = hwcInfo.sourceCrop;
+    const FloatRect& crop = compositionState.sourceCrop;
     StringAppendF(&result, "%6.1f %6.1f %6.1f %6.1f\n", crop.left, crop.top, crop.right,
                   crop.bottom);
 
@@ -2164,25 +2178,29 @@
     LayerProtoHelper::writeToProto(mBounds, layerInfo->mutable_bounds());
 }
 
-void Layer::writeToProto(LayerProto* layerInfo, DisplayId displayId) {
-    if (!hasHwcLayer(displayId)) {
+void Layer::writeToProto(LayerProto* layerInfo, const sp<DisplayDevice>& displayDevice) {
+    auto outputLayer = findOutputLayerForDisplay(displayDevice);
+    if (!outputLayer) {
         return;
     }
 
     writeToProto(layerInfo, LayerVector::StateSet::Drawing);
 
-    const auto& hwcInfo = getBE().mHwcLayers.at(displayId);
+    const auto& compositionState = outputLayer->getState();
 
-    const Rect& frame = hwcInfo.displayFrame;
+    const Rect& frame = compositionState.displayFrame;
     LayerProtoHelper::writeToProto(frame, layerInfo->mutable_hwc_frame());
 
-    const FloatRect& crop = hwcInfo.sourceCrop;
+    const FloatRect& crop = compositionState.sourceCrop;
     LayerProtoHelper::writeToProto(crop, layerInfo->mutable_hwc_crop());
 
-    const int32_t transform = static_cast<int32_t>(hwcInfo.transform);
+    const int32_t transform =
+            getCompositionLayer() ? static_cast<int32_t>(compositionState.bufferTransform) : 0;
     layerInfo->set_hwc_transform(transform);
 
-    const int32_t compositionType = static_cast<int32_t>(hwcInfo.compositionType);
+    const int32_t compositionType =
+            static_cast<int32_t>(compositionState.hwc ? (*compositionState.hwc).hwcCompositionType
+                                                      : Hwc2::IComposerClient::Composition::CLIENT);
     layerInfo->set_hwc_composition_type(compositionType);
 
     if (std::strcmp(getTypeId(), "BufferLayer") == 0 &&
@@ -2249,6 +2267,11 @@
     return isVisible();
 }
 
+compositionengine::OutputLayer* Layer::findOutputLayerForDisplay(
+        const sp<const DisplayDevice>& display) const {
+    return display->getCompositionDisplay()->getOutputLayerForLayer(getCompositionLayer().get());
+}
+
 // ---------------------------------------------------------------------------
 
 }; // namespace android
diff --git a/services/surfaceflinger/Layer.h b/services/surfaceflinger/Layer.h
index 9241e71..45e7443 100644
--- a/services/surfaceflinger/Layer.h
+++ b/services/surfaceflinger/Layer.h
@@ -51,6 +51,7 @@
 #include "SurfaceFlinger.h"
 #include "TransactionCompletedThread.h"
 
+#include "DisplayHardware/ComposerHal.h"
 #include "DisplayHardware/HWComposer.h"
 #include "RenderArea.h"
 
@@ -70,6 +71,7 @@
 
 namespace compositionengine {
 class Layer;
+class OutputLayer;
 }
 
 namespace impl {
@@ -419,7 +421,7 @@
     void writeToProto(LayerProto* layerInfo,
                       LayerVector::StateSet stateSet = LayerVector::StateSet::Drawing);
 
-    void writeToProto(LayerProto* layerInfo, DisplayId displayId);
+    void writeToProto(LayerProto* layerInfo, const sp<DisplayDevice>& displayDevice);
 
     virtual Geometry getActiveGeometry(const Layer::State& s) const { return s.active_legacy; }
     virtual uint32_t getActiveWidth(const Layer::State& s) const { return s.active_legacy.w; }
@@ -443,17 +445,19 @@
     virtual bool isHdrY410() const { return false; }
 
     void setGeometry(const sp<const DisplayDevice>& display, uint32_t z);
-    void forceClientComposition(DisplayId displayId);
-    bool getForceClientComposition(DisplayId displayId);
-    virtual void setPerFrameData(DisplayId displayId, const ui::Transform& transform,
-                                 const Rect& viewport, int32_t supportedPerFrameMetadata) = 0;
+    void forceClientComposition(const sp<DisplayDevice>& display);
+    bool getForceClientComposition(const sp<DisplayDevice>& display);
+    virtual void setPerFrameData(const sp<const DisplayDevice>& display,
+                                 const ui::Transform& transform, const Rect& viewport,
+                                 int32_t supportedPerFrameMetadata) = 0;
 
     // callIntoHwc exists so we can update our local state and call
     // acceptDisplayChanges without unnecessarily updating the device's state
-    void setCompositionType(DisplayId displayId, HWC2::Composition type, bool callIntoHwc = true);
-    HWC2::Composition getCompositionType(const std::optional<DisplayId>& displayId) const;
-    void setClearClientTarget(DisplayId displayId, bool clear);
-    bool getClearClientTarget(DisplayId displayId) const;
+    void setCompositionType(const sp<const DisplayDevice>& display,
+                            Hwc2::IComposerClient::Composition type);
+    Hwc2::IComposerClient::Composition getCompositionType(
+            const sp<const DisplayDevice>& display) const;
+    bool getClearClientTarget(const sp<const DisplayDevice>& display) const;
     void updateCursorPosition(const sp<const DisplayDevice>& display);
 
     /*
@@ -567,27 +571,13 @@
 
     // -----------------------------------------------------------------------
 
-    bool createHwcLayer(HWComposer* hwc, DisplayId displayId);
-    bool destroyHwcLayer(DisplayId displayId);
-    void destroyHwcLayersForAllDisplays();
-    void destroyAllHwcLayersPlusChildren();
+    bool createHwcLayer(HWComposer* hwc, const sp<DisplayDevice>& display);
+    bool destroyHwcLayer(const sp<DisplayDevice>& display);
+    bool destroyHwcLayersForAllDisplays();
+    bool destroyAllHwcLayersPlusChildren();
 
-    bool hasHwcLayer(DisplayId displayId) const { return getBE().mHwcLayers.count(displayId) > 0; }
-
-    HWC2::Layer* getHwcLayer(DisplayId displayId) {
-        if (!hasHwcLayer(displayId)) {
-            return nullptr;
-        }
-        return getBE().mHwcLayers[displayId].layer.get();
-    }
-
-    bool setHwcLayer(DisplayId displayId) {
-        if (!hasHwcLayer(displayId)) {
-            return false;
-        }
-        getBE().compositionInfo.hwc.hwcLayer = getBE().mHwcLayers[displayId].layer;
-        return true;
-    }
+    bool hasHwcLayer(const sp<const DisplayDevice>& displayDevice);
+    HWC2::Layer* getHwcLayer(const sp<const DisplayDevice>& displayDevice);
 
     // -----------------------------------------------------------------------
     void clearWithOpenGL(const RenderArea& renderArea) const;
@@ -600,7 +590,7 @@
 
     /* always call base class first */
     static void miniDumpHeader(std::string& result);
-    void miniDump(std::string& result, DisplayId displayId) const;
+    void miniDump(std::string& result, const sp<DisplayDevice>& display) const;
     void dumpFrameStats(std::string& result) const;
     void dumpFrameEvents(std::string& result);
     void clearFrameStats();
@@ -676,6 +666,9 @@
         return parentBounds;
     }
 
+    compositionengine::OutputLayer* findOutputLayerForDisplay(
+            const sp<const DisplayDevice>& display) const;
+
 protected:
     // constant
     sp<SurfaceFlinger> mFlinger;
@@ -920,11 +913,11 @@
 
 } // namespace android
 
-#define RETURN_IF_NO_HWC_LAYER(displayId, ...)                                         \
+#define RETURN_IF_NO_HWC_LAYER(displayDevice, ...)                                     \
     do {                                                                               \
-        if (!hasHwcLayer(displayId)) {                                                 \
+        if (!hasHwcLayer(displayDevice)) {                                             \
             ALOGE("[%s] %s failed: no HWC layer found for display %s", mName.string(), \
-                  __FUNCTION__, to_string(displayId).c_str());                         \
+                  __FUNCTION__, displayDevice->getDebugName().c_str());                \
             return __VA_ARGS__;                                                        \
         }                                                                              \
     } while (false)
diff --git a/services/surfaceflinger/LayerBE.cpp b/services/surfaceflinger/LayerBE.cpp
index e39babe..4bf5325 100644
--- a/services/surfaceflinger/LayerBE.cpp
+++ b/services/surfaceflinger/LayerBE.cpp
@@ -87,21 +87,12 @@
         result += base::StringPrintf("[%s]HWC parameters\n", tag);
     }
 
-    result += base::StringPrintf("\thwcLayer=%p\n", static_cast<HWC2::Layer*>(&*hwc.hwcLayer));
     result += base::StringPrintf("\tfence=%p\n", hwc.fence.get());
     result += base::StringPrintf("\tblendMode=%d\n", hwc.blendMode);
-    result += base::StringPrintf("\ttransform=%d\n", hwc.transform);
-    result += base::StringPrintf("\tz=%d\n", hwc.z);
     result += base::StringPrintf("\ttype=%d\n", hwc.type);
     result += base::StringPrintf("\tappId=%d\n", hwc.appId);
-    result += base::StringPrintf("\tdisplayFrame=%4d %4d %4d %4d\n", hwc.displayFrame.left,
-                                 hwc.displayFrame.top, hwc.displayFrame.right,
-                                 hwc.displayFrame.bottom);
     result += base::StringPrintf("\talpha=%.3f", hwc.alpha);
-    result += base::StringPrintf("\tsourceCrop=%6.1f %6.1f %6.1f %6.1f\n", hwc.sourceCrop.left,
-                                 hwc.sourceCrop.top, hwc.sourceCrop.right, hwc.sourceCrop.bottom);
 
-    hwc.visibleRegion.dump(result, "visibleRegion");
     hwc.surfaceDamage.dump(result, "surfaceDamage");
 
     result += base::StringPrintf("\tcolor transform matrix:\n"
@@ -146,12 +137,7 @@
                                  getCompositionName(compositionType));
     result += base::StringPrintf("\tmBuffer = %p\n", mBuffer.get());
     result += base::StringPrintf("\tmBufferSlot=%d\n", mBufferSlot);
-    result += base::StringPrintf("\tdisplayFrame=%4d %4d %4d %4d\n", hwc.displayFrame.left,
-                                 hwc.displayFrame.top, hwc.displayFrame.right,
-                                 hwc.displayFrame.bottom);
     result += base::StringPrintf("\talpha=%f\n", hwc.alpha);
-    result += base::StringPrintf("\tsourceCrop=%6.1f %6.1f %6.1f %6.1f\n", hwc.sourceCrop.left,
-                                 hwc.sourceCrop.top, hwc.sourceCrop.right, hwc.sourceCrop.bottom);
 
     switch (compositionType) {
         case HWC2::Composition::Device:
diff --git a/services/surfaceflinger/LayerBE.h b/services/surfaceflinger/LayerBE.h
index 6270efa..e41632c 100644
--- a/services/surfaceflinger/LayerBE.h
+++ b/services/surfaceflinger/LayerBE.h
@@ -19,8 +19,6 @@
 #include <stdint.h>
 #include <sys/types.h>
 
-#include <compositionengine/impl/HwcBufferCache.h>
-
 #include <renderengine/Mesh.h>
 #include <renderengine/RenderEngine.h>
 #include <renderengine/Texture.h>
@@ -42,23 +40,17 @@
     int mBufferSlot = BufferQueue::INVALID_BUFFER_SLOT;
     std::shared_ptr<LayerBE> layer;
     struct {
-        std::shared_ptr<HWC2::Layer> hwcLayer;
         DisplayId displayId;
         sp<Fence> fence;
         HWC2::BlendMode blendMode = HWC2::BlendMode::Invalid;
-        Rect displayFrame;
         float alpha;
-        FloatRect sourceCrop;
         HWC2::Transform transform = HWC2::Transform::None;
-        int z;
         int type;
         int appId;
-        Region visibleRegion;
         Region surfaceDamage;
         sp<NativeHandle> sidebandStream;
         ui::Dataspace dataspace;
         hwc_color_t color;
-        bool clearClientTarget = false;
         bool supportedPerFrameMetadata = false;
         HdrMetadata hdrMetadata;
         mat4 colorTransform;
@@ -104,33 +96,6 @@
     // The mesh used to draw the layer in GLES composition mode
     renderengine::Mesh mMesh;
 
-    // HWC items, accessed from the main thread
-    struct HWCInfo {
-        HWCInfo()
-              : hwc(nullptr),
-                layer(nullptr),
-                forceClientComposition(false),
-                compositionType(HWC2::Composition::Invalid),
-                clearClientTarget(false),
-                transform(HWC2::Transform::None) {}
-
-        HWComposer* hwc;
-        std::shared_ptr<HWC2::Layer> layer;
-        bool forceClientComposition;
-        HWC2::Composition compositionType;
-        bool clearClientTarget;
-        Rect displayFrame;
-        FloatRect sourceCrop;
-        compositionengine::impl::HwcBufferCache bufferCache;
-        HWC2::Transform transform;
-    };
-
-    // A layer can be attached to multiple displays when operating in mirror mode
-    // (a.k.a: when several displays are attached with equal layerStack). In this
-    // case we need to keep track. In non-mirror mode, a layer will have only one
-    // HWCInfo.
-    std::unordered_map<DisplayId, HWCInfo> mHwcLayers;
-
     CompositionInfo compositionInfo;
 };
 
diff --git a/services/surfaceflinger/RenderArea.h b/services/surfaceflinger/RenderArea.h
index 9bad6de..edc6442 100644
--- a/services/surfaceflinger/RenderArea.h
+++ b/services/surfaceflinger/RenderArea.h
@@ -7,6 +7,8 @@
 
 namespace android {
 
+class DisplayDevice;
+
 // RenderArea describes a rectangular area that layers can be rendered to.
 //
 // There is a logical render area and a physical render area.  When a layer is
@@ -76,6 +78,8 @@
     // covered by any rendered layer should be filled with this color.
     CaptureFill getCaptureFill() const { return mCaptureFill; };
 
+    virtual const sp<const DisplayDevice> getDisplayDevice() const = 0;
+
 private:
     const uint32_t mReqWidth;
     const uint32_t mReqHeight;
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp
index 85411b6..37f7631 100644
--- a/services/surfaceflinger/SurfaceFlinger.cpp
+++ b/services/surfaceflinger/SurfaceFlinger.cpp
@@ -44,6 +44,7 @@
 #include <compositionengine/OutputLayer.h>
 #include <compositionengine/RenderSurface.h>
 #include <compositionengine/impl/OutputCompositionState.h>
+#include <compositionengine/impl/OutputLayerCompositionState.h>
 #include <dvr/vr_flinger.h>
 #include <gui/BufferQueue.h>
 #include <gui/GuiConfig.h>
@@ -1823,11 +1824,6 @@
     mVsyncModulator.onRefreshed(mHadClientComposition);
 
     getBE().mEndOfFrameCompositionInfo = std::move(getBE().mCompositionInfo);
-    for (const auto& [token, display] : mDisplays) {
-        for (auto& compositionInfo : getBE().mEndOfFrameCompositionInfo[token]) {
-            compositionInfo.hwc.hwcLayer = nullptr;
-        }
-    }
 
     mLayersWithQueuedFrames.clear();
 }
@@ -1868,16 +1864,16 @@
             for (size_t i = 0; i < currentLayers.size(); i++) {
                 const auto& layer = currentLayers[i];
 
-                if (!layer->hasHwcLayer(*displayId)) {
-                    if (!layer->createHwcLayer(&getHwComposer(), *displayId)) {
-                        layer->forceClientComposition(*displayId);
+                if (!layer->hasHwcLayer(displayDevice)) {
+                    if (!layer->createHwcLayer(&getHwComposer(), displayDevice)) {
+                        layer->forceClientComposition(displayDevice);
                         continue;
                     }
                 }
 
                 layer->setGeometry(displayDevice, i);
                 if (mDebugDisableHWC || mDebugRegion) {
-                    layer->forceClientComposition(*displayId);
+                    layer->forceClientComposition(displayDevice);
                 }
             }
         }
@@ -1897,34 +1893,35 @@
         }
         for (auto& layer : displayDevice->getVisibleLayersSortedByZ()) {
             if (layer->isHdrY410()) {
-                layer->forceClientComposition(*displayId);
+                layer->forceClientComposition(displayDevice);
             } else if ((layer->getDataSpace() == Dataspace::BT2020_PQ ||
                         layer->getDataSpace() == Dataspace::BT2020_ITU_PQ) &&
                        !profile->hasHDR10Support()) {
-                layer->forceClientComposition(*displayId);
+                layer->forceClientComposition(displayDevice);
             } else if ((layer->getDataSpace() == Dataspace::BT2020_HLG ||
                         layer->getDataSpace() == Dataspace::BT2020_ITU_HLG) &&
                        !profile->hasHLGSupport()) {
-                layer->forceClientComposition(*displayId);
+                layer->forceClientComposition(displayDevice);
             }
 
             // TODO(b/111562338) remove when composer 2.3 is shipped.
             if (layer->hasColorTransform()) {
-                layer->forceClientComposition(*displayId);
+                layer->forceClientComposition(displayDevice);
             }
 
             if (layer->getRoundedCornerState().radius > 0.0f) {
-                layer->forceClientComposition(*displayId);
+                layer->forceClientComposition(displayDevice);
             }
 
-            if (layer->getForceClientComposition(*displayId)) {
+            if (layer->getForceClientComposition(displayDevice)) {
                 ALOGV("[%s] Requesting Client composition", layer->getName().string());
-                layer->setCompositionType(*displayId, HWC2::Composition::Client);
+                layer->setCompositionType(displayDevice,
+                                          Hwc2::IComposerClient::Composition::CLIENT);
                 continue;
             }
 
             const auto& displayState = display->getState();
-            layer->setPerFrameData(*displayId, displayState.transform, displayState.viewport,
+            layer->setPerFrameData(displayDevice, displayState.transform, displayState.viewport,
                                    displayDevice->getSupportedPerFrameMetadata());
         }
 
@@ -1939,20 +1936,14 @@
 
     mDrawingState.colorMatrixChanged = false;
 
-    for (const auto& [token, display] : mDisplays) {
-        for (auto& layer : display->getVisibleLayersSortedByZ()) {
+    for (const auto& [token, displayDevice] : mDisplays) {
+        auto display = displayDevice->getCompositionDisplay();
+        for (auto& layer : displayDevice->getVisibleLayersSortedByZ()) {
             const auto displayId = display->getId();
-            layer->getBE().compositionInfo.compositionType = layer->getCompositionType(displayId);
-
-            if (displayId) {
-                if (!layer->setHwcLayer(*displayId)) {
-                    ALOGV("Need to create HWCLayer for %s", layer->getName().string());
-                }
-                layer->getBE().compositionInfo.hwc.displayId = *displayId;
-            }
-
+            layer->getBE().compositionInfo.compositionType =
+                    static_cast<HWC2::Composition>(layer->getCompositionType(displayDevice));
+            layer->getBE().compositionInfo.hwc.displayId = *displayId;
             getBE().mCompositionInfo[token].push_back(layer->getBE().compositionInfo);
-            layer->getBE().compositionInfo.hwc.hwcLayer = nullptr;
         }
     }
 }
@@ -2000,7 +1991,7 @@
     if (CC_UNLIKELY(mLayerStats.isEnabled())) {
         for (const auto& [token, display] : mDisplays) {
             if (display->isPrimary()) {
-                mLayerStats.logLayerStats(dumpVisibleLayersProtoInfo(*display));
+                mLayerStats.logLayerStats(dumpVisibleLayersProtoInfo(display));
                 return;
             }
         }
@@ -2397,13 +2388,13 @@
                         } else {
                             // Clear out the HWC layer if this layer was
                             // previously visible, but no longer is
-                            hwcLayerDestroyed = displayId && layer->destroyHwcLayer(*displayId);
+                            hwcLayerDestroyed = displayId && layer->destroyHwcLayer(displayDevice);
                         }
                     } else {
                         // WM changes display->layerStack upon sleep/awake.
                         // Here we make sure we delete the HWC layers even if
                         // WM changed their layer stack.
-                        hwcLayerDestroyed = displayId && layer->destroyHwcLayer(*displayId);
+                        hwcLayerDestroyed = displayId && layer->destroyHwcLayer(displayDevice);
                     }
 
                     // If a layer is not going to get a release fence because
@@ -2562,8 +2553,7 @@
         return;
     }
 
-    status_t result = display->getRenderSurface()->prepareFrame(
-            getBE().mCompositionInfo[displayDevice->getDisplayToken()]);
+    status_t result = display->getRenderSurface()->prepareFrame();
     ALOGE_IF(result != NO_ERROR, "prepareFrame failed for %s: %d (%s)",
              displayDevice->getDebugName().c_str(), result, strerror(-result));
 }
@@ -2621,9 +2611,10 @@
             // The layer buffer from the previous frame (if any) is released
             // by HWC only when the release fence from this frame (if any) is
             // signaled.  Always get the release fence from HWC first.
-            if (displayId && layer->hasHwcLayer(*displayId)) {
-                releaseFence = getHwComposer().getLayerReleaseFence(*displayId,
-                                                                    layer->getHwcLayer(*displayId));
+            if (displayId && layer->hasHwcLayer(displayDevice)) {
+                releaseFence =
+                        getHwComposer().getLayerReleaseFence(*displayId,
+                                                             layer->getHwcLayer(displayDevice));
             }
 
             // If the layer was client composited in the previous frame, we
@@ -2631,7 +2622,8 @@
             // Since we do not track that, always merge with the current
             // client target acquire fence when it is available, even though
             // this is suboptimal.
-            if (layer->getCompositionType(displayId) == HWC2::Composition::Client) {
+            if (layer->getCompositionType(displayDevice) ==
+                Hwc2::IComposerClient::Composition::CLIENT) {
                 releaseFence =
                         Fence::merge("LayerRelease", releaseFence,
                                      display->getRenderSurface()->getClientTargetAcquireFence());
@@ -3542,16 +3534,16 @@
         const Region viewportRegion(displayState.viewport);
         const Region clip(viewportRegion.intersect(layer->visibleRegion));
         ALOGV("Layer: %s", layer->getName().string());
-        ALOGV("  Composition type: %s", to_string(layer->getCompositionType(displayId)).c_str());
+        ALOGV("  Composition type: %s", toString(layer->getCompositionType(displayDevice)).c_str());
         if (!clip.isEmpty()) {
-            switch (layer->getCompositionType(displayId)) {
-                case HWC2::Composition::Cursor:
-                case HWC2::Composition::Device:
-                case HWC2::Composition::Sideband:
-                case HWC2::Composition::SolidColor: {
+            switch (layer->getCompositionType(displayDevice)) {
+                case Hwc2::IComposerClient::Composition::CURSOR:
+                case Hwc2::IComposerClient::Composition::DEVICE:
+                case Hwc2::IComposerClient::Composition::SIDEBAND:
+                case Hwc2::IComposerClient::Composition::SOLID_COLOR: {
                     LOG_ALWAYS_FATAL_IF(!displayId);
                     const Layer::State& state(layer->getDrawingState());
-                    if (layer->getClearClientTarget(*displayId) && !firstLayer &&
+                    if (layer->getClearClientTarget(displayDevice) && !firstLayer &&
                         layer->isOpaque(state) && (layer->getAlpha() == 1.0f) &&
                         layer->getRoundedCornerState().radius == 0.0f && hasClientComposition) {
                         // never clear the very first layer since we're
@@ -3571,7 +3563,7 @@
                     }
                     break;
                 }
-                case HWC2::Composition::Client: {
+                case Hwc2::IComposerClient::Composition::CLIENT: {
                     renderengine::LayerSettings layerSettings;
                     bool prepared =
                             layer->prepareClientLayer(renderArea, clip, clearRegion, layerSettings);
@@ -4843,26 +4835,27 @@
     return layersProto;
 }
 
-LayersProto SurfaceFlinger::dumpVisibleLayersProtoInfo(const DisplayDevice& displayDevice) const {
+LayersProto SurfaceFlinger::dumpVisibleLayersProtoInfo(
+        const sp<DisplayDevice>& displayDevice) const {
     LayersProto layersProto;
 
     SizeProto* resolution = layersProto.mutable_resolution();
-    resolution->set_w(displayDevice.getWidth());
-    resolution->set_h(displayDevice.getHeight());
+    resolution->set_w(displayDevice->getWidth());
+    resolution->set_h(displayDevice->getHeight());
 
-    auto display = displayDevice.getCompositionDisplay();
+    auto display = displayDevice->getCompositionDisplay();
     const auto& displayState = display->getState();
 
     layersProto.set_color_mode(decodeColorMode(displayState.colorMode));
     layersProto.set_color_transform(decodeColorTransform(displayState.colorTransform));
     layersProto.set_global_transform(displayState.orientation);
 
-    const auto displayId = displayDevice.getId();
+    const auto displayId = displayDevice->getId();
     LOG_ALWAYS_FATAL_IF(!displayId);
     mDrawingState.traverseInZOrder([&](Layer* layer) {
-        if (!layer->visibleRegion.isEmpty() && layer->getBE().mHwcLayers.count(*displayId)) {
+        if (!layer->visibleRegion.isEmpty() && !display->getOutputLayersOrderedByZ().empty()) {
             LayerProto* layerProto = layersProto.add_layers();
-            layer->writeToProto(layerProto, *displayId);
+            layer->writeToProto(layerProto, displayDevice);
         }
     });
 
@@ -4998,7 +4991,9 @@
 
         StringAppendF(&result, "Display %s HWC layers:\n", to_string(*displayId).c_str());
         Layer::miniDumpHeader(result);
-        mCurrentState.traverseInZOrder([&](Layer* layer) { layer->miniDump(result, *displayId); });
+        const sp<DisplayDevice> displayDevice = display;
+        mCurrentState.traverseInZOrder(
+                [&](Layer* layer) { layer->miniDump(result, displayDevice); });
         result.append("\n");
     }
 
@@ -5550,6 +5545,7 @@
         }
         bool isSecure() const override { return false; }
         bool needsFiltering() const override { return mNeedsFiltering; }
+        const sp<const DisplayDevice> getDisplayDevice() const override { return nullptr; }
         Rect getSourceCrop() const override {
             if (mCrop.isEmpty()) {
                 return getBounds();
diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h
index 669d3a1..d8d4ca1 100644
--- a/services/surfaceflinger/SurfaceFlinger.h
+++ b/services/surfaceflinger/SurfaceFlinger.h
@@ -895,7 +895,7 @@
     void dumpWideColorInfo(std::string& result) const;
     void dumpFrameCompositionInfo(std::string& result) const;
     LayersProto dumpProtoInfo(LayerVector::StateSet stateSet) const;
-    LayersProto dumpVisibleLayersProtoInfo(const DisplayDevice& display) const;
+    LayersProto dumpVisibleLayersProtoInfo(const sp<DisplayDevice>& display) const;
 
     bool isLayerTripleBufferingDisabled() const {
         return this->mLayerTripleBufferingDisabled;
diff --git a/services/surfaceflinger/tests/fakehwc/Android.bp b/services/surfaceflinger/tests/fakehwc/Android.bp
index 68cf61e..a2c0611 100644
--- a/services/surfaceflinger/tests/fakehwc/Android.bp
+++ b/services/surfaceflinger/tests/fakehwc/Android.bp
@@ -31,7 +31,6 @@
         "libutils",
     ],
     static_libs: [
-        "libcompositionengine",
         "libgmock",
         "librenderengine",
         "libtrace_proto",
diff --git a/services/surfaceflinger/tests/unittests/CompositionTest.cpp b/services/surfaceflinger/tests/unittests/CompositionTest.cpp
index 3fb8708..3addd61 100644
--- a/services/surfaceflinger/tests/unittests/CompositionTest.cpp
+++ b/services/surfaceflinger/tests/unittests/CompositionTest.cpp
@@ -17,6 +17,7 @@
 #undef LOG_TAG
 #define LOG_TAG "CompositionTest"
 
+#include <compositionengine/Display.h>
 #include <compositionengine/mock/DisplaySurface.h>
 #include <gmock/gmock.h>
 #include <gtest/gtest.h>
@@ -753,12 +754,16 @@
     }
 
     static void injectLayer(CompositionTest* test, sp<Layer> layer) {
+        std::vector<std::unique_ptr<compositionengine::OutputLayer>> outputLayers;
+        outputLayers.emplace_back(
+                test->mDisplay->getCompositionDisplay()
+                        ->getOrCreateOutputLayer(layer->getCompositionLayer(), layer));
+        test->mDisplay->getCompositionDisplay()->setOutputLayersOrderedByZ(std::move(outputLayers));
+
         EXPECT_CALL(*test->mComposer, createLayer(HWC_DISPLAY, _))
                 .WillOnce(DoAll(SetArgPointee<1>(HWC_LAYER), Return(Error::NONE)));
 
-        const auto displayId = test->mDisplay->getId();
-        ASSERT_TRUE(displayId);
-        layer->createHwcLayer(&test->mFlinger.getHwComposer(), *displayId);
+        layer->createHwcLayer(&test->mFlinger.getHwComposer(), test->mDisplay);
 
         Mock::VerifyAndClear(test->mComposer);
 
@@ -771,10 +776,12 @@
     static void cleanupInjectedLayers(CompositionTest* test) {
         EXPECT_CALL(*test->mComposer, destroyLayer(HWC_DISPLAY, HWC_LAYER))
                 .WillOnce(Return(Error::NONE));
-        const auto displayId = test->mDisplay->getId();
-        ASSERT_TRUE(displayId);
+
+        test->mDisplay->getCompositionDisplay()->setOutputLayersOrderedByZ(
+                std::vector<std::unique_ptr<compositionengine::OutputLayer>>());
+
         for (auto layer : test->mFlinger.mutableDrawingState().layersSortedByZ) {
-            layer->destroyHwcLayer(*displayId);
+            layer->destroyHwcLayer(test->mDisplay);
         }
         test->mFlinger.mutableDrawingState().layersSortedByZ.clear();
     }
@@ -963,8 +970,8 @@
 };
 
 struct ForcedClientCompositionResultVariant : public RECompositionResultVariant {
-    static void setupLayerState(CompositionTest*, sp<Layer> layer) {
-        layer->forceClientComposition(DEFAULT_DISPLAY_ID);
+    static void setupLayerState(CompositionTest* test, sp<Layer> layer) {
+        layer->forceClientComposition(test->mDisplay);
     }
 
     template <typename Case>
diff --git a/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h b/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h
index e639b4d..bfdd20b 100644
--- a/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h
+++ b/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h
@@ -16,7 +16,10 @@
 
 #pragma once
 
+#include <compositionengine/Display.h>
+#include <compositionengine/OutputLayer.h>
 #include <compositionengine/impl/CompositionEngine.h>
+#include <compositionengine/impl/OutputLayerCompositionState.h>
 
 #include "BufferQueueLayer.h"
 #include "BufferStateLayer.h"
@@ -206,6 +209,14 @@
         layer->getBE().compositionInfo.hwc.sidebandStream = sidebandStream;
     }
 
+    void setLayerCompositionType(sp<Layer> layer, HWC2::Composition type) {
+        auto outputLayer = layer->findOutputLayerForDisplay(mFlinger->getDefaultDisplayDevice());
+        LOG_ALWAYS_FATAL_IF(!outputLayer);
+        auto& state = outputLayer->editState();
+        LOG_ALWAYS_FATAL_IF(!outputLayer->getState().hwc);
+        (*state.hwc).hwcCompositionType = static_cast<Hwc2::IComposerClient::Composition>(type);
+    };
+
     void setLayerPotentialCursor(sp<Layer> layer, bool potentialCursor) {
         layer->mPotentialCursor = potentialCursor;
     }