1 /* xscreensaver, Copyright (c) 2012-2014 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.x, not 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!)
123 - Not every function is implemented; just the ones that I needed for
124 xscreensaver. However, the trivial ones are trivial to enable
125 as they come up. Harder ones will be harder.
127 As a result of that, these savers look wrong:
129 atlantis Uses EYE_PLANE.
130 blocktube Uses SPHERE_MAP.
131 dnalogo Uses GLUtesselator.
132 extrusion Uses all kinds of GLUT crap.
133 flyingtoasters Uses SPHERE_MAP.
134 winduprobot Uses SPHERE_MAP.
135 jigglypuff Uses SPHERE_MAP (in chrome mode), GL_LINE (in wireframe)
136 jigsaw Uses GLUtesselator.
137 lockward Puts verts in lists without glBegin!
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.
152 #endif /* HAVE_CONFIG_H */
154 #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>
172 # ifndef GL_GLEXT_PROTOTYPES
173 # define GL_GLEXT_PROTOTYPES /* for glBindBuffer */
179 #include "jwzglesI.h"
181 #define STRINGIFY(X) #X
184 #define countof(x) (sizeof((x))/sizeof((*x)))
189 extern void jwxyz_abort (const char *fmt, ...) __dead2;
190 # define Assert(C,S) do { if (!(C)) { jwxyz_abort ("%s",S); }} while(0)
192 # define Assert(C,S) do { \
194 fprintf (stderr, "jwzgles: %s\n", S); \
200 typedef struct { GLfloat x, y, z; } XYZ;
201 typedef struct { GLfloat x, y, z, w; } XYZW;
202 typedef struct { GLfloat s, t, r, q; } STRQ;
203 typedef struct { GLfloat r, g, b, a; } RGBA;
206 /* Used to record all calls to glVertex3f, glNormal3f, etc.
207 while inside glBegin / glEnd so that we can convert that
208 to a single call to glDrawArrays.
212 int count, size; /* size of each array */
214 XYZW *verts; /* Arrays being built */
219 int ncount; /* How many normals, tex coords and colors were */
220 int tcount; /* used. We optimize based on "0, 1, or many". */
222 int materialistic; /* Whether glMaterial was called inside glBegin */
224 XYZ cnorm; /* Prevailing normal/texture/color while building */
231 typedef void (*list_fn_cb) (void);
234 /* We need this nonsense because you can't cast a double to a void*
235 or vice versa. They tend to be passed in different registers,
236 and you need to know about that because it's still 1972 here.
239 const void *v; GLfloat f; GLuint i; GLshort s; GLdouble d;
242 typedef struct { /* saved args for glDrawArrays */
243 int binding, size, type, stride, bytes;
247 typedef enum { /* shorthand describing arglist signature */
248 PROTO_VOID, /* no args */
249 PROTO_I, /* 1 int arg */
250 PROTO_F, /* 1 float arg */
251 PROTO_II, /* int, int */
252 PROTO_FF, /* float, float */
253 PROTO_IF, /* int, float */
254 PROTO_III, /* int, int, int */
255 PROTO_FFF, /* float, float, float */
256 PROTO_IIF, /* int, int, float */
257 PROTO_IIII, /* int, int, int, int */
258 PROTO_FFFF, /* float, float, float, float */
259 PROTO_IIV, /* int, int[4] */
260 PROTO_IFV, /* int, float[4] */
261 PROTO_IIIV, /* int, int, int[4] */
262 PROTO_IIFV, /* int, int, float[4] */
263 PROTO_FV16, /* float[16] */
264 PROTO_ARRAYS /* glDrawArrays */
267 typedef struct { /* A single element of a display list */
269 list_fn_cb fn; /* saved function pointer */
270 fn_proto proto; /* arglist prototype */
271 draw_array *arrays; /* args for glDrawArrays */
272 void_int argv[16]; /* args for everything else */
276 typedef struct { /* a display list: saved activity within glNewList */
281 /* Named buffer that should be freed when this display list is deleted. */
287 typedef struct { /* All display lists */
293 #define ISENABLED_TEXTURE_2D (1<<0)
294 #define ISENABLED_TEXTURE_GEN_S (1<<1)
295 #define ISENABLED_TEXTURE_GEN_T (1<<2)
296 #define ISENABLED_TEXTURE_GEN_R (1<<3)
297 #define ISENABLED_TEXTURE_GEN_Q (1<<4)
298 #define ISENABLED_LIGHTING (1<<5)
299 #define ISENABLED_BLEND (1<<6)
300 #define ISENABLED_DEPTH_TEST (1<<7)
301 #define ISENABLED_CULL_FACE (1<<8)
302 #define ISENABLED_NORMALIZE (1<<9)
303 #define ISENABLED_FOG (1<<10)
304 #define ISENABLED_COLMAT (1<<11)
305 #define ISENABLED_VERT_ARRAY (1<<12)
306 #define ISENABLED_NORM_ARRAY (1<<13)
307 #define ISENABLED_TEX_ARRAY (1<<14)
308 #define ISENABLED_COLOR_ARRAY (1<<15)
313 GLfloat obj[4], eye[4];
317 typedef struct { /* global state */
319 vert_set set; /* set being built */
321 int compiling_list; /* list id if inside glNewList; 0 means immediate */
322 int replaying_list; /* depth of call stack to glCallList */
323 int compiling_verts; /* inside glBegin */
325 list_set lists; /* saved lists */
327 unsigned long enabled; /* enabled flags, immediate mode */
328 unsigned long list_enabled; /* and for the list-in-progress */
330 texgen_state s, t, r, q;
335 static jwzgles_state *state = 0;
339 # define LOG(A) fprintf(stderr,"jwzgles: " A "\n")
340 # define LOG1(A,B) fprintf(stderr,"jwzgles: " A "\n",B)
341 # define LOG2(A,B,C) fprintf(stderr,"jwzgles: " A "\n",B,C)
342 # define LOG3(A,B,C,D) fprintf(stderr,"jwzgles: " A "\n",B,C,D)
343 # define LOG4(A,B,C,D,E) fprintf(stderr,"jwzgles: " A "\n",B,C,D,E)
344 # define LOG5(A,B,C,D,E,F) fprintf(stderr,"jwzgles: " A "\n",B,C,D,E,F)
345 # define LOG6(A,B,C,D,E,F,G) fprintf(stderr,"jwzgles: " A "\n",B,C,D,E,F,G)
346 # define LOG7(A,B,C,D,E,F,G,H) fprintf(stderr,"jwzgles: " A "\n",B,C,D,E,F,G,H)
347 # define LOG8(A,B,C,D,E,F,G,H,I)\
348 fprintf(stderr,"jwzgles: "A "\n",B,C,D,E,F,G,H,I)
349 # define LOG9(A,B,C,D,E,F,G,H,I,J)\
350 fprintf(stderr,"jwzgles: "A "\n",B,C,D,E,F,G,H,I,J)
351 # define LOG10(A,B,C,D,E,F,G,H,I,J,K)\
352 fprintf(stderr,"jwzgles: "A "\n",B,C,D,E,F,G,H,I,J,K)
353 # define LOG17(A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R)\
354 fprintf(stderr,"jwzgles: "A "\n",B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R)
355 # define CHECK(S) check_gl_error(S)
357 # define LOG(A) /* */
358 # define LOG1(A,B) /* */
359 # define LOG2(A,B,C) /* */
360 # define LOG3(A,B,C,D) /* */
361 # define LOG4(A,B,C,D,E) /* */
362 # define LOG5(A,B,C,D,E,F) /* */
363 # define LOG6(A,B,C,D,E,F,G) /* */
364 # define LOG7(A,B,C,D,E,F,G,H) /* */
365 # define LOG8(A,B,C,D,E,F,G,H,I) /* */
366 # define LOG9(A,B,C,D,E,F,G,H,I,J) /* */
367 # define LOG10(A,B,C,D,E,F,G,H,I,J,K) /* */
368 # define LOG17(A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R) /* */
369 # define CHECK(S) /* */
374 mode_desc (int mode) /* for debugging messages */
377 # define SS(X) case GL_##X: return STRINGIFY(X);
381 SS(AMBIENT_AND_DIFFUSE)
397 SS(COLOR_ARRAY_BUFFER_BINDING);
399 SS(COLOR_MATERIAL_FACE)
400 SS(COLOR_MATERIAL_PARAMETER)
412 SS(ELEMENT_ARRAY_BUFFER)
425 SS(INVALID_OPERATION)
433 SS(LIGHT_MODEL_AMBIENT)
434 SS(LIGHT_MODEL_COLOR_CONTROL)
435 SS(LIGHT_MODEL_LOCAL_VIEWER)
436 SS(LIGHT_MODEL_TWO_SIDE)
439 SS(LINEAR_MIPMAP_LINEAR)
440 SS(LINEAR_MIPMAP_NEAREST)
451 SS(NEAREST_MIPMAP_LINEAR)
452 SS(NEAREST_MIPMAP_NEAREST)
455 SS(NORMAL_ARRAY_BUFFER_BINDING);
458 SS(ONE_MINUS_DST_ALPHA)
459 SS(ONE_MINUS_DST_COLOR)
460 SS(ONE_MINUS_SRC_ALPHA)
461 SS(ONE_MINUS_SRC_COLOR)
466 SS(POLYGON_OFFSET_FILL)
482 SS(SEPARATE_SPECULAR_COLOR)
491 SS(SRC_ALPHA_SATURATE)
496 SS(STENCIL_BUFFER_BIT)
508 SS(TEXTURE_ALPHA_SIZE)
509 SS(TEXTURE_BINDING_2D)
510 SS(TEXTURE_BLUE_SIZE)
512 SS(TEXTURE_BORDER_COLOR)
513 SS(TEXTURE_COMPONENTS)
514 SS(TEXTURE_COORD_ARRAY)
515 SS(TEXTURE_COORD_ARRAY_BUFFER_BINDING);
517 SS(TEXTURE_ENV_COLOR)
524 SS(TEXTURE_GREEN_SIZE)
526 SS(TEXTURE_INTENSITY_SIZE)
527 SS(TEXTURE_LUMINANCE_SIZE)
528 SS(TEXTURE_MAG_FILTER)
529 SS(TEXTURE_MIN_FILTER)
537 SS(UNPACK_ROW_LENGTH)
539 SS(UNSIGNED_INT_8_8_8_8_REV)
544 SS(VERTEX_ARRAY_BUFFER_BINDING);
545 /*SS(COLOR_BUFFER_BIT) -- same value as GL_LIGHT0 */
547 case (GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT):
548 return "DEPTH_BUFFER_BIT | COLOR_BUFFER_BIT";
549 /* Oops, same as INVALID_ENUM.
550 case (GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT):
551 return "DEPTH_BUFFER_BIT | STENCIL_BUFFER_BIT";
553 case (GL_COLOR_BUFFER_BIT | GL_STENCIL_BUFFER_BIT):
554 return "COLOR_BUFFER_BIT | STENCIL_BUFFER_BIT";
555 case (GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT | GL_STENCIL_BUFFER_BIT):
556 return "DEPTH_BUFFER_BIT | COLOR_BUFFER_BIT | STENCIL_BUFFER_BIT";
559 static char buf[255];
560 sprintf (buf, "0x%04X", mode);
567 check_gl_error (const char *s)
569 GLenum i = glGetError();
570 if (i == GL_NO_ERROR) return;
571 fprintf (stderr, "jwzgles: GL ERROR: %s: %s\n", s, mode_desc(i));
578 make_room (const char *name, void **array, int span, int *count, int *size)
580 if (*count + 1 >= *size)
582 int new_size = (*count + 20) * 1.2; /* mildly exponential */
583 *array = realloc (*array, new_size * span);
584 Assert (*array, "out of memory");
585 /* LOG3("%s: grew %d -> %d", name, *size, new_size); */
595 state = (jwzgles_state *) calloc (1, sizeof (*state));
597 if (state->lists.lists)
599 state->compiling_list = 0;
600 if (state->lists.count)
601 jwzgles_glDeleteLists (1, state->lists.count);
602 free (state->lists.lists);
605 if (state->set.verts) free (state->set.verts);
606 if (state->set.norms) free (state->set.norms);
607 if (state->set.tex) free (state->set.tex);
608 if (state->set.color) free (state->set.color);
610 memset (state, 0, sizeof(*state));
612 state->s.mode = state->t.mode = state->r.mode = state->q.mode =
614 state->s.obj[0] = state->s.eye[0] = 1; /* s = 1 0 0 0 */
615 state->t.obj[1] = state->t.eye[1] = 1; /* t = 0 1 0 0 */
620 jwzgles_glGenLists (int n)
625 Assert (!state->compiling_verts, "glGenLists not allowed inside glBegin");
627 /* Ensure space in state->lists, clear the one at the end, and tick counter
628 Note that lists are never really deleted, and we can never re-use elements
629 of this array. glDeleteLists zeroes out the contents of the list, but
630 the list ID is still valid for use with glNewList forever.
631 #### So maybe this should be a linked list instead of an array.
633 for (i = 0; i < n; i++)
637 make_room ("glGenLists",
638 (void **) &state->lists.lists,
639 sizeof (*state->lists.lists),
640 &state->lists.count, &state->lists.size);
641 state->lists.count++;
642 id = state->lists.count;
643 L = &state->lists.lists[id-1];
645 memset (L, 0, sizeof (*L));
647 if (ret == 0) ret = id;
648 LOG1("glGenLists -> %d", L->id);
651 /* Return the ID of the first list allocated */
658 jwzgles_glNewList (int id, int mode)
661 Assert (id > 0 && id <= state->lists.count, "glNewList: bogus ID");
662 Assert (mode == GL_COMPILE, "glNewList: bad mode");
663 Assert (!state->compiling_verts, "glNewList not allowed inside glBegin");
664 Assert (!state->compiling_list, "nested glNewList");
665 Assert (state->set.count == 0, "missing glEnd");
667 L = &state->lists.lists[id-1];
668 Assert (L->id == id, "glNewList corrupted");
670 if (L->count != 0) jwzgles_glDeleteLists (L->id, 1); /* Overwriting */
671 Assert (L->count == 0, "glNewList corrupted");
673 state->compiling_list = id;
675 state->list_enabled = state->enabled;
677 LOG1("glNewList -> %d", id);
681 static void save_arrays (list_fn *, int);
682 static void restore_arrays (list_fn *, int);
683 static void copy_array_data (draw_array *, int, const char *);
684 static void optimize_arrays (void);
685 static void generate_texture_coords (GLuint, GLuint);
689 jwzgles_glEndList (void)
691 Assert (state->compiling_list, "extra glEndList");
692 Assert (state->set.count == 0, "missing glEnd");
693 Assert (!state->compiling_verts, "glEndList not allowed inside glBegin");
694 LOG1("glEndList %d", state->compiling_list);
696 state->compiling_list = 0;
697 state->list_enabled = state->enabled;
702 list_push (const char * const name,
703 list_fn_cb fn, fn_proto proto, void_int *av)
709 Assert (state->compiling_list > 0, "not inside glNewList");
710 Assert (state->compiling_list <= state->lists.count, "glNewList corrupted");
712 L = &state->lists.lists[state->compiling_list-1];
713 Assert (L, "glNewList: no list");
715 make_room ("glNewLists",
716 (void **) &L->fns, sizeof (*L->fns),
717 &L->count, &L->size);
718 memset (&L->fns[L->count], 0, sizeof (*L->fns));
719 F = L->fns + L->count;
724 if (proto != PROTO_VOID)
725 for (i = 0; i < countof(F->argv); i++)
731 LOG1 (" push %-12s", name);
734 if (fn == (list_fn_cb) &jwzgles_glBegin ||
735 fn == (list_fn_cb) &jwzgles_glFrontFace ||
736 fn == (list_fn_cb) &jwzgles_glEnable ||
737 fn == (list_fn_cb) &jwzgles_glDisable ||
738 fn == (list_fn_cb) &jwzgles_glEnableClientState ||
739 fn == (list_fn_cb) &jwzgles_glDisableClientState ||
740 fn == (list_fn_cb) &jwzgles_glShadeModel ||
741 fn == (list_fn_cb) &jwzgles_glMatrixMode)
742 LOG2 (" push %-12s %s", name, mode_desc (av[0].i));
744 LOG2 (" push %-12s %d", name, av[0].i);
747 LOG2 (" push %-12s %7.3f", name, av[0].f);
750 if (fn == (list_fn_cb) &jwzgles_glBindTexture ||
751 fn == (list_fn_cb) &jwzgles_glBindBuffer)
752 LOG3 (" push %-12s %s %d", name, mode_desc (av[0].i), av[1].i);
754 LOG3 (" push %-12s %d %d", name, av[0].i, av[1].i);
757 LOG3 (" push %-12s %7.3f %7.3f", name, av[0].f, av[1].f);
760 LOG3 (" push %-12s %s %7.3f", name, mode_desc (av[0].i), av[1].f);
764 if (fn == (list_fn_cb) &jwzgles_glDrawArrays ||
765 fn == (list_fn_cb) &jwzgles_glTexParameteri)
766 LOG4 (" push %-12s %s %d %d", name, mode_desc (av[0].i),
769 LOG4 (" push %-12s %d %d %d", name, av[0].i, av[1].i, av[2].i);
772 LOG4 (" push %-12s %7.3f %7.3f %7.3f", name, av[0].f, av[1].f, av[2].f);
775 LOG4 (" push %-12s %s %s %7.3f", name,
776 mode_desc(av[0].i), mode_desc(av[1].i), av[2].f);
779 LOG5 (" push %-12s %d %d %d %d", name,
780 av[0].i, av[1].i, av[2].i, av[3].i);
783 LOG5 (" push %-12s %7.3f %7.3f %7.3f %7.3f", name,
784 av[0].f, av[1].f, av[2].f, av[3].f);
787 LOG6 (" push %-12s %s %3.1f %3.1f %3.1f %3.1f", name, mode_desc (av[0].i),
788 av[1].f, av[2].f, av[3].f, av[4].f);
791 LOG6 (" push %-12s %s %d %d %d %d", name, mode_desc (av[0].i),
792 av[1].i, av[2].i, av[3].i, av[4].i);
795 LOG7 (" push %-12s %s %-8s %3.1f %3.1f %3.1f %3.1f", name,
796 mode_desc (av[0].i), mode_desc (av[1].i),
797 av[2].f, av[3].f, av[4].f, av[5].f);
800 LOG7 (" push %-12s %s %-8s %3d %3d %3d %3d", name,
801 mode_desc (av[0].i), mode_desc (av[1].i),
802 av[2].i, av[3].i, av[4].i, av[5].i);
805 LOG17 (" push %-12s ["
806 "%8.3f %8.3f %8.3f %8.3f " "\n\t\t\t "
807 "%8.3f %8.3f %8.3f %8.3f " "\n\t\t\t "
808 "%8.3f %8.3f %8.3f %8.3f " "\n\t\t\t "
809 "%8.3f %8.3f %8.3f %8.3f ]",
811 av[0].f, av[1].f, av[2].f, av[3].f,
812 av[4].f, av[5].f, av[6].f, av[7].f,
813 av[8].f, av[9].f, av[10].f, av[11].f,
814 av[12].f, av[13].f, av[14].f, av[15].f);
817 Assert (0, "bogus prototype");
822 if (proto == PROTO_ARRAYS) /* glDrawArrays */
823 save_arrays (F, av[1].i + av[2].i);
830 jwzgles_glBegin (int mode)
832 Assert (!state->compiling_verts, "nested glBegin");
833 state->compiling_verts++;
835 /* Only these commands are allowed inside glBegin:
837 glVertex -- not allowed outside
848 glArrayElement -- not allowed outside
855 if (!state->replaying_list)
856 LOG2 ("%sglBegin %s",
857 (state->compiling_list || state->replaying_list ? " " : ""),
860 Assert (state->set.count == 0, "glBegin corrupted");
861 state->set.mode = mode;
862 state->set.count = 0;
863 state->set.ncount = 0;
864 state->set.tcount = 0;
865 state->set.ccount = 0;
870 jwzgles_glDeleteLists (int id0, int range)
872 Assert (!state->compiling_verts, "glDeleteLists not allowed inside glBegin");
874 if (state->compiling_list)
879 list_push ("glDeleteLists", (list_fn_cb) &jwzgles_glDeleteLists,
886 if (!state->replaying_list)
887 LOG2 ("glDeleteLists %d %d", id0, range);
889 for (id = id0 + range - 1; id >= id0; id--)
893 if (id == 0) continue; /* People do this stupid thing */
894 if (id > state->lists.count) break; /* this too */
895 Assert (id > 0 && id <= state->lists.count,
896 "glDeleteLists: bogus ID");
897 L = &state->lists.lists[id-1];
898 Assert (L->id == id, "glDeleteLists corrupted");
900 for (i = 0; i < L->count; i++)
902 list_fn *lf = &L->fns[i];
906 for (j = 0; j < 4; j++)
907 /* If there's a binding, 'data' is an index, not a ptr. */
908 if (!lf->arrays[j].binding &&
910 free (lf->arrays[j].data);
917 glDeleteBuffers (1, &L->buffer);
919 memset (L, 0, sizeof (*L));
927 jwzgles_glIsList (GLuint id)
929 return (id > 0 && id < state->lists.count);
935 jwzgles_glNormal3fv (const GLfloat *v)
937 if (state->compiling_list && !state->compiling_verts)
943 list_push ("glNormal3f", (list_fn_cb) &jwzgles_glNormal3f,
948 if (!state->replaying_list)
949 LOG5 ("%s%sglNormal3f %7.3f %7.3f %7.3f",
950 (state->compiling_list || state->replaying_list ? " " : ""),
951 (state->compiling_verts ? " rec " : ""),
954 if (state->compiling_verts) /* inside glBegin */
956 state->set.cnorm.x = v[0];
957 state->set.cnorm.y = v[1];
958 state->set.cnorm.z = v[2];
960 if (state->set.count > 0 && state->set.ncount == 1) /* not first! */
963 else /* outside glBegin */
965 glNormal3f (v[0], v[1], v[2]);
973 jwzgles_glNormal3f (GLfloat x, GLfloat y, GLfloat z)
979 jwzgles_glNormal3fv (v);
984 jwzgles_glTexCoord4fv (const GLfloat *v)
986 if (state->compiling_list && !state->compiling_verts)
993 list_push ("glTexCoord4f", (list_fn_cb) &jwzgles_glTexCoord4f,
998 if (!state->replaying_list)
999 LOG6 ("%s%sglTexCoord4f %7.3f %7.3f %7.3f %7.3f",
1000 (state->compiling_list || state->replaying_list ? " " : ""),
1001 (state->compiling_verts ? " rec " : ""),
1002 v[0], v[1], v[2], v[3]);
1004 Assert (state->compiling_verts, "glTexCoord4fv outside glBegin");
1006 if (state->compiling_verts) /* inside glBegin */
1008 state->set.ctex.s = v[0];
1009 state->set.ctex.t = v[1];
1010 state->set.ctex.r = v[2];
1011 state->set.ctex.q = v[3];
1012 state->set.tcount++;
1013 if (state->set.count > 0 && state->set.tcount == 1) /* not first! */
1014 state->set.tcount++;
1021 jwzgles_glTexCoord4f (GLfloat s, GLfloat t, GLfloat r, GLfloat q)
1028 jwzgles_glTexCoord4fv (v);
1033 jwzgles_glTexCoord3fv (const GLfloat *v)
1040 jwzgles_glTexCoord4fv (vv);
1045 jwzgles_glTexCoord2fv (const GLfloat *v)
1052 jwzgles_glTexCoord4fv (vv);
1057 jwzgles_glTexCoord3f (GLfloat s, GLfloat t, GLfloat r)
1059 jwzgles_glTexCoord4f (s, t, r, 1);
1064 jwzgles_glTexCoord2f (GLfloat s, GLfloat t)
1066 jwzgles_glTexCoord4f (s, t, 0, 1);
1071 jwzgles_glTexCoord1f (GLfloat s)
1073 jwzgles_glTexCoord4f (s, 0, 0, 1);
1077 /* glColor: GLfloat */
1080 jwzgles_glColor4fv (const GLfloat *v)
1082 if (state->compiling_list && !state->compiling_verts)
1089 list_push ("glColor4f", (list_fn_cb) &jwzgles_glColor4f,
1094 if (!state->replaying_list)
1095 LOG6 ("%s%sglColor4f %7.3f %7.3f %7.3f %7.3f",
1096 (state->compiling_list || state->replaying_list ? " " : ""),
1097 (state->compiling_verts ? " rec " : ""),
1098 v[0], v[1], v[2], v[3]);
1100 if (state->compiling_verts) /* inside glBegin */
1102 state->set.ccolor.r = v[0];
1103 state->set.ccolor.g = v[1];
1104 state->set.ccolor.b = v[2];
1105 state->set.ccolor.a = v[3];
1106 state->set.ccount++;
1107 if (state->set.count > 0 && state->set.ccount == 1) /* not first! */
1108 state->set.ccount++;
1110 else /* outside glBegin */
1112 glColor4f (v[0], v[1], v[2], v[3]);
1120 jwzgles_glColor4f (GLfloat r, GLfloat g, GLfloat b, GLfloat a)
1127 jwzgles_glColor4fv (v);
1131 jwzgles_glColor3f (GLfloat r, GLfloat g, GLfloat b)
1133 jwzgles_glColor4f (r, g, b, 1);
1137 jwzgles_glColor3fv (const GLfloat *v)
1139 jwzgles_glColor3f (v[0], v[1], v[2]);
1143 /* glColor: GLdouble */
1146 jwzgles_glColor4d (GLdouble r, GLdouble g, GLdouble b, GLdouble a)
1148 jwzgles_glColor4f (r, g, b, a);
1152 jwzgles_glColor4dv (const GLdouble *v)
1154 jwzgles_glColor4d (v[0], v[1], v[2], v[3]);
1158 jwzgles_glColor3d (GLdouble r, GLdouble g, GLdouble b)
1160 jwzgles_glColor4d (r, g, b, 1.0);
1164 jwzgles_glColor3dv (const GLdouble *v)
1166 jwzgles_glColor3d (v[0], v[1], v[2]);
1170 /* glColor: GLint (INT_MIN - INT_MAX) */
1173 jwzgles_glColor4i (GLint r, GLint g, GLint b, GLint a)
1175 /* -0x8000000 - 0x7FFFFFFF => 0.0 - 1.0 */
1176 jwzgles_glColor4f (0.5 + (GLfloat) r / 0xFFFFFFFF,
1177 0.5 + (GLfloat) g / 0xFFFFFFFF,
1178 0.5 + (GLfloat) b / 0xFFFFFFFF,
1179 0.5 + (GLfloat) a / 0xFFFFFFFF);
1183 jwzgles_glColor4iv (const GLint *v)
1185 jwzgles_glColor4i (v[0], v[1], v[2], v[3]);
1190 jwzgles_glColor3i (GLint r, GLint g, GLint b)
1192 jwzgles_glColor4i (r, g, b, 0x7FFFFFFF);
1196 jwzgles_glColor3iv (const GLint *v)
1198 jwzgles_glColor3i (v[0], v[1], v[2]);
1202 /* glColor: GLuint (0 - UINT_MAX) */
1205 jwzgles_glColor4ui (GLuint r, GLuint g, GLuint b, GLuint a)
1207 /* 0 - 0xFFFFFFFF => 0.0 - 1.0 */
1208 jwzgles_glColor4f ((GLfloat) r / 0xFFFFFFFF,
1209 (GLfloat) g / 0xFFFFFFFF,
1210 (GLfloat) b / 0xFFFFFFFF,
1211 (GLfloat) a / 0xFFFFFFFF);
1215 jwzgles_glColor4uiv (const GLuint *v)
1217 jwzgles_glColor4ui (v[0], v[1], v[2], v[3]);
1221 jwzgles_glColor3ui (GLuint r, GLuint g, GLuint b)
1223 jwzgles_glColor4ui (r, g, b, 0xFFFFFFFF);
1227 jwzgles_glColor3uiv (const GLuint *v)
1229 jwzgles_glColor3ui (v[0], v[1], v[2]);
1233 /* glColor: GLshort (SHRT_MIN - SHRT_MAX) */
1236 jwzgles_glColor4s (GLshort r, GLshort g, GLshort b, GLshort a)
1238 /* -0x8000 - 0x7FFF => 0.0 - 1.0 */
1239 jwzgles_glColor4f (0.5 + (GLfloat) r / 0xFFFF,
1240 0.5 + (GLfloat) g / 0xFFFF,
1241 0.5 + (GLfloat) b / 0xFFFF,
1242 0.5 + (GLfloat) a / 0xFFFF);
1246 jwzgles_glColor4sv (const GLshort *v)
1248 jwzgles_glColor4s (v[0], v[1], v[2], v[3]);
1252 jwzgles_glColor3s (GLshort r, GLshort g, GLshort b)
1254 jwzgles_glColor4s (r, g, b, 0x7FFF);
1258 jwzgles_glColor3sv (const GLshort *v)
1260 jwzgles_glColor3s (v[0], v[1], v[2]);
1264 /* glColor: GLushort (0 - USHRT_MAX) */
1267 jwzgles_glColor4us (GLushort r, GLushort g, GLushort b, GLushort a)
1269 /* 0 - 0xFFFF => 0.0 - 1.0 */
1270 jwzgles_glColor4f ((GLfloat) r / 0xFFFF,
1271 (GLfloat) g / 0xFFFF,
1272 (GLfloat) b / 0xFFFF,
1273 (GLfloat) a / 0xFFFF);
1277 jwzgles_glColor4usv (const GLushort *v)
1279 jwzgles_glColor4us (v[0], v[1], v[2], v[3]);
1283 jwzgles_glColor3us (GLushort r, GLushort g, GLushort b)
1285 jwzgles_glColor4us (r, g, b, 0xFFFF);
1289 jwzgles_glColor3usv (const GLushort *v)
1291 jwzgles_glColor3us (v[0], v[1], v[2]);
1295 /* glColor: GLbyte (-128 - 127) */
1298 jwzgles_glColor4b (GLbyte r, GLbyte g, GLbyte b, GLbyte a)
1300 /* -128 - 127 => 0.0 - 1.0 */
1301 jwzgles_glColor4f (0.5 + (GLfloat) r / 255,
1302 0.5 + (GLfloat) g / 255,
1303 0.5 + (GLfloat) b / 255,
1304 0.5 + (GLfloat) a / 255);
1308 jwzgles_glColor4bv (const GLbyte *v)
1310 jwzgles_glColor4b (v[0], v[1], v[2], v[3]);
1314 jwzgles_glColor3b (GLbyte r, GLbyte g, GLbyte b)
1316 jwzgles_glColor4b (r, g, b, 127);
1320 jwzgles_glColor3bv (const GLbyte *v)
1322 jwzgles_glColor3b (v[0], v[1], v[2]);
1326 /* glColor: GLubyte (0 - 255) */
1329 jwzgles_glColor4ub (GLubyte r, GLubyte g, GLubyte b, GLubyte a)
1331 /* 0 - 255 => 0.0 - 1.0 */
1332 jwzgles_glColor4f (r / 255.0, g / 255.0, b / 255.0, a / 255.0);
1336 jwzgles_glColor4ubv (const GLubyte *v)
1338 jwzgles_glColor4ub (v[0], v[1], v[2], v[3]);
1342 jwzgles_glColor3ub (GLubyte r, GLubyte g, GLubyte b)
1344 jwzgles_glColor4ub (r, g, b, 255);
1348 jwzgles_glColor3ubv (const GLubyte *v)
1350 jwzgles_glColor3ub (v[0], v[1], v[2]);
1356 jwzgles_glMaterialfv (GLenum face, GLenum pname, const GLfloat *color)
1358 /* If this is called inside glBegin/glEnd with a front ambient color,
1359 then treat it the same as glColor: set the color of the upcoming
1362 Other faces or lighting types within glBegin are ignored.
1365 if (state->compiling_verts)
1367 if ((face == GL_FRONT ||
1368 face == GL_FRONT_AND_BACK) &&
1369 (pname == GL_AMBIENT ||
1370 pname == GL_DIFFUSE ||
1371 pname == GL_AMBIENT_AND_DIFFUSE))
1373 jwzgles_glColor4f (color[0], color[1], color[2], color[3]);
1374 state->set.materialistic++;
1377 LOG2 (" IGNORING glMaterialfv %s %s",
1378 mode_desc(face), mode_desc(pname));
1380 else if (state->compiling_list)
1389 list_push ("glMaterialfv", (list_fn_cb) &jwzgles_glMaterialfv,
1394 /* If this is called outside of glBegin/glEnd with a front
1395 ambient color, then the intent is presumably for that color
1396 to apply to the upcoming vertexes (which may be played back
1397 from a list that does not have vertex colors in it). In that
1398 case, the only way to make the colors show up is to call
1399 glColor() with GL_COLOR_MATERIAL enabled.
1401 I'm not sure if this will have other inappropriate side effects...
1403 if ((face == GL_FRONT ||
1404 face == GL_FRONT_AND_BACK) &&
1405 (pname == GL_AMBIENT ||
1406 pname == GL_DIFFUSE ||
1407 pname == GL_AMBIENT_AND_DIFFUSE))
1409 jwzgles_glEnable (GL_COLOR_MATERIAL);
1410 jwzgles_glColor4f (color[0], color[1], color[2], color[3]);
1413 /* OpenGLES seems to throw "invalid enum" for GL_FRONT -- but it
1414 goes ahead and sets the material anyway! No error if we just
1415 always use GL_FRONT_AND_BACK.
1417 if (face == GL_FRONT)
1418 face = GL_FRONT_AND_BACK;
1419 if (! state->replaying_list)
1420 LOG7 ("direct %-12s %s %s %7.3f %7.3f %7.3f %7.3f", "glMaterialfv",
1421 mode_desc(face), mode_desc(pname),
1422 color[0], color[1], color[2], color[3]);
1423 glMaterialfv (face, pname, color); /* the real one */
1424 CHECK("glMaterialfv");
1430 jwzgles_glMaterialiv (GLenum face, GLenum pname, const GLint *v)
1437 jwzgles_glMaterialfv (face, pname, vv);
1441 jwzgles_glMaterialf (GLenum face, GLenum pname, const GLfloat c)
1448 jwzgles_glMaterialfv (face, pname, vv);
1453 jwzgles_glMateriali (GLenum face, GLenum pname, const GLuint c)
1455 jwzgles_glMaterialf (face, pname, c);
1460 jwzgles_glColorMaterial (GLenum face, GLenum mode)
1462 Assert (!state->compiling_verts,
1463 "glColorMaterial not allowed inside glBegin");
1465 if (state->compiling_list)
1470 list_push ("glColorMaterial", (list_fn_cb) &jwzgles_glColorMaterial,
1475 /* No real analog to this distinction in OpenGLES, since color
1476 arrays don't distinguish between "color" and "material", */
1477 Assert (0, "glColorMaterial: unimplemented mode");
1486 jwzgles_glVertex4fv (const GLfloat *v)
1488 vert_set *s = &state->set;
1489 int count = s->count;
1491 Assert (state->compiling_verts, "glVertex4fv not inside glBegin");
1493 LOG5("%s rec glVertex4f %7.3f %7.3f %7.3f %7.3f",
1494 (state->compiling_list || state->replaying_list ? " " : ""),
1495 v[0], v[1], v[2], v[3]);
1497 if (count >= s->size - 1)
1499 int new_size = 20 + (s->size * 1.2);
1501 /* 4 arrays, different element sizes...
1502 We allocate all 4 arrays just in case we need them,
1503 but we might not end up using them all at the end.
1506 s->verts = (XYZW *) realloc (s->verts, new_size * sizeof (*s->verts));
1507 Assert (s->verts, "out of memory");
1509 s->norms = (XYZ *) realloc (s->norms, new_size * sizeof (*s->norms));
1510 Assert (s->norms, "out of memory");
1512 s->tex = (STRQ *) realloc (s->tex, new_size * sizeof (*s->tex));
1513 Assert (s->tex, "out of memory");
1515 s->color = (RGBA *) realloc (s->color, new_size * sizeof (*s->color));
1516 Assert (s->color, "out of memory");
1521 s->verts [count].x = v[0];
1522 s->verts [count].y = v[1];
1523 s->verts [count].z = v[2];
1524 s->verts [count].w = v[3];
1525 s->norms [count] = s->cnorm;
1526 s->tex [count] = s->ctex;
1527 s->color [count] = s->ccolor;
1533 jwzgles_glVertex4f (GLfloat x, GLfloat y, GLfloat z, GLfloat w)
1540 jwzgles_glVertex4fv (v);
1544 jwzgles_glVertex4i (GLint x, GLint y, GLint z, GLint w)
1546 jwzgles_glVertex4f (x, y, z, w);
1550 jwzgles_glVertex3f (GLfloat x, GLfloat y, GLfloat z)
1557 jwzgles_glVertex4fv (v);
1561 jwzgles_glVertex3i (GLint x, GLint y, GLint z)
1563 jwzgles_glVertex3f (x, y, z);
1567 jwzgles_glVertex3fv (const GLfloat *v)
1569 jwzgles_glVertex3f (v[0], v[1], v[2]);
1573 jwzgles_glVertex3dv (const GLdouble *v)
1575 jwzgles_glVertex3f (v[0], v[1], v[2]);
1580 jwzgles_glVertex2f (GLfloat x, GLfloat y)
1586 jwzgles_glVertex3fv (v);
1590 jwzgles_glVertex2fv (const GLfloat *v)
1592 jwzgles_glVertex2f (v[0], v[1]);
1596 jwzgles_glVertex2i (GLint x, GLint y)
1598 jwzgles_glVertex2f (x, y);
1603 jwzgles_glLightiv (GLenum light, GLenum pname, const GLint *params)
1610 jwzgles_glLightfv (light, pname, v);
1614 jwzgles_glLightModeliv (GLenum pname, const GLint *params)
1621 jwzgles_glLightModelfv (pname, v);
1625 jwzgles_glFogiv (GLenum pname, const GLint *params)
1632 jwzgles_glFogfv (pname, v);
1636 jwzgles_glLighti (GLenum light, GLenum pname, GLint param)
1638 jwzgles_glLightf (light, pname, param);
1642 jwzgles_glLightModeli (GLenum pname, GLint param)
1644 jwzgles_glLightModelf (pname, param);
1648 jwzgles_glFogi (GLenum pname, GLint param)
1650 jwzgles_glFogf (pname, param);
1655 jwzgles_glRotated (GLdouble angle, GLdouble x, GLdouble y, GLdouble z)
1657 jwzgles_glRotatef (angle, x, y, z);
1662 jwzgles_glClipPlane (GLenum plane, const GLdouble *equation)
1664 Assert (state->compiling_verts, "glClipPlane not inside glBegin");
1665 Assert (0, "glClipPlane unimplemented"); /* no GLES equivalent... */
1670 jwzgles_glPolygonMode (GLenum face, GLenum mode)
1672 Assert (!state->compiling_verts, "not inside glBegin");
1673 if (state->compiling_list)
1678 list_push ("glPolygonMode", (list_fn_cb) &jwzgles_glPolygonMode,
1683 /* POINT and LINE don't exist in GLES */
1684 Assert (mode == GL_FILL, "glPolygonMode: unimplemented mode");
1690 jwzgles_glDrawBuffer (GLenum buf)
1692 Assert (!state->compiling_verts, "not inside glBegin");
1693 if (state->compiling_list)
1697 list_push ("glDrawBuffer", (list_fn_cb) &jwzgles_glDrawBuffer,
1702 /* Assert (buf == GL_BACK, "glDrawBuffer: back buffer only"); */
1703 # ifndef GL_VERSION_ES_CM_1_0 /* not compiling against OpenGLES 1.x */
1704 if (! state->replaying_list)
1705 LOG1 ("direct %-12s", "glDrawBuffer");
1706 glDrawBuffer (buf); /* the real one */
1707 CHECK("glDrawBuffer");
1713 /* Given an array of sets of 4 elements of arbitrary size, convert it
1714 to an array of sets of 6 elements instead: ABCD becomes ABC BCD.
1717 cq2t (unsigned char **arrayP, int stride, int count)
1719 int count2 = count * 6 / 4;
1720 int size = stride * count;
1721 int size2 = stride * count2;
1722 const unsigned char *oarray, *in;
1723 unsigned char *array2, *oarray2, *out;
1727 if (!oarray || count == 0)
1730 array2 = (unsigned char *) malloc (size2);
1731 Assert (array2, "out of memory");
1736 for (i = 0; i < count / 4; i++)
1738 const unsigned char *a, *b, *c, *d; /* the 4 corners */
1739 a = in; in += stride;
1740 b = in; in += stride;
1741 c = in; in += stride;
1742 d = in; in += stride;
1744 # define PUSH(IN) do { \
1745 const unsigned char *ii = IN; \
1747 for (j = 0; j < stride; j++) { \
1751 PUSH (a); PUSH (b); PUSH (d); /* the 2 triangles */
1752 PUSH (b); PUSH (c); PUSH (d);
1756 Assert (in == oarray + size, "convert_quads corrupted");
1757 Assert (out == oarray2 + size2, "convert_quads corrupted");
1765 /* Convert all coordinates in a GL_QUADS vert_set to GL_TRIANGLES.
1768 convert_quads_to_triangles (vert_set *s)
1771 Assert (s->mode == GL_QUADS, "convert_quads bad mode");
1773 cq2t ((unsigned char **) &s->verts, sizeof(*s->verts), s->count);
1774 cq2t ((unsigned char **) &s->norms, sizeof(*s->norms), s->count);
1775 cq2t ((unsigned char **) &s->tex, sizeof(*s->tex), s->count);
1776 cq2t ((unsigned char **) &s->color, sizeof(*s->color), s->count);
1779 s->mode = GL_TRIANGLES;
1784 jwzgles_glEnd (void)
1786 vert_set *s = &state->set;
1787 int was_norm, was_tex, was_color, was_mat;
1788 int is_norm, is_tex, is_color, is_mat;
1790 Assert (state->compiling_verts == 1, "missing glBegin");
1791 state->compiling_verts--;
1793 Assert (!state->replaying_list, "how did glEnd get into a display list?");
1795 if (!state->replaying_list)
1797 LOG5 ("%s [V = %d, N = %d, T = %d, C = %d]",
1798 (state->compiling_list || state->replaying_list ? " " : ""),
1799 s->count, s->ncount, s->tcount, s->ccount);
1801 (state->compiling_list || state->replaying_list ? " " : ""));
1804 if (s->count == 0) return;
1806 if (s->mode == GL_QUADS)
1807 convert_quads_to_triangles (s);
1808 else if (s->mode == GL_QUAD_STRIP)
1809 s->mode = GL_TRIANGLE_STRIP; /* They do the same thing! */
1810 else if (s->mode == GL_POLYGON)
1811 s->mode = GL_TRIANGLE_FAN; /* They do the same thing! */
1813 jwzgles_glColorPointer (4,GL_FLOAT, sizeof(*s->color),s->color); /* RGBA */
1814 jwzgles_glNormalPointer ( GL_FLOAT, sizeof(*s->norms),s->norms); /* XYZ */
1815 jwzgles_glTexCoordPointer(4,GL_FLOAT, sizeof(*s->tex), s->tex); /* STRQ */
1816 jwzgles_glVertexPointer (4,GL_FLOAT, sizeof(*s->verts),s->verts); /* XYZW */
1817 /* glVertexPointer must come after glTexCoordPointer */
1819 /* If there were no calls to glNormal3f inside of glBegin/glEnd,
1820 don't bother enabling the normals array.
1822 If there was exactly *one* call to glNormal3f inside of glBegin/glEnd,
1823 and it was before the first glVertex3f, then also don't enable the
1824 normals array, but do emit that call to glNormal3f before calling
1827 Likewise for texture coordinates and colors.
1829 Be careful to leave the arrays' enabled/disabled state the same as
1830 before, or a later caller might end up using one of our arrays by
1831 mistake. (Remember that jwzgles_glIsEnabled() tracks the enablement
1832 of the list-in-progress as well as the global state.)
1834 was_norm = jwzgles_glIsEnabled (GL_NORMAL_ARRAY);
1835 was_tex = jwzgles_glIsEnabled (GL_TEXTURE_COORD_ARRAY);
1836 was_color = jwzgles_glIsEnabled (GL_COLOR_ARRAY);
1837 was_mat = jwzgles_glIsEnabled (GL_COLOR_MATERIAL);
1839 /* If we're executing glEnd in immediate mode, not from inside a display
1840 list (which is the only way it happens, because glEnd doesn't go into
1841 display lists), make sure we're not stomping on a saved buffer list:
1842 in immediate mode, vertexes are client-side only.
1844 if (! state->compiling_list)
1845 jwzgles_glBindBuffer (GL_ARRAY_BUFFER, 0);
1850 jwzgles_glEnableClientState (GL_NORMAL_ARRAY);
1856 jwzgles_glNormal3f (s->cnorm.x, s->cnorm.y, s->cnorm.z);
1857 jwzgles_glDisableClientState (GL_NORMAL_ARRAY);
1860 if (s->tcount > 1 ||
1861 ((state->compiling_list ? state->list_enabled : state->enabled)
1862 & (ISENABLED_TEXTURE_GEN_S | ISENABLED_TEXTURE_GEN_T |
1863 ISENABLED_TEXTURE_GEN_R | ISENABLED_TEXTURE_GEN_Q)))
1865 /* Enable texture coords if any were specified; or if generation
1866 is on in immediate mode; or if this list turned on generation. */
1868 jwzgles_glEnableClientState (GL_TEXTURE_COORD_ARRAY);
1874 jwzgles_glTexCoord4f (s->ctex.s, s->ctex.t, s->ctex.r, s->ctex.q);
1875 jwzgles_glDisableClientState (GL_TEXTURE_COORD_ARRAY);
1881 jwzgles_glEnableClientState (GL_COLOR_ARRAY);
1887 jwzgles_glColor4f (s->ccolor.r, s->ccolor.g, s->ccolor.b, s->ccolor.a);
1888 jwzgles_glDisableClientState (GL_COLOR_ARRAY);
1891 jwzgles_glEnableClientState (GL_VERTEX_ARRAY);
1893 /* We translated the glMaterial calls to per-vertex colors, which are
1894 of the glColor sort, not the glMaterial sort, so automatically
1895 turn on material mapping. Maybe this is a bad idea.
1897 if (s->materialistic && !jwzgles_glIsEnabled (GL_COLOR_MATERIAL))
1900 jwzgles_glEnable (GL_COLOR_MATERIAL);
1905 glBindBuffer (GL_ARRAY_BUFFER, 0); /* This comes later. */
1906 jwzgles_glDrawArrays (s->mode, 0, s->count);
1907 glBindBuffer (GL_ARRAY_BUFFER, 0); /* Keep out of others' hands */
1909 # define RESET(VAR,FN,ARG) do { \
1910 if (is_##VAR != was_##VAR) { \
1911 if (was_##VAR) jwzgles_glEnable##FN (ARG); \
1912 else jwzgles_glDisable##FN (ARG); \
1914 RESET (norm, ClientState, GL_NORMAL_ARRAY);
1915 RESET (tex, ClientState, GL_TEXTURE_COORD_ARRAY);
1916 RESET (color, ClientState, GL_COLOR_ARRAY);
1917 RESET (mat, , GL_COLOR_MATERIAL);
1924 s->materialistic = 0;
1928 /* The display list is full of calls to glDrawArrays(), plus saved arrays
1929 of the values we need to restore before calling it. "Restore" means
1930 "ship them off to the GPU before each call".
1932 So instead, this function walks through the display list and
1933 combines all of those vertex, normal, texture and color values into
1934 a single VBO array; ships those values off to the GPU *once* at the
1935 time of glEndList; and when running the list with glCallList, the
1936 values are already on the GPU and don't need to be sent over again.
1938 The VBO persists in the GPU until the display list is deleted.
1941 optimize_arrays (void)
1943 list *L = &state->lists.lists[state->compiling_list-1];
1946 int combo_count = 0;
1948 GLuint buf_name = 0;
1950 Assert (state->compiling_list, "not compiling a list");
1951 Assert (L, "no list");
1952 Assert (!L->buffer, "list already has a buffer");
1954 glGenBuffers (1, &buf_name);
1955 CHECK("glGenBuffers");
1956 if (! buf_name) return;
1958 L->buffer = buf_name;
1960 /* Go through the list and dump the contents of the various saved arrays
1961 into one large array.
1963 for (i = 0; i < L->count; i++)
1965 list_fn *F = &L->fns[i];
1969 /* count = F->argv[2].i;*/ /* 3rd arg to glDrawArrays */
1971 for (j = 0; j < 4; j++)
1973 draw_array *A = &F->arrays[j];
1974 int ocount = combo_count;
1976 /* If some caller is using arrays that don't have floats in them,
1977 we just leave them as-is and ship them over at each call.
1978 Doubt this ever really happens.
1980 if (A->type != GL_FLOAT)
1983 if (! A->data) /* No array. */
1986 Assert (A->bytes > 0, "no bytes in draw_array");
1987 Assert (((unsigned long) A->data > 0xFFFF),
1988 "buffer data not a pointer");
1990 combo_count += A->bytes / sizeof(*combo);
1991 make_room ("optimize_arrays",
1992 (void **) &combo, sizeof(*combo),
1993 &combo_count, &combo_size);
1994 memcpy (combo + ocount, A->data, A->bytes);
1995 A->binding = buf_name;
1997 /* 'data' is now the byte offset into the VBO. */
1998 A->data = (void *) (ocount * sizeof(*combo));
1999 /* LOG3(" loaded %lu floats to pos %d of buffer %d",
2000 A->bytes / sizeof(*combo), ocount, buf_name); */
2004 if (combo_count == 0) /* Nothing to do! */
2006 if (combo) free (combo);
2007 glDeleteBuffers (1, &buf_name);
2012 glBindBuffer (GL_ARRAY_BUFFER, buf_name);
2013 glBufferData (GL_ARRAY_BUFFER,
2014 combo_count * sizeof (*combo),
2017 glBindBuffer (GL_ARRAY_BUFFER, 0); /* Keep out of others' hands */
2019 LOG3(" loaded %d floats of list %d into VBO %d",
2020 combo_count, state->compiling_list, buf_name);
2024 for (i = 0; i < combo_count; i++)
2027 fprintf (stderr, "\njwzgles: %4d: ", i);
2028 fprintf (stderr, " %7.3f", combo[i]);
2030 fprintf (stderr, "\n");
2034 if (combo) free (combo);
2039 jwzgles_glCallList (int id)
2041 if (state->compiling_list)
2043 /* Yes, you can call lists inside of lists.
2044 Yes, recursion would be a mistake. */
2047 list_push ("glCallList", (list_fn_cb) &jwzgles_glCallList, PROTO_I, vv);
2054 state->replaying_list++;
2057 fprintf (stderr, "\n");
2058 LOG1 ("glCallList %d", id);
2061 Assert (id > 0 && id <= state->lists.count, "glCallList: bogus ID");
2062 L = &state->lists.lists[id-1];
2063 Assert (id == L->id, "glCallList corrupted");
2065 for (i = 0; i < L->count; i++)
2067 list_fn *F = &L->fns[i];
2068 list_fn_cb fn = F->fn;
2069 void_int *av = F->argv;
2073 LOG1 (" call %-12s", F->name);
2074 ((void (*) (void)) fn) ();
2078 if (fn == (list_fn_cb) &jwzgles_glBegin ||
2079 fn == (list_fn_cb) &jwzgles_glFrontFace ||
2080 fn == (list_fn_cb) &jwzgles_glEnable ||
2081 fn == (list_fn_cb) &jwzgles_glDisable ||
2082 fn == (list_fn_cb) &jwzgles_glEnableClientState ||
2083 fn == (list_fn_cb) &jwzgles_glDisableClientState ||
2084 fn == (list_fn_cb) &jwzgles_glShadeModel ||
2085 fn == (list_fn_cb) &jwzgles_glMatrixMode)
2086 LOG2 (" call %-12s %s", F->name, mode_desc (av[0].i));
2088 LOG2 (" call %-12s %d", F->name, av[0].i);
2089 ((void (*) (int)) fn) (av[0].i);
2093 LOG2 (" call %-12s %7.3f", F->name, av[0].f);
2094 ((void (*) (GLfloat)) fn) (av[0].f);
2098 if (fn == (list_fn_cb) &jwzgles_glBindTexture ||
2099 fn == (list_fn_cb) &jwzgles_glBindBuffer)
2100 LOG3 (" call %-12s %s %d", F->name,
2101 mode_desc (av[0].i), av[1].i);
2103 LOG3 (" call %-12s %d %d", F->name, av[0].i, av[1].i);
2104 ((void (*) (int, int)) fn) (av[0].i, av[1].i);
2108 LOG3 (" call %-12s %7.3f %7.3f", F->name, av[0].f, av[1].f);
2109 ((void (*) (GLfloat, GLfloat)) fn) (av[0].f, av[1].f);
2113 LOG3 (" call %-12s %s %7.3f", F->name,
2114 mode_desc (av[0].f), av[1].f);
2115 ((void (*) (GLint, GLfloat)) fn) (av[0].i, av[1].f);
2118 case PROTO_III: III:
2119 if (fn == (list_fn_cb) &jwzgles_glDrawArrays ||
2120 fn == (list_fn_cb) &jwzgles_glTexParameteri)
2121 LOG4 (" call %-12s %s %d %d", F->name,
2122 mode_desc (av[0].i), av[1].i, av[2].i);
2124 LOG4 (" call %-12s %d %d %d", F->name,
2125 av[0].i, av[1].i, av[2].i);
2126 ((void (*) (int, int, int)) fn) (av[0].i, av[1].i, av[2].i);
2130 LOG4 (" call %-12s %7.3f %7.3f %7.3f", F->name,
2131 av[0].f, av[1].f, av[2].f);
2132 ((void (*) (GLfloat, GLfloat, GLfloat)) fn)
2133 (av[0].f, av[1].f, av[2].f);
2137 LOG4 (" call %-12s %s %s %7.3f", F->name,
2138 mode_desc (av[0].i), mode_desc (av[1].i), av[2].f);
2139 ((void (*) (int, int, GLfloat)) fn) (av[0].i, av[1].i, av[2].f);
2143 LOG5 (" call %-12s %d %d %d %d", F->name,
2144 av[0].i, av[1].i, av[2].i, av[3].i);
2145 ((void (*) (int, int, int, int)) fn)
2146 (av[0].i, av[1].i, av[2].i, av[3].i);
2150 LOG5 (" call %-12s %7.3f %7.3f %7.3f %7.3f", F->name,
2151 av[0].f, av[1].f, av[2].f, av[3].f);
2152 ((void (*) (GLfloat, GLfloat, GLfloat, GLfloat)) fn)
2153 (av[0].f, av[1].f, av[2].f, av[3].f);
2163 LOG6 (" call %-12s %s %3.1f %3.1f %3.1f %3.1f", F->name,
2164 mode_desc (av[0].i),
2165 av[1].f, av[2].f, av[3].f, av[4].f);
2166 ((void (*) (int, const GLfloat *)) fn) (av[0].i, v);
2177 LOG7 (" call %-12s %s %-8s %3.1f %3.1f %3.1f %3.1f", F->name,
2178 mode_desc (av[0].i), mode_desc (av[1].i),
2179 av[2].f, av[3].f, av[4].f, av[5].f);
2180 ((void (*) (int, int, const GLfloat *)) fn)
2181 (av[0].i, av[1].i, v);
2192 LOG6 (" call %-12s %s %3d %3d %3d %3d", F->name,
2193 mode_desc (av[0].i),
2194 av[1].i, av[2].i, av[3].i, av[4].i);
2195 ((void (*) (int, const int *)) fn) (av[0].i, v);
2206 LOG7 (" call %-12s %s %-8s %3d %3d %3d %3d", F->name,
2207 mode_desc (av[0].i), mode_desc (av[1].i),
2208 av[2].i, av[3].i, av[4].i, av[5].i);
2209 ((void (*) (int, int, const int *)) fn)
2210 (av[0].i, av[1].i, v);
2215 restore_arrays (F, av[1].i + av[2].i);
2223 for (i = 0; i < countof(m); i++)
2225 LOG17 (" call %-12s ["
2226 "%8.3f %8.3f %8.3f %8.3f " "\n\t\t\t "
2227 "%8.3f %8.3f %8.3f %8.3f " "\n\t\t\t "
2228 "%8.3f %8.3f %8.3f %8.3f " "\n\t\t\t "
2229 "%8.3f %8.3f %8.3f %8.3f ]",
2231 m[0], m[1], m[2], m[3],
2232 m[4], m[5], m[6], m[7],
2233 m[8], m[9], m[10], m[11],
2234 m[12], m[13], m[14], m[15]);
2235 ((void (*) (GLfloat *)) fn) (m);
2240 Assert (0, "bogus prototype");
2245 LOG1 ("glCallList %d done\n", id);
2247 state->replaying_list--;
2248 Assert (state->replaying_list >= 0, "glCallList corrupted");
2253 /* When we save a call to glDrawArrays into a display list, we also need to
2254 save the prevailing copy of the arrays that it will use, and restore them
2258 save_arrays (list_fn *F, int count)
2261 draw_array *A = (draw_array *) calloc (4, sizeof (*A));
2262 Assert (A, "out of memory");
2264 /* if (state->set.count > 0) */
2266 glGetIntegerv (GL_VERTEX_ARRAY_BUFFER_BINDING, &A[i].binding);
2267 glGetIntegerv (GL_VERTEX_ARRAY_SIZE, &A[i].size);
2268 glGetIntegerv (GL_VERTEX_ARRAY_TYPE, &A[i].type);
2269 glGetIntegerv (GL_VERTEX_ARRAY_STRIDE, &A[i].stride);
2270 glGetPointerv (GL_VERTEX_ARRAY_POINTER, &A[i].data);
2271 CHECK("glGetPointerv");
2272 copy_array_data (&A[i], count, "vert");
2276 if (state->set.ncount > 1)
2279 glGetIntegerv (GL_NORMAL_ARRAY_BUFFER_BINDING, &A[i].binding);
2280 glGetIntegerv (GL_NORMAL_ARRAY_TYPE, &A[i].type);
2281 glGetIntegerv (GL_NORMAL_ARRAY_STRIDE, &A[i].stride);
2282 glGetPointerv (GL_NORMAL_ARRAY_POINTER, &A[i].data);
2283 CHECK("glGetPointerv");
2284 copy_array_data (&A[i], count, "norm");
2288 if (state->set.tcount > 1)
2290 glGetIntegerv (GL_TEXTURE_COORD_ARRAY_BUFFER_BINDING, &A[i].binding);
2291 glGetIntegerv (GL_TEXTURE_COORD_ARRAY_SIZE, &A[i].size);
2292 glGetIntegerv (GL_TEXTURE_COORD_ARRAY_TYPE, &A[i].type);
2293 glGetIntegerv (GL_TEXTURE_COORD_ARRAY_STRIDE, &A[i].stride);
2294 glGetPointerv (GL_TEXTURE_COORD_ARRAY_POINTER, &A[i].data);
2295 CHECK("glGetPointerv");
2296 copy_array_data (&A[i], count, "tex ");
2300 if (state->set.ccount > 1)
2302 glGetIntegerv (GL_COLOR_ARRAY_BUFFER_BINDING, &A[i].binding);
2303 glGetIntegerv (GL_COLOR_ARRAY_SIZE, &A[i].size);
2304 glGetIntegerv (GL_COLOR_ARRAY_TYPE, &A[i].type);
2305 glGetIntegerv (GL_COLOR_ARRAY_STRIDE, &A[i].stride);
2306 glGetPointerv (GL_COLOR_ARRAY_POINTER, &A[i].data);
2307 CHECK("glGetPointerv");
2308 copy_array_data (&A[i], count, "col ");
2311 /* Freed by glDeleteLists. */
2313 Assert (!F->arrays, "save_arrays corrupted");
2321 dump_array_data (draw_array *A, int count,
2322 const char *action, const char *name, const void *old)
2324 int bytes = count * A->stride;
2329 "jwzgles: %s %s %d %s %2d, %4d = %5d bind %d @ %d\n",
2331 A->size, mode_desc(A->type), A->stride,
2332 count, bytes, A->binding, (int) A->data);
2336 Assert (bytes == A->bytes, "array data corrupted");
2338 fprintf (stderr, "jwzgles: %s %s %d %s %2d, %4d = %5d @ %lX",
2340 A->size, mode_desc(A->type), A->stride,
2341 count, bytes, (unsigned long) A->data);
2343 fprintf (stderr, " / %lX", (unsigned long) old);
2344 fprintf (stderr, "\n");
2349 Assert (((unsigned long) A->data < 0xFFFF),
2350 "buffer binding should be a numeric index,"
2351 " but looks like a pointer");
2354 /* glGetBufferSubData doesn't actually exist in OpenGLES, but this
2355 was helpful for debugging on real OpenGL... */
2358 fprintf (stderr, "jwzgles: read back:\n");
2359 d = (GLfloat *) malloc (A->bytes);
2360 glGetBufferSubData (GL_ARRAY_BUFFER, (int) A->data,
2361 count * A->stride, (void *) d);
2362 CHECK("glGetBufferSubData");
2363 for (i = 0; i < count * A->size; i++)
2366 fprintf (stderr, "\njwzgles: %4d: ",
2367 i + (int) A->data / sizeof(GLfloat));
2368 fprintf (stderr, " %7.3f", d[i]);
2370 fprintf (stderr, "\n");
2377 unsigned char *b = (unsigned char *) A->data;
2379 if ((unsigned long) A->data < 0xFFFF)
2381 Assert (0, "buffer data not a pointer");
2384 for (i = 0; i < count; i++)
2387 GLfloat *f = (GLfloat *) b;
2389 if (s == 0) s = 3; /* normals */
2390 fprintf (stderr, "jwzgles: ");
2391 for (j = 0; j < s; j++)
2392 fprintf (stderr, " %7.3f", f[j]);
2393 fprintf (stderr, "\n");
2401 dump_direct_array_data (int count)
2403 draw_array A = { 0, };
2405 if (jwzgles_glIsEnabled (GL_VERTEX_ARRAY))
2407 glGetIntegerv (GL_VERTEX_ARRAY_BUFFER_BINDING, &A.binding);
2408 glGetIntegerv (GL_VERTEX_ARRAY_SIZE, &A.size);
2409 glGetIntegerv (GL_VERTEX_ARRAY_TYPE, &A.type);
2410 glGetIntegerv (GL_VERTEX_ARRAY_STRIDE, &A.stride);
2411 glGetPointerv (GL_VERTEX_ARRAY_POINTER, &A.data);
2412 A.bytes = count * A.stride;
2413 dump_array_data (&A, count, "direct", "vertex ", 0);
2415 if (jwzgles_glIsEnabled (GL_NORMAL_ARRAY))
2418 glGetIntegerv (GL_NORMAL_ARRAY_BUFFER_BINDING, &A.binding);
2419 glGetIntegerv (GL_NORMAL_ARRAY_TYPE, &A.type);
2420 glGetIntegerv (GL_NORMAL_ARRAY_STRIDE, &A.stride);
2421 glGetPointerv (GL_NORMAL_ARRAY_POINTER, &A.data);
2422 A.bytes = count * A.stride;
2423 dump_array_data (&A, count, "direct", "normal ", 0);
2425 if (jwzgles_glIsEnabled (GL_TEXTURE_COORD_ARRAY))
2427 glGetIntegerv (GL_TEXTURE_COORD_ARRAY_BUFFER_BINDING, &A.binding);
2428 glGetIntegerv (GL_TEXTURE_COORD_ARRAY_SIZE, &A.size);
2429 glGetIntegerv (GL_TEXTURE_COORD_ARRAY_TYPE, &A.type);
2430 glGetIntegerv (GL_TEXTURE_COORD_ARRAY_STRIDE, &A.stride);
2431 glGetPointerv (GL_TEXTURE_COORD_ARRAY_POINTER, &A.data);
2432 A.bytes = count * A.stride;
2433 dump_array_data (&A, count, "direct", "texture", 0);
2435 if (jwzgles_glIsEnabled (GL_COLOR_ARRAY))
2437 glGetIntegerv (GL_COLOR_ARRAY_BUFFER_BINDING, &A.binding);
2438 glGetIntegerv (GL_COLOR_ARRAY_SIZE, &A.size);
2439 glGetIntegerv (GL_COLOR_ARRAY_TYPE, &A.type);
2440 glGetIntegerv (GL_COLOR_ARRAY_STRIDE, &A.stride);
2441 glGetPointerv (GL_COLOR_ARRAY_POINTER, &A.data);
2442 A.bytes = count * A.stride;
2443 dump_array_data (&A, count, "direct", "color ", 0);
2451 copy_array_data (draw_array *A, int count, const char *name)
2453 /* Instead of just memcopy'ing the whole array and obeying its previous
2454 'stride' value, we make up a more compact array. This is because if
2455 the same array data is being used with multiple component types,
2456 e.g. with glInterleavedArrays, we don't want to copy all of the
2457 data multiple times.
2459 int stride2, bytes, i, j;
2463 const unsigned char *IB;
2466 if (((unsigned long) A->data) < 0xFFFF)
2468 Assert (0, "buffer data not a pointer");
2472 Assert (A->size >= 2 && A->size <= 4, "bogus array size");
2475 case GL_FLOAT: stride2 = A->size * sizeof(GLfloat); break;
2476 case GL_UNSIGNED_BYTE: stride2 = A->size; break;
2477 default: Assert (0, "bogus array type"); break;
2480 bytes = count * stride2;
2481 Assert (bytes > 0, "bogus array count or stride");
2482 Assert (A->data, "missing array data");
2483 data2 = (void *) malloc (bytes);
2484 Assert (data2, "out of memory");
2486 IB = (const unsigned char *) A->data;
2487 OB = (unsigned char *) data2;
2488 IF = (const GLfloat *) A->data;
2489 OF = (GLfloat *) data2;
2493 for (i = 0; i < count; i++)
2495 for (j = 0; j < A->size; j++)
2497 IF = (const GLfloat *) (((const unsigned char *) IF) + A->stride);
2500 case GL_UNSIGNED_BYTE:
2501 for (i = 0; i < count; i++)
2503 for (j = 0; j < A->size; j++)
2509 Assert (0, "bogus array type");
2515 A->stride = stride2;
2518 dump_array_data (A, count, "saved", name, 0);
2524 restore_arrays (list_fn *F, int count)
2527 draw_array *A = F->arrays;
2528 Assert (A, "missing array");
2530 for (i = 0; i < 4; i++)
2532 const char *name = 0;
2537 Assert ((A[i].binding || A[i].data),
2538 "array has neither buffer binding nor data");
2540 glBindBuffer (GL_ARRAY_BUFFER, A[i].binding);
2541 CHECK("glBindBuffer");
2544 case 0: glVertexPointer (A[i].size, A[i].type, A[i].stride, A[i].data);
2546 CHECK("glVertexPointer");
2548 case 1: glNormalPointer ( A[i].type, A[i].stride, A[i].data);
2550 CHECK("glNormalPointer");
2552 case 2: glTexCoordPointer(A[i].size, A[i].type, A[i].stride, A[i].data);
2554 CHECK("glTexCoordPointer");
2556 case 3: glColorPointer (A[i].size, A[i].type, A[i].stride, A[i].data);
2558 CHECK("glColorPointer");
2560 default: Assert (0, "wat"); break;
2564 dump_array_data (&A[i], count, "restored", name, 0);
2568 glBindBuffer (GL_ARRAY_BUFFER, 0); /* Keep out of others' hands */
2573 jwzgles_glDrawArrays (GLuint mode, GLuint first, GLuint count)
2575 /* If we are auto-generating texture coordinates, do that now, after
2576 the vertex array was installed, but before drawing, This happens
2577 when recording into a list, or in direct mode. It must happen
2578 before calling optimize_arrays() from glEndList().
2580 if (! state->replaying_list &&
2581 ((state->compiling_list ? state->list_enabled : state->enabled)
2582 & (ISENABLED_TEXTURE_GEN_S | ISENABLED_TEXTURE_GEN_T |
2583 ISENABLED_TEXTURE_GEN_R | ISENABLED_TEXTURE_GEN_Q)))
2584 generate_texture_coords (first, count);
2586 if (state->compiling_list)
2592 list_push ("glDrawArrays", (list_fn_cb) &jwzgles_glDrawArrays,
2598 if (! state->replaying_list) {
2599 LOG4("direct %-12s %d %d %d", "glDrawArrays", mode, first, count);
2600 dump_direct_array_data (first + count);
2603 glDrawArrays (mode, first, count); /* the real one */
2604 CHECK("glDrawArrays");
2610 jwzgles_glInterleavedArrays (GLenum format, GLsizei stride, const void *data)
2612 /* We can implement this by calling the various *Pointer functions
2613 with offsets into the same data, taking advantage of stride.
2615 const unsigned char *c = (const unsigned char *) data;
2617 # define F sizeof(GLfloat)
2619 Assert (!state->compiling_verts,
2620 "glInterleavedArrays not allowed inside glBegin");
2622 jwzgles_glEnableClientState (GL_VERTEX_ARRAY);
2624 if (!state->replaying_list)
2625 LOG4 ("%sglInterleavedArrays %s %d %lX",
2626 (state->compiling_list || state->replaying_list ? " " : ""),
2627 mode_desc (format), stride, (unsigned long) data);
2631 glVertexPointer (2, GL_FLOAT, stride, c);
2632 CHECK("glVertexPointer");
2633 if (!state->replaying_list)
2634 LOG3 ("%s -> glVertexPointer 2 FLOAT %d %lX",
2635 (state->compiling_list || state->replaying_list ? " " : ""),
2636 stride, (unsigned long) c);
2639 glVertexPointer (3, GL_FLOAT, stride, c);
2640 CHECK("glVertexPointer");
2641 if (!state->replaying_list)
2642 LOG3 ("%s -> glVertexPointer 3 FLOAT %d %lX",
2643 (state->compiling_list || state->replaying_list ? " " : ""),
2644 stride, (unsigned long) c);
2649 jwzgles_glEnableClientState (GL_COLOR_ARRAY);
2650 glColorPointer (4, GL_UNSIGNED_BYTE, stride, c);
2651 CHECK("glColorPointer");
2652 c += 4*B; /* #### might be incorrect float-aligned address */
2653 glVertexPointer (2, GL_FLOAT, stride, c);
2658 jwzgles_glEnableClientState (GL_COLOR_ARRAY);
2659 glColorPointer (4, GL_UNSIGNED_BYTE, stride, c);
2660 CHECK("glColorPointer");
2662 glVertexPointer (3, GL_FLOAT, stride, c);
2663 CHECK("glVertexPointer");
2668 jwzgles_glEnableClientState (GL_COLOR_ARRAY);
2669 glColorPointer (3, GL_FLOAT, stride, c);
2670 CHECK("glColorPointer");
2672 glVertexPointer (3, GL_FLOAT, stride, c);
2673 CHECK("glVertexPointer");
2678 jwzgles_glEnableClientState (GL_NORMAL_ARRAY);
2679 glNormalPointer (GL_FLOAT, stride, c);
2680 CHECK("glNormalPointer");
2681 if (!state->replaying_list)
2682 LOG3 ("%s -> glNormalPointer FLOAT %d %lX",
2683 (state->compiling_list || state->replaying_list ? " " : ""),
2684 stride, (unsigned long) c);
2686 glVertexPointer (3, GL_FLOAT, stride, c);
2687 CHECK("glVertexPointer");
2688 if (!state->replaying_list)
2689 LOG3 ("%s -> glVertexPointer 3 FLOAT %d %lX",
2690 (state->compiling_list || state->replaying_list ? " " : ""),
2691 stride, (unsigned long) c);
2693 case GL_C4F_N3F_V3F:
2695 stride = 4*F + 3*F + 3*F;
2696 jwzgles_glEnableClientState (GL_COLOR_ARRAY);
2697 glColorPointer (4, GL_FLOAT, stride, c);
2698 CHECK("glColorPointer");
2700 jwzgles_glEnableClientState (GL_NORMAL_ARRAY);
2701 glNormalPointer (GL_FLOAT, stride, c);
2702 CHECK("glNormalPointer");
2704 glVertexPointer (3, GL_FLOAT, stride, c);
2705 CHECK("glVertexPointer");
2710 jwzgles_glEnableClientState (GL_TEXTURE_COORD_ARRAY);
2711 glTexCoordPointer (2, GL_FLOAT, stride, c);
2712 CHECK("glTexCoordPointer");
2714 glVertexPointer (3, GL_FLOAT, stride, c);
2715 CHECK("glVertexPointer");
2720 jwzgles_glEnableClientState (GL_TEXTURE_COORD_ARRAY);
2721 glTexCoordPointer (4, GL_FLOAT, stride, c);
2722 CHECK("glTexCoordPointer");
2724 glVertexPointer (4, GL_FLOAT, stride, c);
2725 CHECK("glVertexPointer");
2727 case GL_T2F_C4UB_V3F:
2729 stride = 2*F + 4*B + 3*F;
2730 jwzgles_glEnableClientState (GL_TEXTURE_COORD_ARRAY);
2731 glTexCoordPointer (2, GL_FLOAT, stride, c);
2732 CHECK("glTexCoordPointer");
2734 jwzgles_glEnableClientState (GL_COLOR_ARRAY);
2735 glColorPointer (4, GL_UNSIGNED_BYTE, stride, c);
2736 CHECK("glColorPointer");
2738 glVertexPointer (3, GL_FLOAT, stride, c);
2739 CHECK("glVertexPointer");
2741 case GL_T2F_C3F_V3F:
2743 stride = 2*F + 3*F + 3*F;
2744 jwzgles_glEnableClientState (GL_TEXTURE_COORD_ARRAY);
2745 glTexCoordPointer (2, GL_FLOAT, stride, c);
2746 CHECK("glTexCoordPointer");
2748 jwzgles_glEnableClientState (GL_COLOR_ARRAY);
2749 glColorPointer (3, GL_FLOAT, stride, c);
2750 CHECK("glColorPointer");
2752 glVertexPointer (3, GL_FLOAT, stride, c);
2753 CHECK("glVertexPointer");
2755 case GL_T2F_N3F_V3F:
2757 stride = 2*F + 3*F + 3*F;
2758 jwzgles_glEnableClientState (GL_TEXTURE_COORD_ARRAY);
2759 glTexCoordPointer (2, GL_FLOAT, stride, c);
2760 CHECK("glTexCoordPointer");
2762 jwzgles_glEnableClientState (GL_NORMAL_ARRAY);
2763 glNormalPointer (GL_FLOAT, stride, c);
2764 CHECK("glNormalPointer");
2766 glVertexPointer (3, GL_FLOAT, stride, c);
2767 CHECK("glVertexPointer");
2769 case GL_T2F_C4F_N3F_V3F:
2771 stride = 2*F + 4*F + 3*F + 3*F;
2772 jwzgles_glEnableClientState (GL_TEXTURE_COORD_ARRAY);
2773 glTexCoordPointer (2, GL_FLOAT, stride, c);
2774 CHECK("glTexCoordPointer");
2776 jwzgles_glEnableClientState (GL_COLOR_ARRAY);
2777 glColorPointer (3, GL_FLOAT, stride, c);
2778 CHECK("glColorPointer");
2780 jwzgles_glEnableClientState (GL_NORMAL_ARRAY);
2781 glNormalPointer (GL_FLOAT, stride, c);
2782 CHECK("glNormalPointer");
2784 glVertexPointer (3, GL_FLOAT, stride, c);
2785 CHECK("glVertexPointer");
2787 case GL_T4F_C4F_N3F_V4F:
2789 stride = 4*F + 4*F + 3*F + 4*F;
2790 jwzgles_glEnableClientState (GL_TEXTURE_COORD_ARRAY);
2791 glTexCoordPointer (4, GL_FLOAT, stride, c);
2792 CHECK("glTexCoordPointer");
2794 jwzgles_glEnableClientState (GL_COLOR_ARRAY);
2795 glColorPointer (4, GL_FLOAT, stride, c);
2796 CHECK("glColorPointer");
2798 jwzgles_glEnableClientState (GL_NORMAL_ARRAY);
2799 glNormalPointer (GL_FLOAT, stride, c);
2800 CHECK("glNormalPointer");
2802 glVertexPointer (3, GL_FLOAT, stride, c);
2803 CHECK("glVertexPointer");
2806 Assert (0, "glInterleavedArrays: bogus format");
2817 jwzgles_glMultMatrixf (const GLfloat *m)
2819 Assert (!state->compiling_verts,
2820 "glMultMatrixf not allowed inside glBegin");
2821 if (state->compiling_list)
2825 for (i = 0; i < countof(vv); i++)
2827 list_push ("glMultMatrixf", (list_fn_cb) &jwzgles_glMultMatrixf,
2832 if (! state->replaying_list)
2833 LOG1 ("direct %-12s", "glMultMatrixf");
2834 glMultMatrixf (m); /* the real one */
2835 CHECK("glMultMatrixf");
2841 jwzgles_glClearIndex(GLfloat c)
2843 /* Does GLES even do indexed color? */
2844 Assert (0, "glClearIndex unimplemented");
2849 jwzgles_glBitmap (GLsizei width, GLsizei height, GLfloat xorig, GLfloat yorig,
2850 GLfloat xmove, GLfloat ymove, const GLubyte *bitmap)
2852 Assert (0, "glBitmap unimplemented");
2856 jwzgles_glPushAttrib(int flags)
2858 Assert (0, "glPushAttrib unimplemented");
2862 jwzgles_glPopAttrib(void)
2864 Assert (0, "glPopAttrib unimplemented");
2868 /* These are needed for object hit detection in pinion.
2869 Might need to rewrite that code entirely. Punt for now.
2872 jwzgles_glInitNames (void)
2874 /* Assert (0, "glInitNames unimplemented");*/
2878 jwzgles_glPushName (GLuint name)
2880 /* Assert (0, "glPushName unimplemented");*/
2884 jwzgles_glPopName (void)
2886 /* Assert (0, "glPopName unimplemented");*/
2891 jwzgles_glRenderMode (GLuint mode)
2893 /* Assert (0, "glRenderMode unimplemented");*/
2898 jwzgles_glSelectBuffer (GLsizei size, GLuint *buf)
2900 /* Assert (0, "glSelectBuffer unimplemented");*/
2905 jwzgles_glGenTextures (GLuint n, GLuint *ret)
2907 Assert (!state->compiling_verts,
2908 "glGenTextures not allowed inside glBegin");
2909 /* technically legal, but stupid! */
2910 Assert (!state->compiling_list,
2911 "glGenTextures not allowed inside glNewList");
2912 if (! state->replaying_list)
2913 LOG1 ("direct %-12s", "glGenTextures");
2914 glGenTextures (n, ret); /* the real one */
2915 CHECK("glGenTextures");
2919 /* return the next larger power of 2. */
2924 while (i < value) i <<= 1;
2929 jwzgles_glTexImage1D (GLenum target, GLint level,
2930 GLint internalFormat,
2931 GLsizei width, GLint border,
2932 GLenum format, GLenum type,
2935 Assert (!state->compiling_verts, "glTexImage1D not allowed inside glBegin");
2936 /* technically legal, but stupid! */
2937 Assert (!state->compiling_list, "glTexImage1D inside glNewList");
2938 Assert (width == to_pow2(width), "width must be a power of 2");
2940 if (target == GL_TEXTURE_1D) target = GL_TEXTURE_2D;
2941 jwzgles_glTexImage2D (target, level, internalFormat, width, 1,
2942 border, format, type, data);
2946 jwzgles_glTexImage2D (GLenum target,
2948 GLint internalFormat,
2956 GLvoid *d2 = (GLvoid *) data;
2957 Assert (!state->compiling_verts, "glTexImage2D not allowed inside glBegin");
2958 Assert (!state->compiling_list, /* technically legal, but stupid! */
2959 "glTexImage2D not allowed inside glNewList");
2961 Assert (width == to_pow2(width), "width must be a power of 2");
2962 Assert (height == to_pow2(height), "height must be a power of 2");
2964 /* OpenGLES no longer supports "4" as a synonym for "RGBA". */
2965 switch (internalFormat) {
2966 case 1: internalFormat = GL_LUMINANCE; break;
2967 case 2: internalFormat = GL_LUMINANCE_ALPHA; break;
2968 case 3: internalFormat = GL_RGB; break;
2969 case 4: internalFormat = GL_RGBA; break;
2972 /* GLES does not let us omit the data pointer to create a blank texture. */
2975 d2 = (GLvoid *) calloc (1, width * height * sizeof(GLfloat) * 4);
2976 Assert (d2, "out of memory");
2979 if (internalFormat == GL_RGB && format == GL_RGBA)
2980 internalFormat = GL_RGBA; /* WTF */
2981 if (type == GL_UNSIGNED_INT_8_8_8_8_REV)
2982 type = GL_UNSIGNED_BYTE;
2984 if (! state->replaying_list)
2985 LOG10 ("direct %-12s %s %d %s %d %d %d %s %s 0x%lX", "glTexImage2D",
2986 mode_desc(target), level, mode_desc(internalFormat),
2987 width, height, border, mode_desc(format), mode_desc(type),
2988 (unsigned long) d2);
2989 glTexImage2D (target, level, internalFormat, width, height, border,
2990 format, type, d2); /* the real one */
2991 CHECK("glTexImage2D");
2993 if (d2 != data) free (d2);
2997 jwzgles_glTexSubImage2D (GLenum target, GLint level,
2998 GLint xoffset, GLint yoffset,
2999 GLsizei width, GLsizei height,
3000 GLenum format, GLenum type,
3001 const GLvoid *pixels)
3003 Assert (!state->compiling_verts,
3004 "glTexSubImage2D not allowed inside glBegin");
3005 Assert (!state->compiling_list, /* technically legal, but stupid! */
3006 "glTexSubImage2D not allowed inside glNewList");
3008 if (! state->replaying_list)
3009 LOG10 ("direct %-12s %s %d %d %d %d %d %s %s 0x%lX", "glTexSubImage2D",
3010 mode_desc(target), level, xoffset, yoffset, width, height,
3011 mode_desc (format), mode_desc (type), (unsigned long) pixels);
3012 glTexSubImage2D (target, level, xoffset, yoffset, width, height,
3013 format, type, pixels); /* the real one */
3014 CHECK("glTexSubImage2D");
3018 jwzgles_glCopyTexImage2D (GLenum target, GLint level, GLenum internalformat,
3019 GLint x, GLint y, GLsizei width, GLsizei height,
3022 Assert (!state->compiling_verts,
3023 "glCopyTexImage2D not allowed inside glBegin");
3024 Assert (!state->compiling_list, /* technically legal, but stupid! */
3025 "glCopyTexImage2D not allowed inside glNewList");
3026 if (! state->replaying_list)
3027 LOG9 ("direct %-12s %s %d %s %d %d %d %d %d", "glCopyTexImage2D",
3028 mode_desc(target), level, mode_desc(internalformat),
3029 x, y, width, height, border);
3030 glCopyTexImage2D (target, level, internalformat, x, y, width, height,
3031 border); /* the real one */
3032 CHECK("glCopyTexImage2D");
3036 /* OpenGLES doesn't have auto texture-generation at all!
3037 "Oh, just rewrite that code to use GPU shaders", they say.
3038 How fucking convenient.
3041 jwzgles_glTexGenfv (GLenum coord, GLenum pname, const GLfloat *params)
3045 if (pname == GL_TEXTURE_GEN_MODE)
3046 LOG5 ("%sdirect %-12s %s %s %s",
3047 (state->compiling_list || state->replaying_list ? " " : ""),
3049 mode_desc(coord), mode_desc(pname), mode_desc(params[0]));
3051 LOG8 ("%sdirect %-12s %s %s %3.1f %3.1f %3.1f %3.1f",
3052 (state->compiling_list || state->replaying_list ? " " : ""),
3054 mode_desc(coord), mode_desc(pname),
3055 params[0], params[1], params[2], params[3]);
3058 case GL_S: s = &state->s; break;
3059 case GL_T: s = &state->t; break;
3060 case GL_R: s = &state->r; break;
3061 case GL_Q: s = &state->q; break;
3062 default: Assert (0, "glGetTexGenfv: unknown coord"); break;
3066 case GL_TEXTURE_GEN_MODE: s->mode = params[0]; break;
3067 case GL_OBJECT_PLANE: memcpy (s->obj, params, sizeof(s->obj)); break;
3068 case GL_EYE_PLANE: memcpy (s->eye, params, sizeof(s->eye)); break;
3069 default: Assert (0, "glTexGenfv: unknown pname"); break;
3074 jwzgles_glTexGeni (GLenum coord, GLenum pname, GLint param)
3077 jwzgles_glTexGenfv (coord, pname, &v);
3081 jwzgles_glGetTexGenfv (GLenum coord, GLenum pname, GLfloat *params)
3086 case GL_S: s = &state->s; break;
3087 case GL_T: s = &state->t; break;
3088 case GL_R: s = &state->r; break;
3089 case GL_Q: s = &state->q; break;
3090 default: Assert (0, "glGetTexGenfv: unknown coord"); break;
3094 case GL_TEXTURE_GEN_MODE: params[0] = s->mode; break;
3095 case GL_OBJECT_PLANE: memcpy (params, s->obj, sizeof(s->obj)); break;
3096 case GL_EYE_PLANE: memcpy (params, s->eye, sizeof(s->eye)); break;
3097 default: Assert (0, "glGetTexGenfv: unknown pname"); break;
3100 if (pname == GL_TEXTURE_GEN_MODE)
3101 LOG5 ("%sdirect %-12s %s %s -> %s",
3102 (state->compiling_list || state->replaying_list ? " " : ""),
3104 mode_desc(coord), mode_desc(pname), mode_desc(params[0]));
3106 LOG8 ("%sdirect %-12s %s %s -> %3.1f %3.1f %3.1f %3.1f",
3107 (state->compiling_list || state->replaying_list ? " " : ""),
3109 mode_desc(coord), mode_desc(pname),
3110 params[0], params[1], params[2], params[3]);
3115 dot_product (int rank, GLfloat *a, GLfloat *b)
3117 /* A dot B => (A[1] * B[1]) + ... + (A[n] * B[n]) */
3120 for (i = 0; i < rank; i++)
3127 /* Compute the texture coordinates of the prevailing list of verts as per
3128 http://www.opengl.org/wiki/Mathematics_of_glTexGen
3131 generate_texture_coords (GLuint first, GLuint count)
3133 GLfloat *tex_out, *tex_array;
3136 draw_array A = { 0, };
3139 struct { GLuint which, flag, mode; GLfloat plane[4]; } tg[4] = {
3140 { GL_S, ISENABLED_TEXTURE_GEN_S, 0, { 0, } },
3141 { GL_T, ISENABLED_TEXTURE_GEN_T, 0, { 0, } },
3142 { GL_R, ISENABLED_TEXTURE_GEN_R, 0, { 0, } },
3143 { GL_Q, ISENABLED_TEXTURE_GEN_Q, 0, { 0, }}};
3147 /* Read the texture plane configs that were stored with glTexGen.
3149 for (i = 0; i < countof(tg); i++)
3152 if (! ((state->compiling_list ? state->list_enabled : state->enabled)
3155 jwzgles_glGetTexGenfv (tg[i].which, GL_TEXTURE_GEN_MODE, &mode);
3156 jwzgles_glGetTexGenfv (tg[i].which, GL_OBJECT_PLANE, tg[i].plane);
3161 if (tcoords == 0) return; /* Nothing to do! */
3164 /* Make the array to store our texture coords in. */
3166 tex_stride = tcoords * sizeof(GLfloat);
3167 tex_array = (GLfloat *) calloc (first + count, tex_stride);
3168 tex_out = tex_array;
3171 /* Read the prevailing vertex array, that was stored with
3172 glVertexPointer or glInterleavedArrays.
3174 glGetIntegerv (GL_VERTEX_ARRAY_BUFFER_BINDING, &A.binding);
3175 glGetIntegerv (GL_VERTEX_ARRAY_SIZE, &A.size);
3176 glGetIntegerv (GL_VERTEX_ARRAY_TYPE, &A.type);
3177 glGetIntegerv (GL_VERTEX_ARRAY_STRIDE, &A.stride);
3178 glGetPointerv (GL_VERTEX_ARRAY_POINTER, &A.data);
3179 A.bytes = count * A.stride;
3181 verts_in = (char *) A.data;
3183 /* Iterate over each vertex we're drawing.
3184 We just skip the ones < start, but the tex array has
3185 left room for zeroes there anyway.
3187 for (i = first; i < first + count; i++)
3189 GLfloat vert[4] = { 0, };
3192 /* Extract this vertex into `vert' as a float, whatever its type was. */
3193 for (j = 0; j < A.size; j++)
3196 case GL_SHORT: vert[j] = ((GLshort *) verts_in)[j]; break;
3197 case GL_INT: vert[j] = ((GLint *) verts_in)[j]; break;
3198 case GL_FLOAT: vert[j] = ((GLfloat *) verts_in)[j]; break;
3199 case GL_DOUBLE: vert[j] = ((GLdouble *) verts_in)[j]; break;
3200 default: Assert (0, "unknown vertex type"); break;
3204 /* Compute the texture coordinate for this vertex.
3205 For GL_OBJECT_LINEAR, these coordinates are static, and can go
3206 into the display list. But for GL_EYE_LINEAR, GL_SPHERE_MAP and
3207 GL_REFLECTION_MAP, they depend on the prevailing ModelView matrix,
3208 and so need to be computed afresh each time glDrawArrays is called.
3209 Unfortunately, our verts and norms are gone by then, dumped down
3210 into the VBO and discarded from CPU RAM. Bleh.
3212 for (j = 0, k = 0; j < countof(tg); j++)
3214 if (! ((state->compiling_list ? state->list_enabled : state->enabled)
3217 switch (tg[j].mode) {
3218 case GL_OBJECT_LINEAR:
3219 tex_out[k] = dot_product (4, vert, tg[j].plane);
3222 Assert (0, "unimplemented texture mode");
3228 /* fprintf (stderr, "%4d: V %-5.1f %-5.1f %-5.1f T %-5.1f %-5.1f\n",
3229 i, vert[0], vert[1], vert[2], tex_out[0], tex_out[1]); */
3231 /* Move verts_in and tex_out forward to the next vertex by stride. */
3232 verts_in += A.stride;
3233 tex_out = (GLfloat *) (((char *) tex_out) + tex_stride);
3236 jwzgles_glEnableClientState (GL_TEXTURE_COORD_ARRAY);
3237 jwzgles_glTexCoordPointer (tcoords, GL_FLOAT, tex_stride,
3238 (GLvoid *) tex_array);
3244 jwzgles_gluBuild2DMipmaps (GLenum target,
3245 GLint internalFormat,
3252 /* Not really bothering with mipmapping; only making one level.
3253 Note that this required a corresponding hack in glTexParameterf().
3256 int w2 = to_pow2(width);
3257 int h2 = to_pow2(height);
3259 void *d2 = (void *) data;
3261 /* OpenGLES no longer supports "4" as a synonym for "RGBA". */
3262 switch (internalFormat) {
3263 case 1: internalFormat = GL_LUMINANCE; break;
3264 case 2: internalFormat = GL_LUMINANCE_ALPHA; break;
3265 case 3: internalFormat = GL_RGB; break;
3266 case 4: internalFormat = GL_RGBA; break;
3269 /* if (w2 < h2) w2 = h2;
3270 if (h2 < w2) h2 = w2;*/
3272 if (w2 != width || h2 != height)
3274 /* Scale up the image bits to fit the power-of-2 texture.
3275 We have to do this because the mipmap API assumes that
3276 the texture bits go to texture coordinates 1.0 x 1.0.
3277 This could be more efficient, but it doesn't happen often.
3279 int istride = (format == GL_RGBA ? 4 : 3);
3281 int ibpl = istride * width;
3282 int obpl = ostride * w2;
3284 const unsigned char *in = (unsigned char *) data;
3285 unsigned char *out = (void *) malloc (h2 * obpl);
3286 Assert (out, "out of memory");
3289 for (oy = 0; oy < h2; oy++)
3291 int iy = oy * height / h2;
3292 const unsigned char *iline = in + (iy * ibpl);
3293 unsigned char *oline = out + (oy * obpl);
3295 for (ox = 0; ox < w2; ox++)
3297 int ix = ox * width / w2;
3298 const unsigned char *i = iline + (ix * istride);
3299 unsigned char *o = oline + (ox * ostride);
3300 *o++ = *i++; /* R */
3301 *o++ = *i++; /* G */
3302 *o++ = *i++; /* B */
3303 *o++ = (istride == 4 ? *i : 0xFF); /* A */
3308 internalFormat = GL_RGBA;
3312 jwzgles_glTexImage2D (target, 0, internalFormat, w2, h2, 0,
3314 if (d2 != data) free (d2);
3321 jwzgles_glRectf (GLfloat x1, GLfloat y1, GLfloat x2, GLfloat y2)
3323 jwzgles_glBegin (GL_POLYGON);
3324 jwzgles_glVertex2f (x1, y1);
3325 jwzgles_glVertex2f (x2, y1);
3326 jwzgles_glVertex2f (x2, y2);
3327 jwzgles_glVertex2f (x1, y2);
3332 jwzgles_glRecti (GLint x1, GLint y1, GLint x2, GLint y2)
3334 jwzgles_glRectf (x1, y1, x2, y2);
3338 jwzgles_glClearDepth (GLfloat d)
3340 /* Not sure what to do here */
3341 Assert (d == 1.0, "glClearDepth unimplemented");
3345 /* When in immediate mode, we store a bit into state->enabled, and also
3346 call the real glEnable() / glDisable().
3348 When recording a list, we store a bit into state->list_enabled instead,
3349 so that we can see what the prevailing enablement state will be when
3352 set: 1 = set, -1 = clear, 0 = query.
3355 enable_disable (GLuint bit, int set)
3357 int result = (set > 0);
3360 unsigned long flag = 0;
3363 case GL_TEXTURE_1D: /* We implement 1D textures as 2D textures. */
3364 case GL_TEXTURE_2D: flag = ISENABLED_TEXTURE_2D; break;
3365 case GL_TEXTURE_GEN_S: flag = ISENABLED_TEXTURE_GEN_S; omitp = 1; break;
3366 case GL_TEXTURE_GEN_T: flag = ISENABLED_TEXTURE_GEN_T; omitp = 1; break;
3367 case GL_TEXTURE_GEN_R: flag = ISENABLED_TEXTURE_GEN_R; omitp = 1; break;
3368 case GL_TEXTURE_GEN_Q: flag = ISENABLED_TEXTURE_GEN_Q; omitp = 1; break;
3369 case GL_LIGHTING: flag = ISENABLED_LIGHTING; break;
3370 case GL_BLEND: flag = ISENABLED_BLEND; break;
3371 case GL_DEPTH_TEST: flag = ISENABLED_DEPTH_TEST; break;
3372 case GL_CULL_FACE: flag = ISENABLED_CULL_FACE; break;
3373 case GL_NORMALIZE: flag = ISENABLED_NORMALIZE; break;
3374 case GL_FOG: flag = ISENABLED_FOG; break;
3375 case GL_COLOR_MATERIAL: flag = ISENABLED_COLMAT; break;
3377 /* Maybe technically these only work with glEnableClientState,
3378 but we treat that as synonymous with glEnable. */
3379 case GL_VERTEX_ARRAY: flag = ISENABLED_VERT_ARRAY; csp = 1; break;
3380 case GL_NORMAL_ARRAY: flag = ISENABLED_NORM_ARRAY; csp = 1; break;
3381 case GL_COLOR_ARRAY: flag = ISENABLED_COLOR_ARRAY; csp = 1; break;
3382 case GL_TEXTURE_COORD_ARRAY: flag = ISENABLED_TEX_ARRAY; csp = 1; break;
3385 Assert (set != 0, "glIsEnabled unimplemented bit");
3389 if (set) /* setting or unsetting, not querying */
3391 const char *fns[4] = { "glEnable", "glDisable",
3392 "glEnableClientState", "glDisableClientState" };
3393 list_fn_cb fs[4] = { (list_fn_cb) &jwzgles_glEnable,
3394 (list_fn_cb) &jwzgles_glDisable,
3395 (list_fn_cb) &jwzgles_glEnableClientState,
3396 (list_fn_cb) &jwzgles_glDisableClientState };
3397 const char *fn = fns[(csp ? 2 : 0) + (set < 0 ? 1 : 0)];
3398 list_fn_cb f = fs[(csp ? 2 : 0) + (set < 0 ? 1 : 0)];
3400 Assert (!state->compiling_verts,
3401 "glEnable/glDisable not allowed inside glBegin");
3403 if (state->compiling_list)
3407 list_push (fn, f,PROTO_I, vv);
3410 if (! state->replaying_list &&
3411 ! state->compiling_list)
3412 LOG2 ("direct %-12s %s", fn, mode_desc(bit));
3414 if (csp && !state->compiling_verts)
3418 case GL_NORMAL_ARRAY: state->set.ncount += 2; break;
3419 case GL_TEXTURE_COORD_ARRAY: state->set.tcount += 2; break;
3420 case GL_COLOR_ARRAY: state->set.ccount += 2; break;
3425 case GL_NORMAL_ARRAY: state->set.ncount = 0; break;
3426 case GL_TEXTURE_COORD_ARRAY: state->set.tcount = 0; break;
3427 case GL_COLOR_ARRAY: state->set.ccount = 0; break;
3432 if (omitp || state->compiling_list)
3434 else if (set > 0 && csp)
3435 glEnableClientState (bit); /* the real one */
3436 else if (set < 0 && csp)
3437 glDisableClientState (bit); /* the real one */
3439 glEnable (bit); /* the real one */
3441 glDisable (bit); /* the real one */
3446 /* Store the bit in our state as well, or query it.
3450 unsigned long *enabled = (state->compiling_list
3451 ? &state->list_enabled
3458 result = !!(*enabled & flag);
3466 jwzgles_glEnable (GLuint bit)
3468 enable_disable (bit, 1);
3472 jwzgles_glDisable (GLuint bit)
3474 enable_disable (bit, -1);
3478 jwzgles_glIsEnabled (GLuint bit)
3480 return enable_disable (bit, 0);
3484 jwzgles_glEnableClientState (GLuint cap)
3486 enable_disable (cap, 1);
3490 jwzgles_glDisableClientState (GLuint cap)
3492 enable_disable (cap, -1);
3497 /* The spec says that OpenGLES 1.x doesn't implement glGetFloatv.
3498 Were this true, it would suck, for it would mean that there was no
3499 way to retrieve the prevailing matrixes. To implement this, we'd
3500 have to keep track of them all on the client side by combining in
3501 all the actions of glMultMatrixf, glRotatef, etc.
3503 However, Apple's iOS OpenGLES *does* provide glGetFloatv!
3506 jwzgles_glGetFloatv (GLenum pname, GLfloat *params)
3508 if (! state->replaying_list)
3509 LOG2 ("direct %-12s %s", "glGetFloatv", mode_desc(pname));
3510 glGetFloatv (pname, params); /* the real one */
3511 CHECK("glGetFloatv");
3515 /* Likewise: not supposed to be there, but it is. */
3517 jwzgles_glGetPointerv (GLenum pname, GLvoid *params)
3519 if (! state->replaying_list)
3520 LOG2 ("direct %-12s %s", "glGetPointerv", mode_desc(pname));
3521 glGetPointerv (pname, params); /* the real one */
3522 CHECK("glGetPointerv");
3526 /* How many cells are written into the *params array.
3527 We need to know this to avoid smashing the caller's stack
3528 if they asked for a single-value parameter.
3531 glGet_ret_count (GLenum pname)
3534 /*case GL_COLOR_MATRIX: */
3535 case GL_MODELVIEW_MATRIX:
3536 case GL_PROJECTION_MATRIX:
3537 case GL_TEXTURE_MATRIX:
3538 /*case GL_TRANSPOSE_COLOR_MATRIX: */
3539 /*case GL_TRANSPOSE_MODELVIEW_MATRIX: */
3540 /*case GL_TRANSPOSE_PROJECTION_MATRIX: */
3541 /*case GL_TRANSPOSE_TEXTURE_MATRIX: */
3543 /*case GL_ACCUM_CLEAR_VALUE: */
3544 /*case GL_BLEND_COLOR: */
3545 case GL_COLOR_CLEAR_VALUE:
3546 case GL_COLOR_WRITEMASK:
3547 case GL_CURRENT_COLOR:
3548 /*case GL_CURRENT_RASTER_COLOR: */
3549 /*case GL_CURRENT_RASTER_POSITION: */
3550 /*case GL_CURRENT_RASTER_SECONDARY_COLOR: */
3551 /*case GL_CURRENT_RASTER_TEXTURE_COORDS: */
3552 /*case GL_CURRENT_SECONDARY_COLOR: */
3553 case GL_CURRENT_TEXTURE_COORDS:
3555 case GL_LIGHT_MODEL_AMBIENT:
3556 /*case GL_MAP2_GRID_DOMAIN: */
3557 case GL_SCISSOR_BOX:
3560 case GL_CURRENT_NORMAL:
3561 case GL_POINT_DISTANCE_ATTENUATION:
3563 case GL_ALIASED_LINE_WIDTH_RANGE:
3564 case GL_ALIASED_POINT_SIZE_RANGE:
3565 case GL_DEPTH_RANGE:
3566 /*case GL_LINE_WIDTH_RANGE: */
3567 /*case GL_MAP1_GRID_DOMAIN: */
3568 /*case GL_MAP2_GRID_SEGMENTS: */
3569 case GL_MAX_VIEWPORT_DIMS:
3570 /*case GL_POINT_SIZE_RANGE: */
3571 case GL_POLYGON_MODE:
3572 case GL_SMOOTH_LINE_WIDTH_RANGE:
3573 case GL_SMOOTH_POINT_SIZE_RANGE:
3582 jwzgles_glGetDoublev (GLenum pname, GLdouble *params)
3585 int i, j = glGet_ret_count (pname);
3586 jwzgles_glGetFloatv (pname, m);
3587 for (i = 0; i < j; i++)
3593 jwzgles_glGetIntegerv (GLenum pname, GLint *params)
3596 int i, j = glGet_ret_count (pname);
3597 jwzgles_glGetFloatv (pname, m);
3598 for (i = 0; i < j; i++)
3604 jwzgles_glGetBooleanv (GLenum pname, GLboolean *params)
3607 int i, j = glGet_ret_count (pname);
3608 jwzgles_glGetFloatv (pname, m);
3609 for (i = 0; i < j; i++)
3610 params[i] = (m[i] != 0.0);
3615 jwzgles_gluErrorString (GLenum error)
3618 sprintf (s, "0x%lX", (unsigned long) error);
3623 /* These four *Pointer calls (plus glBindBuffer and glBufferData) can
3624 be included inside glNewList, but they actually execute immediately
3625 anyway, because their data is recorded in the list by the
3626 subsequently-recorded call to glDrawArrays. This is a little weird.
3629 jwzgles_glVertexPointer (GLuint size, GLuint type, GLuint stride,
3632 if (! state->replaying_list)
3633 LOG5 ("direct %-12s %d %s %d 0x%lX", "glVertexPointer",
3634 size, mode_desc(type), stride, (unsigned long) ptr);
3635 glVertexPointer (size, type, stride, ptr); /* the real one */
3636 CHECK("glVertexPointer");
3641 jwzgles_glNormalPointer (GLuint type, GLuint stride, const GLvoid *ptr)
3643 if (! state->replaying_list)
3644 LOG4 ("direct %-12s %s %d 0x%lX", "glNormalPointer",
3645 mode_desc(type), stride, (unsigned long) ptr);
3646 glNormalPointer (type, stride, ptr); /* the real one */
3647 CHECK("glNormalPointer");
3651 jwzgles_glColorPointer (GLuint size, GLuint type, GLuint stride,
3654 if (! state->replaying_list)
3655 LOG5 ("direct %-12s %d %s %d 0x%lX", "glColorPointer",
3656 size, mode_desc(type), stride, (unsigned long) ptr);
3657 glColorPointer (size, type, stride, ptr); /* the real one */
3658 CHECK("glColorPointer");
3662 jwzgles_glTexCoordPointer (GLuint size, GLuint type, GLuint stride,
3665 if (! state->replaying_list)
3666 LOG5 ("direct %-12s %d %s %d 0x%lX", "glTexCoordPointer",
3667 size, mode_desc(type), stride, (unsigned long) ptr);
3668 glTexCoordPointer (size, type, stride, ptr); /* the real one */
3669 CHECK("glTexCoordPointer");
3673 jwzgles_glBindBuffer (GLuint target, GLuint buffer)
3675 if (! state->replaying_list)
3676 LOG3 ("direct %-12s %s %d", "glBindBuffer", mode_desc(target), buffer);
3677 glBindBuffer (target, buffer); /* the real one */
3678 CHECK("glBindBuffer");
3682 jwzgles_glBufferData (GLenum target, GLsizeiptr size, const void *data,
3685 if (! state->replaying_list)
3686 LOG5 ("direct %-12s %s %ld 0x%lX %s", "glBufferData",
3687 mode_desc(target), size, (unsigned long) data, mode_desc(usage));
3688 glBufferData (target, size, data, usage); /* the real one */
3689 CHECK("glBufferData");
3694 jwzgles_glTexParameterf (GLuint target, GLuint pname, GLfloat param)
3696 Assert (!state->compiling_verts,
3697 "glTexParameterf not allowed inside glBegin");
3699 /* We don't *really* implement mipmaps, so just turn this off. */
3700 if (param == GL_LINEAR_MIPMAP_LINEAR) param = GL_LINEAR;
3701 if (param == GL_NEAREST_MIPMAP_LINEAR) param = GL_LINEAR;
3702 if (param == GL_LINEAR_MIPMAP_NEAREST) param = GL_NEAREST;
3703 if (param == GL_NEAREST_MIPMAP_NEAREST) param = GL_NEAREST;
3705 /* We implement 1D textures as 2D textures. */
3706 if (target == GL_TEXTURE_1D) target = GL_TEXTURE_2D;
3708 /* Apparently this is another invalid enum. Just ignore it. */
3709 if ((pname == GL_TEXTURE_WRAP_S || pname == GL_TEXTURE_WRAP_T) &&
3713 if (state->compiling_list)
3719 list_push ("glTexParameterf", (list_fn_cb) &jwzgles_glTexParameterf,
3724 if (! state->replaying_list)
3725 LOG4 ("direct %-12s %s %s %7.3f", "glTexParameterf",
3726 mode_desc(target), mode_desc(pname), param);
3727 glTexParameterf (target, pname, param); /* the real one */
3728 CHECK("glTexParameterf");
3733 jwzgles_glTexParameteri (GLuint target, GLuint pname, GLuint param)
3735 jwzgles_glTexParameterf (target, pname, param);
3740 jwzgles_glBindTexture (GLuint target, GLuint texture)
3742 Assert (!state->compiling_verts,
3743 "glBindTexture not allowed inside glBegin");
3745 /* We implement 1D textures as 2D textures. */
3746 if (target == GL_TEXTURE_1D) target = GL_TEXTURE_2D;
3748 if (state->compiling_list)
3753 list_push ("glBindTexture", (list_fn_cb) &jwzgles_glBindTexture,
3757 /* Do it immediately as well, for generate_texture_coords */
3760 if (! state->replaying_list)
3761 LOG3 ("direct %-12s %s %d", "glBindTexture",
3762 mode_desc(target), texture);
3763 glBindTexture (target, texture); /* the real one */
3764 CHECK("glBindTexture");
3770 /* Matrix functions, mostly cribbed from Mesa.
3774 jwzgles_glFrustum (GLfloat left, GLfloat right,
3775 GLfloat bottom, GLfloat top,
3776 GLfloat near, GLfloat far)
3779 GLfloat x = (2 * near) / (right-left);
3780 GLfloat y = (2 * near) / (top - bottom);
3781 GLfloat a = (right + left) / (right - left);
3782 GLfloat b = (top + bottom) / (top - bottom);
3783 GLfloat c = -(far + near) / (far - near);
3784 GLfloat d = -(2 * far * near) / (far - near);
3786 # define M(X,Y) m[Y * 4 + X]
3787 M(0,0) = x; M(0,1) = 0; M(0,2) = a; M(0,3) = 0;
3788 M(1,0) = 0; M(1,1) = y; M(1,2) = b; M(1,3) = 0;
3789 M(2,0) = 0; M(2,1) = 0; M(2,2) = c; M(2,3) = d;
3790 M(3,0) = 0; M(3,1) = 0; M(3,2) = -1; M(3,3) = 0;
3793 jwzgles_glMultMatrixf (m);
3798 jwzgles_glOrtho (GLfloat left, GLfloat right,
3799 GLfloat bottom, GLfloat top,
3800 GLfloat near, GLfloat far)
3803 GLfloat a = 2 / (right - left);
3804 GLfloat b = -(right + left) / (right - left);
3805 GLfloat c = 2 / (top - bottom);
3806 GLfloat d = -(top + bottom) / (top - bottom);
3807 GLfloat e = -2 / (far - near);
3808 GLfloat f = -(far + near) / (far - near);
3810 # define M(X,Y) m[Y * 4 + X]
3811 M(0,0) = a; M(0,1) = 0; M(0,2) = 0; M(0,3) = b;
3812 M(1,0) = 0; M(1,1) = c; M(1,2) = 0; M(1,3) = d;
3813 M(2,0) = 0; M(2,1) = 0; M(2,2) = e; M(2,3) = f;
3814 M(3,0) = 0; M(3,1) = 0; M(3,2) = 0; M(3,3) = 1;
3817 jwzgles_glMultMatrixf (m);
3822 jwzgles_gluPerspective (GLdouble fovy, GLdouble aspect,
3823 GLdouble near, GLdouble far)
3827 double rad = fovy / 2 * M_PI / 180;
3832 if (dz == 0 || si == 0 || aspect == 0)
3838 c = -(far + near) / dz;
3839 d = -2 * near * far / dz;
3841 # define M(X,Y) m[Y * 4 + X]
3842 M(0,0) = a; M(0,1) = 0; M(0,2) = 0; M(0,3) = 0;
3843 M(1,0) = 0; M(1,1) = b; M(1,2) = 0; M(1,3) = 0;
3844 M(2,0) = 0; M(2,1) = 0; M(2,2) = c; M(2,3) = d;
3845 M(3,0) = 0; M(3,1) = 0; M(3,2) = -1; M(3,3) = 0;
3848 jwzgles_glMultMatrixf (m);
3853 jwzgles_gluLookAt (GLfloat eyex, GLfloat eyey, GLfloat eyez,
3854 GLfloat centerx, GLfloat centery, GLfloat centerz,
3855 GLfloat upx, GLfloat upy, GLfloat upz)
3858 GLfloat x[3], y[3], z[3];
3861 /* Make rotation matrix */
3864 z[0] = eyex - centerx;
3865 z[1] = eyey - centery;
3866 z[2] = eyez - centerz;
3867 mag = sqrt(z[0] * z[0] + z[1] * z[1] + z[2] * z[2]);
3868 if (mag) { /* mpichler, 19950515 */
3879 /* X vector = Y cross Z */
3880 x[0] = y[1] * z[2] - y[2] * z[1];
3881 x[1] = -y[0] * z[2] + y[2] * z[0];
3882 x[2] = y[0] * z[1] - y[1] * z[0];
3884 /* Recompute Y = Z cross X */
3885 y[0] = z[1] * x[2] - z[2] * x[1];
3886 y[1] = -z[0] * x[2] + z[2] * x[0];
3887 y[2] = z[0] * x[1] - z[1] * x[0];
3889 /* mpichler, 19950515 */
3890 /* cross product gives area of parallelogram, which is < 1.0 for
3891 * non-perpendicular unit-length vectors; so normalize x, y here
3894 mag = sqrt(x[0] * x[0] + x[1] * x[1] + x[2] * x[2]);
3901 mag = sqrt(y[0] * y[0] + y[1] * y[1] + y[2] * y[2]);
3908 #define M(row,col) m[col*4+row]
3909 M(0, 0) = x[0]; M(0, 1) = x[1]; M(0, 2) = x[2]; M(0, 3) = 0.0;
3910 M(1, 0) = y[0]; M(1, 1) = y[1]; M(1, 2) = y[2]; M(1, 3) = 0.0;
3911 M(2, 0) = z[0]; M(2, 1) = z[1]; M(2, 2) = z[2]; M(2, 3) = 0.0;
3912 M(3, 0) = 0.0; M(3, 1) = 0.0; M(3, 2) = 0.0; M(3, 3) = 1.0;
3915 jwzgles_glMultMatrixf(m);
3917 /* Translate Eye to Origin */
3918 jwzgles_glTranslatef(-eyex, -eyey, -eyez);
3922 static void __gluMultMatrixVecd (const GLdouble matrix[16],
3923 const GLdouble in[4],
3928 for (i=0; i<4; i++) {
3930 in[0] * matrix[0*4+i] +
3931 in[1] * matrix[1*4+i] +
3932 in[2] * matrix[2*4+i] +
3933 in[3] * matrix[3*4+i];
3938 jwzgles_gluProject (GLdouble objx, GLdouble objy, GLdouble objz,
3939 const GLdouble modelMatrix[16],
3940 const GLdouble projMatrix[16],
3941 const GLint viewport[4],
3942 GLdouble *winx, GLdouble *winy, GLdouble *winz)
3947 /* #### I suspect this is not working right. I was seeing crazy values
3948 in lament.c. Maybe there's some float-vs-double confusion going on?
3955 __gluMultMatrixVecd(modelMatrix, in, out);
3956 __gluMultMatrixVecd(projMatrix, out, in);
3957 if (in[3] == 0.0) return(GL_FALSE);
3961 /* Map x, y and z to range 0-1 */
3962 in[0] = in[0] * 0.5 + 0.5;
3963 in[1] = in[1] * 0.5 + 0.5;
3964 in[2] = in[2] * 0.5 + 0.5;
3966 /* Map x,y to viewport */
3967 in[0] = in[0] * viewport[2] + viewport[0];
3968 in[1] = in[1] * viewport[3] + viewport[1];
3977 /* The following functions are present in both OpenGL 1.1 and in OpenGLES 1,
3978 but are allowed within glNewList/glEndList, so we must wrap them to allow
3979 them to either be recorded in lists, or run directly.
3981 All this CPP obscenity is me screaming in rage at all the ways that C is
3982 not Lisp, as all I want to do here is DEFADVICE.
3985 #define PROTO_V PROTO_VOID
3986 #define TYPE_V GLuint
3988 #define VARS_V /* */
3990 #define FILL_V /* */
3992 #define TYPE_I GLuint
3993 #define TYPE_II TYPE_I
3994 #define TYPE_III TYPE_I
3995 #define TYPE_IIII TYPE_I
3996 #define ARGS_I TYPE_I a
3997 #define ARGS_II TYPE_I a, TYPE_I b
3998 #define ARGS_III TYPE_I a, TYPE_I b, TYPE_I c
3999 #define ARGS_IIII TYPE_I a, TYPE_I b, TYPE_I c, TYPE_I d
4000 #define LOGS_I "%s\n", mode_desc(a)
4001 #define LOGS_II "%s %d\n", mode_desc(a), b
4002 #define LOGS_III "%s %s %s\n", mode_desc(a), mode_desc(b), mode_desc(c)
4003 #define LOGS_IIII "%d %d %d %d\n", a, b, c, d
4005 #define VARS_II a, b
4006 #define VARS_III a, b, c
4007 #define VARS_IIII a, b, c, d
4008 #define FILL_I vv[0].i = a;
4009 #define FILL_II vv[0].i = a; vv[1].i = b;
4010 #define FILL_III vv[0].i = a; vv[1].i = b; vv[2].i = c;
4011 #define FILL_IIII vv[0].i = a; vv[1].i = b; vv[2].i = c; vv[3].i = d;
4013 #define TYPE_F GLfloat
4014 #define TYPE_FF TYPE_F
4015 #define TYPE_FFF TYPE_F
4016 #define TYPE_FFFF TYPE_F
4017 #define ARGS_F TYPE_F a
4018 #define ARGS_FF TYPE_F a, TYPE_F b
4019 #define ARGS_FFF TYPE_F a, TYPE_F b, TYPE_F c
4020 #define ARGS_FFFF TYPE_F a, TYPE_F b, TYPE_F c, TYPE_F d
4021 #define LOGS_F "%7.3f\n", a
4022 #define LOGS_FF "%7.3f %7.3f\n", a, b
4023 #define LOGS_FFF "%7.3f %7.3f %7.3f\n", a, b, c
4024 #define LOGS_FFFF "%7.3f %7.3f %7.3f %7.3f\n", a, b, c, d
4025 #define VARS_F VARS_I
4026 #define VARS_FF VARS_II
4027 #define VARS_FFF VARS_III
4028 #define VARS_FFFF VARS_IIII
4029 #define FILL_F vv[0].f = a;
4030 #define FILL_FF vv[0].f = a; vv[1].f = b;
4031 #define FILL_FFF vv[0].f = a; vv[1].f = b; vv[2].f = c;
4032 #define FILL_FFFF vv[0].f = a; vv[1].f = b; vv[2].f = c; vv[3].f = d;
4034 #define ARGS_IF TYPE_I a, TYPE_F b
4035 #define VARS_IF VARS_II
4036 #define LOGS_IF "%s %7.3f\n", mode_desc(a), b
4037 #define FILL_IF vv[0].i = a; vv[1].f = b;
4039 #define ARGS_IIF TYPE_I a, TYPE_I b, TYPE_F c
4040 #define VARS_IIF VARS_III
4041 #define LOGS_IIF "%s %s %7.3f\n", mode_desc(a), mode_desc(b), c
4042 #define FILL_IIF vv[0].i = a; vv[1].i = b; vv[2].f = c;
4044 #define TYPE_IV GLint
4045 #define ARGS_IIV TYPE_I a, const TYPE_IV *b
4046 #define VARS_IIV VARS_II
4047 #define LOGS_IIV "%s %d %d %d %d\n", mode_desc(a), b[0], b[1], b[2], b[3]
4048 #define FILL_IIV vv[0].i = a; \
4049 vv[1].i = b[0]; vv[2].i = b[1]; \
4050 vv[3].i = b[2]; vv[4].i = b[3];
4052 #define ARGS_IFV TYPE_I a, const TYPE_F *b
4053 #define VARS_IFV VARS_II
4054 #define LOGS_IFV "%s %7.3f %7.3f %7.3f %7.3f\n", mode_desc(a), \
4055 b[0], b[1], b[2], b[3]
4056 #define FILL_IFV vv[0].i = a; \
4057 vv[1].f = b[0]; vv[2].f = b[1]; \
4058 vv[3].f = b[2]; vv[4].f = b[3];
4060 #define ARGS_IIIV TYPE_I a, TYPE_I b, const TYPE_IV *c
4061 #define VARS_IIIV VARS_III
4062 #define LOGS_IIIV "%s %-8s %3d %3d %3d %3d\n", mode_desc(a), mode_desc(b), \
4063 c[0], c[1], c[2], c[3]
4064 #define FILL_IIIV vv[0].i = a; vv[1].i = b; \
4065 vv[2].i = c[0]; vv[3].i = c[1]; \
4066 vv[4].i = c[2]; vv[5].i = c[3];
4068 #define ARGS_IIFV TYPE_I a, TYPE_I b, const TYPE_F *c
4069 #define VARS_IIFV VARS_III
4070 #define LOGS_IIFV "%s %-8s %7.3f %7.3f %7.3f %7.3f\n", \
4071 mode_desc(a), mode_desc(b), \
4072 c[0], c[1], c[2], c[3]
4073 #define FILL_IIFV vv[0].i = a; vv[1].i = b; \
4074 vv[2].f = c[0]; vv[3].f = c[1]; \
4075 vv[4].f = c[2]; vv[5].f = c[3];
4078 # define WLOG(NAME,ARGS) \
4079 fprintf (stderr, "jwzgles: direct %-12s ", NAME); \
4080 fprintf (stderr, ARGS)
4082 # define WLOG(NAME,ARGS) /* */
4085 #define WRAP(NAME,SIG) \
4086 void jwzgles_##NAME (ARGS_##SIG) \
4088 Assert (!state->compiling_verts, \
4089 STRINGIFY(NAME) " not allowed inside glBegin"); \
4090 if (state->compiling_list) { \
4093 list_push (STRINGIFY(NAME), (list_fn_cb) &jwzgles_##NAME, \
4096 if (! state->replaying_list) { \
4097 WLOG (STRINGIFY(NAME), LOGS_##SIG); \
4099 NAME (VARS_##SIG); \
4100 CHECK(STRINGIFY(NAME)); \
4104 WRAP (glActiveTexture, I)
4105 WRAP (glAlphaFunc, IF)
4106 WRAP (glBlendFunc, II)
4108 WRAP (glClearColor, FFFF)
4109 WRAP (glClearStencil, I)
4110 WRAP (glColorMask, IIII)
4111 WRAP (glCullFace, I)
4112 WRAP (glDepthFunc, I)
4113 WRAP (glDepthMask, I)
4118 WRAP (glFrontFace, I)
4120 WRAP (glLightModelf, IF)
4121 WRAP (glLightModelfv, IFV)
4122 WRAP (glLightf, IIF)
4123 WRAP (glLightfv, IIFV)
4124 WRAP (glLineWidth, F)
4125 WRAP (glLoadIdentity, V)
4127 WRAP (glMatrixMode, I)
4128 WRAP (glPixelStorei, II)
4129 WRAP (glPointSize, F)
4130 WRAP (glPolygonOffset, FF)
4131 WRAP (glPopMatrix, V)
4132 WRAP (glPushMatrix, V)
4133 WRAP (glRotatef, FFFF)
4134 WRAP (glScalef, FFF)
4135 WRAP (glScissor, IIII)
4136 WRAP (glShadeModel, I)
4137 WRAP (glStencilFunc, III)
4138 WRAP (glStencilMask, I)
4139 WRAP (glStencilOp, III)
4140 WRAP (glTexEnvf, IIF)
4141 WRAP (glTexEnvi, III)
4142 WRAP (glTranslatef, FFF)
4143 WRAP (glViewport, IIII)
4145 #define TYPE_IV GLuint
4146 WRAP (glDeleteTextures, IIV)
4149 #endif /* HAVE_JWZGLES - whole file */