SF: Add ability to get basic geometry
For computing the layer visibility, CompositionEngine will need to get
basic geometry state for every layer, without getting everything. Add a
new request type for the basic geometry state, and modify the existing
code in computeVisibleRegions to use it rather than accessing directly
through the front-end layer pointer.
Test: atest libsurfaceflinger_unittest libcompositionengine_test
Test: go/wm-smoke
Bug: 121291683
Change-Id: Ie286fe1986a4c383ee390c1f646c7a8a5b8c14f4
diff --git a/services/surfaceflinger/CompositionEngine/include/compositionengine/LayerFE.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/LayerFE.h
index db4f969..57cca69 100644
--- a/services/surfaceflinger/CompositionEngine/include/compositionengine/LayerFE.h
+++ b/services/surfaceflinger/CompositionEngine/include/compositionengine/LayerFE.h
@@ -39,9 +39,26 @@
// process.
virtual bool onPreComposition(nsecs_t refreshStartTime) = 0;
- // Latches the output-independent state. If includeGeometry is false, the
- // geometry state can be skipped.
- virtual void latchCompositionState(LayerFECompositionState&, bool includeGeometry) const = 0;
+ // Used with latchCompositionState()
+ enum class StateSubset {
+ // Gets the basic geometry (bounds, transparent region, visibility,
+ // transforms, alpha) for the layer, for computing visibility and
+ // coverage.
+ BasicGeometry,
+
+ // Gets the full geometry (crops, buffer transforms, metadata) and
+ // content (buffer or color) state for the layer.
+ GeometryAndContent,
+
+ // Gets the per frame content (buffer or color) state the layer.
+ Content,
+ };
+
+ // Latches the output-independent composition state for the layer. The
+ // StateSubset argument selects what portion of the state is actually needed
+ // by the CompositionEngine code, since computing everything may be
+ // expensive.
+ virtual void latchCompositionState(LayerFECompositionState&, StateSubset) const = 0;
// Latches the minimal bit of state for the cursor for a fast asynchronous
// update.
diff --git a/services/surfaceflinger/CompositionEngine/include/compositionengine/LayerFECompositionState.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/LayerFECompositionState.h
index b066cd1..530f49a 100644
--- a/services/surfaceflinger/CompositionEngine/include/compositionengine/LayerFECompositionState.h
+++ b/services/surfaceflinger/CompositionEngine/include/compositionengine/LayerFECompositionState.h
@@ -40,6 +40,45 @@
// the next geometry change.
bool forceClientComposition{false};
+ // TODO(b/121291683): Reorganize and rename the contents of this structure
+
+ /*
+ * Visibility state
+ */
+ // the layer stack this layer belongs to
+ std::optional<uint32_t> layerStackId;
+
+ // If true, this layer should be only visible on the internal display
+ bool internalOnly{false};
+
+ // If false, this layer should not be considered visible
+ bool isVisible{true};
+
+ // True if the layer is completely opaque
+ bool isOpaque{true};
+
+ // If true, invalidates the entire visible region
+ bool contentDirty{false};
+
+ // The alpha value for this layer
+ float alpha{1.f};
+
+ // The transform from layer local coordinates to composition coordinates
+ ui::Transform geomLayerTransform;
+
+ // The inverse of the layer transform
+ ui::Transform geomInverseLayerTransform;
+
+ // The hint from the layer producer as to what portion of the layer is
+ // transparent.
+ Region transparentRegionHint;
+
+ // The blend mode for this layer
+ Hwc2::IComposerClient::BlendMode blendMode{Hwc2::IComposerClient::BlendMode::INVALID};
+
+ // The bounds of the layer in layer local coordinates
+ FloatRect geomLayerBounds;
+
/*
* Geometry state
*/
@@ -48,23 +87,9 @@
bool geomUsesSourceCrop{false};
bool geomBufferUsesDisplayInverseTransform{false};
uint32_t geomBufferTransform{0};
- ui::Transform geomLayerTransform;
- ui::Transform geomInverseLayerTransform;
Rect geomBufferSize;
Rect geomContentCrop;
Rect geomCrop;
- Region geomActiveTransparentRegion;
- FloatRect geomLayerBounds;
-
- /*
- * Presentation
- */
-
- // The blend mode for this layer
- Hwc2::IComposerClient::BlendMode blendMode{Hwc2::IComposerClient::BlendMode::INVALID};
-
- // The alpha value for this layer
- float alpha{1.f};
/*
* Extra metadata
@@ -113,9 +138,6 @@
mat4 colorTransform;
bool colorTransformIsIdentity{true};
- // True if the layer is completely opaque
- bool isOpaque{true};
-
// True if the layer has protected content
bool hasProtectedContent{false};
diff --git a/services/surfaceflinger/CompositionEngine/include/compositionengine/Output.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/Output.h
index a509ca8..43f44af 100644
--- a/services/surfaceflinger/CompositionEngine/include/compositionengine/Output.h
+++ b/services/surfaceflinger/CompositionEngine/include/compositionengine/Output.h
@@ -132,7 +132,7 @@
// A layer belongs to the output if its layerStackId matches. Additionally
// if the layer should only show in the internal (primary) display only and
// this output allows that.
- virtual bool belongsInOutput(uint32_t layerStackId, bool internalOnly) const = 0;
+ virtual bool belongsInOutput(std::optional<uint32_t> layerStackId, bool internalOnly) const = 0;
// Returns a pointer to the output layer corresponding to the given layer on
// this output, or nullptr if the layer does not have one
diff --git a/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/Output.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/Output.h
index d826161..ece5b1c 100644
--- a/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/Output.h
+++ b/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/Output.h
@@ -62,7 +62,7 @@
OutputCompositionState& editState() override;
Region getDirtyRegion(bool repaintEverything) const override;
- bool belongsInOutput(uint32_t, bool) const override;
+ bool belongsInOutput(std::optional<uint32_t>, bool) const override;
compositionengine::OutputLayer* getOutputLayerForLayer(
compositionengine::Layer*) const override;
diff --git a/services/surfaceflinger/CompositionEngine/include/compositionengine/mock/LayerFE.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/mock/LayerFE.h
index e280295..3eada3c 100644
--- a/services/surfaceflinger/CompositionEngine/include/compositionengine/mock/LayerFE.h
+++ b/services/surfaceflinger/CompositionEngine/include/compositionengine/mock/LayerFE.h
@@ -32,7 +32,8 @@
MOCK_METHOD1(onPreComposition, bool(nsecs_t));
- MOCK_CONST_METHOD2(latchCompositionState, void(LayerFECompositionState&, bool));
+ MOCK_CONST_METHOD2(latchCompositionState,
+ void(LayerFECompositionState&, compositionengine::LayerFE::StateSubset));
MOCK_CONST_METHOD1(latchCursorCompositionState, void(LayerFECompositionState&));
MOCK_METHOD1(prepareClientComposition,
std::optional<renderengine::LayerSettings>(
diff --git a/services/surfaceflinger/CompositionEngine/include/compositionengine/mock/Output.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/mock/Output.h
index 33925d5..2f24c15 100644
--- a/services/surfaceflinger/CompositionEngine/include/compositionengine/mock/Output.h
+++ b/services/surfaceflinger/CompositionEngine/include/compositionengine/mock/Output.h
@@ -59,7 +59,7 @@
MOCK_METHOD0(editState, OutputCompositionState&());
MOCK_CONST_METHOD1(getDirtyRegion, Region(bool));
- MOCK_CONST_METHOD2(belongsInOutput, bool(uint32_t, bool));
+ MOCK_CONST_METHOD2(belongsInOutput, bool(std::optional<uint32_t>, bool));
MOCK_CONST_METHOD1(getOutputLayerForLayer,
compositionengine::OutputLayer*(compositionengine::Layer*));
diff --git a/services/surfaceflinger/CompositionEngine/src/LayerCompositionState.cpp b/services/surfaceflinger/CompositionEngine/src/LayerCompositionState.cpp
index 0dc4bf1..c5debf6 100644
--- a/services/surfaceflinger/CompositionEngine/src/LayerCompositionState.cpp
+++ b/services/surfaceflinger/CompositionEngine/src/LayerCompositionState.cpp
@@ -45,7 +45,7 @@
dumpVal(out, "geomBufferTransform", state.geomBufferTransform);
out.append("\n ");
- dumpVal(out, "geomActiveTransparentRegion", state.geomActiveTransparentRegion);
+ dumpVal(out, "transparentRegionHint", state.transparentRegionHint);
out.append(" ");
dumpVal(out, "geomLayerBounds", state.geomLayerBounds);
diff --git a/services/surfaceflinger/CompositionEngine/src/Output.cpp b/services/surfaceflinger/CompositionEngine/src/Output.cpp
index 9f4f259..4dfdeba 100644
--- a/services/surfaceflinger/CompositionEngine/src/Output.cpp
+++ b/services/surfaceflinger/CompositionEngine/src/Output.cpp
@@ -212,10 +212,11 @@
return dirty;
}
-bool Output::belongsInOutput(uint32_t layerStackId, bool internalOnly) const {
+bool Output::belongsInOutput(std::optional<uint32_t> layerStackId, bool internalOnly) const {
// The layerStackId's must match, and also the layer must not be internal
// only when not on an internal output.
- return (layerStackId == mState.layerStackId) && (!internalOnly || mState.layerStackInternal);
+ return layerStackId && (*layerStackId == mState.layerStackId) &&
+ (!internalOnly || mState.layerStackInternal);
}
compositionengine::OutputLayer* Output::getOutputLayerForLayer(
@@ -281,7 +282,9 @@
void Output::updateLayerStateFromFE(const CompositionRefreshArgs& args) const {
for (auto& layer : mOutputLayersOrderedByZ) {
layer->getLayerFE().latchCompositionState(layer->getLayer().editState().frontEnd,
- args.updatingGeometryThisFrame);
+ args.updatingGeometryThisFrame
+ ? LayerFE::StateSubset::GeometryAndContent
+ : LayerFE::StateSubset::Content);
}
}
diff --git a/services/surfaceflinger/CompositionEngine/src/OutputLayer.cpp b/services/surfaceflinger/CompositionEngine/src/OutputLayer.cpp
index 21f0ce8..3a0ebf8 100644
--- a/services/surfaceflinger/CompositionEngine/src/OutputLayer.cpp
+++ b/services/surfaceflinger/CompositionEngine/src/OutputLayer.cpp
@@ -102,7 +102,7 @@
// pixels in the buffer.
FloatRect activeCropFloat =
- reduce(layerState.geomLayerBounds, layerState.geomActiveTransparentRegion);
+ reduce(layerState.geomLayerBounds, layerState.transparentRegionHint);
const Rect& viewport = mOutput.getState().viewport;
const ui::Transform& layerTransform = layerState.geomLayerTransform;
@@ -209,7 +209,7 @@
// apply the layer's transform, followed by the display's global transform
// here we're guaranteed that the layer's transform preserves rects
- Region activeTransparentRegion = layerState.geomActiveTransparentRegion;
+ Region activeTransparentRegion = layerState.transparentRegionHint;
const ui::Transform& layerTransform = layerState.geomLayerTransform;
const ui::Transform& inverseLayerTransform = layerState.geomInverseLayerTransform;
const Rect& bufferSize = layerState.geomBufferSize;
diff --git a/services/surfaceflinger/CompositionEngine/tests/OutputLayerTest.cpp b/services/surfaceflinger/CompositionEngine/tests/OutputLayerTest.cpp
index 2276dc3..65691ff 100644
--- a/services/surfaceflinger/CompositionEngine/tests/OutputLayerTest.cpp
+++ b/services/surfaceflinger/CompositionEngine/tests/OutputLayerTest.cpp
@@ -124,7 +124,7 @@
// set one specific value to something different.
mLayerState.frontEnd.geomUsesSourceCrop = true;
mLayerState.frontEnd.geomContentCrop = Rect{0, 0, 1920, 1080};
- mLayerState.frontEnd.geomActiveTransparentRegion = Region{};
+ mLayerState.frontEnd.transparentRegionHint = Region{};
mLayerState.frontEnd.geomLayerBounds = FloatRect{0.f, 0.f, 1920.f, 1080.f};
mLayerState.frontEnd.geomLayerTransform = ui::Transform{TR_IDENT};
mLayerState.frontEnd.geomBufferSize = Rect{0, 0, 1920, 1080};
@@ -231,7 +231,7 @@
// Set reasonable default values for a simple case. Each test will
// set one specific value to something different.
- mLayerState.frontEnd.geomActiveTransparentRegion = Region{};
+ mLayerState.frontEnd.transparentRegionHint = Region{};
mLayerState.frontEnd.geomLayerTransform = ui::Transform{TR_IDENT};
mLayerState.frontEnd.geomBufferSize = Rect{0, 0, 1920, 1080};
mLayerState.frontEnd.geomBufferUsesDisplayInverseTransform = false;
@@ -256,7 +256,7 @@
}
TEST_F(OutputLayerDisplayFrameTest, fullActiveTransparentRegionReturnsEmptyFrame) {
- mLayerState.frontEnd.geomActiveTransparentRegion = Region{Rect{0, 0, 1920, 1080}};
+ mLayerState.frontEnd.transparentRegionHint = Region{Rect{0, 0, 1920, 1080}};
const Rect expected{0, 0, 0, 0};
EXPECT_THAT(calculateOutputDisplayFrame(), RectEq(expected));
}
diff --git a/services/surfaceflinger/CompositionEngine/tests/OutputTest.cpp b/services/surfaceflinger/CompositionEngine/tests/OutputTest.cpp
index b0e8e36..70d9871 100644
--- a/services/surfaceflinger/CompositionEngine/tests/OutputTest.cpp
+++ b/services/surfaceflinger/CompositionEngine/tests/OutputTest.cpp
@@ -356,6 +356,10 @@
// If the output accepts layerStack1 and internal-only layers....
mOutput.setLayerStackFilter(layerStack1, true);
+ // A layer with no layerStack does not belong to it, internal-only or not.
+ EXPECT_FALSE(mOutput.belongsInOutput(std::nullopt, false));
+ EXPECT_FALSE(mOutput.belongsInOutput(std::nullopt, true));
+
// Any layer with layerStack1 belongs to it, internal-only or not.
EXPECT_TRUE(mOutput.belongsInOutput(layerStack1, false));
EXPECT_TRUE(mOutput.belongsInOutput(layerStack1, true));