[Bf-blender-cvs] [8037f3602f1] blender2.8: PyAPI: Add exceptions to stack push/pop

Campbell Barton noreply at git.blender.org
Sun Aug 20 09:23:41 CEST 2017


Commit: 8037f3602f12080a1692746e5ee0b6c46c7c3d76
Author: Campbell Barton
Date:   Sun Aug 20 17:23:49 2017 +1000
Branches: blender2.8
https://developer.blender.org/rB8037f3602f12080a1692746e5ee0b6c46c7c3d76

PyAPI: Add exceptions to stack push/pop

Raise exception when stack limits are reached.

===================================================================

M	source/blender/gpu/GPU_matrix.h
M	source/blender/gpu/intern/gpu_matrix.c
M	source/blender/python/intern/gpu_py_matrix.c

===================================================================

diff --git a/source/blender/gpu/GPU_matrix.h b/source/blender/gpu/GPU_matrix.h
index 219c7b1c6c1..4e136ed34b2 100644
--- a/source/blender/gpu/GPU_matrix.h
+++ b/source/blender/gpu/GPU_matrix.h
@@ -113,6 +113,16 @@ const float (*gpuGetNormalMatrixInverse(float m[3][3]))[3];
 void gpuBindMatrices(const Gwn_ShaderInterface*);
 bool gpuMatricesDirty(void); /* since last bind */
 
+
+/* Python API needs to be able to inspect the stack so errors raise exceptions instead of crashing. */
+#ifdef USE_GPU_PY_MATRIX_API
+int GPU_matrix_stack_level_get_model_view(void);
+int GPU_matrix_stack_level_get_projection(void);
+/* static assert ensures this doesn't change! */
+#define GPU_PY_MATRIX_STACK_LEN 31
+#endif  /* USE_GPU_PY_MATRIX_API */
+
+
 #ifdef __cplusplus
 }
 #endif
diff --git a/source/blender/gpu/intern/gpu_matrix.c b/source/blender/gpu/intern/gpu_matrix.c
index f03a076a9fd..7f024a18ba7 100644
--- a/source/blender/gpu/intern/gpu_matrix.c
+++ b/source/blender/gpu/intern/gpu_matrix.c
@@ -30,7 +30,9 @@
  */
 
 #define SUPPRESS_GENERIC_MATRIX_API
+#define USE_GPU_PY_MATRIX_API  /* only so values are declared */
 #include "GPU_matrix.h"
+#undef USE_GPU_PY_MATRIX_API
 
 #include "BLI_math_matrix.h"
 #include "BLI_math_rotation.h"
@@ -622,3 +624,24 @@ bool gpuMatricesDirty(void)
 {
 	return state.dirty;
 }
+
+
+/* -------------------------------------------------------------------- */
+
+/** \name Python API Helpers
+ * \{ */
+BLI_STATIC_ASSERT(GPU_PY_MATRIX_STACK_LEN + 1 == MATRIX_STACK_DEPTH, "define mismatch");
+
+/* Return int since caller is may subtract. */
+
+int GPU_matrix_stack_level_get_model_view(void)
+{
+	return (int)state.model_view_stack.top;
+}
+
+int GPU_matrix_stack_level_get_projection(void)
+{
+	return (int)state.projection_stack.top;
+}
+
+/** \} */
diff --git a/source/blender/python/intern/gpu_py_matrix.c b/source/blender/python/intern/gpu_py_matrix.c
index 74d49a771c5..ab40e4b9110 100644
--- a/source/blender/python/intern/gpu_py_matrix.c
+++ b/source/blender/python/intern/gpu_py_matrix.c
@@ -22,6 +22,9 @@
  *  \ingroup pythonintern
  *
  * This file defines the gpu.matrix stack API.
+ *
+ * \warning While these functions attempt to ensure correct stack usage.
+ * Mixing Python and C functions may still crash on invalid use.
  */
 
 #include <Python.h>
@@ -35,7 +38,9 @@
 
 #include "gpu.h"
 
