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_TAG "SurfaceTexture_test"
18//#define LOG_NDEBUG 0
19
20#include <gtest/gtest.h>
21#include <gui/GLConsumer.h>
22#include <ui/GraphicBuffer.h>
23#include <utils/String8.h>
24#include <utils/threads.h>
25
26#include <gui/ISurfaceComposer.h>
27#include <gui/Surface.h>
28#include <gui/SurfaceComposerClient.h>
29
30#include <EGL/egl.h>
31#include <EGL/eglext.h>
32#include <GLES/gl.h>
33#include <GLES/glext.h>
34#include <GLES2/gl2.h>
35#include <GLES2/gl2ext.h>
36
37#include <ui/FramebufferNativeWindow.h>
38#include <utils/UniquePtr.h>
39#include <android/native_window.h>
40
41namespace android {
42
43class GLTest : public ::testing::Test {
44protected:
45
46    GLTest():
47            mEglDisplay(EGL_NO_DISPLAY),
48            mEglSurface(EGL_NO_SURFACE),
49            mEglContext(EGL_NO_CONTEXT) {
50    }
51
52    virtual void SetUp() {
53        const ::testing::TestInfo* const testInfo =
54            ::testing::UnitTest::GetInstance()->current_test_info();
55        ALOGV("Begin test: %s.%s", testInfo->test_case_name(),
56                testInfo->name());
57
58        mEglDisplay = eglGetDisplay(EGL_DEFAULT_DISPLAY);
59        ASSERT_EQ(EGL_SUCCESS, eglGetError());
60        ASSERT_NE(EGL_NO_DISPLAY, mEglDisplay);
61
62        EGLint majorVersion;
63        EGLint minorVersion;
64        EXPECT_TRUE(eglInitialize(mEglDisplay, &majorVersion, &minorVersion));
65        ASSERT_EQ(EGL_SUCCESS, eglGetError());
66        RecordProperty("EglVersionMajor", majorVersion);
67        RecordProperty("EglVersionMajor", minorVersion);
68
69        EGLint numConfigs = 0;
70        EXPECT_TRUE(eglChooseConfig(mEglDisplay, getConfigAttribs(), &mGlConfig,
71                1, &numConfigs));
72        ASSERT_EQ(EGL_SUCCESS, eglGetError());
73
74        char* displaySecsEnv = getenv("GLTEST_DISPLAY_SECS");
75        if (displaySecsEnv != NULL) {
76            mDisplaySecs = atoi(displaySecsEnv);
77            if (mDisplaySecs < 0) {
78                mDisplaySecs = 0;
79            }
80        } else {
81            mDisplaySecs = 0;
82        }
83
84        if (mDisplaySecs > 0) {
85            mComposerClient = new SurfaceComposerClient;
86            ASSERT_EQ(NO_ERROR, mComposerClient->initCheck());
87
88            mSurfaceControl = mComposerClient->createSurface(
89                    String8("Test Surface"),
90                    getSurfaceWidth(), getSurfaceHeight(),
91                    PIXEL_FORMAT_RGB_888, 0);
92
93            ASSERT_TRUE(mSurfaceControl != NULL);
94            ASSERT_TRUE(mSurfaceControl->isValid());
95
96            SurfaceComposerClient::openGlobalTransaction();
97            ASSERT_EQ(NO_ERROR, mSurfaceControl->setLayer(0x7FFFFFFF));
98            ASSERT_EQ(NO_ERROR, mSurfaceControl->show());
99            SurfaceComposerClient::closeGlobalTransaction();
100
101            sp<ANativeWindow> window = mSurfaceControl->getSurface();
102            mEglSurface = eglCreateWindowSurface(mEglDisplay, mGlConfig,
103                    window.get(), NULL);
104        } else {
105            EGLint pbufferAttribs[] = {
106                EGL_WIDTH, getSurfaceWidth(),
107                EGL_HEIGHT, getSurfaceHeight(),
108                EGL_NONE };
109
110            mEglSurface = eglCreatePbufferSurface(mEglDisplay, mGlConfig,
111                    pbufferAttribs);
112        }
113        ASSERT_EQ(EGL_SUCCESS, eglGetError());
114        ASSERT_NE(EGL_NO_SURFACE, mEglSurface);
115
116        mEglContext = eglCreateContext(mEglDisplay, mGlConfig, EGL_NO_CONTEXT,
117                getContextAttribs());
118        ASSERT_EQ(EGL_SUCCESS, eglGetError());
119        ASSERT_NE(EGL_NO_CONTEXT, mEglContext);
120
121        EXPECT_TRUE(eglMakeCurrent(mEglDisplay, mEglSurface, mEglSurface,
122                mEglContext));
123        ASSERT_EQ(EGL_SUCCESS, eglGetError());
124
125        EGLint w, h;
126        EXPECT_TRUE(eglQuerySurface(mEglDisplay, mEglSurface, EGL_WIDTH, &w));
127        ASSERT_EQ(EGL_SUCCESS, eglGetError());
128        EXPECT_TRUE(eglQuerySurface(mEglDisplay, mEglSurface, EGL_HEIGHT, &h));
129        ASSERT_EQ(EGL_SUCCESS, eglGetError());
130        RecordProperty("EglSurfaceWidth", w);
131        RecordProperty("EglSurfaceHeight", h);
132
133        glViewport(0, 0, w, h);
134        ASSERT_EQ(GLenum(GL_NO_ERROR), glGetError());
135    }
136
137    virtual void TearDown() {
138        // Display the result
139        if (mDisplaySecs > 0 && mEglSurface != EGL_NO_SURFACE) {
140            eglSwapBuffers(mEglDisplay, mEglSurface);
141            sleep(mDisplaySecs);
142        }
143
144        if (mComposerClient != NULL) {
145            mComposerClient->dispose();
146        }
147        if (mEglContext != EGL_NO_CONTEXT) {
148            eglDestroyContext(mEglDisplay, mEglContext);
149        }
150        if (mEglSurface != EGL_NO_SURFACE) {
151            eglDestroySurface(mEglDisplay, mEglSurface);
152        }
153        if (mEglDisplay != EGL_NO_DISPLAY) {
154            eglMakeCurrent(mEglDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE,
155                    EGL_NO_CONTEXT);
156            eglTerminate(mEglDisplay);
157        }
158        ASSERT_EQ(EGL_SUCCESS, eglGetError());
159
160        const ::testing::TestInfo* const testInfo =
161            ::testing::UnitTest::GetInstance()->current_test_info();
162        ALOGV("End test:   %s.%s", testInfo->test_case_name(),
163                testInfo->name());
164    }
165
166    virtual EGLint const* getConfigAttribs() {
167        static EGLint sDefaultConfigAttribs[] = {
168            EGL_SURFACE_TYPE, EGL_PBUFFER_BIT,
169            EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT,
170            EGL_RED_SIZE, 8,
171            EGL_GREEN_SIZE, 8,
172            EGL_BLUE_SIZE, 8,
173            EGL_ALPHA_SIZE, 8,
174            EGL_DEPTH_SIZE, 16,
175            EGL_STENCIL_SIZE, 8,
176            EGL_NONE };
177
178        return sDefaultConfigAttribs;
179    }
180
181    virtual EGLint const* getContextAttribs() {
182        static EGLint sDefaultContextAttribs[] = {
183            EGL_CONTEXT_CLIENT_VERSION, 2,
184            EGL_NONE };
185
186        return sDefaultContextAttribs;
187    }
188
189    virtual EGLint getSurfaceWidth() {
190        return 512;
191    }
192
193    virtual EGLint getSurfaceHeight() {
194        return 512;
195    }
196
197    ::testing::AssertionResult checkPixel(int x, int y, int r,
198            int g, int b, int a, int tolerance=2) {
199        GLubyte pixel[4];
200        String8 msg;
201        glReadPixels(x, y, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, pixel);
202        GLenum err = glGetError();
203        if (err != GL_NO_ERROR) {
204            msg += String8::format("error reading pixel: %#x", err);
205            while ((err = glGetError()) != GL_NO_ERROR) {
206                msg += String8::format(", %#x", err);
207            }
208            return ::testing::AssertionFailure(
209                    ::testing::Message(msg.string()));
210        }
211        if (r >= 0 && abs(r - int(pixel[0])) > tolerance) {
212            msg += String8::format("r(%d isn't %d)", pixel[0], r);
213        }
214        if (g >= 0 && abs(g - int(pixel[1])) > tolerance) {
215            if (!msg.isEmpty()) {
216                msg += " ";
217            }
218            msg += String8::format("g(%d isn't %d)", pixel[1], g);
219        }
220        if (b >= 0 && abs(b - int(pixel[2])) > tolerance) {
221            if (!msg.isEmpty()) {
222                msg += " ";
223            }
224            msg += String8::format("b(%d isn't %d)", pixel[2], b);
225        }
226        if (a >= 0 && abs(a - int(pixel[3])) > tolerance) {
227            if (!msg.isEmpty()) {
228                msg += " ";
229            }
230            msg += String8::format("a(%d isn't %d)", pixel[3], a);
231        }
232        if (!msg.isEmpty()) {
233            return ::testing::AssertionFailure(
234                    ::testing::Message(msg.string()));
235        } else {
236            return ::testing::AssertionSuccess();
237        }
238    }
239
240    ::testing::AssertionResult assertRectEq(const Rect &r1,
241        const Rect &r2, int tolerance=1) {
242
243        String8 msg;
244
245        if (abs(r1.left - r2.left) > tolerance) {
246            msg += String8::format("left(%d isn't %d)", r1.left, r2.left);
247        }
248        if (abs(r1.top - r2.top) > tolerance) {
249            if (!msg.isEmpty()) {
250                msg += " ";
251            }
252            msg += String8::format("top(%d isn't %d)", r1.top, r2.top);
253        }
254        if (abs(r1.right - r2.right) > tolerance) {
255            if (!msg.isEmpty()) {
256                msg += " ";
257            }
258            msg += String8::format("right(%d isn't %d)", r1.right, r2.right);
259        }
260        if (abs(r1.bottom - r2.bottom) > tolerance) {
261            if (!msg.isEmpty()) {
262                msg += " ";
263            }
264            msg += String8::format("bottom(%d isn't %d)", r1.bottom, r2.bottom);
265        }
266        if (!msg.isEmpty()) {
267            msg += String8::format(" R1: [%d %d %d %d] R2: [%d %d %d %d]",
268                r1.left, r1.top, r1.right, r1.bottom,
269                r2.left, r2.top, r2.right, r2.bottom);
270            fprintf(stderr, "assertRectEq: %s\n", msg.string());
271            return ::testing::AssertionFailure(
272                    ::testing::Message(msg.string()));
273        } else {
274            return ::testing::AssertionSuccess();
275        }
276    }
277
278    int mDisplaySecs;
279    sp<SurfaceComposerClient> mComposerClient;
280    sp<SurfaceControl> mSurfaceControl;
281
282    EGLDisplay mEglDisplay;
283    EGLSurface mEglSurface;
284    EGLContext mEglContext;
285    EGLConfig  mGlConfig;
286};
287
288static void loadShader(GLenum shaderType, const char* pSource,
289        GLuint* outShader) {
290    GLuint shader = glCreateShader(shaderType);
291    ASSERT_EQ(GLenum(GL_NO_ERROR), glGetError());
292    if (shader) {
293        glShaderSource(shader, 1, &pSource, NULL);
294        ASSERT_EQ(GLenum(GL_NO_ERROR), glGetError());
295        glCompileShader(shader);
296        ASSERT_EQ(GLenum(GL_NO_ERROR), glGetError());
297        GLint compiled = 0;
298        glGetShaderiv(shader, GL_COMPILE_STATUS, &compiled);
299        ASSERT_EQ(GLenum(GL_NO_ERROR), glGetError());
300        if (!compiled) {
301            GLint infoLen = 0;
302            glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &infoLen);
303            ASSERT_EQ(GLenum(GL_NO_ERROR), glGetError());
304            if (infoLen) {
305                char* buf = (char*) malloc(infoLen);
306                if (buf) {
307                    glGetShaderInfoLog(shader, infoLen, NULL, buf);
308                    printf("Shader compile log:\n%s\n", buf);
309                    free(buf);
310                    FAIL();
311                }
312            } else {
313                char* buf = (char*) malloc(0x1000);
314                if (buf) {
315                    glGetShaderInfoLog(shader, 0x1000, NULL, buf);
316                    printf("Shader compile log:\n%s\n", buf);
317                    free(buf);
318                    FAIL();
319                }
320            }
321            glDeleteShader(shader);
322            shader = 0;
323        }
324    }
325    ASSERT_TRUE(shader != 0);
326    *outShader = shader;
327}
328
329static void createProgram(const char* pVertexSource,
330        const char* pFragmentSource, GLuint* outPgm) {
331    GLuint vertexShader, fragmentShader;
332    {
333        SCOPED_TRACE("compiling vertex shader");
334        ASSERT_NO_FATAL_FAILURE(loadShader(GL_VERTEX_SHADER, pVertexSource,
335                &vertexShader));
336    }
337    {
338        SCOPED_TRACE("compiling fragment shader");
339        ASSERT_NO_FATAL_FAILURE(loadShader(GL_FRAGMENT_SHADER, pFragmentSource,
340                &fragmentShader));
341    }
342
343    GLuint program = glCreateProgram();
344    ASSERT_EQ(GLenum(GL_NO_ERROR), glGetError());
345    if (program) {
346        glAttachShader(program, vertexShader);
347        ASSERT_EQ(GLenum(GL_NO_ERROR), glGetError());
348        glAttachShader(program, fragmentShader);
349        ASSERT_EQ(GLenum(GL_NO_ERROR), glGetError());
350        glLinkProgram(program);
351        GLint linkStatus = GL_FALSE;
352        glGetProgramiv(program, GL_LINK_STATUS, &linkStatus);
353        if (linkStatus != GL_TRUE) {
354            GLint bufLength = 0;
355            glGetProgramiv(program, GL_INFO_LOG_LENGTH, &bufLength);
356            if (bufLength) {
357                char* buf = (char*) malloc(bufLength);
358                if (buf) {
359                    glGetProgramInfoLog(program, bufLength, NULL, buf);
360                    printf("Program link log:\n%s\n", buf);
361                    free(buf);
362                    FAIL();
363                }
364            }
365            glDeleteProgram(program);
366            program = 0;
367        }
368    }
369    glDeleteShader(vertexShader);
370    glDeleteShader(fragmentShader);
371    ASSERT_TRUE(program != 0);
372    *outPgm = program;
373}
374
375static int abs(int value) {
376    return value > 0 ? value : -value;
377}
378
379
380// XXX: Code above this point should live elsewhere
381
382class MultiTextureConsumerTest : public GLTest {
383protected:
384    enum { TEX_ID = 123 };
385
386    virtual void SetUp() {
387        GLTest::SetUp();
388        sp<BufferQueue> bq = new BufferQueue();
389        mGlConsumer = new GLConsumer(bq, TEX_ID);
390        mSurface = new Surface(bq);
391        mANW = mSurface.get();
392
393    }
394    virtual void TearDown() {
395        GLTest::TearDown();
396    }
397    virtual EGLint const* getContextAttribs() {
398        return NULL;
399    }
400    virtual EGLint const* getConfigAttribs() {
401        static EGLint sDefaultConfigAttribs[] = {
402            EGL_SURFACE_TYPE, EGL_PBUFFER_BIT,
403            EGL_RED_SIZE, 8,
404            EGL_GREEN_SIZE, 8,
405            EGL_BLUE_SIZE, 8,
406            EGL_ALPHA_SIZE, 8,
407            EGL_NONE };
408
409        return sDefaultConfigAttribs;
410    }
411    sp<GLConsumer> mGlConsumer;
412    sp<Surface> mSurface;
413    ANativeWindow* mANW;
414};
415
416
417TEST_F(MultiTextureConsumerTest, EGLImageTargetWorks) {
418    ANativeWindow_Buffer buffer;
419
420    ASSERT_EQ(native_window_set_usage(mANW, GRALLOC_USAGE_SW_WRITE_OFTEN), NO_ERROR);
421    ASSERT_EQ(native_window_set_buffers_format(mANW, HAL_PIXEL_FORMAT_RGBA_8888), NO_ERROR);
422
423    glShadeModel(GL_FLAT);
424    glDisable(GL_DITHER);
425    glDisable(GL_CULL_FACE);
426    glViewport(0, 0, getSurfaceWidth(), getSurfaceHeight());
427    glOrthof(0, getSurfaceWidth(), 0, getSurfaceHeight(), 0, 1);
428    glEnableClientState(GL_VERTEX_ARRAY);
429    glColor4f(1, 1, 1, 1);
430
431    glBindTexture(GL_TEXTURE_EXTERNAL_OES, TEX_ID);
432    glTexParameterx(GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
433    glTexParameterx(GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
434    glTexParameterx(GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
435    glTexParameterx(GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
436
437    uint32_t texel = 0x80808080;
438    glBindTexture(GL_TEXTURE_2D, TEX_ID+1);
439    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, &texel);
440    glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
441    glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
442    glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
443    glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
444
445    glActiveTexture(GL_TEXTURE1);
446    glBindTexture(GL_TEXTURE_2D, TEX_ID+1);
447    glEnable(GL_TEXTURE_2D);
448    glTexEnvx(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
449
450    glActiveTexture(GL_TEXTURE0);
451    glBindTexture(GL_TEXTURE_EXTERNAL_OES, TEX_ID);
452    glEnable(GL_TEXTURE_EXTERNAL_OES);
453    glTexEnvx(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
454
455    glClear(GL_COLOR_BUFFER_BIT);
456    for (int i=0 ; i<8 ; i++) {
457        mSurface->lock(&buffer, NULL);
458        memset(buffer.bits, (i&7) * 0x20, buffer.stride * buffer.height * 4);
459        mSurface->unlockAndPost();
460
461        mGlConsumer->updateTexImage();
462
463        GLfloat vertices[][2] = { {i*16.0f, 0}, {(i+1)*16.0f, 0}, {(i+1)*16.0f, 16.0f}, {i*16.0f, 16.0f} };
464        glVertexPointer(2, GL_FLOAT, 0, vertices);
465        glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
466
467        ASSERT_EQ(GLenum(GL_NO_ERROR), glGetError());
468    }
469
470    for (int i=0 ; i<8 ; i++) {
471        EXPECT_TRUE(checkPixel(i*16 + 8,  8, i*16, i*16, i*16, i*16, 0));
472    }
473}
474
475
476
477class SurfaceTextureGLTest : public GLTest {
478protected:
479    enum { TEX_ID = 123 };
480
481    virtual void SetUp() {
482        GLTest::SetUp();
483        sp<BufferQueue> bq = new BufferQueue();
484        mBQ = bq;
485        mST = new GLConsumer(bq, TEX_ID);
486        mSTC = new Surface(bq);
487        mANW = mSTC;
488        mTextureRenderer = new TextureRenderer(TEX_ID, mST);
489        ASSERT_NO_FATAL_FAILURE(mTextureRenderer->SetUp());
490        mFW = new FrameWaiter;
491        mST->setFrameAvailableListener(mFW);
492    }
493
494    virtual void TearDown() {
495        mANW.clear();
496        mSTC.clear();
497        mST.clear();
498        GLTest::TearDown();
499    }
500
501    void drawTexture() {
502        mTextureRenderer->drawTexture();
503    }
504
505    class TextureRenderer: public RefBase {
506    public:
507        TextureRenderer(GLuint texName, const sp<GLConsumer>& st):
508                mTexName(texName),
509                mST(st) {
510        }
511
512        void SetUp() {
513            const char vsrc[] =
514                "attribute vec4 vPosition;\n"
515                "varying vec2 texCoords;\n"
516                "uniform mat4 texMatrix;\n"
517                "void main() {\n"
518                "  vec2 vTexCoords = 0.5 * (vPosition.xy + vec2(1.0, 1.0));\n"
519                "  texCoords = (texMatrix * vec4(vTexCoords, 0.0, 1.0)).xy;\n"
520                "  gl_Position = vPosition;\n"
521                "}\n";
522
523            const char fsrc[] =
524                "#extension GL_OES_EGL_image_external : require\n"
525                "precision mediump float;\n"
526                "uniform samplerExternalOES texSampler;\n"
527                "varying vec2 texCoords;\n"
528                "void main() {\n"
529                "  gl_FragColor = texture2D(texSampler, texCoords);\n"
530                "}\n";
531
532            {
533                SCOPED_TRACE("creating shader program");
534                ASSERT_NO_FATAL_FAILURE(createProgram(vsrc, fsrc, &mPgm));
535            }
536
537            mPositionHandle = glGetAttribLocation(mPgm, "vPosition");
538            ASSERT_EQ(GLenum(GL_NO_ERROR), glGetError());
539            ASSERT_NE(-1, mPositionHandle);
540            mTexSamplerHandle = glGetUniformLocation(mPgm, "texSampler");
541            ASSERT_EQ(GLenum(GL_NO_ERROR), glGetError());
542            ASSERT_NE(-1, mTexSamplerHandle);
543            mTexMatrixHandle = glGetUniformLocation(mPgm, "texMatrix");
544            ASSERT_EQ(GLenum(GL_NO_ERROR), glGetError());
545            ASSERT_NE(-1, mTexMatrixHandle);
546        }
547
548        // drawTexture draws the GLConsumer over the entire GL viewport.
549        void drawTexture() {
550            static const GLfloat triangleVertices[] = {
551                -1.0f, 1.0f,
552                -1.0f, -1.0f,
553                1.0f, -1.0f,
554                1.0f, 1.0f,
555            };
556
557            glVertexAttribPointer(mPositionHandle, 2, GL_FLOAT, GL_FALSE, 0,
558                    triangleVertices);
559            ASSERT_EQ(GLenum(GL_NO_ERROR), glGetError());
560            glEnableVertexAttribArray(mPositionHandle);
561            ASSERT_EQ(GLenum(GL_NO_ERROR), glGetError());
562
563            glUseProgram(mPgm);
564            glUniform1i(mTexSamplerHandle, 0);
565            ASSERT_EQ(GLenum(GL_NO_ERROR), glGetError());
566            glBindTexture(GL_TEXTURE_EXTERNAL_OES, mTexName);
567            ASSERT_EQ(GLenum(GL_NO_ERROR), glGetError());
568
569            // XXX: These calls are not needed for GL_TEXTURE_EXTERNAL_OES as
570            // they're setting the defautls for that target, but when hacking
571            // things to use GL_TEXTURE_2D they are needed to achieve the same
572            // behavior.
573            glTexParameteri(GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_MIN_FILTER,
574                    GL_LINEAR);
575            ASSERT_EQ(GLenum(GL_NO_ERROR), glGetError());
576            glTexParameteri(GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_MAG_FILTER,
577                    GL_LINEAR);
578            ASSERT_EQ(GLenum(GL_NO_ERROR), glGetError());
579            glTexParameteri(GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_WRAP_S,
580                    GL_CLAMP_TO_EDGE);
581            ASSERT_EQ(GLenum(GL_NO_ERROR), glGetError());
582            glTexParameteri(GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_WRAP_T,
583                    GL_CLAMP_TO_EDGE);
584            ASSERT_EQ(GLenum(GL_NO_ERROR), glGetError());
585
586            GLfloat texMatrix[16];
587            mST->getTransformMatrix(texMatrix);
588            glUniformMatrix4fv(mTexMatrixHandle, 1, GL_FALSE, texMatrix);
589
590            glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
591            ASSERT_EQ(GLenum(GL_NO_ERROR), glGetError());
592        }
593
594        GLuint mTexName;
595        sp<GLConsumer> mST;
596        GLuint mPgm;
597        GLint mPositionHandle;
598        GLint mTexSamplerHandle;
599        GLint mTexMatrixHandle;
600    };
601
602    class FrameWaiter : public GLConsumer::FrameAvailableListener {
603    public:
604        FrameWaiter():
605                mPendingFrames(0) {
606        }
607
608        void waitForFrame() {
609            Mutex::Autolock lock(mMutex);
610            while (mPendingFrames == 0) {
611                mCondition.wait(mMutex);
612            }
613            mPendingFrames--;
614        }
615
616        virtual void onFrameAvailable() {
617            Mutex::Autolock lock(mMutex);
618            mPendingFrames++;
619            mCondition.signal();
620        }
621
622        int mPendingFrames;
623        Mutex mMutex;
624        Condition mCondition;
625    };
626
627    // Note that GLConsumer will lose the notifications
628    // onBuffersReleased and onFrameAvailable as there is currently
629    // no way to forward the events.  This DisconnectWaiter will not let the
630    // disconnect finish until finishDisconnect() is called.  It will
631    // also block until a disconnect is called
632    class DisconnectWaiter : public BnConsumerListener {
633    public:
634        DisconnectWaiter () :
635            mWaitForDisconnect(false),
636            mPendingFrames(0) {
637        }
638
639        void waitForFrame() {
640            Mutex::Autolock lock(mMutex);
641            while (mPendingFrames == 0) {
642                mFrameCondition.wait(mMutex);
643            }
644            mPendingFrames--;
645        }
646
647        virtual void onFrameAvailable() {
648            Mutex::Autolock lock(mMutex);
649            mPendingFrames++;
650            mFrameCondition.signal();
651        }
652
653        virtual void onBuffersReleased() {
654            Mutex::Autolock lock(mMutex);
655            while (!mWaitForDisconnect) {
656                mDisconnectCondition.wait(mMutex);
657            }
658        }
659
660        void finishDisconnect() {
661            Mutex::Autolock lock(mMutex);
662            mWaitForDisconnect = true;
663            mDisconnectCondition.signal();
664        }
665
666    private:
667        Mutex mMutex;
668
669        bool mWaitForDisconnect;
670        Condition mDisconnectCondition;
671
672        int mPendingFrames;
673        Condition mFrameCondition;
674    };
675
676    sp<BufferQueue> mBQ;
677    sp<GLConsumer> mST;
678    sp<Surface> mSTC;
679    sp<ANativeWindow> mANW;
680    sp<TextureRenderer> mTextureRenderer;
681    sp<FrameWaiter> mFW;
682};
683
684// Fill a YV12 buffer with a multi-colored checkerboard pattern
685void fillYV12Buffer(uint8_t* buf, int w, int h, int stride) {
686    const int blockWidth = w > 16 ? w / 16 : 1;
687    const int blockHeight = h > 16 ? h / 16 : 1;
688    const int yuvTexOffsetY = 0;
689    int yuvTexStrideY = stride;
690    int yuvTexOffsetV = yuvTexStrideY * h;
691    int yuvTexStrideV = (yuvTexStrideY/2 + 0xf) & ~0xf;
692    int yuvTexOffsetU = yuvTexOffsetV + yuvTexStrideV * h/2;
693    int yuvTexStrideU = yuvTexStrideV;
694    for (int x = 0; x < w; x++) {
695        for (int y = 0; y < h; y++) {
696            int parityX = (x / blockWidth) & 1;
697            int parityY = (y / blockHeight) & 1;
698            unsigned char intensity = (parityX ^ parityY) ? 63 : 191;
699            buf[yuvTexOffsetY + (y * yuvTexStrideY) + x] = intensity;
700            if (x < w / 2 && y < h / 2) {
701                buf[yuvTexOffsetU + (y * yuvTexStrideU) + x] = intensity;
702                if (x * 2 < w / 2 && y * 2 < h / 2) {
703                    buf[yuvTexOffsetV + (y*2 * yuvTexStrideV) + x*2 + 0] =
704                    buf[yuvTexOffsetV + (y*2 * yuvTexStrideV) + x*2 + 1] =
705                    buf[yuvTexOffsetV + ((y*2+1) * yuvTexStrideV) + x*2 + 0] =
706                    buf[yuvTexOffsetV + ((y*2+1) * yuvTexStrideV) + x*2 + 1] =
707                        intensity;
708                }
709            }
710        }
711    }
712}
713
714// Fill a YV12 buffer with red outside a given rectangle and green inside it.
715void fillYV12BufferRect(uint8_t* buf, int w, int h, int stride,
716        const android_native_rect_t& rect) {
717    const int yuvTexOffsetY = 0;
718    int yuvTexStrideY = stride;
719    int yuvTexOffsetV = yuvTexStrideY * h;
720    int yuvTexStrideV = (yuvTexStrideY/2 + 0xf) & ~0xf;
721    int yuvTexOffsetU = yuvTexOffsetV + yuvTexStrideV * h/2;
722    int yuvTexStrideU = yuvTexStrideV;
723    for (int x = 0; x < w; x++) {
724        for (int y = 0; y < h; y++) {
725            bool inside = rect.left <= x && x < rect.right &&
726                    rect.top <= y && y < rect.bottom;
727            buf[yuvTexOffsetY + (y * yuvTexStrideY) + x] = inside ? 240 : 64;
728            if (x < w / 2 && y < h / 2) {
729                bool inside = rect.left <= 2*x && 2*x < rect.right &&
730                        rect.top <= 2*y && 2*y < rect.bottom;
731                buf[yuvTexOffsetU + (y * yuvTexStrideU) + x] = 16;
732                buf[yuvTexOffsetV + (y * yuvTexStrideV) + x] =
733                        inside ? 16 : 255;
734            }
735        }
736    }
737}
738
739void fillRGBA8Buffer(uint8_t* buf, int w, int h, int stride) {
740    const size_t PIXEL_SIZE = 4;
741    for (int x = 0; x < w; x++) {
742        for (int y = 0; y < h; y++) {
743            off_t offset = (y * stride + x) * PIXEL_SIZE;
744            for (int c = 0; c < 4; c++) {
745                int parityX = (x / (1 << (c+2))) & 1;
746                int parityY = (y / (1 << (c+2))) & 1;
747                buf[offset + c] = (parityX ^ parityY) ? 231 : 35;
748            }
749        }
750    }
751}
752
753void fillRGBA8BufferSolid(uint8_t* buf, int w, int h, int stride, uint8_t r,
754        uint8_t g, uint8_t b, uint8_t a) {
755    const size_t PIXEL_SIZE = 4;
756    for (int y = 0; y < h; y++) {
757        for (int x = 0; x < h; x++) {
758            off_t offset = (y * stride + x) * PIXEL_SIZE;
759            buf[offset + 0] = r;
760            buf[offset + 1] = g;
761            buf[offset + 2] = b;
762            buf[offset + 3] = a;
763        }
764    }
765}
766
767// Produce a single RGBA8 frame by filling a buffer with a checkerboard pattern
768// using the CPU.  This assumes that the ANativeWindow is already configured to
769// allow this to be done (e.g. the format is set to RGBA8).
770//
771// Calls to this function should be wrapped in an ASSERT_NO_FATAL_FAILURE().
772void produceOneRGBA8Frame(const sp<ANativeWindow>& anw) {
773    android_native_buffer_t* anb;
774    ASSERT_EQ(NO_ERROR, native_window_dequeue_buffer_and_wait(anw.get(),
775            &anb));
776    ASSERT_TRUE(anb != NULL);
777
778    sp<GraphicBuffer> buf(new GraphicBuffer(anb, false));
779
780    uint8_t* img = NULL;
781    ASSERT_EQ(NO_ERROR, buf->lock(GRALLOC_USAGE_SW_WRITE_OFTEN,
782            (void**)(&img)));
783    fillRGBA8Buffer(img, buf->getWidth(), buf->getHeight(), buf->getStride());
784    ASSERT_EQ(NO_ERROR, buf->unlock());
785    ASSERT_EQ(NO_ERROR, anw->queueBuffer(anw.get(), buf->getNativeBuffer(),
786            -1));
787}
788
789TEST_F(SurfaceTextureGLTest, TexturingFromCpuFilledYV12BufferNpot) {
790    const int texWidth = 64;
791    const int texHeight = 66;
792
793    ASSERT_EQ(NO_ERROR, native_window_set_buffers_geometry(mANW.get(),
794            texWidth, texHeight, HAL_PIXEL_FORMAT_YV12));
795    ASSERT_EQ(NO_ERROR, native_window_set_usage(mANW.get(),
796            GRALLOC_USAGE_SW_READ_OFTEN | GRALLOC_USAGE_SW_WRITE_OFTEN));
797
798    ANativeWindowBuffer* anb;
799    ASSERT_EQ(NO_ERROR, native_window_dequeue_buffer_and_wait(mANW.get(),
800            &anb));
801    ASSERT_TRUE(anb != NULL);
802
803    sp<GraphicBuffer> buf(new GraphicBuffer(anb, false));
804
805    // Fill the buffer with the a checkerboard pattern
806    uint8_t* img = NULL;
807    buf->lock(GRALLOC_USAGE_SW_WRITE_OFTEN, (void**)(&img));
808    fillYV12Buffer(img, texWidth, texHeight, buf->getStride());
809    buf->unlock();
810    ASSERT_EQ(NO_ERROR, mANW->queueBuffer(mANW.get(), buf->getNativeBuffer(),
811            -1));
812
813    ASSERT_EQ(NO_ERROR, mST->updateTexImage());
814
815    glClearColor(0.2, 0.2, 0.2, 0.2);
816    glClear(GL_COLOR_BUFFER_BIT);
817
818    glViewport(0, 0, texWidth, texHeight);
819    drawTexture();
820
821    EXPECT_TRUE(checkPixel( 0,  0, 255, 127, 255, 255, 3));
822    EXPECT_TRUE(checkPixel(63,  0,   0, 133,   0, 255, 3));
823    EXPECT_TRUE(checkPixel(63, 65,   0, 133,   0, 255, 3));
824    EXPECT_TRUE(checkPixel( 0, 65, 255, 127, 255, 255, 3));
825
826    EXPECT_TRUE(checkPixel(22, 44, 255, 127, 255, 255, 3));
827    EXPECT_TRUE(checkPixel(45, 52, 255, 127, 255, 255, 3));
828    EXPECT_TRUE(checkPixel(52, 51,  98, 255,  73, 255, 3));
829    EXPECT_TRUE(checkPixel( 7, 31, 155,   0, 118, 255, 3));
830    EXPECT_TRUE(checkPixel(31,  9, 107,  24,  87, 255, 3));
831    EXPECT_TRUE(checkPixel(29, 35, 255, 127, 255, 255, 3));
832    EXPECT_TRUE(checkPixel(36, 22, 155,  29,   0, 255, 3));
833}
834
835TEST_F(SurfaceTextureGLTest, TexturingFromCpuFilledYV12BufferPow2) {
836    const int texWidth = 64;
837    const int texHeight = 64;
838
839    ASSERT_EQ(NO_ERROR, native_window_set_buffers_geometry(mANW.get(),
840            texWidth, texHeight, HAL_PIXEL_FORMAT_YV12));
841    ASSERT_EQ(NO_ERROR, native_window_set_usage(mANW.get(),
842            GRALLOC_USAGE_SW_READ_OFTEN | GRALLOC_USAGE_SW_WRITE_OFTEN));
843
844    ANativeWindowBuffer* anb;
845    ASSERT_EQ(NO_ERROR, native_window_dequeue_buffer_and_wait(mANW.get(),
846            &anb));
847    ASSERT_TRUE(anb != NULL);
848
849    sp<GraphicBuffer> buf(new GraphicBuffer(anb, false));
850
851    // Fill the buffer with the a checkerboard pattern
852    uint8_t* img = NULL;
853    buf->lock(GRALLOC_USAGE_SW_WRITE_OFTEN, (void**)(&img));
854    fillYV12Buffer(img, texWidth, texHeight, buf->getStride());
855    buf->unlock();
856    ASSERT_EQ(NO_ERROR, mANW->queueBuffer(mANW.get(), buf->getNativeBuffer(),
857            -1));
858
859    ASSERT_EQ(NO_ERROR, mST->updateTexImage());
860
861    glClearColor(0.2, 0.2, 0.2, 0.2);
862    glClear(GL_COLOR_BUFFER_BIT);
863
864    glViewport(0, 0, texWidth, texHeight);
865    drawTexture();
866
867    EXPECT_TRUE(checkPixel( 0,  0,   0, 133,   0, 255));
868    EXPECT_TRUE(checkPixel(63,  0, 255, 127, 255, 255));
869    EXPECT_TRUE(checkPixel(63, 63,   0, 133,   0, 255));
870    EXPECT_TRUE(checkPixel( 0, 63, 255, 127, 255, 255));
871
872    EXPECT_TRUE(checkPixel(22, 19, 100, 255,  74, 255));
873    EXPECT_TRUE(checkPixel(45, 11, 100, 255,  74, 255));
874    EXPECT_TRUE(checkPixel(52, 12, 155,   0, 181, 255));
875    EXPECT_TRUE(checkPixel( 7, 32, 150, 237, 170, 255));
876    EXPECT_TRUE(checkPixel(31, 54,   0,  71, 117, 255));
877    EXPECT_TRUE(checkPixel(29, 28,   0, 133,   0, 255));
878    EXPECT_TRUE(checkPixel(36, 41, 100, 232, 255, 255));
879}
880
881TEST_F(SurfaceTextureGLTest, TexturingFromCpuFilledYV12BufferWithCrop) {
882    const int texWidth = 64;
883    const int texHeight = 66;
884
885    ASSERT_EQ(NO_ERROR, native_window_set_buffers_geometry(mANW.get(),
886            texWidth, texHeight, HAL_PIXEL_FORMAT_YV12));
887    ASSERT_EQ(NO_ERROR, native_window_set_usage(mANW.get(),
888            GRALLOC_USAGE_SW_READ_OFTEN | GRALLOC_USAGE_SW_WRITE_OFTEN));
889
890    android_native_rect_t crops[] = {
891        {4, 6, 22, 36},
892        {0, 6, 22, 36},
893        {4, 0, 22, 36},
894        {4, 6, texWidth, 36},
895        {4, 6, 22, texHeight},
896    };
897
898    for (int i = 0; i < 5; i++) {
899        const android_native_rect_t& crop(crops[i]);
900        SCOPED_TRACE(String8::format("rect{ l: %d t: %d r: %d b: %d }",
901                crop.left, crop.top, crop.right, crop.bottom).string());
902
903        ASSERT_EQ(NO_ERROR, native_window_set_crop(mANW.get(), &crop));
904
905        ANativeWindowBuffer* anb;
906        ASSERT_EQ(NO_ERROR, native_window_dequeue_buffer_and_wait(mANW.get(),
907                &anb));
908        ASSERT_TRUE(anb != NULL);
909
910        sp<GraphicBuffer> buf(new GraphicBuffer(anb, false));
911
912        uint8_t* img = NULL;
913        buf->lock(GRALLOC_USAGE_SW_WRITE_OFTEN, (void**)(&img));
914        fillYV12BufferRect(img, texWidth, texHeight, buf->getStride(), crop);
915        buf->unlock();
916        ASSERT_EQ(NO_ERROR, mANW->queueBuffer(mANW.get(),
917                buf->getNativeBuffer(), -1));
918
919        ASSERT_EQ(NO_ERROR, mST->updateTexImage());
920
921        glClearColor(0.2, 0.2, 0.2, 0.2);
922        glClear(GL_COLOR_BUFFER_BIT);
923
924        glViewport(0, 0, 64, 64);
925        drawTexture();
926
927        EXPECT_TRUE(checkPixel( 0,  0,  82, 255,  35, 255));
928        EXPECT_TRUE(checkPixel(63,  0,  82, 255,  35, 255));
929        EXPECT_TRUE(checkPixel(63, 63,  82, 255,  35, 255));
930        EXPECT_TRUE(checkPixel( 0, 63,  82, 255,  35, 255));
931
932        EXPECT_TRUE(checkPixel(25, 14,  82, 255,  35, 255));
933        EXPECT_TRUE(checkPixel(35, 31,  82, 255,  35, 255));
934        EXPECT_TRUE(checkPixel(57,  6,  82, 255,  35, 255));
935        EXPECT_TRUE(checkPixel( 5, 42,  82, 255,  35, 255));
936        EXPECT_TRUE(checkPixel(32, 33,  82, 255,  35, 255));
937        EXPECT_TRUE(checkPixel(16, 26,  82, 255,  35, 255));
938        EXPECT_TRUE(checkPixel(46, 51,  82, 255,  35, 255));
939    }
940}
941
942// This test is intended to catch synchronization bugs between the CPU-written
943// and GPU-read buffers.
944TEST_F(SurfaceTextureGLTest, TexturingFromCpuFilledYV12BuffersRepeatedly) {
945    enum { texWidth = 16 };
946    enum { texHeight = 16 };
947    enum { numFrames = 1024 };
948
949    ASSERT_EQ(NO_ERROR, mST->setDefaultMaxBufferCount(2));
950    ASSERT_EQ(NO_ERROR, native_window_set_buffers_geometry(mANW.get(),
951            texWidth, texHeight, HAL_PIXEL_FORMAT_YV12));
952    ASSERT_EQ(NO_ERROR, native_window_set_usage(mANW.get(),
953            GRALLOC_USAGE_SW_WRITE_OFTEN));
954
955    struct TestPixel {
956        int x;
957        int y;
958    };
959    const TestPixel testPixels[] = {
960        {  4, 11 },
961        { 12, 14 },
962        {  7,  2 },
963    };
964    enum {numTestPixels = sizeof(testPixels) / sizeof(testPixels[0])};
965
966    class ProducerThread : public Thread {
967    public:
968        ProducerThread(const sp<ANativeWindow>& anw,
969                const TestPixel* testPixels):
970                mANW(anw),
971                mTestPixels(testPixels) {
972        }
973
974        virtual ~ProducerThread() {
975        }
976
977        virtual bool threadLoop() {
978            for (int i = 0; i < numFrames; i++) {
979                ANativeWindowBuffer* anb;
980                if (native_window_dequeue_buffer_and_wait(mANW.get(),
981                        &anb) != NO_ERROR) {
982                    return false;
983                }
984                if (anb == NULL) {
985                    return false;
986                }
987
988                sp<GraphicBuffer> buf(new GraphicBuffer(anb, false));
989
990                const int yuvTexOffsetY = 0;
991                int stride = buf->getStride();
992                int yuvTexStrideY = stride;
993                int yuvTexOffsetV = yuvTexStrideY * texHeight;
994                int yuvTexStrideV = (yuvTexStrideY/2 + 0xf) & ~0xf;
995                int yuvTexOffsetU = yuvTexOffsetV + yuvTexStrideV * texHeight/2;
996                int yuvTexStrideU = yuvTexStrideV;
997
998                uint8_t* img = NULL;
999                buf->lock(GRALLOC_USAGE_SW_WRITE_OFTEN, (void**)(&img));
1000
1001                // Gray out all the test pixels first, so we're more likely to
1002                // see a failure if GL is still texturing from the buffer we
1003                // just dequeued.
1004                for (int j = 0; j < numTestPixels; j++) {
1005                    int x = mTestPixels[j].x;
1006                    int y = mTestPixels[j].y;
1007                    uint8_t value = 128;
1008                    img[y*stride + x] = value;
1009                }
1010
1011                // Fill the buffer with gray.
1012                for (int y = 0; y < texHeight; y++) {
1013                    for (int x = 0; x < texWidth; x++) {
1014                        img[yuvTexOffsetY + y*yuvTexStrideY + x] = 128;
1015                        img[yuvTexOffsetU + (y/2)*yuvTexStrideU + x/2] = 128;
1016                        img[yuvTexOffsetV + (y/2)*yuvTexStrideV + x/2] = 128;
1017                    }
1018                }
1019
1020                // Set the test pixels to either white or black.
1021                for (int j = 0; j < numTestPixels; j++) {
1022                    int x = mTestPixels[j].x;
1023                    int y = mTestPixels[j].y;
1024                    uint8_t value = 0;
1025                    if (j == (i % numTestPixels)) {
1026                        value = 255;
1027                    }
1028                    img[y*stride + x] = value;
1029                }
1030
1031                buf->unlock();
1032                if (mANW->queueBuffer(mANW.get(), buf->getNativeBuffer(), -1)
1033                        != NO_ERROR) {
1034                    return false;
1035                }
1036            }
1037            return false;
1038        }
1039
1040        sp<ANativeWindow> mANW;
1041        const TestPixel* mTestPixels;
1042    };
1043
1044    sp<Thread> pt(new ProducerThread(mANW, testPixels));
1045    pt->run();
1046
1047    glViewport(0, 0, texWidth, texHeight);
1048
1049    glClearColor(0.2, 0.2, 0.2, 0.2);
1050    glClear(GL_COLOR_BUFFER_BIT);
1051
1052    // We wait for the first two frames up front so that the producer will be
1053    // likely to dequeue the buffer that's currently being textured from.
1054    mFW->waitForFrame();
1055    mFW->waitForFrame();
1056
1057    for (int i = 0; i < numFrames; i++) {
1058        SCOPED_TRACE(String8::format("frame %d", i).string());
1059
1060        // We must wait for each frame to come in because if we ever do an
1061        // updateTexImage call that doesn't consume a newly available buffer
1062        // then the producer and consumer will get out of sync, which will cause
1063        // a deadlock.
1064        if (i > 1) {
1065            mFW->waitForFrame();
1066        }
1067        ASSERT_EQ(NO_ERROR, mST->updateTexImage());
1068        drawTexture();
1069
1070        for (int j = 0; j < numTestPixels; j++) {
1071            int x = testPixels[j].x;
1072            int y = testPixels[j].y;
1073            uint8_t value = 0;
1074            if (j == (i % numTestPixels)) {
1075                // We must y-invert the texture coords
1076                EXPECT_TRUE(checkPixel(x, texHeight-y-1, 255, 255, 255, 255));
1077            } else {
1078                // We must y-invert the texture coords
1079                EXPECT_TRUE(checkPixel(x, texHeight-y-1, 0, 0, 0, 255));
1080            }
1081        }
1082    }
1083
1084    pt->requestExitAndWait();
1085}
1086
1087TEST_F(SurfaceTextureGLTest, TexturingFromCpuFilledRGBABufferNpot) {
1088    const int texWidth = 64;
1089    const int texHeight = 66;
1090
1091    ASSERT_EQ(NO_ERROR, native_window_set_buffers_geometry(mANW.get(),
1092            texWidth, texHeight, HAL_PIXEL_FORMAT_RGBA_8888));
1093    ASSERT_EQ(NO_ERROR, native_window_set_usage(mANW.get(),
1094            GRALLOC_USAGE_SW_READ_OFTEN | GRALLOC_USAGE_SW_WRITE_OFTEN));
1095
1096    ASSERT_NO_FATAL_FAILURE(produceOneRGBA8Frame(mANW));
1097
1098    ASSERT_EQ(NO_ERROR, mST->updateTexImage());
1099
1100    glClearColor(0.2, 0.2, 0.2, 0.2);
1101    glClear(GL_COLOR_BUFFER_BIT);
1102
1103    glViewport(0, 0, texWidth, texHeight);
1104    drawTexture();
1105
1106    EXPECT_TRUE(checkPixel( 0,  0,  35,  35,  35,  35));
1107    EXPECT_TRUE(checkPixel(63,  0, 231, 231, 231, 231));
1108    EXPECT_TRUE(checkPixel(63, 65, 231, 231, 231, 231));
1109    EXPECT_TRUE(checkPixel( 0, 65,  35,  35,  35,  35));
1110
1111    EXPECT_TRUE(checkPixel(15, 10,  35, 231, 231, 231));
1112    EXPECT_TRUE(checkPixel(23, 65, 231,  35, 231,  35));
1113    EXPECT_TRUE(checkPixel(19, 40,  35, 231,  35,  35));
1114    EXPECT_TRUE(checkPixel(38, 30, 231,  35,  35,  35));
1115    EXPECT_TRUE(checkPixel(42, 54,  35,  35,  35, 231));
1116    EXPECT_TRUE(checkPixel(37, 34,  35, 231, 231, 231));
1117    EXPECT_TRUE(checkPixel(31,  8, 231,  35,  35, 231));
1118    EXPECT_TRUE(checkPixel(37, 47, 231,  35, 231, 231));
1119    EXPECT_TRUE(checkPixel(25, 38,  35,  35,  35,  35));
1120    EXPECT_TRUE(checkPixel(49,  6,  35, 231,  35,  35));
1121    EXPECT_TRUE(checkPixel(54, 50,  35, 231, 231, 231));
1122    EXPECT_TRUE(checkPixel(27, 26, 231, 231, 231, 231));
1123    EXPECT_TRUE(checkPixel(10,  6,  35,  35, 231, 231));
1124    EXPECT_TRUE(checkPixel(29,  4,  35,  35,  35, 231));
1125    EXPECT_TRUE(checkPixel(55, 28,  35,  35, 231,  35));
1126    EXPECT_TRUE(checkPixel(58, 55,  35,  35, 231, 231));
1127}
1128
1129TEST_F(SurfaceTextureGLTest, TexturingFromCpuFilledRGBABufferPow2) {
1130    const int texWidth = 64;
1131    const int texHeight = 64;
1132
1133    ASSERT_EQ(NO_ERROR, native_window_set_buffers_geometry(mANW.get(),
1134            texWidth, texHeight, HAL_PIXEL_FORMAT_RGBA_8888));
1135    ASSERT_EQ(NO_ERROR, native_window_set_usage(mANW.get(),
1136            GRALLOC_USAGE_SW_READ_OFTEN | GRALLOC_USAGE_SW_WRITE_OFTEN));
1137
1138    ASSERT_NO_FATAL_FAILURE(produceOneRGBA8Frame(mANW));
1139
1140    ASSERT_EQ(NO_ERROR, mST->updateTexImage());
1141
1142    glClearColor(0.2, 0.2, 0.2, 0.2);
1143    glClear(GL_COLOR_BUFFER_BIT);
1144
1145    glViewport(0, 0, texWidth, texHeight);
1146    drawTexture();
1147
1148    EXPECT_TRUE(checkPixel( 0,  0, 231, 231, 231, 231));
1149    EXPECT_TRUE(checkPixel(63,  0,  35,  35,  35,  35));
1150    EXPECT_TRUE(checkPixel(63, 63, 231, 231, 231, 231));
1151    EXPECT_TRUE(checkPixel( 0, 63,  35,  35,  35,  35));
1152
1153    EXPECT_TRUE(checkPixel(12, 46, 231, 231, 231,  35));
1154    EXPECT_TRUE(checkPixel(16,  1, 231, 231,  35, 231));
1155    EXPECT_TRUE(checkPixel(21, 12, 231,  35,  35, 231));
1156    EXPECT_TRUE(checkPixel(26, 51, 231,  35, 231,  35));
1157    EXPECT_TRUE(checkPixel( 5, 32,  35, 231, 231,  35));
1158    EXPECT_TRUE(checkPixel(13,  8,  35, 231, 231, 231));
1159    EXPECT_TRUE(checkPixel(46,  3,  35,  35, 231,  35));
1160    EXPECT_TRUE(checkPixel(30, 33,  35,  35,  35,  35));
1161    EXPECT_TRUE(checkPixel( 6, 52, 231, 231,  35,  35));
1162    EXPECT_TRUE(checkPixel(55, 33,  35, 231,  35, 231));
1163    EXPECT_TRUE(checkPixel(16, 29,  35,  35, 231, 231));
1164    EXPECT_TRUE(checkPixel( 1, 30,  35,  35,  35, 231));
1165    EXPECT_TRUE(checkPixel(41, 37,  35,  35, 231, 231));
1166    EXPECT_TRUE(checkPixel(46, 29, 231, 231,  35,  35));
1167    EXPECT_TRUE(checkPixel(15, 25,  35, 231,  35, 231));
1168    EXPECT_TRUE(checkPixel( 3, 52,  35, 231,  35,  35));
1169}
1170
1171// Tests if GLConsumer and BufferQueue are robust enough
1172// to handle a special case where updateTexImage is called
1173// in the middle of disconnect.  This ordering is enforced
1174// by blocking in the disconnect callback.
1175TEST_F(SurfaceTextureGLTest, DisconnectStressTest) {
1176
1177    class ProducerThread : public Thread {
1178    public:
1179        ProducerThread(const sp<ANativeWindow>& anw):
1180                mANW(anw) {
1181        }
1182
1183        virtual ~ProducerThread() {
1184        }
1185
1186        virtual bool threadLoop() {
1187            ANativeWindowBuffer* anb;
1188
1189            native_window_api_connect(mANW.get(), NATIVE_WINDOW_API_EGL);
1190
1191            for (int numFrames =0 ; numFrames < 2; numFrames ++) {
1192
1193                if (native_window_dequeue_buffer_and_wait(mANW.get(),
1194                        &anb) != NO_ERROR) {
1195                    return false;
1196                }
1197                if (anb == NULL) {
1198                    return false;
1199                }
1200                if (mANW->queueBuffer(mANW.get(), anb, -1)
1201                        != NO_ERROR) {
1202                    return false;
1203                }
1204            }
1205
1206            native_window_api_disconnect(mANW.get(), NATIVE_WINDOW_API_EGL);
1207
1208            return false;
1209        }
1210
1211    private:
1212        sp<ANativeWindow> mANW;
1213    };
1214
1215    sp<DisconnectWaiter> dw(new DisconnectWaiter());
1216    mBQ->consumerConnect(dw, false);
1217
1218
1219    sp<Thread> pt(new ProducerThread(mANW));
1220    pt->run();
1221
1222    // eat a frame so GLConsumer will own an at least one slot
1223    dw->waitForFrame();
1224    EXPECT_EQ(OK,mST->updateTexImage());
1225
1226    dw->waitForFrame();
1227    // Could fail here as GLConsumer thinks it still owns the slot
1228    // but bufferQueue has released all slots
1229    EXPECT_EQ(OK,mST->updateTexImage());
1230
1231    dw->finishDisconnect();
1232}
1233
1234
1235// This test ensures that the GLConsumer clears the mCurrentTexture
1236// when it is disconnected and reconnected.  Otherwise it will
1237// attempt to release a buffer that it does not owned
1238TEST_F(SurfaceTextureGLTest, DisconnectClearsCurrentTexture) {
1239    ASSERT_EQ(OK, native_window_api_connect(mANW.get(),
1240            NATIVE_WINDOW_API_EGL));
1241
1242    ANativeWindowBuffer *anb;
1243
1244    EXPECT_EQ (OK, native_window_dequeue_buffer_and_wait(mANW.get(), &anb));
1245    EXPECT_EQ(OK, mANW->queueBuffer(mANW.get(), anb, -1));
1246
1247    EXPECT_EQ (OK, native_window_dequeue_buffer_and_wait(mANW.get(), &anb));
1248    EXPECT_EQ(OK, mANW->queueBuffer(mANW.get(), anb, -1));
1249
1250    EXPECT_EQ(OK,mST->updateTexImage());
1251    EXPECT_EQ(OK,mST->updateTexImage());
1252
1253    ASSERT_EQ(OK, native_window_api_disconnect(mANW.get(),
1254            NATIVE_WINDOW_API_EGL));
1255    ASSERT_EQ(OK, native_window_api_connect(mANW.get(),
1256            NATIVE_WINDOW_API_EGL));
1257
1258    EXPECT_EQ(OK, native_window_dequeue_buffer_and_wait(mANW.get(), &anb));
1259    EXPECT_EQ(OK, mANW->queueBuffer(mANW.get(), anb, -1));
1260
1261    // Will fail here if mCurrentTexture is not cleared properly
1262    mFW->waitForFrame();
1263    EXPECT_EQ(OK,mST->updateTexImage());
1264
1265    ASSERT_EQ(OK, native_window_api_disconnect(mANW.get(),
1266            NATIVE_WINDOW_API_EGL));
1267}
1268
1269TEST_F(SurfaceTextureGLTest, ScaleToWindowMode) {
1270    ASSERT_EQ(OK, native_window_set_scaling_mode(mANW.get(),
1271        NATIVE_WINDOW_SCALING_MODE_SCALE_TO_WINDOW));
1272
1273    // The producer image size
1274    ASSERT_EQ(OK, native_window_set_buffers_dimensions(mANW.get(), 512, 512));
1275
1276    // The consumer image size (16 x 9) ratio
1277    mST->setDefaultBufferSize(1280, 720);
1278
1279    ASSERT_EQ(OK, native_window_api_connect(mANW.get(),
1280            NATIVE_WINDOW_API_CPU));
1281
1282    ANativeWindowBuffer *anb;
1283
1284    android_native_rect_t odd = {23, 78, 123, 477};
1285    ASSERT_EQ(OK, native_window_set_crop(mANW.get(), &odd));
1286    EXPECT_EQ (OK, native_window_dequeue_buffer_and_wait(mANW.get(), &anb));
1287    EXPECT_EQ(OK, mANW->queueBuffer(mANW.get(), anb, -1));
1288    mFW->waitForFrame();
1289    EXPECT_EQ(OK, mST->updateTexImage());
1290    Rect r = mST->getCurrentCrop();
1291    assertRectEq(Rect(23, 78, 123, 477), r);
1292
1293    ASSERT_EQ(OK, native_window_api_disconnect(mANW.get(),
1294            NATIVE_WINDOW_API_CPU));
1295}
1296
1297// This test ensures the scaling mode does the right thing
1298// ie NATIVE_WINDOW_SCALING_MODE_CROP should crop
1299// the image such that it has the same aspect ratio as the
1300// default buffer size
1301TEST_F(SurfaceTextureGLTest, CroppedScalingMode) {
1302    ASSERT_EQ(OK, native_window_set_scaling_mode(mANW.get(),
1303        NATIVE_WINDOW_SCALING_MODE_SCALE_CROP));
1304
1305    // The producer image size
1306    ASSERT_EQ(OK, native_window_set_buffers_dimensions(mANW.get(), 512, 512));
1307
1308    // The consumer image size (16 x 9) ratio
1309    mST->setDefaultBufferSize(1280, 720);
1310
1311    native_window_api_connect(mANW.get(), NATIVE_WINDOW_API_CPU);
1312
1313    ANativeWindowBuffer *anb;
1314
1315    // The crop is in the shape of (320, 180) === 16 x 9
1316    android_native_rect_t standard = {10, 20, 330, 200};
1317    ASSERT_EQ(OK, native_window_set_crop(mANW.get(), &standard));
1318    EXPECT_EQ (OK, native_window_dequeue_buffer_and_wait(mANW.get(), &anb));
1319    EXPECT_EQ(OK, mANW->queueBuffer(mANW.get(), anb, -1));
1320    mFW->waitForFrame();
1321    EXPECT_EQ(OK, mST->updateTexImage());
1322    Rect r = mST->getCurrentCrop();
1323    // crop should be the same as crop (same aspect ratio)
1324    assertRectEq(Rect(10, 20, 330, 200), r);
1325
1326    // make this wider then desired aspect 239 x 100 (2.39:1)
1327    android_native_rect_t wide = {20, 30, 259, 130};
1328    ASSERT_EQ(OK, native_window_set_crop(mANW.get(), &wide));
1329    EXPECT_EQ (OK, native_window_dequeue_buffer_and_wait(mANW.get(), &anb));
1330    EXPECT_EQ(OK, mANW->queueBuffer(mANW.get(), anb, -1));
1331    mFW->waitForFrame();
1332    EXPECT_EQ(OK, mST->updateTexImage());
1333    r = mST->getCurrentCrop();
1334    // crop should be the same height, but have cropped left and right borders
1335    // offset is 30.6 px L+, R-
1336    assertRectEq(Rect(51, 30, 228, 130), r);
1337
1338    // This image is taller then desired aspect 400 x 300 (4:3)
1339    android_native_rect_t narrow = {0, 0, 400, 300};
1340    ASSERT_EQ(OK, native_window_set_crop(mANW.get(), &narrow));
1341    EXPECT_EQ (OK, native_window_dequeue_buffer_and_wait(mANW.get(), &anb));
1342    EXPECT_EQ(OK, mANW->queueBuffer(mANW.get(), anb, -1));
1343    mFW->waitForFrame();
1344    EXPECT_EQ(OK, mST->updateTexImage());
1345    r = mST->getCurrentCrop();
1346    // crop should be the same width, but have cropped top and bottom borders
1347    // offset is 37.5 px
1348    assertRectEq(Rect(0, 37, 400, 262), r);
1349
1350    native_window_api_disconnect(mANW.get(), NATIVE_WINDOW_API_CPU);
1351}
1352
1353TEST_F(SurfaceTextureGLTest, AbandonUnblocksDequeueBuffer) {
1354    class ProducerThread : public Thread {
1355    public:
1356        ProducerThread(const sp<ANativeWindow>& anw):
1357                mANW(anw),
1358                mDequeueError(NO_ERROR) {
1359        }
1360
1361        virtual ~ProducerThread() {
1362        }
1363
1364        virtual bool threadLoop() {
1365            Mutex::Autolock lock(mMutex);
1366            ANativeWindowBuffer* anb;
1367
1368            // Frame 1
1369            if (native_window_dequeue_buffer_and_wait(mANW.get(),
1370                    &anb) != NO_ERROR) {
1371                return false;
1372            }
1373            if (anb == NULL) {
1374                return false;
1375            }
1376            if (mANW->queueBuffer(mANW.get(), anb, -1)
1377                    != NO_ERROR) {
1378                return false;
1379            }
1380
1381            // Frame 2
1382            if (native_window_dequeue_buffer_and_wait(mANW.get(),
1383                    &anb) != NO_ERROR) {
1384                return false;
1385            }
1386            if (anb == NULL) {
1387                return false;
1388            }
1389            if (mANW->queueBuffer(mANW.get(), anb, -1)
1390                    != NO_ERROR) {
1391                return false;
1392            }
1393
1394            // Frame 3 - error expected
1395            mDequeueError = native_window_dequeue_buffer_and_wait(mANW.get(),
1396                &anb);
1397            return false;
1398        }
1399
1400        status_t getDequeueError() {
1401            Mutex::Autolock lock(mMutex);
1402            return mDequeueError;
1403        }
1404
1405    private:
1406        sp<ANativeWindow> mANW;
1407        status_t mDequeueError;
1408        Mutex mMutex;
1409    };
1410
1411    ASSERT_EQ(OK, mST->setDefaultMaxBufferCount(2));
1412
1413    sp<Thread> pt(new ProducerThread(mANW));
1414    pt->run();
1415
1416    mFW->waitForFrame();
1417    mFW->waitForFrame();
1418
1419    // Sleep for 100ms to allow the producer thread's dequeueBuffer call to
1420    // block waiting for a buffer to become available.
1421    usleep(100000);
1422
1423    mST->abandon();
1424
1425    pt->requestExitAndWait();
1426    ASSERT_EQ(NO_INIT,
1427            reinterpret_cast<ProducerThread*>(pt.get())->getDequeueError());
1428}
1429
1430TEST_F(SurfaceTextureGLTest, InvalidWidthOrHeightFails) {
1431    int texHeight = 16;
1432    ANativeWindowBuffer* anb;
1433
1434    GLint maxTextureSize;
1435    glGetIntegerv(GL_MAX_TEXTURE_SIZE, &maxTextureSize);
1436
1437    // make sure it works with small textures
1438    mST->setDefaultBufferSize(16, texHeight);
1439    EXPECT_EQ(NO_ERROR, native_window_dequeue_buffer_and_wait(mANW.get(),
1440            &anb));
1441    EXPECT_EQ(16, anb->width);
1442    EXPECT_EQ(texHeight, anb->height);
1443    EXPECT_EQ(NO_ERROR, mANW->queueBuffer(mANW.get(), anb, -1));
1444    EXPECT_EQ(NO_ERROR, mST->updateTexImage());
1445
1446    // make sure it works with GL_MAX_TEXTURE_SIZE
1447    mST->setDefaultBufferSize(maxTextureSize, texHeight);
1448    EXPECT_EQ(NO_ERROR, native_window_dequeue_buffer_and_wait(mANW.get(),
1449            &anb));
1450    EXPECT_EQ(maxTextureSize, anb->width);
1451    EXPECT_EQ(texHeight, anb->height);
1452    EXPECT_EQ(NO_ERROR, mANW->queueBuffer(mANW.get(), anb, -1));
1453    EXPECT_EQ(NO_ERROR, mST->updateTexImage());
1454
1455    // make sure it fails with GL_MAX_TEXTURE_SIZE+1
1456    mST->setDefaultBufferSize(maxTextureSize+1, texHeight);
1457    EXPECT_EQ(NO_ERROR, native_window_dequeue_buffer_and_wait(mANW.get(),
1458            &anb));
1459    EXPECT_EQ(maxTextureSize+1, anb->width);
1460    EXPECT_EQ(texHeight, anb->height);
1461    EXPECT_EQ(NO_ERROR, mANW->queueBuffer(mANW.get(), anb, -1));
1462    ASSERT_NE(NO_ERROR, mST->updateTexImage());
1463}
1464
1465/*
1466 * This test fixture is for testing GL -> GL texture streaming.  It creates an
1467 * EGLSurface and an EGLContext for the image producer to use.
1468 */
1469class SurfaceTextureGLToGLTest : public SurfaceTextureGLTest {
1470protected:
1471    SurfaceTextureGLToGLTest():
1472            mProducerEglSurface(EGL_NO_SURFACE),
1473            mProducerEglContext(EGL_NO_CONTEXT) {
1474    }
1475
1476    virtual void SetUp() {
1477        SurfaceTextureGLTest::SetUp();
1478
1479        mProducerEglSurface = eglCreateWindowSurface(mEglDisplay, mGlConfig,
1480                mANW.get(), NULL);
1481        ASSERT_EQ(EGL_SUCCESS, eglGetError());
1482        ASSERT_NE(EGL_NO_SURFACE, mProducerEglSurface);
1483
1484        mProducerEglContext = eglCreateContext(mEglDisplay, mGlConfig,
1485                EGL_NO_CONTEXT, getContextAttribs());
1486        ASSERT_EQ(EGL_SUCCESS, eglGetError());
1487        ASSERT_NE(EGL_NO_CONTEXT, mProducerEglContext);
1488    }
1489
1490    virtual void TearDown() {
1491        if (mProducerEglContext != EGL_NO_CONTEXT) {
1492            eglDestroyContext(mEglDisplay, mProducerEglContext);
1493        }
1494        if (mProducerEglSurface != EGL_NO_SURFACE) {
1495            eglDestroySurface(mEglDisplay, mProducerEglSurface);
1496        }
1497        SurfaceTextureGLTest::TearDown();
1498    }
1499
1500    EGLSurface mProducerEglSurface;
1501    EGLContext mProducerEglContext;
1502};
1503
1504TEST_F(SurfaceTextureGLToGLTest, TransformHintGetsRespected) {
1505    const uint32_t texWidth = 32;
1506    const uint32_t texHeight = 64;
1507
1508    mST->setDefaultBufferSize(texWidth, texHeight);
1509    mST->setTransformHint(NATIVE_WINDOW_TRANSFORM_ROT_90);
1510
1511    // This test requires 3 buffers to avoid deadlock because we're
1512    // both producer and consumer, and only using one thread.
1513    mST->setDefaultMaxBufferCount(3);
1514
1515    // Do the producer side of things
1516    EXPECT_TRUE(eglMakeCurrent(mEglDisplay, mProducerEglSurface,
1517            mProducerEglSurface, mProducerEglContext));
1518    ASSERT_EQ(EGL_SUCCESS, eglGetError());
1519
1520    // Start a buffer with our chosen size and transform hint moving
1521    // through the system.
1522    glClear(GL_COLOR_BUFFER_BIT);  // give the driver something to do
1523    eglSwapBuffers(mEglDisplay, mProducerEglSurface);
1524    mST->updateTexImage();  // consume it
1525    // Swap again.
1526    glClear(GL_COLOR_BUFFER_BIT);
1527    eglSwapBuffers(mEglDisplay, mProducerEglSurface);
1528    mST->updateTexImage();
1529
1530    // The current buffer should either show the effects of the transform
1531    // hint (in the form of an inverse transform), or show that the
1532    // transform hint has been ignored.
1533    sp<GraphicBuffer> buf = mST->getCurrentBuffer();
1534    if (mST->getCurrentTransform() == NATIVE_WINDOW_TRANSFORM_ROT_270) {
1535        ASSERT_EQ(texWidth, buf->getHeight());
1536        ASSERT_EQ(texHeight, buf->getWidth());
1537    } else {
1538        ASSERT_EQ(texWidth, buf->getWidth());
1539        ASSERT_EQ(texHeight, buf->getHeight());
1540    }
1541
1542    // Reset the transform hint and confirm that it takes.
1543    mST->setTransformHint(0);
1544    glClear(GL_COLOR_BUFFER_BIT);
1545    eglSwapBuffers(mEglDisplay, mProducerEglSurface);
1546    mST->updateTexImage();
1547    glClear(GL_COLOR_BUFFER_BIT);
1548    eglSwapBuffers(mEglDisplay, mProducerEglSurface);
1549    mST->updateTexImage();
1550
1551    buf = mST->getCurrentBuffer();
1552    ASSERT_EQ((uint32_t) 0, mST->getCurrentTransform());
1553    ASSERT_EQ(texWidth, buf->getWidth());
1554    ASSERT_EQ(texHeight, buf->getHeight());
1555}
1556
1557TEST_F(SurfaceTextureGLToGLTest, TexturingFromGLFilledRGBABufferPow2) {
1558    const int texWidth = 64;
1559    const int texHeight = 64;
1560
1561    mST->setDefaultBufferSize(texWidth, texHeight);
1562
1563    // This test requires 3 buffers to complete run on a single thread.
1564    mST->setDefaultMaxBufferCount(3);
1565
1566    // Do the producer side of things
1567    EXPECT_TRUE(eglMakeCurrent(mEglDisplay, mProducerEglSurface,
1568            mProducerEglSurface, mProducerEglContext));
1569    ASSERT_EQ(EGL_SUCCESS, eglGetError());
1570
1571    // This is needed to ensure we pick up a buffer of the correct size.
1572    eglSwapBuffers(mEglDisplay, mProducerEglSurface);
1573
1574    glClearColor(0.6, 0.6, 0.6, 0.6);
1575    glClear(GL_COLOR_BUFFER_BIT);
1576
1577    glEnable(GL_SCISSOR_TEST);
1578    glScissor(4, 4, 4, 4);
1579    glClearColor(1.0, 0.0, 0.0, 1.0);
1580    glClear(GL_COLOR_BUFFER_BIT);
1581
1582    glScissor(24, 48, 4, 4);
1583    glClearColor(0.0, 1.0, 0.0, 1.0);
1584    glClear(GL_COLOR_BUFFER_BIT);
1585
1586    glScissor(37, 17, 4, 4);
1587    glClearColor(0.0, 0.0, 1.0, 1.0);
1588    glClear(GL_COLOR_BUFFER_BIT);
1589
1590    eglSwapBuffers(mEglDisplay, mProducerEglSurface);
1591
1592    // Do the consumer side of things
1593    EXPECT_TRUE(eglMakeCurrent(mEglDisplay, mEglSurface, mEglSurface,
1594            mEglContext));
1595    ASSERT_EQ(EGL_SUCCESS, eglGetError());
1596
1597    glDisable(GL_SCISSOR_TEST);
1598
1599    // Skip the first frame, which was empty
1600    ASSERT_EQ(NO_ERROR, mST->updateTexImage());
1601    ASSERT_EQ(NO_ERROR, mST->updateTexImage());
1602
1603    glClearColor(0.2, 0.2, 0.2, 0.2);
1604    glClear(GL_COLOR_BUFFER_BIT);
1605
1606    glViewport(0, 0, texWidth, texHeight);
1607    drawTexture();
1608
1609    EXPECT_TRUE(checkPixel( 0,  0, 153, 153, 153, 153));
1610    EXPECT_TRUE(checkPixel(63,  0, 153, 153, 153, 153));
1611    EXPECT_TRUE(checkPixel(63, 63, 153, 153, 153, 153));
1612    EXPECT_TRUE(checkPixel( 0, 63, 153, 153, 153, 153));
1613
1614    EXPECT_TRUE(checkPixel( 4,  7, 255,   0,   0, 255));
1615    EXPECT_TRUE(checkPixel(25, 51,   0, 255,   0, 255));
1616    EXPECT_TRUE(checkPixel(40, 19,   0,   0, 255, 255));
1617    EXPECT_TRUE(checkPixel(29, 51, 153, 153, 153, 153));
1618    EXPECT_TRUE(checkPixel( 5, 32, 153, 153, 153, 153));
1619    EXPECT_TRUE(checkPixel(13,  8, 153, 153, 153, 153));
1620    EXPECT_TRUE(checkPixel(46,  3, 153, 153, 153, 153));
1621    EXPECT_TRUE(checkPixel(30, 33, 153, 153, 153, 153));
1622    EXPECT_TRUE(checkPixel( 6, 52, 153, 153, 153, 153));
1623    EXPECT_TRUE(checkPixel(55, 33, 153, 153, 153, 153));
1624    EXPECT_TRUE(checkPixel(16, 29, 153, 153, 153, 153));
1625    EXPECT_TRUE(checkPixel( 1, 30, 153, 153, 153, 153));
1626    EXPECT_TRUE(checkPixel(41, 37, 153, 153, 153, 153));
1627    EXPECT_TRUE(checkPixel(46, 29, 153, 153, 153, 153));
1628    EXPECT_TRUE(checkPixel(15, 25, 153, 153, 153, 153));
1629    EXPECT_TRUE(checkPixel( 3, 52, 153, 153, 153, 153));
1630}
1631
1632TEST_F(SurfaceTextureGLToGLTest, EglDestroySurfaceUnrefsBuffers) {
1633    sp<GraphicBuffer> buffers[2];
1634
1635    // This test requires async mode to run on a single thread.
1636    EXPECT_TRUE(eglMakeCurrent(mEglDisplay, mProducerEglSurface,
1637            mProducerEglSurface, mProducerEglContext));
1638    ASSERT_EQ(EGL_SUCCESS, eglGetError());
1639    EXPECT_TRUE(eglSwapInterval(mEglDisplay, 0));
1640    ASSERT_EQ(EGL_SUCCESS, eglGetError());
1641
1642    for (int i = 0; i < 2; i++) {
1643        // Produce a frame
1644        EXPECT_TRUE(eglMakeCurrent(mEglDisplay, mProducerEglSurface,
1645                mProducerEglSurface, mProducerEglContext));
1646        ASSERT_EQ(EGL_SUCCESS, eglGetError());
1647        glClear(GL_COLOR_BUFFER_BIT);
1648        eglSwapBuffers(mEglDisplay, mProducerEglSurface);
1649
1650        // Consume a frame
1651        EXPECT_TRUE(eglMakeCurrent(mEglDisplay, mEglSurface, mEglSurface,
1652                mEglContext));
1653        ASSERT_EQ(EGL_SUCCESS, eglGetError());
1654        mFW->waitForFrame();
1655        ASSERT_EQ(NO_ERROR, mST->updateTexImage());
1656        buffers[i] = mST->getCurrentBuffer();
1657    }
1658
1659    // Destroy the GL texture object to release its ref on buffers[2].
1660    GLuint texID = TEX_ID;
1661    glDeleteTextures(1, &texID);
1662
1663    // Destroy the EGLSurface
1664    EXPECT_TRUE(eglDestroySurface(mEglDisplay, mProducerEglSurface));
1665    ASSERT_EQ(EGL_SUCCESS, eglGetError());
1666    mProducerEglSurface = EGL_NO_SURFACE;
1667
1668    // This test should have the only reference to buffer 0.
1669    EXPECT_EQ(1, buffers[0]->getStrongCount());
1670
1671    // The GLConsumer should hold a single reference to buffer 1 in its
1672    // mCurrentBuffer member.  All of the references in the slots should have
1673    // been released.
1674    EXPECT_EQ(2, buffers[1]->getStrongCount());
1675}
1676
1677TEST_F(SurfaceTextureGLToGLTest, EglDestroySurfaceAfterAbandonUnrefsBuffers) {
1678    sp<GraphicBuffer> buffers[3];
1679
1680    // This test requires async mode to run on a single thread.
1681    EXPECT_TRUE(eglMakeCurrent(mEglDisplay, mProducerEglSurface,
1682            mProducerEglSurface, mProducerEglContext));
1683    ASSERT_EQ(EGL_SUCCESS, eglGetError());
1684    EXPECT_TRUE(eglSwapInterval(mEglDisplay, 0));
1685    ASSERT_EQ(EGL_SUCCESS, eglGetError());
1686
1687    for (int i = 0; i < 3; i++) {
1688        // Produce a frame
1689        EXPECT_TRUE(eglMakeCurrent(mEglDisplay, mProducerEglSurface,
1690                mProducerEglSurface, mProducerEglContext));
1691        ASSERT_EQ(EGL_SUCCESS, eglGetError());
1692        glClear(GL_COLOR_BUFFER_BIT);
1693        EXPECT_TRUE(eglSwapBuffers(mEglDisplay, mProducerEglSurface));
1694        ASSERT_EQ(EGL_SUCCESS, eglGetError());
1695
1696        // Consume a frame
1697        EXPECT_TRUE(eglMakeCurrent(mEglDisplay, mEglSurface, mEglSurface,
1698                mEglContext));
1699        ASSERT_EQ(EGL_SUCCESS, eglGetError());
1700        mFW->waitForFrame();
1701        ASSERT_EQ(NO_ERROR, mST->updateTexImage());
1702        buffers[i] = mST->getCurrentBuffer();
1703    }
1704
1705    // Abandon the GLConsumer, releasing the ref that the GLConsumer has
1706    // on buffers[2].
1707    mST->abandon();
1708
1709    // Destroy the GL texture object to release its ref on buffers[2].
1710    GLuint texID = TEX_ID;
1711    glDeleteTextures(1, &texID);
1712
1713    // Destroy the EGLSurface.
1714    EXPECT_TRUE(eglDestroySurface(mEglDisplay, mProducerEglSurface));
1715    ASSERT_EQ(EGL_SUCCESS, eglGetError());
1716    mProducerEglSurface = EGL_NO_SURFACE;
1717
1718    EXPECT_EQ(1, buffers[0]->getStrongCount());
1719    EXPECT_EQ(1, buffers[1]->getStrongCount());
1720
1721    // Depending on how lazily the GL driver dequeues buffers, we may end up
1722    // with either two or three total buffers.  If there are three, make sure
1723    // the last one was properly down-ref'd.
1724    if (buffers[2] != buffers[0]) {
1725        EXPECT_EQ(1, buffers[2]->getStrongCount());
1726    }
1727}
1728
1729TEST_F(SurfaceTextureGLToGLTest, EglMakeCurrentBeforeConsumerDeathUnrefsBuffers) {
1730    sp<GraphicBuffer> buffer;
1731
1732    EXPECT_TRUE(eglMakeCurrent(mEglDisplay, mProducerEglSurface,
1733            mProducerEglSurface, mProducerEglContext));
1734
1735    // Produce a frame
1736    glClear(GL_COLOR_BUFFER_BIT);
1737    EXPECT_TRUE(eglSwapBuffers(mEglDisplay, mProducerEglSurface));
1738    ASSERT_EQ(EGL_SUCCESS, eglGetError());
1739
1740    // Destroy the EGLSurface.
1741    EXPECT_TRUE(eglDestroySurface(mEglDisplay, mProducerEglSurface));
1742    ASSERT_EQ(EGL_SUCCESS, eglGetError());
1743    mProducerEglSurface = EGL_NO_SURFACE;
1744    mSTC.clear();
1745    mANW.clear();
1746    mTextureRenderer.clear();
1747
1748    // Consume a frame
1749    ASSERT_EQ(NO_ERROR, mST->updateTexImage());
1750    buffer = mST->getCurrentBuffer();
1751
1752    // Destroy the GL texture object to release its ref
1753    GLuint texID = TEX_ID;
1754    glDeleteTextures(1, &texID);
1755
1756    // make un-current, all references to buffer should be gone
1757    EXPECT_TRUE(eglMakeCurrent(mEglDisplay, EGL_NO_SURFACE,
1758            EGL_NO_SURFACE, EGL_NO_CONTEXT));
1759
1760    // Destroy consumer
1761    mST.clear();
1762
1763    EXPECT_EQ(1, buffer->getStrongCount());
1764}
1765
1766TEST_F(SurfaceTextureGLToGLTest, EglMakeCurrentAfterConsumerDeathUnrefsBuffers) {
1767    sp<GraphicBuffer> buffer;
1768
1769    EXPECT_TRUE(eglMakeCurrent(mEglDisplay, mProducerEglSurface,
1770            mProducerEglSurface, mProducerEglContext));
1771
1772    // Produce a frame
1773    glClear(GL_COLOR_BUFFER_BIT);
1774    EXPECT_TRUE(eglSwapBuffers(mEglDisplay, mProducerEglSurface));
1775    ASSERT_EQ(EGL_SUCCESS, eglGetError());
1776
1777    // Destroy the EGLSurface.
1778    EXPECT_TRUE(eglDestroySurface(mEglDisplay, mProducerEglSurface));
1779    ASSERT_EQ(EGL_SUCCESS, eglGetError());
1780    mProducerEglSurface = EGL_NO_SURFACE;
1781    mSTC.clear();
1782    mANW.clear();
1783    mTextureRenderer.clear();
1784
1785    // Consume a frame
1786    ASSERT_EQ(NO_ERROR, mST->updateTexImage());
1787    buffer = mST->getCurrentBuffer();
1788
1789    // Destroy the GL texture object to release its ref
1790    GLuint texID = TEX_ID;
1791    glDeleteTextures(1, &texID);
1792
1793    // Destroy consumer
1794    mST.clear();
1795
1796    // make un-current, all references to buffer should be gone
1797    EXPECT_TRUE(eglMakeCurrent(mEglDisplay, EGL_NO_SURFACE,
1798            EGL_NO_SURFACE, EGL_NO_CONTEXT));
1799
1800    EXPECT_EQ(1, buffer->getStrongCount());
1801}
1802
1803TEST_F(SurfaceTextureGLToGLTest, TexturingFromUserSizedGLFilledBuffer) {
1804    enum { texWidth = 64 };
1805    enum { texHeight = 64 };
1806
1807    // This test requires 3 buffers to complete run on a single thread.
1808    mST->setDefaultMaxBufferCount(3);
1809
1810    // Set the user buffer size.
1811    native_window_set_buffers_user_dimensions(mANW.get(), texWidth, texHeight);
1812
1813    // Do the producer side of things
1814    EXPECT_TRUE(eglMakeCurrent(mEglDisplay, mProducerEglSurface,
1815            mProducerEglSurface, mProducerEglContext));
1816    ASSERT_EQ(EGL_SUCCESS, eglGetError());
1817
1818    // This is needed to ensure we pick up a buffer of the correct size.
1819    eglSwapBuffers(mEglDisplay, mProducerEglSurface);
1820
1821    glClearColor(0.6, 0.6, 0.6, 0.6);
1822    glClear(GL_COLOR_BUFFER_BIT);
1823
1824    glEnable(GL_SCISSOR_TEST);
1825    glScissor(4, 4, 1, 1);
1826    glClearColor(1.0, 0.0, 0.0, 1.0);
1827    glClear(GL_COLOR_BUFFER_BIT);
1828
1829    eglSwapBuffers(mEglDisplay, mProducerEglSurface);
1830
1831    // Do the consumer side of things
1832    EXPECT_TRUE(eglMakeCurrent(mEglDisplay, mEglSurface, mEglSurface,
1833            mEglContext));
1834    ASSERT_EQ(EGL_SUCCESS, eglGetError());
1835
1836    glDisable(GL_SCISSOR_TEST);
1837
1838    // Skip the first frame, which was empty
1839    ASSERT_EQ(NO_ERROR, mST->updateTexImage());
1840    ASSERT_EQ(NO_ERROR, mST->updateTexImage());
1841
1842    glClearColor(0.2, 0.2, 0.2, 0.2);
1843    glClear(GL_COLOR_BUFFER_BIT);
1844
1845    glViewport(0, 0, texWidth, texHeight);
1846    drawTexture();
1847
1848    EXPECT_TRUE(checkPixel( 0,  0, 153, 153, 153, 153));
1849    EXPECT_TRUE(checkPixel(63,  0, 153, 153, 153, 153));
1850    EXPECT_TRUE(checkPixel(63, 63, 153, 153, 153, 153));
1851    EXPECT_TRUE(checkPixel( 0, 63, 153, 153, 153, 153));
1852
1853    EXPECT_TRUE(checkPixel( 4,  4, 255,   0,   0, 255));
1854    EXPECT_TRUE(checkPixel( 5,  5, 153, 153, 153, 153));
1855    EXPECT_TRUE(checkPixel( 3,  3, 153, 153, 153, 153));
1856    EXPECT_TRUE(checkPixel(45, 52, 153, 153, 153, 153));
1857    EXPECT_TRUE(checkPixel(12, 36, 153, 153, 153, 153));
1858}
1859
1860TEST_F(SurfaceTextureGLToGLTest, TexturingFromPreRotatedUserSizedGLFilledBuffer) {
1861    enum { texWidth = 64 };
1862    enum { texHeight = 16 };
1863
1864    // This test requires 3 buffers to complete run on a single thread.
1865    mST->setDefaultMaxBufferCount(3);
1866
1867    // Set the transform hint.
1868    mST->setTransformHint(NATIVE_WINDOW_TRANSFORM_ROT_90);
1869
1870    // Set the user buffer size.
1871    native_window_set_buffers_user_dimensions(mANW.get(), texWidth, texHeight);
1872
1873    // Do the producer side of things
1874    EXPECT_TRUE(eglMakeCurrent(mEglDisplay, mProducerEglSurface,
1875            mProducerEglSurface, mProducerEglContext));
1876    ASSERT_EQ(EGL_SUCCESS, eglGetError());
1877
1878    // This is needed to ensure we pick up a buffer of the correct size and the
1879    // new rotation hint.
1880    eglSwapBuffers(mEglDisplay, mProducerEglSurface);
1881
1882    glClearColor(0.6, 0.6, 0.6, 0.6);
1883    glClear(GL_COLOR_BUFFER_BIT);
1884
1885    glEnable(GL_SCISSOR_TEST);
1886    glScissor(24, 4, 1, 1);
1887    glClearColor(1.0, 0.0, 0.0, 1.0);
1888    glClear(GL_COLOR_BUFFER_BIT);
1889
1890    eglSwapBuffers(mEglDisplay, mProducerEglSurface);
1891
1892    // Do the consumer side of things
1893    EXPECT_TRUE(eglMakeCurrent(mEglDisplay, mEglSurface, mEglSurface,
1894            mEglContext));
1895    ASSERT_EQ(EGL_SUCCESS, eglGetError());
1896
1897    glDisable(GL_SCISSOR_TEST);
1898
1899    // Skip the first frame, which was empty
1900    ASSERT_EQ(NO_ERROR, mST->updateTexImage());
1901    ASSERT_EQ(NO_ERROR, mST->updateTexImage());
1902
1903    glClearColor(0.2, 0.2, 0.2, 0.2);
1904    glClear(GL_COLOR_BUFFER_BIT);
1905
1906    glViewport(0, 0, texWidth, texHeight);
1907    drawTexture();
1908
1909    EXPECT_TRUE(checkPixel( 0,  0, 153, 153, 153, 153));
1910    EXPECT_TRUE(checkPixel(63,  0, 153, 153, 153, 153));
1911    EXPECT_TRUE(checkPixel(63, 15, 153, 153, 153, 153));
1912    EXPECT_TRUE(checkPixel( 0, 15, 153, 153, 153, 153));
1913
1914    EXPECT_TRUE(checkPixel(24,  4, 255,   0,   0, 255));
1915    EXPECT_TRUE(checkPixel(25,  5, 153, 153, 153, 153));
1916    EXPECT_TRUE(checkPixel(23,  3, 153, 153, 153, 153));
1917    EXPECT_TRUE(checkPixel(45, 13, 153, 153, 153, 153));
1918    EXPECT_TRUE(checkPixel(12,  8, 153, 153, 153, 153));
1919}
1920
1921TEST_F(SurfaceTextureGLToGLTest, TexturingFromPreRotatedGLFilledBuffer) {
1922    enum { texWidth = 64 };
1923    enum { texHeight = 16 };
1924
1925    // This test requires 3 buffers to complete run on a single thread.
1926    mST->setDefaultMaxBufferCount(3);
1927
1928    // Set the transform hint.
1929    mST->setTransformHint(NATIVE_WINDOW_TRANSFORM_ROT_90);
1930
1931    // Set the default buffer size.
1932    mST->setDefaultBufferSize(texWidth, texHeight);
1933
1934    // Do the producer side of things
1935    EXPECT_TRUE(eglMakeCurrent(mEglDisplay, mProducerEglSurface,
1936            mProducerEglSurface, mProducerEglContext));
1937    ASSERT_EQ(EGL_SUCCESS, eglGetError());
1938
1939    // This is needed to ensure we pick up a buffer of the correct size and the
1940    // new rotation hint.
1941    eglSwapBuffers(mEglDisplay, mProducerEglSurface);
1942
1943    glClearColor(0.6, 0.6, 0.6, 0.6);
1944    glClear(GL_COLOR_BUFFER_BIT);
1945
1946    glEnable(GL_SCISSOR_TEST);
1947    glScissor(24, 4, 1, 1);
1948    glClearColor(1.0, 0.0, 0.0, 1.0);
1949    glClear(GL_COLOR_BUFFER_BIT);
1950
1951    eglSwapBuffers(mEglDisplay, mProducerEglSurface);
1952
1953    // Do the consumer side of things
1954    EXPECT_TRUE(eglMakeCurrent(mEglDisplay, mEglSurface, mEglSurface,
1955            mEglContext));
1956    ASSERT_EQ(EGL_SUCCESS, eglGetError());
1957
1958    glDisable(GL_SCISSOR_TEST);
1959
1960    // Skip the first frame, which was empty
1961    ASSERT_EQ(NO_ERROR, mST->updateTexImage());
1962    ASSERT_EQ(NO_ERROR, mST->updateTexImage());
1963
1964    glClearColor(0.2, 0.2, 0.2, 0.2);
1965    glClear(GL_COLOR_BUFFER_BIT);
1966
1967    glViewport(0, 0, texWidth, texHeight);
1968    drawTexture();
1969
1970    EXPECT_TRUE(checkPixel( 0,  0, 153, 153, 153, 153));
1971    EXPECT_TRUE(checkPixel(63,  0, 153, 153, 153, 153));
1972    EXPECT_TRUE(checkPixel(63, 15, 153, 153, 153, 153));
1973    EXPECT_TRUE(checkPixel( 0, 15, 153, 153, 153, 153));
1974
1975    EXPECT_TRUE(checkPixel(24,  4, 255,   0,   0, 255));
1976    EXPECT_TRUE(checkPixel(25,  5, 153, 153, 153, 153));
1977    EXPECT_TRUE(checkPixel(23,  3, 153, 153, 153, 153));
1978    EXPECT_TRUE(checkPixel(45, 13, 153, 153, 153, 153));
1979    EXPECT_TRUE(checkPixel(12,  8, 153, 153, 153, 153));
1980}
1981
1982/*
1983 * This test fixture is for testing GL -> GL texture streaming from one thread
1984 * to another.  It contains functionality to create a producer thread that will
1985 * perform GL rendering to an ANativeWindow that feeds frames to a
1986 * GLConsumer.  Additionally it supports interlocking the producer and
1987 * consumer threads so that a specific sequence of calls can be
1988 * deterministically created by the test.
1989 *
1990 * The intended usage is as follows:
1991 *
1992 * TEST_F(...) {
1993 *     class PT : public ProducerThread {
1994 *         virtual void render() {
1995 *             ...
1996 *             swapBuffers();
1997 *         }
1998 *     };
1999 *
2000 *     runProducerThread(new PT());
2001 *
2002 *     // The order of these calls will vary from test to test and may include
2003 *     // multiple frames and additional operations (e.g. GL rendering from the
2004 *     // texture).
2005 *     fc->waitForFrame();
2006 *     mST->updateTexImage();
2007 *     fc->finishFrame();
2008 * }
2009 *
2010 */
2011class SurfaceTextureGLThreadToGLTest : public SurfaceTextureGLToGLTest {
2012protected:
2013
2014    // ProducerThread is an abstract base class to simplify the creation of
2015    // OpenGL ES frame producer threads.
2016    class ProducerThread : public Thread {
2017    public:
2018        virtual ~ProducerThread() {
2019        }
2020
2021        void setEglObjects(EGLDisplay producerEglDisplay,
2022                EGLSurface producerEglSurface,
2023                EGLContext producerEglContext) {
2024            mProducerEglDisplay = producerEglDisplay;
2025            mProducerEglSurface = producerEglSurface;
2026            mProducerEglContext = producerEglContext;
2027        }
2028
2029        virtual bool threadLoop() {
2030            eglMakeCurrent(mProducerEglDisplay, mProducerEglSurface,
2031                    mProducerEglSurface, mProducerEglContext);
2032            render();
2033            eglMakeCurrent(mProducerEglDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE,
2034                    EGL_NO_CONTEXT);
2035            return false;
2036        }
2037
2038    protected:
2039        virtual void render() = 0;
2040
2041        void swapBuffers() {
2042            eglSwapBuffers(mProducerEglDisplay, mProducerEglSurface);
2043        }
2044
2045        EGLDisplay mProducerEglDisplay;
2046        EGLSurface mProducerEglSurface;
2047        EGLContext mProducerEglContext;
2048    };
2049
2050    // FrameCondition is a utility class for interlocking between the producer
2051    // and consumer threads.  The FrameCondition object should be created and
2052    // destroyed in the consumer thread only.  The consumer thread should set
2053    // the FrameCondition as the FrameAvailableListener of the GLConsumer,
2054    // and should call both waitForFrame and finishFrame once for each expected
2055    // frame.
2056    //
2057    // This interlocking relies on the fact that onFrameAvailable gets called
2058    // synchronously from GLConsumer::queueBuffer.
2059    class FrameCondition : public GLConsumer::FrameAvailableListener {
2060    public:
2061        FrameCondition():
2062                mFrameAvailable(false),
2063                mFrameFinished(false) {
2064        }
2065
2066        // waitForFrame waits for the next frame to arrive.  This should be
2067        // called from the consumer thread once for every frame expected by the
2068        // test.
2069        void waitForFrame() {
2070            Mutex::Autolock lock(mMutex);
2071            ALOGV("+waitForFrame");
2072            while (!mFrameAvailable) {
2073                mFrameAvailableCondition.wait(mMutex);
2074            }
2075            mFrameAvailable = false;
2076            ALOGV("-waitForFrame");
2077        }
2078
2079        // Allow the producer to return from its swapBuffers call and continue
2080        // on to produce the next frame.  This should be called by the consumer
2081        // thread once for every frame expected by the test.
2082        void finishFrame() {
2083            Mutex::Autolock lock(mMutex);
2084            ALOGV("+finishFrame");
2085            mFrameFinished = true;
2086            mFrameFinishCondition.signal();
2087            ALOGV("-finishFrame");
2088        }
2089
2090        // This should be called by GLConsumer on the producer thread.
2091        virtual void onFrameAvailable() {
2092            Mutex::Autolock lock(mMutex);
2093            ALOGV("+onFrameAvailable");
2094            mFrameAvailable = true;
2095            mFrameAvailableCondition.signal();
2096            while (!mFrameFinished) {
2097                mFrameFinishCondition.wait(mMutex);
2098            }
2099            mFrameFinished = false;
2100            ALOGV("-onFrameAvailable");
2101        }
2102
2103    protected:
2104        bool mFrameAvailable;
2105        bool mFrameFinished;
2106
2107        Mutex mMutex;
2108        Condition mFrameAvailableCondition;
2109        Condition mFrameFinishCondition;
2110    };
2111
2112    virtual void SetUp() {
2113        SurfaceTextureGLToGLTest::SetUp();
2114        mFC = new FrameCondition();
2115        mST->setFrameAvailableListener(mFC);
2116    }
2117
2118    virtual void TearDown() {
2119        if (mProducerThread != NULL) {
2120            mProducerThread->requestExitAndWait();
2121        }
2122        mProducerThread.clear();
2123        mFC.clear();
2124        SurfaceTextureGLToGLTest::TearDown();
2125    }
2126
2127    void runProducerThread(const sp<ProducerThread> producerThread) {
2128        ASSERT_TRUE(mProducerThread == NULL);
2129        mProducerThread = producerThread;
2130        producerThread->setEglObjects(mEglDisplay, mProducerEglSurface,
2131                mProducerEglContext);
2132        producerThread->run();
2133    }
2134
2135    sp<ProducerThread> mProducerThread;
2136    sp<FrameCondition> mFC;
2137};
2138
2139TEST_F(SurfaceTextureGLThreadToGLTest,
2140        UpdateTexImageBeforeFrameFinishedCompletes) {
2141    class PT : public ProducerThread {
2142        virtual void render() {
2143            glClearColor(0.0f, 1.0f, 0.0f, 1.0f);
2144            glClear(GL_COLOR_BUFFER_BIT);
2145            swapBuffers();
2146        }
2147    };
2148
2149    runProducerThread(new PT());
2150
2151    mFC->waitForFrame();
2152    ASSERT_EQ(NO_ERROR, mST->updateTexImage());
2153    mFC->finishFrame();
2154
2155    // TODO: Add frame verification once RGB TEX_EXTERNAL_OES is supported!
2156}
2157
2158TEST_F(SurfaceTextureGLThreadToGLTest,
2159        UpdateTexImageAfterFrameFinishedCompletes) {
2160    class PT : public ProducerThread {
2161        virtual void render() {
2162            glClearColor(0.0f, 1.0f, 0.0f, 1.0f);
2163            glClear(GL_COLOR_BUFFER_BIT);
2164            swapBuffers();
2165        }
2166    };
2167
2168    runProducerThread(new PT());
2169
2170    mFC->waitForFrame();
2171    mFC->finishFrame();
2172    ASSERT_EQ(NO_ERROR, mST->updateTexImage());
2173
2174    // TODO: Add frame verification once RGB TEX_EXTERNAL_OES is supported!
2175}
2176
2177TEST_F(SurfaceTextureGLThreadToGLTest,
2178        RepeatedUpdateTexImageBeforeFrameFinishedCompletes) {
2179    enum { NUM_ITERATIONS = 1024 };
2180
2181    class PT : public ProducerThread {
2182        virtual void render() {
2183            for (int i = 0; i < NUM_ITERATIONS; i++) {
2184                glClearColor(0.0f, 1.0f, 0.0f, 1.0f);
2185                glClear(GL_COLOR_BUFFER_BIT);
2186                ALOGV("+swapBuffers");
2187                swapBuffers();
2188                ALOGV("-swapBuffers");
2189            }
2190        }
2191    };
2192
2193    runProducerThread(new PT());
2194
2195    for (int i = 0; i < NUM_ITERATIONS; i++) {
2196        mFC->waitForFrame();
2197        ALOGV("+updateTexImage");
2198        ASSERT_EQ(NO_ERROR, mST->updateTexImage());
2199        ALOGV("-updateTexImage");
2200        mFC->finishFrame();
2201
2202        // TODO: Add frame verification once RGB TEX_EXTERNAL_OES is supported!
2203    }
2204}
2205
2206TEST_F(SurfaceTextureGLThreadToGLTest,
2207        RepeatedUpdateTexImageAfterFrameFinishedCompletes) {
2208    enum { NUM_ITERATIONS = 1024 };
2209
2210    class PT : public ProducerThread {
2211        virtual void render() {
2212            for (int i = 0; i < NUM_ITERATIONS; i++) {
2213                glClearColor(0.0f, 1.0f, 0.0f, 1.0f);
2214                glClear(GL_COLOR_BUFFER_BIT);
2215                ALOGV("+swapBuffers");
2216                swapBuffers();
2217                ALOGV("-swapBuffers");
2218            }
2219        }
2220    };
2221
2222    runProducerThread(new PT());
2223
2224    for (int i = 0; i < NUM_ITERATIONS; i++) {
2225        mFC->waitForFrame();
2226        mFC->finishFrame();
2227        ALOGV("+updateTexImage");
2228        ASSERT_EQ(NO_ERROR, mST->updateTexImage());
2229        ALOGV("-updateTexImage");
2230
2231        // TODO: Add frame verification once RGB TEX_EXTERNAL_OES is supported!
2232    }
2233}
2234
2235// XXX: This test is disabled because it is currently hanging on some devices.
2236TEST_F(SurfaceTextureGLThreadToGLTest,
2237        DISABLED_RepeatedSwapBuffersWhileDequeueStalledCompletes) {
2238    enum { NUM_ITERATIONS = 64 };
2239
2240    class PT : public ProducerThread {
2241        virtual void render() {
2242            for (int i = 0; i < NUM_ITERATIONS; i++) {
2243                glClearColor(0.0f, 1.0f, 0.0f, 1.0f);
2244                glClear(GL_COLOR_BUFFER_BIT);
2245                ALOGV("+swapBuffers");
2246                swapBuffers();
2247                ALOGV("-swapBuffers");
2248            }
2249        }
2250    };
2251
2252    ASSERT_EQ(OK, mST->setDefaultMaxBufferCount(2));
2253
2254    runProducerThread(new PT());
2255
2256    // Allow three frames to be rendered and queued before starting the
2257    // rendering in this thread.  For the latter two frames we don't call
2258    // updateTexImage so the next dequeue from the producer thread will block
2259    // waiting for a frame to become available.
2260    mFC->waitForFrame();
2261    mFC->finishFrame();
2262
2263    // We must call updateTexImage to consume the first frame so that the
2264    // SurfaceTexture is able to reduce the buffer count to 2.  This is because
2265    // the GL driver may dequeue a buffer when the EGLSurface is created, and
2266    // that happens before we call setDefaultMaxBufferCount.  It's possible that the
2267    // driver does not dequeue a buffer at EGLSurface creation time, so we
2268    // cannot rely on this to cause the second dequeueBuffer call to block.
2269    ASSERT_EQ(NO_ERROR, mST->updateTexImage());
2270
2271    mFC->waitForFrame();
2272    mFC->finishFrame();
2273    mFC->waitForFrame();
2274    mFC->finishFrame();
2275
2276    // Sleep for 100ms to allow the producer thread's dequeueBuffer call to
2277    // block waiting for a buffer to become available.
2278    usleep(100000);
2279
2280    // Render and present a number of images.  This thread should not be blocked
2281    // by the fact that the producer thread is blocking in dequeue.
2282    for (int i = 0; i < NUM_ITERATIONS; i++) {
2283        glClear(GL_COLOR_BUFFER_BIT);
2284        eglSwapBuffers(mEglDisplay, mEglSurface);
2285    }
2286
2287    // Consume the two pending buffers to unblock the producer thread.
2288    ASSERT_EQ(NO_ERROR, mST->updateTexImage());
2289    ASSERT_EQ(NO_ERROR, mST->updateTexImage());
2290
2291    // Consume the remaining buffers from the producer thread.
2292    for (int i = 0; i < NUM_ITERATIONS-3; i++) {
2293        mFC->waitForFrame();
2294        mFC->finishFrame();
2295        ALOGV("+updateTexImage");
2296        ASSERT_EQ(NO_ERROR, mST->updateTexImage());
2297        ALOGV("-updateTexImage");
2298    }
2299}
2300
2301class SurfaceTextureFBOTest : public SurfaceTextureGLTest {
2302protected:
2303
2304    virtual void SetUp() {
2305        SurfaceTextureGLTest::SetUp();
2306
2307        glGenFramebuffers(1, &mFbo);
2308        ASSERT_EQ(GLenum(GL_NO_ERROR), glGetError());
2309
2310        glGenTextures(1, &mFboTex);
2311        glBindTexture(GL_TEXTURE_2D, mFboTex);
2312        glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, getSurfaceWidth(),
2313                getSurfaceHeight(), 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
2314        glBindTexture(GL_TEXTURE_2D, 0);
2315        ASSERT_EQ(GLenum(GL_NO_ERROR), glGetError());
2316
2317        glBindFramebuffer(GL_FRAMEBUFFER, mFbo);
2318        glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
2319                GL_TEXTURE_2D, mFboTex, 0);
2320        glBindFramebuffer(GL_FRAMEBUFFER, 0);
2321        ASSERT_EQ(GLenum(GL_NO_ERROR), glGetError());
2322    }
2323
2324    virtual void TearDown() {
2325        SurfaceTextureGLTest::TearDown();
2326
2327        glDeleteTextures(1, &mFboTex);
2328        glDeleteFramebuffers(1, &mFbo);
2329    }
2330
2331    GLuint mFbo;
2332    GLuint mFboTex;
2333};
2334
2335// This test is intended to verify that proper synchronization is done when
2336// rendering into an FBO.
2337TEST_F(SurfaceTextureFBOTest, BlitFromCpuFilledBufferToFbo) {
2338    const int texWidth = 64;
2339    const int texHeight = 64;
2340
2341    ASSERT_EQ(NO_ERROR, native_window_set_buffers_geometry(mANW.get(),
2342            texWidth, texHeight, HAL_PIXEL_FORMAT_RGBA_8888));
2343    ASSERT_EQ(NO_ERROR, native_window_set_usage(mANW.get(),
2344            GRALLOC_USAGE_SW_READ_OFTEN | GRALLOC_USAGE_SW_WRITE_OFTEN));
2345
2346    android_native_buffer_t* anb;
2347    ASSERT_EQ(NO_ERROR, native_window_dequeue_buffer_and_wait(mANW.get(),
2348            &anb));
2349    ASSERT_TRUE(anb != NULL);
2350
2351    sp<GraphicBuffer> buf(new GraphicBuffer(anb, false));
2352
2353    // Fill the buffer with green
2354    uint8_t* img = NULL;
2355    buf->lock(GRALLOC_USAGE_SW_WRITE_OFTEN, (void**)(&img));
2356    fillRGBA8BufferSolid(img, texWidth, texHeight, buf->getStride(), 0, 255,
2357            0, 255);
2358    buf->unlock();
2359    ASSERT_EQ(NO_ERROR, mANW->queueBuffer(mANW.get(), buf->getNativeBuffer(),
2360            -1));
2361
2362    ASSERT_EQ(NO_ERROR, mST->updateTexImage());
2363
2364    glBindFramebuffer(GL_FRAMEBUFFER, mFbo);
2365    drawTexture();
2366    glBindFramebuffer(GL_FRAMEBUFFER, 0);
2367
2368    for (int i = 0; i < 4; i++) {
2369        SCOPED_TRACE(String8::format("frame %d", i).string());
2370
2371        ASSERT_EQ(NO_ERROR, native_window_dequeue_buffer_and_wait(mANW.get(),
2372                &anb));
2373        ASSERT_TRUE(anb != NULL);
2374
2375        buf = new GraphicBuffer(anb, false);
2376
2377        // Fill the buffer with red
2378        ASSERT_EQ(NO_ERROR, buf->lock(GRALLOC_USAGE_SW_WRITE_OFTEN,
2379                (void**)(&img)));
2380        fillRGBA8BufferSolid(img, texWidth, texHeight, buf->getStride(), 255, 0,
2381                0, 255);
2382        ASSERT_EQ(NO_ERROR, buf->unlock());
2383        ASSERT_EQ(NO_ERROR, mANW->queueBuffer(mANW.get(),
2384                buf->getNativeBuffer(), -1));
2385
2386        ASSERT_EQ(NO_ERROR, mST->updateTexImage());
2387
2388        drawTexture();
2389
2390        EXPECT_TRUE(checkPixel( 24, 39, 255, 0, 0, 255));
2391    }
2392
2393    glBindFramebuffer(GL_FRAMEBUFFER, mFbo);
2394
2395    EXPECT_TRUE(checkPixel( 24, 39, 0, 255, 0, 255));
2396}
2397
2398class SurfaceTextureMultiContextGLTest : public SurfaceTextureGLTest {
2399protected:
2400    enum { SECOND_TEX_ID = 123 };
2401    enum { THIRD_TEX_ID = 456 };
2402
2403    SurfaceTextureMultiContextGLTest():
2404            mSecondEglContext(EGL_NO_CONTEXT) {
2405    }
2406
2407    virtual void SetUp() {
2408        SurfaceTextureGLTest::SetUp();
2409
2410        // Set up the secondary context and texture renderer.
2411        mSecondEglContext = eglCreateContext(mEglDisplay, mGlConfig,
2412                EGL_NO_CONTEXT, getContextAttribs());
2413        ASSERT_EQ(EGL_SUCCESS, eglGetError());
2414        ASSERT_NE(EGL_NO_CONTEXT, mSecondEglContext);
2415
2416        ASSERT_TRUE(eglMakeCurrent(mEglDisplay, mEglSurface, mEglSurface,
2417                mSecondEglContext));
2418        ASSERT_EQ(EGL_SUCCESS, eglGetError());
2419        mSecondTextureRenderer = new TextureRenderer(SECOND_TEX_ID, mST);
2420        ASSERT_NO_FATAL_FAILURE(mSecondTextureRenderer->SetUp());
2421
2422        // Set up the tertiary context and texture renderer.
2423        mThirdEglContext = eglCreateContext(mEglDisplay, mGlConfig,
2424                EGL_NO_CONTEXT, getContextAttribs());
2425        ASSERT_EQ(EGL_SUCCESS, eglGetError());
2426        ASSERT_NE(EGL_NO_CONTEXT, mThirdEglContext);
2427
2428        ASSERT_TRUE(eglMakeCurrent(mEglDisplay, mEglSurface, mEglSurface,
2429                mThirdEglContext));
2430        ASSERT_EQ(EGL_SUCCESS, eglGetError());
2431        mThirdTextureRenderer = new TextureRenderer(THIRD_TEX_ID, mST);
2432        ASSERT_NO_FATAL_FAILURE(mThirdTextureRenderer->SetUp());
2433
2434        // Switch back to the primary context to start the tests.
2435        ASSERT_TRUE(eglMakeCurrent(mEglDisplay, mEglSurface, mEglSurface,
2436                mEglContext));
2437    }
2438
2439    virtual void TearDown() {
2440        if (mThirdEglContext != EGL_NO_CONTEXT) {
2441            eglDestroyContext(mEglDisplay, mThirdEglContext);
2442        }
2443        if (mSecondEglContext != EGL_NO_CONTEXT) {
2444            eglDestroyContext(mEglDisplay, mSecondEglContext);
2445        }
2446        SurfaceTextureGLTest::TearDown();
2447    }
2448
2449    EGLContext mSecondEglContext;
2450    sp<TextureRenderer> mSecondTextureRenderer;
2451
2452    EGLContext mThirdEglContext;
2453    sp<TextureRenderer> mThirdTextureRenderer;
2454};
2455
2456TEST_F(SurfaceTextureMultiContextGLTest, UpdateFromMultipleContextsFails) {
2457    ASSERT_NO_FATAL_FAILURE(produceOneRGBA8Frame(mANW));
2458
2459    // Latch the texture contents on the primary context.
2460    mFW->waitForFrame();
2461    ASSERT_EQ(OK, mST->updateTexImage());
2462
2463    // Attempt to latch the texture on the secondary context.
2464    ASSERT_TRUE(eglMakeCurrent(mEglDisplay, mEglSurface, mEglSurface,
2465            mSecondEglContext));
2466    ASSERT_EQ(EGL_SUCCESS, eglGetError());
2467    ASSERT_EQ(INVALID_OPERATION, mST->updateTexImage());
2468}
2469
2470TEST_F(SurfaceTextureMultiContextGLTest, DetachFromContextSucceeds) {
2471    ASSERT_NO_FATAL_FAILURE(produceOneRGBA8Frame(mANW));
2472
2473    // Latch the texture contents on the primary context.
2474    mFW->waitForFrame();
2475    ASSERT_EQ(OK, mST->updateTexImage());
2476
2477    // Detach from the primary context.
2478    ASSERT_EQ(OK, mST->detachFromContext());
2479
2480    // Check that the GL texture was deleted.
2481    EXPECT_EQ(GL_FALSE, glIsTexture(TEX_ID));
2482}
2483
2484TEST_F(SurfaceTextureMultiContextGLTest,
2485        DetachFromContextSucceedsAfterProducerDisconnect) {
2486    ASSERT_NO_FATAL_FAILURE(produceOneRGBA8Frame(mANW));
2487
2488    // Latch the texture contents on the primary context.
2489    mFW->waitForFrame();
2490    ASSERT_EQ(OK, mST->updateTexImage());
2491
2492    // Detach from the primary context.
2493    native_window_api_disconnect(mANW.get(), NATIVE_WINDOW_API_CPU);
2494    ASSERT_EQ(OK, mST->detachFromContext());
2495
2496    // Check that the GL texture was deleted.
2497    EXPECT_EQ(GL_FALSE, glIsTexture(TEX_ID));
2498}
2499
2500TEST_F(SurfaceTextureMultiContextGLTest, DetachFromContextFailsWhenAbandoned) {
2501    ASSERT_NO_FATAL_FAILURE(produceOneRGBA8Frame(mANW));
2502
2503    // Latch the texture contents on the primary context.
2504    mFW->waitForFrame();
2505    ASSERT_EQ(OK, mST->updateTexImage());
2506
2507    // Attempt to detach from the primary context.
2508    mST->abandon();
2509    ASSERT_EQ(NO_INIT, mST->detachFromContext());
2510}
2511
2512TEST_F(SurfaceTextureMultiContextGLTest, DetachFromContextFailsWhenDetached) {
2513    ASSERT_NO_FATAL_FAILURE(produceOneRGBA8Frame(mANW));
2514
2515    // Latch the texture contents on the primary context.
2516    mFW->waitForFrame();
2517    ASSERT_EQ(OK, mST->updateTexImage());
2518
2519    // Detach from the primary context.
2520    ASSERT_EQ(OK, mST->detachFromContext());
2521
2522    // Attempt to detach from the primary context again.
2523    ASSERT_EQ(INVALID_OPERATION, mST->detachFromContext());
2524}
2525
2526TEST_F(SurfaceTextureMultiContextGLTest, DetachFromContextFailsWithNoDisplay) {
2527    ASSERT_NO_FATAL_FAILURE(produceOneRGBA8Frame(mANW));
2528
2529    // Latch the texture contents on the primary context.
2530    mFW->waitForFrame();
2531    ASSERT_EQ(OK, mST->updateTexImage());
2532
2533    // Make there be no current display.
2534    ASSERT_TRUE(eglMakeCurrent(mEglDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE,
2535            EGL_NO_CONTEXT));
2536    ASSERT_EQ(EGL_SUCCESS, eglGetError());
2537
2538    // Attempt to detach from the primary context.
2539    ASSERT_EQ(INVALID_OPERATION, mST->detachFromContext());
2540}
2541
2542TEST_F(SurfaceTextureMultiContextGLTest, DetachFromContextFailsWithNoContext) {
2543    ASSERT_NO_FATAL_FAILURE(produceOneRGBA8Frame(mANW));
2544
2545    // Latch the texture contents on the primary context.
2546    mFW->waitForFrame();
2547    ASSERT_EQ(OK, mST->updateTexImage());
2548
2549    // Make current context be incorrect.
2550    ASSERT_TRUE(eglMakeCurrent(mEglDisplay, mEglSurface, mEglSurface,
2551            mSecondEglContext));
2552    ASSERT_EQ(EGL_SUCCESS, eglGetError());
2553
2554    // Attempt to detach from the primary context.
2555    ASSERT_EQ(INVALID_OPERATION, mST->detachFromContext());
2556}
2557
2558TEST_F(SurfaceTextureMultiContextGLTest, UpdateTexImageFailsWhenDetached) {
2559    ASSERT_NO_FATAL_FAILURE(produceOneRGBA8Frame(mANW));
2560
2561    // Detach from the primary context.
2562    ASSERT_EQ(OK, mST->detachFromContext());
2563
2564    // Attempt to latch the texture contents on the primary context.
2565    mFW->waitForFrame();
2566    ASSERT_EQ(INVALID_OPERATION, mST->updateTexImage());
2567}
2568
2569TEST_F(SurfaceTextureMultiContextGLTest, AttachToContextSucceeds) {
2570    ASSERT_NO_FATAL_FAILURE(produceOneRGBA8Frame(mANW));
2571
2572    // Latch the texture contents on the primary context.
2573    mFW->waitForFrame();
2574    ASSERT_EQ(OK, mST->updateTexImage());
2575
2576    // Detach from the primary context.
2577    ASSERT_EQ(OK, mST->detachFromContext());
2578
2579    // Attach to the secondary context.
2580    ASSERT_TRUE(eglMakeCurrent(mEglDisplay, mEglSurface, mEglSurface,
2581            mSecondEglContext));
2582    ASSERT_EQ(OK, mST->attachToContext(SECOND_TEX_ID));
2583
2584    // Verify that the texture object was created and bound.
2585    GLint texBinding = -1;
2586    glGetIntegerv(GL_TEXTURE_BINDING_EXTERNAL_OES, &texBinding);
2587    EXPECT_EQ(SECOND_TEX_ID, texBinding);
2588
2589    // Try to use the texture from the secondary context.
2590    glClearColor(0.2, 0.2, 0.2, 0.2);
2591    glClear(GL_COLOR_BUFFER_BIT);
2592    glViewport(0, 0, 1, 1);
2593    mSecondTextureRenderer->drawTexture();
2594    ASSERT_TRUE(checkPixel( 0,  0,  35,  35,  35,  35));
2595    ASSERT_EQ(GLenum(GL_NO_ERROR), glGetError());
2596}
2597
2598TEST_F(SurfaceTextureMultiContextGLTest,
2599        AttachToContextSucceedsAfterProducerDisconnect) {
2600    ASSERT_NO_FATAL_FAILURE(produceOneRGBA8Frame(mANW));
2601
2602    // Latch the texture contents on the primary context.
2603    mFW->waitForFrame();
2604    ASSERT_EQ(OK, mST->updateTexImage());
2605
2606    // Detach from the primary context.
2607    native_window_api_disconnect(mANW.get(), NATIVE_WINDOW_API_CPU);
2608    ASSERT_EQ(OK, mST->detachFromContext());
2609
2610    // Attach to the secondary context.
2611    ASSERT_TRUE(eglMakeCurrent(mEglDisplay, mEglSurface, mEglSurface,
2612            mSecondEglContext));
2613    ASSERT_EQ(OK, mST->attachToContext(SECOND_TEX_ID));
2614
2615    // Verify that the texture object was created and bound.
2616    GLint texBinding = -1;
2617    glGetIntegerv(GL_TEXTURE_BINDING_EXTERNAL_OES, &texBinding);
2618    EXPECT_EQ(SECOND_TEX_ID, texBinding);
2619
2620    // Try to use the texture from the secondary context.
2621    glClearColor(0.2, 0.2, 0.2, 0.2);
2622    glClear(GL_COLOR_BUFFER_BIT);
2623    glViewport(0, 0, 1, 1);
2624    mSecondTextureRenderer->drawTexture();
2625    ASSERT_EQ(GLenum(GL_NO_ERROR), glGetError());
2626    ASSERT_TRUE(checkPixel( 0,  0,  35,  35,  35,  35));
2627}
2628
2629TEST_F(SurfaceTextureMultiContextGLTest,
2630        AttachToContextSucceedsBeforeUpdateTexImage) {
2631    ASSERT_NO_FATAL_FAILURE(produceOneRGBA8Frame(mANW));
2632
2633    // Detach from the primary context.
2634    native_window_api_disconnect(mANW.get(), NATIVE_WINDOW_API_CPU);
2635    ASSERT_EQ(OK, mST->detachFromContext());
2636
2637    // Attach to the secondary context.
2638    ASSERT_TRUE(eglMakeCurrent(mEglDisplay, mEglSurface, mEglSurface,
2639            mSecondEglContext));
2640    ASSERT_EQ(OK, mST->attachToContext(SECOND_TEX_ID));
2641
2642    // Verify that the texture object was created and bound.
2643    GLint texBinding = -1;
2644    glGetIntegerv(GL_TEXTURE_BINDING_EXTERNAL_OES, &texBinding);
2645    EXPECT_EQ(SECOND_TEX_ID, texBinding);
2646
2647    // Latch the texture contents on the primary context.
2648    mFW->waitForFrame();
2649    ASSERT_EQ(OK, mST->updateTexImage());
2650
2651    // Try to use the texture from the secondary context.
2652    glClearColor(0.2, 0.2, 0.2, 0.2);
2653    glClear(GL_COLOR_BUFFER_BIT);
2654    glViewport(0, 0, 1, 1);
2655    mSecondTextureRenderer->drawTexture();
2656    ASSERT_EQ(GLenum(GL_NO_ERROR), glGetError());
2657    ASSERT_TRUE(checkPixel( 0,  0,  35,  35,  35,  35));
2658}
2659
2660TEST_F(SurfaceTextureMultiContextGLTest, AttachToContextFailsWhenAbandoned) {
2661    ASSERT_NO_FATAL_FAILURE(produceOneRGBA8Frame(mANW));
2662
2663    // Latch the texture contents on the primary context.
2664    mFW->waitForFrame();
2665    ASSERT_EQ(OK, mST->updateTexImage());
2666
2667    // Detach from the primary context.
2668    ASSERT_EQ(OK, mST->detachFromContext());
2669
2670    // Attempt to attach to the secondary context.
2671    mST->abandon();
2672
2673    // Attempt to attach to the primary context.
2674    ASSERT_EQ(NO_INIT, mST->attachToContext(SECOND_TEX_ID));
2675}
2676
2677TEST_F(SurfaceTextureMultiContextGLTest, AttachToContextFailsWhenAttached) {
2678    ASSERT_NO_FATAL_FAILURE(produceOneRGBA8Frame(mANW));
2679
2680    // Latch the texture contents on the primary context.
2681    mFW->waitForFrame();
2682    ASSERT_EQ(OK, mST->updateTexImage());
2683
2684    // Attempt to attach to the primary context.
2685    ASSERT_EQ(INVALID_OPERATION, mST->attachToContext(SECOND_TEX_ID));
2686}
2687
2688TEST_F(SurfaceTextureMultiContextGLTest,
2689        AttachToContextFailsWhenAttachedBeforeUpdateTexImage) {
2690    ASSERT_NO_FATAL_FAILURE(produceOneRGBA8Frame(mANW));
2691
2692    // Attempt to attach to the primary context.
2693    ASSERT_EQ(INVALID_OPERATION, mST->attachToContext(SECOND_TEX_ID));
2694}
2695
2696TEST_F(SurfaceTextureMultiContextGLTest, AttachToContextFailsWithNoDisplay) {
2697    ASSERT_NO_FATAL_FAILURE(produceOneRGBA8Frame(mANW));
2698
2699    // Latch the texture contents on the primary context.
2700    mFW->waitForFrame();
2701    ASSERT_EQ(OK, mST->updateTexImage());
2702
2703    // Detach from the primary context.
2704    ASSERT_EQ(OK, mST->detachFromContext());
2705
2706    // Make there be no current display.
2707    ASSERT_TRUE(eglMakeCurrent(mEglDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE,
2708            EGL_NO_CONTEXT));
2709    ASSERT_EQ(EGL_SUCCESS, eglGetError());
2710
2711    // Attempt to attach with no context current.
2712    ASSERT_EQ(INVALID_OPERATION, mST->attachToContext(SECOND_TEX_ID));
2713}
2714
2715TEST_F(SurfaceTextureMultiContextGLTest, AttachToContextSucceedsTwice) {
2716    ASSERT_NO_FATAL_FAILURE(produceOneRGBA8Frame(mANW));
2717
2718    // Latch the texture contents on the primary context.
2719    mFW->waitForFrame();
2720    ASSERT_EQ(OK, mST->updateTexImage());
2721
2722    // Detach from the primary context.
2723    ASSERT_EQ(OK, mST->detachFromContext());
2724
2725    // Attach to the secondary context.
2726    ASSERT_TRUE(eglMakeCurrent(mEglDisplay, mEglSurface, mEglSurface,
2727            mSecondEglContext));
2728    ASSERT_EQ(OK, mST->attachToContext(SECOND_TEX_ID));
2729
2730    // Detach from the secondary context.
2731    ASSERT_EQ(OK, mST->detachFromContext());
2732
2733    // Attach to the tertiary context.
2734    ASSERT_TRUE(eglMakeCurrent(mEglDisplay, mEglSurface, mEglSurface,
2735            mThirdEglContext));
2736    ASSERT_EQ(OK, mST->attachToContext(THIRD_TEX_ID));
2737
2738    // Verify that the texture object was created and bound.
2739    GLint texBinding = -1;
2740    glGetIntegerv(GL_TEXTURE_BINDING_EXTERNAL_OES, &texBinding);
2741    EXPECT_EQ(THIRD_TEX_ID, texBinding);
2742
2743    // Try to use the texture from the tertiary context.
2744    glClearColor(0.2, 0.2, 0.2, 0.2);
2745    glClear(GL_COLOR_BUFFER_BIT);
2746    glViewport(0, 0, 1, 1);
2747    mThirdTextureRenderer->drawTexture();
2748    ASSERT_EQ(GLenum(GL_NO_ERROR), glGetError());
2749    ASSERT_TRUE(checkPixel( 0,  0,  35,  35,  35,  35));
2750}
2751
2752TEST_F(SurfaceTextureMultiContextGLTest,
2753        AttachToContextSucceedsTwiceBeforeUpdateTexImage) {
2754    ASSERT_NO_FATAL_FAILURE(produceOneRGBA8Frame(mANW));
2755
2756    // Detach from the primary context.
2757    ASSERT_EQ(OK, mST->detachFromContext());
2758
2759    // Attach to the secondary context.
2760    ASSERT_TRUE(eglMakeCurrent(mEglDisplay, mEglSurface, mEglSurface,
2761            mSecondEglContext));
2762    ASSERT_EQ(OK, mST->attachToContext(SECOND_TEX_ID));
2763
2764    // Detach from the secondary context.
2765    ASSERT_EQ(OK, mST->detachFromContext());
2766
2767    // Attach to the tertiary context.
2768    ASSERT_TRUE(eglMakeCurrent(mEglDisplay, mEglSurface, mEglSurface,
2769            mThirdEglContext));
2770    ASSERT_EQ(OK, mST->attachToContext(THIRD_TEX_ID));
2771
2772    // Verify that the texture object was created and bound.
2773    GLint texBinding = -1;
2774    glGetIntegerv(GL_TEXTURE_BINDING_EXTERNAL_OES, &texBinding);
2775    EXPECT_EQ(THIRD_TEX_ID, texBinding);
2776
2777    // Latch the texture contents on the tertiary context.
2778    mFW->waitForFrame();
2779    ASSERT_EQ(OK, mST->updateTexImage());
2780
2781    // Try to use the texture from the tertiary context.
2782    glClearColor(0.2, 0.2, 0.2, 0.2);
2783    glClear(GL_COLOR_BUFFER_BIT);
2784    glViewport(0, 0, 1, 1);
2785    mThirdTextureRenderer->drawTexture();
2786    ASSERT_EQ(GLenum(GL_NO_ERROR), glGetError());
2787    ASSERT_TRUE(checkPixel( 0,  0,  35,  35,  35,  35));
2788}
2789
2790TEST_F(SurfaceTextureMultiContextGLTest,
2791        UpdateTexImageSucceedsForBufferConsumedBeforeDetach) {
2792    ASSERT_EQ(NO_ERROR, mST->setDefaultMaxBufferCount(2));
2793
2794    // produce two frames and consume them both on the primary context
2795    ASSERT_NO_FATAL_FAILURE(produceOneRGBA8Frame(mANW));
2796    mFW->waitForFrame();
2797    ASSERT_EQ(OK, mST->updateTexImage());
2798
2799    ASSERT_NO_FATAL_FAILURE(produceOneRGBA8Frame(mANW));
2800    mFW->waitForFrame();
2801    ASSERT_EQ(OK, mST->updateTexImage());
2802
2803    // produce one more frame
2804    ASSERT_NO_FATAL_FAILURE(produceOneRGBA8Frame(mANW));
2805
2806    // Detach from the primary context and attach to the secondary context
2807    ASSERT_EQ(OK, mST->detachFromContext());
2808    ASSERT_TRUE(eglMakeCurrent(mEglDisplay, mEglSurface, mEglSurface,
2809            mSecondEglContext));
2810    ASSERT_EQ(OK, mST->attachToContext(SECOND_TEX_ID));
2811
2812    // Consume final frame on secondary context
2813    mFW->waitForFrame();
2814    ASSERT_EQ(OK, mST->updateTexImage());
2815}
2816
2817} // namespace android
2818