blob: 746a1c39cd5ed0097f264b1326b1a8e388b23d6b [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
670TEST_F(OutputTest, updateAndWriteCompositionState_takesEarlyOutIfNotEnabled) {
671 mOutput->editState().isEnabled = false;
672
673 CompositionRefreshArgs args;
674 mOutput->updateAndWriteCompositionState(args);
675}
676
677TEST_F(OutputTest, updateAndWriteCompositionState_updatesLayers) {
678 mOutput->editState().isEnabled = true;
679 mock::OutputLayer* outputLayer = new StrictMock<mock::OutputLayer>();
680 mOutput->injectOutputLayerForTest(std::unique_ptr<OutputLayer>(outputLayer));
681
682 EXPECT_CALL(*outputLayer, updateCompositionState(true, true)).Times(1);
683 EXPECT_CALL(*outputLayer, writeStateToHWC(true)).Times(1);
684
685 CompositionRefreshArgs args;
686 args.updatingGeometryThisFrame = true;
687 args.devOptForceClientComposition = true;
688 mOutput->updateAndWriteCompositionState(args);
689}
690
691/*
Lloyd Pique66d68602019-02-13 14:23:31 -0800692 * Output::prepareFrame()
693 */
694
695struct OutputPrepareFrameTest : public testing::Test {
Lloyd Piquefaa3f192019-11-14 14:05:09 -0800696 struct OutputPartialMock : public OutputPartialMockBase {
Lloyd Pique66d68602019-02-13 14:23:31 -0800697 // Sets up the helper functions called by prepareFrame to use a mock
698 // implementations.
699 MOCK_METHOD0(chooseCompositionStrategy, void());
700 };
701
702 OutputPrepareFrameTest() {
703 mOutput.setDisplayColorProfileForTest(
704 std::unique_ptr<DisplayColorProfile>(mDisplayColorProfile));
705 mOutput.setRenderSurfaceForTest(std::unique_ptr<RenderSurface>(mRenderSurface));
706 }
707
708 StrictMock<mock::CompositionEngine> mCompositionEngine;
709 mock::DisplayColorProfile* mDisplayColorProfile = new StrictMock<mock::DisplayColorProfile>();
710 mock::RenderSurface* mRenderSurface = new StrictMock<mock::RenderSurface>();
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700711 StrictMock<OutputPartialMock> mOutput;
Lloyd Pique66d68602019-02-13 14:23:31 -0800712};
713
714TEST_F(OutputPrepareFrameTest, takesEarlyOutIfNotEnabled) {
715 mOutput.editState().isEnabled = false;
716
717 mOutput.prepareFrame();
718}
719
720TEST_F(OutputPrepareFrameTest, delegatesToChooseCompositionStrategyAndRenderSurface) {
721 mOutput.editState().isEnabled = true;
722 mOutput.editState().usesClientComposition = false;
723 mOutput.editState().usesDeviceComposition = true;
724
725 EXPECT_CALL(mOutput, chooseCompositionStrategy()).Times(1);
726 EXPECT_CALL(*mRenderSurface, prepareFrame(false, true));
727
728 mOutput.prepareFrame();
729}
730
731// Note: Use OutputTest and not OutputPrepareFrameTest, so the real
732// base chooseCompositionStrategy() is invoked.
733TEST_F(OutputTest, prepareFrameSetsClientCompositionOnlyByDefault) {
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700734 mOutput->editState().isEnabled = true;
735 mOutput->editState().usesClientComposition = false;
736 mOutput->editState().usesDeviceComposition = true;
Lloyd Pique66d68602019-02-13 14:23:31 -0800737
738 EXPECT_CALL(*mRenderSurface, prepareFrame(true, false));
739
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700740 mOutput->prepareFrame();
Lloyd Pique66d68602019-02-13 14:23:31 -0800741
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700742 EXPECT_TRUE(mOutput->getState().usesClientComposition);
743 EXPECT_FALSE(mOutput->getState().usesDeviceComposition);
Lloyd Pique66d68602019-02-13 14:23:31 -0800744}
745
Lloyd Pique56eba802019-08-28 15:45:25 -0700746/*
Lloyd Piquefaa3f192019-11-14 14:05:09 -0800747 * Output::present()
748 */
749
750struct OutputPresentTest : public testing::Test {
751 struct OutputPartialMock : public OutputPartialMockBase {
752 // All child helper functions Output::present() are defined as mocks,
753 // and those are tested separately, allowing the present() test to
754 // just cover the high level flow.
755 MOCK_METHOD1(updateColorProfile, void(const compositionengine::CompositionRefreshArgs&));
756 MOCK_METHOD1(updateAndWriteCompositionState,
757 void(const compositionengine::CompositionRefreshArgs&));
758 MOCK_METHOD1(setColorTransform, void(const compositionengine::CompositionRefreshArgs&));
759 MOCK_METHOD0(beginFrame, void());
760 MOCK_METHOD0(prepareFrame, void());
761 MOCK_METHOD1(devOptRepaintFlash, void(const compositionengine::CompositionRefreshArgs&));
762 MOCK_METHOD1(finishFrame, void(const compositionengine::CompositionRefreshArgs&));
763 MOCK_METHOD0(postFramebuffer, void());
764 };
765
766 StrictMock<OutputPartialMock> mOutput;
767};
768
769TEST_F(OutputPresentTest, justInvokesChildFunctionsInSequence) {
770 CompositionRefreshArgs args;
771
772 InSequence seq;
773 EXPECT_CALL(mOutput, updateColorProfile(Ref(args)));
774 EXPECT_CALL(mOutput, updateAndWriteCompositionState(Ref(args)));
775 EXPECT_CALL(mOutput, setColorTransform(Ref(args)));
776 EXPECT_CALL(mOutput, beginFrame());
777 EXPECT_CALL(mOutput, prepareFrame());
778 EXPECT_CALL(mOutput, devOptRepaintFlash(Ref(args)));
779 EXPECT_CALL(mOutput, finishFrame(Ref(args)));
780 EXPECT_CALL(mOutput, postFramebuffer());
781
782 mOutput.present(args);
783}
784
785/*
786 * Output::updateColorProfile()
787 */
788
Lloyd Pique17ca7422019-11-14 14:24:10 -0800789struct OutputUpdateColorProfileTest : public testing::Test {
790 using TestType = OutputUpdateColorProfileTest;
791
792 struct OutputPartialMock : public OutputPartialMockBase {
793 // All child helper functions Output::present() are defined as mocks,
794 // and those are tested separately, allowing the present() test to
795 // just cover the high level flow.
796 MOCK_METHOD1(setColorProfile, void(const ColorProfile&));
797 };
798
799 struct Layer {
800 Layer() {
801 EXPECT_CALL(mOutputLayer, getLayer()).WillRepeatedly(ReturnRef(mLayer));
802 EXPECT_CALL(mOutputLayer, getLayerFE()).WillRepeatedly(ReturnRef(mLayerFE));
803 EXPECT_CALL(mLayer, getFEState()).WillRepeatedly(ReturnRef(mLayerFEState));
804 }
805
806 StrictMock<mock::OutputLayer> mOutputLayer;
807 StrictMock<mock::Layer> mLayer;
808 StrictMock<mock::LayerFE> mLayerFE;
809 LayerFECompositionState mLayerFEState;
810 };
811
812 OutputUpdateColorProfileTest() {
813 mOutput.setDisplayColorProfileForTest(
814 std::unique_ptr<DisplayColorProfile>(mDisplayColorProfile));
815 mOutput.setRenderSurfaceForTest(std::unique_ptr<RenderSurface>(mRenderSurface));
816
817 EXPECT_CALL(mOutput, getOutputLayerOrderedByZByIndex(0))
818 .WillRepeatedly(Return(&mLayer1.mOutputLayer));
819 EXPECT_CALL(mOutput, getOutputLayerOrderedByZByIndex(1))
820 .WillRepeatedly(Return(&mLayer2.mOutputLayer));
821 EXPECT_CALL(mOutput, getOutputLayerOrderedByZByIndex(2))
822 .WillRepeatedly(Return(&mLayer3.mOutputLayer));
823 }
824
825 struct ExecuteState : public CallOrderStateMachineHelper<TestType, ExecuteState> {
826 void execute() { getInstance()->mOutput.updateColorProfile(getInstance()->mRefreshArgs); }
827 };
828
829 mock::DisplayColorProfile* mDisplayColorProfile = new StrictMock<mock::DisplayColorProfile>();
830 mock::RenderSurface* mRenderSurface = new StrictMock<mock::RenderSurface>();
831 StrictMock<OutputPartialMock> mOutput;
832
833 Layer mLayer1;
834 Layer mLayer2;
835 Layer mLayer3;
836
837 CompositionRefreshArgs mRefreshArgs;
838};
839
840// TODO(b/144522012): Refactor Output::updateColorProfile and the related code
841// to make it easier to write unit tests.
842
843TEST_F(OutputUpdateColorProfileTest, setsAColorProfileWhenUnmanaged) {
844 // When the outputColorSetting is set to kUnmanaged, the implementation sets
845 // a simple default color profile without looking at anything else.
846
847 EXPECT_CALL(mOutput, getOutputLayerCount()).WillRepeatedly(Return(3));
848 EXPECT_CALL(mOutput,
849 setColorProfile(ColorProfileEq(
850 ColorProfile{ui::ColorMode::NATIVE, ui::Dataspace::UNKNOWN,
851 ui::RenderIntent::COLORIMETRIC, ui::Dataspace::UNKNOWN})));
852
853 mRefreshArgs.outputColorSetting = OutputColorSetting::kUnmanaged;
854 mRefreshArgs.colorSpaceAgnosticDataspace = ui::Dataspace::UNKNOWN;
855
856 mOutput.updateColorProfile(mRefreshArgs);
857}
858
859struct OutputUpdateColorProfileTest_GetBestColorModeResultBecomesSetProfile
860 : public OutputUpdateColorProfileTest {
861 OutputUpdateColorProfileTest_GetBestColorModeResultBecomesSetProfile() {
862 EXPECT_CALL(mOutput, getOutputLayerCount()).WillRepeatedly(Return(0));
863 mRefreshArgs.outputColorSetting = OutputColorSetting::kEnhanced;
864 mRefreshArgs.colorSpaceAgnosticDataspace = ui::Dataspace::UNKNOWN;
865 }
866
867 struct ExpectBestColorModeCallResultUsedToSetColorProfileState
868 : public CallOrderStateMachineHelper<
869 TestType, ExpectBestColorModeCallResultUsedToSetColorProfileState> {
870 [[nodiscard]] auto expectBestColorModeCallResultUsedToSetColorProfile(
871 ui::ColorMode colorMode, ui::Dataspace dataspace, ui::RenderIntent renderIntent) {
872 EXPECT_CALL(*getInstance()->mDisplayColorProfile,
873 getBestColorMode(ui::Dataspace::V0_SRGB, ui::RenderIntent::ENHANCE, _, _,
874 _))
875 .WillOnce(DoAll(SetArgPointee<2>(dataspace), SetArgPointee<3>(colorMode),
876 SetArgPointee<4>(renderIntent)));
877 EXPECT_CALL(getInstance()->mOutput,
878 setColorProfile(
879 ColorProfileEq(ColorProfile{colorMode, dataspace, renderIntent,
880 ui::Dataspace::UNKNOWN})));
881 return nextState<ExecuteState>();
882 }
883 };
884
885 // Call this member function to start using the mini-DSL defined above.
886 [[nodiscard]] auto verify() {
887 return ExpectBestColorModeCallResultUsedToSetColorProfileState::make(this);
888 }
889};
890
891TEST_F(OutputUpdateColorProfileTest_GetBestColorModeResultBecomesSetProfile,
892 Native_Unknown_Colorimetric_Set) {
893 verify().expectBestColorModeCallResultUsedToSetColorProfile(ui::ColorMode::NATIVE,
894 ui::Dataspace::UNKNOWN,
895 ui::RenderIntent::COLORIMETRIC)
896 .execute();
897}
898
899TEST_F(OutputUpdateColorProfileTest_GetBestColorModeResultBecomesSetProfile,
900 DisplayP3_DisplayP3_Enhance_Set) {
901 verify().expectBestColorModeCallResultUsedToSetColorProfile(ui::ColorMode::DISPLAY_P3,
902 ui::Dataspace::DISPLAY_P3,
903 ui::RenderIntent::ENHANCE)
904 .execute();
905}
906
907struct OutputUpdateColorProfileTest_ColorSpaceAgnosticeDataspaceAffectsSetColorProfile
908 : public OutputUpdateColorProfileTest {
909 OutputUpdateColorProfileTest_ColorSpaceAgnosticeDataspaceAffectsSetColorProfile() {
910 EXPECT_CALL(mOutput, getOutputLayerCount()).WillRepeatedly(Return(0));
911 EXPECT_CALL(*mDisplayColorProfile,
912 getBestColorMode(ui::Dataspace::V0_SRGB, ui::RenderIntent::ENHANCE, _, _, _))
913 .WillRepeatedly(DoAll(SetArgPointee<2>(ui::Dataspace::UNKNOWN),
914 SetArgPointee<3>(ui::ColorMode::NATIVE),
915 SetArgPointee<4>(ui::RenderIntent::COLORIMETRIC)));
916 mRefreshArgs.outputColorSetting = OutputColorSetting::kEnhanced;
917 }
918
919 struct IfColorSpaceAgnosticDataspaceSetToState
920 : public CallOrderStateMachineHelper<TestType, IfColorSpaceAgnosticDataspaceSetToState> {
921 [[nodiscard]] auto ifColorSpaceAgnosticDataspaceSetTo(ui::Dataspace dataspace) {
922 getInstance()->mRefreshArgs.colorSpaceAgnosticDataspace = dataspace;
923 return nextState<ThenExpectSetColorProfileCallUsesColorSpaceAgnosticDataspaceState>();
924 }
925 };
926
927 struct ThenExpectSetColorProfileCallUsesColorSpaceAgnosticDataspaceState
928 : public CallOrderStateMachineHelper<
929 TestType, ThenExpectSetColorProfileCallUsesColorSpaceAgnosticDataspaceState> {
930 [[nodiscard]] auto thenExpectSetColorProfileCallUsesColorSpaceAgnosticDataspace(
931 ui::Dataspace dataspace) {
932 EXPECT_CALL(getInstance()->mOutput,
933 setColorProfile(ColorProfileEq(
934 ColorProfile{ui::ColorMode::NATIVE, ui::Dataspace::UNKNOWN,
935 ui::RenderIntent::COLORIMETRIC, dataspace})));
936 return nextState<ExecuteState>();
937 }
938 };
939
940 // Call this member function to start using the mini-DSL defined above.
941 [[nodiscard]] auto verify() { return IfColorSpaceAgnosticDataspaceSetToState::make(this); }
942};
943
944TEST_F(OutputUpdateColorProfileTest_ColorSpaceAgnosticeDataspaceAffectsSetColorProfile, DisplayP3) {
945 verify().ifColorSpaceAgnosticDataspaceSetTo(ui::Dataspace::DISPLAY_P3)
946 .thenExpectSetColorProfileCallUsesColorSpaceAgnosticDataspace(ui::Dataspace::DISPLAY_P3)
947 .execute();
948}
949
950TEST_F(OutputUpdateColorProfileTest_ColorSpaceAgnosticeDataspaceAffectsSetColorProfile, V0_SRGB) {
951 verify().ifColorSpaceAgnosticDataspaceSetTo(ui::Dataspace::V0_SRGB)
952 .thenExpectSetColorProfileCallUsesColorSpaceAgnosticDataspace(ui::Dataspace::V0_SRGB)
953 .execute();
954}
955
956struct OutputUpdateColorProfileTest_TopmostLayerPreferenceSetsOutputPreference
957 : public OutputUpdateColorProfileTest {
958 // Internally the implementation looks through the dataspaces of all the
959 // visible layers. The topmost one that also has an actual dataspace
960 // preference set is used to drive subsequent choices.
961
962 OutputUpdateColorProfileTest_TopmostLayerPreferenceSetsOutputPreference() {
963 mRefreshArgs.outputColorSetting = OutputColorSetting::kEnhanced;
964 mRefreshArgs.colorSpaceAgnosticDataspace = ui::Dataspace::UNKNOWN;
965
966 EXPECT_CALL(mOutput, getOutputLayerCount()).WillRepeatedly(Return(3));
967 EXPECT_CALL(mOutput, setColorProfile(_)).WillRepeatedly(Return());
968 }
969
970 struct IfTopLayerDataspaceState
971 : public CallOrderStateMachineHelper<TestType, IfTopLayerDataspaceState> {
972 [[nodiscard]] auto ifTopLayerIs(ui::Dataspace dataspace) {
973 getInstance()->mLayer3.mLayerFEState.dataspace = dataspace;
974 return nextState<AndIfMiddleLayerDataspaceState>();
975 }
976 [[nodiscard]] auto ifTopLayerHasNoPreference() {
977 return ifTopLayerIs(ui::Dataspace::UNKNOWN);
978 }
979 };
980
981 struct AndIfMiddleLayerDataspaceState
982 : public CallOrderStateMachineHelper<TestType, AndIfMiddleLayerDataspaceState> {
983 [[nodiscard]] auto andIfMiddleLayerIs(ui::Dataspace dataspace) {
984 getInstance()->mLayer2.mLayerFEState.dataspace = dataspace;
985 return nextState<AndIfBottomLayerDataspaceState>();
986 }
987 [[nodiscard]] auto andIfMiddleLayerHasNoPreference() {
988 return andIfMiddleLayerIs(ui::Dataspace::UNKNOWN);
989 }
990 };
991
992 struct AndIfBottomLayerDataspaceState
993 : public CallOrderStateMachineHelper<TestType, AndIfBottomLayerDataspaceState> {
994 [[nodiscard]] auto andIfBottomLayerIs(ui::Dataspace dataspace) {
995 getInstance()->mLayer1.mLayerFEState.dataspace = dataspace;
996 return nextState<ThenExpectBestColorModeCallUsesState>();
997 }
998 [[nodiscard]] auto andIfBottomLayerHasNoPreference() {
999 return andIfBottomLayerIs(ui::Dataspace::UNKNOWN);
1000 }
1001 };
1002
1003 struct ThenExpectBestColorModeCallUsesState
1004 : public CallOrderStateMachineHelper<TestType, ThenExpectBestColorModeCallUsesState> {
1005 [[nodiscard]] auto thenExpectBestColorModeCallUses(ui::Dataspace dataspace) {
1006 EXPECT_CALL(*getInstance()->mDisplayColorProfile,
1007 getBestColorMode(dataspace, _, _, _, _));
1008 return nextState<ExecuteState>();
1009 }
1010 };
1011
1012 // Call this member function to start using the mini-DSL defined above.
1013 [[nodiscard]] auto verify() { return IfTopLayerDataspaceState::make(this); }
1014};
1015
1016TEST_F(OutputUpdateColorProfileTest_TopmostLayerPreferenceSetsOutputPreference,
1017 noStrongLayerPrefenceUses_V0_SRGB) {
1018 // If none of the layers indicate a preference, then V0_SRGB is the
1019 // preferred choice (subject to additional checks).
1020 verify().ifTopLayerHasNoPreference()
1021 .andIfMiddleLayerHasNoPreference()
1022 .andIfBottomLayerHasNoPreference()
1023 .thenExpectBestColorModeCallUses(ui::Dataspace::V0_SRGB)
1024 .execute();
1025}
1026
1027TEST_F(OutputUpdateColorProfileTest_TopmostLayerPreferenceSetsOutputPreference,
1028 ifTopmostUses_DisplayP3_Then_DisplayP3_Chosen) {
1029 // If only the topmost layer has a preference, then that is what is chosen.
1030 verify().ifTopLayerIs(ui::Dataspace::DISPLAY_P3)
1031 .andIfMiddleLayerHasNoPreference()
1032 .andIfBottomLayerHasNoPreference()
1033 .thenExpectBestColorModeCallUses(ui::Dataspace::DISPLAY_P3)
1034 .execute();
1035}
1036
1037TEST_F(OutputUpdateColorProfileTest_TopmostLayerPreferenceSetsOutputPreference,
1038 ifMiddleUses_DisplayP3_Then_DisplayP3_Chosen) {
1039 // If only the middle layer has a preference, that that is what is chosen.
1040 verify().ifTopLayerHasNoPreference()
1041 .andIfMiddleLayerIs(ui::Dataspace::DISPLAY_P3)
1042 .andIfBottomLayerHasNoPreference()
1043 .thenExpectBestColorModeCallUses(ui::Dataspace::DISPLAY_P3)
1044 .execute();
1045}
1046
1047TEST_F(OutputUpdateColorProfileTest_TopmostLayerPreferenceSetsOutputPreference,
1048 ifBottomUses_DisplayP3_Then_DisplayP3_Chosen) {
1049 // If only the middle layer has a preference, that that is what is chosen.
1050 verify().ifTopLayerHasNoPreference()
1051 .andIfMiddleLayerHasNoPreference()
1052 .andIfBottomLayerIs(ui::Dataspace::DISPLAY_P3)
1053 .thenExpectBestColorModeCallUses(ui::Dataspace::DISPLAY_P3)
1054 .execute();
1055}
1056
1057TEST_F(OutputUpdateColorProfileTest_TopmostLayerPreferenceSetsOutputPreference,
1058 ifTopUses_DisplayBT2020_AndBottomUses_DisplayP3_Then_DisplayBT2020_Chosen) {
1059 // If multiple layers have a preference, the topmost value is what is used.
1060 verify().ifTopLayerIs(ui::Dataspace::DISPLAY_BT2020)
1061 .andIfMiddleLayerHasNoPreference()
1062 .andIfBottomLayerIs(ui::Dataspace::DISPLAY_P3)
1063 .thenExpectBestColorModeCallUses(ui::Dataspace::DISPLAY_BT2020)
1064 .execute();
1065}
1066
1067TEST_F(OutputUpdateColorProfileTest_TopmostLayerPreferenceSetsOutputPreference,
1068 ifTopUses_DisplayP3_AndBottomUses_V0_SRGB_Then_DisplayP3_Chosen) {
1069 // If multiple layers have a preference, the topmost value is what is used.
1070 verify().ifTopLayerIs(ui::Dataspace::DISPLAY_P3)
1071 .andIfMiddleLayerHasNoPreference()
1072 .andIfBottomLayerIs(ui::Dataspace::DISPLAY_BT2020)
1073 .thenExpectBestColorModeCallUses(ui::Dataspace::DISPLAY_P3)
1074 .execute();
1075}
1076
1077struct OutputUpdateColorProfileTest_ForceOutputColorOverrides
1078 : public OutputUpdateColorProfileTest {
1079 // If CompositionRefreshArgs::forceOutputColorMode is set to some specific
1080 // values, it overrides the layer dataspace choice.
1081
1082 OutputUpdateColorProfileTest_ForceOutputColorOverrides() {
1083 mRefreshArgs.outputColorSetting = OutputColorSetting::kEnhanced;
1084 mRefreshArgs.colorSpaceAgnosticDataspace = ui::Dataspace::UNKNOWN;
1085
1086 mLayer1.mLayerFEState.dataspace = ui::Dataspace::DISPLAY_BT2020;
1087
1088 EXPECT_CALL(mOutput, getOutputLayerCount()).WillRepeatedly(Return(1));
1089 EXPECT_CALL(mOutput, setColorProfile(_)).WillRepeatedly(Return());
1090 }
1091
1092 struct IfForceOutputColorModeState
1093 : public CallOrderStateMachineHelper<TestType, IfForceOutputColorModeState> {
1094 [[nodiscard]] auto ifForceOutputColorMode(ui::ColorMode colorMode) {
1095 getInstance()->mRefreshArgs.forceOutputColorMode = colorMode;
1096 return nextState<ThenExpectBestColorModeCallUsesState>();
1097 }
1098 [[nodiscard]] auto ifNoOverride() { return ifForceOutputColorMode(ui::ColorMode::NATIVE); }
1099 };
1100
1101 struct ThenExpectBestColorModeCallUsesState
1102 : public CallOrderStateMachineHelper<TestType, ThenExpectBestColorModeCallUsesState> {
1103 [[nodiscard]] auto thenExpectBestColorModeCallUses(ui::Dataspace dataspace) {
1104 EXPECT_CALL(*getInstance()->mDisplayColorProfile,
1105 getBestColorMode(dataspace, _, _, _, _));
1106 return nextState<ExecuteState>();
1107 }
1108 };
1109
1110 // Call this member function to start using the mini-DSL defined above.
1111 [[nodiscard]] auto verify() { return IfForceOutputColorModeState::make(this); }
1112};
1113
1114TEST_F(OutputUpdateColorProfileTest_ForceOutputColorOverrides, NoOverride_DoesNotOverride) {
1115 // By default the layer state is used to set the preferred dataspace
1116 verify().ifNoOverride()
1117 .thenExpectBestColorModeCallUses(ui::Dataspace::DISPLAY_BT2020)
1118 .execute();
1119}
1120
1121TEST_F(OutputUpdateColorProfileTest_ForceOutputColorOverrides, SRGB_Override_USES_V0_SRGB) {
1122 // Setting ui::ColorMode::SRGB overrides it with ui::Dataspace::V0_SRGB
1123 verify().ifForceOutputColorMode(ui::ColorMode::SRGB)
1124 .thenExpectBestColorModeCallUses(ui::Dataspace::V0_SRGB)
1125 .execute();
1126}
1127
1128TEST_F(OutputUpdateColorProfileTest_ForceOutputColorOverrides, DisplayP3_Override_Uses_DisplayP3) {
1129 // Setting ui::ColorMode::DISPLAY_P3 overrides it with ui::Dataspace::DISPLAY_P3
1130 verify().ifForceOutputColorMode(ui::ColorMode::DISPLAY_P3)
1131 .thenExpectBestColorModeCallUses(ui::Dataspace::DISPLAY_P3)
1132 .execute();
1133}
1134
1135// HDR output requires all layers to be compatible with the chosen HDR
1136// dataspace, along with there being proper support.
1137struct OutputUpdateColorProfileTest_Hdr : public OutputUpdateColorProfileTest {
1138 OutputUpdateColorProfileTest_Hdr() {
1139 mRefreshArgs.outputColorSetting = OutputColorSetting::kEnhanced;
1140 mRefreshArgs.colorSpaceAgnosticDataspace = ui::Dataspace::UNKNOWN;
1141 EXPECT_CALL(mOutput, getOutputLayerCount()).WillRepeatedly(Return(2));
1142 EXPECT_CALL(mOutput, setColorProfile(_)).WillRepeatedly(Return());
1143 }
1144
1145 static constexpr ui::Dataspace kNonHdrDataspace = ui::Dataspace::DISPLAY_P3;
1146 static constexpr ui::Dataspace BT2020_PQ = ui::Dataspace::BT2020_PQ;
1147 static constexpr ui::Dataspace BT2020_HLG = ui::Dataspace::BT2020_HLG;
1148 static constexpr ui::Dataspace DISPLAY_P3 = ui::Dataspace::DISPLAY_P3;
1149
1150 struct IfTopLayerDataspaceState
1151 : public CallOrderStateMachineHelper<TestType, IfTopLayerDataspaceState> {
1152 [[nodiscard]] auto ifTopLayerIs(ui::Dataspace dataspace) {
1153 getInstance()->mLayer2.mLayerFEState.dataspace = dataspace;
1154 return nextState<AndTopLayerCompositionTypeState>();
1155 }
1156 [[nodiscard]] auto ifTopLayerIsNotHdr() { return ifTopLayerIs(kNonHdrDataspace); }
1157 };
1158
1159 struct AndTopLayerCompositionTypeState
1160 : public CallOrderStateMachineHelper<TestType, AndTopLayerCompositionTypeState> {
1161 [[nodiscard]] auto andTopLayerIsREComposed(bool renderEngineComposed) {
1162 getInstance()->mLayer2.mLayerFEState.forceClientComposition = renderEngineComposed;
1163 return nextState<AndIfBottomLayerDataspaceState>();
1164 }
1165 };
1166
1167 struct AndIfBottomLayerDataspaceState
1168 : public CallOrderStateMachineHelper<TestType, AndIfBottomLayerDataspaceState> {
1169 [[nodiscard]] auto andIfBottomLayerIs(ui::Dataspace dataspace) {
1170 getInstance()->mLayer1.mLayerFEState.dataspace = dataspace;
1171 return nextState<AndBottomLayerCompositionTypeState>();
1172 }
1173 [[nodiscard]] auto andIfBottomLayerIsNotHdr() {
1174 return andIfBottomLayerIs(kNonHdrDataspace);
1175 }
1176 };
1177
1178 struct AndBottomLayerCompositionTypeState
1179 : public CallOrderStateMachineHelper<TestType, AndBottomLayerCompositionTypeState> {
1180 [[nodiscard]] auto andBottomLayerIsREComposed(bool renderEngineComposed) {
1181 getInstance()->mLayer1.mLayerFEState.forceClientComposition = renderEngineComposed;
1182 return nextState<AndIfHasLegacySupportState>();
1183 }
1184 };
1185
1186 struct AndIfHasLegacySupportState
1187 : public CallOrderStateMachineHelper<TestType, AndIfHasLegacySupportState> {
1188 [[nodiscard]] auto andIfLegacySupportFor(ui::Dataspace dataspace, bool legacySupport) {
1189 EXPECT_CALL(*getInstance()->mDisplayColorProfile, hasLegacyHdrSupport(dataspace))
1190 .WillOnce(Return(legacySupport));
1191 return nextState<ThenExpectBestColorModeCallUsesState>();
1192 }
1193 };
1194
1195 struct ThenExpectBestColorModeCallUsesState
1196 : public CallOrderStateMachineHelper<TestType, ThenExpectBestColorModeCallUsesState> {
1197 [[nodiscard]] auto thenExpectBestColorModeCallUses(ui::Dataspace dataspace) {
1198 EXPECT_CALL(*getInstance()->mDisplayColorProfile,
1199 getBestColorMode(dataspace, _, _, _, _));
1200 return nextState<ExecuteState>();
1201 }
1202 };
1203
1204 // Call this member function to start using the mini-DSL defined above.
1205 [[nodiscard]] auto verify() { return IfTopLayerDataspaceState::make(this); }
1206};
1207
1208TEST_F(OutputUpdateColorProfileTest_Hdr, PQ_HW_On_PQ_HW_Uses_PQ) {
1209 // If all layers use BT2020_PQ, and there are no other special conditions,
1210 // BT2020_PQ is used.
1211 verify().ifTopLayerIs(BT2020_PQ)
1212 .andTopLayerIsREComposed(false)
1213 .andIfBottomLayerIs(BT2020_PQ)
1214 .andBottomLayerIsREComposed(false)
1215 .andIfLegacySupportFor(BT2020_PQ, false)
1216 .thenExpectBestColorModeCallUses(BT2020_PQ)
1217 .execute();
1218}
1219
1220TEST_F(OutputUpdateColorProfileTest_Hdr, PQ_HW_On_PQ_HW_IfPQHasLegacySupport_Uses_DisplayP3) {
1221 // BT2020_PQ is not used if there is only legacy support for it.
1222 verify().ifTopLayerIs(BT2020_PQ)
1223 .andTopLayerIsREComposed(false)
1224 .andIfBottomLayerIs(BT2020_PQ)
1225 .andBottomLayerIsREComposed(false)
1226 .andIfLegacySupportFor(BT2020_PQ, true)
1227 .thenExpectBestColorModeCallUses(DISPLAY_P3)
1228 .execute();
1229}
1230
1231TEST_F(OutputUpdateColorProfileTest_Hdr, PQ_HW_On_PQ_RE_Uses_PQ) {
1232 // BT2020_PQ is still used if the bottom layer is RenderEngine composed.
1233 verify().ifTopLayerIs(BT2020_PQ)
1234 .andTopLayerIsREComposed(false)
1235 .andIfBottomLayerIs(BT2020_PQ)
1236 .andBottomLayerIsREComposed(true)
1237 .andIfLegacySupportFor(BT2020_PQ, false)
1238 .thenExpectBestColorModeCallUses(BT2020_PQ)
1239 .execute();
1240}
1241
1242TEST_F(OutputUpdateColorProfileTest_Hdr, PQ_RE_On_PQ_HW_Uses_DisplayP3) {
1243 // BT2020_PQ is not used if the top layer is RenderEngine composed.
1244 verify().ifTopLayerIs(BT2020_PQ)
1245 .andTopLayerIsREComposed(true)
1246 .andIfBottomLayerIs(BT2020_PQ)
1247 .andBottomLayerIsREComposed(false)
1248 .andIfLegacySupportFor(BT2020_PQ, false)
1249 .thenExpectBestColorModeCallUses(DISPLAY_P3)
1250 .execute();
1251}
1252
1253TEST_F(OutputUpdateColorProfileTest_Hdr, PQ_HW_On_HLG_HW_Uses_PQ) {
1254 // If there is mixed HLG/PQ use, and the topmost layer is PQ, then PQ is used if there
1255 // are no other special conditions.
1256 verify().ifTopLayerIs(BT2020_PQ)
1257 .andTopLayerIsREComposed(false)
1258 .andIfBottomLayerIs(BT2020_HLG)
1259 .andBottomLayerIsREComposed(false)
1260 .andIfLegacySupportFor(BT2020_PQ, false)
1261 .thenExpectBestColorModeCallUses(BT2020_PQ)
1262 .execute();
1263}
1264
1265TEST_F(OutputUpdateColorProfileTest_Hdr, PQ_HW_On_HLG_HW_IfPQHasLegacySupport_Uses_DisplayP3) {
1266 // BT2020_PQ is not used if there is only legacy support for it.
1267 verify().ifTopLayerIs(BT2020_PQ)
1268 .andTopLayerIsREComposed(false)
1269 .andIfBottomLayerIs(BT2020_HLG)
1270 .andBottomLayerIsREComposed(false)
1271 .andIfLegacySupportFor(BT2020_PQ, true)
1272 .thenExpectBestColorModeCallUses(DISPLAY_P3)
1273 .execute();
1274}
1275
1276TEST_F(OutputUpdateColorProfileTest_Hdr, PQ_HW_On_HLG_RE_Uses_PQ) {
1277 // BT2020_PQ is used if the bottom HLG layer is RenderEngine composed.
1278 verify().ifTopLayerIs(BT2020_PQ)
1279 .andTopLayerIsREComposed(false)
1280 .andIfBottomLayerIs(BT2020_HLG)
1281 .andBottomLayerIsREComposed(true)
1282 .andIfLegacySupportFor(BT2020_PQ, false)
1283 .thenExpectBestColorModeCallUses(BT2020_PQ)
1284 .execute();
1285}
1286
1287TEST_F(OutputUpdateColorProfileTest_Hdr, PQ_RE_On_HLG_HW_Uses_DisplayP3) {
1288 // BT2020_PQ is not used if the top PQ layer is RenderEngine composed.
1289 verify().ifTopLayerIs(BT2020_PQ)
1290 .andTopLayerIsREComposed(true)
1291 .andIfBottomLayerIs(BT2020_HLG)
1292 .andBottomLayerIsREComposed(false)
1293 .andIfLegacySupportFor(BT2020_PQ, false)
1294 .thenExpectBestColorModeCallUses(DISPLAY_P3)
1295 .execute();
1296}
1297
1298TEST_F(OutputUpdateColorProfileTest_Hdr, HLG_HW_On_PQ_HW_Uses_PQ) {
1299 // If there is mixed HLG/PQ use, and the topmost layer is HLG, then PQ is
1300 // used if there are no other special conditions.
1301 verify().ifTopLayerIs(BT2020_HLG)
1302 .andTopLayerIsREComposed(false)
1303 .andIfBottomLayerIs(BT2020_PQ)
1304 .andBottomLayerIsREComposed(false)
1305 .andIfLegacySupportFor(BT2020_PQ, false)
1306 .thenExpectBestColorModeCallUses(BT2020_PQ)
1307 .execute();
1308}
1309
1310TEST_F(OutputUpdateColorProfileTest_Hdr, HLG_HW_On_PQ_HW_IfPQHasLegacySupport_Uses_DisplayP3) {
1311 // BT2020_PQ is not used if there is only legacy support for it.
1312 verify().ifTopLayerIs(BT2020_HLG)
1313 .andTopLayerIsREComposed(false)
1314 .andIfBottomLayerIs(BT2020_PQ)
1315 .andBottomLayerIsREComposed(false)
1316 .andIfLegacySupportFor(BT2020_PQ, true)
1317 .thenExpectBestColorModeCallUses(DISPLAY_P3)
1318 .execute();
1319}
1320
1321TEST_F(OutputUpdateColorProfileTest_Hdr, HLG_HW_On_PQ_RE_Uses_DisplayP3) {
1322 // BT2020_PQ is not used if the bottom PQ layer is RenderEngine composed.
1323 verify().ifTopLayerIs(BT2020_HLG)
1324 .andTopLayerIsREComposed(false)
1325 .andIfBottomLayerIs(BT2020_PQ)
1326 .andBottomLayerIsREComposed(true)
1327 .andIfLegacySupportFor(BT2020_PQ, false)
1328 .thenExpectBestColorModeCallUses(DISPLAY_P3)
1329 .execute();
1330}
1331
1332TEST_F(OutputUpdateColorProfileTest_Hdr, HLG_RE_On_PQ_HW_Uses_PQ) {
1333 // BT2020_PQ is still used if the top HLG layer is RenderEngine composed.
1334 verify().ifTopLayerIs(BT2020_HLG)
1335 .andTopLayerIsREComposed(true)
1336 .andIfBottomLayerIs(BT2020_PQ)
1337 .andBottomLayerIsREComposed(false)
1338 .andIfLegacySupportFor(BT2020_PQ, false)
1339 .thenExpectBestColorModeCallUses(BT2020_PQ)
1340 .execute();
1341}
1342
1343TEST_F(OutputUpdateColorProfileTest_Hdr, HLG_HW_On_HLG_HW_Uses_HLG) {
1344 // If all layers use HLG then HLG is used if there are no other special
1345 // conditions.
1346 verify().ifTopLayerIs(BT2020_HLG)
1347 .andTopLayerIsREComposed(false)
1348 .andIfBottomLayerIs(BT2020_HLG)
1349 .andBottomLayerIsREComposed(false)
1350 .andIfLegacySupportFor(BT2020_HLG, false)
1351 .thenExpectBestColorModeCallUses(BT2020_HLG)
1352 .execute();
1353}
1354
1355TEST_F(OutputUpdateColorProfileTest_Hdr, HLG_HW_On_HLG_HW_IfPQHasLegacySupport_Uses_DisplayP3) {
1356 // BT2020_HLG is not used if there is legacy support for it.
1357 verify().ifTopLayerIs(BT2020_HLG)
1358 .andTopLayerIsREComposed(false)
1359 .andIfBottomLayerIs(BT2020_HLG)
1360 .andBottomLayerIsREComposed(false)
1361 .andIfLegacySupportFor(BT2020_HLG, true)
1362 .thenExpectBestColorModeCallUses(DISPLAY_P3)
1363 .execute();
1364}
1365
1366TEST_F(OutputUpdateColorProfileTest_Hdr, HLG_HW_On_HLG_RE_Uses_HLG) {
1367 // BT2020_HLG is used even if the bottom layer is client composed.
1368 verify().ifTopLayerIs(BT2020_HLG)
1369 .andTopLayerIsREComposed(false)
1370 .andIfBottomLayerIs(BT2020_HLG)
1371 .andBottomLayerIsREComposed(true)
1372 .andIfLegacySupportFor(BT2020_HLG, false)
1373 .thenExpectBestColorModeCallUses(BT2020_HLG)
1374 .execute();
1375}
1376
1377TEST_F(OutputUpdateColorProfileTest_Hdr, HLG_RE_On_HLG_HW_Uses_HLG) {
1378 // BT2020_HLG is used even if the top layer is client composed.
1379 verify().ifTopLayerIs(BT2020_HLG)
1380 .andTopLayerIsREComposed(true)
1381 .andIfBottomLayerIs(BT2020_HLG)
1382 .andBottomLayerIsREComposed(false)
1383 .andIfLegacySupportFor(BT2020_HLG, false)
1384 .thenExpectBestColorModeCallUses(BT2020_HLG)
1385 .execute();
1386}
1387
1388TEST_F(OutputUpdateColorProfileTest_Hdr, PQ_HW_On_NonHdr_HW_Uses_PQ) {
1389 // Even if there are non-HDR layers present, BT2020_PQ can still be used.
1390 verify().ifTopLayerIs(BT2020_PQ)
1391 .andTopLayerIsREComposed(false)
1392 .andIfBottomLayerIsNotHdr()
1393 .andBottomLayerIsREComposed(false)
1394 .andIfLegacySupportFor(BT2020_PQ, false)
1395 .thenExpectBestColorModeCallUses(BT2020_PQ)
1396 .execute();
1397}
1398
1399TEST_F(OutputUpdateColorProfileTest_Hdr, HLG_HW_On_NonHdr_RE_Uses_HLG) {
1400 // If all layers use HLG then HLG is used if there are no other special
1401 // conditions.
1402 verify().ifTopLayerIs(BT2020_HLG)
1403 .andTopLayerIsREComposed(false)
1404 .andIfBottomLayerIsNotHdr()
1405 .andBottomLayerIsREComposed(true)
1406 .andIfLegacySupportFor(BT2020_HLG, false)
1407 .thenExpectBestColorModeCallUses(BT2020_HLG)
1408 .execute();
1409}
1410
1411struct OutputUpdateColorProfile_AffectsChosenRenderIntentTest
1412 : public OutputUpdateColorProfileTest {
1413 // The various values for CompositionRefreshArgs::outputColorSetting affect
1414 // the chosen renderIntent, along with whether the preferred dataspace is an
1415 // HDR dataspace or not.
1416
1417 OutputUpdateColorProfile_AffectsChosenRenderIntentTest() {
1418 mRefreshArgs.outputColorSetting = OutputColorSetting::kEnhanced;
1419 mRefreshArgs.colorSpaceAgnosticDataspace = ui::Dataspace::UNKNOWN;
1420 mLayer1.mLayerFEState.dataspace = ui::Dataspace::BT2020_PQ;
1421 EXPECT_CALL(mOutput, getOutputLayerCount()).WillRepeatedly(Return(1));
1422 EXPECT_CALL(mOutput, setColorProfile(_)).WillRepeatedly(Return());
1423 EXPECT_CALL(*mDisplayColorProfile, hasLegacyHdrSupport(ui::Dataspace::BT2020_PQ))
1424 .WillRepeatedly(Return(false));
1425 }
1426
1427 // The tests here involve enough state and GMock setup that using a mini-DSL
1428 // makes the tests much more readable, and allows the test to focus more on
1429 // the intent than on some of the details.
1430
1431 static constexpr ui::Dataspace kNonHdrDataspace = ui::Dataspace::DISPLAY_P3;
1432 static constexpr ui::Dataspace kHdrDataspace = ui::Dataspace::BT2020_PQ;
1433
1434 struct IfDataspaceChosenState
1435 : public CallOrderStateMachineHelper<TestType, IfDataspaceChosenState> {
1436 [[nodiscard]] auto ifDataspaceChosenIs(ui::Dataspace dataspace) {
1437 getInstance()->mLayer1.mLayerFEState.dataspace = dataspace;
1438 return nextState<AndOutputColorSettingState>();
1439 }
1440 [[nodiscard]] auto ifDataspaceChosenIsNonHdr() {
1441 return ifDataspaceChosenIs(kNonHdrDataspace);
1442 }
1443 [[nodiscard]] auto ifDataspaceChosenIsHdr() { return ifDataspaceChosenIs(kHdrDataspace); }
1444 };
1445
1446 struct AndOutputColorSettingState
1447 : public CallOrderStateMachineHelper<TestType, AndOutputColorSettingState> {
1448 [[nodiscard]] auto andOutputColorSettingIs(OutputColorSetting setting) {
1449 getInstance()->mRefreshArgs.outputColorSetting = setting;
1450 return nextState<ThenExpectBestColorModeCallUsesState>();
1451 }
1452 };
1453
1454 struct ThenExpectBestColorModeCallUsesState
1455 : public CallOrderStateMachineHelper<TestType, ThenExpectBestColorModeCallUsesState> {
1456 [[nodiscard]] auto thenExpectBestColorModeCallUses(ui::RenderIntent intent) {
1457 EXPECT_CALL(*getInstance()->mDisplayColorProfile,
1458 getBestColorMode(getInstance()->mLayer1.mLayerFEState.dataspace, intent, _,
1459 _, _));
1460 return nextState<ExecuteState>();
1461 }
1462 };
1463
1464 // Tests call one of these two helper member functions to start using the
1465 // mini-DSL defined above.
1466 [[nodiscard]] auto verify() { return IfDataspaceChosenState::make(this); }
1467};
1468
1469TEST_F(OutputUpdateColorProfile_AffectsChosenRenderIntentTest,
1470 Managed_NonHdr_Prefers_Colorimetric) {
1471 verify().ifDataspaceChosenIsNonHdr()
1472 .andOutputColorSettingIs(OutputColorSetting::kManaged)
1473 .thenExpectBestColorModeCallUses(ui::RenderIntent::COLORIMETRIC)
1474 .execute();
1475}
1476
1477TEST_F(OutputUpdateColorProfile_AffectsChosenRenderIntentTest,
1478 Managed_Hdr_Prefers_ToneMapColorimetric) {
1479 verify().ifDataspaceChosenIsHdr()
1480 .andOutputColorSettingIs(OutputColorSetting::kManaged)
1481 .thenExpectBestColorModeCallUses(ui::RenderIntent::TONE_MAP_COLORIMETRIC)
1482 .execute();
1483}
1484
1485TEST_F(OutputUpdateColorProfile_AffectsChosenRenderIntentTest, Enhanced_NonHdr_Prefers_Enhance) {
1486 verify().ifDataspaceChosenIsNonHdr()
1487 .andOutputColorSettingIs(OutputColorSetting::kEnhanced)
1488 .thenExpectBestColorModeCallUses(ui::RenderIntent::ENHANCE)
1489 .execute();
1490}
1491
1492TEST_F(OutputUpdateColorProfile_AffectsChosenRenderIntentTest,
1493 Enhanced_Hdr_Prefers_ToneMapEnhance) {
1494 verify().ifDataspaceChosenIsHdr()
1495 .andOutputColorSettingIs(OutputColorSetting::kEnhanced)
1496 .thenExpectBestColorModeCallUses(ui::RenderIntent::TONE_MAP_ENHANCE)
1497 .execute();
1498}
1499
1500TEST_F(OutputUpdateColorProfile_AffectsChosenRenderIntentTest, Vendor_NonHdr_Prefers_Vendor) {
1501 verify().ifDataspaceChosenIsNonHdr()
1502 .andOutputColorSettingIs(kVendorSpecifiedOutputColorSetting)
1503 .thenExpectBestColorModeCallUses(
1504 static_cast<ui::RenderIntent>(kVendorSpecifiedOutputColorSetting))
1505 .execute();
1506}
1507
1508TEST_F(OutputUpdateColorProfile_AffectsChosenRenderIntentTest, Vendor_Hdr_Prefers_Vendor) {
1509 verify().ifDataspaceChosenIsHdr()
1510 .andOutputColorSettingIs(kVendorSpecifiedOutputColorSetting)
1511 .thenExpectBestColorModeCallUses(
1512 static_cast<ui::RenderIntent>(kVendorSpecifiedOutputColorSetting))
1513 .execute();
1514}
Lloyd Piquefaa3f192019-11-14 14:05:09 -08001515
1516/*
1517 * Output::beginFrame()
1518 */
1519
1520/*
1521 * Output::devOptRepaintFlash()
1522 */
1523
Lloyd Piquedb462d82019-11-19 17:58:46 -08001524struct OutputDevOptRepaintFlashTest : public testing::Test {
1525 struct OutputPartialMock : public OutputPartialMockBase {
1526 // Sets up the helper functions called by composeSurfaces to use a mock
1527 // implementations.
1528 MOCK_CONST_METHOD1(getDirtyRegion, Region(bool));
1529 MOCK_METHOD1(composeSurfaces, std::optional<base::unique_fd>(const Region&));
1530 MOCK_METHOD0(postFramebuffer, void());
1531 MOCK_METHOD0(prepareFrame, void());
1532 };
1533
1534 OutputDevOptRepaintFlashTest() {
1535 mOutput.setDisplayColorProfileForTest(
1536 std::unique_ptr<DisplayColorProfile>(mDisplayColorProfile));
1537 mOutput.setRenderSurfaceForTest(std::unique_ptr<RenderSurface>(mRenderSurface));
1538 }
1539
1540 static const Region kEmptyRegion;
1541 static const Region kNotEmptyRegion;
1542
1543 StrictMock<OutputPartialMock> mOutput;
1544 mock::DisplayColorProfile* mDisplayColorProfile = new StrictMock<mock::DisplayColorProfile>();
1545 mock::RenderSurface* mRenderSurface = new StrictMock<mock::RenderSurface>();
1546 CompositionRefreshArgs mRefreshArgs;
1547};
1548
1549const Region OutputDevOptRepaintFlashTest::kEmptyRegion{Rect{0, 0, 0, 0}};
1550const Region OutputDevOptRepaintFlashTest::kNotEmptyRegion{Rect{0, 0, 1, 1}};
1551
1552TEST_F(OutputDevOptRepaintFlashTest, doesNothingIfFlashDelayNotSet) {
1553 mRefreshArgs.devOptFlashDirtyRegionsDelay = {};
1554 mRefreshArgs.repaintEverything = true;
1555 mOutput.mState.isEnabled = true;
1556
1557 mOutput.devOptRepaintFlash(mRefreshArgs);
1558}
1559
1560TEST_F(OutputDevOptRepaintFlashTest, postsAndPreparesANewFrameIfNotEnabled) {
1561 mRefreshArgs.devOptFlashDirtyRegionsDelay = std::chrono::microseconds(1);
1562 mRefreshArgs.repaintEverything = true;
1563 mOutput.mState.isEnabled = false;
1564
1565 InSequence seq;
1566 EXPECT_CALL(mOutput, postFramebuffer());
1567 EXPECT_CALL(mOutput, prepareFrame());
1568
1569 mOutput.devOptRepaintFlash(mRefreshArgs);
1570}
1571
1572TEST_F(OutputDevOptRepaintFlashTest, postsAndPreparesANewFrameIfNotDirty) {
1573 mRefreshArgs.devOptFlashDirtyRegionsDelay = std::chrono::microseconds(1);
1574 mRefreshArgs.repaintEverything = true;
1575 mOutput.mState.isEnabled = true;
1576
1577 InSequence seq;
1578 EXPECT_CALL(mOutput, getDirtyRegion(true)).WillOnce(Return(kEmptyRegion));
1579 EXPECT_CALL(mOutput, postFramebuffer());
1580 EXPECT_CALL(mOutput, prepareFrame());
1581
1582 mOutput.devOptRepaintFlash(mRefreshArgs);
1583}
1584
1585TEST_F(OutputDevOptRepaintFlashTest, alsoComposesSurfacesAndQueuesABufferIfDirty) {
1586 mRefreshArgs.devOptFlashDirtyRegionsDelay = std::chrono::microseconds(1);
1587 mRefreshArgs.repaintEverything = false;
1588 mOutput.mState.isEnabled = true;
1589
1590 InSequence seq;
1591 EXPECT_CALL(mOutput, getDirtyRegion(false)).WillOnce(Return(kNotEmptyRegion));
1592 EXPECT_CALL(mOutput, composeSurfaces(RegionEq(kNotEmptyRegion)));
1593 EXPECT_CALL(*mRenderSurface, queueBuffer(_));
1594 EXPECT_CALL(mOutput, postFramebuffer());
1595 EXPECT_CALL(mOutput, prepareFrame());
1596
1597 mOutput.devOptRepaintFlash(mRefreshArgs);
1598}
1599
Lloyd Piquefaa3f192019-11-14 14:05:09 -08001600// TODO(b/144060211) - Add coverage
1601
1602/*
1603 * Output::finishFrame()
1604 */
1605
Lloyd Pique03561a62019-11-19 18:34:52 -08001606struct OutputFinishFrameTest : public testing::Test {
1607 struct OutputPartialMock : public OutputPartialMockBase {
1608 // Sets up the helper functions called by composeSurfaces to use a mock
1609 // implementations.
1610 MOCK_METHOD1(composeSurfaces, std::optional<base::unique_fd>(const Region&));
1611 MOCK_METHOD0(postFramebuffer, void());
1612 };
1613
1614 OutputFinishFrameTest() {
1615 mOutput.setDisplayColorProfileForTest(
1616 std::unique_ptr<DisplayColorProfile>(mDisplayColorProfile));
1617 mOutput.setRenderSurfaceForTest(std::unique_ptr<RenderSurface>(mRenderSurface));
1618 }
1619
1620 StrictMock<OutputPartialMock> mOutput;
1621 mock::DisplayColorProfile* mDisplayColorProfile = new StrictMock<mock::DisplayColorProfile>();
1622 mock::RenderSurface* mRenderSurface = new StrictMock<mock::RenderSurface>();
1623 CompositionRefreshArgs mRefreshArgs;
1624};
1625
1626TEST_F(OutputFinishFrameTest, ifNotEnabledDoesNothing) {
1627 mOutput.mState.isEnabled = false;
1628
1629 mOutput.finishFrame(mRefreshArgs);
1630}
1631
1632TEST_F(OutputFinishFrameTest, takesEarlyOutifComposeSurfacesReturnsNoFence) {
1633 mOutput.mState.isEnabled = true;
1634
1635 InSequence seq;
1636 EXPECT_CALL(mOutput, composeSurfaces(RegionEq(Region::INVALID_REGION)));
1637
1638 mOutput.finishFrame(mRefreshArgs);
1639}
1640
1641TEST_F(OutputFinishFrameTest, queuesBufferIfComposeSurfacesReturnsAFence) {
1642 mOutput.mState.isEnabled = true;
1643
1644 InSequence seq;
1645 EXPECT_CALL(mOutput, composeSurfaces(RegionEq(Region::INVALID_REGION)))
1646 .WillOnce(Return(ByMove(base::unique_fd())));
1647 EXPECT_CALL(*mRenderSurface, queueBuffer(_));
1648
1649 mOutput.finishFrame(mRefreshArgs);
1650}
Lloyd Piquefaa3f192019-11-14 14:05:09 -08001651
1652/*
1653 * Output::postFramebuffer()
1654 */
1655
Lloyd Pique07178e32019-11-19 19:15:26 -08001656struct OutputPostFramebufferTest : public testing::Test {
1657 struct OutputPartialMock : public OutputPartialMockBase {
1658 // Sets up the helper functions called by composeSurfaces to use a mock
1659 // implementations.
1660 MOCK_METHOD0(presentAndGetFrameFences, compositionengine::Output::FrameFences());
1661 };
1662
1663 struct Layer {
1664 Layer() {
1665 EXPECT_CALL(outputLayer, getLayerFE()).WillRepeatedly(ReturnRef(layerFE));
1666 EXPECT_CALL(outputLayer, getHwcLayer()).WillRepeatedly(Return(&hwc2Layer));
1667 }
1668
1669 StrictMock<mock::OutputLayer> outputLayer;
1670 StrictMock<mock::LayerFE> layerFE;
1671 StrictMock<HWC2::mock::Layer> hwc2Layer;
1672 };
1673
1674 OutputPostFramebufferTest() {
1675 mOutput.setDisplayColorProfileForTest(
1676 std::unique_ptr<DisplayColorProfile>(mDisplayColorProfile));
1677 mOutput.setRenderSurfaceForTest(std::unique_ptr<RenderSurface>(mRenderSurface));
1678
1679 EXPECT_CALL(mOutput, getOutputLayerCount()).WillRepeatedly(Return(3u));
1680 EXPECT_CALL(mOutput, getOutputLayerOrderedByZByIndex(0u))
1681 .WillRepeatedly(Return(&mLayer1.outputLayer));
1682 EXPECT_CALL(mOutput, getOutputLayerOrderedByZByIndex(1u))
1683 .WillRepeatedly(Return(&mLayer2.outputLayer));
1684 EXPECT_CALL(mOutput, getOutputLayerOrderedByZByIndex(2u))
1685 .WillRepeatedly(Return(&mLayer3.outputLayer));
1686 }
1687
1688 StrictMock<OutputPartialMock> mOutput;
1689 mock::DisplayColorProfile* mDisplayColorProfile = new StrictMock<mock::DisplayColorProfile>();
1690 mock::RenderSurface* mRenderSurface = new StrictMock<mock::RenderSurface>();
1691
1692 Layer mLayer1;
1693 Layer mLayer2;
1694 Layer mLayer3;
1695};
1696
1697TEST_F(OutputPostFramebufferTest, ifNotEnabledDoesNothing) {
1698 mOutput.mState.isEnabled = false;
1699
1700 mOutput.postFramebuffer();
1701}
1702
1703TEST_F(OutputPostFramebufferTest, ifEnabledMustFlipThenPresentThenSendPresentCompleted) {
1704 mOutput.mState.isEnabled = true;
1705
1706 compositionengine::Output::FrameFences frameFences;
1707
1708 // This should happen even if there are no output layers.
1709 EXPECT_CALL(mOutput, getOutputLayerCount()).WillOnce(Return(0u));
1710
1711 // For this test in particular we want to make sure the call expectations
1712 // setup below are satisfied in the specific order.
1713 InSequence seq;
1714
1715 EXPECT_CALL(*mRenderSurface, flip());
1716 EXPECT_CALL(mOutput, presentAndGetFrameFences()).WillOnce(Return(frameFences));
1717 EXPECT_CALL(*mRenderSurface, onPresentDisplayCompleted());
1718
1719 mOutput.postFramebuffer();
1720}
1721
1722TEST_F(OutputPostFramebufferTest, releaseFencesAreSentToLayerFE) {
1723 // Simulate getting release fences from each layer, and ensure they are passed to the
1724 // front-end layer interface for each layer correctly.
1725
1726 mOutput.mState.isEnabled = true;
1727
1728 // Create three unique fence instances
1729 sp<Fence> layer1Fence = new Fence();
1730 sp<Fence> layer2Fence = new Fence();
1731 sp<Fence> layer3Fence = new Fence();
1732
1733 compositionengine::Output::FrameFences frameFences;
1734 frameFences.layerFences.emplace(&mLayer1.hwc2Layer, layer1Fence);
1735 frameFences.layerFences.emplace(&mLayer2.hwc2Layer, layer2Fence);
1736 frameFences.layerFences.emplace(&mLayer3.hwc2Layer, layer3Fence);
1737
1738 EXPECT_CALL(*mRenderSurface, flip());
1739 EXPECT_CALL(mOutput, presentAndGetFrameFences()).WillOnce(Return(frameFences));
1740 EXPECT_CALL(*mRenderSurface, onPresentDisplayCompleted());
1741
1742 // Compare the pointers values of each fence to make sure the correct ones
1743 // are passed. This happens to work with the current implementation, but
1744 // would not survive certain calls like Fence::merge() which would return a
1745 // new instance.
1746 EXPECT_CALL(mLayer1.layerFE,
1747 onLayerDisplayed(Property(&sp<Fence>::get, Eq(layer1Fence.get()))));
1748 EXPECT_CALL(mLayer2.layerFE,
1749 onLayerDisplayed(Property(&sp<Fence>::get, Eq(layer2Fence.get()))));
1750 EXPECT_CALL(mLayer3.layerFE,
1751 onLayerDisplayed(Property(&sp<Fence>::get, Eq(layer3Fence.get()))));
1752
1753 mOutput.postFramebuffer();
1754}
1755
1756TEST_F(OutputPostFramebufferTest, releaseFencesIncludeClientTargetAcquireFence) {
1757 mOutput.mState.isEnabled = true;
1758 mOutput.mState.usesClientComposition = true;
1759
1760 sp<Fence> clientTargetAcquireFence = new Fence();
1761 sp<Fence> layer1Fence = new Fence();
1762 sp<Fence> layer2Fence = new Fence();
1763 sp<Fence> layer3Fence = new Fence();
1764 compositionengine::Output::FrameFences frameFences;
1765 frameFences.clientTargetAcquireFence = clientTargetAcquireFence;
1766 frameFences.layerFences.emplace(&mLayer1.hwc2Layer, layer1Fence);
1767 frameFences.layerFences.emplace(&mLayer2.hwc2Layer, layer2Fence);
1768 frameFences.layerFences.emplace(&mLayer3.hwc2Layer, layer3Fence);
1769
1770 EXPECT_CALL(*mRenderSurface, flip());
1771 EXPECT_CALL(mOutput, presentAndGetFrameFences()).WillOnce(Return(frameFences));
1772 EXPECT_CALL(*mRenderSurface, onPresentDisplayCompleted());
1773
1774 // Fence::merge is called, and since none of the fences are actually valid,
1775 // Fence::NO_FENCE is returned and passed to each onLayerDisplayed() call.
1776 // This is the best we can do without creating a real kernel fence object.
1777 EXPECT_CALL(mLayer1.layerFE, onLayerDisplayed(Fence::NO_FENCE));
1778 EXPECT_CALL(mLayer2.layerFE, onLayerDisplayed(Fence::NO_FENCE));
1779 EXPECT_CALL(mLayer3.layerFE, onLayerDisplayed(Fence::NO_FENCE));
1780
1781 mOutput.postFramebuffer();
1782}
1783
1784TEST_F(OutputPostFramebufferTest, releasedLayersSentPresentFence) {
1785 mOutput.mState.isEnabled = true;
1786 mOutput.mState.usesClientComposition = true;
1787
1788 // This should happen even if there are no (current) output layers.
1789 EXPECT_CALL(mOutput, getOutputLayerCount()).WillOnce(Return(0u));
1790
1791 // Load up the released layers with some mock instances
1792 sp<StrictMock<mock::LayerFE>> releasedLayer1{new StrictMock<mock::LayerFE>()};
1793 sp<StrictMock<mock::LayerFE>> releasedLayer2{new StrictMock<mock::LayerFE>()};
1794 sp<StrictMock<mock::LayerFE>> releasedLayer3{new StrictMock<mock::LayerFE>()};
1795 Output::ReleasedLayers layers;
1796 layers.push_back(releasedLayer1);
1797 layers.push_back(releasedLayer2);
1798 layers.push_back(releasedLayer3);
1799 mOutput.setReleasedLayers(std::move(layers));
1800
1801 // Set up a fake present fence
1802 sp<Fence> presentFence = new Fence();
1803 compositionengine::Output::FrameFences frameFences;
1804 frameFences.presentFence = presentFence;
1805
1806 EXPECT_CALL(*mRenderSurface, flip());
1807 EXPECT_CALL(mOutput, presentAndGetFrameFences()).WillOnce(Return(frameFences));
1808 EXPECT_CALL(*mRenderSurface, onPresentDisplayCompleted());
1809
1810 // Each released layer should be given the presentFence.
1811 EXPECT_CALL(*releasedLayer1,
1812 onLayerDisplayed(Property(&sp<Fence>::get, Eq(presentFence.get()))));
1813 EXPECT_CALL(*releasedLayer2,
1814 onLayerDisplayed(Property(&sp<Fence>::get, Eq(presentFence.get()))));
1815 EXPECT_CALL(*releasedLayer3,
1816 onLayerDisplayed(Property(&sp<Fence>::get, Eq(presentFence.get()))));
1817
1818 mOutput.postFramebuffer();
1819
1820 // After the call the list of released layers should have been cleared.
1821 EXPECT_TRUE(mOutput.getReleasedLayersForTest().empty());
1822}
Lloyd Piquefaa3f192019-11-14 14:05:09 -08001823
1824/*
Lloyd Pique56eba802019-08-28 15:45:25 -07001825 * Output::composeSurfaces()
1826 */
1827
1828struct OutputComposeSurfacesTest : public testing::Test {
1829 static constexpr uint32_t kDefaultOutputOrientation = TR_IDENT;
1830 static constexpr ui::Dataspace kDefaultOutputDataspace = ui::Dataspace::DISPLAY_P3;
1831
1832 static const Rect kDefaultOutputFrame;
1833 static const Rect kDefaultOutputViewport;
1834 static const Rect kDefaultOutputScissor;
1835 static const mat4 kDefaultColorTransformMat;
1836
Lloyd Piquefaa3f192019-11-14 14:05:09 -08001837 struct OutputPartialMock : public OutputPartialMockBase {
Lloyd Pique56eba802019-08-28 15:45:25 -07001838 // Sets up the helper functions called by composeSurfaces to use a mock
1839 // implementations.
1840 MOCK_CONST_METHOD0(getSkipColorTransform, bool());
1841 MOCK_METHOD2(generateClientCompositionRequests,
1842 std::vector<renderengine::LayerSettings>(bool, Region&));
1843 MOCK_METHOD2(appendRegionFlashRequests,
1844 void(const Region&, std::vector<renderengine::LayerSettings>&));
1845 MOCK_METHOD1(setExpensiveRenderingExpected, void(bool));
1846 };
1847
1848 OutputComposeSurfacesTest() {
1849 mOutput.setDisplayColorProfileForTest(
1850 std::unique_ptr<DisplayColorProfile>(mDisplayColorProfile));
1851 mOutput.setRenderSurfaceForTest(std::unique_ptr<RenderSurface>(mRenderSurface));
1852
Lloyd Pique56eba802019-08-28 15:45:25 -07001853 mOutput.editState().frame = kDefaultOutputFrame;
1854 mOutput.editState().viewport = kDefaultOutputViewport;
1855 mOutput.editState().scissor = kDefaultOutputScissor;
1856 mOutput.editState().transform = ui::Transform{kDefaultOutputOrientation};
1857 mOutput.editState().orientation = kDefaultOutputOrientation;
1858 mOutput.editState().dataspace = kDefaultOutputDataspace;
Lloyd Pique3eb1b212019-03-07 21:15:40 -08001859 mOutput.editState().colorTransformMatrix = kDefaultColorTransformMat;
Lloyd Pique56eba802019-08-28 15:45:25 -07001860 mOutput.editState().isSecure = true;
1861 mOutput.editState().needsFiltering = false;
1862 mOutput.editState().usesClientComposition = true;
1863 mOutput.editState().usesDeviceComposition = false;
1864
Lloyd Pique01c77c12019-04-17 12:48:32 -07001865 EXPECT_CALL(mOutput, getOutputLayerCount()).WillRepeatedly(Return(2u));
1866 EXPECT_CALL(mOutput, getOutputLayerOrderedByZByIndex(0u))
1867 .WillRepeatedly(Return(&mOutputLayer1));
1868 EXPECT_CALL(mOutput, getOutputLayerOrderedByZByIndex(1u))
1869 .WillRepeatedly(Return(&mOutputLayer2));
Lloyd Piquea38ea7e2019-04-16 18:10:26 -07001870 EXPECT_CALL(mOutput, getCompositionEngine()).WillRepeatedly(ReturnRef(mCompositionEngine));
Lloyd Pique56eba802019-08-28 15:45:25 -07001871 EXPECT_CALL(mCompositionEngine, getRenderEngine()).WillRepeatedly(ReturnRef(mRenderEngine));
1872 }
1873
1874 StrictMock<mock::CompositionEngine> mCompositionEngine;
1875 StrictMock<renderengine::mock::RenderEngine> mRenderEngine;
1876 mock::DisplayColorProfile* mDisplayColorProfile = new StrictMock<mock::DisplayColorProfile>();
1877 mock::RenderSurface* mRenderSurface = new StrictMock<mock::RenderSurface>();
Lloyd Pique01c77c12019-04-17 12:48:32 -07001878 StrictMock<mock::OutputLayer> mOutputLayer1;
1879 StrictMock<mock::OutputLayer> mOutputLayer2;
Lloyd Piquea38ea7e2019-04-16 18:10:26 -07001880 StrictMock<OutputPartialMock> mOutput;
Lloyd Pique56eba802019-08-28 15:45:25 -07001881 sp<GraphicBuffer> mOutputBuffer = new GraphicBuffer();
1882};
1883
1884const Rect OutputComposeSurfacesTest::kDefaultOutputFrame{1001, 1002, 1003, 1004};
1885const Rect OutputComposeSurfacesTest::kDefaultOutputViewport{1005, 1006, 1007, 1008};
1886const Rect OutputComposeSurfacesTest::kDefaultOutputScissor{1009, 1010, 1011, 1012};
1887const mat4 OutputComposeSurfacesTest::kDefaultColorTransformMat{mat4() * 0.5};
1888
1889// TODO(b/121291683): Expand unit test coverage for composeSurfaces beyond these
1890// basic tests.
1891
1892TEST_F(OutputComposeSurfacesTest, doesNothingIfNoClientComposition) {
1893 mOutput.editState().usesClientComposition = false;
1894
1895 Region debugRegion;
Lloyd Piqued3d69882019-02-28 16:03:46 -08001896 std::optional<base::unique_fd> readyFence = mOutput.composeSurfaces(debugRegion);
1897 EXPECT_TRUE(readyFence);
Lloyd Pique56eba802019-08-28 15:45:25 -07001898}
1899
1900TEST_F(OutputComposeSurfacesTest, worksIfNoClientLayersQueued) {
1901 const Region kDebugRegion{Rect{100, 101, 102, 103}};
1902
1903 constexpr float kDefaultMaxLuminance = 1.0f;
1904 constexpr float kDefaultAvgLuminance = 0.7f;
1905 constexpr float kDefaultMinLuminance = 0.1f;
1906 HdrCapabilities HdrCapabilities{{},
1907 kDefaultMaxLuminance,
1908 kDefaultAvgLuminance,
1909 kDefaultMinLuminance};
1910
1911 EXPECT_CALL(mRenderEngine, supportsProtectedContent()).WillOnce(Return(false));
1912 EXPECT_CALL(mRenderEngine, drawLayers(_, _, _, true, _, _)).Times(1);
1913
1914 EXPECT_CALL(*mDisplayColorProfile, hasWideColorGamut()).WillOnce(Return(true));
1915 EXPECT_CALL(*mDisplayColorProfile, getHdrCapabilities()).WillOnce(ReturnRef(HdrCapabilities));
1916
1917 EXPECT_CALL(*mRenderSurface, dequeueBuffer(_)).WillOnce(Return(mOutputBuffer));
1918
1919 EXPECT_CALL(mOutput, getSkipColorTransform()).WillOnce(Return(false));
1920 EXPECT_CALL(mOutput, generateClientCompositionRequests(false, _)).Times(1);
1921 EXPECT_CALL(mOutput, appendRegionFlashRequests(RegionEq(kDebugRegion), _)).Times(1);
1922 EXPECT_CALL(mOutput, setExpensiveRenderingExpected(true)).Times(1);
1923 EXPECT_CALL(mOutput, setExpensiveRenderingExpected(false)).Times(1);
1924
Lloyd Piqued3d69882019-02-28 16:03:46 -08001925 std::optional<base::unique_fd> readyFence = mOutput.composeSurfaces(kDebugRegion);
1926 EXPECT_TRUE(readyFence);
Lloyd Pique56eba802019-08-28 15:45:25 -07001927}
1928
1929/*
1930 * Output::generateClientCompositionRequests()
1931 */
1932
1933struct GenerateClientCompositionRequestsTest : public testing::Test {
Lloyd Piquefaa3f192019-11-14 14:05:09 -08001934 struct OutputPartialMock : public OutputPartialMockBase {
Lloyd Piquea38ea7e2019-04-16 18:10:26 -07001935 // compositionengine::Output overrides
Lloyd Pique56eba802019-08-28 15:45:25 -07001936 std::vector<renderengine::LayerSettings> generateClientCompositionRequests(
1937 bool supportsProtectedContent, Region& clearRegion) override {
1938 return impl::Output::generateClientCompositionRequests(supportsProtectedContent,
1939 clearRegion);
1940 }
1941 };
1942
1943 GenerateClientCompositionRequestsTest() {
1944 mOutput.setDisplayColorProfileForTest(
1945 std::unique_ptr<DisplayColorProfile>(mDisplayColorProfile));
1946 mOutput.setRenderSurfaceForTest(std::unique_ptr<RenderSurface>(mRenderSurface));
1947 }
1948
Lloyd Pique56eba802019-08-28 15:45:25 -07001949 mock::DisplayColorProfile* mDisplayColorProfile = new StrictMock<mock::DisplayColorProfile>();
1950 mock::RenderSurface* mRenderSurface = new StrictMock<mock::RenderSurface>();
Lloyd Piquea38ea7e2019-04-16 18:10:26 -07001951 StrictMock<OutputPartialMock> mOutput;
Lloyd Pique56eba802019-08-28 15:45:25 -07001952};
1953
1954// TODO(b/121291683): Add more unit test coverage for generateClientCompositionRequests
1955
1956TEST_F(GenerateClientCompositionRequestsTest, worksForLandscapeModeSplitScreen) {
1957 // In split-screen landscape mode, the screen is rotated 90 degrees, with
1958 // one layer on the left covering the left side of the output, and one layer
1959 // on the right covering that side of the output.
1960
Lloyd Pique01c77c12019-04-17 12:48:32 -07001961 StrictMock<mock::OutputLayer> leftOutputLayer;
1962 StrictMock<mock::OutputLayer> rightOutputLayer;
Lloyd Pique56eba802019-08-28 15:45:25 -07001963
1964 StrictMock<mock::Layer> leftLayer;
1965 StrictMock<mock::LayerFE> leftLayerFE;
1966 StrictMock<mock::Layer> rightLayer;
1967 StrictMock<mock::LayerFE> rightLayerFE;
1968
1969 impl::OutputLayerCompositionState leftOutputLayerState;
1970 leftOutputLayerState.clearClientTarget = false;
Lloyd Piquea2468662019-03-07 21:31:06 -08001971 leftOutputLayerState.visibleRegion = Region{Rect{0, 0, 1000, 1000}};
Lloyd Pique56eba802019-08-28 15:45:25 -07001972
Lloyd Pique9755fb72019-03-26 14:44:40 -07001973 LayerFECompositionState leftLayerFEState;
1974 leftLayerFEState.isOpaque = true;
Lloyd Pique56eba802019-08-28 15:45:25 -07001975
1976 const half3 leftLayerColor{1.f, 0.f, 0.f};
1977 renderengine::LayerSettings leftLayerRESettings;
1978 leftLayerRESettings.source.solidColor = leftLayerColor;
1979
1980 impl::OutputLayerCompositionState rightOutputLayerState;
1981 rightOutputLayerState.clearClientTarget = false;
Lloyd Piquea2468662019-03-07 21:31:06 -08001982 rightOutputLayerState.visibleRegion = Region{Rect{1000, 0, 2000, 1000}};
Lloyd Pique56eba802019-08-28 15:45:25 -07001983
Lloyd Pique9755fb72019-03-26 14:44:40 -07001984 LayerFECompositionState rightLayerFEState;
1985 rightLayerFEState.isOpaque = true;
Lloyd Pique56eba802019-08-28 15:45:25 -07001986
1987 const half3 rightLayerColor{0.f, 1.f, 0.f};
1988 renderengine::LayerSettings rightLayerRESettings;
1989 rightLayerRESettings.source.solidColor = rightLayerColor;
1990
Lloyd Pique01c77c12019-04-17 12:48:32 -07001991 EXPECT_CALL(leftOutputLayer, getState()).WillRepeatedly(ReturnRef(leftOutputLayerState));
1992 EXPECT_CALL(leftOutputLayer, getLayer()).WillRepeatedly(ReturnRef(leftLayer));
1993 EXPECT_CALL(leftOutputLayer, getLayerFE()).WillRepeatedly(ReturnRef(leftLayerFE));
1994 EXPECT_CALL(leftOutputLayer, requiresClientComposition()).WillRepeatedly(Return(true));
1995 EXPECT_CALL(leftOutputLayer, needsFiltering()).WillRepeatedly(Return(false));
Lloyd Pique9755fb72019-03-26 14:44:40 -07001996 EXPECT_CALL(leftLayer, getFEState()).WillRepeatedly(ReturnRef(leftLayerFEState));
Lloyd Pique56eba802019-08-28 15:45:25 -07001997 EXPECT_CALL(leftLayerFE, prepareClientComposition(_)).WillOnce(Return(leftLayerRESettings));
Adithya Srinivasanb69e0762019-11-11 18:39:53 -08001998 EXPECT_CALL(leftOutputLayer, editState()).WillRepeatedly(ReturnRef(leftOutputLayerState));
Lloyd Pique56eba802019-08-28 15:45:25 -07001999
Lloyd Pique01c77c12019-04-17 12:48:32 -07002000 EXPECT_CALL(rightOutputLayer, getState()).WillRepeatedly(ReturnRef(rightOutputLayerState));
2001 EXPECT_CALL(rightOutputLayer, getLayer()).WillRepeatedly(ReturnRef(rightLayer));
2002 EXPECT_CALL(rightOutputLayer, getLayerFE()).WillRepeatedly(ReturnRef(rightLayerFE));
2003 EXPECT_CALL(rightOutputLayer, requiresClientComposition()).WillRepeatedly(Return(true));
2004 EXPECT_CALL(rightOutputLayer, needsFiltering()).WillRepeatedly(Return(false));
Lloyd Pique9755fb72019-03-26 14:44:40 -07002005 EXPECT_CALL(rightLayer, getFEState()).WillRepeatedly(ReturnRef(rightLayerFEState));
Lloyd Pique56eba802019-08-28 15:45:25 -07002006 EXPECT_CALL(rightLayerFE, prepareClientComposition(_)).WillOnce(Return(rightLayerRESettings));
Adithya Srinivasanb69e0762019-11-11 18:39:53 -08002007 EXPECT_CALL(rightOutputLayer, editState()).WillRepeatedly(ReturnRef(rightOutputLayerState));
Lloyd Pique56eba802019-08-28 15:45:25 -07002008
Lloyd Pique01c77c12019-04-17 12:48:32 -07002009 EXPECT_CALL(mOutput, getOutputLayerCount()).WillRepeatedly(Return(2u));
2010 EXPECT_CALL(mOutput, getOutputLayerOrderedByZByIndex(0u))
2011 .WillRepeatedly(Return(&leftOutputLayer));
2012 EXPECT_CALL(mOutput, getOutputLayerOrderedByZByIndex(1u))
2013 .WillRepeatedly(Return(&rightOutputLayer));
Lloyd Pique56eba802019-08-28 15:45:25 -07002014
2015 const Rect kPortraitFrame(0, 0, 1000, 2000);
2016 const Rect kPortraitViewport(0, 0, 2000, 1000);
2017 const Rect kPortraitScissor(0, 0, 1000, 2000);
2018 const uint32_t kPortraitOrientation = TR_ROT_90;
2019
2020 mOutput.editState().frame = kPortraitFrame;
2021 mOutput.editState().viewport = kPortraitViewport;
2022 mOutput.editState().scissor = kPortraitScissor;
2023 mOutput.editState().transform = ui::Transform{kPortraitOrientation};
2024 mOutput.editState().orientation = kPortraitOrientation;
2025 mOutput.editState().needsFiltering = true;
2026 mOutput.editState().isSecure = false;
2027
2028 constexpr bool supportsProtectedContent = false;
2029 Region clearRegion;
2030 auto requests =
2031 mOutput.generateClientCompositionRequests(supportsProtectedContent, clearRegion);
2032
2033 ASSERT_EQ(2u, requests.size());
2034 EXPECT_EQ(leftLayerColor, requests[0].source.solidColor);
2035 EXPECT_EQ(rightLayerColor, requests[1].source.solidColor);
2036}
2037
2038TEST_F(GenerateClientCompositionRequestsTest, ignoresLayersThatDoNotIntersectWithViewport) {
2039 // Layers whose visible region does not intersect with the viewport will be
2040 // skipped when generating client composition request state.
2041
Lloyd Pique01c77c12019-04-17 12:48:32 -07002042 StrictMock<mock::OutputLayer> outputLayer;
Lloyd Pique56eba802019-08-28 15:45:25 -07002043 StrictMock<mock::Layer> layer;
2044 StrictMock<mock::LayerFE> layerFE;
2045
2046 impl::OutputLayerCompositionState outputLayerState;
2047 outputLayerState.clearClientTarget = false;
Lloyd Piquea2468662019-03-07 21:31:06 -08002048 outputLayerState.visibleRegion = Region{Rect{3000, 0, 4000, 1000}};
Lloyd Pique56eba802019-08-28 15:45:25 -07002049
Lloyd Pique9755fb72019-03-26 14:44:40 -07002050 LayerFECompositionState layerFEState;
2051 layerFEState.isOpaque = true;
Lloyd Pique56eba802019-08-28 15:45:25 -07002052
Lloyd Pique01c77c12019-04-17 12:48:32 -07002053 EXPECT_CALL(outputLayer, getState()).WillRepeatedly(ReturnRef(outputLayerState));
2054 EXPECT_CALL(outputLayer, getLayer()).WillRepeatedly(ReturnRef(layer));
2055 EXPECT_CALL(outputLayer, getLayerFE()).WillRepeatedly(ReturnRef(layerFE));
2056 EXPECT_CALL(outputLayer, requiresClientComposition()).WillRepeatedly(Return(true));
2057 EXPECT_CALL(outputLayer, needsFiltering()).WillRepeatedly(Return(false));
Lloyd Pique9755fb72019-03-26 14:44:40 -07002058 EXPECT_CALL(layer, getFEState()).WillRepeatedly(ReturnRef(layerFEState));
Lloyd Pique56eba802019-08-28 15:45:25 -07002059 EXPECT_CALL(layerFE, prepareClientComposition(_)).Times(0);
Adithya Srinivasanb69e0762019-11-11 18:39:53 -08002060 EXPECT_CALL(outputLayer, editState()).WillRepeatedly(ReturnRef(outputLayerState));
Lloyd Pique56eba802019-08-28 15:45:25 -07002061
Lloyd Pique01c77c12019-04-17 12:48:32 -07002062 EXPECT_CALL(mOutput, getOutputLayerCount()).WillRepeatedly(Return(1u));
2063 EXPECT_CALL(mOutput, getOutputLayerOrderedByZByIndex(0u)).WillRepeatedly(Return(&outputLayer));
Lloyd Pique56eba802019-08-28 15:45:25 -07002064
2065 const Rect kPortraitFrame(0, 0, 1000, 2000);
2066 const Rect kPortraitViewport(0, 0, 2000, 1000);
2067 const Rect kPortraitScissor(0, 0, 1000, 2000);
2068 const uint32_t kPortraitOrientation = TR_ROT_90;
2069
2070 mOutput.editState().frame = kPortraitFrame;
2071 mOutput.editState().viewport = kPortraitViewport;
2072 mOutput.editState().scissor = kPortraitScissor;
2073 mOutput.editState().transform = ui::Transform{kPortraitOrientation};
2074 mOutput.editState().orientation = kPortraitOrientation;
2075 mOutput.editState().needsFiltering = true;
2076 mOutput.editState().isSecure = false;
2077
2078 constexpr bool supportsProtectedContent = false;
2079 Region clearRegion;
2080 auto requests =
2081 mOutput.generateClientCompositionRequests(supportsProtectedContent, clearRegion);
2082
2083 EXPECT_EQ(0u, requests.size());
2084}
2085
Lloyd Piquec2d54d42019-08-28 18:04:21 -07002086TEST_F(GenerateClientCompositionRequestsTest, clearsDeviceLayesAfterFirst) {
2087 // If client composition is performed with some layers set to use device
2088 // composition, device layers after the first layer (device or client) will
2089 // clear the frame buffer if they are opaque and if that layer has a flag
2090 // set to do so. The first layer is skipped as the frame buffer is already
2091 // expected to be clear.
2092
Lloyd Pique01c77c12019-04-17 12:48:32 -07002093 StrictMock<mock::OutputLayer> leftOutputLayer;
2094 StrictMock<mock::OutputLayer> rightOutputLayer;
Lloyd Piquec2d54d42019-08-28 18:04:21 -07002095
2096 StrictMock<mock::Layer> leftLayer;
2097 StrictMock<mock::LayerFE> leftLayerFE;
2098 StrictMock<mock::Layer> rightLayer;
2099 StrictMock<mock::LayerFE> rightLayerFE;
2100
2101 impl::OutputLayerCompositionState leftOutputLayerState;
2102 leftOutputLayerState.clearClientTarget = true;
Lloyd Piquea2468662019-03-07 21:31:06 -08002103 leftOutputLayerState.visibleRegion = Region{Rect{0, 0, 1000, 1000}};
Lloyd Piquec2d54d42019-08-28 18:04:21 -07002104
Lloyd Pique9755fb72019-03-26 14:44:40 -07002105 LayerFECompositionState leftLayerFEState;
2106 leftLayerFEState.isOpaque = true;
Lloyd Piquec2d54d42019-08-28 18:04:21 -07002107
2108 impl::OutputLayerCompositionState rightOutputLayerState;
2109 rightOutputLayerState.clearClientTarget = true;
Lloyd Piquea2468662019-03-07 21:31:06 -08002110 rightOutputLayerState.visibleRegion = Region{Rect{1000, 0, 2000, 1000}};
Lloyd Piquec2d54d42019-08-28 18:04:21 -07002111
Lloyd Pique9755fb72019-03-26 14:44:40 -07002112 LayerFECompositionState rightLayerFEState;
2113 rightLayerFEState.isOpaque = true;
Lloyd Piquec2d54d42019-08-28 18:04:21 -07002114
2115 const half3 rightLayerColor{0.f, 1.f, 0.f};
2116 renderengine::LayerSettings rightLayerRESettings;
2117 rightLayerRESettings.geometry.boundaries = FloatRect{456, 0, 0, 0};
2118 rightLayerRESettings.source.solidColor = rightLayerColor;
2119
Lloyd Pique01c77c12019-04-17 12:48:32 -07002120 EXPECT_CALL(leftOutputLayer, getState()).WillRepeatedly(ReturnRef(leftOutputLayerState));
2121 EXPECT_CALL(leftOutputLayer, getLayer()).WillRepeatedly(ReturnRef(leftLayer));
2122 EXPECT_CALL(leftOutputLayer, getLayerFE()).WillRepeatedly(ReturnRef(leftLayerFE));
2123 EXPECT_CALL(leftOutputLayer, requiresClientComposition()).WillRepeatedly(Return(false));
2124 EXPECT_CALL(leftOutputLayer, needsFiltering()).WillRepeatedly(Return(false));
Lloyd Pique9755fb72019-03-26 14:44:40 -07002125 EXPECT_CALL(leftLayer, getFEState()).WillRepeatedly(ReturnRef(leftLayerFEState));
Adithya Srinivasanb69e0762019-11-11 18:39:53 -08002126 EXPECT_CALL(leftOutputLayer, editState()).WillRepeatedly(ReturnRef(leftOutputLayerState));
Lloyd Piquec2d54d42019-08-28 18:04:21 -07002127
Lloyd Pique01c77c12019-04-17 12:48:32 -07002128 EXPECT_CALL(rightOutputLayer, getState()).WillRepeatedly(ReturnRef(rightOutputLayerState));
2129 EXPECT_CALL(rightOutputLayer, getLayer()).WillRepeatedly(ReturnRef(rightLayer));
2130 EXPECT_CALL(rightOutputLayer, getLayerFE()).WillRepeatedly(ReturnRef(rightLayerFE));
2131 EXPECT_CALL(rightOutputLayer, requiresClientComposition()).WillRepeatedly(Return(false));
2132 EXPECT_CALL(rightOutputLayer, needsFiltering()).WillRepeatedly(Return(false));
Lloyd Pique9755fb72019-03-26 14:44:40 -07002133 EXPECT_CALL(rightLayer, getFEState()).WillRepeatedly(ReturnRef(rightLayerFEState));
Lloyd Piquec2d54d42019-08-28 18:04:21 -07002134 EXPECT_CALL(rightLayerFE, prepareClientComposition(_)).WillOnce(Return(rightLayerRESettings));
Adithya Srinivasanb69e0762019-11-11 18:39:53 -08002135 EXPECT_CALL(rightOutputLayer, editState()).WillRepeatedly(ReturnRef(rightOutputLayerState));
Lloyd Piquec2d54d42019-08-28 18:04:21 -07002136
Lloyd Pique01c77c12019-04-17 12:48:32 -07002137 EXPECT_CALL(mOutput, getOutputLayerCount()).WillRepeatedly(Return(2u));
2138 EXPECT_CALL(mOutput, getOutputLayerOrderedByZByIndex(0u))
2139 .WillRepeatedly(Return(&leftOutputLayer));
2140 EXPECT_CALL(mOutput, getOutputLayerOrderedByZByIndex(1u))
2141 .WillRepeatedly(Return(&rightOutputLayer));
Lloyd Piquec2d54d42019-08-28 18:04:21 -07002142
2143 const Rect kPortraitFrame(0, 0, 1000, 2000);
2144 const Rect kPortraitViewport(0, 0, 2000, 1000);
2145 const Rect kPortraitScissor(0, 0, 1000, 2000);
2146 const uint32_t kPortraitOrientation = TR_ROT_90;
2147
2148 mOutput.editState().frame = kPortraitFrame;
2149 mOutput.editState().viewport = kPortraitViewport;
2150 mOutput.editState().scissor = kPortraitScissor;
2151 mOutput.editState().transform = ui::Transform{kPortraitOrientation};
2152 mOutput.editState().orientation = kPortraitOrientation;
2153 mOutput.editState().needsFiltering = true;
2154 mOutput.editState().isSecure = false;
2155
2156 constexpr bool supportsProtectedContent = false;
2157 Region clearRegion;
2158 auto requests =
2159 mOutput.generateClientCompositionRequests(supportsProtectedContent, clearRegion);
2160
2161 const half3 clearColor{0.f, 0.f, 0.f};
2162
2163 ASSERT_EQ(1u, requests.size());
2164 EXPECT_EQ(456.f, requests[0].geometry.boundaries.left);
2165 EXPECT_EQ(clearColor, requests[0].source.solidColor);
2166}
2167
Lloyd Pique32cbe282018-10-19 13:09:22 -07002168} // namespace
2169} // namespace android::compositionengine