]> git.cworth.org Git - apitrace/blob - glretrace.py
Universal config.h for snappy.
[apitrace] / glretrace.py
1 ##########################################################################
2 #
3 # Copyright 2010 VMware, Inc.
4 # All Rights Reserved.
5 #
6 # Permission is hereby granted, free of charge, to any person obtaining a copy
7 # of this software and associated documentation files (the "Software"), to deal
8 # in the Software without restriction, including without limitation the rights
9 # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 # copies of the Software, and to permit persons to whom the Software is
11 # furnished to do so, subject to the following conditions:
12 #
13 # The above copyright notice and this permission notice shall be included in
14 # all copies or substantial portions of the 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 NONINFRINGEMENT. IN NO EVENT SHALL THE
19 # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22 # THE SOFTWARE.
23 #
24 ##########################################################################/
25
26
27 """GL retracer generator."""
28
29
30 import specs.stdapi as stdapi
31 import specs.glapi as glapi
32 from retrace import Retracer
33
34
35 class GlRetracer(Retracer):
36
37     table_name = 'glretrace::gl_callbacks'
38
39     def retrace_function(self, function):
40         Retracer.retrace_function(self, function)
41
42     array_pointer_function_names = set((
43         "glVertexPointer",
44         "glNormalPointer",
45         "glColorPointer",
46         "glIndexPointer",
47         "glTexCoordPointer",
48         "glEdgeFlagPointer",
49         "glFogCoordPointer",
50         "glSecondaryColorPointer",
51
52         "glInterleavedArrays",
53
54         "glVertexPointerEXT",
55         "glNormalPointerEXT",
56         "glColorPointerEXT",
57         "glIndexPointerEXT",
58         "glTexCoordPointerEXT",
59         "glEdgeFlagPointerEXT",
60         "glFogCoordPointerEXT",
61         "glSecondaryColorPointerEXT",
62
63         "glVertexAttribPointer",
64         "glVertexAttribPointerARB",
65         "glVertexAttribPointerNV",
66         "glVertexAttribIPointer",
67         "glVertexAttribIPointerEXT",
68         "glVertexAttribLPointer",
69         "glVertexAttribLPointerEXT",
70         
71         #"glMatrixIndexPointerARB",
72     ))
73
74     draw_array_function_names = set([
75         "glDrawArrays",
76         "glDrawArraysEXT",
77         "glDrawArraysIndirect",
78         "glDrawArraysInstanced",
79         "glDrawArraysInstancedARB",
80         "glDrawArraysInstancedEXT",
81         "glDrawMeshArraysSUN",
82         "glMultiDrawArrays",
83         "glMultiDrawArraysEXT",
84         "glMultiModeDrawArraysIBM",
85     ])
86
87     draw_elements_function_names = set([
88         "glDrawElements",
89         "glDrawElementsBaseVertex",
90         "glDrawElementsIndirect",
91         "glDrawElementsInstanced",
92         "glDrawElementsInstancedARB",
93         "glDrawElementsInstancedBaseVertex",
94         "glDrawElementsInstancedEXT",
95         "glDrawRangeElements",
96         "glDrawRangeElementsBaseVertex",
97         "glDrawRangeElementsEXT",
98         "glMultiDrawElements",
99         "glMultiDrawElementsBaseVertex",
100         "glMultiDrawElementsEXT",
101         "glMultiModeDrawElementsIBM",
102     ])
103
104     draw_indirect_function_names = set([
105         "glDrawArraysIndirect",
106         "glDrawElementsIndirect",
107     ])
108
109     misc_draw_function_names = set([
110         "glClear",
111         "glEnd",
112         "glDrawPixels",
113         "glBlitFramebuffer",
114         "glBlitFramebufferEXT",
115     ])
116
117     bind_framebuffer_function_names = set([
118         "glBindFramebuffer",
119         "glBindFramebufferARB",
120         "glBindFramebufferEXT",
121     ])
122
123     # Names of the functions that can pack into the current pixel buffer
124     # object.  See also the ARB_pixel_buffer_object specification.
125     pack_function_names = set([
126         'glGetCompressedTexImage',
127         'glGetConvolutionFilter',
128         'glGetHistogram',
129         'glGetMinmax',
130         'glGetPixelMapfv',
131         'glGetPixelMapuiv',
132         'glGetPixelMapusv',
133         'glGetPolygonStipple',
134         'glGetSeparableFilter,',
135         'glGetTexImage',
136         'glReadPixels',
137         'glGetnCompressedTexImageARB',
138         'glGetnConvolutionFilterARB',
139         'glGetnHistogramARB',
140         'glGetnMinmaxARB',
141         'glGetnPixelMapfvARB',
142         'glGetnPixelMapuivARB',
143         'glGetnPixelMapusvARB',
144         'glGetnPolygonStippleARB',
145         'glGetnSeparableFilterARB',
146         'glGetnTexImageARB',
147         'glReadnPixelsARB',
148     ])
149
150     def retrace_function_body(self, function):
151         is_array_pointer = function.name in self.array_pointer_function_names
152         is_draw_array = function.name in self.draw_array_function_names
153         is_draw_elements = function.name in self.draw_elements_function_names
154         is_misc_draw = function.name in self.misc_draw_function_names
155
156         if is_array_pointer or is_draw_array or is_draw_elements:
157             print '    if (glretrace::parser.version < 1) {'
158
159             if is_array_pointer or is_draw_array:
160                 print '        GLint __array_buffer = 0;'
161                 print '        glGetIntegerv(GL_ARRAY_BUFFER_BINDING, &__array_buffer);'
162                 print '        if (!__array_buffer) {'
163                 self.fail_function(function)
164                 print '        }'
165
166             if is_draw_elements:
167                 print '        GLint __element_array_buffer = 0;'
168                 print '        glGetIntegerv(GL_ELEMENT_ARRAY_BUFFER_BINDING, &__element_array_buffer);'
169                 print '        if (!__element_array_buffer) {'
170                 self.fail_function(function)
171                 print '        }'
172             
173             print '    }'
174
175         # When no pack buffer object is bound, the pack functions are no-ops.
176         if function.name in self.pack_function_names:
177             print '    GLint __pack_buffer = 0;'
178             print '    glGetIntegerv(GL_PIXEL_PACK_BUFFER_BINDING, &__pack_buffer);'
179             print '    if (!__pack_buffer) {'
180             if function.name == 'glReadPixels':
181                 print '    glFinish();'
182                 print '    if (glretrace::snapshot_frequency == glretrace::FREQUENCY_FRAME ||'
183                 print '        glretrace::snapshot_frequency == glretrace::FREQUENCY_FRAMEBUFFER) {'
184                 print '        glretrace::snapshot(call.no);'
185                 print '    }'
186             print '        return;'
187             print '    }'
188
189         # Pre-snapshots
190         if function.name in self.bind_framebuffer_function_names:
191             print '    if (glretrace::snapshot_frequency == glretrace::FREQUENCY_FRAMEBUFFER) {'
192             print '        glretrace::snapshot(call.no - 1);'
193             print '    }'
194         if function.name == 'glFrameTerminatorGREMEDY':
195             print '    glretrace::frame_complete(call.no);'
196             return
197
198         Retracer.retrace_function_body(self, function)
199
200         # Post-snapshots
201         if function.name in ('glFlush', 'glFinish'):
202             print '    if (!glretrace::double_buffer) {'
203             print '        glretrace::frame_complete(call.no);'
204             print '    }'
205         if is_draw_array or is_draw_elements or is_misc_draw:
206             print '    if (glretrace::snapshot_frequency == glretrace::FREQUENCY_DRAW) {'
207             print '        glretrace::snapshot(call.no);'
208             print '    }'
209
210
211     def call_function(self, function):
212         # Infer the drawable size from GL calls
213         if function.name == "glViewport":
214             print '    glretrace::updateDrawable(x + width, y + height);'
215         if function.name in ('glBlitFramebuffer', 'glBlitFramebufferEXT'):
216             # Some applications do all their rendering in a framebuffer, and
217             # then just blit to the drawable without ever calling glViewport.
218             print '    glretrace::updateDrawable(std::max(dstX0, dstX1), std::max(dstY0, dstY1));'
219
220         if function.name == "glEnd":
221             print '    glretrace::insideGlBeginEnd = false;'
222
223         if function.name == 'memcpy':
224             print '    if (!dest || !src || !n) return;'
225         
226         Retracer.call_function(self, function)
227
228         # Error checking
229         if function.name == "glBegin":
230             print '    glretrace::insideGlBeginEnd = true;'
231         elif function.name.startswith('gl'):
232             # glGetError is not allowed inside glBegin/glEnd
233             print '    if (!glretrace::benchmark && !glretrace::insideGlBeginEnd) {'
234             print '        glretrace::checkGlError(call);'
235             if function.name in ('glProgramStringARB', 'glProgramStringNV'):
236                 print r'        GLint error_position = -1;'
237                 print r'        glGetIntegerv(GL_PROGRAM_ERROR_POSITION_ARB, &error_position);'
238                 print r'        if (error_position != -1) {'
239                 print r'            const char *error_string = (const char *)glGetString(GL_PROGRAM_ERROR_STRING_ARB);'
240                 print r'            std::cerr << call.no << ": warning: " << error_string << "\n";'
241                 print r'        }'
242             if function.name == 'glCompileShader':
243                 print r'        GLint compile_status = 0;'
244                 print r'        glGetShaderiv(shader, GL_COMPILE_STATUS, &compile_status);'
245                 print r'        if (!compile_status) {'
246                 print r'             GLint info_log_length = 0;'
247                 print r'             glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &info_log_length);'
248                 print r'             GLchar *infoLog = new GLchar[info_log_length];'
249                 print r'             glGetShaderInfoLog(shader, info_log_length, NULL, infoLog);'
250                 print r'             std::cerr << call.no << ": warning: " << infoLog << "\n";'
251                 print r'             delete [] infoLog;'
252                 print r'        }'
253             if function.name == 'glLinkProgram':
254                 print r'        GLint link_status = 0;'
255                 print r'        glGetProgramiv(program, GL_LINK_STATUS, &link_status);'
256                 print r'        if (!link_status) {'
257                 print r'             GLint info_log_length = 0;'
258                 print r'             glGetProgramiv(program, GL_INFO_LOG_LENGTH, &info_log_length);'
259                 print r'             GLchar *infoLog = new GLchar[info_log_length];'
260                 print r'             glGetProgramInfoLog(program, info_log_length, NULL, infoLog);'
261                 print r'             std::cerr << call.no << ": warning: " << infoLog << "\n";'
262                 print r'             delete [] infoLog;'
263                 print r'        }'
264             if function.name == 'glCompileShaderARB':
265                 print r'        GLint compile_status = 0;'
266                 print r'        glGetObjectParameterivARB(shaderObj, GL_OBJECT_COMPILE_STATUS_ARB, &compile_status);'
267                 print r'        if (!compile_status) {'
268                 print r'             GLint info_log_length = 0;'
269                 print r'             glGetObjectParameterivARB(shaderObj, GL_OBJECT_INFO_LOG_LENGTH_ARB, &info_log_length);'
270                 print r'             GLchar *infoLog = new GLchar[info_log_length];'
271                 print r'             glGetInfoLogARB(shaderObj, info_log_length, NULL, infoLog);'
272                 print r'             std::cerr << call.no << ": warning: " << infoLog << "\n";'
273                 print r'             delete [] infoLog;'
274                 print r'        }'
275             if function.name == 'glLinkProgramARB':
276                 print r'        GLint link_status = 0;'
277                 print r'        glGetObjectParameterivARB(programObj, GL_OBJECT_LINK_STATUS_ARB, &link_status);'
278                 print r'        if (!link_status) {'
279                 print r'             GLint info_log_length = 0;'
280                 print r'             glGetObjectParameterivARB(programObj, GL_OBJECT_INFO_LOG_LENGTH_ARB, &info_log_length);'
281                 print r'             GLchar *infoLog = new GLchar[info_log_length];'
282                 print r'             glGetInfoLogARB(programObj, info_log_length, NULL, infoLog);'
283                 print r'             std::cerr << call.no << ": warning: " << infoLog << "\n";'
284                 print r'             delete [] infoLog;'
285                 print r'        }'
286             if function.name in ('glMapBuffer', 'glMapBufferARB', 'glMapBufferRange', 'glMapNamedBufferEXT', 'glMapNamedBufferRangeEXT'):
287                 print r'        if (!__result) {'
288                 print r'             std::cerr << call.no << ": warning: failed to map buffer\n";'
289                 print r'        }'
290             if function.name in ('glGetAttribLocation', 'glGetAttribLocationARB'):
291                 print r'    GLint __orig_result = call.ret->toSInt();'
292                 print r'    if (__result != __orig_result) {'
293                 print r'        std::cerr << call.no << ": warning: vertex attrib location mismatch " << __orig_result << " -> " << __result << "\n";'
294                 print r'    }'
295             if function.name in ('glCheckFramebufferStatus', 'glCheckFramebufferStatusEXT', 'glCheckNamedFramebufferStatusEXT'):
296                 print r'    GLint __orig_result = call.ret->toSInt();'
297                 print r'    if (__orig_result == GL_FRAMEBUFFER_COMPLETE &&'
298                 print r'        __result != GL_FRAMEBUFFER_COMPLETE) {'
299                 print r'        std::cerr << call.no << ": warning: incomplete framebuffer (" << glstate::enumToString(__result) << ")\n";'
300                 print r'    }'
301             print '    }'
302
303     def extract_arg(self, function, arg, arg_type, lvalue, rvalue):
304         if function.name in self.array_pointer_function_names and arg.name == 'pointer':
305             print '    %s = static_cast<%s>(%s.toPointer(true));' % (lvalue, arg_type, rvalue)
306             return
307
308         if function.name in self.draw_elements_function_names and arg.name == 'indices' or\
309            function.name in self.draw_indirect_function_names and arg.name == 'indirect':
310             self.extract_opaque_arg(function, arg, arg_type, lvalue, rvalue)
311             return
312
313         # Handle pointer with offsets into the current pack pixel buffer
314         # object.
315         if function.name in self.pack_function_names and arg.output:
316             self.extract_opaque_arg(function, arg, arg_type, lvalue, rvalue)
317             return
318
319         if arg.type is glapi.GLlocation \
320            and 'program' not in [arg.name for arg in function.args]:
321             print '    GLint program = -1;'
322             print '    glGetIntegerv(GL_CURRENT_PROGRAM, &program);'
323         
324         if arg.type is glapi.GLlocationARB \
325            and 'programObj' not in [arg.name for arg in function.args]:
326             print '    GLhandleARB programObj = glGetHandleARB(GL_PROGRAM_OBJECT_ARB);'
327
328         Retracer.extract_arg(self, function, arg, arg_type, lvalue, rvalue)
329
330         # Don't try to use more samples than the implementation supports
331         if arg.name == 'samples':
332             assert arg.type is glapi.GLsizei
333             print '    GLint max_samples = 0;'
334             print '    glGetIntegerv(GL_MAX_SAMPLES, &max_samples);'
335             print '    if (samples > max_samples) {'
336             print '        samples = max_samples;'
337             print '    }'
338
339
340 if __name__ == '__main__':
341     print r'''
342 #include <string.h>
343
344 #include "glproc.hpp"
345 #include "glretrace.hpp"
346 #include "glstate.hpp"
347
348
349 '''
350     api = glapi.glapi
351     api.add_function(glapi.memcpy)
352     retracer = GlRetracer()
353     retracer.retrace_api(api)