Loading services/surfaceflinger/CompositionEngine/Android.bp +1 −0 Original line number Diff line number Diff line Loading @@ -106,6 +106,7 @@ cc_test { "tests/planner/CachedSetTest.cpp", "tests/planner/FlattenerTest.cpp", "tests/planner/LayerStateTest.cpp", "tests/planner/PredictorTest.cpp", "tests/CompositionEngineTest.cpp", "tests/DisplayColorProfileTest.cpp", "tests/DisplayTest.cpp", Loading services/surfaceflinger/CompositionEngine/include/compositionengine/impl/planner/Predictor.h +12 −0 Original line number Diff line number Diff line Loading @@ -24,16 +24,28 @@ class LayerStack { public: LayerStack(const std::vector<const LayerState*>& layers) : mLayers(copyLayers(layers)) {} // Describes an approximate match between two layer stacks struct ApproximateMatch { bool operator==(const ApproximateMatch& other) const { return differingIndex == other.differingIndex && differingFields == other.differingFields; } // The index of the single differing layer between the two stacks. // This implies that only one layer is allowed to differ in an approximate match. size_t differingIndex; // Set of fields that differ for the differing layer in the approximate match. Flags<LayerStateField> differingFields; }; // Returns an approximate match when comparing this layer stack with the provided list of // layers, for the purposes of scoring how closely the two layer stacks will match composition // strategies. // // If the two layer stacks are identical, then an approximate match is still returned, but the // differing fields will be empty to represent an exact match. // // If the two layer stacks differ by too much, then an empty optional is returned. std::optional<ApproximateMatch> getApproximateMatch( const std::vector<const LayerState*>& other) const; Loading services/surfaceflinger/CompositionEngine/src/planner/Predictor.cpp +6 −2 Original line number Diff line number Diff line Loading @@ -50,8 +50,8 @@ std::optional<LayerStack::ApproximateMatch> LayerStack::getApproximateMatch( return std::nullopt; } // If layers are not identical, but we already have a prior approximate match, // the LayerStacks differ by too much, so return nothing // If layers are not identical, but we already detected a prior approximate match for a // previous layer, the LayerStacks differ by too much, so return nothing if (approximateMatch) { return std::nullopt; } Loading @@ -72,6 +72,10 @@ std::optional<LayerStack::ApproximateMatch> LayerStack::getApproximateMatch( } } if (approximateMatch) { return approximateMatch; } // If we make it through the layer-by-layer comparison without an approximate match, // it means that all layers were either identical or had client-composited layers in common, // which don't affect the composition strategy, so return a successful result with Loading services/surfaceflinger/CompositionEngine/tests/planner/PredictorTest.cpp 0 → 100644 +336 −0 Original line number Diff line number Diff line /* * Copyright 2021 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #include "DisplayHardware/Hal.h" #undef LOG_TAG #define LOG_TAG "LayerStateTest" #include <compositionengine/impl/planner/Predictor.h> #include <compositionengine/mock/LayerFE.h> #include <compositionengine/mock/OutputLayer.h> #include <gtest/gtest.h> #include <log/log.h> namespace android::compositionengine::impl::planner { namespace { const FloatRect sFloatRectOne = FloatRect(100.f, 200.f, 300.f, 400.f); const FloatRect sFloatRectTwo = FloatRect(400.f, 300.f, 200.f, 100.f); const Rect sRectOne = Rect(1, 2, 3, 4); const Rect sRectTwo = Rect(4, 3, 2, 1); const constexpr int32_t sZOne = 100; const constexpr int32_t sZTwo = 101; const constexpr float sAlphaOne = 0.25f; const constexpr float sAlphaTwo = 0.5f; const Region sRegionOne = Region(sRectOne); const Region sRegionTwo = Region(sRectTwo); const mat4 sMat4One = mat4::scale(vec4(2.f, 3.f, 1.f, 1.f)); using testing::Return; using testing::ReturnRef; const std::string sDebugName = std::string("Test LayerFE"); const constexpr int32_t sSequenceId = 12345; struct LayerStackTest : public testing::Test { LayerStackTest() { const ::testing::TestInfo* const test_info = ::testing::UnitTest::GetInstance()->current_test_info(); ALOGD("**** Setting up for %s.%s\n", test_info->test_case_name(), test_info->name()); } ~LayerStackTest() { const ::testing::TestInfo* const test_info = ::testing::UnitTest::GetInstance()->current_test_info(); ALOGD("**** Tearing down after %s.%s\n", test_info->test_case_name(), test_info->name()); } void setupMocksForLayer(mock::OutputLayer& layer, mock::LayerFE& layerFE, const OutputLayerCompositionState& outputLayerState, const LayerFECompositionState& layerFEState) { EXPECT_CALL(layer, getLayerFE()).WillRepeatedly(ReturnRef(layerFE)); EXPECT_CALL(layer, getState()).WillRepeatedly(ReturnRef(outputLayerState)); EXPECT_CALL(layerFE, getSequence()).WillRepeatedly(Return(sSequenceId)); EXPECT_CALL(layerFE, getDebugName()).WillRepeatedly(Return(sDebugName.c_str())); EXPECT_CALL(layerFE, getCompositionState()).WillRepeatedly(Return(&layerFEState)); } }; TEST_F(LayerStackTest, getApproximateMatch_doesNotMatchSizeDifferences) { mock::OutputLayer outputLayerOne; mock::LayerFE layerFEOne; OutputLayerCompositionState outputLayerCompositionStateOne; LayerFECompositionState layerFECompositionStateOne; setupMocksForLayer(outputLayerOne, layerFEOne, outputLayerCompositionStateOne, layerFECompositionStateOne); LayerState layerStateOne(&outputLayerOne); mock::OutputLayer outputLayerTwo; mock::LayerFE layerFETwo; OutputLayerCompositionState outputLayerCompositionStateTwo; LayerFECompositionState layerFECompositionStateTwo; setupMocksForLayer(outputLayerTwo, layerFETwo, outputLayerCompositionStateTwo, layerFECompositionStateTwo); LayerState layerStateTwo(&outputLayerTwo); mock::OutputLayer outputLayerThree; mock::LayerFE layerFEThree; OutputLayerCompositionState outputLayerCompositionStateThree; LayerFECompositionState layerFECompositionStateThree; setupMocksForLayer(outputLayerThree, layerFEThree, outputLayerCompositionStateThree, layerFECompositionStateThree); LayerState layerStateThree(&outputLayerThree); LayerStack stack({&layerStateOne}); EXPECT_FALSE(stack.getApproximateMatch({})); EXPECT_FALSE(stack.getApproximateMatch({&layerStateOne, &layerStateThree})); } TEST_F(LayerStackTest, getApproximateMatch_doesNotMatchDifferentCompositionTypes) { mock::OutputLayer outputLayerOne; mock::LayerFE layerFEOne; OutputLayerCompositionState outputLayerCompositionStateOne; LayerFECompositionState layerFECompositionStateOne; layerFECompositionStateOne.compositionType = hal::Composition::DEVICE; setupMocksForLayer(outputLayerOne, layerFEOne, outputLayerCompositionStateOne, layerFECompositionStateOne); LayerState layerStateOne(&outputLayerOne); mock::OutputLayer outputLayerTwo; mock::LayerFE layerFETwo; OutputLayerCompositionState outputLayerCompositionStateTwo; LayerFECompositionState layerFECompositionStateTwo; layerFECompositionStateTwo.compositionType = hal::Composition::SOLID_COLOR; setupMocksForLayer(outputLayerTwo, layerFETwo, outputLayerCompositionStateTwo, layerFECompositionStateTwo); LayerState layerStateTwo(&outputLayerTwo); LayerStack stack({&layerStateOne}); EXPECT_FALSE(stack.getApproximateMatch({&layerStateTwo})); } TEST_F(LayerStackTest, getApproximateMatch_matchesSingleDifferenceInSingleLayer) { mock::OutputLayer outputLayerOne; mock::LayerFE layerFEOne; OutputLayerCompositionState outputLayerCompositionStateOne{ .sourceCrop = sFloatRectOne, }; LayerFECompositionState layerFECompositionStateOne; setupMocksForLayer(outputLayerOne, layerFEOne, outputLayerCompositionStateOne, layerFECompositionStateOne); LayerState layerStateOne(&outputLayerOne); mock::OutputLayer outputLayerTwo; mock::LayerFE layerFETwo; OutputLayerCompositionState outputLayerCompositionStateTwo{ .sourceCrop = sFloatRectTwo, }; LayerFECompositionState layerFECompositionStateTwo; setupMocksForLayer(outputLayerTwo, layerFETwo, outputLayerCompositionStateTwo, layerFECompositionStateTwo); LayerState layerStateTwo(&outputLayerTwo); LayerStack stack({&layerStateOne}); const auto match = stack.getApproximateMatch({&layerStateTwo}); EXPECT_TRUE(match); LayerStack::ApproximateMatch expectedMatch; expectedMatch.differingIndex = 0; expectedMatch.differingFields = LayerStateField::SourceCrop; EXPECT_EQ(expectedMatch, *match); } TEST_F(LayerStackTest, getApproximateMatch_matchesSingleDifferenceInMultiLayerStack) { mock::OutputLayer outputLayerOne; mock::LayerFE layerFEOne; OutputLayerCompositionState outputLayerCompositionStateOne{ .sourceCrop = sFloatRectOne, }; LayerFECompositionState layerFECompositionStateOne; setupMocksForLayer(outputLayerOne, layerFEOne, outputLayerCompositionStateOne, layerFECompositionStateOne); LayerState layerStateOne(&outputLayerOne); mock::OutputLayer outputLayerTwo; mock::LayerFE layerFETwo; OutputLayerCompositionState outputLayerCompositionStateTwo{ .sourceCrop = sFloatRectTwo, }; LayerFECompositionState layerFECompositionStateTwo; setupMocksForLayer(outputLayerTwo, layerFETwo, outputLayerCompositionStateTwo, layerFECompositionStateTwo); LayerState layerStateTwo(&outputLayerTwo); LayerStack stack({&layerStateOne, &layerStateOne}); const auto match = stack.getApproximateMatch({&layerStateOne, &layerStateTwo}); EXPECT_TRUE(match); LayerStack::ApproximateMatch expectedMatch; expectedMatch.differingIndex = 1; expectedMatch.differingFields = LayerStateField::SourceCrop; EXPECT_EQ(expectedMatch, *match); } TEST_F(LayerStackTest, getApproximateMatch_doesNotMatchManyDifferences) { mock::OutputLayer outputLayerOne; mock::LayerFE layerFEOne; OutputLayerCompositionState outputLayerCompositionStateOne{ .visibleRegion = sRegionOne, .displayFrame = sRectOne, .sourceCrop = sFloatRectOne, .dataspace = ui::Dataspace::SRGB, .z = sZOne, }; LayerFECompositionState layerFECompositionStateOne; layerFECompositionStateOne.alpha = sAlphaOne; layerFECompositionStateOne.colorTransformIsIdentity = true; setupMocksForLayer(outputLayerOne, layerFEOne, outputLayerCompositionStateOne, layerFECompositionStateOne); LayerState layerStateOne(&outputLayerOne); mock::OutputLayer outputLayerTwo; mock::LayerFE layerFETwo; OutputLayerCompositionState outputLayerCompositionStateTwo{ .visibleRegion = sRegionTwo, .displayFrame = sRectTwo, .sourceCrop = sFloatRectTwo, .dataspace = ui::Dataspace::DISPLAY_P3, .z = sZTwo, }; LayerFECompositionState layerFECompositionStateTwo; layerFECompositionStateTwo.alpha = sAlphaTwo; layerFECompositionStateTwo.colorTransformIsIdentity = false; layerFECompositionStateTwo.colorTransform = sMat4One; setupMocksForLayer(outputLayerTwo, layerFETwo, outputLayerCompositionStateTwo, layerFECompositionStateTwo); LayerState layerStateTwo(&outputLayerTwo); LayerStack stack({&layerStateOne}); EXPECT_FALSE(stack.getApproximateMatch({&layerStateTwo})); } TEST_F(LayerStackTest, getApproximateMatch_exactMatchesSameBuffer) { sp<GraphicBuffer> buffer = new GraphicBuffer(); mock::OutputLayer outputLayerOne; mock::LayerFE layerFEOne; OutputLayerCompositionState outputLayerCompositionStateOne; LayerFECompositionState layerFECompositionStateOne; layerFECompositionStateOne.buffer = buffer; setupMocksForLayer(outputLayerOne, layerFEOne, outputLayerCompositionStateOne, layerFECompositionStateOne); LayerState layerStateOne(&outputLayerOne); mock::OutputLayer outputLayerTwo; mock::LayerFE layerFETwo; OutputLayerCompositionState outputLayerCompositionStateTwo; LayerFECompositionState layerFECompositionStateTwo; layerFECompositionStateTwo.buffer = buffer; setupMocksForLayer(outputLayerTwo, layerFETwo, outputLayerCompositionStateTwo, layerFECompositionStateTwo); LayerState layerStateTwo(&outputLayerTwo); LayerStack stack({&layerStateOne}); const auto match = stack.getApproximateMatch({&layerStateTwo}); EXPECT_TRUE(match); LayerStack::ApproximateMatch expectedMatch; expectedMatch.differingIndex = 0; expectedMatch.differingFields = LayerStateField::None; EXPECT_EQ(expectedMatch, *match); } TEST_F(LayerStackTest, getApproximateMatch_alwaysMatchesClientComposition) { mock::OutputLayer outputLayerOne; mock::LayerFE layerFEOne; OutputLayerCompositionState outputLayerCompositionStateOne{ .visibleRegion = sRegionOne, .forceClientComposition = true, .displayFrame = sRectOne, .sourceCrop = sFloatRectOne, .dataspace = ui::Dataspace::SRGB, .z = sZOne, }; LayerFECompositionState layerFECompositionStateOne; layerFECompositionStateOne.buffer = new GraphicBuffer(); layerFECompositionStateOne.alpha = sAlphaOne; layerFECompositionStateOne.colorTransformIsIdentity = true; setupMocksForLayer(outputLayerOne, layerFEOne, outputLayerCompositionStateOne, layerFECompositionStateOne); LayerState layerStateOne(&outputLayerOne); mock::OutputLayer outputLayerTwo; mock::LayerFE layerFETwo; OutputLayerCompositionState outputLayerCompositionStateTwo{ .visibleRegion = sRegionTwo, .forceClientComposition = true, .displayFrame = sRectTwo, .sourceCrop = sFloatRectTwo, .dataspace = ui::Dataspace::DISPLAY_P3, .z = sZTwo, }; LayerFECompositionState layerFECompositionStateTwo; layerFECompositionStateTwo.buffer = new GraphicBuffer(); layerFECompositionStateTwo.alpha = sAlphaTwo; layerFECompositionStateTwo.colorTransformIsIdentity = false; layerFECompositionStateTwo.colorTransform = sMat4One; setupMocksForLayer(outputLayerTwo, layerFETwo, outputLayerCompositionStateTwo, layerFECompositionStateTwo); LayerState layerStateTwo(&outputLayerTwo); LayerStack stack({&layerStateOne}); const auto match = stack.getApproximateMatch({&layerStateTwo}); EXPECT_TRUE(match); LayerStack::ApproximateMatch expectedMatch; expectedMatch.differingIndex = 0; expectedMatch.differingFields = LayerStateField::None; EXPECT_EQ(expectedMatch, *match); } TEST_F(LayerStackTest, getApproximateMatch_doesNotMatchMultipleApproximations) { mock::OutputLayer outputLayerOne; mock::LayerFE layerFEOne; OutputLayerCompositionState outputLayerCompositionStateOne{ .sourceCrop = sFloatRectOne, }; LayerFECompositionState layerFECompositionStateOne; layerFECompositionStateOne.buffer = new GraphicBuffer(); setupMocksForLayer(outputLayerOne, layerFEOne, outputLayerCompositionStateOne, layerFECompositionStateOne); LayerState layerStateOne(&outputLayerOne); mock::OutputLayer outputLayerTwo; mock::LayerFE layerFETwo; OutputLayerCompositionState outputLayerCompositionStateTwo{ .sourceCrop = sFloatRectTwo, }; LayerFECompositionState layerFECompositionStateTwo; layerFECompositionStateTwo.buffer = new GraphicBuffer(); setupMocksForLayer(outputLayerTwo, layerFETwo, outputLayerCompositionStateTwo, layerFECompositionStateTwo); LayerState layerStateTwo(&outputLayerTwo); EXPECT_TRUE(LayerStack({&layerStateOne}).getApproximateMatch({&layerStateTwo})); LayerStack stack({&layerStateOne, &layerStateOne}); EXPECT_FALSE(stack.getApproximateMatch({&layerStateTwo, &layerStateTwo})); } } // namespace } // namespace android::compositionengine::impl::planner No newline at end of file Loading
services/surfaceflinger/CompositionEngine/Android.bp +1 −0 Original line number Diff line number Diff line Loading @@ -106,6 +106,7 @@ cc_test { "tests/planner/CachedSetTest.cpp", "tests/planner/FlattenerTest.cpp", "tests/planner/LayerStateTest.cpp", "tests/planner/PredictorTest.cpp", "tests/CompositionEngineTest.cpp", "tests/DisplayColorProfileTest.cpp", "tests/DisplayTest.cpp", Loading
services/surfaceflinger/CompositionEngine/include/compositionengine/impl/planner/Predictor.h +12 −0 Original line number Diff line number Diff line Loading @@ -24,16 +24,28 @@ class LayerStack { public: LayerStack(const std::vector<const LayerState*>& layers) : mLayers(copyLayers(layers)) {} // Describes an approximate match between two layer stacks struct ApproximateMatch { bool operator==(const ApproximateMatch& other) const { return differingIndex == other.differingIndex && differingFields == other.differingFields; } // The index of the single differing layer between the two stacks. // This implies that only one layer is allowed to differ in an approximate match. size_t differingIndex; // Set of fields that differ for the differing layer in the approximate match. Flags<LayerStateField> differingFields; }; // Returns an approximate match when comparing this layer stack with the provided list of // layers, for the purposes of scoring how closely the two layer stacks will match composition // strategies. // // If the two layer stacks are identical, then an approximate match is still returned, but the // differing fields will be empty to represent an exact match. // // If the two layer stacks differ by too much, then an empty optional is returned. std::optional<ApproximateMatch> getApproximateMatch( const std::vector<const LayerState*>& other) const; Loading
services/surfaceflinger/CompositionEngine/src/planner/Predictor.cpp +6 −2 Original line number Diff line number Diff line Loading @@ -50,8 +50,8 @@ std::optional<LayerStack::ApproximateMatch> LayerStack::getApproximateMatch( return std::nullopt; } // If layers are not identical, but we already have a prior approximate match, // the LayerStacks differ by too much, so return nothing // If layers are not identical, but we already detected a prior approximate match for a // previous layer, the LayerStacks differ by too much, so return nothing if (approximateMatch) { return std::nullopt; } Loading @@ -72,6 +72,10 @@ std::optional<LayerStack::ApproximateMatch> LayerStack::getApproximateMatch( } } if (approximateMatch) { return approximateMatch; } // If we make it through the layer-by-layer comparison without an approximate match, // it means that all layers were either identical or had client-composited layers in common, // which don't affect the composition strategy, so return a successful result with Loading
services/surfaceflinger/CompositionEngine/tests/planner/PredictorTest.cpp 0 → 100644 +336 −0 Original line number Diff line number Diff line /* * Copyright 2021 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #include "DisplayHardware/Hal.h" #undef LOG_TAG #define LOG_TAG "LayerStateTest" #include <compositionengine/impl/planner/Predictor.h> #include <compositionengine/mock/LayerFE.h> #include <compositionengine/mock/OutputLayer.h> #include <gtest/gtest.h> #include <log/log.h> namespace android::compositionengine::impl::planner { namespace { const FloatRect sFloatRectOne = FloatRect(100.f, 200.f, 300.f, 400.f); const FloatRect sFloatRectTwo = FloatRect(400.f, 300.f, 200.f, 100.f); const Rect sRectOne = Rect(1, 2, 3, 4); const Rect sRectTwo = Rect(4, 3, 2, 1); const constexpr int32_t sZOne = 100; const constexpr int32_t sZTwo = 101; const constexpr float sAlphaOne = 0.25f; const constexpr float sAlphaTwo = 0.5f; const Region sRegionOne = Region(sRectOne); const Region sRegionTwo = Region(sRectTwo); const mat4 sMat4One = mat4::scale(vec4(2.f, 3.f, 1.f, 1.f)); using testing::Return; using testing::ReturnRef; const std::string sDebugName = std::string("Test LayerFE"); const constexpr int32_t sSequenceId = 12345; struct LayerStackTest : public testing::Test { LayerStackTest() { const ::testing::TestInfo* const test_info = ::testing::UnitTest::GetInstance()->current_test_info(); ALOGD("**** Setting up for %s.%s\n", test_info->test_case_name(), test_info->name()); } ~LayerStackTest() { const ::testing::TestInfo* const test_info = ::testing::UnitTest::GetInstance()->current_test_info(); ALOGD("**** Tearing down after %s.%s\n", test_info->test_case_name(), test_info->name()); } void setupMocksForLayer(mock::OutputLayer& layer, mock::LayerFE& layerFE, const OutputLayerCompositionState& outputLayerState, const LayerFECompositionState& layerFEState) { EXPECT_CALL(layer, getLayerFE()).WillRepeatedly(ReturnRef(layerFE)); EXPECT_CALL(layer, getState()).WillRepeatedly(ReturnRef(outputLayerState)); EXPECT_CALL(layerFE, getSequence()).WillRepeatedly(Return(sSequenceId)); EXPECT_CALL(layerFE, getDebugName()).WillRepeatedly(Return(sDebugName.c_str())); EXPECT_CALL(layerFE, getCompositionState()).WillRepeatedly(Return(&layerFEState)); } }; TEST_F(LayerStackTest, getApproximateMatch_doesNotMatchSizeDifferences) { mock::OutputLayer outputLayerOne; mock::LayerFE layerFEOne; OutputLayerCompositionState outputLayerCompositionStateOne; LayerFECompositionState layerFECompositionStateOne; setupMocksForLayer(outputLayerOne, layerFEOne, outputLayerCompositionStateOne, layerFECompositionStateOne); LayerState layerStateOne(&outputLayerOne); mock::OutputLayer outputLayerTwo; mock::LayerFE layerFETwo; OutputLayerCompositionState outputLayerCompositionStateTwo; LayerFECompositionState layerFECompositionStateTwo; setupMocksForLayer(outputLayerTwo, layerFETwo, outputLayerCompositionStateTwo, layerFECompositionStateTwo); LayerState layerStateTwo(&outputLayerTwo); mock::OutputLayer outputLayerThree; mock::LayerFE layerFEThree; OutputLayerCompositionState outputLayerCompositionStateThree; LayerFECompositionState layerFECompositionStateThree; setupMocksForLayer(outputLayerThree, layerFEThree, outputLayerCompositionStateThree, layerFECompositionStateThree); LayerState layerStateThree(&outputLayerThree); LayerStack stack({&layerStateOne}); EXPECT_FALSE(stack.getApproximateMatch({})); EXPECT_FALSE(stack.getApproximateMatch({&layerStateOne, &layerStateThree})); } TEST_F(LayerStackTest, getApproximateMatch_doesNotMatchDifferentCompositionTypes) { mock::OutputLayer outputLayerOne; mock::LayerFE layerFEOne; OutputLayerCompositionState outputLayerCompositionStateOne; LayerFECompositionState layerFECompositionStateOne; layerFECompositionStateOne.compositionType = hal::Composition::DEVICE; setupMocksForLayer(outputLayerOne, layerFEOne, outputLayerCompositionStateOne, layerFECompositionStateOne); LayerState layerStateOne(&outputLayerOne); mock::OutputLayer outputLayerTwo; mock::LayerFE layerFETwo; OutputLayerCompositionState outputLayerCompositionStateTwo; LayerFECompositionState layerFECompositionStateTwo; layerFECompositionStateTwo.compositionType = hal::Composition::SOLID_COLOR; setupMocksForLayer(outputLayerTwo, layerFETwo, outputLayerCompositionStateTwo, layerFECompositionStateTwo); LayerState layerStateTwo(&outputLayerTwo); LayerStack stack({&layerStateOne}); EXPECT_FALSE(stack.getApproximateMatch({&layerStateTwo})); } TEST_F(LayerStackTest, getApproximateMatch_matchesSingleDifferenceInSingleLayer) { mock::OutputLayer outputLayerOne; mock::LayerFE layerFEOne; OutputLayerCompositionState outputLayerCompositionStateOne{ .sourceCrop = sFloatRectOne, }; LayerFECompositionState layerFECompositionStateOne; setupMocksForLayer(outputLayerOne, layerFEOne, outputLayerCompositionStateOne, layerFECompositionStateOne); LayerState layerStateOne(&outputLayerOne); mock::OutputLayer outputLayerTwo; mock::LayerFE layerFETwo; OutputLayerCompositionState outputLayerCompositionStateTwo{ .sourceCrop = sFloatRectTwo, }; LayerFECompositionState layerFECompositionStateTwo; setupMocksForLayer(outputLayerTwo, layerFETwo, outputLayerCompositionStateTwo, layerFECompositionStateTwo); LayerState layerStateTwo(&outputLayerTwo); LayerStack stack({&layerStateOne}); const auto match = stack.getApproximateMatch({&layerStateTwo}); EXPECT_TRUE(match); LayerStack::ApproximateMatch expectedMatch; expectedMatch.differingIndex = 0; expectedMatch.differingFields = LayerStateField::SourceCrop; EXPECT_EQ(expectedMatch, *match); } TEST_F(LayerStackTest, getApproximateMatch_matchesSingleDifferenceInMultiLayerStack) { mock::OutputLayer outputLayerOne; mock::LayerFE layerFEOne; OutputLayerCompositionState outputLayerCompositionStateOne{ .sourceCrop = sFloatRectOne, }; LayerFECompositionState layerFECompositionStateOne; setupMocksForLayer(outputLayerOne, layerFEOne, outputLayerCompositionStateOne, layerFECompositionStateOne); LayerState layerStateOne(&outputLayerOne); mock::OutputLayer outputLayerTwo; mock::LayerFE layerFETwo; OutputLayerCompositionState outputLayerCompositionStateTwo{ .sourceCrop = sFloatRectTwo, }; LayerFECompositionState layerFECompositionStateTwo; setupMocksForLayer(outputLayerTwo, layerFETwo, outputLayerCompositionStateTwo, layerFECompositionStateTwo); LayerState layerStateTwo(&outputLayerTwo); LayerStack stack({&layerStateOne, &layerStateOne}); const auto match = stack.getApproximateMatch({&layerStateOne, &layerStateTwo}); EXPECT_TRUE(match); LayerStack::ApproximateMatch expectedMatch; expectedMatch.differingIndex = 1; expectedMatch.differingFields = LayerStateField::SourceCrop; EXPECT_EQ(expectedMatch, *match); } TEST_F(LayerStackTest, getApproximateMatch_doesNotMatchManyDifferences) { mock::OutputLayer outputLayerOne; mock::LayerFE layerFEOne; OutputLayerCompositionState outputLayerCompositionStateOne{ .visibleRegion = sRegionOne, .displayFrame = sRectOne, .sourceCrop = sFloatRectOne, .dataspace = ui::Dataspace::SRGB, .z = sZOne, }; LayerFECompositionState layerFECompositionStateOne; layerFECompositionStateOne.alpha = sAlphaOne; layerFECompositionStateOne.colorTransformIsIdentity = true; setupMocksForLayer(outputLayerOne, layerFEOne, outputLayerCompositionStateOne, layerFECompositionStateOne); LayerState layerStateOne(&outputLayerOne); mock::OutputLayer outputLayerTwo; mock::LayerFE layerFETwo; OutputLayerCompositionState outputLayerCompositionStateTwo{ .visibleRegion = sRegionTwo, .displayFrame = sRectTwo, .sourceCrop = sFloatRectTwo, .dataspace = ui::Dataspace::DISPLAY_P3, .z = sZTwo, }; LayerFECompositionState layerFECompositionStateTwo; layerFECompositionStateTwo.alpha = sAlphaTwo; layerFECompositionStateTwo.colorTransformIsIdentity = false; layerFECompositionStateTwo.colorTransform = sMat4One; setupMocksForLayer(outputLayerTwo, layerFETwo, outputLayerCompositionStateTwo, layerFECompositionStateTwo); LayerState layerStateTwo(&outputLayerTwo); LayerStack stack({&layerStateOne}); EXPECT_FALSE(stack.getApproximateMatch({&layerStateTwo})); } TEST_F(LayerStackTest, getApproximateMatch_exactMatchesSameBuffer) { sp<GraphicBuffer> buffer = new GraphicBuffer(); mock::OutputLayer outputLayerOne; mock::LayerFE layerFEOne; OutputLayerCompositionState outputLayerCompositionStateOne; LayerFECompositionState layerFECompositionStateOne; layerFECompositionStateOne.buffer = buffer; setupMocksForLayer(outputLayerOne, layerFEOne, outputLayerCompositionStateOne, layerFECompositionStateOne); LayerState layerStateOne(&outputLayerOne); mock::OutputLayer outputLayerTwo; mock::LayerFE layerFETwo; OutputLayerCompositionState outputLayerCompositionStateTwo; LayerFECompositionState layerFECompositionStateTwo; layerFECompositionStateTwo.buffer = buffer; setupMocksForLayer(outputLayerTwo, layerFETwo, outputLayerCompositionStateTwo, layerFECompositionStateTwo); LayerState layerStateTwo(&outputLayerTwo); LayerStack stack({&layerStateOne}); const auto match = stack.getApproximateMatch({&layerStateTwo}); EXPECT_TRUE(match); LayerStack::ApproximateMatch expectedMatch; expectedMatch.differingIndex = 0; expectedMatch.differingFields = LayerStateField::None; EXPECT_EQ(expectedMatch, *match); } TEST_F(LayerStackTest, getApproximateMatch_alwaysMatchesClientComposition) { mock::OutputLayer outputLayerOne; mock::LayerFE layerFEOne; OutputLayerCompositionState outputLayerCompositionStateOne{ .visibleRegion = sRegionOne, .forceClientComposition = true, .displayFrame = sRectOne, .sourceCrop = sFloatRectOne, .dataspace = ui::Dataspace::SRGB, .z = sZOne, }; LayerFECompositionState layerFECompositionStateOne; layerFECompositionStateOne.buffer = new GraphicBuffer(); layerFECompositionStateOne.alpha = sAlphaOne; layerFECompositionStateOne.colorTransformIsIdentity = true; setupMocksForLayer(outputLayerOne, layerFEOne, outputLayerCompositionStateOne, layerFECompositionStateOne); LayerState layerStateOne(&outputLayerOne); mock::OutputLayer outputLayerTwo; mock::LayerFE layerFETwo; OutputLayerCompositionState outputLayerCompositionStateTwo{ .visibleRegion = sRegionTwo, .forceClientComposition = true, .displayFrame = sRectTwo, .sourceCrop = sFloatRectTwo, .dataspace = ui::Dataspace::DISPLAY_P3, .z = sZTwo, }; LayerFECompositionState layerFECompositionStateTwo; layerFECompositionStateTwo.buffer = new GraphicBuffer(); layerFECompositionStateTwo.alpha = sAlphaTwo; layerFECompositionStateTwo.colorTransformIsIdentity = false; layerFECompositionStateTwo.colorTransform = sMat4One; setupMocksForLayer(outputLayerTwo, layerFETwo, outputLayerCompositionStateTwo, layerFECompositionStateTwo); LayerState layerStateTwo(&outputLayerTwo); LayerStack stack({&layerStateOne}); const auto match = stack.getApproximateMatch({&layerStateTwo}); EXPECT_TRUE(match); LayerStack::ApproximateMatch expectedMatch; expectedMatch.differingIndex = 0; expectedMatch.differingFields = LayerStateField::None; EXPECT_EQ(expectedMatch, *match); } TEST_F(LayerStackTest, getApproximateMatch_doesNotMatchMultipleApproximations) { mock::OutputLayer outputLayerOne; mock::LayerFE layerFEOne; OutputLayerCompositionState outputLayerCompositionStateOne{ .sourceCrop = sFloatRectOne, }; LayerFECompositionState layerFECompositionStateOne; layerFECompositionStateOne.buffer = new GraphicBuffer(); setupMocksForLayer(outputLayerOne, layerFEOne, outputLayerCompositionStateOne, layerFECompositionStateOne); LayerState layerStateOne(&outputLayerOne); mock::OutputLayer outputLayerTwo; mock::LayerFE layerFETwo; OutputLayerCompositionState outputLayerCompositionStateTwo{ .sourceCrop = sFloatRectTwo, }; LayerFECompositionState layerFECompositionStateTwo; layerFECompositionStateTwo.buffer = new GraphicBuffer(); setupMocksForLayer(outputLayerTwo, layerFETwo, outputLayerCompositionStateTwo, layerFECompositionStateTwo); LayerState layerStateTwo(&outputLayerTwo); EXPECT_TRUE(LayerStack({&layerStateOne}).getApproximateMatch({&layerStateTwo})); LayerStack stack({&layerStateOne, &layerStateOne}); EXPECT_FALSE(stack.getApproximateMatch({&layerStateTwo, &layerStateTwo})); } } // namespace } // namespace android::compositionengine::impl::planner No newline at end of file