#include <string.h>
#include <dlfcn.h>
#include <sys/uio.h>
+#include <X11/Xlib.h>
#include <GL/gl.h>
+#include <GL/glx.h>
+#include "arraysize.h"
#include "functions.h"
static inline void *glsym(const char *sym)
{
- static void *libgl=NULL;
+ static void *libgl = NULL;
if(!libgl)
{
- libgl=dlopen("libGL.so", RTLD_NOW);
+ const char *libgl_name = getenv("GLWRAP_LIBGL");
+ if(!libgl_name)
+ libgl_name = "libGL.so";
+ libgl = dlopen(libgl_name, RTLD_NOW);
if(!libgl)
{
- fprintf(stderr, "Could not open libGL: %s\n", dlerror());
+ fprintf(stderr, "Could not open %s: %s\n", libgl_name, dlerror());
abort();
}
}
return dlsym(libgl, sym);
}
-char *buffer=0;
-char *write_pos;
-struct iovec *iovecs=0;
-struct iovec *cur_vec;
+static char *buffer = 0;
+static char *write_pos;
+static struct iovec *iovecs = 0;
+static struct iovec *cur_vec;
+static unsigned length;
static inline void next_vec()
{
if(write_pos!=cur_vec->iov_base)
{
- cur_vec->iov_len=write_pos-(char *)cur_vec->iov_base;
+ cur_vec->iov_len = write_pos-(char *)cur_vec->iov_base;
+ length += cur_vec->iov_len;
++cur_vec;
- cur_vec->iov_base=write_pos;
+ cur_vec->iov_base = write_pos;
}
}
{
unsigned i;
for(i=0; i<size; ++i)
- *write_pos++=*ptr++;
+ *write_pos++ = *ptr++;
}
static inline void write_char(char v)
{
- *write_pos++=v;
+ *write_pos++ = v;
}
static inline void write_short(short v)
write_bytes((char *)&v, sizeof(long));
}
-static inline void write_ulong(unsigned long v)
-{
- write_bytes((char *)&v, sizeof(unsigned long));
-}
-
-static inline void write_longlong(long long v)
+static inline void write_long_long(long long v)
{
write_bytes((char *)&v, sizeof(long long));
}
write_bytes((char *)&v, sizeof(float));
}
-static inline void write_double(float v)
+static inline void write_double(double v)
{
write_bytes((char *)&v, sizeof(double));
}
static inline void write_data(const void *data, unsigned size)
{
- write_int(size);
- next_vec();
- cur_vec->iov_base=(void *)data;
- cur_vec->iov_len=size;
- ++cur_vec;
- cur_vec->iov_base=write_pos;
+ if(data)
+ {
+ write_int(size);
+ next_vec();
+ cur_vec->iov_base = (void *)data;
+ cur_vec->iov_len = size;
+ length += size;
+ ++cur_vec;
+ cur_vec->iov_base = write_pos;
+ }
+ else
+ write_int(0);
+}
+
+static inline void write_string(const char *s)
+{
+ write_data(s, strlen(s)+1);
}
-static inline void write_string(const unsigned char *s)
+static inline void write_string_array(const char **sa, unsigned size)
{
- write_data(s, strlen(s));
- /*int len=strlen(s);
- write_int(len);
- write_bytes(s, len);*/
+ unsigned i;
+ size /= sizeof(const char *);
+ write_int(size);
+ for(i=0; i<size; ++i)
+ write_string(sa[i]);
}
static inline void begin_packet(int func)
{
if(!buffer)
- buffer=(char *)malloc(1024);
+ buffer = (char *)malloc(1024);
if(!iovecs)
- iovecs=(struct iovec *)malloc(16*sizeof(struct iovec));
- write_pos=buffer;
- cur_vec=iovecs;
- cur_vec->iov_base=write_pos;
+ iovecs = (struct iovec *)malloc(16*sizeof(struct iovec));
+ write_pos = buffer;
+ cur_vec = iovecs;
+ cur_vec->iov_base = write_pos;
+ length = 0;
+ write_int(0);
write_short(func);
}
static inline void send_packet()
{
- static int fd=-1;
+ static int fd = -1;
if(fd<0)
{
- const char *var=getenv("GLWRAP_FD");
+ const char *var = getenv("GLWRAP_FD");
if(var)
- fd=strtol(var, NULL, 0);
+ fd = strtol(var, NULL, 0);
else
- fd=2;
+ fd = 2;
}
next_vec();
+ write_pos = buffer;
+ write_int(length);
writev(fd, iovecs, cur_vec-iovecs);
}
-static inline int typesize(GLenum type)
+int in_begin_block = 0;
+GLenum cur_error = GL_NO_ERROR;
+
+static void check_error()
{
- switch(type)
+ GLenum (*orig_glGetError)() = 0;
+ GLenum code;
+
+ if(in_begin_block)
+ return;
+
+ if(!orig_glGetError)
+ orig_glGetError = glsym("glGetError");
+
+ code = orig_glGetError();
+ if(code!=GL_NO_ERROR)
{
- case GL_BYTE: return sizeof(GLbyte);
- case GL_SHORT: return sizeof(GLshort);
- case GL_INT: return sizeof(GLint);
- case GL_UNSIGNED_BYTE: return sizeof(GLubyte);
- case GL_UNSIGNED_SHORT: return sizeof(GLushort);
- case GL_UNSIGNED_INT: return sizeof(GLuint);
- case GL_FLOAT: return sizeof(GLfloat);
- case GL_DOUBLE: return sizeof(GLdouble);
- // Short and byte packed types are broken
- default: return 1;
+ begin_packet(FUNC_GLDERROR);
+ write_int(code);
+ send_packet();
+
+ if(cur_error==GL_NO_ERROR)
+ cur_error = code;
}
}
-static inline int formatsize(GLenum format)
+void APIENTRY glBegin(GLenum mode)
{
- switch(format)
- {
- case GL_COLOR_INDEX: return 1;
- case GL_STENCIL_INDEX: return 1;
- case GL_DEPTH_COMPONENT: return 1;
- case GL_RED: return 1;
- case GL_GREEN: return 1;
- case GL_BLUE: return 1;
- case GL_ALPHA: return 1;
- case GL_RGB: return 3;
- case GL_RGBA: return 4;
- case GL_BGR: return 3;
- case GL_BGRA: return 4;
- case GL_LUMINANCE: return 1;
- case GL_LUMINANCE_ALPHA: return 2;
- default: return 1;
- }
+ static void (*orig)(GLenum);
+ if(!orig)
+ orig = glsym("glBegin");
+ orig(mode);
+
+ begin_packet(FUNC_GLBEGIN);
+ write_int(mode);
+ send_packet();
+
+ in_begin_block = 1;
+}
+
+void APIENTRY glEnd()
+{
+ static void (*orig)();
+ if(!orig)
+ orig = glsym("glEnd");
+ orig();
+
+ begin_packet(FUNC_GLEND);
+ send_packet();
+
+ in_begin_block = 0;
+ check_error();
}
-static inline int paramsize(GLenum pname)
+GLenum APIENTRY glGetError()
{
- switch(pname)
+ GLenum ret = GL_NO_ERROR;
+
+ if(in_begin_block)
{
- // Lighting and material
- case GL_AMBIENT: return 4;
- case GL_DIFFUSE: return 4;
- case GL_AMBIENT_AND_DIFFUSE: return 4;
- case GL_SPECULAR: return 4;
- case GL_EMISSION: return 4;
- case GL_SHININESS: return 1;
- case GL_COLOR_INDEXES: return 3;
- case GL_POSITION: return 4;
- case GL_SPOT_DIRECTION: return 3;
- case GL_SPOT_EXPONENT: return 1;
- case GL_SPOT_CUTOFF: return 1;
- case GL_CONSTANT_ATTENUATION: return 1;
- case GL_LINEAR_ATTENUATION: return 1;
- case GL_QUADRATIC_ATTENUATION: return 1;
- case GL_LIGHT_MODEL_AMBIENT: return 4;
- case GL_LIGHT_MODEL_LOCAL_VIEWER: return 1;
- case GL_LIGHT_MODEL_TWO_SIDE: return 1;
- case GL_LIGHT_MODEL_COLOR_CONTROL: return 1;
-
- // Texture
- case GL_TEXTURE_WRAP_S: return 1;
- case GL_TEXTURE_WRAP_T: return 1;
- case GL_TEXTURE_WRAP_R: return 1;
- case GL_TEXTURE_MIN_FILTER: return 1;
- case GL_TEXTURE_MAG_FILTER: return 1;
- case GL_TEXTURE_BORDER_COLOR: return 4;
- case GL_TEXTURE_MIN_LOD: return 1;
- case GL_TEXTURE_MAX_LOD: return 1;
- case GL_TEXTURE_BASE_LEVEL: return 1;
- case GL_TEXTURE_MAX_LEVEL: return 1;
- case GL_TEXTURE_LOD_BIAS: return 1;
- case GL_DEPTH_TEXTURE_MODE: return 1;
- case GL_TEXTURE_COMPARE_MODE: return 1;
- case GL_TEXTURE_COMPARE_FUNC: return 1;
- case GL_GENERATE_MIPMAP: return 1;
- default: return 1;
+ if(cur_error==GL_NO_ERROR)
+ cur_error = GL_INVALID_OPERATION;
}
+ else
+ {
+ ret = cur_error;
+ cur_error = GL_NO_ERROR;
+ }
+
+ begin_packet(FUNC_GLGETERROR);
+ write_int(ret);
+ send_packet();
+
+ return ret;
}
-static inline int mapsize(GLenum target)
+void (*glXGetProcAddress(const GLubyte *procname))(void)
{
- return 1;
+ void *handle = 0;
+ void (*ret)() = 0;
+
+ if(glsym((const char *)procname))
+ {
+ handle = dlopen(NULL, RTLD_LAZY);
+ ret = dlsym(handle, (const char *)procname);
+ }
+
+ begin_packet(FUNC_GLXGETPROCADDRESS);
+ write_pointer(ret);
+ write_string((const char *)procname);
+ send_packet();
+
+ return ret;
}
+void (*glXGetProcAddressARB(const GLubyte *))(void) __attribute__((alias("glXGetProcAddress")));
+
#include "glwrap.funcs"