blob: 3ae85a9424527e7f756df5014e7c453650e1ef82 [file] [log] [blame]
Jamie Gennis23c2c5d2011-10-11 19:22:19 -07001/*
2 * Copyright (C) 2011 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 <gtest/gtest.h>
18
Michael Lentine5a16a622015-05-21 13:48:24 -070019#include <android/native_window.h>
20
Jamie Gennis23c2c5d2011-10-11 19:22:19 -070021#include <binder/IMemory.h>
Mathias Agopian90ac7992012-02-25 18:48:35 -080022
23#include <gui/ISurfaceComposer.h>
24#include <gui/Surface.h>
25#include <gui/SurfaceComposerClient.h>
26#include <private/gui/ComposerService.h>
27
Jamie Gennis23c2c5d2011-10-11 19:22:19 -070028#include <utils/String8.h>
Mathias Agopianc666cae2012-07-25 18:56:13 -070029#include <ui/DisplayInfo.h>
Jamie Gennis23c2c5d2011-10-11 19:22:19 -070030
31namespace android {
32
33// Fill an RGBA_8888 formatted surface with a single color.
34static void fillSurfaceRGBA8(const sp<SurfaceControl>& sc,
35 uint8_t r, uint8_t g, uint8_t b) {
Mathias Agopiane3c697f2013-02-14 17:11:02 -080036 ANativeWindow_Buffer outBuffer;
Jamie Gennis23c2c5d2011-10-11 19:22:19 -070037 sp<Surface> s = sc->getSurface();
38 ASSERT_TRUE(s != NULL);
Mathias Agopiane3c697f2013-02-14 17:11:02 -080039 ASSERT_EQ(NO_ERROR, s->lock(&outBuffer, NULL));
40 uint8_t* img = reinterpret_cast<uint8_t*>(outBuffer.bits);
41 for (uint32_t y = 0; y < outBuffer.height; y++) {
42 for (uint32_t x = 0; x < outBuffer.width; x++) {
43 uint8_t* pixel = img + (4 * (y*outBuffer.stride + x));
Jamie Gennis23c2c5d2011-10-11 19:22:19 -070044 pixel[0] = r;
45 pixel[1] = g;
46 pixel[2] = b;
47 pixel[3] = 255;
48 }
49 }
50 ASSERT_EQ(NO_ERROR, s->unlockAndPost());
51}
52
53// A ScreenCapture is a screenshot from SurfaceFlinger that can be used to check
54// individual pixel values for testing purposes.
55class ScreenCapture : public RefBase {
56public:
57 static void captureScreen(sp<ScreenCapture>* sc) {
Michael Lentine5a16a622015-05-21 13:48:24 -070058 sp<IGraphicBufferProducer> producer;
59 sp<IGraphicBufferConsumer> consumer;
60 BufferQueue::createBufferQueue(&producer, &consumer);
61 IGraphicBufferProducer::QueueBufferOutput bufferOutput;
62 sp<CpuConsumer> cpuConsumer = new CpuConsumer(consumer, 1);
Jamie Gennis23c2c5d2011-10-11 19:22:19 -070063 sp<ISurfaceComposer> sf(ComposerService::getComposerService());
Michael Lentine5a16a622015-05-21 13:48:24 -070064 sp<IBinder> display(sf->getBuiltInDisplay(
65 ISurfaceComposer::eDisplayIdMain));
66 ASSERT_EQ(NO_ERROR, sf->captureScreen(display, producer, Rect(), 0, 0,
67 0, INT_MAX, false));
68 *sc = new ScreenCapture(cpuConsumer);
Jamie Gennis23c2c5d2011-10-11 19:22:19 -070069 }
70
71 void checkPixel(uint32_t x, uint32_t y, uint8_t r, uint8_t g, uint8_t b) {
Michael Lentine5a16a622015-05-21 13:48:24 -070072 ASSERT_EQ(HAL_PIXEL_FORMAT_RGBA_8888, mBuf.format);
73 const uint8_t* img = static_cast<const uint8_t*>(mBuf.data);
74 const uint8_t* pixel = img + (4 * (y * mBuf.stride + x));
Jamie Gennis23c2c5d2011-10-11 19:22:19 -070075 if (r != pixel[0] || g != pixel[1] || b != pixel[2]) {
76 String8 err(String8::format("pixel @ (%3d, %3d): "
77 "expected [%3d, %3d, %3d], got [%3d, %3d, %3d]",
78 x, y, r, g, b, pixel[0], pixel[1], pixel[2]));
79 EXPECT_EQ(String8(), err);
80 }
81 }
82
83private:
Michael Lentine5a16a622015-05-21 13:48:24 -070084 ScreenCapture(const sp<CpuConsumer>& cc) :
85 mCC(cc) {
86 EXPECT_EQ(NO_ERROR, mCC->lockNextBuffer(&mBuf));
87 }
Jamie Gennis23c2c5d2011-10-11 19:22:19 -070088
Michael Lentine5a16a622015-05-21 13:48:24 -070089 ~ScreenCapture() {
90 mCC->unlockBuffer(mBuf);
91 }
92
93 sp<CpuConsumer> mCC;
94 CpuConsumer::LockedBuffer mBuf;
Jamie Gennis23c2c5d2011-10-11 19:22:19 -070095};
96
97class LayerUpdateTest : public ::testing::Test {
98protected:
99 virtual void SetUp() {
100 mComposerClient = new SurfaceComposerClient;
101 ASSERT_EQ(NO_ERROR, mComposerClient->initCheck());
102
Jeff Brown9d4e3d22012-08-24 20:00:51 -0700103 sp<IBinder> display(SurfaceComposerClient::getBuiltInDisplay(
104 ISurfaceComposer::eDisplayIdMain));
Mathias Agopianc666cae2012-07-25 18:56:13 -0700105 DisplayInfo info;
Jeff Brown9d4e3d22012-08-24 20:00:51 -0700106 SurfaceComposerClient::getDisplayInfo(display, &info);
Mathias Agopianc666cae2012-07-25 18:56:13 -0700107
108 ssize_t displayWidth = info.w;
109 ssize_t displayHeight = info.h;
Jamie Gennis23c2c5d2011-10-11 19:22:19 -0700110
111 // Background surface
112 mBGSurfaceControl = mComposerClient->createSurface(
Jeff Brown9d4e3d22012-08-24 20:00:51 -0700113 String8("BG Test Surface"), displayWidth, displayHeight,
Jamie Gennis23c2c5d2011-10-11 19:22:19 -0700114 PIXEL_FORMAT_RGBA_8888, 0);
115 ASSERT_TRUE(mBGSurfaceControl != NULL);
116 ASSERT_TRUE(mBGSurfaceControl->isValid());
117 fillSurfaceRGBA8(mBGSurfaceControl, 63, 63, 195);
118
119 // Foreground surface
120 mFGSurfaceControl = mComposerClient->createSurface(
Jeff Brown9d4e3d22012-08-24 20:00:51 -0700121 String8("FG Test Surface"), 64, 64, PIXEL_FORMAT_RGBA_8888, 0);
Jamie Gennis23c2c5d2011-10-11 19:22:19 -0700122 ASSERT_TRUE(mFGSurfaceControl != NULL);
123 ASSERT_TRUE(mFGSurfaceControl->isValid());
124
125 fillSurfaceRGBA8(mFGSurfaceControl, 195, 63, 63);
126
127 // Synchronization surface
128 mSyncSurfaceControl = mComposerClient->createSurface(
Jeff Brown9d4e3d22012-08-24 20:00:51 -0700129 String8("Sync Test Surface"), 1, 1, PIXEL_FORMAT_RGBA_8888, 0);
Jamie Gennis23c2c5d2011-10-11 19:22:19 -0700130 ASSERT_TRUE(mSyncSurfaceControl != NULL);
131 ASSERT_TRUE(mSyncSurfaceControl->isValid());
132
133 fillSurfaceRGBA8(mSyncSurfaceControl, 31, 31, 31);
134
135 SurfaceComposerClient::openGlobalTransaction();
136
137 ASSERT_EQ(NO_ERROR, mBGSurfaceControl->setLayer(INT_MAX-2));
138 ASSERT_EQ(NO_ERROR, mBGSurfaceControl->show());
139
140 ASSERT_EQ(NO_ERROR, mFGSurfaceControl->setLayer(INT_MAX-1));
141 ASSERT_EQ(NO_ERROR, mFGSurfaceControl->setPosition(64, 64));
142 ASSERT_EQ(NO_ERROR, mFGSurfaceControl->show());
143
144 ASSERT_EQ(NO_ERROR, mSyncSurfaceControl->setLayer(INT_MAX-1));
145 ASSERT_EQ(NO_ERROR, mSyncSurfaceControl->setPosition(displayWidth-2,
146 displayHeight-2));
147 ASSERT_EQ(NO_ERROR, mSyncSurfaceControl->show());
148
149 SurfaceComposerClient::closeGlobalTransaction(true);
150 }
151
152 virtual void TearDown() {
153 mComposerClient->dispose();
154 mBGSurfaceControl = 0;
155 mFGSurfaceControl = 0;
156 mSyncSurfaceControl = 0;
157 mComposerClient = 0;
158 }
159
160 void waitForPostedBuffers() {
161 // Since the sync surface is in synchronous mode (i.e. double buffered)
162 // posting three buffers to it should ensure that at least two
163 // SurfaceFlinger::handlePageFlip calls have been made, which should
164 // guaranteed that a buffer posted to another Surface has been retired.
165 fillSurfaceRGBA8(mSyncSurfaceControl, 31, 31, 31);
166 fillSurfaceRGBA8(mSyncSurfaceControl, 31, 31, 31);
167 fillSurfaceRGBA8(mSyncSurfaceControl, 31, 31, 31);
168 }
169
170 sp<SurfaceComposerClient> mComposerClient;
171 sp<SurfaceControl> mBGSurfaceControl;
172 sp<SurfaceControl> mFGSurfaceControl;
173
174 // This surface is used to ensure that the buffers posted to
175 // mFGSurfaceControl have been picked up by SurfaceFlinger.
176 sp<SurfaceControl> mSyncSurfaceControl;
177};
178
179TEST_F(LayerUpdateTest, LayerMoveWorks) {
180 sp<ScreenCapture> sc;
181 {
182 SCOPED_TRACE("before move");
183 ScreenCapture::captureScreen(&sc);
184 sc->checkPixel( 0, 12, 63, 63, 195);
185 sc->checkPixel( 75, 75, 195, 63, 63);
186 sc->checkPixel(145, 145, 63, 63, 195);
187 }
188
189 SurfaceComposerClient::openGlobalTransaction();
190 ASSERT_EQ(NO_ERROR, mFGSurfaceControl->setPosition(128, 128));
191 SurfaceComposerClient::closeGlobalTransaction(true);
192 {
193 // This should reflect the new position, but not the new color.
194 SCOPED_TRACE("after move, before redraw");
195 ScreenCapture::captureScreen(&sc);
196 sc->checkPixel( 24, 24, 63, 63, 195);
197 sc->checkPixel( 75, 75, 63, 63, 195);
198 sc->checkPixel(145, 145, 195, 63, 63);
199 }
200
201 fillSurfaceRGBA8(mFGSurfaceControl, 63, 195, 63);
202 waitForPostedBuffers();
203 {
204 // This should reflect the new position and the new color.
205 SCOPED_TRACE("after redraw");
206 ScreenCapture::captureScreen(&sc);
207 sc->checkPixel( 24, 24, 63, 63, 195);
208 sc->checkPixel( 75, 75, 63, 63, 195);
209 sc->checkPixel(145, 145, 63, 195, 63);
210 }
211}
212
213TEST_F(LayerUpdateTest, LayerResizeWorks) {
214 sp<ScreenCapture> sc;
215 {
216 SCOPED_TRACE("before resize");
217 ScreenCapture::captureScreen(&sc);
218 sc->checkPixel( 0, 12, 63, 63, 195);
219 sc->checkPixel( 75, 75, 195, 63, 63);
220 sc->checkPixel(145, 145, 63, 63, 195);
221 }
222
Steve Block9d453682011-12-20 16:23:08 +0000223 ALOGD("resizing");
Jamie Gennis23c2c5d2011-10-11 19:22:19 -0700224 SurfaceComposerClient::openGlobalTransaction();
225 ASSERT_EQ(NO_ERROR, mFGSurfaceControl->setSize(128, 128));
226 SurfaceComposerClient::closeGlobalTransaction(true);
Steve Block9d453682011-12-20 16:23:08 +0000227 ALOGD("resized");
Jamie Gennis23c2c5d2011-10-11 19:22:19 -0700228 {
229 // This should not reflect the new size or color because SurfaceFlinger
230 // has not yet received a buffer of the correct size.
231 SCOPED_TRACE("after resize, before redraw");
232 ScreenCapture::captureScreen(&sc);
233 sc->checkPixel( 0, 12, 63, 63, 195);
234 sc->checkPixel( 75, 75, 195, 63, 63);
235 sc->checkPixel(145, 145, 63, 63, 195);
236 }
237
Steve Block9d453682011-12-20 16:23:08 +0000238 ALOGD("drawing");
Jamie Gennis23c2c5d2011-10-11 19:22:19 -0700239 fillSurfaceRGBA8(mFGSurfaceControl, 63, 195, 63);
240 waitForPostedBuffers();
Steve Block9d453682011-12-20 16:23:08 +0000241 ALOGD("drawn");
Jamie Gennis23c2c5d2011-10-11 19:22:19 -0700242 {
243 // This should reflect the new size and the new color.
244 SCOPED_TRACE("after redraw");
245 ScreenCapture::captureScreen(&sc);
246 sc->checkPixel( 24, 24, 63, 63, 195);
247 sc->checkPixel( 75, 75, 63, 195, 63);
248 sc->checkPixel(145, 145, 63, 195, 63);
249 }
250}
251
Haixia Shid5750962015-07-27 16:50:49 -0700252TEST_F(LayerUpdateTest, LayerCropWorks) {
253 sp<ScreenCapture> sc;
254 {
255 SCOPED_TRACE("before crop");
256 ScreenCapture::captureScreen(&sc);
257 sc->checkPixel( 24, 24, 63, 63, 195);
258 sc->checkPixel( 75, 75, 195, 63, 63);
259 sc->checkPixel(145, 145, 63, 63, 195);
260 }
261
262 SurfaceComposerClient::openGlobalTransaction();
263 Rect cropRect(16, 16, 32, 32);
264 ASSERT_EQ(NO_ERROR, mFGSurfaceControl->setCrop(cropRect));
265 SurfaceComposerClient::closeGlobalTransaction(true);
266 {
267 // This should crop the foreground surface.
268 SCOPED_TRACE("after crop");
269 ScreenCapture::captureScreen(&sc);
270 sc->checkPixel( 24, 24, 63, 63, 195);
271 sc->checkPixel( 75, 75, 63, 63, 195);
272 sc->checkPixel( 95, 80, 195, 63, 63);
273 sc->checkPixel( 80, 95, 195, 63, 63);
274 sc->checkPixel( 96, 96, 63, 63, 195);
275 }
276}
277
278TEST_F(LayerUpdateTest, LayerSetLayerWorks) {
279 sp<ScreenCapture> sc;
280 {
281 SCOPED_TRACE("before setLayer");
282 ScreenCapture::captureScreen(&sc);
283 sc->checkPixel( 24, 24, 63, 63, 195);
284 sc->checkPixel( 75, 75, 195, 63, 63);
285 sc->checkPixel(145, 145, 63, 63, 195);
286 }
287
288 SurfaceComposerClient::openGlobalTransaction();
289 ASSERT_EQ(NO_ERROR, mFGSurfaceControl->setLayer(INT_MAX - 3));
290 SurfaceComposerClient::closeGlobalTransaction(true);
291 {
292 // This should hide the foreground surface beneath the background.
293 SCOPED_TRACE("after setLayer");
294 ScreenCapture::captureScreen(&sc);
295 sc->checkPixel( 24, 24, 63, 63, 195);
296 sc->checkPixel( 75, 75, 63, 63, 195);
297 sc->checkPixel(145, 145, 63, 63, 195);
298 }
299}
300
301TEST_F(LayerUpdateTest, LayerShowHideWorks) {
302 sp<ScreenCapture> sc;
303 {
304 SCOPED_TRACE("before hide");
305 ScreenCapture::captureScreen(&sc);
306 sc->checkPixel( 24, 24, 63, 63, 195);
307 sc->checkPixel( 75, 75, 195, 63, 63);
308 sc->checkPixel(145, 145, 63, 63, 195);
309 }
310
311 SurfaceComposerClient::openGlobalTransaction();
312 ASSERT_EQ(NO_ERROR, mFGSurfaceControl->hide());
313 SurfaceComposerClient::closeGlobalTransaction(true);
314 {
315 // This should hide the foreground surface.
316 SCOPED_TRACE("after hide, before show");
317 ScreenCapture::captureScreen(&sc);
318 sc->checkPixel( 24, 24, 63, 63, 195);
319 sc->checkPixel( 75, 75, 63, 63, 195);
320 sc->checkPixel(145, 145, 63, 63, 195);
321 }
322
323 SurfaceComposerClient::openGlobalTransaction();
324 ASSERT_EQ(NO_ERROR, mFGSurfaceControl->show());
325 SurfaceComposerClient::closeGlobalTransaction(true);
326 {
327 // This should show the foreground surface.
328 SCOPED_TRACE("after show");
329 ScreenCapture::captureScreen(&sc);
330 sc->checkPixel( 24, 24, 63, 63, 195);
331 sc->checkPixel( 75, 75, 195, 63, 63);
332 sc->checkPixel(145, 145, 63, 63, 195);
333 }
334}
335
336TEST_F(LayerUpdateTest, LayerSetAlphaWorks) {
337 sp<ScreenCapture> sc;
338 {
339 SCOPED_TRACE("before setAlpha");
340 ScreenCapture::captureScreen(&sc);
341 sc->checkPixel( 24, 24, 63, 63, 195);
342 sc->checkPixel( 75, 75, 195, 63, 63);
343 sc->checkPixel(145, 145, 63, 63, 195);
344 }
345
346 SurfaceComposerClient::openGlobalTransaction();
347 ASSERT_EQ(NO_ERROR, mFGSurfaceControl->setAlpha(0.75f));
348 SurfaceComposerClient::closeGlobalTransaction(true);
349 {
350 // This should set foreground to be 75% opaque.
351 SCOPED_TRACE("after setAlpha");
352 ScreenCapture::captureScreen(&sc);
353 sc->checkPixel( 24, 24, 63, 63, 195);
354 sc->checkPixel( 75, 75, 162, 63, 96);
355 sc->checkPixel(145, 145, 63, 63, 195);
356 }
357}
358
Jamie Gennis23c2c5d2011-10-11 19:22:19 -0700359}