SurfaceTexture_test.cpp revision 5dd0c4fd7efcb99bdd346ed01f1a8f1d2baa8ef1
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//#define LOG_NDEBUG 0
18
19#include <gtest/gtest.h>
20#include <gui/SurfaceTexture.h>
21#include <gui/SurfaceTextureClient.h>
22#include <ui/GraphicBuffer.h>
23#include <utils/String8.h>
24#include <utils/threads.h>
25
26#include <surfaceflinger/ISurfaceComposer.h>
27#include <surfaceflinger/Surface.h>
28#include <surfaceflinger/SurfaceComposerClient.h>
29
30#include <EGL/egl.h>
31#include <EGL/eglext.h>
32#include <GLES2/gl2.h>
33#include <GLES2/gl2ext.h>
34
35#include <ui/FramebufferNativeWindow.h>
36
37namespace android {
38
39class GLTest : public ::testing::Test {
40protected:
41
42    GLTest():
43            mEglDisplay(EGL_NO_DISPLAY),
44            mEglSurface(EGL_NO_SURFACE),
45            mEglContext(EGL_NO_CONTEXT) {
46    }
47
48    virtual void SetUp() {
49        mEglDisplay = eglGetDisplay(EGL_DEFAULT_DISPLAY);
50        ASSERT_EQ(EGL_SUCCESS, eglGetError());
51        ASSERT_NE(EGL_NO_DISPLAY, mEglDisplay);
52
53        EGLint majorVersion;
54        EGLint minorVersion;
55        EXPECT_TRUE(eglInitialize(mEglDisplay, &majorVersion, &minorVersion));
56        ASSERT_EQ(EGL_SUCCESS, eglGetError());
57        RecordProperty("EglVersionMajor", majorVersion);
58        RecordProperty("EglVersionMajor", minorVersion);
59
60        EGLint numConfigs = 0;
61        EXPECT_TRUE(eglChooseConfig(mEglDisplay, getConfigAttribs(), &mGlConfig,
62                1, &numConfigs));
63        ASSERT_EQ(EGL_SUCCESS, eglGetError());
64
65        char* displaySecsEnv = getenv("GLTEST_DISPLAY_SECS");
66        if (displaySecsEnv != NULL) {
67            mDisplaySecs = atoi(displaySecsEnv);
68            if (mDisplaySecs < 0) {
69                mDisplaySecs = 0;
70            }
71        } else {
72            mDisplaySecs = 0;
73        }
74
75        if (mDisplaySecs > 0) {
76            mComposerClient = new SurfaceComposerClient;
77            ASSERT_EQ(NO_ERROR, mComposerClient->initCheck());
78
79            mSurfaceControl = mComposerClient->createSurface(
80                    String8("Test Surface"), 0,
81                    getSurfaceWidth(), getSurfaceHeight(),
82                    PIXEL_FORMAT_RGB_888, 0);
83
84            ASSERT_TRUE(mSurfaceControl != NULL);
85            ASSERT_TRUE(mSurfaceControl->isValid());
86
87            ASSERT_EQ(NO_ERROR, mComposerClient->openTransaction());
88            ASSERT_EQ(NO_ERROR, mSurfaceControl->setLayer(0x7FFFFFFF));
89            ASSERT_EQ(NO_ERROR, mSurfaceControl->show());
90            ASSERT_EQ(NO_ERROR, mComposerClient->closeTransaction());
91
92            sp<ANativeWindow> window = mSurfaceControl->getSurface();
93            mEglSurface = eglCreateWindowSurface(mEglDisplay, mGlConfig,
94                    window.get(), NULL);
95        } else {
96            EGLint pbufferAttribs[] = {
97                EGL_WIDTH, getSurfaceWidth(),
98                EGL_HEIGHT, getSurfaceHeight(),
99                EGL_NONE };
100
101            mEglSurface = eglCreatePbufferSurface(mEglDisplay, mGlConfig,
102                    pbufferAttribs);
103        }
104        ASSERT_EQ(EGL_SUCCESS, eglGetError());
105        ASSERT_NE(EGL_NO_SURFACE, mEglSurface);
106
107        mEglContext = eglCreateContext(mEglDisplay, mGlConfig, EGL_NO_CONTEXT,
108                getContextAttribs());
109        ASSERT_EQ(EGL_SUCCESS, eglGetError());
110        ASSERT_NE(EGL_NO_CONTEXT, mEglContext);
111
112        EXPECT_TRUE(eglMakeCurrent(mEglDisplay, mEglSurface, mEglSurface,
113                mEglContext));
114        ASSERT_EQ(EGL_SUCCESS, eglGetError());
115
116        EGLint w, h;
117        EXPECT_TRUE(eglQuerySurface(mEglDisplay, mEglSurface, EGL_WIDTH, &w));
118        ASSERT_EQ(EGL_SUCCESS, eglGetError());
119        EXPECT_TRUE(eglQuerySurface(mEglDisplay, mEglSurface, EGL_HEIGHT, &h));
120        ASSERT_EQ(EGL_SUCCESS, eglGetError());
121        RecordProperty("EglSurfaceWidth", w);
122        RecordProperty("EglSurfaceHeight", h);
123
124        glViewport(0, 0, w, h);
125        ASSERT_EQ(GLenum(GL_NO_ERROR), glGetError());
126    }
127
128    virtual void TearDown() {
129        // Display the result
130        if (mDisplaySecs > 0 && mEglSurface != EGL_NO_SURFACE) {
131            eglSwapBuffers(mEglDisplay, mEglSurface);
132            sleep(mDisplaySecs);
133        }
134
135        if (mComposerClient != NULL) {
136            mComposerClient->dispose();
137        }
138        if (mEglContext != EGL_NO_CONTEXT) {
139            eglDestroyContext(mEglDisplay, mEglContext);
140        }
141        if (mEglSurface != EGL_NO_SURFACE) {
142            eglDestroySurface(mEglDisplay, mEglSurface);
143        }
144        if (mEglDisplay != EGL_NO_DISPLAY) {
145            eglMakeCurrent(mEglDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE,
146                    EGL_NO_CONTEXT);
147            eglTerminate(mEglDisplay);
148        }
149        ASSERT_EQ(EGL_SUCCESS, eglGetError());
150    }
151
152    virtual EGLint const* getConfigAttribs() {
153        static EGLint sDefaultConfigAttribs[] = {
154            EGL_SURFACE_TYPE, EGL_PBUFFER_BIT,
155            EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT,
156            EGL_RED_SIZE, 8,
157            EGL_GREEN_SIZE, 8,
158            EGL_BLUE_SIZE, 8,
159            EGL_ALPHA_SIZE, 8,
160            EGL_DEPTH_SIZE, 16,
161            EGL_STENCIL_SIZE, 8,
162            EGL_NONE };
163
164        return sDefaultConfigAttribs;
165    }
166
167    virtual EGLint const* getContextAttribs() {
168        static EGLint sDefaultContextAttribs[] = {
169            EGL_CONTEXT_CLIENT_VERSION, 2,
170            EGL_NONE };
171
172        return sDefaultContextAttribs;
173    }
174
175    virtual EGLint getSurfaceWidth() {
176        return 64;
177    }
178
179    virtual EGLint getSurfaceHeight() {
180        return 64;
181    }
182
183    void loadShader(GLenum shaderType, const char* pSource, GLuint* outShader) {
184        GLuint shader = glCreateShader(shaderType);
185        ASSERT_EQ(GLenum(GL_NO_ERROR), glGetError());
186        if (shader) {
187            glShaderSource(shader, 1, &pSource, NULL);
188            ASSERT_EQ(GLenum(GL_NO_ERROR), glGetError());
189            glCompileShader(shader);
190            ASSERT_EQ(GLenum(GL_NO_ERROR), glGetError());
191            GLint compiled = 0;
192            glGetShaderiv(shader, GL_COMPILE_STATUS, &compiled);
193            ASSERT_EQ(GLenum(GL_NO_ERROR), glGetError());
194            if (!compiled) {
195                GLint infoLen = 0;
196                glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &infoLen);
197                ASSERT_EQ(GLenum(GL_NO_ERROR), glGetError());
198                if (infoLen) {
199                    char* buf = (char*) malloc(infoLen);
200                    if (buf) {
201                        glGetShaderInfoLog(shader, infoLen, NULL, buf);
202                        printf("Shader compile log:\n%s\n", buf);
203                        free(buf);
204                        FAIL();
205                    }
206                } else {
207                    char* buf = (char*) malloc(0x1000);
208                    if (buf) {
209                        glGetShaderInfoLog(shader, 0x1000, NULL, buf);
210                        printf("Shader compile log:\n%s\n", buf);
211                        free(buf);
212                        FAIL();
213                    }
214                }
215                glDeleteShader(shader);
216                shader = 0;
217            }
218        }
219        ASSERT_TRUE(shader != 0);
220        *outShader = shader;
221    }
222
223    void createProgram(const char* pVertexSource, const char* pFragmentSource,
224            GLuint* outPgm) {
225        GLuint vertexShader, fragmentShader;
226        {
227            SCOPED_TRACE("compiling vertex shader");
228            loadShader(GL_VERTEX_SHADER, pVertexSource, &vertexShader);
229            if (HasFatalFailure()) {
230                return;
231            }
232        }
233        {
234            SCOPED_TRACE("compiling fragment shader");
235            loadShader(GL_FRAGMENT_SHADER, pFragmentSource, &fragmentShader);
236            if (HasFatalFailure()) {
237                return;
238            }
239        }
240
241        GLuint program = glCreateProgram();
242        ASSERT_EQ(GLenum(GL_NO_ERROR), glGetError());
243        if (program) {
244            glAttachShader(program, vertexShader);
245            ASSERT_EQ(GLenum(GL_NO_ERROR), glGetError());
246            glAttachShader(program, fragmentShader);
247            ASSERT_EQ(GLenum(GL_NO_ERROR), glGetError());
248            glLinkProgram(program);
249            GLint linkStatus = GL_FALSE;
250            glGetProgramiv(program, GL_LINK_STATUS, &linkStatus);
251            if (linkStatus != GL_TRUE) {
252                GLint bufLength = 0;
253                glGetProgramiv(program, GL_INFO_LOG_LENGTH, &bufLength);
254                if (bufLength) {
255                    char* buf = (char*) malloc(bufLength);
256                    if (buf) {
257                        glGetProgramInfoLog(program, bufLength, NULL, buf);
258                        printf("Program link log:\n%s\n", buf);
259                        free(buf);
260                        FAIL();
261                    }
262                }
263                glDeleteProgram(program);
264                program = 0;
265            }
266        }
267        glDeleteShader(vertexShader);
268        glDeleteShader(fragmentShader);
269        ASSERT_TRUE(program != 0);
270        *outPgm = program;
271    }
272
273    static int abs(int value) {
274        return value > 0 ? value : -value;
275    }
276
277    ::testing::AssertionResult checkPixel(int x, int y, int r,
278            int g, int b, int a, int tolerance=2) {
279        GLubyte pixel[4];
280        String8 msg;
281        glReadPixels(x, y, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, pixel);
282        GLenum err = glGetError();
283        if (err != GL_NO_ERROR) {
284            msg += String8::format("error reading pixel: %#x", err);
285            while ((err = glGetError()) != GL_NO_ERROR) {
286                msg += String8::format(", %#x", err);
287            }
288            fprintf(stderr, "pixel check failure: %s\n", msg.string());
289            return ::testing::AssertionFailure(
290                    ::testing::Message(msg.string()));
291        }
292        if (r >= 0 && abs(r - int(pixel[0])) > tolerance) {
293            msg += String8::format("r(%d isn't %d)", pixel[0], r);
294        }
295        if (g >= 0 && abs(g - int(pixel[1])) > tolerance) {
296            if (!msg.isEmpty()) {
297                msg += " ";
298            }
299            msg += String8::format("g(%d isn't %d)", pixel[1], g);
300        }
301        if (b >= 0 && abs(b - int(pixel[2])) > tolerance) {
302            if (!msg.isEmpty()) {
303                msg += " ";
304            }
305            msg += String8::format("b(%d isn't %d)", pixel[2], b);
306        }
307        if (a >= 0 && abs(a - int(pixel[3])) > tolerance) {
308            if (!msg.isEmpty()) {
309                msg += " ";
310            }
311            msg += String8::format("a(%d isn't %d)", pixel[3], a);
312        }
313        if (!msg.isEmpty()) {
314            fprintf(stderr, "pixel check failure: %s\n", msg.string());
315            return ::testing::AssertionFailure(
316                    ::testing::Message(msg.string()));
317        } else {
318            return ::testing::AssertionSuccess();
319        }
320    }
321
322    int mDisplaySecs;
323    sp<SurfaceComposerClient> mComposerClient;
324    sp<SurfaceControl> mSurfaceControl;
325
326    EGLDisplay mEglDisplay;
327    EGLSurface mEglSurface;
328    EGLContext mEglContext;
329    EGLConfig  mGlConfig;
330};
331
332// XXX: Code above this point should live elsewhere
333
334class SurfaceTextureGLTest : public GLTest {
335protected:
336    static const GLint TEX_ID = 123;
337
338    virtual void SetUp() {
339        GLTest::SetUp();
340        mST = new SurfaceTexture(TEX_ID);
341        mSTC = new SurfaceTextureClient(mST);
342        mANW = mSTC;
343
344        const char vsrc[] =
345            "attribute vec4 vPosition;\n"
346            "varying vec2 texCoords;\n"
347            "uniform mat4 texMatrix;\n"
348            "void main() {\n"
349            "  vec2 vTexCoords = 0.5 * (vPosition.xy + vec2(1.0, 1.0));\n"
350            "  texCoords = (texMatrix * vec4(vTexCoords, 0.0, 1.0)).xy;\n"
351            "  gl_Position = vPosition;\n"
352            "}\n";
353
354        const char fsrc[] =
355            "#extension GL_OES_EGL_image_external : require\n"
356            "precision mediump float;\n"
357            "uniform samplerExternalOES texSampler;\n"
358            "varying vec2 texCoords;\n"
359            "void main() {\n"
360            "  gl_FragColor = texture2D(texSampler, texCoords);\n"
361            "}\n";
362
363        {
364            SCOPED_TRACE("creating shader program");
365            createProgram(vsrc, fsrc, &mPgm);
366            if (HasFatalFailure()) {
367                return;
368            }
369        }
370
371        mPositionHandle = glGetAttribLocation(mPgm, "vPosition");
372        ASSERT_EQ(GLenum(GL_NO_ERROR), glGetError());
373        ASSERT_NE(-1, mPositionHandle);
374        mTexSamplerHandle = glGetUniformLocation(mPgm, "texSampler");
375        ASSERT_EQ(GLenum(GL_NO_ERROR), glGetError());
376        ASSERT_NE(-1, mTexSamplerHandle);
377        mTexMatrixHandle = glGetUniformLocation(mPgm, "texMatrix");
378        ASSERT_EQ(GLenum(GL_NO_ERROR), glGetError());
379        ASSERT_NE(-1, mTexMatrixHandle);
380    }
381
382    // drawTexture draws the SurfaceTexture over the entire GL viewport.
383    void drawTexture() {
384        const GLfloat triangleVertices[] = {
385            -1.0f, 1.0f,
386            -1.0f, -1.0f,
387            1.0f, -1.0f,
388            1.0f, 1.0f,
389        };
390
391        glVertexAttribPointer(mPositionHandle, 2, GL_FLOAT, GL_FALSE, 0, triangleVertices);
392        ASSERT_EQ(GLenum(GL_NO_ERROR), glGetError());
393        glEnableVertexAttribArray(mPositionHandle);
394        ASSERT_EQ(GLenum(GL_NO_ERROR), glGetError());
395
396        glUseProgram(mPgm);
397        glUniform1i(mTexSamplerHandle, 0);
398        ASSERT_EQ(GLenum(GL_NO_ERROR), glGetError());
399        glBindTexture(GL_TEXTURE_EXTERNAL_OES, TEX_ID);
400        ASSERT_EQ(GLenum(GL_NO_ERROR), glGetError());
401
402        // XXX: These calls are not needed for GL_TEXTURE_EXTERNAL_OES as
403        // they're setting the defautls for that target, but when hacking things
404        // to use GL_TEXTURE_2D they are needed to achieve the same behavior.
405        glTexParameteri(GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
406        ASSERT_EQ(GLenum(GL_NO_ERROR), glGetError());
407        glTexParameteri(GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
408        ASSERT_EQ(GLenum(GL_NO_ERROR), glGetError());
409        glTexParameteri(GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
410        ASSERT_EQ(GLenum(GL_NO_ERROR), glGetError());
411        glTexParameteri(GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
412        ASSERT_EQ(GLenum(GL_NO_ERROR), glGetError());
413
414        GLfloat texMatrix[16];
415        mST->getTransformMatrix(texMatrix);
416        glUniformMatrix4fv(mTexMatrixHandle, 1, GL_FALSE, texMatrix);
417
418        glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
419        ASSERT_EQ(GLenum(GL_NO_ERROR), glGetError());
420    }
421
422    sp<SurfaceTexture> mST;
423    sp<SurfaceTextureClient> mSTC;
424    sp<ANativeWindow> mANW;
425
426    GLuint mPgm;
427    GLint mPositionHandle;
428    GLint mTexSamplerHandle;
429    GLint mTexMatrixHandle;
430};
431
432// Fill a YV12 buffer with a multi-colored checkerboard pattern
433void fillYV12Buffer(uint8_t* buf, int w, int h, int stride) {
434    const int blockWidth = w > 16 ? w / 16 : 1;
435    const int blockHeight = h > 16 ? h / 16 : 1;
436    const int yuvTexOffsetY = 0;
437    int yuvTexStrideY = stride;
438    int yuvTexOffsetV = yuvTexStrideY * h;
439    int yuvTexStrideV = (yuvTexStrideY/2 + 0xf) & ~0xf;
440    int yuvTexOffsetU = yuvTexOffsetV + yuvTexStrideV * h/2;
441    int yuvTexStrideU = yuvTexStrideV;
442    for (int x = 0; x < w; x++) {
443        for (int y = 0; y < h; y++) {
444            int parityX = (x / blockWidth) & 1;
445            int parityY = (y / blockHeight) & 1;
446            unsigned char intensity = (parityX ^ parityY) ? 63 : 191;
447            buf[yuvTexOffsetY + (y * yuvTexStrideY) + x] = intensity;
448            if (x < w / 2 && y < h / 2) {
449                buf[yuvTexOffsetU + (y * yuvTexStrideU) + x] = intensity;
450                if (x * 2 < w / 2 && y * 2 < h / 2) {
451                    buf[yuvTexOffsetV + (y*2 * yuvTexStrideV) + x*2 + 0] =
452                    buf[yuvTexOffsetV + (y*2 * yuvTexStrideV) + x*2 + 1] =
453                    buf[yuvTexOffsetV + ((y*2+1) * yuvTexStrideV) + x*2 + 0] =
454                    buf[yuvTexOffsetV + ((y*2+1) * yuvTexStrideV) + x*2 + 1] =
455                        intensity;
456                }
457            }
458        }
459    }
460}
461
462// Fill a YV12 buffer with red outside a given rectangle and green inside it.
463void fillYV12BufferRect(uint8_t* buf, int w, int h, int stride,
464        const android_native_rect_t& rect) {
465    const int yuvTexOffsetY = 0;
466    int yuvTexStrideY = stride;
467    int yuvTexOffsetV = yuvTexStrideY * h;
468    int yuvTexStrideV = (yuvTexStrideY/2 + 0xf) & ~0xf;
469    int yuvTexOffsetU = yuvTexOffsetV + yuvTexStrideV * h/2;
470    int yuvTexStrideU = yuvTexStrideV;
471    for (int x = 0; x < w; x++) {
472        for (int y = 0; y < h; y++) {
473            bool inside = rect.left <= x && x < rect.right &&
474                    rect.top <= y && y < rect.bottom;
475            buf[yuvTexOffsetY + (y * yuvTexStrideY) + x] = inside ? 240 : 64;
476            if (x < w / 2 && y < h / 2) {
477                bool inside = rect.left <= 2*x && 2*x < rect.right &&
478                        rect.top <= 2*y && 2*y < rect.bottom;
479                buf[yuvTexOffsetU + (y * yuvTexStrideU) + x] = 16;
480                buf[yuvTexOffsetV + (y * yuvTexStrideV) + x] =
481                        inside ? 16 : 255;
482            }
483        }
484    }
485}
486
487void fillRGBA8Buffer(uint8_t* buf, int w, int h, int stride) {
488    const size_t PIXEL_SIZE = 4;
489    for (int x = 0; x < w; x++) {
490        for (int y = 0; y < h; y++) {
491            off_t offset = (y * stride + x) * PIXEL_SIZE;
492            for (int c = 0; c < 4; c++) {
493                int parityX = (x / (1 << (c+2))) & 1;
494                int parityY = (y / (1 << (c+2))) & 1;
495                buf[offset + c] = (parityX ^ parityY) ? 231 : 35;
496            }
497        }
498    }
499}
500
501TEST_F(SurfaceTextureGLTest, TexturingFromCpuFilledYV12BufferNpot) {
502    const int texWidth = 64;
503    const int texHeight = 66;
504
505    ASSERT_EQ(NO_ERROR, native_window_set_buffers_geometry(mANW.get(),
506            texWidth, texHeight, HAL_PIXEL_FORMAT_YV12));
507    ASSERT_EQ(NO_ERROR, native_window_set_usage(mANW.get(),
508            GRALLOC_USAGE_SW_READ_OFTEN | GRALLOC_USAGE_SW_WRITE_OFTEN));
509
510    ANativeWindowBuffer* anb;
511    ASSERT_EQ(NO_ERROR, mANW->dequeueBuffer(mANW.get(), &anb));
512    ASSERT_TRUE(anb != NULL);
513
514    sp<GraphicBuffer> buf(new GraphicBuffer(anb, false));
515    ASSERT_EQ(NO_ERROR, mANW->lockBuffer(mANW.get(), buf->getNativeBuffer()));
516
517    // Fill the buffer with the a checkerboard pattern
518    uint8_t* img = NULL;
519    buf->lock(GRALLOC_USAGE_SW_WRITE_OFTEN, (void**)(&img));
520    fillYV12Buffer(img, texWidth, texHeight, buf->getStride());
521    buf->unlock();
522    ASSERT_EQ(NO_ERROR, mANW->queueBuffer(mANW.get(), buf->getNativeBuffer()));
523
524    mST->updateTexImage();
525
526    glClearColor(0.2, 0.2, 0.2, 0.2);
527    glClear(GL_COLOR_BUFFER_BIT);
528
529    drawTexture();
530
531    EXPECT_TRUE(checkPixel( 0,  0, 255, 127, 255, 255));
532    EXPECT_TRUE(checkPixel(63,  0,   0, 133,   0, 255));
533    EXPECT_TRUE(checkPixel(63, 63,   0, 133,   0, 255));
534    EXPECT_TRUE(checkPixel( 0, 63, 255, 127, 255, 255));
535
536    EXPECT_TRUE(checkPixel(22, 44, 247,  70, 255, 255));
537    EXPECT_TRUE(checkPixel(45, 52, 209,  32, 235, 255));
538    EXPECT_TRUE(checkPixel(52, 51, 100, 255,  73, 255));
539    EXPECT_TRUE(checkPixel( 7, 31, 155,   0, 118, 255));
540    EXPECT_TRUE(checkPixel(31,  9, 148,  71, 110, 255));
541    EXPECT_TRUE(checkPixel(29, 35, 255, 127, 255, 255));
542    EXPECT_TRUE(checkPixel(36, 22, 155,  29,   0, 255));
543}
544
545// XXX: This test is disabled because it it currently broken on all devices to
546// which I have access.  Some of the checkPixel calls are not correct because
547// I just copied them from the npot test above and haven't bothered to figure
548// out the correct values.
549TEST_F(SurfaceTextureGLTest, DISABLED_TexturingFromCpuFilledYV12BufferPow2) {
550    const int texWidth = 64;
551    const int texHeight = 64;
552
553    ASSERT_EQ(NO_ERROR, native_window_set_buffers_geometry(mANW.get(),
554            texWidth, texHeight, HAL_PIXEL_FORMAT_YV12));
555    ASSERT_EQ(NO_ERROR, native_window_set_usage(mANW.get(),
556            GRALLOC_USAGE_SW_READ_OFTEN | GRALLOC_USAGE_SW_WRITE_OFTEN));
557
558    ANativeWindowBuffer* anb;
559    ASSERT_EQ(NO_ERROR, mANW->dequeueBuffer(mANW.get(), &anb));
560    ASSERT_TRUE(anb != NULL);
561
562    sp<GraphicBuffer> buf(new GraphicBuffer(anb, false));
563    ASSERT_EQ(NO_ERROR, mANW->lockBuffer(mANW.get(), buf->getNativeBuffer()));
564
565    // Fill the buffer with the a checkerboard pattern
566    uint8_t* img = NULL;
567    buf->lock(GRALLOC_USAGE_SW_WRITE_OFTEN, (void**)(&img));
568    fillYV12Buffer(img, texWidth, texHeight, buf->getStride());
569    buf->unlock();
570    ASSERT_EQ(NO_ERROR, mANW->queueBuffer(mANW.get(), buf->getNativeBuffer()));
571
572    mST->updateTexImage();
573
574    glClearColor(0.2, 0.2, 0.2, 0.2);
575    glClear(GL_COLOR_BUFFER_BIT);
576
577    drawTexture();
578
579    EXPECT_TRUE(checkPixel( 0,  0, 255, 127, 255, 255));
580    EXPECT_TRUE(checkPixel(63,  0,   0, 133,   0, 255));
581    EXPECT_TRUE(checkPixel(63, 63,   0, 133,   0, 255));
582    EXPECT_TRUE(checkPixel( 0, 63, 255, 127, 255, 255));
583
584    EXPECT_TRUE(checkPixel(22, 19, 247,  70, 255, 255));
585    EXPECT_TRUE(checkPixel(45, 11, 209,  32, 235, 255));
586    EXPECT_TRUE(checkPixel(52, 12, 100, 255,  73, 255));
587    EXPECT_TRUE(checkPixel( 7, 32, 155,   0, 118, 255));
588    EXPECT_TRUE(checkPixel(31, 54, 148,  71, 110, 255));
589    EXPECT_TRUE(checkPixel(29, 28, 255, 127, 255, 255));
590    EXPECT_TRUE(checkPixel(36, 41, 155,  29,   0, 255));
591}
592
593TEST_F(SurfaceTextureGLTest, TexturingFromCpuFilledYV12BufferWithCrop) {
594    const int texWidth = 64;
595    const int texHeight = 66;
596
597    ASSERT_EQ(NO_ERROR, native_window_set_buffers_geometry(mANW.get(),
598            texWidth, texHeight, HAL_PIXEL_FORMAT_YV12));
599    ASSERT_EQ(NO_ERROR, native_window_set_usage(mANW.get(),
600            GRALLOC_USAGE_SW_READ_OFTEN | GRALLOC_USAGE_SW_WRITE_OFTEN));
601
602    android_native_rect_t crops[] = {
603        {4, 6, 22, 36},
604        {0, 6, 22, 36},
605        {4, 0, 22, 36},
606        {4, 6, texWidth, 36},
607        {4, 6, 22, texHeight},
608    };
609
610    for (int i = 0; i < 5; i++) {
611        const android_native_rect_t& crop(crops[i]);
612        SCOPED_TRACE(String8::format("rect{ l: %d t: %d r: %d b: %d }", crop.left,
613                crop.top, crop.right, crop.bottom).string());
614
615        ASSERT_EQ(NO_ERROR, native_window_set_crop(mANW.get(), &crop));
616
617        ANativeWindowBuffer* anb;
618        ASSERT_EQ(NO_ERROR, mANW->dequeueBuffer(mANW.get(), &anb));
619        ASSERT_TRUE(anb != NULL);
620
621        sp<GraphicBuffer> buf(new GraphicBuffer(anb, false));
622        ASSERT_EQ(NO_ERROR, mANW->lockBuffer(mANW.get(), buf->getNativeBuffer()));
623
624        uint8_t* img = NULL;
625        buf->lock(GRALLOC_USAGE_SW_WRITE_OFTEN, (void**)(&img));
626        fillYV12BufferRect(img, texWidth, texHeight, buf->getStride(), crop);
627        buf->unlock();
628        ASSERT_EQ(NO_ERROR, mANW->queueBuffer(mANW.get(), buf->getNativeBuffer()));
629
630        mST->updateTexImage();
631
632        glClearColor(0.2, 0.2, 0.2, 0.2);
633        glClear(GL_COLOR_BUFFER_BIT);
634
635        drawTexture();
636
637        EXPECT_TRUE(checkPixel( 0,  0,  82, 255,  35, 255));
638        EXPECT_TRUE(checkPixel(63,  0,  82, 255,  35, 255));
639        EXPECT_TRUE(checkPixel(63, 63,  82, 255,  35, 255));
640        EXPECT_TRUE(checkPixel( 0, 63,  82, 255,  35, 255));
641
642        EXPECT_TRUE(checkPixel(25, 14,  82, 255,  35, 255));
643        EXPECT_TRUE(checkPixel(35, 31,  82, 255,  35, 255));
644        EXPECT_TRUE(checkPixel(57,  6,  82, 255,  35, 255));
645        EXPECT_TRUE(checkPixel( 5, 42,  82, 255,  35, 255));
646        EXPECT_TRUE(checkPixel(32, 33,  82, 255,  35, 255));
647        EXPECT_TRUE(checkPixel(16, 26,  82, 255,  35, 255));
648        EXPECT_TRUE(checkPixel(46, 51,  82, 255,  35, 255));
649    }
650}
651
652// XXX: This test is disabled because there are currently no drivers that can
653// handle RGBA textures with the GL_TEXTURE_EXTERNAL_OES target.
654TEST_F(SurfaceTextureGLTest, DISABLED_TexturingFromCpuFilledRGBABufferNpot) {
655    const int texWidth = 64;
656    const int texHeight = 66;
657
658    ASSERT_EQ(NO_ERROR, native_window_set_buffers_geometry(mANW.get(),
659            texWidth, texHeight, HAL_PIXEL_FORMAT_RGBA_8888));
660    ASSERT_EQ(NO_ERROR, native_window_set_usage(mANW.get(),
661            GRALLOC_USAGE_SW_READ_OFTEN | GRALLOC_USAGE_SW_WRITE_OFTEN));
662
663    android_native_buffer_t* anb;
664    ASSERT_EQ(NO_ERROR, mANW->dequeueBuffer(mANW.get(), &anb));
665    ASSERT_TRUE(anb != NULL);
666
667    sp<GraphicBuffer> buf(new GraphicBuffer(anb, false));
668    ASSERT_EQ(NO_ERROR, mANW->lockBuffer(mANW.get(), buf->getNativeBuffer()));
669
670    // Fill the buffer with the a checkerboard pattern
671    uint8_t* img = NULL;
672    buf->lock(GRALLOC_USAGE_SW_WRITE_OFTEN, (void**)(&img));
673    fillRGBA8Buffer(img, texWidth, texHeight, buf->getStride());
674    buf->unlock();
675    ASSERT_EQ(NO_ERROR, mANW->queueBuffer(mANW.get(), buf->getNativeBuffer()));
676
677    mST->updateTexImage();
678
679    glClearColor(0.2, 0.2, 0.2, 0.2);
680    glClear(GL_COLOR_BUFFER_BIT);
681
682    drawTexture();
683
684    EXPECT_TRUE(checkPixel( 0,  0,  35,  35,  35,  35));
685    EXPECT_TRUE(checkPixel(63,  0, 231, 231, 231, 231));
686    EXPECT_TRUE(checkPixel(63, 63, 231, 231, 231, 231));
687    EXPECT_TRUE(checkPixel( 0, 63,  35,  35,  35,  35));
688
689    EXPECT_TRUE(checkPixel(15, 10,  35, 231, 231, 231));
690    EXPECT_TRUE(checkPixel(24, 63,  35, 231, 231,  35));
691    EXPECT_TRUE(checkPixel(19, 40,  87, 179,  35,  35));
692    EXPECT_TRUE(checkPixel(38, 30, 231,  35,  35,  35));
693    EXPECT_TRUE(checkPixel(42, 54,  35,  35,  35, 231));
694    EXPECT_TRUE(checkPixel(37, 33,  35, 231, 231, 231));
695    EXPECT_TRUE(checkPixel(31,  8, 231,  35,  35, 231));
696    EXPECT_TRUE(checkPixel(36, 47, 231,  35, 231, 231));
697    EXPECT_TRUE(checkPixel(24, 63,  35, 231, 231,  35));
698    EXPECT_TRUE(checkPixel(48,  3, 231, 231,  35,  35));
699    EXPECT_TRUE(checkPixel(54, 50,  35, 231, 231, 231));
700    EXPECT_TRUE(checkPixel(24, 25, 191, 191, 231, 231));
701    EXPECT_TRUE(checkPixel(10,  9,  93,  93, 231, 231));
702    EXPECT_TRUE(checkPixel(29,  4,  35,  35,  35, 231));
703    EXPECT_TRUE(checkPixel(56, 31,  35, 231, 231,  35));
704    EXPECT_TRUE(checkPixel(58, 55,  35,  35, 231, 231));
705}
706
707// XXX: This test is disabled because there are currently no drivers that can
708// handle RGBA textures with the GL_TEXTURE_EXTERNAL_OES target.
709TEST_F(SurfaceTextureGLTest, DISABLED_TexturingFromCpuFilledRGBABufferPow2) {
710    const int texWidth = 64;
711    const int texHeight = 64;
712
713    ASSERT_EQ(NO_ERROR, native_window_set_buffers_geometry(mANW.get(),
714            texWidth, texHeight, HAL_PIXEL_FORMAT_RGBA_8888));
715    ASSERT_EQ(NO_ERROR, native_window_set_usage(mANW.get(),
716            GRALLOC_USAGE_SW_READ_OFTEN | GRALLOC_USAGE_SW_WRITE_OFTEN));
717
718    android_native_buffer_t* anb;
719    ASSERT_EQ(NO_ERROR, mANW->dequeueBuffer(mANW.get(), &anb));
720    ASSERT_TRUE(anb != NULL);
721
722    sp<GraphicBuffer> buf(new GraphicBuffer(anb, false));
723    ASSERT_EQ(NO_ERROR, mANW->lockBuffer(mANW.get(), buf->getNativeBuffer()));
724
725    // Fill the buffer with the a checkerboard pattern
726    uint8_t* img = NULL;
727    buf->lock(GRALLOC_USAGE_SW_WRITE_OFTEN, (void**)(&img));
728    fillRGBA8Buffer(img, texWidth, texHeight, buf->getStride());
729    buf->unlock();
730    ASSERT_EQ(NO_ERROR, mANW->queueBuffer(mANW.get(), buf->getNativeBuffer()));
731
732    mST->updateTexImage();
733
734    glClearColor(0.2, 0.2, 0.2, 0.2);
735    glClear(GL_COLOR_BUFFER_BIT);
736
737    drawTexture();
738
739    EXPECT_TRUE(checkPixel( 0,  0, 231, 231, 231, 231));
740    EXPECT_TRUE(checkPixel(63,  0,  35,  35,  35,  35));
741    EXPECT_TRUE(checkPixel(63, 63, 231, 231, 231, 231));
742    EXPECT_TRUE(checkPixel( 0, 63,  35,  35,  35,  35));
743
744    EXPECT_TRUE(checkPixel(12, 46, 231, 231, 231,  35));
745    EXPECT_TRUE(checkPixel(16,  1, 231, 231,  35, 231));
746    EXPECT_TRUE(checkPixel(21, 12, 231,  35,  35, 231));
747    EXPECT_TRUE(checkPixel(26, 51, 231,  35, 231,  35));
748    EXPECT_TRUE(checkPixel( 5, 32,  35, 231, 231,  35));
749    EXPECT_TRUE(checkPixel(13,  8,  35, 231, 231, 231));
750    EXPECT_TRUE(checkPixel(46,  3,  35,  35, 231,  35));
751    EXPECT_TRUE(checkPixel(30, 33,  35,  35,  35,  35));
752    EXPECT_TRUE(checkPixel( 6, 52, 231, 231,  35,  35));
753    EXPECT_TRUE(checkPixel(55, 33,  35, 231,  35, 231));
754    EXPECT_TRUE(checkPixel(16, 29,  35,  35, 231, 231));
755    EXPECT_TRUE(checkPixel( 1, 30,  35,  35,  35, 231));
756    EXPECT_TRUE(checkPixel(41, 37,  35,  35, 231, 231));
757    EXPECT_TRUE(checkPixel(46, 29, 231, 231,  35,  35));
758    EXPECT_TRUE(checkPixel(15, 25,  35, 231,  35, 231));
759    EXPECT_TRUE(checkPixel( 3, 52,  35, 231,  35,  35));
760}
761
762// XXX: This test is disabled because there are currently no drivers that can
763// handle RGBA textures with the GL_TEXTURE_EXTERNAL_OES target.
764TEST_F(SurfaceTextureGLTest, DISABLED_TexturingFromGLFilledRGBABufferPow2) {
765    const int texWidth = 64;
766    const int texHeight = 64;
767
768    mST->setDefaultBufferSize(texWidth, texHeight);
769
770    // Do the producer side of things
771    EGLSurface stcEglSurface = eglCreateWindowSurface(mEglDisplay, mGlConfig,
772            mANW.get(), NULL);
773    ASSERT_EQ(EGL_SUCCESS, eglGetError());
774    ASSERT_NE(EGL_NO_SURFACE, mEglSurface);
775
776    EXPECT_TRUE(eglMakeCurrent(mEglDisplay, stcEglSurface, stcEglSurface,
777            mEglContext));
778    ASSERT_EQ(EGL_SUCCESS, eglGetError());
779
780    glClearColor(0.6, 0.6, 0.6, 0.6);
781    glClear(GL_COLOR_BUFFER_BIT);
782
783    glEnable(GL_SCISSOR_TEST);
784    glScissor(4, 4, 4, 4);
785    glClearColor(1.0, 0.0, 0.0, 1.0);
786    glClear(GL_COLOR_BUFFER_BIT);
787
788    glScissor(24, 48, 4, 4);
789    glClearColor(0.0, 1.0, 0.0, 1.0);
790    glClear(GL_COLOR_BUFFER_BIT);
791
792    glScissor(37, 17, 4, 4);
793    glClearColor(0.0, 0.0, 1.0, 1.0);
794    glClear(GL_COLOR_BUFFER_BIT);
795
796    eglSwapBuffers(mEglDisplay, stcEglSurface);
797
798    // Do the consumer side of things
799    EXPECT_TRUE(eglMakeCurrent(mEglDisplay, mEglSurface, mEglSurface,
800            mEglContext));
801    ASSERT_EQ(EGL_SUCCESS, eglGetError());
802
803    glDisable(GL_SCISSOR_TEST);
804
805    mST->updateTexImage();
806
807    glClearColor(0.2, 0.2, 0.2, 0.2);
808    glClear(GL_COLOR_BUFFER_BIT);
809
810    drawTexture();
811
812    EXPECT_TRUE(checkPixel( 0,  0, 153, 153, 153, 153));
813    EXPECT_TRUE(checkPixel(63,  0, 153, 153, 153, 153));
814    EXPECT_TRUE(checkPixel(63, 63, 153, 153, 153, 153));
815    EXPECT_TRUE(checkPixel( 0, 63, 153, 153, 153, 153));
816
817    EXPECT_TRUE(checkPixel( 4,  7, 255,   0,   0, 255));
818    EXPECT_TRUE(checkPixel(25, 51,   0, 255,   0, 255));
819    EXPECT_TRUE(checkPixel(40, 19,   0,   0, 255, 255));
820    EXPECT_TRUE(checkPixel(29, 51, 153, 153, 153, 153));
821    EXPECT_TRUE(checkPixel( 5, 32, 153, 153, 153, 153));
822    EXPECT_TRUE(checkPixel(13,  8, 153, 153, 153, 153));
823    EXPECT_TRUE(checkPixel(46,  3, 153, 153, 153, 153));
824    EXPECT_TRUE(checkPixel(30, 33, 153, 153, 153, 153));
825    EXPECT_TRUE(checkPixel( 6, 52, 153, 153, 153, 153));
826    EXPECT_TRUE(checkPixel(55, 33, 153, 153, 153, 153));
827    EXPECT_TRUE(checkPixel(16, 29, 153, 153, 153, 153));
828    EXPECT_TRUE(checkPixel( 1, 30, 153, 153, 153, 153));
829    EXPECT_TRUE(checkPixel(41, 37, 153, 153, 153, 153));
830    EXPECT_TRUE(checkPixel(46, 29, 153, 153, 153, 153));
831    EXPECT_TRUE(checkPixel(15, 25, 153, 153, 153, 153));
832    EXPECT_TRUE(checkPixel( 3, 52, 153, 153, 153, 153));
833}
834
835/*
836 * This test is for testing GL -> GL texture streaming via SurfaceTexture.  It
837 * contains functionality to create a producer thread that will perform GL
838 * rendering to an ANativeWindow that feeds frames to a SurfaceTexture.
839 * Additionally it supports interlocking the producer and consumer threads so
840 * that a specific sequence of calls can be deterministically created by the
841 * test.
842 *
843 * The intended usage is as follows:
844 *
845 * TEST_F(...) {
846 *     class PT : public ProducerThread {
847 *         virtual void render() {
848 *             ...
849 *             swapBuffers();
850 *         }
851 *     };
852 *
853 *     runProducerThread(new PT());
854 *
855 *     // The order of these calls will vary from test to test and may include
856 *     // multiple frames and additional operations (e.g. GL rendering from the
857 *     // texture).
858 *     fc->waitForFrame();
859 *     mST->updateTexImage();
860 *     fc->finishFrame();
861 * }
862 *
863 */
864class SurfaceTextureGLToGLTest : public SurfaceTextureGLTest {
865protected:
866
867    // ProducerThread is an abstract base class to simplify the creation of
868    // OpenGL ES frame producer threads.
869    class ProducerThread : public Thread {
870    public:
871        virtual ~ProducerThread() {
872        }
873
874        void setEglObjects(EGLDisplay producerEglDisplay,
875                EGLSurface producerEglSurface,
876                EGLContext producerEglContext) {
877            mProducerEglDisplay = producerEglDisplay;
878            mProducerEglSurface = producerEglSurface;
879            mProducerEglContext = producerEglContext;
880        }
881
882        virtual bool threadLoop() {
883            eglMakeCurrent(mProducerEglDisplay, mProducerEglSurface,
884                    mProducerEglSurface, mProducerEglContext);
885            render();
886            eglMakeCurrent(mProducerEglDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE,
887                    EGL_NO_CONTEXT);
888            return false;
889        }
890
891    protected:
892        virtual void render() = 0;
893
894        void swapBuffers() {
895            eglSwapBuffers(mProducerEglDisplay, mProducerEglSurface);
896        }
897
898        EGLDisplay mProducerEglDisplay;
899        EGLSurface mProducerEglSurface;
900        EGLContext mProducerEglContext;
901    };
902
903    // FrameCondition is a utility class for interlocking between the producer
904    // and consumer threads.  The FrameCondition object should be created and
905    // destroyed in the consumer thread only.  The consumer thread should set
906    // the FrameCondition as the FrameAvailableListener of the SurfaceTexture,
907    // and should call both waitForFrame and finishFrame once for each expected
908    // frame.
909    //
910    // This interlocking relies on the fact that onFrameAvailable gets called
911    // synchronously from SurfaceTexture::queueBuffer.
912    class FrameCondition : public SurfaceTexture::FrameAvailableListener {
913    public:
914        // waitForFrame waits for the next frame to arrive.  This should be
915        // called from the consumer thread once for every frame expected by the
916        // test.
917        void waitForFrame() {
918            LOGV("+waitForFrame");
919            Mutex::Autolock lock(mMutex);
920            status_t result = mFrameAvailableCondition.wait(mMutex);
921            LOGV("-waitForFrame");
922        }
923
924        // Allow the producer to return from its swapBuffers call and continue
925        // on to produce the next frame.  This should be called by the consumer
926        // thread once for every frame expected by the test.
927        void finishFrame() {
928            LOGV("+finishFrame");
929            Mutex::Autolock lock(mMutex);
930            mFrameFinishCondition.signal();
931            LOGV("-finishFrame");
932        }
933
934        // This should be called by SurfaceTexture on the producer thread.
935        virtual void onFrameAvailable() {
936            LOGV("+onFrameAvailable");
937            Mutex::Autolock lock(mMutex);
938            mFrameAvailableCondition.signal();
939            mFrameFinishCondition.wait(mMutex);
940            LOGV("-onFrameAvailable");
941        }
942
943    protected:
944        Mutex mMutex;
945        Condition mFrameAvailableCondition;
946        Condition mFrameFinishCondition;
947    };
948
949    SurfaceTextureGLToGLTest():
950            mProducerEglSurface(EGL_NO_SURFACE),
951            mProducerEglContext(EGL_NO_CONTEXT) {
952    }
953
954    virtual void SetUp() {
955        SurfaceTextureGLTest::SetUp();
956
957        EGLConfig myConfig = {0};
958        EGLint numConfigs = 0;
959        EXPECT_TRUE(eglChooseConfig(mEglDisplay, getConfigAttribs(), &myConfig,
960                1, &numConfigs));
961        ASSERT_EQ(EGL_SUCCESS, eglGetError());
962
963        mProducerEglSurface = eglCreateWindowSurface(mEglDisplay, myConfig,
964                mANW.get(), NULL);
965        ASSERT_EQ(EGL_SUCCESS, eglGetError());
966        ASSERT_NE(EGL_NO_SURFACE, mProducerEglSurface);
967
968        mProducerEglContext = eglCreateContext(mEglDisplay, myConfig,
969                EGL_NO_CONTEXT, getContextAttribs());
970        ASSERT_EQ(EGL_SUCCESS, eglGetError());
971        ASSERT_NE(EGL_NO_CONTEXT, mProducerEglContext);
972
973        mFC = new FrameCondition();
974        mST->setFrameAvailableListener(mFC);
975    }
976
977    virtual void TearDown() {
978        if (mProducerThread != NULL) {
979            mProducerThread->requestExitAndWait();
980        }
981        if (mProducerEglContext != EGL_NO_CONTEXT) {
982            eglDestroyContext(mEglDisplay, mProducerEglContext);
983        }
984        if (mProducerEglSurface != EGL_NO_SURFACE) {
985            eglDestroySurface(mEglDisplay, mProducerEglSurface);
986        }
987        mProducerThread.clear();
988        mFC.clear();
989    }
990
991    void runProducerThread(const sp<ProducerThread> producerThread) {
992        ASSERT_TRUE(mProducerThread == NULL);
993        mProducerThread = producerThread;
994        producerThread->setEglObjects(mEglDisplay, mProducerEglSurface,
995                mProducerEglContext);
996        producerThread->run();
997    }
998
999    EGLSurface mProducerEglSurface;
1000    EGLContext mProducerEglContext;
1001    sp<ProducerThread> mProducerThread;
1002    sp<FrameCondition> mFC;
1003};
1004
1005// XXX: This test is disabled because it causes hangs on some devices.
1006TEST_F(SurfaceTextureGLToGLTest, DISABLED_UpdateTexImageBeforeFrameFinishedWorks) {
1007    class PT : public ProducerThread {
1008        virtual void render() {
1009            glClearColor(0.0f, 1.0f, 0.0f, 1.0f);
1010            glClear(GL_COLOR_BUFFER_BIT);
1011            swapBuffers();
1012        }
1013    };
1014
1015    runProducerThread(new PT());
1016
1017    mFC->waitForFrame();
1018    mST->updateTexImage();
1019    mFC->finishFrame();
1020
1021    // TODO: Add frame verification once RGB TEX_EXTERNAL_OES is supported!
1022}
1023
1024// XXX: This test is disabled because it causes hangs on some devices.
1025TEST_F(SurfaceTextureGLToGLTest, DISABLED_UpdateTexImageAfterFrameFinishedWorks) {
1026    class PT : public ProducerThread {
1027        virtual void render() {
1028            glClearColor(0.0f, 1.0f, 0.0f, 1.0f);
1029            glClear(GL_COLOR_BUFFER_BIT);
1030            swapBuffers();
1031        }
1032    };
1033
1034    runProducerThread(new PT());
1035
1036    mFC->waitForFrame();
1037    mFC->finishFrame();
1038    mST->updateTexImage();
1039
1040    // TODO: Add frame verification once RGB TEX_EXTERNAL_OES is supported!
1041}
1042
1043// XXX: This test is disabled because it causes hangs on some devices.
1044TEST_F(SurfaceTextureGLToGLTest, DISABLED_RepeatedUpdateTexImageBeforeFrameFinishedWorks) {
1045    enum { NUM_ITERATIONS = 1024 };
1046
1047    class PT : public ProducerThread {
1048        virtual void render() {
1049            for (int i = 0; i < NUM_ITERATIONS; i++) {
1050                glClearColor(0.0f, 1.0f, 0.0f, 1.0f);
1051                glClear(GL_COLOR_BUFFER_BIT);
1052                LOGV("+swapBuffers");
1053                swapBuffers();
1054                LOGV("-swapBuffers");
1055            }
1056        }
1057    };
1058
1059    runProducerThread(new PT());
1060
1061    for (int i = 0; i < NUM_ITERATIONS; i++) {
1062        mFC->waitForFrame();
1063        LOGV("+updateTexImage");
1064        mST->updateTexImage();
1065        LOGV("-updateTexImage");
1066        mFC->finishFrame();
1067
1068        // TODO: Add frame verification once RGB TEX_EXTERNAL_OES is supported!
1069    }
1070}
1071
1072// XXX: This test is disabled because it causes hangs on some devices.
1073TEST_F(SurfaceTextureGLToGLTest, DISABLED_RepeatedUpdateTexImageAfterFrameFinishedWorks) {
1074    enum { NUM_ITERATIONS = 1024 };
1075
1076    class PT : public ProducerThread {
1077        virtual void render() {
1078            for (int i = 0; i < NUM_ITERATIONS; i++) {
1079                glClearColor(0.0f, 1.0f, 0.0f, 1.0f);
1080                glClear(GL_COLOR_BUFFER_BIT);
1081                LOGV("+swapBuffers");
1082                swapBuffers();
1083                LOGV("-swapBuffers");
1084            }
1085        }
1086    };
1087
1088    runProducerThread(new PT());
1089
1090    for (int i = 0; i < NUM_ITERATIONS; i++) {
1091        mFC->waitForFrame();
1092        mFC->finishFrame();
1093        LOGV("+updateTexImage");
1094        mST->updateTexImage();
1095        LOGV("-updateTexImage");
1096
1097        // TODO: Add frame verification once RGB TEX_EXTERNAL_OES is supported!
1098    }
1099}
1100
1101} // namespace android
1102