blob: 7fce520000c7c263d323637f9c1a3b51eddaad0e [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/*
Alec Mourif9a2a2c2019-11-12 12:46:02 -0800486 * Output::updateAndWriteCompositionState()
487 */
488
489TEST_F(OutputTest, updateAndWriteCompositionState_takesEarlyOutIfNotEnabled) {
490 mOutput->editState().isEnabled = false;
491
492 CompositionRefreshArgs args;
493 mOutput->updateAndWriteCompositionState(args);
494}
495
496TEST_F(OutputTest, updateAndWriteCompositionState_updatesLayers) {
497 mOutput->editState().isEnabled = true;
498 mock::OutputLayer* outputLayer = new StrictMock<mock::OutputLayer>();
499 mOutput->injectOutputLayerForTest(std::unique_ptr<OutputLayer>(outputLayer));
500
501 EXPECT_CALL(*outputLayer, updateCompositionState(true, true)).Times(1);
502 EXPECT_CALL(*outputLayer, writeStateToHWC(true)).Times(1);
503
504 CompositionRefreshArgs args;
505 args.updatingGeometryThisFrame = true;
506 args.devOptForceClientComposition = true;
507 mOutput->updateAndWriteCompositionState(args);
508}
509
510/*
Lloyd Pique66d68602019-02-13 14:23:31 -0800511 * Output::prepareFrame()
512 */
513
514struct OutputPrepareFrameTest : public testing::Test {
515 struct OutputPartialMock : public impl::Output {
Lloyd Pique66d68602019-02-13 14:23:31 -0800516 // Sets up the helper functions called by prepareFrame to use a mock
517 // implementations.
518 MOCK_METHOD0(chooseCompositionStrategy, void());
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700519
520 // compositionengine::Output overrides
521 const OutputCompositionState& getState() const override { return mState; }
522 OutputCompositionState& editState() override { return mState; }
523
524 // These need implementations though are not expected to be called.
Lloyd Pique01c77c12019-04-17 12:48:32 -0700525 MOCK_CONST_METHOD0(getOutputLayerCount, size_t());
526 MOCK_CONST_METHOD1(getOutputLayerOrderedByZByIndex,
527 compositionengine::OutputLayer*(size_t));
528 MOCK_METHOD3(ensureOutputLayer,
529 compositionengine::OutputLayer*(
530 std::optional<size_t>,
531 const std::shared_ptr<compositionengine::Layer>&, const sp<LayerFE>&));
532 MOCK_METHOD0(finalizePendingOutputLayers, void());
533 MOCK_METHOD0(clearOutputLayers, void());
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700534 MOCK_CONST_METHOD1(dumpState, void(std::string&));
535 MOCK_CONST_METHOD0(getCompositionEngine, const CompositionEngine&());
Lloyd Pique01c77c12019-04-17 12:48:32 -0700536 MOCK_METHOD2(injectOutputLayerForTest,
537 compositionengine::OutputLayer*(
538 const std::shared_ptr<compositionengine::Layer>&, const sp<LayerFE>&));
539 MOCK_METHOD1(injectOutputLayerForTest, void(std::unique_ptr<OutputLayer>));
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700540
541 impl::OutputCompositionState mState;
Lloyd Pique66d68602019-02-13 14:23:31 -0800542 };
543
544 OutputPrepareFrameTest() {
545 mOutput.setDisplayColorProfileForTest(
546 std::unique_ptr<DisplayColorProfile>(mDisplayColorProfile));
547 mOutput.setRenderSurfaceForTest(std::unique_ptr<RenderSurface>(mRenderSurface));
548 }
549
550 StrictMock<mock::CompositionEngine> mCompositionEngine;
551 mock::DisplayColorProfile* mDisplayColorProfile = new StrictMock<mock::DisplayColorProfile>();
552 mock::RenderSurface* mRenderSurface = new StrictMock<mock::RenderSurface>();
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700553 StrictMock<OutputPartialMock> mOutput;
Lloyd Pique66d68602019-02-13 14:23:31 -0800554};
555
556TEST_F(OutputPrepareFrameTest, takesEarlyOutIfNotEnabled) {
557 mOutput.editState().isEnabled = false;
558
559 mOutput.prepareFrame();
560}
561
562TEST_F(OutputPrepareFrameTest, delegatesToChooseCompositionStrategyAndRenderSurface) {
563 mOutput.editState().isEnabled = true;
564 mOutput.editState().usesClientComposition = false;
565 mOutput.editState().usesDeviceComposition = true;
566
567 EXPECT_CALL(mOutput, chooseCompositionStrategy()).Times(1);
568 EXPECT_CALL(*mRenderSurface, prepareFrame(false, true));
569
570 mOutput.prepareFrame();
571}
572
573// Note: Use OutputTest and not OutputPrepareFrameTest, so the real
574// base chooseCompositionStrategy() is invoked.
575TEST_F(OutputTest, prepareFrameSetsClientCompositionOnlyByDefault) {
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700576 mOutput->editState().isEnabled = true;
577 mOutput->editState().usesClientComposition = false;
578 mOutput->editState().usesDeviceComposition = true;
Lloyd Pique66d68602019-02-13 14:23:31 -0800579
580 EXPECT_CALL(*mRenderSurface, prepareFrame(true, false));
581
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700582 mOutput->prepareFrame();
Lloyd Pique66d68602019-02-13 14:23:31 -0800583
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700584 EXPECT_TRUE(mOutput->getState().usesClientComposition);
585 EXPECT_FALSE(mOutput->getState().usesDeviceComposition);
Lloyd Pique66d68602019-02-13 14:23:31 -0800586}
587
Lloyd Pique56eba802019-08-28 15:45:25 -0700588/*
589 * Output::composeSurfaces()
590 */
591
592struct OutputComposeSurfacesTest : public testing::Test {
593 static constexpr uint32_t kDefaultOutputOrientation = TR_IDENT;
594 static constexpr ui::Dataspace kDefaultOutputDataspace = ui::Dataspace::DISPLAY_P3;
595
596 static const Rect kDefaultOutputFrame;
597 static const Rect kDefaultOutputViewport;
598 static const Rect kDefaultOutputScissor;
599 static const mat4 kDefaultColorTransformMat;
600
601 struct OutputPartialMock : public impl::Output {
Lloyd Pique56eba802019-08-28 15:45:25 -0700602 // Sets up the helper functions called by composeSurfaces to use a mock
603 // implementations.
604 MOCK_CONST_METHOD0(getSkipColorTransform, bool());
605 MOCK_METHOD2(generateClientCompositionRequests,
606 std::vector<renderengine::LayerSettings>(bool, Region&));
607 MOCK_METHOD2(appendRegionFlashRequests,
608 void(const Region&, std::vector<renderengine::LayerSettings>&));
609 MOCK_METHOD1(setExpensiveRenderingExpected, void(bool));
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700610
611 // compositionengine::Output overrides
612 const OutputCompositionState& getState() const override { return mState; }
613 OutputCompositionState& editState() override { return mState; }
614
615 // These need implementations though are not expected to be called.
Lloyd Pique01c77c12019-04-17 12:48:32 -0700616 MOCK_CONST_METHOD0(getOutputLayerCount, size_t());
617 MOCK_CONST_METHOD1(getOutputLayerOrderedByZByIndex,
618 compositionengine::OutputLayer*(size_t));
619 MOCK_METHOD3(ensureOutputLayer,
620 compositionengine::OutputLayer*(
621 std::optional<size_t>,
622 const std::shared_ptr<compositionengine::Layer>&, const sp<LayerFE>&));
623 MOCK_METHOD0(finalizePendingOutputLayers, void());
624 MOCK_METHOD0(clearOutputLayers, void());
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700625 MOCK_CONST_METHOD1(dumpState, void(std::string&));
626 MOCK_CONST_METHOD0(getCompositionEngine, const CompositionEngine&());
Lloyd Pique01c77c12019-04-17 12:48:32 -0700627 MOCK_METHOD2(injectOutputLayerForTest,
628 compositionengine::OutputLayer*(
629 const std::shared_ptr<compositionengine::Layer>&, const sp<LayerFE>&));
630 MOCK_METHOD1(injectOutputLayerForTest, void(std::unique_ptr<OutputLayer>));
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700631
632 impl::OutputCompositionState mState;
Lloyd Pique56eba802019-08-28 15:45:25 -0700633 };
634
635 OutputComposeSurfacesTest() {
636 mOutput.setDisplayColorProfileForTest(
637 std::unique_ptr<DisplayColorProfile>(mDisplayColorProfile));
638 mOutput.setRenderSurfaceForTest(std::unique_ptr<RenderSurface>(mRenderSurface));
639
Lloyd Pique56eba802019-08-28 15:45:25 -0700640 mOutput.editState().frame = kDefaultOutputFrame;
641 mOutput.editState().viewport = kDefaultOutputViewport;
642 mOutput.editState().scissor = kDefaultOutputScissor;
643 mOutput.editState().transform = ui::Transform{kDefaultOutputOrientation};
644 mOutput.editState().orientation = kDefaultOutputOrientation;
645 mOutput.editState().dataspace = kDefaultOutputDataspace;
Lloyd Pique3eb1b212019-03-07 21:15:40 -0800646 mOutput.editState().colorTransformMatrix = kDefaultColorTransformMat;
Lloyd Pique56eba802019-08-28 15:45:25 -0700647 mOutput.editState().isSecure = true;
648 mOutput.editState().needsFiltering = false;
649 mOutput.editState().usesClientComposition = true;
650 mOutput.editState().usesDeviceComposition = false;
651
Lloyd Pique01c77c12019-04-17 12:48:32 -0700652 EXPECT_CALL(mOutput, getOutputLayerCount()).WillRepeatedly(Return(2u));
653 EXPECT_CALL(mOutput, getOutputLayerOrderedByZByIndex(0u))
654 .WillRepeatedly(Return(&mOutputLayer1));
655 EXPECT_CALL(mOutput, getOutputLayerOrderedByZByIndex(1u))
656 .WillRepeatedly(Return(&mOutputLayer2));
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700657 EXPECT_CALL(mOutput, getCompositionEngine()).WillRepeatedly(ReturnRef(mCompositionEngine));
Lloyd Pique56eba802019-08-28 15:45:25 -0700658 EXPECT_CALL(mCompositionEngine, getRenderEngine()).WillRepeatedly(ReturnRef(mRenderEngine));
659 }
660
661 StrictMock<mock::CompositionEngine> mCompositionEngine;
662 StrictMock<renderengine::mock::RenderEngine> mRenderEngine;
663 mock::DisplayColorProfile* mDisplayColorProfile = new StrictMock<mock::DisplayColorProfile>();
664 mock::RenderSurface* mRenderSurface = new StrictMock<mock::RenderSurface>();
Lloyd Pique01c77c12019-04-17 12:48:32 -0700665 StrictMock<mock::OutputLayer> mOutputLayer1;
666 StrictMock<mock::OutputLayer> mOutputLayer2;
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700667 StrictMock<OutputPartialMock> mOutput;
Lloyd Pique56eba802019-08-28 15:45:25 -0700668 sp<GraphicBuffer> mOutputBuffer = new GraphicBuffer();
669};
670
671const Rect OutputComposeSurfacesTest::kDefaultOutputFrame{1001, 1002, 1003, 1004};
672const Rect OutputComposeSurfacesTest::kDefaultOutputViewport{1005, 1006, 1007, 1008};
673const Rect OutputComposeSurfacesTest::kDefaultOutputScissor{1009, 1010, 1011, 1012};
674const mat4 OutputComposeSurfacesTest::kDefaultColorTransformMat{mat4() * 0.5};
675
676// TODO(b/121291683): Expand unit test coverage for composeSurfaces beyond these
677// basic tests.
678
679TEST_F(OutputComposeSurfacesTest, doesNothingIfNoClientComposition) {
680 mOutput.editState().usesClientComposition = false;
681
682 Region debugRegion;
Lloyd Piqued3d69882019-02-28 16:03:46 -0800683 std::optional<base::unique_fd> readyFence = mOutput.composeSurfaces(debugRegion);
684 EXPECT_TRUE(readyFence);
Lloyd Pique56eba802019-08-28 15:45:25 -0700685}
686
687TEST_F(OutputComposeSurfacesTest, worksIfNoClientLayersQueued) {
688 const Region kDebugRegion{Rect{100, 101, 102, 103}};
689
690 constexpr float kDefaultMaxLuminance = 1.0f;
691 constexpr float kDefaultAvgLuminance = 0.7f;
692 constexpr float kDefaultMinLuminance = 0.1f;
693 HdrCapabilities HdrCapabilities{{},
694 kDefaultMaxLuminance,
695 kDefaultAvgLuminance,
696 kDefaultMinLuminance};
697
698 EXPECT_CALL(mRenderEngine, supportsProtectedContent()).WillOnce(Return(false));
699 EXPECT_CALL(mRenderEngine, drawLayers(_, _, _, true, _, _)).Times(1);
700
701 EXPECT_CALL(*mDisplayColorProfile, hasWideColorGamut()).WillOnce(Return(true));
702 EXPECT_CALL(*mDisplayColorProfile, getHdrCapabilities()).WillOnce(ReturnRef(HdrCapabilities));
703
704 EXPECT_CALL(*mRenderSurface, dequeueBuffer(_)).WillOnce(Return(mOutputBuffer));
705
706 EXPECT_CALL(mOutput, getSkipColorTransform()).WillOnce(Return(false));
707 EXPECT_CALL(mOutput, generateClientCompositionRequests(false, _)).Times(1);
708 EXPECT_CALL(mOutput, appendRegionFlashRequests(RegionEq(kDebugRegion), _)).Times(1);
709 EXPECT_CALL(mOutput, setExpensiveRenderingExpected(true)).Times(1);
710 EXPECT_CALL(mOutput, setExpensiveRenderingExpected(false)).Times(1);
711
Lloyd Piqued3d69882019-02-28 16:03:46 -0800712 std::optional<base::unique_fd> readyFence = mOutput.composeSurfaces(kDebugRegion);
713 EXPECT_TRUE(readyFence);
Lloyd Pique56eba802019-08-28 15:45:25 -0700714}
715
716/*
717 * Output::generateClientCompositionRequests()
718 */
719
720struct GenerateClientCompositionRequestsTest : public testing::Test {
721 struct OutputPartialMock : public impl::Output {
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700722 // compositionengine::Output overrides
Lloyd Pique56eba802019-08-28 15:45:25 -0700723
724 std::vector<renderengine::LayerSettings> generateClientCompositionRequests(
725 bool supportsProtectedContent, Region& clearRegion) override {
726 return impl::Output::generateClientCompositionRequests(supportsProtectedContent,
727 clearRegion);
728 }
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700729
730 const OutputCompositionState& getState() const override { return mState; }
731 OutputCompositionState& editState() override { return mState; }
732
733 // These need implementations though are not expected to be called.
Lloyd Pique01c77c12019-04-17 12:48:32 -0700734 MOCK_CONST_METHOD0(getOutputLayerCount, size_t());
735 MOCK_CONST_METHOD1(getOutputLayerOrderedByZByIndex,
736 compositionengine::OutputLayer*(size_t));
737 MOCK_METHOD3(ensureOutputLayer,
738 compositionengine::OutputLayer*(
739 std::optional<size_t>,
740 const std::shared_ptr<compositionengine::Layer>&, const sp<LayerFE>&));
741 MOCK_METHOD0(finalizePendingOutputLayers, void());
742 MOCK_METHOD0(clearOutputLayers, void());
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700743 MOCK_CONST_METHOD1(dumpState, void(std::string&));
744 MOCK_CONST_METHOD0(getCompositionEngine, const CompositionEngine&());
Lloyd Pique01c77c12019-04-17 12:48:32 -0700745 MOCK_METHOD2(injectOutputLayerForTest,
746 compositionengine::OutputLayer*(
747 const std::shared_ptr<compositionengine::Layer>&, const sp<LayerFE>&));
748 MOCK_METHOD1(injectOutputLayerForTest, void(std::unique_ptr<OutputLayer>));
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700749
750 impl::OutputCompositionState mState;
Lloyd Pique56eba802019-08-28 15:45:25 -0700751 };
752
753 GenerateClientCompositionRequestsTest() {
754 mOutput.setDisplayColorProfileForTest(
755 std::unique_ptr<DisplayColorProfile>(mDisplayColorProfile));
756 mOutput.setRenderSurfaceForTest(std::unique_ptr<RenderSurface>(mRenderSurface));
757 }
758
Lloyd Pique56eba802019-08-28 15:45:25 -0700759 mock::DisplayColorProfile* mDisplayColorProfile = new StrictMock<mock::DisplayColorProfile>();
760 mock::RenderSurface* mRenderSurface = new StrictMock<mock::RenderSurface>();
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700761 StrictMock<OutputPartialMock> mOutput;
Lloyd Pique56eba802019-08-28 15:45:25 -0700762};
763
764// TODO(b/121291683): Add more unit test coverage for generateClientCompositionRequests
765
766TEST_F(GenerateClientCompositionRequestsTest, worksForLandscapeModeSplitScreen) {
767 // In split-screen landscape mode, the screen is rotated 90 degrees, with
768 // one layer on the left covering the left side of the output, and one layer
769 // on the right covering that side of the output.
770
Lloyd Pique01c77c12019-04-17 12:48:32 -0700771 StrictMock<mock::OutputLayer> leftOutputLayer;
772 StrictMock<mock::OutputLayer> rightOutputLayer;
Lloyd Pique56eba802019-08-28 15:45:25 -0700773
774 StrictMock<mock::Layer> leftLayer;
775 StrictMock<mock::LayerFE> leftLayerFE;
776 StrictMock<mock::Layer> rightLayer;
777 StrictMock<mock::LayerFE> rightLayerFE;
778
779 impl::OutputLayerCompositionState leftOutputLayerState;
780 leftOutputLayerState.clearClientTarget = false;
Lloyd Piquea2468662019-03-07 21:31:06 -0800781 leftOutputLayerState.visibleRegion = Region{Rect{0, 0, 1000, 1000}};
Lloyd Pique56eba802019-08-28 15:45:25 -0700782
Lloyd Pique9755fb72019-03-26 14:44:40 -0700783 LayerFECompositionState leftLayerFEState;
784 leftLayerFEState.isOpaque = true;
Lloyd Pique56eba802019-08-28 15:45:25 -0700785
786 const half3 leftLayerColor{1.f, 0.f, 0.f};
787 renderengine::LayerSettings leftLayerRESettings;
788 leftLayerRESettings.source.solidColor = leftLayerColor;
789
790 impl::OutputLayerCompositionState rightOutputLayerState;
791 rightOutputLayerState.clearClientTarget = false;
Lloyd Piquea2468662019-03-07 21:31:06 -0800792 rightOutputLayerState.visibleRegion = Region{Rect{1000, 0, 2000, 1000}};
Lloyd Pique56eba802019-08-28 15:45:25 -0700793
Lloyd Pique9755fb72019-03-26 14:44:40 -0700794 LayerFECompositionState rightLayerFEState;
795 rightLayerFEState.isOpaque = true;
Lloyd Pique56eba802019-08-28 15:45:25 -0700796
797 const half3 rightLayerColor{0.f, 1.f, 0.f};
798 renderengine::LayerSettings rightLayerRESettings;
799 rightLayerRESettings.source.solidColor = rightLayerColor;
800
Lloyd Pique01c77c12019-04-17 12:48:32 -0700801 EXPECT_CALL(leftOutputLayer, getState()).WillRepeatedly(ReturnRef(leftOutputLayerState));
802 EXPECT_CALL(leftOutputLayer, getLayer()).WillRepeatedly(ReturnRef(leftLayer));
803 EXPECT_CALL(leftOutputLayer, getLayerFE()).WillRepeatedly(ReturnRef(leftLayerFE));
804 EXPECT_CALL(leftOutputLayer, requiresClientComposition()).WillRepeatedly(Return(true));
805 EXPECT_CALL(leftOutputLayer, needsFiltering()).WillRepeatedly(Return(false));
Lloyd Pique9755fb72019-03-26 14:44:40 -0700806 EXPECT_CALL(leftLayer, getFEState()).WillRepeatedly(ReturnRef(leftLayerFEState));
Lloyd Pique56eba802019-08-28 15:45:25 -0700807 EXPECT_CALL(leftLayerFE, prepareClientComposition(_)).WillOnce(Return(leftLayerRESettings));
808
Lloyd Pique01c77c12019-04-17 12:48:32 -0700809 EXPECT_CALL(rightOutputLayer, getState()).WillRepeatedly(ReturnRef(rightOutputLayerState));
810 EXPECT_CALL(rightOutputLayer, getLayer()).WillRepeatedly(ReturnRef(rightLayer));
811 EXPECT_CALL(rightOutputLayer, getLayerFE()).WillRepeatedly(ReturnRef(rightLayerFE));
812 EXPECT_CALL(rightOutputLayer, requiresClientComposition()).WillRepeatedly(Return(true));
813 EXPECT_CALL(rightOutputLayer, needsFiltering()).WillRepeatedly(Return(false));
Lloyd Pique9755fb72019-03-26 14:44:40 -0700814 EXPECT_CALL(rightLayer, getFEState()).WillRepeatedly(ReturnRef(rightLayerFEState));
Lloyd Pique56eba802019-08-28 15:45:25 -0700815 EXPECT_CALL(rightLayerFE, prepareClientComposition(_)).WillOnce(Return(rightLayerRESettings));
816
Lloyd Pique01c77c12019-04-17 12:48:32 -0700817 EXPECT_CALL(mOutput, getOutputLayerCount()).WillRepeatedly(Return(2u));
818 EXPECT_CALL(mOutput, getOutputLayerOrderedByZByIndex(0u))
819 .WillRepeatedly(Return(&leftOutputLayer));
820 EXPECT_CALL(mOutput, getOutputLayerOrderedByZByIndex(1u))
821 .WillRepeatedly(Return(&rightOutputLayer));
Lloyd Pique56eba802019-08-28 15:45:25 -0700822
823 const Rect kPortraitFrame(0, 0, 1000, 2000);
824 const Rect kPortraitViewport(0, 0, 2000, 1000);
825 const Rect kPortraitScissor(0, 0, 1000, 2000);
826 const uint32_t kPortraitOrientation = TR_ROT_90;
827
828 mOutput.editState().frame = kPortraitFrame;
829 mOutput.editState().viewport = kPortraitViewport;
830 mOutput.editState().scissor = kPortraitScissor;
831 mOutput.editState().transform = ui::Transform{kPortraitOrientation};
832 mOutput.editState().orientation = kPortraitOrientation;
833 mOutput.editState().needsFiltering = true;
834 mOutput.editState().isSecure = false;
835
836 constexpr bool supportsProtectedContent = false;
837 Region clearRegion;
838 auto requests =
839 mOutput.generateClientCompositionRequests(supportsProtectedContent, clearRegion);
840
841 ASSERT_EQ(2u, requests.size());
842 EXPECT_EQ(leftLayerColor, requests[0].source.solidColor);
843 EXPECT_EQ(rightLayerColor, requests[1].source.solidColor);
844}
845
846TEST_F(GenerateClientCompositionRequestsTest, ignoresLayersThatDoNotIntersectWithViewport) {
847 // Layers whose visible region does not intersect with the viewport will be
848 // skipped when generating client composition request state.
849
Lloyd Pique01c77c12019-04-17 12:48:32 -0700850 StrictMock<mock::OutputLayer> outputLayer;
Lloyd Pique56eba802019-08-28 15:45:25 -0700851 StrictMock<mock::Layer> layer;
852 StrictMock<mock::LayerFE> layerFE;
853
854 impl::OutputLayerCompositionState outputLayerState;
855 outputLayerState.clearClientTarget = false;
Lloyd Piquea2468662019-03-07 21:31:06 -0800856 outputLayerState.visibleRegion = Region{Rect{3000, 0, 4000, 1000}};
Lloyd Pique56eba802019-08-28 15:45:25 -0700857
Lloyd Pique9755fb72019-03-26 14:44:40 -0700858 LayerFECompositionState layerFEState;
859 layerFEState.isOpaque = true;
Lloyd Pique56eba802019-08-28 15:45:25 -0700860
Lloyd Pique01c77c12019-04-17 12:48:32 -0700861 EXPECT_CALL(outputLayer, getState()).WillRepeatedly(ReturnRef(outputLayerState));
862 EXPECT_CALL(outputLayer, getLayer()).WillRepeatedly(ReturnRef(layer));
863 EXPECT_CALL(outputLayer, getLayerFE()).WillRepeatedly(ReturnRef(layerFE));
864 EXPECT_CALL(outputLayer, requiresClientComposition()).WillRepeatedly(Return(true));
865 EXPECT_CALL(outputLayer, needsFiltering()).WillRepeatedly(Return(false));
Lloyd Pique9755fb72019-03-26 14:44:40 -0700866 EXPECT_CALL(layer, getFEState()).WillRepeatedly(ReturnRef(layerFEState));
Lloyd Pique56eba802019-08-28 15:45:25 -0700867 EXPECT_CALL(layerFE, prepareClientComposition(_)).Times(0);
868
Lloyd Pique01c77c12019-04-17 12:48:32 -0700869 EXPECT_CALL(mOutput, getOutputLayerCount()).WillRepeatedly(Return(1u));
870 EXPECT_CALL(mOutput, getOutputLayerOrderedByZByIndex(0u)).WillRepeatedly(Return(&outputLayer));
Lloyd Pique56eba802019-08-28 15:45:25 -0700871
872 const Rect kPortraitFrame(0, 0, 1000, 2000);
873 const Rect kPortraitViewport(0, 0, 2000, 1000);
874 const Rect kPortraitScissor(0, 0, 1000, 2000);
875 const uint32_t kPortraitOrientation = TR_ROT_90;
876
877 mOutput.editState().frame = kPortraitFrame;
878 mOutput.editState().viewport = kPortraitViewport;
879 mOutput.editState().scissor = kPortraitScissor;
880 mOutput.editState().transform = ui::Transform{kPortraitOrientation};
881 mOutput.editState().orientation = kPortraitOrientation;
882 mOutput.editState().needsFiltering = true;
883 mOutput.editState().isSecure = false;
884
885 constexpr bool supportsProtectedContent = false;
886 Region clearRegion;
887 auto requests =
888 mOutput.generateClientCompositionRequests(supportsProtectedContent, clearRegion);
889
890 EXPECT_EQ(0u, requests.size());
891}
892
Lloyd Piquec2d54d42019-08-28 18:04:21 -0700893TEST_F(GenerateClientCompositionRequestsTest, clearsDeviceLayesAfterFirst) {
894 // If client composition is performed with some layers set to use device
895 // composition, device layers after the first layer (device or client) will
896 // clear the frame buffer if they are opaque and if that layer has a flag
897 // set to do so. The first layer is skipped as the frame buffer is already
898 // expected to be clear.
899
Lloyd Pique01c77c12019-04-17 12:48:32 -0700900 StrictMock<mock::OutputLayer> leftOutputLayer;
901 StrictMock<mock::OutputLayer> rightOutputLayer;
Lloyd Piquec2d54d42019-08-28 18:04:21 -0700902
903 StrictMock<mock::Layer> leftLayer;
904 StrictMock<mock::LayerFE> leftLayerFE;
905 StrictMock<mock::Layer> rightLayer;
906 StrictMock<mock::LayerFE> rightLayerFE;
907
908 impl::OutputLayerCompositionState leftOutputLayerState;
909 leftOutputLayerState.clearClientTarget = true;
Lloyd Piquea2468662019-03-07 21:31:06 -0800910 leftOutputLayerState.visibleRegion = Region{Rect{0, 0, 1000, 1000}};
Lloyd Piquec2d54d42019-08-28 18:04:21 -0700911
Lloyd Pique9755fb72019-03-26 14:44:40 -0700912 LayerFECompositionState leftLayerFEState;
913 leftLayerFEState.isOpaque = true;
Lloyd Piquec2d54d42019-08-28 18:04:21 -0700914
915 impl::OutputLayerCompositionState rightOutputLayerState;
916 rightOutputLayerState.clearClientTarget = true;
Lloyd Piquea2468662019-03-07 21:31:06 -0800917 rightOutputLayerState.visibleRegion = Region{Rect{1000, 0, 2000, 1000}};
Lloyd Piquec2d54d42019-08-28 18:04:21 -0700918
Lloyd Pique9755fb72019-03-26 14:44:40 -0700919 LayerFECompositionState rightLayerFEState;
920 rightLayerFEState.isOpaque = true;
Lloyd Piquec2d54d42019-08-28 18:04:21 -0700921
922 const half3 rightLayerColor{0.f, 1.f, 0.f};
923 renderengine::LayerSettings rightLayerRESettings;
924 rightLayerRESettings.geometry.boundaries = FloatRect{456, 0, 0, 0};
925 rightLayerRESettings.source.solidColor = rightLayerColor;
926
Lloyd Pique01c77c12019-04-17 12:48:32 -0700927 EXPECT_CALL(leftOutputLayer, getState()).WillRepeatedly(ReturnRef(leftOutputLayerState));
928 EXPECT_CALL(leftOutputLayer, getLayer()).WillRepeatedly(ReturnRef(leftLayer));
929 EXPECT_CALL(leftOutputLayer, getLayerFE()).WillRepeatedly(ReturnRef(leftLayerFE));
930 EXPECT_CALL(leftOutputLayer, requiresClientComposition()).WillRepeatedly(Return(false));
931 EXPECT_CALL(leftOutputLayer, needsFiltering()).WillRepeatedly(Return(false));
Lloyd Pique9755fb72019-03-26 14:44:40 -0700932 EXPECT_CALL(leftLayer, getFEState()).WillRepeatedly(ReturnRef(leftLayerFEState));
Lloyd Piquec2d54d42019-08-28 18:04:21 -0700933
Lloyd Pique01c77c12019-04-17 12:48:32 -0700934 EXPECT_CALL(rightOutputLayer, getState()).WillRepeatedly(ReturnRef(rightOutputLayerState));
935 EXPECT_CALL(rightOutputLayer, getLayer()).WillRepeatedly(ReturnRef(rightLayer));
936 EXPECT_CALL(rightOutputLayer, getLayerFE()).WillRepeatedly(ReturnRef(rightLayerFE));
937 EXPECT_CALL(rightOutputLayer, requiresClientComposition()).WillRepeatedly(Return(false));
938 EXPECT_CALL(rightOutputLayer, needsFiltering()).WillRepeatedly(Return(false));
Lloyd Pique9755fb72019-03-26 14:44:40 -0700939 EXPECT_CALL(rightLayer, getFEState()).WillRepeatedly(ReturnRef(rightLayerFEState));
Lloyd Piquec2d54d42019-08-28 18:04:21 -0700940 EXPECT_CALL(rightLayerFE, prepareClientComposition(_)).WillOnce(Return(rightLayerRESettings));
941
Lloyd Pique01c77c12019-04-17 12:48:32 -0700942 EXPECT_CALL(mOutput, getOutputLayerCount()).WillRepeatedly(Return(2u));
943 EXPECT_CALL(mOutput, getOutputLayerOrderedByZByIndex(0u))
944 .WillRepeatedly(Return(&leftOutputLayer));
945 EXPECT_CALL(mOutput, getOutputLayerOrderedByZByIndex(1u))
946 .WillRepeatedly(Return(&rightOutputLayer));
Lloyd Piquec2d54d42019-08-28 18:04:21 -0700947
948 const Rect kPortraitFrame(0, 0, 1000, 2000);
949 const Rect kPortraitViewport(0, 0, 2000, 1000);
950 const Rect kPortraitScissor(0, 0, 1000, 2000);
951 const uint32_t kPortraitOrientation = TR_ROT_90;
952
953 mOutput.editState().frame = kPortraitFrame;
954 mOutput.editState().viewport = kPortraitViewport;
955 mOutput.editState().scissor = kPortraitScissor;
956 mOutput.editState().transform = ui::Transform{kPortraitOrientation};
957 mOutput.editState().orientation = kPortraitOrientation;
958 mOutput.editState().needsFiltering = true;
959 mOutput.editState().isSecure = false;
960
961 constexpr bool supportsProtectedContent = false;
962 Region clearRegion;
963 auto requests =
964 mOutput.generateClientCompositionRequests(supportsProtectedContent, clearRegion);
965
966 const half3 clearColor{0.f, 0.f, 0.f};
967
968 ASSERT_EQ(1u, requests.size());
969 EXPECT_EQ(456.f, requests[0].geometry.boundaries.left);
970 EXPECT_EQ(clearColor, requests[0].source.solidColor);
971}
972
Lloyd Pique32cbe282018-10-19 13:09:22 -0700973} // namespace
974} // namespace android::compositionengine