blob: 925fb181dd1751e8b8032958fa981636dda1c688 [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",
81 "glDrawMeshArraysSUN",
82 "glMultiDrawArrays",
83 "glMultiDrawArraysEXT",
84 "glMultiModeDrawArraysIBM",
85 ])
86
87 draw_elements_function_names = set([
88 "glDrawElements",
89 "glDrawElementsBaseVertex",
90 "glDrawElementsIndirect",
91 "glDrawElementsInstanced",
92 "glDrawElementsInstancedARB",
93 "glDrawElementsInstancedBaseVertex",
94 "glDrawElementsInstancedEXT",
95 "glDrawRangeElements",
96 "glDrawRangeElementsBaseVertex",
97 "glDrawRangeElementsEXT",
José Fonsecafd34e4e2011-06-03 19:34:29 +010098 "glMultiDrawElements",
99 "glMultiDrawElementsBaseVertex",
100 "glMultiDrawElementsEXT",
101 "glMultiModeDrawElementsIBM",
José Fonseca8caf2c82010-11-30 12:09:12 +0000102 ])
103
José Fonseca9b126ea2011-09-15 08:15:33 +0100104 draw_indirect_function_names = set([
105 "glDrawArraysIndirect",
106 "glDrawElementsIndirect",
107 ])
108
José Fonseca920bffd2011-06-02 10:04:52 +0100109 misc_draw_function_names = set([
110 "glClear",
111 "glEnd",
José Fonsecaf8a99a02011-06-07 20:49:56 +0100112 "glDrawPixels",
113 "glBlitFramebuffer",
114 "glBlitFramebufferEXT",
José Fonseca920bffd2011-06-02 10:04:52 +0100115 ])
116
117 bind_framebuffer_function_names = set([
118 "glBindFramebuffer",
119 "glBindFramebufferARB",
120 "glBindFramebufferEXT",
121 ])
122
José Fonsecac29f4f12011-06-11 12:19:05 +0100123 # Names of the functions that can pack into the current pixel buffer
124 # object. See also the ARB_pixel_buffer_object specification.
125 pack_function_names = set([
126 'glGetCompressedTexImage',
127 'glGetConvolutionFilter',
128 'glGetHistogram',
129 'glGetMinmax',
130 'glGetPixelMapfv',
131 'glGetPixelMapuiv',
132 'glGetPixelMapusv',
133 'glGetPolygonStipple',
134 'glGetSeparableFilter,',
135 'glGetTexImage',
136 'glReadPixels',
137 'glGetnCompressedTexImageARB',
138 'glGetnConvolutionFilterARB',
139 'glGetnHistogramARB',
140 'glGetnMinmaxARB',
141 'glGetnPixelMapfvARB',
142 'glGetnPixelMapuivARB',
143 'glGetnPixelMapusvARB',
144 'glGetnPolygonStippleARB',
145 'glGetnSeparableFilterARB',
146 'glGetnTexImageARB',
147 'glReadnPixelsARB',
148 ])
149
José Fonseca62212972011-03-23 13:22:55 +0000150 def retrace_function_body(self, function):
151 is_array_pointer = function.name in self.array_pointer_function_names
152 is_draw_array = function.name in self.draw_array_function_names
153 is_draw_elements = function.name in self.draw_elements_function_names
José Fonseca920bffd2011-06-02 10:04:52 +0100154 is_misc_draw = function.name in self.misc_draw_function_names
José Fonseca62212972011-03-23 13:22:55 +0000155
156 if is_array_pointer or is_draw_array or is_draw_elements:
José Fonseca6117e312011-04-15 23:52:58 +0100157 print ' if (glretrace::parser.version < 1) {'
José Fonseca62212972011-03-23 13:22:55 +0000158
159 if is_array_pointer or is_draw_array:
160 print ' GLint __array_buffer = 0;'
161 print ' glGetIntegerv(GL_ARRAY_BUFFER_BINDING, &__array_buffer);'
162 print ' if (!__array_buffer) {'
163 self.fail_function(function)
164 print ' }'
165
166 if is_draw_elements:
167 print ' GLint __element_array_buffer = 0;'
168 print ' glGetIntegerv(GL_ELEMENT_ARRAY_BUFFER_BINDING, &__element_array_buffer);'
169 print ' if (!__element_array_buffer) {'
170 self.fail_function(function)
171 print ' }'
172
173 print ' }'
174
José Fonsecac29f4f12011-06-11 12:19:05 +0100175 # When no pack buffer object is bound, the pack functions are no-ops.
176 if function.name in self.pack_function_names:
177 print ' GLint __pack_buffer = 0;'
178 print ' glGetIntegerv(GL_PIXEL_PACK_BUFFER_BINDING, &__pack_buffer);'
179 print ' if (!__pack_buffer) {'
José Fonsecad4ca4e22011-09-02 18:35:50 +0100180 if function.name == 'glReadPixels':
181 print ' glFinish();'
182 print ' if (glretrace::snapshot_frequency == glretrace::FREQUENCY_FRAME ||'
183 print ' glretrace::snapshot_frequency == glretrace::FREQUENCY_FRAMEBUFFER) {'
184 print ' glretrace::snapshot(call.no);'
185 print ' }'
José Fonsecac29f4f12011-06-11 12:19:05 +0100186 print ' return;'
187 print ' }'
188
José Fonseca920bffd2011-06-02 10:04:52 +0100189 # Pre-snapshots
190 if function.name in self.bind_framebuffer_function_names:
191 print ' if (glretrace::snapshot_frequency == glretrace::FREQUENCY_FRAMEBUFFER) {'
192 print ' glretrace::snapshot(call.no - 1);'
193 print ' }'
José Fonseca439ae3c2011-09-01 17:36:10 +0100194 if function.name == 'glFrameTerminatorGREMEDY':
195 print ' glretrace::frame_complete(call.no);'
196 return
José Fonseca920bffd2011-06-02 10:04:52 +0100197
José Fonseca62212972011-03-23 13:22:55 +0000198 Retracer.retrace_function_body(self, function)
199
José Fonseca920bffd2011-06-02 10:04:52 +0100200 # Post-snapshots
José Fonseca4d7f1fe2011-05-09 20:54:31 +0100201 if function.name in ('glFlush', 'glFinish'):
202 print ' if (!glretrace::double_buffer) {'
203 print ' glretrace::frame_complete(call.no);'
204 print ' }'
José Fonseca920bffd2011-06-02 10:04:52 +0100205 if is_draw_array or is_draw_elements or is_misc_draw:
206 print ' if (glretrace::snapshot_frequency == glretrace::FREQUENCY_DRAW) {'
207 print ' glretrace::snapshot(call.no);'
208 print ' }'
209
José Fonseca4d7f1fe2011-05-09 20:54:31 +0100210
José Fonsecafa15d332010-11-25 20:22:39 +0000211 def call_function(self, function):
José Fonseca757b2b62011-09-19 10:09:53 +0100212 # Infer the drawable size from GL calls
José Fonsecacdb574a2010-11-29 12:23:35 +0000213 if function.name == "glViewport":
José Fonseca757b2b62011-09-19 10:09:53 +0100214 print ' glretrace::updateDrawable(x + width, y + height);'
215 if function.name in ('glBlitFramebuffer', 'glBlitFramebufferEXT'):
216 # Some applications do all their rendering in a framebuffer, and
217 # then just blit to the drawable without ever calling glViewport.
218 print ' glretrace::updateDrawable(std::max(dstX0, dstX1), std::max(dstY0, dstY1));'
José Fonsecacdb574a2010-11-29 12:23:35 +0000219
José Fonseca3d245f42010-11-28 00:08:23 +0000220 if function.name == "glEnd":
José Fonseca32871ed2011-04-10 13:40:52 +0100221 print ' glretrace::insideGlBeginEnd = false;'
José Fonsecafea81f92011-05-23 21:20:53 +0100222
223 if function.name == 'memcpy':
224 print ' if (!dest || !src || !n) return;'
José Fonsecacdb574a2010-11-29 12:23:35 +0000225
José Fonsecafa15d332010-11-25 20:22:39 +0000226 Retracer.call_function(self, function)
José Fonsecacdb574a2010-11-29 12:23:35 +0000227
José Fonsecaecf37412011-05-21 01:56:08 +0100228 # Error checking
José Fonseca3d245f42010-11-28 00:08:23 +0000229 if function.name == "glBegin":
José Fonseca32871ed2011-04-10 13:40:52 +0100230 print ' glretrace::insideGlBeginEnd = true;'
José Fonsecab8c56072011-05-05 01:13:04 +0100231 elif function.name.startswith('gl'):
José Fonseca3d245f42010-11-28 00:08:23 +0000232 # glGetError is not allowed inside glBegin/glEnd
José Fonsecaecf37412011-05-21 01:56:08 +0100233 print ' if (!glretrace::benchmark && !glretrace::insideGlBeginEnd) {'
234 print ' glretrace::checkGlError(call);'
235 if function.name in ('glProgramStringARB', 'glProgramStringNV'):
236 print r' GLint error_position = -1;'
237 print r' glGetIntegerv(GL_PROGRAM_ERROR_POSITION_ARB, &error_position);'
238 print r' if (error_position != -1) {'
239 print r' const char *error_string = (const char *)glGetString(GL_PROGRAM_ERROR_STRING_ARB);'
240 print r' std::cerr << call.no << ": warning: " << error_string << "\n";'
241 print r' }'
242 if function.name == 'glCompileShader':
243 print r' GLint compile_status = 0;'
244 print r' glGetShaderiv(shader, GL_COMPILE_STATUS, &compile_status);'
245 print r' if (!compile_status) {'
246 print r' GLint info_log_length = 0;'
247 print r' glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &info_log_length);'
248 print r' GLchar *infoLog = new GLchar[info_log_length];'
249 print r' glGetShaderInfoLog(shader, info_log_length, NULL, infoLog);'
250 print r' std::cerr << call.no << ": warning: " << infoLog << "\n";'
251 print r' delete [] infoLog;'
252 print r' }'
253 if function.name == 'glLinkProgram':
254 print r' GLint link_status = 0;'
255 print r' glGetProgramiv(program, GL_LINK_STATUS, &link_status);'
256 print r' if (!link_status) {'
257 print r' GLint info_log_length = 0;'
258 print r' glGetProgramiv(program, GL_INFO_LOG_LENGTH, &info_log_length);'
259 print r' GLchar *infoLog = new GLchar[info_log_length];'
260 print r' glGetProgramInfoLog(program, info_log_length, NULL, infoLog);'
261 print r' std::cerr << call.no << ": warning: " << infoLog << "\n";'
262 print r' delete [] infoLog;'
263 print r' }'
264 if function.name == 'glCompileShaderARB':
265 print r' GLint compile_status = 0;'
266 print r' glGetObjectParameterivARB(shaderObj, GL_OBJECT_COMPILE_STATUS_ARB, &compile_status);'
267 print r' if (!compile_status) {'
268 print r' GLint info_log_length = 0;'
269 print r' glGetObjectParameterivARB(shaderObj, GL_OBJECT_INFO_LOG_LENGTH_ARB, &info_log_length);'
270 print r' GLchar *infoLog = new GLchar[info_log_length];'
271 print r' glGetInfoLogARB(shaderObj, info_log_length, NULL, infoLog);'
272 print r' std::cerr << call.no << ": warning: " << infoLog << "\n";'
273 print r' delete [] infoLog;'
274 print r' }'
275 if function.name == 'glLinkProgramARB':
276 print r' GLint link_status = 0;'
277 print r' glGetObjectParameterivARB(programObj, GL_OBJECT_LINK_STATUS_ARB, &link_status);'
278 print r' if (!link_status) {'
279 print r' GLint info_log_length = 0;'
280 print r' glGetObjectParameterivARB(programObj, GL_OBJECT_INFO_LOG_LENGTH_ARB, &info_log_length);'
281 print r' GLchar *infoLog = new GLchar[info_log_length];'
282 print r' glGetInfoLogARB(programObj, info_log_length, NULL, infoLog);'
283 print r' std::cerr << call.no << ": warning: " << infoLog << "\n";'
284 print r' delete [] infoLog;'
285 print r' }'
José Fonsecafea81f92011-05-23 21:20:53 +0100286 if function.name in ('glMapBuffer', 'glMapBufferARB', 'glMapBufferRange', 'glMapNamedBufferEXT', 'glMapNamedBufferRangeEXT'):
287 print r' if (!__result) {'
288 print r' std::cerr << call.no << ": warning: failed to map buffer\n";'
289 print r' }'
José Fonseca91492d22011-05-23 21:20:31 +0100290 if function.name in ('glGetAttribLocation', 'glGetAttribLocationARB'):
291 print r' GLint __orig_result = call.ret->toSInt();'
292 print r' if (__result != __orig_result) {'
José Fonseca56391262011-09-19 09:30:10 +0100293 print r' std::cerr << call.no << ": warning: vertex attrib location mismatch " << __orig_result << " -> " << __result << "\n";'
José Fonseca91492d22011-05-23 21:20:31 +0100294 print r' }'
José Fonsecad5377812011-06-07 20:48:55 +0100295 if function.name in ('glCheckFramebufferStatus', 'glCheckFramebufferStatusEXT', 'glCheckNamedFramebufferStatusEXT'):
296 print r' GLint __orig_result = call.ret->toSInt();'
297 print r' if (__orig_result == GL_FRAMEBUFFER_COMPLETE &&'
298 print r' __result != GL_FRAMEBUFFER_COMPLETE) {'
José Fonseca56391262011-09-19 09:30:10 +0100299 print r' std::cerr << call.no << ": warning: incomplete framebuffer (" << glstate::enumToString(__result) << ")\n";'
José Fonsecad5377812011-06-07 20:48:55 +0100300 print r' }'
José Fonsecaecf37412011-05-21 01:56:08 +0100301 print ' }'
José Fonsecae4999b92011-05-05 00:31:01 +0100302
José Fonsecadacd8dd2010-11-25 17:50:26 +0000303 def extract_arg(self, function, arg, arg_type, lvalue, rvalue):
José Fonseca7f5163e2011-03-31 23:37:26 +0100304 if function.name in self.array_pointer_function_names and arg.name == 'pointer':
José Fonseca36a0fd32011-08-28 12:37:30 +0100305 print ' %s = static_cast<%s>(%s.toPointer(true));' % (lvalue, arg_type, rvalue)
José Fonseca14c21bc2011-02-20 23:32:22 +0000306 return
307
José Fonseca9b126ea2011-09-15 08:15:33 +0100308 if function.name in self.draw_elements_function_names and arg.name == 'indices' or\
309 function.name in self.draw_indirect_function_names and arg.name == 'indirect':
José Fonsecafd34e4e2011-06-03 19:34:29 +0100310 self.extract_opaque_arg(function, arg, arg_type, lvalue, rvalue)
José Fonseca8a844ae2010-12-06 18:50:52 +0000311 return
José Fonsecadacd8dd2010-11-25 17:50:26 +0000312
José Fonsecac29f4f12011-06-11 12:19:05 +0100313 # Handle pointer with offsets into the current pack pixel buffer
314 # object.
315 if function.name in self.pack_function_names and arg.output:
316 self.extract_opaque_arg(function, arg, arg_type, lvalue, rvalue)
317 return
318
José Fonseca3c1b7ce2011-05-09 11:22:54 +0100319 if arg.type is glapi.GLlocation \
320 and 'program' not in [arg.name for arg in function.args]:
José Fonseca8a844ae2010-12-06 18:50:52 +0000321 print ' GLint program = -1;'
322 print ' glGetIntegerv(GL_CURRENT_PROGRAM, &program);'
José Fonseca3c1b7ce2011-05-09 11:22:54 +0100323
324 if arg.type is glapi.GLlocationARB \
325 and 'programObj' not in [arg.name for arg in function.args]:
José Fonseca3a84b682011-05-09 11:33:47 +0100326 print ' GLhandleARB programObj = glGetHandleARB(GL_PROGRAM_OBJECT_ARB);'
José Fonseca8a844ae2010-12-06 18:50:52 +0000327
328 Retracer.extract_arg(self, function, arg, arg_type, lvalue, rvalue)
José Fonsecae6a50bd2010-11-24 10:12:22 +0000329
José Fonseca42926462011-05-09 11:32:15 +0100330 # Don't try to use more samples than the implementation supports
331 if arg.name == 'samples':
332 assert arg.type is glapi.GLsizei
333 print ' GLint max_samples = 0;'
334 print ' glGetIntegerv(GL_MAX_SAMPLES, &max_samples);'
335 print ' if (samples > max_samples) {'
336 print ' samples = max_samples;'
337 print ' }'
338
José Fonsecae6a50bd2010-11-24 10:12:22 +0000339
José Fonseca7e329022010-11-19 17:05:18 +0000340if __name__ == '__main__':
José Fonseca796a3042010-11-29 14:21:06 +0000341 print r'''
José Fonseca867b1b72011-04-24 11:58:04 +0100342#include <string.h>
343
José Fonsecadf66a902010-11-29 13:24:20 +0000344#include "glproc.hpp"
José Fonseca32871ed2011-04-10 13:40:52 +0100345#include "glretrace.hpp"
José Fonseca56391262011-09-19 09:30:10 +0100346#include "glstate.hpp"
José Fonseca589082d2011-03-30 09:10:40 +0100347
José Fonsecadf66a902010-11-29 13:24:20 +0000348
José Fonseca3d245f42010-11-28 00:08:23 +0000349'''
José Fonsecae0e61402010-11-25 15:03:23 +0000350 api = glapi.glapi
José Fonseca867b1b72011-04-24 11:58:04 +0100351 api.add_function(glapi.memcpy)
José Fonsecae0e61402010-11-25 15:03:23 +0000352 retracer = GlRetracer()
José Fonseca06aa2842011-05-05 07:55:54 +0100353 retracer.retrace_api(api)