blob: e3a98ffa9163252d6f49bb6ab264fb6c4a684fb4 [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
19#include <binder/IMemory.h>
Mathias Agopian90ac7992012-02-25 18:48:35 -080020
21#include <gui/ISurfaceComposer.h>
22#include <gui/Surface.h>
23#include <gui/SurfaceComposerClient.h>
24#include <private/gui/ComposerService.h>
25
Jamie Gennis23c2c5d2011-10-11 19:22:19 -070026#include <utils/String8.h>
Mathias Agopianc666cae2012-07-25 18:56:13 -070027#include <ui/DisplayInfo.h>
Jamie Gennis23c2c5d2011-10-11 19:22:19 -070028
29namespace android {
30
31// Fill an RGBA_8888 formatted surface with a single color.
32static void fillSurfaceRGBA8(const sp<SurfaceControl>& sc,
33 uint8_t r, uint8_t g, uint8_t b) {
34 Surface::SurfaceInfo info;
35 sp<Surface> s = sc->getSurface();
36 ASSERT_TRUE(s != NULL);
37 ASSERT_EQ(NO_ERROR, s->lock(&info));
38 uint8_t* img = reinterpret_cast<uint8_t*>(info.bits);
39 for (uint32_t y = 0; y < info.h; y++) {
40 for (uint32_t x = 0; x < info.w; x++) {
41 uint8_t* pixel = img + (4 * (y*info.s + x));
42 pixel[0] = r;
43 pixel[1] = g;
44 pixel[2] = b;
45 pixel[3] = 255;
46 }
47 }
48 ASSERT_EQ(NO_ERROR, s->unlockAndPost());
49}
50
51// A ScreenCapture is a screenshot from SurfaceFlinger that can be used to check
52// individual pixel values for testing purposes.
53class ScreenCapture : public RefBase {
54public:
55 static void captureScreen(sp<ScreenCapture>* sc) {
56 sp<IMemoryHeap> heap;
57 uint32_t w=0, h=0;
58 PixelFormat fmt=0;
59 sp<ISurfaceComposer> sf(ComposerService::getComposerService());
60 ASSERT_EQ(NO_ERROR, sf->captureScreen(0, &heap, &w, &h, &fmt, 0, 0,
61 0, INT_MAX));
62 ASSERT_TRUE(heap != NULL);
63 ASSERT_EQ(PIXEL_FORMAT_RGBA_8888, fmt);
64 *sc = new ScreenCapture(w, h, heap);
65 }
66
67 void checkPixel(uint32_t x, uint32_t y, uint8_t r, uint8_t g, uint8_t b) {
68 const uint8_t* img = reinterpret_cast<const uint8_t*>(mHeap->base());
69 const uint8_t* pixel = img + (4 * (y*mWidth + x));
70 if (r != pixel[0] || g != pixel[1] || b != pixel[2]) {
71 String8 err(String8::format("pixel @ (%3d, %3d): "
72 "expected [%3d, %3d, %3d], got [%3d, %3d, %3d]",
73 x, y, r, g, b, pixel[0], pixel[1], pixel[2]));
74 EXPECT_EQ(String8(), err);
75 }
76 }
77
78private:
79 ScreenCapture(uint32_t w, uint32_t h, const sp<IMemoryHeap>& heap) :
80 mWidth(w),
81 mHeight(h),
82 mHeap(heap)
83 {}
84
85 const uint32_t mWidth;
86 const uint32_t mHeight;
87 sp<IMemoryHeap> mHeap;
88};
89
90class LayerUpdateTest : public ::testing::Test {
91protected:
92 virtual void SetUp() {
93 mComposerClient = new SurfaceComposerClient;
94 ASSERT_EQ(NO_ERROR, mComposerClient->initCheck());
95
Mathias Agopianc666cae2012-07-25 18:56:13 -070096 DisplayInfo info;
97 SurfaceComposerClient::getDisplayInfo(0, &info);
98
99 ssize_t displayWidth = info.w;
100 ssize_t displayHeight = info.h;
Jamie Gennis23c2c5d2011-10-11 19:22:19 -0700101
102 // Background surface
103 mBGSurfaceControl = mComposerClient->createSurface(
104 String8("BG Test Surface"), 0, displayWidth, displayHeight,
105 PIXEL_FORMAT_RGBA_8888, 0);
106 ASSERT_TRUE(mBGSurfaceControl != NULL);
107 ASSERT_TRUE(mBGSurfaceControl->isValid());
108 fillSurfaceRGBA8(mBGSurfaceControl, 63, 63, 195);
109
110 // Foreground surface
111 mFGSurfaceControl = mComposerClient->createSurface(
112 String8("FG Test Surface"), 0, 64, 64, PIXEL_FORMAT_RGBA_8888, 0);
113 ASSERT_TRUE(mFGSurfaceControl != NULL);
114 ASSERT_TRUE(mFGSurfaceControl->isValid());
115
116 fillSurfaceRGBA8(mFGSurfaceControl, 195, 63, 63);
117
118 // Synchronization surface
119 mSyncSurfaceControl = mComposerClient->createSurface(
120 String8("Sync Test Surface"), 0, 1, 1, PIXEL_FORMAT_RGBA_8888, 0);
121 ASSERT_TRUE(mSyncSurfaceControl != NULL);
122 ASSERT_TRUE(mSyncSurfaceControl->isValid());
123
124 fillSurfaceRGBA8(mSyncSurfaceControl, 31, 31, 31);
125
126 SurfaceComposerClient::openGlobalTransaction();
127
128 ASSERT_EQ(NO_ERROR, mBGSurfaceControl->setLayer(INT_MAX-2));
129 ASSERT_EQ(NO_ERROR, mBGSurfaceControl->show());
130
131 ASSERT_EQ(NO_ERROR, mFGSurfaceControl->setLayer(INT_MAX-1));
132 ASSERT_EQ(NO_ERROR, mFGSurfaceControl->setPosition(64, 64));
133 ASSERT_EQ(NO_ERROR, mFGSurfaceControl->show());
134
135 ASSERT_EQ(NO_ERROR, mSyncSurfaceControl->setLayer(INT_MAX-1));
136 ASSERT_EQ(NO_ERROR, mSyncSurfaceControl->setPosition(displayWidth-2,
137 displayHeight-2));
138 ASSERT_EQ(NO_ERROR, mSyncSurfaceControl->show());
139
140 SurfaceComposerClient::closeGlobalTransaction(true);
141 }
142
143 virtual void TearDown() {
144 mComposerClient->dispose();
145 mBGSurfaceControl = 0;
146 mFGSurfaceControl = 0;
147 mSyncSurfaceControl = 0;
148 mComposerClient = 0;
149 }
150
151 void waitForPostedBuffers() {
152 // Since the sync surface is in synchronous mode (i.e. double buffered)
153 // posting three buffers to it should ensure that at least two
154 // SurfaceFlinger::handlePageFlip calls have been made, which should
155 // guaranteed that a buffer posted to another Surface has been retired.
156 fillSurfaceRGBA8(mSyncSurfaceControl, 31, 31, 31);
157 fillSurfaceRGBA8(mSyncSurfaceControl, 31, 31, 31);
158 fillSurfaceRGBA8(mSyncSurfaceControl, 31, 31, 31);
159 }
160
161 sp<SurfaceComposerClient> mComposerClient;
162 sp<SurfaceControl> mBGSurfaceControl;
163 sp<SurfaceControl> mFGSurfaceControl;
164
165 // This surface is used to ensure that the buffers posted to
166 // mFGSurfaceControl have been picked up by SurfaceFlinger.
167 sp<SurfaceControl> mSyncSurfaceControl;
168};
169
170TEST_F(LayerUpdateTest, LayerMoveWorks) {
171 sp<ScreenCapture> sc;
172 {
173 SCOPED_TRACE("before move");
174 ScreenCapture::captureScreen(&sc);
175 sc->checkPixel( 0, 12, 63, 63, 195);
176 sc->checkPixel( 75, 75, 195, 63, 63);
177 sc->checkPixel(145, 145, 63, 63, 195);
178 }
179
180 SurfaceComposerClient::openGlobalTransaction();
181 ASSERT_EQ(NO_ERROR, mFGSurfaceControl->setPosition(128, 128));
182 SurfaceComposerClient::closeGlobalTransaction(true);
183 {
184 // This should reflect the new position, but not the new color.
185 SCOPED_TRACE("after move, before redraw");
186 ScreenCapture::captureScreen(&sc);
187 sc->checkPixel( 24, 24, 63, 63, 195);
188 sc->checkPixel( 75, 75, 63, 63, 195);
189 sc->checkPixel(145, 145, 195, 63, 63);
190 }
191
192 fillSurfaceRGBA8(mFGSurfaceControl, 63, 195, 63);
193 waitForPostedBuffers();
194 {
195 // This should reflect the new position and the new color.
196 SCOPED_TRACE("after redraw");
197 ScreenCapture::captureScreen(&sc);
198 sc->checkPixel( 24, 24, 63, 63, 195);
199 sc->checkPixel( 75, 75, 63, 63, 195);
200 sc->checkPixel(145, 145, 63, 195, 63);
201 }
202}
203
204TEST_F(LayerUpdateTest, LayerResizeWorks) {
205 sp<ScreenCapture> sc;
206 {
207 SCOPED_TRACE("before resize");
208 ScreenCapture::captureScreen(&sc);
209 sc->checkPixel( 0, 12, 63, 63, 195);
210 sc->checkPixel( 75, 75, 195, 63, 63);
211 sc->checkPixel(145, 145, 63, 63, 195);
212 }
213
Steve Block9d453682011-12-20 16:23:08 +0000214 ALOGD("resizing");
Jamie Gennis23c2c5d2011-10-11 19:22:19 -0700215 SurfaceComposerClient::openGlobalTransaction();
216 ASSERT_EQ(NO_ERROR, mFGSurfaceControl->setSize(128, 128));
217 SurfaceComposerClient::closeGlobalTransaction(true);
Steve Block9d453682011-12-20 16:23:08 +0000218 ALOGD("resized");
Jamie Gennis23c2c5d2011-10-11 19:22:19 -0700219 {
220 // This should not reflect the new size or color because SurfaceFlinger
221 // has not yet received a buffer of the correct size.
222 SCOPED_TRACE("after resize, before redraw");
223 ScreenCapture::captureScreen(&sc);
224 sc->checkPixel( 0, 12, 63, 63, 195);
225 sc->checkPixel( 75, 75, 195, 63, 63);
226 sc->checkPixel(145, 145, 63, 63, 195);
227 }
228
Steve Block9d453682011-12-20 16:23:08 +0000229 ALOGD("drawing");
Jamie Gennis23c2c5d2011-10-11 19:22:19 -0700230 fillSurfaceRGBA8(mFGSurfaceControl, 63, 195, 63);
231 waitForPostedBuffers();
Steve Block9d453682011-12-20 16:23:08 +0000232 ALOGD("drawn");
Jamie Gennis23c2c5d2011-10-11 19:22:19 -0700233 {
234 // This should reflect the new size and the new color.
235 SCOPED_TRACE("after redraw");
236 ScreenCapture::captureScreen(&sc);
237 sc->checkPixel( 24, 24, 63, 63, 195);
238 sc->checkPixel( 75, 75, 63, 195, 63);
239 sc->checkPixel(145, 145, 63, 195, 63);
240 }
241}
242
243}