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