blob: 615fb94c3437d758cb8e8f508120faf66bff75bb [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 Pique32cbe282018-10-19 13:09:22 -070036#include "RegionMatcher.h"
37#include "TransformMatcher.h"
38
39namespace android::compositionengine {
40namespace {
41
Lloyd Pique56eba802019-08-28 15:45:25 -070042using testing::_;
Lloyd Pique03561a62019-11-19 18:34:52 -080043using testing::ByMove;
Lloyd Pique17ca7422019-11-14 14:24:10 -080044using testing::DoAll;
Lloyd Piquefaa3f192019-11-14 14:05:09 -080045using testing::InSequence;
Lloyd Pique17ca7422019-11-14 14:24:10 -080046using testing::Mock;
Lloyd Piquefaa3f192019-11-14 14:05:09 -080047using testing::Ref;
Lloyd Pique31cb2942018-10-19 17:23:03 -070048using testing::Return;
Lloyd Pique32cbe282018-10-19 13:09:22 -070049using testing::ReturnRef;
Lloyd Pique17ca7422019-11-14 14:24:10 -080050using testing::SetArgPointee;
Lloyd Pique32cbe282018-10-19 13:09:22 -070051using testing::StrictMock;
52
Lloyd Pique56eba802019-08-28 15:45:25 -070053constexpr auto TR_IDENT = 0u;
54constexpr auto TR_ROT_90 = HAL_TRANSFORM_ROT_90;
55
Lloyd Pique3eb1b212019-03-07 21:15:40 -080056const mat4 kIdentity;
57const mat4 kNonIdentityHalf = mat4() * 0.5;
58const mat4 kNonIdentityQuarter = mat4() * 0.25;
59
Lloyd Pique17ca7422019-11-14 14:24:10 -080060constexpr OutputColorSetting kVendorSpecifiedOutputColorSetting =
61 static_cast<OutputColorSetting>(0x100);
62
Lloyd Piquefaa3f192019-11-14 14:05:09 -080063struct OutputPartialMockBase : public impl::Output {
64 // compositionengine::Output overrides
65 const OutputCompositionState& getState() const override { return mState; }
66 OutputCompositionState& editState() override { return mState; }
67
68 // Use mocks for all the remaining virtual functions
69 // not implemented by the base implementation class.
70 MOCK_CONST_METHOD0(getOutputLayerCount, size_t());
71 MOCK_CONST_METHOD1(getOutputLayerOrderedByZByIndex, compositionengine::OutputLayer*(size_t));
72 MOCK_METHOD3(ensureOutputLayer,
73 compositionengine::OutputLayer*(std::optional<size_t>,
74 const std::shared_ptr<compositionengine::Layer>&,
75 const sp<LayerFE>&));
76 MOCK_METHOD0(finalizePendingOutputLayers, void());
77 MOCK_METHOD0(clearOutputLayers, void());
78 MOCK_CONST_METHOD1(dumpState, void(std::string&));
79 MOCK_CONST_METHOD0(getCompositionEngine, const CompositionEngine&());
80 MOCK_METHOD2(injectOutputLayerForTest,
81 compositionengine::OutputLayer*(const std::shared_ptr<compositionengine::Layer>&,
82 const sp<LayerFE>&));
83 MOCK_METHOD1(injectOutputLayerForTest, void(std::unique_ptr<OutputLayer>));
84
85 impl::OutputCompositionState mState;
86};
87
Lloyd Pique66d68602019-02-13 14:23:31 -080088struct OutputTest : public testing::Test {
Lloyd Pique01c77c12019-04-17 12:48:32 -070089 class Output : public impl::Output {
90 public:
91 using impl::Output::injectOutputLayerForTest;
92 virtual void injectOutputLayerForTest(std::unique_ptr<compositionengine::OutputLayer>) = 0;
93 };
94
95 static std::shared_ptr<Output> createOutput(
96 const compositionengine::CompositionEngine& compositionEngine) {
97 return impl::createOutputTemplated<Output>(compositionEngine);
98 }
99
Lloyd Pique31cb2942018-10-19 17:23:03 -0700100 OutputTest() {
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700101 mOutput->setDisplayColorProfileForTest(
Lloyd Pique3d0c02e2018-10-19 18:38:12 -0700102 std::unique_ptr<DisplayColorProfile>(mDisplayColorProfile));
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700103 mOutput->setRenderSurfaceForTest(std::unique_ptr<RenderSurface>(mRenderSurface));
Lloyd Piqueef958122019-02-05 18:00:12 -0800104
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700105 mOutput->editState().bounds = kDefaultDisplaySize;
Lloyd Pique31cb2942018-10-19 17:23:03 -0700106 }
Lloyd Pique32cbe282018-10-19 13:09:22 -0700107
Lloyd Piqueef958122019-02-05 18:00:12 -0800108 static const Rect kDefaultDisplaySize;
109
Lloyd Pique32cbe282018-10-19 13:09:22 -0700110 StrictMock<mock::CompositionEngine> mCompositionEngine;
Lloyd Pique3d0c02e2018-10-19 18:38:12 -0700111 mock::DisplayColorProfile* mDisplayColorProfile = new StrictMock<mock::DisplayColorProfile>();
Lloyd Pique31cb2942018-10-19 17:23:03 -0700112 mock::RenderSurface* mRenderSurface = new StrictMock<mock::RenderSurface>();
Lloyd Pique01c77c12019-04-17 12:48:32 -0700113 std::shared_ptr<Output> mOutput = createOutput(mCompositionEngine);
Lloyd Pique32cbe282018-10-19 13:09:22 -0700114};
115
Lloyd Piqueef958122019-02-05 18:00:12 -0800116const Rect OutputTest::kDefaultDisplaySize{100, 200};
117
Lloyd Pique17ca7422019-11-14 14:24:10 -0800118using ColorProfile = compositionengine::Output::ColorProfile;
119
120void dumpColorProfile(ColorProfile profile, std::string& result, const char* name) {
121 android::base::StringAppendF(&result, "%s (%s[%d] %s[%d] %s[%d] %s[%d]) ", name,
122 toString(profile.mode).c_str(), profile.mode,
123 toString(profile.dataspace).c_str(), profile.dataspace,
124 toString(profile.renderIntent).c_str(), profile.renderIntent,
125 toString(profile.colorSpaceAgnosticDataspace).c_str(),
126 profile.colorSpaceAgnosticDataspace);
127}
128
129// Checks for a ColorProfile match
130MATCHER_P(ColorProfileEq, expected, "") {
131 std::string buf;
132 buf.append("ColorProfiles are not equal\n");
133 dumpColorProfile(expected, buf, "expected value");
134 dumpColorProfile(arg, buf, "actual value");
135 *result_listener << buf;
136
137 return (expected.mode == arg.mode) && (expected.dataspace == arg.dataspace) &&
138 (expected.renderIntent == arg.renderIntent) &&
139 (expected.colorSpaceAgnosticDataspace == arg.colorSpaceAgnosticDataspace);
140}
141
Lloyd Pique66d68602019-02-13 14:23:31 -0800142/*
Lloyd Pique32cbe282018-10-19 13:09:22 -0700143 * Basic construction
144 */
145
Lloyd Pique31cb2942018-10-19 17:23:03 -0700146TEST_F(OutputTest, canInstantiateOutput) {
147 // The validation check checks each required component.
Lloyd Pique3d0c02e2018-10-19 18:38:12 -0700148 EXPECT_CALL(*mDisplayColorProfile, isValid()).WillOnce(Return(true));
Lloyd Pique31cb2942018-10-19 17:23:03 -0700149 EXPECT_CALL(*mRenderSurface, isValid()).WillOnce(Return(true));
150
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700151 EXPECT_TRUE(mOutput->isValid());
Lloyd Pique31cb2942018-10-19 17:23:03 -0700152
153 // If we take away the required components, it is no longer valid.
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700154 mOutput->setRenderSurfaceForTest(std::unique_ptr<RenderSurface>());
Lloyd Pique31cb2942018-10-19 17:23:03 -0700155
Lloyd Pique3d0c02e2018-10-19 18:38:12 -0700156 EXPECT_CALL(*mDisplayColorProfile, isValid()).WillOnce(Return(true));
157
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700158 EXPECT_FALSE(mOutput->isValid());
Lloyd Pique31cb2942018-10-19 17:23:03 -0700159}
Lloyd Pique32cbe282018-10-19 13:09:22 -0700160
Lloyd Pique66d68602019-02-13 14:23:31 -0800161/*
Lloyd Pique32cbe282018-10-19 13:09:22 -0700162 * Output::setCompositionEnabled()
163 */
164
165TEST_F(OutputTest, setCompositionEnabledDoesNothingIfAlreadyEnabled) {
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700166 mOutput->editState().isEnabled = true;
Lloyd Pique32cbe282018-10-19 13:09:22 -0700167
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700168 mOutput->setCompositionEnabled(true);
Lloyd Pique32cbe282018-10-19 13:09:22 -0700169
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700170 EXPECT_TRUE(mOutput->getState().isEnabled);
171 EXPECT_THAT(mOutput->getState().dirtyRegion, RegionEq(Region()));
Lloyd Pique32cbe282018-10-19 13:09:22 -0700172}
173
174TEST_F(OutputTest, setCompositionEnabledSetsEnabledAndDirtiesEntireOutput) {
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700175 mOutput->editState().isEnabled = false;
Lloyd Pique32cbe282018-10-19 13:09:22 -0700176
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700177 mOutput->setCompositionEnabled(true);
Lloyd Pique32cbe282018-10-19 13:09:22 -0700178
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700179 EXPECT_TRUE(mOutput->getState().isEnabled);
180 EXPECT_THAT(mOutput->getState().dirtyRegion, RegionEq(Region(kDefaultDisplaySize)));
Lloyd Pique32cbe282018-10-19 13:09:22 -0700181}
182
183TEST_F(OutputTest, setCompositionEnabledSetsDisabledAndDirtiesEntireOutput) {
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700184 mOutput->editState().isEnabled = true;
Lloyd Pique32cbe282018-10-19 13:09:22 -0700185
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700186 mOutput->setCompositionEnabled(false);
Lloyd Pique32cbe282018-10-19 13:09:22 -0700187
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700188 EXPECT_FALSE(mOutput->getState().isEnabled);
189 EXPECT_THAT(mOutput->getState().dirtyRegion, RegionEq(Region(kDefaultDisplaySize)));
Lloyd Pique32cbe282018-10-19 13:09:22 -0700190}
191
Lloyd Pique66d68602019-02-13 14:23:31 -0800192/*
Lloyd Pique32cbe282018-10-19 13:09:22 -0700193 * Output::setProjection()
194 */
195
196TEST_F(OutputTest, setProjectionTriviallyWorks) {
197 const ui::Transform transform{ui::Transform::ROT_180};
198 const int32_t orientation = 123;
199 const Rect frame{1, 2, 3, 4};
200 const Rect viewport{5, 6, 7, 8};
201 const Rect scissor{9, 10, 11, 12};
202 const bool needsFiltering = true;
203
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700204 mOutput->setProjection(transform, orientation, frame, viewport, scissor, needsFiltering);
Lloyd Pique32cbe282018-10-19 13:09:22 -0700205
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700206 EXPECT_THAT(mOutput->getState().transform, TransformEq(transform));
207 EXPECT_EQ(orientation, mOutput->getState().orientation);
208 EXPECT_EQ(frame, mOutput->getState().frame);
209 EXPECT_EQ(viewport, mOutput->getState().viewport);
210 EXPECT_EQ(scissor, mOutput->getState().scissor);
211 EXPECT_EQ(needsFiltering, mOutput->getState().needsFiltering);
Lloyd Pique32cbe282018-10-19 13:09:22 -0700212}
213
Lloyd Pique66d68602019-02-13 14:23:31 -0800214/*
Lloyd Pique32cbe282018-10-19 13:09:22 -0700215 * Output::setBounds()
216 */
217
218TEST_F(OutputTest, setBoundsSetsSizeAndDirtiesEntireOutput) {
Lloyd Piqueef958122019-02-05 18:00:12 -0800219 const ui::Size displaySize{200, 400};
Lloyd Pique31cb2942018-10-19 17:23:03 -0700220
221 EXPECT_CALL(*mRenderSurface, setDisplaySize(displaySize)).Times(1);
222 EXPECT_CALL(*mRenderSurface, getSize()).WillOnce(ReturnRef(displaySize));
223
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700224 mOutput->setBounds(displaySize);
Lloyd Pique32cbe282018-10-19 13:09:22 -0700225
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700226 EXPECT_EQ(Rect(displaySize), mOutput->getState().bounds);
Lloyd Pique32cbe282018-10-19 13:09:22 -0700227
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700228 EXPECT_THAT(mOutput->getState().dirtyRegion, RegionEq(Region(Rect(displaySize))));
Lloyd Pique32cbe282018-10-19 13:09:22 -0700229}
230
Lloyd Pique66d68602019-02-13 14:23:31 -0800231/*
Lloyd Pique32cbe282018-10-19 13:09:22 -0700232 * Output::setLayerStackFilter()
233 */
234
235TEST_F(OutputTest, setLayerStackFilterSetsFilterAndDirtiesEntireOutput) {
Lloyd Pique32cbe282018-10-19 13:09:22 -0700236 const uint32_t layerStack = 123u;
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700237 mOutput->setLayerStackFilter(layerStack, true);
Lloyd Pique32cbe282018-10-19 13:09:22 -0700238
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700239 EXPECT_TRUE(mOutput->getState().layerStackInternal);
240 EXPECT_EQ(layerStack, mOutput->getState().layerStackId);
Lloyd Pique32cbe282018-10-19 13:09:22 -0700241
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700242 EXPECT_THAT(mOutput->getState().dirtyRegion, RegionEq(Region(kDefaultDisplaySize)));
Lloyd Pique32cbe282018-10-19 13:09:22 -0700243}
244
Lloyd Pique66d68602019-02-13 14:23:31 -0800245/*
Lloyd Pique32cbe282018-10-19 13:09:22 -0700246 * Output::setColorTransform
247 */
248
Lloyd Pique3eb1b212019-03-07 21:15:40 -0800249TEST_F(OutputTest, setColorTransformWithNoChangeFlaggedSkipsUpdates) {
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700250 mOutput->editState().colorTransformMatrix = kIdentity;
Lloyd Pique32cbe282018-10-19 13:09:22 -0700251
Lloyd Pique3eb1b212019-03-07 21:15:40 -0800252 // If no colorTransformMatrix is set the update should be skipped.
253 CompositionRefreshArgs refreshArgs;
254 refreshArgs.colorTransformMatrix = std::nullopt;
Lloyd Pique32cbe282018-10-19 13:09:22 -0700255
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700256 mOutput->setColorTransform(refreshArgs);
Lloyd Pique32cbe282018-10-19 13:09:22 -0700257
Lloyd Pique3eb1b212019-03-07 21:15:40 -0800258 // The internal state should be unchanged
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700259 EXPECT_EQ(kIdentity, mOutput->getState().colorTransformMatrix);
Lloyd Pique3eb1b212019-03-07 21:15:40 -0800260
261 // No dirty region should be set
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700262 EXPECT_THAT(mOutput->getState().dirtyRegion, RegionEq(Region()));
Lloyd Pique3eb1b212019-03-07 21:15:40 -0800263}
Lloyd Piqueef958122019-02-05 18:00:12 -0800264
Lloyd Pique3eb1b212019-03-07 21:15:40 -0800265TEST_F(OutputTest, setColorTransformWithNoActualChangeSkipsUpdates) {
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700266 mOutput->editState().colorTransformMatrix = kIdentity;
Lloyd Pique32cbe282018-10-19 13:09:22 -0700267
Lloyd Pique3eb1b212019-03-07 21:15:40 -0800268 // Attempting to set the same colorTransformMatrix that is already set should
269 // also skip the update.
270 CompositionRefreshArgs refreshArgs;
271 refreshArgs.colorTransformMatrix = kIdentity;
Lloyd Pique32cbe282018-10-19 13:09:22 -0700272
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700273 mOutput->setColorTransform(refreshArgs);
Lloyd Pique77f79a22019-04-29 15:55:40 -0700274
Lloyd Pique3eb1b212019-03-07 21:15:40 -0800275 // The internal state should be unchanged
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700276 EXPECT_EQ(kIdentity, mOutput->getState().colorTransformMatrix);
Lloyd Pique3eb1b212019-03-07 21:15:40 -0800277
278 // No dirty region should be set
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700279 EXPECT_THAT(mOutput->getState().dirtyRegion, RegionEq(Region()));
Lloyd Pique3eb1b212019-03-07 21:15:40 -0800280}
281
282TEST_F(OutputTest, setColorTransformPerformsUpdateToIdentity) {
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700283 mOutput->editState().colorTransformMatrix = kNonIdentityHalf;
Lloyd Pique3eb1b212019-03-07 21:15:40 -0800284
285 // Setting a different colorTransformMatrix should perform the update.
286 CompositionRefreshArgs refreshArgs;
287 refreshArgs.colorTransformMatrix = kIdentity;
288
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700289 mOutput->setColorTransform(refreshArgs);
Lloyd Pique3eb1b212019-03-07 21:15:40 -0800290
291 // The internal state should have been updated
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700292 EXPECT_EQ(kIdentity, mOutput->getState().colorTransformMatrix);
Lloyd Pique3eb1b212019-03-07 21:15:40 -0800293
294 // The dirtyRegion should be set to the full display size
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700295 EXPECT_THAT(mOutput->getState().dirtyRegion, RegionEq(Region(kDefaultDisplaySize)));
Lloyd Pique3eb1b212019-03-07 21:15:40 -0800296}
Lloyd Pique77f79a22019-04-29 15:55:40 -0700297
Lloyd Pique3eb1b212019-03-07 21:15:40 -0800298TEST_F(OutputTest, setColorTransformPerformsUpdateForIdentityToHalf) {
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700299 mOutput->editState().colorTransformMatrix = kIdentity;
Lloyd Pique77f79a22019-04-29 15:55:40 -0700300
Lloyd Pique3eb1b212019-03-07 21:15:40 -0800301 // Setting a different colorTransformMatrix should perform the update.
302 CompositionRefreshArgs refreshArgs;
303 refreshArgs.colorTransformMatrix = kNonIdentityHalf;
Lloyd Pique77f79a22019-04-29 15:55:40 -0700304
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700305 mOutput->setColorTransform(refreshArgs);
Lloyd Piqueef958122019-02-05 18:00:12 -0800306
Lloyd Pique3eb1b212019-03-07 21:15:40 -0800307 // The internal state should have been updated
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700308 EXPECT_EQ(kNonIdentityHalf, mOutput->getState().colorTransformMatrix);
Lloyd Pique3eb1b212019-03-07 21:15:40 -0800309
310 // The dirtyRegion should be set to the full display size
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700311 EXPECT_THAT(mOutput->getState().dirtyRegion, RegionEq(Region(kDefaultDisplaySize)));
Lloyd Pique3eb1b212019-03-07 21:15:40 -0800312}
313
314TEST_F(OutputTest, setColorTransformPerformsUpdateForHalfToQuarter) {
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700315 mOutput->editState().colorTransformMatrix = kNonIdentityHalf;
Lloyd Pique3eb1b212019-03-07 21:15:40 -0800316
317 // Setting a different colorTransformMatrix should perform the update.
318 CompositionRefreshArgs refreshArgs;
319 refreshArgs.colorTransformMatrix = kNonIdentityQuarter;
320
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700321 mOutput->setColorTransform(refreshArgs);
Lloyd Pique3eb1b212019-03-07 21:15:40 -0800322
323 // The internal state should have been updated
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700324 EXPECT_EQ(kNonIdentityQuarter, mOutput->getState().colorTransformMatrix);
Lloyd Pique3eb1b212019-03-07 21:15:40 -0800325
326 // The dirtyRegion should be set to the full display size
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700327 EXPECT_THAT(mOutput->getState().dirtyRegion, RegionEq(Region(kDefaultDisplaySize)));
Lloyd Pique32cbe282018-10-19 13:09:22 -0700328}
329
Lloyd Pique66d68602019-02-13 14:23:31 -0800330/*
Lloyd Pique17ca7422019-11-14 14:24:10 -0800331 * Output::setColorProfile
Lloyd Pique32cbe282018-10-19 13:09:22 -0700332 */
333
Lloyd Pique17ca7422019-11-14 14:24:10 -0800334using OutputSetColorProfileTest = OutputTest;
335
336TEST_F(OutputSetColorProfileTest, setsStateAndDirtiesOutputIfChanged) {
Lloyd Pique6a3b4462019-03-07 20:58:12 -0800337 using ColorProfile = Output::ColorProfile;
338
Lloyd Piquef5275482019-01-29 18:42:42 -0800339 EXPECT_CALL(*mDisplayColorProfile,
340 getTargetDataspace(ui::ColorMode::DISPLAY_P3, ui::Dataspace::DISPLAY_P3,
341 ui::Dataspace::UNKNOWN))
342 .WillOnce(Return(ui::Dataspace::UNKNOWN));
Lloyd Piqueef958122019-02-05 18:00:12 -0800343 EXPECT_CALL(*mRenderSurface, setBufferDataspace(ui::Dataspace::DISPLAY_P3)).Times(1);
Lloyd Pique31cb2942018-10-19 17:23:03 -0700344
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700345 mOutput->setColorProfile(ColorProfile{ui::ColorMode::DISPLAY_P3, ui::Dataspace::DISPLAY_P3,
346 ui::RenderIntent::TONE_MAP_COLORIMETRIC,
347 ui::Dataspace::UNKNOWN});
Lloyd Pique32cbe282018-10-19 13:09:22 -0700348
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700349 EXPECT_EQ(ui::ColorMode::DISPLAY_P3, mOutput->getState().colorMode);
350 EXPECT_EQ(ui::Dataspace::DISPLAY_P3, mOutput->getState().dataspace);
351 EXPECT_EQ(ui::RenderIntent::TONE_MAP_COLORIMETRIC, mOutput->getState().renderIntent);
352 EXPECT_EQ(ui::Dataspace::UNKNOWN, mOutput->getState().targetDataspace);
Lloyd Piquef5275482019-01-29 18:42:42 -0800353
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700354 EXPECT_THAT(mOutput->getState().dirtyRegion, RegionEq(Region(kDefaultDisplaySize)));
Lloyd Piqueef958122019-02-05 18:00:12 -0800355}
356
Lloyd Pique17ca7422019-11-14 14:24:10 -0800357TEST_F(OutputSetColorProfileTest, doesNothingIfNoChange) {
Lloyd Pique6a3b4462019-03-07 20:58:12 -0800358 using ColorProfile = Output::ColorProfile;
359
Lloyd Piquef5275482019-01-29 18:42:42 -0800360 EXPECT_CALL(*mDisplayColorProfile,
361 getTargetDataspace(ui::ColorMode::DISPLAY_P3, ui::Dataspace::DISPLAY_P3,
362 ui::Dataspace::UNKNOWN))
363 .WillOnce(Return(ui::Dataspace::UNKNOWN));
364
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700365 mOutput->editState().colorMode = ui::ColorMode::DISPLAY_P3;
366 mOutput->editState().dataspace = ui::Dataspace::DISPLAY_P3;
367 mOutput->editState().renderIntent = ui::RenderIntent::TONE_MAP_COLORIMETRIC;
368 mOutput->editState().targetDataspace = ui::Dataspace::UNKNOWN;
Lloyd Piqueef958122019-02-05 18:00:12 -0800369
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700370 mOutput->setColorProfile(ColorProfile{ui::ColorMode::DISPLAY_P3, ui::Dataspace::DISPLAY_P3,
371 ui::RenderIntent::TONE_MAP_COLORIMETRIC,
372 ui::Dataspace::UNKNOWN});
Lloyd Piqueef958122019-02-05 18:00:12 -0800373
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700374 EXPECT_THAT(mOutput->getState().dirtyRegion, RegionEq(Region()));
Lloyd Pique32cbe282018-10-19 13:09:22 -0700375}
376
Lloyd Pique66d68602019-02-13 14:23:31 -0800377/*
Lloyd Pique31cb2942018-10-19 17:23:03 -0700378 * Output::setRenderSurface()
379 */
380
381TEST_F(OutputTest, setRenderSurfaceResetsBounds) {
382 const ui::Size newDisplaySize{640, 480};
383
384 mock::RenderSurface* renderSurface = new StrictMock<mock::RenderSurface>();
385 EXPECT_CALL(*renderSurface, getSize()).WillOnce(ReturnRef(newDisplaySize));
386
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700387 mOutput->setRenderSurface(std::unique_ptr<RenderSurface>(renderSurface));
Lloyd Pique31cb2942018-10-19 17:23:03 -0700388
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700389 EXPECT_EQ(Rect(newDisplaySize), mOutput->getState().bounds);
Lloyd Pique31cb2942018-10-19 17:23:03 -0700390}
391
Lloyd Pique66d68602019-02-13 14:23:31 -0800392/*
Alec Mourie7d1d4a2019-02-05 01:13:46 +0000393 * Output::getDirtyRegion()
Lloyd Pique32cbe282018-10-19 13:09:22 -0700394 */
395
Alec Mourie7d1d4a2019-02-05 01:13:46 +0000396TEST_F(OutputTest, getDirtyRegionWithRepaintEverythingTrue) {
397 const Rect viewport{100, 200};
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700398 mOutput->editState().viewport = viewport;
399 mOutput->editState().dirtyRegion.set(50, 300);
Lloyd Pique32cbe282018-10-19 13:09:22 -0700400
401 {
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700402 Region result = mOutput->getDirtyRegion(true);
Lloyd Pique32cbe282018-10-19 13:09:22 -0700403
Alec Mourie7d1d4a2019-02-05 01:13:46 +0000404 EXPECT_THAT(result, RegionEq(Region(viewport)));
Lloyd Pique32cbe282018-10-19 13:09:22 -0700405 }
406}
407
Alec Mourie7d1d4a2019-02-05 01:13:46 +0000408TEST_F(OutputTest, getDirtyRegionWithRepaintEverythingFalse) {
409 const Rect viewport{100, 200};
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700410 mOutput->editState().viewport = viewport;
411 mOutput->editState().dirtyRegion.set(50, 300);
Lloyd Pique32cbe282018-10-19 13:09:22 -0700412
413 {
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700414 Region result = mOutput->getDirtyRegion(false);
Lloyd Pique32cbe282018-10-19 13:09:22 -0700415
416 // The dirtyRegion should be clipped to the display bounds.
417 EXPECT_THAT(result, RegionEq(Region(Rect(50, 200))));
418 }
Lloyd Pique32cbe282018-10-19 13:09:22 -0700419}
420
Lloyd Pique66d68602019-02-13 14:23:31 -0800421/*
Lloyd Piqueef36b002019-01-23 17:52:04 -0800422 * Output::belongsInOutput()
423 */
424
425TEST_F(OutputTest, belongsInOutputFiltersAsExpected) {
426 const uint32_t layerStack1 = 123u;
427 const uint32_t layerStack2 = 456u;
428
429 // If the output accepts layerStack1 and internal-only layers....
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700430 mOutput->setLayerStackFilter(layerStack1, true);
Lloyd Piqueef36b002019-01-23 17:52:04 -0800431
Lloyd Piquec6687342019-03-07 21:34:57 -0800432 // A layer with no layerStack does not belong to it, internal-only or not.
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700433 EXPECT_FALSE(mOutput->belongsInOutput(std::nullopt, false));
434 EXPECT_FALSE(mOutput->belongsInOutput(std::nullopt, true));
Lloyd Piquec6687342019-03-07 21:34:57 -0800435
Lloyd Piqueef36b002019-01-23 17:52:04 -0800436 // Any layer with layerStack1 belongs to it, internal-only or not.
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700437 EXPECT_TRUE(mOutput->belongsInOutput(layerStack1, false));
438 EXPECT_TRUE(mOutput->belongsInOutput(layerStack1, true));
439 EXPECT_FALSE(mOutput->belongsInOutput(layerStack2, true));
440 EXPECT_FALSE(mOutput->belongsInOutput(layerStack2, false));
Lloyd Piqueef36b002019-01-23 17:52:04 -0800441
442 // If the output accepts layerStack21 but not internal-only layers...
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700443 mOutput->setLayerStackFilter(layerStack1, false);
Lloyd Piqueef36b002019-01-23 17:52:04 -0800444
445 // Only non-internal layers with layerStack1 belong to it.
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700446 EXPECT_TRUE(mOutput->belongsInOutput(layerStack1, false));
447 EXPECT_FALSE(mOutput->belongsInOutput(layerStack1, true));
448 EXPECT_FALSE(mOutput->belongsInOutput(layerStack2, true));
449 EXPECT_FALSE(mOutput->belongsInOutput(layerStack2, false));
Lloyd Piqueef36b002019-01-23 17:52:04 -0800450}
451
Lloyd Pique66c20c42019-03-07 21:44:02 -0800452TEST_F(OutputTest, belongsInOutputFiltersLayersAsExpected) {
453 StrictMock<mock::Layer> layer;
Lloyd Pique9755fb72019-03-26 14:44:40 -0700454 LayerFECompositionState layerFEState;
Lloyd Pique66c20c42019-03-07 21:44:02 -0800455
Lloyd Pique9755fb72019-03-26 14:44:40 -0700456 EXPECT_CALL(layer, getFEState()).WillRepeatedly(ReturnRef(layerFEState));
Lloyd Pique66c20c42019-03-07 21:44:02 -0800457
458 const uint32_t layerStack1 = 123u;
459 const uint32_t layerStack2 = 456u;
460
461 // If the output accepts layerStack1 and internal-only layers....
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700462 mOutput->setLayerStackFilter(layerStack1, true);
Lloyd Pique66c20c42019-03-07 21:44:02 -0800463
464 // A null layer pointer does not belong to the output
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700465 EXPECT_FALSE(mOutput->belongsInOutput(nullptr));
Lloyd Pique66c20c42019-03-07 21:44:02 -0800466
467 // A layer with no layerStack does not belong to it, internal-only or not.
Lloyd Pique9755fb72019-03-26 14:44:40 -0700468 layerFEState.layerStackId = std::nullopt;
469 layerFEState.internalOnly = false;
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700470 EXPECT_FALSE(mOutput->belongsInOutput(&layer));
Lloyd Pique66c20c42019-03-07 21:44:02 -0800471
Lloyd Pique9755fb72019-03-26 14:44:40 -0700472 layerFEState.layerStackId = std::nullopt;
473 layerFEState.internalOnly = true;
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700474 EXPECT_FALSE(mOutput->belongsInOutput(&layer));
Lloyd Pique66c20c42019-03-07 21:44:02 -0800475
476 // Any layer with layerStack1 belongs to it, internal-only or not.
Lloyd Pique9755fb72019-03-26 14:44:40 -0700477 layerFEState.layerStackId = layerStack1;
478 layerFEState.internalOnly = false;
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700479 EXPECT_TRUE(mOutput->belongsInOutput(&layer));
Lloyd Pique66c20c42019-03-07 21:44:02 -0800480
Lloyd Pique9755fb72019-03-26 14:44:40 -0700481 layerFEState.layerStackId = layerStack1;
482 layerFEState.internalOnly = true;
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700483 EXPECT_TRUE(mOutput->belongsInOutput(&layer));
Lloyd Pique66c20c42019-03-07 21:44:02 -0800484
Lloyd Pique9755fb72019-03-26 14:44:40 -0700485 layerFEState.layerStackId = layerStack2;
486 layerFEState.internalOnly = true;
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700487 EXPECT_FALSE(mOutput->belongsInOutput(&layer));
Lloyd Pique66c20c42019-03-07 21:44:02 -0800488
Lloyd Pique9755fb72019-03-26 14:44:40 -0700489 layerFEState.layerStackId = layerStack2;
490 layerFEState.internalOnly = false;
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700491 EXPECT_FALSE(mOutput->belongsInOutput(&layer));
Lloyd Pique66c20c42019-03-07 21:44:02 -0800492
493 // If the output accepts layerStack1 but not internal-only layers...
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700494 mOutput->setLayerStackFilter(layerStack1, false);
Lloyd Pique66c20c42019-03-07 21:44:02 -0800495
496 // A null layer pointer does not belong to the output
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700497 EXPECT_FALSE(mOutput->belongsInOutput(nullptr));
Lloyd Pique66c20c42019-03-07 21:44:02 -0800498
499 // Only non-internal layers with layerStack1 belong to it.
Lloyd Pique9755fb72019-03-26 14:44:40 -0700500 layerFEState.layerStackId = layerStack1;
501 layerFEState.internalOnly = false;
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700502 EXPECT_TRUE(mOutput->belongsInOutput(&layer));
Lloyd Pique66c20c42019-03-07 21:44:02 -0800503
Lloyd Pique9755fb72019-03-26 14:44:40 -0700504 layerFEState.layerStackId = layerStack1;
505 layerFEState.internalOnly = true;
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700506 EXPECT_FALSE(mOutput->belongsInOutput(&layer));
Lloyd Pique66c20c42019-03-07 21:44:02 -0800507
Lloyd Pique9755fb72019-03-26 14:44:40 -0700508 layerFEState.layerStackId = layerStack2;
509 layerFEState.internalOnly = true;
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700510 EXPECT_FALSE(mOutput->belongsInOutput(&layer));
Lloyd Pique66c20c42019-03-07 21:44:02 -0800511
Lloyd Pique9755fb72019-03-26 14:44:40 -0700512 layerFEState.layerStackId = layerStack2;
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}
516
Lloyd Pique66d68602019-02-13 14:23:31 -0800517/*
Lloyd Piquecc01a452018-12-04 17:24:00 -0800518 * Output::getOutputLayerForLayer()
519 */
520
521TEST_F(OutputTest, getOutputLayerForLayerWorks) {
522 mock::OutputLayer* outputLayer1 = new StrictMock<mock::OutputLayer>();
523 mock::OutputLayer* outputLayer2 = new StrictMock<mock::OutputLayer>();
524
Lloyd Pique01c77c12019-04-17 12:48:32 -0700525 mOutput->injectOutputLayerForTest(std::unique_ptr<OutputLayer>(outputLayer1));
526 mOutput->injectOutputLayerForTest(nullptr);
527 mOutput->injectOutputLayerForTest(std::unique_ptr<OutputLayer>(outputLayer2));
Lloyd Piquecc01a452018-12-04 17:24:00 -0800528
529 StrictMock<mock::Layer> layer;
530 StrictMock<mock::Layer> otherLayer;
531
532 // If the input layer matches the first OutputLayer, it will be returned.
533 EXPECT_CALL(*outputLayer1, getLayer()).WillOnce(ReturnRef(layer));
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700534 EXPECT_EQ(outputLayer1, mOutput->getOutputLayerForLayer(&layer));
Lloyd Piquecc01a452018-12-04 17:24:00 -0800535
536 // If the input layer matches the second OutputLayer, it will be returned.
537 EXPECT_CALL(*outputLayer1, getLayer()).WillOnce(ReturnRef(otherLayer));
538 EXPECT_CALL(*outputLayer2, getLayer()).WillOnce(ReturnRef(layer));
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700539 EXPECT_EQ(outputLayer2, mOutput->getOutputLayerForLayer(&layer));
Lloyd Piquecc01a452018-12-04 17:24:00 -0800540
541 // If the input layer does not match an output layer, null will be returned.
542 EXPECT_CALL(*outputLayer1, getLayer()).WillOnce(ReturnRef(otherLayer));
543 EXPECT_CALL(*outputLayer2, getLayer()).WillOnce(ReturnRef(otherLayer));
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700544 EXPECT_EQ(nullptr, mOutput->getOutputLayerForLayer(&layer));
Lloyd Piquecc01a452018-12-04 17:24:00 -0800545}
546
Lloyd Pique66d68602019-02-13 14:23:31 -0800547/*
Lloyd Piquec9e60032019-11-14 11:47:26 -0800548 * Output::setReleasedLayers()
549 */
550
551using OutputSetReleasedLayersTest = OutputTest;
552
553TEST_F(OutputSetReleasedLayersTest, setReleasedLayersTakesGivenLayers) {
554 sp<StrictMock<mock::LayerFE>> layer1FE{new StrictMock<mock::LayerFE>()};
555 sp<StrictMock<mock::LayerFE>> layer2FE{new StrictMock<mock::LayerFE>()};
556 sp<StrictMock<mock::LayerFE>> layer3FE{new StrictMock<mock::LayerFE>()};
557
558 Output::ReleasedLayers layers;
559 layers.push_back(layer1FE);
560 layers.push_back(layer2FE);
561 layers.push_back(layer3FE);
562
563 mOutput->setReleasedLayers(std::move(layers));
564
565 const auto& setLayers = mOutput->getReleasedLayersForTest();
566 ASSERT_EQ(3u, setLayers.size());
567 ASSERT_EQ(layer1FE.get(), setLayers[0].promote().get());
568 ASSERT_EQ(layer2FE.get(), setLayers[1].promote().get());
569 ASSERT_EQ(layer3FE.get(), setLayers[2].promote().get());
570}
571
572/*
Alec Mourif9a2a2c2019-11-12 12:46:02 -0800573 * Output::updateAndWriteCompositionState()
574 */
575
576TEST_F(OutputTest, updateAndWriteCompositionState_takesEarlyOutIfNotEnabled) {
577 mOutput->editState().isEnabled = false;
578
579 CompositionRefreshArgs args;
580 mOutput->updateAndWriteCompositionState(args);
581}
582
583TEST_F(OutputTest, updateAndWriteCompositionState_updatesLayers) {
584 mOutput->editState().isEnabled = true;
585 mock::OutputLayer* outputLayer = new StrictMock<mock::OutputLayer>();
586 mOutput->injectOutputLayerForTest(std::unique_ptr<OutputLayer>(outputLayer));
587
588 EXPECT_CALL(*outputLayer, updateCompositionState(true, true)).Times(1);
589 EXPECT_CALL(*outputLayer, writeStateToHWC(true)).Times(1);
590
591 CompositionRefreshArgs args;
592 args.updatingGeometryThisFrame = true;
593 args.devOptForceClientComposition = true;
594 mOutput->updateAndWriteCompositionState(args);
595}
596
597/*
Lloyd Pique66d68602019-02-13 14:23:31 -0800598 * Output::prepareFrame()
599 */
600
601struct OutputPrepareFrameTest : public testing::Test {
Lloyd Piquefaa3f192019-11-14 14:05:09 -0800602 struct OutputPartialMock : public OutputPartialMockBase {
Lloyd Pique66d68602019-02-13 14:23:31 -0800603 // Sets up the helper functions called by prepareFrame to use a mock
604 // implementations.
605 MOCK_METHOD0(chooseCompositionStrategy, void());
606 };
607
608 OutputPrepareFrameTest() {
609 mOutput.setDisplayColorProfileForTest(
610 std::unique_ptr<DisplayColorProfile>(mDisplayColorProfile));
611 mOutput.setRenderSurfaceForTest(std::unique_ptr<RenderSurface>(mRenderSurface));
612 }
613
614 StrictMock<mock::CompositionEngine> mCompositionEngine;
615 mock::DisplayColorProfile* mDisplayColorProfile = new StrictMock<mock::DisplayColorProfile>();
616 mock::RenderSurface* mRenderSurface = new StrictMock<mock::RenderSurface>();
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700617 StrictMock<OutputPartialMock> mOutput;
Lloyd Pique66d68602019-02-13 14:23:31 -0800618};
619
620TEST_F(OutputPrepareFrameTest, takesEarlyOutIfNotEnabled) {
621 mOutput.editState().isEnabled = false;
622
623 mOutput.prepareFrame();
624}
625
626TEST_F(OutputPrepareFrameTest, delegatesToChooseCompositionStrategyAndRenderSurface) {
627 mOutput.editState().isEnabled = true;
628 mOutput.editState().usesClientComposition = false;
629 mOutput.editState().usesDeviceComposition = true;
630
631 EXPECT_CALL(mOutput, chooseCompositionStrategy()).Times(1);
632 EXPECT_CALL(*mRenderSurface, prepareFrame(false, true));
633
634 mOutput.prepareFrame();
635}
636
637// Note: Use OutputTest and not OutputPrepareFrameTest, so the real
638// base chooseCompositionStrategy() is invoked.
639TEST_F(OutputTest, prepareFrameSetsClientCompositionOnlyByDefault) {
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700640 mOutput->editState().isEnabled = true;
641 mOutput->editState().usesClientComposition = false;
642 mOutput->editState().usesDeviceComposition = true;
Lloyd Pique66d68602019-02-13 14:23:31 -0800643
644 EXPECT_CALL(*mRenderSurface, prepareFrame(true, false));
645
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700646 mOutput->prepareFrame();
Lloyd Pique66d68602019-02-13 14:23:31 -0800647
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700648 EXPECT_TRUE(mOutput->getState().usesClientComposition);
649 EXPECT_FALSE(mOutput->getState().usesDeviceComposition);
Lloyd Pique66d68602019-02-13 14:23:31 -0800650}
651
Lloyd Pique56eba802019-08-28 15:45:25 -0700652/*
Lloyd Piquefaa3f192019-11-14 14:05:09 -0800653 * Output::present()
654 */
655
656struct OutputPresentTest : public testing::Test {
657 struct OutputPartialMock : public OutputPartialMockBase {
658 // All child helper functions Output::present() are defined as mocks,
659 // and those are tested separately, allowing the present() test to
660 // just cover the high level flow.
661 MOCK_METHOD1(updateColorProfile, void(const compositionengine::CompositionRefreshArgs&));
662 MOCK_METHOD1(updateAndWriteCompositionState,
663 void(const compositionengine::CompositionRefreshArgs&));
664 MOCK_METHOD1(setColorTransform, void(const compositionengine::CompositionRefreshArgs&));
665 MOCK_METHOD0(beginFrame, void());
666 MOCK_METHOD0(prepareFrame, void());
667 MOCK_METHOD1(devOptRepaintFlash, void(const compositionengine::CompositionRefreshArgs&));
668 MOCK_METHOD1(finishFrame, void(const compositionengine::CompositionRefreshArgs&));
669 MOCK_METHOD0(postFramebuffer, void());
670 };
671
672 StrictMock<OutputPartialMock> mOutput;
673};
674
675TEST_F(OutputPresentTest, justInvokesChildFunctionsInSequence) {
676 CompositionRefreshArgs args;
677
678 InSequence seq;
679 EXPECT_CALL(mOutput, updateColorProfile(Ref(args)));
680 EXPECT_CALL(mOutput, updateAndWriteCompositionState(Ref(args)));
681 EXPECT_CALL(mOutput, setColorTransform(Ref(args)));
682 EXPECT_CALL(mOutput, beginFrame());
683 EXPECT_CALL(mOutput, prepareFrame());
684 EXPECT_CALL(mOutput, devOptRepaintFlash(Ref(args)));
685 EXPECT_CALL(mOutput, finishFrame(Ref(args)));
686 EXPECT_CALL(mOutput, postFramebuffer());
687
688 mOutput.present(args);
689}
690
691/*
692 * Output::updateColorProfile()
693 */
694
Lloyd Pique17ca7422019-11-14 14:24:10 -0800695struct OutputUpdateColorProfileTest : public testing::Test {
696 using TestType = OutputUpdateColorProfileTest;
697
698 struct OutputPartialMock : public OutputPartialMockBase {
699 // All child helper functions Output::present() are defined as mocks,
700 // and those are tested separately, allowing the present() test to
701 // just cover the high level flow.
702 MOCK_METHOD1(setColorProfile, void(const ColorProfile&));
703 };
704
705 struct Layer {
706 Layer() {
707 EXPECT_CALL(mOutputLayer, getLayer()).WillRepeatedly(ReturnRef(mLayer));
708 EXPECT_CALL(mOutputLayer, getLayerFE()).WillRepeatedly(ReturnRef(mLayerFE));
709 EXPECT_CALL(mLayer, getFEState()).WillRepeatedly(ReturnRef(mLayerFEState));
710 }
711
712 StrictMock<mock::OutputLayer> mOutputLayer;
713 StrictMock<mock::Layer> mLayer;
714 StrictMock<mock::LayerFE> mLayerFE;
715 LayerFECompositionState mLayerFEState;
716 };
717
718 OutputUpdateColorProfileTest() {
719 mOutput.setDisplayColorProfileForTest(
720 std::unique_ptr<DisplayColorProfile>(mDisplayColorProfile));
721 mOutput.setRenderSurfaceForTest(std::unique_ptr<RenderSurface>(mRenderSurface));
722
723 EXPECT_CALL(mOutput, getOutputLayerOrderedByZByIndex(0))
724 .WillRepeatedly(Return(&mLayer1.mOutputLayer));
725 EXPECT_CALL(mOutput, getOutputLayerOrderedByZByIndex(1))
726 .WillRepeatedly(Return(&mLayer2.mOutputLayer));
727 EXPECT_CALL(mOutput, getOutputLayerOrderedByZByIndex(2))
728 .WillRepeatedly(Return(&mLayer3.mOutputLayer));
729 }
730
731 struct ExecuteState : public CallOrderStateMachineHelper<TestType, ExecuteState> {
732 void execute() { getInstance()->mOutput.updateColorProfile(getInstance()->mRefreshArgs); }
733 };
734
735 mock::DisplayColorProfile* mDisplayColorProfile = new StrictMock<mock::DisplayColorProfile>();
736 mock::RenderSurface* mRenderSurface = new StrictMock<mock::RenderSurface>();
737 StrictMock<OutputPartialMock> mOutput;
738
739 Layer mLayer1;
740 Layer mLayer2;
741 Layer mLayer3;
742
743 CompositionRefreshArgs mRefreshArgs;
744};
745
746// TODO(b/144522012): Refactor Output::updateColorProfile and the related code
747// to make it easier to write unit tests.
748
749TEST_F(OutputUpdateColorProfileTest, setsAColorProfileWhenUnmanaged) {
750 // When the outputColorSetting is set to kUnmanaged, the implementation sets
751 // a simple default color profile without looking at anything else.
752
753 EXPECT_CALL(mOutput, getOutputLayerCount()).WillRepeatedly(Return(3));
754 EXPECT_CALL(mOutput,
755 setColorProfile(ColorProfileEq(
756 ColorProfile{ui::ColorMode::NATIVE, ui::Dataspace::UNKNOWN,
757 ui::RenderIntent::COLORIMETRIC, ui::Dataspace::UNKNOWN})));
758
759 mRefreshArgs.outputColorSetting = OutputColorSetting::kUnmanaged;
760 mRefreshArgs.colorSpaceAgnosticDataspace = ui::Dataspace::UNKNOWN;
761
762 mOutput.updateColorProfile(mRefreshArgs);
763}
764
765struct OutputUpdateColorProfileTest_GetBestColorModeResultBecomesSetProfile
766 : public OutputUpdateColorProfileTest {
767 OutputUpdateColorProfileTest_GetBestColorModeResultBecomesSetProfile() {
768 EXPECT_CALL(mOutput, getOutputLayerCount()).WillRepeatedly(Return(0));
769 mRefreshArgs.outputColorSetting = OutputColorSetting::kEnhanced;
770 mRefreshArgs.colorSpaceAgnosticDataspace = ui::Dataspace::UNKNOWN;
771 }
772
773 struct ExpectBestColorModeCallResultUsedToSetColorProfileState
774 : public CallOrderStateMachineHelper<
775 TestType, ExpectBestColorModeCallResultUsedToSetColorProfileState> {
776 [[nodiscard]] auto expectBestColorModeCallResultUsedToSetColorProfile(
777 ui::ColorMode colorMode, ui::Dataspace dataspace, ui::RenderIntent renderIntent) {
778 EXPECT_CALL(*getInstance()->mDisplayColorProfile,
779 getBestColorMode(ui::Dataspace::V0_SRGB, ui::RenderIntent::ENHANCE, _, _,
780 _))
781 .WillOnce(DoAll(SetArgPointee<2>(dataspace), SetArgPointee<3>(colorMode),
782 SetArgPointee<4>(renderIntent)));
783 EXPECT_CALL(getInstance()->mOutput,
784 setColorProfile(
785 ColorProfileEq(ColorProfile{colorMode, dataspace, renderIntent,
786 ui::Dataspace::UNKNOWN})));
787 return nextState<ExecuteState>();
788 }
789 };
790
791 // Call this member function to start using the mini-DSL defined above.
792 [[nodiscard]] auto verify() {
793 return ExpectBestColorModeCallResultUsedToSetColorProfileState::make(this);
794 }
795};
796
797TEST_F(OutputUpdateColorProfileTest_GetBestColorModeResultBecomesSetProfile,
798 Native_Unknown_Colorimetric_Set) {
799 verify().expectBestColorModeCallResultUsedToSetColorProfile(ui::ColorMode::NATIVE,
800 ui::Dataspace::UNKNOWN,
801 ui::RenderIntent::COLORIMETRIC)
802 .execute();
803}
804
805TEST_F(OutputUpdateColorProfileTest_GetBestColorModeResultBecomesSetProfile,
806 DisplayP3_DisplayP3_Enhance_Set) {
807 verify().expectBestColorModeCallResultUsedToSetColorProfile(ui::ColorMode::DISPLAY_P3,
808 ui::Dataspace::DISPLAY_P3,
809 ui::RenderIntent::ENHANCE)
810 .execute();
811}
812
813struct OutputUpdateColorProfileTest_ColorSpaceAgnosticeDataspaceAffectsSetColorProfile
814 : public OutputUpdateColorProfileTest {
815 OutputUpdateColorProfileTest_ColorSpaceAgnosticeDataspaceAffectsSetColorProfile() {
816 EXPECT_CALL(mOutput, getOutputLayerCount()).WillRepeatedly(Return(0));
817 EXPECT_CALL(*mDisplayColorProfile,
818 getBestColorMode(ui::Dataspace::V0_SRGB, ui::RenderIntent::ENHANCE, _, _, _))
819 .WillRepeatedly(DoAll(SetArgPointee<2>(ui::Dataspace::UNKNOWN),
820 SetArgPointee<3>(ui::ColorMode::NATIVE),
821 SetArgPointee<4>(ui::RenderIntent::COLORIMETRIC)));
822 mRefreshArgs.outputColorSetting = OutputColorSetting::kEnhanced;
823 }
824
825 struct IfColorSpaceAgnosticDataspaceSetToState
826 : public CallOrderStateMachineHelper<TestType, IfColorSpaceAgnosticDataspaceSetToState> {
827 [[nodiscard]] auto ifColorSpaceAgnosticDataspaceSetTo(ui::Dataspace dataspace) {
828 getInstance()->mRefreshArgs.colorSpaceAgnosticDataspace = dataspace;
829 return nextState<ThenExpectSetColorProfileCallUsesColorSpaceAgnosticDataspaceState>();
830 }
831 };
832
833 struct ThenExpectSetColorProfileCallUsesColorSpaceAgnosticDataspaceState
834 : public CallOrderStateMachineHelper<
835 TestType, ThenExpectSetColorProfileCallUsesColorSpaceAgnosticDataspaceState> {
836 [[nodiscard]] auto thenExpectSetColorProfileCallUsesColorSpaceAgnosticDataspace(
837 ui::Dataspace dataspace) {
838 EXPECT_CALL(getInstance()->mOutput,
839 setColorProfile(ColorProfileEq(
840 ColorProfile{ui::ColorMode::NATIVE, ui::Dataspace::UNKNOWN,
841 ui::RenderIntent::COLORIMETRIC, dataspace})));
842 return nextState<ExecuteState>();
843 }
844 };
845
846 // Call this member function to start using the mini-DSL defined above.
847 [[nodiscard]] auto verify() { return IfColorSpaceAgnosticDataspaceSetToState::make(this); }
848};
849
850TEST_F(OutputUpdateColorProfileTest_ColorSpaceAgnosticeDataspaceAffectsSetColorProfile, DisplayP3) {
851 verify().ifColorSpaceAgnosticDataspaceSetTo(ui::Dataspace::DISPLAY_P3)
852 .thenExpectSetColorProfileCallUsesColorSpaceAgnosticDataspace(ui::Dataspace::DISPLAY_P3)
853 .execute();
854}
855
856TEST_F(OutputUpdateColorProfileTest_ColorSpaceAgnosticeDataspaceAffectsSetColorProfile, V0_SRGB) {
857 verify().ifColorSpaceAgnosticDataspaceSetTo(ui::Dataspace::V0_SRGB)
858 .thenExpectSetColorProfileCallUsesColorSpaceAgnosticDataspace(ui::Dataspace::V0_SRGB)
859 .execute();
860}
861
862struct OutputUpdateColorProfileTest_TopmostLayerPreferenceSetsOutputPreference
863 : public OutputUpdateColorProfileTest {
864 // Internally the implementation looks through the dataspaces of all the
865 // visible layers. The topmost one that also has an actual dataspace
866 // preference set is used to drive subsequent choices.
867
868 OutputUpdateColorProfileTest_TopmostLayerPreferenceSetsOutputPreference() {
869 mRefreshArgs.outputColorSetting = OutputColorSetting::kEnhanced;
870 mRefreshArgs.colorSpaceAgnosticDataspace = ui::Dataspace::UNKNOWN;
871
872 EXPECT_CALL(mOutput, getOutputLayerCount()).WillRepeatedly(Return(3));
873 EXPECT_CALL(mOutput, setColorProfile(_)).WillRepeatedly(Return());
874 }
875
876 struct IfTopLayerDataspaceState
877 : public CallOrderStateMachineHelper<TestType, IfTopLayerDataspaceState> {
878 [[nodiscard]] auto ifTopLayerIs(ui::Dataspace dataspace) {
879 getInstance()->mLayer3.mLayerFEState.dataspace = dataspace;
880 return nextState<AndIfMiddleLayerDataspaceState>();
881 }
882 [[nodiscard]] auto ifTopLayerHasNoPreference() {
883 return ifTopLayerIs(ui::Dataspace::UNKNOWN);
884 }
885 };
886
887 struct AndIfMiddleLayerDataspaceState
888 : public CallOrderStateMachineHelper<TestType, AndIfMiddleLayerDataspaceState> {
889 [[nodiscard]] auto andIfMiddleLayerIs(ui::Dataspace dataspace) {
890 getInstance()->mLayer2.mLayerFEState.dataspace = dataspace;
891 return nextState<AndIfBottomLayerDataspaceState>();
892 }
893 [[nodiscard]] auto andIfMiddleLayerHasNoPreference() {
894 return andIfMiddleLayerIs(ui::Dataspace::UNKNOWN);
895 }
896 };
897
898 struct AndIfBottomLayerDataspaceState
899 : public CallOrderStateMachineHelper<TestType, AndIfBottomLayerDataspaceState> {
900 [[nodiscard]] auto andIfBottomLayerIs(ui::Dataspace dataspace) {
901 getInstance()->mLayer1.mLayerFEState.dataspace = dataspace;
902 return nextState<ThenExpectBestColorModeCallUsesState>();
903 }
904 [[nodiscard]] auto andIfBottomLayerHasNoPreference() {
905 return andIfBottomLayerIs(ui::Dataspace::UNKNOWN);
906 }
907 };
908
909 struct ThenExpectBestColorModeCallUsesState
910 : public CallOrderStateMachineHelper<TestType, ThenExpectBestColorModeCallUsesState> {
911 [[nodiscard]] auto thenExpectBestColorModeCallUses(ui::Dataspace dataspace) {
912 EXPECT_CALL(*getInstance()->mDisplayColorProfile,
913 getBestColorMode(dataspace, _, _, _, _));
914 return nextState<ExecuteState>();
915 }
916 };
917
918 // Call this member function to start using the mini-DSL defined above.
919 [[nodiscard]] auto verify() { return IfTopLayerDataspaceState::make(this); }
920};
921
922TEST_F(OutputUpdateColorProfileTest_TopmostLayerPreferenceSetsOutputPreference,
923 noStrongLayerPrefenceUses_V0_SRGB) {
924 // If none of the layers indicate a preference, then V0_SRGB is the
925 // preferred choice (subject to additional checks).
926 verify().ifTopLayerHasNoPreference()
927 .andIfMiddleLayerHasNoPreference()
928 .andIfBottomLayerHasNoPreference()
929 .thenExpectBestColorModeCallUses(ui::Dataspace::V0_SRGB)
930 .execute();
931}
932
933TEST_F(OutputUpdateColorProfileTest_TopmostLayerPreferenceSetsOutputPreference,
934 ifTopmostUses_DisplayP3_Then_DisplayP3_Chosen) {
935 // If only the topmost layer has a preference, then that is what is chosen.
936 verify().ifTopLayerIs(ui::Dataspace::DISPLAY_P3)
937 .andIfMiddleLayerHasNoPreference()
938 .andIfBottomLayerHasNoPreference()
939 .thenExpectBestColorModeCallUses(ui::Dataspace::DISPLAY_P3)
940 .execute();
941}
942
943TEST_F(OutputUpdateColorProfileTest_TopmostLayerPreferenceSetsOutputPreference,
944 ifMiddleUses_DisplayP3_Then_DisplayP3_Chosen) {
945 // If only the middle layer has a preference, that that is what is chosen.
946 verify().ifTopLayerHasNoPreference()
947 .andIfMiddleLayerIs(ui::Dataspace::DISPLAY_P3)
948 .andIfBottomLayerHasNoPreference()
949 .thenExpectBestColorModeCallUses(ui::Dataspace::DISPLAY_P3)
950 .execute();
951}
952
953TEST_F(OutputUpdateColorProfileTest_TopmostLayerPreferenceSetsOutputPreference,
954 ifBottomUses_DisplayP3_Then_DisplayP3_Chosen) {
955 // If only the middle layer has a preference, that that is what is chosen.
956 verify().ifTopLayerHasNoPreference()
957 .andIfMiddleLayerHasNoPreference()
958 .andIfBottomLayerIs(ui::Dataspace::DISPLAY_P3)
959 .thenExpectBestColorModeCallUses(ui::Dataspace::DISPLAY_P3)
960 .execute();
961}
962
963TEST_F(OutputUpdateColorProfileTest_TopmostLayerPreferenceSetsOutputPreference,
964 ifTopUses_DisplayBT2020_AndBottomUses_DisplayP3_Then_DisplayBT2020_Chosen) {
965 // If multiple layers have a preference, the topmost value is what is used.
966 verify().ifTopLayerIs(ui::Dataspace::DISPLAY_BT2020)
967 .andIfMiddleLayerHasNoPreference()
968 .andIfBottomLayerIs(ui::Dataspace::DISPLAY_P3)
969 .thenExpectBestColorModeCallUses(ui::Dataspace::DISPLAY_BT2020)
970 .execute();
971}
972
973TEST_F(OutputUpdateColorProfileTest_TopmostLayerPreferenceSetsOutputPreference,
974 ifTopUses_DisplayP3_AndBottomUses_V0_SRGB_Then_DisplayP3_Chosen) {
975 // If multiple layers have a preference, the topmost value is what is used.
976 verify().ifTopLayerIs(ui::Dataspace::DISPLAY_P3)
977 .andIfMiddleLayerHasNoPreference()
978 .andIfBottomLayerIs(ui::Dataspace::DISPLAY_BT2020)
979 .thenExpectBestColorModeCallUses(ui::Dataspace::DISPLAY_P3)
980 .execute();
981}
982
983struct OutputUpdateColorProfileTest_ForceOutputColorOverrides
984 : public OutputUpdateColorProfileTest {
985 // If CompositionRefreshArgs::forceOutputColorMode is set to some specific
986 // values, it overrides the layer dataspace choice.
987
988 OutputUpdateColorProfileTest_ForceOutputColorOverrides() {
989 mRefreshArgs.outputColorSetting = OutputColorSetting::kEnhanced;
990 mRefreshArgs.colorSpaceAgnosticDataspace = ui::Dataspace::UNKNOWN;
991
992 mLayer1.mLayerFEState.dataspace = ui::Dataspace::DISPLAY_BT2020;
993
994 EXPECT_CALL(mOutput, getOutputLayerCount()).WillRepeatedly(Return(1));
995 EXPECT_CALL(mOutput, setColorProfile(_)).WillRepeatedly(Return());
996 }
997
998 struct IfForceOutputColorModeState
999 : public CallOrderStateMachineHelper<TestType, IfForceOutputColorModeState> {
1000 [[nodiscard]] auto ifForceOutputColorMode(ui::ColorMode colorMode) {
1001 getInstance()->mRefreshArgs.forceOutputColorMode = colorMode;
1002 return nextState<ThenExpectBestColorModeCallUsesState>();
1003 }
1004 [[nodiscard]] auto ifNoOverride() { return ifForceOutputColorMode(ui::ColorMode::NATIVE); }
1005 };
1006
1007 struct ThenExpectBestColorModeCallUsesState
1008 : public CallOrderStateMachineHelper<TestType, ThenExpectBestColorModeCallUsesState> {
1009 [[nodiscard]] auto thenExpectBestColorModeCallUses(ui::Dataspace dataspace) {
1010 EXPECT_CALL(*getInstance()->mDisplayColorProfile,
1011 getBestColorMode(dataspace, _, _, _, _));
1012 return nextState<ExecuteState>();
1013 }
1014 };
1015
1016 // Call this member function to start using the mini-DSL defined above.
1017 [[nodiscard]] auto verify() { return IfForceOutputColorModeState::make(this); }
1018};
1019
1020TEST_F(OutputUpdateColorProfileTest_ForceOutputColorOverrides, NoOverride_DoesNotOverride) {
1021 // By default the layer state is used to set the preferred dataspace
1022 verify().ifNoOverride()
1023 .thenExpectBestColorModeCallUses(ui::Dataspace::DISPLAY_BT2020)
1024 .execute();
1025}
1026
1027TEST_F(OutputUpdateColorProfileTest_ForceOutputColorOverrides, SRGB_Override_USES_V0_SRGB) {
1028 // Setting ui::ColorMode::SRGB overrides it with ui::Dataspace::V0_SRGB
1029 verify().ifForceOutputColorMode(ui::ColorMode::SRGB)
1030 .thenExpectBestColorModeCallUses(ui::Dataspace::V0_SRGB)
1031 .execute();
1032}
1033
1034TEST_F(OutputUpdateColorProfileTest_ForceOutputColorOverrides, DisplayP3_Override_Uses_DisplayP3) {
1035 // Setting ui::ColorMode::DISPLAY_P3 overrides it with ui::Dataspace::DISPLAY_P3
1036 verify().ifForceOutputColorMode(ui::ColorMode::DISPLAY_P3)
1037 .thenExpectBestColorModeCallUses(ui::Dataspace::DISPLAY_P3)
1038 .execute();
1039}
1040
1041// HDR output requires all layers to be compatible with the chosen HDR
1042// dataspace, along with there being proper support.
1043struct OutputUpdateColorProfileTest_Hdr : public OutputUpdateColorProfileTest {
1044 OutputUpdateColorProfileTest_Hdr() {
1045 mRefreshArgs.outputColorSetting = OutputColorSetting::kEnhanced;
1046 mRefreshArgs.colorSpaceAgnosticDataspace = ui::Dataspace::UNKNOWN;
1047 EXPECT_CALL(mOutput, getOutputLayerCount()).WillRepeatedly(Return(2));
1048 EXPECT_CALL(mOutput, setColorProfile(_)).WillRepeatedly(Return());
1049 }
1050
1051 static constexpr ui::Dataspace kNonHdrDataspace = ui::Dataspace::DISPLAY_P3;
1052 static constexpr ui::Dataspace BT2020_PQ = ui::Dataspace::BT2020_PQ;
1053 static constexpr ui::Dataspace BT2020_HLG = ui::Dataspace::BT2020_HLG;
1054 static constexpr ui::Dataspace DISPLAY_P3 = ui::Dataspace::DISPLAY_P3;
1055
1056 struct IfTopLayerDataspaceState
1057 : public CallOrderStateMachineHelper<TestType, IfTopLayerDataspaceState> {
1058 [[nodiscard]] auto ifTopLayerIs(ui::Dataspace dataspace) {
1059 getInstance()->mLayer2.mLayerFEState.dataspace = dataspace;
1060 return nextState<AndTopLayerCompositionTypeState>();
1061 }
1062 [[nodiscard]] auto ifTopLayerIsNotHdr() { return ifTopLayerIs(kNonHdrDataspace); }
1063 };
1064
1065 struct AndTopLayerCompositionTypeState
1066 : public CallOrderStateMachineHelper<TestType, AndTopLayerCompositionTypeState> {
1067 [[nodiscard]] auto andTopLayerIsREComposed(bool renderEngineComposed) {
1068 getInstance()->mLayer2.mLayerFEState.forceClientComposition = renderEngineComposed;
1069 return nextState<AndIfBottomLayerDataspaceState>();
1070 }
1071 };
1072
1073 struct AndIfBottomLayerDataspaceState
1074 : public CallOrderStateMachineHelper<TestType, AndIfBottomLayerDataspaceState> {
1075 [[nodiscard]] auto andIfBottomLayerIs(ui::Dataspace dataspace) {
1076 getInstance()->mLayer1.mLayerFEState.dataspace = dataspace;
1077 return nextState<AndBottomLayerCompositionTypeState>();
1078 }
1079 [[nodiscard]] auto andIfBottomLayerIsNotHdr() {
1080 return andIfBottomLayerIs(kNonHdrDataspace);
1081 }
1082 };
1083
1084 struct AndBottomLayerCompositionTypeState
1085 : public CallOrderStateMachineHelper<TestType, AndBottomLayerCompositionTypeState> {
1086 [[nodiscard]] auto andBottomLayerIsREComposed(bool renderEngineComposed) {
1087 getInstance()->mLayer1.mLayerFEState.forceClientComposition = renderEngineComposed;
1088 return nextState<AndIfHasLegacySupportState>();
1089 }
1090 };
1091
1092 struct AndIfHasLegacySupportState
1093 : public CallOrderStateMachineHelper<TestType, AndIfHasLegacySupportState> {
1094 [[nodiscard]] auto andIfLegacySupportFor(ui::Dataspace dataspace, bool legacySupport) {
1095 EXPECT_CALL(*getInstance()->mDisplayColorProfile, hasLegacyHdrSupport(dataspace))
1096 .WillOnce(Return(legacySupport));
1097 return nextState<ThenExpectBestColorModeCallUsesState>();
1098 }
1099 };
1100
1101 struct ThenExpectBestColorModeCallUsesState
1102 : public CallOrderStateMachineHelper<TestType, ThenExpectBestColorModeCallUsesState> {
1103 [[nodiscard]] auto thenExpectBestColorModeCallUses(ui::Dataspace dataspace) {
1104 EXPECT_CALL(*getInstance()->mDisplayColorProfile,
1105 getBestColorMode(dataspace, _, _, _, _));
1106 return nextState<ExecuteState>();
1107 }
1108 };
1109
1110 // Call this member function to start using the mini-DSL defined above.
1111 [[nodiscard]] auto verify() { return IfTopLayerDataspaceState::make(this); }
1112};
1113
1114TEST_F(OutputUpdateColorProfileTest_Hdr, PQ_HW_On_PQ_HW_Uses_PQ) {
1115 // If all layers use BT2020_PQ, and there are no other special conditions,
1116 // BT2020_PQ is used.
1117 verify().ifTopLayerIs(BT2020_PQ)
1118 .andTopLayerIsREComposed(false)
1119 .andIfBottomLayerIs(BT2020_PQ)
1120 .andBottomLayerIsREComposed(false)
1121 .andIfLegacySupportFor(BT2020_PQ, false)
1122 .thenExpectBestColorModeCallUses(BT2020_PQ)
1123 .execute();
1124}
1125
1126TEST_F(OutputUpdateColorProfileTest_Hdr, PQ_HW_On_PQ_HW_IfPQHasLegacySupport_Uses_DisplayP3) {
1127 // BT2020_PQ is not used if there is only legacy support for it.
1128 verify().ifTopLayerIs(BT2020_PQ)
1129 .andTopLayerIsREComposed(false)
1130 .andIfBottomLayerIs(BT2020_PQ)
1131 .andBottomLayerIsREComposed(false)
1132 .andIfLegacySupportFor(BT2020_PQ, true)
1133 .thenExpectBestColorModeCallUses(DISPLAY_P3)
1134 .execute();
1135}
1136
1137TEST_F(OutputUpdateColorProfileTest_Hdr, PQ_HW_On_PQ_RE_Uses_PQ) {
1138 // BT2020_PQ is still used if the bottom layer is RenderEngine composed.
1139 verify().ifTopLayerIs(BT2020_PQ)
1140 .andTopLayerIsREComposed(false)
1141 .andIfBottomLayerIs(BT2020_PQ)
1142 .andBottomLayerIsREComposed(true)
1143 .andIfLegacySupportFor(BT2020_PQ, false)
1144 .thenExpectBestColorModeCallUses(BT2020_PQ)
1145 .execute();
1146}
1147
1148TEST_F(OutputUpdateColorProfileTest_Hdr, PQ_RE_On_PQ_HW_Uses_DisplayP3) {
1149 // BT2020_PQ is not used if the top layer is RenderEngine composed.
1150 verify().ifTopLayerIs(BT2020_PQ)
1151 .andTopLayerIsREComposed(true)
1152 .andIfBottomLayerIs(BT2020_PQ)
1153 .andBottomLayerIsREComposed(false)
1154 .andIfLegacySupportFor(BT2020_PQ, false)
1155 .thenExpectBestColorModeCallUses(DISPLAY_P3)
1156 .execute();
1157}
1158
1159TEST_F(OutputUpdateColorProfileTest_Hdr, PQ_HW_On_HLG_HW_Uses_PQ) {
1160 // If there is mixed HLG/PQ use, and the topmost layer is PQ, then PQ is used if there
1161 // are no other special conditions.
1162 verify().ifTopLayerIs(BT2020_PQ)
1163 .andTopLayerIsREComposed(false)
1164 .andIfBottomLayerIs(BT2020_HLG)
1165 .andBottomLayerIsREComposed(false)
1166 .andIfLegacySupportFor(BT2020_PQ, false)
1167 .thenExpectBestColorModeCallUses(BT2020_PQ)
1168 .execute();
1169}
1170
1171TEST_F(OutputUpdateColorProfileTest_Hdr, PQ_HW_On_HLG_HW_IfPQHasLegacySupport_Uses_DisplayP3) {
1172 // BT2020_PQ is not used if there is only legacy support for it.
1173 verify().ifTopLayerIs(BT2020_PQ)
1174 .andTopLayerIsREComposed(false)
1175 .andIfBottomLayerIs(BT2020_HLG)
1176 .andBottomLayerIsREComposed(false)
1177 .andIfLegacySupportFor(BT2020_PQ, true)
1178 .thenExpectBestColorModeCallUses(DISPLAY_P3)
1179 .execute();
1180}
1181
1182TEST_F(OutputUpdateColorProfileTest_Hdr, PQ_HW_On_HLG_RE_Uses_PQ) {
1183 // BT2020_PQ is used if the bottom HLG layer is RenderEngine composed.
1184 verify().ifTopLayerIs(BT2020_PQ)
1185 .andTopLayerIsREComposed(false)
1186 .andIfBottomLayerIs(BT2020_HLG)
1187 .andBottomLayerIsREComposed(true)
1188 .andIfLegacySupportFor(BT2020_PQ, false)
1189 .thenExpectBestColorModeCallUses(BT2020_PQ)
1190 .execute();
1191}
1192
1193TEST_F(OutputUpdateColorProfileTest_Hdr, PQ_RE_On_HLG_HW_Uses_DisplayP3) {
1194 // BT2020_PQ is not used if the top PQ layer is RenderEngine composed.
1195 verify().ifTopLayerIs(BT2020_PQ)
1196 .andTopLayerIsREComposed(true)
1197 .andIfBottomLayerIs(BT2020_HLG)
1198 .andBottomLayerIsREComposed(false)
1199 .andIfLegacySupportFor(BT2020_PQ, false)
1200 .thenExpectBestColorModeCallUses(DISPLAY_P3)
1201 .execute();
1202}
1203
1204TEST_F(OutputUpdateColorProfileTest_Hdr, HLG_HW_On_PQ_HW_Uses_PQ) {
1205 // If there is mixed HLG/PQ use, and the topmost layer is HLG, then PQ is
1206 // used if there are no other special conditions.
1207 verify().ifTopLayerIs(BT2020_HLG)
1208 .andTopLayerIsREComposed(false)
1209 .andIfBottomLayerIs(BT2020_PQ)
1210 .andBottomLayerIsREComposed(false)
1211 .andIfLegacySupportFor(BT2020_PQ, false)
1212 .thenExpectBestColorModeCallUses(BT2020_PQ)
1213 .execute();
1214}
1215
1216TEST_F(OutputUpdateColorProfileTest_Hdr, HLG_HW_On_PQ_HW_IfPQHasLegacySupport_Uses_DisplayP3) {
1217 // BT2020_PQ is not used if there is only legacy support for it.
1218 verify().ifTopLayerIs(BT2020_HLG)
1219 .andTopLayerIsREComposed(false)
1220 .andIfBottomLayerIs(BT2020_PQ)
1221 .andBottomLayerIsREComposed(false)
1222 .andIfLegacySupportFor(BT2020_PQ, true)
1223 .thenExpectBestColorModeCallUses(DISPLAY_P3)
1224 .execute();
1225}
1226
1227TEST_F(OutputUpdateColorProfileTest_Hdr, HLG_HW_On_PQ_RE_Uses_DisplayP3) {
1228 // BT2020_PQ is not used if the bottom PQ layer is RenderEngine composed.
1229 verify().ifTopLayerIs(BT2020_HLG)
1230 .andTopLayerIsREComposed(false)
1231 .andIfBottomLayerIs(BT2020_PQ)
1232 .andBottomLayerIsREComposed(true)
1233 .andIfLegacySupportFor(BT2020_PQ, false)
1234 .thenExpectBestColorModeCallUses(DISPLAY_P3)
1235 .execute();
1236}
1237
1238TEST_F(OutputUpdateColorProfileTest_Hdr, HLG_RE_On_PQ_HW_Uses_PQ) {
1239 // BT2020_PQ is still used if the top HLG layer is RenderEngine composed.
1240 verify().ifTopLayerIs(BT2020_HLG)
1241 .andTopLayerIsREComposed(true)
1242 .andIfBottomLayerIs(BT2020_PQ)
1243 .andBottomLayerIsREComposed(false)
1244 .andIfLegacySupportFor(BT2020_PQ, false)
1245 .thenExpectBestColorModeCallUses(BT2020_PQ)
1246 .execute();
1247}
1248
1249TEST_F(OutputUpdateColorProfileTest_Hdr, HLG_HW_On_HLG_HW_Uses_HLG) {
1250 // If all layers use HLG then HLG is used if there are no other special
1251 // conditions.
1252 verify().ifTopLayerIs(BT2020_HLG)
1253 .andTopLayerIsREComposed(false)
1254 .andIfBottomLayerIs(BT2020_HLG)
1255 .andBottomLayerIsREComposed(false)
1256 .andIfLegacySupportFor(BT2020_HLG, false)
1257 .thenExpectBestColorModeCallUses(BT2020_HLG)
1258 .execute();
1259}
1260
1261TEST_F(OutputUpdateColorProfileTest_Hdr, HLG_HW_On_HLG_HW_IfPQHasLegacySupport_Uses_DisplayP3) {
1262 // BT2020_HLG is not used if there is legacy support for it.
1263 verify().ifTopLayerIs(BT2020_HLG)
1264 .andTopLayerIsREComposed(false)
1265 .andIfBottomLayerIs(BT2020_HLG)
1266 .andBottomLayerIsREComposed(false)
1267 .andIfLegacySupportFor(BT2020_HLG, true)
1268 .thenExpectBestColorModeCallUses(DISPLAY_P3)
1269 .execute();
1270}
1271
1272TEST_F(OutputUpdateColorProfileTest_Hdr, HLG_HW_On_HLG_RE_Uses_HLG) {
1273 // BT2020_HLG is used even if the bottom layer is client composed.
1274 verify().ifTopLayerIs(BT2020_HLG)
1275 .andTopLayerIsREComposed(false)
1276 .andIfBottomLayerIs(BT2020_HLG)
1277 .andBottomLayerIsREComposed(true)
1278 .andIfLegacySupportFor(BT2020_HLG, false)
1279 .thenExpectBestColorModeCallUses(BT2020_HLG)
1280 .execute();
1281}
1282
1283TEST_F(OutputUpdateColorProfileTest_Hdr, HLG_RE_On_HLG_HW_Uses_HLG) {
1284 // BT2020_HLG is used even if the top layer is client composed.
1285 verify().ifTopLayerIs(BT2020_HLG)
1286 .andTopLayerIsREComposed(true)
1287 .andIfBottomLayerIs(BT2020_HLG)
1288 .andBottomLayerIsREComposed(false)
1289 .andIfLegacySupportFor(BT2020_HLG, false)
1290 .thenExpectBestColorModeCallUses(BT2020_HLG)
1291 .execute();
1292}
1293
1294TEST_F(OutputUpdateColorProfileTest_Hdr, PQ_HW_On_NonHdr_HW_Uses_PQ) {
1295 // Even if there are non-HDR layers present, BT2020_PQ can still be used.
1296 verify().ifTopLayerIs(BT2020_PQ)
1297 .andTopLayerIsREComposed(false)
1298 .andIfBottomLayerIsNotHdr()
1299 .andBottomLayerIsREComposed(false)
1300 .andIfLegacySupportFor(BT2020_PQ, false)
1301 .thenExpectBestColorModeCallUses(BT2020_PQ)
1302 .execute();
1303}
1304
1305TEST_F(OutputUpdateColorProfileTest_Hdr, HLG_HW_On_NonHdr_RE_Uses_HLG) {
1306 // If all layers use HLG then HLG is used if there are no other special
1307 // conditions.
1308 verify().ifTopLayerIs(BT2020_HLG)
1309 .andTopLayerIsREComposed(false)
1310 .andIfBottomLayerIsNotHdr()
1311 .andBottomLayerIsREComposed(true)
1312 .andIfLegacySupportFor(BT2020_HLG, false)
1313 .thenExpectBestColorModeCallUses(BT2020_HLG)
1314 .execute();
1315}
1316
1317struct OutputUpdateColorProfile_AffectsChosenRenderIntentTest
1318 : public OutputUpdateColorProfileTest {
1319 // The various values for CompositionRefreshArgs::outputColorSetting affect
1320 // the chosen renderIntent, along with whether the preferred dataspace is an
1321 // HDR dataspace or not.
1322
1323 OutputUpdateColorProfile_AffectsChosenRenderIntentTest() {
1324 mRefreshArgs.outputColorSetting = OutputColorSetting::kEnhanced;
1325 mRefreshArgs.colorSpaceAgnosticDataspace = ui::Dataspace::UNKNOWN;
1326 mLayer1.mLayerFEState.dataspace = ui::Dataspace::BT2020_PQ;
1327 EXPECT_CALL(mOutput, getOutputLayerCount()).WillRepeatedly(Return(1));
1328 EXPECT_CALL(mOutput, setColorProfile(_)).WillRepeatedly(Return());
1329 EXPECT_CALL(*mDisplayColorProfile, hasLegacyHdrSupport(ui::Dataspace::BT2020_PQ))
1330 .WillRepeatedly(Return(false));
1331 }
1332
1333 // The tests here involve enough state and GMock setup that using a mini-DSL
1334 // makes the tests much more readable, and allows the test to focus more on
1335 // the intent than on some of the details.
1336
1337 static constexpr ui::Dataspace kNonHdrDataspace = ui::Dataspace::DISPLAY_P3;
1338 static constexpr ui::Dataspace kHdrDataspace = ui::Dataspace::BT2020_PQ;
1339
1340 struct IfDataspaceChosenState
1341 : public CallOrderStateMachineHelper<TestType, IfDataspaceChosenState> {
1342 [[nodiscard]] auto ifDataspaceChosenIs(ui::Dataspace dataspace) {
1343 getInstance()->mLayer1.mLayerFEState.dataspace = dataspace;
1344 return nextState<AndOutputColorSettingState>();
1345 }
1346 [[nodiscard]] auto ifDataspaceChosenIsNonHdr() {
1347 return ifDataspaceChosenIs(kNonHdrDataspace);
1348 }
1349 [[nodiscard]] auto ifDataspaceChosenIsHdr() { return ifDataspaceChosenIs(kHdrDataspace); }
1350 };
1351
1352 struct AndOutputColorSettingState
1353 : public CallOrderStateMachineHelper<TestType, AndOutputColorSettingState> {
1354 [[nodiscard]] auto andOutputColorSettingIs(OutputColorSetting setting) {
1355 getInstance()->mRefreshArgs.outputColorSetting = setting;
1356 return nextState<ThenExpectBestColorModeCallUsesState>();
1357 }
1358 };
1359
1360 struct ThenExpectBestColorModeCallUsesState
1361 : public CallOrderStateMachineHelper<TestType, ThenExpectBestColorModeCallUsesState> {
1362 [[nodiscard]] auto thenExpectBestColorModeCallUses(ui::RenderIntent intent) {
1363 EXPECT_CALL(*getInstance()->mDisplayColorProfile,
1364 getBestColorMode(getInstance()->mLayer1.mLayerFEState.dataspace, intent, _,
1365 _, _));
1366 return nextState<ExecuteState>();
1367 }
1368 };
1369
1370 // Tests call one of these two helper member functions to start using the
1371 // mini-DSL defined above.
1372 [[nodiscard]] auto verify() { return IfDataspaceChosenState::make(this); }
1373};
1374
1375TEST_F(OutputUpdateColorProfile_AffectsChosenRenderIntentTest,
1376 Managed_NonHdr_Prefers_Colorimetric) {
1377 verify().ifDataspaceChosenIsNonHdr()
1378 .andOutputColorSettingIs(OutputColorSetting::kManaged)
1379 .thenExpectBestColorModeCallUses(ui::RenderIntent::COLORIMETRIC)
1380 .execute();
1381}
1382
1383TEST_F(OutputUpdateColorProfile_AffectsChosenRenderIntentTest,
1384 Managed_Hdr_Prefers_ToneMapColorimetric) {
1385 verify().ifDataspaceChosenIsHdr()
1386 .andOutputColorSettingIs(OutputColorSetting::kManaged)
1387 .thenExpectBestColorModeCallUses(ui::RenderIntent::TONE_MAP_COLORIMETRIC)
1388 .execute();
1389}
1390
1391TEST_F(OutputUpdateColorProfile_AffectsChosenRenderIntentTest, Enhanced_NonHdr_Prefers_Enhance) {
1392 verify().ifDataspaceChosenIsNonHdr()
1393 .andOutputColorSettingIs(OutputColorSetting::kEnhanced)
1394 .thenExpectBestColorModeCallUses(ui::RenderIntent::ENHANCE)
1395 .execute();
1396}
1397
1398TEST_F(OutputUpdateColorProfile_AffectsChosenRenderIntentTest,
1399 Enhanced_Hdr_Prefers_ToneMapEnhance) {
1400 verify().ifDataspaceChosenIsHdr()
1401 .andOutputColorSettingIs(OutputColorSetting::kEnhanced)
1402 .thenExpectBestColorModeCallUses(ui::RenderIntent::TONE_MAP_ENHANCE)
1403 .execute();
1404}
1405
1406TEST_F(OutputUpdateColorProfile_AffectsChosenRenderIntentTest, Vendor_NonHdr_Prefers_Vendor) {
1407 verify().ifDataspaceChosenIsNonHdr()
1408 .andOutputColorSettingIs(kVendorSpecifiedOutputColorSetting)
1409 .thenExpectBestColorModeCallUses(
1410 static_cast<ui::RenderIntent>(kVendorSpecifiedOutputColorSetting))
1411 .execute();
1412}
1413
1414TEST_F(OutputUpdateColorProfile_AffectsChosenRenderIntentTest, Vendor_Hdr_Prefers_Vendor) {
1415 verify().ifDataspaceChosenIsHdr()
1416 .andOutputColorSettingIs(kVendorSpecifiedOutputColorSetting)
1417 .thenExpectBestColorModeCallUses(
1418 static_cast<ui::RenderIntent>(kVendorSpecifiedOutputColorSetting))
1419 .execute();
1420}
Lloyd Piquefaa3f192019-11-14 14:05:09 -08001421
1422/*
1423 * Output::beginFrame()
1424 */
1425
1426/*
1427 * Output::devOptRepaintFlash()
1428 */
1429
Lloyd Piquedb462d82019-11-19 17:58:46 -08001430struct OutputDevOptRepaintFlashTest : public testing::Test {
1431 struct OutputPartialMock : public OutputPartialMockBase {
1432 // Sets up the helper functions called by composeSurfaces to use a mock
1433 // implementations.
1434 MOCK_CONST_METHOD1(getDirtyRegion, Region(bool));
1435 MOCK_METHOD1(composeSurfaces, std::optional<base::unique_fd>(const Region&));
1436 MOCK_METHOD0(postFramebuffer, void());
1437 MOCK_METHOD0(prepareFrame, void());
1438 };
1439
1440 OutputDevOptRepaintFlashTest() {
1441 mOutput.setDisplayColorProfileForTest(
1442 std::unique_ptr<DisplayColorProfile>(mDisplayColorProfile));
1443 mOutput.setRenderSurfaceForTest(std::unique_ptr<RenderSurface>(mRenderSurface));
1444 }
1445
1446 static const Region kEmptyRegion;
1447 static const Region kNotEmptyRegion;
1448
1449 StrictMock<OutputPartialMock> mOutput;
1450 mock::DisplayColorProfile* mDisplayColorProfile = new StrictMock<mock::DisplayColorProfile>();
1451 mock::RenderSurface* mRenderSurface = new StrictMock<mock::RenderSurface>();
1452 CompositionRefreshArgs mRefreshArgs;
1453};
1454
1455const Region OutputDevOptRepaintFlashTest::kEmptyRegion{Rect{0, 0, 0, 0}};
1456const Region OutputDevOptRepaintFlashTest::kNotEmptyRegion{Rect{0, 0, 1, 1}};
1457
1458TEST_F(OutputDevOptRepaintFlashTest, doesNothingIfFlashDelayNotSet) {
1459 mRefreshArgs.devOptFlashDirtyRegionsDelay = {};
1460 mRefreshArgs.repaintEverything = true;
1461 mOutput.mState.isEnabled = true;
1462
1463 mOutput.devOptRepaintFlash(mRefreshArgs);
1464}
1465
1466TEST_F(OutputDevOptRepaintFlashTest, postsAndPreparesANewFrameIfNotEnabled) {
1467 mRefreshArgs.devOptFlashDirtyRegionsDelay = std::chrono::microseconds(1);
1468 mRefreshArgs.repaintEverything = true;
1469 mOutput.mState.isEnabled = false;
1470
1471 InSequence seq;
1472 EXPECT_CALL(mOutput, postFramebuffer());
1473 EXPECT_CALL(mOutput, prepareFrame());
1474
1475 mOutput.devOptRepaintFlash(mRefreshArgs);
1476}
1477
1478TEST_F(OutputDevOptRepaintFlashTest, postsAndPreparesANewFrameIfNotDirty) {
1479 mRefreshArgs.devOptFlashDirtyRegionsDelay = std::chrono::microseconds(1);
1480 mRefreshArgs.repaintEverything = true;
1481 mOutput.mState.isEnabled = true;
1482
1483 InSequence seq;
1484 EXPECT_CALL(mOutput, getDirtyRegion(true)).WillOnce(Return(kEmptyRegion));
1485 EXPECT_CALL(mOutput, postFramebuffer());
1486 EXPECT_CALL(mOutput, prepareFrame());
1487
1488 mOutput.devOptRepaintFlash(mRefreshArgs);
1489}
1490
1491TEST_F(OutputDevOptRepaintFlashTest, alsoComposesSurfacesAndQueuesABufferIfDirty) {
1492 mRefreshArgs.devOptFlashDirtyRegionsDelay = std::chrono::microseconds(1);
1493 mRefreshArgs.repaintEverything = false;
1494 mOutput.mState.isEnabled = true;
1495
1496 InSequence seq;
1497 EXPECT_CALL(mOutput, getDirtyRegion(false)).WillOnce(Return(kNotEmptyRegion));
1498 EXPECT_CALL(mOutput, composeSurfaces(RegionEq(kNotEmptyRegion)));
1499 EXPECT_CALL(*mRenderSurface, queueBuffer(_));
1500 EXPECT_CALL(mOutput, postFramebuffer());
1501 EXPECT_CALL(mOutput, prepareFrame());
1502
1503 mOutput.devOptRepaintFlash(mRefreshArgs);
1504}
1505
Lloyd Piquefaa3f192019-11-14 14:05:09 -08001506// TODO(b/144060211) - Add coverage
1507
1508/*
1509 * Output::finishFrame()
1510 */
1511
Lloyd Pique03561a62019-11-19 18:34:52 -08001512struct OutputFinishFrameTest : public testing::Test {
1513 struct OutputPartialMock : public OutputPartialMockBase {
1514 // Sets up the helper functions called by composeSurfaces to use a mock
1515 // implementations.
1516 MOCK_METHOD1(composeSurfaces, std::optional<base::unique_fd>(const Region&));
1517 MOCK_METHOD0(postFramebuffer, void());
1518 };
1519
1520 OutputFinishFrameTest() {
1521 mOutput.setDisplayColorProfileForTest(
1522 std::unique_ptr<DisplayColorProfile>(mDisplayColorProfile));
1523 mOutput.setRenderSurfaceForTest(std::unique_ptr<RenderSurface>(mRenderSurface));
1524 }
1525
1526 StrictMock<OutputPartialMock> mOutput;
1527 mock::DisplayColorProfile* mDisplayColorProfile = new StrictMock<mock::DisplayColorProfile>();
1528 mock::RenderSurface* mRenderSurface = new StrictMock<mock::RenderSurface>();
1529 CompositionRefreshArgs mRefreshArgs;
1530};
1531
1532TEST_F(OutputFinishFrameTest, ifNotEnabledDoesNothing) {
1533 mOutput.mState.isEnabled = false;
1534
1535 mOutput.finishFrame(mRefreshArgs);
1536}
1537
1538TEST_F(OutputFinishFrameTest, takesEarlyOutifComposeSurfacesReturnsNoFence) {
1539 mOutput.mState.isEnabled = true;
1540
1541 InSequence seq;
1542 EXPECT_CALL(mOutput, composeSurfaces(RegionEq(Region::INVALID_REGION)));
1543
1544 mOutput.finishFrame(mRefreshArgs);
1545}
1546
1547TEST_F(OutputFinishFrameTest, queuesBufferIfComposeSurfacesReturnsAFence) {
1548 mOutput.mState.isEnabled = true;
1549
1550 InSequence seq;
1551 EXPECT_CALL(mOutput, composeSurfaces(RegionEq(Region::INVALID_REGION)))
1552 .WillOnce(Return(ByMove(base::unique_fd())));
1553 EXPECT_CALL(*mRenderSurface, queueBuffer(_));
1554
1555 mOutput.finishFrame(mRefreshArgs);
1556}
Lloyd Piquefaa3f192019-11-14 14:05:09 -08001557
1558/*
1559 * Output::postFramebuffer()
1560 */
1561
1562// TODO(b/144060211) - Add coverage
1563
1564/*
Lloyd Pique56eba802019-08-28 15:45:25 -07001565 * Output::composeSurfaces()
1566 */
1567
1568struct OutputComposeSurfacesTest : public testing::Test {
1569 static constexpr uint32_t kDefaultOutputOrientation = TR_IDENT;
1570 static constexpr ui::Dataspace kDefaultOutputDataspace = ui::Dataspace::DISPLAY_P3;
1571
1572 static const Rect kDefaultOutputFrame;
1573 static const Rect kDefaultOutputViewport;
1574 static const Rect kDefaultOutputScissor;
1575 static const mat4 kDefaultColorTransformMat;
1576
Lloyd Piquefaa3f192019-11-14 14:05:09 -08001577 struct OutputPartialMock : public OutputPartialMockBase {
Lloyd Pique56eba802019-08-28 15:45:25 -07001578 // Sets up the helper functions called by composeSurfaces to use a mock
1579 // implementations.
1580 MOCK_CONST_METHOD0(getSkipColorTransform, bool());
1581 MOCK_METHOD2(generateClientCompositionRequests,
1582 std::vector<renderengine::LayerSettings>(bool, Region&));
1583 MOCK_METHOD2(appendRegionFlashRequests,
1584 void(const Region&, std::vector<renderengine::LayerSettings>&));
1585 MOCK_METHOD1(setExpensiveRenderingExpected, void(bool));
1586 };
1587
1588 OutputComposeSurfacesTest() {
1589 mOutput.setDisplayColorProfileForTest(
1590 std::unique_ptr<DisplayColorProfile>(mDisplayColorProfile));
1591 mOutput.setRenderSurfaceForTest(std::unique_ptr<RenderSurface>(mRenderSurface));
1592
Lloyd Pique56eba802019-08-28 15:45:25 -07001593 mOutput.editState().frame = kDefaultOutputFrame;
1594 mOutput.editState().viewport = kDefaultOutputViewport;
1595 mOutput.editState().scissor = kDefaultOutputScissor;
1596 mOutput.editState().transform = ui::Transform{kDefaultOutputOrientation};
1597 mOutput.editState().orientation = kDefaultOutputOrientation;
1598 mOutput.editState().dataspace = kDefaultOutputDataspace;
Lloyd Pique3eb1b212019-03-07 21:15:40 -08001599 mOutput.editState().colorTransformMatrix = kDefaultColorTransformMat;
Lloyd Pique56eba802019-08-28 15:45:25 -07001600 mOutput.editState().isSecure = true;
1601 mOutput.editState().needsFiltering = false;
1602 mOutput.editState().usesClientComposition = true;
1603 mOutput.editState().usesDeviceComposition = false;
1604
Lloyd Pique01c77c12019-04-17 12:48:32 -07001605 EXPECT_CALL(mOutput, getOutputLayerCount()).WillRepeatedly(Return(2u));
1606 EXPECT_CALL(mOutput, getOutputLayerOrderedByZByIndex(0u))
1607 .WillRepeatedly(Return(&mOutputLayer1));
1608 EXPECT_CALL(mOutput, getOutputLayerOrderedByZByIndex(1u))
1609 .WillRepeatedly(Return(&mOutputLayer2));
Lloyd Piquea38ea7e2019-04-16 18:10:26 -07001610 EXPECT_CALL(mOutput, getCompositionEngine()).WillRepeatedly(ReturnRef(mCompositionEngine));
Lloyd Pique56eba802019-08-28 15:45:25 -07001611 EXPECT_CALL(mCompositionEngine, getRenderEngine()).WillRepeatedly(ReturnRef(mRenderEngine));
1612 }
1613
1614 StrictMock<mock::CompositionEngine> mCompositionEngine;
1615 StrictMock<renderengine::mock::RenderEngine> mRenderEngine;
1616 mock::DisplayColorProfile* mDisplayColorProfile = new StrictMock<mock::DisplayColorProfile>();
1617 mock::RenderSurface* mRenderSurface = new StrictMock<mock::RenderSurface>();
Lloyd Pique01c77c12019-04-17 12:48:32 -07001618 StrictMock<mock::OutputLayer> mOutputLayer1;
1619 StrictMock<mock::OutputLayer> mOutputLayer2;
Lloyd Piquea38ea7e2019-04-16 18:10:26 -07001620 StrictMock<OutputPartialMock> mOutput;
Lloyd Pique56eba802019-08-28 15:45:25 -07001621 sp<GraphicBuffer> mOutputBuffer = new GraphicBuffer();
1622};
1623
1624const Rect OutputComposeSurfacesTest::kDefaultOutputFrame{1001, 1002, 1003, 1004};
1625const Rect OutputComposeSurfacesTest::kDefaultOutputViewport{1005, 1006, 1007, 1008};
1626const Rect OutputComposeSurfacesTest::kDefaultOutputScissor{1009, 1010, 1011, 1012};
1627const mat4 OutputComposeSurfacesTest::kDefaultColorTransformMat{mat4() * 0.5};
1628
1629// TODO(b/121291683): Expand unit test coverage for composeSurfaces beyond these
1630// basic tests.
1631
1632TEST_F(OutputComposeSurfacesTest, doesNothingIfNoClientComposition) {
1633 mOutput.editState().usesClientComposition = false;
1634
1635 Region debugRegion;
Lloyd Piqued3d69882019-02-28 16:03:46 -08001636 std::optional<base::unique_fd> readyFence = mOutput.composeSurfaces(debugRegion);
1637 EXPECT_TRUE(readyFence);
Lloyd Pique56eba802019-08-28 15:45:25 -07001638}
1639
1640TEST_F(OutputComposeSurfacesTest, worksIfNoClientLayersQueued) {
1641 const Region kDebugRegion{Rect{100, 101, 102, 103}};
1642
1643 constexpr float kDefaultMaxLuminance = 1.0f;
1644 constexpr float kDefaultAvgLuminance = 0.7f;
1645 constexpr float kDefaultMinLuminance = 0.1f;
1646 HdrCapabilities HdrCapabilities{{},
1647 kDefaultMaxLuminance,
1648 kDefaultAvgLuminance,
1649 kDefaultMinLuminance};
1650
1651 EXPECT_CALL(mRenderEngine, supportsProtectedContent()).WillOnce(Return(false));
1652 EXPECT_CALL(mRenderEngine, drawLayers(_, _, _, true, _, _)).Times(1);
1653
1654 EXPECT_CALL(*mDisplayColorProfile, hasWideColorGamut()).WillOnce(Return(true));
1655 EXPECT_CALL(*mDisplayColorProfile, getHdrCapabilities()).WillOnce(ReturnRef(HdrCapabilities));
1656
1657 EXPECT_CALL(*mRenderSurface, dequeueBuffer(_)).WillOnce(Return(mOutputBuffer));
1658
1659 EXPECT_CALL(mOutput, getSkipColorTransform()).WillOnce(Return(false));
1660 EXPECT_CALL(mOutput, generateClientCompositionRequests(false, _)).Times(1);
1661 EXPECT_CALL(mOutput, appendRegionFlashRequests(RegionEq(kDebugRegion), _)).Times(1);
1662 EXPECT_CALL(mOutput, setExpensiveRenderingExpected(true)).Times(1);
1663 EXPECT_CALL(mOutput, setExpensiveRenderingExpected(false)).Times(1);
1664
Lloyd Piqued3d69882019-02-28 16:03:46 -08001665 std::optional<base::unique_fd> readyFence = mOutput.composeSurfaces(kDebugRegion);
1666 EXPECT_TRUE(readyFence);
Lloyd Pique56eba802019-08-28 15:45:25 -07001667}
1668
1669/*
1670 * Output::generateClientCompositionRequests()
1671 */
1672
1673struct GenerateClientCompositionRequestsTest : public testing::Test {
Lloyd Piquefaa3f192019-11-14 14:05:09 -08001674 struct OutputPartialMock : public OutputPartialMockBase {
Lloyd Piquea38ea7e2019-04-16 18:10:26 -07001675 // compositionengine::Output overrides
Lloyd Pique56eba802019-08-28 15:45:25 -07001676 std::vector<renderengine::LayerSettings> generateClientCompositionRequests(
1677 bool supportsProtectedContent, Region& clearRegion) override {
1678 return impl::Output::generateClientCompositionRequests(supportsProtectedContent,
1679 clearRegion);
1680 }
1681 };
1682
1683 GenerateClientCompositionRequestsTest() {
1684 mOutput.setDisplayColorProfileForTest(
1685 std::unique_ptr<DisplayColorProfile>(mDisplayColorProfile));
1686 mOutput.setRenderSurfaceForTest(std::unique_ptr<RenderSurface>(mRenderSurface));
1687 }
1688
Lloyd Pique56eba802019-08-28 15:45:25 -07001689 mock::DisplayColorProfile* mDisplayColorProfile = new StrictMock<mock::DisplayColorProfile>();
1690 mock::RenderSurface* mRenderSurface = new StrictMock<mock::RenderSurface>();
Lloyd Piquea38ea7e2019-04-16 18:10:26 -07001691 StrictMock<OutputPartialMock> mOutput;
Lloyd Pique56eba802019-08-28 15:45:25 -07001692};
1693
1694// TODO(b/121291683): Add more unit test coverage for generateClientCompositionRequests
1695
1696TEST_F(GenerateClientCompositionRequestsTest, worksForLandscapeModeSplitScreen) {
1697 // In split-screen landscape mode, the screen is rotated 90 degrees, with
1698 // one layer on the left covering the left side of the output, and one layer
1699 // on the right covering that side of the output.
1700
Lloyd Pique01c77c12019-04-17 12:48:32 -07001701 StrictMock<mock::OutputLayer> leftOutputLayer;
1702 StrictMock<mock::OutputLayer> rightOutputLayer;
Lloyd Pique56eba802019-08-28 15:45:25 -07001703
1704 StrictMock<mock::Layer> leftLayer;
1705 StrictMock<mock::LayerFE> leftLayerFE;
1706 StrictMock<mock::Layer> rightLayer;
1707 StrictMock<mock::LayerFE> rightLayerFE;
1708
1709 impl::OutputLayerCompositionState leftOutputLayerState;
1710 leftOutputLayerState.clearClientTarget = false;
Lloyd Piquea2468662019-03-07 21:31:06 -08001711 leftOutputLayerState.visibleRegion = Region{Rect{0, 0, 1000, 1000}};
Lloyd Pique56eba802019-08-28 15:45:25 -07001712
Lloyd Pique9755fb72019-03-26 14:44:40 -07001713 LayerFECompositionState leftLayerFEState;
1714 leftLayerFEState.isOpaque = true;
Lloyd Pique56eba802019-08-28 15:45:25 -07001715
1716 const half3 leftLayerColor{1.f, 0.f, 0.f};
1717 renderengine::LayerSettings leftLayerRESettings;
1718 leftLayerRESettings.source.solidColor = leftLayerColor;
1719
1720 impl::OutputLayerCompositionState rightOutputLayerState;
1721 rightOutputLayerState.clearClientTarget = false;
Lloyd Piquea2468662019-03-07 21:31:06 -08001722 rightOutputLayerState.visibleRegion = Region{Rect{1000, 0, 2000, 1000}};
Lloyd Pique56eba802019-08-28 15:45:25 -07001723
Lloyd Pique9755fb72019-03-26 14:44:40 -07001724 LayerFECompositionState rightLayerFEState;
1725 rightLayerFEState.isOpaque = true;
Lloyd Pique56eba802019-08-28 15:45:25 -07001726
1727 const half3 rightLayerColor{0.f, 1.f, 0.f};
1728 renderengine::LayerSettings rightLayerRESettings;
1729 rightLayerRESettings.source.solidColor = rightLayerColor;
1730
Lloyd Pique01c77c12019-04-17 12:48:32 -07001731 EXPECT_CALL(leftOutputLayer, getState()).WillRepeatedly(ReturnRef(leftOutputLayerState));
1732 EXPECT_CALL(leftOutputLayer, getLayer()).WillRepeatedly(ReturnRef(leftLayer));
1733 EXPECT_CALL(leftOutputLayer, getLayerFE()).WillRepeatedly(ReturnRef(leftLayerFE));
1734 EXPECT_CALL(leftOutputLayer, requiresClientComposition()).WillRepeatedly(Return(true));
1735 EXPECT_CALL(leftOutputLayer, needsFiltering()).WillRepeatedly(Return(false));
Lloyd Pique9755fb72019-03-26 14:44:40 -07001736 EXPECT_CALL(leftLayer, getFEState()).WillRepeatedly(ReturnRef(leftLayerFEState));
Lloyd Pique56eba802019-08-28 15:45:25 -07001737 EXPECT_CALL(leftLayerFE, prepareClientComposition(_)).WillOnce(Return(leftLayerRESettings));
Adithya Srinivasanb69e0762019-11-11 18:39:53 -08001738 EXPECT_CALL(leftOutputLayer, editState()).WillRepeatedly(ReturnRef(leftOutputLayerState));
Lloyd Pique56eba802019-08-28 15:45:25 -07001739
Lloyd Pique01c77c12019-04-17 12:48:32 -07001740 EXPECT_CALL(rightOutputLayer, getState()).WillRepeatedly(ReturnRef(rightOutputLayerState));
1741 EXPECT_CALL(rightOutputLayer, getLayer()).WillRepeatedly(ReturnRef(rightLayer));
1742 EXPECT_CALL(rightOutputLayer, getLayerFE()).WillRepeatedly(ReturnRef(rightLayerFE));
1743 EXPECT_CALL(rightOutputLayer, requiresClientComposition()).WillRepeatedly(Return(true));
1744 EXPECT_CALL(rightOutputLayer, needsFiltering()).WillRepeatedly(Return(false));
Lloyd Pique9755fb72019-03-26 14:44:40 -07001745 EXPECT_CALL(rightLayer, getFEState()).WillRepeatedly(ReturnRef(rightLayerFEState));
Lloyd Pique56eba802019-08-28 15:45:25 -07001746 EXPECT_CALL(rightLayerFE, prepareClientComposition(_)).WillOnce(Return(rightLayerRESettings));
Adithya Srinivasanb69e0762019-11-11 18:39:53 -08001747 EXPECT_CALL(rightOutputLayer, editState()).WillRepeatedly(ReturnRef(rightOutputLayerState));
Lloyd Pique56eba802019-08-28 15:45:25 -07001748
Lloyd Pique01c77c12019-04-17 12:48:32 -07001749 EXPECT_CALL(mOutput, getOutputLayerCount()).WillRepeatedly(Return(2u));
1750 EXPECT_CALL(mOutput, getOutputLayerOrderedByZByIndex(0u))
1751 .WillRepeatedly(Return(&leftOutputLayer));
1752 EXPECT_CALL(mOutput, getOutputLayerOrderedByZByIndex(1u))
1753 .WillRepeatedly(Return(&rightOutputLayer));
Lloyd Pique56eba802019-08-28 15:45:25 -07001754
1755 const Rect kPortraitFrame(0, 0, 1000, 2000);
1756 const Rect kPortraitViewport(0, 0, 2000, 1000);
1757 const Rect kPortraitScissor(0, 0, 1000, 2000);
1758 const uint32_t kPortraitOrientation = TR_ROT_90;
1759
1760 mOutput.editState().frame = kPortraitFrame;
1761 mOutput.editState().viewport = kPortraitViewport;
1762 mOutput.editState().scissor = kPortraitScissor;
1763 mOutput.editState().transform = ui::Transform{kPortraitOrientation};
1764 mOutput.editState().orientation = kPortraitOrientation;
1765 mOutput.editState().needsFiltering = true;
1766 mOutput.editState().isSecure = false;
1767
1768 constexpr bool supportsProtectedContent = false;
1769 Region clearRegion;
1770 auto requests =
1771 mOutput.generateClientCompositionRequests(supportsProtectedContent, clearRegion);
1772
1773 ASSERT_EQ(2u, requests.size());
1774 EXPECT_EQ(leftLayerColor, requests[0].source.solidColor);
1775 EXPECT_EQ(rightLayerColor, requests[1].source.solidColor);
1776}
1777
1778TEST_F(GenerateClientCompositionRequestsTest, ignoresLayersThatDoNotIntersectWithViewport) {
1779 // Layers whose visible region does not intersect with the viewport will be
1780 // skipped when generating client composition request state.
1781
Lloyd Pique01c77c12019-04-17 12:48:32 -07001782 StrictMock<mock::OutputLayer> outputLayer;
Lloyd Pique56eba802019-08-28 15:45:25 -07001783 StrictMock<mock::Layer> layer;
1784 StrictMock<mock::LayerFE> layerFE;
1785
1786 impl::OutputLayerCompositionState outputLayerState;
1787 outputLayerState.clearClientTarget = false;
Lloyd Piquea2468662019-03-07 21:31:06 -08001788 outputLayerState.visibleRegion = Region{Rect{3000, 0, 4000, 1000}};
Lloyd Pique56eba802019-08-28 15:45:25 -07001789
Lloyd Pique9755fb72019-03-26 14:44:40 -07001790 LayerFECompositionState layerFEState;
1791 layerFEState.isOpaque = true;
Lloyd Pique56eba802019-08-28 15:45:25 -07001792
Lloyd Pique01c77c12019-04-17 12:48:32 -07001793 EXPECT_CALL(outputLayer, getState()).WillRepeatedly(ReturnRef(outputLayerState));
1794 EXPECT_CALL(outputLayer, getLayer()).WillRepeatedly(ReturnRef(layer));
1795 EXPECT_CALL(outputLayer, getLayerFE()).WillRepeatedly(ReturnRef(layerFE));
1796 EXPECT_CALL(outputLayer, requiresClientComposition()).WillRepeatedly(Return(true));
1797 EXPECT_CALL(outputLayer, needsFiltering()).WillRepeatedly(Return(false));
Lloyd Pique9755fb72019-03-26 14:44:40 -07001798 EXPECT_CALL(layer, getFEState()).WillRepeatedly(ReturnRef(layerFEState));
Lloyd Pique56eba802019-08-28 15:45:25 -07001799 EXPECT_CALL(layerFE, prepareClientComposition(_)).Times(0);
Adithya Srinivasanb69e0762019-11-11 18:39:53 -08001800 EXPECT_CALL(outputLayer, editState()).WillRepeatedly(ReturnRef(outputLayerState));
Lloyd Pique56eba802019-08-28 15:45:25 -07001801
Lloyd Pique01c77c12019-04-17 12:48:32 -07001802 EXPECT_CALL(mOutput, getOutputLayerCount()).WillRepeatedly(Return(1u));
1803 EXPECT_CALL(mOutput, getOutputLayerOrderedByZByIndex(0u)).WillRepeatedly(Return(&outputLayer));
Lloyd Pique56eba802019-08-28 15:45:25 -07001804
1805 const Rect kPortraitFrame(0, 0, 1000, 2000);
1806 const Rect kPortraitViewport(0, 0, 2000, 1000);
1807 const Rect kPortraitScissor(0, 0, 1000, 2000);
1808 const uint32_t kPortraitOrientation = TR_ROT_90;
1809
1810 mOutput.editState().frame = kPortraitFrame;
1811 mOutput.editState().viewport = kPortraitViewport;
1812 mOutput.editState().scissor = kPortraitScissor;
1813 mOutput.editState().transform = ui::Transform{kPortraitOrientation};
1814 mOutput.editState().orientation = kPortraitOrientation;
1815 mOutput.editState().needsFiltering = true;
1816 mOutput.editState().isSecure = false;
1817
1818 constexpr bool supportsProtectedContent = false;
1819 Region clearRegion;
1820 auto requests =
1821 mOutput.generateClientCompositionRequests(supportsProtectedContent, clearRegion);
1822
1823 EXPECT_EQ(0u, requests.size());
1824}
1825
Lloyd Piquec2d54d42019-08-28 18:04:21 -07001826TEST_F(GenerateClientCompositionRequestsTest, clearsDeviceLayesAfterFirst) {
1827 // If client composition is performed with some layers set to use device
1828 // composition, device layers after the first layer (device or client) will
1829 // clear the frame buffer if they are opaque and if that layer has a flag
1830 // set to do so. The first layer is skipped as the frame buffer is already
1831 // expected to be clear.
1832
Lloyd Pique01c77c12019-04-17 12:48:32 -07001833 StrictMock<mock::OutputLayer> leftOutputLayer;
1834 StrictMock<mock::OutputLayer> rightOutputLayer;
Lloyd Piquec2d54d42019-08-28 18:04:21 -07001835
1836 StrictMock<mock::Layer> leftLayer;
1837 StrictMock<mock::LayerFE> leftLayerFE;
1838 StrictMock<mock::Layer> rightLayer;
1839 StrictMock<mock::LayerFE> rightLayerFE;
1840
1841 impl::OutputLayerCompositionState leftOutputLayerState;
1842 leftOutputLayerState.clearClientTarget = true;
Lloyd Piquea2468662019-03-07 21:31:06 -08001843 leftOutputLayerState.visibleRegion = Region{Rect{0, 0, 1000, 1000}};
Lloyd Piquec2d54d42019-08-28 18:04:21 -07001844
Lloyd Pique9755fb72019-03-26 14:44:40 -07001845 LayerFECompositionState leftLayerFEState;
1846 leftLayerFEState.isOpaque = true;
Lloyd Piquec2d54d42019-08-28 18:04:21 -07001847
1848 impl::OutputLayerCompositionState rightOutputLayerState;
1849 rightOutputLayerState.clearClientTarget = true;
Lloyd Piquea2468662019-03-07 21:31:06 -08001850 rightOutputLayerState.visibleRegion = Region{Rect{1000, 0, 2000, 1000}};
Lloyd Piquec2d54d42019-08-28 18:04:21 -07001851
Lloyd Pique9755fb72019-03-26 14:44:40 -07001852 LayerFECompositionState rightLayerFEState;
1853 rightLayerFEState.isOpaque = true;
Lloyd Piquec2d54d42019-08-28 18:04:21 -07001854
1855 const half3 rightLayerColor{0.f, 1.f, 0.f};
1856 renderengine::LayerSettings rightLayerRESettings;
1857 rightLayerRESettings.geometry.boundaries = FloatRect{456, 0, 0, 0};
1858 rightLayerRESettings.source.solidColor = rightLayerColor;
1859
Lloyd Pique01c77c12019-04-17 12:48:32 -07001860 EXPECT_CALL(leftOutputLayer, getState()).WillRepeatedly(ReturnRef(leftOutputLayerState));
1861 EXPECT_CALL(leftOutputLayer, getLayer()).WillRepeatedly(ReturnRef(leftLayer));
1862 EXPECT_CALL(leftOutputLayer, getLayerFE()).WillRepeatedly(ReturnRef(leftLayerFE));
1863 EXPECT_CALL(leftOutputLayer, requiresClientComposition()).WillRepeatedly(Return(false));
1864 EXPECT_CALL(leftOutputLayer, needsFiltering()).WillRepeatedly(Return(false));
Lloyd Pique9755fb72019-03-26 14:44:40 -07001865 EXPECT_CALL(leftLayer, getFEState()).WillRepeatedly(ReturnRef(leftLayerFEState));
Adithya Srinivasanb69e0762019-11-11 18:39:53 -08001866 EXPECT_CALL(leftOutputLayer, editState()).WillRepeatedly(ReturnRef(leftOutputLayerState));
Lloyd Piquec2d54d42019-08-28 18:04:21 -07001867
Lloyd Pique01c77c12019-04-17 12:48:32 -07001868 EXPECT_CALL(rightOutputLayer, getState()).WillRepeatedly(ReturnRef(rightOutputLayerState));
1869 EXPECT_CALL(rightOutputLayer, getLayer()).WillRepeatedly(ReturnRef(rightLayer));
1870 EXPECT_CALL(rightOutputLayer, getLayerFE()).WillRepeatedly(ReturnRef(rightLayerFE));
1871 EXPECT_CALL(rightOutputLayer, requiresClientComposition()).WillRepeatedly(Return(false));
1872 EXPECT_CALL(rightOutputLayer, needsFiltering()).WillRepeatedly(Return(false));
Lloyd Pique9755fb72019-03-26 14:44:40 -07001873 EXPECT_CALL(rightLayer, getFEState()).WillRepeatedly(ReturnRef(rightLayerFEState));
Lloyd Piquec2d54d42019-08-28 18:04:21 -07001874 EXPECT_CALL(rightLayerFE, prepareClientComposition(_)).WillOnce(Return(rightLayerRESettings));
Adithya Srinivasanb69e0762019-11-11 18:39:53 -08001875 EXPECT_CALL(rightOutputLayer, editState()).WillRepeatedly(ReturnRef(rightOutputLayerState));
Lloyd Piquec2d54d42019-08-28 18:04:21 -07001876
Lloyd Pique01c77c12019-04-17 12:48:32 -07001877 EXPECT_CALL(mOutput, getOutputLayerCount()).WillRepeatedly(Return(2u));
1878 EXPECT_CALL(mOutput, getOutputLayerOrderedByZByIndex(0u))
1879 .WillRepeatedly(Return(&leftOutputLayer));
1880 EXPECT_CALL(mOutput, getOutputLayerOrderedByZByIndex(1u))
1881 .WillRepeatedly(Return(&rightOutputLayer));
Lloyd Piquec2d54d42019-08-28 18:04:21 -07001882
1883 const Rect kPortraitFrame(0, 0, 1000, 2000);
1884 const Rect kPortraitViewport(0, 0, 2000, 1000);
1885 const Rect kPortraitScissor(0, 0, 1000, 2000);
1886 const uint32_t kPortraitOrientation = TR_ROT_90;
1887
1888 mOutput.editState().frame = kPortraitFrame;
1889 mOutput.editState().viewport = kPortraitViewport;
1890 mOutput.editState().scissor = kPortraitScissor;
1891 mOutput.editState().transform = ui::Transform{kPortraitOrientation};
1892 mOutput.editState().orientation = kPortraitOrientation;
1893 mOutput.editState().needsFiltering = true;
1894 mOutput.editState().isSecure = false;
1895
1896 constexpr bool supportsProtectedContent = false;
1897 Region clearRegion;
1898 auto requests =
1899 mOutput.generateClientCompositionRequests(supportsProtectedContent, clearRegion);
1900
1901 const half3 clearColor{0.f, 0.f, 0.f};
1902
1903 ASSERT_EQ(1u, requests.size());
1904 EXPECT_EQ(456.f, requests[0].geometry.boundaries.left);
1905 EXPECT_EQ(clearColor, requests[0].source.solidColor);
1906}
1907
Lloyd Pique32cbe282018-10-19 13:09:22 -07001908} // namespace
1909} // namespace android::compositionengine