]> git.tdb.fi Git - gldbg.git/commitdiff
Send as much of a packet as possible before calling the original function
authorMikko Rasa <tdb@tdb.fi>
Mon, 14 Jun 2010 13:11:29 +0000 (13:11 +0000)
committerMikko Rasa <tdb@tdb.fi>
Mon, 14 Jun 2010 13:11:29 +0000 (13:11 +0000)
source/gldecoder.c
source/gldecoder.funcs.t
source/glwrap.c
source/glwrap.funcs.t
source/glwrap.h

index f61e327aa92a9217a589ebb8f7174680f8125a7c..cd290aa513b3f1e69ea21009b95513bdff46a5ac 100644 (file)
@@ -11,10 +11,17 @@ Distributed under the GPL
 #include "gldecoder.h"
 #include "tmpalloc.h"
 
-static unsigned read_short(short *, const char *);
-static unsigned read_int(int *, const char *);
-static int decode_func(GlDecoder *, unsigned short, const char *);
-static int decode_gldfunc(GlDecoder *, unsigned short, const char *);
+typedef struct sGlPacket
+{
+       const char *ptr;
+       unsigned chunk;
+       unsigned total;
+} GlPacket;
+
+static void read_short(short *, GlPacket *);
+static void read_int(int *, GlPacket *);
+static int decode_func(GlDecoder *, unsigned short, GlPacket *);
+static int decode_gldfunc(GlDecoder *, unsigned short, GlPacket *);
 
 GlDecoder *gldecoder_new(void *user_data, void (*destroy)(void *))
 {
@@ -37,127 +44,173 @@ void gldecoder_delete(GlDecoder *dec)
 
 int gldecoder_decode(GlDecoder *dec, const char *data, unsigned len)
 {
-       unsigned pos = 0;
-       unsigned pktlen;
        unsigned short func;
-       int ret;
+       GlPacket packet;
 
        if(len<sizeof(int)+sizeof(short))
                return -1;
-       pos += read_int((int *)&pktlen, data);
-       if(len<pktlen)
+
+       packet.ptr = data;
+       packet.chunk = len;
+       read_int((int *)&packet.chunk, &packet);
+
+       if(packet.chunk&0x80000000)
+       {
+               packet.chunk &= 0x7FFFFFFF;
+               packet.total = packet.chunk;
+
+               while(1)
+               {
+                       if(len<packet.total+sizeof(int))
+                               return -1;
+
+                       GlPacket p = { packet.ptr+packet.total, len-packet.total, 0 };
+                       unsigned chunk;
+                       read_int((int *)&chunk, &p);
+                       packet.total += chunk&0x7FFFFFFF;
+                       if(!(chunk&0x80000000))
+                               break;
+               }
+       }
+       else
+               packet.total = packet.chunk;
+
+       if(len<packet.total)
                return -1;
-       pos += read_short((short *)&func, data+pos);
+
+       read_short((short *)&func, &packet);
+
        if(dec)
        {
+               int ret = 0;
+
                if(func&0x8000)
-                       ret = decode_gldfunc(dec, func, data+pos);
+                       ret = decode_gldfunc(dec, func, &packet);
                else
-                       ret = decode_func(dec, func, data+pos);
+                       ret = decode_func(dec, func, &packet);
                if(ret<0)
                        return -1;
        }
-       return pktlen;
+
+       return packet.ptr+packet.total-data;
+}
+
+static void next_chunk(GlPacket *pkt)
+{
+       if(pkt->total==0)
+               return;
+       pkt->chunk = pkt->total;
+       read_int((int *)&pkt->chunk, pkt);
+       pkt->chunk &= 0x7FFFFFFF;
+}
+
+static void read_generic(void *v, unsigned size, int byteswap, GlPacket *pkt)
+{
+       if(pkt->chunk==0)
+               next_chunk(pkt);
+
+       if(pkt->chunk>=size)
+       {
+               // TODO: Actually implement byteswap if needed
+               (void)byteswap;
+               memcpy(v, pkt->ptr, size);
+               pkt->ptr += size;
+               pkt->chunk -= size;
+               pkt->total -= size;
+       }
+       else
+       {
+               memset(v, 0, size);
+               pkt->total -= pkt->chunk;
+               pkt->chunk = 0;
+       }
 }
 
-static unsigned read_char(char *v, const char *data)
+static void read_char(char *v, GlPacket *pkt)
 {
-       *v = *data;
-       return 1;
+       read_generic(v, 1, 0, pkt);
 }
 
-static unsigned read_short(short *v, const char *data)
+static void read_short(short *v, GlPacket *pkt)
 {
-       *v = *(short *)data;
-       return sizeof(short);
+       read_generic(v, sizeof(short), 1, pkt);
 }
 
-static unsigned read_int(int *v, const char *data)
+static void read_int(int *v, GlPacket *pkt)
 {
-       *v = *(int *)data;
-       return sizeof(int);
+       read_generic(v, sizeof(int), 1, pkt);
 }
 
-static unsigned read_long(long *v, const char *data)
+static void read_long(long *v, GlPacket *pkt)
 {
-       *v = *(long *)data;
-       return sizeof(long);
+       read_generic(v, sizeof(long), 1, pkt);
 }
 
-static unsigned read_long_long(long long *v, const char *data)
+static void read_long_long(long long *v, GlPacket *pkt)
 {
-       *v = *(long long *)data;
-       return sizeof(long long);
+       read_generic(v, sizeof(long long), 1, pkt);
 }
 
-static unsigned read_float(float *v, const char *data)
+static void read_float(float *v, GlPacket *pkt)
 {
-       *v = *(float *)data;
-       return sizeof(float);
+       read_generic(v, sizeof(float), 1, pkt);
 }
 
-static unsigned read_double(double *v, const char *data)
+static void read_double(double *v, GlPacket *pkt)
 {
-       *v = *(double *)data;
-       return sizeof(double);
+       read_generic(v, sizeof(double), 1, pkt);
 }
 
-typedef void *pointer;
+typedef const void *pointer;
 
-static unsigned read_pointer(pointer *v, const char *data)
+static void read_pointer(pointer *v, GlPacket *pkt)
 {
-       *v = *(void **)data;
-       return sizeof(void *);
+       read_generic(v, sizeof(pointer), 1, pkt);
 }
 
-static unsigned read_data(const void **v, const char *data)
+static void read_data(pointer *v, GlPacket *pkt)
 {
        int vlen;
-       unsigned pos = 0;
-       pos += read_int(&vlen, data);
+       read_int(&vlen, pkt);
        if(vlen)
-               *v = data+pos;
+               *v = pkt->ptr;
        else
                *v = NULL;
-       return pos+vlen;
 }
 
 typedef const char *string;
 
-static unsigned read_string(string *v, const char *data)
+static void read_string(string *v, GlPacket *pkt)
 {
-       return read_data((const void **)v, data);
+       read_data((pointer *)v, pkt);
 }
 
-static unsigned read_string_array(string **v, const char *data)
+static void read_string_array(string **v, GlPacket *pkt)
 {
        int count;
-       unsigned pos = 0;
        int i;
-       pos += read_int(&count, data);
+       read_int(&count, pkt);
        *v = (string *)tmpalloc(count*sizeof(string));
        for(i=0; i<count; ++i)
-               pos += read_string(*v+i, data+pos);
-       return pos;
+               read_string(*v+i, pkt);
 }
 
 #include "gensrc/gldecoder.funcs"
 
-static int decode_gldError(GlDecoder *dec, const char *data)
+static void decode_gldError(GlDecoder *dec, GlPacket *pkt)
 {
-       unsigned pos = 0;
        GLenum code;
-       pos += read_int((int *)&code, data);
+       read_int((int *)&code, pkt);
        if(dec->gldError)
                dec->gldError(dec->user_data, code);
-       return pos;
 }
 
-static int decode_gldfunc(GlDecoder *dec, unsigned short func, const char *data)
+static int decode_gldfunc(GlDecoder *dec, unsigned short func, GlPacket *pkt)
 {
        switch(func)
        {
-       case FUNC_GLDERROR: return decode_gldError(dec, data);
+       case FUNC_GLDERROR: decode_gldError(dec, pkt); break;
        default: return -1;
        }
+       return 0;
 }
index e02c1e815277fca0833a47489ff0aff3e5fe0e74..545f8b408522a652c5c72cddd3383149f5c34d9d 100644 (file)
@@ -1,22 +1,22 @@
 # $Id$
-wl('static unsigned decode_%s(GlDecoder *dec, const char *data __attribute__((unused)))', func.name)
+:#define UNUSED __attribute__((unused))
+wl('static unsigned decode_%s(GlDecoder *dec, GlPacket *pkt UNUSED)', func.name)
 wl('{')
-wl('   unsigned pos = 0;')
 if ret.ctype!="void":
        wl('    %s ret;', ret.ctype)
 for p in params:
        wl('    %s p_%s;', p.ctype, p.name)
-if ret.ctype!="void":
-       wl('    pos += read_%s((%s *)&ret, data+pos);', ret.io[0].replace(' ', '_'), ret.io[0])
 for p in params:
        if p.kind=="value":
-               wl('    pos += read_%s((%s *)&p_%s, data+pos);', p.io[0].replace(' ', '_'), p.io[0], p.name)
+               wl('    read_%s((%s *)&p_%s, pkt);', p.io[0].replace(' ', '_'), p.io[0], p.name)
        elif p.kind=="array" and p.io and p.io[0]=="string":
-               wl('  pos += read_string_array(&p_%s, data+pos);', p.name)
+               wl('  read_string_array(&p_%s, pkt);', p.name)
        elif p.csize:
-               wl('    pos += read_data((const void **)&p_%s, data+pos);', p.name)
+               wl('    read_data((pointer *)&p_%s, pkt);', p.name)
        else:
-               wl('    pos += read_pointer((void **)&p_%s, data+pos);', p.name)
+               wl('    read_pointer((pointer *)&p_%s, pkt);', p.name)
+if ret.ctype!="void":
+       wl('    read_%s((%s *)&ret, pkt);', ret.io[0].replace(' ', '_'), ret.io[0])
 wl('   if(dec->%s)', func.name)
 w('            dec->%s(dec->user_data', func.name)
 if ret.ctype!="void":
@@ -24,13 +24,14 @@ if ret.ctype!="void":
 for p in params:
        w(', p_%s', p.name)
 wl(');')
-wl('   return pos;')
+wl('   return 0;')
 wl('}')
-:static int decode_func(GlDecoder *dec, unsigned short func, const char *data)
+:static int decode_func(GlDecoder *dec, unsigned short func, GlPacket *pkt)
 :{
 :      switch(func)
 :      {
-wl('   case FUNC_%s: return decode_%s(dec, data);', func.name.upper(), func.name)
+wl('   case FUNC_%s: decode_%s(dec, pkt); break;', func.name.upper(), func.name)
 :      default: return -1;
 :      }
+:      return 0;
 :}
index 52c6552e1f5c0c007939e62f07a31e233ba8e587..4c17edfca772755f16a983253e96d37cf3ef0de6 100644 (file)
@@ -8,7 +8,9 @@ Distributed under the GPL
 #include <stdlib.h>
 #include <stdio.h>
 #include <string.h>
+#include <errno.h>
 #include <dlfcn.h>
+#include <fcntl.h>
 #include <sys/uio.h>
 
 #define INTERNAL __attribute__((visibility("internal")))
@@ -175,17 +177,20 @@ INTERNAL inline void begin_packet(int func)
                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);
 }
 
