1 /* xscreensaver, Copyright (c) 2012-2018 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.1, not 1.0 or 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 */
163 #endif /* HAVE_UNISTD_H */
165 #if defined(USE_IPHONE)
166 # include <OpenGLES/ES1/gl.h>
167 # include <OpenGLES/ES1/glext.h>
168 #elif defined(HAVE_COCOA)
169 # include <OpenGL/gl.h>
170 # include <OpenGL/glu.h>
171 #elif defined(HAVE_ANDROID)
172 # include <GLES/gl.h>
173 # include <android/log.h>
175 # ifndef GL_GLEXT_PROTOTYPES
176 # define GL_GLEXT_PROTOTYPES /* for glBindBuffer */
182 #include "jwzglesI.h"
186 #define STRINGIFY(X) #X
189 #define countof(x) (sizeof((x))/sizeof((*x)))
194 extern void jwxyz_abort (const char *fmt, ...) __dead2;
195 # define Assert(C,S) do { if (!(C)) { jwxyz_abort ("%s",S); }} while(0)
196 #elif defined HAVE_ANDROID
197 # define Assert(C,S) do { \
199 __android_log_print (ANDROID_LOG_ERROR, "xscreensaver", "jwzgles: %s\n", S); \
203 # define Assert(C,S) do { \
205 fprintf (stderr, "jwzgles: %s\n", S); \
211 typedef struct { GLfloat x, y, z; } XYZ;
212 typedef struct { GLfloat x, y, z, w; } XYZW;
213 typedef struct { GLfloat s, t, r, q; } STRQ;
214 typedef struct { GLfloat r, g, b, a; } RGBA;
217 /* Used to record all calls to glVertex3f, glNormal3f, etc.
218 while inside glBegin / glEnd so that we can convert that
219 to a single call to glDrawArrays.
223 int count, size; /* size of each array */
225 XYZW *verts; /* Arrays being built */
230 int ncount; /* How many normals, tex coords and colors were */
231 int tcount; /* used. We optimize based on "0, 1, or many". */
233 int materialistic; /* Whether glMaterial was called inside glBegin */
235 XYZ cnorm; /* Prevailing normal/texture/color while building */
242 typedef void (*list_fn_cb) (void);
245 /* We need this nonsense because you can't cast a double to a void*
246 or vice versa. They tend to be passed in different registers,
247 and you need to know about that because it's still 1972 here.
250 const void *v; GLfloat f; GLuint i; GLshort s; GLdouble d;
253 typedef struct { /* saved args for glDrawArrays */
254 int binding, size, type, stride, bytes;
258 typedef enum { /* shorthand describing arglist signature */
259 PROTO_VOID, /* no args */
260 PROTO_I, /* 1 int arg */
261 PROTO_F, /* 1 float arg */
262 PROTO_II, /* int, int */
263 PROTO_FF, /* float, float */
264 PROTO_IF, /* int, float */
265 PROTO_III, /* int, int, int */
266 PROTO_FFF, /* float, float, float */
267 PROTO_IIF, /* int, int, float */
268 PROTO_IIII, /* int, int, int, int */
269 PROTO_FFFF, /* float, float, float, float */
270 PROTO_IIV, /* int, int[4] */
271 PROTO_IFV, /* int, float[4] */
272 PROTO_IIIV, /* int, int, int[4] */
273 PROTO_IIFV, /* int, int, float[4] */
274 PROTO_FV16, /* float[16] */
275 PROTO_ARRAYS /* glDrawArrays */
278 typedef struct { /* A single element of a display list */
280 list_fn_cb fn; /* saved function pointer */
281 fn_proto proto; /* arglist prototype */
282 draw_array *arrays; /* args for glDrawArrays */
283 void_int argv[16]; /* args for everything else */
287 typedef struct { /* a display list: saved activity within glNewList */
292 /* Named buffer that should be freed when this display list is deleted. */
298 typedef struct { /* All display lists */
304 #define ISENABLED_TEXTURE_2D (1<<0)
305 #define ISENABLED_TEXTURE_GEN_S (1<<1)
306 #define ISENABLED_TEXTURE_GEN_T (1<<2)
307 #define ISENABLED_TEXTURE_GEN_R (1<<3)
308 #define ISENABLED_TEXTURE_GEN_Q (1<<4)
309 #define ISENABLED_LIGHTING (1<<5)
310 #define ISENABLED_BLEND (1<<6)
311 #define ISENABLED_DEPTH_TEST (1<<7)
312 #define ISENABLED_CULL_FACE (1<<8)
313 #define ISENABLED_NORMALIZE (1<<9)
314 #define ISENABLED_FOG (1<<10)
315 #define ISENABLED_COLMAT (1<<11)
316 #define ISENABLED_VERT_ARRAY (1<<12)
317 #define ISENABLED_NORM_ARRAY (1<<13)
318 #define ISENABLED_TEX_ARRAY (1<<14)
319 #define ISENABLED_COLOR_ARRAY (1<<15)
320 #define ISENABLED_ALPHA_TEST (1<<16)
325 GLfloat obj[4], eye[4];
329 struct jwzgles_state { /* global state */
331 vert_set set; /* set being built */
333 int compiling_list; /* list id if inside glNewList; 0 means immediate */
334 int replaying_list; /* depth of call stack to glCallList */
335 int compiling_verts; /* inside glBegin */
337 list_set lists; /* saved lists */
339 unsigned long enabled; /* enabled flags, immediate mode */
340 unsigned long list_enabled; /* and for the list-in-progress */
342 texgen_state s, t, r, q;
344 /* Implementing glPushClientAttrib? Don't forget about these! */
345 draw_array varray, narray, carray, tarray;
350 static jwzgles_state *state = 0;
355 static void Log(const char *fmt, ...)
358 va_start (args, fmt);
360 /* setprop log.redirect-stdio true is another possibility, but that
361 apparently only works on rooted devices.
363 __android_log_vprint(ANDROID_LOG_DEBUG, "xscreensaver", fmt, args);
365 vfprintf(stderr, fmt, args);
370 # define LOG(A) Log("jwzgles: " A "\n")
371 # define LOG1(A,B) Log("jwzgles: " A "\n",B)
372 # define LOG2(A,B,C) Log("jwzgles: " A "\n",B,C)
373 # define LOG3(A,B,C,D) Log("jwzgles: " A "\n",B,C,D)
374 # define LOG4(A,B,C,D,E) Log("jwzgles: " A "\n",B,C,D,E)
375 # define LOG5(A,B,C,D,E,F) Log("jwzgles: " A "\n",B,C,D,E,F)
376 # define LOG6(A,B,C,D,E,F,G) Log("jwzgles: " A "\n",B,C,D,E,F,G)
377 # define LOG7(A,B,C,D,E,F,G,H) Log("jwzgles: " A "\n",B,C,D,E,F,G,H)
378 # define LOG8(A,B,C,D,E,F,G,H,I)\
379 Log("jwzgles: "A "\n",B,C,D,E,F,G,H,I)
380 # define LOG9(A,B,C,D,E,F,G,H,I,J)\
381 Log("jwzgles: "A "\n",B,C,D,E,F,G,H,I,J)
382 # define LOG10(A,B,C,D,E,F,G,H,I,J,K)\
383 Log("jwzgles: "A "\n",B,C,D,E,F,G,H,I,J,K)
384 # define LOG17(A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R)\
385 Log("jwzgles: "A "\n",B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R)
386 # define CHECK(S) jwzgles_check_gl_error(S)
388 # define LOG(A) /* */
389 # define LOG1(A,B) /* */
390 # define LOG2(A,B,C) /* */
391 # define LOG3(A,B,C,D) /* */
392 # define LOG4(A,B,C,D,E) /* */
393 # define LOG5(A,B,C,D,E,F) /* */
394 # define LOG6(A,B,C,D,E,F,G) /* */
395 # define LOG7(A,B,C,D,E,F,G,H) /* */
396 # define LOG8(A,B,C,D,E,F,G,H,I) /* */
397 # define LOG9(A,B,C,D,E,F,G,H,I,J) /* */
398 # define LOG10(A,B,C,D,E,F,G,H,I,J,K) /* */
399 # define LOG17(A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R) /* */
400 # define CHECK(S) /* */
405 mode_desc (int mode) /* for debugging messages */
408 # define SS(X) case GL_##X: return STRINGIFY(X);
412 SS(AMBIENT_AND_DIFFUSE)
428 SS(COLOR_ARRAY_BUFFER_BINDING);
430 SS(COLOR_MATERIAL_FACE)
431 SS(COLOR_MATERIAL_PARAMETER)
443 SS(ELEMENT_ARRAY_BUFFER)
456 SS(INVALID_OPERATION)
464 SS(LIGHT_MODEL_AMBIENT)
465 SS(LIGHT_MODEL_COLOR_CONTROL)
466 SS(LIGHT_MODEL_LOCAL_VIEWER)
467 SS(LIGHT_MODEL_TWO_SIDE)
470 SS(LINEAR_MIPMAP_LINEAR)
471 SS(LINEAR_MIPMAP_NEAREST)
482 SS(NEAREST_MIPMAP_LINEAR)
483 SS(NEAREST_MIPMAP_NEAREST)
486 SS(NORMAL_ARRAY_BUFFER_BINDING);
489 SS(ONE_MINUS_DST_ALPHA)
490 SS(ONE_MINUS_DST_COLOR)
491 SS(ONE_MINUS_SRC_ALPHA)
492 SS(ONE_MINUS_SRC_COLOR)
497 SS(POLYGON_OFFSET_FILL)
513 SS(SEPARATE_SPECULAR_COLOR)
522 SS(SRC_ALPHA_SATURATE)
527 SS(STENCIL_BUFFER_BIT)
539 SS(TEXTURE_ALPHA_SIZE)
540 SS(TEXTURE_BINDING_2D)
541 SS(TEXTURE_BLUE_SIZE)
543 SS(TEXTURE_BORDER_COLOR)
544 SS(TEXTURE_COMPONENTS)
545 SS(TEXTURE_COORD_ARRAY)
546 SS(TEXTURE_COORD_ARRAY_BUFFER_BINDING);
548 SS(TEXTURE_ENV_COLOR)
555 SS(TEXTURE_GREEN_SIZE)
557 SS(TEXTURE_INTENSITY_SIZE)
558 SS(TEXTURE_LUMINANCE_SIZE)
559 SS(TEXTURE_MAG_FILTER)
560 SS(TEXTURE_MIN_FILTER)
568 SS(UNPACK_ROW_LENGTH)
570 SS(UNSIGNED_INT_8_8_8_8_REV)
575 SS(VERTEX_ARRAY_BUFFER_BINDING);
576 /*SS(COLOR_BUFFER_BIT) -- same value as GL_LIGHT0 */
578 case (GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT):
579 return "DEPTH_BUFFER_BIT | COLOR_BUFFER_BIT";
580 /* Oops, same as INVALID_ENUM.
581 case (GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT):
582 return "DEPTH_BUFFER_BIT | STENCIL_BUFFER_BIT";
584 case (GL_COLOR_BUFFER_BIT | GL_STENCIL_BUFFER_BIT):
585 return "COLOR_BUFFER_BIT | STENCIL_BUFFER_BIT";
586 case (GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT | GL_STENCIL_BUFFER_BIT):
587 return "DEPTH_BUFFER_BIT | COLOR_BUFFER_BIT | STENCIL_BUFFER_BIT";
590 static char buf[255];
591 sprintf (buf, "0x%04X", mode);
598 jwzgles_check_gl_error (const char *s)
600 GLenum i = glGetError();
601 if (i == GL_NO_ERROR) return;
602 fprintf (stderr, "jwzgles: GL ERROR: %s: %s\n", s, mode_desc(i));
609 make_room (const char *name, void **array, int span, int *count, int *size)
611 if (*count + 1 >= *size)
613 int new_size = (*count + 20) * 1.2; /* mildly exponential */
614 *array = realloc (*array, new_size * span);
615 Assert (*array, "out of memory");
616 /* LOG3("%s: grew %d -> %d", name, *size, new_size); */
623 jwzgles_free_state (void)
625 /* Tricky: jwzgles_make_state doesn't require an active GLES context, but
626 jwzgles_free_state does.
629 LOG1("jwzgles_free_state %p", state);
631 if (state->lists.lists)
633 state->compiling_list = 0;
634 if (state->lists.count)
635 jwzgles_glDeleteLists (1, state->lists.count);
636 free (state->lists.lists);
639 if (state->set.verts) free (state->set.verts);
640 if (state->set.norms) free (state->set.norms);
641 if (state->set.tex) free (state->set.tex);
642 if (state->set.color) free (state->set.color);
650 jwzgles_make_state (void)
652 jwzgles_state *s = (jwzgles_state *) calloc (1, sizeof (*s));
654 LOG1("jwzgles_make_state %p", s);
656 s->s.mode = s->t.mode = s->r.mode = s->q.mode = GL_EYE_LINEAR;
657 s->s.obj[0] = s->s.eye[0] = 1; /* s = 1 0 0 0 */
658 s->t.obj[1] = s->t.eye[1] = 1; /* t = 0 1 0 0 */
665 jwzgles_make_current (jwzgles_state *s)
667 LOG1("jwzgles_make_current %p", s);
673 jwzgles_glGenLists (int n)
678 Assert (!state->compiling_verts, "glGenLists not allowed inside glBegin");
680 /* Ensure space in state->lists, clear the one at the end, and tick counter
681 Note that lists are never really deleted, and we can never re-use elements
682 of this array. glDeleteLists zeroes out the contents of the list, but
683 the list ID is still valid for use with glNewList forever.
684 #### So maybe this should be a linked list instead of an array.
686 for (i = 0; i < n; i++)
690 make_room ("glGenLists",
691 (void **) &state->lists.lists,
692 sizeof (*state->lists.lists),
693 &state->lists.count, &state->lists.size);
694 state->lists.count++;
695 id = state->lists.count;
696 L = &state->lists.lists[id-1];
698 memset (L, 0, sizeof (*L));
700 if (ret == 0) ret = id;
701 LOG1("glGenLists -> %d", L->id);
704 /* Return the ID of the first list allocated */
711 jwzgles_glNewList (int id, int mode)
714 Assert (id > 0 && id <= state->lists.count, "glNewList: bogus ID");
715 Assert (mode == GL_COMPILE, "glNewList: bad mode");
716 Assert (!state->compiling_verts, "glNewList not allowed inside glBegin");
717 Assert (!state->compiling_list, "nested glNewList");
718 Assert (state->set.count == 0, "missing glEnd");
720 L = &state->lists.lists[id-1];
721 Assert (L->id == id, "glNewList corrupted");
723 if (L->count != 0) jwzgles_glDeleteLists (L->id, 1); /* Overwriting */
724 Assert (L->count == 0, "glNewList corrupted");
726 state->compiling_list = id;
728 state->list_enabled = state->enabled;
730 LOG1("glNewList -> %d", id);
734 static void save_arrays (list_fn *, int);
735 static void restore_arrays (list_fn *, int);
736 static void copy_array_data (draw_array *, int, const char *);
737 static void optimize_arrays (void);
738 static void generate_texture_coords (GLuint, GLuint);
742 jwzgles_glEndList (void)
744 Assert (state->compiling_list, "extra glEndList");
745 Assert (state->set.count == 0, "missing glEnd");
746 Assert (!state->compiling_verts, "glEndList not allowed inside glBegin");
747 LOG1("glEndList %d", state->compiling_list);
749 state->compiling_list = 0;
750 state->list_enabled = state->enabled;
755 list_push (const char * const name,
756 list_fn_cb fn, fn_proto proto, void_int *av)
762 Assert (state->compiling_list > 0, "not inside glNewList");
763 Assert (state->compiling_list <= state->lists.count, "glNewList corrupted");
765 L = &state->lists.lists[state->compiling_list-1];
766 Assert (L, "glNewList: no list");
768 make_room ("glNewLists",
769 (void **) &L->fns, sizeof (*L->fns),
770 &L->count, &L->size);
771 memset (&L->fns[L->count], 0, sizeof (*L->fns));
772 F = L->fns + L->count;
777 if (proto != PROTO_VOID)
778 for (i = 0; i < countof(F->argv); i++)
784 LOG1 (" push %-12s", name);
787 if (fn == (list_fn_cb) &jwzgles_glBegin ||
788 fn == (list_fn_cb) &jwzgles_glFrontFace ||
789 fn == (list_fn_cb) &jwzgles_glEnable ||
790 fn == (list_fn_cb) &jwzgles_glDisable ||
791 fn == (list_fn_cb) &jwzgles_glEnableClientState ||
792 fn == (list_fn_cb) &jwzgles_glDisableClientState ||
793 fn == (list_fn_cb) &jwzgles_glShadeModel ||
794 fn == (list_fn_cb) &jwzgles_glMatrixMode)
795 LOG2 (" push %-12s %s", name, mode_desc (av[0].i));
797 LOG2 (" push %-12s %d", name, av[0].i);
800 LOG2 (" push %-12s %7.3f", name, av[0].f);
803 if (fn == (list_fn_cb) &jwzgles_glBindTexture ||
804 fn == (list_fn_cb) &jwzgles_glBindBuffer)
805 LOG3 (" push %-12s %s %d", name, mode_desc (av[0].i), av[1].i);
807 LOG3 (" push %-12s %d %d", name, av[0].i, av[1].i);
810 LOG3 (" push %-12s %7.3f %7.3f", name, av[0].f, av[1].f);
813 LOG3 (" push %-12s %s %7.3f", name, mode_desc (av[0].i), av[1].f);
817 if (fn == (list_fn_cb) &jwzgles_glDrawArrays ||
818 fn == (list_fn_cb) &jwzgles_glTexParameteri)
819 LOG4 (" push %-12s %s %d %d", name, mode_desc (av[0].i),
822 LOG4 (" push %-12s %d %d %d", name, av[0].i, av[1].i, av[2].i);
825 LOG4 (" push %-12s %7.3f %7.3f %7.3f", name, av[0].f, av[1].f, av[2].f);
828 LOG4 (" push %-12s %s %s %7.3f", name,
829 mode_desc(av[0].i), mode_desc(av[1].i), av[2].f);
832 LOG5 (" push %-12s %d %d %d %d", name,
833 av[0].i, av[1].i, av[2].i, av[3].i);
836 LOG5 (" push %-12s %7.3f %7.3f %7.3f %7.3f", name,
837 av[0].f, av[1].f, av[2].f, av[3].f);
840 LOG6 (" push %-12s %s %3.1f %3.1f %3.1f %3.1f", name, mode_desc (av[0].i),
841 av[1].f, av[2].f, av[3].f, av[4].f);
844 LOG6 (" push %-12s %s %d %d %d %d", name, mode_desc (av[0].i),
845 av[1].i, av[2].i, av[3].i, av[4].i);
848 LOG7 (" push %-12s %s %-8s %3.1f %3.1f %3.1f %3.1f", name,
849 mode_desc (av[0].i), mode_desc (av[1].i),
850 av[2].f, av[3].f, av[4].f, av[5].f);
853 LOG7 (" push %-12s %s %-8s %3d %3d %3d %3d", name,
854 mode_desc (av[0].i), mode_desc (av[1].i),
855 av[2].i, av[3].i, av[4].i, av[5].i);
858 LOG17 (" push %-12s ["
859 "%8.3f %8.3f %8.3f %8.3f " "\n\t\t\t "
860 "%8.3f %8.3f %8.3f %8.3f " "\n\t\t\t "
861 "%8.3f %8.3f %8.3f %8.3f " "\n\t\t\t "
862 "%8.3f %8.3f %8.3f %8.3f ]",
864 av[0].f, av[1].f, av[2].f, av[3].f,
865 av[4].f, av[5].f, av[6].f, av[7].f,
866 av[8].f, av[9].f, av[10].f, av[11].f,
867 av[12].f, av[13].f, av[14].f, av[15].f);
870 Assert (0, "bogus prototype");
875 if (proto == PROTO_ARRAYS) /* glDrawArrays */
876 save_arrays (F, av[1].i + av[2].i);
883 jwzgles_glBegin (int mode)
885 Assert (!state->compiling_verts, "nested glBegin");
886 state->compiling_verts++;
888 /* Only these commands are allowed inside glBegin:
890 glVertex -- not allowed outside
901 glArrayElement -- not allowed outside
908 if (!state->replaying_list)
909 LOG2 ("%sglBegin %s",
910 (state->compiling_list || state->replaying_list ? " " : ""),
913 Assert (state->set.count == 0, "glBegin corrupted");
914 state->set.mode = mode;
915 state->set.count = 0;
916 state->set.ncount = 0;
917 state->set.tcount = 0;
918 state->set.ccount = 0;
923 jwzgles_glDeleteLists (int id0, int range)
925 Assert (!state->compiling_verts, "glDeleteLists not allowed inside glBegin");
927 if (state->compiling_list)
932 list_push ("glDeleteLists", (list_fn_cb) &jwzgles_glDeleteLists,
939 if (!state->replaying_list)
940 LOG2 ("glDeleteLists %d %d", id0, range);
942 for (id = id0 + range - 1; id >= id0; id--)
946 if (id == 0) continue; /* People do this stupid thing */
947 if (id > state->lists.count) break; /* this too */
948 Assert (id > 0 && id <= state->lists.count,
949 "glDeleteLists: bogus ID");
950 L = &state->lists.lists[id-1];
951 Assert (L->id == id, "glDeleteLists corrupted");
953 for (i = 0; i < L->count; i++)
955 list_fn *lf = &L->fns[i];
959 for (j = 0; j < 4; j++)
960 /* If there's a binding, 'data' is an index, not a ptr. */
961 if (!lf->arrays[j].binding &&
963 free (lf->arrays[j].data);
970 glDeleteBuffers (1, &L->buffer);
972 memset (L, 0, sizeof (*L));
980 jwzgles_glIsList (GLuint id)
982 return (id > 0 && id < state->lists.count);
988 jwzgles_glNormal3fv (const GLfloat *v)
990 if (state->compiling_list && !state->compiling_verts)
996 list_push ("glNormal3f", (list_fn_cb) &jwzgles_glNormal3f,
1001 if (!state->replaying_list)
1002 LOG5 ("%s%sglNormal3f %7.3f %7.3f %7.3f",
1003 (state->compiling_list || state->replaying_list ? " " : ""),
1004 (state->compiling_verts ? " rec " : ""),
1007 if (state->compiling_verts) /* inside glBegin */
1009 state->set.cnorm.x = v[0];
1010 state->set.cnorm.y = v[1];
1011 state->set.cnorm.z = v[2];
1012 state->set.ncount++;
1013 if (state->set.count > 0 && state->set.ncount == 1) /* not first! */
1014 state->set.ncount++;
1016 else /* outside glBegin */
1018 glNormal3f (v[0], v[1], v[2]);
1019 CHECK("glNormal3f");
1026 jwzgles_glNormal3f (GLfloat x, GLfloat y, GLfloat z)
1032 jwzgles_glNormal3fv (v);
1037 jwzgles_glTexCoord4fv (const GLfloat *v)
1039 if (state->compiling_list && !state->compiling_verts)
1046 list_push ("glTexCoord4f", (list_fn_cb) &jwzgles_glTexCoord4f,
1051 if (!state->replaying_list)
1052 LOG6 ("%s%sglTexCoord4f %7.3f %7.3f %7.3f %7.3f",
1053 (state->compiling_list || state->replaying_list ? " " : ""),
1054 (state->compiling_verts ? " rec " : ""),
1055 v[0], v[1], v[2], v[3]);
1057 Assert (state->compiling_verts, "glTexCoord4fv outside glBegin");
1059 if (state->compiling_verts) /* inside glBegin */
1061 state->set.ctex.s = v[0];
1062 state->set.ctex.t = v[1];
1063 state->set.ctex.r = v[2];
1064 state->set.ctex.q = v[3];
1065 state->set.tcount++;
1066 if (state->set.count > 0 && state->set.tcount == 1) /* not first! */
1067 state->set.tcount++;
1074 jwzgles_glTexCoord4f (GLfloat s, GLfloat t, GLfloat r, GLfloat q)
1081 jwzgles_glTexCoord4fv (v);
1086 jwzgles_glTexCoord3fv (const GLfloat *v)
1093 jwzgles_glTexCoord4fv (vv);
1098 jwzgles_glTexCoord2fv (const GLfloat *v)
1105 jwzgles_glTexCoord4fv (vv);
1110 jwzgles_glTexCoord3f (GLfloat s, GLfloat t, GLfloat r)
1112 jwzgles_glTexCoord4f (s, t, r, 1);
1117 jwzgles_glTexCoord2f (GLfloat s, GLfloat t)
1119 jwzgles_glTexCoord4f (s, t, 0, 1);
1124 jwzgles_glTexCoord1f (GLfloat s)
1126 jwzgles_glTexCoord4f (s, 0, 0, 1);
1130 /* glColor: GLfloat */
1133 jwzgles_glColor4fv (const GLfloat *v)
1135 if (state->compiling_list && !state->compiling_verts)
1142 list_push ("glColor4f", (list_fn_cb) &jwzgles_glColor4f,
1147 if (!state->replaying_list)
1148 LOG6 ("%s%sglColor4f %7.3f %7.3f %7.3f %7.3f",
1149 (state->compiling_list || state->replaying_list ? " " : ""),
1150 (state->compiling_verts ? " rec " : ""),
1151 v[0], v[1], v[2], v[3]);
1153 if (state->compiling_verts) /* inside glBegin */
1155 state->set.ccolor.r = v[0];
1156 state->set.ccolor.g = v[1];
1157 state->set.ccolor.b = v[2];
1158 state->set.ccolor.a = v[3];
1159 state->set.ccount++;
1160 if (state->set.count > 0 && state->set.ccount == 1) /* not first! */
1161 state->set.ccount++;
1163 else /* outside glBegin */
1165 glColor4f (v[0], v[1], v[2], v[3]);
1173 jwzgles_glColor4f (GLfloat r, GLfloat g, GLfloat b, GLfloat a)
1180 jwzgles_glColor4fv (v);
1184 jwzgles_glColor3f (GLfloat r, GLfloat g, GLfloat b)
1186 jwzgles_glColor4f (r, g, b, 1);
1190 jwzgles_glColor3fv (const GLfloat *v)
1192 jwzgles_glColor3f (v[0], v[1], v[2]);
1196 /* glColor: GLdouble */
1199 jwzgles_glColor4d (GLdouble r, GLdouble g, GLdouble b, GLdouble a)
1201 jwzgles_glColor4f (r, g, b, a);
1205 jwzgles_glColor4dv (const GLdouble *v)
1207 jwzgles_glColor4d (v[0], v[1], v[2], v[3]);
1211 jwzgles_glColor3d (GLdouble r, GLdouble g, GLdouble b)
1213 jwzgles_glColor4d (r, g, b, 1.0);
1217 jwzgles_glColor3dv (const GLdouble *v)
1219 jwzgles_glColor3d (v[0], v[1], v[2]);
1223 /* glColor: GLint (INT_MIN - INT_MAX) */
1226 jwzgles_glColor4i (GLint r, GLint g, GLint b, GLint a)
1228 /* -0x8000000 - 0x7FFFFFFF => 0.0 - 1.0 */
1229 jwzgles_glColor4f (0.5 + (GLfloat) r / 0xFFFFFFFF,
1230 0.5 + (GLfloat) g / 0xFFFFFFFF,
1231 0.5 + (GLfloat) b / 0xFFFFFFFF,
1232 0.5 + (GLfloat) a / 0xFFFFFFFF);
1236 jwzgles_glColor4iv (const GLint *v)
1238 jwzgles_glColor4i (v[0], v[1], v[2], v[3]);
1243 jwzgles_glColor3i (GLint r, GLint g, GLint b)
1245 jwzgles_glColor4i (r, g, b, 0x7FFFFFFF);
1249 jwzgles_glColor3iv (const GLint *v)
1251 jwzgles_glColor3i (v[0], v[1], v[2]);
1255 /* glColor: GLuint (0 - UINT_MAX) */
1258 jwzgles_glColor4ui (GLuint r, GLuint g, GLuint b, GLuint a)
1260 /* 0 - 0xFFFFFFFF => 0.0 - 1.0 */
1261 jwzgles_glColor4f ((GLfloat) r / 0xFFFFFFFF,
1262 (GLfloat) g / 0xFFFFFFFF,
1263 (GLfloat) b / 0xFFFFFFFF,
1264 (GLfloat) a / 0xFFFFFFFF);
1268 jwzgles_glColor4uiv (const GLuint *v)
1270 jwzgles_glColor4ui (v[0], v[1], v[2], v[3]);
1274 jwzgles_glColor3ui (GLuint r, GLuint g, GLuint b)
1276 jwzgles_glColor4ui (r, g, b, 0xFFFFFFFF);
1280 jwzgles_glColor3uiv (const GLuint *v)
1282 jwzgles_glColor3ui (v[0], v[1], v[2]);
1286 /* glColor: GLshort (SHRT_MIN - SHRT_MAX) */
1289 jwzgles_glColor4s (GLshort r, GLshort g, GLshort b, GLshort a)
1291 /* -0x8000 - 0x7FFF => 0.0 - 1.0 */
1292 jwzgles_glColor4f (0.5 + (GLfloat) r / 0xFFFF,
1293 0.5 + (GLfloat) g / 0xFFFF,
1294 0.5 + (GLfloat) b / 0xFFFF,
1295 0.5 + (GLfloat) a / 0xFFFF);
1299 jwzgles_glColor4sv (const GLshort *v)
1301 jwzgles_glColor4s (v[0], v[1], v[2], v[3]);
1305 jwzgles_glColor3s (GLshort r, GLshort g, GLshort b)
1307 jwzgles_glColor4s (r, g, b, 0x7FFF);
1311 jwzgles_glColor3sv (const GLshort *v)
1313 jwzgles_glColor3s (v[0], v[1], v[2]);
1317 /* glColor: GLushort (0 - USHRT_MAX) */
1320 jwzgles_glColor4us (GLushort r, GLushort g, GLushort b, GLushort a)
1322 /* 0 - 0xFFFF => 0.0 - 1.0 */
1323 jwzgles_glColor4f ((GLfloat) r / 0xFFFF,
1324 (GLfloat) g / 0xFFFF,
1325 (GLfloat) b / 0xFFFF,
1326 (GLfloat) a / 0xFFFF);
1330 jwzgles_glColor4usv (const GLushort *v)
1332 jwzgles_glColor4us (v[0], v[1], v[2], v[3]);
1336 jwzgles_glColor3us (GLushort r, GLushort g, GLushort b)
1338 jwzgles_glColor4us (r, g, b, 0xFFFF);
1342 jwzgles_glColor3usv (const GLushort *v)
1344 jwzgles_glColor3us (v[0], v[1], v[2]);
1348 /* glColor: GLbyte (-128 - 127) */
1351 jwzgles_glColor4b (GLbyte r, GLbyte g, GLbyte b, GLbyte a)
1353 /* -128 - 127 => 0.0 - 1.0 */
1354 jwzgles_glColor4f (0.5 + (GLfloat) r / 255,
1355 0.5 + (GLfloat) g / 255,
1356 0.5 + (GLfloat) b / 255,
1357 0.5 + (GLfloat) a / 255);
1361 jwzgles_glColor4bv (const GLbyte *v)
1363 jwzgles_glColor4b (v[0], v[1], v[2], v[3]);
1367 jwzgles_glColor3b (GLbyte r, GLbyte g, GLbyte b)
1369 jwzgles_glColor4b (r, g, b, 127);
1373 jwzgles_glColor3bv (const GLbyte *v)
1375 jwzgles_glColor3b (v[0], v[1], v[2]);
1379 /* glColor: GLubyte (0 - 255) */
1382 jwzgles_glColor4ub (GLubyte r, GLubyte g, GLubyte b, GLubyte a)
1384 /* 0 - 255 => 0.0 - 1.0 */
1385 jwzgles_glColor4f (r / 255.0, g / 255.0, b / 255.0, a / 255.0);
1389 jwzgles_glColor4ubv (const GLubyte *v)
1391 jwzgles_glColor4ub (v[0], v[1], v[2], v[3]);
1395 jwzgles_glColor3ub (GLubyte r, GLubyte g, GLubyte b)
1397 jwzgles_glColor4ub (r, g, b, 255);
1401 jwzgles_glColor3ubv (const GLubyte *v)
1403 jwzgles_glColor3ub (v[0], v[1], v[2]);
1409 jwzgles_glMaterialfv (GLenum face, GLenum pname, const GLfloat *color)
1411 /* If this is called inside glBegin/glEnd with a front ambient color,
1412 then treat it the same as glColor: set the color of the upcoming
1415 Other faces or lighting types within glBegin are ignored.
1418 if (state->compiling_verts)
1420 if ((face == GL_FRONT ||
1421 face == GL_FRONT_AND_BACK) &&
1422 (pname == GL_AMBIENT ||
1423 pname == GL_DIFFUSE ||
1424 pname == GL_AMBIENT_AND_DIFFUSE))
1426 jwzgles_glColor4f (color[0], color[1], color[2], color[3]);
1427 state->set.materialistic++;
1430 LOG2 (" IGNORING glMaterialfv %s %s",
1431 mode_desc(face), mode_desc(pname));
1433 else if (state->compiling_list)
1442 list_push ("glMaterialfv", (list_fn_cb) &jwzgles_glMaterialfv,
1447 /* If this is called outside of glBegin/glEnd with a front
1448 ambient color, then the intent is presumably for that color
1449 to apply to the upcoming vertexes (which may be played back
1450 from a list that does not have vertex colors in it). In that
1451 case, the only way to make the colors show up is to call
1452 glColor() with GL_COLOR_MATERIAL enabled.
1454 I'm not sure if this will have other inappropriate side effects...
1456 if ((face == GL_FRONT ||
1457 face == GL_FRONT_AND_BACK) &&
1458 (pname == GL_AMBIENT ||
1459 pname == GL_DIFFUSE ||
1460 pname == GL_AMBIENT_AND_DIFFUSE))
1462 jwzgles_glEnable (GL_COLOR_MATERIAL);
1463 jwzgles_glColor4f (color[0], color[1], color[2], color[3]);
1466 /* OpenGLES seems to throw "invalid enum" for GL_FRONT -- but it
1467 goes ahead and sets the material anyway! No error if we just
1468 always use GL_FRONT_AND_BACK.
1470 if (face == GL_FRONT)
1471 face = GL_FRONT_AND_BACK;
1472 if (! state->replaying_list)
1473 LOG7 ("direct %-12s %s %s %7.3f %7.3f %7.3f %7.3f", "glMaterialfv",
1474 mode_desc(face), mode_desc(pname),
1475 color[0], color[1], color[2], color[3]);
1476 glMaterialfv (face, pname, color); /* the real one */
1477 CHECK("glMaterialfv");
1483 jwzgles_glMaterialiv (GLenum face, GLenum pname, const GLint *v)
1490 jwzgles_glMaterialfv (face, pname, vv);
1494 jwzgles_glMaterialf (GLenum face, GLenum pname, const GLfloat c)
1501 jwzgles_glMaterialfv (face, pname, vv);
1506 jwzgles_glMateriali (GLenum face, GLenum pname, const GLuint c)
1508 jwzgles_glMaterialf (face, pname, c);
1513 jwzgles_glColorMaterial (GLenum face, GLenum mode)
1515 Assert (!state->compiling_verts,
1516 "glColorMaterial not allowed inside glBegin");
1518 if (state->compiling_list)
1523 list_push ("glColorMaterial", (list_fn_cb) &jwzgles_glColorMaterial,
1528 /* No real analog to this distinction in OpenGLES, since color
1529 arrays don't distinguish between "color" and "material", */
1530 Assert (0, "glColorMaterial: unimplemented mode");
1539 jwzgles_glVertex4fv (const GLfloat *v)
1541 vert_set *s = &state->set;
1542 int count = s->count;
1544 Assert (state->compiling_verts, "glVertex4fv not inside glBegin");
1546 LOG5("%s rec glVertex4f %7.3f %7.3f %7.3f %7.3f",
1547 (state->compiling_list || state->replaying_list ? " " : ""),
1548 v[0], v[1], v[2], v[3]);
1550 if (count >= s->size - 1)
1552 int new_size = 20 + (s->size * 1.2);
1554 /* 4 arrays, different element sizes...
1555 We allocate all 4 arrays just in case we need them,
1556 but we might not end up using them all at the end.
1559 s->verts = (XYZW *) realloc (s->verts, new_size * sizeof (*s->verts));
1560 Assert (s->verts, "out of memory");
1562 s->norms = (XYZ *) realloc (s->norms, new_size * sizeof (*s->norms));
1563 Assert (s->norms, "out of memory");
1565 s->tex = (STRQ *) realloc (s->tex, new_size * sizeof (*s->tex));
1566 Assert (s->tex, "out of memory");
1568 s->color = (RGBA *) realloc (s->color, new_size * sizeof (*s->color));
1569 Assert (s->color, "out of memory");
1574 s->verts [count].x = v[0];
1575 s->verts [count].y = v[1];
1576 s->verts [count].z = v[2];
1577 s->verts [count].w = v[3];
1578 s->norms [count] = s->cnorm;
1579 s->tex [count] = s->ctex;
1580 s->color [count] = s->ccolor;
1586 jwzgles_glVertex4f (GLfloat x, GLfloat y, GLfloat z, GLfloat w)
1593 jwzgles_glVertex4fv (v);
1597 jwzgles_glVertex4i (GLint x, GLint y, GLint z, GLint w)
1599 jwzgles_glVertex4f (x, y, z, w);
1603 jwzgles_glVertex3f (GLfloat x, GLfloat y, GLfloat z)
1610 jwzgles_glVertex4fv (v);
1614 jwzgles_glVertex3i (GLint x, GLint y, GLint z)
1616 jwzgles_glVertex3f (x, y, z);
1620 jwzgles_glVertex3fv (const GLfloat *v)
1622 jwzgles_glVertex3f (v[0], v[1], v[2]);
1626 jwzgles_glVertex3dv (const GLdouble *v)
1628 jwzgles_glVertex3f (v[0], v[1], v[2]);
1633 jwzgles_glVertex2f (GLfloat x, GLfloat y)
1639 jwzgles_glVertex3fv (v);
1643 jwzgles_glVertex2dv (const GLdouble *v)
1645 jwzgles_glVertex2f (v[0], v[1]);
1649 jwzgles_glVertex2fv (const GLfloat *v)
1651 jwzgles_glVertex2f (v[0], v[1]);
1655 jwzgles_glVertex2i (GLint x, GLint y)
1657 jwzgles_glVertex2f (x, y);
1662 jwzgles_glLightiv (GLenum light, GLenum pname, const GLint *params)
1669 jwzgles_glLightfv (light, pname, v);
1673 jwzgles_glLightModeliv (GLenum pname, const GLint *params)
1680 jwzgles_glLightModelfv (pname, v);
1684 jwzgles_glFogiv (GLenum pname, const GLint *params)
1691 jwzgles_glFogfv (pname, v);
1695 jwzgles_glLighti (GLenum light, GLenum pname, GLint param)
1697 jwzgles_glLightf (light, pname, param);
1701 jwzgles_glLightModeli (GLenum pname, GLint param)
1703 jwzgles_glLightModelf (pname, param);
1707 jwzgles_glFogi (GLenum pname, GLint param)
1709 jwzgles_glFogf (pname, param);
1714 jwzgles_glRotated (GLdouble angle, GLdouble x, GLdouble y, GLdouble z)
1716 jwzgles_glRotatef (angle, x, y, z);
1721 jwzgles_glClipPlane (GLenum plane, const GLdouble *equation)
1723 Assert (state->compiling_verts, "glClipPlane not inside glBegin");
1724 Assert (0, "glClipPlane unimplemented"); /* no GLES equivalent... */
1729 jwzgles_glPolygonMode (GLenum face, GLenum mode)
1731 Assert (!state->compiling_verts, "not inside glBegin");
1732 if (state->compiling_list)
1737 list_push ("glPolygonMode", (list_fn_cb) &jwzgles_glPolygonMode,
1742 /* POINT and LINE don't exist in GLES */
1743 Assert (mode == GL_FILL, "glPolygonMode: unimplemented mode");
1749 jwzgles_glDrawBuffer (GLenum buf)
1751 Assert (!state->compiling_verts, "not inside glBegin");
1752 if (state->compiling_list)
1756 list_push ("glDrawBuffer", (list_fn_cb) &jwzgles_glDrawBuffer,
1761 /* Assert (buf == GL_BACK, "glDrawBuffer: back buffer only"); */
1762 # ifndef GL_VERSION_ES_CM_1_0 /* not compiling against OpenGLES 1.x */
1763 if (! state->replaying_list)
1764 LOG1 ("direct %-12s", "glDrawBuffer");
1765 glDrawBuffer (buf); /* the real one */
1766 CHECK("glDrawBuffer");
1772 /* Given an array of sets of 4 elements of arbitrary size, convert it
1773 to an array of sets of 6 elements instead: ABCD becomes ABC BCD.
1776 cq2t (unsigned char **arrayP, int stride, int count)
1778 int count2 = count * 6 / 4;
1779 int size = stride * count;
1780 int size2 = stride * count2;
1781 const unsigned char *oarray, *in;
1782 unsigned char *array2, *oarray2, *out;
1786 if (!oarray || count == 0)
1789 array2 = (unsigned char *) malloc (size2);
1790 Assert (array2, "out of memory");
1795 for (i = 0; i < count / 4; i++)
1797 const unsigned char *a, *b, *c, *d; /* the 4 corners */
1798 a = in; in += stride;
1799 b = in; in += stride;
1800 c = in; in += stride;
1801 d = in; in += stride;
1803 # define PUSH(IN) do { \
1804 const unsigned char *ii = IN; \
1806 for (j = 0; j < stride; j++) { \
1810 PUSH (a); PUSH (b); PUSH (d); /* the 2 triangles */
1811 PUSH (b); PUSH (c); PUSH (d);
1815 Assert (in == oarray + size, "convert_quads corrupted");
1816 Assert (out == oarray2 + size2, "convert_quads corrupted");
1824 /* Convert all coordinates in a GL_QUADS vert_set to GL_TRIANGLES.
1827 convert_quads_to_triangles (vert_set *s)
1830 Assert (s->mode == GL_QUADS, "convert_quads bad mode");
1832 cq2t ((unsigned char **) &s->verts, sizeof(*s->verts), s->count);
1833 cq2t ((unsigned char **) &s->norms, sizeof(*s->norms), s->count);
1834 cq2t ((unsigned char **) &s->tex, sizeof(*s->tex), s->count);
1835 cq2t ((unsigned char **) &s->color, sizeof(*s->color), s->count);
1838 s->mode = GL_TRIANGLES;
1843 jwzgles_glEnd (void)
1845 vert_set *s = &state->set;
1846 int was_norm, was_tex, was_color, was_mat;
1847 int is_norm, is_tex, is_color, is_mat;
1849 Assert (state->compiling_verts == 1, "missing glBegin");
1850 state->compiling_verts--;
1852 Assert (!state->replaying_list, "how did glEnd get into a display list?");
1854 if (!state->replaying_list)
1856 LOG5 ("%s [V = %d, N = %d, T = %d, C = %d]",
1857 (state->compiling_list || state->replaying_list ? " " : ""),
1858 s->count, s->ncount, s->tcount, s->ccount);
1860 (state->compiling_list || state->replaying_list ? " " : ""));
1863 if (s->count == 0) return;
1865 if (s->mode == GL_QUADS)
1866 convert_quads_to_triangles (s);
1867 else if (s->mode == GL_QUAD_STRIP)
1868 s->mode = GL_TRIANGLE_STRIP; /* They do the same thing! */
1869 else if (s->mode == GL_POLYGON)
1870 s->mode = GL_TRIANGLE_FAN; /* They do the same thing! */
1872 jwzgles_glColorPointer (4,GL_FLOAT, sizeof(*s->color),s->color); /* RGBA */
1873 jwzgles_glNormalPointer ( GL_FLOAT, sizeof(*s->norms),s->norms); /* XYZ */
1874 jwzgles_glTexCoordPointer(4,GL_FLOAT, sizeof(*s->tex), s->tex); /* STRQ */
1875 jwzgles_glVertexPointer (4,GL_FLOAT, sizeof(*s->verts),s->verts); /* XYZW */
1876 /* glVertexPointer must come after glTexCoordPointer */
1878 /* If there were no calls to glNormal3f inside of glBegin/glEnd,
1879 don't bother enabling the normals array.
1881 If there was exactly *one* call to glNormal3f inside of glBegin/glEnd,
1882 and it was before the first glVertex3f, then also don't enable the
1883 normals array, but do emit that call to glNormal3f before calling
1886 Likewise for texture coordinates and colors.
1888 Be careful to leave the arrays' enabled/disabled state the same as
1889 before, or a later caller might end up using one of our arrays by
1890 mistake. (Remember that jwzgles_glIsEnabled() tracks the enablement
1891 of the list-in-progress as well as the global state.)
1893 was_norm = jwzgles_glIsEnabled (GL_NORMAL_ARRAY);
1894 was_tex = jwzgles_glIsEnabled (GL_TEXTURE_COORD_ARRAY);
1895 was_color = jwzgles_glIsEnabled (GL_COLOR_ARRAY);
1896 was_mat = jwzgles_glIsEnabled (GL_COLOR_MATERIAL);
1898 /* If we're executing glEnd in immediate mode, not from inside a display
1899 list (which is the only way it happens, because glEnd doesn't go into
1900 display lists), make sure we're not stomping on a saved buffer list:
1901 in immediate mode, vertexes are client-side only.
1903 if (! state->compiling_list)
1904 jwzgles_glBindBuffer (GL_ARRAY_BUFFER, 0);
1909 jwzgles_glEnableClientState (GL_NORMAL_ARRAY);
1915 jwzgles_glNormal3f (s->cnorm.x, s->cnorm.y, s->cnorm.z);
1916 jwzgles_glDisableClientState (GL_NORMAL_ARRAY);
1919 if (s->tcount > 1 ||
1920 ((state->compiling_list ? state->list_enabled : state->enabled)
1921 & (ISENABLED_TEXTURE_GEN_S | ISENABLED_TEXTURE_GEN_T |
1922 ISENABLED_TEXTURE_GEN_R | ISENABLED_TEXTURE_GEN_Q)))
1924 /* Enable texture coords if any were specified; or if generation
1925 is on in immediate mode; or if this list turned on generation. */
1927 jwzgles_glEnableClientState (GL_TEXTURE_COORD_ARRAY);
1933 jwzgles_glTexCoord4f (s->ctex.s, s->ctex.t, s->ctex.r, s->ctex.q);
1934 jwzgles_glDisableClientState (GL_TEXTURE_COORD_ARRAY);
1940 jwzgles_glEnableClientState (GL_COLOR_ARRAY);
1946 jwzgles_glColor4f (s->ccolor.r, s->ccolor.g, s->ccolor.b, s->ccolor.a);
1947 jwzgles_glDisableClientState (GL_COLOR_ARRAY);
1950 jwzgles_glEnableClientState (GL_VERTEX_ARRAY);
1952 /* We translated the glMaterial calls to per-vertex colors, which are
1953 of the glColor sort, not the glMaterial sort, so automatically
1954 turn on material mapping. Maybe this is a bad idea.
1956 if (s->materialistic && !jwzgles_glIsEnabled (GL_COLOR_MATERIAL))
1959 jwzgles_glEnable (GL_COLOR_MATERIAL);
1964 glBindBuffer (GL_ARRAY_BUFFER, 0); /* This comes later. */
1965 jwzgles_glDrawArrays (s->mode, 0, s->count);
1966 glBindBuffer (GL_ARRAY_BUFFER, 0); /* Keep out of others' hands */
1968 # define RESET(VAR,FN,ARG) do { \
1969 if (is_##VAR != was_##VAR) { \
1970 if (was_##VAR) jwzgles_glEnable##FN (ARG); \
1971 else jwzgles_glDisable##FN (ARG); \
1973 RESET (norm, ClientState, GL_NORMAL_ARRAY);
1974 RESET (tex, ClientState, GL_TEXTURE_COORD_ARRAY);
1975 RESET (color, ClientState, GL_COLOR_ARRAY);
1976 RESET (mat, , GL_COLOR_MATERIAL);
1983 s->materialistic = 0;
1987 /* The display list is full of calls to glDrawArrays(), plus saved arrays
1988 of the values we need to restore before calling it. "Restore" means
1989 "ship them off to the GPU before each call".
1991 So instead, this function walks through the display list and
1992 combines all of those vertex, normal, texture and color values into
1993 a single VBO array; ships those values off to the GPU *once* at the
1994 time of glEndList; and when running the list with glCallList, the
1995 values are already on the GPU and don't need to be sent over again.
1997 The VBO persists in the GPU until the display list is deleted.
2000 optimize_arrays (void)
2002 list *L = &state->lists.lists[state->compiling_list-1];
2005 int combo_count = 0;
2007 GLuint buf_name = 0;
2009 Assert (state->compiling_list, "not compiling a list");
2010 Assert (L, "no list");
2011 Assert (!L->buffer, "list already has a buffer");
2013 glGenBuffers (1, &buf_name);
2014 CHECK("glGenBuffers");
2015 if (! buf_name) return;
2017 L->buffer = buf_name;
2019 /* Go through the list and dump the contents of the various saved arrays
2020 into one large array.
2022 for (i = 0; i < L->count; i++)
2024 list_fn *F = &L->fns[i];
2028 /* count = F->argv[2].i;*/ /* 3rd arg to glDrawArrays */
2030 for (j = 0; j < 4; j++)
2032 draw_array *A = &F->arrays[j];
2033 int ocount = combo_count;
2035 /* If some caller is using arrays that don't have floats in them,
2036 we just leave them as-is and ship them over at each call.
2037 Doubt this ever really happens.
2039 if (A->type != GL_FLOAT)
2042 if (! A->data) /* No array. */
2045 Assert (A->bytes > 0, "no bytes in draw_array");
2046 Assert (((unsigned long) A->data > 0xFFFF),
2047 "buffer data not a pointer");
2049 combo_count += A->bytes / sizeof(*combo);
2050 make_room ("optimize_arrays",
2051 (void **) &combo, sizeof(*combo),
2052 &combo_count, &combo_size);
2053 memcpy (combo + ocount, A->data, A->bytes);
2054 A->binding = buf_name;
2056 /* 'data' is now the byte offset into the VBO. */
2057 A->data = (void *) (ocount * sizeof(*combo));
2058 /* LOG3(" loaded %lu floats to pos %d of buffer %d",
2059 A->bytes / sizeof(*combo), ocount, buf_name); */
2063 if (combo_count == 0) /* Nothing to do! */
2065 if (combo) free (combo);
2066 glDeleteBuffers (1, &buf_name);
2071 glBindBuffer (GL_ARRAY_BUFFER, buf_name);
2072 glBufferData (GL_ARRAY_BUFFER,
2073 combo_count * sizeof (*combo),
2076 glBindBuffer (GL_ARRAY_BUFFER, 0); /* Keep out of others' hands */
2078 LOG3(" loaded %d floats of list %d into VBO %d",
2079 combo_count, state->compiling_list, buf_name);
2083 for (i = 0; i < combo_count; i++)
2086 fprintf (stderr, "\njwzgles: %4d: ", i);
2087 fprintf (stderr, " %7.3f", combo[i]);
2089 fprintf (stderr, "\n");
2093 if (combo) free (combo);
2098 jwzgles_glCallList (int id)
2100 if (state->compiling_list)
2102 /* Yes, you can call lists inside of lists.
2103 Yes, recursion would be a mistake. */
2106 list_push ("glCallList", (list_fn_cb) &jwzgles_glCallList, PROTO_I, vv);
2113 state->replaying_list++;
2116 fprintf (stderr, "\n");
2117 LOG1 ("glCallList %d", id);
2120 Assert (id > 0 && id <= state->lists.count, "glCallList: bogus ID");
2121 L = &state->lists.lists[id-1];
2122 Assert (id == L->id, "glCallList corrupted");
2124 for (i = 0; i < L->count; i++)
2126 list_fn *F = &L->fns[i];
2127 list_fn_cb fn = F->fn;
2128 void_int *av = F->argv;
2132 LOG1 (" call %-12s", F->name);
2133 ((void (*) (void)) fn) ();
2137 if (fn == (list_fn_cb) &jwzgles_glBegin ||
2138 fn == (list_fn_cb) &jwzgles_glFrontFace ||
2139 fn == (list_fn_cb) &jwzgles_glEnable ||
2140 fn == (list_fn_cb) &jwzgles_glDisable ||
2141 fn == (list_fn_cb) &jwzgles_glEnableClientState ||
2142 fn == (list_fn_cb) &jwzgles_glDisableClientState ||
2143 fn == (list_fn_cb) &jwzgles_glShadeModel ||
2144 fn == (list_fn_cb) &jwzgles_glMatrixMode)
2145 LOG2 (" call %-12s %s", F->name, mode_desc (av[0].i));
2147 LOG2 (" call %-12s %d", F->name, av[0].i);
2148 ((void (*) (int)) fn) (av[0].i);
2152 LOG2 (" call %-12s %7.3f", F->name, av[0].f);
2153 ((void (*) (GLfloat)) fn) (av[0].f);
2157 if (fn == (list_fn_cb) &jwzgles_glBindTexture ||
2158 fn == (list_fn_cb) &jwzgles_glBindBuffer)
2159 LOG3 (" call %-12s %s %d", F->name,
2160 mode_desc (av[0].i), av[1].i);
2162 LOG3 (" call %-12s %d %d", F->name, av[0].i, av[1].i);
2163 ((void (*) (int, int)) fn) (av[0].i, av[1].i);
2167 LOG3 (" call %-12s %7.3f %7.3f", F->name, av[0].f, av[1].f);
2168 ((void (*) (GLfloat, GLfloat)) fn) (av[0].f, av[1].f);
2172 LOG3 (" call %-12s %s %7.3f", F->name,
2173 mode_desc (av[0].f), av[1].f);
2174 ((void (*) (GLint, GLfloat)) fn) (av[0].i, av[1].f);
2177 case PROTO_III: III:
2178 if (fn == (list_fn_cb) &jwzgles_glDrawArrays ||
2179 fn == (list_fn_cb) &jwzgles_glTexParameteri)
2180 LOG4 (" call %-12s %s %d %d", F->name,
2181 mode_desc (av[0].i), av[1].i, av[2].i);
2183 LOG4 (" call %-12s %d %d %d", F->name,
2184 av[0].i, av[1].i, av[2].i);
2185 ((void (*) (int, int, int)) fn) (av[0].i, av[1].i, av[2].i);
2189 LOG4 (" call %-12s %7.3f %7.3f %7.3f", F->name,
2190 av[0].f, av[1].f, av[2].f);
2191 ((void (*) (GLfloat, GLfloat, GLfloat)) fn)
2192 (av[0].f, av[1].f, av[2].f);
2196 LOG4 (" call %-12s %s %s %7.3f", F->name,
2197 mode_desc (av[0].i), mode_desc (av[1].i), av[2].f);
2198 ((void (*) (int, int, GLfloat)) fn) (av[0].i, av[1].i, av[2].f);
2202 LOG5 (" call %-12s %d %d %d %d", F->name,
2203 av[0].i, av[1].i, av[2].i, av[3].i);
2204 ((void (*) (int, int, int, int)) fn)
2205 (av[0].i, av[1].i, av[2].i, av[3].i);
2209 LOG5 (" call %-12s %7.3f %7.3f %7.3f %7.3f", F->name,
2210 av[0].f, av[1].f, av[2].f, av[3].f);
2211 ((void (*) (GLfloat, GLfloat, GLfloat, GLfloat)) fn)
2212 (av[0].f, av[1].f, av[2].f, av[3].f);
2222 LOG6 (" call %-12s %s %3.1f %3.1f %3.1f %3.1f", F->name,
2223 mode_desc (av[0].i),
2224 av[1].f, av[2].f, av[3].f, av[4].f);
2225 ((void (*) (int, const GLfloat *)) fn) (av[0].i, v);
2236 LOG7 (" call %-12s %s %-8s %3.1f %3.1f %3.1f %3.1f", F->name,
2237 mode_desc (av[0].i), mode_desc (av[1].i),
2238 av[2].f, av[3].f, av[4].f, av[5].f);
2239 ((void (*) (int, int, const GLfloat *)) fn)
2240 (av[0].i, av[1].i, v);
2251 LOG6 (" call %-12s %s %3d %3d %3d %3d", F->name,
2252 mode_desc (av[0].i),
2253 av[1].i, av[2].i, av[3].i, av[4].i);
2254 ((void (*) (int, const int *)) fn) (av[0].i, v);
2265 LOG7 (" call %-12s %s %-8s %3d %3d %3d %3d", F->name,
2266 mode_desc (av[0].i), mode_desc (av[1].i),
2267 av[2].i, av[3].i, av[4].i, av[5].i);
2268 ((void (*) (int, int, const int *)) fn)
2269 (av[0].i, av[1].i, v);
2274 restore_arrays (F, av[1].i + av[2].i);
2282 for (i = 0; i < countof(m); i++)
2284 LOG17 (" call %-12s ["
2285 "%8.3f %8.3f %8.3f %8.3f " "\n\t\t\t "
2286 "%8.3f %8.3f %8.3f %8.3f " "\n\t\t\t "
2287 "%8.3f %8.3f %8.3f %8.3f " "\n\t\t\t "
2288 "%8.3f %8.3f %8.3f %8.3f ]",
2290 m[0], m[1], m[2], m[3],
2291 m[4], m[5], m[6], m[7],
2292 m[8], m[9], m[10], m[11],
2293 m[12], m[13], m[14], m[15]);
2294 ((void (*) (GLfloat *)) fn) (m);
2299 Assert (0, "bogus prototype");
2304 LOG1 ("glCallList %d done\n", id);
2306 state->replaying_list--;
2307 Assert (state->replaying_list >= 0, "glCallList corrupted");
2312 /* When we save a call to glDrawArrays into a display list, we also need to
2313 save the prevailing copy of the arrays that it will use, and restore them
2317 save_arrays (list_fn *F, int count)
2320 draw_array *A = (draw_array *) calloc (4, sizeof (*A));
2321 Assert (A, "out of memory");
2323 /* if (state->set.count > 0) */
2325 jwzgles_glGetIntegerv (GL_VERTEX_ARRAY_BUFFER_BINDING, &A[i].binding);
2326 jwzgles_glGetIntegerv (GL_VERTEX_ARRAY_SIZE, &A[i].size);
2327 jwzgles_glGetIntegerv (GL_VERTEX_ARRAY_TYPE, &A[i].type);
2328 jwzgles_glGetIntegerv (GL_VERTEX_ARRAY_STRIDE, &A[i].stride);
2329 jwzgles_glGetPointerv (GL_VERTEX_ARRAY_POINTER, &A[i].data);
2330 CHECK("glGetPointerv");
2331 copy_array_data (&A[i], count, "vert");
2335 if (state->set.ncount > 1)
2338 jwzgles_glGetIntegerv (GL_NORMAL_ARRAY_BUFFER_BINDING, &A[i].binding);
2339 jwzgles_glGetIntegerv (GL_NORMAL_ARRAY_TYPE, &A[i].type);
2340 jwzgles_glGetIntegerv (GL_NORMAL_ARRAY_STRIDE, &A[i].stride);
2341 jwzgles_glGetPointerv (GL_NORMAL_ARRAY_POINTER, &A[i].data);
2342 CHECK("glGetPointerv");
2343 copy_array_data (&A[i], count, "norm");
2347 if (state->set.tcount > 1)
2349 jwzgles_glGetIntegerv (GL_TEXTURE_COORD_ARRAY_BUFFER_BINDING, &A[i].binding);
2350 jwzgles_glGetIntegerv (GL_TEXTURE_COORD_ARRAY_SIZE, &A[i].size);
2351 jwzgles_glGetIntegerv (GL_TEXTURE_COORD_ARRAY_TYPE, &A[i].type);
2352 jwzgles_glGetIntegerv (GL_TEXTURE_COORD_ARRAY_STRIDE, &A[i].stride);
2353 jwzgles_glGetPointerv (GL_TEXTURE_COORD_ARRAY_POINTER, &A[i].data);
2354 CHECK("glGetPointerv");
2355 copy_array_data (&A[i], count, "tex ");
2359 if (state->set.ccount > 1)
2361 jwzgles_glGetIntegerv (GL_COLOR_ARRAY_BUFFER_BINDING, &A[i].binding);
2362 jwzgles_glGetIntegerv (GL_COLOR_ARRAY_SIZE, &A[i].size);
2363 jwzgles_glGetIntegerv (GL_COLOR_ARRAY_TYPE, &A[i].type);
2364 jwzgles_glGetIntegerv (GL_COLOR_ARRAY_STRIDE, &A[i].stride);
2365 jwzgles_glGetPointerv (GL_COLOR_ARRAY_POINTER, &A[i].data);
2366 CHECK("glGetPointerv");
2367 copy_array_data (&A[i], count, "col ");
2370 /* Freed by glDeleteLists. */
2372 Assert (!F->arrays, "save_arrays corrupted");
2380 dump_array_data (draw_array *A, int count,
2381 const char *action, const char *name, const void *old)
2383 int bytes = count * A->stride;
2388 "jwzgles: %s %s %d %s %2d, %4d = %5d bind %d @ %d\n",
2390 A->size, mode_desc(A->type), A->stride,
2391 count, bytes, A->binding, (int) A->data);
2395 Assert (bytes == A->bytes, "array data corrupted");
2397 fprintf (stderr, "jwzgles: %s %s %d %s %2d, %4d = %5d @ %lX",
2399 A->size, mode_desc(A->type), A->stride,
2400 count, bytes, (unsigned long) A->data);
2402 fprintf (stderr, " / %lX", (unsigned long) old);
2403 fprintf (stderr, "\n");
2408 Assert (((unsigned long) A->binding < 0xFFFF),
2409 "buffer binding should be a numeric index,"
2410 " but looks like a pointer");
2413 /* glGetBufferSubData doesn't actually exist in OpenGLES, but this
2414 was helpful for debugging on real OpenGL... */
2417 fprintf (stderr, "jwzgles: read back:\n");
2418 d = (GLfloat *) malloc (A->bytes);
2419 glGetBufferSubData (GL_ARRAY_BUFFER, (int) A->data,
2420 count * A->stride, (void *) d);
2421 CHECK("glGetBufferSubData");
2422 for (i = 0; i < count * A->size; i++)
2425 fprintf (stderr, "\njwzgles: %4d: ",
2426 i + (int) A->data / sizeof(GLfloat));
2427 fprintf (stderr, " %7.3f", d[i]);
2429 fprintf (stderr, "\n");
2436 unsigned char *b = (unsigned char *) A->data;
2438 if ((unsigned long) A->data < 0xFFFF)
2440 Assert (0, "buffer data not a pointer");
2443 for (i = 0; i < count; i++)
2446 GLfloat *f = (GLfloat *) b;
2448 if (s == 0) s = 3; /* normals */
2449 fprintf (stderr, "jwzgles: ");
2450 for (j = 0; j < s; j++)
2451 fprintf (stderr, " %7.3f", f[j]);
2452 fprintf (stderr, "\n");
2460 dump_direct_array_data (int count)
2462 draw_array A = { 0, };
2464 if (jwzgles_glIsEnabled (GL_VERTEX_ARRAY))
2466 jwzgles_glGetIntegerv (GL_VERTEX_ARRAY_BUFFER_BINDING, &A.binding);
2467 jwzgles_glGetIntegerv (GL_VERTEX_ARRAY_SIZE, &A.size);
2468 jwzgles_glGetIntegerv (GL_VERTEX_ARRAY_TYPE, &A.type);
2469 jwzgles_glGetIntegerv (GL_VERTEX_ARRAY_STRIDE, &A.stride);
2470 jwzgles_glGetPointerv (GL_VERTEX_ARRAY_POINTER, &A.data);
2471 A.bytes = count * A.stride;
2472 dump_array_data (&A, count, "direct", "vertex ", 0);
2474 if (jwzgles_glIsEnabled (GL_NORMAL_ARRAY))
2477 jwzgles_glGetIntegerv (GL_NORMAL_ARRAY_BUFFER_BINDING, &A.binding);
2478 jwzgles_glGetIntegerv (GL_NORMAL_ARRAY_TYPE, &A.type);
2479 jwzgles_glGetIntegerv (GL_NORMAL_ARRAY_STRIDE, &A.stride);
2480 jwzgles_glGetPointerv (GL_NORMAL_ARRAY_POINTER, &A.data);
2481 A.bytes = count * A.stride;
2482 dump_array_data (&A, count, "direct", "normal ", 0);
2484 if (jwzgles_glIsEnabled (GL_TEXTURE_COORD_ARRAY))
2486 jwzgles_glGetIntegerv (GL_TEXTURE_COORD_ARRAY_BUFFER_BINDING, &A.binding);
2487 jwzgles_glGetIntegerv (GL_TEXTURE_COORD_ARRAY_SIZE, &A.size);
2488 jwzgles_glGetIntegerv (GL_TEXTURE_COORD_ARRAY_TYPE, &A.type);
2489 jwzgles_glGetIntegerv (GL_TEXTURE_COORD_ARRAY_STRIDE, &A.stride);
2490 jwzgles_glGetPointerv (GL_TEXTURE_COORD_ARRAY_POINTER, &A.data);
2491 A.bytes = count * A.stride;
2492 dump_array_data (&A, count, "direct", "texture", 0);
2494 if (jwzgles_glIsEnabled (GL_COLOR_ARRAY))
2496 jwzgles_glGetIntegerv (GL_COLOR_ARRAY_BUFFER_BINDING, &A.binding);
2497 jwzgles_glGetIntegerv (GL_COLOR_ARRAY_SIZE, &A.size);
2498 jwzgles_glGetIntegerv (GL_COLOR_ARRAY_TYPE, &A.type);
2499 jwzgles_glGetIntegerv (GL_COLOR_ARRAY_STRIDE, &A.stride);
2500 jwzgles_glGetPointerv (GL_COLOR_ARRAY_POINTER, &A.data);
2501 A.bytes = count * A.stride;
2502 dump_array_data (&A, count, "direct", "color ", 0);
2510 copy_array_data (draw_array *A, int count, const char *name)
2512 /* Instead of just memcopy'ing the whole array and obeying its previous
2513 'stride' value, we make up a more compact array. This is because if
2514 the same array data is being used with multiple component types,
2515 e.g. with glInterleavedArrays, we don't want to copy all of the
2516 data multiple times.
2518 int stride2, bytes, i, j;
2522 const unsigned char *IB;
2525 if (((unsigned long) A->data) < 0xFFFF)
2527 Assert (0, "buffer data not a pointer");
2531 Assert (A->size >= 2 && A->size <= 4, "bogus array size");
2534 case GL_FLOAT: stride2 = A->size * sizeof(GLfloat); break;
2535 case GL_UNSIGNED_BYTE: stride2 = A->size; break;
2536 default: Assert (0, "bogus array type"); break;
2539 bytes = count * stride2;
2540 Assert (bytes > 0, "bogus array count or stride");
2541 Assert (A->data, "missing array data");
2542 data2 = (void *) malloc (bytes);
2543 Assert (data2, "out of memory");
2545 IB = (const unsigned char *) A->data;
2546 OB = (unsigned char *) data2;
2547 IF = (const GLfloat *) A->data;
2548 OF = (GLfloat *) data2;
2552 for (i = 0; i < count; i++)
2554 for (j = 0; j < A->size; j++)
2556 IF = (const GLfloat *) (((const unsigned char *) IF) + A->stride);
2559 case GL_UNSIGNED_BYTE:
2560 for (i = 0; i < count; i++)
2562 for (j = 0; j < A->size; j++)
2568 Assert (0, "bogus array type");
2574 A->stride = stride2;
2577 dump_array_data (A, count, "saved", name, 0);
2583 restore_arrays (list_fn *F, int count)
2586 draw_array *A = F->arrays;
2587 Assert (A, "missing array");
2589 for (i = 0; i < 4; i++)
2591 const char *name = 0;
2596 Assert ((A[i].binding || A[i].data),
2597 "array has neither buffer binding nor data");
2599 glBindBuffer (GL_ARRAY_BUFFER, A[i].binding);
2600 CHECK("glBindBuffer");
2603 case 0: jwzgles_glVertexPointer (A[i].size, A[i].type, A[i].stride, A[i].data);
2605 CHECK("glVertexPointer");
2607 case 1: jwzgles_glNormalPointer ( A[i].type, A[i].stride, A[i].data);
2609 CHECK("glNormalPointer");
2611 case 2: jwzgles_glTexCoordPointer(A[i].size, A[i].type, A[i].stride, A[i].data);
2613 CHECK("glTexCoordPointer");
2615 case 3: jwzgles_glColorPointer (A[i].size, A[i].type, A[i].stride, A[i].data);
2617 CHECK("glColorPointer");
2619 default: Assert (0, "wat"); break;
2623 dump_array_data (&A[i], count, "restored", name, 0);
2628 glBindBuffer (GL_ARRAY_BUFFER, 0); /* Keep out of others' hands */
2633 jwzgles_glDrawArrays (GLuint mode, GLuint first, GLuint count)
2635 /* If we are auto-generating texture coordinates, do that now, after
2636 the vertex array was installed, but before drawing, This happens
2637 when recording into a list, or in direct mode. It must happen
2638 before calling optimize_arrays() from glEndList().
2640 if (! state->replaying_list &&
2641 ((state->compiling_list ? state->list_enabled : state->enabled)
2642 & (ISENABLED_TEXTURE_GEN_S | ISENABLED_TEXTURE_GEN_T |
2643 ISENABLED_TEXTURE_GEN_R | ISENABLED_TEXTURE_GEN_Q)))
2644 generate_texture_coords (first, count);
2646 if (state->compiling_list)
2652 list_push ("glDrawArrays", (list_fn_cb) &jwzgles_glDrawArrays,
2658 if (! state->replaying_list) {
2659 LOG4("direct %-12s %d %d %d", "glDrawArrays", mode, first, count);
2660 dump_direct_array_data (first + count);
2663 glDrawArrays (mode, first, count); /* the real one */
2664 CHECK("glDrawArrays");
2670 jwzgles_glInterleavedArrays (GLenum format, GLsizei stride, const void *data)
2672 /* We can implement this by calling the various *Pointer functions
2673 with offsets into the same data, taking advantage of stride.
2675 const unsigned char *c = (const unsigned char *) data;
2677 # define F sizeof(GLfloat)
2679 Assert (!state->compiling_verts,
2680 "glInterleavedArrays not allowed inside glBegin");
2682 jwzgles_glEnableClientState (GL_VERTEX_ARRAY);
2684 if (!state->replaying_list)
2685 LOG4 ("%sglInterleavedArrays %s %d %lX",
2686 (state->compiling_list || state->replaying_list ? " " : ""),
2687 mode_desc (format), stride, (unsigned long) data);
2691 jwzgles_glVertexPointer (2, GL_FLOAT, stride, c);
2692 CHECK("glVertexPointer");
2693 if (!state->replaying_list)
2694 LOG3 ("%s -> glVertexPointer 2 FLOAT %d %lX",
2695 (state->compiling_list || state->replaying_list ? " " : ""),
2696 stride, (unsigned long) c);
2699 jwzgles_glVertexPointer (3, GL_FLOAT, stride, c);
2700 CHECK("glVertexPointer");
2701 if (!state->replaying_list)
2702 LOG3 ("%s -> glVertexPointer 3 FLOAT %d %lX",
2703 (state->compiling_list || state->replaying_list ? " " : ""),
2704 stride, (unsigned long) c);
2709 jwzgles_glEnableClientState (GL_COLOR_ARRAY);
2710 jwzgles_glColorPointer (4, GL_UNSIGNED_BYTE, stride, c);
2711 CHECK("glColorPointer");
2712 c += 4*B; /* #### might be incorrect float-aligned address */
2713 jwzgles_glVertexPointer (2, GL_FLOAT, stride, c);
2718 jwzgles_glEnableClientState (GL_COLOR_ARRAY);
2719 jwzgles_glColorPointer (4, GL_UNSIGNED_BYTE, stride, c);
2720 CHECK("glColorPointer");
2722 jwzgles_glVertexPointer (3, GL_FLOAT, stride, c);
2723 CHECK("glVertexPointer");
2728 jwzgles_glEnableClientState (GL_COLOR_ARRAY);
2729 jwzgles_glColorPointer (3, GL_FLOAT, stride, c);
2730 CHECK("glColorPointer");
2732 jwzgles_glVertexPointer (3, GL_FLOAT, stride, c);
2733 CHECK("glVertexPointer");
2738 jwzgles_glEnableClientState (GL_NORMAL_ARRAY);
2739 jwzgles_glNormalPointer (GL_FLOAT, stride, c);
2740 CHECK("glNormalPointer");
2741 if (!state->replaying_list)
2742 LOG3 ("%s -> glNormalPointer FLOAT %d %lX",
2743 (state->compiling_list || state->replaying_list ? " " : ""),
2744 stride, (unsigned long) c);
2746 jwzgles_glVertexPointer (3, GL_FLOAT, stride, c);
2747 CHECK("glVertexPointer");
2748 if (!state->replaying_list)
2749 LOG3 ("%s -> glVertexPointer 3 FLOAT %d %lX",
2750 (state->compiling_list || state->replaying_list ? " " : ""),
2751 stride, (unsigned long) c);
2753 case GL_C4F_N3F_V3F:
2755 stride = 4*F + 3*F + 3*F;
2756 jwzgles_glEnableClientState (GL_COLOR_ARRAY);
2757 jwzgles_glColorPointer (4, GL_FLOAT, stride, c);
2758 CHECK("glColorPointer");
2760 jwzgles_glEnableClientState (GL_NORMAL_ARRAY);
2761 jwzgles_glNormalPointer (GL_FLOAT, stride, c);
2762 CHECK("glNormalPointer");
2764 jwzgles_glVertexPointer (3, GL_FLOAT, stride, c);
2765 CHECK("glVertexPointer");
2770 jwzgles_glEnableClientState (GL_TEXTURE_COORD_ARRAY);
2771 jwzgles_glTexCoordPointer (2, GL_FLOAT, stride, c);
2772 CHECK("glTexCoordPointer");
2774 jwzgles_glVertexPointer (3, GL_FLOAT, stride, c);
2775 CHECK("glVertexPointer");
2780 jwzgles_glEnableClientState (GL_TEXTURE_COORD_ARRAY);
2781 jwzgles_glTexCoordPointer (4, GL_FLOAT, stride, c);
2782 CHECK("glTexCoordPointer");
2784 jwzgles_glVertexPointer (4, GL_FLOAT, stride, c);
2785 CHECK("glVertexPointer");
2787 case GL_T2F_C4UB_V3F:
2789 stride = 2*F + 4*B + 3*F;
2790 jwzgles_glEnableClientState (GL_TEXTURE_COORD_ARRAY);
2791 jwzgles_glTexCoordPointer (2, GL_FLOAT, stride, c);
2792 CHECK("glTexCoordPointer");
2794 jwzgles_glEnableClientState (GL_COLOR_ARRAY);
2795 jwzgles_glColorPointer (4, GL_UNSIGNED_BYTE, stride, c);
2796 CHECK("glColorPointer");
2798 jwzgles_glVertexPointer (3, GL_FLOAT, stride, c);
2799 CHECK("glVertexPointer");
2801 case GL_T2F_C3F_V3F:
2803 stride = 2*F + 3*F + 3*F;
2804 jwzgles_glEnableClientState (GL_TEXTURE_COORD_ARRAY);
2805 jwzgles_glTexCoordPointer (2, GL_FLOAT, stride, c);
2806 CHECK("glTexCoordPointer");
2808 jwzgles_glEnableClientState (GL_COLOR_ARRAY);
2809 jwzgles_glColorPointer (3, GL_FLOAT, stride, c);
2810 CHECK("glColorPointer");
2812 jwzgles_glVertexPointer (3, GL_FLOAT, stride, c);
2813 CHECK("glVertexPointer");
2815 case GL_T2F_N3F_V3F:
2817 stride = 2*F + 3*F + 3*F;
2818 jwzgles_glEnableClientState (GL_TEXTURE_COORD_ARRAY);
2819 jwzgles_glTexCoordPointer (2, GL_FLOAT, stride, c);
2820 CHECK("glTexCoordPointer");
2822 jwzgles_glEnableClientState (GL_NORMAL_ARRAY);
2823 jwzgles_glNormalPointer (GL_FLOAT, stride, c);
2824 CHECK("glNormalPointer");
2826 jwzgles_glVertexPointer (3, GL_FLOAT, stride, c);
2827 CHECK("glVertexPointer");
2829 case GL_T2F_C4F_N3F_V3F:
2831 stride = 2*F + 4*F + 3*F + 3*F;
2832 jwzgles_glEnableClientState (GL_TEXTURE_COORD_ARRAY);
2833 jwzgles_glTexCoordPointer (2, GL_FLOAT, stride, c);
2834 CHECK("glTexCoordPointer");
2836 jwzgles_glEnableClientState (GL_COLOR_ARRAY);
2837 jwzgles_glColorPointer (3, GL_FLOAT, stride, c);
2838 CHECK("glColorPointer");
2840 jwzgles_glEnableClientState (GL_NORMAL_ARRAY);
2841 jwzgles_glNormalPointer (GL_FLOAT, stride, c);
2842 CHECK("glNormalPointer");
2844 jwzgles_glVertexPointer (3, GL_FLOAT, stride, c);
2845 CHECK("glVertexPointer");
2847 case GL_T4F_C4F_N3F_V4F:
2849 stride = 4*F + 4*F + 3*F + 4*F;
2850 jwzgles_glEnableClientState (GL_TEXTURE_COORD_ARRAY);
2851 jwzgles_glTexCoordPointer (4, GL_FLOAT, stride, c);
2852 CHECK("glTexCoordPointer");
2854 jwzgles_glEnableClientState (GL_COLOR_ARRAY);
2855 jwzgles_glColorPointer (4, GL_FLOAT, stride, c);
2856 CHECK("glColorPointer");
2858 jwzgles_glEnableClientState (GL_NORMAL_ARRAY);
2859 jwzgles_glNormalPointer (GL_FLOAT, stride, c);
2860 CHECK("glNormalPointer");
2862 jwzgles_glVertexPointer (3, GL_FLOAT, stride, c);
2863 CHECK("glVertexPointer");
2866 Assert (0, "glInterleavedArrays: bogus format");
2877 jwzgles_glMultMatrixf (const GLfloat *m)
2879 Assert (!state->compiling_verts,
2880 "glMultMatrixf not allowed inside glBegin");
2881 if (state->compiling_list)
2885 for (i = 0; i < countof(vv); i++)
2887 list_push ("glMultMatrixf", (list_fn_cb) &jwzgles_glMultMatrixf,
2892 if (! state->replaying_list)
2893 LOG1 ("direct %-12s", "glMultMatrixf");
2894 glMultMatrixf (m); /* the real one */
2895 CHECK("glMultMatrixf");
2901 jwzgles_glClearIndex(GLfloat c)
2903 /* Does GLES even do indexed color? */
2904 Assert (0, "glClearIndex unimplemented");
2909 jwzgles_glBitmap (GLsizei width, GLsizei height, GLfloat xorig, GLfloat yorig,
2910 GLfloat xmove, GLfloat ymove, const GLubyte *bitmap)
2912 Assert (0, "glBitmap unimplemented");
2916 jwzgles_glPushAttrib(int flags)
2918 Assert (0, "glPushAttrib unimplemented");
2922 jwzgles_glPopAttrib(void)
2924 Assert (0, "glPopAttrib unimplemented");
2928 /* These are needed for object hit detection in pinion.
2929 Might need to rewrite that code entirely. Punt for now.
2932 jwzgles_glInitNames (void)
2934 /* Assert (0, "glInitNames unimplemented");*/
2938 jwzgles_glPushName (GLuint name)
2940 /* Assert (0, "glPushName unimplemented");*/
2944 jwzgles_glPopName (void)
2946 /* Assert (0, "glPopName unimplemented");*/
2951 jwzgles_glRenderMode (GLuint mode)
2953 /* Assert (0, "glRenderMode unimplemented");*/
2958 jwzgles_glSelectBuffer (GLsizei size, GLuint *buf)
2960 /* Assert (0, "glSelectBuffer unimplemented");*/
2965 jwzgles_glGenTextures (GLuint n, GLuint *ret)
2967 Assert (!state->compiling_verts,
2968 "glGenTextures not allowed inside glBegin");
2969 /* technically legal, but stupid! */
2970 Assert (!state->compiling_list,
2971 "glGenTextures not allowed inside glNewList");
2972 if (! state->replaying_list)
2973 LOG1 ("direct %-12s", "glGenTextures");
2974 glGenTextures (n, ret); /* the real one */
2975 CHECK("glGenTextures");
2980 jwzgles_glTexImage1D (GLenum target, GLint level,
2981 GLint internalFormat,
2982 GLsizei width, GLint border,
2983 GLenum format, GLenum type,
2986 Assert (!state->compiling_verts, "glTexImage1D not allowed inside glBegin");
2987 /* technically legal, but stupid! */
2988 Assert (!state->compiling_list, "glTexImage1D inside glNewList");
2989 Assert (width == to_pow2(width), "width must be a power of 2");
2991 if (target == GL_TEXTURE_1D) target = GL_TEXTURE_2D;
2992 jwzgles_glTexImage2D (target, level, internalFormat, width, 1,
2993 border, format, type, data);
2997 jwzgles_glTexImage2D (GLenum target,
2999 GLint internalFormat,
3007 GLvoid *d2 = (GLvoid *) data;
3008 Assert (!state->compiling_verts, "glTexImage2D not allowed inside glBegin");
3009 Assert (!state->compiling_list, /* technically legal, but stupid! */
3010 "glTexImage2D not allowed inside glNewList");
3012 Assert (width == to_pow2(width), "width must be a power of 2");
3013 Assert (height == to_pow2(height), "height must be a power of 2");
3015 /* OpenGLES no longer supports "4" as a synonym for "RGBA". */
3016 switch (internalFormat) {
3017 case 1: internalFormat = GL_LUMINANCE; break;
3018 case 2: internalFormat = GL_LUMINANCE_ALPHA; break;
3019 case 3: internalFormat = GL_RGB; break;
3020 case 4: internalFormat = GL_RGBA; break;
3023 /* GLES does not let us omit the data pointer to create a blank texture. */
3026 d2 = (GLvoid *) calloc (1, width * height * sizeof(GLfloat) * 4);
3027 Assert (d2, "out of memory");
3030 if (internalFormat == GL_RGB && format == GL_RGBA)
3031 internalFormat = GL_RGBA; /* WTF */
3032 if (type == GL_UNSIGNED_INT_8_8_8_8_REV)
3033 type = GL_UNSIGNED_BYTE;
3035 if (! state->replaying_list)
3036 LOG10 ("direct %-12s %s %d %s %d %d %d %s %s 0x%lX", "glTexImage2D",
3037 mode_desc(target), level, mode_desc(internalFormat),
3038 width, height, border, mode_desc(format), mode_desc(type),
3039 (unsigned long) d2);
3040 glTexImage2D (target, level, internalFormat, width, height, border,
3041 format, type, d2); /* the real one */
3042 CHECK("glTexImage2D");
3044 if (d2 != data) free (d2);
3048 jwzgles_glTexSubImage2D (GLenum target, GLint level,
3049 GLint xoffset, GLint yoffset,
3050 GLsizei width, GLsizei height,
3051 GLenum format, GLenum type,
3052 const GLvoid *pixels)
3054 Assert (!state->compiling_verts,
3055 "glTexSubImage2D not allowed inside glBegin");
3056 Assert (!state->compiling_list, /* technically legal, but stupid! */
3057 "glTexSubImage2D not allowed inside glNewList");
3059 if (! state->replaying_list)
3060 LOG10 ("direct %-12s %s %d %d %d %d %d %s %s 0x%lX", "glTexSubImage2D",
3061 mode_desc(target), level, xoffset, yoffset, width, height,
3062 mode_desc (format), mode_desc (type), (unsigned long) pixels);
3063 glTexSubImage2D (target, level, xoffset, yoffset, width, height,
3064 format, type, pixels); /* the real one */
3065 CHECK("glTexSubImage2D");
3069 jwzgles_glCopyTexImage2D (GLenum target, GLint level, GLenum internalformat,
3070 GLint x, GLint y, GLsizei width, GLsizei height,
3073 Assert (!state->compiling_verts,
3074 "glCopyTexImage2D not allowed inside glBegin");
3075 Assert (!state->compiling_list, /* technically legal, but stupid! */
3076 "glCopyTexImage2D not allowed inside glNewList");
3077 if (! state->replaying_list)
3078 LOG9 ("direct %-12s %s %d %s %d %d %d %d %d", "glCopyTexImage2D",
3079 mode_desc(target), level, mode_desc(internalformat),
3080 x, y, width, height, border);
3081 glCopyTexImage2D (target, level, internalformat, x, y, width, height,
3082 border); /* the real one */
3083 CHECK("glCopyTexImage2D");
3088 jwzgles_glCopyTexSubImage2D (GLenum target, GLint level,
3089 GLint xoff, GLint yoff,
3091 GLsizei width, GLsizei height)
3093 Assert (!state->compiling_verts,
3094 "glCopyTexSubImage2D not allowed inside glBegin");
3095 Assert (!state->compiling_list, /* technically legal, but stupid! */
3096 "glCopyTexSubImage2D not allowed inside glNewList");
3097 if (! state->replaying_list)
3098 LOG9 ("direct %-12s %s %d %d %d %d %d %d %d", "glCopyTexSubImage2D",
3099 mode_desc(target), level, xoff, yoff, x, y, width, height);
3100 glCopyTexSubImage2D (target, level, /* the real one */
3101 xoff, yoff, x, y, width, height);
3102 CHECK("glCopyTexSubImage2D");
3106 /* OpenGLES doesn't have auto texture-generation at all!
3107 "Oh, just rewrite that code to use GPU shaders", they say.
3108 How fucking convenient.
3111 jwzgles_glTexGenfv (GLenum coord, GLenum pname, const GLfloat *params)
3115 if (pname == GL_TEXTURE_GEN_MODE)
3116 LOG5 ("%sdirect %-12s %s %s %s",
3117 (state->compiling_list || state->replaying_list ? " " : ""),
3119 mode_desc(coord), mode_desc(pname), mode_desc(params[0]));
3121 LOG8 ("%sdirect %-12s %s %s %3.1f %3.1f %3.1f %3.1f",
3122 (state->compiling_list || state->replaying_list ? " " : ""),
3124 mode_desc(coord), mode_desc(pname),
3125 params[0], params[1], params[2], params[3]);
3128 case GL_S: s = &state->s; break;
3129 case GL_T: s = &state->t; break;
3130 case GL_R: s = &state->r; break;
3131 case GL_Q: s = &state->q; break;
3132 default: Assert (0, "glGetTexGenfv: unknown coord"); break;
3136 case GL_TEXTURE_GEN_MODE: s->mode = params[0]; break;
3137 case GL_OBJECT_PLANE: memcpy (s->obj, params, sizeof(s->obj)); break;
3138 case GL_EYE_PLANE: memcpy (s->eye, params, sizeof(s->eye)); break;
3139 default: Assert (0, "glTexGenfv: unknown pname"); break;
3144 jwzgles_glTexGeni (GLenum coord, GLenum pname, GLint param)
3147 jwzgles_glTexGenfv (coord, pname, &v);
3151 jwzgles_glGetTexGenfv (GLenum coord, GLenum pname, GLfloat *params)
3156 case GL_S: s = &state->s; break;
3157 case GL_T: s = &state->t; break;
3158 case GL_R: s = &state->r; break;
3159 case GL_Q: s = &state->q; break;
3160 default: Assert (0, "glGetTexGenfv: unknown coord"); break;
3164 case GL_TEXTURE_GEN_MODE: params[0] = s->mode; break;
3165 case GL_OBJECT_PLANE: memcpy (params, s->obj, sizeof(s->obj)); break;
3166 case GL_EYE_PLANE: memcpy (params, s->eye, sizeof(s->eye)); break;
3167 default: Assert (0, "glGetTexGenfv: unknown pname"); break;
3170 if (pname == GL_TEXTURE_GEN_MODE)
3171 LOG5 ("%sdirect %-12s %s %s -> %s",
3172 (state->compiling_list || state->replaying_list ? " " : ""),
3174 mode_desc(coord), mode_desc(pname), mode_desc(params[0]));
3176 LOG8 ("%sdirect %-12s %s %s -> %3.1f %3.1f %3.1f %3.1f",
3177 (state->compiling_list || state->replaying_list ? " " : ""),
3179 mode_desc(coord), mode_desc(pname),
3180 params[0], params[1], params[2], params[3]);
3185 dot_product (int rank, GLfloat *a, GLfloat *b)
3187 /* A dot B => (A[1] * B[1]) + ... + (A[n] * B[n]) */
3190 for (i = 0; i < rank; i++)
3197 /* Compute the texture coordinates of the prevailing list of verts as per
3198 http://www.opengl.org/wiki/Mathematics_of_glTexGen
3201 generate_texture_coords (GLuint first, GLuint count)
3203 GLfloat *tex_out, *tex_array;
3206 draw_array A = { 0, };
3209 struct { GLuint which, flag, mode; GLfloat plane[4]; } tg[4] = {
3210 { GL_S, ISENABLED_TEXTURE_GEN_S, 0, { 0, } },
3211 { GL_T, ISENABLED_TEXTURE_GEN_T, 0, { 0, } },
3212 { GL_R, ISENABLED_TEXTURE_GEN_R, 0, { 0, } },
3213 { GL_Q, ISENABLED_TEXTURE_GEN_Q, 0, { 0, }}};
3217 /* Read the texture plane configs that were stored with glTexGen.
3219 for (i = 0; i < countof(tg); i++)
3222 if (! ((state->compiling_list ? state->list_enabled : state->enabled)
3225 jwzgles_glGetTexGenfv (tg[i].which, GL_TEXTURE_GEN_MODE, &mode);
3226 jwzgles_glGetTexGenfv (tg[i].which, GL_OBJECT_PLANE, tg[i].plane);
3231 if (tcoords == 0) return; /* Nothing to do! */
3234 /* Make the array to store our texture coords in. */
3236 tex_stride = tcoords * sizeof(GLfloat);
3237 tex_array = (GLfloat *) calloc (first + count, tex_stride);
3238 tex_out = tex_array;
3241 /* Read the prevailing vertex array, that was stored with
3242 glVertexPointer or glInterleavedArrays.
3244 jwzgles_glGetIntegerv (GL_VERTEX_ARRAY_BUFFER_BINDING, &A.binding);
3245 jwzgles_glGetIntegerv (GL_VERTEX_ARRAY_SIZE, &A.size);
3246 jwzgles_glGetIntegerv (GL_VERTEX_ARRAY_TYPE, &A.type);
3247 jwzgles_glGetIntegerv (GL_VERTEX_ARRAY_STRIDE, &A.stride);
3248 jwzgles_glGetPointerv (GL_VERTEX_ARRAY_POINTER, &A.data);
3249 A.bytes = count * A.stride;
3251 verts_in = (char *) A.data;
3253 /* Iterate over each vertex we're drawing.
3254 We just skip the ones < start, but the tex array has
3255 left room for zeroes there anyway.
3257 for (i = first; i < first + count; i++)
3259 GLfloat vert[4] = { 0, };
3262 /* Extract this vertex into `vert' as a float, whatever its type was. */
3263 for (j = 0; j < A.size; j++)
3266 case GL_SHORT: vert[j] = ((GLshort *) verts_in)[j]; break;
3267 case GL_INT: vert[j] = ((GLint *) verts_in)[j]; break;
3268 case GL_FLOAT: vert[j] = ((GLfloat *) verts_in)[j]; break;
3269 case GL_DOUBLE: vert[j] = ((GLdouble *) verts_in)[j]; break;
3270 default: Assert (0, "unknown vertex type"); break;
3274 /* Compute the texture coordinate for this vertex.
3275 For GL_OBJECT_LINEAR, these coordinates are static, and can go
3276 into the display list. But for GL_EYE_LINEAR, GL_SPHERE_MAP and
3277 GL_REFLECTION_MAP, they depend on the prevailing ModelView matrix,
3278 and so need to be computed afresh each time glDrawArrays is called.
3279 Unfortunately, our verts and norms are gone by then, dumped down
3280 into the VBO and discarded from CPU RAM. Bleh.
3282 for (j = 0, k = 0; j < countof(tg); j++)
3284 if (! ((state->compiling_list ? state->list_enabled : state->enabled)
3287 switch (tg[j].mode) {
3288 case GL_OBJECT_LINEAR:
3289 tex_out[k] = dot_product (4, vert, tg[j].plane);
3292 Assert (0, "unimplemented texture mode");
3298 /* fprintf (stderr, "%4d: V %-5.1f %-5.1f %-5.1f T %-5.1f %-5.1f\n",
3299 i, vert[0], vert[1], vert[2], tex_out[0], tex_out[1]); */
3301 /* Move verts_in and tex_out forward to the next vertex by stride. */
3302 verts_in += A.stride;
3303 tex_out = (GLfloat *) (((char *) tex_out) + tex_stride);
3306 jwzgles_glEnableClientState (GL_TEXTURE_COORD_ARRAY);
3307 jwzgles_glTexCoordPointer (tcoords, GL_FLOAT, tex_stride,
3308 (GLvoid *) tex_array);
3314 jwzgles_gluBuild2DMipmaps (GLenum target,
3315 GLint internalFormat,
3322 /* Not really bothering with mipmapping; only making one level.
3323 Note that this required a corresponding hack in glTexParameterf().
3326 GLsizei w2 = (GLsizei)to_pow2(width);
3327 GLsizei h2 = (GLsizei)to_pow2(height);
3329 void *d2 = (void *) data;
3331 /* OpenGLES no longer supports "4" as a synonym for "RGBA". */
3332 switch (internalFormat) {
3333 case 1: internalFormat = GL_LUMINANCE; break;
3334 case 2: internalFormat = GL_LUMINANCE_ALPHA; break;
3335 case 3: internalFormat = GL_RGB; break;
3336 case 4: internalFormat = GL_RGBA; break;
3339 /* if (w2 < h2) w2 = h2;
3340 if (h2 < w2) h2 = w2;*/
3342 if (w2 != width || h2 != height)
3344 /* Scale up the image bits to fit the power-of-2 texture.
3345 We have to do this because the mipmap API assumes that
3346 the texture bits go to texture coordinates 1.0 x 1.0.
3347 This could be more efficient, but it doesn't happen often.
3349 int istride = (format == GL_RGBA ? 4 : 3);
3351 int ibpl = istride * width;
3352 int obpl = ostride * w2;
3354 const unsigned char *in = (unsigned char *) data;
3355 unsigned char *out = (void *) malloc (h2 * obpl);
3356 Assert (out, "out of memory");
3359 for (oy = 0; oy < h2; oy++)
3361 int iy = oy * height / h2;
3362 const unsigned char *iline = in + (iy * ibpl);
3363 unsigned char *oline = out + (oy * obpl);
3365 for (ox = 0; ox < w2; ox++)
3367 int ix = ox * width / w2;
3368 const unsigned char *i = iline + (ix * istride);
3369 unsigned char *o = oline + (ox * ostride);
3370 *o++ = *i++; /* R */
3371 *o++ = *i++; /* G */
3372 *o++ = *i++; /* B */
3373 *o++ = (istride == 4 ? *i : 0xFF); /* A */
3378 internalFormat = GL_RGBA;
3382 jwzgles_glTexImage2D (target, 0, internalFormat, w2, h2, 0,
3384 if (d2 != data) free (d2);
3391 jwzgles_glRectf (GLfloat x1, GLfloat y1, GLfloat x2, GLfloat y2)
3393 jwzgles_glBegin (GL_POLYGON);
3394 jwzgles_glVertex2f (x1, y1);
3395 jwzgles_glVertex2f (x2, y1);
3396 jwzgles_glVertex2f (x2, y2);
3397 jwzgles_glVertex2f (x1, y2);
3402 jwzgles_glRecti (GLint x1, GLint y1, GLint x2, GLint y2)
3404 jwzgles_glRectf (x1, y1, x2, y2);
3408 jwzgles_glClearDepth (GLfloat d)
3410 /* Not sure what to do here */
3411 Assert (d == 1.0, "glClearDepth unimplemented");
3415 /* When in immediate mode, we store a bit into state->enabled, and also
3416 call the real glEnable() / glDisable().
3418 When recording a list, we store a bit into state->list_enabled instead,
3419 so that we can see what the prevailing enablement state will be when
3422 set: 1 = set, -1 = clear, 0 = query.
3425 enable_disable (GLuint bit, int set)
3427 int result = (set > 0);
3430 unsigned long flag = 0;
3433 case GL_TEXTURE_1D: /* We implement 1D textures as 2D textures. */
3434 case GL_TEXTURE_2D: flag = ISENABLED_TEXTURE_2D; break;
3435 case GL_TEXTURE_GEN_S: flag = ISENABLED_TEXTURE_GEN_S; omitp = 1; break;
3436 case GL_TEXTURE_GEN_T: flag = ISENABLED_TEXTURE_GEN_T; omitp = 1; break;
3437 case GL_TEXTURE_GEN_R: flag = ISENABLED_TEXTURE_GEN_R; omitp = 1; break;
3438 case GL_TEXTURE_GEN_Q: flag = ISENABLED_TEXTURE_GEN_Q; omitp = 1; break;
3439 case GL_LIGHTING: flag = ISENABLED_LIGHTING; break;
3440 case GL_BLEND: flag = ISENABLED_BLEND; break;
3441 case GL_DEPTH_TEST: flag = ISENABLED_DEPTH_TEST; break;
3442 case GL_ALPHA_TEST: flag = ISENABLED_ALPHA_TEST; break;
3443 case GL_CULL_FACE: flag = ISENABLED_CULL_FACE; break;
3444 case GL_NORMALIZE: flag = ISENABLED_NORMALIZE; break;
3445 case GL_FOG: flag = ISENABLED_FOG; break;
3446 case GL_COLOR_MATERIAL: flag = ISENABLED_COLMAT; break;
3448 /* Maybe technically these only work with glEnableClientState,
3449 but we treat that as synonymous with glEnable. */
3450 case GL_VERTEX_ARRAY: flag = ISENABLED_VERT_ARRAY; csp = 1; break;
3451 case GL_NORMAL_ARRAY: flag = ISENABLED_NORM_ARRAY; csp = 1; break;
3452 case GL_COLOR_ARRAY: flag = ISENABLED_COLOR_ARRAY; csp = 1; break;
3453 case GL_TEXTURE_COORD_ARRAY: flag = ISENABLED_TEX_ARRAY; csp = 1; break;
3456 Assert (set != 0, "glIsEnabled unimplemented bit");
3460 if (set) /* setting or unsetting, not querying */
3462 const char *fns[4] = { "glEnable", "glDisable",
3463 "glEnableClientState", "glDisableClientState" };
3464 list_fn_cb fs[4] = { (list_fn_cb) &jwzgles_glEnable,
3465 (list_fn_cb) &jwzgles_glDisable,
3466 (list_fn_cb) &jwzgles_glEnableClientState,
3467 (list_fn_cb) &jwzgles_glDisableClientState };
3468 const char *fn = fns[(csp ? 2 : 0) + (set < 0 ? 1 : 0)];
3469 list_fn_cb f = fs[(csp ? 2 : 0) + (set < 0 ? 1 : 0)];
3471 Assert (!state->compiling_verts,
3472 "glEnable/glDisable not allowed inside glBegin");
3474 if (state->compiling_list)
3478 list_push (fn, f,PROTO_I, vv);
3481 if (! state->replaying_list &&
3482 ! state->compiling_list)
3483 LOG2 ("direct %-12s %s", fn, mode_desc(bit));
3485 if (csp && !state->compiling_verts)
3489 case GL_NORMAL_ARRAY: state->set.ncount += 2; break;
3490 case GL_TEXTURE_COORD_ARRAY: state->set.tcount += 2; break;
3491 case GL_COLOR_ARRAY: state->set.ccount += 2; break;
3496 case GL_NORMAL_ARRAY: state->set.ncount = 0; break;
3497 case GL_TEXTURE_COORD_ARRAY: state->set.tcount = 0; break;
3498 case GL_COLOR_ARRAY: state->set.ccount = 0; break;
3503 if (omitp || state->compiling_list)
3505 else if (set > 0 && csp)
3506 glEnableClientState (bit); /* the real one */
3507 else if (set < 0 && csp)
3508 glDisableClientState (bit); /* the real one */
3510 glEnable (bit); /* the real one */
3512 glDisable (bit); /* the real one */
3517 /* Store the bit in our state as well, or query it.
3521 unsigned long *enabled = (state->compiling_list
3522 ? &state->list_enabled
3529 result = !!(*enabled & flag);
3537 jwzgles_glEnable (GLuint bit)
3539 enable_disable (bit, 1);
3543 jwzgles_glDisable (GLuint bit)
3545 enable_disable (bit, -1);
3549 jwzgles_glIsEnabled (GLuint bit)
3551 return enable_disable (bit, 0);
3555 jwzgles_glEnableClientState (GLuint cap)
3557 enable_disable (cap, 1);
3561 jwzgles_glDisableClientState (GLuint cap)
3563 enable_disable (cap, -1);
3567 #define GET(pname, value) \
3572 /* The spec says that OpenGLES 1.0 doesn't implement glGetFloatv.
3574 iOS provides 1.1 (and glGetFloatv by extension) at the very minimum.
3576 Android goes down to 1.0. In particular, this includes the emulator when
3577 running without GPU emulation. Actual devices that don't support 1.1 are
3578 extremely rare at this point.
3580 OpenGL ES 1.0 sucks because without glGetFloatv there is no way to retrieve
3581 the prevailing matrixes. To implement this, we'd have to keep track of
3582 them all on the client side by combining in all the actions of
3583 glMultMatrixf, glRotatef, etc. Right now, we're only keeping track of the
3584 gl*Pointer functions.
3587 jwzgles_glGetFloatv (GLenum pname, GLfloat *params)
3589 if (! state->replaying_list)
3590 LOG2 ("direct %-12s %s", "glGetFloatv", mode_desc(pname));
3594 /* OpenGL ES 1.0 omits a few dozen properties that 1.1 supports. The
3595 following, however, is sufficient to get things basically working in the
3599 GET(GL_VERTEX_ARRAY_BUFFER_BINDING, state->varray.binding)
3600 GET(GL_VERTEX_ARRAY_SIZE, state->varray.size)
3601 GET(GL_VERTEX_ARRAY_TYPE, state->varray.type)
3602 GET(GL_VERTEX_ARRAY_STRIDE, state->varray.stride)
3604 GET(GL_NORMAL_ARRAY_BUFFER_BINDING, state->narray.binding)
3605 GET(GL_NORMAL_ARRAY_TYPE, state->narray.type)
3606 GET(GL_NORMAL_ARRAY_STRIDE, state->narray.stride)
3608 GET(GL_COLOR_ARRAY_BUFFER_BINDING, state->carray.binding)
3609 GET(GL_COLOR_ARRAY_SIZE, state->carray.size)
3610 GET(GL_COLOR_ARRAY_TYPE, state->carray.type)
3611 GET(GL_COLOR_ARRAY_STRIDE, state->carray.stride)
3613 GET(GL_TEXTURE_COORD_ARRAY_BUFFER_BINDING, state->tarray.binding)
3614 GET(GL_TEXTURE_COORD_ARRAY_SIZE, state->tarray.size)
3615 GET(GL_TEXTURE_COORD_ARRAY_TYPE, state->tarray.type)
3616 GET(GL_TEXTURE_COORD_ARRAY_STRIDE, state->tarray.stride)
3619 glGetFloatv (pname, params); /* the real one */
3623 CHECK("glGetFloatv");
3628 jwzgles_glGetPointerv (GLenum pname, GLvoid **params)
3630 if (! state->replaying_list)
3631 LOG2 ("direct %-12s %s", "glGetPointerv", mode_desc(pname));
3635 GET(GL_VERTEX_ARRAY_POINTER, state->varray.data)
3636 GET(GL_NORMAL_ARRAY_POINTER, state->narray.data)
3637 GET(GL_COLOR_ARRAY_POINTER, state->carray.data)
3638 GET(GL_TEXTURE_COORD_ARRAY_POINTER, state->tarray.data)
3641 glGetPointerv (pname, params); /* the real one */
3644 CHECK("glGetPointerv");
3650 /* How many cells are written into the *params array.
3651 We need to know this to avoid smashing the caller's stack
3652 if they asked for a single-value parameter.
3655 glGet_ret_count (GLenum pname)
3658 /*case GL_COLOR_MATRIX: */
3659 case GL_MODELVIEW_MATRIX:
3660 case GL_PROJECTION_MATRIX:
3661 case GL_TEXTURE_MATRIX:
3662 /*case GL_TRANSPOSE_COLOR_MATRIX: */
3663 /*case GL_TRANSPOSE_MODELVIEW_MATRIX: */
3664 /*case GL_TRANSPOSE_PROJECTION_MATRIX: */
3665 /*case GL_TRANSPOSE_TEXTURE_MATRIX: */
3667 /*case GL_ACCUM_CLEAR_VALUE: */
3668 /*case GL_BLEND_COLOR: */
3669 case GL_COLOR_CLEAR_VALUE:
3670 case GL_COLOR_WRITEMASK:
3671 case GL_CURRENT_COLOR:
3672 /*case GL_CURRENT_RASTER_COLOR: */
3673 /*case GL_CURRENT_RASTER_POSITION: */
3674 /*case GL_CURRENT_RASTER_SECONDARY_COLOR: */
3675 /*case GL_CURRENT_RASTER_TEXTURE_COORDS: */
3676 /*case GL_CURRENT_SECONDARY_COLOR: */
3677 case GL_CURRENT_TEXTURE_COORDS:
3679 case GL_LIGHT_MODEL_AMBIENT:
3680 /*case GL_MAP2_GRID_DOMAIN: */
3681 case GL_SCISSOR_BOX:
3684 case GL_CURRENT_NORMAL:
3685 case GL_POINT_DISTANCE_ATTENUATION:
3687 case GL_ALIASED_LINE_WIDTH_RANGE:
3688 case GL_ALIASED_POINT_SIZE_RANGE:
3689 case GL_DEPTH_RANGE:
3690 /*case GL_LINE_WIDTH_RANGE: */
3691 /*case GL_MAP1_GRID_DOMAIN: */
3692 /*case GL_MAP2_GRID_SEGMENTS: */
3693 case GL_MAX_VIEWPORT_DIMS:
3694 /*case GL_POINT_SIZE_RANGE: */
3695 case GL_POLYGON_MODE:
3696 case GL_SMOOTH_LINE_WIDTH_RANGE:
3697 case GL_SMOOTH_POINT_SIZE_RANGE:
3706 jwzgles_glGetDoublev (GLenum pname, GLdouble *params)
3709 int i, j = glGet_ret_count (pname);
3710 jwzgles_glGetFloatv (pname, m);
3711 for (i = 0; i < j; i++)
3717 jwzgles_glGetIntegerv (GLenum pname, GLint *params)
3720 int i, j = glGet_ret_count (pname);
3721 jwzgles_glGetFloatv (pname, m);
3722 for (i = 0; i < j; i++)
3728 jwzgles_glGetBooleanv (GLenum pname, GLboolean *params)
3731 int i, j = glGet_ret_count (pname);
3732 jwzgles_glGetFloatv (pname, m);
3733 for (i = 0; i < j; i++)
3734 params[i] = (m[i] != 0.0);
3739 jwzgles_gluErrorString (GLenum error)
3742 sprintf (s, "0x%lX", (unsigned long) error);
3747 /* These four *Pointer calls (plus glBindBuffer and glBufferData) can
3748 be included inside glNewList, but they actually execute immediately
3749 anyway, because their data is recorded in the list by the
3750 subsequently-recorded call to glDrawArrays. This is a little weird.
3753 jwzgles_glVertexPointer (GLuint size, GLuint type, GLuint stride,
3756 if (! state->replaying_list)
3757 LOG5 ("direct %-12s %d %s %d 0x%lX", "glVertexPointer",
3758 size, mode_desc(type), stride, (unsigned long) ptr);
3760 state->varray.size = size;
3761 state->varray.type = type;
3762 state->varray.stride = stride;
3763 state->varray.data = (GLvoid *)ptr;
3765 glVertexPointer (size, type, stride, ptr); /* the real one */
3766 CHECK("glVertexPointer");
3771 jwzgles_glNormalPointer (GLuint type, GLuint stride, const GLvoid *ptr)
3773 if (! state->replaying_list)
3774 LOG4 ("direct %-12s %s %d 0x%lX", "glNormalPointer",
3775 mode_desc(type), stride, (unsigned long) ptr);
3777 state->narray.type = type;
3778 state->narray.stride = stride;
3779 state->narray.data = (GLvoid *)ptr;
3781 glNormalPointer (type, stride, ptr); /* the real one */
3782 CHECK("glNormalPointer");
3786 jwzgles_glColorPointer (GLuint size, GLuint type, GLuint stride,
3789 if (! state->replaying_list)
3790 LOG5 ("direct %-12s %d %s %d 0x%lX", "glColorPointer",
3791 size, mode_desc(type), stride, (unsigned long) ptr);
3793 state->carray.size = size;
3794 state->carray.type = type;
3795 state->carray.stride = stride;
3796 state->carray.data = (GLvoid *)ptr;
3798 glColorPointer (size, type, stride, ptr); /* the real one */
3799 CHECK("glColorPointer");
3803 jwzgles_glTexCoordPointer (GLuint size, GLuint type, GLuint stride,
3806 if (! state->replaying_list)
3807 LOG5 ("direct %-12s %d %s %d 0x%lX", "glTexCoordPointer",
3808 size, mode_desc(type), stride, (unsigned long) ptr);
3810 state->tarray.size = size;
3811 state->tarray.type = type;
3812 state->tarray.stride = stride;
3813 state->tarray.data = (GLvoid *)ptr;
3815 glTexCoordPointer (size, type, stride, ptr); /* the real one */
3816 CHECK("glTexCoordPointer");
3820 jwzgles_glBindBuffer (GLuint target, GLuint buffer)
3822 if (! state->replaying_list)
3823 LOG3 ("direct %-12s %s %d", "glBindBuffer", mode_desc(target), buffer);
3824 glBindBuffer (target, buffer); /* the real one */
3825 CHECK("glBindBuffer");
3829 jwzgles_glBufferData (GLenum target, GLsizeiptr size, const void *data,
3832 if (! state->replaying_list)
3833 LOG5 ("direct %-12s %s %ld 0x%lX %s", "glBufferData",
3834 mode_desc(target), size, (unsigned long) data, mode_desc(usage));
3835 glBufferData (target, size, data, usage); /* the real one */
3836 CHECK("glBufferData");
3841 jwzgles_glTexParameterf (GLuint target, GLuint pname, GLfloat param)
3843 Assert (!state->compiling_verts,
3844 "glTexParameterf not allowed inside glBegin");
3846 /* We don't *really* implement mipmaps, so just turn this off. */
3847 if (param == GL_LINEAR_MIPMAP_LINEAR) param = GL_LINEAR;
3848 if (param == GL_NEAREST_MIPMAP_LINEAR) param = GL_LINEAR;
3849 if (param == GL_LINEAR_MIPMAP_NEAREST) param = GL_NEAREST;
3850 if (param == GL_NEAREST_MIPMAP_NEAREST) param = GL_NEAREST;
3852 /* We implement 1D textures as 2D textures. */
3853 if (target == GL_TEXTURE_1D) target = GL_TEXTURE_2D;
3855 /* Apparently this is another invalid enum. Just ignore it. */
3856 if ((pname == GL_TEXTURE_WRAP_S || pname == GL_TEXTURE_WRAP_T) &&
3860 if (state->compiling_list)
3866 list_push ("glTexParameterf", (list_fn_cb) &jwzgles_glTexParameterf,
3871 if (! state->replaying_list)
3872 LOG4 ("direct %-12s %s %s %7.3f", "glTexParameterf",
3873 mode_desc(target), mode_desc(pname), param);
3874 glTexParameterf (target, pname, param); /* the real one */
3875 CHECK("glTexParameterf");
3880 jwzgles_glTexParameteri (GLuint target, GLuint pname, GLuint param)
3882 jwzgles_glTexParameterf (target, pname, param);
3887 jwzgles_glBindTexture (GLuint target, GLuint texture)
3889 Assert (!state->compiling_verts,
3890 "glBindTexture not allowed inside glBegin");
3892 /* We implement 1D textures as 2D textures. */
3893 if (target == GL_TEXTURE_1D) target = GL_TEXTURE_2D;
3895 if (state->compiling_list)
3900 list_push ("glBindTexture", (list_fn_cb) &jwzgles_glBindTexture,
3904 /* Do it immediately as well, for generate_texture_coords */
3907 if (! state->replaying_list)
3908 LOG3 ("direct %-12s %s %d", "glBindTexture",
3909 mode_desc(target), texture);
3910 glBindTexture (target, texture); /* the real one */
3911 CHECK("glBindTexture");
3917 /* Matrix functions, mostly cribbed from Mesa.
3921 jwzgles_glFrustum (GLfloat left, GLfloat right,
3922 GLfloat bottom, GLfloat top,
3923 GLfloat near, GLfloat far)
3926 GLfloat x = (2 * near) / (right-left);
3927 GLfloat y = (2 * near) / (top - bottom);
3928 GLfloat a = (right + left) / (right - left);
3929 GLfloat b = (top + bottom) / (top - bottom);
3930 GLfloat c = -(far + near) / (far - near);
3931 GLfloat d = -(2 * far * near) / (far - near);
3933 # define M(X,Y) m[Y * 4 + X]
3934 M(0,0) = x; M(0,1) = 0; M(0,2) = a; M(0,3) = 0;
3935 M(1,0) = 0; M(1,1) = y; M(1,2) = b; M(1,3) = 0;
3936 M(2,0) = 0; M(2,1) = 0; M(2,2) = c; M(2,3) = d;
3937 M(3,0) = 0; M(3,1) = 0; M(3,2) = -1; M(3,3) = 0;
3940 jwzgles_glMultMatrixf (m);
3945 jwzgles_glOrtho (GLfloat left, GLfloat right,
3946 GLfloat bottom, GLfloat top,
3947 GLfloat near, GLfloat far)
3950 GLfloat a = 2 / (right - left);
3951 GLfloat b = -(right + left) / (right - left);
3952 GLfloat c = 2 / (top - bottom);
3953 GLfloat d = -(top + bottom) / (top - bottom);
3954 GLfloat e = -2 / (far - near);
3955 GLfloat f = -(far + near) / (far - near);
3957 # define M(X,Y) m[Y * 4 + X]
3958 M(0,0) = a; M(0,1) = 0; M(0,2) = 0; M(0,3) = b;
3959 M(1,0) = 0; M(1,1) = c; M(1,2) = 0; M(1,3) = d;
3960 M(2,0) = 0; M(2,1) = 0; M(2,2) = e; M(2,3) = f;
3961 M(3,0) = 0; M(3,1) = 0; M(3,2) = 0; M(3,3) = 1;
3964 jwzgles_glMultMatrixf (m);
3969 jwzgles_gluPerspective (GLdouble fovy, GLdouble aspect,
3970 GLdouble near, GLdouble far)
3974 double rad = fovy / 2 * M_PI / 180;
3979 if (dz == 0 || si == 0 || aspect == 0)
3985 c = -(far + near) / dz;
3986 d = -2 * near * far / dz;
3988 # define M(X,Y) m[Y * 4 + X]
3989 M(0,0) = a; M(0,1) = 0; M(0,2) = 0; M(0,3) = 0;
3990 M(1,0) = 0; M(1,1) = b; M(1,2) = 0; M(1,3) = 0;
3991 M(2,0) = 0; M(2,1) = 0; M(2,2) = c; M(2,3) = d;
3992 M(3,0) = 0; M(3,1) = 0; M(3,2) = -1; M(3,3) = 0;
3995 jwzgles_glMultMatrixf (m);
4000 jwzgles_gluLookAt (GLfloat eyex, GLfloat eyey, GLfloat eyez,
4001 GLfloat centerx, GLfloat centery, GLfloat centerz,
4002 GLfloat upx, GLfloat upy, GLfloat upz)
4005 GLfloat x[3], y[3], z[3];
4008 /* Make rotation matrix */
4011 z[0] = eyex - centerx;
4012 z[1] = eyey - centery;
4013 z[2] = eyez - centerz;
4014 mag = sqrt(z[0] * z[0] + z[1] * z[1] + z[2] * z[2]);
4015 if (mag) { /* mpichler, 19950515 */
4026 /* X vector = Y cross Z */
4027 x[0] = y[1] * z[2] - y[2] * z[1];
4028 x[1] = -y[0] * z[2] + y[2] * z[0];
4029 x[2] = y[0] * z[1] - y[1] * z[0];
4031 /* Recompute Y = Z cross X */
4032 y[0] = z[1] * x[2] - z[2] * x[1];
4033 y[1] = -z[0] * x[2] + z[2] * x[0];
4034 y[2] = z[0] * x[1] - z[1] * x[0];
4036 /* mpichler, 19950515 */
4037 /* cross product gives area of parallelogram, which is < 1.0 for
4038 * non-perpendicular unit-length vectors; so normalize x, y here
4041 mag = sqrt(x[0] * x[0] + x[1] * x[1] + x[2] * x[2]);
4048 mag = sqrt(y[0] * y[0] + y[1] * y[1] + y[2] * y[2]);
4055 #define M(row,col) m[col*4+row]
4056 M(0, 0) = x[0]; M(0, 1) = x[1]; M(0, 2) = x[2]; M(0, 3) = 0.0;
4057 M(1, 0) = y[0]; M(1, 1) = y[1]; M(1, 2) = y[2]; M(1, 3) = 0.0;
4058 M(2, 0) = z[0]; M(2, 1) = z[1]; M(2, 2) = z[2]; M(2, 3) = 0.0;
4059 M(3, 0) = 0.0; M(3, 1) = 0.0; M(3, 2) = 0.0; M(3, 3) = 1.0;
4062 jwzgles_glMultMatrixf(m);
4064 /* Translate Eye to Origin */
4065 jwzgles_glTranslatef(-eyex, -eyey, -eyez);
4069 static void __gluMultMatrixVecd (const GLdouble matrix[16],
4070 const GLdouble in[4],
4075 for (i=0; i<4; i++) {
4077 in[0] * matrix[0*4+i] +
4078 in[1] * matrix[1*4+i] +
4079 in[2] * matrix[2*4+i] +
4080 in[3] * matrix[3*4+i];
4085 jwzgles_gluProject (GLdouble objx, GLdouble objy, GLdouble objz,
4086 const GLdouble modelMatrix[16],
4087 const GLdouble projMatrix[16],
4088 const GLint viewport[4],
4089 GLdouble *winx, GLdouble *winy, GLdouble *winz)
4094 /* #### I suspect this is not working right. I was seeing crazy values
4095 in lament.c. Maybe there's some float-vs-double confusion going on?
4102 __gluMultMatrixVecd(modelMatrix, in, out);
4103 __gluMultMatrixVecd(projMatrix, out, in);
4104 if (in[3] == 0.0) return(GL_FALSE);
4108 /* Map x, y and z to range 0-1 */
4109 in[0] = in[0] * 0.5 + 0.5;
4110 in[1] = in[1] * 0.5 + 0.5;
4111 in[2] = in[2] * 0.5 + 0.5;
4113 /* Map x,y to viewport */
4114 in[0] = in[0] * viewport[2] + viewport[0];
4115 in[1] = in[1] * viewport[3] + viewport[1];
4124 /* OpenGL ES has different extensions vs. regular OpenGL, but the basic
4125 principle for checking for extensions is the same.
4128 jwzgles_gluCheckExtension (const GLubyte *ext_name, const GLubyte *ext_string)
4130 size_t ext_len = strlen ((const char *)ext_name);
4133 const GLubyte *found = (const GLubyte *)strstr ((const char *)ext_string,
4134 (const char *)ext_name);
4138 char last_ch = found[ext_len];
4139 if ((found == ext_string || found[-1] == ' ') &&
4140 (last_ch == ' ' || !last_ch)) {
4144 ext_string = found + ext_len;
4151 void jwzgles_glViewport (GLuint x, GLuint y, GLuint w, GLuint h)
4153 # if TARGET_IPHONE_SIMULATOR
4154 /* fprintf (stderr, "glViewport %dx%d\n", w, h); */
4156 glViewport (x, y, w, h); /* the real one */
4160 /* The following functions are present in both OpenGL 1.1 and in OpenGLES 1,
4161 but are allowed within glNewList/glEndList, so we must wrap them to allow
4162 them to either be recorded in lists, or run directly.
4164 All this CPP obscenity is me screaming in rage at all the ways that C is
4165 not Lisp, as all I want to do here is DEFADVICE.
4168 #define PROTO_V PROTO_VOID
4169 #define TYPE_V GLuint
4171 #define VARS_V /* */
4173 #define FILL_V /* */
4175 #define TYPE_I GLuint
4176 #define TYPE_II TYPE_I
4177 #define TYPE_III TYPE_I
4178 #define TYPE_IIII TYPE_I
4179 #define ARGS_I TYPE_I a
4180 #define ARGS_II TYPE_I a, TYPE_I b
4181 #define ARGS_III TYPE_I a, TYPE_I b, TYPE_I c
4182 #define ARGS_IIII TYPE_I a, TYPE_I b, TYPE_I c, TYPE_I d
4183 #define LOGS_I "%s\n", mode_desc(a)
4184 #define LOGS_II "%s %d\n", mode_desc(a), b
4185 #define LOGS_III "%s %s %s\n", mode_desc(a), mode_desc(b), mode_desc(c)
4186 #define LOGS_IIII "%d %d %d %d\n", a, b, c, d
4188 #define VARS_II a, b
4189 #define VARS_III a, b, c
4190 #define VARS_IIII a, b, c, d
4191 #define FILL_I vv[0].i = a;
4192 #define FILL_II vv[0].i = a; vv[1].i = b;
4193 #define FILL_III vv[0].i = a; vv[1].i = b; vv[2].i = c;
4194 #define FILL_IIII vv[0].i = a; vv[1].i = b; vv[2].i = c; vv[3].i = d;
4196 #define TYPE_F GLfloat
4197 #define TYPE_FF TYPE_F
4198 #define TYPE_FFF TYPE_F
4199 #define TYPE_FFFF TYPE_F
4200 #define ARGS_F TYPE_F a
4201 #define ARGS_FF TYPE_F a, TYPE_F b
4202 #define ARGS_FFF TYPE_F a, TYPE_F b, TYPE_F c
4203 #define ARGS_FFFF TYPE_F a, TYPE_F b, TYPE_F c, TYPE_F d
4204 #define LOGS_F "%7.3f\n", a
4205 #define LOGS_FF "%7.3f %7.3f\n", a, b
4206 #define LOGS_FFF "%7.3f %7.3f %7.3f\n", a, b, c
4207 #define LOGS_FFFF "%7.3f %7.3f %7.3f %7.3f\n", a, b, c, d
4208 #define VARS_F VARS_I
4209 #define VARS_FF VARS_II
4210 #define VARS_FFF VARS_III
4211 #define VARS_FFFF VARS_IIII
4212 #define FILL_F vv[0].f = a;
4213 #define FILL_FF vv[0].f = a; vv[1].f = b;
4214 #define FILL_FFF vv[0].f = a; vv[1].f = b; vv[2].f = c;
4215 #define FILL_FFFF vv[0].f = a; vv[1].f = b; vv[2].f = c; vv[3].f = d;
4217 #define ARGS_IF TYPE_I a, TYPE_F b
4218 #define VARS_IF VARS_II
4219 #define LOGS_IF "%s %7.3f\n", mode_desc(a), b
4220 #define FILL_IF vv[0].i = a; vv[1].f = b;
4222 #define ARGS_IIF TYPE_I a, TYPE_I b, TYPE_F c
4223 #define VARS_IIF VARS_III
4224 #define LOGS_IIF "%s %s %7.3f\n", mode_desc(a), mode_desc(b), c
4225 #define FILL_IIF vv[0].i = a; vv[1].i = b; vv[2].f = c;
4227 #define TYPE_IV GLint
4228 #define ARGS_IIV TYPE_I a, const TYPE_IV *b
4229 #define VARS_IIV VARS_II
4230 #define LOGS_IIV "%s %d %d %d %d\n", mode_desc(a), b[0], b[1], b[2], b[3]
4231 #define FILL_IIV vv[0].i = a; \
4232 vv[1].i = b[0]; vv[2].i = b[1]; \
4233 vv[3].i = b[2]; vv[4].i = b[3];
4235 #define ARGS_IFV TYPE_I a, const TYPE_F *b
4236 #define VARS_IFV VARS_II
4237 #define LOGS_IFV "%s %7.3f %7.3f %7.3f %7.3f\n", mode_desc(a), \
4238 b[0], b[1], b[2], b[3]
4239 #define FILL_IFV vv[0].i = a; \
4240 vv[1].f = b[0]; vv[2].f = b[1]; \
4241 vv[3].f = b[2]; vv[4].f = b[3];
4243 #define ARGS_IIIV TYPE_I a, TYPE_I b, const TYPE_IV *c
4244 #define VARS_IIIV VARS_III
4245 #define LOGS_IIIV "%s %-8s %3d %3d %3d %3d\n", mode_desc(a), mode_desc(b), \
4246 c[0], c[1], c[2], c[3]
4247 #define FILL_IIIV vv[0].i = a; vv[1].i = b; \
4248 vv[2].i = c[0]; vv[3].i = c[1]; \
4249 vv[4].i = c[2]; vv[5].i = c[3];
4251 #define ARGS_IIFV TYPE_I a, TYPE_I b, const TYPE_F *c
4252 #define VARS_IIFV VARS_III
4253 #define LOGS_IIFV "%s %-8s %7.3f %7.3f %7.3f %7.3f\n", \
4254 mode_desc(a), mode_desc(b), \
4255 c[0], c[1], c[2], c[3]
4256 #define FILL_IIFV vv[0].i = a; vv[1].i = b; \
4257 vv[2].f = c[0]; vv[3].f = c[1]; \
4258 vv[4].f = c[2]; vv[5].f = c[3];
4261 # define WLOG(NAME,ARGS) \
4262 fprintf (stderr, "jwzgles: direct %-12s ", NAME); \
4263 fprintf (stderr, ARGS)
4265 # define WLOG(NAME,ARGS) /* */
4268 #define WRAP(NAME,SIG) \
4269 void jwzgles_##NAME (ARGS_##SIG) \
4271 Assert (!state->compiling_verts, \
4272 STRINGIFY(NAME) " not allowed inside glBegin"); \
4273 if (state->compiling_list) { \
4276 list_push (STRINGIFY(NAME), (list_fn_cb) &jwzgles_##NAME, \
4279 if (! state->replaying_list) { \
4280 WLOG (STRINGIFY(NAME), LOGS_##SIG); \
4282 NAME (VARS_##SIG); \
4283 CHECK(STRINGIFY(NAME)); \
4287 WRAP (glActiveTexture, I)
4288 WRAP (glAlphaFunc, IF)
4289 WRAP (glBlendFunc, II)
4291 WRAP (glClearColor, FFFF)
4292 WRAP (glClearStencil, I)
4293 WRAP (glColorMask, IIII)
4294 WRAP (glCullFace, I)
4295 WRAP (glDepthFunc, I)
4296 WRAP (glDepthMask, I)
4301 WRAP (glFrontFace, I)
4303 WRAP (glLightModelf, IF)
4304 WRAP (glLightModelfv, IFV)
4305 WRAP (glLightf, IIF)
4306 WRAP (glLightfv, IIFV)
4307 WRAP (glLineWidth, F)
4308 WRAP (glLoadIdentity, V)
4310 WRAP (glMatrixMode, I)
4311 WRAP (glPixelStorei, II)
4312 WRAP (glPointSize, F)
4313 WRAP (glPolygonOffset, FF)
4314 WRAP (glPopMatrix, V)
4315 WRAP (glPushMatrix, V)
4316 WRAP (glRotatef, FFFF)
4317 WRAP (glScalef, FFF)
4318 WRAP (glScissor, IIII)
4319 WRAP (glShadeModel, I)
4320 WRAP (glStencilFunc, III)
4321 WRAP (glStencilMask, I)
4322 WRAP (glStencilOp, III)
4323 WRAP (glTexEnvf, IIF)
4324 WRAP (glTexEnvi, III)
4325 WRAP (glTranslatef, FFF)
4327 #define TYPE_IV GLuint
4328 WRAP (glDeleteTextures, IIV)
4331 #endif /* HAVE_JWZGLES - whole file */