blob: 51e19562c838cd8a287739333f19bfe572e1f080 [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 Piqueb62cebc2019-11-20 18:31:52 -0800806 * Output::prepare()
807 */
808
809struct OutputPrepareTest : public testing::Test {
810 struct OutputPartialMock : public OutputPartialMockBase {
811 // Sets up the helper functions called by the function under test to use
812 // mock implementations.
813 MOCK_METHOD2(rebuildLayerStacks,
814 void(const compositionengine::CompositionRefreshArgs&,
815 compositionengine::LayerFESet&));
816 };
817
818 StrictMock<OutputPartialMock> mOutput;
819 CompositionRefreshArgs mRefreshArgs;
820 compositionengine::LayerFESet mGeomSnapshots;
821};
822
823TEST_F(OutputPrepareTest, justInvokesRebuildLayerStacks) {
824 InSequence seq;
825 EXPECT_CALL(mOutput, rebuildLayerStacks(Ref(mRefreshArgs), Ref(mGeomSnapshots)));
826
827 mOutput.prepare(mRefreshArgs, mGeomSnapshots);
828}
829
830/*
831 * Output::rebuildLayerStacks()
832 */
833
834struct OutputRebuildLayerStacksTest : public testing::Test {
835 struct OutputPartialMock : public OutputPartialMockBase {
836 // Sets up the helper functions called by the function under test to use
837 // mock implementations.
838 MOCK_METHOD2(collectVisibleLayers,
839 void(const compositionengine::CompositionRefreshArgs&,
840 compositionengine::Output::CoverageState&));
841 };
842
843 OutputRebuildLayerStacksTest() {
844 mOutput.mState.isEnabled = true;
845 mOutput.mState.transform = kIdentityTransform;
846 mOutput.mState.bounds = kOutputBounds;
847
848 mRefreshArgs.updatingOutputGeometryThisFrame = true;
849
850 mCoverageAboveCoveredLayersToSet = Region(Rect(0, 0, 10, 10));
851
852 EXPECT_CALL(mOutput, collectVisibleLayers(Ref(mRefreshArgs), _))
853 .WillRepeatedly(Invoke(this, &OutputRebuildLayerStacksTest::setTestCoverageValues));
854 }
855
856 void setTestCoverageValues(const CompositionRefreshArgs&,
857 compositionengine::Output::CoverageState& state) {
858 state.aboveCoveredLayers = mCoverageAboveCoveredLayersToSet;
859 state.aboveOpaqueLayers = mCoverageAboveOpaqueLayersToSet;
860 state.dirtyRegion = mCoverageDirtyRegionToSet;
861 }
862
863 static const ui::Transform kIdentityTransform;
864 static const ui::Transform kRotate90Transform;
865 static const Rect kOutputBounds;
866
867 StrictMock<OutputPartialMock> mOutput;
868 CompositionRefreshArgs mRefreshArgs;
869 compositionengine::LayerFESet mGeomSnapshots;
870 Region mCoverageAboveCoveredLayersToSet;
871 Region mCoverageAboveOpaqueLayersToSet;
872 Region mCoverageDirtyRegionToSet;
873};
874
875const ui::Transform OutputRebuildLayerStacksTest::kIdentityTransform{TR_IDENT, 1920, 1080};
876const ui::Transform OutputRebuildLayerStacksTest::kRotate90Transform{TR_ROT_90, 1920, 1080};
877const Rect OutputRebuildLayerStacksTest::kOutputBounds{0, 0, 1920, 1080};
878
879TEST_F(OutputRebuildLayerStacksTest, doesNothingIfNotEnabled) {
880 mOutput.mState.isEnabled = false;
881
882 mOutput.rebuildLayerStacks(mRefreshArgs, mGeomSnapshots);
883}
884
885TEST_F(OutputRebuildLayerStacksTest, doesNothingIfNotUpdatingGeometryThisFrame) {
886 mRefreshArgs.updatingOutputGeometryThisFrame = false;
887
888 mOutput.rebuildLayerStacks(mRefreshArgs, mGeomSnapshots);
889}
890
891TEST_F(OutputRebuildLayerStacksTest, computesUndefinedRegionWithNoRotationAndFullCoverage) {
892 mOutput.mState.transform = kIdentityTransform;
893
894 mCoverageAboveOpaqueLayersToSet = Region(Rect(0, 0, 1920, 1080));
895
896 mOutput.rebuildLayerStacks(mRefreshArgs, mGeomSnapshots);
897
898 EXPECT_THAT(mOutput.mState.undefinedRegion, RegionEq(Region(Rect(0, 0, 0, 0))));
899}
900
901TEST_F(OutputRebuildLayerStacksTest, computesUndefinedRegionWithNoRotationAndPartialCoverage) {
902 mOutput.mState.transform = kIdentityTransform;
903
904 mCoverageAboveOpaqueLayersToSet = Region(Rect(0, 0, 960, 1080));
905
906 mOutput.rebuildLayerStacks(mRefreshArgs, mGeomSnapshots);
907
908 EXPECT_THAT(mOutput.mState.undefinedRegion, RegionEq(Region(Rect(960, 0, 1920, 1080))));
909}
910
911TEST_F(OutputRebuildLayerStacksTest, computesUndefinedRegionWith90RotationAndFullCoverage) {
912 mOutput.mState.transform = kRotate90Transform;
913
914 mCoverageAboveOpaqueLayersToSet = Region(Rect(0, 0, 1080, 1920));
915
916 mOutput.rebuildLayerStacks(mRefreshArgs, mGeomSnapshots);
917
918 EXPECT_THAT(mOutput.mState.undefinedRegion, RegionEq(Region(Rect(0, 0, 0, 0))));
919}
920
921TEST_F(OutputRebuildLayerStacksTest, computesUndefinedRegionWith90RotationAndPartialCoverage) {
922 mOutput.mState.transform = kRotate90Transform;
923
924 mCoverageAboveOpaqueLayersToSet = Region(Rect(0, 0, 1080, 960));
925
926 mOutput.rebuildLayerStacks(mRefreshArgs, mGeomSnapshots);
927
928 EXPECT_THAT(mOutput.mState.undefinedRegion, RegionEq(Region(Rect(0, 0, 960, 1080))));
929}
930
931TEST_F(OutputRebuildLayerStacksTest, addsToDirtyRegionWithNoRotation) {
932 mOutput.mState.transform = kIdentityTransform;
933 mOutput.mState.dirtyRegion = Region(Rect(960, 0, 1920, 1080));
934
935 mCoverageDirtyRegionToSet = Region(Rect(0, 0, 960, 1080));
936
937 mOutput.rebuildLayerStacks(mRefreshArgs, mGeomSnapshots);
938
939 EXPECT_THAT(mOutput.mState.dirtyRegion, RegionEq(Region(Rect(0, 0, 1920, 1080))));
940}
941
942TEST_F(OutputRebuildLayerStacksTest, addsToDirtyRegionWith90Rotation) {
943 mOutput.mState.transform = kRotate90Transform;
944 mOutput.mState.dirtyRegion = Region(Rect(0, 960, 1080, 1920));
945
946 mCoverageDirtyRegionToSet = Region(Rect(0, 0, 1080, 960));
947
948 mOutput.rebuildLayerStacks(mRefreshArgs, mGeomSnapshots);
949
950 EXPECT_THAT(mOutput.mState.dirtyRegion, RegionEq(Region(Rect(0, 0, 1080, 1920))));
951}
952
953/*
954 * Output::collectVisibleLayers()
955 */
956
957// TODO(b/144060211) - Add coverage
958
959/*
960 * Output::ensureOutputLayerIfVisible()
961 */
962
963// TODO(b/144060211) - Add coverage
964
965/*
Lloyd Piquefaa3f192019-11-14 14:05:09 -0800966 * Output::present()
967 */
968
969struct OutputPresentTest : public testing::Test {
970 struct OutputPartialMock : public OutputPartialMockBase {
971 // All child helper functions Output::present() are defined as mocks,
972 // and those are tested separately, allowing the present() test to
973 // just cover the high level flow.
974 MOCK_METHOD1(updateColorProfile, void(const compositionengine::CompositionRefreshArgs&));
975 MOCK_METHOD1(updateAndWriteCompositionState,
976 void(const compositionengine::CompositionRefreshArgs&));
977 MOCK_METHOD1(setColorTransform, void(const compositionengine::CompositionRefreshArgs&));
978 MOCK_METHOD0(beginFrame, void());
979 MOCK_METHOD0(prepareFrame, void());
980 MOCK_METHOD1(devOptRepaintFlash, void(const compositionengine::CompositionRefreshArgs&));
981 MOCK_METHOD1(finishFrame, void(const compositionengine::CompositionRefreshArgs&));
982 MOCK_METHOD0(postFramebuffer, void());
983 };
984
985 StrictMock<OutputPartialMock> mOutput;
986};
987
988TEST_F(OutputPresentTest, justInvokesChildFunctionsInSequence) {
989 CompositionRefreshArgs args;
990
991 InSequence seq;
992 EXPECT_CALL(mOutput, updateColorProfile(Ref(args)));
993 EXPECT_CALL(mOutput, updateAndWriteCompositionState(Ref(args)));
994 EXPECT_CALL(mOutput, setColorTransform(Ref(args)));
995 EXPECT_CALL(mOutput, beginFrame());
996 EXPECT_CALL(mOutput, prepareFrame());
997 EXPECT_CALL(mOutput, devOptRepaintFlash(Ref(args)));
998 EXPECT_CALL(mOutput, finishFrame(Ref(args)));
999 EXPECT_CALL(mOutput, postFramebuffer());
1000
1001 mOutput.present(args);
1002}
1003
1004/*
1005 * Output::updateColorProfile()
1006 */
1007
Lloyd Pique17ca7422019-11-14 14:24:10 -08001008struct OutputUpdateColorProfileTest : public testing::Test {
1009 using TestType = OutputUpdateColorProfileTest;
1010
1011 struct OutputPartialMock : public OutputPartialMockBase {
1012 // All child helper functions Output::present() are defined as mocks,
1013 // and those are tested separately, allowing the present() test to
1014 // just cover the high level flow.
1015 MOCK_METHOD1(setColorProfile, void(const ColorProfile&));
1016 };
1017
1018 struct Layer {
1019 Layer() {
1020 EXPECT_CALL(mOutputLayer, getLayer()).WillRepeatedly(ReturnRef(mLayer));
1021 EXPECT_CALL(mOutputLayer, getLayerFE()).WillRepeatedly(ReturnRef(mLayerFE));
1022 EXPECT_CALL(mLayer, getFEState()).WillRepeatedly(ReturnRef(mLayerFEState));
1023 }
1024
1025 StrictMock<mock::OutputLayer> mOutputLayer;
1026 StrictMock<mock::Layer> mLayer;
1027 StrictMock<mock::LayerFE> mLayerFE;
1028 LayerFECompositionState mLayerFEState;
1029 };
1030
1031 OutputUpdateColorProfileTest() {
1032 mOutput.setDisplayColorProfileForTest(
1033 std::unique_ptr<DisplayColorProfile>(mDisplayColorProfile));
1034 mOutput.setRenderSurfaceForTest(std::unique_ptr<RenderSurface>(mRenderSurface));
1035
1036 EXPECT_CALL(mOutput, getOutputLayerOrderedByZByIndex(0))
1037 .WillRepeatedly(Return(&mLayer1.mOutputLayer));
1038 EXPECT_CALL(mOutput, getOutputLayerOrderedByZByIndex(1))
1039 .WillRepeatedly(Return(&mLayer2.mOutputLayer));
1040 EXPECT_CALL(mOutput, getOutputLayerOrderedByZByIndex(2))
1041 .WillRepeatedly(Return(&mLayer3.mOutputLayer));
1042 }
1043
1044 struct ExecuteState : public CallOrderStateMachineHelper<TestType, ExecuteState> {
1045 void execute() { getInstance()->mOutput.updateColorProfile(getInstance()->mRefreshArgs); }
1046 };
1047
1048 mock::DisplayColorProfile* mDisplayColorProfile = new StrictMock<mock::DisplayColorProfile>();
1049 mock::RenderSurface* mRenderSurface = new StrictMock<mock::RenderSurface>();
1050 StrictMock<OutputPartialMock> mOutput;
1051
1052 Layer mLayer1;
1053 Layer mLayer2;
1054 Layer mLayer3;
1055
1056 CompositionRefreshArgs mRefreshArgs;
1057};
1058
1059// TODO(b/144522012): Refactor Output::updateColorProfile and the related code
1060// to make it easier to write unit tests.
1061
1062TEST_F(OutputUpdateColorProfileTest, setsAColorProfileWhenUnmanaged) {
1063 // When the outputColorSetting is set to kUnmanaged, the implementation sets
1064 // a simple default color profile without looking at anything else.
1065
1066 EXPECT_CALL(mOutput, getOutputLayerCount()).WillRepeatedly(Return(3));
1067 EXPECT_CALL(mOutput,
1068 setColorProfile(ColorProfileEq(
1069 ColorProfile{ui::ColorMode::NATIVE, ui::Dataspace::UNKNOWN,
1070 ui::RenderIntent::COLORIMETRIC, ui::Dataspace::UNKNOWN})));
1071
1072 mRefreshArgs.outputColorSetting = OutputColorSetting::kUnmanaged;
1073 mRefreshArgs.colorSpaceAgnosticDataspace = ui::Dataspace::UNKNOWN;
1074
1075 mOutput.updateColorProfile(mRefreshArgs);
1076}
1077
1078struct OutputUpdateColorProfileTest_GetBestColorModeResultBecomesSetProfile
1079 : public OutputUpdateColorProfileTest {
1080 OutputUpdateColorProfileTest_GetBestColorModeResultBecomesSetProfile() {
1081 EXPECT_CALL(mOutput, getOutputLayerCount()).WillRepeatedly(Return(0));
1082 mRefreshArgs.outputColorSetting = OutputColorSetting::kEnhanced;
1083 mRefreshArgs.colorSpaceAgnosticDataspace = ui::Dataspace::UNKNOWN;
1084 }
1085
1086 struct ExpectBestColorModeCallResultUsedToSetColorProfileState
1087 : public CallOrderStateMachineHelper<
1088 TestType, ExpectBestColorModeCallResultUsedToSetColorProfileState> {
1089 [[nodiscard]] auto expectBestColorModeCallResultUsedToSetColorProfile(
1090 ui::ColorMode colorMode, ui::Dataspace dataspace, ui::RenderIntent renderIntent) {
1091 EXPECT_CALL(*getInstance()->mDisplayColorProfile,
1092 getBestColorMode(ui::Dataspace::V0_SRGB, ui::RenderIntent::ENHANCE, _, _,
1093 _))
1094 .WillOnce(DoAll(SetArgPointee<2>(dataspace), SetArgPointee<3>(colorMode),
1095 SetArgPointee<4>(renderIntent)));
1096 EXPECT_CALL(getInstance()->mOutput,
1097 setColorProfile(
1098 ColorProfileEq(ColorProfile{colorMode, dataspace, renderIntent,
1099 ui::Dataspace::UNKNOWN})));
1100 return nextState<ExecuteState>();
1101 }
1102 };
1103
1104 // Call this member function to start using the mini-DSL defined above.
1105 [[nodiscard]] auto verify() {
1106 return ExpectBestColorModeCallResultUsedToSetColorProfileState::make(this);
1107 }
1108};
1109
1110TEST_F(OutputUpdateColorProfileTest_GetBestColorModeResultBecomesSetProfile,
1111 Native_Unknown_Colorimetric_Set) {
1112 verify().expectBestColorModeCallResultUsedToSetColorProfile(ui::ColorMode::NATIVE,
1113 ui::Dataspace::UNKNOWN,
1114 ui::RenderIntent::COLORIMETRIC)
1115 .execute();
1116}
1117
1118TEST_F(OutputUpdateColorProfileTest_GetBestColorModeResultBecomesSetProfile,
1119 DisplayP3_DisplayP3_Enhance_Set) {
1120 verify().expectBestColorModeCallResultUsedToSetColorProfile(ui::ColorMode::DISPLAY_P3,
1121 ui::Dataspace::DISPLAY_P3,
1122 ui::RenderIntent::ENHANCE)
1123 .execute();
1124}
1125
1126struct OutputUpdateColorProfileTest_ColorSpaceAgnosticeDataspaceAffectsSetColorProfile
1127 : public OutputUpdateColorProfileTest {
1128 OutputUpdateColorProfileTest_ColorSpaceAgnosticeDataspaceAffectsSetColorProfile() {
1129 EXPECT_CALL(mOutput, getOutputLayerCount()).WillRepeatedly(Return(0));
1130 EXPECT_CALL(*mDisplayColorProfile,
1131 getBestColorMode(ui::Dataspace::V0_SRGB, ui::RenderIntent::ENHANCE, _, _, _))
1132 .WillRepeatedly(DoAll(SetArgPointee<2>(ui::Dataspace::UNKNOWN),
1133 SetArgPointee<3>(ui::ColorMode::NATIVE),
1134 SetArgPointee<4>(ui::RenderIntent::COLORIMETRIC)));
1135 mRefreshArgs.outputColorSetting = OutputColorSetting::kEnhanced;
1136 }
1137
1138 struct IfColorSpaceAgnosticDataspaceSetToState
1139 : public CallOrderStateMachineHelper<TestType, IfColorSpaceAgnosticDataspaceSetToState> {
1140 [[nodiscard]] auto ifColorSpaceAgnosticDataspaceSetTo(ui::Dataspace dataspace) {
1141 getInstance()->mRefreshArgs.colorSpaceAgnosticDataspace = dataspace;
1142 return nextState<ThenExpectSetColorProfileCallUsesColorSpaceAgnosticDataspaceState>();
1143 }
1144 };
1145
1146 struct ThenExpectSetColorProfileCallUsesColorSpaceAgnosticDataspaceState
1147 : public CallOrderStateMachineHelper<
1148 TestType, ThenExpectSetColorProfileCallUsesColorSpaceAgnosticDataspaceState> {
1149 [[nodiscard]] auto thenExpectSetColorProfileCallUsesColorSpaceAgnosticDataspace(
1150 ui::Dataspace dataspace) {
1151 EXPECT_CALL(getInstance()->mOutput,
1152 setColorProfile(ColorProfileEq(
1153 ColorProfile{ui::ColorMode::NATIVE, ui::Dataspace::UNKNOWN,
1154 ui::RenderIntent::COLORIMETRIC, dataspace})));
1155 return nextState<ExecuteState>();
1156 }
1157 };
1158
1159 // Call this member function to start using the mini-DSL defined above.
1160 [[nodiscard]] auto verify() { return IfColorSpaceAgnosticDataspaceSetToState::make(this); }
1161};
1162
1163TEST_F(OutputUpdateColorProfileTest_ColorSpaceAgnosticeDataspaceAffectsSetColorProfile, DisplayP3) {
1164 verify().ifColorSpaceAgnosticDataspaceSetTo(ui::Dataspace::DISPLAY_P3)
1165 .thenExpectSetColorProfileCallUsesColorSpaceAgnosticDataspace(ui::Dataspace::DISPLAY_P3)
1166 .execute();
1167}
1168
1169TEST_F(OutputUpdateColorProfileTest_ColorSpaceAgnosticeDataspaceAffectsSetColorProfile, V0_SRGB) {
1170 verify().ifColorSpaceAgnosticDataspaceSetTo(ui::Dataspace::V0_SRGB)
1171 .thenExpectSetColorProfileCallUsesColorSpaceAgnosticDataspace(ui::Dataspace::V0_SRGB)
1172 .execute();
1173}
1174
1175struct OutputUpdateColorProfileTest_TopmostLayerPreferenceSetsOutputPreference
1176 : public OutputUpdateColorProfileTest {
1177 // Internally the implementation looks through the dataspaces of all the
1178 // visible layers. The topmost one that also has an actual dataspace
1179 // preference set is used to drive subsequent choices.
1180
1181 OutputUpdateColorProfileTest_TopmostLayerPreferenceSetsOutputPreference() {
1182 mRefreshArgs.outputColorSetting = OutputColorSetting::kEnhanced;
1183 mRefreshArgs.colorSpaceAgnosticDataspace = ui::Dataspace::UNKNOWN;
1184
1185 EXPECT_CALL(mOutput, getOutputLayerCount()).WillRepeatedly(Return(3));
1186 EXPECT_CALL(mOutput, setColorProfile(_)).WillRepeatedly(Return());
1187 }
1188
1189 struct IfTopLayerDataspaceState
1190 : public CallOrderStateMachineHelper<TestType, IfTopLayerDataspaceState> {
1191 [[nodiscard]] auto ifTopLayerIs(ui::Dataspace dataspace) {
1192 getInstance()->mLayer3.mLayerFEState.dataspace = dataspace;
1193 return nextState<AndIfMiddleLayerDataspaceState>();
1194 }
1195 [[nodiscard]] auto ifTopLayerHasNoPreference() {
1196 return ifTopLayerIs(ui::Dataspace::UNKNOWN);
1197 }
1198 };
1199
1200 struct AndIfMiddleLayerDataspaceState
1201 : public CallOrderStateMachineHelper<TestType, AndIfMiddleLayerDataspaceState> {
1202 [[nodiscard]] auto andIfMiddleLayerIs(ui::Dataspace dataspace) {
1203 getInstance()->mLayer2.mLayerFEState.dataspace = dataspace;
1204 return nextState<AndIfBottomLayerDataspaceState>();
1205 }
1206 [[nodiscard]] auto andIfMiddleLayerHasNoPreference() {
1207 return andIfMiddleLayerIs(ui::Dataspace::UNKNOWN);
1208 }
1209 };
1210
1211 struct AndIfBottomLayerDataspaceState
1212 : public CallOrderStateMachineHelper<TestType, AndIfBottomLayerDataspaceState> {
1213 [[nodiscard]] auto andIfBottomLayerIs(ui::Dataspace dataspace) {
1214 getInstance()->mLayer1.mLayerFEState.dataspace = dataspace;
1215 return nextState<ThenExpectBestColorModeCallUsesState>();
1216 }
1217 [[nodiscard]] auto andIfBottomLayerHasNoPreference() {
1218 return andIfBottomLayerIs(ui::Dataspace::UNKNOWN);
1219 }
1220 };
1221
1222 struct ThenExpectBestColorModeCallUsesState
1223 : public CallOrderStateMachineHelper<TestType, ThenExpectBestColorModeCallUsesState> {
1224 [[nodiscard]] auto thenExpectBestColorModeCallUses(ui::Dataspace dataspace) {
1225 EXPECT_CALL(*getInstance()->mDisplayColorProfile,
1226 getBestColorMode(dataspace, _, _, _, _));
1227 return nextState<ExecuteState>();
1228 }
1229 };
1230
1231 // Call this member function to start using the mini-DSL defined above.
1232 [[nodiscard]] auto verify() { return IfTopLayerDataspaceState::make(this); }
1233};
1234
1235TEST_F(OutputUpdateColorProfileTest_TopmostLayerPreferenceSetsOutputPreference,
1236 noStrongLayerPrefenceUses_V0_SRGB) {
1237 // If none of the layers indicate a preference, then V0_SRGB is the
1238 // preferred choice (subject to additional checks).
1239 verify().ifTopLayerHasNoPreference()
1240 .andIfMiddleLayerHasNoPreference()
1241 .andIfBottomLayerHasNoPreference()
1242 .thenExpectBestColorModeCallUses(ui::Dataspace::V0_SRGB)
1243 .execute();
1244}
1245
1246TEST_F(OutputUpdateColorProfileTest_TopmostLayerPreferenceSetsOutputPreference,
1247 ifTopmostUses_DisplayP3_Then_DisplayP3_Chosen) {
1248 // If only the topmost layer has a preference, then that is what is chosen.
1249 verify().ifTopLayerIs(ui::Dataspace::DISPLAY_P3)
1250 .andIfMiddleLayerHasNoPreference()
1251 .andIfBottomLayerHasNoPreference()
1252 .thenExpectBestColorModeCallUses(ui::Dataspace::DISPLAY_P3)
1253 .execute();
1254}
1255
1256TEST_F(OutputUpdateColorProfileTest_TopmostLayerPreferenceSetsOutputPreference,
1257 ifMiddleUses_DisplayP3_Then_DisplayP3_Chosen) {
1258 // If only the middle layer has a preference, that that is what is chosen.
1259 verify().ifTopLayerHasNoPreference()
1260 .andIfMiddleLayerIs(ui::Dataspace::DISPLAY_P3)
1261 .andIfBottomLayerHasNoPreference()
1262 .thenExpectBestColorModeCallUses(ui::Dataspace::DISPLAY_P3)
1263 .execute();
1264}
1265
1266TEST_F(OutputUpdateColorProfileTest_TopmostLayerPreferenceSetsOutputPreference,
1267 ifBottomUses_DisplayP3_Then_DisplayP3_Chosen) {
1268 // If only the middle layer has a preference, that that is what is chosen.
1269 verify().ifTopLayerHasNoPreference()
1270 .andIfMiddleLayerHasNoPreference()
1271 .andIfBottomLayerIs(ui::Dataspace::DISPLAY_P3)
1272 .thenExpectBestColorModeCallUses(ui::Dataspace::DISPLAY_P3)
1273 .execute();
1274}
1275
1276TEST_F(OutputUpdateColorProfileTest_TopmostLayerPreferenceSetsOutputPreference,
1277 ifTopUses_DisplayBT2020_AndBottomUses_DisplayP3_Then_DisplayBT2020_Chosen) {
1278 // If multiple layers have a preference, the topmost value is what is used.
1279 verify().ifTopLayerIs(ui::Dataspace::DISPLAY_BT2020)
1280 .andIfMiddleLayerHasNoPreference()
1281 .andIfBottomLayerIs(ui::Dataspace::DISPLAY_P3)
1282 .thenExpectBestColorModeCallUses(ui::Dataspace::DISPLAY_BT2020)
1283 .execute();
1284}
1285
1286TEST_F(OutputUpdateColorProfileTest_TopmostLayerPreferenceSetsOutputPreference,
1287 ifTopUses_DisplayP3_AndBottomUses_V0_SRGB_Then_DisplayP3_Chosen) {
1288 // If multiple layers have a preference, the topmost value is what is used.
1289 verify().ifTopLayerIs(ui::Dataspace::DISPLAY_P3)
1290 .andIfMiddleLayerHasNoPreference()
1291 .andIfBottomLayerIs(ui::Dataspace::DISPLAY_BT2020)
1292 .thenExpectBestColorModeCallUses(ui::Dataspace::DISPLAY_P3)
1293 .execute();
1294}
1295
1296struct OutputUpdateColorProfileTest_ForceOutputColorOverrides
1297 : public OutputUpdateColorProfileTest {
1298 // If CompositionRefreshArgs::forceOutputColorMode is set to some specific
1299 // values, it overrides the layer dataspace choice.
1300
1301 OutputUpdateColorProfileTest_ForceOutputColorOverrides() {
1302 mRefreshArgs.outputColorSetting = OutputColorSetting::kEnhanced;
1303 mRefreshArgs.colorSpaceAgnosticDataspace = ui::Dataspace::UNKNOWN;
1304
1305 mLayer1.mLayerFEState.dataspace = ui::Dataspace::DISPLAY_BT2020;
1306
1307 EXPECT_CALL(mOutput, getOutputLayerCount()).WillRepeatedly(Return(1));
1308 EXPECT_CALL(mOutput, setColorProfile(_)).WillRepeatedly(Return());
1309 }
1310
1311 struct IfForceOutputColorModeState
1312 : public CallOrderStateMachineHelper<TestType, IfForceOutputColorModeState> {
1313 [[nodiscard]] auto ifForceOutputColorMode(ui::ColorMode colorMode) {
1314 getInstance()->mRefreshArgs.forceOutputColorMode = colorMode;
1315 return nextState<ThenExpectBestColorModeCallUsesState>();
1316 }
1317 [[nodiscard]] auto ifNoOverride() { return ifForceOutputColorMode(ui::ColorMode::NATIVE); }
1318 };
1319
1320 struct ThenExpectBestColorModeCallUsesState
1321 : public CallOrderStateMachineHelper<TestType, ThenExpectBestColorModeCallUsesState> {
1322 [[nodiscard]] auto thenExpectBestColorModeCallUses(ui::Dataspace dataspace) {
1323 EXPECT_CALL(*getInstance()->mDisplayColorProfile,
1324 getBestColorMode(dataspace, _, _, _, _));
1325 return nextState<ExecuteState>();
1326 }
1327 };
1328
1329 // Call this member function to start using the mini-DSL defined above.
1330 [[nodiscard]] auto verify() { return IfForceOutputColorModeState::make(this); }
1331};
1332
1333TEST_F(OutputUpdateColorProfileTest_ForceOutputColorOverrides, NoOverride_DoesNotOverride) {
1334 // By default the layer state is used to set the preferred dataspace
1335 verify().ifNoOverride()
1336 .thenExpectBestColorModeCallUses(ui::Dataspace::DISPLAY_BT2020)
1337 .execute();
1338}
1339
1340TEST_F(OutputUpdateColorProfileTest_ForceOutputColorOverrides, SRGB_Override_USES_V0_SRGB) {
1341 // Setting ui::ColorMode::SRGB overrides it with ui::Dataspace::V0_SRGB
1342 verify().ifForceOutputColorMode(ui::ColorMode::SRGB)
1343 .thenExpectBestColorModeCallUses(ui::Dataspace::V0_SRGB)
1344 .execute();
1345}
1346
1347TEST_F(OutputUpdateColorProfileTest_ForceOutputColorOverrides, DisplayP3_Override_Uses_DisplayP3) {
1348 // Setting ui::ColorMode::DISPLAY_P3 overrides it with ui::Dataspace::DISPLAY_P3
1349 verify().ifForceOutputColorMode(ui::ColorMode::DISPLAY_P3)
1350 .thenExpectBestColorModeCallUses(ui::Dataspace::DISPLAY_P3)
1351 .execute();
1352}
1353
1354// HDR output requires all layers to be compatible with the chosen HDR
1355// dataspace, along with there being proper support.
1356struct OutputUpdateColorProfileTest_Hdr : public OutputUpdateColorProfileTest {
1357 OutputUpdateColorProfileTest_Hdr() {
1358 mRefreshArgs.outputColorSetting = OutputColorSetting::kEnhanced;
1359 mRefreshArgs.colorSpaceAgnosticDataspace = ui::Dataspace::UNKNOWN;
1360 EXPECT_CALL(mOutput, getOutputLayerCount()).WillRepeatedly(Return(2));
1361 EXPECT_CALL(mOutput, setColorProfile(_)).WillRepeatedly(Return());
1362 }
1363
1364 static constexpr ui::Dataspace kNonHdrDataspace = ui::Dataspace::DISPLAY_P3;
1365 static constexpr ui::Dataspace BT2020_PQ = ui::Dataspace::BT2020_PQ;
1366 static constexpr ui::Dataspace BT2020_HLG = ui::Dataspace::BT2020_HLG;
1367 static constexpr ui::Dataspace DISPLAY_P3 = ui::Dataspace::DISPLAY_P3;
1368
1369 struct IfTopLayerDataspaceState
1370 : public CallOrderStateMachineHelper<TestType, IfTopLayerDataspaceState> {
1371 [[nodiscard]] auto ifTopLayerIs(ui::Dataspace dataspace) {
1372 getInstance()->mLayer2.mLayerFEState.dataspace = dataspace;
1373 return nextState<AndTopLayerCompositionTypeState>();
1374 }
1375 [[nodiscard]] auto ifTopLayerIsNotHdr() { return ifTopLayerIs(kNonHdrDataspace); }
1376 };
1377
1378 struct AndTopLayerCompositionTypeState
1379 : public CallOrderStateMachineHelper<TestType, AndTopLayerCompositionTypeState> {
1380 [[nodiscard]] auto andTopLayerIsREComposed(bool renderEngineComposed) {
1381 getInstance()->mLayer2.mLayerFEState.forceClientComposition = renderEngineComposed;
1382 return nextState<AndIfBottomLayerDataspaceState>();
1383 }
1384 };
1385
1386 struct AndIfBottomLayerDataspaceState
1387 : public CallOrderStateMachineHelper<TestType, AndIfBottomLayerDataspaceState> {
1388 [[nodiscard]] auto andIfBottomLayerIs(ui::Dataspace dataspace) {
1389 getInstance()->mLayer1.mLayerFEState.dataspace = dataspace;
1390 return nextState<AndBottomLayerCompositionTypeState>();
1391 }
1392 [[nodiscard]] auto andIfBottomLayerIsNotHdr() {
1393 return andIfBottomLayerIs(kNonHdrDataspace);
1394 }
1395 };
1396
1397 struct AndBottomLayerCompositionTypeState
1398 : public CallOrderStateMachineHelper<TestType, AndBottomLayerCompositionTypeState> {
1399 [[nodiscard]] auto andBottomLayerIsREComposed(bool renderEngineComposed) {
1400 getInstance()->mLayer1.mLayerFEState.forceClientComposition = renderEngineComposed;
1401 return nextState<AndIfHasLegacySupportState>();
1402 }
1403 };
1404
1405 struct AndIfHasLegacySupportState
1406 : public CallOrderStateMachineHelper<TestType, AndIfHasLegacySupportState> {
1407 [[nodiscard]] auto andIfLegacySupportFor(ui::Dataspace dataspace, bool legacySupport) {
1408 EXPECT_CALL(*getInstance()->mDisplayColorProfile, hasLegacyHdrSupport(dataspace))
1409 .WillOnce(Return(legacySupport));
1410 return nextState<ThenExpectBestColorModeCallUsesState>();
1411 }
1412 };
1413
1414 struct ThenExpectBestColorModeCallUsesState
1415 : public CallOrderStateMachineHelper<TestType, ThenExpectBestColorModeCallUsesState> {
1416 [[nodiscard]] auto thenExpectBestColorModeCallUses(ui::Dataspace dataspace) {
1417 EXPECT_CALL(*getInstance()->mDisplayColorProfile,
1418 getBestColorMode(dataspace, _, _, _, _));
1419 return nextState<ExecuteState>();
1420 }
1421 };
1422
1423 // Call this member function to start using the mini-DSL defined above.
1424 [[nodiscard]] auto verify() { return IfTopLayerDataspaceState::make(this); }
1425};
1426
1427TEST_F(OutputUpdateColorProfileTest_Hdr, PQ_HW_On_PQ_HW_Uses_PQ) {
1428 // If all layers use BT2020_PQ, and there are no other special conditions,
1429 // BT2020_PQ is used.
1430 verify().ifTopLayerIs(BT2020_PQ)
1431 .andTopLayerIsREComposed(false)
1432 .andIfBottomLayerIs(BT2020_PQ)
1433 .andBottomLayerIsREComposed(false)
1434 .andIfLegacySupportFor(BT2020_PQ, false)
1435 .thenExpectBestColorModeCallUses(BT2020_PQ)
1436 .execute();
1437}
1438
1439TEST_F(OutputUpdateColorProfileTest_Hdr, PQ_HW_On_PQ_HW_IfPQHasLegacySupport_Uses_DisplayP3) {
1440 // BT2020_PQ is not used if there is only legacy support for it.
1441 verify().ifTopLayerIs(BT2020_PQ)
1442 .andTopLayerIsREComposed(false)
1443 .andIfBottomLayerIs(BT2020_PQ)
1444 .andBottomLayerIsREComposed(false)
1445 .andIfLegacySupportFor(BT2020_PQ, true)
1446 .thenExpectBestColorModeCallUses(DISPLAY_P3)
1447 .execute();
1448}
1449
1450TEST_F(OutputUpdateColorProfileTest_Hdr, PQ_HW_On_PQ_RE_Uses_PQ) {
1451 // BT2020_PQ is still used if the bottom layer is RenderEngine composed.
1452 verify().ifTopLayerIs(BT2020_PQ)
1453 .andTopLayerIsREComposed(false)
1454 .andIfBottomLayerIs(BT2020_PQ)
1455 .andBottomLayerIsREComposed(true)
1456 .andIfLegacySupportFor(BT2020_PQ, false)
1457 .thenExpectBestColorModeCallUses(BT2020_PQ)
1458 .execute();
1459}
1460
1461TEST_F(OutputUpdateColorProfileTest_Hdr, PQ_RE_On_PQ_HW_Uses_DisplayP3) {
1462 // BT2020_PQ is not used if the top layer is RenderEngine composed.
1463 verify().ifTopLayerIs(BT2020_PQ)
1464 .andTopLayerIsREComposed(true)
1465 .andIfBottomLayerIs(BT2020_PQ)
1466 .andBottomLayerIsREComposed(false)
1467 .andIfLegacySupportFor(BT2020_PQ, false)
1468 .thenExpectBestColorModeCallUses(DISPLAY_P3)
1469 .execute();
1470}
1471
1472TEST_F(OutputUpdateColorProfileTest_Hdr, PQ_HW_On_HLG_HW_Uses_PQ) {
1473 // If there is mixed HLG/PQ use, and the topmost layer is PQ, then PQ is used if there
1474 // are no other special conditions.
1475 verify().ifTopLayerIs(BT2020_PQ)
1476 .andTopLayerIsREComposed(false)
1477 .andIfBottomLayerIs(BT2020_HLG)
1478 .andBottomLayerIsREComposed(false)
1479 .andIfLegacySupportFor(BT2020_PQ, false)
1480 .thenExpectBestColorModeCallUses(BT2020_PQ)
1481 .execute();
1482}
1483
1484TEST_F(OutputUpdateColorProfileTest_Hdr, PQ_HW_On_HLG_HW_IfPQHasLegacySupport_Uses_DisplayP3) {
1485 // BT2020_PQ is not used if there is only legacy support for it.
1486 verify().ifTopLayerIs(BT2020_PQ)
1487 .andTopLayerIsREComposed(false)
1488 .andIfBottomLayerIs(BT2020_HLG)
1489 .andBottomLayerIsREComposed(false)
1490 .andIfLegacySupportFor(BT2020_PQ, true)
1491 .thenExpectBestColorModeCallUses(DISPLAY_P3)
1492 .execute();
1493}
1494
1495TEST_F(OutputUpdateColorProfileTest_Hdr, PQ_HW_On_HLG_RE_Uses_PQ) {
1496 // BT2020_PQ is used if the bottom HLG layer is RenderEngine composed.
1497 verify().ifTopLayerIs(BT2020_PQ)
1498 .andTopLayerIsREComposed(false)
1499 .andIfBottomLayerIs(BT2020_HLG)
1500 .andBottomLayerIsREComposed(true)
1501 .andIfLegacySupportFor(BT2020_PQ, false)
1502 .thenExpectBestColorModeCallUses(BT2020_PQ)
1503 .execute();
1504}
1505
1506TEST_F(OutputUpdateColorProfileTest_Hdr, PQ_RE_On_HLG_HW_Uses_DisplayP3) {
1507 // BT2020_PQ is not used if the top PQ layer is RenderEngine composed.
1508 verify().ifTopLayerIs(BT2020_PQ)
1509 .andTopLayerIsREComposed(true)
1510 .andIfBottomLayerIs(BT2020_HLG)
1511 .andBottomLayerIsREComposed(false)
1512 .andIfLegacySupportFor(BT2020_PQ, false)
1513 .thenExpectBestColorModeCallUses(DISPLAY_P3)
1514 .execute();
1515}
1516
1517TEST_F(OutputUpdateColorProfileTest_Hdr, HLG_HW_On_PQ_HW_Uses_PQ) {
1518 // If there is mixed HLG/PQ use, and the topmost layer is HLG, then PQ is
1519 // used if there are no other special conditions.
1520 verify().ifTopLayerIs(BT2020_HLG)
1521 .andTopLayerIsREComposed(false)
1522 .andIfBottomLayerIs(BT2020_PQ)
1523 .andBottomLayerIsREComposed(false)
1524 .andIfLegacySupportFor(BT2020_PQ, false)
1525 .thenExpectBestColorModeCallUses(BT2020_PQ)
1526 .execute();
1527}
1528
1529TEST_F(OutputUpdateColorProfileTest_Hdr, HLG_HW_On_PQ_HW_IfPQHasLegacySupport_Uses_DisplayP3) {
1530 // BT2020_PQ is not used if there is only legacy support for it.
1531 verify().ifTopLayerIs(BT2020_HLG)
1532 .andTopLayerIsREComposed(false)
1533 .andIfBottomLayerIs(BT2020_PQ)
1534 .andBottomLayerIsREComposed(false)
1535 .andIfLegacySupportFor(BT2020_PQ, true)
1536 .thenExpectBestColorModeCallUses(DISPLAY_P3)
1537 .execute();
1538}
1539
1540TEST_F(OutputUpdateColorProfileTest_Hdr, HLG_HW_On_PQ_RE_Uses_DisplayP3) {
1541 // BT2020_PQ is not used if the bottom PQ layer is RenderEngine composed.
1542 verify().ifTopLayerIs(BT2020_HLG)
1543 .andTopLayerIsREComposed(false)
1544 .andIfBottomLayerIs(BT2020_PQ)
1545 .andBottomLayerIsREComposed(true)
1546 .andIfLegacySupportFor(BT2020_PQ, false)
1547 .thenExpectBestColorModeCallUses(DISPLAY_P3)
1548 .execute();
1549}
1550
1551TEST_F(OutputUpdateColorProfileTest_Hdr, HLG_RE_On_PQ_HW_Uses_PQ) {
1552 // BT2020_PQ is still used if the top HLG layer is RenderEngine composed.
1553 verify().ifTopLayerIs(BT2020_HLG)
1554 .andTopLayerIsREComposed(true)
1555 .andIfBottomLayerIs(BT2020_PQ)
1556 .andBottomLayerIsREComposed(false)
1557 .andIfLegacySupportFor(BT2020_PQ, false)
1558 .thenExpectBestColorModeCallUses(BT2020_PQ)
1559 .execute();
1560}
1561
1562TEST_F(OutputUpdateColorProfileTest_Hdr, HLG_HW_On_HLG_HW_Uses_HLG) {
1563 // If all layers use HLG then HLG is used if there are no other special
1564 // conditions.
1565 verify().ifTopLayerIs(BT2020_HLG)
1566 .andTopLayerIsREComposed(false)
1567 .andIfBottomLayerIs(BT2020_HLG)
1568 .andBottomLayerIsREComposed(false)
1569 .andIfLegacySupportFor(BT2020_HLG, false)
1570 .thenExpectBestColorModeCallUses(BT2020_HLG)
1571 .execute();
1572}
1573
1574TEST_F(OutputUpdateColorProfileTest_Hdr, HLG_HW_On_HLG_HW_IfPQHasLegacySupport_Uses_DisplayP3) {
1575 // BT2020_HLG is not used if there is legacy support for it.
1576 verify().ifTopLayerIs(BT2020_HLG)
1577 .andTopLayerIsREComposed(false)
1578 .andIfBottomLayerIs(BT2020_HLG)
1579 .andBottomLayerIsREComposed(false)
1580 .andIfLegacySupportFor(BT2020_HLG, true)
1581 .thenExpectBestColorModeCallUses(DISPLAY_P3)
1582 .execute();
1583}
1584
1585TEST_F(OutputUpdateColorProfileTest_Hdr, HLG_HW_On_HLG_RE_Uses_HLG) {
1586 // BT2020_HLG is used even if the bottom layer is client composed.
1587 verify().ifTopLayerIs(BT2020_HLG)
1588 .andTopLayerIsREComposed(false)
1589 .andIfBottomLayerIs(BT2020_HLG)
1590 .andBottomLayerIsREComposed(true)
1591 .andIfLegacySupportFor(BT2020_HLG, false)
1592 .thenExpectBestColorModeCallUses(BT2020_HLG)
1593 .execute();
1594}
1595
1596TEST_F(OutputUpdateColorProfileTest_Hdr, HLG_RE_On_HLG_HW_Uses_HLG) {
1597 // BT2020_HLG is used even if the top layer is client composed.
1598 verify().ifTopLayerIs(BT2020_HLG)
1599 .andTopLayerIsREComposed(true)
1600 .andIfBottomLayerIs(BT2020_HLG)
1601 .andBottomLayerIsREComposed(false)
1602 .andIfLegacySupportFor(BT2020_HLG, false)
1603 .thenExpectBestColorModeCallUses(BT2020_HLG)
1604 .execute();
1605}
1606
1607TEST_F(OutputUpdateColorProfileTest_Hdr, PQ_HW_On_NonHdr_HW_Uses_PQ) {
1608 // Even if there are non-HDR layers present, BT2020_PQ can still be used.
1609 verify().ifTopLayerIs(BT2020_PQ)
1610 .andTopLayerIsREComposed(false)
1611 .andIfBottomLayerIsNotHdr()
1612 .andBottomLayerIsREComposed(false)
1613 .andIfLegacySupportFor(BT2020_PQ, false)
1614 .thenExpectBestColorModeCallUses(BT2020_PQ)
1615 .execute();
1616}
1617
1618TEST_F(OutputUpdateColorProfileTest_Hdr, HLG_HW_On_NonHdr_RE_Uses_HLG) {
1619 // If all layers use HLG then HLG is used if there are no other special
1620 // conditions.
1621 verify().ifTopLayerIs(BT2020_HLG)
1622 .andTopLayerIsREComposed(false)
1623 .andIfBottomLayerIsNotHdr()
1624 .andBottomLayerIsREComposed(true)
1625 .andIfLegacySupportFor(BT2020_HLG, false)
1626 .thenExpectBestColorModeCallUses(BT2020_HLG)
1627 .execute();
1628}
1629
1630struct OutputUpdateColorProfile_AffectsChosenRenderIntentTest
1631 : public OutputUpdateColorProfileTest {
1632 // The various values for CompositionRefreshArgs::outputColorSetting affect
1633 // the chosen renderIntent, along with whether the preferred dataspace is an
1634 // HDR dataspace or not.
1635
1636 OutputUpdateColorProfile_AffectsChosenRenderIntentTest() {
1637 mRefreshArgs.outputColorSetting = OutputColorSetting::kEnhanced;
1638 mRefreshArgs.colorSpaceAgnosticDataspace = ui::Dataspace::UNKNOWN;
1639 mLayer1.mLayerFEState.dataspace = ui::Dataspace::BT2020_PQ;
1640 EXPECT_CALL(mOutput, getOutputLayerCount()).WillRepeatedly(Return(1));
1641 EXPECT_CALL(mOutput, setColorProfile(_)).WillRepeatedly(Return());
1642 EXPECT_CALL(*mDisplayColorProfile, hasLegacyHdrSupport(ui::Dataspace::BT2020_PQ))
1643 .WillRepeatedly(Return(false));
1644 }
1645
1646 // The tests here involve enough state and GMock setup that using a mini-DSL
1647 // makes the tests much more readable, and allows the test to focus more on
1648 // the intent than on some of the details.
1649
1650 static constexpr ui::Dataspace kNonHdrDataspace = ui::Dataspace::DISPLAY_P3;
1651 static constexpr ui::Dataspace kHdrDataspace = ui::Dataspace::BT2020_PQ;
1652
1653 struct IfDataspaceChosenState
1654 : public CallOrderStateMachineHelper<TestType, IfDataspaceChosenState> {
1655 [[nodiscard]] auto ifDataspaceChosenIs(ui::Dataspace dataspace) {
1656 getInstance()->mLayer1.mLayerFEState.dataspace = dataspace;
1657 return nextState<AndOutputColorSettingState>();
1658 }
1659 [[nodiscard]] auto ifDataspaceChosenIsNonHdr() {
1660 return ifDataspaceChosenIs(kNonHdrDataspace);
1661 }
1662 [[nodiscard]] auto ifDataspaceChosenIsHdr() { return ifDataspaceChosenIs(kHdrDataspace); }
1663 };
1664
1665 struct AndOutputColorSettingState
1666 : public CallOrderStateMachineHelper<TestType, AndOutputColorSettingState> {
1667 [[nodiscard]] auto andOutputColorSettingIs(OutputColorSetting setting) {
1668 getInstance()->mRefreshArgs.outputColorSetting = setting;
1669 return nextState<ThenExpectBestColorModeCallUsesState>();
1670 }
1671 };
1672
1673 struct ThenExpectBestColorModeCallUsesState
1674 : public CallOrderStateMachineHelper<TestType, ThenExpectBestColorModeCallUsesState> {
1675 [[nodiscard]] auto thenExpectBestColorModeCallUses(ui::RenderIntent intent) {
1676 EXPECT_CALL(*getInstance()->mDisplayColorProfile,
1677 getBestColorMode(getInstance()->mLayer1.mLayerFEState.dataspace, intent, _,
1678 _, _));
1679 return nextState<ExecuteState>();
1680 }
1681 };
1682
1683 // Tests call one of these two helper member functions to start using the
1684 // mini-DSL defined above.
1685 [[nodiscard]] auto verify() { return IfDataspaceChosenState::make(this); }
1686};
1687
1688TEST_F(OutputUpdateColorProfile_AffectsChosenRenderIntentTest,
1689 Managed_NonHdr_Prefers_Colorimetric) {
1690 verify().ifDataspaceChosenIsNonHdr()
1691 .andOutputColorSettingIs(OutputColorSetting::kManaged)
1692 .thenExpectBestColorModeCallUses(ui::RenderIntent::COLORIMETRIC)
1693 .execute();
1694}
1695
1696TEST_F(OutputUpdateColorProfile_AffectsChosenRenderIntentTest,
1697 Managed_Hdr_Prefers_ToneMapColorimetric) {
1698 verify().ifDataspaceChosenIsHdr()
1699 .andOutputColorSettingIs(OutputColorSetting::kManaged)
1700 .thenExpectBestColorModeCallUses(ui::RenderIntent::TONE_MAP_COLORIMETRIC)
1701 .execute();
1702}
1703
1704TEST_F(OutputUpdateColorProfile_AffectsChosenRenderIntentTest, Enhanced_NonHdr_Prefers_Enhance) {
1705 verify().ifDataspaceChosenIsNonHdr()
1706 .andOutputColorSettingIs(OutputColorSetting::kEnhanced)
1707 .thenExpectBestColorModeCallUses(ui::RenderIntent::ENHANCE)
1708 .execute();
1709}
1710
1711TEST_F(OutputUpdateColorProfile_AffectsChosenRenderIntentTest,
1712 Enhanced_Hdr_Prefers_ToneMapEnhance) {
1713 verify().ifDataspaceChosenIsHdr()
1714 .andOutputColorSettingIs(OutputColorSetting::kEnhanced)
1715 .thenExpectBestColorModeCallUses(ui::RenderIntent::TONE_MAP_ENHANCE)
1716 .execute();
1717}
1718
1719TEST_F(OutputUpdateColorProfile_AffectsChosenRenderIntentTest, Vendor_NonHdr_Prefers_Vendor) {
1720 verify().ifDataspaceChosenIsNonHdr()
1721 .andOutputColorSettingIs(kVendorSpecifiedOutputColorSetting)
1722 .thenExpectBestColorModeCallUses(
1723 static_cast<ui::RenderIntent>(kVendorSpecifiedOutputColorSetting))
1724 .execute();
1725}
1726
1727TEST_F(OutputUpdateColorProfile_AffectsChosenRenderIntentTest, Vendor_Hdr_Prefers_Vendor) {
1728 verify().ifDataspaceChosenIsHdr()
1729 .andOutputColorSettingIs(kVendorSpecifiedOutputColorSetting)
1730 .thenExpectBestColorModeCallUses(
1731 static_cast<ui::RenderIntent>(kVendorSpecifiedOutputColorSetting))
1732 .execute();
1733}
Lloyd Piquefaa3f192019-11-14 14:05:09 -08001734
1735/*
1736 * Output::beginFrame()
1737 */
1738
Lloyd Piquee5965952019-11-18 16:16:32 -08001739struct OutputBeginFrameTest : public ::testing::Test {
1740 using TestType = OutputBeginFrameTest;
1741
1742 struct OutputPartialMock : public OutputPartialMockBase {
1743 // Sets up the helper functions called by begiNFrame to use a mock
1744 // implementations.
1745 MOCK_CONST_METHOD1(getDirtyRegion, Region(bool));
1746 };
1747
1748 OutputBeginFrameTest() {
1749 mOutput.setDisplayColorProfileForTest(
1750 std::unique_ptr<DisplayColorProfile>(mDisplayColorProfile));
1751 mOutput.setRenderSurfaceForTest(std::unique_ptr<RenderSurface>(mRenderSurface));
1752 }
1753
1754 struct IfGetDirtyRegionExpectationState
1755 : public CallOrderStateMachineHelper<TestType, IfGetDirtyRegionExpectationState> {
1756 [[nodiscard]] auto ifGetDirtyRegionReturns(Region dirtyRegion) {
1757 EXPECT_CALL(getInstance()->mOutput, getDirtyRegion(false))
1758 .WillOnce(Return(dirtyRegion));
1759 return nextState<AndIfGetOutputLayerCountExpectationState>();
1760 }
1761 };
1762
1763 struct AndIfGetOutputLayerCountExpectationState
1764 : public CallOrderStateMachineHelper<TestType, AndIfGetOutputLayerCountExpectationState> {
1765 [[nodiscard]] auto andIfGetOutputLayerCountReturns(size_t layerCount) {
1766 EXPECT_CALL(getInstance()->mOutput, getOutputLayerCount()).WillOnce(Return(layerCount));
1767 return nextState<AndIfLastCompositionHadVisibleLayersState>();
1768 }
1769 };
1770
1771 struct AndIfLastCompositionHadVisibleLayersState
1772 : public CallOrderStateMachineHelper<TestType,
1773 AndIfLastCompositionHadVisibleLayersState> {
1774 [[nodiscard]] auto andIfLastCompositionHadVisibleLayersIs(bool hadOutputLayers) {
1775 getInstance()->mOutput.mState.lastCompositionHadVisibleLayers = hadOutputLayers;
1776 return nextState<ThenExpectRenderSurfaceBeginFrameCallState>();
1777 }
1778 };
1779
1780 struct ThenExpectRenderSurfaceBeginFrameCallState
1781 : public CallOrderStateMachineHelper<TestType,
1782 ThenExpectRenderSurfaceBeginFrameCallState> {
1783 [[nodiscard]] auto thenExpectRenderSurfaceBeginFrameCall(bool mustRecompose) {
1784 EXPECT_CALL(*getInstance()->mRenderSurface, beginFrame(mustRecompose));
1785 return nextState<ExecuteState>();
1786 }
1787 };
1788
1789 struct ExecuteState : public CallOrderStateMachineHelper<TestType, ExecuteState> {
1790 [[nodiscard]] auto execute() {
1791 getInstance()->mOutput.beginFrame();
1792 return nextState<CheckPostconditionHadVisibleLayersState>();
1793 }
1794 };
1795
1796 struct CheckPostconditionHadVisibleLayersState
1797 : public CallOrderStateMachineHelper<TestType, CheckPostconditionHadVisibleLayersState> {
1798 void checkPostconditionHadVisibleLayers(bool expected) {
1799 EXPECT_EQ(expected, getInstance()->mOutput.mState.lastCompositionHadVisibleLayers);
1800 }
1801 };
1802
1803 // Tests call one of these two helper member functions to start using the
1804 // mini-DSL defined above.
1805 [[nodiscard]] auto verify() { return IfGetDirtyRegionExpectationState::make(this); }
1806
1807 static const Region kEmptyRegion;
1808 static const Region kNotEmptyRegion;
1809
1810 mock::DisplayColorProfile* mDisplayColorProfile = new StrictMock<mock::DisplayColorProfile>();
1811 mock::RenderSurface* mRenderSurface = new StrictMock<mock::RenderSurface>();
1812 StrictMock<OutputPartialMock> mOutput;
1813};
1814
1815const Region OutputBeginFrameTest::kEmptyRegion{Rect{0, 0, 0, 0}};
1816const Region OutputBeginFrameTest::kNotEmptyRegion{Rect{0, 0, 1, 1}};
1817
1818TEST_F(OutputBeginFrameTest, hasDirtyHasLayersHadLayersLastFrame) {
1819 verify().ifGetDirtyRegionReturns(kNotEmptyRegion)
1820 .andIfGetOutputLayerCountReturns(1u)
1821 .andIfLastCompositionHadVisibleLayersIs(true)
1822 .thenExpectRenderSurfaceBeginFrameCall(true)
1823 .execute()
1824 .checkPostconditionHadVisibleLayers(true);
1825}
1826
1827TEST_F(OutputBeginFrameTest, hasDirtyNotHasLayersHadLayersLastFrame) {
1828 verify().ifGetDirtyRegionReturns(kNotEmptyRegion)
1829 .andIfGetOutputLayerCountReturns(0u)
1830 .andIfLastCompositionHadVisibleLayersIs(true)
1831 .thenExpectRenderSurfaceBeginFrameCall(true)
1832 .execute()
1833 .checkPostconditionHadVisibleLayers(false);
1834}
1835
1836TEST_F(OutputBeginFrameTest, hasDirtyHasLayersNotHadLayersLastFrame) {
1837 verify().ifGetDirtyRegionReturns(kNotEmptyRegion)
1838 .andIfGetOutputLayerCountReturns(1u)
1839 .andIfLastCompositionHadVisibleLayersIs(false)
1840 .thenExpectRenderSurfaceBeginFrameCall(true)
1841 .execute()
1842 .checkPostconditionHadVisibleLayers(true);
1843}
1844
1845TEST_F(OutputBeginFrameTest, hasDirtyNotHasLayersNotHadLayersLastFrame) {
1846 verify().ifGetDirtyRegionReturns(kNotEmptyRegion)
1847 .andIfGetOutputLayerCountReturns(0u)
1848 .andIfLastCompositionHadVisibleLayersIs(false)
1849 .thenExpectRenderSurfaceBeginFrameCall(false)
1850 .execute()
1851 .checkPostconditionHadVisibleLayers(false);
1852}
1853
1854TEST_F(OutputBeginFrameTest, notHasDirtyHasLayersHadLayersLastFrame) {
1855 verify().ifGetDirtyRegionReturns(kEmptyRegion)
1856 .andIfGetOutputLayerCountReturns(1u)
1857 .andIfLastCompositionHadVisibleLayersIs(true)
1858 .thenExpectRenderSurfaceBeginFrameCall(false)
1859 .execute()
1860 .checkPostconditionHadVisibleLayers(true);
1861}
1862
1863TEST_F(OutputBeginFrameTest, notHasDirtyNotHasLayersHadLayersLastFrame) {
1864 verify().ifGetDirtyRegionReturns(kEmptyRegion)
1865 .andIfGetOutputLayerCountReturns(0u)
1866 .andIfLastCompositionHadVisibleLayersIs(true)
1867 .thenExpectRenderSurfaceBeginFrameCall(false)
1868 .execute()
1869 .checkPostconditionHadVisibleLayers(true);
1870}
1871
1872TEST_F(OutputBeginFrameTest, notHasDirtyHasLayersNotHadLayersLastFrame) {
1873 verify().ifGetDirtyRegionReturns(kEmptyRegion)
1874 .andIfGetOutputLayerCountReturns(1u)
1875 .andIfLastCompositionHadVisibleLayersIs(false)
1876 .thenExpectRenderSurfaceBeginFrameCall(false)
1877 .execute()
1878 .checkPostconditionHadVisibleLayers(false);
1879}
1880
1881TEST_F(OutputBeginFrameTest, notHasDirtyNotHasLayersNotHadLayersLastFrame) {
1882 verify().ifGetDirtyRegionReturns(kEmptyRegion)
1883 .andIfGetOutputLayerCountReturns(0u)
1884 .andIfLastCompositionHadVisibleLayersIs(false)
1885 .thenExpectRenderSurfaceBeginFrameCall(false)
1886 .execute()
1887 .checkPostconditionHadVisibleLayers(false);
1888}
1889
Lloyd Piquefaa3f192019-11-14 14:05:09 -08001890/*
1891 * Output::devOptRepaintFlash()
1892 */
1893
Lloyd Piquedb462d82019-11-19 17:58:46 -08001894struct OutputDevOptRepaintFlashTest : public testing::Test {
1895 struct OutputPartialMock : public OutputPartialMockBase {
1896 // Sets up the helper functions called by composeSurfaces to use a mock
1897 // implementations.
1898 MOCK_CONST_METHOD1(getDirtyRegion, Region(bool));
1899 MOCK_METHOD1(composeSurfaces, std::optional<base::unique_fd>(const Region&));
1900 MOCK_METHOD0(postFramebuffer, void());
1901 MOCK_METHOD0(prepareFrame, void());
1902 };
1903
1904 OutputDevOptRepaintFlashTest() {
1905 mOutput.setDisplayColorProfileForTest(
1906 std::unique_ptr<DisplayColorProfile>(mDisplayColorProfile));
1907 mOutput.setRenderSurfaceForTest(std::unique_ptr<RenderSurface>(mRenderSurface));
1908 }
1909
1910 static const Region kEmptyRegion;
1911 static const Region kNotEmptyRegion;
1912
1913 StrictMock<OutputPartialMock> mOutput;
1914 mock::DisplayColorProfile* mDisplayColorProfile = new StrictMock<mock::DisplayColorProfile>();
1915 mock::RenderSurface* mRenderSurface = new StrictMock<mock::RenderSurface>();
1916 CompositionRefreshArgs mRefreshArgs;
1917};
1918
1919const Region OutputDevOptRepaintFlashTest::kEmptyRegion{Rect{0, 0, 0, 0}};
1920const Region OutputDevOptRepaintFlashTest::kNotEmptyRegion{Rect{0, 0, 1, 1}};
1921
1922TEST_F(OutputDevOptRepaintFlashTest, doesNothingIfFlashDelayNotSet) {
1923 mRefreshArgs.devOptFlashDirtyRegionsDelay = {};
1924 mRefreshArgs.repaintEverything = true;
1925 mOutput.mState.isEnabled = true;
1926
1927 mOutput.devOptRepaintFlash(mRefreshArgs);
1928}
1929
1930TEST_F(OutputDevOptRepaintFlashTest, postsAndPreparesANewFrameIfNotEnabled) {
1931 mRefreshArgs.devOptFlashDirtyRegionsDelay = std::chrono::microseconds(1);
1932 mRefreshArgs.repaintEverything = true;
1933 mOutput.mState.isEnabled = false;
1934
1935 InSequence seq;
1936 EXPECT_CALL(mOutput, postFramebuffer());
1937 EXPECT_CALL(mOutput, prepareFrame());
1938
1939 mOutput.devOptRepaintFlash(mRefreshArgs);
1940}
1941
1942TEST_F(OutputDevOptRepaintFlashTest, postsAndPreparesANewFrameIfNotDirty) {
1943 mRefreshArgs.devOptFlashDirtyRegionsDelay = std::chrono::microseconds(1);
1944 mRefreshArgs.repaintEverything = true;
1945 mOutput.mState.isEnabled = true;
1946
1947 InSequence seq;
1948 EXPECT_CALL(mOutput, getDirtyRegion(true)).WillOnce(Return(kEmptyRegion));
1949 EXPECT_CALL(mOutput, postFramebuffer());
1950 EXPECT_CALL(mOutput, prepareFrame());
1951
1952 mOutput.devOptRepaintFlash(mRefreshArgs);
1953}
1954
1955TEST_F(OutputDevOptRepaintFlashTest, alsoComposesSurfacesAndQueuesABufferIfDirty) {
1956 mRefreshArgs.devOptFlashDirtyRegionsDelay = std::chrono::microseconds(1);
1957 mRefreshArgs.repaintEverything = false;
1958 mOutput.mState.isEnabled = true;
1959
1960 InSequence seq;
1961 EXPECT_CALL(mOutput, getDirtyRegion(false)).WillOnce(Return(kNotEmptyRegion));
1962 EXPECT_CALL(mOutput, composeSurfaces(RegionEq(kNotEmptyRegion)));
1963 EXPECT_CALL(*mRenderSurface, queueBuffer(_));
1964 EXPECT_CALL(mOutput, postFramebuffer());
1965 EXPECT_CALL(mOutput, prepareFrame());
1966
1967 mOutput.devOptRepaintFlash(mRefreshArgs);
1968}
1969
Lloyd Piquefaa3f192019-11-14 14:05:09 -08001970// TODO(b/144060211) - Add coverage
1971
1972/*
1973 * Output::finishFrame()
1974 */
1975
Lloyd Pique03561a62019-11-19 18:34:52 -08001976struct OutputFinishFrameTest : public testing::Test {
1977 struct OutputPartialMock : public OutputPartialMockBase {
1978 // Sets up the helper functions called by composeSurfaces to use a mock
1979 // implementations.
1980 MOCK_METHOD1(composeSurfaces, std::optional<base::unique_fd>(const Region&));
1981 MOCK_METHOD0(postFramebuffer, void());
1982 };
1983
1984 OutputFinishFrameTest() {
1985 mOutput.setDisplayColorProfileForTest(
1986 std::unique_ptr<DisplayColorProfile>(mDisplayColorProfile));
1987 mOutput.setRenderSurfaceForTest(std::unique_ptr<RenderSurface>(mRenderSurface));
1988 }
1989
1990 StrictMock<OutputPartialMock> mOutput;
1991 mock::DisplayColorProfile* mDisplayColorProfile = new StrictMock<mock::DisplayColorProfile>();
1992 mock::RenderSurface* mRenderSurface = new StrictMock<mock::RenderSurface>();
1993 CompositionRefreshArgs mRefreshArgs;
1994};
1995
1996TEST_F(OutputFinishFrameTest, ifNotEnabledDoesNothing) {
1997 mOutput.mState.isEnabled = false;
1998
1999 mOutput.finishFrame(mRefreshArgs);
2000}
2001
2002TEST_F(OutputFinishFrameTest, takesEarlyOutifComposeSurfacesReturnsNoFence) {
2003 mOutput.mState.isEnabled = true;
2004
2005 InSequence seq;
2006 EXPECT_CALL(mOutput, composeSurfaces(RegionEq(Region::INVALID_REGION)));
2007
2008 mOutput.finishFrame(mRefreshArgs);
2009}
2010
2011TEST_F(OutputFinishFrameTest, queuesBufferIfComposeSurfacesReturnsAFence) {
2012 mOutput.mState.isEnabled = true;
2013
2014 InSequence seq;
2015 EXPECT_CALL(mOutput, composeSurfaces(RegionEq(Region::INVALID_REGION)))
2016 .WillOnce(Return(ByMove(base::unique_fd())));
2017 EXPECT_CALL(*mRenderSurface, queueBuffer(_));
2018
2019 mOutput.finishFrame(mRefreshArgs);
2020}
Lloyd Piquefaa3f192019-11-14 14:05:09 -08002021
2022/*
2023 * Output::postFramebuffer()
2024 */
2025
Lloyd Pique07178e32019-11-19 19:15:26 -08002026struct OutputPostFramebufferTest : public testing::Test {
2027 struct OutputPartialMock : public OutputPartialMockBase {
2028 // Sets up the helper functions called by composeSurfaces to use a mock
2029 // implementations.
2030 MOCK_METHOD0(presentAndGetFrameFences, compositionengine::Output::FrameFences());
2031 };
2032
2033 struct Layer {
2034 Layer() {
2035 EXPECT_CALL(outputLayer, getLayerFE()).WillRepeatedly(ReturnRef(layerFE));
2036 EXPECT_CALL(outputLayer, getHwcLayer()).WillRepeatedly(Return(&hwc2Layer));
2037 }
2038
2039 StrictMock<mock::OutputLayer> outputLayer;
2040 StrictMock<mock::LayerFE> layerFE;
2041 StrictMock<HWC2::mock::Layer> hwc2Layer;
2042 };
2043
2044 OutputPostFramebufferTest() {
2045 mOutput.setDisplayColorProfileForTest(
2046 std::unique_ptr<DisplayColorProfile>(mDisplayColorProfile));
2047 mOutput.setRenderSurfaceForTest(std::unique_ptr<RenderSurface>(mRenderSurface));
2048
2049 EXPECT_CALL(mOutput, getOutputLayerCount()).WillRepeatedly(Return(3u));
2050 EXPECT_CALL(mOutput, getOutputLayerOrderedByZByIndex(0u))
2051 .WillRepeatedly(Return(&mLayer1.outputLayer));
2052 EXPECT_CALL(mOutput, getOutputLayerOrderedByZByIndex(1u))
2053 .WillRepeatedly(Return(&mLayer2.outputLayer));
2054 EXPECT_CALL(mOutput, getOutputLayerOrderedByZByIndex(2u))
2055 .WillRepeatedly(Return(&mLayer3.outputLayer));
2056 }
2057
2058 StrictMock<OutputPartialMock> mOutput;
2059 mock::DisplayColorProfile* mDisplayColorProfile = new StrictMock<mock::DisplayColorProfile>();
2060 mock::RenderSurface* mRenderSurface = new StrictMock<mock::RenderSurface>();
2061
2062 Layer mLayer1;
2063 Layer mLayer2;
2064 Layer mLayer3;
2065};
2066
2067TEST_F(OutputPostFramebufferTest, ifNotEnabledDoesNothing) {
2068 mOutput.mState.isEnabled = false;
2069
2070 mOutput.postFramebuffer();
2071}
2072
2073TEST_F(OutputPostFramebufferTest, ifEnabledMustFlipThenPresentThenSendPresentCompleted) {
2074 mOutput.mState.isEnabled = true;
2075
2076 compositionengine::Output::FrameFences frameFences;
2077
2078 // This should happen even if there are no output layers.
2079 EXPECT_CALL(mOutput, getOutputLayerCount()).WillOnce(Return(0u));
2080
2081 // For this test in particular we want to make sure the call expectations
2082 // setup below are satisfied in the specific order.
2083 InSequence seq;
2084
2085 EXPECT_CALL(*mRenderSurface, flip());
2086 EXPECT_CALL(mOutput, presentAndGetFrameFences()).WillOnce(Return(frameFences));
2087 EXPECT_CALL(*mRenderSurface, onPresentDisplayCompleted());
2088
2089 mOutput.postFramebuffer();
2090}
2091
2092TEST_F(OutputPostFramebufferTest, releaseFencesAreSentToLayerFE) {
2093 // Simulate getting release fences from each layer, and ensure they are passed to the
2094 // front-end layer interface for each layer correctly.
2095
2096 mOutput.mState.isEnabled = true;
2097
2098 // Create three unique fence instances
2099 sp<Fence> layer1Fence = new Fence();
2100 sp<Fence> layer2Fence = new Fence();
2101 sp<Fence> layer3Fence = new Fence();
2102
2103 compositionengine::Output::FrameFences frameFences;
2104 frameFences.layerFences.emplace(&mLayer1.hwc2Layer, layer1Fence);
2105 frameFences.layerFences.emplace(&mLayer2.hwc2Layer, layer2Fence);
2106 frameFences.layerFences.emplace(&mLayer3.hwc2Layer, layer3Fence);
2107
2108 EXPECT_CALL(*mRenderSurface, flip());
2109 EXPECT_CALL(mOutput, presentAndGetFrameFences()).WillOnce(Return(frameFences));
2110 EXPECT_CALL(*mRenderSurface, onPresentDisplayCompleted());
2111
2112 // Compare the pointers values of each fence to make sure the correct ones
2113 // are passed. This happens to work with the current implementation, but
2114 // would not survive certain calls like Fence::merge() which would return a
2115 // new instance.
2116 EXPECT_CALL(mLayer1.layerFE,
2117 onLayerDisplayed(Property(&sp<Fence>::get, Eq(layer1Fence.get()))));
2118 EXPECT_CALL(mLayer2.layerFE,
2119 onLayerDisplayed(Property(&sp<Fence>::get, Eq(layer2Fence.get()))));
2120 EXPECT_CALL(mLayer3.layerFE,
2121 onLayerDisplayed(Property(&sp<Fence>::get, Eq(layer3Fence.get()))));
2122
2123 mOutput.postFramebuffer();
2124}
2125
2126TEST_F(OutputPostFramebufferTest, releaseFencesIncludeClientTargetAcquireFence) {
2127 mOutput.mState.isEnabled = true;
2128 mOutput.mState.usesClientComposition = true;
2129
2130 sp<Fence> clientTargetAcquireFence = new Fence();
2131 sp<Fence> layer1Fence = new Fence();
2132 sp<Fence> layer2Fence = new Fence();
2133 sp<Fence> layer3Fence = new Fence();
2134 compositionengine::Output::FrameFences frameFences;
2135 frameFences.clientTargetAcquireFence = clientTargetAcquireFence;
2136 frameFences.layerFences.emplace(&mLayer1.hwc2Layer, layer1Fence);
2137 frameFences.layerFences.emplace(&mLayer2.hwc2Layer, layer2Fence);
2138 frameFences.layerFences.emplace(&mLayer3.hwc2Layer, layer3Fence);
2139
2140 EXPECT_CALL(*mRenderSurface, flip());
2141 EXPECT_CALL(mOutput, presentAndGetFrameFences()).WillOnce(Return(frameFences));
2142 EXPECT_CALL(*mRenderSurface, onPresentDisplayCompleted());
2143
2144 // Fence::merge is called, and since none of the fences are actually valid,
2145 // Fence::NO_FENCE is returned and passed to each onLayerDisplayed() call.
2146 // This is the best we can do without creating a real kernel fence object.
2147 EXPECT_CALL(mLayer1.layerFE, onLayerDisplayed(Fence::NO_FENCE));
2148 EXPECT_CALL(mLayer2.layerFE, onLayerDisplayed(Fence::NO_FENCE));
2149 EXPECT_CALL(mLayer3.layerFE, onLayerDisplayed(Fence::NO_FENCE));
2150
2151 mOutput.postFramebuffer();
2152}
2153
2154TEST_F(OutputPostFramebufferTest, releasedLayersSentPresentFence) {
2155 mOutput.mState.isEnabled = true;
2156 mOutput.mState.usesClientComposition = true;
2157
2158 // This should happen even if there are no (current) output layers.
2159 EXPECT_CALL(mOutput, getOutputLayerCount()).WillOnce(Return(0u));
2160
2161 // Load up the released layers with some mock instances
2162 sp<StrictMock<mock::LayerFE>> releasedLayer1{new StrictMock<mock::LayerFE>()};
2163 sp<StrictMock<mock::LayerFE>> releasedLayer2{new StrictMock<mock::LayerFE>()};
2164 sp<StrictMock<mock::LayerFE>> releasedLayer3{new StrictMock<mock::LayerFE>()};
2165 Output::ReleasedLayers layers;
2166 layers.push_back(releasedLayer1);
2167 layers.push_back(releasedLayer2);
2168 layers.push_back(releasedLayer3);
2169 mOutput.setReleasedLayers(std::move(layers));
2170
2171 // Set up a fake present fence
2172 sp<Fence> presentFence = new Fence();
2173 compositionengine::Output::FrameFences frameFences;
2174 frameFences.presentFence = presentFence;
2175
2176 EXPECT_CALL(*mRenderSurface, flip());
2177 EXPECT_CALL(mOutput, presentAndGetFrameFences()).WillOnce(Return(frameFences));
2178 EXPECT_CALL(*mRenderSurface, onPresentDisplayCompleted());
2179
2180 // Each released layer should be given the presentFence.
2181 EXPECT_CALL(*releasedLayer1,
2182 onLayerDisplayed(Property(&sp<Fence>::get, Eq(presentFence.get()))));
2183 EXPECT_CALL(*releasedLayer2,
2184 onLayerDisplayed(Property(&sp<Fence>::get, Eq(presentFence.get()))));
2185 EXPECT_CALL(*releasedLayer3,
2186 onLayerDisplayed(Property(&sp<Fence>::get, Eq(presentFence.get()))));
2187
2188 mOutput.postFramebuffer();
2189
2190 // After the call the list of released layers should have been cleared.
2191 EXPECT_TRUE(mOutput.getReleasedLayersForTest().empty());
2192}
Lloyd Piquefaa3f192019-11-14 14:05:09 -08002193
2194/*
Lloyd Pique56eba802019-08-28 15:45:25 -07002195 * Output::composeSurfaces()
2196 */
2197
2198struct OutputComposeSurfacesTest : public testing::Test {
2199 static constexpr uint32_t kDefaultOutputOrientation = TR_IDENT;
2200 static constexpr ui::Dataspace kDefaultOutputDataspace = ui::Dataspace::DISPLAY_P3;
2201
2202 static const Rect kDefaultOutputFrame;
2203 static const Rect kDefaultOutputViewport;
2204 static const Rect kDefaultOutputScissor;
2205 static const mat4 kDefaultColorTransformMat;
2206
Lloyd Piquefaa3f192019-11-14 14:05:09 -08002207 struct OutputPartialMock : public OutputPartialMockBase {
Lloyd Pique56eba802019-08-28 15:45:25 -07002208 // Sets up the helper functions called by composeSurfaces to use a mock
2209 // implementations.
2210 MOCK_CONST_METHOD0(getSkipColorTransform, bool());
2211 MOCK_METHOD2(generateClientCompositionRequests,
2212 std::vector<renderengine::LayerSettings>(bool, Region&));
2213 MOCK_METHOD2(appendRegionFlashRequests,
2214 void(const Region&, std::vector<renderengine::LayerSettings>&));
2215 MOCK_METHOD1(setExpensiveRenderingExpected, void(bool));
2216 };
2217
2218 OutputComposeSurfacesTest() {
2219 mOutput.setDisplayColorProfileForTest(
2220 std::unique_ptr<DisplayColorProfile>(mDisplayColorProfile));
2221 mOutput.setRenderSurfaceForTest(std::unique_ptr<RenderSurface>(mRenderSurface));
2222
Lloyd Pique56eba802019-08-28 15:45:25 -07002223 mOutput.editState().frame = kDefaultOutputFrame;
2224 mOutput.editState().viewport = kDefaultOutputViewport;
2225 mOutput.editState().scissor = kDefaultOutputScissor;
2226 mOutput.editState().transform = ui::Transform{kDefaultOutputOrientation};
2227 mOutput.editState().orientation = kDefaultOutputOrientation;
2228 mOutput.editState().dataspace = kDefaultOutputDataspace;
Lloyd Pique3eb1b212019-03-07 21:15:40 -08002229 mOutput.editState().colorTransformMatrix = kDefaultColorTransformMat;
Lloyd Pique56eba802019-08-28 15:45:25 -07002230 mOutput.editState().isSecure = true;
2231 mOutput.editState().needsFiltering = false;
2232 mOutput.editState().usesClientComposition = true;
2233 mOutput.editState().usesDeviceComposition = false;
2234
Lloyd Pique01c77c12019-04-17 12:48:32 -07002235 EXPECT_CALL(mOutput, getOutputLayerCount()).WillRepeatedly(Return(2u));
2236 EXPECT_CALL(mOutput, getOutputLayerOrderedByZByIndex(0u))
2237 .WillRepeatedly(Return(&mOutputLayer1));
2238 EXPECT_CALL(mOutput, getOutputLayerOrderedByZByIndex(1u))
2239 .WillRepeatedly(Return(&mOutputLayer2));
Lloyd Piquea38ea7e2019-04-16 18:10:26 -07002240 EXPECT_CALL(mOutput, getCompositionEngine()).WillRepeatedly(ReturnRef(mCompositionEngine));
Lloyd Pique56eba802019-08-28 15:45:25 -07002241 EXPECT_CALL(mCompositionEngine, getRenderEngine()).WillRepeatedly(ReturnRef(mRenderEngine));
2242 }
2243
2244 StrictMock<mock::CompositionEngine> mCompositionEngine;
2245 StrictMock<renderengine::mock::RenderEngine> mRenderEngine;
2246 mock::DisplayColorProfile* mDisplayColorProfile = new StrictMock<mock::DisplayColorProfile>();
2247 mock::RenderSurface* mRenderSurface = new StrictMock<mock::RenderSurface>();
Lloyd Pique01c77c12019-04-17 12:48:32 -07002248 StrictMock<mock::OutputLayer> mOutputLayer1;
2249 StrictMock<mock::OutputLayer> mOutputLayer2;
Lloyd Piquea38ea7e2019-04-16 18:10:26 -07002250 StrictMock<OutputPartialMock> mOutput;
Lloyd Pique56eba802019-08-28 15:45:25 -07002251 sp<GraphicBuffer> mOutputBuffer = new GraphicBuffer();
2252};
2253
2254const Rect OutputComposeSurfacesTest::kDefaultOutputFrame{1001, 1002, 1003, 1004};
2255const Rect OutputComposeSurfacesTest::kDefaultOutputViewport{1005, 1006, 1007, 1008};
2256const Rect OutputComposeSurfacesTest::kDefaultOutputScissor{1009, 1010, 1011, 1012};
2257const mat4 OutputComposeSurfacesTest::kDefaultColorTransformMat{mat4() * 0.5};
2258
2259// TODO(b/121291683): Expand unit test coverage for composeSurfaces beyond these
2260// basic tests.
2261
2262TEST_F(OutputComposeSurfacesTest, doesNothingIfNoClientComposition) {
2263 mOutput.editState().usesClientComposition = false;
2264
2265 Region debugRegion;
Lloyd Piqued3d69882019-02-28 16:03:46 -08002266 std::optional<base::unique_fd> readyFence = mOutput.composeSurfaces(debugRegion);
2267 EXPECT_TRUE(readyFence);
Lloyd Pique56eba802019-08-28 15:45:25 -07002268}
2269
2270TEST_F(OutputComposeSurfacesTest, worksIfNoClientLayersQueued) {
2271 const Region kDebugRegion{Rect{100, 101, 102, 103}};
2272
2273 constexpr float kDefaultMaxLuminance = 1.0f;
2274 constexpr float kDefaultAvgLuminance = 0.7f;
2275 constexpr float kDefaultMinLuminance = 0.1f;
2276 HdrCapabilities HdrCapabilities{{},
2277 kDefaultMaxLuminance,
2278 kDefaultAvgLuminance,
2279 kDefaultMinLuminance};
2280
2281 EXPECT_CALL(mRenderEngine, supportsProtectedContent()).WillOnce(Return(false));
2282 EXPECT_CALL(mRenderEngine, drawLayers(_, _, _, true, _, _)).Times(1);
2283
2284 EXPECT_CALL(*mDisplayColorProfile, hasWideColorGamut()).WillOnce(Return(true));
2285 EXPECT_CALL(*mDisplayColorProfile, getHdrCapabilities()).WillOnce(ReturnRef(HdrCapabilities));
2286
2287 EXPECT_CALL(*mRenderSurface, dequeueBuffer(_)).WillOnce(Return(mOutputBuffer));
2288
2289 EXPECT_CALL(mOutput, getSkipColorTransform()).WillOnce(Return(false));
2290 EXPECT_CALL(mOutput, generateClientCompositionRequests(false, _)).Times(1);
2291 EXPECT_CALL(mOutput, appendRegionFlashRequests(RegionEq(kDebugRegion), _)).Times(1);
2292 EXPECT_CALL(mOutput, setExpensiveRenderingExpected(true)).Times(1);
2293 EXPECT_CALL(mOutput, setExpensiveRenderingExpected(false)).Times(1);
2294
Lloyd Piqued3d69882019-02-28 16:03:46 -08002295 std::optional<base::unique_fd> readyFence = mOutput.composeSurfaces(kDebugRegion);
2296 EXPECT_TRUE(readyFence);
Lloyd Pique56eba802019-08-28 15:45:25 -07002297}
2298
2299/*
2300 * Output::generateClientCompositionRequests()
2301 */
2302
2303struct GenerateClientCompositionRequestsTest : public testing::Test {
Lloyd Piquefaa3f192019-11-14 14:05:09 -08002304 struct OutputPartialMock : public OutputPartialMockBase {
Lloyd Piquea38ea7e2019-04-16 18:10:26 -07002305 // compositionengine::Output overrides
Lloyd Pique56eba802019-08-28 15:45:25 -07002306 std::vector<renderengine::LayerSettings> generateClientCompositionRequests(
2307 bool supportsProtectedContent, Region& clearRegion) override {
2308 return impl::Output::generateClientCompositionRequests(supportsProtectedContent,
2309 clearRegion);
2310 }
2311 };
2312
2313 GenerateClientCompositionRequestsTest() {
2314 mOutput.setDisplayColorProfileForTest(
2315 std::unique_ptr<DisplayColorProfile>(mDisplayColorProfile));
2316 mOutput.setRenderSurfaceForTest(std::unique_ptr<RenderSurface>(mRenderSurface));
2317 }
2318
Lloyd Pique56eba802019-08-28 15:45:25 -07002319 mock::DisplayColorProfile* mDisplayColorProfile = new StrictMock<mock::DisplayColorProfile>();
2320 mock::RenderSurface* mRenderSurface = new StrictMock<mock::RenderSurface>();
Lloyd Piquea38ea7e2019-04-16 18:10:26 -07002321 StrictMock<OutputPartialMock> mOutput;
Lloyd Pique56eba802019-08-28 15:45:25 -07002322};
2323
2324// TODO(b/121291683): Add more unit test coverage for generateClientCompositionRequests
2325
2326TEST_F(GenerateClientCompositionRequestsTest, worksForLandscapeModeSplitScreen) {
2327 // In split-screen landscape mode, the screen is rotated 90 degrees, with
2328 // one layer on the left covering the left side of the output, and one layer
2329 // on the right covering that side of the output.
2330
Lloyd Pique01c77c12019-04-17 12:48:32 -07002331 StrictMock<mock::OutputLayer> leftOutputLayer;
2332 StrictMock<mock::OutputLayer> rightOutputLayer;
Lloyd Pique56eba802019-08-28 15:45:25 -07002333
2334 StrictMock<mock::Layer> leftLayer;
2335 StrictMock<mock::LayerFE> leftLayerFE;
2336 StrictMock<mock::Layer> rightLayer;
2337 StrictMock<mock::LayerFE> rightLayerFE;
2338
2339 impl::OutputLayerCompositionState leftOutputLayerState;
2340 leftOutputLayerState.clearClientTarget = false;
Lloyd Piquea2468662019-03-07 21:31:06 -08002341 leftOutputLayerState.visibleRegion = Region{Rect{0, 0, 1000, 1000}};
Lloyd Pique56eba802019-08-28 15:45:25 -07002342
Lloyd Pique9755fb72019-03-26 14:44:40 -07002343 LayerFECompositionState leftLayerFEState;
2344 leftLayerFEState.isOpaque = true;
Lloyd Pique56eba802019-08-28 15:45:25 -07002345
2346 const half3 leftLayerColor{1.f, 0.f, 0.f};
2347 renderengine::LayerSettings leftLayerRESettings;
2348 leftLayerRESettings.source.solidColor = leftLayerColor;
2349
2350 impl::OutputLayerCompositionState rightOutputLayerState;
2351 rightOutputLayerState.clearClientTarget = false;
Lloyd Piquea2468662019-03-07 21:31:06 -08002352 rightOutputLayerState.visibleRegion = Region{Rect{1000, 0, 2000, 1000}};
Lloyd Pique56eba802019-08-28 15:45:25 -07002353
Lloyd Pique9755fb72019-03-26 14:44:40 -07002354 LayerFECompositionState rightLayerFEState;
2355 rightLayerFEState.isOpaque = true;
Lloyd Pique56eba802019-08-28 15:45:25 -07002356
2357 const half3 rightLayerColor{0.f, 1.f, 0.f};
2358 renderengine::LayerSettings rightLayerRESettings;
2359 rightLayerRESettings.source.solidColor = rightLayerColor;
2360
Lloyd Pique01c77c12019-04-17 12:48:32 -07002361 EXPECT_CALL(leftOutputLayer, getState()).WillRepeatedly(ReturnRef(leftOutputLayerState));
2362 EXPECT_CALL(leftOutputLayer, getLayer()).WillRepeatedly(ReturnRef(leftLayer));
2363 EXPECT_CALL(leftOutputLayer, getLayerFE()).WillRepeatedly(ReturnRef(leftLayerFE));
2364 EXPECT_CALL(leftOutputLayer, requiresClientComposition()).WillRepeatedly(Return(true));
2365 EXPECT_CALL(leftOutputLayer, needsFiltering()).WillRepeatedly(Return(false));
Lloyd Pique9755fb72019-03-26 14:44:40 -07002366 EXPECT_CALL(leftLayer, getFEState()).WillRepeatedly(ReturnRef(leftLayerFEState));
Lloyd Pique56eba802019-08-28 15:45:25 -07002367 EXPECT_CALL(leftLayerFE, prepareClientComposition(_)).WillOnce(Return(leftLayerRESettings));
Adithya Srinivasanb69e0762019-11-11 18:39:53 -08002368 EXPECT_CALL(leftOutputLayer, editState()).WillRepeatedly(ReturnRef(leftOutputLayerState));
Lloyd Pique56eba802019-08-28 15:45:25 -07002369
Lloyd Pique01c77c12019-04-17 12:48:32 -07002370 EXPECT_CALL(rightOutputLayer, getState()).WillRepeatedly(ReturnRef(rightOutputLayerState));
2371 EXPECT_CALL(rightOutputLayer, getLayer()).WillRepeatedly(ReturnRef(rightLayer));
2372 EXPECT_CALL(rightOutputLayer, getLayerFE()).WillRepeatedly(ReturnRef(rightLayerFE));
2373 EXPECT_CALL(rightOutputLayer, requiresClientComposition()).WillRepeatedly(Return(true));
2374 EXPECT_CALL(rightOutputLayer, needsFiltering()).WillRepeatedly(Return(false));
Lloyd Pique9755fb72019-03-26 14:44:40 -07002375 EXPECT_CALL(rightLayer, getFEState()).WillRepeatedly(ReturnRef(rightLayerFEState));
Lloyd Pique56eba802019-08-28 15:45:25 -07002376 EXPECT_CALL(rightLayerFE, prepareClientComposition(_)).WillOnce(Return(rightLayerRESettings));
Adithya Srinivasanb69e0762019-11-11 18:39:53 -08002377 EXPECT_CALL(rightOutputLayer, editState()).WillRepeatedly(ReturnRef(rightOutputLayerState));
Lloyd Pique56eba802019-08-28 15:45:25 -07002378
Lloyd Pique01c77c12019-04-17 12:48:32 -07002379 EXPECT_CALL(mOutput, getOutputLayerCount()).WillRepeatedly(Return(2u));
2380 EXPECT_CALL(mOutput, getOutputLayerOrderedByZByIndex(0u))
2381 .WillRepeatedly(Return(&leftOutputLayer));
2382 EXPECT_CALL(mOutput, getOutputLayerOrderedByZByIndex(1u))
2383 .WillRepeatedly(Return(&rightOutputLayer));
Lloyd Pique56eba802019-08-28 15:45:25 -07002384
2385 const Rect kPortraitFrame(0, 0, 1000, 2000);
2386 const Rect kPortraitViewport(0, 0, 2000, 1000);
2387 const Rect kPortraitScissor(0, 0, 1000, 2000);
2388 const uint32_t kPortraitOrientation = TR_ROT_90;
2389
2390 mOutput.editState().frame = kPortraitFrame;
2391 mOutput.editState().viewport = kPortraitViewport;
2392 mOutput.editState().scissor = kPortraitScissor;
2393 mOutput.editState().transform = ui::Transform{kPortraitOrientation};
2394 mOutput.editState().orientation = kPortraitOrientation;
2395 mOutput.editState().needsFiltering = true;
2396 mOutput.editState().isSecure = false;
2397
2398 constexpr bool supportsProtectedContent = false;
2399 Region clearRegion;
2400 auto requests =
2401 mOutput.generateClientCompositionRequests(supportsProtectedContent, clearRegion);
2402
2403 ASSERT_EQ(2u, requests.size());
2404 EXPECT_EQ(leftLayerColor, requests[0].source.solidColor);
2405 EXPECT_EQ(rightLayerColor, requests[1].source.solidColor);
2406}
2407
2408TEST_F(GenerateClientCompositionRequestsTest, ignoresLayersThatDoNotIntersectWithViewport) {
2409 // Layers whose visible region does not intersect with the viewport will be
2410 // skipped when generating client composition request state.
2411
Lloyd Pique01c77c12019-04-17 12:48:32 -07002412 StrictMock<mock::OutputLayer> outputLayer;
Lloyd Pique56eba802019-08-28 15:45:25 -07002413 StrictMock<mock::Layer> layer;
2414 StrictMock<mock::LayerFE> layerFE;
2415
2416 impl::OutputLayerCompositionState outputLayerState;
2417 outputLayerState.clearClientTarget = false;
Lloyd Piquea2468662019-03-07 21:31:06 -08002418 outputLayerState.visibleRegion = Region{Rect{3000, 0, 4000, 1000}};
Lloyd Pique56eba802019-08-28 15:45:25 -07002419
Lloyd Pique9755fb72019-03-26 14:44:40 -07002420 LayerFECompositionState layerFEState;
2421 layerFEState.isOpaque = true;
Lloyd Pique56eba802019-08-28 15:45:25 -07002422
Lloyd Pique01c77c12019-04-17 12:48:32 -07002423 EXPECT_CALL(outputLayer, getState()).WillRepeatedly(ReturnRef(outputLayerState));
2424 EXPECT_CALL(outputLayer, getLayer()).WillRepeatedly(ReturnRef(layer));
2425 EXPECT_CALL(outputLayer, getLayerFE()).WillRepeatedly(ReturnRef(layerFE));
2426 EXPECT_CALL(outputLayer, requiresClientComposition()).WillRepeatedly(Return(true));
2427 EXPECT_CALL(outputLayer, needsFiltering()).WillRepeatedly(Return(false));
Lloyd Pique9755fb72019-03-26 14:44:40 -07002428 EXPECT_CALL(layer, getFEState()).WillRepeatedly(ReturnRef(layerFEState));
Lloyd Pique56eba802019-08-28 15:45:25 -07002429 EXPECT_CALL(layerFE, prepareClientComposition(_)).Times(0);
Adithya Srinivasanb69e0762019-11-11 18:39:53 -08002430 EXPECT_CALL(outputLayer, editState()).WillRepeatedly(ReturnRef(outputLayerState));
Lloyd Pique56eba802019-08-28 15:45:25 -07002431
Lloyd Pique01c77c12019-04-17 12:48:32 -07002432 EXPECT_CALL(mOutput, getOutputLayerCount()).WillRepeatedly(Return(1u));
2433 EXPECT_CALL(mOutput, getOutputLayerOrderedByZByIndex(0u)).WillRepeatedly(Return(&outputLayer));
Lloyd Pique56eba802019-08-28 15:45:25 -07002434
2435 const Rect kPortraitFrame(0, 0, 1000, 2000);
2436 const Rect kPortraitViewport(0, 0, 2000, 1000);
2437 const Rect kPortraitScissor(0, 0, 1000, 2000);
2438 const uint32_t kPortraitOrientation = TR_ROT_90;
2439
2440 mOutput.editState().frame = kPortraitFrame;
2441 mOutput.editState().viewport = kPortraitViewport;
2442 mOutput.editState().scissor = kPortraitScissor;
2443 mOutput.editState().transform = ui::Transform{kPortraitOrientation};
2444 mOutput.editState().orientation = kPortraitOrientation;
2445 mOutput.editState().needsFiltering = true;
2446 mOutput.editState().isSecure = false;
2447
2448 constexpr bool supportsProtectedContent = false;
2449 Region clearRegion;
2450 auto requests =
2451 mOutput.generateClientCompositionRequests(supportsProtectedContent, clearRegion);
2452
2453 EXPECT_EQ(0u, requests.size());
2454}
2455
Lloyd Piquec2d54d42019-08-28 18:04:21 -07002456TEST_F(GenerateClientCompositionRequestsTest, clearsDeviceLayesAfterFirst) {
2457 // If client composition is performed with some layers set to use device
2458 // composition, device layers after the first layer (device or client) will
2459 // clear the frame buffer if they are opaque and if that layer has a flag
2460 // set to do so. The first layer is skipped as the frame buffer is already
2461 // expected to be clear.
2462
Lloyd Pique01c77c12019-04-17 12:48:32 -07002463 StrictMock<mock::OutputLayer> leftOutputLayer;
2464 StrictMock<mock::OutputLayer> rightOutputLayer;
Lloyd Piquec2d54d42019-08-28 18:04:21 -07002465
2466 StrictMock<mock::Layer> leftLayer;
2467 StrictMock<mock::LayerFE> leftLayerFE;
2468 StrictMock<mock::Layer> rightLayer;
2469 StrictMock<mock::LayerFE> rightLayerFE;
2470
2471 impl::OutputLayerCompositionState leftOutputLayerState;
2472 leftOutputLayerState.clearClientTarget = true;
Lloyd Piquea2468662019-03-07 21:31:06 -08002473 leftOutputLayerState.visibleRegion = Region{Rect{0, 0, 1000, 1000}};
Lloyd Piquec2d54d42019-08-28 18:04:21 -07002474
Lloyd Pique9755fb72019-03-26 14:44:40 -07002475 LayerFECompositionState leftLayerFEState;
2476 leftLayerFEState.isOpaque = true;
Lloyd Piquec2d54d42019-08-28 18:04:21 -07002477
2478 impl::OutputLayerCompositionState rightOutputLayerState;
2479 rightOutputLayerState.clearClientTarget = true;
Lloyd Piquea2468662019-03-07 21:31:06 -08002480 rightOutputLayerState.visibleRegion = Region{Rect{1000, 0, 2000, 1000}};
Lloyd Piquec2d54d42019-08-28 18:04:21 -07002481
Lloyd Pique9755fb72019-03-26 14:44:40 -07002482 LayerFECompositionState rightLayerFEState;
2483 rightLayerFEState.isOpaque = true;
Lloyd Piquec2d54d42019-08-28 18:04:21 -07002484
2485 const half3 rightLayerColor{0.f, 1.f, 0.f};
2486 renderengine::LayerSettings rightLayerRESettings;
2487 rightLayerRESettings.geometry.boundaries = FloatRect{456, 0, 0, 0};
2488 rightLayerRESettings.source.solidColor = rightLayerColor;
2489
Lloyd Pique01c77c12019-04-17 12:48:32 -07002490 EXPECT_CALL(leftOutputLayer, getState()).WillRepeatedly(ReturnRef(leftOutputLayerState));
2491 EXPECT_CALL(leftOutputLayer, getLayer()).WillRepeatedly(ReturnRef(leftLayer));
2492 EXPECT_CALL(leftOutputLayer, getLayerFE()).WillRepeatedly(ReturnRef(leftLayerFE));
2493 EXPECT_CALL(leftOutputLayer, requiresClientComposition()).WillRepeatedly(Return(false));
2494 EXPECT_CALL(leftOutputLayer, needsFiltering()).WillRepeatedly(Return(false));
Lloyd Pique9755fb72019-03-26 14:44:40 -07002495 EXPECT_CALL(leftLayer, getFEState()).WillRepeatedly(ReturnRef(leftLayerFEState));
Adithya Srinivasanb69e0762019-11-11 18:39:53 -08002496 EXPECT_CALL(leftOutputLayer, editState()).WillRepeatedly(ReturnRef(leftOutputLayerState));
Lloyd Piquec2d54d42019-08-28 18:04:21 -07002497
Lloyd Pique01c77c12019-04-17 12:48:32 -07002498 EXPECT_CALL(rightOutputLayer, getState()).WillRepeatedly(ReturnRef(rightOutputLayerState));
2499 EXPECT_CALL(rightOutputLayer, getLayer()).WillRepeatedly(ReturnRef(rightLayer));
2500 EXPECT_CALL(rightOutputLayer, getLayerFE()).WillRepeatedly(ReturnRef(rightLayerFE));
2501 EXPECT_CALL(rightOutputLayer, requiresClientComposition()).WillRepeatedly(Return(false));
2502 EXPECT_CALL(rightOutputLayer, needsFiltering()).WillRepeatedly(Return(false));
Lloyd Pique9755fb72019-03-26 14:44:40 -07002503 EXPECT_CALL(rightLayer, getFEState()).WillRepeatedly(ReturnRef(rightLayerFEState));
Lloyd Piquec2d54d42019-08-28 18:04:21 -07002504 EXPECT_CALL(rightLayerFE, prepareClientComposition(_)).WillOnce(Return(rightLayerRESettings));
Adithya Srinivasanb69e0762019-11-11 18:39:53 -08002505 EXPECT_CALL(rightOutputLayer, editState()).WillRepeatedly(ReturnRef(rightOutputLayerState));
Lloyd Piquec2d54d42019-08-28 18:04:21 -07002506
Lloyd Pique01c77c12019-04-17 12:48:32 -07002507 EXPECT_CALL(mOutput, getOutputLayerCount()).WillRepeatedly(Return(2u));
2508 EXPECT_CALL(mOutput, getOutputLayerOrderedByZByIndex(0u))
2509 .WillRepeatedly(Return(&leftOutputLayer));
2510 EXPECT_CALL(mOutput, getOutputLayerOrderedByZByIndex(1u))
2511 .WillRepeatedly(Return(&rightOutputLayer));
Lloyd Piquec2d54d42019-08-28 18:04:21 -07002512
2513 const Rect kPortraitFrame(0, 0, 1000, 2000);
2514 const Rect kPortraitViewport(0, 0, 2000, 1000);
2515 const Rect kPortraitScissor(0, 0, 1000, 2000);
2516 const uint32_t kPortraitOrientation = TR_ROT_90;
2517
2518 mOutput.editState().frame = kPortraitFrame;
2519 mOutput.editState().viewport = kPortraitViewport;
2520 mOutput.editState().scissor = kPortraitScissor;
2521 mOutput.editState().transform = ui::Transform{kPortraitOrientation};
2522 mOutput.editState().orientation = kPortraitOrientation;
2523 mOutput.editState().needsFiltering = true;
2524 mOutput.editState().isSecure = false;
2525
2526 constexpr bool supportsProtectedContent = false;
2527 Region clearRegion;
2528 auto requests =
2529 mOutput.generateClientCompositionRequests(supportsProtectedContent, clearRegion);
2530
2531 const half3 clearColor{0.f, 0.f, 0.f};
2532
2533 ASSERT_EQ(1u, requests.size());
2534 EXPECT_EQ(456.f, requests[0].geometry.boundaries.left);
2535 EXPECT_EQ(clearColor, requests[0].source.solidColor);
2536}
2537
Lloyd Pique32cbe282018-10-19 13:09:22 -07002538} // namespace
2539} // namespace android::compositionengine