blob: 1d916ee797b6d0025626ab326236353102fefdf2 [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é Fonsecabd86a222011-09-27 09:21:38 +010030import specs.stdapi as stdapi
31import specs.glapi as 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é Fonseca2741ed82011-10-07 23:36:39 +010037 table_name = 'glretrace::gl_callbacks'
38
José Fonseca3d245f42010-11-28 00:08:23 +000039 def retrace_function(self, function):
40 Retracer.retrace_function(self, function)
41
José Fonseca62212972011-03-23 13:22:55 +000042 array_pointer_function_names = set((
43 "glVertexPointer",
44 "glNormalPointer",
45 "glColorPointer",
46 "glIndexPointer",
47 "glTexCoordPointer",
48 "glEdgeFlagPointer",
49 "glFogCoordPointer",
50 "glSecondaryColorPointer",
51
52 "glInterleavedArrays",
53
José Fonsecaac5285b2011-05-04 11:09:08 +010054 "glVertexPointerEXT",
55 "glNormalPointerEXT",
56 "glColorPointerEXT",
57 "glIndexPointerEXT",
58 "glTexCoordPointerEXT",
59 "glEdgeFlagPointerEXT",
60 "glFogCoordPointerEXT",
61 "glSecondaryColorPointerEXT",
José Fonseca62212972011-03-23 13:22:55 +000062
José Fonseca7f5163e2011-03-31 23:37:26 +010063 "glVertexAttribPointer",
64 "glVertexAttribPointerARB",
65 "glVertexAttribPointerNV",
José Fonsecaac5285b2011-05-04 11:09:08 +010066 "glVertexAttribIPointer",
67 "glVertexAttribIPointerEXT",
José Fonseca7f5163e2011-03-31 23:37:26 +010068 "glVertexAttribLPointer",
69 "glVertexAttribLPointerEXT",
José Fonseca62212972011-03-23 13:22:55 +000070
71 #"glMatrixIndexPointerARB",
72 ))
73
José Fonseca8caf2c82010-11-30 12:09:12 +000074 draw_array_function_names = set([
75 "glDrawArrays",
76 "glDrawArraysEXT",
77 "glDrawArraysIndirect",
78 "glDrawArraysInstanced",
79 "glDrawArraysInstancedARB",
80 "glDrawArraysInstancedEXT",
José Fonsecaff8848b2011-10-09 01:04:17 +010081 "glDrawArraysInstancedBaseInstance",
José Fonseca8caf2c82010-11-30 12:09:12 +000082 "glDrawMeshArraysSUN",
83 "glMultiDrawArrays",
84 "glMultiDrawArraysEXT",
85 "glMultiModeDrawArraysIBM",
86 ])
87
88 draw_elements_function_names = set([
89 "glDrawElements",
90 "glDrawElementsBaseVertex",
91 "glDrawElementsIndirect",
92 "glDrawElementsInstanced",
93 "glDrawElementsInstancedARB",
José Fonseca8caf2c82010-11-30 12:09:12 +000094 "glDrawElementsInstancedEXT",
José Fonsecaff8848b2011-10-09 01:04:17 +010095 "glDrawElementsInstancedBaseVertex",
96 "glDrawElementsInstancedBaseInstance",
97 "glDrawElementsInstancedBaseVertexBaseInstance",
José Fonseca8caf2c82010-11-30 12:09:12 +000098 "glDrawRangeElements",
José Fonseca8caf2c82010-11-30 12:09:12 +000099 "glDrawRangeElementsEXT",
José Fonsecaff8848b2011-10-09 01:04:17 +0100100 "glDrawRangeElementsBaseVertex",
José Fonsecafd34e4e2011-06-03 19:34:29 +0100101 "glMultiDrawElements",
102 "glMultiDrawElementsBaseVertex",
103 "glMultiDrawElementsEXT",
104 "glMultiModeDrawElementsIBM",
José Fonseca8caf2c82010-11-30 12:09:12 +0000105 ])
106
José Fonseca9b126ea2011-09-15 08:15:33 +0100107 draw_indirect_function_names = set([
108 "glDrawArraysIndirect",
109 "glDrawElementsIndirect",
110 ])
111
José Fonseca920bffd2011-06-02 10:04:52 +0100112 misc_draw_function_names = set([
113 "glClear",
114 "glEnd",
José Fonsecaf8a99a02011-06-07 20:49:56 +0100115 "glDrawPixels",
116 "glBlitFramebuffer",
117 "glBlitFramebufferEXT",
José Fonseca920bffd2011-06-02 10:04:52 +0100118 ])
119
120 bind_framebuffer_function_names = set([
121 "glBindFramebuffer",
122 "glBindFramebufferARB",
123 "glBindFramebufferEXT",
124 ])
125
José Fonsecac29f4f12011-06-11 12:19:05 +0100126 # Names of the functions that can pack into the current pixel buffer
127 # object. See also the ARB_pixel_buffer_object specification.
128 pack_function_names = set([
129 'glGetCompressedTexImage',
130 'glGetConvolutionFilter',
131 'glGetHistogram',
132 'glGetMinmax',
133 'glGetPixelMapfv',
134 'glGetPixelMapuiv',
135 'glGetPixelMapusv',
136 'glGetPolygonStipple',
137 'glGetSeparableFilter,',
138 'glGetTexImage',
139 'glReadPixels',
140 'glGetnCompressedTexImageARB',
141 'glGetnConvolutionFilterARB',
142 'glGetnHistogramARB',
143 'glGetnMinmaxARB',
144 'glGetnPixelMapfvARB',
145 'glGetnPixelMapuivARB',
146 'glGetnPixelMapusvARB',
147 'glGetnPolygonStippleARB',
148 'glGetnSeparableFilterARB',
149 'glGetnTexImageARB',
150 'glReadnPixelsARB',
151 ])
152
José Fonseca62212972011-03-23 13:22:55 +0000153 def retrace_function_body(self, function):
154 is_array_pointer = function.name in self.array_pointer_function_names
155 is_draw_array = function.name in self.draw_array_function_names
156 is_draw_elements = function.name in self.draw_elements_function_names
José Fonseca920bffd2011-06-02 10:04:52 +0100157 is_misc_draw = function.name in self.misc_draw_function_names
José Fonseca62212972011-03-23 13:22:55 +0000158
159 if is_array_pointer or is_draw_array or is_draw_elements:
José Fonseca6117e312011-04-15 23:52:58 +0100160 print ' if (glretrace::parser.version < 1) {'
José Fonseca62212972011-03-23 13:22:55 +0000161
162 if is_array_pointer or is_draw_array:
163 print ' GLint __array_buffer = 0;'
164 print ' glGetIntegerv(GL_ARRAY_BUFFER_BINDING, &__array_buffer);'
165 print ' if (!__array_buffer) {'
166 self.fail_function(function)
167 print ' }'
168
169 if is_draw_elements:
170 print ' GLint __element_array_buffer = 0;'
171 print ' glGetIntegerv(GL_ELEMENT_ARRAY_BUFFER_BINDING, &__element_array_buffer);'
172 print ' if (!__element_array_buffer) {'
173 self.fail_function(function)
174 print ' }'
175
176 print ' }'
177
José Fonsecac29f4f12011-06-11 12:19:05 +0100178 # When no pack buffer object is bound, the pack functions are no-ops.
179 if function.name in self.pack_function_names:
180 print ' GLint __pack_buffer = 0;'
181 print ' glGetIntegerv(GL_PIXEL_PACK_BUFFER_BINDING, &__pack_buffer);'
182 print ' if (!__pack_buffer) {'
José Fonsecad4ca4e22011-09-02 18:35:50 +0100183 if function.name == 'glReadPixels':
184 print ' glFinish();'
185 print ' if (glretrace::snapshot_frequency == glretrace::FREQUENCY_FRAME ||'
186 print ' glretrace::snapshot_frequency == glretrace::FREQUENCY_FRAMEBUFFER) {'
187 print ' glretrace::snapshot(call.no);'
188 print ' }'
José Fonsecac29f4f12011-06-11 12:19:05 +0100189 print ' return;'
190 print ' }'
191
José Fonseca920bffd2011-06-02 10:04:52 +0100192 # Pre-snapshots
193 if function.name in self.bind_framebuffer_function_names:
194 print ' if (glretrace::snapshot_frequency == glretrace::FREQUENCY_FRAMEBUFFER) {'
195 print ' glretrace::snapshot(call.no - 1);'
196 print ' }'
José Fonseca439ae3c2011-09-01 17:36:10 +0100197 if function.name == 'glFrameTerminatorGREMEDY':
198 print ' glretrace::frame_complete(call.no);'
199 return
José Fonseca920bffd2011-06-02 10:04:52 +0100200
José Fonseca62212972011-03-23 13:22:55 +0000201 Retracer.retrace_function_body(self, function)
202
José Fonseca920bffd2011-06-02 10:04:52 +0100203 # Post-snapshots
José Fonseca4d7f1fe2011-05-09 20:54:31 +0100204 if function.name in ('glFlush', 'glFinish'):
205 print ' if (!glretrace::double_buffer) {'
206 print ' glretrace::frame_complete(call.no);'
207 print ' }'
José Fonseca920bffd2011-06-02 10:04:52 +0100208 if is_draw_array or is_draw_elements or is_misc_draw:
209 print ' if (glretrace::snapshot_frequency == glretrace::FREQUENCY_DRAW) {'
210 print ' glretrace::snapshot(call.no);'
211 print ' }'
212
José Fonseca4d7f1fe2011-05-09 20:54:31 +0100213
José Fonsecafa15d332010-11-25 20:22:39 +0000214 def call_function(self, function):
José Fonseca757b2b62011-09-19 10:09:53 +0100215 # Infer the drawable size from GL calls
José Fonsecacdb574a2010-11-29 12:23:35 +0000216 if function.name == "glViewport":
José Fonseca757b2b62011-09-19 10:09:53 +0100217 print ' glretrace::updateDrawable(x + width, y + height);'
218 if function.name in ('glBlitFramebuffer', 'glBlitFramebufferEXT'):
219 # Some applications do all their rendering in a framebuffer, and
220 # then just blit to the drawable without ever calling glViewport.
221 print ' glretrace::updateDrawable(std::max(dstX0, dstX1), std::max(dstY0, dstY1));'
José Fonsecacdb574a2010-11-29 12:23:35 +0000222
José Fonseca3d245f42010-11-28 00:08:23 +0000223 if function.name == "glEnd":
José Fonseca32871ed2011-04-10 13:40:52 +0100224 print ' glretrace::insideGlBeginEnd = false;'
José Fonsecafea81f92011-05-23 21:20:53 +0100225
226 if function.name == 'memcpy':
227 print ' if (!dest || !src || !n) return;'
José Fonsecacdb574a2010-11-29 12:23:35 +0000228
José Fonsecafa15d332010-11-25 20:22:39 +0000229 Retracer.call_function(self, function)
José Fonsecacdb574a2010-11-29 12:23:35 +0000230
José Fonsecaecf37412011-05-21 01:56:08 +0100231 # Error checking
José Fonseca3d245f42010-11-28 00:08:23 +0000232 if function.name == "glBegin":
José Fonseca32871ed2011-04-10 13:40:52 +0100233 print ' glretrace::insideGlBeginEnd = true;'
José Fonsecab8c56072011-05-05 01:13:04 +0100234 elif function.name.startswith('gl'):
José Fonseca3d245f42010-11-28 00:08:23 +0000235 # glGetError is not allowed inside glBegin/glEnd
José Fonsecaecf37412011-05-21 01:56:08 +0100236 print ' if (!glretrace::benchmark && !glretrace::insideGlBeginEnd) {'
237 print ' glretrace::checkGlError(call);'
238 if function.name in ('glProgramStringARB', 'glProgramStringNV'):
239 print r' GLint error_position = -1;'
240 print r' glGetIntegerv(GL_PROGRAM_ERROR_POSITION_ARB, &error_position);'
241 print r' if (error_position != -1) {'
242 print r' const char *error_string = (const char *)glGetString(GL_PROGRAM_ERROR_STRING_ARB);'
José Fonsecab1bb3c22011-10-08 20:23:18 +0100243 print r' retrace::warning(call) << error_string << "\n";'
José Fonsecaecf37412011-05-21 01:56:08 +0100244 print r' }'
245 if function.name == 'glCompileShader':
246 print r' GLint compile_status = 0;'
247 print r' glGetShaderiv(shader, GL_COMPILE_STATUS, &compile_status);'
248 print r' if (!compile_status) {'
249 print r' GLint info_log_length = 0;'
250 print r' glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &info_log_length);'
251 print r' GLchar *infoLog = new GLchar[info_log_length];'
252 print r' glGetShaderInfoLog(shader, info_log_length, NULL, infoLog);'
José Fonsecab1bb3c22011-10-08 20:23:18 +0100253 print r' retrace::warning(call) << infoLog << "\n";'
José Fonsecaecf37412011-05-21 01:56:08 +0100254 print r' delete [] infoLog;'
255 print r' }'
256 if function.name == 'glLinkProgram':
257 print r' GLint link_status = 0;'
258 print r' glGetProgramiv(program, GL_LINK_STATUS, &link_status);'
259 print r' if (!link_status) {'
260 print r' GLint info_log_length = 0;'
261 print r' glGetProgramiv(program, GL_INFO_LOG_LENGTH, &info_log_length);'
262 print r' GLchar *infoLog = new GLchar[info_log_length];'
263 print r' glGetProgramInfoLog(program, info_log_length, NULL, infoLog);'
José Fonsecab1bb3c22011-10-08 20:23:18 +0100264 print r' retrace::warning(call) << infoLog << "\n";'
José Fonsecaecf37412011-05-21 01:56:08 +0100265 print r' delete [] infoLog;'
266 print r' }'
267 if function.name == 'glCompileShaderARB':
268 print r' GLint compile_status = 0;'
269 print r' glGetObjectParameterivARB(shaderObj, GL_OBJECT_COMPILE_STATUS_ARB, &compile_status);'
270 print r' if (!compile_status) {'
271 print r' GLint info_log_length = 0;'
272 print r' glGetObjectParameterivARB(shaderObj, GL_OBJECT_INFO_LOG_LENGTH_ARB, &info_log_length);'
273 print r' GLchar *infoLog = new GLchar[info_log_length];'
274 print r' glGetInfoLogARB(shaderObj, info_log_length, NULL, infoLog);'
José Fonsecab1bb3c22011-10-08 20:23:18 +0100275 print r' retrace::warning(call) << infoLog << "\n";'
José Fonsecaecf37412011-05-21 01:56:08 +0100276 print r' delete [] infoLog;'
277 print r' }'
278 if function.name == 'glLinkProgramARB':
279 print r' GLint link_status = 0;'
280 print r' glGetObjectParameterivARB(programObj, GL_OBJECT_LINK_STATUS_ARB, &link_status);'
281 print r' if (!link_status) {'
282 print r' GLint info_log_length = 0;'
283 print r' glGetObjectParameterivARB(programObj, GL_OBJECT_INFO_LOG_LENGTH_ARB, &info_log_length);'
284 print r' GLchar *infoLog = new GLchar[info_log_length];'
285 print r' glGetInfoLogARB(programObj, info_log_length, NULL, infoLog);'
José Fonsecab1bb3c22011-10-08 20:23:18 +0100286 print r' retrace::warning(call) << infoLog << "\n";'
José Fonsecaecf37412011-05-21 01:56:08 +0100287 print r' delete [] infoLog;'
288 print r' }'
José Fonsecafea81f92011-05-23 21:20:53 +0100289 if function.name in ('glMapBuffer', 'glMapBufferARB', 'glMapBufferRange', 'glMapNamedBufferEXT', 'glMapNamedBufferRangeEXT'):
290 print r' if (!__result) {'
José Fonsecab1bb3c22011-10-08 20:23:18 +0100291 print r' retrace::warning(call) << "failed to map buffer\n";'
José Fonsecafea81f92011-05-23 21:20:53 +0100292 print r' }'
José Fonseca91492d22011-05-23 21:20:31 +0100293 if function.name in ('glGetAttribLocation', 'glGetAttribLocationARB'):
294 print r' GLint __orig_result = call.ret->toSInt();'
295 print r' if (__result != __orig_result) {'
José Fonsecab1bb3c22011-10-08 20:23:18 +0100296 print r' retrace::warning(call) << "vertex attrib location mismatch " << __orig_result << " -> " << __result << "\n";'
José Fonseca91492d22011-05-23 21:20:31 +0100297 print r' }'
José Fonsecad5377812011-06-07 20:48:55 +0100298 if function.name in ('glCheckFramebufferStatus', 'glCheckFramebufferStatusEXT', 'glCheckNamedFramebufferStatusEXT'):
299 print r' GLint __orig_result = call.ret->toSInt();'
300 print r' if (__orig_result == GL_FRAMEBUFFER_COMPLETE &&'
301 print r' __result != GL_FRAMEBUFFER_COMPLETE) {'
José Fonsecab1bb3c22011-10-08 20:23:18 +0100302 print r' retrace::warning(call) << "incomplete framebuffer (" << glstate::enumToString(__result) << ")\n";'
José Fonsecad5377812011-06-07 20:48:55 +0100303 print r' }'
José Fonsecaecf37412011-05-21 01:56:08 +0100304 print ' }'
José Fonsecae4999b92011-05-05 00:31:01 +0100305
José Fonsecadacd8dd2010-11-25 17:50:26 +0000306 def extract_arg(self, function, arg, arg_type, lvalue, rvalue):
José Fonseca7f5163e2011-03-31 23:37:26 +0100307 if function.name in self.array_pointer_function_names and arg.name == 'pointer':
José Fonseca36a0fd32011-08-28 12:37:30 +0100308 print ' %s = static_cast<%s>(%s.toPointer(true));' % (lvalue, arg_type, rvalue)
José Fonseca14c21bc2011-02-20 23:32:22 +0000309 return
310
José Fonseca9b126ea2011-09-15 08:15:33 +0100311 if function.name in self.draw_elements_function_names and arg.name == 'indices' or\
312 function.name in self.draw_indirect_function_names and arg.name == 'indirect':
José Fonsecafd34e4e2011-06-03 19:34:29 +0100313 self.extract_opaque_arg(function, arg, arg_type, lvalue, rvalue)
José Fonseca8a844ae2010-12-06 18:50:52 +0000314 return
José Fonsecadacd8dd2010-11-25 17:50:26 +0000315
José Fonsecac29f4f12011-06-11 12:19:05 +0100316 # Handle pointer with offsets into the current pack pixel buffer
317 # object.
318 if function.name in self.pack_function_names and arg.output:
319 self.extract_opaque_arg(function, arg, arg_type, lvalue, rvalue)
320 return
321
José Fonseca3c1b7ce2011-05-09 11:22:54 +0100322 if arg.type is glapi.GLlocation \
323 and 'program' not in [arg.name for arg in function.args]:
José Fonseca8a844ae2010-12-06 18:50:52 +0000324 print ' GLint program = -1;'
325 print ' glGetIntegerv(GL_CURRENT_PROGRAM, &program);'
José Fonseca3c1b7ce2011-05-09 11:22:54 +0100326
327 if arg.type is glapi.GLlocationARB \
328 and 'programObj' not in [arg.name for arg in function.args]:
José Fonseca3a84b682011-05-09 11:33:47 +0100329 print ' GLhandleARB programObj = glGetHandleARB(GL_PROGRAM_OBJECT_ARB);'
José Fonseca8a844ae2010-12-06 18:50:52 +0000330
331 Retracer.extract_arg(self, function, arg, arg_type, lvalue, rvalue)
José Fonsecae6a50bd2010-11-24 10:12:22 +0000332
José Fonseca42926462011-05-09 11:32:15 +0100333 # Don't try to use more samples than the implementation supports
334 if arg.name == 'samples':
335 assert arg.type is glapi.GLsizei
336 print ' GLint max_samples = 0;'
337 print ' glGetIntegerv(GL_MAX_SAMPLES, &max_samples);'
338 print ' if (samples > max_samples) {'
339 print ' samples = max_samples;'
340 print ' }'
341
José Fonsecae6a50bd2010-11-24 10:12:22 +0000342
José Fonseca7e329022010-11-19 17:05:18 +0000343if __name__ == '__main__':
José Fonseca796a3042010-11-29 14:21:06 +0000344 print r'''
José Fonseca867b1b72011-04-24 11:58:04 +0100345#include <string.h>
346
José Fonsecadf66a902010-11-29 13:24:20 +0000347#include "glproc.hpp"
José Fonseca32871ed2011-04-10 13:40:52 +0100348#include "glretrace.hpp"
José Fonseca56391262011-09-19 09:30:10 +0100349#include "glstate.hpp"
José Fonseca589082d2011-03-30 09:10:40 +0100350
José Fonsecadf66a902010-11-29 13:24:20 +0000351
José Fonseca3d245f42010-11-28 00:08:23 +0000352'''
José Fonsecae0e61402010-11-25 15:03:23 +0000353 api = glapi.glapi
José Fonseca867b1b72011-04-24 11:58:04 +0100354 api.add_function(glapi.memcpy)
José Fonsecae0e61402010-11-25 15:03:23 +0000355 retracer = GlRetracer()
José Fonseca06aa2842011-05-05 07:55:54 +0100356 retracer.retrace_api(api)