|
"""Helper functions for wrapping array-using operations |
|
|
|
These are functions intended to be used in wrapping |
|
GL functions that deal with OpenGL array data-types. |
|
""" |
|
import OpenGL |
|
import ctypes |
|
from OpenGL import _configflags |
|
from OpenGL import contextdata, error, converters |
|
from OpenGL.arrays import arraydatatype |
|
from OpenGL._bytes import bytes,unicode |
|
import logging |
|
_log = logging.getLogger( 'OpenGL.arrays.arrayhelpers' ) |
|
from OpenGL import acceleratesupport |
|
AsArrayTypedSizeChecked = None |
|
if acceleratesupport.ACCELERATE_AVAILABLE: |
|
try: |
|
from OpenGL_accelerate.arraydatatype import AsArrayTypedSizeChecked |
|
from OpenGL_accelerate.wrapper import returnPyArgumentIndex |
|
from OpenGL_accelerate.arraydatatype import ( |
|
AsArrayOfType,AsArrayTyped,AsArrayTypedSize |
|
) |
|
except ImportError as err: |
|
_log.warning( |
|
"Unable to load arrayhelpers accelerator from OpenGL_accelerate" |
|
) |
|
if AsArrayTypedSizeChecked is None: |
|
def returnPointer( result,baseOperation,pyArgs,cArgs, ): |
|
"""Return the converted object as result of function |
|
|
|
Note: this is a hack that always returns pyArgs[0]! |
|
""" |
|
return pyArgs[0] |
|
class AsArrayOfType( converters.PyConverter ): |
|
"""Given arrayName and typeName coerce arrayName to array of type typeName |
|
|
|
TODO: It should be possible to drop this if ERROR_ON_COPY, |
|
as array inputs always have to be the final objects in that |
|
case. |
|
""" |
|
argNames = ( 'arrayName','typeName' ) |
|
indexLookups = ( |
|
('arrayIndex', 'arrayName','pyArgIndex'), |
|
('typeIndex', 'typeName','pyArgIndex'), |
|
) |
|
def __init__( self, arrayName='pointer', typeName='type' ): |
|
self.arrayName = arrayName |
|
self.typeName = typeName |
|
def __call__( self, arg, wrappedOperation, args): |
|
"""Get the arg as an array of the appropriate type""" |
|
type = args[ self.typeIndex ] |
|
arrayType = arraydatatype.GL_CONSTANT_TO_ARRAY_TYPE[ type ] |
|
return arrayType.asArray( arg ) |
|
class AsArrayTyped( converters.PyConverter ): |
|
"""Given arrayName and arrayType, convert arrayName to array of type |
|
|
|
TODO: It should be possible to drop this if ERROR_ON_COPY, |
|
as array inputs always have to be the final objects in that |
|
case. |
|
""" |
|
argNames = ( 'arrayName','arrayType' ) |
|
indexLookups = ( |
|
('arrayIndex', 'arrayName','pyArgIndex'), |
|
) |
|
def __init__( self, arrayName='pointer', arrayType=None ): |
|
self.arrayName = arrayName |
|
self.arrayType = arrayType |
|
def __call__( self, arg, wrappedOperation, args): |
|
"""Get the arg as an array of the appropriate type""" |
|
return self.arrayType.asArray( arg ) |
|
class AsArrayTypedSize( converters.CConverter ): |
|
"""Given arrayName and arrayType, determine size of arrayName |
|
""" |
|
argNames = ( 'arrayName','arrayType' ) |
|
indexLookups = ( |
|
('arrayIndex', 'arrayName','pyArgIndex'), |
|
) |
|
def __init__( self, arrayName='pointer', arrayType=None ): |
|
self.arrayName = arrayName |
|
self.arrayType = arrayType |
|
def __call__( self, pyArgs, index, wrappedOperation ): |
|
"""Get the arg as an array of the appropriate type""" |
|
return self.arrayType.arraySize( pyArgs[self.arrayIndex ] ) |
|
else: |
|
returnPointer = returnPyArgumentIndex( 0 ) |
|
|
|
if not _configflags.ERROR_ON_COPY: |
|
def asArrayType( typ, size=None ): |
|
"""Create PyConverter to get first argument as array of type""" |
|
return converters.CallFuncPyConverter( typ.asArray ) |
|
else: |
|
def asArrayType( typ, size=None ): |
|
"""No converter required""" |
|
return None |
|
|
|
if not _configflags.ARRAY_SIZE_CHECKING: |
|
asArrayTypeSize = asArrayType |
|
else: |
|
if AsArrayTypedSizeChecked: |
|
asArrayTypeSize = AsArrayTypedSizeChecked |
|
else: |
|
def asArrayTypeSize( typ, size ): |
|
"""Create PyConverter function to get array as type and check size |
|
|
|
Produces a raw function, not a PyConverter instance |
|
""" |
|
asArray = typ.asArray |
|
dataType = typ.typeConstant |
|
arraySize = typ.arraySize |
|
expectedBytes = ctypes.sizeof( typ.baseType ) * size |
|
def asArraySize( incoming, function, args ): |
|
handler = typ.getHandler( incoming ) |
|
result = handler.asArray( incoming, dataType ) |
|
|
|
byteSize = handler.arrayByteCount( result ) |
|
if byteSize != expectedBytes: |
|
raise ValueError( |
|
"""Expected %r byte array, got %r byte array"""%( |
|
expectedBytes, |
|
byteSize, |
|
), |
|
incoming, |
|
) |
|
return result |
|
return asArraySize |
|
|
|
|
|
if not _configflags.ERROR_ON_COPY: |
|
def asVoidArray( ): |
|
"""Create PyConverter returning incoming as an array of any type""" |
|
from OpenGL.arrays import ArrayDatatype |
|
return converters.CallFuncPyConverter( ArrayDatatype.asArray ) |
|
else: |
|
def asVoidArray( ): |
|
"""If there's no copying allowed, we can use default passing""" |
|
return None |
|
|
|
class storePointerType( object ): |
|
"""Store named pointer value in context indexed by constant |
|
|
|
pointerName -- named pointer argument |
|
constant -- constant used to index in the context storage |
|
|
|
Note: OpenGL.STORE_POINTERS can be set with ERROR_ON_COPY |
|
to ignore this storage operation. |
|
|
|
Stores the pyArgs (i.e. result of pyConverters) for the named |
|
pointer argument... |
|
""" |
|
def __init__( self, pointerName, constant ): |
|
self.pointerName = pointerName |
|
self.constant = constant |
|
def finalise( self, wrapper ): |
|
self.pointerIndex = wrapper.pyArgIndex( self.pointerName ) |
|
def __call__( self, result, baseOperation, pyArgs, cArgs ): |
|
contextdata.setValue( self.constant, pyArgs[self.pointerIndex] ) |
|
|
|
|
|
def setInputArraySizeType( baseOperation, size, type, argName=0 ): |
|
"""Decorate function with vector-handling code for a single argument |
|
|
|
if OpenGL.ERROR_ON_COPY is False, then we return the |
|
named argument, converting to the passed array type, |
|
optionally checking that the array matches size. |
|
|
|
if OpenGL.ERROR_ON_COPY is True, then we will dramatically |
|
simplify this function, only wrapping if size is True, i.e. |
|
only wrapping if we intend to do a size check on the array. |
|
""" |
|
from OpenGL import wrapper |
|
return wrapper.wrapper( baseOperation ).setInputArraySize( argName, size ) |
|
|
|
def arraySizeOfFirstType( typ, default ): |
|
unitSize = typ.unitSize |
|
def arraySizeOfFirst( pyArgs, index, baseOperation ): |
|
"""Return the array size of the first argument""" |
|
array = pyArgs[0] |
|
if array is None: |
|
return default |
|
else: |
|
return unitSize( array ) |
|
return arraySizeOfFirst |
|
|