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