File: arrayhelpers.py

package info (click to toggle)
pyopengl 3.1.0%2Bdfsg-1
  • links: PTS, VCS
  • area: main
  • in suites: stretch
  • size: 11,184 kB
  • ctags: 21,473
  • sloc: python: 80,468; makefile: 4
file content (182 lines) | stat: -rw-r--r-- 7,250 bytes parent folder | download | duplicates (12)
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