]> git.cworth.org Git - apitrace/blob - glretrace.py
Trace dwrite.dll too.
[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         "glDrawArraysInstancedBaseInstance",
82         "glDrawMeshArraysSUN",
83         "glMultiDrawArrays",
84         "glMultiDrawArraysEXT",
85         "glMultiModeDrawArraysIBM",
86     ])
87
88     draw_elements_function_names = set([
89         "glDrawElements",
90         "glDrawElementsBaseVertex",
91         "glDrawElementsIndirect",
92         "glDrawElementsInstanced",
93         "glDrawElementsInstancedARB",
94         "glDrawElementsInstancedEXT",
95         "glDrawElementsInstancedBaseVertex",
96         "glDrawElementsInstancedBaseInstance",
97         "glDrawElementsInstancedBaseVertexBaseInstance",
98         "glDrawRangeElements",
99         "glDrawRangeElementsEXT",
100         "glDrawRangeElementsBaseVertex",
101         "glMultiDrawElements",
102         "glMultiDrawElementsBaseVertex",
103         "glMultiDrawElementsEXT",
104         "glMultiModeDrawElementsIBM",
105     ])
106
107     draw_indirect_function_names = set([
108         "glDrawArraysIndirect",
109         "glDrawElementsIndirect",
110     ])
111
112     misc_draw_function_names = set([
113         "glClear",
114         "glEnd",
115         "glDrawPixels",
116         "glBlitFramebuffer",
117         "glBlitFramebufferEXT",
118     ])
119
120     bind_framebuffer_function_names = set([
121         "glBindFramebuffer",
122         "glBindFramebufferARB",
123         "glBindFramebufferEXT",
124     ])
125
126     # Names of the functions that can pack into the current pixel buffer
127     # object.  See also the ARB_pixel_buffer_object specification.
128     pack_function_names = set([
129         'glGetCompressedTexImage',
130         'glGetConvolutionFilter',
131         'glGetHistogram',
132         'glGetMinmax',
133         'glGetPixelMapfv',
134         'glGetPixelMapuiv',
135         'glGetPixelMapusv',
136         'glGetPolygonStipple',
137         'glGetSeparableFilter',
138         'glGetTexImage',
139         'glReadPixels',
140         'glGetnCompressedTexImageARB',
141         'glGetnConvolutionFilterARB',
142         'glGetnHistogramARB',
143         'glGetnMinmaxARB',
144         'glGetnPixelMapfvARB',
145         'glGetnPixelMapuivARB',
146         'glGetnPixelMapusvARB',
147         'glGetnPolygonStippleARB',
148         'glGetnSeparableFilterARB',
149         'glGetnTexImageARB',
150         'glReadnPixelsARB',
151     ])
152
153     def retrace_function_body(self, function):
154         is_array_pointer = function.name in self.array_pointer_function_names
155         is_draw_array = function.name in self.draw_array_function_names
156         is_draw_elements = function.name in self.draw_elements_function_names
157         is_misc_draw = function.name in self.misc_draw_function_names
158
159         if is_array_pointer or is_draw_array or is_draw_elements:
160             print '    if (glretrace::parser.version < 1) {'
161
162             if is_array_pointer or is_draw_array:
163                 print '        GLint __array_buffer = 0;'
164                 print '        glGetIntegerv(GL_ARRAY_BUFFER_BINDING, &__array_buffer);'
165                 print '        if (!__array_buffer) {'
166                 self.fail_function(function)
167                 print '        }'
168
169             if is_draw_elements:
170                 print '        GLint __element_array_buffer = 0;'
171                 print '        glGetIntegerv(GL_ELEMENT_ARRAY_BUFFER_BINDING, &__element_array_buffer);'
172                 print '        if (!__element_array_buffer) {'
173                 self.fail_function(function)
174                 print '        }'
175             
176             print '    }'
177
178         # When no pack buffer object is bound, the pack functions are no-ops.
179         if function.name in self.pack_function_names:
180             print '    GLint __pack_buffer = 0;'
181             print '    glGetIntegerv(GL_PIXEL_PACK_BUFFER_BINDING, &__pack_buffer);'
182             print '    if (!__pack_buffer) {'
183             if function.name == 'glReadPixels':
184                 print '    glFinish();'
185                 print '    if (glretrace::snapshot_frequency == glretrace::FREQUENCY_FRAME ||'
186                 print '        glretrace::snapshot_frequency == glretrace::FREQUENCY_FRAMEBUFFER) {'
187                 print '        glretrace::snapshot(call.no);'
188                 print '    }'
189             print '        return;'
190             print '    }'
191
192         # Pre-snapshots
193         if function.name in self.bind_framebuffer_function_names:
194             print '    if (glretrace::snapshot_frequency == glretrace::FREQUENCY_FRAMEBUFFER) {'
195             print '        glretrace::snapshot(call.no - 1);'
196             print '    }'
197         if function.name == 'glFrameTerminatorGREMEDY':
198             print '    glretrace::frame_complete(call.no);'
199             return
200
201         Retracer.retrace_function_body(self, function)
202
203         # Post-snapshots
204         if function.name in ('glFlush', 'glFinish'):
205             print '    if (!glretrace::double_buffer) {'
206             print '        glretrace::frame_complete(call.no);'
207             print '    }'
208         if is_draw_array or is_draw_elements or is_misc_draw:
209             print '    if (glretrace::snapshot_frequency == glretrace::FREQUENCY_DRAW) {'
210             print '        glretrace::snapshot(call.no);'
211             print '    }'
212
213
214     def call_function(self, function):
215         # Infer the drawable size from GL calls
216         if function.name == "glViewport":
217             print '    glretrace::updateDrawable(x + width, y + height);'
218         if function.name in ('glBlitFramebuffer', 'glBlitFramebufferEXT'):
219             # Some applications do all their rendering in a framebuffer, and
220             # then just blit to the drawable without ever calling glViewport.
221             print '    glretrace::updateDrawable(std::max(dstX0, dstX1), std::max(dstY0, dstY1));'
222
223         if function.name == "glEnd":
224             print '    glretrace::insideGlBeginEnd = false;'
225
226         if function.name == 'memcpy':
227             print '    if (!dest || !src || !n) return;'
228         
229         Retracer.call_function(self, function)
230
231         # Error checking
232         if function.name == "glBegin":
233             print '    glretrace::insideGlBeginEnd = true;'
234         elif function.name.startswith('gl'):
235             # glGetError is not allowed inside glBegin/glEnd
236             print '    if (!glretrace::benchmark && !glretrace::insideGlBeginEnd) {'
237             print '        glretrace::checkGlError(call);'
238             if function.name in ('glProgramStringARB', 'glProgramStringNV'):
239                 print r'        GLint error_position = -1;'
240                 print r'        glGetIntegerv(GL_PROGRAM_ERROR_POSITION_ARB, &error_position);'
241                 print r'        if (error_position != -1) {'
242                 print r'            const char *error_string = (const char *)glGetString(GL_PROGRAM_ERROR_STRING_ARB);'
243                 print r'            retrace::warning(call) << error_string << "\n";'
244                 print r'        }'
245             if function.name == 'glCompileShader':
246                 print r'        GLint compile_status = 0;'
247                 print r'        glGetShaderiv(shader, GL_COMPILE_STATUS, &compile_status);'
248                 print r'        if (!compile_status) {'
249                 print r'             GLint info_log_length = 0;'
250                 print r'             glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &info_log_length);'
251                 print r'             GLchar *infoLog = new GLchar[info_log_length];'
252                 print r'             glGetShaderInfoLog(shader, info_log_length, NULL, infoLog);'
253                 print r'             retrace::warning(call) << infoLog << "\n";'
254                 print r'             delete [] infoLog;'
255                 print r'        }'
256             if function.name == 'glLinkProgram':
257                 print r'        GLint link_status = 0;'
258                 print r'        glGetProgramiv(program, GL_LINK_STATUS, &link_status);'
259                 print r'        if (!link_status) {'
260                 print r'             GLint info_log_length = 0;'
261                 print r'             glGetProgramiv(program, GL_INFO_LOG_LENGTH, &info_log_length);'
262                 print r'             GLchar *infoLog = new GLchar[info_log_length];'
263                 print r'             glGetProgramInfoLog(program, info_log_length, NULL, infoLog);'
264                 print r'             retrace::warning(call) << infoLog << "\n";'
265                 print r'             delete [] infoLog;'
266                 print r'        }'
267             if function.name == 'glCompileShaderARB':
268                 print r'        GLint compile_status = 0;'
269                 print r'        glGetObjectParameterivARB(shaderObj, GL_OBJECT_COMPILE_STATUS_ARB, &compile_status);'
270                 print r'        if (!compile_status) {'
271                 print r'             GLint info_log_length = 0;'
272                 print r'             glGetObjectParameterivARB(shaderObj, GL_OBJECT_INFO_LOG_LENGTH_ARB, &info_log_length);'
273                 print r'             GLchar *infoLog = new GLchar[info_log_length];'
274                 print r'             glGetInfoLogARB(shaderObj, info_log_length, NULL, infoLog);'
275                 print r'             retrace::warning(call) << infoLog << "\n";'
276                 print r'             delete [] infoLog;'
277                 print r'        }'
278             if function.name == 'glLinkProgramARB':
279                 print r'        GLint link_status = 0;'
280                 print r'        glGetObjectParameterivARB(programObj, GL_OBJECT_LINK_STATUS_ARB, &link_status);'
281                 print r'        if (!link_status) {'
282                 print r'             GLint info_log_length = 0;'
283                 print r'             glGetObjectParameterivARB(programObj, GL_OBJECT_INFO_LOG_LENGTH_ARB, &info_log_length);'
284                 print r'             GLchar *infoLog = new GLchar[info_log_length];'
285                 print r'             glGetInfoLogARB(programObj, info_log_length, NULL, infoLog);'
286                 print r'             retrace::warning(call) << infoLog << "\n";'
287                 print r'             delete [] infoLog;'
288                 print r'        }'
289             if function.name in ('glMapBuffer', 'glMapBufferARB', 'glMapBufferRange', 'glMapNamedBufferEXT', 'glMapNamedBufferRangeEXT'):
290                 print r'        if (!__result) {'
291                 print r'             retrace::warning(call) << "failed to map buffer\n";'
292                 print r'        }'
293             if function.name in ('glGetAttribLocation', 'glGetAttribLocationARB'):
294                 print r'    GLint __orig_result = call.ret->toSInt();'
295                 print r'    if (__result != __orig_result) {'
296                 print r'        retrace::warning(call) << "vertex attrib location mismatch " << __orig_result << " -> " << __result << "\n";'
297                 print r'    }'
298             if function.name in ('glCheckFramebufferStatus', 'glCheckFramebufferStatusEXT', 'glCheckNamedFramebufferStatusEXT'):
299                 print r'    GLint __orig_result = call.ret->toSInt();'
300                 print r'    if (__orig_result == GL_FRAMEBUFFER_COMPLETE &&'
301                 print r'        __result != GL_FRAMEBUFFER_COMPLETE) {'
302                 print r'        retrace::warning(call) << "incomplete framebuffer (" << glstate::enumToString(__result) << ")\n";'
303                 print r'    }'
304             print '    }'
305
306     def extract_arg(self, function, arg, arg_type, lvalue, rvalue):
307         if function.name in self.array_pointer_function_names and arg.name == 'pointer':
308             print '    %s = static_cast<%s>(%s.toPointer(true));' % (lvalue, arg_type, rvalue)
309             return
310
311         if function.name in self.draw_elements_function_names and arg.name == 'indices' or\
312            function.name in self.draw_indirect_function_names and arg.name == 'indirect':
313             self.extract_opaque_arg(function, arg, arg_type, lvalue, rvalue)
314             return
315
316         # Handle pointer with offsets into the current pack pixel buffer
317         # object.
318         if function.name in self.pack_function_names and arg.output:
319             self.extract_opaque_arg(function, arg, arg_type, lvalue, rvalue)
320             return
321
322         if arg.type is glapi.GLlocation \
323            and 'program' not in [arg.name for arg in function.args]:
324             print '    GLint program = -1;'
325             print '    glGetIntegerv(GL_CURRENT_PROGRAM, &program);'
326         
327         if arg.type is glapi.GLlocationARB \
328            and 'programObj' not in [arg.name for arg in function.args]:
329             print '    GLhandleARB programObj = glGetHandleARB(GL_PROGRAM_OBJECT_ARB);'
330
331         Retracer.extract_arg(self, function, arg, arg_type, lvalue, rvalue)
332
333         # Don't try to use more samples than the implementation supports
334         if arg.name == 'samples':
335             assert arg.type is glapi.GLsizei
336             print '    GLint max_samples = 0;'
337             print '    glGetIntegerv(GL_MAX_SAMPLES, &max_samples);'
338             print '    if (samples > max_samples) {'
339             print '        samples = max_samples;'
340             print '    }'
341
342
343 if __name__ == '__main__':
344     print r'''
345 #include <string.h>
346
347 #include "glproc.hpp"
348 #include "glretrace.hpp"
349 #include "glstate.hpp"
350
351
352 '''
353     api = glapi.glapi
354     api.add_function(glapi.memcpy)
355     retracer = GlRetracer()
356     retracer.retrace_api(api)