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