blob: 021b82b76371afd25f67f72c45af1d3616e12841 [file] [log] [blame]
David Liaa1f54d2011-03-01 16:54:04 -08001#include "gles2context.h"
2
3//#undef LOGD
4//#define LOGD(...)
5
6void GLES2Context::InitializeVertices()
7{
8 vert.vbos = std::map<GLuint, VBO *>(); // the entire struct has been zeroed in constructor
9 vert.free = 1;
10 vert.vbo = NULL;
11 vert.indices = NULL;
12 for (unsigned i = 0; i < GGL_MAXVERTEXATTRIBS; i++)
13 vert.defaultAttribs[i] = Vector4(0,0,0,1);
14}
15
16void GLES2Context::UninitializeVertices()
17{
18 for (std::map<GLuint, VBO *>::iterator it = vert.vbos.begin(); it != vert.vbos.end(); it++) {
19 if (!it->second)
20 continue;
21 free(it->second->data);
22 free(it->second);
23 }
24}
25
26static inline void FetchElement(const GLES2Context * ctx, const unsigned index,
27 const unsigned maxAttrib, VertexInput * elem)
28{
29 for (unsigned i = 0; i < maxAttrib; i++) {
30 {
31 unsigned size = 0;
32 if (ctx->vert.attribs[i].enabled) {
33 const char * ptr = (const char *)ctx->vert.attribs[i].ptr;
34 ptr += ctx->vert.attribs[i].stride * index;
35 memcpy(elem->attributes + i, ptr, ctx->vert.attribs[i].size * sizeof(float));
36 size = ctx->vert.attribs[i].size;
37// LOGD("agl2: FetchElement %d attribs size=%d %.2f,%.2f,%.2f,%.2f", i, size, elem->attributes[i].x,
38// elem->attributes[i].y, elem->attributes[i].z, elem->attributes[i].w);
39 } else {
40// LOGD("agl2: FetchElement %d default %.2f,%.2f,%.2f,%.2f", i, ctx->vert.defaultAttribs[i].x,
41// ctx->vert.defaultAttribs[i].y, ctx->vert.defaultAttribs[i].z, ctx->vert.defaultAttribs[i].w);
42 }
43
44 switch (size) {
45 case 0: // fall through
46 elem->attributes[i].x = ctx->vert.defaultAttribs[i].x;
47 case 1: // fall through
48 elem->attributes[i].y = ctx->vert.defaultAttribs[i].y;
49 case 2: // fall through
50 elem->attributes[i].z = ctx->vert.defaultAttribs[i].z;
51 case 3: // fall through
52 elem->attributes[i].w = ctx->vert.defaultAttribs[i].w;
53 case 4:
54 break;
55 default:
56 assert(0);
57 break;
58 }
59// LOGD("agl2: FetchElement %d size=%d %.2f,%.2f,%.2f,%.2f", i, size, elem->attributes[i].x,
60// elem->attributes[i].y, elem->attributes[i].z, elem->attributes[i].w);
61 }
62 }
63}
64
65template<typename IndexT> static void DrawElementsTriangles(const GLES2Context * ctx,
66 const unsigned count, const IndexT * indices, const unsigned maxAttrib)
67{
68 VertexInput v[3];
69 if (ctx->vert.indices)
70 indices = (IndexT *)((char *)ctx->vert.indices->data + (long)indices);
71 for (unsigned i = 0; i < count; i += 3) {
72 for (unsigned j = 0; j < 3; j++)
73 FetchElement(ctx, indices[i + j], maxAttrib, v + j);
74 ctx->iface->DrawTriangle(ctx->iface, v, v + 1, v + 2);
75 }
76}
77
78static void DrawArraysTriangles(const GLES2Context * ctx, const unsigned first,
79 const unsigned count, const unsigned maxAttrib)
80{
81// LOGD("agl: DrawArraysTriangles=%p", DrawArraysTriangles);
82 VertexInput v[3];
83 for (unsigned i = 2; i < count; i+=3) {
84 // TODO: fix order
85 FetchElement(ctx, first + i - 2, maxAttrib, v + 0);
86 FetchElement(ctx, first + i - 1, maxAttrib, v + 1);
87 FetchElement(ctx, first + i - 0, maxAttrib, v + 2);
88 ctx->iface->DrawTriangle(ctx->iface, v + 0, v + 1, v + 2);
89 }
90// LOGD("agl: DrawArraysTriangles end");
91}
92
93template<typename IndexT> static void DrawElementsTriangleStrip(const GLES2Context * ctx,
94 const unsigned count, const IndexT * indices, const unsigned maxAttrib)
95{
96 VertexInput v[3];
97 if (ctx->vert.indices)
98 indices = (IndexT *)((char *)ctx->vert.indices->data + (long)indices);
99
100// LOGD("agl2: DrawElementsTriangleStrip");
101// for (unsigned i = 0; i < count; i++)
102// LOGD("indices[%d] = %d", i, indices[i]);
103
104 FetchElement(ctx, indices[0], maxAttrib, v + 0);
105 FetchElement(ctx, indices[1], maxAttrib, v + 1);
106 for (unsigned i = 2; i < count; i ++) {
107 FetchElement(ctx, indices[i], maxAttrib, v + i % 3);
108 ctx->iface->DrawTriangle(ctx->iface, v + (i - 2) % 3, v + (i - 1) % 3 , v + (i + 0) % 3);
109 }
110
111// for (unsigned i = 2; i < count; i++) {
112// FetchElement(ctx, indices[i - 2], maxAttrib, v + 0);
113// FetchElement(ctx, indices[i - 1], maxAttrib, v + 1);
114// FetchElement(ctx, indices[i - 0], maxAttrib, v + 2);
115// ctx->iface->DrawTriangle(ctx->iface, v + 0, v + 1, v + 2);
116// }
117}
118
119static void DrawArraysTriangleStrip(const GLES2Context * ctx, const unsigned first,
120 const unsigned count, const unsigned maxAttrib)
121{
122 VertexInput v[3];
123 FetchElement(ctx, first, maxAttrib, v + 0);
124 FetchElement(ctx, first + 1, maxAttrib, v + 1);
125 for (unsigned i = 2; i < count; i++) {
126 // TODO: fix order
127 FetchElement(ctx, first + i, maxAttrib, v + i % 3);
128 ctx->iface->DrawTriangle(ctx->iface, v + (i - 2) % 3, v + (i - 1) % 3 , v + (i + 0) % 3);
129 }
130}
131
132void glBindBuffer(GLenum target, GLuint buffer)
133{
134 GLES2_GET_CONST_CONTEXT(ctx);
135 VBO * vbo = NULL;
136 if (0 != buffer) {
137 std::map<GLuint, VBO *>::iterator it = ctx->vert.vbos.find(buffer);
138 if (it != ctx->vert.vbos.end()) {
139 vbo = it->second;
140 if (!vbo)
141 vbo = (VBO *)calloc(1, sizeof(VBO));
142 it->second = vbo;
143 } else
144 assert(0);
145 }
146 if (GL_ARRAY_BUFFER == target)
147 ctx->vert.vbo = vbo;
148 else if (GL_ELEMENT_ARRAY_BUFFER == target)
149 ctx->vert.indices = vbo;
150 else
151 assert(0);
152 assert(vbo || buffer == 0);
153// LOGD("\n*\n glBindBuffer 0x%.4X=%d ", target, buffer);
154}
155
156void glBufferData(GLenum target, GLsizeiptr size, const GLvoid* data, GLenum usage)
157{
158 GLES2_GET_CONST_CONTEXT(ctx);
159 if (GL_ARRAY_BUFFER == target) {
160 assert(ctx->vert.vbo);
161 ctx->vert.vbo->data = realloc(ctx->vert.vbo->data, size);
162 ctx->vert.vbo->size = size;
163 ctx->vert.vbo->usage = usage;
164 if (data)
165 memcpy(ctx->vert.vbo->data, data, size);
166 } else if (GL_ELEMENT_ARRAY_BUFFER == target) {
167 assert(ctx->vert.indices);
168 ctx->vert.indices->data = realloc(ctx->vert.indices->data, size);
169 ctx->vert.indices->size = size;
170 ctx->vert.indices->usage = usage;
171 if (data)
172 memcpy(ctx->vert.indices->data, data, size);
173 } else
174 assert(0);
175// LOGD("\n*\n glBufferData target=0x%.4X size=%u data=%p usage=0x%.4X \n",
176// target, size, data, usage);
177}
178
179void glBufferSubData(GLenum target, GLintptr offset, GLsizeiptr size, const GLvoid* data)
180{
181 GLES2_GET_CONST_CONTEXT(ctx);
182 if (GL_ARRAY_BUFFER == target)
183 {
184 assert(ctx->vert.vbo);
185 assert(0 <= offset);
186 assert(0 <= size);
187 assert(offset + size <= ctx->vert.vbo->size);
188 memcpy((char *)ctx->vert.vbo->data + offset, data, size);
189 }
190 else
191 assert(0);
192}
193
194void glDeleteBuffers(GLsizei n, const GLuint* buffers)
195{
196 GLES2_GET_CONST_CONTEXT(ctx);
197 for (unsigned i = 0; i < n; i++) {
198 std::map<GLuint, VBO*>::iterator it = ctx->vert.vbos.find(buffers[i]);
199 if (it == ctx->vert.vbos.end())
200 continue;
201 ctx->vert.free = min(ctx->vert.free, buffers[i]);
202 if (it->second == ctx->vert.vbo)
203 ctx->vert.vbo = NULL;
204 else if (it->second == ctx->vert.indices)
205 ctx->vert.indices = NULL;
206 if (it->second) {
207 free(it->second->data);
208 free(it->second);
209 }
210 }
211}
212
213void glDisableVertexAttribArray(GLuint index)
214{
215 GLES2_GET_CONST_CONTEXT(ctx);
216 assert(GGL_MAXVERTEXATTRIBS > index);
217 ctx->vert.attribs[index].enabled = false;
218}
219
220void glDrawArrays(GLenum mode, GLint first, GLsizei count)
221{
222 GLES2_GET_CONST_CONTEXT(ctx);
223// LOGD("agl2: glDrawArrays=%p", glDrawArrays);
224 assert(ctx->rasterizer.CurrentProgram);
225 assert(0 <= first);
226 int maxAttrib = -1;
227 ctx->iface->ShaderProgramGetiv(ctx->rasterizer.CurrentProgram, GL_ACTIVE_ATTRIBUTES, &maxAttrib);
228 assert(0 <= maxAttrib && GGL_MAXVERTEXATTRIBS >= maxAttrib);
229 switch (mode) {
230 case GL_TRIANGLE_STRIP:
231 DrawArraysTriangleStrip(ctx, first, count, maxAttrib);
232 break;
233 case GL_TRIANGLES:
234 DrawArraysTriangles(ctx, first, count, maxAttrib);
235 break;
236 default:
237 LOGE("agl2: glDrawArrays unsupported mode: 0x%.4X \n", mode);
238 assert(0);
239 break;
240 }
241// LOGD("agl2: glDrawArrays end");
242}
243
244void glDrawElements(GLenum mode, GLsizei count, GLenum type, const GLvoid* indices)
245{
246 GLES2_GET_CONST_CONTEXT(ctx);
247// LOGD("agl2: glDrawElements=%p mode=0x%.4X count=%d type=0x%.4X indices=%p",
248// glDrawElements, mode, count, type, indices);
249 if (!ctx->rasterizer.CurrentProgram)
250 return;
251
252 int maxAttrib = -1;
253 ctx->iface->ShaderProgramGetiv(ctx->rasterizer.CurrentProgram, GL_ACTIVE_ATTRIBUTES, &maxAttrib);
254 assert(0 <= maxAttrib && GGL_MAXVERTEXATTRIBS >= maxAttrib);
255// LOGD("agl2: glDrawElements mode=0x%.4X type=0x%.4X count=%d program=%p indices=%p \n",
256// mode, type, count, ctx->rasterizer.CurrentProgram, indices);
257 switch (mode) {
258 case GL_TRIANGLES:
259 if (GL_UNSIGNED_SHORT == type)
260 DrawElementsTriangles<unsigned short>(ctx, count, (unsigned short *)indices, maxAttrib);
261 else
262 assert(0);
263 break;
264 case GL_TRIANGLE_STRIP:
265 if (GL_UNSIGNED_SHORT == type)
266 DrawElementsTriangleStrip<unsigned short>(ctx, count, (unsigned short *)indices, maxAttrib);
267 else
268 assert(0);
269 break;
270 default:
271 assert(0);
272 }
273// LOGD("agl2: glDrawElements end");
274}
275
276void glEnableVertexAttribArray(GLuint index)
277{
278 GLES2_GET_CONST_CONTEXT(ctx);
279 ctx->vert.attribs[index].enabled = true;
280// LOGD("agl2: glEnableVertexAttribArray %d \n", index);
281}
282
283void glGenBuffers(GLsizei n, GLuint* buffers)
284{
285 GLES2_GET_CONST_CONTEXT(ctx);
286 for (unsigned i = 0; i < n; i++) {
287 buffers[i] = 0;
288 for (ctx->vert.free; ctx->vert.free < 0xffffffffu; ctx->vert.free++) {
289 if (ctx->vert.vbos.find(ctx->vert.free) == ctx->vert.vbos.end()) {
290 ctx->vert.vbos[ctx->vert.free] = NULL;
291 buffers[i] = ctx->vert.free;
292// LOGD("glGenBuffers %d \n", buffers[i]);
293 ctx->vert.free++;
294 break;
295 }
296 }
297 assert(buffers[i]);
298 }
299}
300
301void glVertexAttribPointer(GLuint index, GLint size, GLenum type, GLboolean normalized,
302 GLsizei stride, const GLvoid* ptr)
303{
304 GLES2_GET_CONST_CONTEXT(ctx);
305 assert(GL_FLOAT == type);
306 assert(0 < size && 4 >= size);
307 ctx->vert.attribs[index].size = size;
308 ctx->vert.attribs[index].type = type;
309 ctx->vert.attribs[index].normalized = normalized;
310 if (0 == stride)
311 ctx->vert.attribs[index].stride = size * sizeof(float);
312 else if (stride > 0)
313 ctx->vert.attribs[index].stride = stride;
314 else
315 assert(0);
316// LOGD("\n*\n*\n* agl2: glVertexAttribPointer program=%u index=%d size=%d stride=%d ptr=%p \n*\n*",
317// unsigned(ctx->rasterizer.CurrentProgram) ^ 0x04dc18f9, index, size, stride, ptr);
318 if (ctx->vert.vbo)
319 ctx->vert.attribs[index].ptr = (char *)ctx->vert.vbo->data + (long)ptr;
320 else
321 ctx->vert.attribs[index].ptr = ptr;
322// const float * attrib = (const float *)ctx->vert.attribs[index].ptr;
323// for (unsigned i = 0; i < 3; i++)
324// if (3 == size)
325// LOGD("%.2f %.2f %.2f", attrib[i * 3 + 0], attrib[i * 3 + 1], attrib[i * 3 + 2]);
326// else if (2 == size)
327// LOGD("%.2f %.2f", attrib[i * 3 + 0], attrib[i * 3 + 1]);
328
329}
330
331void glVertexAttrib1f(GLuint indx, GLfloat x)
332{
333 glVertexAttrib4f(indx, x,0,0,1);
334}
335
336void glVertexAttrib1fv(GLuint indx, const GLfloat* values)
337{
338 glVertexAttrib4f(indx, values[0],0,0,1);
339}
340
341void glVertexAttrib2f(GLuint indx, GLfloat x, GLfloat y)
342{
343 glVertexAttrib4f(indx, x,y,0,1);
344}
345
346void glVertexAttrib2fv(GLuint indx, const GLfloat* values)
347{
348 glVertexAttrib4f(indx, values[0],values[1],0,1);
349}
350
351void glVertexAttrib3f(GLuint indx, GLfloat x, GLfloat y, GLfloat z)
352{
353 glVertexAttrib4f(indx, x,y,z,1);
354}
355
356void glVertexAttrib3fv(GLuint indx, const GLfloat* values)
357{
358 glVertexAttrib4f(indx, values[0],values[1],values[2],1);
359}
360
361void glVertexAttrib4f(GLuint indx, GLfloat x, GLfloat y, GLfloat z, GLfloat w)
362{
363 assert(GGL_MAXVERTEXATTRIBS > indx);
364 GLES2_GET_CONST_CONTEXT(ctx);
365// LOGD("\n*\n*\n agl2: glVertexAttrib4f %d %.2f,%.2f,%.2f,%.2f \n*\n*", indx, x, y, z, w);
366 ctx->vert.defaultAttribs[indx] = Vector4(x,y,z,w);
367 assert(0);
368}
369
370void glVertexAttrib4fv(GLuint indx, const GLfloat* values)
371{
372 glVertexAttrib4f(indx, values[0], values[1], values[2], values[3]);
373}