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