blob: 95ae8887678ef985de6001ebcf7183a98659d5a1 [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 Pique01c77c12019-04-17 12:48:32 -070053 class Output : public impl::Output {
54 public:
55 using impl::Output::injectOutputLayerForTest;
56 virtual void injectOutputLayerForTest(std::unique_ptr<compositionengine::OutputLayer>) = 0;
57 };
58
59 static std::shared_ptr<Output> createOutput(
60 const compositionengine::CompositionEngine& compositionEngine) {
61 return impl::createOutputTemplated<Output>(compositionEngine);
62 }
63
Lloyd Pique31cb2942018-10-19 17:23:03 -070064 OutputTest() {
Lloyd Piquea38ea7e2019-04-16 18:10:26 -070065 mOutput->setDisplayColorProfileForTest(
Lloyd Pique3d0c02e2018-10-19 18:38:12 -070066 std::unique_ptr<DisplayColorProfile>(mDisplayColorProfile));
Lloyd Piquea38ea7e2019-04-16 18:10:26 -070067 mOutput->setRenderSurfaceForTest(std::unique_ptr<RenderSurface>(mRenderSurface));
Lloyd Piqueef958122019-02-05 18:00:12 -080068
Lloyd Piquea38ea7e2019-04-16 18:10:26 -070069 mOutput->editState().bounds = kDefaultDisplaySize;
Lloyd Pique31cb2942018-10-19 17:23:03 -070070 }
Lloyd Pique32cbe282018-10-19 13:09:22 -070071
Lloyd Piqueef958122019-02-05 18:00:12 -080072 static const Rect kDefaultDisplaySize;
73
Lloyd Pique32cbe282018-10-19 13:09:22 -070074 StrictMock<mock::CompositionEngine> mCompositionEngine;
Lloyd Pique3d0c02e2018-10-19 18:38:12 -070075 mock::DisplayColorProfile* mDisplayColorProfile = new StrictMock<mock::DisplayColorProfile>();
Lloyd Pique31cb2942018-10-19 17:23:03 -070076 mock::RenderSurface* mRenderSurface = new StrictMock<mock::RenderSurface>();
Lloyd Pique01c77c12019-04-17 12:48:32 -070077 std::shared_ptr<Output> mOutput = createOutput(mCompositionEngine);
Lloyd Pique32cbe282018-10-19 13:09:22 -070078};
79
Lloyd Piqueef958122019-02-05 18:00:12 -080080const Rect OutputTest::kDefaultDisplaySize{100, 200};
81
Lloyd Pique66d68602019-02-13 14:23:31 -080082/*
Lloyd Pique32cbe282018-10-19 13:09:22 -070083 * Basic construction
84 */
85
Lloyd Pique31cb2942018-10-19 17:23:03 -070086TEST_F(OutputTest, canInstantiateOutput) {
87 // The validation check checks each required component.
Lloyd Pique3d0c02e2018-10-19 18:38:12 -070088 EXPECT_CALL(*mDisplayColorProfile, isValid()).WillOnce(Return(true));
Lloyd Pique31cb2942018-10-19 17:23:03 -070089 EXPECT_CALL(*mRenderSurface, isValid()).WillOnce(Return(true));
90
Lloyd Piquea38ea7e2019-04-16 18:10:26 -070091 EXPECT_TRUE(mOutput->isValid());
Lloyd Pique31cb2942018-10-19 17:23:03 -070092
93 // If we take away the required components, it is no longer valid.
Lloyd Piquea38ea7e2019-04-16 18:10:26 -070094 mOutput->setRenderSurfaceForTest(std::unique_ptr<RenderSurface>());
Lloyd Pique31cb2942018-10-19 17:23:03 -070095
Lloyd Pique3d0c02e2018-10-19 18:38:12 -070096 EXPECT_CALL(*mDisplayColorProfile, isValid()).WillOnce(Return(true));
97
Lloyd Piquea38ea7e2019-04-16 18:10:26 -070098 EXPECT_FALSE(mOutput->isValid());
Lloyd Pique31cb2942018-10-19 17:23:03 -070099}
Lloyd Pique32cbe282018-10-19 13:09:22 -0700100
Lloyd Pique66d68602019-02-13 14:23:31 -0800101/*
Lloyd Pique32cbe282018-10-19 13:09:22 -0700102 * Output::setCompositionEnabled()
103 */
104
105TEST_F(OutputTest, setCompositionEnabledDoesNothingIfAlreadyEnabled) {
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700106 mOutput->editState().isEnabled = true;
Lloyd Pique32cbe282018-10-19 13:09:22 -0700107
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700108 mOutput->setCompositionEnabled(true);
Lloyd Pique32cbe282018-10-19 13:09:22 -0700109
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700110 EXPECT_TRUE(mOutput->getState().isEnabled);
111 EXPECT_THAT(mOutput->getState().dirtyRegion, RegionEq(Region()));
Lloyd Pique32cbe282018-10-19 13:09:22 -0700112}
113
114TEST_F(OutputTest, setCompositionEnabledSetsEnabledAndDirtiesEntireOutput) {
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700115 mOutput->editState().isEnabled = false;
Lloyd Pique32cbe282018-10-19 13:09:22 -0700116
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700117 mOutput->setCompositionEnabled(true);
Lloyd Pique32cbe282018-10-19 13:09:22 -0700118
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700119 EXPECT_TRUE(mOutput->getState().isEnabled);
120 EXPECT_THAT(mOutput->getState().dirtyRegion, RegionEq(Region(kDefaultDisplaySize)));
Lloyd Pique32cbe282018-10-19 13:09:22 -0700121}
122
123TEST_F(OutputTest, setCompositionEnabledSetsDisabledAndDirtiesEntireOutput) {
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700124 mOutput->editState().isEnabled = true;
Lloyd Pique32cbe282018-10-19 13:09:22 -0700125
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700126 mOutput->setCompositionEnabled(false);
Lloyd Pique32cbe282018-10-19 13:09:22 -0700127
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700128 EXPECT_FALSE(mOutput->getState().isEnabled);
129 EXPECT_THAT(mOutput->getState().dirtyRegion, RegionEq(Region(kDefaultDisplaySize)));
Lloyd Pique32cbe282018-10-19 13:09:22 -0700130}
131
Lloyd Pique66d68602019-02-13 14:23:31 -0800132/*
Lloyd Pique32cbe282018-10-19 13:09:22 -0700133 * Output::setProjection()
134 */
135
136TEST_F(OutputTest, setProjectionTriviallyWorks) {
137 const ui::Transform transform{ui::Transform::ROT_180};
138 const int32_t orientation = 123;
139 const Rect frame{1, 2, 3, 4};
140 const Rect viewport{5, 6, 7, 8};
141 const Rect scissor{9, 10, 11, 12};
142 const bool needsFiltering = true;
143
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700144 mOutput->setProjection(transform, orientation, frame, viewport, scissor, needsFiltering);
Lloyd Pique32cbe282018-10-19 13:09:22 -0700145
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700146 EXPECT_THAT(mOutput->getState().transform, TransformEq(transform));
147 EXPECT_EQ(orientation, mOutput->getState().orientation);
148 EXPECT_EQ(frame, mOutput->getState().frame);
149 EXPECT_EQ(viewport, mOutput->getState().viewport);
150 EXPECT_EQ(scissor, mOutput->getState().scissor);
151 EXPECT_EQ(needsFiltering, mOutput->getState().needsFiltering);
Lloyd Pique32cbe282018-10-19 13:09:22 -0700152}
153
Lloyd Pique66d68602019-02-13 14:23:31 -0800154/*
Lloyd Pique32cbe282018-10-19 13:09:22 -0700155 * Output::setBounds()
156 */
157
158TEST_F(OutputTest, setBoundsSetsSizeAndDirtiesEntireOutput) {
Lloyd Piqueef958122019-02-05 18:00:12 -0800159 const ui::Size displaySize{200, 400};
Lloyd Pique31cb2942018-10-19 17:23:03 -0700160
161 EXPECT_CALL(*mRenderSurface, setDisplaySize(displaySize)).Times(1);
162 EXPECT_CALL(*mRenderSurface, getSize()).WillOnce(ReturnRef(displaySize));
163
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700164 mOutput->setBounds(displaySize);
Lloyd Pique32cbe282018-10-19 13:09:22 -0700165
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700166 EXPECT_EQ(Rect(displaySize), mOutput->getState().bounds);
Lloyd Pique32cbe282018-10-19 13:09:22 -0700167
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700168 EXPECT_THAT(mOutput->getState().dirtyRegion, RegionEq(Region(Rect(displaySize))));
Lloyd Pique32cbe282018-10-19 13:09:22 -0700169}
170
Lloyd Pique66d68602019-02-13 14:23:31 -0800171/*
Lloyd Pique32cbe282018-10-19 13:09:22 -0700172 * Output::setLayerStackFilter()
173 */
174
175TEST_F(OutputTest, setLayerStackFilterSetsFilterAndDirtiesEntireOutput) {
Lloyd Pique32cbe282018-10-19 13:09:22 -0700176 const uint32_t layerStack = 123u;
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700177 mOutput->setLayerStackFilter(layerStack, true);
Lloyd Pique32cbe282018-10-19 13:09:22 -0700178
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700179 EXPECT_TRUE(mOutput->getState().layerStackInternal);
180 EXPECT_EQ(layerStack, mOutput->getState().layerStackId);
Lloyd Pique32cbe282018-10-19 13:09:22 -0700181
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700182 EXPECT_THAT(mOutput->getState().dirtyRegion, RegionEq(Region(kDefaultDisplaySize)));
Lloyd Pique32cbe282018-10-19 13:09:22 -0700183}
184
Lloyd Pique66d68602019-02-13 14:23:31 -0800185/*
Lloyd Pique32cbe282018-10-19 13:09:22 -0700186 * Output::setColorTransform
187 */
188
Lloyd Pique3eb1b212019-03-07 21:15:40 -0800189TEST_F(OutputTest, setColorTransformWithNoChangeFlaggedSkipsUpdates) {
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700190 mOutput->editState().colorTransformMatrix = kIdentity;
Lloyd Pique32cbe282018-10-19 13:09:22 -0700191
Lloyd Pique3eb1b212019-03-07 21:15:40 -0800192 // If no colorTransformMatrix is set the update should be skipped.
193 CompositionRefreshArgs refreshArgs;
194 refreshArgs.colorTransformMatrix = std::nullopt;
Lloyd Pique32cbe282018-10-19 13:09:22 -0700195
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700196 mOutput->setColorTransform(refreshArgs);
Lloyd Pique32cbe282018-10-19 13:09:22 -0700197
Lloyd Pique3eb1b212019-03-07 21:15:40 -0800198 // The internal state should be unchanged
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700199 EXPECT_EQ(kIdentity, mOutput->getState().colorTransformMatrix);
Lloyd Pique3eb1b212019-03-07 21:15:40 -0800200
201 // No dirty region should be set
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700202 EXPECT_THAT(mOutput->getState().dirtyRegion, RegionEq(Region()));
Lloyd Pique3eb1b212019-03-07 21:15:40 -0800203}
Lloyd Piqueef958122019-02-05 18:00:12 -0800204
Lloyd Pique3eb1b212019-03-07 21:15:40 -0800205TEST_F(OutputTest, setColorTransformWithNoActualChangeSkipsUpdates) {
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700206 mOutput->editState().colorTransformMatrix = kIdentity;
Lloyd Pique32cbe282018-10-19 13:09:22 -0700207
Lloyd Pique3eb1b212019-03-07 21:15:40 -0800208 // Attempting to set the same colorTransformMatrix that is already set should
209 // also skip the update.
210 CompositionRefreshArgs refreshArgs;
211 refreshArgs.colorTransformMatrix = kIdentity;
Lloyd Pique32cbe282018-10-19 13:09:22 -0700212
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700213 mOutput->setColorTransform(refreshArgs);
Lloyd Pique77f79a22019-04-29 15:55:40 -0700214
Lloyd Pique3eb1b212019-03-07 21:15:40 -0800215 // The internal state should be unchanged
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700216 EXPECT_EQ(kIdentity, mOutput->getState().colorTransformMatrix);
Lloyd Pique3eb1b212019-03-07 21:15:40 -0800217
218 // No dirty region should be set
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700219 EXPECT_THAT(mOutput->getState().dirtyRegion, RegionEq(Region()));
Lloyd Pique3eb1b212019-03-07 21:15:40 -0800220}
221
222TEST_F(OutputTest, setColorTransformPerformsUpdateToIdentity) {
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700223 mOutput->editState().colorTransformMatrix = kNonIdentityHalf;
Lloyd Pique3eb1b212019-03-07 21:15:40 -0800224
225 // Setting a different colorTransformMatrix should perform the update.
226 CompositionRefreshArgs refreshArgs;
227 refreshArgs.colorTransformMatrix = kIdentity;
228
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700229 mOutput->setColorTransform(refreshArgs);
Lloyd Pique3eb1b212019-03-07 21:15:40 -0800230
231 // The internal state should have been updated
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700232 EXPECT_EQ(kIdentity, mOutput->getState().colorTransformMatrix);
Lloyd Pique3eb1b212019-03-07 21:15:40 -0800233
234 // The dirtyRegion should be set to the full display size
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700235 EXPECT_THAT(mOutput->getState().dirtyRegion, RegionEq(Region(kDefaultDisplaySize)));
Lloyd Pique3eb1b212019-03-07 21:15:40 -0800236}
Lloyd Pique77f79a22019-04-29 15:55:40 -0700237
Lloyd Pique3eb1b212019-03-07 21:15:40 -0800238TEST_F(OutputTest, setColorTransformPerformsUpdateForIdentityToHalf) {
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700239 mOutput->editState().colorTransformMatrix = kIdentity;
Lloyd Pique77f79a22019-04-29 15:55:40 -0700240
Lloyd Pique3eb1b212019-03-07 21:15:40 -0800241 // Setting a different colorTransformMatrix should perform the update.
242 CompositionRefreshArgs refreshArgs;
243 refreshArgs.colorTransformMatrix = kNonIdentityHalf;
Lloyd Pique77f79a22019-04-29 15:55:40 -0700244
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700245 mOutput->setColorTransform(refreshArgs);
Lloyd Piqueef958122019-02-05 18:00:12 -0800246
Lloyd Pique3eb1b212019-03-07 21:15:40 -0800247 // The internal state should have been updated
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700248 EXPECT_EQ(kNonIdentityHalf, mOutput->getState().colorTransformMatrix);
Lloyd Pique3eb1b212019-03-07 21:15:40 -0800249
250 // The dirtyRegion should be set to the full display size
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700251 EXPECT_THAT(mOutput->getState().dirtyRegion, RegionEq(Region(kDefaultDisplaySize)));
Lloyd Pique3eb1b212019-03-07 21:15:40 -0800252}
253
254TEST_F(OutputTest, setColorTransformPerformsUpdateForHalfToQuarter) {
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700255 mOutput->editState().colorTransformMatrix = kNonIdentityHalf;
Lloyd Pique3eb1b212019-03-07 21:15:40 -0800256
257 // Setting a different colorTransformMatrix should perform the update.
258 CompositionRefreshArgs refreshArgs;
259 refreshArgs.colorTransformMatrix = kNonIdentityQuarter;
260
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700261 mOutput->setColorTransform(refreshArgs);
Lloyd Pique3eb1b212019-03-07 21:15:40 -0800262
263 // The internal state should have been updated
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700264 EXPECT_EQ(kNonIdentityQuarter, mOutput->getState().colorTransformMatrix);
Lloyd Pique3eb1b212019-03-07 21:15:40 -0800265
266 // The dirtyRegion should be set to the full display size
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700267 EXPECT_THAT(mOutput->getState().dirtyRegion, RegionEq(Region(kDefaultDisplaySize)));
Lloyd Pique32cbe282018-10-19 13:09:22 -0700268}
269
Lloyd Pique66d68602019-02-13 14:23:31 -0800270/*
Lloyd Pique32cbe282018-10-19 13:09:22 -0700271 * Output::setColorMode
272 */
273
Lloyd Piqueef958122019-02-05 18:00:12 -0800274TEST_F(OutputTest, setColorModeSetsStateAndDirtiesOutputIfChanged) {
Lloyd Pique6a3b4462019-03-07 20:58:12 -0800275 using ColorProfile = Output::ColorProfile;
276
Lloyd Piquef5275482019-01-29 18:42:42 -0800277 EXPECT_CALL(*mDisplayColorProfile,
278 getTargetDataspace(ui::ColorMode::DISPLAY_P3, ui::Dataspace::DISPLAY_P3,
279 ui::Dataspace::UNKNOWN))
280 .WillOnce(Return(ui::Dataspace::UNKNOWN));
Lloyd Piqueef958122019-02-05 18:00:12 -0800281 EXPECT_CALL(*mRenderSurface, setBufferDataspace(ui::Dataspace::DISPLAY_P3)).Times(1);
Lloyd Pique31cb2942018-10-19 17:23:03 -0700282
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700283 mOutput->setColorProfile(ColorProfile{ui::ColorMode::DISPLAY_P3, ui::Dataspace::DISPLAY_P3,
284 ui::RenderIntent::TONE_MAP_COLORIMETRIC,
285 ui::Dataspace::UNKNOWN});
Lloyd Pique32cbe282018-10-19 13:09:22 -0700286
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700287 EXPECT_EQ(ui::ColorMode::DISPLAY_P3, mOutput->getState().colorMode);
288 EXPECT_EQ(ui::Dataspace::DISPLAY_P3, mOutput->getState().dataspace);
289 EXPECT_EQ(ui::RenderIntent::TONE_MAP_COLORIMETRIC, mOutput->getState().renderIntent);
290 EXPECT_EQ(ui::Dataspace::UNKNOWN, mOutput->getState().targetDataspace);
Lloyd Piquef5275482019-01-29 18:42:42 -0800291
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700292 EXPECT_THAT(mOutput->getState().dirtyRegion, RegionEq(Region(kDefaultDisplaySize)));
Lloyd Piqueef958122019-02-05 18:00:12 -0800293}
294
295TEST_F(OutputTest, setColorModeDoesNothingIfNoChange) {
Lloyd Pique6a3b4462019-03-07 20:58:12 -0800296 using ColorProfile = Output::ColorProfile;
297
Lloyd Piquef5275482019-01-29 18:42:42 -0800298 EXPECT_CALL(*mDisplayColorProfile,
299 getTargetDataspace(ui::ColorMode::DISPLAY_P3, ui::Dataspace::DISPLAY_P3,
300 ui::Dataspace::UNKNOWN))
301 .WillOnce(Return(ui::Dataspace::UNKNOWN));
302
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700303 mOutput->editState().colorMode = ui::ColorMode::DISPLAY_P3;
304 mOutput->editState().dataspace = ui::Dataspace::DISPLAY_P3;
305 mOutput->editState().renderIntent = ui::RenderIntent::TONE_MAP_COLORIMETRIC;
306 mOutput->editState().targetDataspace = ui::Dataspace::UNKNOWN;
Lloyd Piqueef958122019-02-05 18:00:12 -0800307
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700308 mOutput->setColorProfile(ColorProfile{ui::ColorMode::DISPLAY_P3, ui::Dataspace::DISPLAY_P3,
309 ui::RenderIntent::TONE_MAP_COLORIMETRIC,
310 ui::Dataspace::UNKNOWN});
Lloyd Piqueef958122019-02-05 18:00:12 -0800311
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700312 EXPECT_THAT(mOutput->getState().dirtyRegion, RegionEq(Region()));
Lloyd Pique32cbe282018-10-19 13:09:22 -0700313}
314
Lloyd Pique66d68602019-02-13 14:23:31 -0800315/*
Lloyd Pique31cb2942018-10-19 17:23:03 -0700316 * Output::setRenderSurface()
317 */
318
319TEST_F(OutputTest, setRenderSurfaceResetsBounds) {
320 const ui::Size newDisplaySize{640, 480};
321
322 mock::RenderSurface* renderSurface = new StrictMock<mock::RenderSurface>();
323 EXPECT_CALL(*renderSurface, getSize()).WillOnce(ReturnRef(newDisplaySize));
324
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700325 mOutput->setRenderSurface(std::unique_ptr<RenderSurface>(renderSurface));
Lloyd Pique31cb2942018-10-19 17:23:03 -0700326
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700327 EXPECT_EQ(Rect(newDisplaySize), mOutput->getState().bounds);
Lloyd Pique31cb2942018-10-19 17:23:03 -0700328}
329
Lloyd Pique66d68602019-02-13 14:23:31 -0800330/*
Alec Mourie7d1d4a2019-02-05 01:13:46 +0000331 * Output::getDirtyRegion()
Lloyd Pique32cbe282018-10-19 13:09:22 -0700332 */
333
Alec Mourie7d1d4a2019-02-05 01:13:46 +0000334TEST_F(OutputTest, getDirtyRegionWithRepaintEverythingTrue) {
335 const Rect viewport{100, 200};
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700336 mOutput->editState().viewport = viewport;
337 mOutput->editState().dirtyRegion.set(50, 300);
Lloyd Pique32cbe282018-10-19 13:09:22 -0700338
339 {
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700340 Region result = mOutput->getDirtyRegion(true);
Lloyd Pique32cbe282018-10-19 13:09:22 -0700341
Alec Mourie7d1d4a2019-02-05 01:13:46 +0000342 EXPECT_THAT(result, RegionEq(Region(viewport)));
Lloyd Pique32cbe282018-10-19 13:09:22 -0700343 }
344}
345
Alec Mourie7d1d4a2019-02-05 01:13:46 +0000346TEST_F(OutputTest, getDirtyRegionWithRepaintEverythingFalse) {
347 const Rect viewport{100, 200};
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700348 mOutput->editState().viewport = viewport;
349 mOutput->editState().dirtyRegion.set(50, 300);
Lloyd Pique32cbe282018-10-19 13:09:22 -0700350
351 {
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700352 Region result = mOutput->getDirtyRegion(false);
Lloyd Pique32cbe282018-10-19 13:09:22 -0700353
354 // The dirtyRegion should be clipped to the display bounds.
355 EXPECT_THAT(result, RegionEq(Region(Rect(50, 200))));
356 }
Lloyd Pique32cbe282018-10-19 13:09:22 -0700357}
358
Lloyd Pique66d68602019-02-13 14:23:31 -0800359/*
Lloyd Piqueef36b002019-01-23 17:52:04 -0800360 * Output::belongsInOutput()
361 */
362
363TEST_F(OutputTest, belongsInOutputFiltersAsExpected) {
364 const uint32_t layerStack1 = 123u;
365 const uint32_t layerStack2 = 456u;
366
367 // If the output accepts layerStack1 and internal-only layers....
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700368 mOutput->setLayerStackFilter(layerStack1, true);
Lloyd Piqueef36b002019-01-23 17:52:04 -0800369
Lloyd Piquec6687342019-03-07 21:34:57 -0800370 // A layer with no layerStack does not belong to it, internal-only or not.
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700371 EXPECT_FALSE(mOutput->belongsInOutput(std::nullopt, false));
372 EXPECT_FALSE(mOutput->belongsInOutput(std::nullopt, true));
Lloyd Piquec6687342019-03-07 21:34:57 -0800373
Lloyd Piqueef36b002019-01-23 17:52:04 -0800374 // Any layer with layerStack1 belongs to it, internal-only or not.
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700375 EXPECT_TRUE(mOutput->belongsInOutput(layerStack1, false));
376 EXPECT_TRUE(mOutput->belongsInOutput(layerStack1, true));
377 EXPECT_FALSE(mOutput->belongsInOutput(layerStack2, true));
378 EXPECT_FALSE(mOutput->belongsInOutput(layerStack2, false));
Lloyd Piqueef36b002019-01-23 17:52:04 -0800379
380 // If the output accepts layerStack21 but not internal-only layers...
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700381 mOutput->setLayerStackFilter(layerStack1, false);
Lloyd Piqueef36b002019-01-23 17:52:04 -0800382
383 // Only non-internal layers with layerStack1 belong to it.
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700384 EXPECT_TRUE(mOutput->belongsInOutput(layerStack1, false));
385 EXPECT_FALSE(mOutput->belongsInOutput(layerStack1, true));
386 EXPECT_FALSE(mOutput->belongsInOutput(layerStack2, true));
387 EXPECT_FALSE(mOutput->belongsInOutput(layerStack2, false));
Lloyd Piqueef36b002019-01-23 17:52:04 -0800388}
389
Lloyd Pique66c20c42019-03-07 21:44:02 -0800390TEST_F(OutputTest, belongsInOutputFiltersLayersAsExpected) {
391 StrictMock<mock::Layer> layer;
Lloyd Pique9755fb72019-03-26 14:44:40 -0700392 LayerFECompositionState layerFEState;
Lloyd Pique66c20c42019-03-07 21:44:02 -0800393
Lloyd Pique9755fb72019-03-26 14:44:40 -0700394 EXPECT_CALL(layer, getFEState()).WillRepeatedly(ReturnRef(layerFEState));
Lloyd Pique66c20c42019-03-07 21:44:02 -0800395
396 const uint32_t layerStack1 = 123u;
397 const uint32_t layerStack2 = 456u;
398
399 // If the output accepts layerStack1 and internal-only layers....
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700400 mOutput->setLayerStackFilter(layerStack1, true);
Lloyd Pique66c20c42019-03-07 21:44:02 -0800401
402 // A null layer pointer does not belong to the output
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700403 EXPECT_FALSE(mOutput->belongsInOutput(nullptr));
Lloyd Pique66c20c42019-03-07 21:44:02 -0800404
405 // A layer with no layerStack does not belong to it, internal-only or not.
Lloyd Pique9755fb72019-03-26 14:44:40 -0700406 layerFEState.layerStackId = std::nullopt;
407 layerFEState.internalOnly = false;
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700408 EXPECT_FALSE(mOutput->belongsInOutput(&layer));
Lloyd Pique66c20c42019-03-07 21:44:02 -0800409
Lloyd Pique9755fb72019-03-26 14:44:40 -0700410 layerFEState.layerStackId = std::nullopt;
411 layerFEState.internalOnly = true;
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700412 EXPECT_FALSE(mOutput->belongsInOutput(&layer));
Lloyd Pique66c20c42019-03-07 21:44:02 -0800413
414 // Any layer with layerStack1 belongs to it, internal-only or not.
Lloyd Pique9755fb72019-03-26 14:44:40 -0700415 layerFEState.layerStackId = layerStack1;
416 layerFEState.internalOnly = false;
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700417 EXPECT_TRUE(mOutput->belongsInOutput(&layer));
Lloyd Pique66c20c42019-03-07 21:44:02 -0800418
Lloyd Pique9755fb72019-03-26 14:44:40 -0700419 layerFEState.layerStackId = layerStack1;
420 layerFEState.internalOnly = true;
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700421 EXPECT_TRUE(mOutput->belongsInOutput(&layer));
Lloyd Pique66c20c42019-03-07 21:44:02 -0800422
Lloyd Pique9755fb72019-03-26 14:44:40 -0700423 layerFEState.layerStackId = layerStack2;
424 layerFEState.internalOnly = true;
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700425 EXPECT_FALSE(mOutput->belongsInOutput(&layer));
Lloyd Pique66c20c42019-03-07 21:44:02 -0800426
Lloyd Pique9755fb72019-03-26 14:44:40 -0700427 layerFEState.layerStackId = layerStack2;
428 layerFEState.internalOnly = false;
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700429 EXPECT_FALSE(mOutput->belongsInOutput(&layer));
Lloyd Pique66c20c42019-03-07 21:44:02 -0800430
431 // If the output accepts layerStack1 but not internal-only layers...
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700432 mOutput->setLayerStackFilter(layerStack1, false);
Lloyd Pique66c20c42019-03-07 21:44:02 -0800433
434 // A null layer pointer does not belong to the output
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700435 EXPECT_FALSE(mOutput->belongsInOutput(nullptr));
Lloyd Pique66c20c42019-03-07 21:44:02 -0800436
437 // Only non-internal layers with layerStack1 belong to it.
Lloyd Pique9755fb72019-03-26 14:44:40 -0700438 layerFEState.layerStackId = layerStack1;
439 layerFEState.internalOnly = false;
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700440 EXPECT_TRUE(mOutput->belongsInOutput(&layer));
Lloyd Pique66c20c42019-03-07 21:44:02 -0800441
Lloyd Pique9755fb72019-03-26 14:44:40 -0700442 layerFEState.layerStackId = layerStack1;
443 layerFEState.internalOnly = true;
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700444 EXPECT_FALSE(mOutput->belongsInOutput(&layer));
Lloyd Pique66c20c42019-03-07 21:44:02 -0800445
Lloyd Pique9755fb72019-03-26 14:44:40 -0700446 layerFEState.layerStackId = layerStack2;
447 layerFEState.internalOnly = true;
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700448 EXPECT_FALSE(mOutput->belongsInOutput(&layer));
Lloyd Pique66c20c42019-03-07 21:44:02 -0800449
Lloyd Pique9755fb72019-03-26 14:44:40 -0700450 layerFEState.layerStackId = layerStack2;
451 layerFEState.internalOnly = false;
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700452 EXPECT_FALSE(mOutput->belongsInOutput(&layer));
Lloyd Pique66c20c42019-03-07 21:44:02 -0800453}
454
Lloyd Pique66d68602019-02-13 14:23:31 -0800455/*
Lloyd Piquecc01a452018-12-04 17:24:00 -0800456 * Output::getOutputLayerForLayer()
457 */
458
459TEST_F(OutputTest, getOutputLayerForLayerWorks) {
460 mock::OutputLayer* outputLayer1 = new StrictMock<mock::OutputLayer>();
461 mock::OutputLayer* outputLayer2 = new StrictMock<mock::OutputLayer>();
462
Lloyd Pique01c77c12019-04-17 12:48:32 -0700463 mOutput->injectOutputLayerForTest(std::unique_ptr<OutputLayer>(outputLayer1));
464 mOutput->injectOutputLayerForTest(nullptr);
465 mOutput->injectOutputLayerForTest(std::unique_ptr<OutputLayer>(outputLayer2));
Lloyd Piquecc01a452018-12-04 17:24:00 -0800466
467 StrictMock<mock::Layer> layer;
468 StrictMock<mock::Layer> otherLayer;
469
470 // If the input layer matches the first OutputLayer, it will be returned.
471 EXPECT_CALL(*outputLayer1, getLayer()).WillOnce(ReturnRef(layer));
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700472 EXPECT_EQ(outputLayer1, mOutput->getOutputLayerForLayer(&layer));
Lloyd Piquecc01a452018-12-04 17:24:00 -0800473
474 // If the input layer matches the second OutputLayer, it will be returned.
475 EXPECT_CALL(*outputLayer1, getLayer()).WillOnce(ReturnRef(otherLayer));
476 EXPECT_CALL(*outputLayer2, getLayer()).WillOnce(ReturnRef(layer));
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700477 EXPECT_EQ(outputLayer2, mOutput->getOutputLayerForLayer(&layer));
Lloyd Piquecc01a452018-12-04 17:24:00 -0800478
479 // If the input layer does not match an output layer, null will be returned.
480 EXPECT_CALL(*outputLayer1, getLayer()).WillOnce(ReturnRef(otherLayer));
481 EXPECT_CALL(*outputLayer2, getLayer()).WillOnce(ReturnRef(otherLayer));
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700482 EXPECT_EQ(nullptr, mOutput->getOutputLayerForLayer(&layer));
Lloyd Piquecc01a452018-12-04 17:24:00 -0800483}
484
Lloyd Pique66d68602019-02-13 14:23:31 -0800485/*
486 * Output::prepareFrame()
487 */
488
489struct OutputPrepareFrameTest : public testing::Test {
490 struct OutputPartialMock : public impl::Output {
Lloyd Pique66d68602019-02-13 14:23:31 -0800491 // Sets up the helper functions called by prepareFrame to use a mock
492 // implementations.
493 MOCK_METHOD0(chooseCompositionStrategy, void());
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700494
495 // compositionengine::Output overrides
496 const OutputCompositionState& getState() const override { return mState; }
497 OutputCompositionState& editState() override { return mState; }
498
499 // These need implementations though are not expected to be called.
Lloyd Pique01c77c12019-04-17 12:48:32 -0700500 MOCK_CONST_METHOD0(getOutputLayerCount, size_t());
501 MOCK_CONST_METHOD1(getOutputLayerOrderedByZByIndex,
502 compositionengine::OutputLayer*(size_t));
503 MOCK_METHOD3(ensureOutputLayer,
504 compositionengine::OutputLayer*(
505 std::optional<size_t>,
506 const std::shared_ptr<compositionengine::Layer>&, const sp<LayerFE>&));
507 MOCK_METHOD0(finalizePendingOutputLayers, void());
508 MOCK_METHOD0(clearOutputLayers, void());
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700509 MOCK_CONST_METHOD1(dumpState, void(std::string&));
510 MOCK_CONST_METHOD0(getCompositionEngine, const CompositionEngine&());
Lloyd Pique01c77c12019-04-17 12:48:32 -0700511 MOCK_METHOD2(injectOutputLayerForTest,
512 compositionengine::OutputLayer*(
513 const std::shared_ptr<compositionengine::Layer>&, const sp<LayerFE>&));
514 MOCK_METHOD1(injectOutputLayerForTest, void(std::unique_ptr<OutputLayer>));
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700515
516 impl::OutputCompositionState mState;
Lloyd Pique66d68602019-02-13 14:23:31 -0800517 };
518
519 OutputPrepareFrameTest() {
520 mOutput.setDisplayColorProfileForTest(
521 std::unique_ptr<DisplayColorProfile>(mDisplayColorProfile));
522 mOutput.setRenderSurfaceForTest(std::unique_ptr<RenderSurface>(mRenderSurface));
523 }
524
525 StrictMock<mock::CompositionEngine> mCompositionEngine;
526 mock::DisplayColorProfile* mDisplayColorProfile = new StrictMock<mock::DisplayColorProfile>();
527 mock::RenderSurface* mRenderSurface = new StrictMock<mock::RenderSurface>();
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700528 StrictMock<OutputPartialMock> mOutput;
Lloyd Pique66d68602019-02-13 14:23:31 -0800529};
530
531TEST_F(OutputPrepareFrameTest, takesEarlyOutIfNotEnabled) {
532 mOutput.editState().isEnabled = false;
533
534 mOutput.prepareFrame();
535}
536
537TEST_F(OutputPrepareFrameTest, delegatesToChooseCompositionStrategyAndRenderSurface) {
538 mOutput.editState().isEnabled = true;
539 mOutput.editState().usesClientComposition = false;
540 mOutput.editState().usesDeviceComposition = true;
541
542 EXPECT_CALL(mOutput, chooseCompositionStrategy()).Times(1);
543 EXPECT_CALL(*mRenderSurface, prepareFrame(false, true));
544
545 mOutput.prepareFrame();
546}
547
548// Note: Use OutputTest and not OutputPrepareFrameTest, so the real
549// base chooseCompositionStrategy() is invoked.
550TEST_F(OutputTest, prepareFrameSetsClientCompositionOnlyByDefault) {
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700551 mOutput->editState().isEnabled = true;
552 mOutput->editState().usesClientComposition = false;
553 mOutput->editState().usesDeviceComposition = true;
Lloyd Pique66d68602019-02-13 14:23:31 -0800554
555 EXPECT_CALL(*mRenderSurface, prepareFrame(true, false));
556
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700557 mOutput->prepareFrame();
Lloyd Pique66d68602019-02-13 14:23:31 -0800558
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700559 EXPECT_TRUE(mOutput->getState().usesClientComposition);
560 EXPECT_FALSE(mOutput->getState().usesDeviceComposition);
Lloyd Pique66d68602019-02-13 14:23:31 -0800561}
562
Lloyd Pique56eba802019-08-28 15:45:25 -0700563/*
564 * Output::composeSurfaces()
565 */
566
567struct OutputComposeSurfacesTest : public testing::Test {
568 static constexpr uint32_t kDefaultOutputOrientation = TR_IDENT;
569 static constexpr ui::Dataspace kDefaultOutputDataspace = ui::Dataspace::DISPLAY_P3;
570
571 static const Rect kDefaultOutputFrame;
572 static const Rect kDefaultOutputViewport;
573 static const Rect kDefaultOutputScissor;
574 static const mat4 kDefaultColorTransformMat;
575
576 struct OutputPartialMock : public impl::Output {
Lloyd Pique56eba802019-08-28 15:45:25 -0700577 // Sets up the helper functions called by composeSurfaces to use a mock
578 // implementations.
579 MOCK_CONST_METHOD0(getSkipColorTransform, bool());
580 MOCK_METHOD2(generateClientCompositionRequests,
581 std::vector<renderengine::LayerSettings>(bool, Region&));
582 MOCK_METHOD2(appendRegionFlashRequests,
583 void(const Region&, std::vector<renderengine::LayerSettings>&));
584 MOCK_METHOD1(setExpensiveRenderingExpected, void(bool));
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700585
586 // compositionengine::Output overrides
587 const OutputCompositionState& getState() const override { return mState; }
588 OutputCompositionState& editState() override { return mState; }
589
590 // These need implementations though are not expected to be called.
Lloyd Pique01c77c12019-04-17 12:48:32 -0700591 MOCK_CONST_METHOD0(getOutputLayerCount, size_t());
592 MOCK_CONST_METHOD1(getOutputLayerOrderedByZByIndex,
593 compositionengine::OutputLayer*(size_t));
594 MOCK_METHOD3(ensureOutputLayer,
595 compositionengine::OutputLayer*(
596 std::optional<size_t>,
597 const std::shared_ptr<compositionengine::Layer>&, const sp<LayerFE>&));
598 MOCK_METHOD0(finalizePendingOutputLayers, void());
599 MOCK_METHOD0(clearOutputLayers, void());
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700600 MOCK_CONST_METHOD1(dumpState, void(std::string&));
601 MOCK_CONST_METHOD0(getCompositionEngine, const CompositionEngine&());
Lloyd Pique01c77c12019-04-17 12:48:32 -0700602 MOCK_METHOD2(injectOutputLayerForTest,
603 compositionengine::OutputLayer*(
604 const std::shared_ptr<compositionengine::Layer>&, const sp<LayerFE>&));
605 MOCK_METHOD1(injectOutputLayerForTest, void(std::unique_ptr<OutputLayer>));
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700606
607 impl::OutputCompositionState mState;
Lloyd Pique56eba802019-08-28 15:45:25 -0700608 };
609
610 OutputComposeSurfacesTest() {
611 mOutput.setDisplayColorProfileForTest(
612 std::unique_ptr<DisplayColorProfile>(mDisplayColorProfile));
613 mOutput.setRenderSurfaceForTest(std::unique_ptr<RenderSurface>(mRenderSurface));
614
Lloyd Pique56eba802019-08-28 15:45:25 -0700615 mOutput.editState().frame = kDefaultOutputFrame;
616 mOutput.editState().viewport = kDefaultOutputViewport;
617 mOutput.editState().scissor = kDefaultOutputScissor;
618 mOutput.editState().transform = ui::Transform{kDefaultOutputOrientation};
619 mOutput.editState().orientation = kDefaultOutputOrientation;
620 mOutput.editState().dataspace = kDefaultOutputDataspace;
Lloyd Pique3eb1b212019-03-07 21:15:40 -0800621 mOutput.editState().colorTransformMatrix = kDefaultColorTransformMat;
Lloyd Pique56eba802019-08-28 15:45:25 -0700622 mOutput.editState().isSecure = true;
623 mOutput.editState().needsFiltering = false;
624 mOutput.editState().usesClientComposition = true;
625 mOutput.editState().usesDeviceComposition = false;
626
Lloyd Pique01c77c12019-04-17 12:48:32 -0700627 EXPECT_CALL(mOutput, getOutputLayerCount()).WillRepeatedly(Return(2u));
628 EXPECT_CALL(mOutput, getOutputLayerOrderedByZByIndex(0u))
629 .WillRepeatedly(Return(&mOutputLayer1));
630 EXPECT_CALL(mOutput, getOutputLayerOrderedByZByIndex(1u))
631 .WillRepeatedly(Return(&mOutputLayer2));
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700632 EXPECT_CALL(mOutput, getCompositionEngine()).WillRepeatedly(ReturnRef(mCompositionEngine));
Lloyd Pique56eba802019-08-28 15:45:25 -0700633 EXPECT_CALL(mCompositionEngine, getRenderEngine()).WillRepeatedly(ReturnRef(mRenderEngine));
634 }
635
636 StrictMock<mock::CompositionEngine> mCompositionEngine;
637 StrictMock<renderengine::mock::RenderEngine> mRenderEngine;
638 mock::DisplayColorProfile* mDisplayColorProfile = new StrictMock<mock::DisplayColorProfile>();
639 mock::RenderSurface* mRenderSurface = new StrictMock<mock::RenderSurface>();
Lloyd Pique01c77c12019-04-17 12:48:32 -0700640 StrictMock<mock::OutputLayer> mOutputLayer1;
641 StrictMock<mock::OutputLayer> mOutputLayer2;
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700642 StrictMock<OutputPartialMock> mOutput;
Lloyd Pique56eba802019-08-28 15:45:25 -0700643 sp<GraphicBuffer> mOutputBuffer = new GraphicBuffer();
644};
645
646const Rect OutputComposeSurfacesTest::kDefaultOutputFrame{1001, 1002, 1003, 1004};
647const Rect OutputComposeSurfacesTest::kDefaultOutputViewport{1005, 1006, 1007, 1008};
648const Rect OutputComposeSurfacesTest::kDefaultOutputScissor{1009, 1010, 1011, 1012};
649const mat4 OutputComposeSurfacesTest::kDefaultColorTransformMat{mat4() * 0.5};
650
651// TODO(b/121291683): Expand unit test coverage for composeSurfaces beyond these
652// basic tests.
653
654TEST_F(OutputComposeSurfacesTest, doesNothingIfNoClientComposition) {
655 mOutput.editState().usesClientComposition = false;
656
657 Region debugRegion;
Lloyd Piqued3d69882019-02-28 16:03:46 -0800658 std::optional<base::unique_fd> readyFence = mOutput.composeSurfaces(debugRegion);
659 EXPECT_TRUE(readyFence);
Lloyd Pique56eba802019-08-28 15:45:25 -0700660}
661
662TEST_F(OutputComposeSurfacesTest, worksIfNoClientLayersQueued) {
663 const Region kDebugRegion{Rect{100, 101, 102, 103}};
664
665 constexpr float kDefaultMaxLuminance = 1.0f;
666 constexpr float kDefaultAvgLuminance = 0.7f;
667 constexpr float kDefaultMinLuminance = 0.1f;
668 HdrCapabilities HdrCapabilities{{},
669 kDefaultMaxLuminance,
670 kDefaultAvgLuminance,
671 kDefaultMinLuminance};
672
673 EXPECT_CALL(mRenderEngine, supportsProtectedContent()).WillOnce(Return(false));
674 EXPECT_CALL(mRenderEngine, drawLayers(_, _, _, true, _, _)).Times(1);
675
676 EXPECT_CALL(*mDisplayColorProfile, hasWideColorGamut()).WillOnce(Return(true));
677 EXPECT_CALL(*mDisplayColorProfile, getHdrCapabilities()).WillOnce(ReturnRef(HdrCapabilities));
678
679 EXPECT_CALL(*mRenderSurface, dequeueBuffer(_)).WillOnce(Return(mOutputBuffer));
680
681 EXPECT_CALL(mOutput, getSkipColorTransform()).WillOnce(Return(false));
682 EXPECT_CALL(mOutput, generateClientCompositionRequests(false, _)).Times(1);
683 EXPECT_CALL(mOutput, appendRegionFlashRequests(RegionEq(kDebugRegion), _)).Times(1);
684 EXPECT_CALL(mOutput, setExpensiveRenderingExpected(true)).Times(1);
685 EXPECT_CALL(mOutput, setExpensiveRenderingExpected(false)).Times(1);
686
Lloyd Piqued3d69882019-02-28 16:03:46 -0800687 std::optional<base::unique_fd> readyFence = mOutput.composeSurfaces(kDebugRegion);
688 EXPECT_TRUE(readyFence);
Lloyd Pique56eba802019-08-28 15:45:25 -0700689}
690
691/*
692 * Output::generateClientCompositionRequests()
693 */
694
695struct GenerateClientCompositionRequestsTest : public testing::Test {
696 struct OutputPartialMock : public impl::Output {
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700697 // compositionengine::Output overrides
Lloyd Pique56eba802019-08-28 15:45:25 -0700698
699 std::vector<renderengine::LayerSettings> generateClientCompositionRequests(
700 bool supportsProtectedContent, Region& clearRegion) override {
701 return impl::Output::generateClientCompositionRequests(supportsProtectedContent,
702 clearRegion);
703 }
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700704
705 const OutputCompositionState& getState() const override { return mState; }
706 OutputCompositionState& editState() override { return mState; }
707
708 // These need implementations though are not expected to be called.
Lloyd Pique01c77c12019-04-17 12:48:32 -0700709 MOCK_CONST_METHOD0(getOutputLayerCount, size_t());
710 MOCK_CONST_METHOD1(getOutputLayerOrderedByZByIndex,
711 compositionengine::OutputLayer*(size_t));
712 MOCK_METHOD3(ensureOutputLayer,
713 compositionengine::OutputLayer*(
714 std::optional<size_t>,
715 const std::shared_ptr<compositionengine::Layer>&, const sp<LayerFE>&));
716 MOCK_METHOD0(finalizePendingOutputLayers, void());
717 MOCK_METHOD0(clearOutputLayers, void());
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700718 MOCK_CONST_METHOD1(dumpState, void(std::string&));
719 MOCK_CONST_METHOD0(getCompositionEngine, const CompositionEngine&());
Lloyd Pique01c77c12019-04-17 12:48:32 -0700720 MOCK_METHOD2(injectOutputLayerForTest,
721 compositionengine::OutputLayer*(
722 const std::shared_ptr<compositionengine::Layer>&, const sp<LayerFE>&));
723 MOCK_METHOD1(injectOutputLayerForTest, void(std::unique_ptr<OutputLayer>));
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700724
725 impl::OutputCompositionState mState;
Lloyd Pique56eba802019-08-28 15:45:25 -0700726 };
727
728 GenerateClientCompositionRequestsTest() {
729 mOutput.setDisplayColorProfileForTest(
730 std::unique_ptr<DisplayColorProfile>(mDisplayColorProfile));
731 mOutput.setRenderSurfaceForTest(std::unique_ptr<RenderSurface>(mRenderSurface));
732 }
733
Lloyd Pique56eba802019-08-28 15:45:25 -0700734 mock::DisplayColorProfile* mDisplayColorProfile = new StrictMock<mock::DisplayColorProfile>();
735 mock::RenderSurface* mRenderSurface = new StrictMock<mock::RenderSurface>();
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700736 StrictMock<OutputPartialMock> mOutput;
Lloyd Pique56eba802019-08-28 15:45:25 -0700737};
738
739// TODO(b/121291683): Add more unit test coverage for generateClientCompositionRequests
740
741TEST_F(GenerateClientCompositionRequestsTest, worksForLandscapeModeSplitScreen) {
742 // In split-screen landscape mode, the screen is rotated 90 degrees, with
743 // one layer on the left covering the left side of the output, and one layer
744 // on the right covering that side of the output.
745
Lloyd Pique01c77c12019-04-17 12:48:32 -0700746 StrictMock<mock::OutputLayer> leftOutputLayer;
747 StrictMock<mock::OutputLayer> rightOutputLayer;
Lloyd Pique56eba802019-08-28 15:45:25 -0700748
749 StrictMock<mock::Layer> leftLayer;
750 StrictMock<mock::LayerFE> leftLayerFE;
751 StrictMock<mock::Layer> rightLayer;
752 StrictMock<mock::LayerFE> rightLayerFE;
753
754 impl::OutputLayerCompositionState leftOutputLayerState;
755 leftOutputLayerState.clearClientTarget = false;
Lloyd Piquea2468662019-03-07 21:31:06 -0800756 leftOutputLayerState.visibleRegion = Region{Rect{0, 0, 1000, 1000}};
Lloyd Pique56eba802019-08-28 15:45:25 -0700757
Lloyd Pique9755fb72019-03-26 14:44:40 -0700758 LayerFECompositionState leftLayerFEState;
759 leftLayerFEState.isOpaque = true;
Lloyd Pique56eba802019-08-28 15:45:25 -0700760
761 const half3 leftLayerColor{1.f, 0.f, 0.f};
762 renderengine::LayerSettings leftLayerRESettings;
763 leftLayerRESettings.source.solidColor = leftLayerColor;
764
765 impl::OutputLayerCompositionState rightOutputLayerState;
766 rightOutputLayerState.clearClientTarget = false;
Lloyd Piquea2468662019-03-07 21:31:06 -0800767 rightOutputLayerState.visibleRegion = Region{Rect{1000, 0, 2000, 1000}};
Lloyd Pique56eba802019-08-28 15:45:25 -0700768
Lloyd Pique9755fb72019-03-26 14:44:40 -0700769 LayerFECompositionState rightLayerFEState;
770 rightLayerFEState.isOpaque = true;
Lloyd Pique56eba802019-08-28 15:45:25 -0700771
772 const half3 rightLayerColor{0.f, 1.f, 0.f};
773 renderengine::LayerSettings rightLayerRESettings;
774 rightLayerRESettings.source.solidColor = rightLayerColor;
775
Lloyd Pique01c77c12019-04-17 12:48:32 -0700776 EXPECT_CALL(leftOutputLayer, getState()).WillRepeatedly(ReturnRef(leftOutputLayerState));
777 EXPECT_CALL(leftOutputLayer, getLayer()).WillRepeatedly(ReturnRef(leftLayer));
778 EXPECT_CALL(leftOutputLayer, getLayerFE()).WillRepeatedly(ReturnRef(leftLayerFE));
779 EXPECT_CALL(leftOutputLayer, requiresClientComposition()).WillRepeatedly(Return(true));
780 EXPECT_CALL(leftOutputLayer, needsFiltering()).WillRepeatedly(Return(false));
Lloyd Pique9755fb72019-03-26 14:44:40 -0700781 EXPECT_CALL(leftLayer, getFEState()).WillRepeatedly(ReturnRef(leftLayerFEState));
Lloyd Pique56eba802019-08-28 15:45:25 -0700782 EXPECT_CALL(leftLayerFE, prepareClientComposition(_)).WillOnce(Return(leftLayerRESettings));
783
Lloyd Pique01c77c12019-04-17 12:48:32 -0700784 EXPECT_CALL(rightOutputLayer, getState()).WillRepeatedly(ReturnRef(rightOutputLayerState));
785 EXPECT_CALL(rightOutputLayer, getLayer()).WillRepeatedly(ReturnRef(rightLayer));
786 EXPECT_CALL(rightOutputLayer, getLayerFE()).WillRepeatedly(ReturnRef(rightLayerFE));
787 EXPECT_CALL(rightOutputLayer, requiresClientComposition()).WillRepeatedly(Return(true));
788 EXPECT_CALL(rightOutputLayer, needsFiltering()).WillRepeatedly(Return(false));
Lloyd Pique9755fb72019-03-26 14:44:40 -0700789 EXPECT_CALL(rightLayer, getFEState()).WillRepeatedly(ReturnRef(rightLayerFEState));
Lloyd Pique56eba802019-08-28 15:45:25 -0700790 EXPECT_CALL(rightLayerFE, prepareClientComposition(_)).WillOnce(Return(rightLayerRESettings));
791
Lloyd Pique01c77c12019-04-17 12:48:32 -0700792 EXPECT_CALL(mOutput, getOutputLayerCount()).WillRepeatedly(Return(2u));
793 EXPECT_CALL(mOutput, getOutputLayerOrderedByZByIndex(0u))
794 .WillRepeatedly(Return(&leftOutputLayer));
795 EXPECT_CALL(mOutput, getOutputLayerOrderedByZByIndex(1u))
796 .WillRepeatedly(Return(&rightOutputLayer));
Lloyd Pique56eba802019-08-28 15:45:25 -0700797
798 const Rect kPortraitFrame(0, 0, 1000, 2000);
799 const Rect kPortraitViewport(0, 0, 2000, 1000);
800 const Rect kPortraitScissor(0, 0, 1000, 2000);
801 const uint32_t kPortraitOrientation = TR_ROT_90;
802
803 mOutput.editState().frame = kPortraitFrame;
804 mOutput.editState().viewport = kPortraitViewport;
805 mOutput.editState().scissor = kPortraitScissor;
806 mOutput.editState().transform = ui::Transform{kPortraitOrientation};
807 mOutput.editState().orientation = kPortraitOrientation;
808 mOutput.editState().needsFiltering = true;
809 mOutput.editState().isSecure = false;
810
811 constexpr bool supportsProtectedContent = false;
812 Region clearRegion;
813 auto requests =
814 mOutput.generateClientCompositionRequests(supportsProtectedContent, clearRegion);
815
816 ASSERT_EQ(2u, requests.size());
817 EXPECT_EQ(leftLayerColor, requests[0].source.solidColor);
818 EXPECT_EQ(rightLayerColor, requests[1].source.solidColor);
819}
820
821TEST_F(GenerateClientCompositionRequestsTest, ignoresLayersThatDoNotIntersectWithViewport) {
822 // Layers whose visible region does not intersect with the viewport will be
823 // skipped when generating client composition request state.
824
Lloyd Pique01c77c12019-04-17 12:48:32 -0700825 StrictMock<mock::OutputLayer> outputLayer;
Lloyd Pique56eba802019-08-28 15:45:25 -0700826 StrictMock<mock::Layer> layer;
827 StrictMock<mock::LayerFE> layerFE;
828
829 impl::OutputLayerCompositionState outputLayerState;
830 outputLayerState.clearClientTarget = false;
Lloyd Piquea2468662019-03-07 21:31:06 -0800831 outputLayerState.visibleRegion = Region{Rect{3000, 0, 4000, 1000}};
Lloyd Pique56eba802019-08-28 15:45:25 -0700832
Lloyd Pique9755fb72019-03-26 14:44:40 -0700833 LayerFECompositionState layerFEState;
834 layerFEState.isOpaque = true;
Lloyd Pique56eba802019-08-28 15:45:25 -0700835
Lloyd Pique01c77c12019-04-17 12:48:32 -0700836 EXPECT_CALL(outputLayer, getState()).WillRepeatedly(ReturnRef(outputLayerState));
837 EXPECT_CALL(outputLayer, getLayer()).WillRepeatedly(ReturnRef(layer));
838 EXPECT_CALL(outputLayer, getLayerFE()).WillRepeatedly(ReturnRef(layerFE));
839 EXPECT_CALL(outputLayer, requiresClientComposition()).WillRepeatedly(Return(true));
840 EXPECT_CALL(outputLayer, needsFiltering()).WillRepeatedly(Return(false));
Lloyd Pique9755fb72019-03-26 14:44:40 -0700841 EXPECT_CALL(layer, getFEState()).WillRepeatedly(ReturnRef(layerFEState));
Lloyd Pique56eba802019-08-28 15:45:25 -0700842 EXPECT_CALL(layerFE, prepareClientComposition(_)).Times(0);
843
Lloyd Pique01c77c12019-04-17 12:48:32 -0700844 EXPECT_CALL(mOutput, getOutputLayerCount()).WillRepeatedly(Return(1u));
845 EXPECT_CALL(mOutput, getOutputLayerOrderedByZByIndex(0u)).WillRepeatedly(Return(&outputLayer));
Lloyd Pique56eba802019-08-28 15:45:25 -0700846
847 const Rect kPortraitFrame(0, 0, 1000, 2000);
848 const Rect kPortraitViewport(0, 0, 2000, 1000);
849 const Rect kPortraitScissor(0, 0, 1000, 2000);
850 const uint32_t kPortraitOrientation = TR_ROT_90;
851
852 mOutput.editState().frame = kPortraitFrame;
853 mOutput.editState().viewport = kPortraitViewport;
854 mOutput.editState().scissor = kPortraitScissor;
855 mOutput.editState().transform = ui::Transform{kPortraitOrientation};
856 mOutput.editState().orientation = kPortraitOrientation;
857 mOutput.editState().needsFiltering = true;
858 mOutput.editState().isSecure = false;
859
860 constexpr bool supportsProtectedContent = false;
861 Region clearRegion;
862 auto requests =
863 mOutput.generateClientCompositionRequests(supportsProtectedContent, clearRegion);
864
865 EXPECT_EQ(0u, requests.size());
866}
867
Lloyd Piquec2d54d42019-08-28 18:04:21 -0700868TEST_F(GenerateClientCompositionRequestsTest, clearsDeviceLayesAfterFirst) {
869 // If client composition is performed with some layers set to use device
870 // composition, device layers after the first layer (device or client) will
871 // clear the frame buffer if they are opaque and if that layer has a flag
872 // set to do so. The first layer is skipped as the frame buffer is already
873 // expected to be clear.
874
Lloyd Pique01c77c12019-04-17 12:48:32 -0700875 StrictMock<mock::OutputLayer> leftOutputLayer;
876 StrictMock<mock::OutputLayer> rightOutputLayer;
Lloyd Piquec2d54d42019-08-28 18:04:21 -0700877
878 StrictMock<mock::Layer> leftLayer;
879 StrictMock<mock::LayerFE> leftLayerFE;
880 StrictMock<mock::Layer> rightLayer;
881 StrictMock<mock::LayerFE> rightLayerFE;
882
883 impl::OutputLayerCompositionState leftOutputLayerState;
884 leftOutputLayerState.clearClientTarget = true;
Lloyd Piquea2468662019-03-07 21:31:06 -0800885 leftOutputLayerState.visibleRegion = Region{Rect{0, 0, 1000, 1000}};
Lloyd Piquec2d54d42019-08-28 18:04:21 -0700886
Lloyd Pique9755fb72019-03-26 14:44:40 -0700887 LayerFECompositionState leftLayerFEState;
888 leftLayerFEState.isOpaque = true;
Lloyd Piquec2d54d42019-08-28 18:04:21 -0700889
890 impl::OutputLayerCompositionState rightOutputLayerState;
891 rightOutputLayerState.clearClientTarget = true;
Lloyd Piquea2468662019-03-07 21:31:06 -0800892 rightOutputLayerState.visibleRegion = Region{Rect{1000, 0, 2000, 1000}};
Lloyd Piquec2d54d42019-08-28 18:04:21 -0700893
Lloyd Pique9755fb72019-03-26 14:44:40 -0700894 LayerFECompositionState rightLayerFEState;
895 rightLayerFEState.isOpaque = true;
Lloyd Piquec2d54d42019-08-28 18:04:21 -0700896
897 const half3 rightLayerColor{0.f, 1.f, 0.f};
898 renderengine::LayerSettings rightLayerRESettings;
899 rightLayerRESettings.geometry.boundaries = FloatRect{456, 0, 0, 0};
900 rightLayerRESettings.source.solidColor = rightLayerColor;
901
Lloyd Pique01c77c12019-04-17 12:48:32 -0700902 EXPECT_CALL(leftOutputLayer, getState()).WillRepeatedly(ReturnRef(leftOutputLayerState));
903 EXPECT_CALL(leftOutputLayer, getLayer()).WillRepeatedly(ReturnRef(leftLayer));
904 EXPECT_CALL(leftOutputLayer, getLayerFE()).WillRepeatedly(ReturnRef(leftLayerFE));
905 EXPECT_CALL(leftOutputLayer, requiresClientComposition()).WillRepeatedly(Return(false));
906 EXPECT_CALL(leftOutputLayer, needsFiltering()).WillRepeatedly(Return(false));
Lloyd Pique9755fb72019-03-26 14:44:40 -0700907 EXPECT_CALL(leftLayer, getFEState()).WillRepeatedly(ReturnRef(leftLayerFEState));
Lloyd Piquec2d54d42019-08-28 18:04:21 -0700908
Lloyd Pique01c77c12019-04-17 12:48:32 -0700909 EXPECT_CALL(rightOutputLayer, getState()).WillRepeatedly(ReturnRef(rightOutputLayerState));
910 EXPECT_CALL(rightOutputLayer, getLayer()).WillRepeatedly(ReturnRef(rightLayer));
911 EXPECT_CALL(rightOutputLayer, getLayerFE()).WillRepeatedly(ReturnRef(rightLayerFE));
912 EXPECT_CALL(rightOutputLayer, requiresClientComposition()).WillRepeatedly(Return(false));
913 EXPECT_CALL(rightOutputLayer, needsFiltering()).WillRepeatedly(Return(false));
Lloyd Pique9755fb72019-03-26 14:44:40 -0700914 EXPECT_CALL(rightLayer, getFEState()).WillRepeatedly(ReturnRef(rightLayerFEState));
Lloyd Piquec2d54d42019-08-28 18:04:21 -0700915 EXPECT_CALL(rightLayerFE, prepareClientComposition(_)).WillOnce(Return(rightLayerRESettings));
916
Lloyd Pique01c77c12019-04-17 12:48:32 -0700917 EXPECT_CALL(mOutput, getOutputLayerCount()).WillRepeatedly(Return(2u));
918 EXPECT_CALL(mOutput, getOutputLayerOrderedByZByIndex(0u))
919 .WillRepeatedly(Return(&leftOutputLayer));
920 EXPECT_CALL(mOutput, getOutputLayerOrderedByZByIndex(1u))
921 .WillRepeatedly(Return(&rightOutputLayer));
Lloyd Piquec2d54d42019-08-28 18:04:21 -0700922
923 const Rect kPortraitFrame(0, 0, 1000, 2000);
924 const Rect kPortraitViewport(0, 0, 2000, 1000);
925 const Rect kPortraitScissor(0, 0, 1000, 2000);
926 const uint32_t kPortraitOrientation = TR_ROT_90;
927
928 mOutput.editState().frame = kPortraitFrame;
929 mOutput.editState().viewport = kPortraitViewport;
930 mOutput.editState().scissor = kPortraitScissor;
931 mOutput.editState().transform = ui::Transform{kPortraitOrientation};
932 mOutput.editState().orientation = kPortraitOrientation;
933 mOutput.editState().needsFiltering = true;
934 mOutput.editState().isSecure = false;
935
936 constexpr bool supportsProtectedContent = false;
937 Region clearRegion;
938 auto requests =
939 mOutput.generateClientCompositionRequests(supportsProtectedContent, clearRegion);
940
941 const half3 clearColor{0.f, 0.f, 0.f};
942
943 ASSERT_EQ(1u, requests.size());
944 EXPECT_EQ(456.f, requests[0].geometry.boundaries.left);
945 EXPECT_EQ(clearColor, requests[0].source.solidColor);
946}
947
Lloyd Pique32cbe282018-10-19 13:09:22 -0700948} // namespace
949} // namespace android::compositionengine