Package glitter :: Package arrays :: Module basebuffer
[hide private]
[frames] | no frames]

Source Code for Module glitter.arrays.basebuffer

  1  """Base class for buffer objects. 
  2   
  3  @todo: Implement binding as separate object to allow binding buffers to 
  4  different targets. This problem is very similar to rebinding L{Sampler}s to 
  5  different units and should probably be handled in a similar way. 
  6  @todo: Implement slicing with C{glGetBufferSubData}. 
  7  @todo: Remember that C{glBindBuffer} and C{glBindBufferRange}/C{glBindBufferBase} interfer with each other! 
  8   
  9  @author: Stephan Wenger 
 10  @date: 2012-02-29 
 11   
 12  @todo: accept another buffer in constructor, copy _id, proxy shape etc., keep reference to other buffer, disable set_data and __del__ 
 13  """ 
 14   
 15  import numpy as _np 
 16   
 17  import glitter.raw as _gl 
 18  from glitter.utils import primitive_types, buffer_usages, Datatype, coerce_array, ManagedObject, BindableObject 
19 20 -class BaseBuffer(ManagedObject, BindableObject):
21 _generate_id = _gl.glGenBuffers 22 _delete_id = _gl.glDeleteBuffers 23 _db = "buffers" 24 25 drawmodes = primitive_types 26 usages = buffer_usages 27
28 - def __init__(self, data=None, shape=None, dtype=None, usage=None, context=None):
29 if any(x is NotImplemented for x in (self._target,)): 30 raise TypeError("%s is abstract" % self.__class__.__name__) 31 super(BaseBuffer, self).__init__(context=context) 32 if usage is None: 33 usage = BaseBuffer.usages.STATIC_DRAW 34 else: 35 usage = self.usages(usage) 36 self.set_data(data=data, shape=shape, dtype=dtype, usage=usage)
37
38 - def set_data(self, data=None, shape=None, dtype=None, usage=None):
39 if data is None: 40 if shape is None or dtype is None: 41 raise ValueError("must specify either data or both shape and dtype") 42 self._shape = shape 43 self._dtype = dtype.coerced(force_gl=True) 44 else: 45 data = coerce_array(data, dtype, force_gl=True) 46 if shape is not None: 47 data = data.reshape(shape) 48 self._shape = data.shape 49 self._dtype = Datatype.from_numpy(data.dtype) 50 51 if usage is None: 52 usage = self.usage 53 54 _nbytes = _np.prod(self._shape) * self._dtype.nbytes 55 _data = data.ctypes if data is not None else _gl.POINTER(_gl.GLvoid)() 56 with self: 57 _gl.glBufferData(self._target, _nbytes, _data, usage._value)
58
59 - def get_data(self):
60 _data = _np.empty(self.shape, dtype=self.dtype.as_numpy()) 61 with self: 62 _gl.glGetBufferSubData(self._target, 0, _data.nbytes, _data.ctypes) 63 return _data
64 65 @property
66 - def data(self):
67 return self.get_data()
68 69 @data.setter
70 - def data(self, data):
71 self.set_data(data)
72 73 @property
74 - def shape(self):
75 return self._shape
76
77 - def __len__(self):
78 return self.shape[0]
79 80 @property
81 - def dtype(self):
82 return self._dtype
83 84 @property
85 - def _size(self):
86 _size = _gl.GLint() 87 with self: 88 _gl.glGetBufferParameteriv(self._target, _gl.GL_BUFFER_SIZE, _gl.pointer(_size)) 89 return _size.value
90 91 @property
92 - def usage(self):
93 _usage = _gl.GLint() 94 with self: 95 _gl.glGetBufferParameteriv(self._target, _gl.GL_BUFFER_USAGE, _gl.pointer(_usage)) 96 return BaseBuffer.usages[_usage.value]
97 98 __all__ = ["BaseBuffer"] 99