X-Git-Url: http://git.tdb.fi/?a=blobdiff_plain;f=source%2Fglwrap.c;h=cd1c328139e784f2a4bea80d90297e86401d4402;hb=a832996c884a0e0acc9a38ba4dd258edb75ec7af;hp=0a22c3c1ce4b6677c0bb66cdb10d559294fbe160;hpb=6475e8951e1901b247f5d1d1dd9fcfc1e77e163a;p=gldbg.git diff --git a/source/glwrap.c b/source/glwrap.c index 0a22c3c..cd1c328 100644 --- a/source/glwrap.c +++ b/source/glwrap.c @@ -1,276 +1,235 @@ -/* $Id$ - -This file is part of gldbg -Copyright © 2009 Mikko Rasa, Mikkosoft Productions -Distributed under the GPL -*/ - #include #include #include +#include #include -#include -#include -#include -#include +#include +#include +#include "arraysize.h" +#include "breakpoint.h" #include "functions.h" +#include "opengl.h" +#include "packet.h" -static inline void *glsym(const char *sym) -{ - static void *libgl = NULL; - if(!libgl) - { - libgl = dlopen("libGL.so", RTLD_NOW); - if(!libgl) - { - fprintf(stderr, "Could not open libGL: %s\n", dlerror()); - abort(); - } - } - - return dlsym(libgl, sym); -} +#define UNUSED __attribute__((unused)) -static char *buffer = 0; -static char *write_pos; -static struct iovec *iovecs = 0; -static struct iovec *cur_vec; -static unsigned length; +static unsigned char breakpoints[N_FUNCS] = { }; +static char break_any = 0; +static char hold = 0; +static char no_break = 0; -static inline void next_vec() +static const char *get_lib_names(void) { - if(write_pos!=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; - } + const char *env = getenv("GLWRAP_LIBS"); + if(env) + return env; + return "libGL.so.1"; } -static inline void write_bytes(const char *ptr, unsigned size) +void *glsym(const char *name) { + static void **gl_libs = NULL; unsigned i; - for(i=0; iiov_base = (void *)data; - cur_vec->iov_len = size; - length += size; - ++cur_vec; - cur_vec->iov_base = write_pos; + const char *var = getenv("GLWRAP_FD"); + if(var) + fd = strtol(var, NULL, 0); + else + { + var = getenv("GLWRAP_FILE"); + if(var) + { + fd = open(var, O_WRONLY|O_CREAT|O_TRUNC, 0644); + if(fd==-1) + { + fprintf(stderr, "Couldn't open dumpfile %s for output: %s", var, strerror(errno)); + abort(); + } + } + else + fd = 2; + } } - else - write_int(0); -} -static inline void write_string(const unsigned char *s) -{ - write_data(s, strlen(s)+1); -} - -static inline void begin_packet(int func) -{ - if(!buffer) - 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; - length = 0; - write_int(0); - write_short(func); + return fd; } -static inline void send_packet() +int get_in_fd(void) { static int fd = -1; + if(fd<0) { - const char *var = getenv("GLWRAP_FD"); + const char *var = getenv("GLWRAP_CTRL_FD"); if(var) fd = strtol(var, NULL, 0); else - fd = 2; + fd = 0; } - next_vec(); - write_pos = buffer; - write_int(length); - writev(fd, iovecs, cur_vec-iovecs); + + return fd; } -static inline int typesize(GLenum type) +static void receive_gldBreak(GlPacket *pkt) { - switch(type) + unsigned short func; + unsigned char flags_set; + unsigned char flags_clr; + + packet_read_short(pkt, (short *)&func); + packet_read_char(pkt, (char *)&flags_set); + packet_read_char(pkt, (char *)&flags_clr); + + if(func) { - 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; + breakpoints[func] &= ~flags_clr; + breakpoints[func] |= flags_set; } + else + break_any = flags_set; } -static inline int formatsize(GLenum format) +static void receive_gldHold(GlPacket *pkt UNUSED) { - 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; - } + hold = 1; } -static inline int paramsize(GLenum pname) +static void receive_gldQueryViewport(GlPacket *pkt UNUSED) { - switch(pname) - { - // 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; - } + int viewport[4]; + + no_break = 1; + glGetIntegerv(GL_VIEWPORT, viewport); + no_break = 0; } -static inline int mapsize(GLenum target) +static void receive_gldReadPixels(GlPacket *pkt) { - return 1; -} + GLint x, y; + GLsizei width, height; + GLenum format, type; + char *data; + + packet_read_int(pkt, &x); + packet_read_int(pkt, &y); + packet_read_int(pkt, &width); + packet_read_int(pkt, &height); + packet_read_int(pkt, (int *)&format); + packet_read_int(pkt, (int *)&type); -GLenum cur_error = GL_NO_ERROR; + data = (char *)malloc(width*height*typesize(type)*formatsize(format)); + no_break = 1; + glReadPixels(x, y, width, height, format, type, data); + no_break = 0; + free(data); +} -static void check_error() +static void receive(void) { - GLenum (*orig_glGetError)() = 0; - GLenum code; - if(!orig_glGetError) - orig_glGetError = glsym("glGetError"); - code = orig_glGetError(); - if(code!=GL_NO_ERROR) + GlPacket *pkt; + + while((pkt = packet_receive(get_in_fd()))) { - begin_packet(FUNC_GLDERROR); - write_int(code); - send_packet(); - if(cur_error==GL_NO_ERROR) - cur_error = code; + unsigned short func; + + packet_read_short(pkt, (short *)&func); + switch(func) + { + case FUNC_GLDBREAK: receive_gldBreak(pkt); break; + case FUNC_GLDHOLD: receive_gldHold(pkt); break; + case FUNC_GLDQUERYVIEWPORT: receive_gldQueryViewport(pkt); break; + case FUNC_GLDREADPIXELS: receive_gldReadPixels(pkt); break; + default:; + } } } -GLenum APIENTRY glGetError() +void tracepoint(unsigned short func, int flag) { - GLenum ret = cur_error; - cur_error = GL_NO_ERROR; - return ret; -} + int breakpoint; -void (*glXGetProcAddress(const GLubyte *procname))(void) -{ - void *handle = dlopen(NULL, RTLD_LAZY); - return dlsym(handle, (const char *)procname); -} + if(no_break) + return; -void (*glXGetProcAddressARB(const GLubyte *))(void) __attribute__((alias("glXGetProcAddress"))); + receive(); -#include "glwrap.funcs" + breakpoint = (breakpoints[func]|break_any)&flag; + if(breakpoint || hold) + { + GlPacket *pkt; + + if(breakpoint) + { + pkt = packet_begin(FUNC_GLDBREAK); + packet_write_short(pkt, func); + packet_write_char(pkt, flag); + packet_send(pkt, get_out_fd()); + } + + break_any = 0; + + while(1) + { + hold = 0; + raise(SIGTRAP); + receive(); + if(!hold) + break; + } + } +}