From 4aba13fc7690cf79e949d9765b371e85e7530207 Mon Sep 17 00:00:00 2001 From: Mikko Rasa Date: Mon, 14 Jun 2010 13:11:29 +0000 Subject: [PATCH] Send as much of a packet as possible before calling the original function --- source/gldecoder.c | 165 ++++++++++++++++++++++++++------------- source/gldecoder.funcs.t | 23 +++--- source/glwrap.c | 30 ++++++- source/glwrap.funcs.t | 24 ++++-- source/glwrap.h | 1 + 5 files changed, 167 insertions(+), 76 deletions(-) diff --git a/source/gldecoder.c b/source/gldecoder.c index f61e327..cd290aa 100644 --- a/source/gldecoder.c +++ b/source/gldecoder.c @@ -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(lentotal==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; igldError) 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; } diff --git a/source/gldecoder.funcs.t b/source/gldecoder.funcs.t index e02c1e8..545f8b4 100644 --- a/source/gldecoder.funcs.t +++ b/source/gldecoder.funcs.t @@ -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; :} diff --git a/source/glwrap.c b/source/glwrap.c index 52c6552..4c17edf 100644 --- a/source/glwrap.c +++ b/source/glwrap.c @@ -8,7 +8,9 @@ Distributed under the GPL #include #include #include +#include #include +#include #include #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); } diff --git a/source/glwrap.funcs.t b/source/glwrap.funcs.t index eb77b0a..17e711b 100644 --- a/source/glwrap.funcs.t +++ b/source/glwrap.funcs.t @@ -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': diff --git a/source/glwrap.h b/source/glwrap.h index 047f9c4..04d8f37 100644 --- a/source/glwrap.h +++ b/source/glwrap.h @@ -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 -- 2.43.0