1 /* xscreensaver, Copyright (c) 2012-2015 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_glVertex2dv (const GLdouble *v)
1594 jwzgles_glVertex2f (v[0], v[1]);
1598 jwzgles_glVertex2fv (const GLfloat *v)
1600 jwzgles_glVertex2f (v[0], v[1]);
1604 jwzgles_glVertex2i (GLint x, GLint y)
1606 jwzgles_glVertex2f (x, y);
1611 jwzgles_glLightiv (GLenum light, GLenum pname, const GLint *params)
1618 jwzgles_glLightfv (light, pname, v);
1622 jwzgles_glLightModeliv (GLenum pname, const GLint *params)
1629 jwzgles_glLightModelfv (pname, v);
1633 jwzgles_glFogiv (GLenum pname, const GLint *params)
1640 jwzgles_glFogfv (pname, v);
1644 jwzgles_glLighti (GLenum light, GLenum pname, GLint param)
1646 jwzgles_glLightf (light, pname, param);
1650 jwzgles_glLightModeli (GLenum pname, GLint param)
1652 jwzgles_glLightModelf (pname, param);
1656 jwzgles_glFogi (GLenum pname, GLint param)
1658 jwzgles_glFogf (pname, param);
1663 jwzgles_glRotated (GLdouble angle, GLdouble x, GLdouble y, GLdouble z)
1665 jwzgles_glRotatef (angle, x, y, z);
1670 jwzgles_glClipPlane (GLenum plane, const GLdouble *equation)
1672 Assert (state->compiling_verts, "glClipPlane not inside glBegin");
1673 Assert (0, "glClipPlane unimplemented"); /* no GLES equivalent... */
1678 jwzgles_glPolygonMode (GLenum face, GLenum mode)
1680 Assert (!state->compiling_verts, "not inside glBegin");
1681 if (state->compiling_list)
1686 list_push ("glPolygonMode", (list_fn_cb) &jwzgles_glPolygonMode,
1691 /* POINT and LINE don't exist in GLES */
1692 Assert (mode == GL_FILL, "glPolygonMode: unimplemented mode");
1698 jwzgles_glDrawBuffer (GLenum buf)
1700 Assert (!state->compiling_verts, "not inside glBegin");
1701 if (state->compiling_list)
1705 list_push ("glDrawBuffer", (list_fn_cb) &jwzgles_glDrawBuffer,
1710 /* Assert (buf == GL_BACK, "glDrawBuffer: back buffer only"); */
1711 # ifndef GL_VERSION_ES_CM_1_0 /* not compiling against OpenGLES 1.x */
1712 if (! state->replaying_list)
1713 LOG1 ("direct %-12s", "glDrawBuffer");
1714 glDrawBuffer (buf); /* the real one */
1715 CHECK("glDrawBuffer");
1721 /* Given an array of sets of 4 elements of arbitrary size, convert it
1722 to an array of sets of 6 elements instead: ABCD becomes ABC BCD.
1725 cq2t (unsigned char **arrayP, int stride, int count)
1727 int count2 = count * 6 / 4;
1728 int size = stride * count;
1729 int size2 = stride * count2;
1730 const unsigned char *oarray, *in;
1731 unsigned char *array2, *oarray2, *out;
1735 if (!oarray || count == 0)
1738 array2 = (unsigned char *) malloc (size2);
1739 Assert (array2, "out of memory");
1744 for (i = 0; i < count / 4; i++)
1746 const unsigned char *a, *b, *c, *d; /* the 4 corners */
1747 a = in; in += stride;
1748 b = in; in += stride;
1749 c = in; in += stride;
1750 d = in; in += stride;
1752 # define PUSH(IN) do { \
1753 const unsigned char *ii = IN; \
1755 for (j = 0; j < stride; j++) { \
1759 PUSH (a); PUSH (b); PUSH (d); /* the 2 triangles */
1760 PUSH (b); PUSH (c); PUSH (d);
1764 Assert (in == oarray + size, "convert_quads corrupted");
1765 Assert (out == oarray2 + size2, "convert_quads corrupted");
1773 /* Convert all coordinates in a GL_QUADS vert_set to GL_TRIANGLES.
1776 convert_quads_to_triangles (vert_set *s)
1779 Assert (s->mode == GL_QUADS, "convert_quads bad mode");
1781 cq2t ((unsigned char **) &s->verts, sizeof(*s->verts), s->count);
1782 cq2t ((unsigned char **) &s->norms, sizeof(*s->norms), s->count);
1783 cq2t ((unsigned char **) &s->tex, sizeof(*s->tex), s->count);
1784 cq2t ((unsigned char **) &s->color, sizeof(*s->color), s->count);
1787 s->mode = GL_TRIANGLES;
1792 jwzgles_glEnd (void)
1794 vert_set *s = &state->set;
1795 int was_norm, was_tex, was_color, was_mat;
1796 int is_norm, is_tex, is_color, is_mat;
1798 Assert (state->compiling_verts == 1, "missing glBegin");
1799 state->compiling_verts--;
1801 Assert (!state->replaying_list, "how did glEnd get into a display list?");
1803 if (!state->replaying_list)
1805 LOG5 ("%s [V = %d, N = %d, T = %d, C = %d]",
1806 (state->compiling_list || state->replaying_list ? " " : ""),
1807 s->count, s->ncount, s->tcount, s->ccount);
1809 (state->compiling_list || state->replaying_list ? " " : ""));
1812 if (s->count == 0) return;
1814 if (s->mode == GL_QUADS)
1815 convert_quads_to_triangles (s);
1816 else if (s->mode == GL_QUAD_STRIP)
1817 s->mode = GL_TRIANGLE_STRIP; /* They do the same thing! */
1818 else if (s->mode == GL_POLYGON)
1819 s->mode = GL_TRIANGLE_FAN; /* They do the same thing! */
1821 jwzgles_glColorPointer (4,GL_FLOAT, sizeof(*s->color),s->color); /* RGBA */
1822 jwzgles_glNormalPointer ( GL_FLOAT, sizeof(*s->norms),s->norms); /* XYZ */
1823 jwzgles_glTexCoordPointer(4,GL_FLOAT, sizeof(*s->tex), s->tex); /* STRQ */
1824 jwzgles_glVertexPointer (4,GL_FLOAT, sizeof(*s->verts),s->verts); /* XYZW */
1825 /* glVertexPointer must come after glTexCoordPointer */
1827 /* If there were no calls to glNormal3f inside of glBegin/glEnd,
1828 don't bother enabling the normals array.
1830 If there was exactly *one* call to glNormal3f inside of glBegin/glEnd,
1831 and it was before the first glVertex3f, then also don't enable the
1832 normals array, but do emit that call to glNormal3f before calling
1835 Likewise for texture coordinates and colors.
1837 Be careful to leave the arrays' enabled/disabled state the same as
1838 before, or a later caller might end up using one of our arrays by
1839 mistake. (Remember that jwzgles_glIsEnabled() tracks the enablement
1840 of the list-in-progress as well as the global state.)
1842 was_norm = jwzgles_glIsEnabled (GL_NORMAL_ARRAY);
1843 was_tex = jwzgles_glIsEnabled (GL_TEXTURE_COORD_ARRAY);
1844 was_color = jwzgles_glIsEnabled (GL_COLOR_ARRAY);
1845 was_mat = jwzgles_glIsEnabled (GL_COLOR_MATERIAL);
1847 /* If we're executing glEnd in immediate mode, not from inside a display
1848 list (which is the only way it happens, because glEnd doesn't go into
1849 display lists), make sure we're not stomping on a saved buffer list:
1850 in immediate mode, vertexes are client-side only.
1852 if (! state->compiling_list)
1853 jwzgles_glBindBuffer (GL_ARRAY_BUFFER, 0);
1858 jwzgles_glEnableClientState (GL_NORMAL_ARRAY);
1864 jwzgles_glNormal3f (s->cnorm.x, s->cnorm.y, s->cnorm.z);
1865 jwzgles_glDisableClientState (GL_NORMAL_ARRAY);
1868 if (s->tcount > 1 ||
1869 ((state->compiling_list ? state->list_enabled : state->enabled)
1870 & (ISENABLED_TEXTURE_GEN_S | ISENABLED_TEXTURE_GEN_T |
1871 ISENABLED_TEXTURE_GEN_R | ISENABLED_TEXTURE_GEN_Q)))
1873 /* Enable texture coords if any were specified; or if generation
1874 is on in immediate mode; or if this list turned on generation. */
1876 jwzgles_glEnableClientState (GL_TEXTURE_COORD_ARRAY);
1882 jwzgles_glTexCoord4f (s->ctex.s, s->ctex.t, s->ctex.r, s->ctex.q);
1883 jwzgles_glDisableClientState (GL_TEXTURE_COORD_ARRAY);
1889 jwzgles_glEnableClientState (GL_COLOR_ARRAY);
1895 jwzgles_glColor4f (s->ccolor.r, s->ccolor.g, s->ccolor.b, s->ccolor.a);
1896 jwzgles_glDisableClientState (GL_COLOR_ARRAY);
1899 jwzgles_glEnableClientState (GL_VERTEX_ARRAY);
1901 /* We translated the glMaterial calls to per-vertex colors, which are
1902 of the glColor sort, not the glMaterial sort, so automatically
1903 turn on material mapping. Maybe this is a bad idea.
1905 if (s->materialistic && !jwzgles_glIsEnabled (GL_COLOR_MATERIAL))
1908 jwzgles_glEnable (GL_COLOR_MATERIAL);
1913 glBindBuffer (GL_ARRAY_BUFFER, 0); /* This comes later. */
1914 jwzgles_glDrawArrays (s->mode, 0, s->count);
1915 glBindBuffer (GL_ARRAY_BUFFER, 0); /* Keep out of others' hands */
1917 # define RESET(VAR,FN,ARG) do { \
1918 if (is_##VAR != was_##VAR) { \
1919 if (was_##VAR) jwzgles_glEnable##FN (ARG); \
1920 else jwzgles_glDisable##FN (ARG); \
1922 RESET (norm, ClientState, GL_NORMAL_ARRAY);
1923 RESET (tex, ClientState, GL_TEXTURE_COORD_ARRAY);
1924 RESET (color, ClientState, GL_COLOR_ARRAY);
1925 RESET (mat, , GL_COLOR_MATERIAL);
1932 s->materialistic = 0;
1936 /* The display list is full of calls to glDrawArrays(), plus saved arrays
1937 of the values we need to restore before calling it. "Restore" means
1938 "ship them off to the GPU before each call".
1940 So instead, this function walks through the display list and
1941 combines all of those vertex, normal, texture and color values into
1942 a single VBO array; ships those values off to the GPU *once* at the
1943 time of glEndList; and when running the list with glCallList, the
1944 values are already on the GPU and don't need to be sent over again.
1946 The VBO persists in the GPU until the display list is deleted.
1949 optimize_arrays (void)
1951 list *L = &state->lists.lists[state->compiling_list-1];
1954 int combo_count = 0;
1956 GLuint buf_name = 0;
1958 Assert (state->compiling_list, "not compiling a list");
1959 Assert (L, "no list");
1960 Assert (!L->buffer, "list already has a buffer");
1962 glGenBuffers (1, &buf_name);
1963 CHECK("glGenBuffers");
1964 if (! buf_name) return;
1966 L->buffer = buf_name;
1968 /* Go through the list and dump the contents of the various saved arrays
1969 into one large array.
1971 for (i = 0; i < L->count; i++)
1973 list_fn *F = &L->fns[i];
1977 /* count = F->argv[2].i;*/ /* 3rd arg to glDrawArrays */
1979 for (j = 0; j < 4; j++)
1981 draw_array *A = &F->arrays[j];
1982 int ocount = combo_count;
1984 /* If some caller is using arrays that don't have floats in them,
1985 we just leave them as-is and ship them over at each call.
1986 Doubt this ever really happens.
1988 if (A->type != GL_FLOAT)
1991 if (! A->data) /* No array. */
1994 Assert (A->bytes > 0, "no bytes in draw_array");
1995 Assert (((unsigned long) A->data > 0xFFFF),
1996 "buffer data not a pointer");
1998 combo_count += A->bytes / sizeof(*combo);
1999 make_room ("optimize_arrays",
2000 (void **) &combo, sizeof(*combo),
2001 &combo_count, &combo_size);
2002 memcpy (combo + ocount, A->data, A->bytes);
2003 A->binding = buf_name;
2005 /* 'data' is now the byte offset into the VBO. */
2006 A->data = (void *) (ocount * sizeof(*combo));
2007 /* LOG3(" loaded %lu floats to pos %d of buffer %d",
2008 A->bytes / sizeof(*combo), ocount, buf_name); */
2012 if (combo_count == 0) /* Nothing to do! */
2014 if (combo) free (combo);
2015 glDeleteBuffers (1, &buf_name);
2020 glBindBuffer (GL_ARRAY_BUFFER, buf_name);
2021 glBufferData (GL_ARRAY_BUFFER,
2022 combo_count * sizeof (*combo),
2025 glBindBuffer (GL_ARRAY_BUFFER, 0); /* Keep out of others' hands */
2027 LOG3(" loaded %d floats of list %d into VBO %d",
2028 combo_count, state->compiling_list, buf_name);
2032 for (i = 0; i < combo_count; i++)
2035 fprintf (stderr, "\njwzgles: %4d: ", i);
2036 fprintf (stderr, " %7.3f", combo[i]);
2038 fprintf (stderr, "\n");
2042 if (combo) free (combo);
2047 jwzgles_glCallList (int id)
2049 if (state->compiling_list)
2051 /* Yes, you can call lists inside of lists.
2052 Yes, recursion would be a mistake. */
2055 list_push ("glCallList", (list_fn_cb) &jwzgles_glCallList, PROTO_I, vv);
2062 state->replaying_list++;
2065 fprintf (stderr, "\n");
2066 LOG1 ("glCallList %d", id);
2069 Assert (id > 0 && id <= state->lists.count, "glCallList: bogus ID");
2070 L = &state->lists.lists[id-1];
2071 Assert (id == L->id, "glCallList corrupted");
2073 for (i = 0; i < L->count; i++)
2075 list_fn *F = &L->fns[i];
2076 list_fn_cb fn = F->fn;
2077 void_int *av = F->argv;
2081 LOG1 (" call %-12s", F->name);
2082 ((void (*) (void)) fn) ();
2086 if (fn == (list_fn_cb) &jwzgles_glBegin ||
2087 fn == (list_fn_cb) &jwzgles_glFrontFace ||
2088 fn == (list_fn_cb) &jwzgles_glEnable ||
2089 fn == (list_fn_cb) &jwzgles_glDisable ||
2090 fn == (list_fn_cb) &jwzgles_glEnableClientState ||
2091 fn == (list_fn_cb) &jwzgles_glDisableClientState ||
2092 fn == (list_fn_cb) &jwzgles_glShadeModel ||
2093 fn == (list_fn_cb) &jwzgles_glMatrixMode)
2094 LOG2 (" call %-12s %s", F->name, mode_desc (av[0].i));
2096 LOG2 (" call %-12s %d", F->name, av[0].i);
2097 ((void (*) (int)) fn) (av[0].i);
2101 LOG2 (" call %-12s %7.3f", F->name, av[0].f);
2102 ((void (*) (GLfloat)) fn) (av[0].f);
2106 if (fn == (list_fn_cb) &jwzgles_glBindTexture ||
2107 fn == (list_fn_cb) &jwzgles_glBindBuffer)
2108 LOG3 (" call %-12s %s %d", F->name,
2109 mode_desc (av[0].i), av[1].i);
2111 LOG3 (" call %-12s %d %d", F->name, av[0].i, av[1].i);
2112 ((void (*) (int, int)) fn) (av[0].i, av[1].i);
2116 LOG3 (" call %-12s %7.3f %7.3f", F->name, av[0].f, av[1].f);
2117 ((void (*) (GLfloat, GLfloat)) fn) (av[0].f, av[1].f);
2121 LOG3 (" call %-12s %s %7.3f", F->name,
2122 mode_desc (av[0].f), av[1].f);
2123 ((void (*) (GLint, GLfloat)) fn) (av[0].i, av[1].f);
2126 case PROTO_III: III:
2127 if (fn == (list_fn_cb) &jwzgles_glDrawArrays ||
2128 fn == (list_fn_cb) &jwzgles_glTexParameteri)
2129 LOG4 (" call %-12s %s %d %d", F->name,
2130 mode_desc (av[0].i), av[1].i, av[2].i);
2132 LOG4 (" call %-12s %d %d %d", F->name,
2133 av[0].i, av[1].i, av[2].i);
2134 ((void (*) (int, int, int)) fn) (av[0].i, av[1].i, av[2].i);
2138 LOG4 (" call %-12s %7.3f %7.3f %7.3f", F->name,
2139 av[0].f, av[1].f, av[2].f);
2140 ((void (*) (GLfloat, GLfloat, GLfloat)) fn)
2141 (av[0].f, av[1].f, av[2].f);
2145 LOG4 (" call %-12s %s %s %7.3f", F->name,
2146 mode_desc (av[0].i), mode_desc (av[1].i), av[2].f);
2147 ((void (*) (int, int, GLfloat)) fn) (av[0].i, av[1].i, av[2].f);
2151 LOG5 (" call %-12s %d %d %d %d", F->name,
2152 av[0].i, av[1].i, av[2].i, av[3].i);
2153 ((void (*) (int, int, int, int)) fn)
2154 (av[0].i, av[1].i, av[2].i, av[3].i);
2158 LOG5 (" call %-12s %7.3f %7.3f %7.3f %7.3f", F->name,
2159 av[0].f, av[1].f, av[2].f, av[3].f);
2160 ((void (*) (GLfloat, GLfloat, GLfloat, GLfloat)) fn)
2161 (av[0].f, av[1].f, av[2].f, av[3].f);
2171 LOG6 (" call %-12s %s %3.1f %3.1f %3.1f %3.1f", F->name,
2172 mode_desc (av[0].i),
2173 av[1].f, av[2].f, av[3].f, av[4].f);
2174 ((void (*) (int, const GLfloat *)) fn) (av[0].i, v);
2185 LOG7 (" call %-12s %s %-8s %3.1f %3.1f %3.1f %3.1f", F->name,
2186 mode_desc (av[0].i), mode_desc (av[1].i),
2187 av[2].f, av[3].f, av[4].f, av[5].f);
2188 ((void (*) (int, int, const GLfloat *)) fn)
2189 (av[0].i, av[1].i, v);
2200 LOG6 (" call %-12s %s %3d %3d %3d %3d", F->name,
2201 mode_desc (av[0].i),
2202 av[1].i, av[2].i, av[3].i, av[4].i);
2203 ((void (*) (int, const int *)) fn) (av[0].i, v);
2214 LOG7 (" call %-12s %s %-8s %3d %3d %3d %3d", F->name,
2215 mode_desc (av[0].i), mode_desc (av[1].i),
2216 av[2].i, av[3].i, av[4].i, av[5].i);
2217 ((void (*) (int, int, const int *)) fn)
2218 (av[0].i, av[1].i, v);
2223 restore_arrays (F, av[1].i + av[2].i);
2231 for (i = 0; i < countof(m); i++)
2233 LOG17 (" call %-12s ["
2234 "%8.3f %8.3f %8.3f %8.3f " "\n\t\t\t "
2235 "%8.3f %8.3f %8.3f %8.3f " "\n\t\t\t "
2236 "%8.3f %8.3f %8.3f %8.3f " "\n\t\t\t "
2237 "%8.3f %8.3f %8.3f %8.3f ]",
2239 m[0], m[1], m[2], m[3],
2240 m[4], m[5], m[6], m[7],
2241 m[8], m[9], m[10], m[11],
2242 m[12], m[13], m[14], m[15]);
2243 ((void (*) (GLfloat *)) fn) (m);
2248 Assert (0, "bogus prototype");
2253 LOG1 ("glCallList %d done\n", id);
2255 state->replaying_list--;
2256 Assert (state->replaying_list >= 0, "glCallList corrupted");
2261 /* When we save a call to glDrawArrays into a display list, we also need to
2262 save the prevailing copy of the arrays that it will use, and restore them
2266 save_arrays (list_fn *F, int count)
2269 draw_array *A = (draw_array *) calloc (4, sizeof (*A));
2270 Assert (A, "out of memory");
2272 /* if (state->set.count > 0) */
2274 glGetIntegerv (GL_VERTEX_ARRAY_BUFFER_BINDING, &A[i].binding);
2275 glGetIntegerv (GL_VERTEX_ARRAY_SIZE, &A[i].size);
2276 glGetIntegerv (GL_VERTEX_ARRAY_TYPE, &A[i].type);
2277 glGetIntegerv (GL_VERTEX_ARRAY_STRIDE, &A[i].stride);
2278 glGetPointerv (GL_VERTEX_ARRAY_POINTER, &A[i].data);
2279 CHECK("glGetPointerv");
2280 copy_array_data (&A[i], count, "vert");
2284 if (state->set.ncount > 1)
2287 glGetIntegerv (GL_NORMAL_ARRAY_BUFFER_BINDING, &A[i].binding);
2288 glGetIntegerv (GL_NORMAL_ARRAY_TYPE, &A[i].type);
2289 glGetIntegerv (GL_NORMAL_ARRAY_STRIDE, &A[i].stride);
2290 glGetPointerv (GL_NORMAL_ARRAY_POINTER, &A[i].data);
2291 CHECK("glGetPointerv");
2292 copy_array_data (&A[i], count, "norm");
2296 if (state->set.tcount > 1)
2298 glGetIntegerv (GL_TEXTURE_COORD_ARRAY_BUFFER_BINDING, &A[i].binding);
2299 glGetIntegerv (GL_TEXTURE_COORD_ARRAY_SIZE, &A[i].size);
2300 glGetIntegerv (GL_TEXTURE_COORD_ARRAY_TYPE, &A[i].type);
2301 glGetIntegerv (GL_TEXTURE_COORD_ARRAY_STRIDE, &A[i].stride);
2302 glGetPointerv (GL_TEXTURE_COORD_ARRAY_POINTER, &A[i].data);
2303 CHECK("glGetPointerv");
2304 copy_array_data (&A[i], count, "tex ");
2308 if (state->set.ccount > 1)
2310 glGetIntegerv (GL_COLOR_ARRAY_BUFFER_BINDING, &A[i].binding);
2311 glGetIntegerv (GL_COLOR_ARRAY_SIZE, &A[i].size);
2312 glGetIntegerv (GL_COLOR_ARRAY_TYPE, &A[i].type);
2313 glGetIntegerv (GL_COLOR_ARRAY_STRIDE, &A[i].stride);
2314 glGetPointerv (GL_COLOR_ARRAY_POINTER, &A[i].data);
2315 CHECK("glGetPointerv");
2316 copy_array_data (&A[i], count, "col ");
2319 /* Freed by glDeleteLists. */
2321 Assert (!F->arrays, "save_arrays corrupted");
2329 dump_array_data (draw_array *A, int count,
2330 const char *action, const char *name, const void *old)
2332 int bytes = count * A->stride;
2337 "jwzgles: %s %s %d %s %2d, %4d = %5d bind %d @ %d\n",
2339 A->size, mode_desc(A->type), A->stride,
2340 count, bytes, A->binding, (int) A->data);
2344 Assert (bytes == A->bytes, "array data corrupted");
2346 fprintf (stderr, "jwzgles: %s %s %d %s %2d, %4d = %5d @ %lX",
2348 A->size, mode_desc(A->type), A->stride,
2349 count, bytes, (unsigned long) A->data);
2351 fprintf (stderr, " / %lX", (unsigned long) old);
2352 fprintf (stderr, "\n");
2357 Assert (((unsigned long) A->data < 0xFFFF),
2358 "buffer binding should be a numeric index,"
2359 " but looks like a pointer");
2362 /* glGetBufferSubData doesn't actually exist in OpenGLES, but this
2363 was helpful for debugging on real OpenGL... */
2366 fprintf (stderr, "jwzgles: read back:\n");
2367 d = (GLfloat *) malloc (A->bytes);
2368 glGetBufferSubData (GL_ARRAY_BUFFER, (int) A->data,
2369 count * A->stride, (void *) d);
2370 CHECK("glGetBufferSubData");
2371 for (i = 0; i < count * A->size; i++)
2374 fprintf (stderr, "\njwzgles: %4d: ",
2375 i + (int) A->data / sizeof(GLfloat));
2376 fprintf (stderr, " %7.3f", d[i]);
2378 fprintf (stderr, "\n");
2385 unsigned char *b = (unsigned char *) A->data;
2387 if ((unsigned long) A->data < 0xFFFF)
2389 Assert (0, "buffer data not a pointer");
2392 for (i = 0; i < count; i++)
2395 GLfloat *f = (GLfloat *) b;
2397 if (s == 0) s = 3; /* normals */
2398 fprintf (stderr, "jwzgles: ");
2399 for (j = 0; j < s; j++)
2400 fprintf (stderr, " %7.3f", f[j]);
2401 fprintf (stderr, "\n");
2409 dump_direct_array_data (int count)
2411 draw_array A = { 0, };
2413 if (jwzgles_glIsEnabled (GL_VERTEX_ARRAY))
2415 glGetIntegerv (GL_VERTEX_ARRAY_BUFFER_BINDING, &A.binding);
2416 glGetIntegerv (GL_VERTEX_ARRAY_SIZE, &A.size);
2417 glGetIntegerv (GL_VERTEX_ARRAY_TYPE, &A.type);
2418 glGetIntegerv (GL_VERTEX_ARRAY_STRIDE, &A.stride);
2419 glGetPointerv (GL_VERTEX_ARRAY_POINTER, &A.data);
2420 A.bytes = count * A.stride;
2421 dump_array_data (&A, count, "direct", "vertex ", 0);
2423 if (jwzgles_glIsEnabled (GL_NORMAL_ARRAY))
2426 glGetIntegerv (GL_NORMAL_ARRAY_BUFFER_BINDING, &A.binding);
2427 glGetIntegerv (GL_NORMAL_ARRAY_TYPE, &A.type);
2428 glGetIntegerv (GL_NORMAL_ARRAY_STRIDE, &A.stride);
2429 glGetPointerv (GL_NORMAL_ARRAY_POINTER, &A.data);
2430 A.bytes = count * A.stride;
2431 dump_array_data (&A, count, "direct", "normal ", 0);
2433 if (jwzgles_glIsEnabled (GL_TEXTURE_COORD_ARRAY))
2435 glGetIntegerv (GL_TEXTURE_COORD_ARRAY_BUFFER_BINDING, &A.binding);
2436 glGetIntegerv (GL_TEXTURE_COORD_ARRAY_SIZE, &A.size);
2437 glGetIntegerv (GL_TEXTURE_COORD_ARRAY_TYPE, &A.type);
2438 glGetIntegerv (GL_TEXTURE_COORD_ARRAY_STRIDE, &A.stride);
2439 glGetPointerv (GL_TEXTURE_COORD_ARRAY_POINTER, &A.data);
2440 A.bytes = count * A.stride;
2441 dump_array_data (&A, count, "direct", "texture", 0);
2443 if (jwzgles_glIsEnabled (GL_COLOR_ARRAY))
2445 glGetIntegerv (GL_COLOR_ARRAY_BUFFER_BINDING, &A.binding);
2446 glGetIntegerv (GL_COLOR_ARRAY_SIZE, &A.size);
2447 glGetIntegerv (GL_COLOR_ARRAY_TYPE, &A.type);
2448 glGetIntegerv (GL_COLOR_ARRAY_STRIDE, &A.stride);
2449 glGetPointerv (GL_COLOR_ARRAY_POINTER, &A.data);
2450 A.bytes = count * A.stride;
2451 dump_array_data (&A, count, "direct", "color ", 0);
2459 copy_array_data (draw_array *A, int count, const char *name)
2461 /* Instead of just memcopy'ing the whole array and obeying its previous
2462 'stride' value, we make up a more compact array. This is because if
2463 the same array data is being used with multiple component types,
2464 e.g. with glInterleavedArrays, we don't want to copy all of the
2465 data multiple times.
2467 int stride2, bytes, i, j;
2471 const unsigned char *IB;
2474 if (((unsigned long) A->data) < 0xFFFF)
2476 Assert (0, "buffer data not a pointer");
2480 Assert (A->size >= 2 && A->size <= 4, "bogus array size");
2483 case GL_FLOAT: stride2 = A->size * sizeof(GLfloat); break;
2484 case GL_UNSIGNED_BYTE: stride2 = A->size; break;
2485 default: Assert (0, "bogus array type"); break;
2488 bytes = count * stride2;
2489 Assert (bytes > 0, "bogus array count or stride");
2490 Assert (A->data, "missing array data");
2491 data2 = (void *) malloc (bytes);
2492 Assert (data2, "out of memory");
2494 IB = (const unsigned char *) A->data;
2495 OB = (unsigned char *) data2;
2496 IF = (const GLfloat *) A->data;
2497 OF = (GLfloat *) data2;
2501 for (i = 0; i < count; i++)
2503 for (j = 0; j < A->size; j++)
2505 IF = (const GLfloat *) (((const unsigned char *) IF) + A->stride);
2508 case GL_UNSIGNED_BYTE:
2509 for (i = 0; i < count; i++)
2511 for (j = 0; j < A->size; j++)
2517 Assert (0, "bogus array type");
2523 A->stride = stride2;
2526 dump_array_data (A, count, "saved", name, 0);
2532 restore_arrays (list_fn *F, int count)
2535 draw_array *A = F->arrays;
2536 Assert (A, "missing array");
2538 for (i = 0; i < 4; i++)
2540 const char *name = 0;
2545 Assert ((A[i].binding || A[i].data),
2546 "array has neither buffer binding nor data");
2548 glBindBuffer (GL_ARRAY_BUFFER, A[i].binding);
2549 CHECK("glBindBuffer");
2552 case 0: glVertexPointer (A[i].size, A[i].type, A[i].stride, A[i].data);
2554 CHECK("glVertexPointer");
2556 case 1: glNormalPointer ( A[i].type, A[i].stride, A[i].data);
2558 CHECK("glNormalPointer");
2560 case 2: glTexCoordPointer(A[i].size, A[i].type, A[i].stride, A[i].data);
2562 CHECK("glTexCoordPointer");
2564 case 3: glColorPointer (A[i].size, A[i].type, A[i].stride, A[i].data);
2566 CHECK("glColorPointer");
2568 default: Assert (0, "wat"); break;
2572 dump_array_data (&A[i], count, "restored", name, 0);
2576 glBindBuffer (GL_ARRAY_BUFFER, 0); /* Keep out of others' hands */
2581 jwzgles_glDrawArrays (GLuint mode, GLuint first, GLuint count)
2583 /* If we are auto-generating texture coordinates, do that now, after
2584 the vertex array was installed, but before drawing, This happens
2585 when recording into a list, or in direct mode. It must happen
2586 before calling optimize_arrays() from glEndList().
2588 if (! state->replaying_list &&
2589 ((state->compiling_list ? state->list_enabled : state->enabled)
2590 & (ISENABLED_TEXTURE_GEN_S | ISENABLED_TEXTURE_GEN_T |
2591 ISENABLED_TEXTURE_GEN_R | ISENABLED_TEXTURE_GEN_Q)))
2592 generate_texture_coords (first, count);
2594 if (state->compiling_list)
2600 list_push ("glDrawArrays", (list_fn_cb) &jwzgles_glDrawArrays,
2606 if (! state->replaying_list) {
2607 LOG4("direct %-12s %d %d %d", "glDrawArrays", mode, first, count);
2608 dump_direct_array_data (first + count);
2611 glDrawArrays (mode, first, count); /* the real one */
2612 CHECK("glDrawArrays");
2618 jwzgles_glInterleavedArrays (GLenum format, GLsizei stride, const void *data)
2620 /* We can implement this by calling the various *Pointer functions
2621 with offsets into the same data, taking advantage of stride.
2623 const unsigned char *c = (const unsigned char *) data;
2625 # define F sizeof(GLfloat)
2627 Assert (!state->compiling_verts,
2628 "glInterleavedArrays not allowed inside glBegin");
2630 jwzgles_glEnableClientState (GL_VERTEX_ARRAY);
2632 if (!state->replaying_list)
2633 LOG4 ("%sglInterleavedArrays %s %d %lX",
2634 (state->compiling_list || state->replaying_list ? " " : ""),
2635 mode_desc (format), stride, (unsigned long) data);
2639 glVertexPointer (2, GL_FLOAT, stride, c);
2640 CHECK("glVertexPointer");
2641 if (!state->replaying_list)
2642 LOG3 ("%s -> glVertexPointer 2 FLOAT %d %lX",
2643 (state->compiling_list || state->replaying_list ? " " : ""),
2644 stride, (unsigned long) c);
2647 glVertexPointer (3, GL_FLOAT, stride, c);
2648 CHECK("glVertexPointer");
2649 if (!state->replaying_list)
2650 LOG3 ("%s -> glVertexPointer 3 FLOAT %d %lX",
2651 (state->compiling_list || state->replaying_list ? " " : ""),
2652 stride, (unsigned long) c);
2657 jwzgles_glEnableClientState (GL_COLOR_ARRAY);
2658 glColorPointer (4, GL_UNSIGNED_BYTE, stride, c);
2659 CHECK("glColorPointer");
2660 c += 4*B; /* #### might be incorrect float-aligned address */
2661 glVertexPointer (2, GL_FLOAT, stride, c);
2666 jwzgles_glEnableClientState (GL_COLOR_ARRAY);
2667 glColorPointer (4, GL_UNSIGNED_BYTE, stride, c);
2668 CHECK("glColorPointer");
2670 glVertexPointer (3, GL_FLOAT, stride, c);
2671 CHECK("glVertexPointer");
2676 jwzgles_glEnableClientState (GL_COLOR_ARRAY);
2677 glColorPointer (3, GL_FLOAT, stride, c);
2678 CHECK("glColorPointer");
2680 glVertexPointer (3, GL_FLOAT, stride, c);
2681 CHECK("glVertexPointer");
2686 jwzgles_glEnableClientState (GL_NORMAL_ARRAY);
2687 glNormalPointer (GL_FLOAT, stride, c);
2688 CHECK("glNormalPointer");
2689 if (!state->replaying_list)
2690 LOG3 ("%s -> glNormalPointer FLOAT %d %lX",
2691 (state->compiling_list || state->replaying_list ? " " : ""),
2692 stride, (unsigned long) c);
2694 glVertexPointer (3, GL_FLOAT, stride, c);
2695 CHECK("glVertexPointer");
2696 if (!state->replaying_list)
2697 LOG3 ("%s -> glVertexPointer 3 FLOAT %d %lX",
2698 (state->compiling_list || state->replaying_list ? " " : ""),
2699 stride, (unsigned long) c);
2701 case GL_C4F_N3F_V3F:
2703 stride = 4*F + 3*F + 3*F;
2704 jwzgles_glEnableClientState (GL_COLOR_ARRAY);
2705 glColorPointer (4, GL_FLOAT, stride, c);
2706 CHECK("glColorPointer");
2708 jwzgles_glEnableClientState (GL_NORMAL_ARRAY);
2709 glNormalPointer (GL_FLOAT, stride, c);
2710 CHECK("glNormalPointer");
2712 glVertexPointer (3, GL_FLOAT, stride, c);
2713 CHECK("glVertexPointer");
2718 jwzgles_glEnableClientState (GL_TEXTURE_COORD_ARRAY);
2719 glTexCoordPointer (2, GL_FLOAT, stride, c);
2720 CHECK("glTexCoordPointer");
2722 glVertexPointer (3, GL_FLOAT, stride, c);
2723 CHECK("glVertexPointer");
2728 jwzgles_glEnableClientState (GL_TEXTURE_COORD_ARRAY);
2729 glTexCoordPointer (4, GL_FLOAT, stride, c);
2730 CHECK("glTexCoordPointer");
2732 glVertexPointer (4, GL_FLOAT, stride, c);
2733 CHECK("glVertexPointer");
2735 case GL_T2F_C4UB_V3F:
2737 stride = 2*F + 4*B + 3*F;
2738 jwzgles_glEnableClientState (GL_TEXTURE_COORD_ARRAY);
2739 glTexCoordPointer (2, GL_FLOAT, stride, c);
2740 CHECK("glTexCoordPointer");
2742 jwzgles_glEnableClientState (GL_COLOR_ARRAY);
2743 glColorPointer (4, GL_UNSIGNED_BYTE, stride, c);
2744 CHECK("glColorPointer");
2746 glVertexPointer (3, GL_FLOAT, stride, c);
2747 CHECK("glVertexPointer");
2749 case GL_T2F_C3F_V3F:
2751 stride = 2*F + 3*F + 3*F;
2752 jwzgles_glEnableClientState (GL_TEXTURE_COORD_ARRAY);
2753 glTexCoordPointer (2, GL_FLOAT, stride, c);
2754 CHECK("glTexCoordPointer");
2756 jwzgles_glEnableClientState (GL_COLOR_ARRAY);
2757 glColorPointer (3, GL_FLOAT, stride, c);
2758 CHECK("glColorPointer");
2760 glVertexPointer (3, GL_FLOAT, stride, c);
2761 CHECK("glVertexPointer");
2763 case GL_T2F_N3F_V3F:
2765 stride = 2*F + 3*F + 3*F;
2766 jwzgles_glEnableClientState (GL_TEXTURE_COORD_ARRAY);
2767 glTexCoordPointer (2, GL_FLOAT, stride, c);
2768 CHECK("glTexCoordPointer");
2770 jwzgles_glEnableClientState (GL_NORMAL_ARRAY);
2771 glNormalPointer (GL_FLOAT, stride, c);
2772 CHECK("glNormalPointer");
2774 glVertexPointer (3, GL_FLOAT, stride, c);
2775 CHECK("glVertexPointer");
2777 case GL_T2F_C4F_N3F_V3F:
2779 stride = 2*F + 4*F + 3*F + 3*F;
2780 jwzgles_glEnableClientState (GL_TEXTURE_COORD_ARRAY);
2781 glTexCoordPointer (2, GL_FLOAT, stride, c);
2782 CHECK("glTexCoordPointer");
2784 jwzgles_glEnableClientState (GL_COLOR_ARRAY);
2785 glColorPointer (3, GL_FLOAT, stride, c);
2786 CHECK("glColorPointer");
2788 jwzgles_glEnableClientState (GL_NORMAL_ARRAY);
2789 glNormalPointer (GL_FLOAT, stride, c);
2790 CHECK("glNormalPointer");
2792 glVertexPointer (3, GL_FLOAT, stride, c);
2793 CHECK("glVertexPointer");
2795 case GL_T4F_C4F_N3F_V4F:
2797 stride = 4*F + 4*F + 3*F + 4*F;
2798 jwzgles_glEnableClientState (GL_TEXTURE_COORD_ARRAY);
2799 glTexCoordPointer (4, GL_FLOAT, stride, c);
2800 CHECK("glTexCoordPointer");
2802 jwzgles_glEnableClientState (GL_COLOR_ARRAY);
2803 glColorPointer (4, GL_FLOAT, stride, c);
2804 CHECK("glColorPointer");
2806 jwzgles_glEnableClientState (GL_NORMAL_ARRAY);
2807 glNormalPointer (GL_FLOAT, stride, c);
2808 CHECK("glNormalPointer");
2810 glVertexPointer (3, GL_FLOAT, stride, c);
2811 CHECK("glVertexPointer");
2814 Assert (0, "glInterleavedArrays: bogus format");
2825 jwzgles_glMultMatrixf (const GLfloat *m)
2827 Assert (!state->compiling_verts,
2828 "glMultMatrixf not allowed inside glBegin");
2829 if (state->compiling_list)
2833 for (i = 0; i < countof(vv); i++)
2835 list_push ("glMultMatrixf", (list_fn_cb) &jwzgles_glMultMatrixf,
2840 if (! state->replaying_list)
2841 LOG1 ("direct %-12s", "glMultMatrixf");
2842 glMultMatrixf (m); /* the real one */
2843 CHECK("glMultMatrixf");
2849 jwzgles_glClearIndex(GLfloat c)
2851 /* Does GLES even do indexed color? */
2852 Assert (0, "glClearIndex unimplemented");
2857 jwzgles_glBitmap (GLsizei width, GLsizei height, GLfloat xorig, GLfloat yorig,
2858 GLfloat xmove, GLfloat ymove, const GLubyte *bitmap)
2860 Assert (0, "glBitmap unimplemented");
2864 jwzgles_glPushAttrib(int flags)
2866 Assert (0, "glPushAttrib unimplemented");
2870 jwzgles_glPopAttrib(void)
2872 Assert (0, "glPopAttrib unimplemented");
2876 /* These are needed for object hit detection in pinion.
2877 Might need to rewrite that code entirely. Punt for now.
2880 jwzgles_glInitNames (void)
2882 /* Assert (0, "glInitNames unimplemented");*/
2886 jwzgles_glPushName (GLuint name)
2888 /* Assert (0, "glPushName unimplemented");*/
2892 jwzgles_glPopName (void)
2894 /* Assert (0, "glPopName unimplemented");*/
2899 jwzgles_glRenderMode (GLuint mode)
2901 /* Assert (0, "glRenderMode unimplemented");*/
2906 jwzgles_glSelectBuffer (GLsizei size, GLuint *buf)
2908 /* Assert (0, "glSelectBuffer unimplemented");*/
2913 jwzgles_glGenTextures (GLuint n, GLuint *ret)
2915 Assert (!state->compiling_verts,
2916 "glGenTextures not allowed inside glBegin");
2917 /* technically legal, but stupid! */
2918 Assert (!state->compiling_list,
2919 "glGenTextures not allowed inside glNewList");
2920 if (! state->replaying_list)
2921 LOG1 ("direct %-12s", "glGenTextures");
2922 glGenTextures (n, ret); /* the real one */
2923 CHECK("glGenTextures");
2927 /* return the next larger power of 2. */
2932 while (i < value) i <<= 1;
2937 jwzgles_glTexImage1D (GLenum target, GLint level,
2938 GLint internalFormat,
2939 GLsizei width, GLint border,
2940 GLenum format, GLenum type,
2943 Assert (!state->compiling_verts, "glTexImage1D not allowed inside glBegin");
2944 /* technically legal, but stupid! */
2945 Assert (!state->compiling_list, "glTexImage1D inside glNewList");
2946 Assert (width == to_pow2(width), "width must be a power of 2");
2948 if (target == GL_TEXTURE_1D) target = GL_TEXTURE_2D;
2949 jwzgles_glTexImage2D (target, level, internalFormat, width, 1,
2950 border, format, type, data);
2954 jwzgles_glTexImage2D (GLenum target,
2956 GLint internalFormat,
2964 GLvoid *d2 = (GLvoid *) data;
2965 Assert (!state->compiling_verts, "glTexImage2D not allowed inside glBegin");
2966 Assert (!state->compiling_list, /* technically legal, but stupid! */
2967 "glTexImage2D not allowed inside glNewList");
2969 Assert (width == to_pow2(width), "width must be a power of 2");
2970 Assert (height == to_pow2(height), "height must be a power of 2");
2972 /* OpenGLES no longer supports "4" as a synonym for "RGBA". */
2973 switch (internalFormat) {
2974 case 1: internalFormat = GL_LUMINANCE; break;
2975 case 2: internalFormat = GL_LUMINANCE_ALPHA; break;
2976 case 3: internalFormat = GL_RGB; break;
2977 case 4: internalFormat = GL_RGBA; break;
2980 /* GLES does not let us omit the data pointer to create a blank texture. */
2983 d2 = (GLvoid *) calloc (1, width * height * sizeof(GLfloat) * 4);
2984 Assert (d2, "out of memory");
2987 if (internalFormat == GL_RGB && format == GL_RGBA)
2988 internalFormat = GL_RGBA; /* WTF */
2989 if (type == GL_UNSIGNED_INT_8_8_8_8_REV)
2990 type = GL_UNSIGNED_BYTE;
2992 if (! state->replaying_list)
2993 LOG10 ("direct %-12s %s %d %s %d %d %d %s %s 0x%lX", "glTexImage2D",
2994 mode_desc(target), level, mode_desc(internalFormat),
2995 width, height, border, mode_desc(format), mode_desc(type),
2996 (unsigned long) d2);
2997 glTexImage2D (target, level, internalFormat, width, height, border,
2998 format, type, d2); /* the real one */
2999 CHECK("glTexImage2D");
3001 if (d2 != data) free (d2);
3005 jwzgles_glTexSubImage2D (GLenum target, GLint level,
3006 GLint xoffset, GLint yoffset,
3007 GLsizei width, GLsizei height,
3008 GLenum format, GLenum type,
3009 const GLvoid *pixels)
3011 Assert (!state->compiling_verts,
3012 "glTexSubImage2D not allowed inside glBegin");
3013 Assert (!state->compiling_list, /* technically legal, but stupid! */
3014 "glTexSubImage2D not allowed inside glNewList");
3016 if (! state->replaying_list)
3017 LOG10 ("direct %-12s %s %d %d %d %d %d %s %s 0x%lX", "glTexSubImage2D",
3018 mode_desc(target), level, xoffset, yoffset, width, height,
3019 mode_desc (format), mode_desc (type), (unsigned long) pixels);
3020 glTexSubImage2D (target, level, xoffset, yoffset, width, height,
3021 format, type, pixels); /* the real one */
3022 CHECK("glTexSubImage2D");
3026 jwzgles_glCopyTexImage2D (GLenum target, GLint level, GLenum internalformat,
3027 GLint x, GLint y, GLsizei width, GLsizei height,
3030 Assert (!state->compiling_verts,
3031 "glCopyTexImage2D not allowed inside glBegin");
3032 Assert (!state->compiling_list, /* technically legal, but stupid! */
3033 "glCopyTexImage2D not allowed inside glNewList");
3034 if (! state->replaying_list)
3035 LOG9 ("direct %-12s %s %d %s %d %d %d %d %d", "glCopyTexImage2D",
3036 mode_desc(target), level, mode_desc(internalformat),
3037 x, y, width, height, border);
3038 glCopyTexImage2D (target, level, internalformat, x, y, width, height,
3039 border); /* the real one */
3040 CHECK("glCopyTexImage2D");
3044 /* OpenGLES doesn't have auto texture-generation at all!
3045 "Oh, just rewrite that code to use GPU shaders", they say.
3046 How fucking convenient.
3049 jwzgles_glTexGenfv (GLenum coord, GLenum pname, const GLfloat *params)
3053 if (pname == GL_TEXTURE_GEN_MODE)
3054 LOG5 ("%sdirect %-12s %s %s %s",
3055 (state->compiling_list || state->replaying_list ? " " : ""),
3057 mode_desc(coord), mode_desc(pname), mode_desc(params[0]));
3059 LOG8 ("%sdirect %-12s %s %s %3.1f %3.1f %3.1f %3.1f",
3060 (state->compiling_list || state->replaying_list ? " " : ""),
3062 mode_desc(coord), mode_desc(pname),
3063 params[0], params[1], params[2], params[3]);
3066 case GL_S: s = &state->s; break;
3067 case GL_T: s = &state->t; break;
3068 case GL_R: s = &state->r; break;
3069 case GL_Q: s = &state->q; break;
3070 default: Assert (0, "glGetTexGenfv: unknown coord"); break;
3074 case GL_TEXTURE_GEN_MODE: s->mode = params[0]; break;
3075 case GL_OBJECT_PLANE: memcpy (s->obj, params, sizeof(s->obj)); break;
3076 case GL_EYE_PLANE: memcpy (s->eye, params, sizeof(s->eye)); break;
3077 default: Assert (0, "glTexGenfv: unknown pname"); break;
3082 jwzgles_glTexGeni (GLenum coord, GLenum pname, GLint param)
3085 jwzgles_glTexGenfv (coord, pname, &v);
3089 jwzgles_glGetTexGenfv (GLenum coord, GLenum pname, GLfloat *params)
3094 case GL_S: s = &state->s; break;
3095 case GL_T: s = &state->t; break;
3096 case GL_R: s = &state->r; break;
3097 case GL_Q: s = &state->q; break;
3098 default: Assert (0, "glGetTexGenfv: unknown coord"); break;
3102 case GL_TEXTURE_GEN_MODE: params[0] = s->mode; break;
3103 case GL_OBJECT_PLANE: memcpy (params, s->obj, sizeof(s->obj)); break;
3104 case GL_EYE_PLANE: memcpy (params, s->eye, sizeof(s->eye)); break;
3105 default: Assert (0, "glGetTexGenfv: unknown pname"); break;
3108 if (pname == GL_TEXTURE_GEN_MODE)
3109 LOG5 ("%sdirect %-12s %s %s -> %s",
3110 (state->compiling_list || state->replaying_list ? " " : ""),
3112 mode_desc(coord), mode_desc(pname), mode_desc(params[0]));
3114 LOG8 ("%sdirect %-12s %s %s -> %3.1f %3.1f %3.1f %3.1f",
3115 (state->compiling_list || state->replaying_list ? " " : ""),
3117 mode_desc(coord), mode_desc(pname),
3118 params[0], params[1], params[2], params[3]);
3123 dot_product (int rank, GLfloat *a, GLfloat *b)
3125 /* A dot B => (A[1] * B[1]) + ... + (A[n] * B[n]) */
3128 for (i = 0; i < rank; i++)
3135 /* Compute the texture coordinates of the prevailing list of verts as per
3136 http://www.opengl.org/wiki/Mathematics_of_glTexGen
3139 generate_texture_coords (GLuint first, GLuint count)
3141 GLfloat *tex_out, *tex_array;
3144 draw_array A = { 0, };
3147 struct { GLuint which, flag, mode; GLfloat plane[4]; } tg[4] = {
3148 { GL_S, ISENABLED_TEXTURE_GEN_S, 0, { 0, } },
3149 { GL_T, ISENABLED_TEXTURE_GEN_T, 0, { 0, } },
3150 { GL_R, ISENABLED_TEXTURE_GEN_R, 0, { 0, } },
3151 { GL_Q, ISENABLED_TEXTURE_GEN_Q, 0, { 0, }}};
3155 /* Read the texture plane configs that were stored with glTexGen.
3157 for (i = 0; i < countof(tg); i++)
3160 if (! ((state->compiling_list ? state->list_enabled : state->enabled)
3163 jwzgles_glGetTexGenfv (tg[i].which, GL_TEXTURE_GEN_MODE, &mode);
3164 jwzgles_glGetTexGenfv (tg[i].which, GL_OBJECT_PLANE, tg[i].plane);
3169 if (tcoords == 0) return; /* Nothing to do! */
3172 /* Make the array to store our texture coords in. */
3174 tex_stride = tcoords * sizeof(GLfloat);
3175 tex_array = (GLfloat *) calloc (first + count, tex_stride);
3176 tex_out = tex_array;
3179 /* Read the prevailing vertex array, that was stored with
3180 glVertexPointer or glInterleavedArrays.
3182 glGetIntegerv (GL_VERTEX_ARRAY_BUFFER_BINDING, &A.binding);
3183 glGetIntegerv (GL_VERTEX_ARRAY_SIZE, &A.size);
3184 glGetIntegerv (GL_VERTEX_ARRAY_TYPE, &A.type);
3185 glGetIntegerv (GL_VERTEX_ARRAY_STRIDE, &A.stride);
3186 glGetPointerv (GL_VERTEX_ARRAY_POINTER, &A.data);
3187 A.bytes = count * A.stride;
3189 verts_in = (char *) A.data;
3191 /* Iterate over each vertex we're drawing.
3192 We just skip the ones < start, but the tex array has
3193 left room for zeroes there anyway.
3195 for (i = first; i < first + count; i++)
3197 GLfloat vert[4] = { 0, };
3200 /* Extract this vertex into `vert' as a float, whatever its type was. */
3201 for (j = 0; j < A.size; j++)
3204 case GL_SHORT: vert[j] = ((GLshort *) verts_in)[j]; break;
3205 case GL_INT: vert[j] = ((GLint *) verts_in)[j]; break;
3206 case GL_FLOAT: vert[j] = ((GLfloat *) verts_in)[j]; break;
3207 case GL_DOUBLE: vert[j] = ((GLdouble *) verts_in)[j]; break;
3208 default: Assert (0, "unknown vertex type"); break;
3212 /* Compute the texture coordinate for this vertex.
3213 For GL_OBJECT_LINEAR, these coordinates are static, and can go
3214 into the display list. But for GL_EYE_LINEAR, GL_SPHERE_MAP and
3215 GL_REFLECTION_MAP, they depend on the prevailing ModelView matrix,
3216 and so need to be computed afresh each time glDrawArrays is called.
3217 Unfortunately, our verts and norms are gone by then, dumped down
3218 into the VBO and discarded from CPU RAM. Bleh.
3220 for (j = 0, k = 0; j < countof(tg); j++)
3222 if (! ((state->compiling_list ? state->list_enabled : state->enabled)
3225 switch (tg[j].mode) {
3226 case GL_OBJECT_LINEAR:
3227 tex_out[k] = dot_product (4, vert, tg[j].plane);
3230 Assert (0, "unimplemented texture mode");
3236 /* fprintf (stderr, "%4d: V %-5.1f %-5.1f %-5.1f T %-5.1f %-5.1f\n",
3237 i, vert[0], vert[1], vert[2], tex_out[0], tex_out[1]); */
3239 /* Move verts_in and tex_out forward to the next vertex by stride. */
3240 verts_in += A.stride;
3241 tex_out = (GLfloat *) (((char *) tex_out) + tex_stride);
3244 jwzgles_glEnableClientState (GL_TEXTURE_COORD_ARRAY);
3245 jwzgles_glTexCoordPointer (tcoords, GL_FLOAT, tex_stride,
3246 (GLvoid *) tex_array);
3252 jwzgles_gluBuild2DMipmaps (GLenum target,
3253 GLint internalFormat,
3260 /* Not really bothering with mipmapping; only making one level.
3261 Note that this required a corresponding hack in glTexParameterf().
3264 int w2 = to_pow2(width);
3265 int h2 = to_pow2(height);
3267 void *d2 = (void *) data;
3269 /* OpenGLES no longer supports "4" as a synonym for "RGBA". */
3270 switch (internalFormat) {
3271 case 1: internalFormat = GL_LUMINANCE; break;
3272 case 2: internalFormat = GL_LUMINANCE_ALPHA; break;
3273 case 3: internalFormat = GL_RGB; break;
3274 case 4: internalFormat = GL_RGBA; break;
3277 /* if (w2 < h2) w2 = h2;
3278 if (h2 < w2) h2 = w2;*/
3280 if (w2 != width || h2 != height)
3282 /* Scale up the image bits to fit the power-of-2 texture.
3283 We have to do this because the mipmap API assumes that
3284 the texture bits go to texture coordinates 1.0 x 1.0.
3285 This could be more efficient, but it doesn't happen often.
3287 int istride = (format == GL_RGBA ? 4 : 3);
3289 int ibpl = istride * width;
3290 int obpl = ostride * w2;
3292 const unsigned char *in = (unsigned char *) data;
3293 unsigned char *out = (void *) malloc (h2 * obpl);
3294 Assert (out, "out of memory");
3297 for (oy = 0; oy < h2; oy++)
3299 int iy = oy * height / h2;
3300 const unsigned char *iline = in + (iy * ibpl);
3301 unsigned char *oline = out + (oy * obpl);
3303 for (ox = 0; ox < w2; ox++)
3305 int ix = ox * width / w2;
3306 const unsigned char *i = iline + (ix * istride);
3307 unsigned char *o = oline + (ox * ostride);
3308 *o++ = *i++; /* R */
3309 *o++ = *i++; /* G */
3310 *o++ = *i++; /* B */
3311 *o++ = (istride == 4 ? *i : 0xFF); /* A */
3316 internalFormat = GL_RGBA;
3320 jwzgles_glTexImage2D (target, 0, internalFormat, w2, h2, 0,
3322 if (d2 != data) free (d2);
3329 jwzgles_glRectf (GLfloat x1, GLfloat y1, GLfloat x2, GLfloat y2)
3331 jwzgles_glBegin (GL_POLYGON);
3332 jwzgles_glVertex2f (x1, y1);
3333 jwzgles_glVertex2f (x2, y1);
3334 jwzgles_glVertex2f (x2, y2);
3335 jwzgles_glVertex2f (x1, y2);
3340 jwzgles_glRecti (GLint x1, GLint y1, GLint x2, GLint y2)
3342 jwzgles_glRectf (x1, y1, x2, y2);
3346 jwzgles_glClearDepth (GLfloat d)
3348 /* Not sure what to do here */
3349 Assert (d == 1.0, "glClearDepth unimplemented");
3353 /* When in immediate mode, we store a bit into state->enabled, and also
3354 call the real glEnable() / glDisable().
3356 When recording a list, we store a bit into state->list_enabled instead,
3357 so that we can see what the prevailing enablement state will be when
3360 set: 1 = set, -1 = clear, 0 = query.
3363 enable_disable (GLuint bit, int set)
3365 int result = (set > 0);
3368 unsigned long flag = 0;
3371 case GL_TEXTURE_1D: /* We implement 1D textures as 2D textures. */
3372 case GL_TEXTURE_2D: flag = ISENABLED_TEXTURE_2D; break;
3373 case GL_TEXTURE_GEN_S: flag = ISENABLED_TEXTURE_GEN_S; omitp = 1; break;
3374 case GL_TEXTURE_GEN_T: flag = ISENABLED_TEXTURE_GEN_T; omitp = 1; break;
3375 case GL_TEXTURE_GEN_R: flag = ISENABLED_TEXTURE_GEN_R; omitp = 1; break;
3376 case GL_TEXTURE_GEN_Q: flag = ISENABLED_TEXTURE_GEN_Q; omitp = 1; break;
3377 case GL_LIGHTING: flag = ISENABLED_LIGHTING; break;
3378 case GL_BLEND: flag = ISENABLED_BLEND; break;
3379 case GL_DEPTH_TEST: flag = ISENABLED_DEPTH_TEST; break;
3380 case GL_ALPHA_TEST: flag = ISENABLED_ALPHA_TEST; break;
3381 case GL_CULL_FACE: flag = ISENABLED_CULL_FACE; break;
3382 case GL_NORMALIZE: flag = ISENABLED_NORMALIZE; break;
3383 case GL_FOG: flag = ISENABLED_FOG; break;
3384 case GL_COLOR_MATERIAL: flag = ISENABLED_COLMAT; break;
3386 /* Maybe technically these only work with glEnableClientState,
3387 but we treat that as synonymous with glEnable. */
3388 case GL_VERTEX_ARRAY: flag = ISENABLED_VERT_ARRAY; csp = 1; break;
3389 case GL_NORMAL_ARRAY: flag = ISENABLED_NORM_ARRAY; csp = 1; break;
3390 case GL_COLOR_ARRAY: flag = ISENABLED_COLOR_ARRAY; csp = 1; break;
3391 case GL_TEXTURE_COORD_ARRAY: flag = ISENABLED_TEX_ARRAY; csp = 1; break;
3394 Assert (set != 0, "glIsEnabled unimplemented bit");
3398 if (set) /* setting or unsetting, not querying */
3400 const char *fns[4] = { "glEnable", "glDisable",
3401 "glEnableClientState", "glDisableClientState" };
3402 list_fn_cb fs[4] = { (list_fn_cb) &jwzgles_glEnable,
3403 (list_fn_cb) &jwzgles_glDisable,
3404 (list_fn_cb) &jwzgles_glEnableClientState,
3405 (list_fn_cb) &jwzgles_glDisableClientState };
3406 const char *fn = fns[(csp ? 2 : 0) + (set < 0 ? 1 : 0)];
3407 list_fn_cb f = fs[(csp ? 2 : 0) + (set < 0 ? 1 : 0)];
3409 Assert (!state->compiling_verts,
3410 "glEnable/glDisable not allowed inside glBegin");
3412 if (state->compiling_list)
3416 list_push (fn, f,PROTO_I, vv);
3419 if (! state->replaying_list &&
3420 ! state->compiling_list)
3421 LOG2 ("direct %-12s %s", fn, mode_desc(bit));
3423 if (csp && !state->compiling_verts)
3427 case GL_NORMAL_ARRAY: state->set.ncount += 2; break;
3428 case GL_TEXTURE_COORD_ARRAY: state->set.tcount += 2; break;
3429 case GL_COLOR_ARRAY: state->set.ccount += 2; break;
3434 case GL_NORMAL_ARRAY: state->set.ncount = 0; break;
3435 case GL_TEXTURE_COORD_ARRAY: state->set.tcount = 0; break;
3436 case GL_COLOR_ARRAY: state->set.ccount = 0; break;
3441 if (omitp || state->compiling_list)
3443 else if (set > 0 && csp)
3444 glEnableClientState (bit); /* the real one */
3445 else if (set < 0 && csp)
3446 glDisableClientState (bit); /* the real one */
3448 glEnable (bit); /* the real one */
3450 glDisable (bit); /* the real one */
3455 /* Store the bit in our state as well, or query it.
3459 unsigned long *enabled = (state->compiling_list
3460 ? &state->list_enabled
3467 result = !!(*enabled & flag);
3475 jwzgles_glEnable (GLuint bit)
3477 enable_disable (bit, 1);
3481 jwzgles_glDisable (GLuint bit)
3483 enable_disable (bit, -1);
3487 jwzgles_glIsEnabled (GLuint bit)
3489 return enable_disable (bit, 0);
3493 jwzgles_glEnableClientState (GLuint cap)
3495 enable_disable (cap, 1);
3499 jwzgles_glDisableClientState (GLuint cap)
3501 enable_disable (cap, -1);
3506 /* The spec says that OpenGLES 1.x doesn't implement glGetFloatv.
3507 Were this true, it would suck, for it would mean that there was no
3508 way to retrieve the prevailing matrixes. To implement this, we'd
3509 have to keep track of them all on the client side by combining in
3510 all the actions of glMultMatrixf, glRotatef, etc.
3512 However, Apple's iOS OpenGLES *does* provide glGetFloatv!
3515 jwzgles_glGetFloatv (GLenum pname, GLfloat *params)
3517 if (! state->replaying_list)
3518 LOG2 ("direct %-12s %s", "glGetFloatv", mode_desc(pname));
3519 glGetFloatv (pname, params); /* the real one */
3520 CHECK("glGetFloatv");
3524 /* Likewise: not supposed to be there, but it is. */
3526 jwzgles_glGetPointerv (GLenum pname, GLvoid *params)
3528 if (! state->replaying_list)
3529 LOG2 ("direct %-12s %s", "glGetPointerv", mode_desc(pname));
3530 glGetPointerv (pname, params); /* the real one */
3531 CHECK("glGetPointerv");
3535 /* How many cells are written into the *params array.
3536 We need to know this to avoid smashing the caller's stack
3537 if they asked for a single-value parameter.
3540 glGet_ret_count (GLenum pname)
3543 /*case GL_COLOR_MATRIX: */
3544 case GL_MODELVIEW_MATRIX:
3545 case GL_PROJECTION_MATRIX:
3546 case GL_TEXTURE_MATRIX:
3547 /*case GL_TRANSPOSE_COLOR_MATRIX: */
3548 /*case GL_TRANSPOSE_MODELVIEW_MATRIX: */
3549 /*case GL_TRANSPOSE_PROJECTION_MATRIX: */
3550 /*case GL_TRANSPOSE_TEXTURE_MATRIX: */
3552 /*case GL_ACCUM_CLEAR_VALUE: */
3553 /*case GL_BLEND_COLOR: */
3554 case GL_COLOR_CLEAR_VALUE:
3555 case GL_COLOR_WRITEMASK:
3556 case GL_CURRENT_COLOR:
3557 /*case GL_CURRENT_RASTER_COLOR: */
3558 /*case GL_CURRENT_RASTER_POSITION: */
3559 /*case GL_CURRENT_RASTER_SECONDARY_COLOR: */
3560 /*case GL_CURRENT_RASTER_TEXTURE_COORDS: */
3561 /*case GL_CURRENT_SECONDARY_COLOR: */
3562 case GL_CURRENT_TEXTURE_COORDS:
3564 case GL_LIGHT_MODEL_AMBIENT:
3565 /*case GL_MAP2_GRID_DOMAIN: */
3566 case GL_SCISSOR_BOX:
3569 case GL_CURRENT_NORMAL:
3570 case GL_POINT_DISTANCE_ATTENUATION:
3572 case GL_ALIASED_LINE_WIDTH_RANGE:
3573 case GL_ALIASED_POINT_SIZE_RANGE:
3574 case GL_DEPTH_RANGE:
3575 /*case GL_LINE_WIDTH_RANGE: */
3576 /*case GL_MAP1_GRID_DOMAIN: */
3577 /*case GL_MAP2_GRID_SEGMENTS: */
3578 case GL_MAX_VIEWPORT_DIMS:
3579 /*case GL_POINT_SIZE_RANGE: */
3580 case GL_POLYGON_MODE:
3581 case GL_SMOOTH_LINE_WIDTH_RANGE:
3582 case GL_SMOOTH_POINT_SIZE_RANGE:
3591 jwzgles_glGetDoublev (GLenum pname, GLdouble *params)
3594 int i, j = glGet_ret_count (pname);
3595 jwzgles_glGetFloatv (pname, m);
3596 for (i = 0; i < j; i++)
3602 jwzgles_glGetIntegerv (GLenum pname, GLint *params)
3605 int i, j = glGet_ret_count (pname);
3606 jwzgles_glGetFloatv (pname, m);
3607 for (i = 0; i < j; i++)
3613 jwzgles_glGetBooleanv (GLenum pname, GLboolean *params)
3616 int i, j = glGet_ret_count (pname);
3617 jwzgles_glGetFloatv (pname, m);
3618 for (i = 0; i < j; i++)
3619 params[i] = (m[i] != 0.0);
3624 jwzgles_gluErrorString (GLenum error)
3627 sprintf (s, "0x%lX", (unsigned long) error);
3632 /* These four *Pointer calls (plus glBindBuffer and glBufferData) can
3633 be included inside glNewList, but they actually execute immediately
3634 anyway, because their data is recorded in the list by the
3635 subsequently-recorded call to glDrawArrays. This is a little weird.
3638 jwzgles_glVertexPointer (GLuint size, GLuint type, GLuint stride,
3641 if (! state->replaying_list)
3642 LOG5 ("direct %-12s %d %s %d 0x%lX", "glVertexPointer",
3643 size, mode_desc(type), stride, (unsigned long) ptr);
3644 glVertexPointer (size, type, stride, ptr); /* the real one */
3645 CHECK("glVertexPointer");
3650 jwzgles_glNormalPointer (GLuint type, GLuint stride, const GLvoid *ptr)
3652 if (! state->replaying_list)
3653 LOG4 ("direct %-12s %s %d 0x%lX", "glNormalPointer",
3654 mode_desc(type), stride, (unsigned long) ptr);
3655 glNormalPointer (type, stride, ptr); /* the real one */
3656 CHECK("glNormalPointer");
3660 jwzgles_glColorPointer (GLuint size, GLuint type, GLuint stride,
3663 if (! state->replaying_list)
3664 LOG5 ("direct %-12s %d %s %d 0x%lX", "glColorPointer",
3665 size, mode_desc(type), stride, (unsigned long) ptr);
3666 glColorPointer (size, type, stride, ptr); /* the real one */
3667 CHECK("glColorPointer");
3671 jwzgles_glTexCoordPointer (GLuint size, GLuint type, GLuint stride,
3674 if (! state->replaying_list)
3675 LOG5 ("direct %-12s %d %s %d 0x%lX", "glTexCoordPointer",
3676 size, mode_desc(type), stride, (unsigned long) ptr);
3677 glTexCoordPointer (size, type, stride, ptr); /* the real one */
3678 CHECK("glTexCoordPointer");
3682 jwzgles_glBindBuffer (GLuint target, GLuint buffer)
3684 if (! state->replaying_list)
3685 LOG3 ("direct %-12s %s %d", "glBindBuffer", mode_desc(target), buffer);
3686 glBindBuffer (target, buffer); /* the real one */
3687 CHECK("glBindBuffer");
3691 jwzgles_glBufferData (GLenum target, GLsizeiptr size, const void *data,
3694 if (! state->replaying_list)
3695 LOG5 ("direct %-12s %s %ld 0x%lX %s", "glBufferData",
3696 mode_desc(target), size, (unsigned long) data, mode_desc(usage));
3697 glBufferData (target, size, data, usage); /* the real one */
3698 CHECK("glBufferData");
3703 jwzgles_glTexParameterf (GLuint target, GLuint pname, GLfloat param)
3705 Assert (!state->compiling_verts,
3706 "glTexParameterf not allowed inside glBegin");
3708 /* We don't *really* implement mipmaps, so just turn this off. */
3709 if (param == GL_LINEAR_MIPMAP_LINEAR) param = GL_LINEAR;
3710 if (param == GL_NEAREST_MIPMAP_LINEAR) param = GL_LINEAR;
3711 if (param == GL_LINEAR_MIPMAP_NEAREST) param = GL_NEAREST;
3712 if (param == GL_NEAREST_MIPMAP_NEAREST) param = GL_NEAREST;
3714 /* We implement 1D textures as 2D textures. */
3715 if (target == GL_TEXTURE_1D) target = GL_TEXTURE_2D;
3717 /* Apparently this is another invalid enum. Just ignore it. */
3718 if ((pname == GL_TEXTURE_WRAP_S || pname == GL_TEXTURE_WRAP_T) &&
3722 if (state->compiling_list)
3728 list_push ("glTexParameterf", (list_fn_cb) &jwzgles_glTexParameterf,
3733 if (! state->replaying_list)
3734 LOG4 ("direct %-12s %s %s %7.3f", "glTexParameterf",
3735 mode_desc(target), mode_desc(pname), param);
3736 glTexParameterf (target, pname, param); /* the real one */
3737 CHECK("glTexParameterf");
3742 jwzgles_glTexParameteri (GLuint target, GLuint pname, GLuint param)
3744 jwzgles_glTexParameterf (target, pname, param);
3749 jwzgles_glBindTexture (GLuint target, GLuint texture)
3751 Assert (!state->compiling_verts,
3752 "glBindTexture not allowed inside glBegin");
3754 /* We implement 1D textures as 2D textures. */
3755 if (target == GL_TEXTURE_1D) target = GL_TEXTURE_2D;
3757 if (state->compiling_list)
3762 list_push ("glBindTexture", (list_fn_cb) &jwzgles_glBindTexture,
3766 /* Do it immediately as well, for generate_texture_coords */
3769 if (! state->replaying_list)
3770 LOG3 ("direct %-12s %s %d", "glBindTexture",
3771 mode_desc(target), texture);
3772 glBindTexture (target, texture); /* the real one */
3773 CHECK("glBindTexture");
3779 /* Matrix functions, mostly cribbed from Mesa.
3783 jwzgles_glFrustum (GLfloat left, GLfloat right,
3784 GLfloat bottom, GLfloat top,
3785 GLfloat near, GLfloat far)
3788 GLfloat x = (2 * near) / (right-left);
3789 GLfloat y = (2 * near) / (top - bottom);
3790 GLfloat a = (right + left) / (right - left);
3791 GLfloat b = (top + bottom) / (top - bottom);
3792 GLfloat c = -(far + near) / (far - near);
3793 GLfloat d = -(2 * far * near) / (far - near);
3795 # define M(X,Y) m[Y * 4 + X]
3796 M(0,0) = x; M(0,1) = 0; M(0,2) = a; M(0,3) = 0;
3797 M(1,0) = 0; M(1,1) = y; M(1,2) = b; M(1,3) = 0;
3798 M(2,0) = 0; M(2,1) = 0; M(2,2) = c; M(2,3) = d;
3799 M(3,0) = 0; M(3,1) = 0; M(3,2) = -1; M(3,3) = 0;
3802 jwzgles_glMultMatrixf (m);
3807 jwzgles_glOrtho (GLfloat left, GLfloat right,
3808 GLfloat bottom, GLfloat top,
3809 GLfloat near, GLfloat far)
3812 GLfloat a = 2 / (right - left);
3813 GLfloat b = -(right + left) / (right - left);
3814 GLfloat c = 2 / (top - bottom);
3815 GLfloat d = -(top + bottom) / (top - bottom);
3816 GLfloat e = -2 / (far - near);
3817 GLfloat f = -(far + near) / (far - near);
3819 # define M(X,Y) m[Y * 4 + X]
3820 M(0,0) = a; M(0,1) = 0; M(0,2) = 0; M(0,3) = b;
3821 M(1,0) = 0; M(1,1) = c; M(1,2) = 0; M(1,3) = d;
3822 M(2,0) = 0; M(2,1) = 0; M(2,2) = e; M(2,3) = f;
3823 M(3,0) = 0; M(3,1) = 0; M(3,2) = 0; M(3,3) = 1;
3826 jwzgles_glMultMatrixf (m);
3831 jwzgles_gluPerspective (GLdouble fovy, GLdouble aspect,
3832 GLdouble near, GLdouble far)
3836 double rad = fovy / 2 * M_PI / 180;
3841 if (dz == 0 || si == 0 || aspect == 0)
3847 c = -(far + near) / dz;
3848 d = -2 * near * far / dz;
3850 # define M(X,Y) m[Y * 4 + X]
3851 M(0,0) = a; M(0,1) = 0; M(0,2) = 0; M(0,3) = 0;
3852 M(1,0) = 0; M(1,1) = b; M(1,2) = 0; M(1,3) = 0;
3853 M(2,0) = 0; M(2,1) = 0; M(2,2) = c; M(2,3) = d;
3854 M(3,0) = 0; M(3,1) = 0; M(3,2) = -1; M(3,3) = 0;
3857 jwzgles_glMultMatrixf (m);
3862 jwzgles_gluLookAt (GLfloat eyex, GLfloat eyey, GLfloat eyez,
3863 GLfloat centerx, GLfloat centery, GLfloat centerz,
3864 GLfloat upx, GLfloat upy, GLfloat upz)
3867 GLfloat x[3], y[3], z[3];
3870 /* Make rotation matrix */
3873 z[0] = eyex - centerx;
3874 z[1] = eyey - centery;
3875 z[2] = eyez - centerz;
3876 mag = sqrt(z[0] * z[0] + z[1] * z[1] + z[2] * z[2]);
3877 if (mag) { /* mpichler, 19950515 */
3888 /* X vector = Y cross Z */
3889 x[0] = y[1] * z[2] - y[2] * z[1];
3890 x[1] = -y[0] * z[2] + y[2] * z[0];
3891 x[2] = y[0] * z[1] - y[1] * z[0];
3893 /* Recompute Y = Z cross X */
3894 y[0] = z[1] * x[2] - z[2] * x[1];
3895 y[1] = -z[0] * x[2] + z[2] * x[0];
3896 y[2] = z[0] * x[1] - z[1] * x[0];
3898 /* mpichler, 19950515 */
3899 /* cross product gives area of parallelogram, which is < 1.0 for
3900 * non-perpendicular unit-length vectors; so normalize x, y here
3903 mag = sqrt(x[0] * x[0] + x[1] * x[1] + x[2] * x[2]);
3910 mag = sqrt(y[0] * y[0] + y[1] * y[1] + y[2] * y[2]);
3917 #define M(row,col) m[col*4+row]
3918 M(0, 0) = x[0]; M(0, 1) = x[1]; M(0, 2) = x[2]; M(0, 3) = 0.0;
3919 M(1, 0) = y[0]; M(1, 1) = y[1]; M(1, 2) = y[2]; M(1, 3) = 0.0;
3920 M(2, 0) = z[0]; M(2, 1) = z[1]; M(2, 2) = z[2]; M(2, 3) = 0.0;
3921 M(3, 0) = 0.0; M(3, 1) = 0.0; M(3, 2) = 0.0; M(3, 3) = 1.0;
3924 jwzgles_glMultMatrixf(m);
3926 /* Translate Eye to Origin */
3927 jwzgles_glTranslatef(-eyex, -eyey, -eyez);
3931 static void __gluMultMatrixVecd (const GLdouble matrix[16],
3932 const GLdouble in[4],
3937 for (i=0; i<4; i++) {
3939 in[0] * matrix[0*4+i] +
3940 in[1] * matrix[1*4+i] +
3941 in[2] * matrix[2*4+i] +
3942 in[3] * matrix[3*4+i];
3947 jwzgles_gluProject (GLdouble objx, GLdouble objy, GLdouble objz,
3948 const GLdouble modelMatrix[16],
3949 const GLdouble projMatrix[16],
3950 const GLint viewport[4],
3951 GLdouble *winx, GLdouble *winy, GLdouble *winz)
3956 /* #### I suspect this is not working right. I was seeing crazy values
3957 in lament.c. Maybe there's some float-vs-double confusion going on?
3964 __gluMultMatrixVecd(modelMatrix, in, out);
3965 __gluMultMatrixVecd(projMatrix, out, in);
3966 if (in[3] == 0.0) return(GL_FALSE);
3970 /* Map x, y and z to range 0-1 */
3971 in[0] = in[0] * 0.5 + 0.5;
3972 in[1] = in[1] * 0.5 + 0.5;
3973 in[2] = in[2] * 0.5 + 0.5;
3975 /* Map x,y to viewport */
3976 in[0] = in[0] * viewport[2] + viewport[0];
3977 in[1] = in[1] * viewport[3] + viewport[1];
3986 void jwzgles_glViewport (GLuint x, GLuint y, GLuint w, GLuint h)
3988 # if TARGET_IPHONE_SIMULATOR
3989 /* fprintf (stderr, "glViewport %dx%d\n", w, h); */
3991 glViewport (x, y, w, h); /* the real one */
3995 /* The following functions are present in both OpenGL 1.1 and in OpenGLES 1,
3996 but are allowed within glNewList/glEndList, so we must wrap them to allow
3997 them to either be recorded in lists, or run directly.
3999 All this CPP obscenity is me screaming in rage at all the ways that C is
4000 not Lisp, as all I want to do here is DEFADVICE.
4003 #define PROTO_V PROTO_VOID
4004 #define TYPE_V GLuint
4006 #define VARS_V /* */
4008 #define FILL_V /* */
4010 #define TYPE_I GLuint
4011 #define TYPE_II TYPE_I
4012 #define TYPE_III TYPE_I
4013 #define TYPE_IIII TYPE_I
4014 #define ARGS_I TYPE_I a
4015 #define ARGS_II TYPE_I a, TYPE_I b
4016 #define ARGS_III TYPE_I a, TYPE_I b, TYPE_I c
4017 #define ARGS_IIII TYPE_I a, TYPE_I b, TYPE_I c, TYPE_I d
4018 #define LOGS_I "%s\n", mode_desc(a)
4019 #define LOGS_II "%s %d\n", mode_desc(a), b
4020 #define LOGS_III "%s %s %s\n", mode_desc(a), mode_desc(b), mode_desc(c)
4021 #define LOGS_IIII "%d %d %d %d\n", a, b, c, d
4023 #define VARS_II a, b
4024 #define VARS_III a, b, c
4025 #define VARS_IIII a, b, c, d
4026 #define FILL_I vv[0].i = a;
4027 #define FILL_II vv[0].i = a; vv[1].i = b;
4028 #define FILL_III vv[0].i = a; vv[1].i = b; vv[2].i = c;
4029 #define FILL_IIII vv[0].i = a; vv[1].i = b; vv[2].i = c; vv[3].i = d;
4031 #define TYPE_F GLfloat
4032 #define TYPE_FF TYPE_F
4033 #define TYPE_FFF TYPE_F
4034 #define TYPE_FFFF TYPE_F
4035 #define ARGS_F TYPE_F a
4036 #define ARGS_FF TYPE_F a, TYPE_F b
4037 #define ARGS_FFF TYPE_F a, TYPE_F b, TYPE_F c
4038 #define ARGS_FFFF TYPE_F a, TYPE_F b, TYPE_F c, TYPE_F d
4039 #define LOGS_F "%7.3f\n", a
4040 #define LOGS_FF "%7.3f %7.3f\n", a, b
4041 #define LOGS_FFF "%7.3f %7.3f %7.3f\n", a, b, c
4042 #define LOGS_FFFF "%7.3f %7.3f %7.3f %7.3f\n", a, b, c, d
4043 #define VARS_F VARS_I
4044 #define VARS_FF VARS_II
4045 #define VARS_FFF VARS_III
4046 #define VARS_FFFF VARS_IIII
4047 #define FILL_F vv[0].f = a;
4048 #define FILL_FF vv[0].f = a; vv[1].f = b;
4049 #define FILL_FFF vv[0].f = a; vv[1].f = b; vv[2].f = c;
4050 #define FILL_FFFF vv[0].f = a; vv[1].f = b; vv[2].f = c; vv[3].f = d;
4052 #define ARGS_IF TYPE_I a, TYPE_F b
4053 #define VARS_IF VARS_II
4054 #define LOGS_IF "%s %7.3f\n", mode_desc(a), b
4055 #define FILL_IF vv[0].i = a; vv[1].f = b;
4057 #define ARGS_IIF TYPE_I a, TYPE_I b, TYPE_F c
4058 #define VARS_IIF VARS_III
4059 #define LOGS_IIF "%s %s %7.3f\n", mode_desc(a), mode_desc(b), c
4060 #define FILL_IIF vv[0].i = a; vv[1].i = b; vv[2].f = c;
4062 #define TYPE_IV GLint
4063 #define ARGS_IIV TYPE_I a, const TYPE_IV *b
4064 #define VARS_IIV VARS_II
4065 #define LOGS_IIV "%s %d %d %d %d\n", mode_desc(a), b[0], b[1], b[2], b[3]
4066 #define FILL_IIV vv[0].i = a; \
4067 vv[1].i = b[0]; vv[2].i = b[1]; \
4068 vv[3].i = b[2]; vv[4].i = b[3];
4070 #define ARGS_IFV TYPE_I a, const TYPE_F *b
4071 #define VARS_IFV VARS_II
4072 #define LOGS_IFV "%s %7.3f %7.3f %7.3f %7.3f\n", mode_desc(a), \
4073 b[0], b[1], b[2], b[3]
4074 #define FILL_IFV vv[0].i = a; \
4075 vv[1].f = b[0]; vv[2].f = b[1]; \
4076 vv[3].f = b[2]; vv[4].f = b[3];
4078 #define ARGS_IIIV TYPE_I a, TYPE_I b, const TYPE_IV *c
4079 #define VARS_IIIV VARS_III
4080 #define LOGS_IIIV "%s %-8s %3d %3d %3d %3d\n", mode_desc(a), mode_desc(b), \
4081 c[0], c[1], c[2], c[3]
4082 #define FILL_IIIV vv[0].i = a; vv[1].i = b; \
4083 vv[2].i = c[0]; vv[3].i = c[1]; \
4084 vv[4].i = c[2]; vv[5].i = c[3];
4086 #define ARGS_IIFV TYPE_I a, TYPE_I b, const TYPE_F *c
4087 #define VARS_IIFV VARS_III
4088 #define LOGS_IIFV "%s %-8s %7.3f %7.3f %7.3f %7.3f\n", \
4089 mode_desc(a), mode_desc(b), \
4090 c[0], c[1], c[2], c[3]
4091 #define FILL_IIFV vv[0].i = a; vv[1].i = b; \
4092 vv[2].f = c[0]; vv[3].f = c[1]; \
4093 vv[4].f = c[2]; vv[5].f = c[3];
4096 # define WLOG(NAME,ARGS) \
4097 fprintf (stderr, "jwzgles: direct %-12s ", NAME); \
4098 fprintf (stderr, ARGS)
4100 # define WLOG(NAME,ARGS) /* */
4103 #define WRAP(NAME,SIG) \
4104 void jwzgles_##NAME (ARGS_##SIG) \
4106 Assert (!state->compiling_verts, \
4107 STRINGIFY(NAME) " not allowed inside glBegin"); \
4108 if (state->compiling_list) { \
4111 list_push (STRINGIFY(NAME), (list_fn_cb) &jwzgles_##NAME, \
4114 if (! state->replaying_list) { \
4115 WLOG (STRINGIFY(NAME), LOGS_##SIG); \
4117 NAME (VARS_##SIG); \
4118 CHECK(STRINGIFY(NAME)); \
4122 WRAP (glActiveTexture, I)
4123 WRAP (glAlphaFunc, IF)
4124 WRAP (glBlendFunc, II)
4126 WRAP (glClearColor, FFFF)
4127 WRAP (glClearStencil, I)
4128 WRAP (glColorMask, IIII)
4129 WRAP (glCullFace, I)
4130 WRAP (glDepthFunc, I)
4131 WRAP (glDepthMask, I)
4136 WRAP (glFrontFace, I)
4138 WRAP (glLightModelf, IF)
4139 WRAP (glLightModelfv, IFV)
4140 WRAP (glLightf, IIF)
4141 WRAP (glLightfv, IIFV)
4142 WRAP (glLineWidth, F)
4143 WRAP (glLoadIdentity, V)
4145 WRAP (glMatrixMode, I)
4146 WRAP (glPixelStorei, II)
4147 WRAP (glPointSize, F)
4148 WRAP (glPolygonOffset, FF)
4149 WRAP (glPopMatrix, V)
4150 WRAP (glPushMatrix, V)
4151 WRAP (glRotatef, FFFF)
4152 WRAP (glScalef, FFF)
4153 WRAP (glScissor, IIII)
4154 WRAP (glShadeModel, I)
4155 WRAP (glStencilFunc, III)
4156 WRAP (glStencilMask, I)
4157 WRAP (glStencilOp, III)
4158 WRAP (glTexEnvf, IIF)
4159 WRAP (glTexEnvi, III)
4160 WRAP (glTranslatef, FFF)
4162 #define TYPE_IV GLuint
4163 WRAP (glDeleteTextures, IIV)
4166 #endif /* HAVE_JWZGLES - whole file */