• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
createFrame(float width, float height, int itemWidth, int itemHeight)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 
GridQuadFrame()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 
set(int i, int j, float x, float y, float z, float u, float v)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 
bindArrays(GL10 gl)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 
draw(GL11 gl11)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 
unbindArrays(GL10 gl)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 
usingHardwareBuffers()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      */
forgetHardwareBuffers()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      */
freeHardwareBuffers(GL10 gl)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      */
generateHardwareBuffers(GL10 gl)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