blob: a9a735a80dbdc5868188380ea93297b77dab6659 [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 Pique07178e32019-11-19 19:15:26 -080036#include "MockHWC2.h"
Lloyd Pique32cbe282018-10-19 13:09:22 -070037#include "RegionMatcher.h"
38#include "TransformMatcher.h"
39
40namespace android::compositionengine {
41namespace {
42
Lloyd Pique56eba802019-08-28 15:45:25 -070043using testing::_;
Lloyd Pique03561a62019-11-19 18:34:52 -080044using testing::ByMove;
Lloyd Pique17ca7422019-11-14 14:24:10 -080045using testing::DoAll;
Lloyd Pique07178e32019-11-19 19:15:26 -080046using testing::Eq;
Lloyd Piquefaa3f192019-11-14 14:05:09 -080047using testing::InSequence;
Lloyd Pique17ca7422019-11-14 14:24:10 -080048using testing::Mock;
Lloyd Pique07178e32019-11-19 19:15:26 -080049using testing::Property;
Lloyd Piquefaa3f192019-11-14 14:05:09 -080050using testing::Ref;
Lloyd Pique31cb2942018-10-19 17:23:03 -070051using testing::Return;
Lloyd Pique32cbe282018-10-19 13:09:22 -070052using testing::ReturnRef;
Lloyd Pique17ca7422019-11-14 14:24:10 -080053using testing::SetArgPointee;
Lloyd Pique32cbe282018-10-19 13:09:22 -070054using testing::StrictMock;
55
Lloyd Pique56eba802019-08-28 15:45:25 -070056constexpr auto TR_IDENT = 0u;
57constexpr auto TR_ROT_90 = HAL_TRANSFORM_ROT_90;
58
Lloyd Pique3eb1b212019-03-07 21:15:40 -080059const mat4 kIdentity;
60const mat4 kNonIdentityHalf = mat4() * 0.5;
61const mat4 kNonIdentityQuarter = mat4() * 0.25;
62
Lloyd Pique17ca7422019-11-14 14:24:10 -080063constexpr OutputColorSetting kVendorSpecifiedOutputColorSetting =
64 static_cast<OutputColorSetting>(0x100);
65
Lloyd Piquefaa3f192019-11-14 14:05:09 -080066struct OutputPartialMockBase : public impl::Output {
67 // compositionengine::Output overrides
68 const OutputCompositionState& getState() const override { return mState; }
69 OutputCompositionState& editState() override { return mState; }
70
71 // Use mocks for all the remaining virtual functions
72 // not implemented by the base implementation class.
73 MOCK_CONST_METHOD0(getOutputLayerCount, size_t());
74 MOCK_CONST_METHOD1(getOutputLayerOrderedByZByIndex, compositionengine::OutputLayer*(size_t));
75 MOCK_METHOD3(ensureOutputLayer,
76 compositionengine::OutputLayer*(std::optional<size_t>,
77 const std::shared_ptr<compositionengine::Layer>&,
78 const sp<LayerFE>&));
79 MOCK_METHOD0(finalizePendingOutputLayers, void());
80 MOCK_METHOD0(clearOutputLayers, void());
81 MOCK_CONST_METHOD1(dumpState, void(std::string&));
82 MOCK_CONST_METHOD0(getCompositionEngine, const CompositionEngine&());
83 MOCK_METHOD2(injectOutputLayerForTest,
84 compositionengine::OutputLayer*(const std::shared_ptr<compositionengine::Layer>&,
85 const sp<LayerFE>&));
86 MOCK_METHOD1(injectOutputLayerForTest, void(std::unique_ptr<OutputLayer>));
87
88 impl::OutputCompositionState mState;
89};
90
Lloyd Pique66d68602019-02-13 14:23:31 -080091struct OutputTest : public testing::Test {
Lloyd Pique01c77c12019-04-17 12:48:32 -070092 class Output : public impl::Output {
93 public:
94 using impl::Output::injectOutputLayerForTest;
95 virtual void injectOutputLayerForTest(std::unique_ptr<compositionengine::OutputLayer>) = 0;
96 };
97
98 static std::shared_ptr<Output> createOutput(
99 const compositionengine::CompositionEngine& compositionEngine) {
100 return impl::createOutputTemplated<Output>(compositionEngine);
101 }
102
Lloyd Pique31cb2942018-10-19 17:23:03 -0700103 OutputTest() {
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700104 mOutput->setDisplayColorProfileForTest(
Lloyd Pique3d0c02e2018-10-19 18:38:12 -0700105 std::unique_ptr<DisplayColorProfile>(mDisplayColorProfile));
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700106 mOutput->setRenderSurfaceForTest(std::unique_ptr<RenderSurface>(mRenderSurface));
Lloyd Piqueef958122019-02-05 18:00:12 -0800107
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700108 mOutput->editState().bounds = kDefaultDisplaySize;
Lloyd Pique31cb2942018-10-19 17:23:03 -0700109 }
Lloyd Pique32cbe282018-10-19 13:09:22 -0700110
Lloyd Piqueef958122019-02-05 18:00:12 -0800111 static const Rect kDefaultDisplaySize;
112
Lloyd Pique32cbe282018-10-19 13:09:22 -0700113 StrictMock<mock::CompositionEngine> mCompositionEngine;
Lloyd Pique3d0c02e2018-10-19 18:38:12 -0700114 mock::DisplayColorProfile* mDisplayColorProfile = new StrictMock<mock::DisplayColorProfile>();
Lloyd Pique31cb2942018-10-19 17:23:03 -0700115 mock::RenderSurface* mRenderSurface = new StrictMock<mock::RenderSurface>();
Lloyd Pique01c77c12019-04-17 12:48:32 -0700116 std::shared_ptr<Output> mOutput = createOutput(mCompositionEngine);
Lloyd Pique32cbe282018-10-19 13:09:22 -0700117};
118
Lloyd Piquec0ee6ba2019-11-14 12:55:53 -0800119// Extension of the base test useful for checking interactions with the LayerFE
120// functions to latch composition state.
121struct OutputLatchFEStateTest : public OutputTest {
122 OutputLatchFEStateTest() {
123 EXPECT_CALL(*mOutputLayer1, getLayer()).WillRepeatedly(ReturnRef(mLayer1));
124 EXPECT_CALL(*mOutputLayer2, getLayer()).WillRepeatedly(ReturnRef(mLayer2));
125 EXPECT_CALL(*mOutputLayer3, getLayer()).WillRepeatedly(ReturnRef(mLayer3));
126
127 EXPECT_CALL(*mOutputLayer1, getLayerFE()).WillRepeatedly(ReturnRef(mLayer1FE));
128 EXPECT_CALL(*mOutputLayer2, getLayerFE()).WillRepeatedly(ReturnRef(mLayer2FE));
129 EXPECT_CALL(*mOutputLayer3, getLayerFE()).WillRepeatedly(ReturnRef(mLayer3FE));
130
131 EXPECT_CALL(mLayer1, editFEState()).WillRepeatedly(ReturnRef(mLayer1FEState));
132 EXPECT_CALL(mLayer2, editFEState()).WillRepeatedly(ReturnRef(mLayer2FEState));
133 EXPECT_CALL(mLayer3, editFEState()).WillRepeatedly(ReturnRef(mLayer3FEState));
134 }
135
136 void injectLayer(std::unique_ptr<mock::OutputLayer> layer) {
137 mOutput->injectOutputLayerForTest(std::unique_ptr<OutputLayer>(layer.release()));
138 }
139
140 std::unique_ptr<mock::OutputLayer> mOutputLayer1{new StrictMock<mock::OutputLayer>};
141 std::unique_ptr<mock::OutputLayer> mOutputLayer2{new StrictMock<mock::OutputLayer>};
142 std::unique_ptr<mock::OutputLayer> mOutputLayer3{new StrictMock<mock::OutputLayer>};
143
144 StrictMock<mock::Layer> mLayer1;
145 StrictMock<mock::Layer> mLayer2;
146 StrictMock<mock::Layer> mLayer3;
147
148 StrictMock<mock::LayerFE> mLayer1FE;
149 StrictMock<mock::LayerFE> mLayer2FE;
150 StrictMock<mock::LayerFE> mLayer3FE;
151
152 LayerFECompositionState mLayer1FEState;
153 LayerFECompositionState mLayer2FEState;
154 LayerFECompositionState mLayer3FEState;
155};
156
Lloyd Piqueef958122019-02-05 18:00:12 -0800157const Rect OutputTest::kDefaultDisplaySize{100, 200};
158
Lloyd Pique17ca7422019-11-14 14:24:10 -0800159using ColorProfile = compositionengine::Output::ColorProfile;
160
161void dumpColorProfile(ColorProfile profile, std::string& result, const char* name) {
162 android::base::StringAppendF(&result, "%s (%s[%d] %s[%d] %s[%d] %s[%d]) ", name,
163 toString(profile.mode).c_str(), profile.mode,
164 toString(profile.dataspace).c_str(), profile.dataspace,
165 toString(profile.renderIntent).c_str(), profile.renderIntent,
166 toString(profile.colorSpaceAgnosticDataspace).c_str(),
167 profile.colorSpaceAgnosticDataspace);
168}
169
170// Checks for a ColorProfile match
171MATCHER_P(ColorProfileEq, expected, "") {
172 std::string buf;
173 buf.append("ColorProfiles are not equal\n");
174 dumpColorProfile(expected, buf, "expected value");
175 dumpColorProfile(arg, buf, "actual value");
176 *result_listener << buf;
177
178 return (expected.mode == arg.mode) && (expected.dataspace == arg.dataspace) &&
179 (expected.renderIntent == arg.renderIntent) &&
180 (expected.colorSpaceAgnosticDataspace == arg.colorSpaceAgnosticDataspace);
181}
182
Lloyd Pique66d68602019-02-13 14:23:31 -0800183/*
Lloyd Pique32cbe282018-10-19 13:09:22 -0700184 * Basic construction
185 */
186
Lloyd Pique31cb2942018-10-19 17:23:03 -0700187TEST_F(OutputTest, canInstantiateOutput) {
188 // The validation check checks each required component.
Lloyd Pique3d0c02e2018-10-19 18:38:12 -0700189 EXPECT_CALL(*mDisplayColorProfile, isValid()).WillOnce(Return(true));
Lloyd Pique31cb2942018-10-19 17:23:03 -0700190 EXPECT_CALL(*mRenderSurface, isValid()).WillOnce(Return(true));
191
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700192 EXPECT_TRUE(mOutput->isValid());
Lloyd Pique31cb2942018-10-19 17:23:03 -0700193
194 // If we take away the required components, it is no longer valid.
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700195 mOutput->setRenderSurfaceForTest(std::unique_ptr<RenderSurface>());
Lloyd Pique31cb2942018-10-19 17:23:03 -0700196
Lloyd Pique3d0c02e2018-10-19 18:38:12 -0700197 EXPECT_CALL(*mDisplayColorProfile, isValid()).WillOnce(Return(true));
198
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700199 EXPECT_FALSE(mOutput->isValid());
Lloyd Pique31cb2942018-10-19 17:23:03 -0700200}
Lloyd Pique32cbe282018-10-19 13:09:22 -0700201
Lloyd Pique66d68602019-02-13 14:23:31 -0800202/*
Lloyd Pique32cbe282018-10-19 13:09:22 -0700203 * Output::setCompositionEnabled()
204 */
205
206TEST_F(OutputTest, setCompositionEnabledDoesNothingIfAlreadyEnabled) {
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700207 mOutput->editState().isEnabled = true;
Lloyd Pique32cbe282018-10-19 13:09:22 -0700208
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700209 mOutput->setCompositionEnabled(true);
Lloyd Pique32cbe282018-10-19 13:09:22 -0700210
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700211 EXPECT_TRUE(mOutput->getState().isEnabled);
212 EXPECT_THAT(mOutput->getState().dirtyRegion, RegionEq(Region()));
Lloyd Pique32cbe282018-10-19 13:09:22 -0700213}
214
215TEST_F(OutputTest, setCompositionEnabledSetsEnabledAndDirtiesEntireOutput) {
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700216 mOutput->editState().isEnabled = false;
Lloyd Pique32cbe282018-10-19 13:09:22 -0700217
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700218 mOutput->setCompositionEnabled(true);
Lloyd Pique32cbe282018-10-19 13:09:22 -0700219
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700220 EXPECT_TRUE(mOutput->getState().isEnabled);
221 EXPECT_THAT(mOutput->getState().dirtyRegion, RegionEq(Region(kDefaultDisplaySize)));
Lloyd Pique32cbe282018-10-19 13:09:22 -0700222}
223
224TEST_F(OutputTest, setCompositionEnabledSetsDisabledAndDirtiesEntireOutput) {
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700225 mOutput->editState().isEnabled = true;
Lloyd Pique32cbe282018-10-19 13:09:22 -0700226
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700227 mOutput->setCompositionEnabled(false);
Lloyd Pique32cbe282018-10-19 13:09:22 -0700228
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700229 EXPECT_FALSE(mOutput->getState().isEnabled);
230 EXPECT_THAT(mOutput->getState().dirtyRegion, RegionEq(Region(kDefaultDisplaySize)));
Lloyd Pique32cbe282018-10-19 13:09:22 -0700231}
232
Lloyd Pique66d68602019-02-13 14:23:31 -0800233/*
Lloyd Pique32cbe282018-10-19 13:09:22 -0700234 * Output::setProjection()
235 */
236
237TEST_F(OutputTest, setProjectionTriviallyWorks) {
238 const ui::Transform transform{ui::Transform::ROT_180};
239 const int32_t orientation = 123;
240 const Rect frame{1, 2, 3, 4};
241 const Rect viewport{5, 6, 7, 8};
242 const Rect scissor{9, 10, 11, 12};
243 const bool needsFiltering = true;
244
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700245 mOutput->setProjection(transform, orientation, frame, viewport, scissor, needsFiltering);
Lloyd Pique32cbe282018-10-19 13:09:22 -0700246
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700247 EXPECT_THAT(mOutput->getState().transform, TransformEq(transform));
248 EXPECT_EQ(orientation, mOutput->getState().orientation);
249 EXPECT_EQ(frame, mOutput->getState().frame);
250 EXPECT_EQ(viewport, mOutput->getState().viewport);
251 EXPECT_EQ(scissor, mOutput->getState().scissor);
252 EXPECT_EQ(needsFiltering, mOutput->getState().needsFiltering);
Lloyd Pique32cbe282018-10-19 13:09:22 -0700253}
254
Lloyd Pique66d68602019-02-13 14:23:31 -0800255/*
Lloyd Pique32cbe282018-10-19 13:09:22 -0700256 * Output::setBounds()
257 */
258
259TEST_F(OutputTest, setBoundsSetsSizeAndDirtiesEntireOutput) {
Lloyd Piqueef958122019-02-05 18:00:12 -0800260 const ui::Size displaySize{200, 400};
Lloyd Pique31cb2942018-10-19 17:23:03 -0700261
262 EXPECT_CALL(*mRenderSurface, setDisplaySize(displaySize)).Times(1);
263 EXPECT_CALL(*mRenderSurface, getSize()).WillOnce(ReturnRef(displaySize));
264
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700265 mOutput->setBounds(displaySize);
Lloyd Pique32cbe282018-10-19 13:09:22 -0700266
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700267 EXPECT_EQ(Rect(displaySize), mOutput->getState().bounds);
Lloyd Pique32cbe282018-10-19 13:09:22 -0700268
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700269 EXPECT_THAT(mOutput->getState().dirtyRegion, RegionEq(Region(Rect(displaySize))));
Lloyd Pique32cbe282018-10-19 13:09:22 -0700270}
271
Lloyd Pique66d68602019-02-13 14:23:31 -0800272/*
Lloyd Pique32cbe282018-10-19 13:09:22 -0700273 * Output::setLayerStackFilter()
274 */
275
276TEST_F(OutputTest, setLayerStackFilterSetsFilterAndDirtiesEntireOutput) {
Lloyd Pique32cbe282018-10-19 13:09:22 -0700277 const uint32_t layerStack = 123u;
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700278 mOutput->setLayerStackFilter(layerStack, true);
Lloyd Pique32cbe282018-10-19 13:09:22 -0700279
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700280 EXPECT_TRUE(mOutput->getState().layerStackInternal);
281 EXPECT_EQ(layerStack, mOutput->getState().layerStackId);
Lloyd Pique32cbe282018-10-19 13:09:22 -0700282
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700283 EXPECT_THAT(mOutput->getState().dirtyRegion, RegionEq(Region(kDefaultDisplaySize)));
Lloyd Pique32cbe282018-10-19 13:09:22 -0700284}
285
Lloyd Pique66d68602019-02-13 14:23:31 -0800286/*
Lloyd Pique32cbe282018-10-19 13:09:22 -0700287 * Output::setColorTransform
288 */
289
Lloyd Pique3eb1b212019-03-07 21:15:40 -0800290TEST_F(OutputTest, setColorTransformWithNoChangeFlaggedSkipsUpdates) {
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700291 mOutput->editState().colorTransformMatrix = kIdentity;
Lloyd Pique32cbe282018-10-19 13:09:22 -0700292
Lloyd Pique3eb1b212019-03-07 21:15:40 -0800293 // If no colorTransformMatrix is set the update should be skipped.
294 CompositionRefreshArgs refreshArgs;
295 refreshArgs.colorTransformMatrix = std::nullopt;
Lloyd Pique32cbe282018-10-19 13:09:22 -0700296
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700297 mOutput->setColorTransform(refreshArgs);
Lloyd Pique32cbe282018-10-19 13:09:22 -0700298
Lloyd Pique3eb1b212019-03-07 21:15:40 -0800299 // The internal state should be unchanged
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700300 EXPECT_EQ(kIdentity, mOutput->getState().colorTransformMatrix);
Lloyd Pique3eb1b212019-03-07 21:15:40 -0800301
302 // No dirty region should be set
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700303 EXPECT_THAT(mOutput->getState().dirtyRegion, RegionEq(Region()));
Lloyd Pique3eb1b212019-03-07 21:15:40 -0800304}
Lloyd Piqueef958122019-02-05 18:00:12 -0800305
Lloyd Pique3eb1b212019-03-07 21:15:40 -0800306TEST_F(OutputTest, setColorTransformWithNoActualChangeSkipsUpdates) {
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700307 mOutput->editState().colorTransformMatrix = kIdentity;
Lloyd Pique32cbe282018-10-19 13:09:22 -0700308
Lloyd Pique3eb1b212019-03-07 21:15:40 -0800309 // Attempting to set the same colorTransformMatrix that is already set should
310 // also skip the update.
311 CompositionRefreshArgs refreshArgs;
312 refreshArgs.colorTransformMatrix = kIdentity;
Lloyd Pique32cbe282018-10-19 13:09:22 -0700313
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700314 mOutput->setColorTransform(refreshArgs);
Lloyd Pique77f79a22019-04-29 15:55:40 -0700315
Lloyd Pique3eb1b212019-03-07 21:15:40 -0800316 // The internal state should be unchanged
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700317 EXPECT_EQ(kIdentity, mOutput->getState().colorTransformMatrix);
Lloyd Pique3eb1b212019-03-07 21:15:40 -0800318
319 // No dirty region should be set
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700320 EXPECT_THAT(mOutput->getState().dirtyRegion, RegionEq(Region()));
Lloyd Pique3eb1b212019-03-07 21:15:40 -0800321}
322
323TEST_F(OutputTest, setColorTransformPerformsUpdateToIdentity) {
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700324 mOutput->editState().colorTransformMatrix = kNonIdentityHalf;
Lloyd Pique3eb1b212019-03-07 21:15:40 -0800325
326 // Setting a different colorTransformMatrix should perform the update.
327 CompositionRefreshArgs refreshArgs;
328 refreshArgs.colorTransformMatrix = kIdentity;
329
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700330 mOutput->setColorTransform(refreshArgs);
Lloyd Pique3eb1b212019-03-07 21:15:40 -0800331
332 // The internal state should have been updated
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700333 EXPECT_EQ(kIdentity, mOutput->getState().colorTransformMatrix);
Lloyd Pique3eb1b212019-03-07 21:15:40 -0800334
335 // The dirtyRegion should be set to the full display size
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700336 EXPECT_THAT(mOutput->getState().dirtyRegion, RegionEq(Region(kDefaultDisplaySize)));
Lloyd Pique3eb1b212019-03-07 21:15:40 -0800337}
Lloyd Pique77f79a22019-04-29 15:55:40 -0700338
Lloyd Pique3eb1b212019-03-07 21:15:40 -0800339TEST_F(OutputTest, setColorTransformPerformsUpdateForIdentityToHalf) {
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700340 mOutput->editState().colorTransformMatrix = kIdentity;
Lloyd Pique77f79a22019-04-29 15:55:40 -0700341
Lloyd Pique3eb1b212019-03-07 21:15:40 -0800342 // Setting a different colorTransformMatrix should perform the update.
343 CompositionRefreshArgs refreshArgs;
344 refreshArgs.colorTransformMatrix = kNonIdentityHalf;
Lloyd Pique77f79a22019-04-29 15:55:40 -0700345
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700346 mOutput->setColorTransform(refreshArgs);
Lloyd Piqueef958122019-02-05 18:00:12 -0800347
Lloyd Pique3eb1b212019-03-07 21:15:40 -0800348 // The internal state should have been updated
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700349 EXPECT_EQ(kNonIdentityHalf, mOutput->getState().colorTransformMatrix);
Lloyd Pique3eb1b212019-03-07 21:15:40 -0800350
351 // The dirtyRegion should be set to the full display size
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700352 EXPECT_THAT(mOutput->getState().dirtyRegion, RegionEq(Region(kDefaultDisplaySize)));
Lloyd Pique3eb1b212019-03-07 21:15:40 -0800353}
354
355TEST_F(OutputTest, setColorTransformPerformsUpdateForHalfToQuarter) {
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700356 mOutput->editState().colorTransformMatrix = kNonIdentityHalf;
Lloyd Pique3eb1b212019-03-07 21:15:40 -0800357
358 // Setting a different colorTransformMatrix should perform the update.
359 CompositionRefreshArgs refreshArgs;
360 refreshArgs.colorTransformMatrix = kNonIdentityQuarter;
361
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700362 mOutput->setColorTransform(refreshArgs);
Lloyd Pique3eb1b212019-03-07 21:15:40 -0800363
364 // The internal state should have been updated
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700365 EXPECT_EQ(kNonIdentityQuarter, mOutput->getState().colorTransformMatrix);
Lloyd Pique3eb1b212019-03-07 21:15:40 -0800366
367 // The dirtyRegion should be set to the full display size
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700368 EXPECT_THAT(mOutput->getState().dirtyRegion, RegionEq(Region(kDefaultDisplaySize)));
Lloyd Pique32cbe282018-10-19 13:09:22 -0700369}
370
Lloyd Pique66d68602019-02-13 14:23:31 -0800371/*
Lloyd Pique17ca7422019-11-14 14:24:10 -0800372 * Output::setColorProfile
Lloyd Pique32cbe282018-10-19 13:09:22 -0700373 */
374
Lloyd Pique17ca7422019-11-14 14:24:10 -0800375using OutputSetColorProfileTest = OutputTest;
376
377TEST_F(OutputSetColorProfileTest, setsStateAndDirtiesOutputIfChanged) {
Lloyd Pique6a3b4462019-03-07 20:58:12 -0800378 using ColorProfile = Output::ColorProfile;
379
Lloyd Piquef5275482019-01-29 18:42:42 -0800380 EXPECT_CALL(*mDisplayColorProfile,
381 getTargetDataspace(ui::ColorMode::DISPLAY_P3, ui::Dataspace::DISPLAY_P3,
382 ui::Dataspace::UNKNOWN))
383 .WillOnce(Return(ui::Dataspace::UNKNOWN));
Lloyd Piqueef958122019-02-05 18:00:12 -0800384 EXPECT_CALL(*mRenderSurface, setBufferDataspace(ui::Dataspace::DISPLAY_P3)).Times(1);
Lloyd Pique31cb2942018-10-19 17:23:03 -0700385
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700386 mOutput->setColorProfile(ColorProfile{ui::ColorMode::DISPLAY_P3, ui::Dataspace::DISPLAY_P3,
387 ui::RenderIntent::TONE_MAP_COLORIMETRIC,
388 ui::Dataspace::UNKNOWN});
Lloyd Pique32cbe282018-10-19 13:09:22 -0700389
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700390 EXPECT_EQ(ui::ColorMode::DISPLAY_P3, mOutput->getState().colorMode);
391 EXPECT_EQ(ui::Dataspace::DISPLAY_P3, mOutput->getState().dataspace);
392 EXPECT_EQ(ui::RenderIntent::TONE_MAP_COLORIMETRIC, mOutput->getState().renderIntent);
393 EXPECT_EQ(ui::Dataspace::UNKNOWN, mOutput->getState().targetDataspace);
Lloyd Piquef5275482019-01-29 18:42:42 -0800394
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700395 EXPECT_THAT(mOutput->getState().dirtyRegion, RegionEq(Region(kDefaultDisplaySize)));
Lloyd Piqueef958122019-02-05 18:00:12 -0800396}
397
Lloyd Pique17ca7422019-11-14 14:24:10 -0800398TEST_F(OutputSetColorProfileTest, doesNothingIfNoChange) {
Lloyd Pique6a3b4462019-03-07 20:58:12 -0800399 using ColorProfile = Output::ColorProfile;
400
Lloyd Piquef5275482019-01-29 18:42:42 -0800401 EXPECT_CALL(*mDisplayColorProfile,
402 getTargetDataspace(ui::ColorMode::DISPLAY_P3, ui::Dataspace::DISPLAY_P3,
403 ui::Dataspace::UNKNOWN))
404 .WillOnce(Return(ui::Dataspace::UNKNOWN));
405
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700406 mOutput->editState().colorMode = ui::ColorMode::DISPLAY_P3;
407 mOutput->editState().dataspace = ui::Dataspace::DISPLAY_P3;
408 mOutput->editState().renderIntent = ui::RenderIntent::TONE_MAP_COLORIMETRIC;
409 mOutput->editState().targetDataspace = ui::Dataspace::UNKNOWN;
Lloyd Piqueef958122019-02-05 18:00:12 -0800410
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700411 mOutput->setColorProfile(ColorProfile{ui::ColorMode::DISPLAY_P3, ui::Dataspace::DISPLAY_P3,
412 ui::RenderIntent::TONE_MAP_COLORIMETRIC,
413 ui::Dataspace::UNKNOWN});
Lloyd Piqueef958122019-02-05 18:00:12 -0800414
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700415 EXPECT_THAT(mOutput->getState().dirtyRegion, RegionEq(Region()));
Lloyd Pique32cbe282018-10-19 13:09:22 -0700416}
417
Lloyd Pique66d68602019-02-13 14:23:31 -0800418/*
Lloyd Pique31cb2942018-10-19 17:23:03 -0700419 * Output::setRenderSurface()
420 */
421
422TEST_F(OutputTest, setRenderSurfaceResetsBounds) {
423 const ui::Size newDisplaySize{640, 480};
424
425 mock::RenderSurface* renderSurface = new StrictMock<mock::RenderSurface>();
426 EXPECT_CALL(*renderSurface, getSize()).WillOnce(ReturnRef(newDisplaySize));
427
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700428 mOutput->setRenderSurface(std::unique_ptr<RenderSurface>(renderSurface));
Lloyd Pique31cb2942018-10-19 17:23:03 -0700429
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700430 EXPECT_EQ(Rect(newDisplaySize), mOutput->getState().bounds);
Lloyd Pique31cb2942018-10-19 17:23:03 -0700431}
432
Lloyd Pique66d68602019-02-13 14:23:31 -0800433/*
Alec Mourie7d1d4a2019-02-05 01:13:46 +0000434 * Output::getDirtyRegion()
Lloyd Pique32cbe282018-10-19 13:09:22 -0700435 */
436
Alec Mourie7d1d4a2019-02-05 01:13:46 +0000437TEST_F(OutputTest, getDirtyRegionWithRepaintEverythingTrue) {
438 const Rect viewport{100, 200};
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700439 mOutput->editState().viewport = viewport;
440 mOutput->editState().dirtyRegion.set(50, 300);
Lloyd Pique32cbe282018-10-19 13:09:22 -0700441
442 {
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700443 Region result = mOutput->getDirtyRegion(true);
Lloyd Pique32cbe282018-10-19 13:09:22 -0700444
Alec Mourie7d1d4a2019-02-05 01:13:46 +0000445 EXPECT_THAT(result, RegionEq(Region(viewport)));
Lloyd Pique32cbe282018-10-19 13:09:22 -0700446 }
447}
448
Alec Mourie7d1d4a2019-02-05 01:13:46 +0000449TEST_F(OutputTest, getDirtyRegionWithRepaintEverythingFalse) {
450 const Rect viewport{100, 200};
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700451 mOutput->editState().viewport = viewport;
452 mOutput->editState().dirtyRegion.set(50, 300);
Lloyd Pique32cbe282018-10-19 13:09:22 -0700453
454 {
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700455 Region result = mOutput->getDirtyRegion(false);
Lloyd Pique32cbe282018-10-19 13:09:22 -0700456
457 // The dirtyRegion should be clipped to the display bounds.
458 EXPECT_THAT(result, RegionEq(Region(Rect(50, 200))));
459 }
Lloyd Pique32cbe282018-10-19 13:09:22 -0700460}
461
Lloyd Pique66d68602019-02-13 14:23:31 -0800462/*
Lloyd Piqueef36b002019-01-23 17:52:04 -0800463 * Output::belongsInOutput()
464 */
465
466TEST_F(OutputTest, belongsInOutputFiltersAsExpected) {
467 const uint32_t layerStack1 = 123u;
468 const uint32_t layerStack2 = 456u;
469
470 // If the output accepts layerStack1 and internal-only layers....
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700471 mOutput->setLayerStackFilter(layerStack1, true);
Lloyd Piqueef36b002019-01-23 17:52:04 -0800472
Lloyd Piquec6687342019-03-07 21:34:57 -0800473 // A layer with no layerStack does not belong to it, internal-only or not.
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700474 EXPECT_FALSE(mOutput->belongsInOutput(std::nullopt, false));
475 EXPECT_FALSE(mOutput->belongsInOutput(std::nullopt, true));
Lloyd Piquec6687342019-03-07 21:34:57 -0800476
Lloyd Piqueef36b002019-01-23 17:52:04 -0800477 // Any layer with layerStack1 belongs to it, internal-only or not.
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700478 EXPECT_TRUE(mOutput->belongsInOutput(layerStack1, false));
479 EXPECT_TRUE(mOutput->belongsInOutput(layerStack1, true));
480 EXPECT_FALSE(mOutput->belongsInOutput(layerStack2, true));
481 EXPECT_FALSE(mOutput->belongsInOutput(layerStack2, false));
Lloyd Piqueef36b002019-01-23 17:52:04 -0800482
483 // If the output accepts layerStack21 but not internal-only layers...
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700484 mOutput->setLayerStackFilter(layerStack1, false);
Lloyd Piqueef36b002019-01-23 17:52:04 -0800485
486 // Only non-internal layers with layerStack1 belong to it.
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700487 EXPECT_TRUE(mOutput->belongsInOutput(layerStack1, false));
488 EXPECT_FALSE(mOutput->belongsInOutput(layerStack1, true));
489 EXPECT_FALSE(mOutput->belongsInOutput(layerStack2, true));
490 EXPECT_FALSE(mOutput->belongsInOutput(layerStack2, false));
Lloyd Piqueef36b002019-01-23 17:52:04 -0800491}
492
Lloyd Pique66c20c42019-03-07 21:44:02 -0800493TEST_F(OutputTest, belongsInOutputFiltersLayersAsExpected) {
494 StrictMock<mock::Layer> layer;
Lloyd Pique9755fb72019-03-26 14:44:40 -0700495 LayerFECompositionState layerFEState;
Lloyd Pique66c20c42019-03-07 21:44:02 -0800496
Lloyd Pique9755fb72019-03-26 14:44:40 -0700497 EXPECT_CALL(layer, getFEState()).WillRepeatedly(ReturnRef(layerFEState));
Lloyd Pique66c20c42019-03-07 21:44:02 -0800498
499 const uint32_t layerStack1 = 123u;
500 const uint32_t layerStack2 = 456u;
501
502 // If the output accepts layerStack1 and internal-only layers....
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700503 mOutput->setLayerStackFilter(layerStack1, true);
Lloyd Pique66c20c42019-03-07 21:44:02 -0800504
505 // A null layer pointer does not belong to the output
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700506 EXPECT_FALSE(mOutput->belongsInOutput(nullptr));
Lloyd Pique66c20c42019-03-07 21:44:02 -0800507
508 // A layer with no layerStack does not belong to it, internal-only or not.
Lloyd Pique9755fb72019-03-26 14:44:40 -0700509 layerFEState.layerStackId = std::nullopt;
510 layerFEState.internalOnly = false;
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700511 EXPECT_FALSE(mOutput->belongsInOutput(&layer));
Lloyd Pique66c20c42019-03-07 21:44:02 -0800512
Lloyd Pique9755fb72019-03-26 14:44:40 -0700513 layerFEState.layerStackId = std::nullopt;
514 layerFEState.internalOnly = true;
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700515 EXPECT_FALSE(mOutput->belongsInOutput(&layer));
Lloyd Pique66c20c42019-03-07 21:44:02 -0800516
517 // Any layer with layerStack1 belongs to it, internal-only or not.
Lloyd Pique9755fb72019-03-26 14:44:40 -0700518 layerFEState.layerStackId = layerStack1;
519 layerFEState.internalOnly = false;
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700520 EXPECT_TRUE(mOutput->belongsInOutput(&layer));
Lloyd Pique66c20c42019-03-07 21:44:02 -0800521
Lloyd Pique9755fb72019-03-26 14:44:40 -0700522 layerFEState.layerStackId = layerStack1;
523 layerFEState.internalOnly = true;
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700524 EXPECT_TRUE(mOutput->belongsInOutput(&layer));
Lloyd Pique66c20c42019-03-07 21:44:02 -0800525
Lloyd Pique9755fb72019-03-26 14:44:40 -0700526 layerFEState.layerStackId = layerStack2;
527 layerFEState.internalOnly = true;
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700528 EXPECT_FALSE(mOutput->belongsInOutput(&layer));
Lloyd Pique66c20c42019-03-07 21:44:02 -0800529
Lloyd Pique9755fb72019-03-26 14:44:40 -0700530 layerFEState.layerStackId = layerStack2;
531 layerFEState.internalOnly = false;
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700532 EXPECT_FALSE(mOutput->belongsInOutput(&layer));
Lloyd Pique66c20c42019-03-07 21:44:02 -0800533
534 // If the output accepts layerStack1 but not internal-only layers...
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700535 mOutput->setLayerStackFilter(layerStack1, false);
Lloyd Pique66c20c42019-03-07 21:44:02 -0800536
537 // A null layer pointer does not belong to the output
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700538 EXPECT_FALSE(mOutput->belongsInOutput(nullptr));
Lloyd Pique66c20c42019-03-07 21:44:02 -0800539
540 // Only non-internal layers with layerStack1 belong to it.
Lloyd Pique9755fb72019-03-26 14:44:40 -0700541 layerFEState.layerStackId = layerStack1;
542 layerFEState.internalOnly = false;
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700543 EXPECT_TRUE(mOutput->belongsInOutput(&layer));
Lloyd Pique66c20c42019-03-07 21:44:02 -0800544
Lloyd Pique9755fb72019-03-26 14:44:40 -0700545 layerFEState.layerStackId = layerStack1;
546 layerFEState.internalOnly = true;
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700547 EXPECT_FALSE(mOutput->belongsInOutput(&layer));
Lloyd Pique66c20c42019-03-07 21:44:02 -0800548
Lloyd Pique9755fb72019-03-26 14:44:40 -0700549 layerFEState.layerStackId = layerStack2;
550 layerFEState.internalOnly = true;
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700551 EXPECT_FALSE(mOutput->belongsInOutput(&layer));
Lloyd Pique66c20c42019-03-07 21:44:02 -0800552
Lloyd Pique9755fb72019-03-26 14:44:40 -0700553 layerFEState.layerStackId = layerStack2;
554 layerFEState.internalOnly = false;
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700555 EXPECT_FALSE(mOutput->belongsInOutput(&layer));
Lloyd Pique66c20c42019-03-07 21:44:02 -0800556}
557
Lloyd Pique66d68602019-02-13 14:23:31 -0800558/*
Lloyd Piquecc01a452018-12-04 17:24:00 -0800559 * Output::getOutputLayerForLayer()
560 */
561
562TEST_F(OutputTest, getOutputLayerForLayerWorks) {
563 mock::OutputLayer* outputLayer1 = new StrictMock<mock::OutputLayer>();
564 mock::OutputLayer* outputLayer2 = new StrictMock<mock::OutputLayer>();
565
Lloyd Pique01c77c12019-04-17 12:48:32 -0700566 mOutput->injectOutputLayerForTest(std::unique_ptr<OutputLayer>(outputLayer1));
567 mOutput->injectOutputLayerForTest(nullptr);
568 mOutput->injectOutputLayerForTest(std::unique_ptr<OutputLayer>(outputLayer2));
Lloyd Piquecc01a452018-12-04 17:24:00 -0800569
570 StrictMock<mock::Layer> layer;
571 StrictMock<mock::Layer> otherLayer;
572
573 // If the input layer matches the first OutputLayer, it will be returned.
574 EXPECT_CALL(*outputLayer1, getLayer()).WillOnce(ReturnRef(layer));
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700575 EXPECT_EQ(outputLayer1, mOutput->getOutputLayerForLayer(&layer));
Lloyd Piquecc01a452018-12-04 17:24:00 -0800576
577 // If the input layer matches the second OutputLayer, it will be returned.
578 EXPECT_CALL(*outputLayer1, getLayer()).WillOnce(ReturnRef(otherLayer));
579 EXPECT_CALL(*outputLayer2, getLayer()).WillOnce(ReturnRef(layer));
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700580 EXPECT_EQ(outputLayer2, mOutput->getOutputLayerForLayer(&layer));
Lloyd Piquecc01a452018-12-04 17:24:00 -0800581
582 // If the input layer does not match an output layer, null will be returned.
583 EXPECT_CALL(*outputLayer1, getLayer()).WillOnce(ReturnRef(otherLayer));
584 EXPECT_CALL(*outputLayer2, getLayer()).WillOnce(ReturnRef(otherLayer));
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700585 EXPECT_EQ(nullptr, mOutput->getOutputLayerForLayer(&layer));
Lloyd Piquecc01a452018-12-04 17:24:00 -0800586}
587
Lloyd Pique66d68602019-02-13 14:23:31 -0800588/*
Lloyd Piquec9e60032019-11-14 11:47:26 -0800589 * Output::setReleasedLayers()
590 */
591
592using OutputSetReleasedLayersTest = OutputTest;
593
594TEST_F(OutputSetReleasedLayersTest, setReleasedLayersTakesGivenLayers) {
595 sp<StrictMock<mock::LayerFE>> layer1FE{new StrictMock<mock::LayerFE>()};
596 sp<StrictMock<mock::LayerFE>> layer2FE{new StrictMock<mock::LayerFE>()};
597 sp<StrictMock<mock::LayerFE>> layer3FE{new StrictMock<mock::LayerFE>()};
598
599 Output::ReleasedLayers layers;
600 layers.push_back(layer1FE);
601 layers.push_back(layer2FE);
602 layers.push_back(layer3FE);
603
604 mOutput->setReleasedLayers(std::move(layers));
605
606 const auto& setLayers = mOutput->getReleasedLayersForTest();
607 ASSERT_EQ(3u, setLayers.size());
608 ASSERT_EQ(layer1FE.get(), setLayers[0].promote().get());
609 ASSERT_EQ(layer2FE.get(), setLayers[1].promote().get());
610 ASSERT_EQ(layer3FE.get(), setLayers[2].promote().get());
611}
612
613/*
Lloyd Piquec0ee6ba2019-11-14 12:55:53 -0800614 * Output::updateLayerStateFromFE()
615 */
616
617using OutputUpdateLayerStateFromFETest = OutputLatchFEStateTest;
618
619TEST_F(OutputUpdateLayerStateFromFETest, handlesNoOutputLayerCase) {
620 CompositionRefreshArgs refreshArgs;
621
622 mOutput->updateLayerStateFromFE(refreshArgs);
623}
624
625TEST_F(OutputUpdateLayerStateFromFETest, latchesContentStateForAllContainedLayers) {
626 EXPECT_CALL(mLayer1FE,
627 latchCompositionState(Ref(mLayer1FEState), LayerFE::StateSubset::Content));
628 EXPECT_CALL(mLayer2FE,
629 latchCompositionState(Ref(mLayer2FEState), LayerFE::StateSubset::Content));
630 EXPECT_CALL(mLayer3FE,
631 latchCompositionState(Ref(mLayer3FEState), LayerFE::StateSubset::Content));
632
633 // Note: Must be performed after any expectations on these mocks
634 injectLayer(std::move(mOutputLayer1));
635 injectLayer(std::move(mOutputLayer2));
636 injectLayer(std::move(mOutputLayer3));
637
638 CompositionRefreshArgs refreshArgs;
639 refreshArgs.updatingGeometryThisFrame = false;
640
641 mOutput->updateLayerStateFromFE(refreshArgs);
642}
643
644TEST_F(OutputUpdateLayerStateFromFETest, latchesGeometryAndContentStateForAllContainedLayers) {
645 EXPECT_CALL(mLayer1FE,
646 latchCompositionState(Ref(mLayer1FEState),
647 LayerFE::StateSubset::GeometryAndContent));
648 EXPECT_CALL(mLayer2FE,
649 latchCompositionState(Ref(mLayer2FEState),
650 LayerFE::StateSubset::GeometryAndContent));
651 EXPECT_CALL(mLayer3FE,
652 latchCompositionState(Ref(mLayer3FEState),
653 LayerFE::StateSubset::GeometryAndContent));
654
655 // Note: Must be performed after any expectations on these mocks
656 injectLayer(std::move(mOutputLayer1));
657 injectLayer(std::move(mOutputLayer2));
658 injectLayer(std::move(mOutputLayer3));
659
660 CompositionRefreshArgs refreshArgs;
661 refreshArgs.updatingGeometryThisFrame = true;
662
663 mOutput->updateLayerStateFromFE(refreshArgs);
664}
665
666/*
Alec Mourif9a2a2c2019-11-12 12:46:02 -0800667 * Output::updateAndWriteCompositionState()
668 */
669
Lloyd Piqueef63b612019-11-14 13:19:56 -0800670using OutputUpdateAndWriteCompositionStateTest = OutputLatchFEStateTest;
671
672TEST_F(OutputUpdateAndWriteCompositionStateTest, doesNothingIfLayers) {
673 mOutput->editState().isEnabled = true;
Alec Mourif9a2a2c2019-11-12 12:46:02 -0800674
675 CompositionRefreshArgs args;
676 mOutput->updateAndWriteCompositionState(args);
677}
678
Lloyd Piqueef63b612019-11-14 13:19:56 -0800679TEST_F(OutputUpdateAndWriteCompositionStateTest, doesNothingIfOutputNotEnabled) {
680 mOutput->editState().isEnabled = false;
Alec Mourif9a2a2c2019-11-12 12:46:02 -0800681
Lloyd Piqueef63b612019-11-14 13:19:56 -0800682 injectLayer(std::move(mOutputLayer1));
683 injectLayer(std::move(mOutputLayer2));
684 injectLayer(std::move(mOutputLayer3));
685
686 CompositionRefreshArgs args;
687 mOutput->updateAndWriteCompositionState(args);
688}
689
690TEST_F(OutputUpdateAndWriteCompositionStateTest, updatesLayerContentForAllLayers) {
691 EXPECT_CALL(*mOutputLayer1, updateCompositionState(false, false));
692 EXPECT_CALL(*mOutputLayer1, writeStateToHWC(false));
693 EXPECT_CALL(*mOutputLayer2, updateCompositionState(false, false));
694 EXPECT_CALL(*mOutputLayer2, writeStateToHWC(false));
695 EXPECT_CALL(*mOutputLayer3, updateCompositionState(false, false));
696 EXPECT_CALL(*mOutputLayer3, writeStateToHWC(false));
697
698 injectLayer(std::move(mOutputLayer1));
699 injectLayer(std::move(mOutputLayer2));
700 injectLayer(std::move(mOutputLayer3));
701
702 mOutput->editState().isEnabled = true;
703
704 CompositionRefreshArgs args;
705 args.updatingGeometryThisFrame = false;
706 args.devOptForceClientComposition = false;
707 mOutput->updateAndWriteCompositionState(args);
708}
709
710TEST_F(OutputUpdateAndWriteCompositionStateTest, updatesLayerGeometryAndContentForAllLayers) {
711 EXPECT_CALL(*mOutputLayer1, updateCompositionState(true, false));
712 EXPECT_CALL(*mOutputLayer1, writeStateToHWC(true));
713 EXPECT_CALL(*mOutputLayer2, updateCompositionState(true, false));
714 EXPECT_CALL(*mOutputLayer2, writeStateToHWC(true));
715 EXPECT_CALL(*mOutputLayer3, updateCompositionState(true, false));
716 EXPECT_CALL(*mOutputLayer3, writeStateToHWC(true));
717
718 injectLayer(std::move(mOutputLayer1));
719 injectLayer(std::move(mOutputLayer2));
720 injectLayer(std::move(mOutputLayer3));
721
722 mOutput->editState().isEnabled = true;
Alec Mourif9a2a2c2019-11-12 12:46:02 -0800723
724 CompositionRefreshArgs args;
725 args.updatingGeometryThisFrame = true;
Lloyd Piqueef63b612019-11-14 13:19:56 -0800726 args.devOptForceClientComposition = false;
727 mOutput->updateAndWriteCompositionState(args);
728}
729
730TEST_F(OutputUpdateAndWriteCompositionStateTest, forcesClientCompositionForAllLayers) {
731 EXPECT_CALL(*mOutputLayer1, updateCompositionState(false, true));
732 EXPECT_CALL(*mOutputLayer1, writeStateToHWC(false));
733 EXPECT_CALL(*mOutputLayer2, updateCompositionState(false, true));
734 EXPECT_CALL(*mOutputLayer2, writeStateToHWC(false));
735 EXPECT_CALL(*mOutputLayer3, updateCompositionState(false, true));
736 EXPECT_CALL(*mOutputLayer3, writeStateToHWC(false));
737
738 injectLayer(std::move(mOutputLayer1));
739 injectLayer(std::move(mOutputLayer2));
740 injectLayer(std::move(mOutputLayer3));
741
742 mOutput->editState().isEnabled = true;
743
744 CompositionRefreshArgs args;
745 args.updatingGeometryThisFrame = false;
Alec Mourif9a2a2c2019-11-12 12:46:02 -0800746 args.devOptForceClientComposition = true;
747 mOutput->updateAndWriteCompositionState(args);
748}
749
750/*
Lloyd Pique66d68602019-02-13 14:23:31 -0800751 * Output::prepareFrame()
752 */
753
754struct OutputPrepareFrameTest : public testing::Test {
Lloyd Piquefaa3f192019-11-14 14:05:09 -0800755 struct OutputPartialMock : public OutputPartialMockBase {
Lloyd Pique66d68602019-02-13 14:23:31 -0800756 // Sets up the helper functions called by prepareFrame to use a mock
757 // implementations.
758 MOCK_METHOD0(chooseCompositionStrategy, void());
759 };
760
761 OutputPrepareFrameTest() {
762 mOutput.setDisplayColorProfileForTest(
763 std::unique_ptr<DisplayColorProfile>(mDisplayColorProfile));
764 mOutput.setRenderSurfaceForTest(std::unique_ptr<RenderSurface>(mRenderSurface));
765 }
766
767 StrictMock<mock::CompositionEngine> mCompositionEngine;
768 mock::DisplayColorProfile* mDisplayColorProfile = new StrictMock<mock::DisplayColorProfile>();
769 mock::RenderSurface* mRenderSurface = new StrictMock<mock::RenderSurface>();
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700770 StrictMock<OutputPartialMock> mOutput;
Lloyd Pique66d68602019-02-13 14:23:31 -0800771};
772
773TEST_F(OutputPrepareFrameTest, takesEarlyOutIfNotEnabled) {
774 mOutput.editState().isEnabled = false;
775
776 mOutput.prepareFrame();
777}
778
779TEST_F(OutputPrepareFrameTest, delegatesToChooseCompositionStrategyAndRenderSurface) {
780 mOutput.editState().isEnabled = true;
781 mOutput.editState().usesClientComposition = false;
782 mOutput.editState().usesDeviceComposition = true;
783
784 EXPECT_CALL(mOutput, chooseCompositionStrategy()).Times(1);
785 EXPECT_CALL(*mRenderSurface, prepareFrame(false, true));
786
787 mOutput.prepareFrame();
788}
789
790// Note: Use OutputTest and not OutputPrepareFrameTest, so the real
791// base chooseCompositionStrategy() is invoked.
792TEST_F(OutputTest, prepareFrameSetsClientCompositionOnlyByDefault) {
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700793 mOutput->editState().isEnabled = true;
794 mOutput->editState().usesClientComposition = false;
795 mOutput->editState().usesDeviceComposition = true;
Lloyd Pique66d68602019-02-13 14:23:31 -0800796
797 EXPECT_CALL(*mRenderSurface, prepareFrame(true, false));
798
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700799 mOutput->prepareFrame();
Lloyd Pique66d68602019-02-13 14:23:31 -0800800
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700801 EXPECT_TRUE(mOutput->getState().usesClientComposition);
802 EXPECT_FALSE(mOutput->getState().usesDeviceComposition);
Lloyd Pique66d68602019-02-13 14:23:31 -0800803}
804
Lloyd Pique56eba802019-08-28 15:45:25 -0700805/*
Lloyd Piquefaa3f192019-11-14 14:05:09 -0800806 * Output::present()
807 */
808
809struct OutputPresentTest : public testing::Test {
810 struct OutputPartialMock : public OutputPartialMockBase {
811 // All child helper functions Output::present() are defined as mocks,
812 // and those are tested separately, allowing the present() test to
813 // just cover the high level flow.
814 MOCK_METHOD1(updateColorProfile, void(const compositionengine::CompositionRefreshArgs&));
815 MOCK_METHOD1(updateAndWriteCompositionState,
816 void(const compositionengine::CompositionRefreshArgs&));
817 MOCK_METHOD1(setColorTransform, void(const compositionengine::CompositionRefreshArgs&));
818 MOCK_METHOD0(beginFrame, void());
819 MOCK_METHOD0(prepareFrame, void());
820 MOCK_METHOD1(devOptRepaintFlash, void(const compositionengine::CompositionRefreshArgs&));
821 MOCK_METHOD1(finishFrame, void(const compositionengine::CompositionRefreshArgs&));
822 MOCK_METHOD0(postFramebuffer, void());
823 };
824
825 StrictMock<OutputPartialMock> mOutput;
826};
827
828TEST_F(OutputPresentTest, justInvokesChildFunctionsInSequence) {
829 CompositionRefreshArgs args;
830
831 InSequence seq;
832 EXPECT_CALL(mOutput, updateColorProfile(Ref(args)));
833 EXPECT_CALL(mOutput, updateAndWriteCompositionState(Ref(args)));
834 EXPECT_CALL(mOutput, setColorTransform(Ref(args)));
835 EXPECT_CALL(mOutput, beginFrame());
836 EXPECT_CALL(mOutput, prepareFrame());
837 EXPECT_CALL(mOutput, devOptRepaintFlash(Ref(args)));
838 EXPECT_CALL(mOutput, finishFrame(Ref(args)));
839 EXPECT_CALL(mOutput, postFramebuffer());
840
841 mOutput.present(args);
842}
843
844/*
845 * Output::updateColorProfile()
846 */
847
Lloyd Pique17ca7422019-11-14 14:24:10 -0800848struct OutputUpdateColorProfileTest : public testing::Test {
849 using TestType = OutputUpdateColorProfileTest;
850
851 struct OutputPartialMock : public OutputPartialMockBase {
852 // All child helper functions Output::present() are defined as mocks,
853 // and those are tested separately, allowing the present() test to
854 // just cover the high level flow.
855 MOCK_METHOD1(setColorProfile, void(const ColorProfile&));
856 };
857
858 struct Layer {
859 Layer() {
860 EXPECT_CALL(mOutputLayer, getLayer()).WillRepeatedly(ReturnRef(mLayer));
861 EXPECT_CALL(mOutputLayer, getLayerFE()).WillRepeatedly(ReturnRef(mLayerFE));
862 EXPECT_CALL(mLayer, getFEState()).WillRepeatedly(ReturnRef(mLayerFEState));
863 }
864
865 StrictMock<mock::OutputLayer> mOutputLayer;
866 StrictMock<mock::Layer> mLayer;
867 StrictMock<mock::LayerFE> mLayerFE;
868 LayerFECompositionState mLayerFEState;
869 };
870
871 OutputUpdateColorProfileTest() {
872 mOutput.setDisplayColorProfileForTest(
873 std::unique_ptr<DisplayColorProfile>(mDisplayColorProfile));
874 mOutput.setRenderSurfaceForTest(std::unique_ptr<RenderSurface>(mRenderSurface));
875
876 EXPECT_CALL(mOutput, getOutputLayerOrderedByZByIndex(0))
877 .WillRepeatedly(Return(&mLayer1.mOutputLayer));
878 EXPECT_CALL(mOutput, getOutputLayerOrderedByZByIndex(1))
879 .WillRepeatedly(Return(&mLayer2.mOutputLayer));
880 EXPECT_CALL(mOutput, getOutputLayerOrderedByZByIndex(2))
881 .WillRepeatedly(Return(&mLayer3.mOutputLayer));
882 }
883
884 struct ExecuteState : public CallOrderStateMachineHelper<TestType, ExecuteState> {
885 void execute() { getInstance()->mOutput.updateColorProfile(getInstance()->mRefreshArgs); }
886 };
887
888 mock::DisplayColorProfile* mDisplayColorProfile = new StrictMock<mock::DisplayColorProfile>();
889 mock::RenderSurface* mRenderSurface = new StrictMock<mock::RenderSurface>();
890 StrictMock<OutputPartialMock> mOutput;
891
892 Layer mLayer1;
893 Layer mLayer2;
894 Layer mLayer3;
895
896 CompositionRefreshArgs mRefreshArgs;
897};
898
899// TODO(b/144522012): Refactor Output::updateColorProfile and the related code
900// to make it easier to write unit tests.
901
902TEST_F(OutputUpdateColorProfileTest, setsAColorProfileWhenUnmanaged) {
903 // When the outputColorSetting is set to kUnmanaged, the implementation sets
904 // a simple default color profile without looking at anything else.
905
906 EXPECT_CALL(mOutput, getOutputLayerCount()).WillRepeatedly(Return(3));
907 EXPECT_CALL(mOutput,
908 setColorProfile(ColorProfileEq(
909 ColorProfile{ui::ColorMode::NATIVE, ui::Dataspace::UNKNOWN,
910 ui::RenderIntent::COLORIMETRIC, ui::Dataspace::UNKNOWN})));
911
912 mRefreshArgs.outputColorSetting = OutputColorSetting::kUnmanaged;
913 mRefreshArgs.colorSpaceAgnosticDataspace = ui::Dataspace::UNKNOWN;
914
915 mOutput.updateColorProfile(mRefreshArgs);
916}
917
918struct OutputUpdateColorProfileTest_GetBestColorModeResultBecomesSetProfile
919 : public OutputUpdateColorProfileTest {
920 OutputUpdateColorProfileTest_GetBestColorModeResultBecomesSetProfile() {
921 EXPECT_CALL(mOutput, getOutputLayerCount()).WillRepeatedly(Return(0));
922 mRefreshArgs.outputColorSetting = OutputColorSetting::kEnhanced;
923 mRefreshArgs.colorSpaceAgnosticDataspace = ui::Dataspace::UNKNOWN;
924 }
925
926 struct ExpectBestColorModeCallResultUsedToSetColorProfileState
927 : public CallOrderStateMachineHelper<
928 TestType, ExpectBestColorModeCallResultUsedToSetColorProfileState> {
929 [[nodiscard]] auto expectBestColorModeCallResultUsedToSetColorProfile(
930 ui::ColorMode colorMode, ui::Dataspace dataspace, ui::RenderIntent renderIntent) {
931 EXPECT_CALL(*getInstance()->mDisplayColorProfile,
932 getBestColorMode(ui::Dataspace::V0_SRGB, ui::RenderIntent::ENHANCE, _, _,
933 _))
934 .WillOnce(DoAll(SetArgPointee<2>(dataspace), SetArgPointee<3>(colorMode),
935 SetArgPointee<4>(renderIntent)));
936 EXPECT_CALL(getInstance()->mOutput,
937 setColorProfile(
938 ColorProfileEq(ColorProfile{colorMode, dataspace, renderIntent,
939 ui::Dataspace::UNKNOWN})));
940 return nextState<ExecuteState>();
941 }
942 };
943
944 // Call this member function to start using the mini-DSL defined above.
945 [[nodiscard]] auto verify() {
946 return ExpectBestColorModeCallResultUsedToSetColorProfileState::make(this);
947 }
948};
949
950TEST_F(OutputUpdateColorProfileTest_GetBestColorModeResultBecomesSetProfile,
951 Native_Unknown_Colorimetric_Set) {
952 verify().expectBestColorModeCallResultUsedToSetColorProfile(ui::ColorMode::NATIVE,
953 ui::Dataspace::UNKNOWN,
954 ui::RenderIntent::COLORIMETRIC)
955 .execute();
956}
957
958TEST_F(OutputUpdateColorProfileTest_GetBestColorModeResultBecomesSetProfile,
959 DisplayP3_DisplayP3_Enhance_Set) {
960 verify().expectBestColorModeCallResultUsedToSetColorProfile(ui::ColorMode::DISPLAY_P3,
961 ui::Dataspace::DISPLAY_P3,
962 ui::RenderIntent::ENHANCE)
963 .execute();
964}
965
966struct OutputUpdateColorProfileTest_ColorSpaceAgnosticeDataspaceAffectsSetColorProfile
967 : public OutputUpdateColorProfileTest {
968 OutputUpdateColorProfileTest_ColorSpaceAgnosticeDataspaceAffectsSetColorProfile() {
969 EXPECT_CALL(mOutput, getOutputLayerCount()).WillRepeatedly(Return(0));
970 EXPECT_CALL(*mDisplayColorProfile,
971 getBestColorMode(ui::Dataspace::V0_SRGB, ui::RenderIntent::ENHANCE, _, _, _))
972 .WillRepeatedly(DoAll(SetArgPointee<2>(ui::Dataspace::UNKNOWN),
973 SetArgPointee<3>(ui::ColorMode::NATIVE),
974 SetArgPointee<4>(ui::RenderIntent::COLORIMETRIC)));
975 mRefreshArgs.outputColorSetting = OutputColorSetting::kEnhanced;
976 }
977
978 struct IfColorSpaceAgnosticDataspaceSetToState
979 : public CallOrderStateMachineHelper<TestType, IfColorSpaceAgnosticDataspaceSetToState> {
980 [[nodiscard]] auto ifColorSpaceAgnosticDataspaceSetTo(ui::Dataspace dataspace) {
981 getInstance()->mRefreshArgs.colorSpaceAgnosticDataspace = dataspace;
982 return nextState<ThenExpectSetColorProfileCallUsesColorSpaceAgnosticDataspaceState>();
983 }
984 };
985
986 struct ThenExpectSetColorProfileCallUsesColorSpaceAgnosticDataspaceState
987 : public CallOrderStateMachineHelper<
988 TestType, ThenExpectSetColorProfileCallUsesColorSpaceAgnosticDataspaceState> {
989 [[nodiscard]] auto thenExpectSetColorProfileCallUsesColorSpaceAgnosticDataspace(
990 ui::Dataspace dataspace) {
991 EXPECT_CALL(getInstance()->mOutput,
992 setColorProfile(ColorProfileEq(
993 ColorProfile{ui::ColorMode::NATIVE, ui::Dataspace::UNKNOWN,
994 ui::RenderIntent::COLORIMETRIC, dataspace})));
995 return nextState<ExecuteState>();
996 }
997 };
998
999 // Call this member function to start using the mini-DSL defined above.
1000 [[nodiscard]] auto verify() { return IfColorSpaceAgnosticDataspaceSetToState::make(this); }
1001};
1002
1003TEST_F(OutputUpdateColorProfileTest_ColorSpaceAgnosticeDataspaceAffectsSetColorProfile, DisplayP3) {
1004 verify().ifColorSpaceAgnosticDataspaceSetTo(ui::Dataspace::DISPLAY_P3)
1005 .thenExpectSetColorProfileCallUsesColorSpaceAgnosticDataspace(ui::Dataspace::DISPLAY_P3)
1006 .execute();
1007}
1008
1009TEST_F(OutputUpdateColorProfileTest_ColorSpaceAgnosticeDataspaceAffectsSetColorProfile, V0_SRGB) {
1010 verify().ifColorSpaceAgnosticDataspaceSetTo(ui::Dataspace::V0_SRGB)
1011 .thenExpectSetColorProfileCallUsesColorSpaceAgnosticDataspace(ui::Dataspace::V0_SRGB)
1012 .execute();
1013}
1014
1015struct OutputUpdateColorProfileTest_TopmostLayerPreferenceSetsOutputPreference
1016 : public OutputUpdateColorProfileTest {
1017 // Internally the implementation looks through the dataspaces of all the
1018 // visible layers. The topmost one that also has an actual dataspace
1019 // preference set is used to drive subsequent choices.
1020
1021 OutputUpdateColorProfileTest_TopmostLayerPreferenceSetsOutputPreference() {
1022 mRefreshArgs.outputColorSetting = OutputColorSetting::kEnhanced;
1023 mRefreshArgs.colorSpaceAgnosticDataspace = ui::Dataspace::UNKNOWN;
1024
1025 EXPECT_CALL(mOutput, getOutputLayerCount()).WillRepeatedly(Return(3));
1026 EXPECT_CALL(mOutput, setColorProfile(_)).WillRepeatedly(Return());
1027 }
1028
1029 struct IfTopLayerDataspaceState
1030 : public CallOrderStateMachineHelper<TestType, IfTopLayerDataspaceState> {
1031 [[nodiscard]] auto ifTopLayerIs(ui::Dataspace dataspace) {
1032 getInstance()->mLayer3.mLayerFEState.dataspace = dataspace;
1033 return nextState<AndIfMiddleLayerDataspaceState>();
1034 }
1035 [[nodiscard]] auto ifTopLayerHasNoPreference() {
1036 return ifTopLayerIs(ui::Dataspace::UNKNOWN);
1037 }
1038 };
1039
1040 struct AndIfMiddleLayerDataspaceState
1041 : public CallOrderStateMachineHelper<TestType, AndIfMiddleLayerDataspaceState> {
1042 [[nodiscard]] auto andIfMiddleLayerIs(ui::Dataspace dataspace) {
1043 getInstance()->mLayer2.mLayerFEState.dataspace = dataspace;
1044 return nextState<AndIfBottomLayerDataspaceState>();
1045 }
1046 [[nodiscard]] auto andIfMiddleLayerHasNoPreference() {
1047 return andIfMiddleLayerIs(ui::Dataspace::UNKNOWN);
1048 }
1049 };
1050
1051 struct AndIfBottomLayerDataspaceState
1052 : public CallOrderStateMachineHelper<TestType, AndIfBottomLayerDataspaceState> {
1053 [[nodiscard]] auto andIfBottomLayerIs(ui::Dataspace dataspace) {
1054 getInstance()->mLayer1.mLayerFEState.dataspace = dataspace;
1055 return nextState<ThenExpectBestColorModeCallUsesState>();
1056 }
1057 [[nodiscard]] auto andIfBottomLayerHasNoPreference() {
1058 return andIfBottomLayerIs(ui::Dataspace::UNKNOWN);
1059 }
1060 };
1061
1062 struct ThenExpectBestColorModeCallUsesState
1063 : public CallOrderStateMachineHelper<TestType, ThenExpectBestColorModeCallUsesState> {
1064 [[nodiscard]] auto thenExpectBestColorModeCallUses(ui::Dataspace dataspace) {
1065 EXPECT_CALL(*getInstance()->mDisplayColorProfile,
1066 getBestColorMode(dataspace, _, _, _, _));
1067 return nextState<ExecuteState>();
1068 }
1069 };
1070
1071 // Call this member function to start using the mini-DSL defined above.
1072 [[nodiscard]] auto verify() { return IfTopLayerDataspaceState::make(this); }
1073};
1074
1075TEST_F(OutputUpdateColorProfileTest_TopmostLayerPreferenceSetsOutputPreference,
1076 noStrongLayerPrefenceUses_V0_SRGB) {
1077 // If none of the layers indicate a preference, then V0_SRGB is the
1078 // preferred choice (subject to additional checks).
1079 verify().ifTopLayerHasNoPreference()
1080 .andIfMiddleLayerHasNoPreference()
1081 .andIfBottomLayerHasNoPreference()
1082 .thenExpectBestColorModeCallUses(ui::Dataspace::V0_SRGB)
1083 .execute();
1084}
1085
1086TEST_F(OutputUpdateColorProfileTest_TopmostLayerPreferenceSetsOutputPreference,
1087 ifTopmostUses_DisplayP3_Then_DisplayP3_Chosen) {
1088 // If only the topmost layer has a preference, then that is what is chosen.
1089 verify().ifTopLayerIs(ui::Dataspace::DISPLAY_P3)
1090 .andIfMiddleLayerHasNoPreference()
1091 .andIfBottomLayerHasNoPreference()
1092 .thenExpectBestColorModeCallUses(ui::Dataspace::DISPLAY_P3)
1093 .execute();
1094}
1095
1096TEST_F(OutputUpdateColorProfileTest_TopmostLayerPreferenceSetsOutputPreference,
1097 ifMiddleUses_DisplayP3_Then_DisplayP3_Chosen) {
1098 // If only the middle layer has a preference, that that is what is chosen.
1099 verify().ifTopLayerHasNoPreference()
1100 .andIfMiddleLayerIs(ui::Dataspace::DISPLAY_P3)
1101 .andIfBottomLayerHasNoPreference()
1102 .thenExpectBestColorModeCallUses(ui::Dataspace::DISPLAY_P3)
1103 .execute();
1104}
1105
1106TEST_F(OutputUpdateColorProfileTest_TopmostLayerPreferenceSetsOutputPreference,
1107 ifBottomUses_DisplayP3_Then_DisplayP3_Chosen) {
1108 // If only the middle layer has a preference, that that is what is chosen.
1109 verify().ifTopLayerHasNoPreference()
1110 .andIfMiddleLayerHasNoPreference()
1111 .andIfBottomLayerIs(ui::Dataspace::DISPLAY_P3)
1112 .thenExpectBestColorModeCallUses(ui::Dataspace::DISPLAY_P3)
1113 .execute();
1114}
1115
1116TEST_F(OutputUpdateColorProfileTest_TopmostLayerPreferenceSetsOutputPreference,
1117 ifTopUses_DisplayBT2020_AndBottomUses_DisplayP3_Then_DisplayBT2020_Chosen) {
1118 // If multiple layers have a preference, the topmost value is what is used.
1119 verify().ifTopLayerIs(ui::Dataspace::DISPLAY_BT2020)
1120 .andIfMiddleLayerHasNoPreference()
1121 .andIfBottomLayerIs(ui::Dataspace::DISPLAY_P3)
1122 .thenExpectBestColorModeCallUses(ui::Dataspace::DISPLAY_BT2020)
1123 .execute();
1124}
1125
1126TEST_F(OutputUpdateColorProfileTest_TopmostLayerPreferenceSetsOutputPreference,
1127 ifTopUses_DisplayP3_AndBottomUses_V0_SRGB_Then_DisplayP3_Chosen) {
1128 // If multiple layers have a preference, the topmost value is what is used.
1129 verify().ifTopLayerIs(ui::Dataspace::DISPLAY_P3)
1130 .andIfMiddleLayerHasNoPreference()
1131 .andIfBottomLayerIs(ui::Dataspace::DISPLAY_BT2020)
1132 .thenExpectBestColorModeCallUses(ui::Dataspace::DISPLAY_P3)
1133 .execute();
1134}
1135
1136struct OutputUpdateColorProfileTest_ForceOutputColorOverrides
1137 : public OutputUpdateColorProfileTest {
1138 // If CompositionRefreshArgs::forceOutputColorMode is set to some specific
1139 // values, it overrides the layer dataspace choice.
1140
1141 OutputUpdateColorProfileTest_ForceOutputColorOverrides() {
1142 mRefreshArgs.outputColorSetting = OutputColorSetting::kEnhanced;
1143 mRefreshArgs.colorSpaceAgnosticDataspace = ui::Dataspace::UNKNOWN;
1144
1145 mLayer1.mLayerFEState.dataspace = ui::Dataspace::DISPLAY_BT2020;
1146
1147 EXPECT_CALL(mOutput, getOutputLayerCount()).WillRepeatedly(Return(1));
1148 EXPECT_CALL(mOutput, setColorProfile(_)).WillRepeatedly(Return());
1149 }
1150
1151 struct IfForceOutputColorModeState
1152 : public CallOrderStateMachineHelper<TestType, IfForceOutputColorModeState> {
1153 [[nodiscard]] auto ifForceOutputColorMode(ui::ColorMode colorMode) {
1154 getInstance()->mRefreshArgs.forceOutputColorMode = colorMode;
1155 return nextState<ThenExpectBestColorModeCallUsesState>();
1156 }
1157 [[nodiscard]] auto ifNoOverride() { return ifForceOutputColorMode(ui::ColorMode::NATIVE); }
1158 };
1159
1160 struct ThenExpectBestColorModeCallUsesState
1161 : public CallOrderStateMachineHelper<TestType, ThenExpectBestColorModeCallUsesState> {
1162 [[nodiscard]] auto thenExpectBestColorModeCallUses(ui::Dataspace dataspace) {
1163 EXPECT_CALL(*getInstance()->mDisplayColorProfile,
1164 getBestColorMode(dataspace, _, _, _, _));
1165 return nextState<ExecuteState>();
1166 }
1167 };
1168
1169 // Call this member function to start using the mini-DSL defined above.
1170 [[nodiscard]] auto verify() { return IfForceOutputColorModeState::make(this); }
1171};
1172
1173TEST_F(OutputUpdateColorProfileTest_ForceOutputColorOverrides, NoOverride_DoesNotOverride) {
1174 // By default the layer state is used to set the preferred dataspace
1175 verify().ifNoOverride()
1176 .thenExpectBestColorModeCallUses(ui::Dataspace::DISPLAY_BT2020)
1177 .execute();
1178}
1179
1180TEST_F(OutputUpdateColorProfileTest_ForceOutputColorOverrides, SRGB_Override_USES_V0_SRGB) {
1181 // Setting ui::ColorMode::SRGB overrides it with ui::Dataspace::V0_SRGB
1182 verify().ifForceOutputColorMode(ui::ColorMode::SRGB)
1183 .thenExpectBestColorModeCallUses(ui::Dataspace::V0_SRGB)
1184 .execute();
1185}
1186
1187TEST_F(OutputUpdateColorProfileTest_ForceOutputColorOverrides, DisplayP3_Override_Uses_DisplayP3) {
1188 // Setting ui::ColorMode::DISPLAY_P3 overrides it with ui::Dataspace::DISPLAY_P3
1189 verify().ifForceOutputColorMode(ui::ColorMode::DISPLAY_P3)
1190 .thenExpectBestColorModeCallUses(ui::Dataspace::DISPLAY_P3)
1191 .execute();
1192}
1193
1194// HDR output requires all layers to be compatible with the chosen HDR
1195// dataspace, along with there being proper support.
1196struct OutputUpdateColorProfileTest_Hdr : public OutputUpdateColorProfileTest {
1197 OutputUpdateColorProfileTest_Hdr() {
1198 mRefreshArgs.outputColorSetting = OutputColorSetting::kEnhanced;
1199 mRefreshArgs.colorSpaceAgnosticDataspace = ui::Dataspace::UNKNOWN;
1200 EXPECT_CALL(mOutput, getOutputLayerCount()).WillRepeatedly(Return(2));
1201 EXPECT_CALL(mOutput, setColorProfile(_)).WillRepeatedly(Return());
1202 }
1203
1204 static constexpr ui::Dataspace kNonHdrDataspace = ui::Dataspace::DISPLAY_P3;
1205 static constexpr ui::Dataspace BT2020_PQ = ui::Dataspace::BT2020_PQ;
1206 static constexpr ui::Dataspace BT2020_HLG = ui::Dataspace::BT2020_HLG;
1207 static constexpr ui::Dataspace DISPLAY_P3 = ui::Dataspace::DISPLAY_P3;
1208
1209 struct IfTopLayerDataspaceState
1210 : public CallOrderStateMachineHelper<TestType, IfTopLayerDataspaceState> {
1211 [[nodiscard]] auto ifTopLayerIs(ui::Dataspace dataspace) {
1212 getInstance()->mLayer2.mLayerFEState.dataspace = dataspace;
1213 return nextState<AndTopLayerCompositionTypeState>();
1214 }
1215 [[nodiscard]] auto ifTopLayerIsNotHdr() { return ifTopLayerIs(kNonHdrDataspace); }
1216 };
1217
1218 struct AndTopLayerCompositionTypeState
1219 : public CallOrderStateMachineHelper<TestType, AndTopLayerCompositionTypeState> {
1220 [[nodiscard]] auto andTopLayerIsREComposed(bool renderEngineComposed) {
1221 getInstance()->mLayer2.mLayerFEState.forceClientComposition = renderEngineComposed;
1222 return nextState<AndIfBottomLayerDataspaceState>();
1223 }
1224 };
1225
1226 struct AndIfBottomLayerDataspaceState
1227 : public CallOrderStateMachineHelper<TestType, AndIfBottomLayerDataspaceState> {
1228 [[nodiscard]] auto andIfBottomLayerIs(ui::Dataspace dataspace) {
1229 getInstance()->mLayer1.mLayerFEState.dataspace = dataspace;
1230 return nextState<AndBottomLayerCompositionTypeState>();
1231 }
1232 [[nodiscard]] auto andIfBottomLayerIsNotHdr() {
1233 return andIfBottomLayerIs(kNonHdrDataspace);
1234 }
1235 };
1236
1237 struct AndBottomLayerCompositionTypeState
1238 : public CallOrderStateMachineHelper<TestType, AndBottomLayerCompositionTypeState> {
1239 [[nodiscard]] auto andBottomLayerIsREComposed(bool renderEngineComposed) {
1240 getInstance()->mLayer1.mLayerFEState.forceClientComposition = renderEngineComposed;
1241 return nextState<AndIfHasLegacySupportState>();
1242 }
1243 };
1244
1245 struct AndIfHasLegacySupportState
1246 : public CallOrderStateMachineHelper<TestType, AndIfHasLegacySupportState> {
1247 [[nodiscard]] auto andIfLegacySupportFor(ui::Dataspace dataspace, bool legacySupport) {
1248 EXPECT_CALL(*getInstance()->mDisplayColorProfile, hasLegacyHdrSupport(dataspace))
1249 .WillOnce(Return(legacySupport));
1250 return nextState<ThenExpectBestColorModeCallUsesState>();
1251 }
1252 };
1253
1254 struct ThenExpectBestColorModeCallUsesState
1255 : public CallOrderStateMachineHelper<TestType, ThenExpectBestColorModeCallUsesState> {
1256 [[nodiscard]] auto thenExpectBestColorModeCallUses(ui::Dataspace dataspace) {
1257 EXPECT_CALL(*getInstance()->mDisplayColorProfile,
1258 getBestColorMode(dataspace, _, _, _, _));
1259 return nextState<ExecuteState>();
1260 }
1261 };
1262
1263 // Call this member function to start using the mini-DSL defined above.
1264 [[nodiscard]] auto verify() { return IfTopLayerDataspaceState::make(this); }
1265};
1266
1267TEST_F(OutputUpdateColorProfileTest_Hdr, PQ_HW_On_PQ_HW_Uses_PQ) {
1268 // If all layers use BT2020_PQ, and there are no other special conditions,
1269 // BT2020_PQ is used.
1270 verify().ifTopLayerIs(BT2020_PQ)
1271 .andTopLayerIsREComposed(false)
1272 .andIfBottomLayerIs(BT2020_PQ)
1273 .andBottomLayerIsREComposed(false)
1274 .andIfLegacySupportFor(BT2020_PQ, false)
1275 .thenExpectBestColorModeCallUses(BT2020_PQ)
1276 .execute();
1277}
1278
1279TEST_F(OutputUpdateColorProfileTest_Hdr, PQ_HW_On_PQ_HW_IfPQHasLegacySupport_Uses_DisplayP3) {
1280 // BT2020_PQ is not used if there is only legacy support for it.
1281 verify().ifTopLayerIs(BT2020_PQ)
1282 .andTopLayerIsREComposed(false)
1283 .andIfBottomLayerIs(BT2020_PQ)
1284 .andBottomLayerIsREComposed(false)
1285 .andIfLegacySupportFor(BT2020_PQ, true)
1286 .thenExpectBestColorModeCallUses(DISPLAY_P3)
1287 .execute();
1288}
1289
1290TEST_F(OutputUpdateColorProfileTest_Hdr, PQ_HW_On_PQ_RE_Uses_PQ) {
1291 // BT2020_PQ is still used if the bottom layer is RenderEngine composed.
1292 verify().ifTopLayerIs(BT2020_PQ)
1293 .andTopLayerIsREComposed(false)
1294 .andIfBottomLayerIs(BT2020_PQ)
1295 .andBottomLayerIsREComposed(true)
1296 .andIfLegacySupportFor(BT2020_PQ, false)
1297 .thenExpectBestColorModeCallUses(BT2020_PQ)
1298 .execute();
1299}
1300
1301TEST_F(OutputUpdateColorProfileTest_Hdr, PQ_RE_On_PQ_HW_Uses_DisplayP3) {
1302 // BT2020_PQ is not used if the top layer is RenderEngine composed.
1303 verify().ifTopLayerIs(BT2020_PQ)
1304 .andTopLayerIsREComposed(true)
1305 .andIfBottomLayerIs(BT2020_PQ)
1306 .andBottomLayerIsREComposed(false)
1307 .andIfLegacySupportFor(BT2020_PQ, false)
1308 .thenExpectBestColorModeCallUses(DISPLAY_P3)
1309 .execute();
1310}
1311
1312TEST_F(OutputUpdateColorProfileTest_Hdr, PQ_HW_On_HLG_HW_Uses_PQ) {
1313 // If there is mixed HLG/PQ use, and the topmost layer is PQ, then PQ is used if there
1314 // are no other special conditions.
1315 verify().ifTopLayerIs(BT2020_PQ)
1316 .andTopLayerIsREComposed(false)
1317 .andIfBottomLayerIs(BT2020_HLG)
1318 .andBottomLayerIsREComposed(false)
1319 .andIfLegacySupportFor(BT2020_PQ, false)
1320 .thenExpectBestColorModeCallUses(BT2020_PQ)
1321 .execute();
1322}
1323
1324TEST_F(OutputUpdateColorProfileTest_Hdr, PQ_HW_On_HLG_HW_IfPQHasLegacySupport_Uses_DisplayP3) {
1325 // BT2020_PQ is not used if there is only legacy support for it.
1326 verify().ifTopLayerIs(BT2020_PQ)
1327 .andTopLayerIsREComposed(false)
1328 .andIfBottomLayerIs(BT2020_HLG)
1329 .andBottomLayerIsREComposed(false)
1330 .andIfLegacySupportFor(BT2020_PQ, true)
1331 .thenExpectBestColorModeCallUses(DISPLAY_P3)
1332 .execute();
1333}
1334
1335TEST_F(OutputUpdateColorProfileTest_Hdr, PQ_HW_On_HLG_RE_Uses_PQ) {
1336 // BT2020_PQ is used if the bottom HLG layer is RenderEngine composed.
1337 verify().ifTopLayerIs(BT2020_PQ)
1338 .andTopLayerIsREComposed(false)
1339 .andIfBottomLayerIs(BT2020_HLG)
1340 .andBottomLayerIsREComposed(true)
1341 .andIfLegacySupportFor(BT2020_PQ, false)
1342 .thenExpectBestColorModeCallUses(BT2020_PQ)
1343 .execute();
1344}
1345
1346TEST_F(OutputUpdateColorProfileTest_Hdr, PQ_RE_On_HLG_HW_Uses_DisplayP3) {
1347 // BT2020_PQ is not used if the top PQ layer is RenderEngine composed.
1348 verify().ifTopLayerIs(BT2020_PQ)
1349 .andTopLayerIsREComposed(true)
1350 .andIfBottomLayerIs(BT2020_HLG)
1351 .andBottomLayerIsREComposed(false)
1352 .andIfLegacySupportFor(BT2020_PQ, false)
1353 .thenExpectBestColorModeCallUses(DISPLAY_P3)
1354 .execute();
1355}
1356
1357TEST_F(OutputUpdateColorProfileTest_Hdr, HLG_HW_On_PQ_HW_Uses_PQ) {
1358 // If there is mixed HLG/PQ use, and the topmost layer is HLG, then PQ is
1359 // used if there are no other special conditions.
1360 verify().ifTopLayerIs(BT2020_HLG)
1361 .andTopLayerIsREComposed(false)
1362 .andIfBottomLayerIs(BT2020_PQ)
1363 .andBottomLayerIsREComposed(false)
1364 .andIfLegacySupportFor(BT2020_PQ, false)
1365 .thenExpectBestColorModeCallUses(BT2020_PQ)
1366 .execute();
1367}
1368
1369TEST_F(OutputUpdateColorProfileTest_Hdr, HLG_HW_On_PQ_HW_IfPQHasLegacySupport_Uses_DisplayP3) {
1370 // BT2020_PQ is not used if there is only legacy support for it.
1371 verify().ifTopLayerIs(BT2020_HLG)
1372 .andTopLayerIsREComposed(false)
1373 .andIfBottomLayerIs(BT2020_PQ)
1374 .andBottomLayerIsREComposed(false)
1375 .andIfLegacySupportFor(BT2020_PQ, true)
1376 .thenExpectBestColorModeCallUses(DISPLAY_P3)
1377 .execute();
1378}
1379
1380TEST_F(OutputUpdateColorProfileTest_Hdr, HLG_HW_On_PQ_RE_Uses_DisplayP3) {
1381 // BT2020_PQ is not used if the bottom PQ layer is RenderEngine composed.
1382 verify().ifTopLayerIs(BT2020_HLG)
1383 .andTopLayerIsREComposed(false)
1384 .andIfBottomLayerIs(BT2020_PQ)
1385 .andBottomLayerIsREComposed(true)
1386 .andIfLegacySupportFor(BT2020_PQ, false)
1387 .thenExpectBestColorModeCallUses(DISPLAY_P3)
1388 .execute();
1389}
1390
1391TEST_F(OutputUpdateColorProfileTest_Hdr, HLG_RE_On_PQ_HW_Uses_PQ) {
1392 // BT2020_PQ is still used if the top HLG layer is RenderEngine composed.
1393 verify().ifTopLayerIs(BT2020_HLG)
1394 .andTopLayerIsREComposed(true)
1395 .andIfBottomLayerIs(BT2020_PQ)
1396 .andBottomLayerIsREComposed(false)
1397 .andIfLegacySupportFor(BT2020_PQ, false)
1398 .thenExpectBestColorModeCallUses(BT2020_PQ)
1399 .execute();
1400}
1401
1402TEST_F(OutputUpdateColorProfileTest_Hdr, HLG_HW_On_HLG_HW_Uses_HLG) {
1403 // If all layers use HLG then HLG is used if there are no other special
1404 // conditions.
1405 verify().ifTopLayerIs(BT2020_HLG)
1406 .andTopLayerIsREComposed(false)
1407 .andIfBottomLayerIs(BT2020_HLG)
1408 .andBottomLayerIsREComposed(false)
1409 .andIfLegacySupportFor(BT2020_HLG, false)
1410 .thenExpectBestColorModeCallUses(BT2020_HLG)
1411 .execute();
1412}
1413
1414TEST_F(OutputUpdateColorProfileTest_Hdr, HLG_HW_On_HLG_HW_IfPQHasLegacySupport_Uses_DisplayP3) {
1415 // BT2020_HLG is not used if there is legacy support for it.
1416 verify().ifTopLayerIs(BT2020_HLG)
1417 .andTopLayerIsREComposed(false)
1418 .andIfBottomLayerIs(BT2020_HLG)
1419 .andBottomLayerIsREComposed(false)
1420 .andIfLegacySupportFor(BT2020_HLG, true)
1421 .thenExpectBestColorModeCallUses(DISPLAY_P3)
1422 .execute();
1423}
1424
1425TEST_F(OutputUpdateColorProfileTest_Hdr, HLG_HW_On_HLG_RE_Uses_HLG) {
1426 // BT2020_HLG is used even if the bottom layer is client composed.
1427 verify().ifTopLayerIs(BT2020_HLG)
1428 .andTopLayerIsREComposed(false)
1429 .andIfBottomLayerIs(BT2020_HLG)
1430 .andBottomLayerIsREComposed(true)
1431 .andIfLegacySupportFor(BT2020_HLG, false)
1432 .thenExpectBestColorModeCallUses(BT2020_HLG)
1433 .execute();
1434}
1435
1436TEST_F(OutputUpdateColorProfileTest_Hdr, HLG_RE_On_HLG_HW_Uses_HLG) {
1437 // BT2020_HLG is used even if the top layer is client composed.
1438 verify().ifTopLayerIs(BT2020_HLG)
1439 .andTopLayerIsREComposed(true)
1440 .andIfBottomLayerIs(BT2020_HLG)
1441 .andBottomLayerIsREComposed(false)
1442 .andIfLegacySupportFor(BT2020_HLG, false)
1443 .thenExpectBestColorModeCallUses(BT2020_HLG)
1444 .execute();
1445}
1446
1447TEST_F(OutputUpdateColorProfileTest_Hdr, PQ_HW_On_NonHdr_HW_Uses_PQ) {
1448 // Even if there are non-HDR layers present, BT2020_PQ can still be used.
1449 verify().ifTopLayerIs(BT2020_PQ)
1450 .andTopLayerIsREComposed(false)
1451 .andIfBottomLayerIsNotHdr()
1452 .andBottomLayerIsREComposed(false)
1453 .andIfLegacySupportFor(BT2020_PQ, false)
1454 .thenExpectBestColorModeCallUses(BT2020_PQ)
1455 .execute();
1456}
1457
1458TEST_F(OutputUpdateColorProfileTest_Hdr, HLG_HW_On_NonHdr_RE_Uses_HLG) {
1459 // If all layers use HLG then HLG is used if there are no other special
1460 // conditions.
1461 verify().ifTopLayerIs(BT2020_HLG)
1462 .andTopLayerIsREComposed(false)
1463 .andIfBottomLayerIsNotHdr()
1464 .andBottomLayerIsREComposed(true)
1465 .andIfLegacySupportFor(BT2020_HLG, false)
1466 .thenExpectBestColorModeCallUses(BT2020_HLG)
1467 .execute();
1468}
1469
1470struct OutputUpdateColorProfile_AffectsChosenRenderIntentTest
1471 : public OutputUpdateColorProfileTest {
1472 // The various values for CompositionRefreshArgs::outputColorSetting affect
1473 // the chosen renderIntent, along with whether the preferred dataspace is an
1474 // HDR dataspace or not.
1475
1476 OutputUpdateColorProfile_AffectsChosenRenderIntentTest() {
1477 mRefreshArgs.outputColorSetting = OutputColorSetting::kEnhanced;
1478 mRefreshArgs.colorSpaceAgnosticDataspace = ui::Dataspace::UNKNOWN;
1479 mLayer1.mLayerFEState.dataspace = ui::Dataspace::BT2020_PQ;
1480 EXPECT_CALL(mOutput, getOutputLayerCount()).WillRepeatedly(Return(1));
1481 EXPECT_CALL(mOutput, setColorProfile(_)).WillRepeatedly(Return());
1482 EXPECT_CALL(*mDisplayColorProfile, hasLegacyHdrSupport(ui::Dataspace::BT2020_PQ))
1483 .WillRepeatedly(Return(false));
1484 }
1485
1486 // The tests here involve enough state and GMock setup that using a mini-DSL
1487 // makes the tests much more readable, and allows the test to focus more on
1488 // the intent than on some of the details.
1489
1490 static constexpr ui::Dataspace kNonHdrDataspace = ui::Dataspace::DISPLAY_P3;
1491 static constexpr ui::Dataspace kHdrDataspace = ui::Dataspace::BT2020_PQ;
1492
1493 struct IfDataspaceChosenState
1494 : public CallOrderStateMachineHelper<TestType, IfDataspaceChosenState> {
1495 [[nodiscard]] auto ifDataspaceChosenIs(ui::Dataspace dataspace) {
1496 getInstance()->mLayer1.mLayerFEState.dataspace = dataspace;
1497 return nextState<AndOutputColorSettingState>();
1498 }
1499 [[nodiscard]] auto ifDataspaceChosenIsNonHdr() {
1500 return ifDataspaceChosenIs(kNonHdrDataspace);
1501 }
1502 [[nodiscard]] auto ifDataspaceChosenIsHdr() { return ifDataspaceChosenIs(kHdrDataspace); }
1503 };
1504
1505 struct AndOutputColorSettingState
1506 : public CallOrderStateMachineHelper<TestType, AndOutputColorSettingState> {
1507 [[nodiscard]] auto andOutputColorSettingIs(OutputColorSetting setting) {
1508 getInstance()->mRefreshArgs.outputColorSetting = setting;
1509 return nextState<ThenExpectBestColorModeCallUsesState>();
1510 }
1511 };
1512
1513 struct ThenExpectBestColorModeCallUsesState
1514 : public CallOrderStateMachineHelper<TestType, ThenExpectBestColorModeCallUsesState> {
1515 [[nodiscard]] auto thenExpectBestColorModeCallUses(ui::RenderIntent intent) {
1516 EXPECT_CALL(*getInstance()->mDisplayColorProfile,
1517 getBestColorMode(getInstance()->mLayer1.mLayerFEState.dataspace, intent, _,
1518 _, _));
1519 return nextState<ExecuteState>();
1520 }
1521 };
1522
1523 // Tests call one of these two helper member functions to start using the
1524 // mini-DSL defined above.
1525 [[nodiscard]] auto verify() { return IfDataspaceChosenState::make(this); }
1526};
1527
1528TEST_F(OutputUpdateColorProfile_AffectsChosenRenderIntentTest,
1529 Managed_NonHdr_Prefers_Colorimetric) {
1530 verify().ifDataspaceChosenIsNonHdr()
1531 .andOutputColorSettingIs(OutputColorSetting::kManaged)
1532 .thenExpectBestColorModeCallUses(ui::RenderIntent::COLORIMETRIC)
1533 .execute();
1534}
1535
1536TEST_F(OutputUpdateColorProfile_AffectsChosenRenderIntentTest,
1537 Managed_Hdr_Prefers_ToneMapColorimetric) {
1538 verify().ifDataspaceChosenIsHdr()
1539 .andOutputColorSettingIs(OutputColorSetting::kManaged)
1540 .thenExpectBestColorModeCallUses(ui::RenderIntent::TONE_MAP_COLORIMETRIC)
1541 .execute();
1542}
1543
1544TEST_F(OutputUpdateColorProfile_AffectsChosenRenderIntentTest, Enhanced_NonHdr_Prefers_Enhance) {
1545 verify().ifDataspaceChosenIsNonHdr()
1546 .andOutputColorSettingIs(OutputColorSetting::kEnhanced)
1547 .thenExpectBestColorModeCallUses(ui::RenderIntent::ENHANCE)
1548 .execute();
1549}
1550
1551TEST_F(OutputUpdateColorProfile_AffectsChosenRenderIntentTest,
1552 Enhanced_Hdr_Prefers_ToneMapEnhance) {
1553 verify().ifDataspaceChosenIsHdr()
1554 .andOutputColorSettingIs(OutputColorSetting::kEnhanced)
1555 .thenExpectBestColorModeCallUses(ui::RenderIntent::TONE_MAP_ENHANCE)
1556 .execute();
1557}
1558
1559TEST_F(OutputUpdateColorProfile_AffectsChosenRenderIntentTest, Vendor_NonHdr_Prefers_Vendor) {
1560 verify().ifDataspaceChosenIsNonHdr()
1561 .andOutputColorSettingIs(kVendorSpecifiedOutputColorSetting)
1562 .thenExpectBestColorModeCallUses(
1563 static_cast<ui::RenderIntent>(kVendorSpecifiedOutputColorSetting))
1564 .execute();
1565}
1566
1567TEST_F(OutputUpdateColorProfile_AffectsChosenRenderIntentTest, Vendor_Hdr_Prefers_Vendor) {
1568 verify().ifDataspaceChosenIsHdr()
1569 .andOutputColorSettingIs(kVendorSpecifiedOutputColorSetting)
1570 .thenExpectBestColorModeCallUses(
1571 static_cast<ui::RenderIntent>(kVendorSpecifiedOutputColorSetting))
1572 .execute();
1573}
Lloyd Piquefaa3f192019-11-14 14:05:09 -08001574
1575/*
1576 * Output::beginFrame()
1577 */
1578
Lloyd Piquee5965952019-11-18 16:16:32 -08001579struct OutputBeginFrameTest : public ::testing::Test {
1580 using TestType = OutputBeginFrameTest;
1581
1582 struct OutputPartialMock : public OutputPartialMockBase {
1583 // Sets up the helper functions called by begiNFrame to use a mock
1584 // implementations.
1585 MOCK_CONST_METHOD1(getDirtyRegion, Region(bool));
1586 };
1587
1588 OutputBeginFrameTest() {
1589 mOutput.setDisplayColorProfileForTest(
1590 std::unique_ptr<DisplayColorProfile>(mDisplayColorProfile));
1591 mOutput.setRenderSurfaceForTest(std::unique_ptr<RenderSurface>(mRenderSurface));
1592 }
1593
1594 struct IfGetDirtyRegionExpectationState
1595 : public CallOrderStateMachineHelper<TestType, IfGetDirtyRegionExpectationState> {
1596 [[nodiscard]] auto ifGetDirtyRegionReturns(Region dirtyRegion) {
1597 EXPECT_CALL(getInstance()->mOutput, getDirtyRegion(false))
1598 .WillOnce(Return(dirtyRegion));
1599 return nextState<AndIfGetOutputLayerCountExpectationState>();
1600 }
1601 };
1602
1603 struct AndIfGetOutputLayerCountExpectationState
1604 : public CallOrderStateMachineHelper<TestType, AndIfGetOutputLayerCountExpectationState> {
1605 [[nodiscard]] auto andIfGetOutputLayerCountReturns(size_t layerCount) {
1606 EXPECT_CALL(getInstance()->mOutput, getOutputLayerCount()).WillOnce(Return(layerCount));
1607 return nextState<AndIfLastCompositionHadVisibleLayersState>();
1608 }
1609 };
1610
1611 struct AndIfLastCompositionHadVisibleLayersState
1612 : public CallOrderStateMachineHelper<TestType,
1613 AndIfLastCompositionHadVisibleLayersState> {
1614 [[nodiscard]] auto andIfLastCompositionHadVisibleLayersIs(bool hadOutputLayers) {
1615 getInstance()->mOutput.mState.lastCompositionHadVisibleLayers = hadOutputLayers;
1616 return nextState<ThenExpectRenderSurfaceBeginFrameCallState>();
1617 }
1618 };
1619
1620 struct ThenExpectRenderSurfaceBeginFrameCallState
1621 : public CallOrderStateMachineHelper<TestType,
1622 ThenExpectRenderSurfaceBeginFrameCallState> {
1623 [[nodiscard]] auto thenExpectRenderSurfaceBeginFrameCall(bool mustRecompose) {
1624 EXPECT_CALL(*getInstance()->mRenderSurface, beginFrame(mustRecompose));
1625 return nextState<ExecuteState>();
1626 }
1627 };
1628
1629 struct ExecuteState : public CallOrderStateMachineHelper<TestType, ExecuteState> {
1630 [[nodiscard]] auto execute() {
1631 getInstance()->mOutput.beginFrame();
1632 return nextState<CheckPostconditionHadVisibleLayersState>();
1633 }
1634 };
1635
1636 struct CheckPostconditionHadVisibleLayersState
1637 : public CallOrderStateMachineHelper<TestType, CheckPostconditionHadVisibleLayersState> {
1638 void checkPostconditionHadVisibleLayers(bool expected) {
1639 EXPECT_EQ(expected, getInstance()->mOutput.mState.lastCompositionHadVisibleLayers);
1640 }
1641 };
1642
1643 // Tests call one of these two helper member functions to start using the
1644 // mini-DSL defined above.
1645 [[nodiscard]] auto verify() { return IfGetDirtyRegionExpectationState::make(this); }
1646
1647 static const Region kEmptyRegion;
1648 static const Region kNotEmptyRegion;
1649
1650 mock::DisplayColorProfile* mDisplayColorProfile = new StrictMock<mock::DisplayColorProfile>();
1651 mock::RenderSurface* mRenderSurface = new StrictMock<mock::RenderSurface>();
1652 StrictMock<OutputPartialMock> mOutput;
1653};
1654
1655const Region OutputBeginFrameTest::kEmptyRegion{Rect{0, 0, 0, 0}};
1656const Region OutputBeginFrameTest::kNotEmptyRegion{Rect{0, 0, 1, 1}};
1657
1658TEST_F(OutputBeginFrameTest, hasDirtyHasLayersHadLayersLastFrame) {
1659 verify().ifGetDirtyRegionReturns(kNotEmptyRegion)
1660 .andIfGetOutputLayerCountReturns(1u)
1661 .andIfLastCompositionHadVisibleLayersIs(true)
1662 .thenExpectRenderSurfaceBeginFrameCall(true)
1663 .execute()
1664 .checkPostconditionHadVisibleLayers(true);
1665}
1666
1667TEST_F(OutputBeginFrameTest, hasDirtyNotHasLayersHadLayersLastFrame) {
1668 verify().ifGetDirtyRegionReturns(kNotEmptyRegion)
1669 .andIfGetOutputLayerCountReturns(0u)
1670 .andIfLastCompositionHadVisibleLayersIs(true)
1671 .thenExpectRenderSurfaceBeginFrameCall(true)
1672 .execute()
1673 .checkPostconditionHadVisibleLayers(false);
1674}
1675
1676TEST_F(OutputBeginFrameTest, hasDirtyHasLayersNotHadLayersLastFrame) {
1677 verify().ifGetDirtyRegionReturns(kNotEmptyRegion)
1678 .andIfGetOutputLayerCountReturns(1u)
1679 .andIfLastCompositionHadVisibleLayersIs(false)
1680 .thenExpectRenderSurfaceBeginFrameCall(true)
1681 .execute()
1682 .checkPostconditionHadVisibleLayers(true);
1683}
1684
1685TEST_F(OutputBeginFrameTest, hasDirtyNotHasLayersNotHadLayersLastFrame) {
1686 verify().ifGetDirtyRegionReturns(kNotEmptyRegion)
1687 .andIfGetOutputLayerCountReturns(0u)
1688 .andIfLastCompositionHadVisibleLayersIs(false)
1689 .thenExpectRenderSurfaceBeginFrameCall(false)
1690 .execute()
1691 .checkPostconditionHadVisibleLayers(false);
1692}
1693
1694TEST_F(OutputBeginFrameTest, notHasDirtyHasLayersHadLayersLastFrame) {
1695 verify().ifGetDirtyRegionReturns(kEmptyRegion)
1696 .andIfGetOutputLayerCountReturns(1u)
1697 .andIfLastCompositionHadVisibleLayersIs(true)
1698 .thenExpectRenderSurfaceBeginFrameCall(false)
1699 .execute()
1700 .checkPostconditionHadVisibleLayers(true);
1701}
1702
1703TEST_F(OutputBeginFrameTest, notHasDirtyNotHasLayersHadLayersLastFrame) {
1704 verify().ifGetDirtyRegionReturns(kEmptyRegion)
1705 .andIfGetOutputLayerCountReturns(0u)
1706 .andIfLastCompositionHadVisibleLayersIs(true)
1707 .thenExpectRenderSurfaceBeginFrameCall(false)
1708 .execute()
1709 .checkPostconditionHadVisibleLayers(true);
1710}
1711
1712TEST_F(OutputBeginFrameTest, notHasDirtyHasLayersNotHadLayersLastFrame) {
1713 verify().ifGetDirtyRegionReturns(kEmptyRegion)
1714 .andIfGetOutputLayerCountReturns(1u)
1715 .andIfLastCompositionHadVisibleLayersIs(false)
1716 .thenExpectRenderSurfaceBeginFrameCall(false)
1717 .execute()
1718 .checkPostconditionHadVisibleLayers(false);
1719}
1720
1721TEST_F(OutputBeginFrameTest, notHasDirtyNotHasLayersNotHadLayersLastFrame) {
1722 verify().ifGetDirtyRegionReturns(kEmptyRegion)
1723 .andIfGetOutputLayerCountReturns(0u)
1724 .andIfLastCompositionHadVisibleLayersIs(false)
1725 .thenExpectRenderSurfaceBeginFrameCall(false)
1726 .execute()
1727 .checkPostconditionHadVisibleLayers(false);
1728}
1729
Lloyd Piquefaa3f192019-11-14 14:05:09 -08001730/*
1731 * Output::devOptRepaintFlash()
1732 */
1733
Lloyd Piquedb462d82019-11-19 17:58:46 -08001734struct OutputDevOptRepaintFlashTest : public testing::Test {
1735 struct OutputPartialMock : public OutputPartialMockBase {
1736 // Sets up the helper functions called by composeSurfaces to use a mock
1737 // implementations.
1738 MOCK_CONST_METHOD1(getDirtyRegion, Region(bool));
1739 MOCK_METHOD1(composeSurfaces, std::optional<base::unique_fd>(const Region&));
1740 MOCK_METHOD0(postFramebuffer, void());
1741 MOCK_METHOD0(prepareFrame, void());
1742 };
1743
1744 OutputDevOptRepaintFlashTest() {
1745 mOutput.setDisplayColorProfileForTest(
1746 std::unique_ptr<DisplayColorProfile>(mDisplayColorProfile));
1747 mOutput.setRenderSurfaceForTest(std::unique_ptr<RenderSurface>(mRenderSurface));
1748 }
1749
1750 static const Region kEmptyRegion;
1751 static const Region kNotEmptyRegion;
1752
1753 StrictMock<OutputPartialMock> mOutput;
1754 mock::DisplayColorProfile* mDisplayColorProfile = new StrictMock<mock::DisplayColorProfile>();
1755 mock::RenderSurface* mRenderSurface = new StrictMock<mock::RenderSurface>();
1756 CompositionRefreshArgs mRefreshArgs;
1757};
1758
1759const Region OutputDevOptRepaintFlashTest::kEmptyRegion{Rect{0, 0, 0, 0}};
1760const Region OutputDevOptRepaintFlashTest::kNotEmptyRegion{Rect{0, 0, 1, 1}};
1761
1762TEST_F(OutputDevOptRepaintFlashTest, doesNothingIfFlashDelayNotSet) {
1763 mRefreshArgs.devOptFlashDirtyRegionsDelay = {};
1764 mRefreshArgs.repaintEverything = true;
1765 mOutput.mState.isEnabled = true;
1766
1767 mOutput.devOptRepaintFlash(mRefreshArgs);
1768}
1769
1770TEST_F(OutputDevOptRepaintFlashTest, postsAndPreparesANewFrameIfNotEnabled) {
1771 mRefreshArgs.devOptFlashDirtyRegionsDelay = std::chrono::microseconds(1);
1772 mRefreshArgs.repaintEverything = true;
1773 mOutput.mState.isEnabled = false;
1774
1775 InSequence seq;
1776 EXPECT_CALL(mOutput, postFramebuffer());
1777 EXPECT_CALL(mOutput, prepareFrame());
1778
1779 mOutput.devOptRepaintFlash(mRefreshArgs);
1780}
1781
1782TEST_F(OutputDevOptRepaintFlashTest, postsAndPreparesANewFrameIfNotDirty) {
1783 mRefreshArgs.devOptFlashDirtyRegionsDelay = std::chrono::microseconds(1);
1784 mRefreshArgs.repaintEverything = true;
1785 mOutput.mState.isEnabled = true;
1786
1787 InSequence seq;
1788 EXPECT_CALL(mOutput, getDirtyRegion(true)).WillOnce(Return(kEmptyRegion));
1789 EXPECT_CALL(mOutput, postFramebuffer());
1790 EXPECT_CALL(mOutput, prepareFrame());
1791
1792 mOutput.devOptRepaintFlash(mRefreshArgs);
1793}
1794
1795TEST_F(OutputDevOptRepaintFlashTest, alsoComposesSurfacesAndQueuesABufferIfDirty) {
1796 mRefreshArgs.devOptFlashDirtyRegionsDelay = std::chrono::microseconds(1);
1797 mRefreshArgs.repaintEverything = false;
1798 mOutput.mState.isEnabled = true;
1799
1800 InSequence seq;
1801 EXPECT_CALL(mOutput, getDirtyRegion(false)).WillOnce(Return(kNotEmptyRegion));
1802 EXPECT_CALL(mOutput, composeSurfaces(RegionEq(kNotEmptyRegion)));
1803 EXPECT_CALL(*mRenderSurface, queueBuffer(_));
1804 EXPECT_CALL(mOutput, postFramebuffer());
1805 EXPECT_CALL(mOutput, prepareFrame());
1806
1807 mOutput.devOptRepaintFlash(mRefreshArgs);
1808}
1809
Lloyd Piquefaa3f192019-11-14 14:05:09 -08001810// TODO(b/144060211) - Add coverage
1811
1812/*
1813 * Output::finishFrame()
1814 */
1815
Lloyd Pique03561a62019-11-19 18:34:52 -08001816struct OutputFinishFrameTest : public testing::Test {
1817 struct OutputPartialMock : public OutputPartialMockBase {
1818 // Sets up the helper functions called by composeSurfaces to use a mock
1819 // implementations.
1820 MOCK_METHOD1(composeSurfaces, std::optional<base::unique_fd>(const Region&));
1821 MOCK_METHOD0(postFramebuffer, void());
1822 };
1823
1824 OutputFinishFrameTest() {
1825 mOutput.setDisplayColorProfileForTest(
1826 std::unique_ptr<DisplayColorProfile>(mDisplayColorProfile));
1827 mOutput.setRenderSurfaceForTest(std::unique_ptr<RenderSurface>(mRenderSurface));
1828 }
1829
1830 StrictMock<OutputPartialMock> mOutput;
1831 mock::DisplayColorProfile* mDisplayColorProfile = new StrictMock<mock::DisplayColorProfile>();
1832 mock::RenderSurface* mRenderSurface = new StrictMock<mock::RenderSurface>();
1833 CompositionRefreshArgs mRefreshArgs;
1834};
1835
1836TEST_F(OutputFinishFrameTest, ifNotEnabledDoesNothing) {
1837 mOutput.mState.isEnabled = false;
1838
1839 mOutput.finishFrame(mRefreshArgs);
1840}
1841
1842TEST_F(OutputFinishFrameTest, takesEarlyOutifComposeSurfacesReturnsNoFence) {
1843 mOutput.mState.isEnabled = true;
1844
1845 InSequence seq;
1846 EXPECT_CALL(mOutput, composeSurfaces(RegionEq(Region::INVALID_REGION)));
1847
1848 mOutput.finishFrame(mRefreshArgs);
1849}
1850
1851TEST_F(OutputFinishFrameTest, queuesBufferIfComposeSurfacesReturnsAFence) {
1852 mOutput.mState.isEnabled = true;
1853
1854 InSequence seq;
1855 EXPECT_CALL(mOutput, composeSurfaces(RegionEq(Region::INVALID_REGION)))
1856 .WillOnce(Return(ByMove(base::unique_fd())));
1857 EXPECT_CALL(*mRenderSurface, queueBuffer(_));
1858
1859 mOutput.finishFrame(mRefreshArgs);
1860}
Lloyd Piquefaa3f192019-11-14 14:05:09 -08001861
1862/*
1863 * Output::postFramebuffer()
1864 */
1865
Lloyd Pique07178e32019-11-19 19:15:26 -08001866struct OutputPostFramebufferTest : public testing::Test {
1867 struct OutputPartialMock : public OutputPartialMockBase {
1868 // Sets up the helper functions called by composeSurfaces to use a mock
1869 // implementations.
1870 MOCK_METHOD0(presentAndGetFrameFences, compositionengine::Output::FrameFences());
1871 };
1872
1873 struct Layer {
1874 Layer() {
1875 EXPECT_CALL(outputLayer, getLayerFE()).WillRepeatedly(ReturnRef(layerFE));
1876 EXPECT_CALL(outputLayer, getHwcLayer()).WillRepeatedly(Return(&hwc2Layer));
1877 }
1878
1879 StrictMock<mock::OutputLayer> outputLayer;
1880 StrictMock<mock::LayerFE> layerFE;
1881 StrictMock<HWC2::mock::Layer> hwc2Layer;
1882 };
1883
1884 OutputPostFramebufferTest() {
1885 mOutput.setDisplayColorProfileForTest(
1886 std::unique_ptr<DisplayColorProfile>(mDisplayColorProfile));
1887 mOutput.setRenderSurfaceForTest(std::unique_ptr<RenderSurface>(mRenderSurface));
1888
1889 EXPECT_CALL(mOutput, getOutputLayerCount()).WillRepeatedly(Return(3u));
1890 EXPECT_CALL(mOutput, getOutputLayerOrderedByZByIndex(0u))
1891 .WillRepeatedly(Return(&mLayer1.outputLayer));
1892 EXPECT_CALL(mOutput, getOutputLayerOrderedByZByIndex(1u))
1893 .WillRepeatedly(Return(&mLayer2.outputLayer));
1894 EXPECT_CALL(mOutput, getOutputLayerOrderedByZByIndex(2u))
1895 .WillRepeatedly(Return(&mLayer3.outputLayer));
1896 }
1897
1898 StrictMock<OutputPartialMock> mOutput;
1899 mock::DisplayColorProfile* mDisplayColorProfile = new StrictMock<mock::DisplayColorProfile>();
1900 mock::RenderSurface* mRenderSurface = new StrictMock<mock::RenderSurface>();
1901
1902 Layer mLayer1;
1903 Layer mLayer2;
1904 Layer mLayer3;
1905};
1906
1907TEST_F(OutputPostFramebufferTest, ifNotEnabledDoesNothing) {
1908 mOutput.mState.isEnabled = false;
1909
1910 mOutput.postFramebuffer();
1911}
1912
1913TEST_F(OutputPostFramebufferTest, ifEnabledMustFlipThenPresentThenSendPresentCompleted) {
1914 mOutput.mState.isEnabled = true;
1915
1916 compositionengine::Output::FrameFences frameFences;
1917
1918 // This should happen even if there are no output layers.
1919 EXPECT_CALL(mOutput, getOutputLayerCount()).WillOnce(Return(0u));
1920
1921 // For this test in particular we want to make sure the call expectations
1922 // setup below are satisfied in the specific order.
1923 InSequence seq;
1924
1925 EXPECT_CALL(*mRenderSurface, flip());
1926 EXPECT_CALL(mOutput, presentAndGetFrameFences()).WillOnce(Return(frameFences));
1927 EXPECT_CALL(*mRenderSurface, onPresentDisplayCompleted());
1928
1929 mOutput.postFramebuffer();
1930}
1931
1932TEST_F(OutputPostFramebufferTest, releaseFencesAreSentToLayerFE) {
1933 // Simulate getting release fences from each layer, and ensure they are passed to the
1934 // front-end layer interface for each layer correctly.
1935
1936 mOutput.mState.isEnabled = true;
1937
1938 // Create three unique fence instances
1939 sp<Fence> layer1Fence = new Fence();
1940 sp<Fence> layer2Fence = new Fence();
1941 sp<Fence> layer3Fence = new Fence();
1942
1943 compositionengine::Output::FrameFences frameFences;
1944 frameFences.layerFences.emplace(&mLayer1.hwc2Layer, layer1Fence);
1945 frameFences.layerFences.emplace(&mLayer2.hwc2Layer, layer2Fence);
1946 frameFences.layerFences.emplace(&mLayer3.hwc2Layer, layer3Fence);
1947
1948 EXPECT_CALL(*mRenderSurface, flip());
1949 EXPECT_CALL(mOutput, presentAndGetFrameFences()).WillOnce(Return(frameFences));
1950 EXPECT_CALL(*mRenderSurface, onPresentDisplayCompleted());
1951
1952 // Compare the pointers values of each fence to make sure the correct ones
1953 // are passed. This happens to work with the current implementation, but
1954 // would not survive certain calls like Fence::merge() which would return a
1955 // new instance.
1956 EXPECT_CALL(mLayer1.layerFE,
1957 onLayerDisplayed(Property(&sp<Fence>::get, Eq(layer1Fence.get()))));
1958 EXPECT_CALL(mLayer2.layerFE,
1959 onLayerDisplayed(Property(&sp<Fence>::get, Eq(layer2Fence.get()))));
1960 EXPECT_CALL(mLayer3.layerFE,
1961 onLayerDisplayed(Property(&sp<Fence>::get, Eq(layer3Fence.get()))));
1962
1963 mOutput.postFramebuffer();
1964}
1965
1966TEST_F(OutputPostFramebufferTest, releaseFencesIncludeClientTargetAcquireFence) {
1967 mOutput.mState.isEnabled = true;
1968 mOutput.mState.usesClientComposition = true;
1969
1970 sp<Fence> clientTargetAcquireFence = new Fence();
1971 sp<Fence> layer1Fence = new Fence();
1972 sp<Fence> layer2Fence = new Fence();
1973 sp<Fence> layer3Fence = new Fence();
1974 compositionengine::Output::FrameFences frameFences;
1975 frameFences.clientTargetAcquireFence = clientTargetAcquireFence;
1976 frameFences.layerFences.emplace(&mLayer1.hwc2Layer, layer1Fence);
1977 frameFences.layerFences.emplace(&mLayer2.hwc2Layer, layer2Fence);
1978 frameFences.layerFences.emplace(&mLayer3.hwc2Layer, layer3Fence);
1979
1980 EXPECT_CALL(*mRenderSurface, flip());
1981 EXPECT_CALL(mOutput, presentAndGetFrameFences()).WillOnce(Return(frameFences));
1982 EXPECT_CALL(*mRenderSurface, onPresentDisplayCompleted());
1983
1984 // Fence::merge is called, and since none of the fences are actually valid,
1985 // Fence::NO_FENCE is returned and passed to each onLayerDisplayed() call.
1986 // This is the best we can do without creating a real kernel fence object.
1987 EXPECT_CALL(mLayer1.layerFE, onLayerDisplayed(Fence::NO_FENCE));
1988 EXPECT_CALL(mLayer2.layerFE, onLayerDisplayed(Fence::NO_FENCE));
1989 EXPECT_CALL(mLayer3.layerFE, onLayerDisplayed(Fence::NO_FENCE));
1990
1991 mOutput.postFramebuffer();
1992}
1993
1994TEST_F(OutputPostFramebufferTest, releasedLayersSentPresentFence) {
1995 mOutput.mState.isEnabled = true;
1996 mOutput.mState.usesClientComposition = true;
1997
1998 // This should happen even if there are no (current) output layers.
1999 EXPECT_CALL(mOutput, getOutputLayerCount()).WillOnce(Return(0u));
2000
2001 // Load up the released layers with some mock instances
2002 sp<StrictMock<mock::LayerFE>> releasedLayer1{new StrictMock<mock::LayerFE>()};
2003 sp<StrictMock<mock::LayerFE>> releasedLayer2{new StrictMock<mock::LayerFE>()};
2004 sp<StrictMock<mock::LayerFE>> releasedLayer3{new StrictMock<mock::LayerFE>()};
2005 Output::ReleasedLayers layers;
2006 layers.push_back(releasedLayer1);
2007 layers.push_back(releasedLayer2);
2008 layers.push_back(releasedLayer3);
2009 mOutput.setReleasedLayers(std::move(layers));
2010
2011 // Set up a fake present fence
2012 sp<Fence> presentFence = new Fence();
2013 compositionengine::Output::FrameFences frameFences;
2014 frameFences.presentFence = presentFence;
2015
2016 EXPECT_CALL(*mRenderSurface, flip());
2017 EXPECT_CALL(mOutput, presentAndGetFrameFences()).WillOnce(Return(frameFences));
2018 EXPECT_CALL(*mRenderSurface, onPresentDisplayCompleted());
2019
2020 // Each released layer should be given the presentFence.
2021 EXPECT_CALL(*releasedLayer1,
2022 onLayerDisplayed(Property(&sp<Fence>::get, Eq(presentFence.get()))));
2023 EXPECT_CALL(*releasedLayer2,
2024 onLayerDisplayed(Property(&sp<Fence>::get, Eq(presentFence.get()))));
2025 EXPECT_CALL(*releasedLayer3,
2026 onLayerDisplayed(Property(&sp<Fence>::get, Eq(presentFence.get()))));
2027
2028 mOutput.postFramebuffer();
2029
2030 // After the call the list of released layers should have been cleared.
2031 EXPECT_TRUE(mOutput.getReleasedLayersForTest().empty());
2032}
Lloyd Piquefaa3f192019-11-14 14:05:09 -08002033
2034/*
Lloyd Pique56eba802019-08-28 15:45:25 -07002035 * Output::composeSurfaces()
2036 */
2037
2038struct OutputComposeSurfacesTest : public testing::Test {
2039 static constexpr uint32_t kDefaultOutputOrientation = TR_IDENT;
2040 static constexpr ui::Dataspace kDefaultOutputDataspace = ui::Dataspace::DISPLAY_P3;
2041
2042 static const Rect kDefaultOutputFrame;
2043 static const Rect kDefaultOutputViewport;
2044 static const Rect kDefaultOutputScissor;
2045 static const mat4 kDefaultColorTransformMat;
2046
Lloyd Piquefaa3f192019-11-14 14:05:09 -08002047 struct OutputPartialMock : public OutputPartialMockBase {
Lloyd Pique56eba802019-08-28 15:45:25 -07002048 // Sets up the helper functions called by composeSurfaces to use a mock
2049 // implementations.
2050 MOCK_CONST_METHOD0(getSkipColorTransform, bool());
2051 MOCK_METHOD2(generateClientCompositionRequests,
2052 std::vector<renderengine::LayerSettings>(bool, Region&));
2053 MOCK_METHOD2(appendRegionFlashRequests,
2054 void(const Region&, std::vector<renderengine::LayerSettings>&));
2055 MOCK_METHOD1(setExpensiveRenderingExpected, void(bool));
2056 };
2057
2058 OutputComposeSurfacesTest() {
2059 mOutput.setDisplayColorProfileForTest(
2060 std::unique_ptr<DisplayColorProfile>(mDisplayColorProfile));
2061 mOutput.setRenderSurfaceForTest(std::unique_ptr<RenderSurface>(mRenderSurface));
2062
Lloyd Pique56eba802019-08-28 15:45:25 -07002063 mOutput.editState().frame = kDefaultOutputFrame;
2064 mOutput.editState().viewport = kDefaultOutputViewport;
2065 mOutput.editState().scissor = kDefaultOutputScissor;
2066 mOutput.editState().transform = ui::Transform{kDefaultOutputOrientation};
2067 mOutput.editState().orientation = kDefaultOutputOrientation;
2068 mOutput.editState().dataspace = kDefaultOutputDataspace;
Lloyd Pique3eb1b212019-03-07 21:15:40 -08002069 mOutput.editState().colorTransformMatrix = kDefaultColorTransformMat;
Lloyd Pique56eba802019-08-28 15:45:25 -07002070 mOutput.editState().isSecure = true;
2071 mOutput.editState().needsFiltering = false;
2072 mOutput.editState().usesClientComposition = true;
2073 mOutput.editState().usesDeviceComposition = false;
2074
Lloyd Pique01c77c12019-04-17 12:48:32 -07002075 EXPECT_CALL(mOutput, getOutputLayerCount()).WillRepeatedly(Return(2u));
2076 EXPECT_CALL(mOutput, getOutputLayerOrderedByZByIndex(0u))
2077 .WillRepeatedly(Return(&mOutputLayer1));
2078 EXPECT_CALL(mOutput, getOutputLayerOrderedByZByIndex(1u))
2079 .WillRepeatedly(Return(&mOutputLayer2));
Lloyd Piquea38ea7e2019-04-16 18:10:26 -07002080 EXPECT_CALL(mOutput, getCompositionEngine()).WillRepeatedly(ReturnRef(mCompositionEngine));
Lloyd Pique56eba802019-08-28 15:45:25 -07002081 EXPECT_CALL(mCompositionEngine, getRenderEngine()).WillRepeatedly(ReturnRef(mRenderEngine));
2082 }
2083
2084 StrictMock<mock::CompositionEngine> mCompositionEngine;
2085 StrictMock<renderengine::mock::RenderEngine> mRenderEngine;
2086 mock::DisplayColorProfile* mDisplayColorProfile = new StrictMock<mock::DisplayColorProfile>();
2087 mock::RenderSurface* mRenderSurface = new StrictMock<mock::RenderSurface>();
Lloyd Pique01c77c12019-04-17 12:48:32 -07002088 StrictMock<mock::OutputLayer> mOutputLayer1;
2089 StrictMock<mock::OutputLayer> mOutputLayer2;
Lloyd Piquea38ea7e2019-04-16 18:10:26 -07002090 StrictMock<OutputPartialMock> mOutput;
Lloyd Pique56eba802019-08-28 15:45:25 -07002091 sp<GraphicBuffer> mOutputBuffer = new GraphicBuffer();
2092};
2093
2094const Rect OutputComposeSurfacesTest::kDefaultOutputFrame{1001, 1002, 1003, 1004};
2095const Rect OutputComposeSurfacesTest::kDefaultOutputViewport{1005, 1006, 1007, 1008};
2096const Rect OutputComposeSurfacesTest::kDefaultOutputScissor{1009, 1010, 1011, 1012};
2097const mat4 OutputComposeSurfacesTest::kDefaultColorTransformMat{mat4() * 0.5};
2098
2099// TODO(b/121291683): Expand unit test coverage for composeSurfaces beyond these
2100// basic tests.
2101
2102TEST_F(OutputComposeSurfacesTest, doesNothingIfNoClientComposition) {
2103 mOutput.editState().usesClientComposition = false;
2104
2105 Region debugRegion;
Lloyd Piqued3d69882019-02-28 16:03:46 -08002106 std::optional<base::unique_fd> readyFence = mOutput.composeSurfaces(debugRegion);
2107 EXPECT_TRUE(readyFence);
Lloyd Pique56eba802019-08-28 15:45:25 -07002108}
2109
2110TEST_F(OutputComposeSurfacesTest, worksIfNoClientLayersQueued) {
2111 const Region kDebugRegion{Rect{100, 101, 102, 103}};
2112
2113 constexpr float kDefaultMaxLuminance = 1.0f;
2114 constexpr float kDefaultAvgLuminance = 0.7f;
2115 constexpr float kDefaultMinLuminance = 0.1f;
2116 HdrCapabilities HdrCapabilities{{},
2117 kDefaultMaxLuminance,
2118 kDefaultAvgLuminance,
2119 kDefaultMinLuminance};
2120
2121 EXPECT_CALL(mRenderEngine, supportsProtectedContent()).WillOnce(Return(false));
2122 EXPECT_CALL(mRenderEngine, drawLayers(_, _, _, true, _, _)).Times(1);
2123
2124 EXPECT_CALL(*mDisplayColorProfile, hasWideColorGamut()).WillOnce(Return(true));
2125 EXPECT_CALL(*mDisplayColorProfile, getHdrCapabilities()).WillOnce(ReturnRef(HdrCapabilities));
2126
2127 EXPECT_CALL(*mRenderSurface, dequeueBuffer(_)).WillOnce(Return(mOutputBuffer));
2128
2129 EXPECT_CALL(mOutput, getSkipColorTransform()).WillOnce(Return(false));
2130 EXPECT_CALL(mOutput, generateClientCompositionRequests(false, _)).Times(1);
2131 EXPECT_CALL(mOutput, appendRegionFlashRequests(RegionEq(kDebugRegion), _)).Times(1);
2132 EXPECT_CALL(mOutput, setExpensiveRenderingExpected(true)).Times(1);
2133 EXPECT_CALL(mOutput, setExpensiveRenderingExpected(false)).Times(1);
2134
Lloyd Piqued3d69882019-02-28 16:03:46 -08002135 std::optional<base::unique_fd> readyFence = mOutput.composeSurfaces(kDebugRegion);
2136 EXPECT_TRUE(readyFence);
Lloyd Pique56eba802019-08-28 15:45:25 -07002137}
2138
2139/*
2140 * Output::generateClientCompositionRequests()
2141 */
2142
2143struct GenerateClientCompositionRequestsTest : public testing::Test {
Lloyd Piquefaa3f192019-11-14 14:05:09 -08002144 struct OutputPartialMock : public OutputPartialMockBase {
Lloyd Piquea38ea7e2019-04-16 18:10:26 -07002145 // compositionengine::Output overrides
Lloyd Pique56eba802019-08-28 15:45:25 -07002146 std::vector<renderengine::LayerSettings> generateClientCompositionRequests(
2147 bool supportsProtectedContent, Region& clearRegion) override {
2148 return impl::Output::generateClientCompositionRequests(supportsProtectedContent,
2149 clearRegion);
2150 }
2151 };
2152
2153 GenerateClientCompositionRequestsTest() {
2154 mOutput.setDisplayColorProfileForTest(
2155 std::unique_ptr<DisplayColorProfile>(mDisplayColorProfile));
2156 mOutput.setRenderSurfaceForTest(std::unique_ptr<RenderSurface>(mRenderSurface));
2157 }
2158
Lloyd Pique56eba802019-08-28 15:45:25 -07002159 mock::DisplayColorProfile* mDisplayColorProfile = new StrictMock<mock::DisplayColorProfile>();
2160 mock::RenderSurface* mRenderSurface = new StrictMock<mock::RenderSurface>();
Lloyd Piquea38ea7e2019-04-16 18:10:26 -07002161 StrictMock<OutputPartialMock> mOutput;
Lloyd Pique56eba802019-08-28 15:45:25 -07002162};
2163
2164// TODO(b/121291683): Add more unit test coverage for generateClientCompositionRequests
2165
2166TEST_F(GenerateClientCompositionRequestsTest, worksForLandscapeModeSplitScreen) {
2167 // In split-screen landscape mode, the screen is rotated 90 degrees, with
2168 // one layer on the left covering the left side of the output, and one layer
2169 // on the right covering that side of the output.
2170
Lloyd Pique01c77c12019-04-17 12:48:32 -07002171 StrictMock<mock::OutputLayer> leftOutputLayer;
2172 StrictMock<mock::OutputLayer> rightOutputLayer;
Lloyd Pique56eba802019-08-28 15:45:25 -07002173
2174 StrictMock<mock::Layer> leftLayer;
2175 StrictMock<mock::LayerFE> leftLayerFE;
2176 StrictMock<mock::Layer> rightLayer;
2177 StrictMock<mock::LayerFE> rightLayerFE;
2178
2179 impl::OutputLayerCompositionState leftOutputLayerState;
2180 leftOutputLayerState.clearClientTarget = false;
Lloyd Piquea2468662019-03-07 21:31:06 -08002181 leftOutputLayerState.visibleRegion = Region{Rect{0, 0, 1000, 1000}};
Lloyd Pique56eba802019-08-28 15:45:25 -07002182
Lloyd Pique9755fb72019-03-26 14:44:40 -07002183 LayerFECompositionState leftLayerFEState;
2184 leftLayerFEState.isOpaque = true;
Lloyd Pique56eba802019-08-28 15:45:25 -07002185
2186 const half3 leftLayerColor{1.f, 0.f, 0.f};
2187 renderengine::LayerSettings leftLayerRESettings;
2188 leftLayerRESettings.source.solidColor = leftLayerColor;
2189
2190 impl::OutputLayerCompositionState rightOutputLayerState;
2191 rightOutputLayerState.clearClientTarget = false;
Lloyd Piquea2468662019-03-07 21:31:06 -08002192 rightOutputLayerState.visibleRegion = Region{Rect{1000, 0, 2000, 1000}};
Lloyd Pique56eba802019-08-28 15:45:25 -07002193
Lloyd Pique9755fb72019-03-26 14:44:40 -07002194 LayerFECompositionState rightLayerFEState;
2195 rightLayerFEState.isOpaque = true;
Lloyd Pique56eba802019-08-28 15:45:25 -07002196
2197 const half3 rightLayerColor{0.f, 1.f, 0.f};
2198 renderengine::LayerSettings rightLayerRESettings;
2199 rightLayerRESettings.source.solidColor = rightLayerColor;
2200
Lloyd Pique01c77c12019-04-17 12:48:32 -07002201 EXPECT_CALL(leftOutputLayer, getState()).WillRepeatedly(ReturnRef(leftOutputLayerState));
2202 EXPECT_CALL(leftOutputLayer, getLayer()).WillRepeatedly(ReturnRef(leftLayer));
2203 EXPECT_CALL(leftOutputLayer, getLayerFE()).WillRepeatedly(ReturnRef(leftLayerFE));
2204 EXPECT_CALL(leftOutputLayer, requiresClientComposition()).WillRepeatedly(Return(true));
2205 EXPECT_CALL(leftOutputLayer, needsFiltering()).WillRepeatedly(Return(false));
Lloyd Pique9755fb72019-03-26 14:44:40 -07002206 EXPECT_CALL(leftLayer, getFEState()).WillRepeatedly(ReturnRef(leftLayerFEState));
Lloyd Pique56eba802019-08-28 15:45:25 -07002207 EXPECT_CALL(leftLayerFE, prepareClientComposition(_)).WillOnce(Return(leftLayerRESettings));
Adithya Srinivasanb69e0762019-11-11 18:39:53 -08002208 EXPECT_CALL(leftOutputLayer, editState()).WillRepeatedly(ReturnRef(leftOutputLayerState));
Lloyd Pique56eba802019-08-28 15:45:25 -07002209
Lloyd Pique01c77c12019-04-17 12:48:32 -07002210 EXPECT_CALL(rightOutputLayer, getState()).WillRepeatedly(ReturnRef(rightOutputLayerState));
2211 EXPECT_CALL(rightOutputLayer, getLayer()).WillRepeatedly(ReturnRef(rightLayer));
2212 EXPECT_CALL(rightOutputLayer, getLayerFE()).WillRepeatedly(ReturnRef(rightLayerFE));
2213 EXPECT_CALL(rightOutputLayer, requiresClientComposition()).WillRepeatedly(Return(true));
2214 EXPECT_CALL(rightOutputLayer, needsFiltering()).WillRepeatedly(Return(false));
Lloyd Pique9755fb72019-03-26 14:44:40 -07002215 EXPECT_CALL(rightLayer, getFEState()).WillRepeatedly(ReturnRef(rightLayerFEState));
Lloyd Pique56eba802019-08-28 15:45:25 -07002216 EXPECT_CALL(rightLayerFE, prepareClientComposition(_)).WillOnce(Return(rightLayerRESettings));
Adithya Srinivasanb69e0762019-11-11 18:39:53 -08002217 EXPECT_CALL(rightOutputLayer, editState()).WillRepeatedly(ReturnRef(rightOutputLayerState));
Lloyd Pique56eba802019-08-28 15:45:25 -07002218
Lloyd Pique01c77c12019-04-17 12:48:32 -07002219 EXPECT_CALL(mOutput, getOutputLayerCount()).WillRepeatedly(Return(2u));
2220 EXPECT_CALL(mOutput, getOutputLayerOrderedByZByIndex(0u))
2221 .WillRepeatedly(Return(&leftOutputLayer));
2222 EXPECT_CALL(mOutput, getOutputLayerOrderedByZByIndex(1u))
2223 .WillRepeatedly(Return(&rightOutputLayer));
Lloyd Pique56eba802019-08-28 15:45:25 -07002224
2225 const Rect kPortraitFrame(0, 0, 1000, 2000);
2226 const Rect kPortraitViewport(0, 0, 2000, 1000);
2227 const Rect kPortraitScissor(0, 0, 1000, 2000);
2228 const uint32_t kPortraitOrientation = TR_ROT_90;
2229
2230 mOutput.editState().frame = kPortraitFrame;
2231 mOutput.editState().viewport = kPortraitViewport;
2232 mOutput.editState().scissor = kPortraitScissor;
2233 mOutput.editState().transform = ui::Transform{kPortraitOrientation};
2234 mOutput.editState().orientation = kPortraitOrientation;
2235 mOutput.editState().needsFiltering = true;
2236 mOutput.editState().isSecure = false;
2237
2238 constexpr bool supportsProtectedContent = false;
2239 Region clearRegion;
2240 auto requests =
2241 mOutput.generateClientCompositionRequests(supportsProtectedContent, clearRegion);
2242
2243 ASSERT_EQ(2u, requests.size());
2244 EXPECT_EQ(leftLayerColor, requests[0].source.solidColor);
2245 EXPECT_EQ(rightLayerColor, requests[1].source.solidColor);
2246}
2247
2248TEST_F(GenerateClientCompositionRequestsTest, ignoresLayersThatDoNotIntersectWithViewport) {
2249 // Layers whose visible region does not intersect with the viewport will be
2250 // skipped when generating client composition request state.
2251
Lloyd Pique01c77c12019-04-17 12:48:32 -07002252 StrictMock<mock::OutputLayer> outputLayer;
Lloyd Pique56eba802019-08-28 15:45:25 -07002253 StrictMock<mock::Layer> layer;
2254 StrictMock<mock::LayerFE> layerFE;
2255
2256 impl::OutputLayerCompositionState outputLayerState;
2257 outputLayerState.clearClientTarget = false;
Lloyd Piquea2468662019-03-07 21:31:06 -08002258 outputLayerState.visibleRegion = Region{Rect{3000, 0, 4000, 1000}};
Lloyd Pique56eba802019-08-28 15:45:25 -07002259
Lloyd Pique9755fb72019-03-26 14:44:40 -07002260 LayerFECompositionState layerFEState;
2261 layerFEState.isOpaque = true;
Lloyd Pique56eba802019-08-28 15:45:25 -07002262
Lloyd Pique01c77c12019-04-17 12:48:32 -07002263 EXPECT_CALL(outputLayer, getState()).WillRepeatedly(ReturnRef(outputLayerState));
2264 EXPECT_CALL(outputLayer, getLayer()).WillRepeatedly(ReturnRef(layer));
2265 EXPECT_CALL(outputLayer, getLayerFE()).WillRepeatedly(ReturnRef(layerFE));
2266 EXPECT_CALL(outputLayer, requiresClientComposition()).WillRepeatedly(Return(true));
2267 EXPECT_CALL(outputLayer, needsFiltering()).WillRepeatedly(Return(false));
Lloyd Pique9755fb72019-03-26 14:44:40 -07002268 EXPECT_CALL(layer, getFEState()).WillRepeatedly(ReturnRef(layerFEState));
Lloyd Pique56eba802019-08-28 15:45:25 -07002269 EXPECT_CALL(layerFE, prepareClientComposition(_)).Times(0);
Adithya Srinivasanb69e0762019-11-11 18:39:53 -08002270 EXPECT_CALL(outputLayer, editState()).WillRepeatedly(ReturnRef(outputLayerState));
Lloyd Pique56eba802019-08-28 15:45:25 -07002271
Lloyd Pique01c77c12019-04-17 12:48:32 -07002272 EXPECT_CALL(mOutput, getOutputLayerCount()).WillRepeatedly(Return(1u));
2273 EXPECT_CALL(mOutput, getOutputLayerOrderedByZByIndex(0u)).WillRepeatedly(Return(&outputLayer));
Lloyd Pique56eba802019-08-28 15:45:25 -07002274
2275 const Rect kPortraitFrame(0, 0, 1000, 2000);
2276 const Rect kPortraitViewport(0, 0, 2000, 1000);
2277 const Rect kPortraitScissor(0, 0, 1000, 2000);
2278 const uint32_t kPortraitOrientation = TR_ROT_90;
2279
2280 mOutput.editState().frame = kPortraitFrame;
2281 mOutput.editState().viewport = kPortraitViewport;
2282 mOutput.editState().scissor = kPortraitScissor;
2283 mOutput.editState().transform = ui::Transform{kPortraitOrientation};
2284 mOutput.editState().orientation = kPortraitOrientation;
2285 mOutput.editState().needsFiltering = true;
2286 mOutput.editState().isSecure = false;
2287
2288 constexpr bool supportsProtectedContent = false;
2289 Region clearRegion;
2290 auto requests =
2291 mOutput.generateClientCompositionRequests(supportsProtectedContent, clearRegion);
2292
2293 EXPECT_EQ(0u, requests.size());
2294}
2295
Lloyd Piquec2d54d42019-08-28 18:04:21 -07002296TEST_F(GenerateClientCompositionRequestsTest, clearsDeviceLayesAfterFirst) {
2297 // If client composition is performed with some layers set to use device
2298 // composition, device layers after the first layer (device or client) will
2299 // clear the frame buffer if they are opaque and if that layer has a flag
2300 // set to do so. The first layer is skipped as the frame buffer is already
2301 // expected to be clear.
2302
Lloyd Pique01c77c12019-04-17 12:48:32 -07002303 StrictMock<mock::OutputLayer> leftOutputLayer;
2304 StrictMock<mock::OutputLayer> rightOutputLayer;
Lloyd Piquec2d54d42019-08-28 18:04:21 -07002305
2306 StrictMock<mock::Layer> leftLayer;
2307 StrictMock<mock::LayerFE> leftLayerFE;
2308 StrictMock<mock::Layer> rightLayer;
2309 StrictMock<mock::LayerFE> rightLayerFE;
2310
2311 impl::OutputLayerCompositionState leftOutputLayerState;
2312 leftOutputLayerState.clearClientTarget = true;
Lloyd Piquea2468662019-03-07 21:31:06 -08002313 leftOutputLayerState.visibleRegion = Region{Rect{0, 0, 1000, 1000}};
Lloyd Piquec2d54d42019-08-28 18:04:21 -07002314
Lloyd Pique9755fb72019-03-26 14:44:40 -07002315 LayerFECompositionState leftLayerFEState;
2316 leftLayerFEState.isOpaque = true;
Lloyd Piquec2d54d42019-08-28 18:04:21 -07002317
2318 impl::OutputLayerCompositionState rightOutputLayerState;
2319 rightOutputLayerState.clearClientTarget = true;
Lloyd Piquea2468662019-03-07 21:31:06 -08002320 rightOutputLayerState.visibleRegion = Region{Rect{1000, 0, 2000, 1000}};
Lloyd Piquec2d54d42019-08-28 18:04:21 -07002321
Lloyd Pique9755fb72019-03-26 14:44:40 -07002322 LayerFECompositionState rightLayerFEState;
2323 rightLayerFEState.isOpaque = true;
Lloyd Piquec2d54d42019-08-28 18:04:21 -07002324
2325 const half3 rightLayerColor{0.f, 1.f, 0.f};
2326 renderengine::LayerSettings rightLayerRESettings;
2327 rightLayerRESettings.geometry.boundaries = FloatRect{456, 0, 0, 0};
2328 rightLayerRESettings.source.solidColor = rightLayerColor;
2329
Lloyd Pique01c77c12019-04-17 12:48:32 -07002330 EXPECT_CALL(leftOutputLayer, getState()).WillRepeatedly(ReturnRef(leftOutputLayerState));
2331 EXPECT_CALL(leftOutputLayer, getLayer()).WillRepeatedly(ReturnRef(leftLayer));
2332 EXPECT_CALL(leftOutputLayer, getLayerFE()).WillRepeatedly(ReturnRef(leftLayerFE));
2333 EXPECT_CALL(leftOutputLayer, requiresClientComposition()).WillRepeatedly(Return(false));
2334 EXPECT_CALL(leftOutputLayer, needsFiltering()).WillRepeatedly(Return(false));
Lloyd Pique9755fb72019-03-26 14:44:40 -07002335 EXPECT_CALL(leftLayer, getFEState()).WillRepeatedly(ReturnRef(leftLayerFEState));
Adithya Srinivasanb69e0762019-11-11 18:39:53 -08002336 EXPECT_CALL(leftOutputLayer, editState()).WillRepeatedly(ReturnRef(leftOutputLayerState));
Lloyd Piquec2d54d42019-08-28 18:04:21 -07002337
Lloyd Pique01c77c12019-04-17 12:48:32 -07002338 EXPECT_CALL(rightOutputLayer, getState()).WillRepeatedly(ReturnRef(rightOutputLayerState));
2339 EXPECT_CALL(rightOutputLayer, getLayer()).WillRepeatedly(ReturnRef(rightLayer));
2340 EXPECT_CALL(rightOutputLayer, getLayerFE()).WillRepeatedly(ReturnRef(rightLayerFE));
2341 EXPECT_CALL(rightOutputLayer, requiresClientComposition()).WillRepeatedly(Return(false));
2342 EXPECT_CALL(rightOutputLayer, needsFiltering()).WillRepeatedly(Return(false));
Lloyd Pique9755fb72019-03-26 14:44:40 -07002343 EXPECT_CALL(rightLayer, getFEState()).WillRepeatedly(ReturnRef(rightLayerFEState));
Lloyd Piquec2d54d42019-08-28 18:04:21 -07002344 EXPECT_CALL(rightLayerFE, prepareClientComposition(_)).WillOnce(Return(rightLayerRESettings));
Adithya Srinivasanb69e0762019-11-11 18:39:53 -08002345 EXPECT_CALL(rightOutputLayer, editState()).WillRepeatedly(ReturnRef(rightOutputLayerState));
Lloyd Piquec2d54d42019-08-28 18:04:21 -07002346
Lloyd Pique01c77c12019-04-17 12:48:32 -07002347 EXPECT_CALL(mOutput, getOutputLayerCount()).WillRepeatedly(Return(2u));
2348 EXPECT_CALL(mOutput, getOutputLayerOrderedByZByIndex(0u))
2349 .WillRepeatedly(Return(&leftOutputLayer));
2350 EXPECT_CALL(mOutput, getOutputLayerOrderedByZByIndex(1u))
2351 .WillRepeatedly(Return(&rightOutputLayer));
Lloyd Piquec2d54d42019-08-28 18:04:21 -07002352
2353 const Rect kPortraitFrame(0, 0, 1000, 2000);
2354 const Rect kPortraitViewport(0, 0, 2000, 1000);
2355 const Rect kPortraitScissor(0, 0, 1000, 2000);
2356 const uint32_t kPortraitOrientation = TR_ROT_90;
2357
2358 mOutput.editState().frame = kPortraitFrame;
2359 mOutput.editState().viewport = kPortraitViewport;
2360 mOutput.editState().scissor = kPortraitScissor;
2361 mOutput.editState().transform = ui::Transform{kPortraitOrientation};
2362 mOutput.editState().orientation = kPortraitOrientation;
2363 mOutput.editState().needsFiltering = true;
2364 mOutput.editState().isSecure = false;
2365
2366 constexpr bool supportsProtectedContent = false;
2367 Region clearRegion;
2368 auto requests =
2369 mOutput.generateClientCompositionRequests(supportsProtectedContent, clearRegion);
2370
2371 const half3 clearColor{0.f, 0.f, 0.f};
2372
2373 ASSERT_EQ(1u, requests.size());
2374 EXPECT_EQ(456.f, requests[0].geometry.boundaries.left);
2375 EXPECT_EQ(clearColor, requests[0].source.solidColor);
2376}
2377
Lloyd Pique32cbe282018-10-19 13:09:22 -07002378} // namespace
2379} // namespace android::compositionengine