Home | History | Annotate | Download | only in media
      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.cooliris.media;
     18 
     19 import java.nio.ByteBuffer;
     20 import java.nio.ByteOrder;
     21 import java.nio.CharBuffer;
     22 import java.nio.FloatBuffer;
     23 
     24 import javax.microedition.khronos.opengles.GL10;
     25 import javax.microedition.khronos.opengles.GL11;
     26 
     27 final class GridQuadFrame {
     28     private FloatBuffer mVertexBuffer;
     29     private FloatBuffer mTexCoordBuffer;
     30     private FloatBuffer mSecTexCoordBuffer;
     31     private CharBuffer mIndexBuffer;
     32 
     33     private int mW;
     34     private int mH;
     35 
     36     // This has 8 quads, 16 vertices, 22 triangles (for tristrip).
     37     // We have more triangles because we have to make degenerate triangles to
     38     // use tri-strips
     39     public static final int INDEX_COUNT = 25;
     40     private int mVertBufferIndex;
     41     private int mIndexBufferIndex;
     42     private int mTextureCoordBufferIndex;
     43     private int mSecTextureCoordBufferIndex;
     44 
     45     public static GridQuadFrame createFrame(float width, float height, int itemWidth, int itemHeight) {
     46         GridQuadFrame frame = new GridQuadFrame();
     47         final float textureSize = 64.0f;
     48         final float numPixelsYOriginShift = 7;
     49         final float inset = 6;
     50         final float ratio = 1.0f / (float) itemHeight;
     51         final float frameXThickness = 0.5f * textureSize * ratio;
     52         final float frameYThickness = 0.5f * textureSize * ratio;
     53         final float frameX = width * 0.5f + frameXThickness * 0.5f - inset * ratio;
     54         float frameY = height * 0.5f + frameYThickness * 0.5f + (inset - 1) * ratio;
     55         final float originX = 0.0f;
     56         final float originY = numPixelsYOriginShift * ratio;
     57 
     58         frame.set(0, 0, -frameX + originX, -frameY + originY, 0, 1.0f, 1.0f);
     59         frame.set(1, 0, -frameX + originX + frameXThickness, -frameY + originY, 0, 0.5f, 1.0f);
     60         frame.set(2, 0, frameX - frameXThickness + originX, -frameY + originY, 0, 0.5f, 1.0f);
     61         frame.set(3, 0, frameX + originX, -frameY + originY, 0, 0.0f, 1.0f);
     62 
     63         frameY -= frameYThickness;
     64 
     65         frame.set(0, 1, -frameX + originX, -frameY + originY, 0, 1.0f, 0.5f);
     66         frame.set(1, 1, -frameX + frameXThickness + originX, -frameY + originY, 0, 0.5f, 0.5f);
     67         frame.set(2, 1, frameX - frameXThickness + originX, -frameY + originY, 0, 0.5f, 0.5f);
     68         frame.set(3, 1, frameX + originX, -frameY + originY, 0, 0.0f, 0.5f);
     69 
     70         frameY = height * 0.5f - frameYThickness;
     71 
     72         frame.set(0, 2, -frameX + originX, frameY + originY, 0, 1.0f, 0.5f);
     73         frame.set(1, 2, -frameX + frameXThickness + originX, frameY + originY, 0, 0.5f, 0.5f);
     74         frame.set(2, 2, frameX - frameXThickness + originX, frameY + originY, 0, 0.5f, 0.5f);
     75         frame.set(3, 2, frameX + originX, frameY + originY, 0, 0.0f, 0.5f);
     76 
     77         frameY += frameYThickness;
     78 
     79         frame.set(0, 3, -frameX + originX, frameY + originY, 0, 1.0f, 0.0f);
     80         frame.set(1, 3, -frameX + frameXThickness + originX, frameY + originY, 0, 0.5f, 0.0f);
     81         frame.set(2, 3, frameX - frameXThickness + originX, frameY + originY, 0, 0.5f, 0.0f);
     82         frame.set(3, 3, frameX + originX, frameY + originY, 0, 0.0f, 0.0f);
     83 
     84         return frame;
     85     }
     86 
     87     public GridQuadFrame() {
     88         int vertsAcross = 4;
     89         int vertsDown = 4;
     90         mW = vertsAcross;
     91         mH = vertsDown;
     92         int size = vertsAcross * vertsDown;
     93         final int FLOAT_SIZE = 4;
     94         final int CHAR_SIZE = 2;
     95         mVertexBuffer = ByteBuffer.allocateDirect(FLOAT_SIZE * size * 3).order(ByteOrder.nativeOrder()).asFloatBuffer();
     96         mTexCoordBuffer = ByteBuffer.allocateDirect(FLOAT_SIZE * size * 2).order(ByteOrder.nativeOrder()).asFloatBuffer();
     97         mSecTexCoordBuffer = ByteBuffer.allocateDirect(FLOAT_SIZE * size * 2).order(ByteOrder.nativeOrder()).asFloatBuffer();
     98 
     99         int indexCount = INDEX_COUNT; // using tristrips
    100         mIndexBuffer = ByteBuffer.allocateDirect(CHAR_SIZE * indexCount).order(ByteOrder.nativeOrder()).asCharBuffer();
    101 
    102         /*
    103          * Initialize triangle list mesh.
    104          *
    105          * [0]---[1]---------[2]---[3] ... | / | / | / |
    106          * [4]---[5]---------[6]---[7] | / | | /| | / | | / | | / | | / |
    107          * [8]---[9]---------[10]---[11] | / | \ | \ |
    108          * [12]--[13]--------[14]---[15]
    109          */
    110         CharBuffer buffer = mIndexBuffer;
    111         buffer.put(0, (char) 0);
    112         buffer.put(1, (char) 4);
    113         buffer.put(2, (char) 1);
    114         buffer.put(3, (char) 5);
    115         buffer.put(4, (char) 2);
    116         buffer.put(5, (char) 6);
    117         buffer.put(6, (char) 3);
    118         buffer.put(7, (char) 7);
    119         buffer.put(8, (char) 11);
    120         buffer.put(9, (char) 6);
    121         buffer.put(10, (char) 10);
    122         buffer.put(11, (char) 14);
    123         buffer.put(12, (char) 11);
    124         buffer.put(13, (char) 15);
    125         buffer.put(14, (char) 15);
    126         buffer.put(15, (char) 14);
    127         buffer.put(16, (char) 14);
    128         buffer.put(17, (char) 10);
    129         buffer.put(18, (char) 13);
    130         buffer.put(19, (char) 9);
    131         buffer.put(20, (char) 12);
    132         buffer.put(21, (char) 8);
    133         buffer.put(22, (char) 4);
    134         buffer.put(23, (char) 9);
    135         buffer.put(24, (char) 5);
    136         mVertBufferIndex = 0;
    137     }
    138 
    139     void set(int i, int j, float x, float y, float z, float u, float v) {
    140         if (i < 0 || i >= mW) {
    141             throw new IllegalArgumentException("i");
    142         }
    143         if (j < 0 || j >= mH) {
    144             throw new IllegalArgumentException("j");
    145         }
    146 
    147         int index = mW * j + i;
    148 
    149         int posIndex = index * 3;
    150         mVertexBuffer.put(posIndex, x);
    151         mVertexBuffer.put(posIndex + 1, y);
    152         mVertexBuffer.put(posIndex + 2, z);
    153 
    154         int texIndex = index * 2;
    155         mTexCoordBuffer.put(texIndex, u);
    156         mTexCoordBuffer.put(texIndex + 1, v);
    157 
    158         int secTexIndex = index * 2;
    159         mSecTexCoordBuffer.put(secTexIndex, u);
    160         mSecTexCoordBuffer.put(secTexIndex + 1, v);
    161     }
    162 
    163     public void bindArrays(GL10 gl) {
    164         GL11 gl11 = (GL11) gl;
    165         // draw using hardware buffers
    166         gl11.glBindBuffer(GL11.GL_ARRAY_BUFFER, mVertBufferIndex);
    167         gl11.glVertexPointer(3, GL11.GL_FLOAT, 0, 0);
    168 
    169         gl11.glBindBuffer(GL11.GL_ARRAY_BUFFER, mTextureCoordBufferIndex);
    170         gl11.glTexCoordPointer(2, GL11.GL_FLOAT, 0, 0);
    171         gl11.glClientActiveTexture(GL11.GL_TEXTURE1);
    172         gl11.glBindBuffer(GL11.GL_ARRAY_BUFFER, mSecTextureCoordBufferIndex);
    173         gl11.glTexCoordPointer(2, GL11.GL_FLOAT, 0, 0);
    174         gl11.glClientActiveTexture(GL11.GL_TEXTURE0);
    175         gl11.glBindBuffer(GL11.GL_ELEMENT_ARRAY_BUFFER, mIndexBufferIndex);
    176     }
    177 
    178     public static final void draw(GL11 gl11) {
    179         // Don't call this method unless bindArrays was called.
    180         gl11.glDrawElements(GL11.GL_TRIANGLE_STRIP, INDEX_COUNT, GL11.GL_UNSIGNED_SHORT, 0);
    181     }
    182 
    183     public void unbindArrays(GL10 gl) {
    184         GL11 gl11 = (GL11) gl;
    185         gl11.glBindBuffer(GL11.GL_ARRAY_BUFFER, 0);
    186         gl11.glBindBuffer(GL11.GL_ELEMENT_ARRAY_BUFFER, 0);
    187     }
    188 
    189     public boolean usingHardwareBuffers() {
    190         return mVertBufferIndex != 0;
    191     }
    192 
    193     /**
    194      * When the OpenGL ES device is lost, GL handles become invalidated. In that
    195      * case, we just want to "forget" the old handles (without explicitly
    196      * deleting them) and make new ones.
    197      */
    198     public void forgetHardwareBuffers() {
    199         mVertBufferIndex = 0;
    200         mIndexBufferIndex = 0;
    201         mTextureCoordBufferIndex = 0;
    202         mSecTextureCoordBufferIndex = 0;
    203     }
    204 
    205     /**
    206      * Deletes the hardware buffers allocated by this object (if any).
    207      */
    208     public void freeHardwareBuffers(GL10 gl) {
    209         if (mVertBufferIndex != 0) {
    210             if (gl instanceof GL11) {
    211                 GL11 gl11 = (GL11) gl;
    212                 int[] buffer = new int[1];
    213                 buffer[0] = mVertBufferIndex;
    214                 gl11.glDeleteBuffers(1, buffer, 0);
    215 
    216                 buffer[0] = mTextureCoordBufferIndex;
    217                 gl11.glDeleteBuffers(1, buffer, 0);
    218 
    219                 buffer[0] = mSecTextureCoordBufferIndex;
    220                 gl11.glDeleteBuffers(1, buffer, 0);
    221 
    222                 buffer[0] = mIndexBufferIndex;
    223                 gl11.glDeleteBuffers(1, buffer, 0);
    224             }
    225             forgetHardwareBuffers();
    226         }
    227     }
    228 
    229     /**
    230      * Allocates hardware buffers on the graphics card and fills them with data
    231      * if a buffer has not already been previously allocated. Note that this
    232      * function uses the GL_OES_vertex_buffer_object extension, which is not
    233      * guaranteed to be supported on every device.
    234      *
    235      * @param gl
    236      *            A pointer to the OpenGL ES context.
    237      */
    238     public void generateHardwareBuffers(GL10 gl) {
    239         if (mVertBufferIndex == 0) {
    240             if (gl instanceof GL11) {
    241                 GL11 gl11 = (GL11) gl;
    242                 int[] buffer = new int[1];
    243 
    244                 // Allocate and fill the vertex buffer.
    245                 gl11.glGenBuffers(1, buffer, 0);
    246                 mVertBufferIndex = buffer[0];
    247                 gl11.glBindBuffer(GL11.GL_ARRAY_BUFFER, mVertBufferIndex);
    248                 mVertexBuffer.position(0);
    249                 final int vertexSize = mVertexBuffer.capacity() * 4;
    250                 gl11.glBufferData(GL11.GL_ARRAY_BUFFER, vertexSize, mVertexBuffer, GL11.GL_STATIC_DRAW);
    251 
    252                 // Allocate and fill the texture coordinate buffer.
    253                 gl11.glGenBuffers(1, buffer, 0);
    254                 mTextureCoordBufferIndex = buffer[0];
    255                 gl11.glBindBuffer(GL11.GL_ARRAY_BUFFER, mTextureCoordBufferIndex);
    256                 final int texCoordSize = mTexCoordBuffer.capacity() * 4;
    257                 mTexCoordBuffer.position(0);
    258                 gl11.glBufferData(GL11.GL_ARRAY_BUFFER, texCoordSize, mTexCoordBuffer, GL11.GL_STATIC_DRAW);
    259 
    260                 // Allocate and fill the secondary texture coordinate buffer.
    261                 gl11.glGenBuffers(1, buffer, 0);
    262                 mSecTextureCoordBufferIndex = buffer[0];
    263                 gl11.glBindBuffer(GL11.GL_ARRAY_BUFFER, mSecTextureCoordBufferIndex);
    264                 final int secTexCoordSize = mSecTexCoordBuffer.capacity() * 4;
    265                 mSecTexCoordBuffer.position(0);
    266                 gl11.glBufferData(GL11.GL_ARRAY_BUFFER, secTexCoordSize, mSecTexCoordBuffer, GL11.GL_STATIC_DRAW);
    267 
    268                 // Unbind the array buffer.
    269                 gl11.glBindBuffer(GL11.GL_ARRAY_BUFFER, 0);
    270 
    271                 // Allocate and fill the index buffer.
    272                 gl11.glGenBuffers(1, buffer, 0);
    273                 mIndexBufferIndex = buffer[0];
    274                 gl11.glBindBuffer(GL11.GL_ELEMENT_ARRAY_BUFFER, mIndexBufferIndex);
    275                 // A char is 2 bytes.
    276                 final int indexSize = mIndexBuffer.capacity() * 2;
    277                 mIndexBuffer.position(0);
    278                 gl11.glBufferData(GL11.GL_ELEMENT_ARRAY_BUFFER, indexSize, mIndexBuffer, GL11.GL_STATIC_DRAW);
    279 
    280                 // Unbind the element array buffer.
    281                 gl11.glBindBuffer(GL11.GL_ELEMENT_ARRAY_BUFFER, 0);
    282             }
    283         }
    284     }
    285 }
    286