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