1 /* 2 * Copyright 2019 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 #include <compositionengine/impl/OutputLayer.h> 18 #include <compositionengine/mock/CompositionEngine.h> 19 #include <compositionengine/mock/Layer.h> 20 #include <compositionengine/mock/LayerFE.h> 21 #include <compositionengine/mock/Output.h> 22 #include <gtest/gtest.h> 23 24 #include "MockHWC2.h" 25 #include "MockHWComposer.h" 26 #include "RectMatcher.h" 27 28 namespace android::compositionengine { 29 namespace { 30 31 using testing::_; 32 using testing::Return; 33 using testing::ReturnRef; 34 using testing::StrictMock; 35 36 constexpr DisplayId DEFAULT_DISPLAY_ID = DisplayId{42}; 37 38 constexpr auto TR_IDENT = 0u; 39 constexpr auto TR_FLP_H = HAL_TRANSFORM_FLIP_H; 40 constexpr auto TR_FLP_V = HAL_TRANSFORM_FLIP_V; 41 constexpr auto TR_ROT_90 = HAL_TRANSFORM_ROT_90; 42 constexpr auto TR_ROT_180 = TR_FLP_H | TR_FLP_V; 43 constexpr auto TR_ROT_270 = TR_ROT_90 | TR_ROT_180; 44 45 const std::string kOutputName{"Test Output"}; 46 47 class OutputLayerTest : public testing::Test { 48 public: 49 OutputLayerTest() { 50 EXPECT_CALL(*mLayerFE, getDebugName()).WillRepeatedly(Return("Test LayerFE")); 51 EXPECT_CALL(mOutput, getName()).WillRepeatedly(ReturnRef(kOutputName)); 52 53 EXPECT_CALL(*mLayer, getState()).WillRepeatedly(ReturnRef(mLayerState)); 54 EXPECT_CALL(mOutput, getState()).WillRepeatedly(ReturnRef(mOutputState)); 55 } 56 57 ~OutputLayerTest() override = default; 58 59 compositionengine::mock::Output mOutput; 60 std::shared_ptr<compositionengine::mock::Layer> mLayer{ 61 new StrictMock<compositionengine::mock::Layer>()}; 62 sp<compositionengine::mock::LayerFE> mLayerFE{ 63 new StrictMock<compositionengine::mock::LayerFE>()}; 64 impl::OutputLayer mOutputLayer{mOutput, mLayer, mLayerFE}; 65 66 impl::LayerCompositionState mLayerState; 67 impl::OutputCompositionState mOutputState; 68 }; 69 70 /* 71 * Basic construction 72 */ 73 74 TEST_F(OutputLayerTest, canInstantiateOutputLayer) {} 75 76 /* 77 * OutputLayer::initialize() 78 */ 79 80 TEST_F(OutputLayerTest, initializingOutputLayerWithoutHwcDoesNothingInteresting) { 81 StrictMock<compositionengine::mock::CompositionEngine> compositionEngine; 82 83 mOutputLayer.initialize(compositionEngine, std::nullopt); 84 85 EXPECT_FALSE(mOutputLayer.getState().hwc); 86 } 87 88 TEST_F(OutputLayerTest, initializingOutputLayerWithHwcDisplayCreatesHwcLayer) { 89 StrictMock<compositionengine::mock::CompositionEngine> compositionEngine; 90 StrictMock<android::mock::HWComposer> hwc; 91 StrictMock<HWC2::mock::Layer> hwcLayer; 92 93 EXPECT_CALL(compositionEngine, getHwComposer()).WillOnce(ReturnRef(hwc)); 94 EXPECT_CALL(hwc, createLayer(DEFAULT_DISPLAY_ID)).WillOnce(Return(&hwcLayer)); 95 96 mOutputLayer.initialize(compositionEngine, DEFAULT_DISPLAY_ID); 97 98 const auto& outputLayerState = mOutputLayer.getState(); 99 ASSERT_TRUE(outputLayerState.hwc); 100 101 const auto& hwcState = *outputLayerState.hwc; 102 EXPECT_EQ(&hwcLayer, hwcState.hwcLayer.get()); 103 104 EXPECT_CALL(hwc, destroyLayer(DEFAULT_DISPLAY_ID, &hwcLayer)); 105 mOutputLayer.editState().hwc.reset(); 106 } 107 108 /* 109 * OutputLayer::calculateOutputDisplayFrame() 110 */ 111 112 struct OutputLayerDisplayFrameTest : public OutputLayerTest { 113 OutputLayerDisplayFrameTest() { 114 // Set reasonable default values for a simple case. Each test will 115 // set one specific value to something different. 116 117 mLayerState.frontEnd.geomActiveTransparentRegion = Region{}; 118 mLayerState.frontEnd.geomLayerTransform = ui::Transform{TR_IDENT}; 119 mLayerState.frontEnd.geomBufferSize = Rect{0, 0, 1920, 1080}; 120 mLayerState.frontEnd.geomBufferUsesDisplayInverseTransform = false; 121 mLayerState.frontEnd.geomCrop = Rect{0, 0, 1920, 1080}; 122 mLayerState.frontEnd.geomLayerBounds = FloatRect{0.f, 0.f, 1920.f, 1080.f}; 123 124 mOutputState.viewport = Rect{0, 0, 1920, 1080}; 125 mOutputState.transform = ui::Transform{TR_IDENT}; 126 } 127 128 Rect calculateOutputDisplayFrame() { 129 mLayerState.frontEnd.geomInverseLayerTransform = 130 mLayerState.frontEnd.geomLayerTransform.inverse(); 131 132 return mOutputLayer.calculateOutputDisplayFrame(); 133 } 134 }; 135 136 TEST_F(OutputLayerDisplayFrameTest, correctForSimpleDefaultCase) { 137 const Rect expected{0, 0, 1920, 1080}; 138 EXPECT_THAT(calculateOutputDisplayFrame(), RectEq(expected)); 139 } 140 141 TEST_F(OutputLayerDisplayFrameTest, fullActiveTransparentRegionReturnsEmptyFrame) { 142 mLayerState.frontEnd.geomActiveTransparentRegion = Region{Rect{0, 0, 1920, 1080}}; 143 const Rect expected{0, 0, 0, 0}; 144 EXPECT_THAT(calculateOutputDisplayFrame(), RectEq(expected)); 145 } 146 147 TEST_F(OutputLayerDisplayFrameTest, cropAffectsDisplayFrame) { 148 mLayerState.frontEnd.geomCrop = Rect{100, 200, 300, 500}; 149 const Rect expected{100, 200, 300, 500}; 150 EXPECT_THAT(calculateOutputDisplayFrame(), RectEq(expected)); 151 } 152 153 TEST_F(OutputLayerDisplayFrameTest, cropAffectsDisplayFrameRotated) { 154 mLayerState.frontEnd.geomCrop = Rect{100, 200, 300, 500}; 155 mLayerState.frontEnd.geomLayerTransform.set(HAL_TRANSFORM_ROT_90, 1920, 1080); 156 const Rect expected{1420, 100, 1720, 300}; 157 EXPECT_THAT(calculateOutputDisplayFrame(), RectEq(expected)); 158 } 159 160 TEST_F(OutputLayerDisplayFrameTest, emptyGeomCropIsNotUsedToComputeFrame) { 161 mLayerState.frontEnd.geomCrop = Rect{}; 162 const Rect expected{0, 0, 1920, 1080}; 163 EXPECT_THAT(calculateOutputDisplayFrame(), RectEq(expected)); 164 } 165 166 TEST_F(OutputLayerDisplayFrameTest, geomLayerSnapToBoundsAffectsFrame) { 167 mLayerState.frontEnd.geomLayerBounds = FloatRect{0.f, 0.f, 960.f, 540.f}; 168 const Rect expected{0, 0, 960, 540}; 169 EXPECT_THAT(calculateOutputDisplayFrame(), RectEq(expected)); 170 } 171 172 TEST_F(OutputLayerDisplayFrameTest, viewportAffectsFrame) { 173 mOutputState.viewport = Rect{0, 0, 960, 540}; 174 const Rect expected{0, 0, 960, 540}; 175 EXPECT_THAT(calculateOutputDisplayFrame(), RectEq(expected)); 176 } 177 178 TEST_F(OutputLayerDisplayFrameTest, outputTransformAffectsDisplayFrame) { 179 mOutputState.transform = ui::Transform{HAL_TRANSFORM_ROT_90}; 180 const Rect expected{-1080, 0, 0, 1920}; 181 EXPECT_THAT(calculateOutputDisplayFrame(), RectEq(expected)); 182 } 183 184 /* 185 * OutputLayer::calculateOutputRelativeBufferTransform() 186 */ 187 188 TEST_F(OutputLayerTest, calculateOutputRelativeBufferTransformTestsNeeded) { 189 mLayerState.frontEnd.geomBufferUsesDisplayInverseTransform = false; 190 191 struct Entry { 192 uint32_t layer; 193 uint32_t buffer; 194 uint32_t display; 195 uint32_t expected; 196 }; 197 // Not an exhaustive list of cases, but hopefully enough. 198 const std::array<Entry, 24> testData = { 199 // clang-format off 200 // layer buffer display expected 201 /* 0 */ Entry{TR_IDENT, TR_IDENT, TR_IDENT, TR_IDENT}, 202 /* 1 */ Entry{TR_IDENT, TR_IDENT, TR_ROT_90, TR_ROT_90}, 203 /* 2 */ Entry{TR_IDENT, TR_IDENT, TR_ROT_180, TR_ROT_180}, 204 /* 3 */ Entry{TR_IDENT, TR_IDENT, TR_ROT_270, TR_ROT_270}, 205 206 /* 4 */ Entry{TR_IDENT, TR_FLP_H, TR_IDENT, TR_FLP_H ^ TR_IDENT}, 207 /* 5 */ Entry{TR_IDENT, TR_FLP_H, TR_ROT_90, TR_FLP_H ^ TR_ROT_90}, 208 /* 6 */ Entry{TR_IDENT, TR_FLP_H, TR_ROT_180, TR_FLP_H ^ TR_ROT_180}, 209 /* 7 */ Entry{TR_IDENT, TR_FLP_H, TR_ROT_270, TR_FLP_H ^ TR_ROT_270}, 210 211 /* 8 */ Entry{TR_IDENT, TR_FLP_V, TR_IDENT, TR_FLP_V}, 212 /* 9 */ Entry{TR_IDENT, TR_ROT_90, TR_ROT_90, TR_ROT_180}, 213 /* 10 */ Entry{TR_IDENT, TR_ROT_180, TR_ROT_180, TR_IDENT}, 214 /* 11 */ Entry{TR_IDENT, TR_ROT_270, TR_ROT_270, TR_ROT_180}, 215 216 /* 12 */ Entry{TR_ROT_90, TR_IDENT, TR_IDENT, TR_IDENT ^ TR_ROT_90}, 217 /* 13 */ Entry{TR_ROT_90, TR_FLP_H, TR_ROT_90, TR_FLP_H ^ TR_ROT_180}, 218 /* 14 */ Entry{TR_ROT_90, TR_IDENT, TR_ROT_180, TR_IDENT ^ TR_ROT_270}, 219 /* 15 */ Entry{TR_ROT_90, TR_FLP_H, TR_ROT_270, TR_FLP_H ^ TR_IDENT}, 220 221 /* 16 */ Entry{TR_ROT_180, TR_FLP_H, TR_IDENT, TR_FLP_H ^ TR_ROT_180}, 222 /* 17 */ Entry{TR_ROT_180, TR_IDENT, TR_ROT_90, TR_IDENT ^ TR_ROT_270}, 223 /* 18 */ Entry{TR_ROT_180, TR_FLP_H, TR_ROT_180, TR_FLP_H ^ TR_IDENT}, 224 /* 19 */ Entry{TR_ROT_180, TR_IDENT, TR_ROT_270, TR_IDENT ^ TR_ROT_90}, 225 226 /* 20 */ Entry{TR_ROT_270, TR_IDENT, TR_IDENT, TR_IDENT ^ TR_ROT_270}, 227 /* 21 */ Entry{TR_ROT_270, TR_FLP_H, TR_ROT_90, TR_FLP_H ^ TR_IDENT}, 228 /* 22 */ Entry{TR_ROT_270, TR_FLP_H, TR_ROT_180, TR_FLP_H ^ TR_ROT_90}, 229 /* 23 */ Entry{TR_ROT_270, TR_IDENT, TR_ROT_270, TR_IDENT ^ TR_ROT_180}, 230 // clang-format on 231 }; 232 233 for (size_t i = 0; i < testData.size(); i++) { 234 const auto& entry = testData[i]; 235 236 mLayerState.frontEnd.geomLayerTransform.set(entry.layer, 1920, 1080); 237 mLayerState.frontEnd.geomBufferTransform = entry.buffer; 238 mOutputState.orientation = entry.display; 239 240 auto actual = mOutputLayer.calculateOutputRelativeBufferTransform(); 241 EXPECT_EQ(entry.expected, actual) << "entry " << i; 242 } 243 } 244 245 /* 246 * OutputLayer::writeStateToHWC() 247 */ 248 249 struct OutputLayerWriteStateToHWCTest : public OutputLayerTest { 250 static constexpr HWC2::Error kError = HWC2::Error::Unsupported; 251 static constexpr FloatRect kSourceCrop{11.f, 12.f, 13.f, 14.f}; 252 static constexpr uint32_t kZOrder = 21u; 253 static constexpr Hwc2::Transform kBufferTransform = static_cast<Hwc2::Transform>(31); 254 static constexpr Hwc2::IComposerClient::BlendMode kBlendMode = 255 static_cast<Hwc2::IComposerClient::BlendMode>(41); 256 static constexpr float kAlpha = 51.f; 257 static constexpr uint32_t kType = 61u; 258 static constexpr uint32_t kAppId = 62u; 259 260 static const Rect kDisplayFrame; 261 262 OutputLayerWriteStateToHWCTest() { 263 auto& outputLayerState = mOutputLayer.editState(); 264 outputLayerState.hwc = impl::OutputLayerCompositionState::Hwc(mHwcLayer); 265 266 outputLayerState.displayFrame = kDisplayFrame; 267 outputLayerState.sourceCrop = kSourceCrop; 268 outputLayerState.z = kZOrder; 269 outputLayerState.bufferTransform = static_cast<Hwc2::Transform>(kBufferTransform); 270 271 mLayerState.frontEnd.blendMode = kBlendMode; 272 mLayerState.frontEnd.alpha = kAlpha; 273 mLayerState.frontEnd.type = kType; 274 mLayerState.frontEnd.appId = kAppId; 275 } 276 277 void expectGeometryCommonCalls() { 278 EXPECT_CALL(*mHwcLayer, setDisplayFrame(kDisplayFrame)).WillOnce(Return(kError)); 279 EXPECT_CALL(*mHwcLayer, setSourceCrop(kSourceCrop)).WillOnce(Return(kError)); 280 EXPECT_CALL(*mHwcLayer, setZOrder(kZOrder)).WillOnce(Return(kError)); 281 EXPECT_CALL(*mHwcLayer, setTransform(static_cast<HWC2::Transform>(kBufferTransform))) 282 .WillOnce(Return(kError)); 283 284 EXPECT_CALL(*mHwcLayer, setBlendMode(static_cast<HWC2::BlendMode>(kBlendMode))) 285 .WillOnce(Return(kError)); 286 EXPECT_CALL(*mHwcLayer, setPlaneAlpha(kAlpha)).WillOnce(Return(kError)); 287 EXPECT_CALL(*mHwcLayer, setInfo(kType, kAppId)).WillOnce(Return(kError)); 288 } 289 290 std::shared_ptr<HWC2::mock::Layer> mHwcLayer{std::make_shared<StrictMock<HWC2::mock::Layer>>()}; 291 }; 292 293 const Rect OutputLayerWriteStateToHWCTest::kDisplayFrame{1001, 1002, 1003, 10044}; 294 295 TEST_F(OutputLayerWriteStateToHWCTest, doesNothingIfNoHWCState) { 296 mOutputLayer.editState().hwc.reset(); 297 298 mOutputLayer.writeStateToHWC(true); 299 } 300 301 TEST_F(OutputLayerWriteStateToHWCTest, doesNothingIfNoHWCLayer) { 302 mOutputLayer.editState().hwc = impl::OutputLayerCompositionState::Hwc(nullptr); 303 304 mOutputLayer.writeStateToHWC(true); 305 } 306 307 TEST_F(OutputLayerWriteStateToHWCTest, canSetsAllState) { 308 expectGeometryCommonCalls(); 309 310 mOutputLayer.writeStateToHWC(true); 311 } 312 313 } // namespace 314 } // namespace android::compositionengine 315