1/*
2 * Copyright (C) 2009 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *      http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package com.android.gl2java;
18
19import android.content.Context;
20import android.opengl.GLSurfaceView;
21import android.util.AttributeSet;
22import android.util.Log;
23import android.view.KeyEvent;
24import android.view.MotionEvent;
25
26import java.nio.ByteBuffer;
27import java.nio.ByteOrder;
28import java.nio.FloatBuffer;
29
30import javax.microedition.khronos.egl.EGL10;
31import javax.microedition.khronos.egl.EGLConfig;
32import javax.microedition.khronos.egl.EGLContext;
33import javax.microedition.khronos.egl.EGLDisplay;
34import javax.microedition.khronos.opengles.GL10;
35
36import android.opengl.GLES20;
37
38/**
39 * An implementation of SurfaceView that uses the dedicated surface for
40 * displaying an OpenGL animation.  This allows the animation to run in a
41 * separate thread, without requiring that it be driven by the update mechanism
42 * of the view hierarchy.
43 *
44 * The application-specific rendering code is delegated to a GLView.Renderer
45 * instance.
46 */
47class GL2JavaView extends GLSurfaceView {
48    private static String TAG = "GL2JavaView";
49
50    public GL2JavaView(Context context) {
51        super(context);
52        setEGLContextClientVersion(2);
53        setRenderer(new Renderer());
54    }
55
56    private static class Renderer implements GLSurfaceView.Renderer {
57
58        public Renderer() {
59            mTriangleVertices = ByteBuffer.allocateDirect(mTriangleVerticesData.length * 4)
60                .order(ByteOrder.nativeOrder()).asFloatBuffer();
61            mTriangleVertices.put(mTriangleVerticesData).position(0);
62        }
63
64        public void onDrawFrame(GL10 gl) {
65            GLES20.glClearColor(0.0f, 0.0f, 1.0f, 1.0f);
66            GLES20.glClear( GLES20.GL_DEPTH_BUFFER_BIT | GLES20.GL_COLOR_BUFFER_BIT);
67            GLES20.glUseProgram(mProgram);
68            checkGlError("glUseProgram");
69
70            GLES20.glVertexAttribPointer(mvPositionHandle, 2, GLES20.GL_FLOAT, false, 0, mTriangleVertices);
71            checkGlError("glVertexAttribPointer");
72            GLES20.glEnableVertexAttribArray(mvPositionHandle);
73            checkGlError("glEnableVertexAttribArray");
74            GLES20.glDrawArrays(GLES20.GL_TRIANGLES, 0, 3);
75            checkGlError("glDrawArrays");
76
77        }
78
79        public void onSurfaceChanged(GL10 gl, int width, int height) {
80            GLES20.glViewport(0, 0, width, height);
81        }
82
83        public void onSurfaceCreated(GL10 gl, EGLConfig config) {
84            mProgram = createProgram(mVertexShader, mFragmentShader);
85            if (mProgram == 0) {
86                return;
87            }
88            mvPositionHandle = GLES20.glGetAttribLocation(mProgram, "vPosition");
89            checkGlError("glGetAttribLocation");
90            if (mvPositionHandle == -1) {
91                throw new RuntimeException("Could not get attrib location for vPosition");
92            }
93        }
94
95        private int loadShader(int shaderType, String source) {
96            int shader = GLES20.glCreateShader(shaderType);
97            if (shader != 0) {
98                GLES20.glShaderSource(shader, source);
99                GLES20.glCompileShader(shader);
100                int[] compiled = new int[1];
101                GLES20.glGetShaderiv(shader, GLES20.GL_COMPILE_STATUS, compiled, 0);
102                if (compiled[0] == 0) {
103                    Log.e(TAG, "Could not compile shader " + shaderType + ":");
104                    Log.e(TAG, GLES20.glGetShaderInfoLog(shader));
105                    GLES20.glDeleteShader(shader);
106                    shader = 0;
107                }
108            }
109            return shader;
110        }
111
112        private int createProgram(String vertexSource, String fragmentSource) {
113            int vertexShader = loadShader(GLES20.GL_VERTEX_SHADER, vertexSource);
114            if (vertexShader == 0) {
115                return 0;
116            }
117
118            int pixelShader = loadShader(GLES20.GL_FRAGMENT_SHADER, fragmentSource);
119            if (pixelShader == 0) {
120                return 0;
121            }
122
123            int program = GLES20.glCreateProgram();
124            if (program != 0) {
125                GLES20.glAttachShader(program, vertexShader);
126                checkGlError("glAttachShader");
127                GLES20.glAttachShader(program, pixelShader);
128                checkGlError("glAttachShader");
129                GLES20.glLinkProgram(program);
130                int[] linkStatus = new int[1];
131                GLES20.glGetProgramiv(program, GLES20.GL_LINK_STATUS, linkStatus, 0);
132                if (linkStatus[0] != GLES20.GL_TRUE) {
133                    Log.e(TAG, "Could not link program: ");
134                    Log.e(TAG, GLES20.glGetProgramInfoLog(program));
135                    GLES20.glDeleteProgram(program);
136                    program = 0;
137                }
138            }
139            return program;
140        }
141
142        private void checkGlError(String op) {
143            int error;
144            while ((error = GLES20.glGetError()) != GLES20.GL_NO_ERROR) {
145                Log.e(TAG, op + ": glError " + error);
146                throw new RuntimeException(op + ": glError " + error);
147            }
148        }
149
150        private final float[] mTriangleVerticesData = { 0.0f, 0.5f, -0.5f, -0.5f,
151                0.5f, -0.5f };
152
153        private FloatBuffer mTriangleVertices;
154
155        private final String mVertexShader = "attribute vec4 vPosition;\n"
156            + "void main() {\n"
157            + "  gl_Position = vPosition;\n"
158            + "}\n";
159
160        private final String mFragmentShader = "precision mediump float;\n"
161            + "void main() {\n"
162            + "  gl_FragColor = vec4(0.0, 1.0, 0.0, 1.0);\n"
163            + "}\n";
164
165        private int mProgram;
166        private int mvPositionHandle;
167
168    }
169}
170
171