OSDN Git Service

android-2.1_r1 snapshot
[android-x86/packages-apps-Gallery2.git] / src / com / cooliris / media / GridQuadFrame.java
diff --git a/src/com/cooliris/media/GridQuadFrame.java b/src/com/cooliris/media/GridQuadFrame.java
new file mode 100644 (file)
index 0000000..3c808f1
--- /dev/null
@@ -0,0 +1,269 @@
+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);
+            }
+        }
+    }
+}