1 #include "gles2context.h"
2
3 //#undef LOGD
4 //#define LOGD(...)
5
InitializeVertices()6 void 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
UninitializeVertices()16 void 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
FetchElement(const GLES2Context * ctx,const unsigned index,const unsigned maxAttrib,VertexInput * elem)26 static 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
DrawElementsTriangles(const GLES2Context * ctx,const unsigned count,const IndexT * indices,const unsigned maxAttrib)65 template<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
DrawArraysTriangles(const GLES2Context * ctx,const unsigned first,const unsigned count,const unsigned maxAttrib)78 static 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
DrawElementsTriangleStrip(const GLES2Context * ctx,const unsigned count,const IndexT * indices,const unsigned maxAttrib)93 template<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
DrawArraysTriangleStrip(const GLES2Context * ctx,const unsigned first,const unsigned count,const unsigned maxAttrib)119 static 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
glBindBuffer(GLenum target,GLuint buffer)132 void 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
glBufferData(GLenum target,GLsizeiptr size,const GLvoid * data,GLenum usage)156 void 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
glBufferSubData(GLenum target,GLintptr offset,GLsizeiptr size,const GLvoid * data)179 void 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
glDeleteBuffers(GLsizei n,const GLuint * buffers)194 void 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
glDisableVertexAttribArray(GLuint index)213 void glDisableVertexAttribArray(GLuint index)
214 {
215 GLES2_GET_CONST_CONTEXT(ctx);
216 assert(GGL_MAXVERTEXATTRIBS > index);
217 ctx->vert.attribs[index].enabled = false;
218 }
219
glDrawArrays(GLenum mode,GLint first,GLsizei count)220 void 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
glDrawElements(GLenum mode,GLsizei count,GLenum type,const GLvoid * indices)244 void 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
glEnableVertexAttribArray(GLuint index)276 void 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
glGenBuffers(GLsizei n,GLuint * buffers)283 void 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
glVertexAttribPointer(GLuint index,GLint size,GLenum type,GLboolean normalized,GLsizei stride,const GLvoid * ptr)301 void 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
glVertexAttrib1f(GLuint indx,GLfloat x)331 void glVertexAttrib1f(GLuint indx, GLfloat x)
332 {
333 glVertexAttrib4f(indx, x,0,0,1);
334 }
335
glVertexAttrib1fv(GLuint indx,const GLfloat * values)336 void glVertexAttrib1fv(GLuint indx, const GLfloat* values)
337 {
338 glVertexAttrib4f(indx, values[0],0,0,1);
339 }
340
glVertexAttrib2f(GLuint indx,GLfloat x,GLfloat y)341 void glVertexAttrib2f(GLuint indx, GLfloat x, GLfloat y)
342 {
343 glVertexAttrib4f(indx, x,y,0,1);
344 }
345
glVertexAttrib2fv(GLuint indx,const GLfloat * values)346 void glVertexAttrib2fv(GLuint indx, const GLfloat* values)
347 {
348 glVertexAttrib4f(indx, values[0],values[1],0,1);
349 }
350
glVertexAttrib3f(GLuint indx,GLfloat x,GLfloat y,GLfloat z)351 void glVertexAttrib3f(GLuint indx, GLfloat x, GLfloat y, GLfloat z)
352 {
353 glVertexAttrib4f(indx, x,y,z,1);
354 }
355
glVertexAttrib3fv(GLuint indx,const GLfloat * values)356 void glVertexAttrib3fv(GLuint indx, const GLfloat* values)
357 {
358 glVertexAttrib4f(indx, values[0],values[1],values[2],1);
359 }
360
glVertexAttrib4f(GLuint indx,GLfloat x,GLfloat y,GLfloat z,GLfloat w)361 void 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
glVertexAttrib4fv(GLuint indx,const GLfloat * values)370 void glVertexAttrib4fv(GLuint indx, const GLfloat* values)
371 {
372 glVertexAttrib4f(indx, values[0], values[1], values[2], values[3]);
373 }
374