blob: 6e8d3dfa7f6b9d5b91f9554f8b86e15316bf902b [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 Piquea4863342019-12-04 18:45:02 -080044using testing::ByRef;
Lloyd Pique17ca7422019-11-14 14:24:10 -080045using testing::DoAll;
Vishnu Nair9b079a22020-01-21 14:36:08 -080046using testing::ElementsAre;
Lloyd Pique6818fa52019-12-03 12:32:13 -080047using testing::ElementsAreArray;
Lloyd Pique07178e32019-11-19 19:15:26 -080048using testing::Eq;
Lloyd Piquefaa3f192019-11-14 14:05:09 -080049using testing::InSequence;
Lloyd Pique6818fa52019-12-03 12:32:13 -080050using testing::Invoke;
51using testing::IsEmpty;
Lloyd Pique17ca7422019-11-14 14:24:10 -080052using testing::Mock;
Vishnu Nair9b079a22020-01-21 14:36:08 -080053using testing::Pointee;
Lloyd Pique07178e32019-11-19 19:15:26 -080054using testing::Property;
Lloyd Piquefaa3f192019-11-14 14:05:09 -080055using testing::Ref;
Lloyd Pique31cb2942018-10-19 17:23:03 -070056using testing::Return;
Lloyd Pique32cbe282018-10-19 13:09:22 -070057using testing::ReturnRef;
Lloyd Pique17ca7422019-11-14 14:24:10 -080058using testing::SetArgPointee;
Lloyd Pique32cbe282018-10-19 13:09:22 -070059using testing::StrictMock;
60
Lloyd Pique56eba802019-08-28 15:45:25 -070061constexpr auto TR_IDENT = 0u;
62constexpr auto TR_ROT_90 = HAL_TRANSFORM_ROT_90;
Vishnu Nair9b079a22020-01-21 14:36:08 -080063constexpr auto MAX_CLIENT_COMPOSITION_CACHE_SIZE = 3;
Lloyd Pique56eba802019-08-28 15:45:25 -070064
Lloyd Pique3eb1b212019-03-07 21:15:40 -080065const mat4 kIdentity;
Lloyd Pique0a456232020-01-16 17:51:13 -080066const mat4 kNonIdentityHalf = mat4() * 0.5f;
67const mat4 kNonIdentityQuarter = mat4() * 0.25f;
Lloyd Pique3eb1b212019-03-07 21:15:40 -080068
Lloyd Pique17ca7422019-11-14 14:24:10 -080069constexpr OutputColorSetting kVendorSpecifiedOutputColorSetting =
70 static_cast<OutputColorSetting>(0x100);
71
Lloyd Piquefaa3f192019-11-14 14:05:09 -080072struct OutputPartialMockBase : public impl::Output {
73 // compositionengine::Output overrides
74 const OutputCompositionState& getState() const override { return mState; }
75 OutputCompositionState& editState() override { return mState; }
76
77 // Use mocks for all the remaining virtual functions
78 // not implemented by the base implementation class.
79 MOCK_CONST_METHOD0(getOutputLayerCount, size_t());
80 MOCK_CONST_METHOD1(getOutputLayerOrderedByZByIndex, compositionengine::OutputLayer*(size_t));
81 MOCK_METHOD3(ensureOutputLayer,
82 compositionengine::OutputLayer*(std::optional<size_t>,
83 const std::shared_ptr<compositionengine::Layer>&,
84 const sp<LayerFE>&));
85 MOCK_METHOD0(finalizePendingOutputLayers, void());
86 MOCK_METHOD0(clearOutputLayers, void());
87 MOCK_CONST_METHOD1(dumpState, void(std::string&));
88 MOCK_CONST_METHOD0(getCompositionEngine, const CompositionEngine&());
89 MOCK_METHOD2(injectOutputLayerForTest,
90 compositionengine::OutputLayer*(const std::shared_ptr<compositionengine::Layer>&,
91 const sp<LayerFE>&));
92 MOCK_METHOD1(injectOutputLayerForTest, void(std::unique_ptr<OutputLayer>));
93
94 impl::OutputCompositionState mState;
95};
96
Lloyd Pique66d68602019-02-13 14:23:31 -080097struct OutputTest : public testing::Test {
Lloyd Pique01c77c12019-04-17 12:48:32 -070098 class Output : public impl::Output {
99 public:
100 using impl::Output::injectOutputLayerForTest;
101 virtual void injectOutputLayerForTest(std::unique_ptr<compositionengine::OutputLayer>) = 0;
102 };
103
104 static std::shared_ptr<Output> createOutput(
105 const compositionengine::CompositionEngine& compositionEngine) {
106 return impl::createOutputTemplated<Output>(compositionEngine);
107 }
108
Lloyd Pique31cb2942018-10-19 17:23:03 -0700109 OutputTest() {
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700110 mOutput->setDisplayColorProfileForTest(
Lloyd Pique3d0c02e2018-10-19 18:38:12 -0700111 std::unique_ptr<DisplayColorProfile>(mDisplayColorProfile));
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700112 mOutput->setRenderSurfaceForTest(std::unique_ptr<RenderSurface>(mRenderSurface));
Lloyd Piqueef958122019-02-05 18:00:12 -0800113
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700114 mOutput->editState().bounds = kDefaultDisplaySize;
Lloyd Pique31cb2942018-10-19 17:23:03 -0700115 }
Lloyd Pique32cbe282018-10-19 13:09:22 -0700116
Lloyd Piqueef958122019-02-05 18:00:12 -0800117 static const Rect kDefaultDisplaySize;
118
Lloyd Pique32cbe282018-10-19 13:09:22 -0700119 StrictMock<mock::CompositionEngine> mCompositionEngine;
Lloyd Pique3d0c02e2018-10-19 18:38:12 -0700120 mock::DisplayColorProfile* mDisplayColorProfile = new StrictMock<mock::DisplayColorProfile>();
Lloyd Pique31cb2942018-10-19 17:23:03 -0700121 mock::RenderSurface* mRenderSurface = new StrictMock<mock::RenderSurface>();
Lloyd Pique01c77c12019-04-17 12:48:32 -0700122 std::shared_ptr<Output> mOutput = createOutput(mCompositionEngine);
Lloyd Pique32cbe282018-10-19 13:09:22 -0700123};
124
Lloyd Piquec0ee6ba2019-11-14 12:55:53 -0800125// Extension of the base test useful for checking interactions with the LayerFE
126// functions to latch composition state.
127struct OutputLatchFEStateTest : public OutputTest {
128 OutputLatchFEStateTest() {
129 EXPECT_CALL(*mOutputLayer1, getLayer()).WillRepeatedly(ReturnRef(mLayer1));
130 EXPECT_CALL(*mOutputLayer2, getLayer()).WillRepeatedly(ReturnRef(mLayer2));
131 EXPECT_CALL(*mOutputLayer3, getLayer()).WillRepeatedly(ReturnRef(mLayer3));
132
133 EXPECT_CALL(*mOutputLayer1, getLayerFE()).WillRepeatedly(ReturnRef(mLayer1FE));
134 EXPECT_CALL(*mOutputLayer2, getLayerFE()).WillRepeatedly(ReturnRef(mLayer2FE));
135 EXPECT_CALL(*mOutputLayer3, getLayerFE()).WillRepeatedly(ReturnRef(mLayer3FE));
136
137 EXPECT_CALL(mLayer1, editFEState()).WillRepeatedly(ReturnRef(mLayer1FEState));
138 EXPECT_CALL(mLayer2, editFEState()).WillRepeatedly(ReturnRef(mLayer2FEState));
139 EXPECT_CALL(mLayer3, editFEState()).WillRepeatedly(ReturnRef(mLayer3FEState));
Lucas Dupin19c8f0e2019-11-25 17:55:44 -0800140
141 EXPECT_CALL(mLayer1, getFEState()).WillRepeatedly(ReturnRef(mLayer1FEState));
142 EXPECT_CALL(mLayer2, getFEState()).WillRepeatedly(ReturnRef(mLayer2FEState));
143 EXPECT_CALL(mLayer3, getFEState()).WillRepeatedly(ReturnRef(mLayer3FEState));
Lloyd Piquec0ee6ba2019-11-14 12:55:53 -0800144 }
145
146 void injectLayer(std::unique_ptr<mock::OutputLayer> layer) {
147 mOutput->injectOutputLayerForTest(std::unique_ptr<OutputLayer>(layer.release()));
148 }
149
150 std::unique_ptr<mock::OutputLayer> mOutputLayer1{new StrictMock<mock::OutputLayer>};
151 std::unique_ptr<mock::OutputLayer> mOutputLayer2{new StrictMock<mock::OutputLayer>};
152 std::unique_ptr<mock::OutputLayer> mOutputLayer3{new StrictMock<mock::OutputLayer>};
153
154 StrictMock<mock::Layer> mLayer1;
155 StrictMock<mock::Layer> mLayer2;
156 StrictMock<mock::Layer> mLayer3;
157
158 StrictMock<mock::LayerFE> mLayer1FE;
159 StrictMock<mock::LayerFE> mLayer2FE;
160 StrictMock<mock::LayerFE> mLayer3FE;
161
162 LayerFECompositionState mLayer1FEState;
163 LayerFECompositionState mLayer2FEState;
164 LayerFECompositionState mLayer3FEState;
165};
166
Lloyd Piqueef958122019-02-05 18:00:12 -0800167const Rect OutputTest::kDefaultDisplaySize{100, 200};
168
Lloyd Pique17ca7422019-11-14 14:24:10 -0800169using ColorProfile = compositionengine::Output::ColorProfile;
170
171void dumpColorProfile(ColorProfile profile, std::string& result, const char* name) {
172 android::base::StringAppendF(&result, "%s (%s[%d] %s[%d] %s[%d] %s[%d]) ", name,
173 toString(profile.mode).c_str(), profile.mode,
174 toString(profile.dataspace).c_str(), profile.dataspace,
175 toString(profile.renderIntent).c_str(), profile.renderIntent,
176 toString(profile.colorSpaceAgnosticDataspace).c_str(),
177 profile.colorSpaceAgnosticDataspace);
178}
179
180// Checks for a ColorProfile match
181MATCHER_P(ColorProfileEq, expected, "") {
182 std::string buf;
183 buf.append("ColorProfiles are not equal\n");
184 dumpColorProfile(expected, buf, "expected value");
185 dumpColorProfile(arg, buf, "actual value");
186 *result_listener << buf;
187
188 return (expected.mode == arg.mode) && (expected.dataspace == arg.dataspace) &&
189 (expected.renderIntent == arg.renderIntent) &&
190 (expected.colorSpaceAgnosticDataspace == arg.colorSpaceAgnosticDataspace);
191}
192
Lloyd Pique66d68602019-02-13 14:23:31 -0800193/*
Lloyd Pique32cbe282018-10-19 13:09:22 -0700194 * Basic construction
195 */
196
Lloyd Pique31cb2942018-10-19 17:23:03 -0700197TEST_F(OutputTest, canInstantiateOutput) {
198 // The validation check checks each required component.
Lloyd Pique3d0c02e2018-10-19 18:38:12 -0700199 EXPECT_CALL(*mDisplayColorProfile, isValid()).WillOnce(Return(true));
Lloyd Pique31cb2942018-10-19 17:23:03 -0700200 EXPECT_CALL(*mRenderSurface, isValid()).WillOnce(Return(true));
201
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700202 EXPECT_TRUE(mOutput->isValid());
Lloyd Pique31cb2942018-10-19 17:23:03 -0700203
204 // If we take away the required components, it is no longer valid.
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700205 mOutput->setRenderSurfaceForTest(std::unique_ptr<RenderSurface>());
Lloyd Pique31cb2942018-10-19 17:23:03 -0700206
Lloyd Pique3d0c02e2018-10-19 18:38:12 -0700207 EXPECT_CALL(*mDisplayColorProfile, isValid()).WillOnce(Return(true));
208
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700209 EXPECT_FALSE(mOutput->isValid());
Lloyd Pique31cb2942018-10-19 17:23:03 -0700210}
Lloyd Pique32cbe282018-10-19 13:09:22 -0700211
Lloyd Pique66d68602019-02-13 14:23:31 -0800212/*
Lloyd Pique32cbe282018-10-19 13:09:22 -0700213 * Output::setCompositionEnabled()
214 */
215
216TEST_F(OutputTest, setCompositionEnabledDoesNothingIfAlreadyEnabled) {
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700217 mOutput->editState().isEnabled = true;
Lloyd Pique32cbe282018-10-19 13:09:22 -0700218
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700219 mOutput->setCompositionEnabled(true);
Lloyd Pique32cbe282018-10-19 13:09:22 -0700220
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700221 EXPECT_TRUE(mOutput->getState().isEnabled);
222 EXPECT_THAT(mOutput->getState().dirtyRegion, RegionEq(Region()));
Lloyd Pique32cbe282018-10-19 13:09:22 -0700223}
224
225TEST_F(OutputTest, setCompositionEnabledSetsEnabledAndDirtiesEntireOutput) {
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700226 mOutput->editState().isEnabled = false;
Lloyd Pique32cbe282018-10-19 13:09:22 -0700227
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700228 mOutput->setCompositionEnabled(true);
Lloyd Pique32cbe282018-10-19 13:09:22 -0700229
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700230 EXPECT_TRUE(mOutput->getState().isEnabled);
231 EXPECT_THAT(mOutput->getState().dirtyRegion, RegionEq(Region(kDefaultDisplaySize)));
Lloyd Pique32cbe282018-10-19 13:09:22 -0700232}
233
234TEST_F(OutputTest, setCompositionEnabledSetsDisabledAndDirtiesEntireOutput) {
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700235 mOutput->editState().isEnabled = true;
Lloyd Pique32cbe282018-10-19 13:09:22 -0700236
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700237 mOutput->setCompositionEnabled(false);
Lloyd Pique32cbe282018-10-19 13:09:22 -0700238
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700239 EXPECT_FALSE(mOutput->getState().isEnabled);
240 EXPECT_THAT(mOutput->getState().dirtyRegion, RegionEq(Region(kDefaultDisplaySize)));
Lloyd Pique32cbe282018-10-19 13:09:22 -0700241}
242
Lloyd Pique66d68602019-02-13 14:23:31 -0800243/*
Lloyd Pique32cbe282018-10-19 13:09:22 -0700244 * Output::setProjection()
245 */
246
247TEST_F(OutputTest, setProjectionTriviallyWorks) {
248 const ui::Transform transform{ui::Transform::ROT_180};
249 const int32_t orientation = 123;
250 const Rect frame{1, 2, 3, 4};
251 const Rect viewport{5, 6, 7, 8};
252 const Rect scissor{9, 10, 11, 12};
253 const bool needsFiltering = true;
254
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700255 mOutput->setProjection(transform, orientation, frame, viewport, scissor, needsFiltering);
Lloyd Pique32cbe282018-10-19 13:09:22 -0700256
Lloyd Piqueea629282019-12-03 15:57:10 -0800257 EXPECT_THAT(mOutput->getState().transform, transform);
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700258 EXPECT_EQ(orientation, mOutput->getState().orientation);
259 EXPECT_EQ(frame, mOutput->getState().frame);
260 EXPECT_EQ(viewport, mOutput->getState().viewport);
261 EXPECT_EQ(scissor, mOutput->getState().scissor);
262 EXPECT_EQ(needsFiltering, mOutput->getState().needsFiltering);
Lloyd Pique32cbe282018-10-19 13:09:22 -0700263}
264
Lloyd Pique66d68602019-02-13 14:23:31 -0800265/*
Lloyd Pique32cbe282018-10-19 13:09:22 -0700266 * Output::setBounds()
267 */
268
269TEST_F(OutputTest, setBoundsSetsSizeAndDirtiesEntireOutput) {
Lloyd Piqueef958122019-02-05 18:00:12 -0800270 const ui::Size displaySize{200, 400};
Lloyd Pique31cb2942018-10-19 17:23:03 -0700271
272 EXPECT_CALL(*mRenderSurface, setDisplaySize(displaySize)).Times(1);
273 EXPECT_CALL(*mRenderSurface, getSize()).WillOnce(ReturnRef(displaySize));
274
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700275 mOutput->setBounds(displaySize);
Lloyd Pique32cbe282018-10-19 13:09:22 -0700276
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700277 EXPECT_EQ(Rect(displaySize), mOutput->getState().bounds);
Lloyd Pique32cbe282018-10-19 13:09:22 -0700278
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700279 EXPECT_THAT(mOutput->getState().dirtyRegion, RegionEq(Region(Rect(displaySize))));
Lloyd Pique32cbe282018-10-19 13:09:22 -0700280}
281
Lloyd Pique66d68602019-02-13 14:23:31 -0800282/*
Lloyd Pique32cbe282018-10-19 13:09:22 -0700283 * Output::setLayerStackFilter()
284 */
285
286TEST_F(OutputTest, setLayerStackFilterSetsFilterAndDirtiesEntireOutput) {
Lloyd Pique32cbe282018-10-19 13:09:22 -0700287 const uint32_t layerStack = 123u;
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700288 mOutput->setLayerStackFilter(layerStack, true);
Lloyd Pique32cbe282018-10-19 13:09:22 -0700289
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700290 EXPECT_TRUE(mOutput->getState().layerStackInternal);
291 EXPECT_EQ(layerStack, mOutput->getState().layerStackId);
Lloyd Pique32cbe282018-10-19 13:09:22 -0700292
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700293 EXPECT_THAT(mOutput->getState().dirtyRegion, RegionEq(Region(kDefaultDisplaySize)));
Lloyd Pique32cbe282018-10-19 13:09:22 -0700294}
295
Lloyd Pique66d68602019-02-13 14:23:31 -0800296/*
Lloyd Pique32cbe282018-10-19 13:09:22 -0700297 * Output::setColorTransform
298 */
299
Lloyd Pique3eb1b212019-03-07 21:15:40 -0800300TEST_F(OutputTest, setColorTransformWithNoChangeFlaggedSkipsUpdates) {
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700301 mOutput->editState().colorTransformMatrix = kIdentity;
Lloyd Pique32cbe282018-10-19 13:09:22 -0700302
Lloyd Pique3eb1b212019-03-07 21:15:40 -0800303 // If no colorTransformMatrix is set the update should be skipped.
304 CompositionRefreshArgs refreshArgs;
305 refreshArgs.colorTransformMatrix = std::nullopt;
Lloyd Pique32cbe282018-10-19 13:09:22 -0700306
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700307 mOutput->setColorTransform(refreshArgs);
Lloyd Pique32cbe282018-10-19 13:09:22 -0700308
Lloyd Pique3eb1b212019-03-07 21:15:40 -0800309 // The internal state should be unchanged
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700310 EXPECT_EQ(kIdentity, mOutput->getState().colorTransformMatrix);
Lloyd Pique3eb1b212019-03-07 21:15:40 -0800311
312 // No dirty region should be set
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700313 EXPECT_THAT(mOutput->getState().dirtyRegion, RegionEq(Region()));
Lloyd Pique3eb1b212019-03-07 21:15:40 -0800314}
Lloyd Piqueef958122019-02-05 18:00:12 -0800315
Lloyd Pique3eb1b212019-03-07 21:15:40 -0800316TEST_F(OutputTest, setColorTransformWithNoActualChangeSkipsUpdates) {
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700317 mOutput->editState().colorTransformMatrix = kIdentity;
Lloyd Pique32cbe282018-10-19 13:09:22 -0700318
Lloyd Pique3eb1b212019-03-07 21:15:40 -0800319 // Attempting to set the same colorTransformMatrix that is already set should
320 // also skip the update.
321 CompositionRefreshArgs refreshArgs;
322 refreshArgs.colorTransformMatrix = kIdentity;
Lloyd Pique32cbe282018-10-19 13:09:22 -0700323
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700324 mOutput->setColorTransform(refreshArgs);
Lloyd Pique77f79a22019-04-29 15:55:40 -0700325
Lloyd Pique3eb1b212019-03-07 21:15:40 -0800326 // The internal state should be unchanged
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700327 EXPECT_EQ(kIdentity, mOutput->getState().colorTransformMatrix);
Lloyd Pique3eb1b212019-03-07 21:15:40 -0800328
329 // No dirty region should be set
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700330 EXPECT_THAT(mOutput->getState().dirtyRegion, RegionEq(Region()));
Lloyd Pique3eb1b212019-03-07 21:15:40 -0800331}
332
333TEST_F(OutputTest, setColorTransformPerformsUpdateToIdentity) {
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700334 mOutput->editState().colorTransformMatrix = kNonIdentityHalf;
Lloyd Pique3eb1b212019-03-07 21:15:40 -0800335
336 // Setting a different colorTransformMatrix should perform the update.
337 CompositionRefreshArgs refreshArgs;
338 refreshArgs.colorTransformMatrix = kIdentity;
339
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700340 mOutput->setColorTransform(refreshArgs);
Lloyd Pique3eb1b212019-03-07 21:15:40 -0800341
342 // The internal state should have been updated
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700343 EXPECT_EQ(kIdentity, mOutput->getState().colorTransformMatrix);
Lloyd Pique3eb1b212019-03-07 21:15:40 -0800344
345 // The dirtyRegion should be set to the full display size
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700346 EXPECT_THAT(mOutput->getState().dirtyRegion, RegionEq(Region(kDefaultDisplaySize)));
Lloyd Pique3eb1b212019-03-07 21:15:40 -0800347}
Lloyd Pique77f79a22019-04-29 15:55:40 -0700348
Lloyd Pique3eb1b212019-03-07 21:15:40 -0800349TEST_F(OutputTest, setColorTransformPerformsUpdateForIdentityToHalf) {
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700350 mOutput->editState().colorTransformMatrix = kIdentity;
Lloyd Pique77f79a22019-04-29 15:55:40 -0700351
Lloyd Pique3eb1b212019-03-07 21:15:40 -0800352 // Setting a different colorTransformMatrix should perform the update.
353 CompositionRefreshArgs refreshArgs;
354 refreshArgs.colorTransformMatrix = kNonIdentityHalf;
Lloyd Pique77f79a22019-04-29 15:55:40 -0700355
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700356 mOutput->setColorTransform(refreshArgs);
Lloyd Piqueef958122019-02-05 18:00:12 -0800357
Lloyd Pique3eb1b212019-03-07 21:15:40 -0800358 // The internal state should have been updated
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700359 EXPECT_EQ(kNonIdentityHalf, mOutput->getState().colorTransformMatrix);
Lloyd Pique3eb1b212019-03-07 21:15:40 -0800360
361 // The dirtyRegion should be set to the full display size
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700362 EXPECT_THAT(mOutput->getState().dirtyRegion, RegionEq(Region(kDefaultDisplaySize)));
Lloyd Pique3eb1b212019-03-07 21:15:40 -0800363}
364
365TEST_F(OutputTest, setColorTransformPerformsUpdateForHalfToQuarter) {
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700366 mOutput->editState().colorTransformMatrix = kNonIdentityHalf;
Lloyd Pique3eb1b212019-03-07 21:15:40 -0800367
368 // Setting a different colorTransformMatrix should perform the update.
369 CompositionRefreshArgs refreshArgs;
370 refreshArgs.colorTransformMatrix = kNonIdentityQuarter;
371
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700372 mOutput->setColorTransform(refreshArgs);
Lloyd Pique3eb1b212019-03-07 21:15:40 -0800373
374 // The internal state should have been updated
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700375 EXPECT_EQ(kNonIdentityQuarter, mOutput->getState().colorTransformMatrix);
Lloyd Pique3eb1b212019-03-07 21:15:40 -0800376
377 // The dirtyRegion should be set to the full display size
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700378 EXPECT_THAT(mOutput->getState().dirtyRegion, RegionEq(Region(kDefaultDisplaySize)));
Lloyd Pique32cbe282018-10-19 13:09:22 -0700379}
380
Lloyd Pique66d68602019-02-13 14:23:31 -0800381/*
Lloyd Pique17ca7422019-11-14 14:24:10 -0800382 * Output::setColorProfile
Lloyd Pique32cbe282018-10-19 13:09:22 -0700383 */
384
Lloyd Pique17ca7422019-11-14 14:24:10 -0800385using OutputSetColorProfileTest = OutputTest;
386
387TEST_F(OutputSetColorProfileTest, setsStateAndDirtiesOutputIfChanged) {
Lloyd Pique6a3b4462019-03-07 20:58:12 -0800388 using ColorProfile = Output::ColorProfile;
389
Lloyd Piquef5275482019-01-29 18:42:42 -0800390 EXPECT_CALL(*mDisplayColorProfile,
391 getTargetDataspace(ui::ColorMode::DISPLAY_P3, ui::Dataspace::DISPLAY_P3,
392 ui::Dataspace::UNKNOWN))
393 .WillOnce(Return(ui::Dataspace::UNKNOWN));
Lloyd Piqueef958122019-02-05 18:00:12 -0800394 EXPECT_CALL(*mRenderSurface, setBufferDataspace(ui::Dataspace::DISPLAY_P3)).Times(1);
Lloyd Pique31cb2942018-10-19 17:23:03 -0700395
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700396 mOutput->setColorProfile(ColorProfile{ui::ColorMode::DISPLAY_P3, ui::Dataspace::DISPLAY_P3,
397 ui::RenderIntent::TONE_MAP_COLORIMETRIC,
398 ui::Dataspace::UNKNOWN});
Lloyd Pique32cbe282018-10-19 13:09:22 -0700399
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700400 EXPECT_EQ(ui::ColorMode::DISPLAY_P3, mOutput->getState().colorMode);
401 EXPECT_EQ(ui::Dataspace::DISPLAY_P3, mOutput->getState().dataspace);
402 EXPECT_EQ(ui::RenderIntent::TONE_MAP_COLORIMETRIC, mOutput->getState().renderIntent);
403 EXPECT_EQ(ui::Dataspace::UNKNOWN, mOutput->getState().targetDataspace);
Lloyd Piquef5275482019-01-29 18:42:42 -0800404
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700405 EXPECT_THAT(mOutput->getState().dirtyRegion, RegionEq(Region(kDefaultDisplaySize)));
Lloyd Piqueef958122019-02-05 18:00:12 -0800406}
407
Lloyd Pique17ca7422019-11-14 14:24:10 -0800408TEST_F(OutputSetColorProfileTest, doesNothingIfNoChange) {
Lloyd Pique6a3b4462019-03-07 20:58:12 -0800409 using ColorProfile = Output::ColorProfile;
410
Lloyd Piquef5275482019-01-29 18:42:42 -0800411 EXPECT_CALL(*mDisplayColorProfile,
412 getTargetDataspace(ui::ColorMode::DISPLAY_P3, ui::Dataspace::DISPLAY_P3,
413 ui::Dataspace::UNKNOWN))
414 .WillOnce(Return(ui::Dataspace::UNKNOWN));
415
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700416 mOutput->editState().colorMode = ui::ColorMode::DISPLAY_P3;
417 mOutput->editState().dataspace = ui::Dataspace::DISPLAY_P3;
418 mOutput->editState().renderIntent = ui::RenderIntent::TONE_MAP_COLORIMETRIC;
419 mOutput->editState().targetDataspace = ui::Dataspace::UNKNOWN;
Lloyd Piqueef958122019-02-05 18:00:12 -0800420
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700421 mOutput->setColorProfile(ColorProfile{ui::ColorMode::DISPLAY_P3, ui::Dataspace::DISPLAY_P3,
422 ui::RenderIntent::TONE_MAP_COLORIMETRIC,
423 ui::Dataspace::UNKNOWN});
Lloyd Piqueef958122019-02-05 18:00:12 -0800424
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700425 EXPECT_THAT(mOutput->getState().dirtyRegion, RegionEq(Region()));
Lloyd Pique32cbe282018-10-19 13:09:22 -0700426}
427
Lloyd Pique66d68602019-02-13 14:23:31 -0800428/*
Lloyd Pique31cb2942018-10-19 17:23:03 -0700429 * Output::setRenderSurface()
430 */
431
432TEST_F(OutputTest, setRenderSurfaceResetsBounds) {
433 const ui::Size newDisplaySize{640, 480};
434
435 mock::RenderSurface* renderSurface = new StrictMock<mock::RenderSurface>();
436 EXPECT_CALL(*renderSurface, getSize()).WillOnce(ReturnRef(newDisplaySize));
437
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700438 mOutput->setRenderSurface(std::unique_ptr<RenderSurface>(renderSurface));
Lloyd Pique31cb2942018-10-19 17:23:03 -0700439
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700440 EXPECT_EQ(Rect(newDisplaySize), mOutput->getState().bounds);
Lloyd Pique31cb2942018-10-19 17:23:03 -0700441}
442
Lloyd Pique66d68602019-02-13 14:23:31 -0800443/*
Alec Mourie7d1d4a2019-02-05 01:13:46 +0000444 * Output::getDirtyRegion()
Lloyd Pique32cbe282018-10-19 13:09:22 -0700445 */
446
Alec Mourie7d1d4a2019-02-05 01:13:46 +0000447TEST_F(OutputTest, getDirtyRegionWithRepaintEverythingTrue) {
448 const Rect viewport{100, 200};
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700449 mOutput->editState().viewport = viewport;
450 mOutput->editState().dirtyRegion.set(50, 300);
Lloyd Pique32cbe282018-10-19 13:09:22 -0700451
452 {
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700453 Region result = mOutput->getDirtyRegion(true);
Lloyd Pique32cbe282018-10-19 13:09:22 -0700454
Alec Mourie7d1d4a2019-02-05 01:13:46 +0000455 EXPECT_THAT(result, RegionEq(Region(viewport)));
Lloyd Pique32cbe282018-10-19 13:09:22 -0700456 }
457}
458
Alec Mourie7d1d4a2019-02-05 01:13:46 +0000459TEST_F(OutputTest, getDirtyRegionWithRepaintEverythingFalse) {
460 const Rect viewport{100, 200};
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700461 mOutput->editState().viewport = viewport;
462 mOutput->editState().dirtyRegion.set(50, 300);
Lloyd Pique32cbe282018-10-19 13:09:22 -0700463
464 {
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700465 Region result = mOutput->getDirtyRegion(false);
Lloyd Pique32cbe282018-10-19 13:09:22 -0700466
467 // The dirtyRegion should be clipped to the display bounds.
468 EXPECT_THAT(result, RegionEq(Region(Rect(50, 200))));
469 }
Lloyd Pique32cbe282018-10-19 13:09:22 -0700470}
471
Lloyd Pique66d68602019-02-13 14:23:31 -0800472/*
Lloyd Piqueef36b002019-01-23 17:52:04 -0800473 * Output::belongsInOutput()
474 */
475
476TEST_F(OutputTest, belongsInOutputFiltersAsExpected) {
477 const uint32_t layerStack1 = 123u;
478 const uint32_t layerStack2 = 456u;
479
480 // If the output accepts layerStack1 and internal-only layers....
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700481 mOutput->setLayerStackFilter(layerStack1, true);
Lloyd Piqueef36b002019-01-23 17:52:04 -0800482
Lloyd Piquec6687342019-03-07 21:34:57 -0800483 // A layer with no layerStack does not belong to it, internal-only or not.
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700484 EXPECT_FALSE(mOutput->belongsInOutput(std::nullopt, false));
485 EXPECT_FALSE(mOutput->belongsInOutput(std::nullopt, true));
Lloyd Piquec6687342019-03-07 21:34:57 -0800486
Lloyd Piqueef36b002019-01-23 17:52:04 -0800487 // Any layer with layerStack1 belongs to it, internal-only or not.
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700488 EXPECT_TRUE(mOutput->belongsInOutput(layerStack1, false));
489 EXPECT_TRUE(mOutput->belongsInOutput(layerStack1, true));
490 EXPECT_FALSE(mOutput->belongsInOutput(layerStack2, true));
491 EXPECT_FALSE(mOutput->belongsInOutput(layerStack2, false));
Lloyd Piqueef36b002019-01-23 17:52:04 -0800492
493 // If the output accepts layerStack21 but not internal-only layers...
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700494 mOutput->setLayerStackFilter(layerStack1, false);
Lloyd Piqueef36b002019-01-23 17:52:04 -0800495
496 // Only non-internal layers with layerStack1 belong to it.
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700497 EXPECT_TRUE(mOutput->belongsInOutput(layerStack1, false));
498 EXPECT_FALSE(mOutput->belongsInOutput(layerStack1, true));
499 EXPECT_FALSE(mOutput->belongsInOutput(layerStack2, true));
500 EXPECT_FALSE(mOutput->belongsInOutput(layerStack2, false));
Lloyd Piqueef36b002019-01-23 17:52:04 -0800501}
502
Lloyd Pique66c20c42019-03-07 21:44:02 -0800503TEST_F(OutputTest, belongsInOutputFiltersLayersAsExpected) {
504 StrictMock<mock::Layer> layer;
Lloyd Pique9755fb72019-03-26 14:44:40 -0700505 LayerFECompositionState layerFEState;
Lloyd Pique66c20c42019-03-07 21:44:02 -0800506
Lloyd Pique9755fb72019-03-26 14:44:40 -0700507 EXPECT_CALL(layer, getFEState()).WillRepeatedly(ReturnRef(layerFEState));
Lloyd Pique66c20c42019-03-07 21:44:02 -0800508
509 const uint32_t layerStack1 = 123u;
510 const uint32_t layerStack2 = 456u;
511
512 // If the output accepts layerStack1 and internal-only layers....
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700513 mOutput->setLayerStackFilter(layerStack1, true);
Lloyd Pique66c20c42019-03-07 21:44:02 -0800514
515 // A null layer pointer does not belong to the output
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700516 EXPECT_FALSE(mOutput->belongsInOutput(nullptr));
Lloyd Pique66c20c42019-03-07 21:44:02 -0800517
518 // A layer with no layerStack does not belong to it, internal-only or not.
Lloyd Pique9755fb72019-03-26 14:44:40 -0700519 layerFEState.layerStackId = std::nullopt;
520 layerFEState.internalOnly = false;
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700521 EXPECT_FALSE(mOutput->belongsInOutput(&layer));
Lloyd Pique66c20c42019-03-07 21:44:02 -0800522
Lloyd Pique9755fb72019-03-26 14:44:40 -0700523 layerFEState.layerStackId = std::nullopt;
524 layerFEState.internalOnly = true;
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700525 EXPECT_FALSE(mOutput->belongsInOutput(&layer));
Lloyd Pique66c20c42019-03-07 21:44:02 -0800526
527 // Any layer with layerStack1 belongs to it, internal-only or not.
Lloyd Pique9755fb72019-03-26 14:44:40 -0700528 layerFEState.layerStackId = layerStack1;
529 layerFEState.internalOnly = false;
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700530 EXPECT_TRUE(mOutput->belongsInOutput(&layer));
Lloyd Pique66c20c42019-03-07 21:44:02 -0800531
Lloyd Pique9755fb72019-03-26 14:44:40 -0700532 layerFEState.layerStackId = layerStack1;
533 layerFEState.internalOnly = true;
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700534 EXPECT_TRUE(mOutput->belongsInOutput(&layer));
Lloyd Pique66c20c42019-03-07 21:44:02 -0800535
Lloyd Pique9755fb72019-03-26 14:44:40 -0700536 layerFEState.layerStackId = layerStack2;
537 layerFEState.internalOnly = true;
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700538 EXPECT_FALSE(mOutput->belongsInOutput(&layer));
Lloyd Pique66c20c42019-03-07 21:44:02 -0800539
Lloyd Pique9755fb72019-03-26 14:44:40 -0700540 layerFEState.layerStackId = layerStack2;
541 layerFEState.internalOnly = false;
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700542 EXPECT_FALSE(mOutput->belongsInOutput(&layer));
Lloyd Pique66c20c42019-03-07 21:44:02 -0800543
544 // If the output accepts layerStack1 but not internal-only layers...
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700545 mOutput->setLayerStackFilter(layerStack1, false);
Lloyd Pique66c20c42019-03-07 21:44:02 -0800546
547 // A null layer pointer does not belong to the output
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700548 EXPECT_FALSE(mOutput->belongsInOutput(nullptr));
Lloyd Pique66c20c42019-03-07 21:44:02 -0800549
550 // Only non-internal layers with layerStack1 belong to it.
Lloyd Pique9755fb72019-03-26 14:44:40 -0700551 layerFEState.layerStackId = layerStack1;
552 layerFEState.internalOnly = false;
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700553 EXPECT_TRUE(mOutput->belongsInOutput(&layer));
Lloyd Pique66c20c42019-03-07 21:44:02 -0800554
Lloyd Pique9755fb72019-03-26 14:44:40 -0700555 layerFEState.layerStackId = layerStack1;
556 layerFEState.internalOnly = true;
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700557 EXPECT_FALSE(mOutput->belongsInOutput(&layer));
Lloyd Pique66c20c42019-03-07 21:44:02 -0800558
Lloyd Pique9755fb72019-03-26 14:44:40 -0700559 layerFEState.layerStackId = layerStack2;
560 layerFEState.internalOnly = true;
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700561 EXPECT_FALSE(mOutput->belongsInOutput(&layer));
Lloyd Pique66c20c42019-03-07 21:44:02 -0800562
Lloyd Pique9755fb72019-03-26 14:44:40 -0700563 layerFEState.layerStackId = layerStack2;
564 layerFEState.internalOnly = false;
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700565 EXPECT_FALSE(mOutput->belongsInOutput(&layer));
Lloyd Pique66c20c42019-03-07 21:44:02 -0800566}
567
Lloyd Pique66d68602019-02-13 14:23:31 -0800568/*
Lloyd Piquecc01a452018-12-04 17:24:00 -0800569 * Output::getOutputLayerForLayer()
570 */
571
572TEST_F(OutputTest, getOutputLayerForLayerWorks) {
573 mock::OutputLayer* outputLayer1 = new StrictMock<mock::OutputLayer>();
574 mock::OutputLayer* outputLayer2 = new StrictMock<mock::OutputLayer>();
575
Lloyd Pique01c77c12019-04-17 12:48:32 -0700576 mOutput->injectOutputLayerForTest(std::unique_ptr<OutputLayer>(outputLayer1));
577 mOutput->injectOutputLayerForTest(nullptr);
578 mOutput->injectOutputLayerForTest(std::unique_ptr<OutputLayer>(outputLayer2));
Lloyd Piquecc01a452018-12-04 17:24:00 -0800579
580 StrictMock<mock::Layer> layer;
581 StrictMock<mock::Layer> otherLayer;
582
583 // If the input layer matches the first OutputLayer, it will be returned.
584 EXPECT_CALL(*outputLayer1, getLayer()).WillOnce(ReturnRef(layer));
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700585 EXPECT_EQ(outputLayer1, mOutput->getOutputLayerForLayer(&layer));
Lloyd Piquecc01a452018-12-04 17:24:00 -0800586
587 // If the input layer matches the second OutputLayer, it will be returned.
588 EXPECT_CALL(*outputLayer1, getLayer()).WillOnce(ReturnRef(otherLayer));
589 EXPECT_CALL(*outputLayer2, getLayer()).WillOnce(ReturnRef(layer));
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700590 EXPECT_EQ(outputLayer2, mOutput->getOutputLayerForLayer(&layer));
Lloyd Piquecc01a452018-12-04 17:24:00 -0800591
592 // If the input layer does not match an output layer, null will be returned.
593 EXPECT_CALL(*outputLayer1, getLayer()).WillOnce(ReturnRef(otherLayer));
594 EXPECT_CALL(*outputLayer2, getLayer()).WillOnce(ReturnRef(otherLayer));
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700595 EXPECT_EQ(nullptr, mOutput->getOutputLayerForLayer(&layer));
Lloyd Piquecc01a452018-12-04 17:24:00 -0800596}
597
Lloyd Pique66d68602019-02-13 14:23:31 -0800598/*
Lloyd Piquec9e60032019-11-14 11:47:26 -0800599 * Output::setReleasedLayers()
600 */
601
602using OutputSetReleasedLayersTest = OutputTest;
603
604TEST_F(OutputSetReleasedLayersTest, setReleasedLayersTakesGivenLayers) {
605 sp<StrictMock<mock::LayerFE>> layer1FE{new StrictMock<mock::LayerFE>()};
606 sp<StrictMock<mock::LayerFE>> layer2FE{new StrictMock<mock::LayerFE>()};
607 sp<StrictMock<mock::LayerFE>> layer3FE{new StrictMock<mock::LayerFE>()};
608
609 Output::ReleasedLayers layers;
610 layers.push_back(layer1FE);
611 layers.push_back(layer2FE);
612 layers.push_back(layer3FE);
613
614 mOutput->setReleasedLayers(std::move(layers));
615
616 const auto& setLayers = mOutput->getReleasedLayersForTest();
617 ASSERT_EQ(3u, setLayers.size());
618 ASSERT_EQ(layer1FE.get(), setLayers[0].promote().get());
619 ASSERT_EQ(layer2FE.get(), setLayers[1].promote().get());
620 ASSERT_EQ(layer3FE.get(), setLayers[2].promote().get());
621}
622
623/*
Lloyd Piquec0ee6ba2019-11-14 12:55:53 -0800624 * Output::updateLayerStateFromFE()
625 */
626
627using OutputUpdateLayerStateFromFETest = OutputLatchFEStateTest;
628
629TEST_F(OutputUpdateLayerStateFromFETest, handlesNoOutputLayerCase) {
630 CompositionRefreshArgs refreshArgs;
631
632 mOutput->updateLayerStateFromFE(refreshArgs);
633}
634
635TEST_F(OutputUpdateLayerStateFromFETest, latchesContentStateForAllContainedLayers) {
636 EXPECT_CALL(mLayer1FE,
637 latchCompositionState(Ref(mLayer1FEState), LayerFE::StateSubset::Content));
638 EXPECT_CALL(mLayer2FE,
639 latchCompositionState(Ref(mLayer2FEState), LayerFE::StateSubset::Content));
640 EXPECT_CALL(mLayer3FE,
641 latchCompositionState(Ref(mLayer3FEState), LayerFE::StateSubset::Content));
642
643 // Note: Must be performed after any expectations on these mocks
644 injectLayer(std::move(mOutputLayer1));
645 injectLayer(std::move(mOutputLayer2));
646 injectLayer(std::move(mOutputLayer3));
647
648 CompositionRefreshArgs refreshArgs;
649 refreshArgs.updatingGeometryThisFrame = false;
650
651 mOutput->updateLayerStateFromFE(refreshArgs);
652}
653
654TEST_F(OutputUpdateLayerStateFromFETest, latchesGeometryAndContentStateForAllContainedLayers) {
655 EXPECT_CALL(mLayer1FE,
656 latchCompositionState(Ref(mLayer1FEState),
657 LayerFE::StateSubset::GeometryAndContent));
658 EXPECT_CALL(mLayer2FE,
659 latchCompositionState(Ref(mLayer2FEState),
660 LayerFE::StateSubset::GeometryAndContent));
661 EXPECT_CALL(mLayer3FE,
662 latchCompositionState(Ref(mLayer3FEState),
663 LayerFE::StateSubset::GeometryAndContent));
664
665 // Note: Must be performed after any expectations on these mocks
666 injectLayer(std::move(mOutputLayer1));
667 injectLayer(std::move(mOutputLayer2));
668 injectLayer(std::move(mOutputLayer3));
669
670 CompositionRefreshArgs refreshArgs;
671 refreshArgs.updatingGeometryThisFrame = true;
672
673 mOutput->updateLayerStateFromFE(refreshArgs);
674}
675
676/*
Alec Mourif9a2a2c2019-11-12 12:46:02 -0800677 * Output::updateAndWriteCompositionState()
678 */
679
Lloyd Piqueef63b612019-11-14 13:19:56 -0800680using OutputUpdateAndWriteCompositionStateTest = OutputLatchFEStateTest;
681
682TEST_F(OutputUpdateAndWriteCompositionStateTest, doesNothingIfLayers) {
683 mOutput->editState().isEnabled = true;
Alec Mourif9a2a2c2019-11-12 12:46:02 -0800684
685 CompositionRefreshArgs args;
686 mOutput->updateAndWriteCompositionState(args);
687}
688
Lloyd Piqueef63b612019-11-14 13:19:56 -0800689TEST_F(OutputUpdateAndWriteCompositionStateTest, doesNothingIfOutputNotEnabled) {
690 mOutput->editState().isEnabled = false;
Alec Mourif9a2a2c2019-11-12 12:46:02 -0800691
Lloyd Piqueef63b612019-11-14 13:19:56 -0800692 injectLayer(std::move(mOutputLayer1));
693 injectLayer(std::move(mOutputLayer2));
694 injectLayer(std::move(mOutputLayer3));
695
696 CompositionRefreshArgs args;
697 mOutput->updateAndWriteCompositionState(args);
698}
699
700TEST_F(OutputUpdateAndWriteCompositionStateTest, updatesLayerContentForAllLayers) {
701 EXPECT_CALL(*mOutputLayer1, updateCompositionState(false, false));
702 EXPECT_CALL(*mOutputLayer1, writeStateToHWC(false));
703 EXPECT_CALL(*mOutputLayer2, updateCompositionState(false, false));
704 EXPECT_CALL(*mOutputLayer2, writeStateToHWC(false));
705 EXPECT_CALL(*mOutputLayer3, updateCompositionState(false, false));
706 EXPECT_CALL(*mOutputLayer3, writeStateToHWC(false));
707
708 injectLayer(std::move(mOutputLayer1));
709 injectLayer(std::move(mOutputLayer2));
710 injectLayer(std::move(mOutputLayer3));
711
712 mOutput->editState().isEnabled = true;
713
714 CompositionRefreshArgs args;
715 args.updatingGeometryThisFrame = false;
716 args.devOptForceClientComposition = false;
717 mOutput->updateAndWriteCompositionState(args);
718}
719
720TEST_F(OutputUpdateAndWriteCompositionStateTest, updatesLayerGeometryAndContentForAllLayers) {
721 EXPECT_CALL(*mOutputLayer1, updateCompositionState(true, false));
722 EXPECT_CALL(*mOutputLayer1, writeStateToHWC(true));
723 EXPECT_CALL(*mOutputLayer2, updateCompositionState(true, false));
724 EXPECT_CALL(*mOutputLayer2, writeStateToHWC(true));
725 EXPECT_CALL(*mOutputLayer3, updateCompositionState(true, false));
726 EXPECT_CALL(*mOutputLayer3, writeStateToHWC(true));
727
728 injectLayer(std::move(mOutputLayer1));
729 injectLayer(std::move(mOutputLayer2));
730 injectLayer(std::move(mOutputLayer3));
731
732 mOutput->editState().isEnabled = true;
Alec Mourif9a2a2c2019-11-12 12:46:02 -0800733
734 CompositionRefreshArgs args;
735 args.updatingGeometryThisFrame = true;
Lloyd Piqueef63b612019-11-14 13:19:56 -0800736 args.devOptForceClientComposition = false;
737 mOutput->updateAndWriteCompositionState(args);
738}
739
740TEST_F(OutputUpdateAndWriteCompositionStateTest, forcesClientCompositionForAllLayers) {
741 EXPECT_CALL(*mOutputLayer1, updateCompositionState(false, true));
742 EXPECT_CALL(*mOutputLayer1, writeStateToHWC(false));
743 EXPECT_CALL(*mOutputLayer2, updateCompositionState(false, true));
744 EXPECT_CALL(*mOutputLayer2, writeStateToHWC(false));
745 EXPECT_CALL(*mOutputLayer3, updateCompositionState(false, true));
746 EXPECT_CALL(*mOutputLayer3, writeStateToHWC(false));
747
748 injectLayer(std::move(mOutputLayer1));
749 injectLayer(std::move(mOutputLayer2));
750 injectLayer(std::move(mOutputLayer3));
751
752 mOutput->editState().isEnabled = true;
753
754 CompositionRefreshArgs args;
755 args.updatingGeometryThisFrame = false;
Alec Mourif9a2a2c2019-11-12 12:46:02 -0800756 args.devOptForceClientComposition = true;
757 mOutput->updateAndWriteCompositionState(args);
758}
759
760/*
Lloyd Pique66d68602019-02-13 14:23:31 -0800761 * Output::prepareFrame()
762 */
763
764struct OutputPrepareFrameTest : public testing::Test {
Lloyd Piquefaa3f192019-11-14 14:05:09 -0800765 struct OutputPartialMock : public OutputPartialMockBase {
Lloyd Pique739afaf2019-11-21 16:40:05 -0800766 // Sets up the helper functions called by the function under test to use
767 // mock implementations.
Lloyd Pique66d68602019-02-13 14:23:31 -0800768 MOCK_METHOD0(chooseCompositionStrategy, void());
769 };
770
771 OutputPrepareFrameTest() {
772 mOutput.setDisplayColorProfileForTest(
773 std::unique_ptr<DisplayColorProfile>(mDisplayColorProfile));
774 mOutput.setRenderSurfaceForTest(std::unique_ptr<RenderSurface>(mRenderSurface));
775 }
776
777 StrictMock<mock::CompositionEngine> mCompositionEngine;
778 mock::DisplayColorProfile* mDisplayColorProfile = new StrictMock<mock::DisplayColorProfile>();
779 mock::RenderSurface* mRenderSurface = new StrictMock<mock::RenderSurface>();
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700780 StrictMock<OutputPartialMock> mOutput;
Lloyd Pique66d68602019-02-13 14:23:31 -0800781};
782
783TEST_F(OutputPrepareFrameTest, takesEarlyOutIfNotEnabled) {
784 mOutput.editState().isEnabled = false;
785
786 mOutput.prepareFrame();
787}
788
789TEST_F(OutputPrepareFrameTest, delegatesToChooseCompositionStrategyAndRenderSurface) {
790 mOutput.editState().isEnabled = true;
791 mOutput.editState().usesClientComposition = false;
792 mOutput.editState().usesDeviceComposition = true;
793
794 EXPECT_CALL(mOutput, chooseCompositionStrategy()).Times(1);
795 EXPECT_CALL(*mRenderSurface, prepareFrame(false, true));
796
797 mOutput.prepareFrame();
798}
799
800// Note: Use OutputTest and not OutputPrepareFrameTest, so the real
801// base chooseCompositionStrategy() is invoked.
802TEST_F(OutputTest, prepareFrameSetsClientCompositionOnlyByDefault) {
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700803 mOutput->editState().isEnabled = true;
804 mOutput->editState().usesClientComposition = false;
805 mOutput->editState().usesDeviceComposition = true;
Lloyd Pique66d68602019-02-13 14:23:31 -0800806
807 EXPECT_CALL(*mRenderSurface, prepareFrame(true, false));
808
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700809 mOutput->prepareFrame();
Lloyd Pique66d68602019-02-13 14:23:31 -0800810
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700811 EXPECT_TRUE(mOutput->getState().usesClientComposition);
812 EXPECT_FALSE(mOutput->getState().usesDeviceComposition);
Lloyd Pique66d68602019-02-13 14:23:31 -0800813}
814
Lloyd Pique56eba802019-08-28 15:45:25 -0700815/*
Lloyd Piqueb62cebc2019-11-20 18:31:52 -0800816 * Output::prepare()
817 */
818
819struct OutputPrepareTest : public testing::Test {
820 struct OutputPartialMock : public OutputPartialMockBase {
821 // Sets up the helper functions called by the function under test to use
822 // mock implementations.
823 MOCK_METHOD2(rebuildLayerStacks,
824 void(const compositionengine::CompositionRefreshArgs&,
825 compositionengine::LayerFESet&));
826 };
827
828 StrictMock<OutputPartialMock> mOutput;
829 CompositionRefreshArgs mRefreshArgs;
Lloyd Piquefe0ee9e2019-11-22 16:30:30 -0800830 LayerFESet mGeomSnapshots;
Lloyd Piqueb62cebc2019-11-20 18:31:52 -0800831};
832
833TEST_F(OutputPrepareTest, justInvokesRebuildLayerStacks) {
834 InSequence seq;
835 EXPECT_CALL(mOutput, rebuildLayerStacks(Ref(mRefreshArgs), Ref(mGeomSnapshots)));
836
837 mOutput.prepare(mRefreshArgs, mGeomSnapshots);
838}
839
840/*
841 * Output::rebuildLayerStacks()
842 */
843
844struct OutputRebuildLayerStacksTest : public testing::Test {
845 struct OutputPartialMock : public OutputPartialMockBase {
846 // Sets up the helper functions called by the function under test to use
847 // mock implementations.
848 MOCK_METHOD2(collectVisibleLayers,
849 void(const compositionengine::CompositionRefreshArgs&,
850 compositionengine::Output::CoverageState&));
851 };
852
853 OutputRebuildLayerStacksTest() {
854 mOutput.mState.isEnabled = true;
855 mOutput.mState.transform = kIdentityTransform;
856 mOutput.mState.bounds = kOutputBounds;
857
858 mRefreshArgs.updatingOutputGeometryThisFrame = true;
859
860 mCoverageAboveCoveredLayersToSet = Region(Rect(0, 0, 10, 10));
861
862 EXPECT_CALL(mOutput, collectVisibleLayers(Ref(mRefreshArgs), _))
863 .WillRepeatedly(Invoke(this, &OutputRebuildLayerStacksTest::setTestCoverageValues));
864 }
865
866 void setTestCoverageValues(const CompositionRefreshArgs&,
867 compositionengine::Output::CoverageState& state) {
868 state.aboveCoveredLayers = mCoverageAboveCoveredLayersToSet;
869 state.aboveOpaqueLayers = mCoverageAboveOpaqueLayersToSet;
870 state.dirtyRegion = mCoverageDirtyRegionToSet;
871 }
872
873 static const ui::Transform kIdentityTransform;
874 static const ui::Transform kRotate90Transform;
875 static const Rect kOutputBounds;
876
877 StrictMock<OutputPartialMock> mOutput;
878 CompositionRefreshArgs mRefreshArgs;
Lloyd Piquefe0ee9e2019-11-22 16:30:30 -0800879 LayerFESet mGeomSnapshots;
Lloyd Piqueb62cebc2019-11-20 18:31:52 -0800880 Region mCoverageAboveCoveredLayersToSet;
881 Region mCoverageAboveOpaqueLayersToSet;
882 Region mCoverageDirtyRegionToSet;
883};
884
885const ui::Transform OutputRebuildLayerStacksTest::kIdentityTransform{TR_IDENT, 1920, 1080};
886const ui::Transform OutputRebuildLayerStacksTest::kRotate90Transform{TR_ROT_90, 1920, 1080};
887const Rect OutputRebuildLayerStacksTest::kOutputBounds{0, 0, 1920, 1080};
888
889TEST_F(OutputRebuildLayerStacksTest, doesNothingIfNotEnabled) {
890 mOutput.mState.isEnabled = false;
891
892 mOutput.rebuildLayerStacks(mRefreshArgs, mGeomSnapshots);
893}
894
895TEST_F(OutputRebuildLayerStacksTest, doesNothingIfNotUpdatingGeometryThisFrame) {
896 mRefreshArgs.updatingOutputGeometryThisFrame = false;
897
898 mOutput.rebuildLayerStacks(mRefreshArgs, mGeomSnapshots);
899}
900
901TEST_F(OutputRebuildLayerStacksTest, computesUndefinedRegionWithNoRotationAndFullCoverage) {
902 mOutput.mState.transform = kIdentityTransform;
903
904 mCoverageAboveOpaqueLayersToSet = Region(Rect(0, 0, 1920, 1080));
905
906 mOutput.rebuildLayerStacks(mRefreshArgs, mGeomSnapshots);
907
908 EXPECT_THAT(mOutput.mState.undefinedRegion, RegionEq(Region(Rect(0, 0, 0, 0))));
909}
910
911TEST_F(OutputRebuildLayerStacksTest, computesUndefinedRegionWithNoRotationAndPartialCoverage) {
912 mOutput.mState.transform = kIdentityTransform;
913
914 mCoverageAboveOpaqueLayersToSet = Region(Rect(0, 0, 960, 1080));
915
916 mOutput.rebuildLayerStacks(mRefreshArgs, mGeomSnapshots);
917
918 EXPECT_THAT(mOutput.mState.undefinedRegion, RegionEq(Region(Rect(960, 0, 1920, 1080))));
919}
920
921TEST_F(OutputRebuildLayerStacksTest, computesUndefinedRegionWith90RotationAndFullCoverage) {
922 mOutput.mState.transform = kRotate90Transform;
923
924 mCoverageAboveOpaqueLayersToSet = Region(Rect(0, 0, 1080, 1920));
925
926 mOutput.rebuildLayerStacks(mRefreshArgs, mGeomSnapshots);
927
928 EXPECT_THAT(mOutput.mState.undefinedRegion, RegionEq(Region(Rect(0, 0, 0, 0))));
929}
930
931TEST_F(OutputRebuildLayerStacksTest, computesUndefinedRegionWith90RotationAndPartialCoverage) {
932 mOutput.mState.transform = kRotate90Transform;
933
934 mCoverageAboveOpaqueLayersToSet = Region(Rect(0, 0, 1080, 960));
935
936 mOutput.rebuildLayerStacks(mRefreshArgs, mGeomSnapshots);
937
938 EXPECT_THAT(mOutput.mState.undefinedRegion, RegionEq(Region(Rect(0, 0, 960, 1080))));
939}
940
941TEST_F(OutputRebuildLayerStacksTest, addsToDirtyRegionWithNoRotation) {
942 mOutput.mState.transform = kIdentityTransform;
943 mOutput.mState.dirtyRegion = Region(Rect(960, 0, 1920, 1080));
944
945 mCoverageDirtyRegionToSet = Region(Rect(0, 0, 960, 1080));
946
947 mOutput.rebuildLayerStacks(mRefreshArgs, mGeomSnapshots);
948
949 EXPECT_THAT(mOutput.mState.dirtyRegion, RegionEq(Region(Rect(0, 0, 1920, 1080))));
950}
951
952TEST_F(OutputRebuildLayerStacksTest, addsToDirtyRegionWith90Rotation) {
953 mOutput.mState.transform = kRotate90Transform;
954 mOutput.mState.dirtyRegion = Region(Rect(0, 960, 1080, 1920));
955
956 mCoverageDirtyRegionToSet = Region(Rect(0, 0, 1080, 960));
957
958 mOutput.rebuildLayerStacks(mRefreshArgs, mGeomSnapshots);
959
960 EXPECT_THAT(mOutput.mState.dirtyRegion, RegionEq(Region(Rect(0, 0, 1080, 1920))));
961}
962
963/*
964 * Output::collectVisibleLayers()
965 */
966
Lloyd Pique1ef93222019-11-21 16:41:53 -0800967struct OutputCollectVisibleLayersTest : public testing::Test {
968 struct OutputPartialMock : public OutputPartialMockBase {
969 // Sets up the helper functions called by the function under test to use
970 // mock implementations.
971 MOCK_METHOD2(ensureOutputLayerIfVisible,
972 void(std::shared_ptr<compositionengine::Layer>,
973 compositionengine::Output::CoverageState&));
974 MOCK_METHOD1(setReleasedLayers, void(const compositionengine::CompositionRefreshArgs&));
975 MOCK_METHOD0(finalizePendingOutputLayers, void());
976 };
977
978 struct Layer {
979 Layer() {
980 EXPECT_CALL(outputLayer, getState()).WillRepeatedly(ReturnRef(outputLayerState));
981 EXPECT_CALL(outputLayer, editState()).WillRepeatedly(ReturnRef(outputLayerState));
982 }
983
984 StrictMock<mock::OutputLayer> outputLayer;
985 std::shared_ptr<StrictMock<mock::Layer>> layer{new StrictMock<mock::Layer>()};
986 impl::OutputLayerCompositionState outputLayerState;
987 };
988
989 OutputCollectVisibleLayersTest() {
Lloyd Pique0a456232020-01-16 17:51:13 -0800990 EXPECT_CALL(mOutput, getOutputLayerCount()).WillRepeatedly(Return(3u));
Lloyd Pique1ef93222019-11-21 16:41:53 -0800991 EXPECT_CALL(mOutput, getOutputLayerOrderedByZByIndex(0))
992 .WillRepeatedly(Return(&mLayer1.outputLayer));
993 EXPECT_CALL(mOutput, getOutputLayerOrderedByZByIndex(1))
994 .WillRepeatedly(Return(&mLayer2.outputLayer));
995 EXPECT_CALL(mOutput, getOutputLayerOrderedByZByIndex(2))
996 .WillRepeatedly(Return(&mLayer3.outputLayer));
997
998 mRefreshArgs.layers.push_back(mLayer1.layer);
999 mRefreshArgs.layers.push_back(mLayer2.layer);
1000 mRefreshArgs.layers.push_back(mLayer3.layer);
1001 }
1002
1003 StrictMock<OutputPartialMock> mOutput;
1004 CompositionRefreshArgs mRefreshArgs;
Lloyd Piquefe0ee9e2019-11-22 16:30:30 -08001005 LayerFESet mGeomSnapshots;
1006 Output::CoverageState mCoverageState{mGeomSnapshots};
Lloyd Pique1ef93222019-11-21 16:41:53 -08001007 Layer mLayer1;
1008 Layer mLayer2;
1009 Layer mLayer3;
1010};
1011
1012TEST_F(OutputCollectVisibleLayersTest, doesMinimalWorkIfNoLayers) {
1013 mRefreshArgs.layers.clear();
Lloyd Pique0a456232020-01-16 17:51:13 -08001014 EXPECT_CALL(mOutput, getOutputLayerCount()).WillRepeatedly(Return(0u));
Lloyd Pique1ef93222019-11-21 16:41:53 -08001015
1016 EXPECT_CALL(mOutput, setReleasedLayers(Ref(mRefreshArgs)));
1017 EXPECT_CALL(mOutput, finalizePendingOutputLayers());
1018
1019 mOutput.collectVisibleLayers(mRefreshArgs, mCoverageState);
1020}
1021
1022TEST_F(OutputCollectVisibleLayersTest, processesCandidateLayersReversedAndSetsOutputLayerZ) {
1023 // Enforce a call order sequence for this test.
1024 InSequence seq;
1025
1026 // Layer coverage is evaluated from front to back!
1027 EXPECT_CALL(mOutput, ensureOutputLayerIfVisible(Eq(mLayer3.layer), Ref(mCoverageState)));
1028 EXPECT_CALL(mOutput, ensureOutputLayerIfVisible(Eq(mLayer2.layer), Ref(mCoverageState)));
1029 EXPECT_CALL(mOutput, ensureOutputLayerIfVisible(Eq(mLayer1.layer), Ref(mCoverageState)));
1030
1031 EXPECT_CALL(mOutput, setReleasedLayers(Ref(mRefreshArgs)));
1032 EXPECT_CALL(mOutput, finalizePendingOutputLayers());
1033
1034 mOutput.collectVisibleLayers(mRefreshArgs, mCoverageState);
1035
1036 // Ensure all output layers have been assigned a simple/flattened z-order.
1037 EXPECT_EQ(0u, mLayer1.outputLayerState.z);
1038 EXPECT_EQ(1u, mLayer2.outputLayerState.z);
1039 EXPECT_EQ(2u, mLayer3.outputLayerState.z);
1040}
Lloyd Piqueb62cebc2019-11-20 18:31:52 -08001041
1042/*
1043 * Output::ensureOutputLayerIfVisible()
1044 */
1045
Lloyd Piquefe0ee9e2019-11-22 16:30:30 -08001046struct OutputEnsureOutputLayerIfVisibleTest : public testing::Test {
1047 struct OutputPartialMock : public OutputPartialMockBase {
1048 // Sets up the helper functions called by the function under test to use
1049 // mock implementations.
1050 MOCK_CONST_METHOD1(belongsInOutput, bool(const compositionengine::Layer*));
1051 MOCK_CONST_METHOD1(getOutputLayerOrderedByZByIndex, OutputLayer*(size_t));
1052 MOCK_METHOD3(ensureOutputLayer,
1053 compositionengine::OutputLayer*(
1054 std::optional<size_t>,
1055 const std::shared_ptr<compositionengine::Layer>&, const sp<LayerFE>&));
1056 };
1057
1058 OutputEnsureOutputLayerIfVisibleTest() {
1059 EXPECT_CALL(*mLayer, getLayerFE()).WillRepeatedly(Return(mLayerFE));
1060 EXPECT_CALL(*mLayer, getFEState()).WillRepeatedly(ReturnRef(mLayerFEState));
1061 EXPECT_CALL(*mLayer, editFEState()).WillRepeatedly(ReturnRef(mLayerFEState));
1062
1063 EXPECT_CALL(mOutput, belongsInOutput(mLayer.get())).WillRepeatedly(Return(true));
Lloyd Pique0a456232020-01-16 17:51:13 -08001064 EXPECT_CALL(mOutput, getOutputLayerCount()).WillRepeatedly(Return(1u));
Lloyd Piquefe0ee9e2019-11-22 16:30:30 -08001065 EXPECT_CALL(mOutput, getOutputLayerOrderedByZByIndex(0u))
1066 .WillRepeatedly(Return(&mOutputLayer));
1067
1068 EXPECT_CALL(mOutputLayer, getState()).WillRepeatedly(ReturnRef(mOutputLayerState));
1069 EXPECT_CALL(mOutputLayer, editState()).WillRepeatedly(ReturnRef(mOutputLayerState));
1070 EXPECT_CALL(mOutputLayer, getLayer()).WillRepeatedly(ReturnRef(*mLayer.get()));
1071
1072 mOutput.mState.bounds = Rect(0, 0, 200, 300);
1073 mOutput.mState.viewport = Rect(0, 0, 200, 300);
1074 mOutput.mState.transform = ui::Transform(TR_IDENT, 200, 300);
1075
1076 mLayerFEState.isVisible = true;
1077 mLayerFEState.isOpaque = true;
1078 mLayerFEState.contentDirty = true;
1079 mLayerFEState.geomLayerBounds = FloatRect{0, 0, 100, 200};
1080 mLayerFEState.geomLayerTransform = ui::Transform(TR_IDENT, 100, 200);
1081 mLayerFEState.transparentRegionHint = Region(Rect(0, 0, 100, 100));
1082
1083 mOutputLayerState.visibleRegion = Region(Rect(0, 0, 50, 200));
1084 mOutputLayerState.coveredRegion = Region(Rect(50, 0, 100, 200));
1085
1086 mGeomSnapshots.insert(mLayerFE);
1087 }
1088
1089 static const Region kEmptyRegion;
1090 static const Region kFullBoundsNoRotation;
1091 static const Region kRightHalfBoundsNoRotation;
1092 static const Region kLowerHalfBoundsNoRotation;
1093 static const Region kFullBounds90Rotation;
1094
1095 StrictMock<OutputPartialMock> mOutput;
1096 LayerFESet mGeomSnapshots;
1097 Output::CoverageState mCoverageState{mGeomSnapshots};
1098
1099 std::shared_ptr<mock::Layer> mLayer{new StrictMock<mock::Layer>()};
1100 sp<StrictMock<mock::LayerFE>> mLayerFE{new StrictMock<mock::LayerFE>()};
1101 LayerFECompositionState mLayerFEState;
1102 mock::OutputLayer mOutputLayer;
1103 impl::OutputLayerCompositionState mOutputLayerState;
1104};
1105
1106const Region OutputEnsureOutputLayerIfVisibleTest::kEmptyRegion = Region(Rect(0, 0, 0, 0));
1107const Region OutputEnsureOutputLayerIfVisibleTest::kFullBoundsNoRotation =
1108 Region(Rect(0, 0, 100, 200));
1109const Region OutputEnsureOutputLayerIfVisibleTest::kRightHalfBoundsNoRotation =
1110 Region(Rect(0, 100, 100, 200));
1111const Region OutputEnsureOutputLayerIfVisibleTest::kLowerHalfBoundsNoRotation =
1112 Region(Rect(50, 0, 100, 200));
1113const Region OutputEnsureOutputLayerIfVisibleTest::kFullBounds90Rotation =
1114 Region(Rect(0, 0, 200, 100));
1115
1116TEST_F(OutputEnsureOutputLayerIfVisibleTest, doesNothingIfNoLayerFE) {
1117 EXPECT_CALL(*mLayer, getLayerFE).WillOnce(Return(sp<LayerFE>()));
1118
1119 mOutput.ensureOutputLayerIfVisible(mLayer, mCoverageState);
1120}
1121
1122TEST_F(OutputEnsureOutputLayerIfVisibleTest, performsGeomLatchBeforeCheckingIfLayerBelongs) {
1123 EXPECT_CALL(mOutput, belongsInOutput(mLayer.get())).WillOnce(Return(false));
1124 EXPECT_CALL(*mLayerFE.get(),
1125 latchCompositionState(Ref(mLayerFEState),
1126 compositionengine::LayerFE::StateSubset::BasicGeometry));
1127
1128 mGeomSnapshots.clear();
1129
1130 mOutput.ensureOutputLayerIfVisible(mLayer, mCoverageState);
1131}
1132
1133TEST_F(OutputEnsureOutputLayerIfVisibleTest,
1134 skipsLatchIfAlreadyLatchedBeforeCheckingIfLayerBelongs) {
1135 EXPECT_CALL(mOutput, belongsInOutput(mLayer.get())).WillOnce(Return(false));
1136
1137 mOutput.ensureOutputLayerIfVisible(mLayer, mCoverageState);
1138}
1139
1140TEST_F(OutputEnsureOutputLayerIfVisibleTest, takesEarlyOutIfLayerNotVisible) {
1141 mLayerFEState.isVisible = false;
1142
1143 mOutput.ensureOutputLayerIfVisible(mLayer, mCoverageState);
1144}
1145
1146TEST_F(OutputEnsureOutputLayerIfVisibleTest, takesEarlyOutIfLayerHasEmptyVisibleRegion) {
1147 mLayerFEState.geomLayerBounds = FloatRect{0, 0, 0, 0};
1148
1149 mOutput.ensureOutputLayerIfVisible(mLayer, mCoverageState);
1150}
1151
1152TEST_F(OutputEnsureOutputLayerIfVisibleTest, takesNotSoEarlyOutifDrawRegionEmpty) {
1153 mOutput.mState.bounds = Rect(0, 0, 0, 0);
1154
1155 mOutput.ensureOutputLayerIfVisible(mLayer, mCoverageState);
1156}
1157
1158TEST_F(OutputEnsureOutputLayerIfVisibleTest,
1159 handlesCreatingOutputLayerForOpaqueDirtyNotRotatedLayer) {
1160 mLayerFEState.isOpaque = true;
1161 mLayerFEState.contentDirty = true;
1162 mLayerFEState.geomLayerTransform = ui::Transform(TR_IDENT, 100, 200);
1163
1164 EXPECT_CALL(mOutput, getOutputLayerCount()).WillOnce(Return(0u));
1165 EXPECT_CALL(mOutput, ensureOutputLayer(Eq(std::nullopt), Eq(mLayer), Eq(mLayerFE)))
1166 .WillOnce(Return(&mOutputLayer));
1167
1168 mOutput.ensureOutputLayerIfVisible(mLayer, mCoverageState);
1169
1170 EXPECT_THAT(mCoverageState.dirtyRegion, RegionEq(kFullBoundsNoRotation));
1171 EXPECT_THAT(mCoverageState.aboveCoveredLayers, RegionEq(kFullBoundsNoRotation));
1172 EXPECT_THAT(mCoverageState.aboveOpaqueLayers, RegionEq(kFullBoundsNoRotation));
1173
1174 EXPECT_THAT(mOutputLayerState.visibleRegion, RegionEq(kFullBoundsNoRotation));
1175 EXPECT_THAT(mOutputLayerState.visibleNonTransparentRegion, RegionEq(kFullBoundsNoRotation));
1176 EXPECT_THAT(mOutputLayerState.coveredRegion, RegionEq(kEmptyRegion));
1177 EXPECT_THAT(mOutputLayerState.outputSpaceVisibleRegion, RegionEq(kFullBoundsNoRotation));
1178}
1179
1180TEST_F(OutputEnsureOutputLayerIfVisibleTest,
1181 handlesUpdatingOutputLayerForOpaqueDirtyNotRotatedLayer) {
1182 mLayerFEState.isOpaque = true;
1183 mLayerFEState.contentDirty = true;
1184 mLayerFEState.geomLayerTransform = ui::Transform(TR_IDENT, 100, 200);
1185
1186 EXPECT_CALL(mOutput, ensureOutputLayer(Eq(0u), Eq(mLayer), Eq(mLayerFE)))
1187 .WillOnce(Return(&mOutputLayer));
1188
1189 mOutput.ensureOutputLayerIfVisible(mLayer, mCoverageState);
1190
1191 EXPECT_THAT(mCoverageState.dirtyRegion, RegionEq(kFullBoundsNoRotation));
1192 EXPECT_THAT(mCoverageState.aboveCoveredLayers, RegionEq(kFullBoundsNoRotation));
1193 EXPECT_THAT(mCoverageState.aboveOpaqueLayers, RegionEq(kFullBoundsNoRotation));
1194
1195 EXPECT_THAT(mOutputLayerState.visibleRegion, RegionEq(kFullBoundsNoRotation));
1196 EXPECT_THAT(mOutputLayerState.visibleNonTransparentRegion, RegionEq(kFullBoundsNoRotation));
1197 EXPECT_THAT(mOutputLayerState.coveredRegion, RegionEq(kEmptyRegion));
1198 EXPECT_THAT(mOutputLayerState.outputSpaceVisibleRegion, RegionEq(kFullBoundsNoRotation));
1199}
1200
1201TEST_F(OutputEnsureOutputLayerIfVisibleTest,
1202 handlesCreatingOutputLayerForTransparentDirtyNotRotatedLayer) {
1203 mLayerFEState.isOpaque = false;
1204 mLayerFEState.contentDirty = true;
1205 mLayerFEState.geomLayerTransform = ui::Transform(TR_IDENT, 100, 200);
1206
1207 EXPECT_CALL(mOutput, getOutputLayerCount()).WillOnce(Return(0u));
1208 EXPECT_CALL(mOutput, ensureOutputLayer(Eq(std::nullopt), Eq(mLayer), Eq(mLayerFE)))
1209 .WillOnce(Return(&mOutputLayer));
1210
1211 mOutput.ensureOutputLayerIfVisible(mLayer, mCoverageState);
1212
1213 EXPECT_THAT(mCoverageState.dirtyRegion, RegionEq(kFullBoundsNoRotation));
1214 EXPECT_THAT(mCoverageState.aboveCoveredLayers, RegionEq(kFullBoundsNoRotation));
1215 EXPECT_THAT(mCoverageState.aboveOpaqueLayers, RegionEq(kEmptyRegion));
1216
1217 EXPECT_THAT(mOutputLayerState.visibleRegion, RegionEq(kFullBoundsNoRotation));
1218 EXPECT_THAT(mOutputLayerState.visibleNonTransparentRegion,
1219 RegionEq(kRightHalfBoundsNoRotation));
1220 EXPECT_THAT(mOutputLayerState.coveredRegion, RegionEq(kEmptyRegion));
1221 EXPECT_THAT(mOutputLayerState.outputSpaceVisibleRegion, RegionEq(kFullBoundsNoRotation));
1222}
1223
1224TEST_F(OutputEnsureOutputLayerIfVisibleTest,
1225 handlesUpdatingOutputLayerForTransparentDirtyNotRotatedLayer) {
1226 mLayerFEState.isOpaque = false;
1227 mLayerFEState.contentDirty = true;
1228 mLayerFEState.geomLayerTransform = ui::Transform(TR_IDENT, 100, 200);
1229
1230 EXPECT_CALL(mOutput, ensureOutputLayer(Eq(0u), Eq(mLayer), Eq(mLayerFE)))
1231 .WillOnce(Return(&mOutputLayer));
1232
1233 mOutput.ensureOutputLayerIfVisible(mLayer, mCoverageState);
1234
1235 EXPECT_THAT(mCoverageState.dirtyRegion, RegionEq(kFullBoundsNoRotation));
1236 EXPECT_THAT(mCoverageState.aboveCoveredLayers, RegionEq(kFullBoundsNoRotation));
1237 EXPECT_THAT(mCoverageState.aboveOpaqueLayers, RegionEq(kEmptyRegion));
1238
1239 EXPECT_THAT(mOutputLayerState.visibleRegion, RegionEq(kFullBoundsNoRotation));
1240 EXPECT_THAT(mOutputLayerState.visibleNonTransparentRegion,
1241 RegionEq(kRightHalfBoundsNoRotation));
1242 EXPECT_THAT(mOutputLayerState.coveredRegion, RegionEq(kEmptyRegion));
1243 EXPECT_THAT(mOutputLayerState.outputSpaceVisibleRegion, RegionEq(kFullBoundsNoRotation));
1244}
1245
1246TEST_F(OutputEnsureOutputLayerIfVisibleTest,
1247 handlesCreatingOutputLayerForOpaqueNonDirtyNotRotatedLayer) {
1248 mLayerFEState.isOpaque = true;
1249 mLayerFEState.contentDirty = false;
1250 mLayerFEState.geomLayerTransform = ui::Transform(TR_IDENT, 100, 200);
1251
1252 EXPECT_CALL(mOutput, getOutputLayerCount()).WillOnce(Return(0u));
1253 EXPECT_CALL(mOutput, ensureOutputLayer(Eq(std::nullopt), Eq(mLayer), Eq(mLayerFE)))
1254 .WillOnce(Return(&mOutputLayer));
1255
1256 mOutput.ensureOutputLayerIfVisible(mLayer, mCoverageState);
1257
1258 EXPECT_THAT(mCoverageState.dirtyRegion, RegionEq(kFullBoundsNoRotation));
1259 EXPECT_THAT(mCoverageState.aboveCoveredLayers, RegionEq(kFullBoundsNoRotation));
1260 EXPECT_THAT(mCoverageState.aboveOpaqueLayers, RegionEq(kFullBoundsNoRotation));
1261
1262 EXPECT_THAT(mOutputLayerState.visibleRegion, RegionEq(kFullBoundsNoRotation));
1263 EXPECT_THAT(mOutputLayerState.visibleNonTransparentRegion, RegionEq(kFullBoundsNoRotation));
1264 EXPECT_THAT(mOutputLayerState.coveredRegion, RegionEq(kEmptyRegion));
1265 EXPECT_THAT(mOutputLayerState.outputSpaceVisibleRegion, RegionEq(kFullBoundsNoRotation));
1266}
1267
1268TEST_F(OutputEnsureOutputLayerIfVisibleTest,
1269 handlesUpdatingOutputLayerForOpaqueNonDirtyNotRotatedLayer) {
1270 mLayerFEState.isOpaque = true;
1271 mLayerFEState.contentDirty = false;
1272 mLayerFEState.geomLayerTransform = ui::Transform(TR_IDENT, 100, 200);
1273
1274 EXPECT_CALL(mOutput, ensureOutputLayer(Eq(0u), Eq(mLayer), Eq(mLayerFE)))
1275 .WillOnce(Return(&mOutputLayer));
1276
1277 mOutput.ensureOutputLayerIfVisible(mLayer, mCoverageState);
1278
1279 EXPECT_THAT(mCoverageState.dirtyRegion, RegionEq(kLowerHalfBoundsNoRotation));
1280 EXPECT_THAT(mCoverageState.aboveCoveredLayers, RegionEq(kFullBoundsNoRotation));
1281 EXPECT_THAT(mCoverageState.aboveOpaqueLayers, RegionEq(kFullBoundsNoRotation));
1282
1283 EXPECT_THAT(mOutputLayerState.visibleRegion, RegionEq(kFullBoundsNoRotation));
1284 EXPECT_THAT(mOutputLayerState.visibleNonTransparentRegion, RegionEq(kFullBoundsNoRotation));
1285 EXPECT_THAT(mOutputLayerState.coveredRegion, RegionEq(kEmptyRegion));
1286 EXPECT_THAT(mOutputLayerState.outputSpaceVisibleRegion, RegionEq(kFullBoundsNoRotation));
1287}
1288
1289TEST_F(OutputEnsureOutputLayerIfVisibleTest,
1290 handlesCreatingOutputLayerForOpaqueDirtyRotated90Layer) {
1291 mLayerFEState.isOpaque = true;
1292 mLayerFEState.contentDirty = true;
1293 mLayerFEState.geomLayerBounds = FloatRect{0, 0, 200, 100};
1294 mLayerFEState.geomLayerTransform = ui::Transform(TR_ROT_90, 100, 200);
1295 mOutputLayerState.visibleRegion = Region(Rect(0, 0, 100, 100));
1296 mOutputLayerState.coveredRegion = Region(Rect(100, 0, 200, 100));
1297
1298 EXPECT_CALL(mOutput, getOutputLayerCount()).WillOnce(Return(0u));
1299 EXPECT_CALL(mOutput, ensureOutputLayer(Eq(std::nullopt), Eq(mLayer), Eq(mLayerFE)))
1300 .WillOnce(Return(&mOutputLayer));
1301
1302 mOutput.ensureOutputLayerIfVisible(mLayer, mCoverageState);
1303
1304 EXPECT_THAT(mCoverageState.dirtyRegion, RegionEq(kFullBoundsNoRotation));
1305 EXPECT_THAT(mCoverageState.aboveCoveredLayers, RegionEq(kFullBoundsNoRotation));
1306 EXPECT_THAT(mCoverageState.aboveOpaqueLayers, RegionEq(kFullBoundsNoRotation));
1307
1308 EXPECT_THAT(mOutputLayerState.visibleRegion, RegionEq(kFullBoundsNoRotation));
1309 EXPECT_THAT(mOutputLayerState.visibleNonTransparentRegion, RegionEq(kFullBoundsNoRotation));
1310 EXPECT_THAT(mOutputLayerState.coveredRegion, RegionEq(kEmptyRegion));
1311 EXPECT_THAT(mOutputLayerState.outputSpaceVisibleRegion, RegionEq(kFullBoundsNoRotation));
1312}
1313
1314TEST_F(OutputEnsureOutputLayerIfVisibleTest,
1315 handlesUpdatingOutputLayerForOpaqueDirtyRotated90Layer) {
1316 mLayerFEState.isOpaque = true;
1317 mLayerFEState.contentDirty = true;
1318 mLayerFEState.geomLayerBounds = FloatRect{0, 0, 200, 100};
1319 mLayerFEState.geomLayerTransform = ui::Transform(TR_ROT_90, 100, 200);
1320 mOutputLayerState.visibleRegion = Region(Rect(0, 0, 100, 100));
1321 mOutputLayerState.coveredRegion = Region(Rect(100, 0, 200, 100));
1322
1323 EXPECT_CALL(mOutput, ensureOutputLayer(Eq(0u), Eq(mLayer), Eq(mLayerFE)))
1324 .WillOnce(Return(&mOutputLayer));
1325
1326 mOutput.ensureOutputLayerIfVisible(mLayer, mCoverageState);
1327
1328 EXPECT_THAT(mCoverageState.dirtyRegion, RegionEq(kFullBoundsNoRotation));
1329 EXPECT_THAT(mCoverageState.aboveCoveredLayers, RegionEq(kFullBoundsNoRotation));
1330 EXPECT_THAT(mCoverageState.aboveOpaqueLayers, RegionEq(kFullBoundsNoRotation));
1331
1332 EXPECT_THAT(mOutputLayerState.visibleRegion, RegionEq(kFullBoundsNoRotation));
1333 EXPECT_THAT(mOutputLayerState.visibleNonTransparentRegion, RegionEq(kFullBoundsNoRotation));
1334 EXPECT_THAT(mOutputLayerState.coveredRegion, RegionEq(kEmptyRegion));
1335 EXPECT_THAT(mOutputLayerState.outputSpaceVisibleRegion, RegionEq(kFullBoundsNoRotation));
1336}
1337
1338TEST_F(OutputEnsureOutputLayerIfVisibleTest,
1339 handlesCreatingOutputLayerForOpaqueDirtyNotRotatedLayerRotatedOutput) {
1340 mLayerFEState.isOpaque = true;
1341 mLayerFEState.contentDirty = true;
1342 mLayerFEState.geomLayerTransform = ui::Transform(TR_IDENT, 100, 200);
1343
1344 mOutput.mState.viewport = Rect(0, 0, 300, 200);
1345 mOutput.mState.transform = ui::Transform(TR_ROT_90, 200, 300);
1346
1347 EXPECT_CALL(mOutput, getOutputLayerCount()).WillOnce(Return(0u));
1348 EXPECT_CALL(mOutput, ensureOutputLayer(Eq(std::nullopt), Eq(mLayer), Eq(mLayerFE)))
1349 .WillOnce(Return(&mOutputLayer));
1350
1351 mOutput.ensureOutputLayerIfVisible(mLayer, mCoverageState);
1352
1353 EXPECT_THAT(mCoverageState.dirtyRegion, RegionEq(kFullBoundsNoRotation));
1354 EXPECT_THAT(mCoverageState.aboveCoveredLayers, RegionEq(kFullBoundsNoRotation));
1355 EXPECT_THAT(mCoverageState.aboveOpaqueLayers, RegionEq(kFullBoundsNoRotation));
1356
1357 EXPECT_THAT(mOutputLayerState.visibleRegion, RegionEq(kFullBoundsNoRotation));
1358 EXPECT_THAT(mOutputLayerState.visibleNonTransparentRegion, RegionEq(kFullBoundsNoRotation));
1359 EXPECT_THAT(mOutputLayerState.coveredRegion, RegionEq(kEmptyRegion));
1360 EXPECT_THAT(mOutputLayerState.outputSpaceVisibleRegion, RegionEq(kFullBounds90Rotation));
1361}
1362
1363TEST_F(OutputEnsureOutputLayerIfVisibleTest,
1364 handlesUpdatingOutputLayerForOpaqueDirtyNotRotatedLayerRotatedOutput) {
1365 mLayerFEState.isOpaque = true;
1366 mLayerFEState.contentDirty = true;
1367 mLayerFEState.geomLayerTransform = ui::Transform(TR_IDENT, 100, 200);
1368
1369 mOutput.mState.viewport = Rect(0, 0, 300, 200);
1370 mOutput.mState.transform = ui::Transform(TR_ROT_90, 200, 300);
1371
1372 EXPECT_CALL(mOutput, ensureOutputLayer(Eq(0u), Eq(mLayer), Eq(mLayerFE)))
1373 .WillOnce(Return(&mOutputLayer));
1374
1375 mOutput.ensureOutputLayerIfVisible(mLayer, mCoverageState);
1376
1377 EXPECT_THAT(mCoverageState.dirtyRegion, RegionEq(kFullBoundsNoRotation));
1378 EXPECT_THAT(mCoverageState.aboveCoveredLayers, RegionEq(kFullBoundsNoRotation));
1379 EXPECT_THAT(mCoverageState.aboveOpaqueLayers, RegionEq(kFullBoundsNoRotation));
1380
1381 EXPECT_THAT(mOutputLayerState.visibleRegion, RegionEq(kFullBoundsNoRotation));
1382 EXPECT_THAT(mOutputLayerState.visibleNonTransparentRegion, RegionEq(kFullBoundsNoRotation));
1383 EXPECT_THAT(mOutputLayerState.coveredRegion, RegionEq(kEmptyRegion));
1384 EXPECT_THAT(mOutputLayerState.outputSpaceVisibleRegion, RegionEq(kFullBounds90Rotation));
1385}
1386
1387TEST_F(OutputEnsureOutputLayerIfVisibleTest,
1388 handlesCreatingOutputLayerForOpaqueDirtyArbitraryTransformLayer) {
1389 ui::Transform arbitraryTransform;
1390 arbitraryTransform.set(1, 1, -1, 1);
1391 arbitraryTransform.set(0, 100);
1392
1393 mLayerFEState.isOpaque = true;
1394 mLayerFEState.contentDirty = true;
1395 mLayerFEState.geomLayerBounds = FloatRect{0, 0, 100, 200};
1396 mLayerFEState.geomLayerTransform = arbitraryTransform;
1397
1398 EXPECT_CALL(mOutput, getOutputLayerCount()).WillOnce(Return(0u));
1399 EXPECT_CALL(mOutput, ensureOutputLayer(Eq(std::nullopt), Eq(mLayer), Eq(mLayerFE)))
1400 .WillOnce(Return(&mOutputLayer));
1401
1402 mOutput.ensureOutputLayerIfVisible(mLayer, mCoverageState);
1403
1404 const Region kRegion = Region(Rect(0, 0, 300, 300));
1405 const Region kRegionClipped = Region(Rect(0, 0, 200, 300));
1406
1407 EXPECT_THAT(mCoverageState.dirtyRegion, RegionEq(kRegion));
1408 EXPECT_THAT(mCoverageState.aboveCoveredLayers, RegionEq(kRegion));
1409 EXPECT_THAT(mCoverageState.aboveOpaqueLayers, RegionEq(kEmptyRegion));
1410
1411 EXPECT_THAT(mOutputLayerState.visibleRegion, RegionEq(kRegion));
1412 EXPECT_THAT(mOutputLayerState.visibleNonTransparentRegion, RegionEq(kRegion));
1413 EXPECT_THAT(mOutputLayerState.coveredRegion, RegionEq(kEmptyRegion));
1414 EXPECT_THAT(mOutputLayerState.outputSpaceVisibleRegion, RegionEq(kRegionClipped));
1415}
1416
1417TEST_F(OutputEnsureOutputLayerIfVisibleTest, coverageAccumulatesTest) {
1418 mLayerFEState.isOpaque = false;
1419 mLayerFEState.contentDirty = true;
1420 mLayerFEState.geomLayerTransform = ui::Transform(TR_IDENT, 100, 200);
1421
1422 mCoverageState.dirtyRegion = Region(Rect(0, 0, 500, 500));
1423 mCoverageState.aboveCoveredLayers = Region(Rect(50, 0, 150, 200));
1424 mCoverageState.aboveOpaqueLayers = Region(Rect(50, 0, 150, 200));
1425
1426 EXPECT_CALL(mOutput, ensureOutputLayer(Eq(0u), Eq(mLayer), Eq(mLayerFE)))
1427 .WillOnce(Return(&mOutputLayer));
1428
1429 mOutput.ensureOutputLayerIfVisible(mLayer, mCoverageState);
1430
1431 const Region kExpectedDirtyRegion = Region(Rect(0, 0, 500, 500));
1432 const Region kExpectedAboveCoveredRegion = Region(Rect(0, 0, 150, 200));
1433 const Region kExpectedAboveOpaqueRegion = Region(Rect(50, 0, 150, 200));
1434 const Region kExpectedLayerVisibleRegion = Region(Rect(0, 0, 50, 200));
1435 const Region kExpectedLayerCoveredRegion = Region(Rect(50, 0, 100, 200));
1436 const Region kExpectedLayerVisibleNonTransparentRegion = Region(Rect(0, 100, 50, 200));
1437
1438 EXPECT_THAT(mCoverageState.dirtyRegion, RegionEq(kExpectedDirtyRegion));
1439 EXPECT_THAT(mCoverageState.aboveCoveredLayers, RegionEq(kExpectedAboveCoveredRegion));
1440 EXPECT_THAT(mCoverageState.aboveOpaqueLayers, RegionEq(kExpectedAboveOpaqueRegion));
1441
1442 EXPECT_THAT(mOutputLayerState.visibleRegion, RegionEq(kExpectedLayerVisibleRegion));
1443 EXPECT_THAT(mOutputLayerState.visibleNonTransparentRegion,
1444 RegionEq(kExpectedLayerVisibleNonTransparentRegion));
1445 EXPECT_THAT(mOutputLayerState.coveredRegion, RegionEq(kExpectedLayerCoveredRegion));
1446 EXPECT_THAT(mOutputLayerState.outputSpaceVisibleRegion, RegionEq(kExpectedLayerVisibleRegion));
1447}
Lloyd Piqueb62cebc2019-11-20 18:31:52 -08001448
Vishnu Naira483b4a2019-12-12 15:07:52 -08001449TEST_F(OutputEnsureOutputLayerIfVisibleTest, coverageAccumulatesWithShadowsTest) {
1450 ui::Transform translate;
1451 translate.set(50, 50);
1452 mLayerFEState.geomLayerTransform = translate;
1453 mLayerFEState.shadowRadius = 10.0f;
1454
1455 mCoverageState.dirtyRegion = Region(Rect(0, 0, 500, 500));
1456 // half of the layer including the casting shadow is covered and opaque
1457 mCoverageState.aboveCoveredLayers = Region(Rect(40, 40, 100, 260));
1458 mCoverageState.aboveOpaqueLayers = Region(Rect(40, 40, 100, 260));
1459
1460 EXPECT_CALL(mOutput, ensureOutputLayer(Eq(0u), Eq(mLayer), Eq(mLayerFE)))
1461 .WillOnce(Return(&mOutputLayer));
1462
1463 mOutput.ensureOutputLayerIfVisible(mLayer, mCoverageState);
1464
1465 const Region kExpectedDirtyRegion = Region(Rect(0, 0, 500, 500));
1466 const Region kExpectedAboveCoveredRegion = Region(Rect(40, 40, 160, 260));
1467 // add starting opaque region to the opaque half of the casting layer bounds
1468 const Region kExpectedAboveOpaqueRegion =
1469 Region(Rect(40, 40, 100, 260)).orSelf(Rect(100, 50, 150, 250));
1470 const Region kExpectedLayerVisibleRegion = Region(Rect(100, 40, 160, 260));
1471 const Region kExpectedoutputSpaceLayerVisibleRegion = Region(Rect(100, 50, 150, 250));
1472 const Region kExpectedLayerCoveredRegion = Region(Rect(40, 40, 100, 260));
1473 const Region kExpectedLayerVisibleNonTransparentRegion = Region(Rect(100, 40, 160, 260));
1474 const Region kExpectedLayerShadowRegion =
1475 Region(Rect(40, 40, 160, 260)).subtractSelf(Rect(50, 50, 150, 250));
1476
1477 EXPECT_THAT(mCoverageState.dirtyRegion, RegionEq(kExpectedDirtyRegion));
1478 EXPECT_THAT(mCoverageState.aboveCoveredLayers, RegionEq(kExpectedAboveCoveredRegion));
1479 EXPECT_THAT(mCoverageState.aboveOpaqueLayers, RegionEq(kExpectedAboveOpaqueRegion));
1480
1481 EXPECT_THAT(mOutputLayerState.visibleRegion, RegionEq(kExpectedLayerVisibleRegion));
1482 EXPECT_THAT(mOutputLayerState.visibleNonTransparentRegion,
1483 RegionEq(kExpectedLayerVisibleNonTransparentRegion));
1484 EXPECT_THAT(mOutputLayerState.coveredRegion, RegionEq(kExpectedLayerCoveredRegion));
1485 EXPECT_THAT(mOutputLayerState.outputSpaceVisibleRegion,
1486 RegionEq(kExpectedoutputSpaceLayerVisibleRegion));
1487 EXPECT_THAT(mOutputLayerState.shadowRegion, RegionEq(kExpectedLayerShadowRegion));
1488 EXPECT_FALSE(kExpectedLayerVisibleRegion.subtract(kExpectedLayerShadowRegion).isEmpty());
1489}
1490
1491TEST_F(OutputEnsureOutputLayerIfVisibleTest, shadowRegionOnlyTest) {
1492 ui::Transform translate;
1493 translate.set(50, 50);
1494 mLayerFEState.geomLayerTransform = translate;
1495 mLayerFEState.shadowRadius = 10.0f;
1496
1497 mCoverageState.dirtyRegion = Region(Rect(0, 0, 500, 500));
1498 // Casting layer is covered by an opaque region leaving only part of its shadow to be drawn
1499 mCoverageState.aboveCoveredLayers = Region(Rect(40, 40, 150, 260));
1500 mCoverageState.aboveOpaqueLayers = Region(Rect(40, 40, 150, 260));
1501
1502 EXPECT_CALL(mOutput, ensureOutputLayer(Eq(0u), Eq(mLayer), Eq(mLayerFE)))
1503 .WillOnce(Return(&mOutputLayer));
1504
1505 mOutput.ensureOutputLayerIfVisible(mLayer, mCoverageState);
1506
1507 const Region kExpectedLayerVisibleRegion = Region(Rect(150, 40, 160, 260));
1508 const Region kExpectedLayerShadowRegion =
1509 Region(Rect(40, 40, 160, 260)).subtractSelf(Rect(50, 50, 150, 250));
1510
1511 EXPECT_THAT(mOutputLayerState.visibleRegion, RegionEq(kExpectedLayerVisibleRegion));
1512 EXPECT_THAT(mOutputLayerState.shadowRegion, RegionEq(kExpectedLayerShadowRegion));
1513 EXPECT_TRUE(kExpectedLayerVisibleRegion.subtract(kExpectedLayerShadowRegion).isEmpty());
1514}
1515
1516TEST_F(OutputEnsureOutputLayerIfVisibleTest, takesNotSoEarlyOutifLayerWithShadowIsCovered) {
1517 ui::Transform translate;
1518 translate.set(50, 50);
1519 mLayerFEState.geomLayerTransform = translate;
1520 mLayerFEState.shadowRadius = 10.0f;
1521
1522 mCoverageState.dirtyRegion = Region(Rect(0, 0, 500, 500));
1523 // Casting layer and its shadows are covered by an opaque region
1524 mCoverageState.aboveCoveredLayers = Region(Rect(40, 40, 160, 260));
1525 mCoverageState.aboveOpaqueLayers = Region(Rect(40, 40, 160, 260));
1526
1527 mOutput.ensureOutputLayerIfVisible(mLayer, mCoverageState);
1528}
1529
Lloyd Piqueb62cebc2019-11-20 18:31:52 -08001530/*
Lloyd Piquefaa3f192019-11-14 14:05:09 -08001531 * Output::present()
1532 */
1533
1534struct OutputPresentTest : public testing::Test {
1535 struct OutputPartialMock : public OutputPartialMockBase {
Lloyd Pique739afaf2019-11-21 16:40:05 -08001536 // Sets up the helper functions called by the function under test to use
1537 // mock implementations.
Lloyd Piquefaa3f192019-11-14 14:05:09 -08001538 MOCK_METHOD1(updateColorProfile, void(const compositionengine::CompositionRefreshArgs&));
1539 MOCK_METHOD1(updateAndWriteCompositionState,
1540 void(const compositionengine::CompositionRefreshArgs&));
1541 MOCK_METHOD1(setColorTransform, void(const compositionengine::CompositionRefreshArgs&));
1542 MOCK_METHOD0(beginFrame, void());
1543 MOCK_METHOD0(prepareFrame, void());
1544 MOCK_METHOD1(devOptRepaintFlash, void(const compositionengine::CompositionRefreshArgs&));
1545 MOCK_METHOD1(finishFrame, void(const compositionengine::CompositionRefreshArgs&));
1546 MOCK_METHOD0(postFramebuffer, void());
1547 };
1548
1549 StrictMock<OutputPartialMock> mOutput;
1550};
1551
1552TEST_F(OutputPresentTest, justInvokesChildFunctionsInSequence) {
1553 CompositionRefreshArgs args;
1554
1555 InSequence seq;
1556 EXPECT_CALL(mOutput, updateColorProfile(Ref(args)));
1557 EXPECT_CALL(mOutput, updateAndWriteCompositionState(Ref(args)));
1558 EXPECT_CALL(mOutput, setColorTransform(Ref(args)));
1559 EXPECT_CALL(mOutput, beginFrame());
1560 EXPECT_CALL(mOutput, prepareFrame());
1561 EXPECT_CALL(mOutput, devOptRepaintFlash(Ref(args)));
1562 EXPECT_CALL(mOutput, finishFrame(Ref(args)));
1563 EXPECT_CALL(mOutput, postFramebuffer());
1564
1565 mOutput.present(args);
1566}
1567
1568/*
1569 * Output::updateColorProfile()
1570 */
1571
Lloyd Pique17ca7422019-11-14 14:24:10 -08001572struct OutputUpdateColorProfileTest : public testing::Test {
1573 using TestType = OutputUpdateColorProfileTest;
1574
1575 struct OutputPartialMock : public OutputPartialMockBase {
Lloyd Pique739afaf2019-11-21 16:40:05 -08001576 // Sets up the helper functions called by the function under test to use
1577 // mock implementations.
Lloyd Pique17ca7422019-11-14 14:24:10 -08001578 MOCK_METHOD1(setColorProfile, void(const ColorProfile&));
1579 };
1580
1581 struct Layer {
1582 Layer() {
1583 EXPECT_CALL(mOutputLayer, getLayer()).WillRepeatedly(ReturnRef(mLayer));
1584 EXPECT_CALL(mOutputLayer, getLayerFE()).WillRepeatedly(ReturnRef(mLayerFE));
1585 EXPECT_CALL(mLayer, getFEState()).WillRepeatedly(ReturnRef(mLayerFEState));
1586 }
1587
1588 StrictMock<mock::OutputLayer> mOutputLayer;
1589 StrictMock<mock::Layer> mLayer;
1590 StrictMock<mock::LayerFE> mLayerFE;
1591 LayerFECompositionState mLayerFEState;
1592 };
1593
1594 OutputUpdateColorProfileTest() {
1595 mOutput.setDisplayColorProfileForTest(
1596 std::unique_ptr<DisplayColorProfile>(mDisplayColorProfile));
1597 mOutput.setRenderSurfaceForTest(std::unique_ptr<RenderSurface>(mRenderSurface));
1598
1599 EXPECT_CALL(mOutput, getOutputLayerOrderedByZByIndex(0))
1600 .WillRepeatedly(Return(&mLayer1.mOutputLayer));
1601 EXPECT_CALL(mOutput, getOutputLayerOrderedByZByIndex(1))
1602 .WillRepeatedly(Return(&mLayer2.mOutputLayer));
1603 EXPECT_CALL(mOutput, getOutputLayerOrderedByZByIndex(2))
1604 .WillRepeatedly(Return(&mLayer3.mOutputLayer));
1605 }
1606
1607 struct ExecuteState : public CallOrderStateMachineHelper<TestType, ExecuteState> {
1608 void execute() { getInstance()->mOutput.updateColorProfile(getInstance()->mRefreshArgs); }
1609 };
1610
1611 mock::DisplayColorProfile* mDisplayColorProfile = new StrictMock<mock::DisplayColorProfile>();
1612 mock::RenderSurface* mRenderSurface = new StrictMock<mock::RenderSurface>();
1613 StrictMock<OutputPartialMock> mOutput;
1614
1615 Layer mLayer1;
1616 Layer mLayer2;
1617 Layer mLayer3;
1618
1619 CompositionRefreshArgs mRefreshArgs;
1620};
1621
1622// TODO(b/144522012): Refactor Output::updateColorProfile and the related code
1623// to make it easier to write unit tests.
1624
1625TEST_F(OutputUpdateColorProfileTest, setsAColorProfileWhenUnmanaged) {
1626 // When the outputColorSetting is set to kUnmanaged, the implementation sets
1627 // a simple default color profile without looking at anything else.
1628
Lloyd Pique0a456232020-01-16 17:51:13 -08001629 EXPECT_CALL(mOutput, getOutputLayerCount()).WillRepeatedly(Return(3u));
Lloyd Pique17ca7422019-11-14 14:24:10 -08001630 EXPECT_CALL(mOutput,
1631 setColorProfile(ColorProfileEq(
1632 ColorProfile{ui::ColorMode::NATIVE, ui::Dataspace::UNKNOWN,
1633 ui::RenderIntent::COLORIMETRIC, ui::Dataspace::UNKNOWN})));
1634
1635 mRefreshArgs.outputColorSetting = OutputColorSetting::kUnmanaged;
1636 mRefreshArgs.colorSpaceAgnosticDataspace = ui::Dataspace::UNKNOWN;
1637
1638 mOutput.updateColorProfile(mRefreshArgs);
1639}
1640
1641struct OutputUpdateColorProfileTest_GetBestColorModeResultBecomesSetProfile
1642 : public OutputUpdateColorProfileTest {
1643 OutputUpdateColorProfileTest_GetBestColorModeResultBecomesSetProfile() {
Lloyd Pique0a456232020-01-16 17:51:13 -08001644 EXPECT_CALL(mOutput, getOutputLayerCount()).WillRepeatedly(Return(0u));
Lloyd Pique17ca7422019-11-14 14:24:10 -08001645 mRefreshArgs.outputColorSetting = OutputColorSetting::kEnhanced;
1646 mRefreshArgs.colorSpaceAgnosticDataspace = ui::Dataspace::UNKNOWN;
1647 }
1648
1649 struct ExpectBestColorModeCallResultUsedToSetColorProfileState
1650 : public CallOrderStateMachineHelper<
1651 TestType, ExpectBestColorModeCallResultUsedToSetColorProfileState> {
1652 [[nodiscard]] auto expectBestColorModeCallResultUsedToSetColorProfile(
1653 ui::ColorMode colorMode, ui::Dataspace dataspace, ui::RenderIntent renderIntent) {
1654 EXPECT_CALL(*getInstance()->mDisplayColorProfile,
1655 getBestColorMode(ui::Dataspace::V0_SRGB, ui::RenderIntent::ENHANCE, _, _,
1656 _))
1657 .WillOnce(DoAll(SetArgPointee<2>(dataspace), SetArgPointee<3>(colorMode),
1658 SetArgPointee<4>(renderIntent)));
1659 EXPECT_CALL(getInstance()->mOutput,
1660 setColorProfile(
1661 ColorProfileEq(ColorProfile{colorMode, dataspace, renderIntent,
1662 ui::Dataspace::UNKNOWN})));
1663 return nextState<ExecuteState>();
1664 }
1665 };
1666
1667 // Call this member function to start using the mini-DSL defined above.
1668 [[nodiscard]] auto verify() {
1669 return ExpectBestColorModeCallResultUsedToSetColorProfileState::make(this);
1670 }
1671};
1672
1673TEST_F(OutputUpdateColorProfileTest_GetBestColorModeResultBecomesSetProfile,
1674 Native_Unknown_Colorimetric_Set) {
1675 verify().expectBestColorModeCallResultUsedToSetColorProfile(ui::ColorMode::NATIVE,
1676 ui::Dataspace::UNKNOWN,
1677 ui::RenderIntent::COLORIMETRIC)
1678 .execute();
1679}
1680
1681TEST_F(OutputUpdateColorProfileTest_GetBestColorModeResultBecomesSetProfile,
1682 DisplayP3_DisplayP3_Enhance_Set) {
1683 verify().expectBestColorModeCallResultUsedToSetColorProfile(ui::ColorMode::DISPLAY_P3,
1684 ui::Dataspace::DISPLAY_P3,
1685 ui::RenderIntent::ENHANCE)
1686 .execute();
1687}
1688
1689struct OutputUpdateColorProfileTest_ColorSpaceAgnosticeDataspaceAffectsSetColorProfile
1690 : public OutputUpdateColorProfileTest {
1691 OutputUpdateColorProfileTest_ColorSpaceAgnosticeDataspaceAffectsSetColorProfile() {
Lloyd Pique0a456232020-01-16 17:51:13 -08001692 EXPECT_CALL(mOutput, getOutputLayerCount()).WillRepeatedly(Return(0u));
Lloyd Pique17ca7422019-11-14 14:24:10 -08001693 EXPECT_CALL(*mDisplayColorProfile,
1694 getBestColorMode(ui::Dataspace::V0_SRGB, ui::RenderIntent::ENHANCE, _, _, _))
1695 .WillRepeatedly(DoAll(SetArgPointee<2>(ui::Dataspace::UNKNOWN),
1696 SetArgPointee<3>(ui::ColorMode::NATIVE),
1697 SetArgPointee<4>(ui::RenderIntent::COLORIMETRIC)));
1698 mRefreshArgs.outputColorSetting = OutputColorSetting::kEnhanced;
1699 }
1700
1701 struct IfColorSpaceAgnosticDataspaceSetToState
1702 : public CallOrderStateMachineHelper<TestType, IfColorSpaceAgnosticDataspaceSetToState> {
1703 [[nodiscard]] auto ifColorSpaceAgnosticDataspaceSetTo(ui::Dataspace dataspace) {
1704 getInstance()->mRefreshArgs.colorSpaceAgnosticDataspace = dataspace;
1705 return nextState<ThenExpectSetColorProfileCallUsesColorSpaceAgnosticDataspaceState>();
1706 }
1707 };
1708
1709 struct ThenExpectSetColorProfileCallUsesColorSpaceAgnosticDataspaceState
1710 : public CallOrderStateMachineHelper<
1711 TestType, ThenExpectSetColorProfileCallUsesColorSpaceAgnosticDataspaceState> {
1712 [[nodiscard]] auto thenExpectSetColorProfileCallUsesColorSpaceAgnosticDataspace(
1713 ui::Dataspace dataspace) {
1714 EXPECT_CALL(getInstance()->mOutput,
1715 setColorProfile(ColorProfileEq(
1716 ColorProfile{ui::ColorMode::NATIVE, ui::Dataspace::UNKNOWN,
1717 ui::RenderIntent::COLORIMETRIC, dataspace})));
1718 return nextState<ExecuteState>();
1719 }
1720 };
1721
1722 // Call this member function to start using the mini-DSL defined above.
1723 [[nodiscard]] auto verify() { return IfColorSpaceAgnosticDataspaceSetToState::make(this); }
1724};
1725
1726TEST_F(OutputUpdateColorProfileTest_ColorSpaceAgnosticeDataspaceAffectsSetColorProfile, DisplayP3) {
1727 verify().ifColorSpaceAgnosticDataspaceSetTo(ui::Dataspace::DISPLAY_P3)
1728 .thenExpectSetColorProfileCallUsesColorSpaceAgnosticDataspace(ui::Dataspace::DISPLAY_P3)
1729 .execute();
1730}
1731
1732TEST_F(OutputUpdateColorProfileTest_ColorSpaceAgnosticeDataspaceAffectsSetColorProfile, V0_SRGB) {
1733 verify().ifColorSpaceAgnosticDataspaceSetTo(ui::Dataspace::V0_SRGB)
1734 .thenExpectSetColorProfileCallUsesColorSpaceAgnosticDataspace(ui::Dataspace::V0_SRGB)
1735 .execute();
1736}
1737
1738struct OutputUpdateColorProfileTest_TopmostLayerPreferenceSetsOutputPreference
1739 : public OutputUpdateColorProfileTest {
1740 // Internally the implementation looks through the dataspaces of all the
1741 // visible layers. The topmost one that also has an actual dataspace
1742 // preference set is used to drive subsequent choices.
1743
1744 OutputUpdateColorProfileTest_TopmostLayerPreferenceSetsOutputPreference() {
1745 mRefreshArgs.outputColorSetting = OutputColorSetting::kEnhanced;
1746 mRefreshArgs.colorSpaceAgnosticDataspace = ui::Dataspace::UNKNOWN;
1747
Lloyd Pique0a456232020-01-16 17:51:13 -08001748 EXPECT_CALL(mOutput, getOutputLayerCount()).WillRepeatedly(Return(3u));
Lloyd Pique17ca7422019-11-14 14:24:10 -08001749 EXPECT_CALL(mOutput, setColorProfile(_)).WillRepeatedly(Return());
1750 }
1751
1752 struct IfTopLayerDataspaceState
1753 : public CallOrderStateMachineHelper<TestType, IfTopLayerDataspaceState> {
1754 [[nodiscard]] auto ifTopLayerIs(ui::Dataspace dataspace) {
1755 getInstance()->mLayer3.mLayerFEState.dataspace = dataspace;
1756 return nextState<AndIfMiddleLayerDataspaceState>();
1757 }
1758 [[nodiscard]] auto ifTopLayerHasNoPreference() {
1759 return ifTopLayerIs(ui::Dataspace::UNKNOWN);
1760 }
1761 };
1762
1763 struct AndIfMiddleLayerDataspaceState
1764 : public CallOrderStateMachineHelper<TestType, AndIfMiddleLayerDataspaceState> {
1765 [[nodiscard]] auto andIfMiddleLayerIs(ui::Dataspace dataspace) {
1766 getInstance()->mLayer2.mLayerFEState.dataspace = dataspace;
1767 return nextState<AndIfBottomLayerDataspaceState>();
1768 }
1769 [[nodiscard]] auto andIfMiddleLayerHasNoPreference() {
1770 return andIfMiddleLayerIs(ui::Dataspace::UNKNOWN);
1771 }
1772 };
1773
1774 struct AndIfBottomLayerDataspaceState
1775 : public CallOrderStateMachineHelper<TestType, AndIfBottomLayerDataspaceState> {
1776 [[nodiscard]] auto andIfBottomLayerIs(ui::Dataspace dataspace) {
1777 getInstance()->mLayer1.mLayerFEState.dataspace = dataspace;
1778 return nextState<ThenExpectBestColorModeCallUsesState>();
1779 }
1780 [[nodiscard]] auto andIfBottomLayerHasNoPreference() {
1781 return andIfBottomLayerIs(ui::Dataspace::UNKNOWN);
1782 }
1783 };
1784
1785 struct ThenExpectBestColorModeCallUsesState
1786 : public CallOrderStateMachineHelper<TestType, ThenExpectBestColorModeCallUsesState> {
1787 [[nodiscard]] auto thenExpectBestColorModeCallUses(ui::Dataspace dataspace) {
1788 EXPECT_CALL(*getInstance()->mDisplayColorProfile,
1789 getBestColorMode(dataspace, _, _, _, _));
1790 return nextState<ExecuteState>();
1791 }
1792 };
1793
1794 // Call this member function to start using the mini-DSL defined above.
1795 [[nodiscard]] auto verify() { return IfTopLayerDataspaceState::make(this); }
1796};
1797
1798TEST_F(OutputUpdateColorProfileTest_TopmostLayerPreferenceSetsOutputPreference,
1799 noStrongLayerPrefenceUses_V0_SRGB) {
1800 // If none of the layers indicate a preference, then V0_SRGB is the
1801 // preferred choice (subject to additional checks).
1802 verify().ifTopLayerHasNoPreference()
1803 .andIfMiddleLayerHasNoPreference()
1804 .andIfBottomLayerHasNoPreference()
1805 .thenExpectBestColorModeCallUses(ui::Dataspace::V0_SRGB)
1806 .execute();
1807}
1808
1809TEST_F(OutputUpdateColorProfileTest_TopmostLayerPreferenceSetsOutputPreference,
1810 ifTopmostUses_DisplayP3_Then_DisplayP3_Chosen) {
1811 // If only the topmost layer has a preference, then that is what is chosen.
1812 verify().ifTopLayerIs(ui::Dataspace::DISPLAY_P3)
1813 .andIfMiddleLayerHasNoPreference()
1814 .andIfBottomLayerHasNoPreference()
1815 .thenExpectBestColorModeCallUses(ui::Dataspace::DISPLAY_P3)
1816 .execute();
1817}
1818
1819TEST_F(OutputUpdateColorProfileTest_TopmostLayerPreferenceSetsOutputPreference,
1820 ifMiddleUses_DisplayP3_Then_DisplayP3_Chosen) {
1821 // If only the middle layer has a preference, that that is what is chosen.
1822 verify().ifTopLayerHasNoPreference()
1823 .andIfMiddleLayerIs(ui::Dataspace::DISPLAY_P3)
1824 .andIfBottomLayerHasNoPreference()
1825 .thenExpectBestColorModeCallUses(ui::Dataspace::DISPLAY_P3)
1826 .execute();
1827}
1828
1829TEST_F(OutputUpdateColorProfileTest_TopmostLayerPreferenceSetsOutputPreference,
1830 ifBottomUses_DisplayP3_Then_DisplayP3_Chosen) {
1831 // If only the middle layer has a preference, that that is what is chosen.
1832 verify().ifTopLayerHasNoPreference()
1833 .andIfMiddleLayerHasNoPreference()
1834 .andIfBottomLayerIs(ui::Dataspace::DISPLAY_P3)
1835 .thenExpectBestColorModeCallUses(ui::Dataspace::DISPLAY_P3)
1836 .execute();
1837}
1838
1839TEST_F(OutputUpdateColorProfileTest_TopmostLayerPreferenceSetsOutputPreference,
1840 ifTopUses_DisplayBT2020_AndBottomUses_DisplayP3_Then_DisplayBT2020_Chosen) {
1841 // If multiple layers have a preference, the topmost value is what is used.
1842 verify().ifTopLayerIs(ui::Dataspace::DISPLAY_BT2020)
1843 .andIfMiddleLayerHasNoPreference()
1844 .andIfBottomLayerIs(ui::Dataspace::DISPLAY_P3)
1845 .thenExpectBestColorModeCallUses(ui::Dataspace::DISPLAY_BT2020)
1846 .execute();
1847}
1848
1849TEST_F(OutputUpdateColorProfileTest_TopmostLayerPreferenceSetsOutputPreference,
1850 ifTopUses_DisplayP3_AndBottomUses_V0_SRGB_Then_DisplayP3_Chosen) {
1851 // If multiple layers have a preference, the topmost value is what is used.
1852 verify().ifTopLayerIs(ui::Dataspace::DISPLAY_P3)
1853 .andIfMiddleLayerHasNoPreference()
1854 .andIfBottomLayerIs(ui::Dataspace::DISPLAY_BT2020)
1855 .thenExpectBestColorModeCallUses(ui::Dataspace::DISPLAY_P3)
1856 .execute();
1857}
1858
1859struct OutputUpdateColorProfileTest_ForceOutputColorOverrides
1860 : public OutputUpdateColorProfileTest {
1861 // If CompositionRefreshArgs::forceOutputColorMode is set to some specific
1862 // values, it overrides the layer dataspace choice.
1863
1864 OutputUpdateColorProfileTest_ForceOutputColorOverrides() {
1865 mRefreshArgs.outputColorSetting = OutputColorSetting::kEnhanced;
1866 mRefreshArgs.colorSpaceAgnosticDataspace = ui::Dataspace::UNKNOWN;
1867
1868 mLayer1.mLayerFEState.dataspace = ui::Dataspace::DISPLAY_BT2020;
1869
Lloyd Pique0a456232020-01-16 17:51:13 -08001870 EXPECT_CALL(mOutput, getOutputLayerCount()).WillRepeatedly(Return(1u));
Lloyd Pique17ca7422019-11-14 14:24:10 -08001871 EXPECT_CALL(mOutput, setColorProfile(_)).WillRepeatedly(Return());
1872 }
1873
1874 struct IfForceOutputColorModeState
1875 : public CallOrderStateMachineHelper<TestType, IfForceOutputColorModeState> {
1876 [[nodiscard]] auto ifForceOutputColorMode(ui::ColorMode colorMode) {
1877 getInstance()->mRefreshArgs.forceOutputColorMode = colorMode;
1878 return nextState<ThenExpectBestColorModeCallUsesState>();
1879 }
1880 [[nodiscard]] auto ifNoOverride() { return ifForceOutputColorMode(ui::ColorMode::NATIVE); }
1881 };
1882
1883 struct ThenExpectBestColorModeCallUsesState
1884 : public CallOrderStateMachineHelper<TestType, ThenExpectBestColorModeCallUsesState> {
1885 [[nodiscard]] auto thenExpectBestColorModeCallUses(ui::Dataspace dataspace) {
1886 EXPECT_CALL(*getInstance()->mDisplayColorProfile,
1887 getBestColorMode(dataspace, _, _, _, _));
1888 return nextState<ExecuteState>();
1889 }
1890 };
1891
1892 // Call this member function to start using the mini-DSL defined above.
1893 [[nodiscard]] auto verify() { return IfForceOutputColorModeState::make(this); }
1894};
1895
1896TEST_F(OutputUpdateColorProfileTest_ForceOutputColorOverrides, NoOverride_DoesNotOverride) {
1897 // By default the layer state is used to set the preferred dataspace
1898 verify().ifNoOverride()
1899 .thenExpectBestColorModeCallUses(ui::Dataspace::DISPLAY_BT2020)
1900 .execute();
1901}
1902
1903TEST_F(OutputUpdateColorProfileTest_ForceOutputColorOverrides, SRGB_Override_USES_V0_SRGB) {
1904 // Setting ui::ColorMode::SRGB overrides it with ui::Dataspace::V0_SRGB
1905 verify().ifForceOutputColorMode(ui::ColorMode::SRGB)
1906 .thenExpectBestColorModeCallUses(ui::Dataspace::V0_SRGB)
1907 .execute();
1908}
1909
1910TEST_F(OutputUpdateColorProfileTest_ForceOutputColorOverrides, DisplayP3_Override_Uses_DisplayP3) {
1911 // Setting ui::ColorMode::DISPLAY_P3 overrides it with ui::Dataspace::DISPLAY_P3
1912 verify().ifForceOutputColorMode(ui::ColorMode::DISPLAY_P3)
1913 .thenExpectBestColorModeCallUses(ui::Dataspace::DISPLAY_P3)
1914 .execute();
1915}
1916
1917// HDR output requires all layers to be compatible with the chosen HDR
1918// dataspace, along with there being proper support.
1919struct OutputUpdateColorProfileTest_Hdr : public OutputUpdateColorProfileTest {
1920 OutputUpdateColorProfileTest_Hdr() {
1921 mRefreshArgs.outputColorSetting = OutputColorSetting::kEnhanced;
1922 mRefreshArgs.colorSpaceAgnosticDataspace = ui::Dataspace::UNKNOWN;
Lloyd Pique0a456232020-01-16 17:51:13 -08001923 EXPECT_CALL(mOutput, getOutputLayerCount()).WillRepeatedly(Return(2u));
Lloyd Pique17ca7422019-11-14 14:24:10 -08001924 EXPECT_CALL(mOutput, setColorProfile(_)).WillRepeatedly(Return());
1925 }
1926
1927 static constexpr ui::Dataspace kNonHdrDataspace = ui::Dataspace::DISPLAY_P3;
1928 static constexpr ui::Dataspace BT2020_PQ = ui::Dataspace::BT2020_PQ;
1929 static constexpr ui::Dataspace BT2020_HLG = ui::Dataspace::BT2020_HLG;
1930 static constexpr ui::Dataspace DISPLAY_P3 = ui::Dataspace::DISPLAY_P3;
1931
1932 struct IfTopLayerDataspaceState
1933 : public CallOrderStateMachineHelper<TestType, IfTopLayerDataspaceState> {
1934 [[nodiscard]] auto ifTopLayerIs(ui::Dataspace dataspace) {
1935 getInstance()->mLayer2.mLayerFEState.dataspace = dataspace;
1936 return nextState<AndTopLayerCompositionTypeState>();
1937 }
1938 [[nodiscard]] auto ifTopLayerIsNotHdr() { return ifTopLayerIs(kNonHdrDataspace); }
1939 };
1940
1941 struct AndTopLayerCompositionTypeState
1942 : public CallOrderStateMachineHelper<TestType, AndTopLayerCompositionTypeState> {
1943 [[nodiscard]] auto andTopLayerIsREComposed(bool renderEngineComposed) {
1944 getInstance()->mLayer2.mLayerFEState.forceClientComposition = renderEngineComposed;
1945 return nextState<AndIfBottomLayerDataspaceState>();
1946 }
1947 };
1948
1949 struct AndIfBottomLayerDataspaceState
1950 : public CallOrderStateMachineHelper<TestType, AndIfBottomLayerDataspaceState> {
1951 [[nodiscard]] auto andIfBottomLayerIs(ui::Dataspace dataspace) {
1952 getInstance()->mLayer1.mLayerFEState.dataspace = dataspace;
1953 return nextState<AndBottomLayerCompositionTypeState>();
1954 }
1955 [[nodiscard]] auto andIfBottomLayerIsNotHdr() {
1956 return andIfBottomLayerIs(kNonHdrDataspace);
1957 }
1958 };
1959
1960 struct AndBottomLayerCompositionTypeState
1961 : public CallOrderStateMachineHelper<TestType, AndBottomLayerCompositionTypeState> {
1962 [[nodiscard]] auto andBottomLayerIsREComposed(bool renderEngineComposed) {
1963 getInstance()->mLayer1.mLayerFEState.forceClientComposition = renderEngineComposed;
1964 return nextState<AndIfHasLegacySupportState>();
1965 }
1966 };
1967
1968 struct AndIfHasLegacySupportState
1969 : public CallOrderStateMachineHelper<TestType, AndIfHasLegacySupportState> {
1970 [[nodiscard]] auto andIfLegacySupportFor(ui::Dataspace dataspace, bool legacySupport) {
1971 EXPECT_CALL(*getInstance()->mDisplayColorProfile, hasLegacyHdrSupport(dataspace))
1972 .WillOnce(Return(legacySupport));
1973 return nextState<ThenExpectBestColorModeCallUsesState>();
1974 }
1975 };
1976
1977 struct ThenExpectBestColorModeCallUsesState
1978 : public CallOrderStateMachineHelper<TestType, ThenExpectBestColorModeCallUsesState> {
1979 [[nodiscard]] auto thenExpectBestColorModeCallUses(ui::Dataspace dataspace) {
1980 EXPECT_CALL(*getInstance()->mDisplayColorProfile,
1981 getBestColorMode(dataspace, _, _, _, _));
1982 return nextState<ExecuteState>();
1983 }
1984 };
1985
1986 // Call this member function to start using the mini-DSL defined above.
1987 [[nodiscard]] auto verify() { return IfTopLayerDataspaceState::make(this); }
1988};
1989
1990TEST_F(OutputUpdateColorProfileTest_Hdr, PQ_HW_On_PQ_HW_Uses_PQ) {
1991 // If all layers use BT2020_PQ, and there are no other special conditions,
1992 // BT2020_PQ is used.
1993 verify().ifTopLayerIs(BT2020_PQ)
1994 .andTopLayerIsREComposed(false)
1995 .andIfBottomLayerIs(BT2020_PQ)
1996 .andBottomLayerIsREComposed(false)
1997 .andIfLegacySupportFor(BT2020_PQ, false)
1998 .thenExpectBestColorModeCallUses(BT2020_PQ)
1999 .execute();
2000}
2001
2002TEST_F(OutputUpdateColorProfileTest_Hdr, PQ_HW_On_PQ_HW_IfPQHasLegacySupport_Uses_DisplayP3) {
2003 // BT2020_PQ is not used if there is only legacy support for it.
2004 verify().ifTopLayerIs(BT2020_PQ)
2005 .andTopLayerIsREComposed(false)
2006 .andIfBottomLayerIs(BT2020_PQ)
2007 .andBottomLayerIsREComposed(false)
2008 .andIfLegacySupportFor(BT2020_PQ, true)
2009 .thenExpectBestColorModeCallUses(DISPLAY_P3)
2010 .execute();
2011}
2012
2013TEST_F(OutputUpdateColorProfileTest_Hdr, PQ_HW_On_PQ_RE_Uses_PQ) {
2014 // BT2020_PQ is still used if the bottom layer is RenderEngine composed.
2015 verify().ifTopLayerIs(BT2020_PQ)
2016 .andTopLayerIsREComposed(false)
2017 .andIfBottomLayerIs(BT2020_PQ)
2018 .andBottomLayerIsREComposed(true)
2019 .andIfLegacySupportFor(BT2020_PQ, false)
2020 .thenExpectBestColorModeCallUses(BT2020_PQ)
2021 .execute();
2022}
2023
2024TEST_F(OutputUpdateColorProfileTest_Hdr, PQ_RE_On_PQ_HW_Uses_DisplayP3) {
2025 // BT2020_PQ is not used if the top layer is RenderEngine composed.
2026 verify().ifTopLayerIs(BT2020_PQ)
2027 .andTopLayerIsREComposed(true)
2028 .andIfBottomLayerIs(BT2020_PQ)
2029 .andBottomLayerIsREComposed(false)
2030 .andIfLegacySupportFor(BT2020_PQ, false)
2031 .thenExpectBestColorModeCallUses(DISPLAY_P3)
2032 .execute();
2033}
2034
2035TEST_F(OutputUpdateColorProfileTest_Hdr, PQ_HW_On_HLG_HW_Uses_PQ) {
2036 // If there is mixed HLG/PQ use, and the topmost layer is PQ, then PQ is used if there
2037 // are no other special conditions.
2038 verify().ifTopLayerIs(BT2020_PQ)
2039 .andTopLayerIsREComposed(false)
2040 .andIfBottomLayerIs(BT2020_HLG)
2041 .andBottomLayerIsREComposed(false)
2042 .andIfLegacySupportFor(BT2020_PQ, false)
2043 .thenExpectBestColorModeCallUses(BT2020_PQ)
2044 .execute();
2045}
2046
2047TEST_F(OutputUpdateColorProfileTest_Hdr, PQ_HW_On_HLG_HW_IfPQHasLegacySupport_Uses_DisplayP3) {
2048 // BT2020_PQ is not used if there is only legacy support for it.
2049 verify().ifTopLayerIs(BT2020_PQ)
2050 .andTopLayerIsREComposed(false)
2051 .andIfBottomLayerIs(BT2020_HLG)
2052 .andBottomLayerIsREComposed(false)
2053 .andIfLegacySupportFor(BT2020_PQ, true)
2054 .thenExpectBestColorModeCallUses(DISPLAY_P3)
2055 .execute();
2056}
2057
2058TEST_F(OutputUpdateColorProfileTest_Hdr, PQ_HW_On_HLG_RE_Uses_PQ) {
2059 // BT2020_PQ is used if the bottom HLG layer is RenderEngine composed.
2060 verify().ifTopLayerIs(BT2020_PQ)
2061 .andTopLayerIsREComposed(false)
2062 .andIfBottomLayerIs(BT2020_HLG)
2063 .andBottomLayerIsREComposed(true)
2064 .andIfLegacySupportFor(BT2020_PQ, false)
2065 .thenExpectBestColorModeCallUses(BT2020_PQ)
2066 .execute();
2067}
2068
2069TEST_F(OutputUpdateColorProfileTest_Hdr, PQ_RE_On_HLG_HW_Uses_DisplayP3) {
2070 // BT2020_PQ is not used if the top PQ layer is RenderEngine composed.
2071 verify().ifTopLayerIs(BT2020_PQ)
2072 .andTopLayerIsREComposed(true)
2073 .andIfBottomLayerIs(BT2020_HLG)
2074 .andBottomLayerIsREComposed(false)
2075 .andIfLegacySupportFor(BT2020_PQ, false)
2076 .thenExpectBestColorModeCallUses(DISPLAY_P3)
2077 .execute();
2078}
2079
2080TEST_F(OutputUpdateColorProfileTest_Hdr, HLG_HW_On_PQ_HW_Uses_PQ) {
2081 // If there is mixed HLG/PQ use, and the topmost layer is HLG, then PQ is
2082 // used if there are no other special conditions.
2083 verify().ifTopLayerIs(BT2020_HLG)
2084 .andTopLayerIsREComposed(false)
2085 .andIfBottomLayerIs(BT2020_PQ)
2086 .andBottomLayerIsREComposed(false)
2087 .andIfLegacySupportFor(BT2020_PQ, false)
2088 .thenExpectBestColorModeCallUses(BT2020_PQ)
2089 .execute();
2090}
2091
2092TEST_F(OutputUpdateColorProfileTest_Hdr, HLG_HW_On_PQ_HW_IfPQHasLegacySupport_Uses_DisplayP3) {
2093 // BT2020_PQ is not used if there is only legacy support for it.
2094 verify().ifTopLayerIs(BT2020_HLG)
2095 .andTopLayerIsREComposed(false)
2096 .andIfBottomLayerIs(BT2020_PQ)
2097 .andBottomLayerIsREComposed(false)
2098 .andIfLegacySupportFor(BT2020_PQ, true)
2099 .thenExpectBestColorModeCallUses(DISPLAY_P3)
2100 .execute();
2101}
2102
2103TEST_F(OutputUpdateColorProfileTest_Hdr, HLG_HW_On_PQ_RE_Uses_DisplayP3) {
2104 // BT2020_PQ is not used if the bottom PQ layer is RenderEngine composed.
2105 verify().ifTopLayerIs(BT2020_HLG)
2106 .andTopLayerIsREComposed(false)
2107 .andIfBottomLayerIs(BT2020_PQ)
2108 .andBottomLayerIsREComposed(true)
2109 .andIfLegacySupportFor(BT2020_PQ, false)
2110 .thenExpectBestColorModeCallUses(DISPLAY_P3)
2111 .execute();
2112}
2113
2114TEST_F(OutputUpdateColorProfileTest_Hdr, HLG_RE_On_PQ_HW_Uses_PQ) {
2115 // BT2020_PQ is still used if the top HLG layer is RenderEngine composed.
2116 verify().ifTopLayerIs(BT2020_HLG)
2117 .andTopLayerIsREComposed(true)
2118 .andIfBottomLayerIs(BT2020_PQ)
2119 .andBottomLayerIsREComposed(false)
2120 .andIfLegacySupportFor(BT2020_PQ, false)
2121 .thenExpectBestColorModeCallUses(BT2020_PQ)
2122 .execute();
2123}
2124
2125TEST_F(OutputUpdateColorProfileTest_Hdr, HLG_HW_On_HLG_HW_Uses_HLG) {
2126 // If all layers use HLG then HLG is used if there are no other special
2127 // conditions.
2128 verify().ifTopLayerIs(BT2020_HLG)
2129 .andTopLayerIsREComposed(false)
2130 .andIfBottomLayerIs(BT2020_HLG)
2131 .andBottomLayerIsREComposed(false)
2132 .andIfLegacySupportFor(BT2020_HLG, false)
2133 .thenExpectBestColorModeCallUses(BT2020_HLG)
2134 .execute();
2135}
2136
2137TEST_F(OutputUpdateColorProfileTest_Hdr, HLG_HW_On_HLG_HW_IfPQHasLegacySupport_Uses_DisplayP3) {
2138 // BT2020_HLG is not used if there is legacy support for it.
2139 verify().ifTopLayerIs(BT2020_HLG)
2140 .andTopLayerIsREComposed(false)
2141 .andIfBottomLayerIs(BT2020_HLG)
2142 .andBottomLayerIsREComposed(false)
2143 .andIfLegacySupportFor(BT2020_HLG, true)
2144 .thenExpectBestColorModeCallUses(DISPLAY_P3)
2145 .execute();
2146}
2147
2148TEST_F(OutputUpdateColorProfileTest_Hdr, HLG_HW_On_HLG_RE_Uses_HLG) {
2149 // BT2020_HLG is used even if the bottom layer is client composed.
2150 verify().ifTopLayerIs(BT2020_HLG)
2151 .andTopLayerIsREComposed(false)
2152 .andIfBottomLayerIs(BT2020_HLG)
2153 .andBottomLayerIsREComposed(true)
2154 .andIfLegacySupportFor(BT2020_HLG, false)
2155 .thenExpectBestColorModeCallUses(BT2020_HLG)
2156 .execute();
2157}
2158
2159TEST_F(OutputUpdateColorProfileTest_Hdr, HLG_RE_On_HLG_HW_Uses_HLG) {
2160 // BT2020_HLG is used even if the top layer is client composed.
2161 verify().ifTopLayerIs(BT2020_HLG)
2162 .andTopLayerIsREComposed(true)
2163 .andIfBottomLayerIs(BT2020_HLG)
2164 .andBottomLayerIsREComposed(false)
2165 .andIfLegacySupportFor(BT2020_HLG, false)
2166 .thenExpectBestColorModeCallUses(BT2020_HLG)
2167 .execute();
2168}
2169
2170TEST_F(OutputUpdateColorProfileTest_Hdr, PQ_HW_On_NonHdr_HW_Uses_PQ) {
2171 // Even if there are non-HDR layers present, BT2020_PQ can still be used.
2172 verify().ifTopLayerIs(BT2020_PQ)
2173 .andTopLayerIsREComposed(false)
2174 .andIfBottomLayerIsNotHdr()
2175 .andBottomLayerIsREComposed(false)
2176 .andIfLegacySupportFor(BT2020_PQ, false)
2177 .thenExpectBestColorModeCallUses(BT2020_PQ)
2178 .execute();
2179}
2180
2181TEST_F(OutputUpdateColorProfileTest_Hdr, HLG_HW_On_NonHdr_RE_Uses_HLG) {
2182 // If all layers use HLG then HLG is used if there are no other special
2183 // conditions.
2184 verify().ifTopLayerIs(BT2020_HLG)
2185 .andTopLayerIsREComposed(false)
2186 .andIfBottomLayerIsNotHdr()
2187 .andBottomLayerIsREComposed(true)
2188 .andIfLegacySupportFor(BT2020_HLG, false)
2189 .thenExpectBestColorModeCallUses(BT2020_HLG)
2190 .execute();
2191}
2192
2193struct OutputUpdateColorProfile_AffectsChosenRenderIntentTest
2194 : public OutputUpdateColorProfileTest {
2195 // The various values for CompositionRefreshArgs::outputColorSetting affect
2196 // the chosen renderIntent, along with whether the preferred dataspace is an
2197 // HDR dataspace or not.
2198
2199 OutputUpdateColorProfile_AffectsChosenRenderIntentTest() {
2200 mRefreshArgs.outputColorSetting = OutputColorSetting::kEnhanced;
2201 mRefreshArgs.colorSpaceAgnosticDataspace = ui::Dataspace::UNKNOWN;
2202 mLayer1.mLayerFEState.dataspace = ui::Dataspace::BT2020_PQ;
Lloyd Pique0a456232020-01-16 17:51:13 -08002203 EXPECT_CALL(mOutput, getOutputLayerCount()).WillRepeatedly(Return(1u));
Lloyd Pique17ca7422019-11-14 14:24:10 -08002204 EXPECT_CALL(mOutput, setColorProfile(_)).WillRepeatedly(Return());
2205 EXPECT_CALL(*mDisplayColorProfile, hasLegacyHdrSupport(ui::Dataspace::BT2020_PQ))
2206 .WillRepeatedly(Return(false));
2207 }
2208
2209 // The tests here involve enough state and GMock setup that using a mini-DSL
2210 // makes the tests much more readable, and allows the test to focus more on
2211 // the intent than on some of the details.
2212
2213 static constexpr ui::Dataspace kNonHdrDataspace = ui::Dataspace::DISPLAY_P3;
2214 static constexpr ui::Dataspace kHdrDataspace = ui::Dataspace::BT2020_PQ;
2215
2216 struct IfDataspaceChosenState
2217 : public CallOrderStateMachineHelper<TestType, IfDataspaceChosenState> {
2218 [[nodiscard]] auto ifDataspaceChosenIs(ui::Dataspace dataspace) {
2219 getInstance()->mLayer1.mLayerFEState.dataspace = dataspace;
2220 return nextState<AndOutputColorSettingState>();
2221 }
2222 [[nodiscard]] auto ifDataspaceChosenIsNonHdr() {
2223 return ifDataspaceChosenIs(kNonHdrDataspace);
2224 }
2225 [[nodiscard]] auto ifDataspaceChosenIsHdr() { return ifDataspaceChosenIs(kHdrDataspace); }
2226 };
2227
2228 struct AndOutputColorSettingState
2229 : public CallOrderStateMachineHelper<TestType, AndOutputColorSettingState> {
2230 [[nodiscard]] auto andOutputColorSettingIs(OutputColorSetting setting) {
2231 getInstance()->mRefreshArgs.outputColorSetting = setting;
2232 return nextState<ThenExpectBestColorModeCallUsesState>();
2233 }
2234 };
2235
2236 struct ThenExpectBestColorModeCallUsesState
2237 : public CallOrderStateMachineHelper<TestType, ThenExpectBestColorModeCallUsesState> {
2238 [[nodiscard]] auto thenExpectBestColorModeCallUses(ui::RenderIntent intent) {
2239 EXPECT_CALL(*getInstance()->mDisplayColorProfile,
2240 getBestColorMode(getInstance()->mLayer1.mLayerFEState.dataspace, intent, _,
2241 _, _));
2242 return nextState<ExecuteState>();
2243 }
2244 };
2245
2246 // Tests call one of these two helper member functions to start using the
2247 // mini-DSL defined above.
2248 [[nodiscard]] auto verify() { return IfDataspaceChosenState::make(this); }
2249};
2250
2251TEST_F(OutputUpdateColorProfile_AffectsChosenRenderIntentTest,
2252 Managed_NonHdr_Prefers_Colorimetric) {
2253 verify().ifDataspaceChosenIsNonHdr()
2254 .andOutputColorSettingIs(OutputColorSetting::kManaged)
2255 .thenExpectBestColorModeCallUses(ui::RenderIntent::COLORIMETRIC)
2256 .execute();
2257}
2258
2259TEST_F(OutputUpdateColorProfile_AffectsChosenRenderIntentTest,
2260 Managed_Hdr_Prefers_ToneMapColorimetric) {
2261 verify().ifDataspaceChosenIsHdr()
2262 .andOutputColorSettingIs(OutputColorSetting::kManaged)
2263 .thenExpectBestColorModeCallUses(ui::RenderIntent::TONE_MAP_COLORIMETRIC)
2264 .execute();
2265}
2266
2267TEST_F(OutputUpdateColorProfile_AffectsChosenRenderIntentTest, Enhanced_NonHdr_Prefers_Enhance) {
2268 verify().ifDataspaceChosenIsNonHdr()
2269 .andOutputColorSettingIs(OutputColorSetting::kEnhanced)
2270 .thenExpectBestColorModeCallUses(ui::RenderIntent::ENHANCE)
2271 .execute();
2272}
2273
2274TEST_F(OutputUpdateColorProfile_AffectsChosenRenderIntentTest,
2275 Enhanced_Hdr_Prefers_ToneMapEnhance) {
2276 verify().ifDataspaceChosenIsHdr()
2277 .andOutputColorSettingIs(OutputColorSetting::kEnhanced)
2278 .thenExpectBestColorModeCallUses(ui::RenderIntent::TONE_MAP_ENHANCE)
2279 .execute();
2280}
2281
2282TEST_F(OutputUpdateColorProfile_AffectsChosenRenderIntentTest, Vendor_NonHdr_Prefers_Vendor) {
2283 verify().ifDataspaceChosenIsNonHdr()
2284 .andOutputColorSettingIs(kVendorSpecifiedOutputColorSetting)
2285 .thenExpectBestColorModeCallUses(
2286 static_cast<ui::RenderIntent>(kVendorSpecifiedOutputColorSetting))
2287 .execute();
2288}
2289
2290TEST_F(OutputUpdateColorProfile_AffectsChosenRenderIntentTest, Vendor_Hdr_Prefers_Vendor) {
2291 verify().ifDataspaceChosenIsHdr()
2292 .andOutputColorSettingIs(kVendorSpecifiedOutputColorSetting)
2293 .thenExpectBestColorModeCallUses(
2294 static_cast<ui::RenderIntent>(kVendorSpecifiedOutputColorSetting))
2295 .execute();
2296}
Lloyd Piquefaa3f192019-11-14 14:05:09 -08002297
2298/*
2299 * Output::beginFrame()
2300 */
2301
Lloyd Piquee5965952019-11-18 16:16:32 -08002302struct OutputBeginFrameTest : public ::testing::Test {
2303 using TestType = OutputBeginFrameTest;
2304
2305 struct OutputPartialMock : public OutputPartialMockBase {
Lloyd Pique739afaf2019-11-21 16:40:05 -08002306 // Sets up the helper functions called by the function under test to use
2307 // mock implementations.
Lloyd Piquee5965952019-11-18 16:16:32 -08002308 MOCK_CONST_METHOD1(getDirtyRegion, Region(bool));
2309 };
2310
2311 OutputBeginFrameTest() {
2312 mOutput.setDisplayColorProfileForTest(
2313 std::unique_ptr<DisplayColorProfile>(mDisplayColorProfile));
2314 mOutput.setRenderSurfaceForTest(std::unique_ptr<RenderSurface>(mRenderSurface));
2315 }
2316
2317 struct IfGetDirtyRegionExpectationState
2318 : public CallOrderStateMachineHelper<TestType, IfGetDirtyRegionExpectationState> {
2319 [[nodiscard]] auto ifGetDirtyRegionReturns(Region dirtyRegion) {
2320 EXPECT_CALL(getInstance()->mOutput, getDirtyRegion(false))
2321 .WillOnce(Return(dirtyRegion));
2322 return nextState<AndIfGetOutputLayerCountExpectationState>();
2323 }
2324 };
2325
2326 struct AndIfGetOutputLayerCountExpectationState
2327 : public CallOrderStateMachineHelper<TestType, AndIfGetOutputLayerCountExpectationState> {
2328 [[nodiscard]] auto andIfGetOutputLayerCountReturns(size_t layerCount) {
2329 EXPECT_CALL(getInstance()->mOutput, getOutputLayerCount()).WillOnce(Return(layerCount));
2330 return nextState<AndIfLastCompositionHadVisibleLayersState>();
2331 }
2332 };
2333
2334 struct AndIfLastCompositionHadVisibleLayersState
2335 : public CallOrderStateMachineHelper<TestType,
2336 AndIfLastCompositionHadVisibleLayersState> {
2337 [[nodiscard]] auto andIfLastCompositionHadVisibleLayersIs(bool hadOutputLayers) {
2338 getInstance()->mOutput.mState.lastCompositionHadVisibleLayers = hadOutputLayers;
2339 return nextState<ThenExpectRenderSurfaceBeginFrameCallState>();
2340 }
2341 };
2342
2343 struct ThenExpectRenderSurfaceBeginFrameCallState
2344 : public CallOrderStateMachineHelper<TestType,
2345 ThenExpectRenderSurfaceBeginFrameCallState> {
2346 [[nodiscard]] auto thenExpectRenderSurfaceBeginFrameCall(bool mustRecompose) {
2347 EXPECT_CALL(*getInstance()->mRenderSurface, beginFrame(mustRecompose));
2348 return nextState<ExecuteState>();
2349 }
2350 };
2351
2352 struct ExecuteState : public CallOrderStateMachineHelper<TestType, ExecuteState> {
2353 [[nodiscard]] auto execute() {
2354 getInstance()->mOutput.beginFrame();
2355 return nextState<CheckPostconditionHadVisibleLayersState>();
2356 }
2357 };
2358
2359 struct CheckPostconditionHadVisibleLayersState
2360 : public CallOrderStateMachineHelper<TestType, CheckPostconditionHadVisibleLayersState> {
2361 void checkPostconditionHadVisibleLayers(bool expected) {
2362 EXPECT_EQ(expected, getInstance()->mOutput.mState.lastCompositionHadVisibleLayers);
2363 }
2364 };
2365
2366 // Tests call one of these two helper member functions to start using the
2367 // mini-DSL defined above.
2368 [[nodiscard]] auto verify() { return IfGetDirtyRegionExpectationState::make(this); }
2369
2370 static const Region kEmptyRegion;
2371 static const Region kNotEmptyRegion;
2372
2373 mock::DisplayColorProfile* mDisplayColorProfile = new StrictMock<mock::DisplayColorProfile>();
2374 mock::RenderSurface* mRenderSurface = new StrictMock<mock::RenderSurface>();
2375 StrictMock<OutputPartialMock> mOutput;
2376};
2377
2378const Region OutputBeginFrameTest::kEmptyRegion{Rect{0, 0, 0, 0}};
2379const Region OutputBeginFrameTest::kNotEmptyRegion{Rect{0, 0, 1, 1}};
2380
2381TEST_F(OutputBeginFrameTest, hasDirtyHasLayersHadLayersLastFrame) {
2382 verify().ifGetDirtyRegionReturns(kNotEmptyRegion)
2383 .andIfGetOutputLayerCountReturns(1u)
2384 .andIfLastCompositionHadVisibleLayersIs(true)
2385 .thenExpectRenderSurfaceBeginFrameCall(true)
2386 .execute()
2387 .checkPostconditionHadVisibleLayers(true);
2388}
2389
2390TEST_F(OutputBeginFrameTest, hasDirtyNotHasLayersHadLayersLastFrame) {
2391 verify().ifGetDirtyRegionReturns(kNotEmptyRegion)
2392 .andIfGetOutputLayerCountReturns(0u)
2393 .andIfLastCompositionHadVisibleLayersIs(true)
2394 .thenExpectRenderSurfaceBeginFrameCall(true)
2395 .execute()
2396 .checkPostconditionHadVisibleLayers(false);
2397}
2398
2399TEST_F(OutputBeginFrameTest, hasDirtyHasLayersNotHadLayersLastFrame) {
2400 verify().ifGetDirtyRegionReturns(kNotEmptyRegion)
2401 .andIfGetOutputLayerCountReturns(1u)
2402 .andIfLastCompositionHadVisibleLayersIs(false)
2403 .thenExpectRenderSurfaceBeginFrameCall(true)
2404 .execute()
2405 .checkPostconditionHadVisibleLayers(true);
2406}
2407
2408TEST_F(OutputBeginFrameTest, hasDirtyNotHasLayersNotHadLayersLastFrame) {
2409 verify().ifGetDirtyRegionReturns(kNotEmptyRegion)
2410 .andIfGetOutputLayerCountReturns(0u)
2411 .andIfLastCompositionHadVisibleLayersIs(false)
2412 .thenExpectRenderSurfaceBeginFrameCall(false)
2413 .execute()
2414 .checkPostconditionHadVisibleLayers(false);
2415}
2416
2417TEST_F(OutputBeginFrameTest, notHasDirtyHasLayersHadLayersLastFrame) {
2418 verify().ifGetDirtyRegionReturns(kEmptyRegion)
2419 .andIfGetOutputLayerCountReturns(1u)
2420 .andIfLastCompositionHadVisibleLayersIs(true)
2421 .thenExpectRenderSurfaceBeginFrameCall(false)
2422 .execute()
2423 .checkPostconditionHadVisibleLayers(true);
2424}
2425
2426TEST_F(OutputBeginFrameTest, notHasDirtyNotHasLayersHadLayersLastFrame) {
2427 verify().ifGetDirtyRegionReturns(kEmptyRegion)
2428 .andIfGetOutputLayerCountReturns(0u)
2429 .andIfLastCompositionHadVisibleLayersIs(true)
2430 .thenExpectRenderSurfaceBeginFrameCall(false)
2431 .execute()
2432 .checkPostconditionHadVisibleLayers(true);
2433}
2434
2435TEST_F(OutputBeginFrameTest, notHasDirtyHasLayersNotHadLayersLastFrame) {
2436 verify().ifGetDirtyRegionReturns(kEmptyRegion)
2437 .andIfGetOutputLayerCountReturns(1u)
2438 .andIfLastCompositionHadVisibleLayersIs(false)
2439 .thenExpectRenderSurfaceBeginFrameCall(false)
2440 .execute()
2441 .checkPostconditionHadVisibleLayers(false);
2442}
2443
2444TEST_F(OutputBeginFrameTest, notHasDirtyNotHasLayersNotHadLayersLastFrame) {
2445 verify().ifGetDirtyRegionReturns(kEmptyRegion)
2446 .andIfGetOutputLayerCountReturns(0u)
2447 .andIfLastCompositionHadVisibleLayersIs(false)
2448 .thenExpectRenderSurfaceBeginFrameCall(false)
2449 .execute()
2450 .checkPostconditionHadVisibleLayers(false);
2451}
2452
Lloyd Piquefaa3f192019-11-14 14:05:09 -08002453/*
2454 * Output::devOptRepaintFlash()
2455 */
2456
Lloyd Piquedb462d82019-11-19 17:58:46 -08002457struct OutputDevOptRepaintFlashTest : public testing::Test {
2458 struct OutputPartialMock : public OutputPartialMockBase {
Lloyd Pique739afaf2019-11-21 16:40:05 -08002459 // Sets up the helper functions called by the function under test to use
2460 // mock implementations.
Lloyd Piquedb462d82019-11-19 17:58:46 -08002461 MOCK_CONST_METHOD1(getDirtyRegion, Region(bool));
2462 MOCK_METHOD1(composeSurfaces, std::optional<base::unique_fd>(const Region&));
2463 MOCK_METHOD0(postFramebuffer, void());
2464 MOCK_METHOD0(prepareFrame, void());
2465 };
2466
2467 OutputDevOptRepaintFlashTest() {
2468 mOutput.setDisplayColorProfileForTest(
2469 std::unique_ptr<DisplayColorProfile>(mDisplayColorProfile));
2470 mOutput.setRenderSurfaceForTest(std::unique_ptr<RenderSurface>(mRenderSurface));
2471 }
2472
2473 static const Region kEmptyRegion;
2474 static const Region kNotEmptyRegion;
2475
2476 StrictMock<OutputPartialMock> mOutput;
2477 mock::DisplayColorProfile* mDisplayColorProfile = new StrictMock<mock::DisplayColorProfile>();
2478 mock::RenderSurface* mRenderSurface = new StrictMock<mock::RenderSurface>();
2479 CompositionRefreshArgs mRefreshArgs;
2480};
2481
2482const Region OutputDevOptRepaintFlashTest::kEmptyRegion{Rect{0, 0, 0, 0}};
2483const Region OutputDevOptRepaintFlashTest::kNotEmptyRegion{Rect{0, 0, 1, 1}};
2484
2485TEST_F(OutputDevOptRepaintFlashTest, doesNothingIfFlashDelayNotSet) {
2486 mRefreshArgs.devOptFlashDirtyRegionsDelay = {};
2487 mRefreshArgs.repaintEverything = true;
2488 mOutput.mState.isEnabled = true;
2489
2490 mOutput.devOptRepaintFlash(mRefreshArgs);
2491}
2492
2493TEST_F(OutputDevOptRepaintFlashTest, postsAndPreparesANewFrameIfNotEnabled) {
2494 mRefreshArgs.devOptFlashDirtyRegionsDelay = std::chrono::microseconds(1);
2495 mRefreshArgs.repaintEverything = true;
2496 mOutput.mState.isEnabled = false;
2497
2498 InSequence seq;
2499 EXPECT_CALL(mOutput, postFramebuffer());
2500 EXPECT_CALL(mOutput, prepareFrame());
2501
2502 mOutput.devOptRepaintFlash(mRefreshArgs);
2503}
2504
2505TEST_F(OutputDevOptRepaintFlashTest, postsAndPreparesANewFrameIfNotDirty) {
2506 mRefreshArgs.devOptFlashDirtyRegionsDelay = std::chrono::microseconds(1);
2507 mRefreshArgs.repaintEverything = true;
2508 mOutput.mState.isEnabled = true;
2509
2510 InSequence seq;
2511 EXPECT_CALL(mOutput, getDirtyRegion(true)).WillOnce(Return(kEmptyRegion));
2512 EXPECT_CALL(mOutput, postFramebuffer());
2513 EXPECT_CALL(mOutput, prepareFrame());
2514
2515 mOutput.devOptRepaintFlash(mRefreshArgs);
2516}
2517
2518TEST_F(OutputDevOptRepaintFlashTest, alsoComposesSurfacesAndQueuesABufferIfDirty) {
2519 mRefreshArgs.devOptFlashDirtyRegionsDelay = std::chrono::microseconds(1);
2520 mRefreshArgs.repaintEverything = false;
2521 mOutput.mState.isEnabled = true;
2522
2523 InSequence seq;
2524 EXPECT_CALL(mOutput, getDirtyRegion(false)).WillOnce(Return(kNotEmptyRegion));
2525 EXPECT_CALL(mOutput, composeSurfaces(RegionEq(kNotEmptyRegion)));
2526 EXPECT_CALL(*mRenderSurface, queueBuffer(_));
2527 EXPECT_CALL(mOutput, postFramebuffer());
2528 EXPECT_CALL(mOutput, prepareFrame());
2529
2530 mOutput.devOptRepaintFlash(mRefreshArgs);
2531}
2532
Lloyd Piquefaa3f192019-11-14 14:05:09 -08002533/*
2534 * Output::finishFrame()
2535 */
2536
Lloyd Pique03561a62019-11-19 18:34:52 -08002537struct OutputFinishFrameTest : public testing::Test {
2538 struct OutputPartialMock : public OutputPartialMockBase {
Lloyd Pique739afaf2019-11-21 16:40:05 -08002539 // Sets up the helper functions called by the function under test to use
2540 // mock implementations.
Lloyd Pique03561a62019-11-19 18:34:52 -08002541 MOCK_METHOD1(composeSurfaces, std::optional<base::unique_fd>(const Region&));
2542 MOCK_METHOD0(postFramebuffer, void());
2543 };
2544
2545 OutputFinishFrameTest() {
2546 mOutput.setDisplayColorProfileForTest(
2547 std::unique_ptr<DisplayColorProfile>(mDisplayColorProfile));
2548 mOutput.setRenderSurfaceForTest(std::unique_ptr<RenderSurface>(mRenderSurface));
2549 }
2550
2551 StrictMock<OutputPartialMock> mOutput;
2552 mock::DisplayColorProfile* mDisplayColorProfile = new StrictMock<mock::DisplayColorProfile>();
2553 mock::RenderSurface* mRenderSurface = new StrictMock<mock::RenderSurface>();
2554 CompositionRefreshArgs mRefreshArgs;
2555};
2556
2557TEST_F(OutputFinishFrameTest, ifNotEnabledDoesNothing) {
2558 mOutput.mState.isEnabled = false;
2559
2560 mOutput.finishFrame(mRefreshArgs);
2561}
2562
2563TEST_F(OutputFinishFrameTest, takesEarlyOutifComposeSurfacesReturnsNoFence) {
2564 mOutput.mState.isEnabled = true;
2565
2566 InSequence seq;
2567 EXPECT_CALL(mOutput, composeSurfaces(RegionEq(Region::INVALID_REGION)));
2568
2569 mOutput.finishFrame(mRefreshArgs);
2570}
2571
2572TEST_F(OutputFinishFrameTest, queuesBufferIfComposeSurfacesReturnsAFence) {
2573 mOutput.mState.isEnabled = true;
2574
2575 InSequence seq;
2576 EXPECT_CALL(mOutput, composeSurfaces(RegionEq(Region::INVALID_REGION)))
2577 .WillOnce(Return(ByMove(base::unique_fd())));
2578 EXPECT_CALL(*mRenderSurface, queueBuffer(_));
2579
2580 mOutput.finishFrame(mRefreshArgs);
2581}
Lloyd Piquefaa3f192019-11-14 14:05:09 -08002582
2583/*
2584 * Output::postFramebuffer()
2585 */
2586
Lloyd Pique07178e32019-11-19 19:15:26 -08002587struct OutputPostFramebufferTest : public testing::Test {
2588 struct OutputPartialMock : public OutputPartialMockBase {
Lloyd Pique739afaf2019-11-21 16:40:05 -08002589 // Sets up the helper functions called by the function under test to use
2590 // mock implementations.
Lloyd Pique07178e32019-11-19 19:15:26 -08002591 MOCK_METHOD0(presentAndGetFrameFences, compositionengine::Output::FrameFences());
2592 };
2593
2594 struct Layer {
2595 Layer() {
2596 EXPECT_CALL(outputLayer, getLayerFE()).WillRepeatedly(ReturnRef(layerFE));
2597 EXPECT_CALL(outputLayer, getHwcLayer()).WillRepeatedly(Return(&hwc2Layer));
2598 }
2599
2600 StrictMock<mock::OutputLayer> outputLayer;
2601 StrictMock<mock::LayerFE> layerFE;
2602 StrictMock<HWC2::mock::Layer> hwc2Layer;
2603 };
2604
2605 OutputPostFramebufferTest() {
2606 mOutput.setDisplayColorProfileForTest(
2607 std::unique_ptr<DisplayColorProfile>(mDisplayColorProfile));
2608 mOutput.setRenderSurfaceForTest(std::unique_ptr<RenderSurface>(mRenderSurface));
2609
2610 EXPECT_CALL(mOutput, getOutputLayerCount()).WillRepeatedly(Return(3u));
2611 EXPECT_CALL(mOutput, getOutputLayerOrderedByZByIndex(0u))
2612 .WillRepeatedly(Return(&mLayer1.outputLayer));
2613 EXPECT_CALL(mOutput, getOutputLayerOrderedByZByIndex(1u))
2614 .WillRepeatedly(Return(&mLayer2.outputLayer));
2615 EXPECT_CALL(mOutput, getOutputLayerOrderedByZByIndex(2u))
2616 .WillRepeatedly(Return(&mLayer3.outputLayer));
2617 }
2618
2619 StrictMock<OutputPartialMock> mOutput;
2620 mock::DisplayColorProfile* mDisplayColorProfile = new StrictMock<mock::DisplayColorProfile>();
2621 mock::RenderSurface* mRenderSurface = new StrictMock<mock::RenderSurface>();
2622
2623 Layer mLayer1;
2624 Layer mLayer2;
2625 Layer mLayer3;
2626};
2627
2628TEST_F(OutputPostFramebufferTest, ifNotEnabledDoesNothing) {
2629 mOutput.mState.isEnabled = false;
2630
2631 mOutput.postFramebuffer();
2632}
2633
2634TEST_F(OutputPostFramebufferTest, ifEnabledMustFlipThenPresentThenSendPresentCompleted) {
2635 mOutput.mState.isEnabled = true;
2636
2637 compositionengine::Output::FrameFences frameFences;
2638
2639 // This should happen even if there are no output layers.
2640 EXPECT_CALL(mOutput, getOutputLayerCount()).WillOnce(Return(0u));
2641
2642 // For this test in particular we want to make sure the call expectations
2643 // setup below are satisfied in the specific order.
2644 InSequence seq;
2645
2646 EXPECT_CALL(*mRenderSurface, flip());
2647 EXPECT_CALL(mOutput, presentAndGetFrameFences()).WillOnce(Return(frameFences));
2648 EXPECT_CALL(*mRenderSurface, onPresentDisplayCompleted());
2649
2650 mOutput.postFramebuffer();
2651}
2652
2653TEST_F(OutputPostFramebufferTest, releaseFencesAreSentToLayerFE) {
2654 // Simulate getting release fences from each layer, and ensure they are passed to the
2655 // front-end layer interface for each layer correctly.
2656
2657 mOutput.mState.isEnabled = true;
2658
2659 // Create three unique fence instances
2660 sp<Fence> layer1Fence = new Fence();
2661 sp<Fence> layer2Fence = new Fence();
2662 sp<Fence> layer3Fence = new Fence();
2663
Lloyd Piquefe0ee9e2019-11-22 16:30:30 -08002664 Output::FrameFences frameFences;
Lloyd Pique07178e32019-11-19 19:15:26 -08002665 frameFences.layerFences.emplace(&mLayer1.hwc2Layer, layer1Fence);
2666 frameFences.layerFences.emplace(&mLayer2.hwc2Layer, layer2Fence);
2667 frameFences.layerFences.emplace(&mLayer3.hwc2Layer, layer3Fence);
2668
2669 EXPECT_CALL(*mRenderSurface, flip());
2670 EXPECT_CALL(mOutput, presentAndGetFrameFences()).WillOnce(Return(frameFences));
2671 EXPECT_CALL(*mRenderSurface, onPresentDisplayCompleted());
2672
2673 // Compare the pointers values of each fence to make sure the correct ones
2674 // are passed. This happens to work with the current implementation, but
2675 // would not survive certain calls like Fence::merge() which would return a
2676 // new instance.
2677 EXPECT_CALL(mLayer1.layerFE,
2678 onLayerDisplayed(Property(&sp<Fence>::get, Eq(layer1Fence.get()))));
2679 EXPECT_CALL(mLayer2.layerFE,
2680 onLayerDisplayed(Property(&sp<Fence>::get, Eq(layer2Fence.get()))));
2681 EXPECT_CALL(mLayer3.layerFE,
2682 onLayerDisplayed(Property(&sp<Fence>::get, Eq(layer3Fence.get()))));
2683
2684 mOutput.postFramebuffer();
2685}
2686
2687TEST_F(OutputPostFramebufferTest, releaseFencesIncludeClientTargetAcquireFence) {
2688 mOutput.mState.isEnabled = true;
2689 mOutput.mState.usesClientComposition = true;
2690
2691 sp<Fence> clientTargetAcquireFence = new Fence();
2692 sp<Fence> layer1Fence = new Fence();
2693 sp<Fence> layer2Fence = new Fence();
2694 sp<Fence> layer3Fence = new Fence();
Lloyd Piquefe0ee9e2019-11-22 16:30:30 -08002695 Output::FrameFences frameFences;
Lloyd Pique07178e32019-11-19 19:15:26 -08002696 frameFences.clientTargetAcquireFence = clientTargetAcquireFence;
2697 frameFences.layerFences.emplace(&mLayer1.hwc2Layer, layer1Fence);
2698 frameFences.layerFences.emplace(&mLayer2.hwc2Layer, layer2Fence);
2699 frameFences.layerFences.emplace(&mLayer3.hwc2Layer, layer3Fence);
2700
2701 EXPECT_CALL(*mRenderSurface, flip());
2702 EXPECT_CALL(mOutput, presentAndGetFrameFences()).WillOnce(Return(frameFences));
2703 EXPECT_CALL(*mRenderSurface, onPresentDisplayCompleted());
2704
2705 // Fence::merge is called, and since none of the fences are actually valid,
2706 // Fence::NO_FENCE is returned and passed to each onLayerDisplayed() call.
2707 // This is the best we can do without creating a real kernel fence object.
2708 EXPECT_CALL(mLayer1.layerFE, onLayerDisplayed(Fence::NO_FENCE));
2709 EXPECT_CALL(mLayer2.layerFE, onLayerDisplayed(Fence::NO_FENCE));
2710 EXPECT_CALL(mLayer3.layerFE, onLayerDisplayed(Fence::NO_FENCE));
2711
2712 mOutput.postFramebuffer();
2713}
2714
2715TEST_F(OutputPostFramebufferTest, releasedLayersSentPresentFence) {
2716 mOutput.mState.isEnabled = true;
2717 mOutput.mState.usesClientComposition = true;
2718
2719 // This should happen even if there are no (current) output layers.
2720 EXPECT_CALL(mOutput, getOutputLayerCount()).WillOnce(Return(0u));
2721
2722 // Load up the released layers with some mock instances
2723 sp<StrictMock<mock::LayerFE>> releasedLayer1{new StrictMock<mock::LayerFE>()};
2724 sp<StrictMock<mock::LayerFE>> releasedLayer2{new StrictMock<mock::LayerFE>()};
2725 sp<StrictMock<mock::LayerFE>> releasedLayer3{new StrictMock<mock::LayerFE>()};
2726 Output::ReleasedLayers layers;
2727 layers.push_back(releasedLayer1);
2728 layers.push_back(releasedLayer2);
2729 layers.push_back(releasedLayer3);
2730 mOutput.setReleasedLayers(std::move(layers));
2731
2732 // Set up a fake present fence
2733 sp<Fence> presentFence = new Fence();
Lloyd Piquefe0ee9e2019-11-22 16:30:30 -08002734 Output::FrameFences frameFences;
Lloyd Pique07178e32019-11-19 19:15:26 -08002735 frameFences.presentFence = presentFence;
2736
2737 EXPECT_CALL(*mRenderSurface, flip());
2738 EXPECT_CALL(mOutput, presentAndGetFrameFences()).WillOnce(Return(frameFences));
2739 EXPECT_CALL(*mRenderSurface, onPresentDisplayCompleted());
2740
2741 // Each released layer should be given the presentFence.
2742 EXPECT_CALL(*releasedLayer1,
2743 onLayerDisplayed(Property(&sp<Fence>::get, Eq(presentFence.get()))));
2744 EXPECT_CALL(*releasedLayer2,
2745 onLayerDisplayed(Property(&sp<Fence>::get, Eq(presentFence.get()))));
2746 EXPECT_CALL(*releasedLayer3,
2747 onLayerDisplayed(Property(&sp<Fence>::get, Eq(presentFence.get()))));
2748
2749 mOutput.postFramebuffer();
2750
2751 // After the call the list of released layers should have been cleared.
2752 EXPECT_TRUE(mOutput.getReleasedLayersForTest().empty());
2753}
Lloyd Piquefaa3f192019-11-14 14:05:09 -08002754
2755/*
Lloyd Pique56eba802019-08-28 15:45:25 -07002756 * Output::composeSurfaces()
2757 */
2758
2759struct OutputComposeSurfacesTest : public testing::Test {
Lloyd Pique6818fa52019-12-03 12:32:13 -08002760 using TestType = OutputComposeSurfacesTest;
Lloyd Pique56eba802019-08-28 15:45:25 -07002761
Lloyd Piquefaa3f192019-11-14 14:05:09 -08002762 struct OutputPartialMock : public OutputPartialMockBase {
Lloyd Pique739afaf2019-11-21 16:40:05 -08002763 // Sets up the helper functions called by the function under test to use
2764 // mock implementations.
Lloyd Pique56eba802019-08-28 15:45:25 -07002765 MOCK_CONST_METHOD0(getSkipColorTransform, bool());
Vishnu Nair3a7346c2019-12-04 08:09:09 -08002766 MOCK_METHOD3(generateClientCompositionRequests,
Vishnu Nair9b079a22020-01-21 14:36:08 -08002767 std::vector<LayerFE::LayerSettings>(bool, Region&, ui::Dataspace));
Lloyd Pique56eba802019-08-28 15:45:25 -07002768 MOCK_METHOD2(appendRegionFlashRequests,
Vishnu Nair9b079a22020-01-21 14:36:08 -08002769 void(const Region&, std::vector<LayerFE::LayerSettings>&));
Lloyd Pique56eba802019-08-28 15:45:25 -07002770 MOCK_METHOD1(setExpensiveRenderingExpected, void(bool));
2771 };
2772
2773 OutputComposeSurfacesTest() {
2774 mOutput.setDisplayColorProfileForTest(
2775 std::unique_ptr<DisplayColorProfile>(mDisplayColorProfile));
2776 mOutput.setRenderSurfaceForTest(std::unique_ptr<RenderSurface>(mRenderSurface));
Vishnu Nair9b079a22020-01-21 14:36:08 -08002777 mOutput.cacheClientCompositionRequests(MAX_CLIENT_COMPOSITION_CACHE_SIZE);
Lloyd Pique56eba802019-08-28 15:45:25 -07002778
Lloyd Pique6818fa52019-12-03 12:32:13 -08002779 mOutput.mState.frame = kDefaultOutputFrame;
2780 mOutput.mState.viewport = kDefaultOutputViewport;
2781 mOutput.mState.scissor = kDefaultOutputScissor;
2782 mOutput.mState.transform = ui::Transform{kDefaultOutputOrientation};
2783 mOutput.mState.orientation = kDefaultOutputOrientation;
2784 mOutput.mState.dataspace = kDefaultOutputDataspace;
2785 mOutput.mState.colorTransformMatrix = kDefaultColorTransformMat;
2786 mOutput.mState.isSecure = false;
2787 mOutput.mState.needsFiltering = false;
2788 mOutput.mState.usesClientComposition = true;
2789 mOutput.mState.usesDeviceComposition = false;
Vishnu Nair9b079a22020-01-21 14:36:08 -08002790 mOutput.mState.reusedClientComposition = false;
Lloyd Pique56eba802019-08-28 15:45:25 -07002791
Lloyd Piquea38ea7e2019-04-16 18:10:26 -07002792 EXPECT_CALL(mOutput, getCompositionEngine()).WillRepeatedly(ReturnRef(mCompositionEngine));
Lloyd Pique56eba802019-08-28 15:45:25 -07002793 EXPECT_CALL(mCompositionEngine, getRenderEngine()).WillRepeatedly(ReturnRef(mRenderEngine));
Alec Mourie4034bb2019-11-19 12:45:54 -08002794 EXPECT_CALL(mCompositionEngine, getTimeStats())
2795 .WillRepeatedly(ReturnRef(*mTimeStats.get()));
Lloyd Pique6818fa52019-12-03 12:32:13 -08002796 EXPECT_CALL(*mDisplayColorProfile, getHdrCapabilities())
2797 .WillRepeatedly(ReturnRef(kHdrCapabilities));
Lloyd Pique56eba802019-08-28 15:45:25 -07002798 }
2799
Lloyd Pique6818fa52019-12-03 12:32:13 -08002800 struct ExecuteState : public CallOrderStateMachineHelper<TestType, ExecuteState> {
2801 auto execute() {
2802 getInstance()->mReadyFence = getInstance()->mOutput.composeSurfaces(kDebugRegion);
2803 return nextState<FenceCheckState>();
2804 }
2805 };
2806
2807 struct FenceCheckState : public CallOrderStateMachineHelper<TestType, FenceCheckState> {
2808 void expectNoFenceWasReturned() { EXPECT_FALSE(getInstance()->mReadyFence); }
2809
2810 void expectAFenceWasReturned() { EXPECT_TRUE(getInstance()->mReadyFence); }
2811 };
2812
2813 // Call this member function to start using the mini-DSL defined above.
2814 [[nodiscard]] auto verify() { return ExecuteState::make(this); }
2815
2816 static constexpr uint32_t kDefaultOutputOrientation = TR_IDENT;
2817 static constexpr ui::Dataspace kDefaultOutputDataspace = ui::Dataspace::UNKNOWN;
2818 static constexpr ui::Dataspace kExpensiveOutputDataspace = ui::Dataspace::DISPLAY_P3;
2819 static constexpr float kDefaultMaxLuminance = 0.9f;
2820 static constexpr float kDefaultAvgLuminance = 0.7f;
2821 static constexpr float kDefaultMinLuminance = 0.1f;
2822
2823 static const Rect kDefaultOutputFrame;
2824 static const Rect kDefaultOutputViewport;
2825 static const Rect kDefaultOutputScissor;
2826 static const mat4 kDefaultColorTransformMat;
2827
2828 static const Region kDebugRegion;
2829 static const HdrCapabilities kHdrCapabilities;
2830
Lloyd Pique56eba802019-08-28 15:45:25 -07002831 StrictMock<mock::CompositionEngine> mCompositionEngine;
2832 StrictMock<renderengine::mock::RenderEngine> mRenderEngine;
Alec Mourie4034bb2019-11-19 12:45:54 -08002833 // TODO: make this is a proper mock.
2834 std::shared_ptr<TimeStats> mTimeStats = std::make_shared<android::impl::TimeStats>();
Lloyd Pique56eba802019-08-28 15:45:25 -07002835 mock::DisplayColorProfile* mDisplayColorProfile = new StrictMock<mock::DisplayColorProfile>();
2836 mock::RenderSurface* mRenderSurface = new StrictMock<mock::RenderSurface>();
Lloyd Piquea38ea7e2019-04-16 18:10:26 -07002837 StrictMock<OutputPartialMock> mOutput;
Lloyd Pique56eba802019-08-28 15:45:25 -07002838 sp<GraphicBuffer> mOutputBuffer = new GraphicBuffer();
Lloyd Pique6818fa52019-12-03 12:32:13 -08002839
2840 std::optional<base::unique_fd> mReadyFence;
Lloyd Pique56eba802019-08-28 15:45:25 -07002841};
2842
2843const Rect OutputComposeSurfacesTest::kDefaultOutputFrame{1001, 1002, 1003, 1004};
2844const Rect OutputComposeSurfacesTest::kDefaultOutputViewport{1005, 1006, 1007, 1008};
2845const Rect OutputComposeSurfacesTest::kDefaultOutputScissor{1009, 1010, 1011, 1012};
Lloyd Pique0a456232020-01-16 17:51:13 -08002846const mat4 OutputComposeSurfacesTest::kDefaultColorTransformMat{mat4() * 0.5f};
Lloyd Pique6818fa52019-12-03 12:32:13 -08002847const Region OutputComposeSurfacesTest::kDebugRegion{Rect{100, 101, 102, 103}};
2848const HdrCapabilities OutputComposeSurfacesTest::
2849 kHdrCapabilities{{},
2850 OutputComposeSurfacesTest::kDefaultMaxLuminance,
2851 OutputComposeSurfacesTest::kDefaultAvgLuminance,
2852 OutputComposeSurfacesTest::kDefaultMinLuminance};
Lloyd Pique56eba802019-08-28 15:45:25 -07002853
Lloyd Piquea76ce462020-01-14 13:06:37 -08002854TEST_F(OutputComposeSurfacesTest, doesNothingButSignalNoExpensiveRenderingIfNoClientComposition) {
Lloyd Pique6818fa52019-12-03 12:32:13 -08002855 mOutput.mState.usesClientComposition = false;
Lloyd Pique56eba802019-08-28 15:45:25 -07002856
Lloyd Piquea76ce462020-01-14 13:06:37 -08002857 EXPECT_CALL(mOutput, setExpensiveRenderingExpected(false));
2858
Lloyd Pique6818fa52019-12-03 12:32:13 -08002859 verify().execute().expectAFenceWasReturned();
Lloyd Pique56eba802019-08-28 15:45:25 -07002860}
2861
Lloyd Pique6818fa52019-12-03 12:32:13 -08002862TEST_F(OutputComposeSurfacesTest, doesMinimalWorkIfDequeueBufferFails) {
2863 EXPECT_CALL(mOutput, getSkipColorTransform()).WillRepeatedly(Return(false));
2864 EXPECT_CALL(*mDisplayColorProfile, hasWideColorGamut()).WillRepeatedly(Return(true));
2865 EXPECT_CALL(mRenderEngine, supportsProtectedContent()).WillRepeatedly(Return(false));
2866 EXPECT_CALL(mOutput, generateClientCompositionRequests(_, _, kDefaultOutputDataspace))
Vishnu Nair9b079a22020-01-21 14:36:08 -08002867 .WillRepeatedly(Return(std::vector<LayerFE::LayerSettings>{}));
Lloyd Pique6818fa52019-12-03 12:32:13 -08002868 EXPECT_CALL(mOutput, appendRegionFlashRequests(RegionEq(kDebugRegion), _))
2869 .WillRepeatedly(Return());
Lloyd Pique56eba802019-08-28 15:45:25 -07002870
Lloyd Pique6818fa52019-12-03 12:32:13 -08002871 EXPECT_CALL(*mRenderSurface, dequeueBuffer(_)).WillOnce(Return(nullptr));
Lloyd Pique56eba802019-08-28 15:45:25 -07002872
Lloyd Pique6818fa52019-12-03 12:32:13 -08002873 verify().execute().expectNoFenceWasReturned();
2874}
Lloyd Pique56eba802019-08-28 15:45:25 -07002875
Lloyd Pique6818fa52019-12-03 12:32:13 -08002876TEST_F(OutputComposeSurfacesTest, handlesZeroCompositionRequests) {
2877 EXPECT_CALL(mOutput, getSkipColorTransform()).WillRepeatedly(Return(false));
2878 EXPECT_CALL(*mDisplayColorProfile, hasWideColorGamut()).WillRepeatedly(Return(true));
2879 EXPECT_CALL(mRenderEngine, supportsProtectedContent()).WillRepeatedly(Return(false));
2880 EXPECT_CALL(mOutput, generateClientCompositionRequests(_, _, kDefaultOutputDataspace))
Vishnu Nair9b079a22020-01-21 14:36:08 -08002881 .WillRepeatedly(Return(std::vector<LayerFE::LayerSettings>{}));
Lloyd Pique6818fa52019-12-03 12:32:13 -08002882 EXPECT_CALL(mOutput, appendRegionFlashRequests(RegionEq(kDebugRegion), _))
2883 .WillRepeatedly(Return());
Lloyd Pique56eba802019-08-28 15:45:25 -07002884
Lloyd Pique6818fa52019-12-03 12:32:13 -08002885 EXPECT_CALL(*mRenderSurface, dequeueBuffer(_)).WillRepeatedly(Return(mOutputBuffer));
2886 EXPECT_CALL(mRenderEngine, drawLayers(_, IsEmpty(), _, true, _, _))
2887 .WillRepeatedly(Return(NO_ERROR));
Lloyd Pique56eba802019-08-28 15:45:25 -07002888
Lloyd Pique6818fa52019-12-03 12:32:13 -08002889 verify().execute().expectAFenceWasReturned();
2890}
Lloyd Pique56eba802019-08-28 15:45:25 -07002891
Lloyd Pique6818fa52019-12-03 12:32:13 -08002892TEST_F(OutputComposeSurfacesTest, buildsAndRendersRequestList) {
Vishnu Nair9b079a22020-01-21 14:36:08 -08002893 LayerFE::LayerSettings r1;
2894 LayerFE::LayerSettings r2;
Lloyd Pique6818fa52019-12-03 12:32:13 -08002895
2896 r1.geometry.boundaries = FloatRect{1, 2, 3, 4};
2897 r2.geometry.boundaries = FloatRect{5, 6, 7, 8};
2898
2899 EXPECT_CALL(mOutput, getSkipColorTransform()).WillRepeatedly(Return(false));
2900 EXPECT_CALL(*mDisplayColorProfile, hasWideColorGamut()).WillRepeatedly(Return(true));
2901 EXPECT_CALL(mRenderEngine, supportsProtectedContent()).WillRepeatedly(Return(false));
2902 EXPECT_CALL(mOutput, generateClientCompositionRequests(_, _, kDefaultOutputDataspace))
Vishnu Nair9b079a22020-01-21 14:36:08 -08002903 .WillRepeatedly(Return(std::vector<LayerFE::LayerSettings>{r1}));
Lloyd Pique6818fa52019-12-03 12:32:13 -08002904 EXPECT_CALL(mOutput, appendRegionFlashRequests(RegionEq(kDebugRegion), _))
2905 .WillRepeatedly(
2906 Invoke([&](const Region&,
Vishnu Nair9b079a22020-01-21 14:36:08 -08002907 std::vector<LayerFE::LayerSettings>& clientCompositionLayers) {
Lloyd Pique6818fa52019-12-03 12:32:13 -08002908 clientCompositionLayers.emplace_back(r2);
2909 }));
2910
2911 EXPECT_CALL(*mRenderSurface, dequeueBuffer(_)).WillRepeatedly(Return(mOutputBuffer));
Vishnu Nair9b079a22020-01-21 14:36:08 -08002912 EXPECT_CALL(mRenderEngine, drawLayers(_, ElementsAre(Pointee(r1), Pointee(r2)), _, true, _, _))
Lloyd Pique6818fa52019-12-03 12:32:13 -08002913 .WillRepeatedly(Return(NO_ERROR));
2914
2915 verify().execute().expectAFenceWasReturned();
2916}
2917
Vishnu Nair9b079a22020-01-21 14:36:08 -08002918TEST_F(OutputComposeSurfacesTest, renderDuplicateClientCompositionRequestsWithoutCache) {
2919 mOutput.cacheClientCompositionRequests(0);
2920 LayerFE::LayerSettings r1;
2921 LayerFE::LayerSettings r2;
2922
2923 r1.geometry.boundaries = FloatRect{1, 2, 3, 4};
2924 r2.geometry.boundaries = FloatRect{5, 6, 7, 8};
2925
2926 EXPECT_CALL(mOutput, getSkipColorTransform()).WillRepeatedly(Return(false));
2927 EXPECT_CALL(*mDisplayColorProfile, hasWideColorGamut()).WillRepeatedly(Return(true));
2928 EXPECT_CALL(mRenderEngine, supportsProtectedContent()).WillRepeatedly(Return(false));
2929 EXPECT_CALL(mOutput, generateClientCompositionRequests(_, _, kDefaultOutputDataspace))
2930 .WillRepeatedly(Return(std::vector<LayerFE::LayerSettings>{r1, r2}));
2931 EXPECT_CALL(mOutput, appendRegionFlashRequests(RegionEq(kDebugRegion), _))
2932 .WillRepeatedly(Return());
2933
2934 EXPECT_CALL(*mRenderSurface, dequeueBuffer(_)).WillRepeatedly(Return(mOutputBuffer));
2935 EXPECT_CALL(mRenderEngine, drawLayers(_, ElementsAre(Pointee(r1), Pointee(r2)), _, true, _, _))
2936 .Times(2)
2937 .WillOnce(Return(NO_ERROR));
2938
2939 verify().execute().expectAFenceWasReturned();
2940 EXPECT_FALSE(mOutput.mState.reusedClientComposition);
2941
2942 verify().execute().expectAFenceWasReturned();
2943 EXPECT_FALSE(mOutput.mState.reusedClientComposition);
2944}
2945
2946TEST_F(OutputComposeSurfacesTest, skipDuplicateClientCompositionRequests) {
2947 mOutput.cacheClientCompositionRequests(3);
2948 LayerFE::LayerSettings r1;
2949 LayerFE::LayerSettings r2;
2950
2951 r1.geometry.boundaries = FloatRect{1, 2, 3, 4};
2952 r2.geometry.boundaries = FloatRect{5, 6, 7, 8};
2953
2954 EXPECT_CALL(mOutput, getSkipColorTransform()).WillRepeatedly(Return(false));
2955 EXPECT_CALL(*mDisplayColorProfile, hasWideColorGamut()).WillRepeatedly(Return(true));
2956 EXPECT_CALL(mRenderEngine, supportsProtectedContent()).WillRepeatedly(Return(false));
2957 EXPECT_CALL(mOutput, generateClientCompositionRequests(_, _, kDefaultOutputDataspace))
2958 .WillRepeatedly(Return(std::vector<LayerFE::LayerSettings>{r1, r2}));
2959 EXPECT_CALL(mOutput, appendRegionFlashRequests(RegionEq(kDebugRegion), _))
2960 .WillRepeatedly(Return());
2961
2962 EXPECT_CALL(*mRenderSurface, dequeueBuffer(_)).WillRepeatedly(Return(mOutputBuffer));
2963 EXPECT_CALL(mRenderEngine, drawLayers(_, ElementsAre(Pointee(r1), Pointee(r2)), _, true, _, _))
2964 .WillOnce(Return(NO_ERROR));
2965 EXPECT_CALL(mOutput, setExpensiveRenderingExpected(false));
2966
2967 verify().execute().expectAFenceWasReturned();
2968 EXPECT_FALSE(mOutput.mState.reusedClientComposition);
2969
2970 // We do not expect another call to draw layers.
2971 verify().execute().expectAFenceWasReturned();
2972 EXPECT_TRUE(mOutput.mState.reusedClientComposition);
2973}
2974
2975TEST_F(OutputComposeSurfacesTest, clientCompositionIfBufferChanges) {
2976 LayerFE::LayerSettings r1;
2977 LayerFE::LayerSettings r2;
2978
2979 r1.geometry.boundaries = FloatRect{1, 2, 3, 4};
2980 r2.geometry.boundaries = FloatRect{5, 6, 7, 8};
2981
2982 EXPECT_CALL(mOutput, getSkipColorTransform()).WillRepeatedly(Return(false));
2983 EXPECT_CALL(*mDisplayColorProfile, hasWideColorGamut()).WillRepeatedly(Return(true));
2984 EXPECT_CALL(mRenderEngine, supportsProtectedContent()).WillRepeatedly(Return(false));
2985 EXPECT_CALL(mOutput, generateClientCompositionRequests(_, _, kDefaultOutputDataspace))
2986 .WillRepeatedly(Return(std::vector<LayerFE::LayerSettings>{r1, r2}));
2987 EXPECT_CALL(mOutput, appendRegionFlashRequests(RegionEq(kDebugRegion), _))
2988 .WillRepeatedly(Return());
2989
2990 sp<GraphicBuffer> otherOutputBuffer = new GraphicBuffer();
2991 EXPECT_CALL(*mRenderSurface, dequeueBuffer(_))
2992 .WillOnce(Return(mOutputBuffer))
2993 .WillOnce(Return(otherOutputBuffer));
2994 EXPECT_CALL(mRenderEngine, drawLayers(_, ElementsAre(Pointee(r1), Pointee(r2)), _, true, _, _))
2995 .WillRepeatedly(Return(NO_ERROR));
2996
2997 verify().execute().expectAFenceWasReturned();
2998 EXPECT_FALSE(mOutput.mState.reusedClientComposition);
2999
3000 verify().execute().expectAFenceWasReturned();
3001 EXPECT_FALSE(mOutput.mState.reusedClientComposition);
3002}
3003
3004TEST_F(OutputComposeSurfacesTest, clientCompositionIfRequestChanges) {
3005 LayerFE::LayerSettings r1;
3006 LayerFE::LayerSettings r2;
3007 LayerFE::LayerSettings r3;
3008
3009 r1.geometry.boundaries = FloatRect{1, 2, 3, 4};
3010 r2.geometry.boundaries = FloatRect{5, 6, 7, 8};
3011 r3.geometry.boundaries = FloatRect{5, 6, 7, 9};
3012
3013 EXPECT_CALL(mOutput, getSkipColorTransform()).WillRepeatedly(Return(false));
3014 EXPECT_CALL(*mDisplayColorProfile, hasWideColorGamut()).WillRepeatedly(Return(true));
3015 EXPECT_CALL(mRenderEngine, supportsProtectedContent()).WillRepeatedly(Return(false));
3016 EXPECT_CALL(mOutput, generateClientCompositionRequests(_, _, kDefaultOutputDataspace))
3017 .WillOnce(Return(std::vector<LayerFE::LayerSettings>{r1, r2}))
3018 .WillOnce(Return(std::vector<LayerFE::LayerSettings>{r1, r3}));
3019 EXPECT_CALL(mOutput, appendRegionFlashRequests(RegionEq(kDebugRegion), _))
3020 .WillRepeatedly(Return());
3021
3022 EXPECT_CALL(*mRenderSurface, dequeueBuffer(_)).WillRepeatedly(Return(mOutputBuffer));
3023 EXPECT_CALL(mRenderEngine, drawLayers(_, ElementsAre(Pointee(r1), Pointee(r2)), _, true, _, _))
3024 .WillOnce(Return(NO_ERROR));
3025 EXPECT_CALL(mRenderEngine, drawLayers(_, ElementsAre(Pointee(r1), Pointee(r3)), _, true, _, _))
3026 .WillOnce(Return(NO_ERROR));
3027
3028 verify().execute().expectAFenceWasReturned();
3029 EXPECT_FALSE(mOutput.mState.reusedClientComposition);
3030
3031 verify().execute().expectAFenceWasReturned();
3032 EXPECT_FALSE(mOutput.mState.reusedClientComposition);
3033}
3034
Lloyd Pique6818fa52019-12-03 12:32:13 -08003035struct OutputComposeSurfacesTest_UsesExpectedDisplaySettings : public OutputComposeSurfacesTest {
3036 OutputComposeSurfacesTest_UsesExpectedDisplaySettings() {
3037 EXPECT_CALL(mRenderEngine, supportsProtectedContent()).WillRepeatedly(Return(false));
3038 EXPECT_CALL(mOutput, generateClientCompositionRequests(_, _, kDefaultOutputDataspace))
Vishnu Nair9b079a22020-01-21 14:36:08 -08003039 .WillRepeatedly(Return(std::vector<LayerFE::LayerSettings>{}));
Lloyd Pique6818fa52019-12-03 12:32:13 -08003040 EXPECT_CALL(mOutput, appendRegionFlashRequests(RegionEq(kDebugRegion), _))
3041 .WillRepeatedly(Return());
3042 EXPECT_CALL(*mRenderSurface, dequeueBuffer(_)).WillRepeatedly(Return(mOutputBuffer));
3043 }
3044
3045 struct MixedCompositionState
3046 : public CallOrderStateMachineHelper<TestType, MixedCompositionState> {
3047 auto ifMixedCompositionIs(bool used) {
3048 getInstance()->mOutput.mState.usesDeviceComposition = used;
3049 return nextState<OutputUsesHdrState>();
3050 }
3051 };
3052
3053 struct OutputUsesHdrState : public CallOrderStateMachineHelper<TestType, OutputUsesHdrState> {
3054 auto andIfUsesHdr(bool used) {
3055 EXPECT_CALL(*getInstance()->mDisplayColorProfile, hasWideColorGamut())
3056 .WillOnce(Return(used));
3057 return nextState<SkipColorTransformState>();
3058 }
3059 };
3060
3061 struct SkipColorTransformState
3062 : public CallOrderStateMachineHelper<TestType, SkipColorTransformState> {
3063 auto andIfSkipColorTransform(bool skip) {
3064 // May be called zero or one times.
3065 EXPECT_CALL(getInstance()->mOutput, getSkipColorTransform())
3066 .WillRepeatedly(Return(skip));
3067 return nextState<ExpectDisplaySettingsState>();
3068 }
3069 };
3070
3071 struct ExpectDisplaySettingsState
3072 : public CallOrderStateMachineHelper<TestType, ExpectDisplaySettingsState> {
3073 auto thenExpectDisplaySettingsUsed(renderengine::DisplaySettings settings) {
3074 EXPECT_CALL(getInstance()->mRenderEngine, drawLayers(settings, _, _, true, _, _))
3075 .WillOnce(Return(NO_ERROR));
3076 return nextState<ExecuteState>();
3077 }
3078 };
3079
3080 // Call this member function to start using the mini-DSL defined above.
3081 [[nodiscard]] auto verify() { return MixedCompositionState::make(this); }
3082};
3083
3084TEST_F(OutputComposeSurfacesTest_UsesExpectedDisplaySettings, forHdrMixedComposition) {
3085 verify().ifMixedCompositionIs(true)
3086 .andIfUsesHdr(true)
3087 .andIfSkipColorTransform(false)
3088 .thenExpectDisplaySettingsUsed({kDefaultOutputScissor, kDefaultOutputScissor, mat4(),
3089 kDefaultMaxLuminance, kDefaultOutputDataspace, mat4(),
3090 Region::INVALID_REGION, kDefaultOutputOrientation})
3091 .execute()
3092 .expectAFenceWasReturned();
3093}
3094
3095TEST_F(OutputComposeSurfacesTest_UsesExpectedDisplaySettings, forNonHdrMixedComposition) {
3096 verify().ifMixedCompositionIs(true)
3097 .andIfUsesHdr(false)
3098 .andIfSkipColorTransform(false)
3099 .thenExpectDisplaySettingsUsed({kDefaultOutputScissor, kDefaultOutputScissor, mat4(),
3100 kDefaultMaxLuminance, kDefaultOutputDataspace, mat4(),
3101 Region::INVALID_REGION, kDefaultOutputOrientation})
3102 .execute()
3103 .expectAFenceWasReturned();
3104}
3105
3106TEST_F(OutputComposeSurfacesTest_UsesExpectedDisplaySettings, forHdrOnlyClientComposition) {
3107 verify().ifMixedCompositionIs(false)
3108 .andIfUsesHdr(true)
3109 .andIfSkipColorTransform(false)
3110 .thenExpectDisplaySettingsUsed({kDefaultOutputScissor, kDefaultOutputScissor, mat4(),
3111 kDefaultMaxLuminance, kDefaultOutputDataspace,
3112 kDefaultColorTransformMat, Region::INVALID_REGION,
3113 kDefaultOutputOrientation})
3114 .execute()
3115 .expectAFenceWasReturned();
3116}
3117
3118TEST_F(OutputComposeSurfacesTest_UsesExpectedDisplaySettings, forNonHdrOnlyClientComposition) {
3119 verify().ifMixedCompositionIs(false)
3120 .andIfUsesHdr(false)
3121 .andIfSkipColorTransform(false)
3122 .thenExpectDisplaySettingsUsed({kDefaultOutputScissor, kDefaultOutputScissor, mat4(),
3123 kDefaultMaxLuminance, kDefaultOutputDataspace,
3124 kDefaultColorTransformMat, Region::INVALID_REGION,
3125 kDefaultOutputOrientation})
3126 .execute()
3127 .expectAFenceWasReturned();
3128}
3129
3130TEST_F(OutputComposeSurfacesTest_UsesExpectedDisplaySettings,
3131 usesExpectedDisplaySettingsForHdrOnlyClientCompositionWithSkipClientTransform) {
3132 verify().ifMixedCompositionIs(false)
3133 .andIfUsesHdr(true)
3134 .andIfSkipColorTransform(true)
3135 .thenExpectDisplaySettingsUsed({kDefaultOutputScissor, kDefaultOutputScissor, mat4(),
3136 kDefaultMaxLuminance, kDefaultOutputDataspace, mat4(),
3137 Region::INVALID_REGION, kDefaultOutputOrientation})
3138 .execute()
3139 .expectAFenceWasReturned();
3140}
3141
3142struct OutputComposeSurfacesTest_HandlesProtectedContent : public OutputComposeSurfacesTest {
3143 struct Layer {
3144 Layer() {
3145 EXPECT_CALL(mOutputLayer, getLayer()).WillRepeatedly(ReturnRef(mLayer));
3146 EXPECT_CALL(mLayer, getFEState()).WillRepeatedly(ReturnRef(mLayerFEState));
3147 }
3148
3149 StrictMock<mock::OutputLayer> mOutputLayer;
3150 StrictMock<mock::Layer> mLayer;
3151 LayerFECompositionState mLayerFEState;
3152 };
3153
3154 OutputComposeSurfacesTest_HandlesProtectedContent() {
3155 mLayer1.mLayerFEState.hasProtectedContent = false;
3156 mLayer2.mLayerFEState.hasProtectedContent = false;
3157
3158 EXPECT_CALL(mOutput, getOutputLayerCount()).WillRepeatedly(Return(2u));
3159 EXPECT_CALL(mOutput, getOutputLayerOrderedByZByIndex(0u))
3160 .WillRepeatedly(Return(&mLayer1.mOutputLayer));
3161 EXPECT_CALL(mOutput, getOutputLayerOrderedByZByIndex(1u))
3162 .WillRepeatedly(Return(&mLayer2.mOutputLayer));
3163
3164 EXPECT_CALL(mOutput, getSkipColorTransform()).WillRepeatedly(Return(false));
3165
3166 EXPECT_CALL(*mDisplayColorProfile, hasWideColorGamut()).WillRepeatedly(Return(true));
3167
3168 EXPECT_CALL(mOutput, generateClientCompositionRequests(_, _, _))
Vishnu Nair9b079a22020-01-21 14:36:08 -08003169 .WillRepeatedly(Return(std::vector<LayerFE::LayerSettings>{}));
Lloyd Pique6818fa52019-12-03 12:32:13 -08003170 EXPECT_CALL(mOutput, appendRegionFlashRequests(RegionEq(kDebugRegion), _))
3171 .WillRepeatedly(Return());
3172 EXPECT_CALL(*mRenderSurface, dequeueBuffer(_)).WillRepeatedly(Return(mOutputBuffer));
3173 EXPECT_CALL(mRenderEngine, drawLayers(_, _, _, true, _, _))
3174 .WillRepeatedly(Return(NO_ERROR));
3175 }
3176
3177 Layer mLayer1;
3178 Layer mLayer2;
3179};
3180
3181TEST_F(OutputComposeSurfacesTest_HandlesProtectedContent, ifDisplayIsNotSecure) {
3182 mOutput.mState.isSecure = false;
3183 mLayer2.mLayerFEState.hasProtectedContent = true;
3184 EXPECT_CALL(mRenderEngine, supportsProtectedContent()).WillRepeatedly(Return(true));
3185
3186 mOutput.composeSurfaces(kDebugRegion);
3187}
3188
3189TEST_F(OutputComposeSurfacesTest_HandlesProtectedContent, ifRenderEngineDoesNotSupportIt) {
3190 mOutput.mState.isSecure = true;
3191 mLayer2.mLayerFEState.hasProtectedContent = true;
3192 EXPECT_CALL(mRenderEngine, supportsProtectedContent()).WillRepeatedly(Return(false));
3193
3194 mOutput.composeSurfaces(kDebugRegion);
3195}
3196
3197TEST_F(OutputComposeSurfacesTest_HandlesProtectedContent, ifNoProtectedContentLayers) {
3198 mOutput.mState.isSecure = true;
3199 mLayer2.mLayerFEState.hasProtectedContent = false;
3200 EXPECT_CALL(mRenderEngine, supportsProtectedContent()).WillRepeatedly(Return(true));
3201 EXPECT_CALL(mRenderEngine, isProtected).WillOnce(Return(true)).WillOnce(Return(false));
3202 EXPECT_CALL(*mRenderSurface, isProtected).WillOnce(Return(true));
3203 EXPECT_CALL(mRenderEngine, useProtectedContext(false));
3204 EXPECT_CALL(*mRenderSurface, setProtected(false));
3205
3206 mOutput.composeSurfaces(kDebugRegion);
3207}
3208
3209TEST_F(OutputComposeSurfacesTest_HandlesProtectedContent, ifNotEnabled) {
3210 mOutput.mState.isSecure = true;
3211 mLayer2.mLayerFEState.hasProtectedContent = true;
3212 EXPECT_CALL(mRenderEngine, supportsProtectedContent()).WillRepeatedly(Return(true));
3213
3214 // For this test, we also check the call order of key functions.
3215 InSequence seq;
3216
3217 EXPECT_CALL(mRenderEngine, isProtected).WillOnce(Return(false));
3218 EXPECT_CALL(mRenderEngine, useProtectedContext(true));
3219 EXPECT_CALL(*mRenderSurface, isProtected).WillOnce(Return(false));
3220 EXPECT_CALL(mRenderEngine, isProtected).WillOnce(Return(true));
3221 EXPECT_CALL(*mRenderSurface, setProtected(true));
3222 // Must happen after setting the protected content state.
3223 EXPECT_CALL(*mRenderSurface, dequeueBuffer(_)).WillRepeatedly(Return(mOutputBuffer));
3224 EXPECT_CALL(mRenderEngine, drawLayers(_, _, _, true, _, _)).WillOnce(Return(NO_ERROR));
3225
3226 mOutput.composeSurfaces(kDebugRegion);
3227}
3228
3229TEST_F(OutputComposeSurfacesTest_HandlesProtectedContent, ifAlreadyEnabledEverywhere) {
3230 mOutput.mState.isSecure = true;
3231 mLayer2.mLayerFEState.hasProtectedContent = true;
3232 EXPECT_CALL(mRenderEngine, supportsProtectedContent()).WillRepeatedly(Return(true));
3233 EXPECT_CALL(mRenderEngine, isProtected).WillOnce(Return(true));
3234 EXPECT_CALL(*mRenderSurface, isProtected).WillOnce(Return(true));
3235
3236 mOutput.composeSurfaces(kDebugRegion);
3237}
3238
3239TEST_F(OutputComposeSurfacesTest_HandlesProtectedContent, ifFailsToEnableInRenderEngine) {
3240 mOutput.mState.isSecure = true;
3241 mLayer2.mLayerFEState.hasProtectedContent = true;
3242 EXPECT_CALL(mRenderEngine, supportsProtectedContent()).WillRepeatedly(Return(true));
3243 EXPECT_CALL(mRenderEngine, isProtected).WillOnce(Return(false)).WillOnce(Return(false));
3244 EXPECT_CALL(*mRenderSurface, isProtected).WillOnce(Return(false));
3245 EXPECT_CALL(mRenderEngine, useProtectedContext(true));
3246
3247 mOutput.composeSurfaces(kDebugRegion);
3248}
3249
3250TEST_F(OutputComposeSurfacesTest_HandlesProtectedContent, ifAlreadyEnabledInRenderEngine) {
3251 mOutput.mState.isSecure = true;
3252 mLayer2.mLayerFEState.hasProtectedContent = true;
3253 EXPECT_CALL(mRenderEngine, supportsProtectedContent()).WillRepeatedly(Return(true));
3254 EXPECT_CALL(mRenderEngine, isProtected).WillOnce(Return(true)).WillOnce(Return(true));
3255 EXPECT_CALL(*mRenderSurface, isProtected).WillOnce(Return(false));
3256 EXPECT_CALL(*mRenderSurface, setProtected(true));
3257
3258 mOutput.composeSurfaces(kDebugRegion);
3259}
3260
3261TEST_F(OutputComposeSurfacesTest_HandlesProtectedContent, ifAlreadyEnabledInRenderSurface) {
3262 mOutput.mState.isSecure = true;
3263 mLayer2.mLayerFEState.hasProtectedContent = true;
3264 EXPECT_CALL(mRenderEngine, supportsProtectedContent()).WillRepeatedly(Return(true));
3265 EXPECT_CALL(mRenderEngine, isProtected).WillOnce(Return(false));
3266 EXPECT_CALL(*mRenderSurface, isProtected).WillOnce(Return(true));
3267 EXPECT_CALL(mRenderEngine, useProtectedContext(true));
3268
3269 mOutput.composeSurfaces(kDebugRegion);
3270}
3271
3272struct OutputComposeSurfacesTest_SetsExpensiveRendering : public OutputComposeSurfacesTest {
3273 OutputComposeSurfacesTest_SetsExpensiveRendering() {
3274 EXPECT_CALL(mOutput, getSkipColorTransform()).WillRepeatedly(Return(false));
3275 EXPECT_CALL(*mDisplayColorProfile, hasWideColorGamut()).WillRepeatedly(Return(true));
3276 EXPECT_CALL(mRenderEngine, supportsProtectedContent()).WillRepeatedly(Return(false));
3277 EXPECT_CALL(mOutput, appendRegionFlashRequests(RegionEq(kDebugRegion), _))
3278 .WillRepeatedly(Return());
3279 EXPECT_CALL(*mRenderSurface, dequeueBuffer(_)).WillRepeatedly(Return(mOutputBuffer));
3280 }
3281};
3282
3283TEST_F(OutputComposeSurfacesTest_SetsExpensiveRendering, IfExepensiveOutputDataspaceIsUsed) {
3284 mOutput.mState.dataspace = kExpensiveOutputDataspace;
3285
3286 EXPECT_CALL(mOutput, generateClientCompositionRequests(_, _, kExpensiveOutputDataspace))
Vishnu Nair9b079a22020-01-21 14:36:08 -08003287 .WillOnce(Return(std::vector<LayerFE::LayerSettings>{}));
Lloyd Pique6818fa52019-12-03 12:32:13 -08003288
3289 // For this test, we also check the call order of key functions.
3290 InSequence seq;
3291
3292 EXPECT_CALL(mOutput, setExpensiveRenderingExpected(true));
3293 EXPECT_CALL(mRenderEngine, drawLayers(_, _, _, true, _, _)).WillOnce(Return(NO_ERROR));
Lloyd Pique6818fa52019-12-03 12:32:13 -08003294
3295 mOutput.composeSurfaces(kDebugRegion);
Lloyd Pique56eba802019-08-28 15:45:25 -07003296}
3297
3298/*
3299 * Output::generateClientCompositionRequests()
3300 */
3301
3302struct GenerateClientCompositionRequestsTest : public testing::Test {
Lloyd Piquefaa3f192019-11-14 14:05:09 -08003303 struct OutputPartialMock : public OutputPartialMockBase {
Lloyd Piquea38ea7e2019-04-16 18:10:26 -07003304 // compositionengine::Output overrides
Vishnu Nair9b079a22020-01-21 14:36:08 -08003305 std::vector<LayerFE::LayerSettings> generateClientCompositionRequests(
Vishnu Nair3a7346c2019-12-04 08:09:09 -08003306 bool supportsProtectedContent, Region& clearRegion,
3307 ui::Dataspace dataspace) override {
Lloyd Pique56eba802019-08-28 15:45:25 -07003308 return impl::Output::generateClientCompositionRequests(supportsProtectedContent,
Vishnu Nair3a7346c2019-12-04 08:09:09 -08003309 clearRegion, dataspace);
Lloyd Pique56eba802019-08-28 15:45:25 -07003310 }
3311 };
3312
Lloyd Piquea4863342019-12-04 18:45:02 -08003313 struct Layer {
3314 Layer() {
3315 EXPECT_CALL(mOutputLayer, getState()).WillRepeatedly(ReturnRef(mOutputLayerState));
3316 EXPECT_CALL(mOutputLayer, editState()).WillRepeatedly(ReturnRef(mOutputLayerState));
3317 EXPECT_CALL(mOutputLayer, getLayer()).WillRepeatedly(ReturnRef(mLayer));
3318 EXPECT_CALL(mOutputLayer, getLayerFE()).WillRepeatedly(ReturnRef(mLayerFE));
3319 EXPECT_CALL(mLayer, getFEState()).WillRepeatedly(ReturnRef(mLayerFEState));
3320 }
3321
3322 StrictMock<mock::OutputLayer> mOutputLayer;
3323 StrictMock<mock::Layer> mLayer;
3324 StrictMock<mock::LayerFE> mLayerFE;
3325 LayerFECompositionState mLayerFEState;
3326 impl::OutputLayerCompositionState mOutputLayerState;
Vishnu Nair9b079a22020-01-21 14:36:08 -08003327 LayerFE::LayerSettings mLayerSettings;
Lloyd Piquea4863342019-12-04 18:45:02 -08003328 };
3329
Lloyd Pique56eba802019-08-28 15:45:25 -07003330 GenerateClientCompositionRequestsTest() {
Lloyd Piquea4863342019-12-04 18:45:02 -08003331 mOutput.mState.needsFiltering = false;
3332
Lloyd Pique56eba802019-08-28 15:45:25 -07003333 mOutput.setDisplayColorProfileForTest(
3334 std::unique_ptr<DisplayColorProfile>(mDisplayColorProfile));
3335 mOutput.setRenderSurfaceForTest(std::unique_ptr<RenderSurface>(mRenderSurface));
3336 }
3337
Lloyd Pique56eba802019-08-28 15:45:25 -07003338 mock::DisplayColorProfile* mDisplayColorProfile = new StrictMock<mock::DisplayColorProfile>();
3339 mock::RenderSurface* mRenderSurface = new StrictMock<mock::RenderSurface>();
Lloyd Piquea38ea7e2019-04-16 18:10:26 -07003340 StrictMock<OutputPartialMock> mOutput;
Lloyd Pique56eba802019-08-28 15:45:25 -07003341};
3342
Lloyd Piquea4863342019-12-04 18:45:02 -08003343struct GenerateClientCompositionRequestsTest_ThreeLayers
3344 : public GenerateClientCompositionRequestsTest {
3345 GenerateClientCompositionRequestsTest_ThreeLayers() {
3346 mOutput.mState.frame = kDisplayFrame;
3347 mOutput.mState.viewport = kDisplayViewport;
3348 mOutput.mState.scissor = kDisplayScissor;
3349 mOutput.mState.transform = ui::Transform{kDisplayOrientation};
3350 mOutput.mState.orientation = kDisplayOrientation;
3351 mOutput.mState.needsFiltering = false;
3352 mOutput.mState.isSecure = false;
Lloyd Pique56eba802019-08-28 15:45:25 -07003353
Lloyd Piquea4863342019-12-04 18:45:02 -08003354 for (size_t i = 0; i < mLayers.size(); i++) {
3355 mLayers[i].mOutputLayerState.clearClientTarget = false;
3356 mLayers[i].mOutputLayerState.visibleRegion = Region(kDisplayFrame);
3357 mLayers[i].mLayerFEState.isOpaque = true;
Vishnu Nair9b079a22020-01-21 14:36:08 -08003358 mLayers[i].mLayerSettings.geometry.boundaries =
Lloyd Piquea4863342019-12-04 18:45:02 -08003359 FloatRect{static_cast<float>(i + 1), 0.f, 0.f, 0.f};
Vishnu Nair9b079a22020-01-21 14:36:08 -08003360 mLayers[i].mLayerSettings.source.solidColor = {1.0f, 1.0f, 1.0f};
3361 mLayers[i].mLayerSettings.alpha = 1.0f;
3362 mLayers[i].mLayerSettings.disableBlending = false;
Lloyd Pique56eba802019-08-28 15:45:25 -07003363
Lloyd Piquea4863342019-12-04 18:45:02 -08003364 EXPECT_CALL(mOutput, getOutputLayerOrderedByZByIndex(i))
3365 .WillRepeatedly(Return(&mLayers[i].mOutputLayer));
3366 EXPECT_CALL(mLayers[i].mOutputLayer, requiresClientComposition())
3367 .WillRepeatedly(Return(true));
3368 EXPECT_CALL(mLayers[i].mOutputLayer, needsFiltering()).WillRepeatedly(Return(false));
3369 }
Lloyd Pique56eba802019-08-28 15:45:25 -07003370
Lloyd Piquea4863342019-12-04 18:45:02 -08003371 EXPECT_CALL(mOutput, getOutputLayerCount()).WillRepeatedly(Return(mLayers.size()));
3372 }
Lloyd Pique56eba802019-08-28 15:45:25 -07003373
Lloyd Piquea4863342019-12-04 18:45:02 -08003374 static constexpr uint32_t kDisplayOrientation = TR_IDENT;
3375 static constexpr ui::Dataspace kDisplayDataspace = ui::Dataspace::UNKNOWN;
Lloyd Pique56eba802019-08-28 15:45:25 -07003376
Lloyd Piquea4863342019-12-04 18:45:02 -08003377 static const Rect kDisplayFrame;
3378 static const Rect kDisplayViewport;
3379 static const Rect kDisplayScissor;
Lloyd Pique56eba802019-08-28 15:45:25 -07003380
Lloyd Piquea4863342019-12-04 18:45:02 -08003381 std::array<Layer, 3> mLayers;
3382};
Lloyd Pique56eba802019-08-28 15:45:25 -07003383
Lloyd Piquea4863342019-12-04 18:45:02 -08003384const Rect GenerateClientCompositionRequestsTest_ThreeLayers::kDisplayFrame(0, 0, 100, 200);
3385const Rect GenerateClientCompositionRequestsTest_ThreeLayers::kDisplayViewport(0, 0, 101, 201);
3386const Rect GenerateClientCompositionRequestsTest_ThreeLayers::kDisplayScissor(0, 0, 102, 202);
Lloyd Pique56eba802019-08-28 15:45:25 -07003387
Lloyd Piquea4863342019-12-04 18:45:02 -08003388TEST_F(GenerateClientCompositionRequestsTest_ThreeLayers, handlesNoClientCompostionLayers) {
3389 EXPECT_CALL(mLayers[0].mOutputLayer, requiresClientComposition()).WillOnce(Return(false));
3390 EXPECT_CALL(mLayers[1].mOutputLayer, requiresClientComposition()).WillOnce(Return(false));
3391 EXPECT_CALL(mLayers[2].mOutputLayer, requiresClientComposition()).WillOnce(Return(false));
Lloyd Pique56eba802019-08-28 15:45:25 -07003392
Lloyd Piquea4863342019-12-04 18:45:02 -08003393 Region accumClearRegion(Rect(10, 11, 12, 13));
3394 auto requests = mOutput.generateClientCompositionRequests(false /* supportsProtectedContent */,
3395 accumClearRegion, kDisplayDataspace);
Lloyd Pique56eba802019-08-28 15:45:25 -07003396 EXPECT_EQ(0u, requests.size());
Lloyd Piquea4863342019-12-04 18:45:02 -08003397 EXPECT_THAT(accumClearRegion, RegionEq(Region(Rect(10, 11, 12, 13))));
Lloyd Pique56eba802019-08-28 15:45:25 -07003398}
3399
Lloyd Piquea4863342019-12-04 18:45:02 -08003400TEST_F(GenerateClientCompositionRequestsTest_ThreeLayers, requiresVisibleRegionAfterViewportClip) {
3401 mLayers[0].mOutputLayerState.visibleRegion = Region(Rect(10, 10, 10, 10));
3402 mLayers[1].mOutputLayerState.visibleRegion = Region(Rect(4000, 0, 4010, 10));
3403 mLayers[2].mOutputLayerState.visibleRegion = Region(Rect(-10, -10, 0, 0));
3404
3405 Region accumClearRegion(Rect(10, 11, 12, 13));
3406 auto requests = mOutput.generateClientCompositionRequests(false /* supportsProtectedContent */,
3407 accumClearRegion, kDisplayDataspace);
3408 EXPECT_EQ(0u, requests.size());
3409 EXPECT_THAT(accumClearRegion, RegionEq(Region(Rect(10, 11, 12, 13))));
3410}
3411
3412TEST_F(GenerateClientCompositionRequestsTest_ThreeLayers, gathersClientCompositionRequests) {
Vishnu Nair9b079a22020-01-21 14:36:08 -08003413 LayerFE::LayerSettings mShadowSettings;
3414 mShadowSettings.source.solidColor = {0.1f, 0.1f, 0.1f};
Lloyd Piquea4863342019-12-04 18:45:02 -08003415
3416 EXPECT_CALL(mLayers[0].mLayerFE, prepareClientComposition(_)).WillOnce(Return(std::nullopt));
3417 EXPECT_CALL(mLayers[1].mLayerFE, prepareClientComposition(_))
Vishnu Nair9b079a22020-01-21 14:36:08 -08003418 .WillOnce(Return(mLayers[1].mLayerSettings));
Lloyd Piquea4863342019-12-04 18:45:02 -08003419 EXPECT_CALL(mLayers[1].mLayerFE,
Vishnu Nair9b079a22020-01-21 14:36:08 -08003420 prepareShadowClientComposition(mLayers[1].mLayerSettings, kDisplayViewport,
Lloyd Piquea4863342019-12-04 18:45:02 -08003421 kDisplayDataspace))
3422 .WillOnce(Return(std::nullopt));
3423 EXPECT_CALL(mLayers[2].mLayerFE, prepareClientComposition(_))
Vishnu Nair9b079a22020-01-21 14:36:08 -08003424 .WillOnce(Return(mLayers[2].mLayerSettings));
Lloyd Piquea4863342019-12-04 18:45:02 -08003425 EXPECT_CALL(mLayers[2].mLayerFE,
Vishnu Nair9b079a22020-01-21 14:36:08 -08003426 prepareShadowClientComposition(mLayers[2].mLayerSettings, kDisplayViewport,
Lloyd Piquea4863342019-12-04 18:45:02 -08003427 kDisplayDataspace))
Vishnu Nair9b079a22020-01-21 14:36:08 -08003428 .WillOnce(Return(mShadowSettings));
Lloyd Piquea4863342019-12-04 18:45:02 -08003429
3430 Region accumClearRegion(Rect(10, 11, 12, 13));
3431 auto requests = mOutput.generateClientCompositionRequests(false /* supportsProtectedContent */,
3432 accumClearRegion, kDisplayDataspace);
3433 ASSERT_EQ(3u, requests.size());
Vishnu Nair9b079a22020-01-21 14:36:08 -08003434 EXPECT_EQ(mLayers[1].mLayerSettings, requests[0]);
3435 EXPECT_EQ(mShadowSettings, requests[1]);
3436 EXPECT_EQ(mLayers[2].mLayerSettings, requests[2]);
Lloyd Piquea4863342019-12-04 18:45:02 -08003437
3438 EXPECT_THAT(accumClearRegion, RegionEq(Region(Rect(10, 11, 12, 13))));
3439
3440 // Check that a timestamp was set for the layers that generated requests
3441 EXPECT_TRUE(0 == mLayers[0].mOutputLayerState.clientCompositionTimestamp);
3442 EXPECT_TRUE(0 != mLayers[1].mOutputLayerState.clientCompositionTimestamp);
3443 EXPECT_TRUE(0 != mLayers[2].mOutputLayerState.clientCompositionTimestamp);
3444}
3445
3446TEST_F(GenerateClientCompositionRequestsTest_ThreeLayers,
3447 onlyClientComposesClientComposedLayersIfNoClearingNeeded) {
3448 EXPECT_CALL(mLayers[0].mOutputLayer, requiresClientComposition()).WillOnce(Return(false));
3449 EXPECT_CALL(mLayers[1].mOutputLayer, requiresClientComposition()).WillOnce(Return(false));
3450 EXPECT_CALL(mLayers[2].mOutputLayer, requiresClientComposition()).WillOnce(Return(true));
3451
3452 mLayers[0].mOutputLayerState.clearClientTarget = false;
3453 mLayers[1].mOutputLayerState.clearClientTarget = false;
3454 mLayers[2].mOutputLayerState.clearClientTarget = false;
3455
3456 mLayers[0].mLayerFEState.isOpaque = true;
3457 mLayers[1].mLayerFEState.isOpaque = true;
3458 mLayers[2].mLayerFEState.isOpaque = true;
3459
3460 EXPECT_CALL(mLayers[2].mLayerFE, prepareClientComposition(_))
Vishnu Nair9b079a22020-01-21 14:36:08 -08003461 .WillOnce(Return(mLayers[2].mLayerSettings));
Lloyd Piquea4863342019-12-04 18:45:02 -08003462 EXPECT_CALL(mLayers[2].mLayerFE, prepareShadowClientComposition(_, _, _))
3463 .WillOnce(Return(std::nullopt));
3464
3465 Region accumClearRegion(Rect(10, 11, 12, 13));
3466 auto requests = mOutput.generateClientCompositionRequests(false /* supportsProtectedContent */,
3467 accumClearRegion, kDisplayDataspace);
3468 ASSERT_EQ(1u, requests.size());
Vishnu Nair9b079a22020-01-21 14:36:08 -08003469 EXPECT_EQ(mLayers[2].mLayerSettings, requests[0]);
Lloyd Piquea4863342019-12-04 18:45:02 -08003470
3471 EXPECT_THAT(accumClearRegion, RegionEq(Region(Rect(10, 11, 12, 13))));
3472}
3473
3474TEST_F(GenerateClientCompositionRequestsTest_ThreeLayers,
3475 onlyClientComposesClientComposedLayersIfOthersAreNotOpaque) {
3476 EXPECT_CALL(mLayers[0].mOutputLayer, requiresClientComposition()).WillOnce(Return(false));
3477 EXPECT_CALL(mLayers[1].mOutputLayer, requiresClientComposition()).WillOnce(Return(false));
3478 EXPECT_CALL(mLayers[2].mOutputLayer, requiresClientComposition()).WillOnce(Return(true));
3479
3480 mLayers[0].mOutputLayerState.clearClientTarget = true;
3481 mLayers[1].mOutputLayerState.clearClientTarget = true;
3482 mLayers[2].mOutputLayerState.clearClientTarget = true;
3483
3484 mLayers[0].mLayerFEState.isOpaque = false;
3485 mLayers[1].mLayerFEState.isOpaque = false;
3486 mLayers[2].mLayerFEState.isOpaque = false;
3487
3488 EXPECT_CALL(mLayers[2].mLayerFE, prepareClientComposition(_))
Vishnu Nair9b079a22020-01-21 14:36:08 -08003489 .WillOnce(Return(mLayers[2].mLayerSettings));
Lloyd Piquea4863342019-12-04 18:45:02 -08003490 EXPECT_CALL(mLayers[2].mLayerFE, prepareShadowClientComposition(_, _, _))
3491 .WillOnce(Return(std::nullopt));
3492
3493 Region accumClearRegion(Rect(10, 11, 12, 13));
3494 auto requests = mOutput.generateClientCompositionRequests(false /* supportsProtectedContent */,
3495 accumClearRegion, kDisplayDataspace);
3496 ASSERT_EQ(1u, requests.size());
Vishnu Nair9b079a22020-01-21 14:36:08 -08003497 EXPECT_EQ(mLayers[2].mLayerSettings, requests[0]);
Lloyd Piquea4863342019-12-04 18:45:02 -08003498
3499 EXPECT_THAT(accumClearRegion, RegionEq(Region(Rect(10, 11, 12, 13))));
3500}
3501
3502TEST_F(GenerateClientCompositionRequestsTest_ThreeLayers, clearsHWCLayersIfOpaqueAndNotFirst) {
Lloyd Piquec2d54d42019-08-28 18:04:21 -07003503 // If client composition is performed with some layers set to use device
3504 // composition, device layers after the first layer (device or client) will
3505 // clear the frame buffer if they are opaque and if that layer has a flag
3506 // set to do so. The first layer is skipped as the frame buffer is already
3507 // expected to be clear.
3508
Lloyd Piquea4863342019-12-04 18:45:02 -08003509 EXPECT_CALL(mLayers[0].mOutputLayer, requiresClientComposition()).WillOnce(Return(false));
3510 EXPECT_CALL(mLayers[1].mOutputLayer, requiresClientComposition()).WillOnce(Return(false));
3511 EXPECT_CALL(mLayers[2].mOutputLayer, requiresClientComposition()).WillOnce(Return(true));
Lloyd Piquec2d54d42019-08-28 18:04:21 -07003512
Lloyd Piquea4863342019-12-04 18:45:02 -08003513 mLayers[0].mOutputLayerState.clearClientTarget = true;
3514 mLayers[1].mOutputLayerState.clearClientTarget = true;
3515 mLayers[2].mOutputLayerState.clearClientTarget = true;
Lloyd Piquec2d54d42019-08-28 18:04:21 -07003516
Lloyd Piquea4863342019-12-04 18:45:02 -08003517 mLayers[0].mLayerFEState.isOpaque = true;
3518 mLayers[1].mLayerFEState.isOpaque = true;
3519 mLayers[2].mLayerFEState.isOpaque = true;
Lloyd Piquec2d54d42019-08-28 18:04:21 -07003520
Lloyd Piquea4863342019-12-04 18:45:02 -08003521 EXPECT_CALL(mLayers[1].mLayerFE, prepareClientComposition(_))
Vishnu Nair9b079a22020-01-21 14:36:08 -08003522 .WillOnce(Return(mLayers[1].mLayerSettings));
Lloyd Piquea4863342019-12-04 18:45:02 -08003523 EXPECT_CALL(mLayers[2].mLayerFE, prepareClientComposition(_))
Vishnu Nair9b079a22020-01-21 14:36:08 -08003524 .WillOnce(Return(mLayers[2].mLayerSettings));
Lloyd Piquea4863342019-12-04 18:45:02 -08003525 EXPECT_CALL(mLayers[2].mLayerFE, prepareShadowClientComposition(_, _, _))
3526 .WillOnce(Return(std::nullopt));
Lloyd Piquec2d54d42019-08-28 18:04:21 -07003527
Lloyd Piquea4863342019-12-04 18:45:02 -08003528 Region accumClearRegion(Rect(10, 11, 12, 13));
3529 auto requests = mOutput.generateClientCompositionRequests(false /* supportsProtectedContent */,
3530 accumClearRegion, kDisplayDataspace);
3531 ASSERT_EQ(2u, requests.size());
Lloyd Piquec2d54d42019-08-28 18:04:21 -07003532
Lloyd Piquea4863342019-12-04 18:45:02 -08003533 // The second layer is expected to be rendered as alpha=0 black with no blending
Vishnu Nair9b079a22020-01-21 14:36:08 -08003534 EXPECT_EQ(mLayers[1].mLayerSettings.geometry.boundaries, requests[0].geometry.boundaries);
Lloyd Piquea4863342019-12-04 18:45:02 -08003535 EXPECT_FALSE(requests[0].source.buffer.buffer);
3536 EXPECT_EQ((half3{0.f, 0.f, 0.f}), requests[0].source.solidColor);
Lloyd Pique0a456232020-01-16 17:51:13 -08003537 EXPECT_EQ(0.f, static_cast<float>(requests[0].alpha));
Lloyd Piquea4863342019-12-04 18:45:02 -08003538 EXPECT_EQ(true, requests[0].disableBlending);
Lloyd Piquec2d54d42019-08-28 18:04:21 -07003539
Vishnu Nair9b079a22020-01-21 14:36:08 -08003540 EXPECT_EQ(mLayers[2].mLayerSettings, requests[1]);
Lloyd Piquec2d54d42019-08-28 18:04:21 -07003541
Lloyd Piquea4863342019-12-04 18:45:02 -08003542 EXPECT_THAT(accumClearRegion, RegionEq(Region(Rect(10, 11, 12, 13))));
3543}
Lloyd Piquec2d54d42019-08-28 18:04:21 -07003544
Lloyd Piquea4863342019-12-04 18:45:02 -08003545TEST_F(GenerateClientCompositionRequestsTest_ThreeLayers,
3546 clippedVisibleRegionUsedToGenerateRequest) {
3547 mLayers[0].mOutputLayerState.visibleRegion = Region(Rect(10, 10, 20, 20));
3548 mLayers[1].mOutputLayerState.visibleRegion = Region(Rect(-10, -10, 30, 30));
3549 mLayers[2].mOutputLayerState.visibleRegion = Region(Rect(-10, 0, 40, 4000));
Lloyd Piquec2d54d42019-08-28 18:04:21 -07003550
Lloyd Piquea4863342019-12-04 18:45:02 -08003551 Region accumClearRegion(Rect(10, 11, 12, 13));
3552
3553 compositionengine::LayerFE::ClientCompositionTargetSettings layer0TargetSettings{
3554 Region(Rect(10, 10, 20, 20)),
3555 false, /* identity transform */
3556 false, /* needs filtering */
3557 false, /* secure */
3558 false, /* supports protected content */
3559 accumClearRegion,
3560 };
3561 compositionengine::LayerFE::ClientCompositionTargetSettings layer1TargetSettings{
3562 Region(Rect(0, 0, 30, 30)),
3563 false, /* identity transform */
3564 false, /* needs filtering */
3565 false, /* secure */
3566 false, /* supports protected content */
3567 accumClearRegion,
3568 };
3569 compositionengine::LayerFE::ClientCompositionTargetSettings layer2TargetSettings{
3570 Region(Rect(0, 0, 40, 201)),
3571 false, /* identity transform */
3572 false, /* needs filtering */
3573 false, /* secure */
3574 false, /* supports protected content */
3575 accumClearRegion,
3576 };
3577
3578 EXPECT_CALL(mLayers[0].mLayerFE, prepareClientComposition(Eq(ByRef(layer0TargetSettings))))
3579 .WillOnce(Return(std::nullopt));
3580 EXPECT_CALL(mLayers[1].mLayerFE, prepareClientComposition(Eq(ByRef(layer1TargetSettings))))
3581 .WillOnce(Return(std::nullopt));
3582 EXPECT_CALL(mLayers[2].mLayerFE, prepareClientComposition(Eq(ByRef(layer2TargetSettings))))
3583 .WillOnce(Return(std::nullopt));
3584
3585 static_cast<void>(
3586 mOutput.generateClientCompositionRequests(false /* supportsProtectedContent */,
3587 accumClearRegion, kDisplayDataspace));
3588}
3589
3590TEST_F(GenerateClientCompositionRequestsTest_ThreeLayers,
3591 perLayerNeedsFilteringUsedToGenerateRequests) {
3592 mOutput.mState.needsFiltering = false;
3593 EXPECT_CALL(mLayers[0].mOutputLayer, needsFiltering()).WillRepeatedly(Return(true));
3594
3595 Region accumClearRegion(Rect(10, 11, 12, 13));
3596
3597 compositionengine::LayerFE::ClientCompositionTargetSettings layer0TargetSettings{
3598 Region(kDisplayFrame),
3599 false, /* identity transform */
3600 true, /* needs filtering */
3601 false, /* secure */
3602 false, /* supports protected content */
3603 accumClearRegion,
3604 };
3605 compositionengine::LayerFE::ClientCompositionTargetSettings layer1TargetSettings{
3606 Region(kDisplayFrame),
3607 false, /* identity transform */
3608 false, /* needs filtering */
3609 false, /* secure */
3610 false, /* supports protected content */
3611 accumClearRegion,
3612 };
3613 compositionengine::LayerFE::ClientCompositionTargetSettings layer2TargetSettings{
3614 Region(kDisplayFrame),
3615 false, /* identity transform */
3616 false, /* needs filtering */
3617 false, /* secure */
3618 false, /* supports protected content */
3619 accumClearRegion,
3620 };
3621
3622 EXPECT_CALL(mLayers[0].mLayerFE, prepareClientComposition(Eq(ByRef(layer0TargetSettings))))
3623 .WillOnce(Return(std::nullopt));
3624 EXPECT_CALL(mLayers[1].mLayerFE, prepareClientComposition(Eq(ByRef(layer1TargetSettings))))
3625 .WillOnce(Return(std::nullopt));
3626 EXPECT_CALL(mLayers[2].mLayerFE, prepareClientComposition(Eq(ByRef(layer2TargetSettings))))
3627 .WillOnce(Return(std::nullopt));
3628
3629 static_cast<void>(
3630 mOutput.generateClientCompositionRequests(false /* supportsProtectedContent */,
3631 accumClearRegion, kDisplayDataspace));
3632}
3633
3634TEST_F(GenerateClientCompositionRequestsTest_ThreeLayers,
3635 wholeOutputNeedsFilteringUsedToGenerateRequests) {
3636 mOutput.mState.needsFiltering = true;
3637 EXPECT_CALL(mLayers[0].mOutputLayer, needsFiltering()).WillRepeatedly(Return(true));
3638
3639 Region accumClearRegion(Rect(10, 11, 12, 13));
3640
3641 compositionengine::LayerFE::ClientCompositionTargetSettings layer0TargetSettings{
3642 Region(kDisplayFrame),
3643 false, /* identity transform */
3644 true, /* needs filtering */
3645 false, /* secure */
3646 false, /* supports protected content */
3647 accumClearRegion,
3648 };
3649 compositionengine::LayerFE::ClientCompositionTargetSettings layer1TargetSettings{
3650 Region(kDisplayFrame),
3651 false, /* identity transform */
3652 true, /* needs filtering */
3653 false, /* secure */
3654 false, /* supports protected content */
3655 accumClearRegion,
3656 };
3657 compositionengine::LayerFE::ClientCompositionTargetSettings layer2TargetSettings{
3658 Region(kDisplayFrame),
3659 false, /* identity transform */
3660 true, /* needs filtering */
3661 false, /* secure */
3662 false, /* supports protected content */
3663 accumClearRegion,
3664 };
3665
3666 EXPECT_CALL(mLayers[0].mLayerFE, prepareClientComposition(Eq(ByRef(layer0TargetSettings))))
3667 .WillOnce(Return(std::nullopt));
3668 EXPECT_CALL(mLayers[1].mLayerFE, prepareClientComposition(Eq(ByRef(layer1TargetSettings))))
3669 .WillOnce(Return(std::nullopt));
3670 EXPECT_CALL(mLayers[2].mLayerFE, prepareClientComposition(Eq(ByRef(layer2TargetSettings))))
3671 .WillOnce(Return(std::nullopt));
3672
3673 static_cast<void>(
3674 mOutput.generateClientCompositionRequests(false /* supportsProtectedContent */,
3675 accumClearRegion, kDisplayDataspace));
3676}
3677
3678TEST_F(GenerateClientCompositionRequestsTest_ThreeLayers,
3679 wholeOutputSecurityUsedToGenerateRequests) {
3680 mOutput.mState.isSecure = true;
3681
3682 Region accumClearRegion(Rect(10, 11, 12, 13));
3683
3684 compositionengine::LayerFE::ClientCompositionTargetSettings layer0TargetSettings{
3685 Region(kDisplayFrame),
3686 false, /* identity transform */
3687 false, /* needs filtering */
3688 true, /* secure */
3689 false, /* supports protected content */
3690 accumClearRegion,
3691 };
3692 compositionengine::LayerFE::ClientCompositionTargetSettings layer1TargetSettings{
3693 Region(kDisplayFrame),
3694 false, /* identity transform */
3695 false, /* needs filtering */
3696 true, /* secure */
3697 false, /* supports protected content */
3698 accumClearRegion,
3699 };
3700 compositionengine::LayerFE::ClientCompositionTargetSettings layer2TargetSettings{
3701 Region(kDisplayFrame),
3702 false, /* identity transform */
3703 false, /* needs filtering */
3704 true, /* secure */
3705 false, /* supports protected content */
3706 accumClearRegion,
3707 };
3708
3709 EXPECT_CALL(mLayers[0].mLayerFE, prepareClientComposition(Eq(ByRef(layer0TargetSettings))))
3710 .WillOnce(Return(std::nullopt));
3711 EXPECT_CALL(mLayers[1].mLayerFE, prepareClientComposition(Eq(ByRef(layer1TargetSettings))))
3712 .WillOnce(Return(std::nullopt));
3713 EXPECT_CALL(mLayers[2].mLayerFE, prepareClientComposition(Eq(ByRef(layer2TargetSettings))))
3714 .WillOnce(Return(std::nullopt));
3715
3716 static_cast<void>(
3717 mOutput.generateClientCompositionRequests(false /* supportsProtectedContent */,
3718 accumClearRegion, kDisplayDataspace));
3719}
3720
3721TEST_F(GenerateClientCompositionRequestsTest_ThreeLayers,
3722 protectedContentSupportUsedToGenerateRequests) {
3723 Region accumClearRegion(Rect(10, 11, 12, 13));
3724
3725 compositionengine::LayerFE::ClientCompositionTargetSettings layer0TargetSettings{
3726 Region(kDisplayFrame),
3727 false, /* identity transform */
3728 false, /* needs filtering */
3729 false, /* secure */
3730 true, /* supports protected content */
3731 accumClearRegion,
3732 };
3733 compositionengine::LayerFE::ClientCompositionTargetSettings layer1TargetSettings{
3734 Region(kDisplayFrame),
3735 false, /* identity transform */
3736 false, /* needs filtering */
3737 false, /* secure */
3738 true, /* supports protected content */
3739 accumClearRegion,
3740 };
3741 compositionengine::LayerFE::ClientCompositionTargetSettings layer2TargetSettings{
3742 Region(kDisplayFrame),
3743 false, /* identity transform */
3744 false, /* needs filtering */
3745 false, /* secure */
3746 true, /* supports protected content */
3747 accumClearRegion,
3748 };
3749
3750 EXPECT_CALL(mLayers[0].mLayerFE, prepareClientComposition(Eq(ByRef(layer0TargetSettings))))
3751 .WillOnce(Return(std::nullopt));
3752 EXPECT_CALL(mLayers[1].mLayerFE, prepareClientComposition(Eq(ByRef(layer1TargetSettings))))
3753 .WillOnce(Return(std::nullopt));
3754 EXPECT_CALL(mLayers[2].mLayerFE, prepareClientComposition(Eq(ByRef(layer2TargetSettings))))
3755 .WillOnce(Return(std::nullopt));
3756
3757 static_cast<void>(mOutput.generateClientCompositionRequests(true /* supportsProtectedContent */,
3758 accumClearRegion,
3759 kDisplayDataspace));
3760}
3761
Lucas Dupin19c8f0e2019-11-25 17:55:44 -08003762TEST_F(OutputUpdateAndWriteCompositionStateTest, handlesBackgroundBlurRequests) {
3763 // Layer requesting blur, or below, should request client composition.
3764 EXPECT_CALL(*mOutputLayer1, updateCompositionState(false, true));
3765 EXPECT_CALL(*mOutputLayer1, writeStateToHWC(false));
3766 EXPECT_CALL(*mOutputLayer2, updateCompositionState(false, true));
3767 EXPECT_CALL(*mOutputLayer2, writeStateToHWC(false));
3768 EXPECT_CALL(*mOutputLayer3, updateCompositionState(false, false));
3769 EXPECT_CALL(*mOutputLayer3, writeStateToHWC(false));
3770
3771 mLayer2FEState.backgroundBlurRadius = 10;
3772
3773 injectLayer(std::move(mOutputLayer1));
3774 injectLayer(std::move(mOutputLayer2));
3775 injectLayer(std::move(mOutputLayer3));
3776
3777 mOutput->editState().isEnabled = true;
3778
3779 CompositionRefreshArgs args;
3780 args.updatingGeometryThisFrame = false;
3781 args.devOptForceClientComposition = false;
3782 mOutput->updateAndWriteCompositionState(args);
3783}
3784
Lloyd Piquea4863342019-12-04 18:45:02 -08003785TEST_F(GenerateClientCompositionRequestsTest, handlesLandscapeModeSplitScreenRequests) {
3786 // In split-screen landscape mode, the screen is rotated 90 degrees, with
3787 // one layer on the left covering the left side of the output, and one layer
3788 // on the right covering that side of the output.
Lloyd Piquec2d54d42019-08-28 18:04:21 -07003789
3790 const Rect kPortraitFrame(0, 0, 1000, 2000);
3791 const Rect kPortraitViewport(0, 0, 2000, 1000);
3792 const Rect kPortraitScissor(0, 0, 1000, 2000);
3793 const uint32_t kPortraitOrientation = TR_ROT_90;
Lloyd Piquea4863342019-12-04 18:45:02 -08003794 constexpr ui::Dataspace kOutputDataspace = ui::Dataspace::DISPLAY_P3;
Lloyd Piquec2d54d42019-08-28 18:04:21 -07003795
Lloyd Piquea4863342019-12-04 18:45:02 -08003796 mOutput.mState.frame = kPortraitFrame;
3797 mOutput.mState.viewport = kPortraitViewport;
3798 mOutput.mState.scissor = kPortraitScissor;
3799 mOutput.mState.transform = ui::Transform{kPortraitOrientation};
3800 mOutput.mState.orientation = kPortraitOrientation;
3801 mOutput.mState.needsFiltering = false;
3802 mOutput.mState.isSecure = true;
Lloyd Piquec2d54d42019-08-28 18:04:21 -07003803
Lloyd Piquea4863342019-12-04 18:45:02 -08003804 Layer leftLayer;
3805 Layer rightLayer;
Lloyd Piquec2d54d42019-08-28 18:04:21 -07003806
Lloyd Piquea4863342019-12-04 18:45:02 -08003807 leftLayer.mOutputLayerState.clearClientTarget = false;
3808 leftLayer.mOutputLayerState.visibleRegion = Region(Rect(0, 0, 1000, 1000));
3809 leftLayer.mLayerFEState.isOpaque = true;
Vishnu Nair9b079a22020-01-21 14:36:08 -08003810 leftLayer.mLayerSettings.source.solidColor = {1.f, 0.f, 0.f};
Lloyd Piquec2d54d42019-08-28 18:04:21 -07003811
Lloyd Piquea4863342019-12-04 18:45:02 -08003812 rightLayer.mOutputLayerState.clearClientTarget = false;
3813 rightLayer.mOutputLayerState.visibleRegion = Region(Rect(1000, 0, 2000, 1000));
3814 rightLayer.mLayerFEState.isOpaque = true;
Vishnu Nair9b079a22020-01-21 14:36:08 -08003815 rightLayer.mLayerSettings.source.solidColor = {0.f, 1.f, 0.f};
Lloyd Piquea4863342019-12-04 18:45:02 -08003816
3817 EXPECT_CALL(mOutput, getOutputLayerCount()).WillRepeatedly(Return(2u));
3818 EXPECT_CALL(mOutput, getOutputLayerOrderedByZByIndex(0u))
3819 .WillRepeatedly(Return(&leftLayer.mOutputLayer));
3820 EXPECT_CALL(mOutput, getOutputLayerOrderedByZByIndex(1u))
3821 .WillRepeatedly(Return(&rightLayer.mOutputLayer));
3822
3823 Region accumClearRegion(Rect(10, 11, 12, 13));
3824
3825 compositionengine::LayerFE::ClientCompositionTargetSettings leftLayerSettings{
3826 Region(Rect(0, 0, 1000, 1000)),
3827 false, /* identity transform */
3828 false, /* needs filtering */
3829 true, /* secure */
3830 true, /* supports protected content */
3831 accumClearRegion,
3832 };
3833
3834 EXPECT_CALL(leftLayer.mOutputLayer, requiresClientComposition()).WillRepeatedly(Return(true));
3835 EXPECT_CALL(leftLayer.mOutputLayer, needsFiltering()).WillRepeatedly(Return(false));
3836 EXPECT_CALL(leftLayer.mLayerFE, prepareClientComposition(Eq(ByRef(leftLayerSettings))))
Vishnu Nair9b079a22020-01-21 14:36:08 -08003837 .WillOnce(Return(leftLayer.mLayerSettings));
Lloyd Piquea4863342019-12-04 18:45:02 -08003838 EXPECT_CALL(leftLayer.mLayerFE,
Vishnu Nair9b079a22020-01-21 14:36:08 -08003839 prepareShadowClientComposition(leftLayer.mLayerSettings, kPortraitViewport,
Lloyd Piquea4863342019-12-04 18:45:02 -08003840 kOutputDataspace))
3841 .WillOnce(Return(std::nullopt));
3842
3843 compositionengine::LayerFE::ClientCompositionTargetSettings rightLayerSettings{
3844 Region(Rect(1000, 0, 2000, 1000)),
3845 false, /* identity transform */
3846 false, /* needs filtering */
3847 true, /* secure */
3848 true, /* supports protected content */
3849 accumClearRegion,
3850 };
3851
3852 EXPECT_CALL(rightLayer.mOutputLayer, requiresClientComposition()).WillRepeatedly(Return(true));
3853 EXPECT_CALL(rightLayer.mOutputLayer, needsFiltering()).WillRepeatedly(Return(false));
3854 EXPECT_CALL(rightLayer.mLayerFE, prepareClientComposition(Eq(ByRef(rightLayerSettings))))
Vishnu Nair9b079a22020-01-21 14:36:08 -08003855 .WillOnce(Return(rightLayer.mLayerSettings));
Lloyd Piquea4863342019-12-04 18:45:02 -08003856 EXPECT_CALL(rightLayer.mLayerFE,
Vishnu Nair9b079a22020-01-21 14:36:08 -08003857 prepareShadowClientComposition(rightLayer.mLayerSettings, kPortraitViewport,
Lloyd Piquea4863342019-12-04 18:45:02 -08003858 kOutputDataspace))
3859 .WillOnce(Return(std::nullopt));
3860
3861 constexpr bool supportsProtectedContent = true;
3862 auto requests = mOutput.generateClientCompositionRequests(supportsProtectedContent,
3863 accumClearRegion, kOutputDataspace);
3864 ASSERT_EQ(2u, requests.size());
Vishnu Nair9b079a22020-01-21 14:36:08 -08003865 EXPECT_EQ(leftLayer.mLayerSettings, requests[0]);
3866 EXPECT_EQ(rightLayer.mLayerSettings, requests[1]);
Lloyd Piquec2d54d42019-08-28 18:04:21 -07003867}
3868
Vishnu Naira483b4a2019-12-12 15:07:52 -08003869TEST_F(GenerateClientCompositionRequestsTest_ThreeLayers,
3870 shadowRegionOnlyVisibleSkipsContentComposition) {
3871 const Rect kContentWithShadow(40, 40, 70, 90);
3872 const Rect kContent(50, 50, 60, 80);
3873 const Region kShadowRegion = Region(kContentWithShadow).subtract(kContent);
3874 const Region kPartialShadowRegion = Region(kContentWithShadow).subtract(Rect(40, 40, 60, 80));
3875
Vishnu Nair9b079a22020-01-21 14:36:08 -08003876 LayerFE::LayerSettings mShadowSettings;
3877 mShadowSettings.source.solidColor = {0.1f, 0.1f, 0.1f};
Vishnu Naira483b4a2019-12-12 15:07:52 -08003878
3879 mLayers[2].mOutputLayerState.visibleRegion = kPartialShadowRegion;
3880 mLayers[2].mOutputLayerState.shadowRegion = kShadowRegion;
3881
3882 EXPECT_CALL(mLayers[0].mOutputLayer, requiresClientComposition()).WillOnce(Return(false));
3883 EXPECT_CALL(mLayers[1].mOutputLayer, requiresClientComposition()).WillOnce(Return(false));
3884 EXPECT_CALL(mLayers[2].mLayerFE, prepareClientComposition(_))
Vishnu Nair9b079a22020-01-21 14:36:08 -08003885 .WillOnce(Return(mLayers[2].mLayerSettings));
Vishnu Naira483b4a2019-12-12 15:07:52 -08003886 EXPECT_CALL(mLayers[2].mLayerFE,
Vishnu Nair9b079a22020-01-21 14:36:08 -08003887 prepareShadowClientComposition(mLayers[2].mLayerSettings, kDisplayViewport,
Vishnu Naira483b4a2019-12-12 15:07:52 -08003888 kDisplayDataspace))
Vishnu Nair9b079a22020-01-21 14:36:08 -08003889 .WillOnce(Return(mShadowSettings));
Vishnu Naira483b4a2019-12-12 15:07:52 -08003890
3891 Region accumClearRegion(Rect(10, 11, 12, 13));
3892 auto requests = mOutput.generateClientCompositionRequests(false /* supportsProtectedContent */,
3893 accumClearRegion, kDisplayDataspace);
3894 ASSERT_EQ(1u, requests.size());
3895
Vishnu Nair9b079a22020-01-21 14:36:08 -08003896 EXPECT_EQ(mShadowSettings, requests[0]);
Vishnu Naira483b4a2019-12-12 15:07:52 -08003897}
3898
3899TEST_F(GenerateClientCompositionRequestsTest_ThreeLayers,
3900 shadowRegionWithContentVisibleRequestsContentAndShadowComposition) {
3901 const Rect kContentWithShadow(40, 40, 70, 90);
3902 const Rect kContent(50, 50, 60, 80);
3903 const Region kShadowRegion = Region(kContentWithShadow).subtract(kContent);
3904 const Region kPartialContentWithPartialShadowRegion =
3905 Region(kContentWithShadow).subtract(Rect(40, 40, 50, 80));
3906
Vishnu Nair9b079a22020-01-21 14:36:08 -08003907 LayerFE::LayerSettings mShadowSettings;
3908 mShadowSettings.source.solidColor = {0.1f, 0.1f, 0.1f};
Vishnu Naira483b4a2019-12-12 15:07:52 -08003909
3910 mLayers[2].mOutputLayerState.visibleRegion = kPartialContentWithPartialShadowRegion;
3911 mLayers[2].mOutputLayerState.shadowRegion = kShadowRegion;
3912
3913 EXPECT_CALL(mLayers[0].mOutputLayer, requiresClientComposition()).WillOnce(Return(false));
3914 EXPECT_CALL(mLayers[1].mOutputLayer, requiresClientComposition()).WillOnce(Return(false));
3915 EXPECT_CALL(mLayers[2].mLayerFE, prepareClientComposition(_))
Vishnu Nair9b079a22020-01-21 14:36:08 -08003916 .WillOnce(Return(mLayers[2].mLayerSettings));
Vishnu Naira483b4a2019-12-12 15:07:52 -08003917 EXPECT_CALL(mLayers[2].mLayerFE,
Vishnu Nair9b079a22020-01-21 14:36:08 -08003918 prepareShadowClientComposition(mLayers[2].mLayerSettings, kDisplayViewport,
Vishnu Naira483b4a2019-12-12 15:07:52 -08003919 kDisplayDataspace))
Vishnu Nair9b079a22020-01-21 14:36:08 -08003920 .WillOnce(Return(mShadowSettings));
Vishnu Naira483b4a2019-12-12 15:07:52 -08003921
3922 Region accumClearRegion(Rect(10, 11, 12, 13));
3923 auto requests = mOutput.generateClientCompositionRequests(false /* supportsProtectedContent */,
3924 accumClearRegion, kDisplayDataspace);
3925 ASSERT_EQ(2u, requests.size());
3926
Vishnu Nair9b079a22020-01-21 14:36:08 -08003927 EXPECT_EQ(mShadowSettings, requests[0]);
3928 EXPECT_EQ(mLayers[2].mLayerSettings, requests[1]);
Vishnu Naira483b4a2019-12-12 15:07:52 -08003929}
3930
Lloyd Pique32cbe282018-10-19 13:09:22 -07003931} // namespace
3932} // namespace android::compositionengine