1 #!/usr/bin/env python 2 3 # (C) Copyright IBM Corporation 2004, 2005 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 # Ian Romanick <idr (at] us.ibm.com> 27 28 import gl_XML, glX_XML 29 import license 30 import sys, getopt 31 32 class PrintGlOffsets(gl_XML.gl_print_base): 33 def __init__(self, es=False): 34 gl_XML.gl_print_base.__init__(self) 35 36 self.name = "gl_apitemp.py (from Mesa)" 37 self.license = license.bsd_license_template % ( \ 38 """Copyright (C) 1999-2001 Brian Paul All Rights Reserved. 39 (C) Copyright IBM Corporation 2004""", "BRIAN PAUL, IBM") 40 41 self.es = es 42 43 self.undef_list.append( "KEYWORD1" ) 44 self.undef_list.append( "KEYWORD1_ALT" ) 45 self.undef_list.append( "KEYWORD2" ) 46 self.undef_list.append( "NAME" ) 47 self.undef_list.append( "DISPATCH" ) 48 self.undef_list.append( "RETURN_DISPATCH" ) 49 self.undef_list.append( "DISPATCH_TABLE_NAME" ) 50 self.undef_list.append( "UNUSED_TABLE_NAME" ) 51 self.undef_list.append( "TABLE_ENTRY" ) 52 53 54 def printFunction(self, f, name): 55 p_string = "" 56 o_string = "" 57 t_string = "" 58 comma = "" 59 60 if f.is_static_entry_point(name): 61 keyword = "KEYWORD1" 62 else: 63 keyword = "KEYWORD1_ALT" 64 65 n = f.static_name(name) 66 67 silence = '' 68 space = '' 69 for p in f.parameterIterator(): 70 if p.is_padding: 71 continue 72 73 if p.is_pointer(): 74 cast = "(const void *) " 75 else: 76 cast = "" 77 78 t_string = t_string + comma + p.format_string() 79 p_string = p_string + comma + p.name 80 o_string = o_string + comma + cast + p.name 81 comma = ", " 82 83 silence += "%s(void) %s;" % (space, p.name); 84 space = ' ' 85 86 87 if f.return_type != 'void': 88 dispatch = "RETURN_DISPATCH" 89 else: 90 dispatch = "DISPATCH" 91 92 need_proto = False 93 if not f.is_static_entry_point(name): 94 need_proto = True 95 elif self.es: 96 cat, num = api.get_category_for_name(name) 97 if (cat.startswith("es") or cat.startswith("GL_OES")): 98 need_proto = True 99 if need_proto: 100 print '%s %s KEYWORD2 NAME(%s)(%s);' % (keyword, f.return_type, n, f.get_parameter_string(name)) 101 print '' 102 103 print '%s %s KEYWORD2 NAME(%s)(%s)' % (keyword, f.return_type, n, f.get_parameter_string(name)) 104 print '{' 105 if silence: 106 print ' %s' % (silence) 107 if p_string == "": 108 print ' %s(%s, (), (F, "gl%s();\\n"));' \ 109 % (dispatch, f.name, name) 110 else: 111 print ' %s(%s, (%s), (F, "gl%s(%s);\\n", %s));' \ 112 % (dispatch, f.name, p_string, name, t_string, o_string) 113 print '}' 114 print '' 115 return 116 117 def printRealHeader(self): 118 print '' 119 self.printVisibility( "HIDDEN", "hidden" ) 120 print """ 121 /* 122 * This file is a template which generates the OpenGL API entry point 123 * functions. It should be included by a .c file which first defines 124 * the following macros: 125 * KEYWORD1 - usually nothing, but might be __declspec(dllexport) on Win32 126 * KEYWORD2 - usually nothing, but might be __stdcall on Win32 127 * NAME(n) - builds the final function name (usually add "gl" prefix) 128 * DISPATCH(func, args, msg) - code to do dispatch of named function. 129 * msg is a printf-style debug message. 130 * RETURN_DISPATCH(func, args, msg) - code to do dispatch with a return value 131 * 132 * Here is an example which generates the usual OpenGL functions: 133 * #define KEYWORD1 134 * #define KEYWORD2 135 * #define NAME(func) gl##func 136 * #define DISPATCH(func, args, msg) \\ 137 * struct _glapi_table *dispatch = CurrentDispatch; \\ 138 * (*dispatch->func) args 139 * #define RETURN DISPATCH(func, args, msg) \\ 140 * struct _glapi_table *dispatch = CurrentDispatch; \\ 141 * return (*dispatch->func) args 142 * 143 */ 144 145 146 #if defined( NAME ) 147 #ifndef KEYWORD1 148 #define KEYWORD1 149 #endif 150 151 #ifndef KEYWORD1_ALT 152 #define KEYWORD1_ALT HIDDEN 153 #endif 154 155 #ifndef KEYWORD2 156 #define KEYWORD2 157 #endif 158 159 #ifndef DISPATCH 160 #error DISPATCH must be defined 161 #endif 162 163 #ifndef RETURN_DISPATCH 164 #error RETURN_DISPATCH must be defined 165 #endif 166 167 """ 168 return 169 170 171 172 def printInitDispatch(self, api): 173 print """ 174 #endif /* defined( NAME ) */ 175 176 /* 177 * This is how a dispatch table can be initialized with all the functions 178 * we generated above. 179 */ 180 #ifdef DISPATCH_TABLE_NAME 181 182 #ifndef TABLE_ENTRY 183 #error TABLE_ENTRY must be defined 184 #endif 185 186 #ifdef _GLAPI_SKIP_NORMAL_ENTRY_POINTS 187 #error _GLAPI_SKIP_NORMAL_ENTRY_POINTS must not be defined 188 #endif 189 190 _glapi_proc DISPATCH_TABLE_NAME[] = {""" 191 for f in api.functionIterateByOffset(): 192 print ' TABLE_ENTRY(%s),' % (f.dispatch_name()) 193 194 print ' /* A whole bunch of no-op functions. These might be called' 195 print ' * when someone tries to call a dynamically-registered' 196 print ' * extension function without a current rendering context.' 197 print ' */' 198 for i in range(1, 100): 199 print ' TABLE_ENTRY(Unused),' 200 201 print '};' 202 print '#endif /* DISPATCH_TABLE_NAME */' 203 print '' 204 return 205 206 207 def printAliasedTable(self, api): 208 print """ 209 /* 210 * This is just used to silence compiler warnings. 211 * We list the functions which are not otherwise used. 212 */ 213 #ifdef UNUSED_TABLE_NAME 214 _glapi_proc UNUSED_TABLE_NAME[] = {""" 215 216 normal_entries = [] 217 proto_entries = [] 218 for f in api.functionIterateByOffset(): 219 normal_ents, proto_ents = self.classifyEntryPoints(f) 220 221 # exclude f.name 222 if f.name in normal_ents: 223 normal_ents.remove(f.name) 224 elif f.name in proto_ents: 225 proto_ents.remove(f.name) 226 227 normal_ents = [f.static_name(ent) for ent in normal_ents] 228 proto_ents = [f.static_name(ent) for ent in proto_ents] 229 230 normal_entries.extend(normal_ents) 231 proto_entries.extend(proto_ents) 232 233 print '#ifndef _GLAPI_SKIP_NORMAL_ENTRY_POINTS' 234 for ent in normal_entries: 235 print ' TABLE_ENTRY(%s),' % (ent) 236 print '#endif /* _GLAPI_SKIP_NORMAL_ENTRY_POINTS */' 237 print '#ifndef _GLAPI_SKIP_PROTO_ENTRY_POINTS' 238 for ent in proto_entries: 239 print ' TABLE_ENTRY(%s),' % (ent) 240 print '#endif /* _GLAPI_SKIP_PROTO_ENTRY_POINTS */' 241 242 print '};' 243 print '#endif /*UNUSED_TABLE_NAME*/' 244 print '' 245 return 246 247 248 def classifyEntryPoints(self, func): 249 normal_names = [] 250 normal_stubs = [] 251 proto_names = [] 252 proto_stubs = [] 253 # classify the entry points 254 for name in func.entry_points: 255 if func.has_different_protocol(name): 256 if func.is_static_entry_point(name): 257 proto_names.append(name) 258 else: 259 proto_stubs.append(name) 260 else: 261 if func.is_static_entry_point(name): 262 normal_names.append(name) 263 else: 264 normal_stubs.append(name) 265 # there can be at most one stub for a function 266 if normal_stubs: 267 normal_names.append(normal_stubs[0]) 268 elif proto_stubs: 269 proto_names.append(proto_stubs[0]) 270 271 return (normal_names, proto_names) 272 273 def printBody(self, api): 274 normal_entry_points = [] 275 proto_entry_points = [] 276 for func in api.functionIterateByOffset(): 277 normal_ents, proto_ents = self.classifyEntryPoints(func) 278 normal_entry_points.append((func, normal_ents)) 279 proto_entry_points.append((func, proto_ents)) 280 281 print '#ifndef _GLAPI_SKIP_NORMAL_ENTRY_POINTS' 282 print '' 283 for func, ents in normal_entry_points: 284 for ent in ents: 285 self.printFunction(func, ent) 286 print '' 287 print '#endif /* _GLAPI_SKIP_NORMAL_ENTRY_POINTS */' 288 print '' 289 print '/* these entry points might require different protocols */' 290 print '#ifndef _GLAPI_SKIP_PROTO_ENTRY_POINTS' 291 print '' 292 for func, ents in proto_entry_points: 293 for ent in ents: 294 self.printFunction(func, ent) 295 print '' 296 print '#endif /* _GLAPI_SKIP_PROTO_ENTRY_POINTS */' 297 print '' 298 299 self.printInitDispatch(api) 300 self.printAliasedTable(api) 301 return 302 303 304 def show_usage(): 305 print "Usage: %s [-f input_file_name] [-c]" % sys.argv[0] 306 print "-c Enable compatibility with OpenGL ES." 307 sys.exit(1) 308 309 if __name__ == '__main__': 310 file_name = "gl_API.xml" 311 312 try: 313 (args, trail) = getopt.getopt(sys.argv[1:], "f:c") 314 except Exception,e: 315 show_usage() 316 317 es = False 318 for (arg,val) in args: 319 if arg == "-f": 320 file_name = val 321 elif arg == "-c": 322 es = True 323 324 api = gl_XML.parse_GL_API(file_name, glX_XML.glx_item_factory()) 325 326 printer = PrintGlOffsets(es) 327 printer.Print(api) 328