-INTERNAL inline void send_packet(void)
+INTERNAL inline int get_out_fd(void)
 {
        static int fd = -1;
+
        if(fd<0)
        {
                const char *var = getenv("GLWRAP_FD");
@@ -194,8 +199,29 @@ INTERNAL inline void send_packet(void)
                else
                        fd = 2;
        }
+
+       return fd;
+}
+
+INTERNAL inline void send_partial_packet(void)
+{
+       next_vec();
+       write_pos = buffer;
+       write_int(length|0x80000000);
+       writev(get_out_fd(), iovecs, cur_vec-iovecs);
+
+       write_pos = buffer;
+       cur_vec = iovecs;
+       cur_vec->iov_base = write_pos;
+       length = 0;
+
+       write_int(0);
+}
+
+INTERNAL inline void send_packet(void)
+{
        next_vec();
        write_pos = buffer;
        write_int(length);
-       writev(fd, iovecs, cur_vec-iovecs);
+       writev(get_out_fd(), iovecs, cur_vec-iovecs);
 }
index eb77b0a7a3e0e5ce15e19101bffcb18ad73e8928..17e711b870124d46244a37789995d955384dddf4 100644 (file)
@@ -11,23 +11,33 @@ if ret.ctype!='void':
        wl('    %s ret;', ret.ctype)
 wl('   if(!orig)')
 wl('           orig = glsym("%s");', func.name)
