diff options
10 files changed, 86 insertions, 26 deletions
diff --git a/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/OutputLayerCompositionState.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/OutputLayerCompositionState.h index a3e84e2a9c..6c02759bf8 100644 --- a/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/OutputLayerCompositionState.h +++ b/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/OutputLayerCompositionState.h @@ -16,10 +16,7 @@ #pragma once -#include <cstdint> -#include <optional> -#include <string> - +#include <compositionengine/ProjectionSpace.h> #include <compositionengine/impl/HwcBufferCache.h> #include <renderengine/Mesh.h> #include <ui/FloatRect.h> @@ -27,6 +24,10 @@ #include <ui/Rect.h> #include <ui/Region.h> +#include <cstdint> +#include <optional> +#include <string> + // TODO(b/129481165): remove the #pragma below and fix conversion issues #pragma clang diagnostic push #pragma clang diagnostic ignored "-Wconversion" @@ -90,6 +91,7 @@ struct OutputLayerCompositionState { sp<Fence> acquireFence = nullptr; Rect displayFrame = {}; ui::Dataspace dataspace{ui::Dataspace::UNKNOWN}; + ProjectionSpace displaySpace; } overrideInfo; /* diff --git a/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/planner/CachedSet.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/planner/CachedSet.h index cfb496269c..fae17d9747 100644 --- a/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/planner/CachedSet.h +++ b/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/planner/CachedSet.h @@ -64,6 +64,7 @@ public: size_t getAge() const { return mAge; } const sp<GraphicBuffer>& getBuffer() const { return mTexture.getBuffer(); } const sp<Fence>& getDrawFence() const { return mDrawFence; } + const ProjectionSpace& getOutputSpace() const { return mOutputSpace; } ui::Dataspace getOutputDataspace() const { return mOutputDataspace; } NonBufferHash getNonBufferHash() const; @@ -134,6 +135,7 @@ private: Texture mTexture; sp<Fence> mDrawFence; + ProjectionSpace mOutputSpace; ui::Dataspace mOutputDataspace; ui::Transform::RotationFlags mOrientation = ui::Transform::ROT_0; diff --git a/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/planner/Flattener.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/planner/Flattener.h index e21b5bc433..313a180f4f 100644 --- a/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/planner/Flattener.h +++ b/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/planner/Flattener.h @@ -16,6 +16,7 @@ #pragma once +#include <compositionengine/Output.h> #include <compositionengine/impl/planner/CachedSet.h> #include <compositionengine/impl/planner/LayerState.h> diff --git a/services/surfaceflinger/CompositionEngine/src/OutputLayer.cpp b/services/surfaceflinger/CompositionEngine/src/OutputLayer.cpp index e662491791..48327931db 100644 --- a/services/surfaceflinger/CompositionEngine/src/OutputLayer.cpp +++ b/services/surfaceflinger/CompositionEngine/src/OutputLayer.cpp @@ -381,8 +381,9 @@ void OutputLayer::writeOutputDependentGeometryStateToHWC( outputDependentState.z, to_string(error).c_str(), static_cast<int32_t>(error)); } - // Solid-color layers should always use an identity transform. - const auto bufferTransform = requestedCompositionType != hal::Composition::SOLID_COLOR + // Solid-color layers and overridden buffers should always use an identity transform. + const auto bufferTransform = (requestedCompositionType != hal::Composition::SOLID_COLOR && + getState().overrideInfo.buffer == nullptr) ? outputDependentState.bufferTransform : static_cast<hal::Transform>(0); if (auto error = hwcLayer->setTransform(static_cast<hal::Transform>(bufferTransform)); @@ -674,16 +675,26 @@ std::vector<LayerFE::LayerSettings> OutputLayer::getOverrideCompositionList() co return {}; } + // Compute the geometry boundaries in layer stack space: we need to transform from the + // framebuffer space of the override buffer to layer space. + const ProjectionSpace& layerSpace = getOutput().getState().layerStackSpace; + const ui::Transform transform = getState().overrideInfo.displaySpace.getTransform(layerSpace); + const Rect boundaries = transform.transform(getState().overrideInfo.displayFrame); + LayerFE::LayerSettings settings; settings.geometry = renderengine::Geometry{ - .boundaries = getState().overrideInfo.displayFrame.toFloatRect(), + .boundaries = boundaries.toFloatRect(), }; settings.bufferId = getState().overrideInfo.buffer->getId(); - settings.source = - renderengine::PixelSource{.buffer = renderengine::Buffer{ - .buffer = getState().overrideInfo.buffer, - .fence = getState().overrideInfo.acquireFence, - }}; + settings.source = renderengine::PixelSource{ + .buffer = renderengine::Buffer{ + .buffer = getState().overrideInfo.buffer, + .fence = getState().overrideInfo.acquireFence, + // If the transform from layer space to display space contains a rotation, we + // need to undo the rotation in the texture transform + .textureTransform = + ui::Transform(transform.inverse().getOrientation(), 1, 1).asMatrix4(), + }}; settings.sourceDataspace = getState().overrideInfo.dataspace; settings.alpha = 1.0f; diff --git a/services/surfaceflinger/CompositionEngine/src/OutputLayerCompositionState.cpp b/services/surfaceflinger/CompositionEngine/src/OutputLayerCompositionState.cpp index 45dce9842b..0f6804d0ab 100644 --- a/services/surfaceflinger/CompositionEngine/src/OutputLayerCompositionState.cpp +++ b/services/surfaceflinger/CompositionEngine/src/OutputLayerCompositionState.cpp @@ -72,6 +72,7 @@ void OutputLayerCompositionState::dump(std::string& out) const { dumpVal(out, "override acquire fence", overrideInfo.acquireFence.get()); dumpVal(out, "override display frame", overrideInfo.displayFrame); dumpVal(out, "override dataspace", toString(overrideInfo.dataspace), overrideInfo.dataspace); + dumpVal(out, "override display space", to_string(overrideInfo.displaySpace)); if (hwc) { dumpHwc(*hwc, out); diff --git a/services/surfaceflinger/CompositionEngine/src/planner/CachedSet.cpp b/services/surfaceflinger/CompositionEngine/src/planner/CachedSet.cpp index e8c6de0eed..b95a3db547 100644 --- a/services/surfaceflinger/CompositionEngine/src/planner/CachedSet.cpp +++ b/services/surfaceflinger/CompositionEngine/src/planner/CachedSet.cpp @@ -152,20 +152,20 @@ void CachedSet::updateAge(std::chrono::steady_clock::time_point now) { void CachedSet::render(renderengine::RenderEngine& renderEngine, const OutputCompositionState& outputState) { + const Rect& viewport = outputState.layerStackSpace.content; const ui::Dataspace& outputDataspace = outputState.dataspace; const ui::Transform::RotationFlags orientation = - ui::Transform::toRotationFlags(outputState.displaySpace.orientation); + ui::Transform::toRotationFlags(outputState.framebufferSpace.orientation); renderengine::DisplaySettings displaySettings{ .physicalDisplay = Rect(0, 0, mBounds.getWidth(), mBounds.getHeight()), - .clip = mBounds, - .orientation = orientation, + .clip = viewport, .outputDataspace = outputDataspace, + .orientation = orientation, }; Region clearRegion = Region::INVALID_REGION; - Rect viewport = mBounds; LayerFE::ClientCompositionTargetSettings targetSettings{ - .clip = Region(mBounds), + .clip = Region(viewport), .needsFiltering = false, .isSecure = true, .supportsProtectedContent = false, @@ -223,6 +223,10 @@ void CachedSet::render(renderengine::RenderEngine& renderEngine, if (result == NO_ERROR) { mTexture.setBuffer(buffer, &renderEngine); mDrawFence = new Fence(drawFence.release()); + mOutputSpace = ProjectionSpace(ui::Size(outputState.framebufferSpace.bounds.getWidth(), + outputState.framebufferSpace.bounds.getHeight()), + mBounds); + mOutputSpace.orientation = outputState.framebufferSpace.orientation; mOutputDataspace = outputDataspace; mOrientation = orientation; } diff --git a/services/surfaceflinger/CompositionEngine/src/planner/Flattener.cpp b/services/surfaceflinger/CompositionEngine/src/planner/Flattener.cpp index 06f7e7a256..439cfb3507 100644 --- a/services/surfaceflinger/CompositionEngine/src/planner/Flattener.cpp +++ b/services/surfaceflinger/CompositionEngine/src/planner/Flattener.cpp @@ -213,6 +213,7 @@ bool Flattener::mergeWithCachedSets(const std::vector<const LayerState*>& layers .acquireFence = mNewCachedSet->getDrawFence(), .displayFrame = mNewCachedSet->getBounds(), .dataspace = mNewCachedSet->getOutputDataspace(), + .displaySpace = mNewCachedSet->getOutputSpace(), }; ++incomingLayerIter; } @@ -244,6 +245,7 @@ bool Flattener::mergeWithCachedSets(const std::vector<const LayerState*>& layers .acquireFence = currentLayerIter->getDrawFence(), .displayFrame = currentLayerIter->getBounds(), .dataspace = currentLayerIter->getOutputDataspace(), + .displaySpace = currentLayerIter->getOutputSpace(), }; ++incomingLayerIter; } diff --git a/services/surfaceflinger/CompositionEngine/tests/OutputLayerTest.cpp b/services/surfaceflinger/CompositionEngine/tests/OutputLayerTest.cpp index 83fb9e3f78..cbbc966790 100644 --- a/services/surfaceflinger/CompositionEngine/tests/OutputLayerTest.cpp +++ b/services/surfaceflinger/CompositionEngine/tests/OutputLayerTest.cpp @@ -690,6 +690,7 @@ struct OutputLayerWriteStateToHWCTest : public OutputLayerTest { static constexpr FloatRect kSourceCrop{11.f, 12.f, 13.f, 14.f}; static constexpr uint32_t kZOrder = 21u; static constexpr Hwc2::Transform kBufferTransform = static_cast<Hwc2::Transform>(31); + static constexpr Hwc2::Transform kOverrideBufferTransform = static_cast<Hwc2::Transform>(0); static constexpr Hwc2::IComposerClient::BlendMode kBlendMode = static_cast<Hwc2::IComposerClient::BlendMode>(41); static constexpr float kAlpha = 51.f; @@ -765,11 +766,12 @@ struct OutputLayerWriteStateToHWCTest : public OutputLayerTest { } void expectGeometryCommonCalls(Rect displayFrame = kDisplayFrame, - FloatRect sourceCrop = kSourceCrop) { + FloatRect sourceCrop = kSourceCrop, + Hwc2::Transform bufferTransform = kBufferTransform) { EXPECT_CALL(*mHwcLayer, setDisplayFrame(displayFrame)).WillOnce(Return(kError)); EXPECT_CALL(*mHwcLayer, setSourceCrop(sourceCrop)).WillOnce(Return(kError)); EXPECT_CALL(*mHwcLayer, setZOrder(kZOrder)).WillOnce(Return(kError)); - EXPECT_CALL(*mHwcLayer, setTransform(kBufferTransform)).WillOnce(Return(kError)); + EXPECT_CALL(*mHwcLayer, setTransform(bufferTransform)).WillOnce(Return(kError)); EXPECT_CALL(*mHwcLayer, setBlendMode(kBlendMode)).WillOnce(Return(kError)); EXPECT_CALL(*mHwcLayer, setPlaneAlpha(kAlpha)).WillOnce(Return(kError)); @@ -1006,7 +1008,8 @@ TEST_F(OutputLayerWriteStateToHWCTest, includesOverrideInfoIfPresent) { mLayerFEState.compositionType = Hwc2::IComposerClient::Composition::DEVICE; includeOverrideInfo(); - expectGeometryCommonCalls(kOverrideDisplayFrame, kOverrideDisplayFrame.toFloatRect()); + expectGeometryCommonCalls(kOverrideDisplayFrame, kOverrideDisplayFrame.toFloatRect(), + kOverrideBufferTransform); expectPerFrameCommonCalls(SimulateUnsupported::None, kOverrideDataspace); expectSetHdrMetadataAndBufferCalls(kOverrideBuffer, kOverrideFence); expectSetCompositionTypeCall(Hwc2::IComposerClient::Composition::DEVICE); diff --git a/services/surfaceflinger/CompositionEngine/tests/planner/CachedSetTest.cpp b/services/surfaceflinger/CompositionEngine/tests/planner/CachedSetTest.cpp index 0e7ef71c65..d3c4b1f822 100644 --- a/services/surfaceflinger/CompositionEngine/tests/planner/CachedSetTest.cpp +++ b/services/surfaceflinger/CompositionEngine/tests/planner/CachedSetTest.cpp @@ -92,7 +92,9 @@ void CachedSetTest::SetUp() { // set up minimium params needed for rendering mOutputState.dataspace = ui::Dataspace::SRGB; - mOutputState.displaySpace.orientation = ui::ROTATION_0; + mOutputState.framebufferSpace = ProjectionSpace(ui::Size(10, 20), Rect(10, 5)); + mOutputState.framebufferSpace.orientation = ui::ROTATION_90; + mOutputState.layerStackSpace = ProjectionSpace(ui::Size(20, 10), Rect(5, 10)); } } @@ -294,7 +296,9 @@ TEST_F(CachedSetTest, render) { const sp<GraphicBuffer>&, const bool, base::unique_fd&&, base::unique_fd*) -> size_t { EXPECT_EQ(Rect(0, 0, 2, 2), displaySettings.physicalDisplay); - EXPECT_EQ(Rect(0, 0, 2, 2), displaySettings.clip); + EXPECT_EQ(mOutputState.layerStackSpace.content, displaySettings.clip); + EXPECT_EQ(ui::Transform::toRotationFlags(mOutputState.framebufferSpace.orientation), + displaySettings.orientation); EXPECT_EQ(0.5f, layers[0]->alpha); EXPECT_EQ(0.75f, layers[1]->alpha); EXPECT_EQ(ui::Dataspace::SRGB, displaySettings.outputDataspace); @@ -309,6 +313,11 @@ TEST_F(CachedSetTest, render) { cachedSet.render(mRenderEngine, mOutputState); expectReadyBuffer(cachedSet); + EXPECT_EQ(Rect(0, 0, 2, 2), cachedSet.getOutputSpace().content); + EXPECT_EQ(Rect(mOutputState.framebufferSpace.bounds.getWidth(), + mOutputState.framebufferSpace.bounds.getHeight()), + cachedSet.getOutputSpace().bounds); + // Now check that appending a new cached set properly cleans up RenderEngine resources. EXPECT_CALL(mRenderEngine, unbindExternalTextureBuffer(_)); CachedSet::Layer& layer3 = *mTestLayers[2]->cachedSetLayer.get(); diff --git a/services/surfaceflinger/CompositionEngine/tests/planner/FlattenerTest.cpp b/services/surfaceflinger/CompositionEngine/tests/planner/FlattenerTest.cpp index 211b4dc1b4..1bbf11a163 100644 --- a/services/surfaceflinger/CompositionEngine/tests/planner/FlattenerTest.cpp +++ b/services/surfaceflinger/CompositionEngine/tests/planner/FlattenerTest.cpp @@ -125,7 +125,8 @@ void FlattenerTest::SetUp() { // set up minimium params needed for rendering mOutputState.dataspace = ui::Dataspace::SRGB; - mOutputState.displaySpace.orientation = ui::ROTATION_0; + mOutputState.framebufferSpace = ProjectionSpace(ui::Size(10, 20), Rect(10, 5)); + mOutputState.framebufferSpace.orientation = ui::ROTATION_90; } } @@ -254,6 +255,30 @@ TEST_F(FlattenerTest, flattenLayers_FlattenedLayersStayFlattenWhenNoUpdate) { EXPECT_EQ(overrideBuffer2, overrideBuffer3); } +TEST_F(FlattenerTest, flattenLayers_FlattenedLayersSetsProjectionSpace) { + auto& layerState1 = mTestLayers[0]->layerState; + const auto& overrideDisplaySpace = + layerState1->getOutputLayer()->getState().overrideInfo.displaySpace; + + auto& layerState2 = mTestLayers[1]->layerState; + + const std::vector<const LayerState*> layers = { + layerState1.get(), + layerState2.get(), + }; + + initializeFlattener(layers); + + // make all layers inactive + mTime += 200ms; + expectAllLayersFlattened(layers); + EXPECT_EQ(overrideDisplaySpace.bounds, + Rect(mOutputState.framebufferSpace.bounds.getWidth(), + mOutputState.framebufferSpace.bounds.getHeight())); + EXPECT_EQ(overrideDisplaySpace.content, Rect(0, 0, 2, 2)); + EXPECT_EQ(overrideDisplaySpace.orientation, mOutputState.framebufferSpace.orientation); +} + TEST_F(FlattenerTest, flattenLayers_addLayerToFlattenedCauseReset) { auto& layerState1 = mTestLayers[0]->layerState; const auto& overrideBuffer1 = layerState1->getOutputLayer()->getState().overrideInfo.buffer; @@ -405,7 +430,7 @@ TEST_F(FlattenerTest, flattenLayers_BufferUpdateForMiddleLayer) { initializeOverrideBuffer(layers); EXPECT_NE(getNonBufferHash(layers), mFlattener->flattenLayers(layers, getNonBufferHash(layers), mTime)); - mOutputState.displaySpace.orientation = ui::ROTATION_90; + mOutputState.framebufferSpace.orientation = ui::ROTATION_90; mFlattener->renderCachedSets(mRenderEngine, mOutputState); EXPECT_NE(nullptr, overrideBuffer1); @@ -418,7 +443,7 @@ TEST_F(FlattenerTest, flattenLayers_BufferUpdateForMiddleLayer) { initializeOverrideBuffer(layers); EXPECT_NE(getNonBufferHash(layers), mFlattener->flattenLayers(layers, getNonBufferHash(layers), mTime)); - mOutputState.displaySpace.orientation = ui::ROTATION_180; + mOutputState.framebufferSpace.orientation = ui::ROTATION_180; mFlattener->renderCachedSets(mRenderEngine, mOutputState); EXPECT_NE(nullptr, overrideBuffer1); @@ -445,7 +470,7 @@ TEST_F(FlattenerTest, flattenLayers_BufferUpdateForMiddleLayer) { initializeOverrideBuffer(layers); EXPECT_NE(getNonBufferHash(layers), mFlattener->flattenLayers(layers, getNonBufferHash(layers), mTime)); - mOutputState.displaySpace.orientation = ui::ROTATION_270; + mOutputState.framebufferSpace.orientation = ui::ROTATION_270; mFlattener->renderCachedSets(mRenderEngine, mOutputState); EXPECT_NE(nullptr, overrideBuffer1); |