1 /*
2 ** Copyright 2006, 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 #include <stdlib.h>
18 #include <stdio.h>
19
20 #include "context.h"
21 #include "fp.h"
22 #include "state.h"
23 #include "matrix.h"
24 #include "vertex.h"
25 #include "light.h"
26 #include "primitives.h"
27 #include "texture.h"
28 #include "BufferObjectManager.h"
29
30 // ----------------------------------------------------------------------------
31
32 #define VC_CACHE_STATISTICS 0
33 #define VC_CACHE_TYPE_NONE 0
34 #define VC_CACHE_TYPE_INDEXED 1
35 #define VC_CACHE_TYPE_LRU 2
36 #define VC_CACHE_TYPE VC_CACHE_TYPE_INDEXED
37
38 #if VC_CACHE_STATISTICS
39 #include <utils/Timers.h>
40 #endif
41
42 // ----------------------------------------------------------------------------
43
44 namespace android {
45
46 static void validate_arrays(ogles_context_t* c, GLenum mode);
47
48 static void compileElements__generic(ogles_context_t*,
49 vertex_t*, GLint, GLsizei);
50 static void compileElement__generic(ogles_context_t*,
51 vertex_t*, GLint);
52
53 static void drawPrimitivesPoints(ogles_context_t*, GLint, GLsizei);
54 static void drawPrimitivesLineStrip(ogles_context_t*, GLint, GLsizei);
55 static void drawPrimitivesLineLoop(ogles_context_t*, GLint, GLsizei);
56 static void drawPrimitivesLines(ogles_context_t*, GLint, GLsizei);
57 static void drawPrimitivesTriangleStrip(ogles_context_t*, GLint, GLsizei);
58 static void drawPrimitivesTriangleFan(ogles_context_t*, GLint, GLsizei);
59 static void drawPrimitivesTriangles(ogles_context_t*, GLint, GLsizei);
60
61 static void drawIndexedPrimitivesPoints(ogles_context_t*,
62 GLsizei, const GLvoid*);
63 static void drawIndexedPrimitivesLineStrip(ogles_context_t*,
64 GLsizei, const GLvoid*);
65 static void drawIndexedPrimitivesLineLoop(ogles_context_t*,
66 GLsizei, const GLvoid*);
67 static void drawIndexedPrimitivesLines(ogles_context_t*,
68 GLsizei, const GLvoid*);
69 static void drawIndexedPrimitivesTriangleStrip(ogles_context_t*,
70 GLsizei, const GLvoid*);
71 static void drawIndexedPrimitivesTriangleFan(ogles_context_t*,
72 GLsizei, const GLvoid*);
73 static void drawIndexedPrimitivesTriangles(ogles_context_t*,
74 GLsizei, const GLvoid*);
75
76 // ----------------------------------------------------------------------------
77
78 typedef void (*arrays_prims_fct_t)(ogles_context_t*, GLint, GLsizei);
79 static const arrays_prims_fct_t drawArraysPrims[] = {
80 drawPrimitivesPoints,
81 drawPrimitivesLines,
82 drawPrimitivesLineLoop,
83 drawPrimitivesLineStrip,
84 drawPrimitivesTriangles,
85 drawPrimitivesTriangleStrip,
86 drawPrimitivesTriangleFan
87 };
88
89 typedef void (*elements_prims_fct_t)(ogles_context_t*, GLsizei, const GLvoid*);
90 static const elements_prims_fct_t drawElementsPrims[] = {
91 drawIndexedPrimitivesPoints,
92 drawIndexedPrimitivesLines,
93 drawIndexedPrimitivesLineLoop,
94 drawIndexedPrimitivesLineStrip,
95 drawIndexedPrimitivesTriangles,
96 drawIndexedPrimitivesTriangleStrip,
97 drawIndexedPrimitivesTriangleFan
98 };
99
100 // ----------------------------------------------------------------------------
101 #if 0
102 #pragma mark -
103 #endif
104
ogles_init_array(ogles_context_t * c)105 void ogles_init_array(ogles_context_t* c)
106 {
107 c->arrays.vertex.size = 4;
108 c->arrays.vertex.type = GL_FLOAT;
109 c->arrays.color.size = 4;
110 c->arrays.color.type = GL_FLOAT;
111 c->arrays.normal.size = 4;
112 c->arrays.normal.type = GL_FLOAT;
113 for (int i=0 ; i<GGL_TEXTURE_UNIT_COUNT ; i++) {
114 c->arrays.texture[i].size = 4;
115 c->arrays.texture[i].type = GL_FLOAT;
116 }
117 c->vc.init();
118
119 if (!c->vc.vBuffer) {
120 // this could have failed
121 ogles_error(c, GL_OUT_OF_MEMORY);
122 }
123 }
124
ogles_uninit_array(ogles_context_t * c)125 void ogles_uninit_array(ogles_context_t* c)
126 {
127 c->vc.uninit();
128 }
129
130 // ----------------------------------------------------------------------------
131 #if 0
132 #pragma mark -
133 #pragma mark Array fetchers
134 #endif
135
currentColor(ogles_context_t * c,GLfixed * v,const GLvoid *)136 static void currentColor(ogles_context_t* c, GLfixed* v, const GLvoid*) {
137 memcpy(v, c->current.color.v, sizeof(vec4_t));
138 }
currentColor_clamp(ogles_context_t * c,GLfixed * v,const GLvoid *)139 static void currentColor_clamp(ogles_context_t* c, GLfixed* v, const GLvoid*) {
140 memcpy(v, c->currentColorClamped.v, sizeof(vec4_t));
141 }
currentNormal(ogles_context_t * c,GLfixed * v,const GLvoid *)142 static void currentNormal(ogles_context_t* c, GLfixed* v, const GLvoid*) {
143 memcpy(v, c->currentNormal.v, sizeof(vec3_t));
144 }
currentTexCoord(ogles_context_t * c,GLfixed * v,const GLvoid *)145 static void currentTexCoord(ogles_context_t* c, GLfixed* v, const GLvoid*) {
146 memcpy(v, c->current.texture[c->arrays.tmu].v, sizeof(vec4_t));
147 }
148
149
fetchNop(ogles_context_t *,GLfixed *,const GLvoid *)150 static void fetchNop(ogles_context_t*, GLfixed*, const GLvoid*) {
151 }
fetch2b(ogles_context_t *,GLfixed * v,const GLbyte * p)152 static void fetch2b(ogles_context_t*, GLfixed* v, const GLbyte* p) {
153 v[0] = gglIntToFixed(p[0]);
154 v[1] = gglIntToFixed(p[1]);
155 }
fetch2s(ogles_context_t *,GLfixed * v,const GLshort * p)156 static void fetch2s(ogles_context_t*, GLfixed* v, const GLshort* p) {
157 v[0] = gglIntToFixed(p[0]);
158 v[1] = gglIntToFixed(p[1]);
159 }
fetch2x(ogles_context_t *,GLfixed * v,const GLfixed * p)160 static void fetch2x(ogles_context_t*, GLfixed* v, const GLfixed* p) {
161 memcpy(v, p, 2*sizeof(GLfixed));
162 }
fetch2f(ogles_context_t *,GLfixed * v,const GLfloat * p)163 static void fetch2f(ogles_context_t*, GLfixed* v, const GLfloat* p) {
164 v[0] = gglFloatToFixed(p[0]);
165 v[1] = gglFloatToFixed(p[1]);
166 }
fetch3b(ogles_context_t *,GLfixed * v,const GLbyte * p)167 static void fetch3b(ogles_context_t*, GLfixed* v, const GLbyte* p) {
168 v[0] = gglIntToFixed(p[0]);
169 v[1] = gglIntToFixed(p[1]);
170 v[2] = gglIntToFixed(p[2]);
171 }
fetch3s(ogles_context_t *,GLfixed * v,const GLshort * p)172 static void fetch3s(ogles_context_t*, GLfixed* v, const GLshort* p) {
173 v[0] = gglIntToFixed(p[0]);
174 v[1] = gglIntToFixed(p[1]);
175 v[2] = gglIntToFixed(p[2]);
176 }
fetch3x(ogles_context_t *,GLfixed * v,const GLfixed * p)177 static void fetch3x(ogles_context_t*, GLfixed* v, const GLfixed* p) {
178 memcpy(v, p, 3*sizeof(GLfixed));
179 }
fetch3f(ogles_context_t *,GLfixed * v,const GLfloat * p)180 static void fetch3f(ogles_context_t*, GLfixed* v, const GLfloat* p) {
181 v[0] = gglFloatToFixed(p[0]);
182 v[1] = gglFloatToFixed(p[1]);
183 v[2] = gglFloatToFixed(p[2]);
184 }
fetch4b(ogles_context_t *,GLfixed * v,const GLbyte * p)185 static void fetch4b(ogles_context_t*, GLfixed* v, const GLbyte* p) {
186 v[0] = gglIntToFixed(p[0]);
187 v[1] = gglIntToFixed(p[1]);
188 v[2] = gglIntToFixed(p[2]);
189 v[3] = gglIntToFixed(p[3]);
190 }
fetch4s(ogles_context_t *,GLfixed * v,const GLshort * p)191 static void fetch4s(ogles_context_t*, GLfixed* v, const GLshort* p) {
192 v[0] = gglIntToFixed(p[0]);
193 v[1] = gglIntToFixed(p[1]);
194 v[2] = gglIntToFixed(p[2]);
195 v[3] = gglIntToFixed(p[3]);
196 }
fetch4x(ogles_context_t *,GLfixed * v,const GLfixed * p)197 static void fetch4x(ogles_context_t*, GLfixed* v, const GLfixed* p) {
198 memcpy(v, p, 4*sizeof(GLfixed));
199 }
fetch4f(ogles_context_t *,GLfixed * v,const GLfloat * p)200 static void fetch4f(ogles_context_t*, GLfixed* v, const GLfloat* p) {
201 v[0] = gglFloatToFixed(p[0]);
202 v[1] = gglFloatToFixed(p[1]);
203 v[2] = gglFloatToFixed(p[2]);
204 v[3] = gglFloatToFixed(p[3]);
205 }
fetchExpand4ub(ogles_context_t *,GLfixed * v,const GLubyte * p)206 static void fetchExpand4ub(ogles_context_t*, GLfixed* v, const GLubyte* p) {
207 v[0] = GGL_UB_TO_X(p[0]);
208 v[1] = GGL_UB_TO_X(p[1]);
209 v[2] = GGL_UB_TO_X(p[2]);
210 v[3] = GGL_UB_TO_X(p[3]);
211 }
fetchClamp4x(ogles_context_t *,GLfixed * v,const GLfixed * p)212 static void fetchClamp4x(ogles_context_t*, GLfixed* v, const GLfixed* p) {
213 v[0] = gglClampx(p[0]);
214 v[1] = gglClampx(p[1]);
215 v[2] = gglClampx(p[2]);
216 v[3] = gglClampx(p[3]);
217 }
fetchClamp4f(ogles_context_t *,GLfixed * v,const GLfloat * p)218 static void fetchClamp4f(ogles_context_t*, GLfixed* v, const GLfloat* p) {
219 v[0] = gglClampx(gglFloatToFixed(p[0]));
220 v[1] = gglClampx(gglFloatToFixed(p[1]));
221 v[2] = gglClampx(gglFloatToFixed(p[2]));
222 v[3] = gglClampx(gglFloatToFixed(p[3]));
223 }
fetchExpand3ub(ogles_context_t *,GLfixed * v,const GLubyte * p)224 static void fetchExpand3ub(ogles_context_t*, GLfixed* v, const GLubyte* p) {
225 v[0] = GGL_UB_TO_X(p[0]);
226 v[1] = GGL_UB_TO_X(p[1]);
227 v[2] = GGL_UB_TO_X(p[2]);
228 v[3] = 0x10000;
229 }
fetchClamp3x(ogles_context_t *,GLfixed * v,const GLfixed * p)230 static void fetchClamp3x(ogles_context_t*, GLfixed* v, const GLfixed* p) {
231 v[0] = gglClampx(p[0]);
232 v[1] = gglClampx(p[1]);
233 v[2] = gglClampx(p[2]);
234 v[3] = 0x10000;
235 }
fetchClamp3f(ogles_context_t *,GLfixed * v,const GLfloat * p)236 static void fetchClamp3f(ogles_context_t*, GLfixed* v, const GLfloat* p) {
237 v[0] = gglClampx(gglFloatToFixed(p[0]));
238 v[1] = gglClampx(gglFloatToFixed(p[1]));
239 v[2] = gglClampx(gglFloatToFixed(p[2]));
240 v[3] = 0x10000;
241 }
fetchExpand3b(ogles_context_t *,GLfixed * v,const GLbyte * p)242 static void fetchExpand3b(ogles_context_t*, GLfixed* v, const GLbyte* p) {
243 v[0] = GGL_B_TO_X(p[0]);
244 v[1] = GGL_B_TO_X(p[1]);
245 v[2] = GGL_B_TO_X(p[2]);
246 }
fetchExpand3s(ogles_context_t *,GLfixed * v,const GLshort * p)247 static void fetchExpand3s(ogles_context_t*, GLfixed* v, const GLshort* p) {
248 v[0] = GGL_S_TO_X(p[0]);
249 v[1] = GGL_S_TO_X(p[1]);
250 v[2] = GGL_S_TO_X(p[2]);
251 }
252
253 typedef array_t::fetcher_t fn_t;
254
255 static const fn_t color_fct[2][16] = { // size={3,4}, type={ub,f,x}
256 { 0, (fn_t)fetchExpand3ub, 0, 0, 0, 0,
257 (fn_t)fetch3f, 0, 0, 0, 0, 0,
258 (fn_t)fetch3x },
259 { 0, (fn_t)fetchExpand4ub, 0, 0, 0, 0,
260 (fn_t)fetch4f, 0, 0, 0, 0, 0,
261 (fn_t)fetch4x },
262 };
263 static const fn_t color_clamp_fct[2][16] = { // size={3,4}, type={ub,f,x}
264 { 0, (fn_t)fetchExpand3ub, 0, 0, 0, 0,
265 (fn_t)fetchClamp3f, 0, 0, 0, 0, 0,
266 (fn_t)fetchClamp3x },
267 { 0, (fn_t)fetchExpand4ub, 0, 0, 0, 0,
268 (fn_t)fetchClamp4f, 0, 0, 0, 0, 0,
269 (fn_t)fetchClamp4x },
270 };
271 static const fn_t normal_fct[1][16] = { // size={3}, type={b,s,f,x}
272 { (fn_t)fetchExpand3b, 0,
273 (fn_t)fetchExpand3s, 0, 0, 0,
274 (fn_t)fetch3f, 0, 0, 0, 0, 0,
275 (fn_t)fetch3x },
276 };
277 static const fn_t vertex_fct[3][16] = { // size={2,3,4}, type={b,s,f,x}
278 { (fn_t)fetch2b, 0,
279 (fn_t)fetch2s, 0, 0, 0,
280 (fn_t)fetch2f, 0, 0, 0, 0, 0,
281 (fn_t)fetch3x },
282 { (fn_t)fetch3b, 0,
283 (fn_t)fetch3s, 0, 0, 0,
284 (fn_t)fetch3f, 0, 0, 0, 0, 0,
285 (fn_t)fetch3x },
286 { (fn_t)fetch4b, 0,
287 (fn_t)fetch4s, 0, 0, 0,
288 (fn_t)fetch4f, 0, 0, 0, 0, 0,
289 (fn_t)fetch4x }
290 };
291 static const fn_t texture_fct[3][16] = { // size={2,3,4}, type={b,s,f,x}
292 { (fn_t)fetch2b, 0,
293 (fn_t)fetch2s, 0, 0, 0,
294 (fn_t)fetch2f, 0, 0, 0, 0, 0,
295 (fn_t)fetch2x },
296 { (fn_t)fetch3b, 0,
297 (fn_t)fetch3s, 0, 0, 0,
298 (fn_t)fetch3f, 0, 0, 0, 0, 0,
299 (fn_t)fetch3x },
300 { (fn_t)fetch4b, 0,
301 (fn_t)fetch4s, 0, 0, 0,
302 (fn_t)fetch4f, 0, 0, 0, 0, 0,
303 (fn_t)fetch4x }
304 };
305
306 // ----------------------------------------------------------------------------
307 #if 0
308 #pragma mark -
309 #pragma mark array_t
310 #endif
311
init(GLint size,GLenum type,GLsizei stride,const GLvoid * pointer,const buffer_t * bo,GLsizei count)312 void array_t::init(
313 GLint size, GLenum type, GLsizei stride,
314 const GLvoid *pointer, const buffer_t* bo, GLsizei count)
315 {
316 if (!stride) {
317 stride = size;
318 switch (type) {
319 case GL_SHORT:
320 case GL_UNSIGNED_SHORT:
321 stride *= 2;
322 break;
323 case GL_FLOAT:
324 case GL_FIXED:
325 stride *= 4;
326 break;
327 }
328 }
329 this->size = size;
330 this->type = type;
331 this->stride = stride;
332 this->pointer = pointer;
333 this->bo = bo;
334 this->bounds = count;
335 }
336
resolve()337 inline void array_t::resolve()
338 {
339 physical_pointer = (bo) ? (bo->data + uintptr_t(pointer)) : pointer;
340 }
341
342 // ----------------------------------------------------------------------------
343 #if 0
344 #pragma mark -
345 #pragma mark vertex_cache_t
346 #endif
347
init()348 void vertex_cache_t::init()
349 {
350 // make sure the size of vertex_t allows cache-line alignment
351 CTA<(sizeof(vertex_t) & 0x1F) == 0> assertAlignedSize;
352
353 const int align = 32;
354 const size_t s = VERTEX_BUFFER_SIZE + VERTEX_CACHE_SIZE;
355 const size_t size = s*sizeof(vertex_t) + align;
356 base = malloc(size);
357 if (base) {
358 memset(base, 0, size);
359 vBuffer = (vertex_t*)((size_t(base) + align - 1) & ~(align-1));
360 vCache = vBuffer + VERTEX_BUFFER_SIZE;
361 sequence = 0;
362 }
363 }
364
uninit()365 void vertex_cache_t::uninit()
366 {
367 free(base);
368 base = vBuffer = vCache = 0;
369 }
370
clear()371 void vertex_cache_t::clear()
372 {
373 #if VC_CACHE_STATISTICS
374 startTime = systemTime(SYSTEM_TIME_THREAD);
375 total = 0;
376 misses = 0;
377 #endif
378
379 #if VC_CACHE_TYPE == VC_CACHE_TYPE_LRU
380 vertex_t* v = vBuffer;
381 size_t count = VERTEX_BUFFER_SIZE + VERTEX_CACHE_SIZE;
382 do {
383 v->mru = 0;
384 v++;
385 } while (--count);
386 #endif
387
388 sequence += INDEX_SEQ;
389 if (sequence >= 0x80000000LU) {
390 sequence = INDEX_SEQ;
391 vertex_t* v = vBuffer;
392 size_t count = VERTEX_BUFFER_SIZE + VERTEX_CACHE_SIZE;
393 do {
394 v->index = 0;
395 v++;
396 } while (--count);
397 }
398 }
399
400 #if VC_CACHE_STATISTICS
dump_stats(GLenum mode)401 void vertex_cache_t::dump_stats(GLenum mode)
402 {
403 nsecs_t time = systemTime(SYSTEM_TIME_THREAD) - startTime;
404 uint32_t hits = total - misses;
405 uint32_t prim_count;
406 switch (mode) {
407 case GL_POINTS: prim_count = total; break;
408 case GL_LINE_STRIP: prim_count = total - 1; break;
409 case GL_LINE_LOOP: prim_count = total - 1; break;
410 case GL_LINES: prim_count = total / 2; break;
411 case GL_TRIANGLE_STRIP: prim_count = total - 2; break;
412 case GL_TRIANGLE_FAN: prim_count = total - 2; break;
413 case GL_TRIANGLES: prim_count = total / 3; break;
414 default: return;
415 }
416 printf( "total=%5u, hits=%5u, miss=%5u, hitrate=%3u%%,"
417 " prims=%5u, time=%6u us, prims/s=%d, v/t=%f\n",
418 total, hits, misses, (hits*100)/total,
419 prim_count, int(ns2us(time)), int(prim_count*float(seconds(1))/time),
420 float(misses) / prim_count);
421 }
422 #else
dump_stats(GLenum)423 void vertex_cache_t::dump_stats(GLenum /*mode*/)
424 {
425 }
426 #endif
427
428 // ----------------------------------------------------------------------------
429 #if 0
430 #pragma mark -
431 #endif
432
433 static __attribute__((noinline))
enableDisableClientState(ogles_context_t * c,GLenum array,bool enable)434 void enableDisableClientState(ogles_context_t* c, GLenum array, bool enable)
435 {
436 const int tmu = c->arrays.activeTexture;
437 array_t* a;
438 switch (array) {
439 case GL_COLOR_ARRAY: a = &c->arrays.color; break;
440 case GL_NORMAL_ARRAY: a = &c->arrays.normal; break;
441 case GL_TEXTURE_COORD_ARRAY: a = &c->arrays.texture[tmu]; break;
442 case GL_VERTEX_ARRAY: a = &c->arrays.vertex; break;
443 default:
444 ogles_error(c, GL_INVALID_ENUM);
445 return;
446 }
447 a->enable = enable ? GL_TRUE : GL_FALSE;
448 }
449
450 // ----------------------------------------------------------------------------
451 #if 0
452 #pragma mark -
453 #pragma mark Vertex Cache
454 #endif
455
456 static __attribute__((noinline))
cache_vertex(ogles_context_t * c,vertex_t * v,uint32_t index)457 vertex_t* cache_vertex(ogles_context_t* c, vertex_t* v, uint32_t index)
458 {
459 #if VC_CACHE_STATISTICS
460 c->vc.misses++;
461 #endif
462 if (ggl_unlikely(v->locked)) {
463 // we're just looking for an entry in the cache that is not locked.
464 // and we know that there cannot be more than 2 locked entries
465 // because a triangle needs at most 3 vertices.
466 // We never use the first and second entries because they might be in
467 // use by the striper or faner. Any other entry will do as long as
468 // it's not locked.
469 // We compute directly the index of a "free" entry from the locked
470 // state of v[2] and v[3].
471 v = c->vc.vBuffer + 2;
472 v += v[0].locked | (v[1].locked<<1);
473 }
474 // note: compileElement clears v->flags
475 c->arrays.compileElement(c, v, index);
476 v->locked = 1;
477 return v;
478 }
479
480 static __attribute__((noinline))
fetch_vertex(ogles_context_t * c,size_t index)481 vertex_t* fetch_vertex(ogles_context_t* c, size_t index)
482 {
483 index |= c->vc.sequence;
484
485 #if VC_CACHE_TYPE == VC_CACHE_TYPE_INDEXED
486
487 vertex_t* const v = c->vc.vCache +
488 (index & (vertex_cache_t::VERTEX_CACHE_SIZE-1));
489
490 if (ggl_likely(v->index == index)) {
491 v->locked = 1;
492 return v;
493 }
494 return cache_vertex(c, v, index);
495
496 #elif VC_CACHE_TYPE == VC_CACHE_TYPE_LRU
497
498 vertex_t* v = c->vc.vCache +
499 (index & ((vertex_cache_t::VERTEX_CACHE_SIZE-1)>>1))*2;
500
501 // always record LRU in v[0]
502 if (ggl_likely(v[0].index == index)) {
503 v[0].locked = 1;
504 v[0].mru = 0;
505 return &v[0];
506 }
507
508 if (ggl_likely(v[1].index == index)) {
509 v[1].locked = 1;
510 v[0].mru = 1;
511 return &v[1];
512 }
513
514 const int lru = 1 - v[0].mru;
515 v[0].mru = lru;
516 return cache_vertex(c, &v[lru], index);
517
518 #elif VC_CACHE_TYPE == VC_CACHE_TYPE_NONE
519
520 // just for debugging...
521 vertex_t* v = c->vc.vBuffer + 2;
522 return cache_vertex(c, v, index);
523
524 #endif
525 }
526
527 // ----------------------------------------------------------------------------
528 #if 0
529 #pragma mark -
530 #pragma mark Primitive Assembly
531 #endif
532
drawPrimitivesPoints(ogles_context_t * c,GLint first,GLsizei count)533 void drawPrimitivesPoints(ogles_context_t* c, GLint first, GLsizei count)
534 {
535 if (ggl_unlikely(count < 1))
536 return;
537
538 // vertex cache size must be multiple of 1
539 const GLsizei vcs =
540 (vertex_cache_t::VERTEX_BUFFER_SIZE +
541 vertex_cache_t::VERTEX_CACHE_SIZE);
542 do {
543 vertex_t* v = c->vc.vBuffer;
544 GLsizei num = count > vcs ? vcs : count;
545 c->arrays.cull = vertex_t::CLIP_ALL;
546 c->arrays.compileElements(c, v, first, num);
547 first += num;
548 count -= num;
549 if (!c->arrays.cull) {
550 // quick/trivial reject of the whole batch
551 do {
552 const uint32_t cc = v[0].flags;
553 if (ggl_likely(!(cc & vertex_t::CLIP_ALL)))
554 c->prims.renderPoint(c, v);
555 v++;
556 num--;
557 } while (num);
558 }
559 } while (count);
560 }
561
562 // ----------------------------------------------------------------------------
563
drawPrimitivesLineStrip(ogles_context_t * c,GLint first,GLsizei count)564 void drawPrimitivesLineStrip(ogles_context_t* c, GLint first, GLsizei count)
565 {
566 if (ggl_unlikely(count < 2))
567 return;
568
569 vertex_t *v, *v0, *v1;
570 c->arrays.cull = vertex_t::CLIP_ALL;
571 c->arrays.compileElement(c, c->vc.vBuffer, first);
572 first += 1;
573 count -= 1;
574
575 // vertex cache size must be multiple of 1
576 const GLsizei vcs =
577 (vertex_cache_t::VERTEX_BUFFER_SIZE +
578 vertex_cache_t::VERTEX_CACHE_SIZE - 1);
579 do {
580 v0 = c->vc.vBuffer + 0;
581 v = c->vc.vBuffer + 1;
582 GLsizei num = count > vcs ? vcs : count;
583 c->arrays.compileElements(c, v, first, num);
584 first += num;
585 count -= num;
586 if (!c->arrays.cull) {
587 // quick/trivial reject of the whole batch
588 do {
589 v1 = v++;
590 const uint32_t cc = v0->flags & v1->flags;
591 if (ggl_likely(!(cc & vertex_t::CLIP_ALL)))
592 c->prims.renderLine(c, v0, v1);
593 v0 = v1;
594 num--;
595 } while (num);
596 }
597 // copy back the last processed vertex
598 c->vc.vBuffer[0] = *v0;
599 c->arrays.cull = v0->flags & vertex_t::CLIP_ALL;
600 } while (count);
601 }
602
drawPrimitivesLineLoop(ogles_context_t * c,GLint first,GLsizei count)603 void drawPrimitivesLineLoop(ogles_context_t* c, GLint first, GLsizei count)
604 {
605 if (ggl_unlikely(count < 2))
606 return;
607 drawPrimitivesLineStrip(c, first, count);
608 if (ggl_likely(count >= 3)) {
609 vertex_t* v0 = c->vc.vBuffer;
610 vertex_t* v1 = c->vc.vBuffer + 1;
611 c->arrays.compileElement(c, v1, first);
612 const uint32_t cc = v0->flags & v1->flags;
613 if (ggl_likely(!(cc & vertex_t::CLIP_ALL)))
614 c->prims.renderLine(c, v0, v1);
615 }
616 }
617
drawPrimitivesLines(ogles_context_t * c,GLint first,GLsizei count)618 void drawPrimitivesLines(ogles_context_t* c, GLint first, GLsizei count)
619 {
620 if (ggl_unlikely(count < 2))
621 return;
622
623 // vertex cache size must be multiple of 2
624 const GLsizei vcs =
625 ((vertex_cache_t::VERTEX_BUFFER_SIZE +
626 vertex_cache_t::VERTEX_CACHE_SIZE) / 2) * 2;
627 do {
628 vertex_t* v = c->vc.vBuffer;
629 GLsizei num = count > vcs ? vcs : count;
630 c->arrays.cull = vertex_t::CLIP_ALL;
631 c->arrays.compileElements(c, v, first, num);
632 first += num;
633 count -= num;
634 if (!c->arrays.cull) {
635 // quick/trivial reject of the whole batch
636 num -= 2;
637 do {
638 const uint32_t cc = v[0].flags & v[1].flags;
639 if (ggl_likely(!(cc & vertex_t::CLIP_ALL)))
640 c->prims.renderLine(c, v, v+1);
641 v += 2;
642 num -= 2;
643 } while (num >= 0);
644 }
645 } while (count >= 2);
646 }
647
648 // ----------------------------------------------------------------------------
649
drawPrimitivesTriangleFanOrStrip(ogles_context_t * c,GLint first,GLsizei count,int winding)650 static void drawPrimitivesTriangleFanOrStrip(ogles_context_t* c,
651 GLint first, GLsizei count, int winding)
652 {
653 // winding == 2 : fan
654 // winding == 1 : strip
655
656 if (ggl_unlikely(count < 3))
657 return;
658
659 vertex_t *v, *v0, *v1, *v2;
660 c->arrays.cull = vertex_t::CLIP_ALL;
661 c->arrays.compileElements(c, c->vc.vBuffer, first, 2);
662 first += 2;
663 count -= 2;
664
665 // vertex cache size must be multiple of 2. This is extremely important
666 // because it allows us to preserve the same winding when the whole
667 // batch is culled. We also need 2 extra vertices in the array, because
668 // we always keep the two first ones.
669 const GLsizei vcs =
670 ((vertex_cache_t::VERTEX_BUFFER_SIZE +
671 vertex_cache_t::VERTEX_CACHE_SIZE - 2) / 2) * 2;
672 do {
673 v0 = c->vc.vBuffer + 0;
674 v1 = c->vc.vBuffer + 1;
675 v = c->vc.vBuffer + 2;
676 GLsizei num = count > vcs ? vcs : count;
677 c->arrays.compileElements(c, v, first, num);
678 first += num;
679 count -= num;
680 if (!c->arrays.cull) {
681 // quick/trivial reject of the whole batch
682 do {
683 v2 = v++;
684 const uint32_t cc = v0->flags & v1->flags & v2->flags;
685 if (ggl_likely(!(cc & vertex_t::CLIP_ALL)))
686 c->prims.renderTriangle(c, v0, v1, v2);
687 swap(((winding^=1) ? v1 : v0), v2);
688 num--;
689 } while (num);
690 }
691 if (count) {
692 v0 = c->vc.vBuffer + 2 + vcs - 2;
693 v1 = c->vc.vBuffer + 2 + vcs - 1;
694 if ((winding&2) == 0) {
695 // for strips copy back the two last compiled vertices
696 c->vc.vBuffer[0] = *v0;
697 }
698 c->vc.vBuffer[1] = *v1;
699 c->arrays.cull = v0->flags & v1->flags & vertex_t::CLIP_ALL;
700 }
701 } while (count > 0);
702 }
703
drawPrimitivesTriangleStrip(ogles_context_t * c,GLint first,GLsizei count)704 void drawPrimitivesTriangleStrip(ogles_context_t* c,
705 GLint first, GLsizei count) {
706 drawPrimitivesTriangleFanOrStrip(c, first, count, 1);
707 }
708
drawPrimitivesTriangleFan(ogles_context_t * c,GLint first,GLsizei count)709 void drawPrimitivesTriangleFan(ogles_context_t* c,
710 GLint first, GLsizei count) {
711 drawPrimitivesTriangleFanOrStrip(c, first, count, 2);
712 }
713
drawPrimitivesTriangles(ogles_context_t * c,GLint first,GLsizei count)714 void drawPrimitivesTriangles(ogles_context_t* c, GLint first, GLsizei count)
715 {
716 if (ggl_unlikely(count < 3))
717 return;
718
719 // vertex cache size must be multiple of 3
720 const GLsizei vcs =
721 ((vertex_cache_t::VERTEX_BUFFER_SIZE +
722 vertex_cache_t::VERTEX_CACHE_SIZE) / 3) * 3;
723 do {
724 vertex_t* v = c->vc.vBuffer;
725 GLsizei num = count > vcs ? vcs : count;
726 c->arrays.cull = vertex_t::CLIP_ALL;
727 c->arrays.compileElements(c, v, first, num);
728 first += num;
729 count -= num;
730 if (!c->arrays.cull) {
731 // quick/trivial reject of the whole batch
732 num -= 3;
733 do {
734 const uint32_t cc = v[0].flags & v[1].flags & v[2].flags;
735 if (ggl_likely(!(cc & vertex_t::CLIP_ALL)))
736 c->prims.renderTriangle(c, v, v+1, v+2);
737 v += 3;
738 num -= 3;
739 } while (num >= 0);
740 }
741 } while (count >= 3);
742 }
743
744 // ----------------------------------------------------------------------------
745 #if 0
746 #pragma mark -
747 #endif
748
749 // this looks goofy, but gcc does a great job with this...
read_index(int type,const GLvoid * & p)750 static inline unsigned int read_index(int type, const GLvoid*& p) {
751 unsigned int r;
752 if (type) {
753 r = *(const GLubyte*)p;
754 p = (const GLubyte*)p + 1;
755 } else {
756 r = *(const GLushort*)p;
757 p = (const GLushort*)p + 1;
758 }
759 return r;
760 }
761
762 // ----------------------------------------------------------------------------
763
drawIndexedPrimitivesPoints(ogles_context_t * c,GLsizei count,const GLvoid * indices)764 void drawIndexedPrimitivesPoints(ogles_context_t* c,
765 GLsizei count, const GLvoid *indices)
766 {
767 if (ggl_unlikely(count < 1))
768 return;
769 const int type = (c->arrays.indicesType == GL_UNSIGNED_BYTE);
770 do {
771 vertex_t * v = fetch_vertex(c, read_index(type, indices));
772 if (ggl_likely(!(v->flags & vertex_t::CLIP_ALL)))
773 c->prims.renderPoint(c, v);
774 v->locked = 0;
775 count--;
776 } while(count);
777 }
778
779 // ----------------------------------------------------------------------------
780
drawIndexedPrimitivesLineStrip(ogles_context_t * c,GLsizei count,const GLvoid * indices)781 void drawIndexedPrimitivesLineStrip(ogles_context_t* c,
782 GLsizei count, const GLvoid *indices)
783 {
784 if (ggl_unlikely(count < 2))
785 return;
786
787 vertex_t * const v = c->vc.vBuffer;
788 vertex_t* v0 = v;
789 vertex_t* v1;
790
791 const int type = (c->arrays.indicesType == GL_UNSIGNED_BYTE);
792 c->arrays.compileElement(c, v0, read_index(type, indices));
793 count -= 1;
794 do {
795 v1 = fetch_vertex(c, read_index(type, indices));
796 const uint32_t cc = v0->flags & v1->flags;
797 if (ggl_likely(!(cc & vertex_t::CLIP_ALL)))
798 c->prims.renderLine(c, v0, v1);
799 v0->locked = 0;
800 v0 = v1;
801 count--;
802 } while (count);
803 v1->locked = 0;
804 }
805
drawIndexedPrimitivesLineLoop(ogles_context_t * c,GLsizei count,const GLvoid * indices)806 void drawIndexedPrimitivesLineLoop(ogles_context_t* c,
807 GLsizei count, const GLvoid *indices)
808 {
809 if (ggl_unlikely(count <= 2)) {
810 drawIndexedPrimitivesLines(c, count, indices);
811 return;
812 }
813
814 vertex_t * const v = c->vc.vBuffer;
815 vertex_t* v0 = v;
816 vertex_t* v1;
817
818 const int type = (c->arrays.indicesType == GL_UNSIGNED_BYTE);
819 c->arrays.compileElement(c, v0, read_index(type, indices));
820 count -= 1;
821 do {
822 v1 = fetch_vertex(c, read_index(type, indices));
823 const uint32_t cc = v0->flags & v1->flags;
824 if (ggl_likely(!(cc & vertex_t::CLIP_ALL)))
825 c->prims.renderLine(c, v0, v1);
826 v0->locked = 0;
827 v0 = v1;
828 count--;
829 } while (count);
830 v1->locked = 0;
831
832 v1 = c->vc.vBuffer;
833 const uint32_t cc = v0->flags & v1->flags;
834 if (ggl_likely(!(cc & vertex_t::CLIP_ALL)))
835 c->prims.renderLine(c, v0, v1);
836 }
837
drawIndexedPrimitivesLines(ogles_context_t * c,GLsizei count,const GLvoid * indices)838 void drawIndexedPrimitivesLines(ogles_context_t* c,
839 GLsizei count, const GLvoid *indices)
840 {
841 if (ggl_unlikely(count < 2))
842 return;
843
844 count -= 2;
845 const int type = (c->arrays.indicesType == GL_UNSIGNED_BYTE);
846 do {
847 vertex_t* const v0 = fetch_vertex(c, read_index(type, indices));
848 vertex_t* const v1 = fetch_vertex(c, read_index(type, indices));
849 const uint32_t cc = v0->flags & v1->flags;
850 if (ggl_likely(!(cc & vertex_t::CLIP_ALL)))
851 c->prims.renderLine(c, v0, v1);
852 v0->locked = 0;
853 v1->locked = 0;
854 count -= 2;
855 } while (count >= 0);
856 }
857
858 // ----------------------------------------------------------------------------
859
drawIndexedPrimitivesTriangleFanOrStrip(ogles_context_t * c,GLsizei count,const GLvoid * indices,int winding)860 static void drawIndexedPrimitivesTriangleFanOrStrip(ogles_context_t* c,
861 GLsizei count, const GLvoid *indices, int winding)
862 {
863 // winding == 2 : fan
864 // winding == 1 : strip
865
866 if (ggl_unlikely(count < 3))
867 return;
868
869 vertex_t * const v = c->vc.vBuffer;
870 vertex_t* v0 = v;
871 vertex_t* v1 = v+1;
872 vertex_t* v2;
873
874 const int type = (c->arrays.indicesType == GL_UNSIGNED_BYTE);
875 c->arrays.compileElement(c, v0, read_index(type, indices));
876 c->arrays.compileElement(c, v1, read_index(type, indices));
877 count -= 2;
878
879 // note: GCC 4.1.1 here makes a prety interesting optimization
880 // where it duplicates the loop below based on c->arrays.indicesType
881
882 do {
883 v2 = fetch_vertex(c, read_index(type, indices));
884 const uint32_t cc = v0->flags & v1->flags & v2->flags;
885 if (ggl_likely(!(cc & vertex_t::CLIP_ALL)))
886 c->prims.renderTriangle(c, v0, v1, v2);
887 vertex_t* & consumed = ((winding^=1) ? v1 : v0);
888 consumed->locked = 0;
889 consumed = v2;
890 count--;
891 } while (count);
892 v0->locked = v1->locked = 0;
893 v2->locked = 0;
894 }
895
drawIndexedPrimitivesTriangleStrip(ogles_context_t * c,GLsizei count,const GLvoid * indices)896 void drawIndexedPrimitivesTriangleStrip(ogles_context_t* c,
897 GLsizei count, const GLvoid *indices) {
898 drawIndexedPrimitivesTriangleFanOrStrip(c, count, indices, 1);
899 }
900
drawIndexedPrimitivesTriangleFan(ogles_context_t * c,GLsizei count,const GLvoid * indices)901 void drawIndexedPrimitivesTriangleFan(ogles_context_t* c,
902 GLsizei count, const GLvoid *indices) {
903 drawIndexedPrimitivesTriangleFanOrStrip(c, count, indices, 2);
904 }
905
drawIndexedPrimitivesTriangles(ogles_context_t * c,GLsizei count,const GLvoid * indices)906 void drawIndexedPrimitivesTriangles(ogles_context_t* c,
907 GLsizei count, const GLvoid *indices)
908 {
909 if (ggl_unlikely(count < 3))
910 return;
911
912 count -= 3;
913 if (ggl_likely(c->arrays.indicesType == GL_UNSIGNED_SHORT)) {
914 // This case is probably our most common case...
915 uint16_t const * p = (uint16_t const *)indices;
916 do {
917 vertex_t* const v0 = fetch_vertex(c, *p++);
918 vertex_t* const v1 = fetch_vertex(c, *p++);
919 vertex_t* const v2 = fetch_vertex(c, *p++);
920 const uint32_t cc = v0->flags & v1->flags & v2->flags;
921 if (ggl_likely(!(cc & vertex_t::CLIP_ALL)))
922 c->prims.renderTriangle(c, v0, v1, v2);
923 v0->locked = 0;
924 v1->locked = 0;
925 v2->locked = 0;
926 count -= 3;
927 } while (count >= 0);
928 } else {
929 uint8_t const * p = (uint8_t const *)indices;
930 do {
931 vertex_t* const v0 = fetch_vertex(c, *p++);
932 vertex_t* const v1 = fetch_vertex(c, *p++);
933 vertex_t* const v2 = fetch_vertex(c, *p++);
934 const uint32_t cc = v0->flags & v1->flags & v2->flags;
935 if (ggl_likely(!(cc & vertex_t::CLIP_ALL)))
936 c->prims.renderTriangle(c, v0, v1, v2);
937 v0->locked = 0;
938 v1->locked = 0;
939 v2->locked = 0;
940 count -= 3;
941 } while (count >= 0);
942 }
943 }
944
945 // ----------------------------------------------------------------------------
946 #if 0
947 #pragma mark -
948 #pragma mark Array compilers
949 #endif
950
compileElement__generic(ogles_context_t * c,vertex_t * v,GLint first)951 void compileElement__generic(ogles_context_t* c,
952 vertex_t* v, GLint first)
953 {
954 v->flags = 0;
955 v->index = first;
956 first &= vertex_cache_t::INDEX_MASK;
957 const GLubyte* vp = c->arrays.vertex.element(first);
958 v->obj.z = 0;
959 v->obj.w = 0x10000;
960 c->arrays.vertex.fetch(c, v->obj.v, vp);
961 c->arrays.mvp_transform(&c->transforms.mvp, &v->clip, &v->obj);
962 c->arrays.perspective(c, v);
963 }
964
compileElements__generic(ogles_context_t * c,vertex_t * v,GLint first,GLsizei count)965 void compileElements__generic(ogles_context_t* c,
966 vertex_t* v, GLint first, GLsizei count)
967 {
968 const GLubyte* vp = c->arrays.vertex.element(
969 first & vertex_cache_t::INDEX_MASK);
970 const size_t stride = c->arrays.vertex.stride;
971 transform_t const* const mvp = &c->transforms.mvp;
972 do {
973 v->flags = 0;
974 v->index = first++;
975 v->obj.z = 0;
976 v->obj.w = 0x10000;
977 c->arrays.vertex.fetch(c, v->obj.v, vp);
978 c->arrays.mvp_transform(mvp, &v->clip, &v->obj);
979 c->arrays.perspective(c, v);
980 vp += stride;
981 v++;
982 } while (--count);
983 }
984
985 /*
986 void compileElements__3x_full(ogles_context_t* c,
987 vertex_t* v, GLint first, GLsizei count)
988 {
989 const GLfixed* vp = (const GLfixed*)c->arrays.vertex.element(first);
990 const size_t stride = c->arrays.vertex.stride / 4;
991 // const GLfixed* const& m = c->transforms.mvp.matrix.m;
992
993 GLfixed m[16];
994 memcpy(&m, c->transforms.mvp.matrix.m, sizeof(m));
995
996 do {
997 const GLfixed rx = vp[0];
998 const GLfixed ry = vp[1];
999 const GLfixed rz = vp[2];
1000 vp += stride;
1001 v->index = first++;
1002 v->clip.x = mla3a(rx, m[ 0], ry, m[ 4], rz, m[ 8], m[12]);
1003 v->clip.y = mla3a(rx, m[ 1], ry, m[ 5], rz, m[ 9], m[13]);
1004 v->clip.z = mla3a(rx, m[ 2], ry, m[ 6], rz, m[10], m[14]);
1005 v->clip.w = mla3a(rx, m[ 3], ry, m[ 7], rz, m[11], m[15]);
1006
1007 const GLfixed w = v->clip.w;
1008 uint32_t clip = 0;
1009 if (v->clip.x < -w) clip |= vertex_t::CLIP_L;
1010 if (v->clip.x > w) clip |= vertex_t::CLIP_R;
1011 if (v->clip.y < -w) clip |= vertex_t::CLIP_B;
1012 if (v->clip.y > w) clip |= vertex_t::CLIP_T;
1013 if (v->clip.z < -w) clip |= vertex_t::CLIP_N;
1014 if (v->clip.z > w) clip |= vertex_t::CLIP_F;
1015 v->flags = clip;
1016 c->arrays.cull &= clip;
1017
1018 //c->arrays.perspective(c, v);
1019 v++;
1020 } while (--count);
1021 }
1022 */
1023
1024 // ----------------------------------------------------------------------------
1025 #if 0
1026 #pragma mark -
1027 #pragma mark clippers
1028 #endif
1029
clipVec4(vec4_t & nv,GLfixed t,const vec4_t & s,const vec4_t & p)1030 static void clipVec4(vec4_t& nv,
1031 GLfixed t, const vec4_t& s, const vec4_t& p)
1032 {
1033 for (int i=0; i<4 ; i++)
1034 nv.v[i] = gglMulAddx(t, s.v[i] - p.v[i], p.v[i], 28);
1035 }
1036
clipVertex(ogles_context_t * c,vertex_t * nv,GLfixed t,const vertex_t * s,const vertex_t * p)1037 static void clipVertex(ogles_context_t* c, vertex_t* nv,
1038 GLfixed t, const vertex_t* s, const vertex_t* p)
1039 {
1040 clipVec4(nv->clip, t, s->clip, p->clip);
1041 nv->fog = gglMulAddx(t, s->fog - p->fog, p->fog, 28);
1042 ogles_vertex_project(c, nv);
1043 nv->flags |= vertex_t::LIT | vertex_t::EYE | vertex_t::TT;
1044 nv->flags &= ~vertex_t::CLIP_ALL;
1045 }
1046
clipVertexC(ogles_context_t * c,vertex_t * nv,GLfixed t,const vertex_t * s,const vertex_t * p)1047 static void clipVertexC(ogles_context_t* c, vertex_t* nv,
1048 GLfixed t, const vertex_t* s, const vertex_t* p)
1049 {
1050 clipVec4(nv->color, t, s->color, p->color);
1051 clipVertex(c, nv, t, s, p);
1052 }
1053
clipVertexT(ogles_context_t * c,vertex_t * nv,GLfixed t,const vertex_t * s,const vertex_t * p)1054 static void clipVertexT(ogles_context_t* c, vertex_t* nv,
1055 GLfixed t, const vertex_t* s, const vertex_t* p)
1056 {
1057 for (int i=0 ; i<GGL_TEXTURE_UNIT_COUNT ; i++) {
1058 if (c->rasterizer.state.texture[i].enable)
1059 clipVec4(nv->texture[i], t, s->texture[i], p->texture[i]);
1060 }
1061 clipVertex(c, nv, t, s, p);
1062 }
1063
clipVertexAll(ogles_context_t * c,vertex_t * nv,GLfixed t,const vertex_t * s,const vertex_t * p)1064 static void clipVertexAll(ogles_context_t* c, vertex_t* nv,
1065 GLfixed t, const vertex_t* s, const vertex_t* p)
1066 {
1067 clipVec4(nv->color, t, s->color, p->color);
1068 clipVertexT(c, nv, t, s, p);
1069 }
1070
clipEye(ogles_context_t * c,vertex_t * nv,GLfixed t,const vertex_t * s,const vertex_t * p)1071 static void clipEye(ogles_context_t* c, vertex_t* nv,
1072 GLfixed t, const vertex_t* s, const vertex_t* p)
1073 {
1074 nv->clear();
1075 c->arrays.clipVertex(c, nv, t, p, s);
1076 clipVec4(nv->eye, t, s->eye, p->eye);
1077 }
1078
1079 // ----------------------------------------------------------------------------
1080 #if 0
1081 #pragma mark -
1082 #endif
1083
validate_arrays(ogles_context_t * c,GLenum mode)1084 void validate_arrays(ogles_context_t* c, GLenum mode)
1085 {
1086 uint32_t enables = c->rasterizer.state.enables;
1087
1088 // Perspective correction is not need if Ortho transform, but
1089 // the user can still provide the w coordinate manually, so we can't
1090 // automatically turn it off (in fact we could when the 4th coordinate
1091 // is not spcified in the vertex array).
1092 // W interpolation is never needed for points.
1093 GLboolean perspective =
1094 c->perspective && mode!=GL_POINTS && (enables & GGL_ENABLE_TMUS);
1095 c->rasterizer.procs.enableDisable(c, GGL_W_LERP, perspective);
1096
1097 // set anti-aliasing
1098 GLboolean smooth = GL_FALSE;
1099 switch (mode) {
1100 case GL_POINTS:
1101 smooth = c->point.smooth;
1102 break;
1103 case GL_LINES:
1104 case GL_LINE_LOOP:
1105 case GL_LINE_STRIP:
1106 smooth = c->line.smooth;
1107 break;
1108 }
1109 if (((enables & GGL_ENABLE_AA)?1:0) != smooth)
1110 c->rasterizer.procs.enableDisable(c, GGL_AA, smooth);
1111
1112 // set the shade model for this primitive
1113 c->rasterizer.procs.shadeModel(c,
1114 (mode == GL_POINTS) ? GL_FLAT : c->lighting.shadeModel);
1115
1116 // compute all the matrices we'll need...
1117 uint32_t want =
1118 transform_state_t::MVP |
1119 transform_state_t::VIEWPORT;
1120 if (c->lighting.enable) { // needs normal transforms and eye coords
1121 want |= transform_state_t::MVUI;
1122 want |= transform_state_t::MODELVIEW;
1123 }
1124 if (enables & GGL_ENABLE_TMUS) { // needs texture transforms
1125 want |= transform_state_t::TEXTURE;
1126 }
1127 if (c->clipPlanes.enable || (enables & GGL_ENABLE_FOG)) {
1128 want |= transform_state_t::MODELVIEW; // needs eye coords
1129 }
1130 ogles_validate_transform(c, want);
1131
1132 // textures...
1133 if (enables & GGL_ENABLE_TMUS)
1134 ogles_validate_texture(c);
1135
1136 // vertex compilers
1137 c->arrays.compileElement = compileElement__generic;
1138 c->arrays.compileElements = compileElements__generic;
1139
1140 // vertex transform
1141 c->arrays.mvp_transform =
1142 c->transforms.mvp.pointv[c->arrays.vertex.size - 2];
1143
1144 c->arrays.mv_transform =
1145 c->transforms.modelview.transform.pointv[c->arrays.vertex.size - 2];
1146
1147 /*
1148 * ***********************************************************************
1149 * pick fetchers
1150 * ***********************************************************************
1151 */
1152
1153 array_machine_t& am = c->arrays;
1154 am.vertex.fetch = fetchNop;
1155 am.normal.fetch = currentNormal;
1156 am.color.fetch = currentColor;
1157
1158 if (am.vertex.enable) {
1159 am.vertex.resolve();
1160 if (am.vertex.bo || am.vertex.pointer) {
1161 am.vertex.fetch = vertex_fct[am.vertex.size-2][am.vertex.type & 0xF];
1162 }
1163 }
1164
1165 if (am.normal.enable) {
1166 am.normal.resolve();
1167 if (am.normal.bo || am.normal.pointer) {
1168 am.normal.fetch = normal_fct[am.normal.size-3][am.normal.type & 0xF];
1169 }
1170 }
1171
1172 if (am.color.enable) {
1173 am.color.resolve();
1174 if (c->lighting.enable) {
1175 if (am.color.bo || am.color.pointer) {
1176 am.color.fetch = color_fct[am.color.size-3][am.color.type & 0xF];
1177 }
1178 } else {
1179 if (am.color.bo || am.color.pointer) {
1180 am.color.fetch = color_clamp_fct[am.color.size-3][am.color.type & 0xF];
1181 }
1182 }
1183 }
1184
1185 int activeTmuCount = 0;
1186 for (int i=0 ; i<GGL_TEXTURE_UNIT_COUNT ; i++) {
1187 am.texture[i].fetch = currentTexCoord;
1188 if (c->rasterizer.state.texture[i].enable) {
1189
1190 // texture fetchers...
1191 if (am.texture[i].enable) {
1192 am.texture[i].resolve();
1193 if (am.texture[i].bo || am.texture[i].pointer) {
1194 am.texture[i].fetch = texture_fct[am.texture[i].size-2][am.texture[i].type & 0xF];
1195 }
1196 }
1197
1198 // texture transform...
1199 const int index = c->arrays.texture[i].size - 2;
1200 c->arrays.tex_transform[i] =
1201 c->transforms.texture[i].transform.pointv[index];
1202
1203 am.tmu = i;
1204 activeTmuCount++;
1205 }
1206 }
1207
1208 // pick the vertex-clipper
1209 uint32_t clipper = 0;
1210 // we must reload 'enables' here
1211 enables = c->rasterizer.state.enables;
1212 if (enables & GGL_ENABLE_SMOOTH)
1213 clipper |= 1; // we need to interpolate colors
1214 if (enables & GGL_ENABLE_TMUS)
1215 clipper |= 2; // we need to interpolate textures
1216 switch (clipper) {
1217 case 0: c->arrays.clipVertex = clipVertex; break;
1218 case 1: c->arrays.clipVertex = clipVertexC; break;
1219 case 2: c->arrays.clipVertex = clipVertexT; break;
1220 case 3: c->arrays.clipVertex = clipVertexAll; break;
1221 }
1222 c->arrays.clipEye = clipEye;
1223
1224 // pick the primitive rasterizer
1225 ogles_validate_primitives(c);
1226 }
1227
1228 // ----------------------------------------------------------------------------
1229 }; // namespace android
1230 // ----------------------------------------------------------------------------
1231
1232 using namespace android;
1233
1234 #if 0
1235 #pragma mark -
1236 #pragma mark array API
1237 #endif
1238
glVertexPointer(GLint size,GLenum type,GLsizei stride,const GLvoid * pointer)1239 void glVertexPointer(
1240 GLint size, GLenum type, GLsizei stride, const GLvoid *pointer)
1241 {
1242 ogles_context_t* c = ogles_context_t::get();
1243 if (size<2 || size>4 || stride<0) {
1244 ogles_error(c, GL_INVALID_VALUE);
1245 return;
1246 }
1247 switch (type) {
1248 case GL_BYTE:
1249 case GL_SHORT:
1250 case GL_FIXED:
1251 case GL_FLOAT:
1252 break;
1253 default:
1254 ogles_error(c, GL_INVALID_ENUM);
1255 return;
1256 }
1257 c->arrays.vertex.init(size, type, stride, pointer, c->arrays.array_buffer, 0);
1258 }
1259
glColorPointer(GLint size,GLenum type,GLsizei stride,const GLvoid * pointer)1260 void glColorPointer(
1261 GLint size, GLenum type, GLsizei stride, const GLvoid *pointer)
1262 {
1263 ogles_context_t* c = ogles_context_t::get();
1264 if (size!=4 || stride<0) {
1265 ogles_error(c, GL_INVALID_VALUE);
1266 return;
1267 }
1268 switch (type) {
1269 case GL_UNSIGNED_BYTE:
1270 case GL_FIXED:
1271 case GL_FLOAT:
1272 break;
1273 default:
1274 ogles_error(c, GL_INVALID_ENUM);
1275 return;
1276 }
1277 c->arrays.color.init(size, type, stride, pointer, c->arrays.array_buffer, 0);
1278 }
1279
glNormalPointer(GLenum type,GLsizei stride,const GLvoid * pointer)1280 void glNormalPointer(
1281 GLenum type, GLsizei stride, const GLvoid *pointer)
1282 {
1283 ogles_context_t* c = ogles_context_t::get();
1284 if (stride<0) {
1285 ogles_error(c, GL_INVALID_VALUE);
1286 return;
1287 }
1288 switch (type) {
1289 case GL_BYTE:
1290 case GL_SHORT:
1291 case GL_FIXED:
1292 case GL_FLOAT:
1293 break;
1294 default:
1295 ogles_error(c, GL_INVALID_ENUM);
1296 return;
1297 }
1298 c->arrays.normal.init(3, type, stride, pointer, c->arrays.array_buffer, 0);
1299 }
1300
glTexCoordPointer(GLint size,GLenum type,GLsizei stride,const GLvoid * pointer)1301 void glTexCoordPointer(
1302 GLint size, GLenum type, GLsizei stride, const GLvoid *pointer)
1303 {
1304 ogles_context_t* c = ogles_context_t::get();
1305 if (size<2 || size>4 || stride<0) {
1306 ogles_error(c, GL_INVALID_VALUE);
1307 return;
1308 }
1309 switch (type) {
1310 case GL_BYTE:
1311 case GL_SHORT:
1312 case GL_FIXED:
1313 case GL_FLOAT:
1314 break;
1315 default:
1316 ogles_error(c, GL_INVALID_ENUM);
1317 return;
1318 }
1319 const int tmu = c->arrays.activeTexture;
1320 c->arrays.texture[tmu].init(size, type, stride, pointer,
1321 c->arrays.array_buffer, 0);
1322 }
1323
1324
glEnableClientState(GLenum array)1325 void glEnableClientState(GLenum array) {
1326 ogles_context_t* c = ogles_context_t::get();
1327 enableDisableClientState(c, array, true);
1328 }
1329
glDisableClientState(GLenum array)1330 void glDisableClientState(GLenum array) {
1331 ogles_context_t* c = ogles_context_t::get();
1332 enableDisableClientState(c, array, false);
1333 }
1334
glClientActiveTexture(GLenum texture)1335 void glClientActiveTexture(GLenum texture)
1336 {
1337 ogles_context_t* c = ogles_context_t::get();
1338 if (texture<GL_TEXTURE0 || texture>=GL_TEXTURE0+GGL_TEXTURE_UNIT_COUNT) {
1339 ogles_error(c, GL_INVALID_ENUM);
1340 return;
1341 }
1342 c->arrays.activeTexture = texture - GL_TEXTURE0;
1343 }
1344
glDrawArrays(GLenum mode,GLint first,GLsizei count)1345 void glDrawArrays(GLenum mode, GLint first, GLsizei count)
1346 {
1347 ogles_context_t* c = ogles_context_t::get();
1348 if (count<0) {
1349 ogles_error(c, GL_INVALID_VALUE);
1350 return;
1351 }
1352 switch (mode) {
1353 case GL_POINTS:
1354 case GL_LINE_STRIP:
1355 case GL_LINE_LOOP:
1356 case GL_LINES:
1357 case GL_TRIANGLE_STRIP:
1358 case GL_TRIANGLE_FAN:
1359 case GL_TRIANGLES:
1360 break;
1361 default:
1362 ogles_error(c, GL_INVALID_ENUM);
1363 return;
1364 }
1365
1366 if (count == 0 || !c->arrays.vertex.enable)
1367 return;
1368 if ((c->cull.enable) && (c->cull.cullFace == GL_FRONT_AND_BACK))
1369 return; // all triangles are culled
1370
1371
1372 validate_arrays(c, mode);
1373
1374 const uint32_t enables = c->rasterizer.state.enables;
1375 if (enables & GGL_ENABLE_TMUS)
1376 ogles_lock_textures(c);
1377
1378 drawArraysPrims[mode](c, first, count);
1379
1380 if (enables & GGL_ENABLE_TMUS)
1381 ogles_unlock_textures(c);
1382
1383 #if VC_CACHE_STATISTICS
1384 c->vc.total = count;
1385 c->vc.dump_stats(mode);
1386 #endif
1387 }
1388
glDrawElements(GLenum mode,GLsizei count,GLenum type,const GLvoid * indices)1389 void glDrawElements(
1390 GLenum mode, GLsizei count, GLenum type, const GLvoid *indices)
1391 {
1392 ogles_context_t* c = ogles_context_t::get();
1393 if (count<0) {
1394 ogles_error(c, GL_INVALID_VALUE);
1395 return;
1396 }
1397 switch (mode) {
1398 case GL_POINTS:
1399 case GL_LINE_STRIP:
1400 case GL_LINE_LOOP:
1401 case GL_LINES:
1402 case GL_TRIANGLE_STRIP:
1403 case GL_TRIANGLE_FAN:
1404 case GL_TRIANGLES:
1405 break;
1406 default:
1407 ogles_error(c, GL_INVALID_ENUM);
1408 return;
1409 }
1410 switch (type) {
1411 case GL_UNSIGNED_BYTE:
1412 case GL_UNSIGNED_SHORT:
1413 c->arrays.indicesType = type;
1414 break;
1415 default:
1416 ogles_error(c, GL_INVALID_ENUM);
1417 return;
1418 }
1419 if (count == 0 || !c->arrays.vertex.enable)
1420 return;
1421 if ((c->cull.enable) && (c->cull.cullFace == GL_FRONT_AND_BACK))
1422 return; // all triangles are culled
1423
1424 // clear the vertex-cache
1425 c->vc.clear();
1426 validate_arrays(c, mode);
1427
1428 // if indices are in a buffer object, the pointer is treated as an
1429 // offset in that buffer.
1430 if (c->arrays.element_array_buffer) {
1431 indices = c->arrays.element_array_buffer->data + uintptr_t(indices);
1432 }
1433
1434 const uint32_t enables = c->rasterizer.state.enables;
1435 if (enables & GGL_ENABLE_TMUS)
1436 ogles_lock_textures(c);
1437
1438 drawElementsPrims[mode](c, count, indices);
1439
1440 if (enables & GGL_ENABLE_TMUS)
1441 ogles_unlock_textures(c);
1442
1443
1444 #if VC_CACHE_STATISTICS
1445 c->vc.total = count;
1446 c->vc.dump_stats(mode);
1447 #endif
1448 }
1449
1450 // ----------------------------------------------------------------------------
1451 // buffers
1452 // ----------------------------------------------------------------------------
1453
glBindBuffer(GLenum target,GLuint buffer)1454 void glBindBuffer(GLenum target, GLuint buffer)
1455 {
1456 ogles_context_t* c = ogles_context_t::get();
1457 if ((target!=GL_ARRAY_BUFFER) && (target!=GL_ELEMENT_ARRAY_BUFFER)) {
1458 ogles_error(c, GL_INVALID_ENUM);
1459 return;
1460 }
1461 // create a buffer object, or bind an existing one
1462 buffer_t const* bo = 0;
1463 if (buffer) {
1464 bo = c->bufferObjectManager->bind(buffer);
1465 if (!bo) {
1466 ogles_error(c, GL_OUT_OF_MEMORY);
1467 return;
1468 }
1469 }
1470 ((target == GL_ARRAY_BUFFER) ?
1471 c->arrays.array_buffer : c->arrays.element_array_buffer) = bo;
1472 }
1473
glBufferData(GLenum target,GLsizeiptr size,const GLvoid * data,GLenum usage)1474 void glBufferData(GLenum target, GLsizeiptr size, const GLvoid* data, GLenum usage)
1475 {
1476 ogles_context_t* c = ogles_context_t::get();
1477 if ((target!=GL_ARRAY_BUFFER) && (target!=GL_ELEMENT_ARRAY_BUFFER)) {
1478 ogles_error(c, GL_INVALID_ENUM);
1479 return;
1480 }
1481 if (size<0) {
1482 ogles_error(c, GL_INVALID_VALUE);
1483 return;
1484 }
1485 if ((usage!=GL_STATIC_DRAW) && (usage!=GL_DYNAMIC_DRAW)) {
1486 ogles_error(c, GL_INVALID_ENUM);
1487 return;
1488 }
1489 buffer_t const* bo = ((target == GL_ARRAY_BUFFER) ?
1490 c->arrays.array_buffer : c->arrays.element_array_buffer);
1491
1492 if (bo == 0) {
1493 // can't modify buffer 0
1494 ogles_error(c, GL_INVALID_OPERATION);
1495 return;
1496 }
1497
1498 buffer_t* edit_bo = const_cast<buffer_t*>(bo);
1499 if (c->bufferObjectManager->allocateStore(edit_bo, size, usage) != 0) {
1500 ogles_error(c, GL_OUT_OF_MEMORY);
1501 return;
1502 }
1503 if (data) {
1504 memcpy(bo->data, data, size);
1505 }
1506 }
1507
glBufferSubData(GLenum target,GLintptr offset,GLsizeiptr size,const GLvoid * data)1508 void glBufferSubData(GLenum target, GLintptr offset, GLsizeiptr size, const GLvoid* data)
1509 {
1510 ogles_context_t* c = ogles_context_t::get();
1511 if ((target!=GL_ARRAY_BUFFER) && (target!=GL_ELEMENT_ARRAY_BUFFER)) {
1512 ogles_error(c, GL_INVALID_ENUM);
1513 return;
1514 }
1515 if (offset<0 || size<0 || data==0) {
1516 ogles_error(c, GL_INVALID_VALUE);
1517 return;
1518 }
1519 buffer_t const* bo = ((target == GL_ARRAY_BUFFER) ?
1520 c->arrays.array_buffer : c->arrays.element_array_buffer);
1521
1522 if (bo == 0) {
1523 // can't modify buffer 0
1524 ogles_error(c, GL_INVALID_OPERATION);
1525 return;
1526 }
1527 if (offset+size > bo->size) {
1528 ogles_error(c, GL_INVALID_VALUE);
1529 return;
1530 }
1531 memcpy(bo->data + offset, data, size);
1532 }
1533
glDeleteBuffers(GLsizei n,const GLuint * buffers)1534 void glDeleteBuffers(GLsizei n, const GLuint* buffers)
1535 {
1536 ogles_context_t* c = ogles_context_t::get();
1537 if (n<0) {
1538 ogles_error(c, GL_INVALID_VALUE);
1539 return;
1540 }
1541
1542 for (int i=0 ; i<n ; i++) {
1543 GLuint name = buffers[i];
1544 if (name) {
1545 // unbind bound deleted buffers...
1546 if (c->arrays.element_array_buffer) {
1547 if (c->arrays.element_array_buffer->name == name) {
1548 c->arrays.element_array_buffer = 0;
1549 }
1550 }
1551 if (c->arrays.array_buffer) {
1552 if (c->arrays.array_buffer->name == name) {
1553 c->arrays.array_buffer = 0;
1554 }
1555 }
1556 if (c->arrays.vertex.bo) {
1557 if (c->arrays.vertex.bo->name == name) {
1558 c->arrays.vertex.bo = 0;
1559 }
1560 }
1561 if (c->arrays.normal.bo) {
1562 if (c->arrays.normal.bo->name == name) {
1563 c->arrays.normal.bo = 0;
1564 }
1565 }
1566 if (c->arrays.color.bo) {
1567 if (c->arrays.color.bo->name == name) {
1568 c->arrays.color.bo = 0;
1569 }
1570 }
1571 for (int t=0 ; t<GGL_TEXTURE_UNIT_COUNT ; t++) {
1572 if (c->arrays.texture[t].bo) {
1573 if (c->arrays.texture[t].bo->name == name) {
1574 c->arrays.texture[t].bo = 0;
1575 }
1576 }
1577 }
1578 }
1579 }
1580 c->bufferObjectManager->deleteBuffers(n, buffers);
1581 c->bufferObjectManager->recycleTokens(n, buffers);
1582 }
1583
glGenBuffers(GLsizei n,GLuint * buffers)1584 void glGenBuffers(GLsizei n, GLuint* buffers)
1585 {
1586 ogles_context_t* c = ogles_context_t::get();
1587 if (n<0) {
1588 ogles_error(c, GL_INVALID_VALUE);
1589 return;
1590 }
1591 c->bufferObjectManager->getToken(n, buffers);
1592 }
1593