X-Git-Url: https://git.cworth.org/git?a=blobdiff_plain;f=gltrace.py;h=e5be57d3644f4aaacafabc72b4525f872b734ed1;hb=46a4839cd1b65981bec9f33b1d7978b821866a51;hp=bfccd581ad690ba597cc9b6a4082459a89890730;hpb=c493e3ef29b6d8e2c920152222437846316f4cd2;p=apitrace diff --git a/gltrace.py b/gltrace.py index bfccd58..e5be57d 100644 --- a/gltrace.py +++ b/gltrace.py @@ -27,10 +27,10 @@ """GL tracing generator.""" -import stdapi -import glapi -import glparams -from glxapi import glxapi +import specs.stdapi as stdapi +import specs.glapi as glapi +import specs.glparams as glparams +from specs.glxapi import glxapi from trace import Tracer, dump_instance @@ -107,9 +107,40 @@ class GlTracer(Tracer): def header(self, api): Tracer.header(self, api) + print '#include "gltrace.hpp"' + print print '// Whether user arrays were used' print 'static bool __user_arrays = false;' + print 'static bool __user_arrays_arb = false;' + print 'static bool __user_arrays_nv = false;' + print + + # Which glVertexAttrib* variant to use + print 'enum vertex_attrib {' + print ' VERTEX_ATTRIB,' + print ' VERTEX_ATTRIB_ARB,' + print ' VERTEX_ATTRIB_NV,' + print '};' print + print 'static vertex_attrib __get_vertex_attrib(void) {' + print ' if (__user_arrays_arb || __user_arrays_nv) {' + print ' GLboolean __vertex_program = GL_FALSE;' + print ' __glGetBooleanv(GL_VERTEX_PROGRAM_ARB, &__vertex_program);' + print ' if (__vertex_program) {' + print ' if (__user_arrays_nv) {' + print ' GLint __vertex_program_binding_nv = 0;' + print ' __glGetIntegerv(GL_VERTEX_PROGRAM_BINDING_NV, &__vertex_program_binding_nv);' + print ' if (__vertex_program_binding_nv) {' + print ' return VERTEX_ATTRIB_NV;' + print ' }' + print ' }' + print ' return VERTEX_ATTRIB_ARB;' + print ' }' + print ' }' + print ' return VERTEX_ATTRIB;' + print '}' + print + # Whether we need user arrays print 'static inline bool __need_user_arrays(void)' print '{' @@ -135,33 +166,35 @@ class GlTracer(Tracer): self.array_epilog(api, uppercase_name) print - print ' GLboolean __vertex_program = GL_FALSE;' - print ' __glGetBooleanv(GL_VERTEX_PROGRAM_ARB, &__vertex_program);' - print ' if (__vertex_program) {' - print ' // glVertexAttribPointerARB' + print ' vertex_attrib __vertex_attrib = __get_vertex_attrib();' + print + print ' // glVertexAttribPointer' + print ' if (__vertex_attrib == VERTEX_ATTRIB) {' print ' GLint __max_vertex_attribs = 0;' - print ' __glGetIntegerv(GL_MAX_VERTEX_ATTRIBS_ARB, &__max_vertex_attribs);' + print ' __glGetIntegerv(GL_MAX_VERTEX_ATTRIBS, &__max_vertex_attribs);' print ' for (GLint index = 0; index < __max_vertex_attribs; ++index) {' print ' GLint __enabled = 0;' - print ' __glGetVertexAttribivARB(index, GL_VERTEX_ATTRIB_ARRAY_ENABLED_ARB, &__enabled);' + print ' __glGetVertexAttribiv(index, GL_VERTEX_ATTRIB_ARRAY_ENABLED, &__enabled);' print ' if (__enabled) {' print ' GLint __binding = 0;' - print ' __glGetVertexAttribivARB(index, GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING_ARB, &__binding);' + print ' __glGetVertexAttribiv(index, GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING, &__binding);' print ' if (!__binding) {' print ' return true;' print ' }' print ' }' print ' }' - print ' } else {' - print ' // glVertexAttribPointer' + print ' }' + print + print ' // glVertexAttribPointerARB' + print ' if (__vertex_attrib == VERTEX_ATTRIB_ARB) {' print ' GLint __max_vertex_attribs = 0;' - print ' __glGetIntegerv(GL_MAX_VERTEX_ATTRIBS, &__max_vertex_attribs);' + print ' __glGetIntegerv(GL_MAX_VERTEX_ATTRIBS_ARB, &__max_vertex_attribs);' print ' for (GLint index = 0; index < __max_vertex_attribs; ++index) {' print ' GLint __enabled = 0;' - print ' __glGetVertexAttribiv(index, GL_VERTEX_ATTRIB_ARRAY_ENABLED, &__enabled);' + print ' __glGetVertexAttribivARB(index, GL_VERTEX_ATTRIB_ARRAY_ENABLED_ARB, &__enabled);' print ' if (__enabled) {' print ' GLint __binding = 0;' - print ' __glGetVertexAttribiv(index, GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING, &__binding);' + print ' __glGetVertexAttribivARB(index, GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING_ARB, &__binding);' print ' if (!__binding) {' print ' return true;' print ' }' @@ -169,6 +202,17 @@ class GlTracer(Tracer): print ' }' print ' }' print + print ' // glVertexAttribPointerNV' + print ' if (__vertex_attrib == VERTEX_ATTRIB_NV) {' + print ' for (GLint index = 0; index < 16; ++index) {' + print ' GLint __enabled = 0;' + print ' __glGetIntegerv(GL_VERTEX_ATTRIB_ARRAY0_NV + index, &__enabled);' + print ' if (__enabled) {' + print ' return true;' + print ' }' + print ' }' + print ' }' + print print ' return false;' print '}' @@ -200,9 +244,6 @@ class GlTracer(Tracer): print '}' print - # Generate memcpy's signature - self.trace_function_decl(glapi.memcpy) - # Generate a helper function to determine whether a parameter name # refers to a symbolic value or not print 'static bool' @@ -286,12 +327,15 @@ class GlTracer(Tracer): 'glMultiDrawArrays', 'glMultiDrawElements', 'glDrawArraysInstanced', + "glDrawArraysInstancedBaseInstance", 'glDrawElementsInstanced', 'glDrawArraysInstancedARB', 'glDrawElementsInstancedARB', 'glDrawElementsBaseVertex', 'glDrawRangeElementsBaseVertex', 'glDrawElementsInstancedBaseVertex', + "glDrawElementsInstancedBaseInstance", + "glDrawElementsInstancedBaseVertexBaseInstance", 'glMultiDrawElementsBaseVertex', 'glDrawArraysIndirect', 'glDrawElementsIndirect', @@ -330,6 +374,10 @@ class GlTracer(Tracer): print ' __glGetIntegerv(GL_ARRAY_BUFFER_BINDING, &__array_buffer);' print ' if (!__array_buffer) {' print ' __user_arrays = true;' + if function.name == "glVertexAttribPointerARB": + print ' __user_arrays_arb = true;' + if function.name == "glVertexAttribPointerNV": + print ' __user_arrays_nv = true;' self.dispatch_function(function) # And also break down glInterleavedArrays into the individual calls @@ -364,13 +412,13 @@ class GlTracer(Tracer): # Emit a fake function print ' {' print ' static const Trace::FunctionSig &__sig = %s ? __glEnableClientState_sig : __glDisableClientState_sig;' % flag_name - print ' unsigned __call = __writer.beginEnter(&__sig);' - print ' __writer.beginArg(0);' + print ' unsigned __call = Trace::localWriter.beginEnter(&__sig);' + print ' Trace::localWriter.beginArg(0);' dump_instance(glapi.GLenum, enable_name) - print ' __writer.endArg();' - print ' __writer.endEnter();' - print ' __writer.beginLeave(__call);' - print ' __writer.endLeave();' + print ' Trace::localWriter.endArg();' + print ' Trace::localWriter.endEnter();' + print ' Trace::localWriter.beginLeave(__call);' + print ' Trace::localWriter.endLeave();' print ' }' print ' return;' @@ -391,14 +439,13 @@ class GlTracer(Tracer): self.emit_memcpy('mapping->map', 'mapping->map', 'mapping->length') print ' }' if function.name in ('glFlushMappedBufferRange', 'glFlushMappedBufferRangeAPPLE'): - # TODO: avoid copying [0, offset] bytes print ' struct buffer_mapping *mapping = get_buffer_mapping(target);' print ' if (mapping) {' if function.name.endswith('APPLE'): print ' GLsizeiptr length = size;' print ' mapping->explicit_flush = true;' print ' //assert(offset + length <= mapping->length);' - self.emit_memcpy('mapping->map', 'mapping->map', 'offset + length') + self.emit_memcpy('(char *)mapping->map + offset', '(const char *)mapping->map + offset', 'length') print ' }' # FIXME: glFlushMappedNamedBufferRangeEXT @@ -411,7 +458,7 @@ class GlTracer(Tracer): Tracer.dispatch_function(self, function) print ' GLint active_attributes = 0;' print ' __glGetProgramiv(program, GL_ACTIVE_ATTRIBUTES, &active_attributes);' - print ' for (GLuint attrib = 0; attrib < active_attributes; ++attrib) {' + print ' for (GLint attrib = 0; attrib < active_attributes; ++attrib) {' print ' GLint size = 0;' print ' GLenum type = 0;' print ' GLchar name[256];' @@ -429,7 +476,7 @@ class GlTracer(Tracer): Tracer.dispatch_function(self, function) print ' GLint active_attributes = 0;' print ' __glGetObjectParameterivARB(programObj, GL_OBJECT_ACTIVE_ATTRIBUTES_ARB, &active_attributes);' - print ' for (GLuint attrib = 0; attrib < active_attributes; ++attrib) {' + print ' for (GLint attrib = 0; attrib < active_attributes; ++attrib) {' print ' GLint size = 0;' print ' GLenum type = 0;' print ' GLcharARB name[256];' @@ -446,27 +493,53 @@ class GlTracer(Tracer): Tracer.trace_function_impl_body(self, function) + gremedy_functions = [ + 'glStringMarkerGREMEDY', + 'glFrameTerminatorGREMEDY', + ] + def dispatch_function(self, function): if function.name in ('glLinkProgram', 'glLinkProgramARB'): # These functions have been dispatched already return + # We implement the GREMEDY extensions, not the driver + if function.name in self.gremedy_functions: + return + + if function.name in ('glXGetProcAddress', 'glXGetProcAddressARB', 'wglGetProcAddress'): + if_ = 'if' + for gremedy_function in self.gremedy_functions: + print ' %s (strcmp("%s", (const char *)%s) == 0) {' % (if_, gremedy_function, function.args[0].name) + print ' __result = (%s)&%s;' % (function.type, gremedy_function) + print ' }' + if_ = 'else if' + print ' else {' + Tracer.dispatch_function(self, function) + print ' }' + return + + # Override GL extensions + if function.name in ('glGetString', 'glGetIntegerv', 'glGetStringi'): + Tracer.dispatch_function(self, function, prefix = 'gltrace::__', suffix = '_override') + return + Tracer.dispatch_function(self, function) def emit_memcpy(self, dest, src, length): - print ' unsigned __call = __writer.beginEnter(&__memcpy_sig);' - print ' __writer.beginArg(0);' - print ' __writer.writeOpaque(%s);' % dest - print ' __writer.endArg();' - print ' __writer.beginArg(1);' - print ' __writer.writeBlob(%s, %s);' % (src, length) - print ' __writer.endArg();' - print ' __writer.beginArg(2);' - print ' __writer.writeUInt(%s);' % length - print ' __writer.endArg();' - print ' __writer.endEnter();' - print ' __writer.beginLeave(__call);' - print ' __writer.endLeave();' + print ' unsigned __call = Trace::localWriter.beginEnter(&Trace::memcpy_sig);' + print ' Trace::localWriter.beginArg(0);' + print ' Trace::localWriter.writeOpaque(%s);' % dest + print ' Trace::localWriter.endArg();' + print ' Trace::localWriter.beginArg(1);' + print ' Trace::localWriter.writeBlob(%s, %s);' % (src, length) + print ' Trace::localWriter.endArg();' + print ' Trace::localWriter.beginArg(2);' + print ' Trace::localWriter.writeUInt(%s);' % length + print ' Trace::localWriter.endArg();' + print ' Trace::localWriter.endEnter();' + print ' Trace::localWriter.beginLeave(__call);' + print ' Trace::localWriter.endLeave();' buffer_targets = [ 'ARRAY_BUFFER', @@ -477,6 +550,7 @@ class GlTracer(Tracer): def wrap_ret(self, function, instance): Tracer.wrap_ret(self, function, instance) + if function.name in ('glMapBuffer', 'glMapBufferARB'): print ' struct buffer_mapping *mapping = get_buffer_mapping(target);' @@ -557,15 +631,15 @@ class GlTracer(Tracer): print ' __glGetIntegerv(GL_ELEMENT_ARRAY_BUFFER_BINDING, &__element_array_buffer);' print ' if (!__element_array_buffer) {' if isinstance(arg.type, stdapi.Array): - print ' __writer.beginArray(%s);' % arg.type.length + print ' Trace::localWriter.beginArray(%s);' % arg.type.length print ' for(GLsizei i = 0; i < %s; ++i) {' % arg.type.length - print ' __writer.beginElement();' - print ' __writer.writeBlob(%s[i], count[i]*__gl_type_size(type));' % (arg.name) - print ' __writer.endElement();' + print ' Trace::localWriter.beginElement();' + print ' Trace::localWriter.writeBlob(%s[i], count[i]*__gl_type_size(type));' % (arg.name) + print ' Trace::localWriter.endElement();' print ' }' - print ' __writer.endArray();' + print ' Trace::localWriter.endArray();' else: - print ' __writer.writeBlob(%s, count*__gl_type_size(type));' % (arg.name) + print ' Trace::localWriter.writeBlob(%s, count*__gl_type_size(type));' % (arg.name) print ' } else {' Tracer.dump_arg_instance(self, function, arg) print ' }' @@ -580,7 +654,7 @@ class GlTracer(Tracer): print ' GLint __unpack_buffer = 0;' print ' __glGetIntegerv(GL_PIXEL_UNPACK_BUFFER_BINDING, &__unpack_buffer);' print ' if (__unpack_buffer) {' - print ' __writer.writeOpaque(%s);' % arg.name + print ' Trace::localWriter.writeOpaque(%s);' % arg.name print ' } else {' Tracer.dump_arg_instance(self, function, arg) print ' }' @@ -590,7 +664,7 @@ class GlTracer(Tracer): # Several GL state functions take GLenum symbolic names as # integer/floats; so dump the symbolic name whenever possible if function.name.startswith('gl') \ - and arg.type in (glapi.GLint, glapi.GLfloat) \ + and arg.type in (glapi.GLint, glapi.GLfloat, glapi.GLdouble) \ and arg.name == 'param': assert arg.index > 0 assert function.args[arg.index - 1].name == 'pname' @@ -638,19 +712,19 @@ class GlTracer(Tracer): # Emit a fake function self.array_trace_intermezzo(api, uppercase_name) - print ' unsigned __call = __writer.beginEnter(&__%s_sig);' % (function.name,) + print ' unsigned __call = Trace::localWriter.beginEnter(&__%s_sig);' % (function.name,) for arg in function.args: assert not arg.output - print ' __writer.beginArg(%u);' % (arg.index,) + print ' Trace::localWriter.beginArg(%u);' % (arg.index,) if arg.name != 'pointer': dump_instance(arg.type, arg.name) else: - print ' __writer.writeBlob((const void *)%s, __size);' % (arg.name) - print ' __writer.endArg();' + print ' Trace::localWriter.writeBlob((const void *)%s, __size);' % (arg.name) + print ' Trace::localWriter.endArg();' - print ' __writer.endEnter();' - print ' __writer.beginLeave(__call);' - print ' __writer.endLeave();' + print ' Trace::localWriter.endEnter();' + print ' Trace::localWriter.beginLeave(__call);' + print ' Trace::localWriter.endLeave();' print ' }' print ' }' self.array_epilog(api, uppercase_name) @@ -667,57 +741,63 @@ class GlTracer(Tracer): # This means that the implementations of these functions do not always # alias, and they need to be considered independently. # - print ' GLboolean __vertex_program = GL_FALSE;' - print ' __glGetBooleanv(GL_VERTEX_PROGRAM_ARB, &__vertex_program);' - for suffix in ['', 'ARB']: - if suffix == 'ARB': + print ' vertex_attrib __vertex_attrib = __get_vertex_attrib();' + print + for suffix in ['', 'ARB', 'NV']: + if suffix: SUFFIX = '_' + suffix - logic_op = '' else: - SUFFIX = '' - logic_op = '!' - print ' if (%s__vertex_program) {' % logic_op + SUFFIX = suffix function_name = 'glVertexAttribPointer' + suffix - print ' // %s' % function_name - print ' if (__glVertexAttribPointer%s_ptr &&' % suffix - print ' (__glVertexAttribPointer%s_ptr != __glVertexAttribPointer_ptr)) {' % suffix - print ' GLint __max_vertex_attribs = 0;' - print ' __glGetIntegerv(GL_MAX_VERTEX_ATTRIBS, &__max_vertex_attribs);' - print ' for (GLint index = 0; index < __max_vertex_attribs; ++index) {' - print ' GLint __enabled = 0;' - print ' __glGetVertexAttribiv%s(index, GL_VERTEX_ATTRIB_ARRAY_ENABLED%s, &__enabled);' % (suffix, SUFFIX) - print ' if (__enabled) {' - print ' GLint __binding = 0;' - print ' __glGetVertexAttribiv%s(index, GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING%s, &__binding);' % (suffix, SUFFIX) - print ' if (!__binding) {' + print ' // %s' % function_name + print ' if (__vertex_attrib == VERTEX_ATTRIB%s) {' % SUFFIX + if suffix == 'NV': + print ' GLint __max_vertex_attribs = 16;' + else: + print ' GLint __max_vertex_attribs = 0;' + print ' __glGetIntegerv(GL_MAX_VERTEX_ATTRIBS, &__max_vertex_attribs);' + print ' for (GLint index = 0; index < __max_vertex_attribs; ++index) {' + print ' GLint __enabled = 0;' + if suffix == 'NV': + print ' __glGetIntegerv(GL_VERTEX_ATTRIB_ARRAY0_NV + index, &__enabled);' + else: + print ' __glGetVertexAttribiv%s(index, GL_VERTEX_ATTRIB_ARRAY_ENABLED%s, &__enabled);' % (suffix, SUFFIX) + print ' if (__enabled) {' + print ' GLint __binding = 0;' + if suffix != 'NV': + # It doesn't seem possible to use VBOs with NV_vertex_program. + print ' __glGetVertexAttribiv%s(index, GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING%s, &__binding);' % (suffix, SUFFIX) + print ' if (!__binding) {' function = api.get_function_by_name(function_name) # Get the arguments via glGet* for arg in function.args[1:]: - arg_get_enum = 'GL_VERTEX_ATTRIB_ARRAY_%s%s' % (arg.name.upper(), SUFFIX) + if suffix == 'NV': + arg_get_enum = 'GL_ATTRIB_ARRAY_%s%s' % (arg.name.upper(), SUFFIX) + else: + arg_get_enum = 'GL_VERTEX_ATTRIB_ARRAY_%s%s' % (arg.name.upper(), SUFFIX) arg_get_function, arg_type = TypeGetter('glGetVertexAttrib', False, suffix).visit(arg.type) - print ' %s %s = 0;' % (arg_type, arg.name) - print ' __%s(index, %s, &%s);' % (arg_get_function, arg_get_enum, arg.name) + print ' %s %s = 0;' % (arg_type, arg.name) + print ' __%s(index, %s, &%s);' % (arg_get_function, arg_get_enum, arg.name) arg_names = ', '.join([arg.name for arg in function.args[1:-1]]) - print ' size_t __size = __%s_size(%s, maxindex);' % (function.name, arg_names) + print ' size_t __size = __%s_size(%s, maxindex);' % (function.name, arg_names) # Emit a fake function - print ' unsigned __call = __writer.beginEnter(&__%s_sig);' % (function.name,) + print ' unsigned __call = Trace::localWriter.beginEnter(&__%s_sig);' % (function.name,) for arg in function.args: assert not arg.output - print ' __writer.beginArg(%u);' % (arg.index,) + print ' Trace::localWriter.beginArg(%u);' % (arg.index,) if arg.name != 'pointer': dump_instance(arg.type, arg.name) else: - print ' __writer.writeBlob((const void *)%s, __size);' % (arg.name) - print ' __writer.endArg();' + print ' Trace::localWriter.writeBlob((const void *)%s, __size);' % (arg.name) + print ' Trace::localWriter.endArg();' - print ' __writer.endEnter();' - print ' __writer.beginLeave(__call);' - print ' __writer.endLeave();' - print ' }' + print ' Trace::localWriter.endEnter();' + print ' Trace::localWriter.beginLeave(__call);' + print ' Trace::localWriter.endLeave();' print ' }' print ' }' print ' }' @@ -739,7 +819,7 @@ class GlTracer(Tracer): print ' GLint max_texture_coords = 0;' print ' __glGetIntegerv(GL_MAX_TEXTURE_COORDS, &max_texture_coords);' print ' for (GLint unit = 0; unit < max_texture_coords; ++unit) {' - print ' GLenum texture = GL_TEXTURE0 + unit;' + print ' GLint texture = GL_TEXTURE0 + unit;' print ' __glClientActiveTexture(texture);' def array_trace_prolog(self, api, uppercase_name): @@ -773,15 +853,15 @@ class GlTracer(Tracer): self.fake_call(function, [texture]) def fake_call(self, function, args): - print ' unsigned __fake_call = __writer.beginEnter(&__%s_sig);' % (function.name,) + print ' unsigned __fake_call = Trace::localWriter.beginEnter(&__%s_sig);' % (function.name,) for arg, instance in zip(function.args, args): assert not arg.output - print ' __writer.beginArg(%u);' % (arg.index,) + print ' Trace::localWriter.beginArg(%u);' % (arg.index,) dump_instance(arg.type, instance) - print ' __writer.endArg();' - print ' __writer.endEnter();' - print ' __writer.beginLeave(__fake_call);' - print ' __writer.endLeave();' + print ' Trace::localWriter.endArg();' + print ' Trace::localWriter.endEnter();' + print ' Trace::localWriter.beginLeave(__fake_call);' + print ' Trace::localWriter.endLeave();'