From da9f586748f84708feda22ec7e71c4929c371867 Mon Sep 17 00:00:00 2001 From: Brecht Van Lommel Date: Wed, 19 Jun 2024 17:54:35 +0200 Subject: [PATCH] Fix #104061: Python GPU module unusable after too early import Add-ons may attempt to load the GPU module in background mode when no GPU context has been initialized yet. This would give an error on import. If then later the GPU context does get initialized, for example for a render engine, import would still fail as the module is cached. This reverts commit d7f124f06f3fda59523ed05f12d1f4af6a523ba6, and again throws errors in methods and constructors instead of module import. Pull Request: https://projects.blender.org/blender/blender/pulls/123395 --- source/blender/python/gpu/gpu_py.cc | 68 ++----------------- source/blender/python/gpu/gpu_py.hh | 14 +++- source/blender/python/gpu/gpu_py_api.cc | 3 +- source/blender/python/gpu/gpu_py_batch.cc | 3 +- source/blender/python/gpu/gpu_py_buffer.cc | 2 + source/blender/python/gpu/gpu_py_buffer.hh | 2 + .../blender/python/gpu/gpu_py_capabilities.cc | 40 ++++++++++- source/blender/python/gpu/gpu_py_compute.cc | 4 +- source/blender/python/gpu/gpu_py_element.cc | 2 + .../blender/python/gpu/gpu_py_framebuffer.cc | 2 + source/blender/python/gpu/gpu_py_matrix.cc | 38 ++++++++++- source/blender/python/gpu/gpu_py_offscreen.cc | 7 ++ source/blender/python/gpu/gpu_py_platform.cc | 12 +++- source/blender/python/gpu/gpu_py_select.cc | 4 +- source/blender/python/gpu/gpu_py_shader.cc | 8 ++- .../python/gpu/gpu_py_shader_create_info.cc | 1 + source/blender/python/gpu/gpu_py_state.cc | 42 +++++++++++- source/blender/python/gpu/gpu_py_texture.cc | 4 +- source/blender/python/gpu/gpu_py_types.cc | 27 ++++---- .../python/gpu/gpu_py_uniformbuffer.cc | 3 + .../python/gpu/gpu_py_vertex_buffer.cc | 3 + .../python/gpu/gpu_py_vertex_format.cc | 3 + 22 files changed, 202 insertions(+), 90 deletions(-) diff --git a/source/blender/python/gpu/gpu_py.cc b/source/blender/python/gpu/gpu_py.cc index 837a2083ee9..4e7c43f4f97 100644 --- a/source/blender/python/gpu/gpu_py.cc +++ b/source/blender/python/gpu/gpu_py.cc @@ -53,72 +53,16 @@ PyC_StringEnumItems bpygpu_dataformat_items[] = { /** \name Utilities * \{ */ -static const char g_error[] = "GPU API is not available in background mode"; - -static PyObject *py_error__ml_meth(PyObject * /*self*/, PyObject * /*args*/) -{ - PyErr_SetString(PyExc_SystemError, g_error); - return nullptr; -} - -static PyObject *py_error__getter(PyObject * /*self*/, void * /*type*/) -{ - PyErr_SetString(PyExc_SystemError, g_error); - return nullptr; -} - -static int py_error__setter(PyObject * /*self*/, PyObject * /*value*/, void * /*type*/) -{ - PyErr_SetString(PyExc_SystemError, g_error); - return -1; -} - -static PyObject *py_error__tp_new(PyTypeObject * /*type*/, - PyObject * /*args*/, - PyObject * /*kwds*/) -{ - PyErr_SetString(PyExc_SystemError, g_error); - return nullptr; -} - -PyObject *bpygpu_create_module(PyModuleDef *module_type) -{ - if (!GPU_is_init() && module_type->m_methods) { - /* Replace all methods with an error method. - * That way when the method is called, an error will appear instead. */ - for (PyMethodDef *meth = module_type->m_methods; meth->ml_name; meth++) { - meth->ml_meth = py_error__ml_meth; - } - } - - PyObject *module = PyModule_Create(module_type); - - return module; -} - -int bpygpu_finalize_type(PyTypeObject *py_type) +bool bpygpu_is_init_or_error(void) { if (!GPU_is_init()) { - if (py_type->tp_methods) { - /* Replace all methods with an error method. */ - for (PyMethodDef *meth = py_type->tp_methods; meth->ml_name; meth++) { - meth->ml_meth = py_error__ml_meth; - } - } - if (py_type->tp_getset) { - /* Replace all getters and setter with a functions that always returns error. */ - for (PyGetSetDef *getset = py_type->tp_getset; getset->name; getset++) { - getset->get = py_error__getter; - getset->set = py_error__setter; - } - } - if (py_type->tp_new) { - /* If initialized, return error. */ - py_type->tp_new = py_error__tp_new; - } + PyErr_SetString(PyExc_SystemError, + "GPU functions for drawing are not available in background mode"); + + return false; } - return PyType_Ready(py_type); + return true; } /** \} */ diff --git a/source/blender/python/gpu/gpu_py.hh b/source/blender/python/gpu/gpu_py.hh index 2ca31b5c5d9..51ad52d6049 100644 --- a/source/blender/python/gpu/gpu_py.hh +++ b/source/blender/python/gpu/gpu_py.hh @@ -13,5 +13,15 @@ extern struct PyC_StringEnumItems bpygpu_primtype_items[]; extern struct PyC_StringEnumItems bpygpu_dataformat_items[]; -PyObject *bpygpu_create_module(PyModuleDef *module_type); -int bpygpu_finalize_type(PyTypeObject *py_type); +bool bpygpu_is_init_or_error(void); + +#define BPYGPU_IS_INIT_OR_ERROR_OBJ \ + if (UNLIKELY(!bpygpu_is_init_or_error())) { \ + return NULL; \ + } \ + ((void)0) +#define BPYGPU_IS_INIT_OR_ERROR_INT \ + if (UNLIKELY(!bpygpu_is_init_or_error())) { \ + return -1; \ + } \ + ((void)0) diff --git a/source/blender/python/gpu/gpu_py_api.cc b/source/blender/python/gpu/gpu_py_api.cc index 1f7f76ef237..cd7fdc9089a 100644 --- a/source/blender/python/gpu/gpu_py_api.cc +++ b/source/blender/python/gpu/gpu_py_api.cc @@ -24,7 +24,6 @@ #include "gpu_py_state.hh" #include "gpu_py_types.hh" -#include "gpu_py.hh" #include "gpu_py_api.hh" /* Own include. */ /* -------------------------------------------------------------------- */ @@ -54,7 +53,7 @@ PyObject *BPyInit_gpu() PyObject *submodule; PyObject *mod; - mod = bpygpu_create_module(&pygpu_module_def); + mod = PyModule_Create(&pygpu_module_def); PyModule_AddObject(mod, "types", (submodule = bpygpu_types_init())); PyDict_SetItem(sys_modules, PyModule_GetNameObject(submodule), submodule); diff --git a/source/blender/python/gpu/gpu_py_batch.cc b/source/blender/python/gpu/gpu_py_batch.cc index 78f3c3ed484..a5fee03817e 100644 --- a/source/blender/python/gpu/gpu_py_batch.cc +++ b/source/blender/python/gpu/gpu_py_batch.cc @@ -49,6 +49,8 @@ static bool pygpu_batch_is_program_or_error(BPyGPUBatch *self) static PyObject *pygpu_batch__tp_new(PyTypeObject * /*type*/, PyObject *args, PyObject *kwds) { + BPYGPU_IS_INIT_OR_ERROR_OBJ; + const char *exc_str_missing_arg = "GPUBatch.__new__() missing required argument '%s' (pos %d)"; PyC_StringEnum prim_type = {bpygpu_primtype_items, GPU_PRIM_NONE}; @@ -181,7 +183,6 @@ PyDoc_STRVAR( " :type program: :class:`gpu.types.GPUShader`\n"); static PyObject *pygpu_batch_program_set(BPyGPUBatch *self, BPyGPUShader *py_shader) { - static bool deprecation_warning_issued = false; /* Deprecation warning raised when calling `gpu.types.GPUBatch.program_set`. */ diff --git a/source/blender/python/gpu/gpu_py_buffer.cc b/source/blender/python/gpu/gpu_py_buffer.cc index d6393f1a56a..e1d4ca3a23e 100644 --- a/source/blender/python/gpu/gpu_py_buffer.cc +++ b/source/blender/python/gpu/gpu_py_buffer.cc @@ -373,6 +373,8 @@ static int pygpu_buffer_ass_slice(BPyGPUBuffer *self, static PyObject *pygpu_buffer__tp_new(PyTypeObject * /*type*/, PyObject *args, PyObject *kwds) { + BPYGPU_IS_INIT_OR_ERROR_OBJ; + PyObject *length_ob, *init = nullptr; BPyGPUBuffer *buffer = nullptr; Py_ssize_t shape[MAX_DIMENSIONS]; diff --git a/source/blender/python/gpu/gpu_py_buffer.hh b/source/blender/python/gpu/gpu_py_buffer.hh index ef7b9fee7dc..0b0741c9703 100644 --- a/source/blender/python/gpu/gpu_py_buffer.hh +++ b/source/blender/python/gpu/gpu_py_buffer.hh @@ -8,6 +8,8 @@ #pragma once +#include "BLI_sys_types.h" + extern PyTypeObject BPyGPU_BufferType; #define BPyGPU_Buffer_Check(v) (Py_TYPE(v) == &BPyGPU_BufferType) diff --git a/source/blender/python/gpu/gpu_py_capabilities.cc b/source/blender/python/gpu/gpu_py_capabilities.cc index 3184e6a3993..61a2396d955 100644 --- a/source/blender/python/gpu/gpu_py_capabilities.cc +++ b/source/blender/python/gpu/gpu_py_capabilities.cc @@ -33,6 +33,8 @@ PyDoc_STRVAR( " :rtype: int\n"); static PyObject *pygpu_max_texture_size_get(PyObject * /*self*/) { + BPYGPU_IS_INIT_OR_ERROR_OBJ; + return PyLong_FromLong(GPU_max_texture_size()); } @@ -47,6 +49,8 @@ PyDoc_STRVAR( " :rtype: int\n"); static PyObject *pygpu_max_texture_layers_get(PyObject * /*self*/) { + BPYGPU_IS_INIT_OR_ERROR_OBJ; + return PyLong_FromLong(GPU_max_texture_layers()); } @@ -63,6 +67,8 @@ PyDoc_STRVAR( " :rtype: int\n"); static PyObject *pygpu_max_textures_get(PyObject * /*self*/) { + BPYGPU_IS_INIT_OR_ERROR_OBJ; + return PyLong_FromLong(GPU_max_textures()); } @@ -78,6 +84,8 @@ PyDoc_STRVAR( " :rtype: int\n"); static PyObject *pygpu_max_textures_vert_get(PyObject * /*self*/) { + BPYGPU_IS_INIT_OR_ERROR_OBJ; + return PyLong_FromLong(GPU_max_textures_vert()); } @@ -93,6 +101,8 @@ PyDoc_STRVAR( " :rtype: int\n"); static PyObject *pygpu_max_textures_geom_get(PyObject * /*self*/) { + BPYGPU_IS_INIT_OR_ERROR_OBJ; + return PyLong_FromLong(GPU_max_textures_geom()); } @@ -108,6 +118,8 @@ PyDoc_STRVAR( " :rtype: int\n"); static PyObject *pygpu_max_textures_frag_get(PyObject * /*self*/) { + BPYGPU_IS_INIT_OR_ERROR_OBJ; + return PyLong_FromLong(GPU_max_textures_frag()); } @@ -122,6 +134,8 @@ PyDoc_STRVAR( " :rtype: int\n"); static PyObject *pygpu_max_images_get(PyObject * /*self*/) { + BPYGPU_IS_INIT_OR_ERROR_OBJ; + return PyLong_FromLong(GPU_max_images()); } @@ -137,6 +151,8 @@ PyDoc_STRVAR( " :rtype: int\n"); static PyObject *pygpu_max_uniforms_vert_get(PyObject * /*self*/) { + BPYGPU_IS_INIT_OR_ERROR_OBJ; + return PyLong_FromLong(GPU_max_uniforms_vert()); } @@ -152,6 +168,8 @@ PyDoc_STRVAR( " :rtype: int\n"); static PyObject *pygpu_max_uniforms_frag_get(PyObject * /*self*/) { + BPYGPU_IS_INIT_OR_ERROR_OBJ; + return PyLong_FromLong(GPU_max_uniforms_frag()); } @@ -166,6 +184,8 @@ PyDoc_STRVAR( " :rtype: int\n"); static PyObject *pygpu_max_batch_indices_get(PyObject * /*self*/) { + BPYGPU_IS_INIT_OR_ERROR_OBJ; + return PyLong_FromLong(GPU_max_batch_indices()); } @@ -180,6 +200,8 @@ PyDoc_STRVAR( " :rtype: int\n"); static PyObject *pygpu_max_batch_vertices_get(PyObject * /*self*/) { + BPYGPU_IS_INIT_OR_ERROR_OBJ; + return PyLong_FromLong(GPU_max_batch_vertices()); } @@ -195,6 +217,8 @@ PyDoc_STRVAR( " :rtype: int\n"); static PyObject *pygpu_max_vertex_attribs_get(PyObject * /*self*/) { + BPYGPU_IS_INIT_OR_ERROR_OBJ; + return PyLong_FromLong(GPU_max_vertex_attribs()); } @@ -210,6 +234,8 @@ PyDoc_STRVAR( " :rtype: int\n"); static PyObject *pygpu_max_varying_floats_get(PyObject * /*self*/) { + BPYGPU_IS_INIT_OR_ERROR_OBJ; + return PyLong_FromLong(GPU_max_varying_floats()); } @@ -224,6 +250,8 @@ PyDoc_STRVAR( " :rtype: tuple of string\n"); static PyObject *pygpu_extensions_get(PyObject * /*self*/) { + BPYGPU_IS_INIT_OR_ERROR_OBJ; + int extensions_len = GPU_extensions_len(); PyObject *ret = PyTuple_New(extensions_len); PyObject **ob_items = ((PyTupleObject *)ret)->ob_item; @@ -245,6 +273,8 @@ PyDoc_STRVAR( " :rtype: bool\n"); static PyObject *pygpu_compute_shader_support_get(PyObject * /*self*/) { + BPYGPU_IS_INIT_OR_ERROR_OBJ; + static bool deprecation_warning_issued = false; if (!deprecation_warning_issued) { PyErr_WarnEx(PyExc_DeprecationWarning, @@ -268,6 +298,8 @@ PyDoc_STRVAR( " :rtype: bool\n"); static PyObject *pygpu_shader_image_load_store_support_get(PyObject * /*self*/) { + BPYGPU_IS_INIT_OR_ERROR_OBJ; + static bool deprecation_warning_issued = false; if (!deprecation_warning_issued) { PyErr_WarnEx( @@ -292,6 +324,8 @@ PyDoc_STRVAR( " :rtype: bool\n"); static PyObject *pygpu_hdr_support_get(PyObject * /*self*/) { + BPYGPU_IS_INIT_OR_ERROR_OBJ; + return PyBool_FromLong(GPU_hdr_support()); } @@ -308,6 +342,8 @@ PyDoc_STRVAR( " :rtype: int\n"); static PyObject *pygpu_max_work_group_count_get(PyObject * /*self*/, PyObject *args) { + BPYGPU_IS_INIT_OR_ERROR_OBJ; + int index; if (!PyArg_ParseTuple(args, "i", &index)) { return nullptr; @@ -331,6 +367,8 @@ PyDoc_STRVAR( " :rtype: int\n"); static PyObject *pygpu_max_work_group_size_get(PyObject * /*self*/, PyObject *args) { + BPYGPU_IS_INIT_OR_ERROR_OBJ; + int index; if (!PyArg_ParseTuple(args, "i", &index)) { return nullptr; @@ -455,7 +493,7 @@ PyObject *bpygpu_capabilities_init() { PyObject *submodule; - submodule = bpygpu_create_module(&pygpu_capabilities_module_def); + submodule = PyModule_Create(&pygpu_capabilities_module_def); return submodule; } diff --git a/source/blender/python/gpu/gpu_py_compute.cc b/source/blender/python/gpu/gpu_py_compute.cc index f150e516b7a..11506f99286 100644 --- a/source/blender/python/gpu/gpu_py_compute.cc +++ b/source/blender/python/gpu/gpu_py_compute.cc @@ -42,6 +42,8 @@ PyDoc_STRVAR( " :rtype: :class:`bpy.types.GPUShader`\n"); static PyObject *pygpu_compute_dispatch(PyObject * /*self*/, PyObject *args, PyObject *kwds) { + BPYGPU_IS_INIT_OR_ERROR_OBJ; + BPyGPUShader *py_shader; int groups_x_len; int groups_y_len; @@ -138,7 +140,7 @@ PyObject *bpygpu_compute_init() { PyObject *submodule; - submodule = bpygpu_create_module(&pygpu_compute_module_def); + submodule = PyModule_Create(&pygpu_compute_module_def); return submodule; } diff --git a/source/blender/python/gpu/gpu_py_element.cc b/source/blender/python/gpu/gpu_py_element.cc index 8e183c03891..12728a6fc6d 100644 --- a/source/blender/python/gpu/gpu_py_element.cc +++ b/source/blender/python/gpu/gpu_py_element.cc @@ -27,6 +27,8 @@ static PyObject *pygpu_IndexBuf__tp_new(PyTypeObject * /*type*/, PyObject *args, PyObject *kwds) { + BPYGPU_IS_INIT_OR_ERROR_OBJ; + const char *error_prefix = "IndexBuf.__new__"; bool ok = true; diff --git a/source/blender/python/gpu/gpu_py_framebuffer.cc b/source/blender/python/gpu/gpu_py_framebuffer.cc index df2e9e99569..76a0204e769 100644 --- a/source/blender/python/gpu/gpu_py_framebuffer.cc +++ b/source/blender/python/gpu/gpu_py_framebuffer.cc @@ -323,6 +323,8 @@ static bool pygpu_framebuffer_new_parse_arg(PyObject *o, GPUAttachment *r_attach static PyObject *pygpu_framebuffer__tp_new(PyTypeObject * /*self*/, PyObject *args, PyObject *kwds) { + BPYGPU_IS_INIT_OR_ERROR_OBJ; + if (!GPU_context_active_get()) { PyErr_SetString(PyExc_RuntimeError, "No active GPU context found"); return nullptr; diff --git a/source/blender/python/gpu/gpu_py_matrix.cc b/source/blender/python/gpu/gpu_py_matrix.cc index 2d9b595587f..44ec6f26cda 100644 --- a/source/blender/python/gpu/gpu_py_matrix.cc +++ b/source/blender/python/gpu/gpu_py_matrix.cc @@ -87,6 +87,8 @@ PyDoc_STRVAR( " Add to the model-view matrix stack.\n"); static PyObject *pygpu_matrix_push(PyObject * /*self*/) { + BPYGPU_IS_INIT_OR_ERROR_OBJ; + if (!pygpu_stack_is_push_model_view_ok_or_error()) { return nullptr; } @@ -102,6 +104,8 @@ PyDoc_STRVAR( " Remove the last model-view matrix from the stack.\n"); static PyObject *pygpu_matrix_pop(PyObject * /*self*/) { + BPYGPU_IS_INIT_OR_ERROR_OBJ; + if (!pygpu_stack_is_pop_model_view_ok_or_error()) { return nullptr; } @@ -117,6 +121,8 @@ PyDoc_STRVAR( " Add to the projection matrix stack.\n"); static PyObject *pygpu_matrix_push_projection(PyObject * /*self*/) { + BPYGPU_IS_INIT_OR_ERROR_OBJ; + if (!pygpu_stack_is_push_projection_ok_or_error()) { return nullptr; } @@ -132,6 +138,8 @@ PyDoc_STRVAR( " Remove the last projection matrix from the stack.\n"); static PyObject *pygpu_matrix_pop_projection(PyObject * /*self*/) { + BPYGPU_IS_INIT_OR_ERROR_OBJ; + if (!pygpu_stack_is_pop_projection_ok_or_error()) { return nullptr; } @@ -231,6 +239,8 @@ static PyTypeObject PyGPUMatrixStackContext_Type = { static PyObject *pygpu_matrix_stack_context_enter(BPyGPU_MatrixStackContext *self) { + BPYGPU_IS_INIT_OR_ERROR_OBJ; + /* sanity - should never happen */ if (self->level != -1) { PyErr_SetString(PyExc_RuntimeError, "Already in use"); @@ -260,6 +270,8 @@ static PyObject *pygpu_matrix_stack_context_enter(BPyGPU_MatrixStackContext *sel static PyObject *pygpu_matrix_stack_context_exit(BPyGPU_MatrixStackContext *self, PyObject * /*args*/) { + BPYGPU_IS_INIT_OR_ERROR_OBJ; + /* sanity - should never happen */ if (self->level == -1) { fprintf(stderr, "Not yet in use\n"); @@ -308,6 +320,8 @@ PyDoc_STRVAR( " Context manager to ensure balanced push/pop calls, even in the case of an error.\n"); static PyObject *pygpu_matrix_push_pop(PyObject * /*self*/) { + BPYGPU_IS_INIT_OR_ERROR_OBJ; + return pygpu_matrix_push_pop_impl(PYGPU_MATRIX_TYPE_MODEL_VIEW); } @@ -339,6 +353,8 @@ PyDoc_STRVAR( " :type matrix: :class:`mathutils.Matrix`\n"); static PyObject *pygpu_matrix_multiply_matrix(PyObject * /*self*/, PyObject *value) { + BPYGPU_IS_INIT_OR_ERROR_OBJ; + MatrixObject *pymat; if (!Matrix_Parse4x4(value, &pymat)) { return nullptr; @@ -358,6 +374,8 @@ PyDoc_STRVAR( " :type scale: sequence of 2 or 3 floats\n"); static PyObject *pygpu_matrix_scale(PyObject * /*self*/, PyObject *value) { + BPYGPU_IS_INIT_OR_ERROR_OBJ; + float scale[3]; int len; if ((len = mathutils_array_parse( @@ -383,6 +401,8 @@ PyDoc_STRVAR( " :type scale: float\n"); static PyObject *pygpu_matrix_scale_uniform(PyObject * /*self*/, PyObject *value) { + BPYGPU_IS_INIT_OR_ERROR_OBJ; + float scalar; if ((scalar = PyFloat_AsDouble(value)) == -1.0f && PyErr_Occurred()) { PyErr_Format(PyExc_TypeError, "expected a number, not %.200s", Py_TYPE(value)->tp_name); @@ -433,6 +453,8 @@ PyDoc_STRVAR( " Empty stack and set to identity.\n"); static PyObject *pygpu_matrix_reset(PyObject * /*self*/) { + BPYGPU_IS_INIT_OR_ERROR_OBJ; + GPU_matrix_reset(); Py_RETURN_NONE; } @@ -445,6 +467,8 @@ PyDoc_STRVAR( " Load an identity matrix into the stack.\n"); static PyObject *pygpu_matrix_load_identity(PyObject * /*self*/) { + BPYGPU_IS_INIT_OR_ERROR_OBJ; + GPU_matrix_identity_set(); Py_RETURN_NONE; } @@ -460,6 +484,8 @@ PyDoc_STRVAR( " :type matrix: :class:`mathutils.Matrix`\n"); static PyObject *pygpu_matrix_load_matrix(PyObject * /*self*/, PyObject *value) { + BPYGPU_IS_INIT_OR_ERROR_OBJ; + MatrixObject *pymat; if (!Matrix_Parse4x4(value, &pymat)) { return nullptr; @@ -479,6 +505,8 @@ PyDoc_STRVAR( " :type matrix: :class:`mathutils.Matrix`\n"); static PyObject *pygpu_matrix_load_projection_matrix(PyObject * /*self*/, PyObject *value) { + BPYGPU_IS_INIT_OR_ERROR_OBJ; + MatrixObject *pymat; if (!Matrix_Parse4x4(value, &pymat)) { return nullptr; @@ -504,6 +532,8 @@ PyDoc_STRVAR( " :rtype: :class:`mathutils.Matrix`\n"); static PyObject *pygpu_matrix_get_projection_matrix(PyObject * /*self*/) { + BPYGPU_IS_INIT_OR_ERROR_OBJ; + float matrix[4][4]; GPU_matrix_projection_get(matrix); return Matrix_CreatePyObject(&matrix[0][0], 4, 4, nullptr); @@ -520,6 +550,8 @@ PyDoc_STRVAR( " :rtype: :class:`mathutils.Matrix`\n"); static PyObject *pygpu_matrix_get_model_view_matrix(PyObject * /*self*/) { + BPYGPU_IS_INIT_OR_ERROR_OBJ; + float matrix[4][4]; GPU_matrix_model_view_get(matrix); return Matrix_CreatePyObject(&matrix[0][0], 4, 4, nullptr); @@ -536,6 +568,8 @@ PyDoc_STRVAR( " :rtype: :class:`mathutils.Matrix`\n"); static PyObject *pygpu_matrix_get_normal_matrix(PyObject * /*self*/) { + BPYGPU_IS_INIT_OR_ERROR_OBJ; + float matrix[3][3]; GPU_matrix_normal_get(matrix); return Matrix_CreatePyObject(&matrix[0][0], 3, 3, nullptr); @@ -645,9 +679,9 @@ PyObject *bpygpu_matrix_init() { PyObject *submodule; - submodule = bpygpu_create_module(&pygpu_matrix_module_def); + submodule = PyModule_Create(&pygpu_matrix_module_def); - if (bpygpu_finalize_type(&PyGPUMatrixStackContext_Type) < 0) { + if (PyType_Ready(&PyGPUMatrixStackContext_Type) < 0) { return nullptr; } diff --git a/source/blender/python/gpu/gpu_py_offscreen.cc b/source/blender/python/gpu/gpu_py_offscreen.cc index 21129531910..e8782046751 100644 --- a/source/blender/python/gpu/gpu_py_offscreen.cc +++ b/source/blender/python/gpu/gpu_py_offscreen.cc @@ -35,6 +35,7 @@ #include "../generic/py_capi_utils.h" #include "../generic/python_compat.h" +#include "gpu_py.hh" #include "gpu_py_texture.hh" #include "gpu_py_offscreen.hh" /* own include */ @@ -101,6 +102,8 @@ static void pygpu_offscreen_stack_context__tp_dealloc(OffScreenStackContext *sel static PyObject *pygpu_offscreen_stack_context_enter(OffScreenStackContext *self) { + BPYGPU_IS_INIT_OR_ERROR_OBJ; + BPY_GPU_OFFSCREEN_CHECK_OBJ(self->py_offscreen); if (!self->is_explicitly_bound) { @@ -119,6 +122,8 @@ static PyObject *pygpu_offscreen_stack_context_enter(OffScreenStackContext *self static PyObject *pygpu_offscreen_stack_context_exit(OffScreenStackContext *self, PyObject * /*args*/) { + BPYGPU_IS_INIT_OR_ERROR_OBJ; + BPY_GPU_OFFSCREEN_CHECK_OBJ(self->py_offscreen); if (self->level == -1) { @@ -266,6 +271,8 @@ static PyObject *pygpu_offscreen_unbind(BPyGPUOffScreen *self, PyObject *args, P static PyObject *pygpu_offscreen__tp_new(PyTypeObject * /*self*/, PyObject *args, PyObject *kwds) { + BPYGPU_IS_INIT_OR_ERROR_OBJ; + GPUOffScreen *ofs = nullptr; int width, height; PyC_StringEnum pygpu_textureformat = {pygpu_framebuffer_color_texture_formats, GPU_RGBA8}; diff --git a/source/blender/python/gpu/gpu_py_platform.cc b/source/blender/python/gpu/gpu_py_platform.cc index 85d3e29d858..71089544289 100644 --- a/source/blender/python/gpu/gpu_py_platform.cc +++ b/source/blender/python/gpu/gpu_py_platform.cc @@ -34,6 +34,8 @@ PyDoc_STRVAR( " :rtype: str\n"); static PyObject *pygpu_platform_vendor_get(PyObject * /*self*/) { + BPYGPU_IS_INIT_OR_ERROR_OBJ; + return PyUnicode_FromString(GPU_platform_vendor()); } @@ -48,6 +50,8 @@ PyDoc_STRVAR( " :rtype: str\n"); static PyObject *pygpu_platform_renderer_get(PyObject * /*self*/) { + BPYGPU_IS_INIT_OR_ERROR_OBJ; + return PyUnicode_FromString(GPU_platform_renderer()); } @@ -62,6 +66,8 @@ PyDoc_STRVAR( " :rtype: str\n"); static PyObject *pygpu_platform_version_get(PyObject * /*self*/) { + BPYGPU_IS_INIT_OR_ERROR_OBJ; + return PyUnicode_FromString(GPU_platform_version()); } @@ -77,6 +83,8 @@ PyDoc_STRVAR( " :rtype: str\n"); static PyObject *pygpu_platform_device_type_get(PyObject * /*self*/) { + BPYGPU_IS_INIT_OR_ERROR_OBJ; + const char *device; if (GPU_type_matches(GPU_DEVICE_APPLE, GPU_OS_ANY, GPU_DRIVER_ANY)) { device = "APPLE"; @@ -114,6 +122,8 @@ PyDoc_STRVAR( " :rtype: str\n"); static PyObject *pygpu_platform_backend_type_get(PyObject * /*self*/) { + BPYGPU_IS_INIT_OR_ERROR_OBJ; + const char *backend = "UNKNOWN"; switch (GPU_backend_get_type()) { case GPU_BACKEND_VULKAN: { @@ -197,7 +207,7 @@ PyObject *bpygpu_platform_init() { PyObject *submodule; - submodule = bpygpu_create_module(&pygpu_platform_module_def); + submodule = PyModule_Create(&pygpu_platform_module_def); return submodule; } diff --git a/source/blender/python/gpu/gpu_py_select.cc b/source/blender/python/gpu/gpu_py_select.cc index 478c478bbcf..0f58d0a4d7a 100644 --- a/source/blender/python/gpu/gpu_py_select.cc +++ b/source/blender/python/gpu/gpu_py_select.cc @@ -40,6 +40,8 @@ PyDoc_STRVAR( " :type select: int\n"); static PyObject *pygpu_select_load_id(PyObject * /*self*/, PyObject *value) { + BPYGPU_IS_INIT_OR_ERROR_OBJ; + uint id; if ((id = PyC_Long_AsU32(value)) == uint(-1)) { return nullptr; @@ -80,7 +82,7 @@ PyObject *bpygpu_select_init() { PyObject *submodule; - submodule = bpygpu_create_module(&pygpu_select_module_def); + submodule = PyModule_Create(&pygpu_select_module_def); return submodule; } diff --git a/source/blender/python/gpu/gpu_py_shader.cc b/source/blender/python/gpu/gpu_py_shader.cc index 497aabe3c57..3335b2f802d 100644 --- a/source/blender/python/gpu/gpu_py_shader.cc +++ b/source/blender/python/gpu/gpu_py_shader.cc @@ -99,6 +99,8 @@ static int pygpu_shader_uniform_location_get(GPUShader *shader, static PyObject *pygpu_shader__tp_new(PyTypeObject * /*type*/, PyObject *args, PyObject *kwds) { + BPYGPU_IS_INIT_OR_ERROR_OBJ; + struct { const char *vertexcode; const char *fragcode; @@ -948,6 +950,8 @@ PyDoc_STRVAR( " :rtype: :class:`bpy.types.GPUShader`\n"); static PyObject *pygpu_shader_from_builtin(PyObject * /*self*/, PyObject *args, PyObject *kwds) { + BPYGPU_IS_INIT_OR_ERROR_OBJ; + PyC_StringEnum pygpu_bultinshader = {pygpu_shader_builtin_items}; PyC_StringEnum pygpu_config = {pygpu_shader_config_items, GPU_SHADER_CFG_DEFAULT}; @@ -992,6 +996,8 @@ PyDoc_STRVAR( " :rtype: :class:`bpy.types.GPUShader`\n"); static PyObject *pygpu_shader_create_from_info(BPyGPUShader * /*self*/, BPyGPUShaderCreateInfo *o) { + BPYGPU_IS_INIT_OR_ERROR_OBJ; + if (!BPyGPUShaderCreateInfo_Check(o)) { PyErr_Format(PyExc_TypeError, "Expected a GPUShaderCreateInfo, got %s", Py_TYPE(o)->tp_name); return nullptr; @@ -1080,7 +1086,7 @@ PyObject *bpygpu_shader_init() { PyObject *submodule; - submodule = bpygpu_create_module(&pygpu_shader_module_def); + submodule = PyModule_Create(&pygpu_shader_module_def); return submodule; } diff --git a/source/blender/python/gpu/gpu_py_shader_create_info.cc b/source/blender/python/gpu/gpu_py_shader_create_info.cc index 7d7d93610c9..d3e905847c4 100644 --- a/source/blender/python/gpu/gpu_py_shader_create_info.cc +++ b/source/blender/python/gpu/gpu_py_shader_create_info.cc @@ -19,6 +19,7 @@ #include "../generic/py_capi_utils.h" #include "../generic/python_compat.h" +#include "gpu_py.hh" #include "gpu_py_shader.hh" /* own include */ #include "gpu_py_texture.hh" diff --git a/source/blender/python/gpu/gpu_py_state.cc b/source/blender/python/gpu/gpu_py_state.cc index dbd3bb62fa8..074f5755323 100644 --- a/source/blender/python/gpu/gpu_py_state.cc +++ b/source/blender/python/gpu/gpu_py_state.cc @@ -94,6 +94,8 @@ PyDoc_STRVAR( " :type mode: str\n"); static PyObject *pygpu_state_blend_set(PyObject * /*self*/, PyObject *value) { + BPYGPU_IS_INIT_OR_ERROR_OBJ; + PyC_StringEnum pygpu_blend = {pygpu_state_blend_items}; if (!PyC_ParseStringEnum(value, &pygpu_blend)) { return nullptr; @@ -111,6 +113,8 @@ PyDoc_STRVAR( "\n"); static PyObject *pygpu_state_blend_get(PyObject * /*self*/) { + BPYGPU_IS_INIT_OR_ERROR_OBJ; + eGPUBlend blend = GPU_blend_get(); return PyUnicode_FromString(PyC_StringEnum_FindIDFromValue(pygpu_state_blend_items, blend)); } @@ -126,6 +130,8 @@ PyDoc_STRVAR( " :type distances_enabled: int\n"); static PyObject *pygpu_state_clip_distances_set(PyObject * /*self*/, PyObject *value) { + BPYGPU_IS_INIT_OR_ERROR_OBJ; + int distances_enabled = int(PyLong_AsUnsignedLong(value)); if (distances_enabled == -1) { return nullptr; @@ -152,6 +158,8 @@ PyDoc_STRVAR( " :type mode: str\n"); static PyObject *pygpu_state_depth_test_set(PyObject * /*self*/, PyObject *value) { + BPYGPU_IS_INIT_OR_ERROR_OBJ; + PyC_StringEnum pygpu_depth_test = {pygpu_state_depthtest_items}; if (!PyC_ParseStringEnum(value, &pygpu_depth_test)) { return nullptr; @@ -169,6 +177,8 @@ PyDoc_STRVAR( "\n"); static PyObject *pygpu_state_depth_test_get(PyObject * /*self*/) { + BPYGPU_IS_INIT_OR_ERROR_OBJ; + eGPUDepthTest test = GPU_depth_test_get(); return PyUnicode_FromString(PyC_StringEnum_FindIDFromValue(pygpu_state_depthtest_items, test)); } @@ -184,6 +194,8 @@ PyDoc_STRVAR( " :type near: bool\n"); static PyObject *pygpu_state_depth_mask_set(PyObject * /*self*/, PyObject *value) { + BPYGPU_IS_INIT_OR_ERROR_OBJ; + bool write_to_depth; if (!PyC_ParseBool(value, &write_to_depth)) { return nullptr; @@ -200,6 +212,8 @@ PyDoc_STRVAR( " Writing status in the depth component.\n"); static PyObject *pygpu_state_depth_mask_get(PyObject * /*self*/) { + BPYGPU_IS_INIT_OR_ERROR_OBJ; + return PyBool_FromLong(GPU_depth_mask_get()); } @@ -217,6 +231,8 @@ PyDoc_STRVAR( " :type xsize, ysize: int\n"); static PyObject *pygpu_state_viewport_set(PyObject * /*self*/, PyObject *args) { + BPYGPU_IS_INIT_OR_ERROR_OBJ; + int x, y, xsize, ysize; if (!PyArg_ParseTuple(args, "iiii:viewport_set", &x, &y, &xsize, &ysize)) { return nullptr; @@ -234,6 +250,8 @@ PyDoc_STRVAR( " Viewport of the active framebuffer.\n"); static PyObject *pygpu_state_viewport_get(PyObject * /*self*/, PyObject * /*args*/) { + BPYGPU_IS_INIT_OR_ERROR_OBJ; + int viewport[4]; GPU_viewport_size_get_i(viewport); @@ -260,6 +278,8 @@ PyDoc_STRVAR( " :type xsize, ysize: int\n"); static PyObject *pygpu_state_scissor_set(PyObject * /*self*/, PyObject *args) { + BPYGPU_IS_INIT_OR_ERROR_OBJ; + int x, y, xsize, ysize; if (!PyArg_ParseTuple(args, "iiii:scissor_set", &x, &y, &xsize, &ysize)) { return nullptr; @@ -284,6 +304,8 @@ PyDoc_STRVAR( " :rtype: tuple(int, int, int, int)\n"); static PyObject *pygpu_state_scissor_get(PyObject * /*self*/, PyObject * /*args*/) { + BPYGPU_IS_INIT_OR_ERROR_OBJ; + int scissor[4]; GPU_scissor_get(scissor); @@ -309,6 +331,8 @@ PyDoc_STRVAR( " :type enable: bool\n"); static PyObject *pygpu_state_scissor_test_set(PyObject * /*self*/, PyObject *value) { + BPYGPU_IS_INIT_OR_ERROR_OBJ; + bool enabled; if (!PyC_ParseBool(value, &enabled)) { return nullptr; @@ -329,6 +353,8 @@ PyDoc_STRVAR( " :type mode: float\n"); static PyObject *pygpu_state_line_width_set(PyObject * /*self*/, PyObject *value) { + BPYGPU_IS_INIT_OR_ERROR_OBJ; + float width = float(PyFloat_AsDouble(value)); if (PyErr_Occurred()) { return nullptr; @@ -346,6 +372,8 @@ PyDoc_STRVAR( " Current width of rasterized lines.\n"); static PyObject *pygpu_state_line_width_get(PyObject * /*self*/) { + BPYGPU_IS_INIT_OR_ERROR_OBJ; + float width = GPU_line_width_get(); return PyFloat_FromDouble(double(width)); } @@ -361,6 +389,8 @@ PyDoc_STRVAR( " :type mode: float\n"); static PyObject *pygpu_state_point_size_set(PyObject * /*self*/, PyObject *value) { + BPYGPU_IS_INIT_OR_ERROR_OBJ; + float size = float(PyFloat_AsDouble(value)); if (PyErr_Occurred()) { return nullptr; @@ -381,6 +411,8 @@ PyDoc_STRVAR( " :type r, g, b, a: bool\n"); static PyObject *pygpu_state_color_mask_set(PyObject * /*self*/, PyObject *args) { + BPYGPU_IS_INIT_OR_ERROR_OBJ; + int r, g, b, a; if (!PyArg_ParseTuple(args, "pppp:color_mask_set", &r, &g, &b, &a)) { return nullptr; @@ -401,6 +433,8 @@ PyDoc_STRVAR( " :type mode: str\n"); static PyObject *pygpu_state_face_culling_set(PyObject * /*self*/, PyObject *value) { + BPYGPU_IS_INIT_OR_ERROR_OBJ; + PyC_StringEnum pygpu_faceculling = {pygpu_state_faceculling_items}; if (!PyC_ParseStringEnum(value, &pygpu_faceculling)) { return nullptr; @@ -421,6 +455,8 @@ PyDoc_STRVAR( " :type mode: bool\n"); static PyObject *pygpu_state_front_facing_set(PyObject * /*self*/, PyObject *value) { + BPYGPU_IS_INIT_OR_ERROR_OBJ; + bool invert; if (!PyC_ParseBool(value, &invert)) { return nullptr; @@ -442,6 +478,8 @@ PyDoc_STRVAR( " :type enable: bool\n"); static PyObject *pygpu_state_program_point_size_set(PyObject * /*self*/, PyObject *value) { + BPYGPU_IS_INIT_OR_ERROR_OBJ; + bool enable; if (!PyC_ParseBool(value, &enable)) { return nullptr; @@ -459,6 +497,8 @@ PyDoc_STRVAR( " Return the active frame-buffer in context.\n"); static PyObject *pygpu_state_framebuffer_active_get(PyObject * /*self*/) { + BPYGPU_IS_INIT_OR_ERROR_OBJ; + GPUFrameBuffer *fb = GPU_framebuffer_active_get(); return BPyGPUFrameBuffer_CreatePyObject(fb, true); } @@ -577,7 +617,7 @@ PyObject *bpygpu_state_init() { PyObject *submodule; - submodule = bpygpu_create_module(&pygpu_state_module_def); + submodule = PyModule_Create(&pygpu_state_module_def); return submodule; } diff --git a/source/blender/python/gpu/gpu_py_texture.cc b/source/blender/python/gpu/gpu_py_texture.cc index a772cd28f9c..e45d633b05c 100644 --- a/source/blender/python/gpu/gpu_py_texture.cc +++ b/source/blender/python/gpu/gpu_py_texture.cc @@ -114,6 +114,8 @@ static int pygpu_texture_valid_check(BPyGPUTexture *bpygpu_tex) static PyObject *pygpu_texture__tp_new(PyTypeObject * /*self*/, PyObject *args, PyObject *kwds) { + BPYGPU_IS_INIT_OR_ERROR_OBJ; + PyObject *py_size; int size[3] = {1, 1, 1}; int layers = 0; @@ -728,7 +730,7 @@ int bpygpu_ParseTexture(PyObject *o, void *p) PyObject *bpygpu_texture_init() { PyObject *submodule; - submodule = bpygpu_create_module(&pygpu_texture_module_def); + submodule = PyModule_Create(&pygpu_texture_module_def); return submodule; } diff --git a/source/blender/python/gpu/gpu_py_types.cc b/source/blender/python/gpu/gpu_py_types.cc index edc2cd3626e..fe1b51191a6 100644 --- a/source/blender/python/gpu/gpu_py_types.cc +++ b/source/blender/python/gpu/gpu_py_types.cc @@ -11,7 +11,6 @@ #include -#include "gpu_py.hh" #include "gpu_py_types.hh" /* own include */ /* -------------------------------------------------------------------- */ @@ -34,42 +33,42 @@ PyObject *bpygpu_types_init() { PyObject *submodule; - submodule = bpygpu_create_module(&pygpu_types_module_def); + submodule = PyModule_Create(&pygpu_types_module_def); - if (bpygpu_finalize_type(&BPyGPU_BufferType) < 0) { + if (PyType_Ready(&BPyGPU_BufferType) < 0) { return nullptr; } - if (bpygpu_finalize_type(&BPyGPUVertFormat_Type) < 0) { + if (PyType_Ready(&BPyGPUVertFormat_Type) < 0) { return nullptr; } - if (bpygpu_finalize_type(&BPyGPUVertBuf_Type) < 0) { + if (PyType_Ready(&BPyGPUVertBuf_Type) < 0) { return nullptr; } - if (bpygpu_finalize_type(&BPyGPUIndexBuf_Type) < 0) { + if (PyType_Ready(&BPyGPUIndexBuf_Type) < 0) { return nullptr; } - if (bpygpu_finalize_type(&BPyGPUBatch_Type) < 0) { + if (PyType_Ready(&BPyGPUBatch_Type) < 0) { return nullptr; } - if (bpygpu_finalize_type(&BPyGPUOffScreen_Type) < 0) { + if (PyType_Ready(&BPyGPUOffScreen_Type) < 0) { return nullptr; } - if (bpygpu_finalize_type(&BPyGPUShader_Type) < 0) { + if (PyType_Ready(&BPyGPUShader_Type) < 0) { return nullptr; } - if (bpygpu_finalize_type(&BPyGPUTexture_Type) < 0) { + if (PyType_Ready(&BPyGPUTexture_Type) < 0) { return nullptr; } - if (bpygpu_finalize_type(&BPyGPUFrameBuffer_Type) < 0) { + if (PyType_Ready(&BPyGPUFrameBuffer_Type) < 0) { return nullptr; } - if (bpygpu_finalize_type(&BPyGPUUniformBuf_Type) < 0) { + if (PyType_Ready(&BPyGPUUniformBuf_Type) < 0) { return nullptr; } - if (bpygpu_finalize_type(&BPyGPUShaderCreateInfo_Type) < 0) { + if (PyType_Ready(&BPyGPUShaderCreateInfo_Type) < 0) { return nullptr; } - if (bpygpu_finalize_type(&BPyGPUStageInterfaceInfo_Type) < 0) { + if (PyType_Ready(&BPyGPUStageInterfaceInfo_Type) < 0) { return nullptr; } diff --git a/source/blender/python/gpu/gpu_py_uniformbuffer.cc b/source/blender/python/gpu/gpu_py_uniformbuffer.cc index 09d7fce0b70..b5cb00605b6 100644 --- a/source/blender/python/gpu/gpu_py_uniformbuffer.cc +++ b/source/blender/python/gpu/gpu_py_uniformbuffer.cc @@ -20,6 +20,7 @@ #include "../generic/python_compat.h" +#include "gpu_py.hh" #include "gpu_py_uniformbuffer.hh" /* own include */ /* -------------------------------------------------------------------- */ @@ -59,6 +60,8 @@ static PyObject *pygpu_uniformbuffer__tp_new(PyTypeObject * /*self*/, PyObject *args, PyObject *kwds) { + BPYGPU_IS_INIT_OR_ERROR_OBJ; + GPUUniformBuf *ubo = nullptr; PyObject *pybuffer_obj; char err_out[256] = "unknown error. See console"; diff --git a/source/blender/python/gpu/gpu_py_vertex_buffer.cc b/source/blender/python/gpu/gpu_py_vertex_buffer.cc index 0602e5ecf98..85adffab6c5 100644 --- a/source/blender/python/gpu/gpu_py_vertex_buffer.cc +++ b/source/blender/python/gpu/gpu_py_vertex_buffer.cc @@ -19,6 +19,7 @@ #include "../generic/python_compat.h" #include "../generic/python_utildefines.h" +#include "gpu_py.hh" #include "gpu_py_vertex_buffer.hh" /* own include */ #include "gpu_py_vertex_format.hh" @@ -231,6 +232,8 @@ static int pygpu_vertbuf_fill(blender::gpu::VertBuf *buf, static PyObject *pygpu_vertbuf__tp_new(PyTypeObject * /*type*/, PyObject *args, PyObject *kwds) { + BPYGPU_IS_INIT_OR_ERROR_OBJ; + struct { PyObject *py_fmt; uint len; diff --git a/source/blender/python/gpu/gpu_py_vertex_format.cc b/source/blender/python/gpu/gpu_py_vertex_format.cc index 02ea95b6310..d51a0224c1d 100644 --- a/source/blender/python/gpu/gpu_py_vertex_format.cc +++ b/source/blender/python/gpu/gpu_py_vertex_format.cc @@ -14,6 +14,7 @@ #include "../generic/py_capi_utils.h" #include "../generic/python_compat.h" +#include "gpu_py.hh" #include "gpu_py_vertex_format.hh" /* own include */ /* -------------------------------------------------------------------- */ @@ -50,6 +51,8 @@ static PyC_StringEnumItems pygpu_vertfetchmode_items[] = { static PyObject *pygpu_vertformat__tp_new(PyTypeObject * /*type*/, PyObject *args, PyObject *kwds) { + BPYGPU_IS_INIT_OR_ERROR_OBJ; + if (PyTuple_GET_SIZE(args) || (kwds && PyDict_Size(kwds))) { PyErr_SetString(PyExc_ValueError, "This function takes no arguments"); return nullptr;