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