]> git.cworth.org Git - apitrace/blob - glretrace.py
Fix block indentation.
[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 import specs.glesapi as glesapi
33 from retrace import Retracer
34
35
36 class GlRetracer(Retracer):
37
38     table_name = 'glretrace::gl_callbacks'
39
40     def retraceFunction(self, function):
41         Retracer.retraceFunction(self, function)
42
43     array_pointer_function_names = set((
44         "glVertexPointer",
45         "glNormalPointer",
46         "glColorPointer",
47         "glIndexPointer",
48         "glTexCoordPointer",
49         "glEdgeFlagPointer",
50         "glFogCoordPointer",
51         "glSecondaryColorPointer",
52
53         "glInterleavedArrays",
54
55         "glVertexPointerEXT",
56         "glNormalPointerEXT",
57         "glColorPointerEXT",
58         "glIndexPointerEXT",
59         "glTexCoordPointerEXT",
60         "glEdgeFlagPointerEXT",
61         "glFogCoordPointerEXT",
62         "glSecondaryColorPointerEXT",
63
64         "glVertexAttribPointer",
65         "glVertexAttribPointerARB",
66         "glVertexAttribPointerNV",
67         "glVertexAttribIPointer",
68         "glVertexAttribIPointerEXT",
69         "glVertexAttribLPointer",
70         "glVertexAttribLPointerEXT",
71         
72         #"glMatrixIndexPointerARB",
73     ))
74
75     draw_array_function_names = set([
76         "glDrawArrays",
77         "glDrawArraysEXT",
78         "glDrawArraysIndirect",
79         "glDrawArraysInstanced",
80         "glDrawArraysInstancedARB",
81         "glDrawArraysInstancedEXT",
82         "glDrawArraysInstancedBaseInstance",
83         "glDrawMeshArraysSUN",
84         "glMultiDrawArrays",
85         "glMultiDrawArraysEXT",
86         "glMultiModeDrawArraysIBM",
87     ])
88
89     draw_elements_function_names = set([
90         "glDrawElements",
91         "glDrawElementsBaseVertex",
92         "glDrawElementsIndirect",
93         "glDrawElementsInstanced",
94         "glDrawElementsInstancedARB",
95         "glDrawElementsInstancedEXT",
96         "glDrawElementsInstancedBaseVertex",
97         "glDrawElementsInstancedBaseInstance",
98         "glDrawElementsInstancedBaseVertexBaseInstance",
99         "glDrawRangeElements",
100         "glDrawRangeElementsEXT",
101         "glDrawRangeElementsBaseVertex",
102         "glMultiDrawElements",
103         "glMultiDrawElementsBaseVertex",
104         "glMultiDrawElementsEXT",
105         "glMultiModeDrawElementsIBM",
106     ])
107
108     draw_indirect_function_names = set([
109         "glDrawArraysIndirect",
110         "glDrawElementsIndirect",
111     ])
112
113     misc_draw_function_names = set([
114         "glCallList",
115         "glCallLists",
116         "glClear",
117         "glEnd",
118         "glDrawPixels",
119         "glBlitFramebuffer",
120         "glBlitFramebufferEXT",
121     ])
122
123     bind_framebuffer_function_names = set([
124         "glBindFramebuffer",
125         "glBindFramebufferEXT",
126         "glBindFramebufferOES",
127     ])
128
129     # Names of the functions that can pack into the current pixel buffer
130     # object.  See also the ARB_pixel_buffer_object specification.
131     pack_function_names = set([
132         'glGetCompressedTexImage',
133         'glGetConvolutionFilter',
134         'glGetHistogram',
135         'glGetMinmax',
136         'glGetPixelMapfv',
137         'glGetPixelMapuiv',
138         'glGetPixelMapusv',
139         'glGetPolygonStipple',
140         'glGetSeparableFilter',
141         'glGetTexImage',
142         'glReadPixels',
143         'glGetnCompressedTexImageARB',
144         'glGetnConvolutionFilterARB',
145         'glGetnHistogramARB',
146         'glGetnMinmaxARB',
147         'glGetnPixelMapfvARB',
148         'glGetnPixelMapuivARB',
149         'glGetnPixelMapusvARB',
150         'glGetnPolygonStippleARB',
151         'glGetnSeparableFilterARB',
152         'glGetnTexImageARB',
153         'glReadnPixelsARB',
154     ])
155
156     map_function_names = set([
157         'glMapBuffer',
158         'glMapBufferARB',
159         'glMapBufferOES',
160         'glMapBufferRange',
161         'glMapNamedBufferEXT',
162         'glMapNamedBufferRangeEXT'
163     ])
164
165     unmap_function_names = set([
166         'glUnmapBuffer',
167         'glUnmapBufferARB',
168         'glUnmapBufferOES',
169         'glUnmapNamedBufferEXT',
170     ])
171
172     def retraceFunctionBody(self, function):
173         is_array_pointer = function.name in self.array_pointer_function_names
174         is_draw_array = function.name in self.draw_array_function_names
175         is_draw_elements = function.name in self.draw_elements_function_names
176         is_misc_draw = function.name in self.misc_draw_function_names
177
178         if is_array_pointer or is_draw_array or is_draw_elements:
179             print '    if (glretrace::parser.version < 1) {'
180
181             if is_array_pointer or is_draw_array:
182                 print '        GLint __array_buffer = 0;'
183                 print '        glGetIntegerv(GL_ARRAY_BUFFER_BINDING, &__array_buffer);'
184                 print '        if (!__array_buffer) {'
185                 self.failFunction(function)
186                 print '        }'
187
188             if is_draw_elements:
189                 print '        GLint __element_array_buffer = 0;'
190                 print '        glGetIntegerv(GL_ELEMENT_ARRAY_BUFFER_BINDING, &__element_array_buffer);'
191                 print '        if (!__element_array_buffer) {'
192                 self.failFunction(function)
193                 print '        }'
194             
195             print '    }'
196
197         # When no pack buffer object is bound, the pack functions are no-ops.
198         if function.name in self.pack_function_names:
199             print '    GLint __pack_buffer = 0;'
200             print '    glGetIntegerv(GL_PIXEL_PACK_BUFFER_BINDING, &__pack_buffer);'
201             print '    if (!__pack_buffer) {'
202             print '        return;'
203             print '    }'
204
205         # Pre-snapshots
206         if function.name in self.bind_framebuffer_function_names:
207             print '    assert(call.flags & trace::CALL_FLAG_SWAP_RENDERTARGET);'
208         if function.name == 'glFrameTerminatorGREMEDY':
209             print '    glretrace::frame_complete(call);'
210             return
211
212         Retracer.retraceFunctionBody(self, function)
213
214         # Post-snapshots
215         if function.name in ('glFlush', 'glFinish'):
216             print '    if (!glretrace::double_buffer) {'
217             print '        glretrace::frame_complete(call);'
218             print '    }'
219         if is_draw_array or is_draw_elements or is_misc_draw:
220             print '    assert(call.flags & trace::CALL_FLAG_RENDER);'
221
222
223     def invokeFunction(self, function):
224         # Infer the drawable size from GL calls
225         if function.name == "glViewport":
226             print '    glretrace::updateDrawable(x + width, y + height);'
227         if function.name in ('glBlitFramebuffer', 'glBlitFramebufferEXT'):
228             # Some applications do all their rendering in a framebuffer, and
229             # then just blit to the drawable without ever calling glViewport.
230             print '    glretrace::updateDrawable(std::max(dstX0, dstX1), std::max(dstY0, dstY1));'
231
232         if function.name == "glEnd":
233             print '    glretrace::insideGlBeginEnd = false;'
234
235         if function.name.startswith('gl') and not function.name.startswith('glX'):
236             print r'    if (!glretrace::context && !glretrace::benchmark && !retrace::profiling) {'
237             print r'        retrace::warning(call) << "no current context\n";'
238             print r'    }'
239
240         if function.name == 'memcpy':
241             print '    if (!dest || !src || !n) return;'
242
243         # Destroy the buffer mapping
244         if function.name in self.unmap_function_names:
245             print r'        GLvoid *ptr = NULL;'
246             if function.name == 'glUnmapBuffer':
247                 print r'            glGetBufferPointerv(target, GL_BUFFER_MAP_POINTER, &ptr);'
248             elif function.name == 'glUnmapBufferARB':
249                 print r'            glGetBufferPointervARB(target, GL_BUFFER_MAP_POINTER_ARB, &ptr);'
250             elif function.name == 'glUnmapBufferOES':
251                 print r'            glGetBufferPointervOES(target, GL_BUFFER_MAP_POINTER_OES, &ptr);'
252             elif function.name == 'glUnmapNamedBufferEXT':
253                 print r'            glGetNamedBufferPointervEXT(buffer, GL_BUFFER_MAP_POINTER, &ptr);'
254             else:
255                 assert False
256             print r'        if (ptr) {'
257             print r'            retrace::delRegionByPointer(ptr);'
258             print r'        } else {'
259             print r'            retrace::warning(call) << "no current context\n";'
260             print r'        }'
261         
262         Retracer.invokeFunction(self, function)
263
264         # Error checking
265         if function.name == "glBegin":
266             print '    glretrace::insideGlBeginEnd = true;'
267         elif function.name.startswith('gl'):
268             # glGetError is not allowed inside glBegin/glEnd
269             print '    if (!glretrace::benchmark && !retrace::profiling && !glretrace::insideGlBeginEnd) {'
270             print '        glretrace::checkGlError(call);'
271             if function.name in ('glProgramStringARB', 'glProgramStringNV'):
272                 print r'        GLint error_position = -1;'
273                 print r'        glGetIntegerv(GL_PROGRAM_ERROR_POSITION_ARB, &error_position);'
274                 print r'        if (error_position != -1) {'
275                 print r'            const char *error_string = (const char *)glGetString(GL_PROGRAM_ERROR_STRING_ARB);'
276                 print r'            retrace::warning(call) << error_string << "\n";'
277                 print r'        }'
278             if function.name == 'glCompileShader':
279                 print r'        GLint compile_status = 0;'
280                 print r'        glGetShaderiv(shader, GL_COMPILE_STATUS, &compile_status);'
281                 print r'        if (!compile_status) {'
282                 print r'             GLint info_log_length = 0;'
283                 print r'             glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &info_log_length);'
284                 print r'             GLchar *infoLog = new GLchar[info_log_length];'
285                 print r'             glGetShaderInfoLog(shader, 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 == 'glLinkProgram':
290                 print r'        GLint link_status = 0;'
291                 print r'        glGetProgramiv(program, GL_LINK_STATUS, &link_status);'
292                 print r'        if (!link_status) {'
293                 print r'             GLint info_log_length = 0;'
294                 print r'             glGetProgramiv(program, GL_INFO_LOG_LENGTH, &info_log_length);'
295                 print r'             GLchar *infoLog = new GLchar[info_log_length];'
296                 print r'             glGetProgramInfoLog(program, info_log_length, NULL, infoLog);'
297                 print r'             retrace::warning(call) << infoLog << "\n";'
298                 print r'             delete [] infoLog;'
299                 print r'        }'
300             if function.name == 'glCompileShaderARB':
301                 print r'        GLint compile_status = 0;'
302                 print r'        glGetObjectParameterivARB(shaderObj, GL_OBJECT_COMPILE_STATUS_ARB, &compile_status);'
303                 print r'        if (!compile_status) {'
304                 print r'             GLint info_log_length = 0;'
305                 print r'             glGetObjectParameterivARB(shaderObj, GL_OBJECT_INFO_LOG_LENGTH_ARB, &info_log_length);'
306                 print r'             GLchar *infoLog = new GLchar[info_log_length];'
307                 print r'             glGetInfoLogARB(shaderObj, info_log_length, NULL, infoLog);'
308                 print r'             retrace::warning(call) << infoLog << "\n";'
309                 print r'             delete [] infoLog;'
310                 print r'        }'
311             if function.name == 'glLinkProgramARB':
312                 print r'        GLint link_status = 0;'
313                 print r'        glGetObjectParameterivARB(programObj, GL_OBJECT_LINK_STATUS_ARB, &link_status);'
314                 print r'        if (!link_status) {'
315                 print r'             GLint info_log_length = 0;'
316                 print r'             glGetObjectParameterivARB(programObj, GL_OBJECT_INFO_LOG_LENGTH_ARB, &info_log_length);'
317                 print r'             GLchar *infoLog = new GLchar[info_log_length];'
318                 print r'             glGetInfoLogARB(programObj, info_log_length, NULL, infoLog);'
319                 print r'             retrace::warning(call) << infoLog << "\n";'
320                 print r'             delete [] infoLog;'
321                 print r'        }'
322             if function.name in self.map_function_names:
323                 print r'        if (!__result) {'
324                 print r'             retrace::warning(call) << "failed to map buffer\n";'
325                 print r'        }'
326             if function.name in self.unmap_function_names:
327                 print r'        if (!__result) {'
328                 print r'             retrace::warning(call) << "failed to unmap buffer\n";'
329                 print r'        }'
330             if function.name in ('glGetAttribLocation', 'glGetAttribLocationARB'):
331                 print r'    GLint __orig_result = call.ret->toSInt();'
332                 print r'    if (__result != __orig_result) {'
333                 print r'        retrace::warning(call) << "vertex attrib location mismatch " << __orig_result << " -> " << __result << "\n";'
334                 print r'    }'
335             if function.name in ('glCheckFramebufferStatus', 'glCheckFramebufferStatusEXT', 'glCheckNamedFramebufferStatusEXT'):
336                 print r'    GLint __orig_result = call.ret->toSInt();'
337                 print r'    if (__orig_result == GL_FRAMEBUFFER_COMPLETE &&'
338                 print r'        __result != GL_FRAMEBUFFER_COMPLETE) {'
339                 print r'        retrace::warning(call) << "incomplete framebuffer (" << glstate::enumToString(__result) << ")\n";'
340                 print r'    }'
341             print '    }'
342
343         # Query the buffer length for whole buffer mappings
344         if function.name in self.map_function_names:
345             if 'length' in function.argNames():
346                 assert 'BufferRange' in function.name
347             else:
348                 assert 'BufferRange' not in function.name
349                 print r'    GLint length = 0;'
350                 if function.name in ('glMapBuffer', 'glMapBufferOES'):
351                     print r'    glGetBufferParameteriv(target, GL_BUFFER_SIZE, &length);'
352                 elif function.name == 'glMapBufferARB':
353                     print r'    glGetBufferParameterivARB(target, GL_BUFFER_SIZE_ARB, &length);'
354                 elif function.name == 'glMapNamedBufferEXT':
355                     print r'    glGetNamedBufferParameterivEXT(buffer, GL_BUFFER_SIZE, &length);'
356                 else:
357                     assert False
358
359     def extractArg(self, function, arg, arg_type, lvalue, rvalue):
360         if function.name in self.array_pointer_function_names and arg.name == 'pointer':
361             print '    %s = static_cast<%s>(retrace::toPointer(%s, true));' % (lvalue, arg_type, rvalue)
362             return
363
364         if function.name in self.draw_elements_function_names and arg.name == 'indices' or\
365            function.name in self.draw_indirect_function_names and arg.name == 'indirect':
366             self.extractOpaqueArg(function, arg, arg_type, lvalue, rvalue)
367             return
368
369         # Handle pointer with offsets into the current pack pixel buffer
370         # object.
371         if function.name in self.pack_function_names and arg.output:
372             self.extractOpaqueArg(function, arg, arg_type, lvalue, rvalue)
373             return
374
375         if arg.type is glapi.GLlocation \
376            and 'program' not in function.argNames():
377             print '    GLint program = -1;'
378             print '    glGetIntegerv(GL_CURRENT_PROGRAM, &program);'
379         
380         if arg.type is glapi.GLlocationARB \
381            and 'programObj' not in function.argNames():
382             print '    GLhandleARB programObj = glGetHandleARB(GL_PROGRAM_OBJECT_ARB);'
383
384         Retracer.extractArg(self, function, arg, arg_type, lvalue, rvalue)
385
386         # Don't try to use more samples than the implementation supports
387         if arg.name == 'samples':
388             assert arg.type is glapi.GLsizei
389             print '    GLint max_samples = 0;'
390             print '    glGetIntegerv(GL_MAX_SAMPLES, &max_samples);'
391             print '    if (samples > max_samples) {'
392             print '        samples = max_samples;'
393             print '    }'
394
395
396 if __name__ == '__main__':
397     print r'''
398 #include <string.h>
399
400 #include "glproc.hpp"
401 #include "glretrace.hpp"
402 #include "glstate.hpp"
403
404
405 '''
406     api = glapi.glapi
407     api.addApi(glesapi.glesapi)
408     retracer = GlRetracer()
409     retracer.retraceApi(api)