diff --git a/source/blender/python/gpu/gpu_py.c b/source/blender/python/gpu/gpu_py.c index 987d2fbd627..34557f0115b 100644 --- a/source/blender/python/gpu/gpu_py.c +++ b/source/blender/python/gpu/gpu_py.c @@ -51,16 +51,72 @@ struct PyC_StringEnumItems bpygpu_dataformat_items[] = { /** \name Utilities * \{ */ -bool bpygpu_is_init_or_error(void) -{ - if (!GPU_is_init()) { - PyErr_SetString(PyExc_SystemError, - "GPU functions for drawing are not available in background mode"); +static const char g_error[] = "GPU API is not available in background mode"; - return false; +static PyObject *py_error__ml_meth(PyObject *UNUSED(self), PyObject *UNUSED(args)) +{ + PyErr_SetString(PyExc_SystemError, g_error); + Py_RETURN_NONE; +} + +static PyObject *py_error__getter(PyObject *UNUSED(self), void *UNUSED(type)) +{ + PyErr_SetString(PyExc_SystemError, g_error); + Py_RETURN_NONE; +} + +static int py_error__setter(PyObject *UNUSED(self), PyObject *value, void *UNUSED(type)) +{ + PyErr_SetString(PyExc_SystemError, g_error); + return -1; +} + +static PyObject *py_error__tp_new(PyTypeObject *UNUSED(type), + PyObject *UNUSED(args), + PyObject *UNUSED(kwds)) +{ + PyErr_SetString(PyExc_SystemError, g_error); + return NULL; +} + +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; + } } - return true; + PyObject *module = PyModule_Create(module_type); + + return module; +} + +int bpygpu_finalize_type(PyTypeObject *py_type) +{ + 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; + } + } + + return PyType_Ready(py_type); } /** \} */ diff --git a/source/blender/python/gpu/gpu_py.h b/source/blender/python/gpu/gpu_py.h index 2914e370cdc..c0abb60d419 100644 --- a/source/blender/python/gpu/gpu_py.h +++ b/source/blender/python/gpu/gpu_py.h @@ -9,15 +9,5 @@ extern struct PyC_StringEnumItems bpygpu_primtype_items[]; extern struct PyC_StringEnumItems bpygpu_dataformat_items[]; -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) +PyObject *bpygpu_create_module(PyModuleDef *module_type); +int bpygpu_finalize_type(PyTypeObject *py_type); diff --git a/source/blender/python/gpu/gpu_py_api.c b/source/blender/python/gpu/gpu_py_api.c index 8f5897be649..abba2e83cd6 100644 --- a/source/blender/python/gpu/gpu_py_api.c +++ b/source/blender/python/gpu/gpu_py_api.c @@ -21,6 +21,7 @@ #include "gpu_py_state.h" #include "gpu_py_types.h" +#include "gpu_py.h" #include "gpu_py_api.h" /* Own include. */ /* -------------------------------------------------------------------- */ @@ -48,7 +49,7 @@ PyObject *BPyInit_gpu(void) PyObject *submodule; PyObject *mod; - mod = PyModule_Create(&pygpu_module_def); + mod = bpygpu_create_module(&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.c b/source/blender/python/gpu/gpu_py_batch.c index a36b1dfd1b5..25fe31322b1 100644 --- a/source/blender/python/gpu/gpu_py_batch.c +++ b/source/blender/python/gpu/gpu_py_batch.c @@ -47,8 +47,6 @@ static bool pygpu_batch_is_program_or_error(BPyGPUBatch *self) static PyObject *pygpu_batch__tp_new(PyTypeObject *UNUSED(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)"; struct PyC_StringEnum prim_type = {bpygpu_primtype_items, GPU_PRIM_NONE}; diff --git a/source/blender/python/gpu/gpu_py_capabilities.c b/source/blender/python/gpu/gpu_py_capabilities.c index 2345982eb42..80f7df81e9f 100644 --- a/source/blender/python/gpu/gpu_py_capabilities.c +++ b/source/blender/python/gpu/gpu_py_capabilities.c @@ -13,6 +13,7 @@ #include "GPU_capabilities.h" +#include "gpu_py.h" #include "gpu_py_capabilities.h" /* own include */ /* -------------------------------------------------------------------- */ @@ -315,7 +316,7 @@ PyObject *bpygpu_capabilities_init(void) { PyObject *submodule; - submodule = PyModule_Create(&pygpu_capabilities_module_def); + submodule = bpygpu_create_module(&pygpu_capabilities_module_def); return submodule; } diff --git a/source/blender/python/gpu/gpu_py_element.c b/source/blender/python/gpu/gpu_py_element.c index 46f1d4d49eb..d150a51ba04 100644 --- a/source/blender/python/gpu/gpu_py_element.c +++ b/source/blender/python/gpu/gpu_py_element.c @@ -26,8 +26,6 @@ static PyObject *pygpu_IndexBuf__tp_new(PyTypeObject *UNUSED(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.c b/source/blender/python/gpu/gpu_py_framebuffer.c index 2de8c680b23..acbf15b604d 100644 --- a/source/blender/python/gpu/gpu_py_framebuffer.c +++ b/source/blender/python/gpu/gpu_py_framebuffer.c @@ -267,7 +267,6 @@ static PyObject *pygpu_framebuffer__tp_new(PyTypeObject *UNUSED(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 NULL; diff --git a/source/blender/python/gpu/gpu_py_matrix.c b/source/blender/python/gpu/gpu_py_matrix.c index 7d80f763162..414c7751926 100644 --- a/source/blender/python/gpu/gpu_py_matrix.c +++ b/source/blender/python/gpu/gpu_py_matrix.c @@ -24,6 +24,7 @@ #include "GPU_matrix.h" #undef USE_GPU_PY_MATRIX_API +#include "gpu_py.h" #include "gpu_py_matrix.h" /* own include */ /* -------------------------------------------------------------------- */ @@ -542,9 +543,9 @@ PyObject *bpygpu_matrix_init(void) { PyObject *submodule; - submodule = PyModule_Create(&pygpu_matrix_module_def); + submodule = bpygpu_create_module(&pygpu_matrix_module_def); - if (PyType_Ready(&PyGPUMatrixStackContext_Type) < 0) { + if (bpygpu_finalize_type(&PyGPUMatrixStackContext_Type) < 0) { return NULL; } diff --git a/source/blender/python/gpu/gpu_py_offscreen.c b/source/blender/python/gpu/gpu_py_offscreen.c index 621c6647cb9..2738a4e4784 100644 --- a/source/blender/python/gpu/gpu_py_offscreen.c +++ b/source/blender/python/gpu/gpu_py_offscreen.c @@ -211,8 +211,6 @@ static PyObject *pygpu_offscreen__tp_new(PyTypeObject *UNUSED(self), PyObject *args, PyObject *kwds) { - BPYGPU_IS_INIT_OR_ERROR_OBJ; - GPUOffScreen *ofs = NULL; int width, height; struct PyC_StringEnum pygpu_textureformat = {pygpu_framebuffer_color_texture_formats, GPU_RGBA8}; diff --git a/source/blender/python/gpu/gpu_py_platform.c b/source/blender/python/gpu/gpu_py_platform.c index 5f9f653a3c4..e908447e02c 100644 --- a/source/blender/python/gpu/gpu_py_platform.c +++ b/source/blender/python/gpu/gpu_py_platform.c @@ -14,6 +14,7 @@ #include "GPU_context.h" #include "GPU_platform.h" +#include "gpu_py.h" #include "gpu_py_platform.h" /* Own include. */ /* -------------------------------------------------------------------- */ @@ -155,7 +156,7 @@ PyObject *bpygpu_platform_init(void) { PyObject *submodule; - submodule = PyModule_Create(&pygpu_platform_module_def); + submodule = bpygpu_create_module(&pygpu_platform_module_def); return submodule; } diff --git a/source/blender/python/gpu/gpu_py_select.c b/source/blender/python/gpu/gpu_py_select.c index 02e06e0ffd5..dde703fa52d 100644 --- a/source/blender/python/gpu/gpu_py_select.c +++ b/source/blender/python/gpu/gpu_py_select.c @@ -20,6 +20,7 @@ #include "GPU_select.h" +#include "gpu_py.h" #include "gpu_py_select.h" /* Own include. */ /* -------------------------------------------------------------------- */ @@ -72,7 +73,7 @@ PyObject *bpygpu_select_init(void) { PyObject *submodule; - submodule = PyModule_Create(&pygpu_select_module_def); + submodule = bpygpu_create_module(&pygpu_select_module_def); return submodule; } diff --git a/source/blender/python/gpu/gpu_py_shader.c b/source/blender/python/gpu/gpu_py_shader.c index 7222cb1696a..87f09098d46 100644 --- a/source/blender/python/gpu/gpu_py_shader.c +++ b/source/blender/python/gpu/gpu_py_shader.c @@ -95,8 +95,6 @@ static int pygpu_shader_uniform_location_get(GPUShader *shader, static PyObject *pygpu_shader__tp_new(PyTypeObject *UNUSED(type), PyObject *args, PyObject *kwds) { - BPYGPU_IS_INIT_OR_ERROR_OBJ; - struct { const char *vertexcode; const char *fragcode; @@ -835,8 +833,6 @@ PyDoc_STRVAR( " :rtype: :class:`bpy.types.GPUShader`\n"); static PyObject *pygpu_shader_from_builtin(PyObject *UNUSED(self), PyObject *args, PyObject *kwds) { - BPYGPU_IS_INIT_OR_ERROR_OBJ; - struct PyC_StringEnum pygpu_bultinshader = {pygpu_shader_builtin_items}; struct PyC_StringEnum pygpu_config = {pygpu_shader_config_items, GPU_SHADER_CFG_DEFAULT}; @@ -954,7 +950,7 @@ PyObject *bpygpu_shader_init(void) { PyObject *submodule; - submodule = PyModule_Create(&pygpu_shader_module_def); + submodule = bpygpu_create_module(&pygpu_shader_module_def); return submodule; } diff --git a/source/blender/python/gpu/gpu_py_state.c b/source/blender/python/gpu/gpu_py_state.c index f17a3fecfdd..0543825d8a0 100644 --- a/source/blender/python/gpu/gpu_py_state.c +++ b/source/blender/python/gpu/gpu_py_state.c @@ -17,6 +17,7 @@ #include "../generic/py_capi_utils.h" #include "../generic/python_utildefines.h" +#include "gpu_py.h" #include "gpu_py_framebuffer.h" #include "gpu_py_state.h" /* own include */ @@ -445,7 +446,7 @@ PyObject *bpygpu_state_init(void) { PyObject *submodule; - submodule = PyModule_Create(&pygpu_state_module_def); + submodule = bpygpu_create_module(&pygpu_state_module_def); return submodule; } diff --git a/source/blender/python/gpu/gpu_py_texture.c b/source/blender/python/gpu/gpu_py_texture.c index 11b44a2a35e..a45b833b890 100644 --- a/source/blender/python/gpu/gpu_py_texture.c +++ b/source/blender/python/gpu/gpu_py_texture.c @@ -111,8 +111,6 @@ static int pygpu_texture_valid_check(BPyGPUTexture *bpygpu_tex) static PyObject *pygpu_texture__tp_new(PyTypeObject *UNUSED(self), PyObject *args, PyObject *kwds) { - BPYGPU_IS_INIT_OR_ERROR_OBJ; - PyObject *py_size; int size[3] = {1, 1, 1}; int layers = 0; @@ -605,7 +603,7 @@ int bpygpu_ParseTexture(PyObject *o, void *p) PyObject *bpygpu_texture_init(void) { PyObject *submodule; - submodule = PyModule_Create(&pygpu_texture_module_def); + submodule = bpygpu_create_module(&pygpu_texture_module_def); return submodule; } diff --git a/source/blender/python/gpu/gpu_py_types.c b/source/blender/python/gpu/gpu_py_types.c index b5cabd93b42..900351af3ce 100644 --- a/source/blender/python/gpu/gpu_py_types.c +++ b/source/blender/python/gpu/gpu_py_types.c @@ -11,6 +11,7 @@ #include "../generic/py_capi_utils.h" +#include "gpu_py.h" #include "gpu_py_types.h" /* own include */ /* -------------------------------------------------------------------- */ @@ -33,42 +34,42 @@ PyObject *bpygpu_types_init(void) { PyObject *submodule; - submodule = PyModule_Create(&pygpu_types_module_def); + submodule = bpygpu_create_module(&pygpu_types_module_def); - if (PyType_Ready(&BPyGPU_BufferType) < 0) { + if (bpygpu_finalize_type(&BPyGPU_BufferType) < 0) { return NULL; } - if (PyType_Ready(&BPyGPUVertFormat_Type) < 0) { + if (bpygpu_finalize_type(&BPyGPUVertFormat_Type) < 0) { return NULL; } - if (PyType_Ready(&BPyGPUVertBuf_Type) < 0) { + if (bpygpu_finalize_type(&BPyGPUVertBuf_Type) < 0) { return NULL; } - if (PyType_Ready(&BPyGPUIndexBuf_Type) < 0) { + if (bpygpu_finalize_type(&BPyGPUIndexBuf_Type) < 0) { return NULL; } - if (PyType_Ready(&BPyGPUBatch_Type) < 0) { + if (bpygpu_finalize_type(&BPyGPUBatch_Type) < 0) { return NULL; } - if (PyType_Ready(&BPyGPUOffScreen_Type) < 0) { + if (bpygpu_finalize_type(&BPyGPUOffScreen_Type) < 0) { return NULL; } - if (PyType_Ready(&BPyGPUShader_Type) < 0) { + if (bpygpu_finalize_type(&BPyGPUShader_Type) < 0) { return NULL; } - if (PyType_Ready(&BPyGPUTexture_Type) < 0) { + if (bpygpu_finalize_type(&BPyGPUTexture_Type) < 0) { return NULL; } - if (PyType_Ready(&BPyGPUFrameBuffer_Type) < 0) { + if (bpygpu_finalize_type(&BPyGPUFrameBuffer_Type) < 0) { return NULL; } - if (PyType_Ready(&BPyGPUUniformBuf_Type) < 0) { + if (bpygpu_finalize_type(&BPyGPUUniformBuf_Type) < 0) { return NULL; } - if (PyType_Ready(&BPyGPUShaderCreateInfo_Type) < 0) { + if (bpygpu_finalize_type(&BPyGPUShaderCreateInfo_Type) < 0) { return NULL; } - if (PyType_Ready(&BPyGPUStageInterfaceInfo_Type) < 0) { + if (bpygpu_finalize_type(&BPyGPUStageInterfaceInfo_Type) < 0) { return NULL; } diff --git a/source/blender/python/gpu/gpu_py_uniformbuffer.c b/source/blender/python/gpu/gpu_py_uniformbuffer.c index dcf9ab76470..cfa01d5ecb8 100644 --- a/source/blender/python/gpu/gpu_py_uniformbuffer.c +++ b/source/blender/python/gpu/gpu_py_uniformbuffer.c @@ -59,8 +59,6 @@ static PyObject *pygpu_uniformbuffer__tp_new(PyTypeObject *UNUSED(self), PyObject *args, PyObject *kwds) { - BPYGPU_IS_INIT_OR_ERROR_OBJ; - GPUUniformBuf *ubo = NULL; PyObject *pybuffer_obj; char err_out[256] = "unknown error. See console";