blob: 02bb1464cefa25d9dbc92525fcf6e7870daf1738 [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 Pique17ca7422019-11-14 14:24:10 -080019#include <android-base/stringprintf.h>
Lloyd Pique9755fb72019-03-26 14:44:40 -070020#include <compositionengine/LayerFECompositionState.h>
Lloyd Pique32cbe282018-10-19 13:09:22 -070021#include <compositionengine/impl/Output.h>
Lloyd Pique66d68602019-02-13 14:23:31 -080022#include <compositionengine/impl/OutputCompositionState.h>
Lloyd Pique56eba802019-08-28 15:45:25 -070023#include <compositionengine/impl/OutputLayerCompositionState.h>
Lloyd Pique32cbe282018-10-19 13:09:22 -070024#include <compositionengine/mock/CompositionEngine.h>
Lloyd Pique3d0c02e2018-10-19 18:38:12 -070025#include <compositionengine/mock/DisplayColorProfile.h>
Lloyd Piquecc01a452018-12-04 17:24:00 -080026#include <compositionengine/mock/Layer.h>
27#include <compositionengine/mock/LayerFE.h>
28#include <compositionengine/mock/OutputLayer.h>
Lloyd Pique31cb2942018-10-19 17:23:03 -070029#include <compositionengine/mock/RenderSurface.h>
Lloyd Pique32cbe282018-10-19 13:09:22 -070030#include <gtest/gtest.h>
Lloyd Pique56eba802019-08-28 15:45:25 -070031#include <renderengine/mock/RenderEngine.h>
Lloyd Pique32cbe282018-10-19 13:09:22 -070032#include <ui/Rect.h>
33#include <ui/Region.h>
34
Lloyd Pique17ca7422019-11-14 14:24:10 -080035#include "CallOrderStateMachineHelper.h"
Lloyd Pique32cbe282018-10-19 13:09:22 -070036#include "RegionMatcher.h"
37#include "TransformMatcher.h"
38
39namespace android::compositionengine {
40namespace {
41
Lloyd Pique56eba802019-08-28 15:45:25 -070042using testing::_;
Lloyd Pique03561a62019-11-19 18:34:52 -080043using testing::ByMove;
Lloyd Pique17ca7422019-11-14 14:24:10 -080044using testing::DoAll;
Lloyd Piquefaa3f192019-11-14 14:05:09 -080045using testing::InSequence;
Lloyd Pique17ca7422019-11-14 14:24:10 -080046using testing::Mock;
Lloyd Piquefaa3f192019-11-14 14:05:09 -080047using testing::Ref;
Lloyd Pique31cb2942018-10-19 17:23:03 -070048using testing::Return;
Lloyd Pique32cbe282018-10-19 13:09:22 -070049using testing::ReturnRef;
Lloyd Pique17ca7422019-11-14 14:24:10 -080050using testing::SetArgPointee;
Lloyd Pique32cbe282018-10-19 13:09:22 -070051using testing::StrictMock;
52
Lloyd Pique56eba802019-08-28 15:45:25 -070053constexpr auto TR_IDENT = 0u;
54constexpr auto TR_ROT_90 = HAL_TRANSFORM_ROT_90;
55
Lloyd Pique3eb1b212019-03-07 21:15:40 -080056const mat4 kIdentity;
57const mat4 kNonIdentityHalf = mat4() * 0.5;
58const mat4 kNonIdentityQuarter = mat4() * 0.25;
59
Lloyd Pique17ca7422019-11-14 14:24:10 -080060constexpr OutputColorSetting kVendorSpecifiedOutputColorSetting =
61 static_cast<OutputColorSetting>(0x100);
62
Lloyd Piquefaa3f192019-11-14 14:05:09 -080063struct OutputPartialMockBase : public impl::Output {
64 // compositionengine::Output overrides
65 const OutputCompositionState& getState() const override { return mState; }
66 OutputCompositionState& editState() override { return mState; }
67
68 // Use mocks for all the remaining virtual functions
69 // not implemented by the base implementation class.
70 MOCK_CONST_METHOD0(getOutputLayerCount, size_t());
71 MOCK_CONST_METHOD1(getOutputLayerOrderedByZByIndex, compositionengine::OutputLayer*(size_t));
72 MOCK_METHOD3(ensureOutputLayer,
73 compositionengine::OutputLayer*(std::optional<size_t>,
74 const std::shared_ptr<compositionengine::Layer>&,
75 const sp<LayerFE>&));
76 MOCK_METHOD0(finalizePendingOutputLayers, void());
77 MOCK_METHOD0(clearOutputLayers, void());
78 MOCK_CONST_METHOD1(dumpState, void(std::string&));
79 MOCK_CONST_METHOD0(getCompositionEngine, const CompositionEngine&());
80 MOCK_METHOD2(injectOutputLayerForTest,
81 compositionengine::OutputLayer*(const std::shared_ptr<compositionengine::Layer>&,
82 const sp<LayerFE>&));
83 MOCK_METHOD1(injectOutputLayerForTest, void(std::unique_ptr<OutputLayer>));
84
85 impl::OutputCompositionState mState;
86};
87
Lloyd Pique66d68602019-02-13 14:23:31 -080088struct OutputTest : public testing::Test {
Lloyd Pique01c77c12019-04-17 12:48:32 -070089 class Output : public impl::Output {
90 public:
91 using impl::Output::injectOutputLayerForTest;
92 virtual void injectOutputLayerForTest(std::unique_ptr<compositionengine::OutputLayer>) = 0;
93 };
94
95 static std::shared_ptr<Output> createOutput(
96 const compositionengine::CompositionEngine& compositionEngine) {
97 return impl::createOutputTemplated<Output>(compositionEngine);
98 }
99
Lloyd Pique31cb2942018-10-19 17:23:03 -0700100 OutputTest() {
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700101 mOutput->setDisplayColorProfileForTest(
Lloyd Pique3d0c02e2018-10-19 18:38:12 -0700102 std::unique_ptr<DisplayColorProfile>(mDisplayColorProfile));
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700103 mOutput->setRenderSurfaceForTest(std::unique_ptr<RenderSurface>(mRenderSurface));
Lloyd Piqueef958122019-02-05 18:00:12 -0800104
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700105 mOutput->editState().bounds = kDefaultDisplaySize;
Lloyd Pique31cb2942018-10-19 17:23:03 -0700106 }
Lloyd Pique32cbe282018-10-19 13:09:22 -0700107
Lloyd Piqueef958122019-02-05 18:00:12 -0800108 static const Rect kDefaultDisplaySize;
109
Lloyd Pique32cbe282018-10-19 13:09:22 -0700110 StrictMock<mock::CompositionEngine> mCompositionEngine;
Lloyd Pique3d0c02e2018-10-19 18:38:12 -0700111 mock::DisplayColorProfile* mDisplayColorProfile = new StrictMock<mock::DisplayColorProfile>();
Lloyd Pique31cb2942018-10-19 17:23:03 -0700112 mock::RenderSurface* mRenderSurface = new StrictMock<mock::RenderSurface>();
Lloyd Pique01c77c12019-04-17 12:48:32 -0700113 std::shared_ptr<Output> mOutput = createOutput(mCompositionEngine);
Lloyd Pique32cbe282018-10-19 13:09:22 -0700114};
115
Lloyd Piquec0ee6ba2019-11-14 12:55:53 -0800116// Extension of the base test useful for checking interactions with the LayerFE
117// functions to latch composition state.
118struct OutputLatchFEStateTest : public OutputTest {
119 OutputLatchFEStateTest() {
120 EXPECT_CALL(*mOutputLayer1, getLayer()).WillRepeatedly(ReturnRef(mLayer1));
121 EXPECT_CALL(*mOutputLayer2, getLayer()).WillRepeatedly(ReturnRef(mLayer2));
122 EXPECT_CALL(*mOutputLayer3, getLayer()).WillRepeatedly(ReturnRef(mLayer3));
123
124 EXPECT_CALL(*mOutputLayer1, getLayerFE()).WillRepeatedly(ReturnRef(mLayer1FE));
125 EXPECT_CALL(*mOutputLayer2, getLayerFE()).WillRepeatedly(ReturnRef(mLayer2FE));
126 EXPECT_CALL(*mOutputLayer3, getLayerFE()).WillRepeatedly(ReturnRef(mLayer3FE));
127
128 EXPECT_CALL(mLayer1, editFEState()).WillRepeatedly(ReturnRef(mLayer1FEState));
129 EXPECT_CALL(mLayer2, editFEState()).WillRepeatedly(ReturnRef(mLayer2FEState));
130 EXPECT_CALL(mLayer3, editFEState()).WillRepeatedly(ReturnRef(mLayer3FEState));
131 }
132
133 void injectLayer(std::unique_ptr<mock::OutputLayer> layer) {
134 mOutput->injectOutputLayerForTest(std::unique_ptr<OutputLayer>(layer.release()));
135 }
136
137 std::unique_ptr<mock::OutputLayer> mOutputLayer1{new StrictMock<mock::OutputLayer>};
138 std::unique_ptr<mock::OutputLayer> mOutputLayer2{new StrictMock<mock::OutputLayer>};
139 std::unique_ptr<mock::OutputLayer> mOutputLayer3{new StrictMock<mock::OutputLayer>};
140
141 StrictMock<mock::Layer> mLayer1;
142 StrictMock<mock::Layer> mLayer2;
143 StrictMock<mock::Layer> mLayer3;
144
145 StrictMock<mock::LayerFE> mLayer1FE;
146 StrictMock<mock::LayerFE> mLayer2FE;
147 StrictMock<mock::LayerFE> mLayer3FE;
148
149 LayerFECompositionState mLayer1FEState;
150 LayerFECompositionState mLayer2FEState;
151 LayerFECompositionState mLayer3FEState;
152};
153
Lloyd Piqueef958122019-02-05 18:00:12 -0800154const Rect OutputTest::kDefaultDisplaySize{100, 200};
155
Lloyd Pique17ca7422019-11-14 14:24:10 -0800156using ColorProfile = compositionengine::Output::ColorProfile;
157
158void dumpColorProfile(ColorProfile profile, std::string& result, const char* name) {
159 android::base::StringAppendF(&result, "%s (%s[%d] %s[%d] %s[%d] %s[%d]) ", name,
160 toString(profile.mode).c_str(), profile.mode,
161 toString(profile.dataspace).c_str(), profile.dataspace,
162 toString(profile.renderIntent).c_str(), profile.renderIntent,
163 toString(profile.colorSpaceAgnosticDataspace).c_str(),
164 profile.colorSpaceAgnosticDataspace);
165}
166
167// Checks for a ColorProfile match
168MATCHER_P(ColorProfileEq, expected, "") {
169 std::string buf;
170 buf.append("ColorProfiles are not equal\n");
171 dumpColorProfile(expected, buf, "expected value");
172 dumpColorProfile(arg, buf, "actual value");
173 *result_listener << buf;
174
175 return (expected.mode == arg.mode) && (expected.dataspace == arg.dataspace) &&
176 (expected.renderIntent == arg.renderIntent) &&
177 (expected.colorSpaceAgnosticDataspace == arg.colorSpaceAgnosticDataspace);
178}
179
Lloyd Pique66d68602019-02-13 14:23:31 -0800180/*
Lloyd Pique32cbe282018-10-19 13:09:22 -0700181 * Basic construction
182 */
183
Lloyd Pique31cb2942018-10-19 17:23:03 -0700184TEST_F(OutputTest, canInstantiateOutput) {
185 // The validation check checks each required component.
Lloyd Pique3d0c02e2018-10-19 18:38:12 -0700186 EXPECT_CALL(*mDisplayColorProfile, isValid()).WillOnce(Return(true));
Lloyd Pique31cb2942018-10-19 17:23:03 -0700187 EXPECT_CALL(*mRenderSurface, isValid()).WillOnce(Return(true));
188
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700189 EXPECT_TRUE(mOutput->isValid());
Lloyd Pique31cb2942018-10-19 17:23:03 -0700190
191 // If we take away the required components, it is no longer valid.
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700192 mOutput->setRenderSurfaceForTest(std::unique_ptr<RenderSurface>());
Lloyd Pique31cb2942018-10-19 17:23:03 -0700193
Lloyd Pique3d0c02e2018-10-19 18:38:12 -0700194 EXPECT_CALL(*mDisplayColorProfile, isValid()).WillOnce(Return(true));
195
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700196 EXPECT_FALSE(mOutput->isValid());
Lloyd Pique31cb2942018-10-19 17:23:03 -0700197}
Lloyd Pique32cbe282018-10-19 13:09:22 -0700198
Lloyd Pique66d68602019-02-13 14:23:31 -0800199/*
Lloyd Pique32cbe282018-10-19 13:09:22 -0700200 * Output::setCompositionEnabled()
201 */
202
203TEST_F(OutputTest, setCompositionEnabledDoesNothingIfAlreadyEnabled) {
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700204 mOutput->editState().isEnabled = true;
Lloyd Pique32cbe282018-10-19 13:09:22 -0700205
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700206 mOutput->setCompositionEnabled(true);
Lloyd Pique32cbe282018-10-19 13:09:22 -0700207
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700208 EXPECT_TRUE(mOutput->getState().isEnabled);
209 EXPECT_THAT(mOutput->getState().dirtyRegion, RegionEq(Region()));
Lloyd Pique32cbe282018-10-19 13:09:22 -0700210}
211
212TEST_F(OutputTest, setCompositionEnabledSetsEnabledAndDirtiesEntireOutput) {
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700213 mOutput->editState().isEnabled = false;
Lloyd Pique32cbe282018-10-19 13:09:22 -0700214
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700215 mOutput->setCompositionEnabled(true);
Lloyd Pique32cbe282018-10-19 13:09:22 -0700216
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700217 EXPECT_TRUE(mOutput->getState().isEnabled);
218 EXPECT_THAT(mOutput->getState().dirtyRegion, RegionEq(Region(kDefaultDisplaySize)));
Lloyd Pique32cbe282018-10-19 13:09:22 -0700219}
220
221TEST_F(OutputTest, setCompositionEnabledSetsDisabledAndDirtiesEntireOutput) {
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700222 mOutput->editState().isEnabled = true;
Lloyd Pique32cbe282018-10-19 13:09:22 -0700223
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700224 mOutput->setCompositionEnabled(false);
Lloyd Pique32cbe282018-10-19 13:09:22 -0700225
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700226 EXPECT_FALSE(mOutput->getState().isEnabled);
227 EXPECT_THAT(mOutput->getState().dirtyRegion, RegionEq(Region(kDefaultDisplaySize)));
Lloyd Pique32cbe282018-10-19 13:09:22 -0700228}
229
Lloyd Pique66d68602019-02-13 14:23:31 -0800230/*
Lloyd Pique32cbe282018-10-19 13:09:22 -0700231 * Output::setProjection()
232 */
233
234TEST_F(OutputTest, setProjectionTriviallyWorks) {
235 const ui::Transform transform{ui::Transform::ROT_180};
236 const int32_t orientation = 123;
237 const Rect frame{1, 2, 3, 4};
238 const Rect viewport{5, 6, 7, 8};
239 const Rect scissor{9, 10, 11, 12};
240 const bool needsFiltering = true;
241
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700242 mOutput->setProjection(transform, orientation, frame, viewport, scissor, needsFiltering);
Lloyd Pique32cbe282018-10-19 13:09:22 -0700243
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700244 EXPECT_THAT(mOutput->getState().transform, TransformEq(transform));
245 EXPECT_EQ(orientation, mOutput->getState().orientation);
246 EXPECT_EQ(frame, mOutput->getState().frame);
247 EXPECT_EQ(viewport, mOutput->getState().viewport);
248 EXPECT_EQ(scissor, mOutput->getState().scissor);
249 EXPECT_EQ(needsFiltering, mOutput->getState().needsFiltering);
Lloyd Pique32cbe282018-10-19 13:09:22 -0700250}
251
Lloyd Pique66d68602019-02-13 14:23:31 -0800252/*
Lloyd Pique32cbe282018-10-19 13:09:22 -0700253 * Output::setBounds()
254 */
255
256TEST_F(OutputTest, setBoundsSetsSizeAndDirtiesEntireOutput) {
Lloyd Piqueef958122019-02-05 18:00:12 -0800257 const ui::Size displaySize{200, 400};
Lloyd Pique31cb2942018-10-19 17:23:03 -0700258
259 EXPECT_CALL(*mRenderSurface, setDisplaySize(displaySize)).Times(1);
260 EXPECT_CALL(*mRenderSurface, getSize()).WillOnce(ReturnRef(displaySize));
261
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700262 mOutput->setBounds(displaySize);
Lloyd Pique32cbe282018-10-19 13:09:22 -0700263
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700264 EXPECT_EQ(Rect(displaySize), mOutput->getState().bounds);
Lloyd Pique32cbe282018-10-19 13:09:22 -0700265
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700266 EXPECT_THAT(mOutput->getState().dirtyRegion, RegionEq(Region(Rect(displaySize))));
Lloyd Pique32cbe282018-10-19 13:09:22 -0700267}
268
Lloyd Pique66d68602019-02-13 14:23:31 -0800269/*
Lloyd Pique32cbe282018-10-19 13:09:22 -0700270 * Output::setLayerStackFilter()
271 */
272
273TEST_F(OutputTest, setLayerStackFilterSetsFilterAndDirtiesEntireOutput) {
Lloyd Pique32cbe282018-10-19 13:09:22 -0700274 const uint32_t layerStack = 123u;
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700275 mOutput->setLayerStackFilter(layerStack, true);
Lloyd Pique32cbe282018-10-19 13:09:22 -0700276
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700277 EXPECT_TRUE(mOutput->getState().layerStackInternal);
278 EXPECT_EQ(layerStack, mOutput->getState().layerStackId);
Lloyd Pique32cbe282018-10-19 13:09:22 -0700279
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700280 EXPECT_THAT(mOutput->getState().dirtyRegion, RegionEq(Region(kDefaultDisplaySize)));
Lloyd Pique32cbe282018-10-19 13:09:22 -0700281}
282
Lloyd Pique66d68602019-02-13 14:23:31 -0800283/*
Lloyd Pique32cbe282018-10-19 13:09:22 -0700284 * Output::setColorTransform
285 */
286
Lloyd Pique3eb1b212019-03-07 21:15:40 -0800287TEST_F(OutputTest, setColorTransformWithNoChangeFlaggedSkipsUpdates) {
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700288 mOutput->editState().colorTransformMatrix = kIdentity;
Lloyd Pique32cbe282018-10-19 13:09:22 -0700289
Lloyd Pique3eb1b212019-03-07 21:15:40 -0800290 // If no colorTransformMatrix is set the update should be skipped.
291 CompositionRefreshArgs refreshArgs;
292 refreshArgs.colorTransformMatrix = std::nullopt;
Lloyd Pique32cbe282018-10-19 13:09:22 -0700293
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700294 mOutput->setColorTransform(refreshArgs);
Lloyd Pique32cbe282018-10-19 13:09:22 -0700295
Lloyd Pique3eb1b212019-03-07 21:15:40 -0800296 // The internal state should be unchanged
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700297 EXPECT_EQ(kIdentity, mOutput->getState().colorTransformMatrix);
Lloyd Pique3eb1b212019-03-07 21:15:40 -0800298
299 // No dirty region should be set
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700300 EXPECT_THAT(mOutput->getState().dirtyRegion, RegionEq(Region()));
Lloyd Pique3eb1b212019-03-07 21:15:40 -0800301}
Lloyd Piqueef958122019-02-05 18:00:12 -0800302
Lloyd Pique3eb1b212019-03-07 21:15:40 -0800303TEST_F(OutputTest, setColorTransformWithNoActualChangeSkipsUpdates) {
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700304 mOutput->editState().colorTransformMatrix = kIdentity;
Lloyd Pique32cbe282018-10-19 13:09:22 -0700305
Lloyd Pique3eb1b212019-03-07 21:15:40 -0800306 // Attempting to set the same colorTransformMatrix that is already set should
307 // also skip the update.
308 CompositionRefreshArgs refreshArgs;
309 refreshArgs.colorTransformMatrix = kIdentity;
Lloyd Pique32cbe282018-10-19 13:09:22 -0700310
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700311 mOutput->setColorTransform(refreshArgs);
Lloyd Pique77f79a22019-04-29 15:55:40 -0700312
Lloyd Pique3eb1b212019-03-07 21:15:40 -0800313 // The internal state should be unchanged
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700314 EXPECT_EQ(kIdentity, mOutput->getState().colorTransformMatrix);
Lloyd Pique3eb1b212019-03-07 21:15:40 -0800315
316 // No dirty region should be set
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700317 EXPECT_THAT(mOutput->getState().dirtyRegion, RegionEq(Region()));
Lloyd Pique3eb1b212019-03-07 21:15:40 -0800318}
319
320TEST_F(OutputTest, setColorTransformPerformsUpdateToIdentity) {
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700321 mOutput->editState().colorTransformMatrix = kNonIdentityHalf;
Lloyd Pique3eb1b212019-03-07 21:15:40 -0800322
323 // Setting a different colorTransformMatrix should perform the update.
324 CompositionRefreshArgs refreshArgs;
325 refreshArgs.colorTransformMatrix = kIdentity;
326
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700327 mOutput->setColorTransform(refreshArgs);
Lloyd Pique3eb1b212019-03-07 21:15:40 -0800328
329 // The internal state should have been updated
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700330 EXPECT_EQ(kIdentity, mOutput->getState().colorTransformMatrix);
Lloyd Pique3eb1b212019-03-07 21:15:40 -0800331
332 // The dirtyRegion should be set to the full display size
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700333 EXPECT_THAT(mOutput->getState().dirtyRegion, RegionEq(Region(kDefaultDisplaySize)));
Lloyd Pique3eb1b212019-03-07 21:15:40 -0800334}
Lloyd Pique77f79a22019-04-29 15:55:40 -0700335
Lloyd Pique3eb1b212019-03-07 21:15:40 -0800336TEST_F(OutputTest, setColorTransformPerformsUpdateForIdentityToHalf) {
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700337 mOutput->editState().colorTransformMatrix = kIdentity;
Lloyd Pique77f79a22019-04-29 15:55:40 -0700338
Lloyd Pique3eb1b212019-03-07 21:15:40 -0800339 // Setting a different colorTransformMatrix should perform the update.
340 CompositionRefreshArgs refreshArgs;
341 refreshArgs.colorTransformMatrix = kNonIdentityHalf;
Lloyd Pique77f79a22019-04-29 15:55:40 -0700342
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700343 mOutput->setColorTransform(refreshArgs);
Lloyd Piqueef958122019-02-05 18:00:12 -0800344
Lloyd Pique3eb1b212019-03-07 21:15:40 -0800345 // The internal state should have been updated
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700346 EXPECT_EQ(kNonIdentityHalf, mOutput->getState().colorTransformMatrix);
Lloyd Pique3eb1b212019-03-07 21:15:40 -0800347
348 // The dirtyRegion should be set to the full display size
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700349 EXPECT_THAT(mOutput->getState().dirtyRegion, RegionEq(Region(kDefaultDisplaySize)));
Lloyd Pique3eb1b212019-03-07 21:15:40 -0800350}
351
352TEST_F(OutputTest, setColorTransformPerformsUpdateForHalfToQuarter) {
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700353 mOutput->editState().colorTransformMatrix = kNonIdentityHalf;
Lloyd Pique3eb1b212019-03-07 21:15:40 -0800354
355 // Setting a different colorTransformMatrix should perform the update.
356 CompositionRefreshArgs refreshArgs;
357 refreshArgs.colorTransformMatrix = kNonIdentityQuarter;
358
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700359 mOutput->setColorTransform(refreshArgs);
Lloyd Pique3eb1b212019-03-07 21:15:40 -0800360
361 // The internal state should have been updated
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700362 EXPECT_EQ(kNonIdentityQuarter, mOutput->getState().colorTransformMatrix);
Lloyd Pique3eb1b212019-03-07 21:15:40 -0800363
364 // The dirtyRegion should be set to the full display size
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700365 EXPECT_THAT(mOutput->getState().dirtyRegion, RegionEq(Region(kDefaultDisplaySize)));
Lloyd Pique32cbe282018-10-19 13:09:22 -0700366}
367
Lloyd Pique66d68602019-02-13 14:23:31 -0800368/*
Lloyd Pique17ca7422019-11-14 14:24:10 -0800369 * Output::setColorProfile
Lloyd Pique32cbe282018-10-19 13:09:22 -0700370 */
371
Lloyd Pique17ca7422019-11-14 14:24:10 -0800372using OutputSetColorProfileTest = OutputTest;
373
374TEST_F(OutputSetColorProfileTest, setsStateAndDirtiesOutputIfChanged) {
Lloyd Pique6a3b4462019-03-07 20:58:12 -0800375 using ColorProfile = Output::ColorProfile;
376
Lloyd Piquef5275482019-01-29 18:42:42 -0800377 EXPECT_CALL(*mDisplayColorProfile,
378 getTargetDataspace(ui::ColorMode::DISPLAY_P3, ui::Dataspace::DISPLAY_P3,
379 ui::Dataspace::UNKNOWN))
380 .WillOnce(Return(ui::Dataspace::UNKNOWN));
Lloyd Piqueef958122019-02-05 18:00:12 -0800381 EXPECT_CALL(*mRenderSurface, setBufferDataspace(ui::Dataspace::DISPLAY_P3)).Times(1);
Lloyd Pique31cb2942018-10-19 17:23:03 -0700382
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700383 mOutput->setColorProfile(ColorProfile{ui::ColorMode::DISPLAY_P3, ui::Dataspace::DISPLAY_P3,
384 ui::RenderIntent::TONE_MAP_COLORIMETRIC,
385 ui::Dataspace::UNKNOWN});
Lloyd Pique32cbe282018-10-19 13:09:22 -0700386
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700387 EXPECT_EQ(ui::ColorMode::DISPLAY_P3, mOutput->getState().colorMode);
388 EXPECT_EQ(ui::Dataspace::DISPLAY_P3, mOutput->getState().dataspace);
389 EXPECT_EQ(ui::RenderIntent::TONE_MAP_COLORIMETRIC, mOutput->getState().renderIntent);
390 EXPECT_EQ(ui::Dataspace::UNKNOWN, mOutput->getState().targetDataspace);
Lloyd Piquef5275482019-01-29 18:42:42 -0800391
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700392 EXPECT_THAT(mOutput->getState().dirtyRegion, RegionEq(Region(kDefaultDisplaySize)));
Lloyd Piqueef958122019-02-05 18:00:12 -0800393}
394
Lloyd Pique17ca7422019-11-14 14:24:10 -0800395TEST_F(OutputSetColorProfileTest, doesNothingIfNoChange) {
Lloyd Pique6a3b4462019-03-07 20:58:12 -0800396 using ColorProfile = Output::ColorProfile;
397
Lloyd Piquef5275482019-01-29 18:42:42 -0800398 EXPECT_CALL(*mDisplayColorProfile,
399 getTargetDataspace(ui::ColorMode::DISPLAY_P3, ui::Dataspace::DISPLAY_P3,
400 ui::Dataspace::UNKNOWN))
401 .WillOnce(Return(ui::Dataspace::UNKNOWN));
402
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700403 mOutput->editState().colorMode = ui::ColorMode::DISPLAY_P3;
404 mOutput->editState().dataspace = ui::Dataspace::DISPLAY_P3;
405 mOutput->editState().renderIntent = ui::RenderIntent::TONE_MAP_COLORIMETRIC;
406 mOutput->editState().targetDataspace = ui::Dataspace::UNKNOWN;
Lloyd Piqueef958122019-02-05 18:00:12 -0800407
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700408 mOutput->setColorProfile(ColorProfile{ui::ColorMode::DISPLAY_P3, ui::Dataspace::DISPLAY_P3,
409 ui::RenderIntent::TONE_MAP_COLORIMETRIC,
410 ui::Dataspace::UNKNOWN});
Lloyd Piqueef958122019-02-05 18:00:12 -0800411
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700412 EXPECT_THAT(mOutput->getState().dirtyRegion, RegionEq(Region()));
Lloyd Pique32cbe282018-10-19 13:09:22 -0700413}
414
Lloyd Pique66d68602019-02-13 14:23:31 -0800415/*
Lloyd Pique31cb2942018-10-19 17:23:03 -0700416 * Output::setRenderSurface()
417 */
418
419TEST_F(OutputTest, setRenderSurfaceResetsBounds) {
420 const ui::Size newDisplaySize{640, 480};
421
422 mock::RenderSurface* renderSurface = new StrictMock<mock::RenderSurface>();
423 EXPECT_CALL(*renderSurface, getSize()).WillOnce(ReturnRef(newDisplaySize));
424
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700425 mOutput->setRenderSurface(std::unique_ptr<RenderSurface>(renderSurface));
Lloyd Pique31cb2942018-10-19 17:23:03 -0700426
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700427 EXPECT_EQ(Rect(newDisplaySize), mOutput->getState().bounds);
Lloyd Pique31cb2942018-10-19 17:23:03 -0700428}
429
Lloyd Pique66d68602019-02-13 14:23:31 -0800430/*
Alec Mourie7d1d4a2019-02-05 01:13:46 +0000431 * Output::getDirtyRegion()
Lloyd Pique32cbe282018-10-19 13:09:22 -0700432 */
433
Alec Mourie7d1d4a2019-02-05 01:13:46 +0000434TEST_F(OutputTest, getDirtyRegionWithRepaintEverythingTrue) {
435 const Rect viewport{100, 200};
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700436 mOutput->editState().viewport = viewport;
437 mOutput->editState().dirtyRegion.set(50, 300);
Lloyd Pique32cbe282018-10-19 13:09:22 -0700438
439 {
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700440 Region result = mOutput->getDirtyRegion(true);
Lloyd Pique32cbe282018-10-19 13:09:22 -0700441
Alec Mourie7d1d4a2019-02-05 01:13:46 +0000442 EXPECT_THAT(result, RegionEq(Region(viewport)));
Lloyd Pique32cbe282018-10-19 13:09:22 -0700443 }
444}
445
Alec Mourie7d1d4a2019-02-05 01:13:46 +0000446TEST_F(OutputTest, getDirtyRegionWithRepaintEverythingFalse) {
447 const Rect viewport{100, 200};
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700448 mOutput->editState().viewport = viewport;
449 mOutput->editState().dirtyRegion.set(50, 300);
Lloyd Pique32cbe282018-10-19 13:09:22 -0700450
451 {
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700452 Region result = mOutput->getDirtyRegion(false);
Lloyd Pique32cbe282018-10-19 13:09:22 -0700453
454 // The dirtyRegion should be clipped to the display bounds.
455 EXPECT_THAT(result, RegionEq(Region(Rect(50, 200))));
456 }
Lloyd Pique32cbe282018-10-19 13:09:22 -0700457}
458
Lloyd Pique66d68602019-02-13 14:23:31 -0800459/*
Lloyd Piqueef36b002019-01-23 17:52:04 -0800460 * Output::belongsInOutput()
461 */
462
463TEST_F(OutputTest, belongsInOutputFiltersAsExpected) {
464 const uint32_t layerStack1 = 123u;
465 const uint32_t layerStack2 = 456u;
466
467 // If the output accepts layerStack1 and internal-only layers....
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700468 mOutput->setLayerStackFilter(layerStack1, true);
Lloyd Piqueef36b002019-01-23 17:52:04 -0800469
Lloyd Piquec6687342019-03-07 21:34:57 -0800470 // A layer with no layerStack does not belong to it, internal-only or not.
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700471 EXPECT_FALSE(mOutput->belongsInOutput(std::nullopt, false));
472 EXPECT_FALSE(mOutput->belongsInOutput(std::nullopt, true));
Lloyd Piquec6687342019-03-07 21:34:57 -0800473
Lloyd Piqueef36b002019-01-23 17:52:04 -0800474 // Any layer with layerStack1 belongs to it, internal-only or not.
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700475 EXPECT_TRUE(mOutput->belongsInOutput(layerStack1, false));
476 EXPECT_TRUE(mOutput->belongsInOutput(layerStack1, true));
477 EXPECT_FALSE(mOutput->belongsInOutput(layerStack2, true));
478 EXPECT_FALSE(mOutput->belongsInOutput(layerStack2, false));
Lloyd Piqueef36b002019-01-23 17:52:04 -0800479
480 // If the output accepts layerStack21 but not internal-only layers...
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700481 mOutput->setLayerStackFilter(layerStack1, false);
Lloyd Piqueef36b002019-01-23 17:52:04 -0800482
483 // Only non-internal layers with layerStack1 belong to it.
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700484 EXPECT_TRUE(mOutput->belongsInOutput(layerStack1, false));
485 EXPECT_FALSE(mOutput->belongsInOutput(layerStack1, true));
486 EXPECT_FALSE(mOutput->belongsInOutput(layerStack2, true));
487 EXPECT_FALSE(mOutput->belongsInOutput(layerStack2, false));
Lloyd Piqueef36b002019-01-23 17:52:04 -0800488}
489
Lloyd Pique66c20c42019-03-07 21:44:02 -0800490TEST_F(OutputTest, belongsInOutputFiltersLayersAsExpected) {
491 StrictMock<mock::Layer> layer;
Lloyd Pique9755fb72019-03-26 14:44:40 -0700492 LayerFECompositionState layerFEState;
Lloyd Pique66c20c42019-03-07 21:44:02 -0800493
Lloyd Pique9755fb72019-03-26 14:44:40 -0700494 EXPECT_CALL(layer, getFEState()).WillRepeatedly(ReturnRef(layerFEState));
Lloyd Pique66c20c42019-03-07 21:44:02 -0800495
496 const uint32_t layerStack1 = 123u;
497 const uint32_t layerStack2 = 456u;
498
499 // If the output accepts layerStack1 and internal-only layers....
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700500 mOutput->setLayerStackFilter(layerStack1, true);
Lloyd Pique66c20c42019-03-07 21:44:02 -0800501
502 // A null layer pointer does not belong to the output
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700503 EXPECT_FALSE(mOutput->belongsInOutput(nullptr));
Lloyd Pique66c20c42019-03-07 21:44:02 -0800504
505 // A layer with no layerStack does not belong to it, internal-only or not.
Lloyd Pique9755fb72019-03-26 14:44:40 -0700506 layerFEState.layerStackId = std::nullopt;
507 layerFEState.internalOnly = false;
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700508 EXPECT_FALSE(mOutput->belongsInOutput(&layer));
Lloyd Pique66c20c42019-03-07 21:44:02 -0800509
Lloyd Pique9755fb72019-03-26 14:44:40 -0700510 layerFEState.layerStackId = std::nullopt;
511 layerFEState.internalOnly = true;
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700512 EXPECT_FALSE(mOutput->belongsInOutput(&layer));
Lloyd Pique66c20c42019-03-07 21:44:02 -0800513
514 // Any layer with layerStack1 belongs to it, internal-only or not.
Lloyd Pique9755fb72019-03-26 14:44:40 -0700515 layerFEState.layerStackId = layerStack1;
516 layerFEState.internalOnly = false;
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700517 EXPECT_TRUE(mOutput->belongsInOutput(&layer));
Lloyd Pique66c20c42019-03-07 21:44:02 -0800518
Lloyd Pique9755fb72019-03-26 14:44:40 -0700519 layerFEState.layerStackId = layerStack1;
520 layerFEState.internalOnly = true;
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700521 EXPECT_TRUE(mOutput->belongsInOutput(&layer));
Lloyd Pique66c20c42019-03-07 21:44:02 -0800522
Lloyd Pique9755fb72019-03-26 14:44:40 -0700523 layerFEState.layerStackId = layerStack2;
524 layerFEState.internalOnly = true;
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700525 EXPECT_FALSE(mOutput->belongsInOutput(&layer));
Lloyd Pique66c20c42019-03-07 21:44:02 -0800526
Lloyd Pique9755fb72019-03-26 14:44:40 -0700527 layerFEState.layerStackId = layerStack2;
528 layerFEState.internalOnly = false;
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700529 EXPECT_FALSE(mOutput->belongsInOutput(&layer));
Lloyd Pique66c20c42019-03-07 21:44:02 -0800530
531 // If the output accepts layerStack1 but not internal-only layers...
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700532 mOutput->setLayerStackFilter(layerStack1, false);
Lloyd Pique66c20c42019-03-07 21:44:02 -0800533
534 // A null layer pointer does not belong to the output
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700535 EXPECT_FALSE(mOutput->belongsInOutput(nullptr));
Lloyd Pique66c20c42019-03-07 21:44:02 -0800536
537 // Only non-internal layers with layerStack1 belong to it.
Lloyd Pique9755fb72019-03-26 14:44:40 -0700538 layerFEState.layerStackId = layerStack1;
539 layerFEState.internalOnly = false;
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700540 EXPECT_TRUE(mOutput->belongsInOutput(&layer));
Lloyd Pique66c20c42019-03-07 21:44:02 -0800541
Lloyd Pique9755fb72019-03-26 14:44:40 -0700542 layerFEState.layerStackId = layerStack1;
543 layerFEState.internalOnly = true;
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700544 EXPECT_FALSE(mOutput->belongsInOutput(&layer));
Lloyd Pique66c20c42019-03-07 21:44:02 -0800545
Lloyd Pique9755fb72019-03-26 14:44:40 -0700546 layerFEState.layerStackId = layerStack2;
547 layerFEState.internalOnly = true;
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700548 EXPECT_FALSE(mOutput->belongsInOutput(&layer));
Lloyd Pique66c20c42019-03-07 21:44:02 -0800549
Lloyd Pique9755fb72019-03-26 14:44:40 -0700550 layerFEState.layerStackId = layerStack2;
551 layerFEState.internalOnly = false;
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700552 EXPECT_FALSE(mOutput->belongsInOutput(&layer));
Lloyd Pique66c20c42019-03-07 21:44:02 -0800553}
554
Lloyd Pique66d68602019-02-13 14:23:31 -0800555/*
Lloyd Piquecc01a452018-12-04 17:24:00 -0800556 * Output::getOutputLayerForLayer()
557 */
558
559TEST_F(OutputTest, getOutputLayerForLayerWorks) {
560 mock::OutputLayer* outputLayer1 = new StrictMock<mock::OutputLayer>();
561 mock::OutputLayer* outputLayer2 = new StrictMock<mock::OutputLayer>();
562
Lloyd Pique01c77c12019-04-17 12:48:32 -0700563 mOutput->injectOutputLayerForTest(std::unique_ptr<OutputLayer>(outputLayer1));
564 mOutput->injectOutputLayerForTest(nullptr);
565 mOutput->injectOutputLayerForTest(std::unique_ptr<OutputLayer>(outputLayer2));
Lloyd Piquecc01a452018-12-04 17:24:00 -0800566
567 StrictMock<mock::Layer> layer;
568 StrictMock<mock::Layer> otherLayer;
569
570 // If the input layer matches the first OutputLayer, it will be returned.
571 EXPECT_CALL(*outputLayer1, getLayer()).WillOnce(ReturnRef(layer));
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700572 EXPECT_EQ(outputLayer1, mOutput->getOutputLayerForLayer(&layer));
Lloyd Piquecc01a452018-12-04 17:24:00 -0800573
574 // If the input layer matches the second OutputLayer, it will be returned.
575 EXPECT_CALL(*outputLayer1, getLayer()).WillOnce(ReturnRef(otherLayer));
576 EXPECT_CALL(*outputLayer2, getLayer()).WillOnce(ReturnRef(layer));
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700577 EXPECT_EQ(outputLayer2, mOutput->getOutputLayerForLayer(&layer));
Lloyd Piquecc01a452018-12-04 17:24:00 -0800578
579 // If the input layer does not match an output layer, null will be returned.
580 EXPECT_CALL(*outputLayer1, getLayer()).WillOnce(ReturnRef(otherLayer));
581 EXPECT_CALL(*outputLayer2, getLayer()).WillOnce(ReturnRef(otherLayer));
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700582 EXPECT_EQ(nullptr, mOutput->getOutputLayerForLayer(&layer));
Lloyd Piquecc01a452018-12-04 17:24:00 -0800583}
584
Lloyd Pique66d68602019-02-13 14:23:31 -0800585/*
Lloyd Piquec9e60032019-11-14 11:47:26 -0800586 * Output::setReleasedLayers()
587 */
588
589using OutputSetReleasedLayersTest = OutputTest;
590
591TEST_F(OutputSetReleasedLayersTest, setReleasedLayersTakesGivenLayers) {
592 sp<StrictMock<mock::LayerFE>> layer1FE{new StrictMock<mock::LayerFE>()};
593 sp<StrictMock<mock::LayerFE>> layer2FE{new StrictMock<mock::LayerFE>()};
594 sp<StrictMock<mock::LayerFE>> layer3FE{new StrictMock<mock::LayerFE>()};
595
596 Output::ReleasedLayers layers;
597 layers.push_back(layer1FE);
598 layers.push_back(layer2FE);
599 layers.push_back(layer3FE);
600
601 mOutput->setReleasedLayers(std::move(layers));
602
603 const auto& setLayers = mOutput->getReleasedLayersForTest();
604 ASSERT_EQ(3u, setLayers.size());
605 ASSERT_EQ(layer1FE.get(), setLayers[0].promote().get());
606 ASSERT_EQ(layer2FE.get(), setLayers[1].promote().get());
607 ASSERT_EQ(layer3FE.get(), setLayers[2].promote().get());
608}
609
610/*
Lloyd Piquec0ee6ba2019-11-14 12:55:53 -0800611 * Output::updateLayerStateFromFE()
612 */
613
614using OutputUpdateLayerStateFromFETest = OutputLatchFEStateTest;
615
616TEST_F(OutputUpdateLayerStateFromFETest, handlesNoOutputLayerCase) {
617 CompositionRefreshArgs refreshArgs;
618
619 mOutput->updateLayerStateFromFE(refreshArgs);
620}
621
622TEST_F(OutputUpdateLayerStateFromFETest, latchesContentStateForAllContainedLayers) {
623 EXPECT_CALL(mLayer1FE,
624 latchCompositionState(Ref(mLayer1FEState), LayerFE::StateSubset::Content));
625 EXPECT_CALL(mLayer2FE,
626 latchCompositionState(Ref(mLayer2FEState), LayerFE::StateSubset::Content));
627 EXPECT_CALL(mLayer3FE,
628 latchCompositionState(Ref(mLayer3FEState), LayerFE::StateSubset::Content));
629
630 // Note: Must be performed after any expectations on these mocks
631 injectLayer(std::move(mOutputLayer1));
632 injectLayer(std::move(mOutputLayer2));
633 injectLayer(std::move(mOutputLayer3));
634
635 CompositionRefreshArgs refreshArgs;
636 refreshArgs.updatingGeometryThisFrame = false;
637
638 mOutput->updateLayerStateFromFE(refreshArgs);
639}
640
641TEST_F(OutputUpdateLayerStateFromFETest, latchesGeometryAndContentStateForAllContainedLayers) {
642 EXPECT_CALL(mLayer1FE,
643 latchCompositionState(Ref(mLayer1FEState),
644 LayerFE::StateSubset::GeometryAndContent));
645 EXPECT_CALL(mLayer2FE,
646 latchCompositionState(Ref(mLayer2FEState),
647 LayerFE::StateSubset::GeometryAndContent));
648 EXPECT_CALL(mLayer3FE,
649 latchCompositionState(Ref(mLayer3FEState),
650 LayerFE::StateSubset::GeometryAndContent));
651
652 // Note: Must be performed after any expectations on these mocks
653 injectLayer(std::move(mOutputLayer1));
654 injectLayer(std::move(mOutputLayer2));
655 injectLayer(std::move(mOutputLayer3));
656
657 CompositionRefreshArgs refreshArgs;
658 refreshArgs.updatingGeometryThisFrame = true;
659
660 mOutput->updateLayerStateFromFE(refreshArgs);
661}
662
663/*
Alec Mourif9a2a2c2019-11-12 12:46:02 -0800664 * Output::updateAndWriteCompositionState()
665 */
666
667TEST_F(OutputTest, updateAndWriteCompositionState_takesEarlyOutIfNotEnabled) {
668 mOutput->editState().isEnabled = false;
669
670 CompositionRefreshArgs args;
671 mOutput->updateAndWriteCompositionState(args);
672}
673
674TEST_F(OutputTest, updateAndWriteCompositionState_updatesLayers) {
675 mOutput->editState().isEnabled = true;
676 mock::OutputLayer* outputLayer = new StrictMock<mock::OutputLayer>();
677 mOutput->injectOutputLayerForTest(std::unique_ptr<OutputLayer>(outputLayer));
678
679 EXPECT_CALL(*outputLayer, updateCompositionState(true, true)).Times(1);
680 EXPECT_CALL(*outputLayer, writeStateToHWC(true)).Times(1);
681
682 CompositionRefreshArgs args;
683 args.updatingGeometryThisFrame = true;
684 args.devOptForceClientComposition = true;
685 mOutput->updateAndWriteCompositionState(args);
686}
687
688/*
Lloyd Pique66d68602019-02-13 14:23:31 -0800689 * Output::prepareFrame()
690 */
691
692struct OutputPrepareFrameTest : public testing::Test {
Lloyd Piquefaa3f192019-11-14 14:05:09 -0800693 struct OutputPartialMock : public OutputPartialMockBase {
Lloyd Pique66d68602019-02-13 14:23:31 -0800694 // Sets up the helper functions called by prepareFrame to use a mock
695 // implementations.
696 MOCK_METHOD0(chooseCompositionStrategy, void());
697 };
698
699 OutputPrepareFrameTest() {
700 mOutput.setDisplayColorProfileForTest(
701 std::unique_ptr<DisplayColorProfile>(mDisplayColorProfile));
702 mOutput.setRenderSurfaceForTest(std::unique_ptr<RenderSurface>(mRenderSurface));
703 }
704
705 StrictMock<mock::CompositionEngine> mCompositionEngine;
706 mock::DisplayColorProfile* mDisplayColorProfile = new StrictMock<mock::DisplayColorProfile>();
707 mock::RenderSurface* mRenderSurface = new StrictMock<mock::RenderSurface>();
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700708 StrictMock<OutputPartialMock> mOutput;
Lloyd Pique66d68602019-02-13 14:23:31 -0800709};
710
711TEST_F(OutputPrepareFrameTest, takesEarlyOutIfNotEnabled) {
712 mOutput.editState().isEnabled = false;
713
714 mOutput.prepareFrame();
715}
716
717TEST_F(OutputPrepareFrameTest, delegatesToChooseCompositionStrategyAndRenderSurface) {
718 mOutput.editState().isEnabled = true;
719 mOutput.editState().usesClientComposition = false;
720 mOutput.editState().usesDeviceComposition = true;
721
722 EXPECT_CALL(mOutput, chooseCompositionStrategy()).Times(1);
723 EXPECT_CALL(*mRenderSurface, prepareFrame(false, true));
724
725 mOutput.prepareFrame();
726}
727
728// Note: Use OutputTest and not OutputPrepareFrameTest, so the real
729// base chooseCompositionStrategy() is invoked.
730TEST_F(OutputTest, prepareFrameSetsClientCompositionOnlyByDefault) {
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700731 mOutput->editState().isEnabled = true;
732 mOutput->editState().usesClientComposition = false;
733 mOutput->editState().usesDeviceComposition = true;
Lloyd Pique66d68602019-02-13 14:23:31 -0800734
735 EXPECT_CALL(*mRenderSurface, prepareFrame(true, false));
736
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700737 mOutput->prepareFrame();
Lloyd Pique66d68602019-02-13 14:23:31 -0800738
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700739 EXPECT_TRUE(mOutput->getState().usesClientComposition);
740 EXPECT_FALSE(mOutput->getState().usesDeviceComposition);
Lloyd Pique66d68602019-02-13 14:23:31 -0800741}
742
Lloyd Pique56eba802019-08-28 15:45:25 -0700743/*
Lloyd Piquefaa3f192019-11-14 14:05:09 -0800744 * Output::present()
745 */
746
747struct OutputPresentTest : public testing::Test {
748 struct OutputPartialMock : public OutputPartialMockBase {
749 // All child helper functions Output::present() are defined as mocks,
750 // and those are tested separately, allowing the present() test to
751 // just cover the high level flow.
752 MOCK_METHOD1(updateColorProfile, void(const compositionengine::CompositionRefreshArgs&));
753 MOCK_METHOD1(updateAndWriteCompositionState,
754 void(const compositionengine::CompositionRefreshArgs&));
755 MOCK_METHOD1(setColorTransform, void(const compositionengine::CompositionRefreshArgs&));
756 MOCK_METHOD0(beginFrame, void());
757 MOCK_METHOD0(prepareFrame, void());
758 MOCK_METHOD1(devOptRepaintFlash, void(const compositionengine::CompositionRefreshArgs&));
759 MOCK_METHOD1(finishFrame, void(const compositionengine::CompositionRefreshArgs&));
760 MOCK_METHOD0(postFramebuffer, void());
761 };
762
763 StrictMock<OutputPartialMock> mOutput;
764};
765
766TEST_F(OutputPresentTest, justInvokesChildFunctionsInSequence) {
767 CompositionRefreshArgs args;
768
769 InSequence seq;
770 EXPECT_CALL(mOutput, updateColorProfile(Ref(args)));
771 EXPECT_CALL(mOutput, updateAndWriteCompositionState(Ref(args)));
772 EXPECT_CALL(mOutput, setColorTransform(Ref(args)));
773 EXPECT_CALL(mOutput, beginFrame());
774 EXPECT_CALL(mOutput, prepareFrame());
775 EXPECT_CALL(mOutput, devOptRepaintFlash(Ref(args)));
776 EXPECT_CALL(mOutput, finishFrame(Ref(args)));
777 EXPECT_CALL(mOutput, postFramebuffer());
778
779 mOutput.present(args);
780}
781
782/*
783 * Output::updateColorProfile()
784 */
785
Lloyd Pique17ca7422019-11-14 14:24:10 -0800786struct OutputUpdateColorProfileTest : public testing::Test {
787 using TestType = OutputUpdateColorProfileTest;
788
789 struct OutputPartialMock : public OutputPartialMockBase {
790 // All child helper functions Output::present() are defined as mocks,
791 // and those are tested separately, allowing the present() test to
792 // just cover the high level flow.
793 MOCK_METHOD1(setColorProfile, void(const ColorProfile&));
794 };
795
796 struct Layer {
797 Layer() {
798 EXPECT_CALL(mOutputLayer, getLayer()).WillRepeatedly(ReturnRef(mLayer));
799 EXPECT_CALL(mOutputLayer, getLayerFE()).WillRepeatedly(ReturnRef(mLayerFE));
800 EXPECT_CALL(mLayer, getFEState()).WillRepeatedly(ReturnRef(mLayerFEState));
801 }
802
803 StrictMock<mock::OutputLayer> mOutputLayer;
804 StrictMock<mock::Layer> mLayer;
805 StrictMock<mock::LayerFE> mLayerFE;
806 LayerFECompositionState mLayerFEState;
807 };
808
809 OutputUpdateColorProfileTest() {
810 mOutput.setDisplayColorProfileForTest(
811 std::unique_ptr<DisplayColorProfile>(mDisplayColorProfile));
812 mOutput.setRenderSurfaceForTest(std::unique_ptr<RenderSurface>(mRenderSurface));
813
814 EXPECT_CALL(mOutput, getOutputLayerOrderedByZByIndex(0))
815 .WillRepeatedly(Return(&mLayer1.mOutputLayer));
816 EXPECT_CALL(mOutput, getOutputLayerOrderedByZByIndex(1))
817 .WillRepeatedly(Return(&mLayer2.mOutputLayer));
818 EXPECT_CALL(mOutput, getOutputLayerOrderedByZByIndex(2))
819 .WillRepeatedly(Return(&mLayer3.mOutputLayer));
820 }
821
822 struct ExecuteState : public CallOrderStateMachineHelper<TestType, ExecuteState> {
823 void execute() { getInstance()->mOutput.updateColorProfile(getInstance()->mRefreshArgs); }
824 };
825
826 mock::DisplayColorProfile* mDisplayColorProfile = new StrictMock<mock::DisplayColorProfile>();
827 mock::RenderSurface* mRenderSurface = new StrictMock<mock::RenderSurface>();
828 StrictMock<OutputPartialMock> mOutput;
829
830 Layer mLayer1;
831 Layer mLayer2;
832 Layer mLayer3;
833
834 CompositionRefreshArgs mRefreshArgs;
835};
836
837// TODO(b/144522012): Refactor Output::updateColorProfile and the related code
838// to make it easier to write unit tests.
839
840TEST_F(OutputUpdateColorProfileTest, setsAColorProfileWhenUnmanaged) {
841 // When the outputColorSetting is set to kUnmanaged, the implementation sets
842 // a simple default color profile without looking at anything else.
843
844 EXPECT_CALL(mOutput, getOutputLayerCount()).WillRepeatedly(Return(3));
845 EXPECT_CALL(mOutput,
846 setColorProfile(ColorProfileEq(
847 ColorProfile{ui::ColorMode::NATIVE, ui::Dataspace::UNKNOWN,
848 ui::RenderIntent::COLORIMETRIC, ui::Dataspace::UNKNOWN})));
849
850 mRefreshArgs.outputColorSetting = OutputColorSetting::kUnmanaged;
851 mRefreshArgs.colorSpaceAgnosticDataspace = ui::Dataspace::UNKNOWN;
852
853 mOutput.updateColorProfile(mRefreshArgs);
854}
855
856struct OutputUpdateColorProfileTest_GetBestColorModeResultBecomesSetProfile
857 : public OutputUpdateColorProfileTest {
858 OutputUpdateColorProfileTest_GetBestColorModeResultBecomesSetProfile() {
859 EXPECT_CALL(mOutput, getOutputLayerCount()).WillRepeatedly(Return(0));
860 mRefreshArgs.outputColorSetting = OutputColorSetting::kEnhanced;
861 mRefreshArgs.colorSpaceAgnosticDataspace = ui::Dataspace::UNKNOWN;
862 }
863
864 struct ExpectBestColorModeCallResultUsedToSetColorProfileState
865 : public CallOrderStateMachineHelper<
866 TestType, ExpectBestColorModeCallResultUsedToSetColorProfileState> {
867 [[nodiscard]] auto expectBestColorModeCallResultUsedToSetColorProfile(
868 ui::ColorMode colorMode, ui::Dataspace dataspace, ui::RenderIntent renderIntent) {
869 EXPECT_CALL(*getInstance()->mDisplayColorProfile,
870 getBestColorMode(ui::Dataspace::V0_SRGB, ui::RenderIntent::ENHANCE, _, _,
871 _))
872 .WillOnce(DoAll(SetArgPointee<2>(dataspace), SetArgPointee<3>(colorMode),
873 SetArgPointee<4>(renderIntent)));
874 EXPECT_CALL(getInstance()->mOutput,
875 setColorProfile(
876 ColorProfileEq(ColorProfile{colorMode, dataspace, renderIntent,
877 ui::Dataspace::UNKNOWN})));
878 return nextState<ExecuteState>();
879 }
880 };
881
882 // Call this member function to start using the mini-DSL defined above.
883 [[nodiscard]] auto verify() {
884 return ExpectBestColorModeCallResultUsedToSetColorProfileState::make(this);
885 }
886};
887
888TEST_F(OutputUpdateColorProfileTest_GetBestColorModeResultBecomesSetProfile,
889 Native_Unknown_Colorimetric_Set) {
890 verify().expectBestColorModeCallResultUsedToSetColorProfile(ui::ColorMode::NATIVE,
891 ui::Dataspace::UNKNOWN,
892 ui::RenderIntent::COLORIMETRIC)
893 .execute();
894}
895
896TEST_F(OutputUpdateColorProfileTest_GetBestColorModeResultBecomesSetProfile,
897 DisplayP3_DisplayP3_Enhance_Set) {
898 verify().expectBestColorModeCallResultUsedToSetColorProfile(ui::ColorMode::DISPLAY_P3,
899 ui::Dataspace::DISPLAY_P3,
900 ui::RenderIntent::ENHANCE)
901 .execute();
902}
903
904struct OutputUpdateColorProfileTest_ColorSpaceAgnosticeDataspaceAffectsSetColorProfile
905 : public OutputUpdateColorProfileTest {
906 OutputUpdateColorProfileTest_ColorSpaceAgnosticeDataspaceAffectsSetColorProfile() {
907 EXPECT_CALL(mOutput, getOutputLayerCount()).WillRepeatedly(Return(0));
908 EXPECT_CALL(*mDisplayColorProfile,
909 getBestColorMode(ui::Dataspace::V0_SRGB, ui::RenderIntent::ENHANCE, _, _, _))
910 .WillRepeatedly(DoAll(SetArgPointee<2>(ui::Dataspace::UNKNOWN),
911 SetArgPointee<3>(ui::ColorMode::NATIVE),
912 SetArgPointee<4>(ui::RenderIntent::COLORIMETRIC)));
913 mRefreshArgs.outputColorSetting = OutputColorSetting::kEnhanced;
914 }
915
916 struct IfColorSpaceAgnosticDataspaceSetToState
917 : public CallOrderStateMachineHelper<TestType, IfColorSpaceAgnosticDataspaceSetToState> {
918 [[nodiscard]] auto ifColorSpaceAgnosticDataspaceSetTo(ui::Dataspace dataspace) {
919 getInstance()->mRefreshArgs.colorSpaceAgnosticDataspace = dataspace;
920 return nextState<ThenExpectSetColorProfileCallUsesColorSpaceAgnosticDataspaceState>();
921 }
922 };
923
924 struct ThenExpectSetColorProfileCallUsesColorSpaceAgnosticDataspaceState
925 : public CallOrderStateMachineHelper<
926 TestType, ThenExpectSetColorProfileCallUsesColorSpaceAgnosticDataspaceState> {
927 [[nodiscard]] auto thenExpectSetColorProfileCallUsesColorSpaceAgnosticDataspace(
928 ui::Dataspace dataspace) {
929 EXPECT_CALL(getInstance()->mOutput,
930 setColorProfile(ColorProfileEq(
931 ColorProfile{ui::ColorMode::NATIVE, ui::Dataspace::UNKNOWN,
932 ui::RenderIntent::COLORIMETRIC, dataspace})));
933 return nextState<ExecuteState>();
934 }
935 };
936
937 // Call this member function to start using the mini-DSL defined above.
938 [[nodiscard]] auto verify() { return IfColorSpaceAgnosticDataspaceSetToState::make(this); }
939};
940
941TEST_F(OutputUpdateColorProfileTest_ColorSpaceAgnosticeDataspaceAffectsSetColorProfile, DisplayP3) {
942 verify().ifColorSpaceAgnosticDataspaceSetTo(ui::Dataspace::DISPLAY_P3)
943 .thenExpectSetColorProfileCallUsesColorSpaceAgnosticDataspace(ui::Dataspace::DISPLAY_P3)
944 .execute();
945}
946
947TEST_F(OutputUpdateColorProfileTest_ColorSpaceAgnosticeDataspaceAffectsSetColorProfile, V0_SRGB) {
948 verify().ifColorSpaceAgnosticDataspaceSetTo(ui::Dataspace::V0_SRGB)
949 .thenExpectSetColorProfileCallUsesColorSpaceAgnosticDataspace(ui::Dataspace::V0_SRGB)
950 .execute();
951}
952
953struct OutputUpdateColorProfileTest_TopmostLayerPreferenceSetsOutputPreference
954 : public OutputUpdateColorProfileTest {
955 // Internally the implementation looks through the dataspaces of all the
956 // visible layers. The topmost one that also has an actual dataspace
957 // preference set is used to drive subsequent choices.
958
959 OutputUpdateColorProfileTest_TopmostLayerPreferenceSetsOutputPreference() {
960 mRefreshArgs.outputColorSetting = OutputColorSetting::kEnhanced;
961 mRefreshArgs.colorSpaceAgnosticDataspace = ui::Dataspace::UNKNOWN;
962
963 EXPECT_CALL(mOutput, getOutputLayerCount()).WillRepeatedly(Return(3));
964 EXPECT_CALL(mOutput, setColorProfile(_)).WillRepeatedly(Return());
965 }
966
967 struct IfTopLayerDataspaceState
968 : public CallOrderStateMachineHelper<TestType, IfTopLayerDataspaceState> {
969 [[nodiscard]] auto ifTopLayerIs(ui::Dataspace dataspace) {
970 getInstance()->mLayer3.mLayerFEState.dataspace = dataspace;
971 return nextState<AndIfMiddleLayerDataspaceState>();
972 }
973 [[nodiscard]] auto ifTopLayerHasNoPreference() {
974 return ifTopLayerIs(ui::Dataspace::UNKNOWN);
975 }
976 };
977
978 struct AndIfMiddleLayerDataspaceState
979 : public CallOrderStateMachineHelper<TestType, AndIfMiddleLayerDataspaceState> {
980 [[nodiscard]] auto andIfMiddleLayerIs(ui::Dataspace dataspace) {
981 getInstance()->mLayer2.mLayerFEState.dataspace = dataspace;
982 return nextState<AndIfBottomLayerDataspaceState>();
983 }
984 [[nodiscard]] auto andIfMiddleLayerHasNoPreference() {
985 return andIfMiddleLayerIs(ui::Dataspace::UNKNOWN);
986 }
987 };
988
989 struct AndIfBottomLayerDataspaceState
990 : public CallOrderStateMachineHelper<TestType, AndIfBottomLayerDataspaceState> {
991 [[nodiscard]] auto andIfBottomLayerIs(ui::Dataspace dataspace) {
992 getInstance()->mLayer1.mLayerFEState.dataspace = dataspace;
993 return nextState<ThenExpectBestColorModeCallUsesState>();
994 }
995 [[nodiscard]] auto andIfBottomLayerHasNoPreference() {
996 return andIfBottomLayerIs(ui::Dataspace::UNKNOWN);
997 }
998 };
999
1000 struct ThenExpectBestColorModeCallUsesState
1001 : public CallOrderStateMachineHelper<TestType, ThenExpectBestColorModeCallUsesState> {
1002 [[nodiscard]] auto thenExpectBestColorModeCallUses(ui::Dataspace dataspace) {
1003 EXPECT_CALL(*getInstance()->mDisplayColorProfile,
1004 getBestColorMode(dataspace, _, _, _, _));
1005 return nextState<ExecuteState>();
1006 }
1007 };
1008
1009 // Call this member function to start using the mini-DSL defined above.
1010 [[nodiscard]] auto verify() { return IfTopLayerDataspaceState::make(this); }
1011};
1012
1013TEST_F(OutputUpdateColorProfileTest_TopmostLayerPreferenceSetsOutputPreference,
1014 noStrongLayerPrefenceUses_V0_SRGB) {
1015 // If none of the layers indicate a preference, then V0_SRGB is the
1016 // preferred choice (subject to additional checks).
1017 verify().ifTopLayerHasNoPreference()
1018 .andIfMiddleLayerHasNoPreference()
1019 .andIfBottomLayerHasNoPreference()
1020 .thenExpectBestColorModeCallUses(ui::Dataspace::V0_SRGB)
1021 .execute();
1022}
1023
1024TEST_F(OutputUpdateColorProfileTest_TopmostLayerPreferenceSetsOutputPreference,
1025 ifTopmostUses_DisplayP3_Then_DisplayP3_Chosen) {
1026 // If only the topmost layer has a preference, then that is what is chosen.
1027 verify().ifTopLayerIs(ui::Dataspace::DISPLAY_P3)
1028 .andIfMiddleLayerHasNoPreference()
1029 .andIfBottomLayerHasNoPreference()
1030 .thenExpectBestColorModeCallUses(ui::Dataspace::DISPLAY_P3)
1031 .execute();
1032}
1033
1034TEST_F(OutputUpdateColorProfileTest_TopmostLayerPreferenceSetsOutputPreference,
1035 ifMiddleUses_DisplayP3_Then_DisplayP3_Chosen) {
1036 // If only the middle layer has a preference, that that is what is chosen.
1037 verify().ifTopLayerHasNoPreference()
1038 .andIfMiddleLayerIs(ui::Dataspace::DISPLAY_P3)
1039 .andIfBottomLayerHasNoPreference()
1040 .thenExpectBestColorModeCallUses(ui::Dataspace::DISPLAY_P3)
1041 .execute();
1042}
1043
1044TEST_F(OutputUpdateColorProfileTest_TopmostLayerPreferenceSetsOutputPreference,
1045 ifBottomUses_DisplayP3_Then_DisplayP3_Chosen) {
1046 // If only the middle layer has a preference, that that is what is chosen.
1047 verify().ifTopLayerHasNoPreference()
1048 .andIfMiddleLayerHasNoPreference()
1049 .andIfBottomLayerIs(ui::Dataspace::DISPLAY_P3)
1050 .thenExpectBestColorModeCallUses(ui::Dataspace::DISPLAY_P3)
1051 .execute();
1052}
1053
1054TEST_F(OutputUpdateColorProfileTest_TopmostLayerPreferenceSetsOutputPreference,
1055 ifTopUses_DisplayBT2020_AndBottomUses_DisplayP3_Then_DisplayBT2020_Chosen) {
1056 // If multiple layers have a preference, the topmost value is what is used.
1057 verify().ifTopLayerIs(ui::Dataspace::DISPLAY_BT2020)
1058 .andIfMiddleLayerHasNoPreference()
1059 .andIfBottomLayerIs(ui::Dataspace::DISPLAY_P3)
1060 .thenExpectBestColorModeCallUses(ui::Dataspace::DISPLAY_BT2020)
1061 .execute();
1062}
1063
1064TEST_F(OutputUpdateColorProfileTest_TopmostLayerPreferenceSetsOutputPreference,
1065 ifTopUses_DisplayP3_AndBottomUses_V0_SRGB_Then_DisplayP3_Chosen) {
1066 // If multiple layers have a preference, the topmost value is what is used.
1067 verify().ifTopLayerIs(ui::Dataspace::DISPLAY_P3)
1068 .andIfMiddleLayerHasNoPreference()
1069 .andIfBottomLayerIs(ui::Dataspace::DISPLAY_BT2020)
1070 .thenExpectBestColorModeCallUses(ui::Dataspace::DISPLAY_P3)
1071 .execute();
1072}
1073
1074struct OutputUpdateColorProfileTest_ForceOutputColorOverrides
1075 : public OutputUpdateColorProfileTest {
1076 // If CompositionRefreshArgs::forceOutputColorMode is set to some specific
1077 // values, it overrides the layer dataspace choice.
1078
1079 OutputUpdateColorProfileTest_ForceOutputColorOverrides() {
1080 mRefreshArgs.outputColorSetting = OutputColorSetting::kEnhanced;
1081 mRefreshArgs.colorSpaceAgnosticDataspace = ui::Dataspace::UNKNOWN;
1082
1083 mLayer1.mLayerFEState.dataspace = ui::Dataspace::DISPLAY_BT2020;
1084
1085 EXPECT_CALL(mOutput, getOutputLayerCount()).WillRepeatedly(Return(1));
1086 EXPECT_CALL(mOutput, setColorProfile(_)).WillRepeatedly(Return());
1087 }
1088
1089 struct IfForceOutputColorModeState
1090 : public CallOrderStateMachineHelper<TestType, IfForceOutputColorModeState> {
1091 [[nodiscard]] auto ifForceOutputColorMode(ui::ColorMode colorMode) {
1092 getInstance()->mRefreshArgs.forceOutputColorMode = colorMode;
1093 return nextState<ThenExpectBestColorModeCallUsesState>();
1094 }
1095 [[nodiscard]] auto ifNoOverride() { return ifForceOutputColorMode(ui::ColorMode::NATIVE); }
1096 };
1097
1098 struct ThenExpectBestColorModeCallUsesState
1099 : public CallOrderStateMachineHelper<TestType, ThenExpectBestColorModeCallUsesState> {
1100 [[nodiscard]] auto thenExpectBestColorModeCallUses(ui::Dataspace dataspace) {
1101 EXPECT_CALL(*getInstance()->mDisplayColorProfile,
1102 getBestColorMode(dataspace, _, _, _, _));
1103 return nextState<ExecuteState>();
1104 }
1105 };
1106
1107 // Call this member function to start using the mini-DSL defined above.
1108 [[nodiscard]] auto verify() { return IfForceOutputColorModeState::make(this); }
1109};
1110
1111TEST_F(OutputUpdateColorProfileTest_ForceOutputColorOverrides, NoOverride_DoesNotOverride) {
1112 // By default the layer state is used to set the preferred dataspace
1113 verify().ifNoOverride()
1114 .thenExpectBestColorModeCallUses(ui::Dataspace::DISPLAY_BT2020)
1115 .execute();
1116}
1117
1118TEST_F(OutputUpdateColorProfileTest_ForceOutputColorOverrides, SRGB_Override_USES_V0_SRGB) {
1119 // Setting ui::ColorMode::SRGB overrides it with ui::Dataspace::V0_SRGB
1120 verify().ifForceOutputColorMode(ui::ColorMode::SRGB)
1121 .thenExpectBestColorModeCallUses(ui::Dataspace::V0_SRGB)
1122 .execute();
1123}
1124
1125TEST_F(OutputUpdateColorProfileTest_ForceOutputColorOverrides, DisplayP3_Override_Uses_DisplayP3) {
1126 // Setting ui::ColorMode::DISPLAY_P3 overrides it with ui::Dataspace::DISPLAY_P3
1127 verify().ifForceOutputColorMode(ui::ColorMode::DISPLAY_P3)
1128 .thenExpectBestColorModeCallUses(ui::Dataspace::DISPLAY_P3)
1129 .execute();
1130}
1131
1132// HDR output requires all layers to be compatible with the chosen HDR
1133// dataspace, along with there being proper support.
1134struct OutputUpdateColorProfileTest_Hdr : public OutputUpdateColorProfileTest {
1135 OutputUpdateColorProfileTest_Hdr() {
1136 mRefreshArgs.outputColorSetting = OutputColorSetting::kEnhanced;
1137 mRefreshArgs.colorSpaceAgnosticDataspace = ui::Dataspace::UNKNOWN;
1138 EXPECT_CALL(mOutput, getOutputLayerCount()).WillRepeatedly(Return(2));
1139 EXPECT_CALL(mOutput, setColorProfile(_)).WillRepeatedly(Return());
1140 }
1141
1142 static constexpr ui::Dataspace kNonHdrDataspace = ui::Dataspace::DISPLAY_P3;
1143 static constexpr ui::Dataspace BT2020_PQ = ui::Dataspace::BT2020_PQ;
1144 static constexpr ui::Dataspace BT2020_HLG = ui::Dataspace::BT2020_HLG;
1145 static constexpr ui::Dataspace DISPLAY_P3 = ui::Dataspace::DISPLAY_P3;
1146
1147 struct IfTopLayerDataspaceState
1148 : public CallOrderStateMachineHelper<TestType, IfTopLayerDataspaceState> {
1149 [[nodiscard]] auto ifTopLayerIs(ui::Dataspace dataspace) {
1150 getInstance()->mLayer2.mLayerFEState.dataspace = dataspace;
1151 return nextState<AndTopLayerCompositionTypeState>();
1152 }
1153 [[nodiscard]] auto ifTopLayerIsNotHdr() { return ifTopLayerIs(kNonHdrDataspace); }
1154 };
1155
1156 struct AndTopLayerCompositionTypeState
1157 : public CallOrderStateMachineHelper<TestType, AndTopLayerCompositionTypeState> {
1158 [[nodiscard]] auto andTopLayerIsREComposed(bool renderEngineComposed) {
1159 getInstance()->mLayer2.mLayerFEState.forceClientComposition = renderEngineComposed;
1160 return nextState<AndIfBottomLayerDataspaceState>();
1161 }
1162 };
1163
1164 struct AndIfBottomLayerDataspaceState
1165 : public CallOrderStateMachineHelper<TestType, AndIfBottomLayerDataspaceState> {
1166 [[nodiscard]] auto andIfBottomLayerIs(ui::Dataspace dataspace) {
1167 getInstance()->mLayer1.mLayerFEState.dataspace = dataspace;
1168 return nextState<AndBottomLayerCompositionTypeState>();
1169 }
1170 [[nodiscard]] auto andIfBottomLayerIsNotHdr() {
1171 return andIfBottomLayerIs(kNonHdrDataspace);
1172 }
1173 };
1174
1175 struct AndBottomLayerCompositionTypeState
1176 : public CallOrderStateMachineHelper<TestType, AndBottomLayerCompositionTypeState> {
1177 [[nodiscard]] auto andBottomLayerIsREComposed(bool renderEngineComposed) {
1178 getInstance()->mLayer1.mLayerFEState.forceClientComposition = renderEngineComposed;
1179 return nextState<AndIfHasLegacySupportState>();
1180 }
1181 };
1182
1183 struct AndIfHasLegacySupportState
1184 : public CallOrderStateMachineHelper<TestType, AndIfHasLegacySupportState> {
1185 [[nodiscard]] auto andIfLegacySupportFor(ui::Dataspace dataspace, bool legacySupport) {
1186 EXPECT_CALL(*getInstance()->mDisplayColorProfile, hasLegacyHdrSupport(dataspace))
1187 .WillOnce(Return(legacySupport));
1188 return nextState<ThenExpectBestColorModeCallUsesState>();
1189 }
1190 };
1191
1192 struct ThenExpectBestColorModeCallUsesState
1193 : public CallOrderStateMachineHelper<TestType, ThenExpectBestColorModeCallUsesState> {
1194 [[nodiscard]] auto thenExpectBestColorModeCallUses(ui::Dataspace dataspace) {
1195 EXPECT_CALL(*getInstance()->mDisplayColorProfile,
1196 getBestColorMode(dataspace, _, _, _, _));
1197 return nextState<ExecuteState>();
1198 }
1199 };
1200
1201 // Call this member function to start using the mini-DSL defined above.
1202 [[nodiscard]] auto verify() { return IfTopLayerDataspaceState::make(this); }
1203};
1204
1205TEST_F(OutputUpdateColorProfileTest_Hdr, PQ_HW_On_PQ_HW_Uses_PQ) {
1206 // If all layers use BT2020_PQ, and there are no other special conditions,
1207 // BT2020_PQ is used.
1208 verify().ifTopLayerIs(BT2020_PQ)
1209 .andTopLayerIsREComposed(false)
1210 .andIfBottomLayerIs(BT2020_PQ)
1211 .andBottomLayerIsREComposed(false)
1212 .andIfLegacySupportFor(BT2020_PQ, false)
1213 .thenExpectBestColorModeCallUses(BT2020_PQ)
1214 .execute();
1215}
1216
1217TEST_F(OutputUpdateColorProfileTest_Hdr, PQ_HW_On_PQ_HW_IfPQHasLegacySupport_Uses_DisplayP3) {
1218 // BT2020_PQ is not used if there is only legacy support for it.
1219 verify().ifTopLayerIs(BT2020_PQ)
1220 .andTopLayerIsREComposed(false)
1221 .andIfBottomLayerIs(BT2020_PQ)
1222 .andBottomLayerIsREComposed(false)
1223 .andIfLegacySupportFor(BT2020_PQ, true)
1224 .thenExpectBestColorModeCallUses(DISPLAY_P3)
1225 .execute();
1226}
1227
1228TEST_F(OutputUpdateColorProfileTest_Hdr, PQ_HW_On_PQ_RE_Uses_PQ) {
1229 // BT2020_PQ is still used if the bottom layer is RenderEngine composed.
1230 verify().ifTopLayerIs(BT2020_PQ)
1231 .andTopLayerIsREComposed(false)
1232 .andIfBottomLayerIs(BT2020_PQ)
1233 .andBottomLayerIsREComposed(true)
1234 .andIfLegacySupportFor(BT2020_PQ, false)
1235 .thenExpectBestColorModeCallUses(BT2020_PQ)
1236 .execute();
1237}
1238
1239TEST_F(OutputUpdateColorProfileTest_Hdr, PQ_RE_On_PQ_HW_Uses_DisplayP3) {
1240 // BT2020_PQ is not used if the top layer is RenderEngine composed.
1241 verify().ifTopLayerIs(BT2020_PQ)
1242 .andTopLayerIsREComposed(true)
1243 .andIfBottomLayerIs(BT2020_PQ)
1244 .andBottomLayerIsREComposed(false)
1245 .andIfLegacySupportFor(BT2020_PQ, false)
1246 .thenExpectBestColorModeCallUses(DISPLAY_P3)
1247 .execute();
1248}
1249
1250TEST_F(OutputUpdateColorProfileTest_Hdr, PQ_HW_On_HLG_HW_Uses_PQ) {
1251 // If there is mixed HLG/PQ use, and the topmost layer is PQ, then PQ is used if there
1252 // are no other special conditions.
1253 verify().ifTopLayerIs(BT2020_PQ)
1254 .andTopLayerIsREComposed(false)
1255 .andIfBottomLayerIs(BT2020_HLG)
1256 .andBottomLayerIsREComposed(false)
1257 .andIfLegacySupportFor(BT2020_PQ, false)
1258 .thenExpectBestColorModeCallUses(BT2020_PQ)
1259 .execute();
1260}
1261
1262TEST_F(OutputUpdateColorProfileTest_Hdr, PQ_HW_On_HLG_HW_IfPQHasLegacySupport_Uses_DisplayP3) {
1263 // BT2020_PQ is not used if there is only legacy support for it.
1264 verify().ifTopLayerIs(BT2020_PQ)
1265 .andTopLayerIsREComposed(false)
1266 .andIfBottomLayerIs(BT2020_HLG)
1267 .andBottomLayerIsREComposed(false)
1268 .andIfLegacySupportFor(BT2020_PQ, true)
1269 .thenExpectBestColorModeCallUses(DISPLAY_P3)
1270 .execute();
1271}
1272
1273TEST_F(OutputUpdateColorProfileTest_Hdr, PQ_HW_On_HLG_RE_Uses_PQ) {
1274 // BT2020_PQ is used if the bottom HLG layer is RenderEngine composed.
1275 verify().ifTopLayerIs(BT2020_PQ)
1276 .andTopLayerIsREComposed(false)
1277 .andIfBottomLayerIs(BT2020_HLG)
1278 .andBottomLayerIsREComposed(true)
1279 .andIfLegacySupportFor(BT2020_PQ, false)
1280 .thenExpectBestColorModeCallUses(BT2020_PQ)
1281 .execute();
1282}
1283
1284TEST_F(OutputUpdateColorProfileTest_Hdr, PQ_RE_On_HLG_HW_Uses_DisplayP3) {
1285 // BT2020_PQ is not used if the top PQ layer is RenderEngine composed.
1286 verify().ifTopLayerIs(BT2020_PQ)
1287 .andTopLayerIsREComposed(true)
1288 .andIfBottomLayerIs(BT2020_HLG)
1289 .andBottomLayerIsREComposed(false)
1290 .andIfLegacySupportFor(BT2020_PQ, false)
1291 .thenExpectBestColorModeCallUses(DISPLAY_P3)
1292 .execute();
1293}
1294
1295TEST_F(OutputUpdateColorProfileTest_Hdr, HLG_HW_On_PQ_HW_Uses_PQ) {
1296 // If there is mixed HLG/PQ use, and the topmost layer is HLG, then PQ is
1297 // used if there are no other special conditions.
1298 verify().ifTopLayerIs(BT2020_HLG)
1299 .andTopLayerIsREComposed(false)
1300 .andIfBottomLayerIs(BT2020_PQ)
1301 .andBottomLayerIsREComposed(false)
1302 .andIfLegacySupportFor(BT2020_PQ, false)
1303 .thenExpectBestColorModeCallUses(BT2020_PQ)
1304 .execute();
1305}
1306
1307TEST_F(OutputUpdateColorProfileTest_Hdr, HLG_HW_On_PQ_HW_IfPQHasLegacySupport_Uses_DisplayP3) {
1308 // BT2020_PQ is not used if there is only legacy support for it.
1309 verify().ifTopLayerIs(BT2020_HLG)
1310 .andTopLayerIsREComposed(false)
1311 .andIfBottomLayerIs(BT2020_PQ)
1312 .andBottomLayerIsREComposed(false)
1313 .andIfLegacySupportFor(BT2020_PQ, true)
1314 .thenExpectBestColorModeCallUses(DISPLAY_P3)
1315 .execute();
1316}
1317
1318TEST_F(OutputUpdateColorProfileTest_Hdr, HLG_HW_On_PQ_RE_Uses_DisplayP3) {
1319 // BT2020_PQ is not used if the bottom PQ layer is RenderEngine composed.
1320 verify().ifTopLayerIs(BT2020_HLG)
1321 .andTopLayerIsREComposed(false)
1322 .andIfBottomLayerIs(BT2020_PQ)
1323 .andBottomLayerIsREComposed(true)
1324 .andIfLegacySupportFor(BT2020_PQ, false)
1325 .thenExpectBestColorModeCallUses(DISPLAY_P3)
1326 .execute();
1327}
1328
1329TEST_F(OutputUpdateColorProfileTest_Hdr, HLG_RE_On_PQ_HW_Uses_PQ) {
1330 // BT2020_PQ is still used if the top HLG layer is RenderEngine composed.
1331 verify().ifTopLayerIs(BT2020_HLG)
1332 .andTopLayerIsREComposed(true)
1333 .andIfBottomLayerIs(BT2020_PQ)
1334 .andBottomLayerIsREComposed(false)
1335 .andIfLegacySupportFor(BT2020_PQ, false)
1336 .thenExpectBestColorModeCallUses(BT2020_PQ)
1337 .execute();
1338}
1339
1340TEST_F(OutputUpdateColorProfileTest_Hdr, HLG_HW_On_HLG_HW_Uses_HLG) {
1341 // If all layers use HLG then HLG is used if there are no other special
1342 // conditions.
1343 verify().ifTopLayerIs(BT2020_HLG)
1344 .andTopLayerIsREComposed(false)
1345 .andIfBottomLayerIs(BT2020_HLG)
1346 .andBottomLayerIsREComposed(false)
1347 .andIfLegacySupportFor(BT2020_HLG, false)
1348 .thenExpectBestColorModeCallUses(BT2020_HLG)
1349 .execute();
1350}
1351
1352TEST_F(OutputUpdateColorProfileTest_Hdr, HLG_HW_On_HLG_HW_IfPQHasLegacySupport_Uses_DisplayP3) {
1353 // BT2020_HLG is not used if there is legacy support for it.
1354 verify().ifTopLayerIs(BT2020_HLG)
1355 .andTopLayerIsREComposed(false)
1356 .andIfBottomLayerIs(BT2020_HLG)
1357 .andBottomLayerIsREComposed(false)
1358 .andIfLegacySupportFor(BT2020_HLG, true)
1359 .thenExpectBestColorModeCallUses(DISPLAY_P3)
1360 .execute();
1361}
1362
1363TEST_F(OutputUpdateColorProfileTest_Hdr, HLG_HW_On_HLG_RE_Uses_HLG) {
1364 // BT2020_HLG is used even if the bottom layer is client composed.
1365 verify().ifTopLayerIs(BT2020_HLG)
1366 .andTopLayerIsREComposed(false)
1367 .andIfBottomLayerIs(BT2020_HLG)
1368 .andBottomLayerIsREComposed(true)
1369 .andIfLegacySupportFor(BT2020_HLG, false)
1370 .thenExpectBestColorModeCallUses(BT2020_HLG)
1371 .execute();
1372}
1373
1374TEST_F(OutputUpdateColorProfileTest_Hdr, HLG_RE_On_HLG_HW_Uses_HLG) {
1375 // BT2020_HLG is used even if the top layer is client composed.
1376 verify().ifTopLayerIs(BT2020_HLG)
1377 .andTopLayerIsREComposed(true)
1378 .andIfBottomLayerIs(BT2020_HLG)
1379 .andBottomLayerIsREComposed(false)
1380 .andIfLegacySupportFor(BT2020_HLG, false)
1381 .thenExpectBestColorModeCallUses(BT2020_HLG)
1382 .execute();
1383}
1384
1385TEST_F(OutputUpdateColorProfileTest_Hdr, PQ_HW_On_NonHdr_HW_Uses_PQ) {
1386 // Even if there are non-HDR layers present, BT2020_PQ can still be used.
1387 verify().ifTopLayerIs(BT2020_PQ)
1388 .andTopLayerIsREComposed(false)
1389 .andIfBottomLayerIsNotHdr()
1390 .andBottomLayerIsREComposed(false)
1391 .andIfLegacySupportFor(BT2020_PQ, false)
1392 .thenExpectBestColorModeCallUses(BT2020_PQ)
1393 .execute();
1394}
1395
1396TEST_F(OutputUpdateColorProfileTest_Hdr, HLG_HW_On_NonHdr_RE_Uses_HLG) {
1397 // If all layers use HLG then HLG is used if there are no other special
1398 // conditions.
1399 verify().ifTopLayerIs(BT2020_HLG)
1400 .andTopLayerIsREComposed(false)
1401 .andIfBottomLayerIsNotHdr()
1402 .andBottomLayerIsREComposed(true)
1403 .andIfLegacySupportFor(BT2020_HLG, false)
1404 .thenExpectBestColorModeCallUses(BT2020_HLG)
1405 .execute();
1406}
1407
1408struct OutputUpdateColorProfile_AffectsChosenRenderIntentTest
1409 : public OutputUpdateColorProfileTest {
1410 // The various values for CompositionRefreshArgs::outputColorSetting affect
1411 // the chosen renderIntent, along with whether the preferred dataspace is an
1412 // HDR dataspace or not.
1413
1414 OutputUpdateColorProfile_AffectsChosenRenderIntentTest() {
1415 mRefreshArgs.outputColorSetting = OutputColorSetting::kEnhanced;
1416 mRefreshArgs.colorSpaceAgnosticDataspace = ui::Dataspace::UNKNOWN;
1417 mLayer1.mLayerFEState.dataspace = ui::Dataspace::BT2020_PQ;
1418 EXPECT_CALL(mOutput, getOutputLayerCount()).WillRepeatedly(Return(1));
1419 EXPECT_CALL(mOutput, setColorProfile(_)).WillRepeatedly(Return());
1420 EXPECT_CALL(*mDisplayColorProfile, hasLegacyHdrSupport(ui::Dataspace::BT2020_PQ))
1421 .WillRepeatedly(Return(false));
1422 }
1423
1424 // The tests here involve enough state and GMock setup that using a mini-DSL
1425 // makes the tests much more readable, and allows the test to focus more on
1426 // the intent than on some of the details.
1427
1428 static constexpr ui::Dataspace kNonHdrDataspace = ui::Dataspace::DISPLAY_P3;
1429 static constexpr ui::Dataspace kHdrDataspace = ui::Dataspace::BT2020_PQ;
1430
1431 struct IfDataspaceChosenState
1432 : public CallOrderStateMachineHelper<TestType, IfDataspaceChosenState> {
1433 [[nodiscard]] auto ifDataspaceChosenIs(ui::Dataspace dataspace) {
1434 getInstance()->mLayer1.mLayerFEState.dataspace = dataspace;
1435 return nextState<AndOutputColorSettingState>();
1436 }
1437 [[nodiscard]] auto ifDataspaceChosenIsNonHdr() {
1438 return ifDataspaceChosenIs(kNonHdrDataspace);
1439 }
1440 [[nodiscard]] auto ifDataspaceChosenIsHdr() { return ifDataspaceChosenIs(kHdrDataspace); }
1441 };
1442
1443 struct AndOutputColorSettingState
1444 : public CallOrderStateMachineHelper<TestType, AndOutputColorSettingState> {
1445 [[nodiscard]] auto andOutputColorSettingIs(OutputColorSetting setting) {
1446 getInstance()->mRefreshArgs.outputColorSetting = setting;
1447 return nextState<ThenExpectBestColorModeCallUsesState>();
1448 }
1449 };
1450
1451 struct ThenExpectBestColorModeCallUsesState
1452 : public CallOrderStateMachineHelper<TestType, ThenExpectBestColorModeCallUsesState> {
1453 [[nodiscard]] auto thenExpectBestColorModeCallUses(ui::RenderIntent intent) {
1454 EXPECT_CALL(*getInstance()->mDisplayColorProfile,
1455 getBestColorMode(getInstance()->mLayer1.mLayerFEState.dataspace, intent, _,
1456 _, _));
1457 return nextState<ExecuteState>();
1458 }
1459 };
1460
1461 // Tests call one of these two helper member functions to start using the
1462 // mini-DSL defined above.
1463 [[nodiscard]] auto verify() { return IfDataspaceChosenState::make(this); }
1464};
1465
1466TEST_F(OutputUpdateColorProfile_AffectsChosenRenderIntentTest,
1467 Managed_NonHdr_Prefers_Colorimetric) {
1468 verify().ifDataspaceChosenIsNonHdr()
1469 .andOutputColorSettingIs(OutputColorSetting::kManaged)
1470 .thenExpectBestColorModeCallUses(ui::RenderIntent::COLORIMETRIC)
1471 .execute();
1472}
1473
1474TEST_F(OutputUpdateColorProfile_AffectsChosenRenderIntentTest,
1475 Managed_Hdr_Prefers_ToneMapColorimetric) {
1476 verify().ifDataspaceChosenIsHdr()
1477 .andOutputColorSettingIs(OutputColorSetting::kManaged)
1478 .thenExpectBestColorModeCallUses(ui::RenderIntent::TONE_MAP_COLORIMETRIC)
1479 .execute();
1480}
1481
1482TEST_F(OutputUpdateColorProfile_AffectsChosenRenderIntentTest, Enhanced_NonHdr_Prefers_Enhance) {
1483 verify().ifDataspaceChosenIsNonHdr()
1484 .andOutputColorSettingIs(OutputColorSetting::kEnhanced)
1485 .thenExpectBestColorModeCallUses(ui::RenderIntent::ENHANCE)
1486 .execute();
1487}
1488
1489TEST_F(OutputUpdateColorProfile_AffectsChosenRenderIntentTest,
1490 Enhanced_Hdr_Prefers_ToneMapEnhance) {
1491 verify().ifDataspaceChosenIsHdr()
1492 .andOutputColorSettingIs(OutputColorSetting::kEnhanced)
1493 .thenExpectBestColorModeCallUses(ui::RenderIntent::TONE_MAP_ENHANCE)
1494 .execute();
1495}
1496
1497TEST_F(OutputUpdateColorProfile_AffectsChosenRenderIntentTest, Vendor_NonHdr_Prefers_Vendor) {
1498 verify().ifDataspaceChosenIsNonHdr()
1499 .andOutputColorSettingIs(kVendorSpecifiedOutputColorSetting)
1500 .thenExpectBestColorModeCallUses(
1501 static_cast<ui::RenderIntent>(kVendorSpecifiedOutputColorSetting))
1502 .execute();
1503}
1504
1505TEST_F(OutputUpdateColorProfile_AffectsChosenRenderIntentTest, Vendor_Hdr_Prefers_Vendor) {
1506 verify().ifDataspaceChosenIsHdr()
1507 .andOutputColorSettingIs(kVendorSpecifiedOutputColorSetting)
1508 .thenExpectBestColorModeCallUses(
1509 static_cast<ui::RenderIntent>(kVendorSpecifiedOutputColorSetting))
1510 .execute();
1511}
Lloyd Piquefaa3f192019-11-14 14:05:09 -08001512
1513/*
1514 * Output::beginFrame()
1515 */
1516
1517/*
1518 * Output::devOptRepaintFlash()
1519 */
1520
Lloyd Piquedb462d82019-11-19 17:58:46 -08001521struct OutputDevOptRepaintFlashTest : public testing::Test {
1522 struct OutputPartialMock : public OutputPartialMockBase {
1523 // Sets up the helper functions called by composeSurfaces to use a mock
1524 // implementations.
1525 MOCK_CONST_METHOD1(getDirtyRegion, Region(bool));
1526 MOCK_METHOD1(composeSurfaces, std::optional<base::unique_fd>(const Region&));
1527 MOCK_METHOD0(postFramebuffer, void());
1528 MOCK_METHOD0(prepareFrame, void());
1529 };
1530
1531 OutputDevOptRepaintFlashTest() {
1532 mOutput.setDisplayColorProfileForTest(
1533 std::unique_ptr<DisplayColorProfile>(mDisplayColorProfile));
1534 mOutput.setRenderSurfaceForTest(std::unique_ptr<RenderSurface>(mRenderSurface));
1535 }
1536
1537 static const Region kEmptyRegion;
1538 static const Region kNotEmptyRegion;
1539
1540 StrictMock<OutputPartialMock> mOutput;
1541 mock::DisplayColorProfile* mDisplayColorProfile = new StrictMock<mock::DisplayColorProfile>();
1542 mock::RenderSurface* mRenderSurface = new StrictMock<mock::RenderSurface>();
1543 CompositionRefreshArgs mRefreshArgs;
1544};
1545
1546const Region OutputDevOptRepaintFlashTest::kEmptyRegion{Rect{0, 0, 0, 0}};
1547const Region OutputDevOptRepaintFlashTest::kNotEmptyRegion{Rect{0, 0, 1, 1}};
1548
1549TEST_F(OutputDevOptRepaintFlashTest, doesNothingIfFlashDelayNotSet) {
1550 mRefreshArgs.devOptFlashDirtyRegionsDelay = {};
1551 mRefreshArgs.repaintEverything = true;
1552 mOutput.mState.isEnabled = true;
1553
1554 mOutput.devOptRepaintFlash(mRefreshArgs);
1555}
1556
1557TEST_F(OutputDevOptRepaintFlashTest, postsAndPreparesANewFrameIfNotEnabled) {
1558 mRefreshArgs.devOptFlashDirtyRegionsDelay = std::chrono::microseconds(1);
1559 mRefreshArgs.repaintEverything = true;
1560 mOutput.mState.isEnabled = false;
1561
1562 InSequence seq;
1563 EXPECT_CALL(mOutput, postFramebuffer());
1564 EXPECT_CALL(mOutput, prepareFrame());
1565
1566 mOutput.devOptRepaintFlash(mRefreshArgs);
1567}
1568
1569TEST_F(OutputDevOptRepaintFlashTest, postsAndPreparesANewFrameIfNotDirty) {
1570 mRefreshArgs.devOptFlashDirtyRegionsDelay = std::chrono::microseconds(1);
1571 mRefreshArgs.repaintEverything = true;
1572 mOutput.mState.isEnabled = true;
1573
1574 InSequence seq;
1575 EXPECT_CALL(mOutput, getDirtyRegion(true)).WillOnce(Return(kEmptyRegion));
1576 EXPECT_CALL(mOutput, postFramebuffer());
1577 EXPECT_CALL(mOutput, prepareFrame());
1578
1579 mOutput.devOptRepaintFlash(mRefreshArgs);
1580}
1581
1582TEST_F(OutputDevOptRepaintFlashTest, alsoComposesSurfacesAndQueuesABufferIfDirty) {
1583 mRefreshArgs.devOptFlashDirtyRegionsDelay = std::chrono::microseconds(1);
1584 mRefreshArgs.repaintEverything = false;
1585 mOutput.mState.isEnabled = true;
1586
1587 InSequence seq;
1588 EXPECT_CALL(mOutput, getDirtyRegion(false)).WillOnce(Return(kNotEmptyRegion));
1589 EXPECT_CALL(mOutput, composeSurfaces(RegionEq(kNotEmptyRegion)));
1590 EXPECT_CALL(*mRenderSurface, queueBuffer(_));
1591 EXPECT_CALL(mOutput, postFramebuffer());
1592 EXPECT_CALL(mOutput, prepareFrame());
1593
1594 mOutput.devOptRepaintFlash(mRefreshArgs);
1595}
1596
Lloyd Piquefaa3f192019-11-14 14:05:09 -08001597// TODO(b/144060211) - Add coverage
1598
1599/*
1600 * Output::finishFrame()
1601 */
1602
Lloyd Pique03561a62019-11-19 18:34:52 -08001603struct OutputFinishFrameTest : public testing::Test {
1604 struct OutputPartialMock : public OutputPartialMockBase {
1605 // Sets up the helper functions called by composeSurfaces to use a mock
1606 // implementations.
1607 MOCK_METHOD1(composeSurfaces, std::optional<base::unique_fd>(const Region&));
1608 MOCK_METHOD0(postFramebuffer, void());
1609 };
1610
1611 OutputFinishFrameTest() {
1612 mOutput.setDisplayColorProfileForTest(
1613 std::unique_ptr<DisplayColorProfile>(mDisplayColorProfile));
1614 mOutput.setRenderSurfaceForTest(std::unique_ptr<RenderSurface>(mRenderSurface));
1615 }
1616
1617 StrictMock<OutputPartialMock> mOutput;
1618 mock::DisplayColorProfile* mDisplayColorProfile = new StrictMock<mock::DisplayColorProfile>();
1619 mock::RenderSurface* mRenderSurface = new StrictMock<mock::RenderSurface>();
1620 CompositionRefreshArgs mRefreshArgs;
1621};
1622
1623TEST_F(OutputFinishFrameTest, ifNotEnabledDoesNothing) {
1624 mOutput.mState.isEnabled = false;
1625
1626 mOutput.finishFrame(mRefreshArgs);
1627}
1628
1629TEST_F(OutputFinishFrameTest, takesEarlyOutifComposeSurfacesReturnsNoFence) {
1630 mOutput.mState.isEnabled = true;
1631
1632 InSequence seq;
1633 EXPECT_CALL(mOutput, composeSurfaces(RegionEq(Region::INVALID_REGION)));
1634
1635 mOutput.finishFrame(mRefreshArgs);
1636}
1637
1638TEST_F(OutputFinishFrameTest, queuesBufferIfComposeSurfacesReturnsAFence) {
1639 mOutput.mState.isEnabled = true;
1640
1641 InSequence seq;
1642 EXPECT_CALL(mOutput, composeSurfaces(RegionEq(Region::INVALID_REGION)))
1643 .WillOnce(Return(ByMove(base::unique_fd())));
1644 EXPECT_CALL(*mRenderSurface, queueBuffer(_));
1645
1646 mOutput.finishFrame(mRefreshArgs);
1647}
Lloyd Piquefaa3f192019-11-14 14:05:09 -08001648
1649/*
1650 * Output::postFramebuffer()
1651 */
1652
1653// TODO(b/144060211) - Add coverage
1654
1655/*
Lloyd Pique56eba802019-08-28 15:45:25 -07001656 * Output::composeSurfaces()
1657 */
1658
1659struct OutputComposeSurfacesTest : public testing::Test {
1660 static constexpr uint32_t kDefaultOutputOrientation = TR_IDENT;
1661 static constexpr ui::Dataspace kDefaultOutputDataspace = ui::Dataspace::DISPLAY_P3;
1662
1663 static const Rect kDefaultOutputFrame;
1664 static const Rect kDefaultOutputViewport;
1665 static const Rect kDefaultOutputScissor;
1666 static const mat4 kDefaultColorTransformMat;
1667
Lloyd Piquefaa3f192019-11-14 14:05:09 -08001668 struct OutputPartialMock : public OutputPartialMockBase {
Lloyd Pique56eba802019-08-28 15:45:25 -07001669 // Sets up the helper functions called by composeSurfaces to use a mock
1670 // implementations.
1671 MOCK_CONST_METHOD0(getSkipColorTransform, bool());
1672 MOCK_METHOD2(generateClientCompositionRequests,
1673 std::vector<renderengine::LayerSettings>(bool, Region&));
1674 MOCK_METHOD2(appendRegionFlashRequests,
1675 void(const Region&, std::vector<renderengine::LayerSettings>&));
1676 MOCK_METHOD1(setExpensiveRenderingExpected, void(bool));
1677 };
1678
1679 OutputComposeSurfacesTest() {
1680 mOutput.setDisplayColorProfileForTest(
1681 std::unique_ptr<DisplayColorProfile>(mDisplayColorProfile));
1682 mOutput.setRenderSurfaceForTest(std::unique_ptr<RenderSurface>(mRenderSurface));
1683
Lloyd Pique56eba802019-08-28 15:45:25 -07001684 mOutput.editState().frame = kDefaultOutputFrame;
1685 mOutput.editState().viewport = kDefaultOutputViewport;
1686 mOutput.editState().scissor = kDefaultOutputScissor;
1687 mOutput.editState().transform = ui::Transform{kDefaultOutputOrientation};
1688 mOutput.editState().orientation = kDefaultOutputOrientation;
1689 mOutput.editState().dataspace = kDefaultOutputDataspace;
Lloyd Pique3eb1b212019-03-07 21:15:40 -08001690 mOutput.editState().colorTransformMatrix = kDefaultColorTransformMat;
Lloyd Pique56eba802019-08-28 15:45:25 -07001691 mOutput.editState().isSecure = true;
1692 mOutput.editState().needsFiltering = false;
1693 mOutput.editState().usesClientComposition = true;
1694 mOutput.editState().usesDeviceComposition = false;
1695
Lloyd Pique01c77c12019-04-17 12:48:32 -07001696 EXPECT_CALL(mOutput, getOutputLayerCount()).WillRepeatedly(Return(2u));
1697 EXPECT_CALL(mOutput, getOutputLayerOrderedByZByIndex(0u))
1698 .WillRepeatedly(Return(&mOutputLayer1));
1699 EXPECT_CALL(mOutput, getOutputLayerOrderedByZByIndex(1u))
1700 .WillRepeatedly(Return(&mOutputLayer2));
Lloyd Piquea38ea7e2019-04-16 18:10:26 -07001701 EXPECT_CALL(mOutput, getCompositionEngine()).WillRepeatedly(ReturnRef(mCompositionEngine));
Lloyd Pique56eba802019-08-28 15:45:25 -07001702 EXPECT_CALL(mCompositionEngine, getRenderEngine()).WillRepeatedly(ReturnRef(mRenderEngine));
1703 }
1704
1705 StrictMock<mock::CompositionEngine> mCompositionEngine;
1706 StrictMock<renderengine::mock::RenderEngine> mRenderEngine;
1707 mock::DisplayColorProfile* mDisplayColorProfile = new StrictMock<mock::DisplayColorProfile>();
1708 mock::RenderSurface* mRenderSurface = new StrictMock<mock::RenderSurface>();
Lloyd Pique01c77c12019-04-17 12:48:32 -07001709 StrictMock<mock::OutputLayer> mOutputLayer1;
1710 StrictMock<mock::OutputLayer> mOutputLayer2;
Lloyd Piquea38ea7e2019-04-16 18:10:26 -07001711 StrictMock<OutputPartialMock> mOutput;
Lloyd Pique56eba802019-08-28 15:45:25 -07001712 sp<GraphicBuffer> mOutputBuffer = new GraphicBuffer();
1713};
1714
1715const Rect OutputComposeSurfacesTest::kDefaultOutputFrame{1001, 1002, 1003, 1004};
1716const Rect OutputComposeSurfacesTest::kDefaultOutputViewport{1005, 1006, 1007, 1008};
1717const Rect OutputComposeSurfacesTest::kDefaultOutputScissor{1009, 1010, 1011, 1012};
1718const mat4 OutputComposeSurfacesTest::kDefaultColorTransformMat{mat4() * 0.5};
1719
1720// TODO(b/121291683): Expand unit test coverage for composeSurfaces beyond these
1721// basic tests.
1722
1723TEST_F(OutputComposeSurfacesTest, doesNothingIfNoClientComposition) {
1724 mOutput.editState().usesClientComposition = false;
1725
1726 Region debugRegion;
Lloyd Piqued3d69882019-02-28 16:03:46 -08001727 std::optional<base::unique_fd> readyFence = mOutput.composeSurfaces(debugRegion);
1728 EXPECT_TRUE(readyFence);
Lloyd Pique56eba802019-08-28 15:45:25 -07001729}
1730
1731TEST_F(OutputComposeSurfacesTest, worksIfNoClientLayersQueued) {
1732 const Region kDebugRegion{Rect{100, 101, 102, 103}};
1733
1734 constexpr float kDefaultMaxLuminance = 1.0f;
1735 constexpr float kDefaultAvgLuminance = 0.7f;
1736 constexpr float kDefaultMinLuminance = 0.1f;
1737 HdrCapabilities HdrCapabilities{{},
1738 kDefaultMaxLuminance,
1739 kDefaultAvgLuminance,
1740 kDefaultMinLuminance};
1741
1742 EXPECT_CALL(mRenderEngine, supportsProtectedContent()).WillOnce(Return(false));
1743 EXPECT_CALL(mRenderEngine, drawLayers(_, _, _, true, _, _)).Times(1);
1744
1745 EXPECT_CALL(*mDisplayColorProfile, hasWideColorGamut()).WillOnce(Return(true));
1746 EXPECT_CALL(*mDisplayColorProfile, getHdrCapabilities()).WillOnce(ReturnRef(HdrCapabilities));
1747
1748 EXPECT_CALL(*mRenderSurface, dequeueBuffer(_)).WillOnce(Return(mOutputBuffer));
1749
1750 EXPECT_CALL(mOutput, getSkipColorTransform()).WillOnce(Return(false));
1751 EXPECT_CALL(mOutput, generateClientCompositionRequests(false, _)).Times(1);
1752 EXPECT_CALL(mOutput, appendRegionFlashRequests(RegionEq(kDebugRegion), _)).Times(1);
1753 EXPECT_CALL(mOutput, setExpensiveRenderingExpected(true)).Times(1);
1754 EXPECT_CALL(mOutput, setExpensiveRenderingExpected(false)).Times(1);
1755
Lloyd Piqued3d69882019-02-28 16:03:46 -08001756 std::optional<base::unique_fd> readyFence = mOutput.composeSurfaces(kDebugRegion);
1757 EXPECT_TRUE(readyFence);
Lloyd Pique56eba802019-08-28 15:45:25 -07001758}
1759
1760/*
1761 * Output::generateClientCompositionRequests()
1762 */
1763
1764struct GenerateClientCompositionRequestsTest : public testing::Test {
Lloyd Piquefaa3f192019-11-14 14:05:09 -08001765 struct OutputPartialMock : public OutputPartialMockBase {
Lloyd Piquea38ea7e2019-04-16 18:10:26 -07001766 // compositionengine::Output overrides
Lloyd Pique56eba802019-08-28 15:45:25 -07001767 std::vector<renderengine::LayerSettings> generateClientCompositionRequests(
1768 bool supportsProtectedContent, Region& clearRegion) override {
1769 return impl::Output::generateClientCompositionRequests(supportsProtectedContent,
1770 clearRegion);
1771 }
1772 };
1773
1774 GenerateClientCompositionRequestsTest() {
1775 mOutput.setDisplayColorProfileForTest(
1776 std::unique_ptr<DisplayColorProfile>(mDisplayColorProfile));
1777 mOutput.setRenderSurfaceForTest(std::unique_ptr<RenderSurface>(mRenderSurface));
1778 }
1779
Lloyd Pique56eba802019-08-28 15:45:25 -07001780 mock::DisplayColorProfile* mDisplayColorProfile = new StrictMock<mock::DisplayColorProfile>();
1781 mock::RenderSurface* mRenderSurface = new StrictMock<mock::RenderSurface>();
Lloyd Piquea38ea7e2019-04-16 18:10:26 -07001782 StrictMock<OutputPartialMock> mOutput;
Lloyd Pique56eba802019-08-28 15:45:25 -07001783};
1784
1785// TODO(b/121291683): Add more unit test coverage for generateClientCompositionRequests
1786
1787TEST_F(GenerateClientCompositionRequestsTest, worksForLandscapeModeSplitScreen) {
1788 // In split-screen landscape mode, the screen is rotated 90 degrees, with
1789 // one layer on the left covering the left side of the output, and one layer
1790 // on the right covering that side of the output.
1791
Lloyd Pique01c77c12019-04-17 12:48:32 -07001792 StrictMock<mock::OutputLayer> leftOutputLayer;
1793 StrictMock<mock::OutputLayer> rightOutputLayer;
Lloyd Pique56eba802019-08-28 15:45:25 -07001794
1795 StrictMock<mock::Layer> leftLayer;
1796 StrictMock<mock::LayerFE> leftLayerFE;
1797 StrictMock<mock::Layer> rightLayer;
1798 StrictMock<mock::LayerFE> rightLayerFE;
1799
1800 impl::OutputLayerCompositionState leftOutputLayerState;
1801 leftOutputLayerState.clearClientTarget = false;
Lloyd Piquea2468662019-03-07 21:31:06 -08001802 leftOutputLayerState.visibleRegion = Region{Rect{0, 0, 1000, 1000}};
Lloyd Pique56eba802019-08-28 15:45:25 -07001803
Lloyd Pique9755fb72019-03-26 14:44:40 -07001804 LayerFECompositionState leftLayerFEState;
1805 leftLayerFEState.isOpaque = true;
Lloyd Pique56eba802019-08-28 15:45:25 -07001806
1807 const half3 leftLayerColor{1.f, 0.f, 0.f};
1808 renderengine::LayerSettings leftLayerRESettings;
1809 leftLayerRESettings.source.solidColor = leftLayerColor;
1810
1811 impl::OutputLayerCompositionState rightOutputLayerState;
1812 rightOutputLayerState.clearClientTarget = false;
Lloyd Piquea2468662019-03-07 21:31:06 -08001813 rightOutputLayerState.visibleRegion = Region{Rect{1000, 0, 2000, 1000}};
Lloyd Pique56eba802019-08-28 15:45:25 -07001814
Lloyd Pique9755fb72019-03-26 14:44:40 -07001815 LayerFECompositionState rightLayerFEState;
1816 rightLayerFEState.isOpaque = true;
Lloyd Pique56eba802019-08-28 15:45:25 -07001817
1818 const half3 rightLayerColor{0.f, 1.f, 0.f};
1819 renderengine::LayerSettings rightLayerRESettings;
1820 rightLayerRESettings.source.solidColor = rightLayerColor;
1821
Lloyd Pique01c77c12019-04-17 12:48:32 -07001822 EXPECT_CALL(leftOutputLayer, getState()).WillRepeatedly(ReturnRef(leftOutputLayerState));
1823 EXPECT_CALL(leftOutputLayer, getLayer()).WillRepeatedly(ReturnRef(leftLayer));
1824 EXPECT_CALL(leftOutputLayer, getLayerFE()).WillRepeatedly(ReturnRef(leftLayerFE));
1825 EXPECT_CALL(leftOutputLayer, requiresClientComposition()).WillRepeatedly(Return(true));
1826 EXPECT_CALL(leftOutputLayer, needsFiltering()).WillRepeatedly(Return(false));
Lloyd Pique9755fb72019-03-26 14:44:40 -07001827 EXPECT_CALL(leftLayer, getFEState()).WillRepeatedly(ReturnRef(leftLayerFEState));
Lloyd Pique56eba802019-08-28 15:45:25 -07001828 EXPECT_CALL(leftLayerFE, prepareClientComposition(_)).WillOnce(Return(leftLayerRESettings));
Adithya Srinivasanb69e0762019-11-11 18:39:53 -08001829 EXPECT_CALL(leftOutputLayer, editState()).WillRepeatedly(ReturnRef(leftOutputLayerState));
Lloyd Pique56eba802019-08-28 15:45:25 -07001830
Lloyd Pique01c77c12019-04-17 12:48:32 -07001831 EXPECT_CALL(rightOutputLayer, getState()).WillRepeatedly(ReturnRef(rightOutputLayerState));
1832 EXPECT_CALL(rightOutputLayer, getLayer()).WillRepeatedly(ReturnRef(rightLayer));
1833 EXPECT_CALL(rightOutputLayer, getLayerFE()).WillRepeatedly(ReturnRef(rightLayerFE));
1834 EXPECT_CALL(rightOutputLayer, requiresClientComposition()).WillRepeatedly(Return(true));
1835 EXPECT_CALL(rightOutputLayer, needsFiltering()).WillRepeatedly(Return(false));
Lloyd Pique9755fb72019-03-26 14:44:40 -07001836 EXPECT_CALL(rightLayer, getFEState()).WillRepeatedly(ReturnRef(rightLayerFEState));
Lloyd Pique56eba802019-08-28 15:45:25 -07001837 EXPECT_CALL(rightLayerFE, prepareClientComposition(_)).WillOnce(Return(rightLayerRESettings));
Adithya Srinivasanb69e0762019-11-11 18:39:53 -08001838 EXPECT_CALL(rightOutputLayer, editState()).WillRepeatedly(ReturnRef(rightOutputLayerState));
Lloyd Pique56eba802019-08-28 15:45:25 -07001839
Lloyd Pique01c77c12019-04-17 12:48:32 -07001840 EXPECT_CALL(mOutput, getOutputLayerCount()).WillRepeatedly(Return(2u));
1841 EXPECT_CALL(mOutput, getOutputLayerOrderedByZByIndex(0u))
1842 .WillRepeatedly(Return(&leftOutputLayer));
1843 EXPECT_CALL(mOutput, getOutputLayerOrderedByZByIndex(1u))
1844 .WillRepeatedly(Return(&rightOutputLayer));
Lloyd Pique56eba802019-08-28 15:45:25 -07001845
1846 const Rect kPortraitFrame(0, 0, 1000, 2000);
1847 const Rect kPortraitViewport(0, 0, 2000, 1000);
1848 const Rect kPortraitScissor(0, 0, 1000, 2000);
1849 const uint32_t kPortraitOrientation = TR_ROT_90;
1850
1851 mOutput.editState().frame = kPortraitFrame;
1852 mOutput.editState().viewport = kPortraitViewport;
1853 mOutput.editState().scissor = kPortraitScissor;
1854 mOutput.editState().transform = ui::Transform{kPortraitOrientation};
1855 mOutput.editState().orientation = kPortraitOrientation;
1856 mOutput.editState().needsFiltering = true;
1857 mOutput.editState().isSecure = false;
1858
1859 constexpr bool supportsProtectedContent = false;
1860 Region clearRegion;
1861 auto requests =
1862 mOutput.generateClientCompositionRequests(supportsProtectedContent, clearRegion);
1863
1864 ASSERT_EQ(2u, requests.size());
1865 EXPECT_EQ(leftLayerColor, requests[0].source.solidColor);
1866 EXPECT_EQ(rightLayerColor, requests[1].source.solidColor);
1867}
1868
1869TEST_F(GenerateClientCompositionRequestsTest, ignoresLayersThatDoNotIntersectWithViewport) {
1870 // Layers whose visible region does not intersect with the viewport will be
1871 // skipped when generating client composition request state.
1872
Lloyd Pique01c77c12019-04-17 12:48:32 -07001873 StrictMock<mock::OutputLayer> outputLayer;
Lloyd Pique56eba802019-08-28 15:45:25 -07001874 StrictMock<mock::Layer> layer;
1875 StrictMock<mock::LayerFE> layerFE;
1876
1877 impl::OutputLayerCompositionState outputLayerState;
1878 outputLayerState.clearClientTarget = false;
Lloyd Piquea2468662019-03-07 21:31:06 -08001879 outputLayerState.visibleRegion = Region{Rect{3000, 0, 4000, 1000}};
Lloyd Pique56eba802019-08-28 15:45:25 -07001880
Lloyd Pique9755fb72019-03-26 14:44:40 -07001881 LayerFECompositionState layerFEState;
1882 layerFEState.isOpaque = true;
Lloyd Pique56eba802019-08-28 15:45:25 -07001883
Lloyd Pique01c77c12019-04-17 12:48:32 -07001884 EXPECT_CALL(outputLayer, getState()).WillRepeatedly(ReturnRef(outputLayerState));
1885 EXPECT_CALL(outputLayer, getLayer()).WillRepeatedly(ReturnRef(layer));
1886 EXPECT_CALL(outputLayer, getLayerFE()).WillRepeatedly(ReturnRef(layerFE));
1887 EXPECT_CALL(outputLayer, requiresClientComposition()).WillRepeatedly(Return(true));
1888 EXPECT_CALL(outputLayer, needsFiltering()).WillRepeatedly(Return(false));
Lloyd Pique9755fb72019-03-26 14:44:40 -07001889 EXPECT_CALL(layer, getFEState()).WillRepeatedly(ReturnRef(layerFEState));
Lloyd Pique56eba802019-08-28 15:45:25 -07001890 EXPECT_CALL(layerFE, prepareClientComposition(_)).Times(0);
Adithya Srinivasanb69e0762019-11-11 18:39:53 -08001891 EXPECT_CALL(outputLayer, editState()).WillRepeatedly(ReturnRef(outputLayerState));
Lloyd Pique56eba802019-08-28 15:45:25 -07001892
Lloyd Pique01c77c12019-04-17 12:48:32 -07001893 EXPECT_CALL(mOutput, getOutputLayerCount()).WillRepeatedly(Return(1u));
1894 EXPECT_CALL(mOutput, getOutputLayerOrderedByZByIndex(0u)).WillRepeatedly(Return(&outputLayer));
Lloyd Pique56eba802019-08-28 15:45:25 -07001895
1896 const Rect kPortraitFrame(0, 0, 1000, 2000);
1897 const Rect kPortraitViewport(0, 0, 2000, 1000);
1898 const Rect kPortraitScissor(0, 0, 1000, 2000);
1899 const uint32_t kPortraitOrientation = TR_ROT_90;
1900
1901 mOutput.editState().frame = kPortraitFrame;
1902 mOutput.editState().viewport = kPortraitViewport;
1903 mOutput.editState().scissor = kPortraitScissor;
1904 mOutput.editState().transform = ui::Transform{kPortraitOrientation};
1905 mOutput.editState().orientation = kPortraitOrientation;
1906 mOutput.editState().needsFiltering = true;
1907 mOutput.editState().isSecure = false;
1908
1909 constexpr bool supportsProtectedContent = false;
1910 Region clearRegion;
1911 auto requests =
1912 mOutput.generateClientCompositionRequests(supportsProtectedContent, clearRegion);
1913
1914 EXPECT_EQ(0u, requests.size());
1915}
1916
Lloyd Piquec2d54d42019-08-28 18:04:21 -07001917TEST_F(GenerateClientCompositionRequestsTest, clearsDeviceLayesAfterFirst) {
1918 // If client composition is performed with some layers set to use device
1919 // composition, device layers after the first layer (device or client) will
1920 // clear the frame buffer if they are opaque and if that layer has a flag
1921 // set to do so. The first layer is skipped as the frame buffer is already
1922 // expected to be clear.
1923
Lloyd Pique01c77c12019-04-17 12:48:32 -07001924 StrictMock<mock::OutputLayer> leftOutputLayer;
1925 StrictMock<mock::OutputLayer> rightOutputLayer;
Lloyd Piquec2d54d42019-08-28 18:04:21 -07001926
1927 StrictMock<mock::Layer> leftLayer;
1928 StrictMock<mock::LayerFE> leftLayerFE;
1929 StrictMock<mock::Layer> rightLayer;
1930 StrictMock<mock::LayerFE> rightLayerFE;
1931
1932 impl::OutputLayerCompositionState leftOutputLayerState;
1933 leftOutputLayerState.clearClientTarget = true;
Lloyd Piquea2468662019-03-07 21:31:06 -08001934 leftOutputLayerState.visibleRegion = Region{Rect{0, 0, 1000, 1000}};
Lloyd Piquec2d54d42019-08-28 18:04:21 -07001935
Lloyd Pique9755fb72019-03-26 14:44:40 -07001936 LayerFECompositionState leftLayerFEState;
1937 leftLayerFEState.isOpaque = true;
Lloyd Piquec2d54d42019-08-28 18:04:21 -07001938
1939 impl::OutputLayerCompositionState rightOutputLayerState;
1940 rightOutputLayerState.clearClientTarget = true;
Lloyd Piquea2468662019-03-07 21:31:06 -08001941 rightOutputLayerState.visibleRegion = Region{Rect{1000, 0, 2000, 1000}};
Lloyd Piquec2d54d42019-08-28 18:04:21 -07001942
Lloyd Pique9755fb72019-03-26 14:44:40 -07001943 LayerFECompositionState rightLayerFEState;
1944 rightLayerFEState.isOpaque = true;
Lloyd Piquec2d54d42019-08-28 18:04:21 -07001945
1946 const half3 rightLayerColor{0.f, 1.f, 0.f};
1947 renderengine::LayerSettings rightLayerRESettings;
1948 rightLayerRESettings.geometry.boundaries = FloatRect{456, 0, 0, 0};
1949 rightLayerRESettings.source.solidColor = rightLayerColor;
1950
Lloyd Pique01c77c12019-04-17 12:48:32 -07001951 EXPECT_CALL(leftOutputLayer, getState()).WillRepeatedly(ReturnRef(leftOutputLayerState));
1952 EXPECT_CALL(leftOutputLayer, getLayer()).WillRepeatedly(ReturnRef(leftLayer));
1953 EXPECT_CALL(leftOutputLayer, getLayerFE()).WillRepeatedly(ReturnRef(leftLayerFE));
1954 EXPECT_CALL(leftOutputLayer, requiresClientComposition()).WillRepeatedly(Return(false));
1955 EXPECT_CALL(leftOutputLayer, needsFiltering()).WillRepeatedly(Return(false));
Lloyd Pique9755fb72019-03-26 14:44:40 -07001956 EXPECT_CALL(leftLayer, getFEState()).WillRepeatedly(ReturnRef(leftLayerFEState));
Adithya Srinivasanb69e0762019-11-11 18:39:53 -08001957 EXPECT_CALL(leftOutputLayer, editState()).WillRepeatedly(ReturnRef(leftOutputLayerState));
Lloyd Piquec2d54d42019-08-28 18:04:21 -07001958
Lloyd Pique01c77c12019-04-17 12:48:32 -07001959 EXPECT_CALL(rightOutputLayer, getState()).WillRepeatedly(ReturnRef(rightOutputLayerState));
1960 EXPECT_CALL(rightOutputLayer, getLayer()).WillRepeatedly(ReturnRef(rightLayer));
1961 EXPECT_CALL(rightOutputLayer, getLayerFE()).WillRepeatedly(ReturnRef(rightLayerFE));
1962 EXPECT_CALL(rightOutputLayer, requiresClientComposition()).WillRepeatedly(Return(false));
1963 EXPECT_CALL(rightOutputLayer, needsFiltering()).WillRepeatedly(Return(false));
Lloyd Pique9755fb72019-03-26 14:44:40 -07001964 EXPECT_CALL(rightLayer, getFEState()).WillRepeatedly(ReturnRef(rightLayerFEState));
Lloyd Piquec2d54d42019-08-28 18:04:21 -07001965 EXPECT_CALL(rightLayerFE, prepareClientComposition(_)).WillOnce(Return(rightLayerRESettings));
Adithya Srinivasanb69e0762019-11-11 18:39:53 -08001966 EXPECT_CALL(rightOutputLayer, editState()).WillRepeatedly(ReturnRef(rightOutputLayerState));
Lloyd Piquec2d54d42019-08-28 18:04:21 -07001967
Lloyd Pique01c77c12019-04-17 12:48:32 -07001968 EXPECT_CALL(mOutput, getOutputLayerCount()).WillRepeatedly(Return(2u));
1969 EXPECT_CALL(mOutput, getOutputLayerOrderedByZByIndex(0u))
1970 .WillRepeatedly(Return(&leftOutputLayer));
1971 EXPECT_CALL(mOutput, getOutputLayerOrderedByZByIndex(1u))
1972 .WillRepeatedly(Return(&rightOutputLayer));
Lloyd Piquec2d54d42019-08-28 18:04:21 -07001973
1974 const Rect kPortraitFrame(0, 0, 1000, 2000);
1975 const Rect kPortraitViewport(0, 0, 2000, 1000);
1976 const Rect kPortraitScissor(0, 0, 1000, 2000);
1977 const uint32_t kPortraitOrientation = TR_ROT_90;
1978
1979 mOutput.editState().frame = kPortraitFrame;
1980 mOutput.editState().viewport = kPortraitViewport;
1981 mOutput.editState().scissor = kPortraitScissor;
1982 mOutput.editState().transform = ui::Transform{kPortraitOrientation};
1983 mOutput.editState().orientation = kPortraitOrientation;
1984 mOutput.editState().needsFiltering = true;
1985 mOutput.editState().isSecure = false;
1986
1987 constexpr bool supportsProtectedContent = false;
1988 Region clearRegion;
1989 auto requests =
1990 mOutput.generateClientCompositionRequests(supportsProtectedContent, clearRegion);
1991
1992 const half3 clearColor{0.f, 0.f, 0.f};
1993
1994 ASSERT_EQ(1u, requests.size());
1995 EXPECT_EQ(456.f, requests[0].geometry.boundaries.left);
1996 EXPECT_EQ(clearColor, requests[0].source.solidColor);
1997}
1998
Lloyd Pique32cbe282018-10-19 13:09:22 -07001999} // namespace
2000} // namespace android::compositionengine