1baf412994612ae72a3db9698b1d216078297b48aChris Craik/*
2baf412994612ae72a3db9698b1d216078297b48aChris Craik * Copyright (C) 2015 The Android Open Source Project
3baf412994612ae72a3db9698b1d216078297b48aChris Craik *
4baf412994612ae72a3db9698b1d216078297b48aChris Craik * Licensed under the Apache License, Version 2.0 (the "License");
5baf412994612ae72a3db9698b1d216078297b48aChris Craik * you may not use this file except in compliance with the License.
6baf412994612ae72a3db9698b1d216078297b48aChris Craik * You may obtain a copy of the License at
7baf412994612ae72a3db9698b1d216078297b48aChris Craik *
8baf412994612ae72a3db9698b1d216078297b48aChris Craik *      http://www.apache.org/licenses/LICENSE-2.0
9baf412994612ae72a3db9698b1d216078297b48aChris Craik *
10baf412994612ae72a3db9698b1d216078297b48aChris Craik * Unless required by applicable law or agreed to in writing, software
11baf412994612ae72a3db9698b1d216078297b48aChris Craik * distributed under the License is distributed on an "AS IS" BASIS,
12baf412994612ae72a3db9698b1d216078297b48aChris Craik * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13baf412994612ae72a3db9698b1d216078297b48aChris Craik * See the License for the specific language governing permissions and
14baf412994612ae72a3db9698b1d216078297b48aChris Craik * limitations under the License.
15baf412994612ae72a3db9698b1d216078297b48aChris Craik */
16baf412994612ae72a3db9698b1d216078297b48aChris Craikpackage com.android.test.uibench.opengl;
17baf412994612ae72a3db9698b1d216078297b48aChris Craik
18baf412994612ae72a3db9698b1d216078297b48aChris Craikimport android.content.res.Resources;
19baf412994612ae72a3db9698b1d216078297b48aChris Craikimport android.graphics.Bitmap;
20baf412994612ae72a3db9698b1d216078297b48aChris Craikimport android.graphics.BitmapFactory;
21baf412994612ae72a3db9698b1d216078297b48aChris Craikimport android.graphics.SurfaceTexture;
22baf412994612ae72a3db9698b1d216078297b48aChris Craikimport android.opengl.GLUtils;
23baf412994612ae72a3db9698b1d216078297b48aChris Craikimport android.util.Log;
24baf412994612ae72a3db9698b1d216078297b48aChris Craik
25baf412994612ae72a3db9698b1d216078297b48aChris Craikimport com.android.test.uibench.R;
26baf412994612ae72a3db9698b1d216078297b48aChris Craik
27baf412994612ae72a3db9698b1d216078297b48aChris Craikimport java.nio.ByteBuffer;
28baf412994612ae72a3db9698b1d216078297b48aChris Craikimport java.nio.ByteOrder;
29baf412994612ae72a3db9698b1d216078297b48aChris Craikimport java.nio.FloatBuffer;
30baf412994612ae72a3db9698b1d216078297b48aChris Craik
31baf412994612ae72a3db9698b1d216078297b48aChris Craikimport javax.microedition.khronos.egl.EGL10;
32baf412994612ae72a3db9698b1d216078297b48aChris Craikimport javax.microedition.khronos.egl.EGLConfig;
33baf412994612ae72a3db9698b1d216078297b48aChris Craikimport javax.microedition.khronos.egl.EGLContext;
34baf412994612ae72a3db9698b1d216078297b48aChris Craikimport javax.microedition.khronos.egl.EGLDisplay;
35baf412994612ae72a3db9698b1d216078297b48aChris Craikimport javax.microedition.khronos.egl.EGLSurface;
36baf412994612ae72a3db9698b1d216078297b48aChris Craik
37baf412994612ae72a3db9698b1d216078297b48aChris Craikimport static android.opengl.GLES20.GL_CLAMP_TO_EDGE;
38baf412994612ae72a3db9698b1d216078297b48aChris Craikimport static android.opengl.GLES20.GL_COLOR_BUFFER_BIT;
39baf412994612ae72a3db9698b1d216078297b48aChris Craikimport static android.opengl.GLES20.GL_COMPILE_STATUS;
40baf412994612ae72a3db9698b1d216078297b48aChris Craikimport static android.opengl.GLES20.GL_FLOAT;
41baf412994612ae72a3db9698b1d216078297b48aChris Craikimport static android.opengl.GLES20.GL_FRAGMENT_SHADER;
42baf412994612ae72a3db9698b1d216078297b48aChris Craikimport static android.opengl.GLES20.GL_LINEAR;
43baf412994612ae72a3db9698b1d216078297b48aChris Craikimport static android.opengl.GLES20.GL_LINK_STATUS;
44baf412994612ae72a3db9698b1d216078297b48aChris Craikimport static android.opengl.GLES20.GL_NO_ERROR;
45baf412994612ae72a3db9698b1d216078297b48aChris Craikimport static android.opengl.GLES20.GL_RGBA;
46baf412994612ae72a3db9698b1d216078297b48aChris Craikimport static android.opengl.GLES20.GL_TEXTURE0;
47baf412994612ae72a3db9698b1d216078297b48aChris Craikimport static android.opengl.GLES20.GL_TEXTURE_2D;
48baf412994612ae72a3db9698b1d216078297b48aChris Craikimport static android.opengl.GLES20.GL_TEXTURE_MAG_FILTER;
49baf412994612ae72a3db9698b1d216078297b48aChris Craikimport static android.opengl.GLES20.GL_TEXTURE_MIN_FILTER;
50baf412994612ae72a3db9698b1d216078297b48aChris Craikimport static android.opengl.GLES20.GL_TEXTURE_WRAP_S;
51baf412994612ae72a3db9698b1d216078297b48aChris Craikimport static android.opengl.GLES20.GL_TEXTURE_WRAP_T;
52baf412994612ae72a3db9698b1d216078297b48aChris Craikimport static android.opengl.GLES20.GL_TRIANGLE_STRIP;
53baf412994612ae72a3db9698b1d216078297b48aChris Craikimport static android.opengl.GLES20.GL_TRUE;
54baf412994612ae72a3db9698b1d216078297b48aChris Craikimport static android.opengl.GLES20.GL_UNSIGNED_BYTE;
55baf412994612ae72a3db9698b1d216078297b48aChris Craikimport static android.opengl.GLES20.GL_VERTEX_SHADER;
56baf412994612ae72a3db9698b1d216078297b48aChris Craikimport static android.opengl.GLES20.glActiveTexture;
57baf412994612ae72a3db9698b1d216078297b48aChris Craikimport static android.opengl.GLES20.glAttachShader;
58baf412994612ae72a3db9698b1d216078297b48aChris Craikimport static android.opengl.GLES20.glBindTexture;
59baf412994612ae72a3db9698b1d216078297b48aChris Craikimport static android.opengl.GLES20.glClear;
60baf412994612ae72a3db9698b1d216078297b48aChris Craikimport static android.opengl.GLES20.glClearColor;
61baf412994612ae72a3db9698b1d216078297b48aChris Craikimport static android.opengl.GLES20.glCompileShader;
62baf412994612ae72a3db9698b1d216078297b48aChris Craikimport static android.opengl.GLES20.glCreateProgram;
63baf412994612ae72a3db9698b1d216078297b48aChris Craikimport static android.opengl.GLES20.glCreateShader;
64baf412994612ae72a3db9698b1d216078297b48aChris Craikimport static android.opengl.GLES20.glDeleteProgram;
65baf412994612ae72a3db9698b1d216078297b48aChris Craikimport static android.opengl.GLES20.glDeleteShader;
66baf412994612ae72a3db9698b1d216078297b48aChris Craikimport static android.opengl.GLES20.glDrawArrays;
67baf412994612ae72a3db9698b1d216078297b48aChris Craikimport static android.opengl.GLES20.glEnableVertexAttribArray;
68baf412994612ae72a3db9698b1d216078297b48aChris Craikimport static android.opengl.GLES20.glGenTextures;
69baf412994612ae72a3db9698b1d216078297b48aChris Craikimport static android.opengl.GLES20.glGetAttribLocation;
70baf412994612ae72a3db9698b1d216078297b48aChris Craikimport static android.opengl.GLES20.glGetError;
71baf412994612ae72a3db9698b1d216078297b48aChris Craikimport static android.opengl.GLES20.glGetProgramInfoLog;
72baf412994612ae72a3db9698b1d216078297b48aChris Craikimport static android.opengl.GLES20.glGetProgramiv;
73baf412994612ae72a3db9698b1d216078297b48aChris Craikimport static android.opengl.GLES20.glGetShaderInfoLog;
74baf412994612ae72a3db9698b1d216078297b48aChris Craikimport static android.opengl.GLES20.glGetShaderiv;
75baf412994612ae72a3db9698b1d216078297b48aChris Craikimport static android.opengl.GLES20.glGetUniformLocation;
76baf412994612ae72a3db9698b1d216078297b48aChris Craikimport static android.opengl.GLES20.glLinkProgram;
77baf412994612ae72a3db9698b1d216078297b48aChris Craikimport static android.opengl.GLES20.glShaderSource;
78baf412994612ae72a3db9698b1d216078297b48aChris Craikimport static android.opengl.GLES20.glTexParameteri;
79baf412994612ae72a3db9698b1d216078297b48aChris Craikimport static android.opengl.GLES20.glUniform1i;
80baf412994612ae72a3db9698b1d216078297b48aChris Craikimport static android.opengl.GLES20.glUseProgram;
81baf412994612ae72a3db9698b1d216078297b48aChris Craikimport static android.opengl.GLES20.glVertexAttribPointer;
82baf412994612ae72a3db9698b1d216078297b48aChris Craik
83baf412994612ae72a3db9698b1d216078297b48aChris Craikpublic class ImageFlipRenderThread extends Thread {
84baf412994612ae72a3db9698b1d216078297b48aChris Craik    public static final String LOG_TAG = "GLTextureView";
85baf412994612ae72a3db9698b1d216078297b48aChris Craik
86baf412994612ae72a3db9698b1d216078297b48aChris Craik    static final int EGL_CONTEXT_CLIENT_VERSION = 0x3098;
87baf412994612ae72a3db9698b1d216078297b48aChris Craik    static final int EGL_OPENGL_ES2_BIT = 4;
88baf412994612ae72a3db9698b1d216078297b48aChris Craik
89baf412994612ae72a3db9698b1d216078297b48aChris Craik    private volatile boolean mFinished;
90baf412994612ae72a3db9698b1d216078297b48aChris Craik
91baf412994612ae72a3db9698b1d216078297b48aChris Craik    private final Resources mResources;
92baf412994612ae72a3db9698b1d216078297b48aChris Craik    private final SurfaceTexture mSurface;
93baf412994612ae72a3db9698b1d216078297b48aChris Craik
94baf412994612ae72a3db9698b1d216078297b48aChris Craik    private EGL10 mEgl;
95baf412994612ae72a3db9698b1d216078297b48aChris Craik    private EGLDisplay mEglDisplay;
96baf412994612ae72a3db9698b1d216078297b48aChris Craik    private EGLConfig mEglConfig;
97baf412994612ae72a3db9698b1d216078297b48aChris Craik    private EGLContext mEglContext;
98baf412994612ae72a3db9698b1d216078297b48aChris Craik    private EGLSurface mEglSurface;
99baf412994612ae72a3db9698b1d216078297b48aChris Craik
100baf412994612ae72a3db9698b1d216078297b48aChris Craik    public ImageFlipRenderThread(Resources resources, SurfaceTexture surface) {
101baf412994612ae72a3db9698b1d216078297b48aChris Craik        mResources = resources;
102baf412994612ae72a3db9698b1d216078297b48aChris Craik        mSurface = surface;
103baf412994612ae72a3db9698b1d216078297b48aChris Craik    }
104baf412994612ae72a3db9698b1d216078297b48aChris Craik
105baf412994612ae72a3db9698b1d216078297b48aChris Craik    private static final String sSimpleVS =
106baf412994612ae72a3db9698b1d216078297b48aChris Craik            "attribute vec4 position;\n" +
107baf412994612ae72a3db9698b1d216078297b48aChris Craik                    "attribute vec2 texCoords;\n" +
108baf412994612ae72a3db9698b1d216078297b48aChris Craik                    "varying vec2 outTexCoords;\n" +
109baf412994612ae72a3db9698b1d216078297b48aChris Craik                    "\nvoid main(void) {\n" +
110baf412994612ae72a3db9698b1d216078297b48aChris Craik                    "    outTexCoords = texCoords;\n" +
111baf412994612ae72a3db9698b1d216078297b48aChris Craik                    "    gl_Position = position;\n" +
112baf412994612ae72a3db9698b1d216078297b48aChris Craik                    "}\n\n";
113baf412994612ae72a3db9698b1d216078297b48aChris Craik    private static final String sSimpleFS =
114baf412994612ae72a3db9698b1d216078297b48aChris Craik            "precision mediump float;\n\n" +
115baf412994612ae72a3db9698b1d216078297b48aChris Craik                    "varying vec2 outTexCoords;\n" +
116baf412994612ae72a3db9698b1d216078297b48aChris Craik                    "uniform sampler2D texture;\n" +
117baf412994612ae72a3db9698b1d216078297b48aChris Craik                    "\nvoid main(void) {\n" +
118baf412994612ae72a3db9698b1d216078297b48aChris Craik                    "    gl_FragColor = texture2D(texture, outTexCoords);\n" +
119baf412994612ae72a3db9698b1d216078297b48aChris Craik                    "}\n\n";
120baf412994612ae72a3db9698b1d216078297b48aChris Craik
121baf412994612ae72a3db9698b1d216078297b48aChris Craik    private static final int FLOAT_SIZE_BYTES = 4;
122baf412994612ae72a3db9698b1d216078297b48aChris Craik    private static final int TRIANGLE_VERTICES_DATA_STRIDE_BYTES = 5 * FLOAT_SIZE_BYTES;
123baf412994612ae72a3db9698b1d216078297b48aChris Craik    private static final int TRIANGLE_VERTICES_DATA_POS_OFFSET = 0;
124baf412994612ae72a3db9698b1d216078297b48aChris Craik    private static final int TRIANGLE_VERTICES_DATA_UV_OFFSET = 3;
125baf412994612ae72a3db9698b1d216078297b48aChris Craik    private final float[] mTriangleVerticesData = {
126baf412994612ae72a3db9698b1d216078297b48aChris Craik            // X, Y, Z, U, V
127baf412994612ae72a3db9698b1d216078297b48aChris Craik            -1.0f, -1.0f, 0.0f, 0.0f, 0.0f,
128baf412994612ae72a3db9698b1d216078297b48aChris Craik            1.0f, -1.0f, 0.0f, 1.0f, 0.0f,
129baf412994612ae72a3db9698b1d216078297b48aChris Craik            -1.0f, 1.0f, 0.0f, 0.0f, 1.0f,
130baf412994612ae72a3db9698b1d216078297b48aChris Craik            1.0f, 1.0f, 0.0f, 1.0f, 1.0f,
131baf412994612ae72a3db9698b1d216078297b48aChris Craik    };
132baf412994612ae72a3db9698b1d216078297b48aChris Craik
133baf412994612ae72a3db9698b1d216078297b48aChris Craik    @Override
134baf412994612ae72a3db9698b1d216078297b48aChris Craik    public void run() {
135baf412994612ae72a3db9698b1d216078297b48aChris Craik        initGL();
136baf412994612ae72a3db9698b1d216078297b48aChris Craik
137baf412994612ae72a3db9698b1d216078297b48aChris Craik        FloatBuffer triangleVertices = ByteBuffer.allocateDirect(mTriangleVerticesData.length
138baf412994612ae72a3db9698b1d216078297b48aChris Craik                * FLOAT_SIZE_BYTES).order(ByteOrder.nativeOrder()).asFloatBuffer();
139baf412994612ae72a3db9698b1d216078297b48aChris Craik        triangleVertices.put(mTriangleVerticesData).position(0);
140baf412994612ae72a3db9698b1d216078297b48aChris Craik
141baf412994612ae72a3db9698b1d216078297b48aChris Craik        int texture = loadTexture(R.drawable.large_photo);
142baf412994612ae72a3db9698b1d216078297b48aChris Craik        int program = buildProgram(sSimpleVS, sSimpleFS);
143baf412994612ae72a3db9698b1d216078297b48aChris Craik
144baf412994612ae72a3db9698b1d216078297b48aChris Craik        int attribPosition = glGetAttribLocation(program, "position");
145baf412994612ae72a3db9698b1d216078297b48aChris Craik        checkGlError();
146baf412994612ae72a3db9698b1d216078297b48aChris Craik
147baf412994612ae72a3db9698b1d216078297b48aChris Craik        int attribTexCoords = glGetAttribLocation(program, "texCoords");
148baf412994612ae72a3db9698b1d216078297b48aChris Craik        checkGlError();
149baf412994612ae72a3db9698b1d216078297b48aChris Craik
150baf412994612ae72a3db9698b1d216078297b48aChris Craik        int uniformTexture = glGetUniformLocation(program, "texture");
151baf412994612ae72a3db9698b1d216078297b48aChris Craik        checkGlError();
152baf412994612ae72a3db9698b1d216078297b48aChris Craik
153baf412994612ae72a3db9698b1d216078297b48aChris Craik        glBindTexture(GL_TEXTURE_2D, texture);
154baf412994612ae72a3db9698b1d216078297b48aChris Craik        checkGlError();
155baf412994612ae72a3db9698b1d216078297b48aChris Craik
156baf412994612ae72a3db9698b1d216078297b48aChris Craik        glUseProgram(program);
157baf412994612ae72a3db9698b1d216078297b48aChris Craik        checkGlError();
158baf412994612ae72a3db9698b1d216078297b48aChris Craik
159baf412994612ae72a3db9698b1d216078297b48aChris Craik        glEnableVertexAttribArray(attribPosition);
160baf412994612ae72a3db9698b1d216078297b48aChris Craik        checkGlError();
161baf412994612ae72a3db9698b1d216078297b48aChris Craik
162baf412994612ae72a3db9698b1d216078297b48aChris Craik        glEnableVertexAttribArray(attribTexCoords);
163baf412994612ae72a3db9698b1d216078297b48aChris Craik        checkGlError();
164baf412994612ae72a3db9698b1d216078297b48aChris Craik
165baf412994612ae72a3db9698b1d216078297b48aChris Craik        glUniform1i(uniformTexture, 0);
166baf412994612ae72a3db9698b1d216078297b48aChris Craik        checkGlError();
167baf412994612ae72a3db9698b1d216078297b48aChris Craik
168baf412994612ae72a3db9698b1d216078297b48aChris Craik        // drawQuad
169baf412994612ae72a3db9698b1d216078297b48aChris Craik        triangleVertices.position(TRIANGLE_VERTICES_DATA_POS_OFFSET);
170baf412994612ae72a3db9698b1d216078297b48aChris Craik        glVertexAttribPointer(attribPosition, 3, GL_FLOAT, false,
171baf412994612ae72a3db9698b1d216078297b48aChris Craik                TRIANGLE_VERTICES_DATA_STRIDE_BYTES, triangleVertices);
172baf412994612ae72a3db9698b1d216078297b48aChris Craik        checkGlError();
173baf412994612ae72a3db9698b1d216078297b48aChris Craik
174baf412994612ae72a3db9698b1d216078297b48aChris Craik        triangleVertices.position(TRIANGLE_VERTICES_DATA_UV_OFFSET);
175baf412994612ae72a3db9698b1d216078297b48aChris Craik        glVertexAttribPointer(attribTexCoords, 3, GL_FLOAT, false,
176baf412994612ae72a3db9698b1d216078297b48aChris Craik                TRIANGLE_VERTICES_DATA_STRIDE_BYTES, triangleVertices);
177baf412994612ae72a3db9698b1d216078297b48aChris Craik        checkGlError();
178baf412994612ae72a3db9698b1d216078297b48aChris Craik
179baf412994612ae72a3db9698b1d216078297b48aChris Craik        glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
180baf412994612ae72a3db9698b1d216078297b48aChris Craik        checkGlError();
181baf412994612ae72a3db9698b1d216078297b48aChris Craik
182baf412994612ae72a3db9698b1d216078297b48aChris Craik        while (!mFinished) {
183baf412994612ae72a3db9698b1d216078297b48aChris Craik            checkCurrent();
184baf412994612ae72a3db9698b1d216078297b48aChris Craik
185baf412994612ae72a3db9698b1d216078297b48aChris Craik            glClear(GL_COLOR_BUFFER_BIT);
186baf412994612ae72a3db9698b1d216078297b48aChris Craik            checkGlError();
187baf412994612ae72a3db9698b1d216078297b48aChris Craik
188baf412994612ae72a3db9698b1d216078297b48aChris Craik            glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
189baf412994612ae72a3db9698b1d216078297b48aChris Craik            checkGlError();
190baf412994612ae72a3db9698b1d216078297b48aChris Craik
191baf412994612ae72a3db9698b1d216078297b48aChris Craik            if (!mEgl.eglSwapBuffers(mEglDisplay, mEglSurface)) {
192baf412994612ae72a3db9698b1d216078297b48aChris Craik                throw new RuntimeException("Cannot swap buffers");
193baf412994612ae72a3db9698b1d216078297b48aChris Craik            }
194baf412994612ae72a3db9698b1d216078297b48aChris Craik            checkEglError();
195baf412994612ae72a3db9698b1d216078297b48aChris Craik
196baf412994612ae72a3db9698b1d216078297b48aChris Craik            try {
197baf412994612ae72a3db9698b1d216078297b48aChris Craik                Thread.sleep(2000);
198baf412994612ae72a3db9698b1d216078297b48aChris Craik            } catch (InterruptedException e) {
199baf412994612ae72a3db9698b1d216078297b48aChris Craik                // Ignore
200baf412994612ae72a3db9698b1d216078297b48aChris Craik            }
201baf412994612ae72a3db9698b1d216078297b48aChris Craik        }
202baf412994612ae72a3db9698b1d216078297b48aChris Craik
203baf412994612ae72a3db9698b1d216078297b48aChris Craik        finishGL();
204baf412994612ae72a3db9698b1d216078297b48aChris Craik    }
205baf412994612ae72a3db9698b1d216078297b48aChris Craik
206baf412994612ae72a3db9698b1d216078297b48aChris Craik    private int loadTexture(int resource) {
207baf412994612ae72a3db9698b1d216078297b48aChris Craik        int[] textures = new int[1];
208baf412994612ae72a3db9698b1d216078297b48aChris Craik
209baf412994612ae72a3db9698b1d216078297b48aChris Craik        glActiveTexture(GL_TEXTURE0);
210baf412994612ae72a3db9698b1d216078297b48aChris Craik        glGenTextures(1, textures, 0);
211baf412994612ae72a3db9698b1d216078297b48aChris Craik        checkGlError();
212baf412994612ae72a3db9698b1d216078297b48aChris Craik
213baf412994612ae72a3db9698b1d216078297b48aChris Craik        int texture = textures[0];
214baf412994612ae72a3db9698b1d216078297b48aChris Craik        glBindTexture(GL_TEXTURE_2D, texture);
215baf412994612ae72a3db9698b1d216078297b48aChris Craik        checkGlError();
216baf412994612ae72a3db9698b1d216078297b48aChris Craik
217baf412994612ae72a3db9698b1d216078297b48aChris Craik        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
218baf412994612ae72a3db9698b1d216078297b48aChris Craik        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
219baf412994612ae72a3db9698b1d216078297b48aChris Craik
220baf412994612ae72a3db9698b1d216078297b48aChris Craik        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
221baf412994612ae72a3db9698b1d216078297b48aChris Craik        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
222baf412994612ae72a3db9698b1d216078297b48aChris Craik
223baf412994612ae72a3db9698b1d216078297b48aChris Craik        Bitmap bitmap = BitmapFactory.decodeResource(mResources, resource);
224baf412994612ae72a3db9698b1d216078297b48aChris Craik
225baf412994612ae72a3db9698b1d216078297b48aChris Craik        GLUtils.texImage2D(GL_TEXTURE_2D, 0, GL_RGBA, bitmap, GL_UNSIGNED_BYTE, 0);
226baf412994612ae72a3db9698b1d216078297b48aChris Craik        checkGlError();
227baf412994612ae72a3db9698b1d216078297b48aChris Craik
228baf412994612ae72a3db9698b1d216078297b48aChris Craik        bitmap.recycle();
229baf412994612ae72a3db9698b1d216078297b48aChris Craik
230baf412994612ae72a3db9698b1d216078297b48aChris Craik        return texture;
231baf412994612ae72a3db9698b1d216078297b48aChris Craik    }
232baf412994612ae72a3db9698b1d216078297b48aChris Craik
233baf412994612ae72a3db9698b1d216078297b48aChris Craik    private static int buildProgram(String vertex, String fragment) {
234baf412994612ae72a3db9698b1d216078297b48aChris Craik        int vertexShader = buildShader(vertex, GL_VERTEX_SHADER);
235baf412994612ae72a3db9698b1d216078297b48aChris Craik        if (vertexShader == 0) return 0;
236baf412994612ae72a3db9698b1d216078297b48aChris Craik
237baf412994612ae72a3db9698b1d216078297b48aChris Craik        int fragmentShader = buildShader(fragment, GL_FRAGMENT_SHADER);
238baf412994612ae72a3db9698b1d216078297b48aChris Craik        if (fragmentShader == 0) return 0;
239baf412994612ae72a3db9698b1d216078297b48aChris Craik
240baf412994612ae72a3db9698b1d216078297b48aChris Craik        int program = glCreateProgram();
241baf412994612ae72a3db9698b1d216078297b48aChris Craik        glAttachShader(program, vertexShader);
242baf412994612ae72a3db9698b1d216078297b48aChris Craik        checkGlError();
243baf412994612ae72a3db9698b1d216078297b48aChris Craik
244baf412994612ae72a3db9698b1d216078297b48aChris Craik        glAttachShader(program, fragmentShader);
245baf412994612ae72a3db9698b1d216078297b48aChris Craik        checkGlError();
246baf412994612ae72a3db9698b1d216078297b48aChris Craik
247baf412994612ae72a3db9698b1d216078297b48aChris Craik        glLinkProgram(program);
248baf412994612ae72a3db9698b1d216078297b48aChris Craik        checkGlError();
249baf412994612ae72a3db9698b1d216078297b48aChris Craik
250baf412994612ae72a3db9698b1d216078297b48aChris Craik        int[] status = new int[1];
251baf412994612ae72a3db9698b1d216078297b48aChris Craik        glGetProgramiv(program, GL_LINK_STATUS, status, 0);
252baf412994612ae72a3db9698b1d216078297b48aChris Craik        if (status[0] != GL_TRUE) {
253baf412994612ae72a3db9698b1d216078297b48aChris Craik            String error = glGetProgramInfoLog(program);
254baf412994612ae72a3db9698b1d216078297b48aChris Craik            Log.d(LOG_TAG, "Error while linking program:\n" + error);
255baf412994612ae72a3db9698b1d216078297b48aChris Craik            glDeleteShader(vertexShader);
256baf412994612ae72a3db9698b1d216078297b48aChris Craik            glDeleteShader(fragmentShader);
257baf412994612ae72a3db9698b1d216078297b48aChris Craik            glDeleteProgram(program);
258baf412994612ae72a3db9698b1d216078297b48aChris Craik            return 0;
259baf412994612ae72a3db9698b1d216078297b48aChris Craik        }
260baf412994612ae72a3db9698b1d216078297b48aChris Craik
261baf412994612ae72a3db9698b1d216078297b48aChris Craik        return program;
262baf412994612ae72a3db9698b1d216078297b48aChris Craik    }
263baf412994612ae72a3db9698b1d216078297b48aChris Craik
264baf412994612ae72a3db9698b1d216078297b48aChris Craik    private static int buildShader(String source, int type) {
265baf412994612ae72a3db9698b1d216078297b48aChris Craik        int shader = glCreateShader(type);
266baf412994612ae72a3db9698b1d216078297b48aChris Craik
267baf412994612ae72a3db9698b1d216078297b48aChris Craik        glShaderSource(shader, source);
268baf412994612ae72a3db9698b1d216078297b48aChris Craik        checkGlError();
269baf412994612ae72a3db9698b1d216078297b48aChris Craik
270baf412994612ae72a3db9698b1d216078297b48aChris Craik        glCompileShader(shader);
271baf412994612ae72a3db9698b1d216078297b48aChris Craik        checkGlError();
272baf412994612ae72a3db9698b1d216078297b48aChris Craik
273baf412994612ae72a3db9698b1d216078297b48aChris Craik        int[] status = new int[1];
274baf412994612ae72a3db9698b1d216078297b48aChris Craik        glGetShaderiv(shader, GL_COMPILE_STATUS, status, 0);
275baf412994612ae72a3db9698b1d216078297b48aChris Craik        if (status[0] != GL_TRUE) {
276baf412994612ae72a3db9698b1d216078297b48aChris Craik            String error = glGetShaderInfoLog(shader);
277baf412994612ae72a3db9698b1d216078297b48aChris Craik            Log.d(LOG_TAG, "Error while compiling shader:\n" + error);
278baf412994612ae72a3db9698b1d216078297b48aChris Craik            glDeleteShader(shader);
279baf412994612ae72a3db9698b1d216078297b48aChris Craik            return 0;
280baf412994612ae72a3db9698b1d216078297b48aChris Craik        }
281baf412994612ae72a3db9698b1d216078297b48aChris Craik
282baf412994612ae72a3db9698b1d216078297b48aChris Craik        return shader;
283baf412994612ae72a3db9698b1d216078297b48aChris Craik    }
284baf412994612ae72a3db9698b1d216078297b48aChris Craik
285baf412994612ae72a3db9698b1d216078297b48aChris Craik    private void checkEglError() {
286baf412994612ae72a3db9698b1d216078297b48aChris Craik        int error = mEgl.eglGetError();
287baf412994612ae72a3db9698b1d216078297b48aChris Craik        if (error != EGL10.EGL_SUCCESS) {
288baf412994612ae72a3db9698b1d216078297b48aChris Craik            Log.w(LOG_TAG, "EGL error = 0x" + Integer.toHexString(error));
289baf412994612ae72a3db9698b1d216078297b48aChris Craik        }
290baf412994612ae72a3db9698b1d216078297b48aChris Craik    }
291baf412994612ae72a3db9698b1d216078297b48aChris Craik
292baf412994612ae72a3db9698b1d216078297b48aChris Craik    private static void checkGlError() {
293baf412994612ae72a3db9698b1d216078297b48aChris Craik        int error = glGetError();
294baf412994612ae72a3db9698b1d216078297b48aChris Craik        if (error != GL_NO_ERROR) {
295baf412994612ae72a3db9698b1d216078297b48aChris Craik            Log.w(LOG_TAG, "GL error = 0x" + Integer.toHexString(error));
296baf412994612ae72a3db9698b1d216078297b48aChris Craik        }
297baf412994612ae72a3db9698b1d216078297b48aChris Craik    }
298baf412994612ae72a3db9698b1d216078297b48aChris Craik
299baf412994612ae72a3db9698b1d216078297b48aChris Craik    private void finishGL() {
300baf412994612ae72a3db9698b1d216078297b48aChris Craik        mEgl.eglDestroyContext(mEglDisplay, mEglContext);
301baf412994612ae72a3db9698b1d216078297b48aChris Craik        mEgl.eglDestroySurface(mEglDisplay, mEglSurface);
302baf412994612ae72a3db9698b1d216078297b48aChris Craik    }
303baf412994612ae72a3db9698b1d216078297b48aChris Craik
304baf412994612ae72a3db9698b1d216078297b48aChris Craik    private void checkCurrent() {
305baf412994612ae72a3db9698b1d216078297b48aChris Craik        if (!mEglContext.equals(mEgl.eglGetCurrentContext()) ||
306baf412994612ae72a3db9698b1d216078297b48aChris Craik                !mEglSurface.equals(mEgl.eglGetCurrentSurface(EGL10.EGL_DRAW))) {
307baf412994612ae72a3db9698b1d216078297b48aChris Craik            if (!mEgl.eglMakeCurrent(mEglDisplay, mEglSurface, mEglSurface, mEglContext)) {
308baf412994612ae72a3db9698b1d216078297b48aChris Craik                throw new RuntimeException("eglMakeCurrent failed "
309baf412994612ae72a3db9698b1d216078297b48aChris Craik                        + GLUtils.getEGLErrorString(mEgl.eglGetError()));
310baf412994612ae72a3db9698b1d216078297b48aChris Craik            }
311baf412994612ae72a3db9698b1d216078297b48aChris Craik        }
312baf412994612ae72a3db9698b1d216078297b48aChris Craik    }
313baf412994612ae72a3db9698b1d216078297b48aChris Craik
314baf412994612ae72a3db9698b1d216078297b48aChris Craik    private void initGL() {
315baf412994612ae72a3db9698b1d216078297b48aChris Craik        mEgl = (EGL10) EGLContext.getEGL();
316baf412994612ae72a3db9698b1d216078297b48aChris Craik
317baf412994612ae72a3db9698b1d216078297b48aChris Craik        mEglDisplay = mEgl.eglGetDisplay(EGL10.EGL_DEFAULT_DISPLAY);
318baf412994612ae72a3db9698b1d216078297b48aChris Craik        if (mEglDisplay == EGL10.EGL_NO_DISPLAY) {
319baf412994612ae72a3db9698b1d216078297b48aChris Craik            throw new RuntimeException("eglGetDisplay failed "
320baf412994612ae72a3db9698b1d216078297b48aChris Craik                    + GLUtils.getEGLErrorString(mEgl.eglGetError()));
321baf412994612ae72a3db9698b1d216078297b48aChris Craik        }
322baf412994612ae72a3db9698b1d216078297b48aChris Craik
323baf412994612ae72a3db9698b1d216078297b48aChris Craik        int[] version = new int[2];
324baf412994612ae72a3db9698b1d216078297b48aChris Craik        if (!mEgl.eglInitialize(mEglDisplay, version)) {
325baf412994612ae72a3db9698b1d216078297b48aChris Craik            throw new RuntimeException("eglInitialize failed " +
326baf412994612ae72a3db9698b1d216078297b48aChris Craik                    GLUtils.getEGLErrorString(mEgl.eglGetError()));
327baf412994612ae72a3db9698b1d216078297b48aChris Craik        }
328baf412994612ae72a3db9698b1d216078297b48aChris Craik
329baf412994612ae72a3db9698b1d216078297b48aChris Craik        mEglConfig = chooseEglConfig();
330baf412994612ae72a3db9698b1d216078297b48aChris Craik        if (mEglConfig == null) {
331baf412994612ae72a3db9698b1d216078297b48aChris Craik            throw new RuntimeException("eglConfig not initialized");
332baf412994612ae72a3db9698b1d216078297b48aChris Craik        }
333baf412994612ae72a3db9698b1d216078297b48aChris Craik
334baf412994612ae72a3db9698b1d216078297b48aChris Craik        mEglContext = createContext(mEgl, mEglDisplay, mEglConfig);
335baf412994612ae72a3db9698b1d216078297b48aChris Craik
336baf412994612ae72a3db9698b1d216078297b48aChris Craik        mEglSurface = mEgl.eglCreateWindowSurface(mEglDisplay, mEglConfig, mSurface, null);
337baf412994612ae72a3db9698b1d216078297b48aChris Craik
338baf412994612ae72a3db9698b1d216078297b48aChris Craik        if (mEglSurface == null || mEglSurface == EGL10.EGL_NO_SURFACE) {
339baf412994612ae72a3db9698b1d216078297b48aChris Craik            int error = mEgl.eglGetError();
340baf412994612ae72a3db9698b1d216078297b48aChris Craik            if (error == EGL10.EGL_BAD_NATIVE_WINDOW) {
341baf412994612ae72a3db9698b1d216078297b48aChris Craik                Log.e(LOG_TAG, "createWindowSurface returned EGL_BAD_NATIVE_WINDOW.");
342baf412994612ae72a3db9698b1d216078297b48aChris Craik                return;
343baf412994612ae72a3db9698b1d216078297b48aChris Craik            }
344baf412994612ae72a3db9698b1d216078297b48aChris Craik            throw new RuntimeException("createWindowSurface failed "
345baf412994612ae72a3db9698b1d216078297b48aChris Craik                    + GLUtils.getEGLErrorString(error));
346baf412994612ae72a3db9698b1d216078297b48aChris Craik        }
347baf412994612ae72a3db9698b1d216078297b48aChris Craik
348baf412994612ae72a3db9698b1d216078297b48aChris Craik        if (!mEgl.eglMakeCurrent(mEglDisplay, mEglSurface, mEglSurface, mEglContext)) {
349baf412994612ae72a3db9698b1d216078297b48aChris Craik            throw new RuntimeException("eglMakeCurrent failed "
350baf412994612ae72a3db9698b1d216078297b48aChris Craik                    + GLUtils.getEGLErrorString(mEgl.eglGetError()));
351baf412994612ae72a3db9698b1d216078297b48aChris Craik        }
352baf412994612ae72a3db9698b1d216078297b48aChris Craik    }
353baf412994612ae72a3db9698b1d216078297b48aChris Craik
354baf412994612ae72a3db9698b1d216078297b48aChris Craik
355baf412994612ae72a3db9698b1d216078297b48aChris Craik    EGLContext createContext(EGL10 egl, EGLDisplay eglDisplay, EGLConfig eglConfig) {
356baf412994612ae72a3db9698b1d216078297b48aChris Craik        int[] attrib_list = {EGL_CONTEXT_CLIENT_VERSION, 2, EGL10.EGL_NONE};
357baf412994612ae72a3db9698b1d216078297b48aChris Craik        return egl.eglCreateContext(eglDisplay, eglConfig, EGL10.EGL_NO_CONTEXT, attrib_list);
358baf412994612ae72a3db9698b1d216078297b48aChris Craik    }
359baf412994612ae72a3db9698b1d216078297b48aChris Craik
360baf412994612ae72a3db9698b1d216078297b48aChris Craik    private EGLConfig chooseEglConfig() {
361baf412994612ae72a3db9698b1d216078297b48aChris Craik        int[] configsCount = new int[1];
362baf412994612ae72a3db9698b1d216078297b48aChris Craik        EGLConfig[] configs = new EGLConfig[1];
363baf412994612ae72a3db9698b1d216078297b48aChris Craik        int[] configSpec = getConfig();
364baf412994612ae72a3db9698b1d216078297b48aChris Craik        if (!mEgl.eglChooseConfig(mEglDisplay, configSpec, configs, 1, configsCount)) {
365baf412994612ae72a3db9698b1d216078297b48aChris Craik            throw new IllegalArgumentException("eglChooseConfig failed " +
366baf412994612ae72a3db9698b1d216078297b48aChris Craik                    GLUtils.getEGLErrorString(mEgl.eglGetError()));
367baf412994612ae72a3db9698b1d216078297b48aChris Craik        } else if (configsCount[0] > 0) {
368baf412994612ae72a3db9698b1d216078297b48aChris Craik            return configs[0];
369baf412994612ae72a3db9698b1d216078297b48aChris Craik        }
370baf412994612ae72a3db9698b1d216078297b48aChris Craik        return null;
371baf412994612ae72a3db9698b1d216078297b48aChris Craik    }
372baf412994612ae72a3db9698b1d216078297b48aChris Craik
373baf412994612ae72a3db9698b1d216078297b48aChris Craik    private static int[] getConfig() {
374baf412994612ae72a3db9698b1d216078297b48aChris Craik        return new int[]{
375baf412994612ae72a3db9698b1d216078297b48aChris Craik                EGL10.EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT,
376baf412994612ae72a3db9698b1d216078297b48aChris Craik                EGL10.EGL_RED_SIZE, 8,
377baf412994612ae72a3db9698b1d216078297b48aChris Craik                EGL10.EGL_GREEN_SIZE, 8,
378baf412994612ae72a3db9698b1d216078297b48aChris Craik                EGL10.EGL_BLUE_SIZE, 8,
379baf412994612ae72a3db9698b1d216078297b48aChris Craik                EGL10.EGL_ALPHA_SIZE, 8,
380baf412994612ae72a3db9698b1d216078297b48aChris Craik                EGL10.EGL_DEPTH_SIZE, 0,
381baf412994612ae72a3db9698b1d216078297b48aChris Craik                EGL10.EGL_STENCIL_SIZE, 0,
382baf412994612ae72a3db9698b1d216078297b48aChris Craik                EGL10.EGL_NONE
383baf412994612ae72a3db9698b1d216078297b48aChris Craik        };
384baf412994612ae72a3db9698b1d216078297b48aChris Craik    }
385baf412994612ae72a3db9698b1d216078297b48aChris Craik
386baf412994612ae72a3db9698b1d216078297b48aChris Craik    public void finish() {
387baf412994612ae72a3db9698b1d216078297b48aChris Craik        mFinished = true;
388baf412994612ae72a3db9698b1d216078297b48aChris Craik    }
389baf412994612ae72a3db9698b1d216078297b48aChris Craik}
390