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
|
"""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.warn(
"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 )
# check that the number of bytes expected is present...
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
|