]> git.tdb.fi Git - gldbg.git/blobdiff - source/glwrap.c
Query implementation limits on process startup
[gldbg.git] / source / glwrap.c
index a33021a70a89f70c988ea0694ff9f7910ff9e702..ee679577011931b7264fda5e011fecda59077d35 100644 (file)
-/* $Id$
-
-This file is part of gldbg
-Copyright © 2009  Mikko Rasa, Mikkosoft Productions
-Distributed under the GPL
-*/
-
 #include <stdlib.h>
 #include <stdio.h>
 #include <string.h>
+#include <errno.h>
 #include <dlfcn.h>
-#include <sys/uio.h>
-#include <GL/gl.h>
+#include <fcntl.h>
+#include <signal.h>
+#include "arraysize.h"
+#include "breakpoint.h"
 #include "functions.h"
+#include "opengl.h"
+#include "packet.h"
+
+#define UNUSED __attribute__((unused))
 
-static inline void *glsym(const char *sym)
+static unsigned char breakpoints[N_FUNCS] = { };
+static char break_any = 0;
+static char hold = 0;
+static char no_break = 0;
+
+static const char *get_lib_names(void)
 {
-       static void *libgl=NULL;
-       if(!libgl)
+       const char *env = getenv("GLWRAP_LIBS");
+       if(env)
+               return env;
+       return "libGL.so.1";
+}
+
+void *glsym(const char *name)
+{
+       static void **gl_libs = NULL;
+       unsigned i;
+
+       if(!gl_libs)
        {
-               libgl=dlopen("libGL.so", RTLD_NOW);
-               if(!libgl)
+               char *lib_names = strdup(get_lib_names());
+               unsigned n_libs = 1;
+               unsigned j;
+
+               for(i=0; lib_names[i]; ++i)
+                       if(lib_names[i]==':')
+                               ++n_libs;
+
+               gl_libs = (void **)malloc((n_libs+1)*sizeof(void *));
+               i = 0;
+               n_libs = 0;
+               for(j=0;; ++j)
                {
-                       fprintf(stderr, "Could not open libGL: %s\n", dlerror());
-                       abort();
+                       if(lib_names[j]==':' || lib_names[j]==0)
+                       {
+                               int at_end = (lib_names[j]==0);
+                               lib_names[j] = 0;
+
+                               gl_libs[n_libs] = dlopen(lib_names+i, RTLD_NOW);
+                               if(!gl_libs[n_libs])
+                               {
+                                       fprintf(stderr, "Could not open %s: %s\n", lib_names+i, dlerror());
+                                       abort();
+                               }
+
+                               i = j+1;
+                               ++n_libs;
+
+                               if(at_end)
+                                       break;
+                       }
                }
+
+               gl_libs[n_libs] = 0;
+               free(lib_names);
        }
 
-       return dlsym(libgl, sym);
-}
+       for(i=0; gl_libs[i]; ++i)
+       {
+               void *sym = dlsym(gl_libs[i], name);
+               if(sym)
+                       return sym;
+       }
 
-char *buffer=0;
-char *write_pos;
-struct iovec *iovecs=0;
-struct iovec *cur_vec;
+       return NULL;
+}
 
-static inline void next_vec()
+int get_out_fd(void)
 {
-       if(write_pos!=cur_vec->iov_base)
+       static int fd = -1;
+
+       if(fd<0)
        {
-               cur_vec->iov_len=write_pos-(char *)cur_vec->iov_base;
-               ++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;
+               }
        }
-}
 
-static inline void write_bytes(const char *ptr, unsigned size)
-{
-       unsigned i;
-       for(i=0; i<size; ++i)
-               *write_pos++=*ptr++;
+       return fd;
 }
 
-static inline void write_char(char v)
+int get_in_fd(void)
 {
-       *write_pos++=v;
-}
+       static int fd = -1;
 
-static inline void write_short(short v)
-{
-       write_bytes((char *)&v, sizeof(short));
-}
+       if(fd<0)
+       {
+               const char *var = getenv("GLWRAP_CTRL_FD");
+               if(var)
+                       fd = strtol(var, NULL, 0);
+               else
+                       fd = 0;
+       }
 
-static inline void write_int(int v)
-{
-       write_bytes((char *)&v, sizeof(int));
+       return fd;
 }
 
