From 14c21bc57f0772c50850c4a91c0668cd4e6e45b6 Mon Sep 17 00:00:00 2001 From: =?utf8?q?Jos=C3=A9=20Fonseca?= Date: Sun, 20 Feb 2011 23:32:22 +0000 Subject: [PATCH] Basic DrawArrays support. --- glretrace.py | 36 ++++++----- glsize.hpp | 35 ++++++++--- gltrace.py | 188 ++++++++++++++++++++++++++++++++++++++++++-------------- glxtrace.py | 29 ++++++--- trace.py | 48 +++++++-------- trace_model.cpp | 5 ++ trace_model.hpp | 3 +- wgltrace.py | 2 +- 8 files changed, 238 insertions(+), 108 deletions(-) diff --git a/glretrace.py b/glretrace.py index 451c938..40ac1cd 100644 --- a/glretrace.py +++ b/glretrace.py @@ -68,8 +68,7 @@ class GlRetracer(Retracer): ]) def call_function(self, function): - if (function.name in self.draw_array_function_names or - function.name in self.draw_elements_function_names): + if function.name in self.draw_elements_function_names: print ' GLint __array_buffer = 0;' print ' glGetIntegerv(GL_ARRAY_BUFFER_BINDING, &__array_buffer);' print ' if (!__array_buffer) {' @@ -106,31 +105,34 @@ class GlRetracer(Retracer): pointer_function_names = set([ "glColorPointer", - "glColorPointerEXT", + #"glColorPointerEXT", "glEdgeFlagPointer", - "glEdgeFlagPointerEXT", + #"glEdgeFlagPointerEXT", "glFogCoordPointer", - "glFogCoordPointerEXT", + #"glFogCoordPointerEXT", "glIndexPointer", - "glIndexPointerEXT", - "glMatrixIndexPointerARB", + #"glIndexPointerEXT", + #"glMatrixIndexPointerARB", "glNormalPointer", - "glNormalPointerEXT", + #"glNormalPointerEXT", "glSecondaryColorPointer", - "glSecondaryColorPointerEXT", + #"glSecondaryColorPointerEXT", "glTexCoordPointer", - "glTexCoordPointerEXT", - "glVertexAttribLPointer", - "glVertexAttribPointer", - "glVertexAttribPointerARB", - "glVertexAttribPointerNV", + #"glTexCoordPointerEXT", + #"glVertexAttribLPointer", + #"glVertexAttribPointer", + #"glVertexAttribPointerARB", + #"glVertexAttribPointerNV", "glVertexPointer", - "glVertexPointerEXT", + #"glVertexPointerEXT", ]) def extract_arg(self, function, arg, arg_type, lvalue, rvalue): - if (function.name in self.pointer_function_names and arg.name == 'pointer' or - function.name in self.draw_elements_function_names and arg.name == 'indices'): + if function.name in self.pointer_function_names and arg.name == 'pointer': + print ' %s = dynamic_cast(&%s);' % (lvalue, rvalue) + return + + if function.name in self.draw_elements_function_names and arg.name == 'indices': print ' if (dynamic_cast(&%s)) {' % rvalue print ' %s = 0;' % (lvalue) print ' } else {' diff --git a/glsize.hpp b/glsize.hpp index ead293b..edcd78a 100644 --- a/glsize.hpp +++ b/glsize.hpp @@ -44,35 +44,52 @@ static inline size_t -__glCallLists_size(GLsizei n, GLenum type) +__gl_type_size(GLenum type) { - size_t bytes; - switch(type) { + switch (type) { + case GL_BOOL: case GL_BYTE: case GL_UNSIGNED_BYTE: - bytes = 1; + return 1; break; case GL_SHORT: case GL_UNSIGNED_SHORT: case GL_2_BYTES: case GL_HALF_FLOAT: - bytes = 2; + return 2; break; case GL_3_BYTES: - bytes = 3; + return 3; break; case GL_INT: case GL_UNSIGNED_INT: case GL_FLOAT: case GL_4_BYTES: - bytes = 4; + return 4; + break; + case GL_DOUBLE: + return 8; break; default: OS::DebugMessage("warning: %s: unknown GLenum 0x%04X\n", __FUNCTION__, type); - bytes = 0; + return 0; + } +} + +static inline size_t +__glArrayPointer_size(GLint size, GLenum type, GLsizei stride, GLsizei maxIndex) +{ + GLsizei elementSize = size*__gl_type_size(type); + if (!stride) { + stride = elementSize; } + return stride*maxIndex + elementSize; +} - return n*bytes; +static inline size_t +__glCallLists_size(GLsizei n, GLenum type) +{ + return n*__gl_type_size(type); } static inline size_t diff --git a/gltrace.py b/gltrace.py index 9a7c2f2..3e3a2be 100644 --- a/gltrace.py +++ b/gltrace.py @@ -33,24 +33,43 @@ from trace import Tracer, dump_instance class GlTracer(Tracer): + def header(self, api): + Tracer.header(self, api) + self.state_tracker_decl(api) + + def footer(self, api): + Tracer.footer(self, api) + self.state_tracker_impl(api) + + array_names = { + "VERTEX": "glVertexPointer", + "NORMAL": "glNormalPointer", + "COLOR": "glColorPointer", + "INDEX": "glIndexPointer", + "TEX_COORD": "glTexCoordPointer", + "EDGE_FLAG": "glEdgeFlagPointer", + "FOG_COORD": "glFogCoordPointer", + "SECONDARY_COLOR": "glSecondaryColorPointer", + } + pointer_function_names = { - "glVertexPointer": "VertexPointer", - "glVertexPointerEXT": "VertexPointer", - "glNormalPointer": "NormalPointer", - "glNormalPointerEXT": "NormalPointer", - "glColorPointer": "ColorPointer", - "glColorPointerEXT": "ColorPointer", - "glIndexPointer": "IndexPointer", - "glIndexPointerEXT": "IndexPointer", - "glTexCoordPointer": "TexCoordPointer", - "glTexCoordPointerEXT": "TexCoordPointer", - "glEdgeFlagPointer": "EdgeFlagPointer", - "glEdgeFlagPointerEXT": "EdgeFlagPointer", - "glFogCoordPointer": "FogCoordPointer", - "glFogCoordPointerEXT": "FogCoordPointer", - "glSecondaryColorPointer": "SecondaryColorPointer", - "glSecondaryColorPointerEXT": "SecondaryColorPointer", - "glInterleavedArrays": "InterleavedArrays", + "glVertexPointer": "VERTEX", + "glNormalPointer": "NORMAL", + "glColorPointer": "COLOR", + "glIndexPointer": "INDEX", + "glTexCoordPointer": "TEX_COORD", + "glEdgeFlagPointer": "EDGE_FLAG", + "glFogCoordPointer": "FOG_COORD", + "glSecondaryColorPointer": "SECONDARY_COLOR", + #"glInterleavedArrays": ("InterleavedArrays", None) + #"glVertexPointerEXT": "VERTEX", + #"glNormalPointerEXT": "NORMAL", + #"glColorPointerEXT": "COLOR", + #"glIndexPointerEXT": "INDEX", + #"glTexCoordPointerEXT": "TEX_COORD", + #"glEdgeFlagPointerEXT": "EDGE_FLAG", + #"glFogCoordPointerEXT": "FOG_COORD", + #"glSecondaryColorPointerEXT": "SECONDARY_COLOR", #"glVertexAttribPointer": "VertexAttribPointer", #"glVertexAttribPointerARB": "VertexAttribPointer", @@ -60,60 +79,139 @@ class GlTracer(Tracer): #"glMatrixIndexPointerARB": "MatrixIndexPointer", } - def header(self, api): - Tracer.header(self, api) - self.state_tracker_decl(api) - - def footer(self, api): - Tracer.footer(self, api) - self.state_tracker_impl(api) + bind_buffer_enums = [ + 'ARRAY_BUFFER', + 'ELEMENT_ARRAY_BUFFER', + 'PIXEL_PACK_BUFFER', + 'PIXEL_UNPACK_BUFFER', + ] + + client_state_enums = [ + 'COLOR_ARRAY', + 'EDGE_FLAG_ARRAY', + 'FOG_COORD_ARRAY', + 'INDEX_ARRAY', + 'NORMAL_ARRAY', + 'SECONDARY_COLOR_ARRAY', + 'TEXTURE_COORD_ARRAY', + 'VERTEX_ARRAY', + ] def state_tracker_decl(self, api): # A simple state tracker to track the pointer values - atoms = list(set(self.pointer_function_names.itervalues())) - atoms.sort() - # define the NEW_XXXX dirty flags - for i in range(len(atoms)): - atom = atoms[i] - dirtyflag = "NEW_%s" % atom.upper() - print '#define %s 0x%x' % (dirtyflag, 1 << i) + value = 1 + for array_name in self.array_names.iterkeys(): + dirtyflag = "NEW_%s" % array_name.upper() + print '#define %s 0x%x' % (dirtyflag, value) + value <<= 1 print # declare the state structure print 'struct {' - for atom in atoms: - function = api.get_function_by_name('gl%s' % atom) + for enum in self.bind_buffer_enums: + print ' GLuint %s;' % (enum.lower(),) + for enum in self.client_state_enums: + print ' GLboolean %s;' % (enum.lower(),) + for array_name, function_name in self.array_names.iteritems(): + function = api.get_function_by_name(function_name) print ' struct {' for arg in function.args: print ' %s %s;' % (arg.type, arg.name) - print ' } %s;' % atom + print ' } %s;' % array_name.lower() print ' unsigned dirty;' print '} __state;' print + print 'static void __state_update(GLsizei maxIndex);' + print + + def trace_function_impl_body(self, function): + # Track bound VBOs + if function.name in ('glBindBuffer', 'glBindBufferARB'): + print ' switch(%s) {' % function.args[0].name + for enum in self.bind_buffer_enums: + print ' case GL_%s:' % enum + print ' __state.%s = %s;' % (enum.lower(), function.args[1].name) + print ' break;' + print ' }' + + # Track enabled arrays + if function.name == 'glEnableClientState': + print ' switch(%s) {' % function.args[0].name + for enum in self.client_state_enums: + print ' case GL_%s:' % enum + print ' __state.%s = GL_TRUE;' % (enum.lower(),) + print ' break;' + print ' }' + if function.name == 'glDisableClientState': + print ' switch(%s) {' % function.args[0].name + for enum in self.client_state_enums: + print ' case GL_%s:' % enum + print ' __state.%s = GL_FALSE;' % (enum.lower(),) + print ' break;' + print ' }' + + # Track array pointers + if function.name in self.pointer_function_names: + array_name = self.pointer_function_names[function.name] + dirtyflag = "NEW_%s" % array_name.upper() + for arg in function.args: + assert not arg.output + print ' __state.%s.%s = %s;' % (array_name.lower(), arg.name, arg.name) + print ' __state.dirty |= %s; ' % dirtyflag + + # Defer tracing + self.dispatch_function(function) + return + + if function.name == 'glDrawArrays': + print ' __state_update(first + count - 1);' + + Tracer.trace_function_impl_body(self, function) def state_tracker_impl(self, api): # A simple state tracker to track the pointer values - atoms = list(set(self.pointer_function_names.itervalues())) - atoms.sort() - # update the state - print 'void __state_update(GLsizei )' + print 'static void __state_update(GLsizei maxIndex)' print '{' print ' GLint __array_buffer = 0;' - print ' glGetIntegerv(GL_ARRAY_BUFFER_BINDING, &__array_buffer);' - for atom in atoms: - function = api.get_function_by_name('gl%s' % atom) - dirtyflag = "NEW_%s" % atom.upper() - print ' if (__state.dirty & %s) {' % dirtyflag + print ' __glGetIntegerv(GL_ARRAY_BUFFER_BINDING, &__array_buffer);' + for array_name, function_name in self.array_names.iteritems(): + function = api.get_function_by_name(function_name) + dirtyflag = "NEW_%s" % array_name.upper() + if array_name == 'TEX_COORD': + enableflag = 'TEXTURE_COORD_ARRAY'.lower() + else: + enableflag = '%s_array' % array_name.lower() + print ' if (__state.%s && (__state.dirty & %s)) {' % (enableflag, dirtyflag) print ' unsigned __call = Trace::BeginEnter(__%s_sig);' % (function.name,) for arg in function.args: assert not arg.output + value = '__state.%s.%s' % (array_name.lower(), arg.name) print ' Trace::BeginArg(%u);' % (arg.index,) - dump_instance(arg.type, '__state.%s.%s' % (atom, arg.name)) - print ' Trace::EndArg();' + if arg.name != 'pointer': + dump_instance(arg.type, value) + else: + print ' if (__state.array_buffer) {' + print ' Trace::LiteralOpaque((const void *)%s);' % value + print ' __state.dirty &= ~%s;' % dirtyflag + print ' } else {' + if array_name in ('INDEX', 'EDGE_FLAG', 'FOG_COORD'): + size = '1' + elif array_name == 'NORMAL': + size = '3' + else: + size = '__state.%s.size' % array_name.lower() + if array_name == 'EDGE_FLAG': + type = 'GL_BOOL' + else: + type = '__state.%s.type' % array_name.lower() + stride = '__state.%s.stride' % array_name.lower() + print ' Trace::LiteralBlob((const void *)%s, __glArrayPointer_size(%s, %s, %s, maxIndex));' % (value, size, type, stride) + print ' }' + print ' Trace::EndArg();' print ' Trace::EndEnter();' print ' Trace::BeginLeave(__call);' print ' Trace::EndLeave();' diff --git a/glxtrace.py b/glxtrace.py index a7d0787..e1a5aa5 100644 --- a/glxtrace.py +++ b/glxtrace.py @@ -40,16 +40,8 @@ class GlxTracer(GlTracer): return '__%s' % (function.name,) def wrap_ret(self, function, instance): - if function.name.startswith("glXGetProcAddress"): - print ' if (%s) {' % instance - for f in glxapi.functions: - ptype = function_pointer_type(f) - pvalue = function_pointer_value(f) - print ' if(!strcmp("%s", (const char *)procName)) {' % f.name - print ' %s = (%s)%s;' % (pvalue, ptype, instance) - print ' %s = (%s)&%s;' % (instance, function.type, f.name); - print ' }' - print ' }' + if function.name in ("glXGetProcAddress", "glXGetProcAddressARB"): + print ' %s = __unwrap_proc_addr(procName, %s);' % (instance, instance) if __name__ == '__main__': @@ -65,10 +57,27 @@ if __name__ == '__main__': print print 'extern "C" {' print + print 'static __GLXextFuncPtr __unwrap_proc_addr(const GLubyte * procName, __GLXextFuncPtr procPtr);' + print + api = API() api.add_api(glxapi) api.add_api(glapi) tracer = GlxTracer() tracer.trace_api(api) + + print 'static __GLXextFuncPtr __unwrap_proc_addr(const GLubyte * procName, __GLXextFuncPtr procPtr) {' + print ' if (!procPtr) {' + print ' return procPtr;' + print ' }' + for f in api.functions: + ptype = function_pointer_type(f) + pvalue = function_pointer_value(f) + print ' if(!strcmp("%s", (const char *)procName)) {' % f.name + print ' %s = (%s)procPtr;' % (pvalue, ptype) + print ' return (__GLXextFuncPtr)&%s;' % (f.name,) + print ' }' + print ' return procPtr;' + print '}' print print '} /* extern "C" */' diff --git a/trace.py b/trace.py index 3502258..95a9807 100644 --- a/trace.py +++ b/trace.py @@ -300,42 +300,37 @@ class Tracer: pass def trace_function_decl(self, function): + # Per-function declarations + if function.args: - print ' static const char * __%s_args[%u] = {%s};' % (function.name, len(function.args), ', '.join(['"%s"' % arg.name for arg in function.args])) + print 'static const char * __%s_args[%u] = {%s};' % (function.name, len(function.args), ', '.join(['"%s"' % arg.name for arg in function.args])) else: - print ' static const char ** __%s_args = NULL;' % (function.name,) - print ' static const Trace::FunctionSig __%s_sig = {%u, "%s", %u, __%s_args};' % (function.name, int(function.id), function.name, len(function.args), function.name) + print 'static const char ** __%s_args = NULL;' % (function.name,) + print 'static const Trace::FunctionSig __%s_sig = {%u, "%s", %u, __%s_args};' % (function.name, int(function.id), function.name, len(function.args), function.name) print - def trace_function_fail(self, function): - if function.fail is not None: - if function.type is stdapi.Void: - assert function.fail == '' - print ' return;' - else: - assert function.fail != '' - print ' return %s;' % function.fail - else: - print ' Trace::Abort();' - def get_dispatch_function(self, function): return '__' + function.name def trace_function_impl(self, function): print 'extern "C" ' + function.prototype() + ' {' - if function.type is stdapi.Void: - result = '' - else: + if function.type is not stdapi.Void: print ' %s __result;' % function.type - result = '__result = ' + self.trace_function_impl_body(function) + if function.type is not stdapi.Void: + self.wrap_ret(function, "__result") + print ' return __result;' + print '}' + print + + def trace_function_impl_body(self, function): print ' unsigned __call = Trace::BeginEnter(__%s_sig);' % (function.name,) for arg in function.args: if not arg.output: self.unwrap_arg(function, arg) self.dump_arg(function, arg) print ' Trace::EndEnter();' - dispatch = self.get_dispatch_function(function) - print ' %s%s(%s);' % (result, dispatch, ', '.join([str(arg.name) for arg in function.args])) + self.dispatch_function(function) print ' Trace::BeginLeave(__call);' for arg in function.args: if arg.output: @@ -344,11 +339,14 @@ class Tracer: if function.type is not stdapi.Void: self.dump_ret(function, "__result") print ' Trace::EndLeave();' - if function.type is not stdapi.Void: - self.wrap_ret(function, "__result") - print ' return __result;' - print '}' - print + + def dispatch_function(self, function): + if function.type is stdapi.Void: + result = '' + else: + result = '__result = ' + dispatch = self.get_dispatch_function(function) + print ' %s%s(%s);' % (result, dispatch, ', '.join([str(arg.name) for arg in function.args])) def dump_arg(self, function, arg): print ' Trace::BeginArg(%u);' % (arg.index,) diff --git a/trace_model.cpp b/trace_model.cpp index 854e79f..07b0c49 100644 --- a/trace_model.cpp +++ b/trace_model.cpp @@ -278,6 +278,11 @@ void * Value::blob(void) const { const Null *null = dynamic_cast(unwrap(this)); if (null) return NULL; + const Pointer *pointer = dynamic_cast(unwrap(this)); + if (pointer) { + assert(pointer->value < 0x100000ULL); + return (void *)pointer->value; + } assert(0); return NULL; } diff --git a/trace_model.hpp b/trace_model.hpp index 57ebcaa..0371681 100644 --- a/trace_model.hpp +++ b/trace_model.hpp @@ -232,7 +232,8 @@ public: } ~Blob() { - delete [] buf; + // FIXME + //delete [] buf; } void visit(Visitor &visitor); diff --git a/wgltrace.py b/wgltrace.py index cef2e1a..e95a31b 100644 --- a/wgltrace.py +++ b/wgltrace.py @@ -46,7 +46,7 @@ class WglTracer(GlTracer): if function.name == "wglGetProcAddress": print ' if (%s) {' % instance - func_dict = dict([(f.name, f) for f in wglapi.functions]) + func_dict = dict([(f.name, f) for f in glapi.functions + wglapi.functions]) def handle_case(function_name): f = func_dict[function_name] -- 2.7.4