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