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