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