[Bf-blender-cvs] [1b42fe4fa4e] pygpu_extensions: GPU Python: Implement new object type 'gpu.types.GPUTexture'
Germano Cavalcante
noreply at git.blender.org
Thu Feb 11 19:03:05 CET 2021
Commit: 1b42fe4fa4e10c1b4613fc859035b9d9e86944da
Author: Germano Cavalcante
Date: Thu Feb 11 14:14:35 2021 -0300
Branches: pygpu_extensions
https://developer.blender.org/rB1b42fe4fa4e10c1b4613fc859035b9d9e86944da
GPU Python: Implement new object type 'gpu.types.GPUTexture'
This object allows you to do some simple operations with Textures on the GPU.
Can also be used for `gpu.types.GPUShader`.
It will be important to implement `gpu.types.GPUFramebuffer`.
The API of this object includes:
```
>>> gpu.types.GPUTexture.
clear(
free(
height
read(
width
```
===================================================================
M source/blender/python/gpu/CMakeLists.txt
A source/blender/python/gpu/gpu_py.c
A source/blender/python/gpu/gpu_py.h
A source/blender/python/gpu/gpu_py_buffer.c
A source/blender/python/gpu/gpu_py_buffer.h
M source/blender/python/gpu/gpu_py_shader.c
A source/blender/python/gpu/gpu_py_texture.c
A source/blender/python/gpu/gpu_py_texture.h
M source/blender/python/gpu/gpu_py_types.c
M source/blender/python/gpu/gpu_py_types.h
===================================================================
diff --git a/source/blender/python/gpu/CMakeLists.txt b/source/blender/python/gpu/CMakeLists.txt
index 19a3a32a186..010c0c8441e 100644
--- a/source/blender/python/gpu/CMakeLists.txt
+++ b/source/blender/python/gpu/CMakeLists.txt
@@ -33,26 +33,32 @@ set(INC_SYS
)
set(SRC
+ gpu_py.c
gpu_py_api.c
gpu_py_batch.c
+ gpu_py_buffer.c
gpu_py_element.c
gpu_py_matrix.c
gpu_py_offscreen.c
gpu_py_select.c
gpu_py_shader.c
gpu_py_state.c
+ gpu_py_texture.c
gpu_py_types.c
gpu_py_vertex_buffer.c
gpu_py_vertex_format.c
+ gpu_py.h
gpu_py_api.h
gpu_py_batch.h
+ gpu_py_buffer.h
gpu_py_element.h
gpu_py_matrix.h
gpu_py_offscreen.h
gpu_py_select.h
gpu_py_shader.h
gpu_py_state.h
+ gpu_py_texture.h
gpu_py_types.h
gpu_py_vertex_buffer.h
gpu_py_vertex_format.h
diff --git a/source/blender/python/gpu/gpu_py_types.h b/source/blender/python/gpu/gpu_py.c
similarity index 54%
copy from source/blender/python/gpu/gpu_py_types.h
copy to source/blender/python/gpu/gpu_py.c
index cf8d6d694e6..17dc8b89fdf 100644
--- a/source/blender/python/gpu/gpu_py_types.h
+++ b/source/blender/python/gpu/gpu_py.c
@@ -16,15 +16,30 @@
/** \file
* \ingroup bpygpu
+ *
+ * - Use ``bpygpu_`` for local API.
+ * - Use ``BPyGPU`` for public API.
*/
-#pragma once
+#include <Python.h>
+
+#include "GPU_texture.h"
+
+#include "../generic/py_capi_utils.h"
+
+#include "gpu_py.h" /* own include */
-#include "gpu_py_batch.h"
-#include "gpu_py_element.h"
-#include "gpu_py_offscreen.h"
-#include "gpu_py_shader.h"
-#include "gpu_py_vertex_buffer.h"
-#include "gpu_py_vertex_format.h"
+/* -------------------------------------------------------------------- */
+/** \name GPU Module
+ * \{ */
-PyObject *bpygpu_types_init(void);
+struct PyC_StringEnumItems bpygpu_dataformat_items[] = {
+ {GPU_DATA_FLOAT, "FLOAT"},
+ {GPU_DATA_INT, "INT"},
+ {GPU_DATA_UNSIGNED_INT, "UNSIGNED_INT"},
+ {GPU_DATA_UNSIGNED_BYTE, "UNSIGNED_BYTE"},
+ {GPU_DATA_UNSIGNED_INT_24_8, "UNSIGNED_INT_24_8"},
+ {GPU_DATA_10_11_11_REV, "10_11_11_REV"},
+ {0, NULL},
+};
+/** \} */
diff --git a/source/blender/python/gpu/gpu_py_types.h b/source/blender/python/gpu/gpu_py.h
similarity index 78%
copy from source/blender/python/gpu/gpu_py_types.h
copy to source/blender/python/gpu/gpu_py.h
index cf8d6d694e6..8a96391664f 100644
--- a/source/blender/python/gpu/gpu_py_types.h
+++ b/source/blender/python/gpu/gpu_py.h
@@ -20,11 +20,4 @@
#pragma once
-#include "gpu_py_batch.h"
-#include "gpu_py_element.h"
-#include "gpu_py_offscreen.h"
-#include "gpu_py_shader.h"
-#include "gpu_py_vertex_buffer.h"
-#include "gpu_py_vertex_format.h"
-
-PyObject *bpygpu_types_init(void);
+extern struct PyC_StringEnumItems bpygpu_dataformat_items[];
diff --git a/source/blender/python/gpu/gpu_py_buffer.c b/source/blender/python/gpu/gpu_py_buffer.c
new file mode 100644
index 00000000000..2055660ce8a
--- /dev/null
+++ b/source/blender/python/gpu/gpu_py_buffer.c
@@ -0,0 +1,591 @@
+/*
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+/** \file
+ * \ingroup bpygpu
+ *
+ * This file defines the gpu.state API.
+ *
+ * - Use ``bpygpu_`` for local API.
+ * - Use ``BPyGPU`` for public API.
+ */
+
+#include <Python.h>
+
+#include "BLI_utildefines.h"
+
+#include "MEM_guardedalloc.h"
+
+#include "GPU_texture.h"
+
+#include "../generic/py_capi_utils.h"
+
+#include "gpu_py.h"
+
+#include "gpu_py_buffer.h"
+
+/* -------------------------------------------------------------------- */
+/** \name Utility Functions
+ * \{ */
+
+static int py_buffer_format_size(eGPUDataFormat format)
+{
+ switch (format) {
+ case GPU_DATA_FLOAT:
+ return sizeof(float);
+ case GPU_DATA_INT:
+ return sizeof(int);
+ case GPU_DATA_UNSIGNED_BYTE:
+ return sizeof(char);
+ case GPU_DATA_UNSIGNED_INT:
+ case GPU_DATA_UNSIGNED_INT_24_8:
+ case GPU_DATA_10_11_11_REV:
+ return sizeof(uint);
+ default:
+ BLI_assert(!"Unhandled data format");
+ return -1;
+ }
+}
+
+static bool py_buffer_dimensions_compare(int ndim, const int *dim1, const Py_ssize_t *dim2)
+{
+ for (int i = 0; i < ndim; i++) {
+ if (dim1[i] != dim2[i]) {
+ return false;
+ }
+ }
+ return true;
+}
+
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name PyBuffer API
+ * \{ */
+
+static PyBuffer *py_buffer_make_from_data(
+ PyObject *parent, eGPUDataFormat format, int ndimensions, int *dimensions, void *buf)
+{
+ PyBuffer *buffer = (PyBuffer *)PyObject_NEW(PyBuffer, &BPyGPU_BufferType);
+
+ Py_XINCREF(parent);
+ buffer->parent = parent;
+ buffer->ndimensions = ndimensions;
+ buffer->dimensions = MEM_mallocN(ndimensions * sizeof(int), "PyBuffer dimensions");
+ memcpy(buffer->dimensions, dimensions, ndimensions * sizeof(int));
+ buffer->format = format;
+ buffer->buf.asvoid = buf;
+
+ return buffer;
+}
+
+static PyObject *py_buffer_sq_item(PyBuffer *self, int i)
+{
+ if (i >= self->dimensions[0] || i < 0) {
+ PyErr_SetString(PyExc_IndexError, "array index out of range");
+ return NULL;
+ }
+
+ if (self->ndimensions == 1) {
+ switch (self->format) {
+ case GPU_DATA_FLOAT:
+ return Py_BuildValue("f", self->buf.asfloat[i]);
+ case GPU_DATA_INT:
+ return Py_BuildValue("i", self->buf.asint[i]);
+ case GPU_DATA_UNSIGNED_BYTE:
+ return Py_BuildValue("B", self->buf.asbyte[i]);
+ case GPU_DATA_UNSIGNED_INT:
+ case GPU_DATA_UNSIGNED_INT_24_8:
+ case GPU_DATA_10_11_11_REV:
+ return Py_BuildValue("I", self->buf.asuint[i]);
+ }
+ }
+ else {
+ int offset = i * py_buffer_format_size(self->format);
+ for (int j = 1; j < self->ndimensions; j++) {
+ offset *= self->dimensions[j];
+ }
+
+ return (PyObject *)py_buffer_make_from_data((PyObject *)self,
+ self->format,
+ self->ndimensions - 1,
+ self->dimensions + 1,
+ self->buf.asbyte + offset);
+ }
+
+ return NULL;
+}
+
+static PyObject *py_buffer_to_list(PyBuffer *self)
+{
+ int i, len = self->dimensions[0];
+ PyObject *list = PyList_New(len);
+
+ for (i = 0; i < len; i++) {
+ PyList_SET_ITEM(list, i, py_buffer_sq_item(self, i));
+ }
+
+ return list;
+}
+
+static PyObject *py_buffer_to_list_recursive(PyBuffer *self)
+{
+ PyObject *list;
+
+ if (self->ndimensions > 1) {
+ int i, len = self->dimensions[0];
+ list = PyList_New(len);
+
+ for (i = 0; i < len; i++) {
+ PyBuffer *sub = (PyBuffer *)py_buffer_sq_item(self, i);
+ PyList_SET_ITEM(list, i, py_buffer_to_list_recursive(sub));
+ Py_DECREF(sub);
+ }
+ }
+ else {
+ list = py_buffer_to_list(self);
+ }
+
+ return list;
+}
+
+static PyObject *py_buffer_dimensions(PyBuffer *self, void *UNUSED(arg))
+{
+ PyObject *list = PyList_New(self->ndimensions);
+ int i;
+
+ for (i = 0; i < self->ndimensions; i++) {
+ PyList_SET_ITEM(list, i, PyLong_FromLong(self->dimensions[i]));
+ }
+
+ return list;
+}
+
+static void py_buffer_tp_dealloc(PyBuffer *self)
+{
+ if (self->parent) {
+ Py_DECREF(self->parent);
+ }
+ else {
+ MEM_freeN(self->buf.asvoid);
+ }
+
+ MEM_freeN(self->dimensions);
+
+ PyObject_DEL(self);
+}
+
+static PyObject *py_buffer_tp_repr(PyBuffer *self)
+{
+ PyObject *repr;
+
+ PyObject *list = py_buffer_to_list_recursive(self);
+ const char *typestr = PyC_StringEnum_find_id(bpygpu_dataformat_items, self->format);
+
+ repr = PyUnicode_FromFormat("Buffer(%s, %R)", typestr, list);
+ Py_DECREF(list);
+
+ return repr;
+}
+
+static int py_buffer_sq_ass_item(PyBuffer *self, int i, PyObject *v);
+
+static int py_buffer_ass_slice(PyBuffer *self, int begin, int end, PyObject *seq)
+{
+ PyObject *item;
+ int count, err = 0;
+
+ if (begin < 0) {
+ begin = 0;
+ }
+ if (end > self->dimensions[0]) {
+ end = self->dimensions[0];
+ }
+ if (begin > end) {
+ begin = end;
+ }
+
+ if (!PySequence_Check(seq)) {
+ PyErr_Format(PyExc_TypeError,
+ "buffer[:] = value, invalid assignment. "
+ "Expected a sequence, not an %.200s type",
+ Py_TYPE(seq)->tp_name);
+ return -1;
+ }
+
+ /* re-use count var */
+ if ((count = PySequence_Size(seq)) != (end - begin)) {
+ PyErr_Format(PyExc_TypeError,
+ "buffer[:] = value, size mismatch in assignment. "
+ "Expected: %d (given: %d)",
+ count,
+ end - begin);
+ return -1;
+ }
+
+ for (count = begin; count < end; count++) {
+ item = PySequence_GetItem(seq, count - begin);
+ if (item) {
+ err = py_buffer_sq_ass_item(self, count, item);
+ Py_DECREF(item);
+ }
+ else {
+ err = -1;
+ }
+ if (err) {
+ break;
+ }
+ }
+ return err;
+}
+
+#define MAX_DIMENSIONS 256
+static PyObject *py_buffer_tp_new(PyTypeObject *UNUSED(type), PyObject *args, PyObject *kwds)
+{
+ PyObject *length_ob, *init = NULL;
+ PyBuffer *buffer = NULL;
+ int dimensions[MAX_DIMENSIONS];
+
+ Py_ssize_t i, ndimensions = 0;
+
+ if (kwds && PyDict_Size(kwds)) {
+ PyErr_SetString(PyExc_TypeError, "Buffer(): takes no keyword args");
+ return NULL;
+ }
+
+ const struct PyC_StringEnum pygpu_dataformat = {bpygpu_dataformat_items, GPU_DATA_FLOAT};
+ if (!PyArg_ParseTuple(
+ args, "O&O|O: Buffer", PyC_ParseStringEnum, &pygpu_dataformat, &length_ob, &init)) {
+ return NULL;
@@ Diff output truncated at 10240 characters. @@
More information about the Bf-blender-cvs
mailing list