bgl module: Interpret a buffer as a bgl.Buffer

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

View File

@@ -472,6 +472,34 @@ int BGL_typeSize(int type)
return -1; 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*/ 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 * Create a buffer object
* *
@@ -641,30 +685,21 @@ Buffer *BGL_MakeBuffer(int type, int ndimensions, int *dimensions, void *initbuf
{ {
Buffer *buffer; Buffer *buffer;
void *buf = NULL; void *buf = NULL;
int i, size, length; int i, size = BGL_typeSize(type);
length = 1;
for (i = 0; i < ndimensions; i++) { 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 = BGL_MakeBuffer_FromData(NULL, type, ndimensions, dimensions, buf);
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;
if (initbuffer) { if (initbuffer) {
memcpy(buffer->buf.asvoid, initbuffer, length * size); memcpy(buffer->buf.asvoid, initbuffer, size);
} }
else { else {
memset(buffer->buf.asvoid, 0, length * size); memset(buffer->buf.asvoid, 0, size);
} }
return buffer; 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) static PyObject *Buffer_new(PyTypeObject *UNUSED(type), PyObject *args, PyObject *kwds)
{ {
PyObject *length_ob = NULL, *init = NULL; PyObject *length_ob = NULL, *init = NULL;
Buffer *buffer; Buffer *buffer = NULL;
int dimensions[MAX_DIMENSIONS]; int dimensions[MAX_DIMENSIONS];
int type; int type;
@@ -739,9 +774,32 @@ static PyObject *Buffer_new(PyTypeObject *UNUSED(type), PyObject *args, PyObject
return NULL; return NULL;
} }
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); buffer = BGL_MakeBuffer(type, ndimensions, dimensions, NULL);
if (init && ndimensions) { if (init && Buffer_ass_slice(buffer, 0, dimensions[0], init)) {
if (Buffer_ass_slice(buffer, 0, dimensions[0], init)) {
Py_DECREF(buffer); Py_DECREF(buffer);
return NULL; return NULL;
} }
@@ -774,27 +832,17 @@ static PyObject *Buffer_item(Buffer *self, int i)
} }
} }
else { else {
Buffer *newbuf; int j, offset = i * BGL_typeSize(self->type);
int j, length, size;
length = 1;
for (j = 1; j < self->ndimensions; j++) { 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); return BGL_MakeBuffer_FromData(
self, self->type,
Py_INCREF(self); self->ndimensions - 1,
newbuf->parent = (PyObject *)self; self->dimensions + 1,
self->buf.asbyte + offset);
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 NULL; return NULL;