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! Lockward used to do that,
122 before I fixed it to not.
124 - Not every function is implemented; just the ones that I needed for
125 xscreensaver. However, the trivial ones are trivial to enable
126 as they come up. Harder ones will be harder.
128 As a result of that, these savers look wrong:
130 atlantis Uses EYE_PLANE.
131 blocktube Uses SPHERE_MAP.
132 dnalogo Uses GLUtesselator.
133 extrusion Uses all kinds of GLUT crap.
134 flyingtoasters Uses SPHERE_MAP.
135 winduprobot Uses SPHERE_MAP.
136 jigglypuff Uses SPHERE_MAP (in chrome mode), GL_LINE (in wireframe)
137 jigsaw Uses GLUtesselator.
138 pinion Uses glSelectBuffer and gluPickMatrix for mouse-clicks.
139 pipes Uses glMap2f for the Utah Teapot.
140 polyhedra Uses GLUtesselator (concave objects); also Utah Teapot.
141 skytentacles Uses GL_LINE in -cel mode.
142 timetunnel Uses GL_CONSTANT_ALPHA and all kinds of other stuff.
151 #endif /* HAVE_CONFIG_H */
153 #ifdef HAVE_JWZGLES /* whole file */
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>
170 #elif defined(HAVE_ANDROID)
171 # include <GLES/gl.h>
173 # ifndef GL_GLEXT_PROTOTYPES
174 # define GL_GLEXT_PROTOTYPES /* for glBindBuffer */
180 #include "jwzglesI.h"
182 #define STRINGIFY(X) #X
185 #define countof(x) (sizeof((x))/sizeof((*x)))
190 extern void jwxyz_abort (const char *fmt, ...) __dead2;
191 # define Assert(C,S) do { if (!(C)) { jwxyz_abort ("%s",S); }} while(0)
193 # define Assert(C,S) do { \
195 fprintf (stderr, "jwzgles: %s\n", S); \
201 typedef struct { GLfloat x, y, z; } XYZ;
202 typedef struct { GLfloat x, y, z, w; } XYZW;
203 typedef struct { GLfloat s, t, r, q; } STRQ;
204 typedef struct { GLfloat r, g, b, a; } RGBA;
207 /* Used to record all calls to glVertex3f, glNormal3f, etc.
208 while inside glBegin / glEnd so that we can convert that
209 to a single call to glDrawArrays.
213 int count, size; /* size of each array */
215 XYZW *verts; /* Arrays being built */
220 int ncount; /* How many normals, tex coords and colors were */
221 int tcount; /* used. We optimize based on "0, 1, or many". */
223 int materialistic; /* Whether glMaterial was called inside glBegin */
225 XYZ cnorm; /* Prevailing normal/texture/color while building */
232 typedef void (*list_fn_cb) (void);
235 /* We need this nonsense because you can't cast a double to a void*
236 or vice versa. They tend to be passed in different registers,
237 and you need to know about that because it's still 1972 here.
240 const void *v; GLfloat f; GLuint i; GLshort s; GLdouble d;
243 typedef struct { /* saved args for glDrawArrays */
244 int binding, size, type, stride, bytes;
248 typedef enum { /* shorthand describing arglist signature */
249 PROTO_VOID, /* no args */
250 PROTO_I, /* 1 int arg */
251 PROTO_F, /* 1 float arg */
252 PROTO_II, /* int, int */
253 PROTO_FF, /* float, float */
254 PROTO_IF, /* int, float */
255 PROTO_III, /* int, int, int */
256 PROTO_FFF, /* float, float, float */
257 PROTO_IIF, /* int, int, float */
258 PROTO_IIII, /* int, int, int, int */
259 PROTO_FFFF, /* float, float, float, float */
260 PROTO_IIV, /* int, int[4] */
261 PROTO_IFV, /* int, float[4] */
262 PROTO_IIIV, /* int, int, int[4] */
263 PROTO_IIFV, /* int, int, float[4] */
264 PROTO_FV16, /* float[16] */
265 PROTO_ARRAYS /* glDrawArrays */
268 typedef struct { /* A single element of a display list */
270 list_fn_cb fn; /* saved function pointer */
271 fn_proto proto; /* arglist prototype */
272 draw_array *arrays; /* args for glDrawArrays */
273 void_int argv[16]; /* args for everything else */
277 typedef struct { /* a display list: saved activity within glNewList */
282 /* Named buffer that should be freed when this display list is deleted. */
288 typedef struct { /* All display lists */
294 #define ISENABLED_TEXTURE_2D (1<<0)
295 #define ISENABLED_TEXTURE_GEN_S (1<<1)
296 #define ISENABLED_TEXTURE_GEN_T (1<<2)
297 #define ISENABLED_TEXTURE_GEN_R (1<<3)
298 #define ISENABLED_TEXTURE_GEN_Q (1<<4)
299 #define ISENABLED_LIGHTING (1<<5)
300 #define ISENABLED_BLEND (1<<6)
301 #define ISENABLED_DEPTH_TEST (1<<7)
302 #define ISENABLED_CULL_FACE (1<<8)
303 #define ISENABLED_NORMALIZE (1<<9)
304 #define ISENABLED_FOG (1<<10)
305 #define ISENABLED_COLMAT (1<<11)
306 #define ISENABLED_VERT_ARRAY (1<<12)
307 #define ISENABLED_NORM_ARRAY (1<<13)
308 #define ISENABLED_TEX_ARRAY (1<<14)
309 #define ISENABLED_COLOR_ARRAY (1<<15)
310 #define ISENABLED_ALPHA_TEST (1<<16)
315 GLfloat obj[4], eye[4];
319 typedef struct { /* global state */
321 vert_set set; /* set being built */
323 int compiling_list; /* list id if inside glNewList; 0 means immediate */
324 int replaying_list; /* depth of call stack to glCallList */
325 int compiling_verts; /* inside glBegin */
327 list_set lists; /* saved lists */
329 unsigned long enabled; /* enabled flags, immediate mode */
330 unsigned long list_enabled; /* and for the list-in-progress */
332 texgen_state s, t, r, q;
337 static jwzgles_state *state = 0;
341 # define LOG(A) fprintf(stderr,"jwzgles: " A "\n")
342 # define LOG1(A,B) fprintf(stderr,"jwzgles: " A "\n",B)
343 # define LOG2(A,B,C) fprintf(stderr,"jwzgles: " A "\n",B,C)
344 # define LOG3(A,B,C,D) fprintf(stderr,"jwzgles: " A "\n",B,C,D)
345 # define LOG4(A,B,C,D,E) fprintf(stderr,"jwzgles: " A "\n",B,C,D,E)
346 # define LOG5(A,B,C,D,E,F) fprintf(stderr,"jwzgles: " A "\n",B,C,D,E,F)
347 # define LOG6(A,B,C,D,E,F,G) fprintf(stderr,"jwzgles: " A "\n",B,C,D,E,F,G)
348 # define LOG7(A,B,C,D,E,F,G,H) fprintf(stderr,"jwzgles: " A "\n",B,C,D,E,F,G,H)
349 # define LOG8(A,B,C,D,E,F,G,H,I)\
350 fprintf(stderr,"jwzgles: "A "\n",B,C,D,E,F,G,H,I)
351 # define LOG9(A,B,C,D,E,F,G,H,I,J)\
352 fprintf(stderr,"jwzgles: "A "\n",B,C,D,E,F,G,H,I,J)
353 # define LOG10(A,B,C,D,E,F,G,H,I,J,K)\
354 fprintf(stderr,"jwzgles: "A "\n",B,C,D,E,F,G,H,I,J,K)
355 # define LOG17(A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R)\
356 fprintf(stderr,"jwzgles: "A "\n",B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R)
357 # define CHECK(S) check_gl_error(S)
359 # define LOG(A) /* */
360 # define LOG1(A,B) /* */
361 # define LOG2(A,B,C) /* */
362 # define LOG3(A,B,C,D) /* */
363 # define LOG4(A,B,C,D,E) /* */
364 # define LOG5(A,B,C,D,E,F) /* */
365 # define LOG6(A,B,C,D,E,F,G) /* */
366 # define LOG7(A,B,C,D,E,F,G,H) /* */
367 # define LOG8(A,B,C,D,E,F,G,H,I) /* */
368 # define LOG9(A,B,C,D,E,F,G,H,I,J) /* */
369 # define LOG10(A,B,C,D,E,F,G,H,I,J,K) /* */
370 # define LOG17(A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R) /* */
371 # define CHECK(S) /* */
376 mode_desc (int mode) /* for debugging messages */
379 # define SS(X) case GL_##X: return STRINGIFY(X);
383 SS(AMBIENT_AND_DIFFUSE)
399 SS(COLOR_ARRAY_BUFFER_BINDING);
401 SS(COLOR_MATERIAL_FACE)
402 SS(COLOR_MATERIAL_PARAMETER)
414 SS(ELEMENT_ARRAY_BUFFER)
427 SS(INVALID_OPERATION)
435 SS(LIGHT_MODEL_AMBIENT)
436 SS(LIGHT_MODEL_COLOR_CONTROL)
437 SS(LIGHT_MODEL_LOCAL_VIEWER)
438 SS(LIGHT_MODEL_TWO_SIDE)
441 SS(LINEAR_MIPMAP_LINEAR)
442 SS(LINEAR_MIPMAP_NEAREST)
453 SS(NEAREST_MIPMAP_LINEAR)
454 SS(NEAREST_MIPMAP_NEAREST)
457 SS(NORMAL_ARRAY_BUFFER_BINDING);
460 SS(ONE_MINUS_DST_ALPHA)
461 SS(ONE_MINUS_DST_COLOR)
462 SS(ONE_MINUS_SRC_ALPHA)
463 SS(ONE_MINUS_SRC_COLOR)
468 SS(POLYGON_OFFSET_FILL)
484 SS(SEPARATE_SPECULAR_COLOR)
493 SS(SRC_ALPHA_SATURATE)
498 SS(STENCIL_BUFFER_BIT)
510 SS(TEXTURE_ALPHA_SIZE)
511 SS(TEXTURE_BINDING_2D)
512 SS(TEXTURE_BLUE_SIZE)
514 SS(TEXTURE_BORDER_COLOR)
515 SS(TEXTURE_COMPONENTS)
516 SS(TEXTURE_COORD_ARRAY)
517 SS(TEXTURE_COORD_ARRAY_BUFFER_BINDING);
519 SS(TEXTURE_ENV_COLOR)
526 SS(TEXTURE_GREEN_SIZE)
528 SS(TEXTURE_INTENSITY_SIZE)
529 SS(TEXTURE_LUMINANCE_SIZE)
530 SS(TEXTURE_MAG_FILTER)
531 SS(TEXTURE_MIN_FILTER)
539 SS(UNPACK_ROW_LENGTH)
541 SS(UNSIGNED_INT_8_8_8_8_REV)
546 SS(VERTEX_ARRAY_BUFFER_BINDING);
547 /*SS(COLOR_BUFFER_BIT) -- same value as GL_LIGHT0 */
549 case (GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT):
550 return "DEPTH_BUFFER_BIT | COLOR_BUFFER_BIT";
551 /* Oops, same as INVALID_ENUM.
552 case (GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT):
553 return "DEPTH_BUFFER_BIT | STENCIL_BUFFER_BIT";
555 case (GL_COLOR_BUFFER_BIT | GL_STENCIL_BUFFER_BIT):
556 return "COLOR_BUFFER_BIT | STENCIL_BUFFER_BIT";
557 case (GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT | GL_STENCIL_BUFFER_BIT):
558 return "DEPTH_BUFFER_BIT | COLOR_BUFFER_BIT | STENCIL_BUFFER_BIT";
561 static char buf[255];
562 sprintf (buf, "0x%04X", mode);
569 check_gl_error (const char *s)
571 GLenum i = glGetError();
572 if (i == GL_NO_ERROR) return;
573 fprintf (stderr, "jwzgles: GL ERROR: %s: %s\n", s, mode_desc(i));
580 make_room (const char *name, void **array, int span, int *count, int *size)
582 if (*count + 1 >= *size)
584 int new_size = (*count + 20) * 1.2; /* mildly exponential */
585 *array = realloc (*array, new_size * span);
586 Assert (*array, "out of memory");
587 /* LOG3("%s: grew %d -> %d", name, *size, new_size); */
597 state = (jwzgles_state *) calloc (1, sizeof (*state));
599 if (state->lists.lists)
601 state->compiling_list = 0;
602 if (state->lists.count)
603 jwzgles_glDeleteLists (1, state->lists.count);
604 free (state->lists.lists);
607 if (state->set.verts) free (state->set.verts);
608 if (state->set.norms) free (state->set.norms);
609 if (state->set.tex) free (state->set.tex);
610 if (state->set.color) free (state->set.color);
612 memset (state, 0, sizeof(*state));
614 state->s.mode = state->t.mode = state->r.mode = state->q.mode =
616 state->s.obj[0] = state->s.eye[0] = 1; /* s = 1 0 0 0 */
617 state->t.obj[1] = state->t.eye[1] = 1; /* t = 0 1 0 0 */
622 jwzgles_glGenLists (int n)
627 Assert (!state->compiling_verts, "glGenLists not allowed inside glBegin");
629 /* Ensure space in state->lists, clear the one at the end, and tick counter
630 Note that lists are never really deleted, and we can never re-use elements
631 of this array. glDeleteLists zeroes out the contents of the list, but
632 the list ID is still valid for use with glNewList forever.
633 #### So maybe this should be a linked list instead of an array.
635 for (i = 0; i < n; i++)
639 make_room ("glGenLists",
640 (void **) &state->lists.lists,
641 sizeof (*state->lists.lists),
642 &state->lists.count, &state->lists.size);
643 state->lists.count++;
644 id = state->lists.count;
645 L = &state->lists.lists[id-1];
647 memset (L, 0, sizeof (*L));
649 if (ret == 0) ret = id;
650 LOG1("glGenLists -> %d", L->id);
653 /* Return the ID of the first list allocated */
660 jwzgles_glNewList (int id, int mode)
663 Assert (id > 0 && id <= state->lists.count, "glNewList: bogus ID");
664 Assert (mode == GL_COMPILE, "glNewList: bad mode");
665 Assert (!state->compiling_verts, "glNewList not allowed inside glBegin");
666 Assert (!state->compiling_list, "nested glNewList");
667 Assert (state->set.count == 0, "missing glEnd");
669 L = &state->lists.lists[id-1];
670 Assert (L->id == id, "glNewList corrupted");
672 if (L->count != 0) jwzgles_glDeleteLists (L->id, 1); /* Overwriting */
673 Assert (L->count == 0, "glNewList corrupted");
675 state->compiling_list = id;
677 state->list_enabled = state->enabled;
679 LOG1("glNewList -> %d", id);
683 static void save_arrays (list_fn *, int);
684 static void restore_arrays (list_fn *, int);
685 static void copy_array_data (draw_array *, int, const char *);
686 static void optimize_arrays (void);
687 static void generate_texture_coords (GLuint, GLuint);
691 jwzgles_glEndList (void)
693 Assert (state->compiling_list, "extra glEndList");
694 Assert (state->set.count == 0, "missing glEnd");
695 Assert (!state->compiling_verts, "glEndList not allowed inside glBegin");
696 LOG1("glEndList %d", state->compiling_list);
698 state->compiling_list = 0;
699 state->list_enabled = state->enabled;
704 list_push (const char * const name,
705 list_fn_cb fn, fn_proto proto, void_int *av)
711 Assert (state->compiling_list > 0, "not inside glNewList");
712 Assert (state->compiling_list <= state->lists.count, "glNewList corrupted");
714 L = &state->lists.lists[state->compiling_list-1];
715 Assert (L, "glNewList: no list");
717 make_room ("glNewLists",
718 (void **) &L->fns, sizeof (*L->fns),
719 &L->count, &L->size);
720 memset (&L->fns[L->count], 0, sizeof (*L->fns));
721 F = L->fns + L->count;
726 if (proto != PROTO_VOID)
727 for (i = 0; i < countof(F->argv); i++)
733 LOG1 (" push %-12s", name);
736 if (fn == (list_fn_cb) &jwzgles_glBegin ||
737 fn == (list_fn_cb) &jwzgles_glFrontFace ||
738 fn == (list_fn_cb) &jwzgles_glEnable ||
739 fn == (list_fn_cb) &jwzgles_glDisable ||
740 fn == (list_fn_cb) &jwzgles_glEnableClientState ||
741 fn == (list_fn_cb) &jwzgles_glDisableClientState ||
742 fn == (list_fn_cb) &jwzgles_glShadeModel ||
743 fn == (list_fn_cb) &jwzgles_glMatrixMode)
744 LOG2 (" push %-12s %s", name, mode_desc (av[0].i));
746 LOG2 (" push %-12s %d", name, av[0].i);
749 LOG2 (" push %-12s %7.3f", name, av[0].f);
752 if (fn == (list_fn_cb) &jwzgles_glBindTexture ||
753 fn == (list_fn_cb) &jwzgles_glBindBuffer)
754 LOG3 (" push %-12s %s %d", name, mode_desc (av[0].i), av[1].i);
756 LOG3 (" push %-12s %d %d", name, av[0].i, av[1].i);
759 LOG3 (" push %-12s %7.3f %7.3f", name, av[0].f, av[1].f);
762 LOG3 (" push %-12s %s %7.3f", name, mode_desc (av[0].i), av[1].f);
766 if (fn == (list_fn_cb) &jwzgles_glDrawArrays ||
767 fn == (list_fn_cb) &jwzgles_glTexParameteri)
768 LOG4 (" push %-12s %s %d %d", name, mode_desc (av[0].i),
771 LOG4 (" push %-12s %d %d %d", name, av[0].i, av[1].i, av[2].i);
774 LOG4 (" push %-12s %7.3f %7.3f %7.3f", name, av[0].f, av[1].f, av[2].f);
777 LOG4 (" push %-12s %s %s %7.3f", name,
778 mode_desc(av[0].i), mode_desc(av[1].i), av[2].f);
781 LOG5 (" push %-12s %d %d %d %d", name,
782 av[0].i, av[1].i, av[2].i, av[3].i);
785 LOG5 (" push %-12s %7.3f %7.3f %7.3f %7.3f", name,
786 av[0].f, av[1].f, av[2].f, av[3].f);
789 LOG6 (" push %-12s %s %3.1f %3.1f %3.1f %3.1f", name, mode_desc (av[0].i),
790 av[1].f, av[2].f, av[3].f, av[4].f);
793 LOG6 (" push %-12s %s %d %d %d %d", name, mode_desc (av[0].i),
794 av[1].i, av[2].i, av[3].i, av[4].i);
797 LOG7 (" push %-12s %s %-8s %3.1f %3.1f %3.1f %3.1f", name,
798 mode_desc (av[0].i), mode_desc (av[1].i),
799 av[2].f, av[3].f, av[4].f, av[5].f);
802 LOG7 (" push %-12s %s %-8s %3d %3d %3d %3d", name,
803 mode_desc (av[0].i), mode_desc (av[1].i),
804 av[2].i, av[3].i, av[4].i, av[5].i);
807 LOG17 (" push %-12s ["
808 "%8.3f %8.3f %8.3f %8.3f " "\n\t\t\t "
809 "%8.3f %8.3f %8.3f %8.3f " "\n\t\t\t "
810 "%8.3f %8.3f %8.3f %8.3f " "\n\t\t\t "
811 "%8.3f %8.3f %8.3f %8.3f ]",
813 av[0].f, av[1].f, av[2].f, av[3].f,
814 av[4].f, av[5].f, av[6].f, av[7].f,
815 av[8].f, av[9].f, av[10].f, av[11].f,
816 av[12].f, av[13].f, av[14].f, av[15].f);
819 Assert (0, "bogus prototype");
824 if (proto == PROTO_ARRAYS) /* glDrawArrays */
825 save_arrays (F, av[1].i + av[2].i);
832 jwzgles_glBegin (int mode)
834 Assert (!state->compiling_verts, "nested glBegin");
835 state->compiling_verts++;
837 /* Only these commands are allowed inside glBegin:
839 glVertex -- not allowed outside
850 glArrayElement -- not allowed outside
857 if (!state->replaying_list)
858 LOG2 ("%sglBegin %s",
859 (state->compiling_list || state->replaying_list ? " " : ""),
862 Assert (state->set.count == 0, "glBegin corrupted");
863 state->set.mode = mode;
864 state->set.count = 0;
865 state->set.ncount = 0;
866 state->set.tcount = 0;
867 state->set.ccount = 0;
872 jwzgles_glDeleteLists (int id0, int range)
874 Assert (!state->compiling_verts, "glDeleteLists not allowed inside glBegin");
876 if (state->compiling_list)
881 list_push ("glDeleteLists", (list_fn_cb) &jwzgles_glDeleteLists,
888 if (!state->replaying_list)
889 LOG2 ("glDeleteLists %d %d", id0, range);
891 for (id = id0 + range - 1; id >= id0; id--)
895 if (id == 0) continue; /* People do this stupid thing */
896 if (id > state->lists.count) break; /* this too */
897 Assert (id > 0 && id <= state->lists.count,
898 "glDeleteLists: bogus ID");
899 L = &state->lists.lists[id-1];
900 Assert (L->id == id, "glDeleteLists corrupted");
902 for (i = 0; i < L->count; i++)
904 list_fn *lf = &L->fns[i];
908 for (j = 0; j < 4; j++)
909 /* If there's a binding, 'data' is an index, not a ptr. */
910 if (!lf->arrays[j].binding &&
912 free (lf->arrays[j].data);
919 glDeleteBuffers (1, &L->buffer);
921 memset (L, 0, sizeof (*L));
929 jwzgles_glIsList (GLuint id)
931 return (id > 0 && id < state->lists.count);
937 jwzgles_glNormal3fv (const GLfloat *v)
939 if (state->compiling_list && !state->compiling_verts)
945 list_push ("glNormal3f", (list_fn_cb) &jwzgles_glNormal3f,
950 if (!state->replaying_list)
951 LOG5 ("%s%sglNormal3f %7.3f %7.3f %7.3f",
952 (state->compiling_list || state->replaying_list ? " " : ""),
953 (state->compiling_verts ? " rec " : ""),
956 if (state->compiling_verts) /* inside glBegin */
958 state->set.cnorm.x = v[0];
959 state->set.cnorm.y = v[1];
960 state->set.cnorm.z = v[2];
962 if (state->set.count > 0 && state->set.ncount == 1) /* not first! */
965 else /* outside glBegin */
967 glNormal3f (v[0], v[1], v[2]);
975 jwzgles_glNormal3f (GLfloat x, GLfloat y, GLfloat z)
981 jwzgles_glNormal3fv (v);
986 jwzgles_glTexCoord4fv (const GLfloat *v)
988 if (state->compiling_list && !state->compiling_verts)
995 list_push ("glTexCoord4f", (list_fn_cb) &jwzgles_glTexCoord4f,
1000 if (!state->replaying_list)
1001 LOG6 ("%s%sglTexCoord4f %7.3f %7.3f %7.3f %7.3f",
1002 (state->compiling_list || state->replaying_list ? " " : ""),
1003 (state->compiling_verts ? " rec " : ""),
1004 v[0], v[1], v[2], v[3]);
1006 Assert (state->compiling_verts, "glTexCoord4fv outside glBegin");
1008 if (state->compiling_verts) /* inside glBegin */
1010 state->set.ctex.s = v[0];
1011 state->set.ctex.t = v[1];
1012 state->set.ctex.r = v[2];
1013 state->set.ctex.q = v[3];
1014 state->set.tcount++;
1015 if (state->set.count > 0 && state->set.tcount == 1) /* not first! */
1016 state->set.tcount++;
1023 jwzgles_glTexCoord4f (GLfloat s, GLfloat t, GLfloat r, GLfloat q)
1030 jwzgles_glTexCoord4fv (v);
1035 jwzgles_glTexCoord3fv (const GLfloat *v)
1042 jwzgles_glTexCoord4fv (vv);
1047 jwzgles_glTexCoord2fv (const GLfloat *v)
1054 jwzgles_glTexCoord4fv (vv);
1059 jwzgles_glTexCoord3f (GLfloat s, GLfloat t, GLfloat r)
1061 jwzgles_glTexCoord4f (s, t, r, 1);
1066 jwzgles_glTexCoord2f (GLfloat s, GLfloat t)
1068 jwzgles_glTexCoord4f (s, t, 0, 1);
1073 jwzgles_glTexCoord1f (GLfloat s)
1075 jwzgles_glTexCoord4f (s, 0, 0, 1);
1079 /* glColor: GLfloat */
1082 jwzgles_glColor4fv (const GLfloat *v)
1084 if (state->compiling_list && !state->compiling_verts)
1091 list_push ("glColor4f", (list_fn_cb) &jwzgles_glColor4f,
1096 if (!state->replaying_list)
1097 LOG6 ("%s%sglColor4f %7.3f %7.3f %7.3f %7.3f",
1098 (state->compiling_list || state->replaying_list ? " " : ""),
1099 (state->compiling_verts ? " rec " : ""),
1100 v[0], v[1], v[2], v[3]);
1102 if (state->compiling_verts) /* inside glBegin */
1104 state->set.ccolor.r = v[0];
1105 state->set.ccolor.g = v[1];
1106 state->set.ccolor.b = v[2];
1107 state->set.ccolor.a = v[3];
1108 state->set.ccount++;
1109 if (state->set.count > 0 && state->set.ccount == 1) /* not first! */
1110 state->set.ccount++;
1112 else /* outside glBegin */
1114 glColor4f (v[0], v[1], v[2], v[3]);
1122 jwzgles_glColor4f (GLfloat r, GLfloat g, GLfloat b, GLfloat a)
1129 jwzgles_glColor4fv (v);
1133 jwzgles_glColor3f (GLfloat r, GLfloat g, GLfloat b)
1135 jwzgles_glColor4f (r, g, b, 1);
1139 jwzgles_glColor3fv (const GLfloat *v)
1141 jwzgles_glColor3f (v[0], v[1], v[2]);
1145 /* glColor: GLdouble */
1148 jwzgles_glColor4d (GLdouble r, GLdouble g, GLdouble b, GLdouble a)
1150 jwzgles_glColor4f (r, g, b, a);
1154 jwzgles_glColor4dv (const GLdouble *v)
1156 jwzgles_glColor4d (v[0], v[1], v[2], v[3]);
1160 jwzgles_glColor3d (GLdouble r, GLdouble g, GLdouble b)
1162 jwzgles_glColor4d (r, g, b, 1.0);
1166 jwzgles_glColor3dv (const GLdouble *v)
1168 jwzgles_glColor3d (v[0], v[1], v[2]);
1172 /* glColor: GLint (INT_MIN - INT_MAX) */
1175 jwzgles_glColor4i (GLint r, GLint g, GLint b, GLint a)
1177 /* -0x8000000 - 0x7FFFFFFF => 0.0 - 1.0 */
1178 jwzgles_glColor4f (0.5 + (GLfloat) r / 0xFFFFFFFF,
1179 0.5 + (GLfloat) g / 0xFFFFFFFF,
1180 0.5 + (GLfloat) b / 0xFFFFFFFF,
1181 0.5 + (GLfloat) a / 0xFFFFFFFF);
1185 jwzgles_glColor4iv (const GLint *v)
1187 jwzgles_glColor4i (v[0], v[1], v[2], v[3]);
1192 jwzgles_glColor3i (GLint r, GLint g, GLint b)
1194 jwzgles_glColor4i (r, g, b, 0x7FFFFFFF);
1198 jwzgles_glColor3iv (const GLint *v)
1200 jwzgles_glColor3i (v[0], v[1], v[2]);
1204 /* glColor: GLuint (0 - UINT_MAX) */
1207 jwzgles_glColor4ui (GLuint r, GLuint g, GLuint b, GLuint a)
1209 /* 0 - 0xFFFFFFFF => 0.0 - 1.0 */
1210 jwzgles_glColor4f ((GLfloat) r / 0xFFFFFFFF,
1211 (GLfloat) g / 0xFFFFFFFF,
1212 (GLfloat) b / 0xFFFFFFFF,
1213 (GLfloat) a / 0xFFFFFFFF);
1217 jwzgles_glColor4uiv (const GLuint *v)
1219 jwzgles_glColor4ui (v[0], v[1], v[2], v[3]);
1223 jwzgles_glColor3ui (GLuint r, GLuint g, GLuint b)
1225 jwzgles_glColor4ui (r, g, b, 0xFFFFFFFF);
1229 jwzgles_glColor3uiv (const GLuint *v)
1231 jwzgles_glColor3ui (v[0], v[1], v[2]);
1235 /* glColor: GLshort (SHRT_MIN - SHRT_MAX) */
1238 jwzgles_glColor4s (GLshort r, GLshort g, GLshort b, GLshort a)
1240 /* -0x8000 - 0x7FFF => 0.0 - 1.0 */
1241 jwzgles_glColor4f (0.5 + (GLfloat) r / 0xFFFF,
1242 0.5 + (GLfloat) g / 0xFFFF,
1243 0.5 + (GLfloat) b / 0xFFFF,
1244 0.5 + (GLfloat) a / 0xFFFF);
1248 jwzgles_glColor4sv (const GLshort *v)
1250 jwzgles_glColor4s (v[0], v[1], v[2], v[3]);
1254 jwzgles_glColor3s (GLshort r, GLshort g, GLshort b)
1256 jwzgles_glColor4s (r, g, b, 0x7FFF);
1260 jwzgles_glColor3sv (const GLshort *v)
1262 jwzgles_glColor3s (v[0], v[1], v[2]);
1266 /* glColor: GLushort (0 - USHRT_MAX) */
1269 jwzgles_glColor4us (GLushort r, GLushort g, GLushort b, GLushort a)
1271 /* 0 - 0xFFFF => 0.0 - 1.0 */
1272 jwzgles_glColor4f ((GLfloat) r / 0xFFFF,
1273 (GLfloat) g / 0xFFFF,
1274 (GLfloat) b / 0xFFFF,
1275 (GLfloat) a / 0xFFFF);
1279 jwzgles_glColor4usv (const GLushort *v)
1281 jwzgles_glColor4us (v[0], v[1], v[2], v[3]);
1285 jwzgles_glColor3us (GLushort r, GLushort g, GLushort b)
1287 jwzgles_glColor4us (r, g, b, 0xFFFF);
1291 jwzgles_glColor3usv (const GLushort *v)
1293 jwzgles_glColor3us (v[0], v[1], v[2]);
1297 /* glColor: GLbyte (-128 - 127) */
1300 jwzgles_glColor4b (GLbyte r, GLbyte g, GLbyte b, GLbyte a)
1302 /* -128 - 127 => 0.0 - 1.0 */
1303 jwzgles_glColor4f (0.5 + (GLfloat) r / 255,
1304 0.5 + (GLfloat) g / 255,
1305 0.5 + (GLfloat) b / 255,
1306 0.5 + (GLfloat) a / 255);
1310 jwzgles_glColor4bv (const GLbyte *v)
1312 jwzgles_glColor4b (v[0], v[1], v[2], v[3]);
1316 jwzgles_glColor3b (GLbyte r, GLbyte g, GLbyte b)
1318 jwzgles_glColor4b (r, g, b, 127);
1322 jwzgles_glColor3bv (const GLbyte *v)
1324 jwzgles_glColor3b (v[0], v[1], v[2]);
1328 /* glColor: GLubyte (0 - 255) */
1331 jwzgles_glColor4ub (GLubyte r, GLubyte g, GLubyte b, GLubyte a)
1333 /* 0 - 255 => 0.0 - 1.0 */
1334 jwzgles_glColor4f (r / 255.0, g / 255.0, b / 255.0, a / 255.0);
1338 jwzgles_glColor4ubv (const GLubyte *v)
1340 jwzgles_glColor4ub (v[0], v[1], v[2], v[3]);
1344 jwzgles_glColor3ub (GLubyte r, GLubyte g, GLubyte b)
1346 jwzgles_glColor4ub (r, g, b, 255);
1350 jwzgles_glColor3ubv (const GLubyte *v)
1352 jwzgles_glColor3ub (v[0], v[1], v[2]);
1358 jwzgles_glMaterialfv (GLenum face, GLenum pname, const GLfloat *color)
1360 /* If this is called inside glBegin/glEnd with a front ambient color,
1361 then treat it the same as glColor: set the color of the upcoming
1364 Other faces or lighting types within glBegin are ignored.
1367 if (state->compiling_verts)
1369 if ((face == GL_FRONT ||
1370 face == GL_FRONT_AND_BACK) &&
1371 (pname == GL_AMBIENT ||
1372 pname == GL_DIFFUSE ||
1373 pname == GL_AMBIENT_AND_DIFFUSE))
1375 jwzgles_glColor4f (color[0], color[1], color[2], color[3]);
1376 state->set.materialistic++;
1379 LOG2 (" IGNORING glMaterialfv %s %s",
1380 mode_desc(face), mode_desc(pname));
1382 else if (state->compiling_list)
1391 list_push ("glMaterialfv", (list_fn_cb) &jwzgles_glMaterialfv,
1396 /* If this is called outside of glBegin/glEnd with a front
1397 ambient color, then the intent is presumably for that color
1398 to apply to the upcoming vertexes (which may be played back
1399 from a list that does not have vertex colors in it). In that
1400 case, the only way to make the colors show up is to call
1401 glColor() with GL_COLOR_MATERIAL enabled.
1403 I'm not sure if this will have other inappropriate side effects...
1405 if ((face == GL_FRONT ||
1406 face == GL_FRONT_AND_BACK) &&
1407 (pname == GL_AMBIENT ||
1408 pname == GL_DIFFUSE ||
1409 pname == GL_AMBIENT_AND_DIFFUSE))
1411 jwzgles_glEnable (GL_COLOR_MATERIAL);
1412 jwzgles_glColor4f (color[0], color[1], color[2], color[3]);
1415 /* OpenGLES seems to throw "invalid enum" for GL_FRONT -- but it
1416 goes ahead and sets the material anyway! No error if we just
1417 always use GL_FRONT_AND_BACK.
1419 if (face == GL_FRONT)
1420 face = GL_FRONT_AND_BACK;
1421 if (! state->replaying_list)
1422 LOG7 ("direct %-12s %s %s %7.3f %7.3f %7.3f %7.3f", "glMaterialfv",
1423 mode_desc(face), mode_desc(pname),
1424 color[0], color[1], color[2], color[3]);
1425 glMaterialfv (face, pname, color); /* the real one */
1426 CHECK("glMaterialfv");
1432 jwzgles_glMaterialiv (GLenum face, GLenum pname, const GLint *v)
1439 jwzgles_glMaterialfv (face, pname, vv);
1443 jwzgles_glMaterialf (GLenum face, GLenum pname, const GLfloat c)
1450 jwzgles_glMaterialfv (face, pname, vv);
1455 jwzgles_glMateriali (GLenum face, GLenum pname, const GLuint c)
1457 jwzgles_glMaterialf (face, pname, c);
1462 jwzgles_glColorMaterial (GLenum face, GLenum mode)
1464 Assert (!state->compiling_verts,
1465 "glColorMaterial not allowed inside glBegin");
1467 if (state->compiling_list)
1472 list_push ("glColorMaterial", (list_fn_cb) &jwzgles_glColorMaterial,
1477 /* No real analog to this distinction in OpenGLES, since color
1478 arrays don't distinguish between "color" and "material", */
1479 Assert (0, "glColorMaterial: unimplemented mode");
1488 jwzgles_glVertex4fv (const GLfloat *v)
1490 vert_set *s = &state->set;
1491 int count = s->count;
1493 Assert (state->compiling_verts, "glVertex4fv not inside glBegin");
1495 LOG5("%s rec glVertex4f %7.3f %7.3f %7.3f %7.3f",
1496 (state->compiling_list || state->replaying_list ? " " : ""),
1497 v[0], v[1], v[2], v[3]);
1499 if (count >= s->size - 1)
1501 int new_size = 20 + (s->size * 1.2);
1503 /* 4 arrays, different element sizes...
1504 We allocate all 4 arrays just in case we need them,
1505 but we might not end up using them all at the end.
1508 s->verts = (XYZW *) realloc (s->verts, new_size * sizeof (*s->verts));
1509 Assert (s->verts, "out of memory");
1511 s->norms = (XYZ *) realloc (s->norms, new_size * sizeof (*s->norms));
1512 Assert (s->norms, "out of memory");
1514 s->tex = (STRQ *) realloc (s->tex, new_size * sizeof (*s->tex));
1515 Assert (s->tex, "out of memory");
1517 s->color = (RGBA *) realloc (s->color, new_size * sizeof (*s->color));
1518 Assert (s->color, "out of memory");
1523 s->verts [count].x = v[0];
1524 s->verts [count].y = v[1];
1525 s->verts [count].z = v[2];
1526 s->verts [count].w = v[3];
1527 s->norms [count] = s->cnorm;
1528 s->tex [count] = s->ctex;
1529 s->color [count] = s->ccolor;
1535 jwzgles_glVertex4f (GLfloat x, GLfloat y, GLfloat z, GLfloat w)
1542 jwzgles_glVertex4fv (v);
1546 jwzgles_glVertex4i (GLint x, GLint y, GLint z, GLint w)
1548 jwzgles_glVertex4f (x, y, z, w);
1552 jwzgles_glVertex3f (GLfloat x, GLfloat y, GLfloat z)
1559 jwzgles_glVertex4fv (v);
1563 jwzgles_glVertex3i (GLint x, GLint y, GLint z)
1565 jwzgles_glVertex3f (x, y, z);
1569 jwzgles_glVertex3fv (const GLfloat *v)
1571 jwzgles_glVertex3f (v[0], v[1], v[2]);
1575 jwzgles_glVertex3dv (const GLdouble *v)
1577 jwzgles_glVertex3f (v[0], v[1], v[2]);
1582 jwzgles_glVertex2f (GLfloat x, GLfloat y)
1588 jwzgles_glVertex3fv (v);
1592 jwzgles_glVertex2fv (const GLfloat *v)
1594 jwzgles_glVertex2f (v[0], v[1]);
1598 jwzgles_glVertex2i (GLint x, GLint y)
1600 jwzgles_glVertex2f (x, y);
1605 jwzgles_glLightiv (GLenum light, GLenum pname, const GLint *params)
1612 jwzgles_glLightfv (light, pname, v);
1616 jwzgles_glLightModeliv (GLenum pname, const GLint *params)
1623 jwzgles_glLightModelfv (pname, v);
1627 jwzgles_glFogiv (GLenum pname, const GLint *params)
1634 jwzgles_glFogfv (pname, v);
1638 jwzgles_glLighti (GLenum light, GLenum pname, GLint param)
1640 jwzgles_glLightf (light, pname, param);
1644 jwzgles_glLightModeli (GLenum pname, GLint param)
1646 jwzgles_glLightModelf (pname, param);
1650 jwzgles_glFogi (GLenum pname, GLint param)
1652 jwzgles_glFogf (pname, param);
1657 jwzgles_glRotated (GLdouble angle, GLdouble x, GLdouble y, GLdouble z)
1659 jwzgles_glRotatef (angle, x, y, z);
1664 jwzgles_glClipPlane (GLenum plane, const GLdouble *equation)
1666 Assert (state->compiling_verts, "glClipPlane not inside glBegin");
1667 Assert (0, "glClipPlane unimplemented"); /* no GLES equivalent... */
1672 jwzgles_glPolygonMode (GLenum face, GLenum mode)
1674 Assert (!state->compiling_verts, "not inside glBegin");
1675 if (state->compiling_list)
1680 list_push ("glPolygonMode", (list_fn_cb) &jwzgles_glPolygonMode,
1685 /* POINT and LINE don't exist in GLES */
1686 Assert (mode == GL_FILL, "glPolygonMode: unimplemented mode");
1692 jwzgles_glDrawBuffer (GLenum buf)
1694 Assert (!state->compiling_verts, "not inside glBegin");
1695 if (state->compiling_list)
1699 list_push ("glDrawBuffer", (list_fn_cb) &jwzgles_glDrawBuffer,
1704 /* Assert (buf == GL_BACK, "glDrawBuffer: back buffer only"); */
1705 # ifndef GL_VERSION_ES_CM_1_0 /* not compiling against OpenGLES 1.x */
1706 if (! state->replaying_list)
1707 LOG1 ("direct %-12s", "glDrawBuffer");
1708 glDrawBuffer (buf); /* the real one */
1709 CHECK("glDrawBuffer");
1715 /* Given an array of sets of 4 elements of arbitrary size, convert it
1716 to an array of sets of 6 elements instead: ABCD becomes ABC BCD.
1719 cq2t (unsigned char **arrayP, int stride, int count)
1721 int count2 = count * 6 / 4;
1722 int size = stride * count;
1723 int size2 = stride * count2;
1724 const unsigned char *oarray, *in;
1725 unsigned char *array2, *oarray2, *out;
1729 if (!oarray || count == 0)
1732 array2 = (unsigned char *) malloc (size2);
1733 Assert (array2, "out of memory");
1738 for (i = 0; i < count / 4; i++)
1740 const unsigned char *a, *b, *c, *d; /* the 4 corners */
1741 a = in; in += stride;
1742 b = in; in += stride;
1743 c = in; in += stride;
1744 d = in; in += stride;
1746 # define PUSH(IN) do { \
1747 const unsigned char *ii = IN; \
1749 for (j = 0; j < stride; j++) { \
1753 PUSH (a); PUSH (b); PUSH (d); /* the 2 triangles */
1754 PUSH (b); PUSH (c); PUSH (d);
1758 Assert (in == oarray + size, "convert_quads corrupted");
1759 Assert (out == oarray2 + size2, "convert_quads corrupted");
1767 /* Convert all coordinates in a GL_QUADS vert_set to GL_TRIANGLES.
1770 convert_quads_to_triangles (vert_set *s)
1773 Assert (s->mode == GL_QUADS, "convert_quads bad mode");
1775 cq2t ((unsigned char **) &s->verts, sizeof(*s->verts), s->count);
1776 cq2t ((unsigned char **) &s->norms, sizeof(*s->norms), s->count);
1777 cq2t ((unsigned char **) &s->tex, sizeof(*s->tex), s->count);
1778 cq2t ((unsigned char **) &s->color, sizeof(*s->color), s->count);
1781 s->mode = GL_TRIANGLES;
1786 jwzgles_glEnd (void)
1788 vert_set *s = &state->set;
1789 int was_norm, was_tex, was_color, was_mat;
1790 int is_norm, is_tex, is_color, is_mat;
1792 Assert (state->compiling_verts == 1, "missing glBegin");
1793 state->compiling_verts--;
1795 Assert (!state->replaying_list, "how did glEnd get into a display list?");
1797 if (!state->replaying_list)
1799 LOG5 ("%s [V = %d, N = %d, T = %d, C = %d]",
1800 (state->compiling_list || state->replaying_list ? " " : ""),
1801 s->count, s->ncount, s->tcount, s->ccount);
1803 (state->compiling_list || state->replaying_list ? " " : ""));
1806 if (s->count == 0) return;
1808 if (s->mode == GL_QUADS)
1809 convert_quads_to_triangles (s);
1810 else if (s->mode == GL_QUAD_STRIP)
1811 s->mode = GL_TRIANGLE_STRIP; /* They do the same thing! */
1812 else if (s->mode == GL_POLYGON)
1813 s->mode = GL_TRIANGLE_FAN; /* They do the same thing! */
1815 jwzgles_glColorPointer (4,GL_FLOAT, sizeof(*s->color),s->color); /* RGBA */
1816 jwzgles_glNormalPointer ( GL_FLOAT, sizeof(*s->norms),s->norms); /* XYZ */
1817 jwzgles_glTexCoordPointer(4,GL_FLOAT, sizeof(*s->tex), s->tex); /* STRQ */
1818 jwzgles_glVertexPointer (4,GL_FLOAT, sizeof(*s->verts),s->verts); /* XYZW */
1819 /* glVertexPointer must come after glTexCoordPointer */
1821 /* If there were no calls to glNormal3f inside of glBegin/glEnd,
1822 don't bother enabling the normals array.
1824 If there was exactly *one* call to glNormal3f inside of glBegin/glEnd,
1825 and it was before the first glVertex3f, then also don't enable the
1826 normals array, but do emit that call to glNormal3f before calling
1829 Likewise for texture coordinates and colors.
1831 Be careful to leave the arrays' enabled/disabled state the same as
1832 before, or a later caller might end up using one of our arrays by
1833 mistake. (Remember that jwzgles_glIsEnabled() tracks the enablement
1834 of the list-in-progress as well as the global state.)
1836 was_norm = jwzgles_glIsEnabled (GL_NORMAL_ARRAY);
1837 was_tex = jwzgles_glIsEnabled (GL_TEXTURE_COORD_ARRAY);
1838 was_color = jwzgles_glIsEnabled (GL_COLOR_ARRAY);
1839 was_mat = jwzgles_glIsEnabled (GL_COLOR_MATERIAL);
1841 /* If we're executing glEnd in immediate mode, not from inside a display
1842 list (which is the only way it happens, because glEnd doesn't go into
1843 display lists), make sure we're not stomping on a saved buffer list:
1844 in immediate mode, vertexes are client-side only.
1846 if (! state->compiling_list)
1847 jwzgles_glBindBuffer (GL_ARRAY_BUFFER, 0);
1852 jwzgles_glEnableClientState (GL_NORMAL_ARRAY);
1858 jwzgles_glNormal3f (s->cnorm.x, s->cnorm.y, s->cnorm.z);
1859 jwzgles_glDisableClientState (GL_NORMAL_ARRAY);
1862 if (s->tcount > 1 ||
1863 ((state->compiling_list ? state->list_enabled : state->enabled)
1864 & (ISENABLED_TEXTURE_GEN_S | ISENABLED_TEXTURE_GEN_T |
1865 ISENABLED_TEXTURE_GEN_R | ISENABLED_TEXTURE_GEN_Q)))
1867 /* Enable texture coords if any were specified; or if generation
1868 is on in immediate mode; or if this list turned on generation. */
1870 jwzgles_glEnableClientState (GL_TEXTURE_COORD_ARRAY);
1876 jwzgles_glTexCoord4f (s->ctex.s, s->ctex.t, s->ctex.r, s->ctex.q);
1877 jwzgles_glDisableClientState (GL_TEXTURE_COORD_ARRAY);
1883 jwzgles_glEnableClientState (GL_COLOR_ARRAY);
1889 jwzgles_glColor4f (s->ccolor.r, s->ccolor.g, s->ccolor.b, s->ccolor.a);
1890 jwzgles_glDisableClientState (GL_COLOR_ARRAY);
1893 jwzgles_glEnableClientState (GL_VERTEX_ARRAY);
1895 /* We translated the glMaterial calls to per-vertex colors, which are
1896 of the glColor sort, not the glMaterial sort, so automatically
1897 turn on material mapping. Maybe this is a bad idea.
1899 if (s->materialistic && !jwzgles_glIsEnabled (GL_COLOR_MATERIAL))
1902 jwzgles_glEnable (GL_COLOR_MATERIAL);
1907 glBindBuffer (GL_ARRAY_BUFFER, 0); /* This comes later. */
1908 jwzgles_glDrawArrays (s->mode, 0, s->count);
1909 glBindBuffer (GL_ARRAY_BUFFER, 0); /* Keep out of others' hands */
1911 # define RESET(VAR,FN,ARG) do { \
1912 if (is_##VAR != was_##VAR) { \
1913 if (was_##VAR) jwzgles_glEnable##FN (ARG); \
1914 else jwzgles_glDisable##FN (ARG); \
1916 RESET (norm, ClientState, GL_NORMAL_ARRAY);
1917 RESET (tex, ClientState, GL_TEXTURE_COORD_ARRAY);
1918 RESET (color, ClientState, GL_COLOR_ARRAY);
1919 RESET (mat, , GL_COLOR_MATERIAL);
1926 s->materialistic = 0;
1930 /* The display list is full of calls to glDrawArrays(), plus saved arrays
1931 of the values we need to restore before calling it. "Restore" means
1932 "ship them off to the GPU before each call".
1934 So instead, this function walks through the display list and
1935 combines all of those vertex, normal, texture and color values into
1936 a single VBO array; ships those values off to the GPU *once* at the
1937 time of glEndList; and when running the list with glCallList, the
1938 values are already on the GPU and don't need to be sent over again.
1940 The VBO persists in the GPU until the display list is deleted.
1943 optimize_arrays (void)
1945 list *L = &state->lists.lists[state->compiling_list-1];
1948 int combo_count = 0;
1950 GLuint buf_name = 0;
1952 Assert (state->compiling_list, "not compiling a list");
1953 Assert (L, "no list");
1954 Assert (!L->buffer, "list already has a buffer");
1956 glGenBuffers (1, &buf_name);
1957 CHECK("glGenBuffers");
1958 if (! buf_name) return;
1960 L->buffer = buf_name;
1962 /* Go through the list and dump the contents of the various saved arrays
1963 into one large array.
1965 for (i = 0; i < L->count; i++)
1967 list_fn *F = &L->fns[i];
1971 /* count = F->argv[2].i;*/ /* 3rd arg to glDrawArrays */
1973 for (j = 0; j < 4; j++)
1975 draw_array *A = &F->arrays[j];
1976 int ocount = combo_count;
1978 /* If some caller is using arrays that don't have floats in them,
1979 we just leave them as-is and ship them over at each call.
1980 Doubt this ever really happens.
1982 if (A->type != GL_FLOAT)
1985 if (! A->data) /* No array. */
1988 Assert (A->bytes > 0, "no bytes in draw_array");
1989 Assert (((unsigned long) A->data > 0xFFFF),
1990 "buffer data not a pointer");
1992 combo_count += A->bytes / sizeof(*combo);
1993 make_room ("optimize_arrays",
1994 (void **) &combo, sizeof(*combo),
1995 &combo_count, &combo_size);
1996 memcpy (combo + ocount, A->data, A->bytes);
1997 A->binding = buf_name;
1999 /* 'data' is now the byte offset into the VBO. */
2000 A->data = (void *) (ocount * sizeof(*combo));
2001 /* LOG3(" loaded %lu floats to pos %d of buffer %d",
2002 A->bytes / sizeof(*combo), ocount, buf_name); */
2006 if (combo_count == 0) /* Nothing to do! */
2008 if (combo) free (combo);
2009 glDeleteBuffers (1, &buf_name);
2014 glBindBuffer (GL_ARRAY_BUFFER, buf_name);
2015 glBufferData (GL_ARRAY_BUFFER,
2016 combo_count * sizeof (*combo),
2019 glBindBuffer (GL_ARRAY_BUFFER, 0); /* Keep out of others' hands */
2021 LOG3(" loaded %d floats of list %d into VBO %d",
2022 combo_count, state->compiling_list, buf_name);
2026 for (i = 0; i < combo_count; i++)
2029 fprintf (stderr, "\njwzgles: %4d: ", i);
2030 fprintf (stderr, " %7.3f", combo[i]);
2032 fprintf (stderr, "\n");
2036 if (combo) free (combo);
2041 jwzgles_glCallList (int id)
2043 if (state->compiling_list)
2045 /* Yes, you can call lists inside of lists.
2046 Yes, recursion would be a mistake. */
2049 list_push ("glCallList", (list_fn_cb) &jwzgles_glCallList, PROTO_I, vv);
2056 state->replaying_list++;
2059 fprintf (stderr, "\n");
2060 LOG1 ("glCallList %d", id);
2063 Assert (id > 0 && id <= state->lists.count, "glCallList: bogus ID");
2064 L = &state->lists.lists[id-1];
2065 Assert (id == L->id, "glCallList corrupted");
2067 for (i = 0; i < L->count; i++)
2069 list_fn *F = &L->fns[i];
2070 list_fn_cb fn = F->fn;
2071 void_int *av = F->argv;
2075 LOG1 (" call %-12s", F->name);
2076 ((void (*) (void)) fn) ();
2080 if (fn == (list_fn_cb) &jwzgles_glBegin ||
2081 fn == (list_fn_cb) &jwzgles_glFrontFace ||
2082 fn == (list_fn_cb) &jwzgles_glEnable ||
2083 fn == (list_fn_cb) &jwzgles_glDisable ||
2084 fn == (list_fn_cb) &jwzgles_glEnableClientState ||
2085 fn == (list_fn_cb) &jwzgles_glDisableClientState ||
2086 fn == (list_fn_cb) &jwzgles_glShadeModel ||
2087 fn == (list_fn_cb) &jwzgles_glMatrixMode)
2088 LOG2 (" call %-12s %s", F->name, mode_desc (av[0].i));
2090 LOG2 (" call %-12s %d", F->name, av[0].i);
2091 ((void (*) (int)) fn) (av[0].i);
2095 LOG2 (" call %-12s %7.3f", F->name, av[0].f);
2096 ((void (*) (GLfloat)) fn) (av[0].f);
2100 if (fn == (list_fn_cb) &jwzgles_glBindTexture ||
2101 fn == (list_fn_cb) &jwzgles_glBindBuffer)
2102 LOG3 (" call %-12s %s %d", F->name,
2103 mode_desc (av[0].i), av[1].i);
2105 LOG3 (" call %-12s %d %d", F->name, av[0].i, av[1].i);
2106 ((void (*) (int, int)) fn) (av[0].i, av[1].i);
2110 LOG3 (" call %-12s %7.3f %7.3f", F->name, av[0].f, av[1].f);
2111 ((void (*) (GLfloat, GLfloat)) fn) (av[0].f, av[1].f);
2115 LOG3 (" call %-12s %s %7.3f", F->name,
2116 mode_desc (av[0].f), av[1].f);
2117 ((void (*) (GLint, GLfloat)) fn) (av[0].i, av[1].f);
2120 case PROTO_III: III:
2121 if (fn == (list_fn_cb) &jwzgles_glDrawArrays ||
2122 fn == (list_fn_cb) &jwzgles_glTexParameteri)
2123 LOG4 (" call %-12s %s %d %d", F->name,
2124 mode_desc (av[0].i), av[1].i, av[2].i);
2126 LOG4 (" call %-12s %d %d %d", F->name,
2127 av[0].i, av[1].i, av[2].i);
2128 ((void (*) (int, int, int)) fn) (av[0].i, av[1].i, av[2].i);
2132 LOG4 (" call %-12s %7.3f %7.3f %7.3f", F->name,
2133 av[0].f, av[1].f, av[2].f);
2134 ((void (*) (GLfloat, GLfloat, GLfloat)) fn)
2135 (av[0].f, av[1].f, av[2].f);
2139 LOG4 (" call %-12s %s %s %7.3f", F->name,
2140 mode_desc (av[0].i), mode_desc (av[1].i), av[2].f);
2141 ((void (*) (int, int, GLfloat)) fn) (av[0].i, av[1].i, av[2].f);
2145 LOG5 (" call %-12s %d %d %d %d", F->name,
2146 av[0].i, av[1].i, av[2].i, av[3].i);
2147 ((void (*) (int, int, int, int)) fn)
2148 (av[0].i, av[1].i, av[2].i, av[3].i);
2152 LOG5 (" call %-12s %7.3f %7.3f %7.3f %7.3f", F->name,
2153 av[0].f, av[1].f, av[2].f, av[3].f);
2154 ((void (*) (GLfloat, GLfloat, GLfloat, GLfloat)) fn)
2155 (av[0].f, av[1].f, av[2].f, av[3].f);
2165 LOG6 (" call %-12s %s %3.1f %3.1f %3.1f %3.1f", F->name,
2166 mode_desc (av[0].i),
2167 av[1].f, av[2].f, av[3].f, av[4].f);
2168 ((void (*) (int, const GLfloat *)) fn) (av[0].i, v);
2179 LOG7 (" call %-12s %s %-8s %3.1f %3.1f %3.1f %3.1f", F->name,
2180 mode_desc (av[0].i), mode_desc (av[1].i),
2181 av[2].f, av[3].f, av[4].f, av[5].f);
2182 ((void (*) (int, int, const GLfloat *)) fn)
2183 (av[0].i, av[1].i, v);
2194 LOG6 (" call %-12s %s %3d %3d %3d %3d", F->name,
2195 mode_desc (av[0].i),
2196 av[1].i, av[2].i, av[3].i, av[4].i);
2197 ((void (*) (int, const int *)) fn) (av[0].i, v);
2208 LOG7 (" call %-12s %s %-8s %3d %3d %3d %3d", F->name,
2209 mode_desc (av[0].i), mode_desc (av[1].i),
2210 av[2].i, av[3].i, av[4].i, av[5].i);
2211 ((void (*) (int, int, const int *)) fn)
2212 (av[0].i, av[1].i, v);
2217 restore_arrays (F, av[1].i + av[2].i);
2225 for (i = 0; i < countof(m); i++)
2227 LOG17 (" call %-12s ["
2228 "%8.3f %8.3f %8.3f %8.3f " "\n\t\t\t "
2229 "%8.3f %8.3f %8.3f %8.3f " "\n\t\t\t "
2230 "%8.3f %8.3f %8.3f %8.3f " "\n\t\t\t "
2231 "%8.3f %8.3f %8.3f %8.3f ]",
2233 m[0], m[1], m[2], m[3],
2234 m[4], m[5], m[6], m[7],
2235 m[8], m[9], m[10], m[11],
2236 m[12], m[13], m[14], m[15]);
2237 ((void (*) (GLfloat *)) fn) (m);
2242 Assert (0, "bogus prototype");
2247 LOG1 ("glCallList %d done\n", id);
2249 state->replaying_list--;
2250 Assert (state->replaying_list >= 0, "glCallList corrupted");
2255 /* When we save a call to glDrawArrays into a display list, we also need to
2256 save the prevailing copy of the arrays that it will use, and restore them
2260 save_arrays (list_fn *F, int count)
2263 draw_array *A = (draw_array *) calloc (4, sizeof (*A));
2264 Assert (A, "out of memory");
2266 /* if (state->set.count > 0) */
2268 glGetIntegerv (GL_VERTEX_ARRAY_BUFFER_BINDING, &A[i].binding);
2269 glGetIntegerv (GL_VERTEX_ARRAY_SIZE, &A[i].size);
2270 glGetIntegerv (GL_VERTEX_ARRAY_TYPE, &A[i].type);
2271 glGetIntegerv (GL_VERTEX_ARRAY_STRIDE, &A[i].stride);
2272 glGetPointerv (GL_VERTEX_ARRAY_POINTER, &A[i].data);
2273 CHECK("glGetPointerv");
2274 copy_array_data (&A[i], count, "vert");
2278 if (state->set.ncount > 1)
2281 glGetIntegerv (GL_NORMAL_ARRAY_BUFFER_BINDING, &A[i].binding);
2282 glGetIntegerv (GL_NORMAL_ARRAY_TYPE, &A[i].type);
2283 glGetIntegerv (GL_NORMAL_ARRAY_STRIDE, &A[i].stride);
2284 glGetPointerv (GL_NORMAL_ARRAY_POINTER, &A[i].data);
2285 CHECK("glGetPointerv");
2286 copy_array_data (&A[i], count, "norm");
2290 if (state->set.tcount > 1)
2292 glGetIntegerv (GL_TEXTURE_COORD_ARRAY_BUFFER_BINDING, &A[i].binding);
2293 glGetIntegerv (GL_TEXTURE_COORD_ARRAY_SIZE, &A[i].size);
2294 glGetIntegerv (GL_TEXTURE_COORD_ARRAY_TYPE, &A[i].type);
2295 glGetIntegerv (GL_TEXTURE_COORD_ARRAY_STRIDE, &A[i].stride);
2296 glGetPointerv (GL_TEXTURE_COORD_ARRAY_POINTER, &A[i].data);
2297 CHECK("glGetPointerv");
2298 copy_array_data (&A[i], count, "tex ");
2302 if (state->set.ccount > 1)
2304 glGetIntegerv (GL_COLOR_ARRAY_BUFFER_BINDING, &A[i].binding);
2305 glGetIntegerv (GL_COLOR_ARRAY_SIZE, &A[i].size);
2306 glGetIntegerv (GL_COLOR_ARRAY_TYPE, &A[i].type);
2307 glGetIntegerv (GL_COLOR_ARRAY_STRIDE, &A[i].stride);
2308 glGetPointerv (GL_COLOR_ARRAY_POINTER, &A[i].data);
2309 CHECK("glGetPointerv");
2310 copy_array_data (&A[i], count, "col ");
2313 /* Freed by glDeleteLists. */
2315 Assert (!F->arrays, "save_arrays corrupted");
2323 dump_array_data (draw_array *A, int count,
2324 const char *action, const char *name, const void *old)
2326 int bytes = count * A->stride;
2331 "jwzgles: %s %s %d %s %2d, %4d = %5d bind %d @ %d\n",
2333 A->size, mode_desc(A->type), A->stride,
2334 count, bytes, A->binding, (int) A->data);
2338 Assert (bytes == A->bytes, "array data corrupted");
2340 fprintf (stderr, "jwzgles: %s %s %d %s %2d, %4d = %5d @ %lX",
2342 A->size, mode_desc(A->type), A->stride,
2343 count, bytes, (unsigned long) A->data);
2345 fprintf (stderr, " / %lX", (unsigned long) old);
2346 fprintf (stderr, "\n");
2351 Assert (((unsigned long) A->data < 0xFFFF),
2352 "buffer binding should be a numeric index,"
2353 " but looks like a pointer");
2356 /* glGetBufferSubData doesn't actually exist in OpenGLES, but this
2357 was helpful for debugging on real OpenGL... */
2360 fprintf (stderr, "jwzgles: read back:\n");
2361 d = (GLfloat *) malloc (A->bytes);
2362 glGetBufferSubData (GL_ARRAY_BUFFER, (int) A->data,
2363 count * A->stride, (void *) d);
2364 CHECK("glGetBufferSubData");
2365 for (i = 0; i < count * A->size; i++)
2368 fprintf (stderr, "\njwzgles: %4d: ",
2369 i + (int) A->data / sizeof(GLfloat));
2370 fprintf (stderr, " %7.3f", d[i]);
2372 fprintf (stderr, "\n");
2379 unsigned char *b = (unsigned char *) A->data;
2381 if ((unsigned long) A->data < 0xFFFF)
2383 Assert (0, "buffer data not a pointer");
2386 for (i = 0; i < count; i++)
2389 GLfloat *f = (GLfloat *) b;
2391 if (s == 0) s = 3; /* normals */
2392 fprintf (stderr, "jwzgles: ");
2393 for (j = 0; j < s; j++)
2394 fprintf (stderr, " %7.3f", f[j]);
2395 fprintf (stderr, "\n");
2403 dump_direct_array_data (int count)
2405 draw_array A = { 0, };
2407 if (jwzgles_glIsEnabled (GL_VERTEX_ARRAY))
2409 glGetIntegerv (GL_VERTEX_ARRAY_BUFFER_BINDING, &A.binding);
2410 glGetIntegerv (GL_VERTEX_ARRAY_SIZE, &A.size);
2411 glGetIntegerv (GL_VERTEX_ARRAY_TYPE, &A.type);
2412 glGetIntegerv (GL_VERTEX_ARRAY_STRIDE, &A.stride);
2413 glGetPointerv (GL_VERTEX_ARRAY_POINTER, &A.data);
2414 A.bytes = count * A.stride;
2415 dump_array_data (&A, count, "direct", "vertex ", 0);
2417 if (jwzgles_glIsEnabled (GL_NORMAL_ARRAY))
2420 glGetIntegerv (GL_NORMAL_ARRAY_BUFFER_BINDING, &A.binding);
2421 glGetIntegerv (GL_NORMAL_ARRAY_TYPE, &A.type);
2422 glGetIntegerv (GL_NORMAL_ARRAY_STRIDE, &A.stride);
2423 glGetPointerv (GL_NORMAL_ARRAY_POINTER, &A.data);
2424 A.bytes = count * A.stride;
2425 dump_array_data (&A, count, "direct", "normal ", 0);
2427 if (jwzgles_glIsEnabled (GL_TEXTURE_COORD_ARRAY))
2429 glGetIntegerv (GL_TEXTURE_COORD_ARRAY_BUFFER_BINDING, &A.binding);
2430 glGetIntegerv (GL_TEXTURE_COORD_ARRAY_SIZE, &A.size);
2431 glGetIntegerv (GL_TEXTURE_COORD_ARRAY_TYPE, &A.type);
2432 glGetIntegerv (GL_TEXTURE_COORD_ARRAY_STRIDE, &A.stride);
2433 glGetPointerv (GL_TEXTURE_COORD_ARRAY_POINTER, &A.data);
2434 A.bytes = count * A.stride;
2435 dump_array_data (&A, count, "direct", "texture", 0);
2437 if (jwzgles_glIsEnabled (GL_COLOR_ARRAY))
2439 glGetIntegerv (GL_COLOR_ARRAY_BUFFER_BINDING, &A.binding);
2440 glGetIntegerv (GL_COLOR_ARRAY_SIZE, &A.size);
2441 glGetIntegerv (GL_COLOR_ARRAY_TYPE, &A.type);
2442 glGetIntegerv (GL_COLOR_ARRAY_STRIDE, &A.stride);
2443 glGetPointerv (GL_COLOR_ARRAY_POINTER, &A.data);
2444 A.bytes = count * A.stride;
2445 dump_array_data (&A, count, "direct", "color ", 0);
2453 copy_array_data (draw_array *A, int count, const char *name)
2455 /* Instead of just memcopy'ing the whole array and obeying its previous
2456 'stride' value, we make up a more compact array. This is because if
2457 the same array data is being used with multiple component types,
2458 e.g. with glInterleavedArrays, we don't want to copy all of the
2459 data multiple times.
2461 int stride2, bytes, i, j;
2465 const unsigned char *IB;
2468 if (((unsigned long) A->data) < 0xFFFF)
2470 Assert (0, "buffer data not a pointer");
2474 Assert (A->size >= 2 && A->size <= 4, "bogus array size");
2477 case GL_FLOAT: stride2 = A->size * sizeof(GLfloat); break;
2478 case GL_UNSIGNED_BYTE: stride2 = A->size; break;
2479 default: Assert (0, "bogus array type"); break;
2482 bytes = count * stride2;
2483 Assert (bytes > 0, "bogus array count or stride");
2484 Assert (A->data, "missing array data");
2485 data2 = (void *) malloc (bytes);
2486 Assert (data2, "out of memory");
2488 IB = (const unsigned char *) A->data;
2489 OB = (unsigned char *) data2;
2490 IF = (const GLfloat *) A->data;
2491 OF = (GLfloat *) data2;
2495 for (i = 0; i < count; i++)
2497 for (j = 0; j < A->size; j++)
2499 IF = (const GLfloat *) (((const unsigned char *) IF) + A->stride);
2502 case GL_UNSIGNED_BYTE:
2503 for (i = 0; i < count; i++)
2505 for (j = 0; j < A->size; j++)
2511 Assert (0, "bogus array type");
2517 A->stride = stride2;
2520 dump_array_data (A, count, "saved", name, 0);
2526 restore_arrays (list_fn *F, int count)
2529 draw_array *A = F->arrays;
2530 Assert (A, "missing array");
2532 for (i = 0; i < 4; i++)
2534 const char *name = 0;
2539 Assert ((A[i].binding || A[i].data),
2540 "array has neither buffer binding nor data");
2542 glBindBuffer (GL_ARRAY_BUFFER, A[i].binding);
2543 CHECK("glBindBuffer");
2546 case 0: glVertexPointer (A[i].size, A[i].type, A[i].stride, A[i].data);
2548 CHECK("glVertexPointer");
2550 case 1: glNormalPointer ( A[i].type, A[i].stride, A[i].data);
2552 CHECK("glNormalPointer");
2554 case 2: glTexCoordPointer(A[i].size, A[i].type, A[i].stride, A[i].data);
2556 CHECK("glTexCoordPointer");
2558 case 3: glColorPointer (A[i].size, A[i].type, A[i].stride, A[i].data);
2560 CHECK("glColorPointer");
2562 default: Assert (0, "wat"); break;
2566 dump_array_data (&A[i], count, "restored", name, 0);
2570 glBindBuffer (GL_ARRAY_BUFFER, 0); /* Keep out of others' hands */
2575 jwzgles_glDrawArrays (GLuint mode, GLuint first, GLuint count)
2577 /* If we are auto-generating texture coordinates, do that now, after
2578 the vertex array was installed, but before drawing, This happens
2579 when recording into a list, or in direct mode. It must happen
2580 before calling optimize_arrays() from glEndList().
2582 if (! state->replaying_list &&
2583 ((state->compiling_list ? state->list_enabled : state->enabled)
2584 & (ISENABLED_TEXTURE_GEN_S | ISENABLED_TEXTURE_GEN_T |
2585 ISENABLED_TEXTURE_GEN_R | ISENABLED_TEXTURE_GEN_Q)))
2586 generate_texture_coords (first, count);
2588 if (state->compiling_list)
2594 list_push ("glDrawArrays", (list_fn_cb) &jwzgles_glDrawArrays,
2600 if (! state->replaying_list) {
2601 LOG4("direct %-12s %d %d %d", "glDrawArrays", mode, first, count);
2602 dump_direct_array_data (first + count);
2605 glDrawArrays (mode, first, count); /* the real one */
2606 CHECK("glDrawArrays");
2612 jwzgles_glInterleavedArrays (GLenum format, GLsizei stride, const void *data)
2614 /* We can implement this by calling the various *Pointer functions
2615 with offsets into the same data, taking advantage of stride.
2617 const unsigned char *c = (const unsigned char *) data;
2619 # define F sizeof(GLfloat)
2621 Assert (!state->compiling_verts,
2622 "glInterleavedArrays not allowed inside glBegin");
2624 jwzgles_glEnableClientState (GL_VERTEX_ARRAY);
2626 if (!state->replaying_list)
2627 LOG4 ("%sglInterleavedArrays %s %d %lX",
2628 (state->compiling_list || state->replaying_list ? " " : ""),
2629 mode_desc (format), stride, (unsigned long) data);
2633 glVertexPointer (2, GL_FLOAT, stride, c);
2634 CHECK("glVertexPointer");
2635 if (!state->replaying_list)
2636 LOG3 ("%s -> glVertexPointer 2 FLOAT %d %lX",
2637 (state->compiling_list || state->replaying_list ? " " : ""),
2638 stride, (unsigned long) c);
2641 glVertexPointer (3, GL_FLOAT, stride, c);
2642 CHECK("glVertexPointer");
2643 if (!state->replaying_list)
2644 LOG3 ("%s -> glVertexPointer 3 FLOAT %d %lX",
2645 (state->compiling_list || state->replaying_list ? " " : ""),
2646 stride, (unsigned long) c);
2651 jwzgles_glEnableClientState (GL_COLOR_ARRAY);
2652 glColorPointer (4, GL_UNSIGNED_BYTE, stride, c);
2653 CHECK("glColorPointer");
2654 c += 4*B; /* #### might be incorrect float-aligned address */
2655 glVertexPointer (2, GL_FLOAT, stride, c);
2660 jwzgles_glEnableClientState (GL_COLOR_ARRAY);
2661 glColorPointer (4, GL_UNSIGNED_BYTE, stride, c);
2662 CHECK("glColorPointer");
2664 glVertexPointer (3, GL_FLOAT, stride, c);
2665 CHECK("glVertexPointer");
2670 jwzgles_glEnableClientState (GL_COLOR_ARRAY);
2671 glColorPointer (3, GL_FLOAT, stride, c);
2672 CHECK("glColorPointer");
2674 glVertexPointer (3, GL_FLOAT, stride, c);
2675 CHECK("glVertexPointer");
2680 jwzgles_glEnableClientState (GL_NORMAL_ARRAY);
2681 glNormalPointer (GL_FLOAT, stride, c);
2682 CHECK("glNormalPointer");
2683 if (!state->replaying_list)
2684 LOG3 ("%s -> glNormalPointer FLOAT %d %lX",
2685 (state->compiling_list || state->replaying_list ? " " : ""),
2686 stride, (unsigned long) c);
2688 glVertexPointer (3, GL_FLOAT, stride, c);
2689 CHECK("glVertexPointer");
2690 if (!state->replaying_list)
2691 LOG3 ("%s -> glVertexPointer 3 FLOAT %d %lX",
2692 (state->compiling_list || state->replaying_list ? " " : ""),
2693 stride, (unsigned long) c);
2695 case GL_C4F_N3F_V3F:
2697 stride = 4*F + 3*F + 3*F;
2698 jwzgles_glEnableClientState (GL_COLOR_ARRAY);
2699 glColorPointer (4, GL_FLOAT, stride, c);
2700 CHECK("glColorPointer");
2702 jwzgles_glEnableClientState (GL_NORMAL_ARRAY);
2703 glNormalPointer (GL_FLOAT, stride, c);
2704 CHECK("glNormalPointer");
2706 glVertexPointer (3, GL_FLOAT, stride, c);
2707 CHECK("glVertexPointer");
2712 jwzgles_glEnableClientState (GL_TEXTURE_COORD_ARRAY);
2713 glTexCoordPointer (2, GL_FLOAT, stride, c);
2714 CHECK("glTexCoordPointer");
2716 glVertexPointer (3, GL_FLOAT, stride, c);
2717 CHECK("glVertexPointer");
2722 jwzgles_glEnableClientState (GL_TEXTURE_COORD_ARRAY);
2723 glTexCoordPointer (4, GL_FLOAT, stride, c);
2724 CHECK("glTexCoordPointer");
2726 glVertexPointer (4, GL_FLOAT, stride, c);
2727 CHECK("glVertexPointer");
2729 case GL_T2F_C4UB_V3F:
2731 stride = 2*F + 4*B + 3*F;
2732 jwzgles_glEnableClientState (GL_TEXTURE_COORD_ARRAY);
2733 glTexCoordPointer (2, GL_FLOAT, stride, c);
2734 CHECK("glTexCoordPointer");
2736 jwzgles_glEnableClientState (GL_COLOR_ARRAY);
2737 glColorPointer (4, GL_UNSIGNED_BYTE, stride, c);
2738 CHECK("glColorPointer");
2740 glVertexPointer (3, GL_FLOAT, stride, c);
2741 CHECK("glVertexPointer");
2743 case GL_T2F_C3F_V3F:
2745 stride = 2*F + 3*F + 3*F;
2746 jwzgles_glEnableClientState (GL_TEXTURE_COORD_ARRAY);
2747 glTexCoordPointer (2, GL_FLOAT, stride, c);
2748 CHECK("glTexCoordPointer");
2750 jwzgles_glEnableClientState (GL_COLOR_ARRAY);
2751 glColorPointer (3, GL_FLOAT, stride, c);
2752 CHECK("glColorPointer");
2754 glVertexPointer (3, GL_FLOAT, stride, c);
2755 CHECK("glVertexPointer");
2757 case GL_T2F_N3F_V3F:
2759 stride = 2*F + 3*F + 3*F;
2760 jwzgles_glEnableClientState (GL_TEXTURE_COORD_ARRAY);
2761 glTexCoordPointer (2, GL_FLOAT, stride, c);
2762 CHECK("glTexCoordPointer");
2764 jwzgles_glEnableClientState (GL_NORMAL_ARRAY);
2765 glNormalPointer (GL_FLOAT, stride, c);
2766 CHECK("glNormalPointer");
2768 glVertexPointer (3, GL_FLOAT, stride, c);
2769 CHECK("glVertexPointer");
2771 case GL_T2F_C4F_N3F_V3F:
2773 stride = 2*F + 4*F + 3*F + 3*F;
2774 jwzgles_glEnableClientState (GL_TEXTURE_COORD_ARRAY);
2775 glTexCoordPointer (2, GL_FLOAT, stride, c);
2776 CHECK("glTexCoordPointer");
2778 jwzgles_glEnableClientState (GL_COLOR_ARRAY);
2779 glColorPointer (3, GL_FLOAT, stride, c);
2780 CHECK("glColorPointer");
2782 jwzgles_glEnableClientState (GL_NORMAL_ARRAY);
2783 glNormalPointer (GL_FLOAT, stride, c);
2784 CHECK("glNormalPointer");
2786 glVertexPointer (3, GL_FLOAT, stride, c);
2787 CHECK("glVertexPointer");
2789 case GL_T4F_C4F_N3F_V4F:
2791 stride = 4*F + 4*F + 3*F + 4*F;
2792 jwzgles_glEnableClientState (GL_TEXTURE_COORD_ARRAY);
2793 glTexCoordPointer (4, GL_FLOAT, stride, c);
2794 CHECK("glTexCoordPointer");
2796 jwzgles_glEnableClientState (GL_COLOR_ARRAY);
2797 glColorPointer (4, GL_FLOAT, stride, c);
2798 CHECK("glColorPointer");
2800 jwzgles_glEnableClientState (GL_NORMAL_ARRAY);
2801 glNormalPointer (GL_FLOAT, stride, c);
2802 CHECK("glNormalPointer");
2804 glVertexPointer (3, GL_FLOAT, stride, c);
2805 CHECK("glVertexPointer");
2808 Assert (0, "glInterleavedArrays: bogus format");
2819 jwzgles_glMultMatrixf (const GLfloat *m)
2821 Assert (!state->compiling_verts,
2822 "glMultMatrixf not allowed inside glBegin");
2823 if (state->compiling_list)
2827 for (i = 0; i < countof(vv); i++)
2829 list_push ("glMultMatrixf", (list_fn_cb) &jwzgles_glMultMatrixf,
2834 if (! state->replaying_list)
2835 LOG1 ("direct %-12s", "glMultMatrixf");
2836 glMultMatrixf (m); /* the real one */
2837 CHECK("glMultMatrixf");
2843 jwzgles_glClearIndex(GLfloat c)
2845 /* Does GLES even do indexed color? */
2846 Assert (0, "glClearIndex unimplemented");
2851 jwzgles_glBitmap (GLsizei width, GLsizei height, GLfloat xorig, GLfloat yorig,
2852 GLfloat xmove, GLfloat ymove, const GLubyte *bitmap)
2854 Assert (0, "glBitmap unimplemented");
2858 jwzgles_glPushAttrib(int flags)
2860 Assert (0, "glPushAttrib unimplemented");
2864 jwzgles_glPopAttrib(void)
2866 Assert (0, "glPopAttrib unimplemented");
2870 /* These are needed for object hit detection in pinion.
2871 Might need to rewrite that code entirely. Punt for now.
2874 jwzgles_glInitNames (void)
2876 /* Assert (0, "glInitNames unimplemented");*/
2880 jwzgles_glPushName (GLuint name)
2882 /* Assert (0, "glPushName unimplemented");*/
2886 jwzgles_glPopName (void)
2888 /* Assert (0, "glPopName unimplemented");*/
2893 jwzgles_glRenderMode (GLuint mode)
2895 /* Assert (0, "glRenderMode unimplemented");*/
2900 jwzgles_glSelectBuffer (GLsizei size, GLuint *buf)
2902 /* Assert (0, "glSelectBuffer unimplemented");*/
2907 jwzgles_glGenTextures (GLuint n, GLuint *ret)
2909 Assert (!state->compiling_verts,
2910 "glGenTextures not allowed inside glBegin");
2911 /* technically legal, but stupid! */
2912 Assert (!state->compiling_list,
2913 "glGenTextures not allowed inside glNewList");
2914 if (! state->replaying_list)
2915 LOG1 ("direct %-12s", "glGenTextures");
2916 glGenTextures (n, ret); /* the real one */
2917 CHECK("glGenTextures");
2921 /* return the next larger power of 2. */
2926 while (i < value) i <<= 1;
2931 jwzgles_glTexImage1D (GLenum target, GLint level,
2932 GLint internalFormat,
2933 GLsizei width, GLint border,
2934 GLenum format, GLenum type,
2937 Assert (!state->compiling_verts, "glTexImage1D not allowed inside glBegin");
2938 /* technically legal, but stupid! */
2939 Assert (!state->compiling_list, "glTexImage1D inside glNewList");
2940 Assert (width == to_pow2(width), "width must be a power of 2");
2942 if (target == GL_TEXTURE_1D) target = GL_TEXTURE_2D;
2943 jwzgles_glTexImage2D (target, level, internalFormat, width, 1,
2944 border, format, type, data);
2948 jwzgles_glTexImage2D (GLenum target,
2950 GLint internalFormat,
2958 GLvoid *d2 = (GLvoid *) data;
2959 Assert (!state->compiling_verts, "glTexImage2D not allowed inside glBegin");
2960 Assert (!state->compiling_list, /* technically legal, but stupid! */
2961 "glTexImage2D not allowed inside glNewList");
2963 Assert (width == to_pow2(width), "width must be a power of 2");
2964 Assert (height == to_pow2(height), "height must be a power of 2");
2966 /* OpenGLES no longer supports "4" as a synonym for "RGBA". */
2967 switch (internalFormat) {
2968 case 1: internalFormat = GL_LUMINANCE; break;
2969 case 2: internalFormat = GL_LUMINANCE_ALPHA; break;
2970 case 3: internalFormat = GL_RGB; break;
2971 case 4: internalFormat = GL_RGBA; break;
2974 /* GLES does not let us omit the data pointer to create a blank texture. */
2977 d2 = (GLvoid *) calloc (1, width * height * sizeof(GLfloat) * 4);
2978 Assert (d2, "out of memory");
2981 if (internalFormat == GL_RGB && format == GL_RGBA)
2982 internalFormat = GL_RGBA; /* WTF */
2983 if (type == GL_UNSIGNED_INT_8_8_8_8_REV)
2984 type = GL_UNSIGNED_BYTE;
2986 if (! state->replaying_list)
2987 LOG10 ("direct %-12s %s %d %s %d %d %d %s %s 0x%lX", "glTexImage2D",
2988 mode_desc(target), level, mode_desc(internalFormat),
2989 width, height, border, mode_desc(format), mode_desc(type),
2990 (unsigned long) d2);
2991 glTexImage2D (target, level, internalFormat, width, height, border,
2992 format, type, d2); /* the real one */
2993 CHECK("glTexImage2D");
2995 if (d2 != data) free (d2);
2999 jwzgles_glTexSubImage2D (GLenum target, GLint level,
3000 GLint xoffset, GLint yoffset,
3001 GLsizei width, GLsizei height,
3002 GLenum format, GLenum type,
3003 const GLvoid *pixels)
3005 Assert (!state->compiling_verts,
3006 "glTexSubImage2D not allowed inside glBegin");
3007 Assert (!state->compiling_list, /* technically legal, but stupid! */
3008 "glTexSubImage2D not allowed inside glNewList");
3010 if (! state->replaying_list)
3011 LOG10 ("direct %-12s %s %d %d %d %d %d %s %s 0x%lX", "glTexSubImage2D",
3012 mode_desc(target), level, xoffset, yoffset, width, height,
3013 mode_desc (format), mode_desc (type), (unsigned long) pixels);
3014 glTexSubImage2D (target, level, xoffset, yoffset, width, height,
3015 format, type, pixels); /* the real one */
3016 CHECK("glTexSubImage2D");
3020 jwzgles_glCopyTexImage2D (GLenum target, GLint level, GLenum internalformat,
3021 GLint x, GLint y, GLsizei width, GLsizei height,
3024 Assert (!state->compiling_verts,
3025 "glCopyTexImage2D not allowed inside glBegin");
3026 Assert (!state->compiling_list, /* technically legal, but stupid! */
3027 "glCopyTexImage2D not allowed inside glNewList");
3028 if (! state->replaying_list)
3029 LOG9 ("direct %-12s %s %d %s %d %d %d %d %d", "glCopyTexImage2D",
3030 mode_desc(target), level, mode_desc(internalformat),
3031 x, y, width, height, border);
3032 glCopyTexImage2D (target, level, internalformat, x, y, width, height,
3033 border); /* the real one */
3034 CHECK("glCopyTexImage2D");
3038 /* OpenGLES doesn't have auto texture-generation at all!
3039 "Oh, just rewrite that code to use GPU shaders", they say.
3040 How fucking convenient.
3043 jwzgles_glTexGenfv (GLenum coord, GLenum pname, const GLfloat *params)
3047 if (pname == GL_TEXTURE_GEN_MODE)
3048 LOG5 ("%sdirect %-12s %s %s %s",
3049 (state->compiling_list || state->replaying_list ? " " : ""),
3051 mode_desc(coord), mode_desc(pname), mode_desc(params[0]));
3053 LOG8 ("%sdirect %-12s %s %s %3.1f %3.1f %3.1f %3.1f",
3054 (state->compiling_list || state->replaying_list ? " " : ""),
3056 mode_desc(coord), mode_desc(pname),
3057 params[0], params[1], params[2], params[3]);
3060 case GL_S: s = &state->s; break;
3061 case GL_T: s = &state->t; break;
3062 case GL_R: s = &state->r; break;
3063 case GL_Q: s = &state->q; break;
3064 default: Assert (0, "glGetTexGenfv: unknown coord"); break;
3068 case GL_TEXTURE_GEN_MODE: s->mode = params[0]; break;
3069 case GL_OBJECT_PLANE: memcpy (s->obj, params, sizeof(s->obj)); break;
3070 case GL_EYE_PLANE: memcpy (s->eye, params, sizeof(s->eye)); break;
3071 default: Assert (0, "glTexGenfv: unknown pname"); break;
3076 jwzgles_glTexGeni (GLenum coord, GLenum pname, GLint param)
3079 jwzgles_glTexGenfv (coord, pname, &v);
3083 jwzgles_glGetTexGenfv (GLenum coord, GLenum pname, GLfloat *params)
3088 case GL_S: s = &state->s; break;
3089 case GL_T: s = &state->t; break;
3090 case GL_R: s = &state->r; break;
3091 case GL_Q: s = &state->q; break;
3092 default: Assert (0, "glGetTexGenfv: unknown coord"); break;
3096 case GL_TEXTURE_GEN_MODE: params[0] = s->mode; break;
3097 case GL_OBJECT_PLANE: memcpy (params, s->obj, sizeof(s->obj)); break;
3098 case GL_EYE_PLANE: memcpy (params, s->eye, sizeof(s->eye)); break;
3099 default: Assert (0, "glGetTexGenfv: unknown pname"); break;
3102 if (pname == GL_TEXTURE_GEN_MODE)
3103 LOG5 ("%sdirect %-12s %s %s -> %s",
3104 (state->compiling_list || state->replaying_list ? " " : ""),
3106 mode_desc(coord), mode_desc(pname), mode_desc(params[0]));
3108 LOG8 ("%sdirect %-12s %s %s -> %3.1f %3.1f %3.1f %3.1f",
3109 (state->compiling_list || state->replaying_list ? " " : ""),
3111 mode_desc(coord), mode_desc(pname),
3112 params[0], params[1], params[2], params[3]);
3117 dot_product (int rank, GLfloat *a, GLfloat *b)
3119 /* A dot B => (A[1] * B[1]) + ... + (A[n] * B[n]) */
3122 for (i = 0; i < rank; i++)
3129 /* Compute the texture coordinates of the prevailing list of verts as per
3130 http://www.opengl.org/wiki/Mathematics_of_glTexGen
3133 generate_texture_coords (GLuint first, GLuint count)
3135 GLfloat *tex_out, *tex_array;
3138 draw_array A = { 0, };
3141 struct { GLuint which, flag, mode; GLfloat plane[4]; } tg[4] = {
3142 { GL_S, ISENABLED_TEXTURE_GEN_S, 0, { 0, } },
3143 { GL_T, ISENABLED_TEXTURE_GEN_T, 0, { 0, } },
3144 { GL_R, ISENABLED_TEXTURE_GEN_R, 0, { 0, } },
3145 { GL_Q, ISENABLED_TEXTURE_GEN_Q, 0, { 0, }}};
3149 /* Read the texture plane configs that were stored with glTexGen.
3151 for (i = 0; i < countof(tg); i++)
3154 if (! ((state->compiling_list ? state->list_enabled : state->enabled)
3157 jwzgles_glGetTexGenfv (tg[i].which, GL_TEXTURE_GEN_MODE, &mode);
3158 jwzgles_glGetTexGenfv (tg[i].which, GL_OBJECT_PLANE, tg[i].plane);
3163 if (tcoords == 0) return; /* Nothing to do! */
3166 /* Make the array to store our texture coords in. */
3168 tex_stride = tcoords * sizeof(GLfloat);
3169 tex_array = (GLfloat *) calloc (first + count, tex_stride);
3170 tex_out = tex_array;
3173 /* Read the prevailing vertex array, that was stored with
3174 glVertexPointer or glInterleavedArrays.
3176 glGetIntegerv (GL_VERTEX_ARRAY_BUFFER_BINDING, &A.binding);
3177 glGetIntegerv (GL_VERTEX_ARRAY_SIZE, &A.size);
3178 glGetIntegerv (GL_VERTEX_ARRAY_TYPE, &A.type);
3179 glGetIntegerv (GL_VERTEX_ARRAY_STRIDE, &A.stride);
3180 glGetPointerv (GL_VERTEX_ARRAY_POINTER, &A.data);
3181 A.bytes = count * A.stride;
3183 verts_in = (char *) A.data;
3185 /* Iterate over each vertex we're drawing.
3186 We just skip the ones < start, but the tex array has
3187 left room for zeroes there anyway.
3189 for (i = first; i < first + count; i++)
3191 GLfloat vert[4] = { 0, };
3194 /* Extract this vertex into `vert' as a float, whatever its type was. */
3195 for (j = 0; j < A.size; j++)
3198 case GL_SHORT: vert[j] = ((GLshort *) verts_in)[j]; break;
3199 case GL_INT: vert[j] = ((GLint *) verts_in)[j]; break;
3200 case GL_FLOAT: vert[j] = ((GLfloat *) verts_in)[j]; break;
3201 case GL_DOUBLE: vert[j] = ((GLdouble *) verts_in)[j]; break;
3202 default: Assert (0, "unknown vertex type"); break;
3206 /* Compute the texture coordinate for this vertex.
3207 For GL_OBJECT_LINEAR, these coordinates are static, and can go
3208 into the display list. But for GL_EYE_LINEAR, GL_SPHERE_MAP and
3209 GL_REFLECTION_MAP, they depend on the prevailing ModelView matrix,
3210 and so need to be computed afresh each time glDrawArrays is called.
3211 Unfortunately, our verts and norms are gone by then, dumped down
3212 into the VBO and discarded from CPU RAM. Bleh.
3214 for (j = 0, k = 0; j < countof(tg); j++)
3216 if (! ((state->compiling_list ? state->list_enabled : state->enabled)
3219 switch (tg[j].mode) {
3220 case GL_OBJECT_LINEAR:
3221 tex_out[k] = dot_product (4, vert, tg[j].plane);
3224 Assert (0, "unimplemented texture mode");
3230 /* fprintf (stderr, "%4d: V %-5.1f %-5.1f %-5.1f T %-5.1f %-5.1f\n",
3231 i, vert[0], vert[1], vert[2], tex_out[0], tex_out[1]); */
3233 /* Move verts_in and tex_out forward to the next vertex by stride. */
3234 verts_in += A.stride;
3235 tex_out = (GLfloat *) (((char *) tex_out) + tex_stride);
3238 jwzgles_glEnableClientState (GL_TEXTURE_COORD_ARRAY);
3239 jwzgles_glTexCoordPointer (tcoords, GL_FLOAT, tex_stride,
3240 (GLvoid *) tex_array);
3246 jwzgles_gluBuild2DMipmaps (GLenum target,
3247 GLint internalFormat,
3254 /* Not really bothering with mipmapping; only making one level.
3255 Note that this required a corresponding hack in glTexParameterf().
3258 int w2 = to_pow2(width);
3259 int h2 = to_pow2(height);
3261 void *d2 = (void *) data;
3263 /* OpenGLES no longer supports "4" as a synonym for "RGBA". */
3264 switch (internalFormat) {
3265 case 1: internalFormat = GL_LUMINANCE; break;
3266 case 2: internalFormat = GL_LUMINANCE_ALPHA; break;
3267 case 3: internalFormat = GL_RGB; break;
3268 case 4: internalFormat = GL_RGBA; break;
3271 /* if (w2 < h2) w2 = h2;
3272 if (h2 < w2) h2 = w2;*/
3274 if (w2 != width || h2 != height)
3276 /* Scale up the image bits to fit the power-of-2 texture.
3277 We have to do this because the mipmap API assumes that
3278 the texture bits go to texture coordinates 1.0 x 1.0.
3279 This could be more efficient, but it doesn't happen often.
3281 int istride = (format == GL_RGBA ? 4 : 3);
3283 int ibpl = istride * width;
3284 int obpl = ostride * w2;
3286 const unsigned char *in = (unsigned char *) data;
3287 unsigned char *out = (void *) malloc (h2 * obpl);
3288 Assert (out, "out of memory");
3291 for (oy = 0; oy < h2; oy++)
3293 int iy = oy * height / h2;
3294 const unsigned char *iline = in + (iy * ibpl);
3295 unsigned char *oline = out + (oy * obpl);
3297 for (ox = 0; ox < w2; ox++)
3299 int ix = ox * width / w2;
3300 const unsigned char *i = iline + (ix * istride);
3301 unsigned char *o = oline + (ox * ostride);
3302 *o++ = *i++; /* R */
3303 *o++ = *i++; /* G */
3304 *o++ = *i++; /* B */
3305 *o++ = (istride == 4 ? *i : 0xFF); /* A */
3310 internalFormat = GL_RGBA;
3314 jwzgles_glTexImage2D (target, 0, internalFormat, w2, h2, 0,
3316 if (d2 != data) free (d2);
3323 jwzgles_glRectf (GLfloat x1, GLfloat y1, GLfloat x2, GLfloat y2)
3325 jwzgles_glBegin (GL_POLYGON);
3326 jwzgles_glVertex2f (x1, y1);
3327 jwzgles_glVertex2f (x2, y1);
3328 jwzgles_glVertex2f (x2, y2);
3329 jwzgles_glVertex2f (x1, y2);
3334 jwzgles_glRecti (GLint x1, GLint y1, GLint x2, GLint y2)
3336 jwzgles_glRectf (x1, y1, x2, y2);
3340 jwzgles_glClearDepth (GLfloat d)
3342 /* Not sure what to do here */
3343 Assert (d == 1.0, "glClearDepth unimplemented");
3347 /* When in immediate mode, we store a bit into state->enabled, and also
3348 call the real glEnable() / glDisable().
3350 When recording a list, we store a bit into state->list_enabled instead,
3351 so that we can see what the prevailing enablement state will be when
3354 set: 1 = set, -1 = clear, 0 = query.
3357 enable_disable (GLuint bit, int set)
3359 int result = (set > 0);
3362 unsigned long flag = 0;
3365 case GL_TEXTURE_1D: /* We implement 1D textures as 2D textures. */
3366 case GL_TEXTURE_2D: flag = ISENABLED_TEXTURE_2D; break;
3367 case GL_TEXTURE_GEN_S: flag = ISENABLED_TEXTURE_GEN_S; omitp = 1; break;
3368 case GL_TEXTURE_GEN_T: flag = ISENABLED_TEXTURE_GEN_T; omitp = 1; break;
3369 case GL_TEXTURE_GEN_R: flag = ISENABLED_TEXTURE_GEN_R; omitp = 1; break;
3370 case GL_TEXTURE_GEN_Q: flag = ISENABLED_TEXTURE_GEN_Q; omitp = 1; break;
3371 case GL_LIGHTING: flag = ISENABLED_LIGHTING; break;
3372 case GL_BLEND: flag = ISENABLED_BLEND; break;
3373 case GL_DEPTH_TEST: flag = ISENABLED_DEPTH_TEST; break;
3374 case GL_ALPHA_TEST: flag = ISENABLED_ALPHA_TEST; break;
3375 case GL_CULL_FACE: flag = ISENABLED_CULL_FACE; break;
3376 case GL_NORMALIZE: flag = ISENABLED_NORMALIZE; break;
3377 case GL_FOG: flag = ISENABLED_FOG; break;
3378 case GL_COLOR_MATERIAL: flag = ISENABLED_COLMAT; break;
3380 /* Maybe technically these only work with glEnableClientState,
3381 but we treat that as synonymous with glEnable. */
3382 case GL_VERTEX_ARRAY: flag = ISENABLED_VERT_ARRAY; csp = 1; break;
3383 case GL_NORMAL_ARRAY: flag = ISENABLED_NORM_ARRAY; csp = 1; break;
3384 case GL_COLOR_ARRAY: flag = ISENABLED_COLOR_ARRAY; csp = 1; break;
3385 case GL_TEXTURE_COORD_ARRAY: flag = ISENABLED_TEX_ARRAY; csp = 1; break;
3388 Assert (set != 0, "glIsEnabled unimplemented bit");
3392 if (set) /* setting or unsetting, not querying */
3394 const char *fns[4] = { "glEnable", "glDisable",
3395 "glEnableClientState", "glDisableClientState" };
3396 list_fn_cb fs[4] = { (list_fn_cb) &jwzgles_glEnable,
3397 (list_fn_cb) &jwzgles_glDisable,
3398 (list_fn_cb) &jwzgles_glEnableClientState,
3399 (list_fn_cb) &jwzgles_glDisableClientState };
3400 const char *fn = fns[(csp ? 2 : 0) + (set < 0 ? 1 : 0)];
3401 list_fn_cb f = fs[(csp ? 2 : 0) + (set < 0 ? 1 : 0)];
3403 Assert (!state->compiling_verts,
3404 "glEnable/glDisable not allowed inside glBegin");
3406 if (state->compiling_list)
3410 list_push (fn, f,PROTO_I, vv);
3413 if (! state->replaying_list &&
3414 ! state->compiling_list)
3415 LOG2 ("direct %-12s %s", fn, mode_desc(bit));
3417 if (csp && !state->compiling_verts)
3421 case GL_NORMAL_ARRAY: state->set.ncount += 2; break;
3422 case GL_TEXTURE_COORD_ARRAY: state->set.tcount += 2; break;
3423 case GL_COLOR_ARRAY: state->set.ccount += 2; break;
3428 case GL_NORMAL_ARRAY: state->set.ncount = 0; break;
3429 case GL_TEXTURE_COORD_ARRAY: state->set.tcount = 0; break;
3430 case GL_COLOR_ARRAY: state->set.ccount = 0; break;
3435 if (omitp || state->compiling_list)
3437 else if (set > 0 && csp)
3438 glEnableClientState (bit); /* the real one */
3439 else if (set < 0 && csp)
3440 glDisableClientState (bit); /* the real one */
3442 glEnable (bit); /* the real one */
3444 glDisable (bit); /* the real one */
3449 /* Store the bit in our state as well, or query it.
3453 unsigned long *enabled = (state->compiling_list
3454 ? &state->list_enabled
3461 result = !!(*enabled & flag);
3469 jwzgles_glEnable (GLuint bit)
3471 enable_disable (bit, 1);
3475 jwzgles_glDisable (GLuint bit)
3477 enable_disable (bit, -1);
3481 jwzgles_glIsEnabled (GLuint bit)
3483 return enable_disable (bit, 0);
3487 jwzgles_glEnableClientState (GLuint cap)
3489 enable_disable (cap, 1);
3493 jwzgles_glDisableClientState (GLuint cap)
3495 enable_disable (cap, -1);
3500 /* The spec says that OpenGLES 1.x doesn't implement glGetFloatv.
3501 Were this true, it would suck, for it would mean that there was no
3502 way to retrieve the prevailing matrixes. To implement this, we'd
3503 have to keep track of them all on the client side by combining in
3504 all the actions of glMultMatrixf, glRotatef, etc.
3506 However, Apple's iOS OpenGLES *does* provide glGetFloatv!
3509 jwzgles_glGetFloatv (GLenum pname, GLfloat *params)
3511 if (! state->replaying_list)
3512 LOG2 ("direct %-12s %s", "glGetFloatv", mode_desc(pname));
3513 glGetFloatv (pname, params); /* the real one */
3514 CHECK("glGetFloatv");
3518 /* Likewise: not supposed to be there, but it is. */
3520 jwzgles_glGetPointerv (GLenum pname, GLvoid *params)
3522 if (! state->replaying_list)
3523 LOG2 ("direct %-12s %s", "glGetPointerv", mode_desc(pname));
3524 glGetPointerv (pname, params); /* the real one */
3525 CHECK("glGetPointerv");
3529 /* How many cells are written into the *params array.
3530 We need to know this to avoid smashing the caller's stack
3531 if they asked for a single-value parameter.
3534 glGet_ret_count (GLenum pname)
3537 /*case GL_COLOR_MATRIX: */
3538 case GL_MODELVIEW_MATRIX:
3539 case GL_PROJECTION_MATRIX:
3540 case GL_TEXTURE_MATRIX:
3541 /*case GL_TRANSPOSE_COLOR_MATRIX: */
3542 /*case GL_TRANSPOSE_MODELVIEW_MATRIX: */
3543 /*case GL_TRANSPOSE_PROJECTION_MATRIX: */
3544 /*case GL_TRANSPOSE_TEXTURE_MATRIX: */
3546 /*case GL_ACCUM_CLEAR_VALUE: */
3547 /*case GL_BLEND_COLOR: */
3548 case GL_COLOR_CLEAR_VALUE:
3549 case GL_COLOR_WRITEMASK:
3550 case GL_CURRENT_COLOR:
3551 /*case GL_CURRENT_RASTER_COLOR: */
3552 /*case GL_CURRENT_RASTER_POSITION: */
3553 /*case GL_CURRENT_RASTER_SECONDARY_COLOR: */
3554 /*case GL_CURRENT_RASTER_TEXTURE_COORDS: */
3555 /*case GL_CURRENT_SECONDARY_COLOR: */
3556 case GL_CURRENT_TEXTURE_COORDS:
3558 case GL_LIGHT_MODEL_AMBIENT:
3559 /*case GL_MAP2_GRID_DOMAIN: */
3560 case GL_SCISSOR_BOX:
3563 case GL_CURRENT_NORMAL:
3564 case GL_POINT_DISTANCE_ATTENUATION:
3566 case GL_ALIASED_LINE_WIDTH_RANGE:
3567 case GL_ALIASED_POINT_SIZE_RANGE:
3568 case GL_DEPTH_RANGE:
3569 /*case GL_LINE_WIDTH_RANGE: */
3570 /*case GL_MAP1_GRID_DOMAIN: */
3571 /*case GL_MAP2_GRID_SEGMENTS: */
3572 case GL_MAX_VIEWPORT_DIMS:
3573 /*case GL_POINT_SIZE_RANGE: */
3574 case GL_POLYGON_MODE:
3575 case GL_SMOOTH_LINE_WIDTH_RANGE:
3576 case GL_SMOOTH_POINT_SIZE_RANGE:
3585 jwzgles_glGetDoublev (GLenum pname, GLdouble *params)
3588 int i, j = glGet_ret_count (pname);
3589 jwzgles_glGetFloatv (pname, m);
3590 for (i = 0; i < j; i++)
3596 jwzgles_glGetIntegerv (GLenum pname, GLint *params)
3599 int i, j = glGet_ret_count (pname);
3600 jwzgles_glGetFloatv (pname, m);
3601 for (i = 0; i < j; i++)
3607 jwzgles_glGetBooleanv (GLenum pname, GLboolean *params)
3610 int i, j = glGet_ret_count (pname);
3611 jwzgles_glGetFloatv (pname, m);
3612 for (i = 0; i < j; i++)
3613 params[i] = (m[i] != 0.0);
3618 jwzgles_gluErrorString (GLenum error)
3621 sprintf (s, "0x%lX", (unsigned long) error);
3626 /* These four *Pointer calls (plus glBindBuffer and glBufferData) can
3627 be included inside glNewList, but they actually execute immediately
3628 anyway, because their data is recorded in the list by the
3629 subsequently-recorded call to glDrawArrays. This is a little weird.
3632 jwzgles_glVertexPointer (GLuint size, GLuint type, GLuint stride,
3635 if (! state->replaying_list)
3636 LOG5 ("direct %-12s %d %s %d 0x%lX", "glVertexPointer",
3637 size, mode_desc(type), stride, (unsigned long) ptr);
3638 glVertexPointer (size, type, stride, ptr); /* the real one */
3639 CHECK("glVertexPointer");
3644 jwzgles_glNormalPointer (GLuint type, GLuint stride, const GLvoid *ptr)
3646 if (! state->replaying_list)
3647 LOG4 ("direct %-12s %s %d 0x%lX", "glNormalPointer",
3648 mode_desc(type), stride, (unsigned long) ptr);
3649 glNormalPointer (type, stride, ptr); /* the real one */
3650 CHECK("glNormalPointer");
3654 jwzgles_glColorPointer (GLuint size, GLuint type, GLuint stride,
3657 if (! state->replaying_list)
3658 LOG5 ("direct %-12s %d %s %d 0x%lX", "glColorPointer",
3659 size, mode_desc(type), stride, (unsigned long) ptr);
3660 glColorPointer (size, type, stride, ptr); /* the real one */
3661 CHECK("glColorPointer");
3665 jwzgles_glTexCoordPointer (GLuint size, GLuint type, GLuint stride,
3668 if (! state->replaying_list)
3669 LOG5 ("direct %-12s %d %s %d 0x%lX", "glTexCoordPointer",
3670 size, mode_desc(type), stride, (unsigned long) ptr);
3671 glTexCoordPointer (size, type, stride, ptr); /* the real one */
3672 CHECK("glTexCoordPointer");
3676 jwzgles_glBindBuffer (GLuint target, GLuint buffer)
3678 if (! state->replaying_list)
3679 LOG3 ("direct %-12s %s %d", "glBindBuffer", mode_desc(target), buffer);
3680 glBindBuffer (target, buffer); /* the real one */
3681 CHECK("glBindBuffer");
3685 jwzgles_glBufferData (GLenum target, GLsizeiptr size, const void *data,
3688 if (! state->replaying_list)
3689 LOG5 ("direct %-12s %s %ld 0x%lX %s", "glBufferData",
3690 mode_desc(target), size, (unsigned long) data, mode_desc(usage));
3691 glBufferData (target, size, data, usage); /* the real one */
3692 CHECK("glBufferData");
3697 jwzgles_glTexParameterf (GLuint target, GLuint pname, GLfloat param)
3699 Assert (!state->compiling_verts,
3700 "glTexParameterf not allowed inside glBegin");
3702 /* We don't *really* implement mipmaps, so just turn this off. */
3703 if (param == GL_LINEAR_MIPMAP_LINEAR) param = GL_LINEAR;
3704 if (param == GL_NEAREST_MIPMAP_LINEAR) param = GL_LINEAR;
3705 if (param == GL_LINEAR_MIPMAP_NEAREST) param = GL_NEAREST;
3706 if (param == GL_NEAREST_MIPMAP_NEAREST) param = GL_NEAREST;
3708 /* We implement 1D textures as 2D textures. */
3709 if (target == GL_TEXTURE_1D) target = GL_TEXTURE_2D;
3711 /* Apparently this is another invalid enum. Just ignore it. */
3712 if ((pname == GL_TEXTURE_WRAP_S || pname == GL_TEXTURE_WRAP_T) &&
3716 if (state->compiling_list)
3722 list_push ("glTexParameterf", (list_fn_cb) &jwzgles_glTexParameterf,
3727 if (! state->replaying_list)
3728 LOG4 ("direct %-12s %s %s %7.3f", "glTexParameterf",
3729 mode_desc(target), mode_desc(pname), param);
3730 glTexParameterf (target, pname, param); /* the real one */
3731 CHECK("glTexParameterf");
3736 jwzgles_glTexParameteri (GLuint target, GLuint pname, GLuint param)
3738 jwzgles_glTexParameterf (target, pname, param);
3743 jwzgles_glBindTexture (GLuint target, GLuint texture)
3745 Assert (!state->compiling_verts,
3746 "glBindTexture not allowed inside glBegin");
3748 /* We implement 1D textures as 2D textures. */
3749 if (target == GL_TEXTURE_1D) target = GL_TEXTURE_2D;
3751 if (state->compiling_list)
3756 list_push ("glBindTexture", (list_fn_cb) &jwzgles_glBindTexture,
3760 /* Do it immediately as well, for generate_texture_coords */
3763 if (! state->replaying_list)
3764 LOG3 ("direct %-12s %s %d", "glBindTexture",
3765 mode_desc(target), texture);
3766 glBindTexture (target, texture); /* the real one */
3767 CHECK("glBindTexture");
3773 /* Matrix functions, mostly cribbed from Mesa.
3777 jwzgles_glFrustum (GLfloat left, GLfloat right,
3778 GLfloat bottom, GLfloat top,
3779 GLfloat near, GLfloat far)
3782 GLfloat x = (2 * near) / (right-left);
3783 GLfloat y = (2 * near) / (top - bottom);
3784 GLfloat a = (right + left) / (right - left);
3785 GLfloat b = (top + bottom) / (top - bottom);
3786 GLfloat c = -(far + near) / (far - near);
3787 GLfloat d = -(2 * far * near) / (far - near);
3789 # define M(X,Y) m[Y * 4 + X]
3790 M(0,0) = x; M(0,1) = 0; M(0,2) = a; M(0,3) = 0;
3791 M(1,0) = 0; M(1,1) = y; M(1,2) = b; M(1,3) = 0;
3792 M(2,0) = 0; M(2,1) = 0; M(2,2) = c; M(2,3) = d;
3793 M(3,0) = 0; M(3,1) = 0; M(3,2) = -1; M(3,3) = 0;
3796 jwzgles_glMultMatrixf (m);
3801 jwzgles_glOrtho (GLfloat left, GLfloat right,
3802 GLfloat bottom, GLfloat top,
3803 GLfloat near, GLfloat far)
3806 GLfloat a = 2 / (right - left);
3807 GLfloat b = -(right + left) / (right - left);
3808 GLfloat c = 2 / (top - bottom);
3809 GLfloat d = -(top + bottom) / (top - bottom);
3810 GLfloat e = -2 / (far - near);
3811 GLfloat f = -(far + near) / (far - near);
3813 # define M(X,Y) m[Y * 4 + X]
3814 M(0,0) = a; M(0,1) = 0; M(0,2) = 0; M(0,3) = b;
3815 M(1,0) = 0; M(1,1) = c; M(1,2) = 0; M(1,3) = d;
3816 M(2,0) = 0; M(2,1) = 0; M(2,2) = e; M(2,3) = f;
3817 M(3,0) = 0; M(3,1) = 0; M(3,2) = 0; M(3,3) = 1;
3820 jwzgles_glMultMatrixf (m);
3825 jwzgles_gluPerspective (GLdouble fovy, GLdouble aspect,
3826 GLdouble near, GLdouble far)
3830 double rad = fovy / 2 * M_PI / 180;
3835 if (dz == 0 || si == 0 || aspect == 0)
3841 c = -(far + near) / dz;
3842 d = -2 * near * far / dz;
3844 # define M(X,Y) m[Y * 4 + X]
3845 M(0,0) = a; M(0,1) = 0; M(0,2) = 0; M(0,3) = 0;
3846 M(1,0) = 0; M(1,1) = b; M(1,2) = 0; M(1,3) = 0;
3847 M(2,0) = 0; M(2,1) = 0; M(2,2) = c; M(2,3) = d;
3848 M(3,0) = 0; M(3,1) = 0; M(3,2) = -1; M(3,3) = 0;
3851 jwzgles_glMultMatrixf (m);
3856 jwzgles_gluLookAt (GLfloat eyex, GLfloat eyey, GLfloat eyez,
3857 GLfloat centerx, GLfloat centery, GLfloat centerz,
3858 GLfloat upx, GLfloat upy, GLfloat upz)
3861 GLfloat x[3], y[3], z[3];
3864 /* Make rotation matrix */
3867 z[0] = eyex - centerx;
3868 z[1] = eyey - centery;
3869 z[2] = eyez - centerz;
3870 mag = sqrt(z[0] * z[0] + z[1] * z[1] + z[2] * z[2]);
3871 if (mag) { /* mpichler, 19950515 */
3882 /* X vector = Y cross Z */
3883 x[0] = y[1] * z[2] - y[2] * z[1];
3884 x[1] = -y[0] * z[2] + y[2] * z[0];
3885 x[2] = y[0] * z[1] - y[1] * z[0];
3887 /* Recompute Y = Z cross X */
3888 y[0] = z[1] * x[2] - z[2] * x[1];
3889 y[1] = -z[0] * x[2] + z[2] * x[0];
3890 y[2] = z[0] * x[1] - z[1] * x[0];
3892 /* mpichler, 19950515 */
3893 /* cross product gives area of parallelogram, which is < 1.0 for
3894 * non-perpendicular unit-length vectors; so normalize x, y here
3897 mag = sqrt(x[0] * x[0] + x[1] * x[1] + x[2] * x[2]);
3904 mag = sqrt(y[0] * y[0] + y[1] * y[1] + y[2] * y[2]);
3911 #define M(row,col) m[col*4+row]
3912 M(0, 0) = x[0]; M(0, 1) = x[1]; M(0, 2) = x[2]; M(0, 3) = 0.0;
3913 M(1, 0) = y[0]; M(1, 1) = y[1]; M(1, 2) = y[2]; M(1, 3) = 0.0;
3914 M(2, 0) = z[0]; M(2, 1) = z[1]; M(2, 2) = z[2]; M(2, 3) = 0.0;
3915 M(3, 0) = 0.0; M(3, 1) = 0.0; M(3, 2) = 0.0; M(3, 3) = 1.0;
3918 jwzgles_glMultMatrixf(m);
3920 /* Translate Eye to Origin */
3921 jwzgles_glTranslatef(-eyex, -eyey, -eyez);
3925 static void __gluMultMatrixVecd (const GLdouble matrix[16],
3926 const GLdouble in[4],
3931 for (i=0; i<4; i++) {
3933 in[0] * matrix[0*4+i] +
3934 in[1] * matrix[1*4+i] +
3935 in[2] * matrix[2*4+i] +
3936 in[3] * matrix[3*4+i];
3941 jwzgles_gluProject (GLdouble objx, GLdouble objy, GLdouble objz,
3942 const GLdouble modelMatrix[16],
3943 const GLdouble projMatrix[16],
3944 const GLint viewport[4],
3945 GLdouble *winx, GLdouble *winy, GLdouble *winz)
3950 /* #### I suspect this is not working right. I was seeing crazy values
3951 in lament.c. Maybe there's some float-vs-double confusion going on?
3958 __gluMultMatrixVecd(modelMatrix, in, out);
3959 __gluMultMatrixVecd(projMatrix, out, in);
3960 if (in[3] == 0.0) return(GL_FALSE);
3964 /* Map x, y and z to range 0-1 */
3965 in[0] = in[0] * 0.5 + 0.5;
3966 in[1] = in[1] * 0.5 + 0.5;
3967 in[2] = in[2] * 0.5 + 0.5;
3969 /* Map x,y to viewport */
3970 in[0] = in[0] * viewport[2] + viewport[0];
3971 in[1] = in[1] * viewport[3] + viewport[1];
3980 /* The following functions are present in both OpenGL 1.1 and in OpenGLES 1,
3981 but are allowed within glNewList/glEndList, so we must wrap them to allow
3982 them to either be recorded in lists, or run directly.
3984 All this CPP obscenity is me screaming in rage at all the ways that C is
3985 not Lisp, as all I want to do here is DEFADVICE.
3988 #define PROTO_V PROTO_VOID
3989 #define TYPE_V GLuint
3991 #define VARS_V /* */
3993 #define FILL_V /* */
3995 #define TYPE_I GLuint
3996 #define TYPE_II TYPE_I
3997 #define TYPE_III TYPE_I
3998 #define TYPE_IIII TYPE_I
3999 #define ARGS_I TYPE_I a
4000 #define ARGS_II TYPE_I a, TYPE_I b
4001 #define ARGS_III TYPE_I a, TYPE_I b, TYPE_I c
4002 #define ARGS_IIII TYPE_I a, TYPE_I b, TYPE_I c, TYPE_I d
4003 #define LOGS_I "%s\n", mode_desc(a)
4004 #define LOGS_II "%s %d\n", mode_desc(a), b
4005 #define LOGS_III "%s %s %s\n", mode_desc(a), mode_desc(b), mode_desc(c)
4006 #define LOGS_IIII "%d %d %d %d\n", a, b, c, d
4008 #define VARS_II a, b
4009 #define VARS_III a, b, c
4010 #define VARS_IIII a, b, c, d
4011 #define FILL_I vv[0].i = a;
4012 #define FILL_II vv[0].i = a; vv[1].i = b;
4013 #define FILL_III vv[0].i = a; vv[1].i = b; vv[2].i = c;
4014 #define FILL_IIII vv[0].i = a; vv[1].i = b; vv[2].i = c; vv[3].i = d;
4016 #define TYPE_F GLfloat
4017 #define TYPE_FF TYPE_F
4018 #define TYPE_FFF TYPE_F
4019 #define TYPE_FFFF TYPE_F
4020 #define ARGS_F TYPE_F a
4021 #define ARGS_FF TYPE_F a, TYPE_F b
4022 #define ARGS_FFF TYPE_F a, TYPE_F b, TYPE_F c
4023 #define ARGS_FFFF TYPE_F a, TYPE_F b, TYPE_F c, TYPE_F d
4024 #define LOGS_F "%7.3f\n", a
4025 #define LOGS_FF "%7.3f %7.3f\n", a, b
4026 #define LOGS_FFF "%7.3f %7.3f %7.3f\n", a, b, c
4027 #define LOGS_FFFF "%7.3f %7.3f %7.3f %7.3f\n", a, b, c, d
4028 #define VARS_F VARS_I
4029 #define VARS_FF VARS_II
4030 #define VARS_FFF VARS_III
4031 #define VARS_FFFF VARS_IIII
4032 #define FILL_F vv[0].f = a;
4033 #define FILL_FF vv[0].f = a; vv[1].f = b;
4034 #define FILL_FFF vv[0].f = a; vv[1].f = b; vv[2].f = c;
4035 #define FILL_FFFF vv[0].f = a; vv[1].f = b; vv[2].f = c; vv[3].f = d;
4037 #define ARGS_IF TYPE_I a, TYPE_F b
4038 #define VARS_IF VARS_II
4039 #define LOGS_IF "%s %7.3f\n", mode_desc(a), b
4040 #define FILL_IF vv[0].i = a; vv[1].f = b;
4042 #define ARGS_IIF TYPE_I a, TYPE_I b, TYPE_F c
4043 #define VARS_IIF VARS_III
4044 #define LOGS_IIF "%s %s %7.3f\n", mode_desc(a), mode_desc(b), c
4045 #define FILL_IIF vv[0].i = a; vv[1].i = b; vv[2].f = c;
4047 #define TYPE_IV GLint
4048 #define ARGS_IIV TYPE_I a, const TYPE_IV *b
4049 #define VARS_IIV VARS_II
4050 #define LOGS_IIV "%s %d %d %d %d\n", mode_desc(a), b[0], b[1], b[2], b[3]
4051 #define FILL_IIV vv[0].i = a; \
4052 vv[1].i = b[0]; vv[2].i = b[1]; \
4053 vv[3].i = b[2]; vv[4].i = b[3];
4055 #define ARGS_IFV TYPE_I a, const TYPE_F *b
4056 #define VARS_IFV VARS_II
4057 #define LOGS_IFV "%s %7.3f %7.3f %7.3f %7.3f\n", mode_desc(a), \
4058 b[0], b[1], b[2], b[3]
4059 #define FILL_IFV vv[0].i = a; \
4060 vv[1].f = b[0]; vv[2].f = b[1]; \
4061 vv[3].f = b[2]; vv[4].f = b[3];
4063 #define ARGS_IIIV TYPE_I a, TYPE_I b, const TYPE_IV *c
4064 #define VARS_IIIV VARS_III
4065 #define LOGS_IIIV "%s %-8s %3d %3d %3d %3d\n", mode_desc(a), mode_desc(b), \
4066 c[0], c[1], c[2], c[3]
4067 #define FILL_IIIV vv[0].i = a; vv[1].i = b; \
4068 vv[2].i = c[0]; vv[3].i = c[1]; \
4069 vv[4].i = c[2]; vv[5].i = c[3];
4071 #define ARGS_IIFV TYPE_I a, TYPE_I b, const TYPE_F *c
4072 #define VARS_IIFV VARS_III
4073 #define LOGS_IIFV "%s %-8s %7.3f %7.3f %7.3f %7.3f\n", \
4074 mode_desc(a), mode_desc(b), \
4075 c[0], c[1], c[2], c[3]
4076 #define FILL_IIFV vv[0].i = a; vv[1].i = b; \
4077 vv[2].f = c[0]; vv[3].f = c[1]; \
4078 vv[4].f = c[2]; vv[5].f = c[3];
4081 # define WLOG(NAME,ARGS) \
4082 fprintf (stderr, "jwzgles: direct %-12s ", NAME); \
4083 fprintf (stderr, ARGS)
4085 # define WLOG(NAME,ARGS) /* */
4088 #define WRAP(NAME,SIG) \
4089 void jwzgles_##NAME (ARGS_##SIG) \
4091 Assert (!state->compiling_verts, \
4092 STRINGIFY(NAME) " not allowed inside glBegin"); \
4093 if (state->compiling_list) { \
4096 list_push (STRINGIFY(NAME), (list_fn_cb) &jwzgles_##NAME, \
4099 if (! state->replaying_list) { \
4100 WLOG (STRINGIFY(NAME), LOGS_##SIG); \
4102 NAME (VARS_##SIG); \
4103 CHECK(STRINGIFY(NAME)); \
4107 WRAP (glActiveTexture, I)
4108 WRAP (glAlphaFunc, IF)
4109 WRAP (glBlendFunc, II)
4111 WRAP (glClearColor, FFFF)
4112 WRAP (glClearStencil, I)
4113 WRAP (glColorMask, IIII)
4114 WRAP (glCullFace, I)
4115 WRAP (glDepthFunc, I)
4116 WRAP (glDepthMask, I)
4121 WRAP (glFrontFace, I)
4123 WRAP (glLightModelf, IF)
4124 WRAP (glLightModelfv, IFV)
4125 WRAP (glLightf, IIF)
4126 WRAP (glLightfv, IIFV)
4127 WRAP (glLineWidth, F)
4128 WRAP (glLoadIdentity, V)
4130 WRAP (glMatrixMode, I)
4131 WRAP (glPixelStorei, II)
4132 WRAP (glPointSize, F)
4133 WRAP (glPolygonOffset, FF)
4134 WRAP (glPopMatrix, V)
4135 WRAP (glPushMatrix, V)
4136 WRAP (glRotatef, FFFF)
4137 WRAP (glScalef, FFF)
4138 WRAP (glScissor, IIII)
4139 WRAP (glShadeModel, I)
4140 WRAP (glStencilFunc, III)
4141 WRAP (glStencilMask, I)
4142 WRAP (glStencilOp, III)
4143 WRAP (glTexEnvf, IIF)
4144 WRAP (glTexEnvi, III)
4145 WRAP (glTranslatef, FFF)
4146 WRAP (glViewport, IIII)
4148 #define TYPE_IV GLuint
4149 WRAP (glDeleteTextures, IIV)
4152 #endif /* HAVE_JWZGLES - whole file */