blob: 356659abbea11c4c6f365e293c2f807126a13151 [file] [log] [blame]
José Fonseca7e329022010-11-19 17:05:18 +00001##########################################################################
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
José Fonseca4a826ed2010-11-30 16:58:22 +000027"""GL retracer generator."""
28
29
José Fonseca9796b842010-11-25 11:44:50 +000030import stdapi
José Fonseca8fbdd3a2010-11-23 20:55:07 +000031import glapi
José Fonsecadacd8dd2010-11-25 17:50:26 +000032from retrace import Retracer
José Fonseca7e329022010-11-19 17:05:18 +000033
34
José Fonsecadacd8dd2010-11-25 17:50:26 +000035class GlRetracer(Retracer):
José Fonsecac9edb832010-11-20 09:03:10 +000036
José Fonseca3d245f42010-11-28 00:08:23 +000037 def retrace_function(self, function):
38 Retracer.retrace_function(self, function)
39
José Fonseca62212972011-03-23 13:22:55 +000040 array_pointer_function_names = set((
41 "glVertexPointer",
42 "glNormalPointer",
43 "glColorPointer",
44 "glIndexPointer",
45 "glTexCoordPointer",
46 "glEdgeFlagPointer",
47 "glFogCoordPointer",
48 "glSecondaryColorPointer",
49
50 "glInterleavedArrays",
51
José Fonsecaac5285b2011-05-04 11:09:08 +010052 "glVertexPointerEXT",
53 "glNormalPointerEXT",
54 "glColorPointerEXT",
55 "glIndexPointerEXT",
56 "glTexCoordPointerEXT",
57 "glEdgeFlagPointerEXT",
58 "glFogCoordPointerEXT",
59 "glSecondaryColorPointerEXT",
José Fonseca62212972011-03-23 13:22:55 +000060
José Fonseca7f5163e2011-03-31 23:37:26 +010061 "glVertexAttribPointer",
62 "glVertexAttribPointerARB",
63 "glVertexAttribPointerNV",
José Fonsecaac5285b2011-05-04 11:09:08 +010064 "glVertexAttribIPointer",
65 "glVertexAttribIPointerEXT",
José Fonseca7f5163e2011-03-31 23:37:26 +010066 "glVertexAttribLPointer",
67 "glVertexAttribLPointerEXT",
José Fonseca62212972011-03-23 13:22:55 +000068
69 #"glMatrixIndexPointerARB",
70 ))
71
José Fonseca8caf2c82010-11-30 12:09:12 +000072 draw_array_function_names = set([
73 "glDrawArrays",
74 "glDrawArraysEXT",
75 "glDrawArraysIndirect",
76 "glDrawArraysInstanced",
77 "glDrawArraysInstancedARB",
78 "glDrawArraysInstancedEXT",
79 "glDrawMeshArraysSUN",
80 "glMultiDrawArrays",
81 "glMultiDrawArraysEXT",
82 "glMultiModeDrawArraysIBM",
83 ])
84
85 draw_elements_function_names = set([
86 "glDrawElements",
87 "glDrawElementsBaseVertex",
88 "glDrawElementsIndirect",
89 "glDrawElementsInstanced",
90 "glDrawElementsInstancedARB",
91 "glDrawElementsInstancedBaseVertex",
92 "glDrawElementsInstancedEXT",
93 "glDrawRangeElements",
94 "glDrawRangeElementsBaseVertex",
95 "glDrawRangeElementsEXT",
José Fonsecafd34e4e2011-06-03 19:34:29 +010096 "glMultiDrawElements",
97 "glMultiDrawElementsBaseVertex",
98 "glMultiDrawElementsEXT",
99 "glMultiModeDrawElementsIBM",
José Fonseca8caf2c82010-11-30 12:09:12 +0000100 ])
101
José Fonseca9b126ea2011-09-15 08:15:33 +0100102 draw_indirect_function_names = set([
103 "glDrawArraysIndirect",
104 "glDrawElementsIndirect",
105 ])
106
José Fonseca920bffd2011-06-02 10:04:52 +0100107 misc_draw_function_names = set([
108 "glClear",
109 "glEnd",
José Fonsecaf8a99a02011-06-07 20:49:56 +0100110 "glDrawPixels",
111 "glBlitFramebuffer",
112 "glBlitFramebufferEXT",
José Fonseca920bffd2011-06-02 10:04:52 +0100113 ])
114
115 bind_framebuffer_function_names = set([
116 "glBindFramebuffer",
117 "glBindFramebufferARB",
118 "glBindFramebufferEXT",
119 ])
120
José Fonsecac29f4f12011-06-11 12:19:05 +0100121 # Names of the functions that can pack into the current pixel buffer
122 # object. See also the ARB_pixel_buffer_object specification.
123 pack_function_names = set([
124 'glGetCompressedTexImage',
125 'glGetConvolutionFilter',
126 'glGetHistogram',
127 'glGetMinmax',
128 'glGetPixelMapfv',
129 'glGetPixelMapuiv',
130 'glGetPixelMapusv',
131 'glGetPolygonStipple',
132 'glGetSeparableFilter,',
133 'glGetTexImage',
134 'glReadPixels',
135 'glGetnCompressedTexImageARB',
136 'glGetnConvolutionFilterARB',
137 'glGetnHistogramARB',
138 'glGetnMinmaxARB',
139 'glGetnPixelMapfvARB',
140 'glGetnPixelMapuivARB',
141 'glGetnPixelMapusvARB',
142 'glGetnPolygonStippleARB',
143 'glGetnSeparableFilterARB',
144 'glGetnTexImageARB',
145 'glReadnPixelsARB',
146 ])
147
José Fonseca62212972011-03-23 13:22:55 +0000148 def retrace_function_body(self, function):
149 is_array_pointer = function.name in self.array_pointer_function_names
150 is_draw_array = function.name in self.draw_array_function_names
151 is_draw_elements = function.name in self.draw_elements_function_names
José Fonseca920bffd2011-06-02 10:04:52 +0100152 is_misc_draw = function.name in self.misc_draw_function_names
José Fonseca62212972011-03-23 13:22:55 +0000153
154 if is_array_pointer or is_draw_array or is_draw_elements:
José Fonseca6117e312011-04-15 23:52:58 +0100155 print ' if (glretrace::parser.version < 1) {'
José Fonseca62212972011-03-23 13:22:55 +0000156
157 if is_array_pointer or is_draw_array:
158 print ' GLint __array_buffer = 0;'
159 print ' glGetIntegerv(GL_ARRAY_BUFFER_BINDING, &__array_buffer);'
160 print ' if (!__array_buffer) {'
161 self.fail_function(function)
162 print ' }'
163
164 if is_draw_elements:
165 print ' GLint __element_array_buffer = 0;'
166 print ' glGetIntegerv(GL_ELEMENT_ARRAY_BUFFER_BINDING, &__element_array_buffer);'
167 print ' if (!__element_array_buffer) {'
168 self.fail_function(function)
169 print ' }'
170
171 print ' }'
172
José Fonsecac29f4f12011-06-11 12:19:05 +0100173 # When no pack buffer object is bound, the pack functions are no-ops.
174 if function.name in self.pack_function_names:
175 print ' GLint __pack_buffer = 0;'
176 print ' glGetIntegerv(GL_PIXEL_PACK_BUFFER_BINDING, &__pack_buffer);'
177 print ' if (!__pack_buffer) {'
José Fonsecad4ca4e22011-09-02 18:35:50 +0100178 if function.name == 'glReadPixels':
179 print ' glFinish();'
180 print ' if (glretrace::snapshot_frequency == glretrace::FREQUENCY_FRAME ||'
181 print ' glretrace::snapshot_frequency == glretrace::FREQUENCY_FRAMEBUFFER) {'
182 print ' glretrace::snapshot(call.no);'
183 print ' }'
José Fonsecac29f4f12011-06-11 12:19:05 +0100184 print ' return;'
185 print ' }'
186
José Fonseca920bffd2011-06-02 10:04:52 +0100187 # Pre-snapshots
188 if function.name in self.bind_framebuffer_function_names:
189 print ' if (glretrace::snapshot_frequency == glretrace::FREQUENCY_FRAMEBUFFER) {'
190 print ' glretrace::snapshot(call.no - 1);'
191 print ' }'
José Fonseca439ae3c2011-09-01 17:36:10 +0100192 if function.name == 'glFrameTerminatorGREMEDY':
193 print ' glretrace::frame_complete(call.no);'
194 return
José Fonseca920bffd2011-06-02 10:04:52 +0100195
José Fonseca62212972011-03-23 13:22:55 +0000196 Retracer.retrace_function_body(self, function)
197
José Fonseca920bffd2011-06-02 10:04:52 +0100198 # Post-snapshots
José Fonseca4d7f1fe2011-05-09 20:54:31 +0100199 if function.name in ('glFlush', 'glFinish'):
200 print ' if (!glretrace::double_buffer) {'
201 print ' glretrace::frame_complete(call.no);'
202 print ' }'
José Fonseca920bffd2011-06-02 10:04:52 +0100203 if is_draw_array or is_draw_elements or is_misc_draw:
204 print ' if (glretrace::snapshot_frequency == glretrace::FREQUENCY_DRAW) {'
205 print ' glretrace::snapshot(call.no);'
206 print ' }'
207
José Fonseca4d7f1fe2011-05-09 20:54:31 +0100208
José Fonsecafa15d332010-11-25 20:22:39 +0000209 def call_function(self, function):
José Fonseca757b2b62011-09-19 10:09:53 +0100210 # Infer the drawable size from GL calls
José Fonsecacdb574a2010-11-29 12:23:35 +0000211 if function.name == "glViewport":
José Fonseca757b2b62011-09-19 10:09:53 +0100212 print ' glretrace::updateDrawable(x + width, y + height);'
213 if function.name in ('glBlitFramebuffer', 'glBlitFramebufferEXT'):
214 # Some applications do all their rendering in a framebuffer, and
215 # then just blit to the drawable without ever calling glViewport.
216 print ' glretrace::updateDrawable(std::max(dstX0, dstX1), std::max(dstY0, dstY1));'
José Fonsecacdb574a2010-11-29 12:23:35 +0000217
José Fonseca3d245f42010-11-28 00:08:23 +0000218 if function.name == "glEnd":
José Fonseca32871ed2011-04-10 13:40:52 +0100219 print ' glretrace::insideGlBeginEnd = false;'
José Fonsecafea81f92011-05-23 21:20:53 +0100220
221 if function.name == 'memcpy':
222 print ' if (!dest || !src || !n) return;'
José Fonsecacdb574a2010-11-29 12:23:35 +0000223
José Fonsecafa15d332010-11-25 20:22:39 +0000224 Retracer.call_function(self, function)
José Fonsecacdb574a2010-11-29 12:23:35 +0000225
José Fonsecaecf37412011-05-21 01:56:08 +0100226 # Error checking
José Fonseca3d245f42010-11-28 00:08:23 +0000227 if function.name == "glBegin":
José Fonseca32871ed2011-04-10 13:40:52 +0100228 print ' glretrace::insideGlBeginEnd = true;'
José Fonsecab8c56072011-05-05 01:13:04 +0100229 elif function.name.startswith('gl'):
José Fonseca3d245f42010-11-28 00:08:23 +0000230 # glGetError is not allowed inside glBegin/glEnd
José Fonsecaecf37412011-05-21 01:56:08 +0100231 print ' if (!glretrace::benchmark && !glretrace::insideGlBeginEnd) {'
232 print ' glretrace::checkGlError(call);'
233 if function.name in ('glProgramStringARB', 'glProgramStringNV'):
234 print r' GLint error_position = -1;'
235 print r' glGetIntegerv(GL_PROGRAM_ERROR_POSITION_ARB, &error_position);'
236 print r' if (error_position != -1) {'
237 print r' const char *error_string = (const char *)glGetString(GL_PROGRAM_ERROR_STRING_ARB);'
238 print r' std::cerr << call.no << ": warning: " << error_string << "\n";'
239 print r' }'
240 if function.name == 'glCompileShader':
241 print r' GLint compile_status = 0;'
242 print r' glGetShaderiv(shader, GL_COMPILE_STATUS, &compile_status);'
243 print r' if (!compile_status) {'
244 print r' GLint info_log_length = 0;'
245 print r' glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &info_log_length);'
246 print r' GLchar *infoLog = new GLchar[info_log_length];'
247 print r' glGetShaderInfoLog(shader, info_log_length, NULL, infoLog);'
248 print r' std::cerr << call.no << ": warning: " << infoLog << "\n";'
249 print r' delete [] infoLog;'
250 print r' }'
251 if function.name == 'glLinkProgram':
252 print r' GLint link_status = 0;'
253 print r' glGetProgramiv(program, GL_LINK_STATUS, &link_status);'
254 print r' if (!link_status) {'
255 print r' GLint info_log_length = 0;'
256 print r' glGetProgramiv(program, GL_INFO_LOG_LENGTH, &info_log_length);'
257 print r' GLchar *infoLog = new GLchar[info_log_length];'
258 print r' glGetProgramInfoLog(program, info_log_length, NULL, infoLog);'
259 print r' std::cerr << call.no << ": warning: " << infoLog << "\n";'
260 print r' delete [] infoLog;'
261 print r' }'
262 if function.name == 'glCompileShaderARB':
263 print r' GLint compile_status = 0;'
264 print r' glGetObjectParameterivARB(shaderObj, GL_OBJECT_COMPILE_STATUS_ARB, &compile_status);'
265 print r' if (!compile_status) {'
266 print r' GLint info_log_length = 0;'
267 print r' glGetObjectParameterivARB(shaderObj, GL_OBJECT_INFO_LOG_LENGTH_ARB, &info_log_length);'
268 print r' GLchar *infoLog = new GLchar[info_log_length];'
269 print r' glGetInfoLogARB(shaderObj, info_log_length, NULL, infoLog);'
270 print r' std::cerr << call.no << ": warning: " << infoLog << "\n";'
271 print r' delete [] infoLog;'
272 print r' }'
273 if function.name == 'glLinkProgramARB':
274 print r' GLint link_status = 0;'
275 print r' glGetObjectParameterivARB(programObj, GL_OBJECT_LINK_STATUS_ARB, &link_status);'
276 print r' if (!link_status) {'
277 print r' GLint info_log_length = 0;'
278 print r' glGetObjectParameterivARB(programObj, GL_OBJECT_INFO_LOG_LENGTH_ARB, &info_log_length);'
279 print r' GLchar *infoLog = new GLchar[info_log_length];'
280 print r' glGetInfoLogARB(programObj, info_log_length, NULL, infoLog);'
281 print r' std::cerr << call.no << ": warning: " << infoLog << "\n";'
282 print r' delete [] infoLog;'
283 print r' }'
José Fonsecafea81f92011-05-23 21:20:53 +0100284 if function.name in ('glMapBuffer', 'glMapBufferARB', 'glMapBufferRange', 'glMapNamedBufferEXT', 'glMapNamedBufferRangeEXT'):
285 print r' if (!__result) {'
286 print r' std::cerr << call.no << ": warning: failed to map buffer\n";'
287 print r' }'
José Fonseca91492d22011-05-23 21:20:31 +0100288 if function.name in ('glGetAttribLocation', 'glGetAttribLocationARB'):
289 print r' GLint __orig_result = call.ret->toSInt();'
290 print r' if (__result != __orig_result) {'
José Fonseca56391262011-09-19 09:30:10 +0100291 print r' std::cerr << call.no << ": warning: vertex attrib location mismatch " << __orig_result << " -> " << __result << "\n";'
José Fonseca91492d22011-05-23 21:20:31 +0100292 print r' }'
José Fonsecad5377812011-06-07 20:48:55 +0100293 if function.name in ('glCheckFramebufferStatus', 'glCheckFramebufferStatusEXT', 'glCheckNamedFramebufferStatusEXT'):
294 print r' GLint __orig_result = call.ret->toSInt();'
295 print r' if (__orig_result == GL_FRAMEBUFFER_COMPLETE &&'
296 print r' __result != GL_FRAMEBUFFER_COMPLETE) {'
José Fonseca56391262011-09-19 09:30:10 +0100297 print r' std::cerr << call.no << ": warning: incomplete framebuffer (" << glstate::enumToString(__result) << ")\n";'
José Fonsecad5377812011-06-07 20:48:55 +0100298 print r' }'
José Fonsecaecf37412011-05-21 01:56:08 +0100299 print ' }'
José Fonsecae4999b92011-05-05 00:31:01 +0100300
José Fonsecadacd8dd2010-11-25 17:50:26 +0000301 def extract_arg(self, function, arg, arg_type, lvalue, rvalue):
José Fonseca7f5163e2011-03-31 23:37:26 +0100302 if function.name in self.array_pointer_function_names and arg.name == 'pointer':
José Fonseca36a0fd32011-08-28 12:37:30 +0100303 print ' %s = static_cast<%s>(%s.toPointer(true));' % (lvalue, arg_type, rvalue)
José Fonseca14c21bc2011-02-20 23:32:22 +0000304 return
305
José Fonseca9b126ea2011-09-15 08:15:33 +0100306 if function.name in self.draw_elements_function_names and arg.name == 'indices' or\
307 function.name in self.draw_indirect_function_names and arg.name == 'indirect':
José Fonsecafd34e4e2011-06-03 19:34:29 +0100308 self.extract_opaque_arg(function, arg, arg_type, lvalue, rvalue)
José Fonseca8a844ae2010-12-06 18:50:52 +0000309 return
José Fonsecadacd8dd2010-11-25 17:50:26 +0000310
José Fonsecac29f4f12011-06-11 12:19:05 +0100311 # Handle pointer with offsets into the current pack pixel buffer
312 # object.
313 if function.name in self.pack_function_names and arg.output:
314 self.extract_opaque_arg(function, arg, arg_type, lvalue, rvalue)
315 return
316
José Fonseca3c1b7ce2011-05-09 11:22:54 +0100317 if arg.type is glapi.GLlocation \
318 and 'program' not in [arg.name for arg in function.args]:
José Fonseca8a844ae2010-12-06 18:50:52 +0000319 print ' GLint program = -1;'
320 print ' glGetIntegerv(GL_CURRENT_PROGRAM, &program);'
José Fonseca3c1b7ce2011-05-09 11:22:54 +0100321
322 if arg.type is glapi.GLlocationARB \
323 and 'programObj' not in [arg.name for arg in function.args]:
José Fonseca3a84b682011-05-09 11:33:47 +0100324 print ' GLhandleARB programObj = glGetHandleARB(GL_PROGRAM_OBJECT_ARB);'
José Fonseca8a844ae2010-12-06 18:50:52 +0000325
326 Retracer.extract_arg(self, function, arg, arg_type, lvalue, rvalue)
José Fonsecae6a50bd2010-11-24 10:12:22 +0000327
José Fonseca42926462011-05-09 11:32:15 +0100328 # Don't try to use more samples than the implementation supports
329 if arg.name == 'samples':
330 assert arg.type is glapi.GLsizei
331 print ' GLint max_samples = 0;'
332 print ' glGetIntegerv(GL_MAX_SAMPLES, &max_samples);'
333 print ' if (samples > max_samples) {'
334 print ' samples = max_samples;'
335 print ' }'
336
José Fonsecae6a50bd2010-11-24 10:12:22 +0000337
José Fonseca7e329022010-11-19 17:05:18 +0000338if __name__ == '__main__':
José Fonseca796a3042010-11-29 14:21:06 +0000339 print r'''
José Fonseca867b1b72011-04-24 11:58:04 +0100340#include <string.h>
341
José Fonsecadf66a902010-11-29 13:24:20 +0000342#include "glproc.hpp"
José Fonseca32871ed2011-04-10 13:40:52 +0100343#include "glretrace.hpp"
José Fonseca56391262011-09-19 09:30:10 +0100344#include "glstate.hpp"
José Fonseca589082d2011-03-30 09:10:40 +0100345
José Fonsecadf66a902010-11-29 13:24:20 +0000346
José Fonseca3d245f42010-11-28 00:08:23 +0000347'''
José Fonsecae0e61402010-11-25 15:03:23 +0000348 api = glapi.glapi
José Fonseca867b1b72011-04-24 11:58:04 +0100349 api.add_function(glapi.memcpy)
José Fonsecae0e61402010-11-25 15:03:23 +0000350 retracer = GlRetracer()
José Fonseca06aa2842011-05-05 07:55:54 +0100351 retracer.retrace_api(api)