def create_program_attribute_layout(program): active_attribute = c_int(0) GL.glGetProgramiv(program, GL.GL_ACTIVE_ATTRIBUTES, active_attribute) max_name_length = GL.glGetProgramiv(program, GL.GL_ACTIVE_ATTRIBUTE_MAX_LENGTH) name_length = GL.GLsizei(0) attribute_size = GL.GLint(0) attribute_type = GL.GLenum(0) name = (GL.GLchar * max_name_length)() attribute_layout = [] for index in range(active_attribute.value): GL.glGetActiveAttrib(program, index, max_name_length, name_length, attribute_size, attribute_type, name) attribute_location = GL.glGetAttribLocation(program, name.value) attribute_layout.append((attribute_location, ATTRIBUTE_SIZE_BY_TYPES[attribute_type.value])) attribute_layout.sort(key=lambda pair: pair[0]) attribute_locations = [] attribute_sizes = [] for attribute_location, attribute_size in attribute_layout: attribute_locations.append(attribute_location) attribute_sizes.append(attribute_size) return attribute_locations, attribute_sizes
def __init__(self, vertex_shader, fragment_shader, geom_shader=None): self.shaders = list() self.attribs = dict() self.ubos = dict() GLVariable = namedtuple('GLVariable', ['loc', 'size']) # Compile shaders and link program self.compile_shader(vertex_shader, gl.GL_VERTEX_SHADER) self.compile_shader(fragment_shader, gl.GL_FRAGMENT_SHADER) if geom_shader: self.compile_shader(geom_shader, gl.GL_GEOMETRY_SHADER) self.link() size = gl.GLint() name = (ctypes.c_char * 20)() # Obtain list of attributes with location and size info n_attrs = gl.glGetProgramiv(self.program, gl.GL_ACTIVE_ATTRIBUTES) for a in range(n_attrs): atype = gl.GLint() gl.glGetActiveAttrib(self.program, a, 20, None, ctypes.pointer(size), ctypes.pointer(atype), ctypes.pointer(name)) loc = gl.glGetAttribLocation(self.program, name.value) typesize = _glvar_sizes.get(atype.value, 1) self.attribs[name.value.decode('utf8')] = GLVariable(loc, size.value * typesize) n_uniforms = gl.glGetProgramiv(self.program, gl.GL_ACTIVE_UNIFORMS) all_uids = set(range(n_uniforms)) n_ub = gl.glGetProgramiv(self.program, gl.GL_ACTIVE_UNIFORM_BLOCKS) for ub in range(n_ub): gl.glGetActiveUniformBlockName(self.program, ub, 20, None, ctypes.pointer(name)) gl.glGetActiveUniformBlockiv(self.program, ub, gl.GL_UNIFORM_BLOCK_DATA_SIZE, ctypes.pointer(size)) self.ubos[name.value.decode('utf-8')] = size.value ubsize = gl.GLint() gl.glGetActiveUniformBlockiv(self.program, ub, gl.GL_UNIFORM_BLOCK_ACTIVE_UNIFORMS, ctypes.pointer(ubsize)) indices = (ctypes.c_int * ubsize.value)() gl.glGetActiveUniformBlockiv(self.program, ub, gl.GL_UNIFORM_BLOCK_ACTIVE_UNIFORM_INDICES, ctypes.pointer(indices)) all_uids -= set(indices) # print('Uniform block: ', name.value.decode('utf8'), 'size =', ubsize.value) # for i in indices: # usize = gl.GLint() # utype = gl.GLint() # uname = (ctpes.c_char * 20)() # # gl.glGetActiveUniform(self.program, i, 20, None, ctypes.pointer(usize), ctypes.pointer(utype), ctypes.pointer(uname)) # # print('block uniform', i, '=', uname.value.decode('utf8'), 'size =', usize.value) # print(gl.glGetActiveUniform(self.program, i)) for u in all_uids: name, size, utype = gl.glGetActiveUniform(self.program, u) setattr(self, name.decode('utf-8'), GLVariable(u, size * _glvar_sizes.get(utype, 1)))
def get_fence_signalled(self): ''' Returns a boolean describing whether the fence has been signalled. ''' if self.__sync is not None: fence_status = GL.GLint(0) GL_sync.glGetSynciv(self.__sync, GL_sync.GL_SYNC_STATUS, GL.GLint(1), GL.GLint(0), fence_status) return (GL_sync.GL_SIGNALED == fence_status.value) else: return False
def build_attribute_map(self): """ Builds an internal attribute map by querying the program. This way we don't have to query OpenGL (can cause slowdowns) This information is also used when the shader and VAO negotiates the buffer binding. """ attribute_count = GL.glGetProgramiv(self.program, GL.GL_ACTIVE_ATTRIBUTES) bufsize = GL.glGetProgramiv(self.program, GL.GL_ACTIVE_ATTRIBUTE_MAX_LENGTH) print("Shader {} has {} attribute(s)".format(self.name, attribute_count)) for i in range(attribute_count): # Unlike glGetActiveUniform the attrib version do not return a convenient tuple # and we'll have to use to ugly version. (Most people make wrappers for this one) length, size, type, name = GL.GLsizei(), GL.GLint(), GL.GLenum(), ( GL.GLchar * bufsize)() GL.glGetActiveAttrib(self.program, i, bufsize, length, size, type, name) # Get the actual location. Do not trust the original order location = GL.glGetAttribLocation(self.program, name.value) attribute = Attribute(name.value, type.value, location) self.attribute_map[attribute.name] = attribute self.attribute_list.append(attribute) print(" - {}".format(attribute)) self.attribute_key = ','.join( name for name in sorted(self.attribute_map.keys())) print("Shader attribute key:", self.attribute_key)
def _get_attribs(self) -> Dict[str, IndexSizeType]: _active_attrib = GL.glGetProgramiv(self.program, GL.GL_ACTIVE_ATTRIBUTES) # For some reason the PyOpenGL Binding is sorta broken # use the full ctypes-style access bufSize = 50 ct_nameSize = GL.GLsizei() ct_size = GL.GLint() ct_type = GL.GLenum() ct_name = (GL.GLchar * bufSize)() _attribs = {} for attrib_index in range(_active_attrib): GL.glGetActiveAttrib(self.program, attrib_index, bufSize, ct_nameSize, ct_size, ct_type, ct_name) #in python3 attribute names are bytestrings. Convert to UTF8 name = ct_name.value.decode("ascii") _attribs[name] = IndexSizeType(attrib_index, ct_size.value, ct_type.value) return _attribs
def tkCreateContext(self): self.__window = XOpenDisplay(self.winfo_screen().encode('utf-8')) # Check glx version: major = c_int(0) minor = c_int(0) GLX.glXQueryVersion(self.__window, major, minor) print("GLX version: %d.%d" % (major.value, minor.value)) if major.value == 1 and minor.value < 3: # e.g. 1.2 and down visual = GLX.glXChooseVisual(self.__window, 0, (GL.GLint * len(att))(*att)) if not visual: _log.error("glXChooseVisual call failed") self.__context = GLX.glXCreateContext(self.__window, visual, None, GL.GL_TRUE) GLX.glXMakeCurrent(self.__window, self._wid, self.__context) return # OUT HERE FOR 1.2 and less else: # 1.3 or higher # which screen - should it be winfo_screen instead ?? XDefaultScreen = _x11lib.XDefaultScreen XDefaultScreen.argtypes = [POINTER(Display)] XDefaultScreen.restype = c_int screen = XDefaultScreen(self.__window) print("Screen is ", screen) # Look at framebuffer configs ncfg = GL.GLint(0) cfgs = GLX.glXChooseFBConfig(self.__window, screen, (GL.GLint * len(fbatt))(*fbatt), ncfg) print("Number of FBconfigs", ncfg.value) # # Try to match to the current window # ... might also be possible to set this for the frame # ... but for now we just take what Tk gave us ideal = int(self.winfo_visualid(), 16) # convert from hex best = -1 for i in range(ncfg.value): vis = GLX.glXGetVisualFromFBConfig(self.__window, cfgs[i]) if ideal == vis.contents.visualid: best = i print("Got a matching visual: index %d %d xid %s" % (best, vis.contents.visualid, hex(ideal))) if best < 0: print("oh dear - visual does not match") # Take the first in the list (should be another I guess) best = 0 # Here we insist on RGBA - but didn't check earlier self.__context = GLX.glXCreateNewContext( self.__window, cfgs[best], GLX.GLX_RGBA_TYPE, None, # share list GL.GL_TRUE) # direct print("Is Direct?: ", GLX.glXIsDirect(self.__window, self.__context)) # Not creating another window ... some tutorials do # print("wid: ",self._wid) # self._wid = GLX.glXCreateWindow( self.__window, cfgs[best], self._wid, None) # print("wid: ",self._wid) GLX.glXMakeContextCurrent(self.__window, self._wid, self._wid, self.__context) print("Done making a first context") extensions = GLX.glXQueryExtensionsString( self.__window, screen) # Here we quit - getting a modern context needs further work below return if "GLX_ARB_create_context" in extensions: # We can try to upgrade it ?? print("Trying to upgrade context") s = "glXCreateContextAttribsARB" p = GLX.glXGetProcAddress(c_char_p(s)) print(p) if not p: p = GLX.glXGetProcAddressARB( (GL.GLubyte * len(s)).from_buffer_copy(s)) print(p) if p: print(" p is true") p.restype = GLX.GLXContext p.argtypes = [ POINTER(Display), GLX.GLXFBConfig, GLX.GLXContext, c_bool, POINTER(c_int) ] arb_attrs = fbatt[:-1] + [] # GLX.GLX_CONTEXT_MAJOR_VERSION_ARB , 3 # GLX.GLX_CONTEXT_MINOR_VERSION_ARB , 1, # 0 ] # # GLX.GLX_CONTEXT_FLAGS_ARB # GLX.GLX_CONTEXT_PROFILE_MASK_ARB #] # import pdb # pdb.set_trace() self.__context = p(self.__window, cfgs[best], None, GL.GL_TRUE, (GL.GLint * len(arb_attrs))(*arb_attrs))
def CreateTexture(target: GL.GLenum) -> int: _id = GL.GLint() GL.glCreateTextures(target, 1, _id) return _id.value
def CreateFramebuffer() -> int: _id = GL.GLint() GL.glCreateFramebuffers(1, _id) return _id.value
def CreateVertexArray() -> int: _id = GL.GLint() GL.glCreateVertexArrays(1, _id) return _id.value