-w('    ')
-if ret.ctype!='void':
-       w('ret = ')
-wl('orig(%s);', ", ".join([p.name for p in params]))
 wl('   begin_packet(FUNC_%s);', func.name.upper())
-if ret.ctype!='void':
-       wl('    write_%s(ret);', ret.io[0].replace(' ', '_'))
+head_sent = False
 for p in params:
+       if p.direction=="out" and not head_sent:
+               wl('    send_partial_packet();')
+               w('     ')
+               if ret.ctype!='void':
+                       w('ret = ')
+               wl('orig(%s);', ", ".join([q.name for q in params]))
+               head_sent = True
        if p.kind=="value":
                wl('    write_%s(%s);', p.io[0].replace(' ', '_'), p.name)
        elif p.kind=="array" and p.io and p.io[0]=="string":
-               wl('  write_string_array(%s, %s);', p.name, p.csize)
+               wl('    write_string_array(%s, %s);', p.name, p.csize)
        elif p.csize:
                wl('    write_data(%s, %s);', p.name, p.csize)
        else:
                wl('    write_pointer(%s);', p.name)
+if ret.ctype!='void':
+       if not head_sent:
+               wl('    send_partial_packet();')
+               wl('    ret = orig(%s);', ", ".join([p.name for p in params]))
+               head_sent = True
+       wl('    write_%s(ret);', ret.io[0].replace(' ', '_'))
 wl('   send_packet();')
+if not head_sent:
+       wl('    orig(%s);', ", ".join([p.name for p in params]))
 if not func.name.startswith("glX"):
        wl('    check_error();')
 if ret.ctype!='void':
index 047f9c427d16939074f3cef038e4f0b35bb3a845..04d8f37ab2b193719aea76f0a83013b2d284c19a 100644 (file)
@@ -21,6 +21,7 @@ void write_data(const void *, unsigned);
 void write_string(const char *);
 void write_string_array(const char **, unsigned);
 void begin_packet(int);
+void send_partial_packet(void);
 void send_packet(void);
 
 #endif