blob: eecfb49e29d0c926ebae86c6ce3c8ed4f0cccd2b [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/*
Lloyd Piquec9e60032019-11-14 11:47:26 -0800486 * Output::setReleasedLayers()
487 */
488
489using OutputSetReleasedLayersTest = OutputTest;
490
491TEST_F(OutputSetReleasedLayersTest, setReleasedLayersTakesGivenLayers) {
492 sp<StrictMock<mock::LayerFE>> layer1FE{new StrictMock<mock::LayerFE>()};
493 sp<StrictMock<mock::LayerFE>> layer2FE{new StrictMock<mock::LayerFE>()};
494 sp<StrictMock<mock::LayerFE>> layer3FE{new StrictMock<mock::LayerFE>()};
495
496 Output::ReleasedLayers layers;
497 layers.push_back(layer1FE);
498 layers.push_back(layer2FE);
499 layers.push_back(layer3FE);
500
501 mOutput->setReleasedLayers(std::move(layers));
502
503 const auto& setLayers = mOutput->getReleasedLayersForTest();
504 ASSERT_EQ(3u, setLayers.size());
505 ASSERT_EQ(layer1FE.get(), setLayers[0].promote().get());
506 ASSERT_EQ(layer2FE.get(), setLayers[1].promote().get());
507 ASSERT_EQ(layer3FE.get(), setLayers[2].promote().get());
508}
509
510/*
Alec Mourif9a2a2c2019-11-12 12:46:02 -0800511 * Output::updateAndWriteCompositionState()
512 */
513
514TEST_F(OutputTest, updateAndWriteCompositionState_takesEarlyOutIfNotEnabled) {
515 mOutput->editState().isEnabled = false;
516
517 CompositionRefreshArgs args;
518 mOutput->updateAndWriteCompositionState(args);
519}
520
521TEST_F(OutputTest, updateAndWriteCompositionState_updatesLayers) {
522 mOutput->editState().isEnabled = true;
523 mock::OutputLayer* outputLayer = new StrictMock<mock::OutputLayer>();
524 mOutput->injectOutputLayerForTest(std::unique_ptr<OutputLayer>(outputLayer));
525
526 EXPECT_CALL(*outputLayer, updateCompositionState(true, true)).Times(1);
527 EXPECT_CALL(*outputLayer, writeStateToHWC(true)).Times(1);
528
529 CompositionRefreshArgs args;
530 args.updatingGeometryThisFrame = true;
531 args.devOptForceClientComposition = true;
532 mOutput->updateAndWriteCompositionState(args);
533}
534
535/*
Lloyd Pique66d68602019-02-13 14:23:31 -0800536 * Output::prepareFrame()
537 */
538
539struct OutputPrepareFrameTest : public testing::Test {
540 struct OutputPartialMock : public impl::Output {
Lloyd Pique66d68602019-02-13 14:23:31 -0800541 // Sets up the helper functions called by prepareFrame to use a mock
542 // implementations.
543 MOCK_METHOD0(chooseCompositionStrategy, void());
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700544
545 // compositionengine::Output overrides
546 const OutputCompositionState& getState() const override { return mState; }
547 OutputCompositionState& editState() override { return mState; }
548
549 // These need implementations though are not expected to be called.
Lloyd Pique01c77c12019-04-17 12:48:32 -0700550 MOCK_CONST_METHOD0(getOutputLayerCount, size_t());
551 MOCK_CONST_METHOD1(getOutputLayerOrderedByZByIndex,
552 compositionengine::OutputLayer*(size_t));
553 MOCK_METHOD3(ensureOutputLayer,
554 compositionengine::OutputLayer*(
555 std::optional<size_t>,
556 const std::shared_ptr<compositionengine::Layer>&, const sp<LayerFE>&));
557 MOCK_METHOD0(finalizePendingOutputLayers, void());
558 MOCK_METHOD0(clearOutputLayers, void());
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700559 MOCK_CONST_METHOD1(dumpState, void(std::string&));
560 MOCK_CONST_METHOD0(getCompositionEngine, const CompositionEngine&());
Lloyd Pique01c77c12019-04-17 12:48:32 -0700561 MOCK_METHOD2(injectOutputLayerForTest,
562 compositionengine::OutputLayer*(
563 const std::shared_ptr<compositionengine::Layer>&, const sp<LayerFE>&));
564 MOCK_METHOD1(injectOutputLayerForTest, void(std::unique_ptr<OutputLayer>));
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700565
566 impl::OutputCompositionState mState;
Lloyd Pique66d68602019-02-13 14:23:31 -0800567 };
568
569 OutputPrepareFrameTest() {
570 mOutput.setDisplayColorProfileForTest(
571 std::unique_ptr<DisplayColorProfile>(mDisplayColorProfile));
572 mOutput.setRenderSurfaceForTest(std::unique_ptr<RenderSurface>(mRenderSurface));
573 }
574
575 StrictMock<mock::CompositionEngine> mCompositionEngine;
576 mock::DisplayColorProfile* mDisplayColorProfile = new StrictMock<mock::DisplayColorProfile>();
577 mock::RenderSurface* mRenderSurface = new StrictMock<mock::RenderSurface>();
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700578 StrictMock<OutputPartialMock> mOutput;
Lloyd Pique66d68602019-02-13 14:23:31 -0800579};
580
581TEST_F(OutputPrepareFrameTest, takesEarlyOutIfNotEnabled) {
582 mOutput.editState().isEnabled = false;
583
584 mOutput.prepareFrame();
585}
586
587TEST_F(OutputPrepareFrameTest, delegatesToChooseCompositionStrategyAndRenderSurface) {
588 mOutput.editState().isEnabled = true;
589 mOutput.editState().usesClientComposition = false;
590 mOutput.editState().usesDeviceComposition = true;
591
592 EXPECT_CALL(mOutput, chooseCompositionStrategy()).Times(1);
593 EXPECT_CALL(*mRenderSurface, prepareFrame(false, true));
594
595 mOutput.prepareFrame();
596}
597
598// Note: Use OutputTest and not OutputPrepareFrameTest, so the real
599// base chooseCompositionStrategy() is invoked.
600TEST_F(OutputTest, prepareFrameSetsClientCompositionOnlyByDefault) {
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700601 mOutput->editState().isEnabled = true;
602 mOutput->editState().usesClientComposition = false;
603 mOutput->editState().usesDeviceComposition = true;
Lloyd Pique66d68602019-02-13 14:23:31 -0800604
605 EXPECT_CALL(*mRenderSurface, prepareFrame(true, false));
606
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700607 mOutput->prepareFrame();
Lloyd Pique66d68602019-02-13 14:23:31 -0800608
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700609 EXPECT_TRUE(mOutput->getState().usesClientComposition);
610 EXPECT_FALSE(mOutput->getState().usesDeviceComposition);
Lloyd Pique66d68602019-02-13 14:23:31 -0800611}
612
Lloyd Pique56eba802019-08-28 15:45:25 -0700613/*
614 * Output::composeSurfaces()
615 */
616
617struct OutputComposeSurfacesTest : public testing::Test {
618 static constexpr uint32_t kDefaultOutputOrientation = TR_IDENT;
619 static constexpr ui::Dataspace kDefaultOutputDataspace = ui::Dataspace::DISPLAY_P3;
620
621 static const Rect kDefaultOutputFrame;
622 static const Rect kDefaultOutputViewport;
623 static const Rect kDefaultOutputScissor;
624 static const mat4 kDefaultColorTransformMat;
625
626 struct OutputPartialMock : public impl::Output {
Lloyd Pique56eba802019-08-28 15:45:25 -0700627 // Sets up the helper functions called by composeSurfaces to use a mock
628 // implementations.
629 MOCK_CONST_METHOD0(getSkipColorTransform, bool());
630 MOCK_METHOD2(generateClientCompositionRequests,
631 std::vector<renderengine::LayerSettings>(bool, Region&));
632 MOCK_METHOD2(appendRegionFlashRequests,
633 void(const Region&, std::vector<renderengine::LayerSettings>&));
634 MOCK_METHOD1(setExpensiveRenderingExpected, void(bool));
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700635
636 // compositionengine::Output overrides
637 const OutputCompositionState& getState() const override { return mState; }
638 OutputCompositionState& editState() override { return mState; }
639
640 // These need implementations though are not expected to be called.
Lloyd Pique01c77c12019-04-17 12:48:32 -0700641 MOCK_CONST_METHOD0(getOutputLayerCount, size_t());
642 MOCK_CONST_METHOD1(getOutputLayerOrderedByZByIndex,
643 compositionengine::OutputLayer*(size_t));
644 MOCK_METHOD3(ensureOutputLayer,
645 compositionengine::OutputLayer*(
646 std::optional<size_t>,
647 const std::shared_ptr<compositionengine::Layer>&, const sp<LayerFE>&));
648 MOCK_METHOD0(finalizePendingOutputLayers, void());
649 MOCK_METHOD0(clearOutputLayers, void());
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700650 MOCK_CONST_METHOD1(dumpState, void(std::string&));
651 MOCK_CONST_METHOD0(getCompositionEngine, const CompositionEngine&());
Lloyd Pique01c77c12019-04-17 12:48:32 -0700652 MOCK_METHOD2(injectOutputLayerForTest,
653 compositionengine::OutputLayer*(
654 const std::shared_ptr<compositionengine::Layer>&, const sp<LayerFE>&));
655 MOCK_METHOD1(injectOutputLayerForTest, void(std::unique_ptr<OutputLayer>));
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700656
657 impl::OutputCompositionState mState;
Lloyd Pique56eba802019-08-28 15:45:25 -0700658 };
659
660 OutputComposeSurfacesTest() {
661 mOutput.setDisplayColorProfileForTest(
662 std::unique_ptr<DisplayColorProfile>(mDisplayColorProfile));
663 mOutput.setRenderSurfaceForTest(std::unique_ptr<RenderSurface>(mRenderSurface));
664
Lloyd Pique56eba802019-08-28 15:45:25 -0700665 mOutput.editState().frame = kDefaultOutputFrame;
666 mOutput.editState().viewport = kDefaultOutputViewport;
667 mOutput.editState().scissor = kDefaultOutputScissor;
668 mOutput.editState().transform = ui::Transform{kDefaultOutputOrientation};
669 mOutput.editState().orientation = kDefaultOutputOrientation;
670 mOutput.editState().dataspace = kDefaultOutputDataspace;
Lloyd Pique3eb1b212019-03-07 21:15:40 -0800671 mOutput.editState().colorTransformMatrix = kDefaultColorTransformMat;
Lloyd Pique56eba802019-08-28 15:45:25 -0700672 mOutput.editState().isSecure = true;
673 mOutput.editState().needsFiltering = false;
674 mOutput.editState().usesClientComposition = true;
675 mOutput.editState().usesDeviceComposition = false;
676
Lloyd Pique01c77c12019-04-17 12:48:32 -0700677 EXPECT_CALL(mOutput, getOutputLayerCount()).WillRepeatedly(Return(2u));
678 EXPECT_CALL(mOutput, getOutputLayerOrderedByZByIndex(0u))
679 .WillRepeatedly(Return(&mOutputLayer1));
680 EXPECT_CALL(mOutput, getOutputLayerOrderedByZByIndex(1u))
681 .WillRepeatedly(Return(&mOutputLayer2));
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700682 EXPECT_CALL(mOutput, getCompositionEngine()).WillRepeatedly(ReturnRef(mCompositionEngine));
Lloyd Pique56eba802019-08-28 15:45:25 -0700683 EXPECT_CALL(mCompositionEngine, getRenderEngine()).WillRepeatedly(ReturnRef(mRenderEngine));
684 }
685
686 StrictMock<mock::CompositionEngine> mCompositionEngine;
687 StrictMock<renderengine::mock::RenderEngine> mRenderEngine;
688 mock::DisplayColorProfile* mDisplayColorProfile = new StrictMock<mock::DisplayColorProfile>();
689 mock::RenderSurface* mRenderSurface = new StrictMock<mock::RenderSurface>();
Lloyd Pique01c77c12019-04-17 12:48:32 -0700690 StrictMock<mock::OutputLayer> mOutputLayer1;
691 StrictMock<mock::OutputLayer> mOutputLayer2;
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700692 StrictMock<OutputPartialMock> mOutput;
Lloyd Pique56eba802019-08-28 15:45:25 -0700693 sp<GraphicBuffer> mOutputBuffer = new GraphicBuffer();
694};
695
696const Rect OutputComposeSurfacesTest::kDefaultOutputFrame{1001, 1002, 1003, 1004};
697const Rect OutputComposeSurfacesTest::kDefaultOutputViewport{1005, 1006, 1007, 1008};
698const Rect OutputComposeSurfacesTest::kDefaultOutputScissor{1009, 1010, 1011, 1012};
699const mat4 OutputComposeSurfacesTest::kDefaultColorTransformMat{mat4() * 0.5};
700
701// TODO(b/121291683): Expand unit test coverage for composeSurfaces beyond these
702// basic tests.
703
704TEST_F(OutputComposeSurfacesTest, doesNothingIfNoClientComposition) {
705 mOutput.editState().usesClientComposition = false;
706
707 Region debugRegion;
Lloyd Piqued3d69882019-02-28 16:03:46 -0800708 std::optional<base::unique_fd> readyFence = mOutput.composeSurfaces(debugRegion);
709 EXPECT_TRUE(readyFence);
Lloyd Pique56eba802019-08-28 15:45:25 -0700710}
711
712TEST_F(OutputComposeSurfacesTest, worksIfNoClientLayersQueued) {
713 const Region kDebugRegion{Rect{100, 101, 102, 103}};
714
715 constexpr float kDefaultMaxLuminance = 1.0f;
716 constexpr float kDefaultAvgLuminance = 0.7f;
717 constexpr float kDefaultMinLuminance = 0.1f;
718 HdrCapabilities HdrCapabilities{{},
719 kDefaultMaxLuminance,
720 kDefaultAvgLuminance,
721 kDefaultMinLuminance};
722
723 EXPECT_CALL(mRenderEngine, supportsProtectedContent()).WillOnce(Return(false));
724 EXPECT_CALL(mRenderEngine, drawLayers(_, _, _, true, _, _)).Times(1);
725
726 EXPECT_CALL(*mDisplayColorProfile, hasWideColorGamut()).WillOnce(Return(true));
727 EXPECT_CALL(*mDisplayColorProfile, getHdrCapabilities()).WillOnce(ReturnRef(HdrCapabilities));
728
729 EXPECT_CALL(*mRenderSurface, dequeueBuffer(_)).WillOnce(Return(mOutputBuffer));
730
731 EXPECT_CALL(mOutput, getSkipColorTransform()).WillOnce(Return(false));
732 EXPECT_CALL(mOutput, generateClientCompositionRequests(false, _)).Times(1);
733 EXPECT_CALL(mOutput, appendRegionFlashRequests(RegionEq(kDebugRegion), _)).Times(1);
734 EXPECT_CALL(mOutput, setExpensiveRenderingExpected(true)).Times(1);
735 EXPECT_CALL(mOutput, setExpensiveRenderingExpected(false)).Times(1);
736
Lloyd Piqued3d69882019-02-28 16:03:46 -0800737 std::optional<base::unique_fd> readyFence = mOutput.composeSurfaces(kDebugRegion);
738 EXPECT_TRUE(readyFence);
Lloyd Pique56eba802019-08-28 15:45:25 -0700739}
740
741/*
742 * Output::generateClientCompositionRequests()
743 */
744
745struct GenerateClientCompositionRequestsTest : public testing::Test {
746 struct OutputPartialMock : public impl::Output {
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700747 // compositionengine::Output overrides
Lloyd Pique56eba802019-08-28 15:45:25 -0700748
749 std::vector<renderengine::LayerSettings> generateClientCompositionRequests(
750 bool supportsProtectedContent, Region& clearRegion) override {
751 return impl::Output::generateClientCompositionRequests(supportsProtectedContent,
752 clearRegion);
753 }
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700754
755 const OutputCompositionState& getState() const override { return mState; }
756 OutputCompositionState& editState() override { return mState; }
757
758 // These need implementations though are not expected to be called.
Lloyd Pique01c77c12019-04-17 12:48:32 -0700759 MOCK_CONST_METHOD0(getOutputLayerCount, size_t());
760 MOCK_CONST_METHOD1(getOutputLayerOrderedByZByIndex,
761 compositionengine::OutputLayer*(size_t));
762 MOCK_METHOD3(ensureOutputLayer,
763 compositionengine::OutputLayer*(
764 std::optional<size_t>,
765 const std::shared_ptr<compositionengine::Layer>&, const sp<LayerFE>&));
766 MOCK_METHOD0(finalizePendingOutputLayers, void());
767 MOCK_METHOD0(clearOutputLayers, void());
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700768 MOCK_CONST_METHOD1(dumpState, void(std::string&));
769 MOCK_CONST_METHOD0(getCompositionEngine, const CompositionEngine&());
Lloyd Pique01c77c12019-04-17 12:48:32 -0700770 MOCK_METHOD2(injectOutputLayerForTest,
771 compositionengine::OutputLayer*(
772 const std::shared_ptr<compositionengine::Layer>&, const sp<LayerFE>&));
773 MOCK_METHOD1(injectOutputLayerForTest, void(std::unique_ptr<OutputLayer>));
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700774
775 impl::OutputCompositionState mState;
Lloyd Pique56eba802019-08-28 15:45:25 -0700776 };
777
778 GenerateClientCompositionRequestsTest() {
779 mOutput.setDisplayColorProfileForTest(
780 std::unique_ptr<DisplayColorProfile>(mDisplayColorProfile));
781 mOutput.setRenderSurfaceForTest(std::unique_ptr<RenderSurface>(mRenderSurface));
782 }
783
Lloyd Pique56eba802019-08-28 15:45:25 -0700784 mock::DisplayColorProfile* mDisplayColorProfile = new StrictMock<mock::DisplayColorProfile>();
785 mock::RenderSurface* mRenderSurface = new StrictMock<mock::RenderSurface>();
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700786 StrictMock<OutputPartialMock> mOutput;
Lloyd Pique56eba802019-08-28 15:45:25 -0700787};
788
789// TODO(b/121291683): Add more unit test coverage for generateClientCompositionRequests
790
791TEST_F(GenerateClientCompositionRequestsTest, worksForLandscapeModeSplitScreen) {
792 // In split-screen landscape mode, the screen is rotated 90 degrees, with
793 // one layer on the left covering the left side of the output, and one layer
794 // on the right covering that side of the output.
795
Lloyd Pique01c77c12019-04-17 12:48:32 -0700796 StrictMock<mock::OutputLayer> leftOutputLayer;
797 StrictMock<mock::OutputLayer> rightOutputLayer;
Lloyd Pique56eba802019-08-28 15:45:25 -0700798
799 StrictMock<mock::Layer> leftLayer;
800 StrictMock<mock::LayerFE> leftLayerFE;
801 StrictMock<mock::Layer> rightLayer;
802 StrictMock<mock::LayerFE> rightLayerFE;
803
804 impl::OutputLayerCompositionState leftOutputLayerState;
805 leftOutputLayerState.clearClientTarget = false;
Lloyd Piquea2468662019-03-07 21:31:06 -0800806 leftOutputLayerState.visibleRegion = Region{Rect{0, 0, 1000, 1000}};
Lloyd Pique56eba802019-08-28 15:45:25 -0700807
Lloyd Pique9755fb72019-03-26 14:44:40 -0700808 LayerFECompositionState leftLayerFEState;
809 leftLayerFEState.isOpaque = true;
Lloyd Pique56eba802019-08-28 15:45:25 -0700810
811 const half3 leftLayerColor{1.f, 0.f, 0.f};
812 renderengine::LayerSettings leftLayerRESettings;
813 leftLayerRESettings.source.solidColor = leftLayerColor;
814
815 impl::OutputLayerCompositionState rightOutputLayerState;
816 rightOutputLayerState.clearClientTarget = false;
Lloyd Piquea2468662019-03-07 21:31:06 -0800817 rightOutputLayerState.visibleRegion = Region{Rect{1000, 0, 2000, 1000}};
Lloyd Pique56eba802019-08-28 15:45:25 -0700818
Lloyd Pique9755fb72019-03-26 14:44:40 -0700819 LayerFECompositionState rightLayerFEState;
820 rightLayerFEState.isOpaque = true;
Lloyd Pique56eba802019-08-28 15:45:25 -0700821
822 const half3 rightLayerColor{0.f, 1.f, 0.f};
823 renderengine::LayerSettings rightLayerRESettings;
824 rightLayerRESettings.source.solidColor = rightLayerColor;
825
Lloyd Pique01c77c12019-04-17 12:48:32 -0700826 EXPECT_CALL(leftOutputLayer, getState()).WillRepeatedly(ReturnRef(leftOutputLayerState));
827 EXPECT_CALL(leftOutputLayer, getLayer()).WillRepeatedly(ReturnRef(leftLayer));
828 EXPECT_CALL(leftOutputLayer, getLayerFE()).WillRepeatedly(ReturnRef(leftLayerFE));
829 EXPECT_CALL(leftOutputLayer, requiresClientComposition()).WillRepeatedly(Return(true));
830 EXPECT_CALL(leftOutputLayer, needsFiltering()).WillRepeatedly(Return(false));
Lloyd Pique9755fb72019-03-26 14:44:40 -0700831 EXPECT_CALL(leftLayer, getFEState()).WillRepeatedly(ReturnRef(leftLayerFEState));
Lloyd Pique56eba802019-08-28 15:45:25 -0700832 EXPECT_CALL(leftLayerFE, prepareClientComposition(_)).WillOnce(Return(leftLayerRESettings));
833
Lloyd Pique01c77c12019-04-17 12:48:32 -0700834 EXPECT_CALL(rightOutputLayer, getState()).WillRepeatedly(ReturnRef(rightOutputLayerState));
835 EXPECT_CALL(rightOutputLayer, getLayer()).WillRepeatedly(ReturnRef(rightLayer));
836 EXPECT_CALL(rightOutputLayer, getLayerFE()).WillRepeatedly(ReturnRef(rightLayerFE));
837 EXPECT_CALL(rightOutputLayer, requiresClientComposition()).WillRepeatedly(Return(true));
838 EXPECT_CALL(rightOutputLayer, needsFiltering()).WillRepeatedly(Return(false));
Lloyd Pique9755fb72019-03-26 14:44:40 -0700839 EXPECT_CALL(rightLayer, getFEState()).WillRepeatedly(ReturnRef(rightLayerFEState));
Lloyd Pique56eba802019-08-28 15:45:25 -0700840 EXPECT_CALL(rightLayerFE, prepareClientComposition(_)).WillOnce(Return(rightLayerRESettings));
841
Lloyd Pique01c77c12019-04-17 12:48:32 -0700842 EXPECT_CALL(mOutput, getOutputLayerCount()).WillRepeatedly(Return(2u));
843 EXPECT_CALL(mOutput, getOutputLayerOrderedByZByIndex(0u))
844 .WillRepeatedly(Return(&leftOutputLayer));
845 EXPECT_CALL(mOutput, getOutputLayerOrderedByZByIndex(1u))
846 .WillRepeatedly(Return(&rightOutputLayer));
Lloyd Pique56eba802019-08-28 15:45:25 -0700847
848 const Rect kPortraitFrame(0, 0, 1000, 2000);
849 const Rect kPortraitViewport(0, 0, 2000, 1000);
850 const Rect kPortraitScissor(0, 0, 1000, 2000);
851 const uint32_t kPortraitOrientation = TR_ROT_90;
852
853 mOutput.editState().frame = kPortraitFrame;
854 mOutput.editState().viewport = kPortraitViewport;
855 mOutput.editState().scissor = kPortraitScissor;
856 mOutput.editState().transform = ui::Transform{kPortraitOrientation};
857 mOutput.editState().orientation = kPortraitOrientation;
858 mOutput.editState().needsFiltering = true;
859 mOutput.editState().isSecure = false;
860
861 constexpr bool supportsProtectedContent = false;
862 Region clearRegion;
863 auto requests =
864 mOutput.generateClientCompositionRequests(supportsProtectedContent, clearRegion);
865
866 ASSERT_EQ(2u, requests.size());
867 EXPECT_EQ(leftLayerColor, requests[0].source.solidColor);
868 EXPECT_EQ(rightLayerColor, requests[1].source.solidColor);
869}
870
871TEST_F(GenerateClientCompositionRequestsTest, ignoresLayersThatDoNotIntersectWithViewport) {
872 // Layers whose visible region does not intersect with the viewport will be
873 // skipped when generating client composition request state.
874
Lloyd Pique01c77c12019-04-17 12:48:32 -0700875 StrictMock<mock::OutputLayer> outputLayer;
Lloyd Pique56eba802019-08-28 15:45:25 -0700876 StrictMock<mock::Layer> layer;
877 StrictMock<mock::LayerFE> layerFE;
878
879 impl::OutputLayerCompositionState outputLayerState;
880 outputLayerState.clearClientTarget = false;
Lloyd Piquea2468662019-03-07 21:31:06 -0800881 outputLayerState.visibleRegion = Region{Rect{3000, 0, 4000, 1000}};
Lloyd Pique56eba802019-08-28 15:45:25 -0700882
Lloyd Pique9755fb72019-03-26 14:44:40 -0700883 LayerFECompositionState layerFEState;
884 layerFEState.isOpaque = true;
Lloyd Pique56eba802019-08-28 15:45:25 -0700885
Lloyd Pique01c77c12019-04-17 12:48:32 -0700886 EXPECT_CALL(outputLayer, getState()).WillRepeatedly(ReturnRef(outputLayerState));
887 EXPECT_CALL(outputLayer, getLayer()).WillRepeatedly(ReturnRef(layer));
888 EXPECT_CALL(outputLayer, getLayerFE()).WillRepeatedly(ReturnRef(layerFE));
889 EXPECT_CALL(outputLayer, requiresClientComposition()).WillRepeatedly(Return(true));
890 EXPECT_CALL(outputLayer, needsFiltering()).WillRepeatedly(Return(false));
Lloyd Pique9755fb72019-03-26 14:44:40 -0700891 EXPECT_CALL(layer, getFEState()).WillRepeatedly(ReturnRef(layerFEState));
Lloyd Pique56eba802019-08-28 15:45:25 -0700892 EXPECT_CALL(layerFE, prepareClientComposition(_)).Times(0);
893
Lloyd Pique01c77c12019-04-17 12:48:32 -0700894 EXPECT_CALL(mOutput, getOutputLayerCount()).WillRepeatedly(Return(1u));
895 EXPECT_CALL(mOutput, getOutputLayerOrderedByZByIndex(0u)).WillRepeatedly(Return(&outputLayer));
Lloyd Pique56eba802019-08-28 15:45:25 -0700896
897 const Rect kPortraitFrame(0, 0, 1000, 2000);
898 const Rect kPortraitViewport(0, 0, 2000, 1000);
899 const Rect kPortraitScissor(0, 0, 1000, 2000);
900 const uint32_t kPortraitOrientation = TR_ROT_90;
901
902 mOutput.editState().frame = kPortraitFrame;
903 mOutput.editState().viewport = kPortraitViewport;
904 mOutput.editState().scissor = kPortraitScissor;
905 mOutput.editState().transform = ui::Transform{kPortraitOrientation};
906 mOutput.editState().orientation = kPortraitOrientation;
907 mOutput.editState().needsFiltering = true;
908 mOutput.editState().isSecure = false;
909
910 constexpr bool supportsProtectedContent = false;
911 Region clearRegion;
912 auto requests =
913 mOutput.generateClientCompositionRequests(supportsProtectedContent, clearRegion);
914
915 EXPECT_EQ(0u, requests.size());
916}
917
Lloyd Piquec2d54d42019-08-28 18:04:21 -0700918TEST_F(GenerateClientCompositionRequestsTest, clearsDeviceLayesAfterFirst) {
919 // If client composition is performed with some layers set to use device
920 // composition, device layers after the first layer (device or client) will
921 // clear the frame buffer if they are opaque and if that layer has a flag
922 // set to do so. The first layer is skipped as the frame buffer is already
923 // expected to be clear.
924
Lloyd Pique01c77c12019-04-17 12:48:32 -0700925 StrictMock<mock::OutputLayer> leftOutputLayer;
926 StrictMock<mock::OutputLayer> rightOutputLayer;
Lloyd Piquec2d54d42019-08-28 18:04:21 -0700927
928 StrictMock<mock::Layer> leftLayer;
929 StrictMock<mock::LayerFE> leftLayerFE;
930 StrictMock<mock::Layer> rightLayer;
931 StrictMock<mock::LayerFE> rightLayerFE;
932
933 impl::OutputLayerCompositionState leftOutputLayerState;
934 leftOutputLayerState.clearClientTarget = true;
Lloyd Piquea2468662019-03-07 21:31:06 -0800935 leftOutputLayerState.visibleRegion = Region{Rect{0, 0, 1000, 1000}};
Lloyd Piquec2d54d42019-08-28 18:04:21 -0700936
Lloyd Pique9755fb72019-03-26 14:44:40 -0700937 LayerFECompositionState leftLayerFEState;
938 leftLayerFEState.isOpaque = true;
Lloyd Piquec2d54d42019-08-28 18:04:21 -0700939
940 impl::OutputLayerCompositionState rightOutputLayerState;
941 rightOutputLayerState.clearClientTarget = true;
Lloyd Piquea2468662019-03-07 21:31:06 -0800942 rightOutputLayerState.visibleRegion = Region{Rect{1000, 0, 2000, 1000}};
Lloyd Piquec2d54d42019-08-28 18:04:21 -0700943
Lloyd Pique9755fb72019-03-26 14:44:40 -0700944 LayerFECompositionState rightLayerFEState;
945 rightLayerFEState.isOpaque = true;
Lloyd Piquec2d54d42019-08-28 18:04:21 -0700946
947 const half3 rightLayerColor{0.f, 1.f, 0.f};
948 renderengine::LayerSettings rightLayerRESettings;
949 rightLayerRESettings.geometry.boundaries = FloatRect{456, 0, 0, 0};
950 rightLayerRESettings.source.solidColor = rightLayerColor;
951
Lloyd Pique01c77c12019-04-17 12:48:32 -0700952 EXPECT_CALL(leftOutputLayer, getState()).WillRepeatedly(ReturnRef(leftOutputLayerState));
953 EXPECT_CALL(leftOutputLayer, getLayer()).WillRepeatedly(ReturnRef(leftLayer));
954 EXPECT_CALL(leftOutputLayer, getLayerFE()).WillRepeatedly(ReturnRef(leftLayerFE));
955 EXPECT_CALL(leftOutputLayer, requiresClientComposition()).WillRepeatedly(Return(false));
956 EXPECT_CALL(leftOutputLayer, needsFiltering()).WillRepeatedly(Return(false));
Lloyd Pique9755fb72019-03-26 14:44:40 -0700957 EXPECT_CALL(leftLayer, getFEState()).WillRepeatedly(ReturnRef(leftLayerFEState));
Lloyd Piquec2d54d42019-08-28 18:04:21 -0700958
Lloyd Pique01c77c12019-04-17 12:48:32 -0700959 EXPECT_CALL(rightOutputLayer, getState()).WillRepeatedly(ReturnRef(rightOutputLayerState));
960 EXPECT_CALL(rightOutputLayer, getLayer()).WillRepeatedly(ReturnRef(rightLayer));
961 EXPECT_CALL(rightOutputLayer, getLayerFE()).WillRepeatedly(ReturnRef(rightLayerFE));
962 EXPECT_CALL(rightOutputLayer, requiresClientComposition()).WillRepeatedly(Return(false));
963 EXPECT_CALL(rightOutputLayer, needsFiltering()).WillRepeatedly(Return(false));
Lloyd Pique9755fb72019-03-26 14:44:40 -0700964 EXPECT_CALL(rightLayer, getFEState()).WillRepeatedly(ReturnRef(rightLayerFEState));
Lloyd Piquec2d54d42019-08-28 18:04:21 -0700965 EXPECT_CALL(rightLayerFE, prepareClientComposition(_)).WillOnce(Return(rightLayerRESettings));
966
Lloyd Pique01c77c12019-04-17 12:48:32 -0700967 EXPECT_CALL(mOutput, getOutputLayerCount()).WillRepeatedly(Return(2u));
968 EXPECT_CALL(mOutput, getOutputLayerOrderedByZByIndex(0u))
969 .WillRepeatedly(Return(&leftOutputLayer));
970 EXPECT_CALL(mOutput, getOutputLayerOrderedByZByIndex(1u))
971 .WillRepeatedly(Return(&rightOutputLayer));
Lloyd Piquec2d54d42019-08-28 18:04:21 -0700972
973 const Rect kPortraitFrame(0, 0, 1000, 2000);
974 const Rect kPortraitViewport(0, 0, 2000, 1000);
975 const Rect kPortraitScissor(0, 0, 1000, 2000);
976 const uint32_t kPortraitOrientation = TR_ROT_90;
977
978 mOutput.editState().frame = kPortraitFrame;
979 mOutput.editState().viewport = kPortraitViewport;
980 mOutput.editState().scissor = kPortraitScissor;
981 mOutput.editState().transform = ui::Transform{kPortraitOrientation};
982 mOutput.editState().orientation = kPortraitOrientation;
983 mOutput.editState().needsFiltering = true;
984 mOutput.editState().isSecure = false;
985
986 constexpr bool supportsProtectedContent = false;
987 Region clearRegion;
988 auto requests =
989 mOutput.generateClientCompositionRequests(supportsProtectedContent, clearRegion);
990
991 const half3 clearColor{0.f, 0.f, 0.f};
992
993 ASSERT_EQ(1u, requests.size());
994 EXPECT_EQ(456.f, requests[0].geometry.boundaries.left);
995 EXPECT_EQ(clearColor, requests[0].source.solidColor);
996}
997
Lloyd Pique32cbe282018-10-19 13:09:22 -0700998} // namespace
999} // namespace android::compositionengine