X-Git-Url: http://git.hungrycats.org/cgi-bin/gitweb.cgi?p=xscreensaver;a=blobdiff_plain;f=hacks%2Fglx%2Fjwzgles.c;fp=hacks%2Fglx%2Fjwzgles.c;h=0000000000000000000000000000000000000000;hp=5b0b51a5dfc2a6506a92c2f1f0da7147385d08c4;hb=aa75c7476aeaa84cf3abc192b376a8b03c325213;hpb=88cfe534a698a0562e81345957a50714af1453bc diff --git a/hacks/glx/jwzgles.c b/hacks/glx/jwzgles.c deleted file mode 100644 index 5b0b51a5..00000000 --- a/hacks/glx/jwzgles.c +++ /dev/null @@ -1,4166 +0,0 @@ -/* xscreensaver, Copyright (c) 2012-2015 Jamie Zawinski - * - * Permission to use, copy, modify, distribute, and sell this software and its - * documentation for any purpose is hereby granted without fee, provided that - * the above copyright notice appear in all copies and that both that - * copyright notice and this permission notice appear in supporting - * documentation. No representations are made about the suitability of this - * software for any purpose. It is provided "as is" without express or - * implied warranty. - */ - -/* A compatibility shim to allow OpenGL 1.3 source code to work in an - OpenGLES environment, where almost every OpenGL 1.3 function has - been "deprecated". - - There are two major operations going on here: - - - Converting calls to glBegin + glVertex3f + glEnd to glDrawArrays - - Implementing display lists. - - - From an API point of view, OpenGL 1.3 and earlier code looks like this: - - glLightfv (GL_LIGHT0, GL_POSITION, ...); - glLightfv (GL_LIGHT0, GL_AMBIENT, ...); - - glMatrixMode (GL_PROJECTION); - glLoadIdentity (); - gluPerspective (...); - - glMatrixMode (GL_MODELVIEW); - glLoadIdentity (); - gluLookAt (...); - - glPushMatrix (); - - glRotatef (...); - - glColor3f (...); - - glBegin (GL_TRIANGLES); - glNormal3f (...); - glVertex3f (...); - glVertex3f (...); - glVertex3f (...); - glEnd (); - - glPopMatrix (); - - glFinish (); - - - OpenGLES broke that model by eliminating glBegin(). Instead of - iterating a sequence of vertexes, you need to pack your points into - an array first, e.g.: - - GLfloat coords[] = { - 0, 0, 0, - 0, 1, 0, - ... - }; - - glDrawArrays (GL_TRIANGLES, 0, 3); - - The projection model (glRotatef, etc.) works the same, but glColor() - is missing. You're expected to encode that into your arrays. - - Also, OpenGLES doesn't support display lists at all. - - - So this code shadows all of the functions that are allowed within - glBegin, builds up an array, and calls glDrawArrays at the end. - - Likewise, it shadows all of the functions that are allowed within - glNewList and records those calls for later playback. - - - This code only handles OpenGLES 1.x, not 2.x. - - OpenGLES 2.0 broke things further by eliminating the whole OpenGL - lighting model. Instead of specifying the positions and properties - of your lights using the glLight* API, now you are expected to - implement it all yourself by downloading C-like code into the GPU - directly. This is more flexible, in that if you wanted a completely - different lighting model than what OpenGL provides, you could do - that, but it leaves you needing to download boilerplate to reproduce - what used to be built in. - - - Incidentally, the OpenGL numbering scheme goes something like this: - - OpenGL 1.0 1992 - OpenGL 1.1 1997 (improved texture support) - OpenGL 1.2 1998 (nothing interesting) - OpenGL 1.3 2001 (multisampling, cubemaps) - OpenGL 1.4 2002 (added auto-mipmapping) - OpenGLES 1.0 2003 (deprecated 80% of the language; fork of OpenGL 1.3) - OpenGL 1.5 2003 (added VBOs) - OpenGLES 1.1 2004 (fork of OpenGL 1.5) - OpenGL 2.0 2004 (a political quagmire) - OpenGLES 2.0 2007 (deprecated 95% of the language; fork of OpenGL 2.0) - OpenGL 3.0 2008 (added FBOs, VAOs, deprecated 60% of the language) - - - Some things that are missing: - - - glTexGeni, meaning no spherical environment-mapping textures. - - - gluNewTess, meaning no tesselation of complex objects. - - - glMap2f mesh evaluators, meaning no Utah Teapot. - - - glPolygonMode with GL_LINE or GL_POINT, meaning no wireframe modes - that do hidden-surface removal. - - - glSelectBuffer, meaning no mouse-hit detection on rendered objects. - - - gluNewQuadric, gluCylinder, etc: rewrite your code to use tube.c, etc. - - - Putting verts in a display list without a wrapping glBegin. - I didn't realize that even worked! Lockward used to do that, - before I fixed it to not. - - - Not every function is implemented; just the ones that I needed for - xscreensaver. However, the trivial ones are trivial to enable - as they come up. Harder ones will be harder. - - As a result of that, these savers look wrong: - - atlantis Uses EYE_PLANE. - blocktube Uses SPHERE_MAP. - dnalogo Uses GLUtesselator. - extrusion Uses all kinds of GLUT crap. - flyingtoasters Uses SPHERE_MAP. - winduprobot Uses SPHERE_MAP. - jigglypuff Uses SPHERE_MAP (in chrome mode), GL_LINE (in wireframe) - jigsaw Uses GLUtesselator. - pinion Uses glSelectBuffer and gluPickMatrix for mouse-clicks. - pipes Uses glMap2f for the Utah Teapot. - polyhedra Uses GLUtesselator (concave objects); also Utah Teapot. - skytentacles Uses GL_LINE in -cel mode. - timetunnel Uses GL_CONSTANT_ALPHA and all kinds of other stuff. -*/ - - -#undef DEBUG - - -#ifdef HAVE_CONFIG_H -# include "config.h" -#endif /* HAVE_CONFIG_H */ - -#ifdef HAVE_JWZGLES /* whole file */ - -#include -#include -#include -#include -#include -#ifdef HAVE_UNISTD_H -# include -#endif /* HAVE_UNISTD_H */ - -#if defined(USE_IPHONE) -# include -# include -#elif defined(HAVE_COCOA) -# include -# include -#elif defined(HAVE_ANDROID) -# include -#else /* real X11 */ -# ifndef GL_GLEXT_PROTOTYPES -# define GL_GLEXT_PROTOTYPES /* for glBindBuffer */ -# endif -# include -# include -#endif - -#include "jwzglesI.h" - -#define STRINGIFY(X) #X - -#undef countof -#define countof(x) (sizeof((x))/sizeof((*x))) - -#undef Assert - -#ifdef HAVE_COCOA - extern void jwxyz_abort (const char *fmt, ...) __dead2; -# define Assert(C,S) do { if (!(C)) { jwxyz_abort ("%s",S); }} while(0) -#else -# define Assert(C,S) do { \ - if (!(C)) { \ - fprintf (stderr, "jwzgles: %s\n", S); \ - abort(); \ - }} while(0) -#endif - - -typedef struct { GLfloat x, y, z; } XYZ; -typedef struct { GLfloat x, y, z, w; } XYZW; -typedef struct { GLfloat s, t, r, q; } STRQ; -typedef struct { GLfloat r, g, b, a; } RGBA; - - -/* Used to record all calls to glVertex3f, glNormal3f, etc. - while inside glBegin / glEnd so that we can convert that - to a single call to glDrawArrays. - */ -typedef struct { - int mode; - int count, size; /* size of each array */ - - XYZW *verts; /* Arrays being built */ - XYZ *norms; - STRQ *tex; - RGBA *color; - - int ncount; /* How many normals, tex coords and colors were */ - int tcount; /* used. We optimize based on "0, 1, or many". */ - int ccount; - int materialistic; /* Whether glMaterial was called inside glBegin */ - - XYZ cnorm; /* Prevailing normal/texture/color while building */ - STRQ ctex; - RGBA ccolor; - -} vert_set; - - -typedef void (*list_fn_cb) (void); - - -/* We need this nonsense because you can't cast a double to a void* - or vice versa. They tend to be passed in different registers, - and you need to know about that because it's still 1972 here. - */ -typedef union { - const void *v; GLfloat f; GLuint i; GLshort s; GLdouble d; -} void_int; - -typedef struct { /* saved args for glDrawArrays */ - int binding, size, type, stride, bytes; - void *data; -} draw_array; - -typedef enum { /* shorthand describing arglist signature */ - PROTO_VOID, /* no args */ - PROTO_I, /* 1 int arg */ - PROTO_F, /* 1 float arg */ - PROTO_II, /* int, int */ - PROTO_FF, /* float, float */ - PROTO_IF, /* int, float */ - PROTO_III, /* int, int, int */ - PROTO_FFF, /* float, float, float */ - PROTO_IIF, /* int, int, float */ - PROTO_IIII, /* int, int, int, int */ - PROTO_FFFF, /* float, float, float, float */ - PROTO_IIV, /* int, int[4] */ - PROTO_IFV, /* int, float[4] */ - PROTO_IIIV, /* int, int, int[4] */ - PROTO_IIFV, /* int, int, float[4] */ - PROTO_FV16, /* float[16] */ - PROTO_ARRAYS /* glDrawArrays */ -} fn_proto; - -typedef struct { /* A single element of a display list */ - const char *name; - list_fn_cb fn; /* saved function pointer */ - fn_proto proto; /* arglist prototype */ - draw_array *arrays; /* args for glDrawArrays */ - void_int argv[16]; /* args for everything else */ -} list_fn; - - -typedef struct { /* a display list: saved activity within glNewList */ - int id; - int size, count; - list_fn *fns; - - /* Named buffer that should be freed when this display list is deleted. */ - GLuint buffer; - -} list; - - -typedef struct { /* All display lists */ - list *lists; - int count, size; -} list_set; - - -#define ISENABLED_TEXTURE_2D (1<<0) -#define ISENABLED_TEXTURE_GEN_S (1<<1) -#define ISENABLED_TEXTURE_GEN_T (1<<2) -#define ISENABLED_TEXTURE_GEN_R (1<<3) -#define ISENABLED_TEXTURE_GEN_Q (1<<4) -#define ISENABLED_LIGHTING (1<<5) -#define ISENABLED_BLEND (1<<6) -#define ISENABLED_DEPTH_TEST (1<<7) -#define ISENABLED_CULL_FACE (1<<8) -#define ISENABLED_NORMALIZE (1<<9) -#define ISENABLED_FOG (1<<10) -#define ISENABLED_COLMAT (1<<11) -#define ISENABLED_VERT_ARRAY (1<<12) -#define ISENABLED_NORM_ARRAY (1<<13) -#define ISENABLED_TEX_ARRAY (1<<14) -#define ISENABLED_COLOR_ARRAY (1<<15) -#define ISENABLED_ALPHA_TEST (1<<16) - - -typedef struct { - GLuint mode; - GLfloat obj[4], eye[4]; -} texgen_state; - - -typedef struct { /* global state */ - - vert_set set; /* set being built */ - - int compiling_list; /* list id if inside glNewList; 0 means immediate */ - int replaying_list; /* depth of call stack to glCallList */ - int compiling_verts; /* inside glBegin */ - - list_set lists; /* saved lists */ - - unsigned long enabled; /* enabled flags, immediate mode */ - unsigned long list_enabled; /* and for the list-in-progress */ - - texgen_state s, t, r, q; - -} jwzgles_state; - - -static jwzgles_state *state = 0; - - -#ifdef DEBUG -# define LOG(A) fprintf(stderr,"jwzgles: " A "\n") -# define LOG1(A,B) fprintf(stderr,"jwzgles: " A "\n",B) -# define LOG2(A,B,C) fprintf(stderr,"jwzgles: " A "\n",B,C) -# define LOG3(A,B,C,D) fprintf(stderr,"jwzgles: " A "\n",B,C,D) -# define LOG4(A,B,C,D,E) fprintf(stderr,"jwzgles: " A "\n",B,C,D,E) -# define LOG5(A,B,C,D,E,F) fprintf(stderr,"jwzgles: " A "\n",B,C,D,E,F) -# define LOG6(A,B,C,D,E,F,G) fprintf(stderr,"jwzgles: " A "\n",B,C,D,E,F,G) -# define LOG7(A,B,C,D,E,F,G,H) fprintf(stderr,"jwzgles: " A "\n",B,C,D,E,F,G,H) -# define LOG8(A,B,C,D,E,F,G,H,I)\ - fprintf(stderr,"jwzgles: "A "\n",B,C,D,E,F,G,H,I) -# define LOG9(A,B,C,D,E,F,G,H,I,J)\ - fprintf(stderr,"jwzgles: "A "\n",B,C,D,E,F,G,H,I,J) -# define LOG10(A,B,C,D,E,F,G,H,I,J,K)\ - fprintf(stderr,"jwzgles: "A "\n",B,C,D,E,F,G,H,I,J,K) -# define LOG17(A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R)\ - fprintf(stderr,"jwzgles: "A "\n",B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R) -# define CHECK(S) check_gl_error(S) -#else -# define LOG(A) /* */ -# define LOG1(A,B) /* */ -# define LOG2(A,B,C) /* */ -# define LOG3(A,B,C,D) /* */ -# define LOG4(A,B,C,D,E) /* */ -# define LOG5(A,B,C,D,E,F) /* */ -# define LOG6(A,B,C,D,E,F,G) /* */ -# define LOG7(A,B,C,D,E,F,G,H) /* */ -# define LOG8(A,B,C,D,E,F,G,H,I) /* */ -# define LOG9(A,B,C,D,E,F,G,H,I,J) /* */ -# define LOG10(A,B,C,D,E,F,G,H,I,J,K) /* */ -# define LOG17(A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R) /* */ -# define CHECK(S) /* */ -#endif - -#ifdef DEBUG -static const char * -mode_desc (int mode) /* for debugging messages */ -{ - switch (mode) { -# define SS(X) case GL_##X: return STRINGIFY(X); - SS(ALPHA) - SS(ALPHA_TEST) - SS(AMBIENT) - SS(AMBIENT_AND_DIFFUSE) - SS(ARRAY_BUFFER) - SS(AUTO_NORMAL) - SS(BACK) - SS(BLEND) - SS(BLEND_DST) - SS(BLEND_SRC) - SS(BLEND_SRC_ALPHA) - SS(BYTE) - SS(C3F_V3F) - SS(C4F_N3F_V3F) - SS(C4UB_V2F) - SS(C4UB_V3F) - SS(CCW) - SS(CLAMP) - SS(COLOR_ARRAY) - SS(COLOR_ARRAY_BUFFER_BINDING); - SS(COLOR_MATERIAL) - SS(COLOR_MATERIAL_FACE) - SS(COLOR_MATERIAL_PARAMETER) - SS(COMPILE) - SS(CULL_FACE) - SS(CW) - SS(DECAL) - SS(DEPTH_BUFFER_BIT) - SS(DEPTH_TEST) - SS(DIFFUSE) - SS(DOUBLEBUFFER) - SS(DST_ALPHA) - SS(DST_COLOR) - SS(DYNAMIC_DRAW) - SS(ELEMENT_ARRAY_BUFFER) - SS(EYE_LINEAR) - SS(EYE_PLANE) - SS(FEEDBACK) - SS(FILL) - SS(FLAT) - SS(FLOAT) - SS(FOG) - SS(FRONT) - SS(FRONT_AND_BACK) - SS(GREATER) - SS(INTENSITY) - SS(INVALID_ENUM) - SS(INVALID_OPERATION) - SS(INVALID_VALUE) - SS(LESS) - SS(LIGHT0) - SS(LIGHT1) - SS(LIGHT2) - SS(LIGHT3) - SS(LIGHTING) - SS(LIGHT_MODEL_AMBIENT) - SS(LIGHT_MODEL_COLOR_CONTROL) - SS(LIGHT_MODEL_LOCAL_VIEWER) - SS(LIGHT_MODEL_TWO_SIDE) - SS(LINE) - SS(LINEAR) - SS(LINEAR_MIPMAP_LINEAR) - SS(LINEAR_MIPMAP_NEAREST) - SS(LINES) - SS(LINE_LOOP) - SS(LINE_STRIP) - SS(LUMINANCE) - SS(LUMINANCE_ALPHA) - SS(MATRIX_MODE) - SS(MODELVIEW) - SS(MODULATE) - SS(N3F_V3F) - SS(NEAREST) - SS(NEAREST_MIPMAP_LINEAR) - SS(NEAREST_MIPMAP_NEAREST) - SS(NORMALIZE) - SS(NORMAL_ARRAY) - SS(NORMAL_ARRAY_BUFFER_BINDING); - SS(OBJECT_LINEAR) - SS(OBJECT_PLANE) - SS(ONE_MINUS_DST_ALPHA) - SS(ONE_MINUS_DST_COLOR) - SS(ONE_MINUS_SRC_ALPHA) - SS(ONE_MINUS_SRC_COLOR) - SS(OUT_OF_MEMORY) - SS(PACK_ALIGNMENT) - SS(POINTS) - SS(POLYGON) - SS(POLYGON_OFFSET_FILL) - SS(POLYGON_SMOOTH) - SS(POLYGON_STIPPLE) - SS(POSITION) - SS(PROJECTION) - SS(Q) - SS(QUADS) - SS(QUAD_STRIP) - SS(R) - SS(RENDER) - SS(REPEAT) - SS(RGB) - SS(RGBA) - SS(RGBA_MODE) - SS(S) - SS(SELECT) - SS(SEPARATE_SPECULAR_COLOR) - SS(SHADE_MODEL) - SS(SHININESS) - SS(SHORT) - SS(SINGLE_COLOR) - SS(SMOOTH) - SS(SPECULAR) - SS(SPHERE_MAP) - SS(SRC_ALPHA) - SS(SRC_ALPHA_SATURATE) - SS(SRC_COLOR) - SS(STACK_OVERFLOW) - SS(STACK_UNDERFLOW) - SS(STATIC_DRAW) - SS(STENCIL_BUFFER_BIT) - SS(T) - SS(T2F_C3F_V3F) - SS(T2F_C4F_N3F_V3F) - SS(T2F_C4UB_V3F) - SS(T2F_N3F_V3F) - SS(T2F_V3F) - SS(T4F_C4F_N3F_V4F) - SS(T4F_V4F) - SS(TEXTURE) - SS(TEXTURE_1D) - SS(TEXTURE_2D) - SS(TEXTURE_ALPHA_SIZE) - SS(TEXTURE_BINDING_2D) - SS(TEXTURE_BLUE_SIZE) - SS(TEXTURE_BORDER) - SS(TEXTURE_BORDER_COLOR) - SS(TEXTURE_COMPONENTS) - SS(TEXTURE_COORD_ARRAY) - SS(TEXTURE_COORD_ARRAY_BUFFER_BINDING); - SS(TEXTURE_ENV) - SS(TEXTURE_ENV_COLOR) - SS(TEXTURE_ENV_MODE) - SS(TEXTURE_GEN_MODE) - SS(TEXTURE_GEN_Q) - SS(TEXTURE_GEN_R) - SS(TEXTURE_GEN_S) - SS(TEXTURE_GEN_T) - SS(TEXTURE_GREEN_SIZE) - SS(TEXTURE_HEIGHT) - SS(TEXTURE_INTENSITY_SIZE) - SS(TEXTURE_LUMINANCE_SIZE) - SS(TEXTURE_MAG_FILTER) - SS(TEXTURE_MIN_FILTER) - SS(TEXTURE_RED_SIZE) - SS(TEXTURE_WRAP_S) - SS(TEXTURE_WRAP_T) - SS(TRIANGLES) - SS(TRIANGLE_FAN) - SS(TRIANGLE_STRIP) - SS(UNPACK_ALIGNMENT) - SS(UNPACK_ROW_LENGTH) - SS(UNSIGNED_BYTE) - SS(UNSIGNED_INT_8_8_8_8_REV) - SS(UNSIGNED_SHORT) - SS(V2F) - SS(V3F) - SS(VERTEX_ARRAY) - SS(VERTEX_ARRAY_BUFFER_BINDING); -/*SS(COLOR_BUFFER_BIT) -- same value as GL_LIGHT0 */ -# undef SS - case (GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT): - return "DEPTH_BUFFER_BIT | COLOR_BUFFER_BIT"; -/* Oops, same as INVALID_ENUM. - case (GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT): - return "DEPTH_BUFFER_BIT | STENCIL_BUFFER_BIT"; -*/ - case (GL_COLOR_BUFFER_BIT | GL_STENCIL_BUFFER_BIT): - return "COLOR_BUFFER_BIT | STENCIL_BUFFER_BIT"; - case (GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT | GL_STENCIL_BUFFER_BIT): - return "DEPTH_BUFFER_BIT | COLOR_BUFFER_BIT | STENCIL_BUFFER_BIT"; - default: - { - static char buf[255]; - sprintf (buf, "0x%04X", mode); - return buf; - } - } -} - -static void -check_gl_error (const char *s) -{ - GLenum i = glGetError(); - if (i == GL_NO_ERROR) return; - fprintf (stderr, "jwzgles: GL ERROR: %s: %s\n", s, mode_desc(i)); -} - -#endif /* DEBUG */ - - -static void -make_room (const char *name, void **array, int span, int *count, int *size) -{ - if (*count + 1 >= *size) - { - int new_size = (*count + 20) * 1.2; /* mildly exponential */ - *array = realloc (*array, new_size * span); - Assert (*array, "out of memory"); - /* LOG3("%s: grew %d -> %d", name, *size, new_size); */ - *size = new_size; - } -} - - -void -jwzgles_reset (void) -{ - if (! state) - state = (jwzgles_state *) calloc (1, sizeof (*state)); - - if (state->lists.lists) - { - state->compiling_list = 0; - if (state->lists.count) - jwzgles_glDeleteLists (1, state->lists.count); - free (state->lists.lists); - } - - if (state->set.verts) free (state->set.verts); - if (state->set.norms) free (state->set.norms); - if (state->set.tex) free (state->set.tex); - if (state->set.color) free (state->set.color); - - memset (state, 0, sizeof(*state)); - - state->s.mode = state->t.mode = state->r.mode = state->q.mode = - GL_EYE_LINEAR; - state->s.obj[0] = state->s.eye[0] = 1; /* s = 1 0 0 0 */ - state->t.obj[1] = state->t.eye[1] = 1; /* t = 0 1 0 0 */ -} - - -int -jwzgles_glGenLists (int n) -{ - int i; - int ret = 0; - - Assert (!state->compiling_verts, "glGenLists not allowed inside glBegin"); - - /* Ensure space in state->lists, clear the one at the end, and tick counter - Note that lists are never really deleted, and we can never re-use elements - of this array. glDeleteLists zeroes out the contents of the list, but - the list ID is still valid for use with glNewList forever. - #### So maybe this should be a linked list instead of an array. - */ - for (i = 0; i < n; i++) - { - list *L; - int id = 0; - make_room ("glGenLists", - (void **) &state->lists.lists, - sizeof (*state->lists.lists), - &state->lists.count, &state->lists.size); - state->lists.count++; - id = state->lists.count; - L = &state->lists.lists[id-1]; - - memset (L, 0, sizeof (*L)); - L->id = id; - if (ret == 0) ret = id; - LOG1("glGenLists -> %d", L->id); - } - - /* Return the ID of the first list allocated */ - - return ret; -} - - -void -jwzgles_glNewList (int id, int mode) -{ - list *L; - Assert (id > 0 && id <= state->lists.count, "glNewList: bogus ID"); - Assert (mode == GL_COMPILE, "glNewList: bad mode"); - Assert (!state->compiling_verts, "glNewList not allowed inside glBegin"); - Assert (!state->compiling_list, "nested glNewList"); - Assert (state->set.count == 0, "missing glEnd"); - - L = &state->lists.lists[id-1]; - Assert (L->id == id, "glNewList corrupted"); - - if (L->count != 0) jwzgles_glDeleteLists (L->id, 1); /* Overwriting */ - Assert (L->count == 0, "glNewList corrupted"); - - state->compiling_list = id; - - state->list_enabled = state->enabled; - - LOG1("glNewList -> %d", id); -} - - -static void save_arrays (list_fn *, int); -static void restore_arrays (list_fn *, int); -static void copy_array_data (draw_array *, int, const char *); -static void optimize_arrays (void); -static void generate_texture_coords (GLuint, GLuint); - - -void -jwzgles_glEndList (void) -{ - Assert (state->compiling_list, "extra glEndList"); - Assert (state->set.count == 0, "missing glEnd"); - Assert (!state->compiling_verts, "glEndList not allowed inside glBegin"); - LOG1("glEndList %d", state->compiling_list); - optimize_arrays(); - state->compiling_list = 0; - state->list_enabled = state->enabled; -} - - -static void -list_push (const char * const name, - list_fn_cb fn, fn_proto proto, void_int *av) -{ - list *L; - list_fn *F; - int i; - - Assert (state->compiling_list > 0, "not inside glNewList"); - Assert (state->compiling_list <= state->lists.count, "glNewList corrupted"); - - L = &state->lists.lists[state->compiling_list-1]; - Assert (L, "glNewList: no list"); - - make_room ("glNewLists", - (void **) &L->fns, sizeof (*L->fns), - &L->count, &L->size); - memset (&L->fns[L->count], 0, sizeof (*L->fns)); - F = L->fns + L->count; - - F->name = name; - F->fn = fn; - F->proto = proto; - if (proto != PROTO_VOID) - for (i = 0; i < countof(F->argv); i++) - F->argv[i] = av[i]; - -# ifdef DEBUG - switch (proto) { - case PROTO_VOID: - LOG1 (" push %-12s", name); - break; - case PROTO_I: - if (fn == (list_fn_cb) &jwzgles_glBegin || - fn == (list_fn_cb) &jwzgles_glFrontFace || - fn == (list_fn_cb) &jwzgles_glEnable || - fn == (list_fn_cb) &jwzgles_glDisable || - fn == (list_fn_cb) &jwzgles_glEnableClientState || - fn == (list_fn_cb) &jwzgles_glDisableClientState || - fn == (list_fn_cb) &jwzgles_glShadeModel || - fn == (list_fn_cb) &jwzgles_glMatrixMode) - LOG2 (" push %-12s %s", name, mode_desc (av[0].i)); - else - LOG2 (" push %-12s %d", name, av[0].i); - break; - case PROTO_F: - LOG2 (" push %-12s %7.3f", name, av[0].f); - break; - case PROTO_II: - if (fn == (list_fn_cb) &jwzgles_glBindTexture || - fn == (list_fn_cb) &jwzgles_glBindBuffer) - LOG3 (" push %-12s %s %d", name, mode_desc (av[0].i), av[1].i); - else - LOG3 (" push %-12s %d %d", name, av[0].i, av[1].i); - break; - case PROTO_FF: - LOG3 (" push %-12s %7.3f %7.3f", name, av[0].f, av[1].f); - break; - case PROTO_IF: - LOG3 (" push %-12s %s %7.3f", name, mode_desc (av[0].i), av[1].f); - break; - case PROTO_III: - case PROTO_ARRAYS: - if (fn == (list_fn_cb) &jwzgles_glDrawArrays || - fn == (list_fn_cb) &jwzgles_glTexParameteri) - LOG4 (" push %-12s %s %d %d", name, mode_desc (av[0].i), - av[1].i, av[2].i); - else - LOG4 (" push %-12s %d %d %d", name, av[0].i, av[1].i, av[2].i); - break; - case PROTO_FFF: - LOG4 (" push %-12s %7.3f %7.3f %7.3f", name, av[0].f, av[1].f, av[2].f); - break; - case PROTO_IIF: - LOG4 (" push %-12s %s %s %7.3f", name, - mode_desc(av[0].i), mode_desc(av[1].i), av[2].f); - break; - case PROTO_IIII: - LOG5 (" push %-12s %d %d %d %d", name, - av[0].i, av[1].i, av[2].i, av[3].i); - break; - case PROTO_FFFF: - LOG5 (" push %-12s %7.3f %7.3f %7.3f %7.3f", name, - av[0].f, av[1].f, av[2].f, av[3].f); - break; - case PROTO_IFV: - LOG6 (" push %-12s %s %3.1f %3.1f %3.1f %3.1f", name, mode_desc (av[0].i), - av[1].f, av[2].f, av[3].f, av[4].f); - break; - case PROTO_IIV: - LOG6 (" push %-12s %s %d %d %d %d", name, mode_desc (av[0].i), - av[1].i, av[2].i, av[3].i, av[4].i); - break; - case PROTO_IIFV: - LOG7 (" push %-12s %s %-8s %3.1f %3.1f %3.1f %3.1f", name, - mode_desc (av[0].i), mode_desc (av[1].i), - av[2].f, av[3].f, av[4].f, av[5].f); - break; - case PROTO_IIIV: - LOG7 (" push %-12s %s %-8s %3d %3d %3d %3d", name, - mode_desc (av[0].i), mode_desc (av[1].i), - av[2].i, av[3].i, av[4].i, av[5].i); - break; - case PROTO_FV16: - LOG17 (" push %-12s [" - "%8.3f %8.3f %8.3f %8.3f " "\n\t\t\t " - "%8.3f %8.3f %8.3f %8.3f " "\n\t\t\t " - "%8.3f %8.3f %8.3f %8.3f " "\n\t\t\t " - "%8.3f %8.3f %8.3f %8.3f ]", - name, - av[0].f, av[1].f, av[2].f, av[3].f, - av[4].f, av[5].f, av[6].f, av[7].f, - av[8].f, av[9].f, av[10].f, av[11].f, - av[12].f, av[13].f, av[14].f, av[15].f); - break; - default: - Assert (0, "bogus prototype"); - break; - } -# endif /* DEBUG */ - - if (proto == PROTO_ARRAYS) /* glDrawArrays */ - save_arrays (F, av[1].i + av[2].i); - - L->count++; -} - - -void -jwzgles_glBegin (int mode) -{ - Assert (!state->compiling_verts, "nested glBegin"); - state->compiling_verts++; - - /* Only these commands are allowed inside glBegin: - - glVertex -- not allowed outside - glColor - glSecondaryColor - glIndex - glNormal - glFogCoord - glTexCoord - glMultiTexCoord - glVertexAttrib - glEvalCoord - glEvalPoint - glArrayElement -- not allowed outside - glMaterial - glEdgeFlag - glCallList - glCallLists - */ - - if (!state->replaying_list) - LOG2 ("%sglBegin %s", - (state->compiling_list || state->replaying_list ? " " : ""), - mode_desc (mode)); - - Assert (state->set.count == 0, "glBegin corrupted"); - state->set.mode = mode; - state->set.count = 0; - state->set.ncount = 0; - state->set.tcount = 0; - state->set.ccount = 0; -} - - -void -jwzgles_glDeleteLists (int id0, int range) -{ - Assert (!state->compiling_verts, "glDeleteLists not allowed inside glBegin"); - - if (state->compiling_list) - { - void_int vv[2]; - vv[0].i = id0; - vv[1].i = range; - list_push ("glDeleteLists", (list_fn_cb) &jwzgles_glDeleteLists, - PROTO_II, vv); - } - else - { - int id; - - if (!state->replaying_list) - LOG2 ("glDeleteLists %d %d", id0, range); - - for (id = id0 + range - 1; id >= id0; id--) - { - int i; - list *L; - if (id == 0) continue; /* People do this stupid thing */ - if (id > state->lists.count) break; /* this too */ - Assert (id > 0 && id <= state->lists.count, - "glDeleteLists: bogus ID"); - L = &state->lists.lists[id-1]; - Assert (L->id == id, "glDeleteLists corrupted"); - - for (i = 0; i < L->count; i++) - { - list_fn *lf = &L->fns[i]; - if (lf->arrays) - { - int j; - for (j = 0; j < 4; j++) - /* If there's a binding, 'data' is an index, not a ptr. */ - if (!lf->arrays[j].binding && - lf->arrays[j].data) - free (lf->arrays[j].data); - free (lf->arrays); - } - } - if (L->fns) - free (L->fns); - if (L->buffer) - glDeleteBuffers (1, &L->buffer); - - memset (L, 0, sizeof (*L)); - L->id = id; - } - } -} - - -extern GLboolean -jwzgles_glIsList (GLuint id) -{ - return (id > 0 && id < state->lists.count); -} - - - -void -jwzgles_glNormal3fv (const GLfloat *v) -{ - if (state->compiling_list && !state->compiling_verts) - { - void_int vv[3]; - vv[0].f = v[0]; - vv[1].f = v[1]; - vv[2].f = v[2]; - list_push ("glNormal3f", (list_fn_cb) &jwzgles_glNormal3f, - PROTO_FFF, vv); - } - else - { - if (!state->replaying_list) - LOG5 ("%s%sglNormal3f %7.3f %7.3f %7.3f", - (state->compiling_list || state->replaying_list ? " " : ""), - (state->compiling_verts ? " rec " : ""), - v[0], v[1], v[2]); - - if (state->compiling_verts) /* inside glBegin */ - { - state->set.cnorm.x = v[0]; - state->set.cnorm.y = v[1]; - state->set.cnorm.z = v[2]; - state->set.ncount++; - if (state->set.count > 0 && state->set.ncount == 1) /* not first! */ - state->set.ncount++; - } - else /* outside glBegin */ - { - glNormal3f (v[0], v[1], v[2]); - CHECK("glNormal3f"); - } - } -} - - -void -jwzgles_glNormal3f (GLfloat x, GLfloat y, GLfloat z) -{ - GLfloat v[3]; - v[0] = x; - v[1] = y; - v[2] = z; - jwzgles_glNormal3fv (v); -} - - -void -jwzgles_glTexCoord4fv (const GLfloat *v) -{ - if (state->compiling_list && !state->compiling_verts) - { - void_int vv[4]; - vv[0].f = v[0]; - vv[1].f = v[1]; - vv[2].f = v[2]; - vv[3].f = v[3]; - list_push ("glTexCoord4f", (list_fn_cb) &jwzgles_glTexCoord4f, - PROTO_FFFF, vv); - } - else - { - if (!state->replaying_list) - LOG6 ("%s%sglTexCoord4f %7.3f %7.3f %7.3f %7.3f", - (state->compiling_list || state->replaying_list ? " " : ""), - (state->compiling_verts ? " rec " : ""), - v[0], v[1], v[2], v[3]); - - Assert (state->compiling_verts, "glTexCoord4fv outside glBegin"); - - if (state->compiling_verts) /* inside glBegin */ - { - state->set.ctex.s = v[0]; - state->set.ctex.t = v[1]; - state->set.ctex.r = v[2]; - state->set.ctex.q = v[3]; - state->set.tcount++; - if (state->set.count > 0 && state->set.tcount == 1) /* not first! */ - state->set.tcount++; - } - } -} - - -void -jwzgles_glTexCoord4f (GLfloat s, GLfloat t, GLfloat r, GLfloat q) -{ - GLfloat v[4]; - v[0] = s; - v[1] = t; - v[2] = r; - v[3] = q; - jwzgles_glTexCoord4fv (v); -} - - -void -jwzgles_glTexCoord3fv (const GLfloat *v) -{ - GLfloat vv[4]; - vv[0] = v[0]; - vv[1] = v[1]; - vv[2] = v[2]; - vv[3] = 1; - jwzgles_glTexCoord4fv (vv); -} - - -void -jwzgles_glTexCoord2fv (const GLfloat *v) -{ - GLfloat vv[4]; - vv[0] = v[0]; - vv[1] = v[1]; - vv[2] = 0; - vv[3] = 1; - jwzgles_glTexCoord4fv (vv); -} - - -void -jwzgles_glTexCoord3f (GLfloat s, GLfloat t, GLfloat r) -{ - jwzgles_glTexCoord4f (s, t, r, 1); -} - - -void -jwzgles_glTexCoord2f (GLfloat s, GLfloat t) -{ - jwzgles_glTexCoord4f (s, t, 0, 1); -} - - -void -jwzgles_glTexCoord1f (GLfloat s) -{ - jwzgles_glTexCoord4f (s, 0, 0, 1); -} - - -/* glColor: GLfloat */ - -void -jwzgles_glColor4fv (const GLfloat *v) -{ - if (state->compiling_list && !state->compiling_verts) - { - void_int vv[4]; - vv[0].f = v[0]; - vv[1].f = v[1]; - vv[2].f = v[2]; - vv[3].f = v[3]; - list_push ("glColor4f", (list_fn_cb) &jwzgles_glColor4f, - PROTO_FFFF, vv); - } - else - { - if (!state->replaying_list) - LOG6 ("%s%sglColor4f %7.3f %7.3f %7.3f %7.3f", - (state->compiling_list || state->replaying_list ? " " : ""), - (state->compiling_verts ? " rec " : ""), - v[0], v[1], v[2], v[3]); - - if (state->compiling_verts) /* inside glBegin */ - { - state->set.ccolor.r = v[0]; - state->set.ccolor.g = v[1]; - state->set.ccolor.b = v[2]; - state->set.ccolor.a = v[3]; - state->set.ccount++; - if (state->set.count > 0 && state->set.ccount == 1) /* not first! */ - state->set.ccount++; - } - else /* outside glBegin */ - { - glColor4f (v[0], v[1], v[2], v[3]); - CHECK("glColor4"); - } - } -} - - -void -jwzgles_glColor4f (GLfloat r, GLfloat g, GLfloat b, GLfloat a) -{ - GLfloat v[4]; - v[0] = r; - v[1] = g; - v[2] = b; - v[3] = a; - jwzgles_glColor4fv (v); -} - -void -jwzgles_glColor3f (GLfloat r, GLfloat g, GLfloat b) -{ - jwzgles_glColor4f (r, g, b, 1); -} - -void -jwzgles_glColor3fv (const GLfloat *v) -{ - jwzgles_glColor3f (v[0], v[1], v[2]); -} - - -/* glColor: GLdouble */ - -void -jwzgles_glColor4d (GLdouble r, GLdouble g, GLdouble b, GLdouble a) -{ - jwzgles_glColor4f (r, g, b, a); -} - -void -jwzgles_glColor4dv (const GLdouble *v) -{ - jwzgles_glColor4d (v[0], v[1], v[2], v[3]); -} - -void -jwzgles_glColor3d (GLdouble r, GLdouble g, GLdouble b) -{ - jwzgles_glColor4d (r, g, b, 1.0); -} - -void -jwzgles_glColor3dv (const GLdouble *v) -{ - jwzgles_glColor3d (v[0], v[1], v[2]); -} - - -/* glColor: GLint (INT_MIN - INT_MAX) */ - -void -jwzgles_glColor4i (GLint r, GLint g, GLint b, GLint a) -{ - /* -0x8000000 - 0x7FFFFFFF => 0.0 - 1.0 */ - jwzgles_glColor4f (0.5 + (GLfloat) r / 0xFFFFFFFF, - 0.5 + (GLfloat) g / 0xFFFFFFFF, - 0.5 + (GLfloat) b / 0xFFFFFFFF, - 0.5 + (GLfloat) a / 0xFFFFFFFF); -} - -void -jwzgles_glColor4iv (const GLint *v) -{ - jwzgles_glColor4i (v[0], v[1], v[2], v[3]); -} - - -void -jwzgles_glColor3i (GLint r, GLint g, GLint b) -{ - jwzgles_glColor4i (r, g, b, 0x7FFFFFFF); -} - -void -jwzgles_glColor3iv (const GLint *v) -{ - jwzgles_glColor3i (v[0], v[1], v[2]); -} - - -/* glColor: GLuint (0 - UINT_MAX) */ - -void -jwzgles_glColor4ui (GLuint r, GLuint g, GLuint b, GLuint a) -{ - /* 0 - 0xFFFFFFFF => 0.0 - 1.0 */ - jwzgles_glColor4f ((GLfloat) r / 0xFFFFFFFF, - (GLfloat) g / 0xFFFFFFFF, - (GLfloat) b / 0xFFFFFFFF, - (GLfloat) a / 0xFFFFFFFF); -} - -void -jwzgles_glColor4uiv (const GLuint *v) -{ - jwzgles_glColor4ui (v[0], v[1], v[2], v[3]); -} - -void -jwzgles_glColor3ui (GLuint r, GLuint g, GLuint b) -{ - jwzgles_glColor4ui (r, g, b, 0xFFFFFFFF); -} - -void -jwzgles_glColor3uiv (const GLuint *v) -{ - jwzgles_glColor3ui (v[0], v[1], v[2]); -} - - -/* glColor: GLshort (SHRT_MIN - SHRT_MAX) */ - -void -jwzgles_glColor4s (GLshort r, GLshort g, GLshort b, GLshort a) -{ - /* -0x8000 - 0x7FFF => 0.0 - 1.0 */ - jwzgles_glColor4f (0.5 + (GLfloat) r / 0xFFFF, - 0.5 + (GLfloat) g / 0xFFFF, - 0.5 + (GLfloat) b / 0xFFFF, - 0.5 + (GLfloat) a / 0xFFFF); -} - -void -jwzgles_glColor4sv (const GLshort *v) -{ - jwzgles_glColor4s (v[0], v[1], v[2], v[3]); -} - -void -jwzgles_glColor3s (GLshort r, GLshort g, GLshort b) -{ - jwzgles_glColor4s (r, g, b, 0x7FFF); -} - -void -jwzgles_glColor3sv (const GLshort *v) -{ - jwzgles_glColor3s (v[0], v[1], v[2]); -} - - -/* glColor: GLushort (0 - USHRT_MAX) */ - -void -jwzgles_glColor4us (GLushort r, GLushort g, GLushort b, GLushort a) -{ - /* 0 - 0xFFFF => 0.0 - 1.0 */ - jwzgles_glColor4f ((GLfloat) r / 0xFFFF, - (GLfloat) g / 0xFFFF, - (GLfloat) b / 0xFFFF, - (GLfloat) a / 0xFFFF); -} - -void -jwzgles_glColor4usv (const GLushort *v) -{ - jwzgles_glColor4us (v[0], v[1], v[2], v[3]); -} - -void -jwzgles_glColor3us (GLushort r, GLushort g, GLushort b) -{ - jwzgles_glColor4us (r, g, b, 0xFFFF); -} - -void -jwzgles_glColor3usv (const GLushort *v) -{ - jwzgles_glColor3us (v[0], v[1], v[2]); -} - - -/* glColor: GLbyte (-128 - 127) */ - -void -jwzgles_glColor4b (GLbyte r, GLbyte g, GLbyte b, GLbyte a) -{ - /* -128 - 127 => 0.0 - 1.0 */ - jwzgles_glColor4f (0.5 + (GLfloat) r / 255, - 0.5 + (GLfloat) g / 255, - 0.5 + (GLfloat) b / 255, - 0.5 + (GLfloat) a / 255); -} - -void -jwzgles_glColor4bv (const GLbyte *v) -{ - jwzgles_glColor4b (v[0], v[1], v[2], v[3]); -} - -void -jwzgles_glColor3b (GLbyte r, GLbyte g, GLbyte b) -{ - jwzgles_glColor4b (r, g, b, 127); -} - -void -jwzgles_glColor3bv (const GLbyte *v) -{ - jwzgles_glColor3b (v[0], v[1], v[2]); -} - - -/* glColor: GLubyte (0 - 255) */ - -void -jwzgles_glColor4ub (GLubyte r, GLubyte g, GLubyte b, GLubyte a) -{ - /* 0 - 255 => 0.0 - 1.0 */ - jwzgles_glColor4f (r / 255.0, g / 255.0, b / 255.0, a / 255.0); -} - -void -jwzgles_glColor4ubv (const GLubyte *v) -{ - jwzgles_glColor4ub (v[0], v[1], v[2], v[3]); -} - -void -jwzgles_glColor3ub (GLubyte r, GLubyte g, GLubyte b) -{ - jwzgles_glColor4ub (r, g, b, 255); -} - -void -jwzgles_glColor3ubv (const GLubyte *v) -{ - jwzgles_glColor3ub (v[0], v[1], v[2]); -} - - - -void -jwzgles_glMaterialfv (GLenum face, GLenum pname, const GLfloat *color) -{ - /* If this is called inside glBegin/glEnd with a front ambient color, - then treat it the same as glColor: set the color of the upcoming - vertex. - - Other faces or lighting types within glBegin are ignored. - */ - - if (state->compiling_verts) - { - if ((face == GL_FRONT || - face == GL_FRONT_AND_BACK) && - (pname == GL_AMBIENT || - pname == GL_DIFFUSE || - pname == GL_AMBIENT_AND_DIFFUSE)) - { - jwzgles_glColor4f (color[0], color[1], color[2], color[3]); - state->set.materialistic++; - } - else - LOG2 (" IGNORING glMaterialfv %s %s", - mode_desc(face), mode_desc(pname)); - } - else if (state->compiling_list) - { - void_int vv[6]; - vv[0].i = face; - vv[1].i = pname; - vv[2].f = color[0]; - vv[3].f = color[1]; - vv[4].f = color[2]; - vv[5].f = color[3]; - list_push ("glMaterialfv", (list_fn_cb) &jwzgles_glMaterialfv, - PROTO_IIFV, vv); - } - else - { - /* If this is called outside of glBegin/glEnd with a front - ambient color, then the intent is presumably for that color - to apply to the upcoming vertexes (which may be played back - from a list that does not have vertex colors in it). In that - case, the only way to make the colors show up is to call - glColor() with GL_COLOR_MATERIAL enabled. - - I'm not sure if this will have other inappropriate side effects... - */ - if ((face == GL_FRONT || - face == GL_FRONT_AND_BACK) && - (pname == GL_AMBIENT || - pname == GL_DIFFUSE || - pname == GL_AMBIENT_AND_DIFFUSE)) - { - jwzgles_glEnable (GL_COLOR_MATERIAL); - jwzgles_glColor4f (color[0], color[1], color[2], color[3]); - } - - /* OpenGLES seems to throw "invalid enum" for GL_FRONT -- but it - goes ahead and sets the material anyway! No error if we just - always use GL_FRONT_AND_BACK. - */ - if (face == GL_FRONT) - face = GL_FRONT_AND_BACK; - if (! state->replaying_list) - LOG7 ("direct %-12s %s %s %7.3f %7.3f %7.3f %7.3f", "glMaterialfv", - mode_desc(face), mode_desc(pname), - color[0], color[1], color[2], color[3]); - glMaterialfv (face, pname, color); /* the real one */ - CHECK("glMaterialfv"); - } -} - - -void -jwzgles_glMaterialiv (GLenum face, GLenum pname, const GLint *v) -{ - GLfloat vv[4]; - vv[0] = v[0]; - vv[1] = v[1]; - vv[2] = v[2]; - vv[3] = 1; - jwzgles_glMaterialfv (face, pname, vv); -} - -void -jwzgles_glMaterialf (GLenum face, GLenum pname, const GLfloat c) -{ - GLfloat vv[4]; - vv[0] = c; - vv[1] = c; - vv[2] = c; - vv[3] = 1; - jwzgles_glMaterialfv (face, pname, vv); -} - - -void -jwzgles_glMateriali (GLenum face, GLenum pname, const GLuint c) -{ - jwzgles_glMaterialf (face, pname, c); -} - - -void -jwzgles_glColorMaterial (GLenum face, GLenum mode) -{ - Assert (!state->compiling_verts, - "glColorMaterial not allowed inside glBegin"); -#if 0 - if (state->compiling_list) - { - void_int vv[2]; - vv[0].i = face; - vv[1].i = mode; - list_push ("glColorMaterial", (list_fn_cb) &jwzgles_glColorMaterial, - PROTO_II, vv); - } - else - { - /* No real analog to this distinction in OpenGLES, since color - arrays don't distinguish between "color" and "material", */ - Assert (0, "glColorMaterial: unimplemented mode"); - } -#endif -} - - - - -void -jwzgles_glVertex4fv (const GLfloat *v) -{ - vert_set *s = &state->set; - int count = s->count; - - Assert (state->compiling_verts, "glVertex4fv not inside glBegin"); - - LOG5("%s rec glVertex4f %7.3f %7.3f %7.3f %7.3f", - (state->compiling_list || state->replaying_list ? " " : ""), - v[0], v[1], v[2], v[3]); - - if (count >= s->size - 1) - { - int new_size = 20 + (s->size * 1.2); - - /* 4 arrays, different element sizes... - We allocate all 4 arrays just in case we need them, - but we might not end up using them all at the end. - */ - - s->verts = (XYZW *) realloc (s->verts, new_size * sizeof (*s->verts)); - Assert (s->verts, "out of memory"); - - s->norms = (XYZ *) realloc (s->norms, new_size * sizeof (*s->norms)); - Assert (s->norms, "out of memory"); - - s->tex = (STRQ *) realloc (s->tex, new_size * sizeof (*s->tex)); - Assert (s->tex, "out of memory"); - - s->color = (RGBA *) realloc (s->color, new_size * sizeof (*s->color)); - Assert (s->color, "out of memory"); - - s->size = new_size; - } - - s->verts [count].x = v[0]; - s->verts [count].y = v[1]; - s->verts [count].z = v[2]; - s->verts [count].w = v[3]; - s->norms [count] = s->cnorm; - s->tex [count] = s->ctex; - s->color [count] = s->ccolor; - s->count++; -} - - -void -jwzgles_glVertex4f (GLfloat x, GLfloat y, GLfloat z, GLfloat w) -{ - GLfloat v[4]; - v[0] = x; - v[1] = y; - v[2] = z; - v[3] = w; - jwzgles_glVertex4fv (v); -} - -void -jwzgles_glVertex4i (GLint x, GLint y, GLint z, GLint w) -{ - jwzgles_glVertex4f (x, y, z, w); -} - -void -jwzgles_glVertex3f (GLfloat x, GLfloat y, GLfloat z) -{ - GLfloat v[4]; - v[0] = x; - v[1] = y; - v[2] = z; - v[3] = 1; - jwzgles_glVertex4fv (v); -} - -void -jwzgles_glVertex3i (GLint x, GLint y, GLint z) -{ - jwzgles_glVertex3f (x, y, z); -} - -void -jwzgles_glVertex3fv (const GLfloat *v) -{ - jwzgles_glVertex3f (v[0], v[1], v[2]); -} - -void -jwzgles_glVertex3dv (const GLdouble *v) -{ - jwzgles_glVertex3f (v[0], v[1], v[2]); -} - - -void -jwzgles_glVertex2f (GLfloat x, GLfloat y) -{ - GLfloat v[3]; - v[0] = x; - v[1] = y; - v[2] = 0; - jwzgles_glVertex3fv (v); -} - -void -jwzgles_glVertex2dv (const GLdouble *v) -{ - jwzgles_glVertex2f (v[0], v[1]); -} - -void -jwzgles_glVertex2fv (const GLfloat *v) -{ - jwzgles_glVertex2f (v[0], v[1]); -} - -void -jwzgles_glVertex2i (GLint x, GLint y) -{ - jwzgles_glVertex2f (x, y); -} - - -void -jwzgles_glLightiv (GLenum light, GLenum pname, const GLint *params) -{ - GLfloat v[4]; - v[0] = params[0]; - v[1] = params[1]; - v[2] = params[2]; - v[3] = params[3]; - jwzgles_glLightfv (light, pname, v); -} - -void -jwzgles_glLightModeliv (GLenum pname, const GLint *params) -{ - GLfloat v[4]; - v[0] = params[0]; - v[1] = params[1]; - v[2] = params[2]; - v[3] = params[3]; - jwzgles_glLightModelfv (pname, v); -} - -void -jwzgles_glFogiv (GLenum pname, const GLint *params) -{ - GLfloat v[4]; - v[0] = params[0]; - v[1] = params[1]; - v[2] = params[2]; - v[3] = params[3]; - jwzgles_glFogfv (pname, v); -} - -void -jwzgles_glLighti (GLenum light, GLenum pname, GLint param) -{ - jwzgles_glLightf (light, pname, param); -} - -void -jwzgles_glLightModeli (GLenum pname, GLint param) -{ - jwzgles_glLightModelf (pname, param); -} - -void -jwzgles_glFogi (GLenum pname, GLint param) -{ - jwzgles_glFogf (pname, param); -} - - -void -jwzgles_glRotated (GLdouble angle, GLdouble x, GLdouble y, GLdouble z) -{ - jwzgles_glRotatef (angle, x, y, z); -} - - -void -jwzgles_glClipPlane (GLenum plane, const GLdouble *equation) -{ - Assert (state->compiling_verts, "glClipPlane not inside glBegin"); - Assert (0, "glClipPlane unimplemented"); /* no GLES equivalent... */ -} - - -void -jwzgles_glPolygonMode (GLenum face, GLenum mode) -{ - Assert (!state->compiling_verts, "not inside glBegin"); - if (state->compiling_list) - { - void_int vv[2]; - vv[0].i = face; - vv[1].i = mode; - list_push ("glPolygonMode", (list_fn_cb) &jwzgles_glPolygonMode, - PROTO_II, vv); - } - else - { - /* POINT and LINE don't exist in GLES */ - Assert (mode == GL_FILL, "glPolygonMode: unimplemented mode"); - } -} - - -void -jwzgles_glDrawBuffer (GLenum buf) -{ - Assert (!state->compiling_verts, "not inside glBegin"); - if (state->compiling_list) - { - void_int vv[1]; - vv[0].i = buf; - list_push ("glDrawBuffer", (list_fn_cb) &jwzgles_glDrawBuffer, - PROTO_I, vv); - } - else - { -/* Assert (buf == GL_BACK, "glDrawBuffer: back buffer only"); */ -# ifndef GL_VERSION_ES_CM_1_0 /* not compiling against OpenGLES 1.x */ - if (! state->replaying_list) - LOG1 ("direct %-12s", "glDrawBuffer"); - glDrawBuffer (buf); /* the real one */ - CHECK("glDrawBuffer"); -# endif - } -} - - -/* Given an array of sets of 4 elements of arbitrary size, convert it - to an array of sets of 6 elements instead: ABCD becomes ABC BCD. - */ -static int -cq2t (unsigned char **arrayP, int stride, int count) -{ - int count2 = count * 6 / 4; - int size = stride * count; - int size2 = stride * count2; - const unsigned char *oarray, *in; - unsigned char *array2, *oarray2, *out; - int i; - - oarray = *arrayP; - if (!oarray || count == 0) - return count2; - - array2 = (unsigned char *) malloc (size2); - Assert (array2, "out of memory"); - oarray2 = array2; - - in = oarray; - out = oarray2; - for (i = 0; i < count / 4; i++) - { - const unsigned char *a, *b, *c, *d; /* the 4 corners */ - a = in; in += stride; - b = in; in += stride; - c = in; in += stride; - d = in; in += stride; - -# define PUSH(IN) do { \ - const unsigned char *ii = IN; \ - int j; \ - for (j = 0; j < stride; j++) { \ - *out++ = *ii++; \ - }} while(0) - - PUSH (a); PUSH (b); PUSH (d); /* the 2 triangles */ - PUSH (b); PUSH (c); PUSH (d); -# undef PUSH - } - - Assert (in == oarray + size, "convert_quads corrupted"); - Assert (out == oarray2 + size2, "convert_quads corrupted"); - - free (*arrayP); - *arrayP = oarray2; - return count2; -} - - -/* Convert all coordinates in a GL_QUADS vert_set to GL_TRIANGLES. - */ -static void -convert_quads_to_triangles (vert_set *s) -{ - int count2; - Assert (s->mode == GL_QUADS, "convert_quads bad mode"); - count2 = - cq2t ((unsigned char **) &s->verts, sizeof(*s->verts), s->count); - cq2t ((unsigned char **) &s->norms, sizeof(*s->norms), s->count); - cq2t ((unsigned char **) &s->tex, sizeof(*s->tex), s->count); - cq2t ((unsigned char **) &s->color, sizeof(*s->color), s->count); - s->count = count2; - s->size = count2; - s->mode = GL_TRIANGLES; -} - - -void -jwzgles_glEnd (void) -{ - vert_set *s = &state->set; - int was_norm, was_tex, was_color, was_mat; - int is_norm, is_tex, is_color, is_mat; - - Assert (state->compiling_verts == 1, "missing glBegin"); - state->compiling_verts--; - - Assert (!state->replaying_list, "how did glEnd get into a display list?"); - - if (!state->replaying_list) - { - LOG5 ("%s [V = %d, N = %d, T = %d, C = %d]", - (state->compiling_list || state->replaying_list ? " " : ""), - s->count, s->ncount, s->tcount, s->ccount); - LOG1 ("%sglEnd", - (state->compiling_list || state->replaying_list ? " " : "")); - } - - if (s->count == 0) return; - - if (s->mode == GL_QUADS) - convert_quads_to_triangles (s); - else if (s->mode == GL_QUAD_STRIP) - s->mode = GL_TRIANGLE_STRIP; /* They do the same thing! */ - else if (s->mode == GL_POLYGON) - s->mode = GL_TRIANGLE_FAN; /* They do the same thing! */ - - jwzgles_glColorPointer (4,GL_FLOAT, sizeof(*s->color),s->color); /* RGBA */ - jwzgles_glNormalPointer ( GL_FLOAT, sizeof(*s->norms),s->norms); /* XYZ */ - jwzgles_glTexCoordPointer(4,GL_FLOAT, sizeof(*s->tex), s->tex); /* STRQ */ - jwzgles_glVertexPointer (4,GL_FLOAT, sizeof(*s->verts),s->verts); /* XYZW */ - /* glVertexPointer must come after glTexCoordPointer */ - - /* If there were no calls to glNormal3f inside of glBegin/glEnd, - don't bother enabling the normals array. - - If there was exactly *one* call to glNormal3f inside of glBegin/glEnd, - and it was before the first glVertex3f, then also don't enable the - normals array, but do emit that call to glNormal3f before calling - glDrawArrays. - - Likewise for texture coordinates and colors. - - Be careful to leave the arrays' enabled/disabled state the same as - before, or a later caller might end up using one of our arrays by - mistake. (Remember that jwzgles_glIsEnabled() tracks the enablement - of the list-in-progress as well as the global state.) - */ - was_norm = jwzgles_glIsEnabled (GL_NORMAL_ARRAY); - was_tex = jwzgles_glIsEnabled (GL_TEXTURE_COORD_ARRAY); - was_color = jwzgles_glIsEnabled (GL_COLOR_ARRAY); - was_mat = jwzgles_glIsEnabled (GL_COLOR_MATERIAL); - - /* If we're executing glEnd in immediate mode, not from inside a display - list (which is the only way it happens, because glEnd doesn't go into - display lists), make sure we're not stomping on a saved buffer list: - in immediate mode, vertexes are client-side only. - */ - if (! state->compiling_list) - jwzgles_glBindBuffer (GL_ARRAY_BUFFER, 0); - - if (s->ncount > 1) - { - is_norm = 1; - jwzgles_glEnableClientState (GL_NORMAL_ARRAY); - } - else - { - is_norm = 0; - if (s->ncount == 1) - jwzgles_glNormal3f (s->cnorm.x, s->cnorm.y, s->cnorm.z); - jwzgles_glDisableClientState (GL_NORMAL_ARRAY); - } - - if (s->tcount > 1 || - ((state->compiling_list ? state->list_enabled : state->enabled) - & (ISENABLED_TEXTURE_GEN_S | ISENABLED_TEXTURE_GEN_T | - ISENABLED_TEXTURE_GEN_R | ISENABLED_TEXTURE_GEN_Q))) - { - /* Enable texture coords if any were specified; or if generation - is on in immediate mode; or if this list turned on generation. */ - is_tex = 1; - jwzgles_glEnableClientState (GL_TEXTURE_COORD_ARRAY); - } - else - { - is_tex = 0; - if (s->tcount == 1) - jwzgles_glTexCoord4f (s->ctex.s, s->ctex.t, s->ctex.r, s->ctex.q); - jwzgles_glDisableClientState (GL_TEXTURE_COORD_ARRAY); - } - - if (s->ccount > 1) - { - is_color = 1; - jwzgles_glEnableClientState (GL_COLOR_ARRAY); - } - else - { - is_color = 0; - if (s->ccount == 1) - jwzgles_glColor4f (s->ccolor.r, s->ccolor.g, s->ccolor.b, s->ccolor.a); - jwzgles_glDisableClientState (GL_COLOR_ARRAY); - } - - jwzgles_glEnableClientState (GL_VERTEX_ARRAY); - - /* We translated the glMaterial calls to per-vertex colors, which are - of the glColor sort, not the glMaterial sort, so automatically - turn on material mapping. Maybe this is a bad idea. - */ - if (s->materialistic && !jwzgles_glIsEnabled (GL_COLOR_MATERIAL)) - { - is_mat = 1; - jwzgles_glEnable (GL_COLOR_MATERIAL); - } - else - is_mat = 0; - - glBindBuffer (GL_ARRAY_BUFFER, 0); /* This comes later. */ - jwzgles_glDrawArrays (s->mode, 0, s->count); - glBindBuffer (GL_ARRAY_BUFFER, 0); /* Keep out of others' hands */ - -# define RESET(VAR,FN,ARG) do { \ - if (is_##VAR != was_##VAR) { \ - if (was_##VAR) jwzgles_glEnable##FN (ARG); \ - else jwzgles_glDisable##FN (ARG); \ - }} while(0) - RESET (norm, ClientState, GL_NORMAL_ARRAY); - RESET (tex, ClientState, GL_TEXTURE_COORD_ARRAY); - RESET (color, ClientState, GL_COLOR_ARRAY); - RESET (mat, , GL_COLOR_MATERIAL); -# undef RESET - - s->count = 0; - s->ncount = 0; - s->tcount = 0; - s->ccount = 0; - s->materialistic = 0; -} - - -/* The display list is full of calls to glDrawArrays(), plus saved arrays - of the values we need to restore before calling it. "Restore" means - "ship them off to the GPU before each call". - - So instead, this function walks through the display list and - combines all of those vertex, normal, texture and color values into - a single VBO array; ships those values off to the GPU *once* at the - time of glEndList; and when running the list with glCallList, the - values are already on the GPU and don't need to be sent over again. - - The VBO persists in the GPU until the display list is deleted. - */ -static void -optimize_arrays (void) -{ - list *L = &state->lists.lists[state->compiling_list-1]; - int i, j; - GLfloat *combo = 0; - int combo_count = 0; - int combo_size = 0; - GLuint buf_name = 0; - - Assert (state->compiling_list, "not compiling a list"); - Assert (L, "no list"); - Assert (!L->buffer, "list already has a buffer"); - - glGenBuffers (1, &buf_name); - CHECK("glGenBuffers"); - if (! buf_name) return; - - L->buffer = buf_name; - - /* Go through the list and dump the contents of the various saved arrays - into one large array. - */ - for (i = 0; i < L->count; i++) - { - list_fn *F = &L->fns[i]; -/* int count; */ - if (! F->arrays) - continue; -/* count = F->argv[2].i;*/ /* 3rd arg to glDrawArrays */ - - for (j = 0; j < 4; j++) - { - draw_array *A = &F->arrays[j]; - int ocount = combo_count; - - /* If some caller is using arrays that don't have floats in them, - we just leave them as-is and ship them over at each call. - Doubt this ever really happens. - */ - if (A->type != GL_FLOAT) - continue; - - if (! A->data) /* No array. */ - continue; - - Assert (A->bytes > 0, "no bytes in draw_array"); - Assert (((unsigned long) A->data > 0xFFFF), - "buffer data not a pointer"); - - combo_count += A->bytes / sizeof(*combo); - make_room ("optimize_arrays", - (void **) &combo, sizeof(*combo), - &combo_count, &combo_size); - memcpy (combo + ocount, A->data, A->bytes); - A->binding = buf_name; - free (A->data); - /* 'data' is now the byte offset into the VBO. */ - A->data = (void *) (ocount * sizeof(*combo)); - /* LOG3(" loaded %lu floats to pos %d of buffer %d", - A->bytes / sizeof(*combo), ocount, buf_name); */ - } - } - - if (combo_count == 0) /* Nothing to do! */ - { - if (combo) free (combo); - glDeleteBuffers (1, &buf_name); - L->buffer = 0; - return; - } - - glBindBuffer (GL_ARRAY_BUFFER, buf_name); - glBufferData (GL_ARRAY_BUFFER, - combo_count * sizeof (*combo), - combo, - GL_STATIC_DRAW); - glBindBuffer (GL_ARRAY_BUFFER, 0); /* Keep out of others' hands */ - - LOG3(" loaded %d floats of list %d into VBO %d", - combo_count, state->compiling_list, buf_name); - -# ifdef DEBUG -# if 0 - for (i = 0; i < combo_count; i++) - { - if (i % 4 == 0) - fprintf (stderr, "\njwzgles: %4d: ", i); - fprintf (stderr, " %7.3f", combo[i]); - } - fprintf (stderr, "\n"); -# endif -# endif /* DEBUG */ - - if (combo) free (combo); -} - - -void -jwzgles_glCallList (int id) -{ - if (state->compiling_list) - { - /* Yes, you can call lists inside of lists. - Yes, recursion would be a mistake. */ - void_int vv[1]; - vv[0].i = id; - list_push ("glCallList", (list_fn_cb) &jwzgles_glCallList, PROTO_I, vv); - } - else - { - list *L; - int i; - - state->replaying_list++; - -# ifdef DEBUG - fprintf (stderr, "\n"); - LOG1 ("glCallList %d", id); -# endif - - Assert (id > 0 && id <= state->lists.count, "glCallList: bogus ID"); - L = &state->lists.lists[id-1]; - Assert (id == L->id, "glCallList corrupted"); - - for (i = 0; i < L->count; i++) - { - list_fn *F = &L->fns[i]; - list_fn_cb fn = F->fn; - void_int *av = F->argv; - - switch (F->proto) { - case PROTO_VOID: - LOG1 (" call %-12s", F->name); - ((void (*) (void)) fn) (); - break; - - case PROTO_I: - if (fn == (list_fn_cb) &jwzgles_glBegin || - fn == (list_fn_cb) &jwzgles_glFrontFace || - fn == (list_fn_cb) &jwzgles_glEnable || - fn == (list_fn_cb) &jwzgles_glDisable || - fn == (list_fn_cb) &jwzgles_glEnableClientState || - fn == (list_fn_cb) &jwzgles_glDisableClientState || - fn == (list_fn_cb) &jwzgles_glShadeModel || - fn == (list_fn_cb) &jwzgles_glMatrixMode) - LOG2 (" call %-12s %s", F->name, mode_desc (av[0].i)); - else - LOG2 (" call %-12s %d", F->name, av[0].i); - ((void (*) (int)) fn) (av[0].i); - break; - - case PROTO_F: - LOG2 (" call %-12s %7.3f", F->name, av[0].f); - ((void (*) (GLfloat)) fn) (av[0].f); - break; - - case PROTO_II: - if (fn == (list_fn_cb) &jwzgles_glBindTexture || - fn == (list_fn_cb) &jwzgles_glBindBuffer) - LOG3 (" call %-12s %s %d", F->name, - mode_desc (av[0].i), av[1].i); - else - LOG3 (" call %-12s %d %d", F->name, av[0].i, av[1].i); - ((void (*) (int, int)) fn) (av[0].i, av[1].i); - break; - - case PROTO_FF: - LOG3 (" call %-12s %7.3f %7.3f", F->name, av[0].f, av[1].f); - ((void (*) (GLfloat, GLfloat)) fn) (av[0].f, av[1].f); - break; - - case PROTO_IF: - LOG3 (" call %-12s %s %7.3f", F->name, - mode_desc (av[0].f), av[1].f); - ((void (*) (GLint, GLfloat)) fn) (av[0].i, av[1].f); - break; - - case PROTO_III: III: - if (fn == (list_fn_cb) &jwzgles_glDrawArrays || - fn == (list_fn_cb) &jwzgles_glTexParameteri) - LOG4 (" call %-12s %s %d %d", F->name, - mode_desc (av[0].i), av[1].i, av[2].i); - else - LOG4 (" call %-12s %d %d %d", F->name, - av[0].i, av[1].i, av[2].i); - ((void (*) (int, int, int)) fn) (av[0].i, av[1].i, av[2].i); - break; - - case PROTO_FFF: - LOG4 (" call %-12s %7.3f %7.3f %7.3f", F->name, - av[0].f, av[1].f, av[2].f); - ((void (*) (GLfloat, GLfloat, GLfloat)) fn) - (av[0].f, av[1].f, av[2].f); - break; - - case PROTO_IIF: - LOG4 (" call %-12s %s %s %7.3f", F->name, - mode_desc (av[0].i), mode_desc (av[1].i), av[2].f); - ((void (*) (int, int, GLfloat)) fn) (av[0].i, av[1].i, av[2].f); - break; - - case PROTO_IIII: - LOG5 (" call %-12s %d %d %d %d", F->name, - av[0].i, av[1].i, av[2].i, av[3].i); - ((void (*) (int, int, int, int)) fn) - (av[0].i, av[1].i, av[2].i, av[3].i); - break; - - case PROTO_FFFF: - LOG5 (" call %-12s %7.3f %7.3f %7.3f %7.3f", F->name, - av[0].f, av[1].f, av[2].f, av[3].f); - ((void (*) (GLfloat, GLfloat, GLfloat, GLfloat)) fn) - (av[0].f, av[1].f, av[2].f, av[3].f); - break; - - case PROTO_IFV: - { - GLfloat v[4]; - v[0] = av[1].f; - v[1] = av[2].f; - v[2] = av[3].f; - v[3] = av[4].f; - LOG6 (" call %-12s %s %3.1f %3.1f %3.1f %3.1f", F->name, - mode_desc (av[0].i), - av[1].f, av[2].f, av[3].f, av[4].f); - ((void (*) (int, const GLfloat *)) fn) (av[0].i, v); - } - break; - - case PROTO_IIFV: - { - GLfloat v[4]; - v[0] = av[2].f; - v[1] = av[3].f; - v[2] = av[4].f; - v[3] = av[5].f; - LOG7 (" call %-12s %s %-8s %3.1f %3.1f %3.1f %3.1f", F->name, - mode_desc (av[0].i), mode_desc (av[1].i), - av[2].f, av[3].f, av[4].f, av[5].f); - ((void (*) (int, int, const GLfloat *)) fn) - (av[0].i, av[1].i, v); - } - break; - - case PROTO_IIV: - { - int v[4]; - v[0] = av[1].i; - v[1] = av[2].i; - v[2] = av[3].i; - v[3] = av[4].i; - LOG6 (" call %-12s %s %3d %3d %3d %3d", F->name, - mode_desc (av[0].i), - av[1].i, av[2].i, av[3].i, av[4].i); - ((void (*) (int, const int *)) fn) (av[0].i, v); - } - break; - - case PROTO_IIIV: - { - int v[4]; - v[0] = av[2].i; - v[1] = av[3].i; - v[2] = av[4].i; - v[3] = av[5].i; - LOG7 (" call %-12s %s %-8s %3d %3d %3d %3d", F->name, - mode_desc (av[0].i), mode_desc (av[1].i), - av[2].i, av[3].i, av[4].i, av[5].i); - ((void (*) (int, int, const int *)) fn) - (av[0].i, av[1].i, v); - } - break; - - case PROTO_ARRAYS: - restore_arrays (F, av[1].i + av[2].i); - goto III; - break; - - case PROTO_FV16: - { - GLfloat m[16]; - int i; - for (i = 0; i < countof(m); i++) - m[i] = av[i].f; - LOG17 (" call %-12s [" - "%8.3f %8.3f %8.3f %8.3f " "\n\t\t\t " - "%8.3f %8.3f %8.3f %8.3f " "\n\t\t\t " - "%8.3f %8.3f %8.3f %8.3f " "\n\t\t\t " - "%8.3f %8.3f %8.3f %8.3f ]", - F->name, - m[0], m[1], m[2], m[3], - m[4], m[5], m[6], m[7], - m[8], m[9], m[10], m[11], - m[12], m[13], m[14], m[15]); - ((void (*) (GLfloat *)) fn) (m); - } - break; - - default: - Assert (0, "bogus prototype"); - break; - } - } - - LOG1 ("glCallList %d done\n", id); - - state->replaying_list--; - Assert (state->replaying_list >= 0, "glCallList corrupted"); - } -} - - -/* When we save a call to glDrawArrays into a display list, we also need to - save the prevailing copy of the arrays that it will use, and restore them - later. - */ -static void -save_arrays (list_fn *F, int count) -{ - int i = 0; - draw_array *A = (draw_array *) calloc (4, sizeof (*A)); - Assert (A, "out of memory"); - -/* if (state->set.count > 0) */ - { - glGetIntegerv (GL_VERTEX_ARRAY_BUFFER_BINDING, &A[i].binding); - glGetIntegerv (GL_VERTEX_ARRAY_SIZE, &A[i].size); - glGetIntegerv (GL_VERTEX_ARRAY_TYPE, &A[i].type); - glGetIntegerv (GL_VERTEX_ARRAY_STRIDE, &A[i].stride); - glGetPointerv (GL_VERTEX_ARRAY_POINTER, &A[i].data); - CHECK("glGetPointerv"); - copy_array_data (&A[i], count, "vert"); - } - - i++; - if (state->set.ncount > 1) - { - A[i].size = 3; - glGetIntegerv (GL_NORMAL_ARRAY_BUFFER_BINDING, &A[i].binding); - glGetIntegerv (GL_NORMAL_ARRAY_TYPE, &A[i].type); - glGetIntegerv (GL_NORMAL_ARRAY_STRIDE, &A[i].stride); - glGetPointerv (GL_NORMAL_ARRAY_POINTER, &A[i].data); - CHECK("glGetPointerv"); - copy_array_data (&A[i], count, "norm"); - } - - i++; - if (state->set.tcount > 1) - { - glGetIntegerv (GL_TEXTURE_COORD_ARRAY_BUFFER_BINDING, &A[i].binding); - glGetIntegerv (GL_TEXTURE_COORD_ARRAY_SIZE, &A[i].size); - glGetIntegerv (GL_TEXTURE_COORD_ARRAY_TYPE, &A[i].type); - glGetIntegerv (GL_TEXTURE_COORD_ARRAY_STRIDE, &A[i].stride); - glGetPointerv (GL_TEXTURE_COORD_ARRAY_POINTER, &A[i].data); - CHECK("glGetPointerv"); - copy_array_data (&A[i], count, "tex "); - } - - i++; - if (state->set.ccount > 1) - { - glGetIntegerv (GL_COLOR_ARRAY_BUFFER_BINDING, &A[i].binding); - glGetIntegerv (GL_COLOR_ARRAY_SIZE, &A[i].size); - glGetIntegerv (GL_COLOR_ARRAY_TYPE, &A[i].type); - glGetIntegerv (GL_COLOR_ARRAY_STRIDE, &A[i].stride); - glGetPointerv (GL_COLOR_ARRAY_POINTER, &A[i].data); - CHECK("glGetPointerv"); - copy_array_data (&A[i], count, "col "); - } - - /* Freed by glDeleteLists. */ - - Assert (!F->arrays, "save_arrays corrupted"); - F->arrays = A; -} - - -#ifdef DEBUG - -static void -dump_array_data (draw_array *A, int count, - const char *action, const char *name, const void *old) -{ - int bytes = count * A->stride; - - if (A->binding) - { - fprintf (stderr, - "jwzgles: %s %s %d %s %2d, %4d = %5d bind %d @ %d\n", - action, name, - A->size, mode_desc(A->type), A->stride, - count, bytes, A->binding, (int) A->data); - } - else - { - Assert (bytes == A->bytes, "array data corrupted"); - - fprintf (stderr, "jwzgles: %s %s %d %s %2d, %4d = %5d @ %lX", - action, name, - A->size, mode_desc(A->type), A->stride, - count, bytes, (unsigned long) A->data); - if (old) - fprintf (stderr, " / %lX", (unsigned long) old); - fprintf (stderr, "\n"); - } - - if (A->binding) - { - Assert (((unsigned long) A->data < 0xFFFF), - "buffer binding should be a numeric index," - " but looks like a pointer"); - -# if 0 - /* glGetBufferSubData doesn't actually exist in OpenGLES, but this - was helpful for debugging on real OpenGL... */ - GLfloat *d; - int i; - fprintf (stderr, "jwzgles: read back:\n"); - d = (GLfloat *) malloc (A->bytes); - glGetBufferSubData (GL_ARRAY_BUFFER, (int) A->data, - count * A->stride, (void *) d); - CHECK("glGetBufferSubData"); - for (i = 0; i < count * A->size; i++) - { - if (i % 4 == 0) - fprintf (stderr, "\njwzgles: %4d: ", - i + (int) A->data / sizeof(GLfloat)); - fprintf (stderr, " %7.3f", d[i]); - } - fprintf (stderr, "\n"); - free (d); -# endif - } -# if 0 - else - { - unsigned char *b = (unsigned char *) A->data; - int i; - if ((unsigned long) A->data < 0xFFFF) - { - Assert (0, "buffer data not a pointer"); - return; - } - for (i = 0; i < count; i++) - { - int j; - GLfloat *f = (GLfloat *) b; - int s = A->size; - if (s == 0) s = 3; /* normals */ - fprintf (stderr, "jwzgles: "); - for (j = 0; j < s; j++) - fprintf (stderr, " %7.3f", f[j]); - fprintf (stderr, "\n"); - b += A->stride; - } - } -# endif -} - -static void -dump_direct_array_data (int count) -{ - draw_array A = { 0, }; - - if (jwzgles_glIsEnabled (GL_VERTEX_ARRAY)) - { - glGetIntegerv (GL_VERTEX_ARRAY_BUFFER_BINDING, &A.binding); - glGetIntegerv (GL_VERTEX_ARRAY_SIZE, &A.size); - glGetIntegerv (GL_VERTEX_ARRAY_TYPE, &A.type); - glGetIntegerv (GL_VERTEX_ARRAY_STRIDE, &A.stride); - glGetPointerv (GL_VERTEX_ARRAY_POINTER, &A.data); - A.bytes = count * A.stride; - dump_array_data (&A, count, "direct", "vertex ", 0); - } - if (jwzgles_glIsEnabled (GL_NORMAL_ARRAY)) - { - A.size = 0; - glGetIntegerv (GL_NORMAL_ARRAY_BUFFER_BINDING, &A.binding); - glGetIntegerv (GL_NORMAL_ARRAY_TYPE, &A.type); - glGetIntegerv (GL_NORMAL_ARRAY_STRIDE, &A.stride); - glGetPointerv (GL_NORMAL_ARRAY_POINTER, &A.data); - A.bytes = count * A.stride; - dump_array_data (&A, count, "direct", "normal ", 0); - } - if (jwzgles_glIsEnabled (GL_TEXTURE_COORD_ARRAY)) - { - glGetIntegerv (GL_TEXTURE_COORD_ARRAY_BUFFER_BINDING, &A.binding); - glGetIntegerv (GL_TEXTURE_COORD_ARRAY_SIZE, &A.size); - glGetIntegerv (GL_TEXTURE_COORD_ARRAY_TYPE, &A.type); - glGetIntegerv (GL_TEXTURE_COORD_ARRAY_STRIDE, &A.stride); - glGetPointerv (GL_TEXTURE_COORD_ARRAY_POINTER, &A.data); - A.bytes = count * A.stride; - dump_array_data (&A, count, "direct", "texture", 0); - } - if (jwzgles_glIsEnabled (GL_COLOR_ARRAY)) - { - glGetIntegerv (GL_COLOR_ARRAY_BUFFER_BINDING, &A.binding); - glGetIntegerv (GL_COLOR_ARRAY_SIZE, &A.size); - glGetIntegerv (GL_COLOR_ARRAY_TYPE, &A.type); - glGetIntegerv (GL_COLOR_ARRAY_STRIDE, &A.stride); - glGetPointerv (GL_COLOR_ARRAY_POINTER, &A.data); - A.bytes = count * A.stride; - dump_array_data (&A, count, "direct", "color ", 0); - } -} - -#endif /* DEBUG */ - - -static void -copy_array_data (draw_array *A, int count, const char *name) -{ - /* Instead of just memcopy'ing the whole array and obeying its previous - 'stride' value, we make up a more compact array. This is because if - the same array data is being used with multiple component types, - e.g. with glInterleavedArrays, we don't want to copy all of the - data multiple times. - */ - int stride2, bytes, i, j; - void *data2; - const GLfloat *IF; - GLfloat *OF; - const unsigned char *IB; - unsigned char *OB; - - if (((unsigned long) A->data) < 0xFFFF) - { - Assert (0, "buffer data not a pointer"); - return; - } - - Assert (A->size >= 2 && A->size <= 4, "bogus array size"); - - switch (A->type) { - case GL_FLOAT: stride2 = A->size * sizeof(GLfloat); break; - case GL_UNSIGNED_BYTE: stride2 = A->size; break; - default: Assert (0, "bogus array type"); break; - } - - bytes = count * stride2; - Assert (bytes > 0, "bogus array count or stride"); - Assert (A->data, "missing array data"); - data2 = (void *) malloc (bytes); - Assert (data2, "out of memory"); - - IB = (const unsigned char *) A->data; - OB = (unsigned char *) data2; - IF = (const GLfloat *) A->data; - OF = (GLfloat *) data2; - - switch (A->type) { - case GL_FLOAT: - for (i = 0; i < count; i++) - { - for (j = 0; j < A->size; j++) - *OF++ = IF[j]; - IF = (const GLfloat *) (((const unsigned char *) IF) + A->stride); - } - break; - case GL_UNSIGNED_BYTE: - for (i = 0; i < count; i++) - { - for (j = 0; j < A->size; j++) - *OB++ = IB[j]; - IB += A->stride; - } - break; - default: - Assert (0, "bogus array type"); - break; - } - - A->data = data2; - A->bytes = bytes; - A->stride = stride2; - -# ifdef DEBUG - dump_array_data (A, count, "saved", name, 0); -# endif -} - - -static void -restore_arrays (list_fn *F, int count) -{ - int i = 0; - draw_array *A = F->arrays; - Assert (A, "missing array"); - - for (i = 0; i < 4; i++) - { - const char *name = 0; - - if (!A[i].size) - continue; - - Assert ((A[i].binding || A[i].data), - "array has neither buffer binding nor data"); - - glBindBuffer (GL_ARRAY_BUFFER, A[i].binding); - CHECK("glBindBuffer"); - - switch (i) { - case 0: glVertexPointer (A[i].size, A[i].type, A[i].stride, A[i].data); - name = "vertex "; - CHECK("glVertexPointer"); - break; - case 1: glNormalPointer ( A[i].type, A[i].stride, A[i].data); - name = "normal "; - CHECK("glNormalPointer"); - break; - case 2: glTexCoordPointer(A[i].size, A[i].type, A[i].stride, A[i].data); - name = "texture"; - CHECK("glTexCoordPointer"); - break; - case 3: glColorPointer (A[i].size, A[i].type, A[i].stride, A[i].data); - name = "color "; - CHECK("glColorPointer"); - break; - default: Assert (0, "wat"); break; - } - -# ifdef DEBUG - dump_array_data (&A[i], count, "restored", name, 0); -# endif - } - - glBindBuffer (GL_ARRAY_BUFFER, 0); /* Keep out of others' hands */ -} - - -void -jwzgles_glDrawArrays (GLuint mode, GLuint first, GLuint count) -{ - /* If we are auto-generating texture coordinates, do that now, after - the vertex array was installed, but before drawing, This happens - when recording into a list, or in direct mode. It must happen - before calling optimize_arrays() from glEndList(). - */ - if (! state->replaying_list && - ((state->compiling_list ? state->list_enabled : state->enabled) - & (ISENABLED_TEXTURE_GEN_S | ISENABLED_TEXTURE_GEN_T | - ISENABLED_TEXTURE_GEN_R | ISENABLED_TEXTURE_GEN_Q))) - generate_texture_coords (first, count); - - if (state->compiling_list) - { - void_int vv[3]; - vv[0].i = mode; - vv[1].i = first; - vv[2].i = count; - list_push ("glDrawArrays", (list_fn_cb) &jwzgles_glDrawArrays, - PROTO_ARRAYS, vv); - } - else - { -# ifdef DEBUG - if (! state->replaying_list) { - LOG4("direct %-12s %d %d %d", "glDrawArrays", mode, first, count); - dump_direct_array_data (first + count); - } -# endif - glDrawArrays (mode, first, count); /* the real one */ - CHECK("glDrawArrays"); - } -} - - -void -jwzgles_glInterleavedArrays (GLenum format, GLsizei stride, const void *data) -{ - /* We can implement this by calling the various *Pointer functions - with offsets into the same data, taking advantage of stride. - */ - const unsigned char *c = (const unsigned char *) data; -# define B 1 -# define F sizeof(GLfloat) - - Assert (!state->compiling_verts, - "glInterleavedArrays not allowed inside glBegin"); - - jwzgles_glEnableClientState (GL_VERTEX_ARRAY); - - if (!state->replaying_list) - LOG4 ("%sglInterleavedArrays %s %d %lX", - (state->compiling_list || state->replaying_list ? " " : ""), - mode_desc (format), stride, (unsigned long) data); - - switch (format) { - case GL_V2F: - glVertexPointer (2, GL_FLOAT, stride, c); - CHECK("glVertexPointer"); - if (!state->replaying_list) - LOG3 ("%s -> glVertexPointer 2 FLOAT %d %lX", - (state->compiling_list || state->replaying_list ? " " : ""), - stride, (unsigned long) c); - break; - case GL_V3F: - glVertexPointer (3, GL_FLOAT, stride, c); - CHECK("glVertexPointer"); - if (!state->replaying_list) - LOG3 ("%s -> glVertexPointer 3 FLOAT %d %lX", - (state->compiling_list || state->replaying_list ? " " : ""), - stride, (unsigned long) c); - break; - case GL_C4UB_V2F: - if (stride == 0) - stride = 4*B + 2*F; - jwzgles_glEnableClientState (GL_COLOR_ARRAY); - glColorPointer (4, GL_UNSIGNED_BYTE, stride, c); - CHECK("glColorPointer"); - c += 4*B; /* #### might be incorrect float-aligned address */ - glVertexPointer (2, GL_FLOAT, stride, c); - break; - case GL_C4UB_V3F: - if (stride == 0) - stride = 4*B + 3*F; - jwzgles_glEnableClientState (GL_COLOR_ARRAY); - glColorPointer (4, GL_UNSIGNED_BYTE, stride, c); - CHECK("glColorPointer"); - c += 4*B; - glVertexPointer (3, GL_FLOAT, stride, c); - CHECK("glVertexPointer"); - break; - case GL_C3F_V3F: - if (stride == 0) - stride = 3*F + 3*F; - jwzgles_glEnableClientState (GL_COLOR_ARRAY); - glColorPointer (3, GL_FLOAT, stride, c); - CHECK("glColorPointer"); - c += 3*F; - glVertexPointer (3, GL_FLOAT, stride, c); - CHECK("glVertexPointer"); - break; - case GL_N3F_V3F: - if (stride == 0) - stride = 3*F + 3*F; - jwzgles_glEnableClientState (GL_NORMAL_ARRAY); - glNormalPointer (GL_FLOAT, stride, c); - CHECK("glNormalPointer"); - if (!state->replaying_list) - LOG3 ("%s -> glNormalPointer FLOAT %d %lX", - (state->compiling_list || state->replaying_list ? " " : ""), - stride, (unsigned long) c); - c += 3*F; - glVertexPointer (3, GL_FLOAT, stride, c); - CHECK("glVertexPointer"); - if (!state->replaying_list) - LOG3 ("%s -> glVertexPointer 3 FLOAT %d %lX", - (state->compiling_list || state->replaying_list ? " " : ""), - stride, (unsigned long) c); - break; - case GL_C4F_N3F_V3F: - if (stride == 0) - stride = 4*F + 3*F + 3*F; - jwzgles_glEnableClientState (GL_COLOR_ARRAY); - glColorPointer (4, GL_FLOAT, stride, c); - CHECK("glColorPointer"); - c += 4*F; - jwzgles_glEnableClientState (GL_NORMAL_ARRAY); - glNormalPointer (GL_FLOAT, stride, c); - CHECK("glNormalPointer"); - c += 3*F; - glVertexPointer (3, GL_FLOAT, stride, c); - CHECK("glVertexPointer"); - break; - case GL_T2F_V3F: - if (stride == 0) - stride = 2*F + 3*F; - jwzgles_glEnableClientState (GL_TEXTURE_COORD_ARRAY); - glTexCoordPointer (2, GL_FLOAT, stride, c); - CHECK("glTexCoordPointer"); - c += 2*F; - glVertexPointer (3, GL_FLOAT, stride, c); - CHECK("glVertexPointer"); - break; - case GL_T4F_V4F: - if (stride == 0) - stride = 4*F + 4*F; - jwzgles_glEnableClientState (GL_TEXTURE_COORD_ARRAY); - glTexCoordPointer (4, GL_FLOAT, stride, c); - CHECK("glTexCoordPointer"); - c += 4*F; - glVertexPointer (4, GL_FLOAT, stride, c); - CHECK("glVertexPointer"); - break; - case GL_T2F_C4UB_V3F: - if (stride == 0) - stride = 2*F + 4*B + 3*F; - jwzgles_glEnableClientState (GL_TEXTURE_COORD_ARRAY); - glTexCoordPointer (2, GL_FLOAT, stride, c); - CHECK("glTexCoordPointer"); - c += 2*F; - jwzgles_glEnableClientState (GL_COLOR_ARRAY); - glColorPointer (4, GL_UNSIGNED_BYTE, stride, c); - CHECK("glColorPointer"); - c += 4*B; - glVertexPointer (3, GL_FLOAT, stride, c); - CHECK("glVertexPointer"); - break; - case GL_T2F_C3F_V3F: - if (stride == 0) - stride = 2*F + 3*F + 3*F; - jwzgles_glEnableClientState (GL_TEXTURE_COORD_ARRAY); - glTexCoordPointer (2, GL_FLOAT, stride, c); - CHECK("glTexCoordPointer"); - c += 2*F; - jwzgles_glEnableClientState (GL_COLOR_ARRAY); - glColorPointer (3, GL_FLOAT, stride, c); - CHECK("glColorPointer"); - c += 3*F; - glVertexPointer (3, GL_FLOAT, stride, c); - CHECK("glVertexPointer"); - break; - case GL_T2F_N3F_V3F: - if (stride == 0) - stride = 2*F + 3*F + 3*F; - jwzgles_glEnableClientState (GL_TEXTURE_COORD_ARRAY); - glTexCoordPointer (2, GL_FLOAT, stride, c); - CHECK("glTexCoordPointer"); - c += 2*F; - jwzgles_glEnableClientState (GL_NORMAL_ARRAY); - glNormalPointer (GL_FLOAT, stride, c); - CHECK("glNormalPointer"); - c += 3*F; - glVertexPointer (3, GL_FLOAT, stride, c); - CHECK("glVertexPointer"); - break; - case GL_T2F_C4F_N3F_V3F: - if (stride == 0) - stride = 2*F + 4*F + 3*F + 3*F; - jwzgles_glEnableClientState (GL_TEXTURE_COORD_ARRAY); - glTexCoordPointer (2, GL_FLOAT, stride, c); - CHECK("glTexCoordPointer"); - c += 2*F; - jwzgles_glEnableClientState (GL_COLOR_ARRAY); - glColorPointer (3, GL_FLOAT, stride, c); - CHECK("glColorPointer"); - c += 3*F; - jwzgles_glEnableClientState (GL_NORMAL_ARRAY); - glNormalPointer (GL_FLOAT, stride, c); - CHECK("glNormalPointer"); - c += 3*F; - glVertexPointer (3, GL_FLOAT, stride, c); - CHECK("glVertexPointer"); - break; - case GL_T4F_C4F_N3F_V4F: - if (stride == 0) - stride = 4*F + 4*F + 3*F + 4*F; - jwzgles_glEnableClientState (GL_TEXTURE_COORD_ARRAY); - glTexCoordPointer (4, GL_FLOAT, stride, c); - CHECK("glTexCoordPointer"); - c += 4*F; - jwzgles_glEnableClientState (GL_COLOR_ARRAY); - glColorPointer (4, GL_FLOAT, stride, c); - CHECK("glColorPointer"); - c += 4*F; - jwzgles_glEnableClientState (GL_NORMAL_ARRAY); - glNormalPointer (GL_FLOAT, stride, c); - CHECK("glNormalPointer"); - c += 3*F; - glVertexPointer (3, GL_FLOAT, stride, c); - CHECK("glVertexPointer"); - break; - default: - Assert (0, "glInterleavedArrays: bogus format"); - break; - } - -# undef B -# undef F -} - - - -void -jwzgles_glMultMatrixf (const GLfloat *m) -{ - Assert (!state->compiling_verts, - "glMultMatrixf not allowed inside glBegin"); - if (state->compiling_list) - { - void_int vv[16]; - int i; - for (i = 0; i < countof(vv); i++) - vv[i].f = m[i]; - list_push ("glMultMatrixf", (list_fn_cb) &jwzgles_glMultMatrixf, - PROTO_FV16, vv); - } - else - { - if (! state->replaying_list) - LOG1 ("direct %-12s", "glMultMatrixf"); - glMultMatrixf (m); /* the real one */ - CHECK("glMultMatrixf"); - } -} - - -void -jwzgles_glClearIndex(GLfloat c) -{ - /* Does GLES even do indexed color? */ - Assert (0, "glClearIndex unimplemented"); -} - - -void -jwzgles_glBitmap (GLsizei width, GLsizei height, GLfloat xorig, GLfloat yorig, - GLfloat xmove, GLfloat ymove, const GLubyte *bitmap) -{ - Assert (0, "glBitmap unimplemented"); -} - -void -jwzgles_glPushAttrib(int flags) -{ - Assert (0, "glPushAttrib unimplemented"); -} - -void -jwzgles_glPopAttrib(void) -{ - Assert (0, "glPopAttrib unimplemented"); -} - - -/* These are needed for object hit detection in pinion. - Might need to rewrite that code entirely. Punt for now. - */ -void -jwzgles_glInitNames (void) -{ -/* Assert (0, "glInitNames unimplemented");*/ -} - -void -jwzgles_glPushName (GLuint name) -{ -/* Assert (0, "glPushName unimplemented");*/ -} - -GLuint -jwzgles_glPopName (void) -{ -/* Assert (0, "glPopName unimplemented");*/ - return 0; -} - -GLuint -jwzgles_glRenderMode (GLuint mode) -{ -/* Assert (0, "glRenderMode unimplemented");*/ - return 0; -} - -void -jwzgles_glSelectBuffer (GLsizei size, GLuint *buf) -{ -/* Assert (0, "glSelectBuffer unimplemented");*/ -} - - -void -jwzgles_glGenTextures (GLuint n, GLuint *ret) -{ - Assert (!state->compiling_verts, - "glGenTextures not allowed inside glBegin"); - /* technically legal, but stupid! */ - Assert (!state->compiling_list, - "glGenTextures not allowed inside glNewList"); - if (! state->replaying_list) - LOG1 ("direct %-12s", "glGenTextures"); - glGenTextures (n, ret); /* the real one */ - CHECK("glGenTextures"); -} - - -/* return the next larger power of 2. */ -static int -to_pow2 (int value) -{ - int i = 1; - while (i < value) i <<= 1; - return i; -} - -void -jwzgles_glTexImage1D (GLenum target, GLint level, - GLint internalFormat, - GLsizei width, GLint border, - GLenum format, GLenum type, - const GLvoid *data) -{ - Assert (!state->compiling_verts, "glTexImage1D not allowed inside glBegin"); - /* technically legal, but stupid! */ - Assert (!state->compiling_list, "glTexImage1D inside glNewList"); - Assert (width == to_pow2(width), "width must be a power of 2"); - - if (target == GL_TEXTURE_1D) target = GL_TEXTURE_2D; - jwzgles_glTexImage2D (target, level, internalFormat, width, 1, - border, format, type, data); -} - -void -jwzgles_glTexImage2D (GLenum target, - GLint level, - GLint internalFormat, - GLsizei width, - GLsizei height, - GLint border, - GLenum format, - GLenum type, - const GLvoid *data) -{ - GLvoid *d2 = (GLvoid *) data; - Assert (!state->compiling_verts, "glTexImage2D not allowed inside glBegin"); - Assert (!state->compiling_list, /* technically legal, but stupid! */ - "glTexImage2D not allowed inside glNewList"); - - Assert (width == to_pow2(width), "width must be a power of 2"); - Assert (height == to_pow2(height), "height must be a power of 2"); - - /* OpenGLES no longer supports "4" as a synonym for "RGBA". */ - switch (internalFormat) { - case 1: internalFormat = GL_LUMINANCE; break; - case 2: internalFormat = GL_LUMINANCE_ALPHA; break; - case 3: internalFormat = GL_RGB; break; - case 4: internalFormat = GL_RGBA; break; - } - - /* GLES does not let us omit the data pointer to create a blank texture. */ - if (! data) - { - d2 = (GLvoid *) calloc (1, width * height * sizeof(GLfloat) * 4); - Assert (d2, "out of memory"); - } - - if (internalFormat == GL_RGB && format == GL_RGBA) - internalFormat = GL_RGBA; /* WTF */ - if (type == GL_UNSIGNED_INT_8_8_8_8_REV) - type = GL_UNSIGNED_BYTE; - - if (! state->replaying_list) - LOG10 ("direct %-12s %s %d %s %d %d %d %s %s 0x%lX", "glTexImage2D", - mode_desc(target), level, mode_desc(internalFormat), - width, height, border, mode_desc(format), mode_desc(type), - (unsigned long) d2); - glTexImage2D (target, level, internalFormat, width, height, border, - format, type, d2); /* the real one */ - CHECK("glTexImage2D"); - - if (d2 != data) free (d2); -} - -void -jwzgles_glTexSubImage2D (GLenum target, GLint level, - GLint xoffset, GLint yoffset, - GLsizei width, GLsizei height, - GLenum format, GLenum type, - const GLvoid *pixels) -{ - Assert (!state->compiling_verts, - "glTexSubImage2D not allowed inside glBegin"); - Assert (!state->compiling_list, /* technically legal, but stupid! */ - "glTexSubImage2D not allowed inside glNewList"); - - if (! state->replaying_list) - LOG10 ("direct %-12s %s %d %d %d %d %d %s %s 0x%lX", "glTexSubImage2D", - mode_desc(target), level, xoffset, yoffset, width, height, - mode_desc (format), mode_desc (type), (unsigned long) pixels); - glTexSubImage2D (target, level, xoffset, yoffset, width, height, - format, type, pixels); /* the real one */ - CHECK("glTexSubImage2D"); -} - -void -jwzgles_glCopyTexImage2D (GLenum target, GLint level, GLenum internalformat, - GLint x, GLint y, GLsizei width, GLsizei height, - GLint border) -{ - Assert (!state->compiling_verts, - "glCopyTexImage2D not allowed inside glBegin"); - Assert (!state->compiling_list, /* technically legal, but stupid! */ - "glCopyTexImage2D not allowed inside glNewList"); - if (! state->replaying_list) - LOG9 ("direct %-12s %s %d %s %d %d %d %d %d", "glCopyTexImage2D", - mode_desc(target), level, mode_desc(internalformat), - x, y, width, height, border); - glCopyTexImage2D (target, level, internalformat, x, y, width, height, - border); /* the real one */ - CHECK("glCopyTexImage2D"); -} - - -/* OpenGLES doesn't have auto texture-generation at all! - "Oh, just rewrite that code to use GPU shaders", they say. - How fucking convenient. - */ -void -jwzgles_glTexGenfv (GLenum coord, GLenum pname, const GLfloat *params) -{ - texgen_state *s; - - if (pname == GL_TEXTURE_GEN_MODE) - LOG5 ("%sdirect %-12s %s %s %s", - (state->compiling_list || state->replaying_list ? " " : ""), - "glTexGenfv", - mode_desc(coord), mode_desc(pname), mode_desc(params[0])); - else - LOG8 ("%sdirect %-12s %s %s %3.1f %3.1f %3.1f %3.1f", - (state->compiling_list || state->replaying_list ? " " : ""), - "glTexGenfv", - mode_desc(coord), mode_desc(pname), - params[0], params[1], params[2], params[3]); - - switch (coord) { - case GL_S: s = &state->s; break; - case GL_T: s = &state->t; break; - case GL_R: s = &state->r; break; - case GL_Q: s = &state->q; break; - default: Assert (0, "glGetTexGenfv: unknown coord"); break; - } - - switch (pname) { - case GL_TEXTURE_GEN_MODE: s->mode = params[0]; break; - case GL_OBJECT_PLANE: memcpy (s->obj, params, sizeof(s->obj)); break; - case GL_EYE_PLANE: memcpy (s->eye, params, sizeof(s->eye)); break; - default: Assert (0, "glTexGenfv: unknown pname"); break; - } -} - -void -jwzgles_glTexGeni (GLenum coord, GLenum pname, GLint param) -{ - GLfloat v = param; - jwzgles_glTexGenfv (coord, pname, &v); -} - -void -jwzgles_glGetTexGenfv (GLenum coord, GLenum pname, GLfloat *params) -{ - texgen_state *s; - - switch (coord) { - case GL_S: s = &state->s; break; - case GL_T: s = &state->t; break; - case GL_R: s = &state->r; break; - case GL_Q: s = &state->q; break; - default: Assert (0, "glGetTexGenfv: unknown coord"); break; - } - - switch (pname) { - case GL_TEXTURE_GEN_MODE: params[0] = s->mode; break; - case GL_OBJECT_PLANE: memcpy (params, s->obj, sizeof(s->obj)); break; - case GL_EYE_PLANE: memcpy (params, s->eye, sizeof(s->eye)); break; - default: Assert (0, "glGetTexGenfv: unknown pname"); break; - } - - if (pname == GL_TEXTURE_GEN_MODE) - LOG5 ("%sdirect %-12s %s %s -> %s", - (state->compiling_list || state->replaying_list ? " " : ""), - "glGetTexGenfv", - mode_desc(coord), mode_desc(pname), mode_desc(params[0])); - else - LOG8 ("%sdirect %-12s %s %s -> %3.1f %3.1f %3.1f %3.1f", - (state->compiling_list || state->replaying_list ? " " : ""), - "glGetTexGenfv", - mode_desc(coord), mode_desc(pname), - params[0], params[1], params[2], params[3]); -} - - -static GLfloat -dot_product (int rank, GLfloat *a, GLfloat *b) -{ - /* A dot B => (A[1] * B[1]) + ... + (A[n] * B[n]) */ - GLfloat ret = 0; - int i; - for (i = 0; i < rank; i++) - ret += a[i] * b[i]; - return ret; -} - - - -/* Compute the texture coordinates of the prevailing list of verts as per - http://www.opengl.org/wiki/Mathematics_of_glTexGen - */ -static void -generate_texture_coords (GLuint first, GLuint count) -{ - GLfloat *tex_out, *tex_array; - GLsizei tex_stride; - GLuint i; - draw_array A = { 0, }; - char *verts_in; - - struct { GLuint which, flag, mode; GLfloat plane[4]; } tg[4] = { - { GL_S, ISENABLED_TEXTURE_GEN_S, 0, { 0, } }, - { GL_T, ISENABLED_TEXTURE_GEN_T, 0, { 0, } }, - { GL_R, ISENABLED_TEXTURE_GEN_R, 0, { 0, } }, - { GL_Q, ISENABLED_TEXTURE_GEN_Q, 0, { 0, }}}; - - int tcoords = 0; - - /* Read the texture plane configs that were stored with glTexGen. - */ - for (i = 0; i < countof(tg); i++) - { - GLfloat mode = 0; - if (! ((state->compiling_list ? state->list_enabled : state->enabled) - & tg[i].flag)) - continue; - jwzgles_glGetTexGenfv (tg[i].which, GL_TEXTURE_GEN_MODE, &mode); - jwzgles_glGetTexGenfv (tg[i].which, GL_OBJECT_PLANE, tg[i].plane); - tg[i].mode = mode; - tcoords++; - } - - if (tcoords == 0) return; /* Nothing to do! */ - - - /* Make the array to store our texture coords in. */ - - tex_stride = tcoords * sizeof(GLfloat); - tex_array = (GLfloat *) calloc (first + count, tex_stride); - tex_out = tex_array; - - - /* Read the prevailing vertex array, that was stored with - glVertexPointer or glInterleavedArrays. - */ - glGetIntegerv (GL_VERTEX_ARRAY_BUFFER_BINDING, &A.binding); - glGetIntegerv (GL_VERTEX_ARRAY_SIZE, &A.size); - glGetIntegerv (GL_VERTEX_ARRAY_TYPE, &A.type); - glGetIntegerv (GL_VERTEX_ARRAY_STRIDE, &A.stride); - glGetPointerv (GL_VERTEX_ARRAY_POINTER, &A.data); - A.bytes = count * A.stride; - - verts_in = (char *) A.data; - - /* Iterate over each vertex we're drawing. - We just skip the ones < start, but the tex array has - left room for zeroes there anyway. - */ - for (i = first; i < first + count; i++) - { - GLfloat vert[4] = { 0, }; - int j, k; - - /* Extract this vertex into `vert' as a float, whatever its type was. */ - for (j = 0; j < A.size; j++) - { - switch (A.type) { - case GL_SHORT: vert[j] = ((GLshort *) verts_in)[j]; break; - case GL_INT: vert[j] = ((GLint *) verts_in)[j]; break; - case GL_FLOAT: vert[j] = ((GLfloat *) verts_in)[j]; break; - case GL_DOUBLE: vert[j] = ((GLdouble *) verts_in)[j]; break; - default: Assert (0, "unknown vertex type"); break; - } - } - - /* Compute the texture coordinate for this vertex. - For GL_OBJECT_LINEAR, these coordinates are static, and can go - into the display list. But for GL_EYE_LINEAR, GL_SPHERE_MAP and - GL_REFLECTION_MAP, they depend on the prevailing ModelView matrix, - and so need to be computed afresh each time glDrawArrays is called. - Unfortunately, our verts and norms are gone by then, dumped down - into the VBO and discarded from CPU RAM. Bleh. - */ - for (j = 0, k = 0; j < countof(tg); j++) - { - if (! ((state->compiling_list ? state->list_enabled : state->enabled) - & tg[j].flag)) - continue; - switch (tg[j].mode) { - case GL_OBJECT_LINEAR: - tex_out[k] = dot_product (4, vert, tg[j].plane); - break; - default: - Assert (0, "unimplemented texture mode"); - break; - } - k++; - } - - /* fprintf (stderr, "%4d: V %-5.1f %-5.1f %-5.1f T %-5.1f %-5.1f\n", - i, vert[0], vert[1], vert[2], tex_out[0], tex_out[1]); */ - - /* Move verts_in and tex_out forward to the next vertex by stride. */ - verts_in += A.stride; - tex_out = (GLfloat *) (((char *) tex_out) + tex_stride); - } - - jwzgles_glEnableClientState (GL_TEXTURE_COORD_ARRAY); - jwzgles_glTexCoordPointer (tcoords, GL_FLOAT, tex_stride, - (GLvoid *) tex_array); - free (tex_array); -} - - -int -jwzgles_gluBuild2DMipmaps (GLenum target, - GLint internalFormat, - GLsizei width, - GLsizei height, - GLenum format, - GLenum type, - const GLvoid *data) -{ - /* Not really bothering with mipmapping; only making one level. - Note that this required a corresponding hack in glTexParameterf(). - */ - - int w2 = to_pow2(width); - int h2 = to_pow2(height); - - void *d2 = (void *) data; - - /* OpenGLES no longer supports "4" as a synonym for "RGBA". */ - switch (internalFormat) { - case 1: internalFormat = GL_LUMINANCE; break; - case 2: internalFormat = GL_LUMINANCE_ALPHA; break; - case 3: internalFormat = GL_RGB; break; - case 4: internalFormat = GL_RGBA; break; - } - -/* if (w2 < h2) w2 = h2; - if (h2 < w2) h2 = w2;*/ - - if (w2 != width || h2 != height) - { - /* Scale up the image bits to fit the power-of-2 texture. - We have to do this because the mipmap API assumes that - the texture bits go to texture coordinates 1.0 x 1.0. - This could be more efficient, but it doesn't happen often. - */ - int istride = (format == GL_RGBA ? 4 : 3); - int ostride = 4; - int ibpl = istride * width; - int obpl = ostride * w2; - int oy; - const unsigned char *in = (unsigned char *) data; - unsigned char *out = (void *) malloc (h2 * obpl); - Assert (out, "out of memory"); - d2 = out; - - for (oy = 0; oy < h2; oy++) - { - int iy = oy * height / h2; - const unsigned char *iline = in + (iy * ibpl); - unsigned char *oline = out + (oy * obpl); - int ox; - for (ox = 0; ox < w2; ox++) - { - int ix = ox * width / w2; - const unsigned char *i = iline + (ix * istride); - unsigned char *o = oline + (ox * ostride); - *o++ = *i++; /* R */ - *o++ = *i++; /* G */ - *o++ = *i++; /* B */ - *o++ = (istride == 4 ? *i : 0xFF); /* A */ - } - } - width = w2; - height = h2; - internalFormat = GL_RGBA; - format = GL_RGBA; - } - - jwzgles_glTexImage2D (target, 0, internalFormat, w2, h2, 0, - format, type, d2); - if (d2 != data) free (d2); - - return 0; -} - - -void -jwzgles_glRectf (GLfloat x1, GLfloat y1, GLfloat x2, GLfloat y2) -{ - jwzgles_glBegin (GL_POLYGON); - jwzgles_glVertex2f (x1, y1); - jwzgles_glVertex2f (x2, y1); - jwzgles_glVertex2f (x2, y2); - jwzgles_glVertex2f (x1, y2); - jwzgles_glEnd (); -} - -void -jwzgles_glRecti (GLint x1, GLint y1, GLint x2, GLint y2) -{ - jwzgles_glRectf (x1, y1, x2, y2); -} - -void -jwzgles_glClearDepth (GLfloat d) -{ - /* Not sure what to do here */ - Assert (d == 1.0, "glClearDepth unimplemented"); -} - - -/* When in immediate mode, we store a bit into state->enabled, and also - call the real glEnable() / glDisable(). - - When recording a list, we store a bit into state->list_enabled instead, - so that we can see what the prevailing enablement state will be when - the list is run. - - set: 1 = set, -1 = clear, 0 = query. -*/ -static int -enable_disable (GLuint bit, int set) -{ - int result = (set > 0); - int omitp = 0; - int csp = 0; - unsigned long flag = 0; - - switch (bit) { - case GL_TEXTURE_1D: /* We implement 1D textures as 2D textures. */ - case GL_TEXTURE_2D: flag = ISENABLED_TEXTURE_2D; break; - case GL_TEXTURE_GEN_S: flag = ISENABLED_TEXTURE_GEN_S; omitp = 1; break; - case GL_TEXTURE_GEN_T: flag = ISENABLED_TEXTURE_GEN_T; omitp = 1; break; - case GL_TEXTURE_GEN_R: flag = ISENABLED_TEXTURE_GEN_R; omitp = 1; break; - case GL_TEXTURE_GEN_Q: flag = ISENABLED_TEXTURE_GEN_Q; omitp = 1; break; - case GL_LIGHTING: flag = ISENABLED_LIGHTING; break; - case GL_BLEND: flag = ISENABLED_BLEND; break; - case GL_DEPTH_TEST: flag = ISENABLED_DEPTH_TEST; break; - case GL_ALPHA_TEST: flag = ISENABLED_ALPHA_TEST; break; - case GL_CULL_FACE: flag = ISENABLED_CULL_FACE; break; - case GL_NORMALIZE: flag = ISENABLED_NORMALIZE; break; - case GL_FOG: flag = ISENABLED_FOG; break; - case GL_COLOR_MATERIAL: flag = ISENABLED_COLMAT; break; - - /* Maybe technically these only work with glEnableClientState, - but we treat that as synonymous with glEnable. */ - case GL_VERTEX_ARRAY: flag = ISENABLED_VERT_ARRAY; csp = 1; break; - case GL_NORMAL_ARRAY: flag = ISENABLED_NORM_ARRAY; csp = 1; break; - case GL_COLOR_ARRAY: flag = ISENABLED_COLOR_ARRAY; csp = 1; break; - case GL_TEXTURE_COORD_ARRAY: flag = ISENABLED_TEX_ARRAY; csp = 1; break; - - default: - Assert (set != 0, "glIsEnabled unimplemented bit"); - break; - } - - if (set) /* setting or unsetting, not querying */ - { - const char *fns[4] = { "glEnable", "glDisable", - "glEnableClientState", "glDisableClientState" }; - list_fn_cb fs[4] = { (list_fn_cb) &jwzgles_glEnable, - (list_fn_cb) &jwzgles_glDisable, - (list_fn_cb) &jwzgles_glEnableClientState, - (list_fn_cb) &jwzgles_glDisableClientState }; - const char *fn = fns[(csp ? 2 : 0) + (set < 0 ? 1 : 0)]; - list_fn_cb f = fs[(csp ? 2 : 0) + (set < 0 ? 1 : 0)]; - - Assert (!state->compiling_verts, - "glEnable/glDisable not allowed inside glBegin"); - - if (state->compiling_list) - { - void_int vv[1]; - vv[0].i = bit; - list_push (fn, f,PROTO_I, vv); - } - - if (! state->replaying_list && - ! state->compiling_list) - LOG2 ("direct %-12s %s", fn, mode_desc(bit)); - - if (csp && !state->compiling_verts) - { - if (set > 0) - switch (bit) { - case GL_NORMAL_ARRAY: state->set.ncount += 2; break; - case GL_TEXTURE_COORD_ARRAY: state->set.tcount += 2; break; - case GL_COLOR_ARRAY: state->set.ccount += 2; break; - default: break; - } - else - switch (bit) { - case GL_NORMAL_ARRAY: state->set.ncount = 0; break; - case GL_TEXTURE_COORD_ARRAY: state->set.tcount = 0; break; - case GL_COLOR_ARRAY: state->set.ccount = 0; break; - default: break; - } - } - - if (omitp || state->compiling_list) - ; - else if (set > 0 && csp) - glEnableClientState (bit); /* the real one */ - else if (set < 0 && csp) - glDisableClientState (bit); /* the real one */ - else if (set > 0) - glEnable (bit); /* the real one */ - else - glDisable (bit); /* the real one */ - - CHECK(fn); - } - - /* Store the bit in our state as well, or query it. - */ - if (flag) - { - unsigned long *enabled = (state->compiling_list - ? &state->list_enabled - : &state->enabled); - if (set > 0) - *enabled |= flag; - else if (set < 0) - *enabled &= ~flag; - else - result = !!(*enabled & flag); - } - - return result; -} - - -void -jwzgles_glEnable (GLuint bit) -{ - enable_disable (bit, 1); -} - -void -jwzgles_glDisable (GLuint bit) -{ - enable_disable (bit, -1); -} - -GLboolean -jwzgles_glIsEnabled (GLuint bit) -{ - return enable_disable (bit, 0); -} - -void -jwzgles_glEnableClientState (GLuint cap) -{ - enable_disable (cap, 1); -} - -void -jwzgles_glDisableClientState (GLuint cap) -{ - enable_disable (cap, -1); -} - - - -/* The spec says that OpenGLES 1.x doesn't implement glGetFloatv. - Were this true, it would suck, for it would mean that there was no - way to retrieve the prevailing matrixes. To implement this, we'd - have to keep track of them all on the client side by combining in - all the actions of glMultMatrixf, glRotatef, etc. - - However, Apple's iOS OpenGLES *does* provide glGetFloatv! - */ -void -jwzgles_glGetFloatv (GLenum pname, GLfloat *params) -{ - if (! state->replaying_list) - LOG2 ("direct %-12s %s", "glGetFloatv", mode_desc(pname)); - glGetFloatv (pname, params); /* the real one */ - CHECK("glGetFloatv"); -} - - -/* Likewise: not supposed to be there, but it is. */ -void -jwzgles_glGetPointerv (GLenum pname, GLvoid *params) -{ - if (! state->replaying_list) - LOG2 ("direct %-12s %s", "glGetPointerv", mode_desc(pname)); - glGetPointerv (pname, params); /* the real one */ - CHECK("glGetPointerv"); -} - - -/* How many cells are written into the *params array. - We need to know this to avoid smashing the caller's stack - if they asked for a single-value parameter. - */ -static int -glGet_ret_count (GLenum pname) -{ - switch (pname) { -/*case GL_COLOR_MATRIX: */ - case GL_MODELVIEW_MATRIX: - case GL_PROJECTION_MATRIX: - case GL_TEXTURE_MATRIX: -/*case GL_TRANSPOSE_COLOR_MATRIX: */ -/*case GL_TRANSPOSE_MODELVIEW_MATRIX: */ -/*case GL_TRANSPOSE_PROJECTION_MATRIX: */ -/*case GL_TRANSPOSE_TEXTURE_MATRIX: */ - return 16; -/*case GL_ACCUM_CLEAR_VALUE: */ -/*case GL_BLEND_COLOR: */ - case GL_COLOR_CLEAR_VALUE: - case GL_COLOR_WRITEMASK: - case GL_CURRENT_COLOR: -/*case GL_CURRENT_RASTER_COLOR: */ -/*case GL_CURRENT_RASTER_POSITION: */ -/*case GL_CURRENT_RASTER_SECONDARY_COLOR: */ -/*case GL_CURRENT_RASTER_TEXTURE_COORDS: */ -/*case GL_CURRENT_SECONDARY_COLOR: */ - case GL_CURRENT_TEXTURE_COORDS: - case GL_FOG_COLOR: - case GL_LIGHT_MODEL_AMBIENT: -/*case GL_MAP2_GRID_DOMAIN: */ - case GL_SCISSOR_BOX: - case GL_VIEWPORT: - return 4; - case GL_CURRENT_NORMAL: - case GL_POINT_DISTANCE_ATTENUATION: - return 3; - case GL_ALIASED_LINE_WIDTH_RANGE: - case GL_ALIASED_POINT_SIZE_RANGE: - case GL_DEPTH_RANGE: -/*case GL_LINE_WIDTH_RANGE: */ -/*case GL_MAP1_GRID_DOMAIN: */ -/*case GL_MAP2_GRID_SEGMENTS: */ - case GL_MAX_VIEWPORT_DIMS: -/*case GL_POINT_SIZE_RANGE: */ - case GL_POLYGON_MODE: - case GL_SMOOTH_LINE_WIDTH_RANGE: - case GL_SMOOTH_POINT_SIZE_RANGE: - return 2; - default: - return 1; - } -} - - -void -jwzgles_glGetDoublev (GLenum pname, GLdouble *params) -{ - GLfloat m[16]; - int i, j = glGet_ret_count (pname); - jwzgles_glGetFloatv (pname, m); - for (i = 0; i < j; i++) - params[i] = m[i]; -} - - -void -jwzgles_glGetIntegerv (GLenum pname, GLint *params) -{ - GLfloat m[16]; - int i, j = glGet_ret_count (pname); - jwzgles_glGetFloatv (pname, m); - for (i = 0; i < j; i++) - params[i] = m[i]; -} - - -void -jwzgles_glGetBooleanv (GLenum pname, GLboolean *params) -{ - GLfloat m[16]; - int i, j = glGet_ret_count (pname); - jwzgles_glGetFloatv (pname, m); - for (i = 0; i < j; i++) - params[i] = (m[i] != 0.0); -} - - -const char * -jwzgles_gluErrorString (GLenum error) -{ - static char s[20]; - sprintf (s, "0x%lX", (unsigned long) error); - return s; -} - - -/* These four *Pointer calls (plus glBindBuffer and glBufferData) can - be included inside glNewList, but they actually execute immediately - anyway, because their data is recorded in the list by the - subsequently-recorded call to glDrawArrays. This is a little weird. - */ -void -jwzgles_glVertexPointer (GLuint size, GLuint type, GLuint stride, - const GLvoid *ptr) -{ - if (! state->replaying_list) - LOG5 ("direct %-12s %d %s %d 0x%lX", "glVertexPointer", - size, mode_desc(type), stride, (unsigned long) ptr); - glVertexPointer (size, type, stride, ptr); /* the real one */ - CHECK("glVertexPointer"); -} - - -void -jwzgles_glNormalPointer (GLuint type, GLuint stride, const GLvoid *ptr) -{ - if (! state->replaying_list) - LOG4 ("direct %-12s %s %d 0x%lX", "glNormalPointer", - mode_desc(type), stride, (unsigned long) ptr); - glNormalPointer (type, stride, ptr); /* the real one */ - CHECK("glNormalPointer"); -} - -void -jwzgles_glColorPointer (GLuint size, GLuint type, GLuint stride, - const GLvoid *ptr) -{ - if (! state->replaying_list) - LOG5 ("direct %-12s %d %s %d 0x%lX", "glColorPointer", - size, mode_desc(type), stride, (unsigned long) ptr); - glColorPointer (size, type, stride, ptr); /* the real one */ - CHECK("glColorPointer"); -} - -void -jwzgles_glTexCoordPointer (GLuint size, GLuint type, GLuint stride, - const GLvoid *ptr) -{ - if (! state->replaying_list) - LOG5 ("direct %-12s %d %s %d 0x%lX", "glTexCoordPointer", - size, mode_desc(type), stride, (unsigned long) ptr); - glTexCoordPointer (size, type, stride, ptr); /* the real one */ - CHECK("glTexCoordPointer"); -} - -void -jwzgles_glBindBuffer (GLuint target, GLuint buffer) -{ - if (! state->replaying_list) - LOG3 ("direct %-12s %s %d", "glBindBuffer", mode_desc(target), buffer); - glBindBuffer (target, buffer); /* the real one */ - CHECK("glBindBuffer"); -} - -void -jwzgles_glBufferData (GLenum target, GLsizeiptr size, const void *data, - GLenum usage) -{ - if (! state->replaying_list) - LOG5 ("direct %-12s %s %ld 0x%lX %s", "glBufferData", - mode_desc(target), size, (unsigned long) data, mode_desc(usage)); - glBufferData (target, size, data, usage); /* the real one */ - CHECK("glBufferData"); -} - - -void -jwzgles_glTexParameterf (GLuint target, GLuint pname, GLfloat param) -{ - Assert (!state->compiling_verts, - "glTexParameterf not allowed inside glBegin"); - - /* We don't *really* implement mipmaps, so just turn this off. */ - if (param == GL_LINEAR_MIPMAP_LINEAR) param = GL_LINEAR; - if (param == GL_NEAREST_MIPMAP_LINEAR) param = GL_LINEAR; - if (param == GL_LINEAR_MIPMAP_NEAREST) param = GL_NEAREST; - if (param == GL_NEAREST_MIPMAP_NEAREST) param = GL_NEAREST; - - /* We implement 1D textures as 2D textures. */ - if (target == GL_TEXTURE_1D) target = GL_TEXTURE_2D; - - /* Apparently this is another invalid enum. Just ignore it. */ - if ((pname == GL_TEXTURE_WRAP_S || pname == GL_TEXTURE_WRAP_T) && - param == GL_CLAMP) - return; - - if (state->compiling_list) - { - void_int vv[3]; - vv[0].i = target; - vv[1].i = pname; - vv[2].f = param; - list_push ("glTexParameterf", (list_fn_cb) &jwzgles_glTexParameterf, - PROTO_IIF, vv); - } - else - { - if (! state->replaying_list) - LOG4 ("direct %-12s %s %s %7.3f", "glTexParameterf", - mode_desc(target), mode_desc(pname), param); - glTexParameterf (target, pname, param); /* the real one */ - CHECK("glTexParameterf"); - } -} - -void -jwzgles_glTexParameteri (GLuint target, GLuint pname, GLuint param) -{ - jwzgles_glTexParameterf (target, pname, param); -} - - -void -jwzgles_glBindTexture (GLuint target, GLuint texture) -{ - Assert (!state->compiling_verts, - "glBindTexture not allowed inside glBegin"); - - /* We implement 1D textures as 2D textures. */ - if (target == GL_TEXTURE_1D) target = GL_TEXTURE_2D; - - if (state->compiling_list) - { - void_int vv[2]; - vv[0].i = target; - vv[1].i = texture; - list_push ("glBindTexture", (list_fn_cb) &jwzgles_glBindTexture, - PROTO_II, vv); - } - - /* Do it immediately as well, for generate_texture_coords */ - /* else */ - { - if (! state->replaying_list) - LOG3 ("direct %-12s %s %d", "glBindTexture", - mode_desc(target), texture); - glBindTexture (target, texture); /* the real one */ - CHECK("glBindTexture"); - } -} - - - -/* Matrix functions, mostly cribbed from Mesa. - */ - -void -jwzgles_glFrustum (GLfloat left, GLfloat right, - GLfloat bottom, GLfloat top, - GLfloat near, GLfloat far) -{ - GLfloat m[16]; - GLfloat x = (2 * near) / (right-left); - GLfloat y = (2 * near) / (top - bottom); - GLfloat a = (right + left) / (right - left); - GLfloat b = (top + bottom) / (top - bottom); - GLfloat c = -(far + near) / (far - near); - GLfloat d = -(2 * far * near) / (far - near); - -# define M(X,Y) m[Y * 4 + X] - M(0,0) = x; M(0,1) = 0; M(0,2) = a; M(0,3) = 0; - M(1,0) = 0; M(1,1) = y; M(1,2) = b; M(1,3) = 0; - M(2,0) = 0; M(2,1) = 0; M(2,2) = c; M(2,3) = d; - M(3,0) = 0; M(3,1) = 0; M(3,2) = -1; M(3,3) = 0; -# undef M - - jwzgles_glMultMatrixf (m); -} - - -void -jwzgles_glOrtho (GLfloat left, GLfloat right, - GLfloat bottom, GLfloat top, - GLfloat near, GLfloat far) -{ - GLfloat m[16]; - GLfloat a = 2 / (right - left); - GLfloat b = -(right + left) / (right - left); - GLfloat c = 2 / (top - bottom); - GLfloat d = -(top + bottom) / (top - bottom); - GLfloat e = -2 / (far - near); - GLfloat f = -(far + near) / (far - near); - -# define M(X,Y) m[Y * 4 + X] - M(0,0) = a; M(0,1) = 0; M(0,2) = 0; M(0,3) = b; - M(1,0) = 0; M(1,1) = c; M(1,2) = 0; M(1,3) = d; - M(2,0) = 0; M(2,1) = 0; M(2,2) = e; M(2,3) = f; - M(3,0) = 0; M(3,1) = 0; M(3,2) = 0; M(3,3) = 1; -# undef M - - jwzgles_glMultMatrixf (m); -} - - -void -jwzgles_gluPerspective (GLdouble fovy, GLdouble aspect, - GLdouble near, GLdouble far) -{ - GLfloat m[16]; - double si, co, dz; - double rad = fovy / 2 * M_PI / 180; - double a, b, c, d; - - dz = far - near; - si = sin(rad); - if (dz == 0 || si == 0 || aspect == 0) - return; - co = cos(rad) / si; - - a = co / aspect; - b = co; - c = -(far + near) / dz; - d = -2 * near * far / dz; - -# define M(X,Y) m[Y * 4 + X] - M(0,0) = a; M(0,1) = 0; M(0,2) = 0; M(0,3) = 0; - M(1,0) = 0; M(1,1) = b; M(1,2) = 0; M(1,3) = 0; - M(2,0) = 0; M(2,1) = 0; M(2,2) = c; M(2,3) = d; - M(3,0) = 0; M(3,1) = 0; M(3,2) = -1; M(3,3) = 0; -# undef M - - jwzgles_glMultMatrixf (m); -} - - -void -jwzgles_gluLookAt (GLfloat eyex, GLfloat eyey, GLfloat eyez, - GLfloat centerx, GLfloat centery, GLfloat centerz, - GLfloat upx, GLfloat upy, GLfloat upz) -{ - GLfloat m[16]; - GLfloat x[3], y[3], z[3]; - GLfloat mag; - - /* Make rotation matrix */ - - /* Z vector */ - z[0] = eyex - centerx; - z[1] = eyey - centery; - z[2] = eyez - centerz; - mag = sqrt(z[0] * z[0] + z[1] * z[1] + z[2] * z[2]); - if (mag) { /* mpichler, 19950515 */ - z[0] /= mag; - z[1] /= mag; - z[2] /= mag; - } - - /* Y vector */ - y[0] = upx; - y[1] = upy; - y[2] = upz; - - /* X vector = Y cross Z */ - x[0] = y[1] * z[2] - y[2] * z[1]; - x[1] = -y[0] * z[2] + y[2] * z[0]; - x[2] = y[0] * z[1] - y[1] * z[0]; - - /* Recompute Y = Z cross X */ - y[0] = z[1] * x[2] - z[2] * x[1]; - y[1] = -z[0] * x[2] + z[2] * x[0]; - y[2] = z[0] * x[1] - z[1] * x[0]; - - /* mpichler, 19950515 */ - /* cross product gives area of parallelogram, which is < 1.0 for - * non-perpendicular unit-length vectors; so normalize x, y here - */ - - mag = sqrt(x[0] * x[0] + x[1] * x[1] + x[2] * x[2]); - if (mag) { - x[0] /= mag; - x[1] /= mag; - x[2] /= mag; - } - - mag = sqrt(y[0] * y[0] + y[1] * y[1] + y[2] * y[2]); - if (mag) { - y[0] /= mag; - y[1] /= mag; - y[2] /= mag; - } - -#define M(row,col) m[col*4+row] - M(0, 0) = x[0]; M(0, 1) = x[1]; M(0, 2) = x[2]; M(0, 3) = 0.0; - M(1, 0) = y[0]; M(1, 1) = y[1]; M(1, 2) = y[2]; M(1, 3) = 0.0; - M(2, 0) = z[0]; M(2, 1) = z[1]; M(2, 2) = z[2]; M(2, 3) = 0.0; - M(3, 0) = 0.0; M(3, 1) = 0.0; M(3, 2) = 0.0; M(3, 3) = 1.0; -#undef M - - jwzgles_glMultMatrixf(m); - - /* Translate Eye to Origin */ - jwzgles_glTranslatef(-eyex, -eyey, -eyez); -} - - -static void __gluMultMatrixVecd (const GLdouble matrix[16], - const GLdouble in[4], - GLdouble out[4]) -{ - int i; - - for (i=0; i<4; i++) { - out[i] = - in[0] * matrix[0*4+i] + - in[1] * matrix[1*4+i] + - in[2] * matrix[2*4+i] + - in[3] * matrix[3*4+i]; - } -} - -GLint -jwzgles_gluProject (GLdouble objx, GLdouble objy, GLdouble objz, - const GLdouble modelMatrix[16], - const GLdouble projMatrix[16], - const GLint viewport[4], - GLdouble *winx, GLdouble *winy, GLdouble *winz) -{ - GLdouble in[4]; - GLdouble out[4]; - - /* #### I suspect this is not working right. I was seeing crazy values - in lament.c. Maybe there's some float-vs-double confusion going on? - */ - - in[0]=objx; - in[1]=objy; - in[2]=objz; - in[3]=1.0; - __gluMultMatrixVecd(modelMatrix, in, out); - __gluMultMatrixVecd(projMatrix, out, in); - if (in[3] == 0.0) return(GL_FALSE); - in[0] /= in[3]; - in[1] /= in[3]; - in[2] /= in[3]; - /* Map x, y and z to range 0-1 */ - in[0] = in[0] * 0.5 + 0.5; - in[1] = in[1] * 0.5 + 0.5; - in[2] = in[2] * 0.5 + 0.5; - - /* Map x,y to viewport */ - in[0] = in[0] * viewport[2] + viewport[0]; - in[1] = in[1] * viewport[3] + viewport[1]; - - *winx=in[0]; - *winy=in[1]; - *winz=in[2]; - return(GL_TRUE); -} - - -void jwzgles_glViewport (GLuint x, GLuint y, GLuint w, GLuint h) -{ -# if TARGET_IPHONE_SIMULATOR -/* fprintf (stderr, "glViewport %dx%d\n", w, h); */ -# endif - glViewport (x, y, w, h); /* the real one */ -} - - -/* The following functions are present in both OpenGL 1.1 and in OpenGLES 1, - but are allowed within glNewList/glEndList, so we must wrap them to allow - them to either be recorded in lists, or run directly. - - All this CPP obscenity is me screaming in rage at all the ways that C is - not Lisp, as all I want to do here is DEFADVICE. - */ - -#define PROTO_V PROTO_VOID -#define TYPE_V GLuint -#define ARGS_V void -#define VARS_V /* */ -#define LOGS_V "\n" -#define FILL_V /* */ - -#define TYPE_I GLuint -#define TYPE_II TYPE_I -#define TYPE_III TYPE_I -#define TYPE_IIII TYPE_I -#define ARGS_I TYPE_I a -#define ARGS_II TYPE_I a, TYPE_I b -#define ARGS_III TYPE_I a, TYPE_I b, TYPE_I c -#define ARGS_IIII TYPE_I a, TYPE_I b, TYPE_I c, TYPE_I d -#define LOGS_I "%s\n", mode_desc(a) -#define LOGS_II "%s %d\n", mode_desc(a), b -#define LOGS_III "%s %s %s\n", mode_desc(a), mode_desc(b), mode_desc(c) -#define LOGS_IIII "%d %d %d %d\n", a, b, c, d -#define VARS_I a -#define VARS_II a, b -#define VARS_III a, b, c -#define VARS_IIII a, b, c, d -#define FILL_I vv[0].i = a; -#define FILL_II vv[0].i = a; vv[1].i = b; -#define FILL_III vv[0].i = a; vv[1].i = b; vv[2].i = c; -#define FILL_IIII vv[0].i = a; vv[1].i = b; vv[2].i = c; vv[3].i = d; - -#define TYPE_F GLfloat -#define TYPE_FF TYPE_F -#define TYPE_FFF TYPE_F -#define TYPE_FFFF TYPE_F -#define ARGS_F TYPE_F a -#define ARGS_FF TYPE_F a, TYPE_F b -#define ARGS_FFF TYPE_F a, TYPE_F b, TYPE_F c -#define ARGS_FFFF TYPE_F a, TYPE_F b, TYPE_F c, TYPE_F d -#define LOGS_F "%7.3f\n", a -#define LOGS_FF "%7.3f %7.3f\n", a, b -#define LOGS_FFF "%7.3f %7.3f %7.3f\n", a, b, c -#define LOGS_FFFF "%7.3f %7.3f %7.3f %7.3f\n", a, b, c, d -#define VARS_F VARS_I -#define VARS_FF VARS_II -#define VARS_FFF VARS_III -#define VARS_FFFF VARS_IIII -#define FILL_F vv[0].f = a; -#define FILL_FF vv[0].f = a; vv[1].f = b; -#define FILL_FFF vv[0].f = a; vv[1].f = b; vv[2].f = c; -#define FILL_FFFF vv[0].f = a; vv[1].f = b; vv[2].f = c; vv[3].f = d; - -#define ARGS_IF TYPE_I a, TYPE_F b -#define VARS_IF VARS_II -#define LOGS_IF "%s %7.3f\n", mode_desc(a), b -#define FILL_IF vv[0].i = a; vv[1].f = b; - -#define ARGS_IIF TYPE_I a, TYPE_I b, TYPE_F c -#define VARS_IIF VARS_III -#define LOGS_IIF "%s %s %7.3f\n", mode_desc(a), mode_desc(b), c -#define FILL_IIF vv[0].i = a; vv[1].i = b; vv[2].f = c; - -#define TYPE_IV GLint -#define ARGS_IIV TYPE_I a, const TYPE_IV *b -#define VARS_IIV VARS_II -#define LOGS_IIV "%s %d %d %d %d\n", mode_desc(a), b[0], b[1], b[2], b[3] -#define FILL_IIV vv[0].i = a; \ - vv[1].i = b[0]; vv[2].i = b[1]; \ - vv[3].i = b[2]; vv[4].i = b[3]; - -#define ARGS_IFV TYPE_I a, const TYPE_F *b -#define VARS_IFV VARS_II -#define LOGS_IFV "%s %7.3f %7.3f %7.3f %7.3f\n", mode_desc(a), \ - b[0], b[1], b[2], b[3] -#define FILL_IFV vv[0].i = a; \ - vv[1].f = b[0]; vv[2].f = b[1]; \ - vv[3].f = b[2]; vv[4].f = b[3]; - -#define ARGS_IIIV TYPE_I a, TYPE_I b, const TYPE_IV *c -#define VARS_IIIV VARS_III -#define LOGS_IIIV "%s %-8s %3d %3d %3d %3d\n", mode_desc(a), mode_desc(b), \ - c[0], c[1], c[2], c[3] -#define FILL_IIIV vv[0].i = a; vv[1].i = b; \ - vv[2].i = c[0]; vv[3].i = c[1]; \ - vv[4].i = c[2]; vv[5].i = c[3]; - -#define ARGS_IIFV TYPE_I a, TYPE_I b, const TYPE_F *c -#define VARS_IIFV VARS_III -#define LOGS_IIFV "%s %-8s %7.3f %7.3f %7.3f %7.3f\n", \ - mode_desc(a), mode_desc(b), \ - c[0], c[1], c[2], c[3] -#define FILL_IIFV vv[0].i = a; vv[1].i = b; \ - vv[2].f = c[0]; vv[3].f = c[1]; \ - vv[4].f = c[2]; vv[5].f = c[3]; - -#ifdef DEBUG -# define WLOG(NAME,ARGS) \ - fprintf (stderr, "jwzgles: direct %-12s ", NAME); \ - fprintf (stderr, ARGS) -#else -# define WLOG(NAME,ARGS) /* */ -#endif - -#define WRAP(NAME,SIG) \ -void jwzgles_##NAME (ARGS_##SIG) \ -{ \ - Assert (!state->compiling_verts, \ - STRINGIFY(NAME) " not allowed inside glBegin"); \ - if (state->compiling_list) { \ - void_int vv[10]; \ - FILL_##SIG \ - list_push (STRINGIFY(NAME), (list_fn_cb) &jwzgles_##NAME, \ - PROTO_##SIG, vv); \ - } else { \ - if (! state->replaying_list) { \ - WLOG (STRINGIFY(NAME), LOGS_##SIG); \ - } \ - NAME (VARS_##SIG); \ - CHECK(STRINGIFY(NAME)); \ - } \ -} - -WRAP (glActiveTexture, I) -WRAP (glAlphaFunc, IF) -WRAP (glBlendFunc, II) -WRAP (glClear, I) -WRAP (glClearColor, FFFF) -WRAP (glClearStencil, I) -WRAP (glColorMask, IIII) -WRAP (glCullFace, I) -WRAP (glDepthFunc, I) -WRAP (glDepthMask, I) -WRAP (glFinish, V) -WRAP (glFlush, V) -WRAP (glFogf, IF) -WRAP (glFogfv, IFV) -WRAP (glFrontFace, I) -WRAP (glHint, II) -WRAP (glLightModelf, IF) -WRAP (glLightModelfv, IFV) -WRAP (glLightf, IIF) -WRAP (glLightfv, IIFV) -WRAP (glLineWidth, F) -WRAP (glLoadIdentity, V) -WRAP (glLogicOp, I) -WRAP (glMatrixMode, I) -WRAP (glPixelStorei, II) -WRAP (glPointSize, F) -WRAP (glPolygonOffset, FF) -WRAP (glPopMatrix, V) -WRAP (glPushMatrix, V) -WRAP (glRotatef, FFFF) -WRAP (glScalef, FFF) -WRAP (glScissor, IIII) -WRAP (glShadeModel, I) -WRAP (glStencilFunc, III) -WRAP (glStencilMask, I) -WRAP (glStencilOp, III) -WRAP (glTexEnvf, IIF) -WRAP (glTexEnvi, III) -WRAP (glTranslatef, FFF) -#undef TYPE_IV -#define TYPE_IV GLuint -WRAP (glDeleteTextures, IIV) - - -#endif /* HAVE_JWZGLES - whole file */