1 /* xscreensaver, Copyright (c) 2012 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 blocktube Uses SPHERE_MAP.
130 bouncingcow Uses OBJECT_LINEAR (when run with -texture)
131 dnalogo Uses GLUtesselator.
132 extrusion Uses all kinds of GLUT crap.
133 flyingtoasters Uses SPHERE_MAP and OBJECT_LINEAR.
134 jigglypuff Uses SPHERE_MAP (in chrome mode), GL_LINE (in wireframe)
135 jigsaw Uses GLUtesselator.
136 lockward Puts verts in lists without glBegin!
137 pinion Uses glSelectBuffer and gluPickMatrix for mouse-clicks.
138 pipes Uses glMap2f for the Utah Teapot.
139 polyhedra Uses GLUtesselator (concave objects); also Utah Teapot.
140 skytentacles Uses GL_LINE in -cel mode.
141 timetunnel Uses GL_CONSTANT_ALPHA and all kinds of other stuff.
151 #endif /* HAVE_CONFIG_H */
153 #ifdef HAVE_JWZGLES /* whole file */
162 #endif /* HAVE_UNISTD_H */
164 #if defined(USE_IPHONE)
165 # include <OpenGLES/ES1/gl.h>
166 # include <OpenGLES/ES1/glext.h>
167 #elif defined(HAVE_COCOA)
168 # include <OpenGL/gl.h>
169 # include <OpenGL/glu.h>
171 # ifndef GL_GLEXT_PROTOTYPES
172 # define GL_GLEXT_PROTOTYPES /* for glBindBuffer */
178 #include "jwzglesI.h"
180 #define STRINGIFY(X) #X
183 #define countof(x) (sizeof((x))/sizeof((*x)))
188 extern void jwxyz_abort (const char *fmt, ...) __dead2;
189 # define Assert(C,S) do { if (!(C)) { jwxyz_abort ("%s",S); }} while(0)
191 # define Assert(C,S) do { \
193 fprintf (stderr, "jwzgles: %s\n", S); \
199 typedef struct { GLfloat x, y, z; } XYZ;
200 typedef struct { GLfloat x, y, z, w; } XYZW;
201 typedef struct { GLfloat s, t, r, q; } STRQ;
202 typedef struct { GLfloat r, g, b, a; } RGBA;
205 /* Used to record all calls to glVertex3f, glNormal3f, etc.
206 while inside glBegin / glEnd so that we can convert that
207 to a single call to glDrawArrays.
211 int count, size; /* size of each array */
213 XYZW *verts; /* Arrays being built */
218 int ncount; /* How many normals, tex coords and colors were */
219 int tcount; /* used. We optimize based on "0, 1, or many". */
221 int materialistic; /* Whether glMaterial was called inside glBegin */
223 XYZ cnorm; /* Prevailing normal/texture/color while building */
230 typedef void (*list_fn_cb) (void);
233 /* We need this nonsense because you can't cast a double to a void*
234 or vice versa. They tend to be passed in different registers,
235 and you need to know about that because it's still 1972 here.
237 typedef union { const void *v; GLfloat f; GLuint i; } void_int;
239 typedef struct { /* saved args for glDrawArrays */
240 int binding, size, type, stride, bytes;
244 typedef enum { /* shorthand describing arglist signature */
245 PROTO_VOID, /* no args */
246 PROTO_I, /* 1 int arg */
247 PROTO_F, /* 1 float arg */
248 PROTO_II, /* int, int */
249 PROTO_FF, /* float, float */
250 PROTO_IF, /* int, float */
251 PROTO_III, /* int, int, int */
252 PROTO_FFF, /* float, float, float */
253 PROTO_IIF, /* int, int, float */
254 PROTO_IIII, /* int, int, int, int */
255 PROTO_FFFF, /* float, float, float, float */
256 PROTO_IIV, /* int, int[4] */
257 PROTO_IFV, /* int, float[4] */
258 PROTO_IIIV, /* int, int, int[4] */
259 PROTO_IIFV, /* int, int, float[4] */
260 PROTO_FV16, /* float[16] */
261 PROTO_ARRAYS /* glDrawArrays */
264 typedef struct { /* A single element of a display list */
266 list_fn_cb fn; /* saved function pointer */
267 fn_proto proto; /* arglist prototype */
268 draw_array *arrays; /* args for glDrawArrays */
269 void_int argv[16]; /* args for everything else */
273 typedef struct { /* a display list: saved activity within glNewList */
278 /* Named buffer that should be freed when this display list is deleted. */
284 typedef struct { /* All display lists */
290 #define ISENABLED_TEXTURE_2D (1<<0)
291 #define ISENABLED_TEXTURE_GEN_S (1<<1)
292 #define ISENABLED_TEXTURE_GEN_T (1<<2)
293 #define ISENABLED_LIGHTING (1<<3)
294 #define ISENABLED_BLEND (1<<4)
295 #define ISENABLED_DEPTH_TEST (1<<5)
296 #define ISENABLED_CULL_FACE (1<<6)
297 #define ISENABLED_NORMALIZE (1<<7)
298 #define ISENABLED_FOG (1<<8)
299 #define ISENABLED_COLMAT (1<<9)
300 #define ISENABLED_VERT_ARRAY (1<<10)
301 #define ISENABLED_NORM_ARRAY (1<<11)
302 #define ISENABLED_TEX_ARRAY (1<<12)
303 #define ISENABLED_COLOR_ARRAY (1<<13)
306 typedef struct { /* global state */
308 vert_set set; /* set being built */
310 int compiling_list; /* list id if inside glNewList; 0 means immediate */
311 int replaying_list; /* depth of call stack to glCallList */
312 int compiling_verts; /* inside glBegin */
314 list_set lists; /* saved lists */
315 unsigned long enabled;
320 static jwzgles_state global_state = { { 0, }, 0, 0, 0, { 0, }, 0, };
321 static jwzgles_state *state = &global_state;
325 # define LOG(A) fprintf(stderr,"jwzgles: " A "\n")
326 # define LOG1(A,B) fprintf(stderr,"jwzgles: " A "\n",B)
327 # define LOG2(A,B,C) fprintf(stderr,"jwzgles: " A "\n",B,C)
328 # define LOG3(A,B,C,D) fprintf(stderr,"jwzgles: " A "\n",B,C,D)
329 # define LOG4(A,B,C,D,E) fprintf(stderr,"jwzgles: " A "\n",B,C,D,E)
330 # define LOG5(A,B,C,D,E,F) fprintf(stderr,"jwzgles: " A "\n",B,C,D,E,F)
331 # define LOG6(A,B,C,D,E,F,G) fprintf(stderr,"jwzgles: " A "\n",B,C,D,E,F,G)
332 # define LOG7(A,B,C,D,E,F,G,H) fprintf(stderr,"jwzgles: " A "\n",B,C,D,E,F,G,H)
333 # define LOG8(A,B,C,D,E,F,G,H,I)\
334 fprintf(stderr,"jwzgles: "A "\n",B,C,D,E,F,G,H,I)
335 # define LOG9(A,B,C,D,E,F,G,H,I,J)\
336 fprintf(stderr,"jwzgles: "A "\n",B,C,D,E,F,G,H,I,J)
337 # define LOG10(A,B,C,D,E,F,G,H,I,J,K)\
338 fprintf(stderr,"jwzgles: "A "\n",B,C,D,E,F,G,H,I,J,K)
339 # define LOG17(A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R)\
340 fprintf(stderr,"jwzgles: "A "\n",B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R)
341 # define CHECK(S) check_gl_error(S)
343 # define LOG(A) /* */
344 # define LOG1(A,B) /* */
345 # define LOG2(A,B,C) /* */
346 # define LOG3(A,B,C,D) /* */
347 # define LOG4(A,B,C,D,E) /* */
348 # define LOG5(A,B,C,D,E,F) /* */
349 # define LOG6(A,B,C,D,E,F,G) /* */
350 # define LOG7(A,B,C,D,E,F,G,H) /* */
351 # define LOG8(A,B,C,D,E,F,G,H,I) /* */
352 # define LOG9(A,B,C,D,E,F,G,H,I,J) /* */
353 # define LOG10(A,B,C,D,E,F,G,H,I,J,K) /* */
354 # define LOG17(A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R) /* */
355 # define CHECK(S) /* */
360 mode_desc (int mode) /* for debugging messages */
363 # define SS(X) case GL_##X: return STRINGIFY(X);
367 SS(AMBIENT_AND_DIFFUSE)
383 SS(COLOR_ARRAY_BUFFER_BINDING);
385 SS(COLOR_MATERIAL_FACE)
386 SS(COLOR_MATERIAL_PARAMETER)
398 SS(ELEMENT_ARRAY_BUFFER)
411 SS(INVALID_OPERATION)
419 SS(LIGHT_MODEL_AMBIENT)
420 SS(LIGHT_MODEL_COLOR_CONTROL)
421 SS(LIGHT_MODEL_LOCAL_VIEWER)
422 SS(LIGHT_MODEL_TWO_SIDE)
425 SS(LINEAR_MIPMAP_LINEAR)
426 SS(LINEAR_MIPMAP_NEAREST)
437 SS(NEAREST_MIPMAP_LINEAR)
438 SS(NEAREST_MIPMAP_NEAREST)
441 SS(NORMAL_ARRAY_BUFFER_BINDING);
444 SS(ONE_MINUS_DST_ALPHA)
445 SS(ONE_MINUS_DST_COLOR)
446 SS(ONE_MINUS_SRC_ALPHA)
447 SS(ONE_MINUS_SRC_COLOR)
452 SS(POLYGON_OFFSET_FILL)
468 SS(SEPARATE_SPECULAR_COLOR)
477 SS(SRC_ALPHA_SATURATE)
482 SS(STENCIL_BUFFER_BIT)
494 SS(TEXTURE_ALPHA_SIZE)
495 SS(TEXTURE_BINDING_2D)
496 SS(TEXTURE_BLUE_SIZE)
498 SS(TEXTURE_BORDER_COLOR)
499 SS(TEXTURE_COMPONENTS)
500 SS(TEXTURE_COORD_ARRAY)
501 SS(TEXTURE_COORD_ARRAY_BUFFER_BINDING);
503 SS(TEXTURE_ENV_COLOR)
510 SS(TEXTURE_GREEN_SIZE)
512 SS(TEXTURE_INTENSITY_SIZE)
513 SS(TEXTURE_LUMINANCE_SIZE)
514 SS(TEXTURE_MAG_FILTER)
515 SS(TEXTURE_MIN_FILTER)
523 SS(UNPACK_ROW_LENGTH)
525 SS(UNSIGNED_INT_8_8_8_8_REV)
530 SS(VERTEX_ARRAY_BUFFER_BINDING);
531 /*SS(COLOR_BUFFER_BIT) -- same value as GL_LIGHT0 */
533 case (GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT):
534 return "DEPTH_BUFFER_BIT | COLOR_BUFFER_BIT";
535 /* Oops, same as INVALID_ENUM.
536 case (GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT):
537 return "DEPTH_BUFFER_BIT | STENCIL_BUFFER_BIT";
539 case (GL_COLOR_BUFFER_BIT | GL_STENCIL_BUFFER_BIT):
540 return "COLOR_BUFFER_BIT | STENCIL_BUFFER_BIT";
541 case (GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT | GL_STENCIL_BUFFER_BIT):
542 return "DEPTH_BUFFER_BIT | COLOR_BUFFER_BIT | STENCIL_BUFFER_BIT";
545 static char buf[255];
546 sprintf (buf, "0x%04X", mode);
553 check_gl_error (const char *s)
555 GLenum i = glGetError();
556 if (i == GL_NO_ERROR) return;
557 fprintf (stderr, "jwzgles: GL ERROR: %s: %s\n", s, mode_desc(i));
564 make_room (const char *name, void **array, int span, int *count, int *size)
566 if (*count + 1 >= *size)
568 int new_size = (*count + 20) * 1.2; /* mildly exponential */
569 *array = realloc (*array, new_size * span);
570 Assert (*array, "out of memory");
571 /* LOG3("%s: grew %d -> %d", name, *size, new_size); */
578 jwzgles_glGenLists (int n)
583 Assert (!state->compiling_verts, "glGenLists not allowed inside glBegin");
585 /* Ensure space in state->lists, clear the one at the end, and tick counter
586 Note that lists are never really deleted, and we can never re-use elements
587 of this array. glDeleteLists zeroes out the contents of the list, but
588 the list ID is still valid for use with glNewList forever.
589 #### So maybe this should be a linked list instead of an array.
591 for (i = 0; i < n; i++)
595 make_room ("glGenLists",
596 (void **) &state->lists.lists,
597 sizeof (*state->lists.lists),
598 &state->lists.count, &state->lists.size);
599 state->lists.count++;
600 id = state->lists.count;
601 L = &state->lists.lists[id-1];
603 memset (L, 0, sizeof (*L));
605 if (ret == 0) ret = id;
606 LOG1("glGenLists -> %d", L->id);
609 /* Return the ID of the first list allocated */
616 jwzgles_glNewList (int id, int mode)
619 Assert (id > 0 && id <= state->lists.count, "glNewList: bogus ID");
620 Assert (mode == GL_COMPILE, "glNewList: bad mode");
621 Assert (!state->compiling_verts, "glNewList not allowed inside glBegin");
622 Assert (!state->compiling_list, "nested glNewList");
623 Assert (state->set.count == 0, "missing glEnd");
625 L = &state->lists.lists[id-1];
626 Assert (L->id == id, "glNewList corrupted");
628 if (L->count != 0) jwzgles_glDeleteLists (L->id, 1); /* Overwriting */
629 Assert (L->count == 0, "glNewList corrupted");
631 state->compiling_list = id;
633 LOG1("glNewList -> %d", id);
637 static void save_arrays (list_fn *, int);
638 static void restore_arrays (list_fn *, int);
639 static void copy_array_data (draw_array *, int, const char *);
640 static void optimize_arrays (void);
643 jwzgles_glEndList (void)
645 Assert (state->compiling_list, "extra glEndList");
646 Assert (state->set.count == 0, "missing glEnd");
647 Assert (!state->compiling_verts, "glEndList not allowed inside glBegin");
648 LOG1("glEndList %d", state->compiling_list);
650 state->compiling_list = 0;
655 list_push (const char * const name,
656 list_fn_cb fn, fn_proto proto, void_int *av)
662 Assert (state->compiling_list > 0, "not inside glNewList");
663 Assert (state->compiling_list <= state->lists.count, "glNewList corrupted");
665 L = &state->lists.lists[state->compiling_list-1];
666 Assert (L, "glNewList: no list");
668 make_room ("glNewLists",
669 (void **) &L->fns, sizeof (*L->fns),
670 &L->count, &L->size);
671 memset (&L->fns[L->count], 0, sizeof (*L->fns));
672 F = L->fns + L->count;
677 if (proto != PROTO_VOID)
678 for (i = 0; i < countof(F->argv); i++)
684 LOG1 (" push %-12s", name);
687 if (fn == (list_fn_cb) &jwzgles_glBegin ||
688 fn == (list_fn_cb) &jwzgles_glFrontFace ||
689 fn == (list_fn_cb) &jwzgles_glEnable ||
690 fn == (list_fn_cb) &jwzgles_glDisable ||
691 fn == (list_fn_cb) &jwzgles_glEnableClientState ||
692 fn == (list_fn_cb) &jwzgles_glDisableClientState ||
693 fn == (list_fn_cb) &jwzgles_glShadeModel ||
694 fn == (list_fn_cb) &jwzgles_glMatrixMode)
695 LOG2 (" push %-12s %s", name, mode_desc (av[0].i));
697 LOG2 (" push %-12s %d", name, av[0].i);
700 LOG2 (" push %-12s %7.3f", name, av[0].f);
703 if (fn == (list_fn_cb) &jwzgles_glBindTexture ||
704 fn == (list_fn_cb) &jwzgles_glBindBuffer)
705 LOG3 (" push %-12s %s %d", name, mode_desc (av[0].i), av[1].i);
707 LOG3 (" push %-12s %d %d", name, av[0].i, av[1].i);
710 LOG3 (" push %-12s %7.3f %7.3f", name, av[0].f, av[1].f);
713 LOG3 (" push %-12s %s %7.3f", name, mode_desc (av[0].i), av[1].f);
717 if (fn == (list_fn_cb) &jwzgles_glDrawArrays ||
718 fn == (list_fn_cb) &jwzgles_glTexParameteri)
719 LOG4 (" push %-12s %s %d %d", name, mode_desc (av[0].i),
722 LOG4 (" push %-12s %d %d %d", name, av[0].i, av[1].i, av[2].i);
725 LOG4 (" push %-12s %7.3f %7.3f %7.3f", name, av[0].f, av[1].f, av[2].f);
728 LOG4 (" push %-12s %s %s %7.3f", name,
729 mode_desc(av[0].i), mode_desc(av[1].i), av[2].f);
732 LOG5 (" push %-12s %d %d %d %d", name,
733 av[0].i, av[1].i, av[2].i, av[3].i);
736 LOG5 (" push %-12s %7.3f %7.3f %7.3f %7.3f", name,
737 av[0].f, av[1].f, av[2].f, av[3].f);
740 LOG6 (" push %-12s %s %3.1f %3.1f %3.1f %3.1f", name, mode_desc (av[0].i),
741 av[1].f, av[2].f, av[3].f, av[4].f);
744 LOG6 (" push %-12s %s %d %d %d %d", name, mode_desc (av[0].i),
745 av[1].i, av[2].i, av[3].i, av[4].i);
748 LOG7 (" push %-12s %s %-8s %3.1f %3.1f %3.1f %3.1f", name,
749 mode_desc (av[0].i), mode_desc (av[1].i),
750 av[2].f, av[3].f, av[4].f, av[5].f);
753 LOG7 (" push %-12s %s %-8s %3d %3d %3d %3d", name,
754 mode_desc (av[0].i), mode_desc (av[1].i),
755 av[2].i, av[3].i, av[4].i, av[5].i);
758 LOG17 (" push %-12s ["
759 "%8.3f %8.3f %8.3f %8.3f " "\n\t\t\t "
760 "%8.3f %8.3f %8.3f %8.3f " "\n\t\t\t "
761 "%8.3f %8.3f %8.3f %8.3f " "\n\t\t\t "
762 "%8.3f %8.3f %8.3f %8.3f ]",
764 av[0].f, av[1].f, av[2].f, av[3].f,
765 av[4].f, av[5].f, av[6].f, av[7].f,
766 av[8].f, av[9].f, av[10].f, av[11].f,
767 av[12].f, av[13].f, av[14].f, av[15].f);
770 Assert (0, "bogus prototype");
775 if (proto == PROTO_ARRAYS) /* glDrawArrays */
776 save_arrays (F, av[1].i + av[2].i);
783 jwzgles_glBegin (int mode)
785 Assert (!state->compiling_verts, "nested glBegin");
786 state->compiling_verts++;
788 /* Only these commands are allowed inside glBegin:
790 glVertex -- not allowed outside
801 glArrayElement -- not allowed outside
808 if (!state->replaying_list)
809 LOG2 ("%sglBegin %s",
810 (state->compiling_list || state->replaying_list ? " " : ""),
813 Assert (state->set.count == 0, "glBegin corrupted");
814 state->set.mode = mode;
815 state->set.count = 0;
816 state->set.ncount = 0;
817 state->set.tcount = 0;
818 state->set.ccount = 0;
823 jwzgles_glDeleteLists (int id0, int range)
825 Assert (!state->compiling_verts, "glDeleteLists not allowed inside glBegin");
827 if (state->compiling_list)
832 list_push ("glDeleteLists", (list_fn_cb) &jwzgles_glDeleteLists,
839 if (!state->replaying_list)
840 LOG2 ("glDeleteLists %d %d", id0, range);
842 for (id = id0 + range - 1; id >= id0; id--)
846 if (id == 0) continue; /* People do this stupid thing */
847 if (id > state->lists.count) break; /* this too */
848 Assert (id > 0 && id <= state->lists.count,
849 "glDeleteLists: bogus ID");
850 L = &state->lists.lists[id-1];
851 Assert (L->id == id, "glDeleteLists corrupted");
853 for (i = 0; i < L->count; i++)
855 list_fn *lf = &L->fns[i];
859 for (j = 0; j < 4; j++)
860 /* If there's a binding, 'data' is an index, not a ptr. */
861 if (!lf->arrays[j].binding &&
863 free (lf->arrays[j].data);
870 glDeleteBuffers (1, &L->buffer);
872 memset (L, 0, sizeof (*L));
880 jwzgles_glIsList (GLuint id)
882 return (id > 0 && id < state->lists.count);
888 jwzgles_glNormal3fv (const GLfloat *v)
890 if (state->compiling_list && !state->compiling_verts)
896 list_push ("glNormal3f", (list_fn_cb) &jwzgles_glNormal3f,
901 if (!state->replaying_list)
902 LOG5 ("%s%sglNormal3f %7.3f %7.3f %7.3f",
903 (state->compiling_list || state->replaying_list ? " " : ""),
904 (state->compiling_verts ? " rec " : ""),
907 if (state->compiling_verts) /* inside glBegin */
909 state->set.cnorm.x = v[0];
910 state->set.cnorm.y = v[1];
911 state->set.cnorm.z = v[2];
913 if (state->set.count > 0 && state->set.ncount == 1) /* not first! */
916 else /* outside glBegin */
918 glNormal3f (v[0], v[1], v[2]);
926 jwzgles_glNormal3f (GLfloat x, GLfloat y, GLfloat z)
932 jwzgles_glNormal3fv (v);
937 jwzgles_glTexCoord4fv (const GLfloat *v)
939 if (state->compiling_list && !state->compiling_verts)
946 list_push ("glTexCoord4f", (list_fn_cb) &jwzgles_glTexCoord4f,
951 if (!state->replaying_list)
952 LOG6 ("%s%sglTexCoord4f %7.3f %7.3f %7.3f %7.3f",
953 (state->compiling_list || state->replaying_list ? " " : ""),
954 (state->compiling_verts ? " rec " : ""),
955 v[0], v[1], v[2], v[3]);
957 Assert (state->compiling_verts, "glTexCoord4fv outside glBegin");
959 if (state->compiling_verts) /* inside glBegin */
961 state->set.ctex.s = v[0];
962 state->set.ctex.t = v[1];
963 state->set.ctex.r = v[2];
964 state->set.ctex.q = v[3];
966 if (state->set.count > 0 && state->set.tcount == 1) /* not first! */
974 jwzgles_glTexCoord4f (GLfloat s, GLfloat t, GLfloat r, GLfloat q)
981 jwzgles_glTexCoord4fv (v);
986 jwzgles_glTexCoord3fv (const GLfloat *v)
993 jwzgles_glTexCoord4fv (vv);
998 jwzgles_glTexCoord2fv (const GLfloat *v)
1005 jwzgles_glTexCoord4fv (vv);
1010 jwzgles_glTexCoord3f (GLfloat s, GLfloat t, GLfloat r)
1012 jwzgles_glTexCoord4f (s, t, r, 1);
1017 jwzgles_glTexCoord2f (GLfloat s, GLfloat t)
1019 jwzgles_glTexCoord4f (s, t, 0, 1);
1024 jwzgles_glTexCoord1f (GLfloat s)
1026 jwzgles_glTexCoord4f (s, 0, 0, 1);
1032 jwzgles_glColor4fv (const GLfloat *v)
1034 if (state->compiling_list && !state->compiling_verts)
1041 list_push ("glColor4f", (list_fn_cb) &jwzgles_glColor4f,
1046 if (!state->replaying_list)
1047 LOG6 ("%s%sglColor4f %7.3f %7.3f %7.3f %7.3f",
1048 (state->compiling_list || state->replaying_list ? " " : ""),
1049 (state->compiling_verts ? " rec " : ""),
1050 v[0], v[1], v[2], v[3]);
1052 if (state->compiling_verts) /* inside glBegin */
1054 state->set.ccolor.r = v[0];
1055 state->set.ccolor.g = v[1];
1056 state->set.ccolor.b = v[2];
1057 state->set.ccolor.a = v[3];
1058 state->set.ccount++;
1059 if (state->set.count > 0 && state->set.ccount == 1) /* not first! */
1060 state->set.ccount++;
1062 else /* outside glBegin */
1064 glColor4f (v[0], v[1], v[2], v[3]);
1072 jwzgles_glColor4f (GLfloat r, GLfloat g, GLfloat b, GLfloat a)
1079 jwzgles_glColor4fv (v);
1084 jwzgles_glColor3f (GLfloat r, GLfloat g, GLfloat b)
1086 jwzgles_glColor4f (r, g, b, 1);
1091 jwzgles_glColor3fv (const GLfloat *v)
1098 jwzgles_glColor4fv (vv);
1103 jwzgles_glColor4i (GLuint r, GLuint g, GLuint b, GLuint a)
1105 jwzgles_glColor4f (r, g, b, a);
1110 jwzgles_glColor3i (GLuint r, GLuint g, GLuint b)
1112 jwzgles_glColor4f (r, g, b, 1);
1117 jwzgles_glColor4iv (const GLint *v)
1124 jwzgles_glColor4fv (vv);
1129 jwzgles_glColor3iv (const GLint *v)
1136 jwzgles_glColor4fv (vv);
1141 jwzgles_glColor4ub (GLubyte r, GLubyte g, GLubyte b, GLubyte a)
1143 jwzgles_glColor4f (r, g, b, a);
1148 jwzgles_glColor3ub (GLubyte r, GLubyte g, GLubyte b)
1150 jwzgles_glColor4f (r, g, b, 1);
1155 jwzgles_glMaterialfv (GLenum face, GLenum pname, const GLfloat *color)
1157 /* If this is called inside glBegin/glEnd with a front ambient color,
1158 then treat it the same as glColor: set the color of the upcoming
1161 Other faces or lighting types within glBegin are ignored.
1164 if (state->compiling_verts)
1166 if ((face == GL_FRONT ||
1167 face == GL_FRONT_AND_BACK) &&
1168 (pname == GL_AMBIENT ||
1169 pname == GL_DIFFUSE ||
1170 pname == GL_AMBIENT_AND_DIFFUSE))
1172 jwzgles_glColor4f (color[0], color[1], color[2], color[3]);
1173 state->set.materialistic++;
1176 LOG2 (" IGNORING glMaterialfv %s %s",
1177 mode_desc(face), mode_desc(pname));
1179 else if (state->compiling_list)
1188 list_push ("glMaterialfv", (list_fn_cb) &jwzgles_glMaterialfv,
1193 /* If this is called outside of glBegin/glEnd with a front
1194 ambient color, then the intent is presumably for that color
1195 to apply to the upcoming vertexes (which may be played back
1196 from a list that does not have vertex colors in it). In that
1197 case, the only way to make the colors show up is to call
1198 glColor() with GL_COLOR_MATERIAL enabled.
1200 I'm not sure if this will have other inappropriate side effects...
1202 if ((face == GL_FRONT ||
1203 face == GL_FRONT_AND_BACK) &&
1204 (pname == GL_AMBIENT ||
1205 pname == GL_DIFFUSE ||
1206 pname == GL_AMBIENT_AND_DIFFUSE))
1208 jwzgles_glEnable (GL_COLOR_MATERIAL);
1209 jwzgles_glColor4f (color[0], color[1], color[2], color[3]);
1212 /* OpenGLES seems to throw "invalid enum" for GL_FRONT -- but it
1213 goes ahead and sets the material anyway! No error if we just
1214 always use GL_FRONT_AND_BACK.
1216 if (face == GL_FRONT)
1217 face = GL_FRONT_AND_BACK;
1218 if (! state->replaying_list)
1219 LOG7 ("direct %-12s %s %s %7.3f %7.3f %7.3f %7.3f", "glMaterialfv",
1220 mode_desc(face), mode_desc(pname),
1221 color[0], color[1], color[2], color[3]);
1222 glMaterialfv (face, pname, color); /* the real one */
1223 CHECK("glMaterialfv");
1229 jwzgles_glMaterialiv (GLenum face, GLenum pname, const GLint *v)
1236 jwzgles_glMaterialfv (face, pname, vv);
1240 jwzgles_glMaterialf (GLenum face, GLenum pname, const GLfloat c)
1247 jwzgles_glMaterialfv (face, pname, vv);
1252 jwzgles_glMateriali (GLenum face, GLenum pname, const GLuint c)
1254 jwzgles_glMaterialf (face, pname, c);
1259 jwzgles_glColorMaterial (GLenum face, GLenum mode)
1261 Assert (!state->compiling_verts,
1262 "glColorMaterial not allowed inside glBegin");
1264 if (state->compiling_list)
1269 list_push ("glColorMaterial", (list_fn_cb) &jwzgles_glColorMaterial,
1274 /* No real analog to this distinction in OpenGLES, since color
1275 arrays don't distinguish between "color" and "material", */
1276 Assert (0, "glColorMaterial: unimplemented mode");
1285 jwzgles_glVertex4fv (const GLfloat *v)
1287 vert_set *s = &state->set;
1288 int count = s->count;
1290 Assert (state->compiling_verts, "glVertex4fv not inside glBegin");
1292 LOG5("%s rec glVertex4f %7.3f %7.3f %7.3f %7.3f",
1293 (state->compiling_list || state->replaying_list ? " " : ""),
1294 v[0], v[1], v[2], v[3]);
1296 if (count >= s->size - 1)
1298 int new_size = 20 + (s->size * 1.2);
1300 /* 4 arrays, different element sizes...
1301 We allocate all 4 arrays just in case we need them,
1302 but we might not end up using them all at the end.
1305 s->verts = (XYZW *) realloc (s->verts, new_size * sizeof (*s->verts));
1306 Assert (s->verts, "out of memory");
1308 s->norms = (XYZ *) realloc (s->norms, new_size * sizeof (*s->norms));
1309 Assert (s->norms, "out of memory");
1311 s->tex = (STRQ *) realloc (s->tex, new_size * sizeof (*s->tex));
1312 Assert (s->tex, "out of memory");
1314 s->color = (RGBA *) realloc (s->color, new_size * sizeof (*s->color));
1315 Assert (s->color, "out of memory");
1320 s->verts [count].x = v[0];
1321 s->verts [count].y = v[1];
1322 s->verts [count].z = v[2];
1323 s->verts [count].w = v[3];
1324 s->norms [count] = s->cnorm;
1325 s->tex [count] = s->ctex;
1326 s->color [count] = s->ccolor;
1332 jwzgles_glVertex4f (GLfloat x, GLfloat y, GLfloat z, GLfloat w)
1339 jwzgles_glVertex4fv (v);
1343 jwzgles_glVertex4i (GLint x, GLint y, GLint z, GLint w)
1345 jwzgles_glVertex4f (x, y, z, w);
1349 jwzgles_glVertex3f (GLfloat x, GLfloat y, GLfloat z)
1356 jwzgles_glVertex4fv (v);
1360 jwzgles_glVertex3i (GLint x, GLint y, GLint z)
1362 jwzgles_glVertex3f (x, y, z);
1366 jwzgles_glVertex3fv (const GLfloat *v)
1368 jwzgles_glVertex3f (v[0], v[1], v[2]);
1372 jwzgles_glVertex3dv (const GLdouble *v)
1374 jwzgles_glVertex3f (v[0], v[1], v[2]);
1379 jwzgles_glVertex2f (GLfloat x, GLfloat y)
1385 jwzgles_glVertex3fv (v);
1389 jwzgles_glVertex2fv (const GLfloat *v)
1391 jwzgles_glVertex2f (v[0], v[1]);
1395 jwzgles_glVertex2i (GLint x, GLint y)
1397 jwzgles_glVertex2f (x, y);
1402 jwzgles_glLightiv (GLenum light, GLenum pname, const GLint *params)
1409 jwzgles_glLightfv (light, pname, v);
1413 jwzgles_glLightModeliv (GLenum pname, const GLint *params)
1420 jwzgles_glLightModelfv (pname, v);
1424 jwzgles_glFogiv (GLenum pname, const GLint *params)
1431 jwzgles_glFogfv (pname, v);
1435 jwzgles_glLighti (GLenum light, GLenum pname, GLint param)
1437 jwzgles_glLightf (light, pname, param);
1441 jwzgles_glLightModeli (GLenum pname, GLint param)
1443 jwzgles_glLightModelf (pname, param);
1447 jwzgles_glFogi (GLenum pname, GLint param)
1449 jwzgles_glFogf (pname, param);
1454 jwzgles_glRotated (GLdouble angle, GLdouble x, GLdouble y, GLdouble z)
1456 jwzgles_glRotatef (angle, x, y, z);
1461 jwzgles_glClipPlane (GLenum plane, const GLdouble *equation)
1463 Assert (state->compiling_verts, "glClipPlane not inside glBegin");
1464 Assert (0, "glClipPlane unimplemented"); /* no GLES equivalent... */
1469 jwzgles_glPolygonMode (GLenum face, GLenum mode)
1471 Assert (!state->compiling_verts, "not inside glBegin");
1472 if (state->compiling_list)
1477 list_push ("glPolygonMode", (list_fn_cb) &jwzgles_glPolygonMode,
1482 /* POINT and LINE don't exist in GLES */
1483 Assert (mode == GL_FILL, "glPolygonMode: unimplemented mode");
1489 jwzgles_glDrawBuffer (GLenum buf)
1491 Assert (!state->compiling_verts, "not inside glBegin");
1492 if (state->compiling_list)
1496 list_push ("glDrawBuffer", (list_fn_cb) &jwzgles_glDrawBuffer,
1501 /* Assert (buf == GL_BACK, "glDrawBuffer: back buffer only"); */
1502 # ifndef GL_VERSION_ES_CM_1_0 /* not compiling against OpenGLES 1.x */
1503 if (! state->replaying_list)
1504 LOG1 ("direct %-12s", "glDrawBuffer");
1505 glDrawBuffer (buf); /* the real one */
1506 CHECK("glDrawBuffer");
1512 /* Given an array of sets of 4 elements of arbitrary size, convert it
1513 to an array of sets of 6 elements instead: ABCD becomes ABC BCD.
1516 cq2t (unsigned char **arrayP, int stride, int count)
1518 int count2 = count * 6 / 4;
1519 int size = stride * count;
1520 int size2 = stride * count2;
1521 const unsigned char *oarray, *in;
1522 unsigned char *array2, *oarray2, *out;
1526 if (!oarray || count == 0)
1529 array2 = (unsigned char *) malloc (size2);
1530 Assert (array2, "out of memory");
1535 for (i = 0; i < count / 4; i++)
1537 const unsigned char *a, *b, *c, *d; /* the 4 corners */
1538 a = in; in += stride;
1539 b = in; in += stride;
1540 c = in; in += stride;
1541 d = in; in += stride;
1543 # define PUSH(IN) do { \
1544 const unsigned char *ii = IN; \
1546 for (j = 0; j < stride; j++) { \
1550 PUSH (a); PUSH (b); PUSH (d); /* the 2 triangles */
1551 PUSH (b); PUSH (c); PUSH (d);
1555 Assert (in == oarray + size, "convert_quads corrupted");
1556 Assert (out == oarray2 + size2, "convert_quads corrupted");
1564 /* Convert all coordinates in a GL_QUADS vert_set to GL_TRIANGLES.
1567 convert_quads_to_triangles (vert_set *s)
1570 Assert (s->mode == GL_QUADS, "convert_quads bad mode");
1572 cq2t ((unsigned char **) &s->verts, sizeof(*s->verts), s->count);
1573 cq2t ((unsigned char **) &s->norms, sizeof(*s->norms), s->count);
1574 cq2t ((unsigned char **) &s->tex, sizeof(*s->tex), s->count);
1575 cq2t ((unsigned char **) &s->color, sizeof(*s->color), s->count);
1578 s->mode = GL_TRIANGLES;
1583 jwzgles_glEnd (void)
1585 vert_set *s = &state->set;
1586 int was_norm, was_tex, was_color, was_mat;
1587 int is_norm, is_tex, is_color, is_mat;
1589 Assert (state->compiling_verts == 1, "missing glBegin");
1590 state->compiling_verts--;
1592 Assert (!state->replaying_list, "how did glEnd get into a display list?");
1594 if (!state->replaying_list)
1596 LOG5 ("%s [V = %d, N = %d, T = %d, C = %d]",
1597 (state->compiling_list || state->replaying_list ? " " : ""),
1598 s->count, s->ncount, s->tcount, s->ccount);
1600 (state->compiling_list || state->replaying_list ? " " : ""));
1603 if (s->count == 0) return;
1605 if (s->mode == GL_QUADS)
1606 convert_quads_to_triangles (s);
1607 else if (s->mode == GL_QUAD_STRIP)
1608 s->mode = GL_TRIANGLE_STRIP; /* They do the same thing! */
1609 else if (s->mode == GL_POLYGON)
1610 s->mode = GL_TRIANGLE_FAN; /* They do the same thing! */
1612 glVertexPointer (4, GL_FLOAT, sizeof(*s->verts), s->verts); /* XYZW */
1613 glNormalPointer ( GL_FLOAT, sizeof(*s->norms), s->norms); /* XYZ */
1614 glTexCoordPointer (4, GL_FLOAT, sizeof(*s->tex), s->tex); /* STRQ */
1615 glColorPointer (4, GL_FLOAT, sizeof(*s->color), s->color); /* RGBA */
1616 CHECK("glColorPointer");
1618 /* If there were no calls to glNormal3f inside of glBegin/glEnd,
1619 don't bother enabling the normals array.
1621 If there was exactly *one* call to glNormal3f inside of glBegin/glEnd,
1622 and it was before the first glVertex3f, then also don't enable the
1623 normals array, but do emit that call to glNormal3f before calling
1626 Likewise for texture coordinates and colors.
1628 Be careful to leave the arrays' enabled/disabled state the same as
1629 before, or a later caller might end up using one of our arrays by
1630 mistake. #### Actually this isn't quite right: if glEnd is in a
1631 list, it saves the trailing enable/disable calls in the list, instead
1632 if restoring them to what their state was before the list was run.
1634 was_norm = jwzgles_glIsEnabled (GL_NORMAL_ARRAY);
1635 was_tex = jwzgles_glIsEnabled (GL_TEXTURE_COORD_ARRAY);
1636 was_color = jwzgles_glIsEnabled (GL_COLOR_ARRAY);
1637 was_mat = jwzgles_glIsEnabled (GL_COLOR_MATERIAL);
1639 /* If we're executing glEnd in immediate mode, not from inside a display
1640 list (which is the only way it happens, because glEnd doesn't go into
1641 display lists), make sure we're not stomping on a saved buffer list:
1642 in immediate mode, vertexes are client-side only.
1644 if (! state->compiling_list)
1645 jwzgles_glBindBuffer (GL_ARRAY_BUFFER, 0);
1650 jwzgles_glEnableClientState (GL_NORMAL_ARRAY);
1656 jwzgles_glNormal3f (s->cnorm.x, s->cnorm.y, s->cnorm.z);
1657 jwzgles_glDisableClientState (GL_NORMAL_ARRAY);
1663 jwzgles_glEnableClientState (GL_TEXTURE_COORD_ARRAY);
1669 jwzgles_glTexCoord4f (s->ctex.s, s->ctex.t, s->ctex.r, s->ctex.q);
1670 jwzgles_glDisableClientState (GL_TEXTURE_COORD_ARRAY);
1676 jwzgles_glEnableClientState (GL_COLOR_ARRAY);
1682 jwzgles_glColor4f (s->ccolor.r, s->ccolor.g, s->ccolor.b, s->ccolor.a);
1683 jwzgles_glDisableClientState (GL_COLOR_ARRAY);
1686 jwzgles_glEnableClientState (GL_VERTEX_ARRAY);
1688 /* We translated the glMaterial calls to per-vertex colors, which are
1689 of the glColor sort, not the glMaterial sort, so automatically
1690 turn on material mapping. Maybe this is a bad idea.
1692 if (s->materialistic && !jwzgles_glIsEnabled (GL_COLOR_MATERIAL))
1695 jwzgles_glEnable (GL_COLOR_MATERIAL);
1700 glBindBuffer (GL_ARRAY_BUFFER, 0); /* This comes later. */
1701 jwzgles_glDrawArrays (s->mode, 0, s->count);
1702 glBindBuffer (GL_ARRAY_BUFFER, 0); /* Keep out of others' hands */
1704 # define RESET(VAR,FN,ARG) do { \
1705 if (is_##VAR != was_##VAR) { \
1706 if (was_##VAR) jwzgles_glEnable##FN (ARG); \
1707 else jwzgles_glDisable##FN (ARG); \
1709 RESET (norm, ClientState, GL_NORMAL_ARRAY);
1710 RESET (tex, ClientState, GL_TEXTURE_COORD_ARRAY);
1711 RESET (color, ClientState, GL_COLOR_ARRAY);
1712 RESET (mat, , GL_COLOR_MATERIAL);
1719 s->materialistic = 0;
1723 /* The display list is full of calls to glDrawArrays(), plus saved arrays
1724 of the values we need to restore before calling it. "Restore" means
1725 "ship them off to the GPU before each call".
1727 So instead, this function walks through the display list and
1728 combines all of those vertex, normal, texture and color values into
1729 a single VBO array; ships those values off to the GPU *once* at the
1730 time of glEndList; and when running the list with glCallList, the
1731 values are already on the GPU and don't need to be sent over again.
1733 The VBO persists in the GPU until the display list is deleted.
1736 optimize_arrays (void)
1738 list *L = &state->lists.lists[state->compiling_list-1];
1741 int combo_count = 0;
1743 GLuint buf_name = 0;
1745 Assert (state->compiling_list, "not compiling a list");
1746 Assert (L, "no list");
1747 Assert (!L->buffer, "list already has a buffer");
1749 glGenBuffers (1, &buf_name);
1750 CHECK("glGenBuffers");
1751 if (! buf_name) return;
1753 L->buffer = buf_name;
1755 /* Go through the list and dump the contents of the various saved arrays
1756 into one large array.
1758 for (i = 0; i < L->count; i++)
1760 list_fn *F = &L->fns[i];
1764 count = F->argv[2].i; /* 3rd arg to glDrawArrays */
1766 for (j = 0; j < 4; j++)
1768 draw_array *A = &F->arrays[j];
1769 int ocount = combo_count;
1771 /* If some caller is using arrays that don't have floats in them,
1772 we just leave them as-is and ship them over at each call.
1773 Doubt this ever really happens.
1775 if (A->type != GL_FLOAT)
1778 if (! A->data) /* No array. */
1781 Assert (A->bytes > 0, "no bytes in draw_array");
1782 Assert (((unsigned long) A->data > 0xFFFF),
1783 "buffer data not a pointer");
1785 combo_count += A->bytes / sizeof(*combo);
1786 make_room ("optimize_arrays",
1787 (void **) &combo, sizeof(*combo),
1788 &combo_count, &combo_size);
1789 memcpy (combo + ocount, A->data, A->bytes);
1790 A->binding = buf_name;
1792 /* 'data' is now the byte offset into the VBO. */
1793 A->data = (void *) (ocount * sizeof(*combo));
1794 /* LOG3(" loaded %lu floats to pos %d of buffer %d",
1795 A->bytes / sizeof(*combo), ocount, buf_name); */
1799 if (combo_count == 0) /* Nothing to do! */
1801 if (combo) free (combo);
1802 glDeleteBuffers (1, &buf_name);
1807 glBindBuffer (GL_ARRAY_BUFFER, buf_name);
1808 glBufferData (GL_ARRAY_BUFFER,
1809 combo_count * sizeof (*combo),
1812 glBindBuffer (GL_ARRAY_BUFFER, 0); /* Keep out of others' hands */
1814 LOG3(" loaded %d floats of list %d into VBO %d",
1815 combo_count, state->compiling_list, buf_name);
1819 for (i = 0; i < combo_count; i++)
1822 fprintf (stderr, "\njwzgles: %4d: ", i);
1823 fprintf (stderr, " %7.3f", combo[i]);
1825 fprintf (stderr, "\n");
1829 if (combo) free (combo);
1834 jwzgles_glCallList (int id)
1836 if (state->compiling_list)
1838 /* Yes, you can call lists inside of lists.
1839 Yes, recursion would be a mistake. */
1842 list_push ("glCallList", (list_fn_cb) &jwzgles_glCallList, PROTO_I, vv);
1849 state->replaying_list++;
1852 fprintf (stderr, "\n");
1853 LOG1 ("glCallList %d", id);
1856 Assert (id > 0 && id <= state->lists.count, "glCallList: bogus ID");
1857 L = &state->lists.lists[id-1];
1858 Assert (id == L->id, "glCallList corrupted");
1860 for (i = 0; i < L->count; i++)
1862 list_fn *F = &L->fns[i];
1863 list_fn_cb fn = F->fn;
1864 void_int *av = F->argv;
1868 LOG1 (" call %-12s", F->name);
1869 ((void (*) (void)) fn) ();
1873 if (fn == (list_fn_cb) &jwzgles_glBegin ||
1874 fn == (list_fn_cb) &jwzgles_glFrontFace ||
1875 fn == (list_fn_cb) &jwzgles_glEnable ||
1876 fn == (list_fn_cb) &jwzgles_glDisable ||
1877 fn == (list_fn_cb) &jwzgles_glEnableClientState ||
1878 fn == (list_fn_cb) &jwzgles_glDisableClientState ||
1879 fn == (list_fn_cb) &jwzgles_glShadeModel ||
1880 fn == (list_fn_cb) &jwzgles_glMatrixMode)
1881 LOG2 (" call %-12s %s", F->name, mode_desc (av[0].i));
1883 LOG2 (" call %-12s %d", F->name, av[0].i);
1884 ((void (*) (int)) fn) (av[0].i);
1888 LOG2 (" call %-12s %7.3f", F->name, av[0].f);
1889 ((void (*) (GLfloat)) fn) (av[0].f);
1893 if (fn == (list_fn_cb) &jwzgles_glBindTexture ||
1894 fn == (list_fn_cb) &jwzgles_glBindBuffer)
1895 LOG3 (" call %-12s %s %d", F->name,
1896 mode_desc (av[0].i), av[1].i);
1898 LOG3 (" call %-12s %d %d", F->name, av[0].i, av[1].i);
1899 ((void (*) (int, int)) fn) (av[0].i, av[1].i);
1903 LOG3 (" call %-12s %7.3f %7.3f", F->name, av[0].f, av[1].f);
1904 ((void (*) (GLfloat, GLfloat)) fn) (av[0].f, av[1].f);
1908 LOG3 (" call %-12s %s %7.3f", F->name,
1909 mode_desc (av[0].f), av[1].f);
1910 ((void (*) (GLint, GLfloat)) fn) (av[0].i, av[1].f);
1913 case PROTO_III: III:
1914 if (fn == (list_fn_cb) &jwzgles_glDrawArrays ||
1915 fn == (list_fn_cb) &jwzgles_glTexParameteri)
1916 LOG4 (" call %-12s %s %d %d", F->name,
1917 mode_desc (av[0].i), av[1].i, av[2].i);
1919 LOG4 (" call %-12s %d %d %d", F->name,
1920 av[0].i, av[1].i, av[2].i);
1921 ((void (*) (int, int, int)) fn) (av[0].i, av[1].i, av[2].i);
1925 LOG4 (" call %-12s %7.3f %7.3f %7.3f", F->name,
1926 av[0].f, av[1].f, av[2].f);
1927 ((void (*) (GLfloat, GLfloat, GLfloat)) fn)
1928 (av[0].f, av[1].f, av[2].f);
1932 LOG4 (" call %-12s %s %s %7.3f", F->name,
1933 mode_desc (av[0].i), mode_desc (av[1].i), av[2].f);
1934 ((void (*) (int, int, GLfloat)) fn) (av[0].i, av[1].i, av[2].f);
1938 LOG5 (" call %-12s %d %d %d %d", F->name,
1939 av[0].i, av[1].i, av[2].i, av[3].i);
1940 ((void (*) (int, int, int, int)) fn)
1941 (av[0].i, av[1].i, av[2].i, av[3].i);
1945 LOG5 (" call %-12s %7.3f %7.3f %7.3f %7.3f", F->name,
1946 av[0].f, av[1].f, av[2].f, av[3].f);
1947 ((void (*) (GLfloat, GLfloat, GLfloat, GLfloat)) fn)
1948 (av[0].f, av[1].f, av[2].f, av[3].f);
1958 LOG6 (" call %-12s %s %3.1f %3.1f %3.1f %3.1f", F->name,
1959 mode_desc (av[0].i),
1960 av[1].f, av[2].f, av[3].f, av[4].f);
1961 ((void (*) (int, const GLfloat *)) fn) (av[0].i, v);
1972 LOG7 (" call %-12s %s %-8s %3.1f %3.1f %3.1f %3.1f", F->name,
1973 mode_desc (av[0].i), mode_desc (av[1].i),
1974 av[2].f, av[3].f, av[4].f, av[5].f);
1975 ((void (*) (int, int, const GLfloat *)) fn)
1976 (av[0].i, av[1].i, v);
1987 LOG6 (" call %-12s %s %3d %3d %3d %3d", F->name,
1988 mode_desc (av[0].i),
1989 av[1].i, av[2].i, av[3].i, av[4].i);
1990 ((void (*) (int, const int *)) fn) (av[0].i, v);
2001 LOG7 (" call %-12s %s %-8s %3d %3d %3d %3d", F->name,
2002 mode_desc (av[0].i), mode_desc (av[1].i),
2003 av[2].i, av[3].i, av[4].i, av[5].i);
2004 ((void (*) (int, int, const int *)) fn)
2005 (av[0].i, av[1].i, v);
2010 restore_arrays (F, av[1].i + av[2].i);
2018 for (i = 0; i < countof(m); i++)
2020 LOG17 (" call %-12s ["
2021 "%8.3f %8.3f %8.3f %8.3f " "\n\t\t\t "
2022 "%8.3f %8.3f %8.3f %8.3f " "\n\t\t\t "
2023 "%8.3f %8.3f %8.3f %8.3f " "\n\t\t\t "
2024 "%8.3f %8.3f %8.3f %8.3f ]",
2026 m[0], m[1], m[2], m[3],
2027 m[4], m[5], m[6], m[7],
2028 m[8], m[9], m[10], m[11],
2029 m[12], m[13], m[14], m[15]);
2030 ((void (*) (GLfloat *)) fn) (m);
2035 Assert (0, "bogus prototype");
2040 LOG1 ("glCallList %d done\n", id);
2042 state->replaying_list--;
2043 Assert (state->replaying_list >= 0, "glCallList corrupted");
2048 /* When we save a call to glDrawArrays into a display list, we also need to
2049 save the prevailing copy of the arrays that it will use, and restore them
2053 save_arrays (list_fn *F, int count)
2056 draw_array *A = (draw_array *) calloc (4, sizeof (*A));
2057 Assert (A, "out of memory");
2059 /* if (state->set.count > 0) */
2061 glGetIntegerv (GL_VERTEX_ARRAY_BUFFER_BINDING, &A[i].binding);
2062 glGetIntegerv (GL_VERTEX_ARRAY_SIZE, &A[i].size);
2063 glGetIntegerv (GL_VERTEX_ARRAY_TYPE, &A[i].type);
2064 glGetIntegerv (GL_VERTEX_ARRAY_STRIDE, &A[i].stride);
2065 glGetPointerv (GL_VERTEX_ARRAY_POINTER, &A[i].data);
2066 CHECK("glGetPointerv");
2067 copy_array_data (&A[i], count, "vert");
2071 if (state->set.ncount > 1)
2074 glGetIntegerv (GL_NORMAL_ARRAY_BUFFER_BINDING, &A[i].binding);
2075 glGetIntegerv (GL_NORMAL_ARRAY_TYPE, &A[i].type);
2076 glGetIntegerv (GL_NORMAL_ARRAY_STRIDE, &A[i].stride);
2077 glGetPointerv (GL_NORMAL_ARRAY_POINTER, &A[i].data);
2078 CHECK("glGetPointerv");
2079 copy_array_data (&A[i], count, "norm");
2083 if (state->set.tcount > 1)
2085 glGetIntegerv (GL_TEXTURE_COORD_ARRAY_BUFFER_BINDING, &A[i].binding);
2086 glGetIntegerv (GL_TEXTURE_COORD_ARRAY_SIZE, &A[i].size);
2087 glGetIntegerv (GL_TEXTURE_COORD_ARRAY_TYPE, &A[i].type);
2088 glGetIntegerv (GL_TEXTURE_COORD_ARRAY_STRIDE, &A[i].stride);
2089 glGetPointerv (GL_TEXTURE_COORD_ARRAY_POINTER, &A[i].data);
2090 CHECK("glGetPointerv");
2091 copy_array_data (&A[i], count, "tex ");
2095 if (state->set.ccount > 1)
2097 glGetIntegerv (GL_COLOR_ARRAY_BUFFER_BINDING, &A[i].binding);
2098 glGetIntegerv (GL_COLOR_ARRAY_SIZE, &A[i].size);
2099 glGetIntegerv (GL_COLOR_ARRAY_TYPE, &A[i].type);
2100 glGetIntegerv (GL_COLOR_ARRAY_STRIDE, &A[i].stride);
2101 glGetPointerv (GL_COLOR_ARRAY_POINTER, &A[i].data);
2102 CHECK("glGetPointerv");
2103 copy_array_data (&A[i], count, "col ");
2106 /* Freed by glDeleteLists. */
2108 Assert (!F->arrays, "save_arrays corrupted");
2116 dump_array_data (draw_array *A, int count,
2117 const char *action, const char *name, const void *old)
2119 int bytes = count * A->stride;
2124 "jwzgles: %s %s %d %s %2d, %4d = %5d bind %d @ %d\n",
2126 A->size, mode_desc(A->type), A->stride,
2127 count, bytes, A->binding, (int) A->data);
2131 Assert (bytes == A->bytes, "array data corrupted");
2133 fprintf (stderr, "jwzgles: %s %s %d %s %2d, %4d = %5d @ %lX",
2135 A->size, mode_desc(A->type), A->stride,
2136 count, bytes, (unsigned long) A->data);
2138 fprintf (stderr, " / %lX", (unsigned long) old);
2139 fprintf (stderr, "\n");
2144 Assert (((unsigned long) A->data < 0xFFFF),
2145 "buffer binding should be a numeric index,"
2146 " but looks like a pointer");
2149 /* glGetBufferSubData doesn't actually exist in OpenGLES, but this
2150 was helpful for debugging on real OpenGL... */
2153 fprintf (stderr, "jwzgles: read back:\n");
2154 d = (GLfloat *) malloc (A->bytes);
2155 glGetBufferSubData (GL_ARRAY_BUFFER, (int) A->data,
2156 count * A->stride, (void *) d);
2157 CHECK("glGetBufferSubData");
2158 for (i = 0; i < count * A->size; i++)
2161 fprintf (stderr, "\njwzgles: %4d: ",
2162 i + (int) A->data / sizeof(GLfloat));
2163 fprintf (stderr, " %7.3f", d[i]);
2165 fprintf (stderr, "\n");
2172 unsigned char *b = (unsigned char *) A->data;
2174 if ((unsigned long) A->data < 0xFFFF)
2176 Assert (0, "buffer data not a pointer");
2179 for (i = 0; i < count; i++)
2182 GLfloat *f = (GLfloat *) b;
2184 if (s == 0) s = 3; /* normals */
2185 fprintf (stderr, "jwzgles: ");
2186 for (j = 0; j < s; j++)
2187 fprintf (stderr, " %7.3f", f[j]);
2188 fprintf (stderr, "\n");
2196 dump_direct_array_data (int count)
2198 draw_array A = { 0, };
2200 if (jwzgles_glIsEnabled (GL_VERTEX_ARRAY))
2202 glGetIntegerv (GL_VERTEX_ARRAY_BUFFER_BINDING, &A.binding);
2203 glGetIntegerv (GL_VERTEX_ARRAY_SIZE, &A.size);
2204 glGetIntegerv (GL_VERTEX_ARRAY_TYPE, &A.type);
2205 glGetIntegerv (GL_VERTEX_ARRAY_STRIDE, &A.stride);
2206 glGetPointerv (GL_VERTEX_ARRAY_POINTER, &A.data);
2207 A.bytes = count * A.stride;
2208 dump_array_data (&A, count, "direct", "vertex ", 0);
2210 if (jwzgles_glIsEnabled (GL_NORMAL_ARRAY))
2213 glGetIntegerv (GL_NORMAL_ARRAY_BUFFER_BINDING, &A.binding);
2214 glGetIntegerv (GL_NORMAL_ARRAY_TYPE, &A.type);
2215 glGetIntegerv (GL_NORMAL_ARRAY_STRIDE, &A.stride);
2216 glGetPointerv (GL_NORMAL_ARRAY_POINTER, &A.data);
2217 A.bytes = count * A.stride;
2218 dump_array_data (&A, count, "direct", "normal ", 0);
2220 if (jwzgles_glIsEnabled (GL_TEXTURE_COORD_ARRAY))
2222 glGetIntegerv (GL_TEXTURE_COORD_ARRAY_BUFFER_BINDING, &A.binding);
2223 glGetIntegerv (GL_TEXTURE_COORD_ARRAY_SIZE, &A.size);
2224 glGetIntegerv (GL_TEXTURE_COORD_ARRAY_TYPE, &A.type);
2225 glGetIntegerv (GL_TEXTURE_COORD_ARRAY_STRIDE, &A.stride);
2226 glGetPointerv (GL_TEXTURE_COORD_ARRAY_POINTER, &A.data);
2227 A.bytes = count * A.stride;
2228 dump_array_data (&A, count, "direct", "texture", 0);
2230 if (jwzgles_glIsEnabled (GL_COLOR_ARRAY))
2232 glGetIntegerv (GL_COLOR_ARRAY_BUFFER_BINDING, &A.binding);
2233 glGetIntegerv (GL_COLOR_ARRAY_SIZE, &A.size);
2234 glGetIntegerv (GL_COLOR_ARRAY_TYPE, &A.type);
2235 glGetIntegerv (GL_COLOR_ARRAY_STRIDE, &A.stride);
2236 glGetPointerv (GL_COLOR_ARRAY_POINTER, &A.data);
2237 A.bytes = count * A.stride;
2238 dump_array_data (&A, count, "direct", "color ", 0);
2246 copy_array_data (draw_array *A, int count, const char *name)
2248 /* Instead of just memcopy'ing the whole array and obeying its previous
2249 'stride' value, we make up a more compact array. This is because if
2250 the same array data is being used with multiple component types,
2251 e.g. with glInterleavedArrays, we don't want to copy all of the
2252 data multiple times.
2254 int stride2, bytes, i, j;
2259 const unsigned char *IB;
2262 if (((unsigned long) A->data) < 0xFFFF)
2264 Assert (0, "buffer data not a pointer");
2268 Assert (A->size >= 2 && A->size <= 4, "bogus array size");
2271 case GL_FLOAT: stride2 = A->size * sizeof(GLfloat); break;
2272 case GL_UNSIGNED_BYTE: stride2 = A->size; break;
2273 default: Assert (0, "bogus array type"); break;
2276 bytes = count * stride2;
2277 Assert (bytes > 0, "bogus array count or stride");
2278 Assert (A->data, "missing array data");
2279 data2 = (void *) malloc (bytes);
2280 Assert (data2, "out of memory");
2282 IB = (const unsigned char *) A->data;
2283 OB = (unsigned char *) data2;
2284 IF = (const GLfloat *) A->data;
2285 OF = (GLfloat *) data2;
2289 for (i = 0; i < count; i++)
2291 for (j = 0; j < A->size; j++)
2293 IF = (const GLfloat *) (((const unsigned char *) IF) + A->stride);
2296 case GL_UNSIGNED_BYTE:
2297 for (i = 0; i < count; i++)
2299 for (j = 0; j < A->size; j++)
2305 Assert (0, "bogus array type");
2312 A->stride = stride2;
2315 dump_array_data (A, count, "saved", name, old);
2321 restore_arrays (list_fn *F, int count)
2324 draw_array *A = F->arrays;
2325 Assert (A, "missing array");
2327 for (i = 0; i < 4; i++)
2329 const char *name = 0;
2334 Assert ((A[i].binding || A[i].data),
2335 "array has neither buffer binding nor data");
2337 glBindBuffer (GL_ARRAY_BUFFER, A[i].binding);
2338 CHECK("glBindBuffer");
2341 case 0: glVertexPointer (A[i].size, A[i].type, A[i].stride, A[i].data);
2343 CHECK("glVertexPointer");
2345 case 1: glNormalPointer ( A[i].type, A[i].stride, A[i].data);
2347 CHECK("glNormalPointer");
2349 case 2: glTexCoordPointer(A[i].size, A[i].type, A[i].stride, A[i].data);
2351 CHECK("glTexCoordPointer");
2353 case 3: glColorPointer (A[i].size, A[i].type, A[i].stride, A[i].data);
2355 CHECK("glColorPointer");
2357 default: Assert (0, "wat"); break;
2361 dump_array_data (&A[i], count, "restored", name, 0);
2365 glBindBuffer (GL_ARRAY_BUFFER, 0); /* Keep out of others' hands */
2370 jwzgles_glDrawArrays (GLuint mode, GLuint first, GLuint count)
2372 if (state->compiling_list)
2378 list_push ("glDrawArrays", (list_fn_cb) &jwzgles_glDrawArrays,
2384 if (! state->replaying_list) {
2385 LOG4("direct %-12s %d %d %d", "glDrawArrays", mode, first, count);
2386 dump_direct_array_data (first + count);
2389 glDrawArrays (mode, first, count); /* the real one */
2390 CHECK("glDrawArrays");
2396 jwzgles_glInterleavedArrays (GLenum format, GLsizei stride, const void *data)
2398 /* We can implement this by calling the various *Pointer functions
2399 with offsets into the same data, taking advantage of stride.
2401 const unsigned char *c = (const unsigned char *) data;
2403 # define F sizeof(GLfloat)
2405 Assert (!state->compiling_verts,
2406 "glInterleavedArrays not allowed inside glBegin");
2408 jwzgles_glEnableClientState (GL_VERTEX_ARRAY);
2410 if (!state->replaying_list)
2411 LOG4 ("%sglInterleavedArrays %s %d %lX",
2412 (state->compiling_list || state->replaying_list ? " " : ""),
2413 mode_desc (format), stride, (unsigned long) data);
2417 glVertexPointer (2, GL_FLOAT, stride, c);
2418 CHECK("glVertexPointer");
2419 if (!state->replaying_list)
2420 LOG3 ("%s -> glVertexPointer 2 FLOAT %d %lX",
2421 (state->compiling_list || state->replaying_list ? " " : ""),
2422 stride, (unsigned long) c);
2425 glVertexPointer (3, GL_FLOAT, stride, c);
2426 CHECK("glVertexPointer");
2427 if (!state->replaying_list)
2428 LOG3 ("%s -> glVertexPointer 3 FLOAT %d %lX",
2429 (state->compiling_list || state->replaying_list ? " " : ""),
2430 stride, (unsigned long) c);
2435 jwzgles_glEnableClientState (GL_COLOR_ARRAY);
2436 glColorPointer (4, GL_UNSIGNED_BYTE, stride, c);
2437 CHECK("glColorPointer");
2438 c += 4*B; /* #### might be incorrect float-aligned address */
2439 glVertexPointer (2, GL_FLOAT, stride, c);
2444 jwzgles_glEnableClientState (GL_COLOR_ARRAY);
2445 glColorPointer (4, GL_UNSIGNED_BYTE, stride, c);
2446 CHECK("glColorPointer");
2448 glVertexPointer (3, GL_FLOAT, stride, c);
2449 CHECK("glVertexPointer");
2454 jwzgles_glEnableClientState (GL_COLOR_ARRAY);
2455 glColorPointer (3, GL_FLOAT, stride, c);
2456 CHECK("glColorPointer");
2458 glVertexPointer (3, GL_FLOAT, stride, c);
2459 CHECK("glVertexPointer");
2464 jwzgles_glEnableClientState (GL_NORMAL_ARRAY);
2465 glNormalPointer (GL_FLOAT, stride, c);
2466 CHECK("glNormalPointer");
2467 if (!state->replaying_list)
2468 LOG3 ("%s -> glNormalPointer FLOAT %d %lX",
2469 (state->compiling_list || state->replaying_list ? " " : ""),
2470 stride, (unsigned long) c);
2472 glVertexPointer (3, GL_FLOAT, stride, c);
2473 CHECK("glVertexPointer");
2474 if (!state->replaying_list)
2475 LOG3 ("%s -> glVertexPointer 3 FLOAT %d %lX",
2476 (state->compiling_list || state->replaying_list ? " " : ""),
2477 stride, (unsigned long) c);
2479 case GL_C4F_N3F_V3F:
2481 stride = 4*F + 3*F + 3*F;
2482 jwzgles_glEnableClientState (GL_COLOR_ARRAY);
2483 glColorPointer (4, GL_FLOAT, stride, c);
2484 CHECK("glColorPointer");
2486 jwzgles_glEnableClientState (GL_NORMAL_ARRAY);
2487 glNormalPointer (GL_FLOAT, stride, c);
2488 CHECK("glNormalPointer");
2490 glVertexPointer (3, GL_FLOAT, stride, c);
2491 CHECK("glVertexPointer");
2496 jwzgles_glEnableClientState (GL_TEXTURE_COORD_ARRAY);
2497 glTexCoordPointer (2, GL_FLOAT, stride, c);
2498 CHECK("glTexCoordPointer");
2500 glVertexPointer (3, GL_FLOAT, stride, c);
2501 CHECK("glVertexPointer");
2506 jwzgles_glEnableClientState (GL_TEXTURE_COORD_ARRAY);
2507 glTexCoordPointer (4, GL_FLOAT, stride, c);
2508 CHECK("glTexCoordPointer");
2510 glVertexPointer (4, GL_FLOAT, stride, c);
2511 CHECK("glVertexPointer");
2513 case GL_T2F_C4UB_V3F:
2515 stride = 2*F + 4*B + 3*F;
2516 jwzgles_glEnableClientState (GL_TEXTURE_COORD_ARRAY);
2517 glTexCoordPointer (2, GL_FLOAT, stride, c);
2518 CHECK("glTexCoordPointer");
2520 jwzgles_glEnableClientState (GL_COLOR_ARRAY);
2521 glColorPointer (4, GL_UNSIGNED_BYTE, stride, c);
2522 CHECK("glColorPointer");
2524 glVertexPointer (3, GL_FLOAT, stride, c);
2525 CHECK("glVertexPointer");
2527 case GL_T2F_C3F_V3F:
2529 stride = 2*F + 3*F + 3*F;
2530 jwzgles_glEnableClientState (GL_TEXTURE_COORD_ARRAY);
2531 glTexCoordPointer (2, GL_FLOAT, stride, c);
2532 CHECK("glTexCoordPointer");
2534 jwzgles_glEnableClientState (GL_COLOR_ARRAY);
2535 glColorPointer (3, GL_FLOAT, stride, c);
2536 CHECK("glColorPointer");
2538 glVertexPointer (3, GL_FLOAT, stride, c);
2539 CHECK("glVertexPointer");
2541 case GL_T2F_N3F_V3F:
2543 stride = 2*F + 3*F + 3*F;
2544 jwzgles_glEnableClientState (GL_TEXTURE_COORD_ARRAY);
2545 glTexCoordPointer (2, GL_FLOAT, stride, c);
2546 CHECK("glTexCoordPointer");
2548 jwzgles_glEnableClientState (GL_NORMAL_ARRAY);
2549 glNormalPointer (GL_FLOAT, stride, c);
2550 CHECK("glNormalPointer");
2552 glVertexPointer (3, GL_FLOAT, stride, c);
2553 CHECK("glVertexPointer");
2555 case GL_T2F_C4F_N3F_V3F:
2557 stride = 2*F + 4*F + 3*F + 3*F;
2558 jwzgles_glEnableClientState (GL_TEXTURE_COORD_ARRAY);
2559 glTexCoordPointer (2, GL_FLOAT, stride, c);
2560 CHECK("glTexCoordPointer");
2562 jwzgles_glEnableClientState (GL_COLOR_ARRAY);
2563 glColorPointer (3, GL_FLOAT, stride, c);
2564 CHECK("glColorPointer");
2566 jwzgles_glEnableClientState (GL_NORMAL_ARRAY);
2567 glNormalPointer (GL_FLOAT, stride, c);
2568 CHECK("glNormalPointer");
2570 glVertexPointer (3, GL_FLOAT, stride, c);
2571 CHECK("glVertexPointer");
2573 case GL_T4F_C4F_N3F_V4F:
2575 stride = 4*F + 4*F + 3*F + 4*F;
2576 jwzgles_glEnableClientState (GL_TEXTURE_COORD_ARRAY);
2577 glTexCoordPointer (4, GL_FLOAT, stride, c);
2578 CHECK("glTexCoordPointer");
2580 jwzgles_glEnableClientState (GL_COLOR_ARRAY);
2581 glColorPointer (4, GL_FLOAT, stride, c);
2582 CHECK("glColorPointer");
2584 jwzgles_glEnableClientState (GL_NORMAL_ARRAY);
2585 glNormalPointer (GL_FLOAT, stride, c);
2586 CHECK("glNormalPointer");
2588 glVertexPointer (3, GL_FLOAT, stride, c);
2589 CHECK("glVertexPointer");
2592 Assert (0, "glInterleavedArrays: bogus format");
2603 jwzgles_glEnableClientState (GLuint cap)
2605 if (state->compiling_list)
2609 list_push ("glEnableClientState",
2610 (list_fn_cb) &jwzgles_glEnableClientState,
2615 if (! state->replaying_list)
2616 LOG2 ("direct %-12s %s", "glEnableClientState", mode_desc(cap));
2617 glEnableClientState (cap); /* the real one */
2618 CHECK("glEnableClientState");
2622 case GL_VERTEX_ARRAY:
2623 state->enabled |= ISENABLED_VERT_ARRAY;
2625 case GL_NORMAL_ARRAY:
2626 if (! state->compiling_verts)
2627 state->set.ncount += 2;
2628 state->enabled |= ISENABLED_NORM_ARRAY;
2630 case GL_TEXTURE_COORD_ARRAY:
2631 if (! state->compiling_verts)
2632 state->set.tcount += 2;
2633 state->enabled |= ISENABLED_TEX_ARRAY;
2635 case GL_COLOR_ARRAY:
2636 if (! state->compiling_verts)
2637 state->set.ccount += 2;
2638 state->enabled |= ISENABLED_COLOR_ARRAY;
2646 jwzgles_glDisableClientState (GLuint cap)
2648 if (state->compiling_list)
2652 list_push ("glDisableClientState",
2653 (list_fn_cb) &jwzgles_glDisableClientState,
2658 if (! state->replaying_list)
2659 LOG2 ("direct %-12s %s", "glDisableClientState", mode_desc(cap));
2660 glDisableClientState (cap); /* the real one */
2661 CHECK("glDisableClientState");
2665 case GL_VERTEX_ARRAY:
2666 state->enabled &= ~ISENABLED_VERT_ARRAY;
2668 case GL_NORMAL_ARRAY:
2669 if (! state->compiling_verts)
2670 state->set.ncount = 0;
2671 state->enabled &= ~ISENABLED_NORM_ARRAY;
2673 case GL_TEXTURE_COORD_ARRAY:
2674 if (! state->compiling_verts)
2675 state->set.tcount = 0;
2676 state->enabled &= ~ISENABLED_TEX_ARRAY;
2678 case GL_COLOR_ARRAY:
2679 if (! state->compiling_verts)
2680 state->set.ccount = 0;
2681 state->enabled &= ~ISENABLED_COLOR_ARRAY;
2690 jwzgles_glMultMatrixf (const GLfloat *m)
2692 Assert (!state->compiling_verts,
2693 "glMultMatrixf not allowed inside glBegin");
2694 if (state->compiling_list)
2698 for (i = 0; i < countof(vv); i++)
2700 list_push ("glMultMatrixf", (list_fn_cb) &jwzgles_glMultMatrixf,
2705 if (! state->replaying_list)
2706 LOG1 ("direct %-12s", "glMultMatrixf");
2707 glMultMatrixf (m); /* the real one */
2708 CHECK("glMultMatrixf");
2714 jwzgles_glClearIndex(GLfloat c)
2716 /* Does GLES even do indexed color? */
2717 Assert (0, "glClearIndex unimplemented");
2722 jwzgles_glBitmap (GLsizei width, GLsizei height, GLfloat xorig, GLfloat yorig,
2723 GLfloat xmove, GLfloat ymove, const GLubyte *bitmap)
2725 Assert (0, "glBitmap unimplemented");
2729 jwzgles_glPushAttrib(int flags)
2731 Assert (0, "glPushAttrib unimplemented");
2735 jwzgles_glPopAttrib(void)
2737 Assert (0, "glPopAttrib unimplemented");
2741 /* These are needed for object hit detection in pinion.
2742 Might need to rewrite that code entirely. Punt for now.
2745 jwzgles_glInitNames (void)
2747 /* Assert (0, "glInitNames unimplemented");*/
2751 jwzgles_glPushName (GLuint name)
2753 /* Assert (0, "glPushName unimplemented");*/
2757 jwzgles_glPopName (void)
2759 /* Assert (0, "glPopName unimplemented");*/
2764 jwzgles_glRenderMode (GLuint mode)
2766 /* Assert (0, "glRenderMode unimplemented");*/
2771 jwzgles_glSelectBuffer (GLsizei size, GLuint *buf)
2773 /* Assert (0, "glSelectBuffer unimplemented");*/
2778 jwzgles_glGenTextures (GLuint n, GLuint *ret)
2780 Assert (!state->compiling_verts,
2781 "glGenTextures not allowed inside glBegin");
2782 /* technically legal, but stupid! */
2783 Assert (!state->compiling_list,
2784 "glGenTextures not allowed inside glNewList");
2785 if (! state->replaying_list)
2786 LOG1 ("direct %-12s", "glGenTextures");
2787 glGenTextures (n, ret); /* the real one */
2788 CHECK("glGenTextures");
2792 /* return the next larger power of 2. */
2797 while (i < value) i <<= 1;
2802 jwzgles_glTexImage1D (GLenum target, GLint level,
2803 GLint internalFormat,
2804 GLsizei width, GLint border,
2805 GLenum format, GLenum type,
2808 Assert (!state->compiling_verts, "glTexImage1D not allowed inside glBegin");
2809 /* technically legal, but stupid! */
2810 Assert (!state->compiling_list, "glTexImage1D inside glNewList");
2811 Assert (width == to_pow2(width), "width must be a power of 2");
2813 if (target == GL_TEXTURE_1D) target = GL_TEXTURE_2D;
2814 jwzgles_glTexImage2D (target, level, internalFormat, width, 1,
2815 border, format, type, data);
2819 jwzgles_glTexImage2D (GLenum target,
2821 GLint internalFormat,
2829 GLvoid *d2 = (GLvoid *) data;
2830 Assert (!state->compiling_verts, "glTexImage2D not allowed inside glBegin");
2831 Assert (!state->compiling_list, /* technically legal, but stupid! */
2832 "glTexImage2D not allowed inside glNewList");
2834 Assert (width == to_pow2(width), "width must be a power of 2");
2835 Assert (height == to_pow2(height), "height must be a power of 2");
2837 /* OpenGLES no longer supports "4" as a synonym for "RGBA". */
2838 switch (internalFormat) {
2839 case 1: internalFormat = GL_LUMINANCE; break;
2840 case 2: internalFormat = GL_LUMINANCE_ALPHA; break;
2841 case 3: internalFormat = GL_RGB; break;
2842 case 4: internalFormat = GL_RGBA; break;
2845 /* GLES does not let us omit the data pointer to create a blank texture. */
2848 d2 = (GLvoid *) calloc (1, width * height * sizeof(GLfloat) * 4);
2849 Assert (d2, "out of memory");
2852 if (internalFormat == GL_RGB && format == GL_RGBA)
2853 internalFormat = GL_RGBA; /* WTF */
2854 if (type == GL_UNSIGNED_INT_8_8_8_8_REV)
2855 type = GL_UNSIGNED_BYTE;
2857 if (! state->replaying_list)
2858 LOG10 ("direct %-12s %s %d %s %d %d %d %s %s 0x%lX", "glTexImage2D",
2859 mode_desc(target), level, mode_desc(internalFormat),
2860 width, height, border, mode_desc(format), mode_desc(type),
2861 (unsigned long) d2);
2862 glTexImage2D (target, level, internalFormat, width, height, border,
2863 format, type, d2); /* the real one */
2864 CHECK("glTexImage2D");
2866 if (d2 != data) free (d2);
2870 jwzgles_glTexSubImage2D (GLenum target, GLint level,
2871 GLint xoffset, GLint yoffset,
2872 GLsizei width, GLsizei height,
2873 GLenum format, GLenum type,
2874 const GLvoid *pixels)
2876 Assert (!state->compiling_verts,
2877 "glTexSubImage2D not allowed inside glBegin");
2878 Assert (!state->compiling_list, /* technically legal, but stupid! */
2879 "glTexSubImage2D not allowed inside glNewList");
2881 if (! state->replaying_list)
2882 LOG10 ("direct %-12s %s %d %d %d %d %d %s %s 0x%lX", "glTexSubImage2D",
2883 mode_desc(target), level, xoffset, yoffset, width, height,
2884 mode_desc (format), mode_desc (type), (unsigned long) pixels);
2885 glTexSubImage2D (target, level, xoffset, yoffset, width, height,
2886 format, type, pixels); /* the real one */
2887 CHECK("glTexSubImage2D");
2891 jwzgles_glCopyTexImage2D (GLenum target, GLint level, GLenum internalformat,
2892 GLint x, GLint y, GLsizei width, GLsizei height,
2895 Assert (!state->compiling_verts,
2896 "glCopyTexImage2D not allowed inside glBegin");
2897 Assert (!state->compiling_list, /* technically legal, but stupid! */
2898 "glCopyTexImage2D not allowed inside glNewList");
2899 if (! state->replaying_list)
2900 LOG9 ("direct %-12s %s %d %s %d %d %d %d %d", "glCopyTexImage2D",
2901 mode_desc(target), level, mode_desc(internalformat),
2902 x, y, width, height, border);
2903 glCopyTexImage2D (target, level, internalformat, x, y, width, height,
2904 border); /* the real one */
2905 CHECK("glCopyTexImage2D");
2910 jwzgles_glTexGenfv (GLenum coord, GLenum pname, const GLfloat *params)
2912 /* OpenGLES doesn't have this at all!
2913 "Oh, just rewrite that code to use GPU shaders", they say.
2914 How fucking convenient.
2916 So, when this is enabled, we could emit a GL_TEXTURE_COORD_ARRAY
2917 and compute coords for each vertex in the current GL_VERTEX_ARRAY
2918 as per http://www.opengl.org/wiki/Mathematics_of_glTexGen
2919 but holy shit, what a pain in the ass!
2921 For GL_OBJECT_LINEAR, we can just re-use the vertex array as
2922 the texture array, using a proper stride. That's hardly worth
2923 the effort, though, because bouncingcow is the only hack that
2924 uses that, and not even by default.
2926 Assert (coord == GL_S || coord == GL_T, "glTexGenfv: unimplemented coord");
2928 /* This is probably default-ish, so do nothing. */
2929 if (pname == GL_EYE_PLANE) return;
2931 Assert (pname == GL_TEXTURE_GEN_MODE, "glTexGenfv: unimplemented name");
2932 Assert (params[0] == GL_EYE_LINEAR, "glTexGenfv: unimplemented mode");
2936 jwzgles_glTexGeni (GLenum coord, GLenum pname, GLint param)
2939 jwzgles_glTexGenfv (coord, pname, &v);
2944 jwzgles_gluBuild2DMipmaps (GLenum target,
2945 GLint internalFormat,
2952 /* Not really bothering with mipmapping; only making one level.
2953 Note that this required a corresponding hack in glTexParameterf().
2956 int w2 = to_pow2(width);
2957 int h2 = to_pow2(height);
2959 void *d2 = (void *) data;
2961 /* OpenGLES no longer supports "4" as a synonym for "RGBA". */
2962 switch (internalFormat) {
2963 case 1: internalFormat = GL_LUMINANCE; break;
2964 case 2: internalFormat = GL_LUMINANCE_ALPHA; break;
2965 case 3: internalFormat = GL_RGB; break;
2966 case 4: internalFormat = GL_RGBA; break;
2969 /* if (w2 < h2) w2 = h2;
2970 if (h2 < w2) h2 = w2;*/
2972 if (w2 != width || h2 != height)
2974 /* Scale up the image bits to fit the power-of-2 texture.
2975 We have to do this because the mipmap API assumes that
2976 the texture bits go to texture coordinates 1.0 x 1.0.
2977 This could be more efficient, but it doesn't happen often.
2979 int istride = (format == GL_RGBA ? 4 : 3);
2981 int ibpl = istride * width;
2982 int obpl = ostride * w2;
2984 const unsigned char *in = (unsigned char *) data;
2985 unsigned char *out = (void *) malloc (h2 * obpl);
2986 Assert (out, "out of memory");
2989 for (oy = 0; oy < h2; oy++)
2991 int iy = oy * height / h2;
2992 const unsigned char *iline = in + (iy * ibpl);
2993 unsigned char *oline = out + (oy * obpl);
2995 for (ox = 0; ox < w2; ox++)
2997 int ix = ox * width / w2;
2998 const unsigned char *i = iline + (ix * istride);
2999 unsigned char *o = oline + (ox * ostride);
3000 *o++ = *i++; /* R */
3001 *o++ = *i++; /* G */
3002 *o++ = *i++; /* B */
3003 *o++ = (istride == 4 ? *i : 0xFF); /* A */
3008 internalFormat = GL_RGBA;
3012 jwzgles_glTexImage2D (target, 0, internalFormat, w2, h2, 0,
3014 if (d2 != data) free (d2);
3021 jwzgles_glRectf (GLfloat x1, GLfloat y1, GLfloat x2, GLfloat y2)
3023 jwzgles_glBegin (GL_POLYGON);
3024 jwzgles_glVertex2f (x1, y1);
3025 jwzgles_glVertex2f (x2, y1);
3026 jwzgles_glVertex2f (x2, y2);
3027 jwzgles_glVertex2f (x1, y2);
3032 jwzgles_glRecti (GLint x1, GLint y1, GLint x2, GLint y2)
3034 jwzgles_glRectf (x1, y1, x2, y2);
3038 jwzgles_glClearDepth (GLfloat d)
3040 /* Not sure what to do here */
3041 Assert (d == 1.0, "glClearDepth unimplemented");
3046 jwzgles_glEnable (GLuint bit)
3048 Assert (!state->compiling_verts, "glEnable not allowed inside glBegin");
3049 if (state->compiling_list)
3053 list_push ("glEnable", (list_fn_cb) &jwzgles_glEnable, PROTO_I, vv);
3057 if (! state->replaying_list)
3058 LOG2 ("direct %-12s %s", "glEnable", mode_desc(bit));
3059 glEnable (bit); /* the real one */
3063 case GL_TEXTURE_2D: state->enabled |= ISENABLED_TEXTURE_2D; break;
3064 case GL_TEXTURE_GEN_S: state->enabled |= ISENABLED_TEXTURE_GEN_S; break;
3065 case GL_TEXTURE_GEN_T: state->enabled |= ISENABLED_TEXTURE_GEN_T; break;
3066 case GL_LIGHTING: state->enabled |= ISENABLED_LIGHTING; break;
3067 case GL_BLEND: state->enabled |= ISENABLED_BLEND; break;
3068 case GL_DEPTH_TEST: state->enabled |= ISENABLED_DEPTH_TEST; break;
3069 case GL_CULL_FACE: state->enabled |= ISENABLED_CULL_FACE; break;
3070 case GL_NORMALIZE: state->enabled |= ISENABLED_NORMALIZE; break;
3071 case GL_FOG: state->enabled |= ISENABLED_FOG; break;
3072 case GL_COLOR_MATERIAL: state->enabled |= ISENABLED_COLMAT; break;
3074 /* Do these work with glEnable or only with glEnableClientState? */
3075 case GL_VERTEX_ARRAY: state->enabled |= ISENABLED_VERT_ARRAY; break;
3076 case GL_NORMAL_ARRAY: state->enabled |= ISENABLED_NORM_ARRAY; break;
3077 case GL_TEXTURE_COORD_ARRAY: state->enabled |= ISENABLED_TEX_ARRAY;break;
3078 case GL_COLOR_ARRAY: state->enabled |= ISENABLED_COLOR_ARRAY; break;
3087 jwzgles_glDisable (GLuint bit)
3089 Assert (!state->compiling_verts, "glDisable not allowed inside glBegin");
3090 if (state->compiling_list)
3094 list_push ("glDisable", (list_fn_cb) &jwzgles_glDisable, PROTO_I, vv);
3098 if (! state->replaying_list)
3099 LOG2 ("direct %-12s %s", "glDisable", mode_desc(bit));
3100 glDisable (bit); /* the real one */
3104 case GL_TEXTURE_2D: state->enabled &= ~ISENABLED_TEXTURE_2D; break;
3105 case GL_TEXTURE_GEN_S: state->enabled &= ~ISENABLED_TEXTURE_GEN_S; break;
3106 case GL_TEXTURE_GEN_T: state->enabled &= ~ISENABLED_TEXTURE_GEN_T; break;
3107 case GL_LIGHTING: state->enabled &= ~ISENABLED_LIGHTING; break;
3108 case GL_BLEND: state->enabled &= ~ISENABLED_BLEND; break;
3109 case GL_DEPTH_TEST: state->enabled &= ~ISENABLED_DEPTH_TEST; break;
3110 case GL_CULL_FACE: state->enabled &= ~ISENABLED_CULL_FACE; break;
3111 case GL_NORMALIZE: state->enabled &= ~ISENABLED_NORMALIZE; break;
3112 case GL_FOG: state->enabled &= ~ISENABLED_FOG; break;
3113 case GL_COLOR_MATERIAL: state->enabled &= ~ISENABLED_COLMAT; break;
3115 /* Do these work with glEnable or only with glEnableClientState? */
3116 case GL_VERTEX_ARRAY: state->enabled &= ~ISENABLED_VERT_ARRAY; break;
3117 case GL_NORMAL_ARRAY: state->enabled &= ~ISENABLED_NORM_ARRAY; break;
3118 case GL_TEXTURE_COORD_ARRAY: state->enabled &= ~ISENABLED_TEX_ARRAY;break;
3119 case GL_COLOR_ARRAY: state->enabled &= ~ISENABLED_COLOR_ARRAY; break;
3128 jwzgles_glIsEnabled (GLuint bit)
3131 Assert (!state->compiling_verts, "glIsEnabled not allowed inside glBegin");
3132 Assert (!state->compiling_list, "glIsEnabled not allowed inside glNewList");
3135 case GL_TEXTURE_2D: return !!(state->enabled & ISENABLED_TEXTURE_2D);
3136 case GL_TEXTURE_GEN_S: return !!(state->enabled & ISENABLED_TEXTURE_GEN_S);
3137 case GL_TEXTURE_GEN_T: return !!(state->enabled & ISENABLED_TEXTURE_GEN_T);
3138 case GL_LIGHTING: return !!(state->enabled & ISENABLED_LIGHTING);
3139 case GL_BLEND: return !!(state->enabled & ISENABLED_BLEND);
3140 case GL_DEPTH_TEST: return !!(state->enabled & ISENABLED_DEPTH_TEST);
3141 case GL_CULL_FACE: return !!(state->enabled & ISENABLED_CULL_FACE);
3142 case GL_NORMALIZE: return !!(state->enabled & ISENABLED_NORMALIZE);
3143 case GL_FOG: return !!(state->enabled & ISENABLED_FOG);
3144 case GL_COLOR_MATERIAL: return !!(state->enabled & ISENABLED_COLMAT);
3146 /* Do these work with glEnable or only with glEnableClientState?
3147 We need to query them, and there is no glIsClientStateEnabled.
3149 case GL_VERTEX_ARRAY: return !!(state->enabled & ISENABLED_VERT_ARRAY);
3150 case GL_NORMAL_ARRAY: return !!(state->enabled & ISENABLED_NORM_ARRAY);
3151 case GL_TEXTURE_COORD_ARRAY: return !!(state->enabled & ISENABLED_TEX_ARRAY);
3152 case GL_COLOR_ARRAY: return !!(state->enabled & ISENABLED_COLOR_ARRAY);
3153 default: Assert (0, "glIsEnabled unimplemented bit"); break;
3158 /* The spec says that OpenGLES 1.x doesn't implement glGetFloatv.
3159 Were this true, it would suck, for it would mean that there was no
3160 way to retrieve the prevailing matrixes. To implement this, we'd
3161 have to keep track of them all on the client side by combining in
3162 all the actions of glMultMatrixf, glRotatef, etc.
3164 However, Apple's iOS OpenGLES *does* provide glGetFloatv!
3167 jwzgles_glGetFloatv (GLenum pname, GLfloat *params)
3169 if (! state->replaying_list)
3170 LOG2 ("direct %-12s %s", "glGetFloatv", mode_desc(pname));
3171 glGetFloatv (pname, params); /* the real one */
3172 CHECK("glGetFloatv");
3176 /* Likewise: not supposed to be there, but it is. */
3178 jwzgles_glGetPointerv (GLenum pname, GLvoid *params)
3180 if (! state->replaying_list)
3181 LOG2 ("direct %-12s %s", "glGetPointerv", mode_desc(pname));
3182 glGetPointerv (pname, params); /* the real one */
3183 CHECK("glGetPointerv");
3187 /* How many cells are written into the *params array.
3188 We need to know this to avoid smashing the caller's stack
3189 if they asked for a single-value parameter.
3192 glGet_ret_count (GLenum pname)
3195 /*case GL_COLOR_MATRIX: */
3196 case GL_MODELVIEW_MATRIX:
3197 case GL_PROJECTION_MATRIX:
3198 case GL_TEXTURE_MATRIX:
3199 /*case GL_TRANSPOSE_COLOR_MATRIX: */
3200 /*case GL_TRANSPOSE_MODELVIEW_MATRIX: */
3201 /*case GL_TRANSPOSE_PROJECTION_MATRIX: */
3202 /*case GL_TRANSPOSE_TEXTURE_MATRIX: */
3204 /*case GL_ACCUM_CLEAR_VALUE: */
3205 /*case GL_BLEND_COLOR: */
3206 case GL_COLOR_CLEAR_VALUE:
3207 case GL_COLOR_WRITEMASK:
3208 case GL_CURRENT_COLOR:
3209 /*case GL_CURRENT_RASTER_COLOR: */
3210 /*case GL_CURRENT_RASTER_POSITION: */
3211 /*case GL_CURRENT_RASTER_SECONDARY_COLOR: */
3212 /*case GL_CURRENT_RASTER_TEXTURE_COORDS: */
3213 /*case GL_CURRENT_SECONDARY_COLOR: */
3214 case GL_CURRENT_TEXTURE_COORDS:
3216 case GL_LIGHT_MODEL_AMBIENT:
3217 /*case GL_MAP2_GRID_DOMAIN: */
3218 case GL_SCISSOR_BOX:
3221 case GL_CURRENT_NORMAL:
3222 case GL_POINT_DISTANCE_ATTENUATION:
3224 case GL_ALIASED_LINE_WIDTH_RANGE:
3225 case GL_ALIASED_POINT_SIZE_RANGE:
3226 case GL_DEPTH_RANGE:
3227 /*case GL_LINE_WIDTH_RANGE: */
3228 /*case GL_MAP1_GRID_DOMAIN: */
3229 /*case GL_MAP2_GRID_SEGMENTS: */
3230 case GL_MAX_VIEWPORT_DIMS:
3231 /*case GL_POINT_SIZE_RANGE: */
3232 case GL_POLYGON_MODE:
3233 case GL_SMOOTH_LINE_WIDTH_RANGE:
3234 case GL_SMOOTH_POINT_SIZE_RANGE:
3243 jwzgles_glGetDoublev (GLenum pname, GLdouble *params)
3246 int i, j = glGet_ret_count (pname);
3247 jwzgles_glGetFloatv (pname, m);
3248 for (i = 0; i < j; i++)
3254 jwzgles_glGetIntegerv (GLenum pname, GLint *params)
3257 int i, j = glGet_ret_count (pname);
3258 jwzgles_glGetFloatv (pname, m);
3259 for (i = 0; i < j; i++)
3265 jwzgles_glGetBooleanv (GLenum pname, GLboolean *params)
3268 int i, j = glGet_ret_count (pname);
3269 jwzgles_glGetFloatv (pname, m);
3270 for (i = 0; i < j; i++)
3271 params[i] = (m[i] != 0.0);
3276 jwzgles_gluErrorString (GLenum error)
3279 sprintf (s, "0x%lX", (unsigned long) error);
3284 /* These four *Pointer calls (plus glBindBuffer and glBufferData) can
3285 be included inside glNewList, but they actually execute immediately
3286 anyway, because their data is recorded in the list by the
3287 subsequently-recorded call to glDrawArrays. This is a little weird.
3290 jwzgles_glVertexPointer (GLuint size, GLuint type, GLuint stride,
3293 if (! state->replaying_list)
3294 LOG5 ("direct %-12s %d %s %d 0x%lX", "glVertexPointer",
3295 size, mode_desc(type), stride, (unsigned long) ptr);
3296 glVertexPointer (size, type, stride, ptr); /* the real one */
3297 CHECK("glVertexPointer");
3301 jwzgles_glNormalPointer (GLuint type, GLuint stride, const GLvoid *ptr)
3303 if (! state->replaying_list)
3304 LOG4 ("direct %-12s %s %d 0x%lX", "glNormalPointer",
3305 mode_desc(type), stride, (unsigned long) ptr);
3306 glNormalPointer (type, stride, ptr); /* the real one */
3307 CHECK("glNormalPointer");
3311 jwzgles_glColorPointer (GLuint size, GLuint type, GLuint stride,
3314 if (! state->replaying_list)
3315 LOG5 ("direct %-12s %d %s %d 0x%lX", "glColorPointer",
3316 size, mode_desc(type), stride, (unsigned long) ptr);
3317 glColorPointer (size, type, stride, ptr); /* the real one */
3318 CHECK("glColorPointer");
3322 jwzgles_glTexCoordPointer (GLuint size, GLuint type, GLuint stride,
3325 if (! state->replaying_list)
3326 LOG5 ("direct %-12s %d %s %d 0x%lX", "glTexCoordPointer",
3327 size, mode_desc(type), stride, (unsigned long) ptr);
3328 glTexCoordPointer (size, type, stride, ptr); /* the real one */
3329 CHECK("glTexCoordPointer");
3333 jwzgles_glBindBuffer (GLuint target, GLuint buffer)
3335 if (! state->replaying_list)
3336 LOG3 ("direct %-12s %s %d", "glBindBuffer", mode_desc(target), buffer);
3337 glBindBuffer (target, buffer); /* the real one */
3338 CHECK("glBindBuffer");
3342 jwzgles_glBufferData (GLenum target, GLsizeiptr size, const void *data,
3345 if (! state->replaying_list)
3346 LOG5 ("direct %-12s %s %ld 0x%lX %s", "glBufferData",
3347 mode_desc(target), size, (unsigned long) data, mode_desc(usage));
3348 glBufferData (target, size, data, usage); /* the real one */
3349 CHECK("glBufferData");
3354 jwzgles_glTexParameterf (GLuint target, GLuint pname, GLfloat param)
3356 Assert (!state->compiling_verts,
3357 "glTexParameterf not allowed inside glBegin");
3359 /* We don't *really* implement mipmaps, so just turn this off. */
3360 if (param == GL_LINEAR_MIPMAP_LINEAR) param = GL_LINEAR;
3361 if (param == GL_NEAREST_MIPMAP_LINEAR) param = GL_LINEAR;
3362 if (param == GL_LINEAR_MIPMAP_NEAREST) param = GL_NEAREST;
3363 if (param == GL_NEAREST_MIPMAP_NEAREST) param = GL_NEAREST;
3365 /* We implement 1D textures as 2D textures. */
3366 if (target == GL_TEXTURE_1D) target = GL_TEXTURE_2D;
3368 /* Apparently this is another invalid enum. Just ignore it. */
3369 if ((pname == GL_TEXTURE_WRAP_S || pname == GL_TEXTURE_WRAP_T) &&
3373 if (state->compiling_list)
3379 list_push ("glTexParameterf", (list_fn_cb) &jwzgles_glTexParameterf,
3384 if (! state->replaying_list)
3385 LOG4 ("direct %-12s %s %s %7.3f", "glTexParameterf",
3386 mode_desc(target), mode_desc(pname), param);
3387 glTexParameterf (target, pname, param); /* the real one */
3388 CHECK("glTexParameterf");
3393 jwzgles_glTexParameteri (GLuint target, GLuint pname, GLuint param)
3395 jwzgles_glTexParameterf (target, pname, param);
3400 jwzgles_glBindTexture (GLuint target, GLuint texture)
3402 Assert (!state->compiling_verts,
3403 "glBindTexture not allowed inside glBegin");
3405 /* We implement 1D textures as 2D textures. */
3406 if (target == GL_TEXTURE_1D) target = GL_TEXTURE_2D;
3408 if (state->compiling_list)
3413 list_push ("glBindTexture", (list_fn_cb) &jwzgles_glBindTexture,
3418 if (! state->replaying_list)
3419 LOG3 ("direct %-12s %s %d", "glBindTexture",
3420 mode_desc(target), texture);
3421 glBindTexture (target, texture); /* the real one */
3422 CHECK("glBindTexture");
3428 /* Matrix functions, mostly cribbed from Mesa.
3432 jwzgles_glFrustum (GLfloat left, GLfloat right,
3433 GLfloat bottom, GLfloat top,
3434 GLfloat near, GLfloat far)
3437 GLfloat x = (2 * near) / (right-left);
3438 GLfloat y = (2 * near) / (top - bottom);
3439 GLfloat a = (right + left) / (right - left);
3440 GLfloat b = (top + bottom) / (top - bottom);
3441 GLfloat c = -(far + near) / (far - near);
3442 GLfloat d = -(2 * far * near) / (far - near);
3444 # define M(X,Y) m[Y * 4 + X]
3445 M(0,0) = x; M(0,1) = 0; M(0,2) = a; M(0,3) = 0;
3446 M(1,0) = 0; M(1,1) = y; M(1,2) = b; M(1,3) = 0;
3447 M(2,0) = 0; M(2,1) = 0; M(2,2) = c; M(2,3) = d;
3448 M(3,0) = 0; M(3,1) = 0; M(3,2) = -1; M(3,3) = 0;
3451 jwzgles_glMultMatrixf (m);
3456 jwzgles_glOrtho (GLfloat left, GLfloat right,
3457 GLfloat bottom, GLfloat top,
3458 GLfloat near, GLfloat far)
3461 GLfloat a = 2 / (right - left);
3462 GLfloat b = -(right + left) / (right - left);
3463 GLfloat c = 2 / (top - bottom);
3464 GLfloat d = -(top + bottom) / (top - bottom);
3465 GLfloat e = -2 / (far - near);
3466 GLfloat f = -(far + near) / (far - near);
3468 # define M(X,Y) m[Y * 4 + X]
3469 M(0,0) = a; M(0,1) = 0; M(0,2) = 0; M(0,3) = b;
3470 M(1,0) = 0; M(1,1) = c; M(1,2) = 0; M(1,3) = d;
3471 M(2,0) = 0; M(2,1) = 0; M(2,2) = e; M(2,3) = f;
3472 M(3,0) = 0; M(3,1) = 0; M(3,2) = 0; M(3,3) = 1;
3475 jwzgles_glMultMatrixf (m);
3480 jwzgles_gluPerspective (GLdouble fovy, GLdouble aspect,
3481 GLdouble near, GLdouble far)
3485 double rad = fovy / 2 * M_PI / 180;
3490 if (dz == 0 || si == 0 || aspect == 0)
3496 c = -(far + near) / dz;
3497 d = -2 * near * far / dz;
3499 # define M(X,Y) m[Y * 4 + X]
3500 M(0,0) = a; M(0,1) = 0; M(0,2) = 0; M(0,3) = 0;
3501 M(1,0) = 0; M(1,1) = b; M(1,2) = 0; M(1,3) = 0;
3502 M(2,0) = 0; M(2,1) = 0; M(2,2) = c; M(2,3) = d;
3503 M(3,0) = 0; M(3,1) = 0; M(3,2) = -1; M(3,3) = 0;
3506 jwzgles_glMultMatrixf (m);
3511 jwzgles_gluLookAt (GLfloat eyex, GLfloat eyey, GLfloat eyez,
3512 GLfloat centerx, GLfloat centery, GLfloat centerz,
3513 GLfloat upx, GLfloat upy, GLfloat upz)
3516 GLfloat x[3], y[3], z[3];
3519 /* Make rotation matrix */
3522 z[0] = eyex - centerx;
3523 z[1] = eyey - centery;
3524 z[2] = eyez - centerz;
3525 mag = sqrt(z[0] * z[0] + z[1] * z[1] + z[2] * z[2]);
3526 if (mag) { /* mpichler, 19950515 */
3537 /* X vector = Y cross Z */
3538 x[0] = y[1] * z[2] - y[2] * z[1];
3539 x[1] = -y[0] * z[2] + y[2] * z[0];
3540 x[2] = y[0] * z[1] - y[1] * z[0];
3542 /* Recompute Y = Z cross X */
3543 y[0] = z[1] * x[2] - z[2] * x[1];
3544 y[1] = -z[0] * x[2] + z[2] * x[0];
3545 y[2] = z[0] * x[1] - z[1] * x[0];
3547 /* mpichler, 19950515 */
3548 /* cross product gives area of parallelogram, which is < 1.0 for
3549 * non-perpendicular unit-length vectors; so normalize x, y here
3552 mag = sqrt(x[0] * x[0] + x[1] * x[1] + x[2] * x[2]);
3559 mag = sqrt(y[0] * y[0] + y[1] * y[1] + y[2] * y[2]);
3566 #define M(row,col) m[col*4+row]
3567 M(0, 0) = x[0]; M(0, 1) = x[1]; M(0, 2) = x[2]; M(0, 3) = 0.0;
3568 M(1, 0) = y[0]; M(1, 1) = y[1]; M(1, 2) = y[2]; M(1, 3) = 0.0;
3569 M(2, 0) = z[0]; M(2, 1) = z[1]; M(2, 2) = z[2]; M(2, 3) = 0.0;
3570 M(3, 0) = 0.0; M(3, 1) = 0.0; M(3, 2) = 0.0; M(3, 3) = 1.0;
3573 jwzgles_glMultMatrixf(m);
3575 /* Translate Eye to Origin */
3576 jwzgles_glTranslatef(-eyex, -eyey, -eyez);
3580 static void __gluMultMatrixVecd (const GLdouble matrix[16],
3581 const GLdouble in[4],
3586 for (i=0; i<4; i++) {
3588 in[0] * matrix[0*4+i] +
3589 in[1] * matrix[1*4+i] +
3590 in[2] * matrix[2*4+i] +
3591 in[3] * matrix[3*4+i];
3596 jwzgles_gluProject (GLdouble objx, GLdouble objy, GLdouble objz,
3597 const GLdouble modelMatrix[16],
3598 const GLdouble projMatrix[16],
3599 const GLint viewport[4],
3600 GLdouble *winx, GLdouble *winy, GLdouble *winz)
3605 /* #### I suspect this is not working right. I was seeing crazy values
3606 in lament.c. Maybe there's some float-vs-double confusion going on?
3613 __gluMultMatrixVecd(modelMatrix, in, out);
3614 __gluMultMatrixVecd(projMatrix, out, in);
3615 if (in[3] == 0.0) return(GL_FALSE);
3619 /* Map x, y and z to range 0-1 */
3620 in[0] = in[0] * 0.5 + 0.5;
3621 in[1] = in[1] * 0.5 + 0.5;
3622 in[2] = in[2] * 0.5 + 0.5;
3624 /* Map x,y to viewport */
3625 in[0] = in[0] * viewport[2] + viewport[0];
3626 in[1] = in[1] * viewport[3] + viewport[1];
3635 /* The following functions are present in both OpenGL 1.1 and in OpenGLES 1,
3636 but are allowed within glNewList/glEndList, so we must wrap them to allow
3637 them to either be recorded in lists, or run directly.
3639 All this CPP obscenity is me screaming in rage at all the ways that C is
3640 not Lisp, as all I want to do here is DEFADVICE.
3643 #define PROTO_V PROTO_VOID
3644 #define TYPE_V GLuint
3646 #define VARS_V /* */
3648 #define FILL_V /* */
3650 #define TYPE_I GLuint
3651 #define TYPE_II TYPE_I
3652 #define TYPE_III TYPE_I
3653 #define TYPE_IIII TYPE_I
3654 #define ARGS_I TYPE_I a
3655 #define ARGS_II TYPE_I a, TYPE_I b
3656 #define ARGS_III TYPE_I a, TYPE_I b, TYPE_I c
3657 #define ARGS_IIII TYPE_I a, TYPE_I b, TYPE_I c, TYPE_I d
3658 #define LOGS_I "%s\n", mode_desc(a)
3659 #define LOGS_II "%s %d\n", mode_desc(a), b
3660 #define LOGS_III "%s %s %s\n", mode_desc(a), mode_desc(b), mode_desc(c)
3661 #define LOGS_IIII "%d %d %d %d\n", a, b, c, d
3663 #define VARS_II a, b
3664 #define VARS_III a, b, c
3665 #define VARS_IIII a, b, c, d
3666 #define FILL_I vv[0].i = a;
3667 #define FILL_II vv[0].i = a; vv[1].i = b;
3668 #define FILL_III vv[0].i = a; vv[1].i = b; vv[2].i = c;
3669 #define FILL_IIII vv[0].i = a; vv[1].i = b; vv[2].i = c; vv[3].i = d;
3671 #define TYPE_F GLfloat
3672 #define TYPE_FF TYPE_F
3673 #define TYPE_FFF TYPE_F
3674 #define TYPE_FFFF TYPE_F
3675 #define ARGS_F TYPE_F a
3676 #define ARGS_FF TYPE_F a, TYPE_F b
3677 #define ARGS_FFF TYPE_F a, TYPE_F b, TYPE_F c
3678 #define ARGS_FFFF TYPE_F a, TYPE_F b, TYPE_F c, TYPE_F d
3679 #define LOGS_F "%7.3f\n", a
3680 #define LOGS_FF "%7.3f %7.3f\n", a, b
3681 #define LOGS_FFF "%7.3f %7.3f %7.3f\n", a, b, c
3682 #define LOGS_FFFF "%7.3f %7.3f %7.3f %7.3f\n", a, b, c, d
3683 #define VARS_F VARS_I
3684 #define VARS_FF VARS_II
3685 #define VARS_FFF VARS_III
3686 #define VARS_FFFF VARS_IIII
3687 #define FILL_F vv[0].f = a;
3688 #define FILL_FF vv[0].f = a; vv[1].f = b;
3689 #define FILL_FFF vv[0].f = a; vv[1].f = b; vv[2].f = c;
3690 #define FILL_FFFF vv[0].f = a; vv[1].f = b; vv[2].f = c; vv[3].f = d;
3692 #define ARGS_IF TYPE_I a, TYPE_F b
3693 #define VARS_IF VARS_II
3694 #define LOGS_IF "%s %7.3f\n", mode_desc(a), b
3695 #define FILL_IF vv[0].i = a; vv[1].f = b;
3697 #define ARGS_IIF TYPE_I a, TYPE_I b, TYPE_F c
3698 #define VARS_IIF VARS_III
3699 #define LOGS_IIF "%s %s %7.3f\n", mode_desc(a), mode_desc(b), c
3700 #define FILL_IIF vv[0].i = a; vv[1].i = b; vv[2].f = c;
3702 #define TYPE_IV GLint
3703 #define ARGS_IIV TYPE_I a, const TYPE_IV *b
3704 #define VARS_IIV VARS_II
3705 #define LOGS_IIV "%s %d %d %d %d\n", mode_desc(a), b[0], b[1], b[2], b[3]
3706 #define FILL_IIV vv[0].i = a; \
3707 vv[1].i = b[0]; vv[2].i = b[1]; \
3708 vv[3].i = b[2]; vv[4].i = b[3];
3710 #define ARGS_IFV TYPE_I a, const TYPE_F *b
3711 #define VARS_IFV VARS_II
3712 #define LOGS_IFV "%s %7.3f %7.3f %7.3f %7.3f\n", mode_desc(a), \
3713 b[0], b[1], b[2], b[3]
3714 #define FILL_IFV vv[0].i = a; \
3715 vv[1].f = b[0]; vv[2].f = b[1]; \
3716 vv[3].f = b[2]; vv[4].f = b[3];
3718 #define ARGS_IIIV TYPE_I a, TYPE_I b, const TYPE_IV *c
3719 #define VARS_IIIV VARS_III
3720 #define LOGS_IIIV "%s %-8s %3d %3d %3d %3d\n", mode_desc(a), mode_desc(b), \
3721 c[0], c[1], c[2], c[3]
3722 #define FILL_IIIV vv[0].i = a; vv[1].i = b; \
3723 vv[2].i = c[0]; vv[3].i = c[1]; \
3724 vv[4].i = c[2]; vv[5].i = c[3];
3726 #define ARGS_IIFV TYPE_I a, TYPE_I b, const TYPE_F *c
3727 #define VARS_IIFV VARS_III
3728 #define LOGS_IIFV "%s %-8s %7.3f %7.3f %7.3f %7.3f\n", \
3729 mode_desc(a), mode_desc(b), \
3730 c[0], c[1], c[2], c[3]
3731 #define FILL_IIFV vv[0].i = a; vv[1].i = b; \
3732 vv[2].f = c[0]; vv[3].f = c[1]; \
3733 vv[4].f = c[2]; vv[5].f = c[3];
3736 # define WLOG(NAME,ARGS) \
3737 fprintf (stderr, "jwzgles: direct %-12s ", NAME); \
3738 fprintf (stderr, ARGS)
3740 # define WLOG(NAME,ARGS) /* */
3743 #define WRAP(NAME,SIG) \
3744 void jwzgles_##NAME (ARGS_##SIG) \
3746 Assert (!state->compiling_verts, \
3747 STRINGIFY(NAME) " not allowed inside glBegin"); \
3748 if (state->compiling_list) { \
3751 list_push (STRINGIFY(NAME), (list_fn_cb) &jwzgles_##NAME, \
3754 if (! state->replaying_list) { \
3755 WLOG (STRINGIFY(NAME), LOGS_##SIG); \
3757 NAME (VARS_##SIG); \
3758 CHECK(STRINGIFY(NAME)); \
3762 WRAP (glActiveTexture, I)
3763 WRAP (glAlphaFunc, IF)
3764 WRAP (glBlendFunc, II)
3766 WRAP (glClearColor, FFFF)
3767 WRAP (glClearStencil, I)
3768 WRAP (glColorMask, IIII)
3769 WRAP (glCullFace, I)
3770 WRAP (glDepthFunc, I)
3771 WRAP (glDepthMask, I)
3776 WRAP (glFrontFace, I)
3778 WRAP (glLightModelf, IF)
3779 WRAP (glLightModelfv, IFV)
3780 WRAP (glLightf, IIF)
3781 WRAP (glLightfv, IIFV)
3782 WRAP (glLineWidth, F)
3783 WRAP (glLoadIdentity, V)
3785 WRAP (glMatrixMode, I)
3786 WRAP (glPixelStorei, II)
3787 WRAP (glPointSize, F)
3788 WRAP (glPolygonOffset, FF)
3789 WRAP (glPopMatrix, V)
3790 WRAP (glPushMatrix, V)
3791 WRAP (glRotatef, FFFF)
3792 WRAP (glScalef, FFF)
3793 WRAP (glScissor, IIII)
3794 WRAP (glShadeModel, I)
3795 WRAP (glStencilFunc, III)
3796 WRAP (glStencilMask, I)
3797 WRAP (glStencilOp, III)
3798 WRAP (glTexEnvf, IIF)
3799 WRAP (glTexEnvi, III)
3800 WRAP (glTranslatef, FFF)
3801 WRAP (glViewport, IIII)
3803 #define TYPE_IV GLuint
3804 WRAP (glDeleteTextures, IIV)
3807 #endif /* HAVE_JWZGLES - whole file */