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