--- /dev/null
+package com.cooliris.media;
+
+import java.nio.ByteBuffer;
+import java.nio.ByteOrder;
+import java.nio.CharBuffer;
+import java.nio.FloatBuffer;
+
+import javax.microedition.khronos.opengles.GL10;
+import javax.microedition.khronos.opengles.GL11;
+
+final class GridQuadFrame {
+ private FloatBuffer mVertexBuffer;
+ private FloatBuffer mTexCoordBuffer;
+ private FloatBuffer mSecTexCoordBuffer;
+ private CharBuffer mIndexBuffer;
+
+ private int mW;
+ private int mH;
+
+ // This has 8 quads, 16 vertices, 22 triangles (for tristrip).
+ // We have more triangles because we have to make degenerate triangles to
+ // use tri-strips
+ public static final int INDEX_COUNT = 25;
+ private int mVertBufferIndex;
+ private int mIndexBufferIndex;
+ private int mTextureCoordBufferIndex;
+ private int mSecTextureCoordBufferIndex;
+
+ public static GridQuadFrame createFrame(float width, float height, int itemWidth, int itemHeight) {
+ GridQuadFrame frame = new GridQuadFrame();
+ final float textureSize = 64.0f;
+ final float numPixelsYOriginShift = 7;
+ final float inset = 6;
+ final float ratio = 1.0f / (float) itemHeight;
+ final float frameXThickness = 0.5f * textureSize * ratio;
+ final float frameYThickness = 0.5f * textureSize * ratio;
+ final float frameX = width * 0.5f + frameXThickness * 0.5f - inset * ratio;
+ float frameY = height * 0.5f + frameYThickness * 0.5f + (inset - 1) * ratio;
+ final float originX = 0.0f;
+ final float originY = numPixelsYOriginShift * ratio;
+
+ frame.set(0, 0, -frameX + originX, -frameY + originY, 0, 1.0f, 1.0f);
+ frame.set(1, 0, -frameX + originX + frameXThickness, -frameY + originY, 0, 0.5f, 1.0f);
+ frame.set(2, 0, frameX - frameXThickness + originX, -frameY + originY, 0, 0.5f, 1.0f);
+ frame.set(3, 0, frameX + originX, -frameY + originY, 0, 0.0f, 1.0f);
+
+ frameY -= frameYThickness;
+
+ frame.set(0, 1, -frameX + originX, -frameY + originY, 0, 1.0f, 0.5f);
+ frame.set(1, 1, -frameX + frameXThickness + originX, -frameY + originY, 0, 0.5f, 0.5f);
+ frame.set(2, 1, frameX - frameXThickness + originX, -frameY + originY, 0, 0.5f, 0.5f);
+ frame.set(3, 1, frameX + originX, -frameY + originY, 0, 0.0f, 0.5f);
+
+ frameY = height * 0.5f - frameYThickness;
+
+ frame.set(0, 2, -frameX + originX, frameY + originY, 0, 1.0f, 0.5f);
+ frame.set(1, 2, -frameX + frameXThickness + originX, frameY + originY, 0, 0.5f, 0.5f);
+ frame.set(2, 2, frameX - frameXThickness + originX, frameY + originY, 0, 0.5f, 0.5f);
+ frame.set(3, 2, frameX + originX, frameY + originY, 0, 0.0f, 0.5f);
+
+ frameY += frameYThickness;
+
+ frame.set(0, 3, -frameX + originX, frameY + originY, 0, 1.0f, 0.0f);
+ frame.set(1, 3, -frameX + frameXThickness + originX, frameY + originY, 0, 0.5f, 0.0f);
+ frame.set(2, 3, frameX - frameXThickness + originX, frameY + originY, 0, 0.5f, 0.0f);
+ frame.set(3, 3, frameX + originX, frameY + originY, 0, 0.0f, 0.0f);
+
+ return frame;
+ }
+
+ public GridQuadFrame() {
+ int vertsAcross = 4;
+ int vertsDown = 4;
+ mW = vertsAcross;
+ mH = vertsDown;
+ int size = vertsAcross * vertsDown;
+ final int FLOAT_SIZE = 4;
+ final int CHAR_SIZE = 2;
+ mVertexBuffer = ByteBuffer.allocateDirect(FLOAT_SIZE * size * 3).order(ByteOrder.nativeOrder()).asFloatBuffer();
+ mTexCoordBuffer = ByteBuffer.allocateDirect(FLOAT_SIZE * size * 2).order(ByteOrder.nativeOrder()).asFloatBuffer();
+ mSecTexCoordBuffer = ByteBuffer.allocateDirect(FLOAT_SIZE * size * 2).order(ByteOrder.nativeOrder()).asFloatBuffer();
+
+ int indexCount = INDEX_COUNT; // using tristrips
+ mIndexBuffer = ByteBuffer.allocateDirect(CHAR_SIZE * indexCount).order(ByteOrder.nativeOrder()).asCharBuffer();
+
+ /*
+ * Initialize triangle list mesh.
+ *
+ * [0]---[1]---------[2]---[3] ... | / | / | / |
+ * [4]---[5]---------[6]---[7] | / | | /| | / | | / | | / | | / |
+ * [8]---[9]---------[10]---[11] | / | \ | \ |
+ * [12]--[13]--------[14]---[15]
+ */
+ CharBuffer buffer = mIndexBuffer;
+ buffer.put(0, (char) 0);
+ buffer.put(1, (char) 4);
+ buffer.put(2, (char) 1);
+ buffer.put(3, (char) 5);
+ buffer.put(4, (char) 2);
+ buffer.put(5, (char) 6);
+ buffer.put(6, (char) 3);
+ buffer.put(7, (char) 7);
+ buffer.put(8, (char) 11);
+ buffer.put(9, (char) 6);
+ buffer.put(10, (char) 10);
+ buffer.put(11, (char) 14);
+ buffer.put(12, (char) 11);
+ buffer.put(13, (char) 15);
+ buffer.put(14, (char) 15);
+ buffer.put(15, (char) 14);
+ buffer.put(16, (char) 14);
+ buffer.put(17, (char) 10);
+ buffer.put(18, (char) 13);
+ buffer.put(19, (char) 9);
+ buffer.put(20, (char) 12);
+ buffer.put(21, (char) 8);
+ buffer.put(22, (char) 4);
+ buffer.put(23, (char) 9);
+ buffer.put(24, (char) 5);
+ mVertBufferIndex = 0;
+ }
+
+ void set(int i, int j, float x, float y, float z, float u, float v) {
+ if (i < 0 || i >= mW) {
+ throw new IllegalArgumentException("i");
+ }
+ if (j < 0 || j >= mH) {
+ throw new IllegalArgumentException("j");
+ }
+
+ int index = mW * j + i;
+
+ int posIndex = index * 3;
+ mVertexBuffer.put(posIndex, x);
+ mVertexBuffer.put(posIndex + 1, y);
+ mVertexBuffer.put(posIndex + 2, z);
+
+ int texIndex = index * 2;
+ mTexCoordBuffer.put(texIndex, u);
+ mTexCoordBuffer.put(texIndex + 1, v);
+
+ int secTexIndex = index * 2;
+ mSecTexCoordBuffer.put(secTexIndex, u);
+ mSecTexCoordBuffer.put(secTexIndex + 1, v);
+ }
+
+ public void bindArrays(GL10 gl) {
+ GL11 gl11 = (GL11) gl;
+ // draw using hardware buffers
+ gl11.glBindBuffer(GL11.GL_ARRAY_BUFFER, mVertBufferIndex);
+ gl11.glVertexPointer(3, GL11.GL_FLOAT, 0, 0);
+
+ gl11.glBindBuffer(GL11.GL_ARRAY_BUFFER, mTextureCoordBufferIndex);
+ gl11.glTexCoordPointer(2, GL11.GL_FLOAT, 0, 0);
+ gl11.glClientActiveTexture(GL11.GL_TEXTURE1);
+ gl11.glBindBuffer(GL11.GL_ARRAY_BUFFER, mSecTextureCoordBufferIndex);
+ gl11.glTexCoordPointer(2, GL11.GL_FLOAT, 0, 0);
+ gl11.glClientActiveTexture(GL11.GL_TEXTURE0);
+ gl11.glBindBuffer(GL11.GL_ELEMENT_ARRAY_BUFFER, mIndexBufferIndex);
+ }
+
+ public static final void draw(GL11 gl11) {
+ // Don't call this method unless bindArrays was called.
+ gl11.glDrawElements(GL11.GL_TRIANGLE_STRIP, INDEX_COUNT, GL11.GL_UNSIGNED_SHORT, 0);
+ }
+
+ public void unbindArrays(GL10 gl) {
+ GL11 gl11 = (GL11) gl;
+ gl11.glBindBuffer(GL11.GL_ARRAY_BUFFER, 0);
+ gl11.glBindBuffer(GL11.GL_ELEMENT_ARRAY_BUFFER, 0);
+ }
+
+ public boolean usingHardwareBuffers() {
+ return mVertBufferIndex != 0;
+ }
+
+ /**
+ * When the OpenGL ES device is lost, GL handles become invalidated. In that
+ * case, we just want to "forget" the old handles (without explicitly
+ * deleting them) and make new ones.
+ */
+ public void forgetHardwareBuffers() {
+ mVertBufferIndex = 0;
+ mIndexBufferIndex = 0;
+ mTextureCoordBufferIndex = 0;
+ mSecTextureCoordBufferIndex = 0;
+ }
+
+ /**
+ * Deletes the hardware buffers allocated by this object (if any).
+ */
+ public void freeHardwareBuffers(GL10 gl) {
+ if (mVertBufferIndex != 0) {
+ if (gl instanceof GL11) {
+ GL11 gl11 = (GL11) gl;
+ int[] buffer = new int[1];
+ buffer[0] = mVertBufferIndex;
+ gl11.glDeleteBuffers(1, buffer, 0);
+
+ buffer[0] = mTextureCoordBufferIndex;
+ gl11.glDeleteBuffers(1, buffer, 0);
+
+ buffer[0] = mSecTextureCoordBufferIndex;
+ gl11.glDeleteBuffers(1, buffer, 0);
+
+ buffer[0] = mIndexBufferIndex;
+ gl11.glDeleteBuffers(1, buffer, 0);
+ }
+ forgetHardwareBuffers();
+ }
+ }
+
+ /**
+ * Allocates hardware buffers on the graphics card and fills them with data
+ * if a buffer has not already been previously allocated. Note that this
+ * function uses the GL_OES_vertex_buffer_object extension, which is not
+ * guaranteed to be supported on every device.
+ *
+ * @param gl
+ * A pointer to the OpenGL ES context.
+ */
+ public void generateHardwareBuffers(GL10 gl) {
+ if (mVertBufferIndex == 0) {
+ if (gl instanceof GL11) {
+ GL11 gl11 = (GL11) gl;
+ int[] buffer = new int[1];
+
+ // Allocate and fill the vertex buffer.
+ gl11.glGenBuffers(1, buffer, 0);
+ mVertBufferIndex = buffer[0];
+ gl11.glBindBuffer(GL11.GL_ARRAY_BUFFER, mVertBufferIndex);
+ mVertexBuffer.position(0);
+ final int vertexSize = mVertexBuffer.capacity() * 4;
+ gl11.glBufferData(GL11.GL_ARRAY_BUFFER, vertexSize, mVertexBuffer, GL11.GL_STATIC_DRAW);
+
+ // Allocate and fill the texture coordinate buffer.
+ gl11.glGenBuffers(1, buffer, 0);
+ mTextureCoordBufferIndex = buffer[0];
+ gl11.glBindBuffer(GL11.GL_ARRAY_BUFFER, mTextureCoordBufferIndex);
+ final int texCoordSize = mTexCoordBuffer.capacity() * 4;
+ mTexCoordBuffer.position(0);
+ gl11.glBufferData(GL11.GL_ARRAY_BUFFER, texCoordSize, mTexCoordBuffer, GL11.GL_STATIC_DRAW);
+
+ // Allocate and fill the secondary texture coordinate buffer.
+ gl11.glGenBuffers(1, buffer, 0);
+ mSecTextureCoordBufferIndex = buffer[0];
+ gl11.glBindBuffer(GL11.GL_ARRAY_BUFFER, mSecTextureCoordBufferIndex);
+ final int secTexCoordSize = mSecTexCoordBuffer.capacity() * 4;
+ mSecTexCoordBuffer.position(0);
+ gl11.glBufferData(GL11.GL_ARRAY_BUFFER, secTexCoordSize, mSecTexCoordBuffer, GL11.GL_STATIC_DRAW);
+
+ // Unbind the array buffer.
+ gl11.glBindBuffer(GL11.GL_ARRAY_BUFFER, 0);
+
+ // Allocate and fill the index buffer.
+ gl11.glGenBuffers(1, buffer, 0);
+ mIndexBufferIndex = buffer[0];
+ gl11.glBindBuffer(GL11.GL_ELEMENT_ARRAY_BUFFER, mIndexBufferIndex);
+ // A char is 2 bytes.
+ final int indexSize = mIndexBuffer.capacity() * 2;
+ mIndexBuffer.position(0);
+ gl11.glBufferData(GL11.GL_ELEMENT_ARRAY_BUFFER, indexSize, mIndexBuffer, GL11.GL_STATIC_DRAW);
+
+ // Unbind the element array buffer.
+ gl11.glBindBuffer(GL11.GL_ELEMENT_ARRAY_BUFFER, 0);
+ }
+ }
+ }
+}