Brian Paul | 65ced47 | 2006-06-02 14:50:28 +0000 | [diff] [blame] | 1 | #!/usr/bin/env python |
| 2 | |
| 3 | # Copyright (C) 2006 Thomas Sondergaard |
| 4 | # All Rights Reserved. |
| 5 | # |
| 6 | # Permission is hereby granted, free of charge, to any person obtaining a |
| 7 | # copy of this software and associated documentation files (the "Software"), |
| 8 | # to deal in the Software without restriction, including without limitation |
| 9 | # on the rights to use, copy, modify, merge, publish, distribute, sub |
| 10 | # license, and/or sell copies of the Software, and to permit persons to whom |
| 11 | # the Software is furnished to do so, subject to the following conditions: |
| 12 | # |
| 13 | # The above copyright notice and this permission notice (including the next |
| 14 | # paragraph) shall be included in all copies or substantial portions of the |
| 15 | # Software. |
| 16 | # |
| 17 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
| 18 | # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
| 19 | # FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL |
| 20 | # IBM AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER |
| 21 | # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING |
| 22 | # FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS |
| 23 | # IN THE SOFTWARE. |
| 24 | # |
| 25 | # Authors: |
| 26 | # Thomas Sondergaard <ts@medical-insight.com> |
| 27 | |
| 28 | import gl_XML, glX_XML, glX_proto_common, license |
| 29 | import sys, getopt, copy, string |
| 30 | |
| 31 | def create_argument_string(parameters): |
| 32 | """Create a parameter string from a list of gl_parameters.""" |
| 33 | |
| 34 | list = [] |
| 35 | for p in parameters: |
| 36 | list.append( p.name ) |
| 37 | #if len(list) == 0: list = ["void"] |
| 38 | |
| 39 | return string.join(list, ", ") |
| 40 | |
| 41 | def create_logfunc_string(func, name): |
| 42 | """Create a parameter string from a list of gl_parameters.""" |
| 43 | |
| 44 | list = [] |
| 45 | list.append('"gl' + name + '("') |
| 46 | sep = None |
| 47 | for p in func.parameters: |
| 48 | if (sep): |
| 49 | list.append(sep) |
| 50 | list.append( p.name ) |
| 51 | sep = '", "' |
| 52 | list.append('");"') |
| 53 | #if len(list) == 0: list = ["void"] |
| 54 | |
| 55 | return "if (config.logCalls) GLTRACE_LOG(" + string.join(list, " << ")+");"; |
| 56 | |
| 57 | class PrintGltrace(glX_proto_common.glx_print_proto): #(gl_XML.gl_print_base): |
| 58 | def __init__(self): |
| 59 | gl_XML.gl_print_base.__init__(self) |
| 60 | |
| 61 | self.name = "gltrace.py" |
| 62 | self.license = license.bsd_license_template % ( \ |
| 63 | """Copyright 1998-1999 Precision Insight, Inc., Cedar Park, Texas. |
| 64 | (C) Copyright IBM Corporation 2004""", "PRECISION INSIGHT, IBM") |
| 65 | #self.header_tag = "_INDIRECT_H_" |
| 66 | |
| 67 | self.last_category = "" |
| 68 | return |
| 69 | |
| 70 | |
| 71 | def printRealHeader(self): |
| 72 | print """/** |
| 73 | * \\file |
| 74 | * gl and glX wrappers for tracing |
| 75 | * |
| 76 | * \\author Thomas Sondergaard <ts@medical-insight.com> |
| 77 | */ |
| 78 | """ |
| 79 | #self.printVisibility( "HIDDEN", "hidden" ) |
| 80 | #self.printFastcall() |
| 81 | #self.printNoinline() |
| 82 | |
| 83 | print """ |
| 84 | #include <GL/gl.h> |
| 85 | #include <GL/glx.h> |
| 86 | #include <GL/glu.h> |
| 87 | #include <dlfcn.h> |
| 88 | #include "gltrace_support.h" |
| 89 | |
| 90 | using namespace gltrace; |
| 91 | |
| 92 | static GLenum real_glGetError() { |
| 93 | static GLenum (*real_func)(void) = 0; |
| 94 | if (!real_func) real_func = (GLenum (*)(void)) dlsym(RTLD_NEXT, "glGetError"); |
| 95 | return real_func(); |
| 96 | } |
| 97 | |
| 98 | bool betweenGLBeginEnd = false; |
| 99 | |
| 100 | extern "C" { |
| 101 | |
| 102 | |
| 103 | __GLXextFuncPtr real_glXGetProcAddressARB(const GLubyte *func_name) { |
| 104 | static __GLXextFuncPtr (*real_func)(const GLubyte *func_name) = 0; |
| 105 | if (!real_func) real_func = (__GLXextFuncPtr (*)(const GLubyte *func_name)) dlsym(RTLD_NEXT, "glXGetProcAddressARB"); |
| 106 | |
| 107 | return real_func(func_name); |
| 108 | } |
| 109 | |
| 110 | __GLXextFuncPtr glXGetProcAddressARB(const GLubyte *func_name_ubyte) { |
| 111 | std::string func_name = |
| 112 | std::string("gltrace_")+reinterpret_cast<const char*>(func_name_ubyte); |
| 113 | |
| 114 | __GLXextFuncPtr f = (__GLXextFuncPtr) dlsym(RTLD_DEFAULT, func_name.c_str()); |
| 115 | if (!f) { |
| 116 | GLTRACE_LOG("warning: Could not resolve '" << func_name << "' - function will not be intercepted"); |
| 117 | return real_glXGetProcAddressARB(func_name_ubyte); |
| 118 | } |
| 119 | return f; |
| 120 | } |
| 121 | |
| 122 | """ |
| 123 | |
| 124 | def printRealFooter(self): |
| 125 | print "} // Extern \"C\"" |
| 126 | |
| 127 | def printBody(self, api): |
| 128 | for func in api.functionIterateGlx(): |
| 129 | for func_name in func.entry_points: |
| 130 | functionPrefix = "" |
| 131 | use_dlsym = True |
| 132 | if (api.get_category_for_name(func.name)[1] != None): |
| 133 | functionPrefix = "gltrace_" |
| 134 | use_dlsym = False |
| 135 | |
| 136 | print '%s %sgl%s(%s) {' % (func.return_type, functionPrefix, func_name, func.get_parameter_string()) |
| 137 | if (use_dlsym): |
| 138 | print ' static %s (*real_func)(%s) = 0;' % (func.return_type, func.get_parameter_string()) |
| 139 | print ' if (!real_func) real_func = (%s (*)(%s)) dlsym(RTLD_NEXT, "gl%s");' % (func.return_type, func.get_parameter_string(), func_name) |
| 140 | else: # use glXGetProcAddressArb |
| 141 | print ' static %s (*real_func)(%s) = 0;' % (func.return_type, func.get_parameter_string()) |
| 142 | print ' if (!real_func) real_func = (%s (*)(%s)) real_glXGetProcAddressARB((GLubyte *)"gl%s");' % (func.return_type, func.get_parameter_string(), func_name) |
| 143 | print ' ' + create_logfunc_string(func, func_name) |
| 144 | if (func.return_type == "void"): |
| 145 | print ' real_func(%s);' % (create_argument_string(func.parameters)) |
| 146 | else: |
| 147 | print ' %s retval = real_func(%s);' % (func.return_type, create_argument_string(func.parameters)) |
| 148 | if (func.name == "Begin"): |
| 149 | print ' betweenGLBeginEnd = true;' |
| 150 | elif (func.name == "End"): |
| 151 | print ' betweenGLBeginEnd = false;' |
| 152 | print ' if (!betweenGLBeginEnd && config.checkErrors) {' |
| 153 | print ' GLenum res;' |
| 154 | print ' while ((res = real_glGetError ()) != GL_NO_ERROR) ' |
| 155 | print ' GLTRACE_LOG("OpenGL Error (" << res << "): <" << gluErrorString(res) << "> at " << gltrace::getStackTrace());' |
| 156 | print ' }' |
| 157 | if (func.return_type != "void"): |
| 158 | print " return retval;" |
| 159 | print '}' |
| 160 | |
| 161 | |
| 162 | def show_usage(): |
| 163 | print "Usage: %s [-f input_file_name] [-m output_mode] [-d]" % sys.argv[0] |
| 164 | print " -m output_mode Output mode can be one of 'proto', 'init_c' or 'init_h'." |
| 165 | print " -d Enable extra debug information in the generated code." |
| 166 | sys.exit(1) |
| 167 | |
| 168 | |
| 169 | if __name__ == '__main__': |
| 170 | file_name = "gl_API.xml" |
| 171 | |
| 172 | try: |
| 173 | (args, trail) = getopt.getopt(sys.argv[1:], "f:d") |
| 174 | except Exception,e: |
| 175 | show_usage() |
| 176 | |
| 177 | debug = 0 |
| 178 | for (arg,val) in args: |
| 179 | if arg == "-f": |
| 180 | file_name = val |
| 181 | elif arg == "-d": |
| 182 | debug = 1 |
| 183 | |
| 184 | printer = PrintGltrace() |
| 185 | |
| 186 | printer.debug = debug |
| 187 | api = gl_XML.parse_GL_API( file_name, glX_XML.glx_item_factory() ) |
| 188 | |
| 189 | printer.Print( api ) |