]> git.cworth.org Git - apitrace/blob - glretrace.py
Use Python 2.6
[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     draw_array_function_names = set([
41         "glDrawArrays",
42         "glDrawArraysEXT",
43         "glDrawArraysIndirect",
44         "glDrawArraysInstanced",
45         "glDrawArraysInstancedARB",
46         "glDrawArraysInstancedEXT",
47         "glDrawMeshArraysSUN",
48         "glMultiDrawArrays",
49         "glMultiDrawArraysEXT",
50         "glMultiModeDrawArraysIBM",
51     ])
52
53     draw_elements_function_names = set([
54         "glDrawElements",
55         "glDrawElementsBaseVertex",
56         "glDrawElementsIndirect",
57         "glDrawElementsInstanced",
58         "glDrawElementsInstancedARB",
59         "glDrawElementsInstancedBaseVertex",
60         "glDrawElementsInstancedEXT",
61         "glDrawRangeElements",
62         "glDrawRangeElementsBaseVertex",
63         "glDrawRangeElementsEXT",
64         "glMultiDrawElements",
65         "glMultiDrawElementsBaseVertex",
66         "glMultiDrawElementsEXT",
67         "glMultiModeDrawElementsIBM",
68     ])
69
70     def call_function(self, function):
71         if (function.name in self.draw_array_function_names or 
72             function.name in self.draw_elements_function_names):
73             print '    GLint __array_buffer = 0;'
74             print '    glGetIntegerv(GL_ARRAY_BUFFER_BINDING, &__array_buffer);'
75             print '    if (!__array_buffer) {'
76             self.fail_function(function)
77             print '    }'
78
79         if function.name in self.draw_elements_function_names:
80             print '    GLint __element_array_buffer = 0;'
81             print '    glGetIntegerv(GL_ELEMENT_ARRAY_BUFFER_BINDING, &__element_array_buffer);'
82             print '    if (!__element_array_buffer) {'
83             self.fail_function(function)
84             print '    }'
85
86         if function.name == "glViewport":
87             print '    if (x + width > __window_width) {'
88             print '        __window_width = x + width;'
89             print '        __reshape_window = true;'
90             print '    }'
91             print '    if (y + height > __window_height) {'
92             print '        __window_height = y + height;'
93             print '        __reshape_window = true;'
94             print '    }'
95
96         if function.name == "glEnd":
97             print '    insideGlBeginEnd = false;'
98         
99         Retracer.call_function(self, function)
100
101         if function.name == "glBegin":
102             print '    insideGlBeginEnd = true;'
103         else:
104             # glGetError is not allowed inside glBegin/glEnd
105             print '    checkGlError();'
106
107     pointer_function_names = set([
108         "glColorPointer",
109         "glColorPointerEXT",
110         "glEdgeFlagPointer",
111         "glEdgeFlagPointerEXT",
112         "glFogCoordPointer",
113         "glFogCoordPointerEXT",
114         "glIndexPointer",
115         "glIndexPointerEXT",
116         "glMatrixIndexPointerARB",
117         "glNormalPointer",
118         "glNormalPointerEXT",
119         "glSecondaryColorPointer",
120         "glSecondaryColorPointerEXT",
121         "glTexCoordPointer",
122         "glTexCoordPointerEXT",
123         "glVertexAttribLPointer",
124         "glVertexAttribPointer",
125         "glVertexAttribPointerARB",
126         "glVertexAttribPointerNV",
127         "glVertexPointer",
128         "glVertexPointerEXT",
129     ])
130
131     def extract_arg(self, function, arg, arg_type, lvalue, rvalue):
132         if (function.name in self.pointer_function_names and arg.name == 'pointer' or
133             function.name in self.draw_elements_function_names and arg.name == 'indices'):
134             print '    if (dynamic_cast<Trace::Null *>(&%s)) {' % rvalue
135             print '        %s = 0;' % (lvalue)
136             print '    } else {'
137             print '        %s = (%s)(uintptr_t)(%s);' % (lvalue, arg_type, rvalue)
138             print '    }'
139             return
140
141         if function.name.startswith('glUniform') and function.args[0].name == arg.name == 'location':
142             print '    GLint program = -1;'
143             print '    glGetIntegerv(GL_CURRENT_PROGRAM, &program);'
144
145         Retracer.extract_arg(self, function, arg, arg_type, lvalue, rvalue)
146
147
148 if __name__ == '__main__':
149     print r'''
150 #include <string.h>
151 #include <stdio.h>
152 #include <iostream>
153
154 #include "glproc.hpp"
155 #include <GL/glut.h>
156
157 static bool double_buffer = false;
158 static bool insideGlBeginEnd = false;
159
160 static int __window_width = 256, __window_height = 256;
161 bool __reshape_window = false;
162
163 unsigned __frame = 0;
164 long long __startTime = 0;
165 bool __screenshots = 0;
166
167
168 static void
169 checkGlError(void) {
170     if (insideGlBeginEnd) {
171         return;
172     }
173
174     GLenum error = glGetError();
175     if (error == GL_NO_ERROR) {
176         return;
177     }
178
179     std::cerr << "warning: glGetError() = ";
180     switch (error) {
181     case GL_INVALID_ENUM:
182         std::cerr << "GL_INVALID_ENUM";
183         break;
184     case GL_INVALID_VALUE:
185         std::cerr << "GL_INVALID_VALUE";
186         break;
187     case GL_INVALID_OPERATION:
188         std::cerr << "GL_INVALID_OPERATION";
189         break;
190     case GL_STACK_OVERFLOW:
191         std::cerr << "GL_STACK_OVERFLOW";
192         break;
193     case GL_STACK_UNDERFLOW:
194         std::cerr << "GL_STACK_UNDERFLOW";
195         break;
196     case GL_OUT_OF_MEMORY:
197         std::cerr << "GL_OUT_OF_MEMORY";
198         break;
199     case GL_INVALID_FRAMEBUFFER_OPERATION:
200         std::cerr << "GL_INVALID_FRAMEBUFFER_OPERATION";
201         break;
202     case GL_TABLE_TOO_LARGE:
203         std::cerr << "GL_TABLE_TOO_LARGE";
204         break;
205     default:
206         std::cerr << error;
207         break;
208     }
209     std::cerr << "\n";
210 }
211 '''
212     api = glapi.glapi
213     retracer = GlRetracer()
214     retracer.retrace_api(glapi.glapi)
215     print r'''
216
217 static Trace::Parser parser;
218
219 static void display_noop(void) {
220 }
221
222 #include "image.hpp"
223
224 static void frame_complete(void) {
225     ++__frame;
226     
227     if (__screenshots && !__reshape_window) {
228         char filename[PATH_MAX];
229         snprintf(filename, sizeof filename, "screenshot_%04u.png", __frame);
230         Image::Image image(__window_width, __window_height, true);
231         glReadPixels(0, 0, __window_width, __window_height, GL_RGBA, GL_UNSIGNED_BYTE, image.pixels);
232         image.writePNG(filename);
233     }
234
235 }
236
237 static void display(void) {
238     Trace::Call *call;
239
240     while ((call = parser.parse_call())) {
241         if (call->name() == "glFlush") {
242             glFlush();
243             if (!double_buffer) {
244                 frame_complete();
245             }
246         }
247         
248         if (!retrace_call(*call)) {
249             if (call->name() == "glXSwapBuffers" ||
250                 call->name() == "wglSwapBuffers") {
251                 if (double_buffer)
252                     glutSwapBuffers();
253                 else
254                     glFlush();
255                 frame_complete();
256                 return;
257             }
258         }
259     }
260
261     // Reached the end of trace
262     glFlush();
263
264     long long endTime = OS::GetTime();
265     float timeInterval = (endTime - __startTime) * 1.0E-6;
266
267     std::cout << 
268         "Rendered " << __frame << " frames"
269         " in " <<  timeInterval << " secs,"
270         " average of " << (__frame/timeInterval) << " fps\n";
271
272     glutDisplayFunc(&display_noop);
273     glutIdleFunc(NULL);
274 }
275
276 static void idle(void) {
277     if (__reshape_window) {
278         // XXX: doesn't quite work
279         glutReshapeWindow(__window_width, __window_height);
280         __reshape_window = false;
281     }
282     glutPostRedisplay();
283 }
284
285 int main(int argc, char **argv)
286 {
287
288     int i;
289     for (i = 1; i < argc; ++i) {
290         const char *arg = argv[i];
291
292         if (arg[0] != '-') {
293             break;
294         }
295
296         if (!strcmp(arg, "--")) {
297             break;
298         } else if (!strcmp(arg, "-db")) {
299             double_buffer = true;
300         } else if (!strcmp(arg, "-s")) {
301             __screenshots = true;
302         } else if (!strcmp(arg, "-v")) {
303             ++verbosity;
304         } else {
305             std::cerr << "error: unknown option " << arg << "\n";
306             return 1;
307         }
308     }
309
310     glutInit(&argc, argv);
311     glutInitWindowPosition(0, 0);
312     glutInitWindowSize(__window_width, __window_height);
313     glutInitDisplayMode(GLUT_DEPTH | GLUT_RGB | (double_buffer ? GLUT_DOUBLE : GLUT_SINGLE));
314     glutCreateWindow(argv[0]);
315
316     glutDisplayFunc(&display);
317     glutIdleFunc(&idle);
318
319     for (GLuint h = 0; h < 1024; ++h) {
320         __list_map[h] = h;
321     }
322
323     for ( ; i < argc; ++i) {
324         if (parser.open(argv[i])) {
325             __startTime = OS::GetTime();
326             glutMainLoop();
327             parser.close();
328         }
329     }
330
331     return 0;
332 }
333
334 '''