-static inline void write_long(long v)
+static void receive_gldBreak(GlPacket *pkt)
 {
-       write_bytes((char *)&v, sizeof(long));
-}
+       unsigned short func;
+       unsigned char flags_set;
+       unsigned char flags_clr;
 
-static inline void write_ulong(unsigned long v)
-{
-       write_bytes((char *)&v, sizeof(unsigned long));
-}
+       packet_read_short(pkt, (short *)&func);
+       packet_read_char(pkt, (char *)&flags_set);
+       packet_read_char(pkt, (char *)&flags_clr);
 
-static inline void write_longlong(long long v)
-{
-       write_bytes((char *)&v, sizeof(long long));
+       if(func)
+       {
+               breakpoints[func] &= ~flags_clr;
+               breakpoints[func] |= flags_set;
+       }
+       else
+               break_any = flags_set;
 }
 
-static inline void write_float(float v)
+static void receive_gldHold(GlPacket *pkt UNUSED)
 {
-       write_bytes((char *)&v, sizeof(float));
+       hold = 1;
 }
 
-static inline void write_double(float v)
+static void receive_gldQueryViewport(GlPacket *pkt UNUSED)
 {
-       write_bytes((char *)&v, sizeof(double));
-}
+       int viewport[4];
 
-static inline void write_pointer(const void *p)
-{
-       write_bytes((char *)&p, sizeof(void *));
+       no_break = 1;
+       glGetIntegerv(GL_VIEWPORT, viewport);
+       no_break = 0;
 }
 
-static inline void write_data(const void *data, unsigned size)
+static void receive_gldReadPixels(GlPacket *pkt)
 {
-       write_int(size);
-       next_vec();
-       cur_vec->iov_base=(void *)data;
-       cur_vec->iov_len=size;
-       ++cur_vec;
-       cur_vec->iov_base=write_pos;
-}
+       GLint x, y;
+       GLsizei width, height;
+       GLenum format, type;
+       char *data;
 
-static inline void write_string(const unsigned char *s)
-{
-       write_data(s, strlen(s));
-       /*int len=strlen(s);
-       write_int(len);
-       write_bytes(s, len);*/
-}
+       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);
 
-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;
-       write_short(func);
+       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 inline void send_packet()
+static void receive_gldQueryLimits(GlPacket *pkt UNUSED)
 {
-       static int fd=-1;
-       if(fd<0)
-       {
-               const char *var=getenv("GLWRAP_FD");
-               if(var)
-                       fd=strtol(var, NULL, 0);
-               else
-                       fd=2;
-       }
-       next_vec();
-       writev(fd, iovecs, cur_vec-iovecs);
-}
+       int value;
 
-static inline int typesize(GLenum type)
-{
-       switch(type)
-       {
-       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;
-       }
+       no_break = 1;
+       value = 0;
+       glGetIntegerv(GL_MAX_TEXTURE_UNITS, &value);
+       value = 0;
+       glGetIntegerv(GL_MAX_VERTEX_ATTRIBS, &value);
+       value = 0;
+       glGetIntegerv(GL_MAX_UNIFORM_BUFFER_BINDINGS, &value);
+       no_break = 0;
 }
 
-static inline int formatsize(GLenum format)
+static void receive(void)
 {
-       switch(format)
+       GlPacket *pkt;
+
+       while((pkt = packet_receive(get_in_fd())))
        {
-       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;
+               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;
+               case FUNC_GLDQUERYLIMITS: receive_gldQueryLimits(pkt); break;
+               default:;
+               }
        }
 }
 
-static inline int paramsize(GLenum pname)
+void tracepoint(unsigned short func, int flag)
 {
-       switch(pname)
+       int breakpoint;
+
+       if(no_break)
+               return;
+
+       receive();
+
+       breakpoint = (breakpoints[func]|break_any)&flag;
+       if(breakpoint || hold)
        {
-       // 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;
-       }
-}
+               GlPacket *pkt;
 
-static inline int mapsize(GLenum target)
-{
-       return 1;
-}
+               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;
 
-#include "glwrap.funcs"
+               while(1)
+               {
+                       hold = 0;
+                       raise(SIGTRAP);
+                       receive();
+                       if(!hold)
+                               break;
+               }
+       }
+}