blob: 9a2889e2fd51b090823a593b91a1e8063df002d1 [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
Ady Abrahamb0dbdaa2020-01-06 16:19:42 -080017// TODO(b/129481165): remove the #pragma below and fix conversion issues
18#pragma clang diagnostic push
19#pragma clang diagnostic ignored "-Wconversion"
20
Lloyd Pique32cbe282018-10-19 13:09:22 -070021#include <cmath>
22
Lloyd Pique17ca7422019-11-14 14:24:10 -080023#include <android-base/stringprintf.h>
Lloyd Pique9755fb72019-03-26 14:44:40 -070024#include <compositionengine/LayerFECompositionState.h>
Lloyd Pique32cbe282018-10-19 13:09:22 -070025#include <compositionengine/impl/Output.h>
Lloyd Pique66d68602019-02-13 14:23:31 -080026#include <compositionengine/impl/OutputCompositionState.h>
Lloyd Pique56eba802019-08-28 15:45:25 -070027#include <compositionengine/impl/OutputLayerCompositionState.h>
Lloyd Pique32cbe282018-10-19 13:09:22 -070028#include <compositionengine/mock/CompositionEngine.h>
Lloyd Pique3d0c02e2018-10-19 18:38:12 -070029#include <compositionengine/mock/DisplayColorProfile.h>
Lloyd Piquecc01a452018-12-04 17:24:00 -080030#include <compositionengine/mock/Layer.h>
31#include <compositionengine/mock/LayerFE.h>
32#include <compositionengine/mock/OutputLayer.h>
Lloyd Pique31cb2942018-10-19 17:23:03 -070033#include <compositionengine/mock/RenderSurface.h>
Lloyd Pique32cbe282018-10-19 13:09:22 -070034#include <gtest/gtest.h>
Lloyd Pique56eba802019-08-28 15:45:25 -070035#include <renderengine/mock/RenderEngine.h>
Lloyd Pique32cbe282018-10-19 13:09:22 -070036#include <ui/Rect.h>
37#include <ui/Region.h>
38
Lloyd Pique17ca7422019-11-14 14:24:10 -080039#include "CallOrderStateMachineHelper.h"
Lloyd Pique07178e32019-11-19 19:15:26 -080040#include "MockHWC2.h"
Lloyd Pique32cbe282018-10-19 13:09:22 -070041#include "RegionMatcher.h"
Lloyd Pique32cbe282018-10-19 13:09:22 -070042
43namespace android::compositionengine {
44namespace {
45
Lloyd Pique56eba802019-08-28 15:45:25 -070046using testing::_;
Lloyd Pique03561a62019-11-19 18:34:52 -080047using testing::ByMove;
Lloyd Piquea4863342019-12-04 18:45:02 -080048using testing::ByRef;
Lloyd Pique17ca7422019-11-14 14:24:10 -080049using testing::DoAll;
Vishnu Nair9b079a22020-01-21 14:36:08 -080050using testing::ElementsAre;
Lloyd Pique6818fa52019-12-03 12:32:13 -080051using testing::ElementsAreArray;
Lloyd Pique07178e32019-11-19 19:15:26 -080052using testing::Eq;
Lloyd Piquefaa3f192019-11-14 14:05:09 -080053using testing::InSequence;
Lloyd Pique6818fa52019-12-03 12:32:13 -080054using testing::Invoke;
55using testing::IsEmpty;
Lloyd Pique17ca7422019-11-14 14:24:10 -080056using testing::Mock;
Vishnu Nair9b079a22020-01-21 14:36:08 -080057using testing::Pointee;
Lloyd Pique07178e32019-11-19 19:15:26 -080058using testing::Property;
Lloyd Piquefaa3f192019-11-14 14:05:09 -080059using testing::Ref;
Lloyd Pique31cb2942018-10-19 17:23:03 -070060using testing::Return;
Lloyd Pique32cbe282018-10-19 13:09:22 -070061using testing::ReturnRef;
Lloyd Pique17ca7422019-11-14 14:24:10 -080062using testing::SetArgPointee;
Lloyd Pique32cbe282018-10-19 13:09:22 -070063using testing::StrictMock;
64
Lloyd Pique56eba802019-08-28 15:45:25 -070065constexpr auto TR_IDENT = 0u;
66constexpr auto TR_ROT_90 = HAL_TRANSFORM_ROT_90;
Vishnu Nair9b079a22020-01-21 14:36:08 -080067constexpr auto MAX_CLIENT_COMPOSITION_CACHE_SIZE = 3;
Lloyd Pique56eba802019-08-28 15:45:25 -070068
Lloyd Pique3eb1b212019-03-07 21:15:40 -080069const mat4 kIdentity;
Lloyd Pique0a456232020-01-16 17:51:13 -080070const mat4 kNonIdentityHalf = mat4() * 0.5f;
71const mat4 kNonIdentityQuarter = mat4() * 0.25f;
Lloyd Pique3eb1b212019-03-07 21:15:40 -080072
Lloyd Pique17ca7422019-11-14 14:24:10 -080073constexpr OutputColorSetting kVendorSpecifiedOutputColorSetting =
74 static_cast<OutputColorSetting>(0x100);
75
Lloyd Piquefaa3f192019-11-14 14:05:09 -080076struct OutputPartialMockBase : public impl::Output {
77 // compositionengine::Output overrides
78 const OutputCompositionState& getState() const override { return mState; }
79 OutputCompositionState& editState() override { return mState; }
80
81 // Use mocks for all the remaining virtual functions
82 // not implemented by the base implementation class.
83 MOCK_CONST_METHOD0(getOutputLayerCount, size_t());
84 MOCK_CONST_METHOD1(getOutputLayerOrderedByZByIndex, compositionengine::OutputLayer*(size_t));
85 MOCK_METHOD3(ensureOutputLayer,
86 compositionengine::OutputLayer*(std::optional<size_t>,
87 const std::shared_ptr<compositionengine::Layer>&,
88 const sp<LayerFE>&));
89 MOCK_METHOD0(finalizePendingOutputLayers, void());
90 MOCK_METHOD0(clearOutputLayers, void());
91 MOCK_CONST_METHOD1(dumpState, void(std::string&));
92 MOCK_CONST_METHOD0(getCompositionEngine, const CompositionEngine&());
93 MOCK_METHOD2(injectOutputLayerForTest,
94 compositionengine::OutputLayer*(const std::shared_ptr<compositionengine::Layer>&,
95 const sp<LayerFE>&));
96 MOCK_METHOD1(injectOutputLayerForTest, void(std::unique_ptr<OutputLayer>));
97
98 impl::OutputCompositionState mState;
99};
100
Lloyd Pique66d68602019-02-13 14:23:31 -0800101struct OutputTest : public testing::Test {
Lloyd Pique01c77c12019-04-17 12:48:32 -0700102 class Output : public impl::Output {
103 public:
104 using impl::Output::injectOutputLayerForTest;
105 virtual void injectOutputLayerForTest(std::unique_ptr<compositionengine::OutputLayer>) = 0;
106 };
107
108 static std::shared_ptr<Output> createOutput(
109 const compositionengine::CompositionEngine& compositionEngine) {
110 return impl::createOutputTemplated<Output>(compositionEngine);
111 }
112
Lloyd Pique31cb2942018-10-19 17:23:03 -0700113 OutputTest() {
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700114 mOutput->setDisplayColorProfileForTest(
Lloyd Pique3d0c02e2018-10-19 18:38:12 -0700115 std::unique_ptr<DisplayColorProfile>(mDisplayColorProfile));
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700116 mOutput->setRenderSurfaceForTest(std::unique_ptr<RenderSurface>(mRenderSurface));
Lloyd Piqueef958122019-02-05 18:00:12 -0800117
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700118 mOutput->editState().bounds = kDefaultDisplaySize;
Lloyd Pique31cb2942018-10-19 17:23:03 -0700119 }
Lloyd Pique32cbe282018-10-19 13:09:22 -0700120
Lloyd Piqueef958122019-02-05 18:00:12 -0800121 static const Rect kDefaultDisplaySize;
122
Lloyd Pique32cbe282018-10-19 13:09:22 -0700123 StrictMock<mock::CompositionEngine> mCompositionEngine;
Lloyd Pique3d0c02e2018-10-19 18:38:12 -0700124 mock::DisplayColorProfile* mDisplayColorProfile = new StrictMock<mock::DisplayColorProfile>();
Lloyd Pique31cb2942018-10-19 17:23:03 -0700125 mock::RenderSurface* mRenderSurface = new StrictMock<mock::RenderSurface>();
Lloyd Pique01c77c12019-04-17 12:48:32 -0700126 std::shared_ptr<Output> mOutput = createOutput(mCompositionEngine);
Lloyd Pique32cbe282018-10-19 13:09:22 -0700127};
128
Lloyd Piquec0ee6ba2019-11-14 12:55:53 -0800129// Extension of the base test useful for checking interactions with the LayerFE
130// functions to latch composition state.
131struct OutputLatchFEStateTest : public OutputTest {
132 OutputLatchFEStateTest() {
133 EXPECT_CALL(*mOutputLayer1, getLayer()).WillRepeatedly(ReturnRef(mLayer1));
134 EXPECT_CALL(*mOutputLayer2, getLayer()).WillRepeatedly(ReturnRef(mLayer2));
135 EXPECT_CALL(*mOutputLayer3, getLayer()).WillRepeatedly(ReturnRef(mLayer3));
136
137 EXPECT_CALL(*mOutputLayer1, getLayerFE()).WillRepeatedly(ReturnRef(mLayer1FE));
138 EXPECT_CALL(*mOutputLayer2, getLayerFE()).WillRepeatedly(ReturnRef(mLayer2FE));
139 EXPECT_CALL(*mOutputLayer3, getLayerFE()).WillRepeatedly(ReturnRef(mLayer3FE));
140
141 EXPECT_CALL(mLayer1, editFEState()).WillRepeatedly(ReturnRef(mLayer1FEState));
142 EXPECT_CALL(mLayer2, editFEState()).WillRepeatedly(ReturnRef(mLayer2FEState));
143 EXPECT_CALL(mLayer3, editFEState()).WillRepeatedly(ReturnRef(mLayer3FEState));
Lucas Dupin19c8f0e2019-11-25 17:55:44 -0800144
145 EXPECT_CALL(mLayer1, getFEState()).WillRepeatedly(ReturnRef(mLayer1FEState));
146 EXPECT_CALL(mLayer2, getFEState()).WillRepeatedly(ReturnRef(mLayer2FEState));
147 EXPECT_CALL(mLayer3, getFEState()).WillRepeatedly(ReturnRef(mLayer3FEState));
Lloyd Piquec0ee6ba2019-11-14 12:55:53 -0800148 }
149
150 void injectLayer(std::unique_ptr<mock::OutputLayer> layer) {
151 mOutput->injectOutputLayerForTest(std::unique_ptr<OutputLayer>(layer.release()));
152 }
153
154 std::unique_ptr<mock::OutputLayer> mOutputLayer1{new StrictMock<mock::OutputLayer>};
155 std::unique_ptr<mock::OutputLayer> mOutputLayer2{new StrictMock<mock::OutputLayer>};
156 std::unique_ptr<mock::OutputLayer> mOutputLayer3{new StrictMock<mock::OutputLayer>};
157
158 StrictMock<mock::Layer> mLayer1;
159 StrictMock<mock::Layer> mLayer2;
160 StrictMock<mock::Layer> mLayer3;
161
162 StrictMock<mock::LayerFE> mLayer1FE;
163 StrictMock<mock::LayerFE> mLayer2FE;
164 StrictMock<mock::LayerFE> mLayer3FE;
165
166 LayerFECompositionState mLayer1FEState;
167 LayerFECompositionState mLayer2FEState;
168 LayerFECompositionState mLayer3FEState;
169};
170
Lloyd Piqueef958122019-02-05 18:00:12 -0800171const Rect OutputTest::kDefaultDisplaySize{100, 200};
172
Lloyd Pique17ca7422019-11-14 14:24:10 -0800173using ColorProfile = compositionengine::Output::ColorProfile;
174
175void dumpColorProfile(ColorProfile profile, std::string& result, const char* name) {
176 android::base::StringAppendF(&result, "%s (%s[%d] %s[%d] %s[%d] %s[%d]) ", name,
177 toString(profile.mode).c_str(), profile.mode,
178 toString(profile.dataspace).c_str(), profile.dataspace,
179 toString(profile.renderIntent).c_str(), profile.renderIntent,
180 toString(profile.colorSpaceAgnosticDataspace).c_str(),
181 profile.colorSpaceAgnosticDataspace);
182}
183
184// Checks for a ColorProfile match
185MATCHER_P(ColorProfileEq, expected, "") {
186 std::string buf;
187 buf.append("ColorProfiles are not equal\n");
188 dumpColorProfile(expected, buf, "expected value");
189 dumpColorProfile(arg, buf, "actual value");
190 *result_listener << buf;
191
192 return (expected.mode == arg.mode) && (expected.dataspace == arg.dataspace) &&
193 (expected.renderIntent == arg.renderIntent) &&
194 (expected.colorSpaceAgnosticDataspace == arg.colorSpaceAgnosticDataspace);
195}
196
Lloyd Pique66d68602019-02-13 14:23:31 -0800197/*
Lloyd Pique32cbe282018-10-19 13:09:22 -0700198 * Basic construction
199 */
200
Lloyd Pique31cb2942018-10-19 17:23:03 -0700201TEST_F(OutputTest, canInstantiateOutput) {
202 // The validation check checks each required component.
Lloyd Pique3d0c02e2018-10-19 18:38:12 -0700203 EXPECT_CALL(*mDisplayColorProfile, isValid()).WillOnce(Return(true));
Lloyd Pique31cb2942018-10-19 17:23:03 -0700204 EXPECT_CALL(*mRenderSurface, isValid()).WillOnce(Return(true));
205
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700206 EXPECT_TRUE(mOutput->isValid());
Lloyd Pique31cb2942018-10-19 17:23:03 -0700207
208 // If we take away the required components, it is no longer valid.
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700209 mOutput->setRenderSurfaceForTest(std::unique_ptr<RenderSurface>());
Lloyd Pique31cb2942018-10-19 17:23:03 -0700210
Lloyd Pique3d0c02e2018-10-19 18:38:12 -0700211 EXPECT_CALL(*mDisplayColorProfile, isValid()).WillOnce(Return(true));
212
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700213 EXPECT_FALSE(mOutput->isValid());
Lloyd Pique31cb2942018-10-19 17:23:03 -0700214}
Lloyd Pique32cbe282018-10-19 13:09:22 -0700215
Lloyd Pique66d68602019-02-13 14:23:31 -0800216/*
Lloyd Pique32cbe282018-10-19 13:09:22 -0700217 * Output::setCompositionEnabled()
218 */
219
220TEST_F(OutputTest, setCompositionEnabledDoesNothingIfAlreadyEnabled) {
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700221 mOutput->editState().isEnabled = true;
Lloyd Pique32cbe282018-10-19 13:09:22 -0700222
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700223 mOutput->setCompositionEnabled(true);
Lloyd Pique32cbe282018-10-19 13:09:22 -0700224
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700225 EXPECT_TRUE(mOutput->getState().isEnabled);
226 EXPECT_THAT(mOutput->getState().dirtyRegion, RegionEq(Region()));
Lloyd Pique32cbe282018-10-19 13:09:22 -0700227}
228
229TEST_F(OutputTest, setCompositionEnabledSetsEnabledAndDirtiesEntireOutput) {
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700230 mOutput->editState().isEnabled = false;
Lloyd Pique32cbe282018-10-19 13:09:22 -0700231
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700232 mOutput->setCompositionEnabled(true);
Lloyd Pique32cbe282018-10-19 13:09:22 -0700233
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700234 EXPECT_TRUE(mOutput->getState().isEnabled);
235 EXPECT_THAT(mOutput->getState().dirtyRegion, RegionEq(Region(kDefaultDisplaySize)));
Lloyd Pique32cbe282018-10-19 13:09:22 -0700236}
237
238TEST_F(OutputTest, setCompositionEnabledSetsDisabledAndDirtiesEntireOutput) {
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700239 mOutput->editState().isEnabled = true;
Lloyd Pique32cbe282018-10-19 13:09:22 -0700240
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700241 mOutput->setCompositionEnabled(false);
Lloyd Pique32cbe282018-10-19 13:09:22 -0700242
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700243 EXPECT_FALSE(mOutput->getState().isEnabled);
244 EXPECT_THAT(mOutput->getState().dirtyRegion, RegionEq(Region(kDefaultDisplaySize)));
Lloyd Pique32cbe282018-10-19 13:09:22 -0700245}
246
Lloyd Pique66d68602019-02-13 14:23:31 -0800247/*
Lloyd Pique32cbe282018-10-19 13:09:22 -0700248 * Output::setProjection()
249 */
250
251TEST_F(OutputTest, setProjectionTriviallyWorks) {
252 const ui::Transform transform{ui::Transform::ROT_180};
253 const int32_t orientation = 123;
254 const Rect frame{1, 2, 3, 4};
255 const Rect viewport{5, 6, 7, 8};
256 const Rect scissor{9, 10, 11, 12};
257 const bool needsFiltering = true;
258
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700259 mOutput->setProjection(transform, orientation, frame, viewport, scissor, needsFiltering);
Lloyd Pique32cbe282018-10-19 13:09:22 -0700260
Lloyd Piqueea629282019-12-03 15:57:10 -0800261 EXPECT_THAT(mOutput->getState().transform, transform);
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700262 EXPECT_EQ(orientation, mOutput->getState().orientation);
263 EXPECT_EQ(frame, mOutput->getState().frame);
264 EXPECT_EQ(viewport, mOutput->getState().viewport);
265 EXPECT_EQ(scissor, mOutput->getState().scissor);
266 EXPECT_EQ(needsFiltering, mOutput->getState().needsFiltering);
Lloyd Pique32cbe282018-10-19 13:09:22 -0700267}
268
Lloyd Pique66d68602019-02-13 14:23:31 -0800269/*
Lloyd Pique32cbe282018-10-19 13:09:22 -0700270 * Output::setBounds()
271 */
272
273TEST_F(OutputTest, setBoundsSetsSizeAndDirtiesEntireOutput) {
Lloyd Piqueef958122019-02-05 18:00:12 -0800274 const ui::Size displaySize{200, 400};
Lloyd Pique31cb2942018-10-19 17:23:03 -0700275
276 EXPECT_CALL(*mRenderSurface, setDisplaySize(displaySize)).Times(1);
277 EXPECT_CALL(*mRenderSurface, getSize()).WillOnce(ReturnRef(displaySize));
278
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700279 mOutput->setBounds(displaySize);
Lloyd Pique32cbe282018-10-19 13:09:22 -0700280
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700281 EXPECT_EQ(Rect(displaySize), mOutput->getState().bounds);
Lloyd Pique32cbe282018-10-19 13:09:22 -0700282
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700283 EXPECT_THAT(mOutput->getState().dirtyRegion, RegionEq(Region(Rect(displaySize))));
Lloyd Pique32cbe282018-10-19 13:09:22 -0700284}
285
Lloyd Pique66d68602019-02-13 14:23:31 -0800286/*
Lloyd Pique32cbe282018-10-19 13:09:22 -0700287 * Output::setLayerStackFilter()
288 */
289
290TEST_F(OutputTest, setLayerStackFilterSetsFilterAndDirtiesEntireOutput) {
Lloyd Pique32cbe282018-10-19 13:09:22 -0700291 const uint32_t layerStack = 123u;
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700292 mOutput->setLayerStackFilter(layerStack, true);
Lloyd Pique32cbe282018-10-19 13:09:22 -0700293
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700294 EXPECT_TRUE(mOutput->getState().layerStackInternal);
295 EXPECT_EQ(layerStack, mOutput->getState().layerStackId);
Lloyd Pique32cbe282018-10-19 13:09:22 -0700296
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700297 EXPECT_THAT(mOutput->getState().dirtyRegion, RegionEq(Region(kDefaultDisplaySize)));
Lloyd Pique32cbe282018-10-19 13:09:22 -0700298}
299
Lloyd Pique66d68602019-02-13 14:23:31 -0800300/*
Lloyd Pique32cbe282018-10-19 13:09:22 -0700301 * Output::setColorTransform
302 */
303
Lloyd Pique3eb1b212019-03-07 21:15:40 -0800304TEST_F(OutputTest, setColorTransformWithNoChangeFlaggedSkipsUpdates) {
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700305 mOutput->editState().colorTransformMatrix = kIdentity;
Lloyd Pique32cbe282018-10-19 13:09:22 -0700306
Lloyd Pique3eb1b212019-03-07 21:15:40 -0800307 // If no colorTransformMatrix is set the update should be skipped.
308 CompositionRefreshArgs refreshArgs;
309 refreshArgs.colorTransformMatrix = std::nullopt;
Lloyd Pique32cbe282018-10-19 13:09:22 -0700310
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700311 mOutput->setColorTransform(refreshArgs);
Lloyd Pique32cbe282018-10-19 13:09:22 -0700312
Lloyd Pique3eb1b212019-03-07 21:15:40 -0800313 // The internal state should be unchanged
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700314 EXPECT_EQ(kIdentity, mOutput->getState().colorTransformMatrix);
Lloyd Pique3eb1b212019-03-07 21:15:40 -0800315
316 // No dirty region should be set
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700317 EXPECT_THAT(mOutput->getState().dirtyRegion, RegionEq(Region()));
Lloyd Pique3eb1b212019-03-07 21:15:40 -0800318}
Lloyd Piqueef958122019-02-05 18:00:12 -0800319
Lloyd Pique3eb1b212019-03-07 21:15:40 -0800320TEST_F(OutputTest, setColorTransformWithNoActualChangeSkipsUpdates) {
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700321 mOutput->editState().colorTransformMatrix = kIdentity;
Lloyd Pique32cbe282018-10-19 13:09:22 -0700322
Lloyd Pique3eb1b212019-03-07 21:15:40 -0800323 // Attempting to set the same colorTransformMatrix that is already set should
324 // also skip the update.
325 CompositionRefreshArgs refreshArgs;
326 refreshArgs.colorTransformMatrix = kIdentity;
Lloyd Pique32cbe282018-10-19 13:09:22 -0700327
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700328 mOutput->setColorTransform(refreshArgs);
Lloyd Pique77f79a22019-04-29 15:55:40 -0700329
Lloyd Pique3eb1b212019-03-07 21:15:40 -0800330 // The internal state should be unchanged
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700331 EXPECT_EQ(kIdentity, mOutput->getState().colorTransformMatrix);
Lloyd Pique3eb1b212019-03-07 21:15:40 -0800332
333 // No dirty region should be set
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700334 EXPECT_THAT(mOutput->getState().dirtyRegion, RegionEq(Region()));
Lloyd Pique3eb1b212019-03-07 21:15:40 -0800335}
336
337TEST_F(OutputTest, setColorTransformPerformsUpdateToIdentity) {
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700338 mOutput->editState().colorTransformMatrix = kNonIdentityHalf;
Lloyd Pique3eb1b212019-03-07 21:15:40 -0800339
340 // Setting a different colorTransformMatrix should perform the update.
341 CompositionRefreshArgs refreshArgs;
342 refreshArgs.colorTransformMatrix = kIdentity;
343
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700344 mOutput->setColorTransform(refreshArgs);
Lloyd Pique3eb1b212019-03-07 21:15:40 -0800345
346 // The internal state should have been updated
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700347 EXPECT_EQ(kIdentity, mOutput->getState().colorTransformMatrix);
Lloyd Pique3eb1b212019-03-07 21:15:40 -0800348
349 // The dirtyRegion should be set to the full display size
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700350 EXPECT_THAT(mOutput->getState().dirtyRegion, RegionEq(Region(kDefaultDisplaySize)));
Lloyd Pique3eb1b212019-03-07 21:15:40 -0800351}
Lloyd Pique77f79a22019-04-29 15:55:40 -0700352
Lloyd Pique3eb1b212019-03-07 21:15:40 -0800353TEST_F(OutputTest, setColorTransformPerformsUpdateForIdentityToHalf) {
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700354 mOutput->editState().colorTransformMatrix = kIdentity;
Lloyd Pique77f79a22019-04-29 15:55:40 -0700355
Lloyd Pique3eb1b212019-03-07 21:15:40 -0800356 // Setting a different colorTransformMatrix should perform the update.
357 CompositionRefreshArgs refreshArgs;
358 refreshArgs.colorTransformMatrix = kNonIdentityHalf;
Lloyd Pique77f79a22019-04-29 15:55:40 -0700359
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700360 mOutput->setColorTransform(refreshArgs);
Lloyd Piqueef958122019-02-05 18:00:12 -0800361
Lloyd Pique3eb1b212019-03-07 21:15:40 -0800362 // The internal state should have been updated
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700363 EXPECT_EQ(kNonIdentityHalf, mOutput->getState().colorTransformMatrix);
Lloyd Pique3eb1b212019-03-07 21:15:40 -0800364
365 // The dirtyRegion should be set to the full display size
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700366 EXPECT_THAT(mOutput->getState().dirtyRegion, RegionEq(Region(kDefaultDisplaySize)));
Lloyd Pique3eb1b212019-03-07 21:15:40 -0800367}
368
369TEST_F(OutputTest, setColorTransformPerformsUpdateForHalfToQuarter) {
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700370 mOutput->editState().colorTransformMatrix = kNonIdentityHalf;
Lloyd Pique3eb1b212019-03-07 21:15:40 -0800371
372 // Setting a different colorTransformMatrix should perform the update.
373 CompositionRefreshArgs refreshArgs;
374 refreshArgs.colorTransformMatrix = kNonIdentityQuarter;
375
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700376 mOutput->setColorTransform(refreshArgs);
Lloyd Pique3eb1b212019-03-07 21:15:40 -0800377
378 // The internal state should have been updated
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700379 EXPECT_EQ(kNonIdentityQuarter, mOutput->getState().colorTransformMatrix);
Lloyd Pique3eb1b212019-03-07 21:15:40 -0800380
381 // The dirtyRegion should be set to the full display size
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700382 EXPECT_THAT(mOutput->getState().dirtyRegion, RegionEq(Region(kDefaultDisplaySize)));
Lloyd Pique32cbe282018-10-19 13:09:22 -0700383}
384
Lloyd Pique66d68602019-02-13 14:23:31 -0800385/*
Lloyd Pique17ca7422019-11-14 14:24:10 -0800386 * Output::setColorProfile
Lloyd Pique32cbe282018-10-19 13:09:22 -0700387 */
388
Lloyd Pique17ca7422019-11-14 14:24:10 -0800389using OutputSetColorProfileTest = OutputTest;
390
391TEST_F(OutputSetColorProfileTest, setsStateAndDirtiesOutputIfChanged) {
Lloyd Pique6a3b4462019-03-07 20:58:12 -0800392 using ColorProfile = Output::ColorProfile;
393
Lloyd Piquef5275482019-01-29 18:42:42 -0800394 EXPECT_CALL(*mDisplayColorProfile,
395 getTargetDataspace(ui::ColorMode::DISPLAY_P3, ui::Dataspace::DISPLAY_P3,
396 ui::Dataspace::UNKNOWN))
397 .WillOnce(Return(ui::Dataspace::UNKNOWN));
Lloyd Piqueef958122019-02-05 18:00:12 -0800398 EXPECT_CALL(*mRenderSurface, setBufferDataspace(ui::Dataspace::DISPLAY_P3)).Times(1);
Lloyd Pique31cb2942018-10-19 17:23:03 -0700399
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700400 mOutput->setColorProfile(ColorProfile{ui::ColorMode::DISPLAY_P3, ui::Dataspace::DISPLAY_P3,
401 ui::RenderIntent::TONE_MAP_COLORIMETRIC,
402 ui::Dataspace::UNKNOWN});
Lloyd Pique32cbe282018-10-19 13:09:22 -0700403
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700404 EXPECT_EQ(ui::ColorMode::DISPLAY_P3, mOutput->getState().colorMode);
405 EXPECT_EQ(ui::Dataspace::DISPLAY_P3, mOutput->getState().dataspace);
406 EXPECT_EQ(ui::RenderIntent::TONE_MAP_COLORIMETRIC, mOutput->getState().renderIntent);
407 EXPECT_EQ(ui::Dataspace::UNKNOWN, mOutput->getState().targetDataspace);
Lloyd Piquef5275482019-01-29 18:42:42 -0800408
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700409 EXPECT_THAT(mOutput->getState().dirtyRegion, RegionEq(Region(kDefaultDisplaySize)));
Lloyd Piqueef958122019-02-05 18:00:12 -0800410}
411
Lloyd Pique17ca7422019-11-14 14:24:10 -0800412TEST_F(OutputSetColorProfileTest, doesNothingIfNoChange) {
Lloyd Pique6a3b4462019-03-07 20:58:12 -0800413 using ColorProfile = Output::ColorProfile;
414
Lloyd Piquef5275482019-01-29 18:42:42 -0800415 EXPECT_CALL(*mDisplayColorProfile,
416 getTargetDataspace(ui::ColorMode::DISPLAY_P3, ui::Dataspace::DISPLAY_P3,
417 ui::Dataspace::UNKNOWN))
418 .WillOnce(Return(ui::Dataspace::UNKNOWN));
419
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700420 mOutput->editState().colorMode = ui::ColorMode::DISPLAY_P3;
421 mOutput->editState().dataspace = ui::Dataspace::DISPLAY_P3;
422 mOutput->editState().renderIntent = ui::RenderIntent::TONE_MAP_COLORIMETRIC;
423 mOutput->editState().targetDataspace = ui::Dataspace::UNKNOWN;
Lloyd Piqueef958122019-02-05 18:00:12 -0800424
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700425 mOutput->setColorProfile(ColorProfile{ui::ColorMode::DISPLAY_P3, ui::Dataspace::DISPLAY_P3,
426 ui::RenderIntent::TONE_MAP_COLORIMETRIC,
427 ui::Dataspace::UNKNOWN});
Lloyd Piqueef958122019-02-05 18:00:12 -0800428
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700429 EXPECT_THAT(mOutput->getState().dirtyRegion, RegionEq(Region()));
Lloyd Pique32cbe282018-10-19 13:09:22 -0700430}
431
Lloyd Pique66d68602019-02-13 14:23:31 -0800432/*
Lloyd Pique31cb2942018-10-19 17:23:03 -0700433 * Output::setRenderSurface()
434 */
435
436TEST_F(OutputTest, setRenderSurfaceResetsBounds) {
437 const ui::Size newDisplaySize{640, 480};
438
439 mock::RenderSurface* renderSurface = new StrictMock<mock::RenderSurface>();
440 EXPECT_CALL(*renderSurface, getSize()).WillOnce(ReturnRef(newDisplaySize));
441
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700442 mOutput->setRenderSurface(std::unique_ptr<RenderSurface>(renderSurface));
Lloyd Pique31cb2942018-10-19 17:23:03 -0700443
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700444 EXPECT_EQ(Rect(newDisplaySize), mOutput->getState().bounds);
Lloyd Pique31cb2942018-10-19 17:23:03 -0700445}
446
Lloyd Pique66d68602019-02-13 14:23:31 -0800447/*
Alec Mourie7d1d4a2019-02-05 01:13:46 +0000448 * Output::getDirtyRegion()
Lloyd Pique32cbe282018-10-19 13:09:22 -0700449 */
450
Alec Mourie7d1d4a2019-02-05 01:13:46 +0000451TEST_F(OutputTest, getDirtyRegionWithRepaintEverythingTrue) {
452 const Rect viewport{100, 200};
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700453 mOutput->editState().viewport = viewport;
454 mOutput->editState().dirtyRegion.set(50, 300);
Lloyd Pique32cbe282018-10-19 13:09:22 -0700455
456 {
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700457 Region result = mOutput->getDirtyRegion(true);
Lloyd Pique32cbe282018-10-19 13:09:22 -0700458
Alec Mourie7d1d4a2019-02-05 01:13:46 +0000459 EXPECT_THAT(result, RegionEq(Region(viewport)));
Lloyd Pique32cbe282018-10-19 13:09:22 -0700460 }
461}
462
Alec Mourie7d1d4a2019-02-05 01:13:46 +0000463TEST_F(OutputTest, getDirtyRegionWithRepaintEverythingFalse) {
464 const Rect viewport{100, 200};
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700465 mOutput->editState().viewport = viewport;
466 mOutput->editState().dirtyRegion.set(50, 300);
Lloyd Pique32cbe282018-10-19 13:09:22 -0700467
468 {
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700469 Region result = mOutput->getDirtyRegion(false);
Lloyd Pique32cbe282018-10-19 13:09:22 -0700470
471 // The dirtyRegion should be clipped to the display bounds.
472 EXPECT_THAT(result, RegionEq(Region(Rect(50, 200))));
473 }
Lloyd Pique32cbe282018-10-19 13:09:22 -0700474}
475
Lloyd Pique66d68602019-02-13 14:23:31 -0800476/*
Lloyd Piqueef36b002019-01-23 17:52:04 -0800477 * Output::belongsInOutput()
478 */
479
480TEST_F(OutputTest, belongsInOutputFiltersAsExpected) {
481 const uint32_t layerStack1 = 123u;
482 const uint32_t layerStack2 = 456u;
483
484 // If the output accepts layerStack1 and internal-only layers....
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700485 mOutput->setLayerStackFilter(layerStack1, true);
Lloyd Piqueef36b002019-01-23 17:52:04 -0800486
Lloyd Piquec6687342019-03-07 21:34:57 -0800487 // A layer with no layerStack does not belong to it, internal-only or not.
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700488 EXPECT_FALSE(mOutput->belongsInOutput(std::nullopt, false));
489 EXPECT_FALSE(mOutput->belongsInOutput(std::nullopt, true));
Lloyd Piquec6687342019-03-07 21:34:57 -0800490
Lloyd Piqueef36b002019-01-23 17:52:04 -0800491 // Any layer with layerStack1 belongs to it, internal-only or not.
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700492 EXPECT_TRUE(mOutput->belongsInOutput(layerStack1, false));
493 EXPECT_TRUE(mOutput->belongsInOutput(layerStack1, true));
494 EXPECT_FALSE(mOutput->belongsInOutput(layerStack2, true));
495 EXPECT_FALSE(mOutput->belongsInOutput(layerStack2, false));
Lloyd Piqueef36b002019-01-23 17:52:04 -0800496
497 // If the output accepts layerStack21 but not internal-only layers...
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700498 mOutput->setLayerStackFilter(layerStack1, false);
Lloyd Piqueef36b002019-01-23 17:52:04 -0800499
500 // Only non-internal layers with layerStack1 belong to it.
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700501 EXPECT_TRUE(mOutput->belongsInOutput(layerStack1, false));
502 EXPECT_FALSE(mOutput->belongsInOutput(layerStack1, true));
503 EXPECT_FALSE(mOutput->belongsInOutput(layerStack2, true));
504 EXPECT_FALSE(mOutput->belongsInOutput(layerStack2, false));
Lloyd Piqueef36b002019-01-23 17:52:04 -0800505}
506
Lloyd Pique66c20c42019-03-07 21:44:02 -0800507TEST_F(OutputTest, belongsInOutputFiltersLayersAsExpected) {
508 StrictMock<mock::Layer> layer;
Lloyd Pique9755fb72019-03-26 14:44:40 -0700509 LayerFECompositionState layerFEState;
Lloyd Pique66c20c42019-03-07 21:44:02 -0800510
Lloyd Pique9755fb72019-03-26 14:44:40 -0700511 EXPECT_CALL(layer, getFEState()).WillRepeatedly(ReturnRef(layerFEState));
Lloyd Pique66c20c42019-03-07 21:44:02 -0800512
513 const uint32_t layerStack1 = 123u;
514 const uint32_t layerStack2 = 456u;
515
516 // If the output accepts layerStack1 and internal-only layers....
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700517 mOutput->setLayerStackFilter(layerStack1, true);
Lloyd Pique66c20c42019-03-07 21:44:02 -0800518
519 // A null layer pointer does not belong to the output
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700520 EXPECT_FALSE(mOutput->belongsInOutput(nullptr));
Lloyd Pique66c20c42019-03-07 21:44:02 -0800521
522 // A layer with no layerStack does not belong to it, internal-only or not.
Lloyd Pique9755fb72019-03-26 14:44:40 -0700523 layerFEState.layerStackId = std::nullopt;
524 layerFEState.internalOnly = false;
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700525 EXPECT_FALSE(mOutput->belongsInOutput(&layer));
Lloyd Pique66c20c42019-03-07 21:44:02 -0800526
Lloyd Pique9755fb72019-03-26 14:44:40 -0700527 layerFEState.layerStackId = std::nullopt;
528 layerFEState.internalOnly = true;
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700529 EXPECT_FALSE(mOutput->belongsInOutput(&layer));
Lloyd Pique66c20c42019-03-07 21:44:02 -0800530
531 // Any layer with layerStack1 belongs to it, internal-only or not.
Lloyd Pique9755fb72019-03-26 14:44:40 -0700532 layerFEState.layerStackId = layerStack1;
533 layerFEState.internalOnly = false;
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 = layerStack1;
537 layerFEState.internalOnly = true;
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700538 EXPECT_TRUE(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 = true;
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700542 EXPECT_FALSE(mOutput->belongsInOutput(&layer));
Lloyd Pique66c20c42019-03-07 21:44:02 -0800543
Lloyd Pique9755fb72019-03-26 14:44:40 -0700544 layerFEState.layerStackId = layerStack2;
545 layerFEState.internalOnly = false;
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700546 EXPECT_FALSE(mOutput->belongsInOutput(&layer));
Lloyd Pique66c20c42019-03-07 21:44:02 -0800547
548 // If the output accepts layerStack1 but not internal-only layers...
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700549 mOutput->setLayerStackFilter(layerStack1, false);
Lloyd Pique66c20c42019-03-07 21:44:02 -0800550
551 // A null layer pointer does not belong to the output
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700552 EXPECT_FALSE(mOutput->belongsInOutput(nullptr));
Lloyd Pique66c20c42019-03-07 21:44:02 -0800553
554 // Only non-internal layers with layerStack1 belong to it.
Lloyd Pique9755fb72019-03-26 14:44:40 -0700555 layerFEState.layerStackId = layerStack1;
556 layerFEState.internalOnly = false;
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700557 EXPECT_TRUE(mOutput->belongsInOutput(&layer));
Lloyd Pique66c20c42019-03-07 21:44:02 -0800558
Lloyd Pique9755fb72019-03-26 14:44:40 -0700559 layerFEState.layerStackId = layerStack1;
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 = true;
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700565 EXPECT_FALSE(mOutput->belongsInOutput(&layer));
Lloyd Pique66c20c42019-03-07 21:44:02 -0800566
Lloyd Pique9755fb72019-03-26 14:44:40 -0700567 layerFEState.layerStackId = layerStack2;
568 layerFEState.internalOnly = false;
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700569 EXPECT_FALSE(mOutput->belongsInOutput(&layer));
Lloyd Pique66c20c42019-03-07 21:44:02 -0800570}
571
Lloyd Pique66d68602019-02-13 14:23:31 -0800572/*
Lloyd Piquecc01a452018-12-04 17:24:00 -0800573 * Output::getOutputLayerForLayer()
574 */
575
576TEST_F(OutputTest, getOutputLayerForLayerWorks) {
577 mock::OutputLayer* outputLayer1 = new StrictMock<mock::OutputLayer>();
578 mock::OutputLayer* outputLayer2 = new StrictMock<mock::OutputLayer>();
579
Lloyd Pique01c77c12019-04-17 12:48:32 -0700580 mOutput->injectOutputLayerForTest(std::unique_ptr<OutputLayer>(outputLayer1));
581 mOutput->injectOutputLayerForTest(nullptr);
582 mOutput->injectOutputLayerForTest(std::unique_ptr<OutputLayer>(outputLayer2));
Lloyd Piquecc01a452018-12-04 17:24:00 -0800583
584 StrictMock<mock::Layer> layer;
585 StrictMock<mock::Layer> otherLayer;
586
587 // If the input layer matches the first OutputLayer, it will be returned.
588 EXPECT_CALL(*outputLayer1, getLayer()).WillOnce(ReturnRef(layer));
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700589 EXPECT_EQ(outputLayer1, mOutput->getOutputLayerForLayer(&layer));
Lloyd Piquecc01a452018-12-04 17:24:00 -0800590
591 // If the input layer matches the second OutputLayer, it will be returned.
592 EXPECT_CALL(*outputLayer1, getLayer()).WillOnce(ReturnRef(otherLayer));
593 EXPECT_CALL(*outputLayer2, getLayer()).WillOnce(ReturnRef(layer));
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700594 EXPECT_EQ(outputLayer2, mOutput->getOutputLayerForLayer(&layer));
Lloyd Piquecc01a452018-12-04 17:24:00 -0800595
596 // If the input layer does not match an output layer, null will be returned.
597 EXPECT_CALL(*outputLayer1, getLayer()).WillOnce(ReturnRef(otherLayer));
598 EXPECT_CALL(*outputLayer2, getLayer()).WillOnce(ReturnRef(otherLayer));
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700599 EXPECT_EQ(nullptr, mOutput->getOutputLayerForLayer(&layer));
Lloyd Piquecc01a452018-12-04 17:24:00 -0800600}
601
Lloyd Pique66d68602019-02-13 14:23:31 -0800602/*
Lloyd Piquec9e60032019-11-14 11:47:26 -0800603 * Output::setReleasedLayers()
604 */
605
606using OutputSetReleasedLayersTest = OutputTest;
607
608TEST_F(OutputSetReleasedLayersTest, setReleasedLayersTakesGivenLayers) {
609 sp<StrictMock<mock::LayerFE>> layer1FE{new StrictMock<mock::LayerFE>()};
610 sp<StrictMock<mock::LayerFE>> layer2FE{new StrictMock<mock::LayerFE>()};
611 sp<StrictMock<mock::LayerFE>> layer3FE{new StrictMock<mock::LayerFE>()};
612
613 Output::ReleasedLayers layers;
614 layers.push_back(layer1FE);
615 layers.push_back(layer2FE);
616 layers.push_back(layer3FE);
617
618 mOutput->setReleasedLayers(std::move(layers));
619
620 const auto& setLayers = mOutput->getReleasedLayersForTest();
621 ASSERT_EQ(3u, setLayers.size());
622 ASSERT_EQ(layer1FE.get(), setLayers[0].promote().get());
623 ASSERT_EQ(layer2FE.get(), setLayers[1].promote().get());
624 ASSERT_EQ(layer3FE.get(), setLayers[2].promote().get());
625}
626
627/*
Lloyd Piquec0ee6ba2019-11-14 12:55:53 -0800628 * Output::updateLayerStateFromFE()
629 */
630
631using OutputUpdateLayerStateFromFETest = OutputLatchFEStateTest;
632
633TEST_F(OutputUpdateLayerStateFromFETest, handlesNoOutputLayerCase) {
634 CompositionRefreshArgs refreshArgs;
635
636 mOutput->updateLayerStateFromFE(refreshArgs);
637}
638
639TEST_F(OutputUpdateLayerStateFromFETest, latchesContentStateForAllContainedLayers) {
640 EXPECT_CALL(mLayer1FE,
641 latchCompositionState(Ref(mLayer1FEState), LayerFE::StateSubset::Content));
642 EXPECT_CALL(mLayer2FE,
643 latchCompositionState(Ref(mLayer2FEState), LayerFE::StateSubset::Content));
644 EXPECT_CALL(mLayer3FE,
645 latchCompositionState(Ref(mLayer3FEState), LayerFE::StateSubset::Content));
646
647 // Note: Must be performed after any expectations on these mocks
648 injectLayer(std::move(mOutputLayer1));
649 injectLayer(std::move(mOutputLayer2));
650 injectLayer(std::move(mOutputLayer3));
651
652 CompositionRefreshArgs refreshArgs;
653 refreshArgs.updatingGeometryThisFrame = false;
654
655 mOutput->updateLayerStateFromFE(refreshArgs);
656}
657
658TEST_F(OutputUpdateLayerStateFromFETest, latchesGeometryAndContentStateForAllContainedLayers) {
659 EXPECT_CALL(mLayer1FE,
660 latchCompositionState(Ref(mLayer1FEState),
661 LayerFE::StateSubset::GeometryAndContent));
662 EXPECT_CALL(mLayer2FE,
663 latchCompositionState(Ref(mLayer2FEState),
664 LayerFE::StateSubset::GeometryAndContent));
665 EXPECT_CALL(mLayer3FE,
666 latchCompositionState(Ref(mLayer3FEState),
667 LayerFE::StateSubset::GeometryAndContent));
668
669 // Note: Must be performed after any expectations on these mocks
670 injectLayer(std::move(mOutputLayer1));
671 injectLayer(std::move(mOutputLayer2));
672 injectLayer(std::move(mOutputLayer3));
673
674 CompositionRefreshArgs refreshArgs;
675 refreshArgs.updatingGeometryThisFrame = true;
676
677 mOutput->updateLayerStateFromFE(refreshArgs);
678}
679
680/*
Alec Mourif9a2a2c2019-11-12 12:46:02 -0800681 * Output::updateAndWriteCompositionState()
682 */
683
Lloyd Piqueef63b612019-11-14 13:19:56 -0800684using OutputUpdateAndWriteCompositionStateTest = OutputLatchFEStateTest;
685
686TEST_F(OutputUpdateAndWriteCompositionStateTest, doesNothingIfLayers) {
687 mOutput->editState().isEnabled = true;
Alec Mourif9a2a2c2019-11-12 12:46:02 -0800688
689 CompositionRefreshArgs args;
690 mOutput->updateAndWriteCompositionState(args);
691}
692
Lloyd Piqueef63b612019-11-14 13:19:56 -0800693TEST_F(OutputUpdateAndWriteCompositionStateTest, doesNothingIfOutputNotEnabled) {
694 mOutput->editState().isEnabled = false;
Alec Mourif9a2a2c2019-11-12 12:46:02 -0800695
Lloyd Piqueef63b612019-11-14 13:19:56 -0800696 injectLayer(std::move(mOutputLayer1));
697 injectLayer(std::move(mOutputLayer2));
698 injectLayer(std::move(mOutputLayer3));
699
700 CompositionRefreshArgs args;
701 mOutput->updateAndWriteCompositionState(args);
702}
703
704TEST_F(OutputUpdateAndWriteCompositionStateTest, updatesLayerContentForAllLayers) {
705 EXPECT_CALL(*mOutputLayer1, updateCompositionState(false, false));
706 EXPECT_CALL(*mOutputLayer1, writeStateToHWC(false));
707 EXPECT_CALL(*mOutputLayer2, updateCompositionState(false, false));
708 EXPECT_CALL(*mOutputLayer2, writeStateToHWC(false));
709 EXPECT_CALL(*mOutputLayer3, updateCompositionState(false, false));
710 EXPECT_CALL(*mOutputLayer3, writeStateToHWC(false));
711
712 injectLayer(std::move(mOutputLayer1));
713 injectLayer(std::move(mOutputLayer2));
714 injectLayer(std::move(mOutputLayer3));
715
716 mOutput->editState().isEnabled = true;
717
718 CompositionRefreshArgs args;
719 args.updatingGeometryThisFrame = false;
720 args.devOptForceClientComposition = false;
721 mOutput->updateAndWriteCompositionState(args);
722}
723
724TEST_F(OutputUpdateAndWriteCompositionStateTest, updatesLayerGeometryAndContentForAllLayers) {
725 EXPECT_CALL(*mOutputLayer1, updateCompositionState(true, false));
726 EXPECT_CALL(*mOutputLayer1, writeStateToHWC(true));
727 EXPECT_CALL(*mOutputLayer2, updateCompositionState(true, false));
728 EXPECT_CALL(*mOutputLayer2, writeStateToHWC(true));
729 EXPECT_CALL(*mOutputLayer3, updateCompositionState(true, false));
730 EXPECT_CALL(*mOutputLayer3, writeStateToHWC(true));
731
732 injectLayer(std::move(mOutputLayer1));
733 injectLayer(std::move(mOutputLayer2));
734 injectLayer(std::move(mOutputLayer3));
735
736 mOutput->editState().isEnabled = true;
Alec Mourif9a2a2c2019-11-12 12:46:02 -0800737
738 CompositionRefreshArgs args;
739 args.updatingGeometryThisFrame = true;
Lloyd Piqueef63b612019-11-14 13:19:56 -0800740 args.devOptForceClientComposition = false;
741 mOutput->updateAndWriteCompositionState(args);
742}
743
744TEST_F(OutputUpdateAndWriteCompositionStateTest, forcesClientCompositionForAllLayers) {
745 EXPECT_CALL(*mOutputLayer1, updateCompositionState(false, true));
746 EXPECT_CALL(*mOutputLayer1, writeStateToHWC(false));
747 EXPECT_CALL(*mOutputLayer2, updateCompositionState(false, true));
748 EXPECT_CALL(*mOutputLayer2, writeStateToHWC(false));
749 EXPECT_CALL(*mOutputLayer3, updateCompositionState(false, true));
750 EXPECT_CALL(*mOutputLayer3, writeStateToHWC(false));
751
752 injectLayer(std::move(mOutputLayer1));
753 injectLayer(std::move(mOutputLayer2));
754 injectLayer(std::move(mOutputLayer3));
755
756 mOutput->editState().isEnabled = true;
757
758 CompositionRefreshArgs args;
759 args.updatingGeometryThisFrame = false;
Alec Mourif9a2a2c2019-11-12 12:46:02 -0800760 args.devOptForceClientComposition = true;
761 mOutput->updateAndWriteCompositionState(args);
762}
763
764/*
Lloyd Pique66d68602019-02-13 14:23:31 -0800765 * Output::prepareFrame()
766 */
767
768struct OutputPrepareFrameTest : public testing::Test {
Lloyd Piquefaa3f192019-11-14 14:05:09 -0800769 struct OutputPartialMock : public OutputPartialMockBase {
Lloyd Pique739afaf2019-11-21 16:40:05 -0800770 // Sets up the helper functions called by the function under test to use
771 // mock implementations.
Lloyd Pique66d68602019-02-13 14:23:31 -0800772 MOCK_METHOD0(chooseCompositionStrategy, void());
773 };
774
775 OutputPrepareFrameTest() {
776 mOutput.setDisplayColorProfileForTest(
777 std::unique_ptr<DisplayColorProfile>(mDisplayColorProfile));
778 mOutput.setRenderSurfaceForTest(std::unique_ptr<RenderSurface>(mRenderSurface));
779 }
780
781 StrictMock<mock::CompositionEngine> mCompositionEngine;
782 mock::DisplayColorProfile* mDisplayColorProfile = new StrictMock<mock::DisplayColorProfile>();
783 mock::RenderSurface* mRenderSurface = new StrictMock<mock::RenderSurface>();
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700784 StrictMock<OutputPartialMock> mOutput;
Lloyd Pique66d68602019-02-13 14:23:31 -0800785};
786
787TEST_F(OutputPrepareFrameTest, takesEarlyOutIfNotEnabled) {
788 mOutput.editState().isEnabled = false;
789
790 mOutput.prepareFrame();
791}
792
793TEST_F(OutputPrepareFrameTest, delegatesToChooseCompositionStrategyAndRenderSurface) {
794 mOutput.editState().isEnabled = true;
795 mOutput.editState().usesClientComposition = false;
796 mOutput.editState().usesDeviceComposition = true;
797
798 EXPECT_CALL(mOutput, chooseCompositionStrategy()).Times(1);
799 EXPECT_CALL(*mRenderSurface, prepareFrame(false, true));
800
801 mOutput.prepareFrame();
802}
803
804// Note: Use OutputTest and not OutputPrepareFrameTest, so the real
805// base chooseCompositionStrategy() is invoked.
806TEST_F(OutputTest, prepareFrameSetsClientCompositionOnlyByDefault) {
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700807 mOutput->editState().isEnabled = true;
808 mOutput->editState().usesClientComposition = false;
809 mOutput->editState().usesDeviceComposition = true;
Lloyd Pique66d68602019-02-13 14:23:31 -0800810
811 EXPECT_CALL(*mRenderSurface, prepareFrame(true, false));
812
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700813 mOutput->prepareFrame();
Lloyd Pique66d68602019-02-13 14:23:31 -0800814
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700815 EXPECT_TRUE(mOutput->getState().usesClientComposition);
816 EXPECT_FALSE(mOutput->getState().usesDeviceComposition);
Lloyd Pique66d68602019-02-13 14:23:31 -0800817}
818
Lloyd Pique56eba802019-08-28 15:45:25 -0700819/*
Lloyd Piqueb62cebc2019-11-20 18:31:52 -0800820 * Output::prepare()
821 */
822
823struct OutputPrepareTest : public testing::Test {
824 struct OutputPartialMock : public OutputPartialMockBase {
825 // Sets up the helper functions called by the function under test to use
826 // mock implementations.
827 MOCK_METHOD2(rebuildLayerStacks,
828 void(const compositionengine::CompositionRefreshArgs&,
829 compositionengine::LayerFESet&));
830 };
831
832 StrictMock<OutputPartialMock> mOutput;
833 CompositionRefreshArgs mRefreshArgs;
Lloyd Piquefe0ee9e2019-11-22 16:30:30 -0800834 LayerFESet mGeomSnapshots;
Lloyd Piqueb62cebc2019-11-20 18:31:52 -0800835};
836
837TEST_F(OutputPrepareTest, justInvokesRebuildLayerStacks) {
838 InSequence seq;
839 EXPECT_CALL(mOutput, rebuildLayerStacks(Ref(mRefreshArgs), Ref(mGeomSnapshots)));
840
841 mOutput.prepare(mRefreshArgs, mGeomSnapshots);
842}
843
844/*
845 * Output::rebuildLayerStacks()
846 */
847
848struct OutputRebuildLayerStacksTest : public testing::Test {
849 struct OutputPartialMock : public OutputPartialMockBase {
850 // Sets up the helper functions called by the function under test to use
851 // mock implementations.
852 MOCK_METHOD2(collectVisibleLayers,
853 void(const compositionengine::CompositionRefreshArgs&,
854 compositionengine::Output::CoverageState&));
855 };
856
857 OutputRebuildLayerStacksTest() {
858 mOutput.mState.isEnabled = true;
859 mOutput.mState.transform = kIdentityTransform;
860 mOutput.mState.bounds = kOutputBounds;
861
862 mRefreshArgs.updatingOutputGeometryThisFrame = true;
863
864 mCoverageAboveCoveredLayersToSet = Region(Rect(0, 0, 10, 10));
865
866 EXPECT_CALL(mOutput, collectVisibleLayers(Ref(mRefreshArgs), _))
867 .WillRepeatedly(Invoke(this, &OutputRebuildLayerStacksTest::setTestCoverageValues));
868 }
869
870 void setTestCoverageValues(const CompositionRefreshArgs&,
871 compositionengine::Output::CoverageState& state) {
872 state.aboveCoveredLayers = mCoverageAboveCoveredLayersToSet;
873 state.aboveOpaqueLayers = mCoverageAboveOpaqueLayersToSet;
874 state.dirtyRegion = mCoverageDirtyRegionToSet;
875 }
876
877 static const ui::Transform kIdentityTransform;
878 static const ui::Transform kRotate90Transform;
879 static const Rect kOutputBounds;
880
881 StrictMock<OutputPartialMock> mOutput;
882 CompositionRefreshArgs mRefreshArgs;
Lloyd Piquefe0ee9e2019-11-22 16:30:30 -0800883 LayerFESet mGeomSnapshots;
Lloyd Piqueb62cebc2019-11-20 18:31:52 -0800884 Region mCoverageAboveCoveredLayersToSet;
885 Region mCoverageAboveOpaqueLayersToSet;
886 Region mCoverageDirtyRegionToSet;
887};
888
889const ui::Transform OutputRebuildLayerStacksTest::kIdentityTransform{TR_IDENT, 1920, 1080};
890const ui::Transform OutputRebuildLayerStacksTest::kRotate90Transform{TR_ROT_90, 1920, 1080};
891const Rect OutputRebuildLayerStacksTest::kOutputBounds{0, 0, 1920, 1080};
892
893TEST_F(OutputRebuildLayerStacksTest, doesNothingIfNotEnabled) {
894 mOutput.mState.isEnabled = false;
895
896 mOutput.rebuildLayerStacks(mRefreshArgs, mGeomSnapshots);
897}
898
899TEST_F(OutputRebuildLayerStacksTest, doesNothingIfNotUpdatingGeometryThisFrame) {
900 mRefreshArgs.updatingOutputGeometryThisFrame = false;
901
902 mOutput.rebuildLayerStacks(mRefreshArgs, mGeomSnapshots);
903}
904
905TEST_F(OutputRebuildLayerStacksTest, computesUndefinedRegionWithNoRotationAndFullCoverage) {
906 mOutput.mState.transform = kIdentityTransform;
907
908 mCoverageAboveOpaqueLayersToSet = Region(Rect(0, 0, 1920, 1080));
909
910 mOutput.rebuildLayerStacks(mRefreshArgs, mGeomSnapshots);
911
912 EXPECT_THAT(mOutput.mState.undefinedRegion, RegionEq(Region(Rect(0, 0, 0, 0))));
913}
914
915TEST_F(OutputRebuildLayerStacksTest, computesUndefinedRegionWithNoRotationAndPartialCoverage) {
916 mOutput.mState.transform = kIdentityTransform;
917
918 mCoverageAboveOpaqueLayersToSet = Region(Rect(0, 0, 960, 1080));
919
920 mOutput.rebuildLayerStacks(mRefreshArgs, mGeomSnapshots);
921
922 EXPECT_THAT(mOutput.mState.undefinedRegion, RegionEq(Region(Rect(960, 0, 1920, 1080))));
923}
924
925TEST_F(OutputRebuildLayerStacksTest, computesUndefinedRegionWith90RotationAndFullCoverage) {
926 mOutput.mState.transform = kRotate90Transform;
927
928 mCoverageAboveOpaqueLayersToSet = Region(Rect(0, 0, 1080, 1920));
929
930 mOutput.rebuildLayerStacks(mRefreshArgs, mGeomSnapshots);
931
932 EXPECT_THAT(mOutput.mState.undefinedRegion, RegionEq(Region(Rect(0, 0, 0, 0))));
933}
934
935TEST_F(OutputRebuildLayerStacksTest, computesUndefinedRegionWith90RotationAndPartialCoverage) {
936 mOutput.mState.transform = kRotate90Transform;
937
938 mCoverageAboveOpaqueLayersToSet = Region(Rect(0, 0, 1080, 960));
939
940 mOutput.rebuildLayerStacks(mRefreshArgs, mGeomSnapshots);
941
942 EXPECT_THAT(mOutput.mState.undefinedRegion, RegionEq(Region(Rect(0, 0, 960, 1080))));
943}
944
945TEST_F(OutputRebuildLayerStacksTest, addsToDirtyRegionWithNoRotation) {
946 mOutput.mState.transform = kIdentityTransform;
947 mOutput.mState.dirtyRegion = Region(Rect(960, 0, 1920, 1080));
948
949 mCoverageDirtyRegionToSet = Region(Rect(0, 0, 960, 1080));
950
951 mOutput.rebuildLayerStacks(mRefreshArgs, mGeomSnapshots);
952
953 EXPECT_THAT(mOutput.mState.dirtyRegion, RegionEq(Region(Rect(0, 0, 1920, 1080))));
954}
955
956TEST_F(OutputRebuildLayerStacksTest, addsToDirtyRegionWith90Rotation) {
957 mOutput.mState.transform = kRotate90Transform;
958 mOutput.mState.dirtyRegion = Region(Rect(0, 960, 1080, 1920));
959
960 mCoverageDirtyRegionToSet = Region(Rect(0, 0, 1080, 960));
961
962 mOutput.rebuildLayerStacks(mRefreshArgs, mGeomSnapshots);
963
964 EXPECT_THAT(mOutput.mState.dirtyRegion, RegionEq(Region(Rect(0, 0, 1080, 1920))));
965}
966
967/*
968 * Output::collectVisibleLayers()
969 */
970
Lloyd Pique1ef93222019-11-21 16:41:53 -0800971struct OutputCollectVisibleLayersTest : public testing::Test {
972 struct OutputPartialMock : public OutputPartialMockBase {
973 // Sets up the helper functions called by the function under test to use
974 // mock implementations.
975 MOCK_METHOD2(ensureOutputLayerIfVisible,
976 void(std::shared_ptr<compositionengine::Layer>,
977 compositionengine::Output::CoverageState&));
978 MOCK_METHOD1(setReleasedLayers, void(const compositionengine::CompositionRefreshArgs&));
979 MOCK_METHOD0(finalizePendingOutputLayers, void());
980 };
981
982 struct Layer {
983 Layer() {
984 EXPECT_CALL(outputLayer, getState()).WillRepeatedly(ReturnRef(outputLayerState));
985 EXPECT_CALL(outputLayer, editState()).WillRepeatedly(ReturnRef(outputLayerState));
986 }
987
988 StrictMock<mock::OutputLayer> outputLayer;
989 std::shared_ptr<StrictMock<mock::Layer>> layer{new StrictMock<mock::Layer>()};
990 impl::OutputLayerCompositionState outputLayerState;
991 };
992
993 OutputCollectVisibleLayersTest() {
Lloyd Pique0a456232020-01-16 17:51:13 -0800994 EXPECT_CALL(mOutput, getOutputLayerCount()).WillRepeatedly(Return(3u));
Lloyd Pique1ef93222019-11-21 16:41:53 -0800995 EXPECT_CALL(mOutput, getOutputLayerOrderedByZByIndex(0))
996 .WillRepeatedly(Return(&mLayer1.outputLayer));
997 EXPECT_CALL(mOutput, getOutputLayerOrderedByZByIndex(1))
998 .WillRepeatedly(Return(&mLayer2.outputLayer));
999 EXPECT_CALL(mOutput, getOutputLayerOrderedByZByIndex(2))
1000 .WillRepeatedly(Return(&mLayer3.outputLayer));
1001
1002 mRefreshArgs.layers.push_back(mLayer1.layer);
1003 mRefreshArgs.layers.push_back(mLayer2.layer);
1004 mRefreshArgs.layers.push_back(mLayer3.layer);
1005 }
1006
1007 StrictMock<OutputPartialMock> mOutput;
1008 CompositionRefreshArgs mRefreshArgs;
Lloyd Piquefe0ee9e2019-11-22 16:30:30 -08001009 LayerFESet mGeomSnapshots;
1010 Output::CoverageState mCoverageState{mGeomSnapshots};
Lloyd Pique1ef93222019-11-21 16:41:53 -08001011 Layer mLayer1;
1012 Layer mLayer2;
1013 Layer mLayer3;
1014};
1015
1016TEST_F(OutputCollectVisibleLayersTest, doesMinimalWorkIfNoLayers) {
1017 mRefreshArgs.layers.clear();
Lloyd Pique0a456232020-01-16 17:51:13 -08001018 EXPECT_CALL(mOutput, getOutputLayerCount()).WillRepeatedly(Return(0u));
Lloyd Pique1ef93222019-11-21 16:41:53 -08001019
1020 EXPECT_CALL(mOutput, setReleasedLayers(Ref(mRefreshArgs)));
1021 EXPECT_CALL(mOutput, finalizePendingOutputLayers());
1022
1023 mOutput.collectVisibleLayers(mRefreshArgs, mCoverageState);
1024}
1025
1026TEST_F(OutputCollectVisibleLayersTest, processesCandidateLayersReversedAndSetsOutputLayerZ) {
1027 // Enforce a call order sequence for this test.
1028 InSequence seq;
1029
1030 // Layer coverage is evaluated from front to back!
1031 EXPECT_CALL(mOutput, ensureOutputLayerIfVisible(Eq(mLayer3.layer), Ref(mCoverageState)));
1032 EXPECT_CALL(mOutput, ensureOutputLayerIfVisible(Eq(mLayer2.layer), Ref(mCoverageState)));
1033 EXPECT_CALL(mOutput, ensureOutputLayerIfVisible(Eq(mLayer1.layer), Ref(mCoverageState)));
1034
1035 EXPECT_CALL(mOutput, setReleasedLayers(Ref(mRefreshArgs)));
1036 EXPECT_CALL(mOutput, finalizePendingOutputLayers());
1037
1038 mOutput.collectVisibleLayers(mRefreshArgs, mCoverageState);
1039
1040 // Ensure all output layers have been assigned a simple/flattened z-order.
1041 EXPECT_EQ(0u, mLayer1.outputLayerState.z);
1042 EXPECT_EQ(1u, mLayer2.outputLayerState.z);
1043 EXPECT_EQ(2u, mLayer3.outputLayerState.z);
1044}
Lloyd Piqueb62cebc2019-11-20 18:31:52 -08001045
1046/*
1047 * Output::ensureOutputLayerIfVisible()
1048 */
1049
Lloyd Piquefe0ee9e2019-11-22 16:30:30 -08001050struct OutputEnsureOutputLayerIfVisibleTest : public testing::Test {
1051 struct OutputPartialMock : public OutputPartialMockBase {
1052 // Sets up the helper functions called by the function under test to use
1053 // mock implementations.
1054 MOCK_CONST_METHOD1(belongsInOutput, bool(const compositionengine::Layer*));
1055 MOCK_CONST_METHOD1(getOutputLayerOrderedByZByIndex, OutputLayer*(size_t));
1056 MOCK_METHOD3(ensureOutputLayer,
1057 compositionengine::OutputLayer*(
1058 std::optional<size_t>,
1059 const std::shared_ptr<compositionengine::Layer>&, const sp<LayerFE>&));
1060 };
1061
1062 OutputEnsureOutputLayerIfVisibleTest() {
1063 EXPECT_CALL(*mLayer, getLayerFE()).WillRepeatedly(Return(mLayerFE));
1064 EXPECT_CALL(*mLayer, getFEState()).WillRepeatedly(ReturnRef(mLayerFEState));
1065 EXPECT_CALL(*mLayer, editFEState()).WillRepeatedly(ReturnRef(mLayerFEState));
1066
1067 EXPECT_CALL(mOutput, belongsInOutput(mLayer.get())).WillRepeatedly(Return(true));
Lloyd Pique0a456232020-01-16 17:51:13 -08001068 EXPECT_CALL(mOutput, getOutputLayerCount()).WillRepeatedly(Return(1u));
Lloyd Piquefe0ee9e2019-11-22 16:30:30 -08001069 EXPECT_CALL(mOutput, getOutputLayerOrderedByZByIndex(0u))
1070 .WillRepeatedly(Return(&mOutputLayer));
1071
1072 EXPECT_CALL(mOutputLayer, getState()).WillRepeatedly(ReturnRef(mOutputLayerState));
1073 EXPECT_CALL(mOutputLayer, editState()).WillRepeatedly(ReturnRef(mOutputLayerState));
1074 EXPECT_CALL(mOutputLayer, getLayer()).WillRepeatedly(ReturnRef(*mLayer.get()));
1075
1076 mOutput.mState.bounds = Rect(0, 0, 200, 300);
1077 mOutput.mState.viewport = Rect(0, 0, 200, 300);
1078 mOutput.mState.transform = ui::Transform(TR_IDENT, 200, 300);
1079
1080 mLayerFEState.isVisible = true;
1081 mLayerFEState.isOpaque = true;
1082 mLayerFEState.contentDirty = true;
1083 mLayerFEState.geomLayerBounds = FloatRect{0, 0, 100, 200};
1084 mLayerFEState.geomLayerTransform = ui::Transform(TR_IDENT, 100, 200);
1085 mLayerFEState.transparentRegionHint = Region(Rect(0, 0, 100, 100));
1086
1087 mOutputLayerState.visibleRegion = Region(Rect(0, 0, 50, 200));
1088 mOutputLayerState.coveredRegion = Region(Rect(50, 0, 100, 200));
1089
1090 mGeomSnapshots.insert(mLayerFE);
1091 }
1092
1093 static const Region kEmptyRegion;
1094 static const Region kFullBoundsNoRotation;
1095 static const Region kRightHalfBoundsNoRotation;
1096 static const Region kLowerHalfBoundsNoRotation;
1097 static const Region kFullBounds90Rotation;
1098
1099 StrictMock<OutputPartialMock> mOutput;
1100 LayerFESet mGeomSnapshots;
1101 Output::CoverageState mCoverageState{mGeomSnapshots};
1102
1103 std::shared_ptr<mock::Layer> mLayer{new StrictMock<mock::Layer>()};
1104 sp<StrictMock<mock::LayerFE>> mLayerFE{new StrictMock<mock::LayerFE>()};
1105 LayerFECompositionState mLayerFEState;
1106 mock::OutputLayer mOutputLayer;
1107 impl::OutputLayerCompositionState mOutputLayerState;
1108};
1109
1110const Region OutputEnsureOutputLayerIfVisibleTest::kEmptyRegion = Region(Rect(0, 0, 0, 0));
1111const Region OutputEnsureOutputLayerIfVisibleTest::kFullBoundsNoRotation =
1112 Region(Rect(0, 0, 100, 200));
1113const Region OutputEnsureOutputLayerIfVisibleTest::kRightHalfBoundsNoRotation =
1114 Region(Rect(0, 100, 100, 200));
1115const Region OutputEnsureOutputLayerIfVisibleTest::kLowerHalfBoundsNoRotation =
1116 Region(Rect(50, 0, 100, 200));
1117const Region OutputEnsureOutputLayerIfVisibleTest::kFullBounds90Rotation =
1118 Region(Rect(0, 0, 200, 100));
1119
1120TEST_F(OutputEnsureOutputLayerIfVisibleTest, doesNothingIfNoLayerFE) {
1121 EXPECT_CALL(*mLayer, getLayerFE).WillOnce(Return(sp<LayerFE>()));
1122
1123 mOutput.ensureOutputLayerIfVisible(mLayer, mCoverageState);
1124}
1125
1126TEST_F(OutputEnsureOutputLayerIfVisibleTest, performsGeomLatchBeforeCheckingIfLayerBelongs) {
1127 EXPECT_CALL(mOutput, belongsInOutput(mLayer.get())).WillOnce(Return(false));
1128 EXPECT_CALL(*mLayerFE.get(),
1129 latchCompositionState(Ref(mLayerFEState),
1130 compositionengine::LayerFE::StateSubset::BasicGeometry));
1131
1132 mGeomSnapshots.clear();
1133
1134 mOutput.ensureOutputLayerIfVisible(mLayer, mCoverageState);
1135}
1136
1137TEST_F(OutputEnsureOutputLayerIfVisibleTest,
1138 skipsLatchIfAlreadyLatchedBeforeCheckingIfLayerBelongs) {
1139 EXPECT_CALL(mOutput, belongsInOutput(mLayer.get())).WillOnce(Return(false));
1140
1141 mOutput.ensureOutputLayerIfVisible(mLayer, mCoverageState);
1142}
1143
1144TEST_F(OutputEnsureOutputLayerIfVisibleTest, takesEarlyOutIfLayerNotVisible) {
1145 mLayerFEState.isVisible = false;
1146
1147 mOutput.ensureOutputLayerIfVisible(mLayer, mCoverageState);
1148}
1149
1150TEST_F(OutputEnsureOutputLayerIfVisibleTest, takesEarlyOutIfLayerHasEmptyVisibleRegion) {
1151 mLayerFEState.geomLayerBounds = FloatRect{0, 0, 0, 0};
1152
1153 mOutput.ensureOutputLayerIfVisible(mLayer, mCoverageState);
1154}
1155
1156TEST_F(OutputEnsureOutputLayerIfVisibleTest, takesNotSoEarlyOutifDrawRegionEmpty) {
1157 mOutput.mState.bounds = Rect(0, 0, 0, 0);
1158
1159 mOutput.ensureOutputLayerIfVisible(mLayer, mCoverageState);
1160}
1161
1162TEST_F(OutputEnsureOutputLayerIfVisibleTest,
1163 handlesCreatingOutputLayerForOpaqueDirtyNotRotatedLayer) {
1164 mLayerFEState.isOpaque = true;
1165 mLayerFEState.contentDirty = true;
1166 mLayerFEState.geomLayerTransform = ui::Transform(TR_IDENT, 100, 200);
1167
1168 EXPECT_CALL(mOutput, getOutputLayerCount()).WillOnce(Return(0u));
1169 EXPECT_CALL(mOutput, ensureOutputLayer(Eq(std::nullopt), Eq(mLayer), Eq(mLayerFE)))
1170 .WillOnce(Return(&mOutputLayer));
1171
1172 mOutput.ensureOutputLayerIfVisible(mLayer, mCoverageState);
1173
1174 EXPECT_THAT(mCoverageState.dirtyRegion, RegionEq(kFullBoundsNoRotation));
1175 EXPECT_THAT(mCoverageState.aboveCoveredLayers, RegionEq(kFullBoundsNoRotation));
1176 EXPECT_THAT(mCoverageState.aboveOpaqueLayers, RegionEq(kFullBoundsNoRotation));
1177
1178 EXPECT_THAT(mOutputLayerState.visibleRegion, RegionEq(kFullBoundsNoRotation));
1179 EXPECT_THAT(mOutputLayerState.visibleNonTransparentRegion, RegionEq(kFullBoundsNoRotation));
1180 EXPECT_THAT(mOutputLayerState.coveredRegion, RegionEq(kEmptyRegion));
1181 EXPECT_THAT(mOutputLayerState.outputSpaceVisibleRegion, RegionEq(kFullBoundsNoRotation));
1182}
1183
1184TEST_F(OutputEnsureOutputLayerIfVisibleTest,
1185 handlesUpdatingOutputLayerForOpaqueDirtyNotRotatedLayer) {
1186 mLayerFEState.isOpaque = true;
1187 mLayerFEState.contentDirty = true;
1188 mLayerFEState.geomLayerTransform = ui::Transform(TR_IDENT, 100, 200);
1189
1190 EXPECT_CALL(mOutput, ensureOutputLayer(Eq(0u), Eq(mLayer), Eq(mLayerFE)))
1191 .WillOnce(Return(&mOutputLayer));
1192
1193 mOutput.ensureOutputLayerIfVisible(mLayer, mCoverageState);
1194
1195 EXPECT_THAT(mCoverageState.dirtyRegion, RegionEq(kFullBoundsNoRotation));
1196 EXPECT_THAT(mCoverageState.aboveCoveredLayers, RegionEq(kFullBoundsNoRotation));
1197 EXPECT_THAT(mCoverageState.aboveOpaqueLayers, RegionEq(kFullBoundsNoRotation));
1198
1199 EXPECT_THAT(mOutputLayerState.visibleRegion, RegionEq(kFullBoundsNoRotation));
1200 EXPECT_THAT(mOutputLayerState.visibleNonTransparentRegion, RegionEq(kFullBoundsNoRotation));
1201 EXPECT_THAT(mOutputLayerState.coveredRegion, RegionEq(kEmptyRegion));
1202 EXPECT_THAT(mOutputLayerState.outputSpaceVisibleRegion, RegionEq(kFullBoundsNoRotation));
1203}
1204
1205TEST_F(OutputEnsureOutputLayerIfVisibleTest,
1206 handlesCreatingOutputLayerForTransparentDirtyNotRotatedLayer) {
1207 mLayerFEState.isOpaque = false;
1208 mLayerFEState.contentDirty = true;
1209 mLayerFEState.geomLayerTransform = ui::Transform(TR_IDENT, 100, 200);
1210
1211 EXPECT_CALL(mOutput, getOutputLayerCount()).WillOnce(Return(0u));
1212 EXPECT_CALL(mOutput, ensureOutputLayer(Eq(std::nullopt), Eq(mLayer), Eq(mLayerFE)))
1213 .WillOnce(Return(&mOutputLayer));
1214
1215 mOutput.ensureOutputLayerIfVisible(mLayer, mCoverageState);
1216
1217 EXPECT_THAT(mCoverageState.dirtyRegion, RegionEq(kFullBoundsNoRotation));
1218 EXPECT_THAT(mCoverageState.aboveCoveredLayers, RegionEq(kFullBoundsNoRotation));
1219 EXPECT_THAT(mCoverageState.aboveOpaqueLayers, RegionEq(kEmptyRegion));
1220
1221 EXPECT_THAT(mOutputLayerState.visibleRegion, RegionEq(kFullBoundsNoRotation));
1222 EXPECT_THAT(mOutputLayerState.visibleNonTransparentRegion,
1223 RegionEq(kRightHalfBoundsNoRotation));
1224 EXPECT_THAT(mOutputLayerState.coveredRegion, RegionEq(kEmptyRegion));
1225 EXPECT_THAT(mOutputLayerState.outputSpaceVisibleRegion, RegionEq(kFullBoundsNoRotation));
1226}
1227
1228TEST_F(OutputEnsureOutputLayerIfVisibleTest,
1229 handlesUpdatingOutputLayerForTransparentDirtyNotRotatedLayer) {
1230 mLayerFEState.isOpaque = false;
1231 mLayerFEState.contentDirty = true;
1232 mLayerFEState.geomLayerTransform = ui::Transform(TR_IDENT, 100, 200);
1233
1234 EXPECT_CALL(mOutput, ensureOutputLayer(Eq(0u), Eq(mLayer), Eq(mLayerFE)))
1235 .WillOnce(Return(&mOutputLayer));
1236
1237 mOutput.ensureOutputLayerIfVisible(mLayer, mCoverageState);
1238
1239 EXPECT_THAT(mCoverageState.dirtyRegion, RegionEq(kFullBoundsNoRotation));
1240 EXPECT_THAT(mCoverageState.aboveCoveredLayers, RegionEq(kFullBoundsNoRotation));
1241 EXPECT_THAT(mCoverageState.aboveOpaqueLayers, RegionEq(kEmptyRegion));
1242
1243 EXPECT_THAT(mOutputLayerState.visibleRegion, RegionEq(kFullBoundsNoRotation));
1244 EXPECT_THAT(mOutputLayerState.visibleNonTransparentRegion,
1245 RegionEq(kRightHalfBoundsNoRotation));
1246 EXPECT_THAT(mOutputLayerState.coveredRegion, RegionEq(kEmptyRegion));
1247 EXPECT_THAT(mOutputLayerState.outputSpaceVisibleRegion, RegionEq(kFullBoundsNoRotation));
1248}
1249
1250TEST_F(OutputEnsureOutputLayerIfVisibleTest,
1251 handlesCreatingOutputLayerForOpaqueNonDirtyNotRotatedLayer) {
1252 mLayerFEState.isOpaque = true;
1253 mLayerFEState.contentDirty = false;
1254 mLayerFEState.geomLayerTransform = ui::Transform(TR_IDENT, 100, 200);
1255
1256 EXPECT_CALL(mOutput, getOutputLayerCount()).WillOnce(Return(0u));
1257 EXPECT_CALL(mOutput, ensureOutputLayer(Eq(std::nullopt), Eq(mLayer), Eq(mLayerFE)))
1258 .WillOnce(Return(&mOutputLayer));
1259
1260 mOutput.ensureOutputLayerIfVisible(mLayer, mCoverageState);
1261
1262 EXPECT_THAT(mCoverageState.dirtyRegion, RegionEq(kFullBoundsNoRotation));
1263 EXPECT_THAT(mCoverageState.aboveCoveredLayers, RegionEq(kFullBoundsNoRotation));
1264 EXPECT_THAT(mCoverageState.aboveOpaqueLayers, RegionEq(kFullBoundsNoRotation));
1265
1266 EXPECT_THAT(mOutputLayerState.visibleRegion, RegionEq(kFullBoundsNoRotation));
1267 EXPECT_THAT(mOutputLayerState.visibleNonTransparentRegion, RegionEq(kFullBoundsNoRotation));
1268 EXPECT_THAT(mOutputLayerState.coveredRegion, RegionEq(kEmptyRegion));
1269 EXPECT_THAT(mOutputLayerState.outputSpaceVisibleRegion, RegionEq(kFullBoundsNoRotation));
1270}
1271
1272TEST_F(OutputEnsureOutputLayerIfVisibleTest,
1273 handlesUpdatingOutputLayerForOpaqueNonDirtyNotRotatedLayer) {
1274 mLayerFEState.isOpaque = true;
1275 mLayerFEState.contentDirty = false;
1276 mLayerFEState.geomLayerTransform = ui::Transform(TR_IDENT, 100, 200);
1277
1278 EXPECT_CALL(mOutput, ensureOutputLayer(Eq(0u), Eq(mLayer), Eq(mLayerFE)))
1279 .WillOnce(Return(&mOutputLayer));
1280
1281 mOutput.ensureOutputLayerIfVisible(mLayer, mCoverageState);
1282
1283 EXPECT_THAT(mCoverageState.dirtyRegion, RegionEq(kLowerHalfBoundsNoRotation));
1284 EXPECT_THAT(mCoverageState.aboveCoveredLayers, RegionEq(kFullBoundsNoRotation));
1285 EXPECT_THAT(mCoverageState.aboveOpaqueLayers, RegionEq(kFullBoundsNoRotation));
1286
1287 EXPECT_THAT(mOutputLayerState.visibleRegion, RegionEq(kFullBoundsNoRotation));
1288 EXPECT_THAT(mOutputLayerState.visibleNonTransparentRegion, RegionEq(kFullBoundsNoRotation));
1289 EXPECT_THAT(mOutputLayerState.coveredRegion, RegionEq(kEmptyRegion));
1290 EXPECT_THAT(mOutputLayerState.outputSpaceVisibleRegion, RegionEq(kFullBoundsNoRotation));
1291}
1292
1293TEST_F(OutputEnsureOutputLayerIfVisibleTest,
1294 handlesCreatingOutputLayerForOpaqueDirtyRotated90Layer) {
1295 mLayerFEState.isOpaque = true;
1296 mLayerFEState.contentDirty = true;
1297 mLayerFEState.geomLayerBounds = FloatRect{0, 0, 200, 100};
1298 mLayerFEState.geomLayerTransform = ui::Transform(TR_ROT_90, 100, 200);
1299 mOutputLayerState.visibleRegion = Region(Rect(0, 0, 100, 100));
1300 mOutputLayerState.coveredRegion = Region(Rect(100, 0, 200, 100));
1301
1302 EXPECT_CALL(mOutput, getOutputLayerCount()).WillOnce(Return(0u));
1303 EXPECT_CALL(mOutput, ensureOutputLayer(Eq(std::nullopt), Eq(mLayer), Eq(mLayerFE)))
1304 .WillOnce(Return(&mOutputLayer));
1305
1306 mOutput.ensureOutputLayerIfVisible(mLayer, mCoverageState);
1307
1308 EXPECT_THAT(mCoverageState.dirtyRegion, RegionEq(kFullBoundsNoRotation));
1309 EXPECT_THAT(mCoverageState.aboveCoveredLayers, RegionEq(kFullBoundsNoRotation));
1310 EXPECT_THAT(mCoverageState.aboveOpaqueLayers, RegionEq(kFullBoundsNoRotation));
1311
1312 EXPECT_THAT(mOutputLayerState.visibleRegion, RegionEq(kFullBoundsNoRotation));
1313 EXPECT_THAT(mOutputLayerState.visibleNonTransparentRegion, RegionEq(kFullBoundsNoRotation));
1314 EXPECT_THAT(mOutputLayerState.coveredRegion, RegionEq(kEmptyRegion));
1315 EXPECT_THAT(mOutputLayerState.outputSpaceVisibleRegion, RegionEq(kFullBoundsNoRotation));
1316}
1317
1318TEST_F(OutputEnsureOutputLayerIfVisibleTest,
1319 handlesUpdatingOutputLayerForOpaqueDirtyRotated90Layer) {
1320 mLayerFEState.isOpaque = true;
1321 mLayerFEState.contentDirty = true;
1322 mLayerFEState.geomLayerBounds = FloatRect{0, 0, 200, 100};
1323 mLayerFEState.geomLayerTransform = ui::Transform(TR_ROT_90, 100, 200);
1324 mOutputLayerState.visibleRegion = Region(Rect(0, 0, 100, 100));
1325 mOutputLayerState.coveredRegion = Region(Rect(100, 0, 200, 100));
1326
1327 EXPECT_CALL(mOutput, ensureOutputLayer(Eq(0u), Eq(mLayer), Eq(mLayerFE)))
1328 .WillOnce(Return(&mOutputLayer));
1329
1330 mOutput.ensureOutputLayerIfVisible(mLayer, mCoverageState);
1331
1332 EXPECT_THAT(mCoverageState.dirtyRegion, RegionEq(kFullBoundsNoRotation));
1333 EXPECT_THAT(mCoverageState.aboveCoveredLayers, RegionEq(kFullBoundsNoRotation));
1334 EXPECT_THAT(mCoverageState.aboveOpaqueLayers, RegionEq(kFullBoundsNoRotation));
1335
1336 EXPECT_THAT(mOutputLayerState.visibleRegion, RegionEq(kFullBoundsNoRotation));
1337 EXPECT_THAT(mOutputLayerState.visibleNonTransparentRegion, RegionEq(kFullBoundsNoRotation));
1338 EXPECT_THAT(mOutputLayerState.coveredRegion, RegionEq(kEmptyRegion));
1339 EXPECT_THAT(mOutputLayerState.outputSpaceVisibleRegion, RegionEq(kFullBoundsNoRotation));
1340}
1341
1342TEST_F(OutputEnsureOutputLayerIfVisibleTest,
1343 handlesCreatingOutputLayerForOpaqueDirtyNotRotatedLayerRotatedOutput) {
1344 mLayerFEState.isOpaque = true;
1345 mLayerFEState.contentDirty = true;
1346 mLayerFEState.geomLayerTransform = ui::Transform(TR_IDENT, 100, 200);
1347
1348 mOutput.mState.viewport = Rect(0, 0, 300, 200);
1349 mOutput.mState.transform = ui::Transform(TR_ROT_90, 200, 300);
1350
1351 EXPECT_CALL(mOutput, getOutputLayerCount()).WillOnce(Return(0u));
1352 EXPECT_CALL(mOutput, ensureOutputLayer(Eq(std::nullopt), Eq(mLayer), Eq(mLayerFE)))
1353 .WillOnce(Return(&mOutputLayer));
1354
1355 mOutput.ensureOutputLayerIfVisible(mLayer, mCoverageState);
1356
1357 EXPECT_THAT(mCoverageState.dirtyRegion, RegionEq(kFullBoundsNoRotation));
1358 EXPECT_THAT(mCoverageState.aboveCoveredLayers, RegionEq(kFullBoundsNoRotation));
1359 EXPECT_THAT(mCoverageState.aboveOpaqueLayers, RegionEq(kFullBoundsNoRotation));
1360
1361 EXPECT_THAT(mOutputLayerState.visibleRegion, RegionEq(kFullBoundsNoRotation));
1362 EXPECT_THAT(mOutputLayerState.visibleNonTransparentRegion, RegionEq(kFullBoundsNoRotation));
1363 EXPECT_THAT(mOutputLayerState.coveredRegion, RegionEq(kEmptyRegion));
1364 EXPECT_THAT(mOutputLayerState.outputSpaceVisibleRegion, RegionEq(kFullBounds90Rotation));
1365}
1366
1367TEST_F(OutputEnsureOutputLayerIfVisibleTest,
1368 handlesUpdatingOutputLayerForOpaqueDirtyNotRotatedLayerRotatedOutput) {
1369 mLayerFEState.isOpaque = true;
1370 mLayerFEState.contentDirty = true;
1371 mLayerFEState.geomLayerTransform = ui::Transform(TR_IDENT, 100, 200);
1372
1373 mOutput.mState.viewport = Rect(0, 0, 300, 200);
1374 mOutput.mState.transform = ui::Transform(TR_ROT_90, 200, 300);
1375
1376 EXPECT_CALL(mOutput, ensureOutputLayer(Eq(0u), Eq(mLayer), Eq(mLayerFE)))
1377 .WillOnce(Return(&mOutputLayer));
1378
1379 mOutput.ensureOutputLayerIfVisible(mLayer, mCoverageState);
1380
1381 EXPECT_THAT(mCoverageState.dirtyRegion, RegionEq(kFullBoundsNoRotation));
1382 EXPECT_THAT(mCoverageState.aboveCoveredLayers, RegionEq(kFullBoundsNoRotation));
1383 EXPECT_THAT(mCoverageState.aboveOpaqueLayers, RegionEq(kFullBoundsNoRotation));
1384
1385 EXPECT_THAT(mOutputLayerState.visibleRegion, RegionEq(kFullBoundsNoRotation));
1386 EXPECT_THAT(mOutputLayerState.visibleNonTransparentRegion, RegionEq(kFullBoundsNoRotation));
1387 EXPECT_THAT(mOutputLayerState.coveredRegion, RegionEq(kEmptyRegion));
1388 EXPECT_THAT(mOutputLayerState.outputSpaceVisibleRegion, RegionEq(kFullBounds90Rotation));
1389}
1390
1391TEST_F(OutputEnsureOutputLayerIfVisibleTest,
1392 handlesCreatingOutputLayerForOpaqueDirtyArbitraryTransformLayer) {
1393 ui::Transform arbitraryTransform;
1394 arbitraryTransform.set(1, 1, -1, 1);
1395 arbitraryTransform.set(0, 100);
1396
1397 mLayerFEState.isOpaque = true;
1398 mLayerFEState.contentDirty = true;
1399 mLayerFEState.geomLayerBounds = FloatRect{0, 0, 100, 200};
1400 mLayerFEState.geomLayerTransform = arbitraryTransform;
1401
1402 EXPECT_CALL(mOutput, getOutputLayerCount()).WillOnce(Return(0u));
1403 EXPECT_CALL(mOutput, ensureOutputLayer(Eq(std::nullopt), Eq(mLayer), Eq(mLayerFE)))
1404 .WillOnce(Return(&mOutputLayer));
1405
1406 mOutput.ensureOutputLayerIfVisible(mLayer, mCoverageState);
1407
1408 const Region kRegion = Region(Rect(0, 0, 300, 300));
1409 const Region kRegionClipped = Region(Rect(0, 0, 200, 300));
1410
1411 EXPECT_THAT(mCoverageState.dirtyRegion, RegionEq(kRegion));
1412 EXPECT_THAT(mCoverageState.aboveCoveredLayers, RegionEq(kRegion));
1413 EXPECT_THAT(mCoverageState.aboveOpaqueLayers, RegionEq(kEmptyRegion));
1414
1415 EXPECT_THAT(mOutputLayerState.visibleRegion, RegionEq(kRegion));
1416 EXPECT_THAT(mOutputLayerState.visibleNonTransparentRegion, RegionEq(kRegion));
1417 EXPECT_THAT(mOutputLayerState.coveredRegion, RegionEq(kEmptyRegion));
1418 EXPECT_THAT(mOutputLayerState.outputSpaceVisibleRegion, RegionEq(kRegionClipped));
1419}
1420
1421TEST_F(OutputEnsureOutputLayerIfVisibleTest, coverageAccumulatesTest) {
1422 mLayerFEState.isOpaque = false;
1423 mLayerFEState.contentDirty = true;
1424 mLayerFEState.geomLayerTransform = ui::Transform(TR_IDENT, 100, 200);
1425
1426 mCoverageState.dirtyRegion = Region(Rect(0, 0, 500, 500));
1427 mCoverageState.aboveCoveredLayers = Region(Rect(50, 0, 150, 200));
1428 mCoverageState.aboveOpaqueLayers = Region(Rect(50, 0, 150, 200));
1429
1430 EXPECT_CALL(mOutput, ensureOutputLayer(Eq(0u), Eq(mLayer), Eq(mLayerFE)))
1431 .WillOnce(Return(&mOutputLayer));
1432
1433 mOutput.ensureOutputLayerIfVisible(mLayer, mCoverageState);
1434
1435 const Region kExpectedDirtyRegion = Region(Rect(0, 0, 500, 500));
1436 const Region kExpectedAboveCoveredRegion = Region(Rect(0, 0, 150, 200));
1437 const Region kExpectedAboveOpaqueRegion = Region(Rect(50, 0, 150, 200));
1438 const Region kExpectedLayerVisibleRegion = Region(Rect(0, 0, 50, 200));
1439 const Region kExpectedLayerCoveredRegion = Region(Rect(50, 0, 100, 200));
1440 const Region kExpectedLayerVisibleNonTransparentRegion = Region(Rect(0, 100, 50, 200));
1441
1442 EXPECT_THAT(mCoverageState.dirtyRegion, RegionEq(kExpectedDirtyRegion));
1443 EXPECT_THAT(mCoverageState.aboveCoveredLayers, RegionEq(kExpectedAboveCoveredRegion));
1444 EXPECT_THAT(mCoverageState.aboveOpaqueLayers, RegionEq(kExpectedAboveOpaqueRegion));
1445
1446 EXPECT_THAT(mOutputLayerState.visibleRegion, RegionEq(kExpectedLayerVisibleRegion));
1447 EXPECT_THAT(mOutputLayerState.visibleNonTransparentRegion,
1448 RegionEq(kExpectedLayerVisibleNonTransparentRegion));
1449 EXPECT_THAT(mOutputLayerState.coveredRegion, RegionEq(kExpectedLayerCoveredRegion));
1450 EXPECT_THAT(mOutputLayerState.outputSpaceVisibleRegion, RegionEq(kExpectedLayerVisibleRegion));
1451}
Lloyd Piqueb62cebc2019-11-20 18:31:52 -08001452
Vishnu Naira483b4a2019-12-12 15:07:52 -08001453TEST_F(OutputEnsureOutputLayerIfVisibleTest, coverageAccumulatesWithShadowsTest) {
1454 ui::Transform translate;
1455 translate.set(50, 50);
1456 mLayerFEState.geomLayerTransform = translate;
1457 mLayerFEState.shadowRadius = 10.0f;
1458
1459 mCoverageState.dirtyRegion = Region(Rect(0, 0, 500, 500));
1460 // half of the layer including the casting shadow is covered and opaque
1461 mCoverageState.aboveCoveredLayers = Region(Rect(40, 40, 100, 260));
1462 mCoverageState.aboveOpaqueLayers = Region(Rect(40, 40, 100, 260));
1463
1464 EXPECT_CALL(mOutput, ensureOutputLayer(Eq(0u), Eq(mLayer), Eq(mLayerFE)))
1465 .WillOnce(Return(&mOutputLayer));
1466
1467 mOutput.ensureOutputLayerIfVisible(mLayer, mCoverageState);
1468
1469 const Region kExpectedDirtyRegion = Region(Rect(0, 0, 500, 500));
1470 const Region kExpectedAboveCoveredRegion = Region(Rect(40, 40, 160, 260));
1471 // add starting opaque region to the opaque half of the casting layer bounds
1472 const Region kExpectedAboveOpaqueRegion =
1473 Region(Rect(40, 40, 100, 260)).orSelf(Rect(100, 50, 150, 250));
1474 const Region kExpectedLayerVisibleRegion = Region(Rect(100, 40, 160, 260));
1475 const Region kExpectedoutputSpaceLayerVisibleRegion = Region(Rect(100, 50, 150, 250));
1476 const Region kExpectedLayerCoveredRegion = Region(Rect(40, 40, 100, 260));
1477 const Region kExpectedLayerVisibleNonTransparentRegion = Region(Rect(100, 40, 160, 260));
1478 const Region kExpectedLayerShadowRegion =
1479 Region(Rect(40, 40, 160, 260)).subtractSelf(Rect(50, 50, 150, 250));
1480
1481 EXPECT_THAT(mCoverageState.dirtyRegion, RegionEq(kExpectedDirtyRegion));
1482 EXPECT_THAT(mCoverageState.aboveCoveredLayers, RegionEq(kExpectedAboveCoveredRegion));
1483 EXPECT_THAT(mCoverageState.aboveOpaqueLayers, RegionEq(kExpectedAboveOpaqueRegion));
1484
1485 EXPECT_THAT(mOutputLayerState.visibleRegion, RegionEq(kExpectedLayerVisibleRegion));
1486 EXPECT_THAT(mOutputLayerState.visibleNonTransparentRegion,
1487 RegionEq(kExpectedLayerVisibleNonTransparentRegion));
1488 EXPECT_THAT(mOutputLayerState.coveredRegion, RegionEq(kExpectedLayerCoveredRegion));
1489 EXPECT_THAT(mOutputLayerState.outputSpaceVisibleRegion,
1490 RegionEq(kExpectedoutputSpaceLayerVisibleRegion));
1491 EXPECT_THAT(mOutputLayerState.shadowRegion, RegionEq(kExpectedLayerShadowRegion));
1492 EXPECT_FALSE(kExpectedLayerVisibleRegion.subtract(kExpectedLayerShadowRegion).isEmpty());
1493}
1494
1495TEST_F(OutputEnsureOutputLayerIfVisibleTest, shadowRegionOnlyTest) {
1496 ui::Transform translate;
1497 translate.set(50, 50);
1498 mLayerFEState.geomLayerTransform = translate;
1499 mLayerFEState.shadowRadius = 10.0f;
1500
1501 mCoverageState.dirtyRegion = Region(Rect(0, 0, 500, 500));
1502 // Casting layer is covered by an opaque region leaving only part of its shadow to be drawn
1503 mCoverageState.aboveCoveredLayers = Region(Rect(40, 40, 150, 260));
1504 mCoverageState.aboveOpaqueLayers = Region(Rect(40, 40, 150, 260));
1505
1506 EXPECT_CALL(mOutput, ensureOutputLayer(Eq(0u), Eq(mLayer), Eq(mLayerFE)))
1507 .WillOnce(Return(&mOutputLayer));
1508
1509 mOutput.ensureOutputLayerIfVisible(mLayer, mCoverageState);
1510
1511 const Region kExpectedLayerVisibleRegion = Region(Rect(150, 40, 160, 260));
1512 const Region kExpectedLayerShadowRegion =
1513 Region(Rect(40, 40, 160, 260)).subtractSelf(Rect(50, 50, 150, 250));
1514
1515 EXPECT_THAT(mOutputLayerState.visibleRegion, RegionEq(kExpectedLayerVisibleRegion));
1516 EXPECT_THAT(mOutputLayerState.shadowRegion, RegionEq(kExpectedLayerShadowRegion));
1517 EXPECT_TRUE(kExpectedLayerVisibleRegion.subtract(kExpectedLayerShadowRegion).isEmpty());
1518}
1519
1520TEST_F(OutputEnsureOutputLayerIfVisibleTest, takesNotSoEarlyOutifLayerWithShadowIsCovered) {
1521 ui::Transform translate;
1522 translate.set(50, 50);
1523 mLayerFEState.geomLayerTransform = translate;
1524 mLayerFEState.shadowRadius = 10.0f;
1525
1526 mCoverageState.dirtyRegion = Region(Rect(0, 0, 500, 500));
1527 // Casting layer and its shadows are covered by an opaque region
1528 mCoverageState.aboveCoveredLayers = Region(Rect(40, 40, 160, 260));
1529 mCoverageState.aboveOpaqueLayers = Region(Rect(40, 40, 160, 260));
1530
1531 mOutput.ensureOutputLayerIfVisible(mLayer, mCoverageState);
1532}
1533
Lloyd Piqueb62cebc2019-11-20 18:31:52 -08001534/*
Lloyd Piquefaa3f192019-11-14 14:05:09 -08001535 * Output::present()
1536 */
1537
1538struct OutputPresentTest : public testing::Test {
1539 struct OutputPartialMock : public OutputPartialMockBase {
Lloyd Pique739afaf2019-11-21 16:40:05 -08001540 // Sets up the helper functions called by the function under test to use
1541 // mock implementations.
Lloyd Piquefaa3f192019-11-14 14:05:09 -08001542 MOCK_METHOD1(updateColorProfile, void(const compositionengine::CompositionRefreshArgs&));
1543 MOCK_METHOD1(updateAndWriteCompositionState,
1544 void(const compositionengine::CompositionRefreshArgs&));
1545 MOCK_METHOD1(setColorTransform, void(const compositionengine::CompositionRefreshArgs&));
1546 MOCK_METHOD0(beginFrame, void());
1547 MOCK_METHOD0(prepareFrame, void());
1548 MOCK_METHOD1(devOptRepaintFlash, void(const compositionengine::CompositionRefreshArgs&));
1549 MOCK_METHOD1(finishFrame, void(const compositionengine::CompositionRefreshArgs&));
1550 MOCK_METHOD0(postFramebuffer, void());
1551 };
1552
1553 StrictMock<OutputPartialMock> mOutput;
1554};
1555
1556TEST_F(OutputPresentTest, justInvokesChildFunctionsInSequence) {
1557 CompositionRefreshArgs args;
1558
1559 InSequence seq;
1560 EXPECT_CALL(mOutput, updateColorProfile(Ref(args)));
1561 EXPECT_CALL(mOutput, updateAndWriteCompositionState(Ref(args)));
1562 EXPECT_CALL(mOutput, setColorTransform(Ref(args)));
1563 EXPECT_CALL(mOutput, beginFrame());
1564 EXPECT_CALL(mOutput, prepareFrame());
1565 EXPECT_CALL(mOutput, devOptRepaintFlash(Ref(args)));
1566 EXPECT_CALL(mOutput, finishFrame(Ref(args)));
1567 EXPECT_CALL(mOutput, postFramebuffer());
1568
1569 mOutput.present(args);
1570}
1571
1572/*
1573 * Output::updateColorProfile()
1574 */
1575
Lloyd Pique17ca7422019-11-14 14:24:10 -08001576struct OutputUpdateColorProfileTest : public testing::Test {
1577 using TestType = OutputUpdateColorProfileTest;
1578
1579 struct OutputPartialMock : public OutputPartialMockBase {
Lloyd Pique739afaf2019-11-21 16:40:05 -08001580 // Sets up the helper functions called by the function under test to use
1581 // mock implementations.
Lloyd Pique17ca7422019-11-14 14:24:10 -08001582 MOCK_METHOD1(setColorProfile, void(const ColorProfile&));
1583 };
1584
1585 struct Layer {
1586 Layer() {
1587 EXPECT_CALL(mOutputLayer, getLayer()).WillRepeatedly(ReturnRef(mLayer));
1588 EXPECT_CALL(mOutputLayer, getLayerFE()).WillRepeatedly(ReturnRef(mLayerFE));
1589 EXPECT_CALL(mLayer, getFEState()).WillRepeatedly(ReturnRef(mLayerFEState));
1590 }
1591
1592 StrictMock<mock::OutputLayer> mOutputLayer;
1593 StrictMock<mock::Layer> mLayer;
1594 StrictMock<mock::LayerFE> mLayerFE;
1595 LayerFECompositionState mLayerFEState;
1596 };
1597
1598 OutputUpdateColorProfileTest() {
1599 mOutput.setDisplayColorProfileForTest(
1600 std::unique_ptr<DisplayColorProfile>(mDisplayColorProfile));
1601 mOutput.setRenderSurfaceForTest(std::unique_ptr<RenderSurface>(mRenderSurface));
1602
1603 EXPECT_CALL(mOutput, getOutputLayerOrderedByZByIndex(0))
1604 .WillRepeatedly(Return(&mLayer1.mOutputLayer));
1605 EXPECT_CALL(mOutput, getOutputLayerOrderedByZByIndex(1))
1606 .WillRepeatedly(Return(&mLayer2.mOutputLayer));
1607 EXPECT_CALL(mOutput, getOutputLayerOrderedByZByIndex(2))
1608 .WillRepeatedly(Return(&mLayer3.mOutputLayer));
1609 }
1610
1611 struct ExecuteState : public CallOrderStateMachineHelper<TestType, ExecuteState> {
1612 void execute() { getInstance()->mOutput.updateColorProfile(getInstance()->mRefreshArgs); }
1613 };
1614
1615 mock::DisplayColorProfile* mDisplayColorProfile = new StrictMock<mock::DisplayColorProfile>();
1616 mock::RenderSurface* mRenderSurface = new StrictMock<mock::RenderSurface>();
1617 StrictMock<OutputPartialMock> mOutput;
1618
1619 Layer mLayer1;
1620 Layer mLayer2;
1621 Layer mLayer3;
1622
1623 CompositionRefreshArgs mRefreshArgs;
1624};
1625
1626// TODO(b/144522012): Refactor Output::updateColorProfile and the related code
1627// to make it easier to write unit tests.
1628
1629TEST_F(OutputUpdateColorProfileTest, setsAColorProfileWhenUnmanaged) {
1630 // When the outputColorSetting is set to kUnmanaged, the implementation sets
1631 // a simple default color profile without looking at anything else.
1632
Lloyd Pique0a456232020-01-16 17:51:13 -08001633 EXPECT_CALL(mOutput, getOutputLayerCount()).WillRepeatedly(Return(3u));
Lloyd Pique17ca7422019-11-14 14:24:10 -08001634 EXPECT_CALL(mOutput,
1635 setColorProfile(ColorProfileEq(
1636 ColorProfile{ui::ColorMode::NATIVE, ui::Dataspace::UNKNOWN,
1637 ui::RenderIntent::COLORIMETRIC, ui::Dataspace::UNKNOWN})));
1638
1639 mRefreshArgs.outputColorSetting = OutputColorSetting::kUnmanaged;
1640 mRefreshArgs.colorSpaceAgnosticDataspace = ui::Dataspace::UNKNOWN;
1641
1642 mOutput.updateColorProfile(mRefreshArgs);
1643}
1644
1645struct OutputUpdateColorProfileTest_GetBestColorModeResultBecomesSetProfile
1646 : public OutputUpdateColorProfileTest {
1647 OutputUpdateColorProfileTest_GetBestColorModeResultBecomesSetProfile() {
Lloyd Pique0a456232020-01-16 17:51:13 -08001648 EXPECT_CALL(mOutput, getOutputLayerCount()).WillRepeatedly(Return(0u));
Lloyd Pique17ca7422019-11-14 14:24:10 -08001649 mRefreshArgs.outputColorSetting = OutputColorSetting::kEnhanced;
1650 mRefreshArgs.colorSpaceAgnosticDataspace = ui::Dataspace::UNKNOWN;
1651 }
1652
1653 struct ExpectBestColorModeCallResultUsedToSetColorProfileState
1654 : public CallOrderStateMachineHelper<
1655 TestType, ExpectBestColorModeCallResultUsedToSetColorProfileState> {
1656 [[nodiscard]] auto expectBestColorModeCallResultUsedToSetColorProfile(
1657 ui::ColorMode colorMode, ui::Dataspace dataspace, ui::RenderIntent renderIntent) {
1658 EXPECT_CALL(*getInstance()->mDisplayColorProfile,
1659 getBestColorMode(ui::Dataspace::V0_SRGB, ui::RenderIntent::ENHANCE, _, _,
1660 _))
1661 .WillOnce(DoAll(SetArgPointee<2>(dataspace), SetArgPointee<3>(colorMode),
1662 SetArgPointee<4>(renderIntent)));
1663 EXPECT_CALL(getInstance()->mOutput,
1664 setColorProfile(
1665 ColorProfileEq(ColorProfile{colorMode, dataspace, renderIntent,
1666 ui::Dataspace::UNKNOWN})));
1667 return nextState<ExecuteState>();
1668 }
1669 };
1670
1671 // Call this member function to start using the mini-DSL defined above.
1672 [[nodiscard]] auto verify() {
1673 return ExpectBestColorModeCallResultUsedToSetColorProfileState::make(this);
1674 }
1675};
1676
1677TEST_F(OutputUpdateColorProfileTest_GetBestColorModeResultBecomesSetProfile,
1678 Native_Unknown_Colorimetric_Set) {
1679 verify().expectBestColorModeCallResultUsedToSetColorProfile(ui::ColorMode::NATIVE,
1680 ui::Dataspace::UNKNOWN,
1681 ui::RenderIntent::COLORIMETRIC)
1682 .execute();
1683}
1684
1685TEST_F(OutputUpdateColorProfileTest_GetBestColorModeResultBecomesSetProfile,
1686 DisplayP3_DisplayP3_Enhance_Set) {
1687 verify().expectBestColorModeCallResultUsedToSetColorProfile(ui::ColorMode::DISPLAY_P3,
1688 ui::Dataspace::DISPLAY_P3,
1689 ui::RenderIntent::ENHANCE)
1690 .execute();
1691}
1692
1693struct OutputUpdateColorProfileTest_ColorSpaceAgnosticeDataspaceAffectsSetColorProfile
1694 : public OutputUpdateColorProfileTest {
1695 OutputUpdateColorProfileTest_ColorSpaceAgnosticeDataspaceAffectsSetColorProfile() {
Lloyd Pique0a456232020-01-16 17:51:13 -08001696 EXPECT_CALL(mOutput, getOutputLayerCount()).WillRepeatedly(Return(0u));
Lloyd Pique17ca7422019-11-14 14:24:10 -08001697 EXPECT_CALL(*mDisplayColorProfile,
1698 getBestColorMode(ui::Dataspace::V0_SRGB, ui::RenderIntent::ENHANCE, _, _, _))
1699 .WillRepeatedly(DoAll(SetArgPointee<2>(ui::Dataspace::UNKNOWN),
1700 SetArgPointee<3>(ui::ColorMode::NATIVE),
1701 SetArgPointee<4>(ui::RenderIntent::COLORIMETRIC)));
1702 mRefreshArgs.outputColorSetting = OutputColorSetting::kEnhanced;
1703 }
1704
1705 struct IfColorSpaceAgnosticDataspaceSetToState
1706 : public CallOrderStateMachineHelper<TestType, IfColorSpaceAgnosticDataspaceSetToState> {
1707 [[nodiscard]] auto ifColorSpaceAgnosticDataspaceSetTo(ui::Dataspace dataspace) {
1708 getInstance()->mRefreshArgs.colorSpaceAgnosticDataspace = dataspace;
1709 return nextState<ThenExpectSetColorProfileCallUsesColorSpaceAgnosticDataspaceState>();
1710 }
1711 };
1712
1713 struct ThenExpectSetColorProfileCallUsesColorSpaceAgnosticDataspaceState
1714 : public CallOrderStateMachineHelper<
1715 TestType, ThenExpectSetColorProfileCallUsesColorSpaceAgnosticDataspaceState> {
1716 [[nodiscard]] auto thenExpectSetColorProfileCallUsesColorSpaceAgnosticDataspace(
1717 ui::Dataspace dataspace) {
1718 EXPECT_CALL(getInstance()->mOutput,
1719 setColorProfile(ColorProfileEq(
1720 ColorProfile{ui::ColorMode::NATIVE, ui::Dataspace::UNKNOWN,
1721 ui::RenderIntent::COLORIMETRIC, dataspace})));
1722 return nextState<ExecuteState>();
1723 }
1724 };
1725
1726 // Call this member function to start using the mini-DSL defined above.
1727 [[nodiscard]] auto verify() { return IfColorSpaceAgnosticDataspaceSetToState::make(this); }
1728};
1729
1730TEST_F(OutputUpdateColorProfileTest_ColorSpaceAgnosticeDataspaceAffectsSetColorProfile, DisplayP3) {
1731 verify().ifColorSpaceAgnosticDataspaceSetTo(ui::Dataspace::DISPLAY_P3)
1732 .thenExpectSetColorProfileCallUsesColorSpaceAgnosticDataspace(ui::Dataspace::DISPLAY_P3)
1733 .execute();
1734}
1735
1736TEST_F(OutputUpdateColorProfileTest_ColorSpaceAgnosticeDataspaceAffectsSetColorProfile, V0_SRGB) {
1737 verify().ifColorSpaceAgnosticDataspaceSetTo(ui::Dataspace::V0_SRGB)
1738 .thenExpectSetColorProfileCallUsesColorSpaceAgnosticDataspace(ui::Dataspace::V0_SRGB)
1739 .execute();
1740}
1741
1742struct OutputUpdateColorProfileTest_TopmostLayerPreferenceSetsOutputPreference
1743 : public OutputUpdateColorProfileTest {
1744 // Internally the implementation looks through the dataspaces of all the
1745 // visible layers. The topmost one that also has an actual dataspace
1746 // preference set is used to drive subsequent choices.
1747
1748 OutputUpdateColorProfileTest_TopmostLayerPreferenceSetsOutputPreference() {
1749 mRefreshArgs.outputColorSetting = OutputColorSetting::kEnhanced;
1750 mRefreshArgs.colorSpaceAgnosticDataspace = ui::Dataspace::UNKNOWN;
1751
Lloyd Pique0a456232020-01-16 17:51:13 -08001752 EXPECT_CALL(mOutput, getOutputLayerCount()).WillRepeatedly(Return(3u));
Lloyd Pique17ca7422019-11-14 14:24:10 -08001753 EXPECT_CALL(mOutput, setColorProfile(_)).WillRepeatedly(Return());
1754 }
1755
1756 struct IfTopLayerDataspaceState
1757 : public CallOrderStateMachineHelper<TestType, IfTopLayerDataspaceState> {
1758 [[nodiscard]] auto ifTopLayerIs(ui::Dataspace dataspace) {
1759 getInstance()->mLayer3.mLayerFEState.dataspace = dataspace;
1760 return nextState<AndIfMiddleLayerDataspaceState>();
1761 }
1762 [[nodiscard]] auto ifTopLayerHasNoPreference() {
1763 return ifTopLayerIs(ui::Dataspace::UNKNOWN);
1764 }
1765 };
1766
1767 struct AndIfMiddleLayerDataspaceState
1768 : public CallOrderStateMachineHelper<TestType, AndIfMiddleLayerDataspaceState> {
1769 [[nodiscard]] auto andIfMiddleLayerIs(ui::Dataspace dataspace) {
1770 getInstance()->mLayer2.mLayerFEState.dataspace = dataspace;
1771 return nextState<AndIfBottomLayerDataspaceState>();
1772 }
1773 [[nodiscard]] auto andIfMiddleLayerHasNoPreference() {
1774 return andIfMiddleLayerIs(ui::Dataspace::UNKNOWN);
1775 }
1776 };
1777
1778 struct AndIfBottomLayerDataspaceState
1779 : public CallOrderStateMachineHelper<TestType, AndIfBottomLayerDataspaceState> {
1780 [[nodiscard]] auto andIfBottomLayerIs(ui::Dataspace dataspace) {
1781 getInstance()->mLayer1.mLayerFEState.dataspace = dataspace;
1782 return nextState<ThenExpectBestColorModeCallUsesState>();
1783 }
1784 [[nodiscard]] auto andIfBottomLayerHasNoPreference() {
1785 return andIfBottomLayerIs(ui::Dataspace::UNKNOWN);
1786 }
1787 };
1788
1789 struct ThenExpectBestColorModeCallUsesState
1790 : public CallOrderStateMachineHelper<TestType, ThenExpectBestColorModeCallUsesState> {
1791 [[nodiscard]] auto thenExpectBestColorModeCallUses(ui::Dataspace dataspace) {
1792 EXPECT_CALL(*getInstance()->mDisplayColorProfile,
1793 getBestColorMode(dataspace, _, _, _, _));
1794 return nextState<ExecuteState>();
1795 }
1796 };
1797
1798 // Call this member function to start using the mini-DSL defined above.
1799 [[nodiscard]] auto verify() { return IfTopLayerDataspaceState::make(this); }
1800};
1801
1802TEST_F(OutputUpdateColorProfileTest_TopmostLayerPreferenceSetsOutputPreference,
1803 noStrongLayerPrefenceUses_V0_SRGB) {
1804 // If none of the layers indicate a preference, then V0_SRGB is the
1805 // preferred choice (subject to additional checks).
1806 verify().ifTopLayerHasNoPreference()
1807 .andIfMiddleLayerHasNoPreference()
1808 .andIfBottomLayerHasNoPreference()
1809 .thenExpectBestColorModeCallUses(ui::Dataspace::V0_SRGB)
1810 .execute();
1811}
1812
1813TEST_F(OutputUpdateColorProfileTest_TopmostLayerPreferenceSetsOutputPreference,
1814 ifTopmostUses_DisplayP3_Then_DisplayP3_Chosen) {
1815 // If only the topmost layer has a preference, then that is what is chosen.
1816 verify().ifTopLayerIs(ui::Dataspace::DISPLAY_P3)
1817 .andIfMiddleLayerHasNoPreference()
1818 .andIfBottomLayerHasNoPreference()
1819 .thenExpectBestColorModeCallUses(ui::Dataspace::DISPLAY_P3)
1820 .execute();
1821}
1822
1823TEST_F(OutputUpdateColorProfileTest_TopmostLayerPreferenceSetsOutputPreference,
1824 ifMiddleUses_DisplayP3_Then_DisplayP3_Chosen) {
1825 // If only the middle layer has a preference, that that is what is chosen.
1826 verify().ifTopLayerHasNoPreference()
1827 .andIfMiddleLayerIs(ui::Dataspace::DISPLAY_P3)
1828 .andIfBottomLayerHasNoPreference()
1829 .thenExpectBestColorModeCallUses(ui::Dataspace::DISPLAY_P3)
1830 .execute();
1831}
1832
1833TEST_F(OutputUpdateColorProfileTest_TopmostLayerPreferenceSetsOutputPreference,
1834 ifBottomUses_DisplayP3_Then_DisplayP3_Chosen) {
1835 // If only the middle layer has a preference, that that is what is chosen.
1836 verify().ifTopLayerHasNoPreference()
1837 .andIfMiddleLayerHasNoPreference()
1838 .andIfBottomLayerIs(ui::Dataspace::DISPLAY_P3)
1839 .thenExpectBestColorModeCallUses(ui::Dataspace::DISPLAY_P3)
1840 .execute();
1841}
1842
1843TEST_F(OutputUpdateColorProfileTest_TopmostLayerPreferenceSetsOutputPreference,
1844 ifTopUses_DisplayBT2020_AndBottomUses_DisplayP3_Then_DisplayBT2020_Chosen) {
1845 // If multiple layers have a preference, the topmost value is what is used.
1846 verify().ifTopLayerIs(ui::Dataspace::DISPLAY_BT2020)
1847 .andIfMiddleLayerHasNoPreference()
1848 .andIfBottomLayerIs(ui::Dataspace::DISPLAY_P3)
1849 .thenExpectBestColorModeCallUses(ui::Dataspace::DISPLAY_BT2020)
1850 .execute();
1851}
1852
1853TEST_F(OutputUpdateColorProfileTest_TopmostLayerPreferenceSetsOutputPreference,
1854 ifTopUses_DisplayP3_AndBottomUses_V0_SRGB_Then_DisplayP3_Chosen) {
1855 // If multiple layers have a preference, the topmost value is what is used.
1856 verify().ifTopLayerIs(ui::Dataspace::DISPLAY_P3)
1857 .andIfMiddleLayerHasNoPreference()
1858 .andIfBottomLayerIs(ui::Dataspace::DISPLAY_BT2020)
1859 .thenExpectBestColorModeCallUses(ui::Dataspace::DISPLAY_P3)
1860 .execute();
1861}
1862
1863struct OutputUpdateColorProfileTest_ForceOutputColorOverrides
1864 : public OutputUpdateColorProfileTest {
1865 // If CompositionRefreshArgs::forceOutputColorMode is set to some specific
1866 // values, it overrides the layer dataspace choice.
1867
1868 OutputUpdateColorProfileTest_ForceOutputColorOverrides() {
1869 mRefreshArgs.outputColorSetting = OutputColorSetting::kEnhanced;
1870 mRefreshArgs.colorSpaceAgnosticDataspace = ui::Dataspace::UNKNOWN;
1871
1872 mLayer1.mLayerFEState.dataspace = ui::Dataspace::DISPLAY_BT2020;
1873
Lloyd Pique0a456232020-01-16 17:51:13 -08001874 EXPECT_CALL(mOutput, getOutputLayerCount()).WillRepeatedly(Return(1u));
Lloyd Pique17ca7422019-11-14 14:24:10 -08001875 EXPECT_CALL(mOutput, setColorProfile(_)).WillRepeatedly(Return());
1876 }
1877
1878 struct IfForceOutputColorModeState
1879 : public CallOrderStateMachineHelper<TestType, IfForceOutputColorModeState> {
1880 [[nodiscard]] auto ifForceOutputColorMode(ui::ColorMode colorMode) {
1881 getInstance()->mRefreshArgs.forceOutputColorMode = colorMode;
1882 return nextState<ThenExpectBestColorModeCallUsesState>();
1883 }
1884 [[nodiscard]] auto ifNoOverride() { return ifForceOutputColorMode(ui::ColorMode::NATIVE); }
1885 };
1886
1887 struct ThenExpectBestColorModeCallUsesState
1888 : public CallOrderStateMachineHelper<TestType, ThenExpectBestColorModeCallUsesState> {
1889 [[nodiscard]] auto thenExpectBestColorModeCallUses(ui::Dataspace dataspace) {
1890 EXPECT_CALL(*getInstance()->mDisplayColorProfile,
1891 getBestColorMode(dataspace, _, _, _, _));
1892 return nextState<ExecuteState>();
1893 }
1894 };
1895
1896 // Call this member function to start using the mini-DSL defined above.
1897 [[nodiscard]] auto verify() { return IfForceOutputColorModeState::make(this); }
1898};
1899
1900TEST_F(OutputUpdateColorProfileTest_ForceOutputColorOverrides, NoOverride_DoesNotOverride) {
1901 // By default the layer state is used to set the preferred dataspace
1902 verify().ifNoOverride()
1903 .thenExpectBestColorModeCallUses(ui::Dataspace::DISPLAY_BT2020)
1904 .execute();
1905}
1906
1907TEST_F(OutputUpdateColorProfileTest_ForceOutputColorOverrides, SRGB_Override_USES_V0_SRGB) {
1908 // Setting ui::ColorMode::SRGB overrides it with ui::Dataspace::V0_SRGB
1909 verify().ifForceOutputColorMode(ui::ColorMode::SRGB)
1910 .thenExpectBestColorModeCallUses(ui::Dataspace::V0_SRGB)
1911 .execute();
1912}
1913
1914TEST_F(OutputUpdateColorProfileTest_ForceOutputColorOverrides, DisplayP3_Override_Uses_DisplayP3) {
1915 // Setting ui::ColorMode::DISPLAY_P3 overrides it with ui::Dataspace::DISPLAY_P3
1916 verify().ifForceOutputColorMode(ui::ColorMode::DISPLAY_P3)
1917 .thenExpectBestColorModeCallUses(ui::Dataspace::DISPLAY_P3)
1918 .execute();
1919}
1920
1921// HDR output requires all layers to be compatible with the chosen HDR
1922// dataspace, along with there being proper support.
1923struct OutputUpdateColorProfileTest_Hdr : public OutputUpdateColorProfileTest {
1924 OutputUpdateColorProfileTest_Hdr() {
1925 mRefreshArgs.outputColorSetting = OutputColorSetting::kEnhanced;
1926 mRefreshArgs.colorSpaceAgnosticDataspace = ui::Dataspace::UNKNOWN;
Lloyd Pique0a456232020-01-16 17:51:13 -08001927 EXPECT_CALL(mOutput, getOutputLayerCount()).WillRepeatedly(Return(2u));
Lloyd Pique17ca7422019-11-14 14:24:10 -08001928 EXPECT_CALL(mOutput, setColorProfile(_)).WillRepeatedly(Return());
1929 }
1930
1931 static constexpr ui::Dataspace kNonHdrDataspace = ui::Dataspace::DISPLAY_P3;
1932 static constexpr ui::Dataspace BT2020_PQ = ui::Dataspace::BT2020_PQ;
1933 static constexpr ui::Dataspace BT2020_HLG = ui::Dataspace::BT2020_HLG;
1934 static constexpr ui::Dataspace DISPLAY_P3 = ui::Dataspace::DISPLAY_P3;
1935
1936 struct IfTopLayerDataspaceState
1937 : public CallOrderStateMachineHelper<TestType, IfTopLayerDataspaceState> {
1938 [[nodiscard]] auto ifTopLayerIs(ui::Dataspace dataspace) {
1939 getInstance()->mLayer2.mLayerFEState.dataspace = dataspace;
1940 return nextState<AndTopLayerCompositionTypeState>();
1941 }
1942 [[nodiscard]] auto ifTopLayerIsNotHdr() { return ifTopLayerIs(kNonHdrDataspace); }
1943 };
1944
1945 struct AndTopLayerCompositionTypeState
1946 : public CallOrderStateMachineHelper<TestType, AndTopLayerCompositionTypeState> {
1947 [[nodiscard]] auto andTopLayerIsREComposed(bool renderEngineComposed) {
1948 getInstance()->mLayer2.mLayerFEState.forceClientComposition = renderEngineComposed;
1949 return nextState<AndIfBottomLayerDataspaceState>();
1950 }
1951 };
1952
1953 struct AndIfBottomLayerDataspaceState
1954 : public CallOrderStateMachineHelper<TestType, AndIfBottomLayerDataspaceState> {
1955 [[nodiscard]] auto andIfBottomLayerIs(ui::Dataspace dataspace) {
1956 getInstance()->mLayer1.mLayerFEState.dataspace = dataspace;
1957 return nextState<AndBottomLayerCompositionTypeState>();
1958 }
1959 [[nodiscard]] auto andIfBottomLayerIsNotHdr() {
1960 return andIfBottomLayerIs(kNonHdrDataspace);
1961 }
1962 };
1963
1964 struct AndBottomLayerCompositionTypeState
1965 : public CallOrderStateMachineHelper<TestType, AndBottomLayerCompositionTypeState> {
1966 [[nodiscard]] auto andBottomLayerIsREComposed(bool renderEngineComposed) {
1967 getInstance()->mLayer1.mLayerFEState.forceClientComposition = renderEngineComposed;
1968 return nextState<AndIfHasLegacySupportState>();
1969 }
1970 };
1971
1972 struct AndIfHasLegacySupportState
1973 : public CallOrderStateMachineHelper<TestType, AndIfHasLegacySupportState> {
1974 [[nodiscard]] auto andIfLegacySupportFor(ui::Dataspace dataspace, bool legacySupport) {
1975 EXPECT_CALL(*getInstance()->mDisplayColorProfile, hasLegacyHdrSupport(dataspace))
1976 .WillOnce(Return(legacySupport));
1977 return nextState<ThenExpectBestColorModeCallUsesState>();
1978 }
1979 };
1980
1981 struct ThenExpectBestColorModeCallUsesState
1982 : public CallOrderStateMachineHelper<TestType, ThenExpectBestColorModeCallUsesState> {
1983 [[nodiscard]] auto thenExpectBestColorModeCallUses(ui::Dataspace dataspace) {
1984 EXPECT_CALL(*getInstance()->mDisplayColorProfile,
1985 getBestColorMode(dataspace, _, _, _, _));
1986 return nextState<ExecuteState>();
1987 }
1988 };
1989
1990 // Call this member function to start using the mini-DSL defined above.
1991 [[nodiscard]] auto verify() { return IfTopLayerDataspaceState::make(this); }
1992};
1993
1994TEST_F(OutputUpdateColorProfileTest_Hdr, PQ_HW_On_PQ_HW_Uses_PQ) {
1995 // If all layers use BT2020_PQ, and there are no other special conditions,
1996 // BT2020_PQ is used.
1997 verify().ifTopLayerIs(BT2020_PQ)
1998 .andTopLayerIsREComposed(false)
1999 .andIfBottomLayerIs(BT2020_PQ)
2000 .andBottomLayerIsREComposed(false)
2001 .andIfLegacySupportFor(BT2020_PQ, false)
2002 .thenExpectBestColorModeCallUses(BT2020_PQ)
2003 .execute();
2004}
2005
2006TEST_F(OutputUpdateColorProfileTest_Hdr, PQ_HW_On_PQ_HW_IfPQHasLegacySupport_Uses_DisplayP3) {
2007 // BT2020_PQ is not used if there is only legacy support for it.
2008 verify().ifTopLayerIs(BT2020_PQ)
2009 .andTopLayerIsREComposed(false)
2010 .andIfBottomLayerIs(BT2020_PQ)
2011 .andBottomLayerIsREComposed(false)
2012 .andIfLegacySupportFor(BT2020_PQ, true)
2013 .thenExpectBestColorModeCallUses(DISPLAY_P3)
2014 .execute();
2015}
2016
2017TEST_F(OutputUpdateColorProfileTest_Hdr, PQ_HW_On_PQ_RE_Uses_PQ) {
2018 // BT2020_PQ is still used if the bottom layer is RenderEngine composed.
2019 verify().ifTopLayerIs(BT2020_PQ)
2020 .andTopLayerIsREComposed(false)
2021 .andIfBottomLayerIs(BT2020_PQ)
2022 .andBottomLayerIsREComposed(true)
2023 .andIfLegacySupportFor(BT2020_PQ, false)
2024 .thenExpectBestColorModeCallUses(BT2020_PQ)
2025 .execute();
2026}
2027
2028TEST_F(OutputUpdateColorProfileTest_Hdr, PQ_RE_On_PQ_HW_Uses_DisplayP3) {
2029 // BT2020_PQ is not used if the top layer is RenderEngine composed.
2030 verify().ifTopLayerIs(BT2020_PQ)
2031 .andTopLayerIsREComposed(true)
2032 .andIfBottomLayerIs(BT2020_PQ)
2033 .andBottomLayerIsREComposed(false)
2034 .andIfLegacySupportFor(BT2020_PQ, false)
2035 .thenExpectBestColorModeCallUses(DISPLAY_P3)
2036 .execute();
2037}
2038
2039TEST_F(OutputUpdateColorProfileTest_Hdr, PQ_HW_On_HLG_HW_Uses_PQ) {
2040 // If there is mixed HLG/PQ use, and the topmost layer is PQ, then PQ is used if there
2041 // are no other special conditions.
2042 verify().ifTopLayerIs(BT2020_PQ)
2043 .andTopLayerIsREComposed(false)
2044 .andIfBottomLayerIs(BT2020_HLG)
2045 .andBottomLayerIsREComposed(false)
2046 .andIfLegacySupportFor(BT2020_PQ, false)
2047 .thenExpectBestColorModeCallUses(BT2020_PQ)
2048 .execute();
2049}
2050
2051TEST_F(OutputUpdateColorProfileTest_Hdr, PQ_HW_On_HLG_HW_IfPQHasLegacySupport_Uses_DisplayP3) {
2052 // BT2020_PQ is not used if there is only legacy support for it.
2053 verify().ifTopLayerIs(BT2020_PQ)
2054 .andTopLayerIsREComposed(false)
2055 .andIfBottomLayerIs(BT2020_HLG)
2056 .andBottomLayerIsREComposed(false)
2057 .andIfLegacySupportFor(BT2020_PQ, true)
2058 .thenExpectBestColorModeCallUses(DISPLAY_P3)
2059 .execute();
2060}
2061
2062TEST_F(OutputUpdateColorProfileTest_Hdr, PQ_HW_On_HLG_RE_Uses_PQ) {
2063 // BT2020_PQ is used if the bottom HLG layer is RenderEngine composed.
2064 verify().ifTopLayerIs(BT2020_PQ)
2065 .andTopLayerIsREComposed(false)
2066 .andIfBottomLayerIs(BT2020_HLG)
2067 .andBottomLayerIsREComposed(true)
2068 .andIfLegacySupportFor(BT2020_PQ, false)
2069 .thenExpectBestColorModeCallUses(BT2020_PQ)
2070 .execute();
2071}
2072
2073TEST_F(OutputUpdateColorProfileTest_Hdr, PQ_RE_On_HLG_HW_Uses_DisplayP3) {
2074 // BT2020_PQ is not used if the top PQ layer is RenderEngine composed.
2075 verify().ifTopLayerIs(BT2020_PQ)
2076 .andTopLayerIsREComposed(true)
2077 .andIfBottomLayerIs(BT2020_HLG)
2078 .andBottomLayerIsREComposed(false)
2079 .andIfLegacySupportFor(BT2020_PQ, false)
2080 .thenExpectBestColorModeCallUses(DISPLAY_P3)
2081 .execute();
2082}
2083
2084TEST_F(OutputUpdateColorProfileTest_Hdr, HLG_HW_On_PQ_HW_Uses_PQ) {
2085 // If there is mixed HLG/PQ use, and the topmost layer is HLG, then PQ is
2086 // used if there are no other special conditions.
2087 verify().ifTopLayerIs(BT2020_HLG)
2088 .andTopLayerIsREComposed(false)
2089 .andIfBottomLayerIs(BT2020_PQ)
2090 .andBottomLayerIsREComposed(false)
2091 .andIfLegacySupportFor(BT2020_PQ, false)
2092 .thenExpectBestColorModeCallUses(BT2020_PQ)
2093 .execute();
2094}
2095
2096TEST_F(OutputUpdateColorProfileTest_Hdr, HLG_HW_On_PQ_HW_IfPQHasLegacySupport_Uses_DisplayP3) {
2097 // BT2020_PQ is not used if there is only legacy support for it.
2098 verify().ifTopLayerIs(BT2020_HLG)
2099 .andTopLayerIsREComposed(false)
2100 .andIfBottomLayerIs(BT2020_PQ)
2101 .andBottomLayerIsREComposed(false)
2102 .andIfLegacySupportFor(BT2020_PQ, true)
2103 .thenExpectBestColorModeCallUses(DISPLAY_P3)
2104 .execute();
2105}
2106
2107TEST_F(OutputUpdateColorProfileTest_Hdr, HLG_HW_On_PQ_RE_Uses_DisplayP3) {
2108 // BT2020_PQ is not used if the bottom PQ layer is RenderEngine composed.
2109 verify().ifTopLayerIs(BT2020_HLG)
2110 .andTopLayerIsREComposed(false)
2111 .andIfBottomLayerIs(BT2020_PQ)
2112 .andBottomLayerIsREComposed(true)
2113 .andIfLegacySupportFor(BT2020_PQ, false)
2114 .thenExpectBestColorModeCallUses(DISPLAY_P3)
2115 .execute();
2116}
2117
2118TEST_F(OutputUpdateColorProfileTest_Hdr, HLG_RE_On_PQ_HW_Uses_PQ) {
2119 // BT2020_PQ is still used if the top HLG layer is RenderEngine composed.
2120 verify().ifTopLayerIs(BT2020_HLG)
2121 .andTopLayerIsREComposed(true)
2122 .andIfBottomLayerIs(BT2020_PQ)
2123 .andBottomLayerIsREComposed(false)
2124 .andIfLegacySupportFor(BT2020_PQ, false)
2125 .thenExpectBestColorModeCallUses(BT2020_PQ)
2126 .execute();
2127}
2128
2129TEST_F(OutputUpdateColorProfileTest_Hdr, HLG_HW_On_HLG_HW_Uses_HLG) {
2130 // If all layers use HLG then HLG is used if there are no other special
2131 // conditions.
2132 verify().ifTopLayerIs(BT2020_HLG)
2133 .andTopLayerIsREComposed(false)
2134 .andIfBottomLayerIs(BT2020_HLG)
2135 .andBottomLayerIsREComposed(false)
2136 .andIfLegacySupportFor(BT2020_HLG, false)
2137 .thenExpectBestColorModeCallUses(BT2020_HLG)
2138 .execute();
2139}
2140
2141TEST_F(OutputUpdateColorProfileTest_Hdr, HLG_HW_On_HLG_HW_IfPQHasLegacySupport_Uses_DisplayP3) {
2142 // BT2020_HLG is not used if there is legacy support for it.
2143 verify().ifTopLayerIs(BT2020_HLG)
2144 .andTopLayerIsREComposed(false)
2145 .andIfBottomLayerIs(BT2020_HLG)
2146 .andBottomLayerIsREComposed(false)
2147 .andIfLegacySupportFor(BT2020_HLG, true)
2148 .thenExpectBestColorModeCallUses(DISPLAY_P3)
2149 .execute();
2150}
2151
2152TEST_F(OutputUpdateColorProfileTest_Hdr, HLG_HW_On_HLG_RE_Uses_HLG) {
2153 // BT2020_HLG is used even if the bottom layer is client composed.
2154 verify().ifTopLayerIs(BT2020_HLG)
2155 .andTopLayerIsREComposed(false)
2156 .andIfBottomLayerIs(BT2020_HLG)
2157 .andBottomLayerIsREComposed(true)
2158 .andIfLegacySupportFor(BT2020_HLG, false)
2159 .thenExpectBestColorModeCallUses(BT2020_HLG)
2160 .execute();
2161}
2162
2163TEST_F(OutputUpdateColorProfileTest_Hdr, HLG_RE_On_HLG_HW_Uses_HLG) {
2164 // BT2020_HLG is used even if the top layer is client composed.
2165 verify().ifTopLayerIs(BT2020_HLG)
2166 .andTopLayerIsREComposed(true)
2167 .andIfBottomLayerIs(BT2020_HLG)
2168 .andBottomLayerIsREComposed(false)
2169 .andIfLegacySupportFor(BT2020_HLG, false)
2170 .thenExpectBestColorModeCallUses(BT2020_HLG)
2171 .execute();
2172}
2173
2174TEST_F(OutputUpdateColorProfileTest_Hdr, PQ_HW_On_NonHdr_HW_Uses_PQ) {
2175 // Even if there are non-HDR layers present, BT2020_PQ can still be used.
2176 verify().ifTopLayerIs(BT2020_PQ)
2177 .andTopLayerIsREComposed(false)
2178 .andIfBottomLayerIsNotHdr()
2179 .andBottomLayerIsREComposed(false)
2180 .andIfLegacySupportFor(BT2020_PQ, false)
2181 .thenExpectBestColorModeCallUses(BT2020_PQ)
2182 .execute();
2183}
2184
2185TEST_F(OutputUpdateColorProfileTest_Hdr, HLG_HW_On_NonHdr_RE_Uses_HLG) {
2186 // If all layers use HLG then HLG is used if there are no other special
2187 // conditions.
2188 verify().ifTopLayerIs(BT2020_HLG)
2189 .andTopLayerIsREComposed(false)
2190 .andIfBottomLayerIsNotHdr()
2191 .andBottomLayerIsREComposed(true)
2192 .andIfLegacySupportFor(BT2020_HLG, false)
2193 .thenExpectBestColorModeCallUses(BT2020_HLG)
2194 .execute();
2195}
2196
2197struct OutputUpdateColorProfile_AffectsChosenRenderIntentTest
2198 : public OutputUpdateColorProfileTest {
2199 // The various values for CompositionRefreshArgs::outputColorSetting affect
2200 // the chosen renderIntent, along with whether the preferred dataspace is an
2201 // HDR dataspace or not.
2202
2203 OutputUpdateColorProfile_AffectsChosenRenderIntentTest() {
2204 mRefreshArgs.outputColorSetting = OutputColorSetting::kEnhanced;
2205 mRefreshArgs.colorSpaceAgnosticDataspace = ui::Dataspace::UNKNOWN;
2206 mLayer1.mLayerFEState.dataspace = ui::Dataspace::BT2020_PQ;
Lloyd Pique0a456232020-01-16 17:51:13 -08002207 EXPECT_CALL(mOutput, getOutputLayerCount()).WillRepeatedly(Return(1u));
Lloyd Pique17ca7422019-11-14 14:24:10 -08002208 EXPECT_CALL(mOutput, setColorProfile(_)).WillRepeatedly(Return());
2209 EXPECT_CALL(*mDisplayColorProfile, hasLegacyHdrSupport(ui::Dataspace::BT2020_PQ))
2210 .WillRepeatedly(Return(false));
2211 }
2212
2213 // The tests here involve enough state and GMock setup that using a mini-DSL
2214 // makes the tests much more readable, and allows the test to focus more on
2215 // the intent than on some of the details.
2216
2217 static constexpr ui::Dataspace kNonHdrDataspace = ui::Dataspace::DISPLAY_P3;
2218 static constexpr ui::Dataspace kHdrDataspace = ui::Dataspace::BT2020_PQ;
2219
2220 struct IfDataspaceChosenState
2221 : public CallOrderStateMachineHelper<TestType, IfDataspaceChosenState> {
2222 [[nodiscard]] auto ifDataspaceChosenIs(ui::Dataspace dataspace) {
2223 getInstance()->mLayer1.mLayerFEState.dataspace = dataspace;
2224 return nextState<AndOutputColorSettingState>();
2225 }
2226 [[nodiscard]] auto ifDataspaceChosenIsNonHdr() {
2227 return ifDataspaceChosenIs(kNonHdrDataspace);
2228 }
2229 [[nodiscard]] auto ifDataspaceChosenIsHdr() { return ifDataspaceChosenIs(kHdrDataspace); }
2230 };
2231
2232 struct AndOutputColorSettingState
2233 : public CallOrderStateMachineHelper<TestType, AndOutputColorSettingState> {
2234 [[nodiscard]] auto andOutputColorSettingIs(OutputColorSetting setting) {
2235 getInstance()->mRefreshArgs.outputColorSetting = setting;
2236 return nextState<ThenExpectBestColorModeCallUsesState>();
2237 }
2238 };
2239
2240 struct ThenExpectBestColorModeCallUsesState
2241 : public CallOrderStateMachineHelper<TestType, ThenExpectBestColorModeCallUsesState> {
2242 [[nodiscard]] auto thenExpectBestColorModeCallUses(ui::RenderIntent intent) {
2243 EXPECT_CALL(*getInstance()->mDisplayColorProfile,
2244 getBestColorMode(getInstance()->mLayer1.mLayerFEState.dataspace, intent, _,
2245 _, _));
2246 return nextState<ExecuteState>();
2247 }
2248 };
2249
2250 // Tests call one of these two helper member functions to start using the
2251 // mini-DSL defined above.
2252 [[nodiscard]] auto verify() { return IfDataspaceChosenState::make(this); }
2253};
2254
2255TEST_F(OutputUpdateColorProfile_AffectsChosenRenderIntentTest,
2256 Managed_NonHdr_Prefers_Colorimetric) {
2257 verify().ifDataspaceChosenIsNonHdr()
2258 .andOutputColorSettingIs(OutputColorSetting::kManaged)
2259 .thenExpectBestColorModeCallUses(ui::RenderIntent::COLORIMETRIC)
2260 .execute();
2261}
2262
2263TEST_F(OutputUpdateColorProfile_AffectsChosenRenderIntentTest,
2264 Managed_Hdr_Prefers_ToneMapColorimetric) {
2265 verify().ifDataspaceChosenIsHdr()
2266 .andOutputColorSettingIs(OutputColorSetting::kManaged)
2267 .thenExpectBestColorModeCallUses(ui::RenderIntent::TONE_MAP_COLORIMETRIC)
2268 .execute();
2269}
2270
2271TEST_F(OutputUpdateColorProfile_AffectsChosenRenderIntentTest, Enhanced_NonHdr_Prefers_Enhance) {
2272 verify().ifDataspaceChosenIsNonHdr()
2273 .andOutputColorSettingIs(OutputColorSetting::kEnhanced)
2274 .thenExpectBestColorModeCallUses(ui::RenderIntent::ENHANCE)
2275 .execute();
2276}
2277
2278TEST_F(OutputUpdateColorProfile_AffectsChosenRenderIntentTest,
2279 Enhanced_Hdr_Prefers_ToneMapEnhance) {
2280 verify().ifDataspaceChosenIsHdr()
2281 .andOutputColorSettingIs(OutputColorSetting::kEnhanced)
2282 .thenExpectBestColorModeCallUses(ui::RenderIntent::TONE_MAP_ENHANCE)
2283 .execute();
2284}
2285
2286TEST_F(OutputUpdateColorProfile_AffectsChosenRenderIntentTest, Vendor_NonHdr_Prefers_Vendor) {
2287 verify().ifDataspaceChosenIsNonHdr()
2288 .andOutputColorSettingIs(kVendorSpecifiedOutputColorSetting)
2289 .thenExpectBestColorModeCallUses(
2290 static_cast<ui::RenderIntent>(kVendorSpecifiedOutputColorSetting))
2291 .execute();
2292}
2293
2294TEST_F(OutputUpdateColorProfile_AffectsChosenRenderIntentTest, Vendor_Hdr_Prefers_Vendor) {
2295 verify().ifDataspaceChosenIsHdr()
2296 .andOutputColorSettingIs(kVendorSpecifiedOutputColorSetting)
2297 .thenExpectBestColorModeCallUses(
2298 static_cast<ui::RenderIntent>(kVendorSpecifiedOutputColorSetting))
2299 .execute();
2300}
Lloyd Piquefaa3f192019-11-14 14:05:09 -08002301
2302/*
2303 * Output::beginFrame()
2304 */
2305
Lloyd Piquee5965952019-11-18 16:16:32 -08002306struct OutputBeginFrameTest : public ::testing::Test {
2307 using TestType = OutputBeginFrameTest;
2308
2309 struct OutputPartialMock : public OutputPartialMockBase {
Lloyd Pique739afaf2019-11-21 16:40:05 -08002310 // Sets up the helper functions called by the function under test to use
2311 // mock implementations.
Lloyd Piquee5965952019-11-18 16:16:32 -08002312 MOCK_CONST_METHOD1(getDirtyRegion, Region(bool));
2313 };
2314
2315 OutputBeginFrameTest() {
2316 mOutput.setDisplayColorProfileForTest(
2317 std::unique_ptr<DisplayColorProfile>(mDisplayColorProfile));
2318 mOutput.setRenderSurfaceForTest(std::unique_ptr<RenderSurface>(mRenderSurface));
2319 }
2320
2321 struct IfGetDirtyRegionExpectationState
2322 : public CallOrderStateMachineHelper<TestType, IfGetDirtyRegionExpectationState> {
2323 [[nodiscard]] auto ifGetDirtyRegionReturns(Region dirtyRegion) {
2324 EXPECT_CALL(getInstance()->mOutput, getDirtyRegion(false))
2325 .WillOnce(Return(dirtyRegion));
2326 return nextState<AndIfGetOutputLayerCountExpectationState>();
2327 }
2328 };
2329
2330 struct AndIfGetOutputLayerCountExpectationState
2331 : public CallOrderStateMachineHelper<TestType, AndIfGetOutputLayerCountExpectationState> {
2332 [[nodiscard]] auto andIfGetOutputLayerCountReturns(size_t layerCount) {
2333 EXPECT_CALL(getInstance()->mOutput, getOutputLayerCount()).WillOnce(Return(layerCount));
2334 return nextState<AndIfLastCompositionHadVisibleLayersState>();
2335 }
2336 };
2337
2338 struct AndIfLastCompositionHadVisibleLayersState
2339 : public CallOrderStateMachineHelper<TestType,
2340 AndIfLastCompositionHadVisibleLayersState> {
2341 [[nodiscard]] auto andIfLastCompositionHadVisibleLayersIs(bool hadOutputLayers) {
2342 getInstance()->mOutput.mState.lastCompositionHadVisibleLayers = hadOutputLayers;
2343 return nextState<ThenExpectRenderSurfaceBeginFrameCallState>();
2344 }
2345 };
2346
2347 struct ThenExpectRenderSurfaceBeginFrameCallState
2348 : public CallOrderStateMachineHelper<TestType,
2349 ThenExpectRenderSurfaceBeginFrameCallState> {
2350 [[nodiscard]] auto thenExpectRenderSurfaceBeginFrameCall(bool mustRecompose) {
2351 EXPECT_CALL(*getInstance()->mRenderSurface, beginFrame(mustRecompose));
2352 return nextState<ExecuteState>();
2353 }
2354 };
2355
2356 struct ExecuteState : public CallOrderStateMachineHelper<TestType, ExecuteState> {
2357 [[nodiscard]] auto execute() {
2358 getInstance()->mOutput.beginFrame();
2359 return nextState<CheckPostconditionHadVisibleLayersState>();
2360 }
2361 };
2362
2363 struct CheckPostconditionHadVisibleLayersState
2364 : public CallOrderStateMachineHelper<TestType, CheckPostconditionHadVisibleLayersState> {
2365 void checkPostconditionHadVisibleLayers(bool expected) {
2366 EXPECT_EQ(expected, getInstance()->mOutput.mState.lastCompositionHadVisibleLayers);
2367 }
2368 };
2369
2370 // Tests call one of these two helper member functions to start using the
2371 // mini-DSL defined above.
2372 [[nodiscard]] auto verify() { return IfGetDirtyRegionExpectationState::make(this); }
2373
2374 static const Region kEmptyRegion;
2375 static const Region kNotEmptyRegion;
2376
2377 mock::DisplayColorProfile* mDisplayColorProfile = new StrictMock<mock::DisplayColorProfile>();
2378 mock::RenderSurface* mRenderSurface = new StrictMock<mock::RenderSurface>();
2379 StrictMock<OutputPartialMock> mOutput;
2380};
2381
2382const Region OutputBeginFrameTest::kEmptyRegion{Rect{0, 0, 0, 0}};
2383const Region OutputBeginFrameTest::kNotEmptyRegion{Rect{0, 0, 1, 1}};
2384
2385TEST_F(OutputBeginFrameTest, hasDirtyHasLayersHadLayersLastFrame) {
2386 verify().ifGetDirtyRegionReturns(kNotEmptyRegion)
2387 .andIfGetOutputLayerCountReturns(1u)
2388 .andIfLastCompositionHadVisibleLayersIs(true)
2389 .thenExpectRenderSurfaceBeginFrameCall(true)
2390 .execute()
2391 .checkPostconditionHadVisibleLayers(true);
2392}
2393
2394TEST_F(OutputBeginFrameTest, hasDirtyNotHasLayersHadLayersLastFrame) {
2395 verify().ifGetDirtyRegionReturns(kNotEmptyRegion)
2396 .andIfGetOutputLayerCountReturns(0u)
2397 .andIfLastCompositionHadVisibleLayersIs(true)
2398 .thenExpectRenderSurfaceBeginFrameCall(true)
2399 .execute()
2400 .checkPostconditionHadVisibleLayers(false);
2401}
2402
2403TEST_F(OutputBeginFrameTest, hasDirtyHasLayersNotHadLayersLastFrame) {
2404 verify().ifGetDirtyRegionReturns(kNotEmptyRegion)
2405 .andIfGetOutputLayerCountReturns(1u)
2406 .andIfLastCompositionHadVisibleLayersIs(false)
2407 .thenExpectRenderSurfaceBeginFrameCall(true)
2408 .execute()
2409 .checkPostconditionHadVisibleLayers(true);
2410}
2411
2412TEST_F(OutputBeginFrameTest, hasDirtyNotHasLayersNotHadLayersLastFrame) {
2413 verify().ifGetDirtyRegionReturns(kNotEmptyRegion)
2414 .andIfGetOutputLayerCountReturns(0u)
2415 .andIfLastCompositionHadVisibleLayersIs(false)
2416 .thenExpectRenderSurfaceBeginFrameCall(false)
2417 .execute()
2418 .checkPostconditionHadVisibleLayers(false);
2419}
2420
2421TEST_F(OutputBeginFrameTest, notHasDirtyHasLayersHadLayersLastFrame) {
2422 verify().ifGetDirtyRegionReturns(kEmptyRegion)
2423 .andIfGetOutputLayerCountReturns(1u)
2424 .andIfLastCompositionHadVisibleLayersIs(true)
2425 .thenExpectRenderSurfaceBeginFrameCall(false)
2426 .execute()
2427 .checkPostconditionHadVisibleLayers(true);
2428}
2429
2430TEST_F(OutputBeginFrameTest, notHasDirtyNotHasLayersHadLayersLastFrame) {
2431 verify().ifGetDirtyRegionReturns(kEmptyRegion)
2432 .andIfGetOutputLayerCountReturns(0u)
2433 .andIfLastCompositionHadVisibleLayersIs(true)
2434 .thenExpectRenderSurfaceBeginFrameCall(false)
2435 .execute()
2436 .checkPostconditionHadVisibleLayers(true);
2437}
2438
2439TEST_F(OutputBeginFrameTest, notHasDirtyHasLayersNotHadLayersLastFrame) {
2440 verify().ifGetDirtyRegionReturns(kEmptyRegion)
2441 .andIfGetOutputLayerCountReturns(1u)
2442 .andIfLastCompositionHadVisibleLayersIs(false)
2443 .thenExpectRenderSurfaceBeginFrameCall(false)
2444 .execute()
2445 .checkPostconditionHadVisibleLayers(false);
2446}
2447
2448TEST_F(OutputBeginFrameTest, notHasDirtyNotHasLayersNotHadLayersLastFrame) {
2449 verify().ifGetDirtyRegionReturns(kEmptyRegion)
2450 .andIfGetOutputLayerCountReturns(0u)
2451 .andIfLastCompositionHadVisibleLayersIs(false)
2452 .thenExpectRenderSurfaceBeginFrameCall(false)
2453 .execute()
2454 .checkPostconditionHadVisibleLayers(false);
2455}
2456
Lloyd Piquefaa3f192019-11-14 14:05:09 -08002457/*
2458 * Output::devOptRepaintFlash()
2459 */
2460
Lloyd Piquedb462d82019-11-19 17:58:46 -08002461struct OutputDevOptRepaintFlashTest : public testing::Test {
2462 struct OutputPartialMock : public OutputPartialMockBase {
Lloyd Pique739afaf2019-11-21 16:40:05 -08002463 // Sets up the helper functions called by the function under test to use
2464 // mock implementations.
Lloyd Piquedb462d82019-11-19 17:58:46 -08002465 MOCK_CONST_METHOD1(getDirtyRegion, Region(bool));
2466 MOCK_METHOD1(composeSurfaces, std::optional<base::unique_fd>(const Region&));
2467 MOCK_METHOD0(postFramebuffer, void());
2468 MOCK_METHOD0(prepareFrame, void());
2469 };
2470
2471 OutputDevOptRepaintFlashTest() {
2472 mOutput.setDisplayColorProfileForTest(
2473 std::unique_ptr<DisplayColorProfile>(mDisplayColorProfile));
2474 mOutput.setRenderSurfaceForTest(std::unique_ptr<RenderSurface>(mRenderSurface));
2475 }
2476
2477 static const Region kEmptyRegion;
2478 static const Region kNotEmptyRegion;
2479
2480 StrictMock<OutputPartialMock> mOutput;
2481 mock::DisplayColorProfile* mDisplayColorProfile = new StrictMock<mock::DisplayColorProfile>();
2482 mock::RenderSurface* mRenderSurface = new StrictMock<mock::RenderSurface>();
2483 CompositionRefreshArgs mRefreshArgs;
2484};
2485
2486const Region OutputDevOptRepaintFlashTest::kEmptyRegion{Rect{0, 0, 0, 0}};
2487const Region OutputDevOptRepaintFlashTest::kNotEmptyRegion{Rect{0, 0, 1, 1}};
2488
2489TEST_F(OutputDevOptRepaintFlashTest, doesNothingIfFlashDelayNotSet) {
2490 mRefreshArgs.devOptFlashDirtyRegionsDelay = {};
2491 mRefreshArgs.repaintEverything = true;
2492 mOutput.mState.isEnabled = true;
2493
2494 mOutput.devOptRepaintFlash(mRefreshArgs);
2495}
2496
2497TEST_F(OutputDevOptRepaintFlashTest, postsAndPreparesANewFrameIfNotEnabled) {
2498 mRefreshArgs.devOptFlashDirtyRegionsDelay = std::chrono::microseconds(1);
2499 mRefreshArgs.repaintEverything = true;
2500 mOutput.mState.isEnabled = false;
2501
2502 InSequence seq;
2503 EXPECT_CALL(mOutput, postFramebuffer());
2504 EXPECT_CALL(mOutput, prepareFrame());
2505
2506 mOutput.devOptRepaintFlash(mRefreshArgs);
2507}
2508
2509TEST_F(OutputDevOptRepaintFlashTest, postsAndPreparesANewFrameIfNotDirty) {
2510 mRefreshArgs.devOptFlashDirtyRegionsDelay = std::chrono::microseconds(1);
2511 mRefreshArgs.repaintEverything = true;
2512 mOutput.mState.isEnabled = true;
2513
2514 InSequence seq;
2515 EXPECT_CALL(mOutput, getDirtyRegion(true)).WillOnce(Return(kEmptyRegion));
2516 EXPECT_CALL(mOutput, postFramebuffer());
2517 EXPECT_CALL(mOutput, prepareFrame());
2518
2519 mOutput.devOptRepaintFlash(mRefreshArgs);
2520}
2521
2522TEST_F(OutputDevOptRepaintFlashTest, alsoComposesSurfacesAndQueuesABufferIfDirty) {
2523 mRefreshArgs.devOptFlashDirtyRegionsDelay = std::chrono::microseconds(1);
2524 mRefreshArgs.repaintEverything = false;
2525 mOutput.mState.isEnabled = true;
2526
2527 InSequence seq;
2528 EXPECT_CALL(mOutput, getDirtyRegion(false)).WillOnce(Return(kNotEmptyRegion));
2529 EXPECT_CALL(mOutput, composeSurfaces(RegionEq(kNotEmptyRegion)));
2530 EXPECT_CALL(*mRenderSurface, queueBuffer(_));
2531 EXPECT_CALL(mOutput, postFramebuffer());
2532 EXPECT_CALL(mOutput, prepareFrame());
2533
2534 mOutput.devOptRepaintFlash(mRefreshArgs);
2535}
2536
Lloyd Piquefaa3f192019-11-14 14:05:09 -08002537/*
2538 * Output::finishFrame()
2539 */
2540
Lloyd Pique03561a62019-11-19 18:34:52 -08002541struct OutputFinishFrameTest : public testing::Test {
2542 struct OutputPartialMock : public OutputPartialMockBase {
Lloyd Pique739afaf2019-11-21 16:40:05 -08002543 // Sets up the helper functions called by the function under test to use
2544 // mock implementations.
Lloyd Pique03561a62019-11-19 18:34:52 -08002545 MOCK_METHOD1(composeSurfaces, std::optional<base::unique_fd>(const Region&));
2546 MOCK_METHOD0(postFramebuffer, void());
2547 };
2548
2549 OutputFinishFrameTest() {
2550 mOutput.setDisplayColorProfileForTest(
2551 std::unique_ptr<DisplayColorProfile>(mDisplayColorProfile));
2552 mOutput.setRenderSurfaceForTest(std::unique_ptr<RenderSurface>(mRenderSurface));
2553 }
2554
2555 StrictMock<OutputPartialMock> mOutput;
2556 mock::DisplayColorProfile* mDisplayColorProfile = new StrictMock<mock::DisplayColorProfile>();
2557 mock::RenderSurface* mRenderSurface = new StrictMock<mock::RenderSurface>();
2558 CompositionRefreshArgs mRefreshArgs;
2559};
2560
2561TEST_F(OutputFinishFrameTest, ifNotEnabledDoesNothing) {
2562 mOutput.mState.isEnabled = false;
2563
2564 mOutput.finishFrame(mRefreshArgs);
2565}
2566
2567TEST_F(OutputFinishFrameTest, takesEarlyOutifComposeSurfacesReturnsNoFence) {
2568 mOutput.mState.isEnabled = true;
2569
2570 InSequence seq;
2571 EXPECT_CALL(mOutput, composeSurfaces(RegionEq(Region::INVALID_REGION)));
2572
2573 mOutput.finishFrame(mRefreshArgs);
2574}
2575
2576TEST_F(OutputFinishFrameTest, queuesBufferIfComposeSurfacesReturnsAFence) {
2577 mOutput.mState.isEnabled = true;
2578
2579 InSequence seq;
2580 EXPECT_CALL(mOutput, composeSurfaces(RegionEq(Region::INVALID_REGION)))
2581 .WillOnce(Return(ByMove(base::unique_fd())));
2582 EXPECT_CALL(*mRenderSurface, queueBuffer(_));
2583
2584 mOutput.finishFrame(mRefreshArgs);
2585}
Lloyd Piquefaa3f192019-11-14 14:05:09 -08002586
2587/*
2588 * Output::postFramebuffer()
2589 */
2590
Lloyd Pique07178e32019-11-19 19:15:26 -08002591struct OutputPostFramebufferTest : public testing::Test {
2592 struct OutputPartialMock : public OutputPartialMockBase {
Lloyd Pique739afaf2019-11-21 16:40:05 -08002593 // Sets up the helper functions called by the function under test to use
2594 // mock implementations.
Lloyd Pique07178e32019-11-19 19:15:26 -08002595 MOCK_METHOD0(presentAndGetFrameFences, compositionengine::Output::FrameFences());
2596 };
2597
2598 struct Layer {
2599 Layer() {
2600 EXPECT_CALL(outputLayer, getLayerFE()).WillRepeatedly(ReturnRef(layerFE));
2601 EXPECT_CALL(outputLayer, getHwcLayer()).WillRepeatedly(Return(&hwc2Layer));
2602 }
2603
2604 StrictMock<mock::OutputLayer> outputLayer;
2605 StrictMock<mock::LayerFE> layerFE;
2606 StrictMock<HWC2::mock::Layer> hwc2Layer;
2607 };
2608
2609 OutputPostFramebufferTest() {
2610 mOutput.setDisplayColorProfileForTest(
2611 std::unique_ptr<DisplayColorProfile>(mDisplayColorProfile));
2612 mOutput.setRenderSurfaceForTest(std::unique_ptr<RenderSurface>(mRenderSurface));
2613
2614 EXPECT_CALL(mOutput, getOutputLayerCount()).WillRepeatedly(Return(3u));
2615 EXPECT_CALL(mOutput, getOutputLayerOrderedByZByIndex(0u))
2616 .WillRepeatedly(Return(&mLayer1.outputLayer));
2617 EXPECT_CALL(mOutput, getOutputLayerOrderedByZByIndex(1u))
2618 .WillRepeatedly(Return(&mLayer2.outputLayer));
2619 EXPECT_CALL(mOutput, getOutputLayerOrderedByZByIndex(2u))
2620 .WillRepeatedly(Return(&mLayer3.outputLayer));
2621 }
2622
2623 StrictMock<OutputPartialMock> mOutput;
2624 mock::DisplayColorProfile* mDisplayColorProfile = new StrictMock<mock::DisplayColorProfile>();
2625 mock::RenderSurface* mRenderSurface = new StrictMock<mock::RenderSurface>();
2626
2627 Layer mLayer1;
2628 Layer mLayer2;
2629 Layer mLayer3;
2630};
2631
2632TEST_F(OutputPostFramebufferTest, ifNotEnabledDoesNothing) {
2633 mOutput.mState.isEnabled = false;
2634
2635 mOutput.postFramebuffer();
2636}
2637
2638TEST_F(OutputPostFramebufferTest, ifEnabledMustFlipThenPresentThenSendPresentCompleted) {
2639 mOutput.mState.isEnabled = true;
2640
2641 compositionengine::Output::FrameFences frameFences;
2642
2643 // This should happen even if there are no output layers.
2644 EXPECT_CALL(mOutput, getOutputLayerCount()).WillOnce(Return(0u));
2645
2646 // For this test in particular we want to make sure the call expectations
2647 // setup below are satisfied in the specific order.
2648 InSequence seq;
2649
2650 EXPECT_CALL(*mRenderSurface, flip());
2651 EXPECT_CALL(mOutput, presentAndGetFrameFences()).WillOnce(Return(frameFences));
2652 EXPECT_CALL(*mRenderSurface, onPresentDisplayCompleted());
2653
2654 mOutput.postFramebuffer();
2655}
2656
2657TEST_F(OutputPostFramebufferTest, releaseFencesAreSentToLayerFE) {
2658 // Simulate getting release fences from each layer, and ensure they are passed to the
2659 // front-end layer interface for each layer correctly.
2660
2661 mOutput.mState.isEnabled = true;
2662
2663 // Create three unique fence instances
2664 sp<Fence> layer1Fence = new Fence();
2665 sp<Fence> layer2Fence = new Fence();
2666 sp<Fence> layer3Fence = new Fence();
2667
Lloyd Piquefe0ee9e2019-11-22 16:30:30 -08002668 Output::FrameFences frameFences;
Lloyd Pique07178e32019-11-19 19:15:26 -08002669 frameFences.layerFences.emplace(&mLayer1.hwc2Layer, layer1Fence);
2670 frameFences.layerFences.emplace(&mLayer2.hwc2Layer, layer2Fence);
2671 frameFences.layerFences.emplace(&mLayer3.hwc2Layer, layer3Fence);
2672
2673 EXPECT_CALL(*mRenderSurface, flip());
2674 EXPECT_CALL(mOutput, presentAndGetFrameFences()).WillOnce(Return(frameFences));
2675 EXPECT_CALL(*mRenderSurface, onPresentDisplayCompleted());
2676
2677 // Compare the pointers values of each fence to make sure the correct ones
2678 // are passed. This happens to work with the current implementation, but
2679 // would not survive certain calls like Fence::merge() which would return a
2680 // new instance.
2681 EXPECT_CALL(mLayer1.layerFE,
2682 onLayerDisplayed(Property(&sp<Fence>::get, Eq(layer1Fence.get()))));
2683 EXPECT_CALL(mLayer2.layerFE,
2684 onLayerDisplayed(Property(&sp<Fence>::get, Eq(layer2Fence.get()))));
2685 EXPECT_CALL(mLayer3.layerFE,
2686 onLayerDisplayed(Property(&sp<Fence>::get, Eq(layer3Fence.get()))));
2687
2688 mOutput.postFramebuffer();
2689}
2690
2691TEST_F(OutputPostFramebufferTest, releaseFencesIncludeClientTargetAcquireFence) {
2692 mOutput.mState.isEnabled = true;
2693 mOutput.mState.usesClientComposition = true;
2694
2695 sp<Fence> clientTargetAcquireFence = new Fence();
2696 sp<Fence> layer1Fence = new Fence();
2697 sp<Fence> layer2Fence = new Fence();
2698 sp<Fence> layer3Fence = new Fence();
Lloyd Piquefe0ee9e2019-11-22 16:30:30 -08002699 Output::FrameFences frameFences;
Lloyd Pique07178e32019-11-19 19:15:26 -08002700 frameFences.clientTargetAcquireFence = clientTargetAcquireFence;
2701 frameFences.layerFences.emplace(&mLayer1.hwc2Layer, layer1Fence);
2702 frameFences.layerFences.emplace(&mLayer2.hwc2Layer, layer2Fence);
2703 frameFences.layerFences.emplace(&mLayer3.hwc2Layer, layer3Fence);
2704
2705 EXPECT_CALL(*mRenderSurface, flip());
2706 EXPECT_CALL(mOutput, presentAndGetFrameFences()).WillOnce(Return(frameFences));
2707 EXPECT_CALL(*mRenderSurface, onPresentDisplayCompleted());
2708
2709 // Fence::merge is called, and since none of the fences are actually valid,
2710 // Fence::NO_FENCE is returned and passed to each onLayerDisplayed() call.
2711 // This is the best we can do without creating a real kernel fence object.
2712 EXPECT_CALL(mLayer1.layerFE, onLayerDisplayed(Fence::NO_FENCE));
2713 EXPECT_CALL(mLayer2.layerFE, onLayerDisplayed(Fence::NO_FENCE));
2714 EXPECT_CALL(mLayer3.layerFE, onLayerDisplayed(Fence::NO_FENCE));
2715
2716 mOutput.postFramebuffer();
2717}
2718
2719TEST_F(OutputPostFramebufferTest, releasedLayersSentPresentFence) {
2720 mOutput.mState.isEnabled = true;
2721 mOutput.mState.usesClientComposition = true;
2722
2723 // This should happen even if there are no (current) output layers.
2724 EXPECT_CALL(mOutput, getOutputLayerCount()).WillOnce(Return(0u));
2725
2726 // Load up the released layers with some mock instances
2727 sp<StrictMock<mock::LayerFE>> releasedLayer1{new StrictMock<mock::LayerFE>()};
2728 sp<StrictMock<mock::LayerFE>> releasedLayer2{new StrictMock<mock::LayerFE>()};
2729 sp<StrictMock<mock::LayerFE>> releasedLayer3{new StrictMock<mock::LayerFE>()};
2730 Output::ReleasedLayers layers;
2731 layers.push_back(releasedLayer1);
2732 layers.push_back(releasedLayer2);
2733 layers.push_back(releasedLayer3);
2734 mOutput.setReleasedLayers(std::move(layers));
2735
2736 // Set up a fake present fence
2737 sp<Fence> presentFence = new Fence();
Lloyd Piquefe0ee9e2019-11-22 16:30:30 -08002738 Output::FrameFences frameFences;
Lloyd Pique07178e32019-11-19 19:15:26 -08002739 frameFences.presentFence = presentFence;
2740
2741 EXPECT_CALL(*mRenderSurface, flip());
2742 EXPECT_CALL(mOutput, presentAndGetFrameFences()).WillOnce(Return(frameFences));
2743 EXPECT_CALL(*mRenderSurface, onPresentDisplayCompleted());
2744
2745 // Each released layer should be given the presentFence.
2746 EXPECT_CALL(*releasedLayer1,
2747 onLayerDisplayed(Property(&sp<Fence>::get, Eq(presentFence.get()))));
2748 EXPECT_CALL(*releasedLayer2,
2749 onLayerDisplayed(Property(&sp<Fence>::get, Eq(presentFence.get()))));
2750 EXPECT_CALL(*releasedLayer3,
2751 onLayerDisplayed(Property(&sp<Fence>::get, Eq(presentFence.get()))));
2752
2753 mOutput.postFramebuffer();
2754
2755 // After the call the list of released layers should have been cleared.
2756 EXPECT_TRUE(mOutput.getReleasedLayersForTest().empty());
2757}
Lloyd Piquefaa3f192019-11-14 14:05:09 -08002758
2759/*
Lloyd Pique56eba802019-08-28 15:45:25 -07002760 * Output::composeSurfaces()
2761 */
2762
2763struct OutputComposeSurfacesTest : public testing::Test {
Lloyd Pique6818fa52019-12-03 12:32:13 -08002764 using TestType = OutputComposeSurfacesTest;
Lloyd Pique56eba802019-08-28 15:45:25 -07002765
Lloyd Piquefaa3f192019-11-14 14:05:09 -08002766 struct OutputPartialMock : public OutputPartialMockBase {
Lloyd Pique739afaf2019-11-21 16:40:05 -08002767 // Sets up the helper functions called by the function under test to use
2768 // mock implementations.
Lloyd Pique56eba802019-08-28 15:45:25 -07002769 MOCK_CONST_METHOD0(getSkipColorTransform, bool());
Vishnu Nair3a7346c2019-12-04 08:09:09 -08002770 MOCK_METHOD3(generateClientCompositionRequests,
Vishnu Nair9b079a22020-01-21 14:36:08 -08002771 std::vector<LayerFE::LayerSettings>(bool, Region&, ui::Dataspace));
Lloyd Pique56eba802019-08-28 15:45:25 -07002772 MOCK_METHOD2(appendRegionFlashRequests,
Vishnu Nair9b079a22020-01-21 14:36:08 -08002773 void(const Region&, std::vector<LayerFE::LayerSettings>&));
Lloyd Pique56eba802019-08-28 15:45:25 -07002774 MOCK_METHOD1(setExpensiveRenderingExpected, void(bool));
2775 };
2776
2777 OutputComposeSurfacesTest() {
2778 mOutput.setDisplayColorProfileForTest(
2779 std::unique_ptr<DisplayColorProfile>(mDisplayColorProfile));
2780 mOutput.setRenderSurfaceForTest(std::unique_ptr<RenderSurface>(mRenderSurface));
Vishnu Nair9b079a22020-01-21 14:36:08 -08002781 mOutput.cacheClientCompositionRequests(MAX_CLIENT_COMPOSITION_CACHE_SIZE);
Lloyd Pique56eba802019-08-28 15:45:25 -07002782
Lloyd Pique6818fa52019-12-03 12:32:13 -08002783 mOutput.mState.frame = kDefaultOutputFrame;
2784 mOutput.mState.viewport = kDefaultOutputViewport;
2785 mOutput.mState.scissor = kDefaultOutputScissor;
2786 mOutput.mState.transform = ui::Transform{kDefaultOutputOrientation};
2787 mOutput.mState.orientation = kDefaultOutputOrientation;
2788 mOutput.mState.dataspace = kDefaultOutputDataspace;
2789 mOutput.mState.colorTransformMatrix = kDefaultColorTransformMat;
2790 mOutput.mState.isSecure = false;
2791 mOutput.mState.needsFiltering = false;
2792 mOutput.mState.usesClientComposition = true;
2793 mOutput.mState.usesDeviceComposition = false;
Vishnu Nair9b079a22020-01-21 14:36:08 -08002794 mOutput.mState.reusedClientComposition = false;
Lloyd Pique56eba802019-08-28 15:45:25 -07002795
Lloyd Piquea38ea7e2019-04-16 18:10:26 -07002796 EXPECT_CALL(mOutput, getCompositionEngine()).WillRepeatedly(ReturnRef(mCompositionEngine));
Lloyd Pique56eba802019-08-28 15:45:25 -07002797 EXPECT_CALL(mCompositionEngine, getRenderEngine()).WillRepeatedly(ReturnRef(mRenderEngine));
Alec Mourie4034bb2019-11-19 12:45:54 -08002798 EXPECT_CALL(mCompositionEngine, getTimeStats())
2799 .WillRepeatedly(ReturnRef(*mTimeStats.get()));
Lloyd Pique6818fa52019-12-03 12:32:13 -08002800 EXPECT_CALL(*mDisplayColorProfile, getHdrCapabilities())
2801 .WillRepeatedly(ReturnRef(kHdrCapabilities));
Lloyd Pique56eba802019-08-28 15:45:25 -07002802 }
2803
Lloyd Pique6818fa52019-12-03 12:32:13 -08002804 struct ExecuteState : public CallOrderStateMachineHelper<TestType, ExecuteState> {
2805 auto execute() {
2806 getInstance()->mReadyFence = getInstance()->mOutput.composeSurfaces(kDebugRegion);
2807 return nextState<FenceCheckState>();
2808 }
2809 };
2810
2811 struct FenceCheckState : public CallOrderStateMachineHelper<TestType, FenceCheckState> {
2812 void expectNoFenceWasReturned() { EXPECT_FALSE(getInstance()->mReadyFence); }
2813
2814 void expectAFenceWasReturned() { EXPECT_TRUE(getInstance()->mReadyFence); }
2815 };
2816
2817 // Call this member function to start using the mini-DSL defined above.
2818 [[nodiscard]] auto verify() { return ExecuteState::make(this); }
2819
2820 static constexpr uint32_t kDefaultOutputOrientation = TR_IDENT;
2821 static constexpr ui::Dataspace kDefaultOutputDataspace = ui::Dataspace::UNKNOWN;
2822 static constexpr ui::Dataspace kExpensiveOutputDataspace = ui::Dataspace::DISPLAY_P3;
2823 static constexpr float kDefaultMaxLuminance = 0.9f;
2824 static constexpr float kDefaultAvgLuminance = 0.7f;
2825 static constexpr float kDefaultMinLuminance = 0.1f;
2826
2827 static const Rect kDefaultOutputFrame;
2828 static const Rect kDefaultOutputViewport;
2829 static const Rect kDefaultOutputScissor;
2830 static const mat4 kDefaultColorTransformMat;
2831
2832 static const Region kDebugRegion;
2833 static const HdrCapabilities kHdrCapabilities;
2834
Lloyd Pique56eba802019-08-28 15:45:25 -07002835 StrictMock<mock::CompositionEngine> mCompositionEngine;
2836 StrictMock<renderengine::mock::RenderEngine> mRenderEngine;
Alec Mourie4034bb2019-11-19 12:45:54 -08002837 // TODO: make this is a proper mock.
2838 std::shared_ptr<TimeStats> mTimeStats = std::make_shared<android::impl::TimeStats>();
Lloyd Pique56eba802019-08-28 15:45:25 -07002839 mock::DisplayColorProfile* mDisplayColorProfile = new StrictMock<mock::DisplayColorProfile>();
2840 mock::RenderSurface* mRenderSurface = new StrictMock<mock::RenderSurface>();
Lloyd Piquea38ea7e2019-04-16 18:10:26 -07002841 StrictMock<OutputPartialMock> mOutput;
Lloyd Pique56eba802019-08-28 15:45:25 -07002842 sp<GraphicBuffer> mOutputBuffer = new GraphicBuffer();
Lloyd Pique6818fa52019-12-03 12:32:13 -08002843
2844 std::optional<base::unique_fd> mReadyFence;
Lloyd Pique56eba802019-08-28 15:45:25 -07002845};
2846
2847const Rect OutputComposeSurfacesTest::kDefaultOutputFrame{1001, 1002, 1003, 1004};
2848const Rect OutputComposeSurfacesTest::kDefaultOutputViewport{1005, 1006, 1007, 1008};
2849const Rect OutputComposeSurfacesTest::kDefaultOutputScissor{1009, 1010, 1011, 1012};
Lloyd Pique0a456232020-01-16 17:51:13 -08002850const mat4 OutputComposeSurfacesTest::kDefaultColorTransformMat{mat4() * 0.5f};
Lloyd Pique6818fa52019-12-03 12:32:13 -08002851const Region OutputComposeSurfacesTest::kDebugRegion{Rect{100, 101, 102, 103}};
2852const HdrCapabilities OutputComposeSurfacesTest::
2853 kHdrCapabilities{{},
2854 OutputComposeSurfacesTest::kDefaultMaxLuminance,
2855 OutputComposeSurfacesTest::kDefaultAvgLuminance,
2856 OutputComposeSurfacesTest::kDefaultMinLuminance};
Lloyd Pique56eba802019-08-28 15:45:25 -07002857
Lloyd Piquea76ce462020-01-14 13:06:37 -08002858TEST_F(OutputComposeSurfacesTest, doesNothingButSignalNoExpensiveRenderingIfNoClientComposition) {
Lloyd Pique6818fa52019-12-03 12:32:13 -08002859 mOutput.mState.usesClientComposition = false;
Lloyd Pique56eba802019-08-28 15:45:25 -07002860
Lloyd Piquea76ce462020-01-14 13:06:37 -08002861 EXPECT_CALL(mOutput, setExpensiveRenderingExpected(false));
2862
Lloyd Pique6818fa52019-12-03 12:32:13 -08002863 verify().execute().expectAFenceWasReturned();
Lloyd Pique56eba802019-08-28 15:45:25 -07002864}
2865
Lloyd Pique6818fa52019-12-03 12:32:13 -08002866TEST_F(OutputComposeSurfacesTest, doesMinimalWorkIfDequeueBufferFails) {
2867 EXPECT_CALL(mOutput, getSkipColorTransform()).WillRepeatedly(Return(false));
2868 EXPECT_CALL(*mDisplayColorProfile, hasWideColorGamut()).WillRepeatedly(Return(true));
2869 EXPECT_CALL(mRenderEngine, supportsProtectedContent()).WillRepeatedly(Return(false));
2870 EXPECT_CALL(mOutput, generateClientCompositionRequests(_, _, kDefaultOutputDataspace))
Vishnu Nair9b079a22020-01-21 14:36:08 -08002871 .WillRepeatedly(Return(std::vector<LayerFE::LayerSettings>{}));
Lloyd Pique6818fa52019-12-03 12:32:13 -08002872 EXPECT_CALL(mOutput, appendRegionFlashRequests(RegionEq(kDebugRegion), _))
2873 .WillRepeatedly(Return());
Lloyd Pique56eba802019-08-28 15:45:25 -07002874
Lloyd Pique6818fa52019-12-03 12:32:13 -08002875 EXPECT_CALL(*mRenderSurface, dequeueBuffer(_)).WillOnce(Return(nullptr));
Lloyd Pique56eba802019-08-28 15:45:25 -07002876
Lloyd Pique6818fa52019-12-03 12:32:13 -08002877 verify().execute().expectNoFenceWasReturned();
2878}
Lloyd Pique56eba802019-08-28 15:45:25 -07002879
Lloyd Pique6818fa52019-12-03 12:32:13 -08002880TEST_F(OutputComposeSurfacesTest, handlesZeroCompositionRequests) {
2881 EXPECT_CALL(mOutput, getSkipColorTransform()).WillRepeatedly(Return(false));
2882 EXPECT_CALL(*mDisplayColorProfile, hasWideColorGamut()).WillRepeatedly(Return(true));
2883 EXPECT_CALL(mRenderEngine, supportsProtectedContent()).WillRepeatedly(Return(false));
2884 EXPECT_CALL(mOutput, generateClientCompositionRequests(_, _, kDefaultOutputDataspace))
Vishnu Nair9b079a22020-01-21 14:36:08 -08002885 .WillRepeatedly(Return(std::vector<LayerFE::LayerSettings>{}));
Lloyd Pique6818fa52019-12-03 12:32:13 -08002886 EXPECT_CALL(mOutput, appendRegionFlashRequests(RegionEq(kDebugRegion), _))
2887 .WillRepeatedly(Return());
Lloyd Pique56eba802019-08-28 15:45:25 -07002888
Lloyd Pique6818fa52019-12-03 12:32:13 -08002889 EXPECT_CALL(*mRenderSurface, dequeueBuffer(_)).WillRepeatedly(Return(mOutputBuffer));
2890 EXPECT_CALL(mRenderEngine, drawLayers(_, IsEmpty(), _, true, _, _))
2891 .WillRepeatedly(Return(NO_ERROR));
Lloyd Pique56eba802019-08-28 15:45:25 -07002892
Lloyd Pique6818fa52019-12-03 12:32:13 -08002893 verify().execute().expectAFenceWasReturned();
2894}
Lloyd Pique56eba802019-08-28 15:45:25 -07002895
Lloyd Pique6818fa52019-12-03 12:32:13 -08002896TEST_F(OutputComposeSurfacesTest, buildsAndRendersRequestList) {
Vishnu Nair9b079a22020-01-21 14:36:08 -08002897 LayerFE::LayerSettings r1;
2898 LayerFE::LayerSettings r2;
Lloyd Pique6818fa52019-12-03 12:32:13 -08002899
2900 r1.geometry.boundaries = FloatRect{1, 2, 3, 4};
2901 r2.geometry.boundaries = FloatRect{5, 6, 7, 8};
2902
2903 EXPECT_CALL(mOutput, getSkipColorTransform()).WillRepeatedly(Return(false));
2904 EXPECT_CALL(*mDisplayColorProfile, hasWideColorGamut()).WillRepeatedly(Return(true));
2905 EXPECT_CALL(mRenderEngine, supportsProtectedContent()).WillRepeatedly(Return(false));
2906 EXPECT_CALL(mOutput, generateClientCompositionRequests(_, _, kDefaultOutputDataspace))
Vishnu Nair9b079a22020-01-21 14:36:08 -08002907 .WillRepeatedly(Return(std::vector<LayerFE::LayerSettings>{r1}));
Lloyd Pique6818fa52019-12-03 12:32:13 -08002908 EXPECT_CALL(mOutput, appendRegionFlashRequests(RegionEq(kDebugRegion), _))
2909 .WillRepeatedly(
2910 Invoke([&](const Region&,
Vishnu Nair9b079a22020-01-21 14:36:08 -08002911 std::vector<LayerFE::LayerSettings>& clientCompositionLayers) {
Lloyd Pique6818fa52019-12-03 12:32:13 -08002912 clientCompositionLayers.emplace_back(r2);
2913 }));
2914
2915 EXPECT_CALL(*mRenderSurface, dequeueBuffer(_)).WillRepeatedly(Return(mOutputBuffer));
Vishnu Nair9b079a22020-01-21 14:36:08 -08002916 EXPECT_CALL(mRenderEngine, drawLayers(_, ElementsAre(Pointee(r1), Pointee(r2)), _, true, _, _))
Lloyd Pique6818fa52019-12-03 12:32:13 -08002917 .WillRepeatedly(Return(NO_ERROR));
2918
2919 verify().execute().expectAFenceWasReturned();
2920}
2921
Vishnu Nair9b079a22020-01-21 14:36:08 -08002922TEST_F(OutputComposeSurfacesTest, renderDuplicateClientCompositionRequestsWithoutCache) {
2923 mOutput.cacheClientCompositionRequests(0);
2924 LayerFE::LayerSettings r1;
2925 LayerFE::LayerSettings r2;
2926
2927 r1.geometry.boundaries = FloatRect{1, 2, 3, 4};
2928 r2.geometry.boundaries = FloatRect{5, 6, 7, 8};
2929
2930 EXPECT_CALL(mOutput, getSkipColorTransform()).WillRepeatedly(Return(false));
2931 EXPECT_CALL(*mDisplayColorProfile, hasWideColorGamut()).WillRepeatedly(Return(true));
2932 EXPECT_CALL(mRenderEngine, supportsProtectedContent()).WillRepeatedly(Return(false));
2933 EXPECT_CALL(mOutput, generateClientCompositionRequests(_, _, kDefaultOutputDataspace))
2934 .WillRepeatedly(Return(std::vector<LayerFE::LayerSettings>{r1, r2}));
2935 EXPECT_CALL(mOutput, appendRegionFlashRequests(RegionEq(kDebugRegion), _))
2936 .WillRepeatedly(Return());
2937
2938 EXPECT_CALL(*mRenderSurface, dequeueBuffer(_)).WillRepeatedly(Return(mOutputBuffer));
2939 EXPECT_CALL(mRenderEngine, drawLayers(_, ElementsAre(Pointee(r1), Pointee(r2)), _, true, _, _))
2940 .Times(2)
2941 .WillOnce(Return(NO_ERROR));
2942
2943 verify().execute().expectAFenceWasReturned();
2944 EXPECT_FALSE(mOutput.mState.reusedClientComposition);
2945
2946 verify().execute().expectAFenceWasReturned();
2947 EXPECT_FALSE(mOutput.mState.reusedClientComposition);
2948}
2949
2950TEST_F(OutputComposeSurfacesTest, skipDuplicateClientCompositionRequests) {
2951 mOutput.cacheClientCompositionRequests(3);
2952 LayerFE::LayerSettings r1;
2953 LayerFE::LayerSettings r2;
2954
2955 r1.geometry.boundaries = FloatRect{1, 2, 3, 4};
2956 r2.geometry.boundaries = FloatRect{5, 6, 7, 8};
2957
2958 EXPECT_CALL(mOutput, getSkipColorTransform()).WillRepeatedly(Return(false));
2959 EXPECT_CALL(*mDisplayColorProfile, hasWideColorGamut()).WillRepeatedly(Return(true));
2960 EXPECT_CALL(mRenderEngine, supportsProtectedContent()).WillRepeatedly(Return(false));
2961 EXPECT_CALL(mOutput, generateClientCompositionRequests(_, _, kDefaultOutputDataspace))
2962 .WillRepeatedly(Return(std::vector<LayerFE::LayerSettings>{r1, r2}));
2963 EXPECT_CALL(mOutput, appendRegionFlashRequests(RegionEq(kDebugRegion), _))
2964 .WillRepeatedly(Return());
2965
2966 EXPECT_CALL(*mRenderSurface, dequeueBuffer(_)).WillRepeatedly(Return(mOutputBuffer));
2967 EXPECT_CALL(mRenderEngine, drawLayers(_, ElementsAre(Pointee(r1), Pointee(r2)), _, true, _, _))
2968 .WillOnce(Return(NO_ERROR));
2969 EXPECT_CALL(mOutput, setExpensiveRenderingExpected(false));
2970
2971 verify().execute().expectAFenceWasReturned();
2972 EXPECT_FALSE(mOutput.mState.reusedClientComposition);
2973
2974 // We do not expect another call to draw layers.
2975 verify().execute().expectAFenceWasReturned();
2976 EXPECT_TRUE(mOutput.mState.reusedClientComposition);
2977}
2978
2979TEST_F(OutputComposeSurfacesTest, clientCompositionIfBufferChanges) {
2980 LayerFE::LayerSettings r1;
2981 LayerFE::LayerSettings r2;
2982
2983 r1.geometry.boundaries = FloatRect{1, 2, 3, 4};
2984 r2.geometry.boundaries = FloatRect{5, 6, 7, 8};
2985
2986 EXPECT_CALL(mOutput, getSkipColorTransform()).WillRepeatedly(Return(false));
2987 EXPECT_CALL(*mDisplayColorProfile, hasWideColorGamut()).WillRepeatedly(Return(true));
2988 EXPECT_CALL(mRenderEngine, supportsProtectedContent()).WillRepeatedly(Return(false));
2989 EXPECT_CALL(mOutput, generateClientCompositionRequests(_, _, kDefaultOutputDataspace))
2990 .WillRepeatedly(Return(std::vector<LayerFE::LayerSettings>{r1, r2}));
2991 EXPECT_CALL(mOutput, appendRegionFlashRequests(RegionEq(kDebugRegion), _))
2992 .WillRepeatedly(Return());
2993
2994 sp<GraphicBuffer> otherOutputBuffer = new GraphicBuffer();
2995 EXPECT_CALL(*mRenderSurface, dequeueBuffer(_))
2996 .WillOnce(Return(mOutputBuffer))
2997 .WillOnce(Return(otherOutputBuffer));
2998 EXPECT_CALL(mRenderEngine, drawLayers(_, ElementsAre(Pointee(r1), Pointee(r2)), _, true, _, _))
2999 .WillRepeatedly(Return(NO_ERROR));
3000
3001 verify().execute().expectAFenceWasReturned();
3002 EXPECT_FALSE(mOutput.mState.reusedClientComposition);
3003
3004 verify().execute().expectAFenceWasReturned();
3005 EXPECT_FALSE(mOutput.mState.reusedClientComposition);
3006}
3007
3008TEST_F(OutputComposeSurfacesTest, clientCompositionIfRequestChanges) {
3009 LayerFE::LayerSettings r1;
3010 LayerFE::LayerSettings r2;
3011 LayerFE::LayerSettings r3;
3012
3013 r1.geometry.boundaries = FloatRect{1, 2, 3, 4};
3014 r2.geometry.boundaries = FloatRect{5, 6, 7, 8};
3015 r3.geometry.boundaries = FloatRect{5, 6, 7, 9};
3016
3017 EXPECT_CALL(mOutput, getSkipColorTransform()).WillRepeatedly(Return(false));
3018 EXPECT_CALL(*mDisplayColorProfile, hasWideColorGamut()).WillRepeatedly(Return(true));
3019 EXPECT_CALL(mRenderEngine, supportsProtectedContent()).WillRepeatedly(Return(false));
3020 EXPECT_CALL(mOutput, generateClientCompositionRequests(_, _, kDefaultOutputDataspace))
3021 .WillOnce(Return(std::vector<LayerFE::LayerSettings>{r1, r2}))
3022 .WillOnce(Return(std::vector<LayerFE::LayerSettings>{r1, r3}));
3023 EXPECT_CALL(mOutput, appendRegionFlashRequests(RegionEq(kDebugRegion), _))
3024 .WillRepeatedly(Return());
3025
3026 EXPECT_CALL(*mRenderSurface, dequeueBuffer(_)).WillRepeatedly(Return(mOutputBuffer));
3027 EXPECT_CALL(mRenderEngine, drawLayers(_, ElementsAre(Pointee(r1), Pointee(r2)), _, true, _, _))
3028 .WillOnce(Return(NO_ERROR));
3029 EXPECT_CALL(mRenderEngine, drawLayers(_, ElementsAre(Pointee(r1), Pointee(r3)), _, true, _, _))
3030 .WillOnce(Return(NO_ERROR));
3031
3032 verify().execute().expectAFenceWasReturned();
3033 EXPECT_FALSE(mOutput.mState.reusedClientComposition);
3034
3035 verify().execute().expectAFenceWasReturned();
3036 EXPECT_FALSE(mOutput.mState.reusedClientComposition);
3037}
3038
Lloyd Pique6818fa52019-12-03 12:32:13 -08003039struct OutputComposeSurfacesTest_UsesExpectedDisplaySettings : public OutputComposeSurfacesTest {
3040 OutputComposeSurfacesTest_UsesExpectedDisplaySettings() {
3041 EXPECT_CALL(mRenderEngine, supportsProtectedContent()).WillRepeatedly(Return(false));
3042 EXPECT_CALL(mOutput, generateClientCompositionRequests(_, _, kDefaultOutputDataspace))
Vishnu Nair9b079a22020-01-21 14:36:08 -08003043 .WillRepeatedly(Return(std::vector<LayerFE::LayerSettings>{}));
Lloyd Pique6818fa52019-12-03 12:32:13 -08003044 EXPECT_CALL(mOutput, appendRegionFlashRequests(RegionEq(kDebugRegion), _))
3045 .WillRepeatedly(Return());
3046 EXPECT_CALL(*mRenderSurface, dequeueBuffer(_)).WillRepeatedly(Return(mOutputBuffer));
3047 }
3048
3049 struct MixedCompositionState
3050 : public CallOrderStateMachineHelper<TestType, MixedCompositionState> {
3051 auto ifMixedCompositionIs(bool used) {
3052 getInstance()->mOutput.mState.usesDeviceComposition = used;
3053 return nextState<OutputUsesHdrState>();
3054 }
3055 };
3056
3057 struct OutputUsesHdrState : public CallOrderStateMachineHelper<TestType, OutputUsesHdrState> {
3058 auto andIfUsesHdr(bool used) {
3059 EXPECT_CALL(*getInstance()->mDisplayColorProfile, hasWideColorGamut())
3060 .WillOnce(Return(used));
3061 return nextState<SkipColorTransformState>();
3062 }
3063 };
3064
3065 struct SkipColorTransformState
3066 : public CallOrderStateMachineHelper<TestType, SkipColorTransformState> {
3067 auto andIfSkipColorTransform(bool skip) {
3068 // May be called zero or one times.
3069 EXPECT_CALL(getInstance()->mOutput, getSkipColorTransform())
3070 .WillRepeatedly(Return(skip));
3071 return nextState<ExpectDisplaySettingsState>();
3072 }
3073 };
3074
3075 struct ExpectDisplaySettingsState
3076 : public CallOrderStateMachineHelper<TestType, ExpectDisplaySettingsState> {
3077 auto thenExpectDisplaySettingsUsed(renderengine::DisplaySettings settings) {
3078 EXPECT_CALL(getInstance()->mRenderEngine, drawLayers(settings, _, _, true, _, _))
3079 .WillOnce(Return(NO_ERROR));
3080 return nextState<ExecuteState>();
3081 }
3082 };
3083
3084 // Call this member function to start using the mini-DSL defined above.
3085 [[nodiscard]] auto verify() { return MixedCompositionState::make(this); }
3086};
3087
3088TEST_F(OutputComposeSurfacesTest_UsesExpectedDisplaySettings, forHdrMixedComposition) {
3089 verify().ifMixedCompositionIs(true)
3090 .andIfUsesHdr(true)
3091 .andIfSkipColorTransform(false)
3092 .thenExpectDisplaySettingsUsed({kDefaultOutputScissor, kDefaultOutputScissor, mat4(),
3093 kDefaultMaxLuminance, kDefaultOutputDataspace, mat4(),
3094 Region::INVALID_REGION, kDefaultOutputOrientation})
3095 .execute()
3096 .expectAFenceWasReturned();
3097}
3098
3099TEST_F(OutputComposeSurfacesTest_UsesExpectedDisplaySettings, forNonHdrMixedComposition) {
3100 verify().ifMixedCompositionIs(true)
3101 .andIfUsesHdr(false)
3102 .andIfSkipColorTransform(false)
3103 .thenExpectDisplaySettingsUsed({kDefaultOutputScissor, kDefaultOutputScissor, mat4(),
3104 kDefaultMaxLuminance, kDefaultOutputDataspace, mat4(),
3105 Region::INVALID_REGION, kDefaultOutputOrientation})
3106 .execute()
3107 .expectAFenceWasReturned();
3108}
3109
3110TEST_F(OutputComposeSurfacesTest_UsesExpectedDisplaySettings, forHdrOnlyClientComposition) {
3111 verify().ifMixedCompositionIs(false)
3112 .andIfUsesHdr(true)
3113 .andIfSkipColorTransform(false)
3114 .thenExpectDisplaySettingsUsed({kDefaultOutputScissor, kDefaultOutputScissor, mat4(),
3115 kDefaultMaxLuminance, kDefaultOutputDataspace,
3116 kDefaultColorTransformMat, Region::INVALID_REGION,
3117 kDefaultOutputOrientation})
3118 .execute()
3119 .expectAFenceWasReturned();
3120}
3121
3122TEST_F(OutputComposeSurfacesTest_UsesExpectedDisplaySettings, forNonHdrOnlyClientComposition) {
3123 verify().ifMixedCompositionIs(false)
3124 .andIfUsesHdr(false)
3125 .andIfSkipColorTransform(false)
3126 .thenExpectDisplaySettingsUsed({kDefaultOutputScissor, kDefaultOutputScissor, mat4(),
3127 kDefaultMaxLuminance, kDefaultOutputDataspace,
3128 kDefaultColorTransformMat, Region::INVALID_REGION,
3129 kDefaultOutputOrientation})
3130 .execute()
3131 .expectAFenceWasReturned();
3132}
3133
3134TEST_F(OutputComposeSurfacesTest_UsesExpectedDisplaySettings,
3135 usesExpectedDisplaySettingsForHdrOnlyClientCompositionWithSkipClientTransform) {
3136 verify().ifMixedCompositionIs(false)
3137 .andIfUsesHdr(true)
3138 .andIfSkipColorTransform(true)
3139 .thenExpectDisplaySettingsUsed({kDefaultOutputScissor, kDefaultOutputScissor, mat4(),
3140 kDefaultMaxLuminance, kDefaultOutputDataspace, mat4(),
3141 Region::INVALID_REGION, kDefaultOutputOrientation})
3142 .execute()
3143 .expectAFenceWasReturned();
3144}
3145
3146struct OutputComposeSurfacesTest_HandlesProtectedContent : public OutputComposeSurfacesTest {
3147 struct Layer {
3148 Layer() {
3149 EXPECT_CALL(mOutputLayer, getLayer()).WillRepeatedly(ReturnRef(mLayer));
3150 EXPECT_CALL(mLayer, getFEState()).WillRepeatedly(ReturnRef(mLayerFEState));
3151 }
3152
3153 StrictMock<mock::OutputLayer> mOutputLayer;
3154 StrictMock<mock::Layer> mLayer;
3155 LayerFECompositionState mLayerFEState;
3156 };
3157
3158 OutputComposeSurfacesTest_HandlesProtectedContent() {
3159 mLayer1.mLayerFEState.hasProtectedContent = false;
3160 mLayer2.mLayerFEState.hasProtectedContent = false;
3161
3162 EXPECT_CALL(mOutput, getOutputLayerCount()).WillRepeatedly(Return(2u));
3163 EXPECT_CALL(mOutput, getOutputLayerOrderedByZByIndex(0u))
3164 .WillRepeatedly(Return(&mLayer1.mOutputLayer));
3165 EXPECT_CALL(mOutput, getOutputLayerOrderedByZByIndex(1u))
3166 .WillRepeatedly(Return(&mLayer2.mOutputLayer));
3167
3168 EXPECT_CALL(mOutput, getSkipColorTransform()).WillRepeatedly(Return(false));
3169
3170 EXPECT_CALL(*mDisplayColorProfile, hasWideColorGamut()).WillRepeatedly(Return(true));
3171
3172 EXPECT_CALL(mOutput, generateClientCompositionRequests(_, _, _))
Vishnu Nair9b079a22020-01-21 14:36:08 -08003173 .WillRepeatedly(Return(std::vector<LayerFE::LayerSettings>{}));
Lloyd Pique6818fa52019-12-03 12:32:13 -08003174 EXPECT_CALL(mOutput, appendRegionFlashRequests(RegionEq(kDebugRegion), _))
3175 .WillRepeatedly(Return());
3176 EXPECT_CALL(*mRenderSurface, dequeueBuffer(_)).WillRepeatedly(Return(mOutputBuffer));
3177 EXPECT_CALL(mRenderEngine, drawLayers(_, _, _, true, _, _))
3178 .WillRepeatedly(Return(NO_ERROR));
3179 }
3180
3181 Layer mLayer1;
3182 Layer mLayer2;
3183};
3184
3185TEST_F(OutputComposeSurfacesTest_HandlesProtectedContent, ifDisplayIsNotSecure) {
3186 mOutput.mState.isSecure = false;
3187 mLayer2.mLayerFEState.hasProtectedContent = true;
3188 EXPECT_CALL(mRenderEngine, supportsProtectedContent()).WillRepeatedly(Return(true));
3189
3190 mOutput.composeSurfaces(kDebugRegion);
3191}
3192
3193TEST_F(OutputComposeSurfacesTest_HandlesProtectedContent, ifRenderEngineDoesNotSupportIt) {
3194 mOutput.mState.isSecure = true;
3195 mLayer2.mLayerFEState.hasProtectedContent = true;
3196 EXPECT_CALL(mRenderEngine, supportsProtectedContent()).WillRepeatedly(Return(false));
3197
3198 mOutput.composeSurfaces(kDebugRegion);
3199}
3200
3201TEST_F(OutputComposeSurfacesTest_HandlesProtectedContent, ifNoProtectedContentLayers) {
3202 mOutput.mState.isSecure = true;
3203 mLayer2.mLayerFEState.hasProtectedContent = false;
3204 EXPECT_CALL(mRenderEngine, supportsProtectedContent()).WillRepeatedly(Return(true));
3205 EXPECT_CALL(mRenderEngine, isProtected).WillOnce(Return(true)).WillOnce(Return(false));
3206 EXPECT_CALL(*mRenderSurface, isProtected).WillOnce(Return(true));
3207 EXPECT_CALL(mRenderEngine, useProtectedContext(false));
3208 EXPECT_CALL(*mRenderSurface, setProtected(false));
3209
3210 mOutput.composeSurfaces(kDebugRegion);
3211}
3212
3213TEST_F(OutputComposeSurfacesTest_HandlesProtectedContent, ifNotEnabled) {
3214 mOutput.mState.isSecure = true;
3215 mLayer2.mLayerFEState.hasProtectedContent = true;
3216 EXPECT_CALL(mRenderEngine, supportsProtectedContent()).WillRepeatedly(Return(true));
3217
3218 // For this test, we also check the call order of key functions.
3219 InSequence seq;
3220
3221 EXPECT_CALL(mRenderEngine, isProtected).WillOnce(Return(false));
3222 EXPECT_CALL(mRenderEngine, useProtectedContext(true));
3223 EXPECT_CALL(*mRenderSurface, isProtected).WillOnce(Return(false));
3224 EXPECT_CALL(mRenderEngine, isProtected).WillOnce(Return(true));
3225 EXPECT_CALL(*mRenderSurface, setProtected(true));
3226 // Must happen after setting the protected content state.
3227 EXPECT_CALL(*mRenderSurface, dequeueBuffer(_)).WillRepeatedly(Return(mOutputBuffer));
3228 EXPECT_CALL(mRenderEngine, drawLayers(_, _, _, true, _, _)).WillOnce(Return(NO_ERROR));
3229
3230 mOutput.composeSurfaces(kDebugRegion);
3231}
3232
3233TEST_F(OutputComposeSurfacesTest_HandlesProtectedContent, ifAlreadyEnabledEverywhere) {
3234 mOutput.mState.isSecure = true;
3235 mLayer2.mLayerFEState.hasProtectedContent = true;
3236 EXPECT_CALL(mRenderEngine, supportsProtectedContent()).WillRepeatedly(Return(true));
3237 EXPECT_CALL(mRenderEngine, isProtected).WillOnce(Return(true));
3238 EXPECT_CALL(*mRenderSurface, isProtected).WillOnce(Return(true));
3239
3240 mOutput.composeSurfaces(kDebugRegion);
3241}
3242
3243TEST_F(OutputComposeSurfacesTest_HandlesProtectedContent, ifFailsToEnableInRenderEngine) {
3244 mOutput.mState.isSecure = true;
3245 mLayer2.mLayerFEState.hasProtectedContent = true;
3246 EXPECT_CALL(mRenderEngine, supportsProtectedContent()).WillRepeatedly(Return(true));
3247 EXPECT_CALL(mRenderEngine, isProtected).WillOnce(Return(false)).WillOnce(Return(false));
3248 EXPECT_CALL(*mRenderSurface, isProtected).WillOnce(Return(false));
3249 EXPECT_CALL(mRenderEngine, useProtectedContext(true));
3250
3251 mOutput.composeSurfaces(kDebugRegion);
3252}
3253
3254TEST_F(OutputComposeSurfacesTest_HandlesProtectedContent, ifAlreadyEnabledInRenderEngine) {
3255 mOutput.mState.isSecure = true;
3256 mLayer2.mLayerFEState.hasProtectedContent = true;
3257 EXPECT_CALL(mRenderEngine, supportsProtectedContent()).WillRepeatedly(Return(true));
3258 EXPECT_CALL(mRenderEngine, isProtected).WillOnce(Return(true)).WillOnce(Return(true));
3259 EXPECT_CALL(*mRenderSurface, isProtected).WillOnce(Return(false));
3260 EXPECT_CALL(*mRenderSurface, setProtected(true));
3261
3262 mOutput.composeSurfaces(kDebugRegion);
3263}
3264
3265TEST_F(OutputComposeSurfacesTest_HandlesProtectedContent, ifAlreadyEnabledInRenderSurface) {
3266 mOutput.mState.isSecure = true;
3267 mLayer2.mLayerFEState.hasProtectedContent = true;
3268 EXPECT_CALL(mRenderEngine, supportsProtectedContent()).WillRepeatedly(Return(true));
3269 EXPECT_CALL(mRenderEngine, isProtected).WillOnce(Return(false));
3270 EXPECT_CALL(*mRenderSurface, isProtected).WillOnce(Return(true));
3271 EXPECT_CALL(mRenderEngine, useProtectedContext(true));
3272
3273 mOutput.composeSurfaces(kDebugRegion);
3274}
3275
3276struct OutputComposeSurfacesTest_SetsExpensiveRendering : public OutputComposeSurfacesTest {
3277 OutputComposeSurfacesTest_SetsExpensiveRendering() {
3278 EXPECT_CALL(mOutput, getSkipColorTransform()).WillRepeatedly(Return(false));
3279 EXPECT_CALL(*mDisplayColorProfile, hasWideColorGamut()).WillRepeatedly(Return(true));
3280 EXPECT_CALL(mRenderEngine, supportsProtectedContent()).WillRepeatedly(Return(false));
3281 EXPECT_CALL(mOutput, appendRegionFlashRequests(RegionEq(kDebugRegion), _))
3282 .WillRepeatedly(Return());
3283 EXPECT_CALL(*mRenderSurface, dequeueBuffer(_)).WillRepeatedly(Return(mOutputBuffer));
3284 }
3285};
3286
3287TEST_F(OutputComposeSurfacesTest_SetsExpensiveRendering, IfExepensiveOutputDataspaceIsUsed) {
3288 mOutput.mState.dataspace = kExpensiveOutputDataspace;
3289
3290 EXPECT_CALL(mOutput, generateClientCompositionRequests(_, _, kExpensiveOutputDataspace))
Vishnu Nair9b079a22020-01-21 14:36:08 -08003291 .WillOnce(Return(std::vector<LayerFE::LayerSettings>{}));
Lloyd Pique6818fa52019-12-03 12:32:13 -08003292
3293 // For this test, we also check the call order of key functions.
3294 InSequence seq;
3295
3296 EXPECT_CALL(mOutput, setExpensiveRenderingExpected(true));
3297 EXPECT_CALL(mRenderEngine, drawLayers(_, _, _, true, _, _)).WillOnce(Return(NO_ERROR));
Lloyd Pique6818fa52019-12-03 12:32:13 -08003298
3299 mOutput.composeSurfaces(kDebugRegion);
Lloyd Pique56eba802019-08-28 15:45:25 -07003300}
3301
3302/*
3303 * Output::generateClientCompositionRequests()
3304 */
3305
3306struct GenerateClientCompositionRequestsTest : public testing::Test {
Lloyd Piquefaa3f192019-11-14 14:05:09 -08003307 struct OutputPartialMock : public OutputPartialMockBase {
Lloyd Piquea38ea7e2019-04-16 18:10:26 -07003308 // compositionengine::Output overrides
Vishnu Nair9b079a22020-01-21 14:36:08 -08003309 std::vector<LayerFE::LayerSettings> generateClientCompositionRequests(
Vishnu Nair3a7346c2019-12-04 08:09:09 -08003310 bool supportsProtectedContent, Region& clearRegion,
3311 ui::Dataspace dataspace) override {
Lloyd Pique56eba802019-08-28 15:45:25 -07003312 return impl::Output::generateClientCompositionRequests(supportsProtectedContent,
Vishnu Nair3a7346c2019-12-04 08:09:09 -08003313 clearRegion, dataspace);
Lloyd Pique56eba802019-08-28 15:45:25 -07003314 }
3315 };
3316
Lloyd Piquea4863342019-12-04 18:45:02 -08003317 struct Layer {
3318 Layer() {
3319 EXPECT_CALL(mOutputLayer, getState()).WillRepeatedly(ReturnRef(mOutputLayerState));
3320 EXPECT_CALL(mOutputLayer, editState()).WillRepeatedly(ReturnRef(mOutputLayerState));
3321 EXPECT_CALL(mOutputLayer, getLayer()).WillRepeatedly(ReturnRef(mLayer));
3322 EXPECT_CALL(mOutputLayer, getLayerFE()).WillRepeatedly(ReturnRef(mLayerFE));
3323 EXPECT_CALL(mLayer, getFEState()).WillRepeatedly(ReturnRef(mLayerFEState));
3324 }
3325
3326 StrictMock<mock::OutputLayer> mOutputLayer;
3327 StrictMock<mock::Layer> mLayer;
3328 StrictMock<mock::LayerFE> mLayerFE;
3329 LayerFECompositionState mLayerFEState;
3330 impl::OutputLayerCompositionState mOutputLayerState;
Vishnu Nair9b079a22020-01-21 14:36:08 -08003331 LayerFE::LayerSettings mLayerSettings;
Lloyd Piquea4863342019-12-04 18:45:02 -08003332 };
3333
Lloyd Pique56eba802019-08-28 15:45:25 -07003334 GenerateClientCompositionRequestsTest() {
Lloyd Piquea4863342019-12-04 18:45:02 -08003335 mOutput.mState.needsFiltering = false;
3336
Lloyd Pique56eba802019-08-28 15:45:25 -07003337 mOutput.setDisplayColorProfileForTest(
3338 std::unique_ptr<DisplayColorProfile>(mDisplayColorProfile));
3339 mOutput.setRenderSurfaceForTest(std::unique_ptr<RenderSurface>(mRenderSurface));
3340 }
3341
Lloyd Pique56eba802019-08-28 15:45:25 -07003342 mock::DisplayColorProfile* mDisplayColorProfile = new StrictMock<mock::DisplayColorProfile>();
3343 mock::RenderSurface* mRenderSurface = new StrictMock<mock::RenderSurface>();
Lloyd Piquea38ea7e2019-04-16 18:10:26 -07003344 StrictMock<OutputPartialMock> mOutput;
Lloyd Pique56eba802019-08-28 15:45:25 -07003345};
3346
Lloyd Piquea4863342019-12-04 18:45:02 -08003347struct GenerateClientCompositionRequestsTest_ThreeLayers
3348 : public GenerateClientCompositionRequestsTest {
3349 GenerateClientCompositionRequestsTest_ThreeLayers() {
3350 mOutput.mState.frame = kDisplayFrame;
3351 mOutput.mState.viewport = kDisplayViewport;
3352 mOutput.mState.scissor = kDisplayScissor;
3353 mOutput.mState.transform = ui::Transform{kDisplayOrientation};
3354 mOutput.mState.orientation = kDisplayOrientation;
3355 mOutput.mState.needsFiltering = false;
3356 mOutput.mState.isSecure = false;
Lloyd Pique56eba802019-08-28 15:45:25 -07003357
Lloyd Piquea4863342019-12-04 18:45:02 -08003358 for (size_t i = 0; i < mLayers.size(); i++) {
3359 mLayers[i].mOutputLayerState.clearClientTarget = false;
3360 mLayers[i].mOutputLayerState.visibleRegion = Region(kDisplayFrame);
3361 mLayers[i].mLayerFEState.isOpaque = true;
Vishnu Nair9b079a22020-01-21 14:36:08 -08003362 mLayers[i].mLayerSettings.geometry.boundaries =
Lloyd Piquea4863342019-12-04 18:45:02 -08003363 FloatRect{static_cast<float>(i + 1), 0.f, 0.f, 0.f};
Vishnu Nair9b079a22020-01-21 14:36:08 -08003364 mLayers[i].mLayerSettings.source.solidColor = {1.0f, 1.0f, 1.0f};
3365 mLayers[i].mLayerSettings.alpha = 1.0f;
3366 mLayers[i].mLayerSettings.disableBlending = false;
Lloyd Pique56eba802019-08-28 15:45:25 -07003367
Lloyd Piquea4863342019-12-04 18:45:02 -08003368 EXPECT_CALL(mOutput, getOutputLayerOrderedByZByIndex(i))
3369 .WillRepeatedly(Return(&mLayers[i].mOutputLayer));
3370 EXPECT_CALL(mLayers[i].mOutputLayer, requiresClientComposition())
3371 .WillRepeatedly(Return(true));
3372 EXPECT_CALL(mLayers[i].mOutputLayer, needsFiltering()).WillRepeatedly(Return(false));
3373 }
Lloyd Pique56eba802019-08-28 15:45:25 -07003374
Lloyd Piquea4863342019-12-04 18:45:02 -08003375 EXPECT_CALL(mOutput, getOutputLayerCount()).WillRepeatedly(Return(mLayers.size()));
3376 }
Lloyd Pique56eba802019-08-28 15:45:25 -07003377
Lloyd Piquea4863342019-12-04 18:45:02 -08003378 static constexpr uint32_t kDisplayOrientation = TR_IDENT;
3379 static constexpr ui::Dataspace kDisplayDataspace = ui::Dataspace::UNKNOWN;
Lloyd Pique56eba802019-08-28 15:45:25 -07003380
Lloyd Piquea4863342019-12-04 18:45:02 -08003381 static const Rect kDisplayFrame;
3382 static const Rect kDisplayViewport;
3383 static const Rect kDisplayScissor;
Lloyd Pique56eba802019-08-28 15:45:25 -07003384
Lloyd Piquea4863342019-12-04 18:45:02 -08003385 std::array<Layer, 3> mLayers;
3386};
Lloyd Pique56eba802019-08-28 15:45:25 -07003387
Lloyd Piquea4863342019-12-04 18:45:02 -08003388const Rect GenerateClientCompositionRequestsTest_ThreeLayers::kDisplayFrame(0, 0, 100, 200);
3389const Rect GenerateClientCompositionRequestsTest_ThreeLayers::kDisplayViewport(0, 0, 101, 201);
3390const Rect GenerateClientCompositionRequestsTest_ThreeLayers::kDisplayScissor(0, 0, 102, 202);
Lloyd Pique56eba802019-08-28 15:45:25 -07003391
Lloyd Piquea4863342019-12-04 18:45:02 -08003392TEST_F(GenerateClientCompositionRequestsTest_ThreeLayers, handlesNoClientCompostionLayers) {
3393 EXPECT_CALL(mLayers[0].mOutputLayer, requiresClientComposition()).WillOnce(Return(false));
3394 EXPECT_CALL(mLayers[1].mOutputLayer, requiresClientComposition()).WillOnce(Return(false));
3395 EXPECT_CALL(mLayers[2].mOutputLayer, requiresClientComposition()).WillOnce(Return(false));
Lloyd Pique56eba802019-08-28 15:45:25 -07003396
Lloyd Piquea4863342019-12-04 18:45:02 -08003397 Region accumClearRegion(Rect(10, 11, 12, 13));
3398 auto requests = mOutput.generateClientCompositionRequests(false /* supportsProtectedContent */,
3399 accumClearRegion, kDisplayDataspace);
Lloyd Pique56eba802019-08-28 15:45:25 -07003400 EXPECT_EQ(0u, requests.size());
Lloyd Piquea4863342019-12-04 18:45:02 -08003401 EXPECT_THAT(accumClearRegion, RegionEq(Region(Rect(10, 11, 12, 13))));
Lloyd Pique56eba802019-08-28 15:45:25 -07003402}
3403
Lloyd Piquea4863342019-12-04 18:45:02 -08003404TEST_F(GenerateClientCompositionRequestsTest_ThreeLayers, requiresVisibleRegionAfterViewportClip) {
3405 mLayers[0].mOutputLayerState.visibleRegion = Region(Rect(10, 10, 10, 10));
3406 mLayers[1].mOutputLayerState.visibleRegion = Region(Rect(4000, 0, 4010, 10));
3407 mLayers[2].mOutputLayerState.visibleRegion = Region(Rect(-10, -10, 0, 0));
3408
3409 Region accumClearRegion(Rect(10, 11, 12, 13));
3410 auto requests = mOutput.generateClientCompositionRequests(false /* supportsProtectedContent */,
3411 accumClearRegion, kDisplayDataspace);
3412 EXPECT_EQ(0u, requests.size());
3413 EXPECT_THAT(accumClearRegion, RegionEq(Region(Rect(10, 11, 12, 13))));
3414}
3415
3416TEST_F(GenerateClientCompositionRequestsTest_ThreeLayers, gathersClientCompositionRequests) {
Vishnu Nair9b079a22020-01-21 14:36:08 -08003417 LayerFE::LayerSettings mShadowSettings;
3418 mShadowSettings.source.solidColor = {0.1f, 0.1f, 0.1f};
Lloyd Piquea4863342019-12-04 18:45:02 -08003419
3420 EXPECT_CALL(mLayers[0].mLayerFE, prepareClientComposition(_)).WillOnce(Return(std::nullopt));
3421 EXPECT_CALL(mLayers[1].mLayerFE, prepareClientComposition(_))
Vishnu Nair9b079a22020-01-21 14:36:08 -08003422 .WillOnce(Return(mLayers[1].mLayerSettings));
Lloyd Piquea4863342019-12-04 18:45:02 -08003423 EXPECT_CALL(mLayers[1].mLayerFE,
Vishnu Nair9b079a22020-01-21 14:36:08 -08003424 prepareShadowClientComposition(mLayers[1].mLayerSettings, kDisplayViewport,
Lloyd Piquea4863342019-12-04 18:45:02 -08003425 kDisplayDataspace))
3426 .WillOnce(Return(std::nullopt));
3427 EXPECT_CALL(mLayers[2].mLayerFE, prepareClientComposition(_))
Vishnu Nair9b079a22020-01-21 14:36:08 -08003428 .WillOnce(Return(mLayers[2].mLayerSettings));
Lloyd Piquea4863342019-12-04 18:45:02 -08003429 EXPECT_CALL(mLayers[2].mLayerFE,
Vishnu Nair9b079a22020-01-21 14:36:08 -08003430 prepareShadowClientComposition(mLayers[2].mLayerSettings, kDisplayViewport,
Lloyd Piquea4863342019-12-04 18:45:02 -08003431 kDisplayDataspace))
Vishnu Nair9b079a22020-01-21 14:36:08 -08003432 .WillOnce(Return(mShadowSettings));
Lloyd Piquea4863342019-12-04 18:45:02 -08003433
3434 Region accumClearRegion(Rect(10, 11, 12, 13));
3435 auto requests = mOutput.generateClientCompositionRequests(false /* supportsProtectedContent */,
3436 accumClearRegion, kDisplayDataspace);
3437 ASSERT_EQ(3u, requests.size());
Vishnu Nair9b079a22020-01-21 14:36:08 -08003438 EXPECT_EQ(mLayers[1].mLayerSettings, requests[0]);
3439 EXPECT_EQ(mShadowSettings, requests[1]);
3440 EXPECT_EQ(mLayers[2].mLayerSettings, requests[2]);
Lloyd Piquea4863342019-12-04 18:45:02 -08003441
3442 EXPECT_THAT(accumClearRegion, RegionEq(Region(Rect(10, 11, 12, 13))));
3443
3444 // Check that a timestamp was set for the layers that generated requests
3445 EXPECT_TRUE(0 == mLayers[0].mOutputLayerState.clientCompositionTimestamp);
3446 EXPECT_TRUE(0 != mLayers[1].mOutputLayerState.clientCompositionTimestamp);
3447 EXPECT_TRUE(0 != mLayers[2].mOutputLayerState.clientCompositionTimestamp);
3448}
3449
3450TEST_F(GenerateClientCompositionRequestsTest_ThreeLayers,
3451 onlyClientComposesClientComposedLayersIfNoClearingNeeded) {
3452 EXPECT_CALL(mLayers[0].mOutputLayer, requiresClientComposition()).WillOnce(Return(false));
3453 EXPECT_CALL(mLayers[1].mOutputLayer, requiresClientComposition()).WillOnce(Return(false));
3454 EXPECT_CALL(mLayers[2].mOutputLayer, requiresClientComposition()).WillOnce(Return(true));
3455
3456 mLayers[0].mOutputLayerState.clearClientTarget = false;
3457 mLayers[1].mOutputLayerState.clearClientTarget = false;
3458 mLayers[2].mOutputLayerState.clearClientTarget = false;
3459
3460 mLayers[0].mLayerFEState.isOpaque = true;
3461 mLayers[1].mLayerFEState.isOpaque = true;
3462 mLayers[2].mLayerFEState.isOpaque = true;
3463
3464 EXPECT_CALL(mLayers[2].mLayerFE, prepareClientComposition(_))
Vishnu Nair9b079a22020-01-21 14:36:08 -08003465 .WillOnce(Return(mLayers[2].mLayerSettings));
Lloyd Piquea4863342019-12-04 18:45:02 -08003466 EXPECT_CALL(mLayers[2].mLayerFE, prepareShadowClientComposition(_, _, _))
3467 .WillOnce(Return(std::nullopt));
3468
3469 Region accumClearRegion(Rect(10, 11, 12, 13));
3470 auto requests = mOutput.generateClientCompositionRequests(false /* supportsProtectedContent */,
3471 accumClearRegion, kDisplayDataspace);
3472 ASSERT_EQ(1u, requests.size());
Vishnu Nair9b079a22020-01-21 14:36:08 -08003473 EXPECT_EQ(mLayers[2].mLayerSettings, requests[0]);
Lloyd Piquea4863342019-12-04 18:45:02 -08003474
3475 EXPECT_THAT(accumClearRegion, RegionEq(Region(Rect(10, 11, 12, 13))));
3476}
3477
3478TEST_F(GenerateClientCompositionRequestsTest_ThreeLayers,
3479 onlyClientComposesClientComposedLayersIfOthersAreNotOpaque) {
3480 EXPECT_CALL(mLayers[0].mOutputLayer, requiresClientComposition()).WillOnce(Return(false));
3481 EXPECT_CALL(mLayers[1].mOutputLayer, requiresClientComposition()).WillOnce(Return(false));
3482 EXPECT_CALL(mLayers[2].mOutputLayer, requiresClientComposition()).WillOnce(Return(true));
3483
3484 mLayers[0].mOutputLayerState.clearClientTarget = true;
3485 mLayers[1].mOutputLayerState.clearClientTarget = true;
3486 mLayers[2].mOutputLayerState.clearClientTarget = true;
3487
3488 mLayers[0].mLayerFEState.isOpaque = false;
3489 mLayers[1].mLayerFEState.isOpaque = false;
3490 mLayers[2].mLayerFEState.isOpaque = false;
3491
3492 EXPECT_CALL(mLayers[2].mLayerFE, prepareClientComposition(_))
Vishnu Nair9b079a22020-01-21 14:36:08 -08003493 .WillOnce(Return(mLayers[2].mLayerSettings));
Lloyd Piquea4863342019-12-04 18:45:02 -08003494 EXPECT_CALL(mLayers[2].mLayerFE, prepareShadowClientComposition(_, _, _))
3495 .WillOnce(Return(std::nullopt));
3496
3497 Region accumClearRegion(Rect(10, 11, 12, 13));
3498 auto requests = mOutput.generateClientCompositionRequests(false /* supportsProtectedContent */,
3499 accumClearRegion, kDisplayDataspace);
3500 ASSERT_EQ(1u, requests.size());
Vishnu Nair9b079a22020-01-21 14:36:08 -08003501 EXPECT_EQ(mLayers[2].mLayerSettings, requests[0]);
Lloyd Piquea4863342019-12-04 18:45:02 -08003502
3503 EXPECT_THAT(accumClearRegion, RegionEq(Region(Rect(10, 11, 12, 13))));
3504}
3505
3506TEST_F(GenerateClientCompositionRequestsTest_ThreeLayers, clearsHWCLayersIfOpaqueAndNotFirst) {
Lloyd Piquec2d54d42019-08-28 18:04:21 -07003507 // If client composition is performed with some layers set to use device
3508 // composition, device layers after the first layer (device or client) will
3509 // clear the frame buffer if they are opaque and if that layer has a flag
3510 // set to do so. The first layer is skipped as the frame buffer is already
3511 // expected to be clear.
3512
Lloyd Piquea4863342019-12-04 18:45:02 -08003513 EXPECT_CALL(mLayers[0].mOutputLayer, requiresClientComposition()).WillOnce(Return(false));
3514 EXPECT_CALL(mLayers[1].mOutputLayer, requiresClientComposition()).WillOnce(Return(false));
3515 EXPECT_CALL(mLayers[2].mOutputLayer, requiresClientComposition()).WillOnce(Return(true));
Lloyd Piquec2d54d42019-08-28 18:04:21 -07003516
Lloyd Piquea4863342019-12-04 18:45:02 -08003517 mLayers[0].mOutputLayerState.clearClientTarget = true;
3518 mLayers[1].mOutputLayerState.clearClientTarget = true;
3519 mLayers[2].mOutputLayerState.clearClientTarget = true;
Lloyd Piquec2d54d42019-08-28 18:04:21 -07003520
Lloyd Piquea4863342019-12-04 18:45:02 -08003521 mLayers[0].mLayerFEState.isOpaque = true;
3522 mLayers[1].mLayerFEState.isOpaque = true;
3523 mLayers[2].mLayerFEState.isOpaque = true;
Lloyd Piquec2d54d42019-08-28 18:04:21 -07003524
Lloyd Piquea4863342019-12-04 18:45:02 -08003525 EXPECT_CALL(mLayers[1].mLayerFE, prepareClientComposition(_))
Vishnu Nair9b079a22020-01-21 14:36:08 -08003526 .WillOnce(Return(mLayers[1].mLayerSettings));
Lloyd Piquea4863342019-12-04 18:45:02 -08003527 EXPECT_CALL(mLayers[2].mLayerFE, prepareClientComposition(_))
Vishnu Nair9b079a22020-01-21 14:36:08 -08003528 .WillOnce(Return(mLayers[2].mLayerSettings));
Lloyd Piquea4863342019-12-04 18:45:02 -08003529 EXPECT_CALL(mLayers[2].mLayerFE, prepareShadowClientComposition(_, _, _))
3530 .WillOnce(Return(std::nullopt));
Lloyd Piquec2d54d42019-08-28 18:04:21 -07003531
Lloyd Piquea4863342019-12-04 18:45:02 -08003532 Region accumClearRegion(Rect(10, 11, 12, 13));
3533 auto requests = mOutput.generateClientCompositionRequests(false /* supportsProtectedContent */,
3534 accumClearRegion, kDisplayDataspace);
3535 ASSERT_EQ(2u, requests.size());
Lloyd Piquec2d54d42019-08-28 18:04:21 -07003536
Lloyd Piquea4863342019-12-04 18:45:02 -08003537 // The second layer is expected to be rendered as alpha=0 black with no blending
Vishnu Nair9b079a22020-01-21 14:36:08 -08003538 EXPECT_EQ(mLayers[1].mLayerSettings.geometry.boundaries, requests[0].geometry.boundaries);
Lloyd Piquea4863342019-12-04 18:45:02 -08003539 EXPECT_FALSE(requests[0].source.buffer.buffer);
3540 EXPECT_EQ((half3{0.f, 0.f, 0.f}), requests[0].source.solidColor);
Lloyd Pique0a456232020-01-16 17:51:13 -08003541 EXPECT_EQ(0.f, static_cast<float>(requests[0].alpha));
Lloyd Piquea4863342019-12-04 18:45:02 -08003542 EXPECT_EQ(true, requests[0].disableBlending);
Lloyd Piquec2d54d42019-08-28 18:04:21 -07003543
Vishnu Nair9b079a22020-01-21 14:36:08 -08003544 EXPECT_EQ(mLayers[2].mLayerSettings, requests[1]);
Lloyd Piquec2d54d42019-08-28 18:04:21 -07003545
Lloyd Piquea4863342019-12-04 18:45:02 -08003546 EXPECT_THAT(accumClearRegion, RegionEq(Region(Rect(10, 11, 12, 13))));
3547}
Lloyd Piquec2d54d42019-08-28 18:04:21 -07003548
Lloyd Piquea4863342019-12-04 18:45:02 -08003549TEST_F(GenerateClientCompositionRequestsTest_ThreeLayers,
3550 clippedVisibleRegionUsedToGenerateRequest) {
3551 mLayers[0].mOutputLayerState.visibleRegion = Region(Rect(10, 10, 20, 20));
3552 mLayers[1].mOutputLayerState.visibleRegion = Region(Rect(-10, -10, 30, 30));
3553 mLayers[2].mOutputLayerState.visibleRegion = Region(Rect(-10, 0, 40, 4000));
Lloyd Piquec2d54d42019-08-28 18:04:21 -07003554
Lloyd Piquea4863342019-12-04 18:45:02 -08003555 Region accumClearRegion(Rect(10, 11, 12, 13));
3556
3557 compositionengine::LayerFE::ClientCompositionTargetSettings layer0TargetSettings{
3558 Region(Rect(10, 10, 20, 20)),
3559 false, /* identity transform */
3560 false, /* needs filtering */
3561 false, /* secure */
3562 false, /* supports protected content */
3563 accumClearRegion,
3564 };
3565 compositionengine::LayerFE::ClientCompositionTargetSettings layer1TargetSettings{
3566 Region(Rect(0, 0, 30, 30)),
3567 false, /* identity transform */
3568 false, /* needs filtering */
3569 false, /* secure */
3570 false, /* supports protected content */
3571 accumClearRegion,
3572 };
3573 compositionengine::LayerFE::ClientCompositionTargetSettings layer2TargetSettings{
3574 Region(Rect(0, 0, 40, 201)),
3575 false, /* identity transform */
3576 false, /* needs filtering */
3577 false, /* secure */
3578 false, /* supports protected content */
3579 accumClearRegion,
3580 };
3581
3582 EXPECT_CALL(mLayers[0].mLayerFE, prepareClientComposition(Eq(ByRef(layer0TargetSettings))))
3583 .WillOnce(Return(std::nullopt));
3584 EXPECT_CALL(mLayers[1].mLayerFE, prepareClientComposition(Eq(ByRef(layer1TargetSettings))))
3585 .WillOnce(Return(std::nullopt));
3586 EXPECT_CALL(mLayers[2].mLayerFE, prepareClientComposition(Eq(ByRef(layer2TargetSettings))))
3587 .WillOnce(Return(std::nullopt));
3588
3589 static_cast<void>(
3590 mOutput.generateClientCompositionRequests(false /* supportsProtectedContent */,
3591 accumClearRegion, kDisplayDataspace));
3592}
3593
3594TEST_F(GenerateClientCompositionRequestsTest_ThreeLayers,
3595 perLayerNeedsFilteringUsedToGenerateRequests) {
3596 mOutput.mState.needsFiltering = false;
3597 EXPECT_CALL(mLayers[0].mOutputLayer, needsFiltering()).WillRepeatedly(Return(true));
3598
3599 Region accumClearRegion(Rect(10, 11, 12, 13));
3600
3601 compositionengine::LayerFE::ClientCompositionTargetSettings layer0TargetSettings{
3602 Region(kDisplayFrame),
3603 false, /* identity transform */
3604 true, /* needs filtering */
3605 false, /* secure */
3606 false, /* supports protected content */
3607 accumClearRegion,
3608 };
3609 compositionengine::LayerFE::ClientCompositionTargetSettings layer1TargetSettings{
3610 Region(kDisplayFrame),
3611 false, /* identity transform */
3612 false, /* needs filtering */
3613 false, /* secure */
3614 false, /* supports protected content */
3615 accumClearRegion,
3616 };
3617 compositionengine::LayerFE::ClientCompositionTargetSettings layer2TargetSettings{
3618 Region(kDisplayFrame),
3619 false, /* identity transform */
3620 false, /* needs filtering */
3621 false, /* secure */
3622 false, /* supports protected content */
3623 accumClearRegion,
3624 };
3625
3626 EXPECT_CALL(mLayers[0].mLayerFE, prepareClientComposition(Eq(ByRef(layer0TargetSettings))))
3627 .WillOnce(Return(std::nullopt));
3628 EXPECT_CALL(mLayers[1].mLayerFE, prepareClientComposition(Eq(ByRef(layer1TargetSettings))))
3629 .WillOnce(Return(std::nullopt));
3630 EXPECT_CALL(mLayers[2].mLayerFE, prepareClientComposition(Eq(ByRef(layer2TargetSettings))))
3631 .WillOnce(Return(std::nullopt));
3632
3633 static_cast<void>(
3634 mOutput.generateClientCompositionRequests(false /* supportsProtectedContent */,
3635 accumClearRegion, kDisplayDataspace));
3636}
3637
3638TEST_F(GenerateClientCompositionRequestsTest_ThreeLayers,
3639 wholeOutputNeedsFilteringUsedToGenerateRequests) {
3640 mOutput.mState.needsFiltering = true;
3641 EXPECT_CALL(mLayers[0].mOutputLayer, needsFiltering()).WillRepeatedly(Return(true));
3642
3643 Region accumClearRegion(Rect(10, 11, 12, 13));
3644
3645 compositionengine::LayerFE::ClientCompositionTargetSettings layer0TargetSettings{
3646 Region(kDisplayFrame),
3647 false, /* identity transform */
3648 true, /* needs filtering */
3649 false, /* secure */
3650 false, /* supports protected content */
3651 accumClearRegion,
3652 };
3653 compositionengine::LayerFE::ClientCompositionTargetSettings layer1TargetSettings{
3654 Region(kDisplayFrame),
3655 false, /* identity transform */
3656 true, /* needs filtering */
3657 false, /* secure */
3658 false, /* supports protected content */
3659 accumClearRegion,
3660 };
3661 compositionengine::LayerFE::ClientCompositionTargetSettings layer2TargetSettings{
3662 Region(kDisplayFrame),
3663 false, /* identity transform */
3664 true, /* needs filtering */
3665 false, /* secure */
3666 false, /* supports protected content */
3667 accumClearRegion,
3668 };
3669
3670 EXPECT_CALL(mLayers[0].mLayerFE, prepareClientComposition(Eq(ByRef(layer0TargetSettings))))
3671 .WillOnce(Return(std::nullopt));
3672 EXPECT_CALL(mLayers[1].mLayerFE, prepareClientComposition(Eq(ByRef(layer1TargetSettings))))
3673 .WillOnce(Return(std::nullopt));
3674 EXPECT_CALL(mLayers[2].mLayerFE, prepareClientComposition(Eq(ByRef(layer2TargetSettings))))
3675 .WillOnce(Return(std::nullopt));
3676
3677 static_cast<void>(
3678 mOutput.generateClientCompositionRequests(false /* supportsProtectedContent */,
3679 accumClearRegion, kDisplayDataspace));
3680}
3681
3682TEST_F(GenerateClientCompositionRequestsTest_ThreeLayers,
3683 wholeOutputSecurityUsedToGenerateRequests) {
3684 mOutput.mState.isSecure = true;
3685
3686 Region accumClearRegion(Rect(10, 11, 12, 13));
3687
3688 compositionengine::LayerFE::ClientCompositionTargetSettings layer0TargetSettings{
3689 Region(kDisplayFrame),
3690 false, /* identity transform */
3691 false, /* needs filtering */
3692 true, /* secure */
3693 false, /* supports protected content */
3694 accumClearRegion,
3695 };
3696 compositionengine::LayerFE::ClientCompositionTargetSettings layer1TargetSettings{
3697 Region(kDisplayFrame),
3698 false, /* identity transform */
3699 false, /* needs filtering */
3700 true, /* secure */
3701 false, /* supports protected content */
3702 accumClearRegion,
3703 };
3704 compositionengine::LayerFE::ClientCompositionTargetSettings layer2TargetSettings{
3705 Region(kDisplayFrame),
3706 false, /* identity transform */
3707 false, /* needs filtering */
3708 true, /* secure */
3709 false, /* supports protected content */
3710 accumClearRegion,
3711 };
3712
3713 EXPECT_CALL(mLayers[0].mLayerFE, prepareClientComposition(Eq(ByRef(layer0TargetSettings))))
3714 .WillOnce(Return(std::nullopt));
3715 EXPECT_CALL(mLayers[1].mLayerFE, prepareClientComposition(Eq(ByRef(layer1TargetSettings))))
3716 .WillOnce(Return(std::nullopt));
3717 EXPECT_CALL(mLayers[2].mLayerFE, prepareClientComposition(Eq(ByRef(layer2TargetSettings))))
3718 .WillOnce(Return(std::nullopt));
3719
3720 static_cast<void>(
3721 mOutput.generateClientCompositionRequests(false /* supportsProtectedContent */,
3722 accumClearRegion, kDisplayDataspace));
3723}
3724
3725TEST_F(GenerateClientCompositionRequestsTest_ThreeLayers,
3726 protectedContentSupportUsedToGenerateRequests) {
3727 Region accumClearRegion(Rect(10, 11, 12, 13));
3728
3729 compositionengine::LayerFE::ClientCompositionTargetSettings layer0TargetSettings{
3730 Region(kDisplayFrame),
3731 false, /* identity transform */
3732 false, /* needs filtering */
3733 false, /* secure */
3734 true, /* supports protected content */
3735 accumClearRegion,
3736 };
3737 compositionengine::LayerFE::ClientCompositionTargetSettings layer1TargetSettings{
3738 Region(kDisplayFrame),
3739 false, /* identity transform */
3740 false, /* needs filtering */
3741 false, /* secure */
3742 true, /* supports protected content */
3743 accumClearRegion,
3744 };
3745 compositionengine::LayerFE::ClientCompositionTargetSettings layer2TargetSettings{
3746 Region(kDisplayFrame),
3747 false, /* identity transform */
3748 false, /* needs filtering */
3749 false, /* secure */
3750 true, /* supports protected content */
3751 accumClearRegion,
3752 };
3753
3754 EXPECT_CALL(mLayers[0].mLayerFE, prepareClientComposition(Eq(ByRef(layer0TargetSettings))))
3755 .WillOnce(Return(std::nullopt));
3756 EXPECT_CALL(mLayers[1].mLayerFE, prepareClientComposition(Eq(ByRef(layer1TargetSettings))))
3757 .WillOnce(Return(std::nullopt));
3758 EXPECT_CALL(mLayers[2].mLayerFE, prepareClientComposition(Eq(ByRef(layer2TargetSettings))))
3759 .WillOnce(Return(std::nullopt));
3760
3761 static_cast<void>(mOutput.generateClientCompositionRequests(true /* supportsProtectedContent */,
3762 accumClearRegion,
3763 kDisplayDataspace));
3764}
3765
Lucas Dupin19c8f0e2019-11-25 17:55:44 -08003766TEST_F(OutputUpdateAndWriteCompositionStateTest, handlesBackgroundBlurRequests) {
3767 // Layer requesting blur, or below, should request client composition.
3768 EXPECT_CALL(*mOutputLayer1, updateCompositionState(false, true));
3769 EXPECT_CALL(*mOutputLayer1, writeStateToHWC(false));
3770 EXPECT_CALL(*mOutputLayer2, updateCompositionState(false, true));
3771 EXPECT_CALL(*mOutputLayer2, writeStateToHWC(false));
3772 EXPECT_CALL(*mOutputLayer3, updateCompositionState(false, false));
3773 EXPECT_CALL(*mOutputLayer3, writeStateToHWC(false));
3774
3775 mLayer2FEState.backgroundBlurRadius = 10;
3776
3777 injectLayer(std::move(mOutputLayer1));
3778 injectLayer(std::move(mOutputLayer2));
3779 injectLayer(std::move(mOutputLayer3));
3780
3781 mOutput->editState().isEnabled = true;
3782
3783 CompositionRefreshArgs args;
3784 args.updatingGeometryThisFrame = false;
3785 args.devOptForceClientComposition = false;
3786 mOutput->updateAndWriteCompositionState(args);
3787}
3788
Lloyd Piquea4863342019-12-04 18:45:02 -08003789TEST_F(GenerateClientCompositionRequestsTest, handlesLandscapeModeSplitScreenRequests) {
3790 // In split-screen landscape mode, the screen is rotated 90 degrees, with
3791 // one layer on the left covering the left side of the output, and one layer
3792 // on the right covering that side of the output.
Lloyd Piquec2d54d42019-08-28 18:04:21 -07003793
3794 const Rect kPortraitFrame(0, 0, 1000, 2000);
3795 const Rect kPortraitViewport(0, 0, 2000, 1000);
3796 const Rect kPortraitScissor(0, 0, 1000, 2000);
3797 const uint32_t kPortraitOrientation = TR_ROT_90;
Lloyd Piquea4863342019-12-04 18:45:02 -08003798 constexpr ui::Dataspace kOutputDataspace = ui::Dataspace::DISPLAY_P3;
Lloyd Piquec2d54d42019-08-28 18:04:21 -07003799
Lloyd Piquea4863342019-12-04 18:45:02 -08003800 mOutput.mState.frame = kPortraitFrame;
3801 mOutput.mState.viewport = kPortraitViewport;
3802 mOutput.mState.scissor = kPortraitScissor;
3803 mOutput.mState.transform = ui::Transform{kPortraitOrientation};
3804 mOutput.mState.orientation = kPortraitOrientation;
3805 mOutput.mState.needsFiltering = false;
3806 mOutput.mState.isSecure = true;
Lloyd Piquec2d54d42019-08-28 18:04:21 -07003807
Lloyd Piquea4863342019-12-04 18:45:02 -08003808 Layer leftLayer;
3809 Layer rightLayer;
Lloyd Piquec2d54d42019-08-28 18:04:21 -07003810
Lloyd Piquea4863342019-12-04 18:45:02 -08003811 leftLayer.mOutputLayerState.clearClientTarget = false;
3812 leftLayer.mOutputLayerState.visibleRegion = Region(Rect(0, 0, 1000, 1000));
3813 leftLayer.mLayerFEState.isOpaque = true;
Vishnu Nair9b079a22020-01-21 14:36:08 -08003814 leftLayer.mLayerSettings.source.solidColor = {1.f, 0.f, 0.f};
Lloyd Piquec2d54d42019-08-28 18:04:21 -07003815
Lloyd Piquea4863342019-12-04 18:45:02 -08003816 rightLayer.mOutputLayerState.clearClientTarget = false;
3817 rightLayer.mOutputLayerState.visibleRegion = Region(Rect(1000, 0, 2000, 1000));
3818 rightLayer.mLayerFEState.isOpaque = true;
Vishnu Nair9b079a22020-01-21 14:36:08 -08003819 rightLayer.mLayerSettings.source.solidColor = {0.f, 1.f, 0.f};
Lloyd Piquea4863342019-12-04 18:45:02 -08003820
3821 EXPECT_CALL(mOutput, getOutputLayerCount()).WillRepeatedly(Return(2u));
3822 EXPECT_CALL(mOutput, getOutputLayerOrderedByZByIndex(0u))
3823 .WillRepeatedly(Return(&leftLayer.mOutputLayer));
3824 EXPECT_CALL(mOutput, getOutputLayerOrderedByZByIndex(1u))
3825 .WillRepeatedly(Return(&rightLayer.mOutputLayer));
3826
3827 Region accumClearRegion(Rect(10, 11, 12, 13));
3828
3829 compositionengine::LayerFE::ClientCompositionTargetSettings leftLayerSettings{
3830 Region(Rect(0, 0, 1000, 1000)),
3831 false, /* identity transform */
3832 false, /* needs filtering */
3833 true, /* secure */
3834 true, /* supports protected content */
3835 accumClearRegion,
3836 };
3837
3838 EXPECT_CALL(leftLayer.mOutputLayer, requiresClientComposition()).WillRepeatedly(Return(true));
3839 EXPECT_CALL(leftLayer.mOutputLayer, needsFiltering()).WillRepeatedly(Return(false));
3840 EXPECT_CALL(leftLayer.mLayerFE, prepareClientComposition(Eq(ByRef(leftLayerSettings))))
Vishnu Nair9b079a22020-01-21 14:36:08 -08003841 .WillOnce(Return(leftLayer.mLayerSettings));
Lloyd Piquea4863342019-12-04 18:45:02 -08003842 EXPECT_CALL(leftLayer.mLayerFE,
Vishnu Nair9b079a22020-01-21 14:36:08 -08003843 prepareShadowClientComposition(leftLayer.mLayerSettings, kPortraitViewport,
Lloyd Piquea4863342019-12-04 18:45:02 -08003844 kOutputDataspace))
3845 .WillOnce(Return(std::nullopt));
3846
3847 compositionengine::LayerFE::ClientCompositionTargetSettings rightLayerSettings{
3848 Region(Rect(1000, 0, 2000, 1000)),
3849 false, /* identity transform */
3850 false, /* needs filtering */
3851 true, /* secure */
3852 true, /* supports protected content */
3853 accumClearRegion,
3854 };
3855
3856 EXPECT_CALL(rightLayer.mOutputLayer, requiresClientComposition()).WillRepeatedly(Return(true));
3857 EXPECT_CALL(rightLayer.mOutputLayer, needsFiltering()).WillRepeatedly(Return(false));
3858 EXPECT_CALL(rightLayer.mLayerFE, prepareClientComposition(Eq(ByRef(rightLayerSettings))))
Vishnu Nair9b079a22020-01-21 14:36:08 -08003859 .WillOnce(Return(rightLayer.mLayerSettings));
Lloyd Piquea4863342019-12-04 18:45:02 -08003860 EXPECT_CALL(rightLayer.mLayerFE,
Vishnu Nair9b079a22020-01-21 14:36:08 -08003861 prepareShadowClientComposition(rightLayer.mLayerSettings, kPortraitViewport,
Lloyd Piquea4863342019-12-04 18:45:02 -08003862 kOutputDataspace))
3863 .WillOnce(Return(std::nullopt));
3864
3865 constexpr bool supportsProtectedContent = true;
3866 auto requests = mOutput.generateClientCompositionRequests(supportsProtectedContent,
3867 accumClearRegion, kOutputDataspace);
3868 ASSERT_EQ(2u, requests.size());
Vishnu Nair9b079a22020-01-21 14:36:08 -08003869 EXPECT_EQ(leftLayer.mLayerSettings, requests[0]);
3870 EXPECT_EQ(rightLayer.mLayerSettings, requests[1]);
Lloyd Piquec2d54d42019-08-28 18:04:21 -07003871}
3872
Vishnu Naira483b4a2019-12-12 15:07:52 -08003873TEST_F(GenerateClientCompositionRequestsTest_ThreeLayers,
3874 shadowRegionOnlyVisibleSkipsContentComposition) {
3875 const Rect kContentWithShadow(40, 40, 70, 90);
3876 const Rect kContent(50, 50, 60, 80);
3877 const Region kShadowRegion = Region(kContentWithShadow).subtract(kContent);
3878 const Region kPartialShadowRegion = Region(kContentWithShadow).subtract(Rect(40, 40, 60, 80));
3879
Vishnu Nair9b079a22020-01-21 14:36:08 -08003880 LayerFE::LayerSettings mShadowSettings;
3881 mShadowSettings.source.solidColor = {0.1f, 0.1f, 0.1f};
Vishnu Naira483b4a2019-12-12 15:07:52 -08003882
3883 mLayers[2].mOutputLayerState.visibleRegion = kPartialShadowRegion;
3884 mLayers[2].mOutputLayerState.shadowRegion = kShadowRegion;
3885
3886 EXPECT_CALL(mLayers[0].mOutputLayer, requiresClientComposition()).WillOnce(Return(false));
3887 EXPECT_CALL(mLayers[1].mOutputLayer, requiresClientComposition()).WillOnce(Return(false));
3888 EXPECT_CALL(mLayers[2].mLayerFE, prepareClientComposition(_))
Vishnu Nair9b079a22020-01-21 14:36:08 -08003889 .WillOnce(Return(mLayers[2].mLayerSettings));
Vishnu Naira483b4a2019-12-12 15:07:52 -08003890 EXPECT_CALL(mLayers[2].mLayerFE,
Vishnu Nair9b079a22020-01-21 14:36:08 -08003891 prepareShadowClientComposition(mLayers[2].mLayerSettings, kDisplayViewport,
Vishnu Naira483b4a2019-12-12 15:07:52 -08003892 kDisplayDataspace))
Vishnu Nair9b079a22020-01-21 14:36:08 -08003893 .WillOnce(Return(mShadowSettings));
Vishnu Naira483b4a2019-12-12 15:07:52 -08003894
3895 Region accumClearRegion(Rect(10, 11, 12, 13));
3896 auto requests = mOutput.generateClientCompositionRequests(false /* supportsProtectedContent */,
3897 accumClearRegion, kDisplayDataspace);
3898 ASSERT_EQ(1u, requests.size());
3899
Vishnu Nair9b079a22020-01-21 14:36:08 -08003900 EXPECT_EQ(mShadowSettings, requests[0]);
Vishnu Naira483b4a2019-12-12 15:07:52 -08003901}
3902
3903TEST_F(GenerateClientCompositionRequestsTest_ThreeLayers,
3904 shadowRegionWithContentVisibleRequestsContentAndShadowComposition) {
3905 const Rect kContentWithShadow(40, 40, 70, 90);
3906 const Rect kContent(50, 50, 60, 80);
3907 const Region kShadowRegion = Region(kContentWithShadow).subtract(kContent);
3908 const Region kPartialContentWithPartialShadowRegion =
3909 Region(kContentWithShadow).subtract(Rect(40, 40, 50, 80));
3910
Vishnu Nair9b079a22020-01-21 14:36:08 -08003911 LayerFE::LayerSettings mShadowSettings;
3912 mShadowSettings.source.solidColor = {0.1f, 0.1f, 0.1f};
Vishnu Naira483b4a2019-12-12 15:07:52 -08003913
3914 mLayers[2].mOutputLayerState.visibleRegion = kPartialContentWithPartialShadowRegion;
3915 mLayers[2].mOutputLayerState.shadowRegion = kShadowRegion;
3916
3917 EXPECT_CALL(mLayers[0].mOutputLayer, requiresClientComposition()).WillOnce(Return(false));
3918 EXPECT_CALL(mLayers[1].mOutputLayer, requiresClientComposition()).WillOnce(Return(false));
3919 EXPECT_CALL(mLayers[2].mLayerFE, prepareClientComposition(_))
Vishnu Nair9b079a22020-01-21 14:36:08 -08003920 .WillOnce(Return(mLayers[2].mLayerSettings));
Vishnu Naira483b4a2019-12-12 15:07:52 -08003921 EXPECT_CALL(mLayers[2].mLayerFE,
Vishnu Nair9b079a22020-01-21 14:36:08 -08003922 prepareShadowClientComposition(mLayers[2].mLayerSettings, kDisplayViewport,
Vishnu Naira483b4a2019-12-12 15:07:52 -08003923 kDisplayDataspace))
Vishnu Nair9b079a22020-01-21 14:36:08 -08003924 .WillOnce(Return(mShadowSettings));
Vishnu Naira483b4a2019-12-12 15:07:52 -08003925
3926 Region accumClearRegion(Rect(10, 11, 12, 13));
3927 auto requests = mOutput.generateClientCompositionRequests(false /* supportsProtectedContent */,
3928 accumClearRegion, kDisplayDataspace);
3929 ASSERT_EQ(2u, requests.size());
3930
Vishnu Nair9b079a22020-01-21 14:36:08 -08003931 EXPECT_EQ(mShadowSettings, requests[0]);
3932 EXPECT_EQ(mLayers[2].mLayerSettings, requests[1]);
Vishnu Naira483b4a2019-12-12 15:07:52 -08003933}
3934
Lloyd Pique32cbe282018-10-19 13:09:22 -07003935} // namespace
3936} // namespace android::compositionengine
Ady Abrahamb0dbdaa2020-01-06 16:19:42 -08003937
3938// TODO(b/129481165): remove the #pragma below and fix conversion issues
3939#pragma clang diagnostic pop // ignored "-Wconversion"