| | """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 ) |
| | |
| | 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 |
| |
|