#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 *))
{
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;
}
# $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":
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;
:}
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':