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