diff options
author | Germano Cavalcante <mano-wii> | 2021-02-22 14:26:45 +0300 |
---|---|---|
committer | Germano Cavalcante <germano.costa@ig.com.br> | 2021-02-22 14:35:52 +0300 |
commit | 086d70e910a09185e220169342367a0c95ade0fc (patch) | |
tree | afbb7111ce365bcd61fd6cd307e34c01accb6b19 /source/blender/python/gpu | |
parent | 78c3caf3c1b87f449837b11c903ddeaf00afe7b9 (diff) |
GPU Python: Use 'PyC_ParseStringEnum' to parse items
Currently the GPU module for python has different ways to handle enums.
- Organizing items in `PyC_StringEnumItems` arrays and parsing them with `PyC_ParseStringEnum`.
- Using dedicated functions for each type of enum (`bpygpu_ParsePrimType`, `pygpu_ParseVertCompType` and `pygpu_ParseVertFetchMode`).
Although apparently more efficient (especially `pygpu_ParseVertCompType`
which transforms strings into integers for simple comparison), these
dedicated functions duplicate functionality, increase the complexity of
the code and consequently make it less readable.
Reviewed By: campbellbarton
Differential Revision: https://developer.blender.org/D10456
Diffstat (limited to 'source/blender/python/gpu')
-rw-r--r-- | source/blender/python/gpu/gpu_py.c | 17 | ||||
-rw-r--r-- | source/blender/python/gpu/gpu_py.h | 1 | ||||
-rw-r--r-- | source/blender/python/gpu/gpu_py_api.c | 45 | ||||
-rw-r--r-- | source/blender/python/gpu/gpu_py_api.h | 2 | ||||
-rw-r--r-- | source/blender/python/gpu/gpu_py_batch.c | 44 | ||||
-rw-r--r-- | source/blender/python/gpu/gpu_py_element.c | 21 | ||||
-rw-r--r-- | source/blender/python/gpu/gpu_py_vertex_format.c | 144 |
7 files changed, 76 insertions, 198 deletions
diff --git a/source/blender/python/gpu/gpu_py.c b/source/blender/python/gpu/gpu_py.c index 35cc945e76c..2c5daaf1962 100644 --- a/source/blender/python/gpu/gpu_py.c +++ b/source/blender/python/gpu/gpu_py.c @@ -23,6 +23,7 @@ #include <Python.h> +#include "GPU_primitive.h" #include "GPU_texture.h" #include "../generic/py_capi_utils.h" @@ -30,9 +31,23 @@ #include "gpu_py.h" /* own include */ /* -------------------------------------------------------------------- */ -/** \name GPU Module +/** \name GPU Enums * \{ */ +struct PyC_StringEnumItems bpygpu_primtype_items[] = { + {GPU_PRIM_POINTS, "POINTS"}, + {GPU_PRIM_LINES, "LINES"}, + {GPU_PRIM_TRIS, "TRIS"}, + {GPU_PRIM_LINE_STRIP, "LINE_STRIP"}, + {GPU_PRIM_LINE_LOOP, "LINE_LOOP"}, + {GPU_PRIM_TRI_STRIP, "TRI_STRIP"}, + {GPU_PRIM_TRI_FAN, "TRI_FAN"}, + {GPU_PRIM_LINES_ADJ, "LINES_ADJ"}, + {GPU_PRIM_TRIS_ADJ, "TRIS_ADJ"}, + {GPU_PRIM_LINE_STRIP_ADJ, "LINE_STRIP_ADJ"}, + {0, NULL}, +}; + struct PyC_StringEnumItems bpygpu_dataformat_items[] = { {GPU_DATA_FLOAT, "FLOAT"}, {GPU_DATA_INT, "INT"}, diff --git a/source/blender/python/gpu/gpu_py.h b/source/blender/python/gpu/gpu_py.h index 8a96391664f..28b3e41a08f 100644 --- a/source/blender/python/gpu/gpu_py.h +++ b/source/blender/python/gpu/gpu_py.h @@ -20,4 +20,5 @@ #pragma once +extern struct PyC_StringEnumItems bpygpu_primtype_items[]; extern struct PyC_StringEnumItems bpygpu_dataformat_items[]; diff --git a/source/blender/python/gpu/gpu_py_api.c b/source/blender/python/gpu/gpu_py_api.c index 38e9b61e147..7213dc59886 100644 --- a/source/blender/python/gpu/gpu_py_api.c +++ b/source/blender/python/gpu/gpu_py_api.c @@ -31,7 +31,6 @@ #include "../generic/python_utildefines.h" #include "GPU_init_exit.h" -#include "GPU_primitive.h" #include "gpu_py_matrix.h" #include "gpu_py_select.h" @@ -59,50 +58,6 @@ bool bpygpu_is_init_or_error(void) /** \} */ /* -------------------------------------------------------------------- */ -/** \name Primitive Type Utils - * \{ */ - -int bpygpu_ParsePrimType(PyObject *o, void *p) -{ - Py_ssize_t mode_id_len; - const char *mode_id = PyUnicode_AsUTF8AndSize(o, &mode_id_len); - if (mode_id == NULL) { - PyErr_Format(PyExc_ValueError, "expected a string, got %s", Py_TYPE(o)->tp_name); - return 0; - } -#define MATCH_ID(id) \ - if (mode_id_len == strlen(STRINGIFY(id))) { \ - if (STREQ(mode_id, STRINGIFY(id))) { \ - mode = GPU_PRIM_##id; \ - goto success; \ - } \ - } \ - ((void)0) - - GPUPrimType mode; - MATCH_ID(POINTS); - MATCH_ID(LINES); - MATCH_ID(TRIS); - MATCH_ID(LINE_STRIP); - MATCH_ID(LINE_LOOP); - MATCH_ID(TRI_STRIP); - MATCH_ID(TRI_FAN); - MATCH_ID(LINES_ADJ); - MATCH_ID(TRIS_ADJ); - MATCH_ID(LINE_STRIP_ADJ); - -#undef MATCH_ID - PyErr_Format(PyExc_ValueError, "unknown type literal: '%s'", mode_id); - return 0; - -success: - (*(GPUPrimType *)p) = mode; - return 1; -} - -/** \} */ - -/* -------------------------------------------------------------------- */ /** \name GPU Module * \{ */ diff --git a/source/blender/python/gpu/gpu_py_api.h b/source/blender/python/gpu/gpu_py_api.h index fe645d8cd3a..5e399a233aa 100644 --- a/source/blender/python/gpu/gpu_py_api.h +++ b/source/blender/python/gpu/gpu_py_api.h @@ -24,8 +24,6 @@ * However, it is currently of little use. */ // #define BPYGPU_USE_GPUOBJ_FREE_METHOD -int bpygpu_ParsePrimType(PyObject *o, void *p); - PyObject *BPyInit_gpu(void); bool bpygpu_is_init_or_error(void); diff --git a/source/blender/python/gpu/gpu_py_batch.c b/source/blender/python/gpu/gpu_py_batch.c index 0e4cc4d2219..9989077670b 100644 --- a/source/blender/python/gpu/gpu_py_batch.c +++ b/source/blender/python/gpu/gpu_py_batch.c @@ -38,12 +38,14 @@ #include "../generic/py_capi_utils.h" +#include "gpu_py.h" #include "gpu_py_api.h" -#include "gpu_py_batch.h" /* own include */ #include "gpu_py_element.h" #include "gpu_py_shader.h" #include "gpu_py_vertex_buffer.h" +#include "gpu_py_batch.h" /* own include */ + /* -------------------------------------------------------------------- */ /** \name Utility Functions * \{ */ @@ -69,50 +71,44 @@ static PyObject *pygpu_batch__tp_new(PyTypeObject *UNUSED(type), PyObject *args, const char *exc_str_missing_arg = "GPUBatch.__new__() missing required argument '%s' (pos %d)"; - struct { - GPUPrimType type_id; - BPyGPUVertBuf *py_vertbuf; - BPyGPUIndexBuf *py_indexbuf; - } params = {GPU_PRIM_NONE, NULL, NULL}; + struct PyC_StringEnum prim_type = {bpygpu_primtype_items, GPU_PRIM_NONE}; + BPyGPUVertBuf *py_vertbuf = NULL; + BPyGPUIndexBuf *py_indexbuf = NULL; static const char *_keywords[] = {"type", "buf", "elem", NULL}; static _PyArg_Parser _parser = {"|$O&O!O!:GPUBatch.__new__", _keywords, 0}; if (!_PyArg_ParseTupleAndKeywordsFast(args, kwds, &_parser, - bpygpu_ParsePrimType, - ¶ms.type_id, + PyC_ParseStringEnum, + &prim_type, &BPyGPUVertBuf_Type, - ¶ms.py_vertbuf, + &py_vertbuf, &BPyGPUIndexBuf_Type, - ¶ms.py_indexbuf)) { + &py_indexbuf)) { return NULL; } - if (params.type_id == GPU_PRIM_NONE) { - PyErr_Format(PyExc_TypeError, exc_str_missing_arg, _keywords[0], 1); - return NULL; - } + BLI_assert(prim_type.value_found != GPU_PRIM_NONE); - if (params.py_vertbuf == NULL) { + if (py_vertbuf == NULL) { PyErr_Format(PyExc_TypeError, exc_str_missing_arg, _keywords[1], 2); return NULL; } - GPUBatch *batch = GPU_batch_create(params.type_id, - params.py_vertbuf->buf, - params.py_indexbuf ? params.py_indexbuf->elem : NULL); + GPUBatch *batch = GPU_batch_create( + prim_type.value_found, py_vertbuf->buf, py_indexbuf ? py_indexbuf->elem : NULL); BPyGPUBatch *ret = (BPyGPUBatch *)BPyGPUBatch_CreatePyObject(batch); #ifdef USE_GPU_PY_REFERENCES - ret->references = PyList_New(params.py_indexbuf ? 2 : 1); - PyList_SET_ITEM(ret->references, 0, (PyObject *)params.py_vertbuf); - Py_INCREF(params.py_vertbuf); + ret->references = PyList_New(py_indexbuf ? 2 : 1); + PyList_SET_ITEM(ret->references, 0, (PyObject *)py_vertbuf); + Py_INCREF(py_vertbuf); - if (params.py_indexbuf != NULL) { - PyList_SET_ITEM(ret->references, 1, (PyObject *)params.py_indexbuf); - Py_INCREF(params.py_indexbuf); + if (py_indexbuf != NULL) { + PyList_SET_ITEM(ret->references, 1, (PyObject *)py_indexbuf); + Py_INCREF(py_indexbuf); } PyObject_GC_Track(ret); diff --git a/source/blender/python/gpu/gpu_py_element.c b/source/blender/python/gpu/gpu_py_element.c index f43338c42d2..0e5094cbbc0 100644 --- a/source/blender/python/gpu/gpu_py_element.c +++ b/source/blender/python/gpu/gpu_py_element.c @@ -32,6 +32,7 @@ #include "../generic/py_capi_utils.h" #include "../generic/python_utildefines.h" +#include "gpu_py.h" #include "gpu_py_api.h" #include "gpu_py_element.h" /* own include */ @@ -46,10 +47,8 @@ static PyObject *pygpu_IndexBuf__tp_new(PyTypeObject *UNUSED(type), PyObject *ar const char *error_prefix = "IndexBuf.__new__"; bool ok = true; - struct { - GPUPrimType type_id; - PyObject *seq; - } params; + struct PyC_StringEnum prim_type = {bpygpu_primtype_items, GPU_PRIM_NONE}; + PyObject *seq; uint verts_per_prim; uint index_len; @@ -58,11 +57,11 @@ static PyObject *pygpu_IndexBuf__tp_new(PyTypeObject *UNUSED(type), PyObject *ar static const char *_keywords[] = {"type", "seq", NULL}; static _PyArg_Parser _parser = {"$O&O:IndexBuf.__new__", _keywords, 0}; if (!_PyArg_ParseTupleAndKeywordsFast( - args, kwds, &_parser, bpygpu_ParsePrimType, ¶ms.type_id, ¶ms.seq)) { + args, kwds, &_parser, PyC_ParseStringEnum, &prim_type, &seq)) { return NULL; } - verts_per_prim = GPU_indexbuf_primitive_len(params.type_id); + verts_per_prim = GPU_indexbuf_primitive_len(prim_type.value_found); if (verts_per_prim == -1) { PyErr_Format(PyExc_ValueError, "The argument 'type' must be " @@ -70,10 +69,10 @@ static PyObject *pygpu_IndexBuf__tp_new(PyTypeObject *UNUSED(type), PyObject *ar return NULL; } - if (PyObject_CheckBuffer(params.seq)) { + if (PyObject_CheckBuffer(seq)) { Py_buffer pybuffer; - if (PyObject_GetBuffer(params.seq, &pybuffer, PyBUF_FORMAT | PyBUF_ND) == -1) { + if (PyObject_GetBuffer(seq, &pybuffer, PyBUF_FORMAT | PyBUF_ND) == -1) { /* PyObject_GetBuffer already handles error messages. */ return NULL; } @@ -97,7 +96,7 @@ static PyObject *pygpu_IndexBuf__tp_new(PyTypeObject *UNUSED(type), PyObject *ar /* The `vertex_len` parameter is only used for asserts in the Debug build. */ /* Not very useful in python since scripts are often tested in Release build. */ /* Use `INT_MAX` instead of the actual number of vertices. */ - GPU_indexbuf_init(&builder, params.type_id, index_len, INT_MAX); + GPU_indexbuf_init(&builder, prim_type.value_found, index_len, INT_MAX); #if 0 uint *buf = pybuffer.buf; @@ -111,7 +110,7 @@ static PyObject *pygpu_IndexBuf__tp_new(PyTypeObject *UNUSED(type), PyObject *ar PyBuffer_Release(&pybuffer); } else { - PyObject *seq_fast = PySequence_Fast(params.seq, error_prefix); + PyObject *seq_fast = PySequence_Fast(seq, error_prefix); if (seq_fast == NULL) { return false; @@ -126,7 +125,7 @@ static PyObject *pygpu_IndexBuf__tp_new(PyTypeObject *UNUSED(type), PyObject *ar /* The `vertex_len` parameter is only used for asserts in the Debug build. */ /* Not very useful in python since scripts are often tested in Release build. */ /* Use `INT_MAX` instead of the actual number of vertices. */ - GPU_indexbuf_init(&builder, params.type_id, index_len, INT_MAX); + GPU_indexbuf_init(&builder, prim_type.value_found, index_len, INT_MAX); if (verts_per_prim == 1) { for (uint i = 0; i < seq_len; i++) { diff --git a/source/blender/python/gpu/gpu_py_vertex_format.c b/source/blender/python/gpu/gpu_py_vertex_format.c index 67f612f8ba3..343cf06b20a 100644 --- a/source/blender/python/gpu/gpu_py_vertex_format.c +++ b/source/blender/python/gpu/gpu_py_vertex_format.c @@ -32,115 +32,31 @@ #include "gpu_py_vertex_format.h" /* own include */ -#ifdef __BIG_ENDIAN__ -/* big endian */ -# define MAKE_ID2(c, d) ((c) << 8 | (d)) -# define MAKE_ID3(a, b, c) ((int)(a) << 24 | (int)(b) << 16 | (c) << 8) -# define MAKE_ID4(a, b, c, d) ((int)(a) << 24 | (int)(b) << 16 | (c) << 8 | (d)) -#else -/* little endian */ -# define MAKE_ID2(c, d) ((d) << 8 | (c)) -# define MAKE_ID3(a, b, c) ((int)(c) << 16 | (b) << 8 | (a)) -# define MAKE_ID4(a, b, c, d) ((int)(d) << 24 | (int)(c) << 16 | (b) << 8 | (a)) -#endif - /* -------------------------------------------------------------------- */ /** \name Enum Conversion * * Use with PyArg_ParseTuple's "O&" formatting. * \{ */ -static int pygpu_vertformat_parse_component_type(const char *str, int length) -{ - if (length == 2) { - switch (*((ushort *)str)) { - case MAKE_ID2('I', '8'): - return GPU_COMP_I8; - case MAKE_ID2('U', '8'): - return GPU_COMP_U8; - default: - break; - } - } - else if (length == 3) { - switch (*((uint *)str)) { - case MAKE_ID3('I', '1', '6'): - return GPU_COMP_I16; - case MAKE_ID3('U', '1', '6'): - return GPU_COMP_U16; - case MAKE_ID3('I', '3', '2'): - return GPU_COMP_I32; - case MAKE_ID3('U', '3', '2'): - return GPU_COMP_U32; - case MAKE_ID3('F', '3', '2'): - return GPU_COMP_F32; - case MAKE_ID3('I', '1', '0'): - return GPU_COMP_I10; - default: - break; - } - } - return -1; -} - -static int pygpu_vertformat_parse_fetch_mode(const char *str, int length) -{ -#define MATCH_ID(id) \ - if (length == strlen(STRINGIFY(id))) { \ - if (STREQ(str, STRINGIFY(id))) { \ - return GPU_FETCH_##id; \ - } \ - } \ - ((void)0) - - MATCH_ID(FLOAT); - MATCH_ID(INT); - MATCH_ID(INT_TO_FLOAT_UNIT); - MATCH_ID(INT_TO_FLOAT); -#undef MATCH_ID - - return -1; -} - -static int pygpu_ParseVertCompType(PyObject *o, void *p) -{ - Py_ssize_t length; - const char *str = PyUnicode_AsUTF8AndSize(o, &length); - - if (str == NULL) { - PyErr_Format(PyExc_ValueError, "expected a string, got %s", Py_TYPE(o)->tp_name); - return 0; - } - - const int comp_type = pygpu_vertformat_parse_component_type(str, length); - if (comp_type == -1) { - PyErr_Format(PyExc_ValueError, "unknown component type: '%s", str); - return 0; - } - - *((GPUVertCompType *)p) = comp_type; - return 1; -} - -static int pygpu_ParseVertFetchMode(PyObject *o, void *p) -{ - Py_ssize_t length; - const char *str = PyUnicode_AsUTF8AndSize(o, &length); - - if (str == NULL) { - PyErr_Format(PyExc_ValueError, "expected a string, got %s", Py_TYPE(o)->tp_name); - return 0; - } - - const int fetch_mode = pygpu_vertformat_parse_fetch_mode(str, length); - if (fetch_mode == -1) { - PyErr_Format(PyExc_ValueError, "unknown type literal: '%s'", str); - return 0; - } +static struct PyC_StringEnumItems pygpu_vertcomptype_items[] = { + {GPU_COMP_I8, "I8"}, + {GPU_COMP_U8, "U8"}, + {GPU_COMP_I16, "I16"}, + {GPU_COMP_U16, "U16"}, + {GPU_COMP_I32, "I32"}, + {GPU_COMP_U32, "U32"}, + {GPU_COMP_F32, "F32"}, + {GPU_COMP_I10, "I10"}, + {0, NULL}, +}; - (*(GPUVertFetchMode *)p) = fetch_mode; - return 1; -} +static struct PyC_StringEnumItems pygpu_vertfetchmode_items[] = { + {GPU_FETCH_FLOAT, "FLOAT"}, + {GPU_FETCH_INT, "INT"}, + {GPU_FETCH_INT_TO_FLOAT_UNIT, "INT_TO_FLOAT_UNIT"}, + {GPU_FETCH_INT_TO_FLOAT, "INT_TO_FLOAT"}, + {0, NULL}, +}; /** \} */ @@ -181,12 +97,10 @@ PyDoc_STRVAR( " :type fetch_mode: `str`\n"); static PyObject *pygpu_vertformat_attr_add(BPyGPUVertFormat *self, PyObject *args, PyObject *kwds) { - struct { - const char *id; - GPUVertCompType comp_type; - uint len; - GPUVertFetchMode fetch_mode; - } params; + const char *id; + uint len; + struct PyC_StringEnum comp_type = {pygpu_vertcomptype_items, GPU_COMP_I8}; + struct PyC_StringEnum fetch_mode = {pygpu_vertfetchmode_items, GPU_FETCH_FLOAT}; if (self->fmt.attr_len == GPU_VERT_ATTR_MAX_LEN) { PyErr_SetString(PyExc_ValueError, "Maximum attr reached " STRINGIFY(GPU_VERT_ATTR_MAX_LEN)); @@ -198,17 +112,17 @@ static PyObject *pygpu_vertformat_attr_add(BPyGPUVertFormat *self, PyObject *arg if (!_PyArg_ParseTupleAndKeywordsFast(args, kwds, &_parser, - ¶ms.id, - pygpu_ParseVertCompType, - ¶ms.comp_type, - ¶ms.len, - pygpu_ParseVertFetchMode, - ¶ms.fetch_mode)) { + &id, + PyC_ParseStringEnum, + &comp_type, + &len, + PyC_ParseStringEnum, + &fetch_mode)) { return NULL; } uint attr_id = GPU_vertformat_attr_add( - &self->fmt, params.id, params.comp_type, params.len, params.fetch_mode); + &self->fmt, id, comp_type.value_found, len, fetch_mode.value_found); return PyLong_FromLong(attr_id); } |