1 /* xscreensaver, Copyright (c) 2012 Jamie Zawinski <jwz@jwz.org>
3 * Permission to use, copy, modify, distribute, and sell this software and its
4 * documentation for any purpose is hereby granted without fee, provided that
5 * the above copyright notice appear in all copies and that both that
6 * copyright notice and this permission notice appear in supporting
7 * documentation. No representations are made about the suitability of this
8 * software for any purpose. It is provided "as is" without express or
12 /* A compatibility shim to allow OpenGL 1.3 source code to work in an
13 OpenGLES environment, where almost every OpenGL 1.3 function has
16 There are two major operations going on here:
18 - Converting calls to glBegin + glVertex3f + glEnd to glDrawArrays
19 - Implementing display lists.
22 From an API point of view, OpenGL 1.3 and earlier code looks like this:
24 glLightfv (GL_LIGHT0, GL_POSITION, ...);
25 glLightfv (GL_LIGHT0, GL_AMBIENT, ...);
27 glMatrixMode (GL_PROJECTION);
31 glMatrixMode (GL_MODELVIEW);
41 glBegin (GL_TRIANGLES);
53 OpenGLES broke that model by eliminating glBegin(). Instead of
54 iterating a sequence of vertexes, you need to pack your points into
63 glDrawArrays (GL_TRIANGLES, 0, 3);
65 The projection model (glRotatef, etc.) works the same, but glColor()
66 is missing. You're expected to encode that into your arrays.
68 Also, OpenGLES doesn't support display lists at all.
71 So this code shadows all of the functions that are allowed within
72 glBegin, builds up an array, and calls glDrawArrays at the end.
74 Likewise, it shadows all of the functions that are allowed within
75 glNewList and records those calls for later playback.
78 This code only handles OpenGLES 1.x, not 2.x.
80 OpenGLES 2.0 broke things further by eliminating the whole OpenGL
81 lighting model. Instead of specifying the positions and properties
82 of your lights using the glLight* API, now you are expected to
83 implement it all yourself by downloading C-like code into the GPU
84 directly. This is more flexible, in that if you wanted a completely
85 different lighting model than what OpenGL provides, you could do
86 that, but it leaves you needing to download boilerplate to reproduce
87 what used to be built in.
90 Incidentally, the OpenGL numbering scheme goes something like this:
93 OpenGL 1.1 1997 (improved texture support)
94 OpenGL 1.2 1998 (nothing interesting)
95 OpenGL 1.3 2001 (multisampling, cubemaps)
96 OpenGL 1.4 2002 (added auto-mipmapping)
97 OpenGLES 1.0 2003 (deprecated 80% of the language; fork of OpenGL 1.3)
98 OpenGL 1.5 2003 (added VBOs)
99 OpenGLES 1.1 2004 (fork of OpenGL 1.5)
100 OpenGL 2.0 2004 (a political quagmire)
101 OpenGLES 2.0 2007 (deprecated 95% of the language; fork of OpenGL 2.0)
102 OpenGL 3.0 2008 (added FBOs, VAOs, deprecated 60% of the language)
105 Some things that are missing:
107 - glTexGeni, meaning no spherical environment-mapping textures.
109 - gluNewTess, meaning no tesselation of complex objects.
111 - glMap2f mesh evaluators, meaning no Utah Teapot.
113 - glPolygonMode with GL_LINE or GL_POINT, meaning no wireframe modes
114 that do hidden-surface removal.
116 - glSelectBuffer, meaning no mouse-hit detection on rendered objects.
118 - gluNewQuadric, gluCylinder, etc: rewrite your code to use tube.c, etc.
120 - Putting verts in a display list without a wrapping glBegin.
121 (I didn't realize that even worked!)
123 - Not every function is implemented; just the ones that I needed for
124 xscreensaver. However, the trivial ones are trivial to enable
125 as they come up. Harder ones will be harder.
127 As a result of that, these savers look wrong:
129 blocktube Uses SPHERE_MAP.
130 bouncingcow Uses OBJECT_LINEAR (when run with -texture)
131 dnalogo Uses GLUtesselator.
132 extrusion Uses all kinds of GLUT crap.
133 flyingtoasters Uses SPHERE_MAP and OBJECT_LINEAR.
134 jigglypuff Uses SPHERE_MAP (in chrome mode), GL_LINE (in wireframe)
135 jigsaw Uses GLUtesselator.
136 lockward Puts verts in lists without glBegin!
137 pinion Uses glSelectBuffer and gluPickMatrix for mouse-clicks.
138 pipes Uses glMap2f for the Utah Teapot.
139 polyhedra Uses GLUtesselator; also Utah Teapot.
140 skytentacles Uses glTexImage1D and GL_LINE in -cel mode.
141 timetunnel Uses GL_CONSTANT_ALPHA and all kinds of other stuff.
151 #endif /* HAVE_CONFIG_H */
153 #ifdef HAVE_JWZGLES /* whole file */
162 #endif /* HAVE_UNISTD_H */
164 #if defined(USE_IPHONE)
165 # include <OpenGLES/ES1/gl.h>
166 # include <OpenGLES/ES1/glext.h>
167 #elif defined(HAVE_COCOA)
168 # include <OpenGL/gl.h>
169 # include <OpenGL/glu.h>
175 #include "jwzglesI.h"
177 #define STRINGIFY(X) #X
180 #define countof(x) (sizeof((x))/sizeof((*x)))
183 #define Assert(C,S) do { \
185 fprintf (stderr, "jwzgles: %s\n", S); \
190 typedef struct { GLfloat x, y, z; } XYZ;
191 typedef struct { GLfloat x, y, z, w; } XYZW;
192 typedef struct { GLfloat s, t, r, q; } STRQ;
193 typedef struct { GLfloat r, g, b, a; } RGBA;
196 /* Used to record all calls to glVertex3f, glNormal3f, etc.
197 while inside glBegin / glEnd so that we can convert that
198 to a single call to glDrawArrays.
202 int count, size; /* size of each array */
204 XYZW *verts; /* Arrays being built */
209 int ncount; /* How many normals, tex coords and colors were */
210 int tcount; /* used. We optimize based on "0, 1, or many". */
212 int materialistic; /* Whether glMaterial was called inside glBegin */
214 XYZ cnorm; /* Prevailing normal/texture/color while building */
221 typedef void (*list_fn_cb) (void);
224 /* We need this nonsense because you can't cast a double to a void*
225 or vice versa. They tend to be passed in different registers,
226 and you need to know about that because it's still 1972 here.
228 typedef union { const void *v; GLfloat f; GLuint i; } void_int;
230 typedef struct { /* saved args for glDrawArrays */
231 int size, type, stride, bytes;
235 typedef enum { /* shorthand describing arglist signature */
236 PROTO_VOID, /* no args */
237 PROTO_I, /* 1 int arg */
238 PROTO_F, /* 1 float arg */
239 PROTO_II, /* int, int */
240 PROTO_FF, /* float, float */
241 PROTO_IF, /* int, float */
242 PROTO_III, /* int, int, int */
243 PROTO_FFF, /* float, float, float */
244 PROTO_IIF, /* int, int, float */
245 PROTO_IIII, /* int, int, int, int */
246 PROTO_FFFF, /* float, float, float, float */
247 PROTO_IIV, /* int, int[4] */
248 PROTO_IFV, /* int, float[4] */
249 PROTO_IIIV, /* int, int, int[4] */
250 PROTO_IIFV, /* int, int, float[4] */
251 PROTO_FV16, /* float[16] */
252 PROTO_ARRAYS /* glDrawArrays */
255 typedef struct { /* A single element of a display list */
257 list_fn_cb fn; /* saved function pointer */
258 fn_proto proto; /* arglist prototype */
259 draw_array *arrays; /* args for glDrawArrays */
260 void_int argv[16]; /* args for everything else */
264 typedef struct { /* saved activity within glNewList */
271 typedef struct { /* A display list */
277 #define ISENABLED_TEXTURE_2D (1<<0)
278 #define ISENABLED_TEXTURE_GEN_S (1<<1)
279 #define ISENABLED_TEXTURE_GEN_T (1<<2)
280 #define ISENABLED_LIGHTING (1<<3)
281 #define ISENABLED_BLEND (1<<4)
282 #define ISENABLED_DEPTH_TEST (1<<5)
283 #define ISENABLED_CULL_FACE (1<<6)
284 #define ISENABLED_NORMALIZE (1<<7)
285 #define ISENABLED_FOG (1<<8)
286 #define ISENABLED_COLMAT (1<<9)
287 #define ISENABLED_VERT_ARRAY (1<<10)
288 #define ISENABLED_NORM_ARRAY (1<<11)
289 #define ISENABLED_TEX_ARRAY (1<<12)
290 #define ISENABLED_COLOR_ARRAY (1<<13)
293 typedef struct { /* global state */
295 vert_set set; /* set being built */
297 int compiling_list; /* list id if inside glNewList; 0 means immediate */
298 int replaying_list; /* depth of call stack to glCallList */
299 int compiling_verts; /* inside glBegin */
301 list_set lists; /* saved lists */
302 unsigned long enabled;
307 static jwzgles_state global_state = { { 0, }, 0, 0, 0, { 0, }, 0, };
308 static jwzgles_state *state = &global_state;
312 # define LOG(A) fprintf(stderr,"jwzgles: " A "\n")
313 # define LOG1(A,B) fprintf(stderr,"jwzgles: " A "\n",B)
314 # define LOG2(A,B,C) fprintf(stderr,"jwzgles: " A "\n",B,C)
315 # define LOG3(A,B,C,D) fprintf(stderr,"jwzgles: " A "\n",B,C,D)
316 # define LOG4(A,B,C,D,E) fprintf(stderr,"jwzgles: " A "\n",B,C,D,E)
317 # define LOG5(A,B,C,D,E,F) fprintf(stderr,"jwzgles: " A "\n",B,C,D,E,F)
318 # define LOG6(A,B,C,D,E,F,G) fprintf(stderr,"jwzgles: " A "\n",B,C,D,E,F,G)
319 # define LOG7(A,B,C,D,E,F,G,H) fprintf(stderr,"jwzgles: " A "\n",B,C,D,E,F,G,H)
320 # define LOG8(A,B,C,D,E,F,G,H,I)\
321 fprintf(stderr,"jwzgles: "A "\n",B,C,D,E,F,G,H,I)
322 # define LOG9(A,B,C,D,E,F,G,H,I,J)\
323 fprintf(stderr,"jwzgles: "A "\n",B,C,D,E,F,G,H,I,J)
324 # define LOG10(A,B,C,D,E,F,G,H,I,J,K)\
325 fprintf(stderr,"jwzgles: "A "\n",B,C,D,E,F,G,H,I,J,K)
326 # define LOG17(A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R)\
327 fprintf(stderr,"jwzgles: "A "\n",B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R)
328 # define CHECK(S) check_gl_error(S)
330 # define LOG(A) /* */
331 # define LOG1(A,B) /* */
332 # define LOG2(A,B,C) /* */
333 # define LOG3(A,B,C,D) /* */
334 # define LOG4(A,B,C,D,E) /* */
335 # define LOG5(A,B,C,D,E,F) /* */
336 # define LOG6(A,B,C,D,E,F,G) /* */
337 # define LOG7(A,B,C,D,E,F,G,H) /* */
338 # define LOG8(A,B,C,D,E,F,G,H,I) /* */
339 # define LOG9(A,B,C,D,E,F,G,H,I,J) /* */
340 # define LOG10(A,B,C,D,E,F,G,H,I,J,K) /* */
341 # define LOG17(A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R) /* */
342 # define CHECK(S) /* */
347 mode_desc (int mode) /* for debugging messages */
350 # define SS(X) case GL_##X: return STRINGIFY(X);
353 SS(AMBIENT_AND_DIFFUSE)
374 SS(COLOR_MATERIAL_FACE)
375 SS(COLOR_MATERIAL_PARAMETER)
396 SS(INVALID_OPERATION)
403 SS(LIGHT_MODEL_AMBIENT)
404 SS(LIGHT_MODEL_COLOR_CONTROL)
405 SS(LIGHT_MODEL_LOCAL_VIEWER)
406 SS(LIGHT_MODEL_TWO_SIDE)
409 SS(LINEAR_MIPMAP_LINEAR)
410 SS(LINEAR_MIPMAP_NEAREST)
421 SS(NEAREST_MIPMAP_LINEAR)
422 SS(NEAREST_MIPMAP_NEAREST)
427 SS(ONE_MINUS_DST_ALPHA)
428 SS(ONE_MINUS_DST_COLOR)
429 SS(ONE_MINUS_SRC_ALPHA)
430 SS(ONE_MINUS_SRC_COLOR)
435 SS(POLYGON_OFFSET_FILL)
450 SS(SEPARATE_SPECULAR_COLOR)
459 SS(SRC_ALPHA_SATURATE)
463 SS(STENCIL_BUFFER_BIT)
475 SS(TEXTURE_ALPHA_SIZE)
476 SS(TEXTURE_BINDING_2D)
477 SS(TEXTURE_BLUE_SIZE)
479 SS(TEXTURE_BORDER_COLOR)
480 SS(TEXTURE_COMPONENTS)
481 SS(TEXTURE_COORD_ARRAY)
483 SS(TEXTURE_ENV_COLOR)
490 SS(TEXTURE_GREEN_SIZE)
492 SS(TEXTURE_INTENSITY_SIZE)
493 SS(TEXTURE_LUMINANCE_SIZE)
494 SS(TEXTURE_MAG_FILTER)
495 SS(TEXTURE_MIN_FILTER)
503 SS(UNPACK_ROW_LENGTH)
505 SS(UNSIGNED_INT_8_8_8_8_REV)
510 /*SS(COLOR_BUFFER_BIT) -- same value as GL_LIGHT0 */
512 case (GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT):
513 return "DEPTH_BUFFER_BIT | COLOR_BUFFER_BIT";
514 /* Oops, same as INVALID_ENUM.
515 case (GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT):
516 return "DEPTH_BUFFER_BIT | STENCIL_BUFFER_BIT";
518 case (GL_COLOR_BUFFER_BIT | GL_STENCIL_BUFFER_BIT):
519 return "COLOR_BUFFER_BIT | STENCIL_BUFFER_BIT";
520 case (GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT | GL_STENCIL_BUFFER_BIT):
521 return "DEPTH_BUFFER_BIT | COLOR_BUFFER_BIT | STENCIL_BUFFER_BIT";
524 static char buf[255];
525 sprintf (buf, "0x%04X", mode);
532 check_gl_error (const char *s)
534 GLenum i = glGetError();
535 if (i == GL_NO_ERROR) return;
536 fprintf (stderr, "jwzgles: GL ERROR: %s: %s\n", s, mode_desc(i));
543 jwzgles_glGenLists (int n)
548 Assert (!state->compiling_verts, "glGenLists not allowed inside glBegin");
550 /* Ensure space in state->lists, clear the one at the end, and tick counter
551 Note that lists are never really deleted, and we can never re-use elements
552 of this array. glDeleteLists zeroes out the contents of the list, but
553 the list ID is still valid for use with glNewList forever.
554 #### So maybe this should be a linked list instead of an array.
556 for (i = 0; i < n; i++)
561 /* Adding a new list at the end. Make room for it.
563 if (state->lists.count >= state->lists.size - 1)
565 int new_size = 20 + (state->lists.size * 1.2);
566 state->lists.lists = (list *)
567 realloc (state->lists.lists,
568 new_size * sizeof (*state->lists.lists));
569 Assert (state->lists.lists, "out of memory");
570 state->lists.size = new_size;
571 LOG1("glGenLists grew -> %d", new_size);
573 state->lists.count++;
574 id = state->lists.count;
575 L = &state->lists.lists[id-1];
577 memset (L, 0, sizeof (*L));
579 if (ret == 0) ret = id;
580 LOG1("glGenLists -> %d", L->id);
583 /* Return the ID of the first list allocated */
590 jwzgles_glNewList (int id, int mode)
593 Assert (id > 0 && id <= state->lists.count, "glNewList: bogus ID");
594 Assert (mode == GL_COMPILE, "glNewList: bad mode");
595 Assert (!state->compiling_verts, "glNewList not allowed inside glBegin");
596 Assert (!state->compiling_list, "nested glNewList");
597 Assert (state->set.count == 0, "missing glEnd");
599 L = &state->lists.lists[id-1];
600 Assert (L->id == id, "glNewList corrupted");
602 if (L->count != 0) jwzgles_glDeleteLists (L->id, 1); /* Overwriting */
603 Assert (L->count == 0, "glNewList corrupted");
605 state->compiling_list = id;
607 LOG1("glNewList -> %d", id);
612 jwzgles_glEndList (void)
614 Assert (state->compiling_list, "extra glEndList");
615 Assert (state->set.count == 0, "missing glEnd");
616 Assert (!state->compiling_verts, "glEndList not allowed inside glBegin");
617 LOG1("glEndList %d", state->compiling_list);
618 state->compiling_list = 0;
622 static void save_arrays (list_fn *, int);
623 static void restore_arrays (list_fn *, int);
624 static void copy_array_data (draw_array *, int, const char *);
627 list_push (const char * const name,
628 list_fn_cb fn, fn_proto proto, void_int *av)
634 Assert (state->compiling_list > 0, "not inside glNewList");
635 Assert (state->compiling_list <= state->lists.count, "glNewList corrupted");
637 L = &state->lists.lists[state->compiling_list-1];
638 Assert (L, "glNewList: no list");
640 if (L->count >= L->size - 1)
642 int new_size = 20 + (L->size * 1.2);
643 L->fns = (list_fn *) realloc (L->fns, new_size * sizeof (*L->fns));
644 Assert (L->fns, "glNewList: no functions");
648 memset (&L->fns[L->count], 0, sizeof (*L->fns));
650 F = L->fns + L->count;
655 if (proto != PROTO_VOID)
656 for (i = 0; i < countof(F->argv); i++)
662 LOG1 (" push %-12s", name);
665 if (fn == (list_fn_cb) &jwzgles_glBegin ||
666 fn == (list_fn_cb) &jwzgles_glFrontFace ||
667 fn == (list_fn_cb) &jwzgles_glEnable ||
668 fn == (list_fn_cb) &jwzgles_glDisable ||
669 fn == (list_fn_cb) &jwzgles_glEnableClientState ||
670 fn == (list_fn_cb) &jwzgles_glDisableClientState ||
671 fn == (list_fn_cb) &jwzgles_glShadeModel ||
672 fn == (list_fn_cb) &jwzgles_glMatrixMode)
673 LOG2 (" push %-12s %s", name, mode_desc (av[0].i));
675 LOG2 (" push %-12s %d", name, av[0].i);
678 LOG2 (" push %-12s %7.3f", name, av[0].f);
681 if (fn == (list_fn_cb) &jwzgles_glBindTexture)
682 LOG3 (" push %-12s %s %d", name, mode_desc (av[0].i), av[1].i);
684 LOG3 (" push %-12s %d %d", name, av[0].i, av[1].i);
687 LOG3 (" push %-12s %7.3f %7.3f", name, av[0].f, av[1].f);
690 LOG3 (" push %-12s %s %7.3f", name, mode_desc (av[0].i), av[1].f);
694 if (fn == (list_fn_cb) &jwzgles_glDrawArrays ||
695 fn == (list_fn_cb) &jwzgles_glTexParameteri)
696 LOG4 (" push %-12s %s %d %d", name, mode_desc (av[0].i),
699 LOG4 (" push %-12s %d %d %d", name, av[0].i, av[1].i, av[2].i);
702 LOG4 (" push %-12s %7.3f %7.3f %7.3f", name, av[0].f, av[1].f, av[2].f);
705 LOG4 (" push %-12s %s %s %7.3f", name,
706 mode_desc(av[0].i), mode_desc(av[1].i), av[2].f);
709 LOG5 (" push %-12s %d %d %d %d", name,
710 av[0].i, av[1].i, av[2].i, av[3].i);
713 LOG5 (" push %-12s %7.3f %7.3f %7.3f %7.3f", name,
714 av[0].f, av[1].f, av[2].f, av[3].f);
717 LOG6 (" push %-12s %s %3.1f %3.1f %3.1f %3.1f", name, mode_desc (av[0].i),
718 av[1].f, av[2].f, av[3].f, av[4].f);
721 LOG6 (" push %-12s %s %d %d %d %d", name, mode_desc (av[0].i),
722 av[1].i, av[2].i, av[3].i, av[4].i);
725 LOG7 (" push %-12s %s %-8s %3.1f %3.1f %3.1f %3.1f", name,
726 mode_desc (av[0].i), mode_desc (av[1].i),
727 av[2].f, av[3].f, av[4].f, av[5].f);
730 LOG7 (" push %-12s %s %-8s %3d %3d %3d %3d", name,
731 mode_desc (av[0].i), mode_desc (av[1].i),
732 av[2].i, av[3].i, av[4].i, av[5].i);
735 LOG17 (" push %-12s ["
736 "%8.3f %8.3f %8.3f %8.3f " "\n\t\t\t "
737 "%8.3f %8.3f %8.3f %8.3f " "\n\t\t\t "
738 "%8.3f %8.3f %8.3f %8.3f " "\n\t\t\t "
739 "%8.3f %8.3f %8.3f %8.3f ]",
741 av[0].f, av[1].f, av[2].f, av[3].f,
742 av[4].f, av[5].f, av[6].f, av[7].f,
743 av[8].f, av[9].f, av[10].f, av[11].f,
744 av[12].f, av[13].f, av[14].f, av[15].f);
747 Assert (0, "bogus prototype");
752 if (proto == PROTO_ARRAYS) /* glDrawArrays */
753 save_arrays (F, av[1].i + av[2].i);
760 jwzgles_glBegin (int mode)
762 Assert (!state->compiling_verts, "nested glBegin");
763 state->compiling_verts++;
765 /* Only these commands are allowed inside glBegin:
767 glVertex -- not allowed outside
778 glArrayElement -- not allowed outside
785 if (!state->replaying_list)
786 LOG2 ("%sglBegin %s",
787 (state->compiling_list || state->replaying_list ? " " : ""),
790 Assert (state->set.count == 0, "glBegin corrupted");
791 state->set.mode = mode;
792 state->set.count = 0;
793 state->set.ncount = 0;
794 state->set.tcount = 0;
795 state->set.ccount = 0;
800 jwzgles_glDeleteLists (int id0, int range)
802 Assert (!state->compiling_verts, "glDeleteLists not allowed inside glBegin");
804 if (state->compiling_list)
809 list_push ("glDeleteLists", (list_fn_cb) &jwzgles_glDeleteLists,
816 if (!state->replaying_list)
817 LOG2 ("glDeleteLists %d %d", id0, range);
819 for (id = id0 + range - 1; id >= id0; id--)
823 if (id == 0) continue; /* People do this stupid thing */
824 if (id > state->lists.count) break; /* this too */
825 Assert (id > 0 && id <= state->lists.count,
826 "glDeleteLists: bogus ID");
827 L = &state->lists.lists[id-1];
828 Assert (L->id == id, "glDeleteLists corrupted");
830 for (i = 0; i < L->count; i++)
832 list_fn *lf = &L->fns[i];
836 for (j = 0; j < 4; j++)
838 if (lf->arrays[j].data)
839 free (lf->arrays[j].data);
846 memset (L, 0, sizeof (*L));
854 jwzgles_glIsList (GLuint id)
856 return (id > 0 && id < state->lists.count);
862 jwzgles_glNormal3fv (const GLfloat *v)
864 if (state->compiling_list && !state->compiling_verts)
870 list_push ("glNormal3f", (list_fn_cb) &jwzgles_glNormal3f,
875 if (!state->replaying_list)
876 LOG5 ("%s%sglNormal3f %7.3f %7.3f %7.3f",
877 (state->compiling_list || state->replaying_list ? " " : ""),
878 (state->compiling_verts ? " rec " : ""),
881 state->set.cnorm.x = v[0];
882 state->set.cnorm.y = v[1];
883 state->set.cnorm.z = v[2];
885 if (state->set.count > 0 && state->set.ncount == 1) /* not first! */
888 if (! state->compiling_verts) /* outside glBegin */
890 glNormal3f (v[0], v[1], v[2]);
898 jwzgles_glNormal3f (GLfloat x, GLfloat y, GLfloat z)
904 jwzgles_glNormal3fv (v);
909 jwzgles_glTexCoord4fv (const GLfloat *v)
911 if (state->compiling_list && !state->compiling_verts)
918 list_push ("glTexCoord4f", (list_fn_cb) &jwzgles_glTexCoord4f,
923 if (!state->replaying_list)
924 LOG6 ("%s%sglTexCoord4f %7.3f %7.3f %7.3f %7.3f",
925 (state->compiling_list || state->replaying_list ? " " : ""),
926 (state->compiling_verts ? " rec " : ""),
927 v[0], v[1], v[2], v[3]);
929 state->set.ctex.s = v[0];
930 state->set.ctex.t = v[1];
931 state->set.ctex.r = v[2];
932 state->set.ctex.q = v[3];
934 if (state->set.count > 0 && state->set.tcount == 1) /* not first! */
937 Assert (state->compiling_verts, "glTexCoord4fv outside glBegin");
943 jwzgles_glTexCoord4f (GLfloat s, GLfloat t, GLfloat r, GLfloat q)
950 jwzgles_glTexCoord4fv (v);
955 jwzgles_glTexCoord3fv (const GLfloat *v)
962 jwzgles_glTexCoord4fv (vv);
967 jwzgles_glTexCoord2fv (const GLfloat *v)
974 jwzgles_glTexCoord4fv (vv);
979 jwzgles_glTexCoord3f (GLfloat s, GLfloat t, GLfloat r)
981 jwzgles_glTexCoord4f (s, t, r, 1);
986 jwzgles_glTexCoord2f (GLfloat s, GLfloat t)
988 jwzgles_glTexCoord4f (s, t, 0, 1);
993 jwzgles_glTexCoord1f (GLfloat s)
995 jwzgles_glTexCoord4f (s, 0, 0, 1);
1001 jwzgles_glColor4fv (const GLfloat *v)
1003 if (state->compiling_list && !state->compiling_verts)
1010 list_push ("glColor4f", (list_fn_cb) &jwzgles_glColor4f,
1015 if (!state->replaying_list)
1016 LOG6 ("%s%sglColor4f %7.3f %7.3f %7.3f %7.3f",
1017 (state->compiling_list || state->replaying_list ? " " : ""),
1018 (state->compiling_verts ? " rec " : ""),
1019 v[0], v[1], v[2], v[3]);
1021 state->set.ccolor.r = v[0];
1022 state->set.ccolor.g = v[1];
1023 state->set.ccolor.b = v[2];
1024 state->set.ccolor.a = v[3];
1025 state->set.ccount++;
1026 if (state->set.count > 0 && state->set.ccount == 1) /* not first! */
1027 state->set.ccount++;
1029 if (! state->compiling_verts) /* outside glBegin */
1031 glColor4f (v[0], v[1], v[2], v[3]);
1039 jwzgles_glColor4f (GLfloat r, GLfloat g, GLfloat b, GLfloat a)
1046 jwzgles_glColor4fv (v);
1051 jwzgles_glColor3f (GLfloat r, GLfloat g, GLfloat b)
1053 jwzgles_glColor4f (r, g, b, 1);
1058 jwzgles_glColor3fv (const GLfloat *v)
1065 jwzgles_glColor4fv (vv);
1070 jwzgles_glColor4i (GLuint r, GLuint g, GLuint b, GLuint a)
1072 jwzgles_glColor4f (r, g, b, a);
1077 jwzgles_glColor3i (GLuint r, GLuint g, GLuint b)
1079 jwzgles_glColor4f (r, g, b, 1);
1084 jwzgles_glColor4iv (const GLint *v)
1091 jwzgles_glColor4fv (vv);
1096 jwzgles_glColor3iv (const GLint *v)
1103 jwzgles_glColor4fv (vv);
1108 jwzgles_glColor4ub (GLubyte r, GLubyte g, GLubyte b, GLubyte a)
1110 jwzgles_glColor4f (r, g, b, a);
1115 jwzgles_glColor3ub (GLubyte r, GLubyte g, GLubyte b)
1117 jwzgles_glColor4f (r, g, b, 1);
1122 jwzgles_glMaterialfv (GLenum face, GLenum pname, const GLfloat *color)
1124 /* If this is called inside glBegin/glEnd with a front ambient color,
1125 then treat it the same as glColor: set the color of the upcoming
1128 Other faces or lighting types within glBegin are ignored.
1131 if (state->compiling_verts)
1133 if ((face == GL_FRONT ||
1134 face == GL_FRONT_AND_BACK) &&
1135 (pname == GL_AMBIENT ||
1136 pname == GL_DIFFUSE ||
1137 pname == GL_AMBIENT_AND_DIFFUSE))
1139 jwzgles_glColor4f (color[0], color[1], color[2], color[3]);
1140 state->set.materialistic++;
1143 LOG2 (" IGNORING glMaterialfv %s %s",
1144 mode_desc(face), mode_desc(pname));
1146 else if (state->compiling_list)
1155 list_push ("glMaterialfv", (list_fn_cb) &jwzgles_glMaterialfv,
1160 /* If this is called outside of glBegin/glEnd with a front
1161 ambient color, then the intent is presumably for that color
1162 to apply to the upcoming vertexes (which may be played back
1163 from a list that does not have vertex colors in it). In that
1164 case, the only way to make the colors show up is to call
1165 glColor() with GL_COLOR_MATERIAL enabled.
1167 I'm not sure if this will have other inappropriate side effects...
1169 if ((face == GL_FRONT ||
1170 face == GL_FRONT_AND_BACK) &&
1171 (pname == GL_AMBIENT ||
1172 pname == GL_DIFFUSE ||
1173 pname == GL_AMBIENT_AND_DIFFUSE))
1175 jwzgles_glEnable (GL_COLOR_MATERIAL);
1176 jwzgles_glColor4f (color[0], color[1], color[2], color[3]);
1179 /* OpenGLES seems to throw "invalid enum" for GL_FRONT -- but it
1180 goes ahead and sets the material anyway! No error if we just
1181 always use GL_FRONT_AND_BACK.
1183 if (face == GL_FRONT)
1184 face = GL_FRONT_AND_BACK;
1185 if (! state->replaying_list)
1186 LOG7 ("direct %-12s %s %s %7.3f %7.3f %7.3f %7.3f", "glMaterialfv",
1187 mode_desc(face), mode_desc(pname),
1188 color[0], color[1], color[2], color[3]);
1189 glMaterialfv (face, pname, color); /* the real one */
1190 CHECK("glMaterialfv");
1196 jwzgles_glMaterialiv (GLenum face, GLenum pname, const GLint *v)
1203 jwzgles_glMaterialfv (face, pname, vv);
1207 jwzgles_glMaterialf (GLenum face, GLenum pname, const GLfloat c)
1214 jwzgles_glMaterialfv (face, pname, vv);
1219 jwzgles_glMateriali (GLenum face, GLenum pname, const GLuint c)
1221 jwzgles_glMaterialf (face, pname, c);
1226 jwzgles_glColorMaterial (GLenum face, GLenum mode)
1228 Assert (!state->compiling_verts,
1229 "glColorMaterial not allowed inside glBegin");
1231 if (state->compiling_list)
1236 list_push ("glColorMaterial", (list_fn_cb) &jwzgles_glColorMaterial,
1241 /* No real analog to this distinction in OpenGLES, since color
1242 arrays don't distinguish between "color" and "material", */
1243 Assert (0, "glColorMaterial: unimplemented mode");
1252 jwzgles_glVertex4fv (const GLfloat *v)
1254 vert_set *s = &state->set;
1255 int count = s->count;
1257 Assert (state->compiling_verts, "glVertex4fv not inside glBegin");
1259 LOG5("%s rec glVertex4f %7.3f %7.3f %7.3f %7.3f",
1260 (state->compiling_list || state->replaying_list ? " " : ""),
1261 v[0], v[1], v[2], v[3]);
1263 if (count >= s->size - 1)
1265 int new_size = 20 + (s->size * 1.2);
1267 /* 4 arrays, different element sizes...
1268 We allocate all 4 arrays just in case we need them,
1269 but we might not end up using them all at the end.
1272 s->verts = (XYZW *) realloc (s->verts, new_size * sizeof (*s->verts));
1273 Assert (s->verts, "out of memory");
1275 s->norms = (XYZ *) realloc (s->norms, new_size * sizeof (*s->norms));
1276 Assert (s->norms, "out of memory");
1278 s->tex = (STRQ *) realloc (s->tex, new_size * sizeof (*s->tex));
1279 Assert (s->tex, "out of memory");
1281 s->color = (RGBA *) realloc (s->color, new_size * sizeof (*s->color));
1282 Assert (s->color, "out of memory");
1287 s->verts [count].x = v[0];
1288 s->verts [count].y = v[1];
1289 s->verts [count].z = v[2];
1290 s->verts [count].w = v[3];
1291 s->norms [count] = s->cnorm;
1292 s->tex [count] = s->ctex;
1293 s->color [count] = s->ccolor;
1299 jwzgles_glVertex4f (GLfloat x, GLfloat y, GLfloat z, GLfloat w)
1306 jwzgles_glVertex4fv (v);
1310 jwzgles_glVertex4i (GLint x, GLint y, GLint z, GLint w)
1312 jwzgles_glVertex4f (x, y, z, w);
1316 jwzgles_glVertex3f (GLfloat x, GLfloat y, GLfloat z)
1323 jwzgles_glVertex4fv (v);
1327 jwzgles_glVertex3i (GLint x, GLint y, GLint z)
1329 jwzgles_glVertex3f (x, y, z);
1333 jwzgles_glVertex3fv (const GLfloat *v)
1335 jwzgles_glVertex3f (v[0], v[1], v[2]);
1339 jwzgles_glVertex3dv (const GLdouble *v)
1341 jwzgles_glVertex3f (v[0], v[1], v[2]);
1346 jwzgles_glVertex2f (GLfloat x, GLfloat y)
1352 jwzgles_glVertex3fv (v);
1356 jwzgles_glVertex2fv (const GLfloat *v)
1358 jwzgles_glVertex2f (v[0], v[1]);
1362 jwzgles_glVertex2i (GLint x, GLint y)
1364 jwzgles_glVertex2f (x, y);
1369 jwzgles_glLightiv (GLenum light, GLenum pname, const GLint *params)
1376 jwzgles_glLightfv (light, pname, v);
1380 jwzgles_glLightModeliv (GLenum pname, const GLint *params)
1387 jwzgles_glLightModelfv (pname, v);
1391 jwzgles_glFogiv (GLenum pname, const GLint *params)
1398 jwzgles_glFogfv (pname, v);
1402 jwzgles_glLighti (GLenum light, GLenum pname, GLint param)
1404 jwzgles_glLightf (light, pname, param);
1408 jwzgles_glLightModeli (GLenum pname, GLint param)
1410 jwzgles_glLightModelf (pname, param);
1414 jwzgles_glFogi (GLenum pname, GLint param)
1416 jwzgles_glFogf (pname, param);
1421 jwzgles_glRotated (GLdouble angle, GLdouble x, GLdouble y, GLdouble z)
1423 jwzgles_glRotatef (angle, x, y, z);
1428 jwzgles_glClipPlane (GLenum plane, const GLdouble *equation)
1430 Assert (state->compiling_verts, "glClipPlane not inside glBegin");
1431 Assert (0, "glClipPlane unimplemented"); /* no GLES equivalent... */
1436 jwzgles_glPolygonMode (GLenum face, GLenum mode)
1438 Assert (!state->compiling_verts, "not inside glBegin");
1439 if (state->compiling_list)
1444 list_push ("glPolygonMode", (list_fn_cb) &jwzgles_glPolygonMode,
1449 /* POINT and LINE don't exist in GLES */
1450 Assert (mode == GL_FILL, "glPolygonMode: unimplemented mode");
1456 jwzgles_glDrawBuffer (GLenum buf)
1458 Assert (!state->compiling_verts, "not inside glBegin");
1459 if (state->compiling_list)
1463 list_push ("glDrawBuffer", (list_fn_cb) &jwzgles_glDrawBuffer,
1468 /* Assert (buf == GL_BACK, "glDrawBuffer: back buffer only"); */
1469 # ifndef GL_VERSION_ES_CM_1_0 /* not compiling against OpenGLES 1.x */
1470 if (! state->replaying_list)
1471 LOG1 ("direct %-12s", "glDrawBuffer");
1472 glDrawBuffer (buf); /* the real one */
1473 CHECK("glDrawBuffer");
1479 /* Given an array of sets of 4 elements of arbitrary size, convert it
1480 to an array of sets of 6 elements instead: ABCD becomes ABC BCD.
1483 cq2t (unsigned char **arrayP, int stride, int count)
1485 int count2 = count * 6 / 4;
1486 int size = stride * count;
1487 int size2 = stride * count2;
1488 const unsigned char *oarray, *in;
1489 unsigned char *array2, *oarray2, *out;
1493 if (!oarray || count == 0)
1496 array2 = (unsigned char *) malloc (size2);
1497 Assert (array2, "out of memory");
1502 for (i = 0; i < count / 4; i++)
1504 const unsigned char *a, *b, *c, *d; /* the 4 corners */
1505 a = in; in += stride;
1506 b = in; in += stride;
1507 c = in; in += stride;
1508 d = in; in += stride;
1510 # define PUSH(IN) do { \
1511 const unsigned char *ii = IN; \
1513 for (j = 0; j < stride; j++) { \
1517 PUSH (a); PUSH (b); PUSH (d); /* the 2 triangles */
1518 PUSH (b); PUSH (c); PUSH (d);
1522 Assert (in == oarray + size, "convert_quads corrupted");
1523 Assert (out == oarray2 + size2, "convert_quads corrupted");
1531 /* Convert all coordinates in a GL_QUADS vert_set to GL_TRIANGLES.
1534 convert_quads_to_triangles (vert_set *s)
1537 Assert (s->mode == GL_QUADS, "convert_quads bad mode");
1539 cq2t ((unsigned char **) &s->verts, sizeof(*s->verts), s->count);
1540 cq2t ((unsigned char **) &s->norms, sizeof(*s->norms), s->count);
1541 cq2t ((unsigned char **) &s->tex, sizeof(*s->tex), s->count);
1542 cq2t ((unsigned char **) &s->color, sizeof(*s->color), s->count);
1545 s->mode = GL_TRIANGLES;
1550 jwzgles_glEnd (void)
1552 vert_set *s = &state->set;
1553 int was_norm, was_tex, was_color, was_mat;
1554 int is_norm, is_tex, is_color, is_mat;
1556 Assert (state->compiling_verts == 1, "missing glBegin");
1557 state->compiling_verts--;
1559 if (!state->replaying_list)
1561 LOG5 ("%s [V = %d, N = %d, T = %d, C = %d]",
1562 (state->compiling_list || state->replaying_list ? " " : ""),
1563 s->count, s->ncount, s->tcount, s->ccount);
1565 (state->compiling_list || state->replaying_list ? " " : ""));
1568 if (s->count == 0) return;
1570 if (s->mode == GL_QUADS)
1571 convert_quads_to_triangles (s);
1572 else if (s->mode == GL_QUAD_STRIP)
1573 s->mode = GL_TRIANGLE_STRIP; /* They do the same thing! */
1574 else if (s->mode == GL_POLYGON)
1575 s->mode = GL_TRIANGLE_FAN; /* They do the same thing! */
1577 glVertexPointer (4, GL_FLOAT, sizeof(*s->verts), s->verts); /* XYZW */
1578 glNormalPointer ( GL_FLOAT, sizeof(*s->norms), s->norms); /* XYZ */
1579 glTexCoordPointer (4, GL_FLOAT, sizeof(*s->tex), s->tex); /* STRQ */
1580 glColorPointer (4, GL_FLOAT, sizeof(*s->color), s->color); /* RGBA */
1581 CHECK("glColorPointer");
1583 /* If there were no calls to glNormal3f inside of glBegin/glEnd,
1584 don't bother enabling the normals array.
1586 If there was exactly *one* call to glNormal3f inside of glBegin/glEnd,
1587 and it was before the first glVertex3f, then also don't enable the
1588 normals array, but do emit that call to glNormal3f before calling
1591 Likewise for texture coordinates and colors.
1593 Be careful to leave the arrays' enabled/disabled state the same as
1594 before, or a later caller might end up using one of our arrays by
1595 mistake. #### Actually this isn't quite right: if glEnd is in a
1596 list, it saves the trailing enable/disable calls in the list, instead
1597 if restoring them to what their state was before the list was run.
1599 was_norm = jwzgles_glIsEnabled (GL_NORMAL_ARRAY);
1600 was_tex = jwzgles_glIsEnabled (GL_TEXTURE_COORD_ARRAY);
1601 was_color = jwzgles_glIsEnabled (GL_COLOR_ARRAY);
1602 was_mat = jwzgles_glIsEnabled (GL_COLOR_MATERIAL);
1607 jwzgles_glEnableClientState (GL_NORMAL_ARRAY);
1613 jwzgles_glNormal3f (s->cnorm.x, s->cnorm.y, s->cnorm.z);
1614 jwzgles_glDisableClientState (GL_NORMAL_ARRAY);
1620 jwzgles_glEnableClientState (GL_TEXTURE_COORD_ARRAY);
1626 jwzgles_glTexCoord4f (s->ctex.s, s->ctex.t, s->ctex.r, s->ctex.q);
1627 jwzgles_glDisableClientState (GL_TEXTURE_COORD_ARRAY);
1633 jwzgles_glEnableClientState (GL_COLOR_ARRAY);
1639 jwzgles_glColor4f (s->ccolor.r, s->ccolor.g, s->ccolor.b, s->ccolor.a);
1640 jwzgles_glDisableClientState (GL_COLOR_ARRAY);
1643 jwzgles_glEnableClientState (GL_VERTEX_ARRAY);
1645 /* We translated the glMaterial calls to per-vertex colors, which are
1646 of the glColor sort, not the glMaterial sort, so automatically
1647 turn on material mapping. Maybe this is a bad idea.
1649 if (s->materialistic && !jwzgles_glIsEnabled (GL_COLOR_MATERIAL))
1652 jwzgles_glEnable (GL_COLOR_MATERIAL);
1657 jwzgles_glDrawArrays (s->mode, 0, s->count);
1659 # define RESET(VAR,FN,ARG) do { \
1660 if (is_##VAR != was_##VAR) { \
1661 if (was_##VAR) jwzgles_glEnable##FN (ARG); \
1662 else jwzgles_glDisable##FN (ARG); \
1664 RESET (norm, ClientState, GL_NORMAL_ARRAY);
1665 RESET (tex, ClientState, GL_TEXTURE_COORD_ARRAY);
1666 RESET (color, ClientState, GL_COLOR_ARRAY);
1667 RESET (mat, , GL_COLOR_MATERIAL);
1674 s->materialistic = 0;
1679 jwzgles_glCallList (int id)
1681 if (state->compiling_list)
1683 /* Yes, you can call lists inside of lists.
1684 Yes, recursion would be a mistake. */
1687 list_push ("glCallList", (list_fn_cb) &jwzgles_glCallList, PROTO_I, vv);
1694 state->replaying_list++;
1697 fprintf (stderr, "\n");
1698 LOG1 ("glCallList %d", id);
1701 Assert (id > 0 && id <= state->lists.count, "glCallList: bogus ID");
1702 L = &state->lists.lists[id-1];
1703 Assert (id == L->id, "glCallList corrupted");
1705 for (i = 0; i < L->count; i++)
1707 list_fn *F = &L->fns[i];
1708 list_fn_cb fn = F->fn;
1709 void_int *av = F->argv;
1713 LOG1 (" call %-12s", F->name);
1714 ((void (*) (void)) fn) ();
1718 if (fn == (list_fn_cb) &jwzgles_glBegin ||
1719 fn == (list_fn_cb) &jwzgles_glFrontFace ||
1720 fn == (list_fn_cb) &jwzgles_glEnable ||
1721 fn == (list_fn_cb) &jwzgles_glDisable ||
1722 fn == (list_fn_cb) &jwzgles_glEnableClientState ||
1723 fn == (list_fn_cb) &jwzgles_glDisableClientState ||
1724 fn == (list_fn_cb) &jwzgles_glShadeModel ||
1725 fn == (list_fn_cb) &jwzgles_glMatrixMode)
1726 LOG2 (" call %-12s %s", F->name, mode_desc (av[0].i));
1728 LOG2 (" call %-12s %d", F->name, av[0].i);
1729 ((void (*) (int)) fn) (av[0].i);
1733 LOG2 (" call %-12s %7.3f", F->name, av[0].f);
1734 ((void (*) (GLfloat)) fn) (av[0].f);
1738 if (fn == (list_fn_cb) &jwzgles_glBindTexture)
1739 LOG3 (" call %-12s %s %d", F->name,
1740 mode_desc (av[0].i), av[1].i);
1742 LOG3 (" call %-12s %d %d", F->name, av[0].i, av[1].i);
1743 ((void (*) (int, int)) fn) (av[0].i, av[1].i);
1747 LOG3 (" call %-12s %7.3f %7.3f", F->name, av[0].f, av[1].f);
1748 ((void (*) (GLfloat, GLfloat)) fn) (av[0].f, av[1].f);
1752 LOG3 (" call %-12s %s %7.3f", F->name,
1753 mode_desc (av[0].f), av[1].f);
1754 ((void (*) (GLint, GLfloat)) fn) (av[0].i, av[1].f);
1757 case PROTO_III: III:
1758 if (fn == (list_fn_cb) &jwzgles_glDrawArrays ||
1759 fn == (list_fn_cb) &jwzgles_glTexParameteri)
1760 LOG4 (" call %-12s %s %d %d", F->name,
1761 mode_desc (av[0].i), av[1].i, av[2].i);
1763 LOG4 (" call %-12s %d %d %d", F->name,
1764 av[0].i, av[1].i, av[2].i);
1765 ((void (*) (int, int, int)) fn) (av[0].i, av[1].i, av[2].i);
1769 LOG4 (" call %-12s %7.3f %7.3f %7.3f", F->name,
1770 av[0].f, av[1].f, av[2].f);
1771 ((void (*) (GLfloat, GLfloat, GLfloat)) fn)
1772 (av[0].f, av[1].f, av[2].f);
1776 LOG4 (" call %-12s %s %s %7.3f", F->name,
1777 mode_desc (av[0].i), mode_desc (av[1].i), av[2].f);
1778 ((void (*) (int, int, GLfloat)) fn) (av[0].i, av[1].i, av[2].f);
1782 LOG5 (" call %-12s %d %d %d %d", F->name,
1783 av[0].i, av[1].i, av[2].i, av[3].i);
1784 ((void (*) (int, int, int, int)) fn)
1785 (av[0].i, av[1].i, av[2].i, av[3].i);
1789 LOG5 (" call %-12s %7.3f %7.3f %7.3f %7.3f", F->name,
1790 av[0].f, av[1].f, av[2].f, av[3].f);
1791 ((void (*) (GLfloat, GLfloat, GLfloat, GLfloat)) fn)
1792 (av[0].f, av[1].f, av[2].f, av[3].f);
1802 LOG6 (" call %-12s %s %3.1f %3.1f %3.1f %3.1f", F->name,
1803 mode_desc (av[0].i),
1804 av[1].f, av[2].f, av[3].f, av[4].f);
1805 ((void (*) (int, const GLfloat *)) fn) (av[0].i, v);
1816 LOG7 (" call %-12s %s %-8s %3.1f %3.1f %3.1f %3.1f", F->name,
1817 mode_desc (av[0].i), mode_desc (av[1].i),
1818 av[2].f, av[3].f, av[4].f, av[5].f);
1819 ((void (*) (int, int, const GLfloat *)) fn)
1820 (av[0].i, av[1].i, v);
1831 LOG6 (" call %-12s %s %3d %3d %3d %3d", F->name,
1832 mode_desc (av[0].i),
1833 av[1].i, av[2].i, av[3].i, av[4].i);
1834 ((void (*) (int, const int *)) fn) (av[0].i, v);
1845 LOG7 (" call %-12s %s %-8s %3d %3d %3d %3d", F->name,
1846 mode_desc (av[0].i), mode_desc (av[1].i),
1847 av[2].i, av[3].i, av[4].i, av[5].i);
1848 ((void (*) (int, int, const int *)) fn)
1849 (av[0].i, av[1].i, v);
1854 restore_arrays (F, av[1].i + av[2].i);
1862 for (i = 0; i < countof(m); i++)
1864 LOG17 (" call %-12s ["
1865 "%8.3f %8.3f %8.3f %8.3f " "\n\t\t\t "
1866 "%8.3f %8.3f %8.3f %8.3f " "\n\t\t\t "
1867 "%8.3f %8.3f %8.3f %8.3f " "\n\t\t\t "
1868 "%8.3f %8.3f %8.3f %8.3f ]",
1870 m[0], m[1], m[2], m[3],
1871 m[4], m[5], m[6], m[7],
1872 m[8], m[9], m[10], m[11],
1873 m[12], m[13], m[14], m[15]);
1874 ((void (*) (GLfloat *)) fn) (m);
1879 Assert (0, "bogus prototype");
1884 LOG1 ("glCallList %d done\n", id);
1886 state->replaying_list--;
1887 Assert (state->replaying_list >= 0, "glCallList corrupted");
1892 /* When we save a call to glDrawArrays into a display list, we also need to
1893 save the prevailing copy of the arrays that it will use, and restore them
1897 save_arrays (list_fn *F, int count)
1900 draw_array *A = (draw_array *) calloc (4, sizeof (*A));
1901 Assert (A, "out of memory");
1903 /* if (state->set.count > 0) */
1905 glGetIntegerv (GL_VERTEX_ARRAY_SIZE, &A[i].size);
1906 glGetIntegerv (GL_VERTEX_ARRAY_TYPE, &A[i].type);
1907 glGetIntegerv (GL_VERTEX_ARRAY_STRIDE, &A[i].stride);
1908 glGetPointerv (GL_VERTEX_ARRAY_POINTER, &A[i].data);
1909 CHECK("glGetPointerv");
1910 copy_array_data (&A[i], count, "vert");
1914 if (state->set.ncount > 1)
1917 glGetIntegerv (GL_NORMAL_ARRAY_TYPE, &A[i].type);
1918 glGetIntegerv (GL_NORMAL_ARRAY_STRIDE, &A[i].stride);
1919 glGetPointerv (GL_NORMAL_ARRAY_POINTER, &A[i].data);
1920 CHECK("glGetPointerv");
1921 copy_array_data (&A[i], count, "norm");
1925 if (state->set.tcount > 1)
1927 glGetIntegerv (GL_TEXTURE_COORD_ARRAY_SIZE, &A[i].size);
1928 glGetIntegerv (GL_TEXTURE_COORD_ARRAY_TYPE, &A[i].type);
1929 glGetIntegerv (GL_TEXTURE_COORD_ARRAY_STRIDE, &A[i].stride);
1930 glGetPointerv (GL_TEXTURE_COORD_ARRAY_POINTER, &A[i].data);
1931 CHECK("glGetPointerv");
1932 copy_array_data (&A[i], count, "tex ");
1936 if (state->set.ccount > 1)
1938 glGetIntegerv (GL_COLOR_ARRAY_SIZE, &A[i].size);
1939 glGetIntegerv (GL_COLOR_ARRAY_TYPE, &A[i].type);
1940 glGetIntegerv (GL_COLOR_ARRAY_STRIDE, &A[i].stride);
1941 glGetPointerv (GL_COLOR_ARRAY_POINTER, &A[i].data);
1942 CHECK("glGetPointerv");
1943 copy_array_data (&A[i], count, "col ");
1946 /* Freed by glDeleteLists. */
1948 Assert (!F->arrays, "save_arrays corrupted");
1956 dump_array_data (draw_array *A, int count,
1957 const char *action, const char *name, const void *old)
1959 int bytes = count * A->stride;
1961 Assert (bytes == A->bytes, "array data corrupted");
1963 fprintf (stderr, "jwzgles: %s %s %d %s %2d, %4d = %5d @ %lX",
1965 A->size, mode_desc(A->type), A->stride,
1966 count, bytes, (unsigned long) A->data);
1968 fprintf (stderr, " / %lX", (unsigned long) old);
1969 fprintf (stderr, "\n");
1973 unsigned char *b = (unsigned char *) A->data;
1975 for (i = 0; i < count; i++)
1978 GLfloat *f = (GLfloat *) b;
1980 if (s == 0) s = 3; /* normals */
1981 fprintf (stderr, "jwzgles: ");
1982 for (j = 0; j < s; j++)
1983 fprintf (stderr, " %7.3f", f[j]);
1984 fprintf (stderr, "\n");
1992 dump_direct_array_data (int count)
1996 if (jwzgles_glIsEnabled (GL_VERTEX_ARRAY))
1998 glGetIntegerv (GL_VERTEX_ARRAY_SIZE, &A.size);
1999 glGetIntegerv (GL_VERTEX_ARRAY_TYPE, &A.type);
2000 glGetIntegerv (GL_VERTEX_ARRAY_STRIDE, &A.stride);
2001 glGetPointerv (GL_VERTEX_ARRAY_POINTER, &A.data);
2002 A.bytes = count * A.stride;
2003 dump_array_data (&A, count, "direct", "vertex ", 0);
2005 if (jwzgles_glIsEnabled (GL_NORMAL_ARRAY))
2008 glGetIntegerv (GL_NORMAL_ARRAY_TYPE, &A.type);
2009 glGetIntegerv (GL_NORMAL_ARRAY_STRIDE, &A.stride);
2010 glGetPointerv (GL_NORMAL_ARRAY_POINTER, &A.data);
2011 A.bytes = count * A.stride;
2012 dump_array_data (&A, count, "direct", "normal ", 0);
2014 if (jwzgles_glIsEnabled (GL_TEXTURE_COORD_ARRAY))
2016 glGetIntegerv (GL_TEXTURE_COORD_ARRAY_SIZE, &A.size);
2017 glGetIntegerv (GL_TEXTURE_COORD_ARRAY_TYPE, &A.type);
2018 glGetIntegerv (GL_TEXTURE_COORD_ARRAY_STRIDE, &A.stride);
2019 glGetPointerv (GL_TEXTURE_COORD_ARRAY_POINTER, &A.data);
2020 A.bytes = count * A.stride;
2021 dump_array_data (&A, count, "direct", "texture", 0);
2023 if (jwzgles_glIsEnabled (GL_COLOR_ARRAY))
2025 glGetIntegerv (GL_COLOR_ARRAY_SIZE, &A.size);
2026 glGetIntegerv (GL_COLOR_ARRAY_TYPE, &A.type);
2027 glGetIntegerv (GL_COLOR_ARRAY_STRIDE, &A.stride);
2028 glGetPointerv (GL_COLOR_ARRAY_POINTER, &A.data);
2029 A.bytes = count * A.stride;
2030 dump_array_data (&A, count, "direct", "color ", 0);
2038 copy_array_data (draw_array *A, int count, const char *name)
2040 /* Instead of just memcopy'ing the whole array and obeying its previous
2041 'stride' value, we make up a more compact array. This is because if
2042 the same array data is being used with multiple component types,
2043 e.g. with glInterleavedArrays, we don't want to copy all of the
2044 data multiple times.
2046 int stride2, bytes, i, j;
2051 const unsigned char *IB;
2054 if (! A->data) return;
2056 Assert (A->size >= 2 && A->size <= 4, "bogus array size");
2059 case GL_FLOAT: stride2 = A->size * sizeof(GLfloat); break;
2060 case GL_UNSIGNED_BYTE: stride2 = A->size; break;
2061 default: Assert (0, "bogus array type"); break;
2064 bytes = count * stride2;
2065 Assert (bytes > 0, "bogus array count or stride");
2066 Assert (A->data, "missing array data");
2067 data2 = (void *) malloc (bytes);
2068 Assert (data2, "out of memory");
2070 IB = (const unsigned char *) A->data;
2071 OB = (unsigned char *) data2;
2072 IF = (const GLfloat *) A->data;
2073 OF = (GLfloat *) data2;
2077 for (i = 0; i < count; i++)
2079 for (j = 0; j < A->size; j++)
2081 IF = (const GLfloat *) (((const unsigned char *) IF) + A->stride);
2084 case GL_UNSIGNED_BYTE:
2085 for (i = 0; i < count; i++)
2087 for (j = 0; j < A->size; j++)
2093 Assert (0, "bogus array type");
2100 A->stride = stride2;
2103 dump_array_data (A, count, "saved", name, old);
2109 restore_arrays (list_fn *F, int count)
2112 draw_array *A = F->arrays;
2113 Assert (A, "missing array");
2115 for (i = 0; i < 4; i++)
2118 if (! A[i].data) continue;
2120 case 0: glVertexPointer (A[i].size, A[i].type, A[i].stride, A[i].data);
2122 CHECK("glVertexPointer");
2124 case 1: glNormalPointer ( A[i].type, A[i].stride, A[i].data);
2126 CHECK("glNormalPointer");
2128 case 2: glTexCoordPointer(A[i].size, A[i].type, A[i].stride, A[i].data);
2130 CHECK("glTexCoordPointer");
2132 case 3: glColorPointer (A[i].size, A[i].type, A[i].stride, A[i].data);
2134 CHECK("glColorPointer");
2136 default: Assert (0, "wat"); break;
2140 dump_array_data (&A[i], count, "restored", name, 0);
2147 jwzgles_glDrawArrays (GLuint mode, GLuint first, GLuint count)
2149 if (state->compiling_list)
2155 list_push ("glDrawArrays", (list_fn_cb) &jwzgles_glDrawArrays,
2161 if (! state->replaying_list) {
2162 LOG4("direct %-12s %d %d %d", "glDrawArrays", mode, first, count);
2163 dump_direct_array_data (first + count);
2166 glDrawArrays (mode, first, count); /* the real one */
2167 CHECK("glDrawArrays");
2173 jwzgles_glInterleavedArrays (GLenum format, GLsizei stride, const void *data)
2175 /* We can implement this by calling the various *Pointer functions
2176 with offsets into the same data, taking advantage of stride.
2178 const unsigned char *c = (const unsigned char *) data;
2180 # define F sizeof(GLfloat)
2182 Assert (!state->compiling_verts,
2183 "glInterleavedArrays not allowed inside glBegin");
2185 jwzgles_glEnableClientState (GL_VERTEX_ARRAY);
2187 if (!state->replaying_list)
2188 LOG4 ("%sglInterleavedArrays %s %d %lX",
2189 (state->compiling_list || state->replaying_list ? " " : ""),
2190 mode_desc (format), stride, (unsigned long) data);
2194 glVertexPointer (2, GL_FLOAT, stride, c);
2195 CHECK("glVertexPointer");
2196 if (!state->replaying_list)
2197 LOG3 ("%s -> glVertexPointer 2 FLOAT %d %lX",
2198 (state->compiling_list || state->replaying_list ? " " : ""),
2199 stride, (unsigned long) c);
2202 glVertexPointer (3, GL_FLOAT, stride, c);
2203 CHECK("glVertexPointer");
2204 if (!state->replaying_list)
2205 LOG3 ("%s -> glVertexPointer 3 FLOAT %d %lX",
2206 (state->compiling_list || state->replaying_list ? " " : ""),
2207 stride, (unsigned long) c);
2212 jwzgles_glEnableClientState (GL_COLOR_ARRAY);
2213 glColorPointer (4, GL_UNSIGNED_BYTE, stride, c);
2214 CHECK("glColorPointer");
2215 c += 4*B; /* #### might be incorrect float-aligned address */
2216 glVertexPointer (2, GL_FLOAT, stride, c);
2221 jwzgles_glEnableClientState (GL_COLOR_ARRAY);
2222 glColorPointer (4, GL_UNSIGNED_BYTE, stride, c);
2223 CHECK("glColorPointer");
2225 glVertexPointer (3, GL_FLOAT, stride, c);
2226 CHECK("glVertexPointer");
2231 jwzgles_glEnableClientState (GL_COLOR_ARRAY);
2232 glColorPointer (3, GL_FLOAT, stride, c);
2233 CHECK("glColorPointer");
2235 glVertexPointer (3, GL_FLOAT, stride, c);
2236 CHECK("glVertexPointer");
2241 jwzgles_glEnableClientState (GL_NORMAL_ARRAY);
2242 glNormalPointer (GL_FLOAT, stride, c);
2243 CHECK("glNormalPointer");
2244 if (!state->replaying_list)
2245 LOG3 ("%s -> glNormalPointer FLOAT %d %lX",
2246 (state->compiling_list || state->replaying_list ? " " : ""),
2247 stride, (unsigned long) c);
2249 glVertexPointer (3, GL_FLOAT, stride, c);
2250 CHECK("glVertexPointer");
2251 if (!state->replaying_list)
2252 LOG3 ("%s -> glVertexPointer 3 FLOAT %d %lX",
2253 (state->compiling_list || state->replaying_list ? " " : ""),
2254 stride, (unsigned long) c);
2256 case GL_C4F_N3F_V3F:
2258 stride = 4*F + 3*F + 3*F;
2259 jwzgles_glEnableClientState (GL_COLOR_ARRAY);
2260 glColorPointer (4, GL_FLOAT, stride, c);
2261 CHECK("glColorPointer");
2263 jwzgles_glEnableClientState (GL_NORMAL_ARRAY);
2264 glNormalPointer (GL_FLOAT, stride, c);
2265 CHECK("glNormalPointer");
2267 glVertexPointer (3, GL_FLOAT, stride, c);
2268 CHECK("glVertexPointer");
2273 jwzgles_glEnableClientState (GL_TEXTURE_COORD_ARRAY);
2274 glTexCoordPointer (2, GL_FLOAT, stride, c);
2275 CHECK("glTexCoordPointer");
2277 glVertexPointer (3, GL_FLOAT, stride, c);
2278 CHECK("glVertexPointer");
2283 jwzgles_glEnableClientState (GL_TEXTURE_COORD_ARRAY);
2284 glTexCoordPointer (4, GL_FLOAT, stride, c);
2285 CHECK("glTexCoordPointer");
2287 glVertexPointer (4, GL_FLOAT, stride, c);
2288 CHECK("glVertexPointer");
2290 case GL_T2F_C4UB_V3F:
2292 stride = 2*F + 4*B + 3*F;
2293 jwzgles_glEnableClientState (GL_TEXTURE_COORD_ARRAY);
2294 glTexCoordPointer (2, GL_FLOAT, stride, c);
2295 CHECK("glTexCoordPointer");
2297 jwzgles_glEnableClientState (GL_COLOR_ARRAY);
2298 glColorPointer (4, GL_UNSIGNED_BYTE, stride, c);
2299 CHECK("glColorPointer");
2301 glVertexPointer (3, GL_FLOAT, stride, c);
2302 CHECK("glVertexPointer");
2304 case GL_T2F_C3F_V3F:
2306 stride = 2*F + 3*F + 3*F;
2307 jwzgles_glEnableClientState (GL_TEXTURE_COORD_ARRAY);
2308 glTexCoordPointer (2, GL_FLOAT, stride, c);
2309 CHECK("glTexCoordPointer");
2311 jwzgles_glEnableClientState (GL_COLOR_ARRAY);
2312 glColorPointer (3, GL_FLOAT, stride, c);
2313 CHECK("glColorPointer");
2315 glVertexPointer (3, GL_FLOAT, stride, c);
2316 CHECK("glVertexPointer");
2318 case GL_T2F_N3F_V3F:
2320 stride = 2*F + 3*F + 3*F;
2321 jwzgles_glEnableClientState (GL_TEXTURE_COORD_ARRAY);
2322 glTexCoordPointer (2, GL_FLOAT, stride, c);
2323 CHECK("glTexCoordPointer");
2325 jwzgles_glEnableClientState (GL_NORMAL_ARRAY);
2326 glNormalPointer (GL_FLOAT, stride, c);
2327 CHECK("glNormalPointer");
2329 glVertexPointer (3, GL_FLOAT, stride, c);
2330 CHECK("glVertexPointer");
2332 case GL_T2F_C4F_N3F_V3F:
2334 stride = 2*F + 4*F + 3*F + 3*F;
2335 jwzgles_glEnableClientState (GL_TEXTURE_COORD_ARRAY);
2336 glTexCoordPointer (2, GL_FLOAT, stride, c);
2337 CHECK("glTexCoordPointer");
2339 jwzgles_glEnableClientState (GL_COLOR_ARRAY);
2340 glColorPointer (3, GL_FLOAT, stride, c);
2341 CHECK("glColorPointer");
2343 jwzgles_glEnableClientState (GL_NORMAL_ARRAY);
2344 glNormalPointer (GL_FLOAT, stride, c);
2345 CHECK("glNormalPointer");
2347 glVertexPointer (3, GL_FLOAT, stride, c);
2348 CHECK("glVertexPointer");
2350 case GL_T4F_C4F_N3F_V4F:
2352 stride = 4*F + 4*F + 3*F + 4*F;
2353 jwzgles_glEnableClientState (GL_TEXTURE_COORD_ARRAY);
2354 glTexCoordPointer (4, GL_FLOAT, stride, c);
2355 CHECK("glTexCoordPointer");
2357 jwzgles_glEnableClientState (GL_COLOR_ARRAY);
2358 glColorPointer (4, GL_FLOAT, stride, c);
2359 CHECK("glColorPointer");
2361 jwzgles_glEnableClientState (GL_NORMAL_ARRAY);
2362 glNormalPointer (GL_FLOAT, stride, c);
2363 CHECK("glNormalPointer");
2365 glVertexPointer (3, GL_FLOAT, stride, c);
2366 CHECK("glVertexPointer");
2369 Assert (0, "glInterleavedArrays: bogus format");
2380 jwzgles_glEnableClientState (GLuint cap)
2382 if (state->compiling_list)
2386 list_push ("glEnableClientState",
2387 (list_fn_cb) &jwzgles_glEnableClientState,
2392 if (! state->replaying_list)
2393 LOG2 ("direct %-12s %s", "glEnableClientState", mode_desc(cap));
2394 glEnableClientState (cap); /* the real one */
2395 CHECK("glEnableClientState");
2399 case GL_NORMAL_ARRAY:
2400 state->set.ncount += 2;
2401 state->enabled |= ISENABLED_NORM_ARRAY;
2403 case GL_TEXTURE_COORD_ARRAY:
2404 state->set.tcount += 2;
2405 state->enabled |= ISENABLED_TEX_ARRAY;
2407 case GL_COLOR_ARRAY:
2408 state->set.ccount += 2;
2409 state->enabled |= ISENABLED_COLOR_ARRAY;
2417 jwzgles_glDisableClientState (GLuint cap)
2419 if (state->compiling_list)
2423 list_push ("glDisableClientState",
2424 (list_fn_cb) &jwzgles_glDisableClientState,
2429 if (! state->replaying_list)
2430 LOG2 ("direct %-12s %s", "glDisableClientState", mode_desc(cap));
2431 glDisableClientState (cap); /* the real one */
2432 CHECK("glDisableClientState");
2436 case GL_NORMAL_ARRAY:
2437 state->set.ncount = 0;
2438 state->enabled &= ~ISENABLED_NORM_ARRAY;
2440 case GL_TEXTURE_COORD_ARRAY:
2441 state->set.tcount = 0;
2442 state->enabled &= ~ISENABLED_TEX_ARRAY;
2444 case GL_COLOR_ARRAY:
2445 state->set.ccount = 0;
2446 state->enabled &= ~ISENABLED_COLOR_ARRAY;
2455 jwzgles_glMultMatrixf (const GLfloat *m)
2457 Assert (!state->compiling_verts,
2458 "glMultMatrixf not allowed inside glBegin");
2459 if (state->compiling_list)
2463 for (i = 0; i < countof(vv); i++)
2465 list_push ("glMultMatrixf", (list_fn_cb) &jwzgles_glMultMatrixf,
2470 if (! state->replaying_list)
2471 LOG1 ("direct %-12s", "glMultMatrixf");
2472 glMultMatrixf (m); /* the real one */
2473 CHECK("glMultMatrixf");
2479 jwzgles_glClearIndex(GLfloat c)
2481 /* Does GLES even do indexed color? */
2482 Assert (0, "glClearIndex unimplemented");
2487 jwzgles_glBitmap (GLsizei width, GLsizei height, GLfloat xorig, GLfloat yorig,
2488 GLfloat xmove, GLfloat ymove, const GLubyte *bitmap)
2490 Assert (0, "glBitmap unimplemented");
2494 jwzgles_glPushAttrib(int flags)
2496 Assert (0, "glPushAttrib unimplemented");
2500 jwzgles_glPopAttrib(void)
2502 Assert (0, "glPopAttrib unimplemented");
2506 /* These are needed for object hit detection in pinion.
2507 Might need to rewrite that code entirely. Punt for now.
2510 jwzgles_glInitNames (void)
2512 /* Assert (0, "glInitNames unimplemented");*/
2516 jwzgles_glPushName (GLuint name)
2518 /* Assert (0, "glPushName unimplemented");*/
2522 jwzgles_glPopName (void)
2524 /* Assert (0, "glPopName unimplemented");*/
2529 jwzgles_glRenderMode (GLuint mode)
2531 /* Assert (0, "glRenderMode unimplemented");*/
2536 jwzgles_glSelectBuffer (GLsizei size, GLuint *buf)
2538 /* Assert (0, "glSelectBuffer unimplemented");*/
2543 jwzgles_glGenTextures (GLuint n, GLuint *ret)
2545 Assert (!state->compiling_verts,
2546 "glGenTextures not allowed inside glBegin");
2547 /* technically legal, but stupid! */
2548 Assert (!state->compiling_list,
2549 "glGenTextures not allowed inside glNewList");
2550 if (! state->replaying_list)
2551 LOG1 ("direct %-12s", "glGenTextures");
2552 glGenTextures (n, ret); /* the real one */
2553 CHECK("glGenTextures");
2557 /* return the next larger power of 2. */
2562 while (i < value) i <<= 1;
2567 jwzgles_glTexImage1D (GLenum target, GLint level,
2568 GLint internalFormat,
2569 GLsizei width, GLint border,
2570 GLenum format, GLenum type,
2571 const GLvoid *pixels)
2573 Assert (!state->compiling_verts, "glTexImage1D not allowed inside glBegin");
2574 /* technically legal, but stupid! */
2575 Assert (!state->compiling_list, "glTexImage1D inside glNewList");
2576 Assert (width == to_pow2(width), "width must be a power of 2");
2577 Assert (0, "glTexImage1D unimplemented"); /* does not exist in GLES */
2581 jwzgles_glTexImage2D (GLenum target,
2583 GLint internalFormat,
2591 GLvoid *d2 = (GLvoid *) data;
2592 Assert (!state->compiling_verts, "glTexImage2D not allowed inside glBegin");
2593 Assert (!state->compiling_list, /* technically legal, but stupid! */
2594 "glTexImage2D not allowed inside glNewList");
2596 Assert (width == to_pow2(width), "width must be a power of 2");
2597 Assert (height == to_pow2(height), "height must be a power of 2");
2599 /* OpenGLES no longer supports "4" as a synonym for "RGBA". */
2600 switch (internalFormat) {
2601 case 1: internalFormat = GL_LUMINANCE; break;
2602 case 2: internalFormat = GL_LUMINANCE_ALPHA; break;
2603 case 3: internalFormat = GL_RGB; break;
2604 case 4: internalFormat = GL_RGBA; break;
2607 /* GLES does not let us omit the data pointer to create a blank texture. */
2610 d2 = (GLvoid *) calloc (1, width * height * sizeof(GLfloat) * 4);
2611 Assert (d2, "out of memory");
2614 if (internalFormat == GL_RGB && format == GL_RGBA)
2615 internalFormat = GL_RGBA; /* WTF */
2617 if (! state->replaying_list)
2618 LOG10 ("direct %-12s %s %d %s %d %d %d %s %s 0x%lX", "glTexImage2D",
2619 mode_desc(target), level, mode_desc(internalFormat),
2620 width, height, border, mode_desc(format), mode_desc(type),
2621 (unsigned long) d2);
2622 glTexImage2D (target, level, internalFormat, width, height, border,
2623 format, type, d2); /* the real one */
2624 CHECK("glTexImage2D");
2626 if (d2 != data) free (d2);
2630 jwzgles_glTexSubImage2D (GLenum target, GLint level,
2631 GLint xoffset, GLint yoffset,
2632 GLsizei width, GLsizei height,
2633 GLenum format, GLenum type,
2634 const GLvoid *pixels)
2636 Assert (!state->compiling_verts,
2637 "glTexSubImage2D not allowed inside glBegin");
2638 Assert (!state->compiling_list, /* technically legal, but stupid! */
2639 "glTexSubImage2D not allowed inside glNewList");
2641 if (! state->replaying_list)
2642 LOG10 ("direct %-12s %s %d %d %d %d %d %s %s 0x%lX", "glTexSubImage2D",
2643 mode_desc(target), level, xoffset, yoffset, width, height,
2644 mode_desc (format), mode_desc (type), (unsigned long) pixels);
2645 glTexSubImage2D (target, level, xoffset, yoffset, width, height,
2646 format, type, pixels); /* the real one */
2647 CHECK("glTexSubImage2D");
2651 jwzgles_glCopyTexImage2D (GLenum target, GLint level, GLenum internalformat,
2652 GLint x, GLint y, GLsizei width, GLsizei height,
2655 Assert (!state->compiling_verts,
2656 "glCopyTexImage2D not allowed inside glBegin");
2657 Assert (!state->compiling_list, /* technically legal, but stupid! */
2658 "glCopyTexImage2D not allowed inside glNewList");
2659 if (! state->replaying_list)
2660 LOG9 ("direct %-12s %s %d %s %d %d %d %d %d", "glCopyTexImage2D",
2661 mode_desc(target), level, mode_desc(internalformat),
2662 x, y, width, height, border);
2663 glCopyTexImage2D (target, level, internalformat, x, y, width, height,
2664 border); /* the real one */
2665 CHECK("glCopyTexImage2D");
2670 jwzgles_glTexGenfv (GLenum coord, GLenum pname, const GLfloat *params)
2672 /* OpenGLES doesn't have this at all!
2673 "Oh, just rewrite that code to use GPU shaders", they say.
2674 How fucking convenient.
2676 So, when this is enabled, we could emit a GL_TEXTURE_COORD_ARRAY
2677 and compute coords for each vertex in the current GL_VERTEX_ARRAY
2678 as per http://www.opengl.org/wiki/Mathematics_of_glTexGen
2679 but holy shit, what a pain in the ass!
2681 For GL_OBJECT_LINEAR, we can just re-use the vertex array as
2682 the texture array, using a proper stride. That's hardly worth
2683 the effort, though, because bouncingcow is the only hack that
2684 uses that, and not even by default.
2686 Assert (coord == GL_S || coord == GL_T, "glTexGenfv: unimplemented coord");
2688 /* This is probably default-ish, so do nothing. */
2689 if (pname == GL_EYE_PLANE) return;
2691 Assert (pname == GL_TEXTURE_GEN_MODE, "glTexGenfv: unimplemented name");
2692 Assert (params[0] == GL_EYE_LINEAR, "glTexGenfv: unimplemented mode");
2696 jwzgles_glTexGeni (GLenum coord, GLenum pname, GLint param)
2699 jwzgles_glTexGenfv (coord, pname, &v);
2704 jwzgles_gluBuild2DMipmaps (GLenum target,
2705 GLint internalFormat,
2712 /* Not really bothering with mipmapping; only making one level.
2713 Note that this required a corresponding hack in glTexParameterf().
2716 int w2 = to_pow2(width);
2717 int h2 = to_pow2(height);
2719 void *d2 = (void *) data;
2721 /* OpenGLES no longer supports "4" as a synonym for "RGBA". */
2722 switch (internalFormat) {
2723 case 1: internalFormat = GL_LUMINANCE; break;
2724 case 2: internalFormat = GL_LUMINANCE_ALPHA; break;
2725 case 3: internalFormat = GL_RGB; break;
2726 case 4: internalFormat = GL_RGBA; break;
2729 /* if (w2 < h2) w2 = h2;
2730 if (h2 < w2) h2 = w2;*/
2732 if (w2 != width || h2 != height)
2734 /* Scale up the image bits to fit the power-of-2 texture.
2735 We have to do this because the mipmap API assumes that
2736 the texture bits go to texture coordinates 1.0 x 1.0.
2737 This could be more efficient, but it doesn't happen often.
2739 int istride = (format == GL_RGBA ? 4 : 3);
2741 int ibpl = istride * width;
2742 int obpl = ostride * w2;
2744 const unsigned char *in = (unsigned char *) data;
2745 unsigned char *out = (void *) malloc (h2 * obpl);
2746 Assert (out, "out of memory");
2749 for (oy = 0; oy < h2; oy++)
2751 int iy = oy * height / h2;
2752 const unsigned char *iline = in + (iy * ibpl);
2753 unsigned char *oline = out + (oy * obpl);
2755 for (ox = 0; ox < w2; ox++)
2757 int ix = ox * width / w2;
2758 const unsigned char *i = iline + (ix * istride);
2759 unsigned char *o = oline + (ox * ostride);
2760 *o++ = *i++; /* R */
2761 *o++ = *i++; /* G */
2762 *o++ = *i++; /* B */
2763 *o++ = (istride == 4 ? *i : 0xFF); /* A */
2768 internalFormat = GL_RGBA;
2772 jwzgles_glTexImage2D (target, 0, internalFormat, w2, h2, 0,
2774 if (d2 != data) free (d2);
2781 jwzgles_glRectf (GLfloat x1, GLfloat y1, GLfloat x2, GLfloat y2)
2783 jwzgles_glBegin (GL_POLYGON);
2784 jwzgles_glVertex2f (x1, y1);
2785 jwzgles_glVertex2f (x2, y1);
2786 jwzgles_glVertex2f (x2, y2);
2787 jwzgles_glVertex2f (x1, y2);
2792 jwzgles_glRecti (GLint x1, GLint y1, GLint x2, GLint y2)
2794 jwzgles_glRectf (x1, y1, x2, y2);
2798 jwzgles_glClearDepth (GLfloat d)
2800 /* Not sure what to do here */
2801 Assert (d == 1.0, "glClearDepth unimplemented");
2806 jwzgles_glEnable (GLuint bit)
2808 Assert (!state->compiling_verts, "glEnable not allowed inside glBegin");
2809 if (state->compiling_list)
2813 list_push ("glEnable", (list_fn_cb) &jwzgles_glEnable, PROTO_I, vv);
2817 if (! state->replaying_list)
2818 LOG2 ("direct %-12s %s", "glEnable", mode_desc(bit));
2819 glEnable (bit); /* the real one */
2823 case GL_TEXTURE_2D: state->enabled |= ISENABLED_TEXTURE_2D; break;
2824 case GL_TEXTURE_GEN_S: state->enabled |= ISENABLED_TEXTURE_GEN_S; break;
2825 case GL_TEXTURE_GEN_T: state->enabled |= ISENABLED_TEXTURE_GEN_T; break;
2826 case GL_LIGHTING: state->enabled |= ISENABLED_LIGHTING; break;
2827 case GL_BLEND: state->enabled |= ISENABLED_BLEND; break;
2828 case GL_DEPTH_TEST: state->enabled |= ISENABLED_DEPTH_TEST; break;
2829 case GL_CULL_FACE: state->enabled |= ISENABLED_CULL_FACE; break;
2830 case GL_NORMALIZE: state->enabled |= ISENABLED_NORMALIZE; break;
2831 case GL_FOG: state->enabled |= ISENABLED_FOG; break;
2832 case GL_COLOR_MATERIAL: state->enabled |= ISENABLED_COLMAT; break;
2834 /* Do these work with glEnable or only with glEnableClientState? */
2835 case GL_VERTEX_ARRAY: state->enabled |= ISENABLED_VERT_ARRAY; break;
2836 case GL_NORMAL_ARRAY: state->enabled |= ISENABLED_NORM_ARRAY; break;
2837 case GL_TEXTURE_COORD_ARRAY: state->enabled |= ISENABLED_TEX_ARRAY;break;
2838 case GL_COLOR_ARRAY: state->enabled |= ISENABLED_COLOR_ARRAY; break;
2847 jwzgles_glDisable (GLuint bit)
2849 Assert (!state->compiling_verts, "glDisable not allowed inside glBegin");
2850 if (state->compiling_list)
2854 list_push ("glDisable", (list_fn_cb) &jwzgles_glDisable, PROTO_I, vv);
2858 if (! state->replaying_list)
2859 LOG2 ("direct %-12s %s", "glDisable", mode_desc(bit));
2860 glDisable (bit); /* the real one */
2864 case GL_TEXTURE_2D: state->enabled &= ~ISENABLED_TEXTURE_2D; break;
2865 case GL_TEXTURE_GEN_S: state->enabled &= ~ISENABLED_TEXTURE_GEN_S; break;
2866 case GL_TEXTURE_GEN_T: state->enabled &= ~ISENABLED_TEXTURE_GEN_T; break;
2867 case GL_LIGHTING: state->enabled &= ~ISENABLED_LIGHTING; break;
2868 case GL_BLEND: state->enabled &= ~ISENABLED_BLEND; break;
2869 case GL_DEPTH_TEST: state->enabled &= ~ISENABLED_DEPTH_TEST; break;
2870 case GL_CULL_FACE: state->enabled &= ~ISENABLED_CULL_FACE; break;
2871 case GL_NORMALIZE: state->enabled &= ~ISENABLED_NORMALIZE; break;
2872 case GL_FOG: state->enabled &= ~ISENABLED_FOG; break;
2873 case GL_COLOR_MATERIAL: state->enabled &= ~ISENABLED_COLMAT; break;
2875 /* Do these work with glEnable or only with glEnableClientState? */
2876 case GL_VERTEX_ARRAY: state->enabled &= ~ISENABLED_VERT_ARRAY; break;
2877 case GL_NORMAL_ARRAY: state->enabled &= ~ISENABLED_NORM_ARRAY; break;
2878 case GL_TEXTURE_COORD_ARRAY: state->enabled &= ~ISENABLED_TEX_ARRAY;break;
2879 case GL_COLOR_ARRAY: state->enabled &= ~ISENABLED_COLOR_ARRAY; break;
2888 jwzgles_glIsEnabled (GLuint bit)
2891 Assert (!state->compiling_verts, "glIsEnabled not allowed inside glBegin");
2892 Assert (!state->compiling_list, "glIsEnabled not allowed inside glNewList");
2895 case GL_TEXTURE_2D: return !!(state->enabled & ISENABLED_TEXTURE_2D);
2896 case GL_TEXTURE_GEN_S: return !!(state->enabled & ISENABLED_TEXTURE_GEN_S);
2897 case GL_TEXTURE_GEN_T: return !!(state->enabled & ISENABLED_TEXTURE_GEN_T);
2898 case GL_LIGHTING: return !!(state->enabled & ISENABLED_LIGHTING);
2899 case GL_BLEND: return !!(state->enabled & ISENABLED_BLEND);
2900 case GL_DEPTH_TEST: return !!(state->enabled & ISENABLED_DEPTH_TEST);
2901 case GL_CULL_FACE: return !!(state->enabled & ISENABLED_CULL_FACE);
2902 case GL_NORMALIZE: return !!(state->enabled & ISENABLED_NORMALIZE);
2903 case GL_FOG: return !!(state->enabled & ISENABLED_FOG);
2904 case GL_COLOR_MATERIAL: return !!(state->enabled & ISENABLED_COLMAT);
2906 /* Do these work with glEnable or only with glEnableClientState?
2907 We need to query them, and there is no glIsClientStateEnabled.
2909 case GL_VERTEX_ARRAY: return !!(state->enabled & ISENABLED_VERT_ARRAY);
2910 case GL_NORMAL_ARRAY: return !!(state->enabled & ISENABLED_NORM_ARRAY);
2911 case GL_TEXTURE_COORD_ARRAY: return !!(state->enabled & ISENABLED_TEX_ARRAY);
2912 case GL_COLOR_ARRAY: return !!(state->enabled & ISENABLED_COLOR_ARRAY);
2913 default: Assert (0, "glIsEnabled unimplemented bit"); break;
2918 /* The spec says that OpenGLES 1.x doesn't implement glGetFloatv.
2919 Were this true, it would suck, for it would mean that there was no
2920 way to retrieve the prevailing matrixes. To implement this, we'd
2921 have to keep track of them all on the client side by combining in
2922 all the actions of glMultMatrixf, glRotatef, etc.
2924 However, Apple's iOS OpenGLES *does* provide glGetFloatv!
2927 jwzgles_glGetFloatv (GLenum pname, GLfloat *params)
2929 if (! state->replaying_list)
2930 LOG2 ("direct %-12s %s", "glGetFloatv", mode_desc(pname));
2931 glGetFloatv (pname, params); /* the real one */
2932 CHECK("glGetFloatv");
2936 /* Likewise: not supposed to be there, but it is. */
2938 jwzgles_glGetPointerv (GLenum pname, GLvoid *params)
2940 if (! state->replaying_list)
2941 LOG2 ("direct %-12s %s", "glGetPointerv", mode_desc(pname));
2942 glGetPointerv (pname, params); /* the real one */
2943 CHECK("glGetPointerv");
2947 /* How many cells are written into the *params array.
2948 We need to know this to avoid smashing the caller's stack
2949 if they asked for a single-value parameter.
2952 glGet_ret_count (GLenum pname)
2955 /*case GL_COLOR_MATRIX: */
2956 case GL_MODELVIEW_MATRIX:
2957 case GL_PROJECTION_MATRIX:
2958 case GL_TEXTURE_MATRIX:
2959 /*case GL_TRANSPOSE_COLOR_MATRIX: */
2960 /*case GL_TRANSPOSE_MODELVIEW_MATRIX: */
2961 /*case GL_TRANSPOSE_PROJECTION_MATRIX: */
2962 /*case GL_TRANSPOSE_TEXTURE_MATRIX: */
2964 /*case GL_ACCUM_CLEAR_VALUE: */
2965 /*case GL_BLEND_COLOR: */
2966 case GL_COLOR_CLEAR_VALUE:
2967 case GL_COLOR_WRITEMASK:
2968 case GL_CURRENT_COLOR:
2969 /*case GL_CURRENT_RASTER_COLOR: */
2970 /*case GL_CURRENT_RASTER_POSITION: */
2971 /*case GL_CURRENT_RASTER_SECONDARY_COLOR: */
2972 /*case GL_CURRENT_RASTER_TEXTURE_COORDS: */
2973 /*case GL_CURRENT_SECONDARY_COLOR: */
2974 case GL_CURRENT_TEXTURE_COORDS:
2976 case GL_LIGHT_MODEL_AMBIENT:
2977 /*case GL_MAP2_GRID_DOMAIN: */
2978 case GL_SCISSOR_BOX:
2981 case GL_CURRENT_NORMAL:
2982 case GL_POINT_DISTANCE_ATTENUATION:
2984 case GL_ALIASED_LINE_WIDTH_RANGE:
2985 case GL_ALIASED_POINT_SIZE_RANGE:
2986 case GL_DEPTH_RANGE:
2987 /*case GL_LINE_WIDTH_RANGE: */
2988 /*case GL_MAP1_GRID_DOMAIN: */
2989 /*case GL_MAP2_GRID_SEGMENTS: */
2990 case GL_MAX_VIEWPORT_DIMS:
2991 /*case GL_POINT_SIZE_RANGE: */
2992 case GL_POLYGON_MODE:
2993 case GL_SMOOTH_LINE_WIDTH_RANGE:
2994 case GL_SMOOTH_POINT_SIZE_RANGE:
3003 jwzgles_glGetDoublev (GLenum pname, GLdouble *params)
3006 int i, j = glGet_ret_count (pname);
3007 jwzgles_glGetFloatv (pname, m);
3008 for (i = 0; i < j; i++)
3014 jwzgles_glGetIntegerv (GLenum pname, GLint *params)
3017 int i, j = glGet_ret_count (pname);
3018 jwzgles_glGetFloatv (pname, m);
3019 for (i = 0; i < j; i++)
3025 jwzgles_glGetBooleanv (GLenum pname, GLboolean *params)
3028 int i, j = glGet_ret_count (pname);
3029 jwzgles_glGetFloatv (pname, m);
3030 for (i = 0; i < j; i++)
3031 params[i] = (m[i] != 0.0);
3036 jwzgles_gluErrorString (GLenum error)
3039 sprintf (s, "0x%lX", (unsigned long) error);
3044 /* These can be included inside glNewList, but they actually execute
3048 jwzgles_glVertexPointer (GLuint size, GLuint type, GLuint stride,
3051 if (! state->replaying_list)
3052 LOG5 ("direct %-12s %d %s %d 0x%lX", "glVertexPointer",
3053 size, mode_desc(type), stride, (unsigned long) ptr);
3054 glVertexPointer (size, type, stride, ptr); /* the real one */
3055 CHECK("glVertexPointer");
3059 jwzgles_glNormalPointer (GLuint type, GLuint stride, const GLvoid *ptr)
3061 if (! state->replaying_list)
3062 LOG4 ("direct %-12s %s %d 0x%lX", "glNormalPointer",
3063 mode_desc(type), stride, (unsigned long) ptr);
3064 glNormalPointer (type, stride, ptr); /* the real one */
3065 CHECK("glNormalPointer");
3069 jwzgles_glColorPointer (GLuint size, GLuint type, GLuint stride,
3072 if (! state->replaying_list)
3073 LOG5 ("direct %-12s %d %s %d 0x%lX", "glColorPointer",
3074 size, mode_desc(type), stride, (unsigned long) ptr);
3075 glColorPointer (size, type, stride, ptr); /* the real one */
3076 CHECK("glColorPointer");
3080 jwzgles_glTexCoordPointer (GLuint size, GLuint type, GLuint stride,
3083 if (! state->replaying_list)
3084 LOG5 ("direct %-12s %d %s %d 0x%lX", "glTexCoordPointer",
3085 size, mode_desc(type), stride, (unsigned long) ptr);
3086 glTexCoordPointer (size, type, stride, ptr); /* the real one */
3087 CHECK("glTexCoordPointer");
3092 jwzgles_glTexParameterf (GLuint target, GLuint pname, GLfloat param)
3094 Assert (!state->compiling_verts,
3095 "glTexParameterf not allowed inside glBegin");
3097 /* We don't *really* implement mipmaps, so just turn this off.
3099 if (param == GL_LINEAR_MIPMAP_LINEAR) param = GL_LINEAR;
3100 if (param == GL_NEAREST_MIPMAP_LINEAR) param = GL_LINEAR;
3101 if (param == GL_LINEAR_MIPMAP_NEAREST) param = GL_NEAREST;
3102 if (param == GL_NEAREST_MIPMAP_NEAREST) param = GL_NEAREST;
3104 if (state->compiling_list)
3110 list_push ("glTexParameterf", (list_fn_cb) &jwzgles_glTexParameterf,
3115 if (! state->replaying_list)
3116 LOG4 ("direct %-12s %s %s %7.3f", "glTexParameterf",
3117 mode_desc(target), mode_desc(pname), param);
3118 glTexParameterf (target, pname, param); /* the real one */
3119 CHECK("glTexParameterf");
3124 jwzgles_glTexParameteri (GLuint target, GLuint pname, GLuint param)
3126 jwzgles_glTexParameterf (target, pname, param);
3130 /* Matrix functions, mostly cribbed from Mesa.
3134 jwzgles_glFrustum (GLfloat left, GLfloat right,
3135 GLfloat bottom, GLfloat top,
3136 GLfloat near, GLfloat far)
3139 GLfloat x = (2 * near) / (right-left);
3140 GLfloat y = (2 * near) / (top - bottom);
3141 GLfloat a = (right + left) / (right - left);
3142 GLfloat b = (top + bottom) / (top - bottom);
3143 GLfloat c = -(far + near) / (far - near);
3144 GLfloat d = -(2 * far * near) / (far - near);
3146 # define M(X,Y) m[Y * 4 + X]
3147 M(0,0) = x; M(0,1) = 0; M(0,2) = a; M(0,3) = 0;
3148 M(1,0) = 0; M(1,1) = y; M(1,2) = b; M(1,3) = 0;
3149 M(2,0) = 0; M(2,1) = 0; M(2,2) = c; M(2,3) = d;
3150 M(3,0) = 0; M(3,1) = 0; M(3,2) = -1; M(3,3) = 0;
3153 jwzgles_glMultMatrixf (m);
3158 jwzgles_glOrtho (GLfloat left, GLfloat right,
3159 GLfloat bottom, GLfloat top,
3160 GLfloat near, GLfloat far)
3163 GLfloat a = 2 / (right - left);
3164 GLfloat b = -(right + left) / (right - left);
3165 GLfloat c = 2 / (top - bottom);
3166 GLfloat d = -(top + bottom) / (top - bottom);
3167 GLfloat e = -2 / (far - near);
3168 GLfloat f = -(far + near) / (far - near);
3170 # define M(X,Y) m[Y * 4 + X]
3171 M(0,0) = a; M(0,1) = 0; M(0,2) = 0; M(0,3) = b;
3172 M(1,0) = 0; M(1,1) = c; M(1,2) = 0; M(1,3) = d;
3173 M(2,0) = 0; M(2,1) = 0; M(2,2) = e; M(2,3) = f;
3174 M(3,0) = 0; M(3,1) = 0; M(3,2) = 0; M(3,3) = 1;
3177 jwzgles_glMultMatrixf (m);
3182 jwzgles_gluPerspective (GLdouble fovy, GLdouble aspect,
3183 GLdouble near, GLdouble far)
3187 double rad = fovy / 2 * M_PI / 180;
3192 if (dz == 0 || si == 0 || aspect == 0)
3198 c = -(far + near) / dz;
3199 d = -2 * near * far / dz;
3201 # define M(X,Y) m[Y * 4 + X]
3202 M(0,0) = a; M(0,1) = 0; M(0,2) = 0; M(0,3) = 0;
3203 M(1,0) = 0; M(1,1) = b; M(1,2) = 0; M(1,3) = 0;
3204 M(2,0) = 0; M(2,1) = 0; M(2,2) = c; M(2,3) = d;
3205 M(3,0) = 0; M(3,1) = 0; M(3,2) = -1; M(3,3) = 0;
3208 jwzgles_glMultMatrixf (m);
3213 jwzgles_gluLookAt (GLfloat eyex, GLfloat eyey, GLfloat eyez,
3214 GLfloat centerx, GLfloat centery, GLfloat centerz,
3215 GLfloat upx, GLfloat upy, GLfloat upz)
3218 GLfloat x[3], y[3], z[3];
3221 /* Make rotation matrix */
3224 z[0] = eyex - centerx;
3225 z[1] = eyey - centery;
3226 z[2] = eyez - centerz;
3227 mag = sqrt(z[0] * z[0] + z[1] * z[1] + z[2] * z[2]);
3228 if (mag) { /* mpichler, 19950515 */
3239 /* X vector = Y cross Z */
3240 x[0] = y[1] * z[2] - y[2] * z[1];
3241 x[1] = -y[0] * z[2] + y[2] * z[0];
3242 x[2] = y[0] * z[1] - y[1] * z[0];
3244 /* Recompute Y = Z cross X */
3245 y[0] = z[1] * x[2] - z[2] * x[1];
3246 y[1] = -z[0] * x[2] + z[2] * x[0];
3247 y[2] = z[0] * x[1] - z[1] * x[0];
3249 /* mpichler, 19950515 */
3250 /* cross product gives area of parallelogram, which is < 1.0 for
3251 * non-perpendicular unit-length vectors; so normalize x, y here
3254 mag = sqrt(x[0] * x[0] + x[1] * x[1] + x[2] * x[2]);
3261 mag = sqrt(y[0] * y[0] + y[1] * y[1] + y[2] * y[2]);
3268 #define M(row,col) m[col*4+row]
3269 M(0, 0) = x[0]; M(0, 1) = x[1]; M(0, 2) = x[2]; M(0, 3) = 0.0;
3270 M(1, 0) = y[0]; M(1, 1) = y[1]; M(1, 2) = y[2]; M(1, 3) = 0.0;
3271 M(2, 0) = z[0]; M(2, 1) = z[1]; M(2, 2) = z[2]; M(2, 3) = 0.0;
3272 M(3, 0) = 0.0; M(3, 1) = 0.0; M(3, 2) = 0.0; M(3, 3) = 1.0;
3275 jwzgles_glMultMatrixf(m);
3277 /* Translate Eye to Origin */
3278 jwzgles_glTranslatef(-eyex, -eyey, -eyez);
3282 static void __gluMultMatrixVecd (const GLdouble matrix[16],
3283 const GLdouble in[4],
3288 for (i=0; i<4; i++) {
3290 in[0] * matrix[0*4+i] +
3291 in[1] * matrix[1*4+i] +
3292 in[2] * matrix[2*4+i] +
3293 in[3] * matrix[3*4+i];
3298 jwzgles_gluProject (GLdouble objx, GLdouble objy, GLdouble objz,
3299 const GLdouble modelMatrix[16],
3300 const GLdouble projMatrix[16],
3301 const GLint viewport[4],
3302 GLdouble *winx, GLdouble *winy, GLdouble *winz)
3307 /* #### I suspect this is not working right. I was seeing crazy values
3308 in lament.c. Maybe there's some float-vs-double confusion going on?
3315 __gluMultMatrixVecd(modelMatrix, in, out);
3316 __gluMultMatrixVecd(projMatrix, out, in);
3317 if (in[3] == 0.0) return(GL_FALSE);
3321 /* Map x, y and z to range 0-1 */
3322 in[0] = in[0] * 0.5 + 0.5;
3323 in[1] = in[1] * 0.5 + 0.5;
3324 in[2] = in[2] * 0.5 + 0.5;
3326 /* Map x,y to viewport */
3327 in[0] = in[0] * viewport[2] + viewport[0];
3328 in[1] = in[1] * viewport[3] + viewport[1];
3337 /* The following functions are present in both OpenGL 1.1 and in OpenGLES 1,
3338 but are allowed within glNewList/glEndList, so we must wrap them to allow
3339 them to either be recorded in lists, or run directly.
3341 All this CPP obscenity is me screaming in rage at all the ways that C is
3342 not Lisp, as all I want to do here is DEFADVICE.
3345 #define PROTO_V PROTO_VOID
3346 #define TYPE_V GLuint
3348 #define VARS_V /* */
3350 #define FILL_V /* */
3352 #define TYPE_I GLuint
3353 #define TYPE_II TYPE_I
3354 #define TYPE_III TYPE_I
3355 #define TYPE_IIII TYPE_I
3356 #define ARGS_I TYPE_I a
3357 #define ARGS_II TYPE_I a, TYPE_I b
3358 #define ARGS_III TYPE_I a, TYPE_I b, TYPE_I c
3359 #define ARGS_IIII TYPE_I a, TYPE_I b, TYPE_I c, TYPE_I d
3360 #define LOGS_I "%s\n", mode_desc(a)
3361 #define LOGS_II "%s %d\n", mode_desc(a), b
3362 #define LOGS_III "%s %s %s\n", mode_desc(a), mode_desc(b), mode_desc(c)
3363 #define LOGS_IIII "%d %d %d %d\n", a, b, c, d
3365 #define VARS_II a, b
3366 #define VARS_III a, b, c
3367 #define VARS_IIII a, b, c, d
3368 #define FILL_I vv[0].i = a;
3369 #define FILL_II vv[0].i = a; vv[1].i = b;
3370 #define FILL_III vv[0].i = a; vv[1].i = b; vv[2].i = c;
3371 #define FILL_IIII vv[0].i = a; vv[1].i = b; vv[2].i = c; vv[3].i = d;
3373 #define TYPE_F GLfloat
3374 #define TYPE_FF TYPE_F
3375 #define TYPE_FFF TYPE_F
3376 #define TYPE_FFFF TYPE_F
3377 #define ARGS_F TYPE_F a
3378 #define ARGS_FF TYPE_F a, TYPE_F b
3379 #define ARGS_FFF TYPE_F a, TYPE_F b, TYPE_F c
3380 #define ARGS_FFFF TYPE_F a, TYPE_F b, TYPE_F c, TYPE_F d
3381 #define LOGS_F "%7.3f\n", a
3382 #define LOGS_FF "%7.3f %7.3f\n", a, b
3383 #define LOGS_FFF "%7.3f %7.3f %7.3f\n", a, b, c
3384 #define LOGS_FFFF "%7.3f %7.3f %7.3f %7.3f\n", a, b, c, d
3385 #define VARS_F VARS_I
3386 #define VARS_FF VARS_II
3387 #define VARS_FFF VARS_III
3388 #define VARS_FFFF VARS_IIII
3389 #define FILL_F vv[0].f = a;
3390 #define FILL_FF vv[0].f = a; vv[1].f = b;
3391 #define FILL_FFF vv[0].f = a; vv[1].f = b; vv[2].f = c;
3392 #define FILL_FFFF vv[0].f = a; vv[1].f = b; vv[2].f = c; vv[3].f = d;
3394 #define ARGS_IF TYPE_I a, TYPE_F b
3395 #define VARS_IF VARS_II
3396 #define LOGS_IF "%s %7.3f\n", mode_desc(a), b
3397 #define FILL_IF vv[0].i = a; vv[1].f = b;
3399 #define ARGS_IIF TYPE_I a, TYPE_I b, TYPE_F c
3400 #define VARS_IIF VARS_III
3401 #define LOGS_IIF "%s %s %7.3f\n", mode_desc(a), mode_desc(b), c
3402 #define FILL_IIF vv[0].i = a; vv[1].i = b; vv[2].f = c;
3404 #define TYPE_IV GLint
3405 #define ARGS_IIV TYPE_I a, const TYPE_IV *b
3406 #define VARS_IIV VARS_II
3407 #define LOGS_IIV "%s %d %d %d %d\n", mode_desc(a), b[0], b[1], b[2], b[3]
3408 #define FILL_IIV vv[0].i = a; \
3409 vv[1].i = b[0]; vv[2].i = b[1]; \
3410 vv[3].i = b[2]; vv[4].i = b[3];
3412 #define ARGS_IFV TYPE_I a, const TYPE_F *b
3413 #define VARS_IFV VARS_II
3414 #define LOGS_IFV "%s %7.3f %7.3f %7.3f %7.3f\n", mode_desc(a), \
3415 b[0], b[1], b[2], b[3]
3416 #define FILL_IFV vv[0].i = a; \
3417 vv[1].f = b[0]; vv[2].f = b[1]; \
3418 vv[3].f = b[2]; vv[4].f = b[3];
3420 #define ARGS_IIIV TYPE_I a, TYPE_I b, const TYPE_IV *c
3421 #define VARS_IIIV VARS_III
3422 #define LOGS_IIIV "%s %-8s %3d %3d %3d %3d\n", mode_desc(a), mode_desc(b), \
3423 c[0], c[1], c[2], c[3]
3424 #define FILL_IIIV vv[0].i = a; vv[1].i = b; \
3425 vv[2].i = c[0]; vv[3].i = c[1]; \
3426 vv[4].i = c[2]; vv[5].i = c[3];
3428 #define ARGS_IIFV TYPE_I a, TYPE_I b, const TYPE_F *c
3429 #define VARS_IIFV VARS_III
3430 #define LOGS_IIFV "%s %-8s %7.3f %7.3f %7.3f %7.3f\n", \
3431 mode_desc(a), mode_desc(b), \
3432 c[0], c[1], c[2], c[3]
3433 #define FILL_IIFV vv[0].i = a; vv[1].i = b; \
3434 vv[2].f = c[0]; vv[3].f = c[1]; \
3435 vv[4].f = c[2]; vv[5].f = c[3];
3438 # define WLOG(NAME,ARGS) \
3439 fprintf (stderr, "jwzgles: direct %-12s ", NAME); \
3440 fprintf (stderr, ARGS)
3442 # define WLOG(NAME,ARGS) /* */
3445 #define WRAP(NAME,SIG) \
3446 void jwzgles_##NAME (ARGS_##SIG) \
3448 Assert (!state->compiling_verts, \
3449 STRINGIFY(NAME) " not allowed inside glBegin"); \
3450 if (state->compiling_list) { \
3453 list_push (STRINGIFY(NAME), (list_fn_cb) &jwzgles_##NAME, \
3456 if (! state->replaying_list) { \
3457 WLOG (STRINGIFY(NAME), LOGS_##SIG); \
3459 NAME (VARS_##SIG); \
3460 CHECK(STRINGIFY(NAME)); \
3464 WRAP (glActiveTexture, I)
3465 WRAP (glAlphaFunc, IF)
3466 WRAP (glBindTexture, II)
3467 WRAP (glBlendFunc, II)
3469 WRAP (glClearColor, FFFF)
3470 WRAP (glClearStencil, I)
3471 WRAP (glColorMask, IIII)
3472 WRAP (glCullFace, I)
3473 WRAP (glDepthFunc, I)
3474 WRAP (glDepthMask, I)
3479 WRAP (glFrontFace, I)
3481 WRAP (glLightModelf, IF)
3482 WRAP (glLightModelfv, IFV)
3483 WRAP (glLightf, IIF)
3484 WRAP (glLightfv, IIFV)
3485 WRAP (glLineWidth, F)
3486 WRAP (glLoadIdentity, V)
3488 WRAP (glMatrixMode, I)
3489 WRAP (glPixelStorei, II)
3490 WRAP (glPointSize, F)
3491 WRAP (glPolygonOffset, FF)
3492 WRAP (glPopMatrix, V)
3493 WRAP (glPushMatrix, V)
3494 WRAP (glRotatef, FFFF)
3495 WRAP (glScalef, FFF)
3496 WRAP (glScissor, IIII)
3497 WRAP (glShadeModel, I)
3498 WRAP (glStencilFunc, III)
3499 WRAP (glStencilMask, I)
3500 WRAP (glStencilOp, III)
3501 WRAP (glTexEnvf, IIF)
3502 WRAP (glTexEnvi, III)
3503 WRAP (glTranslatef, FFF)
3504 WRAP (glViewport, IIII)
3506 #define TYPE_IV GLuint
3507 WRAP (glDeleteTextures, IIV)
3510 #endif /* HAVE_JWZGLES - whole file */