1 /*
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 
19 #include <compositionengine/DisplayColorProfileCreationArgs.h>
20 #include <compositionengine/DisplayCreationArgs.h>
21 #include <compositionengine/DisplaySurface.h>
22 #include <compositionengine/RenderSurfaceCreationArgs.h>
23 #include <compositionengine/impl/Display.h>
24 #include <compositionengine/mock/CompositionEngine.h>
25 #include <compositionengine/mock/NativeWindow.h>
26 #include <compositionengine/mock/RenderSurface.h>
27 #include <gtest/gtest.h>
28 
29 #include "MockHWComposer.h"
30 
31 namespace android::compositionengine {
32 namespace {
33 
34 using testing::Return;
35 using testing::ReturnRef;
36 using testing::StrictMock;
37 
38 constexpr DisplayId DEFAULT_DISPLAY_ID = DisplayId{42};
39 
40 class DisplayTest : public testing::Test {
41 public:
42     ~DisplayTest() override = default;
43 
44     StrictMock<android::mock::HWComposer> mHwComposer;
45     StrictMock<mock::CompositionEngine> mCompositionEngine;
46     sp<mock::NativeWindow> mNativeWindow = new StrictMock<mock::NativeWindow>();
47     impl::Display mDisplay{mCompositionEngine,
48                            DisplayCreationArgsBuilder().setDisplayId(DEFAULT_DISPLAY_ID).build()};
49 };
50 
51 /* ------------------------------------------------------------------------
52  * Basic construction
53  */
54 
TEST_F(DisplayTest,canInstantiateDisplay)55 TEST_F(DisplayTest, canInstantiateDisplay) {
56     {
57         constexpr DisplayId display1 = DisplayId{123u};
58         auto display =
59                 impl::createDisplay(mCompositionEngine,
60                                     DisplayCreationArgsBuilder().setDisplayId(display1).build());
61         EXPECT_FALSE(display->isSecure());
62         EXPECT_FALSE(display->isVirtual());
63         EXPECT_EQ(display1, display->getId());
64     }
65 
66     {
67         constexpr DisplayId display2 = DisplayId{546u};
68         auto display = impl::createDisplay(mCompositionEngine,
69                                            DisplayCreationArgsBuilder()
70                                                    .setIsSecure(true)
71                                                    .setDisplayId(display2)
72                                                    .build());
73         EXPECT_TRUE(display->isSecure());
74         EXPECT_FALSE(display->isVirtual());
75         EXPECT_EQ(display2, display->getId());
76     }
77 
78     {
79         constexpr DisplayId display3 = DisplayId{789u};
80         auto display = impl::createDisplay(mCompositionEngine,
81                                            DisplayCreationArgsBuilder()
82                                                    .setIsVirtual(true)
83                                                    .setDisplayId(display3)
84                                                    .build());
85         EXPECT_FALSE(display->isSecure());
86         EXPECT_TRUE(display->isVirtual());
87         EXPECT_EQ(display3, display->getId());
88     }
89 }
90 
91 /* ------------------------------------------------------------------------
92  * Display::disconnect()
93  */
94 
TEST_F(DisplayTest,disconnectDisconnectsDisplay)95 TEST_F(DisplayTest, disconnectDisconnectsDisplay) {
96     EXPECT_CALL(mCompositionEngine, getHwComposer()).WillRepeatedly(ReturnRef(mHwComposer));
97 
98     // The first call to disconnect will disconnect the display with the HWC and
99     // set mHwcId to -1.
100     EXPECT_CALL(mHwComposer, disconnectDisplay(DEFAULT_DISPLAY_ID)).Times(1);
101     mDisplay.disconnect();
102     EXPECT_FALSE(mDisplay.getId());
103 
104     // Subsequent calls will do nothing,
105     EXPECT_CALL(mHwComposer, disconnectDisplay(DEFAULT_DISPLAY_ID)).Times(0);
106     mDisplay.disconnect();
107     EXPECT_FALSE(mDisplay.getId());
108 }
109 
110 /* ------------------------------------------------------------------------
111  * Display::setColorTransform()
112  */
113 
TEST_F(DisplayTest,setColorTransformSetsTransform)114 TEST_F(DisplayTest, setColorTransformSetsTransform) {
115     // Identity matrix sets an identity state value
116     const mat4 identity;
117 
118     EXPECT_CALL(mCompositionEngine, getHwComposer()).WillRepeatedly(ReturnRef(mHwComposer));
119 
120     EXPECT_CALL(mHwComposer, setColorTransform(DEFAULT_DISPLAY_ID, identity)).Times(1);
121 
122     mDisplay.setColorTransform(identity);
123 
124     EXPECT_EQ(HAL_COLOR_TRANSFORM_IDENTITY, mDisplay.getState().colorTransform);
125 
126     // Non-identity matrix sets a non-identity state value
127     const mat4 nonIdentity = mat4() * 2;
128 
129     EXPECT_CALL(mHwComposer, setColorTransform(DEFAULT_DISPLAY_ID, nonIdentity)).Times(1);
130 
131     mDisplay.setColorTransform(nonIdentity);
132 
133     EXPECT_EQ(HAL_COLOR_TRANSFORM_ARBITRARY_MATRIX, mDisplay.getState().colorTransform);
134 }
135 
136 /* ------------------------------------------------------------------------
137  * Display::setColorMode()
138  */
139 
TEST_F(DisplayTest,setColorModeSetsModeUnlessNoChange)140 TEST_F(DisplayTest, setColorModeSetsModeUnlessNoChange) {
141     mock::RenderSurface* renderSurface = new StrictMock<mock::RenderSurface>();
142     mDisplay.setRenderSurfaceForTest(std::unique_ptr<RenderSurface>(renderSurface));
143 
144     EXPECT_CALL(mCompositionEngine, getHwComposer()).WillRepeatedly(ReturnRef(mHwComposer));
145 
146     // These values are expected to be the initial state.
147     ASSERT_EQ(ui::ColorMode::NATIVE, mDisplay.getState().colorMode);
148     ASSERT_EQ(ui::Dataspace::UNKNOWN, mDisplay.getState().dataspace);
149     ASSERT_EQ(ui::RenderIntent::COLORIMETRIC, mDisplay.getState().renderIntent);
150 
151     // Otherwise if the values are unchanged, nothing happens
152     mDisplay.setColorMode(ui::ColorMode::NATIVE, ui::Dataspace::UNKNOWN,
153                           ui::RenderIntent::COLORIMETRIC);
154 
155     EXPECT_EQ(ui::ColorMode::NATIVE, mDisplay.getState().colorMode);
156     EXPECT_EQ(ui::Dataspace::UNKNOWN, mDisplay.getState().dataspace);
157     EXPECT_EQ(ui::RenderIntent::COLORIMETRIC, mDisplay.getState().renderIntent);
158 
159     // Otherwise if the values are different, updates happen
160     EXPECT_CALL(*renderSurface, setBufferDataspace(ui::Dataspace::DISPLAY_P3)).Times(1);
161     EXPECT_CALL(mHwComposer,
162                 setActiveColorMode(DEFAULT_DISPLAY_ID, ui::ColorMode::DISPLAY_P3,
163                                    ui::RenderIntent::TONE_MAP_COLORIMETRIC))
164             .Times(1);
165 
166     mDisplay.setColorMode(ui::ColorMode::DISPLAY_P3, ui::Dataspace::DISPLAY_P3,
167                           ui::RenderIntent::TONE_MAP_COLORIMETRIC);
168 
169     EXPECT_EQ(ui::ColorMode::DISPLAY_P3, mDisplay.getState().colorMode);
170     EXPECT_EQ(ui::Dataspace::DISPLAY_P3, mDisplay.getState().dataspace);
171     EXPECT_EQ(ui::RenderIntent::TONE_MAP_COLORIMETRIC, mDisplay.getState().renderIntent);
172 }
173 
TEST_F(DisplayTest,setColorModeDoesNothingForVirtualDisplay)174 TEST_F(DisplayTest, setColorModeDoesNothingForVirtualDisplay) {
175     impl::Display virtualDisplay{mCompositionEngine,
176                                  DisplayCreationArgs{false, true, DEFAULT_DISPLAY_ID}};
177 
178     virtualDisplay.setColorMode(ui::ColorMode::DISPLAY_P3, ui::Dataspace::DISPLAY_P3,
179                                 ui::RenderIntent::TONE_MAP_COLORIMETRIC);
180 
181     EXPECT_EQ(ui::ColorMode::NATIVE, virtualDisplay.getState().colorMode);
182     EXPECT_EQ(ui::Dataspace::UNKNOWN, virtualDisplay.getState().dataspace);
183     EXPECT_EQ(ui::RenderIntent::COLORIMETRIC, virtualDisplay.getState().renderIntent);
184 }
185 
186 /* ------------------------------------------------------------------------
187  * Display::createDisplayColorProfile()
188  */
189 
TEST_F(DisplayTest,createDisplayColorProfileSetsDisplayColorProfile)190 TEST_F(DisplayTest, createDisplayColorProfileSetsDisplayColorProfile) {
191     EXPECT_TRUE(mDisplay.getDisplayColorProfile() == nullptr);
192     mDisplay.createDisplayColorProfile(
193             DisplayColorProfileCreationArgs{false, HdrCapabilities(), 0,
194                                             DisplayColorProfileCreationArgs::HwcColorModes()});
195     EXPECT_TRUE(mDisplay.getDisplayColorProfile() != nullptr);
196 }
197 
198 /* ------------------------------------------------------------------------
199  * Display::createRenderSurface()
200  */
201 
TEST_F(DisplayTest,createRenderSurfaceSetsRenderSurface)202 TEST_F(DisplayTest, createRenderSurfaceSetsRenderSurface) {
203     EXPECT_CALL(*mNativeWindow, disconnect(NATIVE_WINDOW_API_EGL)).WillRepeatedly(Return(NO_ERROR));
204     EXPECT_TRUE(mDisplay.getRenderSurface() == nullptr);
205     mDisplay.createRenderSurface(RenderSurfaceCreationArgs{640, 480, mNativeWindow, nullptr});
206     EXPECT_TRUE(mDisplay.getRenderSurface() != nullptr);
207 }
208 
209 } // namespace
210 } // namespace android::compositionengine
211