[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