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