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