blob: 2060c5aaff22b083f99550d091f36e6e3d781fd6 [file] [log] [blame]
Lloyd Piquecc01a452018-12-04 17:24:00 -08001/*
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>
Lloyd Pique07e33212018-12-18 16:33:37 -080018#include <compositionengine/mock/CompositionEngine.h>
Lloyd Piquecc01a452018-12-04 17:24:00 -080019#include <compositionengine/mock/Layer.h>
20#include <compositionengine/mock/LayerFE.h>
21#include <compositionengine/mock/Output.h>
22#include <gtest/gtest.h>
23
Lloyd Pique07e33212018-12-18 16:33:37 -080024#include "MockHWC2.h"
25#include "MockHWComposer.h"
Lloyd Piquea83776c2019-01-29 18:42:32 -080026#include "RectMatcher.h"
Lloyd Pique07e33212018-12-18 16:33:37 -080027
Lloyd Piquecc01a452018-12-04 17:24:00 -080028namespace android::compositionengine {
29namespace {
30
Lloyd Piquea83776c2019-01-29 18:42:32 -080031using testing::_;
32using testing::Return;
33using testing::ReturnRef;
Lloyd Piquecc01a452018-12-04 17:24:00 -080034using testing::StrictMock;
35
Lloyd Pique07e33212018-12-18 16:33:37 -080036constexpr DisplayId DEFAULT_DISPLAY_ID = DisplayId{42};
37
Lloyd Piquea83776c2019-01-29 18:42:32 -080038constexpr auto TR_IDENT = 0u;
39constexpr auto TR_FLP_H = HAL_TRANSFORM_FLIP_H;
40constexpr auto TR_FLP_V = HAL_TRANSFORM_FLIP_V;
41constexpr auto TR_ROT_90 = HAL_TRANSFORM_ROT_90;
42constexpr auto TR_ROT_180 = TR_FLP_H | TR_FLP_V;
43constexpr auto TR_ROT_270 = TR_ROT_90 | TR_ROT_180;
44
45const std::string kOutputName{"Test Output"};
46
Lloyd Piquecc01a452018-12-04 17:24:00 -080047class OutputLayerTest : public testing::Test {
48public:
Lloyd Piquea83776c2019-01-29 18:42:32 -080049 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
Lloyd Piquecc01a452018-12-04 17:24:00 -080057 ~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};
Lloyd Piquea83776c2019-01-29 18:42:32 -080065
66 impl::LayerCompositionState mLayerState;
67 impl::OutputCompositionState mOutputState;
Lloyd Piquecc01a452018-12-04 17:24:00 -080068};
69
Lloyd Piquea83776c2019-01-29 18:42:32 -080070/*
Lloyd Piquecc01a452018-12-04 17:24:00 -080071 * Basic construction
72 */
73
74TEST_F(OutputLayerTest, canInstantiateOutputLayer) {}
75
Lloyd Piquea83776c2019-01-29 18:42:32 -080076/*
Lloyd Pique07e33212018-12-18 16:33:37 -080077 * OutputLayer::initialize()
78 */
79
80TEST_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
88TEST_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
Lloyd Piquea83776c2019-01-29 18:42:32 -080098 const auto& outputLayerState = mOutputLayer.getState();
99 ASSERT_TRUE(outputLayerState.hwc);
Lloyd Pique07e33212018-12-18 16:33:37 -0800100
Lloyd Piquea83776c2019-01-29 18:42:32 -0800101 const auto& hwcState = *outputLayerState.hwc;
Lloyd Pique07e33212018-12-18 16:33:37 -0800102 EXPECT_EQ(&hwcLayer, hwcState.hwcLayer.get());
103
104 EXPECT_CALL(hwc, destroyLayer(DEFAULT_DISPLAY_ID, &hwcLayer));
105 mOutputLayer.editState().hwc.reset();
106}
107
Lloyd Piquea83776c2019-01-29 18:42:32 -0800108/*
109 * OutputLayer::calculateOutputDisplayFrame()
110 */
111
112struct 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
136TEST_F(OutputLayerDisplayFrameTest, correctForSimpleDefaultCase) {
137 const Rect expected{0, 0, 1920, 1080};
138 EXPECT_THAT(calculateOutputDisplayFrame(), RectEq(expected));
139}
140
141TEST_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
147TEST_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
153TEST_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
160TEST_F(OutputLayerDisplayFrameTest, emptyGeomCropIsNotUsedToComputeFrame) {
161 mLayerState.frontEnd.geomCrop = Rect{};
162 const Rect expected{0, 0, 1920, 1080};
163 EXPECT_THAT(calculateOutputDisplayFrame(), RectEq(expected));
164}
165
166TEST_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
172TEST_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
178TEST_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
188TEST_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
249struct 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
293const Rect OutputLayerWriteStateToHWCTest::kDisplayFrame{1001, 1002, 1003, 10044};
294
295TEST_F(OutputLayerWriteStateToHWCTest, doesNothingIfNoHWCState) {
296 mOutputLayer.editState().hwc.reset();
297
298 mOutputLayer.writeStateToHWC(true);
299}
300
301TEST_F(OutputLayerWriteStateToHWCTest, doesNothingIfNoHWCLayer) {
302 mOutputLayer.editState().hwc = impl::OutputLayerCompositionState::Hwc(nullptr);
303
304 mOutputLayer.writeStateToHWC(true);
305}
306
307TEST_F(OutputLayerWriteStateToHWCTest, canSetsAllState) {
308 expectGeometryCommonCalls();
309
310 mOutputLayer.writeStateToHWC(true);
311}
312
Lloyd Piquecc01a452018-12-04 17:24:00 -0800313} // namespace
314} // namespace android::compositionengine