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 <cstdarg>
18 #include <cstdint>
19
20 #include <compositionengine/RenderSurfaceCreationArgs.h>
21 #include <compositionengine/impl/OutputCompositionState.h>
22 #include <compositionengine/impl/RenderSurface.h>
23 #include <compositionengine/mock/CompositionEngine.h>
24 #include <compositionengine/mock/Display.h>
25 #include <compositionengine/mock/DisplaySurface.h>
26 #include <compositionengine/mock/NativeWindow.h>
27 #include <compositionengine/mock/OutputLayer.h>
28 #include <gtest/gtest.h>
29 #include <renderengine/ExternalTexture.h>
30 #include <renderengine/impl/ExternalTexture.h>
31 #include <renderengine/mock/RenderEngine.h>
32 #include <ui/GraphicBuffer.h>
33
34 namespace android::compositionengine {
35 namespace {
36
37 constexpr int32_t DEFAULT_DISPLAY_WIDTH = 1920;
38 constexpr int32_t DEFAULT_DISPLAY_HEIGHT = 1080;
39 constexpr DisplayId DEFAULT_DISPLAY_ID = PhysicalDisplayId::fromPort(123u);
40 const std::string DEFAULT_DISPLAY_NAME = "Mock Display";
41
42 using testing::_;
43 using testing::ByMove;
44 using testing::DoAll;
45 using testing::Ref;
46 using testing::Return;
47 using testing::ReturnRef;
48 using testing::SetArgPointee;
49 using testing::StrictMock;
50
51 class RenderSurfaceTest : public testing::Test {
52 public:
RenderSurfaceTest()53 RenderSurfaceTest() {
54 EXPECT_CALL(mDisplay, getId()).WillRepeatedly(Return(DEFAULT_DISPLAY_ID));
55 EXPECT_CALL(mDisplay, getName()).WillRepeatedly(ReturnRef(DEFAULT_DISPLAY_NAME));
56 EXPECT_CALL(mCompositionEngine, getRenderEngine).WillRepeatedly(ReturnRef(mRenderEngine));
57 EXPECT_CALL(*mNativeWindow, disconnect(NATIVE_WINDOW_API_EGL))
58 .WillRepeatedly(Return(NO_ERROR));
59 }
60
61 StrictMock<renderengine::mock::RenderEngine> mRenderEngine;
62 StrictMock<mock::CompositionEngine> mCompositionEngine;
63 StrictMock<mock::Display> mDisplay;
64 sp<mock::NativeWindow> mNativeWindow = sp<StrictMock<mock::NativeWindow>>::make();
65 sp<mock::DisplaySurface> mDisplaySurface = sp<StrictMock<mock::DisplaySurface>>::make();
66 impl::RenderSurface mSurface{mCompositionEngine, mDisplay,
67 RenderSurfaceCreationArgsBuilder()
68 .setDisplayWidth(DEFAULT_DISPLAY_WIDTH)
69 .setDisplayHeight(DEFAULT_DISPLAY_HEIGHT)
70 .setNativeWindow(mNativeWindow)
71 .setDisplaySurface(mDisplaySurface)
72 .build()};
73 };
74
75 /*
76 * Basic construction
77 */
78
TEST_F(RenderSurfaceTest,canInstantiate)79 TEST_F(RenderSurfaceTest, canInstantiate) {
80 EXPECT_TRUE(mSurface.isValid());
81 }
82
83 /*
84 * RenderSurface::initialize()
85 */
86
TEST_F(RenderSurfaceTest,initializeConfiguresNativeWindow)87 TEST_F(RenderSurfaceTest, initializeConfiguresNativeWindow) {
88 EXPECT_CALL(*mNativeWindow, connect(NATIVE_WINDOW_API_EGL)).WillOnce(Return(NO_ERROR));
89 EXPECT_CALL(*mNativeWindow, setBuffersFormat(HAL_PIXEL_FORMAT_RGBA_8888))
90 .WillOnce(Return(NO_ERROR));
91 EXPECT_CALL(*mNativeWindow, setUsage(GRALLOC_USAGE_HW_RENDER | GRALLOC_USAGE_HW_TEXTURE))
92 .WillOnce(Return(NO_ERROR));
93
94 mSurface.initialize();
95 }
96
97 /*
98 * RenderSurface::getSize()
99 */
100
TEST_F(RenderSurfaceTest,sizeReturnsConstructedSize)101 TEST_F(RenderSurfaceTest, sizeReturnsConstructedSize) {
102 const ui::Size expected{DEFAULT_DISPLAY_WIDTH, DEFAULT_DISPLAY_HEIGHT};
103
104 EXPECT_EQ(expected, mSurface.getSize());
105 }
106
107 /*
108 * RenderSurface::getClientTargetAcquireFence()
109 */
110
TEST_F(RenderSurfaceTest,getClientTargetAcquireFenceForwardsCall)111 TEST_F(RenderSurfaceTest, getClientTargetAcquireFenceForwardsCall) {
112 sp<Fence> fence = sp<Fence>::make();
113
114 EXPECT_CALL(*mDisplaySurface, getClientTargetAcquireFence()).WillOnce(ReturnRef(fence));
115
116 EXPECT_EQ(fence.get(), mSurface.getClientTargetAcquireFence().get());
117 }
118
119 /*
120 * RenderSurface::setDisplaySize()
121 */
122
TEST_F(RenderSurfaceTest,setDisplaySizeAppliesChange)123 TEST_F(RenderSurfaceTest, setDisplaySizeAppliesChange) {
124 const ui::Size size(640, 480);
125 EXPECT_CALL(*mDisplaySurface, resizeBuffers(size)).Times(1);
126
127 mSurface.setDisplaySize(size);
128 }
129
130 /*
131 * RenderSurface::setBufferDataspace()
132 */
133
TEST_F(RenderSurfaceTest,setBufferDataspaceAppliesChange)134 TEST_F(RenderSurfaceTest, setBufferDataspaceAppliesChange) {
135 EXPECT_CALL(*mNativeWindow, setBuffersDataSpace(ui::Dataspace::DISPLAY_P3))
136 .WillOnce(Return(NO_ERROR));
137
138 mSurface.setBufferDataspace(ui::Dataspace::DISPLAY_P3);
139 }
140
141 /*
142 * RenderSurface::setProtected()
143 */
144
TEST_F(RenderSurfaceTest,setProtectedTrueEnablesProtection)145 TEST_F(RenderSurfaceTest, setProtectedTrueEnablesProtection) {
146 EXPECT_FALSE(mSurface.isProtected());
147 EXPECT_CALL(*mNativeWindow,
148 setUsage(GRALLOC_USAGE_HW_RENDER | GRALLOC_USAGE_HW_TEXTURE |
149 GRALLOC_USAGE_PROTECTED))
150 .WillOnce(Return(NO_ERROR));
151
152 mSurface.setProtected(true);
153 EXPECT_TRUE(mSurface.isProtected());
154 }
155
TEST_F(RenderSurfaceTest,setProtectedFalseDisablesProtection)156 TEST_F(RenderSurfaceTest, setProtectedFalseDisablesProtection) {
157 EXPECT_FALSE(mSurface.isProtected());
158 EXPECT_CALL(*mNativeWindow, setUsage(GRALLOC_USAGE_HW_RENDER | GRALLOC_USAGE_HW_TEXTURE))
159 .WillOnce(Return(NO_ERROR));
160
161 mSurface.setProtected(false);
162 EXPECT_FALSE(mSurface.isProtected());
163 }
164
TEST_F(RenderSurfaceTest,setProtectedEnableAndDisable)165 TEST_F(RenderSurfaceTest, setProtectedEnableAndDisable) {
166 EXPECT_FALSE(mSurface.isProtected());
167 EXPECT_CALL(*mNativeWindow,
168 setUsage(GRALLOC_USAGE_HW_RENDER | GRALLOC_USAGE_HW_TEXTURE |
169 GRALLOC_USAGE_PROTECTED))
170 .WillOnce(Return(NO_ERROR));
171 EXPECT_CALL(*mNativeWindow, setUsage(GRALLOC_USAGE_HW_RENDER | GRALLOC_USAGE_HW_TEXTURE))
172 .WillOnce(Return(NO_ERROR));
173
174 mSurface.setProtected(true);
175 EXPECT_TRUE(mSurface.isProtected());
176 mSurface.setProtected(false);
177 EXPECT_FALSE(mSurface.isProtected());
178 }
179
TEST_F(RenderSurfaceTest,setProtectedEnableWithError)180 TEST_F(RenderSurfaceTest, setProtectedEnableWithError) {
181 EXPECT_FALSE(mSurface.isProtected());
182 EXPECT_CALL(*mNativeWindow,
183 setUsage(GRALLOC_USAGE_HW_RENDER | GRALLOC_USAGE_HW_TEXTURE |
184 GRALLOC_USAGE_PROTECTED))
185 .WillOnce(Return(INVALID_OPERATION));
186 mSurface.setProtected(true);
187 EXPECT_FALSE(mSurface.isProtected());
188 }
189
190 /*
191 * RenderSurface::beginFrame()
192 */
193
TEST_F(RenderSurfaceTest,beginFrameAppliesChange)194 TEST_F(RenderSurfaceTest, beginFrameAppliesChange) {
195 EXPECT_CALL(*mDisplaySurface, beginFrame(true)).WillOnce(Return(NO_ERROR));
196
197 EXPECT_EQ(NO_ERROR, mSurface.beginFrame(true));
198 }
199
200 /*
201 * RenderSurface::prepareFrame()
202 */
203
TEST_F(RenderSurfaceTest,prepareFrameHandlesMixedComposition)204 TEST_F(RenderSurfaceTest, prepareFrameHandlesMixedComposition) {
205 EXPECT_CALL(*mDisplaySurface, prepareFrame(DisplaySurface::CompositionType::Mixed))
206 .WillOnce(Return(NO_ERROR));
207
208 mSurface.prepareFrame(true, true);
209 }
210
TEST_F(RenderSurfaceTest,prepareFrameHandlesOnlyGpuComposition)211 TEST_F(RenderSurfaceTest, prepareFrameHandlesOnlyGpuComposition) {
212 EXPECT_CALL(*mDisplaySurface, prepareFrame(DisplaySurface::CompositionType::Gpu))
213 .WillOnce(Return(NO_ERROR));
214
215 mSurface.prepareFrame(true, false);
216 }
217
TEST_F(RenderSurfaceTest,prepareFrameHandlesOnlyHwcComposition)218 TEST_F(RenderSurfaceTest, prepareFrameHandlesOnlyHwcComposition) {
219 EXPECT_CALL(*mDisplaySurface, prepareFrame(DisplaySurface::CompositionType::Hwc))
220 .WillOnce(Return(NO_ERROR));
221
222 mSurface.prepareFrame(false, true);
223 }
224
TEST_F(RenderSurfaceTest,prepareFrameHandlesNoComposition)225 TEST_F(RenderSurfaceTest, prepareFrameHandlesNoComposition) {
226 EXPECT_CALL(*mDisplaySurface, prepareFrame(DisplaySurface::CompositionType::Hwc))
227 .WillOnce(Return(NO_ERROR));
228
229 mSurface.prepareFrame(false, false);
230 }
231
232 /*
233 * RenderSurface::dequeueBuffer()
234 */
235
TEST_F(RenderSurfaceTest,dequeueBufferObtainsABuffer)236 TEST_F(RenderSurfaceTest, dequeueBufferObtainsABuffer) {
237 sp<GraphicBuffer> buffer = sp<GraphicBuffer>::make();
238
239 EXPECT_CALL(*mNativeWindow, dequeueBuffer(_, _))
240 .WillOnce(
241 DoAll(SetArgPointee<0>(buffer.get()), SetArgPointee<1>(-1), Return(NO_ERROR)));
242
243 base::unique_fd fence;
244 EXPECT_EQ(buffer.get(), mSurface.dequeueBuffer(&fence)->getBuffer().get());
245
246 EXPECT_EQ(buffer.get(), mSurface.mutableTextureForTest()->getBuffer().get());
247 }
248
249 /*
250 * RenderSurface::queueBuffer()
251 */
252
TEST_F(RenderSurfaceTest,queueBufferHandlesNoClientComposition)253 TEST_F(RenderSurfaceTest, queueBufferHandlesNoClientComposition) {
254 const auto buffer = std::make_shared<
255 renderengine::impl::
256 ExternalTexture>(sp<GraphicBuffer>::make(), mRenderEngine,
257 renderengine::impl::ExternalTexture::Usage::READABLE |
258 renderengine::impl::ExternalTexture::Usage::WRITEABLE);
259 mSurface.mutableTextureForTest() = buffer;
260
261 impl::OutputCompositionState state;
262 state.usesClientComposition = false;
263 state.flipClientTarget = false;
264
265 EXPECT_CALL(mDisplay, getState()).WillOnce(ReturnRef(state));
266 EXPECT_CALL(*mDisplaySurface, advanceFrame(0.5f)).Times(1);
267
268 mSurface.queueBuffer(base::unique_fd(), 0.5f);
269
270 EXPECT_EQ(buffer.get(), mSurface.mutableTextureForTest().get());
271 }
272
TEST_F(RenderSurfaceTest,queueBufferHandlesClientComposition)273 TEST_F(RenderSurfaceTest, queueBufferHandlesClientComposition) {
274 const auto buffer =
275 std::make_shared<renderengine::impl::ExternalTexture>(sp<GraphicBuffer>::make(),
276 mRenderEngine, false);
277 mSurface.mutableTextureForTest() = buffer;
278
279 impl::OutputCompositionState state;
280 state.usesClientComposition = true;
281 state.flipClientTarget = false;
282
283 EXPECT_CALL(mDisplay, getState()).WillOnce(ReturnRef(state));
284 EXPECT_CALL(*mNativeWindow, queueBuffer(buffer->getBuffer()->getNativeBuffer(), -1))
285 .WillOnce(Return(NO_ERROR));
286 EXPECT_CALL(*mDisplaySurface, advanceFrame(0.5f)).Times(1);
287
288 mSurface.queueBuffer(base::unique_fd(), 0.5f);
289
290 EXPECT_EQ(nullptr, mSurface.mutableTextureForTest().get());
291 }
292
TEST_F(RenderSurfaceTest,queueBufferHandlesFlipClientTargetRequest)293 TEST_F(RenderSurfaceTest, queueBufferHandlesFlipClientTargetRequest) {
294 const auto buffer =
295 std::make_shared<renderengine::impl::ExternalTexture>(sp<GraphicBuffer>::make(),
296 mRenderEngine, false);
297 mSurface.mutableTextureForTest() = buffer;
298
299 impl::OutputCompositionState state;
300 state.usesClientComposition = false;
301 state.flipClientTarget = true;
302
303 EXPECT_CALL(mDisplay, getState()).WillOnce(ReturnRef(state));
304 EXPECT_CALL(*mNativeWindow, queueBuffer(buffer->getBuffer()->getNativeBuffer(), -1))
305 .WillOnce(Return(NO_ERROR));
306 EXPECT_CALL(*mDisplaySurface, advanceFrame(0.5f)).Times(1);
307
308 mSurface.queueBuffer(base::unique_fd(), 0.5f);
309
310 EXPECT_EQ(nullptr, mSurface.mutableTextureForTest().get());
311 }
312
TEST_F(RenderSurfaceTest,queueBufferHandlesFlipClientTargetRequestWithNoBufferYetDequeued)313 TEST_F(RenderSurfaceTest, queueBufferHandlesFlipClientTargetRequestWithNoBufferYetDequeued) {
314 sp<GraphicBuffer> buffer = sp<GraphicBuffer>::make();
315
316 impl::OutputCompositionState state;
317 state.usesClientComposition = false;
318 state.flipClientTarget = true;
319
320 EXPECT_CALL(mDisplay, getState()).WillOnce(ReturnRef(state));
321 EXPECT_CALL(*mNativeWindow, dequeueBuffer(_, _))
322 .WillOnce(
323 DoAll(SetArgPointee<0>(buffer.get()), SetArgPointee<1>(-1), Return(NO_ERROR)));
324 EXPECT_CALL(*mNativeWindow, queueBuffer(buffer->getNativeBuffer(), -1))
325 .WillOnce(Return(NO_ERROR));
326 EXPECT_CALL(*mDisplaySurface, advanceFrame(0.5f)).Times(1);
327
328 mSurface.queueBuffer(base::unique_fd(), 0.5f);
329
330 EXPECT_EQ(nullptr, mSurface.mutableTextureForTest().get());
331 }
332
TEST_F(RenderSurfaceTest,queueBufferHandlesNativeWindowQueueBufferFailureOnVirtualDisplay)333 TEST_F(RenderSurfaceTest, queueBufferHandlesNativeWindowQueueBufferFailureOnVirtualDisplay) {
334 const auto buffer =
335 std::make_shared<renderengine::impl::ExternalTexture>(sp<GraphicBuffer>::make(),
336 mRenderEngine, false);
337 mSurface.mutableTextureForTest() = buffer;
338
339 impl::OutputCompositionState state;
340 state.usesClientComposition = true;
341
342 EXPECT_CALL(mDisplay, getState()).WillOnce(ReturnRef(state));
343 EXPECT_CALL(*mNativeWindow, queueBuffer(buffer->getBuffer()->getNativeBuffer(), -1))
344 .WillOnce(Return(INVALID_OPERATION));
345 EXPECT_CALL(mDisplay, isVirtual()).WillOnce(Return(true));
346 EXPECT_CALL(*mNativeWindow, cancelBuffer(buffer->getBuffer()->getNativeBuffer(), -1))
347 .WillOnce(Return(NO_ERROR));
348 EXPECT_CALL(*mDisplaySurface, advanceFrame(0.5f)).Times(1);
349
350 mSurface.queueBuffer(base::unique_fd(), 0.5f);
351
352 EXPECT_EQ(nullptr, mSurface.mutableTextureForTest().get());
353 }
354
355 /*
356 * RenderSurface::onPresentDisplayCompleted()
357 */
358
TEST_F(RenderSurfaceTest,onPresentDisplayCompletedForwardsSignal)359 TEST_F(RenderSurfaceTest, onPresentDisplayCompletedForwardsSignal) {
360 EXPECT_CALL(*mDisplaySurface, onFrameCommitted()).Times(1);
361
362 mSurface.onPresentDisplayCompleted();
363 }
364
365 } // namespace
366 } // namespace android::compositionengine
367