blob: 80528e3cb9475b096d5fd7864c4b0bb244dae186 [file] [log] [blame]
Lloyd Pique32cbe282018-10-19 13:09:22 -07001/*
2 * Copyright 2019 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#include <cmath>
18
Lloyd Pique17ca7422019-11-14 14:24:10 -080019#include <android-base/stringprintf.h>
Lloyd Pique9755fb72019-03-26 14:44:40 -070020#include <compositionengine/LayerFECompositionState.h>
Lloyd Pique32cbe282018-10-19 13:09:22 -070021#include <compositionengine/impl/Output.h>
Lloyd Pique66d68602019-02-13 14:23:31 -080022#include <compositionengine/impl/OutputCompositionState.h>
Lloyd Pique56eba802019-08-28 15:45:25 -070023#include <compositionengine/impl/OutputLayerCompositionState.h>
Lloyd Pique32cbe282018-10-19 13:09:22 -070024#include <compositionengine/mock/CompositionEngine.h>
Lloyd Pique3d0c02e2018-10-19 18:38:12 -070025#include <compositionengine/mock/DisplayColorProfile.h>
Lloyd Piquecc01a452018-12-04 17:24:00 -080026#include <compositionengine/mock/Layer.h>
27#include <compositionengine/mock/LayerFE.h>
28#include <compositionengine/mock/OutputLayer.h>
Lloyd Pique31cb2942018-10-19 17:23:03 -070029#include <compositionengine/mock/RenderSurface.h>
Lloyd Pique32cbe282018-10-19 13:09:22 -070030#include <gtest/gtest.h>
Lloyd Pique56eba802019-08-28 15:45:25 -070031#include <renderengine/mock/RenderEngine.h>
Lloyd Pique32cbe282018-10-19 13:09:22 -070032#include <ui/Rect.h>
33#include <ui/Region.h>
34
Lloyd Pique17ca7422019-11-14 14:24:10 -080035#include "CallOrderStateMachineHelper.h"
Lloyd Pique07178e32019-11-19 19:15:26 -080036#include "MockHWC2.h"
Lloyd Pique32cbe282018-10-19 13:09:22 -070037#include "RegionMatcher.h"
Lloyd Pique32cbe282018-10-19 13:09:22 -070038
39namespace android::compositionengine {
40namespace {
41
Lloyd Pique56eba802019-08-28 15:45:25 -070042using testing::_;
Lloyd Pique03561a62019-11-19 18:34:52 -080043using testing::ByMove;
Lloyd Piquea4863342019-12-04 18:45:02 -080044using testing::ByRef;
Lloyd Pique17ca7422019-11-14 14:24:10 -080045using testing::DoAll;
Lloyd Pique6818fa52019-12-03 12:32:13 -080046using testing::ElementsAreArray;
Lloyd Pique07178e32019-11-19 19:15:26 -080047using testing::Eq;
Lloyd Piquefaa3f192019-11-14 14:05:09 -080048using testing::InSequence;
Lloyd Pique6818fa52019-12-03 12:32:13 -080049using testing::Invoke;
50using testing::IsEmpty;
Lloyd Pique17ca7422019-11-14 14:24:10 -080051using testing::Mock;
Lloyd Pique07178e32019-11-19 19:15:26 -080052using testing::Property;
Lloyd Piquefaa3f192019-11-14 14:05:09 -080053using testing::Ref;
Lloyd Pique31cb2942018-10-19 17:23:03 -070054using testing::Return;
Lloyd Pique32cbe282018-10-19 13:09:22 -070055using testing::ReturnRef;
Lloyd Pique17ca7422019-11-14 14:24:10 -080056using testing::SetArgPointee;
Lloyd Pique32cbe282018-10-19 13:09:22 -070057using testing::StrictMock;
58
Lloyd Pique56eba802019-08-28 15:45:25 -070059constexpr auto TR_IDENT = 0u;
60constexpr auto TR_ROT_90 = HAL_TRANSFORM_ROT_90;
61
Lloyd Pique3eb1b212019-03-07 21:15:40 -080062const mat4 kIdentity;
63const mat4 kNonIdentityHalf = mat4() * 0.5;
64const mat4 kNonIdentityQuarter = mat4() * 0.25;
65
Lloyd Pique17ca7422019-11-14 14:24:10 -080066constexpr OutputColorSetting kVendorSpecifiedOutputColorSetting =
67 static_cast<OutputColorSetting>(0x100);
68
Lloyd Piquefaa3f192019-11-14 14:05:09 -080069struct OutputPartialMockBase : public impl::Output {
70 // compositionengine::Output overrides
71 const OutputCompositionState& getState() const override { return mState; }
72 OutputCompositionState& editState() override { return mState; }
73
74 // Use mocks for all the remaining virtual functions
75 // not implemented by the base implementation class.
76 MOCK_CONST_METHOD0(getOutputLayerCount, size_t());
77 MOCK_CONST_METHOD1(getOutputLayerOrderedByZByIndex, compositionengine::OutputLayer*(size_t));
78 MOCK_METHOD3(ensureOutputLayer,
79 compositionengine::OutputLayer*(std::optional<size_t>,
80 const std::shared_ptr<compositionengine::Layer>&,
81 const sp<LayerFE>&));
82 MOCK_METHOD0(finalizePendingOutputLayers, void());
83 MOCK_METHOD0(clearOutputLayers, void());
84 MOCK_CONST_METHOD1(dumpState, void(std::string&));
85 MOCK_CONST_METHOD0(getCompositionEngine, const CompositionEngine&());
86 MOCK_METHOD2(injectOutputLayerForTest,
87 compositionengine::OutputLayer*(const std::shared_ptr<compositionengine::Layer>&,
88 const sp<LayerFE>&));
89 MOCK_METHOD1(injectOutputLayerForTest, void(std::unique_ptr<OutputLayer>));
90
91 impl::OutputCompositionState mState;
92};
93
Lloyd Pique66d68602019-02-13 14:23:31 -080094struct OutputTest : public testing::Test {
Lloyd Pique01c77c12019-04-17 12:48:32 -070095 class Output : public impl::Output {
96 public:
97 using impl::Output::injectOutputLayerForTest;
98 virtual void injectOutputLayerForTest(std::unique_ptr<compositionengine::OutputLayer>) = 0;
99 };
100
101 static std::shared_ptr<Output> createOutput(
102 const compositionengine::CompositionEngine& compositionEngine) {
103 return impl::createOutputTemplated<Output>(compositionEngine);
104 }
105
Lloyd Pique31cb2942018-10-19 17:23:03 -0700106 OutputTest() {
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700107 mOutput->setDisplayColorProfileForTest(
Lloyd Pique3d0c02e2018-10-19 18:38:12 -0700108 std::unique_ptr<DisplayColorProfile>(mDisplayColorProfile));
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700109 mOutput->setRenderSurfaceForTest(std::unique_ptr<RenderSurface>(mRenderSurface));
Lloyd Piqueef958122019-02-05 18:00:12 -0800110
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700111 mOutput->editState().bounds = kDefaultDisplaySize;
Lloyd Pique31cb2942018-10-19 17:23:03 -0700112 }
Lloyd Pique32cbe282018-10-19 13:09:22 -0700113
Lloyd Piqueef958122019-02-05 18:00:12 -0800114 static const Rect kDefaultDisplaySize;
115
Lloyd Pique32cbe282018-10-19 13:09:22 -0700116 StrictMock<mock::CompositionEngine> mCompositionEngine;
Lloyd Pique3d0c02e2018-10-19 18:38:12 -0700117 mock::DisplayColorProfile* mDisplayColorProfile = new StrictMock<mock::DisplayColorProfile>();
Lloyd Pique31cb2942018-10-19 17:23:03 -0700118 mock::RenderSurface* mRenderSurface = new StrictMock<mock::RenderSurface>();
Lloyd Pique01c77c12019-04-17 12:48:32 -0700119 std::shared_ptr<Output> mOutput = createOutput(mCompositionEngine);
Lloyd Pique32cbe282018-10-19 13:09:22 -0700120};
121
Lloyd Piquec0ee6ba2019-11-14 12:55:53 -0800122// Extension of the base test useful for checking interactions with the LayerFE
123// functions to latch composition state.
124struct OutputLatchFEStateTest : public OutputTest {
125 OutputLatchFEStateTest() {
126 EXPECT_CALL(*mOutputLayer1, getLayer()).WillRepeatedly(ReturnRef(mLayer1));
127 EXPECT_CALL(*mOutputLayer2, getLayer()).WillRepeatedly(ReturnRef(mLayer2));
128 EXPECT_CALL(*mOutputLayer3, getLayer()).WillRepeatedly(ReturnRef(mLayer3));
129
130 EXPECT_CALL(*mOutputLayer1, getLayerFE()).WillRepeatedly(ReturnRef(mLayer1FE));
131 EXPECT_CALL(*mOutputLayer2, getLayerFE()).WillRepeatedly(ReturnRef(mLayer2FE));
132 EXPECT_CALL(*mOutputLayer3, getLayerFE()).WillRepeatedly(ReturnRef(mLayer3FE));
133
134 EXPECT_CALL(mLayer1, editFEState()).WillRepeatedly(ReturnRef(mLayer1FEState));
135 EXPECT_CALL(mLayer2, editFEState()).WillRepeatedly(ReturnRef(mLayer2FEState));
136 EXPECT_CALL(mLayer3, editFEState()).WillRepeatedly(ReturnRef(mLayer3FEState));
137 }
138
139 void injectLayer(std::unique_ptr<mock::OutputLayer> layer) {
140 mOutput->injectOutputLayerForTest(std::unique_ptr<OutputLayer>(layer.release()));
141 }
142
143 std::unique_ptr<mock::OutputLayer> mOutputLayer1{new StrictMock<mock::OutputLayer>};
144 std::unique_ptr<mock::OutputLayer> mOutputLayer2{new StrictMock<mock::OutputLayer>};
145 std::unique_ptr<mock::OutputLayer> mOutputLayer3{new StrictMock<mock::OutputLayer>};
146
147 StrictMock<mock::Layer> mLayer1;
148 StrictMock<mock::Layer> mLayer2;
149 StrictMock<mock::Layer> mLayer3;
150
151 StrictMock<mock::LayerFE> mLayer1FE;
152 StrictMock<mock::LayerFE> mLayer2FE;
153 StrictMock<mock::LayerFE> mLayer3FE;
154
155 LayerFECompositionState mLayer1FEState;
156 LayerFECompositionState mLayer2FEState;
157 LayerFECompositionState mLayer3FEState;
158};
159
Lloyd Piqueef958122019-02-05 18:00:12 -0800160const Rect OutputTest::kDefaultDisplaySize{100, 200};
161
Lloyd Pique17ca7422019-11-14 14:24:10 -0800162using ColorProfile = compositionengine::Output::ColorProfile;
163
164void dumpColorProfile(ColorProfile profile, std::string& result, const char* name) {
165 android::base::StringAppendF(&result, "%s (%s[%d] %s[%d] %s[%d] %s[%d]) ", name,
166 toString(profile.mode).c_str(), profile.mode,
167 toString(profile.dataspace).c_str(), profile.dataspace,
168 toString(profile.renderIntent).c_str(), profile.renderIntent,
169 toString(profile.colorSpaceAgnosticDataspace).c_str(),
170 profile.colorSpaceAgnosticDataspace);
171}
172
173// Checks for a ColorProfile match
174MATCHER_P(ColorProfileEq, expected, "") {
175 std::string buf;
176 buf.append("ColorProfiles are not equal\n");
177 dumpColorProfile(expected, buf, "expected value");
178 dumpColorProfile(arg, buf, "actual value");
179 *result_listener << buf;
180
181 return (expected.mode == arg.mode) && (expected.dataspace == arg.dataspace) &&
182 (expected.renderIntent == arg.renderIntent) &&
183 (expected.colorSpaceAgnosticDataspace == arg.colorSpaceAgnosticDataspace);
184}
185
Lloyd Pique66d68602019-02-13 14:23:31 -0800186/*
Lloyd Pique32cbe282018-10-19 13:09:22 -0700187 * Basic construction
188 */
189
Lloyd Pique31cb2942018-10-19 17:23:03 -0700190TEST_F(OutputTest, canInstantiateOutput) {
191 // The validation check checks each required component.
Lloyd Pique3d0c02e2018-10-19 18:38:12 -0700192 EXPECT_CALL(*mDisplayColorProfile, isValid()).WillOnce(Return(true));
Lloyd Pique31cb2942018-10-19 17:23:03 -0700193 EXPECT_CALL(*mRenderSurface, isValid()).WillOnce(Return(true));
194
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700195 EXPECT_TRUE(mOutput->isValid());
Lloyd Pique31cb2942018-10-19 17:23:03 -0700196
197 // If we take away the required components, it is no longer valid.
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700198 mOutput->setRenderSurfaceForTest(std::unique_ptr<RenderSurface>());
Lloyd Pique31cb2942018-10-19 17:23:03 -0700199
Lloyd Pique3d0c02e2018-10-19 18:38:12 -0700200 EXPECT_CALL(*mDisplayColorProfile, isValid()).WillOnce(Return(true));
201
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700202 EXPECT_FALSE(mOutput->isValid());
Lloyd Pique31cb2942018-10-19 17:23:03 -0700203}
Lloyd Pique32cbe282018-10-19 13:09:22 -0700204
Lloyd Pique66d68602019-02-13 14:23:31 -0800205/*
Lloyd Pique32cbe282018-10-19 13:09:22 -0700206 * Output::setCompositionEnabled()
207 */
208
209TEST_F(OutputTest, setCompositionEnabledDoesNothingIfAlreadyEnabled) {
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700210 mOutput->editState().isEnabled = true;
Lloyd Pique32cbe282018-10-19 13:09:22 -0700211
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700212 mOutput->setCompositionEnabled(true);
Lloyd Pique32cbe282018-10-19 13:09:22 -0700213
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700214 EXPECT_TRUE(mOutput->getState().isEnabled);
215 EXPECT_THAT(mOutput->getState().dirtyRegion, RegionEq(Region()));
Lloyd Pique32cbe282018-10-19 13:09:22 -0700216}
217
218TEST_F(OutputTest, setCompositionEnabledSetsEnabledAndDirtiesEntireOutput) {
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700219 mOutput->editState().isEnabled = false;
Lloyd Pique32cbe282018-10-19 13:09:22 -0700220
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700221 mOutput->setCompositionEnabled(true);
Lloyd Pique32cbe282018-10-19 13:09:22 -0700222
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700223 EXPECT_TRUE(mOutput->getState().isEnabled);
224 EXPECT_THAT(mOutput->getState().dirtyRegion, RegionEq(Region(kDefaultDisplaySize)));
Lloyd Pique32cbe282018-10-19 13:09:22 -0700225}
226
227TEST_F(OutputTest, setCompositionEnabledSetsDisabledAndDirtiesEntireOutput) {
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700228 mOutput->editState().isEnabled = true;
Lloyd Pique32cbe282018-10-19 13:09:22 -0700229
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700230 mOutput->setCompositionEnabled(false);
Lloyd Pique32cbe282018-10-19 13:09:22 -0700231
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700232 EXPECT_FALSE(mOutput->getState().isEnabled);
233 EXPECT_THAT(mOutput->getState().dirtyRegion, RegionEq(Region(kDefaultDisplaySize)));
Lloyd Pique32cbe282018-10-19 13:09:22 -0700234}
235
Lloyd Pique66d68602019-02-13 14:23:31 -0800236/*
Lloyd Pique32cbe282018-10-19 13:09:22 -0700237 * Output::setProjection()
238 */
239
240TEST_F(OutputTest, setProjectionTriviallyWorks) {
241 const ui::Transform transform{ui::Transform::ROT_180};
242 const int32_t orientation = 123;
243 const Rect frame{1, 2, 3, 4};
244 const Rect viewport{5, 6, 7, 8};
245 const Rect scissor{9, 10, 11, 12};
246 const bool needsFiltering = true;
247
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700248 mOutput->setProjection(transform, orientation, frame, viewport, scissor, needsFiltering);
Lloyd Pique32cbe282018-10-19 13:09:22 -0700249
Lloyd Piqueea629282019-12-03 15:57:10 -0800250 EXPECT_THAT(mOutput->getState().transform, transform);
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700251 EXPECT_EQ(orientation, mOutput->getState().orientation);
252 EXPECT_EQ(frame, mOutput->getState().frame);
253 EXPECT_EQ(viewport, mOutput->getState().viewport);
254 EXPECT_EQ(scissor, mOutput->getState().scissor);
255 EXPECT_EQ(needsFiltering, mOutput->getState().needsFiltering);
Lloyd Pique32cbe282018-10-19 13:09:22 -0700256}
257
Lloyd Pique66d68602019-02-13 14:23:31 -0800258/*
Lloyd Pique32cbe282018-10-19 13:09:22 -0700259 * Output::setBounds()
260 */
261
262TEST_F(OutputTest, setBoundsSetsSizeAndDirtiesEntireOutput) {
Lloyd Piqueef958122019-02-05 18:00:12 -0800263 const ui::Size displaySize{200, 400};
Lloyd Pique31cb2942018-10-19 17:23:03 -0700264
265 EXPECT_CALL(*mRenderSurface, setDisplaySize(displaySize)).Times(1);
266 EXPECT_CALL(*mRenderSurface, getSize()).WillOnce(ReturnRef(displaySize));
267
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700268 mOutput->setBounds(displaySize);
Lloyd Pique32cbe282018-10-19 13:09:22 -0700269
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700270 EXPECT_EQ(Rect(displaySize), mOutput->getState().bounds);
Lloyd Pique32cbe282018-10-19 13:09:22 -0700271
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700272 EXPECT_THAT(mOutput->getState().dirtyRegion, RegionEq(Region(Rect(displaySize))));
Lloyd Pique32cbe282018-10-19 13:09:22 -0700273}
274
Lloyd Pique66d68602019-02-13 14:23:31 -0800275/*
Lloyd Pique32cbe282018-10-19 13:09:22 -0700276 * Output::setLayerStackFilter()
277 */
278
279TEST_F(OutputTest, setLayerStackFilterSetsFilterAndDirtiesEntireOutput) {
Lloyd Pique32cbe282018-10-19 13:09:22 -0700280 const uint32_t layerStack = 123u;
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700281 mOutput->setLayerStackFilter(layerStack, true);
Lloyd Pique32cbe282018-10-19 13:09:22 -0700282
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700283 EXPECT_TRUE(mOutput->getState().layerStackInternal);
284 EXPECT_EQ(layerStack, mOutput->getState().layerStackId);
Lloyd Pique32cbe282018-10-19 13:09:22 -0700285
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700286 EXPECT_THAT(mOutput->getState().dirtyRegion, RegionEq(Region(kDefaultDisplaySize)));
Lloyd Pique32cbe282018-10-19 13:09:22 -0700287}
288
Lloyd Pique66d68602019-02-13 14:23:31 -0800289/*
Lloyd Pique32cbe282018-10-19 13:09:22 -0700290 * Output::setColorTransform
291 */
292
Lloyd Pique3eb1b212019-03-07 21:15:40 -0800293TEST_F(OutputTest, setColorTransformWithNoChangeFlaggedSkipsUpdates) {
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700294 mOutput->editState().colorTransformMatrix = kIdentity;
Lloyd Pique32cbe282018-10-19 13:09:22 -0700295
Lloyd Pique3eb1b212019-03-07 21:15:40 -0800296 // If no colorTransformMatrix is set the update should be skipped.
297 CompositionRefreshArgs refreshArgs;
298 refreshArgs.colorTransformMatrix = std::nullopt;
Lloyd Pique32cbe282018-10-19 13:09:22 -0700299
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700300 mOutput->setColorTransform(refreshArgs);
Lloyd Pique32cbe282018-10-19 13:09:22 -0700301
Lloyd Pique3eb1b212019-03-07 21:15:40 -0800302 // The internal state should be unchanged
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700303 EXPECT_EQ(kIdentity, mOutput->getState().colorTransformMatrix);
Lloyd Pique3eb1b212019-03-07 21:15:40 -0800304
305 // No dirty region should be set
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700306 EXPECT_THAT(mOutput->getState().dirtyRegion, RegionEq(Region()));
Lloyd Pique3eb1b212019-03-07 21:15:40 -0800307}
Lloyd Piqueef958122019-02-05 18:00:12 -0800308
Lloyd Pique3eb1b212019-03-07 21:15:40 -0800309TEST_F(OutputTest, setColorTransformWithNoActualChangeSkipsUpdates) {
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700310 mOutput->editState().colorTransformMatrix = kIdentity;
Lloyd Pique32cbe282018-10-19 13:09:22 -0700311
Lloyd Pique3eb1b212019-03-07 21:15:40 -0800312 // Attempting to set the same colorTransformMatrix that is already set should
313 // also skip the update.
314 CompositionRefreshArgs refreshArgs;
315 refreshArgs.colorTransformMatrix = kIdentity;
Lloyd Pique32cbe282018-10-19 13:09:22 -0700316
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700317 mOutput->setColorTransform(refreshArgs);
Lloyd Pique77f79a22019-04-29 15:55:40 -0700318
Lloyd Pique3eb1b212019-03-07 21:15:40 -0800319 // The internal state should be unchanged
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700320 EXPECT_EQ(kIdentity, mOutput->getState().colorTransformMatrix);
Lloyd Pique3eb1b212019-03-07 21:15:40 -0800321
322 // No dirty region should be set
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700323 EXPECT_THAT(mOutput->getState().dirtyRegion, RegionEq(Region()));
Lloyd Pique3eb1b212019-03-07 21:15:40 -0800324}
325
326TEST_F(OutputTest, setColorTransformPerformsUpdateToIdentity) {
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700327 mOutput->editState().colorTransformMatrix = kNonIdentityHalf;
Lloyd Pique3eb1b212019-03-07 21:15:40 -0800328
329 // Setting a different colorTransformMatrix should perform the update.
330 CompositionRefreshArgs refreshArgs;
331 refreshArgs.colorTransformMatrix = kIdentity;
332
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700333 mOutput->setColorTransform(refreshArgs);
Lloyd Pique3eb1b212019-03-07 21:15:40 -0800334
335 // The internal state should have been updated
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700336 EXPECT_EQ(kIdentity, mOutput->getState().colorTransformMatrix);
Lloyd Pique3eb1b212019-03-07 21:15:40 -0800337
338 // The dirtyRegion should be set to the full display size
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700339 EXPECT_THAT(mOutput->getState().dirtyRegion, RegionEq(Region(kDefaultDisplaySize)));
Lloyd Pique3eb1b212019-03-07 21:15:40 -0800340}
Lloyd Pique77f79a22019-04-29 15:55:40 -0700341
Lloyd Pique3eb1b212019-03-07 21:15:40 -0800342TEST_F(OutputTest, setColorTransformPerformsUpdateForIdentityToHalf) {
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700343 mOutput->editState().colorTransformMatrix = kIdentity;
Lloyd Pique77f79a22019-04-29 15:55:40 -0700344
Lloyd Pique3eb1b212019-03-07 21:15:40 -0800345 // Setting a different colorTransformMatrix should perform the update.
346 CompositionRefreshArgs refreshArgs;
347 refreshArgs.colorTransformMatrix = kNonIdentityHalf;
Lloyd Pique77f79a22019-04-29 15:55:40 -0700348
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700349 mOutput->setColorTransform(refreshArgs);
Lloyd Piqueef958122019-02-05 18:00:12 -0800350
Lloyd Pique3eb1b212019-03-07 21:15:40 -0800351 // The internal state should have been updated
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700352 EXPECT_EQ(kNonIdentityHalf, mOutput->getState().colorTransformMatrix);
Lloyd Pique3eb1b212019-03-07 21:15:40 -0800353
354 // The dirtyRegion should be set to the full display size
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700355 EXPECT_THAT(mOutput->getState().dirtyRegion, RegionEq(Region(kDefaultDisplaySize)));
Lloyd Pique3eb1b212019-03-07 21:15:40 -0800356}
357
358TEST_F(OutputTest, setColorTransformPerformsUpdateForHalfToQuarter) {
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700359 mOutput->editState().colorTransformMatrix = kNonIdentityHalf;
Lloyd Pique3eb1b212019-03-07 21:15:40 -0800360
361 // Setting a different colorTransformMatrix should perform the update.
362 CompositionRefreshArgs refreshArgs;
363 refreshArgs.colorTransformMatrix = kNonIdentityQuarter;
364
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700365 mOutput->setColorTransform(refreshArgs);
Lloyd Pique3eb1b212019-03-07 21:15:40 -0800366
367 // The internal state should have been updated
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700368 EXPECT_EQ(kNonIdentityQuarter, mOutput->getState().colorTransformMatrix);
Lloyd Pique3eb1b212019-03-07 21:15:40 -0800369
370 // The dirtyRegion should be set to the full display size
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700371 EXPECT_THAT(mOutput->getState().dirtyRegion, RegionEq(Region(kDefaultDisplaySize)));
Lloyd Pique32cbe282018-10-19 13:09:22 -0700372}
373
Lloyd Pique66d68602019-02-13 14:23:31 -0800374/*
Lloyd Pique17ca7422019-11-14 14:24:10 -0800375 * Output::setColorProfile
Lloyd Pique32cbe282018-10-19 13:09:22 -0700376 */
377
Lloyd Pique17ca7422019-11-14 14:24:10 -0800378using OutputSetColorProfileTest = OutputTest;
379
380TEST_F(OutputSetColorProfileTest, setsStateAndDirtiesOutputIfChanged) {
Lloyd Pique6a3b4462019-03-07 20:58:12 -0800381 using ColorProfile = Output::ColorProfile;
382
Lloyd Piquef5275482019-01-29 18:42:42 -0800383 EXPECT_CALL(*mDisplayColorProfile,
384 getTargetDataspace(ui::ColorMode::DISPLAY_P3, ui::Dataspace::DISPLAY_P3,
385 ui::Dataspace::UNKNOWN))
386 .WillOnce(Return(ui::Dataspace::UNKNOWN));
Lloyd Piqueef958122019-02-05 18:00:12 -0800387 EXPECT_CALL(*mRenderSurface, setBufferDataspace(ui::Dataspace::DISPLAY_P3)).Times(1);
Lloyd Pique31cb2942018-10-19 17:23:03 -0700388
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700389 mOutput->setColorProfile(ColorProfile{ui::ColorMode::DISPLAY_P3, ui::Dataspace::DISPLAY_P3,
390 ui::RenderIntent::TONE_MAP_COLORIMETRIC,
391 ui::Dataspace::UNKNOWN});
Lloyd Pique32cbe282018-10-19 13:09:22 -0700392
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700393 EXPECT_EQ(ui::ColorMode::DISPLAY_P3, mOutput->getState().colorMode);
394 EXPECT_EQ(ui::Dataspace::DISPLAY_P3, mOutput->getState().dataspace);
395 EXPECT_EQ(ui::RenderIntent::TONE_MAP_COLORIMETRIC, mOutput->getState().renderIntent);
396 EXPECT_EQ(ui::Dataspace::UNKNOWN, mOutput->getState().targetDataspace);
Lloyd Piquef5275482019-01-29 18:42:42 -0800397
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700398 EXPECT_THAT(mOutput->getState().dirtyRegion, RegionEq(Region(kDefaultDisplaySize)));
Lloyd Piqueef958122019-02-05 18:00:12 -0800399}
400
Lloyd Pique17ca7422019-11-14 14:24:10 -0800401TEST_F(OutputSetColorProfileTest, doesNothingIfNoChange) {
Lloyd Pique6a3b4462019-03-07 20:58:12 -0800402 using ColorProfile = Output::ColorProfile;
403
Lloyd Piquef5275482019-01-29 18:42:42 -0800404 EXPECT_CALL(*mDisplayColorProfile,
405 getTargetDataspace(ui::ColorMode::DISPLAY_P3, ui::Dataspace::DISPLAY_P3,
406 ui::Dataspace::UNKNOWN))
407 .WillOnce(Return(ui::Dataspace::UNKNOWN));
408
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700409 mOutput->editState().colorMode = ui::ColorMode::DISPLAY_P3;
410 mOutput->editState().dataspace = ui::Dataspace::DISPLAY_P3;
411 mOutput->editState().renderIntent = ui::RenderIntent::TONE_MAP_COLORIMETRIC;
412 mOutput->editState().targetDataspace = ui::Dataspace::UNKNOWN;
Lloyd Piqueef958122019-02-05 18:00:12 -0800413
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700414 mOutput->setColorProfile(ColorProfile{ui::ColorMode::DISPLAY_P3, ui::Dataspace::DISPLAY_P3,
415 ui::RenderIntent::TONE_MAP_COLORIMETRIC,
416 ui::Dataspace::UNKNOWN});
Lloyd Piqueef958122019-02-05 18:00:12 -0800417
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700418 EXPECT_THAT(mOutput->getState().dirtyRegion, RegionEq(Region()));
Lloyd Pique32cbe282018-10-19 13:09:22 -0700419}
420
Lloyd Pique66d68602019-02-13 14:23:31 -0800421/*
Lloyd Pique31cb2942018-10-19 17:23:03 -0700422 * Output::setRenderSurface()
423 */
424
425TEST_F(OutputTest, setRenderSurfaceResetsBounds) {
426 const ui::Size newDisplaySize{640, 480};
427
428 mock::RenderSurface* renderSurface = new StrictMock<mock::RenderSurface>();
429 EXPECT_CALL(*renderSurface, getSize()).WillOnce(ReturnRef(newDisplaySize));
430
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700431 mOutput->setRenderSurface(std::unique_ptr<RenderSurface>(renderSurface));
Lloyd Pique31cb2942018-10-19 17:23:03 -0700432
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700433 EXPECT_EQ(Rect(newDisplaySize), mOutput->getState().bounds);
Lloyd Pique31cb2942018-10-19 17:23:03 -0700434}
435
Lloyd Pique66d68602019-02-13 14:23:31 -0800436/*
Alec Mourie7d1d4a2019-02-05 01:13:46 +0000437 * Output::getDirtyRegion()
Lloyd Pique32cbe282018-10-19 13:09:22 -0700438 */
439
Alec Mourie7d1d4a2019-02-05 01:13:46 +0000440TEST_F(OutputTest, getDirtyRegionWithRepaintEverythingTrue) {
441 const Rect viewport{100, 200};
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700442 mOutput->editState().viewport = viewport;
443 mOutput->editState().dirtyRegion.set(50, 300);
Lloyd Pique32cbe282018-10-19 13:09:22 -0700444
445 {
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700446 Region result = mOutput->getDirtyRegion(true);
Lloyd Pique32cbe282018-10-19 13:09:22 -0700447
Alec Mourie7d1d4a2019-02-05 01:13:46 +0000448 EXPECT_THAT(result, RegionEq(Region(viewport)));
Lloyd Pique32cbe282018-10-19 13:09:22 -0700449 }
450}
451
Alec Mourie7d1d4a2019-02-05 01:13:46 +0000452TEST_F(OutputTest, getDirtyRegionWithRepaintEverythingFalse) {
453 const Rect viewport{100, 200};
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700454 mOutput->editState().viewport = viewport;
455 mOutput->editState().dirtyRegion.set(50, 300);
Lloyd Pique32cbe282018-10-19 13:09:22 -0700456
457 {
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700458 Region result = mOutput->getDirtyRegion(false);
Lloyd Pique32cbe282018-10-19 13:09:22 -0700459
460 // The dirtyRegion should be clipped to the display bounds.
461 EXPECT_THAT(result, RegionEq(Region(Rect(50, 200))));
462 }
Lloyd Pique32cbe282018-10-19 13:09:22 -0700463}
464
Lloyd Pique66d68602019-02-13 14:23:31 -0800465/*
Lloyd Piqueef36b002019-01-23 17:52:04 -0800466 * Output::belongsInOutput()
467 */
468
469TEST_F(OutputTest, belongsInOutputFiltersAsExpected) {
470 const uint32_t layerStack1 = 123u;
471 const uint32_t layerStack2 = 456u;
472
473 // If the output accepts layerStack1 and internal-only layers....
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700474 mOutput->setLayerStackFilter(layerStack1, true);
Lloyd Piqueef36b002019-01-23 17:52:04 -0800475
Lloyd Piquec6687342019-03-07 21:34:57 -0800476 // A layer with no layerStack does not belong to it, internal-only or not.
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700477 EXPECT_FALSE(mOutput->belongsInOutput(std::nullopt, false));
478 EXPECT_FALSE(mOutput->belongsInOutput(std::nullopt, true));
Lloyd Piquec6687342019-03-07 21:34:57 -0800479
Lloyd Piqueef36b002019-01-23 17:52:04 -0800480 // Any layer with layerStack1 belongs to it, internal-only or not.
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700481 EXPECT_TRUE(mOutput->belongsInOutput(layerStack1, false));
482 EXPECT_TRUE(mOutput->belongsInOutput(layerStack1, true));
483 EXPECT_FALSE(mOutput->belongsInOutput(layerStack2, true));
484 EXPECT_FALSE(mOutput->belongsInOutput(layerStack2, false));
Lloyd Piqueef36b002019-01-23 17:52:04 -0800485
486 // If the output accepts layerStack21 but not internal-only layers...
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700487 mOutput->setLayerStackFilter(layerStack1, false);
Lloyd Piqueef36b002019-01-23 17:52:04 -0800488
489 // Only non-internal layers with layerStack1 belong to it.
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700490 EXPECT_TRUE(mOutput->belongsInOutput(layerStack1, false));
491 EXPECT_FALSE(mOutput->belongsInOutput(layerStack1, true));
492 EXPECT_FALSE(mOutput->belongsInOutput(layerStack2, true));
493 EXPECT_FALSE(mOutput->belongsInOutput(layerStack2, false));
Lloyd Piqueef36b002019-01-23 17:52:04 -0800494}
495
Lloyd Pique66c20c42019-03-07 21:44:02 -0800496TEST_F(OutputTest, belongsInOutputFiltersLayersAsExpected) {
497 StrictMock<mock::Layer> layer;
Lloyd Pique9755fb72019-03-26 14:44:40 -0700498 LayerFECompositionState layerFEState;
Lloyd Pique66c20c42019-03-07 21:44:02 -0800499
Lloyd Pique9755fb72019-03-26 14:44:40 -0700500 EXPECT_CALL(layer, getFEState()).WillRepeatedly(ReturnRef(layerFEState));
Lloyd Pique66c20c42019-03-07 21:44:02 -0800501
502 const uint32_t layerStack1 = 123u;
503 const uint32_t layerStack2 = 456u;
504
505 // If the output accepts layerStack1 and internal-only layers....
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700506 mOutput->setLayerStackFilter(layerStack1, true);
Lloyd Pique66c20c42019-03-07 21:44:02 -0800507
508 // A null layer pointer does not belong to the output
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700509 EXPECT_FALSE(mOutput->belongsInOutput(nullptr));
Lloyd Pique66c20c42019-03-07 21:44:02 -0800510
511 // A layer with no layerStack does not belong to it, internal-only or not.
Lloyd Pique9755fb72019-03-26 14:44:40 -0700512 layerFEState.layerStackId = std::nullopt;
513 layerFEState.internalOnly = false;
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700514 EXPECT_FALSE(mOutput->belongsInOutput(&layer));
Lloyd Pique66c20c42019-03-07 21:44:02 -0800515
Lloyd Pique9755fb72019-03-26 14:44:40 -0700516 layerFEState.layerStackId = std::nullopt;
517 layerFEState.internalOnly = true;
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700518 EXPECT_FALSE(mOutput->belongsInOutput(&layer));
Lloyd Pique66c20c42019-03-07 21:44:02 -0800519
520 // Any layer with layerStack1 belongs to it, internal-only or not.
Lloyd Pique9755fb72019-03-26 14:44:40 -0700521 layerFEState.layerStackId = layerStack1;
522 layerFEState.internalOnly = false;
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700523 EXPECT_TRUE(mOutput->belongsInOutput(&layer));
Lloyd Pique66c20c42019-03-07 21:44:02 -0800524
Lloyd Pique9755fb72019-03-26 14:44:40 -0700525 layerFEState.layerStackId = layerStack1;
526 layerFEState.internalOnly = true;
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700527 EXPECT_TRUE(mOutput->belongsInOutput(&layer));
Lloyd Pique66c20c42019-03-07 21:44:02 -0800528
Lloyd Pique9755fb72019-03-26 14:44:40 -0700529 layerFEState.layerStackId = layerStack2;
530 layerFEState.internalOnly = true;
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700531 EXPECT_FALSE(mOutput->belongsInOutput(&layer));
Lloyd Pique66c20c42019-03-07 21:44:02 -0800532
Lloyd Pique9755fb72019-03-26 14:44:40 -0700533 layerFEState.layerStackId = layerStack2;
534 layerFEState.internalOnly = false;
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700535 EXPECT_FALSE(mOutput->belongsInOutput(&layer));
Lloyd Pique66c20c42019-03-07 21:44:02 -0800536
537 // If the output accepts layerStack1 but not internal-only layers...
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700538 mOutput->setLayerStackFilter(layerStack1, false);
Lloyd Pique66c20c42019-03-07 21:44:02 -0800539
540 // A null layer pointer does not belong to the output
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700541 EXPECT_FALSE(mOutput->belongsInOutput(nullptr));
Lloyd Pique66c20c42019-03-07 21:44:02 -0800542
543 // Only non-internal layers with layerStack1 belong to it.
Lloyd Pique9755fb72019-03-26 14:44:40 -0700544 layerFEState.layerStackId = layerStack1;
545 layerFEState.internalOnly = false;
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700546 EXPECT_TRUE(mOutput->belongsInOutput(&layer));
Lloyd Pique66c20c42019-03-07 21:44:02 -0800547
Lloyd Pique9755fb72019-03-26 14:44:40 -0700548 layerFEState.layerStackId = layerStack1;
549 layerFEState.internalOnly = true;
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700550 EXPECT_FALSE(mOutput->belongsInOutput(&layer));
Lloyd Pique66c20c42019-03-07 21:44:02 -0800551
Lloyd Pique9755fb72019-03-26 14:44:40 -0700552 layerFEState.layerStackId = layerStack2;
553 layerFEState.internalOnly = true;
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700554 EXPECT_FALSE(mOutput->belongsInOutput(&layer));
Lloyd Pique66c20c42019-03-07 21:44:02 -0800555
Lloyd Pique9755fb72019-03-26 14:44:40 -0700556 layerFEState.layerStackId = layerStack2;
557 layerFEState.internalOnly = false;
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700558 EXPECT_FALSE(mOutput->belongsInOutput(&layer));
Lloyd Pique66c20c42019-03-07 21:44:02 -0800559}
560
Lloyd Pique66d68602019-02-13 14:23:31 -0800561/*
Lloyd Piquecc01a452018-12-04 17:24:00 -0800562 * Output::getOutputLayerForLayer()
563 */
564
565TEST_F(OutputTest, getOutputLayerForLayerWorks) {
566 mock::OutputLayer* outputLayer1 = new StrictMock<mock::OutputLayer>();
567 mock::OutputLayer* outputLayer2 = new StrictMock<mock::OutputLayer>();
568
Lloyd Pique01c77c12019-04-17 12:48:32 -0700569 mOutput->injectOutputLayerForTest(std::unique_ptr<OutputLayer>(outputLayer1));
570 mOutput->injectOutputLayerForTest(nullptr);
571 mOutput->injectOutputLayerForTest(std::unique_ptr<OutputLayer>(outputLayer2));
Lloyd Piquecc01a452018-12-04 17:24:00 -0800572
573 StrictMock<mock::Layer> layer;
574 StrictMock<mock::Layer> otherLayer;
575
576 // If the input layer matches the first OutputLayer, it will be returned.
577 EXPECT_CALL(*outputLayer1, getLayer()).WillOnce(ReturnRef(layer));
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700578 EXPECT_EQ(outputLayer1, mOutput->getOutputLayerForLayer(&layer));
Lloyd Piquecc01a452018-12-04 17:24:00 -0800579
580 // If the input layer matches the second OutputLayer, it will be returned.
581 EXPECT_CALL(*outputLayer1, getLayer()).WillOnce(ReturnRef(otherLayer));
582 EXPECT_CALL(*outputLayer2, getLayer()).WillOnce(ReturnRef(layer));
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700583 EXPECT_EQ(outputLayer2, mOutput->getOutputLayerForLayer(&layer));
Lloyd Piquecc01a452018-12-04 17:24:00 -0800584
585 // If the input layer does not match an output layer, null will be returned.
586 EXPECT_CALL(*outputLayer1, getLayer()).WillOnce(ReturnRef(otherLayer));
587 EXPECT_CALL(*outputLayer2, getLayer()).WillOnce(ReturnRef(otherLayer));
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700588 EXPECT_EQ(nullptr, mOutput->getOutputLayerForLayer(&layer));
Lloyd Piquecc01a452018-12-04 17:24:00 -0800589}
590
Lloyd Pique66d68602019-02-13 14:23:31 -0800591/*
Lloyd Piquec9e60032019-11-14 11:47:26 -0800592 * Output::setReleasedLayers()
593 */
594
595using OutputSetReleasedLayersTest = OutputTest;
596
597TEST_F(OutputSetReleasedLayersTest, setReleasedLayersTakesGivenLayers) {
598 sp<StrictMock<mock::LayerFE>> layer1FE{new StrictMock<mock::LayerFE>()};
599 sp<StrictMock<mock::LayerFE>> layer2FE{new StrictMock<mock::LayerFE>()};
600 sp<StrictMock<mock::LayerFE>> layer3FE{new StrictMock<mock::LayerFE>()};
601
602 Output::ReleasedLayers layers;
603 layers.push_back(layer1FE);
604 layers.push_back(layer2FE);
605 layers.push_back(layer3FE);
606
607 mOutput->setReleasedLayers(std::move(layers));
608
609 const auto& setLayers = mOutput->getReleasedLayersForTest();
610 ASSERT_EQ(3u, setLayers.size());
611 ASSERT_EQ(layer1FE.get(), setLayers[0].promote().get());
612 ASSERT_EQ(layer2FE.get(), setLayers[1].promote().get());
613 ASSERT_EQ(layer3FE.get(), setLayers[2].promote().get());
614}
615
616/*
Lloyd Piquec0ee6ba2019-11-14 12:55:53 -0800617 * Output::updateLayerStateFromFE()
618 */
619
620using OutputUpdateLayerStateFromFETest = OutputLatchFEStateTest;
621
622TEST_F(OutputUpdateLayerStateFromFETest, handlesNoOutputLayerCase) {
623 CompositionRefreshArgs refreshArgs;
624
625 mOutput->updateLayerStateFromFE(refreshArgs);
626}
627
628TEST_F(OutputUpdateLayerStateFromFETest, latchesContentStateForAllContainedLayers) {
629 EXPECT_CALL(mLayer1FE,
630 latchCompositionState(Ref(mLayer1FEState), LayerFE::StateSubset::Content));
631 EXPECT_CALL(mLayer2FE,
632 latchCompositionState(Ref(mLayer2FEState), LayerFE::StateSubset::Content));
633 EXPECT_CALL(mLayer3FE,
634 latchCompositionState(Ref(mLayer3FEState), LayerFE::StateSubset::Content));
635
636 // Note: Must be performed after any expectations on these mocks
637 injectLayer(std::move(mOutputLayer1));
638 injectLayer(std::move(mOutputLayer2));
639 injectLayer(std::move(mOutputLayer3));
640
641 CompositionRefreshArgs refreshArgs;
642 refreshArgs.updatingGeometryThisFrame = false;
643
644 mOutput->updateLayerStateFromFE(refreshArgs);
645}
646
647TEST_F(OutputUpdateLayerStateFromFETest, latchesGeometryAndContentStateForAllContainedLayers) {
648 EXPECT_CALL(mLayer1FE,
649 latchCompositionState(Ref(mLayer1FEState),
650 LayerFE::StateSubset::GeometryAndContent));
651 EXPECT_CALL(mLayer2FE,
652 latchCompositionState(Ref(mLayer2FEState),
653 LayerFE::StateSubset::GeometryAndContent));
654 EXPECT_CALL(mLayer3FE,
655 latchCompositionState(Ref(mLayer3FEState),
656 LayerFE::StateSubset::GeometryAndContent));
657
658 // Note: Must be performed after any expectations on these mocks
659 injectLayer(std::move(mOutputLayer1));
660 injectLayer(std::move(mOutputLayer2));
661 injectLayer(std::move(mOutputLayer3));
662
663 CompositionRefreshArgs refreshArgs;
664 refreshArgs.updatingGeometryThisFrame = true;
665
666 mOutput->updateLayerStateFromFE(refreshArgs);
667}
668
669/*
Alec Mourif9a2a2c2019-11-12 12:46:02 -0800670 * Output::updateAndWriteCompositionState()
671 */
672
Lloyd Piqueef63b612019-11-14 13:19:56 -0800673using OutputUpdateAndWriteCompositionStateTest = OutputLatchFEStateTest;
674
675TEST_F(OutputUpdateAndWriteCompositionStateTest, doesNothingIfLayers) {
676 mOutput->editState().isEnabled = true;
Alec Mourif9a2a2c2019-11-12 12:46:02 -0800677
678 CompositionRefreshArgs args;
679 mOutput->updateAndWriteCompositionState(args);
680}
681
Lloyd Piqueef63b612019-11-14 13:19:56 -0800682TEST_F(OutputUpdateAndWriteCompositionStateTest, doesNothingIfOutputNotEnabled) {
683 mOutput->editState().isEnabled = false;
Alec Mourif9a2a2c2019-11-12 12:46:02 -0800684
Lloyd Piqueef63b612019-11-14 13:19:56 -0800685 injectLayer(std::move(mOutputLayer1));
686 injectLayer(std::move(mOutputLayer2));
687 injectLayer(std::move(mOutputLayer3));
688
689 CompositionRefreshArgs args;
690 mOutput->updateAndWriteCompositionState(args);
691}
692
693TEST_F(OutputUpdateAndWriteCompositionStateTest, updatesLayerContentForAllLayers) {
694 EXPECT_CALL(*mOutputLayer1, updateCompositionState(false, false));
695 EXPECT_CALL(*mOutputLayer1, writeStateToHWC(false));
696 EXPECT_CALL(*mOutputLayer2, updateCompositionState(false, false));
697 EXPECT_CALL(*mOutputLayer2, writeStateToHWC(false));
698 EXPECT_CALL(*mOutputLayer3, updateCompositionState(false, false));
699 EXPECT_CALL(*mOutputLayer3, writeStateToHWC(false));
700
701 injectLayer(std::move(mOutputLayer1));
702 injectLayer(std::move(mOutputLayer2));
703 injectLayer(std::move(mOutputLayer3));
704
705 mOutput->editState().isEnabled = true;
706
707 CompositionRefreshArgs args;
708 args.updatingGeometryThisFrame = false;
709 args.devOptForceClientComposition = false;
710 mOutput->updateAndWriteCompositionState(args);
711}
712
713TEST_F(OutputUpdateAndWriteCompositionStateTest, updatesLayerGeometryAndContentForAllLayers) {
714 EXPECT_CALL(*mOutputLayer1, updateCompositionState(true, false));
715 EXPECT_CALL(*mOutputLayer1, writeStateToHWC(true));
716 EXPECT_CALL(*mOutputLayer2, updateCompositionState(true, false));
717 EXPECT_CALL(*mOutputLayer2, writeStateToHWC(true));
718 EXPECT_CALL(*mOutputLayer3, updateCompositionState(true, false));
719 EXPECT_CALL(*mOutputLayer3, writeStateToHWC(true));
720
721 injectLayer(std::move(mOutputLayer1));
722 injectLayer(std::move(mOutputLayer2));
723 injectLayer(std::move(mOutputLayer3));
724
725 mOutput->editState().isEnabled = true;
Alec Mourif9a2a2c2019-11-12 12:46:02 -0800726
727 CompositionRefreshArgs args;
728 args.updatingGeometryThisFrame = true;
Lloyd Piqueef63b612019-11-14 13:19:56 -0800729 args.devOptForceClientComposition = false;
730 mOutput->updateAndWriteCompositionState(args);
731}
732
733TEST_F(OutputUpdateAndWriteCompositionStateTest, forcesClientCompositionForAllLayers) {
734 EXPECT_CALL(*mOutputLayer1, updateCompositionState(false, true));
735 EXPECT_CALL(*mOutputLayer1, writeStateToHWC(false));
736 EXPECT_CALL(*mOutputLayer2, updateCompositionState(false, true));
737 EXPECT_CALL(*mOutputLayer2, writeStateToHWC(false));
738 EXPECT_CALL(*mOutputLayer3, updateCompositionState(false, true));
739 EXPECT_CALL(*mOutputLayer3, writeStateToHWC(false));
740
741 injectLayer(std::move(mOutputLayer1));
742 injectLayer(std::move(mOutputLayer2));
743 injectLayer(std::move(mOutputLayer3));
744
745 mOutput->editState().isEnabled = true;
746
747 CompositionRefreshArgs args;
748 args.updatingGeometryThisFrame = false;
Alec Mourif9a2a2c2019-11-12 12:46:02 -0800749 args.devOptForceClientComposition = true;
750 mOutput->updateAndWriteCompositionState(args);
751}
752
753/*
Lloyd Pique66d68602019-02-13 14:23:31 -0800754 * Output::prepareFrame()
755 */
756
757struct OutputPrepareFrameTest : public testing::Test {
Lloyd Piquefaa3f192019-11-14 14:05:09 -0800758 struct OutputPartialMock : public OutputPartialMockBase {
Lloyd Pique739afaf2019-11-21 16:40:05 -0800759 // Sets up the helper functions called by the function under test to use
760 // mock implementations.
Lloyd Pique66d68602019-02-13 14:23:31 -0800761 MOCK_METHOD0(chooseCompositionStrategy, void());
762 };
763
764 OutputPrepareFrameTest() {
765 mOutput.setDisplayColorProfileForTest(
766 std::unique_ptr<DisplayColorProfile>(mDisplayColorProfile));
767 mOutput.setRenderSurfaceForTest(std::unique_ptr<RenderSurface>(mRenderSurface));
768 }
769
770 StrictMock<mock::CompositionEngine> mCompositionEngine;
771 mock::DisplayColorProfile* mDisplayColorProfile = new StrictMock<mock::DisplayColorProfile>();
772 mock::RenderSurface* mRenderSurface = new StrictMock<mock::RenderSurface>();
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700773 StrictMock<OutputPartialMock> mOutput;
Lloyd Pique66d68602019-02-13 14:23:31 -0800774};
775
776TEST_F(OutputPrepareFrameTest, takesEarlyOutIfNotEnabled) {
777 mOutput.editState().isEnabled = false;
778
779 mOutput.prepareFrame();
780}
781
782TEST_F(OutputPrepareFrameTest, delegatesToChooseCompositionStrategyAndRenderSurface) {
783 mOutput.editState().isEnabled = true;
784 mOutput.editState().usesClientComposition = false;
785 mOutput.editState().usesDeviceComposition = true;
786
787 EXPECT_CALL(mOutput, chooseCompositionStrategy()).Times(1);
788 EXPECT_CALL(*mRenderSurface, prepareFrame(false, true));
789
790 mOutput.prepareFrame();
791}
792
793// Note: Use OutputTest and not OutputPrepareFrameTest, so the real
794// base chooseCompositionStrategy() is invoked.
795TEST_F(OutputTest, prepareFrameSetsClientCompositionOnlyByDefault) {
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700796 mOutput->editState().isEnabled = true;
797 mOutput->editState().usesClientComposition = false;
798 mOutput->editState().usesDeviceComposition = true;
Lloyd Pique66d68602019-02-13 14:23:31 -0800799
800 EXPECT_CALL(*mRenderSurface, prepareFrame(true, false));
801
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700802 mOutput->prepareFrame();
Lloyd Pique66d68602019-02-13 14:23:31 -0800803
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700804 EXPECT_TRUE(mOutput->getState().usesClientComposition);
805 EXPECT_FALSE(mOutput->getState().usesDeviceComposition);
Lloyd Pique66d68602019-02-13 14:23:31 -0800806}
807
Lloyd Pique56eba802019-08-28 15:45:25 -0700808/*
Lloyd Piqueb62cebc2019-11-20 18:31:52 -0800809 * Output::prepare()
810 */
811
812struct OutputPrepareTest : public testing::Test {
813 struct OutputPartialMock : public OutputPartialMockBase {
814 // Sets up the helper functions called by the function under test to use
815 // mock implementations.
816 MOCK_METHOD2(rebuildLayerStacks,
817 void(const compositionengine::CompositionRefreshArgs&,
818 compositionengine::LayerFESet&));
819 };
820
821 StrictMock<OutputPartialMock> mOutput;
822 CompositionRefreshArgs mRefreshArgs;
Lloyd Piquefe0ee9e2019-11-22 16:30:30 -0800823 LayerFESet mGeomSnapshots;
Lloyd Piqueb62cebc2019-11-20 18:31:52 -0800824};
825
826TEST_F(OutputPrepareTest, justInvokesRebuildLayerStacks) {
827 InSequence seq;
828 EXPECT_CALL(mOutput, rebuildLayerStacks(Ref(mRefreshArgs), Ref(mGeomSnapshots)));
829
830 mOutput.prepare(mRefreshArgs, mGeomSnapshots);
831}
832
833/*
834 * Output::rebuildLayerStacks()
835 */
836
837struct OutputRebuildLayerStacksTest : public testing::Test {
838 struct OutputPartialMock : public OutputPartialMockBase {
839 // Sets up the helper functions called by the function under test to use
840 // mock implementations.
841 MOCK_METHOD2(collectVisibleLayers,
842 void(const compositionengine::CompositionRefreshArgs&,
843 compositionengine::Output::CoverageState&));
844 };
845
846 OutputRebuildLayerStacksTest() {
847 mOutput.mState.isEnabled = true;
848 mOutput.mState.transform = kIdentityTransform;
849 mOutput.mState.bounds = kOutputBounds;
850
851 mRefreshArgs.updatingOutputGeometryThisFrame = true;
852
853 mCoverageAboveCoveredLayersToSet = Region(Rect(0, 0, 10, 10));
854
855 EXPECT_CALL(mOutput, collectVisibleLayers(Ref(mRefreshArgs), _))
856 .WillRepeatedly(Invoke(this, &OutputRebuildLayerStacksTest::setTestCoverageValues));
857 }
858
859 void setTestCoverageValues(const CompositionRefreshArgs&,
860 compositionengine::Output::CoverageState& state) {
861 state.aboveCoveredLayers = mCoverageAboveCoveredLayersToSet;
862 state.aboveOpaqueLayers = mCoverageAboveOpaqueLayersToSet;
863 state.dirtyRegion = mCoverageDirtyRegionToSet;
864 }
865
866 static const ui::Transform kIdentityTransform;
867 static const ui::Transform kRotate90Transform;
868 static const Rect kOutputBounds;
869
870 StrictMock<OutputPartialMock> mOutput;
871 CompositionRefreshArgs mRefreshArgs;
Lloyd Piquefe0ee9e2019-11-22 16:30:30 -0800872 LayerFESet mGeomSnapshots;
Lloyd Piqueb62cebc2019-11-20 18:31:52 -0800873 Region mCoverageAboveCoveredLayersToSet;
874 Region mCoverageAboveOpaqueLayersToSet;
875 Region mCoverageDirtyRegionToSet;
876};
877
878const ui::Transform OutputRebuildLayerStacksTest::kIdentityTransform{TR_IDENT, 1920, 1080};
879const ui::Transform OutputRebuildLayerStacksTest::kRotate90Transform{TR_ROT_90, 1920, 1080};
880const Rect OutputRebuildLayerStacksTest::kOutputBounds{0, 0, 1920, 1080};
881
882TEST_F(OutputRebuildLayerStacksTest, doesNothingIfNotEnabled) {
883 mOutput.mState.isEnabled = false;
884
885 mOutput.rebuildLayerStacks(mRefreshArgs, mGeomSnapshots);
886}
887
888TEST_F(OutputRebuildLayerStacksTest, doesNothingIfNotUpdatingGeometryThisFrame) {
889 mRefreshArgs.updatingOutputGeometryThisFrame = false;
890
891 mOutput.rebuildLayerStacks(mRefreshArgs, mGeomSnapshots);
892}
893
894TEST_F(OutputRebuildLayerStacksTest, computesUndefinedRegionWithNoRotationAndFullCoverage) {
895 mOutput.mState.transform = kIdentityTransform;
896
897 mCoverageAboveOpaqueLayersToSet = Region(Rect(0, 0, 1920, 1080));
898
899 mOutput.rebuildLayerStacks(mRefreshArgs, mGeomSnapshots);
900
901 EXPECT_THAT(mOutput.mState.undefinedRegion, RegionEq(Region(Rect(0, 0, 0, 0))));
902}
903
904TEST_F(OutputRebuildLayerStacksTest, computesUndefinedRegionWithNoRotationAndPartialCoverage) {
905 mOutput.mState.transform = kIdentityTransform;
906
907 mCoverageAboveOpaqueLayersToSet = Region(Rect(0, 0, 960, 1080));
908
909 mOutput.rebuildLayerStacks(mRefreshArgs, mGeomSnapshots);
910
911 EXPECT_THAT(mOutput.mState.undefinedRegion, RegionEq(Region(Rect(960, 0, 1920, 1080))));
912}
913
914TEST_F(OutputRebuildLayerStacksTest, computesUndefinedRegionWith90RotationAndFullCoverage) {
915 mOutput.mState.transform = kRotate90Transform;
916
917 mCoverageAboveOpaqueLayersToSet = Region(Rect(0, 0, 1080, 1920));
918
919 mOutput.rebuildLayerStacks(mRefreshArgs, mGeomSnapshots);
920
921 EXPECT_THAT(mOutput.mState.undefinedRegion, RegionEq(Region(Rect(0, 0, 0, 0))));
922}
923
924TEST_F(OutputRebuildLayerStacksTest, computesUndefinedRegionWith90RotationAndPartialCoverage) {
925 mOutput.mState.transform = kRotate90Transform;
926
927 mCoverageAboveOpaqueLayersToSet = Region(Rect(0, 0, 1080, 960));
928
929 mOutput.rebuildLayerStacks(mRefreshArgs, mGeomSnapshots);
930
931 EXPECT_THAT(mOutput.mState.undefinedRegion, RegionEq(Region(Rect(0, 0, 960, 1080))));
932}
933
934TEST_F(OutputRebuildLayerStacksTest, addsToDirtyRegionWithNoRotation) {
935 mOutput.mState.transform = kIdentityTransform;
936 mOutput.mState.dirtyRegion = Region(Rect(960, 0, 1920, 1080));
937
938 mCoverageDirtyRegionToSet = Region(Rect(0, 0, 960, 1080));
939
940 mOutput.rebuildLayerStacks(mRefreshArgs, mGeomSnapshots);
941
942 EXPECT_THAT(mOutput.mState.dirtyRegion, RegionEq(Region(Rect(0, 0, 1920, 1080))));
943}
944
945TEST_F(OutputRebuildLayerStacksTest, addsToDirtyRegionWith90Rotation) {
946 mOutput.mState.transform = kRotate90Transform;
947 mOutput.mState.dirtyRegion = Region(Rect(0, 960, 1080, 1920));
948
949 mCoverageDirtyRegionToSet = Region(Rect(0, 0, 1080, 960));
950
951 mOutput.rebuildLayerStacks(mRefreshArgs, mGeomSnapshots);
952
953 EXPECT_THAT(mOutput.mState.dirtyRegion, RegionEq(Region(Rect(0, 0, 1080, 1920))));
954}
955
956/*
957 * Output::collectVisibleLayers()
958 */
959
Lloyd Pique1ef93222019-11-21 16:41:53 -0800960struct OutputCollectVisibleLayersTest : public testing::Test {
961 struct OutputPartialMock : public OutputPartialMockBase {
962 // Sets up the helper functions called by the function under test to use
963 // mock implementations.
964 MOCK_METHOD2(ensureOutputLayerIfVisible,
965 void(std::shared_ptr<compositionengine::Layer>,
966 compositionengine::Output::CoverageState&));
967 MOCK_METHOD1(setReleasedLayers, void(const compositionengine::CompositionRefreshArgs&));
968 MOCK_METHOD0(finalizePendingOutputLayers, void());
969 };
970
971 struct Layer {
972 Layer() {
973 EXPECT_CALL(outputLayer, getState()).WillRepeatedly(ReturnRef(outputLayerState));
974 EXPECT_CALL(outputLayer, editState()).WillRepeatedly(ReturnRef(outputLayerState));
975 }
976
977 StrictMock<mock::OutputLayer> outputLayer;
978 std::shared_ptr<StrictMock<mock::Layer>> layer{new StrictMock<mock::Layer>()};
979 impl::OutputLayerCompositionState outputLayerState;
980 };
981
982 OutputCollectVisibleLayersTest() {
983 EXPECT_CALL(mOutput, getOutputLayerCount()).WillRepeatedly(Return(3));
984 EXPECT_CALL(mOutput, getOutputLayerOrderedByZByIndex(0))
985 .WillRepeatedly(Return(&mLayer1.outputLayer));
986 EXPECT_CALL(mOutput, getOutputLayerOrderedByZByIndex(1))
987 .WillRepeatedly(Return(&mLayer2.outputLayer));
988 EXPECT_CALL(mOutput, getOutputLayerOrderedByZByIndex(2))
989 .WillRepeatedly(Return(&mLayer3.outputLayer));
990
991 mRefreshArgs.layers.push_back(mLayer1.layer);
992 mRefreshArgs.layers.push_back(mLayer2.layer);
993 mRefreshArgs.layers.push_back(mLayer3.layer);
994 }
995
996 StrictMock<OutputPartialMock> mOutput;
997 CompositionRefreshArgs mRefreshArgs;
Lloyd Piquefe0ee9e2019-11-22 16:30:30 -0800998 LayerFESet mGeomSnapshots;
999 Output::CoverageState mCoverageState{mGeomSnapshots};
Lloyd Pique1ef93222019-11-21 16:41:53 -08001000 Layer mLayer1;
1001 Layer mLayer2;
1002 Layer mLayer3;
1003};
1004
1005TEST_F(OutputCollectVisibleLayersTest, doesMinimalWorkIfNoLayers) {
1006 mRefreshArgs.layers.clear();
1007 EXPECT_CALL(mOutput, getOutputLayerCount()).WillRepeatedly(Return(0));
1008
1009 EXPECT_CALL(mOutput, setReleasedLayers(Ref(mRefreshArgs)));
1010 EXPECT_CALL(mOutput, finalizePendingOutputLayers());
1011
1012 mOutput.collectVisibleLayers(mRefreshArgs, mCoverageState);
1013}
1014
1015TEST_F(OutputCollectVisibleLayersTest, processesCandidateLayersReversedAndSetsOutputLayerZ) {
1016 // Enforce a call order sequence for this test.
1017 InSequence seq;
1018
1019 // Layer coverage is evaluated from front to back!
1020 EXPECT_CALL(mOutput, ensureOutputLayerIfVisible(Eq(mLayer3.layer), Ref(mCoverageState)));
1021 EXPECT_CALL(mOutput, ensureOutputLayerIfVisible(Eq(mLayer2.layer), Ref(mCoverageState)));
1022 EXPECT_CALL(mOutput, ensureOutputLayerIfVisible(Eq(mLayer1.layer), Ref(mCoverageState)));
1023
1024 EXPECT_CALL(mOutput, setReleasedLayers(Ref(mRefreshArgs)));
1025 EXPECT_CALL(mOutput, finalizePendingOutputLayers());
1026
1027 mOutput.collectVisibleLayers(mRefreshArgs, mCoverageState);
1028
1029 // Ensure all output layers have been assigned a simple/flattened z-order.
1030 EXPECT_EQ(0u, mLayer1.outputLayerState.z);
1031 EXPECT_EQ(1u, mLayer2.outputLayerState.z);
1032 EXPECT_EQ(2u, mLayer3.outputLayerState.z);
1033}
Lloyd Piqueb62cebc2019-11-20 18:31:52 -08001034
1035/*
1036 * Output::ensureOutputLayerIfVisible()
1037 */
1038
Lloyd Piquefe0ee9e2019-11-22 16:30:30 -08001039struct OutputEnsureOutputLayerIfVisibleTest : public testing::Test {
1040 struct OutputPartialMock : public OutputPartialMockBase {
1041 // Sets up the helper functions called by the function under test to use
1042 // mock implementations.
1043 MOCK_CONST_METHOD1(belongsInOutput, bool(const compositionengine::Layer*));
1044 MOCK_CONST_METHOD1(getOutputLayerOrderedByZByIndex, OutputLayer*(size_t));
1045 MOCK_METHOD3(ensureOutputLayer,
1046 compositionengine::OutputLayer*(
1047 std::optional<size_t>,
1048 const std::shared_ptr<compositionengine::Layer>&, const sp<LayerFE>&));
1049 };
1050
1051 OutputEnsureOutputLayerIfVisibleTest() {
1052 EXPECT_CALL(*mLayer, getLayerFE()).WillRepeatedly(Return(mLayerFE));
1053 EXPECT_CALL(*mLayer, getFEState()).WillRepeatedly(ReturnRef(mLayerFEState));
1054 EXPECT_CALL(*mLayer, editFEState()).WillRepeatedly(ReturnRef(mLayerFEState));
1055
1056 EXPECT_CALL(mOutput, belongsInOutput(mLayer.get())).WillRepeatedly(Return(true));
1057 EXPECT_CALL(mOutput, getOutputLayerCount()).WillRepeatedly(Return(1));
1058 EXPECT_CALL(mOutput, getOutputLayerOrderedByZByIndex(0u))
1059 .WillRepeatedly(Return(&mOutputLayer));
1060
1061 EXPECT_CALL(mOutputLayer, getState()).WillRepeatedly(ReturnRef(mOutputLayerState));
1062 EXPECT_CALL(mOutputLayer, editState()).WillRepeatedly(ReturnRef(mOutputLayerState));
1063 EXPECT_CALL(mOutputLayer, getLayer()).WillRepeatedly(ReturnRef(*mLayer.get()));
1064
1065 mOutput.mState.bounds = Rect(0, 0, 200, 300);
1066 mOutput.mState.viewport = Rect(0, 0, 200, 300);
1067 mOutput.mState.transform = ui::Transform(TR_IDENT, 200, 300);
1068
1069 mLayerFEState.isVisible = true;
1070 mLayerFEState.isOpaque = true;
1071 mLayerFEState.contentDirty = true;
1072 mLayerFEState.geomLayerBounds = FloatRect{0, 0, 100, 200};
1073 mLayerFEState.geomLayerTransform = ui::Transform(TR_IDENT, 100, 200);
1074 mLayerFEState.transparentRegionHint = Region(Rect(0, 0, 100, 100));
1075
1076 mOutputLayerState.visibleRegion = Region(Rect(0, 0, 50, 200));
1077 mOutputLayerState.coveredRegion = Region(Rect(50, 0, 100, 200));
1078
1079 mGeomSnapshots.insert(mLayerFE);
1080 }
1081
1082 static const Region kEmptyRegion;
1083 static const Region kFullBoundsNoRotation;
1084 static const Region kRightHalfBoundsNoRotation;
1085 static const Region kLowerHalfBoundsNoRotation;
1086 static const Region kFullBounds90Rotation;
1087
1088 StrictMock<OutputPartialMock> mOutput;
1089 LayerFESet mGeomSnapshots;
1090 Output::CoverageState mCoverageState{mGeomSnapshots};
1091
1092 std::shared_ptr<mock::Layer> mLayer{new StrictMock<mock::Layer>()};
1093 sp<StrictMock<mock::LayerFE>> mLayerFE{new StrictMock<mock::LayerFE>()};
1094 LayerFECompositionState mLayerFEState;
1095 mock::OutputLayer mOutputLayer;
1096 impl::OutputLayerCompositionState mOutputLayerState;
1097};
1098
1099const Region OutputEnsureOutputLayerIfVisibleTest::kEmptyRegion = Region(Rect(0, 0, 0, 0));
1100const Region OutputEnsureOutputLayerIfVisibleTest::kFullBoundsNoRotation =
1101 Region(Rect(0, 0, 100, 200));
1102const Region OutputEnsureOutputLayerIfVisibleTest::kRightHalfBoundsNoRotation =
1103 Region(Rect(0, 100, 100, 200));
1104const Region OutputEnsureOutputLayerIfVisibleTest::kLowerHalfBoundsNoRotation =
1105 Region(Rect(50, 0, 100, 200));
1106const Region OutputEnsureOutputLayerIfVisibleTest::kFullBounds90Rotation =
1107 Region(Rect(0, 0, 200, 100));
1108
1109TEST_F(OutputEnsureOutputLayerIfVisibleTest, doesNothingIfNoLayerFE) {
1110 EXPECT_CALL(*mLayer, getLayerFE).WillOnce(Return(sp<LayerFE>()));
1111
1112 mOutput.ensureOutputLayerIfVisible(mLayer, mCoverageState);
1113}
1114
1115TEST_F(OutputEnsureOutputLayerIfVisibleTest, performsGeomLatchBeforeCheckingIfLayerBelongs) {
1116 EXPECT_CALL(mOutput, belongsInOutput(mLayer.get())).WillOnce(Return(false));
1117 EXPECT_CALL(*mLayerFE.get(),
1118 latchCompositionState(Ref(mLayerFEState),
1119 compositionengine::LayerFE::StateSubset::BasicGeometry));
1120
1121 mGeomSnapshots.clear();
1122
1123 mOutput.ensureOutputLayerIfVisible(mLayer, mCoverageState);
1124}
1125
1126TEST_F(OutputEnsureOutputLayerIfVisibleTest,
1127 skipsLatchIfAlreadyLatchedBeforeCheckingIfLayerBelongs) {
1128 EXPECT_CALL(mOutput, belongsInOutput(mLayer.get())).WillOnce(Return(false));
1129
1130 mOutput.ensureOutputLayerIfVisible(mLayer, mCoverageState);
1131}
1132
1133TEST_F(OutputEnsureOutputLayerIfVisibleTest, takesEarlyOutIfLayerNotVisible) {
1134 mLayerFEState.isVisible = false;
1135
1136 mOutput.ensureOutputLayerIfVisible(mLayer, mCoverageState);
1137}
1138
1139TEST_F(OutputEnsureOutputLayerIfVisibleTest, takesEarlyOutIfLayerHasEmptyVisibleRegion) {
1140 mLayerFEState.geomLayerBounds = FloatRect{0, 0, 0, 0};
1141
1142 mOutput.ensureOutputLayerIfVisible(mLayer, mCoverageState);
1143}
1144
1145TEST_F(OutputEnsureOutputLayerIfVisibleTest, takesNotSoEarlyOutifDrawRegionEmpty) {
1146 mOutput.mState.bounds = Rect(0, 0, 0, 0);
1147
1148 mOutput.ensureOutputLayerIfVisible(mLayer, mCoverageState);
1149}
1150
1151TEST_F(OutputEnsureOutputLayerIfVisibleTest,
1152 handlesCreatingOutputLayerForOpaqueDirtyNotRotatedLayer) {
1153 mLayerFEState.isOpaque = true;
1154 mLayerFEState.contentDirty = true;
1155 mLayerFEState.geomLayerTransform = ui::Transform(TR_IDENT, 100, 200);
1156
1157 EXPECT_CALL(mOutput, getOutputLayerCount()).WillOnce(Return(0u));
1158 EXPECT_CALL(mOutput, ensureOutputLayer(Eq(std::nullopt), Eq(mLayer), Eq(mLayerFE)))
1159 .WillOnce(Return(&mOutputLayer));
1160
1161 mOutput.ensureOutputLayerIfVisible(mLayer, mCoverageState);
1162
1163 EXPECT_THAT(mCoverageState.dirtyRegion, RegionEq(kFullBoundsNoRotation));
1164 EXPECT_THAT(mCoverageState.aboveCoveredLayers, RegionEq(kFullBoundsNoRotation));
1165 EXPECT_THAT(mCoverageState.aboveOpaqueLayers, RegionEq(kFullBoundsNoRotation));
1166
1167 EXPECT_THAT(mOutputLayerState.visibleRegion, RegionEq(kFullBoundsNoRotation));
1168 EXPECT_THAT(mOutputLayerState.visibleNonTransparentRegion, RegionEq(kFullBoundsNoRotation));
1169 EXPECT_THAT(mOutputLayerState.coveredRegion, RegionEq(kEmptyRegion));
1170 EXPECT_THAT(mOutputLayerState.outputSpaceVisibleRegion, RegionEq(kFullBoundsNoRotation));
1171}
1172
1173TEST_F(OutputEnsureOutputLayerIfVisibleTest,
1174 handlesUpdatingOutputLayerForOpaqueDirtyNotRotatedLayer) {
1175 mLayerFEState.isOpaque = true;
1176 mLayerFEState.contentDirty = true;
1177 mLayerFEState.geomLayerTransform = ui::Transform(TR_IDENT, 100, 200);
1178
1179 EXPECT_CALL(mOutput, ensureOutputLayer(Eq(0u), Eq(mLayer), Eq(mLayerFE)))
1180 .WillOnce(Return(&mOutputLayer));
1181
1182 mOutput.ensureOutputLayerIfVisible(mLayer, mCoverageState);
1183
1184 EXPECT_THAT(mCoverageState.dirtyRegion, RegionEq(kFullBoundsNoRotation));
1185 EXPECT_THAT(mCoverageState.aboveCoveredLayers, RegionEq(kFullBoundsNoRotation));
1186 EXPECT_THAT(mCoverageState.aboveOpaqueLayers, RegionEq(kFullBoundsNoRotation));
1187
1188 EXPECT_THAT(mOutputLayerState.visibleRegion, RegionEq(kFullBoundsNoRotation));
1189 EXPECT_THAT(mOutputLayerState.visibleNonTransparentRegion, RegionEq(kFullBoundsNoRotation));
1190 EXPECT_THAT(mOutputLayerState.coveredRegion, RegionEq(kEmptyRegion));
1191 EXPECT_THAT(mOutputLayerState.outputSpaceVisibleRegion, RegionEq(kFullBoundsNoRotation));
1192}
1193
1194TEST_F(OutputEnsureOutputLayerIfVisibleTest,
1195 handlesCreatingOutputLayerForTransparentDirtyNotRotatedLayer) {
1196 mLayerFEState.isOpaque = false;
1197 mLayerFEState.contentDirty = true;
1198 mLayerFEState.geomLayerTransform = ui::Transform(TR_IDENT, 100, 200);
1199
1200 EXPECT_CALL(mOutput, getOutputLayerCount()).WillOnce(Return(0u));
1201 EXPECT_CALL(mOutput, ensureOutputLayer(Eq(std::nullopt), Eq(mLayer), Eq(mLayerFE)))
1202 .WillOnce(Return(&mOutputLayer));
1203
1204 mOutput.ensureOutputLayerIfVisible(mLayer, mCoverageState);
1205
1206 EXPECT_THAT(mCoverageState.dirtyRegion, RegionEq(kFullBoundsNoRotation));
1207 EXPECT_THAT(mCoverageState.aboveCoveredLayers, RegionEq(kFullBoundsNoRotation));
1208 EXPECT_THAT(mCoverageState.aboveOpaqueLayers, RegionEq(kEmptyRegion));
1209
1210 EXPECT_THAT(mOutputLayerState.visibleRegion, RegionEq(kFullBoundsNoRotation));
1211 EXPECT_THAT(mOutputLayerState.visibleNonTransparentRegion,
1212 RegionEq(kRightHalfBoundsNoRotation));
1213 EXPECT_THAT(mOutputLayerState.coveredRegion, RegionEq(kEmptyRegion));
1214 EXPECT_THAT(mOutputLayerState.outputSpaceVisibleRegion, RegionEq(kFullBoundsNoRotation));
1215}
1216
1217TEST_F(OutputEnsureOutputLayerIfVisibleTest,
1218 handlesUpdatingOutputLayerForTransparentDirtyNotRotatedLayer) {
1219 mLayerFEState.isOpaque = false;
1220 mLayerFEState.contentDirty = true;
1221 mLayerFEState.geomLayerTransform = ui::Transform(TR_IDENT, 100, 200);
1222
1223 EXPECT_CALL(mOutput, ensureOutputLayer(Eq(0u), Eq(mLayer), Eq(mLayerFE)))
1224 .WillOnce(Return(&mOutputLayer));
1225
1226 mOutput.ensureOutputLayerIfVisible(mLayer, mCoverageState);
1227
1228 EXPECT_THAT(mCoverageState.dirtyRegion, RegionEq(kFullBoundsNoRotation));
1229 EXPECT_THAT(mCoverageState.aboveCoveredLayers, RegionEq(kFullBoundsNoRotation));
1230 EXPECT_THAT(mCoverageState.aboveOpaqueLayers, RegionEq(kEmptyRegion));
1231
1232 EXPECT_THAT(mOutputLayerState.visibleRegion, RegionEq(kFullBoundsNoRotation));
1233 EXPECT_THAT(mOutputLayerState.visibleNonTransparentRegion,
1234 RegionEq(kRightHalfBoundsNoRotation));
1235 EXPECT_THAT(mOutputLayerState.coveredRegion, RegionEq(kEmptyRegion));
1236 EXPECT_THAT(mOutputLayerState.outputSpaceVisibleRegion, RegionEq(kFullBoundsNoRotation));
1237}
1238
1239TEST_F(OutputEnsureOutputLayerIfVisibleTest,
1240 handlesCreatingOutputLayerForOpaqueNonDirtyNotRotatedLayer) {
1241 mLayerFEState.isOpaque = true;
1242 mLayerFEState.contentDirty = false;
1243 mLayerFEState.geomLayerTransform = ui::Transform(TR_IDENT, 100, 200);
1244
1245 EXPECT_CALL(mOutput, getOutputLayerCount()).WillOnce(Return(0u));
1246 EXPECT_CALL(mOutput, ensureOutputLayer(Eq(std::nullopt), Eq(mLayer), Eq(mLayerFE)))
1247 .WillOnce(Return(&mOutputLayer));
1248
1249 mOutput.ensureOutputLayerIfVisible(mLayer, mCoverageState);
1250
1251 EXPECT_THAT(mCoverageState.dirtyRegion, RegionEq(kFullBoundsNoRotation));
1252 EXPECT_THAT(mCoverageState.aboveCoveredLayers, RegionEq(kFullBoundsNoRotation));
1253 EXPECT_THAT(mCoverageState.aboveOpaqueLayers, RegionEq(kFullBoundsNoRotation));
1254
1255 EXPECT_THAT(mOutputLayerState.visibleRegion, RegionEq(kFullBoundsNoRotation));
1256 EXPECT_THAT(mOutputLayerState.visibleNonTransparentRegion, RegionEq(kFullBoundsNoRotation));
1257 EXPECT_THAT(mOutputLayerState.coveredRegion, RegionEq(kEmptyRegion));
1258 EXPECT_THAT(mOutputLayerState.outputSpaceVisibleRegion, RegionEq(kFullBoundsNoRotation));
1259}
1260
1261TEST_F(OutputEnsureOutputLayerIfVisibleTest,
1262 handlesUpdatingOutputLayerForOpaqueNonDirtyNotRotatedLayer) {
1263 mLayerFEState.isOpaque = true;
1264 mLayerFEState.contentDirty = false;
1265 mLayerFEState.geomLayerTransform = ui::Transform(TR_IDENT, 100, 200);
1266
1267 EXPECT_CALL(mOutput, ensureOutputLayer(Eq(0u), Eq(mLayer), Eq(mLayerFE)))
1268 .WillOnce(Return(&mOutputLayer));
1269
1270 mOutput.ensureOutputLayerIfVisible(mLayer, mCoverageState);
1271
1272 EXPECT_THAT(mCoverageState.dirtyRegion, RegionEq(kLowerHalfBoundsNoRotation));
1273 EXPECT_THAT(mCoverageState.aboveCoveredLayers, RegionEq(kFullBoundsNoRotation));
1274 EXPECT_THAT(mCoverageState.aboveOpaqueLayers, RegionEq(kFullBoundsNoRotation));
1275
1276 EXPECT_THAT(mOutputLayerState.visibleRegion, RegionEq(kFullBoundsNoRotation));
1277 EXPECT_THAT(mOutputLayerState.visibleNonTransparentRegion, RegionEq(kFullBoundsNoRotation));
1278 EXPECT_THAT(mOutputLayerState.coveredRegion, RegionEq(kEmptyRegion));
1279 EXPECT_THAT(mOutputLayerState.outputSpaceVisibleRegion, RegionEq(kFullBoundsNoRotation));
1280}
1281
1282TEST_F(OutputEnsureOutputLayerIfVisibleTest,
1283 handlesCreatingOutputLayerForOpaqueDirtyRotated90Layer) {
1284 mLayerFEState.isOpaque = true;
1285 mLayerFEState.contentDirty = true;
1286 mLayerFEState.geomLayerBounds = FloatRect{0, 0, 200, 100};
1287 mLayerFEState.geomLayerTransform = ui::Transform(TR_ROT_90, 100, 200);
1288 mOutputLayerState.visibleRegion = Region(Rect(0, 0, 100, 100));
1289 mOutputLayerState.coveredRegion = Region(Rect(100, 0, 200, 100));
1290
1291 EXPECT_CALL(mOutput, getOutputLayerCount()).WillOnce(Return(0u));
1292 EXPECT_CALL(mOutput, ensureOutputLayer(Eq(std::nullopt), Eq(mLayer), Eq(mLayerFE)))
1293 .WillOnce(Return(&mOutputLayer));
1294
1295 mOutput.ensureOutputLayerIfVisible(mLayer, mCoverageState);
1296
1297 EXPECT_THAT(mCoverageState.dirtyRegion, RegionEq(kFullBoundsNoRotation));
1298 EXPECT_THAT(mCoverageState.aboveCoveredLayers, RegionEq(kFullBoundsNoRotation));
1299 EXPECT_THAT(mCoverageState.aboveOpaqueLayers, RegionEq(kFullBoundsNoRotation));
1300
1301 EXPECT_THAT(mOutputLayerState.visibleRegion, RegionEq(kFullBoundsNoRotation));
1302 EXPECT_THAT(mOutputLayerState.visibleNonTransparentRegion, RegionEq(kFullBoundsNoRotation));
1303 EXPECT_THAT(mOutputLayerState.coveredRegion, RegionEq(kEmptyRegion));
1304 EXPECT_THAT(mOutputLayerState.outputSpaceVisibleRegion, RegionEq(kFullBoundsNoRotation));
1305}
1306
1307TEST_F(OutputEnsureOutputLayerIfVisibleTest,
1308 handlesUpdatingOutputLayerForOpaqueDirtyRotated90Layer) {
1309 mLayerFEState.isOpaque = true;
1310 mLayerFEState.contentDirty = true;
1311 mLayerFEState.geomLayerBounds = FloatRect{0, 0, 200, 100};
1312 mLayerFEState.geomLayerTransform = ui::Transform(TR_ROT_90, 100, 200);
1313 mOutputLayerState.visibleRegion = Region(Rect(0, 0, 100, 100));
1314 mOutputLayerState.coveredRegion = Region(Rect(100, 0, 200, 100));
1315
1316 EXPECT_CALL(mOutput, ensureOutputLayer(Eq(0u), Eq(mLayer), Eq(mLayerFE)))
1317 .WillOnce(Return(&mOutputLayer));
1318
1319 mOutput.ensureOutputLayerIfVisible(mLayer, mCoverageState);
1320
1321 EXPECT_THAT(mCoverageState.dirtyRegion, RegionEq(kFullBoundsNoRotation));
1322 EXPECT_THAT(mCoverageState.aboveCoveredLayers, RegionEq(kFullBoundsNoRotation));
1323 EXPECT_THAT(mCoverageState.aboveOpaqueLayers, RegionEq(kFullBoundsNoRotation));
1324
1325 EXPECT_THAT(mOutputLayerState.visibleRegion, RegionEq(kFullBoundsNoRotation));
1326 EXPECT_THAT(mOutputLayerState.visibleNonTransparentRegion, RegionEq(kFullBoundsNoRotation));
1327 EXPECT_THAT(mOutputLayerState.coveredRegion, RegionEq(kEmptyRegion));
1328 EXPECT_THAT(mOutputLayerState.outputSpaceVisibleRegion, RegionEq(kFullBoundsNoRotation));
1329}
1330
1331TEST_F(OutputEnsureOutputLayerIfVisibleTest,
1332 handlesCreatingOutputLayerForOpaqueDirtyNotRotatedLayerRotatedOutput) {
1333 mLayerFEState.isOpaque = true;
1334 mLayerFEState.contentDirty = true;
1335 mLayerFEState.geomLayerTransform = ui::Transform(TR_IDENT, 100, 200);
1336
1337 mOutput.mState.viewport = Rect(0, 0, 300, 200);
1338 mOutput.mState.transform = ui::Transform(TR_ROT_90, 200, 300);
1339
1340 EXPECT_CALL(mOutput, getOutputLayerCount()).WillOnce(Return(0u));
1341 EXPECT_CALL(mOutput, ensureOutputLayer(Eq(std::nullopt), Eq(mLayer), Eq(mLayerFE)))
1342 .WillOnce(Return(&mOutputLayer));
1343
1344 mOutput.ensureOutputLayerIfVisible(mLayer, mCoverageState);
1345
1346 EXPECT_THAT(mCoverageState.dirtyRegion, RegionEq(kFullBoundsNoRotation));
1347 EXPECT_THAT(mCoverageState.aboveCoveredLayers, RegionEq(kFullBoundsNoRotation));
1348 EXPECT_THAT(mCoverageState.aboveOpaqueLayers, RegionEq(kFullBoundsNoRotation));
1349
1350 EXPECT_THAT(mOutputLayerState.visibleRegion, RegionEq(kFullBoundsNoRotation));
1351 EXPECT_THAT(mOutputLayerState.visibleNonTransparentRegion, RegionEq(kFullBoundsNoRotation));
1352 EXPECT_THAT(mOutputLayerState.coveredRegion, RegionEq(kEmptyRegion));
1353 EXPECT_THAT(mOutputLayerState.outputSpaceVisibleRegion, RegionEq(kFullBounds90Rotation));
1354}
1355
1356TEST_F(OutputEnsureOutputLayerIfVisibleTest,
1357 handlesUpdatingOutputLayerForOpaqueDirtyNotRotatedLayerRotatedOutput) {
1358 mLayerFEState.isOpaque = true;
1359 mLayerFEState.contentDirty = true;
1360 mLayerFEState.geomLayerTransform = ui::Transform(TR_IDENT, 100, 200);
1361
1362 mOutput.mState.viewport = Rect(0, 0, 300, 200);
1363 mOutput.mState.transform = ui::Transform(TR_ROT_90, 200, 300);
1364
1365 EXPECT_CALL(mOutput, ensureOutputLayer(Eq(0u), Eq(mLayer), Eq(mLayerFE)))
1366 .WillOnce(Return(&mOutputLayer));
1367
1368 mOutput.ensureOutputLayerIfVisible(mLayer, mCoverageState);
1369
1370 EXPECT_THAT(mCoverageState.dirtyRegion, RegionEq(kFullBoundsNoRotation));
1371 EXPECT_THAT(mCoverageState.aboveCoveredLayers, RegionEq(kFullBoundsNoRotation));
1372 EXPECT_THAT(mCoverageState.aboveOpaqueLayers, RegionEq(kFullBoundsNoRotation));
1373
1374 EXPECT_THAT(mOutputLayerState.visibleRegion, RegionEq(kFullBoundsNoRotation));
1375 EXPECT_THAT(mOutputLayerState.visibleNonTransparentRegion, RegionEq(kFullBoundsNoRotation));
1376 EXPECT_THAT(mOutputLayerState.coveredRegion, RegionEq(kEmptyRegion));
1377 EXPECT_THAT(mOutputLayerState.outputSpaceVisibleRegion, RegionEq(kFullBounds90Rotation));
1378}
1379
1380TEST_F(OutputEnsureOutputLayerIfVisibleTest,
1381 handlesCreatingOutputLayerForOpaqueDirtyArbitraryTransformLayer) {
1382 ui::Transform arbitraryTransform;
1383 arbitraryTransform.set(1, 1, -1, 1);
1384 arbitraryTransform.set(0, 100);
1385
1386 mLayerFEState.isOpaque = true;
1387 mLayerFEState.contentDirty = true;
1388 mLayerFEState.geomLayerBounds = FloatRect{0, 0, 100, 200};
1389 mLayerFEState.geomLayerTransform = arbitraryTransform;
1390
1391 EXPECT_CALL(mOutput, getOutputLayerCount()).WillOnce(Return(0u));
1392 EXPECT_CALL(mOutput, ensureOutputLayer(Eq(std::nullopt), Eq(mLayer), Eq(mLayerFE)))
1393 .WillOnce(Return(&mOutputLayer));
1394
1395 mOutput.ensureOutputLayerIfVisible(mLayer, mCoverageState);
1396
1397 const Region kRegion = Region(Rect(0, 0, 300, 300));
1398 const Region kRegionClipped = Region(Rect(0, 0, 200, 300));
1399
1400 EXPECT_THAT(mCoverageState.dirtyRegion, RegionEq(kRegion));
1401 EXPECT_THAT(mCoverageState.aboveCoveredLayers, RegionEq(kRegion));
1402 EXPECT_THAT(mCoverageState.aboveOpaqueLayers, RegionEq(kEmptyRegion));
1403
1404 EXPECT_THAT(mOutputLayerState.visibleRegion, RegionEq(kRegion));
1405 EXPECT_THAT(mOutputLayerState.visibleNonTransparentRegion, RegionEq(kRegion));
1406 EXPECT_THAT(mOutputLayerState.coveredRegion, RegionEq(kEmptyRegion));
1407 EXPECT_THAT(mOutputLayerState.outputSpaceVisibleRegion, RegionEq(kRegionClipped));
1408}
1409
1410TEST_F(OutputEnsureOutputLayerIfVisibleTest, coverageAccumulatesTest) {
1411 mLayerFEState.isOpaque = false;
1412 mLayerFEState.contentDirty = true;
1413 mLayerFEState.geomLayerTransform = ui::Transform(TR_IDENT, 100, 200);
1414
1415 mCoverageState.dirtyRegion = Region(Rect(0, 0, 500, 500));
1416 mCoverageState.aboveCoveredLayers = Region(Rect(50, 0, 150, 200));
1417 mCoverageState.aboveOpaqueLayers = Region(Rect(50, 0, 150, 200));
1418
1419 EXPECT_CALL(mOutput, ensureOutputLayer(Eq(0u), Eq(mLayer), Eq(mLayerFE)))
1420 .WillOnce(Return(&mOutputLayer));
1421
1422 mOutput.ensureOutputLayerIfVisible(mLayer, mCoverageState);
1423
1424 const Region kExpectedDirtyRegion = Region(Rect(0, 0, 500, 500));
1425 const Region kExpectedAboveCoveredRegion = Region(Rect(0, 0, 150, 200));
1426 const Region kExpectedAboveOpaqueRegion = Region(Rect(50, 0, 150, 200));
1427 const Region kExpectedLayerVisibleRegion = Region(Rect(0, 0, 50, 200));
1428 const Region kExpectedLayerCoveredRegion = Region(Rect(50, 0, 100, 200));
1429 const Region kExpectedLayerVisibleNonTransparentRegion = Region(Rect(0, 100, 50, 200));
1430
1431 EXPECT_THAT(mCoverageState.dirtyRegion, RegionEq(kExpectedDirtyRegion));
1432 EXPECT_THAT(mCoverageState.aboveCoveredLayers, RegionEq(kExpectedAboveCoveredRegion));
1433 EXPECT_THAT(mCoverageState.aboveOpaqueLayers, RegionEq(kExpectedAboveOpaqueRegion));
1434
1435 EXPECT_THAT(mOutputLayerState.visibleRegion, RegionEq(kExpectedLayerVisibleRegion));
1436 EXPECT_THAT(mOutputLayerState.visibleNonTransparentRegion,
1437 RegionEq(kExpectedLayerVisibleNonTransparentRegion));
1438 EXPECT_THAT(mOutputLayerState.coveredRegion, RegionEq(kExpectedLayerCoveredRegion));
1439 EXPECT_THAT(mOutputLayerState.outputSpaceVisibleRegion, RegionEq(kExpectedLayerVisibleRegion));
1440}
Lloyd Piqueb62cebc2019-11-20 18:31:52 -08001441
Vishnu Naira483b4a2019-12-12 15:07:52 -08001442TEST_F(OutputEnsureOutputLayerIfVisibleTest, coverageAccumulatesWithShadowsTest) {
1443 ui::Transform translate;
1444 translate.set(50, 50);
1445 mLayerFEState.geomLayerTransform = translate;
1446 mLayerFEState.shadowRadius = 10.0f;
1447
1448 mCoverageState.dirtyRegion = Region(Rect(0, 0, 500, 500));
1449 // half of the layer including the casting shadow is covered and opaque
1450 mCoverageState.aboveCoveredLayers = Region(Rect(40, 40, 100, 260));
1451 mCoverageState.aboveOpaqueLayers = Region(Rect(40, 40, 100, 260));
1452
1453 EXPECT_CALL(mOutput, ensureOutputLayer(Eq(0u), Eq(mLayer), Eq(mLayerFE)))
1454 .WillOnce(Return(&mOutputLayer));
1455
1456 mOutput.ensureOutputLayerIfVisible(mLayer, mCoverageState);
1457
1458 const Region kExpectedDirtyRegion = Region(Rect(0, 0, 500, 500));
1459 const Region kExpectedAboveCoveredRegion = Region(Rect(40, 40, 160, 260));
1460 // add starting opaque region to the opaque half of the casting layer bounds
1461 const Region kExpectedAboveOpaqueRegion =
1462 Region(Rect(40, 40, 100, 260)).orSelf(Rect(100, 50, 150, 250));
1463 const Region kExpectedLayerVisibleRegion = Region(Rect(100, 40, 160, 260));
1464 const Region kExpectedoutputSpaceLayerVisibleRegion = Region(Rect(100, 50, 150, 250));
1465 const Region kExpectedLayerCoveredRegion = Region(Rect(40, 40, 100, 260));
1466 const Region kExpectedLayerVisibleNonTransparentRegion = Region(Rect(100, 40, 160, 260));
1467 const Region kExpectedLayerShadowRegion =
1468 Region(Rect(40, 40, 160, 260)).subtractSelf(Rect(50, 50, 150, 250));
1469
1470 EXPECT_THAT(mCoverageState.dirtyRegion, RegionEq(kExpectedDirtyRegion));
1471 EXPECT_THAT(mCoverageState.aboveCoveredLayers, RegionEq(kExpectedAboveCoveredRegion));
1472 EXPECT_THAT(mCoverageState.aboveOpaqueLayers, RegionEq(kExpectedAboveOpaqueRegion));
1473
1474 EXPECT_THAT(mOutputLayerState.visibleRegion, RegionEq(kExpectedLayerVisibleRegion));
1475 EXPECT_THAT(mOutputLayerState.visibleNonTransparentRegion,
1476 RegionEq(kExpectedLayerVisibleNonTransparentRegion));
1477 EXPECT_THAT(mOutputLayerState.coveredRegion, RegionEq(kExpectedLayerCoveredRegion));
1478 EXPECT_THAT(mOutputLayerState.outputSpaceVisibleRegion,
1479 RegionEq(kExpectedoutputSpaceLayerVisibleRegion));
1480 EXPECT_THAT(mOutputLayerState.shadowRegion, RegionEq(kExpectedLayerShadowRegion));
1481 EXPECT_FALSE(kExpectedLayerVisibleRegion.subtract(kExpectedLayerShadowRegion).isEmpty());
1482}
1483
1484TEST_F(OutputEnsureOutputLayerIfVisibleTest, shadowRegionOnlyTest) {
1485 ui::Transform translate;
1486 translate.set(50, 50);
1487 mLayerFEState.geomLayerTransform = translate;
1488 mLayerFEState.shadowRadius = 10.0f;
1489
1490 mCoverageState.dirtyRegion = Region(Rect(0, 0, 500, 500));
1491 // Casting layer is covered by an opaque region leaving only part of its shadow to be drawn
1492 mCoverageState.aboveCoveredLayers = Region(Rect(40, 40, 150, 260));
1493 mCoverageState.aboveOpaqueLayers = Region(Rect(40, 40, 150, 260));
1494
1495 EXPECT_CALL(mOutput, ensureOutputLayer(Eq(0u), Eq(mLayer), Eq(mLayerFE)))
1496 .WillOnce(Return(&mOutputLayer));
1497
1498 mOutput.ensureOutputLayerIfVisible(mLayer, mCoverageState);
1499
1500 const Region kExpectedLayerVisibleRegion = Region(Rect(150, 40, 160, 260));
1501 const Region kExpectedLayerShadowRegion =
1502 Region(Rect(40, 40, 160, 260)).subtractSelf(Rect(50, 50, 150, 250));
1503
1504 EXPECT_THAT(mOutputLayerState.visibleRegion, RegionEq(kExpectedLayerVisibleRegion));
1505 EXPECT_THAT(mOutputLayerState.shadowRegion, RegionEq(kExpectedLayerShadowRegion));
1506 EXPECT_TRUE(kExpectedLayerVisibleRegion.subtract(kExpectedLayerShadowRegion).isEmpty());
1507}
1508
1509TEST_F(OutputEnsureOutputLayerIfVisibleTest, takesNotSoEarlyOutifLayerWithShadowIsCovered) {
1510 ui::Transform translate;
1511 translate.set(50, 50);
1512 mLayerFEState.geomLayerTransform = translate;
1513 mLayerFEState.shadowRadius = 10.0f;
1514
1515 mCoverageState.dirtyRegion = Region(Rect(0, 0, 500, 500));
1516 // Casting layer and its shadows are covered by an opaque region
1517 mCoverageState.aboveCoveredLayers = Region(Rect(40, 40, 160, 260));
1518 mCoverageState.aboveOpaqueLayers = Region(Rect(40, 40, 160, 260));
1519
1520 mOutput.ensureOutputLayerIfVisible(mLayer, mCoverageState);
1521}
1522
Lloyd Piqueb62cebc2019-11-20 18:31:52 -08001523/*
Lloyd Piquefaa3f192019-11-14 14:05:09 -08001524 * Output::present()
1525 */
1526
1527struct OutputPresentTest : public testing::Test {
1528 struct OutputPartialMock : public OutputPartialMockBase {
Lloyd Pique739afaf2019-11-21 16:40:05 -08001529 // Sets up the helper functions called by the function under test to use
1530 // mock implementations.
Lloyd Piquefaa3f192019-11-14 14:05:09 -08001531 MOCK_METHOD1(updateColorProfile, void(const compositionengine::CompositionRefreshArgs&));
1532 MOCK_METHOD1(updateAndWriteCompositionState,
1533 void(const compositionengine::CompositionRefreshArgs&));
1534 MOCK_METHOD1(setColorTransform, void(const compositionengine::CompositionRefreshArgs&));
1535 MOCK_METHOD0(beginFrame, void());
1536 MOCK_METHOD0(prepareFrame, void());
1537 MOCK_METHOD1(devOptRepaintFlash, void(const compositionengine::CompositionRefreshArgs&));
1538 MOCK_METHOD1(finishFrame, void(const compositionengine::CompositionRefreshArgs&));
1539 MOCK_METHOD0(postFramebuffer, void());
1540 };
1541
1542 StrictMock<OutputPartialMock> mOutput;
1543};
1544
1545TEST_F(OutputPresentTest, justInvokesChildFunctionsInSequence) {
1546 CompositionRefreshArgs args;
1547
1548 InSequence seq;
1549 EXPECT_CALL(mOutput, updateColorProfile(Ref(args)));
1550 EXPECT_CALL(mOutput, updateAndWriteCompositionState(Ref(args)));
1551 EXPECT_CALL(mOutput, setColorTransform(Ref(args)));
1552 EXPECT_CALL(mOutput, beginFrame());
1553 EXPECT_CALL(mOutput, prepareFrame());
1554 EXPECT_CALL(mOutput, devOptRepaintFlash(Ref(args)));
1555 EXPECT_CALL(mOutput, finishFrame(Ref(args)));
1556 EXPECT_CALL(mOutput, postFramebuffer());
1557
1558 mOutput.present(args);
1559}
1560
1561/*
1562 * Output::updateColorProfile()
1563 */
1564
Lloyd Pique17ca7422019-11-14 14:24:10 -08001565struct OutputUpdateColorProfileTest : public testing::Test {
1566 using TestType = OutputUpdateColorProfileTest;
1567
1568 struct OutputPartialMock : public OutputPartialMockBase {
Lloyd Pique739afaf2019-11-21 16:40:05 -08001569 // Sets up the helper functions called by the function under test to use
1570 // mock implementations.
Lloyd Pique17ca7422019-11-14 14:24:10 -08001571 MOCK_METHOD1(setColorProfile, void(const ColorProfile&));
1572 };
1573
1574 struct Layer {
1575 Layer() {
1576 EXPECT_CALL(mOutputLayer, getLayer()).WillRepeatedly(ReturnRef(mLayer));
1577 EXPECT_CALL(mOutputLayer, getLayerFE()).WillRepeatedly(ReturnRef(mLayerFE));
1578 EXPECT_CALL(mLayer, getFEState()).WillRepeatedly(ReturnRef(mLayerFEState));
1579 }
1580
1581 StrictMock<mock::OutputLayer> mOutputLayer;
1582 StrictMock<mock::Layer> mLayer;
1583 StrictMock<mock::LayerFE> mLayerFE;
1584 LayerFECompositionState mLayerFEState;
1585 };
1586
1587 OutputUpdateColorProfileTest() {
1588 mOutput.setDisplayColorProfileForTest(
1589 std::unique_ptr<DisplayColorProfile>(mDisplayColorProfile));
1590 mOutput.setRenderSurfaceForTest(std::unique_ptr<RenderSurface>(mRenderSurface));
1591
1592 EXPECT_CALL(mOutput, getOutputLayerOrderedByZByIndex(0))
1593 .WillRepeatedly(Return(&mLayer1.mOutputLayer));
1594 EXPECT_CALL(mOutput, getOutputLayerOrderedByZByIndex(1))
1595 .WillRepeatedly(Return(&mLayer2.mOutputLayer));
1596 EXPECT_CALL(mOutput, getOutputLayerOrderedByZByIndex(2))
1597 .WillRepeatedly(Return(&mLayer3.mOutputLayer));
1598 }
1599
1600 struct ExecuteState : public CallOrderStateMachineHelper<TestType, ExecuteState> {
1601 void execute() { getInstance()->mOutput.updateColorProfile(getInstance()->mRefreshArgs); }
1602 };
1603
1604 mock::DisplayColorProfile* mDisplayColorProfile = new StrictMock<mock::DisplayColorProfile>();
1605 mock::RenderSurface* mRenderSurface = new StrictMock<mock::RenderSurface>();
1606 StrictMock<OutputPartialMock> mOutput;
1607
1608 Layer mLayer1;
1609 Layer mLayer2;
1610 Layer mLayer3;
1611
1612 CompositionRefreshArgs mRefreshArgs;
1613};
1614
1615// TODO(b/144522012): Refactor Output::updateColorProfile and the related code
1616// to make it easier to write unit tests.
1617
1618TEST_F(OutputUpdateColorProfileTest, setsAColorProfileWhenUnmanaged) {
1619 // When the outputColorSetting is set to kUnmanaged, the implementation sets
1620 // a simple default color profile without looking at anything else.
1621
1622 EXPECT_CALL(mOutput, getOutputLayerCount()).WillRepeatedly(Return(3));
1623 EXPECT_CALL(mOutput,
1624 setColorProfile(ColorProfileEq(
1625 ColorProfile{ui::ColorMode::NATIVE, ui::Dataspace::UNKNOWN,
1626 ui::RenderIntent::COLORIMETRIC, ui::Dataspace::UNKNOWN})));
1627
1628 mRefreshArgs.outputColorSetting = OutputColorSetting::kUnmanaged;
1629 mRefreshArgs.colorSpaceAgnosticDataspace = ui::Dataspace::UNKNOWN;
1630
1631 mOutput.updateColorProfile(mRefreshArgs);
1632}
1633
1634struct OutputUpdateColorProfileTest_GetBestColorModeResultBecomesSetProfile
1635 : public OutputUpdateColorProfileTest {
1636 OutputUpdateColorProfileTest_GetBestColorModeResultBecomesSetProfile() {
1637 EXPECT_CALL(mOutput, getOutputLayerCount()).WillRepeatedly(Return(0));
1638 mRefreshArgs.outputColorSetting = OutputColorSetting::kEnhanced;
1639 mRefreshArgs.colorSpaceAgnosticDataspace = ui::Dataspace::UNKNOWN;
1640 }
1641
1642 struct ExpectBestColorModeCallResultUsedToSetColorProfileState
1643 : public CallOrderStateMachineHelper<
1644 TestType, ExpectBestColorModeCallResultUsedToSetColorProfileState> {
1645 [[nodiscard]] auto expectBestColorModeCallResultUsedToSetColorProfile(
1646 ui::ColorMode colorMode, ui::Dataspace dataspace, ui::RenderIntent renderIntent) {
1647 EXPECT_CALL(*getInstance()->mDisplayColorProfile,
1648 getBestColorMode(ui::Dataspace::V0_SRGB, ui::RenderIntent::ENHANCE, _, _,
1649 _))
1650 .WillOnce(DoAll(SetArgPointee<2>(dataspace), SetArgPointee<3>(colorMode),
1651 SetArgPointee<4>(renderIntent)));
1652 EXPECT_CALL(getInstance()->mOutput,
1653 setColorProfile(
1654 ColorProfileEq(ColorProfile{colorMode, dataspace, renderIntent,
1655 ui::Dataspace::UNKNOWN})));
1656 return nextState<ExecuteState>();
1657 }
1658 };
1659
1660 // Call this member function to start using the mini-DSL defined above.
1661 [[nodiscard]] auto verify() {
1662 return ExpectBestColorModeCallResultUsedToSetColorProfileState::make(this);
1663 }
1664};
1665
1666TEST_F(OutputUpdateColorProfileTest_GetBestColorModeResultBecomesSetProfile,
1667 Native_Unknown_Colorimetric_Set) {
1668 verify().expectBestColorModeCallResultUsedToSetColorProfile(ui::ColorMode::NATIVE,
1669 ui::Dataspace::UNKNOWN,
1670 ui::RenderIntent::COLORIMETRIC)
1671 .execute();
1672}
1673
1674TEST_F(OutputUpdateColorProfileTest_GetBestColorModeResultBecomesSetProfile,
1675 DisplayP3_DisplayP3_Enhance_Set) {
1676 verify().expectBestColorModeCallResultUsedToSetColorProfile(ui::ColorMode::DISPLAY_P3,
1677 ui::Dataspace::DISPLAY_P3,
1678 ui::RenderIntent::ENHANCE)
1679 .execute();
1680}
1681
1682struct OutputUpdateColorProfileTest_ColorSpaceAgnosticeDataspaceAffectsSetColorProfile
1683 : public OutputUpdateColorProfileTest {
1684 OutputUpdateColorProfileTest_ColorSpaceAgnosticeDataspaceAffectsSetColorProfile() {
1685 EXPECT_CALL(mOutput, getOutputLayerCount()).WillRepeatedly(Return(0));
1686 EXPECT_CALL(*mDisplayColorProfile,
1687 getBestColorMode(ui::Dataspace::V0_SRGB, ui::RenderIntent::ENHANCE, _, _, _))
1688 .WillRepeatedly(DoAll(SetArgPointee<2>(ui::Dataspace::UNKNOWN),
1689 SetArgPointee<3>(ui::ColorMode::NATIVE),
1690 SetArgPointee<4>(ui::RenderIntent::COLORIMETRIC)));
1691 mRefreshArgs.outputColorSetting = OutputColorSetting::kEnhanced;
1692 }
1693
1694 struct IfColorSpaceAgnosticDataspaceSetToState
1695 : public CallOrderStateMachineHelper<TestType, IfColorSpaceAgnosticDataspaceSetToState> {
1696 [[nodiscard]] auto ifColorSpaceAgnosticDataspaceSetTo(ui::Dataspace dataspace) {
1697 getInstance()->mRefreshArgs.colorSpaceAgnosticDataspace = dataspace;
1698 return nextState<ThenExpectSetColorProfileCallUsesColorSpaceAgnosticDataspaceState>();
1699 }
1700 };
1701
1702 struct ThenExpectSetColorProfileCallUsesColorSpaceAgnosticDataspaceState
1703 : public CallOrderStateMachineHelper<
1704 TestType, ThenExpectSetColorProfileCallUsesColorSpaceAgnosticDataspaceState> {
1705 [[nodiscard]] auto thenExpectSetColorProfileCallUsesColorSpaceAgnosticDataspace(
1706 ui::Dataspace dataspace) {
1707 EXPECT_CALL(getInstance()->mOutput,
1708 setColorProfile(ColorProfileEq(
1709 ColorProfile{ui::ColorMode::NATIVE, ui::Dataspace::UNKNOWN,
1710 ui::RenderIntent::COLORIMETRIC, dataspace})));
1711 return nextState<ExecuteState>();
1712 }
1713 };
1714
1715 // Call this member function to start using the mini-DSL defined above.
1716 [[nodiscard]] auto verify() { return IfColorSpaceAgnosticDataspaceSetToState::make(this); }
1717};
1718
1719TEST_F(OutputUpdateColorProfileTest_ColorSpaceAgnosticeDataspaceAffectsSetColorProfile, DisplayP3) {
1720 verify().ifColorSpaceAgnosticDataspaceSetTo(ui::Dataspace::DISPLAY_P3)
1721 .thenExpectSetColorProfileCallUsesColorSpaceAgnosticDataspace(ui::Dataspace::DISPLAY_P3)
1722 .execute();
1723}
1724
1725TEST_F(OutputUpdateColorProfileTest_ColorSpaceAgnosticeDataspaceAffectsSetColorProfile, V0_SRGB) {
1726 verify().ifColorSpaceAgnosticDataspaceSetTo(ui::Dataspace::V0_SRGB)
1727 .thenExpectSetColorProfileCallUsesColorSpaceAgnosticDataspace(ui::Dataspace::V0_SRGB)
1728 .execute();
1729}
1730
1731struct OutputUpdateColorProfileTest_TopmostLayerPreferenceSetsOutputPreference
1732 : public OutputUpdateColorProfileTest {
1733 // Internally the implementation looks through the dataspaces of all the
1734 // visible layers. The topmost one that also has an actual dataspace
1735 // preference set is used to drive subsequent choices.
1736
1737 OutputUpdateColorProfileTest_TopmostLayerPreferenceSetsOutputPreference() {
1738 mRefreshArgs.outputColorSetting = OutputColorSetting::kEnhanced;
1739 mRefreshArgs.colorSpaceAgnosticDataspace = ui::Dataspace::UNKNOWN;
1740
1741 EXPECT_CALL(mOutput, getOutputLayerCount()).WillRepeatedly(Return(3));
1742 EXPECT_CALL(mOutput, setColorProfile(_)).WillRepeatedly(Return());
1743 }
1744
1745 struct IfTopLayerDataspaceState
1746 : public CallOrderStateMachineHelper<TestType, IfTopLayerDataspaceState> {
1747 [[nodiscard]] auto ifTopLayerIs(ui::Dataspace dataspace) {
1748 getInstance()->mLayer3.mLayerFEState.dataspace = dataspace;
1749 return nextState<AndIfMiddleLayerDataspaceState>();
1750 }
1751 [[nodiscard]] auto ifTopLayerHasNoPreference() {
1752 return ifTopLayerIs(ui::Dataspace::UNKNOWN);
1753 }
1754 };
1755
1756 struct AndIfMiddleLayerDataspaceState
1757 : public CallOrderStateMachineHelper<TestType, AndIfMiddleLayerDataspaceState> {
1758 [[nodiscard]] auto andIfMiddleLayerIs(ui::Dataspace dataspace) {
1759 getInstance()->mLayer2.mLayerFEState.dataspace = dataspace;
1760 return nextState<AndIfBottomLayerDataspaceState>();
1761 }
1762 [[nodiscard]] auto andIfMiddleLayerHasNoPreference() {
1763 return andIfMiddleLayerIs(ui::Dataspace::UNKNOWN);
1764 }
1765 };
1766
1767 struct AndIfBottomLayerDataspaceState
1768 : public CallOrderStateMachineHelper<TestType, AndIfBottomLayerDataspaceState> {
1769 [[nodiscard]] auto andIfBottomLayerIs(ui::Dataspace dataspace) {
1770 getInstance()->mLayer1.mLayerFEState.dataspace = dataspace;
1771 return nextState<ThenExpectBestColorModeCallUsesState>();
1772 }
1773 [[nodiscard]] auto andIfBottomLayerHasNoPreference() {
1774 return andIfBottomLayerIs(ui::Dataspace::UNKNOWN);
1775 }
1776 };
1777
1778 struct ThenExpectBestColorModeCallUsesState
1779 : public CallOrderStateMachineHelper<TestType, ThenExpectBestColorModeCallUsesState> {
1780 [[nodiscard]] auto thenExpectBestColorModeCallUses(ui::Dataspace dataspace) {
1781 EXPECT_CALL(*getInstance()->mDisplayColorProfile,
1782 getBestColorMode(dataspace, _, _, _, _));
1783 return nextState<ExecuteState>();
1784 }
1785 };
1786
1787 // Call this member function to start using the mini-DSL defined above.
1788 [[nodiscard]] auto verify() { return IfTopLayerDataspaceState::make(this); }
1789};
1790
1791TEST_F(OutputUpdateColorProfileTest_TopmostLayerPreferenceSetsOutputPreference,
1792 noStrongLayerPrefenceUses_V0_SRGB) {
1793 // If none of the layers indicate a preference, then V0_SRGB is the
1794 // preferred choice (subject to additional checks).
1795 verify().ifTopLayerHasNoPreference()
1796 .andIfMiddleLayerHasNoPreference()
1797 .andIfBottomLayerHasNoPreference()
1798 .thenExpectBestColorModeCallUses(ui::Dataspace::V0_SRGB)
1799 .execute();
1800}
1801
1802TEST_F(OutputUpdateColorProfileTest_TopmostLayerPreferenceSetsOutputPreference,
1803 ifTopmostUses_DisplayP3_Then_DisplayP3_Chosen) {
1804 // If only the topmost layer has a preference, then that is what is chosen.
1805 verify().ifTopLayerIs(ui::Dataspace::DISPLAY_P3)
1806 .andIfMiddleLayerHasNoPreference()
1807 .andIfBottomLayerHasNoPreference()
1808 .thenExpectBestColorModeCallUses(ui::Dataspace::DISPLAY_P3)
1809 .execute();
1810}
1811
1812TEST_F(OutputUpdateColorProfileTest_TopmostLayerPreferenceSetsOutputPreference,
1813 ifMiddleUses_DisplayP3_Then_DisplayP3_Chosen) {
1814 // If only the middle layer has a preference, that that is what is chosen.
1815 verify().ifTopLayerHasNoPreference()
1816 .andIfMiddleLayerIs(ui::Dataspace::DISPLAY_P3)
1817 .andIfBottomLayerHasNoPreference()
1818 .thenExpectBestColorModeCallUses(ui::Dataspace::DISPLAY_P3)
1819 .execute();
1820}
1821
1822TEST_F(OutputUpdateColorProfileTest_TopmostLayerPreferenceSetsOutputPreference,
1823 ifBottomUses_DisplayP3_Then_DisplayP3_Chosen) {
1824 // If only the middle layer has a preference, that that is what is chosen.
1825 verify().ifTopLayerHasNoPreference()
1826 .andIfMiddleLayerHasNoPreference()
1827 .andIfBottomLayerIs(ui::Dataspace::DISPLAY_P3)
1828 .thenExpectBestColorModeCallUses(ui::Dataspace::DISPLAY_P3)
1829 .execute();
1830}
1831
1832TEST_F(OutputUpdateColorProfileTest_TopmostLayerPreferenceSetsOutputPreference,
1833 ifTopUses_DisplayBT2020_AndBottomUses_DisplayP3_Then_DisplayBT2020_Chosen) {
1834 // If multiple layers have a preference, the topmost value is what is used.
1835 verify().ifTopLayerIs(ui::Dataspace::DISPLAY_BT2020)
1836 .andIfMiddleLayerHasNoPreference()
1837 .andIfBottomLayerIs(ui::Dataspace::DISPLAY_P3)
1838 .thenExpectBestColorModeCallUses(ui::Dataspace::DISPLAY_BT2020)
1839 .execute();
1840}
1841
1842TEST_F(OutputUpdateColorProfileTest_TopmostLayerPreferenceSetsOutputPreference,
1843 ifTopUses_DisplayP3_AndBottomUses_V0_SRGB_Then_DisplayP3_Chosen) {
1844 // If multiple layers have a preference, the topmost value is what is used.
1845 verify().ifTopLayerIs(ui::Dataspace::DISPLAY_P3)
1846 .andIfMiddleLayerHasNoPreference()
1847 .andIfBottomLayerIs(ui::Dataspace::DISPLAY_BT2020)
1848 .thenExpectBestColorModeCallUses(ui::Dataspace::DISPLAY_P3)
1849 .execute();
1850}
1851
1852struct OutputUpdateColorProfileTest_ForceOutputColorOverrides
1853 : public OutputUpdateColorProfileTest {
1854 // If CompositionRefreshArgs::forceOutputColorMode is set to some specific
1855 // values, it overrides the layer dataspace choice.
1856
1857 OutputUpdateColorProfileTest_ForceOutputColorOverrides() {
1858 mRefreshArgs.outputColorSetting = OutputColorSetting::kEnhanced;
1859 mRefreshArgs.colorSpaceAgnosticDataspace = ui::Dataspace::UNKNOWN;
1860
1861 mLayer1.mLayerFEState.dataspace = ui::Dataspace::DISPLAY_BT2020;
1862
1863 EXPECT_CALL(mOutput, getOutputLayerCount()).WillRepeatedly(Return(1));
1864 EXPECT_CALL(mOutput, setColorProfile(_)).WillRepeatedly(Return());
1865 }
1866
1867 struct IfForceOutputColorModeState
1868 : public CallOrderStateMachineHelper<TestType, IfForceOutputColorModeState> {
1869 [[nodiscard]] auto ifForceOutputColorMode(ui::ColorMode colorMode) {
1870 getInstance()->mRefreshArgs.forceOutputColorMode = colorMode;
1871 return nextState<ThenExpectBestColorModeCallUsesState>();
1872 }
1873 [[nodiscard]] auto ifNoOverride() { return ifForceOutputColorMode(ui::ColorMode::NATIVE); }
1874 };
1875
1876 struct ThenExpectBestColorModeCallUsesState
1877 : public CallOrderStateMachineHelper<TestType, ThenExpectBestColorModeCallUsesState> {
1878 [[nodiscard]] auto thenExpectBestColorModeCallUses(ui::Dataspace dataspace) {
1879 EXPECT_CALL(*getInstance()->mDisplayColorProfile,
1880 getBestColorMode(dataspace, _, _, _, _));
1881 return nextState<ExecuteState>();
1882 }
1883 };
1884
1885 // Call this member function to start using the mini-DSL defined above.
1886 [[nodiscard]] auto verify() { return IfForceOutputColorModeState::make(this); }
1887};
1888
1889TEST_F(OutputUpdateColorProfileTest_ForceOutputColorOverrides, NoOverride_DoesNotOverride) {
1890 // By default the layer state is used to set the preferred dataspace
1891 verify().ifNoOverride()
1892 .thenExpectBestColorModeCallUses(ui::Dataspace::DISPLAY_BT2020)
1893 .execute();
1894}
1895
1896TEST_F(OutputUpdateColorProfileTest_ForceOutputColorOverrides, SRGB_Override_USES_V0_SRGB) {
1897 // Setting ui::ColorMode::SRGB overrides it with ui::Dataspace::V0_SRGB
1898 verify().ifForceOutputColorMode(ui::ColorMode::SRGB)
1899 .thenExpectBestColorModeCallUses(ui::Dataspace::V0_SRGB)
1900 .execute();
1901}
1902
1903TEST_F(OutputUpdateColorProfileTest_ForceOutputColorOverrides, DisplayP3_Override_Uses_DisplayP3) {
1904 // Setting ui::ColorMode::DISPLAY_P3 overrides it with ui::Dataspace::DISPLAY_P3
1905 verify().ifForceOutputColorMode(ui::ColorMode::DISPLAY_P3)
1906 .thenExpectBestColorModeCallUses(ui::Dataspace::DISPLAY_P3)
1907 .execute();
1908}
1909
1910// HDR output requires all layers to be compatible with the chosen HDR
1911// dataspace, along with there being proper support.
1912struct OutputUpdateColorProfileTest_Hdr : public OutputUpdateColorProfileTest {
1913 OutputUpdateColorProfileTest_Hdr() {
1914 mRefreshArgs.outputColorSetting = OutputColorSetting::kEnhanced;
1915 mRefreshArgs.colorSpaceAgnosticDataspace = ui::Dataspace::UNKNOWN;
1916 EXPECT_CALL(mOutput, getOutputLayerCount()).WillRepeatedly(Return(2));
1917 EXPECT_CALL(mOutput, setColorProfile(_)).WillRepeatedly(Return());
1918 }
1919
1920 static constexpr ui::Dataspace kNonHdrDataspace = ui::Dataspace::DISPLAY_P3;
1921 static constexpr ui::Dataspace BT2020_PQ = ui::Dataspace::BT2020_PQ;
1922 static constexpr ui::Dataspace BT2020_HLG = ui::Dataspace::BT2020_HLG;
1923 static constexpr ui::Dataspace DISPLAY_P3 = ui::Dataspace::DISPLAY_P3;
1924
1925 struct IfTopLayerDataspaceState
1926 : public CallOrderStateMachineHelper<TestType, IfTopLayerDataspaceState> {
1927 [[nodiscard]] auto ifTopLayerIs(ui::Dataspace dataspace) {
1928 getInstance()->mLayer2.mLayerFEState.dataspace = dataspace;
1929 return nextState<AndTopLayerCompositionTypeState>();
1930 }
1931 [[nodiscard]] auto ifTopLayerIsNotHdr() { return ifTopLayerIs(kNonHdrDataspace); }
1932 };
1933
1934 struct AndTopLayerCompositionTypeState
1935 : public CallOrderStateMachineHelper<TestType, AndTopLayerCompositionTypeState> {
1936 [[nodiscard]] auto andTopLayerIsREComposed(bool renderEngineComposed) {
1937 getInstance()->mLayer2.mLayerFEState.forceClientComposition = renderEngineComposed;
1938 return nextState<AndIfBottomLayerDataspaceState>();
1939 }
1940 };
1941
1942 struct AndIfBottomLayerDataspaceState
1943 : public CallOrderStateMachineHelper<TestType, AndIfBottomLayerDataspaceState> {
1944 [[nodiscard]] auto andIfBottomLayerIs(ui::Dataspace dataspace) {
1945 getInstance()->mLayer1.mLayerFEState.dataspace = dataspace;
1946 return nextState<AndBottomLayerCompositionTypeState>();
1947 }
1948 [[nodiscard]] auto andIfBottomLayerIsNotHdr() {
1949 return andIfBottomLayerIs(kNonHdrDataspace);
1950 }
1951 };
1952
1953 struct AndBottomLayerCompositionTypeState
1954 : public CallOrderStateMachineHelper<TestType, AndBottomLayerCompositionTypeState> {
1955 [[nodiscard]] auto andBottomLayerIsREComposed(bool renderEngineComposed) {
1956 getInstance()->mLayer1.mLayerFEState.forceClientComposition = renderEngineComposed;
1957 return nextState<AndIfHasLegacySupportState>();
1958 }
1959 };
1960
1961 struct AndIfHasLegacySupportState
1962 : public CallOrderStateMachineHelper<TestType, AndIfHasLegacySupportState> {
1963 [[nodiscard]] auto andIfLegacySupportFor(ui::Dataspace dataspace, bool legacySupport) {
1964 EXPECT_CALL(*getInstance()->mDisplayColorProfile, hasLegacyHdrSupport(dataspace))
1965 .WillOnce(Return(legacySupport));
1966 return nextState<ThenExpectBestColorModeCallUsesState>();
1967 }
1968 };
1969
1970 struct ThenExpectBestColorModeCallUsesState
1971 : public CallOrderStateMachineHelper<TestType, ThenExpectBestColorModeCallUsesState> {
1972 [[nodiscard]] auto thenExpectBestColorModeCallUses(ui::Dataspace dataspace) {
1973 EXPECT_CALL(*getInstance()->mDisplayColorProfile,
1974 getBestColorMode(dataspace, _, _, _, _));
1975 return nextState<ExecuteState>();
1976 }
1977 };
1978
1979 // Call this member function to start using the mini-DSL defined above.
1980 [[nodiscard]] auto verify() { return IfTopLayerDataspaceState::make(this); }
1981};
1982
1983TEST_F(OutputUpdateColorProfileTest_Hdr, PQ_HW_On_PQ_HW_Uses_PQ) {
1984 // If all layers use BT2020_PQ, and there are no other special conditions,
1985 // BT2020_PQ is used.
1986 verify().ifTopLayerIs(BT2020_PQ)
1987 .andTopLayerIsREComposed(false)
1988 .andIfBottomLayerIs(BT2020_PQ)
1989 .andBottomLayerIsREComposed(false)
1990 .andIfLegacySupportFor(BT2020_PQ, false)
1991 .thenExpectBestColorModeCallUses(BT2020_PQ)
1992 .execute();
1993}
1994
1995TEST_F(OutputUpdateColorProfileTest_Hdr, PQ_HW_On_PQ_HW_IfPQHasLegacySupport_Uses_DisplayP3) {
1996 // BT2020_PQ is not used if there is only legacy support for it.
1997 verify().ifTopLayerIs(BT2020_PQ)
1998 .andTopLayerIsREComposed(false)
1999 .andIfBottomLayerIs(BT2020_PQ)
2000 .andBottomLayerIsREComposed(false)
2001 .andIfLegacySupportFor(BT2020_PQ, true)
2002 .thenExpectBestColorModeCallUses(DISPLAY_P3)
2003 .execute();
2004}
2005
2006TEST_F(OutputUpdateColorProfileTest_Hdr, PQ_HW_On_PQ_RE_Uses_PQ) {
2007 // BT2020_PQ is still used if the bottom layer is RenderEngine composed.
2008 verify().ifTopLayerIs(BT2020_PQ)
2009 .andTopLayerIsREComposed(false)
2010 .andIfBottomLayerIs(BT2020_PQ)
2011 .andBottomLayerIsREComposed(true)
2012 .andIfLegacySupportFor(BT2020_PQ, false)
2013 .thenExpectBestColorModeCallUses(BT2020_PQ)
2014 .execute();
2015}
2016
2017TEST_F(OutputUpdateColorProfileTest_Hdr, PQ_RE_On_PQ_HW_Uses_DisplayP3) {
2018 // BT2020_PQ is not used if the top layer is RenderEngine composed.
2019 verify().ifTopLayerIs(BT2020_PQ)
2020 .andTopLayerIsREComposed(true)
2021 .andIfBottomLayerIs(BT2020_PQ)
2022 .andBottomLayerIsREComposed(false)
2023 .andIfLegacySupportFor(BT2020_PQ, false)
2024 .thenExpectBestColorModeCallUses(DISPLAY_P3)
2025 .execute();
2026}
2027
2028TEST_F(OutputUpdateColorProfileTest_Hdr, PQ_HW_On_HLG_HW_Uses_PQ) {
2029 // If there is mixed HLG/PQ use, and the topmost layer is PQ, then PQ is used if there
2030 // are no other special conditions.
2031 verify().ifTopLayerIs(BT2020_PQ)
2032 .andTopLayerIsREComposed(false)
2033 .andIfBottomLayerIs(BT2020_HLG)
2034 .andBottomLayerIsREComposed(false)
2035 .andIfLegacySupportFor(BT2020_PQ, false)
2036 .thenExpectBestColorModeCallUses(BT2020_PQ)
2037 .execute();
2038}
2039
2040TEST_F(OutputUpdateColorProfileTest_Hdr, PQ_HW_On_HLG_HW_IfPQHasLegacySupport_Uses_DisplayP3) {
2041 // BT2020_PQ is not used if there is only legacy support for it.
2042 verify().ifTopLayerIs(BT2020_PQ)
2043 .andTopLayerIsREComposed(false)
2044 .andIfBottomLayerIs(BT2020_HLG)
2045 .andBottomLayerIsREComposed(false)
2046 .andIfLegacySupportFor(BT2020_PQ, true)
2047 .thenExpectBestColorModeCallUses(DISPLAY_P3)
2048 .execute();
2049}
2050
2051TEST_F(OutputUpdateColorProfileTest_Hdr, PQ_HW_On_HLG_RE_Uses_PQ) {
2052 // BT2020_PQ is used if the bottom HLG layer is RenderEngine composed.
2053 verify().ifTopLayerIs(BT2020_PQ)
2054 .andTopLayerIsREComposed(false)
2055 .andIfBottomLayerIs(BT2020_HLG)
2056 .andBottomLayerIsREComposed(true)
2057 .andIfLegacySupportFor(BT2020_PQ, false)
2058 .thenExpectBestColorModeCallUses(BT2020_PQ)
2059 .execute();
2060}
2061
2062TEST_F(OutputUpdateColorProfileTest_Hdr, PQ_RE_On_HLG_HW_Uses_DisplayP3) {
2063 // BT2020_PQ is not used if the top PQ layer is RenderEngine composed.
2064 verify().ifTopLayerIs(BT2020_PQ)
2065 .andTopLayerIsREComposed(true)
2066 .andIfBottomLayerIs(BT2020_HLG)
2067 .andBottomLayerIsREComposed(false)
2068 .andIfLegacySupportFor(BT2020_PQ, false)
2069 .thenExpectBestColorModeCallUses(DISPLAY_P3)
2070 .execute();
2071}
2072
2073TEST_F(OutputUpdateColorProfileTest_Hdr, HLG_HW_On_PQ_HW_Uses_PQ) {
2074 // If there is mixed HLG/PQ use, and the topmost layer is HLG, then PQ is
2075 // used if there are no other special conditions.
2076 verify().ifTopLayerIs(BT2020_HLG)
2077 .andTopLayerIsREComposed(false)
2078 .andIfBottomLayerIs(BT2020_PQ)
2079 .andBottomLayerIsREComposed(false)
2080 .andIfLegacySupportFor(BT2020_PQ, false)
2081 .thenExpectBestColorModeCallUses(BT2020_PQ)
2082 .execute();
2083}
2084
2085TEST_F(OutputUpdateColorProfileTest_Hdr, HLG_HW_On_PQ_HW_IfPQHasLegacySupport_Uses_DisplayP3) {
2086 // BT2020_PQ is not used if there is only legacy support for it.
2087 verify().ifTopLayerIs(BT2020_HLG)
2088 .andTopLayerIsREComposed(false)
2089 .andIfBottomLayerIs(BT2020_PQ)
2090 .andBottomLayerIsREComposed(false)
2091 .andIfLegacySupportFor(BT2020_PQ, true)
2092 .thenExpectBestColorModeCallUses(DISPLAY_P3)
2093 .execute();
2094}
2095
2096TEST_F(OutputUpdateColorProfileTest_Hdr, HLG_HW_On_PQ_RE_Uses_DisplayP3) {
2097 // BT2020_PQ is not used if the bottom PQ layer is RenderEngine composed.
2098 verify().ifTopLayerIs(BT2020_HLG)
2099 .andTopLayerIsREComposed(false)
2100 .andIfBottomLayerIs(BT2020_PQ)
2101 .andBottomLayerIsREComposed(true)
2102 .andIfLegacySupportFor(BT2020_PQ, false)
2103 .thenExpectBestColorModeCallUses(DISPLAY_P3)
2104 .execute();
2105}
2106
2107TEST_F(OutputUpdateColorProfileTest_Hdr, HLG_RE_On_PQ_HW_Uses_PQ) {
2108 // BT2020_PQ is still used if the top HLG layer is RenderEngine composed.
2109 verify().ifTopLayerIs(BT2020_HLG)
2110 .andTopLayerIsREComposed(true)
2111 .andIfBottomLayerIs(BT2020_PQ)
2112 .andBottomLayerIsREComposed(false)
2113 .andIfLegacySupportFor(BT2020_PQ, false)
2114 .thenExpectBestColorModeCallUses(BT2020_PQ)
2115 .execute();
2116}
2117
2118TEST_F(OutputUpdateColorProfileTest_Hdr, HLG_HW_On_HLG_HW_Uses_HLG) {
2119 // If all layers use HLG then HLG is used if there are no other special
2120 // conditions.
2121 verify().ifTopLayerIs(BT2020_HLG)
2122 .andTopLayerIsREComposed(false)
2123 .andIfBottomLayerIs(BT2020_HLG)
2124 .andBottomLayerIsREComposed(false)
2125 .andIfLegacySupportFor(BT2020_HLG, false)
2126 .thenExpectBestColorModeCallUses(BT2020_HLG)
2127 .execute();
2128}
2129
2130TEST_F(OutputUpdateColorProfileTest_Hdr, HLG_HW_On_HLG_HW_IfPQHasLegacySupport_Uses_DisplayP3) {
2131 // BT2020_HLG is not used if there is legacy support for it.
2132 verify().ifTopLayerIs(BT2020_HLG)
2133 .andTopLayerIsREComposed(false)
2134 .andIfBottomLayerIs(BT2020_HLG)
2135 .andBottomLayerIsREComposed(false)
2136 .andIfLegacySupportFor(BT2020_HLG, true)
2137 .thenExpectBestColorModeCallUses(DISPLAY_P3)
2138 .execute();
2139}
2140
2141TEST_F(OutputUpdateColorProfileTest_Hdr, HLG_HW_On_HLG_RE_Uses_HLG) {
2142 // BT2020_HLG is used even if the bottom layer is client composed.
2143 verify().ifTopLayerIs(BT2020_HLG)
2144 .andTopLayerIsREComposed(false)
2145 .andIfBottomLayerIs(BT2020_HLG)
2146 .andBottomLayerIsREComposed(true)
2147 .andIfLegacySupportFor(BT2020_HLG, false)
2148 .thenExpectBestColorModeCallUses(BT2020_HLG)
2149 .execute();
2150}
2151
2152TEST_F(OutputUpdateColorProfileTest_Hdr, HLG_RE_On_HLG_HW_Uses_HLG) {
2153 // BT2020_HLG is used even if the top layer is client composed.
2154 verify().ifTopLayerIs(BT2020_HLG)
2155 .andTopLayerIsREComposed(true)
2156 .andIfBottomLayerIs(BT2020_HLG)
2157 .andBottomLayerIsREComposed(false)
2158 .andIfLegacySupportFor(BT2020_HLG, false)
2159 .thenExpectBestColorModeCallUses(BT2020_HLG)
2160 .execute();
2161}
2162
2163TEST_F(OutputUpdateColorProfileTest_Hdr, PQ_HW_On_NonHdr_HW_Uses_PQ) {
2164 // Even if there are non-HDR layers present, BT2020_PQ can still be used.
2165 verify().ifTopLayerIs(BT2020_PQ)
2166 .andTopLayerIsREComposed(false)
2167 .andIfBottomLayerIsNotHdr()
2168 .andBottomLayerIsREComposed(false)
2169 .andIfLegacySupportFor(BT2020_PQ, false)
2170 .thenExpectBestColorModeCallUses(BT2020_PQ)
2171 .execute();
2172}
2173
2174TEST_F(OutputUpdateColorProfileTest_Hdr, HLG_HW_On_NonHdr_RE_Uses_HLG) {
2175 // If all layers use HLG then HLG is used if there are no other special
2176 // conditions.
2177 verify().ifTopLayerIs(BT2020_HLG)
2178 .andTopLayerIsREComposed(false)
2179 .andIfBottomLayerIsNotHdr()
2180 .andBottomLayerIsREComposed(true)
2181 .andIfLegacySupportFor(BT2020_HLG, false)
2182 .thenExpectBestColorModeCallUses(BT2020_HLG)
2183 .execute();
2184}
2185
2186struct OutputUpdateColorProfile_AffectsChosenRenderIntentTest
2187 : public OutputUpdateColorProfileTest {
2188 // The various values for CompositionRefreshArgs::outputColorSetting affect
2189 // the chosen renderIntent, along with whether the preferred dataspace is an
2190 // HDR dataspace or not.
2191
2192 OutputUpdateColorProfile_AffectsChosenRenderIntentTest() {
2193 mRefreshArgs.outputColorSetting = OutputColorSetting::kEnhanced;
2194 mRefreshArgs.colorSpaceAgnosticDataspace = ui::Dataspace::UNKNOWN;
2195 mLayer1.mLayerFEState.dataspace = ui::Dataspace::BT2020_PQ;
2196 EXPECT_CALL(mOutput, getOutputLayerCount()).WillRepeatedly(Return(1));
2197 EXPECT_CALL(mOutput, setColorProfile(_)).WillRepeatedly(Return());
2198 EXPECT_CALL(*mDisplayColorProfile, hasLegacyHdrSupport(ui::Dataspace::BT2020_PQ))
2199 .WillRepeatedly(Return(false));
2200 }
2201
2202 // The tests here involve enough state and GMock setup that using a mini-DSL
2203 // makes the tests much more readable, and allows the test to focus more on
2204 // the intent than on some of the details.
2205
2206 static constexpr ui::Dataspace kNonHdrDataspace = ui::Dataspace::DISPLAY_P3;
2207 static constexpr ui::Dataspace kHdrDataspace = ui::Dataspace::BT2020_PQ;
2208
2209 struct IfDataspaceChosenState
2210 : public CallOrderStateMachineHelper<TestType, IfDataspaceChosenState> {
2211 [[nodiscard]] auto ifDataspaceChosenIs(ui::Dataspace dataspace) {
2212 getInstance()->mLayer1.mLayerFEState.dataspace = dataspace;
2213 return nextState<AndOutputColorSettingState>();
2214 }
2215 [[nodiscard]] auto ifDataspaceChosenIsNonHdr() {
2216 return ifDataspaceChosenIs(kNonHdrDataspace);
2217 }
2218 [[nodiscard]] auto ifDataspaceChosenIsHdr() { return ifDataspaceChosenIs(kHdrDataspace); }
2219 };
2220
2221 struct AndOutputColorSettingState
2222 : public CallOrderStateMachineHelper<TestType, AndOutputColorSettingState> {
2223 [[nodiscard]] auto andOutputColorSettingIs(OutputColorSetting setting) {
2224 getInstance()->mRefreshArgs.outputColorSetting = setting;
2225 return nextState<ThenExpectBestColorModeCallUsesState>();
2226 }
2227 };
2228
2229 struct ThenExpectBestColorModeCallUsesState
2230 : public CallOrderStateMachineHelper<TestType, ThenExpectBestColorModeCallUsesState> {
2231 [[nodiscard]] auto thenExpectBestColorModeCallUses(ui::RenderIntent intent) {
2232 EXPECT_CALL(*getInstance()->mDisplayColorProfile,
2233 getBestColorMode(getInstance()->mLayer1.mLayerFEState.dataspace, intent, _,
2234 _, _));
2235 return nextState<ExecuteState>();
2236 }
2237 };
2238
2239 // Tests call one of these two helper member functions to start using the
2240 // mini-DSL defined above.
2241 [[nodiscard]] auto verify() { return IfDataspaceChosenState::make(this); }
2242};
2243
2244TEST_F(OutputUpdateColorProfile_AffectsChosenRenderIntentTest,
2245 Managed_NonHdr_Prefers_Colorimetric) {
2246 verify().ifDataspaceChosenIsNonHdr()
2247 .andOutputColorSettingIs(OutputColorSetting::kManaged)
2248 .thenExpectBestColorModeCallUses(ui::RenderIntent::COLORIMETRIC)
2249 .execute();
2250}
2251
2252TEST_F(OutputUpdateColorProfile_AffectsChosenRenderIntentTest,
2253 Managed_Hdr_Prefers_ToneMapColorimetric) {
2254 verify().ifDataspaceChosenIsHdr()
2255 .andOutputColorSettingIs(OutputColorSetting::kManaged)
2256 .thenExpectBestColorModeCallUses(ui::RenderIntent::TONE_MAP_COLORIMETRIC)
2257 .execute();
2258}
2259
2260TEST_F(OutputUpdateColorProfile_AffectsChosenRenderIntentTest, Enhanced_NonHdr_Prefers_Enhance) {
2261 verify().ifDataspaceChosenIsNonHdr()
2262 .andOutputColorSettingIs(OutputColorSetting::kEnhanced)
2263 .thenExpectBestColorModeCallUses(ui::RenderIntent::ENHANCE)
2264 .execute();
2265}
2266
2267TEST_F(OutputUpdateColorProfile_AffectsChosenRenderIntentTest,
2268 Enhanced_Hdr_Prefers_ToneMapEnhance) {
2269 verify().ifDataspaceChosenIsHdr()
2270 .andOutputColorSettingIs(OutputColorSetting::kEnhanced)
2271 .thenExpectBestColorModeCallUses(ui::RenderIntent::TONE_MAP_ENHANCE)
2272 .execute();
2273}
2274
2275TEST_F(OutputUpdateColorProfile_AffectsChosenRenderIntentTest, Vendor_NonHdr_Prefers_Vendor) {
2276 verify().ifDataspaceChosenIsNonHdr()
2277 .andOutputColorSettingIs(kVendorSpecifiedOutputColorSetting)
2278 .thenExpectBestColorModeCallUses(
2279 static_cast<ui::RenderIntent>(kVendorSpecifiedOutputColorSetting))
2280 .execute();
2281}
2282
2283TEST_F(OutputUpdateColorProfile_AffectsChosenRenderIntentTest, Vendor_Hdr_Prefers_Vendor) {
2284 verify().ifDataspaceChosenIsHdr()
2285 .andOutputColorSettingIs(kVendorSpecifiedOutputColorSetting)
2286 .thenExpectBestColorModeCallUses(
2287 static_cast<ui::RenderIntent>(kVendorSpecifiedOutputColorSetting))
2288 .execute();
2289}
Lloyd Piquefaa3f192019-11-14 14:05:09 -08002290
2291/*
2292 * Output::beginFrame()
2293 */
2294
Lloyd Piquee5965952019-11-18 16:16:32 -08002295struct OutputBeginFrameTest : public ::testing::Test {
2296 using TestType = OutputBeginFrameTest;
2297
2298 struct OutputPartialMock : public OutputPartialMockBase {
Lloyd Pique739afaf2019-11-21 16:40:05 -08002299 // Sets up the helper functions called by the function under test to use
2300 // mock implementations.
Lloyd Piquee5965952019-11-18 16:16:32 -08002301 MOCK_CONST_METHOD1(getDirtyRegion, Region(bool));
2302 };
2303
2304 OutputBeginFrameTest() {
2305 mOutput.setDisplayColorProfileForTest(
2306 std::unique_ptr<DisplayColorProfile>(mDisplayColorProfile));
2307 mOutput.setRenderSurfaceForTest(std::unique_ptr<RenderSurface>(mRenderSurface));
2308 }
2309
2310 struct IfGetDirtyRegionExpectationState
2311 : public CallOrderStateMachineHelper<TestType, IfGetDirtyRegionExpectationState> {
2312 [[nodiscard]] auto ifGetDirtyRegionReturns(Region dirtyRegion) {
2313 EXPECT_CALL(getInstance()->mOutput, getDirtyRegion(false))
2314 .WillOnce(Return(dirtyRegion));
2315 return nextState<AndIfGetOutputLayerCountExpectationState>();
2316 }
2317 };
2318
2319 struct AndIfGetOutputLayerCountExpectationState
2320 : public CallOrderStateMachineHelper<TestType, AndIfGetOutputLayerCountExpectationState> {
2321 [[nodiscard]] auto andIfGetOutputLayerCountReturns(size_t layerCount) {
2322 EXPECT_CALL(getInstance()->mOutput, getOutputLayerCount()).WillOnce(Return(layerCount));
2323 return nextState<AndIfLastCompositionHadVisibleLayersState>();
2324 }
2325 };
2326
2327 struct AndIfLastCompositionHadVisibleLayersState
2328 : public CallOrderStateMachineHelper<TestType,
2329 AndIfLastCompositionHadVisibleLayersState> {
2330 [[nodiscard]] auto andIfLastCompositionHadVisibleLayersIs(bool hadOutputLayers) {
2331 getInstance()->mOutput.mState.lastCompositionHadVisibleLayers = hadOutputLayers;
2332 return nextState<ThenExpectRenderSurfaceBeginFrameCallState>();
2333 }
2334 };
2335
2336 struct ThenExpectRenderSurfaceBeginFrameCallState
2337 : public CallOrderStateMachineHelper<TestType,
2338 ThenExpectRenderSurfaceBeginFrameCallState> {
2339 [[nodiscard]] auto thenExpectRenderSurfaceBeginFrameCall(bool mustRecompose) {
2340 EXPECT_CALL(*getInstance()->mRenderSurface, beginFrame(mustRecompose));
2341 return nextState<ExecuteState>();
2342 }
2343 };
2344
2345 struct ExecuteState : public CallOrderStateMachineHelper<TestType, ExecuteState> {
2346 [[nodiscard]] auto execute() {
2347 getInstance()->mOutput.beginFrame();
2348 return nextState<CheckPostconditionHadVisibleLayersState>();
2349 }
2350 };
2351
2352 struct CheckPostconditionHadVisibleLayersState
2353 : public CallOrderStateMachineHelper<TestType, CheckPostconditionHadVisibleLayersState> {
2354 void checkPostconditionHadVisibleLayers(bool expected) {
2355 EXPECT_EQ(expected, getInstance()->mOutput.mState.lastCompositionHadVisibleLayers);
2356 }
2357 };
2358
2359 // Tests call one of these two helper member functions to start using the
2360 // mini-DSL defined above.
2361 [[nodiscard]] auto verify() { return IfGetDirtyRegionExpectationState::make(this); }
2362
2363 static const Region kEmptyRegion;
2364 static const Region kNotEmptyRegion;
2365
2366 mock::DisplayColorProfile* mDisplayColorProfile = new StrictMock<mock::DisplayColorProfile>();
2367 mock::RenderSurface* mRenderSurface = new StrictMock<mock::RenderSurface>();
2368 StrictMock<OutputPartialMock> mOutput;
2369};
2370
2371const Region OutputBeginFrameTest::kEmptyRegion{Rect{0, 0, 0, 0}};
2372const Region OutputBeginFrameTest::kNotEmptyRegion{Rect{0, 0, 1, 1}};
2373
2374TEST_F(OutputBeginFrameTest, hasDirtyHasLayersHadLayersLastFrame) {
2375 verify().ifGetDirtyRegionReturns(kNotEmptyRegion)
2376 .andIfGetOutputLayerCountReturns(1u)
2377 .andIfLastCompositionHadVisibleLayersIs(true)
2378 .thenExpectRenderSurfaceBeginFrameCall(true)
2379 .execute()
2380 .checkPostconditionHadVisibleLayers(true);
2381}
2382
2383TEST_F(OutputBeginFrameTest, hasDirtyNotHasLayersHadLayersLastFrame) {
2384 verify().ifGetDirtyRegionReturns(kNotEmptyRegion)
2385 .andIfGetOutputLayerCountReturns(0u)
2386 .andIfLastCompositionHadVisibleLayersIs(true)
2387 .thenExpectRenderSurfaceBeginFrameCall(true)
2388 .execute()
2389 .checkPostconditionHadVisibleLayers(false);
2390}
2391
2392TEST_F(OutputBeginFrameTest, hasDirtyHasLayersNotHadLayersLastFrame) {
2393 verify().ifGetDirtyRegionReturns(kNotEmptyRegion)
2394 .andIfGetOutputLayerCountReturns(1u)
2395 .andIfLastCompositionHadVisibleLayersIs(false)
2396 .thenExpectRenderSurfaceBeginFrameCall(true)
2397 .execute()
2398 .checkPostconditionHadVisibleLayers(true);
2399}
2400
2401TEST_F(OutputBeginFrameTest, hasDirtyNotHasLayersNotHadLayersLastFrame) {
2402 verify().ifGetDirtyRegionReturns(kNotEmptyRegion)
2403 .andIfGetOutputLayerCountReturns(0u)
2404 .andIfLastCompositionHadVisibleLayersIs(false)
2405 .thenExpectRenderSurfaceBeginFrameCall(false)
2406 .execute()
2407 .checkPostconditionHadVisibleLayers(false);
2408}
2409
2410TEST_F(OutputBeginFrameTest, notHasDirtyHasLayersHadLayersLastFrame) {
2411 verify().ifGetDirtyRegionReturns(kEmptyRegion)
2412 .andIfGetOutputLayerCountReturns(1u)
2413 .andIfLastCompositionHadVisibleLayersIs(true)
2414 .thenExpectRenderSurfaceBeginFrameCall(false)
2415 .execute()
2416 .checkPostconditionHadVisibleLayers(true);
2417}
2418
2419TEST_F(OutputBeginFrameTest, notHasDirtyNotHasLayersHadLayersLastFrame) {
2420 verify().ifGetDirtyRegionReturns(kEmptyRegion)
2421 .andIfGetOutputLayerCountReturns(0u)
2422 .andIfLastCompositionHadVisibleLayersIs(true)
2423 .thenExpectRenderSurfaceBeginFrameCall(false)
2424 .execute()
2425 .checkPostconditionHadVisibleLayers(true);
2426}
2427
2428TEST_F(OutputBeginFrameTest, notHasDirtyHasLayersNotHadLayersLastFrame) {
2429 verify().ifGetDirtyRegionReturns(kEmptyRegion)
2430 .andIfGetOutputLayerCountReturns(1u)
2431 .andIfLastCompositionHadVisibleLayersIs(false)
2432 .thenExpectRenderSurfaceBeginFrameCall(false)
2433 .execute()
2434 .checkPostconditionHadVisibleLayers(false);
2435}
2436
2437TEST_F(OutputBeginFrameTest, notHasDirtyNotHasLayersNotHadLayersLastFrame) {
2438 verify().ifGetDirtyRegionReturns(kEmptyRegion)
2439 .andIfGetOutputLayerCountReturns(0u)
2440 .andIfLastCompositionHadVisibleLayersIs(false)
2441 .thenExpectRenderSurfaceBeginFrameCall(false)
2442 .execute()
2443 .checkPostconditionHadVisibleLayers(false);
2444}
2445
Lloyd Piquefaa3f192019-11-14 14:05:09 -08002446/*
2447 * Output::devOptRepaintFlash()
2448 */
2449
Lloyd Piquedb462d82019-11-19 17:58:46 -08002450struct OutputDevOptRepaintFlashTest : public testing::Test {
2451 struct OutputPartialMock : public OutputPartialMockBase {
Lloyd Pique739afaf2019-11-21 16:40:05 -08002452 // Sets up the helper functions called by the function under test to use
2453 // mock implementations.
Lloyd Piquedb462d82019-11-19 17:58:46 -08002454 MOCK_CONST_METHOD1(getDirtyRegion, Region(bool));
2455 MOCK_METHOD1(composeSurfaces, std::optional<base::unique_fd>(const Region&));
2456 MOCK_METHOD0(postFramebuffer, void());
2457 MOCK_METHOD0(prepareFrame, void());
2458 };
2459
2460 OutputDevOptRepaintFlashTest() {
2461 mOutput.setDisplayColorProfileForTest(
2462 std::unique_ptr<DisplayColorProfile>(mDisplayColorProfile));
2463 mOutput.setRenderSurfaceForTest(std::unique_ptr<RenderSurface>(mRenderSurface));
2464 }
2465
2466 static const Region kEmptyRegion;
2467 static const Region kNotEmptyRegion;
2468
2469 StrictMock<OutputPartialMock> mOutput;
2470 mock::DisplayColorProfile* mDisplayColorProfile = new StrictMock<mock::DisplayColorProfile>();
2471 mock::RenderSurface* mRenderSurface = new StrictMock<mock::RenderSurface>();
2472 CompositionRefreshArgs mRefreshArgs;
2473};
2474
2475const Region OutputDevOptRepaintFlashTest::kEmptyRegion{Rect{0, 0, 0, 0}};
2476const Region OutputDevOptRepaintFlashTest::kNotEmptyRegion{Rect{0, 0, 1, 1}};
2477
2478TEST_F(OutputDevOptRepaintFlashTest, doesNothingIfFlashDelayNotSet) {
2479 mRefreshArgs.devOptFlashDirtyRegionsDelay = {};
2480 mRefreshArgs.repaintEverything = true;
2481 mOutput.mState.isEnabled = true;
2482
2483 mOutput.devOptRepaintFlash(mRefreshArgs);
2484}
2485
2486TEST_F(OutputDevOptRepaintFlashTest, postsAndPreparesANewFrameIfNotEnabled) {
2487 mRefreshArgs.devOptFlashDirtyRegionsDelay = std::chrono::microseconds(1);
2488 mRefreshArgs.repaintEverything = true;
2489 mOutput.mState.isEnabled = false;
2490
2491 InSequence seq;
2492 EXPECT_CALL(mOutput, postFramebuffer());
2493 EXPECT_CALL(mOutput, prepareFrame());
2494
2495 mOutput.devOptRepaintFlash(mRefreshArgs);
2496}
2497
2498TEST_F(OutputDevOptRepaintFlashTest, postsAndPreparesANewFrameIfNotDirty) {
2499 mRefreshArgs.devOptFlashDirtyRegionsDelay = std::chrono::microseconds(1);
2500 mRefreshArgs.repaintEverything = true;
2501 mOutput.mState.isEnabled = true;
2502
2503 InSequence seq;
2504 EXPECT_CALL(mOutput, getDirtyRegion(true)).WillOnce(Return(kEmptyRegion));
2505 EXPECT_CALL(mOutput, postFramebuffer());
2506 EXPECT_CALL(mOutput, prepareFrame());
2507
2508 mOutput.devOptRepaintFlash(mRefreshArgs);
2509}
2510
2511TEST_F(OutputDevOptRepaintFlashTest, alsoComposesSurfacesAndQueuesABufferIfDirty) {
2512 mRefreshArgs.devOptFlashDirtyRegionsDelay = std::chrono::microseconds(1);
2513 mRefreshArgs.repaintEverything = false;
2514 mOutput.mState.isEnabled = true;
2515
2516 InSequence seq;
2517 EXPECT_CALL(mOutput, getDirtyRegion(false)).WillOnce(Return(kNotEmptyRegion));
2518 EXPECT_CALL(mOutput, composeSurfaces(RegionEq(kNotEmptyRegion)));
2519 EXPECT_CALL(*mRenderSurface, queueBuffer(_));
2520 EXPECT_CALL(mOutput, postFramebuffer());
2521 EXPECT_CALL(mOutput, prepareFrame());
2522
2523 mOutput.devOptRepaintFlash(mRefreshArgs);
2524}
2525
Lloyd Piquefaa3f192019-11-14 14:05:09 -08002526/*
2527 * Output::finishFrame()
2528 */
2529
Lloyd Pique03561a62019-11-19 18:34:52 -08002530struct OutputFinishFrameTest : public testing::Test {
2531 struct OutputPartialMock : public OutputPartialMockBase {
Lloyd Pique739afaf2019-11-21 16:40:05 -08002532 // Sets up the helper functions called by the function under test to use
2533 // mock implementations.
Lloyd Pique03561a62019-11-19 18:34:52 -08002534 MOCK_METHOD1(composeSurfaces, std::optional<base::unique_fd>(const Region&));
2535 MOCK_METHOD0(postFramebuffer, void());
2536 };
2537
2538 OutputFinishFrameTest() {
2539 mOutput.setDisplayColorProfileForTest(
2540 std::unique_ptr<DisplayColorProfile>(mDisplayColorProfile));
2541 mOutput.setRenderSurfaceForTest(std::unique_ptr<RenderSurface>(mRenderSurface));
2542 }
2543
2544 StrictMock<OutputPartialMock> mOutput;
2545 mock::DisplayColorProfile* mDisplayColorProfile = new StrictMock<mock::DisplayColorProfile>();
2546 mock::RenderSurface* mRenderSurface = new StrictMock<mock::RenderSurface>();
2547 CompositionRefreshArgs mRefreshArgs;
2548};
2549
2550TEST_F(OutputFinishFrameTest, ifNotEnabledDoesNothing) {
2551 mOutput.mState.isEnabled = false;
2552
2553 mOutput.finishFrame(mRefreshArgs);
2554}
2555
2556TEST_F(OutputFinishFrameTest, takesEarlyOutifComposeSurfacesReturnsNoFence) {
2557 mOutput.mState.isEnabled = true;
2558
2559 InSequence seq;
2560 EXPECT_CALL(mOutput, composeSurfaces(RegionEq(Region::INVALID_REGION)));
2561
2562 mOutput.finishFrame(mRefreshArgs);
2563}
2564
2565TEST_F(OutputFinishFrameTest, queuesBufferIfComposeSurfacesReturnsAFence) {
2566 mOutput.mState.isEnabled = true;
2567
2568 InSequence seq;
2569 EXPECT_CALL(mOutput, composeSurfaces(RegionEq(Region::INVALID_REGION)))
2570 .WillOnce(Return(ByMove(base::unique_fd())));
2571 EXPECT_CALL(*mRenderSurface, queueBuffer(_));
2572
2573 mOutput.finishFrame(mRefreshArgs);
2574}
Lloyd Piquefaa3f192019-11-14 14:05:09 -08002575
2576/*
2577 * Output::postFramebuffer()
2578 */
2579
Lloyd Pique07178e32019-11-19 19:15:26 -08002580struct OutputPostFramebufferTest : public testing::Test {
2581 struct OutputPartialMock : public OutputPartialMockBase {
Lloyd Pique739afaf2019-11-21 16:40:05 -08002582 // Sets up the helper functions called by the function under test to use
2583 // mock implementations.
Lloyd Pique07178e32019-11-19 19:15:26 -08002584 MOCK_METHOD0(presentAndGetFrameFences, compositionengine::Output::FrameFences());
2585 };
2586
2587 struct Layer {
2588 Layer() {
2589 EXPECT_CALL(outputLayer, getLayerFE()).WillRepeatedly(ReturnRef(layerFE));
2590 EXPECT_CALL(outputLayer, getHwcLayer()).WillRepeatedly(Return(&hwc2Layer));
2591 }
2592
2593 StrictMock<mock::OutputLayer> outputLayer;
2594 StrictMock<mock::LayerFE> layerFE;
2595 StrictMock<HWC2::mock::Layer> hwc2Layer;
2596 };
2597
2598 OutputPostFramebufferTest() {
2599 mOutput.setDisplayColorProfileForTest(
2600 std::unique_ptr<DisplayColorProfile>(mDisplayColorProfile));
2601 mOutput.setRenderSurfaceForTest(std::unique_ptr<RenderSurface>(mRenderSurface));
2602
2603 EXPECT_CALL(mOutput, getOutputLayerCount()).WillRepeatedly(Return(3u));
2604 EXPECT_CALL(mOutput, getOutputLayerOrderedByZByIndex(0u))
2605 .WillRepeatedly(Return(&mLayer1.outputLayer));
2606 EXPECT_CALL(mOutput, getOutputLayerOrderedByZByIndex(1u))
2607 .WillRepeatedly(Return(&mLayer2.outputLayer));
2608 EXPECT_CALL(mOutput, getOutputLayerOrderedByZByIndex(2u))
2609 .WillRepeatedly(Return(&mLayer3.outputLayer));
2610 }
2611
2612 StrictMock<OutputPartialMock> mOutput;
2613 mock::DisplayColorProfile* mDisplayColorProfile = new StrictMock<mock::DisplayColorProfile>();
2614 mock::RenderSurface* mRenderSurface = new StrictMock<mock::RenderSurface>();
2615
2616 Layer mLayer1;
2617 Layer mLayer2;
2618 Layer mLayer3;
2619};
2620
2621TEST_F(OutputPostFramebufferTest, ifNotEnabledDoesNothing) {
2622 mOutput.mState.isEnabled = false;
2623
2624 mOutput.postFramebuffer();
2625}
2626
2627TEST_F(OutputPostFramebufferTest, ifEnabledMustFlipThenPresentThenSendPresentCompleted) {
2628 mOutput.mState.isEnabled = true;
2629
2630 compositionengine::Output::FrameFences frameFences;
2631
2632 // This should happen even if there are no output layers.
2633 EXPECT_CALL(mOutput, getOutputLayerCount()).WillOnce(Return(0u));
2634
2635 // For this test in particular we want to make sure the call expectations
2636 // setup below are satisfied in the specific order.
2637 InSequence seq;
2638
2639 EXPECT_CALL(*mRenderSurface, flip());
2640 EXPECT_CALL(mOutput, presentAndGetFrameFences()).WillOnce(Return(frameFences));
2641 EXPECT_CALL(*mRenderSurface, onPresentDisplayCompleted());
2642
2643 mOutput.postFramebuffer();
2644}
2645
2646TEST_F(OutputPostFramebufferTest, releaseFencesAreSentToLayerFE) {
2647 // Simulate getting release fences from each layer, and ensure they are passed to the
2648 // front-end layer interface for each layer correctly.
2649
2650 mOutput.mState.isEnabled = true;
2651
2652 // Create three unique fence instances
2653 sp<Fence> layer1Fence = new Fence();
2654 sp<Fence> layer2Fence = new Fence();
2655 sp<Fence> layer3Fence = new Fence();
2656
Lloyd Piquefe0ee9e2019-11-22 16:30:30 -08002657 Output::FrameFences frameFences;
Lloyd Pique07178e32019-11-19 19:15:26 -08002658 frameFences.layerFences.emplace(&mLayer1.hwc2Layer, layer1Fence);
2659 frameFences.layerFences.emplace(&mLayer2.hwc2Layer, layer2Fence);
2660 frameFences.layerFences.emplace(&mLayer3.hwc2Layer, layer3Fence);
2661
2662 EXPECT_CALL(*mRenderSurface, flip());
2663 EXPECT_CALL(mOutput, presentAndGetFrameFences()).WillOnce(Return(frameFences));
2664 EXPECT_CALL(*mRenderSurface, onPresentDisplayCompleted());
2665
2666 // Compare the pointers values of each fence to make sure the correct ones
2667 // are passed. This happens to work with the current implementation, but
2668 // would not survive certain calls like Fence::merge() which would return a
2669 // new instance.
2670 EXPECT_CALL(mLayer1.layerFE,
2671 onLayerDisplayed(Property(&sp<Fence>::get, Eq(layer1Fence.get()))));
2672 EXPECT_CALL(mLayer2.layerFE,
2673 onLayerDisplayed(Property(&sp<Fence>::get, Eq(layer2Fence.get()))));
2674 EXPECT_CALL(mLayer3.layerFE,
2675 onLayerDisplayed(Property(&sp<Fence>::get, Eq(layer3Fence.get()))));
2676
2677 mOutput.postFramebuffer();
2678}
2679
2680TEST_F(OutputPostFramebufferTest, releaseFencesIncludeClientTargetAcquireFence) {
2681 mOutput.mState.isEnabled = true;
2682 mOutput.mState.usesClientComposition = true;
2683
2684 sp<Fence> clientTargetAcquireFence = new Fence();
2685 sp<Fence> layer1Fence = new Fence();
2686 sp<Fence> layer2Fence = new Fence();
2687 sp<Fence> layer3Fence = new Fence();
Lloyd Piquefe0ee9e2019-11-22 16:30:30 -08002688 Output::FrameFences frameFences;
Lloyd Pique07178e32019-11-19 19:15:26 -08002689 frameFences.clientTargetAcquireFence = clientTargetAcquireFence;
2690 frameFences.layerFences.emplace(&mLayer1.hwc2Layer, layer1Fence);
2691 frameFences.layerFences.emplace(&mLayer2.hwc2Layer, layer2Fence);
2692 frameFences.layerFences.emplace(&mLayer3.hwc2Layer, layer3Fence);
2693
2694 EXPECT_CALL(*mRenderSurface, flip());
2695 EXPECT_CALL(mOutput, presentAndGetFrameFences()).WillOnce(Return(frameFences));
2696 EXPECT_CALL(*mRenderSurface, onPresentDisplayCompleted());
2697
2698 // Fence::merge is called, and since none of the fences are actually valid,
2699 // Fence::NO_FENCE is returned and passed to each onLayerDisplayed() call.
2700 // This is the best we can do without creating a real kernel fence object.
2701 EXPECT_CALL(mLayer1.layerFE, onLayerDisplayed(Fence::NO_FENCE));
2702 EXPECT_CALL(mLayer2.layerFE, onLayerDisplayed(Fence::NO_FENCE));
2703 EXPECT_CALL(mLayer3.layerFE, onLayerDisplayed(Fence::NO_FENCE));
2704
2705 mOutput.postFramebuffer();
2706}
2707
2708TEST_F(OutputPostFramebufferTest, releasedLayersSentPresentFence) {
2709 mOutput.mState.isEnabled = true;
2710 mOutput.mState.usesClientComposition = true;
2711
2712 // This should happen even if there are no (current) output layers.
2713 EXPECT_CALL(mOutput, getOutputLayerCount()).WillOnce(Return(0u));
2714
2715 // Load up the released layers with some mock instances
2716 sp<StrictMock<mock::LayerFE>> releasedLayer1{new StrictMock<mock::LayerFE>()};
2717 sp<StrictMock<mock::LayerFE>> releasedLayer2{new StrictMock<mock::LayerFE>()};
2718 sp<StrictMock<mock::LayerFE>> releasedLayer3{new StrictMock<mock::LayerFE>()};
2719 Output::ReleasedLayers layers;
2720 layers.push_back(releasedLayer1);
2721 layers.push_back(releasedLayer2);
2722 layers.push_back(releasedLayer3);
2723 mOutput.setReleasedLayers(std::move(layers));
2724
2725 // Set up a fake present fence
2726 sp<Fence> presentFence = new Fence();
Lloyd Piquefe0ee9e2019-11-22 16:30:30 -08002727 Output::FrameFences frameFences;
Lloyd Pique07178e32019-11-19 19:15:26 -08002728 frameFences.presentFence = presentFence;
2729
2730 EXPECT_CALL(*mRenderSurface, flip());
2731 EXPECT_CALL(mOutput, presentAndGetFrameFences()).WillOnce(Return(frameFences));
2732 EXPECT_CALL(*mRenderSurface, onPresentDisplayCompleted());
2733
2734 // Each released layer should be given the presentFence.
2735 EXPECT_CALL(*releasedLayer1,
2736 onLayerDisplayed(Property(&sp<Fence>::get, Eq(presentFence.get()))));
2737 EXPECT_CALL(*releasedLayer2,
2738 onLayerDisplayed(Property(&sp<Fence>::get, Eq(presentFence.get()))));
2739 EXPECT_CALL(*releasedLayer3,
2740 onLayerDisplayed(Property(&sp<Fence>::get, Eq(presentFence.get()))));
2741
2742 mOutput.postFramebuffer();
2743
2744 // After the call the list of released layers should have been cleared.
2745 EXPECT_TRUE(mOutput.getReleasedLayersForTest().empty());
2746}
Lloyd Piquefaa3f192019-11-14 14:05:09 -08002747
2748/*
Lloyd Pique56eba802019-08-28 15:45:25 -07002749 * Output::composeSurfaces()
2750 */
2751
2752struct OutputComposeSurfacesTest : public testing::Test {
Lloyd Pique6818fa52019-12-03 12:32:13 -08002753 using TestType = OutputComposeSurfacesTest;
Lloyd Pique56eba802019-08-28 15:45:25 -07002754
Lloyd Piquefaa3f192019-11-14 14:05:09 -08002755 struct OutputPartialMock : public OutputPartialMockBase {
Lloyd Pique739afaf2019-11-21 16:40:05 -08002756 // Sets up the helper functions called by the function under test to use
2757 // mock implementations.
Lloyd Pique56eba802019-08-28 15:45:25 -07002758 MOCK_CONST_METHOD0(getSkipColorTransform, bool());
Vishnu Nair3a7346c2019-12-04 08:09:09 -08002759 MOCK_METHOD3(generateClientCompositionRequests,
2760 std::vector<renderengine::LayerSettings>(bool, Region&, ui::Dataspace));
Lloyd Pique56eba802019-08-28 15:45:25 -07002761 MOCK_METHOD2(appendRegionFlashRequests,
2762 void(const Region&, std::vector<renderengine::LayerSettings>&));
2763 MOCK_METHOD1(setExpensiveRenderingExpected, void(bool));
2764 };
2765
2766 OutputComposeSurfacesTest() {
2767 mOutput.setDisplayColorProfileForTest(
2768 std::unique_ptr<DisplayColorProfile>(mDisplayColorProfile));
2769 mOutput.setRenderSurfaceForTest(std::unique_ptr<RenderSurface>(mRenderSurface));
2770
Lloyd Pique6818fa52019-12-03 12:32:13 -08002771 mOutput.mState.frame = kDefaultOutputFrame;
2772 mOutput.mState.viewport = kDefaultOutputViewport;
2773 mOutput.mState.scissor = kDefaultOutputScissor;
2774 mOutput.mState.transform = ui::Transform{kDefaultOutputOrientation};
2775 mOutput.mState.orientation = kDefaultOutputOrientation;
2776 mOutput.mState.dataspace = kDefaultOutputDataspace;
2777 mOutput.mState.colorTransformMatrix = kDefaultColorTransformMat;
2778 mOutput.mState.isSecure = false;
2779 mOutput.mState.needsFiltering = false;
2780 mOutput.mState.usesClientComposition = true;
2781 mOutput.mState.usesDeviceComposition = false;
Lloyd Pique56eba802019-08-28 15:45:25 -07002782
Lloyd Piquea38ea7e2019-04-16 18:10:26 -07002783 EXPECT_CALL(mOutput, getCompositionEngine()).WillRepeatedly(ReturnRef(mCompositionEngine));
Lloyd Pique56eba802019-08-28 15:45:25 -07002784 EXPECT_CALL(mCompositionEngine, getRenderEngine()).WillRepeatedly(ReturnRef(mRenderEngine));
Alec Mourie4034bb2019-11-19 12:45:54 -08002785 EXPECT_CALL(mCompositionEngine, getTimeStats())
2786 .WillRepeatedly(ReturnRef(*mTimeStats.get()));
Lloyd Pique6818fa52019-12-03 12:32:13 -08002787 EXPECT_CALL(*mDisplayColorProfile, getHdrCapabilities())
2788 .WillRepeatedly(ReturnRef(kHdrCapabilities));
Lloyd Pique56eba802019-08-28 15:45:25 -07002789 }
2790
Lloyd Pique6818fa52019-12-03 12:32:13 -08002791 struct ExecuteState : public CallOrderStateMachineHelper<TestType, ExecuteState> {
2792 auto execute() {
2793 getInstance()->mReadyFence = getInstance()->mOutput.composeSurfaces(kDebugRegion);
2794 return nextState<FenceCheckState>();
2795 }
2796 };
2797
2798 struct FenceCheckState : public CallOrderStateMachineHelper<TestType, FenceCheckState> {
2799 void expectNoFenceWasReturned() { EXPECT_FALSE(getInstance()->mReadyFence); }
2800
2801 void expectAFenceWasReturned() { EXPECT_TRUE(getInstance()->mReadyFence); }
2802 };
2803
2804 // Call this member function to start using the mini-DSL defined above.
2805 [[nodiscard]] auto verify() { return ExecuteState::make(this); }
2806
2807 static constexpr uint32_t kDefaultOutputOrientation = TR_IDENT;
2808 static constexpr ui::Dataspace kDefaultOutputDataspace = ui::Dataspace::UNKNOWN;
2809 static constexpr ui::Dataspace kExpensiveOutputDataspace = ui::Dataspace::DISPLAY_P3;
2810 static constexpr float kDefaultMaxLuminance = 0.9f;
2811 static constexpr float kDefaultAvgLuminance = 0.7f;
2812 static constexpr float kDefaultMinLuminance = 0.1f;
2813
2814 static const Rect kDefaultOutputFrame;
2815 static const Rect kDefaultOutputViewport;
2816 static const Rect kDefaultOutputScissor;
2817 static const mat4 kDefaultColorTransformMat;
2818
2819 static const Region kDebugRegion;
2820 static const HdrCapabilities kHdrCapabilities;
2821
Lloyd Pique56eba802019-08-28 15:45:25 -07002822 StrictMock<mock::CompositionEngine> mCompositionEngine;
2823 StrictMock<renderengine::mock::RenderEngine> mRenderEngine;
Alec Mourie4034bb2019-11-19 12:45:54 -08002824 // TODO: make this is a proper mock.
2825 std::shared_ptr<TimeStats> mTimeStats = std::make_shared<android::impl::TimeStats>();
Lloyd Pique56eba802019-08-28 15:45:25 -07002826 mock::DisplayColorProfile* mDisplayColorProfile = new StrictMock<mock::DisplayColorProfile>();
2827 mock::RenderSurface* mRenderSurface = new StrictMock<mock::RenderSurface>();
Lloyd Piquea38ea7e2019-04-16 18:10:26 -07002828 StrictMock<OutputPartialMock> mOutput;
Lloyd Pique56eba802019-08-28 15:45:25 -07002829 sp<GraphicBuffer> mOutputBuffer = new GraphicBuffer();
Lloyd Pique6818fa52019-12-03 12:32:13 -08002830
2831 std::optional<base::unique_fd> mReadyFence;
Lloyd Pique56eba802019-08-28 15:45:25 -07002832};
2833
2834const Rect OutputComposeSurfacesTest::kDefaultOutputFrame{1001, 1002, 1003, 1004};
2835const Rect OutputComposeSurfacesTest::kDefaultOutputViewport{1005, 1006, 1007, 1008};
2836const Rect OutputComposeSurfacesTest::kDefaultOutputScissor{1009, 1010, 1011, 1012};
2837const mat4 OutputComposeSurfacesTest::kDefaultColorTransformMat{mat4() * 0.5};
Lloyd Pique6818fa52019-12-03 12:32:13 -08002838const Region OutputComposeSurfacesTest::kDebugRegion{Rect{100, 101, 102, 103}};
2839const HdrCapabilities OutputComposeSurfacesTest::
2840 kHdrCapabilities{{},
2841 OutputComposeSurfacesTest::kDefaultMaxLuminance,
2842 OutputComposeSurfacesTest::kDefaultAvgLuminance,
2843 OutputComposeSurfacesTest::kDefaultMinLuminance};
Lloyd Pique56eba802019-08-28 15:45:25 -07002844
Lloyd Piquea76ce462020-01-14 13:06:37 -08002845TEST_F(OutputComposeSurfacesTest, doesNothingButSignalNoExpensiveRenderingIfNoClientComposition) {
Lloyd Pique6818fa52019-12-03 12:32:13 -08002846 mOutput.mState.usesClientComposition = false;
Lloyd Pique56eba802019-08-28 15:45:25 -07002847
Lloyd Piquea76ce462020-01-14 13:06:37 -08002848 EXPECT_CALL(mOutput, setExpensiveRenderingExpected(false));
2849
Lloyd Pique6818fa52019-12-03 12:32:13 -08002850 verify().execute().expectAFenceWasReturned();
Lloyd Pique56eba802019-08-28 15:45:25 -07002851}
2852
Lloyd Pique6818fa52019-12-03 12:32:13 -08002853TEST_F(OutputComposeSurfacesTest, doesMinimalWorkIfDequeueBufferFails) {
2854 EXPECT_CALL(mOutput, getSkipColorTransform()).WillRepeatedly(Return(false));
2855 EXPECT_CALL(*mDisplayColorProfile, hasWideColorGamut()).WillRepeatedly(Return(true));
2856 EXPECT_CALL(mRenderEngine, supportsProtectedContent()).WillRepeatedly(Return(false));
2857 EXPECT_CALL(mOutput, generateClientCompositionRequests(_, _, kDefaultOutputDataspace))
2858 .WillRepeatedly(Return(std::vector<renderengine::LayerSettings>{}));
2859 EXPECT_CALL(mOutput, appendRegionFlashRequests(RegionEq(kDebugRegion), _))
2860 .WillRepeatedly(Return());
Lloyd Pique56eba802019-08-28 15:45:25 -07002861
Lloyd Pique6818fa52019-12-03 12:32:13 -08002862 EXPECT_CALL(*mRenderSurface, dequeueBuffer(_)).WillOnce(Return(nullptr));
Lloyd Pique56eba802019-08-28 15:45:25 -07002863
Lloyd Pique6818fa52019-12-03 12:32:13 -08002864 verify().execute().expectNoFenceWasReturned();
2865}
Lloyd Pique56eba802019-08-28 15:45:25 -07002866
Lloyd Pique6818fa52019-12-03 12:32:13 -08002867TEST_F(OutputComposeSurfacesTest, handlesZeroCompositionRequests) {
2868 EXPECT_CALL(mOutput, getSkipColorTransform()).WillRepeatedly(Return(false));
2869 EXPECT_CALL(*mDisplayColorProfile, hasWideColorGamut()).WillRepeatedly(Return(true));
2870 EXPECT_CALL(mRenderEngine, supportsProtectedContent()).WillRepeatedly(Return(false));
2871 EXPECT_CALL(mOutput, generateClientCompositionRequests(_, _, kDefaultOutputDataspace))
2872 .WillRepeatedly(Return(std::vector<renderengine::LayerSettings>{}));
2873 EXPECT_CALL(mOutput, appendRegionFlashRequests(RegionEq(kDebugRegion), _))
2874 .WillRepeatedly(Return());
Lloyd Pique56eba802019-08-28 15:45:25 -07002875
Lloyd Pique6818fa52019-12-03 12:32:13 -08002876 EXPECT_CALL(*mRenderSurface, dequeueBuffer(_)).WillRepeatedly(Return(mOutputBuffer));
2877 EXPECT_CALL(mRenderEngine, drawLayers(_, IsEmpty(), _, true, _, _))
2878 .WillRepeatedly(Return(NO_ERROR));
Lloyd Pique56eba802019-08-28 15:45:25 -07002879
Lloyd Pique6818fa52019-12-03 12:32:13 -08002880 verify().execute().expectAFenceWasReturned();
2881}
Lloyd Pique56eba802019-08-28 15:45:25 -07002882
Lloyd Pique6818fa52019-12-03 12:32:13 -08002883TEST_F(OutputComposeSurfacesTest, buildsAndRendersRequestList) {
2884 renderengine::LayerSettings r1;
2885 renderengine::LayerSettings r2;
2886
2887 r1.geometry.boundaries = FloatRect{1, 2, 3, 4};
2888 r2.geometry.boundaries = FloatRect{5, 6, 7, 8};
2889
2890 EXPECT_CALL(mOutput, getSkipColorTransform()).WillRepeatedly(Return(false));
2891 EXPECT_CALL(*mDisplayColorProfile, hasWideColorGamut()).WillRepeatedly(Return(true));
2892 EXPECT_CALL(mRenderEngine, supportsProtectedContent()).WillRepeatedly(Return(false));
2893 EXPECT_CALL(mOutput, generateClientCompositionRequests(_, _, kDefaultOutputDataspace))
2894 .WillRepeatedly(Return(std::vector<renderengine::LayerSettings>{r1}));
2895 EXPECT_CALL(mOutput, appendRegionFlashRequests(RegionEq(kDebugRegion), _))
2896 .WillRepeatedly(
2897 Invoke([&](const Region&,
2898 std::vector<renderengine::LayerSettings>& clientCompositionLayers) {
2899 clientCompositionLayers.emplace_back(r2);
2900 }));
2901
2902 EXPECT_CALL(*mRenderSurface, dequeueBuffer(_)).WillRepeatedly(Return(mOutputBuffer));
2903 EXPECT_CALL(mRenderEngine, drawLayers(_, ElementsAreArray({r1, r2}), _, true, _, _))
2904 .WillRepeatedly(Return(NO_ERROR));
2905
2906 verify().execute().expectAFenceWasReturned();
2907}
2908
2909struct OutputComposeSurfacesTest_UsesExpectedDisplaySettings : public OutputComposeSurfacesTest {
2910 OutputComposeSurfacesTest_UsesExpectedDisplaySettings() {
2911 EXPECT_CALL(mRenderEngine, supportsProtectedContent()).WillRepeatedly(Return(false));
2912 EXPECT_CALL(mOutput, generateClientCompositionRequests(_, _, kDefaultOutputDataspace))
2913 .WillRepeatedly(Return(std::vector<renderengine::LayerSettings>{}));
2914 EXPECT_CALL(mOutput, appendRegionFlashRequests(RegionEq(kDebugRegion), _))
2915 .WillRepeatedly(Return());
2916 EXPECT_CALL(*mRenderSurface, dequeueBuffer(_)).WillRepeatedly(Return(mOutputBuffer));
2917 }
2918
2919 struct MixedCompositionState
2920 : public CallOrderStateMachineHelper<TestType, MixedCompositionState> {
2921 auto ifMixedCompositionIs(bool used) {
2922 getInstance()->mOutput.mState.usesDeviceComposition = used;
2923 return nextState<OutputUsesHdrState>();
2924 }
2925 };
2926
2927 struct OutputUsesHdrState : public CallOrderStateMachineHelper<TestType, OutputUsesHdrState> {
2928 auto andIfUsesHdr(bool used) {
2929 EXPECT_CALL(*getInstance()->mDisplayColorProfile, hasWideColorGamut())
2930 .WillOnce(Return(used));
2931 return nextState<SkipColorTransformState>();
2932 }
2933 };
2934
2935 struct SkipColorTransformState
2936 : public CallOrderStateMachineHelper<TestType, SkipColorTransformState> {
2937 auto andIfSkipColorTransform(bool skip) {
2938 // May be called zero or one times.
2939 EXPECT_CALL(getInstance()->mOutput, getSkipColorTransform())
2940 .WillRepeatedly(Return(skip));
2941 return nextState<ExpectDisplaySettingsState>();
2942 }
2943 };
2944
2945 struct ExpectDisplaySettingsState
2946 : public CallOrderStateMachineHelper<TestType, ExpectDisplaySettingsState> {
2947 auto thenExpectDisplaySettingsUsed(renderengine::DisplaySettings settings) {
2948 EXPECT_CALL(getInstance()->mRenderEngine, drawLayers(settings, _, _, true, _, _))
2949 .WillOnce(Return(NO_ERROR));
2950 return nextState<ExecuteState>();
2951 }
2952 };
2953
2954 // Call this member function to start using the mini-DSL defined above.
2955 [[nodiscard]] auto verify() { return MixedCompositionState::make(this); }
2956};
2957
2958TEST_F(OutputComposeSurfacesTest_UsesExpectedDisplaySettings, forHdrMixedComposition) {
2959 verify().ifMixedCompositionIs(true)
2960 .andIfUsesHdr(true)
2961 .andIfSkipColorTransform(false)
2962 .thenExpectDisplaySettingsUsed({kDefaultOutputScissor, kDefaultOutputScissor, mat4(),
2963 kDefaultMaxLuminance, kDefaultOutputDataspace, mat4(),
2964 Region::INVALID_REGION, kDefaultOutputOrientation})
2965 .execute()
2966 .expectAFenceWasReturned();
2967}
2968
2969TEST_F(OutputComposeSurfacesTest_UsesExpectedDisplaySettings, forNonHdrMixedComposition) {
2970 verify().ifMixedCompositionIs(true)
2971 .andIfUsesHdr(false)
2972 .andIfSkipColorTransform(false)
2973 .thenExpectDisplaySettingsUsed({kDefaultOutputScissor, kDefaultOutputScissor, mat4(),
2974 kDefaultMaxLuminance, kDefaultOutputDataspace, mat4(),
2975 Region::INVALID_REGION, kDefaultOutputOrientation})
2976 .execute()
2977 .expectAFenceWasReturned();
2978}
2979
2980TEST_F(OutputComposeSurfacesTest_UsesExpectedDisplaySettings, forHdrOnlyClientComposition) {
2981 verify().ifMixedCompositionIs(false)
2982 .andIfUsesHdr(true)
2983 .andIfSkipColorTransform(false)
2984 .thenExpectDisplaySettingsUsed({kDefaultOutputScissor, kDefaultOutputScissor, mat4(),
2985 kDefaultMaxLuminance, kDefaultOutputDataspace,
2986 kDefaultColorTransformMat, Region::INVALID_REGION,
2987 kDefaultOutputOrientation})
2988 .execute()
2989 .expectAFenceWasReturned();
2990}
2991
2992TEST_F(OutputComposeSurfacesTest_UsesExpectedDisplaySettings, forNonHdrOnlyClientComposition) {
2993 verify().ifMixedCompositionIs(false)
2994 .andIfUsesHdr(false)
2995 .andIfSkipColorTransform(false)
2996 .thenExpectDisplaySettingsUsed({kDefaultOutputScissor, kDefaultOutputScissor, mat4(),
2997 kDefaultMaxLuminance, kDefaultOutputDataspace,
2998 kDefaultColorTransformMat, Region::INVALID_REGION,
2999 kDefaultOutputOrientation})
3000 .execute()
3001 .expectAFenceWasReturned();
3002}
3003
3004TEST_F(OutputComposeSurfacesTest_UsesExpectedDisplaySettings,
3005 usesExpectedDisplaySettingsForHdrOnlyClientCompositionWithSkipClientTransform) {
3006 verify().ifMixedCompositionIs(false)
3007 .andIfUsesHdr(true)
3008 .andIfSkipColorTransform(true)
3009 .thenExpectDisplaySettingsUsed({kDefaultOutputScissor, kDefaultOutputScissor, mat4(),
3010 kDefaultMaxLuminance, kDefaultOutputDataspace, mat4(),
3011 Region::INVALID_REGION, kDefaultOutputOrientation})
3012 .execute()
3013 .expectAFenceWasReturned();
3014}
3015
3016struct OutputComposeSurfacesTest_HandlesProtectedContent : public OutputComposeSurfacesTest {
3017 struct Layer {
3018 Layer() {
3019 EXPECT_CALL(mOutputLayer, getLayer()).WillRepeatedly(ReturnRef(mLayer));
3020 EXPECT_CALL(mLayer, getFEState()).WillRepeatedly(ReturnRef(mLayerFEState));
3021 }
3022
3023 StrictMock<mock::OutputLayer> mOutputLayer;
3024 StrictMock<mock::Layer> mLayer;
3025 LayerFECompositionState mLayerFEState;
3026 };
3027
3028 OutputComposeSurfacesTest_HandlesProtectedContent() {
3029 mLayer1.mLayerFEState.hasProtectedContent = false;
3030 mLayer2.mLayerFEState.hasProtectedContent = false;
3031
3032 EXPECT_CALL(mOutput, getOutputLayerCount()).WillRepeatedly(Return(2u));
3033 EXPECT_CALL(mOutput, getOutputLayerOrderedByZByIndex(0u))
3034 .WillRepeatedly(Return(&mLayer1.mOutputLayer));
3035 EXPECT_CALL(mOutput, getOutputLayerOrderedByZByIndex(1u))
3036 .WillRepeatedly(Return(&mLayer2.mOutputLayer));
3037
3038 EXPECT_CALL(mOutput, getSkipColorTransform()).WillRepeatedly(Return(false));
3039
3040 EXPECT_CALL(*mDisplayColorProfile, hasWideColorGamut()).WillRepeatedly(Return(true));
3041
3042 EXPECT_CALL(mOutput, generateClientCompositionRequests(_, _, _))
3043 .WillRepeatedly(Return(std::vector<renderengine::LayerSettings>{}));
3044 EXPECT_CALL(mOutput, appendRegionFlashRequests(RegionEq(kDebugRegion), _))
3045 .WillRepeatedly(Return());
3046 EXPECT_CALL(*mRenderSurface, dequeueBuffer(_)).WillRepeatedly(Return(mOutputBuffer));
3047 EXPECT_CALL(mRenderEngine, drawLayers(_, _, _, true, _, _))
3048 .WillRepeatedly(Return(NO_ERROR));
3049 }
3050
3051 Layer mLayer1;
3052 Layer mLayer2;
3053};
3054
3055TEST_F(OutputComposeSurfacesTest_HandlesProtectedContent, ifDisplayIsNotSecure) {
3056 mOutput.mState.isSecure = false;
3057 mLayer2.mLayerFEState.hasProtectedContent = true;
3058 EXPECT_CALL(mRenderEngine, supportsProtectedContent()).WillRepeatedly(Return(true));
3059
3060 mOutput.composeSurfaces(kDebugRegion);
3061}
3062
3063TEST_F(OutputComposeSurfacesTest_HandlesProtectedContent, ifRenderEngineDoesNotSupportIt) {
3064 mOutput.mState.isSecure = true;
3065 mLayer2.mLayerFEState.hasProtectedContent = true;
3066 EXPECT_CALL(mRenderEngine, supportsProtectedContent()).WillRepeatedly(Return(false));
3067
3068 mOutput.composeSurfaces(kDebugRegion);
3069}
3070
3071TEST_F(OutputComposeSurfacesTest_HandlesProtectedContent, ifNoProtectedContentLayers) {
3072 mOutput.mState.isSecure = true;
3073 mLayer2.mLayerFEState.hasProtectedContent = false;
3074 EXPECT_CALL(mRenderEngine, supportsProtectedContent()).WillRepeatedly(Return(true));
3075 EXPECT_CALL(mRenderEngine, isProtected).WillOnce(Return(true)).WillOnce(Return(false));
3076 EXPECT_CALL(*mRenderSurface, isProtected).WillOnce(Return(true));
3077 EXPECT_CALL(mRenderEngine, useProtectedContext(false));
3078 EXPECT_CALL(*mRenderSurface, setProtected(false));
3079
3080 mOutput.composeSurfaces(kDebugRegion);
3081}
3082
3083TEST_F(OutputComposeSurfacesTest_HandlesProtectedContent, ifNotEnabled) {
3084 mOutput.mState.isSecure = true;
3085 mLayer2.mLayerFEState.hasProtectedContent = true;
3086 EXPECT_CALL(mRenderEngine, supportsProtectedContent()).WillRepeatedly(Return(true));
3087
3088 // For this test, we also check the call order of key functions.
3089 InSequence seq;
3090
3091 EXPECT_CALL(mRenderEngine, isProtected).WillOnce(Return(false));
3092 EXPECT_CALL(mRenderEngine, useProtectedContext(true));
3093 EXPECT_CALL(*mRenderSurface, isProtected).WillOnce(Return(false));
3094 EXPECT_CALL(mRenderEngine, isProtected).WillOnce(Return(true));
3095 EXPECT_CALL(*mRenderSurface, setProtected(true));
3096 // Must happen after setting the protected content state.
3097 EXPECT_CALL(*mRenderSurface, dequeueBuffer(_)).WillRepeatedly(Return(mOutputBuffer));
3098 EXPECT_CALL(mRenderEngine, drawLayers(_, _, _, true, _, _)).WillOnce(Return(NO_ERROR));
3099
3100 mOutput.composeSurfaces(kDebugRegion);
3101}
3102
3103TEST_F(OutputComposeSurfacesTest_HandlesProtectedContent, ifAlreadyEnabledEverywhere) {
3104 mOutput.mState.isSecure = true;
3105 mLayer2.mLayerFEState.hasProtectedContent = true;
3106 EXPECT_CALL(mRenderEngine, supportsProtectedContent()).WillRepeatedly(Return(true));
3107 EXPECT_CALL(mRenderEngine, isProtected).WillOnce(Return(true));
3108 EXPECT_CALL(*mRenderSurface, isProtected).WillOnce(Return(true));
3109
3110 mOutput.composeSurfaces(kDebugRegion);
3111}
3112
3113TEST_F(OutputComposeSurfacesTest_HandlesProtectedContent, ifFailsToEnableInRenderEngine) {
3114 mOutput.mState.isSecure = true;
3115 mLayer2.mLayerFEState.hasProtectedContent = true;
3116 EXPECT_CALL(mRenderEngine, supportsProtectedContent()).WillRepeatedly(Return(true));
3117 EXPECT_CALL(mRenderEngine, isProtected).WillOnce(Return(false)).WillOnce(Return(false));
3118 EXPECT_CALL(*mRenderSurface, isProtected).WillOnce(Return(false));
3119 EXPECT_CALL(mRenderEngine, useProtectedContext(true));
3120
3121 mOutput.composeSurfaces(kDebugRegion);
3122}
3123
3124TEST_F(OutputComposeSurfacesTest_HandlesProtectedContent, ifAlreadyEnabledInRenderEngine) {
3125 mOutput.mState.isSecure = true;
3126 mLayer2.mLayerFEState.hasProtectedContent = true;
3127 EXPECT_CALL(mRenderEngine, supportsProtectedContent()).WillRepeatedly(Return(true));
3128 EXPECT_CALL(mRenderEngine, isProtected).WillOnce(Return(true)).WillOnce(Return(true));
3129 EXPECT_CALL(*mRenderSurface, isProtected).WillOnce(Return(false));
3130 EXPECT_CALL(*mRenderSurface, setProtected(true));
3131
3132 mOutput.composeSurfaces(kDebugRegion);
3133}
3134
3135TEST_F(OutputComposeSurfacesTest_HandlesProtectedContent, ifAlreadyEnabledInRenderSurface) {
3136 mOutput.mState.isSecure = true;
3137 mLayer2.mLayerFEState.hasProtectedContent = true;
3138 EXPECT_CALL(mRenderEngine, supportsProtectedContent()).WillRepeatedly(Return(true));
3139 EXPECT_CALL(mRenderEngine, isProtected).WillOnce(Return(false));
3140 EXPECT_CALL(*mRenderSurface, isProtected).WillOnce(Return(true));
3141 EXPECT_CALL(mRenderEngine, useProtectedContext(true));
3142
3143 mOutput.composeSurfaces(kDebugRegion);
3144}
3145
3146struct OutputComposeSurfacesTest_SetsExpensiveRendering : public OutputComposeSurfacesTest {
3147 OutputComposeSurfacesTest_SetsExpensiveRendering() {
3148 EXPECT_CALL(mOutput, getSkipColorTransform()).WillRepeatedly(Return(false));
3149 EXPECT_CALL(*mDisplayColorProfile, hasWideColorGamut()).WillRepeatedly(Return(true));
3150 EXPECT_CALL(mRenderEngine, supportsProtectedContent()).WillRepeatedly(Return(false));
3151 EXPECT_CALL(mOutput, appendRegionFlashRequests(RegionEq(kDebugRegion), _))
3152 .WillRepeatedly(Return());
3153 EXPECT_CALL(*mRenderSurface, dequeueBuffer(_)).WillRepeatedly(Return(mOutputBuffer));
3154 }
3155};
3156
3157TEST_F(OutputComposeSurfacesTest_SetsExpensiveRendering, IfExepensiveOutputDataspaceIsUsed) {
3158 mOutput.mState.dataspace = kExpensiveOutputDataspace;
3159
3160 EXPECT_CALL(mOutput, generateClientCompositionRequests(_, _, kExpensiveOutputDataspace))
3161 .WillOnce(Return(std::vector<renderengine::LayerSettings>{}));
3162
3163 // For this test, we also check the call order of key functions.
3164 InSequence seq;
3165
3166 EXPECT_CALL(mOutput, setExpensiveRenderingExpected(true));
3167 EXPECT_CALL(mRenderEngine, drawLayers(_, _, _, true, _, _)).WillOnce(Return(NO_ERROR));
Lloyd Pique6818fa52019-12-03 12:32:13 -08003168
3169 mOutput.composeSurfaces(kDebugRegion);
Lloyd Pique56eba802019-08-28 15:45:25 -07003170}
3171
3172/*
3173 * Output::generateClientCompositionRequests()
3174 */
3175
3176struct GenerateClientCompositionRequestsTest : public testing::Test {
Lloyd Piquefaa3f192019-11-14 14:05:09 -08003177 struct OutputPartialMock : public OutputPartialMockBase {
Lloyd Piquea38ea7e2019-04-16 18:10:26 -07003178 // compositionengine::Output overrides
Lloyd Pique56eba802019-08-28 15:45:25 -07003179 std::vector<renderengine::LayerSettings> generateClientCompositionRequests(
Vishnu Nair3a7346c2019-12-04 08:09:09 -08003180 bool supportsProtectedContent, Region& clearRegion,
3181 ui::Dataspace dataspace) override {
Lloyd Pique56eba802019-08-28 15:45:25 -07003182 return impl::Output::generateClientCompositionRequests(supportsProtectedContent,
Vishnu Nair3a7346c2019-12-04 08:09:09 -08003183 clearRegion, dataspace);
Lloyd Pique56eba802019-08-28 15:45:25 -07003184 }
3185 };
3186
Lloyd Piquea4863342019-12-04 18:45:02 -08003187 struct Layer {
3188 Layer() {
3189 EXPECT_CALL(mOutputLayer, getState()).WillRepeatedly(ReturnRef(mOutputLayerState));
3190 EXPECT_CALL(mOutputLayer, editState()).WillRepeatedly(ReturnRef(mOutputLayerState));
3191 EXPECT_CALL(mOutputLayer, getLayer()).WillRepeatedly(ReturnRef(mLayer));
3192 EXPECT_CALL(mOutputLayer, getLayerFE()).WillRepeatedly(ReturnRef(mLayerFE));
3193 EXPECT_CALL(mLayer, getFEState()).WillRepeatedly(ReturnRef(mLayerFEState));
3194 }
3195
3196 StrictMock<mock::OutputLayer> mOutputLayer;
3197 StrictMock<mock::Layer> mLayer;
3198 StrictMock<mock::LayerFE> mLayerFE;
3199 LayerFECompositionState mLayerFEState;
3200 impl::OutputLayerCompositionState mOutputLayerState;
3201 renderengine::LayerSettings mRELayerSettings;
3202 };
3203
Lloyd Pique56eba802019-08-28 15:45:25 -07003204 GenerateClientCompositionRequestsTest() {
Lloyd Piquea4863342019-12-04 18:45:02 -08003205 mOutput.mState.needsFiltering = false;
3206
Lloyd Pique56eba802019-08-28 15:45:25 -07003207 mOutput.setDisplayColorProfileForTest(
3208 std::unique_ptr<DisplayColorProfile>(mDisplayColorProfile));
3209 mOutput.setRenderSurfaceForTest(std::unique_ptr<RenderSurface>(mRenderSurface));
3210 }
3211
Lloyd Pique56eba802019-08-28 15:45:25 -07003212 mock::DisplayColorProfile* mDisplayColorProfile = new StrictMock<mock::DisplayColorProfile>();
3213 mock::RenderSurface* mRenderSurface = new StrictMock<mock::RenderSurface>();
Lloyd Piquea38ea7e2019-04-16 18:10:26 -07003214 StrictMock<OutputPartialMock> mOutput;
Lloyd Pique56eba802019-08-28 15:45:25 -07003215};
3216
Lloyd Piquea4863342019-12-04 18:45:02 -08003217struct GenerateClientCompositionRequestsTest_ThreeLayers
3218 : public GenerateClientCompositionRequestsTest {
3219 GenerateClientCompositionRequestsTest_ThreeLayers() {
3220 mOutput.mState.frame = kDisplayFrame;
3221 mOutput.mState.viewport = kDisplayViewport;
3222 mOutput.mState.scissor = kDisplayScissor;
3223 mOutput.mState.transform = ui::Transform{kDisplayOrientation};
3224 mOutput.mState.orientation = kDisplayOrientation;
3225 mOutput.mState.needsFiltering = false;
3226 mOutput.mState.isSecure = false;
Lloyd Pique56eba802019-08-28 15:45:25 -07003227
Lloyd Piquea4863342019-12-04 18:45:02 -08003228 for (size_t i = 0; i < mLayers.size(); i++) {
3229 mLayers[i].mOutputLayerState.clearClientTarget = false;
3230 mLayers[i].mOutputLayerState.visibleRegion = Region(kDisplayFrame);
3231 mLayers[i].mLayerFEState.isOpaque = true;
3232 mLayers[i].mRELayerSettings.geometry.boundaries =
3233 FloatRect{static_cast<float>(i + 1), 0.f, 0.f, 0.f};
3234 mLayers[i].mRELayerSettings.source.solidColor = {1.0f, 1.0f, 1.0f};
3235 mLayers[i].mRELayerSettings.alpha = 1.0f;
3236 mLayers[i].mRELayerSettings.disableBlending = false;
Lloyd Pique56eba802019-08-28 15:45:25 -07003237
Lloyd Piquea4863342019-12-04 18:45:02 -08003238 EXPECT_CALL(mOutput, getOutputLayerOrderedByZByIndex(i))
3239 .WillRepeatedly(Return(&mLayers[i].mOutputLayer));
3240 EXPECT_CALL(mLayers[i].mOutputLayer, requiresClientComposition())
3241 .WillRepeatedly(Return(true));
3242 EXPECT_CALL(mLayers[i].mOutputLayer, needsFiltering()).WillRepeatedly(Return(false));
3243 }
Lloyd Pique56eba802019-08-28 15:45:25 -07003244
Lloyd Piquea4863342019-12-04 18:45:02 -08003245 EXPECT_CALL(mOutput, getOutputLayerCount()).WillRepeatedly(Return(mLayers.size()));
3246 }
Lloyd Pique56eba802019-08-28 15:45:25 -07003247
Lloyd Piquea4863342019-12-04 18:45:02 -08003248 static constexpr uint32_t kDisplayOrientation = TR_IDENT;
3249 static constexpr ui::Dataspace kDisplayDataspace = ui::Dataspace::UNKNOWN;
Lloyd Pique56eba802019-08-28 15:45:25 -07003250
Lloyd Piquea4863342019-12-04 18:45:02 -08003251 static const Rect kDisplayFrame;
3252 static const Rect kDisplayViewport;
3253 static const Rect kDisplayScissor;
Lloyd Pique56eba802019-08-28 15:45:25 -07003254
Lloyd Piquea4863342019-12-04 18:45:02 -08003255 std::array<Layer, 3> mLayers;
3256};
Lloyd Pique56eba802019-08-28 15:45:25 -07003257
Lloyd Piquea4863342019-12-04 18:45:02 -08003258const Rect GenerateClientCompositionRequestsTest_ThreeLayers::kDisplayFrame(0, 0, 100, 200);
3259const Rect GenerateClientCompositionRequestsTest_ThreeLayers::kDisplayViewport(0, 0, 101, 201);
3260const Rect GenerateClientCompositionRequestsTest_ThreeLayers::kDisplayScissor(0, 0, 102, 202);
Lloyd Pique56eba802019-08-28 15:45:25 -07003261
Lloyd Piquea4863342019-12-04 18:45:02 -08003262TEST_F(GenerateClientCompositionRequestsTest_ThreeLayers, handlesNoClientCompostionLayers) {
3263 EXPECT_CALL(mLayers[0].mOutputLayer, requiresClientComposition()).WillOnce(Return(false));
3264 EXPECT_CALL(mLayers[1].mOutputLayer, requiresClientComposition()).WillOnce(Return(false));
3265 EXPECT_CALL(mLayers[2].mOutputLayer, requiresClientComposition()).WillOnce(Return(false));
Lloyd Pique56eba802019-08-28 15:45:25 -07003266
Lloyd Piquea4863342019-12-04 18:45:02 -08003267 Region accumClearRegion(Rect(10, 11, 12, 13));
3268 auto requests = mOutput.generateClientCompositionRequests(false /* supportsProtectedContent */,
3269 accumClearRegion, kDisplayDataspace);
Lloyd Pique56eba802019-08-28 15:45:25 -07003270 EXPECT_EQ(0u, requests.size());
Lloyd Piquea4863342019-12-04 18:45:02 -08003271 EXPECT_THAT(accumClearRegion, RegionEq(Region(Rect(10, 11, 12, 13))));
Lloyd Pique56eba802019-08-28 15:45:25 -07003272}
3273
Lloyd Piquea4863342019-12-04 18:45:02 -08003274TEST_F(GenerateClientCompositionRequestsTest_ThreeLayers, requiresVisibleRegionAfterViewportClip) {
3275 mLayers[0].mOutputLayerState.visibleRegion = Region(Rect(10, 10, 10, 10));
3276 mLayers[1].mOutputLayerState.visibleRegion = Region(Rect(4000, 0, 4010, 10));
3277 mLayers[2].mOutputLayerState.visibleRegion = Region(Rect(-10, -10, 0, 0));
3278
3279 Region accumClearRegion(Rect(10, 11, 12, 13));
3280 auto requests = mOutput.generateClientCompositionRequests(false /* supportsProtectedContent */,
3281 accumClearRegion, kDisplayDataspace);
3282 EXPECT_EQ(0u, requests.size());
3283 EXPECT_THAT(accumClearRegion, RegionEq(Region(Rect(10, 11, 12, 13))));
3284}
3285
3286TEST_F(GenerateClientCompositionRequestsTest_ThreeLayers, gathersClientCompositionRequests) {
3287 renderengine::LayerSettings mREShadowSettings;
3288 mREShadowSettings.source.solidColor = {0.1f, 0.1f, 0.1f};
3289
3290 EXPECT_CALL(mLayers[0].mLayerFE, prepareClientComposition(_)).WillOnce(Return(std::nullopt));
3291 EXPECT_CALL(mLayers[1].mLayerFE, prepareClientComposition(_))
3292 .WillOnce(Return(mLayers[1].mRELayerSettings));
3293 EXPECT_CALL(mLayers[1].mLayerFE,
3294 prepareShadowClientComposition(mLayers[1].mRELayerSettings, kDisplayViewport,
3295 kDisplayDataspace))
3296 .WillOnce(Return(std::nullopt));
3297 EXPECT_CALL(mLayers[2].mLayerFE, prepareClientComposition(_))
3298 .WillOnce(Return(mLayers[2].mRELayerSettings));
3299 EXPECT_CALL(mLayers[2].mLayerFE,
3300 prepareShadowClientComposition(mLayers[2].mRELayerSettings, kDisplayViewport,
3301 kDisplayDataspace))
3302 .WillOnce(Return(mREShadowSettings));
3303
3304 Region accumClearRegion(Rect(10, 11, 12, 13));
3305 auto requests = mOutput.generateClientCompositionRequests(false /* supportsProtectedContent */,
3306 accumClearRegion, kDisplayDataspace);
3307 ASSERT_EQ(3u, requests.size());
3308 EXPECT_EQ(mLayers[1].mRELayerSettings, requests[0]);
3309 EXPECT_EQ(mREShadowSettings, requests[1]);
3310 EXPECT_EQ(mLayers[2].mRELayerSettings, requests[2]);
3311
3312 EXPECT_THAT(accumClearRegion, RegionEq(Region(Rect(10, 11, 12, 13))));
3313
3314 // Check that a timestamp was set for the layers that generated requests
3315 EXPECT_TRUE(0 == mLayers[0].mOutputLayerState.clientCompositionTimestamp);
3316 EXPECT_TRUE(0 != mLayers[1].mOutputLayerState.clientCompositionTimestamp);
3317 EXPECT_TRUE(0 != mLayers[2].mOutputLayerState.clientCompositionTimestamp);
3318}
3319
3320TEST_F(GenerateClientCompositionRequestsTest_ThreeLayers,
3321 onlyClientComposesClientComposedLayersIfNoClearingNeeded) {
3322 EXPECT_CALL(mLayers[0].mOutputLayer, requiresClientComposition()).WillOnce(Return(false));
3323 EXPECT_CALL(mLayers[1].mOutputLayer, requiresClientComposition()).WillOnce(Return(false));
3324 EXPECT_CALL(mLayers[2].mOutputLayer, requiresClientComposition()).WillOnce(Return(true));
3325
3326 mLayers[0].mOutputLayerState.clearClientTarget = false;
3327 mLayers[1].mOutputLayerState.clearClientTarget = false;
3328 mLayers[2].mOutputLayerState.clearClientTarget = false;
3329
3330 mLayers[0].mLayerFEState.isOpaque = true;
3331 mLayers[1].mLayerFEState.isOpaque = true;
3332 mLayers[2].mLayerFEState.isOpaque = true;
3333
3334 EXPECT_CALL(mLayers[2].mLayerFE, prepareClientComposition(_))
3335 .WillOnce(Return(mLayers[2].mRELayerSettings));
3336 EXPECT_CALL(mLayers[2].mLayerFE, prepareShadowClientComposition(_, _, _))
3337 .WillOnce(Return(std::nullopt));
3338
3339 Region accumClearRegion(Rect(10, 11, 12, 13));
3340 auto requests = mOutput.generateClientCompositionRequests(false /* supportsProtectedContent */,
3341 accumClearRegion, kDisplayDataspace);
3342 ASSERT_EQ(1u, requests.size());
3343 EXPECT_EQ(mLayers[2].mRELayerSettings, requests[0]);
3344
3345 EXPECT_THAT(accumClearRegion, RegionEq(Region(Rect(10, 11, 12, 13))));
3346}
3347
3348TEST_F(GenerateClientCompositionRequestsTest_ThreeLayers,
3349 onlyClientComposesClientComposedLayersIfOthersAreNotOpaque) {
3350 EXPECT_CALL(mLayers[0].mOutputLayer, requiresClientComposition()).WillOnce(Return(false));
3351 EXPECT_CALL(mLayers[1].mOutputLayer, requiresClientComposition()).WillOnce(Return(false));
3352 EXPECT_CALL(mLayers[2].mOutputLayer, requiresClientComposition()).WillOnce(Return(true));
3353
3354 mLayers[0].mOutputLayerState.clearClientTarget = true;
3355 mLayers[1].mOutputLayerState.clearClientTarget = true;
3356 mLayers[2].mOutputLayerState.clearClientTarget = true;
3357
3358 mLayers[0].mLayerFEState.isOpaque = false;
3359 mLayers[1].mLayerFEState.isOpaque = false;
3360 mLayers[2].mLayerFEState.isOpaque = false;
3361
3362 EXPECT_CALL(mLayers[2].mLayerFE, prepareClientComposition(_))
3363 .WillOnce(Return(mLayers[2].mRELayerSettings));
3364 EXPECT_CALL(mLayers[2].mLayerFE, prepareShadowClientComposition(_, _, _))
3365 .WillOnce(Return(std::nullopt));
3366
3367 Region accumClearRegion(Rect(10, 11, 12, 13));
3368 auto requests = mOutput.generateClientCompositionRequests(false /* supportsProtectedContent */,
3369 accumClearRegion, kDisplayDataspace);
3370 ASSERT_EQ(1u, requests.size());
3371 EXPECT_EQ(mLayers[2].mRELayerSettings, requests[0]);
3372
3373 EXPECT_THAT(accumClearRegion, RegionEq(Region(Rect(10, 11, 12, 13))));
3374}
3375
3376TEST_F(GenerateClientCompositionRequestsTest_ThreeLayers, clearsHWCLayersIfOpaqueAndNotFirst) {
Lloyd Piquec2d54d42019-08-28 18:04:21 -07003377 // If client composition is performed with some layers set to use device
3378 // composition, device layers after the first layer (device or client) will
3379 // clear the frame buffer if they are opaque and if that layer has a flag
3380 // set to do so. The first layer is skipped as the frame buffer is already
3381 // expected to be clear.
3382
Lloyd Piquea4863342019-12-04 18:45:02 -08003383 EXPECT_CALL(mLayers[0].mOutputLayer, requiresClientComposition()).WillOnce(Return(false));
3384 EXPECT_CALL(mLayers[1].mOutputLayer, requiresClientComposition()).WillOnce(Return(false));
3385 EXPECT_CALL(mLayers[2].mOutputLayer, requiresClientComposition()).WillOnce(Return(true));
Lloyd Piquec2d54d42019-08-28 18:04:21 -07003386
Lloyd Piquea4863342019-12-04 18:45:02 -08003387 mLayers[0].mOutputLayerState.clearClientTarget = true;
3388 mLayers[1].mOutputLayerState.clearClientTarget = true;
3389 mLayers[2].mOutputLayerState.clearClientTarget = true;
Lloyd Piquec2d54d42019-08-28 18:04:21 -07003390
Lloyd Piquea4863342019-12-04 18:45:02 -08003391 mLayers[0].mLayerFEState.isOpaque = true;
3392 mLayers[1].mLayerFEState.isOpaque = true;
3393 mLayers[2].mLayerFEState.isOpaque = true;
Lloyd Piquec2d54d42019-08-28 18:04:21 -07003394
Lloyd Piquea4863342019-12-04 18:45:02 -08003395 EXPECT_CALL(mLayers[1].mLayerFE, prepareClientComposition(_))
3396 .WillOnce(Return(mLayers[1].mRELayerSettings));
3397 EXPECT_CALL(mLayers[2].mLayerFE, prepareClientComposition(_))
3398 .WillOnce(Return(mLayers[2].mRELayerSettings));
3399 EXPECT_CALL(mLayers[2].mLayerFE, prepareShadowClientComposition(_, _, _))
3400 .WillOnce(Return(std::nullopt));
Lloyd Piquec2d54d42019-08-28 18:04:21 -07003401
Lloyd Piquea4863342019-12-04 18:45:02 -08003402 Region accumClearRegion(Rect(10, 11, 12, 13));
3403 auto requests = mOutput.generateClientCompositionRequests(false /* supportsProtectedContent */,
3404 accumClearRegion, kDisplayDataspace);
3405 ASSERT_EQ(2u, requests.size());
Lloyd Piquec2d54d42019-08-28 18:04:21 -07003406
Lloyd Piquea4863342019-12-04 18:45:02 -08003407 // The second layer is expected to be rendered as alpha=0 black with no blending
3408 EXPECT_EQ(mLayers[1].mRELayerSettings.geometry.boundaries, requests[0].geometry.boundaries);
3409 EXPECT_FALSE(requests[0].source.buffer.buffer);
3410 EXPECT_EQ((half3{0.f, 0.f, 0.f}), requests[0].source.solidColor);
3411 EXPECT_EQ(half{0.f}, requests[0].alpha);
3412 EXPECT_EQ(true, requests[0].disableBlending);
Lloyd Piquec2d54d42019-08-28 18:04:21 -07003413
Lloyd Piquea4863342019-12-04 18:45:02 -08003414 EXPECT_EQ(mLayers[2].mRELayerSettings, requests[1]);
Lloyd Piquec2d54d42019-08-28 18:04:21 -07003415
Lloyd Piquea4863342019-12-04 18:45:02 -08003416 EXPECT_THAT(accumClearRegion, RegionEq(Region(Rect(10, 11, 12, 13))));
3417}
Lloyd Piquec2d54d42019-08-28 18:04:21 -07003418
Lloyd Piquea4863342019-12-04 18:45:02 -08003419TEST_F(GenerateClientCompositionRequestsTest_ThreeLayers,
3420 clippedVisibleRegionUsedToGenerateRequest) {
3421 mLayers[0].mOutputLayerState.visibleRegion = Region(Rect(10, 10, 20, 20));
3422 mLayers[1].mOutputLayerState.visibleRegion = Region(Rect(-10, -10, 30, 30));
3423 mLayers[2].mOutputLayerState.visibleRegion = Region(Rect(-10, 0, 40, 4000));
Lloyd Piquec2d54d42019-08-28 18:04:21 -07003424
Lloyd Piquea4863342019-12-04 18:45:02 -08003425 Region accumClearRegion(Rect(10, 11, 12, 13));
3426
3427 compositionengine::LayerFE::ClientCompositionTargetSettings layer0TargetSettings{
3428 Region(Rect(10, 10, 20, 20)),
3429 false, /* identity transform */
3430 false, /* needs filtering */
3431 false, /* secure */
3432 false, /* supports protected content */
3433 accumClearRegion,
3434 };
3435 compositionengine::LayerFE::ClientCompositionTargetSettings layer1TargetSettings{
3436 Region(Rect(0, 0, 30, 30)),
3437 false, /* identity transform */
3438 false, /* needs filtering */
3439 false, /* secure */
3440 false, /* supports protected content */
3441 accumClearRegion,
3442 };
3443 compositionengine::LayerFE::ClientCompositionTargetSettings layer2TargetSettings{
3444 Region(Rect(0, 0, 40, 201)),
3445 false, /* identity transform */
3446 false, /* needs filtering */
3447 false, /* secure */
3448 false, /* supports protected content */
3449 accumClearRegion,
3450 };
3451
3452 EXPECT_CALL(mLayers[0].mLayerFE, prepareClientComposition(Eq(ByRef(layer0TargetSettings))))
3453 .WillOnce(Return(std::nullopt));
3454 EXPECT_CALL(mLayers[1].mLayerFE, prepareClientComposition(Eq(ByRef(layer1TargetSettings))))
3455 .WillOnce(Return(std::nullopt));
3456 EXPECT_CALL(mLayers[2].mLayerFE, prepareClientComposition(Eq(ByRef(layer2TargetSettings))))
3457 .WillOnce(Return(std::nullopt));
3458
3459 static_cast<void>(
3460 mOutput.generateClientCompositionRequests(false /* supportsProtectedContent */,
3461 accumClearRegion, kDisplayDataspace));
3462}
3463
3464TEST_F(GenerateClientCompositionRequestsTest_ThreeLayers,
3465 perLayerNeedsFilteringUsedToGenerateRequests) {
3466 mOutput.mState.needsFiltering = false;
3467 EXPECT_CALL(mLayers[0].mOutputLayer, needsFiltering()).WillRepeatedly(Return(true));
3468
3469 Region accumClearRegion(Rect(10, 11, 12, 13));
3470
3471 compositionengine::LayerFE::ClientCompositionTargetSettings layer0TargetSettings{
3472 Region(kDisplayFrame),
3473 false, /* identity transform */
3474 true, /* needs filtering */
3475 false, /* secure */
3476 false, /* supports protected content */
3477 accumClearRegion,
3478 };
3479 compositionengine::LayerFE::ClientCompositionTargetSettings layer1TargetSettings{
3480 Region(kDisplayFrame),
3481 false, /* identity transform */
3482 false, /* needs filtering */
3483 false, /* secure */
3484 false, /* supports protected content */
3485 accumClearRegion,
3486 };
3487 compositionengine::LayerFE::ClientCompositionTargetSettings layer2TargetSettings{
3488 Region(kDisplayFrame),
3489 false, /* identity transform */
3490 false, /* needs filtering */
3491 false, /* secure */
3492 false, /* supports protected content */
3493 accumClearRegion,
3494 };
3495
3496 EXPECT_CALL(mLayers[0].mLayerFE, prepareClientComposition(Eq(ByRef(layer0TargetSettings))))
3497 .WillOnce(Return(std::nullopt));
3498 EXPECT_CALL(mLayers[1].mLayerFE, prepareClientComposition(Eq(ByRef(layer1TargetSettings))))
3499 .WillOnce(Return(std::nullopt));
3500 EXPECT_CALL(mLayers[2].mLayerFE, prepareClientComposition(Eq(ByRef(layer2TargetSettings))))
3501 .WillOnce(Return(std::nullopt));
3502
3503 static_cast<void>(
3504 mOutput.generateClientCompositionRequests(false /* supportsProtectedContent */,
3505 accumClearRegion, kDisplayDataspace));
3506}
3507
3508TEST_F(GenerateClientCompositionRequestsTest_ThreeLayers,
3509 wholeOutputNeedsFilteringUsedToGenerateRequests) {
3510 mOutput.mState.needsFiltering = true;
3511 EXPECT_CALL(mLayers[0].mOutputLayer, needsFiltering()).WillRepeatedly(Return(true));
3512
3513 Region accumClearRegion(Rect(10, 11, 12, 13));
3514
3515 compositionengine::LayerFE::ClientCompositionTargetSettings layer0TargetSettings{
3516 Region(kDisplayFrame),
3517 false, /* identity transform */
3518 true, /* needs filtering */
3519 false, /* secure */
3520 false, /* supports protected content */
3521 accumClearRegion,
3522 };
3523 compositionengine::LayerFE::ClientCompositionTargetSettings layer1TargetSettings{
3524 Region(kDisplayFrame),
3525 false, /* identity transform */
3526 true, /* needs filtering */
3527 false, /* secure */
3528 false, /* supports protected content */
3529 accumClearRegion,
3530 };
3531 compositionengine::LayerFE::ClientCompositionTargetSettings layer2TargetSettings{
3532 Region(kDisplayFrame),
3533 false, /* identity transform */
3534 true, /* needs filtering */
3535 false, /* secure */
3536 false, /* supports protected content */
3537 accumClearRegion,
3538 };
3539
3540 EXPECT_CALL(mLayers[0].mLayerFE, prepareClientComposition(Eq(ByRef(layer0TargetSettings))))
3541 .WillOnce(Return(std::nullopt));
3542 EXPECT_CALL(mLayers[1].mLayerFE, prepareClientComposition(Eq(ByRef(layer1TargetSettings))))
3543 .WillOnce(Return(std::nullopt));
3544 EXPECT_CALL(mLayers[2].mLayerFE, prepareClientComposition(Eq(ByRef(layer2TargetSettings))))
3545 .WillOnce(Return(std::nullopt));
3546
3547 static_cast<void>(
3548 mOutput.generateClientCompositionRequests(false /* supportsProtectedContent */,
3549 accumClearRegion, kDisplayDataspace));
3550}
3551
3552TEST_F(GenerateClientCompositionRequestsTest_ThreeLayers,
3553 wholeOutputSecurityUsedToGenerateRequests) {
3554 mOutput.mState.isSecure = true;
3555
3556 Region accumClearRegion(Rect(10, 11, 12, 13));
3557
3558 compositionengine::LayerFE::ClientCompositionTargetSettings layer0TargetSettings{
3559 Region(kDisplayFrame),
3560 false, /* identity transform */
3561 false, /* needs filtering */
3562 true, /* secure */
3563 false, /* supports protected content */
3564 accumClearRegion,
3565 };
3566 compositionengine::LayerFE::ClientCompositionTargetSettings layer1TargetSettings{
3567 Region(kDisplayFrame),
3568 false, /* identity transform */
3569 false, /* needs filtering */
3570 true, /* secure */
3571 false, /* supports protected content */
3572 accumClearRegion,
3573 };
3574 compositionengine::LayerFE::ClientCompositionTargetSettings layer2TargetSettings{
3575 Region(kDisplayFrame),
3576 false, /* identity transform */
3577 false, /* needs filtering */
3578 true, /* secure */
3579 false, /* supports protected content */
3580 accumClearRegion,
3581 };
3582
3583 EXPECT_CALL(mLayers[0].mLayerFE, prepareClientComposition(Eq(ByRef(layer0TargetSettings))))
3584 .WillOnce(Return(std::nullopt));
3585 EXPECT_CALL(mLayers[1].mLayerFE, prepareClientComposition(Eq(ByRef(layer1TargetSettings))))
3586 .WillOnce(Return(std::nullopt));
3587 EXPECT_CALL(mLayers[2].mLayerFE, prepareClientComposition(Eq(ByRef(layer2TargetSettings))))
3588 .WillOnce(Return(std::nullopt));
3589
3590 static_cast<void>(
3591 mOutput.generateClientCompositionRequests(false /* supportsProtectedContent */,
3592 accumClearRegion, kDisplayDataspace));
3593}
3594
3595TEST_F(GenerateClientCompositionRequestsTest_ThreeLayers,
3596 protectedContentSupportUsedToGenerateRequests) {
3597 Region accumClearRegion(Rect(10, 11, 12, 13));
3598
3599 compositionengine::LayerFE::ClientCompositionTargetSettings layer0TargetSettings{
3600 Region(kDisplayFrame),
3601 false, /* identity transform */
3602 false, /* needs filtering */
3603 false, /* secure */
3604 true, /* supports protected content */
3605 accumClearRegion,
3606 };
3607 compositionengine::LayerFE::ClientCompositionTargetSettings layer1TargetSettings{
3608 Region(kDisplayFrame),
3609 false, /* identity transform */
3610 false, /* needs filtering */
3611 false, /* secure */
3612 true, /* supports protected content */
3613 accumClearRegion,
3614 };
3615 compositionengine::LayerFE::ClientCompositionTargetSettings layer2TargetSettings{
3616 Region(kDisplayFrame),
3617 false, /* identity transform */
3618 false, /* needs filtering */
3619 false, /* secure */
3620 true, /* supports protected content */
3621 accumClearRegion,
3622 };
3623
3624 EXPECT_CALL(mLayers[0].mLayerFE, prepareClientComposition(Eq(ByRef(layer0TargetSettings))))
3625 .WillOnce(Return(std::nullopt));
3626 EXPECT_CALL(mLayers[1].mLayerFE, prepareClientComposition(Eq(ByRef(layer1TargetSettings))))
3627 .WillOnce(Return(std::nullopt));
3628 EXPECT_CALL(mLayers[2].mLayerFE, prepareClientComposition(Eq(ByRef(layer2TargetSettings))))
3629 .WillOnce(Return(std::nullopt));
3630
3631 static_cast<void>(mOutput.generateClientCompositionRequests(true /* supportsProtectedContent */,
3632 accumClearRegion,
3633 kDisplayDataspace));
3634}
3635
3636TEST_F(GenerateClientCompositionRequestsTest, handlesLandscapeModeSplitScreenRequests) {
3637 // In split-screen landscape mode, the screen is rotated 90 degrees, with
3638 // one layer on the left covering the left side of the output, and one layer
3639 // on the right covering that side of the output.
Lloyd Piquec2d54d42019-08-28 18:04:21 -07003640
3641 const Rect kPortraitFrame(0, 0, 1000, 2000);
3642 const Rect kPortraitViewport(0, 0, 2000, 1000);
3643 const Rect kPortraitScissor(0, 0, 1000, 2000);
3644 const uint32_t kPortraitOrientation = TR_ROT_90;
Lloyd Piquea4863342019-12-04 18:45:02 -08003645 constexpr ui::Dataspace kOutputDataspace = ui::Dataspace::DISPLAY_P3;
Lloyd Piquec2d54d42019-08-28 18:04:21 -07003646
Lloyd Piquea4863342019-12-04 18:45:02 -08003647 mOutput.mState.frame = kPortraitFrame;
3648 mOutput.mState.viewport = kPortraitViewport;
3649 mOutput.mState.scissor = kPortraitScissor;
3650 mOutput.mState.transform = ui::Transform{kPortraitOrientation};
3651 mOutput.mState.orientation = kPortraitOrientation;
3652 mOutput.mState.needsFiltering = false;
3653 mOutput.mState.isSecure = true;
Lloyd Piquec2d54d42019-08-28 18:04:21 -07003654
Lloyd Piquea4863342019-12-04 18:45:02 -08003655 Layer leftLayer;
3656 Layer rightLayer;
Lloyd Piquec2d54d42019-08-28 18:04:21 -07003657
Lloyd Piquea4863342019-12-04 18:45:02 -08003658 leftLayer.mOutputLayerState.clearClientTarget = false;
3659 leftLayer.mOutputLayerState.visibleRegion = Region(Rect(0, 0, 1000, 1000));
3660 leftLayer.mLayerFEState.isOpaque = true;
3661 leftLayer.mRELayerSettings.source.solidColor = {1.f, 0.f, 0.f};
Lloyd Piquec2d54d42019-08-28 18:04:21 -07003662
Lloyd Piquea4863342019-12-04 18:45:02 -08003663 rightLayer.mOutputLayerState.clearClientTarget = false;
3664 rightLayer.mOutputLayerState.visibleRegion = Region(Rect(1000, 0, 2000, 1000));
3665 rightLayer.mLayerFEState.isOpaque = true;
3666 rightLayer.mRELayerSettings.source.solidColor = {0.f, 1.f, 0.f};
3667
3668 EXPECT_CALL(mOutput, getOutputLayerCount()).WillRepeatedly(Return(2u));
3669 EXPECT_CALL(mOutput, getOutputLayerOrderedByZByIndex(0u))
3670 .WillRepeatedly(Return(&leftLayer.mOutputLayer));
3671 EXPECT_CALL(mOutput, getOutputLayerOrderedByZByIndex(1u))
3672 .WillRepeatedly(Return(&rightLayer.mOutputLayer));
3673
3674 Region accumClearRegion(Rect(10, 11, 12, 13));
3675
3676 compositionengine::LayerFE::ClientCompositionTargetSettings leftLayerSettings{
3677 Region(Rect(0, 0, 1000, 1000)),
3678 false, /* identity transform */
3679 false, /* needs filtering */
3680 true, /* secure */
3681 true, /* supports protected content */
3682 accumClearRegion,
3683 };
3684
3685 EXPECT_CALL(leftLayer.mOutputLayer, requiresClientComposition()).WillRepeatedly(Return(true));
3686 EXPECT_CALL(leftLayer.mOutputLayer, needsFiltering()).WillRepeatedly(Return(false));
3687 EXPECT_CALL(leftLayer.mLayerFE, prepareClientComposition(Eq(ByRef(leftLayerSettings))))
3688 .WillOnce(Return(leftLayer.mRELayerSettings));
3689 EXPECT_CALL(leftLayer.mLayerFE,
3690 prepareShadowClientComposition(leftLayer.mRELayerSettings, kPortraitViewport,
3691 kOutputDataspace))
3692 .WillOnce(Return(std::nullopt));
3693
3694 compositionengine::LayerFE::ClientCompositionTargetSettings rightLayerSettings{
3695 Region(Rect(1000, 0, 2000, 1000)),
3696 false, /* identity transform */
3697 false, /* needs filtering */
3698 true, /* secure */
3699 true, /* supports protected content */
3700 accumClearRegion,
3701 };
3702
3703 EXPECT_CALL(rightLayer.mOutputLayer, requiresClientComposition()).WillRepeatedly(Return(true));
3704 EXPECT_CALL(rightLayer.mOutputLayer, needsFiltering()).WillRepeatedly(Return(false));
3705 EXPECT_CALL(rightLayer.mLayerFE, prepareClientComposition(Eq(ByRef(rightLayerSettings))))
3706 .WillOnce(Return(rightLayer.mRELayerSettings));
3707 EXPECT_CALL(rightLayer.mLayerFE,
3708 prepareShadowClientComposition(rightLayer.mRELayerSettings, kPortraitViewport,
3709 kOutputDataspace))
3710 .WillOnce(Return(std::nullopt));
3711
3712 constexpr bool supportsProtectedContent = true;
3713 auto requests = mOutput.generateClientCompositionRequests(supportsProtectedContent,
3714 accumClearRegion, kOutputDataspace);
3715 ASSERT_EQ(2u, requests.size());
3716 EXPECT_EQ(leftLayer.mRELayerSettings, requests[0]);
3717 EXPECT_EQ(rightLayer.mRELayerSettings, requests[1]);
Lloyd Piquec2d54d42019-08-28 18:04:21 -07003718}
3719
Vishnu Naira483b4a2019-12-12 15:07:52 -08003720TEST_F(GenerateClientCompositionRequestsTest_ThreeLayers,
3721 shadowRegionOnlyVisibleSkipsContentComposition) {
3722 const Rect kContentWithShadow(40, 40, 70, 90);
3723 const Rect kContent(50, 50, 60, 80);
3724 const Region kShadowRegion = Region(kContentWithShadow).subtract(kContent);
3725 const Region kPartialShadowRegion = Region(kContentWithShadow).subtract(Rect(40, 40, 60, 80));
3726
3727 renderengine::LayerSettings mREShadowSettings;
3728 mREShadowSettings.source.solidColor = {0.1f, 0.1f, 0.1f};
3729
3730 mLayers[2].mOutputLayerState.visibleRegion = kPartialShadowRegion;
3731 mLayers[2].mOutputLayerState.shadowRegion = kShadowRegion;
3732
3733 EXPECT_CALL(mLayers[0].mOutputLayer, requiresClientComposition()).WillOnce(Return(false));
3734 EXPECT_CALL(mLayers[1].mOutputLayer, requiresClientComposition()).WillOnce(Return(false));
3735 EXPECT_CALL(mLayers[2].mLayerFE, prepareClientComposition(_))
3736 .WillOnce(Return(mLayers[2].mRELayerSettings));
3737 EXPECT_CALL(mLayers[2].mLayerFE,
3738 prepareShadowClientComposition(mLayers[2].mRELayerSettings, kDisplayViewport,
3739 kDisplayDataspace))
3740 .WillOnce(Return(mREShadowSettings));
3741
3742 Region accumClearRegion(Rect(10, 11, 12, 13));
3743 auto requests = mOutput.generateClientCompositionRequests(false /* supportsProtectedContent */,
3744 accumClearRegion, kDisplayDataspace);
3745 ASSERT_EQ(1u, requests.size());
3746
3747 EXPECT_EQ(mREShadowSettings, requests[0]);
3748}
3749
3750TEST_F(GenerateClientCompositionRequestsTest_ThreeLayers,
3751 shadowRegionWithContentVisibleRequestsContentAndShadowComposition) {
3752 const Rect kContentWithShadow(40, 40, 70, 90);
3753 const Rect kContent(50, 50, 60, 80);
3754 const Region kShadowRegion = Region(kContentWithShadow).subtract(kContent);
3755 const Region kPartialContentWithPartialShadowRegion =
3756 Region(kContentWithShadow).subtract(Rect(40, 40, 50, 80));
3757
3758 renderengine::LayerSettings mREShadowSettings;
3759 mREShadowSettings.source.solidColor = {0.1f, 0.1f, 0.1f};
3760
3761 mLayers[2].mOutputLayerState.visibleRegion = kPartialContentWithPartialShadowRegion;
3762 mLayers[2].mOutputLayerState.shadowRegion = kShadowRegion;
3763
3764 EXPECT_CALL(mLayers[0].mOutputLayer, requiresClientComposition()).WillOnce(Return(false));
3765 EXPECT_CALL(mLayers[1].mOutputLayer, requiresClientComposition()).WillOnce(Return(false));
3766 EXPECT_CALL(mLayers[2].mLayerFE, prepareClientComposition(_))
3767 .WillOnce(Return(mLayers[2].mRELayerSettings));
3768 EXPECT_CALL(mLayers[2].mLayerFE,
3769 prepareShadowClientComposition(mLayers[2].mRELayerSettings, kDisplayViewport,
3770 kDisplayDataspace))
3771 .WillOnce(Return(mREShadowSettings));
3772
3773 Region accumClearRegion(Rect(10, 11, 12, 13));
3774 auto requests = mOutput.generateClientCompositionRequests(false /* supportsProtectedContent */,
3775 accumClearRegion, kDisplayDataspace);
3776 ASSERT_EQ(2u, requests.size());
3777
3778 EXPECT_EQ(mREShadowSettings, requests[0]);
3779 EXPECT_EQ(mLayers[2].mRELayerSettings, requests[1]);
3780}
3781
Lloyd Pique32cbe282018-10-19 13:09:22 -07003782} // namespace
3783} // namespace android::compositionengine