GL2JavaView.java revision 50d0b14689b0ae95ea7b66a8c2f7b955115812dd
150d0b14689b0ae95ea7b66a8c2f7b955115812ddJack Palevich/*
250d0b14689b0ae95ea7b66a8c2f7b955115812ddJack Palevich * Copyright (C) 2009 The Android Open Source Project
350d0b14689b0ae95ea7b66a8c2f7b955115812ddJack Palevich *
450d0b14689b0ae95ea7b66a8c2f7b955115812ddJack Palevich * Licensed under the Apache License, Version 2.0 (the "License");
550d0b14689b0ae95ea7b66a8c2f7b955115812ddJack Palevich * you may not use this file except in compliance with the License.
650d0b14689b0ae95ea7b66a8c2f7b955115812ddJack Palevich * You may obtain a copy of the License at
750d0b14689b0ae95ea7b66a8c2f7b955115812ddJack Palevich *
850d0b14689b0ae95ea7b66a8c2f7b955115812ddJack Palevich *      http://www.apache.org/licenses/LICENSE-2.0
950d0b14689b0ae95ea7b66a8c2f7b955115812ddJack Palevich *
1050d0b14689b0ae95ea7b66a8c2f7b955115812ddJack Palevich * Unless required by applicable law or agreed to in writing, software
1150d0b14689b0ae95ea7b66a8c2f7b955115812ddJack Palevich * distributed under the License is distributed on an "AS IS" BASIS,
1250d0b14689b0ae95ea7b66a8c2f7b955115812ddJack Palevich * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1350d0b14689b0ae95ea7b66a8c2f7b955115812ddJack Palevich * See the License for the specific language governing permissions and
1450d0b14689b0ae95ea7b66a8c2f7b955115812ddJack Palevich * limitations under the License.
1550d0b14689b0ae95ea7b66a8c2f7b955115812ddJack Palevich */
1650d0b14689b0ae95ea7b66a8c2f7b955115812ddJack Palevich
1750d0b14689b0ae95ea7b66a8c2f7b955115812ddJack Palevichpackage com.android.gl2java;
1850d0b14689b0ae95ea7b66a8c2f7b955115812ddJack Palevich
1950d0b14689b0ae95ea7b66a8c2f7b955115812ddJack Palevichimport android.content.Context;
2050d0b14689b0ae95ea7b66a8c2f7b955115812ddJack Palevichimport android.opengl.GLSurfaceView;
2150d0b14689b0ae95ea7b66a8c2f7b955115812ddJack Palevichimport android.util.AttributeSet;
2250d0b14689b0ae95ea7b66a8c2f7b955115812ddJack Palevichimport android.util.Log;
2350d0b14689b0ae95ea7b66a8c2f7b955115812ddJack Palevichimport android.view.KeyEvent;
2450d0b14689b0ae95ea7b66a8c2f7b955115812ddJack Palevichimport android.view.MotionEvent;
2550d0b14689b0ae95ea7b66a8c2f7b955115812ddJack Palevich
2650d0b14689b0ae95ea7b66a8c2f7b955115812ddJack Palevichimport java.nio.ByteBuffer;
2750d0b14689b0ae95ea7b66a8c2f7b955115812ddJack Palevichimport java.nio.ByteOrder;
2850d0b14689b0ae95ea7b66a8c2f7b955115812ddJack Palevichimport java.nio.FloatBuffer;
2950d0b14689b0ae95ea7b66a8c2f7b955115812ddJack Palevich
3050d0b14689b0ae95ea7b66a8c2f7b955115812ddJack Palevichimport javax.microedition.khronos.egl.EGL10;
3150d0b14689b0ae95ea7b66a8c2f7b955115812ddJack Palevichimport javax.microedition.khronos.egl.EGLConfig;
3250d0b14689b0ae95ea7b66a8c2f7b955115812ddJack Palevichimport javax.microedition.khronos.egl.EGLContext;
3350d0b14689b0ae95ea7b66a8c2f7b955115812ddJack Palevichimport javax.microedition.khronos.egl.EGLDisplay;
3450d0b14689b0ae95ea7b66a8c2f7b955115812ddJack Palevichimport javax.microedition.khronos.opengles.GL10;
3550d0b14689b0ae95ea7b66a8c2f7b955115812ddJack Palevich
3650d0b14689b0ae95ea7b66a8c2f7b955115812ddJack Palevichimport android.opengl.GLES20;
3750d0b14689b0ae95ea7b66a8c2f7b955115812ddJack Palevich
3850d0b14689b0ae95ea7b66a8c2f7b955115812ddJack Palevich/**
3950d0b14689b0ae95ea7b66a8c2f7b955115812ddJack Palevich * An implementation of SurfaceView that uses the dedicated surface for
4050d0b14689b0ae95ea7b66a8c2f7b955115812ddJack Palevich * displaying an OpenGL animation.  This allows the animation to run in a
4150d0b14689b0ae95ea7b66a8c2f7b955115812ddJack Palevich * separate thread, without requiring that it be driven by the update mechanism
4250d0b14689b0ae95ea7b66a8c2f7b955115812ddJack Palevich * of the view hierarchy.
4350d0b14689b0ae95ea7b66a8c2f7b955115812ddJack Palevich *
4450d0b14689b0ae95ea7b66a8c2f7b955115812ddJack Palevich * The application-specific rendering code is delegated to a GLView.Renderer
4550d0b14689b0ae95ea7b66a8c2f7b955115812ddJack Palevich * instance.
4650d0b14689b0ae95ea7b66a8c2f7b955115812ddJack Palevich */
4750d0b14689b0ae95ea7b66a8c2f7b955115812ddJack Palevichclass GL2JavaView extends GLSurfaceView {
4850d0b14689b0ae95ea7b66a8c2f7b955115812ddJack Palevich    private static String TAG = "GL2JavaView";
4950d0b14689b0ae95ea7b66a8c2f7b955115812ddJack Palevich
5050d0b14689b0ae95ea7b66a8c2f7b955115812ddJack Palevich    public GL2JavaView(Context context) {
5150d0b14689b0ae95ea7b66a8c2f7b955115812ddJack Palevich        super(context);
5250d0b14689b0ae95ea7b66a8c2f7b955115812ddJack Palevich        init(false, 0, 0);
5350d0b14689b0ae95ea7b66a8c2f7b955115812ddJack Palevich    }
5450d0b14689b0ae95ea7b66a8c2f7b955115812ddJack Palevich
5550d0b14689b0ae95ea7b66a8c2f7b955115812ddJack Palevich    public GL2JavaView(Context context, boolean translucent, int depth, int stencil) {
5650d0b14689b0ae95ea7b66a8c2f7b955115812ddJack Palevich        super(context);
5750d0b14689b0ae95ea7b66a8c2f7b955115812ddJack Palevich        init(translucent, depth, stencil);
5850d0b14689b0ae95ea7b66a8c2f7b955115812ddJack Palevich    }
5950d0b14689b0ae95ea7b66a8c2f7b955115812ddJack Palevich
6050d0b14689b0ae95ea7b66a8c2f7b955115812ddJack Palevich    private void init(boolean translucent, int depth, int stencil) {
6150d0b14689b0ae95ea7b66a8c2f7b955115812ddJack Palevich        setEGLContextFactory(new ContextFactory());
6250d0b14689b0ae95ea7b66a8c2f7b955115812ddJack Palevich        setEGLConfigChooser( translucent ?
6350d0b14689b0ae95ea7b66a8c2f7b955115812ddJack Palevich              new ConfigChooser(8,8,8,8, depth, stencil) :
6450d0b14689b0ae95ea7b66a8c2f7b955115812ddJack Palevich              new ConfigChooser(5,6,5,0, depth, stencil));
6550d0b14689b0ae95ea7b66a8c2f7b955115812ddJack Palevich        setRenderer(new Renderer());
6650d0b14689b0ae95ea7b66a8c2f7b955115812ddJack Palevich    }
6750d0b14689b0ae95ea7b66a8c2f7b955115812ddJack Palevich
6850d0b14689b0ae95ea7b66a8c2f7b955115812ddJack Palevich    private static class ContextFactory implements GLSurfaceView.EGLContextFactory {
6950d0b14689b0ae95ea7b66a8c2f7b955115812ddJack Palevich        private static int EGL_CONTEXT_CLIENT_VERSION = 0x3098;
7050d0b14689b0ae95ea7b66a8c2f7b955115812ddJack Palevich        public EGLContext createContext(EGL10 egl, EGLDisplay display, EGLConfig eglConfig) {
7150d0b14689b0ae95ea7b66a8c2f7b955115812ddJack Palevich            Log.w(TAG, "creating OpenGL ES 2.0 context");
7250d0b14689b0ae95ea7b66a8c2f7b955115812ddJack Palevich            checkEglError("Before eglCreateContext", egl);
7350d0b14689b0ae95ea7b66a8c2f7b955115812ddJack Palevich            int[] attrib_list = {EGL_CONTEXT_CLIENT_VERSION, 2, EGL10.EGL_NONE };
7450d0b14689b0ae95ea7b66a8c2f7b955115812ddJack Palevich            EGLContext context = egl.eglCreateContext(display, eglConfig, EGL10.EGL_NO_CONTEXT, attrib_list);
7550d0b14689b0ae95ea7b66a8c2f7b955115812ddJack Palevich            checkEglError("After eglCreateContext", egl);
7650d0b14689b0ae95ea7b66a8c2f7b955115812ddJack Palevich            return context;
7750d0b14689b0ae95ea7b66a8c2f7b955115812ddJack Palevich        }
7850d0b14689b0ae95ea7b66a8c2f7b955115812ddJack Palevich
7950d0b14689b0ae95ea7b66a8c2f7b955115812ddJack Palevich        public void destroyContext(EGL10 egl, EGLDisplay display, EGLContext context) {
8050d0b14689b0ae95ea7b66a8c2f7b955115812ddJack Palevich            egl.eglDestroyContext(display, context);
8150d0b14689b0ae95ea7b66a8c2f7b955115812ddJack Palevich        }
8250d0b14689b0ae95ea7b66a8c2f7b955115812ddJack Palevich    }
8350d0b14689b0ae95ea7b66a8c2f7b955115812ddJack Palevich
8450d0b14689b0ae95ea7b66a8c2f7b955115812ddJack Palevich    private static void checkEglError(String prompt, EGL10 egl) {
8550d0b14689b0ae95ea7b66a8c2f7b955115812ddJack Palevich        int error;
8650d0b14689b0ae95ea7b66a8c2f7b955115812ddJack Palevich        while ((error = egl.eglGetError()) != EGL10.EGL_SUCCESS) {
8750d0b14689b0ae95ea7b66a8c2f7b955115812ddJack Palevich            Log.e(TAG, String.format("%s: EGL error: 0x%x", prompt, error));
8850d0b14689b0ae95ea7b66a8c2f7b955115812ddJack Palevich        }
8950d0b14689b0ae95ea7b66a8c2f7b955115812ddJack Palevich    }
9050d0b14689b0ae95ea7b66a8c2f7b955115812ddJack Palevich
9150d0b14689b0ae95ea7b66a8c2f7b955115812ddJack Palevich    private static class ConfigChooser implements GLSurfaceView.EGLConfigChooser {
9250d0b14689b0ae95ea7b66a8c2f7b955115812ddJack Palevich        private static int EGL_OPENGL_ES2_BIT = 4;
9350d0b14689b0ae95ea7b66a8c2f7b955115812ddJack Palevich        private static int[] s_configAttribs2 =
9450d0b14689b0ae95ea7b66a8c2f7b955115812ddJack Palevich        {
9550d0b14689b0ae95ea7b66a8c2f7b955115812ddJack Palevich            EGL10.EGL_RED_SIZE, 4,
9650d0b14689b0ae95ea7b66a8c2f7b955115812ddJack Palevich            EGL10.EGL_GREEN_SIZE, 4,
9750d0b14689b0ae95ea7b66a8c2f7b955115812ddJack Palevich            EGL10.EGL_BLUE_SIZE, 4,
9850d0b14689b0ae95ea7b66a8c2f7b955115812ddJack Palevich            EGL10.EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT,
9950d0b14689b0ae95ea7b66a8c2f7b955115812ddJack Palevich            EGL10.EGL_NONE
10050d0b14689b0ae95ea7b66a8c2f7b955115812ddJack Palevich        };
10150d0b14689b0ae95ea7b66a8c2f7b955115812ddJack Palevich
10250d0b14689b0ae95ea7b66a8c2f7b955115812ddJack Palevich        public ConfigChooser(int r, int g, int b, int a, int depth, int stencil) {
10350d0b14689b0ae95ea7b66a8c2f7b955115812ddJack Palevich            mRedSize = r;
10450d0b14689b0ae95ea7b66a8c2f7b955115812ddJack Palevich            mGreenSize = g;
10550d0b14689b0ae95ea7b66a8c2f7b955115812ddJack Palevich            mBlueSize = b;
10650d0b14689b0ae95ea7b66a8c2f7b955115812ddJack Palevich            mAlphaSize = a;
10750d0b14689b0ae95ea7b66a8c2f7b955115812ddJack Palevich            mDepthSize = depth;
10850d0b14689b0ae95ea7b66a8c2f7b955115812ddJack Palevich            mStencilSize = stencil;
10950d0b14689b0ae95ea7b66a8c2f7b955115812ddJack Palevich        }
11050d0b14689b0ae95ea7b66a8c2f7b955115812ddJack Palevich
11150d0b14689b0ae95ea7b66a8c2f7b955115812ddJack Palevich        public EGLConfig chooseConfig(EGL10 egl, EGLDisplay display) {
11250d0b14689b0ae95ea7b66a8c2f7b955115812ddJack Palevich
11350d0b14689b0ae95ea7b66a8c2f7b955115812ddJack Palevich            int[] num_config = new int[1];
11450d0b14689b0ae95ea7b66a8c2f7b955115812ddJack Palevich            egl.eglChooseConfig(display, s_configAttribs2, null, 0, num_config);
11550d0b14689b0ae95ea7b66a8c2f7b955115812ddJack Palevich
11650d0b14689b0ae95ea7b66a8c2f7b955115812ddJack Palevich            int numConfigs = num_config[0];
11750d0b14689b0ae95ea7b66a8c2f7b955115812ddJack Palevich
11850d0b14689b0ae95ea7b66a8c2f7b955115812ddJack Palevich            if (numConfigs <= 0) {
11950d0b14689b0ae95ea7b66a8c2f7b955115812ddJack Palevich                throw new IllegalArgumentException("No configs match configSpec");
12050d0b14689b0ae95ea7b66a8c2f7b955115812ddJack Palevich            }
12150d0b14689b0ae95ea7b66a8c2f7b955115812ddJack Palevich            EGLConfig[] configs = new EGLConfig[numConfigs];
12250d0b14689b0ae95ea7b66a8c2f7b955115812ddJack Palevich            egl.eglChooseConfig(display, s_configAttribs2, configs, numConfigs, num_config);
12350d0b14689b0ae95ea7b66a8c2f7b955115812ddJack Palevich            // printConfigs(egl, display, configs);
12450d0b14689b0ae95ea7b66a8c2f7b955115812ddJack Palevich            return chooseConfig(egl, display, configs);
12550d0b14689b0ae95ea7b66a8c2f7b955115812ddJack Palevich        }
12650d0b14689b0ae95ea7b66a8c2f7b955115812ddJack Palevich
12750d0b14689b0ae95ea7b66a8c2f7b955115812ddJack Palevich        public EGLConfig chooseConfig(EGL10 egl, EGLDisplay display,
12850d0b14689b0ae95ea7b66a8c2f7b955115812ddJack Palevich                EGLConfig[] configs) {
12950d0b14689b0ae95ea7b66a8c2f7b955115812ddJack Palevich            EGLConfig closestConfig = null;
13050d0b14689b0ae95ea7b66a8c2f7b955115812ddJack Palevich            int closestDistance = 1000;
13150d0b14689b0ae95ea7b66a8c2f7b955115812ddJack Palevich            for(EGLConfig config : configs) {
13250d0b14689b0ae95ea7b66a8c2f7b955115812ddJack Palevich                int d = findConfigAttrib(egl, display, config,
13350d0b14689b0ae95ea7b66a8c2f7b955115812ddJack Palevich                        EGL10.EGL_DEPTH_SIZE, 0);
13450d0b14689b0ae95ea7b66a8c2f7b955115812ddJack Palevich                int s = findConfigAttrib(egl, display, config,
13550d0b14689b0ae95ea7b66a8c2f7b955115812ddJack Palevich                        EGL10.EGL_STENCIL_SIZE, 0);
13650d0b14689b0ae95ea7b66a8c2f7b955115812ddJack Palevich                if (d >= mDepthSize && s>= mStencilSize) {
13750d0b14689b0ae95ea7b66a8c2f7b955115812ddJack Palevich                    int r = findConfigAttrib(egl, display, config,
13850d0b14689b0ae95ea7b66a8c2f7b955115812ddJack Palevich                            EGL10.EGL_RED_SIZE, 0);
13950d0b14689b0ae95ea7b66a8c2f7b955115812ddJack Palevich                    int g = findConfigAttrib(egl, display, config,
14050d0b14689b0ae95ea7b66a8c2f7b955115812ddJack Palevich                             EGL10.EGL_GREEN_SIZE, 0);
14150d0b14689b0ae95ea7b66a8c2f7b955115812ddJack Palevich                    int b = findConfigAttrib(egl, display, config,
14250d0b14689b0ae95ea7b66a8c2f7b955115812ddJack Palevich                              EGL10.EGL_BLUE_SIZE, 0);
14350d0b14689b0ae95ea7b66a8c2f7b955115812ddJack Palevich                    int a = findConfigAttrib(egl, display, config,
14450d0b14689b0ae95ea7b66a8c2f7b955115812ddJack Palevich                            EGL10.EGL_ALPHA_SIZE, 0);
14550d0b14689b0ae95ea7b66a8c2f7b955115812ddJack Palevich                    int distance = Math.abs(r - mRedSize)
14650d0b14689b0ae95ea7b66a8c2f7b955115812ddJack Palevich                                + Math.abs(g - mGreenSize)
14750d0b14689b0ae95ea7b66a8c2f7b955115812ddJack Palevich                                + Math.abs(b - mBlueSize)
14850d0b14689b0ae95ea7b66a8c2f7b955115812ddJack Palevich                                + Math.abs(a - mAlphaSize);
14950d0b14689b0ae95ea7b66a8c2f7b955115812ddJack Palevich                    if (distance < closestDistance) {
15050d0b14689b0ae95ea7b66a8c2f7b955115812ddJack Palevich                        closestDistance = distance;
15150d0b14689b0ae95ea7b66a8c2f7b955115812ddJack Palevich                        closestConfig = config;
15250d0b14689b0ae95ea7b66a8c2f7b955115812ddJack Palevich                    }
15350d0b14689b0ae95ea7b66a8c2f7b955115812ddJack Palevich                }
15450d0b14689b0ae95ea7b66a8c2f7b955115812ddJack Palevich            }
15550d0b14689b0ae95ea7b66a8c2f7b955115812ddJack Palevich            return closestConfig;
15650d0b14689b0ae95ea7b66a8c2f7b955115812ddJack Palevich        }
15750d0b14689b0ae95ea7b66a8c2f7b955115812ddJack Palevich
15850d0b14689b0ae95ea7b66a8c2f7b955115812ddJack Palevich        private int findConfigAttrib(EGL10 egl, EGLDisplay display,
15950d0b14689b0ae95ea7b66a8c2f7b955115812ddJack Palevich                EGLConfig config, int attribute, int defaultValue) {
16050d0b14689b0ae95ea7b66a8c2f7b955115812ddJack Palevich
16150d0b14689b0ae95ea7b66a8c2f7b955115812ddJack Palevich            if (egl.eglGetConfigAttrib(display, config, attribute, mValue)) {
16250d0b14689b0ae95ea7b66a8c2f7b955115812ddJack Palevich                return mValue[0];
16350d0b14689b0ae95ea7b66a8c2f7b955115812ddJack Palevich            }
16450d0b14689b0ae95ea7b66a8c2f7b955115812ddJack Palevich            return defaultValue;
16550d0b14689b0ae95ea7b66a8c2f7b955115812ddJack Palevich        }
16650d0b14689b0ae95ea7b66a8c2f7b955115812ddJack Palevich
16750d0b14689b0ae95ea7b66a8c2f7b955115812ddJack Palevich        private void printConfigs(EGL10 egl, EGLDisplay display,
16850d0b14689b0ae95ea7b66a8c2f7b955115812ddJack Palevich            EGLConfig[] configs) {
16950d0b14689b0ae95ea7b66a8c2f7b955115812ddJack Palevich            int numConfigs = configs.length;
17050d0b14689b0ae95ea7b66a8c2f7b955115812ddJack Palevich            Log.w(TAG, String.format("%d configurations", numConfigs));
17150d0b14689b0ae95ea7b66a8c2f7b955115812ddJack Palevich            for (int i = 0; i < numConfigs; i++) {
17250d0b14689b0ae95ea7b66a8c2f7b955115812ddJack Palevich                Log.w(TAG, String.format("Configuration %d:\n", i));
17350d0b14689b0ae95ea7b66a8c2f7b955115812ddJack Palevich                printConfig(egl, display, configs[i]);
17450d0b14689b0ae95ea7b66a8c2f7b955115812ddJack Palevich            }
17550d0b14689b0ae95ea7b66a8c2f7b955115812ddJack Palevich        }
17650d0b14689b0ae95ea7b66a8c2f7b955115812ddJack Palevich
17750d0b14689b0ae95ea7b66a8c2f7b955115812ddJack Palevich        private void printConfig(EGL10 egl, EGLDisplay display,
17850d0b14689b0ae95ea7b66a8c2f7b955115812ddJack Palevich                EGLConfig config) {
17950d0b14689b0ae95ea7b66a8c2f7b955115812ddJack Palevich            int[] attributes = {
18050d0b14689b0ae95ea7b66a8c2f7b955115812ddJack Palevich                    EGL10.EGL_BUFFER_SIZE,
18150d0b14689b0ae95ea7b66a8c2f7b955115812ddJack Palevich                    EGL10.EGL_ALPHA_SIZE,
18250d0b14689b0ae95ea7b66a8c2f7b955115812ddJack Palevich                    EGL10.EGL_BLUE_SIZE,
18350d0b14689b0ae95ea7b66a8c2f7b955115812ddJack Palevich                    EGL10.EGL_GREEN_SIZE,
18450d0b14689b0ae95ea7b66a8c2f7b955115812ddJack Palevich                    EGL10.EGL_RED_SIZE,
18550d0b14689b0ae95ea7b66a8c2f7b955115812ddJack Palevich                    EGL10.EGL_DEPTH_SIZE,
18650d0b14689b0ae95ea7b66a8c2f7b955115812ddJack Palevich                    EGL10.EGL_STENCIL_SIZE,
18750d0b14689b0ae95ea7b66a8c2f7b955115812ddJack Palevich                    EGL10.EGL_CONFIG_CAVEAT,
18850d0b14689b0ae95ea7b66a8c2f7b955115812ddJack Palevich                    EGL10.EGL_CONFIG_ID,
18950d0b14689b0ae95ea7b66a8c2f7b955115812ddJack Palevich                    EGL10.EGL_LEVEL,
19050d0b14689b0ae95ea7b66a8c2f7b955115812ddJack Palevich                    EGL10.EGL_MAX_PBUFFER_HEIGHT,
19150d0b14689b0ae95ea7b66a8c2f7b955115812ddJack Palevich                    EGL10.EGL_MAX_PBUFFER_PIXELS,
19250d0b14689b0ae95ea7b66a8c2f7b955115812ddJack Palevich                    EGL10.EGL_MAX_PBUFFER_WIDTH,
19350d0b14689b0ae95ea7b66a8c2f7b955115812ddJack Palevich                    EGL10.EGL_NATIVE_RENDERABLE,
19450d0b14689b0ae95ea7b66a8c2f7b955115812ddJack Palevich                    EGL10.EGL_NATIVE_VISUAL_ID,
19550d0b14689b0ae95ea7b66a8c2f7b955115812ddJack Palevich                    EGL10.EGL_NATIVE_VISUAL_TYPE,
19650d0b14689b0ae95ea7b66a8c2f7b955115812ddJack Palevich                    0x3030, // EGL10.EGL_PRESERVED_RESOURCES,
19750d0b14689b0ae95ea7b66a8c2f7b955115812ddJack Palevich                    EGL10.EGL_SAMPLES,
19850d0b14689b0ae95ea7b66a8c2f7b955115812ddJack Palevich                    EGL10.EGL_SAMPLE_BUFFERS,
19950d0b14689b0ae95ea7b66a8c2f7b955115812ddJack Palevich                    EGL10.EGL_SURFACE_TYPE,
20050d0b14689b0ae95ea7b66a8c2f7b955115812ddJack Palevich                    EGL10.EGL_TRANSPARENT_TYPE,
20150d0b14689b0ae95ea7b66a8c2f7b955115812ddJack Palevich                    EGL10.EGL_TRANSPARENT_RED_VALUE,
20250d0b14689b0ae95ea7b66a8c2f7b955115812ddJack Palevich                    EGL10.EGL_TRANSPARENT_GREEN_VALUE,
20350d0b14689b0ae95ea7b66a8c2f7b955115812ddJack Palevich                    EGL10.EGL_TRANSPARENT_BLUE_VALUE,
20450d0b14689b0ae95ea7b66a8c2f7b955115812ddJack Palevich                    0x3039, // EGL10.EGL_BIND_TO_TEXTURE_RGB,
20550d0b14689b0ae95ea7b66a8c2f7b955115812ddJack Palevich                    0x303A, // EGL10.EGL_BIND_TO_TEXTURE_RGBA,
20650d0b14689b0ae95ea7b66a8c2f7b955115812ddJack Palevich                    0x303B, // EGL10.EGL_MIN_SWAP_INTERVAL,
20750d0b14689b0ae95ea7b66a8c2f7b955115812ddJack Palevich                    0x303C, // EGL10.EGL_MAX_SWAP_INTERVAL,
20850d0b14689b0ae95ea7b66a8c2f7b955115812ddJack Palevich                    EGL10.EGL_LUMINANCE_SIZE,
20950d0b14689b0ae95ea7b66a8c2f7b955115812ddJack Palevich                    EGL10.EGL_ALPHA_MASK_SIZE,
21050d0b14689b0ae95ea7b66a8c2f7b955115812ddJack Palevich                    EGL10.EGL_COLOR_BUFFER_TYPE,
21150d0b14689b0ae95ea7b66a8c2f7b955115812ddJack Palevich                    EGL10.EGL_RENDERABLE_TYPE,
21250d0b14689b0ae95ea7b66a8c2f7b955115812ddJack Palevich                    0x3042 // EGL10.EGL_CONFORMANT
21350d0b14689b0ae95ea7b66a8c2f7b955115812ddJack Palevich            };
21450d0b14689b0ae95ea7b66a8c2f7b955115812ddJack Palevich            String[] names = {
21550d0b14689b0ae95ea7b66a8c2f7b955115812ddJack Palevich                    "EGL_BUFFER_SIZE",
21650d0b14689b0ae95ea7b66a8c2f7b955115812ddJack Palevich                    "EGL_ALPHA_SIZE",
21750d0b14689b0ae95ea7b66a8c2f7b955115812ddJack Palevich                    "EGL_BLUE_SIZE",
21850d0b14689b0ae95ea7b66a8c2f7b955115812ddJack Palevich                    "EGL_GREEN_SIZE",
21950d0b14689b0ae95ea7b66a8c2f7b955115812ddJack Palevich                    "EGL_RED_SIZE",
22050d0b14689b0ae95ea7b66a8c2f7b955115812ddJack Palevich                    "EGL_DEPTH_SIZE",
22150d0b14689b0ae95ea7b66a8c2f7b955115812ddJack Palevich                    "EGL_STENCIL_SIZE",
22250d0b14689b0ae95ea7b66a8c2f7b955115812ddJack Palevich                    "EGL_CONFIG_CAVEAT",
22350d0b14689b0ae95ea7b66a8c2f7b955115812ddJack Palevich                    "EGL_CONFIG_ID",
22450d0b14689b0ae95ea7b66a8c2f7b955115812ddJack Palevich                    "EGL_LEVEL",
22550d0b14689b0ae95ea7b66a8c2f7b955115812ddJack Palevich                    "EGL_MAX_PBUFFER_HEIGHT",
22650d0b14689b0ae95ea7b66a8c2f7b955115812ddJack Palevich                    "EGL_MAX_PBUFFER_PIXELS",
22750d0b14689b0ae95ea7b66a8c2f7b955115812ddJack Palevich                    "EGL_MAX_PBUFFER_WIDTH",
22850d0b14689b0ae95ea7b66a8c2f7b955115812ddJack Palevich                    "EGL_NATIVE_RENDERABLE",
22950d0b14689b0ae95ea7b66a8c2f7b955115812ddJack Palevich                    "EGL_NATIVE_VISUAL_ID",
23050d0b14689b0ae95ea7b66a8c2f7b955115812ddJack Palevich                    "EGL_NATIVE_VISUAL_TYPE",
23150d0b14689b0ae95ea7b66a8c2f7b955115812ddJack Palevich                    "EGL_PRESERVED_RESOURCES",
23250d0b14689b0ae95ea7b66a8c2f7b955115812ddJack Palevich                    "EGL_SAMPLES",
23350d0b14689b0ae95ea7b66a8c2f7b955115812ddJack Palevich                    "EGL_SAMPLE_BUFFERS",
23450d0b14689b0ae95ea7b66a8c2f7b955115812ddJack Palevich                    "EGL_SURFACE_TYPE",
23550d0b14689b0ae95ea7b66a8c2f7b955115812ddJack Palevich                    "EGL_TRANSPARENT_TYPE",
23650d0b14689b0ae95ea7b66a8c2f7b955115812ddJack Palevich                    "EGL_TRANSPARENT_RED_VALUE",
23750d0b14689b0ae95ea7b66a8c2f7b955115812ddJack Palevich                    "EGL_TRANSPARENT_GREEN_VALUE",
23850d0b14689b0ae95ea7b66a8c2f7b955115812ddJack Palevich                    "EGL_TRANSPARENT_BLUE_VALUE",
23950d0b14689b0ae95ea7b66a8c2f7b955115812ddJack Palevich                    "EGL_BIND_TO_TEXTURE_RGB",
24050d0b14689b0ae95ea7b66a8c2f7b955115812ddJack Palevich                    "EGL_BIND_TO_TEXTURE_RGBA",
24150d0b14689b0ae95ea7b66a8c2f7b955115812ddJack Palevich                    "EGL_MIN_SWAP_INTERVAL",
24250d0b14689b0ae95ea7b66a8c2f7b955115812ddJack Palevich                    "EGL_MAX_SWAP_INTERVAL",
24350d0b14689b0ae95ea7b66a8c2f7b955115812ddJack Palevich                    "EGL_LUMINANCE_SIZE",
24450d0b14689b0ae95ea7b66a8c2f7b955115812ddJack Palevich                    "EGL_ALPHA_MASK_SIZE",
24550d0b14689b0ae95ea7b66a8c2f7b955115812ddJack Palevich                    "EGL_COLOR_BUFFER_TYPE",
24650d0b14689b0ae95ea7b66a8c2f7b955115812ddJack Palevich                    "EGL_RENDERABLE_TYPE",
24750d0b14689b0ae95ea7b66a8c2f7b955115812ddJack Palevich                    "EGL_CONFORMANT"
24850d0b14689b0ae95ea7b66a8c2f7b955115812ddJack Palevich            };
24950d0b14689b0ae95ea7b66a8c2f7b955115812ddJack Palevich            int[] value = new int[1];
25050d0b14689b0ae95ea7b66a8c2f7b955115812ddJack Palevich            for (int i = 0; i < attributes.length; i++) {
25150d0b14689b0ae95ea7b66a8c2f7b955115812ddJack Palevich                int attribute = attributes[i];
25250d0b14689b0ae95ea7b66a8c2f7b955115812ddJack Palevich                String name = names[i];
25350d0b14689b0ae95ea7b66a8c2f7b955115812ddJack Palevich                if ( egl.eglGetConfigAttrib(display, config, attribute, value)) {
25450d0b14689b0ae95ea7b66a8c2f7b955115812ddJack Palevich                    Log.w(TAG, String.format("  %s: %d\n", name, value[0]));
25550d0b14689b0ae95ea7b66a8c2f7b955115812ddJack Palevich                } else {
25650d0b14689b0ae95ea7b66a8c2f7b955115812ddJack Palevich                    // Log.w(TAG, String.format("  %s: failed\n", name));
25750d0b14689b0ae95ea7b66a8c2f7b955115812ddJack Palevich                    while (egl.eglGetError() != EGL10.EGL_SUCCESS);
25850d0b14689b0ae95ea7b66a8c2f7b955115812ddJack Palevich                }
25950d0b14689b0ae95ea7b66a8c2f7b955115812ddJack Palevich            }
26050d0b14689b0ae95ea7b66a8c2f7b955115812ddJack Palevich        }
26150d0b14689b0ae95ea7b66a8c2f7b955115812ddJack Palevich
26250d0b14689b0ae95ea7b66a8c2f7b955115812ddJack Palevich        // Subclasses can adjust these values:
26350d0b14689b0ae95ea7b66a8c2f7b955115812ddJack Palevich        protected int mRedSize;
26450d0b14689b0ae95ea7b66a8c2f7b955115812ddJack Palevich        protected int mGreenSize;
26550d0b14689b0ae95ea7b66a8c2f7b955115812ddJack Palevich        protected int mBlueSize;
26650d0b14689b0ae95ea7b66a8c2f7b955115812ddJack Palevich        protected int mAlphaSize;
26750d0b14689b0ae95ea7b66a8c2f7b955115812ddJack Palevich        protected int mDepthSize;
26850d0b14689b0ae95ea7b66a8c2f7b955115812ddJack Palevich        protected int mStencilSize;
26950d0b14689b0ae95ea7b66a8c2f7b955115812ddJack Palevich        private int[] mValue = new int[1];
27050d0b14689b0ae95ea7b66a8c2f7b955115812ddJack Palevich    }
27150d0b14689b0ae95ea7b66a8c2f7b955115812ddJack Palevich
27250d0b14689b0ae95ea7b66a8c2f7b955115812ddJack Palevich    private static class Renderer implements GLSurfaceView.Renderer {
27350d0b14689b0ae95ea7b66a8c2f7b955115812ddJack Palevich
27450d0b14689b0ae95ea7b66a8c2f7b955115812ddJack Palevich        public Renderer() {
27550d0b14689b0ae95ea7b66a8c2f7b955115812ddJack Palevich            mTriangleVertices = ByteBuffer.allocateDirect(mTriangleVerticesData.length * 4)
27650d0b14689b0ae95ea7b66a8c2f7b955115812ddJack Palevich                .order(ByteOrder.nativeOrder()).asFloatBuffer();
27750d0b14689b0ae95ea7b66a8c2f7b955115812ddJack Palevich            mTriangleVertices.put(mTriangleVerticesData).position(0);
27850d0b14689b0ae95ea7b66a8c2f7b955115812ddJack Palevich        }
27950d0b14689b0ae95ea7b66a8c2f7b955115812ddJack Palevich
28050d0b14689b0ae95ea7b66a8c2f7b955115812ddJack Palevich        public void onDrawFrame(GL10 gl) {
28150d0b14689b0ae95ea7b66a8c2f7b955115812ddJack Palevich            GLES20.glClearColor(0.0f, 0.0f, 1.0f, 1.0f);
28250d0b14689b0ae95ea7b66a8c2f7b955115812ddJack Palevich            GLES20.glClear( GLES20.GL_DEPTH_BUFFER_BIT | GLES20.GL_COLOR_BUFFER_BIT);
28350d0b14689b0ae95ea7b66a8c2f7b955115812ddJack Palevich            GLES20.glUseProgram(mProgram);
28450d0b14689b0ae95ea7b66a8c2f7b955115812ddJack Palevich            checkGlError("glUseProgram");
28550d0b14689b0ae95ea7b66a8c2f7b955115812ddJack Palevich
28650d0b14689b0ae95ea7b66a8c2f7b955115812ddJack Palevich            GLES20.glVertexAttribPointer(mvPositionHandle, 2, GLES20.GL_FLOAT, false, 0, mTriangleVertices);
28750d0b14689b0ae95ea7b66a8c2f7b955115812ddJack Palevich            checkGlError("glVertexAttribPointer");
28850d0b14689b0ae95ea7b66a8c2f7b955115812ddJack Palevich            GLES20.glEnableVertexAttribArray(mvPositionHandle);
28950d0b14689b0ae95ea7b66a8c2f7b955115812ddJack Palevich            checkGlError("glEnableVertexAttribArray");
29050d0b14689b0ae95ea7b66a8c2f7b955115812ddJack Palevich            GLES20.glDrawArrays(GLES20.GL_TRIANGLES, 0, 3);
29150d0b14689b0ae95ea7b66a8c2f7b955115812ddJack Palevich            checkGlError("glDrawArrays");
29250d0b14689b0ae95ea7b66a8c2f7b955115812ddJack Palevich
29350d0b14689b0ae95ea7b66a8c2f7b955115812ddJack Palevich        }
29450d0b14689b0ae95ea7b66a8c2f7b955115812ddJack Palevich
29550d0b14689b0ae95ea7b66a8c2f7b955115812ddJack Palevich        public void onSurfaceChanged(GL10 gl, int width, int height) {
29650d0b14689b0ae95ea7b66a8c2f7b955115812ddJack Palevich            GLES20.glViewport(0, 0, width, height);
29750d0b14689b0ae95ea7b66a8c2f7b955115812ddJack Palevich        }
29850d0b14689b0ae95ea7b66a8c2f7b955115812ddJack Palevich
29950d0b14689b0ae95ea7b66a8c2f7b955115812ddJack Palevich        public void onSurfaceCreated(GL10 gl, EGLConfig config) {
30050d0b14689b0ae95ea7b66a8c2f7b955115812ddJack Palevich            mProgram = createProgram(mVertexShader, mFragmentShader);
30150d0b14689b0ae95ea7b66a8c2f7b955115812ddJack Palevich            if (mProgram == 0) {
30250d0b14689b0ae95ea7b66a8c2f7b955115812ddJack Palevich                return;
30350d0b14689b0ae95ea7b66a8c2f7b955115812ddJack Palevich            }
30450d0b14689b0ae95ea7b66a8c2f7b955115812ddJack Palevich            mvPositionHandle = GLES20.glGetAttribLocation(mProgram, "vPosition");
30550d0b14689b0ae95ea7b66a8c2f7b955115812ddJack Palevich            checkGlError("glGetAttribLocation");
30650d0b14689b0ae95ea7b66a8c2f7b955115812ddJack Palevich            if (mvPositionHandle == -1) {
30750d0b14689b0ae95ea7b66a8c2f7b955115812ddJack Palevich                throw new RuntimeException("Could not get attrib location for vPosition");
30850d0b14689b0ae95ea7b66a8c2f7b955115812ddJack Palevich            }
30950d0b14689b0ae95ea7b66a8c2f7b955115812ddJack Palevich        }
31050d0b14689b0ae95ea7b66a8c2f7b955115812ddJack Palevich
31150d0b14689b0ae95ea7b66a8c2f7b955115812ddJack Palevich        private int loadShader(int shaderType, String source) {
31250d0b14689b0ae95ea7b66a8c2f7b955115812ddJack Palevich            int shader = GLES20.glCreateShader(shaderType);
31350d0b14689b0ae95ea7b66a8c2f7b955115812ddJack Palevich            if (shader != 0) {
31450d0b14689b0ae95ea7b66a8c2f7b955115812ddJack Palevich                GLES20.glShaderSource(shader, source);
31550d0b14689b0ae95ea7b66a8c2f7b955115812ddJack Palevich                GLES20.glCompileShader(shader);
31650d0b14689b0ae95ea7b66a8c2f7b955115812ddJack Palevich                int[] compiled = new int[1];
31750d0b14689b0ae95ea7b66a8c2f7b955115812ddJack Palevich                GLES20.glGetShaderiv(shader, GLES20.GL_COMPILE_STATUS, compiled, 0);
31850d0b14689b0ae95ea7b66a8c2f7b955115812ddJack Palevich                if (compiled[0] == 0) {
31950d0b14689b0ae95ea7b66a8c2f7b955115812ddJack Palevich                    Log.e(TAG, "Could not compile shader " + shaderType + ":");
32050d0b14689b0ae95ea7b66a8c2f7b955115812ddJack Palevich                    Log.e(TAG, GLES20.glGetShaderInfoLog(shader));
32150d0b14689b0ae95ea7b66a8c2f7b955115812ddJack Palevich                    GLES20.glDeleteShader(shader);
32250d0b14689b0ae95ea7b66a8c2f7b955115812ddJack Palevich                    shader = 0;
32350d0b14689b0ae95ea7b66a8c2f7b955115812ddJack Palevich                }
32450d0b14689b0ae95ea7b66a8c2f7b955115812ddJack Palevich            }
32550d0b14689b0ae95ea7b66a8c2f7b955115812ddJack Palevich            return shader;
32650d0b14689b0ae95ea7b66a8c2f7b955115812ddJack Palevich        }
32750d0b14689b0ae95ea7b66a8c2f7b955115812ddJack Palevich
32850d0b14689b0ae95ea7b66a8c2f7b955115812ddJack Palevich        private int createProgram(String vertexSource, String fragmentSource) {
32950d0b14689b0ae95ea7b66a8c2f7b955115812ddJack Palevich            int vertexShader = loadShader(GLES20.GL_VERTEX_SHADER, vertexSource);
33050d0b14689b0ae95ea7b66a8c2f7b955115812ddJack Palevich            if (vertexShader == 0) {
33150d0b14689b0ae95ea7b66a8c2f7b955115812ddJack Palevich                return 0;
33250d0b14689b0ae95ea7b66a8c2f7b955115812ddJack Palevich            }
33350d0b14689b0ae95ea7b66a8c2f7b955115812ddJack Palevich
33450d0b14689b0ae95ea7b66a8c2f7b955115812ddJack Palevich            int pixelShader = loadShader(GLES20.GL_FRAGMENT_SHADER, fragmentSource);
33550d0b14689b0ae95ea7b66a8c2f7b955115812ddJack Palevich            if (pixelShader == 0) {
33650d0b14689b0ae95ea7b66a8c2f7b955115812ddJack Palevich                return 0;
33750d0b14689b0ae95ea7b66a8c2f7b955115812ddJack Palevich            }
33850d0b14689b0ae95ea7b66a8c2f7b955115812ddJack Palevich
33950d0b14689b0ae95ea7b66a8c2f7b955115812ddJack Palevich            int program = GLES20.glCreateProgram();
34050d0b14689b0ae95ea7b66a8c2f7b955115812ddJack Palevich            if (program != 0) {
34150d0b14689b0ae95ea7b66a8c2f7b955115812ddJack Palevich                GLES20.glAttachShader(program, vertexShader);
34250d0b14689b0ae95ea7b66a8c2f7b955115812ddJack Palevich                checkGlError("glAttachShader");
34350d0b14689b0ae95ea7b66a8c2f7b955115812ddJack Palevich                GLES20.glAttachShader(program, pixelShader);
34450d0b14689b0ae95ea7b66a8c2f7b955115812ddJack Palevich                checkGlError("glAttachShader");
34550d0b14689b0ae95ea7b66a8c2f7b955115812ddJack Palevich                GLES20.glLinkProgram(program);
34650d0b14689b0ae95ea7b66a8c2f7b955115812ddJack Palevich                int[] linkStatus = new int[1];
34750d0b14689b0ae95ea7b66a8c2f7b955115812ddJack Palevich                GLES20.glGetProgramiv(program, GLES20.GL_LINK_STATUS, linkStatus, 0);
34850d0b14689b0ae95ea7b66a8c2f7b955115812ddJack Palevich                if (linkStatus[0] != GLES20.GL_TRUE) {
34950d0b14689b0ae95ea7b66a8c2f7b955115812ddJack Palevich                    Log.e(TAG, "Could not link program: ");
35050d0b14689b0ae95ea7b66a8c2f7b955115812ddJack Palevich                    Log.e(TAG, GLES20.glGetProgramInfoLog(program));
35150d0b14689b0ae95ea7b66a8c2f7b955115812ddJack Palevich                    GLES20.glDeleteProgram(program);
35250d0b14689b0ae95ea7b66a8c2f7b955115812ddJack Palevich                    program = 0;
35350d0b14689b0ae95ea7b66a8c2f7b955115812ddJack Palevich                }
35450d0b14689b0ae95ea7b66a8c2f7b955115812ddJack Palevich            }
35550d0b14689b0ae95ea7b66a8c2f7b955115812ddJack Palevich            return program;
35650d0b14689b0ae95ea7b66a8c2f7b955115812ddJack Palevich        }
35750d0b14689b0ae95ea7b66a8c2f7b955115812ddJack Palevich
35850d0b14689b0ae95ea7b66a8c2f7b955115812ddJack Palevich        private void checkGlError(String op) {
35950d0b14689b0ae95ea7b66a8c2f7b955115812ddJack Palevich            int error;
36050d0b14689b0ae95ea7b66a8c2f7b955115812ddJack Palevich            while ((error = GLES20.glGetError()) != GLES20.GL_NO_ERROR) {
36150d0b14689b0ae95ea7b66a8c2f7b955115812ddJack Palevich                Log.e(TAG, op + ": glError " + error);
36250d0b14689b0ae95ea7b66a8c2f7b955115812ddJack Palevich                throw new RuntimeException(op + ": glError " + error);
36350d0b14689b0ae95ea7b66a8c2f7b955115812ddJack Palevich            }
36450d0b14689b0ae95ea7b66a8c2f7b955115812ddJack Palevich        }
36550d0b14689b0ae95ea7b66a8c2f7b955115812ddJack Palevich
36650d0b14689b0ae95ea7b66a8c2f7b955115812ddJack Palevich        private final float[] mTriangleVerticesData = { 0.0f, 0.5f, -0.5f, -0.5f,
36750d0b14689b0ae95ea7b66a8c2f7b955115812ddJack Palevich                0.5f, -0.5f };
36850d0b14689b0ae95ea7b66a8c2f7b955115812ddJack Palevich
36950d0b14689b0ae95ea7b66a8c2f7b955115812ddJack Palevich        private FloatBuffer mTriangleVertices;
37050d0b14689b0ae95ea7b66a8c2f7b955115812ddJack Palevich
37150d0b14689b0ae95ea7b66a8c2f7b955115812ddJack Palevich        private final String mVertexShader = "attribute vec4 vPosition;\n"
37250d0b14689b0ae95ea7b66a8c2f7b955115812ddJack Palevich            + "void main() {\n"
37350d0b14689b0ae95ea7b66a8c2f7b955115812ddJack Palevich            + "  gl_Position = vPosition;\n"
37450d0b14689b0ae95ea7b66a8c2f7b955115812ddJack Palevich            + "}\n";
37550d0b14689b0ae95ea7b66a8c2f7b955115812ddJack Palevich
37650d0b14689b0ae95ea7b66a8c2f7b955115812ddJack Palevich        private final String mFragmentShader = "precision mediump float;\n"
37750d0b14689b0ae95ea7b66a8c2f7b955115812ddJack Palevich            + "void main() {\n"
37850d0b14689b0ae95ea7b66a8c2f7b955115812ddJack Palevich            + "  gl_FragColor = vec4(0.0, 1.0, 0.0, 1.0);\n"
37950d0b14689b0ae95ea7b66a8c2f7b955115812ddJack Palevich            + "}\n";
38050d0b14689b0ae95ea7b66a8c2f7b955115812ddJack Palevich
38150d0b14689b0ae95ea7b66a8c2f7b955115812ddJack Palevich        private int mProgram;
38250d0b14689b0ae95ea7b66a8c2f7b955115812ddJack Palevich        private int mvPositionHandle;
38350d0b14689b0ae95ea7b66a8c2f7b955115812ddJack Palevich
38450d0b14689b0ae95ea7b66a8c2f7b955115812ddJack Palevich    }
38550d0b14689b0ae95ea7b66a8c2f7b955115812ddJack Palevich}
38650d0b14689b0ae95ea7b66a8c2f7b955115812ddJack Palevich
387