blob: 7b9528be9cfcd95a95a6e18c5d46e48869cedc22 [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 Piquef5275482019-01-29 18:42:42 -080019#include <compositionengine/mock/DisplayColorProfile.h>
Lloyd Piquecc01a452018-12-04 17:24:00 -080020#include <compositionengine/mock/Layer.h>
21#include <compositionengine/mock/LayerFE.h>
22#include <compositionengine/mock/Output.h>
23#include <gtest/gtest.h>
24
Lloyd Pique67e3d9b2019-03-22 23:09:28 +000025#include "FloatRectMatcher.h"
Lloyd Pique07e33212018-12-18 16:33:37 -080026#include "MockHWC2.h"
27#include "MockHWComposer.h"
Lloyd Piquea83776c2019-01-29 18:42:32 -080028#include "RectMatcher.h"
Lloyd Piquef5275482019-01-29 18:42:42 -080029#include "RegionMatcher.h"
Lloyd Pique07e33212018-12-18 16:33:37 -080030
Lloyd Piquecc01a452018-12-04 17:24:00 -080031namespace android::compositionengine {
32namespace {
33
Lloyd Piquea83776c2019-01-29 18:42:32 -080034using testing::_;
35using testing::Return;
36using testing::ReturnRef;
Lloyd Piquecc01a452018-12-04 17:24:00 -080037using testing::StrictMock;
38
Lloyd Pique07e33212018-12-18 16:33:37 -080039constexpr DisplayId DEFAULT_DISPLAY_ID = DisplayId{42};
40
Lloyd Piquea83776c2019-01-29 18:42:32 -080041constexpr auto TR_IDENT = 0u;
42constexpr auto TR_FLP_H = HAL_TRANSFORM_FLIP_H;
43constexpr auto TR_FLP_V = HAL_TRANSFORM_FLIP_V;
44constexpr auto TR_ROT_90 = HAL_TRANSFORM_ROT_90;
45constexpr auto TR_ROT_180 = TR_FLP_H | TR_FLP_V;
46constexpr auto TR_ROT_270 = TR_ROT_90 | TR_ROT_180;
47
48const std::string kOutputName{"Test Output"};
49
Lloyd Piquef5275482019-01-29 18:42:42 -080050MATCHER_P(ColorEq, expected, "") {
51 *result_listener << "Colors are not equal\n";
52 *result_listener << "expected " << expected.r << " " << expected.g << " " << expected.b << " "
53 << expected.a << "\n";
54 *result_listener << "actual " << arg.r << " " << arg.g << " " << arg.b << " " << arg.a << "\n";
55
56 return expected.r == arg.r && expected.g == arg.g && expected.b == arg.b && expected.a == arg.a;
57}
58
Lloyd Piquecc01a452018-12-04 17:24:00 -080059class OutputLayerTest : public testing::Test {
60public:
Lloyd Piquea83776c2019-01-29 18:42:32 -080061 OutputLayerTest() {
62 EXPECT_CALL(*mLayerFE, getDebugName()).WillRepeatedly(Return("Test LayerFE"));
63 EXPECT_CALL(mOutput, getName()).WillRepeatedly(ReturnRef(kOutputName));
64
65 EXPECT_CALL(*mLayer, getState()).WillRepeatedly(ReturnRef(mLayerState));
66 EXPECT_CALL(mOutput, getState()).WillRepeatedly(ReturnRef(mOutputState));
67 }
68
Lloyd Piquecc01a452018-12-04 17:24:00 -080069 ~OutputLayerTest() override = default;
70
71 compositionengine::mock::Output mOutput;
72 std::shared_ptr<compositionengine::mock::Layer> mLayer{
73 new StrictMock<compositionengine::mock::Layer>()};
74 sp<compositionengine::mock::LayerFE> mLayerFE{
75 new StrictMock<compositionengine::mock::LayerFE>()};
76 impl::OutputLayer mOutputLayer{mOutput, mLayer, mLayerFE};
Lloyd Piquea83776c2019-01-29 18:42:32 -080077
78 impl::LayerCompositionState mLayerState;
79 impl::OutputCompositionState mOutputState;
Lloyd Piquecc01a452018-12-04 17:24:00 -080080};
81
Lloyd Piquea83776c2019-01-29 18:42:32 -080082/*
Lloyd Piquecc01a452018-12-04 17:24:00 -080083 * Basic construction
84 */
85
86TEST_F(OutputLayerTest, canInstantiateOutputLayer) {}
87
Lloyd Piquea83776c2019-01-29 18:42:32 -080088/*
Lloyd Pique07e33212018-12-18 16:33:37 -080089 * OutputLayer::initialize()
90 */
91
92TEST_F(OutputLayerTest, initializingOutputLayerWithoutHwcDoesNothingInteresting) {
93 StrictMock<compositionengine::mock::CompositionEngine> compositionEngine;
94
95 mOutputLayer.initialize(compositionEngine, std::nullopt);
96
97 EXPECT_FALSE(mOutputLayer.getState().hwc);
98}
99
100TEST_F(OutputLayerTest, initializingOutputLayerWithHwcDisplayCreatesHwcLayer) {
101 StrictMock<compositionengine::mock::CompositionEngine> compositionEngine;
102 StrictMock<android::mock::HWComposer> hwc;
103 StrictMock<HWC2::mock::Layer> hwcLayer;
104
105 EXPECT_CALL(compositionEngine, getHwComposer()).WillOnce(ReturnRef(hwc));
106 EXPECT_CALL(hwc, createLayer(DEFAULT_DISPLAY_ID)).WillOnce(Return(&hwcLayer));
107
108 mOutputLayer.initialize(compositionEngine, DEFAULT_DISPLAY_ID);
109
Lloyd Piquea83776c2019-01-29 18:42:32 -0800110 const auto& outputLayerState = mOutputLayer.getState();
111 ASSERT_TRUE(outputLayerState.hwc);
Lloyd Pique07e33212018-12-18 16:33:37 -0800112
Lloyd Piquea83776c2019-01-29 18:42:32 -0800113 const auto& hwcState = *outputLayerState.hwc;
Lloyd Pique07e33212018-12-18 16:33:37 -0800114 EXPECT_EQ(&hwcLayer, hwcState.hwcLayer.get());
115
116 EXPECT_CALL(hwc, destroyLayer(DEFAULT_DISPLAY_ID, &hwcLayer));
117 mOutputLayer.editState().hwc.reset();
118}
119
Lloyd Piquea83776c2019-01-29 18:42:32 -0800120/*
Lloyd Pique67e3d9b2019-03-22 23:09:28 +0000121 * OutputLayer::calculateOutputSourceCrop()
122 */
123
124struct OutputLayerSourceCropTest : public OutputLayerTest {
125 OutputLayerSourceCropTest() {
126 // Set reasonable default values for a simple case. Each test will
127 // set one specific value to something different.
128 mLayerState.frontEnd.geomUsesSourceCrop = true;
129 mLayerState.frontEnd.geomContentCrop = Rect{0, 0, 1920, 1080};
130 mLayerState.frontEnd.geomActiveTransparentRegion = Region{};
131 mLayerState.frontEnd.geomLayerBounds = FloatRect{0.f, 0.f, 1920.f, 1080.f};
132 mLayerState.frontEnd.geomLayerTransform = ui::Transform{TR_IDENT};
133 mLayerState.frontEnd.geomBufferSize = Rect{0, 0, 1920, 1080};
134 mLayerState.frontEnd.geomBufferTransform = TR_IDENT;
135
136 mOutputState.viewport = Rect{0, 0, 1920, 1080};
137 }
138
139 FloatRect calculateOutputSourceCrop() {
140 mLayerState.frontEnd.geomInverseLayerTransform =
141 mLayerState.frontEnd.geomLayerTransform.inverse();
142
143 return mOutputLayer.calculateOutputSourceCrop();
144 }
145};
146
147TEST_F(OutputLayerSourceCropTest, computesEmptyIfSourceCropNotUsed) {
148 mLayerState.frontEnd.geomUsesSourceCrop = false;
149
150 const FloatRect expected{};
151 EXPECT_THAT(calculateOutputSourceCrop(), FloatRectEq(expected));
152}
153
154TEST_F(OutputLayerSourceCropTest, correctForSimpleDefaultCase) {
155 const FloatRect expected{0.f, 0.f, 1920.f, 1080.f};
156 EXPECT_THAT(calculateOutputSourceCrop(), FloatRectEq(expected));
157}
158
159TEST_F(OutputLayerSourceCropTest, handlesBoundsOutsideViewport) {
160 mLayerState.frontEnd.geomLayerBounds = FloatRect{-2000.f, -2000.f, 2000.f, 2000.f};
161
162 const FloatRect expected{0.f, 0.f, 1920.f, 1080.f};
163 EXPECT_THAT(calculateOutputSourceCrop(), FloatRectEq(expected));
164}
165
166TEST_F(OutputLayerSourceCropTest, handlesBoundsOutsideViewportRotated) {
167 mLayerState.frontEnd.geomLayerBounds = FloatRect{-2000.f, -2000.f, 2000.f, 2000.f};
168 mLayerState.frontEnd.geomLayerTransform.set(HAL_TRANSFORM_ROT_90, 1920, 1080);
169
170 const FloatRect expected{0.f, 0.f, 1080.f, 1080.f};
171 EXPECT_THAT(calculateOutputSourceCrop(), FloatRectEq(expected));
172}
173
174TEST_F(OutputLayerSourceCropTest, calculateOutputSourceCropWorksWithATransformedBuffer) {
175 struct Entry {
176 uint32_t bufferInvDisplay;
177 uint32_t buffer;
178 uint32_t display;
179 FloatRect expected;
180 };
181 // Not an exhaustive list of cases, but hopefully enough.
182 const std::array<Entry, 12> testData = {
183 // clang-format off
184 // inv buffer display expected
185 /* 0 */ Entry{false, TR_IDENT, TR_IDENT, FloatRect{0.f, 0.f, 1920.f, 1080.f}},
186 /* 1 */ Entry{false, TR_IDENT, TR_ROT_90, FloatRect{0.f, 0.f, 1920.f, 1080.f}},
187 /* 2 */ Entry{false, TR_IDENT, TR_ROT_180, FloatRect{0.f, 0.f, 1920.f, 1080.f}},
188 /* 3 */ Entry{false, TR_IDENT, TR_ROT_270, FloatRect{0.f, 0.f, 1920.f, 1080.f}},
189
190 /* 4 */ Entry{true, TR_IDENT, TR_IDENT, FloatRect{0.f, 0.f, 1920.f, 1080.f}},
191 /* 5 */ Entry{true, TR_IDENT, TR_ROT_90, FloatRect{0.f, 0.f, 1920.f, 1080.f}},
192 /* 6 */ Entry{true, TR_IDENT, TR_ROT_180, FloatRect{0.f, 0.f, 1920.f, 1080.f}},
193 /* 7 */ Entry{true, TR_IDENT, TR_ROT_270, FloatRect{0.f, 0.f, 1920.f, 1080.f}},
194
195 /* 8 */ Entry{false, TR_IDENT, TR_IDENT, FloatRect{0.f, 0.f, 1920.f, 1080.f}},
196 /* 9 */ Entry{false, TR_ROT_90, TR_ROT_90, FloatRect{0.f, 0.f, 1920.f, 1080.f}},
197 /* 10 */ Entry{false, TR_ROT_180, TR_ROT_180, FloatRect{0.f, 0.f, 1920.f, 1080.f}},
198 /* 11 */ Entry{false, TR_ROT_270, TR_ROT_270, FloatRect{0.f, 0.f, 1920.f, 1080.f}},
199
200 // clang-format on
201 };
202
203 for (size_t i = 0; i < testData.size(); i++) {
204 const auto& entry = testData[i];
205
206 mLayerState.frontEnd.geomBufferUsesDisplayInverseTransform = entry.bufferInvDisplay;
207 mLayerState.frontEnd.geomBufferTransform = entry.buffer;
208 mOutputState.orientation = entry.display;
209
210 EXPECT_THAT(calculateOutputSourceCrop(), FloatRectEq(entry.expected)) << "entry " << i;
211 }
212}
213
214TEST_F(OutputLayerSourceCropTest, geomContentCropAffectsCrop) {
215 mLayerState.frontEnd.geomContentCrop = Rect{0, 0, 960, 540};
216
217 const FloatRect expected{0.f, 0.f, 960.f, 540.f};
218 EXPECT_THAT(calculateOutputSourceCrop(), FloatRectEq(expected));
219}
220
221TEST_F(OutputLayerSourceCropTest, viewportAffectsCrop) {
222 mOutputState.viewport = Rect{0, 0, 960, 540};
223
224 const FloatRect expected{0.f, 0.f, 960.f, 540.f};
225 EXPECT_THAT(calculateOutputSourceCrop(), FloatRectEq(expected));
226}
227
228/*
Lloyd Piquea83776c2019-01-29 18:42:32 -0800229 * OutputLayer::calculateOutputDisplayFrame()
230 */
231
232struct OutputLayerDisplayFrameTest : public OutputLayerTest {
233 OutputLayerDisplayFrameTest() {
234 // Set reasonable default values for a simple case. Each test will
235 // set one specific value to something different.
236
237 mLayerState.frontEnd.geomActiveTransparentRegion = Region{};
238 mLayerState.frontEnd.geomLayerTransform = ui::Transform{TR_IDENT};
239 mLayerState.frontEnd.geomBufferSize = Rect{0, 0, 1920, 1080};
240 mLayerState.frontEnd.geomBufferUsesDisplayInverseTransform = false;
241 mLayerState.frontEnd.geomCrop = Rect{0, 0, 1920, 1080};
242 mLayerState.frontEnd.geomLayerBounds = FloatRect{0.f, 0.f, 1920.f, 1080.f};
243
244 mOutputState.viewport = Rect{0, 0, 1920, 1080};
245 mOutputState.transform = ui::Transform{TR_IDENT};
246 }
247
248 Rect calculateOutputDisplayFrame() {
249 mLayerState.frontEnd.geomInverseLayerTransform =
250 mLayerState.frontEnd.geomLayerTransform.inverse();
251
252 return mOutputLayer.calculateOutputDisplayFrame();
253 }
254};
255
256TEST_F(OutputLayerDisplayFrameTest, correctForSimpleDefaultCase) {
257 const Rect expected{0, 0, 1920, 1080};
258 EXPECT_THAT(calculateOutputDisplayFrame(), RectEq(expected));
259}
260
261TEST_F(OutputLayerDisplayFrameTest, fullActiveTransparentRegionReturnsEmptyFrame) {
262 mLayerState.frontEnd.geomActiveTransparentRegion = Region{Rect{0, 0, 1920, 1080}};
263 const Rect expected{0, 0, 0, 0};
264 EXPECT_THAT(calculateOutputDisplayFrame(), RectEq(expected));
265}
266
267TEST_F(OutputLayerDisplayFrameTest, cropAffectsDisplayFrame) {
268 mLayerState.frontEnd.geomCrop = Rect{100, 200, 300, 500};
269 const Rect expected{100, 200, 300, 500};
270 EXPECT_THAT(calculateOutputDisplayFrame(), RectEq(expected));
271}
272
273TEST_F(OutputLayerDisplayFrameTest, cropAffectsDisplayFrameRotated) {
274 mLayerState.frontEnd.geomCrop = Rect{100, 200, 300, 500};
275 mLayerState.frontEnd.geomLayerTransform.set(HAL_TRANSFORM_ROT_90, 1920, 1080);
276 const Rect expected{1420, 100, 1720, 300};
277 EXPECT_THAT(calculateOutputDisplayFrame(), RectEq(expected));
278}
279
280TEST_F(OutputLayerDisplayFrameTest, emptyGeomCropIsNotUsedToComputeFrame) {
281 mLayerState.frontEnd.geomCrop = Rect{};
282 const Rect expected{0, 0, 1920, 1080};
283 EXPECT_THAT(calculateOutputDisplayFrame(), RectEq(expected));
284}
285
Lloyd Pique67e3d9b2019-03-22 23:09:28 +0000286TEST_F(OutputLayerDisplayFrameTest, geomLayerBoundsAffectsFrame) {
Lloyd Piquea83776c2019-01-29 18:42:32 -0800287 mLayerState.frontEnd.geomLayerBounds = FloatRect{0.f, 0.f, 960.f, 540.f};
288 const Rect expected{0, 0, 960, 540};
289 EXPECT_THAT(calculateOutputDisplayFrame(), RectEq(expected));
290}
291
292TEST_F(OutputLayerDisplayFrameTest, viewportAffectsFrame) {
293 mOutputState.viewport = Rect{0, 0, 960, 540};
294 const Rect expected{0, 0, 960, 540};
295 EXPECT_THAT(calculateOutputDisplayFrame(), RectEq(expected));
296}
297
298TEST_F(OutputLayerDisplayFrameTest, outputTransformAffectsDisplayFrame) {
299 mOutputState.transform = ui::Transform{HAL_TRANSFORM_ROT_90};
300 const Rect expected{-1080, 0, 0, 1920};
301 EXPECT_THAT(calculateOutputDisplayFrame(), RectEq(expected));
302}
303
304/*
305 * OutputLayer::calculateOutputRelativeBufferTransform()
306 */
307
308TEST_F(OutputLayerTest, calculateOutputRelativeBufferTransformTestsNeeded) {
309 mLayerState.frontEnd.geomBufferUsesDisplayInverseTransform = false;
310
311 struct Entry {
312 uint32_t layer;
313 uint32_t buffer;
314 uint32_t display;
315 uint32_t expected;
316 };
317 // Not an exhaustive list of cases, but hopefully enough.
318 const std::array<Entry, 24> testData = {
319 // clang-format off
320 // layer buffer display expected
321 /* 0 */ Entry{TR_IDENT, TR_IDENT, TR_IDENT, TR_IDENT},
322 /* 1 */ Entry{TR_IDENT, TR_IDENT, TR_ROT_90, TR_ROT_90},
323 /* 2 */ Entry{TR_IDENT, TR_IDENT, TR_ROT_180, TR_ROT_180},
324 /* 3 */ Entry{TR_IDENT, TR_IDENT, TR_ROT_270, TR_ROT_270},
325
326 /* 4 */ Entry{TR_IDENT, TR_FLP_H, TR_IDENT, TR_FLP_H ^ TR_IDENT},
327 /* 5 */ Entry{TR_IDENT, TR_FLP_H, TR_ROT_90, TR_FLP_H ^ TR_ROT_90},
328 /* 6 */ Entry{TR_IDENT, TR_FLP_H, TR_ROT_180, TR_FLP_H ^ TR_ROT_180},
329 /* 7 */ Entry{TR_IDENT, TR_FLP_H, TR_ROT_270, TR_FLP_H ^ TR_ROT_270},
330
331 /* 8 */ Entry{TR_IDENT, TR_FLP_V, TR_IDENT, TR_FLP_V},
332 /* 9 */ Entry{TR_IDENT, TR_ROT_90, TR_ROT_90, TR_ROT_180},
333 /* 10 */ Entry{TR_IDENT, TR_ROT_180, TR_ROT_180, TR_IDENT},
334 /* 11 */ Entry{TR_IDENT, TR_ROT_270, TR_ROT_270, TR_ROT_180},
335
336 /* 12 */ Entry{TR_ROT_90, TR_IDENT, TR_IDENT, TR_IDENT ^ TR_ROT_90},
337 /* 13 */ Entry{TR_ROT_90, TR_FLP_H, TR_ROT_90, TR_FLP_H ^ TR_ROT_180},
338 /* 14 */ Entry{TR_ROT_90, TR_IDENT, TR_ROT_180, TR_IDENT ^ TR_ROT_270},
339 /* 15 */ Entry{TR_ROT_90, TR_FLP_H, TR_ROT_270, TR_FLP_H ^ TR_IDENT},
340
341 /* 16 */ Entry{TR_ROT_180, TR_FLP_H, TR_IDENT, TR_FLP_H ^ TR_ROT_180},
342 /* 17 */ Entry{TR_ROT_180, TR_IDENT, TR_ROT_90, TR_IDENT ^ TR_ROT_270},
343 /* 18 */ Entry{TR_ROT_180, TR_FLP_H, TR_ROT_180, TR_FLP_H ^ TR_IDENT},
344 /* 19 */ Entry{TR_ROT_180, TR_IDENT, TR_ROT_270, TR_IDENT ^ TR_ROT_90},
345
346 /* 20 */ Entry{TR_ROT_270, TR_IDENT, TR_IDENT, TR_IDENT ^ TR_ROT_270},
347 /* 21 */ Entry{TR_ROT_270, TR_FLP_H, TR_ROT_90, TR_FLP_H ^ TR_IDENT},
348 /* 22 */ Entry{TR_ROT_270, TR_FLP_H, TR_ROT_180, TR_FLP_H ^ TR_ROT_90},
349 /* 23 */ Entry{TR_ROT_270, TR_IDENT, TR_ROT_270, TR_IDENT ^ TR_ROT_180},
350 // clang-format on
351 };
352
353 for (size_t i = 0; i < testData.size(); i++) {
354 const auto& entry = testData[i];
355
356 mLayerState.frontEnd.geomLayerTransform.set(entry.layer, 1920, 1080);
357 mLayerState.frontEnd.geomBufferTransform = entry.buffer;
358 mOutputState.orientation = entry.display;
359
360 auto actual = mOutputLayer.calculateOutputRelativeBufferTransform();
361 EXPECT_EQ(entry.expected, actual) << "entry " << i;
362 }
363}
364
Lloyd Pique67e3d9b2019-03-22 23:09:28 +0000365TEST_F(OutputLayerTest,
366 calculateOutputRelativeBufferTransformTestWithOfBufferUsesDisplayInverseTransform) {
367 mLayerState.frontEnd.geomBufferUsesDisplayInverseTransform = true;
368
369 struct Entry {
370 uint32_t layer;
371 uint32_t buffer;
372 uint32_t display;
373 uint32_t expected;
374 };
375 // Not an exhaustive list of cases, but hopefully enough.
376 const std::array<Entry, 24> testData = {
377 // clang-format off
378 // layer buffer display expected
379 /* 0 */ Entry{TR_IDENT, TR_IDENT, TR_IDENT, TR_IDENT},
380 /* 1 */ Entry{TR_IDENT, TR_IDENT, TR_ROT_90, TR_IDENT},
381 /* 2 */ Entry{TR_IDENT, TR_IDENT, TR_ROT_180, TR_IDENT},
382 /* 3 */ Entry{TR_IDENT, TR_IDENT, TR_ROT_270, TR_IDENT},
383
384 /* 4 */ Entry{TR_IDENT, TR_FLP_H, TR_IDENT, TR_FLP_H},
385 /* 5 */ Entry{TR_IDENT, TR_FLP_H, TR_ROT_90, TR_FLP_H},
386 /* 6 */ Entry{TR_IDENT, TR_FLP_H, TR_ROT_180, TR_FLP_H},
387 /* 7 */ Entry{TR_IDENT, TR_FLP_H, TR_ROT_270, TR_FLP_H},
388
389 /* 8 */ Entry{TR_IDENT, TR_FLP_V, TR_IDENT, TR_FLP_V},
390 /* 9 */ Entry{TR_IDENT, TR_ROT_90, TR_ROT_90, TR_ROT_90},
391 /* 10 */ Entry{TR_IDENT, TR_ROT_180, TR_ROT_180, TR_ROT_180},
392 /* 11 */ Entry{TR_IDENT, TR_ROT_270, TR_ROT_270, TR_ROT_270},
393
394 /* 12 */ Entry{TR_ROT_90, TR_IDENT, TR_IDENT, TR_IDENT},
395 /* 13 */ Entry{TR_ROT_90, TR_FLP_H, TR_ROT_90, TR_FLP_H},
396 /* 14 */ Entry{TR_ROT_90, TR_IDENT, TR_ROT_180, TR_IDENT},
397 /* 15 */ Entry{TR_ROT_90, TR_FLP_H, TR_ROT_270, TR_FLP_H},
398
399 /* 16 */ Entry{TR_ROT_180, TR_FLP_H, TR_IDENT, TR_FLP_H},
400 /* 17 */ Entry{TR_ROT_180, TR_IDENT, TR_ROT_90, TR_IDENT},
401 /* 18 */ Entry{TR_ROT_180, TR_FLP_H, TR_ROT_180, TR_FLP_H},
402 /* 19 */ Entry{TR_ROT_180, TR_IDENT, TR_ROT_270, TR_IDENT},
403
404 /* 20 */ Entry{TR_ROT_270, TR_IDENT, TR_IDENT, TR_IDENT},
405 /* 21 */ Entry{TR_ROT_270, TR_FLP_H, TR_ROT_90, TR_FLP_H},
406 /* 22 */ Entry{TR_ROT_270, TR_FLP_H, TR_ROT_180, TR_FLP_H},
407 /* 23 */ Entry{TR_ROT_270, TR_IDENT, TR_ROT_270, TR_IDENT},
408 // clang-format on
409 };
410
411 for (size_t i = 0; i < testData.size(); i++) {
412 const auto& entry = testData[i];
413
414 mLayerState.frontEnd.geomLayerTransform = ui::Transform{entry.layer};
415 mLayerState.frontEnd.geomBufferTransform = entry.buffer;
416 mOutputState.orientation = entry.display;
417
418 auto actual = mOutputLayer.calculateOutputRelativeBufferTransform();
419 EXPECT_EQ(entry.expected, actual) << "entry " << i;
420 }
421}
422
423/*
424 * OutputLayer::updateCompositionState()
425 */
426
427struct OutputLayerPartialMockForUpdateCompositionState : public impl::OutputLayer {
428 OutputLayerPartialMockForUpdateCompositionState(const compositionengine::Output& output,
429 std::shared_ptr<compositionengine::Layer> layer,
430 sp<compositionengine::LayerFE> layerFE)
431 : impl::OutputLayer(output, layer, layerFE) {}
432 // Mock everything called by updateCompositionState to simplify testing it.
433 MOCK_CONST_METHOD0(calculateOutputSourceCrop, FloatRect());
434 MOCK_CONST_METHOD0(calculateOutputDisplayFrame, Rect());
435 MOCK_CONST_METHOD0(calculateOutputRelativeBufferTransform, uint32_t());
436};
437
438struct OutputLayerUpdateCompositionStateTest : public OutputLayerTest {
439public:
440 OutputLayerUpdateCompositionStateTest() {
441 EXPECT_CALL(*mLayer, getState()).WillRepeatedly(ReturnRef(mLayerState));
442 EXPECT_CALL(mOutput, getState()).WillRepeatedly(ReturnRef(mOutputState));
Lloyd Piquef5275482019-01-29 18:42:42 -0800443 EXPECT_CALL(mOutput, getDisplayColorProfile())
444 .WillRepeatedly(Return(&mDisplayColorProfile));
445 EXPECT_CALL(mDisplayColorProfile, isDataspaceSupported(_)).WillRepeatedly(Return(true));
Lloyd Pique67e3d9b2019-03-22 23:09:28 +0000446 }
447
448 ~OutputLayerUpdateCompositionStateTest() = default;
449
450 void setupGeometryChildCallValues() {
451 EXPECT_CALL(mOutputLayer, calculateOutputSourceCrop()).WillOnce(Return(kSourceCrop));
452 EXPECT_CALL(mOutputLayer, calculateOutputDisplayFrame()).WillOnce(Return(kDisplayFrame));
453 EXPECT_CALL(mOutputLayer, calculateOutputRelativeBufferTransform())
454 .WillOnce(Return(mBufferTransform));
455 }
456
457 void validateComputedGeometryState() {
458 const auto& state = mOutputLayer.getState();
459 EXPECT_EQ(kSourceCrop, state.sourceCrop);
460 EXPECT_EQ(kDisplayFrame, state.displayFrame);
461 EXPECT_EQ(static_cast<Hwc2::Transform>(mBufferTransform), state.bufferTransform);
462 }
463
464 const FloatRect kSourceCrop{1.f, 2.f, 3.f, 4.f};
465 const Rect kDisplayFrame{11, 12, 13, 14};
466 uint32_t mBufferTransform{21};
467
468 using OutputLayer = OutputLayerPartialMockForUpdateCompositionState;
469 StrictMock<OutputLayer> mOutputLayer{mOutput, mLayer, mLayerFE};
Lloyd Piquef5275482019-01-29 18:42:42 -0800470 StrictMock<mock::DisplayColorProfile> mDisplayColorProfile;
Lloyd Pique67e3d9b2019-03-22 23:09:28 +0000471};
472
473TEST_F(OutputLayerUpdateCompositionStateTest, setsStateNormally) {
474 mLayerState.frontEnd.isSecure = true;
475 mOutputState.isSecure = true;
476
477 setupGeometryChildCallValues();
478
479 mOutputLayer.updateCompositionState(true);
480
481 validateComputedGeometryState();
482
483 EXPECT_EQ(false, mOutputLayer.getState().forceClientComposition);
484}
485
486TEST_F(OutputLayerUpdateCompositionStateTest,
487 alsoSetsForceCompositionIfSecureLayerOnNonsecureOutput) {
488 mLayerState.frontEnd.isSecure = true;
489 mOutputState.isSecure = false;
490
491 setupGeometryChildCallValues();
492
493 mOutputLayer.updateCompositionState(true);
494
495 validateComputedGeometryState();
496
497 EXPECT_EQ(true, mOutputLayer.getState().forceClientComposition);
498}
499
500TEST_F(OutputLayerUpdateCompositionStateTest,
501 alsoSetsForceCompositionIfUnsupportedBufferTransform) {
502 mLayerState.frontEnd.isSecure = true;
503 mOutputState.isSecure = true;
504
505 mBufferTransform = ui::Transform::ROT_INVALID;
506
507 setupGeometryChildCallValues();
508
509 mOutputLayer.updateCompositionState(true);
510
511 validateComputedGeometryState();
512
513 EXPECT_EQ(true, mOutputLayer.getState().forceClientComposition);
514}
515
Lloyd Piquef5275482019-01-29 18:42:42 -0800516TEST_F(OutputLayerUpdateCompositionStateTest, setsOutputLayerColorspaceCorrectly) {
517 mLayerState.frontEnd.dataspace = ui::Dataspace::DISPLAY_P3;
518 mOutputState.targetDataspace = ui::Dataspace::V0_SCRGB;
519
520 // If the layer is not colorspace agnostic, the output layer dataspace
521 // should use the layers requested colorspace.
522 mLayerState.frontEnd.isColorspaceAgnostic = false;
523
524 mOutputLayer.updateCompositionState(false);
525
526 EXPECT_EQ(ui::Dataspace::DISPLAY_P3, mOutputLayer.getState().dataspace);
527
528 // If the layer is colorspace agnostic, the output layer dataspace
529 // should use the colorspace chosen for the whole output.
530 mLayerState.frontEnd.isColorspaceAgnostic = true;
531
532 mOutputLayer.updateCompositionState(false);
533
534 EXPECT_EQ(ui::Dataspace::V0_SCRGB, mOutputLayer.getState().dataspace);
535}
536
Lloyd Pique67e3d9b2019-03-22 23:09:28 +0000537TEST_F(OutputLayerUpdateCompositionStateTest, doesNotRecomputeGeometryIfNotRequested) {
538 mOutputLayer.updateCompositionState(false);
539
540 EXPECT_EQ(false, mOutputLayer.getState().forceClientComposition);
541}
542
Lloyd Piquef5275482019-01-29 18:42:42 -0800543TEST_F(OutputLayerUpdateCompositionStateTest, clientCompositionForcedFromFrontEndFlagAtAnyTime) {
544 mLayerState.frontEnd.forceClientComposition = true;
545
546 mOutputLayer.updateCompositionState(false);
547
548 EXPECT_EQ(true, mOutputLayer.getState().forceClientComposition);
549}
550
551TEST_F(OutputLayerUpdateCompositionStateTest,
552 clientCompositionForcedFromUnsupportedDataspaceAtAnyTime) {
553 EXPECT_CALL(mDisplayColorProfile, isDataspaceSupported(_)).WillRepeatedly(Return(false));
554
555 mOutputLayer.updateCompositionState(false);
556
557 EXPECT_EQ(true, mOutputLayer.getState().forceClientComposition);
558}
559
Lloyd Piquea83776c2019-01-29 18:42:32 -0800560/*
561 * OutputLayer::writeStateToHWC()
562 */
563
564struct OutputLayerWriteStateToHWCTest : public OutputLayerTest {
565 static constexpr HWC2::Error kError = HWC2::Error::Unsupported;
566 static constexpr FloatRect kSourceCrop{11.f, 12.f, 13.f, 14.f};
567 static constexpr uint32_t kZOrder = 21u;
568 static constexpr Hwc2::Transform kBufferTransform = static_cast<Hwc2::Transform>(31);
569 static constexpr Hwc2::IComposerClient::BlendMode kBlendMode =
570 static_cast<Hwc2::IComposerClient::BlendMode>(41);
571 static constexpr float kAlpha = 51.f;
572 static constexpr uint32_t kType = 61u;
573 static constexpr uint32_t kAppId = 62u;
Lloyd Piquef5275482019-01-29 18:42:42 -0800574 static constexpr ui::Dataspace kDataspace = static_cast<ui::Dataspace>(71);
575 static constexpr int kSupportedPerFrameMetadata = 101;
576 static constexpr int kExpectedHwcSlot = 0;
Lloyd Piquea83776c2019-01-29 18:42:32 -0800577
Lloyd Piquef5275482019-01-29 18:42:42 -0800578 static const half4 kColor;
Lloyd Piquea83776c2019-01-29 18:42:32 -0800579 static const Rect kDisplayFrame;
Lloyd Piquef5275482019-01-29 18:42:42 -0800580 static const Region kVisibleRegion;
581 static const mat4 kColorTransform;
582 static const Region kSurfaceDamage;
583 static const HdrMetadata kHdrMetadata;
584 static native_handle_t* kSidebandStreamHandle;
585 static const sp<GraphicBuffer> kBuffer;
586 static const sp<Fence> kFence;
Lloyd Piquea83776c2019-01-29 18:42:32 -0800587
588 OutputLayerWriteStateToHWCTest() {
589 auto& outputLayerState = mOutputLayer.editState();
590 outputLayerState.hwc = impl::OutputLayerCompositionState::Hwc(mHwcLayer);
591
592 outputLayerState.displayFrame = kDisplayFrame;
593 outputLayerState.sourceCrop = kSourceCrop;
594 outputLayerState.z = kZOrder;
595 outputLayerState.bufferTransform = static_cast<Hwc2::Transform>(kBufferTransform);
Lloyd Piquef5275482019-01-29 18:42:42 -0800596 outputLayerState.visibleRegion = kVisibleRegion;
597 outputLayerState.dataspace = kDataspace;
Lloyd Piquea83776c2019-01-29 18:42:32 -0800598
599 mLayerState.frontEnd.blendMode = kBlendMode;
600 mLayerState.frontEnd.alpha = kAlpha;
601 mLayerState.frontEnd.type = kType;
602 mLayerState.frontEnd.appId = kAppId;
Lloyd Piquef5275482019-01-29 18:42:42 -0800603 mLayerState.frontEnd.colorTransform = kColorTransform;
604 mLayerState.frontEnd.color = kColor;
605 mLayerState.frontEnd.surfaceDamage = kSurfaceDamage;
606 mLayerState.frontEnd.hdrMetadata = kHdrMetadata;
607 mLayerState.frontEnd.sidebandStream = NativeHandle::create(kSidebandStreamHandle, false);
608 mLayerState.frontEnd.buffer = kBuffer;
609 mLayerState.frontEnd.bufferSlot = BufferQueue::INVALID_BUFFER_SLOT;
610 mLayerState.frontEnd.acquireFence = kFence;
611
612 EXPECT_CALL(mOutput, getDisplayColorProfile())
613 .WillRepeatedly(Return(&mDisplayColorProfile));
614 EXPECT_CALL(mDisplayColorProfile, getSupportedPerFrameMetadata())
615 .WillRepeatedly(Return(kSupportedPerFrameMetadata));
Lloyd Piquea83776c2019-01-29 18:42:32 -0800616 }
617
Lloyd Piquef5275482019-01-29 18:42:42 -0800618 // Some tests may need to simulate unsupported HWC calls
619 enum class SimulateUnsupported { None, ColorTransform };
620
Lloyd Piquea83776c2019-01-29 18:42:32 -0800621 void expectGeometryCommonCalls() {
622 EXPECT_CALL(*mHwcLayer, setDisplayFrame(kDisplayFrame)).WillOnce(Return(kError));
623 EXPECT_CALL(*mHwcLayer, setSourceCrop(kSourceCrop)).WillOnce(Return(kError));
624 EXPECT_CALL(*mHwcLayer, setZOrder(kZOrder)).WillOnce(Return(kError));
625 EXPECT_CALL(*mHwcLayer, setTransform(static_cast<HWC2::Transform>(kBufferTransform)))
626 .WillOnce(Return(kError));
627
628 EXPECT_CALL(*mHwcLayer, setBlendMode(static_cast<HWC2::BlendMode>(kBlendMode)))
629 .WillOnce(Return(kError));
630 EXPECT_CALL(*mHwcLayer, setPlaneAlpha(kAlpha)).WillOnce(Return(kError));
631 EXPECT_CALL(*mHwcLayer, setInfo(kType, kAppId)).WillOnce(Return(kError));
632 }
633
Lloyd Piquef5275482019-01-29 18:42:42 -0800634 void expectPerFrameCommonCalls(SimulateUnsupported unsupported = SimulateUnsupported::None) {
635 EXPECT_CALL(*mHwcLayer, setVisibleRegion(RegionEq(kVisibleRegion)))
636 .WillOnce(Return(kError));
637 EXPECT_CALL(*mHwcLayer, setDataspace(kDataspace)).WillOnce(Return(kError));
638 EXPECT_CALL(*mHwcLayer, setColorTransform(kColorTransform))
639 .WillOnce(Return(unsupported == SimulateUnsupported::ColorTransform
640 ? HWC2::Error::Unsupported
641 : HWC2::Error::None));
642 EXPECT_CALL(*mHwcLayer, setSurfaceDamage(RegionEq(kSurfaceDamage)))
643 .WillOnce(Return(kError));
644 }
645
646 void expectSetCompositionTypeCall(Hwc2::IComposerClient::Composition compositionType) {
647 EXPECT_CALL(*mHwcLayer, setCompositionType(static_cast<HWC2::Composition>(compositionType)))
648 .WillOnce(Return(kError));
649 }
650
651 void expectNoSetCompositionTypeCall() {
652 EXPECT_CALL(*mHwcLayer, setCompositionType(_)).Times(0);
653 }
654
655 void expectSetColorCall() {
656 hwc_color_t color = {static_cast<uint8_t>(std::round(kColor.r * 255)),
657 static_cast<uint8_t>(std::round(kColor.g * 255)),
658 static_cast<uint8_t>(std::round(kColor.b * 255)), 255};
659
660 EXPECT_CALL(*mHwcLayer, setColor(ColorEq(color))).WillOnce(Return(kError));
661 }
662
663 void expectSetSidebandHandleCall() {
664 EXPECT_CALL(*mHwcLayer, setSidebandStream(kSidebandStreamHandle));
665 }
666
667 void expectSetHdrMetadataAndBufferCalls() {
668 EXPECT_CALL(*mHwcLayer, setPerFrameMetadata(kSupportedPerFrameMetadata, kHdrMetadata));
669 EXPECT_CALL(*mHwcLayer, setBuffer(kExpectedHwcSlot, kBuffer, kFence));
670 }
671
Lloyd Piquea83776c2019-01-29 18:42:32 -0800672 std::shared_ptr<HWC2::mock::Layer> mHwcLayer{std::make_shared<StrictMock<HWC2::mock::Layer>>()};
Lloyd Piquef5275482019-01-29 18:42:42 -0800673 StrictMock<mock::DisplayColorProfile> mDisplayColorProfile;
Lloyd Piquea83776c2019-01-29 18:42:32 -0800674};
675
Lloyd Piquef5275482019-01-29 18:42:42 -0800676const half4 OutputLayerWriteStateToHWCTest::kColor{81.f / 255.f, 82.f / 255.f, 83.f / 255.f,
677 84.f / 255.f};
Lloyd Piquea83776c2019-01-29 18:42:32 -0800678const Rect OutputLayerWriteStateToHWCTest::kDisplayFrame{1001, 1002, 1003, 10044};
Lloyd Piquef5275482019-01-29 18:42:42 -0800679const Region OutputLayerWriteStateToHWCTest::kVisibleRegion{Rect{1005, 1006, 1007, 1008}};
680const mat4 OutputLayerWriteStateToHWCTest::kColorTransform{
681 1009, 1010, 1011, 1012, 1013, 1014, 1015, 1016,
682 1017, 1018, 1019, 1020, 1021, 1022, 1023, 1024,
683};
684const Region OutputLayerWriteStateToHWCTest::kSurfaceDamage{Rect{1025, 1026, 1027, 1028}};
685const HdrMetadata OutputLayerWriteStateToHWCTest::kHdrMetadata{{/* LightFlattenable */}, 1029};
686native_handle_t* OutputLayerWriteStateToHWCTest::kSidebandStreamHandle =
687 reinterpret_cast<native_handle_t*>(1031);
688const sp<GraphicBuffer> OutputLayerWriteStateToHWCTest::kBuffer;
689const sp<Fence> OutputLayerWriteStateToHWCTest::kFence;
Lloyd Piquea83776c2019-01-29 18:42:32 -0800690
691TEST_F(OutputLayerWriteStateToHWCTest, doesNothingIfNoHWCState) {
692 mOutputLayer.editState().hwc.reset();
693
694 mOutputLayer.writeStateToHWC(true);
695}
696
697TEST_F(OutputLayerWriteStateToHWCTest, doesNothingIfNoHWCLayer) {
698 mOutputLayer.editState().hwc = impl::OutputLayerCompositionState::Hwc(nullptr);
699
700 mOutputLayer.writeStateToHWC(true);
701}
702
Lloyd Piquef5275482019-01-29 18:42:42 -0800703TEST_F(OutputLayerWriteStateToHWCTest, canSetAllState) {
Lloyd Piquea83776c2019-01-29 18:42:32 -0800704 expectGeometryCommonCalls();
Lloyd Piquef5275482019-01-29 18:42:42 -0800705 expectPerFrameCommonCalls();
706
707 expectNoSetCompositionTypeCall();
Lloyd Piquea83776c2019-01-29 18:42:32 -0800708
709 mOutputLayer.writeStateToHWC(true);
710}
711
Lloyd Piquef5275482019-01-29 18:42:42 -0800712TEST_F(OutputLayerWriteStateToHWCTest, canSetPerFrameStateForSolidColor) {
713 mLayerState.frontEnd.compositionType = Hwc2::IComposerClient::Composition::SOLID_COLOR;
714
715 expectPerFrameCommonCalls();
716 expectSetColorCall();
717 expectSetCompositionTypeCall(Hwc2::IComposerClient::Composition::SOLID_COLOR);
718
719 mOutputLayer.writeStateToHWC(false);
720}
721
722TEST_F(OutputLayerWriteStateToHWCTest, canSetPerFrameStateForSideband) {
723 mLayerState.frontEnd.compositionType = Hwc2::IComposerClient::Composition::SIDEBAND;
724
725 expectPerFrameCommonCalls();
726 expectSetSidebandHandleCall();
727 expectSetCompositionTypeCall(Hwc2::IComposerClient::Composition::SIDEBAND);
728
729 mOutputLayer.writeStateToHWC(false);
730}
731
732TEST_F(OutputLayerWriteStateToHWCTest, canSetPerFrameStateForCursor) {
733 mLayerState.frontEnd.compositionType = Hwc2::IComposerClient::Composition::CURSOR;
734
735 expectPerFrameCommonCalls();
736 expectSetHdrMetadataAndBufferCalls();
737 expectSetCompositionTypeCall(Hwc2::IComposerClient::Composition::CURSOR);
738
739 mOutputLayer.writeStateToHWC(false);
740}
741
742TEST_F(OutputLayerWriteStateToHWCTest, canSetPerFrameStateForDevice) {
743 mLayerState.frontEnd.compositionType = Hwc2::IComposerClient::Composition::DEVICE;
744
745 expectPerFrameCommonCalls();
746 expectSetHdrMetadataAndBufferCalls();
747 expectSetCompositionTypeCall(Hwc2::IComposerClient::Composition::DEVICE);
748
749 mOutputLayer.writeStateToHWC(false);
750}
751
752TEST_F(OutputLayerWriteStateToHWCTest, compositionTypeIsNotSetIfUnchanged) {
753 (*mOutputLayer.editState().hwc).hwcCompositionType =
754 Hwc2::IComposerClient::Composition::SOLID_COLOR;
755
756 mLayerState.frontEnd.compositionType = Hwc2::IComposerClient::Composition::SOLID_COLOR;
757
758 expectPerFrameCommonCalls();
759 expectSetColorCall();
760 expectNoSetCompositionTypeCall();
761
762 mOutputLayer.writeStateToHWC(false);
763}
764
765TEST_F(OutputLayerWriteStateToHWCTest, compositionTypeIsSetToClientIfColorTransformNotSupported) {
766 mLayerState.frontEnd.compositionType = Hwc2::IComposerClient::Composition::SOLID_COLOR;
767
768 expectPerFrameCommonCalls(SimulateUnsupported::ColorTransform);
769 expectSetColorCall();
770 expectSetCompositionTypeCall(Hwc2::IComposerClient::Composition::CLIENT);
771
772 mOutputLayer.writeStateToHWC(false);
773}
774
775TEST_F(OutputLayerWriteStateToHWCTest, compositionTypeIsSetToClientIfClientCompositionForced) {
776 mOutputLayer.editState().forceClientComposition = true;
777
778 mLayerState.frontEnd.compositionType = Hwc2::IComposerClient::Composition::SOLID_COLOR;
779
780 expectPerFrameCommonCalls();
781 expectSetColorCall();
782 expectSetCompositionTypeCall(Hwc2::IComposerClient::Composition::CLIENT);
783
784 mOutputLayer.writeStateToHWC(false);
785}
786
Lloyd Piquecc01a452018-12-04 17:24:00 -0800787} // namespace
788} // namespace android::compositionengine