]> git.cworth.org Git - apitrace/blob - glretrace.py
Add Function.argNames() method.
[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         "glClear",
115         "glEnd",
116         "glDrawPixels",
117         "glBlitFramebuffer",
118         "glBlitFramebufferEXT",
119     ])
120
121     bind_framebuffer_function_names = set([
122         "glBindFramebuffer",
123         "glBindFramebufferARB",
124         "glBindFramebufferEXT",
125     ])
126
127     # Names of the functions that can pack into the current pixel buffer
128     # object.  See also the ARB_pixel_buffer_object specification.
129     pack_function_names = set([
130         'glGetCompressedTexImage',
131         'glGetConvolutionFilter',
132         'glGetHistogram',
133         'glGetMinmax',
134         'glGetPixelMapfv',
135         'glGetPixelMapuiv',
136         'glGetPixelMapusv',
137         'glGetPolygonStipple',
138         'glGetSeparableFilter',
139         'glGetTexImage',
140         'glReadPixels',
141         'glGetnCompressedTexImageARB',
142         'glGetnConvolutionFilterARB',
143         'glGetnHistogramARB',
144         'glGetnMinmaxARB',
145         'glGetnPixelMapfvARB',
146         'glGetnPixelMapuivARB',
147         'glGetnPixelMapusvARB',
148         'glGetnPolygonStippleARB',
149         'glGetnSeparableFilterARB',
150         'glGetnTexImageARB',
151         'glReadnPixelsARB',
152     ])
153
154     map_function_names = set([
155         'glMapBuffer',
156         'glMapBufferARB',
157         'glMapBufferOES',
158         'glMapBufferRange',
159         'glMapNamedBufferEXT',
160         'glMapNamedBufferRangeEXT'
161     ])
162
163     unmap_function_names = set([
164         'glUnmapBuffer',
165         'glUnmapBufferARB',
166         'glUnmapBufferOES',
167         'glUnmapNamedBufferEXT',
168     ])
169
170     def retraceFunctionBody(self, function):
171         is_array_pointer = function.name in self.array_pointer_function_names
172         is_draw_array = function.name in self.draw_array_function_names
173         is_draw_elements = function.name in self.draw_elements_function_names
174         is_misc_draw = function.name in self.misc_draw_function_names
175
176         if is_array_pointer or is_draw_array or is_draw_elements:
177             print '    if (glretrace::parser.version < 1) {'
178
179             if is_array_pointer or is_draw_array:
180                 print '        GLint __array_buffer = 0;'
181                 print '        glGetIntegerv(GL_ARRAY_BUFFER_BINDING, &__array_buffer);'
182                 print '        if (!__array_buffer) {'
183                 self.failFunction(function)
184                 print '        }'
185
186             if is_draw_elements:
187                 print '        GLint __element_array_buffer = 0;'
188                 print '        glGetIntegerv(GL_ELEMENT_ARRAY_BUFFER_BINDING, &__element_array_buffer);'
189                 print '        if (!__element_array_buffer) {'
190                 self.failFunction(function)
191                 print '        }'
192             
193             print '    }'
194
195         # When no pack buffer object is bound, the pack functions are no-ops.
196         if function.name in self.pack_function_names:
197             print '    GLint __pack_buffer = 0;'
198             print '    glGetIntegerv(GL_PIXEL_PACK_BUFFER_BINDING, &__pack_buffer);'
199             print '    if (!__pack_buffer) {'
200             if function.name == 'glReadPixels':
201                 print '    glFinish();'
202                 print '    if (glretrace::snapshot_frequency == glretrace::FREQUENCY_FRAME ||'
203                 print '        glretrace::snapshot_frequency == glretrace::FREQUENCY_FRAMEBUFFER) {'
204                 print '        glretrace::snapshot(call.no);'
205                 print '    }'
206             print '        return;'
207             print '    }'
208
209         # Pre-snapshots
210         if function.name in self.bind_framebuffer_function_names:
211             print '    if (glretrace::snapshot_frequency == glretrace::FREQUENCY_FRAMEBUFFER) {'
212             print '        glretrace::snapshot(call.no - 1);'
213             print '    }'
214         if function.name == 'glFrameTerminatorGREMEDY':
215             print '    glretrace::frame_complete(call);'
216             return
217
218         Retracer.retraceFunctionBody(self, function)
219
220         # Post-snapshots
221         if function.name in ('glFlush', 'glFinish'):
222             print '    if (!glretrace::double_buffer) {'
223             print '        glretrace::frame_complete(call);'
224             print '    }'
225         if is_draw_array or is_draw_elements or is_misc_draw:
226             print '    if (glretrace::snapshot_frequency == glretrace::FREQUENCY_DRAW) {'
227             print '        glretrace::snapshot(call.no);'
228             print '    }'
229
230
231     def invokeFunction(self, function):
232         # Infer the drawable size from GL calls
233         if function.name == "glViewport":
234             print '    glretrace::updateDrawable(x + width, y + height);'
235         if function.name in ('glBlitFramebuffer', 'glBlitFramebufferEXT'):
236             # Some applications do all their rendering in a framebuffer, and
237             # then just blit to the drawable without ever calling glViewport.
238             print '    glretrace::updateDrawable(std::max(dstX0, dstX1), std::max(dstY0, dstY1));'
239
240         if function.name == "glEnd":
241             print '    glretrace::insideGlBeginEnd = false;'
242
243         if function.name == 'memcpy':
244             print '    if (!dest || !src || !n) return;'
245         
246         Retracer.invokeFunction(self, function)
247
248         # Error checking
249         if function.name == "glBegin":
250             print '    glretrace::insideGlBeginEnd = true;'
251         elif function.name.startswith('gl'):
252             # glGetError is not allowed inside glBegin/glEnd
253             print '    if (!glretrace::benchmark && !glretrace::insideGlBeginEnd) {'
254             print '        glretrace::checkGlError(call);'
255             if function.name in ('glProgramStringARB', 'glProgramStringNV'):
256                 print r'        GLint error_position = -1;'
257                 print r'        glGetIntegerv(GL_PROGRAM_ERROR_POSITION_ARB, &error_position);'
258                 print r'        if (error_position != -1) {'
259                 print r'            const char *error_string = (const char *)glGetString(GL_PROGRAM_ERROR_STRING_ARB);'
260                 print r'            retrace::warning(call) << error_string << "\n";'
261                 print r'        }'
262             if function.name == 'glCompileShader':
263                 print r'        GLint compile_status = 0;'
264                 print r'        glGetShaderiv(shader, GL_COMPILE_STATUS, &compile_status);'
265                 print r'        if (!compile_status) {'
266                 print r'             GLint info_log_length = 0;'
267                 print r'             glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &info_log_length);'
268                 print r'             GLchar *infoLog = new GLchar[info_log_length];'
269                 print r'             glGetShaderInfoLog(shader, info_log_length, NULL, infoLog);'
270                 print r'             retrace::warning(call) << infoLog << "\n";'
271                 print r'             delete [] infoLog;'
272                 print r'        }'
273             if function.name == 'glLinkProgram':
274                 print r'        GLint link_status = 0;'
275                 print r'        glGetProgramiv(program, GL_LINK_STATUS, &link_status);'
276                 print r'        if (!link_status) {'
277                 print r'             GLint info_log_length = 0;'
278                 print r'             glGetProgramiv(program, GL_INFO_LOG_LENGTH, &info_log_length);'
279                 print r'             GLchar *infoLog = new GLchar[info_log_length];'
280                 print r'             glGetProgramInfoLog(program, info_log_length, NULL, infoLog);'
281                 print r'             retrace::warning(call) << infoLog << "\n";'
282                 print r'             delete [] infoLog;'
283                 print r'        }'
284             if function.name == 'glCompileShaderARB':
285                 print r'        GLint compile_status = 0;'
286                 print r'        glGetObjectParameterivARB(shaderObj, GL_OBJECT_COMPILE_STATUS_ARB, &compile_status);'
287                 print r'        if (!compile_status) {'
288                 print r'             GLint info_log_length = 0;'
289                 print r'             glGetObjectParameterivARB(shaderObj, GL_OBJECT_INFO_LOG_LENGTH_ARB, &info_log_length);'
290                 print r'             GLchar *infoLog = new GLchar[info_log_length];'
291                 print r'             glGetInfoLogARB(shaderObj, info_log_length, NULL, infoLog);'
292                 print r'             retrace::warning(call) << infoLog << "\n";'
293                 print r'             delete [] infoLog;'
294                 print r'        }'
295             if function.name == 'glLinkProgramARB':
296                 print r'        GLint link_status = 0;'
297                 print r'        glGetObjectParameterivARB(programObj, GL_OBJECT_LINK_STATUS_ARB, &link_status);'
298                 print r'        if (!link_status) {'
299                 print r'             GLint info_log_length = 0;'
300                 print r'             glGetObjectParameterivARB(programObj, GL_OBJECT_INFO_LOG_LENGTH_ARB, &info_log_length);'
301                 print r'             GLchar *infoLog = new GLchar[info_log_length];'
302                 print r'             glGetInfoLogARB(programObj, info_log_length, NULL, infoLog);'
303                 print r'             retrace::warning(call) << infoLog << "\n";'
304                 print r'             delete [] infoLog;'
305                 print r'        }'
306             if function.name in self.map_function_names:
307                 print r'        if (!__result) {'
308                 print r'             retrace::warning(call) << "failed to map buffer\n";'
309                 print r'        }'
310             if function.name in ('glGetAttribLocation', 'glGetAttribLocationARB'):
311                 print r'    GLint __orig_result = call.ret->toSInt();'
312                 print r'    if (__result != __orig_result) {'
313                 print r'        retrace::warning(call) << "vertex attrib location mismatch " << __orig_result << " -> " << __result << "\n";'
314                 print r'    }'
315             if function.name in ('glCheckFramebufferStatus', 'glCheckFramebufferStatusEXT', 'glCheckNamedFramebufferStatusEXT'):
316                 print r'    GLint __orig_result = call.ret->toSInt();'
317                 print r'    if (__orig_result == GL_FRAMEBUFFER_COMPLETE &&'
318                 print r'        __result != GL_FRAMEBUFFER_COMPLETE) {'
319                 print r'        retrace::warning(call) << "incomplete framebuffer (" << glstate::enumToString(__result) << ")\n";'
320                 print r'    }'
321             print '    }'
322
323             # Update buffer mappings
324             if function.name in self.map_function_names:
325                 print r'        if (__result) {'
326                 print r'            unsigned long long __address = call.ret->toUIntPtr();'
327                 if 'BufferRange' not in function.name:
328                     print r'            GLint length = 0;'
329                     if function.name in ('glMapBuffer', 'glMapBufferOES'):
330                         print r'    glGetBufferParameteriv(target, GL_BUFFER_SIZE, &length);'
331                     elif function.name == 'glMapBufferARB':
332                         print r'            glGetBufferParameterivARB(target, GL_BUFFER_SIZE_ARB, &length);'
333                     elif function.name == 'glMapNamedBufferEXT':
334                         print r'            glGetNamedBufferParameterivEXT(buffer, GL_BUFFER_SIZE, &length);'
335                     else:
336                         assert False
337                 print r'             retrace::addRegion(__address, __result, length);'
338                 print r'        }'
339             if function.name in self.unmap_function_names:
340                 print r'        GLvoid *ptr = NULL;'
341                 if function.name == 'glUnmapBuffer':
342                     print r'            glGetBufferPointerv(target, GL_BUFFER_MAP_POINTER, &ptr);'
343                 elif function.name == 'glUnmapBufferARB':
344                     print r'            glGetBufferPointervARB(target, GL_BUFFER_MAP_POINTER_ARB, &ptr);'
345                 elif function.name == 'glUnmapBufferOES':
346                     print r'            glGetBufferPointervOES(target, GL_BUFFER_MAP_POINTER_OES, &ptr);'
347                 elif function.name == 'glUnmapNamedBufferEXT':
348                     print r'            glGetNamedBufferPointervEXT(buffer, GL_BUFFER_MAP_POINTER, &ptr);'
349                 else:
350                     assert False
351                 print r'        if (ptr) {'
352                 print r'            retrace::delRegionByPointer(ptr);'
353                 print r'        }'
354
355     def extractArg(self, function, arg, arg_type, lvalue, rvalue):
356         if function.name in self.array_pointer_function_names and arg.name == 'pointer':
357             print '    %s = static_cast<%s>(retrace::toPointer(%s, true));' % (lvalue, arg_type, rvalue)
358             return
359
360         if function.name in self.draw_elements_function_names and arg.name == 'indices' or\
361            function.name in self.draw_indirect_function_names and arg.name == 'indirect':
362             self.extractOpaqueArg(function, arg, arg_type, lvalue, rvalue)
363             return
364
365         # Handle pointer with offsets into the current pack pixel buffer
366         # object.
367         if function.name in self.pack_function_names and arg.output:
368             self.extractOpaqueArg(function, arg, arg_type, lvalue, rvalue)
369             return
370
371         if arg.type is glapi.GLlocation \
372            and 'program' not in function.argNames():
373             print '    GLint program = -1;'
374             print '    glGetIntegerv(GL_CURRENT_PROGRAM, &program);'
375         
376         if arg.type is glapi.GLlocationARB \
377            and 'programObj' not in function.argNames():
378             print '    GLhandleARB programObj = glGetHandleARB(GL_PROGRAM_OBJECT_ARB);'
379
380         Retracer.extractArg(self, function, arg, arg_type, lvalue, rvalue)
381
382         # Don't try to use more samples than the implementation supports
383         if arg.name == 'samples':
384             assert arg.type is glapi.GLsizei
385             print '    GLint max_samples = 0;'
386             print '    glGetIntegerv(GL_MAX_SAMPLES, &max_samples);'
387             print '    if (samples > max_samples) {'
388             print '        samples = max_samples;'
389             print '    }'
390
391
392 if __name__ == '__main__':
393     print r'''
394 #include <string.h>
395
396 #include "glproc.hpp"
397 #include "glretrace.hpp"
398 #include "glstate.hpp"
399
400
401 '''
402     api = glapi.glapi
403     api.addApi(glesapi.glesapi)
404     retracer = GlRetracer()
405     retracer.retraceApi(api)