]> git.cworth.org Git - apitrace/blob - glretrace.py
PNG read support.
[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             self.extract_pointer(function, arg, arg_type, lvalue, rvalue)
135         else:
136             Retracer.extract_arg(self, function, arg, arg_type, lvalue, rvalue)
137
138     def extract_pointer(self, function, arg, arg_type, lvalue, rvalue):
139         print '    if (dynamic_cast<Trace::Null *>(&%s)) {' % rvalue
140         print '        %s = 0;' % (lvalue)
141         print '    } else {'
142         print '        %s = (%s)(uintptr_t)(%s);' % (lvalue, arg_type, rvalue)
143         print '    }'
144
145
146 if __name__ == '__main__':
147     print r'''
148 #include <string.h>
149 #include <stdio.h>
150 #include <iostream>
151
152 #include "glproc.hpp"
153 #include <GL/glut.h>
154
155 static bool double_buffer = false;
156 static bool insideGlBeginEnd = false;
157
158 static int __window_width = 256, __window_height = 256;
159 bool __reshape_window = false;
160
161 unsigned __frame = 0;
162 long long __startTime = 0;
163 bool __screenshots = 0;
164
165
166 static void
167 checkGlError(void) {
168     if (insideGlBeginEnd) {
169         return;
170     }
171
172     GLenum error = glGetError();
173     if (error == GL_NO_ERROR) {
174         return;
175     }
176
177     std::cerr << "warning: glGetError() = ";
178     switch (error) {
179     case GL_INVALID_ENUM:
180         std::cerr << "GL_INVALID_ENUM";
181         break;
182     case GL_INVALID_VALUE:
183         std::cerr << "GL_INVALID_VALUE";
184         break;
185     case GL_INVALID_OPERATION:
186         std::cerr << "GL_INVALID_OPERATION";
187         break;
188     case GL_STACK_OVERFLOW:
189         std::cerr << "GL_STACK_OVERFLOW";
190         break;
191     case GL_STACK_UNDERFLOW:
192         std::cerr << "GL_STACK_UNDERFLOW";
193         break;
194     case GL_OUT_OF_MEMORY:
195         std::cerr << "GL_OUT_OF_MEMORY";
196         break;
197     case GL_INVALID_FRAMEBUFFER_OPERATION:
198         std::cerr << "GL_INVALID_FRAMEBUFFER_OPERATION";
199         break;
200     case GL_TABLE_TOO_LARGE:
201         std::cerr << "GL_TABLE_TOO_LARGE";
202         break;
203     default:
204         std::cerr << error;
205         break;
206     }
207     std::cerr << "\n";
208 }
209 '''
210     api = glapi.glapi
211     retracer = GlRetracer()
212     retracer.retrace_api(glapi.glapi)
213     print r'''
214
215 static Trace::Parser parser;
216
217 static void display_noop(void) {
218 }
219
220 #include "image.hpp"
221
222 static void frame_complete(void) {
223     ++__frame;
224     
225     if (__screenshots && !__reshape_window) {
226         char filename[PATH_MAX];
227         snprintf(filename, sizeof filename, "screenshot_%04u.png", __frame);
228         Image::Image image(__window_width, __window_height, true);
229         glReadPixels(0, 0, __window_width, __window_height, GL_RGBA, GL_UNSIGNED_BYTE, image.pixels);
230         image.writePNG(filename);
231     }
232
233 }
234
235 static void display(void) {
236     Trace::Call *call;
237
238     while ((call = parser.parse_call())) {
239         if (call->name() == "glFlush") {
240             glFlush();
241             if (!double_buffer) {
242                 frame_complete();
243             }
244         }
245         
246         if (!retrace_call(*call)) {
247             if (call->name() == "glXSwapBuffers" ||
248                 call->name() == "wglSwapBuffers") {
249                 if (double_buffer)
250                     glutSwapBuffers();
251                 else
252                     glFlush();
253                 frame_complete();
254                 return;
255             }
256         }
257     }
258
259     // Reached the end of trace
260     glFlush();
261
262     long long endTime = OS::GetTime();
263     float timeInterval = (endTime - __startTime) * 1.0E-6;
264
265     std::cout << 
266         "Rendered " << __frame << " frames"
267         " in " <<  timeInterval << " secs,"
268         " average of " << (__frame/timeInterval) << " fps\n";
269
270     glutDisplayFunc(&display_noop);
271     glutIdleFunc(NULL);
272 }
273
274 static void idle(void) {
275     if (__reshape_window) {
276         // XXX: doesn't quite work
277         glutReshapeWindow(__window_width, __window_height);
278         __reshape_window = false;
279     }
280     glutPostRedisplay();
281 }
282
283 int main(int argc, char **argv)
284 {
285
286     int i;
287     for (i = 1; i < argc; ++i) {
288         const char *arg = argv[i];
289
290         if (arg[0] != '-') {
291             break;
292         }
293
294         if (!strcmp(arg, "--")) {
295             break;
296         } else if (!strcmp(arg, "-db")) {
297             double_buffer = true;
298         } else if (!strcmp(arg, "-s")) {
299             __screenshots = true;
300         } else if (!strcmp(arg, "-v")) {
301             ++verbosity;
302         } else {
303             std::cerr << "error: unknown option " << arg << "\n";
304             return 1;
305         }
306     }
307
308     glutInit(&argc, argv);
309     glutInitWindowPosition(0, 0);
310     glutInitWindowSize(__window_width, __window_height);
311     glutInitDisplayMode(GLUT_DEPTH | GLUT_RGB | (double_buffer ? GLUT_DOUBLE : GLUT_SINGLE));
312     glutCreateWindow(argv[0]);
313
314     glutDisplayFunc(&display);
315     glutIdleFunc(&idle);
316
317     for (GLuint h = 0; h < 1024; ++h) {
318         __list_map[h] = h;
319     }
320
321     for ( ; i < argc; ++i) {
322         if (parser.open(argv[i])) {
323             __startTime = OS::GetTime();
324             glutMainLoop();
325             parser.close();
326         }
327     }
328
329     return 0;
330 }
331
332 '''