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
|
#! /usr/bin/env python
"""Test for a buffer-protocol-based access mechanism
Will *only* work for Python 2.6+, and pretty much just works for strings
under 2.6 (in terms of the common object types).
"""
import ctypes,sys,operator,logging,traceback
from OpenGL.arrays import _buffers
from OpenGL.raw.GL import _types
from OpenGL.raw.GL.VERSION import GL_1_1
from OpenGL.arrays import formathandler
from OpenGL import _configflags
from OpenGL import acceleratesupport
_log = logging.getLogger( __name__ )
try:
reduce
except NameError as err:
from functools import reduce
MemoryviewHandler = BufferHandler = None
if sys.version_info[:2] > (2,6):
# Only Python 2.7+ has memoryview support, and the accelerate module
# requires memoryviews to be able to pass around the buffer structures
if acceleratesupport.ACCELERATE_AVAILABLE:
try:
from OpenGL_accelerate.buffers_formathandler import MemoryviewHandler
except ImportError as err:
traceback.print_exc()
_log.warn(
"Unable to load buffers_formathandler accelerator from OpenGL_accelerate"
)
else:
BufferHandler = MemoryviewHandler
if not BufferHandler:
class BufferHandler( formathandler.FormatHandler ):
"""Buffer-protocol data-type handler for OpenGL"""
isOutput=False
ERROR_ON_COPY = _configflags.ERROR_ON_COPY
if sys.version_info[:2] >= (3,0):
@classmethod
def from_param( cls, value, typeCode=None ):
if not isinstance( value, _buffers.Py_buffer ):
value = cls.asArray( value )
#raise TypeError( """Can't convert value to py-buffer in from_param""" )
return value
else:
# Not sure *why* 2.7 segfaults with the "use a buffer as the buffer"
# version above, but it works fine with the value.buf here
@classmethod
def from_param( cls, value, typeCode=None ):
if not isinstance( value, _buffers.Py_buffer ):
value = cls.asArray( value )
#raise TypeError( """Can't convert value to py-buffer in from_param""" )
return value.buf
def dataPointer( value ):
if not isinstance( value, _buffers.Py_buffer ):
value = _buffers.Py_buffer.from_object( value )
return value.buf
dataPointer = staticmethod( dataPointer )
@classmethod
def zeros( cls, dims, typeCode=None ):
"""Currently don't allow strings as output types!"""
raise NotImplementedError( "Generic buffer type does not have output capability" )
return cls.asArray( bytearray( b'\000'*reduce(operator.mul,dims)*BYTE_SIZES[typeCode] ) )
@classmethod
def ones( cls, dims, typeCode=None ):
"""Currently don't allow strings as output types!"""
raise NotImplementedError( """Have not implemented ones for buffer type""" )
@classmethod
def arrayToGLType( cls, value ):
"""Given a value, guess OpenGL type of the corresponding pointer"""
format = value.format
if format in ARRAY_TO_GL_TYPE_MAPPING:
return ARRAY_TO_GL_TYPE_MAPPING[format]
raise TypeError( 'Unknown format: %r'%(format,))
@classmethod
def arraySize( cls, value, typeCode = None ):
"""Given a data-value, calculate ravelled size for the array"""
return value.len // value.itemsize
@classmethod
def arrayByteCount( cls, value, typeCode = None ):
"""Given a data-value, calculate number of bytes required to represent"""
return value.len
@classmethod
def unitSize( cls, value, default=None ):
return value.dims[-1]
@classmethod
def asArray( cls, value, typeCode=None ):
"""Convert given value to an array value of given typeCode"""
buf = _buffers.Py_buffer.from_object( value )
return buf
@classmethod
def dimensions( cls, value, typeCode=None ):
"""Determine dimensions of the passed array value (if possible)"""
return value.dims
ARRAY_TO_GL_TYPE_MAPPING = _buffers.ARRAY_TO_GL_TYPE_MAPPING
BYTE_SIZES = _buffers.BYTE_SIZES
|