GLTextureViewActivity.java revision 402f05530352f34d5320c2d23be43c274d97c4e2
18f0095cd33558e9cc8a440047908e53b68906f5fRomain Guy/*
28f0095cd33558e9cc8a440047908e53b68906f5fRomain Guy * Copyright (C) 2011 The Android Open Source Project
38f0095cd33558e9cc8a440047908e53b68906f5fRomain Guy *
48f0095cd33558e9cc8a440047908e53b68906f5fRomain Guy * Licensed under the Apache License, Version 2.0 (the "License");
58f0095cd33558e9cc8a440047908e53b68906f5fRomain Guy * you may not use this file except in compliance with the License.
68f0095cd33558e9cc8a440047908e53b68906f5fRomain Guy * You may obtain a copy of the License at
78f0095cd33558e9cc8a440047908e53b68906f5fRomain Guy *
88f0095cd33558e9cc8a440047908e53b68906f5fRomain Guy *      http://www.apache.org/licenses/LICENSE-2.0
98f0095cd33558e9cc8a440047908e53b68906f5fRomain Guy *
108f0095cd33558e9cc8a440047908e53b68906f5fRomain Guy * Unless required by applicable law or agreed to in writing, software
118f0095cd33558e9cc8a440047908e53b68906f5fRomain Guy * distributed under the License is distributed on an "AS IS" BASIS,
128f0095cd33558e9cc8a440047908e53b68906f5fRomain Guy * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
138f0095cd33558e9cc8a440047908e53b68906f5fRomain Guy * See the License for the specific language governing permissions and
148f0095cd33558e9cc8a440047908e53b68906f5fRomain Guy * limitations under the License.
158f0095cd33558e9cc8a440047908e53b68906f5fRomain Guy */
168f0095cd33558e9cc8a440047908e53b68906f5fRomain Guy
178f0095cd33558e9cc8a440047908e53b68906f5fRomain Guypackage com.android.test.hwui;
188f0095cd33558e9cc8a440047908e53b68906f5fRomain Guy
198f0095cd33558e9cc8a440047908e53b68906f5fRomain Guyimport android.animation.ObjectAnimator;
208f0095cd33558e9cc8a440047908e53b68906f5fRomain Guyimport android.animation.ValueAnimator;
218f0095cd33558e9cc8a440047908e53b68906f5fRomain Guyimport android.app.Activity;
22d0d07059943603c8d20ab9e2ee31ba5c7d477fbaRomain Guyimport android.content.res.Resources;
23d0d07059943603c8d20ab9e2ee31ba5c7d477fbaRomain Guyimport android.graphics.Bitmap;
24d0d07059943603c8d20ab9e2ee31ba5c7d477fbaRomain Guyimport android.graphics.BitmapFactory;
258f0095cd33558e9cc8a440047908e53b68906f5fRomain Guyimport android.graphics.SurfaceTexture;
26d0d07059943603c8d20ab9e2ee31ba5c7d477fbaRomain Guyimport android.opengl.GLUtils;
278f0095cd33558e9cc8a440047908e53b68906f5fRomain Guyimport android.os.Bundle;
288f0095cd33558e9cc8a440047908e53b68906f5fRomain Guyimport android.util.Log;
298f0095cd33558e9cc8a440047908e53b68906f5fRomain Guyimport android.view.Gravity;
308f0095cd33558e9cc8a440047908e53b68906f5fRomain Guyimport android.view.TextureView;
318f0095cd33558e9cc8a440047908e53b68906f5fRomain Guyimport android.view.View;
32d0d07059943603c8d20ab9e2ee31ba5c7d477fbaRomain Guyimport android.view.ViewGroup;
338f0095cd33558e9cc8a440047908e53b68906f5fRomain Guyimport android.widget.FrameLayout;
348f0095cd33558e9cc8a440047908e53b68906f5fRomain Guy
358f0095cd33558e9cc8a440047908e53b68906f5fRomain Guyimport javax.microedition.khronos.egl.EGL10;
368f0095cd33558e9cc8a440047908e53b68906f5fRomain Guyimport javax.microedition.khronos.egl.EGL11;
378f0095cd33558e9cc8a440047908e53b68906f5fRomain Guyimport javax.microedition.khronos.egl.EGLConfig;
388f0095cd33558e9cc8a440047908e53b68906f5fRomain Guyimport javax.microedition.khronos.egl.EGLContext;
398f0095cd33558e9cc8a440047908e53b68906f5fRomain Guyimport javax.microedition.khronos.egl.EGLDisplay;
408f0095cd33558e9cc8a440047908e53b68906f5fRomain Guyimport javax.microedition.khronos.egl.EGLSurface;
418f0095cd33558e9cc8a440047908e53b68906f5fRomain Guyimport javax.microedition.khronos.opengles.GL;
42ec19b4a764d512091a780fc93ced567dfbf80914Romain Guyimport java.io.BufferedOutputStream;
43ec19b4a764d512091a780fc93ced567dfbf80914Romain Guyimport java.io.FileNotFoundException;
44ec19b4a764d512091a780fc93ced567dfbf80914Romain Guyimport java.io.FileOutputStream;
45ec19b4a764d512091a780fc93ced567dfbf80914Romain Guyimport java.io.IOException;
46d0d07059943603c8d20ab9e2ee31ba5c7d477fbaRomain Guyimport java.nio.ByteBuffer;
47d0d07059943603c8d20ab9e2ee31ba5c7d477fbaRomain Guyimport java.nio.ByteOrder;
48d0d07059943603c8d20ab9e2ee31ba5c7d477fbaRomain Guyimport java.nio.FloatBuffer;
49d0d07059943603c8d20ab9e2ee31ba5c7d477fbaRomain Guy
50d0d07059943603c8d20ab9e2ee31ba5c7d477fbaRomain Guyimport static android.opengl.GLES20.*;
51d0d07059943603c8d20ab9e2ee31ba5c7d477fbaRomain Guy
528f0095cd33558e9cc8a440047908e53b68906f5fRomain Guy@SuppressWarnings({"UnusedDeclaration"})
538f0095cd33558e9cc8a440047908e53b68906f5fRomain Guypublic class GLTextureViewActivity extends Activity implements TextureView.SurfaceTextureListener {
548f0095cd33558e9cc8a440047908e53b68906f5fRomain Guy    private RenderThread mRenderThread;
558f0095cd33558e9cc8a440047908e53b68906f5fRomain Guy    private TextureView mTextureView;
568f0095cd33558e9cc8a440047908e53b68906f5fRomain Guy
578f0095cd33558e9cc8a440047908e53b68906f5fRomain Guy    @Override
588f0095cd33558e9cc8a440047908e53b68906f5fRomain Guy    protected void onCreate(Bundle savedInstanceState) {
598f0095cd33558e9cc8a440047908e53b68906f5fRomain Guy        super.onCreate(savedInstanceState);
608f0095cd33558e9cc8a440047908e53b68906f5fRomain Guy
618f0095cd33558e9cc8a440047908e53b68906f5fRomain Guy        mTextureView = new TextureView(this);
628f0095cd33558e9cc8a440047908e53b68906f5fRomain Guy        mTextureView.setSurfaceTextureListener(this);
63ec19b4a764d512091a780fc93ced567dfbf80914Romain Guy        mTextureView.setOnClickListener(new View.OnClickListener() {
64ec19b4a764d512091a780fc93ced567dfbf80914Romain Guy            @Override
65ec19b4a764d512091a780fc93ced567dfbf80914Romain Guy            public void onClick(View v) {
66cfacbeadffb5dccbf0434d9c05b19430a5237c3bRomain Guy                Bitmap b = mTextureView.getBitmap(800, 800);
67ec19b4a764d512091a780fc93ced567dfbf80914Romain Guy                BufferedOutputStream out = null;
68ec19b4a764d512091a780fc93ced567dfbf80914Romain Guy                try {
69ec19b4a764d512091a780fc93ced567dfbf80914Romain Guy                    out = new BufferedOutputStream(new FileOutputStream("/sdcard/out.png"));
70ec19b4a764d512091a780fc93ced567dfbf80914Romain Guy                    b.compress(Bitmap.CompressFormat.PNG, 100, out);
71ec19b4a764d512091a780fc93ced567dfbf80914Romain Guy                } catch (FileNotFoundException e) {
72ec19b4a764d512091a780fc93ced567dfbf80914Romain Guy                    e.printStackTrace();
73ec19b4a764d512091a780fc93ced567dfbf80914Romain Guy                } finally {
74ec19b4a764d512091a780fc93ced567dfbf80914Romain Guy                    if (out != null) try {
75ec19b4a764d512091a780fc93ced567dfbf80914Romain Guy                        out.close();
76ec19b4a764d512091a780fc93ced567dfbf80914Romain Guy                    } catch (IOException e) {
77ec19b4a764d512091a780fc93ced567dfbf80914Romain Guy                        e.printStackTrace();
78ec19b4a764d512091a780fc93ced567dfbf80914Romain Guy                    }
79ec19b4a764d512091a780fc93ced567dfbf80914Romain Guy                }
80ec19b4a764d512091a780fc93ced567dfbf80914Romain Guy            }
81ec19b4a764d512091a780fc93ced567dfbf80914Romain Guy        });
828f0095cd33558e9cc8a440047908e53b68906f5fRomain Guy
83d0d07059943603c8d20ab9e2ee31ba5c7d477fbaRomain Guy        setContentView(mTextureView, new FrameLayout.LayoutParams(
84d0d07059943603c8d20ab9e2ee31ba5c7d477fbaRomain Guy                ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT,
85d0d07059943603c8d20ab9e2ee31ba5c7d477fbaRomain Guy                Gravity.CENTER));
868f0095cd33558e9cc8a440047908e53b68906f5fRomain Guy    }
878f0095cd33558e9cc8a440047908e53b68906f5fRomain Guy
888f0095cd33558e9cc8a440047908e53b68906f5fRomain Guy    @Override
89451ce44a18e4c48f8a43aa250957f76967a35d31Romain Guy    public void onSurfaceTextureAvailable(SurfaceTexture surface, int width, int height) {
90d0d07059943603c8d20ab9e2ee31ba5c7d477fbaRomain Guy        mRenderThread = new RenderThread(getResources(), surface);
918f0095cd33558e9cc8a440047908e53b68906f5fRomain Guy        mRenderThread.start();
928f0095cd33558e9cc8a440047908e53b68906f5fRomain Guy
938f0095cd33558e9cc8a440047908e53b68906f5fRomain Guy        mTextureView.setCameraDistance(5000);
948f0095cd33558e9cc8a440047908e53b68906f5fRomain Guy
958f0095cd33558e9cc8a440047908e53b68906f5fRomain Guy        ObjectAnimator animator = ObjectAnimator.ofFloat(mTextureView, "rotationY", 0.0f, 360.0f);
968f0095cd33558e9cc8a440047908e53b68906f5fRomain Guy        animator.setRepeatMode(ObjectAnimator.REVERSE);
978f0095cd33558e9cc8a440047908e53b68906f5fRomain Guy        animator.setRepeatCount(ObjectAnimator.INFINITE);
988f0095cd33558e9cc8a440047908e53b68906f5fRomain Guy        animator.setDuration(4000);
998f0095cd33558e9cc8a440047908e53b68906f5fRomain Guy        animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
1008f0095cd33558e9cc8a440047908e53b68906f5fRomain Guy            @Override
1018f0095cd33558e9cc8a440047908e53b68906f5fRomain Guy            public void onAnimationUpdate(ValueAnimator animation) {
102ec19b4a764d512091a780fc93ced567dfbf80914Romain Guy                mTextureView.invalidate();
1038f0095cd33558e9cc8a440047908e53b68906f5fRomain Guy            }
1048f0095cd33558e9cc8a440047908e53b68906f5fRomain Guy        });
1058f0095cd33558e9cc8a440047908e53b68906f5fRomain Guy        animator.start();
1068f0095cd33558e9cc8a440047908e53b68906f5fRomain Guy    }
1078f0095cd33558e9cc8a440047908e53b68906f5fRomain Guy
1088f0095cd33558e9cc8a440047908e53b68906f5fRomain Guy    @Override
1098f0095cd33558e9cc8a440047908e53b68906f5fRomain Guy    public void onSurfaceTextureSizeChanged(SurfaceTexture surface, int width, int height) {
1108f0095cd33558e9cc8a440047908e53b68906f5fRomain Guy    }
1118f0095cd33558e9cc8a440047908e53b68906f5fRomain Guy
112451ce44a18e4c48f8a43aa250957f76967a35d31Romain Guy    @Override
113402f05530352f34d5320c2d23be43c274d97c4e2Grace Kloba    public boolean onSurfaceTextureDestroyed(SurfaceTexture surface) {
114451ce44a18e4c48f8a43aa250957f76967a35d31Romain Guy        mRenderThread.finish();
115451ce44a18e4c48f8a43aa250957f76967a35d31Romain Guy        try {
116451ce44a18e4c48f8a43aa250957f76967a35d31Romain Guy            mRenderThread.join();
117451ce44a18e4c48f8a43aa250957f76967a35d31Romain Guy        } catch (InterruptedException e) {
118451ce44a18e4c48f8a43aa250957f76967a35d31Romain Guy            Log.e(RenderThread.LOG_TAG, "Could not wait for render thread");
119451ce44a18e4c48f8a43aa250957f76967a35d31Romain Guy        }
120402f05530352f34d5320c2d23be43c274d97c4e2Grace Kloba        return true;
121451ce44a18e4c48f8a43aa250957f76967a35d31Romain Guy    }
122451ce44a18e4c48f8a43aa250957f76967a35d31Romain Guy
123cf559377b750271472aa0a717bf3b7d34abc0b39Grace Kloba    @Override
124cf559377b750271472aa0a717bf3b7d34abc0b39Grace Kloba    public void onSurfaceTextureUpdated(SurfaceTexture surface) {
125cf559377b750271472aa0a717bf3b7d34abc0b39Grace Kloba    }
126cf559377b750271472aa0a717bf3b7d34abc0b39Grace Kloba
1278f0095cd33558e9cc8a440047908e53b68906f5fRomain Guy    private static class RenderThread extends Thread {
1288f0095cd33558e9cc8a440047908e53b68906f5fRomain Guy        private static final String LOG_TAG = "GLTextureView";
1298f0095cd33558e9cc8a440047908e53b68906f5fRomain Guy
1308f0095cd33558e9cc8a440047908e53b68906f5fRomain Guy        static final int EGL_CONTEXT_CLIENT_VERSION = 0x3098;
1318f0095cd33558e9cc8a440047908e53b68906f5fRomain Guy        static final int EGL_OPENGL_ES2_BIT = 4;
1328f0095cd33558e9cc8a440047908e53b68906f5fRomain Guy
1338f0095cd33558e9cc8a440047908e53b68906f5fRomain Guy        private volatile boolean mFinished;
1348f0095cd33558e9cc8a440047908e53b68906f5fRomain Guy
135d0d07059943603c8d20ab9e2ee31ba5c7d477fbaRomain Guy        private final Resources mResources;
136d0d07059943603c8d20ab9e2ee31ba5c7d477fbaRomain Guy        private final SurfaceTexture mSurface;
1378f0095cd33558e9cc8a440047908e53b68906f5fRomain Guy
1388f0095cd33558e9cc8a440047908e53b68906f5fRomain Guy        private EGL10 mEgl;
1398f0095cd33558e9cc8a440047908e53b68906f5fRomain Guy        private EGLDisplay mEglDisplay;
1408f0095cd33558e9cc8a440047908e53b68906f5fRomain Guy        private EGLConfig mEglConfig;
1418f0095cd33558e9cc8a440047908e53b68906f5fRomain Guy        private EGLContext mEglContext;
1428f0095cd33558e9cc8a440047908e53b68906f5fRomain Guy        private EGLSurface mEglSurface;
1438f0095cd33558e9cc8a440047908e53b68906f5fRomain Guy        private GL mGL;
1448f0095cd33558e9cc8a440047908e53b68906f5fRomain Guy
145d0d07059943603c8d20ab9e2ee31ba5c7d477fbaRomain Guy        RenderThread(Resources resources, SurfaceTexture surface) {
146d0d07059943603c8d20ab9e2ee31ba5c7d477fbaRomain Guy            mResources = resources;
1478f0095cd33558e9cc8a440047908e53b68906f5fRomain Guy            mSurface = surface;
1488f0095cd33558e9cc8a440047908e53b68906f5fRomain Guy        }
1498f0095cd33558e9cc8a440047908e53b68906f5fRomain Guy
150d0d07059943603c8d20ab9e2ee31ba5c7d477fbaRomain Guy        private static final String sSimpleVS =
151d0d07059943603c8d20ab9e2ee31ba5c7d477fbaRomain Guy                "attribute vec4 position;\n" +
152d0d07059943603c8d20ab9e2ee31ba5c7d477fbaRomain Guy                "attribute vec2 texCoords;\n" +
153d0d07059943603c8d20ab9e2ee31ba5c7d477fbaRomain Guy                "varying vec2 outTexCoords;\n" +
154d0d07059943603c8d20ab9e2ee31ba5c7d477fbaRomain Guy                "\nvoid main(void) {\n" +
155d0d07059943603c8d20ab9e2ee31ba5c7d477fbaRomain Guy                "    outTexCoords = texCoords;\n" +
156d0d07059943603c8d20ab9e2ee31ba5c7d477fbaRomain Guy                "    gl_Position = position;\n" +
157d0d07059943603c8d20ab9e2ee31ba5c7d477fbaRomain Guy                "}\n\n";
158d0d07059943603c8d20ab9e2ee31ba5c7d477fbaRomain Guy        private static final String sSimpleFS =
159d0d07059943603c8d20ab9e2ee31ba5c7d477fbaRomain Guy                "precision mediump float;\n\n" +
160d0d07059943603c8d20ab9e2ee31ba5c7d477fbaRomain Guy                "varying vec2 outTexCoords;\n" +
161d0d07059943603c8d20ab9e2ee31ba5c7d477fbaRomain Guy                "uniform sampler2D texture;\n" +
162d0d07059943603c8d20ab9e2ee31ba5c7d477fbaRomain Guy                "\nvoid main(void) {\n" +
163d0d07059943603c8d20ab9e2ee31ba5c7d477fbaRomain Guy                "    gl_FragColor = texture2D(texture, outTexCoords);\n" +
164d0d07059943603c8d20ab9e2ee31ba5c7d477fbaRomain Guy                "}\n\n";
165d0d07059943603c8d20ab9e2ee31ba5c7d477fbaRomain Guy
166d0d07059943603c8d20ab9e2ee31ba5c7d477fbaRomain Guy        private static final int FLOAT_SIZE_BYTES = 4;
167d0d07059943603c8d20ab9e2ee31ba5c7d477fbaRomain Guy        private static final int TRIANGLE_VERTICES_DATA_STRIDE_BYTES = 5 * FLOAT_SIZE_BYTES;
168d0d07059943603c8d20ab9e2ee31ba5c7d477fbaRomain Guy        private static final int TRIANGLE_VERTICES_DATA_POS_OFFSET = 0;
169d0d07059943603c8d20ab9e2ee31ba5c7d477fbaRomain Guy        private static final int TRIANGLE_VERTICES_DATA_UV_OFFSET = 3;
170d0d07059943603c8d20ab9e2ee31ba5c7d477fbaRomain Guy        private final float[] mTriangleVerticesData = {
171d0d07059943603c8d20ab9e2ee31ba5c7d477fbaRomain Guy                // X, Y, Z, U, V
172d0d07059943603c8d20ab9e2ee31ba5c7d477fbaRomain Guy                -1.0f, -1.0f, 0, 0.f, 0.f,
173d0d07059943603c8d20ab9e2ee31ba5c7d477fbaRomain Guy                1.0f, -1.0f, 0, 1.f, 0.f,
174d0d07059943603c8d20ab9e2ee31ba5c7d477fbaRomain Guy                -1.0f,  1.0f, 0, 0.f, 1.f,
175d0d07059943603c8d20ab9e2ee31ba5c7d477fbaRomain Guy                1.0f,   1.0f, 0, 1.f, 1.f,
176d0d07059943603c8d20ab9e2ee31ba5c7d477fbaRomain Guy        };
177d0d07059943603c8d20ab9e2ee31ba5c7d477fbaRomain Guy
1788f0095cd33558e9cc8a440047908e53b68906f5fRomain Guy        @Override
1798f0095cd33558e9cc8a440047908e53b68906f5fRomain Guy        public void run() {
1808f0095cd33558e9cc8a440047908e53b68906f5fRomain Guy            initGL();
181d0d07059943603c8d20ab9e2ee31ba5c7d477fbaRomain Guy
182d0d07059943603c8d20ab9e2ee31ba5c7d477fbaRomain Guy            FloatBuffer triangleVertices = ByteBuffer.allocateDirect(mTriangleVerticesData.length
183d0d07059943603c8d20ab9e2ee31ba5c7d477fbaRomain Guy                    * FLOAT_SIZE_BYTES).order(ByteOrder.nativeOrder()).asFloatBuffer();
184d0d07059943603c8d20ab9e2ee31ba5c7d477fbaRomain Guy            triangleVertices.put(mTriangleVerticesData).position(0);
185d0d07059943603c8d20ab9e2ee31ba5c7d477fbaRomain Guy
186d0d07059943603c8d20ab9e2ee31ba5c7d477fbaRomain Guy            int texture = loadTexture(R.drawable.large_photo);
187d0d07059943603c8d20ab9e2ee31ba5c7d477fbaRomain Guy            int program = buildProgram(sSimpleVS, sSimpleFS);
188d0d07059943603c8d20ab9e2ee31ba5c7d477fbaRomain Guy
189d0d07059943603c8d20ab9e2ee31ba5c7d477fbaRomain Guy            int attribPosition = glGetAttribLocation(program, "position");
190d0d07059943603c8d20ab9e2ee31ba5c7d477fbaRomain Guy            checkGlError();
191d0d07059943603c8d20ab9e2ee31ba5c7d477fbaRomain Guy
192d0d07059943603c8d20ab9e2ee31ba5c7d477fbaRomain Guy            int attribTexCoords = glGetAttribLocation(program, "texCoords");
193d0d07059943603c8d20ab9e2ee31ba5c7d477fbaRomain Guy            checkGlError();
194d0d07059943603c8d20ab9e2ee31ba5c7d477fbaRomain Guy
195d0d07059943603c8d20ab9e2ee31ba5c7d477fbaRomain Guy            int uniformTexture = glGetUniformLocation(program, "texture");
196d0d07059943603c8d20ab9e2ee31ba5c7d477fbaRomain Guy            checkGlError();
197d0d07059943603c8d20ab9e2ee31ba5c7d477fbaRomain Guy
198d0d07059943603c8d20ab9e2ee31ba5c7d477fbaRomain Guy            glBindTexture(GL_TEXTURE_2D, texture);
199d0d07059943603c8d20ab9e2ee31ba5c7d477fbaRomain Guy            checkGlError();
200d0d07059943603c8d20ab9e2ee31ba5c7d477fbaRomain Guy
201d0d07059943603c8d20ab9e2ee31ba5c7d477fbaRomain Guy            glUseProgram(program);
202d0d07059943603c8d20ab9e2ee31ba5c7d477fbaRomain Guy            checkGlError();
2038f0095cd33558e9cc8a440047908e53b68906f5fRomain Guy
204d0d07059943603c8d20ab9e2ee31ba5c7d477fbaRomain Guy            glEnableVertexAttribArray(attribPosition);
205d0d07059943603c8d20ab9e2ee31ba5c7d477fbaRomain Guy            checkGlError();
206d0d07059943603c8d20ab9e2ee31ba5c7d477fbaRomain Guy
207d0d07059943603c8d20ab9e2ee31ba5c7d477fbaRomain Guy            glEnableVertexAttribArray(attribTexCoords);
208d0d07059943603c8d20ab9e2ee31ba5c7d477fbaRomain Guy            checkGlError();
209d0d07059943603c8d20ab9e2ee31ba5c7d477fbaRomain Guy
210d0d07059943603c8d20ab9e2ee31ba5c7d477fbaRomain Guy            glUniform1i(texture, 0);
211d0d07059943603c8d20ab9e2ee31ba5c7d477fbaRomain Guy            checkGlError();
212d0d07059943603c8d20ab9e2ee31ba5c7d477fbaRomain Guy
2138f0095cd33558e9cc8a440047908e53b68906f5fRomain Guy            while (!mFinished) {
2148f0095cd33558e9cc8a440047908e53b68906f5fRomain Guy                checkCurrent();
2158f0095cd33558e9cc8a440047908e53b68906f5fRomain Guy
216451ce44a18e4c48f8a43aa250957f76967a35d31Romain Guy                Log.d(LOG_TAG, "Rendering frame");
217451ce44a18e4c48f8a43aa250957f76967a35d31Romain Guy
218d0d07059943603c8d20ab9e2ee31ba5c7d477fbaRomain Guy                glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
219451ce44a18e4c48f8a43aa250957f76967a35d31Romain Guy                checkGlError();
2208f0095cd33558e9cc8a440047908e53b68906f5fRomain Guy
221d0d07059943603c8d20ab9e2ee31ba5c7d477fbaRomain Guy                glClear(GL_COLOR_BUFFER_BIT);
222451ce44a18e4c48f8a43aa250957f76967a35d31Romain Guy                checkGlError();
2238f0095cd33558e9cc8a440047908e53b68906f5fRomain Guy
224d0d07059943603c8d20ab9e2ee31ba5c7d477fbaRomain Guy                // drawQuad
225d0d07059943603c8d20ab9e2ee31ba5c7d477fbaRomain Guy                triangleVertices.position(TRIANGLE_VERTICES_DATA_POS_OFFSET);
226d0d07059943603c8d20ab9e2ee31ba5c7d477fbaRomain Guy                glVertexAttribPointer(attribPosition, 3, GL_FLOAT, false,
227d0d07059943603c8d20ab9e2ee31ba5c7d477fbaRomain Guy                        TRIANGLE_VERTICES_DATA_STRIDE_BYTES, triangleVertices);
228d0d07059943603c8d20ab9e2ee31ba5c7d477fbaRomain Guy
229d0d07059943603c8d20ab9e2ee31ba5c7d477fbaRomain Guy                triangleVertices.position(TRIANGLE_VERTICES_DATA_UV_OFFSET);
230d0d07059943603c8d20ab9e2ee31ba5c7d477fbaRomain Guy                glVertexAttribPointer(attribTexCoords, 3, GL_FLOAT, false,
231d0d07059943603c8d20ab9e2ee31ba5c7d477fbaRomain Guy                        TRIANGLE_VERTICES_DATA_STRIDE_BYTES, triangleVertices);
232d0d07059943603c8d20ab9e2ee31ba5c7d477fbaRomain Guy
233d0d07059943603c8d20ab9e2ee31ba5c7d477fbaRomain Guy                glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
234d0d07059943603c8d20ab9e2ee31ba5c7d477fbaRomain Guy
2358f0095cd33558e9cc8a440047908e53b68906f5fRomain Guy                if (!mEgl.eglSwapBuffers(mEglDisplay, mEglSurface)) {
2368f0095cd33558e9cc8a440047908e53b68906f5fRomain Guy                    throw new RuntimeException("Cannot swap buffers");
2378f0095cd33558e9cc8a440047908e53b68906f5fRomain Guy                }
238451ce44a18e4c48f8a43aa250957f76967a35d31Romain Guy                checkEglError();
239451ce44a18e4c48f8a43aa250957f76967a35d31Romain Guy
2408f0095cd33558e9cc8a440047908e53b68906f5fRomain Guy                try {
2418f0095cd33558e9cc8a440047908e53b68906f5fRomain Guy                    Thread.sleep(20);
2428f0095cd33558e9cc8a440047908e53b68906f5fRomain Guy                } catch (InterruptedException e) {
2438f0095cd33558e9cc8a440047908e53b68906f5fRomain Guy                    // Ignore
2448f0095cd33558e9cc8a440047908e53b68906f5fRomain Guy                }
2458f0095cd33558e9cc8a440047908e53b68906f5fRomain Guy            }
2468f0095cd33558e9cc8a440047908e53b68906f5fRomain Guy
2478f0095cd33558e9cc8a440047908e53b68906f5fRomain Guy            finishGL();
2488f0095cd33558e9cc8a440047908e53b68906f5fRomain Guy        }
2498f0095cd33558e9cc8a440047908e53b68906f5fRomain Guy
250d0d07059943603c8d20ab9e2ee31ba5c7d477fbaRomain Guy        private int loadTexture(int resource) {
251d0d07059943603c8d20ab9e2ee31ba5c7d477fbaRomain Guy            int[] textures = new int[1];
252d0d07059943603c8d20ab9e2ee31ba5c7d477fbaRomain Guy
253d0d07059943603c8d20ab9e2ee31ba5c7d477fbaRomain Guy            glActiveTexture(GL_TEXTURE0);
254d0d07059943603c8d20ab9e2ee31ba5c7d477fbaRomain Guy            glGenTextures(1, textures, 0);
255d0d07059943603c8d20ab9e2ee31ba5c7d477fbaRomain Guy            checkGlError();
256d0d07059943603c8d20ab9e2ee31ba5c7d477fbaRomain Guy
257d0d07059943603c8d20ab9e2ee31ba5c7d477fbaRomain Guy            int texture = textures[0];
258d0d07059943603c8d20ab9e2ee31ba5c7d477fbaRomain Guy            glBindTexture(GL_TEXTURE_2D, texture);
259d0d07059943603c8d20ab9e2ee31ba5c7d477fbaRomain Guy            checkGlError();
260d0d07059943603c8d20ab9e2ee31ba5c7d477fbaRomain Guy
261d0d07059943603c8d20ab9e2ee31ba5c7d477fbaRomain Guy            glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
262d0d07059943603c8d20ab9e2ee31ba5c7d477fbaRomain Guy            glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
263d0d07059943603c8d20ab9e2ee31ba5c7d477fbaRomain Guy
264d0d07059943603c8d20ab9e2ee31ba5c7d477fbaRomain Guy            glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
265d0d07059943603c8d20ab9e2ee31ba5c7d477fbaRomain Guy            glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
266d0d07059943603c8d20ab9e2ee31ba5c7d477fbaRomain Guy
267d0d07059943603c8d20ab9e2ee31ba5c7d477fbaRomain Guy            Bitmap bitmap = BitmapFactory.decodeResource(mResources, resource);
268d0d07059943603c8d20ab9e2ee31ba5c7d477fbaRomain Guy
269d0d07059943603c8d20ab9e2ee31ba5c7d477fbaRomain Guy            GLUtils.texImage2D(GL_TEXTURE_2D, 0, GL_RGBA, bitmap, GL_UNSIGNED_BYTE, 0);
270d0d07059943603c8d20ab9e2ee31ba5c7d477fbaRomain Guy            checkGlError();
271d0d07059943603c8d20ab9e2ee31ba5c7d477fbaRomain Guy
272d0d07059943603c8d20ab9e2ee31ba5c7d477fbaRomain Guy            bitmap.recycle();
273d0d07059943603c8d20ab9e2ee31ba5c7d477fbaRomain Guy
274d0d07059943603c8d20ab9e2ee31ba5c7d477fbaRomain Guy            return texture;
275d0d07059943603c8d20ab9e2ee31ba5c7d477fbaRomain Guy        }
276d0d07059943603c8d20ab9e2ee31ba5c7d477fbaRomain Guy
277d0d07059943603c8d20ab9e2ee31ba5c7d477fbaRomain Guy        private int buildProgram(String vertex, String fragment) {
278d0d07059943603c8d20ab9e2ee31ba5c7d477fbaRomain Guy            int vertexShader = buildShader(vertex, GL_VERTEX_SHADER);
279d0d07059943603c8d20ab9e2ee31ba5c7d477fbaRomain Guy            if (vertexShader == 0) return 0;
280d0d07059943603c8d20ab9e2ee31ba5c7d477fbaRomain Guy
281d0d07059943603c8d20ab9e2ee31ba5c7d477fbaRomain Guy            int fragmentShader = buildShader(fragment, GL_FRAGMENT_SHADER);
282d0d07059943603c8d20ab9e2ee31ba5c7d477fbaRomain Guy            if (fragmentShader == 0) return 0;
283d0d07059943603c8d20ab9e2ee31ba5c7d477fbaRomain Guy
284d0d07059943603c8d20ab9e2ee31ba5c7d477fbaRomain Guy            int program = glCreateProgram();
285d0d07059943603c8d20ab9e2ee31ba5c7d477fbaRomain Guy            glAttachShader(program, vertexShader);
286d0d07059943603c8d20ab9e2ee31ba5c7d477fbaRomain Guy            checkGlError();
287d0d07059943603c8d20ab9e2ee31ba5c7d477fbaRomain Guy
288d0d07059943603c8d20ab9e2ee31ba5c7d477fbaRomain Guy            glAttachShader(program, fragmentShader);
289d0d07059943603c8d20ab9e2ee31ba5c7d477fbaRomain Guy            checkGlError();
290d0d07059943603c8d20ab9e2ee31ba5c7d477fbaRomain Guy
291d0d07059943603c8d20ab9e2ee31ba5c7d477fbaRomain Guy            glLinkProgram(program);
292d0d07059943603c8d20ab9e2ee31ba5c7d477fbaRomain Guy            checkGlError();
293d0d07059943603c8d20ab9e2ee31ba5c7d477fbaRomain Guy
294d0d07059943603c8d20ab9e2ee31ba5c7d477fbaRomain Guy            int[] status = new int[1];
295d0d07059943603c8d20ab9e2ee31ba5c7d477fbaRomain Guy            glGetProgramiv(program, GL_LINK_STATUS, status, 0);
296d0d07059943603c8d20ab9e2ee31ba5c7d477fbaRomain Guy            if (status[0] != GL_TRUE) {
297d0d07059943603c8d20ab9e2ee31ba5c7d477fbaRomain Guy                String error = glGetProgramInfoLog(program);
298d0d07059943603c8d20ab9e2ee31ba5c7d477fbaRomain Guy                Log.d(LOG_TAG, "Error while linking program:\n" + error);
299d0d07059943603c8d20ab9e2ee31ba5c7d477fbaRomain Guy                glDeleteShader(vertexShader);
300d0d07059943603c8d20ab9e2ee31ba5c7d477fbaRomain Guy                glDeleteShader(fragmentShader);
301d0d07059943603c8d20ab9e2ee31ba5c7d477fbaRomain Guy                glDeleteProgram(program);
302d0d07059943603c8d20ab9e2ee31ba5c7d477fbaRomain Guy                return 0;
303d0d07059943603c8d20ab9e2ee31ba5c7d477fbaRomain Guy            }
304d0d07059943603c8d20ab9e2ee31ba5c7d477fbaRomain Guy
305d0d07059943603c8d20ab9e2ee31ba5c7d477fbaRomain Guy            return program;
306d0d07059943603c8d20ab9e2ee31ba5c7d477fbaRomain Guy        }
307d0d07059943603c8d20ab9e2ee31ba5c7d477fbaRomain Guy
308d0d07059943603c8d20ab9e2ee31ba5c7d477fbaRomain Guy        private int buildShader(String source, int type) {
309d0d07059943603c8d20ab9e2ee31ba5c7d477fbaRomain Guy            int shader = glCreateShader(type);
310d0d07059943603c8d20ab9e2ee31ba5c7d477fbaRomain Guy
311d0d07059943603c8d20ab9e2ee31ba5c7d477fbaRomain Guy            glShaderSource(shader, source);
312d0d07059943603c8d20ab9e2ee31ba5c7d477fbaRomain Guy            checkGlError();
313d0d07059943603c8d20ab9e2ee31ba5c7d477fbaRomain Guy
314d0d07059943603c8d20ab9e2ee31ba5c7d477fbaRomain Guy            glCompileShader(shader);
315d0d07059943603c8d20ab9e2ee31ba5c7d477fbaRomain Guy            checkGlError();
316d0d07059943603c8d20ab9e2ee31ba5c7d477fbaRomain Guy
317d0d07059943603c8d20ab9e2ee31ba5c7d477fbaRomain Guy            int[] status = new int[1];
318d0d07059943603c8d20ab9e2ee31ba5c7d477fbaRomain Guy            glGetShaderiv(shader, GL_COMPILE_STATUS, status, 0);
319d0d07059943603c8d20ab9e2ee31ba5c7d477fbaRomain Guy            if (status[0] != GL_TRUE) {
320d0d07059943603c8d20ab9e2ee31ba5c7d477fbaRomain Guy                String error = glGetShaderInfoLog(shader);
321d0d07059943603c8d20ab9e2ee31ba5c7d477fbaRomain Guy                Log.d(LOG_TAG, "Error while compiling shader:\n" + error);
322d0d07059943603c8d20ab9e2ee31ba5c7d477fbaRomain Guy                glDeleteShader(shader);
323d0d07059943603c8d20ab9e2ee31ba5c7d477fbaRomain Guy                return 0;
324d0d07059943603c8d20ab9e2ee31ba5c7d477fbaRomain Guy            }
325d0d07059943603c8d20ab9e2ee31ba5c7d477fbaRomain Guy
326d0d07059943603c8d20ab9e2ee31ba5c7d477fbaRomain Guy            return shader;
327d0d07059943603c8d20ab9e2ee31ba5c7d477fbaRomain Guy        }
328d0d07059943603c8d20ab9e2ee31ba5c7d477fbaRomain Guy
329451ce44a18e4c48f8a43aa250957f76967a35d31Romain Guy        private void checkEglError() {
330451ce44a18e4c48f8a43aa250957f76967a35d31Romain Guy            int error = mEgl.eglGetError();
331451ce44a18e4c48f8a43aa250957f76967a35d31Romain Guy            if (error != EGL10.EGL_SUCCESS) {
332451ce44a18e4c48f8a43aa250957f76967a35d31Romain Guy                Log.w(LOG_TAG, "EGL error = 0x" + Integer.toHexString(error));
333451ce44a18e4c48f8a43aa250957f76967a35d31Romain Guy            }
334451ce44a18e4c48f8a43aa250957f76967a35d31Romain Guy        }
335451ce44a18e4c48f8a43aa250957f76967a35d31Romain Guy
336451ce44a18e4c48f8a43aa250957f76967a35d31Romain Guy        private void checkGlError() {
337d0d07059943603c8d20ab9e2ee31ba5c7d477fbaRomain Guy            int error = glGetError();
338d0d07059943603c8d20ab9e2ee31ba5c7d477fbaRomain Guy            if (error != GL_NO_ERROR) {
339451ce44a18e4c48f8a43aa250957f76967a35d31Romain Guy                Log.w(LOG_TAG, "GL error = 0x" + Integer.toHexString(error));
340451ce44a18e4c48f8a43aa250957f76967a35d31Romain Guy            }
341451ce44a18e4c48f8a43aa250957f76967a35d31Romain Guy        }
342451ce44a18e4c48f8a43aa250957f76967a35d31Romain Guy
3438f0095cd33558e9cc8a440047908e53b68906f5fRomain Guy        private void finishGL() {
3448f0095cd33558e9cc8a440047908e53b68906f5fRomain Guy            mEgl.eglDestroyContext(mEglDisplay, mEglContext);
3458f0095cd33558e9cc8a440047908e53b68906f5fRomain Guy            mEgl.eglDestroySurface(mEglDisplay, mEglSurface);
3468f0095cd33558e9cc8a440047908e53b68906f5fRomain Guy        }
3478f0095cd33558e9cc8a440047908e53b68906f5fRomain Guy
3488f0095cd33558e9cc8a440047908e53b68906f5fRomain Guy        private void checkCurrent() {
3498f0095cd33558e9cc8a440047908e53b68906f5fRomain Guy            if (!mEglContext.equals(mEgl.eglGetCurrentContext()) ||
3508f0095cd33558e9cc8a440047908e53b68906f5fRomain Guy                    !mEglSurface.equals(mEgl.eglGetCurrentSurface(EGL10.EGL_DRAW))) {
3518f0095cd33558e9cc8a440047908e53b68906f5fRomain Guy                if (!mEgl.eglMakeCurrent(mEglDisplay, mEglSurface, mEglSurface, mEglContext)) {
3528f0095cd33558e9cc8a440047908e53b68906f5fRomain Guy                    throw new RuntimeException("eglMakeCurrent failed "
3538f0095cd33558e9cc8a440047908e53b68906f5fRomain Guy                            + getEGLErrorString(mEgl.eglGetError()));
3548f0095cd33558e9cc8a440047908e53b68906f5fRomain Guy                }
3558f0095cd33558e9cc8a440047908e53b68906f5fRomain Guy            }
3568f0095cd33558e9cc8a440047908e53b68906f5fRomain Guy        }
3578f0095cd33558e9cc8a440047908e53b68906f5fRomain Guy
3588f0095cd33558e9cc8a440047908e53b68906f5fRomain Guy        private void initGL() {
3598f0095cd33558e9cc8a440047908e53b68906f5fRomain Guy            mEgl = (EGL10) EGLContext.getEGL();
3608f0095cd33558e9cc8a440047908e53b68906f5fRomain Guy
3618f0095cd33558e9cc8a440047908e53b68906f5fRomain Guy            mEglDisplay = mEgl.eglGetDisplay(EGL10.EGL_DEFAULT_DISPLAY);
3628f0095cd33558e9cc8a440047908e53b68906f5fRomain Guy            if (mEglDisplay == EGL10.EGL_NO_DISPLAY) {
3638f0095cd33558e9cc8a440047908e53b68906f5fRomain Guy                throw new RuntimeException("eglGetDisplay failed "
3648f0095cd33558e9cc8a440047908e53b68906f5fRomain Guy                        + getEGLErrorString(mEgl.eglGetError()));
3658f0095cd33558e9cc8a440047908e53b68906f5fRomain Guy            }
3668f0095cd33558e9cc8a440047908e53b68906f5fRomain Guy
3678f0095cd33558e9cc8a440047908e53b68906f5fRomain Guy            int[] version = new int[2];
3688f0095cd33558e9cc8a440047908e53b68906f5fRomain Guy            if (!mEgl.eglInitialize(mEglDisplay, version)) {
3698f0095cd33558e9cc8a440047908e53b68906f5fRomain Guy                throw new RuntimeException("eglInitialize failed " +
3708f0095cd33558e9cc8a440047908e53b68906f5fRomain Guy                        getEGLErrorString(mEgl.eglGetError()));
3718f0095cd33558e9cc8a440047908e53b68906f5fRomain Guy            }
3728f0095cd33558e9cc8a440047908e53b68906f5fRomain Guy
3738f0095cd33558e9cc8a440047908e53b68906f5fRomain Guy            mEglConfig = chooseEglConfig();
3748f0095cd33558e9cc8a440047908e53b68906f5fRomain Guy            if (mEglConfig == null) {
3758f0095cd33558e9cc8a440047908e53b68906f5fRomain Guy                throw new RuntimeException("eglConfig not initialized");
3768f0095cd33558e9cc8a440047908e53b68906f5fRomain Guy            }
3778f0095cd33558e9cc8a440047908e53b68906f5fRomain Guy
3788f0095cd33558e9cc8a440047908e53b68906f5fRomain Guy            mEglContext = createContext(mEgl, mEglDisplay, mEglConfig);
3798f0095cd33558e9cc8a440047908e53b68906f5fRomain Guy
3808f0095cd33558e9cc8a440047908e53b68906f5fRomain Guy            mEglSurface = mEgl.eglCreateWindowSurface(mEglDisplay, mEglConfig, mSurface, null);
3818f0095cd33558e9cc8a440047908e53b68906f5fRomain Guy
3828f0095cd33558e9cc8a440047908e53b68906f5fRomain Guy            if (mEglSurface == null || mEglSurface == EGL10.EGL_NO_SURFACE) {
3838f0095cd33558e9cc8a440047908e53b68906f5fRomain Guy                int error = mEgl.eglGetError();
3848f0095cd33558e9cc8a440047908e53b68906f5fRomain Guy                if (error == EGL10.EGL_BAD_NATIVE_WINDOW) {
3858f0095cd33558e9cc8a440047908e53b68906f5fRomain Guy                    Log.e(LOG_TAG, "createWindowSurface returned EGL_BAD_NATIVE_WINDOW.");
3868f0095cd33558e9cc8a440047908e53b68906f5fRomain Guy                    return;
3878f0095cd33558e9cc8a440047908e53b68906f5fRomain Guy                }
3888f0095cd33558e9cc8a440047908e53b68906f5fRomain Guy                throw new RuntimeException("createWindowSurface failed "
3898f0095cd33558e9cc8a440047908e53b68906f5fRomain Guy                        + getEGLErrorString(error));
3908f0095cd33558e9cc8a440047908e53b68906f5fRomain Guy            }
3918f0095cd33558e9cc8a440047908e53b68906f5fRomain Guy
3928f0095cd33558e9cc8a440047908e53b68906f5fRomain Guy            if (!mEgl.eglMakeCurrent(mEglDisplay, mEglSurface, mEglSurface, mEglContext)) {
3938f0095cd33558e9cc8a440047908e53b68906f5fRomain Guy                throw new RuntimeException("eglMakeCurrent failed "
3948f0095cd33558e9cc8a440047908e53b68906f5fRomain Guy                        + getEGLErrorString(mEgl.eglGetError()));
3958f0095cd33558e9cc8a440047908e53b68906f5fRomain Guy            }
3968f0095cd33558e9cc8a440047908e53b68906f5fRomain Guy
3978f0095cd33558e9cc8a440047908e53b68906f5fRomain Guy            mGL = mEglContext.getGL();
3988f0095cd33558e9cc8a440047908e53b68906f5fRomain Guy        }
3998f0095cd33558e9cc8a440047908e53b68906f5fRomain Guy
4008f0095cd33558e9cc8a440047908e53b68906f5fRomain Guy
4018f0095cd33558e9cc8a440047908e53b68906f5fRomain Guy        EGLContext createContext(EGL10 egl, EGLDisplay eglDisplay, EGLConfig eglConfig) {
4028f0095cd33558e9cc8a440047908e53b68906f5fRomain Guy            int[] attrib_list = { EGL_CONTEXT_CLIENT_VERSION, 2, EGL10.EGL_NONE };
4038f0095cd33558e9cc8a440047908e53b68906f5fRomain Guy            return egl.eglCreateContext(eglDisplay, eglConfig, EGL10.EGL_NO_CONTEXT, attrib_list);
4048f0095cd33558e9cc8a440047908e53b68906f5fRomain Guy        }
4058f0095cd33558e9cc8a440047908e53b68906f5fRomain Guy
4068f0095cd33558e9cc8a440047908e53b68906f5fRomain Guy        private EGLConfig chooseEglConfig() {
4078f0095cd33558e9cc8a440047908e53b68906f5fRomain Guy            int[] configsCount = new int[1];
4088f0095cd33558e9cc8a440047908e53b68906f5fRomain Guy            EGLConfig[] configs = new EGLConfig[1];
4098f0095cd33558e9cc8a440047908e53b68906f5fRomain Guy            int[] configSpec = getConfig();
4108f0095cd33558e9cc8a440047908e53b68906f5fRomain Guy            if (!mEgl.eglChooseConfig(mEglDisplay, configSpec, configs, 1, configsCount)) {
4118f0095cd33558e9cc8a440047908e53b68906f5fRomain Guy                throw new IllegalArgumentException("eglChooseConfig failed " +
4128f0095cd33558e9cc8a440047908e53b68906f5fRomain Guy                        getEGLErrorString(mEgl.eglGetError()));
4138f0095cd33558e9cc8a440047908e53b68906f5fRomain Guy            } else if (configsCount[0] > 0) {
4148f0095cd33558e9cc8a440047908e53b68906f5fRomain Guy                return configs[0];
4158f0095cd33558e9cc8a440047908e53b68906f5fRomain Guy            }
4168f0095cd33558e9cc8a440047908e53b68906f5fRomain Guy            return null;
4178f0095cd33558e9cc8a440047908e53b68906f5fRomain Guy        }
4188f0095cd33558e9cc8a440047908e53b68906f5fRomain Guy
4198f0095cd33558e9cc8a440047908e53b68906f5fRomain Guy        private int[] getConfig() {
4208f0095cd33558e9cc8a440047908e53b68906f5fRomain Guy            return new int[] {
4218f0095cd33558e9cc8a440047908e53b68906f5fRomain Guy                    EGL10.EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT,
4228f0095cd33558e9cc8a440047908e53b68906f5fRomain Guy                    EGL10.EGL_RED_SIZE, 8,
4238f0095cd33558e9cc8a440047908e53b68906f5fRomain Guy                    EGL10.EGL_GREEN_SIZE, 8,
4248f0095cd33558e9cc8a440047908e53b68906f5fRomain Guy                    EGL10.EGL_BLUE_SIZE, 8,
4258f0095cd33558e9cc8a440047908e53b68906f5fRomain Guy                    EGL10.EGL_ALPHA_SIZE, 8,
4268f0095cd33558e9cc8a440047908e53b68906f5fRomain Guy                    EGL10.EGL_DEPTH_SIZE, 0,
4278f0095cd33558e9cc8a440047908e53b68906f5fRomain Guy                    EGL10.EGL_STENCIL_SIZE, 0,
4288f0095cd33558e9cc8a440047908e53b68906f5fRomain Guy                    EGL10.EGL_NONE
4298f0095cd33558e9cc8a440047908e53b68906f5fRomain Guy            };
4308f0095cd33558e9cc8a440047908e53b68906f5fRomain Guy        }
4318f0095cd33558e9cc8a440047908e53b68906f5fRomain Guy
4328f0095cd33558e9cc8a440047908e53b68906f5fRomain Guy        static String getEGLErrorString(int error) {
4338f0095cd33558e9cc8a440047908e53b68906f5fRomain Guy            switch (error) {
4348f0095cd33558e9cc8a440047908e53b68906f5fRomain Guy                case EGL10.EGL_SUCCESS:
4358f0095cd33558e9cc8a440047908e53b68906f5fRomain Guy                    return "EGL_SUCCESS";
4368f0095cd33558e9cc8a440047908e53b68906f5fRomain Guy                case EGL10.EGL_NOT_INITIALIZED:
4378f0095cd33558e9cc8a440047908e53b68906f5fRomain Guy                    return "EGL_NOT_INITIALIZED";
4388f0095cd33558e9cc8a440047908e53b68906f5fRomain Guy                case EGL10.EGL_BAD_ACCESS:
4398f0095cd33558e9cc8a440047908e53b68906f5fRomain Guy                    return "EGL_BAD_ACCESS";
4408f0095cd33558e9cc8a440047908e53b68906f5fRomain Guy                case EGL10.EGL_BAD_ALLOC:
4418f0095cd33558e9cc8a440047908e53b68906f5fRomain Guy                    return "EGL_BAD_ALLOC";
4428f0095cd33558e9cc8a440047908e53b68906f5fRomain Guy                case EGL10.EGL_BAD_ATTRIBUTE:
4438f0095cd33558e9cc8a440047908e53b68906f5fRomain Guy                    return "EGL_BAD_ATTRIBUTE";
4448f0095cd33558e9cc8a440047908e53b68906f5fRomain Guy                case EGL10.EGL_BAD_CONFIG:
4458f0095cd33558e9cc8a440047908e53b68906f5fRomain Guy                    return "EGL_BAD_CONFIG";
4468f0095cd33558e9cc8a440047908e53b68906f5fRomain Guy                case EGL10.EGL_BAD_CONTEXT:
4478f0095cd33558e9cc8a440047908e53b68906f5fRomain Guy                    return "EGL_BAD_CONTEXT";
4488f0095cd33558e9cc8a440047908e53b68906f5fRomain Guy                case EGL10.EGL_BAD_CURRENT_SURFACE:
4498f0095cd33558e9cc8a440047908e53b68906f5fRomain Guy                    return "EGL_BAD_CURRENT_SURFACE";
4508f0095cd33558e9cc8a440047908e53b68906f5fRomain Guy                case EGL10.EGL_BAD_DISPLAY:
4518f0095cd33558e9cc8a440047908e53b68906f5fRomain Guy                    return "EGL_BAD_DISPLAY";
4528f0095cd33558e9cc8a440047908e53b68906f5fRomain Guy                case EGL10.EGL_BAD_MATCH:
4538f0095cd33558e9cc8a440047908e53b68906f5fRomain Guy                    return "EGL_BAD_MATCH";
4548f0095cd33558e9cc8a440047908e53b68906f5fRomain Guy                case EGL10.EGL_BAD_NATIVE_PIXMAP:
4558f0095cd33558e9cc8a440047908e53b68906f5fRomain Guy                    return "EGL_BAD_NATIVE_PIXMAP";
4568f0095cd33558e9cc8a440047908e53b68906f5fRomain Guy                case EGL10.EGL_BAD_NATIVE_WINDOW:
4578f0095cd33558e9cc8a440047908e53b68906f5fRomain Guy                    return "EGL_BAD_NATIVE_WINDOW";
4588f0095cd33558e9cc8a440047908e53b68906f5fRomain Guy                case EGL10.EGL_BAD_PARAMETER:
4598f0095cd33558e9cc8a440047908e53b68906f5fRomain Guy                    return "EGL_BAD_PARAMETER";
4608f0095cd33558e9cc8a440047908e53b68906f5fRomain Guy                case EGL10.EGL_BAD_SURFACE:
4618f0095cd33558e9cc8a440047908e53b68906f5fRomain Guy                    return "EGL_BAD_SURFACE";
4628f0095cd33558e9cc8a440047908e53b68906f5fRomain Guy                case EGL11.EGL_CONTEXT_LOST:
4638f0095cd33558e9cc8a440047908e53b68906f5fRomain Guy                    return "EGL_CONTEXT_LOST";
4648f0095cd33558e9cc8a440047908e53b68906f5fRomain Guy                default:
4658f0095cd33558e9cc8a440047908e53b68906f5fRomain Guy                    return "0x" + Integer.toHexString(error);
4668f0095cd33558e9cc8a440047908e53b68906f5fRomain Guy            }
4678f0095cd33558e9cc8a440047908e53b68906f5fRomain Guy        }
4688f0095cd33558e9cc8a440047908e53b68906f5fRomain Guy
4698f0095cd33558e9cc8a440047908e53b68906f5fRomain Guy        void finish() {
4708f0095cd33558e9cc8a440047908e53b68906f5fRomain Guy            mFinished = true;
4718f0095cd33558e9cc8a440047908e53b68906f5fRomain Guy        }
4728f0095cd33558e9cc8a440047908e53b68906f5fRomain Guy    }
4738f0095cd33558e9cc8a440047908e53b68906f5fRomain Guy}
474