SurfaceTexture_test.cpp revision 2510d9576ff2c529d584082aa1098480a73079e4
1d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis/*
2d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis * Copyright (C) 2011 The Android Open Source Project
3d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis *
4d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis * Licensed under the Apache License, Version 2.0 (the "License");
5d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis * you may not use this file except in compliance with the License.
6d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis * You may obtain a copy of the License at
7d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis *
8d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis *      http://www.apache.org/licenses/LICENSE-2.0
9d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis *
10d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis * Unless required by applicable law or agreed to in writing, software
11d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis * distributed under the License is distributed on an "AS IS" BASIS,
12d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis * See the License for the specific language governing permissions and
14d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis * limitations under the License.
15d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis */
16d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis
175451d15ee209f29d64beea87583f7058dee69911Jamie Gennis//#define LOG_NDEBUG 0
185451d15ee209f29d64beea87583f7058dee69911Jamie Gennis
19d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis#include <gtest/gtest.h>
20d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis#include <gui/SurfaceTexture.h>
21d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis#include <gui/SurfaceTextureClient.h>
22d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis#include <ui/GraphicBuffer.h>
23d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis#include <utils/String8.h>
245451d15ee209f29d64beea87583f7058dee69911Jamie Gennis#include <utils/threads.h>
25d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis
26d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis#include <surfaceflinger/ISurfaceComposer.h>
27d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis#include <surfaceflinger/Surface.h>
28d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis#include <surfaceflinger/SurfaceComposerClient.h>
29d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis
30d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis#include <EGL/egl.h>
31d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis#include <EGL/eglext.h>
32d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis#include <GLES2/gl2.h>
33d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis#include <GLES2/gl2ext.h>
34d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis
35d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis#include <ui/FramebufferNativeWindow.h>
36d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis
37d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennisnamespace android {
38d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis
39d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennisclass GLTest : public ::testing::Test {
40d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennisprotected:
41d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis
42d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis    GLTest():
43d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis            mEglDisplay(EGL_NO_DISPLAY),
44d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis            mEglSurface(EGL_NO_SURFACE),
45d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis            mEglContext(EGL_NO_CONTEXT) {
46d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis    }
47d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis
48d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis    virtual void SetUp() {
49d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis        EGLBoolean returnValue;
50d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis
51d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis        mEglDisplay = eglGetDisplay(EGL_DEFAULT_DISPLAY);
52d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis        ASSERT_EQ(EGL_SUCCESS, eglGetError());
53d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis        ASSERT_NE(EGL_NO_DISPLAY, mEglDisplay);
54d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis
55d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis        EGLint majorVersion;
56d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis        EGLint minorVersion;
57d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis        EXPECT_TRUE(eglInitialize(mEglDisplay, &majorVersion, &minorVersion));
58d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis        ASSERT_EQ(EGL_SUCCESS, eglGetError());
59d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis        RecordProperty("EglVersionMajor", majorVersion);
60d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis        RecordProperty("EglVersionMajor", minorVersion);
61d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis
62d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis        EGLConfig myConfig = {0};
63d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis        EGLint numConfigs = 0;
64d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis        EXPECT_TRUE(eglChooseConfig(mEglDisplay, getConfigAttribs(), &myConfig,
65d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis                1, &numConfigs));
66d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis        ASSERT_EQ(EGL_SUCCESS, eglGetError());
67d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis
68d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis        char* displaySecsEnv = getenv("GLTEST_DISPLAY_SECS");
69d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis        if (displaySecsEnv != NULL) {
70d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis            mDisplaySecs = atoi(displaySecsEnv);
71d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis            if (mDisplaySecs < 0) {
72d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis                mDisplaySecs = 0;
73d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis            }
74d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis        } else {
75d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis            mDisplaySecs = 0;
76d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis        }
77d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis
78d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis        if (mDisplaySecs > 0) {
79d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis            mComposerClient = new SurfaceComposerClient;
80d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis            ASSERT_EQ(NO_ERROR, mComposerClient->initCheck());
81d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis
82fc850124b35abd00a31e9bcf57e14e0fa74f4cd7Jamie Gennis            mSurfaceControl = mComposerClient->createSurface(
83d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis                    String8("Test Surface"), 0,
84d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis                    getSurfaceWidth(), getSurfaceHeight(),
85d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis                    PIXEL_FORMAT_RGB_888, 0);
86d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis
87d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis            ASSERT_TRUE(mSurfaceControl != NULL);
88d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis            ASSERT_TRUE(mSurfaceControl->isValid());
89d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis
90d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis            ASSERT_EQ(NO_ERROR, mComposerClient->openTransaction());
91d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis            ASSERT_EQ(NO_ERROR, mSurfaceControl->setLayer(30000));
92d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis            ASSERT_EQ(NO_ERROR, mSurfaceControl->show());
93d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis            ASSERT_EQ(NO_ERROR, mComposerClient->closeTransaction());
94d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis
95d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis            sp<ANativeWindow> window = mSurfaceControl->getSurface();
96d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis            mEglSurface = eglCreateWindowSurface(mEglDisplay, myConfig,
97d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis                    window.get(), NULL);
98d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis        } else {
99d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis            EGLint pbufferAttribs[] = {
100d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis                EGL_WIDTH, getSurfaceWidth(),
101d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis                EGL_HEIGHT, getSurfaceHeight(),
102d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis                EGL_NONE };
103d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis
104d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis            mEglSurface = eglCreatePbufferSurface(mEglDisplay, myConfig,
105d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis                    pbufferAttribs);
106d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis        }
107d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis        ASSERT_EQ(EGL_SUCCESS, eglGetError());
108d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis        ASSERT_NE(EGL_NO_SURFACE, mEglSurface);
109d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis
110d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis        mEglContext = eglCreateContext(mEglDisplay, myConfig, EGL_NO_CONTEXT,
111d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis                getContextAttribs());
112d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis        ASSERT_EQ(EGL_SUCCESS, eglGetError());
113d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis        ASSERT_NE(EGL_NO_CONTEXT, mEglContext);
114d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis
115d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis        EXPECT_TRUE(eglMakeCurrent(mEglDisplay, mEglSurface, mEglSurface,
116d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis                mEglContext));
117d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis        ASSERT_EQ(EGL_SUCCESS, eglGetError());
118d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis
119d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis        EGLint w, h;
120d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis        EXPECT_TRUE(eglQuerySurface(mEglDisplay, mEglSurface, EGL_WIDTH, &w));
121d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis        ASSERT_EQ(EGL_SUCCESS, eglGetError());
122d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis        EXPECT_TRUE(eglQuerySurface(mEglDisplay, mEglSurface, EGL_HEIGHT, &h));
123d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis        ASSERT_EQ(EGL_SUCCESS, eglGetError());
124d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis        RecordProperty("EglSurfaceWidth", w);
125d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis        RecordProperty("EglSurfaceHeight", h);
126d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis
127d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis        glViewport(0, 0, w, h);
128d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis        ASSERT_EQ(GLenum(GL_NO_ERROR), glGetError());
129d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis    }
130d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis
131d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis    virtual void TearDown() {
132d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis        // Display the result
133d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis        if (mDisplaySecs > 0 && mEglSurface != EGL_NO_SURFACE) {
134d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis            eglSwapBuffers(mEglDisplay, mEglSurface);
135d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis            sleep(mDisplaySecs);
136d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis        }
137d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis
138d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis        if (mComposerClient != NULL) {
139d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis            mComposerClient->dispose();
140d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis        }
141d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis        if (mEglContext != EGL_NO_CONTEXT) {
142d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis            eglDestroyContext(mEglDisplay, mEglContext);
143d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis        }
144d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis        if (mEglSurface != EGL_NO_SURFACE) {
145d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis            eglDestroySurface(mEglDisplay, mEglSurface);
146d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis        }
147d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis        if (mEglDisplay != EGL_NO_DISPLAY) {
148d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis            eglMakeCurrent(mEglDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE,
149d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis                    EGL_NO_CONTEXT);
150d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis            eglTerminate(mEglDisplay);
151d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis        }
152d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis        ASSERT_EQ(EGL_SUCCESS, eglGetError());
153d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis    }
154d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis
155d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis    virtual EGLint const* getConfigAttribs() {
156d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis        static EGLint sDefaultConfigAttribs[] = {
157d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis            EGL_SURFACE_TYPE, EGL_PBUFFER_BIT,
158d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis            EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT,
159d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis            EGL_RED_SIZE, 8,
160d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis            EGL_GREEN_SIZE, 8,
161d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis            EGL_BLUE_SIZE, 8,
162d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis            EGL_ALPHA_SIZE, 8,
163d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis            EGL_DEPTH_SIZE, 16,
164d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis            EGL_STENCIL_SIZE, 8,
165d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis            EGL_NONE };
166d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis
167d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis        return sDefaultConfigAttribs;
168d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis    }
169d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis
170d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis    virtual EGLint const* getContextAttribs() {
171d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis        static EGLint sDefaultContextAttribs[] = {
172d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis            EGL_CONTEXT_CLIENT_VERSION, 2,
173d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis            EGL_NONE };
174d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis
175d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis        return sDefaultContextAttribs;
176d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis    }
177d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis
178d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis    virtual EGLint getSurfaceWidth() {
179d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis        return 64;
180d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis    }
181d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis
182d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis    virtual EGLint getSurfaceHeight() {
183d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis        return 64;
184d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis    }
185d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis
186d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis    void loadShader(GLenum shaderType, const char* pSource, GLuint* outShader) {
187d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis        GLuint shader = glCreateShader(shaderType);
188d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis        ASSERT_EQ(GLenum(GL_NO_ERROR), glGetError());
189d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis        if (shader) {
190d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis            glShaderSource(shader, 1, &pSource, NULL);
191d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis            ASSERT_EQ(GLenum(GL_NO_ERROR), glGetError());
192d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis            glCompileShader(shader);
193d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis            ASSERT_EQ(GLenum(GL_NO_ERROR), glGetError());
194d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis            GLint compiled = 0;
195d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis            glGetShaderiv(shader, GL_COMPILE_STATUS, &compiled);
196d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis            ASSERT_EQ(GLenum(GL_NO_ERROR), glGetError());
197d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis            if (!compiled) {
198d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis                GLint infoLen = 0;
199d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis                glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &infoLen);
200d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis                ASSERT_EQ(GLenum(GL_NO_ERROR), glGetError());
201d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis                if (infoLen) {
202d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis                    char* buf = (char*) malloc(infoLen);
203d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis                    if (buf) {
204d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis                        glGetShaderInfoLog(shader, infoLen, NULL, buf);
205d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis                        printf("Shader compile log:\n%s\n", buf);
206d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis                        free(buf);
207d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis                        FAIL();
208d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis                    }
209d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis                } else {
210d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis                    char* buf = (char*) malloc(0x1000);
211d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis                    if (buf) {
212d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis                        glGetShaderInfoLog(shader, 0x1000, NULL, buf);
213d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis                        printf("Shader compile log:\n%s\n", buf);
214d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis                        free(buf);
215d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis                        FAIL();
216d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis                    }
217d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis                }
218d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis                glDeleteShader(shader);
219d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis                shader = 0;
220d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis            }
221d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis        }
222d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis        ASSERT_TRUE(shader != 0);
223d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis        *outShader = shader;
224d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis    }
225d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis
226d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis    void createProgram(const char* pVertexSource, const char* pFragmentSource,
227d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis            GLuint* outPgm) {
228d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis        GLuint vertexShader, fragmentShader;
229d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis        {
230d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis            SCOPED_TRACE("compiling vertex shader");
231d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis            loadShader(GL_VERTEX_SHADER, pVertexSource, &vertexShader);
232d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis            if (HasFatalFailure()) {
233d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis                return;
234d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis            }
235d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis        }
236d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis        {
237d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis            SCOPED_TRACE("compiling fragment shader");
238d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis            loadShader(GL_FRAGMENT_SHADER, pFragmentSource, &fragmentShader);
239d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis            if (HasFatalFailure()) {
240d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis                return;
241d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis            }
242d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis        }
243d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis
244d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis        GLuint program = glCreateProgram();
245d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis        ASSERT_EQ(GLenum(GL_NO_ERROR), glGetError());
246d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis        if (program) {
247d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis            glAttachShader(program, vertexShader);
248d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis            ASSERT_EQ(GLenum(GL_NO_ERROR), glGetError());
249d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis            glAttachShader(program, fragmentShader);
250d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis            ASSERT_EQ(GLenum(GL_NO_ERROR), glGetError());
251d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis            glLinkProgram(program);
252d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis            GLint linkStatus = GL_FALSE;
253d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis            glGetProgramiv(program, GL_LINK_STATUS, &linkStatus);
254d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis            if (linkStatus != GL_TRUE) {
255d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis                GLint bufLength = 0;
256d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis                glGetProgramiv(program, GL_INFO_LOG_LENGTH, &bufLength);
257d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis                if (bufLength) {
258d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis                    char* buf = (char*) malloc(bufLength);
259d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis                    if (buf) {
260d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis                        glGetProgramInfoLog(program, bufLength, NULL, buf);
261d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis                        printf("Program link log:\n%s\n", buf);
262d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis                        free(buf);
263d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis                        FAIL();
264d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis                    }
265d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis                }
266d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis                glDeleteProgram(program);
267d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis                program = 0;
268d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis            }
269d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis        }
270d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis        glDeleteShader(vertexShader);
271d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis        glDeleteShader(fragmentShader);
272d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis        ASSERT_TRUE(program != 0);
273d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis        *outPgm = program;
274d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis    }
275d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis
276824efa74e7ff0a8dd95302daf73c23a056da0d07Jamie Gennis    static int abs(int value) {
277824efa74e7ff0a8dd95302daf73c23a056da0d07Jamie Gennis        return value > 0 ? value : -value;
278824efa74e7ff0a8dd95302daf73c23a056da0d07Jamie Gennis    }
279824efa74e7ff0a8dd95302daf73c23a056da0d07Jamie Gennis
280d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis    ::testing::AssertionResult checkPixel(int x, int y, int r,
281824efa74e7ff0a8dd95302daf73c23a056da0d07Jamie Gennis            int g, int b, int a, int tolerance=2) {
282d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis        GLubyte pixel[4];
283d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis        String8 msg;
284d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis        glReadPixels(x, y, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, pixel);
285d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis        GLenum err = glGetError();
286d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis        if (err != GL_NO_ERROR) {
287d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis            msg += String8::format("error reading pixel: %#x", err);
288d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis            while ((err = glGetError()) != GL_NO_ERROR) {
289d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis                msg += String8::format(", %#x", err);
290d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis            }
291d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis            fprintf(stderr, "pixel check failure: %s\n", msg.string());
292d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis            return ::testing::AssertionFailure(
293d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis                    ::testing::Message(msg.string()));
294d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis        }
295824efa74e7ff0a8dd95302daf73c23a056da0d07Jamie Gennis        if (r >= 0 && abs(r - int(pixel[0])) > tolerance) {
296d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis            msg += String8::format("r(%d isn't %d)", pixel[0], r);
297d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis        }
298824efa74e7ff0a8dd95302daf73c23a056da0d07Jamie Gennis        if (g >= 0 && abs(g - int(pixel[1])) > tolerance) {
299d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis            if (!msg.isEmpty()) {
300d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis                msg += " ";
301d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis            }
302d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis            msg += String8::format("g(%d isn't %d)", pixel[1], g);
303d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis        }
304824efa74e7ff0a8dd95302daf73c23a056da0d07Jamie Gennis        if (b >= 0 && abs(b - int(pixel[2])) > tolerance) {
305d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis            if (!msg.isEmpty()) {
306d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis                msg += " ";
307d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis            }
308d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis            msg += String8::format("b(%d isn't %d)", pixel[2], b);
309d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis        }
310824efa74e7ff0a8dd95302daf73c23a056da0d07Jamie Gennis        if (a >= 0 && abs(a - int(pixel[3])) > tolerance) {
311d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis            if (!msg.isEmpty()) {
312d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis                msg += " ";
313d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis            }
314d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis            msg += String8::format("a(%d isn't %d)", pixel[3], a);
315d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis        }
316d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis        if (!msg.isEmpty()) {
317d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis            fprintf(stderr, "pixel check failure: %s\n", msg.string());
318d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis            return ::testing::AssertionFailure(
319d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis                    ::testing::Message(msg.string()));
320d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis        } else {
321d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis            return ::testing::AssertionSuccess();
322d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis        }
323d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis    }
324d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis
325d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis    int mDisplaySecs;
326d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis    sp<SurfaceComposerClient> mComposerClient;
327d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis    sp<SurfaceControl> mSurfaceControl;
328d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis
329d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis    EGLDisplay mEglDisplay;
330d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis    EGLSurface mEglSurface;
331d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis    EGLContext mEglContext;
332d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis};
333d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis
334d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis// XXX: Code above this point should live elsewhere
335d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis
336d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennisclass SurfaceTextureGLTest : public GLTest {
337d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennisprotected:
338d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis    static const GLint TEX_ID = 123;
339d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis
340d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis    virtual void SetUp() {
341d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis        GLTest::SetUp();
342d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis        mST = new SurfaceTexture(TEX_ID);
343d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis        mSTC = new SurfaceTextureClient(mST);
344d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis        mANW = mSTC;
345d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis
346d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis        const char vsrc[] =
347d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis            "attribute vec4 vPosition;\n"
348d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis            "varying vec2 texCoords;\n"
349d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis            "uniform mat4 texMatrix;\n"
350d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis            "void main() {\n"
351d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis            "  vec2 vTexCoords = 0.5 * (vPosition.xy + vec2(1.0, 1.0));\n"
352d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis            "  texCoords = (texMatrix * vec4(vTexCoords, 0.0, 1.0)).xy;\n"
353d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis            "  gl_Position = vPosition;\n"
354d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis            "}\n";
355d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis
356d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis        const char fsrc[] =
357d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis            "#extension GL_OES_EGL_image_external : require\n"
358d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis            "precision mediump float;\n"
359d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis            "uniform samplerExternalOES texSampler;\n"
360d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis            "varying vec2 texCoords;\n"
361d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis            "void main() {\n"
362d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis            "  gl_FragColor = texture2D(texSampler, texCoords);\n"
363d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis            "}\n";
364d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis
365d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis        {
366d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis            SCOPED_TRACE("creating shader program");
367d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis            createProgram(vsrc, fsrc, &mPgm);
368d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis            if (HasFatalFailure()) {
369d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis                return;
370d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis            }
371d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis        }
372d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis
373d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis        mPositionHandle = glGetAttribLocation(mPgm, "vPosition");
374d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis        ASSERT_EQ(GLenum(GL_NO_ERROR), glGetError());
375d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis        ASSERT_NE(-1, mPositionHandle);
376d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis        mTexSamplerHandle = glGetUniformLocation(mPgm, "texSampler");
377d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis        ASSERT_EQ(GLenum(GL_NO_ERROR), glGetError());
378d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis        ASSERT_NE(-1, mTexSamplerHandle);
379d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis        mTexMatrixHandle = glGetUniformLocation(mPgm, "texMatrix");
380d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis        ASSERT_EQ(GLenum(GL_NO_ERROR), glGetError());
381d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis        ASSERT_NE(-1, mTexMatrixHandle);
382d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis    }
383d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis
384d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis    // drawTexture draws the SurfaceTexture over the entire GL viewport.
385d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis    void drawTexture() {
386d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis        const GLfloat triangleVertices[] = {
387d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis            -1.0f, 1.0f,
388d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis            -1.0f, -1.0f,
389d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis            1.0f, -1.0f,
390d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis            1.0f, 1.0f,
391d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis        };
392d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis
393d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis        glVertexAttribPointer(mPositionHandle, 2, GL_FLOAT, GL_FALSE, 0, triangleVertices);
394d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis        ASSERT_EQ(GLenum(GL_NO_ERROR), glGetError());
395d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis        glEnableVertexAttribArray(mPositionHandle);
396d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis        ASSERT_EQ(GLenum(GL_NO_ERROR), glGetError());
397d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis
398d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis        glUseProgram(mPgm);
399d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis        glUniform1i(mTexSamplerHandle, 0);
400d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis        ASSERT_EQ(GLenum(GL_NO_ERROR), glGetError());
401d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis        glBindTexture(GL_TEXTURE_EXTERNAL_OES, TEX_ID);
402d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis        ASSERT_EQ(GLenum(GL_NO_ERROR), glGetError());
403d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis
404d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis        GLfloat texMatrix[16];
405d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis        mST->getTransformMatrix(texMatrix);
406d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis        glUniformMatrix4fv(mTexMatrixHandle, 1, GL_FALSE, texMatrix);
407d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis
408d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis        glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
409d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis        ASSERT_EQ(GLenum(GL_NO_ERROR), glGetError());
410d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis    }
411d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis
412d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis    sp<SurfaceTexture> mST;
413d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis    sp<SurfaceTextureClient> mSTC;
414d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis    sp<ANativeWindow> mANW;
415d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis
416d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis    GLuint mPgm;
417d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis    GLint mPositionHandle;
418d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis    GLint mTexSamplerHandle;
419d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis    GLint mTexMatrixHandle;
420d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis};
421d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis
422d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis// Fill a YV12 buffer with a multi-colored checkerboard pattern
423d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennisvoid fillYV12Buffer(uint8_t* buf, int w, int h, int stride) {
424d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis    const int blockWidth = w > 16 ? w / 16 : 1;
425d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis    const int blockHeight = h > 16 ? h / 16 : 1;
426d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis    const int yuvTexOffsetY = 0;
427d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis    int yuvTexStrideY = stride;
428d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis    int yuvTexOffsetV = yuvTexStrideY * h;
429d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis    int yuvTexStrideV = (yuvTexStrideY/2 + 0xf) & ~0xf;
430d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis    int yuvTexOffsetU = yuvTexOffsetV + yuvTexStrideV * h/2;
431d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis    int yuvTexStrideU = yuvTexStrideV;
432d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis    for (int x = 0; x < w; x++) {
433d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis        for (int y = 0; y < h; y++) {
434d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis            int parityX = (x / blockWidth) & 1;
435d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis            int parityY = (y / blockHeight) & 1;
436d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis            unsigned char intensity = (parityX ^ parityY) ? 63 : 191;
437d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis            buf[yuvTexOffsetY + (y * yuvTexStrideY) + x] = intensity;
438d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis            if (x < w / 2 && y < h / 2) {
439d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis                buf[yuvTexOffsetU + (y * yuvTexStrideU) + x] = intensity;
440d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis                if (x * 2 < w / 2 && y * 2 < h / 2) {
441d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis                    buf[yuvTexOffsetV + (y*2 * yuvTexStrideV) + x*2 + 0] =
442d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis                    buf[yuvTexOffsetV + (y*2 * yuvTexStrideV) + x*2 + 1] =
443d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis                    buf[yuvTexOffsetV + ((y*2+1) * yuvTexStrideV) + x*2 + 0] =
444d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis                    buf[yuvTexOffsetV + ((y*2+1) * yuvTexStrideV) + x*2 + 1] =
445d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis                        intensity;
446d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis                }
447d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis            }
448d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis        }
449d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis    }
450d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis}
451d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis
452d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis// Fill a YV12 buffer with red outside a given rectangle and green inside it.
453d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennisvoid fillYV12BufferRect(uint8_t* buf, int w, int h, int stride,
454d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis        const android_native_rect_t& rect) {
455d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis    const int yuvTexOffsetY = 0;
456d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis    int yuvTexStrideY = stride;
457d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis    int yuvTexOffsetV = yuvTexStrideY * h;
458d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis    int yuvTexStrideV = (yuvTexStrideY/2 + 0xf) & ~0xf;
459d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis    int yuvTexOffsetU = yuvTexOffsetV + yuvTexStrideV * h/2;
460d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis    int yuvTexStrideU = yuvTexStrideV;
461d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis    for (int x = 0; x < w; x++) {
462d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis        for (int y = 0; y < h; y++) {
463d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis            bool inside = rect.left <= x && x < rect.right &&
464d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis                    rect.top <= y && y < rect.bottom;
465d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis            buf[yuvTexOffsetY + (y * yuvTexStrideY) + x] = inside ? 240 : 64;
466d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis            if (x < w / 2 && y < h / 2) {
467d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis                bool inside = rect.left <= 2*x && 2*x < rect.right &&
468d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis                        rect.top <= 2*y && 2*y < rect.bottom;
469d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis                buf[yuvTexOffsetU + (y * yuvTexStrideU) + x] = 16;
470d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis                buf[yuvTexOffsetV + (y * yuvTexStrideV) + x] =
471d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis                        inside ? 16 : 255;
472d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis            }
473d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis        }
474d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis    }
475d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis}
476d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis
477d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie GennisTEST_F(SurfaceTextureGLTest, TexturingFromCpuFilledYV12BufferNpot) {
478d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis    const int yuvTexWidth = 64;
479d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis    const int yuvTexHeight = 66;
480d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis
481d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis    ASSERT_EQ(NO_ERROR, native_window_set_buffers_geometry(mANW.get(),
482d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis            yuvTexWidth, yuvTexHeight, HAL_PIXEL_FORMAT_YV12));
483d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis    ASSERT_EQ(NO_ERROR, native_window_set_usage(mANW.get(),
484d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis            GRALLOC_USAGE_SW_READ_OFTEN | GRALLOC_USAGE_SW_WRITE_OFTEN));
485d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis
486697526bc9e44ce61c88614f98387ae8bbf0a187eIliyan Malchev    ANativeWindowBuffer* anb;
487d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis    ASSERT_EQ(NO_ERROR, mANW->dequeueBuffer(mANW.get(), &anb));
488d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis    ASSERT_TRUE(anb != NULL);
489d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis
490d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis    sp<GraphicBuffer> buf(new GraphicBuffer(anb, false));
491d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis    ASSERT_EQ(NO_ERROR, mANW->lockBuffer(mANW.get(), buf->getNativeBuffer()));
492d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis
493d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis    // Fill the buffer with the a checkerboard pattern
494d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis    uint8_t* img = NULL;
495d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis    buf->lock(GRALLOC_USAGE_SW_WRITE_OFTEN, (void**)(&img));
496d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis    fillYV12Buffer(img, yuvTexWidth, yuvTexHeight, buf->getStride());
497d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis    buf->unlock();
498d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis    ASSERT_EQ(NO_ERROR, mANW->queueBuffer(mANW.get(), buf->getNativeBuffer()));
499d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis
500d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis    mST->updateTexImage();
501d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis
502d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis    glClearColor(0.2, 0.2, 0.2, 0.2);
503d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis    glClear(GL_COLOR_BUFFER_BIT);
504d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis
505d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis    drawTexture();
506d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis
507d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis    EXPECT_TRUE(checkPixel( 0,  0, 255, 127, 255, 255));
508d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis    EXPECT_TRUE(checkPixel(63,  0,   0, 133,   0, 255));
509d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis    EXPECT_TRUE(checkPixel(63, 63,   0, 133,   0, 255));
510d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis    EXPECT_TRUE(checkPixel( 0, 63, 255, 127, 255, 255));
511d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis
512d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis    EXPECT_TRUE(checkPixel(22, 44, 247,  70, 255, 255));
513d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis    EXPECT_TRUE(checkPixel(45, 52, 209,  32, 235, 255));
514d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis    EXPECT_TRUE(checkPixel(52, 51, 100, 255,  73, 255));
515d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis    EXPECT_TRUE(checkPixel( 7, 31, 155,   0, 118, 255));
516d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis    EXPECT_TRUE(checkPixel(31,  9, 148,  71, 110, 255));
517d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis    EXPECT_TRUE(checkPixel(29, 35, 255, 127, 255, 255));
518d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis    EXPECT_TRUE(checkPixel(36, 22, 155,  29,   0, 255));
519d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis}
520d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis
521d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis// XXX: This test is disabled because it it currently broken on all devices to
522d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis// which I have access.  Some of the checkPixel calls are not correct because
523d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis// I just copied them from the npot test above and haven't bothered to figure
524d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis// out the correct values.
525d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie GennisTEST_F(SurfaceTextureGLTest, DISABLED_TexturingFromCpuFilledYV12BufferPow2) {
526d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis    const int yuvTexWidth = 64;
527d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis    const int yuvTexHeight = 64;
528d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis
529d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis    ASSERT_EQ(NO_ERROR, native_window_set_buffers_geometry(mANW.get(),
530d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis            yuvTexWidth, yuvTexHeight, HAL_PIXEL_FORMAT_YV12));
531d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis    ASSERT_EQ(NO_ERROR, native_window_set_usage(mANW.get(),
532d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis            GRALLOC_USAGE_SW_READ_OFTEN | GRALLOC_USAGE_SW_WRITE_OFTEN));
533d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis
534697526bc9e44ce61c88614f98387ae8bbf0a187eIliyan Malchev    ANativeWindowBuffer* anb;
535d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis    ASSERT_EQ(NO_ERROR, mANW->dequeueBuffer(mANW.get(), &anb));
536d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis    ASSERT_TRUE(anb != NULL);
537d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis
538d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis    sp<GraphicBuffer> buf(new GraphicBuffer(anb, false));
539d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis    ASSERT_EQ(NO_ERROR, mANW->lockBuffer(mANW.get(), buf->getNativeBuffer()));
540d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis
541d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis    // Fill the buffer with the a checkerboard pattern
542d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis    uint8_t* img = NULL;
543d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis    buf->lock(GRALLOC_USAGE_SW_WRITE_OFTEN, (void**)(&img));
544d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis    fillYV12Buffer(img, yuvTexWidth, yuvTexHeight, buf->getStride());
545d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis    buf->unlock();
546d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis    ASSERT_EQ(NO_ERROR, mANW->queueBuffer(mANW.get(), buf->getNativeBuffer()));
547d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis
548d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis    mST->updateTexImage();
549d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis
550d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis    glClearColor(0.2, 0.2, 0.2, 0.2);
551d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis    glClear(GL_COLOR_BUFFER_BIT);
552d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis
553d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis    drawTexture();
554d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis
555d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis    EXPECT_TRUE(checkPixel( 0,  0, 255, 127, 255, 255));
556d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis    EXPECT_TRUE(checkPixel(63,  0,   0, 133,   0, 255));
557d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis    EXPECT_TRUE(checkPixel(63, 63,   0, 133,   0, 255));
558d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis    EXPECT_TRUE(checkPixel( 0, 63, 255, 127, 255, 255));
559d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis
560d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis    EXPECT_TRUE(checkPixel(22, 19, 247,  70, 255, 255));
561d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis    EXPECT_TRUE(checkPixel(45, 11, 209,  32, 235, 255));
562d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis    EXPECT_TRUE(checkPixel(52, 12, 100, 255,  73, 255));
563d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis    EXPECT_TRUE(checkPixel( 7, 32, 155,   0, 118, 255));
564d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis    EXPECT_TRUE(checkPixel(31, 54, 148,  71, 110, 255));
565d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis    EXPECT_TRUE(checkPixel(29, 28, 255, 127, 255, 255));
566d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis    EXPECT_TRUE(checkPixel(36, 41, 155,  29,   0, 255));
567d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis}
568d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis
569d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie GennisTEST_F(SurfaceTextureGLTest, TexturingFromCpuFilledYV12BufferWithCrop) {
570d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis    const int yuvTexWidth = 64;
571d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis    const int yuvTexHeight = 66;
572d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis
573d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis    ASSERT_EQ(NO_ERROR, native_window_set_buffers_geometry(mANW.get(),
574d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis            yuvTexWidth, yuvTexHeight, HAL_PIXEL_FORMAT_YV12));
575d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis    ASSERT_EQ(NO_ERROR, native_window_set_usage(mANW.get(),
576d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis            GRALLOC_USAGE_SW_READ_OFTEN | GRALLOC_USAGE_SW_WRITE_OFTEN));
577d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis
578d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis    android_native_rect_t crops[] = {
579d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis        {4, 6, 22, 36},
580d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis        {0, 6, 22, 36},
581d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis        {4, 0, 22, 36},
582d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis        {4, 6, yuvTexWidth, 36},
583d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis        {4, 6, 22, yuvTexHeight},
584d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis    };
585d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis
586d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis    for (int i = 0; i < 5; i++) {
587d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis        const android_native_rect_t& crop(crops[i]);
588d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis        SCOPED_TRACE(String8::format("rect{ l: %d t: %d r: %d b: %d }", crop.left,
589d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis                crop.top, crop.right, crop.bottom).string());
590d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis
591d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis        ASSERT_EQ(NO_ERROR, native_window_set_crop(mANW.get(), &crop));
592d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis
593697526bc9e44ce61c88614f98387ae8bbf0a187eIliyan Malchev        ANativeWindowBuffer* anb;
594d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis        ASSERT_EQ(NO_ERROR, mANW->dequeueBuffer(mANW.get(), &anb));
595d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis        ASSERT_TRUE(anb != NULL);
596d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis
597d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis        sp<GraphicBuffer> buf(new GraphicBuffer(anb, false));
598d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis        ASSERT_EQ(NO_ERROR, mANW->lockBuffer(mANW.get(), buf->getNativeBuffer()));
599d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis
600d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis        uint8_t* img = NULL;
601d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis        buf->lock(GRALLOC_USAGE_SW_WRITE_OFTEN, (void**)(&img));
602d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis        fillYV12BufferRect(img, yuvTexWidth, yuvTexHeight, buf->getStride(), crop);
603d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis        buf->unlock();
604d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis        ASSERT_EQ(NO_ERROR, mANW->queueBuffer(mANW.get(), buf->getNativeBuffer()));
605d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis
606d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis        mST->updateTexImage();
607d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis
608d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis        glClearColor(0.2, 0.2, 0.2, 0.2);
609d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis        glClear(GL_COLOR_BUFFER_BIT);
610d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis
611d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis        drawTexture();
612d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis
613d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis        EXPECT_TRUE(checkPixel( 0,  0,  82, 255,  35, 255));
614d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis        EXPECT_TRUE(checkPixel(63,  0,  82, 255,  35, 255));
615d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis        EXPECT_TRUE(checkPixel(63, 63,  82, 255,  35, 255));
616d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis        EXPECT_TRUE(checkPixel( 0, 63,  82, 255,  35, 255));
617d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis
618d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis        EXPECT_TRUE(checkPixel(25, 14,  82, 255,  35, 255));
619d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis        EXPECT_TRUE(checkPixel(35, 31,  82, 255,  35, 255));
620d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis        EXPECT_TRUE(checkPixel(57,  6,  82, 255,  35, 255));
621d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis        EXPECT_TRUE(checkPixel( 5, 42,  82, 255,  35, 255));
622d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis        EXPECT_TRUE(checkPixel(32, 33,  82, 255,  35, 255));
623d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis        EXPECT_TRUE(checkPixel(16, 26,  82, 255,  35, 255));
624d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis        EXPECT_TRUE(checkPixel(46, 51,  82, 255,  35, 255));
625d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis    }
626d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis}
627d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis
6285451d15ee209f29d64beea87583f7058dee69911Jamie Gennis/*
6295451d15ee209f29d64beea87583f7058dee69911Jamie Gennis * This test is for testing GL -> GL texture streaming via SurfaceTexture.  It
6305451d15ee209f29d64beea87583f7058dee69911Jamie Gennis * contains functionality to create a producer thread that will perform GL
6315451d15ee209f29d64beea87583f7058dee69911Jamie Gennis * rendering to an ANativeWindow that feeds frames to a SurfaceTexture.
6325451d15ee209f29d64beea87583f7058dee69911Jamie Gennis * Additionally it supports interlocking the producer and consumer threads so
6335451d15ee209f29d64beea87583f7058dee69911Jamie Gennis * that a specific sequence of calls can be deterministically created by the
6345451d15ee209f29d64beea87583f7058dee69911Jamie Gennis * test.
6355451d15ee209f29d64beea87583f7058dee69911Jamie Gennis *
6365451d15ee209f29d64beea87583f7058dee69911Jamie Gennis * The intended usage is as follows:
6375451d15ee209f29d64beea87583f7058dee69911Jamie Gennis *
6385451d15ee209f29d64beea87583f7058dee69911Jamie Gennis * TEST_F(...) {
6395451d15ee209f29d64beea87583f7058dee69911Jamie Gennis *     class PT : public ProducerThread {
6405451d15ee209f29d64beea87583f7058dee69911Jamie Gennis *         virtual void render() {
6415451d15ee209f29d64beea87583f7058dee69911Jamie Gennis *             ...
6425451d15ee209f29d64beea87583f7058dee69911Jamie Gennis *             swapBuffers();
6435451d15ee209f29d64beea87583f7058dee69911Jamie Gennis *         }
6445451d15ee209f29d64beea87583f7058dee69911Jamie Gennis *     };
6455451d15ee209f29d64beea87583f7058dee69911Jamie Gennis *
6465451d15ee209f29d64beea87583f7058dee69911Jamie Gennis *     runProducerThread(new PT());
6475451d15ee209f29d64beea87583f7058dee69911Jamie Gennis *
6485451d15ee209f29d64beea87583f7058dee69911Jamie Gennis *     // The order of these calls will vary from test to test and may include
6495451d15ee209f29d64beea87583f7058dee69911Jamie Gennis *     // multiple frames and additional operations (e.g. GL rendering from the
6505451d15ee209f29d64beea87583f7058dee69911Jamie Gennis *     // texture).
6515451d15ee209f29d64beea87583f7058dee69911Jamie Gennis *     fc->waitForFrame();
6525451d15ee209f29d64beea87583f7058dee69911Jamie Gennis *     mST->updateTexImage();
6535451d15ee209f29d64beea87583f7058dee69911Jamie Gennis *     fc->finishFrame();
6545451d15ee209f29d64beea87583f7058dee69911Jamie Gennis * }
6555451d15ee209f29d64beea87583f7058dee69911Jamie Gennis *
6565451d15ee209f29d64beea87583f7058dee69911Jamie Gennis */
6575451d15ee209f29d64beea87583f7058dee69911Jamie Gennisclass SurfaceTextureGLToGLTest : public SurfaceTextureGLTest {
6585451d15ee209f29d64beea87583f7058dee69911Jamie Gennisprotected:
6595451d15ee209f29d64beea87583f7058dee69911Jamie Gennis
6605451d15ee209f29d64beea87583f7058dee69911Jamie Gennis    // ProducerThread is an abstract base class to simplify the creation of
6615451d15ee209f29d64beea87583f7058dee69911Jamie Gennis    // OpenGL ES frame producer threads.
6625451d15ee209f29d64beea87583f7058dee69911Jamie Gennis    class ProducerThread : public Thread {
6635451d15ee209f29d64beea87583f7058dee69911Jamie Gennis    public:
6645451d15ee209f29d64beea87583f7058dee69911Jamie Gennis        virtual ~ProducerThread() {
6655451d15ee209f29d64beea87583f7058dee69911Jamie Gennis        }
6665451d15ee209f29d64beea87583f7058dee69911Jamie Gennis
6675451d15ee209f29d64beea87583f7058dee69911Jamie Gennis        void setEglObjects(EGLDisplay producerEglDisplay,
6685451d15ee209f29d64beea87583f7058dee69911Jamie Gennis                EGLSurface producerEglSurface,
6695451d15ee209f29d64beea87583f7058dee69911Jamie Gennis                EGLContext producerEglContext) {
6705451d15ee209f29d64beea87583f7058dee69911Jamie Gennis            mProducerEglDisplay = producerEglDisplay;
6715451d15ee209f29d64beea87583f7058dee69911Jamie Gennis            mProducerEglSurface = producerEglSurface;
6725451d15ee209f29d64beea87583f7058dee69911Jamie Gennis            mProducerEglContext = producerEglContext;
6735451d15ee209f29d64beea87583f7058dee69911Jamie Gennis        }
6745451d15ee209f29d64beea87583f7058dee69911Jamie Gennis
6755451d15ee209f29d64beea87583f7058dee69911Jamie Gennis        virtual bool threadLoop() {
6765451d15ee209f29d64beea87583f7058dee69911Jamie Gennis            eglMakeCurrent(mProducerEglDisplay, mProducerEglSurface,
6775451d15ee209f29d64beea87583f7058dee69911Jamie Gennis                    mProducerEglSurface, mProducerEglContext);
6785451d15ee209f29d64beea87583f7058dee69911Jamie Gennis            render();
6795451d15ee209f29d64beea87583f7058dee69911Jamie Gennis            eglMakeCurrent(mProducerEglDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE,
6805451d15ee209f29d64beea87583f7058dee69911Jamie Gennis                    EGL_NO_CONTEXT);
6815451d15ee209f29d64beea87583f7058dee69911Jamie Gennis            return false;
6825451d15ee209f29d64beea87583f7058dee69911Jamie Gennis        }
6835451d15ee209f29d64beea87583f7058dee69911Jamie Gennis
6845451d15ee209f29d64beea87583f7058dee69911Jamie Gennis    protected:
6855451d15ee209f29d64beea87583f7058dee69911Jamie Gennis        virtual void render() = 0;
6865451d15ee209f29d64beea87583f7058dee69911Jamie Gennis
6875451d15ee209f29d64beea87583f7058dee69911Jamie Gennis        void swapBuffers() {
6885451d15ee209f29d64beea87583f7058dee69911Jamie Gennis            eglSwapBuffers(mProducerEglDisplay, mProducerEglSurface);
6895451d15ee209f29d64beea87583f7058dee69911Jamie Gennis        }
6905451d15ee209f29d64beea87583f7058dee69911Jamie Gennis
6915451d15ee209f29d64beea87583f7058dee69911Jamie Gennis        EGLDisplay mProducerEglDisplay;
6925451d15ee209f29d64beea87583f7058dee69911Jamie Gennis        EGLSurface mProducerEglSurface;
6935451d15ee209f29d64beea87583f7058dee69911Jamie Gennis        EGLContext mProducerEglContext;
6945451d15ee209f29d64beea87583f7058dee69911Jamie Gennis    };
6955451d15ee209f29d64beea87583f7058dee69911Jamie Gennis
6965451d15ee209f29d64beea87583f7058dee69911Jamie Gennis    // FrameCondition is a utility class for interlocking between the producer
6975451d15ee209f29d64beea87583f7058dee69911Jamie Gennis    // and consumer threads.  The FrameCondition object should be created and
6985451d15ee209f29d64beea87583f7058dee69911Jamie Gennis    // destroyed in the consumer thread only.  The consumer thread should set
6995451d15ee209f29d64beea87583f7058dee69911Jamie Gennis    // the FrameCondition as the FrameAvailableListener of the SurfaceTexture,
7005451d15ee209f29d64beea87583f7058dee69911Jamie Gennis    // and should call both waitForFrame and finishFrame once for each expected
7015451d15ee209f29d64beea87583f7058dee69911Jamie Gennis    // frame.
7025451d15ee209f29d64beea87583f7058dee69911Jamie Gennis    //
7035451d15ee209f29d64beea87583f7058dee69911Jamie Gennis    // This interlocking relies on the fact that onFrameAvailable gets called
7045451d15ee209f29d64beea87583f7058dee69911Jamie Gennis    // synchronously from SurfaceTexture::queueBuffer.
7055451d15ee209f29d64beea87583f7058dee69911Jamie Gennis    class FrameCondition : public SurfaceTexture::FrameAvailableListener {
7065451d15ee209f29d64beea87583f7058dee69911Jamie Gennis    public:
7075451d15ee209f29d64beea87583f7058dee69911Jamie Gennis        // waitForFrame waits for the next frame to arrive.  This should be
7085451d15ee209f29d64beea87583f7058dee69911Jamie Gennis        // called from the consumer thread once for every frame expected by the
7095451d15ee209f29d64beea87583f7058dee69911Jamie Gennis        // test.
7105451d15ee209f29d64beea87583f7058dee69911Jamie Gennis        void waitForFrame() {
7115451d15ee209f29d64beea87583f7058dee69911Jamie Gennis            LOGV("+waitForFrame");
7125451d15ee209f29d64beea87583f7058dee69911Jamie Gennis            Mutex::Autolock lock(mMutex);
7135451d15ee209f29d64beea87583f7058dee69911Jamie Gennis            status_t result = mFrameAvailableCondition.wait(mMutex);
7145451d15ee209f29d64beea87583f7058dee69911Jamie Gennis            LOGV("-waitForFrame");
7155451d15ee209f29d64beea87583f7058dee69911Jamie Gennis        }
7165451d15ee209f29d64beea87583f7058dee69911Jamie Gennis
7175451d15ee209f29d64beea87583f7058dee69911Jamie Gennis        // Allow the producer to return from its swapBuffers call and continue
7185451d15ee209f29d64beea87583f7058dee69911Jamie Gennis        // on to produce the next frame.  This should be called by the consumer
7195451d15ee209f29d64beea87583f7058dee69911Jamie Gennis        // thread once for every frame expected by the test.
7205451d15ee209f29d64beea87583f7058dee69911Jamie Gennis        void finishFrame() {
7215451d15ee209f29d64beea87583f7058dee69911Jamie Gennis            LOGV("+finishFrame");
7225451d15ee209f29d64beea87583f7058dee69911Jamie Gennis            Mutex::Autolock lock(mMutex);
7235451d15ee209f29d64beea87583f7058dee69911Jamie Gennis            mFrameFinishCondition.signal();
7245451d15ee209f29d64beea87583f7058dee69911Jamie Gennis            LOGV("-finishFrame");
7255451d15ee209f29d64beea87583f7058dee69911Jamie Gennis        }
7265451d15ee209f29d64beea87583f7058dee69911Jamie Gennis
7275451d15ee209f29d64beea87583f7058dee69911Jamie Gennis        // This should be called by SurfaceTexture on the producer thread.
7285451d15ee209f29d64beea87583f7058dee69911Jamie Gennis        virtual void onFrameAvailable() {
7295451d15ee209f29d64beea87583f7058dee69911Jamie Gennis            LOGV("+onFrameAvailable");
7305451d15ee209f29d64beea87583f7058dee69911Jamie Gennis            Mutex::Autolock lock(mMutex);
7315451d15ee209f29d64beea87583f7058dee69911Jamie Gennis            mFrameAvailableCondition.signal();
7325451d15ee209f29d64beea87583f7058dee69911Jamie Gennis            mFrameFinishCondition.wait(mMutex);
7335451d15ee209f29d64beea87583f7058dee69911Jamie Gennis            LOGV("-onFrameAvailable");
7345451d15ee209f29d64beea87583f7058dee69911Jamie Gennis        }
7355451d15ee209f29d64beea87583f7058dee69911Jamie Gennis
7365451d15ee209f29d64beea87583f7058dee69911Jamie Gennis    protected:
7375451d15ee209f29d64beea87583f7058dee69911Jamie Gennis        Mutex mMutex;
7385451d15ee209f29d64beea87583f7058dee69911Jamie Gennis        Condition mFrameAvailableCondition;
7395451d15ee209f29d64beea87583f7058dee69911Jamie Gennis        Condition mFrameFinishCondition;
7405451d15ee209f29d64beea87583f7058dee69911Jamie Gennis    };
7415451d15ee209f29d64beea87583f7058dee69911Jamie Gennis
7425451d15ee209f29d64beea87583f7058dee69911Jamie Gennis    SurfaceTextureGLToGLTest():
7435451d15ee209f29d64beea87583f7058dee69911Jamie Gennis            mProducerEglSurface(EGL_NO_SURFACE),
7445451d15ee209f29d64beea87583f7058dee69911Jamie Gennis            mProducerEglContext(EGL_NO_CONTEXT) {
7455451d15ee209f29d64beea87583f7058dee69911Jamie Gennis    }
7465451d15ee209f29d64beea87583f7058dee69911Jamie Gennis
7475451d15ee209f29d64beea87583f7058dee69911Jamie Gennis    virtual void SetUp() {
7485451d15ee209f29d64beea87583f7058dee69911Jamie Gennis        SurfaceTextureGLTest::SetUp();
7495451d15ee209f29d64beea87583f7058dee69911Jamie Gennis
7505451d15ee209f29d64beea87583f7058dee69911Jamie Gennis        EGLConfig myConfig = {0};
7515451d15ee209f29d64beea87583f7058dee69911Jamie Gennis        EGLint numConfigs = 0;
7525451d15ee209f29d64beea87583f7058dee69911Jamie Gennis        EXPECT_TRUE(eglChooseConfig(mEglDisplay, getConfigAttribs(), &myConfig,
7535451d15ee209f29d64beea87583f7058dee69911Jamie Gennis                1, &numConfigs));
7545451d15ee209f29d64beea87583f7058dee69911Jamie Gennis        ASSERT_EQ(EGL_SUCCESS, eglGetError());
7555451d15ee209f29d64beea87583f7058dee69911Jamie Gennis
7565451d15ee209f29d64beea87583f7058dee69911Jamie Gennis        mProducerEglSurface = eglCreateWindowSurface(mEglDisplay, myConfig,
7575451d15ee209f29d64beea87583f7058dee69911Jamie Gennis                mANW.get(), NULL);
7585451d15ee209f29d64beea87583f7058dee69911Jamie Gennis        ASSERT_EQ(EGL_SUCCESS, eglGetError());
7595451d15ee209f29d64beea87583f7058dee69911Jamie Gennis        ASSERT_NE(EGL_NO_SURFACE, mProducerEglSurface);
7605451d15ee209f29d64beea87583f7058dee69911Jamie Gennis
7615451d15ee209f29d64beea87583f7058dee69911Jamie Gennis        mProducerEglContext = eglCreateContext(mEglDisplay, myConfig,
7625451d15ee209f29d64beea87583f7058dee69911Jamie Gennis                EGL_NO_CONTEXT, getContextAttribs());
7635451d15ee209f29d64beea87583f7058dee69911Jamie Gennis        ASSERT_EQ(EGL_SUCCESS, eglGetError());
7645451d15ee209f29d64beea87583f7058dee69911Jamie Gennis        ASSERT_NE(EGL_NO_CONTEXT, mProducerEglContext);
7655451d15ee209f29d64beea87583f7058dee69911Jamie Gennis
7665451d15ee209f29d64beea87583f7058dee69911Jamie Gennis        mFC = new FrameCondition();
7675451d15ee209f29d64beea87583f7058dee69911Jamie Gennis        mST->setFrameAvailableListener(mFC);
7685451d15ee209f29d64beea87583f7058dee69911Jamie Gennis    }
7695451d15ee209f29d64beea87583f7058dee69911Jamie Gennis
7705451d15ee209f29d64beea87583f7058dee69911Jamie Gennis    virtual void TearDown() {
7715451d15ee209f29d64beea87583f7058dee69911Jamie Gennis        if (mProducerThread != NULL) {
7725451d15ee209f29d64beea87583f7058dee69911Jamie Gennis            mProducerThread->requestExitAndWait();
7735451d15ee209f29d64beea87583f7058dee69911Jamie Gennis        }
7745451d15ee209f29d64beea87583f7058dee69911Jamie Gennis        if (mProducerEglContext != EGL_NO_CONTEXT) {
7755451d15ee209f29d64beea87583f7058dee69911Jamie Gennis            eglDestroyContext(mEglDisplay, mProducerEglContext);
7765451d15ee209f29d64beea87583f7058dee69911Jamie Gennis        }
7775451d15ee209f29d64beea87583f7058dee69911Jamie Gennis        if (mProducerEglSurface != EGL_NO_SURFACE) {
7785451d15ee209f29d64beea87583f7058dee69911Jamie Gennis            eglDestroySurface(mEglDisplay, mProducerEglSurface);
7795451d15ee209f29d64beea87583f7058dee69911Jamie Gennis        }
7805451d15ee209f29d64beea87583f7058dee69911Jamie Gennis        mProducerThread.clear();
7815451d15ee209f29d64beea87583f7058dee69911Jamie Gennis        mFC.clear();
7825451d15ee209f29d64beea87583f7058dee69911Jamie Gennis    }
7835451d15ee209f29d64beea87583f7058dee69911Jamie Gennis
7845451d15ee209f29d64beea87583f7058dee69911Jamie Gennis    void runProducerThread(const sp<ProducerThread> producerThread) {
7855451d15ee209f29d64beea87583f7058dee69911Jamie Gennis        ASSERT_TRUE(mProducerThread == NULL);
7865451d15ee209f29d64beea87583f7058dee69911Jamie Gennis        mProducerThread = producerThread;
7875451d15ee209f29d64beea87583f7058dee69911Jamie Gennis        producerThread->setEglObjects(mEglDisplay, mProducerEglSurface,
7885451d15ee209f29d64beea87583f7058dee69911Jamie Gennis                mProducerEglContext);
7895451d15ee209f29d64beea87583f7058dee69911Jamie Gennis        producerThread->run();
7905451d15ee209f29d64beea87583f7058dee69911Jamie Gennis    }
7915451d15ee209f29d64beea87583f7058dee69911Jamie Gennis
7925451d15ee209f29d64beea87583f7058dee69911Jamie Gennis    EGLSurface mProducerEglSurface;
7935451d15ee209f29d64beea87583f7058dee69911Jamie Gennis    EGLContext mProducerEglContext;
7945451d15ee209f29d64beea87583f7058dee69911Jamie Gennis    sp<ProducerThread> mProducerThread;
7955451d15ee209f29d64beea87583f7058dee69911Jamie Gennis    sp<FrameCondition> mFC;
7965451d15ee209f29d64beea87583f7058dee69911Jamie Gennis};
7975451d15ee209f29d64beea87583f7058dee69911Jamie Gennis
7985451d15ee209f29d64beea87583f7058dee69911Jamie Gennis// XXX: This test is disabled because it causes hangs on some devices.
7995451d15ee209f29d64beea87583f7058dee69911Jamie GennisTEST_F(SurfaceTextureGLToGLTest, DISABLED_UpdateTexImageBeforeFrameFinishedWorks) {
8005451d15ee209f29d64beea87583f7058dee69911Jamie Gennis    class PT : public ProducerThread {
8015451d15ee209f29d64beea87583f7058dee69911Jamie Gennis        virtual void render() {
8025451d15ee209f29d64beea87583f7058dee69911Jamie Gennis            glClearColor(0.0f, 1.0f, 0.0f, 1.0f);
8035451d15ee209f29d64beea87583f7058dee69911Jamie Gennis            glClear(GL_COLOR_BUFFER_BIT);
8045451d15ee209f29d64beea87583f7058dee69911Jamie Gennis            swapBuffers();
8055451d15ee209f29d64beea87583f7058dee69911Jamie Gennis        }
8065451d15ee209f29d64beea87583f7058dee69911Jamie Gennis    };
8075451d15ee209f29d64beea87583f7058dee69911Jamie Gennis
8085451d15ee209f29d64beea87583f7058dee69911Jamie Gennis    runProducerThread(new PT());
8095451d15ee209f29d64beea87583f7058dee69911Jamie Gennis
8105451d15ee209f29d64beea87583f7058dee69911Jamie Gennis    mFC->waitForFrame();
8115451d15ee209f29d64beea87583f7058dee69911Jamie Gennis    mST->updateTexImage();
8125451d15ee209f29d64beea87583f7058dee69911Jamie Gennis    mFC->finishFrame();
8135451d15ee209f29d64beea87583f7058dee69911Jamie Gennis
8145451d15ee209f29d64beea87583f7058dee69911Jamie Gennis    // TODO: Add frame verification once RGB TEX_EXTERNAL_OES is supported!
815d99c088f35960b7f0ef948c3bb948a99a800eba1Jamie Gennis}
8165451d15ee209f29d64beea87583f7058dee69911Jamie Gennis
8172510d9576ff2c529d584082aa1098480a73079e4Jamie Gennis// XXX: This test is disabled because it causes hangs on some devices.
8182510d9576ff2c529d584082aa1098480a73079e4Jamie GennisTEST_F(SurfaceTextureGLToGLTest, DISABLED_UpdateTexImageAfterFrameFinishedWorks) {
8195451d15ee209f29d64beea87583f7058dee69911Jamie Gennis    class PT : public ProducerThread {
8205451d15ee209f29d64beea87583f7058dee69911Jamie Gennis        virtual void render() {
8215451d15ee209f29d64beea87583f7058dee69911Jamie Gennis            glClearColor(0.0f, 1.0f, 0.0f, 1.0f);
8225451d15ee209f29d64beea87583f7058dee69911Jamie Gennis            glClear(GL_COLOR_BUFFER_BIT);
8235451d15ee209f29d64beea87583f7058dee69911Jamie Gennis            swapBuffers();
8245451d15ee209f29d64beea87583f7058dee69911Jamie Gennis        }
8255451d15ee209f29d64beea87583f7058dee69911Jamie Gennis    };
8265451d15ee209f29d64beea87583f7058dee69911Jamie Gennis
8275451d15ee209f29d64beea87583f7058dee69911Jamie Gennis    runProducerThread(new PT());
8285451d15ee209f29d64beea87583f7058dee69911Jamie Gennis
8295451d15ee209f29d64beea87583f7058dee69911Jamie Gennis    mFC->waitForFrame();
8305451d15ee209f29d64beea87583f7058dee69911Jamie Gennis    mFC->finishFrame();
8315451d15ee209f29d64beea87583f7058dee69911Jamie Gennis    mST->updateTexImage();
8325451d15ee209f29d64beea87583f7058dee69911Jamie Gennis
8335451d15ee209f29d64beea87583f7058dee69911Jamie Gennis    // TODO: Add frame verification once RGB TEX_EXTERNAL_OES is supported!
8345451d15ee209f29d64beea87583f7058dee69911Jamie Gennis}
8355451d15ee209f29d64beea87583f7058dee69911Jamie Gennis
8365451d15ee209f29d64beea87583f7058dee69911Jamie Gennis// XXX: This test is disabled because it causes hangs on some devices.
8375451d15ee209f29d64beea87583f7058dee69911Jamie GennisTEST_F(SurfaceTextureGLToGLTest, DISABLED_RepeatedUpdateTexImageBeforeFrameFinishedWorks) {
8385451d15ee209f29d64beea87583f7058dee69911Jamie Gennis    enum { NUM_ITERATIONS = 1024 };
8395451d15ee209f29d64beea87583f7058dee69911Jamie Gennis
8405451d15ee209f29d64beea87583f7058dee69911Jamie Gennis    class PT : public ProducerThread {
8415451d15ee209f29d64beea87583f7058dee69911Jamie Gennis        virtual void render() {
8425451d15ee209f29d64beea87583f7058dee69911Jamie Gennis            for (int i = 0; i < NUM_ITERATIONS; i++) {
8435451d15ee209f29d64beea87583f7058dee69911Jamie Gennis                glClearColor(0.0f, 1.0f, 0.0f, 1.0f);
8445451d15ee209f29d64beea87583f7058dee69911Jamie Gennis                glClear(GL_COLOR_BUFFER_BIT);
8455451d15ee209f29d64beea87583f7058dee69911Jamie Gennis                LOGV("+swapBuffers");
8465451d15ee209f29d64beea87583f7058dee69911Jamie Gennis                swapBuffers();
8475451d15ee209f29d64beea87583f7058dee69911Jamie Gennis                LOGV("-swapBuffers");
8485451d15ee209f29d64beea87583f7058dee69911Jamie Gennis            }
8495451d15ee209f29d64beea87583f7058dee69911Jamie Gennis        }
8505451d15ee209f29d64beea87583f7058dee69911Jamie Gennis    };
8515451d15ee209f29d64beea87583f7058dee69911Jamie Gennis
8525451d15ee209f29d64beea87583f7058dee69911Jamie Gennis    runProducerThread(new PT());
8535451d15ee209f29d64beea87583f7058dee69911Jamie Gennis
8545451d15ee209f29d64beea87583f7058dee69911Jamie Gennis    for (int i = 0; i < NUM_ITERATIONS; i++) {
8555451d15ee209f29d64beea87583f7058dee69911Jamie Gennis        mFC->waitForFrame();
8565451d15ee209f29d64beea87583f7058dee69911Jamie Gennis        LOGV("+updateTexImage");
8575451d15ee209f29d64beea87583f7058dee69911Jamie Gennis        mST->updateTexImage();
8585451d15ee209f29d64beea87583f7058dee69911Jamie Gennis        LOGV("-updateTexImage");
8595451d15ee209f29d64beea87583f7058dee69911Jamie Gennis        mFC->finishFrame();
8605451d15ee209f29d64beea87583f7058dee69911Jamie Gennis
8615451d15ee209f29d64beea87583f7058dee69911Jamie Gennis        // TODO: Add frame verification once RGB TEX_EXTERNAL_OES is supported!
8625451d15ee209f29d64beea87583f7058dee69911Jamie Gennis    }
8635451d15ee209f29d64beea87583f7058dee69911Jamie Gennis}
8645451d15ee209f29d64beea87583f7058dee69911Jamie Gennis
8655451d15ee209f29d64beea87583f7058dee69911Jamie Gennis// XXX: This test is disabled because it causes hangs on some devices.
8665451d15ee209f29d64beea87583f7058dee69911Jamie GennisTEST_F(SurfaceTextureGLToGLTest, DISABLED_RepeatedUpdateTexImageAfterFrameFinishedWorks) {
8675451d15ee209f29d64beea87583f7058dee69911Jamie Gennis    enum { NUM_ITERATIONS = 1024 };
8685451d15ee209f29d64beea87583f7058dee69911Jamie Gennis
8695451d15ee209f29d64beea87583f7058dee69911Jamie Gennis    class PT : public ProducerThread {
8705451d15ee209f29d64beea87583f7058dee69911Jamie Gennis        virtual void render() {
8715451d15ee209f29d64beea87583f7058dee69911Jamie Gennis            for (int i = 0; i < NUM_ITERATIONS; i++) {
8725451d15ee209f29d64beea87583f7058dee69911Jamie Gennis                glClearColor(0.0f, 1.0f, 0.0f, 1.0f);
8735451d15ee209f29d64beea87583f7058dee69911Jamie Gennis                glClear(GL_COLOR_BUFFER_BIT);
8745451d15ee209f29d64beea87583f7058dee69911Jamie Gennis                LOGV("+swapBuffers");
8755451d15ee209f29d64beea87583f7058dee69911Jamie Gennis                swapBuffers();
8765451d15ee209f29d64beea87583f7058dee69911Jamie Gennis                LOGV("-swapBuffers");
8775451d15ee209f29d64beea87583f7058dee69911Jamie Gennis            }
8785451d15ee209f29d64beea87583f7058dee69911Jamie Gennis        }
8795451d15ee209f29d64beea87583f7058dee69911Jamie Gennis    };
8805451d15ee209f29d64beea87583f7058dee69911Jamie Gennis
8815451d15ee209f29d64beea87583f7058dee69911Jamie Gennis    runProducerThread(new PT());
8825451d15ee209f29d64beea87583f7058dee69911Jamie Gennis
8835451d15ee209f29d64beea87583f7058dee69911Jamie Gennis    for (int i = 0; i < NUM_ITERATIONS; i++) {
8845451d15ee209f29d64beea87583f7058dee69911Jamie Gennis        mFC->waitForFrame();
8855451d15ee209f29d64beea87583f7058dee69911Jamie Gennis        mFC->finishFrame();
8865451d15ee209f29d64beea87583f7058dee69911Jamie Gennis        LOGV("+updateTexImage");
8875451d15ee209f29d64beea87583f7058dee69911Jamie Gennis        mST->updateTexImage();
8885451d15ee209f29d64beea87583f7058dee69911Jamie Gennis        LOGV("-updateTexImage");
8895451d15ee209f29d64beea87583f7058dee69911Jamie Gennis
8905451d15ee209f29d64beea87583f7058dee69911Jamie Gennis        // TODO: Add frame verification once RGB TEX_EXTERNAL_OES is supported!
8915451d15ee209f29d64beea87583f7058dee69911Jamie Gennis    }
8925451d15ee209f29d64beea87583f7058dee69911Jamie Gennis}
8935451d15ee209f29d64beea87583f7058dee69911Jamie Gennis
8945451d15ee209f29d64beea87583f7058dee69911Jamie Gennis} // namespace android
895