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 17 package com.android.test; 18 /* 19 * Copyright (C) 2008 The Android Open Source Project 20 * 21 * Licensed under the Apache License, Version 2.0 (the "License"); 22 * you may not use this file except in compliance with the License. 23 * You may obtain a copy of the License at 24 * 25 * http://www.apache.org/licenses/LICENSE-2.0 26 * 27 * Unless required by applicable law or agreed to in writing, software 28 * distributed under the License is distributed on an "AS IS" BASIS, 29 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 30 * See the License for the specific language governing permissions and 31 * limitations under the License. 32 */ 33 34 import java.nio.ByteBuffer; 35 import java.nio.ByteOrder; 36 import java.nio.CharBuffer; 37 import java.nio.FloatBuffer; 38 39 import android.content.Context; 40 import android.opengl.GLSurfaceView; 41 import android.util.AttributeSet; 42 import android.util.Log; 43 import android.view.KeyEvent; 44 import android.view.MotionEvent; 45 46 import javax.microedition.khronos.egl.EGL10; 47 import javax.microedition.khronos.egl.EGLConfig; 48 import javax.microedition.khronos.opengles.GL; 49 import javax.microedition.khronos.opengles.GL10; 50 import javax.microedition.khronos.opengles.GL11; 51 /** 52 * An implementation of SurfaceView that uses the dedicated surface for 53 * displaying an OpenGL animation. This allows the animation to run in a 54 * separate thread, without requiring that it be driven by the update mechanism 55 * of the view hierarchy. 56 * 57 * The application-specific rendering code is delegated to a GLView.Renderer 58 * instance. 59 */ 60 class TestView extends GLSurfaceView { TestView(Context context)61 TestView(Context context) { 62 super(context); 63 init(); 64 } 65 TestView(Context context, AttributeSet attrs)66 public TestView(Context context, AttributeSet attrs) { 67 super(context, attrs); 68 init(); 69 } 70 init()71 private void init() { 72 setRenderer(new Renderer()); 73 setRenderMode(RENDERMODE_WHEN_DIRTY); 74 } 75 76 /** A grid is a topologically rectangular array of vertices. 77 * 78 * The vertex and index data are held in VBO objects because on most 79 * GPUs VBO objects are the fastest way of rendering static vertex 80 * and index data. 81 * 82 */ 83 84 private static class Grid { 85 // Size of vertex data elements in bytes: 86 final static int FLOAT_SIZE = 4; 87 final static int CHAR_SIZE = 2; 88 89 // Vertex structure: 90 // float x, y, z; 91 92 final static int VERTEX_SIZE = 3 * FLOAT_SIZE; 93 94 private int mVertexBufferObjectId; 95 private int mElementBufferObjectId; 96 97 // These buffers are used to hold the vertex and index data while 98 // constructing the grid. Once createBufferObjects() is called 99 // the buffers are nulled out to save memory. 100 101 private ByteBuffer mVertexByteBuffer; 102 private FloatBuffer mVertexBuffer; 103 private CharBuffer mIndexBuffer; 104 105 private int mW; 106 private int mH; 107 private int mIndexCount; 108 Grid(int w, int h)109 public Grid(int w, int h) { 110 if (w < 0 || w >= 65536) { 111 throw new IllegalArgumentException("w"); 112 } 113 if (h < 0 || h >= 65536) { 114 throw new IllegalArgumentException("h"); 115 } 116 if (w * h >= 65536) { 117 throw new IllegalArgumentException("w * h >= 65536"); 118 } 119 120 mW = w; 121 mH = h; 122 int size = w * h; 123 124 mVertexByteBuffer = ByteBuffer.allocateDirect(VERTEX_SIZE * size) 125 .order(ByteOrder.nativeOrder()); 126 mVertexBuffer = mVertexByteBuffer.asFloatBuffer(); 127 128 int quadW = mW - 1; 129 int quadH = mH - 1; 130 int quadCount = quadW * quadH; 131 int indexCount = quadCount * 6; 132 mIndexCount = indexCount; 133 mIndexBuffer = ByteBuffer.allocateDirect(CHAR_SIZE * indexCount) 134 .order(ByteOrder.nativeOrder()).asCharBuffer(); 135 136 /* 137 * Initialize triangle list mesh. 138 * 139 * [0]-----[ 1] ... 140 * | / | 141 * | / | 142 * | / | 143 * [w]-----[w+1] ... 144 * | | 145 * 146 */ 147 148 { 149 int i = 0; 150 for (int y = 0; y < quadH; y++) { 151 for (int x = 0; x < quadW; x++) { 152 char a = (char) (y * mW + x); 153 char b = (char) (y * mW + x + 1); 154 char c = (char) ((y + 1) * mW + x); 155 char d = (char) ((y + 1) * mW + x + 1); 156 157 mIndexBuffer.put(i++, a); 158 mIndexBuffer.put(i++, c); 159 mIndexBuffer.put(i++, b); 160 161 mIndexBuffer.put(i++, b); 162 mIndexBuffer.put(i++, c); 163 mIndexBuffer.put(i++, d); 164 } 165 } 166 } 167 168 } 169 set(int i, int j, float x, float y, float z)170 public void set(int i, int j, float x, float y, float z) { 171 if (i < 0 || i >= mW) { 172 throw new IllegalArgumentException("i"); 173 } 174 if (j < 0 || j >= mH) { 175 throw new IllegalArgumentException("j"); 176 } 177 178 int index = mW * j + i; 179 180 mVertexBuffer.position(index * VERTEX_SIZE / FLOAT_SIZE); 181 mVertexBuffer.put(x); 182 mVertexBuffer.put(y); 183 mVertexBuffer.put(z); 184 } 185 createBufferObjects(GL gl)186 public void createBufferObjects(GL gl) { 187 // Generate a the vertex and element buffer IDs 188 int[] vboIds = new int[2]; 189 GL11 gl11 = (GL11) gl; 190 gl11.glGenBuffers(2, vboIds, 0); 191 mVertexBufferObjectId = vboIds[0]; 192 mElementBufferObjectId = vboIds[1]; 193 194 // Upload the vertex data 195 gl11.glBindBuffer(GL11.GL_ARRAY_BUFFER, mVertexBufferObjectId); 196 mVertexByteBuffer.position(0); 197 gl11.glBufferData(GL11.GL_ARRAY_BUFFER, mVertexByteBuffer.capacity(), mVertexByteBuffer, GL11.GL_STATIC_DRAW); 198 199 gl11.glBindBuffer(GL11.GL_ELEMENT_ARRAY_BUFFER, mElementBufferObjectId); 200 mIndexBuffer.position(0); 201 gl11.glBufferData(GL11.GL_ELEMENT_ARRAY_BUFFER, mIndexBuffer.capacity() * CHAR_SIZE, mIndexBuffer, GL11.GL_STATIC_DRAW); 202 203 // We don't need the in-memory data any more 204 mVertexBuffer = null; 205 mVertexByteBuffer = null; 206 mIndexBuffer = null; 207 } 208 draw(GL10 gl)209 public void draw(GL10 gl) { 210 GL11 gl11 = (GL11) gl; 211 212 gl.glEnableClientState(GL10.GL_VERTEX_ARRAY); 213 214 gl11.glBindBuffer(GL11.GL_ARRAY_BUFFER, mVertexBufferObjectId); 215 gl11.glVertexPointer(3, GL10.GL_FLOAT, VERTEX_SIZE, 0); 216 217 gl11.glBindBuffer(GL11.GL_ELEMENT_ARRAY_BUFFER, mElementBufferObjectId); 218 gl11.glDrawElements(GL10.GL_TRIANGLES, mIndexCount, GL10.GL_UNSIGNED_SHORT, 0); 219 gl.glDisableClientState(GL10.GL_VERTEX_ARRAY); 220 gl11.glBindBuffer(GL11.GL_ARRAY_BUFFER, 0); 221 gl11.glBindBuffer(GL11.GL_ELEMENT_ARRAY_BUFFER, 0); 222 } 223 } 224 225 226 private class Renderer implements GLSurfaceView.Renderer { 227 private static final String TAG = "Renderer"; 228 private Grid mGrid; 229 onDrawFrame(GL10 gl)230 public void onDrawFrame(GL10 gl) { 231 gl.glClearColor(0,0,1,1); 232 gl.glClear(GL10.GL_COLOR_BUFFER_BIT); 233 mGrid.draw(gl); 234 } 235 onSurfaceChanged(GL10 gl, int width, int height)236 public void onSurfaceChanged(GL10 gl, int width, int height) { 237 gl.glViewport(0, 0, width, height); 238 gl.glMatrixMode(GL11.GL_PROJECTION); 239 gl.glLoadIdentity(); 240 gl.glOrthof(0, width, height, 0, -1, 1); 241 gl.glMatrixMode(GL11.GL_MODELVIEW); 242 createGrid(gl, width, height); 243 } 244 onSurfaceCreated(GL10 gl, EGLConfig config)245 public void onSurfaceCreated(GL10 gl, EGLConfig config) { 246 } 247 createGrid(GL10 gl, float w, float h)248 private void createGrid(GL10 gl, float w, float h) { 249 mGrid = new Grid(2, 2); 250 for (int j = 0; j < 2; j++) { 251 for (int i = 0; i < 2; i++) { 252 float x = w * i; 253 float y = h * j; 254 float z = 0.0f; 255 mGrid.set(i,j, x, y, z); 256 } 257 } 258 mGrid.createBufferObjects(gl); 259 } 260 } 261 } 262 263