blob: d87389fb62139a881991cd7e2f70367154738540 [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"
Lloyd Pique32cbe282018-10-19 13:09:22 -070038
39namespace android::compositionengine {
40namespace {
41
Lloyd Pique56eba802019-08-28 15:45:25 -070042using testing::_;
Lloyd Pique03561a62019-11-19 18:34:52 -080043using testing::ByMove;
Lloyd Pique17ca7422019-11-14 14:24:10 -080044using testing::DoAll;
Lloyd Pique6818fa52019-12-03 12:32:13 -080045using testing::ElementsAreArray;
Lloyd Pique07178e32019-11-19 19:15:26 -080046using testing::Eq;
Lloyd Piquefaa3f192019-11-14 14:05:09 -080047using testing::InSequence;
Lloyd Pique6818fa52019-12-03 12:32:13 -080048using testing::Invoke;
49using testing::IsEmpty;
Lloyd Pique17ca7422019-11-14 14:24:10 -080050using testing::Mock;
Lloyd Pique07178e32019-11-19 19:15:26 -080051using testing::Property;
Lloyd Piquefaa3f192019-11-14 14:05:09 -080052using testing::Ref;
Lloyd Pique31cb2942018-10-19 17:23:03 -070053using testing::Return;
Lloyd Pique32cbe282018-10-19 13:09:22 -070054using testing::ReturnRef;
Lloyd Pique17ca7422019-11-14 14:24:10 -080055using testing::SetArgPointee;
Lloyd Pique32cbe282018-10-19 13:09:22 -070056using testing::StrictMock;
57
Lloyd Pique56eba802019-08-28 15:45:25 -070058constexpr auto TR_IDENT = 0u;
59constexpr auto TR_ROT_90 = HAL_TRANSFORM_ROT_90;
60
Lloyd Pique3eb1b212019-03-07 21:15:40 -080061const mat4 kIdentity;
62const mat4 kNonIdentityHalf = mat4() * 0.5;
63const mat4 kNonIdentityQuarter = mat4() * 0.25;
64
Lloyd Pique17ca7422019-11-14 14:24:10 -080065constexpr OutputColorSetting kVendorSpecifiedOutputColorSetting =
66 static_cast<OutputColorSetting>(0x100);
67
Lloyd Piquefaa3f192019-11-14 14:05:09 -080068struct OutputPartialMockBase : public impl::Output {
69 // compositionengine::Output overrides
70 const OutputCompositionState& getState() const override { return mState; }
71 OutputCompositionState& editState() override { return mState; }
72
73 // Use mocks for all the remaining virtual functions
74 // not implemented by the base implementation class.
75 MOCK_CONST_METHOD0(getOutputLayerCount, size_t());
76 MOCK_CONST_METHOD1(getOutputLayerOrderedByZByIndex, compositionengine::OutputLayer*(size_t));
77 MOCK_METHOD3(ensureOutputLayer,
78 compositionengine::OutputLayer*(std::optional<size_t>,
79 const std::shared_ptr<compositionengine::Layer>&,
80 const sp<LayerFE>&));
81 MOCK_METHOD0(finalizePendingOutputLayers, void());
82 MOCK_METHOD0(clearOutputLayers, void());
83 MOCK_CONST_METHOD1(dumpState, void(std::string&));
84 MOCK_CONST_METHOD0(getCompositionEngine, const CompositionEngine&());
85 MOCK_METHOD2(injectOutputLayerForTest,
86 compositionengine::OutputLayer*(const std::shared_ptr<compositionengine::Layer>&,
87 const sp<LayerFE>&));
88 MOCK_METHOD1(injectOutputLayerForTest, void(std::unique_ptr<OutputLayer>));
89
90 impl::OutputCompositionState mState;
91};
92
Lloyd Pique66d68602019-02-13 14:23:31 -080093struct OutputTest : public testing::Test {
Lloyd Pique01c77c12019-04-17 12:48:32 -070094 class Output : public impl::Output {
95 public:
96 using impl::Output::injectOutputLayerForTest;
97 virtual void injectOutputLayerForTest(std::unique_ptr<compositionengine::OutputLayer>) = 0;
98 };
99
100 static std::shared_ptr<Output> createOutput(
101 const compositionengine::CompositionEngine& compositionEngine) {
102 return impl::createOutputTemplated<Output>(compositionEngine);
103 }
104
Lloyd Pique31cb2942018-10-19 17:23:03 -0700105 OutputTest() {
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700106 mOutput->setDisplayColorProfileForTest(
Lloyd Pique3d0c02e2018-10-19 18:38:12 -0700107 std::unique_ptr<DisplayColorProfile>(mDisplayColorProfile));
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700108 mOutput->setRenderSurfaceForTest(std::unique_ptr<RenderSurface>(mRenderSurface));
Lloyd Piqueef958122019-02-05 18:00:12 -0800109
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700110 mOutput->editState().bounds = kDefaultDisplaySize;
Lloyd Pique31cb2942018-10-19 17:23:03 -0700111 }
Lloyd Pique32cbe282018-10-19 13:09:22 -0700112
Lloyd Piqueef958122019-02-05 18:00:12 -0800113 static const Rect kDefaultDisplaySize;
114
Lloyd Pique32cbe282018-10-19 13:09:22 -0700115 StrictMock<mock::CompositionEngine> mCompositionEngine;
Lloyd Pique3d0c02e2018-10-19 18:38:12 -0700116 mock::DisplayColorProfile* mDisplayColorProfile = new StrictMock<mock::DisplayColorProfile>();
Lloyd Pique31cb2942018-10-19 17:23:03 -0700117 mock::RenderSurface* mRenderSurface = new StrictMock<mock::RenderSurface>();
Lloyd Pique01c77c12019-04-17 12:48:32 -0700118 std::shared_ptr<Output> mOutput = createOutput(mCompositionEngine);
Lloyd Pique32cbe282018-10-19 13:09:22 -0700119};
120
Lloyd Piquec0ee6ba2019-11-14 12:55:53 -0800121// Extension of the base test useful for checking interactions with the LayerFE
122// functions to latch composition state.
123struct OutputLatchFEStateTest : public OutputTest {
124 OutputLatchFEStateTest() {
125 EXPECT_CALL(*mOutputLayer1, getLayer()).WillRepeatedly(ReturnRef(mLayer1));
126 EXPECT_CALL(*mOutputLayer2, getLayer()).WillRepeatedly(ReturnRef(mLayer2));
127 EXPECT_CALL(*mOutputLayer3, getLayer()).WillRepeatedly(ReturnRef(mLayer3));
128
129 EXPECT_CALL(*mOutputLayer1, getLayerFE()).WillRepeatedly(ReturnRef(mLayer1FE));
130 EXPECT_CALL(*mOutputLayer2, getLayerFE()).WillRepeatedly(ReturnRef(mLayer2FE));
131 EXPECT_CALL(*mOutputLayer3, getLayerFE()).WillRepeatedly(ReturnRef(mLayer3FE));
132
133 EXPECT_CALL(mLayer1, editFEState()).WillRepeatedly(ReturnRef(mLayer1FEState));
134 EXPECT_CALL(mLayer2, editFEState()).WillRepeatedly(ReturnRef(mLayer2FEState));
135 EXPECT_CALL(mLayer3, editFEState()).WillRepeatedly(ReturnRef(mLayer3FEState));
136 }
137
138 void injectLayer(std::unique_ptr<mock::OutputLayer> layer) {
139 mOutput->injectOutputLayerForTest(std::unique_ptr<OutputLayer>(layer.release()));
140 }
141
142 std::unique_ptr<mock::OutputLayer> mOutputLayer1{new StrictMock<mock::OutputLayer>};
143 std::unique_ptr<mock::OutputLayer> mOutputLayer2{new StrictMock<mock::OutputLayer>};
144 std::unique_ptr<mock::OutputLayer> mOutputLayer3{new StrictMock<mock::OutputLayer>};
145
146 StrictMock<mock::Layer> mLayer1;
147 StrictMock<mock::Layer> mLayer2;
148 StrictMock<mock::Layer> mLayer3;
149
150 StrictMock<mock::LayerFE> mLayer1FE;
151 StrictMock<mock::LayerFE> mLayer2FE;
152 StrictMock<mock::LayerFE> mLayer3FE;
153
154 LayerFECompositionState mLayer1FEState;
155 LayerFECompositionState mLayer2FEState;
156 LayerFECompositionState mLayer3FEState;
157};
158
Lloyd Piqueef958122019-02-05 18:00:12 -0800159const Rect OutputTest::kDefaultDisplaySize{100, 200};
160
Lloyd Pique17ca7422019-11-14 14:24:10 -0800161using ColorProfile = compositionengine::Output::ColorProfile;
162
163void dumpColorProfile(ColorProfile profile, std::string& result, const char* name) {
164 android::base::StringAppendF(&result, "%s (%s[%d] %s[%d] %s[%d] %s[%d]) ", name,
165 toString(profile.mode).c_str(), profile.mode,
166 toString(profile.dataspace).c_str(), profile.dataspace,
167 toString(profile.renderIntent).c_str(), profile.renderIntent,
168 toString(profile.colorSpaceAgnosticDataspace).c_str(),
169 profile.colorSpaceAgnosticDataspace);
170}
171
172// Checks for a ColorProfile match
173MATCHER_P(ColorProfileEq, expected, "") {
174 std::string buf;
175 buf.append("ColorProfiles are not equal\n");
176 dumpColorProfile(expected, buf, "expected value");
177 dumpColorProfile(arg, buf, "actual value");
178 *result_listener << buf;
179
180 return (expected.mode == arg.mode) && (expected.dataspace == arg.dataspace) &&
181 (expected.renderIntent == arg.renderIntent) &&
182 (expected.colorSpaceAgnosticDataspace == arg.colorSpaceAgnosticDataspace);
183}
184
Lloyd Pique66d68602019-02-13 14:23:31 -0800185/*
Lloyd Pique32cbe282018-10-19 13:09:22 -0700186 * Basic construction
187 */
188
Lloyd Pique31cb2942018-10-19 17:23:03 -0700189TEST_F(OutputTest, canInstantiateOutput) {
190 // The validation check checks each required component.
Lloyd Pique3d0c02e2018-10-19 18:38:12 -0700191 EXPECT_CALL(*mDisplayColorProfile, isValid()).WillOnce(Return(true));
Lloyd Pique31cb2942018-10-19 17:23:03 -0700192 EXPECT_CALL(*mRenderSurface, isValid()).WillOnce(Return(true));
193
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700194 EXPECT_TRUE(mOutput->isValid());
Lloyd Pique31cb2942018-10-19 17:23:03 -0700195
196 // If we take away the required components, it is no longer valid.
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700197 mOutput->setRenderSurfaceForTest(std::unique_ptr<RenderSurface>());
Lloyd Pique31cb2942018-10-19 17:23:03 -0700198
Lloyd Pique3d0c02e2018-10-19 18:38:12 -0700199 EXPECT_CALL(*mDisplayColorProfile, isValid()).WillOnce(Return(true));
200
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700201 EXPECT_FALSE(mOutput->isValid());
Lloyd Pique31cb2942018-10-19 17:23:03 -0700202}
Lloyd Pique32cbe282018-10-19 13:09:22 -0700203
Lloyd Pique66d68602019-02-13 14:23:31 -0800204/*
Lloyd Pique32cbe282018-10-19 13:09:22 -0700205 * Output::setCompositionEnabled()
206 */
207
208TEST_F(OutputTest, setCompositionEnabledDoesNothingIfAlreadyEnabled) {
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700209 mOutput->editState().isEnabled = true;
Lloyd Pique32cbe282018-10-19 13:09:22 -0700210
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700211 mOutput->setCompositionEnabled(true);
Lloyd Pique32cbe282018-10-19 13:09:22 -0700212
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700213 EXPECT_TRUE(mOutput->getState().isEnabled);
214 EXPECT_THAT(mOutput->getState().dirtyRegion, RegionEq(Region()));
Lloyd Pique32cbe282018-10-19 13:09:22 -0700215}
216
217TEST_F(OutputTest, setCompositionEnabledSetsEnabledAndDirtiesEntireOutput) {
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700218 mOutput->editState().isEnabled = false;
Lloyd Pique32cbe282018-10-19 13:09:22 -0700219
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700220 mOutput->setCompositionEnabled(true);
Lloyd Pique32cbe282018-10-19 13:09:22 -0700221
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700222 EXPECT_TRUE(mOutput->getState().isEnabled);
223 EXPECT_THAT(mOutput->getState().dirtyRegion, RegionEq(Region(kDefaultDisplaySize)));
Lloyd Pique32cbe282018-10-19 13:09:22 -0700224}
225
226TEST_F(OutputTest, setCompositionEnabledSetsDisabledAndDirtiesEntireOutput) {
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700227 mOutput->editState().isEnabled = true;
Lloyd Pique32cbe282018-10-19 13:09:22 -0700228
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700229 mOutput->setCompositionEnabled(false);
Lloyd Pique32cbe282018-10-19 13:09:22 -0700230
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700231 EXPECT_FALSE(mOutput->getState().isEnabled);
232 EXPECT_THAT(mOutput->getState().dirtyRegion, RegionEq(Region(kDefaultDisplaySize)));
Lloyd Pique32cbe282018-10-19 13:09:22 -0700233}
234
Lloyd Pique66d68602019-02-13 14:23:31 -0800235/*
Lloyd Pique32cbe282018-10-19 13:09:22 -0700236 * Output::setProjection()
237 */
238
239TEST_F(OutputTest, setProjectionTriviallyWorks) {
240 const ui::Transform transform{ui::Transform::ROT_180};
241 const int32_t orientation = 123;
242 const Rect frame{1, 2, 3, 4};
243 const Rect viewport{5, 6, 7, 8};
244 const Rect scissor{9, 10, 11, 12};
245 const bool needsFiltering = true;
246
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700247 mOutput->setProjection(transform, orientation, frame, viewport, scissor, needsFiltering);
Lloyd Pique32cbe282018-10-19 13:09:22 -0700248
Lloyd Piqueea629282019-12-03 15:57:10 -0800249 EXPECT_THAT(mOutput->getState().transform, transform);
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700250 EXPECT_EQ(orientation, mOutput->getState().orientation);
251 EXPECT_EQ(frame, mOutput->getState().frame);
252 EXPECT_EQ(viewport, mOutput->getState().viewport);
253 EXPECT_EQ(scissor, mOutput->getState().scissor);
254 EXPECT_EQ(needsFiltering, mOutput->getState().needsFiltering);
Lloyd Pique32cbe282018-10-19 13:09:22 -0700255}
256
Lloyd Pique66d68602019-02-13 14:23:31 -0800257/*
Lloyd Pique32cbe282018-10-19 13:09:22 -0700258 * Output::setBounds()
259 */
260
261TEST_F(OutputTest, setBoundsSetsSizeAndDirtiesEntireOutput) {
Lloyd Piqueef958122019-02-05 18:00:12 -0800262 const ui::Size displaySize{200, 400};
Lloyd Pique31cb2942018-10-19 17:23:03 -0700263
264 EXPECT_CALL(*mRenderSurface, setDisplaySize(displaySize)).Times(1);
265 EXPECT_CALL(*mRenderSurface, getSize()).WillOnce(ReturnRef(displaySize));
266
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700267 mOutput->setBounds(displaySize);
Lloyd Pique32cbe282018-10-19 13:09:22 -0700268
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700269 EXPECT_EQ(Rect(displaySize), mOutput->getState().bounds);
Lloyd Pique32cbe282018-10-19 13:09:22 -0700270
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700271 EXPECT_THAT(mOutput->getState().dirtyRegion, RegionEq(Region(Rect(displaySize))));
Lloyd Pique32cbe282018-10-19 13:09:22 -0700272}
273
Lloyd Pique66d68602019-02-13 14:23:31 -0800274/*
Lloyd Pique32cbe282018-10-19 13:09:22 -0700275 * Output::setLayerStackFilter()
276 */
277
278TEST_F(OutputTest, setLayerStackFilterSetsFilterAndDirtiesEntireOutput) {
Lloyd Pique32cbe282018-10-19 13:09:22 -0700279 const uint32_t layerStack = 123u;
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700280 mOutput->setLayerStackFilter(layerStack, true);
Lloyd Pique32cbe282018-10-19 13:09:22 -0700281
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700282 EXPECT_TRUE(mOutput->getState().layerStackInternal);
283 EXPECT_EQ(layerStack, mOutput->getState().layerStackId);
Lloyd Pique32cbe282018-10-19 13:09:22 -0700284
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700285 EXPECT_THAT(mOutput->getState().dirtyRegion, RegionEq(Region(kDefaultDisplaySize)));
Lloyd Pique32cbe282018-10-19 13:09:22 -0700286}
287
Lloyd Pique66d68602019-02-13 14:23:31 -0800288/*
Lloyd Pique32cbe282018-10-19 13:09:22 -0700289 * Output::setColorTransform
290 */
291
Lloyd Pique3eb1b212019-03-07 21:15:40 -0800292TEST_F(OutputTest, setColorTransformWithNoChangeFlaggedSkipsUpdates) {
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700293 mOutput->editState().colorTransformMatrix = kIdentity;
Lloyd Pique32cbe282018-10-19 13:09:22 -0700294
Lloyd Pique3eb1b212019-03-07 21:15:40 -0800295 // If no colorTransformMatrix is set the update should be skipped.
296 CompositionRefreshArgs refreshArgs;
297 refreshArgs.colorTransformMatrix = std::nullopt;
Lloyd Pique32cbe282018-10-19 13:09:22 -0700298
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700299 mOutput->setColorTransform(refreshArgs);
Lloyd Pique32cbe282018-10-19 13:09:22 -0700300
Lloyd Pique3eb1b212019-03-07 21:15:40 -0800301 // The internal state should be unchanged
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700302 EXPECT_EQ(kIdentity, mOutput->getState().colorTransformMatrix);
Lloyd Pique3eb1b212019-03-07 21:15:40 -0800303
304 // No dirty region should be set
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700305 EXPECT_THAT(mOutput->getState().dirtyRegion, RegionEq(Region()));
Lloyd Pique3eb1b212019-03-07 21:15:40 -0800306}
Lloyd Piqueef958122019-02-05 18:00:12 -0800307
Lloyd Pique3eb1b212019-03-07 21:15:40 -0800308TEST_F(OutputTest, setColorTransformWithNoActualChangeSkipsUpdates) {
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700309 mOutput->editState().colorTransformMatrix = kIdentity;
Lloyd Pique32cbe282018-10-19 13:09:22 -0700310
Lloyd Pique3eb1b212019-03-07 21:15:40 -0800311 // Attempting to set the same colorTransformMatrix that is already set should
312 // also skip the update.
313 CompositionRefreshArgs refreshArgs;
314 refreshArgs.colorTransformMatrix = kIdentity;
Lloyd Pique32cbe282018-10-19 13:09:22 -0700315
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700316 mOutput->setColorTransform(refreshArgs);
Lloyd Pique77f79a22019-04-29 15:55:40 -0700317
Lloyd Pique3eb1b212019-03-07 21:15:40 -0800318 // The internal state should be unchanged
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700319 EXPECT_EQ(kIdentity, mOutput->getState().colorTransformMatrix);
Lloyd Pique3eb1b212019-03-07 21:15:40 -0800320
321 // No dirty region should be set
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700322 EXPECT_THAT(mOutput->getState().dirtyRegion, RegionEq(Region()));
Lloyd Pique3eb1b212019-03-07 21:15:40 -0800323}
324
325TEST_F(OutputTest, setColorTransformPerformsUpdateToIdentity) {
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700326 mOutput->editState().colorTransformMatrix = kNonIdentityHalf;
Lloyd Pique3eb1b212019-03-07 21:15:40 -0800327
328 // Setting a different colorTransformMatrix should perform the update.
329 CompositionRefreshArgs refreshArgs;
330 refreshArgs.colorTransformMatrix = kIdentity;
331
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700332 mOutput->setColorTransform(refreshArgs);
Lloyd Pique3eb1b212019-03-07 21:15:40 -0800333
334 // The internal state should have been updated
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700335 EXPECT_EQ(kIdentity, mOutput->getState().colorTransformMatrix);
Lloyd Pique3eb1b212019-03-07 21:15:40 -0800336
337 // The dirtyRegion should be set to the full display size
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700338 EXPECT_THAT(mOutput->getState().dirtyRegion, RegionEq(Region(kDefaultDisplaySize)));
Lloyd Pique3eb1b212019-03-07 21:15:40 -0800339}
Lloyd Pique77f79a22019-04-29 15:55:40 -0700340
Lloyd Pique3eb1b212019-03-07 21:15:40 -0800341TEST_F(OutputTest, setColorTransformPerformsUpdateForIdentityToHalf) {
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700342 mOutput->editState().colorTransformMatrix = kIdentity;
Lloyd Pique77f79a22019-04-29 15:55:40 -0700343
Lloyd Pique3eb1b212019-03-07 21:15:40 -0800344 // Setting a different colorTransformMatrix should perform the update.
345 CompositionRefreshArgs refreshArgs;
346 refreshArgs.colorTransformMatrix = kNonIdentityHalf;
Lloyd Pique77f79a22019-04-29 15:55:40 -0700347
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700348 mOutput->setColorTransform(refreshArgs);
Lloyd Piqueef958122019-02-05 18:00:12 -0800349
Lloyd Pique3eb1b212019-03-07 21:15:40 -0800350 // The internal state should have been updated
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700351 EXPECT_EQ(kNonIdentityHalf, mOutput->getState().colorTransformMatrix);
Lloyd Pique3eb1b212019-03-07 21:15:40 -0800352
353 // The dirtyRegion should be set to the full display size
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700354 EXPECT_THAT(mOutput->getState().dirtyRegion, RegionEq(Region(kDefaultDisplaySize)));
Lloyd Pique3eb1b212019-03-07 21:15:40 -0800355}
356
357TEST_F(OutputTest, setColorTransformPerformsUpdateForHalfToQuarter) {
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700358 mOutput->editState().colorTransformMatrix = kNonIdentityHalf;
Lloyd Pique3eb1b212019-03-07 21:15:40 -0800359
360 // Setting a different colorTransformMatrix should perform the update.
361 CompositionRefreshArgs refreshArgs;
362 refreshArgs.colorTransformMatrix = kNonIdentityQuarter;
363
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700364 mOutput->setColorTransform(refreshArgs);
Lloyd Pique3eb1b212019-03-07 21:15:40 -0800365
366 // The internal state should have been updated
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700367 EXPECT_EQ(kNonIdentityQuarter, mOutput->getState().colorTransformMatrix);
Lloyd Pique3eb1b212019-03-07 21:15:40 -0800368
369 // The dirtyRegion should be set to the full display size
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700370 EXPECT_THAT(mOutput->getState().dirtyRegion, RegionEq(Region(kDefaultDisplaySize)));
Lloyd Pique32cbe282018-10-19 13:09:22 -0700371}
372
Lloyd Pique66d68602019-02-13 14:23:31 -0800373/*
Lloyd Pique17ca7422019-11-14 14:24:10 -0800374 * Output::setColorProfile
Lloyd Pique32cbe282018-10-19 13:09:22 -0700375 */
376
Lloyd Pique17ca7422019-11-14 14:24:10 -0800377using OutputSetColorProfileTest = OutputTest;
378
379TEST_F(OutputSetColorProfileTest, setsStateAndDirtiesOutputIfChanged) {
Lloyd Pique6a3b4462019-03-07 20:58:12 -0800380 using ColorProfile = Output::ColorProfile;
381
Lloyd Piquef5275482019-01-29 18:42:42 -0800382 EXPECT_CALL(*mDisplayColorProfile,
383 getTargetDataspace(ui::ColorMode::DISPLAY_P3, ui::Dataspace::DISPLAY_P3,
384 ui::Dataspace::UNKNOWN))
385 .WillOnce(Return(ui::Dataspace::UNKNOWN));
Lloyd Piqueef958122019-02-05 18:00:12 -0800386 EXPECT_CALL(*mRenderSurface, setBufferDataspace(ui::Dataspace::DISPLAY_P3)).Times(1);
Lloyd Pique31cb2942018-10-19 17:23:03 -0700387
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700388 mOutput->setColorProfile(ColorProfile{ui::ColorMode::DISPLAY_P3, ui::Dataspace::DISPLAY_P3,
389 ui::RenderIntent::TONE_MAP_COLORIMETRIC,
390 ui::Dataspace::UNKNOWN});
Lloyd Pique32cbe282018-10-19 13:09:22 -0700391
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700392 EXPECT_EQ(ui::ColorMode::DISPLAY_P3, mOutput->getState().colorMode);
393 EXPECT_EQ(ui::Dataspace::DISPLAY_P3, mOutput->getState().dataspace);
394 EXPECT_EQ(ui::RenderIntent::TONE_MAP_COLORIMETRIC, mOutput->getState().renderIntent);
395 EXPECT_EQ(ui::Dataspace::UNKNOWN, mOutput->getState().targetDataspace);
Lloyd Piquef5275482019-01-29 18:42:42 -0800396
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700397 EXPECT_THAT(mOutput->getState().dirtyRegion, RegionEq(Region(kDefaultDisplaySize)));
Lloyd Piqueef958122019-02-05 18:00:12 -0800398}
399
Lloyd Pique17ca7422019-11-14 14:24:10 -0800400TEST_F(OutputSetColorProfileTest, doesNothingIfNoChange) {
Lloyd Pique6a3b4462019-03-07 20:58:12 -0800401 using ColorProfile = Output::ColorProfile;
402
Lloyd Piquef5275482019-01-29 18:42:42 -0800403 EXPECT_CALL(*mDisplayColorProfile,
404 getTargetDataspace(ui::ColorMode::DISPLAY_P3, ui::Dataspace::DISPLAY_P3,
405 ui::Dataspace::UNKNOWN))
406 .WillOnce(Return(ui::Dataspace::UNKNOWN));
407
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700408 mOutput->editState().colorMode = ui::ColorMode::DISPLAY_P3;
409 mOutput->editState().dataspace = ui::Dataspace::DISPLAY_P3;
410 mOutput->editState().renderIntent = ui::RenderIntent::TONE_MAP_COLORIMETRIC;
411 mOutput->editState().targetDataspace = ui::Dataspace::UNKNOWN;
Lloyd Piqueef958122019-02-05 18:00:12 -0800412
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700413 mOutput->setColorProfile(ColorProfile{ui::ColorMode::DISPLAY_P3, ui::Dataspace::DISPLAY_P3,
414 ui::RenderIntent::TONE_MAP_COLORIMETRIC,
415 ui::Dataspace::UNKNOWN});
Lloyd Piqueef958122019-02-05 18:00:12 -0800416
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700417 EXPECT_THAT(mOutput->getState().dirtyRegion, RegionEq(Region()));
Lloyd Pique32cbe282018-10-19 13:09:22 -0700418}
419
Lloyd Pique66d68602019-02-13 14:23:31 -0800420/*
Lloyd Pique31cb2942018-10-19 17:23:03 -0700421 * Output::setRenderSurface()
422 */
423
424TEST_F(OutputTest, setRenderSurfaceResetsBounds) {
425 const ui::Size newDisplaySize{640, 480};
426
427 mock::RenderSurface* renderSurface = new StrictMock<mock::RenderSurface>();
428 EXPECT_CALL(*renderSurface, getSize()).WillOnce(ReturnRef(newDisplaySize));
429
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700430 mOutput->setRenderSurface(std::unique_ptr<RenderSurface>(renderSurface));
Lloyd Pique31cb2942018-10-19 17:23:03 -0700431
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700432 EXPECT_EQ(Rect(newDisplaySize), mOutput->getState().bounds);
Lloyd Pique31cb2942018-10-19 17:23:03 -0700433}
434
Lloyd Pique66d68602019-02-13 14:23:31 -0800435/*
Alec Mourie7d1d4a2019-02-05 01:13:46 +0000436 * Output::getDirtyRegion()
Lloyd Pique32cbe282018-10-19 13:09:22 -0700437 */
438
Alec Mourie7d1d4a2019-02-05 01:13:46 +0000439TEST_F(OutputTest, getDirtyRegionWithRepaintEverythingTrue) {
440 const Rect viewport{100, 200};
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700441 mOutput->editState().viewport = viewport;
442 mOutput->editState().dirtyRegion.set(50, 300);
Lloyd Pique32cbe282018-10-19 13:09:22 -0700443
444 {
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700445 Region result = mOutput->getDirtyRegion(true);
Lloyd Pique32cbe282018-10-19 13:09:22 -0700446
Alec Mourie7d1d4a2019-02-05 01:13:46 +0000447 EXPECT_THAT(result, RegionEq(Region(viewport)));
Lloyd Pique32cbe282018-10-19 13:09:22 -0700448 }
449}
450
Alec Mourie7d1d4a2019-02-05 01:13:46 +0000451TEST_F(OutputTest, getDirtyRegionWithRepaintEverythingFalse) {
452 const Rect viewport{100, 200};
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700453 mOutput->editState().viewport = viewport;
454 mOutput->editState().dirtyRegion.set(50, 300);
Lloyd Pique32cbe282018-10-19 13:09:22 -0700455
456 {
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700457 Region result = mOutput->getDirtyRegion(false);
Lloyd Pique32cbe282018-10-19 13:09:22 -0700458
459 // The dirtyRegion should be clipped to the display bounds.
460 EXPECT_THAT(result, RegionEq(Region(Rect(50, 200))));
461 }
Lloyd Pique32cbe282018-10-19 13:09:22 -0700462}
463
Lloyd Pique66d68602019-02-13 14:23:31 -0800464/*
Lloyd Piqueef36b002019-01-23 17:52:04 -0800465 * Output::belongsInOutput()
466 */
467
468TEST_F(OutputTest, belongsInOutputFiltersAsExpected) {
469 const uint32_t layerStack1 = 123u;
470 const uint32_t layerStack2 = 456u;
471
472 // If the output accepts layerStack1 and internal-only layers....
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700473 mOutput->setLayerStackFilter(layerStack1, true);
Lloyd Piqueef36b002019-01-23 17:52:04 -0800474
Lloyd Piquec6687342019-03-07 21:34:57 -0800475 // A layer with no layerStack does not belong to it, internal-only or not.
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700476 EXPECT_FALSE(mOutput->belongsInOutput(std::nullopt, false));
477 EXPECT_FALSE(mOutput->belongsInOutput(std::nullopt, true));
Lloyd Piquec6687342019-03-07 21:34:57 -0800478
Lloyd Piqueef36b002019-01-23 17:52:04 -0800479 // Any layer with layerStack1 belongs to it, internal-only or not.
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700480 EXPECT_TRUE(mOutput->belongsInOutput(layerStack1, false));
481 EXPECT_TRUE(mOutput->belongsInOutput(layerStack1, true));
482 EXPECT_FALSE(mOutput->belongsInOutput(layerStack2, true));
483 EXPECT_FALSE(mOutput->belongsInOutput(layerStack2, false));
Lloyd Piqueef36b002019-01-23 17:52:04 -0800484
485 // If the output accepts layerStack21 but not internal-only layers...
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700486 mOutput->setLayerStackFilter(layerStack1, false);
Lloyd Piqueef36b002019-01-23 17:52:04 -0800487
488 // Only non-internal layers with layerStack1 belong to it.
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700489 EXPECT_TRUE(mOutput->belongsInOutput(layerStack1, false));
490 EXPECT_FALSE(mOutput->belongsInOutput(layerStack1, true));
491 EXPECT_FALSE(mOutput->belongsInOutput(layerStack2, true));
492 EXPECT_FALSE(mOutput->belongsInOutput(layerStack2, false));
Lloyd Piqueef36b002019-01-23 17:52:04 -0800493}
494
Lloyd Pique66c20c42019-03-07 21:44:02 -0800495TEST_F(OutputTest, belongsInOutputFiltersLayersAsExpected) {
496 StrictMock<mock::Layer> layer;
Lloyd Pique9755fb72019-03-26 14:44:40 -0700497 LayerFECompositionState layerFEState;
Lloyd Pique66c20c42019-03-07 21:44:02 -0800498
Lloyd Pique9755fb72019-03-26 14:44:40 -0700499 EXPECT_CALL(layer, getFEState()).WillRepeatedly(ReturnRef(layerFEState));
Lloyd Pique66c20c42019-03-07 21:44:02 -0800500
501 const uint32_t layerStack1 = 123u;
502 const uint32_t layerStack2 = 456u;
503
504 // If the output accepts layerStack1 and internal-only layers....
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700505 mOutput->setLayerStackFilter(layerStack1, true);
Lloyd Pique66c20c42019-03-07 21:44:02 -0800506
507 // A null layer pointer does not belong to the output
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700508 EXPECT_FALSE(mOutput->belongsInOutput(nullptr));
Lloyd Pique66c20c42019-03-07 21:44:02 -0800509
510 // A layer with no layerStack does not belong to it, internal-only or not.
Lloyd Pique9755fb72019-03-26 14:44:40 -0700511 layerFEState.layerStackId = std::nullopt;
512 layerFEState.internalOnly = false;
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700513 EXPECT_FALSE(mOutput->belongsInOutput(&layer));
Lloyd Pique66c20c42019-03-07 21:44:02 -0800514
Lloyd Pique9755fb72019-03-26 14:44:40 -0700515 layerFEState.layerStackId = std::nullopt;
516 layerFEState.internalOnly = true;
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700517 EXPECT_FALSE(mOutput->belongsInOutput(&layer));
Lloyd Pique66c20c42019-03-07 21:44:02 -0800518
519 // Any layer with layerStack1 belongs to it, internal-only or not.
Lloyd Pique9755fb72019-03-26 14:44:40 -0700520 layerFEState.layerStackId = layerStack1;
521 layerFEState.internalOnly = false;
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700522 EXPECT_TRUE(mOutput->belongsInOutput(&layer));
Lloyd Pique66c20c42019-03-07 21:44:02 -0800523
Lloyd Pique9755fb72019-03-26 14:44:40 -0700524 layerFEState.layerStackId = layerStack1;
525 layerFEState.internalOnly = true;
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700526 EXPECT_TRUE(mOutput->belongsInOutput(&layer));
Lloyd Pique66c20c42019-03-07 21:44:02 -0800527
Lloyd Pique9755fb72019-03-26 14:44:40 -0700528 layerFEState.layerStackId = layerStack2;
529 layerFEState.internalOnly = true;
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700530 EXPECT_FALSE(mOutput->belongsInOutput(&layer));
Lloyd Pique66c20c42019-03-07 21:44:02 -0800531
Lloyd Pique9755fb72019-03-26 14:44:40 -0700532 layerFEState.layerStackId = layerStack2;
533 layerFEState.internalOnly = false;
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700534 EXPECT_FALSE(mOutput->belongsInOutput(&layer));
Lloyd Pique66c20c42019-03-07 21:44:02 -0800535
536 // If the output accepts layerStack1 but not internal-only layers...
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700537 mOutput->setLayerStackFilter(layerStack1, false);
Lloyd Pique66c20c42019-03-07 21:44:02 -0800538
539 // A null layer pointer does not belong to the output
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700540 EXPECT_FALSE(mOutput->belongsInOutput(nullptr));
Lloyd Pique66c20c42019-03-07 21:44:02 -0800541
542 // Only non-internal layers with layerStack1 belong to it.
Lloyd Pique9755fb72019-03-26 14:44:40 -0700543 layerFEState.layerStackId = layerStack1;
544 layerFEState.internalOnly = false;
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700545 EXPECT_TRUE(mOutput->belongsInOutput(&layer));
Lloyd Pique66c20c42019-03-07 21:44:02 -0800546
Lloyd Pique9755fb72019-03-26 14:44:40 -0700547 layerFEState.layerStackId = layerStack1;
548 layerFEState.internalOnly = true;
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700549 EXPECT_FALSE(mOutput->belongsInOutput(&layer));
Lloyd Pique66c20c42019-03-07 21:44:02 -0800550
Lloyd Pique9755fb72019-03-26 14:44:40 -0700551 layerFEState.layerStackId = layerStack2;
552 layerFEState.internalOnly = true;
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700553 EXPECT_FALSE(mOutput->belongsInOutput(&layer));
Lloyd Pique66c20c42019-03-07 21:44:02 -0800554
Lloyd Pique9755fb72019-03-26 14:44:40 -0700555 layerFEState.layerStackId = layerStack2;
556 layerFEState.internalOnly = false;
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700557 EXPECT_FALSE(mOutput->belongsInOutput(&layer));
Lloyd Pique66c20c42019-03-07 21:44:02 -0800558}
559
Lloyd Pique66d68602019-02-13 14:23:31 -0800560/*
Lloyd Piquecc01a452018-12-04 17:24:00 -0800561 * Output::getOutputLayerForLayer()
562 */
563
564TEST_F(OutputTest, getOutputLayerForLayerWorks) {
565 mock::OutputLayer* outputLayer1 = new StrictMock<mock::OutputLayer>();
566 mock::OutputLayer* outputLayer2 = new StrictMock<mock::OutputLayer>();
567
Lloyd Pique01c77c12019-04-17 12:48:32 -0700568 mOutput->injectOutputLayerForTest(std::unique_ptr<OutputLayer>(outputLayer1));
569 mOutput->injectOutputLayerForTest(nullptr);
570 mOutput->injectOutputLayerForTest(std::unique_ptr<OutputLayer>(outputLayer2));
Lloyd Piquecc01a452018-12-04 17:24:00 -0800571
572 StrictMock<mock::Layer> layer;
573 StrictMock<mock::Layer> otherLayer;
574
575 // If the input layer matches the first OutputLayer, it will be returned.
576 EXPECT_CALL(*outputLayer1, getLayer()).WillOnce(ReturnRef(layer));
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700577 EXPECT_EQ(outputLayer1, mOutput->getOutputLayerForLayer(&layer));
Lloyd Piquecc01a452018-12-04 17:24:00 -0800578
579 // If the input layer matches the second OutputLayer, it will be returned.
580 EXPECT_CALL(*outputLayer1, getLayer()).WillOnce(ReturnRef(otherLayer));
581 EXPECT_CALL(*outputLayer2, getLayer()).WillOnce(ReturnRef(layer));
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700582 EXPECT_EQ(outputLayer2, mOutput->getOutputLayerForLayer(&layer));
Lloyd Piquecc01a452018-12-04 17:24:00 -0800583
584 // If the input layer does not match an output layer, null will be returned.
585 EXPECT_CALL(*outputLayer1, getLayer()).WillOnce(ReturnRef(otherLayer));
586 EXPECT_CALL(*outputLayer2, getLayer()).WillOnce(ReturnRef(otherLayer));
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700587 EXPECT_EQ(nullptr, mOutput->getOutputLayerForLayer(&layer));
Lloyd Piquecc01a452018-12-04 17:24:00 -0800588}
589
Lloyd Pique66d68602019-02-13 14:23:31 -0800590/*
Lloyd Piquec9e60032019-11-14 11:47:26 -0800591 * Output::setReleasedLayers()
592 */
593
594using OutputSetReleasedLayersTest = OutputTest;
595
596TEST_F(OutputSetReleasedLayersTest, setReleasedLayersTakesGivenLayers) {
597 sp<StrictMock<mock::LayerFE>> layer1FE{new StrictMock<mock::LayerFE>()};
598 sp<StrictMock<mock::LayerFE>> layer2FE{new StrictMock<mock::LayerFE>()};
599 sp<StrictMock<mock::LayerFE>> layer3FE{new StrictMock<mock::LayerFE>()};
600
601 Output::ReleasedLayers layers;
602 layers.push_back(layer1FE);
603 layers.push_back(layer2FE);
604 layers.push_back(layer3FE);
605
606 mOutput->setReleasedLayers(std::move(layers));
607
608 const auto& setLayers = mOutput->getReleasedLayersForTest();
609 ASSERT_EQ(3u, setLayers.size());
610 ASSERT_EQ(layer1FE.get(), setLayers[0].promote().get());
611 ASSERT_EQ(layer2FE.get(), setLayers[1].promote().get());
612 ASSERT_EQ(layer3FE.get(), setLayers[2].promote().get());
613}
614
615/*
Lloyd Piquec0ee6ba2019-11-14 12:55:53 -0800616 * Output::updateLayerStateFromFE()
617 */
618
619using OutputUpdateLayerStateFromFETest = OutputLatchFEStateTest;
620
621TEST_F(OutputUpdateLayerStateFromFETest, handlesNoOutputLayerCase) {
622 CompositionRefreshArgs refreshArgs;
623
624 mOutput->updateLayerStateFromFE(refreshArgs);
625}
626
627TEST_F(OutputUpdateLayerStateFromFETest, latchesContentStateForAllContainedLayers) {
628 EXPECT_CALL(mLayer1FE,
629 latchCompositionState(Ref(mLayer1FEState), LayerFE::StateSubset::Content));
630 EXPECT_CALL(mLayer2FE,
631 latchCompositionState(Ref(mLayer2FEState), LayerFE::StateSubset::Content));
632 EXPECT_CALL(mLayer3FE,
633 latchCompositionState(Ref(mLayer3FEState), LayerFE::StateSubset::Content));
634
635 // Note: Must be performed after any expectations on these mocks
636 injectLayer(std::move(mOutputLayer1));
637 injectLayer(std::move(mOutputLayer2));
638 injectLayer(std::move(mOutputLayer3));
639
640 CompositionRefreshArgs refreshArgs;
641 refreshArgs.updatingGeometryThisFrame = false;
642
643 mOutput->updateLayerStateFromFE(refreshArgs);
644}
645
646TEST_F(OutputUpdateLayerStateFromFETest, latchesGeometryAndContentStateForAllContainedLayers) {
647 EXPECT_CALL(mLayer1FE,
648 latchCompositionState(Ref(mLayer1FEState),
649 LayerFE::StateSubset::GeometryAndContent));
650 EXPECT_CALL(mLayer2FE,
651 latchCompositionState(Ref(mLayer2FEState),
652 LayerFE::StateSubset::GeometryAndContent));
653 EXPECT_CALL(mLayer3FE,
654 latchCompositionState(Ref(mLayer3FEState),
655 LayerFE::StateSubset::GeometryAndContent));
656
657 // Note: Must be performed after any expectations on these mocks
658 injectLayer(std::move(mOutputLayer1));
659 injectLayer(std::move(mOutputLayer2));
660 injectLayer(std::move(mOutputLayer3));
661
662 CompositionRefreshArgs refreshArgs;
663 refreshArgs.updatingGeometryThisFrame = true;
664
665 mOutput->updateLayerStateFromFE(refreshArgs);
666}
667
668/*
Alec Mourif9a2a2c2019-11-12 12:46:02 -0800669 * Output::updateAndWriteCompositionState()
670 */
671
Lloyd Piqueef63b612019-11-14 13:19:56 -0800672using OutputUpdateAndWriteCompositionStateTest = OutputLatchFEStateTest;
673
674TEST_F(OutputUpdateAndWriteCompositionStateTest, doesNothingIfLayers) {
675 mOutput->editState().isEnabled = true;
Alec Mourif9a2a2c2019-11-12 12:46:02 -0800676
677 CompositionRefreshArgs args;
678 mOutput->updateAndWriteCompositionState(args);
679}
680
Lloyd Piqueef63b612019-11-14 13:19:56 -0800681TEST_F(OutputUpdateAndWriteCompositionStateTest, doesNothingIfOutputNotEnabled) {
682 mOutput->editState().isEnabled = false;
Alec Mourif9a2a2c2019-11-12 12:46:02 -0800683
Lloyd Piqueef63b612019-11-14 13:19:56 -0800684 injectLayer(std::move(mOutputLayer1));
685 injectLayer(std::move(mOutputLayer2));
686 injectLayer(std::move(mOutputLayer3));
687
688 CompositionRefreshArgs args;
689 mOutput->updateAndWriteCompositionState(args);
690}
691
692TEST_F(OutputUpdateAndWriteCompositionStateTest, updatesLayerContentForAllLayers) {
693 EXPECT_CALL(*mOutputLayer1, updateCompositionState(false, false));
694 EXPECT_CALL(*mOutputLayer1, writeStateToHWC(false));
695 EXPECT_CALL(*mOutputLayer2, updateCompositionState(false, false));
696 EXPECT_CALL(*mOutputLayer2, writeStateToHWC(false));
697 EXPECT_CALL(*mOutputLayer3, updateCompositionState(false, false));
698 EXPECT_CALL(*mOutputLayer3, writeStateToHWC(false));
699
700 injectLayer(std::move(mOutputLayer1));
701 injectLayer(std::move(mOutputLayer2));
702 injectLayer(std::move(mOutputLayer3));
703
704 mOutput->editState().isEnabled = true;
705
706 CompositionRefreshArgs args;
707 args.updatingGeometryThisFrame = false;
708 args.devOptForceClientComposition = false;
709 mOutput->updateAndWriteCompositionState(args);
710}
711
712TEST_F(OutputUpdateAndWriteCompositionStateTest, updatesLayerGeometryAndContentForAllLayers) {
713 EXPECT_CALL(*mOutputLayer1, updateCompositionState(true, false));
714 EXPECT_CALL(*mOutputLayer1, writeStateToHWC(true));
715 EXPECT_CALL(*mOutputLayer2, updateCompositionState(true, false));
716 EXPECT_CALL(*mOutputLayer2, writeStateToHWC(true));
717 EXPECT_CALL(*mOutputLayer3, updateCompositionState(true, false));
718 EXPECT_CALL(*mOutputLayer3, writeStateToHWC(true));
719
720 injectLayer(std::move(mOutputLayer1));
721 injectLayer(std::move(mOutputLayer2));
722 injectLayer(std::move(mOutputLayer3));
723
724 mOutput->editState().isEnabled = true;
Alec Mourif9a2a2c2019-11-12 12:46:02 -0800725
726 CompositionRefreshArgs args;
727 args.updatingGeometryThisFrame = true;
Lloyd Piqueef63b612019-11-14 13:19:56 -0800728 args.devOptForceClientComposition = false;
729 mOutput->updateAndWriteCompositionState(args);
730}
731
732TEST_F(OutputUpdateAndWriteCompositionStateTest, forcesClientCompositionForAllLayers) {
733 EXPECT_CALL(*mOutputLayer1, updateCompositionState(false, true));
734 EXPECT_CALL(*mOutputLayer1, writeStateToHWC(false));
735 EXPECT_CALL(*mOutputLayer2, updateCompositionState(false, true));
736 EXPECT_CALL(*mOutputLayer2, writeStateToHWC(false));
737 EXPECT_CALL(*mOutputLayer3, updateCompositionState(false, true));
738 EXPECT_CALL(*mOutputLayer3, writeStateToHWC(false));
739
740 injectLayer(std::move(mOutputLayer1));
741 injectLayer(std::move(mOutputLayer2));
742 injectLayer(std::move(mOutputLayer3));
743
744 mOutput->editState().isEnabled = true;
745
746 CompositionRefreshArgs args;
747 args.updatingGeometryThisFrame = false;
Alec Mourif9a2a2c2019-11-12 12:46:02 -0800748 args.devOptForceClientComposition = true;
749 mOutput->updateAndWriteCompositionState(args);
750}
751
752/*
Lloyd Pique66d68602019-02-13 14:23:31 -0800753 * Output::prepareFrame()
754 */
755
756struct OutputPrepareFrameTest : public testing::Test {
Lloyd Piquefaa3f192019-11-14 14:05:09 -0800757 struct OutputPartialMock : public OutputPartialMockBase {
Lloyd Pique739afaf2019-11-21 16:40:05 -0800758 // Sets up the helper functions called by the function under test to use
759 // mock implementations.
Lloyd Pique66d68602019-02-13 14:23:31 -0800760 MOCK_METHOD0(chooseCompositionStrategy, void());
761 };
762
763 OutputPrepareFrameTest() {
764 mOutput.setDisplayColorProfileForTest(
765 std::unique_ptr<DisplayColorProfile>(mDisplayColorProfile));
766 mOutput.setRenderSurfaceForTest(std::unique_ptr<RenderSurface>(mRenderSurface));
767 }
768
769 StrictMock<mock::CompositionEngine> mCompositionEngine;
770 mock::DisplayColorProfile* mDisplayColorProfile = new StrictMock<mock::DisplayColorProfile>();
771 mock::RenderSurface* mRenderSurface = new StrictMock<mock::RenderSurface>();
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700772 StrictMock<OutputPartialMock> mOutput;
Lloyd Pique66d68602019-02-13 14:23:31 -0800773};
774
775TEST_F(OutputPrepareFrameTest, takesEarlyOutIfNotEnabled) {
776 mOutput.editState().isEnabled = false;
777
778 mOutput.prepareFrame();
779}
780
781TEST_F(OutputPrepareFrameTest, delegatesToChooseCompositionStrategyAndRenderSurface) {
782 mOutput.editState().isEnabled = true;
783 mOutput.editState().usesClientComposition = false;
784 mOutput.editState().usesDeviceComposition = true;
785
786 EXPECT_CALL(mOutput, chooseCompositionStrategy()).Times(1);
787 EXPECT_CALL(*mRenderSurface, prepareFrame(false, true));
788
789 mOutput.prepareFrame();
790}
791
792// Note: Use OutputTest and not OutputPrepareFrameTest, so the real
793// base chooseCompositionStrategy() is invoked.
794TEST_F(OutputTest, prepareFrameSetsClientCompositionOnlyByDefault) {
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700795 mOutput->editState().isEnabled = true;
796 mOutput->editState().usesClientComposition = false;
797 mOutput->editState().usesDeviceComposition = true;
Lloyd Pique66d68602019-02-13 14:23:31 -0800798
799 EXPECT_CALL(*mRenderSurface, prepareFrame(true, false));
800
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700801 mOutput->prepareFrame();
Lloyd Pique66d68602019-02-13 14:23:31 -0800802
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700803 EXPECT_TRUE(mOutput->getState().usesClientComposition);
804 EXPECT_FALSE(mOutput->getState().usesDeviceComposition);
Lloyd Pique66d68602019-02-13 14:23:31 -0800805}
806
Lloyd Pique56eba802019-08-28 15:45:25 -0700807/*
Lloyd Piqueb62cebc2019-11-20 18:31:52 -0800808 * Output::prepare()
809 */
810
811struct OutputPrepareTest : public testing::Test {
812 struct OutputPartialMock : public OutputPartialMockBase {
813 // Sets up the helper functions called by the function under test to use
814 // mock implementations.
815 MOCK_METHOD2(rebuildLayerStacks,
816 void(const compositionengine::CompositionRefreshArgs&,
817 compositionengine::LayerFESet&));
818 };
819
820 StrictMock<OutputPartialMock> mOutput;
821 CompositionRefreshArgs mRefreshArgs;
Lloyd Piquefe0ee9e2019-11-22 16:30:30 -0800822 LayerFESet mGeomSnapshots;
Lloyd Piqueb62cebc2019-11-20 18:31:52 -0800823};
824
825TEST_F(OutputPrepareTest, justInvokesRebuildLayerStacks) {
826 InSequence seq;
827 EXPECT_CALL(mOutput, rebuildLayerStacks(Ref(mRefreshArgs), Ref(mGeomSnapshots)));
828
829 mOutput.prepare(mRefreshArgs, mGeomSnapshots);
830}
831
832/*
833 * Output::rebuildLayerStacks()
834 */
835
836struct OutputRebuildLayerStacksTest : public testing::Test {
837 struct OutputPartialMock : public OutputPartialMockBase {
838 // Sets up the helper functions called by the function under test to use
839 // mock implementations.
840 MOCK_METHOD2(collectVisibleLayers,
841 void(const compositionengine::CompositionRefreshArgs&,
842 compositionengine::Output::CoverageState&));
843 };
844
845 OutputRebuildLayerStacksTest() {
846 mOutput.mState.isEnabled = true;
847 mOutput.mState.transform = kIdentityTransform;
848 mOutput.mState.bounds = kOutputBounds;
849
850 mRefreshArgs.updatingOutputGeometryThisFrame = true;
851
852 mCoverageAboveCoveredLayersToSet = Region(Rect(0, 0, 10, 10));
853
854 EXPECT_CALL(mOutput, collectVisibleLayers(Ref(mRefreshArgs), _))
855 .WillRepeatedly(Invoke(this, &OutputRebuildLayerStacksTest::setTestCoverageValues));
856 }
857
858 void setTestCoverageValues(const CompositionRefreshArgs&,
859 compositionengine::Output::CoverageState& state) {
860 state.aboveCoveredLayers = mCoverageAboveCoveredLayersToSet;
861 state.aboveOpaqueLayers = mCoverageAboveOpaqueLayersToSet;
862 state.dirtyRegion = mCoverageDirtyRegionToSet;
863 }
864
865 static const ui::Transform kIdentityTransform;
866 static const ui::Transform kRotate90Transform;
867 static const Rect kOutputBounds;
868
869 StrictMock<OutputPartialMock> mOutput;
870 CompositionRefreshArgs mRefreshArgs;
Lloyd Piquefe0ee9e2019-11-22 16:30:30 -0800871 LayerFESet mGeomSnapshots;
Lloyd Piqueb62cebc2019-11-20 18:31:52 -0800872 Region mCoverageAboveCoveredLayersToSet;
873 Region mCoverageAboveOpaqueLayersToSet;
874 Region mCoverageDirtyRegionToSet;
875};
876
877const ui::Transform OutputRebuildLayerStacksTest::kIdentityTransform{TR_IDENT, 1920, 1080};
878const ui::Transform OutputRebuildLayerStacksTest::kRotate90Transform{TR_ROT_90, 1920, 1080};
879const Rect OutputRebuildLayerStacksTest::kOutputBounds{0, 0, 1920, 1080};
880
881TEST_F(OutputRebuildLayerStacksTest, doesNothingIfNotEnabled) {
882 mOutput.mState.isEnabled = false;
883
884 mOutput.rebuildLayerStacks(mRefreshArgs, mGeomSnapshots);
885}
886
887TEST_F(OutputRebuildLayerStacksTest, doesNothingIfNotUpdatingGeometryThisFrame) {
888 mRefreshArgs.updatingOutputGeometryThisFrame = false;
889
890 mOutput.rebuildLayerStacks(mRefreshArgs, mGeomSnapshots);
891}
892
893TEST_F(OutputRebuildLayerStacksTest, computesUndefinedRegionWithNoRotationAndFullCoverage) {
894 mOutput.mState.transform = kIdentityTransform;
895
896 mCoverageAboveOpaqueLayersToSet = Region(Rect(0, 0, 1920, 1080));
897
898 mOutput.rebuildLayerStacks(mRefreshArgs, mGeomSnapshots);
899
900 EXPECT_THAT(mOutput.mState.undefinedRegion, RegionEq(Region(Rect(0, 0, 0, 0))));
901}
902
903TEST_F(OutputRebuildLayerStacksTest, computesUndefinedRegionWithNoRotationAndPartialCoverage) {
904 mOutput.mState.transform = kIdentityTransform;
905
906 mCoverageAboveOpaqueLayersToSet = Region(Rect(0, 0, 960, 1080));
907
908 mOutput.rebuildLayerStacks(mRefreshArgs, mGeomSnapshots);
909
910 EXPECT_THAT(mOutput.mState.undefinedRegion, RegionEq(Region(Rect(960, 0, 1920, 1080))));
911}
912
913TEST_F(OutputRebuildLayerStacksTest, computesUndefinedRegionWith90RotationAndFullCoverage) {
914 mOutput.mState.transform = kRotate90Transform;
915
916 mCoverageAboveOpaqueLayersToSet = Region(Rect(0, 0, 1080, 1920));
917
918 mOutput.rebuildLayerStacks(mRefreshArgs, mGeomSnapshots);
919
920 EXPECT_THAT(mOutput.mState.undefinedRegion, RegionEq(Region(Rect(0, 0, 0, 0))));
921}
922
923TEST_F(OutputRebuildLayerStacksTest, computesUndefinedRegionWith90RotationAndPartialCoverage) {
924 mOutput.mState.transform = kRotate90Transform;
925
926 mCoverageAboveOpaqueLayersToSet = Region(Rect(0, 0, 1080, 960));
927
928 mOutput.rebuildLayerStacks(mRefreshArgs, mGeomSnapshots);
929
930 EXPECT_THAT(mOutput.mState.undefinedRegion, RegionEq(Region(Rect(0, 0, 960, 1080))));
931}
932
933TEST_F(OutputRebuildLayerStacksTest, addsToDirtyRegionWithNoRotation) {
934 mOutput.mState.transform = kIdentityTransform;
935 mOutput.mState.dirtyRegion = Region(Rect(960, 0, 1920, 1080));
936
937 mCoverageDirtyRegionToSet = Region(Rect(0, 0, 960, 1080));
938
939 mOutput.rebuildLayerStacks(mRefreshArgs, mGeomSnapshots);
940
941 EXPECT_THAT(mOutput.mState.dirtyRegion, RegionEq(Region(Rect(0, 0, 1920, 1080))));
942}
943
944TEST_F(OutputRebuildLayerStacksTest, addsToDirtyRegionWith90Rotation) {
945 mOutput.mState.transform = kRotate90Transform;
946 mOutput.mState.dirtyRegion = Region(Rect(0, 960, 1080, 1920));
947
948 mCoverageDirtyRegionToSet = Region(Rect(0, 0, 1080, 960));
949
950 mOutput.rebuildLayerStacks(mRefreshArgs, mGeomSnapshots);
951
952 EXPECT_THAT(mOutput.mState.dirtyRegion, RegionEq(Region(Rect(0, 0, 1080, 1920))));
953}
954
955/*
956 * Output::collectVisibleLayers()
957 */
958
Lloyd Pique1ef93222019-11-21 16:41:53 -0800959struct OutputCollectVisibleLayersTest : public testing::Test {
960 struct OutputPartialMock : public OutputPartialMockBase {
961 // Sets up the helper functions called by the function under test to use
962 // mock implementations.
963 MOCK_METHOD2(ensureOutputLayerIfVisible,
964 void(std::shared_ptr<compositionengine::Layer>,
965 compositionengine::Output::CoverageState&));
966 MOCK_METHOD1(setReleasedLayers, void(const compositionengine::CompositionRefreshArgs&));
967 MOCK_METHOD0(finalizePendingOutputLayers, void());
968 };
969
970 struct Layer {
971 Layer() {
972 EXPECT_CALL(outputLayer, getState()).WillRepeatedly(ReturnRef(outputLayerState));
973 EXPECT_CALL(outputLayer, editState()).WillRepeatedly(ReturnRef(outputLayerState));
974 }
975
976 StrictMock<mock::OutputLayer> outputLayer;
977 std::shared_ptr<StrictMock<mock::Layer>> layer{new StrictMock<mock::Layer>()};
978 impl::OutputLayerCompositionState outputLayerState;
979 };
980
981 OutputCollectVisibleLayersTest() {
982 EXPECT_CALL(mOutput, getOutputLayerCount()).WillRepeatedly(Return(3));
983 EXPECT_CALL(mOutput, getOutputLayerOrderedByZByIndex(0))
984 .WillRepeatedly(Return(&mLayer1.outputLayer));
985 EXPECT_CALL(mOutput, getOutputLayerOrderedByZByIndex(1))
986 .WillRepeatedly(Return(&mLayer2.outputLayer));
987 EXPECT_CALL(mOutput, getOutputLayerOrderedByZByIndex(2))
988 .WillRepeatedly(Return(&mLayer3.outputLayer));
989
990 mRefreshArgs.layers.push_back(mLayer1.layer);
991 mRefreshArgs.layers.push_back(mLayer2.layer);
992 mRefreshArgs.layers.push_back(mLayer3.layer);
993 }
994
995 StrictMock<OutputPartialMock> mOutput;
996 CompositionRefreshArgs mRefreshArgs;
Lloyd Piquefe0ee9e2019-11-22 16:30:30 -0800997 LayerFESet mGeomSnapshots;
998 Output::CoverageState mCoverageState{mGeomSnapshots};
Lloyd Pique1ef93222019-11-21 16:41:53 -0800999 Layer mLayer1;
1000 Layer mLayer2;
1001 Layer mLayer3;
1002};
1003
1004TEST_F(OutputCollectVisibleLayersTest, doesMinimalWorkIfNoLayers) {
1005 mRefreshArgs.layers.clear();
1006 EXPECT_CALL(mOutput, getOutputLayerCount()).WillRepeatedly(Return(0));
1007
1008 EXPECT_CALL(mOutput, setReleasedLayers(Ref(mRefreshArgs)));
1009 EXPECT_CALL(mOutput, finalizePendingOutputLayers());
1010
1011 mOutput.collectVisibleLayers(mRefreshArgs, mCoverageState);
1012}
1013
1014TEST_F(OutputCollectVisibleLayersTest, processesCandidateLayersReversedAndSetsOutputLayerZ) {
1015 // Enforce a call order sequence for this test.
1016 InSequence seq;
1017
1018 // Layer coverage is evaluated from front to back!
1019 EXPECT_CALL(mOutput, ensureOutputLayerIfVisible(Eq(mLayer3.layer), Ref(mCoverageState)));
1020 EXPECT_CALL(mOutput, ensureOutputLayerIfVisible(Eq(mLayer2.layer), Ref(mCoverageState)));
1021 EXPECT_CALL(mOutput, ensureOutputLayerIfVisible(Eq(mLayer1.layer), Ref(mCoverageState)));
1022
1023 EXPECT_CALL(mOutput, setReleasedLayers(Ref(mRefreshArgs)));
1024 EXPECT_CALL(mOutput, finalizePendingOutputLayers());
1025
1026 mOutput.collectVisibleLayers(mRefreshArgs, mCoverageState);
1027
1028 // Ensure all output layers have been assigned a simple/flattened z-order.
1029 EXPECT_EQ(0u, mLayer1.outputLayerState.z);
1030 EXPECT_EQ(1u, mLayer2.outputLayerState.z);
1031 EXPECT_EQ(2u, mLayer3.outputLayerState.z);
1032}
Lloyd Piqueb62cebc2019-11-20 18:31:52 -08001033
1034/*
1035 * Output::ensureOutputLayerIfVisible()
1036 */
1037
Lloyd Piquefe0ee9e2019-11-22 16:30:30 -08001038struct OutputEnsureOutputLayerIfVisibleTest : public testing::Test {
1039 struct OutputPartialMock : public OutputPartialMockBase {
1040 // Sets up the helper functions called by the function under test to use
1041 // mock implementations.
1042 MOCK_CONST_METHOD1(belongsInOutput, bool(const compositionengine::Layer*));
1043 MOCK_CONST_METHOD1(getOutputLayerOrderedByZByIndex, OutputLayer*(size_t));
1044 MOCK_METHOD3(ensureOutputLayer,
1045 compositionengine::OutputLayer*(
1046 std::optional<size_t>,
1047 const std::shared_ptr<compositionengine::Layer>&, const sp<LayerFE>&));
1048 };
1049
1050 OutputEnsureOutputLayerIfVisibleTest() {
1051 EXPECT_CALL(*mLayer, getLayerFE()).WillRepeatedly(Return(mLayerFE));
1052 EXPECT_CALL(*mLayer, getFEState()).WillRepeatedly(ReturnRef(mLayerFEState));
1053 EXPECT_CALL(*mLayer, editFEState()).WillRepeatedly(ReturnRef(mLayerFEState));
1054
1055 EXPECT_CALL(mOutput, belongsInOutput(mLayer.get())).WillRepeatedly(Return(true));
1056 EXPECT_CALL(mOutput, getOutputLayerCount()).WillRepeatedly(Return(1));
1057 EXPECT_CALL(mOutput, getOutputLayerOrderedByZByIndex(0u))
1058 .WillRepeatedly(Return(&mOutputLayer));
1059
1060 EXPECT_CALL(mOutputLayer, getState()).WillRepeatedly(ReturnRef(mOutputLayerState));
1061 EXPECT_CALL(mOutputLayer, editState()).WillRepeatedly(ReturnRef(mOutputLayerState));
1062 EXPECT_CALL(mOutputLayer, getLayer()).WillRepeatedly(ReturnRef(*mLayer.get()));
1063
1064 mOutput.mState.bounds = Rect(0, 0, 200, 300);
1065 mOutput.mState.viewport = Rect(0, 0, 200, 300);
1066 mOutput.mState.transform = ui::Transform(TR_IDENT, 200, 300);
1067
1068 mLayerFEState.isVisible = true;
1069 mLayerFEState.isOpaque = true;
1070 mLayerFEState.contentDirty = true;
1071 mLayerFEState.geomLayerBounds = FloatRect{0, 0, 100, 200};
1072 mLayerFEState.geomLayerTransform = ui::Transform(TR_IDENT, 100, 200);
1073 mLayerFEState.transparentRegionHint = Region(Rect(0, 0, 100, 100));
1074
1075 mOutputLayerState.visibleRegion = Region(Rect(0, 0, 50, 200));
1076 mOutputLayerState.coveredRegion = Region(Rect(50, 0, 100, 200));
1077
1078 mGeomSnapshots.insert(mLayerFE);
1079 }
1080
1081 static const Region kEmptyRegion;
1082 static const Region kFullBoundsNoRotation;
1083 static const Region kRightHalfBoundsNoRotation;
1084 static const Region kLowerHalfBoundsNoRotation;
1085 static const Region kFullBounds90Rotation;
1086
1087 StrictMock<OutputPartialMock> mOutput;
1088 LayerFESet mGeomSnapshots;
1089 Output::CoverageState mCoverageState{mGeomSnapshots};
1090
1091 std::shared_ptr<mock::Layer> mLayer{new StrictMock<mock::Layer>()};
1092 sp<StrictMock<mock::LayerFE>> mLayerFE{new StrictMock<mock::LayerFE>()};
1093 LayerFECompositionState mLayerFEState;
1094 mock::OutputLayer mOutputLayer;
1095 impl::OutputLayerCompositionState mOutputLayerState;
1096};
1097
1098const Region OutputEnsureOutputLayerIfVisibleTest::kEmptyRegion = Region(Rect(0, 0, 0, 0));
1099const Region OutputEnsureOutputLayerIfVisibleTest::kFullBoundsNoRotation =
1100 Region(Rect(0, 0, 100, 200));
1101const Region OutputEnsureOutputLayerIfVisibleTest::kRightHalfBoundsNoRotation =
1102 Region(Rect(0, 100, 100, 200));
1103const Region OutputEnsureOutputLayerIfVisibleTest::kLowerHalfBoundsNoRotation =
1104 Region(Rect(50, 0, 100, 200));
1105const Region OutputEnsureOutputLayerIfVisibleTest::kFullBounds90Rotation =
1106 Region(Rect(0, 0, 200, 100));
1107
1108TEST_F(OutputEnsureOutputLayerIfVisibleTest, doesNothingIfNoLayerFE) {
1109 EXPECT_CALL(*mLayer, getLayerFE).WillOnce(Return(sp<LayerFE>()));
1110
1111 mOutput.ensureOutputLayerIfVisible(mLayer, mCoverageState);
1112}
1113
1114TEST_F(OutputEnsureOutputLayerIfVisibleTest, performsGeomLatchBeforeCheckingIfLayerBelongs) {
1115 EXPECT_CALL(mOutput, belongsInOutput(mLayer.get())).WillOnce(Return(false));
1116 EXPECT_CALL(*mLayerFE.get(),
1117 latchCompositionState(Ref(mLayerFEState),
1118 compositionengine::LayerFE::StateSubset::BasicGeometry));
1119
1120 mGeomSnapshots.clear();
1121
1122 mOutput.ensureOutputLayerIfVisible(mLayer, mCoverageState);
1123}
1124
1125TEST_F(OutputEnsureOutputLayerIfVisibleTest,
1126 skipsLatchIfAlreadyLatchedBeforeCheckingIfLayerBelongs) {
1127 EXPECT_CALL(mOutput, belongsInOutput(mLayer.get())).WillOnce(Return(false));
1128
1129 mOutput.ensureOutputLayerIfVisible(mLayer, mCoverageState);
1130}
1131
1132TEST_F(OutputEnsureOutputLayerIfVisibleTest, takesEarlyOutIfLayerNotVisible) {
1133 mLayerFEState.isVisible = false;
1134
1135 mOutput.ensureOutputLayerIfVisible(mLayer, mCoverageState);
1136}
1137
1138TEST_F(OutputEnsureOutputLayerIfVisibleTest, takesEarlyOutIfLayerHasEmptyVisibleRegion) {
1139 mLayerFEState.geomLayerBounds = FloatRect{0, 0, 0, 0};
1140
1141 mOutput.ensureOutputLayerIfVisible(mLayer, mCoverageState);
1142}
1143
1144TEST_F(OutputEnsureOutputLayerIfVisibleTest, takesNotSoEarlyOutifDrawRegionEmpty) {
1145 mOutput.mState.bounds = Rect(0, 0, 0, 0);
1146
1147 mOutput.ensureOutputLayerIfVisible(mLayer, mCoverageState);
1148}
1149
1150TEST_F(OutputEnsureOutputLayerIfVisibleTest,
1151 handlesCreatingOutputLayerForOpaqueDirtyNotRotatedLayer) {
1152 mLayerFEState.isOpaque = true;
1153 mLayerFEState.contentDirty = true;
1154 mLayerFEState.geomLayerTransform = ui::Transform(TR_IDENT, 100, 200);
1155
1156 EXPECT_CALL(mOutput, getOutputLayerCount()).WillOnce(Return(0u));
1157 EXPECT_CALL(mOutput, ensureOutputLayer(Eq(std::nullopt), Eq(mLayer), Eq(mLayerFE)))
1158 .WillOnce(Return(&mOutputLayer));
1159
1160 mOutput.ensureOutputLayerIfVisible(mLayer, mCoverageState);
1161
1162 EXPECT_THAT(mCoverageState.dirtyRegion, RegionEq(kFullBoundsNoRotation));
1163 EXPECT_THAT(mCoverageState.aboveCoveredLayers, RegionEq(kFullBoundsNoRotation));
1164 EXPECT_THAT(mCoverageState.aboveOpaqueLayers, RegionEq(kFullBoundsNoRotation));
1165
1166 EXPECT_THAT(mOutputLayerState.visibleRegion, RegionEq(kFullBoundsNoRotation));
1167 EXPECT_THAT(mOutputLayerState.visibleNonTransparentRegion, RegionEq(kFullBoundsNoRotation));
1168 EXPECT_THAT(mOutputLayerState.coveredRegion, RegionEq(kEmptyRegion));
1169 EXPECT_THAT(mOutputLayerState.outputSpaceVisibleRegion, RegionEq(kFullBoundsNoRotation));
1170}
1171
1172TEST_F(OutputEnsureOutputLayerIfVisibleTest,
1173 handlesUpdatingOutputLayerForOpaqueDirtyNotRotatedLayer) {
1174 mLayerFEState.isOpaque = true;
1175 mLayerFEState.contentDirty = true;
1176 mLayerFEState.geomLayerTransform = ui::Transform(TR_IDENT, 100, 200);
1177
1178 EXPECT_CALL(mOutput, ensureOutputLayer(Eq(0u), Eq(mLayer), Eq(mLayerFE)))
1179 .WillOnce(Return(&mOutputLayer));
1180
1181 mOutput.ensureOutputLayerIfVisible(mLayer, mCoverageState);
1182
1183 EXPECT_THAT(mCoverageState.dirtyRegion, RegionEq(kFullBoundsNoRotation));
1184 EXPECT_THAT(mCoverageState.aboveCoveredLayers, RegionEq(kFullBoundsNoRotation));
1185 EXPECT_THAT(mCoverageState.aboveOpaqueLayers, RegionEq(kFullBoundsNoRotation));
1186
1187 EXPECT_THAT(mOutputLayerState.visibleRegion, RegionEq(kFullBoundsNoRotation));
1188 EXPECT_THAT(mOutputLayerState.visibleNonTransparentRegion, RegionEq(kFullBoundsNoRotation));
1189 EXPECT_THAT(mOutputLayerState.coveredRegion, RegionEq(kEmptyRegion));
1190 EXPECT_THAT(mOutputLayerState.outputSpaceVisibleRegion, RegionEq(kFullBoundsNoRotation));
1191}
1192
1193TEST_F(OutputEnsureOutputLayerIfVisibleTest,
1194 handlesCreatingOutputLayerForTransparentDirtyNotRotatedLayer) {
1195 mLayerFEState.isOpaque = false;
1196 mLayerFEState.contentDirty = true;
1197 mLayerFEState.geomLayerTransform = ui::Transform(TR_IDENT, 100, 200);
1198
1199 EXPECT_CALL(mOutput, getOutputLayerCount()).WillOnce(Return(0u));
1200 EXPECT_CALL(mOutput, ensureOutputLayer(Eq(std::nullopt), Eq(mLayer), Eq(mLayerFE)))
1201 .WillOnce(Return(&mOutputLayer));
1202
1203 mOutput.ensureOutputLayerIfVisible(mLayer, mCoverageState);
1204
1205 EXPECT_THAT(mCoverageState.dirtyRegion, RegionEq(kFullBoundsNoRotation));
1206 EXPECT_THAT(mCoverageState.aboveCoveredLayers, RegionEq(kFullBoundsNoRotation));
1207 EXPECT_THAT(mCoverageState.aboveOpaqueLayers, RegionEq(kEmptyRegion));
1208
1209 EXPECT_THAT(mOutputLayerState.visibleRegion, RegionEq(kFullBoundsNoRotation));
1210 EXPECT_THAT(mOutputLayerState.visibleNonTransparentRegion,
1211 RegionEq(kRightHalfBoundsNoRotation));
1212 EXPECT_THAT(mOutputLayerState.coveredRegion, RegionEq(kEmptyRegion));
1213 EXPECT_THAT(mOutputLayerState.outputSpaceVisibleRegion, RegionEq(kFullBoundsNoRotation));
1214}
1215
1216TEST_F(OutputEnsureOutputLayerIfVisibleTest,
1217 handlesUpdatingOutputLayerForTransparentDirtyNotRotatedLayer) {
1218 mLayerFEState.isOpaque = false;
1219 mLayerFEState.contentDirty = true;
1220 mLayerFEState.geomLayerTransform = ui::Transform(TR_IDENT, 100, 200);
1221
1222 EXPECT_CALL(mOutput, ensureOutputLayer(Eq(0u), Eq(mLayer), Eq(mLayerFE)))
1223 .WillOnce(Return(&mOutputLayer));
1224
1225 mOutput.ensureOutputLayerIfVisible(mLayer, mCoverageState);
1226
1227 EXPECT_THAT(mCoverageState.dirtyRegion, RegionEq(kFullBoundsNoRotation));
1228 EXPECT_THAT(mCoverageState.aboveCoveredLayers, RegionEq(kFullBoundsNoRotation));
1229 EXPECT_THAT(mCoverageState.aboveOpaqueLayers, RegionEq(kEmptyRegion));
1230
1231 EXPECT_THAT(mOutputLayerState.visibleRegion, RegionEq(kFullBoundsNoRotation));
1232 EXPECT_THAT(mOutputLayerState.visibleNonTransparentRegion,
1233 RegionEq(kRightHalfBoundsNoRotation));
1234 EXPECT_THAT(mOutputLayerState.coveredRegion, RegionEq(kEmptyRegion));
1235 EXPECT_THAT(mOutputLayerState.outputSpaceVisibleRegion, RegionEq(kFullBoundsNoRotation));
1236}
1237
1238TEST_F(OutputEnsureOutputLayerIfVisibleTest,
1239 handlesCreatingOutputLayerForOpaqueNonDirtyNotRotatedLayer) {
1240 mLayerFEState.isOpaque = true;
1241 mLayerFEState.contentDirty = false;
1242 mLayerFEState.geomLayerTransform = ui::Transform(TR_IDENT, 100, 200);
1243
1244 EXPECT_CALL(mOutput, getOutputLayerCount()).WillOnce(Return(0u));
1245 EXPECT_CALL(mOutput, ensureOutputLayer(Eq(std::nullopt), Eq(mLayer), Eq(mLayerFE)))
1246 .WillOnce(Return(&mOutputLayer));
1247
1248 mOutput.ensureOutputLayerIfVisible(mLayer, mCoverageState);
1249
1250 EXPECT_THAT(mCoverageState.dirtyRegion, RegionEq(kFullBoundsNoRotation));
1251 EXPECT_THAT(mCoverageState.aboveCoveredLayers, RegionEq(kFullBoundsNoRotation));
1252 EXPECT_THAT(mCoverageState.aboveOpaqueLayers, RegionEq(kFullBoundsNoRotation));
1253
1254 EXPECT_THAT(mOutputLayerState.visibleRegion, RegionEq(kFullBoundsNoRotation));
1255 EXPECT_THAT(mOutputLayerState.visibleNonTransparentRegion, RegionEq(kFullBoundsNoRotation));
1256 EXPECT_THAT(mOutputLayerState.coveredRegion, RegionEq(kEmptyRegion));
1257 EXPECT_THAT(mOutputLayerState.outputSpaceVisibleRegion, RegionEq(kFullBoundsNoRotation));
1258}
1259
1260TEST_F(OutputEnsureOutputLayerIfVisibleTest,
1261 handlesUpdatingOutputLayerForOpaqueNonDirtyNotRotatedLayer) {
1262 mLayerFEState.isOpaque = true;
1263 mLayerFEState.contentDirty = false;
1264 mLayerFEState.geomLayerTransform = ui::Transform(TR_IDENT, 100, 200);
1265
1266 EXPECT_CALL(mOutput, ensureOutputLayer(Eq(0u), Eq(mLayer), Eq(mLayerFE)))
1267 .WillOnce(Return(&mOutputLayer));
1268
1269 mOutput.ensureOutputLayerIfVisible(mLayer, mCoverageState);
1270
1271 EXPECT_THAT(mCoverageState.dirtyRegion, RegionEq(kLowerHalfBoundsNoRotation));
1272 EXPECT_THAT(mCoverageState.aboveCoveredLayers, RegionEq(kFullBoundsNoRotation));
1273 EXPECT_THAT(mCoverageState.aboveOpaqueLayers, RegionEq(kFullBoundsNoRotation));
1274
1275 EXPECT_THAT(mOutputLayerState.visibleRegion, RegionEq(kFullBoundsNoRotation));
1276 EXPECT_THAT(mOutputLayerState.visibleNonTransparentRegion, RegionEq(kFullBoundsNoRotation));
1277 EXPECT_THAT(mOutputLayerState.coveredRegion, RegionEq(kEmptyRegion));
1278 EXPECT_THAT(mOutputLayerState.outputSpaceVisibleRegion, RegionEq(kFullBoundsNoRotation));
1279}
1280
1281TEST_F(OutputEnsureOutputLayerIfVisibleTest,
1282 handlesCreatingOutputLayerForOpaqueDirtyRotated90Layer) {
1283 mLayerFEState.isOpaque = true;
1284 mLayerFEState.contentDirty = true;
1285 mLayerFEState.geomLayerBounds = FloatRect{0, 0, 200, 100};
1286 mLayerFEState.geomLayerTransform = ui::Transform(TR_ROT_90, 100, 200);
1287 mOutputLayerState.visibleRegion = Region(Rect(0, 0, 100, 100));
1288 mOutputLayerState.coveredRegion = Region(Rect(100, 0, 200, 100));
1289
1290 EXPECT_CALL(mOutput, getOutputLayerCount()).WillOnce(Return(0u));
1291 EXPECT_CALL(mOutput, ensureOutputLayer(Eq(std::nullopt), Eq(mLayer), Eq(mLayerFE)))
1292 .WillOnce(Return(&mOutputLayer));
1293
1294 mOutput.ensureOutputLayerIfVisible(mLayer, mCoverageState);
1295
1296 EXPECT_THAT(mCoverageState.dirtyRegion, RegionEq(kFullBoundsNoRotation));
1297 EXPECT_THAT(mCoverageState.aboveCoveredLayers, RegionEq(kFullBoundsNoRotation));
1298 EXPECT_THAT(mCoverageState.aboveOpaqueLayers, RegionEq(kFullBoundsNoRotation));
1299
1300 EXPECT_THAT(mOutputLayerState.visibleRegion, RegionEq(kFullBoundsNoRotation));
1301 EXPECT_THAT(mOutputLayerState.visibleNonTransparentRegion, RegionEq(kFullBoundsNoRotation));
1302 EXPECT_THAT(mOutputLayerState.coveredRegion, RegionEq(kEmptyRegion));
1303 EXPECT_THAT(mOutputLayerState.outputSpaceVisibleRegion, RegionEq(kFullBoundsNoRotation));
1304}
1305
1306TEST_F(OutputEnsureOutputLayerIfVisibleTest,
1307 handlesUpdatingOutputLayerForOpaqueDirtyRotated90Layer) {
1308 mLayerFEState.isOpaque = true;
1309 mLayerFEState.contentDirty = true;
1310 mLayerFEState.geomLayerBounds = FloatRect{0, 0, 200, 100};
1311 mLayerFEState.geomLayerTransform = ui::Transform(TR_ROT_90, 100, 200);
1312 mOutputLayerState.visibleRegion = Region(Rect(0, 0, 100, 100));
1313 mOutputLayerState.coveredRegion = Region(Rect(100, 0, 200, 100));
1314
1315 EXPECT_CALL(mOutput, ensureOutputLayer(Eq(0u), Eq(mLayer), Eq(mLayerFE)))
1316 .WillOnce(Return(&mOutputLayer));
1317
1318 mOutput.ensureOutputLayerIfVisible(mLayer, mCoverageState);
1319
1320 EXPECT_THAT(mCoverageState.dirtyRegion, RegionEq(kFullBoundsNoRotation));
1321 EXPECT_THAT(mCoverageState.aboveCoveredLayers, RegionEq(kFullBoundsNoRotation));
1322 EXPECT_THAT(mCoverageState.aboveOpaqueLayers, RegionEq(kFullBoundsNoRotation));
1323
1324 EXPECT_THAT(mOutputLayerState.visibleRegion, RegionEq(kFullBoundsNoRotation));
1325 EXPECT_THAT(mOutputLayerState.visibleNonTransparentRegion, RegionEq(kFullBoundsNoRotation));
1326 EXPECT_THAT(mOutputLayerState.coveredRegion, RegionEq(kEmptyRegion));
1327 EXPECT_THAT(mOutputLayerState.outputSpaceVisibleRegion, RegionEq(kFullBoundsNoRotation));
1328}
1329
1330TEST_F(OutputEnsureOutputLayerIfVisibleTest,
1331 handlesCreatingOutputLayerForOpaqueDirtyNotRotatedLayerRotatedOutput) {
1332 mLayerFEState.isOpaque = true;
1333 mLayerFEState.contentDirty = true;
1334 mLayerFEState.geomLayerTransform = ui::Transform(TR_IDENT, 100, 200);
1335
1336 mOutput.mState.viewport = Rect(0, 0, 300, 200);
1337 mOutput.mState.transform = ui::Transform(TR_ROT_90, 200, 300);
1338
1339 EXPECT_CALL(mOutput, getOutputLayerCount()).WillOnce(Return(0u));
1340 EXPECT_CALL(mOutput, ensureOutputLayer(Eq(std::nullopt), Eq(mLayer), Eq(mLayerFE)))
1341 .WillOnce(Return(&mOutputLayer));
1342
1343 mOutput.ensureOutputLayerIfVisible(mLayer, mCoverageState);
1344
1345 EXPECT_THAT(mCoverageState.dirtyRegion, RegionEq(kFullBoundsNoRotation));
1346 EXPECT_THAT(mCoverageState.aboveCoveredLayers, RegionEq(kFullBoundsNoRotation));
1347 EXPECT_THAT(mCoverageState.aboveOpaqueLayers, RegionEq(kFullBoundsNoRotation));
1348
1349 EXPECT_THAT(mOutputLayerState.visibleRegion, RegionEq(kFullBoundsNoRotation));
1350 EXPECT_THAT(mOutputLayerState.visibleNonTransparentRegion, RegionEq(kFullBoundsNoRotation));
1351 EXPECT_THAT(mOutputLayerState.coveredRegion, RegionEq(kEmptyRegion));
1352 EXPECT_THAT(mOutputLayerState.outputSpaceVisibleRegion, RegionEq(kFullBounds90Rotation));
1353}
1354
1355TEST_F(OutputEnsureOutputLayerIfVisibleTest,
1356 handlesUpdatingOutputLayerForOpaqueDirtyNotRotatedLayerRotatedOutput) {
1357 mLayerFEState.isOpaque = true;
1358 mLayerFEState.contentDirty = true;
1359 mLayerFEState.geomLayerTransform = ui::Transform(TR_IDENT, 100, 200);
1360
1361 mOutput.mState.viewport = Rect(0, 0, 300, 200);
1362 mOutput.mState.transform = ui::Transform(TR_ROT_90, 200, 300);
1363
1364 EXPECT_CALL(mOutput, ensureOutputLayer(Eq(0u), Eq(mLayer), Eq(mLayerFE)))
1365 .WillOnce(Return(&mOutputLayer));
1366
1367 mOutput.ensureOutputLayerIfVisible(mLayer, mCoverageState);
1368
1369 EXPECT_THAT(mCoverageState.dirtyRegion, RegionEq(kFullBoundsNoRotation));
1370 EXPECT_THAT(mCoverageState.aboveCoveredLayers, RegionEq(kFullBoundsNoRotation));
1371 EXPECT_THAT(mCoverageState.aboveOpaqueLayers, RegionEq(kFullBoundsNoRotation));
1372
1373 EXPECT_THAT(mOutputLayerState.visibleRegion, RegionEq(kFullBoundsNoRotation));
1374 EXPECT_THAT(mOutputLayerState.visibleNonTransparentRegion, RegionEq(kFullBoundsNoRotation));
1375 EXPECT_THAT(mOutputLayerState.coveredRegion, RegionEq(kEmptyRegion));
1376 EXPECT_THAT(mOutputLayerState.outputSpaceVisibleRegion, RegionEq(kFullBounds90Rotation));
1377}
1378
1379TEST_F(OutputEnsureOutputLayerIfVisibleTest,
1380 handlesCreatingOutputLayerForOpaqueDirtyArbitraryTransformLayer) {
1381 ui::Transform arbitraryTransform;
1382 arbitraryTransform.set(1, 1, -1, 1);
1383 arbitraryTransform.set(0, 100);
1384
1385 mLayerFEState.isOpaque = true;
1386 mLayerFEState.contentDirty = true;
1387 mLayerFEState.geomLayerBounds = FloatRect{0, 0, 100, 200};
1388 mLayerFEState.geomLayerTransform = arbitraryTransform;
1389
1390 EXPECT_CALL(mOutput, getOutputLayerCount()).WillOnce(Return(0u));
1391 EXPECT_CALL(mOutput, ensureOutputLayer(Eq(std::nullopt), Eq(mLayer), Eq(mLayerFE)))
1392 .WillOnce(Return(&mOutputLayer));
1393
1394 mOutput.ensureOutputLayerIfVisible(mLayer, mCoverageState);
1395
1396 const Region kRegion = Region(Rect(0, 0, 300, 300));
1397 const Region kRegionClipped = Region(Rect(0, 0, 200, 300));
1398
1399 EXPECT_THAT(mCoverageState.dirtyRegion, RegionEq(kRegion));
1400 EXPECT_THAT(mCoverageState.aboveCoveredLayers, RegionEq(kRegion));
1401 EXPECT_THAT(mCoverageState.aboveOpaqueLayers, RegionEq(kEmptyRegion));
1402
1403 EXPECT_THAT(mOutputLayerState.visibleRegion, RegionEq(kRegion));
1404 EXPECT_THAT(mOutputLayerState.visibleNonTransparentRegion, RegionEq(kRegion));
1405 EXPECT_THAT(mOutputLayerState.coveredRegion, RegionEq(kEmptyRegion));
1406 EXPECT_THAT(mOutputLayerState.outputSpaceVisibleRegion, RegionEq(kRegionClipped));
1407}
1408
1409TEST_F(OutputEnsureOutputLayerIfVisibleTest, coverageAccumulatesTest) {
1410 mLayerFEState.isOpaque = false;
1411 mLayerFEState.contentDirty = true;
1412 mLayerFEState.geomLayerTransform = ui::Transform(TR_IDENT, 100, 200);
1413
1414 mCoverageState.dirtyRegion = Region(Rect(0, 0, 500, 500));
1415 mCoverageState.aboveCoveredLayers = Region(Rect(50, 0, 150, 200));
1416 mCoverageState.aboveOpaqueLayers = Region(Rect(50, 0, 150, 200));
1417
1418 EXPECT_CALL(mOutput, ensureOutputLayer(Eq(0u), Eq(mLayer), Eq(mLayerFE)))
1419 .WillOnce(Return(&mOutputLayer));
1420
1421 mOutput.ensureOutputLayerIfVisible(mLayer, mCoverageState);
1422
1423 const Region kExpectedDirtyRegion = Region(Rect(0, 0, 500, 500));
1424 const Region kExpectedAboveCoveredRegion = Region(Rect(0, 0, 150, 200));
1425 const Region kExpectedAboveOpaqueRegion = Region(Rect(50, 0, 150, 200));
1426 const Region kExpectedLayerVisibleRegion = Region(Rect(0, 0, 50, 200));
1427 const Region kExpectedLayerCoveredRegion = Region(Rect(50, 0, 100, 200));
1428 const Region kExpectedLayerVisibleNonTransparentRegion = Region(Rect(0, 100, 50, 200));
1429
1430 EXPECT_THAT(mCoverageState.dirtyRegion, RegionEq(kExpectedDirtyRegion));
1431 EXPECT_THAT(mCoverageState.aboveCoveredLayers, RegionEq(kExpectedAboveCoveredRegion));
1432 EXPECT_THAT(mCoverageState.aboveOpaqueLayers, RegionEq(kExpectedAboveOpaqueRegion));
1433
1434 EXPECT_THAT(mOutputLayerState.visibleRegion, RegionEq(kExpectedLayerVisibleRegion));
1435 EXPECT_THAT(mOutputLayerState.visibleNonTransparentRegion,
1436 RegionEq(kExpectedLayerVisibleNonTransparentRegion));
1437 EXPECT_THAT(mOutputLayerState.coveredRegion, RegionEq(kExpectedLayerCoveredRegion));
1438 EXPECT_THAT(mOutputLayerState.outputSpaceVisibleRegion, RegionEq(kExpectedLayerVisibleRegion));
1439}
Lloyd Piqueb62cebc2019-11-20 18:31:52 -08001440
1441/*
Lloyd Piquefaa3f192019-11-14 14:05:09 -08001442 * Output::present()
1443 */
1444
1445struct OutputPresentTest : public testing::Test {
1446 struct OutputPartialMock : public OutputPartialMockBase {
Lloyd Pique739afaf2019-11-21 16:40:05 -08001447 // Sets up the helper functions called by the function under test to use
1448 // mock implementations.
Lloyd Piquefaa3f192019-11-14 14:05:09 -08001449 MOCK_METHOD1(updateColorProfile, void(const compositionengine::CompositionRefreshArgs&));
1450 MOCK_METHOD1(updateAndWriteCompositionState,
1451 void(const compositionengine::CompositionRefreshArgs&));
1452 MOCK_METHOD1(setColorTransform, void(const compositionengine::CompositionRefreshArgs&));
1453 MOCK_METHOD0(beginFrame, void());
1454 MOCK_METHOD0(prepareFrame, void());
1455 MOCK_METHOD1(devOptRepaintFlash, void(const compositionengine::CompositionRefreshArgs&));
1456 MOCK_METHOD1(finishFrame, void(const compositionengine::CompositionRefreshArgs&));
1457 MOCK_METHOD0(postFramebuffer, void());
1458 };
1459
1460 StrictMock<OutputPartialMock> mOutput;
1461};
1462
1463TEST_F(OutputPresentTest, justInvokesChildFunctionsInSequence) {
1464 CompositionRefreshArgs args;
1465
1466 InSequence seq;
1467 EXPECT_CALL(mOutput, updateColorProfile(Ref(args)));
1468 EXPECT_CALL(mOutput, updateAndWriteCompositionState(Ref(args)));
1469 EXPECT_CALL(mOutput, setColorTransform(Ref(args)));
1470 EXPECT_CALL(mOutput, beginFrame());
1471 EXPECT_CALL(mOutput, prepareFrame());
1472 EXPECT_CALL(mOutput, devOptRepaintFlash(Ref(args)));
1473 EXPECT_CALL(mOutput, finishFrame(Ref(args)));
1474 EXPECT_CALL(mOutput, postFramebuffer());
1475
1476 mOutput.present(args);
1477}
1478
1479/*
1480 * Output::updateColorProfile()
1481 */
1482
Lloyd Pique17ca7422019-11-14 14:24:10 -08001483struct OutputUpdateColorProfileTest : public testing::Test {
1484 using TestType = OutputUpdateColorProfileTest;
1485
1486 struct OutputPartialMock : public OutputPartialMockBase {
Lloyd Pique739afaf2019-11-21 16:40:05 -08001487 // Sets up the helper functions called by the function under test to use
1488 // mock implementations.
Lloyd Pique17ca7422019-11-14 14:24:10 -08001489 MOCK_METHOD1(setColorProfile, void(const ColorProfile&));
1490 };
1491
1492 struct Layer {
1493 Layer() {
1494 EXPECT_CALL(mOutputLayer, getLayer()).WillRepeatedly(ReturnRef(mLayer));
1495 EXPECT_CALL(mOutputLayer, getLayerFE()).WillRepeatedly(ReturnRef(mLayerFE));
1496 EXPECT_CALL(mLayer, getFEState()).WillRepeatedly(ReturnRef(mLayerFEState));
1497 }
1498
1499 StrictMock<mock::OutputLayer> mOutputLayer;
1500 StrictMock<mock::Layer> mLayer;
1501 StrictMock<mock::LayerFE> mLayerFE;
1502 LayerFECompositionState mLayerFEState;
1503 };
1504
1505 OutputUpdateColorProfileTest() {
1506 mOutput.setDisplayColorProfileForTest(
1507 std::unique_ptr<DisplayColorProfile>(mDisplayColorProfile));
1508 mOutput.setRenderSurfaceForTest(std::unique_ptr<RenderSurface>(mRenderSurface));
1509
1510 EXPECT_CALL(mOutput, getOutputLayerOrderedByZByIndex(0))
1511 .WillRepeatedly(Return(&mLayer1.mOutputLayer));
1512 EXPECT_CALL(mOutput, getOutputLayerOrderedByZByIndex(1))
1513 .WillRepeatedly(Return(&mLayer2.mOutputLayer));
1514 EXPECT_CALL(mOutput, getOutputLayerOrderedByZByIndex(2))
1515 .WillRepeatedly(Return(&mLayer3.mOutputLayer));
1516 }
1517
1518 struct ExecuteState : public CallOrderStateMachineHelper<TestType, ExecuteState> {
1519 void execute() { getInstance()->mOutput.updateColorProfile(getInstance()->mRefreshArgs); }
1520 };
1521
1522 mock::DisplayColorProfile* mDisplayColorProfile = new StrictMock<mock::DisplayColorProfile>();
1523 mock::RenderSurface* mRenderSurface = new StrictMock<mock::RenderSurface>();
1524 StrictMock<OutputPartialMock> mOutput;
1525
1526 Layer mLayer1;
1527 Layer mLayer2;
1528 Layer mLayer3;
1529
1530 CompositionRefreshArgs mRefreshArgs;
1531};
1532
1533// TODO(b/144522012): Refactor Output::updateColorProfile and the related code
1534// to make it easier to write unit tests.
1535
1536TEST_F(OutputUpdateColorProfileTest, setsAColorProfileWhenUnmanaged) {
1537 // When the outputColorSetting is set to kUnmanaged, the implementation sets
1538 // a simple default color profile without looking at anything else.
1539
1540 EXPECT_CALL(mOutput, getOutputLayerCount()).WillRepeatedly(Return(3));
1541 EXPECT_CALL(mOutput,
1542 setColorProfile(ColorProfileEq(
1543 ColorProfile{ui::ColorMode::NATIVE, ui::Dataspace::UNKNOWN,
1544 ui::RenderIntent::COLORIMETRIC, ui::Dataspace::UNKNOWN})));
1545
1546 mRefreshArgs.outputColorSetting = OutputColorSetting::kUnmanaged;
1547 mRefreshArgs.colorSpaceAgnosticDataspace = ui::Dataspace::UNKNOWN;
1548
1549 mOutput.updateColorProfile(mRefreshArgs);
1550}
1551
1552struct OutputUpdateColorProfileTest_GetBestColorModeResultBecomesSetProfile
1553 : public OutputUpdateColorProfileTest {
1554 OutputUpdateColorProfileTest_GetBestColorModeResultBecomesSetProfile() {
1555 EXPECT_CALL(mOutput, getOutputLayerCount()).WillRepeatedly(Return(0));
1556 mRefreshArgs.outputColorSetting = OutputColorSetting::kEnhanced;
1557 mRefreshArgs.colorSpaceAgnosticDataspace = ui::Dataspace::UNKNOWN;
1558 }
1559
1560 struct ExpectBestColorModeCallResultUsedToSetColorProfileState
1561 : public CallOrderStateMachineHelper<
1562 TestType, ExpectBestColorModeCallResultUsedToSetColorProfileState> {
1563 [[nodiscard]] auto expectBestColorModeCallResultUsedToSetColorProfile(
1564 ui::ColorMode colorMode, ui::Dataspace dataspace, ui::RenderIntent renderIntent) {
1565 EXPECT_CALL(*getInstance()->mDisplayColorProfile,
1566 getBestColorMode(ui::Dataspace::V0_SRGB, ui::RenderIntent::ENHANCE, _, _,
1567 _))
1568 .WillOnce(DoAll(SetArgPointee<2>(dataspace), SetArgPointee<3>(colorMode),
1569 SetArgPointee<4>(renderIntent)));
1570 EXPECT_CALL(getInstance()->mOutput,
1571 setColorProfile(
1572 ColorProfileEq(ColorProfile{colorMode, dataspace, renderIntent,
1573 ui::Dataspace::UNKNOWN})));
1574 return nextState<ExecuteState>();
1575 }
1576 };
1577
1578 // Call this member function to start using the mini-DSL defined above.
1579 [[nodiscard]] auto verify() {
1580 return ExpectBestColorModeCallResultUsedToSetColorProfileState::make(this);
1581 }
1582};
1583
1584TEST_F(OutputUpdateColorProfileTest_GetBestColorModeResultBecomesSetProfile,
1585 Native_Unknown_Colorimetric_Set) {
1586 verify().expectBestColorModeCallResultUsedToSetColorProfile(ui::ColorMode::NATIVE,
1587 ui::Dataspace::UNKNOWN,
1588 ui::RenderIntent::COLORIMETRIC)
1589 .execute();
1590}
1591
1592TEST_F(OutputUpdateColorProfileTest_GetBestColorModeResultBecomesSetProfile,
1593 DisplayP3_DisplayP3_Enhance_Set) {
1594 verify().expectBestColorModeCallResultUsedToSetColorProfile(ui::ColorMode::DISPLAY_P3,
1595 ui::Dataspace::DISPLAY_P3,
1596 ui::RenderIntent::ENHANCE)
1597 .execute();
1598}
1599
1600struct OutputUpdateColorProfileTest_ColorSpaceAgnosticeDataspaceAffectsSetColorProfile
1601 : public OutputUpdateColorProfileTest {
1602 OutputUpdateColorProfileTest_ColorSpaceAgnosticeDataspaceAffectsSetColorProfile() {
1603 EXPECT_CALL(mOutput, getOutputLayerCount()).WillRepeatedly(Return(0));
1604 EXPECT_CALL(*mDisplayColorProfile,
1605 getBestColorMode(ui::Dataspace::V0_SRGB, ui::RenderIntent::ENHANCE, _, _, _))
1606 .WillRepeatedly(DoAll(SetArgPointee<2>(ui::Dataspace::UNKNOWN),
1607 SetArgPointee<3>(ui::ColorMode::NATIVE),
1608 SetArgPointee<4>(ui::RenderIntent::COLORIMETRIC)));
1609 mRefreshArgs.outputColorSetting = OutputColorSetting::kEnhanced;
1610 }
1611
1612 struct IfColorSpaceAgnosticDataspaceSetToState
1613 : public CallOrderStateMachineHelper<TestType, IfColorSpaceAgnosticDataspaceSetToState> {
1614 [[nodiscard]] auto ifColorSpaceAgnosticDataspaceSetTo(ui::Dataspace dataspace) {
1615 getInstance()->mRefreshArgs.colorSpaceAgnosticDataspace = dataspace;
1616 return nextState<ThenExpectSetColorProfileCallUsesColorSpaceAgnosticDataspaceState>();
1617 }
1618 };
1619
1620 struct ThenExpectSetColorProfileCallUsesColorSpaceAgnosticDataspaceState
1621 : public CallOrderStateMachineHelper<
1622 TestType, ThenExpectSetColorProfileCallUsesColorSpaceAgnosticDataspaceState> {
1623 [[nodiscard]] auto thenExpectSetColorProfileCallUsesColorSpaceAgnosticDataspace(
1624 ui::Dataspace dataspace) {
1625 EXPECT_CALL(getInstance()->mOutput,
1626 setColorProfile(ColorProfileEq(
1627 ColorProfile{ui::ColorMode::NATIVE, ui::Dataspace::UNKNOWN,
1628 ui::RenderIntent::COLORIMETRIC, dataspace})));
1629 return nextState<ExecuteState>();
1630 }
1631 };
1632
1633 // Call this member function to start using the mini-DSL defined above.
1634 [[nodiscard]] auto verify() { return IfColorSpaceAgnosticDataspaceSetToState::make(this); }
1635};
1636
1637TEST_F(OutputUpdateColorProfileTest_ColorSpaceAgnosticeDataspaceAffectsSetColorProfile, DisplayP3) {
1638 verify().ifColorSpaceAgnosticDataspaceSetTo(ui::Dataspace::DISPLAY_P3)
1639 .thenExpectSetColorProfileCallUsesColorSpaceAgnosticDataspace(ui::Dataspace::DISPLAY_P3)
1640 .execute();
1641}
1642
1643TEST_F(OutputUpdateColorProfileTest_ColorSpaceAgnosticeDataspaceAffectsSetColorProfile, V0_SRGB) {
1644 verify().ifColorSpaceAgnosticDataspaceSetTo(ui::Dataspace::V0_SRGB)
1645 .thenExpectSetColorProfileCallUsesColorSpaceAgnosticDataspace(ui::Dataspace::V0_SRGB)
1646 .execute();
1647}
1648
1649struct OutputUpdateColorProfileTest_TopmostLayerPreferenceSetsOutputPreference
1650 : public OutputUpdateColorProfileTest {
1651 // Internally the implementation looks through the dataspaces of all the
1652 // visible layers. The topmost one that also has an actual dataspace
1653 // preference set is used to drive subsequent choices.
1654
1655 OutputUpdateColorProfileTest_TopmostLayerPreferenceSetsOutputPreference() {
1656 mRefreshArgs.outputColorSetting = OutputColorSetting::kEnhanced;
1657 mRefreshArgs.colorSpaceAgnosticDataspace = ui::Dataspace::UNKNOWN;
1658
1659 EXPECT_CALL(mOutput, getOutputLayerCount()).WillRepeatedly(Return(3));
1660 EXPECT_CALL(mOutput, setColorProfile(_)).WillRepeatedly(Return());
1661 }
1662
1663 struct IfTopLayerDataspaceState
1664 : public CallOrderStateMachineHelper<TestType, IfTopLayerDataspaceState> {
1665 [[nodiscard]] auto ifTopLayerIs(ui::Dataspace dataspace) {
1666 getInstance()->mLayer3.mLayerFEState.dataspace = dataspace;
1667 return nextState<AndIfMiddleLayerDataspaceState>();
1668 }
1669 [[nodiscard]] auto ifTopLayerHasNoPreference() {
1670 return ifTopLayerIs(ui::Dataspace::UNKNOWN);
1671 }
1672 };
1673
1674 struct AndIfMiddleLayerDataspaceState
1675 : public CallOrderStateMachineHelper<TestType, AndIfMiddleLayerDataspaceState> {
1676 [[nodiscard]] auto andIfMiddleLayerIs(ui::Dataspace dataspace) {
1677 getInstance()->mLayer2.mLayerFEState.dataspace = dataspace;
1678 return nextState<AndIfBottomLayerDataspaceState>();
1679 }
1680 [[nodiscard]] auto andIfMiddleLayerHasNoPreference() {
1681 return andIfMiddleLayerIs(ui::Dataspace::UNKNOWN);
1682 }
1683 };
1684
1685 struct AndIfBottomLayerDataspaceState
1686 : public CallOrderStateMachineHelper<TestType, AndIfBottomLayerDataspaceState> {
1687 [[nodiscard]] auto andIfBottomLayerIs(ui::Dataspace dataspace) {
1688 getInstance()->mLayer1.mLayerFEState.dataspace = dataspace;
1689 return nextState<ThenExpectBestColorModeCallUsesState>();
1690 }
1691 [[nodiscard]] auto andIfBottomLayerHasNoPreference() {
1692 return andIfBottomLayerIs(ui::Dataspace::UNKNOWN);
1693 }
1694 };
1695
1696 struct ThenExpectBestColorModeCallUsesState
1697 : public CallOrderStateMachineHelper<TestType, ThenExpectBestColorModeCallUsesState> {
1698 [[nodiscard]] auto thenExpectBestColorModeCallUses(ui::Dataspace dataspace) {
1699 EXPECT_CALL(*getInstance()->mDisplayColorProfile,
1700 getBestColorMode(dataspace, _, _, _, _));
1701 return nextState<ExecuteState>();
1702 }
1703 };
1704
1705 // Call this member function to start using the mini-DSL defined above.
1706 [[nodiscard]] auto verify() { return IfTopLayerDataspaceState::make(this); }
1707};
1708
1709TEST_F(OutputUpdateColorProfileTest_TopmostLayerPreferenceSetsOutputPreference,
1710 noStrongLayerPrefenceUses_V0_SRGB) {
1711 // If none of the layers indicate a preference, then V0_SRGB is the
1712 // preferred choice (subject to additional checks).
1713 verify().ifTopLayerHasNoPreference()
1714 .andIfMiddleLayerHasNoPreference()
1715 .andIfBottomLayerHasNoPreference()
1716 .thenExpectBestColorModeCallUses(ui::Dataspace::V0_SRGB)
1717 .execute();
1718}
1719
1720TEST_F(OutputUpdateColorProfileTest_TopmostLayerPreferenceSetsOutputPreference,
1721 ifTopmostUses_DisplayP3_Then_DisplayP3_Chosen) {
1722 // If only the topmost layer has a preference, then that is what is chosen.
1723 verify().ifTopLayerIs(ui::Dataspace::DISPLAY_P3)
1724 .andIfMiddleLayerHasNoPreference()
1725 .andIfBottomLayerHasNoPreference()
1726 .thenExpectBestColorModeCallUses(ui::Dataspace::DISPLAY_P3)
1727 .execute();
1728}
1729
1730TEST_F(OutputUpdateColorProfileTest_TopmostLayerPreferenceSetsOutputPreference,
1731 ifMiddleUses_DisplayP3_Then_DisplayP3_Chosen) {
1732 // If only the middle layer has a preference, that that is what is chosen.
1733 verify().ifTopLayerHasNoPreference()
1734 .andIfMiddleLayerIs(ui::Dataspace::DISPLAY_P3)
1735 .andIfBottomLayerHasNoPreference()
1736 .thenExpectBestColorModeCallUses(ui::Dataspace::DISPLAY_P3)
1737 .execute();
1738}
1739
1740TEST_F(OutputUpdateColorProfileTest_TopmostLayerPreferenceSetsOutputPreference,
1741 ifBottomUses_DisplayP3_Then_DisplayP3_Chosen) {
1742 // If only the middle layer has a preference, that that is what is chosen.
1743 verify().ifTopLayerHasNoPreference()
1744 .andIfMiddleLayerHasNoPreference()
1745 .andIfBottomLayerIs(ui::Dataspace::DISPLAY_P3)
1746 .thenExpectBestColorModeCallUses(ui::Dataspace::DISPLAY_P3)
1747 .execute();
1748}
1749
1750TEST_F(OutputUpdateColorProfileTest_TopmostLayerPreferenceSetsOutputPreference,
1751 ifTopUses_DisplayBT2020_AndBottomUses_DisplayP3_Then_DisplayBT2020_Chosen) {
1752 // If multiple layers have a preference, the topmost value is what is used.
1753 verify().ifTopLayerIs(ui::Dataspace::DISPLAY_BT2020)
1754 .andIfMiddleLayerHasNoPreference()
1755 .andIfBottomLayerIs(ui::Dataspace::DISPLAY_P3)
1756 .thenExpectBestColorModeCallUses(ui::Dataspace::DISPLAY_BT2020)
1757 .execute();
1758}
1759
1760TEST_F(OutputUpdateColorProfileTest_TopmostLayerPreferenceSetsOutputPreference,
1761 ifTopUses_DisplayP3_AndBottomUses_V0_SRGB_Then_DisplayP3_Chosen) {
1762 // If multiple layers have a preference, the topmost value is what is used.
1763 verify().ifTopLayerIs(ui::Dataspace::DISPLAY_P3)
1764 .andIfMiddleLayerHasNoPreference()
1765 .andIfBottomLayerIs(ui::Dataspace::DISPLAY_BT2020)
1766 .thenExpectBestColorModeCallUses(ui::Dataspace::DISPLAY_P3)
1767 .execute();
1768}
1769
1770struct OutputUpdateColorProfileTest_ForceOutputColorOverrides
1771 : public OutputUpdateColorProfileTest {
1772 // If CompositionRefreshArgs::forceOutputColorMode is set to some specific
1773 // values, it overrides the layer dataspace choice.
1774
1775 OutputUpdateColorProfileTest_ForceOutputColorOverrides() {
1776 mRefreshArgs.outputColorSetting = OutputColorSetting::kEnhanced;
1777 mRefreshArgs.colorSpaceAgnosticDataspace = ui::Dataspace::UNKNOWN;
1778
1779 mLayer1.mLayerFEState.dataspace = ui::Dataspace::DISPLAY_BT2020;
1780
1781 EXPECT_CALL(mOutput, getOutputLayerCount()).WillRepeatedly(Return(1));
1782 EXPECT_CALL(mOutput, setColorProfile(_)).WillRepeatedly(Return());
1783 }
1784
1785 struct IfForceOutputColorModeState
1786 : public CallOrderStateMachineHelper<TestType, IfForceOutputColorModeState> {
1787 [[nodiscard]] auto ifForceOutputColorMode(ui::ColorMode colorMode) {
1788 getInstance()->mRefreshArgs.forceOutputColorMode = colorMode;
1789 return nextState<ThenExpectBestColorModeCallUsesState>();
1790 }
1791 [[nodiscard]] auto ifNoOverride() { return ifForceOutputColorMode(ui::ColorMode::NATIVE); }
1792 };
1793
1794 struct ThenExpectBestColorModeCallUsesState
1795 : public CallOrderStateMachineHelper<TestType, ThenExpectBestColorModeCallUsesState> {
1796 [[nodiscard]] auto thenExpectBestColorModeCallUses(ui::Dataspace dataspace) {
1797 EXPECT_CALL(*getInstance()->mDisplayColorProfile,
1798 getBestColorMode(dataspace, _, _, _, _));
1799 return nextState<ExecuteState>();
1800 }
1801 };
1802
1803 // Call this member function to start using the mini-DSL defined above.
1804 [[nodiscard]] auto verify() { return IfForceOutputColorModeState::make(this); }
1805};
1806
1807TEST_F(OutputUpdateColorProfileTest_ForceOutputColorOverrides, NoOverride_DoesNotOverride) {
1808 // By default the layer state is used to set the preferred dataspace
1809 verify().ifNoOverride()
1810 .thenExpectBestColorModeCallUses(ui::Dataspace::DISPLAY_BT2020)
1811 .execute();
1812}
1813
1814TEST_F(OutputUpdateColorProfileTest_ForceOutputColorOverrides, SRGB_Override_USES_V0_SRGB) {
1815 // Setting ui::ColorMode::SRGB overrides it with ui::Dataspace::V0_SRGB
1816 verify().ifForceOutputColorMode(ui::ColorMode::SRGB)
1817 .thenExpectBestColorModeCallUses(ui::Dataspace::V0_SRGB)
1818 .execute();
1819}
1820
1821TEST_F(OutputUpdateColorProfileTest_ForceOutputColorOverrides, DisplayP3_Override_Uses_DisplayP3) {
1822 // Setting ui::ColorMode::DISPLAY_P3 overrides it with ui::Dataspace::DISPLAY_P3
1823 verify().ifForceOutputColorMode(ui::ColorMode::DISPLAY_P3)
1824 .thenExpectBestColorModeCallUses(ui::Dataspace::DISPLAY_P3)
1825 .execute();
1826}
1827
1828// HDR output requires all layers to be compatible with the chosen HDR
1829// dataspace, along with there being proper support.
1830struct OutputUpdateColorProfileTest_Hdr : public OutputUpdateColorProfileTest {
1831 OutputUpdateColorProfileTest_Hdr() {
1832 mRefreshArgs.outputColorSetting = OutputColorSetting::kEnhanced;
1833 mRefreshArgs.colorSpaceAgnosticDataspace = ui::Dataspace::UNKNOWN;
1834 EXPECT_CALL(mOutput, getOutputLayerCount()).WillRepeatedly(Return(2));
1835 EXPECT_CALL(mOutput, setColorProfile(_)).WillRepeatedly(Return());
1836 }
1837
1838 static constexpr ui::Dataspace kNonHdrDataspace = ui::Dataspace::DISPLAY_P3;
1839 static constexpr ui::Dataspace BT2020_PQ = ui::Dataspace::BT2020_PQ;
1840 static constexpr ui::Dataspace BT2020_HLG = ui::Dataspace::BT2020_HLG;
1841 static constexpr ui::Dataspace DISPLAY_P3 = ui::Dataspace::DISPLAY_P3;
1842
1843 struct IfTopLayerDataspaceState
1844 : public CallOrderStateMachineHelper<TestType, IfTopLayerDataspaceState> {
1845 [[nodiscard]] auto ifTopLayerIs(ui::Dataspace dataspace) {
1846 getInstance()->mLayer2.mLayerFEState.dataspace = dataspace;
1847 return nextState<AndTopLayerCompositionTypeState>();
1848 }
1849 [[nodiscard]] auto ifTopLayerIsNotHdr() { return ifTopLayerIs(kNonHdrDataspace); }
1850 };
1851
1852 struct AndTopLayerCompositionTypeState
1853 : public CallOrderStateMachineHelper<TestType, AndTopLayerCompositionTypeState> {
1854 [[nodiscard]] auto andTopLayerIsREComposed(bool renderEngineComposed) {
1855 getInstance()->mLayer2.mLayerFEState.forceClientComposition = renderEngineComposed;
1856 return nextState<AndIfBottomLayerDataspaceState>();
1857 }
1858 };
1859
1860 struct AndIfBottomLayerDataspaceState
1861 : public CallOrderStateMachineHelper<TestType, AndIfBottomLayerDataspaceState> {
1862 [[nodiscard]] auto andIfBottomLayerIs(ui::Dataspace dataspace) {
1863 getInstance()->mLayer1.mLayerFEState.dataspace = dataspace;
1864 return nextState<AndBottomLayerCompositionTypeState>();
1865 }
1866 [[nodiscard]] auto andIfBottomLayerIsNotHdr() {
1867 return andIfBottomLayerIs(kNonHdrDataspace);
1868 }
1869 };
1870
1871 struct AndBottomLayerCompositionTypeState
1872 : public CallOrderStateMachineHelper<TestType, AndBottomLayerCompositionTypeState> {
1873 [[nodiscard]] auto andBottomLayerIsREComposed(bool renderEngineComposed) {
1874 getInstance()->mLayer1.mLayerFEState.forceClientComposition = renderEngineComposed;
1875 return nextState<AndIfHasLegacySupportState>();
1876 }
1877 };
1878
1879 struct AndIfHasLegacySupportState
1880 : public CallOrderStateMachineHelper<TestType, AndIfHasLegacySupportState> {
1881 [[nodiscard]] auto andIfLegacySupportFor(ui::Dataspace dataspace, bool legacySupport) {
1882 EXPECT_CALL(*getInstance()->mDisplayColorProfile, hasLegacyHdrSupport(dataspace))
1883 .WillOnce(Return(legacySupport));
1884 return nextState<ThenExpectBestColorModeCallUsesState>();
1885 }
1886 };
1887
1888 struct ThenExpectBestColorModeCallUsesState
1889 : public CallOrderStateMachineHelper<TestType, ThenExpectBestColorModeCallUsesState> {
1890 [[nodiscard]] auto thenExpectBestColorModeCallUses(ui::Dataspace dataspace) {
1891 EXPECT_CALL(*getInstance()->mDisplayColorProfile,
1892 getBestColorMode(dataspace, _, _, _, _));
1893 return nextState<ExecuteState>();
1894 }
1895 };
1896
1897 // Call this member function to start using the mini-DSL defined above.
1898 [[nodiscard]] auto verify() { return IfTopLayerDataspaceState::make(this); }
1899};
1900
1901TEST_F(OutputUpdateColorProfileTest_Hdr, PQ_HW_On_PQ_HW_Uses_PQ) {
1902 // If all layers use BT2020_PQ, and there are no other special conditions,
1903 // BT2020_PQ is used.
1904 verify().ifTopLayerIs(BT2020_PQ)
1905 .andTopLayerIsREComposed(false)
1906 .andIfBottomLayerIs(BT2020_PQ)
1907 .andBottomLayerIsREComposed(false)
1908 .andIfLegacySupportFor(BT2020_PQ, false)
1909 .thenExpectBestColorModeCallUses(BT2020_PQ)
1910 .execute();
1911}
1912
1913TEST_F(OutputUpdateColorProfileTest_Hdr, PQ_HW_On_PQ_HW_IfPQHasLegacySupport_Uses_DisplayP3) {
1914 // BT2020_PQ is not used if there is only legacy support for it.
1915 verify().ifTopLayerIs(BT2020_PQ)
1916 .andTopLayerIsREComposed(false)
1917 .andIfBottomLayerIs(BT2020_PQ)
1918 .andBottomLayerIsREComposed(false)
1919 .andIfLegacySupportFor(BT2020_PQ, true)
1920 .thenExpectBestColorModeCallUses(DISPLAY_P3)
1921 .execute();
1922}
1923
1924TEST_F(OutputUpdateColorProfileTest_Hdr, PQ_HW_On_PQ_RE_Uses_PQ) {
1925 // BT2020_PQ is still used if the bottom layer is RenderEngine composed.
1926 verify().ifTopLayerIs(BT2020_PQ)
1927 .andTopLayerIsREComposed(false)
1928 .andIfBottomLayerIs(BT2020_PQ)
1929 .andBottomLayerIsREComposed(true)
1930 .andIfLegacySupportFor(BT2020_PQ, false)
1931 .thenExpectBestColorModeCallUses(BT2020_PQ)
1932 .execute();
1933}
1934
1935TEST_F(OutputUpdateColorProfileTest_Hdr, PQ_RE_On_PQ_HW_Uses_DisplayP3) {
1936 // BT2020_PQ is not used if the top layer is RenderEngine composed.
1937 verify().ifTopLayerIs(BT2020_PQ)
1938 .andTopLayerIsREComposed(true)
1939 .andIfBottomLayerIs(BT2020_PQ)
1940 .andBottomLayerIsREComposed(false)
1941 .andIfLegacySupportFor(BT2020_PQ, false)
1942 .thenExpectBestColorModeCallUses(DISPLAY_P3)
1943 .execute();
1944}
1945
1946TEST_F(OutputUpdateColorProfileTest_Hdr, PQ_HW_On_HLG_HW_Uses_PQ) {
1947 // If there is mixed HLG/PQ use, and the topmost layer is PQ, then PQ is used if there
1948 // are no other special conditions.
1949 verify().ifTopLayerIs(BT2020_PQ)
1950 .andTopLayerIsREComposed(false)
1951 .andIfBottomLayerIs(BT2020_HLG)
1952 .andBottomLayerIsREComposed(false)
1953 .andIfLegacySupportFor(BT2020_PQ, false)
1954 .thenExpectBestColorModeCallUses(BT2020_PQ)
1955 .execute();
1956}
1957
1958TEST_F(OutputUpdateColorProfileTest_Hdr, PQ_HW_On_HLG_HW_IfPQHasLegacySupport_Uses_DisplayP3) {
1959 // BT2020_PQ is not used if there is only legacy support for it.
1960 verify().ifTopLayerIs(BT2020_PQ)
1961 .andTopLayerIsREComposed(false)
1962 .andIfBottomLayerIs(BT2020_HLG)
1963 .andBottomLayerIsREComposed(false)
1964 .andIfLegacySupportFor(BT2020_PQ, true)
1965 .thenExpectBestColorModeCallUses(DISPLAY_P3)
1966 .execute();
1967}
1968
1969TEST_F(OutputUpdateColorProfileTest_Hdr, PQ_HW_On_HLG_RE_Uses_PQ) {
1970 // BT2020_PQ is used if the bottom HLG layer is RenderEngine composed.
1971 verify().ifTopLayerIs(BT2020_PQ)
1972 .andTopLayerIsREComposed(false)
1973 .andIfBottomLayerIs(BT2020_HLG)
1974 .andBottomLayerIsREComposed(true)
1975 .andIfLegacySupportFor(BT2020_PQ, false)
1976 .thenExpectBestColorModeCallUses(BT2020_PQ)
1977 .execute();
1978}
1979
1980TEST_F(OutputUpdateColorProfileTest_Hdr, PQ_RE_On_HLG_HW_Uses_DisplayP3) {
1981 // BT2020_PQ is not used if the top PQ layer is RenderEngine composed.
1982 verify().ifTopLayerIs(BT2020_PQ)
1983 .andTopLayerIsREComposed(true)
1984 .andIfBottomLayerIs(BT2020_HLG)
1985 .andBottomLayerIsREComposed(false)
1986 .andIfLegacySupportFor(BT2020_PQ, false)
1987 .thenExpectBestColorModeCallUses(DISPLAY_P3)
1988 .execute();
1989}
1990
1991TEST_F(OutputUpdateColorProfileTest_Hdr, HLG_HW_On_PQ_HW_Uses_PQ) {
1992 // If there is mixed HLG/PQ use, and the topmost layer is HLG, then PQ is
1993 // used if there are no other special conditions.
1994 verify().ifTopLayerIs(BT2020_HLG)
1995 .andTopLayerIsREComposed(false)
1996 .andIfBottomLayerIs(BT2020_PQ)
1997 .andBottomLayerIsREComposed(false)
1998 .andIfLegacySupportFor(BT2020_PQ, false)
1999 .thenExpectBestColorModeCallUses(BT2020_PQ)
2000 .execute();
2001}
2002
2003TEST_F(OutputUpdateColorProfileTest_Hdr, HLG_HW_On_PQ_HW_IfPQHasLegacySupport_Uses_DisplayP3) {
2004 // BT2020_PQ is not used if there is only legacy support for it.
2005 verify().ifTopLayerIs(BT2020_HLG)
2006 .andTopLayerIsREComposed(false)
2007 .andIfBottomLayerIs(BT2020_PQ)
2008 .andBottomLayerIsREComposed(false)
2009 .andIfLegacySupportFor(BT2020_PQ, true)
2010 .thenExpectBestColorModeCallUses(DISPLAY_P3)
2011 .execute();
2012}
2013
2014TEST_F(OutputUpdateColorProfileTest_Hdr, HLG_HW_On_PQ_RE_Uses_DisplayP3) {
2015 // BT2020_PQ is not used if the bottom PQ layer is RenderEngine composed.
2016 verify().ifTopLayerIs(BT2020_HLG)
2017 .andTopLayerIsREComposed(false)
2018 .andIfBottomLayerIs(BT2020_PQ)
2019 .andBottomLayerIsREComposed(true)
2020 .andIfLegacySupportFor(BT2020_PQ, false)
2021 .thenExpectBestColorModeCallUses(DISPLAY_P3)
2022 .execute();
2023}
2024
2025TEST_F(OutputUpdateColorProfileTest_Hdr, HLG_RE_On_PQ_HW_Uses_PQ) {
2026 // BT2020_PQ is still used if the top HLG layer is RenderEngine composed.
2027 verify().ifTopLayerIs(BT2020_HLG)
2028 .andTopLayerIsREComposed(true)
2029 .andIfBottomLayerIs(BT2020_PQ)
2030 .andBottomLayerIsREComposed(false)
2031 .andIfLegacySupportFor(BT2020_PQ, false)
2032 .thenExpectBestColorModeCallUses(BT2020_PQ)
2033 .execute();
2034}
2035
2036TEST_F(OutputUpdateColorProfileTest_Hdr, HLG_HW_On_HLG_HW_Uses_HLG) {
2037 // If all layers use HLG then HLG is used if there are no other special
2038 // conditions.
2039 verify().ifTopLayerIs(BT2020_HLG)
2040 .andTopLayerIsREComposed(false)
2041 .andIfBottomLayerIs(BT2020_HLG)
2042 .andBottomLayerIsREComposed(false)
2043 .andIfLegacySupportFor(BT2020_HLG, false)
2044 .thenExpectBestColorModeCallUses(BT2020_HLG)
2045 .execute();
2046}
2047
2048TEST_F(OutputUpdateColorProfileTest_Hdr, HLG_HW_On_HLG_HW_IfPQHasLegacySupport_Uses_DisplayP3) {
2049 // BT2020_HLG is not used if there is legacy support for it.
2050 verify().ifTopLayerIs(BT2020_HLG)
2051 .andTopLayerIsREComposed(false)
2052 .andIfBottomLayerIs(BT2020_HLG)
2053 .andBottomLayerIsREComposed(false)
2054 .andIfLegacySupportFor(BT2020_HLG, true)
2055 .thenExpectBestColorModeCallUses(DISPLAY_P3)
2056 .execute();
2057}
2058
2059TEST_F(OutputUpdateColorProfileTest_Hdr, HLG_HW_On_HLG_RE_Uses_HLG) {
2060 // BT2020_HLG is used even if the bottom layer is client composed.
2061 verify().ifTopLayerIs(BT2020_HLG)
2062 .andTopLayerIsREComposed(false)
2063 .andIfBottomLayerIs(BT2020_HLG)
2064 .andBottomLayerIsREComposed(true)
2065 .andIfLegacySupportFor(BT2020_HLG, false)
2066 .thenExpectBestColorModeCallUses(BT2020_HLG)
2067 .execute();
2068}
2069
2070TEST_F(OutputUpdateColorProfileTest_Hdr, HLG_RE_On_HLG_HW_Uses_HLG) {
2071 // BT2020_HLG is used even if the top layer is client composed.
2072 verify().ifTopLayerIs(BT2020_HLG)
2073 .andTopLayerIsREComposed(true)
2074 .andIfBottomLayerIs(BT2020_HLG)
2075 .andBottomLayerIsREComposed(false)
2076 .andIfLegacySupportFor(BT2020_HLG, false)
2077 .thenExpectBestColorModeCallUses(BT2020_HLG)
2078 .execute();
2079}
2080
2081TEST_F(OutputUpdateColorProfileTest_Hdr, PQ_HW_On_NonHdr_HW_Uses_PQ) {
2082 // Even if there are non-HDR layers present, BT2020_PQ can still be used.
2083 verify().ifTopLayerIs(BT2020_PQ)
2084 .andTopLayerIsREComposed(false)
2085 .andIfBottomLayerIsNotHdr()
2086 .andBottomLayerIsREComposed(false)
2087 .andIfLegacySupportFor(BT2020_PQ, false)
2088 .thenExpectBestColorModeCallUses(BT2020_PQ)
2089 .execute();
2090}
2091
2092TEST_F(OutputUpdateColorProfileTest_Hdr, HLG_HW_On_NonHdr_RE_Uses_HLG) {
2093 // If all layers use HLG then HLG is used if there are no other special
2094 // conditions.
2095 verify().ifTopLayerIs(BT2020_HLG)
2096 .andTopLayerIsREComposed(false)
2097 .andIfBottomLayerIsNotHdr()
2098 .andBottomLayerIsREComposed(true)
2099 .andIfLegacySupportFor(BT2020_HLG, false)
2100 .thenExpectBestColorModeCallUses(BT2020_HLG)
2101 .execute();
2102}
2103
2104struct OutputUpdateColorProfile_AffectsChosenRenderIntentTest
2105 : public OutputUpdateColorProfileTest {
2106 // The various values for CompositionRefreshArgs::outputColorSetting affect
2107 // the chosen renderIntent, along with whether the preferred dataspace is an
2108 // HDR dataspace or not.
2109
2110 OutputUpdateColorProfile_AffectsChosenRenderIntentTest() {
2111 mRefreshArgs.outputColorSetting = OutputColorSetting::kEnhanced;
2112 mRefreshArgs.colorSpaceAgnosticDataspace = ui::Dataspace::UNKNOWN;
2113 mLayer1.mLayerFEState.dataspace = ui::Dataspace::BT2020_PQ;
2114 EXPECT_CALL(mOutput, getOutputLayerCount()).WillRepeatedly(Return(1));
2115 EXPECT_CALL(mOutput, setColorProfile(_)).WillRepeatedly(Return());
2116 EXPECT_CALL(*mDisplayColorProfile, hasLegacyHdrSupport(ui::Dataspace::BT2020_PQ))
2117 .WillRepeatedly(Return(false));
2118 }
2119
2120 // The tests here involve enough state and GMock setup that using a mini-DSL
2121 // makes the tests much more readable, and allows the test to focus more on
2122 // the intent than on some of the details.
2123
2124 static constexpr ui::Dataspace kNonHdrDataspace = ui::Dataspace::DISPLAY_P3;
2125 static constexpr ui::Dataspace kHdrDataspace = ui::Dataspace::BT2020_PQ;
2126
2127 struct IfDataspaceChosenState
2128 : public CallOrderStateMachineHelper<TestType, IfDataspaceChosenState> {
2129 [[nodiscard]] auto ifDataspaceChosenIs(ui::Dataspace dataspace) {
2130 getInstance()->mLayer1.mLayerFEState.dataspace = dataspace;
2131 return nextState<AndOutputColorSettingState>();
2132 }
2133 [[nodiscard]] auto ifDataspaceChosenIsNonHdr() {
2134 return ifDataspaceChosenIs(kNonHdrDataspace);
2135 }
2136 [[nodiscard]] auto ifDataspaceChosenIsHdr() { return ifDataspaceChosenIs(kHdrDataspace); }
2137 };
2138
2139 struct AndOutputColorSettingState
2140 : public CallOrderStateMachineHelper<TestType, AndOutputColorSettingState> {
2141 [[nodiscard]] auto andOutputColorSettingIs(OutputColorSetting setting) {
2142 getInstance()->mRefreshArgs.outputColorSetting = setting;
2143 return nextState<ThenExpectBestColorModeCallUsesState>();
2144 }
2145 };
2146
2147 struct ThenExpectBestColorModeCallUsesState
2148 : public CallOrderStateMachineHelper<TestType, ThenExpectBestColorModeCallUsesState> {
2149 [[nodiscard]] auto thenExpectBestColorModeCallUses(ui::RenderIntent intent) {
2150 EXPECT_CALL(*getInstance()->mDisplayColorProfile,
2151 getBestColorMode(getInstance()->mLayer1.mLayerFEState.dataspace, intent, _,
2152 _, _));
2153 return nextState<ExecuteState>();
2154 }
2155 };
2156
2157 // Tests call one of these two helper member functions to start using the
2158 // mini-DSL defined above.
2159 [[nodiscard]] auto verify() { return IfDataspaceChosenState::make(this); }
2160};
2161
2162TEST_F(OutputUpdateColorProfile_AffectsChosenRenderIntentTest,
2163 Managed_NonHdr_Prefers_Colorimetric) {
2164 verify().ifDataspaceChosenIsNonHdr()
2165 .andOutputColorSettingIs(OutputColorSetting::kManaged)
2166 .thenExpectBestColorModeCallUses(ui::RenderIntent::COLORIMETRIC)
2167 .execute();
2168}
2169
2170TEST_F(OutputUpdateColorProfile_AffectsChosenRenderIntentTest,
2171 Managed_Hdr_Prefers_ToneMapColorimetric) {
2172 verify().ifDataspaceChosenIsHdr()
2173 .andOutputColorSettingIs(OutputColorSetting::kManaged)
2174 .thenExpectBestColorModeCallUses(ui::RenderIntent::TONE_MAP_COLORIMETRIC)
2175 .execute();
2176}
2177
2178TEST_F(OutputUpdateColorProfile_AffectsChosenRenderIntentTest, Enhanced_NonHdr_Prefers_Enhance) {
2179 verify().ifDataspaceChosenIsNonHdr()
2180 .andOutputColorSettingIs(OutputColorSetting::kEnhanced)
2181 .thenExpectBestColorModeCallUses(ui::RenderIntent::ENHANCE)
2182 .execute();
2183}
2184
2185TEST_F(OutputUpdateColorProfile_AffectsChosenRenderIntentTest,
2186 Enhanced_Hdr_Prefers_ToneMapEnhance) {
2187 verify().ifDataspaceChosenIsHdr()
2188 .andOutputColorSettingIs(OutputColorSetting::kEnhanced)
2189 .thenExpectBestColorModeCallUses(ui::RenderIntent::TONE_MAP_ENHANCE)
2190 .execute();
2191}
2192
2193TEST_F(OutputUpdateColorProfile_AffectsChosenRenderIntentTest, Vendor_NonHdr_Prefers_Vendor) {
2194 verify().ifDataspaceChosenIsNonHdr()
2195 .andOutputColorSettingIs(kVendorSpecifiedOutputColorSetting)
2196 .thenExpectBestColorModeCallUses(
2197 static_cast<ui::RenderIntent>(kVendorSpecifiedOutputColorSetting))
2198 .execute();
2199}
2200
2201TEST_F(OutputUpdateColorProfile_AffectsChosenRenderIntentTest, Vendor_Hdr_Prefers_Vendor) {
2202 verify().ifDataspaceChosenIsHdr()
2203 .andOutputColorSettingIs(kVendorSpecifiedOutputColorSetting)
2204 .thenExpectBestColorModeCallUses(
2205 static_cast<ui::RenderIntent>(kVendorSpecifiedOutputColorSetting))
2206 .execute();
2207}
Lloyd Piquefaa3f192019-11-14 14:05:09 -08002208
2209/*
2210 * Output::beginFrame()
2211 */
2212
Lloyd Piquee5965952019-11-18 16:16:32 -08002213struct OutputBeginFrameTest : public ::testing::Test {
2214 using TestType = OutputBeginFrameTest;
2215
2216 struct OutputPartialMock : public OutputPartialMockBase {
Lloyd Pique739afaf2019-11-21 16:40:05 -08002217 // Sets up the helper functions called by the function under test to use
2218 // mock implementations.
Lloyd Piquee5965952019-11-18 16:16:32 -08002219 MOCK_CONST_METHOD1(getDirtyRegion, Region(bool));
2220 };
2221
2222 OutputBeginFrameTest() {
2223 mOutput.setDisplayColorProfileForTest(
2224 std::unique_ptr<DisplayColorProfile>(mDisplayColorProfile));
2225 mOutput.setRenderSurfaceForTest(std::unique_ptr<RenderSurface>(mRenderSurface));
2226 }
2227
2228 struct IfGetDirtyRegionExpectationState
2229 : public CallOrderStateMachineHelper<TestType, IfGetDirtyRegionExpectationState> {
2230 [[nodiscard]] auto ifGetDirtyRegionReturns(Region dirtyRegion) {
2231 EXPECT_CALL(getInstance()->mOutput, getDirtyRegion(false))
2232 .WillOnce(Return(dirtyRegion));
2233 return nextState<AndIfGetOutputLayerCountExpectationState>();
2234 }
2235 };
2236
2237 struct AndIfGetOutputLayerCountExpectationState
2238 : public CallOrderStateMachineHelper<TestType, AndIfGetOutputLayerCountExpectationState> {
2239 [[nodiscard]] auto andIfGetOutputLayerCountReturns(size_t layerCount) {
2240 EXPECT_CALL(getInstance()->mOutput, getOutputLayerCount()).WillOnce(Return(layerCount));
2241 return nextState<AndIfLastCompositionHadVisibleLayersState>();
2242 }
2243 };
2244
2245 struct AndIfLastCompositionHadVisibleLayersState
2246 : public CallOrderStateMachineHelper<TestType,
2247 AndIfLastCompositionHadVisibleLayersState> {
2248 [[nodiscard]] auto andIfLastCompositionHadVisibleLayersIs(bool hadOutputLayers) {
2249 getInstance()->mOutput.mState.lastCompositionHadVisibleLayers = hadOutputLayers;
2250 return nextState<ThenExpectRenderSurfaceBeginFrameCallState>();
2251 }
2252 };
2253
2254 struct ThenExpectRenderSurfaceBeginFrameCallState
2255 : public CallOrderStateMachineHelper<TestType,
2256 ThenExpectRenderSurfaceBeginFrameCallState> {
2257 [[nodiscard]] auto thenExpectRenderSurfaceBeginFrameCall(bool mustRecompose) {
2258 EXPECT_CALL(*getInstance()->mRenderSurface, beginFrame(mustRecompose));
2259 return nextState<ExecuteState>();
2260 }
2261 };
2262
2263 struct ExecuteState : public CallOrderStateMachineHelper<TestType, ExecuteState> {
2264 [[nodiscard]] auto execute() {
2265 getInstance()->mOutput.beginFrame();
2266 return nextState<CheckPostconditionHadVisibleLayersState>();
2267 }
2268 };
2269
2270 struct CheckPostconditionHadVisibleLayersState
2271 : public CallOrderStateMachineHelper<TestType, CheckPostconditionHadVisibleLayersState> {
2272 void checkPostconditionHadVisibleLayers(bool expected) {
2273 EXPECT_EQ(expected, getInstance()->mOutput.mState.lastCompositionHadVisibleLayers);
2274 }
2275 };
2276
2277 // Tests call one of these two helper member functions to start using the
2278 // mini-DSL defined above.
2279 [[nodiscard]] auto verify() { return IfGetDirtyRegionExpectationState::make(this); }
2280
2281 static const Region kEmptyRegion;
2282 static const Region kNotEmptyRegion;
2283
2284 mock::DisplayColorProfile* mDisplayColorProfile = new StrictMock<mock::DisplayColorProfile>();
2285 mock::RenderSurface* mRenderSurface = new StrictMock<mock::RenderSurface>();
2286 StrictMock<OutputPartialMock> mOutput;
2287};
2288
2289const Region OutputBeginFrameTest::kEmptyRegion{Rect{0, 0, 0, 0}};
2290const Region OutputBeginFrameTest::kNotEmptyRegion{Rect{0, 0, 1, 1}};
2291
2292TEST_F(OutputBeginFrameTest, hasDirtyHasLayersHadLayersLastFrame) {
2293 verify().ifGetDirtyRegionReturns(kNotEmptyRegion)
2294 .andIfGetOutputLayerCountReturns(1u)
2295 .andIfLastCompositionHadVisibleLayersIs(true)
2296 .thenExpectRenderSurfaceBeginFrameCall(true)
2297 .execute()
2298 .checkPostconditionHadVisibleLayers(true);
2299}
2300
2301TEST_F(OutputBeginFrameTest, hasDirtyNotHasLayersHadLayersLastFrame) {
2302 verify().ifGetDirtyRegionReturns(kNotEmptyRegion)
2303 .andIfGetOutputLayerCountReturns(0u)
2304 .andIfLastCompositionHadVisibleLayersIs(true)
2305 .thenExpectRenderSurfaceBeginFrameCall(true)
2306 .execute()
2307 .checkPostconditionHadVisibleLayers(false);
2308}
2309
2310TEST_F(OutputBeginFrameTest, hasDirtyHasLayersNotHadLayersLastFrame) {
2311 verify().ifGetDirtyRegionReturns(kNotEmptyRegion)
2312 .andIfGetOutputLayerCountReturns(1u)
2313 .andIfLastCompositionHadVisibleLayersIs(false)
2314 .thenExpectRenderSurfaceBeginFrameCall(true)
2315 .execute()
2316 .checkPostconditionHadVisibleLayers(true);
2317}
2318
2319TEST_F(OutputBeginFrameTest, hasDirtyNotHasLayersNotHadLayersLastFrame) {
2320 verify().ifGetDirtyRegionReturns(kNotEmptyRegion)
2321 .andIfGetOutputLayerCountReturns(0u)
2322 .andIfLastCompositionHadVisibleLayersIs(false)
2323 .thenExpectRenderSurfaceBeginFrameCall(false)
2324 .execute()
2325 .checkPostconditionHadVisibleLayers(false);
2326}
2327
2328TEST_F(OutputBeginFrameTest, notHasDirtyHasLayersHadLayersLastFrame) {
2329 verify().ifGetDirtyRegionReturns(kEmptyRegion)
2330 .andIfGetOutputLayerCountReturns(1u)
2331 .andIfLastCompositionHadVisibleLayersIs(true)
2332 .thenExpectRenderSurfaceBeginFrameCall(false)
2333 .execute()
2334 .checkPostconditionHadVisibleLayers(true);
2335}
2336
2337TEST_F(OutputBeginFrameTest, notHasDirtyNotHasLayersHadLayersLastFrame) {
2338 verify().ifGetDirtyRegionReturns(kEmptyRegion)
2339 .andIfGetOutputLayerCountReturns(0u)
2340 .andIfLastCompositionHadVisibleLayersIs(true)
2341 .thenExpectRenderSurfaceBeginFrameCall(false)
2342 .execute()
2343 .checkPostconditionHadVisibleLayers(true);
2344}
2345
2346TEST_F(OutputBeginFrameTest, notHasDirtyHasLayersNotHadLayersLastFrame) {
2347 verify().ifGetDirtyRegionReturns(kEmptyRegion)
2348 .andIfGetOutputLayerCountReturns(1u)
2349 .andIfLastCompositionHadVisibleLayersIs(false)
2350 .thenExpectRenderSurfaceBeginFrameCall(false)
2351 .execute()
2352 .checkPostconditionHadVisibleLayers(false);
2353}
2354
2355TEST_F(OutputBeginFrameTest, notHasDirtyNotHasLayersNotHadLayersLastFrame) {
2356 verify().ifGetDirtyRegionReturns(kEmptyRegion)
2357 .andIfGetOutputLayerCountReturns(0u)
2358 .andIfLastCompositionHadVisibleLayersIs(false)
2359 .thenExpectRenderSurfaceBeginFrameCall(false)
2360 .execute()
2361 .checkPostconditionHadVisibleLayers(false);
2362}
2363
Lloyd Piquefaa3f192019-11-14 14:05:09 -08002364/*
2365 * Output::devOptRepaintFlash()
2366 */
2367
Lloyd Piquedb462d82019-11-19 17:58:46 -08002368struct OutputDevOptRepaintFlashTest : public testing::Test {
2369 struct OutputPartialMock : public OutputPartialMockBase {
Lloyd Pique739afaf2019-11-21 16:40:05 -08002370 // Sets up the helper functions called by the function under test to use
2371 // mock implementations.
Lloyd Piquedb462d82019-11-19 17:58:46 -08002372 MOCK_CONST_METHOD1(getDirtyRegion, Region(bool));
2373 MOCK_METHOD1(composeSurfaces, std::optional<base::unique_fd>(const Region&));
2374 MOCK_METHOD0(postFramebuffer, void());
2375 MOCK_METHOD0(prepareFrame, void());
2376 };
2377
2378 OutputDevOptRepaintFlashTest() {
2379 mOutput.setDisplayColorProfileForTest(
2380 std::unique_ptr<DisplayColorProfile>(mDisplayColorProfile));
2381 mOutput.setRenderSurfaceForTest(std::unique_ptr<RenderSurface>(mRenderSurface));
2382 }
2383
2384 static const Region kEmptyRegion;
2385 static const Region kNotEmptyRegion;
2386
2387 StrictMock<OutputPartialMock> mOutput;
2388 mock::DisplayColorProfile* mDisplayColorProfile = new StrictMock<mock::DisplayColorProfile>();
2389 mock::RenderSurface* mRenderSurface = new StrictMock<mock::RenderSurface>();
2390 CompositionRefreshArgs mRefreshArgs;
2391};
2392
2393const Region OutputDevOptRepaintFlashTest::kEmptyRegion{Rect{0, 0, 0, 0}};
2394const Region OutputDevOptRepaintFlashTest::kNotEmptyRegion{Rect{0, 0, 1, 1}};
2395
2396TEST_F(OutputDevOptRepaintFlashTest, doesNothingIfFlashDelayNotSet) {
2397 mRefreshArgs.devOptFlashDirtyRegionsDelay = {};
2398 mRefreshArgs.repaintEverything = true;
2399 mOutput.mState.isEnabled = true;
2400
2401 mOutput.devOptRepaintFlash(mRefreshArgs);
2402}
2403
2404TEST_F(OutputDevOptRepaintFlashTest, postsAndPreparesANewFrameIfNotEnabled) {
2405 mRefreshArgs.devOptFlashDirtyRegionsDelay = std::chrono::microseconds(1);
2406 mRefreshArgs.repaintEverything = true;
2407 mOutput.mState.isEnabled = false;
2408
2409 InSequence seq;
2410 EXPECT_CALL(mOutput, postFramebuffer());
2411 EXPECT_CALL(mOutput, prepareFrame());
2412
2413 mOutput.devOptRepaintFlash(mRefreshArgs);
2414}
2415
2416TEST_F(OutputDevOptRepaintFlashTest, postsAndPreparesANewFrameIfNotDirty) {
2417 mRefreshArgs.devOptFlashDirtyRegionsDelay = std::chrono::microseconds(1);
2418 mRefreshArgs.repaintEverything = true;
2419 mOutput.mState.isEnabled = true;
2420
2421 InSequence seq;
2422 EXPECT_CALL(mOutput, getDirtyRegion(true)).WillOnce(Return(kEmptyRegion));
2423 EXPECT_CALL(mOutput, postFramebuffer());
2424 EXPECT_CALL(mOutput, prepareFrame());
2425
2426 mOutput.devOptRepaintFlash(mRefreshArgs);
2427}
2428
2429TEST_F(OutputDevOptRepaintFlashTest, alsoComposesSurfacesAndQueuesABufferIfDirty) {
2430 mRefreshArgs.devOptFlashDirtyRegionsDelay = std::chrono::microseconds(1);
2431 mRefreshArgs.repaintEverything = false;
2432 mOutput.mState.isEnabled = true;
2433
2434 InSequence seq;
2435 EXPECT_CALL(mOutput, getDirtyRegion(false)).WillOnce(Return(kNotEmptyRegion));
2436 EXPECT_CALL(mOutput, composeSurfaces(RegionEq(kNotEmptyRegion)));
2437 EXPECT_CALL(*mRenderSurface, queueBuffer(_));
2438 EXPECT_CALL(mOutput, postFramebuffer());
2439 EXPECT_CALL(mOutput, prepareFrame());
2440
2441 mOutput.devOptRepaintFlash(mRefreshArgs);
2442}
2443
Lloyd Piquefaa3f192019-11-14 14:05:09 -08002444/*
2445 * Output::finishFrame()
2446 */
2447
Lloyd Pique03561a62019-11-19 18:34:52 -08002448struct OutputFinishFrameTest : public testing::Test {
2449 struct OutputPartialMock : public OutputPartialMockBase {
Lloyd Pique739afaf2019-11-21 16:40:05 -08002450 // Sets up the helper functions called by the function under test to use
2451 // mock implementations.
Lloyd Pique03561a62019-11-19 18:34:52 -08002452 MOCK_METHOD1(composeSurfaces, std::optional<base::unique_fd>(const Region&));
2453 MOCK_METHOD0(postFramebuffer, void());
2454 };
2455
2456 OutputFinishFrameTest() {
2457 mOutput.setDisplayColorProfileForTest(
2458 std::unique_ptr<DisplayColorProfile>(mDisplayColorProfile));
2459 mOutput.setRenderSurfaceForTest(std::unique_ptr<RenderSurface>(mRenderSurface));
2460 }
2461
2462 StrictMock<OutputPartialMock> mOutput;
2463 mock::DisplayColorProfile* mDisplayColorProfile = new StrictMock<mock::DisplayColorProfile>();
2464 mock::RenderSurface* mRenderSurface = new StrictMock<mock::RenderSurface>();
2465 CompositionRefreshArgs mRefreshArgs;
2466};
2467
2468TEST_F(OutputFinishFrameTest, ifNotEnabledDoesNothing) {
2469 mOutput.mState.isEnabled = false;
2470
2471 mOutput.finishFrame(mRefreshArgs);
2472}
2473
2474TEST_F(OutputFinishFrameTest, takesEarlyOutifComposeSurfacesReturnsNoFence) {
2475 mOutput.mState.isEnabled = true;
2476
2477 InSequence seq;
2478 EXPECT_CALL(mOutput, composeSurfaces(RegionEq(Region::INVALID_REGION)));
2479
2480 mOutput.finishFrame(mRefreshArgs);
2481}
2482
2483TEST_F(OutputFinishFrameTest, queuesBufferIfComposeSurfacesReturnsAFence) {
2484 mOutput.mState.isEnabled = true;
2485
2486 InSequence seq;
2487 EXPECT_CALL(mOutput, composeSurfaces(RegionEq(Region::INVALID_REGION)))
2488 .WillOnce(Return(ByMove(base::unique_fd())));
2489 EXPECT_CALL(*mRenderSurface, queueBuffer(_));
2490
2491 mOutput.finishFrame(mRefreshArgs);
2492}
Lloyd Piquefaa3f192019-11-14 14:05:09 -08002493
2494/*
2495 * Output::postFramebuffer()
2496 */
2497
Lloyd Pique07178e32019-11-19 19:15:26 -08002498struct OutputPostFramebufferTest : public testing::Test {
2499 struct OutputPartialMock : public OutputPartialMockBase {
Lloyd Pique739afaf2019-11-21 16:40:05 -08002500 // Sets up the helper functions called by the function under test to use
2501 // mock implementations.
Lloyd Pique07178e32019-11-19 19:15:26 -08002502 MOCK_METHOD0(presentAndGetFrameFences, compositionengine::Output::FrameFences());
2503 };
2504
2505 struct Layer {
2506 Layer() {
2507 EXPECT_CALL(outputLayer, getLayerFE()).WillRepeatedly(ReturnRef(layerFE));
2508 EXPECT_CALL(outputLayer, getHwcLayer()).WillRepeatedly(Return(&hwc2Layer));
2509 }
2510
2511 StrictMock<mock::OutputLayer> outputLayer;
2512 StrictMock<mock::LayerFE> layerFE;
2513 StrictMock<HWC2::mock::Layer> hwc2Layer;
2514 };
2515
2516 OutputPostFramebufferTest() {
2517 mOutput.setDisplayColorProfileForTest(
2518 std::unique_ptr<DisplayColorProfile>(mDisplayColorProfile));
2519 mOutput.setRenderSurfaceForTest(std::unique_ptr<RenderSurface>(mRenderSurface));
2520
2521 EXPECT_CALL(mOutput, getOutputLayerCount()).WillRepeatedly(Return(3u));
2522 EXPECT_CALL(mOutput, getOutputLayerOrderedByZByIndex(0u))
2523 .WillRepeatedly(Return(&mLayer1.outputLayer));
2524 EXPECT_CALL(mOutput, getOutputLayerOrderedByZByIndex(1u))
2525 .WillRepeatedly(Return(&mLayer2.outputLayer));
2526 EXPECT_CALL(mOutput, getOutputLayerOrderedByZByIndex(2u))
2527 .WillRepeatedly(Return(&mLayer3.outputLayer));
2528 }
2529
2530 StrictMock<OutputPartialMock> mOutput;
2531 mock::DisplayColorProfile* mDisplayColorProfile = new StrictMock<mock::DisplayColorProfile>();
2532 mock::RenderSurface* mRenderSurface = new StrictMock<mock::RenderSurface>();
2533
2534 Layer mLayer1;
2535 Layer mLayer2;
2536 Layer mLayer3;
2537};
2538
2539TEST_F(OutputPostFramebufferTest, ifNotEnabledDoesNothing) {
2540 mOutput.mState.isEnabled = false;
2541
2542 mOutput.postFramebuffer();
2543}
2544
2545TEST_F(OutputPostFramebufferTest, ifEnabledMustFlipThenPresentThenSendPresentCompleted) {
2546 mOutput.mState.isEnabled = true;
2547
2548 compositionengine::Output::FrameFences frameFences;
2549
2550 // This should happen even if there are no output layers.
2551 EXPECT_CALL(mOutput, getOutputLayerCount()).WillOnce(Return(0u));
2552
2553 // For this test in particular we want to make sure the call expectations
2554 // setup below are satisfied in the specific order.
2555 InSequence seq;
2556
2557 EXPECT_CALL(*mRenderSurface, flip());
2558 EXPECT_CALL(mOutput, presentAndGetFrameFences()).WillOnce(Return(frameFences));
2559 EXPECT_CALL(*mRenderSurface, onPresentDisplayCompleted());
2560
2561 mOutput.postFramebuffer();
2562}
2563
2564TEST_F(OutputPostFramebufferTest, releaseFencesAreSentToLayerFE) {
2565 // Simulate getting release fences from each layer, and ensure they are passed to the
2566 // front-end layer interface for each layer correctly.
2567
2568 mOutput.mState.isEnabled = true;
2569
2570 // Create three unique fence instances
2571 sp<Fence> layer1Fence = new Fence();
2572 sp<Fence> layer2Fence = new Fence();
2573 sp<Fence> layer3Fence = new Fence();
2574
Lloyd Piquefe0ee9e2019-11-22 16:30:30 -08002575 Output::FrameFences frameFences;
Lloyd Pique07178e32019-11-19 19:15:26 -08002576 frameFences.layerFences.emplace(&mLayer1.hwc2Layer, layer1Fence);
2577 frameFences.layerFences.emplace(&mLayer2.hwc2Layer, layer2Fence);
2578 frameFences.layerFences.emplace(&mLayer3.hwc2Layer, layer3Fence);
2579
2580 EXPECT_CALL(*mRenderSurface, flip());
2581 EXPECT_CALL(mOutput, presentAndGetFrameFences()).WillOnce(Return(frameFences));
2582 EXPECT_CALL(*mRenderSurface, onPresentDisplayCompleted());
2583
2584 // Compare the pointers values of each fence to make sure the correct ones
2585 // are passed. This happens to work with the current implementation, but
2586 // would not survive certain calls like Fence::merge() which would return a
2587 // new instance.
2588 EXPECT_CALL(mLayer1.layerFE,
2589 onLayerDisplayed(Property(&sp<Fence>::get, Eq(layer1Fence.get()))));
2590 EXPECT_CALL(mLayer2.layerFE,
2591 onLayerDisplayed(Property(&sp<Fence>::get, Eq(layer2Fence.get()))));
2592 EXPECT_CALL(mLayer3.layerFE,
2593 onLayerDisplayed(Property(&sp<Fence>::get, Eq(layer3Fence.get()))));
2594
2595 mOutput.postFramebuffer();
2596}
2597
2598TEST_F(OutputPostFramebufferTest, releaseFencesIncludeClientTargetAcquireFence) {
2599 mOutput.mState.isEnabled = true;
2600 mOutput.mState.usesClientComposition = true;
2601
2602 sp<Fence> clientTargetAcquireFence = new Fence();
2603 sp<Fence> layer1Fence = new Fence();
2604 sp<Fence> layer2Fence = new Fence();
2605 sp<Fence> layer3Fence = new Fence();
Lloyd Piquefe0ee9e2019-11-22 16:30:30 -08002606 Output::FrameFences frameFences;
Lloyd Pique07178e32019-11-19 19:15:26 -08002607 frameFences.clientTargetAcquireFence = clientTargetAcquireFence;
2608 frameFences.layerFences.emplace(&mLayer1.hwc2Layer, layer1Fence);
2609 frameFences.layerFences.emplace(&mLayer2.hwc2Layer, layer2Fence);
2610 frameFences.layerFences.emplace(&mLayer3.hwc2Layer, layer3Fence);
2611
2612 EXPECT_CALL(*mRenderSurface, flip());
2613 EXPECT_CALL(mOutput, presentAndGetFrameFences()).WillOnce(Return(frameFences));
2614 EXPECT_CALL(*mRenderSurface, onPresentDisplayCompleted());
2615
2616 // Fence::merge is called, and since none of the fences are actually valid,
2617 // Fence::NO_FENCE is returned and passed to each onLayerDisplayed() call.
2618 // This is the best we can do without creating a real kernel fence object.
2619 EXPECT_CALL(mLayer1.layerFE, onLayerDisplayed(Fence::NO_FENCE));
2620 EXPECT_CALL(mLayer2.layerFE, onLayerDisplayed(Fence::NO_FENCE));
2621 EXPECT_CALL(mLayer3.layerFE, onLayerDisplayed(Fence::NO_FENCE));
2622
2623 mOutput.postFramebuffer();
2624}
2625
2626TEST_F(OutputPostFramebufferTest, releasedLayersSentPresentFence) {
2627 mOutput.mState.isEnabled = true;
2628 mOutput.mState.usesClientComposition = true;
2629
2630 // This should happen even if there are no (current) output layers.
2631 EXPECT_CALL(mOutput, getOutputLayerCount()).WillOnce(Return(0u));
2632
2633 // Load up the released layers with some mock instances
2634 sp<StrictMock<mock::LayerFE>> releasedLayer1{new StrictMock<mock::LayerFE>()};
2635 sp<StrictMock<mock::LayerFE>> releasedLayer2{new StrictMock<mock::LayerFE>()};
2636 sp<StrictMock<mock::LayerFE>> releasedLayer3{new StrictMock<mock::LayerFE>()};
2637 Output::ReleasedLayers layers;
2638 layers.push_back(releasedLayer1);
2639 layers.push_back(releasedLayer2);
2640 layers.push_back(releasedLayer3);
2641 mOutput.setReleasedLayers(std::move(layers));
2642
2643 // Set up a fake present fence
2644 sp<Fence> presentFence = new Fence();
Lloyd Piquefe0ee9e2019-11-22 16:30:30 -08002645 Output::FrameFences frameFences;
Lloyd Pique07178e32019-11-19 19:15:26 -08002646 frameFences.presentFence = presentFence;
2647
2648 EXPECT_CALL(*mRenderSurface, flip());
2649 EXPECT_CALL(mOutput, presentAndGetFrameFences()).WillOnce(Return(frameFences));
2650 EXPECT_CALL(*mRenderSurface, onPresentDisplayCompleted());
2651
2652 // Each released layer should be given the presentFence.
2653 EXPECT_CALL(*releasedLayer1,
2654 onLayerDisplayed(Property(&sp<Fence>::get, Eq(presentFence.get()))));
2655 EXPECT_CALL(*releasedLayer2,
2656 onLayerDisplayed(Property(&sp<Fence>::get, Eq(presentFence.get()))));
2657 EXPECT_CALL(*releasedLayer3,
2658 onLayerDisplayed(Property(&sp<Fence>::get, Eq(presentFence.get()))));
2659
2660 mOutput.postFramebuffer();
2661
2662 // After the call the list of released layers should have been cleared.
2663 EXPECT_TRUE(mOutput.getReleasedLayersForTest().empty());
2664}
Lloyd Piquefaa3f192019-11-14 14:05:09 -08002665
2666/*
Lloyd Pique56eba802019-08-28 15:45:25 -07002667 * Output::composeSurfaces()
2668 */
2669
2670struct OutputComposeSurfacesTest : public testing::Test {
Lloyd Pique6818fa52019-12-03 12:32:13 -08002671 using TestType = OutputComposeSurfacesTest;
Lloyd Pique56eba802019-08-28 15:45:25 -07002672
Lloyd Piquefaa3f192019-11-14 14:05:09 -08002673 struct OutputPartialMock : public OutputPartialMockBase {
Lloyd Pique739afaf2019-11-21 16:40:05 -08002674 // Sets up the helper functions called by the function under test to use
2675 // mock implementations.
Lloyd Pique56eba802019-08-28 15:45:25 -07002676 MOCK_CONST_METHOD0(getSkipColorTransform, bool());
Vishnu Nair3a7346c2019-12-04 08:09:09 -08002677 MOCK_METHOD3(generateClientCompositionRequests,
2678 std::vector<renderengine::LayerSettings>(bool, Region&, ui::Dataspace));
Lloyd Pique56eba802019-08-28 15:45:25 -07002679 MOCK_METHOD2(appendRegionFlashRequests,
2680 void(const Region&, std::vector<renderengine::LayerSettings>&));
2681 MOCK_METHOD1(setExpensiveRenderingExpected, void(bool));
2682 };
2683
2684 OutputComposeSurfacesTest() {
2685 mOutput.setDisplayColorProfileForTest(
2686 std::unique_ptr<DisplayColorProfile>(mDisplayColorProfile));
2687 mOutput.setRenderSurfaceForTest(std::unique_ptr<RenderSurface>(mRenderSurface));
2688
Lloyd Pique6818fa52019-12-03 12:32:13 -08002689 mOutput.mState.frame = kDefaultOutputFrame;
2690 mOutput.mState.viewport = kDefaultOutputViewport;
2691 mOutput.mState.scissor = kDefaultOutputScissor;
2692 mOutput.mState.transform = ui::Transform{kDefaultOutputOrientation};
2693 mOutput.mState.orientation = kDefaultOutputOrientation;
2694 mOutput.mState.dataspace = kDefaultOutputDataspace;
2695 mOutput.mState.colorTransformMatrix = kDefaultColorTransformMat;
2696 mOutput.mState.isSecure = false;
2697 mOutput.mState.needsFiltering = false;
2698 mOutput.mState.usesClientComposition = true;
2699 mOutput.mState.usesDeviceComposition = false;
Lloyd Pique56eba802019-08-28 15:45:25 -07002700
Lloyd Piquea38ea7e2019-04-16 18:10:26 -07002701 EXPECT_CALL(mOutput, getCompositionEngine()).WillRepeatedly(ReturnRef(mCompositionEngine));
Lloyd Pique56eba802019-08-28 15:45:25 -07002702 EXPECT_CALL(mCompositionEngine, getRenderEngine()).WillRepeatedly(ReturnRef(mRenderEngine));
Alec Mourie4034bb2019-11-19 12:45:54 -08002703 EXPECT_CALL(mCompositionEngine, getTimeStats())
2704 .WillRepeatedly(ReturnRef(*mTimeStats.get()));
Lloyd Pique6818fa52019-12-03 12:32:13 -08002705 EXPECT_CALL(*mDisplayColorProfile, getHdrCapabilities())
2706 .WillRepeatedly(ReturnRef(kHdrCapabilities));
Lloyd Pique56eba802019-08-28 15:45:25 -07002707 }
2708
Lloyd Pique6818fa52019-12-03 12:32:13 -08002709 struct ExecuteState : public CallOrderStateMachineHelper<TestType, ExecuteState> {
2710 auto execute() {
2711 getInstance()->mReadyFence = getInstance()->mOutput.composeSurfaces(kDebugRegion);
2712 return nextState<FenceCheckState>();
2713 }
2714 };
2715
2716 struct FenceCheckState : public CallOrderStateMachineHelper<TestType, FenceCheckState> {
2717 void expectNoFenceWasReturned() { EXPECT_FALSE(getInstance()->mReadyFence); }
2718
2719 void expectAFenceWasReturned() { EXPECT_TRUE(getInstance()->mReadyFence); }
2720 };
2721
2722 // Call this member function to start using the mini-DSL defined above.
2723 [[nodiscard]] auto verify() { return ExecuteState::make(this); }
2724
2725 static constexpr uint32_t kDefaultOutputOrientation = TR_IDENT;
2726 static constexpr ui::Dataspace kDefaultOutputDataspace = ui::Dataspace::UNKNOWN;
2727 static constexpr ui::Dataspace kExpensiveOutputDataspace = ui::Dataspace::DISPLAY_P3;
2728 static constexpr float kDefaultMaxLuminance = 0.9f;
2729 static constexpr float kDefaultAvgLuminance = 0.7f;
2730 static constexpr float kDefaultMinLuminance = 0.1f;
2731
2732 static const Rect kDefaultOutputFrame;
2733 static const Rect kDefaultOutputViewport;
2734 static const Rect kDefaultOutputScissor;
2735 static const mat4 kDefaultColorTransformMat;
2736
2737 static const Region kDebugRegion;
2738 static const HdrCapabilities kHdrCapabilities;
2739
Lloyd Pique56eba802019-08-28 15:45:25 -07002740 StrictMock<mock::CompositionEngine> mCompositionEngine;
2741 StrictMock<renderengine::mock::RenderEngine> mRenderEngine;
Alec Mourie4034bb2019-11-19 12:45:54 -08002742 // TODO: make this is a proper mock.
2743 std::shared_ptr<TimeStats> mTimeStats = std::make_shared<android::impl::TimeStats>();
Lloyd Pique56eba802019-08-28 15:45:25 -07002744 mock::DisplayColorProfile* mDisplayColorProfile = new StrictMock<mock::DisplayColorProfile>();
2745 mock::RenderSurface* mRenderSurface = new StrictMock<mock::RenderSurface>();
Lloyd Piquea38ea7e2019-04-16 18:10:26 -07002746 StrictMock<OutputPartialMock> mOutput;
Lloyd Pique56eba802019-08-28 15:45:25 -07002747 sp<GraphicBuffer> mOutputBuffer = new GraphicBuffer();
Lloyd Pique6818fa52019-12-03 12:32:13 -08002748
2749 std::optional<base::unique_fd> mReadyFence;
Lloyd Pique56eba802019-08-28 15:45:25 -07002750};
2751
2752const Rect OutputComposeSurfacesTest::kDefaultOutputFrame{1001, 1002, 1003, 1004};
2753const Rect OutputComposeSurfacesTest::kDefaultOutputViewport{1005, 1006, 1007, 1008};
2754const Rect OutputComposeSurfacesTest::kDefaultOutputScissor{1009, 1010, 1011, 1012};
2755const mat4 OutputComposeSurfacesTest::kDefaultColorTransformMat{mat4() * 0.5};
Lloyd Pique6818fa52019-12-03 12:32:13 -08002756const Region OutputComposeSurfacesTest::kDebugRegion{Rect{100, 101, 102, 103}};
2757const HdrCapabilities OutputComposeSurfacesTest::
2758 kHdrCapabilities{{},
2759 OutputComposeSurfacesTest::kDefaultMaxLuminance,
2760 OutputComposeSurfacesTest::kDefaultAvgLuminance,
2761 OutputComposeSurfacesTest::kDefaultMinLuminance};
Lloyd Pique56eba802019-08-28 15:45:25 -07002762
2763TEST_F(OutputComposeSurfacesTest, doesNothingIfNoClientComposition) {
Lloyd Pique6818fa52019-12-03 12:32:13 -08002764 mOutput.mState.usesClientComposition = false;
Lloyd Pique56eba802019-08-28 15:45:25 -07002765
Lloyd Pique6818fa52019-12-03 12:32:13 -08002766 verify().execute().expectAFenceWasReturned();
Lloyd Pique56eba802019-08-28 15:45:25 -07002767}
2768
Lloyd Pique6818fa52019-12-03 12:32:13 -08002769TEST_F(OutputComposeSurfacesTest, doesMinimalWorkIfDequeueBufferFails) {
2770 EXPECT_CALL(mOutput, getSkipColorTransform()).WillRepeatedly(Return(false));
2771 EXPECT_CALL(*mDisplayColorProfile, hasWideColorGamut()).WillRepeatedly(Return(true));
2772 EXPECT_CALL(mRenderEngine, supportsProtectedContent()).WillRepeatedly(Return(false));
2773 EXPECT_CALL(mOutput, generateClientCompositionRequests(_, _, kDefaultOutputDataspace))
2774 .WillRepeatedly(Return(std::vector<renderengine::LayerSettings>{}));
2775 EXPECT_CALL(mOutput, appendRegionFlashRequests(RegionEq(kDebugRegion), _))
2776 .WillRepeatedly(Return());
Lloyd Pique56eba802019-08-28 15:45:25 -07002777
Lloyd Pique6818fa52019-12-03 12:32:13 -08002778 EXPECT_CALL(*mRenderSurface, dequeueBuffer(_)).WillOnce(Return(nullptr));
Lloyd Pique56eba802019-08-28 15:45:25 -07002779
Lloyd Pique6818fa52019-12-03 12:32:13 -08002780 verify().execute().expectNoFenceWasReturned();
2781}
Lloyd Pique56eba802019-08-28 15:45:25 -07002782
Lloyd Pique6818fa52019-12-03 12:32:13 -08002783TEST_F(OutputComposeSurfacesTest, handlesZeroCompositionRequests) {
2784 EXPECT_CALL(mOutput, getSkipColorTransform()).WillRepeatedly(Return(false));
2785 EXPECT_CALL(*mDisplayColorProfile, hasWideColorGamut()).WillRepeatedly(Return(true));
2786 EXPECT_CALL(mRenderEngine, supportsProtectedContent()).WillRepeatedly(Return(false));
2787 EXPECT_CALL(mOutput, generateClientCompositionRequests(_, _, kDefaultOutputDataspace))
2788 .WillRepeatedly(Return(std::vector<renderengine::LayerSettings>{}));
2789 EXPECT_CALL(mOutput, appendRegionFlashRequests(RegionEq(kDebugRegion), _))
2790 .WillRepeatedly(Return());
Lloyd Pique56eba802019-08-28 15:45:25 -07002791
Lloyd Pique6818fa52019-12-03 12:32:13 -08002792 EXPECT_CALL(*mRenderSurface, dequeueBuffer(_)).WillRepeatedly(Return(mOutputBuffer));
2793 EXPECT_CALL(mRenderEngine, drawLayers(_, IsEmpty(), _, true, _, _))
2794 .WillRepeatedly(Return(NO_ERROR));
Lloyd Pique56eba802019-08-28 15:45:25 -07002795
Lloyd Pique6818fa52019-12-03 12:32:13 -08002796 verify().execute().expectAFenceWasReturned();
2797}
Lloyd Pique56eba802019-08-28 15:45:25 -07002798
Lloyd Pique6818fa52019-12-03 12:32:13 -08002799TEST_F(OutputComposeSurfacesTest, buildsAndRendersRequestList) {
2800 renderengine::LayerSettings r1;
2801 renderengine::LayerSettings r2;
2802
2803 r1.geometry.boundaries = FloatRect{1, 2, 3, 4};
2804 r2.geometry.boundaries = FloatRect{5, 6, 7, 8};
2805
2806 EXPECT_CALL(mOutput, getSkipColorTransform()).WillRepeatedly(Return(false));
2807 EXPECT_CALL(*mDisplayColorProfile, hasWideColorGamut()).WillRepeatedly(Return(true));
2808 EXPECT_CALL(mRenderEngine, supportsProtectedContent()).WillRepeatedly(Return(false));
2809 EXPECT_CALL(mOutput, generateClientCompositionRequests(_, _, kDefaultOutputDataspace))
2810 .WillRepeatedly(Return(std::vector<renderengine::LayerSettings>{r1}));
2811 EXPECT_CALL(mOutput, appendRegionFlashRequests(RegionEq(kDebugRegion), _))
2812 .WillRepeatedly(
2813 Invoke([&](const Region&,
2814 std::vector<renderengine::LayerSettings>& clientCompositionLayers) {
2815 clientCompositionLayers.emplace_back(r2);
2816 }));
2817
2818 EXPECT_CALL(*mRenderSurface, dequeueBuffer(_)).WillRepeatedly(Return(mOutputBuffer));
2819 EXPECT_CALL(mRenderEngine, drawLayers(_, ElementsAreArray({r1, r2}), _, true, _, _))
2820 .WillRepeatedly(Return(NO_ERROR));
2821
2822 verify().execute().expectAFenceWasReturned();
2823}
2824
2825struct OutputComposeSurfacesTest_UsesExpectedDisplaySettings : public OutputComposeSurfacesTest {
2826 OutputComposeSurfacesTest_UsesExpectedDisplaySettings() {
2827 EXPECT_CALL(mRenderEngine, supportsProtectedContent()).WillRepeatedly(Return(false));
2828 EXPECT_CALL(mOutput, generateClientCompositionRequests(_, _, kDefaultOutputDataspace))
2829 .WillRepeatedly(Return(std::vector<renderengine::LayerSettings>{}));
2830 EXPECT_CALL(mOutput, appendRegionFlashRequests(RegionEq(kDebugRegion), _))
2831 .WillRepeatedly(Return());
2832 EXPECT_CALL(*mRenderSurface, dequeueBuffer(_)).WillRepeatedly(Return(mOutputBuffer));
2833 }
2834
2835 struct MixedCompositionState
2836 : public CallOrderStateMachineHelper<TestType, MixedCompositionState> {
2837 auto ifMixedCompositionIs(bool used) {
2838 getInstance()->mOutput.mState.usesDeviceComposition = used;
2839 return nextState<OutputUsesHdrState>();
2840 }
2841 };
2842
2843 struct OutputUsesHdrState : public CallOrderStateMachineHelper<TestType, OutputUsesHdrState> {
2844 auto andIfUsesHdr(bool used) {
2845 EXPECT_CALL(*getInstance()->mDisplayColorProfile, hasWideColorGamut())
2846 .WillOnce(Return(used));
2847 return nextState<SkipColorTransformState>();
2848 }
2849 };
2850
2851 struct SkipColorTransformState
2852 : public CallOrderStateMachineHelper<TestType, SkipColorTransformState> {
2853 auto andIfSkipColorTransform(bool skip) {
2854 // May be called zero or one times.
2855 EXPECT_CALL(getInstance()->mOutput, getSkipColorTransform())
2856 .WillRepeatedly(Return(skip));
2857 return nextState<ExpectDisplaySettingsState>();
2858 }
2859 };
2860
2861 struct ExpectDisplaySettingsState
2862 : public CallOrderStateMachineHelper<TestType, ExpectDisplaySettingsState> {
2863 auto thenExpectDisplaySettingsUsed(renderengine::DisplaySettings settings) {
2864 EXPECT_CALL(getInstance()->mRenderEngine, drawLayers(settings, _, _, true, _, _))
2865 .WillOnce(Return(NO_ERROR));
2866 return nextState<ExecuteState>();
2867 }
2868 };
2869
2870 // Call this member function to start using the mini-DSL defined above.
2871 [[nodiscard]] auto verify() { return MixedCompositionState::make(this); }
2872};
2873
2874TEST_F(OutputComposeSurfacesTest_UsesExpectedDisplaySettings, forHdrMixedComposition) {
2875 verify().ifMixedCompositionIs(true)
2876 .andIfUsesHdr(true)
2877 .andIfSkipColorTransform(false)
2878 .thenExpectDisplaySettingsUsed({kDefaultOutputScissor, kDefaultOutputScissor, mat4(),
2879 kDefaultMaxLuminance, kDefaultOutputDataspace, mat4(),
2880 Region::INVALID_REGION, kDefaultOutputOrientation})
2881 .execute()
2882 .expectAFenceWasReturned();
2883}
2884
2885TEST_F(OutputComposeSurfacesTest_UsesExpectedDisplaySettings, forNonHdrMixedComposition) {
2886 verify().ifMixedCompositionIs(true)
2887 .andIfUsesHdr(false)
2888 .andIfSkipColorTransform(false)
2889 .thenExpectDisplaySettingsUsed({kDefaultOutputScissor, kDefaultOutputScissor, mat4(),
2890 kDefaultMaxLuminance, kDefaultOutputDataspace, mat4(),
2891 Region::INVALID_REGION, kDefaultOutputOrientation})
2892 .execute()
2893 .expectAFenceWasReturned();
2894}
2895
2896TEST_F(OutputComposeSurfacesTest_UsesExpectedDisplaySettings, forHdrOnlyClientComposition) {
2897 verify().ifMixedCompositionIs(false)
2898 .andIfUsesHdr(true)
2899 .andIfSkipColorTransform(false)
2900 .thenExpectDisplaySettingsUsed({kDefaultOutputScissor, kDefaultOutputScissor, mat4(),
2901 kDefaultMaxLuminance, kDefaultOutputDataspace,
2902 kDefaultColorTransformMat, Region::INVALID_REGION,
2903 kDefaultOutputOrientation})
2904 .execute()
2905 .expectAFenceWasReturned();
2906}
2907
2908TEST_F(OutputComposeSurfacesTest_UsesExpectedDisplaySettings, forNonHdrOnlyClientComposition) {
2909 verify().ifMixedCompositionIs(false)
2910 .andIfUsesHdr(false)
2911 .andIfSkipColorTransform(false)
2912 .thenExpectDisplaySettingsUsed({kDefaultOutputScissor, kDefaultOutputScissor, mat4(),
2913 kDefaultMaxLuminance, kDefaultOutputDataspace,
2914 kDefaultColorTransformMat, Region::INVALID_REGION,
2915 kDefaultOutputOrientation})
2916 .execute()
2917 .expectAFenceWasReturned();
2918}
2919
2920TEST_F(OutputComposeSurfacesTest_UsesExpectedDisplaySettings,
2921 usesExpectedDisplaySettingsForHdrOnlyClientCompositionWithSkipClientTransform) {
2922 verify().ifMixedCompositionIs(false)
2923 .andIfUsesHdr(true)
2924 .andIfSkipColorTransform(true)
2925 .thenExpectDisplaySettingsUsed({kDefaultOutputScissor, kDefaultOutputScissor, mat4(),
2926 kDefaultMaxLuminance, kDefaultOutputDataspace, mat4(),
2927 Region::INVALID_REGION, kDefaultOutputOrientation})
2928 .execute()
2929 .expectAFenceWasReturned();
2930}
2931
2932struct OutputComposeSurfacesTest_HandlesProtectedContent : public OutputComposeSurfacesTest {
2933 struct Layer {
2934 Layer() {
2935 EXPECT_CALL(mOutputLayer, getLayer()).WillRepeatedly(ReturnRef(mLayer));
2936 EXPECT_CALL(mLayer, getFEState()).WillRepeatedly(ReturnRef(mLayerFEState));
2937 }
2938
2939 StrictMock<mock::OutputLayer> mOutputLayer;
2940 StrictMock<mock::Layer> mLayer;
2941 LayerFECompositionState mLayerFEState;
2942 };
2943
2944 OutputComposeSurfacesTest_HandlesProtectedContent() {
2945 mLayer1.mLayerFEState.hasProtectedContent = false;
2946 mLayer2.mLayerFEState.hasProtectedContent = false;
2947
2948 EXPECT_CALL(mOutput, getOutputLayerCount()).WillRepeatedly(Return(2u));
2949 EXPECT_CALL(mOutput, getOutputLayerOrderedByZByIndex(0u))
2950 .WillRepeatedly(Return(&mLayer1.mOutputLayer));
2951 EXPECT_CALL(mOutput, getOutputLayerOrderedByZByIndex(1u))
2952 .WillRepeatedly(Return(&mLayer2.mOutputLayer));
2953
2954 EXPECT_CALL(mOutput, getSkipColorTransform()).WillRepeatedly(Return(false));
2955
2956 EXPECT_CALL(*mDisplayColorProfile, hasWideColorGamut()).WillRepeatedly(Return(true));
2957
2958 EXPECT_CALL(mOutput, generateClientCompositionRequests(_, _, _))
2959 .WillRepeatedly(Return(std::vector<renderengine::LayerSettings>{}));
2960 EXPECT_CALL(mOutput, appendRegionFlashRequests(RegionEq(kDebugRegion), _))
2961 .WillRepeatedly(Return());
2962 EXPECT_CALL(*mRenderSurface, dequeueBuffer(_)).WillRepeatedly(Return(mOutputBuffer));
2963 EXPECT_CALL(mRenderEngine, drawLayers(_, _, _, true, _, _))
2964 .WillRepeatedly(Return(NO_ERROR));
2965 }
2966
2967 Layer mLayer1;
2968 Layer mLayer2;
2969};
2970
2971TEST_F(OutputComposeSurfacesTest_HandlesProtectedContent, ifDisplayIsNotSecure) {
2972 mOutput.mState.isSecure = false;
2973 mLayer2.mLayerFEState.hasProtectedContent = true;
2974 EXPECT_CALL(mRenderEngine, supportsProtectedContent()).WillRepeatedly(Return(true));
2975
2976 mOutput.composeSurfaces(kDebugRegion);
2977}
2978
2979TEST_F(OutputComposeSurfacesTest_HandlesProtectedContent, ifRenderEngineDoesNotSupportIt) {
2980 mOutput.mState.isSecure = true;
2981 mLayer2.mLayerFEState.hasProtectedContent = true;
2982 EXPECT_CALL(mRenderEngine, supportsProtectedContent()).WillRepeatedly(Return(false));
2983
2984 mOutput.composeSurfaces(kDebugRegion);
2985}
2986
2987TEST_F(OutputComposeSurfacesTest_HandlesProtectedContent, ifNoProtectedContentLayers) {
2988 mOutput.mState.isSecure = true;
2989 mLayer2.mLayerFEState.hasProtectedContent = false;
2990 EXPECT_CALL(mRenderEngine, supportsProtectedContent()).WillRepeatedly(Return(true));
2991 EXPECT_CALL(mRenderEngine, isProtected).WillOnce(Return(true)).WillOnce(Return(false));
2992 EXPECT_CALL(*mRenderSurface, isProtected).WillOnce(Return(true));
2993 EXPECT_CALL(mRenderEngine, useProtectedContext(false));
2994 EXPECT_CALL(*mRenderSurface, setProtected(false));
2995
2996 mOutput.composeSurfaces(kDebugRegion);
2997}
2998
2999TEST_F(OutputComposeSurfacesTest_HandlesProtectedContent, ifNotEnabled) {
3000 mOutput.mState.isSecure = true;
3001 mLayer2.mLayerFEState.hasProtectedContent = true;
3002 EXPECT_CALL(mRenderEngine, supportsProtectedContent()).WillRepeatedly(Return(true));
3003
3004 // For this test, we also check the call order of key functions.
3005 InSequence seq;
3006
3007 EXPECT_CALL(mRenderEngine, isProtected).WillOnce(Return(false));
3008 EXPECT_CALL(mRenderEngine, useProtectedContext(true));
3009 EXPECT_CALL(*mRenderSurface, isProtected).WillOnce(Return(false));
3010 EXPECT_CALL(mRenderEngine, isProtected).WillOnce(Return(true));
3011 EXPECT_CALL(*mRenderSurface, setProtected(true));
3012 // Must happen after setting the protected content state.
3013 EXPECT_CALL(*mRenderSurface, dequeueBuffer(_)).WillRepeatedly(Return(mOutputBuffer));
3014 EXPECT_CALL(mRenderEngine, drawLayers(_, _, _, true, _, _)).WillOnce(Return(NO_ERROR));
3015
3016 mOutput.composeSurfaces(kDebugRegion);
3017}
3018
3019TEST_F(OutputComposeSurfacesTest_HandlesProtectedContent, ifAlreadyEnabledEverywhere) {
3020 mOutput.mState.isSecure = true;
3021 mLayer2.mLayerFEState.hasProtectedContent = true;
3022 EXPECT_CALL(mRenderEngine, supportsProtectedContent()).WillRepeatedly(Return(true));
3023 EXPECT_CALL(mRenderEngine, isProtected).WillOnce(Return(true));
3024 EXPECT_CALL(*mRenderSurface, isProtected).WillOnce(Return(true));
3025
3026 mOutput.composeSurfaces(kDebugRegion);
3027}
3028
3029TEST_F(OutputComposeSurfacesTest_HandlesProtectedContent, ifFailsToEnableInRenderEngine) {
3030 mOutput.mState.isSecure = true;
3031 mLayer2.mLayerFEState.hasProtectedContent = true;
3032 EXPECT_CALL(mRenderEngine, supportsProtectedContent()).WillRepeatedly(Return(true));
3033 EXPECT_CALL(mRenderEngine, isProtected).WillOnce(Return(false)).WillOnce(Return(false));
3034 EXPECT_CALL(*mRenderSurface, isProtected).WillOnce(Return(false));
3035 EXPECT_CALL(mRenderEngine, useProtectedContext(true));
3036
3037 mOutput.composeSurfaces(kDebugRegion);
3038}
3039
3040TEST_F(OutputComposeSurfacesTest_HandlesProtectedContent, ifAlreadyEnabledInRenderEngine) {
3041 mOutput.mState.isSecure = true;
3042 mLayer2.mLayerFEState.hasProtectedContent = true;
3043 EXPECT_CALL(mRenderEngine, supportsProtectedContent()).WillRepeatedly(Return(true));
3044 EXPECT_CALL(mRenderEngine, isProtected).WillOnce(Return(true)).WillOnce(Return(true));
3045 EXPECT_CALL(*mRenderSurface, isProtected).WillOnce(Return(false));
3046 EXPECT_CALL(*mRenderSurface, setProtected(true));
3047
3048 mOutput.composeSurfaces(kDebugRegion);
3049}
3050
3051TEST_F(OutputComposeSurfacesTest_HandlesProtectedContent, ifAlreadyEnabledInRenderSurface) {
3052 mOutput.mState.isSecure = true;
3053 mLayer2.mLayerFEState.hasProtectedContent = true;
3054 EXPECT_CALL(mRenderEngine, supportsProtectedContent()).WillRepeatedly(Return(true));
3055 EXPECT_CALL(mRenderEngine, isProtected).WillOnce(Return(false));
3056 EXPECT_CALL(*mRenderSurface, isProtected).WillOnce(Return(true));
3057 EXPECT_CALL(mRenderEngine, useProtectedContext(true));
3058
3059 mOutput.composeSurfaces(kDebugRegion);
3060}
3061
3062struct OutputComposeSurfacesTest_SetsExpensiveRendering : public OutputComposeSurfacesTest {
3063 OutputComposeSurfacesTest_SetsExpensiveRendering() {
3064 EXPECT_CALL(mOutput, getSkipColorTransform()).WillRepeatedly(Return(false));
3065 EXPECT_CALL(*mDisplayColorProfile, hasWideColorGamut()).WillRepeatedly(Return(true));
3066 EXPECT_CALL(mRenderEngine, supportsProtectedContent()).WillRepeatedly(Return(false));
3067 EXPECT_CALL(mOutput, appendRegionFlashRequests(RegionEq(kDebugRegion), _))
3068 .WillRepeatedly(Return());
3069 EXPECT_CALL(*mRenderSurface, dequeueBuffer(_)).WillRepeatedly(Return(mOutputBuffer));
3070 }
3071};
3072
3073TEST_F(OutputComposeSurfacesTest_SetsExpensiveRendering, IfExepensiveOutputDataspaceIsUsed) {
3074 mOutput.mState.dataspace = kExpensiveOutputDataspace;
3075
3076 EXPECT_CALL(mOutput, generateClientCompositionRequests(_, _, kExpensiveOutputDataspace))
3077 .WillOnce(Return(std::vector<renderengine::LayerSettings>{}));
3078
3079 // For this test, we also check the call order of key functions.
3080 InSequence seq;
3081
3082 EXPECT_CALL(mOutput, setExpensiveRenderingExpected(true));
3083 EXPECT_CALL(mRenderEngine, drawLayers(_, _, _, true, _, _)).WillOnce(Return(NO_ERROR));
3084 EXPECT_CALL(mOutput, setExpensiveRenderingExpected(false));
3085
3086 mOutput.composeSurfaces(kDebugRegion);
Lloyd Pique56eba802019-08-28 15:45:25 -07003087}
3088
3089/*
3090 * Output::generateClientCompositionRequests()
3091 */
3092
3093struct GenerateClientCompositionRequestsTest : public testing::Test {
Lloyd Piquefaa3f192019-11-14 14:05:09 -08003094 struct OutputPartialMock : public OutputPartialMockBase {
Lloyd Piquea38ea7e2019-04-16 18:10:26 -07003095 // compositionengine::Output overrides
Lloyd Pique56eba802019-08-28 15:45:25 -07003096 std::vector<renderengine::LayerSettings> generateClientCompositionRequests(
Vishnu Nair3a7346c2019-12-04 08:09:09 -08003097 bool supportsProtectedContent, Region& clearRegion,
3098 ui::Dataspace dataspace) override {
Lloyd Pique56eba802019-08-28 15:45:25 -07003099 return impl::Output::generateClientCompositionRequests(supportsProtectedContent,
Vishnu Nair3a7346c2019-12-04 08:09:09 -08003100 clearRegion, dataspace);
Lloyd Pique56eba802019-08-28 15:45:25 -07003101 }
3102 };
3103
3104 GenerateClientCompositionRequestsTest() {
3105 mOutput.setDisplayColorProfileForTest(
3106 std::unique_ptr<DisplayColorProfile>(mDisplayColorProfile));
3107 mOutput.setRenderSurfaceForTest(std::unique_ptr<RenderSurface>(mRenderSurface));
3108 }
3109
Lloyd Pique56eba802019-08-28 15:45:25 -07003110 mock::DisplayColorProfile* mDisplayColorProfile = new StrictMock<mock::DisplayColorProfile>();
3111 mock::RenderSurface* mRenderSurface = new StrictMock<mock::RenderSurface>();
Lloyd Piquea38ea7e2019-04-16 18:10:26 -07003112 StrictMock<OutputPartialMock> mOutput;
Lloyd Pique56eba802019-08-28 15:45:25 -07003113};
3114
3115// TODO(b/121291683): Add more unit test coverage for generateClientCompositionRequests
3116
3117TEST_F(GenerateClientCompositionRequestsTest, worksForLandscapeModeSplitScreen) {
3118 // In split-screen landscape mode, the screen is rotated 90 degrees, with
3119 // one layer on the left covering the left side of the output, and one layer
3120 // on the right covering that side of the output.
3121
Lloyd Pique01c77c12019-04-17 12:48:32 -07003122 StrictMock<mock::OutputLayer> leftOutputLayer;
3123 StrictMock<mock::OutputLayer> rightOutputLayer;
Lloyd Pique56eba802019-08-28 15:45:25 -07003124
3125 StrictMock<mock::Layer> leftLayer;
3126 StrictMock<mock::LayerFE> leftLayerFE;
3127 StrictMock<mock::Layer> rightLayer;
3128 StrictMock<mock::LayerFE> rightLayerFE;
3129
3130 impl::OutputLayerCompositionState leftOutputLayerState;
3131 leftOutputLayerState.clearClientTarget = false;
Lloyd Piquea2468662019-03-07 21:31:06 -08003132 leftOutputLayerState.visibleRegion = Region{Rect{0, 0, 1000, 1000}};
Lloyd Pique56eba802019-08-28 15:45:25 -07003133
Lloyd Pique9755fb72019-03-26 14:44:40 -07003134 LayerFECompositionState leftLayerFEState;
3135 leftLayerFEState.isOpaque = true;
Lloyd Pique56eba802019-08-28 15:45:25 -07003136
3137 const half3 leftLayerColor{1.f, 0.f, 0.f};
3138 renderengine::LayerSettings leftLayerRESettings;
3139 leftLayerRESettings.source.solidColor = leftLayerColor;
3140
3141 impl::OutputLayerCompositionState rightOutputLayerState;
3142 rightOutputLayerState.clearClientTarget = false;
Lloyd Piquea2468662019-03-07 21:31:06 -08003143 rightOutputLayerState.visibleRegion = Region{Rect{1000, 0, 2000, 1000}};
Lloyd Pique56eba802019-08-28 15:45:25 -07003144
Lloyd Pique9755fb72019-03-26 14:44:40 -07003145 LayerFECompositionState rightLayerFEState;
3146 rightLayerFEState.isOpaque = true;
Lloyd Pique56eba802019-08-28 15:45:25 -07003147
3148 const half3 rightLayerColor{0.f, 1.f, 0.f};
3149 renderengine::LayerSettings rightLayerRESettings;
3150 rightLayerRESettings.source.solidColor = rightLayerColor;
3151
Lloyd Pique01c77c12019-04-17 12:48:32 -07003152 EXPECT_CALL(leftOutputLayer, getState()).WillRepeatedly(ReturnRef(leftOutputLayerState));
3153 EXPECT_CALL(leftOutputLayer, getLayer()).WillRepeatedly(ReturnRef(leftLayer));
3154 EXPECT_CALL(leftOutputLayer, getLayerFE()).WillRepeatedly(ReturnRef(leftLayerFE));
3155 EXPECT_CALL(leftOutputLayer, requiresClientComposition()).WillRepeatedly(Return(true));
3156 EXPECT_CALL(leftOutputLayer, needsFiltering()).WillRepeatedly(Return(false));
Lloyd Pique9755fb72019-03-26 14:44:40 -07003157 EXPECT_CALL(leftLayer, getFEState()).WillRepeatedly(ReturnRef(leftLayerFEState));
Lloyd Pique56eba802019-08-28 15:45:25 -07003158 EXPECT_CALL(leftLayerFE, prepareClientComposition(_)).WillOnce(Return(leftLayerRESettings));
Vishnu Nair3a7346c2019-12-04 08:09:09 -08003159 EXPECT_CALL(leftLayerFE, prepareShadowClientComposition(_, _, _))
3160 .WillOnce(Return(std::optional<renderengine::LayerSettings>()));
Adithya Srinivasanb69e0762019-11-11 18:39:53 -08003161 EXPECT_CALL(leftOutputLayer, editState()).WillRepeatedly(ReturnRef(leftOutputLayerState));
Lloyd Pique56eba802019-08-28 15:45:25 -07003162
Lloyd Pique01c77c12019-04-17 12:48:32 -07003163 EXPECT_CALL(rightOutputLayer, getState()).WillRepeatedly(ReturnRef(rightOutputLayerState));
3164 EXPECT_CALL(rightOutputLayer, getLayer()).WillRepeatedly(ReturnRef(rightLayer));
3165 EXPECT_CALL(rightOutputLayer, getLayerFE()).WillRepeatedly(ReturnRef(rightLayerFE));
3166 EXPECT_CALL(rightOutputLayer, requiresClientComposition()).WillRepeatedly(Return(true));
3167 EXPECT_CALL(rightOutputLayer, needsFiltering()).WillRepeatedly(Return(false));
Lloyd Pique9755fb72019-03-26 14:44:40 -07003168 EXPECT_CALL(rightLayer, getFEState()).WillRepeatedly(ReturnRef(rightLayerFEState));
Lloyd Pique56eba802019-08-28 15:45:25 -07003169 EXPECT_CALL(rightLayerFE, prepareClientComposition(_)).WillOnce(Return(rightLayerRESettings));
Vishnu Nair3a7346c2019-12-04 08:09:09 -08003170 EXPECT_CALL(rightLayerFE, prepareShadowClientComposition(_, _, _))
3171 .WillOnce(Return(std::optional<renderengine::LayerSettings>()));
Adithya Srinivasanb69e0762019-11-11 18:39:53 -08003172 EXPECT_CALL(rightOutputLayer, editState()).WillRepeatedly(ReturnRef(rightOutputLayerState));
Lloyd Pique56eba802019-08-28 15:45:25 -07003173
Lloyd Pique01c77c12019-04-17 12:48:32 -07003174 EXPECT_CALL(mOutput, getOutputLayerCount()).WillRepeatedly(Return(2u));
3175 EXPECT_CALL(mOutput, getOutputLayerOrderedByZByIndex(0u))
3176 .WillRepeatedly(Return(&leftOutputLayer));
3177 EXPECT_CALL(mOutput, getOutputLayerOrderedByZByIndex(1u))
3178 .WillRepeatedly(Return(&rightOutputLayer));
Lloyd Pique56eba802019-08-28 15:45:25 -07003179
3180 const Rect kPortraitFrame(0, 0, 1000, 2000);
3181 const Rect kPortraitViewport(0, 0, 2000, 1000);
3182 const Rect kPortraitScissor(0, 0, 1000, 2000);
3183 const uint32_t kPortraitOrientation = TR_ROT_90;
3184
3185 mOutput.editState().frame = kPortraitFrame;
3186 mOutput.editState().viewport = kPortraitViewport;
3187 mOutput.editState().scissor = kPortraitScissor;
3188 mOutput.editState().transform = ui::Transform{kPortraitOrientation};
3189 mOutput.editState().orientation = kPortraitOrientation;
3190 mOutput.editState().needsFiltering = true;
3191 mOutput.editState().isSecure = false;
3192
3193 constexpr bool supportsProtectedContent = false;
3194 Region clearRegion;
Vishnu Nair3a7346c2019-12-04 08:09:09 -08003195 auto requests = mOutput.generateClientCompositionRequests(supportsProtectedContent, clearRegion,
3196 mOutput.getState().targetDataspace);
Lloyd Pique56eba802019-08-28 15:45:25 -07003197
3198 ASSERT_EQ(2u, requests.size());
3199 EXPECT_EQ(leftLayerColor, requests[0].source.solidColor);
3200 EXPECT_EQ(rightLayerColor, requests[1].source.solidColor);
3201}
3202
3203TEST_F(GenerateClientCompositionRequestsTest, ignoresLayersThatDoNotIntersectWithViewport) {
3204 // Layers whose visible region does not intersect with the viewport will be
3205 // skipped when generating client composition request state.
3206
Lloyd Pique01c77c12019-04-17 12:48:32 -07003207 StrictMock<mock::OutputLayer> outputLayer;
Lloyd Pique56eba802019-08-28 15:45:25 -07003208 StrictMock<mock::Layer> layer;
3209 StrictMock<mock::LayerFE> layerFE;
3210
3211 impl::OutputLayerCompositionState outputLayerState;
3212 outputLayerState.clearClientTarget = false;
Lloyd Piquea2468662019-03-07 21:31:06 -08003213 outputLayerState.visibleRegion = Region{Rect{3000, 0, 4000, 1000}};
Lloyd Pique56eba802019-08-28 15:45:25 -07003214
Lloyd Pique9755fb72019-03-26 14:44:40 -07003215 LayerFECompositionState layerFEState;
3216 layerFEState.isOpaque = true;
Lloyd Pique56eba802019-08-28 15:45:25 -07003217
Lloyd Pique01c77c12019-04-17 12:48:32 -07003218 EXPECT_CALL(outputLayer, getState()).WillRepeatedly(ReturnRef(outputLayerState));
3219 EXPECT_CALL(outputLayer, getLayer()).WillRepeatedly(ReturnRef(layer));
3220 EXPECT_CALL(outputLayer, getLayerFE()).WillRepeatedly(ReturnRef(layerFE));
3221 EXPECT_CALL(outputLayer, requiresClientComposition()).WillRepeatedly(Return(true));
3222 EXPECT_CALL(outputLayer, needsFiltering()).WillRepeatedly(Return(false));
Lloyd Pique9755fb72019-03-26 14:44:40 -07003223 EXPECT_CALL(layer, getFEState()).WillRepeatedly(ReturnRef(layerFEState));
Lloyd Pique56eba802019-08-28 15:45:25 -07003224 EXPECT_CALL(layerFE, prepareClientComposition(_)).Times(0);
Adithya Srinivasanb69e0762019-11-11 18:39:53 -08003225 EXPECT_CALL(outputLayer, editState()).WillRepeatedly(ReturnRef(outputLayerState));
Lloyd Pique56eba802019-08-28 15:45:25 -07003226
Lloyd Pique01c77c12019-04-17 12:48:32 -07003227 EXPECT_CALL(mOutput, getOutputLayerCount()).WillRepeatedly(Return(1u));
3228 EXPECT_CALL(mOutput, getOutputLayerOrderedByZByIndex(0u)).WillRepeatedly(Return(&outputLayer));
Lloyd Pique56eba802019-08-28 15:45:25 -07003229
3230 const Rect kPortraitFrame(0, 0, 1000, 2000);
3231 const Rect kPortraitViewport(0, 0, 2000, 1000);
3232 const Rect kPortraitScissor(0, 0, 1000, 2000);
3233 const uint32_t kPortraitOrientation = TR_ROT_90;
3234
3235 mOutput.editState().frame = kPortraitFrame;
3236 mOutput.editState().viewport = kPortraitViewport;
3237 mOutput.editState().scissor = kPortraitScissor;
3238 mOutput.editState().transform = ui::Transform{kPortraitOrientation};
3239 mOutput.editState().orientation = kPortraitOrientation;
3240 mOutput.editState().needsFiltering = true;
3241 mOutput.editState().isSecure = false;
3242
3243 constexpr bool supportsProtectedContent = false;
3244 Region clearRegion;
Vishnu Nair3a7346c2019-12-04 08:09:09 -08003245 auto requests = mOutput.generateClientCompositionRequests(supportsProtectedContent, clearRegion,
3246 mOutput.getState().targetDataspace);
Lloyd Pique56eba802019-08-28 15:45:25 -07003247
3248 EXPECT_EQ(0u, requests.size());
3249}
3250
Lloyd Piquec2d54d42019-08-28 18:04:21 -07003251TEST_F(GenerateClientCompositionRequestsTest, clearsDeviceLayesAfterFirst) {
3252 // If client composition is performed with some layers set to use device
3253 // composition, device layers after the first layer (device or client) will
3254 // clear the frame buffer if they are opaque and if that layer has a flag
3255 // set to do so. The first layer is skipped as the frame buffer is already
3256 // expected to be clear.
3257
Lloyd Pique01c77c12019-04-17 12:48:32 -07003258 StrictMock<mock::OutputLayer> leftOutputLayer;
3259 StrictMock<mock::OutputLayer> rightOutputLayer;
Lloyd Piquec2d54d42019-08-28 18:04:21 -07003260
3261 StrictMock<mock::Layer> leftLayer;
3262 StrictMock<mock::LayerFE> leftLayerFE;
3263 StrictMock<mock::Layer> rightLayer;
3264 StrictMock<mock::LayerFE> rightLayerFE;
3265
3266 impl::OutputLayerCompositionState leftOutputLayerState;
3267 leftOutputLayerState.clearClientTarget = true;
Lloyd Piquea2468662019-03-07 21:31:06 -08003268 leftOutputLayerState.visibleRegion = Region{Rect{0, 0, 1000, 1000}};
Lloyd Piquec2d54d42019-08-28 18:04:21 -07003269
Lloyd Pique9755fb72019-03-26 14:44:40 -07003270 LayerFECompositionState leftLayerFEState;
3271 leftLayerFEState.isOpaque = true;
Lloyd Piquec2d54d42019-08-28 18:04:21 -07003272
3273 impl::OutputLayerCompositionState rightOutputLayerState;
3274 rightOutputLayerState.clearClientTarget = true;
Lloyd Piquea2468662019-03-07 21:31:06 -08003275 rightOutputLayerState.visibleRegion = Region{Rect{1000, 0, 2000, 1000}};
Lloyd Piquec2d54d42019-08-28 18:04:21 -07003276
Lloyd Pique9755fb72019-03-26 14:44:40 -07003277 LayerFECompositionState rightLayerFEState;
3278 rightLayerFEState.isOpaque = true;
Lloyd Piquec2d54d42019-08-28 18:04:21 -07003279
3280 const half3 rightLayerColor{0.f, 1.f, 0.f};
3281 renderengine::LayerSettings rightLayerRESettings;
3282 rightLayerRESettings.geometry.boundaries = FloatRect{456, 0, 0, 0};
3283 rightLayerRESettings.source.solidColor = rightLayerColor;
3284
Lloyd Pique01c77c12019-04-17 12:48:32 -07003285 EXPECT_CALL(leftOutputLayer, getState()).WillRepeatedly(ReturnRef(leftOutputLayerState));
3286 EXPECT_CALL(leftOutputLayer, getLayer()).WillRepeatedly(ReturnRef(leftLayer));
3287 EXPECT_CALL(leftOutputLayer, getLayerFE()).WillRepeatedly(ReturnRef(leftLayerFE));
3288 EXPECT_CALL(leftOutputLayer, requiresClientComposition()).WillRepeatedly(Return(false));
3289 EXPECT_CALL(leftOutputLayer, needsFiltering()).WillRepeatedly(Return(false));
Lloyd Pique9755fb72019-03-26 14:44:40 -07003290 EXPECT_CALL(leftLayer, getFEState()).WillRepeatedly(ReturnRef(leftLayerFEState));
Adithya Srinivasanb69e0762019-11-11 18:39:53 -08003291 EXPECT_CALL(leftOutputLayer, editState()).WillRepeatedly(ReturnRef(leftOutputLayerState));
Lloyd Piquec2d54d42019-08-28 18:04:21 -07003292
Lloyd Pique01c77c12019-04-17 12:48:32 -07003293 EXPECT_CALL(rightOutputLayer, getState()).WillRepeatedly(ReturnRef(rightOutputLayerState));
3294 EXPECT_CALL(rightOutputLayer, getLayer()).WillRepeatedly(ReturnRef(rightLayer));
3295 EXPECT_CALL(rightOutputLayer, getLayerFE()).WillRepeatedly(ReturnRef(rightLayerFE));
3296 EXPECT_CALL(rightOutputLayer, requiresClientComposition()).WillRepeatedly(Return(false));
3297 EXPECT_CALL(rightOutputLayer, needsFiltering()).WillRepeatedly(Return(false));
Lloyd Pique9755fb72019-03-26 14:44:40 -07003298 EXPECT_CALL(rightLayer, getFEState()).WillRepeatedly(ReturnRef(rightLayerFEState));
Lloyd Piquec2d54d42019-08-28 18:04:21 -07003299 EXPECT_CALL(rightLayerFE, prepareClientComposition(_)).WillOnce(Return(rightLayerRESettings));
Adithya Srinivasanb69e0762019-11-11 18:39:53 -08003300 EXPECT_CALL(rightOutputLayer, editState()).WillRepeatedly(ReturnRef(rightOutputLayerState));
Lloyd Piquec2d54d42019-08-28 18:04:21 -07003301
Lloyd Pique01c77c12019-04-17 12:48:32 -07003302 EXPECT_CALL(mOutput, getOutputLayerCount()).WillRepeatedly(Return(2u));
3303 EXPECT_CALL(mOutput, getOutputLayerOrderedByZByIndex(0u))
3304 .WillRepeatedly(Return(&leftOutputLayer));
3305 EXPECT_CALL(mOutput, getOutputLayerOrderedByZByIndex(1u))
3306 .WillRepeatedly(Return(&rightOutputLayer));
Lloyd Piquec2d54d42019-08-28 18:04:21 -07003307
3308 const Rect kPortraitFrame(0, 0, 1000, 2000);
3309 const Rect kPortraitViewport(0, 0, 2000, 1000);
3310 const Rect kPortraitScissor(0, 0, 1000, 2000);
3311 const uint32_t kPortraitOrientation = TR_ROT_90;
3312
3313 mOutput.editState().frame = kPortraitFrame;
3314 mOutput.editState().viewport = kPortraitViewport;
3315 mOutput.editState().scissor = kPortraitScissor;
3316 mOutput.editState().transform = ui::Transform{kPortraitOrientation};
3317 mOutput.editState().orientation = kPortraitOrientation;
3318 mOutput.editState().needsFiltering = true;
3319 mOutput.editState().isSecure = false;
3320
3321 constexpr bool supportsProtectedContent = false;
3322 Region clearRegion;
Vishnu Nair3a7346c2019-12-04 08:09:09 -08003323 auto requests = mOutput.generateClientCompositionRequests(supportsProtectedContent, clearRegion,
3324 mOutput.getState().targetDataspace);
Lloyd Piquec2d54d42019-08-28 18:04:21 -07003325
3326 const half3 clearColor{0.f, 0.f, 0.f};
3327
3328 ASSERT_EQ(1u, requests.size());
3329 EXPECT_EQ(456.f, requests[0].geometry.boundaries.left);
3330 EXPECT_EQ(clearColor, requests[0].source.solidColor);
3331}
3332
Lloyd Pique32cbe282018-10-19 13:09:22 -07003333} // namespace
3334} // namespace android::compositionengine