+ if function.name.endswith('ARB'):
+ suffix = 'ARB'
+ else:
+ suffix = ''
+ print ' GLint access = 0;'
+ print ' __glGetBufferParameteriv%s(target, GL_BUFFER_ACCESS, &access);' % suffix
+ print ' if (access != GL_READ_ONLY) {'
+ print ' GLvoid *map = NULL;'
+ print ' __glGetBufferPointerv%s(target, GL_BUFFER_MAP_POINTER, &map);' % suffix
+ print ' if (map) {'
+ print ' GLint length = -1;'
+ print ' bool flush = true;'
+ print ' if (__checkBufferMapRange) {'
+ print ' __glGetBufferParameteriv%s(target, GL_BUFFER_MAP_LENGTH, &length);' % suffix
+ print ' GLint access_flags = 0;'
+ print ' __glGetBufferParameteriv(target, GL_BUFFER_ACCESS_FLAGS, &access_flags);'
+ print ' flush = flush && !(access_flags & GL_MAP_FLUSH_EXPLICIT_BIT);'
+ print ' if (length == -1) {'
+ print ' // Mesa drivers refuse GL_BUFFER_MAP_LENGTH without GL 3.0'
+ print ' static bool warned = false;'
+ print ' if (!warned) {'
+ print ' os::log("apitrace: warning: glGetBufferParameteriv%s(GL_BUFFER_MAP_LENGTH) failed\\n");' % suffix
+ print ' warned = true;'
+ print ' }'
+ print ' struct buffer_mapping *mapping = get_buffer_mapping(target);'
+ print ' if (mapping) {'
+ print ' length = mapping->length;'
+ print ' flush = flush && !mapping->explicit_flush;'
+ print ' } else {'
+ print ' length = 0;'
+ print ' flush = false;'
+ print ' }'
+ print ' }'
+ print ' } else {'
+ print ' length = 0;'
+ print ' __glGetBufferParameteriv%s(target, GL_BUFFER_SIZE, &length);' % suffix
+ print ' }'
+ print ' if (__checkBufferFlushingUnmapAPPLE) {'
+ print ' GLint flushing_unmap = GL_TRUE;'
+ print ' __glGetBufferParameteriv%s(target, GL_BUFFER_FLUSHING_UNMAP_APPLE, &flushing_unmap);' % suffix
+ print ' flush = flush && flushing_unmap;'
+ print ' }'
+ print ' if (flush && length > 0) {'
+ self.emit_memcpy('map', 'map', 'length')
+ print ' }'
+ print ' }'
+ print ' }'
+ if function.name == 'glUnmapBufferOES':
+ print ' GLint access = 0;'
+ print ' __glGetBufferParameteriv(target, GL_BUFFER_ACCESS_OES, &access);'
+ print ' if (access == GL_WRITE_ONLY_OES) {'
+ print ' GLvoid *map = NULL;'
+ print ' __glGetBufferPointervOES(target, GL_BUFFER_MAP_POINTER_OES, &map);'
+ print ' GLint size = 0;'
+ print ' __glGetBufferParameteriv(target, GL_BUFFER_SIZE, &size);'
+ print ' if (map && size > 0) {'
+ self.emit_memcpy('map', 'map', 'size')
+ print ' }'
+ print ' }'
+ if function.name == 'glUnmapNamedBufferEXT':
+ print ' GLint access_flags = 0;'
+ print ' __glGetNamedBufferParameterivEXT(buffer, GL_BUFFER_ACCESS_FLAGS, &access_flags);'
+ print ' if ((access_flags & GL_MAP_WRITE_BIT) && !(access_flags & GL_MAP_FLUSH_EXPLICIT_BIT)) {'
+ print ' GLvoid *map = NULL;'
+ print ' __glGetNamedBufferPointervEXT(buffer, GL_BUFFER_MAP_POINTER, &map);'
+ print ' GLint length = 0;'
+ print ' __glGetNamedBufferParameterivEXT(buffer, GL_BUFFER_MAP_LENGTH, &length);'
+ print ' if (map && length > 0) {'
+ self.emit_memcpy('map', 'map', 'length')
+ print ' }'
+ print ' }'
+ if function.name == 'glFlushMappedBufferRange':
+ print ' GLvoid *map = NULL;'
+ print ' __glGetBufferPointerv(target, GL_BUFFER_MAP_POINTER, &map);'
+ print ' if (map && length > 0) {'
+ self.emit_memcpy('(char *)map + offset', '(const char *)map + offset', 'length')
+ print ' }'
+ if function.name == 'glFlushMappedBufferRangeAPPLE':
+ print ' GLvoid *map = NULL;'
+ print ' __glGetBufferPointerv(target, GL_BUFFER_MAP_POINTER, &map);'
+ print ' if (map && size > 0) {'
+ self.emit_memcpy('(char *)map + offset', '(const char *)map + offset', 'size')
+ print ' }'
+ if function.name == 'glFlushMappedNamedBufferRangeEXT':
+ print ' GLvoid *map = NULL;'
+ print ' __glGetNamedBufferPointervEXT(buffer, GL_BUFFER_MAP_POINTER, &map);'
+ print ' if (map && length > 0) {'
+ self.emit_memcpy('(char *)map + offset', '(const char *)map + offset', 'length')
+ print ' }'
+
+ # Don't leave vertex attrib locations to chance. Instead emit fake
+ # glBindAttribLocation calls to ensure that the same locations will be
+ # used when retracing. Trying to remap locations after the fact would
+ # be an herculian task given that vertex attrib locations appear in
+ # many entry-points, including non-shader related ones.
+ if function.name == 'glLinkProgram':
+ Tracer.invokeFunction(self, function)
+ print ' GLint active_attributes = 0;'
+ print ' __glGetProgramiv(program, GL_ACTIVE_ATTRIBUTES, &active_attributes);'
+ print ' for (GLint attrib = 0; attrib < active_attributes; ++attrib) {'
+ print ' GLint size = 0;'
+ print ' GLenum type = 0;'
+ print ' GLchar name[256];'
+ # TODO: Use ACTIVE_ATTRIBUTE_MAX_LENGTH instead of 256
+ print ' __glGetActiveAttrib(program, attrib, sizeof name, NULL, &size, &type, name);'
+ print " if (name[0] != 'g' || name[1] != 'l' || name[2] != '_') {"
+ print ' GLint location = __glGetAttribLocation(program, name);'
+ print ' if (location >= 0) {'
+ bind_function = glapi.glapi.get_function_by_name('glBindAttribLocation')
+ self.fake_call(bind_function, ['program', 'location', 'name'])
+ print ' }'
+ print ' }'
+ print ' }'
+ if function.name == 'glLinkProgramARB':
+ Tracer.invokeFunction(self, function)
+ print ' GLint active_attributes = 0;'
+ print ' __glGetObjectParameterivARB(programObj, GL_OBJECT_ACTIVE_ATTRIBUTES_ARB, &active_attributes);'
+ print ' for (GLint attrib = 0; attrib < active_attributes; ++attrib) {'
+ print ' GLint size = 0;'
+ print ' GLenum type = 0;'
+ print ' GLcharARB name[256];'
+ # TODO: Use ACTIVE_ATTRIBUTE_MAX_LENGTH instead of 256
+ print ' __glGetActiveAttribARB(programObj, attrib, sizeof name, NULL, &size, &type, name);'
+ print " if (name[0] != 'g' || name[1] != 'l' || name[2] != '_') {"
+ print ' GLint location = __glGetAttribLocationARB(programObj, name);'
+ print ' if (location >= 0) {'
+ bind_function = glapi.glapi.get_function_by_name('glBindAttribLocationARB')
+ self.fake_call(bind_function, ['programObj', 'location', 'name'])
+ print ' }'
+ print ' }'