1 /* xscreensaver, Copyright (c) 2012-2016 Jamie Zawinski <jwz@jwz.org>
3 * Permission to use, copy, modify, distribute, and sell this software and its
4 * documentation for any purpose is hereby granted without fee, provided that
5 * the above copyright notice appear in all copies and that both that
6 * copyright notice and this permission notice appear in supporting
7 * documentation. No representations are made about the suitability of this
8 * software for any purpose. It is provided "as is" without express or
12 /* A compatibility shim to allow OpenGL 1.3 source code to work in an
13 OpenGLES environment, where almost every OpenGL 1.3 function has
16 There are two major operations going on here:
18 - Converting calls to glBegin + glVertex3f + glEnd to glDrawArrays
19 - Implementing display lists.
22 From an API point of view, OpenGL 1.3 and earlier code looks like this:
24 glLightfv (GL_LIGHT0, GL_POSITION, ...);
25 glLightfv (GL_LIGHT0, GL_AMBIENT, ...);
27 glMatrixMode (GL_PROJECTION);
31 glMatrixMode (GL_MODELVIEW);
41 glBegin (GL_TRIANGLES);
53 OpenGLES broke that model by eliminating glBegin(). Instead of
54 iterating a sequence of vertexes, you need to pack your points into
63 glDrawArrays (GL_TRIANGLES, 0, 3);
65 The projection model (glRotatef, etc.) works the same, but glColor()
66 is missing. You're expected to encode that into your arrays.
68 Also, OpenGLES doesn't support display lists at all.
71 So this code shadows all of the functions that are allowed within
72 glBegin, builds up an array, and calls glDrawArrays at the end.
74 Likewise, it shadows all of the functions that are allowed within
75 glNewList and records those calls for later playback.
78 This code only handles OpenGLES 1.1, not 1.0 or 2.x.
80 OpenGLES 2.0 broke things further by eliminating the whole OpenGL
81 lighting model. Instead of specifying the positions and properties
82 of your lights using the glLight* API, now you are expected to
83 implement it all yourself by downloading C-like code into the GPU
84 directly. This is more flexible, in that if you wanted a completely
85 different lighting model than what OpenGL provides, you could do
86 that, but it leaves you needing to download boilerplate to reproduce
87 what used to be built in.
90 Incidentally, the OpenGL numbering scheme goes something like this:
93 OpenGL 1.1 1997 (improved texture support)
94 OpenGL 1.2 1998 (nothing interesting)
95 OpenGL 1.3 2001 (multisampling, cubemaps)
96 OpenGL 1.4 2002 (added auto-mipmapping)
97 OpenGLES 1.0 2003 (deprecated 80% of the language; fork of OpenGL 1.3)
98 OpenGL 1.5 2003 (added VBOs)
99 OpenGLES 1.1 2004 (fork of OpenGL 1.5)
100 OpenGL 2.0 2004 (a political quagmire)
101 OpenGLES 2.0 2007 (deprecated 95% of the language; fork of OpenGL 2.0)
102 OpenGL 3.0 2008 (added FBOs, VAOs, deprecated 60% of the language)
105 Some things that are missing:
107 - glTexGeni, meaning no spherical environment-mapping textures.
109 - gluNewTess, meaning no tesselation of complex objects.
111 - glMap2f mesh evaluators, meaning no Utah Teapot.
113 - glPolygonMode with GL_LINE or GL_POINT, meaning no wireframe modes
114 that do hidden-surface removal.
116 - glSelectBuffer, meaning no mouse-hit detection on rendered objects.
118 - gluNewQuadric, gluCylinder, etc: rewrite your code to use tube.c, etc.
120 - Putting verts in a display list without a wrapping glBegin.
121 I didn't realize that even worked! Lockward used to do that,
122 before I fixed it to not.
124 - Not every function is implemented; just the ones that I needed for
125 xscreensaver. However, the trivial ones are trivial to enable
126 as they come up. Harder ones will be harder.
128 As a result of that, these savers look wrong:
130 atlantis Uses EYE_PLANE.
131 blocktube Uses SPHERE_MAP.
132 dnalogo Uses GLUtesselator.
133 extrusion Uses all kinds of GLUT crap.
134 flyingtoasters Uses SPHERE_MAP.
135 winduprobot Uses SPHERE_MAP.
136 jigglypuff Uses SPHERE_MAP (in chrome mode), GL_LINE (in wireframe)
137 jigsaw Uses GLUtesselator.
138 pinion Uses glSelectBuffer and gluPickMatrix for mouse-clicks.
139 pipes Uses glMap2f for the Utah Teapot.
140 polyhedra Uses GLUtesselator (concave objects); also Utah Teapot.
141 skytentacles Uses GL_LINE in -cel mode.
142 timetunnel Uses GL_CONSTANT_ALPHA and all kinds of other stuff.
151 #endif /* HAVE_CONFIG_H */
153 #ifdef HAVE_JWZGLES /* whole file */
163 #endif /* HAVE_UNISTD_H */
165 #if defined(USE_IPHONE)
166 # include <OpenGLES/ES1/gl.h>
167 # include <OpenGLES/ES1/glext.h>
168 #elif defined(HAVE_COCOA)
169 # include <OpenGL/gl.h>
170 # include <OpenGL/glu.h>
171 #elif defined(HAVE_ANDROID)
172 # include <GLES/gl.h>
173 # include <android/log.h>
175 # ifndef GL_GLEXT_PROTOTYPES
176 # define GL_GLEXT_PROTOTYPES /* for glBindBuffer */
182 #include "jwzglesI.h"
184 #define STRINGIFY(X) #X
187 #define countof(x) (sizeof((x))/sizeof((*x)))
192 extern void jwxyz_abort (const char *fmt, ...) __dead2;
193 # define Assert(C,S) do { if (!(C)) { jwxyz_abort ("%s",S); }} while(0)
194 #elif defined HAVE_ANDROID
195 # define Assert(C,S) do { \
197 __android_log_print (ANDROID_LOG_ERROR, "xscreensaver", "jwzgles: %s\n", S); \
201 # define Assert(C,S) do { \
203 fprintf (stderr, "jwzgles: %s\n", S); \
209 typedef struct { GLfloat x, y, z; } XYZ;
210 typedef struct { GLfloat x, y, z, w; } XYZW;
211 typedef struct { GLfloat s, t, r, q; } STRQ;
212 typedef struct { GLfloat r, g, b, a; } RGBA;
215 /* Used to record all calls to glVertex3f, glNormal3f, etc.
216 while inside glBegin / glEnd so that we can convert that
217 to a single call to glDrawArrays.
221 int count, size; /* size of each array */
223 XYZW *verts; /* Arrays being built */
228 int ncount; /* How many normals, tex coords and colors were */
229 int tcount; /* used. We optimize based on "0, 1, or many". */
231 int materialistic; /* Whether glMaterial was called inside glBegin */
233 XYZ cnorm; /* Prevailing normal/texture/color while building */
240 typedef void (*list_fn_cb) (void);
243 /* We need this nonsense because you can't cast a double to a void*
244 or vice versa. They tend to be passed in different registers,
245 and you need to know about that because it's still 1972 here.
248 const void *v; GLfloat f; GLuint i; GLshort s; GLdouble d;
251 typedef struct { /* saved args for glDrawArrays */
252 int binding, size, type, stride, bytes;
256 typedef enum { /* shorthand describing arglist signature */
257 PROTO_VOID, /* no args */
258 PROTO_I, /* 1 int arg */
259 PROTO_F, /* 1 float arg */
260 PROTO_II, /* int, int */
261 PROTO_FF, /* float, float */
262 PROTO_IF, /* int, float */
263 PROTO_III, /* int, int, int */
264 PROTO_FFF, /* float, float, float */
265 PROTO_IIF, /* int, int, float */
266 PROTO_IIII, /* int, int, int, int */
267 PROTO_FFFF, /* float, float, float, float */
268 PROTO_IIV, /* int, int[4] */
269 PROTO_IFV, /* int, float[4] */
270 PROTO_IIIV, /* int, int, int[4] */
271 PROTO_IIFV, /* int, int, float[4] */
272 PROTO_FV16, /* float[16] */
273 PROTO_ARRAYS /* glDrawArrays */
276 typedef struct { /* A single element of a display list */
278 list_fn_cb fn; /* saved function pointer */
279 fn_proto proto; /* arglist prototype */
280 draw_array *arrays; /* args for glDrawArrays */
281 void_int argv[16]; /* args for everything else */
285 typedef struct { /* a display list: saved activity within glNewList */
290 /* Named buffer that should be freed when this display list is deleted. */
296 typedef struct { /* All display lists */
302 #define ISENABLED_TEXTURE_2D (1<<0)
303 #define ISENABLED_TEXTURE_GEN_S (1<<1)
304 #define ISENABLED_TEXTURE_GEN_T (1<<2)
305 #define ISENABLED_TEXTURE_GEN_R (1<<3)
306 #define ISENABLED_TEXTURE_GEN_Q (1<<4)
307 #define ISENABLED_LIGHTING (1<<5)
308 #define ISENABLED_BLEND (1<<6)
309 #define ISENABLED_DEPTH_TEST (1<<7)
310 #define ISENABLED_CULL_FACE (1<<8)
311 #define ISENABLED_NORMALIZE (1<<9)
312 #define ISENABLED_FOG (1<<10)
313 #define ISENABLED_COLMAT (1<<11)
314 #define ISENABLED_VERT_ARRAY (1<<12)
315 #define ISENABLED_NORM_ARRAY (1<<13)
316 #define ISENABLED_TEX_ARRAY (1<<14)
317 #define ISENABLED_COLOR_ARRAY (1<<15)
318 #define ISENABLED_ALPHA_TEST (1<<16)
323 GLfloat obj[4], eye[4];
327 typedef struct { /* global state */
329 vert_set set; /* set being built */
331 int compiling_list; /* list id if inside glNewList; 0 means immediate */
332 int replaying_list; /* depth of call stack to glCallList */
333 int compiling_verts; /* inside glBegin */
335 list_set lists; /* saved lists */
337 unsigned long enabled; /* enabled flags, immediate mode */
338 unsigned long list_enabled; /* and for the list-in-progress */
340 texgen_state s, t, r, q;
342 /* Implementing glPushClientAttrib? Don't forget about these! */
343 draw_array varray, narray, carray, tarray;
348 static jwzgles_state *state = 0;
353 static void Log(const char *fmt, ...)
356 va_start (args, fmt);
358 /* setprop log.redirect-stdio true is another possibility, but that
359 apparently only works on rooted devices.
361 __android_log_vprint(ANDROID_LOG_DEBUG, "xscreensaver", fmt, args);
363 vfprintf(stderr, fmt, args);
368 # define LOG(A) Log("jwzgles: " A "\n")
369 # define LOG1(A,B) Log("jwzgles: " A "\n",B)
370 # define LOG2(A,B,C) Log("jwzgles: " A "\n",B,C)
371 # define LOG3(A,B,C,D) Log("jwzgles: " A "\n",B,C,D)
372 # define LOG4(A,B,C,D,E) Log("jwzgles: " A "\n",B,C,D,E)
373 # define LOG5(A,B,C,D,E,F) Log("jwzgles: " A "\n",B,C,D,E,F)
374 # define LOG6(A,B,C,D,E,F,G) Log("jwzgles: " A "\n",B,C,D,E,F,G)
375 # define LOG7(A,B,C,D,E,F,G,H) Log("jwzgles: " A "\n",B,C,D,E,F,G,H)
376 # define LOG8(A,B,C,D,E,F,G,H,I)\
377 Log("jwzgles: "A "\n",B,C,D,E,F,G,H,I)
378 # define LOG9(A,B,C,D,E,F,G,H,I,J)\
379 Log("jwzgles: "A "\n",B,C,D,E,F,G,H,I,J)
380 # define LOG10(A,B,C,D,E,F,G,H,I,J,K)\
381 Log("jwzgles: "A "\n",B,C,D,E,F,G,H,I,J,K)
382 # define LOG17(A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R)\
383 Log("jwzgles: "A "\n",B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R)
384 # define CHECK(S) jwzgles_check_gl_error(S)
386 # define LOG(A) /* */
387 # define LOG1(A,B) /* */
388 # define LOG2(A,B,C) /* */
389 # define LOG3(A,B,C,D) /* */
390 # define LOG4(A,B,C,D,E) /* */
391 # define LOG5(A,B,C,D,E,F) /* */
392 # define LOG6(A,B,C,D,E,F,G) /* */
393 # define LOG7(A,B,C,D,E,F,G,H) /* */
394 # define LOG8(A,B,C,D,E,F,G,H,I) /* */
395 # define LOG9(A,B,C,D,E,F,G,H,I,J) /* */
396 # define LOG10(A,B,C,D,E,F,G,H,I,J,K) /* */
397 # define LOG17(A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R) /* */
398 # define CHECK(S) /* */
403 mode_desc (int mode) /* for debugging messages */
406 # define SS(X) case GL_##X: return STRINGIFY(X);
410 SS(AMBIENT_AND_DIFFUSE)
426 SS(COLOR_ARRAY_BUFFER_BINDING);
428 SS(COLOR_MATERIAL_FACE)
429 SS(COLOR_MATERIAL_PARAMETER)
441 SS(ELEMENT_ARRAY_BUFFER)
454 SS(INVALID_OPERATION)
462 SS(LIGHT_MODEL_AMBIENT)
463 SS(LIGHT_MODEL_COLOR_CONTROL)
464 SS(LIGHT_MODEL_LOCAL_VIEWER)
465 SS(LIGHT_MODEL_TWO_SIDE)
468 SS(LINEAR_MIPMAP_LINEAR)
469 SS(LINEAR_MIPMAP_NEAREST)
480 SS(NEAREST_MIPMAP_LINEAR)
481 SS(NEAREST_MIPMAP_NEAREST)
484 SS(NORMAL_ARRAY_BUFFER_BINDING);
487 SS(ONE_MINUS_DST_ALPHA)
488 SS(ONE_MINUS_DST_COLOR)
489 SS(ONE_MINUS_SRC_ALPHA)
490 SS(ONE_MINUS_SRC_COLOR)
495 SS(POLYGON_OFFSET_FILL)
511 SS(SEPARATE_SPECULAR_COLOR)
520 SS(SRC_ALPHA_SATURATE)
525 SS(STENCIL_BUFFER_BIT)
537 SS(TEXTURE_ALPHA_SIZE)
538 SS(TEXTURE_BINDING_2D)
539 SS(TEXTURE_BLUE_SIZE)
541 SS(TEXTURE_BORDER_COLOR)
542 SS(TEXTURE_COMPONENTS)
543 SS(TEXTURE_COORD_ARRAY)
544 SS(TEXTURE_COORD_ARRAY_BUFFER_BINDING);
546 SS(TEXTURE_ENV_COLOR)
553 SS(TEXTURE_GREEN_SIZE)
555 SS(TEXTURE_INTENSITY_SIZE)
556 SS(TEXTURE_LUMINANCE_SIZE)
557 SS(TEXTURE_MAG_FILTER)
558 SS(TEXTURE_MIN_FILTER)
566 SS(UNPACK_ROW_LENGTH)
568 SS(UNSIGNED_INT_8_8_8_8_REV)
573 SS(VERTEX_ARRAY_BUFFER_BINDING);
574 /*SS(COLOR_BUFFER_BIT) -- same value as GL_LIGHT0 */
576 case (GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT):
577 return "DEPTH_BUFFER_BIT | COLOR_BUFFER_BIT";
578 /* Oops, same as INVALID_ENUM.
579 case (GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT):
580 return "DEPTH_BUFFER_BIT | STENCIL_BUFFER_BIT";
582 case (GL_COLOR_BUFFER_BIT | GL_STENCIL_BUFFER_BIT):
583 return "COLOR_BUFFER_BIT | STENCIL_BUFFER_BIT";
584 case (GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT | GL_STENCIL_BUFFER_BIT):
585 return "DEPTH_BUFFER_BIT | COLOR_BUFFER_BIT | STENCIL_BUFFER_BIT";
588 static char buf[255];
589 sprintf (buf, "0x%04X", mode);
596 jwzgles_check_gl_error (const char *s)
598 GLenum i = glGetError();
599 if (i == GL_NO_ERROR) return;
600 fprintf (stderr, "jwzgles: GL ERROR: %s: %s\n", s, mode_desc(i));
607 make_room (const char *name, void **array, int span, int *count, int *size)
609 if (*count + 1 >= *size)
611 int new_size = (*count + 20) * 1.2; /* mildly exponential */
612 *array = realloc (*array, new_size * span);
613 Assert (*array, "out of memory");
614 /* LOG3("%s: grew %d -> %d", name, *size, new_size); */
624 state = (jwzgles_state *) calloc (1, sizeof (*state));
626 if (state->lists.lists)
628 state->compiling_list = 0;
629 if (state->lists.count)
630 jwzgles_glDeleteLists (1, state->lists.count);
631 free (state->lists.lists);
634 if (state->set.verts) free (state->set.verts);
635 if (state->set.norms) free (state->set.norms);
636 if (state->set.tex) free (state->set.tex);
637 if (state->set.color) free (state->set.color);
639 memset (state, 0, sizeof(*state));
641 state->s.mode = state->t.mode = state->r.mode = state->q.mode =
643 state->s.obj[0] = state->s.eye[0] = 1; /* s = 1 0 0 0 */
644 state->t.obj[1] = state->t.eye[1] = 1; /* t = 0 1 0 0 */
649 jwzgles_glGenLists (int n)
654 Assert (!state->compiling_verts, "glGenLists not allowed inside glBegin");
656 /* Ensure space in state->lists, clear the one at the end, and tick counter
657 Note that lists are never really deleted, and we can never re-use elements
658 of this array. glDeleteLists zeroes out the contents of the list, but
659 the list ID is still valid for use with glNewList forever.
660 #### So maybe this should be a linked list instead of an array.
662 for (i = 0; i < n; i++)
666 make_room ("glGenLists",
667 (void **) &state->lists.lists,
668 sizeof (*state->lists.lists),
669 &state->lists.count, &state->lists.size);
670 state->lists.count++;
671 id = state->lists.count;
672 L = &state->lists.lists[id-1];
674 memset (L, 0, sizeof (*L));
676 if (ret == 0) ret = id;
677 LOG1("glGenLists -> %d", L->id);
680 /* Return the ID of the first list allocated */
687 jwzgles_glNewList (int id, int mode)
690 Assert (id > 0 && id <= state->lists.count, "glNewList: bogus ID");
691 Assert (mode == GL_COMPILE, "glNewList: bad mode");
692 Assert (!state->compiling_verts, "glNewList not allowed inside glBegin");
693 Assert (!state->compiling_list, "nested glNewList");
694 Assert (state->set.count == 0, "missing glEnd");
696 L = &state->lists.lists[id-1];
697 Assert (L->id == id, "glNewList corrupted");
699 if (L->count != 0) jwzgles_glDeleteLists (L->id, 1); /* Overwriting */
700 Assert (L->count == 0, "glNewList corrupted");
702 state->compiling_list = id;
704 state->list_enabled = state->enabled;
706 LOG1("glNewList -> %d", id);
710 static void save_arrays (list_fn *, int);
711 static void restore_arrays (list_fn *, int);
712 static void copy_array_data (draw_array *, int, const char *);
713 static void optimize_arrays (void);
714 static void generate_texture_coords (GLuint, GLuint);
718 jwzgles_glEndList (void)
720 Assert (state->compiling_list, "extra glEndList");
721 Assert (state->set.count == 0, "missing glEnd");
722 Assert (!state->compiling_verts, "glEndList not allowed inside glBegin");
723 LOG1("glEndList %d", state->compiling_list);
725 state->compiling_list = 0;
726 state->list_enabled = state->enabled;
731 list_push (const char * const name,
732 list_fn_cb fn, fn_proto proto, void_int *av)
738 Assert (state->compiling_list > 0, "not inside glNewList");
739 Assert (state->compiling_list <= state->lists.count, "glNewList corrupted");
741 L = &state->lists.lists[state->compiling_list-1];
742 Assert (L, "glNewList: no list");
744 make_room ("glNewLists",
745 (void **) &L->fns, sizeof (*L->fns),
746 &L->count, &L->size);
747 memset (&L->fns[L->count], 0, sizeof (*L->fns));
748 F = L->fns + L->count;
753 if (proto != PROTO_VOID)
754 for (i = 0; i < countof(F->argv); i++)
760 LOG1 (" push %-12s", name);
763 if (fn == (list_fn_cb) &jwzgles_glBegin ||
764 fn == (list_fn_cb) &jwzgles_glFrontFace ||
765 fn == (list_fn_cb) &jwzgles_glEnable ||
766 fn == (list_fn_cb) &jwzgles_glDisable ||
767 fn == (list_fn_cb) &jwzgles_glEnableClientState ||
768 fn == (list_fn_cb) &jwzgles_glDisableClientState ||
769 fn == (list_fn_cb) &jwzgles_glShadeModel ||
770 fn == (list_fn_cb) &jwzgles_glMatrixMode)
771 LOG2 (" push %-12s %s", name, mode_desc (av[0].i));
773 LOG2 (" push %-12s %d", name, av[0].i);
776 LOG2 (" push %-12s %7.3f", name, av[0].f);
779 if (fn == (list_fn_cb) &jwzgles_glBindTexture ||
780 fn == (list_fn_cb) &jwzgles_glBindBuffer)
781 LOG3 (" push %-12s %s %d", name, mode_desc (av[0].i), av[1].i);
783 LOG3 (" push %-12s %d %d", name, av[0].i, av[1].i);
786 LOG3 (" push %-12s %7.3f %7.3f", name, av[0].f, av[1].f);
789 LOG3 (" push %-12s %s %7.3f", name, mode_desc (av[0].i), av[1].f);
793 if (fn == (list_fn_cb) &jwzgles_glDrawArrays ||
794 fn == (list_fn_cb) &jwzgles_glTexParameteri)
795 LOG4 (" push %-12s %s %d %d", name, mode_desc (av[0].i),
798 LOG4 (" push %-12s %d %d %d", name, av[0].i, av[1].i, av[2].i);
801 LOG4 (" push %-12s %7.3f %7.3f %7.3f", name, av[0].f, av[1].f, av[2].f);
804 LOG4 (" push %-12s %s %s %7.3f", name,
805 mode_desc(av[0].i), mode_desc(av[1].i), av[2].f);
808 LOG5 (" push %-12s %d %d %d %d", name,
809 av[0].i, av[1].i, av[2].i, av[3].i);
812 LOG5 (" push %-12s %7.3f %7.3f %7.3f %7.3f", name,
813 av[0].f, av[1].f, av[2].f, av[3].f);
816 LOG6 (" push %-12s %s %3.1f %3.1f %3.1f %3.1f", name, mode_desc (av[0].i),
817 av[1].f, av[2].f, av[3].f, av[4].f);
820 LOG6 (" push %-12s %s %d %d %d %d", name, mode_desc (av[0].i),
821 av[1].i, av[2].i, av[3].i, av[4].i);
824 LOG7 (" push %-12s %s %-8s %3.1f %3.1f %3.1f %3.1f", name,
825 mode_desc (av[0].i), mode_desc (av[1].i),
826 av[2].f, av[3].f, av[4].f, av[5].f);
829 LOG7 (" push %-12s %s %-8s %3d %3d %3d %3d", name,
830 mode_desc (av[0].i), mode_desc (av[1].i),
831 av[2].i, av[3].i, av[4].i, av[5].i);
834 LOG17 (" push %-12s ["
835 "%8.3f %8.3f %8.3f %8.3f " "\n\t\t\t "
836 "%8.3f %8.3f %8.3f %8.3f " "\n\t\t\t "
837 "%8.3f %8.3f %8.3f %8.3f " "\n\t\t\t "
838 "%8.3f %8.3f %8.3f %8.3f ]",
840 av[0].f, av[1].f, av[2].f, av[3].f,
841 av[4].f, av[5].f, av[6].f, av[7].f,
842 av[8].f, av[9].f, av[10].f, av[11].f,
843 av[12].f, av[13].f, av[14].f, av[15].f);
846 Assert (0, "bogus prototype");
851 if (proto == PROTO_ARRAYS) /* glDrawArrays */
852 save_arrays (F, av[1].i + av[2].i);
859 jwzgles_glBegin (int mode)
861 Assert (!state->compiling_verts, "nested glBegin");
862 state->compiling_verts++;
864 /* Only these commands are allowed inside glBegin:
866 glVertex -- not allowed outside
877 glArrayElement -- not allowed outside
884 if (!state->replaying_list)
885 LOG2 ("%sglBegin %s",
886 (state->compiling_list || state->replaying_list ? " " : ""),
889 Assert (state->set.count == 0, "glBegin corrupted");
890 state->set.mode = mode;
891 state->set.count = 0;
892 state->set.ncount = 0;
893 state->set.tcount = 0;
894 state->set.ccount = 0;
899 jwzgles_glDeleteLists (int id0, int range)
901 Assert (!state->compiling_verts, "glDeleteLists not allowed inside glBegin");
903 if (state->compiling_list)
908 list_push ("glDeleteLists", (list_fn_cb) &jwzgles_glDeleteLists,
915 if (!state->replaying_list)
916 LOG2 ("glDeleteLists %d %d", id0, range);
918 for (id = id0 + range - 1; id >= id0; id--)
922 if (id == 0) continue; /* People do this stupid thing */
923 if (id > state->lists.count) break; /* this too */
924 Assert (id > 0 && id <= state->lists.count,
925 "glDeleteLists: bogus ID");
926 L = &state->lists.lists[id-1];
927 Assert (L->id == id, "glDeleteLists corrupted");
929 for (i = 0; i < L->count; i++)
931 list_fn *lf = &L->fns[i];
935 for (j = 0; j < 4; j++)
936 /* If there's a binding, 'data' is an index, not a ptr. */
937 if (!lf->arrays[j].binding &&
939 free (lf->arrays[j].data);
946 glDeleteBuffers (1, &L->buffer);
948 memset (L, 0, sizeof (*L));
956 jwzgles_glIsList (GLuint id)
958 return (id > 0 && id < state->lists.count);
964 jwzgles_glNormal3fv (const GLfloat *v)
966 if (state->compiling_list && !state->compiling_verts)
972 list_push ("glNormal3f", (list_fn_cb) &jwzgles_glNormal3f,
977 if (!state->replaying_list)
978 LOG5 ("%s%sglNormal3f %7.3f %7.3f %7.3f",
979 (state->compiling_list || state->replaying_list ? " " : ""),
980 (state->compiling_verts ? " rec " : ""),
983 if (state->compiling_verts) /* inside glBegin */
985 state->set.cnorm.x = v[0];
986 state->set.cnorm.y = v[1];
987 state->set.cnorm.z = v[2];
989 if (state->set.count > 0 && state->set.ncount == 1) /* not first! */
992 else /* outside glBegin */
994 glNormal3f (v[0], v[1], v[2]);
1002 jwzgles_glNormal3f (GLfloat x, GLfloat y, GLfloat z)
1008 jwzgles_glNormal3fv (v);
1013 jwzgles_glTexCoord4fv (const GLfloat *v)
1015 if (state->compiling_list && !state->compiling_verts)
1022 list_push ("glTexCoord4f", (list_fn_cb) &jwzgles_glTexCoord4f,
1027 if (!state->replaying_list)
1028 LOG6 ("%s%sglTexCoord4f %7.3f %7.3f %7.3f %7.3f",
1029 (state->compiling_list || state->replaying_list ? " " : ""),
1030 (state->compiling_verts ? " rec " : ""),
1031 v[0], v[1], v[2], v[3]);
1033 Assert (state->compiling_verts, "glTexCoord4fv outside glBegin");
1035 if (state->compiling_verts) /* inside glBegin */
1037 state->set.ctex.s = v[0];
1038 state->set.ctex.t = v[1];
1039 state->set.ctex.r = v[2];
1040 state->set.ctex.q = v[3];
1041 state->set.tcount++;
1042 if (state->set.count > 0 && state->set.tcount == 1) /* not first! */
1043 state->set.tcount++;
1050 jwzgles_glTexCoord4f (GLfloat s, GLfloat t, GLfloat r, GLfloat q)
1057 jwzgles_glTexCoord4fv (v);
1062 jwzgles_glTexCoord3fv (const GLfloat *v)
1069 jwzgles_glTexCoord4fv (vv);
1074 jwzgles_glTexCoord2fv (const GLfloat *v)
1081 jwzgles_glTexCoord4fv (vv);
1086 jwzgles_glTexCoord3f (GLfloat s, GLfloat t, GLfloat r)
1088 jwzgles_glTexCoord4f (s, t, r, 1);
1093 jwzgles_glTexCoord2f (GLfloat s, GLfloat t)
1095 jwzgles_glTexCoord4f (s, t, 0, 1);
1100 jwzgles_glTexCoord1f (GLfloat s)
1102 jwzgles_glTexCoord4f (s, 0, 0, 1);
1106 /* glColor: GLfloat */
1109 jwzgles_glColor4fv (const GLfloat *v)
1111 if (state->compiling_list && !state->compiling_verts)
1118 list_push ("glColor4f", (list_fn_cb) &jwzgles_glColor4f,
1123 if (!state->replaying_list)
1124 LOG6 ("%s%sglColor4f %7.3f %7.3f %7.3f %7.3f",
1125 (state->compiling_list || state->replaying_list ? " " : ""),
1126 (state->compiling_verts ? " rec " : ""),
1127 v[0], v[1], v[2], v[3]);
1129 if (state->compiling_verts) /* inside glBegin */
1131 state->set.ccolor.r = v[0];
1132 state->set.ccolor.g = v[1];
1133 state->set.ccolor.b = v[2];
1134 state->set.ccolor.a = v[3];
1135 state->set.ccount++;
1136 if (state->set.count > 0 && state->set.ccount == 1) /* not first! */
1137 state->set.ccount++;
1139 else /* outside glBegin */
1141 glColor4f (v[0], v[1], v[2], v[3]);
1149 jwzgles_glColor4f (GLfloat r, GLfloat g, GLfloat b, GLfloat a)
1156 jwzgles_glColor4fv (v);
1160 jwzgles_glColor3f (GLfloat r, GLfloat g, GLfloat b)
1162 jwzgles_glColor4f (r, g, b, 1);
1166 jwzgles_glColor3fv (const GLfloat *v)
1168 jwzgles_glColor3f (v[0], v[1], v[2]);
1172 /* glColor: GLdouble */
1175 jwzgles_glColor4d (GLdouble r, GLdouble g, GLdouble b, GLdouble a)
1177 jwzgles_glColor4f (r, g, b, a);
1181 jwzgles_glColor4dv (const GLdouble *v)
1183 jwzgles_glColor4d (v[0], v[1], v[2], v[3]);
1187 jwzgles_glColor3d (GLdouble r, GLdouble g, GLdouble b)
1189 jwzgles_glColor4d (r, g, b, 1.0);
1193 jwzgles_glColor3dv (const GLdouble *v)
1195 jwzgles_glColor3d (v[0], v[1], v[2]);
1199 /* glColor: GLint (INT_MIN - INT_MAX) */
1202 jwzgles_glColor4i (GLint r, GLint g, GLint b, GLint a)
1204 /* -0x8000000 - 0x7FFFFFFF => 0.0 - 1.0 */
1205 jwzgles_glColor4f (0.5 + (GLfloat) r / 0xFFFFFFFF,
1206 0.5 + (GLfloat) g / 0xFFFFFFFF,
1207 0.5 + (GLfloat) b / 0xFFFFFFFF,
1208 0.5 + (GLfloat) a / 0xFFFFFFFF);
1212 jwzgles_glColor4iv (const GLint *v)
1214 jwzgles_glColor4i (v[0], v[1], v[2], v[3]);
1219 jwzgles_glColor3i (GLint r, GLint g, GLint b)
1221 jwzgles_glColor4i (r, g, b, 0x7FFFFFFF);
1225 jwzgles_glColor3iv (const GLint *v)
1227 jwzgles_glColor3i (v[0], v[1], v[2]);
1231 /* glColor: GLuint (0 - UINT_MAX) */
1234 jwzgles_glColor4ui (GLuint r, GLuint g, GLuint b, GLuint a)
1236 /* 0 - 0xFFFFFFFF => 0.0 - 1.0 */
1237 jwzgles_glColor4f ((GLfloat) r / 0xFFFFFFFF,
1238 (GLfloat) g / 0xFFFFFFFF,
1239 (GLfloat) b / 0xFFFFFFFF,
1240 (GLfloat) a / 0xFFFFFFFF);
1244 jwzgles_glColor4uiv (const GLuint *v)
1246 jwzgles_glColor4ui (v[0], v[1], v[2], v[3]);
1250 jwzgles_glColor3ui (GLuint r, GLuint g, GLuint b)
1252 jwzgles_glColor4ui (r, g, b, 0xFFFFFFFF);
1256 jwzgles_glColor3uiv (const GLuint *v)
1258 jwzgles_glColor3ui (v[0], v[1], v[2]);
1262 /* glColor: GLshort (SHRT_MIN - SHRT_MAX) */
1265 jwzgles_glColor4s (GLshort r, GLshort g, GLshort b, GLshort a)
1267 /* -0x8000 - 0x7FFF => 0.0 - 1.0 */
1268 jwzgles_glColor4f (0.5 + (GLfloat) r / 0xFFFF,
1269 0.5 + (GLfloat) g / 0xFFFF,
1270 0.5 + (GLfloat) b / 0xFFFF,
1271 0.5 + (GLfloat) a / 0xFFFF);
1275 jwzgles_glColor4sv (const GLshort *v)
1277 jwzgles_glColor4s (v[0], v[1], v[2], v[3]);
1281 jwzgles_glColor3s (GLshort r, GLshort g, GLshort b)
1283 jwzgles_glColor4s (r, g, b, 0x7FFF);
1287 jwzgles_glColor3sv (const GLshort *v)
1289 jwzgles_glColor3s (v[0], v[1], v[2]);
1293 /* glColor: GLushort (0 - USHRT_MAX) */
1296 jwzgles_glColor4us (GLushort r, GLushort g, GLushort b, GLushort a)
1298 /* 0 - 0xFFFF => 0.0 - 1.0 */
1299 jwzgles_glColor4f ((GLfloat) r / 0xFFFF,
1300 (GLfloat) g / 0xFFFF,
1301 (GLfloat) b / 0xFFFF,
1302 (GLfloat) a / 0xFFFF);
1306 jwzgles_glColor4usv (const GLushort *v)
1308 jwzgles_glColor4us (v[0], v[1], v[2], v[3]);
1312 jwzgles_glColor3us (GLushort r, GLushort g, GLushort b)
1314 jwzgles_glColor4us (r, g, b, 0xFFFF);
1318 jwzgles_glColor3usv (const GLushort *v)
1320 jwzgles_glColor3us (v[0], v[1], v[2]);
1324 /* glColor: GLbyte (-128 - 127) */
1327 jwzgles_glColor4b (GLbyte r, GLbyte g, GLbyte b, GLbyte a)
1329 /* -128 - 127 => 0.0 - 1.0 */
1330 jwzgles_glColor4f (0.5 + (GLfloat) r / 255,
1331 0.5 + (GLfloat) g / 255,
1332 0.5 + (GLfloat) b / 255,
1333 0.5 + (GLfloat) a / 255);
1337 jwzgles_glColor4bv (const GLbyte *v)
1339 jwzgles_glColor4b (v[0], v[1], v[2], v[3]);
1343 jwzgles_glColor3b (GLbyte r, GLbyte g, GLbyte b)
1345 jwzgles_glColor4b (r, g, b, 127);
1349 jwzgles_glColor3bv (const GLbyte *v)
1351 jwzgles_glColor3b (v[0], v[1], v[2]);
1355 /* glColor: GLubyte (0 - 255) */
1358 jwzgles_glColor4ub (GLubyte r, GLubyte g, GLubyte b, GLubyte a)
1360 /* 0 - 255 => 0.0 - 1.0 */
1361 jwzgles_glColor4f (r / 255.0, g / 255.0, b / 255.0, a / 255.0);
1365 jwzgles_glColor4ubv (const GLubyte *v)
1367 jwzgles_glColor4ub (v[0], v[1], v[2], v[3]);
1371 jwzgles_glColor3ub (GLubyte r, GLubyte g, GLubyte b)
1373 jwzgles_glColor4ub (r, g, b, 255);
1377 jwzgles_glColor3ubv (const GLubyte *v)
1379 jwzgles_glColor3ub (v[0], v[1], v[2]);
1385 jwzgles_glMaterialfv (GLenum face, GLenum pname, const GLfloat *color)
1387 /* If this is called inside glBegin/glEnd with a front ambient color,
1388 then treat it the same as glColor: set the color of the upcoming
1391 Other faces or lighting types within glBegin are ignored.
1394 if (state->compiling_verts)
1396 if ((face == GL_FRONT ||
1397 face == GL_FRONT_AND_BACK) &&
1398 (pname == GL_AMBIENT ||
1399 pname == GL_DIFFUSE ||
1400 pname == GL_AMBIENT_AND_DIFFUSE))
1402 jwzgles_glColor4f (color[0], color[1], color[2], color[3]);
1403 state->set.materialistic++;
1406 LOG2 (" IGNORING glMaterialfv %s %s",
1407 mode_desc(face), mode_desc(pname));
1409 else if (state->compiling_list)
1418 list_push ("glMaterialfv", (list_fn_cb) &jwzgles_glMaterialfv,
1423 /* If this is called outside of glBegin/glEnd with a front
1424 ambient color, then the intent is presumably for that color
1425 to apply to the upcoming vertexes (which may be played back
1426 from a list that does not have vertex colors in it). In that
1427 case, the only way to make the colors show up is to call
1428 glColor() with GL_COLOR_MATERIAL enabled.
1430 I'm not sure if this will have other inappropriate side effects...
1432 if ((face == GL_FRONT ||
1433 face == GL_FRONT_AND_BACK) &&
1434 (pname == GL_AMBIENT ||
1435 pname == GL_DIFFUSE ||
1436 pname == GL_AMBIENT_AND_DIFFUSE))
1438 jwzgles_glEnable (GL_COLOR_MATERIAL);
1439 jwzgles_glColor4f (color[0], color[1], color[2], color[3]);
1442 /* OpenGLES seems to throw "invalid enum" for GL_FRONT -- but it
1443 goes ahead and sets the material anyway! No error if we just
1444 always use GL_FRONT_AND_BACK.
1446 if (face == GL_FRONT)
1447 face = GL_FRONT_AND_BACK;
1448 if (! state->replaying_list)
1449 LOG7 ("direct %-12s %s %s %7.3f %7.3f %7.3f %7.3f", "glMaterialfv",
1450 mode_desc(face), mode_desc(pname),
1451 color[0], color[1], color[2], color[3]);
1452 glMaterialfv (face, pname, color); /* the real one */
1453 CHECK("glMaterialfv");
1459 jwzgles_glMaterialiv (GLenum face, GLenum pname, const GLint *v)
1466 jwzgles_glMaterialfv (face, pname, vv);
1470 jwzgles_glMaterialf (GLenum face, GLenum pname, const GLfloat c)
1477 jwzgles_glMaterialfv (face, pname, vv);
1482 jwzgles_glMateriali (GLenum face, GLenum pname, const GLuint c)
1484 jwzgles_glMaterialf (face, pname, c);
1489 jwzgles_glColorMaterial (GLenum face, GLenum mode)
1491 Assert (!state->compiling_verts,
1492 "glColorMaterial not allowed inside glBegin");
1494 if (state->compiling_list)
1499 list_push ("glColorMaterial", (list_fn_cb) &jwzgles_glColorMaterial,
1504 /* No real analog to this distinction in OpenGLES, since color
1505 arrays don't distinguish between "color" and "material", */
1506 Assert (0, "glColorMaterial: unimplemented mode");
1515 jwzgles_glVertex4fv (const GLfloat *v)
1517 vert_set *s = &state->set;
1518 int count = s->count;
1520 Assert (state->compiling_verts, "glVertex4fv not inside glBegin");
1522 LOG5("%s rec glVertex4f %7.3f %7.3f %7.3f %7.3f",
1523 (state->compiling_list || state->replaying_list ? " " : ""),
1524 v[0], v[1], v[2], v[3]);
1526 if (count >= s->size - 1)
1528 int new_size = 20 + (s->size * 1.2);
1530 /* 4 arrays, different element sizes...
1531 We allocate all 4 arrays just in case we need them,
1532 but we might not end up using them all at the end.
1535 s->verts = (XYZW *) realloc (s->verts, new_size * sizeof (*s->verts));
1536 Assert (s->verts, "out of memory");
1538 s->norms = (XYZ *) realloc (s->norms, new_size * sizeof (*s->norms));
1539 Assert (s->norms, "out of memory");
1541 s->tex = (STRQ *) realloc (s->tex, new_size * sizeof (*s->tex));
1542 Assert (s->tex, "out of memory");
1544 s->color = (RGBA *) realloc (s->color, new_size * sizeof (*s->color));
1545 Assert (s->color, "out of memory");
1550 s->verts [count].x = v[0];
1551 s->verts [count].y = v[1];
1552 s->verts [count].z = v[2];
1553 s->verts [count].w = v[3];
1554 s->norms [count] = s->cnorm;
1555 s->tex [count] = s->ctex;
1556 s->color [count] = s->ccolor;
1562 jwzgles_glVertex4f (GLfloat x, GLfloat y, GLfloat z, GLfloat w)
1569 jwzgles_glVertex4fv (v);
1573 jwzgles_glVertex4i (GLint x, GLint y, GLint z, GLint w)
1575 jwzgles_glVertex4f (x, y, z, w);
1579 jwzgles_glVertex3f (GLfloat x, GLfloat y, GLfloat z)
1586 jwzgles_glVertex4fv (v);
1590 jwzgles_glVertex3i (GLint x, GLint y, GLint z)
1592 jwzgles_glVertex3f (x, y, z);
1596 jwzgles_glVertex3fv (const GLfloat *v)
1598 jwzgles_glVertex3f (v[0], v[1], v[2]);
1602 jwzgles_glVertex3dv (const GLdouble *v)
1604 jwzgles_glVertex3f (v[0], v[1], v[2]);
1609 jwzgles_glVertex2f (GLfloat x, GLfloat y)
1615 jwzgles_glVertex3fv (v);
1619 jwzgles_glVertex2dv (const GLdouble *v)
1621 jwzgles_glVertex2f (v[0], v[1]);
1625 jwzgles_glVertex2fv (const GLfloat *v)
1627 jwzgles_glVertex2f (v[0], v[1]);
1631 jwzgles_glVertex2i (GLint x, GLint y)
1633 jwzgles_glVertex2f (x, y);
1638 jwzgles_glLightiv (GLenum light, GLenum pname, const GLint *params)
1645 jwzgles_glLightfv (light, pname, v);
1649 jwzgles_glLightModeliv (GLenum pname, const GLint *params)
1656 jwzgles_glLightModelfv (pname, v);
1660 jwzgles_glFogiv (GLenum pname, const GLint *params)
1667 jwzgles_glFogfv (pname, v);
1671 jwzgles_glLighti (GLenum light, GLenum pname, GLint param)
1673 jwzgles_glLightf (light, pname, param);
1677 jwzgles_glLightModeli (GLenum pname, GLint param)
1679 jwzgles_glLightModelf (pname, param);
1683 jwzgles_glFogi (GLenum pname, GLint param)
1685 jwzgles_glFogf (pname, param);
1690 jwzgles_glRotated (GLdouble angle, GLdouble x, GLdouble y, GLdouble z)
1692 jwzgles_glRotatef (angle, x, y, z);
1697 jwzgles_glClipPlane (GLenum plane, const GLdouble *equation)
1699 Assert (state->compiling_verts, "glClipPlane not inside glBegin");
1700 Assert (0, "glClipPlane unimplemented"); /* no GLES equivalent... */
1705 jwzgles_glPolygonMode (GLenum face, GLenum mode)
1707 Assert (!state->compiling_verts, "not inside glBegin");
1708 if (state->compiling_list)
1713 list_push ("glPolygonMode", (list_fn_cb) &jwzgles_glPolygonMode,
1718 /* POINT and LINE don't exist in GLES */
1719 Assert (mode == GL_FILL, "glPolygonMode: unimplemented mode");
1725 jwzgles_glDrawBuffer (GLenum buf)
1727 Assert (!state->compiling_verts, "not inside glBegin");
1728 if (state->compiling_list)
1732 list_push ("glDrawBuffer", (list_fn_cb) &jwzgles_glDrawBuffer,
1737 /* Assert (buf == GL_BACK, "glDrawBuffer: back buffer only"); */
1738 # ifndef GL_VERSION_ES_CM_1_0 /* not compiling against OpenGLES 1.x */
1739 if (! state->replaying_list)
1740 LOG1 ("direct %-12s", "glDrawBuffer");
1741 glDrawBuffer (buf); /* the real one */
1742 CHECK("glDrawBuffer");
1748 /* Given an array of sets of 4 elements of arbitrary size, convert it
1749 to an array of sets of 6 elements instead: ABCD becomes ABC BCD.
1752 cq2t (unsigned char **arrayP, int stride, int count)
1754 int count2 = count * 6 / 4;
1755 int size = stride * count;
1756 int size2 = stride * count2;
1757 const unsigned char *oarray, *in;
1758 unsigned char *array2, *oarray2, *out;
1762 if (!oarray || count == 0)
1765 array2 = (unsigned char *) malloc (size2);
1766 Assert (array2, "out of memory");
1771 for (i = 0; i < count / 4; i++)
1773 const unsigned char *a, *b, *c, *d; /* the 4 corners */
1774 a = in; in += stride;
1775 b = in; in += stride;
1776 c = in; in += stride;
1777 d = in; in += stride;
1779 # define PUSH(IN) do { \
1780 const unsigned char *ii = IN; \
1782 for (j = 0; j < stride; j++) { \
1786 PUSH (a); PUSH (b); PUSH (d); /* the 2 triangles */
1787 PUSH (b); PUSH (c); PUSH (d);
1791 Assert (in == oarray + size, "convert_quads corrupted");
1792 Assert (out == oarray2 + size2, "convert_quads corrupted");
1800 /* Convert all coordinates in a GL_QUADS vert_set to GL_TRIANGLES.
1803 convert_quads_to_triangles (vert_set *s)
1806 Assert (s->mode == GL_QUADS, "convert_quads bad mode");
1808 cq2t ((unsigned char **) &s->verts, sizeof(*s->verts), s->count);
1809 cq2t ((unsigned char **) &s->norms, sizeof(*s->norms), s->count);
1810 cq2t ((unsigned char **) &s->tex, sizeof(*s->tex), s->count);
1811 cq2t ((unsigned char **) &s->color, sizeof(*s->color), s->count);
1814 s->mode = GL_TRIANGLES;
1819 jwzgles_glEnd (void)
1821 vert_set *s = &state->set;
1822 int was_norm, was_tex, was_color, was_mat;
1823 int is_norm, is_tex, is_color, is_mat;
1825 Assert (state->compiling_verts == 1, "missing glBegin");
1826 state->compiling_verts--;
1828 Assert (!state->replaying_list, "how did glEnd get into a display list?");
1830 if (!state->replaying_list)
1832 LOG5 ("%s [V = %d, N = %d, T = %d, C = %d]",
1833 (state->compiling_list || state->replaying_list ? " " : ""),
1834 s->count, s->ncount, s->tcount, s->ccount);
1836 (state->compiling_list || state->replaying_list ? " " : ""));
1839 if (s->count == 0) return;
1841 if (s->mode == GL_QUADS)
1842 convert_quads_to_triangles (s);
1843 else if (s->mode == GL_QUAD_STRIP)
1844 s->mode = GL_TRIANGLE_STRIP; /* They do the same thing! */
1845 else if (s->mode == GL_POLYGON)
1846 s->mode = GL_TRIANGLE_FAN; /* They do the same thing! */
1848 jwzgles_glColorPointer (4,GL_FLOAT, sizeof(*s->color),s->color); /* RGBA */
1849 jwzgles_glNormalPointer ( GL_FLOAT, sizeof(*s->norms),s->norms); /* XYZ */
1850 jwzgles_glTexCoordPointer(4,GL_FLOAT, sizeof(*s->tex), s->tex); /* STRQ */
1851 jwzgles_glVertexPointer (4,GL_FLOAT, sizeof(*s->verts),s->verts); /* XYZW */
1852 /* glVertexPointer must come after glTexCoordPointer */
1854 /* If there were no calls to glNormal3f inside of glBegin/glEnd,
1855 don't bother enabling the normals array.
1857 If there was exactly *one* call to glNormal3f inside of glBegin/glEnd,
1858 and it was before the first glVertex3f, then also don't enable the
1859 normals array, but do emit that call to glNormal3f before calling
1862 Likewise for texture coordinates and colors.
1864 Be careful to leave the arrays' enabled/disabled state the same as
1865 before, or a later caller might end up using one of our arrays by
1866 mistake. (Remember that jwzgles_glIsEnabled() tracks the enablement
1867 of the list-in-progress as well as the global state.)
1869 was_norm = jwzgles_glIsEnabled (GL_NORMAL_ARRAY);
1870 was_tex = jwzgles_glIsEnabled (GL_TEXTURE_COORD_ARRAY);
1871 was_color = jwzgles_glIsEnabled (GL_COLOR_ARRAY);
1872 was_mat = jwzgles_glIsEnabled (GL_COLOR_MATERIAL);
1874 /* If we're executing glEnd in immediate mode, not from inside a display
1875 list (which is the only way it happens, because glEnd doesn't go into
1876 display lists), make sure we're not stomping on a saved buffer list:
1877 in immediate mode, vertexes are client-side only.
1879 if (! state->compiling_list)
1880 jwzgles_glBindBuffer (GL_ARRAY_BUFFER, 0);
1885 jwzgles_glEnableClientState (GL_NORMAL_ARRAY);
1891 jwzgles_glNormal3f (s->cnorm.x, s->cnorm.y, s->cnorm.z);
1892 jwzgles_glDisableClientState (GL_NORMAL_ARRAY);
1895 if (s->tcount > 1 ||
1896 ((state->compiling_list ? state->list_enabled : state->enabled)
1897 & (ISENABLED_TEXTURE_GEN_S | ISENABLED_TEXTURE_GEN_T |
1898 ISENABLED_TEXTURE_GEN_R | ISENABLED_TEXTURE_GEN_Q)))
1900 /* Enable texture coords if any were specified; or if generation
1901 is on in immediate mode; or if this list turned on generation. */
1903 jwzgles_glEnableClientState (GL_TEXTURE_COORD_ARRAY);
1909 jwzgles_glTexCoord4f (s->ctex.s, s->ctex.t, s->ctex.r, s->ctex.q);
1910 jwzgles_glDisableClientState (GL_TEXTURE_COORD_ARRAY);
1916 jwzgles_glEnableClientState (GL_COLOR_ARRAY);
1922 jwzgles_glColor4f (s->ccolor.r, s->ccolor.g, s->ccolor.b, s->ccolor.a);
1923 jwzgles_glDisableClientState (GL_COLOR_ARRAY);
1926 jwzgles_glEnableClientState (GL_VERTEX_ARRAY);
1928 /* We translated the glMaterial calls to per-vertex colors, which are
1929 of the glColor sort, not the glMaterial sort, so automatically
1930 turn on material mapping. Maybe this is a bad idea.
1932 if (s->materialistic && !jwzgles_glIsEnabled (GL_COLOR_MATERIAL))
1935 jwzgles_glEnable (GL_COLOR_MATERIAL);
1940 glBindBuffer (GL_ARRAY_BUFFER, 0); /* This comes later. */
1941 jwzgles_glDrawArrays (s->mode, 0, s->count);
1942 glBindBuffer (GL_ARRAY_BUFFER, 0); /* Keep out of others' hands */
1944 # define RESET(VAR,FN,ARG) do { \
1945 if (is_##VAR != was_##VAR) { \
1946 if (was_##VAR) jwzgles_glEnable##FN (ARG); \
1947 else jwzgles_glDisable##FN (ARG); \
1949 RESET (norm, ClientState, GL_NORMAL_ARRAY);
1950 RESET (tex, ClientState, GL_TEXTURE_COORD_ARRAY);
1951 RESET (color, ClientState, GL_COLOR_ARRAY);
1952 RESET (mat, , GL_COLOR_MATERIAL);
1959 s->materialistic = 0;
1963 /* The display list is full of calls to glDrawArrays(), plus saved arrays
1964 of the values we need to restore before calling it. "Restore" means
1965 "ship them off to the GPU before each call".
1967 So instead, this function walks through the display list and
1968 combines all of those vertex, normal, texture and color values into
1969 a single VBO array; ships those values off to the GPU *once* at the
1970 time of glEndList; and when running the list with glCallList, the
1971 values are already on the GPU and don't need to be sent over again.
1973 The VBO persists in the GPU until the display list is deleted.
1976 optimize_arrays (void)
1978 list *L = &state->lists.lists[state->compiling_list-1];
1981 int combo_count = 0;
1983 GLuint buf_name = 0;
1985 Assert (state->compiling_list, "not compiling a list");
1986 Assert (L, "no list");
1987 Assert (!L->buffer, "list already has a buffer");
1989 glGenBuffers (1, &buf_name);
1990 CHECK("glGenBuffers");
1991 if (! buf_name) return;
1993 L->buffer = buf_name;
1995 /* Go through the list and dump the contents of the various saved arrays
1996 into one large array.
1998 for (i = 0; i < L->count; i++)
2000 list_fn *F = &L->fns[i];
2004 /* count = F->argv[2].i;*/ /* 3rd arg to glDrawArrays */
2006 for (j = 0; j < 4; j++)
2008 draw_array *A = &F->arrays[j];
2009 int ocount = combo_count;
2011 /* If some caller is using arrays that don't have floats in them,
2012 we just leave them as-is and ship them over at each call.
2013 Doubt this ever really happens.
2015 if (A->type != GL_FLOAT)
2018 if (! A->data) /* No array. */
2021 Assert (A->bytes > 0, "no bytes in draw_array");
2022 Assert (((unsigned long) A->data > 0xFFFF),
2023 "buffer data not a pointer");
2025 combo_count += A->bytes / sizeof(*combo);
2026 make_room ("optimize_arrays",
2027 (void **) &combo, sizeof(*combo),
2028 &combo_count, &combo_size);
2029 memcpy (combo + ocount, A->data, A->bytes);
2030 A->binding = buf_name;
2032 /* 'data' is now the byte offset into the VBO. */
2033 A->data = (void *) (ocount * sizeof(*combo));
2034 /* LOG3(" loaded %lu floats to pos %d of buffer %d",
2035 A->bytes / sizeof(*combo), ocount, buf_name); */
2039 if (combo_count == 0) /* Nothing to do! */
2041 if (combo) free (combo);
2042 glDeleteBuffers (1, &buf_name);
2047 glBindBuffer (GL_ARRAY_BUFFER, buf_name);
2048 glBufferData (GL_ARRAY_BUFFER,
2049 combo_count * sizeof (*combo),
2052 glBindBuffer (GL_ARRAY_BUFFER, 0); /* Keep out of others' hands */
2054 LOG3(" loaded %d floats of list %d into VBO %d",
2055 combo_count, state->compiling_list, buf_name);
2059 for (i = 0; i < combo_count; i++)
2062 fprintf (stderr, "\njwzgles: %4d: ", i);
2063 fprintf (stderr, " %7.3f", combo[i]);
2065 fprintf (stderr, "\n");
2069 if (combo) free (combo);
2074 jwzgles_glCallList (int id)
2076 if (state->compiling_list)
2078 /* Yes, you can call lists inside of lists.
2079 Yes, recursion would be a mistake. */
2082 list_push ("glCallList", (list_fn_cb) &jwzgles_glCallList, PROTO_I, vv);
2089 state->replaying_list++;
2092 fprintf (stderr, "\n");
2093 LOG1 ("glCallList %d", id);
2096 Assert (id > 0 && id <= state->lists.count, "glCallList: bogus ID");
2097 L = &state->lists.lists[id-1];
2098 Assert (id == L->id, "glCallList corrupted");
2100 for (i = 0; i < L->count; i++)
2102 list_fn *F = &L->fns[i];
2103 list_fn_cb fn = F->fn;
2104 void_int *av = F->argv;
2108 LOG1 (" call %-12s", F->name);
2109 ((void (*) (void)) fn) ();
2113 if (fn == (list_fn_cb) &jwzgles_glBegin ||
2114 fn == (list_fn_cb) &jwzgles_glFrontFace ||
2115 fn == (list_fn_cb) &jwzgles_glEnable ||
2116 fn == (list_fn_cb) &jwzgles_glDisable ||
2117 fn == (list_fn_cb) &jwzgles_glEnableClientState ||
2118 fn == (list_fn_cb) &jwzgles_glDisableClientState ||
2119 fn == (list_fn_cb) &jwzgles_glShadeModel ||
2120 fn == (list_fn_cb) &jwzgles_glMatrixMode)
2121 LOG2 (" call %-12s %s", F->name, mode_desc (av[0].i));
2123 LOG2 (" call %-12s %d", F->name, av[0].i);
2124 ((void (*) (int)) fn) (av[0].i);
2128 LOG2 (" call %-12s %7.3f", F->name, av[0].f);
2129 ((void (*) (GLfloat)) fn) (av[0].f);
2133 if (fn == (list_fn_cb) &jwzgles_glBindTexture ||
2134 fn == (list_fn_cb) &jwzgles_glBindBuffer)
2135 LOG3 (" call %-12s %s %d", F->name,
2136 mode_desc (av[0].i), av[1].i);
2138 LOG3 (" call %-12s %d %d", F->name, av[0].i, av[1].i);
2139 ((void (*) (int, int)) fn) (av[0].i, av[1].i);
2143 LOG3 (" call %-12s %7.3f %7.3f", F->name, av[0].f, av[1].f);
2144 ((void (*) (GLfloat, GLfloat)) fn) (av[0].f, av[1].f);
2148 LOG3 (" call %-12s %s %7.3f", F->name,
2149 mode_desc (av[0].f), av[1].f);
2150 ((void (*) (GLint, GLfloat)) fn) (av[0].i, av[1].f);
2153 case PROTO_III: III:
2154 if (fn == (list_fn_cb) &jwzgles_glDrawArrays ||
2155 fn == (list_fn_cb) &jwzgles_glTexParameteri)
2156 LOG4 (" call %-12s %s %d %d", F->name,
2157 mode_desc (av[0].i), av[1].i, av[2].i);
2159 LOG4 (" call %-12s %d %d %d", F->name,
2160 av[0].i, av[1].i, av[2].i);
2161 ((void (*) (int, int, int)) fn) (av[0].i, av[1].i, av[2].i);
2165 LOG4 (" call %-12s %7.3f %7.3f %7.3f", F->name,
2166 av[0].f, av[1].f, av[2].f);
2167 ((void (*) (GLfloat, GLfloat, GLfloat)) fn)
2168 (av[0].f, av[1].f, av[2].f);
2172 LOG4 (" call %-12s %s %s %7.3f", F->name,
2173 mode_desc (av[0].i), mode_desc (av[1].i), av[2].f);
2174 ((void (*) (int, int, GLfloat)) fn) (av[0].i, av[1].i, av[2].f);
2178 LOG5 (" call %-12s %d %d %d %d", F->name,
2179 av[0].i, av[1].i, av[2].i, av[3].i);
2180 ((void (*) (int, int, int, int)) fn)
2181 (av[0].i, av[1].i, av[2].i, av[3].i);
2185 LOG5 (" call %-12s %7.3f %7.3f %7.3f %7.3f", F->name,
2186 av[0].f, av[1].f, av[2].f, av[3].f);
2187 ((void (*) (GLfloat, GLfloat, GLfloat, GLfloat)) fn)
2188 (av[0].f, av[1].f, av[2].f, av[3].f);
2198 LOG6 (" call %-12s %s %3.1f %3.1f %3.1f %3.1f", F->name,
2199 mode_desc (av[0].i),
2200 av[1].f, av[2].f, av[3].f, av[4].f);
2201 ((void (*) (int, const GLfloat *)) fn) (av[0].i, v);
2212 LOG7 (" call %-12s %s %-8s %3.1f %3.1f %3.1f %3.1f", F->name,
2213 mode_desc (av[0].i), mode_desc (av[1].i),
2214 av[2].f, av[3].f, av[4].f, av[5].f);
2215 ((void (*) (int, int, const GLfloat *)) fn)
2216 (av[0].i, av[1].i, v);
2227 LOG6 (" call %-12s %s %3d %3d %3d %3d", F->name,
2228 mode_desc (av[0].i),
2229 av[1].i, av[2].i, av[3].i, av[4].i);
2230 ((void (*) (int, const int *)) fn) (av[0].i, v);
2241 LOG7 (" call %-12s %s %-8s %3d %3d %3d %3d", F->name,
2242 mode_desc (av[0].i), mode_desc (av[1].i),
2243 av[2].i, av[3].i, av[4].i, av[5].i);
2244 ((void (*) (int, int, const int *)) fn)
2245 (av[0].i, av[1].i, v);
2250 restore_arrays (F, av[1].i + av[2].i);
2258 for (i = 0; i < countof(m); i++)
2260 LOG17 (" call %-12s ["
2261 "%8.3f %8.3f %8.3f %8.3f " "\n\t\t\t "
2262 "%8.3f %8.3f %8.3f %8.3f " "\n\t\t\t "
2263 "%8.3f %8.3f %8.3f %8.3f " "\n\t\t\t "
2264 "%8.3f %8.3f %8.3f %8.3f ]",
2266 m[0], m[1], m[2], m[3],
2267 m[4], m[5], m[6], m[7],
2268 m[8], m[9], m[10], m[11],
2269 m[12], m[13], m[14], m[15]);
2270 ((void (*) (GLfloat *)) fn) (m);
2275 Assert (0, "bogus prototype");
2280 LOG1 ("glCallList %d done\n", id);
2282 state->replaying_list--;
2283 Assert (state->replaying_list >= 0, "glCallList corrupted");
2288 /* When we save a call to glDrawArrays into a display list, we also need to
2289 save the prevailing copy of the arrays that it will use, and restore them
2293 save_arrays (list_fn *F, int count)
2296 draw_array *A = (draw_array *) calloc (4, sizeof (*A));
2297 Assert (A, "out of memory");
2299 /* if (state->set.count > 0) */
2301 jwzgles_glGetIntegerv (GL_VERTEX_ARRAY_BUFFER_BINDING, &A[i].binding);
2302 jwzgles_glGetIntegerv (GL_VERTEX_ARRAY_SIZE, &A[i].size);
2303 jwzgles_glGetIntegerv (GL_VERTEX_ARRAY_TYPE, &A[i].type);
2304 jwzgles_glGetIntegerv (GL_VERTEX_ARRAY_STRIDE, &A[i].stride);
2305 jwzgles_glGetPointerv (GL_VERTEX_ARRAY_POINTER, &A[i].data);
2306 CHECK("glGetPointerv");
2307 copy_array_data (&A[i], count, "vert");
2311 if (state->set.ncount > 1)
2314 jwzgles_glGetIntegerv (GL_NORMAL_ARRAY_BUFFER_BINDING, &A[i].binding);
2315 jwzgles_glGetIntegerv (GL_NORMAL_ARRAY_TYPE, &A[i].type);
2316 jwzgles_glGetIntegerv (GL_NORMAL_ARRAY_STRIDE, &A[i].stride);
2317 jwzgles_glGetPointerv (GL_NORMAL_ARRAY_POINTER, &A[i].data);
2318 CHECK("glGetPointerv");
2319 copy_array_data (&A[i], count, "norm");
2323 if (state->set.tcount > 1)
2325 jwzgles_glGetIntegerv (GL_TEXTURE_COORD_ARRAY_BUFFER_BINDING, &A[i].binding);
2326 jwzgles_glGetIntegerv (GL_TEXTURE_COORD_ARRAY_SIZE, &A[i].size);
2327 jwzgles_glGetIntegerv (GL_TEXTURE_COORD_ARRAY_TYPE, &A[i].type);
2328 jwzgles_glGetIntegerv (GL_TEXTURE_COORD_ARRAY_STRIDE, &A[i].stride);
2329 jwzgles_glGetPointerv (GL_TEXTURE_COORD_ARRAY_POINTER, &A[i].data);
2330 CHECK("glGetPointerv");
2331 copy_array_data (&A[i], count, "tex ");
2335 if (state->set.ccount > 1)
2337 jwzgles_glGetIntegerv (GL_COLOR_ARRAY_BUFFER_BINDING, &A[i].binding);
2338 jwzgles_glGetIntegerv (GL_COLOR_ARRAY_SIZE, &A[i].size);
2339 jwzgles_glGetIntegerv (GL_COLOR_ARRAY_TYPE, &A[i].type);
2340 jwzgles_glGetIntegerv (GL_COLOR_ARRAY_STRIDE, &A[i].stride);
2341 jwzgles_glGetPointerv (GL_COLOR_ARRAY_POINTER, &A[i].data);
2342 CHECK("glGetPointerv");
2343 copy_array_data (&A[i], count, "col ");
2346 /* Freed by glDeleteLists. */
2348 Assert (!F->arrays, "save_arrays corrupted");
2356 dump_array_data (draw_array *A, int count,
2357 const char *action, const char *name, const void *old)
2359 int bytes = count * A->stride;
2364 "jwzgles: %s %s %d %s %2d, %4d = %5d bind %d @ %d\n",
2366 A->size, mode_desc(A->type), A->stride,
2367 count, bytes, A->binding, (int) A->data);
2371 Assert (bytes == A->bytes, "array data corrupted");
2373 fprintf (stderr, "jwzgles: %s %s %d %s %2d, %4d = %5d @ %lX",
2375 A->size, mode_desc(A->type), A->stride,
2376 count, bytes, (unsigned long) A->data);
2378 fprintf (stderr, " / %lX", (unsigned long) old);
2379 fprintf (stderr, "\n");
2384 Assert (((unsigned long) A->binding < 0xFFFF),
2385 "buffer binding should be a numeric index,"
2386 " but looks like a pointer");
2389 /* glGetBufferSubData doesn't actually exist in OpenGLES, but this
2390 was helpful for debugging on real OpenGL... */
2393 fprintf (stderr, "jwzgles: read back:\n");
2394 d = (GLfloat *) malloc (A->bytes);
2395 glGetBufferSubData (GL_ARRAY_BUFFER, (int) A->data,
2396 count * A->stride, (void *) d);
2397 CHECK("glGetBufferSubData");
2398 for (i = 0; i < count * A->size; i++)
2401 fprintf (stderr, "\njwzgles: %4d: ",
2402 i + (int) A->data / sizeof(GLfloat));
2403 fprintf (stderr, " %7.3f", d[i]);
2405 fprintf (stderr, "\n");
2412 unsigned char *b = (unsigned char *) A->data;
2414 if ((unsigned long) A->data < 0xFFFF)
2416 Assert (0, "buffer data not a pointer");
2419 for (i = 0; i < count; i++)
2422 GLfloat *f = (GLfloat *) b;
2424 if (s == 0) s = 3; /* normals */
2425 fprintf (stderr, "jwzgles: ");
2426 for (j = 0; j < s; j++)
2427 fprintf (stderr, " %7.3f", f[j]);
2428 fprintf (stderr, "\n");
2436 dump_direct_array_data (int count)
2438 draw_array A = { 0, };
2440 if (jwzgles_glIsEnabled (GL_VERTEX_ARRAY))
2442 jwzgles_glGetIntegerv (GL_VERTEX_ARRAY_BUFFER_BINDING, &A.binding);
2443 jwzgles_glGetIntegerv (GL_VERTEX_ARRAY_SIZE, &A.size);
2444 jwzgles_glGetIntegerv (GL_VERTEX_ARRAY_TYPE, &A.type);
2445 jwzgles_glGetIntegerv (GL_VERTEX_ARRAY_STRIDE, &A.stride);
2446 jwzgles_glGetPointerv (GL_VERTEX_ARRAY_POINTER, &A.data);
2447 A.bytes = count * A.stride;
2448 dump_array_data (&A, count, "direct", "vertex ", 0);
2450 if (jwzgles_glIsEnabled (GL_NORMAL_ARRAY))
2453 jwzgles_glGetIntegerv (GL_NORMAL_ARRAY_BUFFER_BINDING, &A.binding);
2454 jwzgles_glGetIntegerv (GL_NORMAL_ARRAY_TYPE, &A.type);
2455 jwzgles_glGetIntegerv (GL_NORMAL_ARRAY_STRIDE, &A.stride);
2456 jwzgles_glGetPointerv (GL_NORMAL_ARRAY_POINTER, &A.data);
2457 A.bytes = count * A.stride;
2458 dump_array_data (&A, count, "direct", "normal ", 0);
2460 if (jwzgles_glIsEnabled (GL_TEXTURE_COORD_ARRAY))
2462 jwzgles_glGetIntegerv (GL_TEXTURE_COORD_ARRAY_BUFFER_BINDING, &A.binding);
2463 jwzgles_glGetIntegerv (GL_TEXTURE_COORD_ARRAY_SIZE, &A.size);
2464 jwzgles_glGetIntegerv (GL_TEXTURE_COORD_ARRAY_TYPE, &A.type);
2465 jwzgles_glGetIntegerv (GL_TEXTURE_COORD_ARRAY_STRIDE, &A.stride);
2466 jwzgles_glGetPointerv (GL_TEXTURE_COORD_ARRAY_POINTER, &A.data);
2467 A.bytes = count * A.stride;
2468 dump_array_data (&A, count, "direct", "texture", 0);
2470 if (jwzgles_glIsEnabled (GL_COLOR_ARRAY))
2472 jwzgles_glGetIntegerv (GL_COLOR_ARRAY_BUFFER_BINDING, &A.binding);
2473 jwzgles_glGetIntegerv (GL_COLOR_ARRAY_SIZE, &A.size);
2474 jwzgles_glGetIntegerv (GL_COLOR_ARRAY_TYPE, &A.type);
2475 jwzgles_glGetIntegerv (GL_COLOR_ARRAY_STRIDE, &A.stride);
2476 jwzgles_glGetPointerv (GL_COLOR_ARRAY_POINTER, &A.data);
2477 A.bytes = count * A.stride;
2478 dump_array_data (&A, count, "direct", "color ", 0);
2486 copy_array_data (draw_array *A, int count, const char *name)
2488 /* Instead of just memcopy'ing the whole array and obeying its previous
2489 'stride' value, we make up a more compact array. This is because if
2490 the same array data is being used with multiple component types,
2491 e.g. with glInterleavedArrays, we don't want to copy all of the
2492 data multiple times.
2494 int stride2, bytes, i, j;
2498 const unsigned char *IB;
2501 if (((unsigned long) A->data) < 0xFFFF)
2503 Assert (0, "buffer data not a pointer");
2507 Assert (A->size >= 2 && A->size <= 4, "bogus array size");
2510 case GL_FLOAT: stride2 = A->size * sizeof(GLfloat); break;
2511 case GL_UNSIGNED_BYTE: stride2 = A->size; break;
2512 default: Assert (0, "bogus array type"); break;
2515 bytes = count * stride2;
2516 Assert (bytes > 0, "bogus array count or stride");
2517 Assert (A->data, "missing array data");
2518 data2 = (void *) malloc (bytes);
2519 Assert (data2, "out of memory");
2521 IB = (const unsigned char *) A->data;
2522 OB = (unsigned char *) data2;
2523 IF = (const GLfloat *) A->data;
2524 OF = (GLfloat *) data2;
2528 for (i = 0; i < count; i++)
2530 for (j = 0; j < A->size; j++)
2532 IF = (const GLfloat *) (((const unsigned char *) IF) + A->stride);
2535 case GL_UNSIGNED_BYTE:
2536 for (i = 0; i < count; i++)
2538 for (j = 0; j < A->size; j++)
2544 Assert (0, "bogus array type");
2550 A->stride = stride2;
2553 dump_array_data (A, count, "saved", name, 0);
2559 restore_arrays (list_fn *F, int count)
2562 draw_array *A = F->arrays;
2563 Assert (A, "missing array");
2565 for (i = 0; i < 4; i++)
2567 const char *name = 0;
2572 Assert ((A[i].binding || A[i].data),
2573 "array has neither buffer binding nor data");
2575 glBindBuffer (GL_ARRAY_BUFFER, A[i].binding);
2576 CHECK("glBindBuffer");
2579 case 0: jwzgles_glVertexPointer (A[i].size, A[i].type, A[i].stride, A[i].data);
2581 CHECK("glVertexPointer");
2583 case 1: jwzgles_glNormalPointer ( A[i].type, A[i].stride, A[i].data);
2585 CHECK("glNormalPointer");
2587 case 2: jwzgles_glTexCoordPointer(A[i].size, A[i].type, A[i].stride, A[i].data);
2589 CHECK("glTexCoordPointer");
2591 case 3: jwzgles_glColorPointer (A[i].size, A[i].type, A[i].stride, A[i].data);
2593 CHECK("glColorPointer");
2595 default: Assert (0, "wat"); break;
2599 dump_array_data (&A[i], count, "restored", name, 0);
2604 glBindBuffer (GL_ARRAY_BUFFER, 0); /* Keep out of others' hands */
2609 jwzgles_glDrawArrays (GLuint mode, GLuint first, GLuint count)
2611 /* If we are auto-generating texture coordinates, do that now, after
2612 the vertex array was installed, but before drawing, This happens
2613 when recording into a list, or in direct mode. It must happen
2614 before calling optimize_arrays() from glEndList().
2616 if (! state->replaying_list &&
2617 ((state->compiling_list ? state->list_enabled : state->enabled)
2618 & (ISENABLED_TEXTURE_GEN_S | ISENABLED_TEXTURE_GEN_T |
2619 ISENABLED_TEXTURE_GEN_R | ISENABLED_TEXTURE_GEN_Q)))
2620 generate_texture_coords (first, count);
2622 if (state->compiling_list)
2628 list_push ("glDrawArrays", (list_fn_cb) &jwzgles_glDrawArrays,
2634 if (! state->replaying_list) {
2635 LOG4("direct %-12s %d %d %d", "glDrawArrays", mode, first, count);
2636 dump_direct_array_data (first + count);
2639 glDrawArrays (mode, first, count); /* the real one */
2640 CHECK("glDrawArrays");
2646 jwzgles_glInterleavedArrays (GLenum format, GLsizei stride, const void *data)
2648 /* We can implement this by calling the various *Pointer functions
2649 with offsets into the same data, taking advantage of stride.
2651 const unsigned char *c = (const unsigned char *) data;
2653 # define F sizeof(GLfloat)
2655 Assert (!state->compiling_verts,
2656 "glInterleavedArrays not allowed inside glBegin");
2658 jwzgles_glEnableClientState (GL_VERTEX_ARRAY);
2660 if (!state->replaying_list)
2661 LOG4 ("%sglInterleavedArrays %s %d %lX",
2662 (state->compiling_list || state->replaying_list ? " " : ""),
2663 mode_desc (format), stride, (unsigned long) data);
2667 jwzgles_glVertexPointer (2, GL_FLOAT, stride, c);
2668 CHECK("glVertexPointer");
2669 if (!state->replaying_list)
2670 LOG3 ("%s -> glVertexPointer 2 FLOAT %d %lX",
2671 (state->compiling_list || state->replaying_list ? " " : ""),
2672 stride, (unsigned long) c);
2675 jwzgles_glVertexPointer (3, GL_FLOAT, stride, c);
2676 CHECK("glVertexPointer");
2677 if (!state->replaying_list)
2678 LOG3 ("%s -> glVertexPointer 3 FLOAT %d %lX",
2679 (state->compiling_list || state->replaying_list ? " " : ""),
2680 stride, (unsigned long) c);
2685 jwzgles_glEnableClientState (GL_COLOR_ARRAY);
2686 jwzgles_glColorPointer (4, GL_UNSIGNED_BYTE, stride, c);
2687 CHECK("glColorPointer");
2688 c += 4*B; /* #### might be incorrect float-aligned address */
2689 jwzgles_glVertexPointer (2, GL_FLOAT, stride, c);
2694 jwzgles_glEnableClientState (GL_COLOR_ARRAY);
2695 jwzgles_glColorPointer (4, GL_UNSIGNED_BYTE, stride, c);
2696 CHECK("glColorPointer");
2698 jwzgles_glVertexPointer (3, GL_FLOAT, stride, c);
2699 CHECK("glVertexPointer");
2704 jwzgles_glEnableClientState (GL_COLOR_ARRAY);
2705 jwzgles_glColorPointer (3, GL_FLOAT, stride, c);
2706 CHECK("glColorPointer");
2708 jwzgles_glVertexPointer (3, GL_FLOAT, stride, c);
2709 CHECK("glVertexPointer");
2714 jwzgles_glEnableClientState (GL_NORMAL_ARRAY);
2715 jwzgles_glNormalPointer (GL_FLOAT, stride, c);
2716 CHECK("glNormalPointer");
2717 if (!state->replaying_list)
2718 LOG3 ("%s -> glNormalPointer FLOAT %d %lX",
2719 (state->compiling_list || state->replaying_list ? " " : ""),
2720 stride, (unsigned long) c);
2722 jwzgles_glVertexPointer (3, GL_FLOAT, stride, c);
2723 CHECK("glVertexPointer");
2724 if (!state->replaying_list)
2725 LOG3 ("%s -> glVertexPointer 3 FLOAT %d %lX",
2726 (state->compiling_list || state->replaying_list ? " " : ""),
2727 stride, (unsigned long) c);
2729 case GL_C4F_N3F_V3F:
2731 stride = 4*F + 3*F + 3*F;
2732 jwzgles_glEnableClientState (GL_COLOR_ARRAY);
2733 jwzgles_glColorPointer (4, GL_FLOAT, stride, c);
2734 CHECK("glColorPointer");
2736 jwzgles_glEnableClientState (GL_NORMAL_ARRAY);
2737 jwzgles_glNormalPointer (GL_FLOAT, stride, c);
2738 CHECK("glNormalPointer");
2740 jwzgles_glVertexPointer (3, GL_FLOAT, stride, c);
2741 CHECK("glVertexPointer");
2746 jwzgles_glEnableClientState (GL_TEXTURE_COORD_ARRAY);
2747 jwzgles_glTexCoordPointer (2, GL_FLOAT, stride, c);
2748 CHECK("glTexCoordPointer");
2750 jwzgles_glVertexPointer (3, GL_FLOAT, stride, c);
2751 CHECK("glVertexPointer");
2756 jwzgles_glEnableClientState (GL_TEXTURE_COORD_ARRAY);
2757 jwzgles_glTexCoordPointer (4, GL_FLOAT, stride, c);
2758 CHECK("glTexCoordPointer");
2760 jwzgles_glVertexPointer (4, GL_FLOAT, stride, c);
2761 CHECK("glVertexPointer");
2763 case GL_T2F_C4UB_V3F:
2765 stride = 2*F + 4*B + 3*F;
2766 jwzgles_glEnableClientState (GL_TEXTURE_COORD_ARRAY);
2767 jwzgles_glTexCoordPointer (2, GL_FLOAT, stride, c);
2768 CHECK("glTexCoordPointer");
2770 jwzgles_glEnableClientState (GL_COLOR_ARRAY);
2771 jwzgles_glColorPointer (4, GL_UNSIGNED_BYTE, stride, c);
2772 CHECK("glColorPointer");
2774 jwzgles_glVertexPointer (3, GL_FLOAT, stride, c);
2775 CHECK("glVertexPointer");
2777 case GL_T2F_C3F_V3F:
2779 stride = 2*F + 3*F + 3*F;
2780 jwzgles_glEnableClientState (GL_TEXTURE_COORD_ARRAY);
2781 jwzgles_glTexCoordPointer (2, GL_FLOAT, stride, c);
2782 CHECK("glTexCoordPointer");
2784 jwzgles_glEnableClientState (GL_COLOR_ARRAY);
2785 jwzgles_glColorPointer (3, GL_FLOAT, stride, c);
2786 CHECK("glColorPointer");
2788 jwzgles_glVertexPointer (3, GL_FLOAT, stride, c);
2789 CHECK("glVertexPointer");
2791 case GL_T2F_N3F_V3F:
2793 stride = 2*F + 3*F + 3*F;
2794 jwzgles_glEnableClientState (GL_TEXTURE_COORD_ARRAY);
2795 jwzgles_glTexCoordPointer (2, GL_FLOAT, stride, c);
2796 CHECK("glTexCoordPointer");
2798 jwzgles_glEnableClientState (GL_NORMAL_ARRAY);
2799 jwzgles_glNormalPointer (GL_FLOAT, stride, c);
2800 CHECK("glNormalPointer");
2802 jwzgles_glVertexPointer (3, GL_FLOAT, stride, c);
2803 CHECK("glVertexPointer");
2805 case GL_T2F_C4F_N3F_V3F:
2807 stride = 2*F + 4*F + 3*F + 3*F;
2808 jwzgles_glEnableClientState (GL_TEXTURE_COORD_ARRAY);
2809 jwzgles_glTexCoordPointer (2, GL_FLOAT, stride, c);
2810 CHECK("glTexCoordPointer");
2812 jwzgles_glEnableClientState (GL_COLOR_ARRAY);
2813 jwzgles_glColorPointer (3, GL_FLOAT, stride, c);
2814 CHECK("glColorPointer");
2816 jwzgles_glEnableClientState (GL_NORMAL_ARRAY);
2817 jwzgles_glNormalPointer (GL_FLOAT, stride, c);
2818 CHECK("glNormalPointer");
2820 jwzgles_glVertexPointer (3, GL_FLOAT, stride, c);
2821 CHECK("glVertexPointer");
2823 case GL_T4F_C4F_N3F_V4F:
2825 stride = 4*F + 4*F + 3*F + 4*F;
2826 jwzgles_glEnableClientState (GL_TEXTURE_COORD_ARRAY);
2827 jwzgles_glTexCoordPointer (4, GL_FLOAT, stride, c);
2828 CHECK("glTexCoordPointer");
2830 jwzgles_glEnableClientState (GL_COLOR_ARRAY);
2831 jwzgles_glColorPointer (4, GL_FLOAT, stride, c);
2832 CHECK("glColorPointer");
2834 jwzgles_glEnableClientState (GL_NORMAL_ARRAY);
2835 jwzgles_glNormalPointer (GL_FLOAT, stride, c);
2836 CHECK("glNormalPointer");
2838 jwzgles_glVertexPointer (3, GL_FLOAT, stride, c);
2839 CHECK("glVertexPointer");
2842 Assert (0, "glInterleavedArrays: bogus format");
2853 jwzgles_glMultMatrixf (const GLfloat *m)
2855 Assert (!state->compiling_verts,
2856 "glMultMatrixf not allowed inside glBegin");
2857 if (state->compiling_list)
2861 for (i = 0; i < countof(vv); i++)
2863 list_push ("glMultMatrixf", (list_fn_cb) &jwzgles_glMultMatrixf,
2868 if (! state->replaying_list)
2869 LOG1 ("direct %-12s", "glMultMatrixf");
2870 glMultMatrixf (m); /* the real one */
2871 CHECK("glMultMatrixf");
2877 jwzgles_glClearIndex(GLfloat c)
2879 /* Does GLES even do indexed color? */
2880 Assert (0, "glClearIndex unimplemented");
2885 jwzgles_glBitmap (GLsizei width, GLsizei height, GLfloat xorig, GLfloat yorig,
2886 GLfloat xmove, GLfloat ymove, const GLubyte *bitmap)
2888 Assert (0, "glBitmap unimplemented");
2892 jwzgles_glPushAttrib(int flags)
2894 Assert (0, "glPushAttrib unimplemented");
2898 jwzgles_glPopAttrib(void)
2900 Assert (0, "glPopAttrib unimplemented");
2904 /* These are needed for object hit detection in pinion.
2905 Might need to rewrite that code entirely. Punt for now.
2908 jwzgles_glInitNames (void)
2910 /* Assert (0, "glInitNames unimplemented");*/
2914 jwzgles_glPushName (GLuint name)
2916 /* Assert (0, "glPushName unimplemented");*/
2920 jwzgles_glPopName (void)
2922 /* Assert (0, "glPopName unimplemented");*/
2927 jwzgles_glRenderMode (GLuint mode)
2929 /* Assert (0, "glRenderMode unimplemented");*/
2934 jwzgles_glSelectBuffer (GLsizei size, GLuint *buf)
2936 /* Assert (0, "glSelectBuffer unimplemented");*/
2941 jwzgles_glGenTextures (GLuint n, GLuint *ret)
2943 Assert (!state->compiling_verts,
2944 "glGenTextures not allowed inside glBegin");
2945 /* technically legal, but stupid! */
2946 Assert (!state->compiling_list,
2947 "glGenTextures not allowed inside glNewList");
2948 if (! state->replaying_list)
2949 LOG1 ("direct %-12s", "glGenTextures");
2950 glGenTextures (n, ret); /* the real one */
2951 CHECK("glGenTextures");
2955 /* return the next larger power of 2. */
2960 while (i < value) i <<= 1;
2965 jwzgles_glTexImage1D (GLenum target, GLint level,
2966 GLint internalFormat,
2967 GLsizei width, GLint border,
2968 GLenum format, GLenum type,
2971 Assert (!state->compiling_verts, "glTexImage1D not allowed inside glBegin");
2972 /* technically legal, but stupid! */
2973 Assert (!state->compiling_list, "glTexImage1D inside glNewList");
2974 Assert (width == to_pow2(width), "width must be a power of 2");
2976 if (target == GL_TEXTURE_1D) target = GL_TEXTURE_2D;
2977 jwzgles_glTexImage2D (target, level, internalFormat, width, 1,
2978 border, format, type, data);
2982 jwzgles_glTexImage2D (GLenum target,
2984 GLint internalFormat,
2992 GLvoid *d2 = (GLvoid *) data;
2993 Assert (!state->compiling_verts, "glTexImage2D not allowed inside glBegin");
2994 Assert (!state->compiling_list, /* technically legal, but stupid! */
2995 "glTexImage2D not allowed inside glNewList");
2997 Assert (width == to_pow2(width), "width must be a power of 2");
2998 Assert (height == to_pow2(height), "height must be a power of 2");
3000 /* OpenGLES no longer supports "4" as a synonym for "RGBA". */
3001 switch (internalFormat) {
3002 case 1: internalFormat = GL_LUMINANCE; break;
3003 case 2: internalFormat = GL_LUMINANCE_ALPHA; break;
3004 case 3: internalFormat = GL_RGB; break;
3005 case 4: internalFormat = GL_RGBA; break;
3008 /* GLES does not let us omit the data pointer to create a blank texture. */
3011 d2 = (GLvoid *) calloc (1, width * height * sizeof(GLfloat) * 4);
3012 Assert (d2, "out of memory");
3015 if (internalFormat == GL_RGB && format == GL_RGBA)
3016 internalFormat = GL_RGBA; /* WTF */
3017 if (type == GL_UNSIGNED_INT_8_8_8_8_REV)
3018 type = GL_UNSIGNED_BYTE;
3020 if (! state->replaying_list)
3021 LOG10 ("direct %-12s %s %d %s %d %d %d %s %s 0x%lX", "glTexImage2D",
3022 mode_desc(target), level, mode_desc(internalFormat),
3023 width, height, border, mode_desc(format), mode_desc(type),
3024 (unsigned long) d2);
3025 glTexImage2D (target, level, internalFormat, width, height, border,
3026 format, type, d2); /* the real one */
3027 CHECK("glTexImage2D");
3029 if (d2 != data) free (d2);
3033 jwzgles_glTexSubImage2D (GLenum target, GLint level,
3034 GLint xoffset, GLint yoffset,
3035 GLsizei width, GLsizei height,
3036 GLenum format, GLenum type,
3037 const GLvoid *pixels)
3039 Assert (!state->compiling_verts,
3040 "glTexSubImage2D not allowed inside glBegin");
3041 Assert (!state->compiling_list, /* technically legal, but stupid! */
3042 "glTexSubImage2D not allowed inside glNewList");
3044 if (! state->replaying_list)
3045 LOG10 ("direct %-12s %s %d %d %d %d %d %s %s 0x%lX", "glTexSubImage2D",
3046 mode_desc(target), level, xoffset, yoffset, width, height,
3047 mode_desc (format), mode_desc (type), (unsigned long) pixels);
3048 glTexSubImage2D (target, level, xoffset, yoffset, width, height,
3049 format, type, pixels); /* the real one */
3050 CHECK("glTexSubImage2D");
3054 jwzgles_glCopyTexImage2D (GLenum target, GLint level, GLenum internalformat,
3055 GLint x, GLint y, GLsizei width, GLsizei height,
3058 Assert (!state->compiling_verts,
3059 "glCopyTexImage2D not allowed inside glBegin");
3060 Assert (!state->compiling_list, /* technically legal, but stupid! */
3061 "glCopyTexImage2D not allowed inside glNewList");
3062 if (! state->replaying_list)
3063 LOG9 ("direct %-12s %s %d %s %d %d %d %d %d", "glCopyTexImage2D",
3064 mode_desc(target), level, mode_desc(internalformat),
3065 x, y, width, height, border);
3066 glCopyTexImage2D (target, level, internalformat, x, y, width, height,
3067 border); /* the real one */
3068 CHECK("glCopyTexImage2D");
3072 /* OpenGLES doesn't have auto texture-generation at all!
3073 "Oh, just rewrite that code to use GPU shaders", they say.
3074 How fucking convenient.
3077 jwzgles_glTexGenfv (GLenum coord, GLenum pname, const GLfloat *params)
3081 if (pname == GL_TEXTURE_GEN_MODE)
3082 LOG5 ("%sdirect %-12s %s %s %s",
3083 (state->compiling_list || state->replaying_list ? " " : ""),
3085 mode_desc(coord), mode_desc(pname), mode_desc(params[0]));
3087 LOG8 ("%sdirect %-12s %s %s %3.1f %3.1f %3.1f %3.1f",
3088 (state->compiling_list || state->replaying_list ? " " : ""),
3090 mode_desc(coord), mode_desc(pname),
3091 params[0], params[1], params[2], params[3]);
3094 case GL_S: s = &state->s; break;
3095 case GL_T: s = &state->t; break;
3096 case GL_R: s = &state->r; break;
3097 case GL_Q: s = &state->q; break;
3098 default: Assert (0, "glGetTexGenfv: unknown coord"); break;
3102 case GL_TEXTURE_GEN_MODE: s->mode = params[0]; break;
3103 case GL_OBJECT_PLANE: memcpy (s->obj, params, sizeof(s->obj)); break;
3104 case GL_EYE_PLANE: memcpy (s->eye, params, sizeof(s->eye)); break;
3105 default: Assert (0, "glTexGenfv: unknown pname"); break;
3110 jwzgles_glTexGeni (GLenum coord, GLenum pname, GLint param)
3113 jwzgles_glTexGenfv (coord, pname, &v);
3117 jwzgles_glGetTexGenfv (GLenum coord, GLenum pname, GLfloat *params)
3122 case GL_S: s = &state->s; break;
3123 case GL_T: s = &state->t; break;
3124 case GL_R: s = &state->r; break;
3125 case GL_Q: s = &state->q; break;
3126 default: Assert (0, "glGetTexGenfv: unknown coord"); break;
3130 case GL_TEXTURE_GEN_MODE: params[0] = s->mode; break;
3131 case GL_OBJECT_PLANE: memcpy (params, s->obj, sizeof(s->obj)); break;
3132 case GL_EYE_PLANE: memcpy (params, s->eye, sizeof(s->eye)); break;
3133 default: Assert (0, "glGetTexGenfv: unknown pname"); break;
3136 if (pname == GL_TEXTURE_GEN_MODE)
3137 LOG5 ("%sdirect %-12s %s %s -> %s",
3138 (state->compiling_list || state->replaying_list ? " " : ""),
3140 mode_desc(coord), mode_desc(pname), mode_desc(params[0]));
3142 LOG8 ("%sdirect %-12s %s %s -> %3.1f %3.1f %3.1f %3.1f",
3143 (state->compiling_list || state->replaying_list ? " " : ""),
3145 mode_desc(coord), mode_desc(pname),
3146 params[0], params[1], params[2], params[3]);
3151 dot_product (int rank, GLfloat *a, GLfloat *b)
3153 /* A dot B => (A[1] * B[1]) + ... + (A[n] * B[n]) */
3156 for (i = 0; i < rank; i++)
3163 /* Compute the texture coordinates of the prevailing list of verts as per
3164 http://www.opengl.org/wiki/Mathematics_of_glTexGen
3167 generate_texture_coords (GLuint first, GLuint count)
3169 GLfloat *tex_out, *tex_array;
3172 draw_array A = { 0, };
3175 struct { GLuint which, flag, mode; GLfloat plane[4]; } tg[4] = {
3176 { GL_S, ISENABLED_TEXTURE_GEN_S, 0, { 0, } },
3177 { GL_T, ISENABLED_TEXTURE_GEN_T, 0, { 0, } },
3178 { GL_R, ISENABLED_TEXTURE_GEN_R, 0, { 0, } },
3179 { GL_Q, ISENABLED_TEXTURE_GEN_Q, 0, { 0, }}};
3183 /* Read the texture plane configs that were stored with glTexGen.
3185 for (i = 0; i < countof(tg); i++)
3188 if (! ((state->compiling_list ? state->list_enabled : state->enabled)
3191 jwzgles_glGetTexGenfv (tg[i].which, GL_TEXTURE_GEN_MODE, &mode);
3192 jwzgles_glGetTexGenfv (tg[i].which, GL_OBJECT_PLANE, tg[i].plane);
3197 if (tcoords == 0) return; /* Nothing to do! */
3200 /* Make the array to store our texture coords in. */
3202 tex_stride = tcoords * sizeof(GLfloat);
3203 tex_array = (GLfloat *) calloc (first + count, tex_stride);
3204 tex_out = tex_array;
3207 /* Read the prevailing vertex array, that was stored with
3208 glVertexPointer or glInterleavedArrays.
3210 jwzgles_glGetIntegerv (GL_VERTEX_ARRAY_BUFFER_BINDING, &A.binding);
3211 jwzgles_glGetIntegerv (GL_VERTEX_ARRAY_SIZE, &A.size);
3212 jwzgles_glGetIntegerv (GL_VERTEX_ARRAY_TYPE, &A.type);
3213 jwzgles_glGetIntegerv (GL_VERTEX_ARRAY_STRIDE, &A.stride);
3214 jwzgles_glGetPointerv (GL_VERTEX_ARRAY_POINTER, &A.data);
3215 A.bytes = count * A.stride;
3217 verts_in = (char *) A.data;
3219 /* Iterate over each vertex we're drawing.
3220 We just skip the ones < start, but the tex array has
3221 left room for zeroes there anyway.
3223 for (i = first; i < first + count; i++)
3225 GLfloat vert[4] = { 0, };
3228 /* Extract this vertex into `vert' as a float, whatever its type was. */
3229 for (j = 0; j < A.size; j++)
3232 case GL_SHORT: vert[j] = ((GLshort *) verts_in)[j]; break;
3233 case GL_INT: vert[j] = ((GLint *) verts_in)[j]; break;
3234 case GL_FLOAT: vert[j] = ((GLfloat *) verts_in)[j]; break;
3235 case GL_DOUBLE: vert[j] = ((GLdouble *) verts_in)[j]; break;
3236 default: Assert (0, "unknown vertex type"); break;
3240 /* Compute the texture coordinate for this vertex.
3241 For GL_OBJECT_LINEAR, these coordinates are static, and can go
3242 into the display list. But for GL_EYE_LINEAR, GL_SPHERE_MAP and
3243 GL_REFLECTION_MAP, they depend on the prevailing ModelView matrix,
3244 and so need to be computed afresh each time glDrawArrays is called.
3245 Unfortunately, our verts and norms are gone by then, dumped down
3246 into the VBO and discarded from CPU RAM. Bleh.
3248 for (j = 0, k = 0; j < countof(tg); j++)
3250 if (! ((state->compiling_list ? state->list_enabled : state->enabled)
3253 switch (tg[j].mode) {
3254 case GL_OBJECT_LINEAR:
3255 tex_out[k] = dot_product (4, vert, tg[j].plane);
3258 Assert (0, "unimplemented texture mode");
3264 /* fprintf (stderr, "%4d: V %-5.1f %-5.1f %-5.1f T %-5.1f %-5.1f\n",
3265 i, vert[0], vert[1], vert[2], tex_out[0], tex_out[1]); */
3267 /* Move verts_in and tex_out forward to the next vertex by stride. */
3268 verts_in += A.stride;
3269 tex_out = (GLfloat *) (((char *) tex_out) + tex_stride);
3272 jwzgles_glEnableClientState (GL_TEXTURE_COORD_ARRAY);
3273 jwzgles_glTexCoordPointer (tcoords, GL_FLOAT, tex_stride,
3274 (GLvoid *) tex_array);
3280 jwzgles_gluBuild2DMipmaps (GLenum target,
3281 GLint internalFormat,
3288 /* Not really bothering with mipmapping; only making one level.
3289 Note that this required a corresponding hack in glTexParameterf().
3292 int w2 = to_pow2(width);
3293 int h2 = to_pow2(height);
3295 void *d2 = (void *) data;
3297 /* OpenGLES no longer supports "4" as a synonym for "RGBA". */
3298 switch (internalFormat) {
3299 case 1: internalFormat = GL_LUMINANCE; break;
3300 case 2: internalFormat = GL_LUMINANCE_ALPHA; break;
3301 case 3: internalFormat = GL_RGB; break;
3302 case 4: internalFormat = GL_RGBA; break;
3305 /* if (w2 < h2) w2 = h2;
3306 if (h2 < w2) h2 = w2;*/
3308 if (w2 != width || h2 != height)
3310 /* Scale up the image bits to fit the power-of-2 texture.
3311 We have to do this because the mipmap API assumes that
3312 the texture bits go to texture coordinates 1.0 x 1.0.
3313 This could be more efficient, but it doesn't happen often.
3315 int istride = (format == GL_RGBA ? 4 : 3);
3317 int ibpl = istride * width;
3318 int obpl = ostride * w2;
3320 const unsigned char *in = (unsigned char *) data;
3321 unsigned char *out = (void *) malloc (h2 * obpl);
3322 Assert (out, "out of memory");
3325 for (oy = 0; oy < h2; oy++)
3327 int iy = oy * height / h2;
3328 const unsigned char *iline = in + (iy * ibpl);
3329 unsigned char *oline = out + (oy * obpl);
3331 for (ox = 0; ox < w2; ox++)
3333 int ix = ox * width / w2;
3334 const unsigned char *i = iline + (ix * istride);
3335 unsigned char *o = oline + (ox * ostride);
3336 *o++ = *i++; /* R */
3337 *o++ = *i++; /* G */
3338 *o++ = *i++; /* B */
3339 *o++ = (istride == 4 ? *i : 0xFF); /* A */
3344 internalFormat = GL_RGBA;
3348 jwzgles_glTexImage2D (target, 0, internalFormat, w2, h2, 0,
3350 if (d2 != data) free (d2);
3357 jwzgles_glRectf (GLfloat x1, GLfloat y1, GLfloat x2, GLfloat y2)
3359 jwzgles_glBegin (GL_POLYGON);
3360 jwzgles_glVertex2f (x1, y1);
3361 jwzgles_glVertex2f (x2, y1);
3362 jwzgles_glVertex2f (x2, y2);
3363 jwzgles_glVertex2f (x1, y2);
3368 jwzgles_glRecti (GLint x1, GLint y1, GLint x2, GLint y2)
3370 jwzgles_glRectf (x1, y1, x2, y2);
3374 jwzgles_glClearDepth (GLfloat d)
3376 /* Not sure what to do here */
3377 Assert (d == 1.0, "glClearDepth unimplemented");
3381 /* When in immediate mode, we store a bit into state->enabled, and also
3382 call the real glEnable() / glDisable().
3384 When recording a list, we store a bit into state->list_enabled instead,
3385 so that we can see what the prevailing enablement state will be when
3388 set: 1 = set, -1 = clear, 0 = query.
3391 enable_disable (GLuint bit, int set)
3393 int result = (set > 0);
3396 unsigned long flag = 0;
3399 case GL_TEXTURE_1D: /* We implement 1D textures as 2D textures. */
3400 case GL_TEXTURE_2D: flag = ISENABLED_TEXTURE_2D; break;
3401 case GL_TEXTURE_GEN_S: flag = ISENABLED_TEXTURE_GEN_S; omitp = 1; break;
3402 case GL_TEXTURE_GEN_T: flag = ISENABLED_TEXTURE_GEN_T; omitp = 1; break;
3403 case GL_TEXTURE_GEN_R: flag = ISENABLED_TEXTURE_GEN_R; omitp = 1; break;
3404 case GL_TEXTURE_GEN_Q: flag = ISENABLED_TEXTURE_GEN_Q; omitp = 1; break;
3405 case GL_LIGHTING: flag = ISENABLED_LIGHTING; break;
3406 case GL_BLEND: flag = ISENABLED_BLEND; break;
3407 case GL_DEPTH_TEST: flag = ISENABLED_DEPTH_TEST; break;
3408 case GL_ALPHA_TEST: flag = ISENABLED_ALPHA_TEST; break;
3409 case GL_CULL_FACE: flag = ISENABLED_CULL_FACE; break;
3410 case GL_NORMALIZE: flag = ISENABLED_NORMALIZE; break;
3411 case GL_FOG: flag = ISENABLED_FOG; break;
3412 case GL_COLOR_MATERIAL: flag = ISENABLED_COLMAT; break;
3414 /* Maybe technically these only work with glEnableClientState,
3415 but we treat that as synonymous with glEnable. */
3416 case GL_VERTEX_ARRAY: flag = ISENABLED_VERT_ARRAY; csp = 1; break;
3417 case GL_NORMAL_ARRAY: flag = ISENABLED_NORM_ARRAY; csp = 1; break;
3418 case GL_COLOR_ARRAY: flag = ISENABLED_COLOR_ARRAY; csp = 1; break;
3419 case GL_TEXTURE_COORD_ARRAY: flag = ISENABLED_TEX_ARRAY; csp = 1; break;
3422 Assert (set != 0, "glIsEnabled unimplemented bit");
3426 if (set) /* setting or unsetting, not querying */
3428 const char *fns[4] = { "glEnable", "glDisable",
3429 "glEnableClientState", "glDisableClientState" };
3430 list_fn_cb fs[4] = { (list_fn_cb) &jwzgles_glEnable,
3431 (list_fn_cb) &jwzgles_glDisable,
3432 (list_fn_cb) &jwzgles_glEnableClientState,
3433 (list_fn_cb) &jwzgles_glDisableClientState };
3434 const char *fn = fns[(csp ? 2 : 0) + (set < 0 ? 1 : 0)];
3435 list_fn_cb f = fs[(csp ? 2 : 0) + (set < 0 ? 1 : 0)];
3437 Assert (!state->compiling_verts,
3438 "glEnable/glDisable not allowed inside glBegin");
3440 if (state->compiling_list)
3444 list_push (fn, f,PROTO_I, vv);
3447 if (! state->replaying_list &&
3448 ! state->compiling_list)
3449 LOG2 ("direct %-12s %s", fn, mode_desc(bit));
3451 if (csp && !state->compiling_verts)
3455 case GL_NORMAL_ARRAY: state->set.ncount += 2; break;
3456 case GL_TEXTURE_COORD_ARRAY: state->set.tcount += 2; break;
3457 case GL_COLOR_ARRAY: state->set.ccount += 2; break;
3462 case GL_NORMAL_ARRAY: state->set.ncount = 0; break;
3463 case GL_TEXTURE_COORD_ARRAY: state->set.tcount = 0; break;
3464 case GL_COLOR_ARRAY: state->set.ccount = 0; break;
3469 if (omitp || state->compiling_list)
3471 else if (set > 0 && csp)
3472 glEnableClientState (bit); /* the real one */
3473 else if (set < 0 && csp)
3474 glDisableClientState (bit); /* the real one */
3476 glEnable (bit); /* the real one */
3478 glDisable (bit); /* the real one */
3483 /* Store the bit in our state as well, or query it.
3487 unsigned long *enabled = (state->compiling_list
3488 ? &state->list_enabled
3495 result = !!(*enabled & flag);
3503 jwzgles_glEnable (GLuint bit)
3505 enable_disable (bit, 1);
3509 jwzgles_glDisable (GLuint bit)
3511 enable_disable (bit, -1);
3515 jwzgles_glIsEnabled (GLuint bit)
3517 return enable_disable (bit, 0);
3521 jwzgles_glEnableClientState (GLuint cap)
3523 enable_disable (cap, 1);
3527 jwzgles_glDisableClientState (GLuint cap)
3529 enable_disable (cap, -1);
3533 #define GET(pname, value) \
3538 /* The spec says that OpenGLES 1.0 doesn't implement glGetFloatv.
3540 iOS provides 1.1 (and glGetFloatv by extension) at the very minimum.
3542 Android goes down to 1.0. In particular, this includes the emulator when
3543 running without GPU emulation. Actual devices that don't support 1.1 are
3544 extremely rare at this point.
3546 OpenGL ES 1.0 sucks because without glGetFloatv there is no way to retrieve
3547 the prevailing matrixes. To implement this, we'd have to keep track of
3548 them all on the client side by combining in all the actions of
3549 glMultMatrixf, glRotatef, etc. Right now, we're only keeping track of the
3550 gl*Pointer functions.
3553 jwzgles_glGetFloatv (GLenum pname, GLfloat *params)
3555 if (! state->replaying_list)
3556 LOG2 ("direct %-12s %s", "glGetFloatv", mode_desc(pname));
3560 /* OpenGL ES 1.0 omits a few dozen properties that 1.1 supports. The
3561 following, however, is sufficient to get things basically working in the
3565 GET(GL_VERTEX_ARRAY_BUFFER_BINDING, state->varray.binding)
3566 GET(GL_VERTEX_ARRAY_SIZE, state->varray.size)
3567 GET(GL_VERTEX_ARRAY_TYPE, state->varray.type)
3568 GET(GL_VERTEX_ARRAY_STRIDE, state->varray.stride)
3570 GET(GL_NORMAL_ARRAY_BUFFER_BINDING, state->narray.binding)
3571 GET(GL_NORMAL_ARRAY_TYPE, state->narray.type)
3572 GET(GL_NORMAL_ARRAY_STRIDE, state->narray.stride)
3574 GET(GL_COLOR_ARRAY_BUFFER_BINDING, state->carray.binding)
3575 GET(GL_COLOR_ARRAY_SIZE, state->carray.size)
3576 GET(GL_COLOR_ARRAY_TYPE, state->carray.type)
3577 GET(GL_COLOR_ARRAY_STRIDE, state->carray.stride)
3579 GET(GL_TEXTURE_COORD_ARRAY_BUFFER_BINDING, state->tarray.binding)
3580 GET(GL_TEXTURE_COORD_ARRAY_SIZE, state->tarray.size)
3581 GET(GL_TEXTURE_COORD_ARRAY_TYPE, state->tarray.type)
3582 GET(GL_TEXTURE_COORD_ARRAY_STRIDE, state->tarray.stride)
3585 glGetFloatv (pname, params); /* the real one */
3589 CHECK("glGetFloatv");
3594 jwzgles_glGetPointerv (GLenum pname, GLvoid **params)
3596 if (! state->replaying_list)
3597 LOG2 ("direct %-12s %s", "glGetPointerv", mode_desc(pname));
3601 GET(GL_VERTEX_ARRAY_POINTER, state->varray.data)
3602 GET(GL_NORMAL_ARRAY_POINTER, state->narray.data)
3603 GET(GL_COLOR_ARRAY_POINTER, state->carray.data)
3604 GET(GL_TEXTURE_COORD_ARRAY_POINTER, state->tarray.data)
3607 glGetPointerv (pname, params); /* the real one */
3610 CHECK("glGetPointerv");
3616 /* How many cells are written into the *params array.
3617 We need to know this to avoid smashing the caller's stack
3618 if they asked for a single-value parameter.
3621 glGet_ret_count (GLenum pname)
3624 /*case GL_COLOR_MATRIX: */
3625 case GL_MODELVIEW_MATRIX:
3626 case GL_PROJECTION_MATRIX:
3627 case GL_TEXTURE_MATRIX:
3628 /*case GL_TRANSPOSE_COLOR_MATRIX: */
3629 /*case GL_TRANSPOSE_MODELVIEW_MATRIX: */
3630 /*case GL_TRANSPOSE_PROJECTION_MATRIX: */
3631 /*case GL_TRANSPOSE_TEXTURE_MATRIX: */
3633 /*case GL_ACCUM_CLEAR_VALUE: */
3634 /*case GL_BLEND_COLOR: */
3635 case GL_COLOR_CLEAR_VALUE:
3636 case GL_COLOR_WRITEMASK:
3637 case GL_CURRENT_COLOR:
3638 /*case GL_CURRENT_RASTER_COLOR: */
3639 /*case GL_CURRENT_RASTER_POSITION: */
3640 /*case GL_CURRENT_RASTER_SECONDARY_COLOR: */
3641 /*case GL_CURRENT_RASTER_TEXTURE_COORDS: */
3642 /*case GL_CURRENT_SECONDARY_COLOR: */
3643 case GL_CURRENT_TEXTURE_COORDS:
3645 case GL_LIGHT_MODEL_AMBIENT:
3646 /*case GL_MAP2_GRID_DOMAIN: */
3647 case GL_SCISSOR_BOX:
3650 case GL_CURRENT_NORMAL:
3651 case GL_POINT_DISTANCE_ATTENUATION:
3653 case GL_ALIASED_LINE_WIDTH_RANGE:
3654 case GL_ALIASED_POINT_SIZE_RANGE:
3655 case GL_DEPTH_RANGE:
3656 /*case GL_LINE_WIDTH_RANGE: */
3657 /*case GL_MAP1_GRID_DOMAIN: */
3658 /*case GL_MAP2_GRID_SEGMENTS: */
3659 case GL_MAX_VIEWPORT_DIMS:
3660 /*case GL_POINT_SIZE_RANGE: */
3661 case GL_POLYGON_MODE:
3662 case GL_SMOOTH_LINE_WIDTH_RANGE:
3663 case GL_SMOOTH_POINT_SIZE_RANGE:
3672 jwzgles_glGetDoublev (GLenum pname, GLdouble *params)
3675 int i, j = glGet_ret_count (pname);
3676 jwzgles_glGetFloatv (pname, m);
3677 for (i = 0; i < j; i++)
3683 jwzgles_glGetIntegerv (GLenum pname, GLint *params)
3686 int i, j = glGet_ret_count (pname);
3687 jwzgles_glGetFloatv (pname, m);
3688 for (i = 0; i < j; i++)
3694 jwzgles_glGetBooleanv (GLenum pname, GLboolean *params)
3697 int i, j = glGet_ret_count (pname);
3698 jwzgles_glGetFloatv (pname, m);
3699 for (i = 0; i < j; i++)
3700 params[i] = (m[i] != 0.0);
3705 jwzgles_gluErrorString (GLenum error)
3708 sprintf (s, "0x%lX", (unsigned long) error);
3713 /* These four *Pointer calls (plus glBindBuffer and glBufferData) can
3714 be included inside glNewList, but they actually execute immediately
3715 anyway, because their data is recorded in the list by the
3716 subsequently-recorded call to glDrawArrays. This is a little weird.
3719 jwzgles_glVertexPointer (GLuint size, GLuint type, GLuint stride,
3722 if (! state->replaying_list)
3723 LOG5 ("direct %-12s %d %s %d 0x%lX", "glVertexPointer",
3724 size, mode_desc(type), stride, (unsigned long) ptr);
3726 state->varray.size = size;
3727 state->varray.type = type;
3728 state->varray.stride = stride;
3729 state->varray.data = (GLvoid *)ptr;
3731 glVertexPointer (size, type, stride, ptr); /* the real one */
3732 CHECK("glVertexPointer");
3737 jwzgles_glNormalPointer (GLuint type, GLuint stride, const GLvoid *ptr)
3739 if (! state->replaying_list)
3740 LOG4 ("direct %-12s %s %d 0x%lX", "glNormalPointer",
3741 mode_desc(type), stride, (unsigned long) ptr);
3743 state->narray.type = type;
3744 state->narray.stride = stride;
3745 state->narray.data = (GLvoid *)ptr;
3747 glNormalPointer (type, stride, ptr); /* the real one */
3748 CHECK("glNormalPointer");
3752 jwzgles_glColorPointer (GLuint size, GLuint type, GLuint stride,
3755 if (! state->replaying_list)
3756 LOG5 ("direct %-12s %d %s %d 0x%lX", "glColorPointer",
3757 size, mode_desc(type), stride, (unsigned long) ptr);
3759 state->carray.size = size;
3760 state->carray.type = type;
3761 state->carray.stride = stride;
3762 state->carray.data = (GLvoid *)ptr;
3764 glColorPointer (size, type, stride, ptr); /* the real one */
3765 CHECK("glColorPointer");
3769 jwzgles_glTexCoordPointer (GLuint size, GLuint type, GLuint stride,
3772 if (! state->replaying_list)
3773 LOG5 ("direct %-12s %d %s %d 0x%lX", "glTexCoordPointer",
3774 size, mode_desc(type), stride, (unsigned long) ptr);
3776 state->tarray.size = size;
3777 state->tarray.type = type;
3778 state->tarray.stride = stride;
3779 state->tarray.data = (GLvoid *)ptr;
3781 glTexCoordPointer (size, type, stride, ptr); /* the real one */
3782 CHECK("glTexCoordPointer");
3786 jwzgles_glBindBuffer (GLuint target, GLuint buffer)
3788 if (! state->replaying_list)
3789 LOG3 ("direct %-12s %s %d", "glBindBuffer", mode_desc(target), buffer);
3790 glBindBuffer (target, buffer); /* the real one */
3791 CHECK("glBindBuffer");
3795 jwzgles_glBufferData (GLenum target, GLsizeiptr size, const void *data,
3798 if (! state->replaying_list)
3799 LOG5 ("direct %-12s %s %ld 0x%lX %s", "glBufferData",
3800 mode_desc(target), size, (unsigned long) data, mode_desc(usage));
3801 glBufferData (target, size, data, usage); /* the real one */
3802 CHECK("glBufferData");
3807 jwzgles_glTexParameterf (GLuint target, GLuint pname, GLfloat param)
3809 Assert (!state->compiling_verts,
3810 "glTexParameterf not allowed inside glBegin");
3812 /* We don't *really* implement mipmaps, so just turn this off. */
3813 if (param == GL_LINEAR_MIPMAP_LINEAR) param = GL_LINEAR;
3814 if (param == GL_NEAREST_MIPMAP_LINEAR) param = GL_LINEAR;
3815 if (param == GL_LINEAR_MIPMAP_NEAREST) param = GL_NEAREST;
3816 if (param == GL_NEAREST_MIPMAP_NEAREST) param = GL_NEAREST;
3818 /* We implement 1D textures as 2D textures. */
3819 if (target == GL_TEXTURE_1D) target = GL_TEXTURE_2D;
3821 /* Apparently this is another invalid enum. Just ignore it. */
3822 if ((pname == GL_TEXTURE_WRAP_S || pname == GL_TEXTURE_WRAP_T) &&
3826 if (state->compiling_list)
3832 list_push ("glTexParameterf", (list_fn_cb) &jwzgles_glTexParameterf,
3837 if (! state->replaying_list)
3838 LOG4 ("direct %-12s %s %s %7.3f", "glTexParameterf",
3839 mode_desc(target), mode_desc(pname), param);
3840 glTexParameterf (target, pname, param); /* the real one */
3841 CHECK("glTexParameterf");
3846 jwzgles_glTexParameteri (GLuint target, GLuint pname, GLuint param)
3848 jwzgles_glTexParameterf (target, pname, param);
3853 jwzgles_glBindTexture (GLuint target, GLuint texture)
3855 Assert (!state->compiling_verts,
3856 "glBindTexture not allowed inside glBegin");
3858 /* We implement 1D textures as 2D textures. */
3859 if (target == GL_TEXTURE_1D) target = GL_TEXTURE_2D;
3861 if (state->compiling_list)
3866 list_push ("glBindTexture", (list_fn_cb) &jwzgles_glBindTexture,
3870 /* Do it immediately as well, for generate_texture_coords */
3873 if (! state->replaying_list)
3874 LOG3 ("direct %-12s %s %d", "glBindTexture",
3875 mode_desc(target), texture);
3876 glBindTexture (target, texture); /* the real one */
3877 CHECK("glBindTexture");
3883 /* Matrix functions, mostly cribbed from Mesa.
3887 jwzgles_glFrustum (GLfloat left, GLfloat right,
3888 GLfloat bottom, GLfloat top,
3889 GLfloat near, GLfloat far)
3892 GLfloat x = (2 * near) / (right-left);
3893 GLfloat y = (2 * near) / (top - bottom);
3894 GLfloat a = (right + left) / (right - left);
3895 GLfloat b = (top + bottom) / (top - bottom);
3896 GLfloat c = -(far + near) / (far - near);
3897 GLfloat d = -(2 * far * near) / (far - near);
3899 # define M(X,Y) m[Y * 4 + X]
3900 M(0,0) = x; M(0,1) = 0; M(0,2) = a; M(0,3) = 0;
3901 M(1,0) = 0; M(1,1) = y; M(1,2) = b; M(1,3) = 0;
3902 M(2,0) = 0; M(2,1) = 0; M(2,2) = c; M(2,3) = d;
3903 M(3,0) = 0; M(3,1) = 0; M(3,2) = -1; M(3,3) = 0;
3906 jwzgles_glMultMatrixf (m);
3911 jwzgles_glOrtho (GLfloat left, GLfloat right,
3912 GLfloat bottom, GLfloat top,
3913 GLfloat near, GLfloat far)
3916 GLfloat a = 2 / (right - left);
3917 GLfloat b = -(right + left) / (right - left);
3918 GLfloat c = 2 / (top - bottom);
3919 GLfloat d = -(top + bottom) / (top - bottom);
3920 GLfloat e = -2 / (far - near);
3921 GLfloat f = -(far + near) / (far - near);
3923 # define M(X,Y) m[Y * 4 + X]
3924 M(0,0) = a; M(0,1) = 0; M(0,2) = 0; M(0,3) = b;
3925 M(1,0) = 0; M(1,1) = c; M(1,2) = 0; M(1,3) = d;
3926 M(2,0) = 0; M(2,1) = 0; M(2,2) = e; M(2,3) = f;
3927 M(3,0) = 0; M(3,1) = 0; M(3,2) = 0; M(3,3) = 1;
3930 jwzgles_glMultMatrixf (m);
3935 jwzgles_gluPerspective (GLdouble fovy, GLdouble aspect,
3936 GLdouble near, GLdouble far)
3940 double rad = fovy / 2 * M_PI / 180;
3945 if (dz == 0 || si == 0 || aspect == 0)
3951 c = -(far + near) / dz;
3952 d = -2 * near * far / dz;
3954 # define M(X,Y) m[Y * 4 + X]
3955 M(0,0) = a; M(0,1) = 0; M(0,2) = 0; M(0,3) = 0;
3956 M(1,0) = 0; M(1,1) = b; M(1,2) = 0; M(1,3) = 0;
3957 M(2,0) = 0; M(2,1) = 0; M(2,2) = c; M(2,3) = d;
3958 M(3,0) = 0; M(3,1) = 0; M(3,2) = -1; M(3,3) = 0;
3961 jwzgles_glMultMatrixf (m);
3966 jwzgles_gluLookAt (GLfloat eyex, GLfloat eyey, GLfloat eyez,
3967 GLfloat centerx, GLfloat centery, GLfloat centerz,
3968 GLfloat upx, GLfloat upy, GLfloat upz)
3971 GLfloat x[3], y[3], z[3];
3974 /* Make rotation matrix */
3977 z[0] = eyex - centerx;
3978 z[1] = eyey - centery;
3979 z[2] = eyez - centerz;
3980 mag = sqrt(z[0] * z[0] + z[1] * z[1] + z[2] * z[2]);
3981 if (mag) { /* mpichler, 19950515 */
3992 /* X vector = Y cross Z */
3993 x[0] = y[1] * z[2] - y[2] * z[1];
3994 x[1] = -y[0] * z[2] + y[2] * z[0];
3995 x[2] = y[0] * z[1] - y[1] * z[0];
3997 /* Recompute Y = Z cross X */
3998 y[0] = z[1] * x[2] - z[2] * x[1];
3999 y[1] = -z[0] * x[2] + z[2] * x[0];
4000 y[2] = z[0] * x[1] - z[1] * x[0];
4002 /* mpichler, 19950515 */
4003 /* cross product gives area of parallelogram, which is < 1.0 for
4004 * non-perpendicular unit-length vectors; so normalize x, y here
4007 mag = sqrt(x[0] * x[0] + x[1] * x[1] + x[2] * x[2]);
4014 mag = sqrt(y[0] * y[0] + y[1] * y[1] + y[2] * y[2]);
4021 #define M(row,col) m[col*4+row]
4022 M(0, 0) = x[0]; M(0, 1) = x[1]; M(0, 2) = x[2]; M(0, 3) = 0.0;
4023 M(1, 0) = y[0]; M(1, 1) = y[1]; M(1, 2) = y[2]; M(1, 3) = 0.0;
4024 M(2, 0) = z[0]; M(2, 1) = z[1]; M(2, 2) = z[2]; M(2, 3) = 0.0;
4025 M(3, 0) = 0.0; M(3, 1) = 0.0; M(3, 2) = 0.0; M(3, 3) = 1.0;
4028 jwzgles_glMultMatrixf(m);
4030 /* Translate Eye to Origin */
4031 jwzgles_glTranslatef(-eyex, -eyey, -eyez);
4035 static void __gluMultMatrixVecd (const GLdouble matrix[16],
4036 const GLdouble in[4],
4041 for (i=0; i<4; i++) {
4043 in[0] * matrix[0*4+i] +
4044 in[1] * matrix[1*4+i] +
4045 in[2] * matrix[2*4+i] +
4046 in[3] * matrix[3*4+i];
4051 jwzgles_gluProject (GLdouble objx, GLdouble objy, GLdouble objz,
4052 const GLdouble modelMatrix[16],
4053 const GLdouble projMatrix[16],
4054 const GLint viewport[4],
4055 GLdouble *winx, GLdouble *winy, GLdouble *winz)
4060 /* #### I suspect this is not working right. I was seeing crazy values
4061 in lament.c. Maybe there's some float-vs-double confusion going on?
4068 __gluMultMatrixVecd(modelMatrix, in, out);
4069 __gluMultMatrixVecd(projMatrix, out, in);
4070 if (in[3] == 0.0) return(GL_FALSE);
4074 /* Map x, y and z to range 0-1 */
4075 in[0] = in[0] * 0.5 + 0.5;
4076 in[1] = in[1] * 0.5 + 0.5;
4077 in[2] = in[2] * 0.5 + 0.5;
4079 /* Map x,y to viewport */
4080 in[0] = in[0] * viewport[2] + viewport[0];
4081 in[1] = in[1] * viewport[3] + viewport[1];
4090 /* OpenGL ES has different extensions vs. regular OpenGL, but the basic
4091 principle for checking for extensions is the same.
4094 jwzgles_gluCheckExtension (const GLubyte *ext_name, const GLubyte *ext_string)
4096 size_t ext_len = strlen ((const char *)ext_name);
4099 const GLubyte *found = (const GLubyte *)strstr ((const char *)ext_string,
4100 (const char *)ext_name);
4104 char last_ch = found[ext_len];
4105 if ((found == ext_string || found[-1] == ' ') &&
4106 (last_ch == ' ' || !last_ch)) {
4110 ext_string = found + ext_len;
4117 void jwzgles_glViewport (GLuint x, GLuint y, GLuint w, GLuint h)
4119 # if TARGET_IPHONE_SIMULATOR
4120 /* fprintf (stderr, "glViewport %dx%d\n", w, h); */
4122 glViewport (x, y, w, h); /* the real one */
4126 /* The following functions are present in both OpenGL 1.1 and in OpenGLES 1,
4127 but are allowed within glNewList/glEndList, so we must wrap them to allow
4128 them to either be recorded in lists, or run directly.
4130 All this CPP obscenity is me screaming in rage at all the ways that C is
4131 not Lisp, as all I want to do here is DEFADVICE.
4134 #define PROTO_V PROTO_VOID
4135 #define TYPE_V GLuint
4137 #define VARS_V /* */
4139 #define FILL_V /* */
4141 #define TYPE_I GLuint
4142 #define TYPE_II TYPE_I
4143 #define TYPE_III TYPE_I
4144 #define TYPE_IIII TYPE_I
4145 #define ARGS_I TYPE_I a
4146 #define ARGS_II TYPE_I a, TYPE_I b
4147 #define ARGS_III TYPE_I a, TYPE_I b, TYPE_I c
4148 #define ARGS_IIII TYPE_I a, TYPE_I b, TYPE_I c, TYPE_I d
4149 #define LOGS_I "%s\n", mode_desc(a)
4150 #define LOGS_II "%s %d\n", mode_desc(a), b
4151 #define LOGS_III "%s %s %s\n", mode_desc(a), mode_desc(b), mode_desc(c)
4152 #define LOGS_IIII "%d %d %d %d\n", a, b, c, d
4154 #define VARS_II a, b
4155 #define VARS_III a, b, c
4156 #define VARS_IIII a, b, c, d
4157 #define FILL_I vv[0].i = a;
4158 #define FILL_II vv[0].i = a; vv[1].i = b;
4159 #define FILL_III vv[0].i = a; vv[1].i = b; vv[2].i = c;
4160 #define FILL_IIII vv[0].i = a; vv[1].i = b; vv[2].i = c; vv[3].i = d;
4162 #define TYPE_F GLfloat
4163 #define TYPE_FF TYPE_F
4164 #define TYPE_FFF TYPE_F
4165 #define TYPE_FFFF TYPE_F
4166 #define ARGS_F TYPE_F a
4167 #define ARGS_FF TYPE_F a, TYPE_F b
4168 #define ARGS_FFF TYPE_F a, TYPE_F b, TYPE_F c
4169 #define ARGS_FFFF TYPE_F a, TYPE_F b, TYPE_F c, TYPE_F d
4170 #define LOGS_F "%7.3f\n", a
4171 #define LOGS_FF "%7.3f %7.3f\n", a, b
4172 #define LOGS_FFF "%7.3f %7.3f %7.3f\n", a, b, c
4173 #define LOGS_FFFF "%7.3f %7.3f %7.3f %7.3f\n", a, b, c, d
4174 #define VARS_F VARS_I
4175 #define VARS_FF VARS_II
4176 #define VARS_FFF VARS_III
4177 #define VARS_FFFF VARS_IIII
4178 #define FILL_F vv[0].f = a;
4179 #define FILL_FF vv[0].f = a; vv[1].f = b;
4180 #define FILL_FFF vv[0].f = a; vv[1].f = b; vv[2].f = c;
4181 #define FILL_FFFF vv[0].f = a; vv[1].f = b; vv[2].f = c; vv[3].f = d;
4183 #define ARGS_IF TYPE_I a, TYPE_F b
4184 #define VARS_IF VARS_II
4185 #define LOGS_IF "%s %7.3f\n", mode_desc(a), b
4186 #define FILL_IF vv[0].i = a; vv[1].f = b;
4188 #define ARGS_IIF TYPE_I a, TYPE_I b, TYPE_F c
4189 #define VARS_IIF VARS_III
4190 #define LOGS_IIF "%s %s %7.3f\n", mode_desc(a), mode_desc(b), c
4191 #define FILL_IIF vv[0].i = a; vv[1].i = b; vv[2].f = c;
4193 #define TYPE_IV GLint
4194 #define ARGS_IIV TYPE_I a, const TYPE_IV *b
4195 #define VARS_IIV VARS_II
4196 #define LOGS_IIV "%s %d %d %d %d\n", mode_desc(a), b[0], b[1], b[2], b[3]
4197 #define FILL_IIV vv[0].i = a; \
4198 vv[1].i = b[0]; vv[2].i = b[1]; \
4199 vv[3].i = b[2]; vv[4].i = b[3];
4201 #define ARGS_IFV TYPE_I a, const TYPE_F *b
4202 #define VARS_IFV VARS_II
4203 #define LOGS_IFV "%s %7.3f %7.3f %7.3f %7.3f\n", mode_desc(a), \
4204 b[0], b[1], b[2], b[3]
4205 #define FILL_IFV vv[0].i = a; \
4206 vv[1].f = b[0]; vv[2].f = b[1]; \
4207 vv[3].f = b[2]; vv[4].f = b[3];
4209 #define ARGS_IIIV TYPE_I a, TYPE_I b, const TYPE_IV *c
4210 #define VARS_IIIV VARS_III
4211 #define LOGS_IIIV "%s %-8s %3d %3d %3d %3d\n", mode_desc(a), mode_desc(b), \
4212 c[0], c[1], c[2], c[3]
4213 #define FILL_IIIV vv[0].i = a; vv[1].i = b; \
4214 vv[2].i = c[0]; vv[3].i = c[1]; \
4215 vv[4].i = c[2]; vv[5].i = c[3];
4217 #define ARGS_IIFV TYPE_I a, TYPE_I b, const TYPE_F *c
4218 #define VARS_IIFV VARS_III
4219 #define LOGS_IIFV "%s %-8s %7.3f %7.3f %7.3f %7.3f\n", \
4220 mode_desc(a), mode_desc(b), \
4221 c[0], c[1], c[2], c[3]
4222 #define FILL_IIFV vv[0].i = a; vv[1].i = b; \
4223 vv[2].f = c[0]; vv[3].f = c[1]; \
4224 vv[4].f = c[2]; vv[5].f = c[3];
4227 # define WLOG(NAME,ARGS) \
4228 fprintf (stderr, "jwzgles: direct %-12s ", NAME); \
4229 fprintf (stderr, ARGS)
4231 # define WLOG(NAME,ARGS) /* */
4234 #define WRAP(NAME,SIG) \
4235 void jwzgles_##NAME (ARGS_##SIG) \
4237 Assert (!state->compiling_verts, \
4238 STRINGIFY(NAME) " not allowed inside glBegin"); \
4239 if (state->compiling_list) { \
4242 list_push (STRINGIFY(NAME), (list_fn_cb) &jwzgles_##NAME, \
4245 if (! state->replaying_list) { \
4246 WLOG (STRINGIFY(NAME), LOGS_##SIG); \
4248 NAME (VARS_##SIG); \
4249 CHECK(STRINGIFY(NAME)); \
4253 WRAP (glActiveTexture, I)
4254 WRAP (glAlphaFunc, IF)
4255 WRAP (glBlendFunc, II)
4257 WRAP (glClearColor, FFFF)
4258 WRAP (glClearStencil, I)
4259 WRAP (glColorMask, IIII)
4260 WRAP (glCullFace, I)
4261 WRAP (glDepthFunc, I)
4262 WRAP (glDepthMask, I)
4267 WRAP (glFrontFace, I)
4269 WRAP (glLightModelf, IF)
4270 WRAP (glLightModelfv, IFV)
4271 WRAP (glLightf, IIF)
4272 WRAP (glLightfv, IIFV)
4273 WRAP (glLineWidth, F)
4274 WRAP (glLoadIdentity, V)
4276 WRAP (glMatrixMode, I)
4277 WRAP (glPixelStorei, II)
4278 WRAP (glPointSize, F)
4279 WRAP (glPolygonOffset, FF)
4280 WRAP (glPopMatrix, V)
4281 WRAP (glPushMatrix, V)
4282 WRAP (glRotatef, FFFF)
4283 WRAP (glScalef, FFF)
4284 WRAP (glScissor, IIII)
4285 WRAP (glShadeModel, I)
4286 WRAP (glStencilFunc, III)
4287 WRAP (glStencilMask, I)
4288 WRAP (glStencilOp, III)
4289 WRAP (glTexEnvf, IIF)
4290 WRAP (glTexEnvi, III)
4291 WRAP (glTranslatef, FFF)
4293 #define TYPE_IV GLuint
4294 WRAP (glDeleteTextures, IIV)
4297 #endif /* HAVE_JWZGLES - whole file */