Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJacques Lucke <mail@jlucke.com>2018-10-05 16:10:56 +0300
committerJacques Lucke <mail@jlucke.com>2018-10-05 16:10:56 +0300
commit564d37c4b67af534b6c12d2bebbd7883c3d3817c (patch)
treeb66ffd18788459459ea38e652e002f0332dce05c /source/blender/python
parent1aae42aa8837fe5b82bc6ba5ead90583700908ad (diff)
Python API: new GPUVertFormat constructor and vbo.fill_attribute method
Reviewer: fclem Differential Revision: https://developer.blender.org/D3760
Diffstat (limited to 'source/blender/python')
-rw-r--r--source/blender/python/gpu/gpu_py_vertex_buffer.c98
-rw-r--r--source/blender/python/gpu/gpu_py_vertex_format.c180
2 files changed, 190 insertions, 88 deletions
diff --git a/source/blender/python/gpu/gpu_py_vertex_buffer.c b/source/blender/python/gpu/gpu_py_vertex_buffer.c
index 53fbbf623fa..fd4ee64c996 100644
--- a/source/blender/python/gpu/gpu_py_vertex_buffer.c
+++ b/source/blender/python/gpu/gpu_py_vertex_buffer.c
@@ -188,20 +188,28 @@ finally:
return ok;
}
-/* handy, but not used just now */
-#if 0
-static int bpygpu_find_id(const GPUVertFormat *fmt, const char *id)
+static int bpygpu_fill_attribute(GPUVertBuf *buf, int id, PyObject *py_seq_data)
{
- for (int i = 0; i < fmt->attr_len; i++) {
- for (uint j = 0; j < fmt->name_len; j++) {
- if (STREQ(fmt->attribs[i].name[j], id)) {
- return i;
- }
- }
+ if (id < 0 || id >= buf->format.attr_len) {
+ PyErr_Format(PyExc_ValueError,
+ "Format id %d out of range",
+ id);
+ return 0;
+ }
+
+ if (buf->data == NULL) {
+ PyErr_SetString(PyExc_ValueError,
+ "Can't fill, static buffer already in use");
+ return 0;
}
- return -1;
+
+ if (!bpygpu_vertbuf_fill_impl(buf, (uint)id, py_seq_data)) {
+ return 0;
+ }
+
+ return 1;
}
-#endif
+
/** \} */
@@ -218,12 +226,12 @@ static PyObject *bpygpu_VertBuf_new(PyTypeObject *UNUSED(type), PyObject *args,
uint len;
} params;
- static const char *_keywords[] = {"len", "format", NULL};
- static _PyArg_Parser _parser = {"$IO!:GPUVertBuf.__new__", _keywords, 0};
+ static const char *_keywords[] = {"format", "len", NULL};
+ static _PyArg_Parser _parser = {"O!I:GPUVertBuf.__new__", _keywords, 0};
if (!_PyArg_ParseTupleAndKeywordsFast(
args, kwds, &_parser,
- &params.len,
- &BPyGPUVertFormat_Type, &params.py_fmt))
+ &BPyGPUVertFormat_Type, &params.py_fmt,
+ &params.len))
{
return NULL;
}
@@ -235,48 +243,62 @@ static PyObject *bpygpu_VertBuf_new(PyTypeObject *UNUSED(type), PyObject *args,
return BPyGPUVertBuf_CreatePyObject(vbo);
}
-PyDoc_STRVAR(bpygpu_VertBuf_fill_doc,
-"TODO"
+PyDoc_STRVAR(bpygpu_VertBuf_fill_attribute_doc,
+"fill_attribute(identifier, data)\n"
+"\n"
+" Insert data into the buffer for a single attribute.\n"
+"\n"
+" :param identifier: Either the name or the id of the attribute.\n"
+" :type identifier: int or str\n"
+" :param data: Sequence of data that should be stored in the buffer\n"
+" :type data: sequence of individual values or tuples\n"
);
-static PyObject *bpygpu_VertBuf_fill(BPyGPUVertBuf *self, PyObject *args, PyObject *kwds)
+static PyObject *bpygpu_VertBuf_fill_attribute(BPyGPUVertBuf *self, PyObject *args, PyObject *kwds)
{
- struct {
- uint id;
- PyObject *py_seq_data;
- } params;
+ PyObject *data;
+ PyObject *identifier;
- static const char *_keywords[] = {"id", "data", NULL};
- static _PyArg_Parser _parser = {"$IO:fill", _keywords, 0};
+ static const char *_keywords[] = {"identifier", "data", NULL};
+ static _PyArg_Parser _parser = {"OO:fill_attribute", _keywords, 0};
if (!_PyArg_ParseTupleAndKeywordsFast(
args, kwds, &_parser,
- &params.id,
- &params.py_seq_data))
+ &identifier, &data))
{
return NULL;
}
- if (params.id >= self->buf->format.attr_len) {
- PyErr_Format(PyExc_ValueError,
- "Format id %d out of range",
- params.id);
- return NULL;
- }
+ int id;
- if (self->buf->data == NULL) {
- PyErr_SetString(PyExc_ValueError,
- "Can't fill, static buffer already in use");
+ if (PyLong_Check(identifier)) {
+ id = PyLong_AsLong(identifier);
+ }
+ else if (PyUnicode_Check(identifier)) {
+ const char *name = PyUnicode_AsUTF8(identifier);
+ id = GPU_vertformat_attr_id_get(&self->buf->format, name);
+ if (id == -1) {
+ PyErr_SetString(PyExc_ValueError,
+ "Unknown attribute name");
+ return NULL;
+ }
+ }
+ else {
+ PyErr_SetString(PyExc_TypeError,
+ "expected int or str type as identifier");
return NULL;
}
- if (!bpygpu_vertbuf_fill_impl(self->buf, params.id, params.py_seq_data)) {
+
+ if (!bpygpu_fill_attribute(self->buf, id, data)) {
return NULL;
}
+
Py_RETURN_NONE;
}
+
static struct PyMethodDef bpygpu_VertBuf_methods[] = {
- {"fill", (PyCFunction) bpygpu_VertBuf_fill,
- METH_VARARGS | METH_KEYWORDS, bpygpu_VertBuf_fill_doc},
+ {"fill_attribute", (PyCFunction) bpygpu_VertBuf_fill_attribute,
+ METH_VARARGS | METH_KEYWORDS, bpygpu_VertBuf_fill_attribute_doc},
{NULL, NULL, 0, NULL}
};
diff --git a/source/blender/python/gpu/gpu_py_vertex_format.c b/source/blender/python/gpu/gpu_py_vertex_format.c
index 34f6af75477..794167fab7a 100644
--- a/source/blender/python/gpu/gpu_py_vertex_format.c
+++ b/source/blender/python/gpu/gpu_py_vertex_format.c
@@ -55,79 +55,104 @@
* Use with PyArg_ParseTuple's "O&" formatting.
* \{ */
+static int bpygpu_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 bpygpu_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 bpygpu_ParseVertCompType(PyObject *o, void *p)
{
- Py_ssize_t comp_type_id_len;
- const char *comp_type_id = _PyUnicode_AsStringAndSize(o, &comp_type_id_len);
- if (comp_type_id == NULL) {
+ Py_ssize_t length;
+ const char *str = _PyUnicode_AsStringAndSize(o, &length);
+
+ if (str == NULL) {
PyErr_Format(PyExc_ValueError,
"expected a string, got %s",
Py_TYPE(o)->tp_name);
return 0;
}
- GPUVertCompType comp_type;
- if (comp_type_id_len == 2) {
- switch (*((ushort *)comp_type_id)) {
- case MAKE_ID2('I', '8'): { comp_type = GPU_COMP_I8; goto success; }
- case MAKE_ID2('U', '8'): { comp_type = GPU_COMP_U8; goto success; }
- }
- }
- else if (comp_type_id_len == 3) {
- switch (*((uint *)comp_type_id)) {
- case MAKE_ID3('I', '1', '6'): { comp_type = GPU_COMP_I16; goto success; }
- case MAKE_ID3('U', '1', '6'): { comp_type = GPU_COMP_U16; goto success; }
- case MAKE_ID3('I', '3', '2'): { comp_type = GPU_COMP_I32; goto success; }
- case MAKE_ID3('U', '3', '2'): { comp_type = GPU_COMP_U32; goto success; }
- case MAKE_ID3('F', '3', '2'): { comp_type = GPU_COMP_F32; goto success; }
- case MAKE_ID3('I', '1', '0'): { comp_type = GPU_COMP_I10; goto success; }
- }
+ int comp_type = bpygpu_parse_component_type(str, length);
+ if (comp_type == -1) {
+ PyErr_Format(PyExc_ValueError,
+ "unkown component type: '%s",
+ str);
+ return 0;
}
- PyErr_Format(PyExc_ValueError,
- "unknown type literal: '%s'",
- comp_type_id);
- return 0;
-
-success:
*((GPUVertCompType *)p) = comp_type;
return 1;
}
static int bpygpu_ParseVertFetchMode(PyObject *o, void *p)
{
- Py_ssize_t mode_id_len;
- const char *mode_id = _PyUnicode_AsStringAndSize(o, &mode_id_len);
- if (mode_id == NULL) {
+ Py_ssize_t length;
+ const char *str = _PyUnicode_AsStringAndSize(o, &length);
+
+ if (str == 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_FETCH_##id; \
- goto success; \
- } \
- } ((void)0)
- GPUVertFetchMode mode;
- MATCH_ID(FLOAT);
- MATCH_ID(INT);
- MATCH_ID(INT_TO_FLOAT_UNIT);
- MATCH_ID(INT_TO_FLOAT);
-#undef MATCH_ID
- PyErr_Format(PyExc_ValueError,
- "unknown type literal: '%s'",
- mode_id);
- return 0;
+ int fetch_mode = bpygpu_parse_fetch_mode(str, length);
+ if (fetch_mode == -1) {
+ PyErr_Format(PyExc_ValueError,
+ "unknown type literal: '%s'",
+ str);
+ return 0;
+ }
-success:
- (*(GPUVertFetchMode *)p) = mode;
+ (*(GPUVertFetchMode *)p) = fetch_mode;
return 1;
}
+static int get_default_fetch_mode(GPUVertCompType type)
+{
+ switch (type)
+ {
+ case GPU_COMP_F32: return GPU_FETCH_FLOAT;
+ default: return -1;
+ }
+}
+
/** \} */
@@ -136,16 +161,71 @@ success:
/** \name VertFormat Type
* \{ */
+static int add_attribute_simple(GPUVertFormat *format, char *name, GPUVertCompType comp_type, int length)
+{
+ if (length <= 0) {
+ PyErr_SetString(PyExc_ValueError,
+ "length of an attribute must greater than 0");
+ return 0;
+ }
+
+ int fetch_mode = get_default_fetch_mode(comp_type);
+ if (fetch_mode == -1) {
+ PyErr_SetString(PyExc_ValueError,
+ "no default fetch mode found");
+ return 0;
+ }
+
+ GPU_vertformat_attr_add(format, name, comp_type, length, fetch_mode);
+ return 1;
+}
+
+static int add_attribute_from_tuple(GPUVertFormat *format, PyObject *data)
+{
+ char *name;
+ GPUVertCompType comp_type;
+ int length;
+
+ if (!PyArg_ParseTuple(data, "sO&i", &name, bpygpu_ParseVertCompType, &comp_type, &length)) {
+ return 0;
+ }
+
+ return add_attribute_simple(format, name, comp_type, length);
+}
+
+static int insert_attributes_from_list(GPUVertFormat *format, PyObject *list)
+{
+ Py_ssize_t amount = PyList_Size(list);
+
+ for (Py_ssize_t i = 0; i < amount; i++) {
+ PyObject *element = PyList_GET_ITEM(list, i);
+ if (!PyTuple_Check(element)) {
+ PyErr_SetString(PyExc_TypeError, "expected a list of tuples");
+ return 0;
+ }
+ if (!add_attribute_from_tuple(format, element)) return 0;
+ }
+
+ return 1;
+}
+
static PyObject *bpygpu_VertFormat_new(PyTypeObject *UNUSED(type), PyObject *args, PyObject *kwds)
{
- if (PyTuple_GET_SIZE(args) || (kwds && PyDict_Size(kwds))) {
- PyErr_SetString(PyExc_TypeError,
- "VertFormat(): takes no arguments");
+
+ PyObject *format_list;
+
+ static const char *keywords[] = {"format", NULL};
+ if (!PyArg_ParseTupleAndKeywords(args, kwds, "O!", (char**)keywords, &PyList_Type, &format_list)) {
return NULL;
}
BPyGPUVertFormat *ret = (BPyGPUVertFormat *)BPyGPUVertFormat_CreatePyObject(NULL);
+ if (!insert_attributes_from_list(&ret->fmt, format_list)) {
+ Py_DecRef((PyObject *)ret);
+ return NULL;
+ }
+
return (PyObject *)ret;
}