]> git.cworth.org Git - apitrace/blob - glretrace.py
Silence unitialized variable warning
[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 static enum {
166     MODE_DISPLAY = 0,
167     MODE_SNAPSHOT,
168     MODE_COMPARE,
169 } __mode = MODE_DISPLAY;
170
171 const char *__snapshot_prefix = "";
172
173
174 static void
175 checkGlError(void) {
176     if (insideGlBeginEnd) {
177         return;
178     }
179
180     GLenum error = glGetError();
181     if (error == GL_NO_ERROR) {
182         return;
183     }
184
185     std::cerr << "warning: glGetError() = ";
186     switch (error) {
187     case GL_INVALID_ENUM:
188         std::cerr << "GL_INVALID_ENUM";
189         break;
190     case GL_INVALID_VALUE:
191         std::cerr << "GL_INVALID_VALUE";
192         break;
193     case GL_INVALID_OPERATION:
194         std::cerr << "GL_INVALID_OPERATION";
195         break;
196     case GL_STACK_OVERFLOW:
197         std::cerr << "GL_STACK_OVERFLOW";
198         break;
199     case GL_STACK_UNDERFLOW:
200         std::cerr << "GL_STACK_UNDERFLOW";
201         break;
202     case GL_OUT_OF_MEMORY:
203         std::cerr << "GL_OUT_OF_MEMORY";
204         break;
205     case GL_INVALID_FRAMEBUFFER_OPERATION:
206         std::cerr << "GL_INVALID_FRAMEBUFFER_OPERATION";
207         break;
208     case GL_TABLE_TOO_LARGE:
209         std::cerr << "GL_TABLE_TOO_LARGE";
210         break;
211     default:
212         std::cerr << error;
213         break;
214     }
215     std::cerr << "\n";
216 }
217 '''
218     api = glapi.glapi
219     retracer = GlRetracer()
220     retracer.retrace_api(glapi.glapi)
221     print r'''
222
223 static Trace::Parser parser;
224
225 static void display_noop(void) {
226 }
227
228 #include "image.hpp"
229
230 static void frame_complete(void) {
231     ++__frame;
232     
233     if (!__reshape_window && (__mode == MODE_SNAPSHOT || __mode == MODE_COMPARE)) {
234         char filename[PATH_MAX];
235
236         snprintf(filename, sizeof filename, "%s%04u.png", __snapshot_prefix, __frame);
237         
238         Image::Image *ref = NULL;
239         if (__mode == MODE_COMPARE) {
240             ref = Image::readPNG(filename);
241             if (!ref) {
242                 return;
243             }
244             if (verbosity)
245                 std::cout << "Read " << filename << "\n";
246         }
247         
248         Image::Image src(__window_width, __window_height, true);
249         glReadPixels(0, 0, __window_width, __window_height, GL_RGBA, GL_UNSIGNED_BYTE, src.pixels);
250
251         if (__mode == MODE_SNAPSHOT) {
252             if (src.writePNG(filename) && verbosity) {
253                 std::cout << "Wrote " << filename << "\n";
254             }
255         }
256
257         if (__mode == MODE_COMPARE) {
258             std::cout << "Frame " << __frame << " average precision of " << src.compare(*ref) << " bits\n";
259             delete ref;
260         }
261     }
262
263 }
264
265 static void display(void) {
266     Trace::Call *call;
267
268     while ((call = parser.parse_call())) {
269         const std::string &name = call->name();
270
271         if ((name[0] == 'w' && name[1] == 'g' && name[2] == 'l') ||
272             (name[0] == 'g' && name[1] == 'l' && name[2] == 'X')) {
273             // XXX: We ignore the majority of the OS-specific calls for now
274             if (name == "glXSwapBuffers" ||
275                 name == "wglSwapBuffers") {
276                 if (double_buffer)
277                     glutSwapBuffers();
278                 else
279                     glFlush();
280                 frame_complete();
281                 return;
282             } else {
283                 continue;
284             }
285         }
286
287         if (name == "glFlush") {
288             glFlush();
289             if (!double_buffer) {
290                 frame_complete();
291             }
292         }
293         
294         retrace_call(*call);
295     }
296
297     // Reached the end of trace
298     glFlush();
299
300     long long endTime = OS::GetTime();
301     float timeInterval = (endTime - __startTime) * 1.0E-6;
302
303     std::cout << 
304         "Rendered " << __frame << " frames"
305         " in " <<  timeInterval << " secs,"
306         " average of " << (__frame/timeInterval) << " fps\n";
307
308     if (__mode == MODE_DISPLAY) {
309         glutDisplayFunc(&display_noop);
310         glutIdleFunc(NULL);
311     } else {
312         exit(0);
313     }
314 }
315
316 static void idle(void) {
317     if (__reshape_window) {
318         // XXX: doesn't quite work
319         glutReshapeWindow(__window_width, __window_height);
320         __reshape_window = false;
321     }
322     glutPostRedisplay();
323 }
324
325 static void usage(void) {
326     std::cout << 
327         "Usage: glretrace [OPTION] TRACE\n"
328         "Replay TRACE.\n"
329         "\n"
330         "  -c           compare against snapshots\n"
331         "  -db          use a double buffer visual\n"
332         "  -p PREFIX    snapshot prefix\n"
333         "  -s           take snapshots\n"
334         "  -v           verbose output\n";
335 }
336
337 int main(int argc, char **argv)
338 {
339
340     int i;
341     for (i = 1; i < argc; ++i) {
342         const char *arg = argv[i];
343
344         if (arg[0] != '-') {
345             break;
346         }
347
348         if (!strcmp(arg, "--")) {
349             break;
350         } else if (!strcmp(arg, "-c")) {
351             __mode = MODE_COMPARE;
352         } else if (!strcmp(arg, "-db")) {
353             double_buffer = true;
354         } else if (!strcmp(arg, "--help")) {
355             usage();
356             return 0;
357         } else if (!strcmp(arg, "-p")) {
358             __snapshot_prefix = argv[++i];
359         } else if (!strcmp(arg, "-s")) {
360             __mode = MODE_SNAPSHOT;
361         } else if (!strcmp(arg, "-v")) {
362             ++verbosity;
363         } else {
364             std::cerr << "error: unknown option " << arg << "\n";
365             usage();
366             return 1;
367         }
368     }
369
370     glutInit(&argc, argv);
371     glutInitWindowPosition(0, 0);
372     glutInitWindowSize(__window_width, __window_height);
373     glutInitDisplayMode(GLUT_DEPTH | GLUT_RGB | (double_buffer ? GLUT_DOUBLE : GLUT_SINGLE));
374     glutCreateWindow(argv[0]);
375
376     glutDisplayFunc(&display);
377     glutIdleFunc(&idle);
378
379     for (GLuint h = 0; h < 1024; ++h) {
380         __list_map[h] = h;
381     }
382
383     for ( ; i < argc; ++i) {
384         if (parser.open(argv[i])) {
385             __startTime = OS::GetTime();
386             glutMainLoop();
387             parser.close();
388         }
389     }
390
391     return 0;
392 }
393
394 '''