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