GLDepthTestActivity.java revision b4dabadd89f8a6928b51e809eec6425a3df9b593
1/* 2 * Copyright (C) 2014 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.test.hwui; 18 19import android.app.Activity; 20import android.app.ActivityManager; 21import android.content.Context; 22import android.content.pm.ConfigurationInfo; 23import android.graphics.Bitmap; 24import android.graphics.BitmapFactory; 25import android.opengl.GLES20; 26import android.opengl.GLSurfaceView; 27import android.opengl.GLUtils; 28import android.opengl.Matrix; 29import android.os.Bundle; 30import android.os.SystemClock; 31import android.util.Log; 32 33 34import java.io.IOException; 35import java.io.InputStream; 36import java.nio.ByteBuffer; 37import java.nio.ByteOrder; 38import java.nio.FloatBuffer; 39 40import javax.microedition.khronos.egl.EGLConfig; 41import javax.microedition.khronos.opengles.GL10; 42 43/** 44 * This sample shows how to check for OpenGL ES 2.0 support at runtime, and then 45 * use either OpenGL ES 1.0 or OpenGL ES 2.0, as appropriate. 46 */ 47public class GLDepthTestActivity extends Activity { 48 @Override 49 protected void onCreate(Bundle savedInstanceState) { 50 super.onCreate(savedInstanceState); 51 mGLSurfaceView = new GLSurfaceView(this); 52 if (detectOpenGLES20()) { 53 // Tell the surface view we want to create an OpenGL ES 54 // 2.0-compatible 55 // context, and set an OpenGL ES 2.0-compatible renderer. 56 mGLSurfaceView.setEGLContextClientVersion(2); 57 mGLSurfaceView.setRenderer(new GLES20TriangleRenderer(this)); 58 } else { 59 throw new IllegalStateException("Can't find OGL ES2.0 context"); 60 } 61 setContentView(mGLSurfaceView); 62 } 63 64 private boolean detectOpenGLES20() { 65 ActivityManager am = 66 (ActivityManager) getSystemService(Context.ACTIVITY_SERVICE); 67 ConfigurationInfo info = am.getDeviceConfigurationInfo(); 68 return (info.reqGlEsVersion >= 0x20000); 69 } 70 71 @Override 72 protected void onResume() { 73 // Ideally a game should implement onResume() and onPause() 74 // to take appropriate action when the activity looses focus 75 super.onResume(); 76 mGLSurfaceView.onResume(); 77 } 78 79 @Override 80 protected void onPause() { 81 // Ideally a game should implement onResume() and onPause() 82 // to take appropriate action when the activity looses focus 83 super.onPause(); 84 mGLSurfaceView.onPause(); 85 } 86 87 private GLSurfaceView mGLSurfaceView; 88 89 /* 90 * Copyright (C) 2009 The Android Open Source Project Licensed under the 91 * Apache License, Version 2.0 (the "License"); you may not use this file 92 * except in compliance with the License. You may obtain a copy of the 93 * License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by 94 * applicable law or agreed to in writing, software distributed under the 95 * License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR 96 * CONDITIONS OF ANY KIND, either express or implied. See the License for 97 * the specific language governing permissions and limitations under the 98 * License. 99 */ 100 101 class GLES20TriangleRenderer implements GLSurfaceView.Renderer { 102 103 public GLES20TriangleRenderer(Context context) { 104 mContext = context; 105 mTriangleVertices = ByteBuffer.allocateDirect(mTriangleVerticesData.length 106 * FLOAT_SIZE_BYTES).order(ByteOrder.nativeOrder()).asFloatBuffer(); 107 mTriangleVertices.put(mTriangleVerticesData).position(0); 108 } 109 110 public void onDrawFrame(GL10 glUnused) { 111 // Ignore the passed-in GL10 interface, and use the GLES20 112 // class's static methods instead. 113 GLES20.glClearColor(0.0f, 0.0f, 1.0f, 1.0f); 114 GLES20.glClear(GLES20.GL_DEPTH_BUFFER_BIT | GLES20.GL_COLOR_BUFFER_BIT); 115 GLES20.glUseProgram(mProgram); 116 checkGlError("glUseProgram"); 117 118 GLES20.glActiveTexture(GLES20.GL_TEXTURE0); 119 GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, mTextureID); 120 121 mTriangleVertices.position(TRIANGLE_VERTICES_DATA_POS_OFFSET); 122 GLES20.glVertexAttribPointer(maPositionHandle, 3, GLES20.GL_FLOAT, false, 123 TRIANGLE_VERTICES_DATA_STRIDE_BYTES, mTriangleVertices); 124 checkGlError("glVertexAttribPointer maPosition"); 125 mTriangleVertices.position(TRIANGLE_VERTICES_DATA_UV_OFFSET); 126 GLES20.glEnableVertexAttribArray(maPositionHandle); 127 checkGlError("glEnableVertexAttribArray maPositionHandle"); 128 GLES20.glVertexAttribPointer(maTextureHandle, 2, GLES20.GL_FLOAT, false, 129 TRIANGLE_VERTICES_DATA_STRIDE_BYTES, mTriangleVertices); 130 checkGlError("glVertexAttribPointer maTextureHandle"); 131 GLES20.glEnableVertexAttribArray(maTextureHandle); 132 checkGlError("glEnableVertexAttribArray maTextureHandle"); 133 134 long time = SystemClock.uptimeMillis() % 4000L; 135 float angle = 0.090f * ((int) time); 136 Matrix.setRotateM(mMMatrix, 0, angle, 0, 0, 1.0f); 137 Matrix.multiplyMM(mMVPMatrix, 0, mVMatrix, 0, mMMatrix, 0); 138 Matrix.multiplyMM(mMVPMatrix, 0, mProjMatrix, 0, mMVPMatrix, 0); 139 140 GLES20.glUniformMatrix4fv(muMVPMatrixHandle, 1, false, mMVPMatrix, 0); 141 GLES20.glDrawArrays(GLES20.GL_TRIANGLES, 0, 3); 142 checkGlError("glDrawArrays"); 143 } 144 145 public void onSurfaceChanged(GL10 glUnused, int width, int height) { 146 // Ignore the passed-in GL10 interface, and use the GLES20 147 // class's static methods instead. 148 GLES20.glViewport(0, 0, width, height); 149 float ratio = (float) width / height; 150 Matrix.frustumM(mProjMatrix, 0, -ratio, ratio, -1, 1, 3, 7); 151 } 152 153 public void onSurfaceCreated(GL10 glUnused, EGLConfig config) { 154 // Ignore the passed-in GL10 interface, and use the GLES20 155 // class's static methods instead. 156 mProgram = createProgram(mVertexShader, mFragmentShader); 157 if (mProgram == 0) { 158 return; 159 } 160 maPositionHandle = GLES20.glGetAttribLocation(mProgram, "aPosition"); 161 checkGlError("glGetAttribLocation aPosition"); 162 if (maPositionHandle == -1) { 163 throw new RuntimeException("Could not get attrib location for aPosition"); 164 } 165 maTextureHandle = GLES20.glGetAttribLocation(mProgram, "aTextureCoord"); 166 checkGlError("glGetAttribLocation aTextureCoord"); 167 if (maTextureHandle == -1) { 168 throw new RuntimeException("Could not get attrib location for aTextureCoord"); 169 } 170 171 muMVPMatrixHandle = GLES20.glGetUniformLocation(mProgram, "uMVPMatrix"); 172 checkGlError("glGetUniformLocation uMVPMatrix"); 173 if (muMVPMatrixHandle == -1) { 174 throw new RuntimeException("Could not get attrib location for uMVPMatrix"); 175 } 176 177 /* 178 * Create our texture. This has to be done each time the surface is 179 * created. 180 */ 181 182 int[] textures = new int[1]; 183 GLES20.glGenTextures(1, textures, 0); 184 185 mTextureID = textures[0]; 186 GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, mTextureID); 187 188 GLES20.glTexParameterf(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MIN_FILTER, 189 GLES20.GL_NEAREST); 190 GLES20.glTexParameterf(GLES20.GL_TEXTURE_2D, 191 GLES20.GL_TEXTURE_MAG_FILTER, 192 GLES20.GL_LINEAR); 193 194 GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_WRAP_S, 195 GLES20.GL_REPEAT); 196 GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_WRAP_T, 197 GLES20.GL_REPEAT); 198 199 InputStream is = mContext.getResources() 200 .openRawResource(R.drawable.robot); 201 Bitmap bitmap; 202 try { 203 bitmap = BitmapFactory.decodeStream(is); 204 } finally { 205 try { 206 is.close(); 207 } catch (IOException e) { 208 // Ignore. 209 } 210 } 211 212 GLUtils.texImage2D(GLES20.GL_TEXTURE_2D, 0, bitmap, 0); 213 bitmap.recycle(); 214 215 Matrix.setLookAtM(mVMatrix, 0, 0, 0, -5, 0f, 0f, 0f, 0f, 1.0f, 0.0f); 216 } 217 218 private int loadShader(int shaderType, String source) { 219 int shader = GLES20.glCreateShader(shaderType); 220 if (shader != 0) { 221 GLES20.glShaderSource(shader, source); 222 GLES20.glCompileShader(shader); 223 int[] compiled = new int[1]; 224 GLES20.glGetShaderiv(shader, GLES20.GL_COMPILE_STATUS, compiled, 0); 225 if (compiled[0] == 0) { 226 Log.e(TAG, "Could not compile shader " + shaderType + ":"); 227 Log.e(TAG, GLES20.glGetShaderInfoLog(shader)); 228 GLES20.glDeleteShader(shader); 229 shader = 0; 230 } 231 } 232 return shader; 233 } 234 235 private int createProgram(String vertexSource, String fragmentSource) { 236 int vertexShader = loadShader(GLES20.GL_VERTEX_SHADER, vertexSource); 237 if (vertexShader == 0) { 238 return 0; 239 } 240 241 int pixelShader = loadShader(GLES20.GL_FRAGMENT_SHADER, fragmentSource); 242 if (pixelShader == 0) { 243 return 0; 244 } 245 246 int program = GLES20.glCreateProgram(); 247 if (program != 0) { 248 GLES20.glAttachShader(program, vertexShader); 249 checkGlError("glAttachShader"); 250 GLES20.glAttachShader(program, pixelShader); 251 checkGlError("glAttachShader"); 252 GLES20.glLinkProgram(program); 253 int[] linkStatus = new int[1]; 254 GLES20.glGetProgramiv(program, GLES20.GL_LINK_STATUS, linkStatus, 0); 255 if (linkStatus[0] != GLES20.GL_TRUE) { 256 Log.e(TAG, "Could not link program: "); 257 Log.e(TAG, GLES20.glGetProgramInfoLog(program)); 258 GLES20.glDeleteProgram(program); 259 program = 0; 260 } 261 } 262 return program; 263 } 264 265 private void checkGlError(String op) { 266 int error; 267 while ((error = GLES20.glGetError()) != GLES20.GL_NO_ERROR) { 268 Log.e(TAG, op + ": glError " + error); 269 throw new RuntimeException(op + ": glError " + error); 270 } 271 } 272 273 private static final int FLOAT_SIZE_BYTES = 4; 274 private static final int TRIANGLE_VERTICES_DATA_STRIDE_BYTES = 5 * FLOAT_SIZE_BYTES; 275 private static final int TRIANGLE_VERTICES_DATA_POS_OFFSET = 0; 276 private static final int TRIANGLE_VERTICES_DATA_UV_OFFSET = 3; 277 private final float[] mTriangleVerticesData = { 278 // X, Y, Z, U, V 279 -1.0f, -0.5f, 0, -0.5f, 0.0f, 280 1.0f, -0.5f, 0, 1.5f, -0.0f, 281 0.0f, 1.11803399f, 0, 0.5f, 1.61803399f }; 282 283 private FloatBuffer mTriangleVertices; 284 285 private final String mVertexShader = 286 "uniform mat4 uMVPMatrix;\n" + 287 "attribute vec4 aPosition;\n" + 288 "attribute vec2 aTextureCoord;\n" + 289 "varying vec2 vTextureCoord;\n" + 290 "void main() {\n" + 291 " gl_Position = uMVPMatrix * aPosition;\n" + 292 " vTextureCoord = aTextureCoord;\n" + 293 "}\n"; 294 295 private final String mFragmentShader = 296 "precision mediump float;\n" + 297 "varying vec2 vTextureCoord;\n" + 298 "uniform sampler2D sTexture;\n" + 299 "void main() {\n" + 300 " gl_FragColor = texture2D(sTexture, vTextureCoord);\n" + 301 "}\n"; 302 303 private float[] mMVPMatrix = new float[16]; 304 private float[] mProjMatrix = new float[16]; 305 private float[] mMMatrix = new float[16]; 306 private float[] mVMatrix = new float[16]; 307 308 private int mProgram; 309 private int mTextureID; 310 private int muMVPMatrixHandle; 311 private int maPositionHandle; 312 private int maTextureHandle; 313 314 private Context mContext; 315 private static final String TAG = "GLES20TriangleRenderer"; 316 } 317 318} 319