blob: 1497e326d91e9003aa848a875bdfa5df3fde6c17 [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é Fonsecaac3d4642014-08-14 19:20:03 +010030import re
31import sys
32
José Fonseca9d27a542012-04-14 17:22:57 +010033from retrace import Retracer
José Fonsecabd86a222011-09-27 09:21:38 +010034import specs.stdapi as stdapi
35import specs.glapi as glapi
José Fonseca7e329022010-11-19 17:05:18 +000036
37
José Fonsecadacd8dd2010-11-25 17:50:26 +000038class GlRetracer(Retracer):
José Fonsecac9edb832010-11-20 09:03:10 +000039
José Fonseca2741ed82011-10-07 23:36:39 +010040 table_name = 'glretrace::gl_callbacks'
41
José Fonseca9a240382014-11-12 22:32:17 +000042 def retraceApi(self, api):
43 # Ensure pack function have side effects
44 abort = False
45 for function in api.getAllFunctions():
Jose Fonseca0a676c52016-04-04 23:24:32 +010046 if not function.sideeffects:
47 if self.pack_function_regex.match(function.name) or \
48 function.name.startswith('glGetQueryObject'):
49 sys.stderr.write('error: function %s must have sideeffects\n' % function.name)
50 abort = True
José Fonseca9a240382014-11-12 22:32:17 +000051 if abort:
52 sys.exit(1)
53
54 Retracer.retraceApi(self, api)
José Fonseca3d245f42010-11-28 00:08:23 +000055
José Fonseca62212972011-03-23 13:22:55 +000056 array_pointer_function_names = set((
57 "glVertexPointer",
58 "glNormalPointer",
59 "glColorPointer",
60 "glIndexPointer",
61 "glTexCoordPointer",
62 "glEdgeFlagPointer",
63 "glFogCoordPointer",
64 "glSecondaryColorPointer",
65
66 "glInterleavedArrays",
67
José Fonsecaac5285b2011-05-04 11:09:08 +010068 "glVertexPointerEXT",
69 "glNormalPointerEXT",
70 "glColorPointerEXT",
71 "glIndexPointerEXT",
72 "glTexCoordPointerEXT",
73 "glEdgeFlagPointerEXT",
74 "glFogCoordPointerEXT",
75 "glSecondaryColorPointerEXT",
José Fonseca62212972011-03-23 13:22:55 +000076
José Fonseca7f5163e2011-03-31 23:37:26 +010077 "glVertexAttribPointer",
78 "glVertexAttribPointerARB",
79 "glVertexAttribPointerNV",
José Fonsecaac5285b2011-05-04 11:09:08 +010080 "glVertexAttribIPointer",
81 "glVertexAttribIPointerEXT",
José Fonseca7f5163e2011-03-31 23:37:26 +010082 "glVertexAttribLPointer",
83 "glVertexAttribLPointerEXT",
José Fonseca62212972011-03-23 13:22:55 +000084
85 #"glMatrixIndexPointerARB",
86 ))
87
José Fonsecaac3d4642014-08-14 19:20:03 +010088 draw_arrays_function_regex = re.compile(r'^gl([A-Z][a-z]+)*Draw(Range)?Arrays([A-Z][a-zA-Z]*)?$' )
89 draw_elements_function_regex = re.compile(r'^gl([A-Z][a-z]+)*Draw(Range)?Elements([A-Z][a-zA-Z]*)?$' )
90 draw_indirect_function_regex = re.compile(r'^gl([A-Z][a-z]+)*Draw(Range)?(Arrays|Elements)Indirect([A-Z][a-zA-Z]*)?$' )
José Fonseca9b126ea2011-09-15 08:15:33 +010091
José Fonsecae16ee252014-11-18 20:27:46 +000092 misc_draw_function_regex = re.compile(r'^gl(' + r'|'.join([
93 r'CallList',
94 r'CallLists',
95 r'Clear',
96 r'End',
97 r'DrawPixels',
José Fonseca1c968fd2014-12-30 20:58:42 +000098 r'DrawTransformFeedback([A-Z][a-zA-Z]*)?',
José Fonsecae16ee252014-11-18 20:27:46 +000099 r'BlitFramebuffer',
José Fonseca1c968fd2014-12-30 20:58:42 +0000100 r'Rect[dfis]v?',
101 r'EvalMesh[0-9]+',
José Fonsecae16ee252014-11-18 20:27:46 +0000102 ]) + r')[0-9A-Z]*$')
José Fonseca920bffd2011-06-02 10:04:52 +0100103
José Fonsecae16ee252014-11-18 20:27:46 +0000104
105 bind_framebuffer_function_regex = re.compile(r'^glBindFramebuffer[0-9A-Z]*$')
José Fonseca920bffd2011-06-02 10:04:52 +0100106
José Fonsecac29f4f12011-06-11 12:19:05 +0100107 # Names of the functions that can pack into the current pixel buffer
108 # object. See also the ARB_pixel_buffer_object specification.
José Fonseca920f8e72014-11-12 21:31:59 +0000109 pack_function_regex = re.compile(r'^gl(' + r'|'.join([
110 r'Getn?Histogram',
111 r'Getn?PolygonStipple',
112 r'Getn?PixelMap[a-z]+v',
113 r'Getn?Minmax',
114 r'Getn?(Convolution|Separable)Filter',
115 r'Getn?(Compressed)?(Multi)?Tex(ture)?(Sub)?Image',
116 r'Readn?Pixels',
117 ]) + r')[0-9A-Z]*$')
José Fonsecac29f4f12011-06-11 12:19:05 +0100118
José Fonsecabd503ed2014-11-12 21:36:10 +0000119 map_function_regex = re.compile(r'^glMap(|Named|Object)Buffer(Range)?[0-9A-Z]*$')
José Fonseca46a48392011-10-14 11:34:27 +0100120
José Fonsecabd503ed2014-11-12 21:36:10 +0000121 unmap_function_regex = re.compile(r'^glUnmap(|Named|Object)Buffer[0-9A-Z]*$')
José Fonseca46a48392011-10-14 11:34:27 +0100122
José Fonseca54f304a2012-01-14 19:33:08 +0000123 def retraceFunctionBody(self, function):
José Fonseca62212972011-03-23 13:22:55 +0000124 is_array_pointer = function.name in self.array_pointer_function_names
José Fonsecaac3d4642014-08-14 19:20:03 +0100125 is_draw_arrays = self.draw_arrays_function_regex.match(function.name) is not None
126 is_draw_elements = self.draw_elements_function_regex.match(function.name) is not None
127 is_draw_indirect = self.draw_indirect_function_regex.match(function.name) is not None
José Fonsecae16ee252014-11-18 20:27:46 +0000128 is_misc_draw = self.misc_draw_function_regex.match(function.name)
José Fonseca62212972011-03-23 13:22:55 +0000129
Jose Fonseca0a676c52016-04-04 23:24:32 +0100130 if function.name.startswith('gl') and not function.name.startswith('glX'):
131 # The Windows OpenGL runtime will skip calls when there's no
132 # context bound to the current context, but this might cause
133 # crashes on other systems, particularly with NVIDIA Linux drivers.
Piotr Podsiadły0b8b0192019-01-03 20:39:55 +0100134 print(r' glretrace::Context *currentContext = glretrace::getCurrentContext();')
135 print(r' if (!currentContext) {')
136 print(r' if (retrace::debug > 0) {')
137 print(r' retrace::warning(call) << "no current context\n";')
138 print(r' }')
139 print(r'#ifndef _WIN32')
140 print(r' return;')
141 print(r'#endif')
142 print(r' }')
Jose Fonseca0a676c52016-04-04 23:24:32 +0100143
Piotr Podsiadły0b8b0192019-01-03 20:39:55 +0100144 print(r' if (retrace::markers) {')
145 print(r' glretrace::insertCallMarker(call, currentContext);')
146 print(r' }')
Jose Fonseca0a676c52016-04-04 23:24:32 +0100147
José Fonsecaac3d4642014-08-14 19:20:03 +0100148 # For backwards compatibility with old traces where non VBO drawing was supported
149 if (is_array_pointer or is_draw_arrays or is_draw_elements) and not is_draw_indirect:
Piotr Podsiadły0b8b0192019-01-03 20:39:55 +0100150 print(' if (retrace::parser->getVersion() < 1) {')
José Fonseca62212972011-03-23 13:22:55 +0000151
José Fonsecaac3d4642014-08-14 19:20:03 +0100152 if is_array_pointer or is_draw_arrays:
Piotr Podsiadły0b8b0192019-01-03 20:39:55 +0100153 print(' GLint _array_buffer = 0;')
154 print(' glGetIntegerv(GL_ARRAY_BUFFER_BINDING, &_array_buffer);')
155 print(' if (!_array_buffer) {')
José Fonseca54f304a2012-01-14 19:33:08 +0000156 self.failFunction(function)
Piotr Podsiadły0b8b0192019-01-03 20:39:55 +0100157 print(' }')
José Fonseca62212972011-03-23 13:22:55 +0000158
159 if is_draw_elements:
Piotr Podsiadły0b8b0192019-01-03 20:39:55 +0100160 print(' GLint _element_array_buffer = 0;')
161 print(' glGetIntegerv(GL_ELEMENT_ARRAY_BUFFER_BINDING, &_element_array_buffer);')
162 print(' if (!_element_array_buffer) {')
José Fonseca54f304a2012-01-14 19:33:08 +0000163 self.failFunction(function)
Piotr Podsiadły0b8b0192019-01-03 20:39:55 +0100164 print(' }')
José Fonseca62212972011-03-23 13:22:55 +0000165
Piotr Podsiadły0b8b0192019-01-03 20:39:55 +0100166 print(' }')
José Fonseca62212972011-03-23 13:22:55 +0000167
José Fonsecac29f4f12011-06-11 12:19:05 +0100168 # When no pack buffer object is bound, the pack functions are no-ops.
José Fonseca920f8e72014-11-12 21:31:59 +0000169 if self.pack_function_regex.match(function.name):
Piotr Podsiadły0b8b0192019-01-03 20:39:55 +0100170 print(r' GLint _pack_buffer = 0;')
Jose Fonseca4b448392019-08-22 11:04:53 +0100171 print(r' if (currentContext && currentContext->features().pixel_buffer_object) {')
Piotr Podsiadły0b8b0192019-01-03 20:39:55 +0100172 print(r' glGetIntegerv(GL_PIXEL_PACK_BUFFER_BINDING, &_pack_buffer);')
173 print(r' }')
174 print(r' if (!_pack_buffer) {')
175 print(r' return;')
176 print(r' }')
José Fonsecac29f4f12011-06-11 12:19:05 +0100177
Jose Fonseca0a676c52016-04-04 23:24:32 +0100178 # When no query buffer object is bound, glGetQueryObject is a no-op.
179 if function.name.startswith('glGetQueryObject'):
Piotr Podsiadły0b8b0192019-01-03 20:39:55 +0100180 print(r' GLint _query_buffer = 0;')
Jose Fonseca4b448392019-08-22 11:04:53 +0100181 print(r' if (currentContext && currentContext->features().query_buffer_object) {')
Piotr Podsiadły0b8b0192019-01-03 20:39:55 +0100182 print(r' glGetIntegerv(GL_QUERY_BUFFER_BINDING, &_query_buffer);')
183 print(r' }')
184 print(r' if (!_query_buffer) {')
185 print(r' return;')
186 print(r' }')
Jose Fonseca0a676c52016-04-04 23:24:32 +0100187
José Fonseca920bffd2011-06-02 10:04:52 +0100188 # Pre-snapshots
José Fonsecae16ee252014-11-18 20:27:46 +0000189 if self.bind_framebuffer_function_regex.match(function.name):
Piotr Podsiadły0b8b0192019-01-03 20:39:55 +0100190 print(' assert(call.flags & trace::CALL_FLAG_SWAP_RENDERTARGET);')
José Fonseca3ee3cd42013-10-29 19:28:31 +0000191 if function.name == 'glStringMarkerGREMEDY':
192 return
José Fonseca439ae3c2011-09-01 17:36:10 +0100193 if function.name == 'glFrameTerminatorGREMEDY':
Piotr Podsiadły0b8b0192019-01-03 20:39:55 +0100194 print(' glretrace::frame_complete(call);')
José Fonseca439ae3c2011-09-01 17:36:10 +0100195 return
José Fonseca920bffd2011-06-02 10:04:52 +0100196
José Fonseca54f304a2012-01-14 19:33:08 +0000197 Retracer.retraceFunctionBody(self, function)
José Fonseca62212972011-03-23 13:22:55 +0000198
José Fonseca920bffd2011-06-02 10:04:52 +0100199 # Post-snapshots
José Fonseca4d7f1fe2011-05-09 20:54:31 +0100200 if function.name in ('glFlush', 'glFinish'):
Piotr Podsiadły0b8b0192019-01-03 20:39:55 +0100201 print(' if (!retrace::doubleBuffer) {')
202 print(' glretrace::frame_complete(call);')
203 print(' }')
José Fonsecaac3d4642014-08-14 19:20:03 +0100204 if is_draw_arrays or is_draw_elements or is_misc_draw:
Piotr Podsiadły0b8b0192019-01-03 20:39:55 +0100205 print(' assert(call.flags & trace::CALL_FLAG_RENDER);')
José Fonseca920bffd2011-06-02 10:04:52 +0100206
José Fonseca4d7f1fe2011-05-09 20:54:31 +0100207
José Fonseca54f304a2012-01-14 19:33:08 +0000208 def invokeFunction(self, function):
Mark Janes35b25362020-01-02 20:47:44 -0800209 if function.name == "glGetActiveUniformBlockName":
210 print(' std::vector<GLchar> name_buf(bufSize);')
211 print(' uniformBlockName = name_buf.data();')
212 print(' const auto traced_name = (const GLchar *)((call.arg(4)).toString());')
213 print(' glretrace::mapUniformBlockName(program, (call.arg(1)).toSInt(), traced_name, _uniformBlock_map);')
Mark Janes95feab72019-12-20 17:01:56 -0800214 if function.name == "glGetProgramResourceName":
215 print(' std::vector<GLchar> name_buf(bufSize);')
216 print(' name = name_buf.data();')
217 print(' const auto traced_name = (const GLchar *)((call.arg(5)).toString());')
218 print(' glretrace::trackResourceName(program, programInterface, index, traced_name);')
219 if function.name == "glGetProgramResourceiv":
220 print(' glretrace::mapResourceLocation(program, programInterface, index, call.arg(4).toArray(), call.arg(7).toArray(), _location_map);')
José Fonseca757b2b62011-09-19 10:09:53 +0100221 # Infer the drawable size from GL calls
José Fonsecacdb574a2010-11-29 12:23:35 +0000222 if function.name == "glViewport":
Piotr Podsiadły0b8b0192019-01-03 20:39:55 +0100223 print(' glretrace::updateDrawable(x + width, y + height);')
Jose Fonsecaf89d3d72016-12-02 15:14:06 +0000224 if function.name == "glViewportArrayv":
José Fonsecaea82c3f2012-03-29 08:19:19 +0100225 # We are concerned about drawables so only care for the first viewport
Piotr Podsiadły0b8b0192019-01-03 20:39:55 +0100226 print(' if (first == 0 && count > 0) {')
227 print(' GLfloat x = v[0], y = v[1], w = v[2], h = v[3];')
228 print(' glretrace::updateDrawable(x + w, y + h);')
229 print(' }')
José Fonsecaea82c3f2012-03-29 08:19:19 +0100230 if function.name == "glViewportIndexedf":
Piotr Podsiadły0b8b0192019-01-03 20:39:55 +0100231 print(' if (index == 0) {')
232 print(' glretrace::updateDrawable(x + w, y + h);')
233 print(' }')
José Fonsecaea82c3f2012-03-29 08:19:19 +0100234 if function.name == "glViewportIndexedfv":
Piotr Podsiadły0b8b0192019-01-03 20:39:55 +0100235 print(' if (index == 0) {')
236 print(' GLfloat x = v[0], y = v[1], w = v[2], h = v[3];')
237 print(' glretrace::updateDrawable(x + w, y + h);')
238 print(' }')
José Fonseca757b2b62011-09-19 10:09:53 +0100239 if function.name in ('glBlitFramebuffer', 'glBlitFramebufferEXT'):
240 # Some applications do all their rendering in a framebuffer, and
241 # then just blit to the drawable without ever calling glViewport.
Piotr Podsiadły0b8b0192019-01-03 20:39:55 +0100242 print(' glretrace::updateDrawable(std::max(dstX0, dstX1), std::max(dstY0, dstY1));')
José Fonsecacdb574a2010-11-29 12:23:35 +0000243
Jose Fonseca12b82172015-08-06 13:41:54 +0100244 if function.name == "glEnd":
Piotr Podsiadły0b8b0192019-01-03 20:39:55 +0100245 print(r' if (currentContext) {')
246 print(r' currentContext->insideBeginEnd = false;')
247 print(r' }')
José Fonsecaae9c4c12012-02-02 13:59:31 +0000248
José Fonsecafea81f92011-05-23 21:20:53 +0100249 if function.name == 'memcpy':
Piotr Podsiadły0b8b0192019-01-03 20:39:55 +0100250 print(' if (!dest || !src || !n) return;')
José Fonseca694dc0b2012-03-01 15:44:07 +0000251
Gregory Hainaut8ac8b6b2012-06-11 13:58:22 +0100252 # Skip glEnable/Disable(GL_DEBUG_OUTPUT_SYNCHRONOUS_ARB) as we don't
253 # faithfully set the CONTEXT_DEBUG_BIT_ARB flags on context creation.
254 if function.name in ('glEnable', 'glDisable'):
Piotr Podsiadły0b8b0192019-01-03 20:39:55 +0100255 print(' if (cap == GL_DEBUG_OUTPUT_SYNCHRONOUS_ARB) return;')
Gregory Hainaut8ac8b6b2012-06-11 13:58:22 +0100256
José Fonseca694dc0b2012-03-01 15:44:07 +0000257 # Destroy the buffer mapping
José Fonsecabd503ed2014-11-12 21:36:10 +0000258 if self.unmap_function_regex.match(function.name):
Piotr Podsiadły0b8b0192019-01-03 20:39:55 +0100259 print(r' GLvoid *ptr = NULL;')
José Fonseca694dc0b2012-03-01 15:44:07 +0000260 if function.name == 'glUnmapBuffer':
Piotr Podsiadły0b8b0192019-01-03 20:39:55 +0100261 print(r' glGetBufferPointerv(target, GL_BUFFER_MAP_POINTER, &ptr);')
José Fonseca694dc0b2012-03-01 15:44:07 +0000262 elif function.name == 'glUnmapBufferARB':
Piotr Podsiadły0b8b0192019-01-03 20:39:55 +0100263 print(r' glGetBufferPointervARB(target, GL_BUFFER_MAP_POINTER_ARB, &ptr);')
José Fonseca694dc0b2012-03-01 15:44:07 +0000264 elif function.name == 'glUnmapBufferOES':
Piotr Podsiadły0b8b0192019-01-03 20:39:55 +0100265 print(r' glGetBufferPointervOES(target, GL_BUFFER_MAP_POINTER_OES, &ptr);')
José Fonseca4920c302014-08-13 18:35:57 +0100266 elif function.name == 'glUnmapNamedBuffer':
Piotr Podsiadły0b8b0192019-01-03 20:39:55 +0100267 print(r' glGetNamedBufferPointerv(buffer, GL_BUFFER_MAP_POINTER, &ptr);')
José Fonseca694dc0b2012-03-01 15:44:07 +0000268 elif function.name == 'glUnmapNamedBufferEXT':
Piotr Podsiadły0b8b0192019-01-03 20:39:55 +0100269 print(r' glGetNamedBufferPointervEXT(buffer, GL_BUFFER_MAP_POINTER, &ptr);')
José Fonsecacbc859f2012-04-05 19:55:53 +0100270 elif function.name == 'glUnmapObjectBufferATI':
271 # TODO
272 pass
José Fonseca694dc0b2012-03-01 15:44:07 +0000273 else:
274 assert False
Piotr Podsiadły0b8b0192019-01-03 20:39:55 +0100275 print(r' if (ptr) {')
276 print(r' retrace::delRegionByPointer(ptr);')
277 print(r' } else {')
278 print(r' retrace::warning(call) << "failed to get mapped pointer\n";')
279 print(r' }')
Gregory Hainautb79e26a2012-05-11 14:49:10 +0100280
Nicolai Hähnle019ebe22016-06-07 13:19:44 +0100281 # Implicit destruction of buffer mappings
282 # TODO: handle BufferData variants
283 # TODO: don't rely on GL_ARB_direct_state_access
284 if function.name in ('glDeleteBuffers', 'glDeleteBuffersARB'):
Jose Fonseca4b448392019-08-22 11:04:53 +0100285 print(r' if (currentContext && currentContext->features().ARB_direct_state_access) {')
Piotr Podsiadły0b8b0192019-01-03 20:39:55 +0100286 print(r' for (GLsizei i = 0; i < n; ++i) {')
287 print(r' GLvoid *ptr = nullptr;')
288 print(r' glGetNamedBufferPointerv(buffers[i], GL_BUFFER_MAP_POINTER, &ptr);')
289 print(r' if (ptr) {')
290 print(r' retrace::delRegionByPointer(ptr);')
291 print(r' }')
292 print(r' }')
293 print(r' }')
Nicolai Hähnle019ebe22016-06-07 13:19:44 +0100294
Jose Fonsecae99df402015-12-22 12:31:20 +0000295 if function.name.startswith('glCopyImageSubData'):
Piotr Podsiadły0b8b0192019-01-03 20:39:55 +0100296 print(r' if (srcTarget == GL_RENDERBUFFER || dstTarget == GL_RENDERBUFFER) {')
297 print(r' retrace::warning(call) << " renderbuffer targets unsupported (https://github.com/apitrace/apitrace/issues/404)\n";')
298 print(r' }')
Jose Fonsecae99df402015-12-22 12:31:20 +0000299
Jose Fonsecaae3c6382015-04-25 06:52:33 +0100300 is_draw_arrays = self.draw_arrays_function_regex.match(function.name) is not None
301 is_draw_elements = self.draw_elements_function_regex.match(function.name) is not None
302 is_misc_draw = self.misc_draw_function_regex.match(function.name) is not None
303
James Bentonaddf7f92012-07-20 18:56:19 +0100304 profileDraw = (
Jose Fonsecaae3c6382015-04-25 06:52:33 +0100305 is_draw_arrays or
306 is_draw_elements or
307 is_misc_draw or
Jose Fonseca9c8857d2016-03-05 22:14:00 +0000308 function.name == 'glBegin' or
309 function.name.startswith('glDispatchCompute')
James Bentonaddf7f92012-07-20 18:56:19 +0100310 )
311
Jose Fonseca8e0a0302016-05-04 23:53:46 +0100312 # Keep track of current program/pipeline
James Benton6d923272012-07-25 13:48:20 +0100313 if function.name in ('glUseProgram', 'glUseProgramObjectARB'):
Piotr Podsiadły0b8b0192019-01-03 20:39:55 +0100314 print(r' if (currentContext) {')
315 print(r' currentContext->currentUserProgram = call.arg(0).toUInt();')
316 print(r' currentContext->currentProgram = %s;' % function.args[0].name)
317 print(r' }')
Jose Fonseca8e0a0302016-05-04 23:53:46 +0100318 if function.name in ('glBindProgramPipeline', 'glBindProgramPipelineEXT'):
Piotr Podsiadły0b8b0192019-01-03 20:39:55 +0100319 print(r' if (currentContext) {')
320 print(r' currentContext->currentPipeline = %s;' % function.args[0].name)
321 print(r' }')
James Benton6d923272012-07-25 13:48:20 +0100322
323 # Only profile if not inside a list as the queries get inserted into list
James Bentonaddf7f92012-07-20 18:56:19 +0100324 if function.name == 'glNewList':
Piotr Podsiadły0b8b0192019-01-03 20:39:55 +0100325 print(r' if (currentContext) {')
326 print(r' currentContext->insideList = true;')
327 print(r' }')
James Bentonaddf7f92012-07-20 18:56:19 +0100328
329 if function.name == 'glEndList':
Piotr Podsiadły0b8b0192019-01-03 20:39:55 +0100330 print(r' if (currentContext) {')
331 print(r' currentContext->insideList = false;')
332 print(r' }')
James Bentonaddf7f92012-07-20 18:56:19 +0100333
Jose Fonsecaae3c6382015-04-25 06:52:33 +0100334 if function.name == 'glBegin' or \
335 is_draw_arrays or \
336 is_draw_elements or \
337 function.name.startswith('glBeginTransformFeedback'):
Piotr Podsiadły0b8b0192019-01-03 20:39:55 +0100338 print(r' if (retrace::debug > 0) {')
339 print(r' _validateActiveProgram(call);')
340 print(r' }')
Jose Fonseca21b8f332015-04-24 22:43:23 +0100341
James Bentonc53c6492012-08-13 18:21:16 +0100342 if function.name != 'glEnd':
Piotr Podsiadły0b8b0192019-01-03 20:39:55 +0100343 print(r' if (currentContext && !currentContext->insideList && !currentContext->insideBeginEnd && retrace::profiling) {')
James Bentonc53c6492012-08-13 18:21:16 +0100344 if profileDraw:
Piotr Podsiadły0b8b0192019-01-03 20:39:55 +0100345 print(r' glretrace::beginProfile(call, true);')
James Bentonc53c6492012-08-13 18:21:16 +0100346 else:
Piotr Podsiadły0b8b0192019-01-03 20:39:55 +0100347 print(r' glretrace::beginProfile(call, false);')
348 print(r' }')
James Bentonaddf7f92012-07-20 18:56:19 +0100349
José Fonseca474c5022015-01-29 12:02:03 +0000350 if function.name in ('glCreateShaderProgramv', 'glCreateShaderProgramEXT', 'glCreateShaderProgramvEXT'):
351 # When dumping state, break down glCreateShaderProgram* so that the
José Fonseca3db3b2f2012-05-11 14:55:50 +0100352 # shader source can be recovered.
Piotr Podsiadły0b8b0192019-01-03 20:39:55 +0100353 print(r' if (retrace::dumpingState) {')
354 print(r' GLuint _shader = glCreateShader(type);')
355 print(r' if (_shader) {')
José Fonseca474c5022015-01-29 12:02:03 +0000356 if not function.name.startswith('glCreateShaderProgramv'):
Piotr Podsiadły0b8b0192019-01-03 20:39:55 +0100357 print(r' GLsizei count = 1;')
358 print(r' const GLchar **strings = &string;')
359 print(r' glShaderSource(_shader, count, strings, NULL);')
360 print(r' glCompileShader(_shader);')
361 print(r' const GLuint _program = glCreateProgram();')
362 print(r' if (_program) {')
363 print(r' GLint compiled = GL_FALSE;')
364 print(r' glGetShaderiv(_shader, GL_COMPILE_STATUS, &compiled);')
José Fonseca474c5022015-01-29 12:02:03 +0000365 if function.name == 'glCreateShaderProgramvEXT':
Piotr Podsiadły0b8b0192019-01-03 20:39:55 +0100366 print(r' glProgramParameteriEXT(_program, GL_PROGRAM_SEPARABLE, GL_TRUE);')
José Fonseca474c5022015-01-29 12:02:03 +0000367 else:
Piotr Podsiadły0b8b0192019-01-03 20:39:55 +0100368 print(r' glProgramParameteri(_program, GL_PROGRAM_SEPARABLE, GL_TRUE);')
369 print(r' if (compiled) {')
370 print(r' glAttachShader(_program, _shader);')
371 print(r' glLinkProgram(_program);')
372 print(r' if (false) glDetachShader(_program, _shader);')
373 print(r' }')
374 print(r' // TODO: append shader info log to program info log')
375 print(r' }')
376 print(r' glDeleteShader(_shader);')
377 print(r' _result = _program;')
378 print(r' } else {')
379 print(r' _result = 0;')
380 print(r' }')
381 print(r' } else {')
José Fonseca3db3b2f2012-05-11 14:55:50 +0100382 Retracer.invokeFunction(self, function)
Piotr Podsiadły0b8b0192019-01-03 20:39:55 +0100383 print(r' }')
José Fonsecaa4d4d772015-01-29 15:20:11 +0000384 elif function.name in ('glDetachShader', 'glDetachObjectARB'):
Piotr Podsiadły0b8b0192019-01-03 20:39:55 +0100385 print(r' if (!retrace::dumpingState) {')
gregorya468a7a2012-07-01 16:30:08 +0200386 Retracer.invokeFunction(self, function)
Piotr Podsiadły0b8b0192019-01-03 20:39:55 +0100387 print(r' }')
José Fonseca04e95f62014-12-12 21:09:21 +0000388 elif function.name == 'glClientWaitSync':
Piotr Podsiadły0b8b0192019-01-03 20:39:55 +0100389 print(r' _result = glretrace::clientWaitSync(call, sync, flags, timeout);')
390 print(r' (void)_result;')
José Fonseca04e95f62014-12-12 21:09:21 +0000391 elif function.name == 'glGetSynciv':
Piotr Podsiadły0b8b0192019-01-03 20:39:55 +0100392 print(r' if (pname == GL_SYNC_STATUS &&')
393 print(r' bufSize >= 1 &&')
394 print(r' values != NULL &&')
395 print(r' call.arg(4)[0].toSInt() == GL_SIGNALED) {')
396 print(r' // Fence was signalled, so ensure it happened here')
397 print(r' glretrace::blockOnFence(call, sync, GL_SYNC_FLUSH_COMMANDS_BIT);')
398 print(r' (void)length;')
399 print(r' }')
José Fonseca3db3b2f2012-05-11 14:55:50 +0100400 else:
401 Retracer.invokeFunction(self, function)
José Fonsecacdb574a2010-11-29 12:23:35 +0000402
Jose Fonsecaa7caf012016-04-14 07:11:12 +0100403 # Ensure this context flushes before switching to another thread to
404 # prevent deadlock.
405 # TODO: Defer flushing until another thread actually invokes
406 # ClientWaitSync.
407 if function.name.startswith("glFenceSync"):
Piotr Podsiadły0b8b0192019-01-03 20:39:55 +0100408 print(' if (currentContext) {')
409 print(' currentContext->needsFlush = true;')
410 print(' }')
Jose Fonsecaa7caf012016-04-14 07:11:12 +0100411 if function.name in ("glFlush", "glFinish"):
Piotr Podsiadły0b8b0192019-01-03 20:39:55 +0100412 print(' if (currentContext) {')
413 print(' currentContext->needsFlush = false;')
414 print(' }')
Jose Fonsecaa7caf012016-04-14 07:11:12 +0100415
James Bentond852eae2012-08-10 15:56:18 +0100416 if function.name == "glBegin":
Piotr Podsiadły0b8b0192019-01-03 20:39:55 +0100417 print(' if (currentContext) {')
418 print(' currentContext->insideBeginEnd = true;')
419 print(' }')
James Bentond852eae2012-08-10 15:56:18 +0100420
Piotr Podsiadły0b8b0192019-01-03 20:39:55 +0100421 print(r' if (currentContext && !currentContext->insideList && !currentContext->insideBeginEnd && retrace::profiling) {')
James Bentonc53c6492012-08-13 18:21:16 +0100422 if profileDraw:
Piotr Podsiadły0b8b0192019-01-03 20:39:55 +0100423 print(r' glretrace::endProfile(call, true);')
James Bentonc53c6492012-08-13 18:21:16 +0100424 else:
Piotr Podsiadły0b8b0192019-01-03 20:39:55 +0100425 print(r' glretrace::endProfile(call, false);')
426 print(r' }')
James Bentonaddf7f92012-07-20 18:56:19 +0100427
José Fonsecaecf37412011-05-21 01:56:08 +0100428 # Error checking
James Bentond852eae2012-08-10 15:56:18 +0100429 if function.name.startswith('gl'):
José Fonseca3d245f42010-11-28 00:08:23 +0000430 # glGetError is not allowed inside glBegin/glEnd
Piotr Podsiadły0b8b0192019-01-03 20:39:55 +0100431 print(' if (retrace::debug > 0 && currentContext && !currentContext->insideBeginEnd) {')
432 print(' glretrace::checkGlError(call);')
José Fonseca8f39c872015-01-25 22:20:15 +0000433 if function.name in ('glProgramStringARB', 'glLoadProgramNV'):
Piotr Podsiadły0b8b0192019-01-03 20:39:55 +0100434 print(r' GLint error_position = -1;')
435 print(r' glGetIntegerv(GL_PROGRAM_ERROR_POSITION_ARB, &error_position);')
436 print(r' if (error_position != -1) {')
437 print(r' const char *error_string = (const char *)glGetString(GL_PROGRAM_ERROR_STRING_ARB);')
438 print(r' retrace::warning(call) << "error in position " << error_position << ": " << error_string << "\n";')
439 print(r' }')
José Fonsecaecf37412011-05-21 01:56:08 +0100440 if function.name == 'glCompileShader':
Piotr Podsiadły0b8b0192019-01-03 20:39:55 +0100441 print(r' GLint compile_status = 0;')
442 print(r' glGetShaderiv(shader, GL_COMPILE_STATUS, &compile_status);')
443 print(r' if (!compile_status) {')
444 print(r' retrace::warning(call) << "compilation failed\n";')
445 print(r' }')
446 print(r' GLint info_log_length = 0;')
447 print(r' glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &info_log_length);')
448 print(r' if (info_log_length > 1) {')
449 print(r' GLchar *infoLog = new GLchar[info_log_length];')
450 print(r' glGetShaderInfoLog(shader, info_log_length, NULL, infoLog);')
451 print(r' retrace::warning(call) << infoLog << "\n";')
452 print(r' delete [] infoLog;')
453 print(r' }')
José Fonseca8f39c872015-01-25 22:20:15 +0000454 if function.name in ('glLinkProgram', 'glCreateShaderProgramv', 'glCreateShaderProgramEXT', 'glCreateShaderProgramvEXT', 'glProgramBinary', 'glProgramBinaryOES'):
455 if function.name.startswith('glCreateShaderProgram'):
Piotr Podsiadły0b8b0192019-01-03 20:39:55 +0100456 print(r' GLuint program = _result;')
457 print(r' GLint link_status = 0;')
458 print(r' glGetProgramiv(program, GL_LINK_STATUS, &link_status);')
459 print(r' if (!link_status) {')
460 print(r' retrace::warning(call) << "link failed\n";')
461 print(r' }')
462 print(r' GLint info_log_length = 0;')
463 print(r' glGetProgramiv(program, GL_INFO_LOG_LENGTH, &info_log_length);')
464 print(r' if (info_log_length > 1) {')
465 print(r' GLchar *infoLog = new GLchar[info_log_length];')
466 print(r' glGetProgramInfoLog(program, info_log_length, NULL, infoLog);')
467 print(r' retrace::warning(call) << infoLog << "\n";')
468 print(r' delete [] infoLog;')
469 print(r' }')
José Fonsecaecf37412011-05-21 01:56:08 +0100470 if function.name == 'glCompileShaderARB':
Piotr Podsiadły0b8b0192019-01-03 20:39:55 +0100471 print(r' GLint compile_status = 0;')
472 print(r' glGetObjectParameterivARB(shaderObj, GL_OBJECT_COMPILE_STATUS_ARB, &compile_status);')
473 print(r' if (!compile_status) {')
474 print(r' retrace::warning(call) << "compilation failed\n";')
475 print(r' }')
476 print(r' GLint info_log_length = 0;')
477 print(r' glGetObjectParameterivARB(shaderObj, GL_OBJECT_INFO_LOG_LENGTH_ARB, &info_log_length);')
478 print(r' if (info_log_length > 1) {')
479 print(r' GLchar *infoLog = new GLchar[info_log_length];')
480 print(r' glGetInfoLogARB(shaderObj, info_log_length, NULL, infoLog);')
481 print(r' retrace::warning(call) << infoLog << "\n";')
482 print(r' delete [] infoLog;')
483 print(r' }')
José Fonsecaecf37412011-05-21 01:56:08 +0100484 if function.name == 'glLinkProgramARB':
Piotr Podsiadły0b8b0192019-01-03 20:39:55 +0100485 print(r' GLint link_status = 0;')
486 print(r' glGetObjectParameterivARB(programObj, GL_OBJECT_LINK_STATUS_ARB, &link_status);')
487 print(r' if (!link_status) {')
488 print(r' retrace::warning(call) << "link failed\n";')
489 print(r' }')
490 print(r' GLint info_log_length = 0;')
491 print(r' glGetObjectParameterivARB(programObj, GL_OBJECT_INFO_LOG_LENGTH_ARB, &info_log_length);')
492 print(r' if (info_log_length > 1) {')
493 print(r' GLchar *infoLog = new GLchar[info_log_length];')
494 print(r' glGetInfoLogARB(programObj, info_log_length, NULL, infoLog);')
495 print(r' retrace::warning(call) << infoLog << "\n";')
496 print(r' delete [] infoLog;')
497 print(r' }')
José Fonsecabd503ed2014-11-12 21:36:10 +0000498 if self.map_function_regex.match(function.name):
Piotr Podsiadły0b8b0192019-01-03 20:39:55 +0100499 print(r' if (!_result) {')
500 print(r' retrace::warning(call) << "failed to map buffer\n";')
501 print(r' }')
José Fonsecabd503ed2014-11-12 21:36:10 +0000502 if self.unmap_function_regex.match(function.name) and function.type is not stdapi.Void:
Piotr Podsiadły0b8b0192019-01-03 20:39:55 +0100503 print(r' if (!_result) {')
504 print(r' retrace::warning(call) << "failed to unmap buffer\n";')
505 print(r' }')
José Fonseca91492d22011-05-23 21:20:31 +0100506 if function.name in ('glGetAttribLocation', 'glGetAttribLocationARB'):
Piotr Podsiadły0b8b0192019-01-03 20:39:55 +0100507 print(r' GLint _origResult = call.ret->toSInt();')
508 print(r' if (_result != _origResult) {')
509 print(r' retrace::warning(call) << "vertex attrib location mismatch " << _origResult << " -> " << _result << "\n";')
510 print(r' }')
José Fonseca4920c302014-08-13 18:35:57 +0100511 if function.name in ('glCheckFramebufferStatus', 'glCheckFramebufferStatusEXT', 'glCheckNamedFramebufferStatus', 'glCheckNamedFramebufferStatusEXT'):
Piotr Podsiadły0b8b0192019-01-03 20:39:55 +0100512 print(r' GLint _origResult = call.ret->toSInt();')
513 print(r' if (_origResult == GL_FRAMEBUFFER_COMPLETE &&')
514 print(r' _result != GL_FRAMEBUFFER_COMPLETE) {')
515 print(r' retrace::warning(call) << "incomplete framebuffer (" << glstate::enumToString(_result) << ")\n";')
516 print(r' }')
517 print(' }')
José Fonsecae4999b92011-05-05 00:31:01 +0100518
José Fonseca561266b2012-03-21 06:49:41 +0000519 # Query the buffer length for whole buffer mappings
José Fonsecabd503ed2014-11-12 21:36:10 +0000520 if self.map_function_regex.match(function.name):
José Fonseca561266b2012-03-21 06:49:41 +0000521 if 'length' in function.argNames():
522 assert 'BufferRange' in function.name
523 else:
524 assert 'BufferRange' not in function.name
Piotr Podsiadły0b8b0192019-01-03 20:39:55 +0100525 print(r' GLint length = 0;')
José Fonseca561266b2012-03-21 06:49:41 +0000526 if function.name in ('glMapBuffer', 'glMapBufferOES'):
Piotr Podsiadły0b8b0192019-01-03 20:39:55 +0100527 print(r' glGetBufferParameteriv(target, GL_BUFFER_SIZE, &length);')
José Fonseca561266b2012-03-21 06:49:41 +0000528 elif function.name == 'glMapBufferARB':
Piotr Podsiadły0b8b0192019-01-03 20:39:55 +0100529 print(r' glGetBufferParameterivARB(target, GL_BUFFER_SIZE_ARB, &length);')
José Fonseca4920c302014-08-13 18:35:57 +0100530 elif function.name == 'glMapNamedBuffer':
Piotr Podsiadły0b8b0192019-01-03 20:39:55 +0100531 print(r' glGetNamedBufferParameteriv(buffer, GL_BUFFER_SIZE, &length);')
José Fonseca561266b2012-03-21 06:49:41 +0000532 elif function.name == 'glMapNamedBufferEXT':
Piotr Podsiadły0b8b0192019-01-03 20:39:55 +0100533 print(r' glGetNamedBufferParameterivEXT(buffer, GL_BUFFER_SIZE, &length);')
José Fonsecacbc859f2012-04-05 19:55:53 +0100534 elif function.name == 'glMapObjectBufferATI':
Piotr Podsiadły0b8b0192019-01-03 20:39:55 +0100535 print(r' glGetObjectBufferivATI(buffer, GL_OBJECT_BUFFER_SIZE_ATI, &length);')
José Fonseca59ee88e2012-01-15 14:24:10 +0000536 else:
José Fonseca561266b2012-03-21 06:49:41 +0000537 assert False
José Fonseca46a48392011-10-14 11:34:27 +0100538
José Fonseca54f304a2012-01-14 19:33:08 +0000539 def extractArg(self, function, arg, arg_type, lvalue, rvalue):
José Fonseca7f5163e2011-03-31 23:37:26 +0100540 if function.name in self.array_pointer_function_names and arg.name == 'pointer':
Piotr Podsiadły0b8b0192019-01-03 20:39:55 +0100541 print(' %s = static_cast<%s>(retrace::toPointer(%s, true));' % (lvalue, arg_type, rvalue))
José Fonseca14c21bc2011-02-20 23:32:22 +0000542 return
543
José Fonsecaac3d4642014-08-14 19:20:03 +0100544 if self.draw_elements_function_regex.match(function.name) and arg.name == 'indices' or\
545 self.draw_indirect_function_regex.match(function.name) and arg.name == 'indirect':
José Fonseca54f304a2012-01-14 19:33:08 +0000546 self.extractOpaqueArg(function, arg, arg_type, lvalue, rvalue)
José Fonseca8a844ae2010-12-06 18:50:52 +0000547 return
José Fonsecadacd8dd2010-11-25 17:50:26 +0000548
José Fonsecac29f4f12011-06-11 12:19:05 +0100549 # Handle pointer with offsets into the current pack pixel buffer
550 # object.
José Fonseca920f8e72014-11-12 21:31:59 +0000551 if self.pack_function_regex.match(function.name) and arg.output:
José Fonseca4a2c57b2012-04-07 10:50:53 +0100552 assert isinstance(arg_type, (stdapi.Pointer, stdapi.Array, stdapi.Blob, stdapi.Opaque))
Piotr Podsiadły0b8b0192019-01-03 20:39:55 +0100553 print(' %s = static_cast<%s>((%s).toPointer());' % (lvalue, arg_type, rvalue))
José Fonsecac29f4f12011-06-11 12:19:05 +0100554 return
Jose Fonseca0a676c52016-04-04 23:24:32 +0100555 if function.name.startswith('glGetQueryObject') and arg.output:
Piotr Podsiadły0b8b0192019-01-03 20:39:55 +0100556 print(' %s = static_cast<%s>((%s).toPointer());' % (lvalue, arg_type, rvalue))
Jose Fonseca0a676c52016-04-04 23:24:32 +0100557 return
José Fonsecac29f4f12011-06-11 12:19:05 +0100558
José Fonseca13b93432014-11-18 20:21:23 +0000559 if (arg.type.depends(glapi.GLlocation) or \
560 arg.type.depends(glapi.GLsubroutine)) \
José Fonseca568ecc22012-01-15 13:57:03 +0000561 and 'program' not in function.argNames():
Gregory Hainautb79e26a2012-05-11 14:49:10 +0100562 # Determine the active program for uniforms swizzling
Piotr Podsiadły0b8b0192019-01-03 20:39:55 +0100563 print(' GLint program = _getActiveProgram();')
Gregory Hainautb79e26a2012-05-11 14:49:10 +0100564
José Fonseca3c1b7ce2011-05-09 11:22:54 +0100565 if arg.type is glapi.GLlocationARB \
José Fonseca568ecc22012-01-15 13:57:03 +0000566 and 'programObj' not in function.argNames():
Piotr Podsiadły0b8b0192019-01-03 20:39:55 +0100567 print(' GLhandleARB programObj = glGetHandleARB(GL_PROGRAM_OBJECT_ARB);')
José Fonseca8a844ae2010-12-06 18:50:52 +0000568
José Fonseca54f304a2012-01-14 19:33:08 +0000569 Retracer.extractArg(self, function, arg, arg_type, lvalue, rvalue)
José Fonsecae6a50bd2010-11-24 10:12:22 +0000570
José Fonseca42926462011-05-09 11:32:15 +0100571 # Don't try to use more samples than the implementation supports
572 if arg.name == 'samples':
Kimmo Kinnunen24ce7492015-05-25 13:18:44 +0300573 if function.name == 'glRasterSamplesEXT':
574 assert arg.type is glapi.GLuint
Piotr Podsiadły0b8b0192019-01-03 20:39:55 +0100575 print(' GLint max_samples = 0;')
576 print(' glGetIntegerv(GL_MAX_RASTER_SAMPLES_EXT, &max_samples);')
577 print(' if (samples > static_cast<GLuint>(max_samples)) {')
578 print(' samples = static_cast<GLuint>(max_samples);')
579 print(' }')
Kimmo Kinnunen24ce7492015-05-25 13:18:44 +0300580 else:
581 assert arg.type is glapi.GLsizei
Piotr Podsiadły0b8b0192019-01-03 20:39:55 +0100582 print(' GLint max_samples = 0;')
583 print(' glGetIntegerv(GL_MAX_SAMPLES, &max_samples);')
584 print(' if (samples > max_samples) {')
585 print(' samples = max_samples;')
586 print(' }')
José Fonseca42926462011-05-09 11:32:15 +0100587
José Fonseca62abddc2012-04-13 14:57:08 +0100588 # These parameters are referred beyond the call life-time
589 # TODO: Replace ad-hoc solution for bindable parameters with general one
590 if function.name in ('glFeedbackBuffer', 'glSelectBuffer') and arg.output:
Piotr Podsiadły0b8b0192019-01-03 20:39:55 +0100591 print(' _allocator.bind(%s);' % arg.name)
José Fonseca62abddc2012-04-13 14:57:08 +0100592
593
José Fonsecae6a50bd2010-11-24 10:12:22 +0000594
José Fonseca7e329022010-11-19 17:05:18 +0000595if __name__ == '__main__':
Piotr Podsiadły0b8b0192019-01-03 20:39:55 +0100596 print(r'''
José Fonseca867b1b72011-04-24 11:58:04 +0100597#include <string.h>
598
José Fonsecadf66a902010-11-29 13:24:20 +0000599#include "glproc.hpp"
José Fonseca32871ed2011-04-10 13:40:52 +0100600#include "glretrace.hpp"
José Fonseca56391262011-09-19 09:30:10 +0100601#include "glstate.hpp"
Jose Fonseca8e0a0302016-05-04 23:53:46 +0100602#include "glsize.hpp"
José Fonseca8a56fde2014-11-12 22:59:18 +0000603
604
605static GLint
606_getActiveProgram(void);
607
Jose Fonseca21b8f332015-04-24 22:43:23 +0100608static void
609_validateActiveProgram(trace::Call &call);
610
Piotr Podsiadły0b8b0192019-01-03 20:39:55 +0100611''')
José Fonseca81301932012-11-11 00:10:20 +0000612 api = stdapi.API()
613 api.addModule(glapi.glapi)
José Fonsecae0e61402010-11-25 15:03:23 +0000614 retracer = GlRetracer()
José Fonseca54f304a2012-01-14 19:33:08 +0000615 retracer.retraceApi(api)
José Fonseca8a56fde2014-11-12 22:59:18 +0000616
Piotr Podsiadły0b8b0192019-01-03 20:39:55 +0100617 print(r'''
José Fonseca8a56fde2014-11-12 22:59:18 +0000618static GLint
619_getActiveProgram(void)
620{
621 GLint program = -1;
Jose Fonseca12b82172015-08-06 13:41:54 +0100622 glretrace::Context *currentContext = glretrace::getCurrentContext();
Jose Fonseca8e0a0302016-05-04 23:53:46 +0100623 if (currentContext) {
624 GLint pipeline = currentContext->currentPipeline;
José Fonseca8a56fde2014-11-12 22:59:18 +0000625 if (pipeline) {
626 glGetProgramPipelineiv(pipeline, GL_ACTIVE_PROGRAM, &program);
627 } else {
Jose Fonseca8e0a0302016-05-04 23:53:46 +0100628 program = currentContext->currentProgram;
629 assert(program == _glGetInteger(GL_CURRENT_PROGRAM));
José Fonseca8a56fde2014-11-12 22:59:18 +0000630 }
631 }
632 return program;
633}
634
Jose Fonseca21b8f332015-04-24 22:43:23 +0100635static void
636_validateActiveProgram(trace::Call &call)
637{
Jose Fonseca65dc5c32018-08-22 19:20:00 +0100638 assert(retrace::debug > 0);
Jose Fonseca12b82172015-08-06 13:41:54 +0100639
640 glretrace::Context *currentContext = glretrace::getCurrentContext();
641 if (!currentContext ||
642 currentContext->insideList ||
643 currentContext->insideBeginEnd ||
644 currentContext->wsContext->profile.major < 2) {
645 return;
646 }
Jose Fonseca21b8f332015-04-24 22:43:23 +0100647
Jose Fonseca8e0a0302016-05-04 23:53:46 +0100648 GLint pipeline = currentContext->currentPipeline;
Jose Fonseca21b8f332015-04-24 22:43:23 +0100649 if (pipeline) {
650 // TODO
651 } else {
Jose Fonseca8e0a0302016-05-04 23:53:46 +0100652 GLint program = currentContext->currentProgram;
653 assert(program == _glGetInteger(GL_CURRENT_PROGRAM));
Jose Fonseca21b8f332015-04-24 22:43:23 +0100654 if (!program) {
655 return;
656 }
657
658 GLint validate_status = GL_FALSE;
659 glGetProgramiv(program, GL_VALIDATE_STATUS, &validate_status);
660 if (validate_status) {
661 // Validate only once
662 return;
663 }
664
665 glValidateProgram(program);
666 glGetProgramiv(program, GL_VALIDATE_STATUS, &validate_status);
667 if (!validate_status) {
668 retrace::warning(call) << "program validation failed\n";
669 }
670
671 GLint info_log_length = 0;
672 glGetProgramiv(program, GL_INFO_LOG_LENGTH, &info_log_length);
673 if (info_log_length > 1) {
674 GLchar *infoLog = new GLchar[info_log_length];
675 glGetProgramInfoLog(program, info_log_length, NULL, infoLog);
676 retrace::warning(call) << infoLog << "\n";
677 delete [] infoLog;
678 }
679 }
680}
681
Piotr Podsiadły0b8b0192019-01-03 20:39:55 +0100682''')