/usr/share/pyshared/OpenGL/GL/shaders.py is in python-opengl 3.0.2-1.
This file is owned by root:root, with mode 0o644.
The actual contents of the file can be viewed below.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 | """Convenience module providing common shader entry points
The point of this module is to allow client code to use
OpenGL Core names to reference shader-related operations
even if the local hardware only supports ARB extension-based
shader rendering.
There are also two utility methods compileProgram and compileShader
which make it easy to create demos which are shader-using.
"""
import logging
logging.basicConfig()
log = logging.getLogger( 'OpenGL.GL.shaders' )
from OpenGL import GL
from OpenGL.GL.ARB import (
shader_objects, fragment_shader, vertex_shader, vertex_program,
geometry_shader4, separate_shader_objects, get_program_binary,
)
from OpenGL.extensions import alternate
__all__ = [
'glAttachShader',
'glDeleteShader',
'glGetProgramInfoLog',
'glGetShaderInfoLog',
'glGetProgramiv',
'glGetShaderiv',
'compileProgram',
'compileShader',
'GL_VALIDATE_STATUS',
'GL_LINK_STATUS',
# automatically added stuff here...
]
def _alt( base, name ):
if hasattr( GL, base ):
root = getattr( GL, base )
if hasattr(root,'__call__'):
globals()[base] = alternate(
getattr(GL,base),
getattr(module,name)
)
__all__.append( base )
else:
globals()[base] = root
__all__.append( base )
return True
return False
_excludes = ['glGetProgramiv']
for module in (
shader_objects,fragment_shader,vertex_shader,vertex_program,
geometry_shader4,
):
for name in dir(module):
found = None
for suffix in ('ObjectARB','_ARB','ARB'):
if name.endswith( suffix ):
found = False
base = name[:-(len(suffix))]
if base not in _excludes:
if _alt( base, name ):
found = True
break
if found is False:
log.debug( '''Found no alternate for: %s.%s''',
module.__name__,name,
)
glAttachShader = alternate( GL.glAttachShader,shader_objects.glAttachObjectARB )
glDetachShader = alternate( GL.glDetachShader,shader_objects.glDetachObjectARB )
glDeleteShader = alternate( GL.glDeleteShader,shader_objects.glDeleteObjectARB )
glGetAttachedShaders = alternate( GL.glGetAttachedShaders, shader_objects.glGetAttachedObjectsARB )
glGetProgramInfoLog = alternate( GL.glGetProgramInfoLog, shader_objects.glGetInfoLogARB )
glGetShaderInfoLog = alternate( GL.glGetShaderInfoLog, shader_objects.glGetInfoLogARB )
glGetShaderiv = alternate( GL.glGetShaderiv, shader_objects.glGetObjectParameterivARB )
glGetProgramiv = alternate( GL.glGetProgramiv, shader_objects.glGetObjectParameterivARB )
GL_VALIDATE_STATUS = GL.GL_VALIDATE_STATUS
GL_COMPILE_STATUS = GL.GL_COMPILE_STATUS
GL_LINK_STATUS = GL.GL_LINK_STATUS
GL_FALSE = GL.GL_FALSE
GL_TRUE = GL.GL_TRUE
class ShaderProgram( int ):
"""Integer sub-class with context-manager operation"""
def __enter__( self ):
"""Start use of the program"""
glUseProgram( self )
def __exit__( self, typ, val, tb ):
"""Stop use of the program"""
glUseProgram( 0 )
def check_validate( self ):
"""Check that the program validates
Validation has to occur *after* linking/loading
raises RuntimeError on failures
"""
glValidateProgram( self )
validation = glGetProgramiv( self, GL_VALIDATE_STATUS )
if validation == GL_FALSE:
raise RuntimeError(
"""Validation failure (%s): %s"""%(
validation,
glGetProgramInfoLog( self ),
))
return self
def check_linked( self ):
"""Check link status for this program
raises RuntimeError on failures
"""
link_status = glGetProgramiv( self, GL_LINK_STATUS )
if link_status == GL_FALSE:
raise RuntimeError(
"""Link failure (%s): %s"""%(
link_status,
glGetProgramInfoLog( self ),
))
return self
def retrieve( self ):
"""Attempt to retrieve binary for this compiled shader
Note that binaries for a program are *not* generally portable,
they should be used solely for caching compiled programs for
local use; i.e. to reduce compilation overhead.
returns (format,binaryData) for the shader program
"""
from OpenGL.constants import GLint,GLenum
from OpenGL.arrays import GLbyteArray
size = GLint()
glGetProgramiv( self, get_program_binary.GL_PROGRAM_BINARY_LENGTH, size )
result = GLbyteArray.zeros( (size.value,))
size2 = GLint()
format = GLenum()
get_program_binary.glGetProgramBinary( self, size.value, size2, format, result )
return format.value, result
def load( self, format, binary ):
"""Attempt to load binary-format for a pre-compiled shader
See notes in retrieve
"""
get_program_binary.glProgramBinary( self, format, binary, len(binary))
self.check_validate()
self.check_linked()
return self
def compileProgram(*shaders, **named):
"""Create a new program, attach shaders and validate
shaders -- arbitrary number of shaders to attach to the
generated program.
separable (keyword only) -- set the separable flag to allow
for partial installation of shader into the pipeline (see
glUseProgramStages)
retrievable (keyword only) -- set the retrievable flag to
allow retrieval of the program binary representation, (see
glProgramBinary, glGetProgramBinary)
This convenience function is *not* standard OpenGL,
but it does wind up being fairly useful for demos
and the like. You may wish to copy it to your code
base to guard against PyOpenGL changes.
Usage:
shader = compileProgram(
compileShader( source, GL_VERTEX_SHADER ),
compileShader( source2, GL_FRAGMENT_SHADER ),
)
glUseProgram( shader )
Note:
If (and only if) validation of the linked program
*passes* then the passed-in shader objects will be
deleted from the GL.
returns ShaderProgram() (GLuint) program reference
raises RuntimeError when a link/validation failure occurs
"""
program = glCreateProgram()
if named.get('separable'):
glProgramParameteri( program, separate_shader_objects.GL_PROGRAM_SEPARABLE, GL_TRUE )
if named.get('retrievable'):
glProgramParameteri( program, get_program_binary.GL_PROGRAM_BINARY_RETRIEVABLE_HINT, GL_TRUE )
for shader in shaders:
glAttachShader(program, shader)
program = ShaderProgram( program )
glLinkProgram(program)
program.check_validate()
program.check_linked()
for shader in shaders:
glDeleteShader(shader)
return program
def as_bytes( s ):
"""Utility to retrieve s as raw string (8-bit)"""
if isinstance( s, unicode ):
s = s.encode( ) # TODO: can we use latin-1 or utf-8?
return s
def compileShader( source, shaderType ):
"""Compile shader source of given type
source -- GLSL source-code for the shader
shaderType -- GLenum GL_VERTEX_SHADER, GL_FRAGMENT_SHADER, etc,
returns GLuint compiled shader reference
raises RuntimeError when a compilation failure occurs
"""
if isinstance( source, (str,unicode)):
source = [ source ]
source = [ as_bytes(s) for s in source ]
shader = glCreateShader(shaderType)
glShaderSource( shader, source )
glCompileShader( shader )
result = glGetShaderiv( shader, GL_COMPILE_STATUS )
if not(result):
# TODO: this will be wrong if the user has
# disabled traditional unpacking array support.
raise RuntimeError(
"""Shader compile failure (%s): %s"""%(
result,
glGetShaderInfoLog( shader ),
),
source,
shaderType,
)
return shader
|