diff options
Diffstat (limited to 'services/surfaceflinger/CompositionEngine/tests/planner/CachedSetTest.cpp')
-rw-r--r-- | services/surfaceflinger/CompositionEngine/tests/planner/CachedSetTest.cpp | 257 |
1 files changed, 245 insertions, 12 deletions
diff --git a/services/surfaceflinger/CompositionEngine/tests/planner/CachedSetTest.cpp b/services/surfaceflinger/CompositionEngine/tests/planner/CachedSetTest.cpp index 283c69270f..a39331c02d 100644 --- a/services/surfaceflinger/CompositionEngine/tests/planner/CachedSetTest.cpp +++ b/services/surfaceflinger/CompositionEngine/tests/planner/CachedSetTest.cpp @@ -19,8 +19,12 @@ #include <compositionengine/impl/planner/LayerState.h> #include <compositionengine/mock/LayerFE.h> #include <compositionengine/mock/OutputLayer.h> +#include <gmock/gmock-actions.h> #include <gtest/gtest.h> +#include <renderengine/ExternalTexture.h> #include <renderengine/mock/RenderEngine.h> +#include <ui/GraphicTypes.h> +#include <memory> namespace android::compositionengine { using namespace std::chrono_literals; @@ -105,7 +109,6 @@ void CachedSetTest::TearDown() { } void expectEqual(const CachedSet& cachedSet, const CachedSet::Layer& layer) { - EXPECT_EQ(layer.getHash(), cachedSet.getFingerprint()); EXPECT_EQ(layer.getLastUpdate(), cachedSet.getLastUpdate()); EXPECT_EQ(layer.getDisplayFrame(), cachedSet.getBounds()); EXPECT_TRUE(layer.getVisibleRegion().hasSameRects(cachedSet.getVisibleRegion())); @@ -154,7 +157,6 @@ TEST_F(CachedSetTest, addLayer) { CachedSet cachedSet(layer1); cachedSet.addLayer(layer2.getState(), kStartTime + 10ms); - EXPECT_EQ(layer1.getHash(), cachedSet.getFingerprint()); EXPECT_EQ(kStartTime, cachedSet.getLastUpdate()); EXPECT_EQ(Rect(0, 0, 2, 2), cachedSet.getBounds()); Region expectedRegion; @@ -243,7 +245,6 @@ TEST_F(CachedSetTest, append) { cachedSet1.addLayer(layer3.getState(), kStartTime + 10ms); cachedSet1.append(cachedSet2); - EXPECT_EQ(layer1.getHash(), cachedSet1.getFingerprint()); EXPECT_EQ(kStartTime, cachedSet1.getLastUpdate()); EXPECT_EQ(Rect(0, 0, 3, 3), cachedSet1.getBounds()); Region expectedRegion; @@ -287,10 +288,11 @@ TEST_F(CachedSetTest, updateAge_BufferUpdate) { } TEST_F(CachedSetTest, render) { - CachedSet::Layer& layer1 = *mTestLayers[0]->cachedSetLayer.get(); - sp<mock::LayerFE> layerFE1 = mTestLayers[0]->layerFE; - CachedSet::Layer& layer2 = *mTestLayers[1]->cachedSetLayer.get(); - sp<mock::LayerFE> layerFE2 = mTestLayers[1]->layerFE; + // Skip the 0th layer to ensure that the bounding box of the layers is offset from (0, 0) + CachedSet::Layer& layer1 = *mTestLayers[1]->cachedSetLayer.get(); + sp<mock::LayerFE> layerFE1 = mTestLayers[1]->layerFE; + CachedSet::Layer& layer2 = *mTestLayers[2]->cachedSetLayer.get(); + sp<mock::LayerFE> layerFE2 = mTestLayers[2]->layerFE; CachedSet cachedSet(layer1); cachedSet.append(CachedSet(layer2)); @@ -307,7 +309,7 @@ TEST_F(CachedSetTest, render) { const std::vector<const renderengine::LayerSettings*>& layers, const std::shared_ptr<renderengine::ExternalTexture>&, const bool, base::unique_fd&&, base::unique_fd*) -> size_t { - EXPECT_EQ(Rect(0, 0, 2, 2), displaySettings.physicalDisplay); + EXPECT_EQ(Rect(-1, -1, 9, 4), displaySettings.physicalDisplay); EXPECT_EQ(mOutputState.layerStackSpace.content, displaySettings.clip); EXPECT_EQ(ui::Transform::toRotationFlags(mOutputState.framebufferSpace.orientation), displaySettings.orientation); @@ -324,15 +326,246 @@ 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); + EXPECT_EQ(mOutputState.framebufferSpace, cachedSet.getOutputSpace()); // Now check that appending a new cached set properly cleans up RenderEngine resources. CachedSet::Layer& layer3 = *mTestLayers[2]->cachedSetLayer.get(); cachedSet.append(CachedSet(layer3)); } +TEST_F(CachedSetTest, rendersWithOffsetFramebufferContent) { + // Skip the 0th layer to ensure that the bounding box of the layers is offset from (0, 0) + CachedSet::Layer& layer1 = *mTestLayers[1]->cachedSetLayer.get(); + sp<mock::LayerFE> layerFE1 = mTestLayers[1]->layerFE; + CachedSet::Layer& layer2 = *mTestLayers[2]->cachedSetLayer.get(); + sp<mock::LayerFE> layerFE2 = mTestLayers[2]->layerFE; + + CachedSet cachedSet(layer1); + cachedSet.append(CachedSet(layer2)); + + std::vector<compositionengine::LayerFE::LayerSettings> clientCompList1; + clientCompList1.push_back({}); + clientCompList1[0].alpha = 0.5f; + + std::vector<compositionengine::LayerFE::LayerSettings> clientCompList2; + clientCompList2.push_back({}); + clientCompList2[0].alpha = 0.75f; + + mOutputState.framebufferSpace = ProjectionSpace(ui::Size(10, 20), Rect(2, 3, 10, 5)); + + const auto drawLayers = [&](const renderengine::DisplaySettings& displaySettings, + const std::vector<const renderengine::LayerSettings*>& layers, + const std::shared_ptr<renderengine::ExternalTexture>&, const bool, + base::unique_fd&&, base::unique_fd*) -> size_t { + EXPECT_EQ(Rect(1, 2, 9, 4), displaySettings.physicalDisplay); + EXPECT_EQ(mOutputState.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); + + return NO_ERROR; + }; + + EXPECT_CALL(*layerFE1, prepareClientCompositionList(_)).WillOnce(Return(clientCompList1)); + EXPECT_CALL(*layerFE2, prepareClientCompositionList(_)).WillOnce(Return(clientCompList2)); + EXPECT_CALL(mRenderEngine, drawLayers(_, _, _, _, _, _)).WillOnce(Invoke(drawLayers)); + cachedSet.render(mRenderEngine, mOutputState); + expectReadyBuffer(cachedSet); + + EXPECT_EQ(mOutputState.framebufferSpace, cachedSet.getOutputSpace()); + + // Now check that appending a new cached set properly cleans up RenderEngine resources. + CachedSet::Layer& layer3 = *mTestLayers[2]->cachedSetLayer.get(); + cachedSet.append(CachedSet(layer3)); +} + +TEST_F(CachedSetTest, holePunch_requiresBuffer) { + CachedSet::Layer& layer1 = *mTestLayers[0]->cachedSetLayer.get(); + sp<mock::LayerFE> layerFE1 = mTestLayers[0]->layerFE; + + CachedSet cachedSet(layer1); + EXPECT_CALL(*layerFE1, hasRoundedCorners()).WillRepeatedly(Return(true)); + + EXPECT_FALSE(cachedSet.requiresHolePunch()); +} + +TEST_F(CachedSetTest, holePunch_requiresRoundedCorners) { + CachedSet::Layer& layer1 = *mTestLayers[0]->cachedSetLayer.get(); + mTestLayers[0]->layerFECompositionState.buffer = sp<GraphicBuffer>::make(); + + CachedSet cachedSet(layer1); + + EXPECT_FALSE(cachedSet.requiresHolePunch()); +} + +TEST_F(CachedSetTest, holePunch_requiresSingleLayer) { + CachedSet::Layer& layer1 = *mTestLayers[0]->cachedSetLayer.get(); + mTestLayers[0]->layerFECompositionState.buffer = sp<GraphicBuffer>::make(); + sp<mock::LayerFE> layerFE = mTestLayers[0]->layerFE; + EXPECT_CALL(*layerFE, hasRoundedCorners()).WillRepeatedly(Return(true)); + + CachedSet::Layer& layer2 = *mTestLayers[1]->cachedSetLayer.get(); + + CachedSet cachedSet(layer1); + cachedSet.append(layer2); + + EXPECT_FALSE(cachedSet.requiresHolePunch()); +} + +TEST_F(CachedSetTest, requiresHolePunch) { + CachedSet::Layer& layer = *mTestLayers[0]->cachedSetLayer.get(); + mTestLayers[0]->layerFECompositionState.buffer = sp<GraphicBuffer>::make(); + sp<mock::LayerFE> layerFE = mTestLayers[0]->layerFE; + + CachedSet cachedSet(layer); + EXPECT_CALL(*layerFE, hasRoundedCorners()).WillRepeatedly(Return(true)); + + EXPECT_TRUE(cachedSet.requiresHolePunch()); +} + +TEST_F(CachedSetTest, holePunch_requiresDeviceComposition) { + CachedSet::Layer& layer = *mTestLayers[0]->cachedSetLayer.get(); + sp<mock::LayerFE> layerFE = mTestLayers[0]->layerFE; + auto& layerFECompositionState = mTestLayers[0]->layerFECompositionState; + layerFECompositionState.buffer = sp<GraphicBuffer>::make(); + layerFECompositionState.forceClientComposition = true; + + CachedSet cachedSet(layer); + EXPECT_CALL(*layerFE, hasRoundedCorners()).WillRepeatedly(Return(true)); + + EXPECT_FALSE(cachedSet.requiresHolePunch()); +} + +TEST_F(CachedSetTest, addHolePunch_requiresOverlap) { + CachedSet::Layer& layer1 = *mTestLayers[0]->cachedSetLayer.get(); + CachedSet::Layer& layer2 = *mTestLayers[1]->cachedSetLayer.get(); + CachedSet::Layer& layer3 = *mTestLayers[2]->cachedSetLayer.get(); + + CachedSet cachedSet(layer1); + cachedSet.addLayer(layer2.getState(), kStartTime + 10ms); + + cachedSet.addHolePunchLayerIfFeasible(layer3, true); + + ASSERT_EQ(nullptr, cachedSet.getHolePunchLayer()); +} + +TEST_F(CachedSetTest, addHolePunch_requiresOpaque) { + mTestLayers[0]->outputLayerCompositionState.displayFrame = Rect(0, 0, 5, 5); + mTestLayers[0]->layerFECompositionState.isOpaque = false; + CachedSet::Layer& layer1 = *mTestLayers[0]->cachedSetLayer.get(); + CachedSet::Layer& layer2 = *mTestLayers[1]->cachedSetLayer.get(); + CachedSet::Layer& layer3 = *mTestLayers[2]->cachedSetLayer.get(); + + CachedSet cachedSet(layer1); + cachedSet.addLayer(layer2.getState(), kStartTime + 10ms); + + cachedSet.addHolePunchLayerIfFeasible(layer3, false); + + ASSERT_EQ(nullptr, cachedSet.getHolePunchLayer()); +} + +TEST_F(CachedSetTest, addHolePunch_opaque) { + mTestLayers[0]->outputLayerCompositionState.displayFrame = Rect(0, 0, 5, 5); + mTestLayers[0]->layerFECompositionState.isOpaque = true; + CachedSet::Layer& layer1 = *mTestLayers[0]->cachedSetLayer.get(); + CachedSet::Layer& layer2 = *mTestLayers[1]->cachedSetLayer.get(); + CachedSet::Layer& layer3 = *mTestLayers[2]->cachedSetLayer.get(); + + CachedSet cachedSet(layer1); + cachedSet.addLayer(layer2.getState(), kStartTime + 10ms); + + cachedSet.addHolePunchLayerIfFeasible(layer3, false); + + ASSERT_EQ(&mTestLayers[2]->outputLayer, cachedSet.getHolePunchLayer()); +} + +TEST_F(CachedSetTest, addHolePunch_firstLayer) { + mTestLayers[0]->outputLayerCompositionState.displayFrame = Rect(0, 0, 5, 5); + mTestLayers[0]->layerFECompositionState.isOpaque = false; + CachedSet::Layer& layer1 = *mTestLayers[0]->cachedSetLayer.get(); + CachedSet::Layer& layer2 = *mTestLayers[1]->cachedSetLayer.get(); + CachedSet::Layer& layer3 = *mTestLayers[2]->cachedSetLayer.get(); + + CachedSet cachedSet(layer1); + cachedSet.addLayer(layer2.getState(), kStartTime + 10ms); + + cachedSet.addHolePunchLayerIfFeasible(layer3, true); + + ASSERT_EQ(&mTestLayers[2]->outputLayer, cachedSet.getHolePunchLayer()); +} + +TEST_F(CachedSetTest, addHolePunch) { + mTestLayers[0]->outputLayerCompositionState.displayFrame = Rect(0, 0, 5, 5); + CachedSet::Layer& layer1 = *mTestLayers[0]->cachedSetLayer.get(); + sp<mock::LayerFE> layerFE1 = mTestLayers[0]->layerFE; + + CachedSet::Layer& layer2 = *mTestLayers[1]->cachedSetLayer.get(); + sp<mock::LayerFE> layerFE2 = mTestLayers[1]->layerFE; + + CachedSet::Layer& layer3 = *mTestLayers[2]->cachedSetLayer.get(); + sp<mock::LayerFE> layerFE3 = mTestLayers[2]->layerFE; + + CachedSet cachedSet(layer1); + cachedSet.addLayer(layer2.getState(), kStartTime + 10ms); + + cachedSet.addHolePunchLayerIfFeasible(layer3, true); + + std::vector<compositionengine::LayerFE::LayerSettings> clientCompList1; + clientCompList1.push_back({}); + std::vector<compositionengine::LayerFE::LayerSettings> clientCompList2; + clientCompList2.push_back({}); + std::vector<compositionengine::LayerFE::LayerSettings> clientCompList3; + clientCompList3.push_back({}); + + clientCompList3[0].source.buffer.buffer = std::make_shared< + renderengine::ExternalTexture>(sp<GraphicBuffer>::make(), mRenderEngine, + renderengine::ExternalTexture::READABLE); + + EXPECT_CALL(*layerFE1, prepareClientCompositionList(_)).WillOnce(Return(clientCompList1)); + EXPECT_CALL(*layerFE2, prepareClientCompositionList(_)).WillOnce(Return(clientCompList2)); + EXPECT_CALL(*layerFE3, prepareClientCompositionList(_)).WillOnce(Return(clientCompList3)); + + const auto drawLayers = [&](const renderengine::DisplaySettings&, + const std::vector<const renderengine::LayerSettings*>& layers, + const std::shared_ptr<renderengine::ExternalTexture>&, const bool, + base::unique_fd&&, base::unique_fd*) -> size_t { + // If the highlight layer is enabled, it will increase the size by 1. + // We're interested in the third layer either way. + EXPECT_GE(layers.size(), 3u); + const auto* holePunchSettings = layers[2]; + EXPECT_EQ(nullptr, holePunchSettings->source.buffer.buffer); + EXPECT_EQ(half3(0.0f, 0.0f, 0.0f), holePunchSettings->source.solidColor); + EXPECT_TRUE(holePunchSettings->disableBlending); + EXPECT_EQ(0.0f, holePunchSettings->alpha); + + return NO_ERROR; + }; + + EXPECT_CALL(mRenderEngine, drawLayers(_, _, _, _, _, _)).WillOnce(Invoke(drawLayers)); + cachedSet.render(mRenderEngine, mOutputState); +} + +TEST_F(CachedSetTest, decompose_removesHolePunch) { + mTestLayers[0]->outputLayerCompositionState.displayFrame = Rect(0, 0, 5, 5); + CachedSet::Layer& layer1 = *mTestLayers[0]->cachedSetLayer.get(); + CachedSet::Layer& layer2 = *mTestLayers[1]->cachedSetLayer.get(); + CachedSet::Layer& layer3 = *mTestLayers[2]->cachedSetLayer.get(); + + CachedSet cachedSet(layer1); + cachedSet.addLayer(layer2.getState(), kStartTime + 10ms); + + cachedSet.addHolePunchLayerIfFeasible(layer3, true); + + ASSERT_EQ(&mTestLayers[2]->outputLayer, cachedSet.getHolePunchLayer()); + + std::vector<CachedSet> decomposed = cachedSet.decompose(); + EXPECT_EQ(2u, decomposed.size()); + for (const auto& set : decomposed) { + EXPECT_EQ(nullptr, set.getHolePunchLayer()); + } +} + } // namespace } // namespace android::compositionengine |