1848b8605Smrg
2848b8605Smrg# (C) Copyright IBM Corporation 2004, 2005
3848b8605Smrg# All Rights Reserved.
4848b8605Smrg#
5848b8605Smrg# Permission is hereby granted, free of charge, to any person obtaining a
6848b8605Smrg# copy of this software and associated documentation files (the "Software"),
7848b8605Smrg# to deal in the Software without restriction, including without limitation
8848b8605Smrg# on the rights to use, copy, modify, merge, publish, distribute, sub
9848b8605Smrg# license, and/or sell copies of the Software, and to permit persons to whom
10848b8605Smrg# the Software is furnished to do so, subject to the following conditions:
11848b8605Smrg#
12848b8605Smrg# The above copyright notice and this permission notice (including the next
13848b8605Smrg# paragraph) shall be included in all copies or substantial portions of the
14848b8605Smrg# Software.
15848b8605Smrg#
16848b8605Smrg# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17848b8605Smrg# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18848b8605Smrg# FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.  IN NO EVENT SHALL
19848b8605Smrg# IBM AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20848b8605Smrg# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
21848b8605Smrg# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
22848b8605Smrg# IN THE SOFTWARE.
23848b8605Smrg#
24848b8605Smrg# Authors:
25848b8605Smrg#    Ian Romanick <idr@us.ibm.com>
26848b8605Smrg
27b8e80941Smrgfrom __future__ import print_function
28b8e80941Smrg
29b8e80941Smrgimport argparse
30b8e80941Smrg
31848b8605Smrgimport gl_XML, glX_XML
32848b8605Smrgimport license
33848b8605Smrg
34848b8605Smrgclass PrintGlOffsets(gl_XML.gl_print_base):
35848b8605Smrg    def __init__(self, es=False):
36848b8605Smrg        gl_XML.gl_print_base.__init__(self)
37848b8605Smrg
38848b8605Smrg        self.name = "gl_apitemp.py (from Mesa)"
39848b8605Smrg        self.license = license.bsd_license_template % ( \
40848b8605Smrg"""Copyright (C) 1999-2001  Brian Paul   All Rights Reserved.
41848b8605Smrg(C) Copyright IBM Corporation 2004""", "BRIAN PAUL, IBM")
42848b8605Smrg
43848b8605Smrg        self.es = es
44848b8605Smrg
45848b8605Smrg        self.undef_list.append( "KEYWORD1" )
46848b8605Smrg        self.undef_list.append( "KEYWORD1_ALT" )
47848b8605Smrg        self.undef_list.append( "KEYWORD2" )
48848b8605Smrg        self.undef_list.append( "NAME" )
49848b8605Smrg        self.undef_list.append( "DISPATCH" )
50848b8605Smrg        self.undef_list.append( "RETURN_DISPATCH" )
51848b8605Smrg        self.undef_list.append( "DISPATCH_TABLE_NAME" )
52848b8605Smrg        self.undef_list.append( "UNUSED_TABLE_NAME" )
53848b8605Smrg        self.undef_list.append( "TABLE_ENTRY" )
54848b8605Smrg
55848b8605Smrg
56848b8605Smrg    def printFunction(self, f, name):
57848b8605Smrg        p_string = ""
58848b8605Smrg        o_string = ""
59848b8605Smrg        t_string = ""
60848b8605Smrg        comma = ""
61848b8605Smrg
62848b8605Smrg        if f.is_static_entry_point(name):
63848b8605Smrg            keyword = "KEYWORD1"
64848b8605Smrg        else:
65848b8605Smrg            keyword = "KEYWORD1_ALT"
66848b8605Smrg
67848b8605Smrg        n = f.static_name(name)
68848b8605Smrg
69848b8605Smrg        silence = ''
70848b8605Smrg        space = ''
71848b8605Smrg        for p in f.parameterIterator(name):
72848b8605Smrg            if p.is_padding:
73848b8605Smrg                continue
74848b8605Smrg
75848b8605Smrg            if p.is_pointer():
76848b8605Smrg                cast = "(const void *) "
77848b8605Smrg            else:
78848b8605Smrg                cast = ""
79848b8605Smrg
80848b8605Smrg            t_string = t_string + comma + p.format_string()
81848b8605Smrg            p_string = p_string + comma + p.name
82848b8605Smrg            o_string = o_string + comma + cast + p.name
83848b8605Smrg            comma = ", "
84848b8605Smrg
85848b8605Smrg            silence += "%s(void) %s;" % (space, p.name);
86848b8605Smrg            space = ' '
87848b8605Smrg
88848b8605Smrg
89848b8605Smrg        if f.return_type != 'void':
90848b8605Smrg            dispatch = "RETURN_DISPATCH"
91848b8605Smrg        else:
92848b8605Smrg            dispatch = "DISPATCH"
93848b8605Smrg
94848b8605Smrg        need_proto = False
95848b8605Smrg        if not f.is_static_entry_point(name):
96848b8605Smrg            need_proto = True
97848b8605Smrg        elif self.es:
98848b8605Smrg            cat, num = api.get_category_for_name(name)
99848b8605Smrg            if (cat.startswith("es") or cat.startswith("GL_OES")):
100848b8605Smrg                need_proto = True
101848b8605Smrg        if need_proto:
102b8e80941Smrg            print('%s %s KEYWORD2 NAME(%s)(%s);' % (keyword, f.return_type, n, f.get_parameter_string(name)))
103b8e80941Smrg            print('')
104848b8605Smrg
105b8e80941Smrg        print('%s %s KEYWORD2 NAME(%s)(%s)' % (keyword, f.return_type, n, f.get_parameter_string(name)))
106b8e80941Smrg        print('{')
107848b8605Smrg        if silence:
108b8e80941Smrg            print('    %s' % (silence))
109848b8605Smrg        if p_string == "":
110b8e80941Smrg            print('   %s(%s, (), (F, "gl%s();\\n"));' \
111b8e80941Smrg                    % (dispatch, f.name, name))
112848b8605Smrg        else:
113b8e80941Smrg            print('   %s(%s, (%s), (F, "gl%s(%s);\\n", %s));' \
114b8e80941Smrg                    % (dispatch, f.name, p_string, name, t_string, o_string))
115b8e80941Smrg        print('}')
116b8e80941Smrg        print('')
117848b8605Smrg        return
118848b8605Smrg
119848b8605Smrg    def printRealHeader(self):
120b8e80941Smrg        print('')
121848b8605Smrg        self.printVisibility( "HIDDEN", "hidden" )
122b8e80941Smrg        print("""
123848b8605Smrg/*
124848b8605Smrg * This file is a template which generates the OpenGL API entry point
125848b8605Smrg * functions.  It should be included by a .c file which first defines
126848b8605Smrg * the following macros:
127848b8605Smrg *   KEYWORD1 - usually nothing, but might be __declspec(dllexport) on Win32
128848b8605Smrg *   KEYWORD2 - usually nothing, but might be __stdcall on Win32
129848b8605Smrg *   NAME(n)  - builds the final function name (usually add "gl" prefix)
130848b8605Smrg *   DISPATCH(func, args, msg) - code to do dispatch of named function.
131848b8605Smrg *                               msg is a printf-style debug message.
132848b8605Smrg *   RETURN_DISPATCH(func, args, msg) - code to do dispatch with a return value
133848b8605Smrg *
134848b8605Smrg * Here is an example which generates the usual OpenGL functions:
135848b8605Smrg *   #define KEYWORD1
136848b8605Smrg *   #define KEYWORD2
137848b8605Smrg *   #define NAME(func)  gl##func
138b8e80941Smrg *   #define DISPATCH(func, args, msg)                             \\
139b8e80941Smrg *          struct _glapi_table *dispatch = CurrentClientDispatch; \\
140848b8605Smrg *          (*dispatch->func) args
141b8e80941Smrg *   #define RETURN DISPATCH(func, args, msg)                      \\
142b8e80941Smrg *          struct _glapi_table *dispatch = CurrentClientDispatch; \\
143848b8605Smrg *          return (*dispatch->func) args
144848b8605Smrg *
145848b8605Smrg */
146848b8605Smrg
147848b8605Smrg
148848b8605Smrg#if defined( NAME )
149848b8605Smrg#ifndef KEYWORD1
150848b8605Smrg#define KEYWORD1
151848b8605Smrg#endif
152848b8605Smrg
153848b8605Smrg#ifndef KEYWORD1_ALT
154848b8605Smrg#define KEYWORD1_ALT HIDDEN
155848b8605Smrg#endif
156848b8605Smrg
157848b8605Smrg#ifndef KEYWORD2
158848b8605Smrg#define KEYWORD2
159848b8605Smrg#endif
160848b8605Smrg
161848b8605Smrg#ifndef DISPATCH
162848b8605Smrg#error DISPATCH must be defined
163848b8605Smrg#endif
164848b8605Smrg
165848b8605Smrg#ifndef RETURN_DISPATCH
166848b8605Smrg#error RETURN_DISPATCH must be defined
167848b8605Smrg#endif
168848b8605Smrg
169b8e80941Smrg""")
170848b8605Smrg        return
171848b8605Smrg
172848b8605Smrg
173848b8605Smrg
174848b8605Smrg    def printInitDispatch(self, api):
175b8e80941Smrg        print("""
176848b8605Smrg#endif /* defined( NAME ) */
177848b8605Smrg
178848b8605Smrg/*
179848b8605Smrg * This is how a dispatch table can be initialized with all the functions
180848b8605Smrg * we generated above.
181848b8605Smrg */
182848b8605Smrg#ifdef DISPATCH_TABLE_NAME
183848b8605Smrg
184848b8605Smrg#ifndef TABLE_ENTRY
185848b8605Smrg#error TABLE_ENTRY must be defined
186848b8605Smrg#endif
187848b8605Smrg
188848b8605Smrg#ifdef _GLAPI_SKIP_NORMAL_ENTRY_POINTS
189848b8605Smrg#error _GLAPI_SKIP_NORMAL_ENTRY_POINTS must not be defined
190848b8605Smrg#endif
191848b8605Smrg
192b8e80941Smrg_glapi_proc DISPATCH_TABLE_NAME[] = {""")
193848b8605Smrg        for f in api.functionIterateByOffset():
194b8e80941Smrg            print('   TABLE_ENTRY(%s),' % (f.dispatch_name()))
195848b8605Smrg
196b8e80941Smrg        print('   /* A whole bunch of no-op functions.  These might be called')
197b8e80941Smrg        print('    * when someone tries to call a dynamically-registered')
198b8e80941Smrg        print('    * extension function without a current rendering context.')
199b8e80941Smrg        print('    */')
200848b8605Smrg        for i in range(1, 100):
201b8e80941Smrg            print('   TABLE_ENTRY(Unused),')
202848b8605Smrg
203b8e80941Smrg        print('};')
204b8e80941Smrg        print('#endif /* DISPATCH_TABLE_NAME */')
205b8e80941Smrg        print('')
206848b8605Smrg        return
207848b8605Smrg
208848b8605Smrg
209848b8605Smrg    def printAliasedTable(self, api):
210b8e80941Smrg        print("""
211848b8605Smrg/*
212848b8605Smrg * This is just used to silence compiler warnings.
213848b8605Smrg * We list the functions which are not otherwise used.
214848b8605Smrg */
215848b8605Smrg#ifdef UNUSED_TABLE_NAME
216b8e80941Smrg_glapi_proc UNUSED_TABLE_NAME[] = {""")
217848b8605Smrg
218848b8605Smrg        normal_entries = []
219848b8605Smrg        proto_entries = []
220848b8605Smrg        for f in api.functionIterateByOffset():
221848b8605Smrg            normal_ents, proto_ents = self.classifyEntryPoints(f)
222848b8605Smrg
223848b8605Smrg            # exclude f.name
224848b8605Smrg            if f.name in normal_ents:
225848b8605Smrg                normal_ents.remove(f.name)
226848b8605Smrg            elif f.name in proto_ents:
227848b8605Smrg                proto_ents.remove(f.name)
228848b8605Smrg
229848b8605Smrg            normal_ents = [f.static_name(ent) for ent in normal_ents]
230848b8605Smrg            proto_ents = [f.static_name(ent) for ent in proto_ents]
231848b8605Smrg
232848b8605Smrg            normal_entries.extend(normal_ents)
233848b8605Smrg            proto_entries.extend(proto_ents)
234848b8605Smrg
235b8e80941Smrg        print('#ifndef _GLAPI_SKIP_NORMAL_ENTRY_POINTS')
236848b8605Smrg        for ent in normal_entries:
237b8e80941Smrg            print('   TABLE_ENTRY(%s),' % (ent))
238b8e80941Smrg        print('#endif /* _GLAPI_SKIP_NORMAL_ENTRY_POINTS */')
239b8e80941Smrg        print('#ifndef _GLAPI_SKIP_PROTO_ENTRY_POINTS')
240848b8605Smrg        for ent in proto_entries:
241b8e80941Smrg            print('   TABLE_ENTRY(%s),' % (ent))
242b8e80941Smrg        print('#endif /* _GLAPI_SKIP_PROTO_ENTRY_POINTS */')
243848b8605Smrg
244b8e80941Smrg        print('};')
245b8e80941Smrg        print('#endif /*UNUSED_TABLE_NAME*/')
246b8e80941Smrg        print('')
247848b8605Smrg        return
248848b8605Smrg
249848b8605Smrg
250848b8605Smrg    def classifyEntryPoints(self, func):
251848b8605Smrg        normal_names = []
252848b8605Smrg        normal_stubs = []
253848b8605Smrg        proto_names = []
254848b8605Smrg        proto_stubs = []
255848b8605Smrg        # classify the entry points
256848b8605Smrg        for name in func.entry_points:
257848b8605Smrg            if func.has_different_protocol(name):
258848b8605Smrg                if func.is_static_entry_point(name):
259848b8605Smrg                    proto_names.append(name)
260848b8605Smrg                else:
261848b8605Smrg                    proto_stubs.append(name)
262848b8605Smrg            else:
263848b8605Smrg                if func.is_static_entry_point(name):
264848b8605Smrg                    normal_names.append(name)
265848b8605Smrg                else:
266848b8605Smrg                    normal_stubs.append(name)
267848b8605Smrg        # there can be at most one stub for a function
268848b8605Smrg        if normal_stubs:
269848b8605Smrg            normal_names.append(normal_stubs[0])
270848b8605Smrg        elif proto_stubs:
271848b8605Smrg            proto_names.append(proto_stubs[0])
272848b8605Smrg
273848b8605Smrg        return (normal_names, proto_names)
274848b8605Smrg
275848b8605Smrg    def printBody(self, api):
276848b8605Smrg        normal_entry_points = []
277848b8605Smrg        proto_entry_points = []
278848b8605Smrg        for func in api.functionIterateByOffset():
279848b8605Smrg            normal_ents, proto_ents = self.classifyEntryPoints(func)
280848b8605Smrg            normal_entry_points.append((func, normal_ents))
281848b8605Smrg            proto_entry_points.append((func, proto_ents))
282848b8605Smrg
283b8e80941Smrg        print('#ifndef _GLAPI_SKIP_NORMAL_ENTRY_POINTS')
284b8e80941Smrg        print('')
285848b8605Smrg        for func, ents in normal_entry_points:
286848b8605Smrg            for ent in ents:
287848b8605Smrg                self.printFunction(func, ent)
288b8e80941Smrg        print('')
289b8e80941Smrg        print('#endif /* _GLAPI_SKIP_NORMAL_ENTRY_POINTS */')
290b8e80941Smrg        print('')
291b8e80941Smrg        print('/* these entry points might require different protocols */')
292b8e80941Smrg        print('#ifndef _GLAPI_SKIP_PROTO_ENTRY_POINTS')
293b8e80941Smrg        print('')
294848b8605Smrg        for func, ents in proto_entry_points:
295848b8605Smrg            for ent in ents:
296848b8605Smrg                self.printFunction(func, ent)
297b8e80941Smrg        print('')
298b8e80941Smrg        print('#endif /* _GLAPI_SKIP_PROTO_ENTRY_POINTS */')
299b8e80941Smrg        print('')
300848b8605Smrg
301848b8605Smrg        self.printInitDispatch(api)
302848b8605Smrg        self.printAliasedTable(api)
303848b8605Smrg        return
304848b8605Smrg
305848b8605Smrg
306b8e80941Smrgdef _parser():
307b8e80941Smrg    """Parser arguments and return a namespace."""
308b8e80941Smrg    parser = argparse.ArgumentParser()
309b8e80941Smrg    parser.add_argument('-f',
310b8e80941Smrg                        metavar='<input file name>',
311b8e80941Smrg                        dest='filename',
312b8e80941Smrg                        default="gl_API.xml",
313b8e80941Smrg                        help="An XML file describing the API.")
314b8e80941Smrg    parser.add_argument('-c',
315b8e80941Smrg                        action='store_true',
316b8e80941Smrg                        dest='es',
317b8e80941Smrg                        help="Enable OpenGL ES compatibility")
318b8e80941Smrg    return parser.parse_args()
319848b8605Smrg
320848b8605Smrg
321b8e80941Smrgdef main():
322b8e80941Smrg    """Main function."""
323b8e80941Smrg    args = _parser()
324848b8605Smrg
325b8e80941Smrg    api = gl_XML.parse_GL_API(args.filename, glX_XML.glx_item_factory())
326848b8605Smrg
327b8e80941Smrg    printer = PrintGlOffsets(args.es)
328848b8605Smrg    printer.Print(api)
329b8e80941Smrg
330b8e80941Smrg
331b8e80941Smrgif __name__ == '__main__':
332b8e80941Smrg    main()
333