bgl module: Interpret a buffer as a bgl.Buffer

Differential Revision: https://developer.blender.org/D2857
This commit is contained in:
Germano 2017-09-27 11:20:00 -03:00
parent 88520dd5b6
commit 2de5e14f53

@ -472,6 +472,34 @@ int BGL_typeSize(int type)
return -1;
}
static int gl_buffer_type_from_py_format_char(char format)
{
switch (format) {
case 'b':
return GL_BYTE;
case 'h':
case 'i':
return GL_SHORT;
case 'l':
return GL_INT;
case 'f':
return GL_FLOAT;
case 'd':
return GL_DOUBLE;
}
return -1; /* UNKNOWN */
}
static bool compare_dimensions(int ndim, int *dim1, Py_ssize_t *dim2)
{
for (int i = 0; i < ndim; i++) {
if (dim1[i] != dim2[i]) {
return false;
}
}
return true;
}
/** \} */
@ -630,6 +658,22 @@ PyTypeObject BGL_bufferType = {
NULL /*tp_del*/
};
static Buffer *BGL_MakeBuffer_FromData(PyObject *parent, int type, int ndimensions, int *dimensions, void *buf)
{
Buffer *buffer = (Buffer *)PyObject_NEW(Buffer, &BGL_bufferType);
Py_XINCREF(parent);
buffer->parent = parent;
buffer->ndimensions = ndimensions;
buffer->dimensions = MEM_mallocN(ndimensions * sizeof(int), "Buffer dimensions");
memcpy(buffer->dimensions, dimensions, ndimensions * sizeof(int));
buffer->type = type;
buffer->buf.asvoid = buf;
return buffer;
}
/**
* Create a buffer object
*
@ -641,30 +685,21 @@ Buffer *BGL_MakeBuffer(int type, int ndimensions, int *dimensions, void *initbuf
{
Buffer *buffer;
void *buf = NULL;
int i, size, length;
int i, size = BGL_typeSize(type);
length = 1;
for (i = 0; i < ndimensions; i++) {
length *= dimensions[i];
size *= dimensions[i];
}
size = BGL_typeSize(type);
buf = MEM_mallocN(size, "Buffer buffer");
buf = MEM_mallocN(length * size, "Buffer buffer");
buffer = (Buffer *)PyObject_NEW(Buffer, &BGL_bufferType);
buffer->parent = NULL;
buffer->ndimensions = ndimensions;
buffer->dimensions = MEM_mallocN(ndimensions * sizeof(int), "Buffer dimensions");
memcpy(buffer->dimensions, dimensions, ndimensions * sizeof(int));
buffer->type = type;
buffer->buf.asvoid = buf;
buffer = BGL_MakeBuffer_FromData(NULL, type, ndimensions, dimensions, buf);
if (initbuffer) {
memcpy(buffer->buf.asvoid, initbuffer, length * size);
memcpy(buffer->buf.asvoid, initbuffer, size);
}
else {
memset(buffer->buf.asvoid, 0, length * size);
memset(buffer->buf.asvoid, 0, size);
}
return buffer;
}
@ -674,7 +709,7 @@ Buffer *BGL_MakeBuffer(int type, int ndimensions, int *dimensions, void *initbuf
static PyObject *Buffer_new(PyTypeObject *UNUSED(type), PyObject *args, PyObject *kwds)
{
PyObject *length_ob = NULL, *init = NULL;
Buffer *buffer;
Buffer *buffer = NULL;
int dimensions[MAX_DIMENSIONS];
int type;
@ -739,9 +774,32 @@ static PyObject *Buffer_new(PyTypeObject *UNUSED(type), PyObject *args, PyObject
return NULL;
}
buffer = BGL_MakeBuffer(type, ndimensions, dimensions, NULL);
if (init && ndimensions) {
if (Buffer_ass_slice(buffer, 0, dimensions[0], init)) {
if (init && PyObject_CheckBuffer(init)) {
Py_buffer pybuffer;
if (PyObject_GetBuffer(init, &pybuffer, PyBUF_ND | PyBUF_FORMAT) == -1) {
/* PyObject_GetBuffer raise a PyExc_BufferError */
return NULL;
}
if (type != gl_buffer_type_from_py_format_char(*pybuffer.format)) {
PyErr_Format(PyExc_TypeError,
"`GL_TYPE` and `format` of object with buffer interface do not match");
}
else if (ndimensions != pybuffer.ndim ||
!compare_dimensions(ndimensions, dimensions, pybuffer.shape))
{
PyErr_Format(PyExc_TypeError, "array size does not match");
}
else {
buffer = BGL_MakeBuffer_FromData(init, type, pybuffer.ndim, dimensions, pybuffer.buf);
}
PyBuffer_Release(&pybuffer);
}
else {
buffer = BGL_MakeBuffer(type, ndimensions, dimensions, NULL);
if (init && Buffer_ass_slice(buffer, 0, dimensions[0], init)) {
Py_DECREF(buffer);
return NULL;
}
@ -774,27 +832,17 @@ static PyObject *Buffer_item(Buffer *self, int i)
}
}
else {
Buffer *newbuf;
int j, length, size;
int j, offset = i * BGL_typeSize(self->type);
length = 1;
for (j = 1; j < self->ndimensions; j++) {
length *= self->dimensions[j];
offset *= self->dimensions[j];
}
size = BGL_typeSize(self->type);
newbuf = (Buffer *)PyObject_NEW(Buffer, &BGL_bufferType);
Py_INCREF(self);
newbuf->parent = (PyObject *)self;
newbuf->ndimensions = self->ndimensions - 1;
newbuf->type = self->type;
newbuf->buf.asvoid = self->buf.asbyte + i * length * size;
newbuf->dimensions = MEM_mallocN(newbuf->ndimensions * sizeof(int), "Buffer dimensions");
memcpy(newbuf->dimensions, self->dimensions + 1, newbuf->ndimensions * sizeof(int));
return (PyObject *)newbuf;
return BGL_MakeBuffer_FromData(
self, self->type,
self->ndimensions - 1,
self->dimensions + 1,
self->buf.asbyte + offset);
}
return NULL;