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