+#define USE_GPU_PY_MATRIX_API
 #include "GPU_matrix.h"
+#undef USE_GPU_PY_MATRIX_API
 
 /* -------------------------------------------------------------------- */
 
@@ -45,10 +50,15 @@
 PyDoc_STRVAR(pygpu_matrix_push_doc,
 "push()\n"
 "\n"
-"   Add to the matrix stack.\n"
+"   Add to the model-view matrix stack.\n"
 );
 static PyObject *pygpu_matrix_push(PyObject *UNUSED(self))
 {
+	if (GPU_matrix_stack_level_get_model_view() >= GPU_PY_MATRIX_STACK_LEN) {
+		PyErr_SetString(PyExc_RuntimeError,
+		                "Maximum model-view stack depth " STRINGIFY(GPU_PY_MATRIX_STACK_DEPTH) " reached");
+		return NULL;
+	}
 	gpuPushMatrix();
 	Py_RETURN_NONE;
 }
@@ -56,10 +66,15 @@ static PyObject *pygpu_matrix_push(PyObject *UNUSED(self))
 PyDoc_STRVAR(pygpu_matrix_pop_doc,
 "pop()\n"
 "\n"
-"   Remove the last matrix from the stack.\n"
+"   Remove the last model-view matrix from the stack.\n"
 );
 static PyObject *pygpu_matrix_pop(PyObject *UNUSED(self))
 {
+	if (GPU_matrix_stack_level_get_model_view() == 0) {
+		PyErr_SetString(PyExc_RuntimeError,
+		                "Minimum model-view stack depth reached");
+		return NULL;
+	}
 	gpuPopMatrix();
 	Py_RETURN_NONE;
 }
@@ -71,7 +86,13 @@ PyDoc_STRVAR(pygpu_matrix_push_projection_doc,
 );
 static PyObject *pygpu_matrix_push_projection(PyObject *UNUSED(self))
 {
-	gpuPushMatrix();
+	if (GPU_matrix_stack_level_get_projection() >= GPU_PY_MATRIX_STACK_LEN) {
+		PyErr_SetString(PyExc_RuntimeError,
+		                "Maximum projection stack depth " STRINGIFY(GPU_PY_MATRIX_STACK_DEPTH) " reached");
+		return NULL;
+	}
+
+	gpuPushProjectionMatrix();
 	Py_RETURN_NONE;
 }
 
@@ -82,7 +103,12 @@ PyDoc_STRVAR(pygpu_matrix_pop_projection_doc,
 );
 static PyObject *pygpu_matrix_pop_projection(PyObject *UNUSED(self))
 {
-	gpuPopMatrix();
+	if (GPU_matrix_stack_level_get_projection() == 0) {
+		PyErr_SetString(PyExc_RuntimeError,
+		                "Minimum projection stack depth reached");
+		return NULL;
+	}
+	gpuPopProjectionMatrix();
 	Py_RETURN_NONE;
 }
 
@@ -289,8 +315,10 @@ static PyObject *pygpu_matrix_get_normal_matrix(PyObject *UNUSED(self))
 
 static struct PyMethodDef BPy_GPU_matrix_methods[] = {
 	/* Manage Stack */
-	{"push", (PyCFunction)pygpu_matrix_push, METH_NOARGS, pygpu_matrix_push_doc},
-	{"pop", (PyCFunction)pygpu_matrix_pop, METH_NOARGS, pygpu_matrix_pop_doc},
+	{"push", (PyCFunction)pygpu_matrix_push,
+	 METH_NOARGS, pygpu_matrix_push_doc},
+	{"pop", (PyCFunction)pygpu_matrix_pop,
+	 METH_NOARGS, pygpu_matrix_pop_doc},
 
 	{"push_projection", (PyCFunction)pygpu_matrix_push_projection,
 	 METH_NOARGS, pygpu_matrix_push_projection_doc},



More information about the Bf-blender-cvs mailing list