blob: 635d77be8aac62293ca5997efe09d3e8e6ce7793 [file] [log] [blame]
Lloyd Pique32cbe282018-10-19 13:09:22 -07001/*
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 <cmath>
18
Lloyd Pique9755fb72019-03-26 14:44:40 -070019#include <compositionengine/LayerFECompositionState.h>
Lloyd Pique32cbe282018-10-19 13:09:22 -070020#include <compositionengine/impl/Output.h>
Lloyd Pique66d68602019-02-13 14:23:31 -080021#include <compositionengine/impl/OutputCompositionState.h>
Lloyd Pique56eba802019-08-28 15:45:25 -070022#include <compositionengine/impl/OutputLayerCompositionState.h>
Lloyd Pique32cbe282018-10-19 13:09:22 -070023#include <compositionengine/mock/CompositionEngine.h>
Lloyd Pique3d0c02e2018-10-19 18:38:12 -070024#include <compositionengine/mock/DisplayColorProfile.h>
Lloyd Piquecc01a452018-12-04 17:24:00 -080025#include <compositionengine/mock/Layer.h>
26#include <compositionengine/mock/LayerFE.h>
27#include <compositionengine/mock/OutputLayer.h>
Lloyd Pique31cb2942018-10-19 17:23:03 -070028#include <compositionengine/mock/RenderSurface.h>
Lloyd Pique32cbe282018-10-19 13:09:22 -070029#include <gtest/gtest.h>
Lloyd Pique56eba802019-08-28 15:45:25 -070030#include <renderengine/mock/RenderEngine.h>
Lloyd Pique32cbe282018-10-19 13:09:22 -070031#include <ui/Rect.h>
32#include <ui/Region.h>
33
34#include "RegionMatcher.h"
35#include "TransformMatcher.h"
36
37namespace android::compositionengine {
38namespace {
39
Lloyd Pique56eba802019-08-28 15:45:25 -070040using testing::_;
Lloyd Pique31cb2942018-10-19 17:23:03 -070041using testing::Return;
Lloyd Pique32cbe282018-10-19 13:09:22 -070042using testing::ReturnRef;
43using testing::StrictMock;
44
Lloyd Pique56eba802019-08-28 15:45:25 -070045constexpr auto TR_IDENT = 0u;
46constexpr auto TR_ROT_90 = HAL_TRANSFORM_ROT_90;
47
Lloyd Pique3eb1b212019-03-07 21:15:40 -080048const mat4 kIdentity;
49const mat4 kNonIdentityHalf = mat4() * 0.5;
50const mat4 kNonIdentityQuarter = mat4() * 0.25;
51
Lloyd Pique66d68602019-02-13 14:23:31 -080052struct OutputTest : public testing::Test {
Lloyd Pique31cb2942018-10-19 17:23:03 -070053 OutputTest() {
Lloyd Piquea38ea7e2019-04-16 18:10:26 -070054 mOutput->setDisplayColorProfileForTest(
Lloyd Pique3d0c02e2018-10-19 18:38:12 -070055 std::unique_ptr<DisplayColorProfile>(mDisplayColorProfile));
Lloyd Piquea38ea7e2019-04-16 18:10:26 -070056 mOutput->setRenderSurfaceForTest(std::unique_ptr<RenderSurface>(mRenderSurface));
Lloyd Piqueef958122019-02-05 18:00:12 -080057
Lloyd Piquea38ea7e2019-04-16 18:10:26 -070058 mOutput->editState().bounds = kDefaultDisplaySize;
Lloyd Pique31cb2942018-10-19 17:23:03 -070059 }
Lloyd Pique32cbe282018-10-19 13:09:22 -070060
Lloyd Piqueef958122019-02-05 18:00:12 -080061 static const Rect kDefaultDisplaySize;
62
Lloyd Pique32cbe282018-10-19 13:09:22 -070063 StrictMock<mock::CompositionEngine> mCompositionEngine;
Lloyd Pique3d0c02e2018-10-19 18:38:12 -070064 mock::DisplayColorProfile* mDisplayColorProfile = new StrictMock<mock::DisplayColorProfile>();
Lloyd Pique31cb2942018-10-19 17:23:03 -070065 mock::RenderSurface* mRenderSurface = new StrictMock<mock::RenderSurface>();
Lloyd Piquea38ea7e2019-04-16 18:10:26 -070066 std::shared_ptr<impl::Output> mOutput = impl::createOutput(mCompositionEngine);
Lloyd Pique32cbe282018-10-19 13:09:22 -070067};
68
Lloyd Piqueef958122019-02-05 18:00:12 -080069const Rect OutputTest::kDefaultDisplaySize{100, 200};
70
Lloyd Pique66d68602019-02-13 14:23:31 -080071/*
Lloyd Pique32cbe282018-10-19 13:09:22 -070072 * Basic construction
73 */
74
Lloyd Pique31cb2942018-10-19 17:23:03 -070075TEST_F(OutputTest, canInstantiateOutput) {
76 // The validation check checks each required component.
Lloyd Pique3d0c02e2018-10-19 18:38:12 -070077 EXPECT_CALL(*mDisplayColorProfile, isValid()).WillOnce(Return(true));
Lloyd Pique31cb2942018-10-19 17:23:03 -070078 EXPECT_CALL(*mRenderSurface, isValid()).WillOnce(Return(true));
79
Lloyd Piquea38ea7e2019-04-16 18:10:26 -070080 EXPECT_TRUE(mOutput->isValid());
Lloyd Pique31cb2942018-10-19 17:23:03 -070081
82 // If we take away the required components, it is no longer valid.
Lloyd Piquea38ea7e2019-04-16 18:10:26 -070083 mOutput->setRenderSurfaceForTest(std::unique_ptr<RenderSurface>());
Lloyd Pique31cb2942018-10-19 17:23:03 -070084
Lloyd Pique3d0c02e2018-10-19 18:38:12 -070085 EXPECT_CALL(*mDisplayColorProfile, isValid()).WillOnce(Return(true));
86
Lloyd Piquea38ea7e2019-04-16 18:10:26 -070087 EXPECT_FALSE(mOutput->isValid());
Lloyd Pique31cb2942018-10-19 17:23:03 -070088}
Lloyd Pique32cbe282018-10-19 13:09:22 -070089
Lloyd Pique66d68602019-02-13 14:23:31 -080090/*
Lloyd Pique32cbe282018-10-19 13:09:22 -070091 * Output::setCompositionEnabled()
92 */
93
94TEST_F(OutputTest, setCompositionEnabledDoesNothingIfAlreadyEnabled) {
Lloyd Piquea38ea7e2019-04-16 18:10:26 -070095 mOutput->editState().isEnabled = true;
Lloyd Pique32cbe282018-10-19 13:09:22 -070096
Lloyd Piquea38ea7e2019-04-16 18:10:26 -070097 mOutput->setCompositionEnabled(true);
Lloyd Pique32cbe282018-10-19 13:09:22 -070098
Lloyd Piquea38ea7e2019-04-16 18:10:26 -070099 EXPECT_TRUE(mOutput->getState().isEnabled);
100 EXPECT_THAT(mOutput->getState().dirtyRegion, RegionEq(Region()));
Lloyd Pique32cbe282018-10-19 13:09:22 -0700101}
102
103TEST_F(OutputTest, setCompositionEnabledSetsEnabledAndDirtiesEntireOutput) {
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700104 mOutput->editState().isEnabled = false;
Lloyd Pique32cbe282018-10-19 13:09:22 -0700105
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700106 mOutput->setCompositionEnabled(true);
Lloyd Pique32cbe282018-10-19 13:09:22 -0700107
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700108 EXPECT_TRUE(mOutput->getState().isEnabled);
109 EXPECT_THAT(mOutput->getState().dirtyRegion, RegionEq(Region(kDefaultDisplaySize)));
Lloyd Pique32cbe282018-10-19 13:09:22 -0700110}
111
112TEST_F(OutputTest, setCompositionEnabledSetsDisabledAndDirtiesEntireOutput) {
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700113 mOutput->editState().isEnabled = true;
Lloyd Pique32cbe282018-10-19 13:09:22 -0700114
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700115 mOutput->setCompositionEnabled(false);
Lloyd Pique32cbe282018-10-19 13:09:22 -0700116
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700117 EXPECT_FALSE(mOutput->getState().isEnabled);
118 EXPECT_THAT(mOutput->getState().dirtyRegion, RegionEq(Region(kDefaultDisplaySize)));
Lloyd Pique32cbe282018-10-19 13:09:22 -0700119}
120
Lloyd Pique66d68602019-02-13 14:23:31 -0800121/*
Lloyd Pique32cbe282018-10-19 13:09:22 -0700122 * Output::setProjection()
123 */
124
125TEST_F(OutputTest, setProjectionTriviallyWorks) {
126 const ui::Transform transform{ui::Transform::ROT_180};
127 const int32_t orientation = 123;
128 const Rect frame{1, 2, 3, 4};
129 const Rect viewport{5, 6, 7, 8};
130 const Rect scissor{9, 10, 11, 12};
131 const bool needsFiltering = true;
132
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700133 mOutput->setProjection(transform, orientation, frame, viewport, scissor, needsFiltering);
Lloyd Pique32cbe282018-10-19 13:09:22 -0700134
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700135 EXPECT_THAT(mOutput->getState().transform, TransformEq(transform));
136 EXPECT_EQ(orientation, mOutput->getState().orientation);
137 EXPECT_EQ(frame, mOutput->getState().frame);
138 EXPECT_EQ(viewport, mOutput->getState().viewport);
139 EXPECT_EQ(scissor, mOutput->getState().scissor);
140 EXPECT_EQ(needsFiltering, mOutput->getState().needsFiltering);
Lloyd Pique32cbe282018-10-19 13:09:22 -0700141}
142
Lloyd Pique66d68602019-02-13 14:23:31 -0800143/*
Lloyd Pique32cbe282018-10-19 13:09:22 -0700144 * Output::setBounds()
145 */
146
147TEST_F(OutputTest, setBoundsSetsSizeAndDirtiesEntireOutput) {
Lloyd Piqueef958122019-02-05 18:00:12 -0800148 const ui::Size displaySize{200, 400};
Lloyd Pique31cb2942018-10-19 17:23:03 -0700149
150 EXPECT_CALL(*mRenderSurface, setDisplaySize(displaySize)).Times(1);
151 EXPECT_CALL(*mRenderSurface, getSize()).WillOnce(ReturnRef(displaySize));
152
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700153 mOutput->setBounds(displaySize);
Lloyd Pique32cbe282018-10-19 13:09:22 -0700154
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700155 EXPECT_EQ(Rect(displaySize), mOutput->getState().bounds);
Lloyd Pique32cbe282018-10-19 13:09:22 -0700156
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700157 EXPECT_THAT(mOutput->getState().dirtyRegion, RegionEq(Region(Rect(displaySize))));
Lloyd Pique32cbe282018-10-19 13:09:22 -0700158}
159
Lloyd Pique66d68602019-02-13 14:23:31 -0800160/*
Lloyd Pique32cbe282018-10-19 13:09:22 -0700161 * Output::setLayerStackFilter()
162 */
163
164TEST_F(OutputTest, setLayerStackFilterSetsFilterAndDirtiesEntireOutput) {
Lloyd Pique32cbe282018-10-19 13:09:22 -0700165 const uint32_t layerStack = 123u;
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700166 mOutput->setLayerStackFilter(layerStack, true);
Lloyd Pique32cbe282018-10-19 13:09:22 -0700167
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700168 EXPECT_TRUE(mOutput->getState().layerStackInternal);
169 EXPECT_EQ(layerStack, mOutput->getState().layerStackId);
Lloyd Pique32cbe282018-10-19 13:09:22 -0700170
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700171 EXPECT_THAT(mOutput->getState().dirtyRegion, RegionEq(Region(kDefaultDisplaySize)));
Lloyd Pique32cbe282018-10-19 13:09:22 -0700172}
173
Lloyd Pique66d68602019-02-13 14:23:31 -0800174/*
Lloyd Pique32cbe282018-10-19 13:09:22 -0700175 * Output::setColorTransform
176 */
177
Lloyd Pique3eb1b212019-03-07 21:15:40 -0800178TEST_F(OutputTest, setColorTransformWithNoChangeFlaggedSkipsUpdates) {
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700179 mOutput->editState().colorTransformMatrix = kIdentity;
Lloyd Pique32cbe282018-10-19 13:09:22 -0700180
Lloyd Pique3eb1b212019-03-07 21:15:40 -0800181 // If no colorTransformMatrix is set the update should be skipped.
182 CompositionRefreshArgs refreshArgs;
183 refreshArgs.colorTransformMatrix = std::nullopt;
Lloyd Pique32cbe282018-10-19 13:09:22 -0700184
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700185 mOutput->setColorTransform(refreshArgs);
Lloyd Pique32cbe282018-10-19 13:09:22 -0700186
Lloyd Pique3eb1b212019-03-07 21:15:40 -0800187 // The internal state should be unchanged
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700188 EXPECT_EQ(kIdentity, mOutput->getState().colorTransformMatrix);
Lloyd Pique3eb1b212019-03-07 21:15:40 -0800189
190 // No dirty region should be set
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700191 EXPECT_THAT(mOutput->getState().dirtyRegion, RegionEq(Region()));
Lloyd Pique3eb1b212019-03-07 21:15:40 -0800192}
Lloyd Piqueef958122019-02-05 18:00:12 -0800193
Lloyd Pique3eb1b212019-03-07 21:15:40 -0800194TEST_F(OutputTest, setColorTransformWithNoActualChangeSkipsUpdates) {
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700195 mOutput->editState().colorTransformMatrix = kIdentity;
Lloyd Pique32cbe282018-10-19 13:09:22 -0700196
Lloyd Pique3eb1b212019-03-07 21:15:40 -0800197 // Attempting to set the same colorTransformMatrix that is already set should
198 // also skip the update.
199 CompositionRefreshArgs refreshArgs;
200 refreshArgs.colorTransformMatrix = kIdentity;
Lloyd Pique32cbe282018-10-19 13:09:22 -0700201
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700202 mOutput->setColorTransform(refreshArgs);
Lloyd Pique77f79a22019-04-29 15:55:40 -0700203
Lloyd Pique3eb1b212019-03-07 21:15:40 -0800204 // The internal state should be unchanged
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700205 EXPECT_EQ(kIdentity, mOutput->getState().colorTransformMatrix);
Lloyd Pique3eb1b212019-03-07 21:15:40 -0800206
207 // No dirty region should be set
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700208 EXPECT_THAT(mOutput->getState().dirtyRegion, RegionEq(Region()));
Lloyd Pique3eb1b212019-03-07 21:15:40 -0800209}
210
211TEST_F(OutputTest, setColorTransformPerformsUpdateToIdentity) {
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700212 mOutput->editState().colorTransformMatrix = kNonIdentityHalf;
Lloyd Pique3eb1b212019-03-07 21:15:40 -0800213
214 // Setting a different colorTransformMatrix should perform the update.
215 CompositionRefreshArgs refreshArgs;
216 refreshArgs.colorTransformMatrix = kIdentity;
217
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700218 mOutput->setColorTransform(refreshArgs);
Lloyd Pique3eb1b212019-03-07 21:15:40 -0800219
220 // The internal state should have been updated
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700221 EXPECT_EQ(kIdentity, mOutput->getState().colorTransformMatrix);
Lloyd Pique3eb1b212019-03-07 21:15:40 -0800222
223 // The dirtyRegion should be set to the full display size
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700224 EXPECT_THAT(mOutput->getState().dirtyRegion, RegionEq(Region(kDefaultDisplaySize)));
Lloyd Pique3eb1b212019-03-07 21:15:40 -0800225}
Lloyd Pique77f79a22019-04-29 15:55:40 -0700226
Lloyd Pique3eb1b212019-03-07 21:15:40 -0800227TEST_F(OutputTest, setColorTransformPerformsUpdateForIdentityToHalf) {
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700228 mOutput->editState().colorTransformMatrix = kIdentity;
Lloyd Pique77f79a22019-04-29 15:55:40 -0700229
Lloyd Pique3eb1b212019-03-07 21:15:40 -0800230 // Setting a different colorTransformMatrix should perform the update.
231 CompositionRefreshArgs refreshArgs;
232 refreshArgs.colorTransformMatrix = kNonIdentityHalf;
Lloyd Pique77f79a22019-04-29 15:55:40 -0700233
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700234 mOutput->setColorTransform(refreshArgs);
Lloyd Piqueef958122019-02-05 18:00:12 -0800235
Lloyd Pique3eb1b212019-03-07 21:15:40 -0800236 // The internal state should have been updated
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700237 EXPECT_EQ(kNonIdentityHalf, mOutput->getState().colorTransformMatrix);
Lloyd Pique3eb1b212019-03-07 21:15:40 -0800238
239 // The dirtyRegion should be set to the full display size
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700240 EXPECT_THAT(mOutput->getState().dirtyRegion, RegionEq(Region(kDefaultDisplaySize)));
Lloyd Pique3eb1b212019-03-07 21:15:40 -0800241}
242
243TEST_F(OutputTest, setColorTransformPerformsUpdateForHalfToQuarter) {
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700244 mOutput->editState().colorTransformMatrix = kNonIdentityHalf;
Lloyd Pique3eb1b212019-03-07 21:15:40 -0800245
246 // Setting a different colorTransformMatrix should perform the update.
247 CompositionRefreshArgs refreshArgs;
248 refreshArgs.colorTransformMatrix = kNonIdentityQuarter;
249
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700250 mOutput->setColorTransform(refreshArgs);
Lloyd Pique3eb1b212019-03-07 21:15:40 -0800251
252 // The internal state should have been updated
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700253 EXPECT_EQ(kNonIdentityQuarter, mOutput->getState().colorTransformMatrix);
Lloyd Pique3eb1b212019-03-07 21:15:40 -0800254
255 // The dirtyRegion should be set to the full display size
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700256 EXPECT_THAT(mOutput->getState().dirtyRegion, RegionEq(Region(kDefaultDisplaySize)));
Lloyd Pique32cbe282018-10-19 13:09:22 -0700257}
258
Lloyd Pique66d68602019-02-13 14:23:31 -0800259/*
Lloyd Pique32cbe282018-10-19 13:09:22 -0700260 * Output::setColorMode
261 */
262
Lloyd Piqueef958122019-02-05 18:00:12 -0800263TEST_F(OutputTest, setColorModeSetsStateAndDirtiesOutputIfChanged) {
Lloyd Pique6a3b4462019-03-07 20:58:12 -0800264 using ColorProfile = Output::ColorProfile;
265
Lloyd Piquef5275482019-01-29 18:42:42 -0800266 EXPECT_CALL(*mDisplayColorProfile,
267 getTargetDataspace(ui::ColorMode::DISPLAY_P3, ui::Dataspace::DISPLAY_P3,
268 ui::Dataspace::UNKNOWN))
269 .WillOnce(Return(ui::Dataspace::UNKNOWN));
Lloyd Piqueef958122019-02-05 18:00:12 -0800270 EXPECT_CALL(*mRenderSurface, setBufferDataspace(ui::Dataspace::DISPLAY_P3)).Times(1);
Lloyd Pique31cb2942018-10-19 17:23:03 -0700271
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700272 mOutput->setColorProfile(ColorProfile{ui::ColorMode::DISPLAY_P3, ui::Dataspace::DISPLAY_P3,
273 ui::RenderIntent::TONE_MAP_COLORIMETRIC,
274 ui::Dataspace::UNKNOWN});
Lloyd Pique32cbe282018-10-19 13:09:22 -0700275
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700276 EXPECT_EQ(ui::ColorMode::DISPLAY_P3, mOutput->getState().colorMode);
277 EXPECT_EQ(ui::Dataspace::DISPLAY_P3, mOutput->getState().dataspace);
278 EXPECT_EQ(ui::RenderIntent::TONE_MAP_COLORIMETRIC, mOutput->getState().renderIntent);
279 EXPECT_EQ(ui::Dataspace::UNKNOWN, mOutput->getState().targetDataspace);
Lloyd Piquef5275482019-01-29 18:42:42 -0800280
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700281 EXPECT_THAT(mOutput->getState().dirtyRegion, RegionEq(Region(kDefaultDisplaySize)));
Lloyd Piqueef958122019-02-05 18:00:12 -0800282}
283
284TEST_F(OutputTest, setColorModeDoesNothingIfNoChange) {
Lloyd Pique6a3b4462019-03-07 20:58:12 -0800285 using ColorProfile = Output::ColorProfile;
286
Lloyd Piquef5275482019-01-29 18:42:42 -0800287 EXPECT_CALL(*mDisplayColorProfile,
288 getTargetDataspace(ui::ColorMode::DISPLAY_P3, ui::Dataspace::DISPLAY_P3,
289 ui::Dataspace::UNKNOWN))
290 .WillOnce(Return(ui::Dataspace::UNKNOWN));
291
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700292 mOutput->editState().colorMode = ui::ColorMode::DISPLAY_P3;
293 mOutput->editState().dataspace = ui::Dataspace::DISPLAY_P3;
294 mOutput->editState().renderIntent = ui::RenderIntent::TONE_MAP_COLORIMETRIC;
295 mOutput->editState().targetDataspace = ui::Dataspace::UNKNOWN;
Lloyd Piqueef958122019-02-05 18:00:12 -0800296
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700297 mOutput->setColorProfile(ColorProfile{ui::ColorMode::DISPLAY_P3, ui::Dataspace::DISPLAY_P3,
298 ui::RenderIntent::TONE_MAP_COLORIMETRIC,
299 ui::Dataspace::UNKNOWN});
Lloyd Piqueef958122019-02-05 18:00:12 -0800300
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700301 EXPECT_THAT(mOutput->getState().dirtyRegion, RegionEq(Region()));
Lloyd Pique32cbe282018-10-19 13:09:22 -0700302}
303
Lloyd Pique66d68602019-02-13 14:23:31 -0800304/*
Lloyd Pique31cb2942018-10-19 17:23:03 -0700305 * Output::setRenderSurface()
306 */
307
308TEST_F(OutputTest, setRenderSurfaceResetsBounds) {
309 const ui::Size newDisplaySize{640, 480};
310
311 mock::RenderSurface* renderSurface = new StrictMock<mock::RenderSurface>();
312 EXPECT_CALL(*renderSurface, getSize()).WillOnce(ReturnRef(newDisplaySize));
313
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700314 mOutput->setRenderSurface(std::unique_ptr<RenderSurface>(renderSurface));
Lloyd Pique31cb2942018-10-19 17:23:03 -0700315
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700316 EXPECT_EQ(Rect(newDisplaySize), mOutput->getState().bounds);
Lloyd Pique31cb2942018-10-19 17:23:03 -0700317}
318
Lloyd Pique66d68602019-02-13 14:23:31 -0800319/*
Alec Mourie7d1d4a2019-02-05 01:13:46 +0000320 * Output::getDirtyRegion()
Lloyd Pique32cbe282018-10-19 13:09:22 -0700321 */
322
Alec Mourie7d1d4a2019-02-05 01:13:46 +0000323TEST_F(OutputTest, getDirtyRegionWithRepaintEverythingTrue) {
324 const Rect viewport{100, 200};
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700325 mOutput->editState().viewport = viewport;
326 mOutput->editState().dirtyRegion.set(50, 300);
Lloyd Pique32cbe282018-10-19 13:09:22 -0700327
328 {
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700329 Region result = mOutput->getDirtyRegion(true);
Lloyd Pique32cbe282018-10-19 13:09:22 -0700330
Alec Mourie7d1d4a2019-02-05 01:13:46 +0000331 EXPECT_THAT(result, RegionEq(Region(viewport)));
Lloyd Pique32cbe282018-10-19 13:09:22 -0700332 }
333}
334
Alec Mourie7d1d4a2019-02-05 01:13:46 +0000335TEST_F(OutputTest, getDirtyRegionWithRepaintEverythingFalse) {
336 const Rect viewport{100, 200};
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700337 mOutput->editState().viewport = viewport;
338 mOutput->editState().dirtyRegion.set(50, 300);
Lloyd Pique32cbe282018-10-19 13:09:22 -0700339
340 {
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700341 Region result = mOutput->getDirtyRegion(false);
Lloyd Pique32cbe282018-10-19 13:09:22 -0700342
343 // The dirtyRegion should be clipped to the display bounds.
344 EXPECT_THAT(result, RegionEq(Region(Rect(50, 200))));
345 }
Lloyd Pique32cbe282018-10-19 13:09:22 -0700346}
347
Lloyd Pique66d68602019-02-13 14:23:31 -0800348/*
Lloyd Piqueef36b002019-01-23 17:52:04 -0800349 * Output::belongsInOutput()
350 */
351
352TEST_F(OutputTest, belongsInOutputFiltersAsExpected) {
353 const uint32_t layerStack1 = 123u;
354 const uint32_t layerStack2 = 456u;
355
356 // If the output accepts layerStack1 and internal-only layers....
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700357 mOutput->setLayerStackFilter(layerStack1, true);
Lloyd Piqueef36b002019-01-23 17:52:04 -0800358
Lloyd Piquec6687342019-03-07 21:34:57 -0800359 // A layer with no layerStack does not belong to it, internal-only or not.
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700360 EXPECT_FALSE(mOutput->belongsInOutput(std::nullopt, false));
361 EXPECT_FALSE(mOutput->belongsInOutput(std::nullopt, true));
Lloyd Piquec6687342019-03-07 21:34:57 -0800362
Lloyd Piqueef36b002019-01-23 17:52:04 -0800363 // Any layer with layerStack1 belongs to it, internal-only or not.
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700364 EXPECT_TRUE(mOutput->belongsInOutput(layerStack1, false));
365 EXPECT_TRUE(mOutput->belongsInOutput(layerStack1, true));
366 EXPECT_FALSE(mOutput->belongsInOutput(layerStack2, true));
367 EXPECT_FALSE(mOutput->belongsInOutput(layerStack2, false));
Lloyd Piqueef36b002019-01-23 17:52:04 -0800368
369 // If the output accepts layerStack21 but not internal-only layers...
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700370 mOutput->setLayerStackFilter(layerStack1, false);
Lloyd Piqueef36b002019-01-23 17:52:04 -0800371
372 // Only non-internal layers with layerStack1 belong to it.
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700373 EXPECT_TRUE(mOutput->belongsInOutput(layerStack1, false));
374 EXPECT_FALSE(mOutput->belongsInOutput(layerStack1, true));
375 EXPECT_FALSE(mOutput->belongsInOutput(layerStack2, true));
376 EXPECT_FALSE(mOutput->belongsInOutput(layerStack2, false));
Lloyd Piqueef36b002019-01-23 17:52:04 -0800377}
378
Lloyd Pique66c20c42019-03-07 21:44:02 -0800379TEST_F(OutputTest, belongsInOutputFiltersLayersAsExpected) {
380 StrictMock<mock::Layer> layer;
Lloyd Pique9755fb72019-03-26 14:44:40 -0700381 LayerFECompositionState layerFEState;
Lloyd Pique66c20c42019-03-07 21:44:02 -0800382
Lloyd Pique9755fb72019-03-26 14:44:40 -0700383 EXPECT_CALL(layer, getFEState()).WillRepeatedly(ReturnRef(layerFEState));
Lloyd Pique66c20c42019-03-07 21:44:02 -0800384
385 const uint32_t layerStack1 = 123u;
386 const uint32_t layerStack2 = 456u;
387
388 // If the output accepts layerStack1 and internal-only layers....
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700389 mOutput->setLayerStackFilter(layerStack1, true);
Lloyd Pique66c20c42019-03-07 21:44:02 -0800390
391 // A null layer pointer does not belong to the output
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700392 EXPECT_FALSE(mOutput->belongsInOutput(nullptr));
Lloyd Pique66c20c42019-03-07 21:44:02 -0800393
394 // A layer with no layerStack does not belong to it, internal-only or not.
Lloyd Pique9755fb72019-03-26 14:44:40 -0700395 layerFEState.layerStackId = std::nullopt;
396 layerFEState.internalOnly = false;
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700397 EXPECT_FALSE(mOutput->belongsInOutput(&layer));
Lloyd Pique66c20c42019-03-07 21:44:02 -0800398
Lloyd Pique9755fb72019-03-26 14:44:40 -0700399 layerFEState.layerStackId = std::nullopt;
400 layerFEState.internalOnly = true;
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700401 EXPECT_FALSE(mOutput->belongsInOutput(&layer));
Lloyd Pique66c20c42019-03-07 21:44:02 -0800402
403 // Any layer with layerStack1 belongs to it, internal-only or not.
Lloyd Pique9755fb72019-03-26 14:44:40 -0700404 layerFEState.layerStackId = layerStack1;
405 layerFEState.internalOnly = false;
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700406 EXPECT_TRUE(mOutput->belongsInOutput(&layer));
Lloyd Pique66c20c42019-03-07 21:44:02 -0800407
Lloyd Pique9755fb72019-03-26 14:44:40 -0700408 layerFEState.layerStackId = layerStack1;
409 layerFEState.internalOnly = true;
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700410 EXPECT_TRUE(mOutput->belongsInOutput(&layer));
Lloyd Pique66c20c42019-03-07 21:44:02 -0800411
Lloyd Pique9755fb72019-03-26 14:44:40 -0700412 layerFEState.layerStackId = layerStack2;
413 layerFEState.internalOnly = true;
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700414 EXPECT_FALSE(mOutput->belongsInOutput(&layer));
Lloyd Pique66c20c42019-03-07 21:44:02 -0800415
Lloyd Pique9755fb72019-03-26 14:44:40 -0700416 layerFEState.layerStackId = layerStack2;
417 layerFEState.internalOnly = false;
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700418 EXPECT_FALSE(mOutput->belongsInOutput(&layer));
Lloyd Pique66c20c42019-03-07 21:44:02 -0800419
420 // If the output accepts layerStack1 but not internal-only layers...
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700421 mOutput->setLayerStackFilter(layerStack1, false);
Lloyd Pique66c20c42019-03-07 21:44:02 -0800422
423 // A null layer pointer does not belong to the output
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700424 EXPECT_FALSE(mOutput->belongsInOutput(nullptr));
Lloyd Pique66c20c42019-03-07 21:44:02 -0800425
426 // Only non-internal layers with layerStack1 belong to it.
Lloyd Pique9755fb72019-03-26 14:44:40 -0700427 layerFEState.layerStackId = layerStack1;
428 layerFEState.internalOnly = false;
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700429 EXPECT_TRUE(mOutput->belongsInOutput(&layer));
Lloyd Pique66c20c42019-03-07 21:44:02 -0800430
Lloyd Pique9755fb72019-03-26 14:44:40 -0700431 layerFEState.layerStackId = layerStack1;
432 layerFEState.internalOnly = true;
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700433 EXPECT_FALSE(mOutput->belongsInOutput(&layer));
Lloyd Pique66c20c42019-03-07 21:44:02 -0800434
Lloyd Pique9755fb72019-03-26 14:44:40 -0700435 layerFEState.layerStackId = layerStack2;
436 layerFEState.internalOnly = true;
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700437 EXPECT_FALSE(mOutput->belongsInOutput(&layer));
Lloyd Pique66c20c42019-03-07 21:44:02 -0800438
Lloyd Pique9755fb72019-03-26 14:44:40 -0700439 layerFEState.layerStackId = layerStack2;
440 layerFEState.internalOnly = false;
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700441 EXPECT_FALSE(mOutput->belongsInOutput(&layer));
Lloyd Pique66c20c42019-03-07 21:44:02 -0800442}
443
Lloyd Pique66d68602019-02-13 14:23:31 -0800444/*
Lloyd Piquecc01a452018-12-04 17:24:00 -0800445 * Output::getOutputLayerForLayer()
446 */
447
448TEST_F(OutputTest, getOutputLayerForLayerWorks) {
449 mock::OutputLayer* outputLayer1 = new StrictMock<mock::OutputLayer>();
450 mock::OutputLayer* outputLayer2 = new StrictMock<mock::OutputLayer>();
451
452 Output::OutputLayers outputLayers;
453 outputLayers.emplace_back(std::unique_ptr<OutputLayer>(outputLayer1));
454 outputLayers.emplace_back(nullptr);
455 outputLayers.emplace_back(std::unique_ptr<OutputLayer>(outputLayer2));
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700456 mOutput->setOutputLayersOrderedByZ(std::move(outputLayers));
Lloyd Piquecc01a452018-12-04 17:24:00 -0800457
458 StrictMock<mock::Layer> layer;
459 StrictMock<mock::Layer> otherLayer;
460
461 // If the input layer matches the first OutputLayer, it will be returned.
462 EXPECT_CALL(*outputLayer1, getLayer()).WillOnce(ReturnRef(layer));
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700463 EXPECT_EQ(outputLayer1, mOutput->getOutputLayerForLayer(&layer));
Lloyd Piquecc01a452018-12-04 17:24:00 -0800464
465 // If the input layer matches the second OutputLayer, it will be returned.
466 EXPECT_CALL(*outputLayer1, getLayer()).WillOnce(ReturnRef(otherLayer));
467 EXPECT_CALL(*outputLayer2, getLayer()).WillOnce(ReturnRef(layer));
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700468 EXPECT_EQ(outputLayer2, mOutput->getOutputLayerForLayer(&layer));
Lloyd Piquecc01a452018-12-04 17:24:00 -0800469
470 // If the input layer does not match an output layer, null will be returned.
471 EXPECT_CALL(*outputLayer1, getLayer()).WillOnce(ReturnRef(otherLayer));
472 EXPECT_CALL(*outputLayer2, getLayer()).WillOnce(ReturnRef(otherLayer));
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700473 EXPECT_EQ(nullptr, mOutput->getOutputLayerForLayer(&layer));
Lloyd Piquecc01a452018-12-04 17:24:00 -0800474}
475
Lloyd Pique66d68602019-02-13 14:23:31 -0800476/*
477 * Output::prepareFrame()
478 */
479
480struct OutputPrepareFrameTest : public testing::Test {
481 struct OutputPartialMock : public impl::Output {
Lloyd Pique66d68602019-02-13 14:23:31 -0800482 // Sets up the helper functions called by prepareFrame to use a mock
483 // implementations.
484 MOCK_METHOD0(chooseCompositionStrategy, void());
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700485
486 // compositionengine::Output overrides
487 const OutputCompositionState& getState() const override { return mState; }
488 OutputCompositionState& editState() override { return mState; }
489
490 // These need implementations though are not expected to be called.
491 MOCK_CONST_METHOD1(dumpState, void(std::string&));
492 MOCK_CONST_METHOD0(getCompositionEngine, const CompositionEngine&());
493
494 impl::OutputCompositionState mState;
Lloyd Pique66d68602019-02-13 14:23:31 -0800495 };
496
497 OutputPrepareFrameTest() {
498 mOutput.setDisplayColorProfileForTest(
499 std::unique_ptr<DisplayColorProfile>(mDisplayColorProfile));
500 mOutput.setRenderSurfaceForTest(std::unique_ptr<RenderSurface>(mRenderSurface));
501 }
502
503 StrictMock<mock::CompositionEngine> mCompositionEngine;
504 mock::DisplayColorProfile* mDisplayColorProfile = new StrictMock<mock::DisplayColorProfile>();
505 mock::RenderSurface* mRenderSurface = new StrictMock<mock::RenderSurface>();
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700506 StrictMock<OutputPartialMock> mOutput;
Lloyd Pique66d68602019-02-13 14:23:31 -0800507};
508
509TEST_F(OutputPrepareFrameTest, takesEarlyOutIfNotEnabled) {
510 mOutput.editState().isEnabled = false;
511
512 mOutput.prepareFrame();
513}
514
515TEST_F(OutputPrepareFrameTest, delegatesToChooseCompositionStrategyAndRenderSurface) {
516 mOutput.editState().isEnabled = true;
517 mOutput.editState().usesClientComposition = false;
518 mOutput.editState().usesDeviceComposition = true;
519
520 EXPECT_CALL(mOutput, chooseCompositionStrategy()).Times(1);
521 EXPECT_CALL(*mRenderSurface, prepareFrame(false, true));
522
523 mOutput.prepareFrame();
524}
525
526// Note: Use OutputTest and not OutputPrepareFrameTest, so the real
527// base chooseCompositionStrategy() is invoked.
528TEST_F(OutputTest, prepareFrameSetsClientCompositionOnlyByDefault) {
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700529 mOutput->editState().isEnabled = true;
530 mOutput->editState().usesClientComposition = false;
531 mOutput->editState().usesDeviceComposition = true;
Lloyd Pique66d68602019-02-13 14:23:31 -0800532
533 EXPECT_CALL(*mRenderSurface, prepareFrame(true, false));
534
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700535 mOutput->prepareFrame();
Lloyd Pique66d68602019-02-13 14:23:31 -0800536
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700537 EXPECT_TRUE(mOutput->getState().usesClientComposition);
538 EXPECT_FALSE(mOutput->getState().usesDeviceComposition);
Lloyd Pique66d68602019-02-13 14:23:31 -0800539}
540
Lloyd Pique56eba802019-08-28 15:45:25 -0700541/*
542 * Output::composeSurfaces()
543 */
544
545struct OutputComposeSurfacesTest : public testing::Test {
546 static constexpr uint32_t kDefaultOutputOrientation = TR_IDENT;
547 static constexpr ui::Dataspace kDefaultOutputDataspace = ui::Dataspace::DISPLAY_P3;
548
549 static const Rect kDefaultOutputFrame;
550 static const Rect kDefaultOutputViewport;
551 static const Rect kDefaultOutputScissor;
552 static const mat4 kDefaultColorTransformMat;
553
554 struct OutputPartialMock : public impl::Output {
Lloyd Pique56eba802019-08-28 15:45:25 -0700555 // Sets up the helper functions called by composeSurfaces to use a mock
556 // implementations.
557 MOCK_CONST_METHOD0(getSkipColorTransform, bool());
558 MOCK_METHOD2(generateClientCompositionRequests,
559 std::vector<renderengine::LayerSettings>(bool, Region&));
560 MOCK_METHOD2(appendRegionFlashRequests,
561 void(const Region&, std::vector<renderengine::LayerSettings>&));
562 MOCK_METHOD1(setExpensiveRenderingExpected, void(bool));
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700563
564 // compositionengine::Output overrides
565 const OutputCompositionState& getState() const override { return mState; }
566 OutputCompositionState& editState() override { return mState; }
567
568 // These need implementations though are not expected to be called.
569 MOCK_CONST_METHOD1(dumpState, void(std::string&));
570 MOCK_CONST_METHOD0(getCompositionEngine, const CompositionEngine&());
571
572 impl::OutputCompositionState mState;
Lloyd Pique56eba802019-08-28 15:45:25 -0700573 };
574
575 OutputComposeSurfacesTest() {
576 mOutput.setDisplayColorProfileForTest(
577 std::unique_ptr<DisplayColorProfile>(mDisplayColorProfile));
578 mOutput.setRenderSurfaceForTest(std::unique_ptr<RenderSurface>(mRenderSurface));
579
580 Output::OutputLayers outputLayers;
581 outputLayers.emplace_back(std::unique_ptr<OutputLayer>(mOutputLayer1));
582 outputLayers.emplace_back(std::unique_ptr<OutputLayer>(mOutputLayer2));
583 mOutput.setOutputLayersOrderedByZ(std::move(outputLayers));
584
585 mOutput.editState().frame = kDefaultOutputFrame;
586 mOutput.editState().viewport = kDefaultOutputViewport;
587 mOutput.editState().scissor = kDefaultOutputScissor;
588 mOutput.editState().transform = ui::Transform{kDefaultOutputOrientation};
589 mOutput.editState().orientation = kDefaultOutputOrientation;
590 mOutput.editState().dataspace = kDefaultOutputDataspace;
Lloyd Pique3eb1b212019-03-07 21:15:40 -0800591 mOutput.editState().colorTransformMatrix = kDefaultColorTransformMat;
Lloyd Pique56eba802019-08-28 15:45:25 -0700592 mOutput.editState().isSecure = true;
593 mOutput.editState().needsFiltering = false;
594 mOutput.editState().usesClientComposition = true;
595 mOutput.editState().usesDeviceComposition = false;
596
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700597 EXPECT_CALL(mOutput, getCompositionEngine()).WillRepeatedly(ReturnRef(mCompositionEngine));
Lloyd Pique56eba802019-08-28 15:45:25 -0700598 EXPECT_CALL(mCompositionEngine, getRenderEngine()).WillRepeatedly(ReturnRef(mRenderEngine));
599 }
600
601 StrictMock<mock::CompositionEngine> mCompositionEngine;
602 StrictMock<renderengine::mock::RenderEngine> mRenderEngine;
603 mock::DisplayColorProfile* mDisplayColorProfile = new StrictMock<mock::DisplayColorProfile>();
604 mock::RenderSurface* mRenderSurface = new StrictMock<mock::RenderSurface>();
605 mock::OutputLayer* mOutputLayer1 = new StrictMock<mock::OutputLayer>();
606 mock::OutputLayer* mOutputLayer2 = new StrictMock<mock::OutputLayer>();
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700607 StrictMock<OutputPartialMock> mOutput;
Lloyd Pique56eba802019-08-28 15:45:25 -0700608 sp<GraphicBuffer> mOutputBuffer = new GraphicBuffer();
609};
610
611const Rect OutputComposeSurfacesTest::kDefaultOutputFrame{1001, 1002, 1003, 1004};
612const Rect OutputComposeSurfacesTest::kDefaultOutputViewport{1005, 1006, 1007, 1008};
613const Rect OutputComposeSurfacesTest::kDefaultOutputScissor{1009, 1010, 1011, 1012};
614const mat4 OutputComposeSurfacesTest::kDefaultColorTransformMat{mat4() * 0.5};
615
616// TODO(b/121291683): Expand unit test coverage for composeSurfaces beyond these
617// basic tests.
618
619TEST_F(OutputComposeSurfacesTest, doesNothingIfNoClientComposition) {
620 mOutput.editState().usesClientComposition = false;
621
622 Region debugRegion;
Lloyd Piqued3d69882019-02-28 16:03:46 -0800623 std::optional<base::unique_fd> readyFence = mOutput.composeSurfaces(debugRegion);
624 EXPECT_TRUE(readyFence);
Lloyd Pique56eba802019-08-28 15:45:25 -0700625}
626
627TEST_F(OutputComposeSurfacesTest, worksIfNoClientLayersQueued) {
628 const Region kDebugRegion{Rect{100, 101, 102, 103}};
629
630 constexpr float kDefaultMaxLuminance = 1.0f;
631 constexpr float kDefaultAvgLuminance = 0.7f;
632 constexpr float kDefaultMinLuminance = 0.1f;
633 HdrCapabilities HdrCapabilities{{},
634 kDefaultMaxLuminance,
635 kDefaultAvgLuminance,
636 kDefaultMinLuminance};
637
638 EXPECT_CALL(mRenderEngine, supportsProtectedContent()).WillOnce(Return(false));
639 EXPECT_CALL(mRenderEngine, drawLayers(_, _, _, true, _, _)).Times(1);
640
641 EXPECT_CALL(*mDisplayColorProfile, hasWideColorGamut()).WillOnce(Return(true));
642 EXPECT_CALL(*mDisplayColorProfile, getHdrCapabilities()).WillOnce(ReturnRef(HdrCapabilities));
643
644 EXPECT_CALL(*mRenderSurface, dequeueBuffer(_)).WillOnce(Return(mOutputBuffer));
645
646 EXPECT_CALL(mOutput, getSkipColorTransform()).WillOnce(Return(false));
647 EXPECT_CALL(mOutput, generateClientCompositionRequests(false, _)).Times(1);
648 EXPECT_CALL(mOutput, appendRegionFlashRequests(RegionEq(kDebugRegion), _)).Times(1);
649 EXPECT_CALL(mOutput, setExpensiveRenderingExpected(true)).Times(1);
650 EXPECT_CALL(mOutput, setExpensiveRenderingExpected(false)).Times(1);
651
Lloyd Piqued3d69882019-02-28 16:03:46 -0800652 std::optional<base::unique_fd> readyFence = mOutput.composeSurfaces(kDebugRegion);
653 EXPECT_TRUE(readyFence);
Lloyd Pique56eba802019-08-28 15:45:25 -0700654}
655
656/*
657 * Output::generateClientCompositionRequests()
658 */
659
660struct GenerateClientCompositionRequestsTest : public testing::Test {
661 struct OutputPartialMock : public impl::Output {
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700662 // compositionengine::Output overrides
Lloyd Pique56eba802019-08-28 15:45:25 -0700663
664 std::vector<renderengine::LayerSettings> generateClientCompositionRequests(
665 bool supportsProtectedContent, Region& clearRegion) override {
666 return impl::Output::generateClientCompositionRequests(supportsProtectedContent,
667 clearRegion);
668 }
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700669
670 const OutputCompositionState& getState() const override { return mState; }
671 OutputCompositionState& editState() override { return mState; }
672
673 // These need implementations though are not expected to be called.
674 MOCK_CONST_METHOD1(dumpState, void(std::string&));
675 MOCK_CONST_METHOD0(getCompositionEngine, const CompositionEngine&());
676
677 impl::OutputCompositionState mState;
Lloyd Pique56eba802019-08-28 15:45:25 -0700678 };
679
680 GenerateClientCompositionRequestsTest() {
681 mOutput.setDisplayColorProfileForTest(
682 std::unique_ptr<DisplayColorProfile>(mDisplayColorProfile));
683 mOutput.setRenderSurfaceForTest(std::unique_ptr<RenderSurface>(mRenderSurface));
684 }
685
Lloyd Pique56eba802019-08-28 15:45:25 -0700686 mock::DisplayColorProfile* mDisplayColorProfile = new StrictMock<mock::DisplayColorProfile>();
687 mock::RenderSurface* mRenderSurface = new StrictMock<mock::RenderSurface>();
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700688 StrictMock<OutputPartialMock> mOutput;
Lloyd Pique56eba802019-08-28 15:45:25 -0700689};
690
691// TODO(b/121291683): Add more unit test coverage for generateClientCompositionRequests
692
693TEST_F(GenerateClientCompositionRequestsTest, worksForLandscapeModeSplitScreen) {
694 // In split-screen landscape mode, the screen is rotated 90 degrees, with
695 // one layer on the left covering the left side of the output, and one layer
696 // on the right covering that side of the output.
697
698 mock::OutputLayer* leftOutputLayer = new StrictMock<mock::OutputLayer>();
699 mock::OutputLayer* rightOutputLayer = new StrictMock<mock::OutputLayer>();
700
701 StrictMock<mock::Layer> leftLayer;
702 StrictMock<mock::LayerFE> leftLayerFE;
703 StrictMock<mock::Layer> rightLayer;
704 StrictMock<mock::LayerFE> rightLayerFE;
705
706 impl::OutputLayerCompositionState leftOutputLayerState;
707 leftOutputLayerState.clearClientTarget = false;
Lloyd Piquea2468662019-03-07 21:31:06 -0800708 leftOutputLayerState.visibleRegion = Region{Rect{0, 0, 1000, 1000}};
Lloyd Pique56eba802019-08-28 15:45:25 -0700709
Lloyd Pique9755fb72019-03-26 14:44:40 -0700710 LayerFECompositionState leftLayerFEState;
711 leftLayerFEState.isOpaque = true;
Lloyd Pique56eba802019-08-28 15:45:25 -0700712
713 const half3 leftLayerColor{1.f, 0.f, 0.f};
714 renderengine::LayerSettings leftLayerRESettings;
715 leftLayerRESettings.source.solidColor = leftLayerColor;
716
717 impl::OutputLayerCompositionState rightOutputLayerState;
718 rightOutputLayerState.clearClientTarget = false;
Lloyd Piquea2468662019-03-07 21:31:06 -0800719 rightOutputLayerState.visibleRegion = Region{Rect{1000, 0, 2000, 1000}};
Lloyd Pique56eba802019-08-28 15:45:25 -0700720
Lloyd Pique9755fb72019-03-26 14:44:40 -0700721 LayerFECompositionState rightLayerFEState;
722 rightLayerFEState.isOpaque = true;
Lloyd Pique56eba802019-08-28 15:45:25 -0700723
724 const half3 rightLayerColor{0.f, 1.f, 0.f};
725 renderengine::LayerSettings rightLayerRESettings;
726 rightLayerRESettings.source.solidColor = rightLayerColor;
727
728 EXPECT_CALL(*leftOutputLayer, getState()).WillRepeatedly(ReturnRef(leftOutputLayerState));
729 EXPECT_CALL(*leftOutputLayer, getLayer()).WillRepeatedly(ReturnRef(leftLayer));
730 EXPECT_CALL(*leftOutputLayer, getLayerFE()).WillRepeatedly(ReturnRef(leftLayerFE));
731 EXPECT_CALL(*leftOutputLayer, requiresClientComposition()).WillRepeatedly(Return(true));
732 EXPECT_CALL(*leftOutputLayer, needsFiltering()).WillRepeatedly(Return(false));
Lloyd Pique9755fb72019-03-26 14:44:40 -0700733 EXPECT_CALL(leftLayer, getFEState()).WillRepeatedly(ReturnRef(leftLayerFEState));
Lloyd Pique56eba802019-08-28 15:45:25 -0700734 EXPECT_CALL(leftLayerFE, prepareClientComposition(_)).WillOnce(Return(leftLayerRESettings));
735
736 EXPECT_CALL(*rightOutputLayer, getState()).WillRepeatedly(ReturnRef(rightOutputLayerState));
737 EXPECT_CALL(*rightOutputLayer, getLayer()).WillRepeatedly(ReturnRef(rightLayer));
738 EXPECT_CALL(*rightOutputLayer, getLayerFE()).WillRepeatedly(ReturnRef(rightLayerFE));
739 EXPECT_CALL(*rightOutputLayer, requiresClientComposition()).WillRepeatedly(Return(true));
740 EXPECT_CALL(*rightOutputLayer, needsFiltering()).WillRepeatedly(Return(false));
Lloyd Pique9755fb72019-03-26 14:44:40 -0700741 EXPECT_CALL(rightLayer, getFEState()).WillRepeatedly(ReturnRef(rightLayerFEState));
Lloyd Pique56eba802019-08-28 15:45:25 -0700742 EXPECT_CALL(rightLayerFE, prepareClientComposition(_)).WillOnce(Return(rightLayerRESettings));
743
744 Output::OutputLayers outputLayers;
745 outputLayers.emplace_back(std::unique_ptr<OutputLayer>(leftOutputLayer));
746 outputLayers.emplace_back(std::unique_ptr<OutputLayer>(rightOutputLayer));
747 mOutput.setOutputLayersOrderedByZ(std::move(outputLayers));
748
749 const Rect kPortraitFrame(0, 0, 1000, 2000);
750 const Rect kPortraitViewport(0, 0, 2000, 1000);
751 const Rect kPortraitScissor(0, 0, 1000, 2000);
752 const uint32_t kPortraitOrientation = TR_ROT_90;
753
754 mOutput.editState().frame = kPortraitFrame;
755 mOutput.editState().viewport = kPortraitViewport;
756 mOutput.editState().scissor = kPortraitScissor;
757 mOutput.editState().transform = ui::Transform{kPortraitOrientation};
758 mOutput.editState().orientation = kPortraitOrientation;
759 mOutput.editState().needsFiltering = true;
760 mOutput.editState().isSecure = false;
761
762 constexpr bool supportsProtectedContent = false;
763 Region clearRegion;
764 auto requests =
765 mOutput.generateClientCompositionRequests(supportsProtectedContent, clearRegion);
766
767 ASSERT_EQ(2u, requests.size());
768 EXPECT_EQ(leftLayerColor, requests[0].source.solidColor);
769 EXPECT_EQ(rightLayerColor, requests[1].source.solidColor);
770}
771
772TEST_F(GenerateClientCompositionRequestsTest, ignoresLayersThatDoNotIntersectWithViewport) {
773 // Layers whose visible region does not intersect with the viewport will be
774 // skipped when generating client composition request state.
775
776 mock::OutputLayer* outputLayer = new StrictMock<mock::OutputLayer>();
777 StrictMock<mock::Layer> layer;
778 StrictMock<mock::LayerFE> layerFE;
779
780 impl::OutputLayerCompositionState outputLayerState;
781 outputLayerState.clearClientTarget = false;
Lloyd Piquea2468662019-03-07 21:31:06 -0800782 outputLayerState.visibleRegion = Region{Rect{3000, 0, 4000, 1000}};
Lloyd Pique56eba802019-08-28 15:45:25 -0700783
Lloyd Pique9755fb72019-03-26 14:44:40 -0700784 LayerFECompositionState layerFEState;
785 layerFEState.isOpaque = true;
Lloyd Pique56eba802019-08-28 15:45:25 -0700786
787 EXPECT_CALL(*outputLayer, getState()).WillRepeatedly(ReturnRef(outputLayerState));
788 EXPECT_CALL(*outputLayer, getLayer()).WillRepeatedly(ReturnRef(layer));
789 EXPECT_CALL(*outputLayer, getLayerFE()).WillRepeatedly(ReturnRef(layerFE));
790 EXPECT_CALL(*outputLayer, requiresClientComposition()).WillRepeatedly(Return(true));
791 EXPECT_CALL(*outputLayer, needsFiltering()).WillRepeatedly(Return(false));
Lloyd Pique9755fb72019-03-26 14:44:40 -0700792 EXPECT_CALL(layer, getFEState()).WillRepeatedly(ReturnRef(layerFEState));
Lloyd Pique56eba802019-08-28 15:45:25 -0700793 EXPECT_CALL(layerFE, prepareClientComposition(_)).Times(0);
794
795 Output::OutputLayers outputLayers;
796 outputLayers.emplace_back(std::unique_ptr<OutputLayer>(outputLayer));
797 mOutput.setOutputLayersOrderedByZ(std::move(outputLayers));
798
799 const Rect kPortraitFrame(0, 0, 1000, 2000);
800 const Rect kPortraitViewport(0, 0, 2000, 1000);
801 const Rect kPortraitScissor(0, 0, 1000, 2000);
802 const uint32_t kPortraitOrientation = TR_ROT_90;
803
804 mOutput.editState().frame = kPortraitFrame;
805 mOutput.editState().viewport = kPortraitViewport;
806 mOutput.editState().scissor = kPortraitScissor;
807 mOutput.editState().transform = ui::Transform{kPortraitOrientation};
808 mOutput.editState().orientation = kPortraitOrientation;
809 mOutput.editState().needsFiltering = true;
810 mOutput.editState().isSecure = false;
811
812 constexpr bool supportsProtectedContent = false;
813 Region clearRegion;
814 auto requests =
815 mOutput.generateClientCompositionRequests(supportsProtectedContent, clearRegion);
816
817 EXPECT_EQ(0u, requests.size());
818}
819
Lloyd Piquec2d54d42019-08-28 18:04:21 -0700820TEST_F(GenerateClientCompositionRequestsTest, clearsDeviceLayesAfterFirst) {
821 // If client composition is performed with some layers set to use device
822 // composition, device layers after the first layer (device or client) will
823 // clear the frame buffer if they are opaque and if that layer has a flag
824 // set to do so. The first layer is skipped as the frame buffer is already
825 // expected to be clear.
826
827 mock::OutputLayer* leftOutputLayer = new StrictMock<mock::OutputLayer>();
828 mock::OutputLayer* rightOutputLayer = new StrictMock<mock::OutputLayer>();
829
830 StrictMock<mock::Layer> leftLayer;
831 StrictMock<mock::LayerFE> leftLayerFE;
832 StrictMock<mock::Layer> rightLayer;
833 StrictMock<mock::LayerFE> rightLayerFE;
834
835 impl::OutputLayerCompositionState leftOutputLayerState;
836 leftOutputLayerState.clearClientTarget = true;
Lloyd Piquea2468662019-03-07 21:31:06 -0800837 leftOutputLayerState.visibleRegion = Region{Rect{0, 0, 1000, 1000}};
Lloyd Piquec2d54d42019-08-28 18:04:21 -0700838
Lloyd Pique9755fb72019-03-26 14:44:40 -0700839 LayerFECompositionState leftLayerFEState;
840 leftLayerFEState.isOpaque = true;
Lloyd Piquec2d54d42019-08-28 18:04:21 -0700841
842 impl::OutputLayerCompositionState rightOutputLayerState;
843 rightOutputLayerState.clearClientTarget = true;
Lloyd Piquea2468662019-03-07 21:31:06 -0800844 rightOutputLayerState.visibleRegion = Region{Rect{1000, 0, 2000, 1000}};
Lloyd Piquec2d54d42019-08-28 18:04:21 -0700845
Lloyd Pique9755fb72019-03-26 14:44:40 -0700846 LayerFECompositionState rightLayerFEState;
847 rightLayerFEState.isOpaque = true;
Lloyd Piquec2d54d42019-08-28 18:04:21 -0700848
849 const half3 rightLayerColor{0.f, 1.f, 0.f};
850 renderengine::LayerSettings rightLayerRESettings;
851 rightLayerRESettings.geometry.boundaries = FloatRect{456, 0, 0, 0};
852 rightLayerRESettings.source.solidColor = rightLayerColor;
853
854 EXPECT_CALL(*leftOutputLayer, getState()).WillRepeatedly(ReturnRef(leftOutputLayerState));
855 EXPECT_CALL(*leftOutputLayer, getLayer()).WillRepeatedly(ReturnRef(leftLayer));
856 EXPECT_CALL(*leftOutputLayer, getLayerFE()).WillRepeatedly(ReturnRef(leftLayerFE));
857 EXPECT_CALL(*leftOutputLayer, requiresClientComposition()).WillRepeatedly(Return(false));
858 EXPECT_CALL(*leftOutputLayer, needsFiltering()).WillRepeatedly(Return(false));
Lloyd Pique9755fb72019-03-26 14:44:40 -0700859 EXPECT_CALL(leftLayer, getFEState()).WillRepeatedly(ReturnRef(leftLayerFEState));
Lloyd Piquec2d54d42019-08-28 18:04:21 -0700860
861 EXPECT_CALL(*rightOutputLayer, getState()).WillRepeatedly(ReturnRef(rightOutputLayerState));
862 EXPECT_CALL(*rightOutputLayer, getLayer()).WillRepeatedly(ReturnRef(rightLayer));
863 EXPECT_CALL(*rightOutputLayer, getLayerFE()).WillRepeatedly(ReturnRef(rightLayerFE));
864 EXPECT_CALL(*rightOutputLayer, requiresClientComposition()).WillRepeatedly(Return(false));
865 EXPECT_CALL(*rightOutputLayer, needsFiltering()).WillRepeatedly(Return(false));
Lloyd Pique9755fb72019-03-26 14:44:40 -0700866 EXPECT_CALL(rightLayer, getFEState()).WillRepeatedly(ReturnRef(rightLayerFEState));
Lloyd Piquec2d54d42019-08-28 18:04:21 -0700867 EXPECT_CALL(rightLayerFE, prepareClientComposition(_)).WillOnce(Return(rightLayerRESettings));
868
869 Output::OutputLayers outputLayers;
870 outputLayers.emplace_back(std::unique_ptr<OutputLayer>(leftOutputLayer));
871 outputLayers.emplace_back(std::unique_ptr<OutputLayer>(rightOutputLayer));
872 mOutput.setOutputLayersOrderedByZ(std::move(outputLayers));
873
874 const Rect kPortraitFrame(0, 0, 1000, 2000);
875 const Rect kPortraitViewport(0, 0, 2000, 1000);
876 const Rect kPortraitScissor(0, 0, 1000, 2000);
877 const uint32_t kPortraitOrientation = TR_ROT_90;
878
879 mOutput.editState().frame = kPortraitFrame;
880 mOutput.editState().viewport = kPortraitViewport;
881 mOutput.editState().scissor = kPortraitScissor;
882 mOutput.editState().transform = ui::Transform{kPortraitOrientation};
883 mOutput.editState().orientation = kPortraitOrientation;
884 mOutput.editState().needsFiltering = true;
885 mOutput.editState().isSecure = false;
886
887 constexpr bool supportsProtectedContent = false;
888 Region clearRegion;
889 auto requests =
890 mOutput.generateClientCompositionRequests(supportsProtectedContent, clearRegion);
891
892 const half3 clearColor{0.f, 0.f, 0.f};
893
894 ASSERT_EQ(1u, requests.size());
895 EXPECT_EQ(456.f, requests[0].geometry.boundaries.left);
896 EXPECT_EQ(clearColor, requests[0].source.solidColor);
897}
898
Lloyd Pique32cbe282018-10-19 13:09:22 -0700899} // namespace
900} // namespace android::compositionengine