1'''OpenGL extension ARB.shader_objects 2 3This module customises the behaviour of the 4OpenGL.raw.GL.ARB.shader_objects to provide a more 5Python-friendly API 6 7Overview (from the spec) 8 9 This extension adds API calls that are necessary to manage shader 10 objects and program objects as defined in the OpenGL 2.0 white papers by 11 3Dlabs. 12 13 The generation of an executable that runs on one of OpenGL's 14 programmable units is modeled to that of developing a typical C/C++ 15 application. There are one or more source files, each of which are 16 stored by OpenGL in a shader object. Each shader object (source file) 17 needs to be compiled and attached to a program object. Once all shader 18 objects are compiled successfully, the program object needs to be linked 19 to produce an executable. This executable is part of the program object, 20 and can now be loaded onto the programmable units to make it part of the 21 current OpenGL state. Both the compile and link stages generate a text 22 string that can be queried to get more information. This information 23 could be, but is not limited to, compile errors, link errors, 24 optimization hints, etc. Values for uniform variables, declared in a 25 shader, can be set by the application and used to control a shader's 26 behavior. 27 28 This extension defines functions for creating shader objects and program 29 objects, for compiling shader objects, for linking program objects, for 30 attaching shader objects to program objects, and for using a program 31 object as part of current state. Functions to load uniform values are 32 also defined. Some house keeping functions, like deleting an object and 33 querying object state, are also provided. 34 35 Although this extension defines the API for creating shader objects, it 36 does not define any specific types of shader objects. It is assumed that 37 this extension will be implemented along with at least one such 38 additional extension for creating a specific type of OpenGL 2.0 shader 39 (e.g., the ARB_fragment_shader extension or the ARB_vertex_shader 40 extension). 41 42The official definition of this extension is available here: 43http://www.opengl.org/registry/specs/ARB/shader_objects.txt 44''' 45from OpenGL import platform, constant, arrays 46from OpenGL import extensions, wrapper 47import ctypes 48from OpenGL.raw.GL import _types, _glgets 49from OpenGL.raw.GL.ARB.shader_objects import * 50from OpenGL.raw.GL.ARB.shader_objects import _EXTENSION_NAME 51 52def glInitShaderObjectsARB(): 53 '''Return boolean indicating whether this extension is available''' 54 from OpenGL import extensions 55 return extensions.hasGLExtension( _EXTENSION_NAME ) 56 57# INPUT glShaderSourceARB.length size not checked against count 58# INPUT glShaderSourceARB.string size not checked against count 59glShaderSourceARB=wrapper.wrapper(glShaderSourceARB).setInputArraySize( 60 'length', None 61).setInputArraySize( 62 'string', None 63) 64# INPUT glUniform1fvARB.value size not checked against count 65glUniform1fvARB=wrapper.wrapper(glUniform1fvARB).setInputArraySize( 66 'value', None 67) 68# INPUT glUniform2fvARB.value size not checked against count*2 69glUniform2fvARB=wrapper.wrapper(glUniform2fvARB).setInputArraySize( 70 'value', None 71) 72# INPUT glUniform3fvARB.value size not checked against count*3 73glUniform3fvARB=wrapper.wrapper(glUniform3fvARB).setInputArraySize( 74 'value', None 75) 76# INPUT glUniform4fvARB.value size not checked against count*4 77glUniform4fvARB=wrapper.wrapper(glUniform4fvARB).setInputArraySize( 78 'value', None 79) 80# INPUT glUniform1ivARB.value size not checked against count 81glUniform1ivARB=wrapper.wrapper(glUniform1ivARB).setInputArraySize( 82 'value', None 83) 84# INPUT glUniform2ivARB.value size not checked against count*2 85glUniform2ivARB=wrapper.wrapper(glUniform2ivARB).setInputArraySize( 86 'value', None 87) 88# INPUT glUniform3ivARB.value size not checked against count*3 89glUniform3ivARB=wrapper.wrapper(glUniform3ivARB).setInputArraySize( 90 'value', None 91) 92# INPUT glUniform4ivARB.value size not checked against count*4 93glUniform4ivARB=wrapper.wrapper(glUniform4ivARB).setInputArraySize( 94 'value', None 95) 96# INPUT glUniformMatrix2fvARB.value size not checked against count*4 97glUniformMatrix2fvARB=wrapper.wrapper(glUniformMatrix2fvARB).setInputArraySize( 98 'value', None 99) 100# INPUT glUniformMatrix3fvARB.value size not checked against count*9 101glUniformMatrix3fvARB=wrapper.wrapper(glUniformMatrix3fvARB).setInputArraySize( 102 'value', None 103) 104# INPUT glUniformMatrix4fvARB.value size not checked against count*16 105glUniformMatrix4fvARB=wrapper.wrapper(glUniformMatrix4fvARB).setInputArraySize( 106 'value', None 107) 108glGetObjectParameterfvARB=wrapper.wrapper(glGetObjectParameterfvARB).setOutput( 109 'params',size=_glgets._glget_size_mapping,pnameArg='pname',orPassIn=True 110) 111glGetObjectParameterivARB=wrapper.wrapper(glGetObjectParameterivARB).setOutput( 112 'params',size=_glgets._glget_size_mapping,pnameArg='pname',orPassIn=True 113) 114glGetInfoLogARB=wrapper.wrapper(glGetInfoLogARB).setOutput( 115 'infoLog',size=lambda x:(x,),pnameArg='maxLength',orPassIn=True 116).setOutput( 117 'length',size=(1,),orPassIn=True 118) 119glGetAttachedObjectsARB=wrapper.wrapper(glGetAttachedObjectsARB).setOutput( 120 'count',size=(1,),orPassIn=True 121).setOutput( 122 'obj',size=lambda x:(x,),pnameArg='maxCount',orPassIn=True 123) 124glGetActiveUniformARB=wrapper.wrapper(glGetActiveUniformARB).setOutput( 125 'length',size=(1,),orPassIn=True 126).setOutput( 127 'name',size=lambda x:(x,),pnameArg='maxLength',orPassIn=True 128).setOutput( 129 'size',size=(1,),orPassIn=True 130).setOutput( 131 'type',size=(1,),orPassIn=True 132) 133# OUTPUT glGetUniformfvARB.params COMPSIZE(programObj, location) 134# OUTPUT glGetUniformivARB.params COMPSIZE(programObj, location) 135glGetShaderSourceARB=wrapper.wrapper(glGetShaderSourceARB).setOutput( 136 'length',size=(1,),orPassIn=True 137).setOutput( 138 'source',size=lambda x:(x,),pnameArg='maxLength',orPassIn=True 139) 140### END AUTOGENERATED SECTION 141import OpenGL 142from OpenGL._bytes import bytes, _NULL_8_BYTE, as_8_bit 143from OpenGL.raw.GL import _errors 144from OpenGL.lazywrapper import lazy as _lazy 145from OpenGL import converters, error 146GL_INFO_LOG_LENGTH_ARB = constant.Constant( 'GL_INFO_LOG_LENGTH_ARB', 0x8B84 ) 147 148glShaderSourceARB = platform.createExtensionFunction( 149 'glShaderSourceARB', dll=platform.PLATFORM.GL, 150 resultType=None, 151 argTypes=(_types.GLhandleARB, _types.GLsizei, ctypes.POINTER(ctypes.c_char_p), arrays.GLintArray,), 152 doc = 'glShaderSourceARB( GLhandleARB(shaderObj), [bytes(string),...] ) -> None', 153 argNames = ('shaderObj', 'count', 'string', 'length',), 154 extension = _EXTENSION_NAME, 155) 156conv = converters.StringLengths( name='string' ) 157glShaderSourceARB = wrapper.wrapper( 158 glShaderSourceARB 159).setPyConverter( 160 'count' # number of strings 161).setPyConverter( 162 'length' # lengths of strings 163).setPyConverter( 164 'string', conv.stringArray 165).setCResolver( 166 'string', conv.stringArrayForC, 167).setCConverter( 168 'length', conv, 169).setCConverter( 170 'count', conv.totalCount, 171) 172try: 173 del conv 174except NameError as err: 175 pass 176 177def _afterCheck( key ): 178 """Generate an error-checking function for compilation operations""" 179 def GLSLCheckError( 180 result, 181 baseOperation=None, 182 cArguments=None, 183 *args 184 ): 185 result = _errors._error_checker.glCheckError( result, baseOperation, cArguments, *args ) 186 status = glGetObjectParameterivARB( 187 cArguments[0], key 188 ) 189 if not status: 190 raise error.GLError( 191 result = result, 192 baseOperation = baseOperation, 193 cArguments = cArguments, 194 description= glGetInfoLogARB( cArguments[0] ) 195 ) 196 return result 197 return GLSLCheckError 198 199if OpenGL.ERROR_CHECKING: 200 glCompileShaderARB.errcheck = _afterCheck( GL_OBJECT_COMPILE_STATUS_ARB ) 201if OpenGL.ERROR_CHECKING: 202 glLinkProgramARB.errcheck = _afterCheck( GL_OBJECT_LINK_STATUS_ARB ) 203## Not sure why, but these give invalid operation :( 204##if glValidateProgramARB and OpenGL.ERROR_CHECKING: 205## glValidateProgramARB.errcheck = _afterCheck( GL_OBJECT_VALIDATE_STATUS_ARB ) 206 207@_lazy( glGetInfoLogARB ) 208def glGetInfoLogARB( baseOperation, obj ): 209 """Retrieve the program/shader's error messages as a Python string 210 211 returns string which is '' if no message 212 """ 213 length = int(glGetObjectParameterivARB(obj, GL_INFO_LOG_LENGTH_ARB)) 214 if length > 0: 215 log = ctypes.create_string_buffer(length) 216 baseOperation(obj, length, None, log) 217 return log.value.strip(_NULL_8_BYTE) # null-termination 218 return '' 219 220@_lazy( glGetAttachedObjectsARB ) 221def glGetAttachedObjectsARB( baseOperation, obj ): 222 """Retrieve the attached objects as an array of GLhandleARB instances""" 223 length= glGetObjectParameterivARB( obj, GL_OBJECT_ATTACHED_OBJECTS_ARB ) 224 if length > 0: 225 storage = arrays.GLuintArray.zeros( (length,)) 226 baseOperation( obj, length, None, storage ) 227 return storage 228 return arrays.GLuintArray.zeros( (0,)) 229 230@_lazy( glGetShaderSourceARB ) 231def glGetShaderSourceARB( baseOperation, obj ): 232 """Retrieve the program/shader's source code as a Python string 233 234 returns string which is '' if no source code 235 """ 236 length = int(glGetObjectParameterivARB(obj, GL_OBJECT_SHADER_SOURCE_LENGTH_ARB)) 237 if length > 0: 238 source = ctypes.create_string_buffer(length) 239 baseOperation(obj, length, None, source) 240 return source.value.strip(_NULL_8_BYTE) # null-termination 241 return '' 242 243@_lazy( glGetActiveUniformARB ) 244def glGetActiveUniformARB(baseOperation,program, index,bufSize=None): 245 """Retrieve the name, size and type of the uniform of the index in the program""" 246 max_index = int(glGetObjectParameterivARB( program, GL_OBJECT_ACTIVE_UNIFORMS_ARB )) 247 if bufSize is None: 248 bufSize = int(glGetObjectParameterivARB( program, GL_OBJECT_ACTIVE_UNIFORM_MAX_LENGTH_ARB)) 249 if index < max_index and index >= 0: 250 length,name,size,type = baseOperation( program, index, bufSize ) 251 if hasattr(name,'tostring'): 252 name = name.tostring().rstrip(b'\000') 253 elif hasattr(name,'value'): 254 name = name.value 255 return name,size,type 256 raise IndexError( 'Index %s out of range 0 to %i' % (index, max_index - 1, ) ) 257 258@_lazy( glGetUniformLocationARB ) 259def glGetUniformLocationARB( baseOperation, program, name ): 260 """Check that name is a string with a null byte at the end of it""" 261 if not name: 262 raise ValueError( """Non-null name required""" ) 263 name = as_8_bit( name ) 264 if name[-1] != _NULL_8_BYTE: 265 name = name + _NULL_8_BYTE 266 return baseOperation( program, name ) 267