1 2# (C) Copyright IBM Corporation 2004, 2005 3# All Rights Reserved. 4# 5# Permission is hereby granted, free of charge, to any person obtaining a 6# copy of this software and associated documentation files (the "Software"), 7# to deal in the Software without restriction, including without limitation 8# on the rights to use, copy, modify, merge, publish, distribute, sub 9# license, and/or sell copies of the Software, and to permit persons to whom 10# the Software is furnished to do so, subject to the following conditions: 11# 12# The above copyright notice and this permission notice (including the next 13# paragraph) shall be included in all copies or substantial portions of the 14# Software. 15# 16# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18# FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL 19# IBM AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 21# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 22# IN THE SOFTWARE. 23# 24# Authors: 25# Ian Romanick <idr@us.ibm.com> 26 27import argparse 28 29import gl_XML, glX_XML 30import license 31 32class 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(name): 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 = CurrentClientDispatch; \\ 138 * (*dispatch->func) args 139 * #define RETURN DISPATCH(func, args, msg) \\ 140 * struct _glapi_table *dispatch = CurrentClientDispatch; \\ 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#ifdef MemoryBarrier 168#undef MemoryBarrier 169#endif 170 171""") 172 return 173 174 175 176 def printInitDispatch(self, api): 177 print(""" 178#endif /* defined( NAME ) */ 179 180/* 181 * This is how a dispatch table can be initialized with all the functions 182 * we generated above. 183 */ 184#ifdef DISPATCH_TABLE_NAME 185 186#ifndef TABLE_ENTRY 187#error TABLE_ENTRY must be defined 188#endif 189 190#ifdef _GLAPI_SKIP_NORMAL_ENTRY_POINTS 191#error _GLAPI_SKIP_NORMAL_ENTRY_POINTS must not be defined 192#endif 193 194_glapi_proc DISPATCH_TABLE_NAME[] = {""") 195 for f in api.functionIterateByOffset(): 196 print(' TABLE_ENTRY(%s),' % (f.dispatch_name())) 197 198 print(' /* A whole bunch of no-op functions. These might be called') 199 print(' * when someone tries to call a dynamically-registered') 200 print(' * extension function without a current rendering context.') 201 print(' */') 202 for i in range(1, 100): 203 print(' TABLE_ENTRY(Unused),') 204 205 print('};') 206 print('#endif /* DISPATCH_TABLE_NAME */') 207 print('') 208 return 209 210 211 def printAliasedTable(self, api): 212 print(""" 213/* 214 * This is just used to silence compiler warnings. 215 * We list the functions which are not otherwise used. 216 */ 217#ifdef UNUSED_TABLE_NAME 218_glapi_proc UNUSED_TABLE_NAME[] = {""") 219 220 normal_entries = [] 221 proto_entries = [] 222 for f in api.functionIterateByOffset(): 223 normal_ents, proto_ents = self.classifyEntryPoints(f) 224 225 # exclude f.name 226 if f.name in normal_ents: 227 normal_ents.remove(f.name) 228 elif f.name in proto_ents: 229 proto_ents.remove(f.name) 230 231 normal_ents = [f.static_name(ent) for ent in normal_ents] 232 proto_ents = [f.static_name(ent) for ent in proto_ents] 233 234 normal_entries.extend(normal_ents) 235 proto_entries.extend(proto_ents) 236 237 print('#ifndef _GLAPI_SKIP_NORMAL_ENTRY_POINTS') 238 for ent in normal_entries: 239 print(' TABLE_ENTRY(%s),' % (ent)) 240 print('#endif /* _GLAPI_SKIP_NORMAL_ENTRY_POINTS */') 241 print('#ifndef _GLAPI_SKIP_PROTO_ENTRY_POINTS') 242 for ent in proto_entries: 243 print(' TABLE_ENTRY(%s),' % (ent)) 244 print('#endif /* _GLAPI_SKIP_PROTO_ENTRY_POINTS */') 245 246 print('};') 247 print('#endif /*UNUSED_TABLE_NAME*/') 248 print('') 249 return 250 251 252 def classifyEntryPoints(self, func): 253 normal_names = [] 254 normal_stubs = [] 255 proto_names = [] 256 proto_stubs = [] 257 # classify the entry points 258 for name in func.entry_points: 259 if func.has_different_protocol(name): 260 if func.is_static_entry_point(name): 261 proto_names.append(name) 262 else: 263 proto_stubs.append(name) 264 else: 265 if func.is_static_entry_point(name): 266 normal_names.append(name) 267 else: 268 normal_stubs.append(name) 269 # there can be at most one stub for a function 270 if normal_stubs: 271 normal_names.append(normal_stubs[0]) 272 elif proto_stubs: 273 proto_names.append(proto_stubs[0]) 274 275 return (normal_names, proto_names) 276 277 def printBody(self, api): 278 normal_entry_points = [] 279 proto_entry_points = [] 280 for func in api.functionIterateByOffset(): 281 normal_ents, proto_ents = self.classifyEntryPoints(func) 282 normal_entry_points.append((func, normal_ents)) 283 proto_entry_points.append((func, proto_ents)) 284 285 print('#ifndef _GLAPI_SKIP_NORMAL_ENTRY_POINTS') 286 print('') 287 for func, ents in normal_entry_points: 288 for ent in ents: 289 self.printFunction(func, ent) 290 print('') 291 print('#endif /* _GLAPI_SKIP_NORMAL_ENTRY_POINTS */') 292 print('') 293 print('/* these entry points might require different protocols */') 294 print('#ifndef _GLAPI_SKIP_PROTO_ENTRY_POINTS') 295 print('') 296 for func, ents in proto_entry_points: 297 for ent in ents: 298 self.printFunction(func, ent) 299 print('') 300 print('#endif /* _GLAPI_SKIP_PROTO_ENTRY_POINTS */') 301 print('') 302 303 self.printInitDispatch(api) 304 self.printAliasedTable(api) 305 return 306 307 308def _parser(): 309 """Parser arguments and return a namespace.""" 310 parser = argparse.ArgumentParser() 311 parser.add_argument('-f', 312 metavar='<input file name>', 313 dest='filename', 314 default="gl_API.xml", 315 help="An XML file describing the API.") 316 parser.add_argument('-c', 317 action='store_true', 318 dest='es', 319 help="Enable OpenGL ES compatibility") 320 return parser.parse_args() 321 322 323def main(): 324 """Main function.""" 325 args = _parser() 326 327 api = gl_XML.parse_GL_API(args.filename, glX_XML.glx_item_factory()) 328 329 printer = PrintGlOffsets(args.es) 330 printer.Print(api) 331 332 333if __name__ == '__main__': 334 main() 335