From: José Fonseca Date: Tue, 22 Mar 2011 22:15:46 +0000 (+0000) Subject: More complete glDrawArrays and glDrawElements support. X-Git-Url: https://git.cworth.org/git?a=commitdiff_plain;h=9922183f368ba2bfbe3bce18320684212cef8c2e;p=apitrace More complete glDrawArrays and glDrawElements support. --- diff --git a/glretrace.py b/glretrace.py index 40ac1cd..ea8d71f 100644 --- a/glretrace.py +++ b/glretrace.py @@ -61,14 +61,17 @@ class GlRetracer(Retracer): "glDrawRangeElements", "glDrawRangeElementsBaseVertex", "glDrawRangeElementsEXT", - "glMultiDrawElements", - "glMultiDrawElementsBaseVertex", - "glMultiDrawElementsEXT", - "glMultiModeDrawElementsIBM", + #"glMultiDrawElements", + #"glMultiDrawElementsBaseVertex", + #"glMultiDrawElementsEXT", + #"glMultiModeDrawElementsIBM", ]) def call_function(self, function): - if function.name in self.draw_elements_function_names: + print ' if (Trace::Parser::version < 1) {' + + if function.name in self.draw_array_function_names or \ + 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) {' @@ -82,6 +85,8 @@ class GlRetracer(Retracer): self.fail_function(function) print ' }' + print ' }' + if function.name == "glViewport": print ' if (x + width > __window_width) {' print ' __window_width = x + width;' @@ -129,15 +134,11 @@ class GlRetracer(Retracer): def extract_arg(self, function, arg, arg_type, lvalue, rvalue): if function.name in self.pointer_function_names and arg.name == 'pointer': - print ' %s = dynamic_cast(&%s);' % (lvalue, rvalue) + print ' %s = %s.blob();' % (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 {' - print ' %s = (%s)(uintptr_t)(%s);' % (lvalue, arg_type, rvalue) - print ' }' + print ' %s = %s.blob();' % (lvalue, rvalue) return if function.name.startswith('glUniform') and function.args[0].name == arg.name == 'location': diff --git a/glsize.hpp b/glsize.hpp index edcd78a..1f20aba 100644 --- a/glsize.hpp +++ b/glsize.hpp @@ -86,6 +86,61 @@ __glArrayPointer_size(GLint size, GLenum type, GLsizei stride, GLsizei maxIndex) return stride*maxIndex + elementSize; } +#define __glVertexPointer_size(size, type, stride, maxIndex) __glArrayPointer_size(size, type, stride, maxIndex) +#define __glNormalPointer_size(type, stride, maxIndex) __glArrayPointer_size(3, type, stride, maxIndex) +#define __glColorPointer_size(size, type, stride, maxIndex) __glArrayPointer_size(size, type, stride, maxIndex) +#define __glIndexPointer_size(type, stride, maxIndex) __glArrayPointer_size(1, type, stride, maxIndex) +#define __glTexCoordPointer_size(size, type, stride, maxIndex) __glArrayPointer_size(size, type, stride, maxIndex) +#define __glEdgeFlagPointer_size(stride, maxIndex) __glArrayPointer_size(1, GL_BOOL, stride, maxIndex) +#define __glFogCoordPointer_size(type, stride, maxIndex) __glArrayPointer_size(1, type, stride, maxIndex) +#define __glSecondaryColorPointer_size(size, type, stride, maxIndex) __glArrayPointer_size(size, type, stride, maxIndex) + +static inline size_t +__glDrawArrays_maxindex(GLint first, GLsizei count) +{ + return first + count - 1; +} + +static inline size_t +__glDrawElements_maxindex(GLsizei count, GLenum type, const GLvoid *_indices) +{ + size_t maxindex = 0; + unsigned i; + + if (type == GL_UNSIGNED_BYTE) { + const GLubyte *indices = (const GLubyte *)_indices; + for (i = 0; i < count; ++i) { + if (indices[i] > maxindex) { + maxindex = indices[i]; + } + } + } else if (type == GL_UNSIGNED_SHORT) { + const GLushort *indices = (const GLushort *)_indices; + for (i = 0; i < count; ++i) { + if (indices[i] > maxindex) { + maxindex = indices[i]; + } + } + } else if (type == GL_UNSIGNED_INT) { + const GLuint *indices = (const GLuint *)_indices; + for (i = 0; i < count; ++i) { + if (indices[i] > maxindex) { + maxindex = indices[i]; + } + } + } else { + OS::DebugMessage("warning: %s: unknown GLenum 0x%04X\n", __FUNCTION__, type); + } + + return maxindex; +} + +static inline size_t +__glDrawRangeElements_maxindex(GLuint start, GLuint end, GLsizei count, GLenum type, const GLvoid * indices) +{ + return __glDrawElements_maxindex(count, type, indices); +} + static inline size_t __glCallLists_size(GLsizei n, GLenum type) { diff --git a/gltrace.py b/gltrace.py index 3e3a2be..0aa60cd 100644 --- a/gltrace.py +++ b/gltrace.py @@ -27,10 +27,41 @@ """GL tracing generator.""" +import stdapi +import glapi from glxapi import glxapi from trace import Tracer, dump_instance +class TypeGetter(stdapi.Visitor): + '''Determine which glGet*v function that matches the specified type.''' + + def visit_const(self, const): + return self.visit(const.type) + + def visit_alias(self, alias): + if alias.expr == 'GLboolean': + return 'glGetBooleanv', alias.expr + elif alias.expr == 'GLdouble': + return 'glGetDoublev', alias.expr + elif alias.expr == 'GLfloat': + return 'glGetFloatv', alias.expr + elif alias.expr in ('GLint', 'GLsizei'): + return 'glGetIntegerv', 'GLint' + else: + print alias.expr + assert False + + def visit_enum(self, enum): + return 'glGetIntegerv', 'GLint' + + def visit_bitmask(self, bitmask): + return 'glGetIntegerv', 'GLint' + + def visit_opaque(self, pointer): + return 'glGetPointerv', 'GLvoid *' + + class GlTracer(Tracer): def header(self, api): @@ -41,181 +72,129 @@ class GlTracer(Tracer): 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": "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", - #"glVertexAttribPointerNV": "VertexAttribPointer", - #"glVertexAttribLPointer": "VertexAttribLPointer", - - #"glMatrixIndexPointerARB": "MatrixIndexPointer", - } - - 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', + arrays = [ + ("Vertex", "VERTEX"), + ("Normal", "NORMAL"), + ("Color", "COLOR"), + ("Index", "INDEX"), + ("TexCoord", "TEXTURE_COORD"), + ("EdgeFlag", "EDGE_FLAG"), + ("FogCoord", "FOG_COORD"), + ("SecondaryColor", "SECONDARY_COLOR"), ] def state_tracker_decl(self, api): # A simple state tracker to track the pointer values - # define the NEW_XXXX dirty flags - 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 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;' % array_name.lower() - print ' unsigned dirty;' - print '} __state;' - print - print 'static void __state_update(GLsizei maxIndex);' + print 'static void __trace_arrays(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 ' }' + array_pointer_function_names = set(( + "glVertexPointer", + "glNormalPointer", + "glColorPointer", + "glIndexPointer", + "glTexCoordPointer", + "glEdgeFlagPointer", + "glFogCoordPointer", + "glSecondaryColorPointer", + + "glInterleavedArrays", + + #"glVertexPointerEXT", + #"glNormalPointerEXT", + #"glColorPointerEXT", + #"glIndexPointerEXT", + #"glTexCoordPointerEXT", + #"glEdgeFlagPointerEXT", + #"glFogCoordPointerEXT", + #"glSecondaryColorPointerEXT", + + #"glVertexAttribPointer", + #"glVertexAttribPointerARB", + #"glVertexAttribPointerNV", + #"glVertexAttribLPointer", + + #"glMatrixIndexPointerARB", + )) - # 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 + draw_function_names = set(( + 'glDrawArrays', + 'glDrawElements', + 'glDrawRangeElements', + )) - # Defer tracing + def trace_function_impl_body(self, function): + # Defer tracing of array pointers + if function.name in self.array_pointer_function_names: + print ' GLint __array_buffer = 0;' + print ' __glGetIntegerv(GL_ARRAY_BUFFER_BINDING, &__array_buffer);' + print ' if (!__array_buffer) {' self.dispatch_function(function) - return + print ' return;' + print ' }' - if function.name == 'glDrawArrays': - print ' __state_update(first + count - 1);' + if function.name in self.draw_function_names: + arg_names = ', '.join([arg.name for arg in function.args[1:]]) + print ' __trace_arrays(__%s_maxindex(%s));' % (function.name, arg_names) Tracer.trace_function_impl_body(self, function) + def dump_arg_instance(self, function, arg): + if function.name in self.draw_function_names and arg.name == 'indices': + print ' Trace::LiteralBlob((const void *)%s, count*__gl_type_size(type));' % (arg.name) + else: + dump_instance(arg.type, arg.name) + def state_tracker_impl(self, api): # A simple state tracker to track the pointer values # update the state - print 'static void __state_update(GLsizei maxIndex)' + print 'static void __trace_arrays(GLsizei maxindex)' print '{' - print ' GLint __array_buffer = 0;' - print ' __glGetIntegerv(GL_ARRAY_BUFFER_BINDING, &__array_buffer);' - for array_name, function_name in self.array_names.iteritems(): + for camelcase_name, uppercase_name in self.arrays: + function_name = 'gl%sPointer' % camelcase_name + enable_name = 'GL_%s_ARRAY' % uppercase_name + binding_name = 'GL_%s_ARRAY_BUFFER_BINDING' % uppercase_name 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,) + + print ' // %s' % function.name + print ' {' + print ' GLboolean __enabled = GL_FALSE;' + print ' __glGetBooleanv(%s, &__enabled);' % enable_name + print ' if (__enabled) {' + print ' GLint __binding = 0;' + print ' __glGetIntegerv(%s, &__binding);' % binding_name + print ' if (!__binding) {' + + # Get the arguments via glGet* + for arg in function.args: + arg_get_enum = 'GL_%s_ARRAY_%s' % (uppercase_name, arg.name.upper()) + arg_get_function, arg_type = TypeGetter().visit(arg.type) + print ' %s %s = 0;' % (arg_type, arg.name) + print ' __%s(%s, &%s);' % (arg_get_function, arg_get_enum, arg.name) + + arg_names = ', '.join([arg.name for arg in function.args[:-1]]) + print ' size_t __size = __%s_size(%s, maxindex);' % (function.name, arg_names) + + # Emit a fake function + 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,) + print ' Trace::BeginArg(%u);' % (arg.index,) if arg.name != 'pointer': - dump_instance(arg.type, value) + dump_instance(arg.type, arg.name) 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();' + print ' Trace::LiteralBlob((const void *)%s, __size);' % (arg.name) + print ' Trace::EndArg();' + + print ' Trace::EndEnter();' + print ' Trace::BeginLeave(__call);' + print ' Trace::EndLeave();' + print ' }' + print ' }' print ' }' + print print '}' print diff --git a/trace.py b/trace.py index 95a9807..5711fa0 100644 --- a/trace.py +++ b/trace.py @@ -350,9 +350,12 @@ class Tracer: def dump_arg(self, function, arg): print ' Trace::BeginArg(%u);' % (arg.index,) - dump_instance(arg.type, arg.name) + self.dump_arg_instance(function, arg) print ' Trace::EndArg();' + def dump_arg_instance(self, function, arg): + dump_instance(arg.type, arg.name) + def wrap_arg(self, function, arg): wrap_instance(arg.type, arg.name) diff --git a/trace_format.hpp b/trace_format.hpp index ba57a51..3a3787b 100644 --- a/trace_format.hpp +++ b/trace_format.hpp @@ -32,7 +32,7 @@ namespace Trace { -#define TRACE_VERSION 0 +#define TRACE_VERSION 1 enum Event { EVENT_ENTER = 0, diff --git a/trace_model.cpp b/trace_model.cpp index 07b0c49..70039c6 100644 --- a/trace_model.cpp +++ b/trace_model.cpp @@ -55,6 +55,11 @@ Array::~Array() { } } +Blob::~Blob() { + // FIXME + //delete [] buf; +} + void Null::visit(Visitor &visitor) { visitor.visit(this); } void Bool::visit(Visitor &visitor) { visitor.visit(this); } diff --git a/trace_model.hpp b/trace_model.hpp index 0371681..f978435 100644 --- a/trace_model.hpp +++ b/trace_model.hpp @@ -231,10 +231,7 @@ public: buf = new char[_size]; } - ~Blob() { - // FIXME - //delete [] buf; - } + ~Blob(); void visit(Visitor &visitor); diff --git a/trace_parser.hpp b/trace_parser.hpp index 538ff6c..dfaf42e 100644 --- a/trace_parser.hpp +++ b/trace_parser.hpp @@ -69,6 +69,8 @@ protected: unsigned next_call_no; public: + static unsigned long long version; + Parser() { file = NULL; next_call_no = 0; @@ -79,15 +81,13 @@ public: } bool open(const char *filename) { - unsigned long long version; - file = gzopen(filename, "rb"); if (!file) { return false; } version = read_uint(); - if (version != TRACE_VERSION) { + if (version > TRACE_VERSION) { std::cerr << "error: unsupported format version" << version << "\n"; return false; } @@ -400,6 +400,9 @@ public: }; +unsigned long long Trace::Parser::version = 0; + + } /* namespace Trace */ #endif /* _TRACE_PARSER_HPP_ */