blob: 36cb5a40e372747170cfb4b92c551a1308052c20 [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 Pique9755fb72019-03-26 14:44:40 -070019#include <compositionengine/LayerFECompositionState.h>
Lloyd Pique32cbe282018-10-19 13:09:22 -070020#include <compositionengine/impl/Output.h>
Lloyd Pique66d68602019-02-13 14:23:31 -080021#include <compositionengine/impl/OutputCompositionState.h>
Lloyd Pique56eba802019-08-28 15:45:25 -070022#include <compositionengine/impl/OutputLayerCompositionState.h>
Lloyd Pique32cbe282018-10-19 13:09:22 -070023#include <compositionengine/mock/CompositionEngine.h>
Lloyd Pique3d0c02e2018-10-19 18:38:12 -070024#include <compositionengine/mock/DisplayColorProfile.h>
Lloyd Piquecc01a452018-12-04 17:24:00 -080025#include <compositionengine/mock/Layer.h>
26#include <compositionengine/mock/LayerFE.h>
27#include <compositionengine/mock/OutputLayer.h>
Lloyd Pique31cb2942018-10-19 17:23:03 -070028#include <compositionengine/mock/RenderSurface.h>
Lloyd Pique32cbe282018-10-19 13:09:22 -070029#include <gtest/gtest.h>
Lloyd Pique56eba802019-08-28 15:45:25 -070030#include <renderengine/mock/RenderEngine.h>
Lloyd Pique32cbe282018-10-19 13:09:22 -070031#include <ui/Rect.h>
32#include <ui/Region.h>
33
34#include "RegionMatcher.h"
35#include "TransformMatcher.h"
36
37namespace android::compositionengine {
38namespace {
39
Lloyd Pique56eba802019-08-28 15:45:25 -070040using testing::_;
Lloyd Piquefaa3f192019-11-14 14:05:09 -080041using testing::InSequence;
42using testing::Ref;
Lloyd Pique31cb2942018-10-19 17:23:03 -070043using testing::Return;
Lloyd Pique32cbe282018-10-19 13:09:22 -070044using testing::ReturnRef;
45using testing::StrictMock;
46
Lloyd Pique56eba802019-08-28 15:45:25 -070047constexpr auto TR_IDENT = 0u;
48constexpr auto TR_ROT_90 = HAL_TRANSFORM_ROT_90;
49
Lloyd Pique3eb1b212019-03-07 21:15:40 -080050const mat4 kIdentity;
51const mat4 kNonIdentityHalf = mat4() * 0.5;
52const mat4 kNonIdentityQuarter = mat4() * 0.25;
53
Lloyd Piquefaa3f192019-11-14 14:05:09 -080054struct OutputPartialMockBase : public impl::Output {
55 // compositionengine::Output overrides
56 const OutputCompositionState& getState() const override { return mState; }
57 OutputCompositionState& editState() override { return mState; }
58
59 // Use mocks for all the remaining virtual functions
60 // not implemented by the base implementation class.
61 MOCK_CONST_METHOD0(getOutputLayerCount, size_t());
62 MOCK_CONST_METHOD1(getOutputLayerOrderedByZByIndex, compositionengine::OutputLayer*(size_t));
63 MOCK_METHOD3(ensureOutputLayer,
64 compositionengine::OutputLayer*(std::optional<size_t>,
65 const std::shared_ptr<compositionengine::Layer>&,
66 const sp<LayerFE>&));
67 MOCK_METHOD0(finalizePendingOutputLayers, void());
68 MOCK_METHOD0(clearOutputLayers, void());
69 MOCK_CONST_METHOD1(dumpState, void(std::string&));
70 MOCK_CONST_METHOD0(getCompositionEngine, const CompositionEngine&());
71 MOCK_METHOD2(injectOutputLayerForTest,
72 compositionengine::OutputLayer*(const std::shared_ptr<compositionengine::Layer>&,
73 const sp<LayerFE>&));
74 MOCK_METHOD1(injectOutputLayerForTest, void(std::unique_ptr<OutputLayer>));
75
76 impl::OutputCompositionState mState;
77};
78
Lloyd Pique66d68602019-02-13 14:23:31 -080079struct OutputTest : public testing::Test {
Lloyd Pique01c77c12019-04-17 12:48:32 -070080 class Output : public impl::Output {
81 public:
82 using impl::Output::injectOutputLayerForTest;
83 virtual void injectOutputLayerForTest(std::unique_ptr<compositionengine::OutputLayer>) = 0;
84 };
85
86 static std::shared_ptr<Output> createOutput(
87 const compositionengine::CompositionEngine& compositionEngine) {
88 return impl::createOutputTemplated<Output>(compositionEngine);
89 }
90
Lloyd Pique31cb2942018-10-19 17:23:03 -070091 OutputTest() {
Lloyd Piquea38ea7e2019-04-16 18:10:26 -070092 mOutput->setDisplayColorProfileForTest(
Lloyd Pique3d0c02e2018-10-19 18:38:12 -070093 std::unique_ptr<DisplayColorProfile>(mDisplayColorProfile));
Lloyd Piquea38ea7e2019-04-16 18:10:26 -070094 mOutput->setRenderSurfaceForTest(std::unique_ptr<RenderSurface>(mRenderSurface));
Lloyd Piqueef958122019-02-05 18:00:12 -080095
Lloyd Piquea38ea7e2019-04-16 18:10:26 -070096 mOutput->editState().bounds = kDefaultDisplaySize;
Lloyd Pique31cb2942018-10-19 17:23:03 -070097 }
Lloyd Pique32cbe282018-10-19 13:09:22 -070098
Lloyd Piqueef958122019-02-05 18:00:12 -080099 static const Rect kDefaultDisplaySize;
100
Lloyd Pique32cbe282018-10-19 13:09:22 -0700101 StrictMock<mock::CompositionEngine> mCompositionEngine;
Lloyd Pique3d0c02e2018-10-19 18:38:12 -0700102 mock::DisplayColorProfile* mDisplayColorProfile = new StrictMock<mock::DisplayColorProfile>();
Lloyd Pique31cb2942018-10-19 17:23:03 -0700103 mock::RenderSurface* mRenderSurface = new StrictMock<mock::RenderSurface>();
Lloyd Pique01c77c12019-04-17 12:48:32 -0700104 std::shared_ptr<Output> mOutput = createOutput(mCompositionEngine);
Lloyd Pique32cbe282018-10-19 13:09:22 -0700105};
106
Lloyd Piqueef958122019-02-05 18:00:12 -0800107const Rect OutputTest::kDefaultDisplaySize{100, 200};
108
Lloyd Pique66d68602019-02-13 14:23:31 -0800109/*
Lloyd Pique32cbe282018-10-19 13:09:22 -0700110 * Basic construction
111 */
112
Lloyd Pique31cb2942018-10-19 17:23:03 -0700113TEST_F(OutputTest, canInstantiateOutput) {
114 // The validation check checks each required component.
Lloyd Pique3d0c02e2018-10-19 18:38:12 -0700115 EXPECT_CALL(*mDisplayColorProfile, isValid()).WillOnce(Return(true));
Lloyd Pique31cb2942018-10-19 17:23:03 -0700116 EXPECT_CALL(*mRenderSurface, isValid()).WillOnce(Return(true));
117
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700118 EXPECT_TRUE(mOutput->isValid());
Lloyd Pique31cb2942018-10-19 17:23:03 -0700119
120 // If we take away the required components, it is no longer valid.
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700121 mOutput->setRenderSurfaceForTest(std::unique_ptr<RenderSurface>());
Lloyd Pique31cb2942018-10-19 17:23:03 -0700122
Lloyd Pique3d0c02e2018-10-19 18:38:12 -0700123 EXPECT_CALL(*mDisplayColorProfile, isValid()).WillOnce(Return(true));
124
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700125 EXPECT_FALSE(mOutput->isValid());
Lloyd Pique31cb2942018-10-19 17:23:03 -0700126}
Lloyd Pique32cbe282018-10-19 13:09:22 -0700127
Lloyd Pique66d68602019-02-13 14:23:31 -0800128/*
Lloyd Pique32cbe282018-10-19 13:09:22 -0700129 * Output::setCompositionEnabled()
130 */
131
132TEST_F(OutputTest, setCompositionEnabledDoesNothingIfAlreadyEnabled) {
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700133 mOutput->editState().isEnabled = true;
Lloyd Pique32cbe282018-10-19 13:09:22 -0700134
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700135 mOutput->setCompositionEnabled(true);
Lloyd Pique32cbe282018-10-19 13:09:22 -0700136
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700137 EXPECT_TRUE(mOutput->getState().isEnabled);
138 EXPECT_THAT(mOutput->getState().dirtyRegion, RegionEq(Region()));
Lloyd Pique32cbe282018-10-19 13:09:22 -0700139}
140
141TEST_F(OutputTest, setCompositionEnabledSetsEnabledAndDirtiesEntireOutput) {
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700142 mOutput->editState().isEnabled = false;
Lloyd Pique32cbe282018-10-19 13:09:22 -0700143
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700144 mOutput->setCompositionEnabled(true);
Lloyd Pique32cbe282018-10-19 13:09:22 -0700145
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700146 EXPECT_TRUE(mOutput->getState().isEnabled);
147 EXPECT_THAT(mOutput->getState().dirtyRegion, RegionEq(Region(kDefaultDisplaySize)));
Lloyd Pique32cbe282018-10-19 13:09:22 -0700148}
149
150TEST_F(OutputTest, setCompositionEnabledSetsDisabledAndDirtiesEntireOutput) {
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700151 mOutput->editState().isEnabled = true;
Lloyd Pique32cbe282018-10-19 13:09:22 -0700152
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700153 mOutput->setCompositionEnabled(false);
Lloyd Pique32cbe282018-10-19 13:09:22 -0700154
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700155 EXPECT_FALSE(mOutput->getState().isEnabled);
156 EXPECT_THAT(mOutput->getState().dirtyRegion, RegionEq(Region(kDefaultDisplaySize)));
Lloyd Pique32cbe282018-10-19 13:09:22 -0700157}
158
Lloyd Pique66d68602019-02-13 14:23:31 -0800159/*
Lloyd Pique32cbe282018-10-19 13:09:22 -0700160 * Output::setProjection()
161 */
162
163TEST_F(OutputTest, setProjectionTriviallyWorks) {
164 const ui::Transform transform{ui::Transform::ROT_180};
165 const int32_t orientation = 123;
166 const Rect frame{1, 2, 3, 4};
167 const Rect viewport{5, 6, 7, 8};
168 const Rect scissor{9, 10, 11, 12};
169 const bool needsFiltering = true;
170
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700171 mOutput->setProjection(transform, orientation, frame, viewport, scissor, needsFiltering);
Lloyd Pique32cbe282018-10-19 13:09:22 -0700172
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700173 EXPECT_THAT(mOutput->getState().transform, TransformEq(transform));
174 EXPECT_EQ(orientation, mOutput->getState().orientation);
175 EXPECT_EQ(frame, mOutput->getState().frame);
176 EXPECT_EQ(viewport, mOutput->getState().viewport);
177 EXPECT_EQ(scissor, mOutput->getState().scissor);
178 EXPECT_EQ(needsFiltering, mOutput->getState().needsFiltering);
Lloyd Pique32cbe282018-10-19 13:09:22 -0700179}
180
Lloyd Pique66d68602019-02-13 14:23:31 -0800181/*
Lloyd Pique32cbe282018-10-19 13:09:22 -0700182 * Output::setBounds()
183 */
184
185TEST_F(OutputTest, setBoundsSetsSizeAndDirtiesEntireOutput) {
Lloyd Piqueef958122019-02-05 18:00:12 -0800186 const ui::Size displaySize{200, 400};
Lloyd Pique31cb2942018-10-19 17:23:03 -0700187
188 EXPECT_CALL(*mRenderSurface, setDisplaySize(displaySize)).Times(1);
189 EXPECT_CALL(*mRenderSurface, getSize()).WillOnce(ReturnRef(displaySize));
190
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700191 mOutput->setBounds(displaySize);
Lloyd Pique32cbe282018-10-19 13:09:22 -0700192
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700193 EXPECT_EQ(Rect(displaySize), mOutput->getState().bounds);
Lloyd Pique32cbe282018-10-19 13:09:22 -0700194
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700195 EXPECT_THAT(mOutput->getState().dirtyRegion, RegionEq(Region(Rect(displaySize))));
Lloyd Pique32cbe282018-10-19 13:09:22 -0700196}
197
Lloyd Pique66d68602019-02-13 14:23:31 -0800198/*
Lloyd Pique32cbe282018-10-19 13:09:22 -0700199 * Output::setLayerStackFilter()
200 */
201
202TEST_F(OutputTest, setLayerStackFilterSetsFilterAndDirtiesEntireOutput) {
Lloyd Pique32cbe282018-10-19 13:09:22 -0700203 const uint32_t layerStack = 123u;
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700204 mOutput->setLayerStackFilter(layerStack, true);
Lloyd Pique32cbe282018-10-19 13:09:22 -0700205
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700206 EXPECT_TRUE(mOutput->getState().layerStackInternal);
207 EXPECT_EQ(layerStack, mOutput->getState().layerStackId);
Lloyd Pique32cbe282018-10-19 13:09:22 -0700208
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700209 EXPECT_THAT(mOutput->getState().dirtyRegion, RegionEq(Region(kDefaultDisplaySize)));
Lloyd Pique32cbe282018-10-19 13:09:22 -0700210}
211
Lloyd Pique66d68602019-02-13 14:23:31 -0800212/*
Lloyd Pique32cbe282018-10-19 13:09:22 -0700213 * Output::setColorTransform
214 */
215
Lloyd Pique3eb1b212019-03-07 21:15:40 -0800216TEST_F(OutputTest, setColorTransformWithNoChangeFlaggedSkipsUpdates) {
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700217 mOutput->editState().colorTransformMatrix = kIdentity;
Lloyd Pique32cbe282018-10-19 13:09:22 -0700218
Lloyd Pique3eb1b212019-03-07 21:15:40 -0800219 // If no colorTransformMatrix is set the update should be skipped.
220 CompositionRefreshArgs refreshArgs;
221 refreshArgs.colorTransformMatrix = std::nullopt;
Lloyd Pique32cbe282018-10-19 13:09:22 -0700222
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700223 mOutput->setColorTransform(refreshArgs);
Lloyd Pique32cbe282018-10-19 13:09:22 -0700224
Lloyd Pique3eb1b212019-03-07 21:15:40 -0800225 // The internal state should be unchanged
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700226 EXPECT_EQ(kIdentity, mOutput->getState().colorTransformMatrix);
Lloyd Pique3eb1b212019-03-07 21:15:40 -0800227
228 // No dirty region should be set
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700229 EXPECT_THAT(mOutput->getState().dirtyRegion, RegionEq(Region()));
Lloyd Pique3eb1b212019-03-07 21:15:40 -0800230}
Lloyd Piqueef958122019-02-05 18:00:12 -0800231
Lloyd Pique3eb1b212019-03-07 21:15:40 -0800232TEST_F(OutputTest, setColorTransformWithNoActualChangeSkipsUpdates) {
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700233 mOutput->editState().colorTransformMatrix = kIdentity;
Lloyd Pique32cbe282018-10-19 13:09:22 -0700234
Lloyd Pique3eb1b212019-03-07 21:15:40 -0800235 // Attempting to set the same colorTransformMatrix that is already set should
236 // also skip the update.
237 CompositionRefreshArgs refreshArgs;
238 refreshArgs.colorTransformMatrix = kIdentity;
Lloyd Pique32cbe282018-10-19 13:09:22 -0700239
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700240 mOutput->setColorTransform(refreshArgs);
Lloyd Pique77f79a22019-04-29 15:55:40 -0700241
Lloyd Pique3eb1b212019-03-07 21:15:40 -0800242 // The internal state should be unchanged
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700243 EXPECT_EQ(kIdentity, mOutput->getState().colorTransformMatrix);
Lloyd Pique3eb1b212019-03-07 21:15:40 -0800244
245 // No dirty region should be set
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700246 EXPECT_THAT(mOutput->getState().dirtyRegion, RegionEq(Region()));
Lloyd Pique3eb1b212019-03-07 21:15:40 -0800247}
248
249TEST_F(OutputTest, setColorTransformPerformsUpdateToIdentity) {
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700250 mOutput->editState().colorTransformMatrix = kNonIdentityHalf;
Lloyd Pique3eb1b212019-03-07 21:15:40 -0800251
252 // Setting a different colorTransformMatrix should perform the update.
253 CompositionRefreshArgs refreshArgs;
254 refreshArgs.colorTransformMatrix = kIdentity;
255
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700256 mOutput->setColorTransform(refreshArgs);
Lloyd Pique3eb1b212019-03-07 21:15:40 -0800257
258 // The internal state should have been updated
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700259 EXPECT_EQ(kIdentity, mOutput->getState().colorTransformMatrix);
Lloyd Pique3eb1b212019-03-07 21:15:40 -0800260
261 // The dirtyRegion should be set to the full display size
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700262 EXPECT_THAT(mOutput->getState().dirtyRegion, RegionEq(Region(kDefaultDisplaySize)));
Lloyd Pique3eb1b212019-03-07 21:15:40 -0800263}
Lloyd Pique77f79a22019-04-29 15:55:40 -0700264
Lloyd Pique3eb1b212019-03-07 21:15:40 -0800265TEST_F(OutputTest, setColorTransformPerformsUpdateForIdentityToHalf) {
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700266 mOutput->editState().colorTransformMatrix = kIdentity;
Lloyd Pique77f79a22019-04-29 15:55:40 -0700267
Lloyd Pique3eb1b212019-03-07 21:15:40 -0800268 // Setting a different colorTransformMatrix should perform the update.
269 CompositionRefreshArgs refreshArgs;
270 refreshArgs.colorTransformMatrix = kNonIdentityHalf;
Lloyd Pique77f79a22019-04-29 15:55:40 -0700271
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700272 mOutput->setColorTransform(refreshArgs);
Lloyd Piqueef958122019-02-05 18:00:12 -0800273
Lloyd Pique3eb1b212019-03-07 21:15:40 -0800274 // The internal state should have been updated
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700275 EXPECT_EQ(kNonIdentityHalf, mOutput->getState().colorTransformMatrix);
Lloyd Pique3eb1b212019-03-07 21:15:40 -0800276
277 // The dirtyRegion should be set to the full display size
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700278 EXPECT_THAT(mOutput->getState().dirtyRegion, RegionEq(Region(kDefaultDisplaySize)));
Lloyd Pique3eb1b212019-03-07 21:15:40 -0800279}
280
281TEST_F(OutputTest, setColorTransformPerformsUpdateForHalfToQuarter) {
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700282 mOutput->editState().colorTransformMatrix = kNonIdentityHalf;
Lloyd Pique3eb1b212019-03-07 21:15:40 -0800283
284 // Setting a different colorTransformMatrix should perform the update.
285 CompositionRefreshArgs refreshArgs;
286 refreshArgs.colorTransformMatrix = kNonIdentityQuarter;
287
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700288 mOutput->setColorTransform(refreshArgs);
Lloyd Pique3eb1b212019-03-07 21:15:40 -0800289
290 // The internal state should have been updated
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700291 EXPECT_EQ(kNonIdentityQuarter, mOutput->getState().colorTransformMatrix);
Lloyd Pique3eb1b212019-03-07 21:15:40 -0800292
293 // The dirtyRegion should be set to the full display size
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700294 EXPECT_THAT(mOutput->getState().dirtyRegion, RegionEq(Region(kDefaultDisplaySize)));
Lloyd Pique32cbe282018-10-19 13:09:22 -0700295}
296
Lloyd Pique66d68602019-02-13 14:23:31 -0800297/*
Lloyd Pique32cbe282018-10-19 13:09:22 -0700298 * Output::setColorMode
299 */
300
Lloyd Piqueef958122019-02-05 18:00:12 -0800301TEST_F(OutputTest, setColorModeSetsStateAndDirtiesOutputIfChanged) {
Lloyd Pique6a3b4462019-03-07 20:58:12 -0800302 using ColorProfile = Output::ColorProfile;
303
Lloyd Piquef5275482019-01-29 18:42:42 -0800304 EXPECT_CALL(*mDisplayColorProfile,
305 getTargetDataspace(ui::ColorMode::DISPLAY_P3, ui::Dataspace::DISPLAY_P3,
306 ui::Dataspace::UNKNOWN))
307 .WillOnce(Return(ui::Dataspace::UNKNOWN));
Lloyd Piqueef958122019-02-05 18:00:12 -0800308 EXPECT_CALL(*mRenderSurface, setBufferDataspace(ui::Dataspace::DISPLAY_P3)).Times(1);
Lloyd Pique31cb2942018-10-19 17:23:03 -0700309
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700310 mOutput->setColorProfile(ColorProfile{ui::ColorMode::DISPLAY_P3, ui::Dataspace::DISPLAY_P3,
311 ui::RenderIntent::TONE_MAP_COLORIMETRIC,
312 ui::Dataspace::UNKNOWN});
Lloyd Pique32cbe282018-10-19 13:09:22 -0700313
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700314 EXPECT_EQ(ui::ColorMode::DISPLAY_P3, mOutput->getState().colorMode);
315 EXPECT_EQ(ui::Dataspace::DISPLAY_P3, mOutput->getState().dataspace);
316 EXPECT_EQ(ui::RenderIntent::TONE_MAP_COLORIMETRIC, mOutput->getState().renderIntent);
317 EXPECT_EQ(ui::Dataspace::UNKNOWN, mOutput->getState().targetDataspace);
Lloyd Piquef5275482019-01-29 18:42:42 -0800318
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700319 EXPECT_THAT(mOutput->getState().dirtyRegion, RegionEq(Region(kDefaultDisplaySize)));
Lloyd Piqueef958122019-02-05 18:00:12 -0800320}
321
322TEST_F(OutputTest, setColorModeDoesNothingIfNoChange) {
Lloyd Pique6a3b4462019-03-07 20:58:12 -0800323 using ColorProfile = Output::ColorProfile;
324
Lloyd Piquef5275482019-01-29 18:42:42 -0800325 EXPECT_CALL(*mDisplayColorProfile,
326 getTargetDataspace(ui::ColorMode::DISPLAY_P3, ui::Dataspace::DISPLAY_P3,
327 ui::Dataspace::UNKNOWN))
328 .WillOnce(Return(ui::Dataspace::UNKNOWN));
329
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700330 mOutput->editState().colorMode = ui::ColorMode::DISPLAY_P3;
331 mOutput->editState().dataspace = ui::Dataspace::DISPLAY_P3;
332 mOutput->editState().renderIntent = ui::RenderIntent::TONE_MAP_COLORIMETRIC;
333 mOutput->editState().targetDataspace = ui::Dataspace::UNKNOWN;
Lloyd Piqueef958122019-02-05 18:00:12 -0800334
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700335 mOutput->setColorProfile(ColorProfile{ui::ColorMode::DISPLAY_P3, ui::Dataspace::DISPLAY_P3,
336 ui::RenderIntent::TONE_MAP_COLORIMETRIC,
337 ui::Dataspace::UNKNOWN});
Lloyd Piqueef958122019-02-05 18:00:12 -0800338
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700339 EXPECT_THAT(mOutput->getState().dirtyRegion, RegionEq(Region()));
Lloyd Pique32cbe282018-10-19 13:09:22 -0700340}
341
Lloyd Pique66d68602019-02-13 14:23:31 -0800342/*
Lloyd Pique31cb2942018-10-19 17:23:03 -0700343 * Output::setRenderSurface()
344 */
345
346TEST_F(OutputTest, setRenderSurfaceResetsBounds) {
347 const ui::Size newDisplaySize{640, 480};
348
349 mock::RenderSurface* renderSurface = new StrictMock<mock::RenderSurface>();
350 EXPECT_CALL(*renderSurface, getSize()).WillOnce(ReturnRef(newDisplaySize));
351
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700352 mOutput->setRenderSurface(std::unique_ptr<RenderSurface>(renderSurface));
Lloyd Pique31cb2942018-10-19 17:23:03 -0700353
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700354 EXPECT_EQ(Rect(newDisplaySize), mOutput->getState().bounds);
Lloyd Pique31cb2942018-10-19 17:23:03 -0700355}
356
Lloyd Pique66d68602019-02-13 14:23:31 -0800357/*
Alec Mourie7d1d4a2019-02-05 01:13:46 +0000358 * Output::getDirtyRegion()
Lloyd Pique32cbe282018-10-19 13:09:22 -0700359 */
360
Alec Mourie7d1d4a2019-02-05 01:13:46 +0000361TEST_F(OutputTest, getDirtyRegionWithRepaintEverythingTrue) {
362 const Rect viewport{100, 200};
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700363 mOutput->editState().viewport = viewport;
364 mOutput->editState().dirtyRegion.set(50, 300);
Lloyd Pique32cbe282018-10-19 13:09:22 -0700365
366 {
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700367 Region result = mOutput->getDirtyRegion(true);
Lloyd Pique32cbe282018-10-19 13:09:22 -0700368
Alec Mourie7d1d4a2019-02-05 01:13:46 +0000369 EXPECT_THAT(result, RegionEq(Region(viewport)));
Lloyd Pique32cbe282018-10-19 13:09:22 -0700370 }
371}
372
Alec Mourie7d1d4a2019-02-05 01:13:46 +0000373TEST_F(OutputTest, getDirtyRegionWithRepaintEverythingFalse) {
374 const Rect viewport{100, 200};
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700375 mOutput->editState().viewport = viewport;
376 mOutput->editState().dirtyRegion.set(50, 300);
Lloyd Pique32cbe282018-10-19 13:09:22 -0700377
378 {
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700379 Region result = mOutput->getDirtyRegion(false);
Lloyd Pique32cbe282018-10-19 13:09:22 -0700380
381 // The dirtyRegion should be clipped to the display bounds.
382 EXPECT_THAT(result, RegionEq(Region(Rect(50, 200))));
383 }
Lloyd Pique32cbe282018-10-19 13:09:22 -0700384}
385
Lloyd Pique66d68602019-02-13 14:23:31 -0800386/*
Lloyd Piqueef36b002019-01-23 17:52:04 -0800387 * Output::belongsInOutput()
388 */
389
390TEST_F(OutputTest, belongsInOutputFiltersAsExpected) {
391 const uint32_t layerStack1 = 123u;
392 const uint32_t layerStack2 = 456u;
393
394 // If the output accepts layerStack1 and internal-only layers....
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700395 mOutput->setLayerStackFilter(layerStack1, true);
Lloyd Piqueef36b002019-01-23 17:52:04 -0800396
Lloyd Piquec6687342019-03-07 21:34:57 -0800397 // A layer with no layerStack does not belong to it, internal-only or not.
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700398 EXPECT_FALSE(mOutput->belongsInOutput(std::nullopt, false));
399 EXPECT_FALSE(mOutput->belongsInOutput(std::nullopt, true));
Lloyd Piquec6687342019-03-07 21:34:57 -0800400
Lloyd Piqueef36b002019-01-23 17:52:04 -0800401 // Any layer with layerStack1 belongs to it, internal-only or not.
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700402 EXPECT_TRUE(mOutput->belongsInOutput(layerStack1, false));
403 EXPECT_TRUE(mOutput->belongsInOutput(layerStack1, true));
404 EXPECT_FALSE(mOutput->belongsInOutput(layerStack2, true));
405 EXPECT_FALSE(mOutput->belongsInOutput(layerStack2, false));
Lloyd Piqueef36b002019-01-23 17:52:04 -0800406
407 // If the output accepts layerStack21 but not internal-only layers...
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700408 mOutput->setLayerStackFilter(layerStack1, false);
Lloyd Piqueef36b002019-01-23 17:52:04 -0800409
410 // Only non-internal layers with layerStack1 belong to it.
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700411 EXPECT_TRUE(mOutput->belongsInOutput(layerStack1, false));
412 EXPECT_FALSE(mOutput->belongsInOutput(layerStack1, true));
413 EXPECT_FALSE(mOutput->belongsInOutput(layerStack2, true));
414 EXPECT_FALSE(mOutput->belongsInOutput(layerStack2, false));
Lloyd Piqueef36b002019-01-23 17:52:04 -0800415}
416
Lloyd Pique66c20c42019-03-07 21:44:02 -0800417TEST_F(OutputTest, belongsInOutputFiltersLayersAsExpected) {
418 StrictMock<mock::Layer> layer;
Lloyd Pique9755fb72019-03-26 14:44:40 -0700419 LayerFECompositionState layerFEState;
Lloyd Pique66c20c42019-03-07 21:44:02 -0800420
Lloyd Pique9755fb72019-03-26 14:44:40 -0700421 EXPECT_CALL(layer, getFEState()).WillRepeatedly(ReturnRef(layerFEState));
Lloyd Pique66c20c42019-03-07 21:44:02 -0800422
423 const uint32_t layerStack1 = 123u;
424 const uint32_t layerStack2 = 456u;
425
426 // If the output accepts layerStack1 and internal-only layers....
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700427 mOutput->setLayerStackFilter(layerStack1, true);
Lloyd Pique66c20c42019-03-07 21:44:02 -0800428
429 // A null layer pointer does not belong to the output
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700430 EXPECT_FALSE(mOutput->belongsInOutput(nullptr));
Lloyd Pique66c20c42019-03-07 21:44:02 -0800431
432 // A layer with no layerStack does not belong to it, internal-only or not.
Lloyd Pique9755fb72019-03-26 14:44:40 -0700433 layerFEState.layerStackId = std::nullopt;
434 layerFEState.internalOnly = false;
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700435 EXPECT_FALSE(mOutput->belongsInOutput(&layer));
Lloyd Pique66c20c42019-03-07 21:44:02 -0800436
Lloyd Pique9755fb72019-03-26 14:44:40 -0700437 layerFEState.layerStackId = std::nullopt;
438 layerFEState.internalOnly = true;
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700439 EXPECT_FALSE(mOutput->belongsInOutput(&layer));
Lloyd Pique66c20c42019-03-07 21:44:02 -0800440
441 // Any layer with layerStack1 belongs to it, internal-only or not.
Lloyd Pique9755fb72019-03-26 14:44:40 -0700442 layerFEState.layerStackId = layerStack1;
443 layerFEState.internalOnly = false;
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700444 EXPECT_TRUE(mOutput->belongsInOutput(&layer));
Lloyd Pique66c20c42019-03-07 21:44:02 -0800445
Lloyd Pique9755fb72019-03-26 14:44:40 -0700446 layerFEState.layerStackId = layerStack1;
447 layerFEState.internalOnly = true;
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700448 EXPECT_TRUE(mOutput->belongsInOutput(&layer));
Lloyd Pique66c20c42019-03-07 21:44:02 -0800449
Lloyd Pique9755fb72019-03-26 14:44:40 -0700450 layerFEState.layerStackId = layerStack2;
451 layerFEState.internalOnly = true;
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700452 EXPECT_FALSE(mOutput->belongsInOutput(&layer));
Lloyd Pique66c20c42019-03-07 21:44:02 -0800453
Lloyd Pique9755fb72019-03-26 14:44:40 -0700454 layerFEState.layerStackId = layerStack2;
455 layerFEState.internalOnly = false;
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700456 EXPECT_FALSE(mOutput->belongsInOutput(&layer));
Lloyd Pique66c20c42019-03-07 21:44:02 -0800457
458 // If the output accepts layerStack1 but not internal-only layers...
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700459 mOutput->setLayerStackFilter(layerStack1, false);
Lloyd Pique66c20c42019-03-07 21:44:02 -0800460
461 // A null layer pointer does not belong to the output
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700462 EXPECT_FALSE(mOutput->belongsInOutput(nullptr));
Lloyd Pique66c20c42019-03-07 21:44:02 -0800463
464 // Only non-internal layers with layerStack1 belong to it.
Lloyd Pique9755fb72019-03-26 14:44:40 -0700465 layerFEState.layerStackId = layerStack1;
466 layerFEState.internalOnly = false;
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700467 EXPECT_TRUE(mOutput->belongsInOutput(&layer));
Lloyd Pique66c20c42019-03-07 21:44:02 -0800468
Lloyd Pique9755fb72019-03-26 14:44:40 -0700469 layerFEState.layerStackId = layerStack1;
470 layerFEState.internalOnly = true;
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700471 EXPECT_FALSE(mOutput->belongsInOutput(&layer));
Lloyd Pique66c20c42019-03-07 21:44:02 -0800472
Lloyd Pique9755fb72019-03-26 14:44:40 -0700473 layerFEState.layerStackId = layerStack2;
474 layerFEState.internalOnly = true;
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700475 EXPECT_FALSE(mOutput->belongsInOutput(&layer));
Lloyd Pique66c20c42019-03-07 21:44:02 -0800476
Lloyd Pique9755fb72019-03-26 14:44:40 -0700477 layerFEState.layerStackId = layerStack2;
478 layerFEState.internalOnly = false;
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700479 EXPECT_FALSE(mOutput->belongsInOutput(&layer));
Lloyd Pique66c20c42019-03-07 21:44:02 -0800480}
481
Lloyd Pique66d68602019-02-13 14:23:31 -0800482/*
Lloyd Piquecc01a452018-12-04 17:24:00 -0800483 * Output::getOutputLayerForLayer()
484 */
485
486TEST_F(OutputTest, getOutputLayerForLayerWorks) {
487 mock::OutputLayer* outputLayer1 = new StrictMock<mock::OutputLayer>();
488 mock::OutputLayer* outputLayer2 = new StrictMock<mock::OutputLayer>();
489
Lloyd Pique01c77c12019-04-17 12:48:32 -0700490 mOutput->injectOutputLayerForTest(std::unique_ptr<OutputLayer>(outputLayer1));
491 mOutput->injectOutputLayerForTest(nullptr);
492 mOutput->injectOutputLayerForTest(std::unique_ptr<OutputLayer>(outputLayer2));
Lloyd Piquecc01a452018-12-04 17:24:00 -0800493
494 StrictMock<mock::Layer> layer;
495 StrictMock<mock::Layer> otherLayer;
496
497 // If the input layer matches the first OutputLayer, it will be returned.
498 EXPECT_CALL(*outputLayer1, getLayer()).WillOnce(ReturnRef(layer));
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700499 EXPECT_EQ(outputLayer1, mOutput->getOutputLayerForLayer(&layer));
Lloyd Piquecc01a452018-12-04 17:24:00 -0800500
501 // If the input layer matches the second OutputLayer, it will be returned.
502 EXPECT_CALL(*outputLayer1, getLayer()).WillOnce(ReturnRef(otherLayer));
503 EXPECT_CALL(*outputLayer2, getLayer()).WillOnce(ReturnRef(layer));
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700504 EXPECT_EQ(outputLayer2, mOutput->getOutputLayerForLayer(&layer));
Lloyd Piquecc01a452018-12-04 17:24:00 -0800505
506 // If the input layer does not match an output layer, null will be returned.
507 EXPECT_CALL(*outputLayer1, getLayer()).WillOnce(ReturnRef(otherLayer));
508 EXPECT_CALL(*outputLayer2, getLayer()).WillOnce(ReturnRef(otherLayer));
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700509 EXPECT_EQ(nullptr, mOutput->getOutputLayerForLayer(&layer));
Lloyd Piquecc01a452018-12-04 17:24:00 -0800510}
511
Lloyd Pique66d68602019-02-13 14:23:31 -0800512/*
Alec Mourif9a2a2c2019-11-12 12:46:02 -0800513 * Output::updateAndWriteCompositionState()
514 */
515
516TEST_F(OutputTest, updateAndWriteCompositionState_takesEarlyOutIfNotEnabled) {
517 mOutput->editState().isEnabled = false;
518
519 CompositionRefreshArgs args;
520 mOutput->updateAndWriteCompositionState(args);
521}
522
523TEST_F(OutputTest, updateAndWriteCompositionState_updatesLayers) {
524 mOutput->editState().isEnabled = true;
525 mock::OutputLayer* outputLayer = new StrictMock<mock::OutputLayer>();
526 mOutput->injectOutputLayerForTest(std::unique_ptr<OutputLayer>(outputLayer));
527
528 EXPECT_CALL(*outputLayer, updateCompositionState(true, true)).Times(1);
529 EXPECT_CALL(*outputLayer, writeStateToHWC(true)).Times(1);
530
531 CompositionRefreshArgs args;
532 args.updatingGeometryThisFrame = true;
533 args.devOptForceClientComposition = true;
534 mOutput->updateAndWriteCompositionState(args);
535}
536
537/*
Lloyd Pique66d68602019-02-13 14:23:31 -0800538 * Output::prepareFrame()
539 */
540
541struct OutputPrepareFrameTest : public testing::Test {
Lloyd Piquefaa3f192019-11-14 14:05:09 -0800542 struct OutputPartialMock : public OutputPartialMockBase {
Lloyd Pique66d68602019-02-13 14:23:31 -0800543 // Sets up the helper functions called by prepareFrame to use a mock
544 // implementations.
545 MOCK_METHOD0(chooseCompositionStrategy, void());
546 };
547
548 OutputPrepareFrameTest() {
549 mOutput.setDisplayColorProfileForTest(
550 std::unique_ptr<DisplayColorProfile>(mDisplayColorProfile));
551 mOutput.setRenderSurfaceForTest(std::unique_ptr<RenderSurface>(mRenderSurface));
552 }
553
554 StrictMock<mock::CompositionEngine> mCompositionEngine;
555 mock::DisplayColorProfile* mDisplayColorProfile = new StrictMock<mock::DisplayColorProfile>();
556 mock::RenderSurface* mRenderSurface = new StrictMock<mock::RenderSurface>();
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700557 StrictMock<OutputPartialMock> mOutput;
Lloyd Pique66d68602019-02-13 14:23:31 -0800558};
559
560TEST_F(OutputPrepareFrameTest, takesEarlyOutIfNotEnabled) {
561 mOutput.editState().isEnabled = false;
562
563 mOutput.prepareFrame();
564}
565
566TEST_F(OutputPrepareFrameTest, delegatesToChooseCompositionStrategyAndRenderSurface) {
567 mOutput.editState().isEnabled = true;
568 mOutput.editState().usesClientComposition = false;
569 mOutput.editState().usesDeviceComposition = true;
570
571 EXPECT_CALL(mOutput, chooseCompositionStrategy()).Times(1);
572 EXPECT_CALL(*mRenderSurface, prepareFrame(false, true));
573
574 mOutput.prepareFrame();
575}
576
577// Note: Use OutputTest and not OutputPrepareFrameTest, so the real
578// base chooseCompositionStrategy() is invoked.
579TEST_F(OutputTest, prepareFrameSetsClientCompositionOnlyByDefault) {
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700580 mOutput->editState().isEnabled = true;
581 mOutput->editState().usesClientComposition = false;
582 mOutput->editState().usesDeviceComposition = true;
Lloyd Pique66d68602019-02-13 14:23:31 -0800583
584 EXPECT_CALL(*mRenderSurface, prepareFrame(true, false));
585
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700586 mOutput->prepareFrame();
Lloyd Pique66d68602019-02-13 14:23:31 -0800587
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700588 EXPECT_TRUE(mOutput->getState().usesClientComposition);
589 EXPECT_FALSE(mOutput->getState().usesDeviceComposition);
Lloyd Pique66d68602019-02-13 14:23:31 -0800590}
591
Lloyd Pique56eba802019-08-28 15:45:25 -0700592/*
Lloyd Piquefaa3f192019-11-14 14:05:09 -0800593 * Output::present()
594 */
595
596struct OutputPresentTest : public testing::Test {
597 struct OutputPartialMock : public OutputPartialMockBase {
598 // All child helper functions Output::present() are defined as mocks,
599 // and those are tested separately, allowing the present() test to
600 // just cover the high level flow.
601 MOCK_METHOD1(updateColorProfile, void(const compositionengine::CompositionRefreshArgs&));
602 MOCK_METHOD1(updateAndWriteCompositionState,
603 void(const compositionengine::CompositionRefreshArgs&));
604 MOCK_METHOD1(setColorTransform, void(const compositionengine::CompositionRefreshArgs&));
605 MOCK_METHOD0(beginFrame, void());
606 MOCK_METHOD0(prepareFrame, void());
607 MOCK_METHOD1(devOptRepaintFlash, void(const compositionengine::CompositionRefreshArgs&));
608 MOCK_METHOD1(finishFrame, void(const compositionengine::CompositionRefreshArgs&));
609 MOCK_METHOD0(postFramebuffer, void());
610 };
611
612 StrictMock<OutputPartialMock> mOutput;
613};
614
615TEST_F(OutputPresentTest, justInvokesChildFunctionsInSequence) {
616 CompositionRefreshArgs args;
617
618 InSequence seq;
619 EXPECT_CALL(mOutput, updateColorProfile(Ref(args)));
620 EXPECT_CALL(mOutput, updateAndWriteCompositionState(Ref(args)));
621 EXPECT_CALL(mOutput, setColorTransform(Ref(args)));
622 EXPECT_CALL(mOutput, beginFrame());
623 EXPECT_CALL(mOutput, prepareFrame());
624 EXPECT_CALL(mOutput, devOptRepaintFlash(Ref(args)));
625 EXPECT_CALL(mOutput, finishFrame(Ref(args)));
626 EXPECT_CALL(mOutput, postFramebuffer());
627
628 mOutput.present(args);
629}
630
631/*
632 * Output::updateColorProfile()
633 */
634
635// TODO(b/144060211) - Add coverage
636
637/*
638 * Output::beginFrame()
639 */
640
641/*
642 * Output::devOptRepaintFlash()
643 */
644
645// TODO(b/144060211) - Add coverage
646
647/*
648 * Output::finishFrame()
649 */
650
651// TODO(b/144060211) - Add coverage
652
653/*
654 * Output::postFramebuffer()
655 */
656
657// TODO(b/144060211) - Add coverage
658
659/*
Lloyd Pique56eba802019-08-28 15:45:25 -0700660 * Output::composeSurfaces()
661 */
662
663struct OutputComposeSurfacesTest : public testing::Test {
664 static constexpr uint32_t kDefaultOutputOrientation = TR_IDENT;
665 static constexpr ui::Dataspace kDefaultOutputDataspace = ui::Dataspace::DISPLAY_P3;
666
667 static const Rect kDefaultOutputFrame;
668 static const Rect kDefaultOutputViewport;
669 static const Rect kDefaultOutputScissor;
670 static const mat4 kDefaultColorTransformMat;
671
Lloyd Piquefaa3f192019-11-14 14:05:09 -0800672 struct OutputPartialMock : public OutputPartialMockBase {
Lloyd Pique56eba802019-08-28 15:45:25 -0700673 // Sets up the helper functions called by composeSurfaces to use a mock
674 // implementations.
675 MOCK_CONST_METHOD0(getSkipColorTransform, bool());
676 MOCK_METHOD2(generateClientCompositionRequests,
677 std::vector<renderengine::LayerSettings>(bool, Region&));
678 MOCK_METHOD2(appendRegionFlashRequests,
679 void(const Region&, std::vector<renderengine::LayerSettings>&));
680 MOCK_METHOD1(setExpensiveRenderingExpected, void(bool));
681 };
682
683 OutputComposeSurfacesTest() {
684 mOutput.setDisplayColorProfileForTest(
685 std::unique_ptr<DisplayColorProfile>(mDisplayColorProfile));
686 mOutput.setRenderSurfaceForTest(std::unique_ptr<RenderSurface>(mRenderSurface));
687
Lloyd Pique56eba802019-08-28 15:45:25 -0700688 mOutput.editState().frame = kDefaultOutputFrame;
689 mOutput.editState().viewport = kDefaultOutputViewport;
690 mOutput.editState().scissor = kDefaultOutputScissor;
691 mOutput.editState().transform = ui::Transform{kDefaultOutputOrientation};
692 mOutput.editState().orientation = kDefaultOutputOrientation;
693 mOutput.editState().dataspace = kDefaultOutputDataspace;
Lloyd Pique3eb1b212019-03-07 21:15:40 -0800694 mOutput.editState().colorTransformMatrix = kDefaultColorTransformMat;
Lloyd Pique56eba802019-08-28 15:45:25 -0700695 mOutput.editState().isSecure = true;
696 mOutput.editState().needsFiltering = false;
697 mOutput.editState().usesClientComposition = true;
698 mOutput.editState().usesDeviceComposition = false;
699
Lloyd Pique01c77c12019-04-17 12:48:32 -0700700 EXPECT_CALL(mOutput, getOutputLayerCount()).WillRepeatedly(Return(2u));
701 EXPECT_CALL(mOutput, getOutputLayerOrderedByZByIndex(0u))
702 .WillRepeatedly(Return(&mOutputLayer1));
703 EXPECT_CALL(mOutput, getOutputLayerOrderedByZByIndex(1u))
704 .WillRepeatedly(Return(&mOutputLayer2));
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700705 EXPECT_CALL(mOutput, getCompositionEngine()).WillRepeatedly(ReturnRef(mCompositionEngine));
Lloyd Pique56eba802019-08-28 15:45:25 -0700706 EXPECT_CALL(mCompositionEngine, getRenderEngine()).WillRepeatedly(ReturnRef(mRenderEngine));
707 }
708
709 StrictMock<mock::CompositionEngine> mCompositionEngine;
710 StrictMock<renderengine::mock::RenderEngine> mRenderEngine;
711 mock::DisplayColorProfile* mDisplayColorProfile = new StrictMock<mock::DisplayColorProfile>();
712 mock::RenderSurface* mRenderSurface = new StrictMock<mock::RenderSurface>();
Lloyd Pique01c77c12019-04-17 12:48:32 -0700713 StrictMock<mock::OutputLayer> mOutputLayer1;
714 StrictMock<mock::OutputLayer> mOutputLayer2;
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700715 StrictMock<OutputPartialMock> mOutput;
Lloyd Pique56eba802019-08-28 15:45:25 -0700716 sp<GraphicBuffer> mOutputBuffer = new GraphicBuffer();
717};
718
719const Rect OutputComposeSurfacesTest::kDefaultOutputFrame{1001, 1002, 1003, 1004};
720const Rect OutputComposeSurfacesTest::kDefaultOutputViewport{1005, 1006, 1007, 1008};
721const Rect OutputComposeSurfacesTest::kDefaultOutputScissor{1009, 1010, 1011, 1012};
722const mat4 OutputComposeSurfacesTest::kDefaultColorTransformMat{mat4() * 0.5};
723
724// TODO(b/121291683): Expand unit test coverage for composeSurfaces beyond these
725// basic tests.
726
727TEST_F(OutputComposeSurfacesTest, doesNothingIfNoClientComposition) {
728 mOutput.editState().usesClientComposition = false;
729
730 Region debugRegion;
Lloyd Piqued3d69882019-02-28 16:03:46 -0800731 std::optional<base::unique_fd> readyFence = mOutput.composeSurfaces(debugRegion);
732 EXPECT_TRUE(readyFence);
Lloyd Pique56eba802019-08-28 15:45:25 -0700733}
734
735TEST_F(OutputComposeSurfacesTest, worksIfNoClientLayersQueued) {
736 const Region kDebugRegion{Rect{100, 101, 102, 103}};
737
738 constexpr float kDefaultMaxLuminance = 1.0f;
739 constexpr float kDefaultAvgLuminance = 0.7f;
740 constexpr float kDefaultMinLuminance = 0.1f;
741 HdrCapabilities HdrCapabilities{{},
742 kDefaultMaxLuminance,
743 kDefaultAvgLuminance,
744 kDefaultMinLuminance};
745
746 EXPECT_CALL(mRenderEngine, supportsProtectedContent()).WillOnce(Return(false));
747 EXPECT_CALL(mRenderEngine, drawLayers(_, _, _, true, _, _)).Times(1);
748
749 EXPECT_CALL(*mDisplayColorProfile, hasWideColorGamut()).WillOnce(Return(true));
750 EXPECT_CALL(*mDisplayColorProfile, getHdrCapabilities()).WillOnce(ReturnRef(HdrCapabilities));
751
752 EXPECT_CALL(*mRenderSurface, dequeueBuffer(_)).WillOnce(Return(mOutputBuffer));
753
754 EXPECT_CALL(mOutput, getSkipColorTransform()).WillOnce(Return(false));
755 EXPECT_CALL(mOutput, generateClientCompositionRequests(false, _)).Times(1);
756 EXPECT_CALL(mOutput, appendRegionFlashRequests(RegionEq(kDebugRegion), _)).Times(1);
757 EXPECT_CALL(mOutput, setExpensiveRenderingExpected(true)).Times(1);
758 EXPECT_CALL(mOutput, setExpensiveRenderingExpected(false)).Times(1);
759
Lloyd Piqued3d69882019-02-28 16:03:46 -0800760 std::optional<base::unique_fd> readyFence = mOutput.composeSurfaces(kDebugRegion);
761 EXPECT_TRUE(readyFence);
Lloyd Pique56eba802019-08-28 15:45:25 -0700762}
763
764/*
765 * Output::generateClientCompositionRequests()
766 */
767
768struct GenerateClientCompositionRequestsTest : public testing::Test {
Lloyd Piquefaa3f192019-11-14 14:05:09 -0800769 struct OutputPartialMock : public OutputPartialMockBase {
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700770 // compositionengine::Output overrides
Lloyd Pique56eba802019-08-28 15:45:25 -0700771 std::vector<renderengine::LayerSettings> generateClientCompositionRequests(
772 bool supportsProtectedContent, Region& clearRegion) override {
773 return impl::Output::generateClientCompositionRequests(supportsProtectedContent,
774 clearRegion);
775 }
776 };
777
778 GenerateClientCompositionRequestsTest() {
779 mOutput.setDisplayColorProfileForTest(
780 std::unique_ptr<DisplayColorProfile>(mDisplayColorProfile));
781 mOutput.setRenderSurfaceForTest(std::unique_ptr<RenderSurface>(mRenderSurface));
782 }
783
Lloyd Pique56eba802019-08-28 15:45:25 -0700784 mock::DisplayColorProfile* mDisplayColorProfile = new StrictMock<mock::DisplayColorProfile>();
785 mock::RenderSurface* mRenderSurface = new StrictMock<mock::RenderSurface>();
Lloyd Piquea38ea7e2019-04-16 18:10:26 -0700786 StrictMock<OutputPartialMock> mOutput;
Lloyd Pique56eba802019-08-28 15:45:25 -0700787};
788
789// TODO(b/121291683): Add more unit test coverage for generateClientCompositionRequests
790
791TEST_F(GenerateClientCompositionRequestsTest, worksForLandscapeModeSplitScreen) {
792 // In split-screen landscape mode, the screen is rotated 90 degrees, with
793 // one layer on the left covering the left side of the output, and one layer
794 // on the right covering that side of the output.
795
Lloyd Pique01c77c12019-04-17 12:48:32 -0700796 StrictMock<mock::OutputLayer> leftOutputLayer;
797 StrictMock<mock::OutputLayer> rightOutputLayer;
Lloyd Pique56eba802019-08-28 15:45:25 -0700798
799 StrictMock<mock::Layer> leftLayer;
800 StrictMock<mock::LayerFE> leftLayerFE;
801 StrictMock<mock::Layer> rightLayer;
802 StrictMock<mock::LayerFE> rightLayerFE;
803
804 impl::OutputLayerCompositionState leftOutputLayerState;
805 leftOutputLayerState.clearClientTarget = false;
Lloyd Piquea2468662019-03-07 21:31:06 -0800806 leftOutputLayerState.visibleRegion = Region{Rect{0, 0, 1000, 1000}};
Lloyd Pique56eba802019-08-28 15:45:25 -0700807
Lloyd Pique9755fb72019-03-26 14:44:40 -0700808 LayerFECompositionState leftLayerFEState;
809 leftLayerFEState.isOpaque = true;
Lloyd Pique56eba802019-08-28 15:45:25 -0700810
811 const half3 leftLayerColor{1.f, 0.f, 0.f};
812 renderengine::LayerSettings leftLayerRESettings;
813 leftLayerRESettings.source.solidColor = leftLayerColor;
814
815 impl::OutputLayerCompositionState rightOutputLayerState;
816 rightOutputLayerState.clearClientTarget = false;
Lloyd Piquea2468662019-03-07 21:31:06 -0800817 rightOutputLayerState.visibleRegion = Region{Rect{1000, 0, 2000, 1000}};
Lloyd Pique56eba802019-08-28 15:45:25 -0700818
Lloyd Pique9755fb72019-03-26 14:44:40 -0700819 LayerFECompositionState rightLayerFEState;
820 rightLayerFEState.isOpaque = true;
Lloyd Pique56eba802019-08-28 15:45:25 -0700821
822 const half3 rightLayerColor{0.f, 1.f, 0.f};
823 renderengine::LayerSettings rightLayerRESettings;
824 rightLayerRESettings.source.solidColor = rightLayerColor;
825
Lloyd Pique01c77c12019-04-17 12:48:32 -0700826 EXPECT_CALL(leftOutputLayer, getState()).WillRepeatedly(ReturnRef(leftOutputLayerState));
827 EXPECT_CALL(leftOutputLayer, getLayer()).WillRepeatedly(ReturnRef(leftLayer));
828 EXPECT_CALL(leftOutputLayer, getLayerFE()).WillRepeatedly(ReturnRef(leftLayerFE));
829 EXPECT_CALL(leftOutputLayer, requiresClientComposition()).WillRepeatedly(Return(true));
830 EXPECT_CALL(leftOutputLayer, needsFiltering()).WillRepeatedly(Return(false));
Lloyd Pique9755fb72019-03-26 14:44:40 -0700831 EXPECT_CALL(leftLayer, getFEState()).WillRepeatedly(ReturnRef(leftLayerFEState));
Lloyd Pique56eba802019-08-28 15:45:25 -0700832 EXPECT_CALL(leftLayerFE, prepareClientComposition(_)).WillOnce(Return(leftLayerRESettings));
833
Lloyd Pique01c77c12019-04-17 12:48:32 -0700834 EXPECT_CALL(rightOutputLayer, getState()).WillRepeatedly(ReturnRef(rightOutputLayerState));
835 EXPECT_CALL(rightOutputLayer, getLayer()).WillRepeatedly(ReturnRef(rightLayer));
836 EXPECT_CALL(rightOutputLayer, getLayerFE()).WillRepeatedly(ReturnRef(rightLayerFE));
837 EXPECT_CALL(rightOutputLayer, requiresClientComposition()).WillRepeatedly(Return(true));
838 EXPECT_CALL(rightOutputLayer, needsFiltering()).WillRepeatedly(Return(false));
Lloyd Pique9755fb72019-03-26 14:44:40 -0700839 EXPECT_CALL(rightLayer, getFEState()).WillRepeatedly(ReturnRef(rightLayerFEState));
Lloyd Pique56eba802019-08-28 15:45:25 -0700840 EXPECT_CALL(rightLayerFE, prepareClientComposition(_)).WillOnce(Return(rightLayerRESettings));
841
Lloyd Pique01c77c12019-04-17 12:48:32 -0700842 EXPECT_CALL(mOutput, getOutputLayerCount()).WillRepeatedly(Return(2u));
843 EXPECT_CALL(mOutput, getOutputLayerOrderedByZByIndex(0u))
844 .WillRepeatedly(Return(&leftOutputLayer));
845 EXPECT_CALL(mOutput, getOutputLayerOrderedByZByIndex(1u))
846 .WillRepeatedly(Return(&rightOutputLayer));
Lloyd Pique56eba802019-08-28 15:45:25 -0700847
848 const Rect kPortraitFrame(0, 0, 1000, 2000);
849 const Rect kPortraitViewport(0, 0, 2000, 1000);
850 const Rect kPortraitScissor(0, 0, 1000, 2000);
851 const uint32_t kPortraitOrientation = TR_ROT_90;
852
853 mOutput.editState().frame = kPortraitFrame;
854 mOutput.editState().viewport = kPortraitViewport;
855 mOutput.editState().scissor = kPortraitScissor;
856 mOutput.editState().transform = ui::Transform{kPortraitOrientation};
857 mOutput.editState().orientation = kPortraitOrientation;
858 mOutput.editState().needsFiltering = true;
859 mOutput.editState().isSecure = false;
860
861 constexpr bool supportsProtectedContent = false;
862 Region clearRegion;
863 auto requests =
864 mOutput.generateClientCompositionRequests(supportsProtectedContent, clearRegion);
865
866 ASSERT_EQ(2u, requests.size());
867 EXPECT_EQ(leftLayerColor, requests[0].source.solidColor);
868 EXPECT_EQ(rightLayerColor, requests[1].source.solidColor);
869}
870
871TEST_F(GenerateClientCompositionRequestsTest, ignoresLayersThatDoNotIntersectWithViewport) {
872 // Layers whose visible region does not intersect with the viewport will be
873 // skipped when generating client composition request state.
874
Lloyd Pique01c77c12019-04-17 12:48:32 -0700875 StrictMock<mock::OutputLayer> outputLayer;
Lloyd Pique56eba802019-08-28 15:45:25 -0700876 StrictMock<mock::Layer> layer;
877 StrictMock<mock::LayerFE> layerFE;
878
879 impl::OutputLayerCompositionState outputLayerState;
880 outputLayerState.clearClientTarget = false;
Lloyd Piquea2468662019-03-07 21:31:06 -0800881 outputLayerState.visibleRegion = Region{Rect{3000, 0, 4000, 1000}};
Lloyd Pique56eba802019-08-28 15:45:25 -0700882
Lloyd Pique9755fb72019-03-26 14:44:40 -0700883 LayerFECompositionState layerFEState;
884 layerFEState.isOpaque = true;
Lloyd Pique56eba802019-08-28 15:45:25 -0700885
Lloyd Pique01c77c12019-04-17 12:48:32 -0700886 EXPECT_CALL(outputLayer, getState()).WillRepeatedly(ReturnRef(outputLayerState));
887 EXPECT_CALL(outputLayer, getLayer()).WillRepeatedly(ReturnRef(layer));
888 EXPECT_CALL(outputLayer, getLayerFE()).WillRepeatedly(ReturnRef(layerFE));
889 EXPECT_CALL(outputLayer, requiresClientComposition()).WillRepeatedly(Return(true));
890 EXPECT_CALL(outputLayer, needsFiltering()).WillRepeatedly(Return(false));
Lloyd Pique9755fb72019-03-26 14:44:40 -0700891 EXPECT_CALL(layer, getFEState()).WillRepeatedly(ReturnRef(layerFEState));
Lloyd Pique56eba802019-08-28 15:45:25 -0700892 EXPECT_CALL(layerFE, prepareClientComposition(_)).Times(0);
893
Lloyd Pique01c77c12019-04-17 12:48:32 -0700894 EXPECT_CALL(mOutput, getOutputLayerCount()).WillRepeatedly(Return(1u));
895 EXPECT_CALL(mOutput, getOutputLayerOrderedByZByIndex(0u)).WillRepeatedly(Return(&outputLayer));
Lloyd Pique56eba802019-08-28 15:45:25 -0700896
897 const Rect kPortraitFrame(0, 0, 1000, 2000);
898 const Rect kPortraitViewport(0, 0, 2000, 1000);
899 const Rect kPortraitScissor(0, 0, 1000, 2000);
900 const uint32_t kPortraitOrientation = TR_ROT_90;
901
902 mOutput.editState().frame = kPortraitFrame;
903 mOutput.editState().viewport = kPortraitViewport;
904 mOutput.editState().scissor = kPortraitScissor;
905 mOutput.editState().transform = ui::Transform{kPortraitOrientation};
906 mOutput.editState().orientation = kPortraitOrientation;
907 mOutput.editState().needsFiltering = true;
908 mOutput.editState().isSecure = false;
909
910 constexpr bool supportsProtectedContent = false;
911 Region clearRegion;
912 auto requests =
913 mOutput.generateClientCompositionRequests(supportsProtectedContent, clearRegion);
914
915 EXPECT_EQ(0u, requests.size());
916}
917
Lloyd Piquec2d54d42019-08-28 18:04:21 -0700918TEST_F(GenerateClientCompositionRequestsTest, clearsDeviceLayesAfterFirst) {
919 // If client composition is performed with some layers set to use device
920 // composition, device layers after the first layer (device or client) will
921 // clear the frame buffer if they are opaque and if that layer has a flag
922 // set to do so. The first layer is skipped as the frame buffer is already
923 // expected to be clear.
924
Lloyd Pique01c77c12019-04-17 12:48:32 -0700925 StrictMock<mock::OutputLayer> leftOutputLayer;
926 StrictMock<mock::OutputLayer> rightOutputLayer;
Lloyd Piquec2d54d42019-08-28 18:04:21 -0700927
928 StrictMock<mock::Layer> leftLayer;
929 StrictMock<mock::LayerFE> leftLayerFE;
930 StrictMock<mock::Layer> rightLayer;
931 StrictMock<mock::LayerFE> rightLayerFE;
932
933 impl::OutputLayerCompositionState leftOutputLayerState;
934 leftOutputLayerState.clearClientTarget = true;
Lloyd Piquea2468662019-03-07 21:31:06 -0800935 leftOutputLayerState.visibleRegion = Region{Rect{0, 0, 1000, 1000}};
Lloyd Piquec2d54d42019-08-28 18:04:21 -0700936
Lloyd Pique9755fb72019-03-26 14:44:40 -0700937 LayerFECompositionState leftLayerFEState;
938 leftLayerFEState.isOpaque = true;
Lloyd Piquec2d54d42019-08-28 18:04:21 -0700939
940 impl::OutputLayerCompositionState rightOutputLayerState;
941 rightOutputLayerState.clearClientTarget = true;
Lloyd Piquea2468662019-03-07 21:31:06 -0800942 rightOutputLayerState.visibleRegion = Region{Rect{1000, 0, 2000, 1000}};
Lloyd Piquec2d54d42019-08-28 18:04:21 -0700943
Lloyd Pique9755fb72019-03-26 14:44:40 -0700944 LayerFECompositionState rightLayerFEState;
945 rightLayerFEState.isOpaque = true;
Lloyd Piquec2d54d42019-08-28 18:04:21 -0700946
947 const half3 rightLayerColor{0.f, 1.f, 0.f};
948 renderengine::LayerSettings rightLayerRESettings;
949 rightLayerRESettings.geometry.boundaries = FloatRect{456, 0, 0, 0};
950 rightLayerRESettings.source.solidColor = rightLayerColor;
951
Lloyd Pique01c77c12019-04-17 12:48:32 -0700952 EXPECT_CALL(leftOutputLayer, getState()).WillRepeatedly(ReturnRef(leftOutputLayerState));
953 EXPECT_CALL(leftOutputLayer, getLayer()).WillRepeatedly(ReturnRef(leftLayer));
954 EXPECT_CALL(leftOutputLayer, getLayerFE()).WillRepeatedly(ReturnRef(leftLayerFE));
955 EXPECT_CALL(leftOutputLayer, requiresClientComposition()).WillRepeatedly(Return(false));
956 EXPECT_CALL(leftOutputLayer, needsFiltering()).WillRepeatedly(Return(false));
Lloyd Pique9755fb72019-03-26 14:44:40 -0700957 EXPECT_CALL(leftLayer, getFEState()).WillRepeatedly(ReturnRef(leftLayerFEState));
Lloyd Piquec2d54d42019-08-28 18:04:21 -0700958
Lloyd Pique01c77c12019-04-17 12:48:32 -0700959 EXPECT_CALL(rightOutputLayer, getState()).WillRepeatedly(ReturnRef(rightOutputLayerState));
960 EXPECT_CALL(rightOutputLayer, getLayer()).WillRepeatedly(ReturnRef(rightLayer));
961 EXPECT_CALL(rightOutputLayer, getLayerFE()).WillRepeatedly(ReturnRef(rightLayerFE));
962 EXPECT_CALL(rightOutputLayer, requiresClientComposition()).WillRepeatedly(Return(false));
963 EXPECT_CALL(rightOutputLayer, needsFiltering()).WillRepeatedly(Return(false));
Lloyd Pique9755fb72019-03-26 14:44:40 -0700964 EXPECT_CALL(rightLayer, getFEState()).WillRepeatedly(ReturnRef(rightLayerFEState));
Lloyd Piquec2d54d42019-08-28 18:04:21 -0700965 EXPECT_CALL(rightLayerFE, prepareClientComposition(_)).WillOnce(Return(rightLayerRESettings));
966
Lloyd Pique01c77c12019-04-17 12:48:32 -0700967 EXPECT_CALL(mOutput, getOutputLayerCount()).WillRepeatedly(Return(2u));
968 EXPECT_CALL(mOutput, getOutputLayerOrderedByZByIndex(0u))
969 .WillRepeatedly(Return(&leftOutputLayer));
970 EXPECT_CALL(mOutput, getOutputLayerOrderedByZByIndex(1u))
971 .WillRepeatedly(Return(&rightOutputLayer));
Lloyd Piquec2d54d42019-08-28 18:04:21 -0700972
973 const Rect kPortraitFrame(0, 0, 1000, 2000);
974 const Rect kPortraitViewport(0, 0, 2000, 1000);
975 const Rect kPortraitScissor(0, 0, 1000, 2000);
976 const uint32_t kPortraitOrientation = TR_ROT_90;
977
978 mOutput.editState().frame = kPortraitFrame;
979 mOutput.editState().viewport = kPortraitViewport;
980 mOutput.editState().scissor = kPortraitScissor;
981 mOutput.editState().transform = ui::Transform{kPortraitOrientation};
982 mOutput.editState().orientation = kPortraitOrientation;
983 mOutput.editState().needsFiltering = true;
984 mOutput.editState().isSecure = false;
985
986 constexpr bool supportsProtectedContent = false;
987 Region clearRegion;
988 auto requests =
989 mOutput.generateClientCompositionRequests(supportsProtectedContent, clearRegion);
990
991 const half3 clearColor{0.f, 0.f, 0.f};
992
993 ASSERT_EQ(1u, requests.size());
994 EXPECT_EQ(456.f, requests[0].geometry.boundaries.left);
995 EXPECT_EQ(clearColor, requests[0].source.solidColor);
996}
997
Lloyd Pique32cbe282018-10-19 13:09:22 -0700998} // namespace
999} // namespace android::compositionengine