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 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301
|
"""Array data-type implementations (abstraction points for GL array types"""
import ctypes
import OpenGL
from OpenGL.raw.GL import _types
from OpenGL import plugins
from OpenGL.arrays import formathandler, _arrayconstants as GL_1_1
from OpenGL import logs
_log = logs.getLog( 'OpenGL.arrays.arraydatatype' )
from OpenGL import acceleratesupport
ADT = None
if acceleratesupport.ACCELERATE_AVAILABLE:
try:
from OpenGL_accelerate.arraydatatype import ArrayDatatype as ADT
except ImportError as err:
_log.warn(
"Unable to load ArrayDatatype accelerator from OpenGL_accelerate"
)
if ADT is None:
# Python-coded version
class HandlerRegistry( dict ):
GENERIC_OUTPUT_PREFERENCES = ['numpy','ctypesarrays']
def __init__( self, plugin_match ):
self.match = plugin_match
self.output_handler = None
self.preferredOutput = None
self.all_output_handlers = []
def __call__( self, value ):
"""Lookup of handler for given value"""
try:
typ = value.__class__
except AttributeError as err:
typ = type(value)
handler = self.get( typ )
if not handler:
if hasattr( typ, '__mro__' ):
for base in typ.__mro__:
handler = self.get( base )
if not handler:
handler = self.match( base )
if handler:
handler = handler.load()
if handler:
handler = handler()
if handler:
self[ typ ] = handler
if hasattr( handler, 'registerEquivalent' ):
handler.registerEquivalent( typ, base )
return handler
raise TypeError(
"""No array-type handler for type %s.%s (value: %s) registered"""%(
typ.__module__, type.__name__, repr(value)[:50]
)
)
return handler
def handler_by_plugin_name( self, name ):
plugin = plugins.FormatHandler.by_name( name )
if plugin:
try:
return plugin.load()
except ImportError as err:
return None
else:
raise RuntimeError( 'No handler of name %s found'%(name,))
def get_output_handler( self ):
"""Fast-path lookup for output handler object"""
if self.output_handler is None:
if self.preferredOutput is not None:
self.output_handler = self.handler_by_plugin_name( self.preferredOutput )
if not self.output_handler:
for preferred in self.GENERIC_OUTPUT_PREFERENCES:
self.output_handler = self.handler_by_plugin_name( preferred )
if self.output_handler:
break
if not self.output_handler:
raise RuntimeError(
"""Unable to find any output handler at all (not even ctypes/numpy ones!)"""
)
return self.output_handler
def register( self, handler, types=None ):
"""Register this class as handler for given set of types"""
if not isinstance( types, (list,tuple)):
types = [ types ]
for type in types:
self[ type ] = handler
if handler.isOutput:
self.all_output_handlers.append( handler )
def registerReturn( self, handler ):
"""Register this handler as the default return-type handler"""
if isinstance( handler, (str,unicode)):
self.preferredOutput = handler
self.output_handler = None
else:
self.preferredOutput = None
self.output_handler = handler
GLOBAL_REGISTRY = HandlerRegistry( plugins.FormatHandler.match)
formathandler.FormatHandler.TYPE_REGISTRY = GLOBAL_REGISTRY
class ArrayDatatype( object ):
"""Mix-in for array datatype classes
The ArrayDatatype marker essentially is used to mark a particular argument
as having an "array" type, which means that it is eligible for handling
via the arrays sub-package and its registered handlers.
"""
typeConstant = None
handler = GLOBAL_REGISTRY
getHandler = GLOBAL_REGISTRY.__call__
returnHandler = GLOBAL_REGISTRY.get_output_handler
isAccelerated = False
@classmethod
def getRegistry( cls ):
"""Get our handler registry"""
return cls.handler
def from_param( cls, value, typeConstant=None ):
"""Given a value in a known data-pointer type, convert to a ctypes pointer"""
return cls.getHandler(value).from_param( value, cls.typeConstant )
from_param = classmethod( logs.logOnFail( from_param, _log ) )
def dataPointer( cls, value ):
"""Given a value in a known data-pointer type, return long for pointer"""
try:
return cls.getHandler(value).dataPointer( value )
except Exception as err:
_log.warn(
"""Failure in dataPointer for %s instance %s""", type(value), value,
)
raise
dataPointer = classmethod( logs.logOnFail( dataPointer, _log ) )
def voidDataPointer( cls, value ):
"""Given value in a known data-pointer type, return void_p for pointer"""
pointer = cls.dataPointer( value )
try:
return ctypes.c_void_p(pointer)
except TypeError as err:
return pointer
voidDataPointer = classmethod( logs.logOnFail( voidDataPointer, _log ) )
def typedPointer( cls, value ):
"""Return a pointer-to-base-type pointer for given value"""
return ctypes.cast( cls.dataPointer(value), ctypes.POINTER( cls.baseType ))
typedPointer = classmethod( typedPointer )
def asArray( cls, value, typeCode=None ):
"""Given a value, convert to preferred array representation"""
return cls.getHandler(value).asArray( value, typeCode or cls.typeConstant )
asArray = classmethod( logs.logOnFail( asArray, _log ) )
def arrayToGLType( cls, value ):
"""Given a data-value, guess the OpenGL type of the corresponding pointer
Note: this is not currently used in PyOpenGL and may be removed
eventually.
"""
return cls.getHandler(value).arrayToGLType( value )
arrayToGLType = classmethod( logs.logOnFail( arrayToGLType, _log ) )
def arraySize( cls, value, typeCode = None ):
"""Given a data-value, calculate dimensions for the array (number-of-units)"""
return cls.getHandler(value).arraySize( value, typeCode or cls.typeConstant )
arraySize = classmethod( logs.logOnFail( arraySize, _log ) )
def unitSize( cls, value, typeCode=None ):
"""Determine unit size of an array (if possible)
Uses our local type if defined, otherwise asks the handler to guess...
"""
return cls.getHandler(value).unitSize( value, typeCode or cls.typeConstant )
unitSize = classmethod( logs.logOnFail( unitSize, _log ) )
def zeros( cls, dims, typeCode=None ):
"""Allocate a return array of the given dimensions filled with zeros"""
return cls.returnHandler().zeros( dims, typeCode or cls.typeConstant )
zeros = classmethod( logs.logOnFail( zeros, _log ) )
def dimensions( cls, value ):
"""Given a data-value, get the dimensions (assumes full structure info)"""
return cls.getHandler(value).dimensions( value )
dimensions = classmethod( logs.logOnFail( dimensions, _log ) )
def arrayByteCount( cls, value ):
"""Given a data-value, try to determine number of bytes it's final form occupies
For most data-types this is arraySize() * atomic-unit-size
"""
return cls.getHandler(value).arrayByteCount( value )
arrayByteCount = classmethod( logs.logOnFail( arrayByteCount, _log ) )
# the final array data-type classes...
class GLclampdArray( ArrayDatatype, ctypes.POINTER(_types.GLclampd )):
"""Array datatype for GLclampd types"""
baseType = _types.GLclampd
typeConstant = _types.GL_DOUBLE
class GLclampfArray( ArrayDatatype, ctypes.POINTER(_types.GLclampf )):
"""Array datatype for GLclampf types"""
baseType = _types.GLclampf
typeConstant = _types.GL_FLOAT
class GLfloatArray( ArrayDatatype, ctypes.POINTER(_types.GLfloat )):
"""Array datatype for GLfloat types"""
baseType = _types.GLfloat
typeConstant = _types.GL_FLOAT
class GLdoubleArray( ArrayDatatype, ctypes.POINTER(_types.GLdouble )):
"""Array datatype for GLdouble types"""
baseType = _types.GLdouble
typeConstant = _types.GL_DOUBLE
class GLbyteArray( ArrayDatatype, ctypes.POINTER(_types.GLbyte )):
"""Array datatype for GLbyte types"""
baseType = _types.GLbyte
typeConstant = _types.GL_BYTE
class GLcharArray( ArrayDatatype, ctypes.c_char_p):
"""Array datatype for ARB extension pointers-to-arrays"""
baseType = _types.GLchar
typeConstant = _types.GL_BYTE
GLcharARBArray = GLcharArray
class GLshortArray( ArrayDatatype, ctypes.POINTER(_types.GLshort )):
"""Array datatype for GLshort types"""
baseType = _types.GLshort
typeConstant = _types.GL_SHORT
class GLintArray( ArrayDatatype, ctypes.POINTER(_types.GLint )):
"""Array datatype for GLint types"""
baseType = _types.GLint
typeConstant = _types.GL_INT
class GLubyteArray( ArrayDatatype, ctypes.POINTER(_types.GLubyte )):
"""Array datatype for GLubyte types"""
baseType = _types.GLubyte
typeConstant = _types.GL_UNSIGNED_BYTE
GLbooleanArray = GLubyteArray
class GLushortArray( ArrayDatatype, ctypes.POINTER(_types.GLushort )):
"""Array datatype for GLushort types"""
baseType = _types.GLushort
typeConstant = _types.GL_UNSIGNED_SHORT
class GLuintArray( ArrayDatatype, ctypes.POINTER(_types.GLuint )):
"""Array datatype for GLuint types"""
baseType = _types.GLuint
typeConstant = _types.GL_UNSIGNED_INT
class GLint64Array( ArrayDatatype, ctypes.POINTER(_types.GLint64 )):
"""Array datatype for GLuint types"""
baseType = _types.GLint64
typeConstant = None # TODO: find out what this should be!
class GLuint64Array( ArrayDatatype, ctypes.POINTER(_types.GLuint64 )):
"""Array datatype for GLuint types"""
baseType = _types.GLuint64
typeConstant = _types.GL_UNSIGNED_INT64
class GLenumArray( ArrayDatatype, ctypes.POINTER(_types.GLenum )):
"""Array datatype for GLenum types"""
baseType = _types.GLenum
typeConstant = _types.GL_UNSIGNED_INT
class GLsizeiArray( ArrayDatatype, ctypes.POINTER(_types.GLsizei )):
"""Array datatype for GLsizei types"""
baseType = _types.GLsizei
typeConstant = _types.GL_INT
class GLvoidpArray( ArrayDatatype, ctypes.POINTER(_types.GLvoid )):
"""Array datatype for GLenum types"""
baseType = _types.GLvoidp
typeConstant = _types.GL_VOID_P
else:
# Cython-coded array handler
_log.info( 'Using accelerated ArrayDatatype' )
ArrayDatatype = ADT( None, None )
GLclampdArray = ADT( GL_1_1.GL_DOUBLE, _types.GLclampd )
GLclampfArray = ADT( GL_1_1.GL_FLOAT, _types.GLclampf )
GLdoubleArray = ADT( GL_1_1.GL_DOUBLE, _types.GLdouble )
GLfloatArray = ADT( GL_1_1.GL_FLOAT, _types.GLfloat )
GLbyteArray = ADT( GL_1_1.GL_BYTE, _types.GLbyte )
GLcharArray = GLcharARBArray = ADT( GL_1_1.GL_BYTE, _types.GLchar )
GLshortArray = ADT( GL_1_1.GL_SHORT, _types.GLshort )
GLintArray = ADT( GL_1_1.GL_INT, _types.GLint )
GLubyteArray = GLbooleanArray = ADT( GL_1_1.GL_UNSIGNED_BYTE, _types.GLubyte )
GLushortArray = ADT( GL_1_1.GL_UNSIGNED_SHORT, _types.GLushort )
GLuintArray = ADT( GL_1_1.GL_UNSIGNED_INT, _types.GLuint )
GLint64Array = ADT( None, _types.GLint64 )
GLuint64Array = ADT( GL_1_1.GL_UNSIGNED_INT64, _types.GLuint64 )
GLenumArray = ADT( GL_1_1.GL_UNSIGNED_INT, _types.GLenum )
GLsizeiArray = ADT( GL_1_1.GL_INT, _types.GLsizei )
GLvoidpArray = ADT( _types.GL_VOID_P, _types.GLvoidp )
GL_CONSTANT_TO_ARRAY_TYPE = {
GL_1_1.GL_DOUBLE : GLclampdArray,
GL_1_1.GL_FLOAT : GLclampfArray,
GL_1_1.GL_FLOAT : GLfloatArray,
GL_1_1.GL_DOUBLE : GLdoubleArray,
GL_1_1.GL_BYTE : GLbyteArray,
GL_1_1.GL_SHORT : GLshortArray,
GL_1_1.GL_INT : GLintArray,
GL_1_1.GL_UNSIGNED_BYTE : GLubyteArray,
GL_1_1.GL_UNSIGNED_SHORT : GLushortArray,
GL_1_1.GL_UNSIGNED_INT : GLuintArray,
#GL_1_1.GL_UNSIGNED_INT : GLenumArray,
}
|