| 
									
										
										
										
											2018-09-14 09:32:19 -03:00
										 |  |  | /*
 | 
					
						
							|  |  |  |  * ***** BEGIN GPL LICENSE BLOCK ***** | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * This program is free software; you can redistribute it and/or | 
					
						
							|  |  |  |  * modify it under the terms of the GNU General Public License | 
					
						
							|  |  |  |  * as published by the Free Software Foundation; either version 2 | 
					
						
							|  |  |  |  * of the License, or (at your option) any later version. | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * This program is distributed in the hope that it will be useful, | 
					
						
							|  |  |  |  * but WITHOUT ANY WARRANTY; without even the implied warranty of | 
					
						
							|  |  |  |  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | 
					
						
							|  |  |  |  * GNU General Public License for more details. | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * You should have received a copy of the GNU General Public License | 
					
						
							|  |  |  |  * along with this program; if not, write to the Free Software Foundation, | 
					
						
							|  |  |  |  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * ***** END GPL LICENSE BLOCK ***** | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /** \file blender/python/gpu/gpu_py_shader.c
 | 
					
						
							|  |  |  |  *  \ingroup bpygpu | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * - Use ``bpygpu_`` for local API. | 
					
						
							|  |  |  |  * - Use ``BPyGPU`` for public API. | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #include <Python.h>
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #include "BLI_utildefines.h"
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #include "GPU_shader.h"
 | 
					
						
							|  |  |  | #include "GPU_shader_interface.h"
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #include "../generic/py_capi_utils.h"
 | 
					
						
							|  |  |  | #include "../generic/python_utildefines.h"
 | 
					
						
							| 
									
										
										
										
											2018-10-23 10:17:38 +02:00
										 |  |  | #include "../mathutils/mathutils.h"
 | 
					
						
							| 
									
										
										
										
											2018-09-14 09:32:19 -03:00
										 |  |  | 
 | 
					
						
							|  |  |  | #include "gpu_py_shader.h" /* own include */
 | 
					
						
							| 
									
										
										
										
											2018-10-09 11:17:29 +02:00
										 |  |  | #include "gpu_py_vertex_format.h"
 | 
					
						
							| 
									
										
										
										
											2018-09-14 09:32:19 -03:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |  /* -------------------------------------------------------------------- */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |  /** \name Enum Conversion.
 | 
					
						
							|  |  |  |  * \{ */ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-10-09 12:06:42 -03:00
										 |  |  | static int bpygpu_ParseBultinShaderEnum(PyObject *o, void *p) | 
					
						
							| 
									
										
										
										
											2018-09-14 09:32:19 -03:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2018-10-09 12:06:42 -03:00
										 |  |  | 	Py_ssize_t mode_id_len; | 
					
						
							|  |  |  | 	const char *mode_id = _PyUnicode_AsStringAndSize(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 == (Py_ssize_t)strlen(STRINGIFY(id))) { \ | 
					
						
							|  |  |  | 		if (STREQ(mode_id, STRINGIFY(id))) { \ | 
					
						
							|  |  |  | 			mode = GPU_SHADER_##id; \ | 
					
						
							|  |  |  | 			goto success; \ | 
					
						
							|  |  |  | 		} \ | 
					
						
							|  |  |  | 	} ((void)0) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	GPUBuiltinShader mode; | 
					
						
							|  |  |  | 	MATCH_ID(2D_UNIFORM_COLOR); | 
					
						
							|  |  |  | 	MATCH_ID(2D_FLAT_COLOR); | 
					
						
							|  |  |  | 	MATCH_ID(2D_SMOOTH_COLOR); | 
					
						
							|  |  |  | 	MATCH_ID(2D_IMAGE); | 
					
						
							|  |  |  | 	MATCH_ID(3D_UNIFORM_COLOR); | 
					
						
							|  |  |  | 	MATCH_ID(3D_FLAT_COLOR); | 
					
						
							|  |  |  | 	MATCH_ID(3D_SMOOTH_COLOR); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #undef MATCH_ID
 | 
					
						
							|  |  |  | 	PyErr_Format(PyExc_ValueError, | 
					
						
							|  |  |  | 	             "unknown type literal: '%s'", | 
					
						
							|  |  |  | 	             mode_id); | 
					
						
							|  |  |  | 	return 0; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | success: | 
					
						
							|  |  |  | 	(*(GPUBuiltinShader *)p) = mode; | 
					
						
							|  |  |  | 	return 1; | 
					
						
							| 
									
										
										
										
											2018-09-14 09:32:19 -03:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-10-12 15:48:22 -03:00
										 |  |  | static int bpygpu_uniform_location_get(GPUShader *shader, const char *name, const char *error_prefix) | 
					
						
							| 
									
										
										
										
											2018-10-03 23:34:27 -03:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2018-10-12 15:48:22 -03:00
										 |  |  | 	int uniform = GPU_shader_get_uniform(shader, name); | 
					
						
							| 
									
										
										
										
											2018-10-03 23:34:27 -03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-10-12 15:48:22 -03:00
										 |  |  | 	if (uniform == -1) { | 
					
						
							|  |  |  | 		PyErr_Format(PyExc_ValueError, "%s: uniform %.32s %.32s not found", error_prefix, name); | 
					
						
							| 
									
										
										
										
											2018-10-03 23:34:27 -03:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-10-12 15:48:22 -03:00
										 |  |  | 	return uniform; | 
					
						
							| 
									
										
										
										
											2018-10-03 23:34:27 -03:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-09-14 09:32:19 -03:00
										 |  |  | /** \} */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* -------------------------------------------------------------------- */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /** \name Shader Type
 | 
					
						
							|  |  |  |  * \{ */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static PyObject *bpygpu_shader_new(PyTypeObject *UNUSED(type), PyObject *args, PyObject *kwds) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	struct { | 
					
						
							|  |  |  | 		const char *vertexcode; | 
					
						
							|  |  |  | 		const char *fragcode; | 
					
						
							|  |  |  | 		const char *geocode; | 
					
						
							|  |  |  | 		const char *libcode; | 
					
						
							|  |  |  | 		const char *defines; | 
					
						
							|  |  |  | 	} params = {0}; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-09-27 00:22:57 -03:00
										 |  |  | 	static const char *_keywords[] = { | 
					
						
							|  |  |  | 	        "vertexcode", "fragcode", "geocode", | 
					
						
							|  |  |  | 	        "libcode", "defines", NULL}; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	static _PyArg_Parser _parser = {"ss|$sss:GPUShader.__new__", _keywords, 0}; | 
					
						
							|  |  |  | 	if (!_PyArg_ParseTupleAndKeywordsFast( | 
					
						
							|  |  |  | 	        args, kwds, &_parser, | 
					
						
							| 
									
										
										
										
											2018-09-14 09:32:19 -03:00
										 |  |  | 	        ¶ms.vertexcode, ¶ms.fragcode, ¶ms.geocode, | 
					
						
							|  |  |  | 	        ¶ms.libcode, ¶ms.defines)) | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 		return NULL; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	GPUShader *shader = GPU_shader_create( | 
					
						
							|  |  |  | 	        params.vertexcode, | 
					
						
							|  |  |  | 	        params.fragcode, | 
					
						
							|  |  |  | 	        params.geocode, | 
					
						
							|  |  |  | 	        params.libcode, | 
					
						
							|  |  |  | 	        params.defines, | 
					
						
							|  |  |  | 	        NULL); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if (shader == NULL) { | 
					
						
							|  |  |  | 		PyErr_SetString(PyExc_Exception, | 
					
						
							|  |  |  | 		                "Shader Compile Error, see console for more details"); | 
					
						
							|  |  |  | 		return NULL; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-09-20 15:21:59 -03:00
										 |  |  | 	return BPyGPUShader_CreatePyObject(shader, false); | 
					
						
							| 
									
										
										
										
											2018-09-14 09:32:19 -03:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | PyDoc_STRVAR(bpygpu_shader_bind_doc, | 
					
						
							|  |  |  | ".. method:: bind()\n" | 
					
						
							|  |  |  | "\n" | 
					
						
							|  |  |  | "   Bind the Shader object.\n" | 
					
						
							|  |  |  | ); | 
					
						
							|  |  |  | static PyObject *bpygpu_shader_bind(BPyGPUShader *self) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	GPU_shader_bind(self->shader); | 
					
						
							|  |  |  | 	Py_RETURN_NONE; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | PyDoc_STRVAR(bpygpu_shader_transform_feedback_enable_doc, | 
					
						
							|  |  |  | ".. method:: transform_feedback_enable(vbo_id)\n" | 
					
						
							|  |  |  | "\n" | 
					
						
							|  |  |  | "   Start transform feedback operation.\n" | 
					
						
							|  |  |  | "\n" | 
					
						
							|  |  |  | "   :return: true if transform feedback was succesfully enabled.\n" | 
					
						
							| 
									
										
										
										
											2018-10-04 13:08:04 +10:00
										 |  |  | "   :rtype: bool\n" | 
					
						
							| 
									
										
										
										
											2018-09-14 09:32:19 -03:00
										 |  |  | ); | 
					
						
							|  |  |  | static PyObject *bpygpu_shader_transform_feedback_enable( | 
					
						
							|  |  |  |         BPyGPUShader *self, PyObject *arg) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	uint vbo_id; | 
					
						
							|  |  |  | 	if ((vbo_id = PyC_Long_AsU32(arg)) == (uint)-1) { | 
					
						
							|  |  |  | 		return NULL; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	return PyBool_FromLong(GPU_shader_transform_feedback_enable(self->shader, vbo_id)); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | PyDoc_STRVAR(bpygpu_shader_transform_feedback_disable_doc, | 
					
						
							|  |  |  | ".. method:: transform_feedback_disable()\n" | 
					
						
							|  |  |  | "\n" | 
					
						
							|  |  |  | "   Disable transform feedback.\n" | 
					
						
							|  |  |  | ); | 
					
						
							|  |  |  | static PyObject *bpygpu_transform_feedback_disable(BPyGPUShader *self) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	GPU_shader_transform_feedback_disable(self->shader); | 
					
						
							|  |  |  | 	Py_RETURN_NONE; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | PyDoc_STRVAR(bpygpu_shader_uniform_from_name_doc, | 
					
						
							|  |  |  | ".. method:: uniform_from_name(name)\n" | 
					
						
							|  |  |  | "\n" | 
					
						
							|  |  |  | "   Get uniform location by name.\n" | 
					
						
							|  |  |  | "\n" | 
					
						
							|  |  |  | "   :param name: name of the uniform variable whose location is to be queried.\n" | 
					
						
							| 
									
										
										
										
											2018-10-04 13:08:04 +10:00
										 |  |  | "   :type name: str\n" | 
					
						
							| 
									
										
										
										
											2018-09-14 09:32:19 -03:00
										 |  |  | "   :return: the location of the uniform variable.\n" | 
					
						
							| 
									
										
										
										
											2018-10-04 13:08:04 +10:00
										 |  |  | "   :rtype: int\n" | 
					
						
							| 
									
										
										
										
											2018-09-14 09:32:19 -03:00
										 |  |  | ); | 
					
						
							|  |  |  | static PyObject *bpygpu_shader_uniform_from_name( | 
					
						
							|  |  |  |         BPyGPUShader *self, PyObject *arg) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	const char *name = PyUnicode_AsUTF8(arg); | 
					
						
							|  |  |  | 	if (name == NULL) { | 
					
						
							|  |  |  | 		return NULL; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-10-12 15:48:22 -03:00
										 |  |  | 	int uniform = bpygpu_uniform_location_get( | 
					
						
							|  |  |  | 	        self->shader, name, "GPUShader.get_uniform"); | 
					
						
							| 
									
										
										
										
											2018-09-14 09:32:19 -03:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	if (uniform == -1) { | 
					
						
							|  |  |  | 		return NULL; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return PyLong_FromLong(uniform); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | PyDoc_STRVAR(bpygpu_shader_uniform_block_from_name_doc, | 
					
						
							|  |  |  | ".. method:: uniform_block_from_name(name)\n" | 
					
						
							|  |  |  | "\n" | 
					
						
							|  |  |  | "   Get uniform block location by name.\n" | 
					
						
							|  |  |  | "\n" | 
					
						
							|  |  |  | "   :param name: name of the uniform block variable whose location is to be queried.\n" | 
					
						
							| 
									
										
										
										
											2018-10-04 13:08:04 +10:00
										 |  |  | "   :type name: str\n" | 
					
						
							| 
									
										
										
										
											2018-09-14 09:32:19 -03:00
										 |  |  | "   :return: the location of the uniform block variable.\n" | 
					
						
							| 
									
										
										
										
											2018-10-04 13:08:04 +10:00
										 |  |  | "   :rtype: int\n" | 
					
						
							| 
									
										
										
										
											2018-09-14 09:32:19 -03:00
										 |  |  | ); | 
					
						
							|  |  |  | static PyObject *bpygpu_shader_uniform_block_from_name( | 
					
						
							|  |  |  |         BPyGPUShader *self, PyObject *arg) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	const char *name = PyUnicode_AsUTF8(arg); | 
					
						
							|  |  |  | 	if (name == NULL) { | 
					
						
							|  |  |  | 		return NULL; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	int uniform = GPU_shader_get_uniform_block(self->shader, name); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if (uniform == -1) { | 
					
						
							| 
									
										
										
										
											2018-10-12 15:48:22 -03:00
										 |  |  | 		PyErr_Format(PyExc_ValueError, | 
					
						
							|  |  |  | 		             "GPUShader.get_uniform_block: uniform %.32s not found", name); | 
					
						
							| 
									
										
										
										
											2018-09-14 09:32:19 -03:00
										 |  |  | 		return NULL; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return PyLong_FromLong(uniform); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static bool bpygpu_shader_uniform_vector_imp( | 
					
						
							|  |  |  |         PyObject *args, int elem_size, | 
					
						
							|  |  |  |         int *r_location, int *r_length, int *r_count, Py_buffer *r_pybuffer) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	PyObject *buffer; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	*r_count = 1; | 
					
						
							|  |  |  | 	if (!PyArg_ParseTuple( | 
					
						
							|  |  |  | 	        args, "iOi|i:GPUShader.uniform_vector_*", | 
					
						
							|  |  |  | 	        r_location, &buffer, r_length, r_count)) | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 		return false; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if (PyObject_GetBuffer(buffer, r_pybuffer, PyBUF_SIMPLE) == -1) { | 
					
						
							|  |  |  | 		/* PyObject_GetBuffer raise a PyExc_BufferError */ | 
					
						
							|  |  |  | 		return false; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if (r_pybuffer->len != (*r_length * *r_count * elem_size)) { | 
					
						
							|  |  |  | 		PyErr_SetString( | 
					
						
							|  |  |  | 		        PyExc_BufferError, | 
					
						
							|  |  |  | 		        "GPUShader.uniform_vector_*: buffer size does not match."); | 
					
						
							|  |  |  | 		return false; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return true; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | PyDoc_STRVAR(bpygpu_shader_uniform_vector_float_doc, | 
					
						
							|  |  |  | ".. method:: uniform_vector_float(location, buffer, length, count)\n" | 
					
						
							|  |  |  | "\n" | 
					
						
							|  |  |  | "   Set the buffer to fill the uniform.\n" | 
					
						
							|  |  |  | "\n" | 
					
						
							|  |  |  | "   :param location: location of the uniform variable to be modified.\n" | 
					
						
							| 
									
										
										
										
											2018-10-04 13:08:04 +10:00
										 |  |  | "   :type location: int\n" | 
					
						
							| 
									
										
										
										
											2018-09-15 08:00:47 +10:00
										 |  |  | "   :param buffer: buffer object with format float.\n" | 
					
						
							| 
									
										
										
										
											2018-10-04 13:08:04 +10:00
										 |  |  | "   :type buffer: buffer object\n" | 
					
						
							| 
									
										
										
										
											2018-09-15 08:00:47 +10:00
										 |  |  | "   :param length:\n" | 
					
						
							|  |  |  | "      size of the uniform data type:\n" | 
					
						
							|  |  |  | "\n" | 
					
						
							|  |  |  | "      - 1: float\n" | 
					
						
							|  |  |  | "      - 2: vec2 or float[2]\n" | 
					
						
							|  |  |  | "      - 3: vec3 or float[3]\n" | 
					
						
							|  |  |  | "      - 4: vec4 or float[4]\n" | 
					
						
							|  |  |  | "      - 9: mat3\n" | 
					
						
							|  |  |  | "      - 16: mat4\n" | 
					
						
							|  |  |  | "\n" | 
					
						
							| 
									
										
										
										
											2018-10-04 13:08:04 +10:00
										 |  |  | "   :type length: int\n" | 
					
						
							|  |  |  | "   :param count: specifies the number of elements, vector or matrices that are to be modified.\n" | 
					
						
							|  |  |  | "   :type count: int\n" | 
					
						
							| 
									
										
										
										
											2018-09-14 09:32:19 -03:00
										 |  |  | ); | 
					
						
							|  |  |  | static PyObject *bpygpu_shader_uniform_vector_float( | 
					
						
							|  |  |  |         BPyGPUShader *self, PyObject *args) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	int location, length, count; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	Py_buffer pybuffer; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if (!bpygpu_shader_uniform_vector_imp( | 
					
						
							|  |  |  | 	        args, sizeof(float), | 
					
						
							|  |  |  | 	        &location, &length, &count, &pybuffer)) | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 		return NULL; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	GPU_shader_uniform_vector( | 
					
						
							|  |  |  | 	        self->shader, location, length, | 
					
						
							|  |  |  | 	        count, pybuffer.buf); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	PyBuffer_Release(&pybuffer); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	Py_RETURN_NONE; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | PyDoc_STRVAR(bpygpu_shader_uniform_vector_int_doc, | 
					
						
							|  |  |  | ".. method:: uniform_vector_int(location, buffer, length, count)\n" | 
					
						
							|  |  |  | "\n" | 
					
						
							| 
									
										
										
										
											2018-09-15 08:00:47 +10:00
										 |  |  | "   See GPUShader.uniform_vector_float(...) description.\n" | 
					
						
							| 
									
										
										
										
											2018-09-14 09:32:19 -03:00
										 |  |  | ); | 
					
						
							|  |  |  | static PyObject *bpygpu_shader_uniform_vector_int( | 
					
						
							|  |  |  |         BPyGPUShader *self, PyObject *args) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	int location, length, count; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	Py_buffer pybuffer; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if (!bpygpu_shader_uniform_vector_imp( | 
					
						
							|  |  |  | 	        args, sizeof(int), | 
					
						
							|  |  |  | 	        &location, &length, &count, &pybuffer)) | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 		return NULL; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	GPU_shader_uniform_vector_int( | 
					
						
							|  |  |  | 	        self->shader, location, length, | 
					
						
							|  |  |  | 	        count, pybuffer.buf); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	PyBuffer_Release(&pybuffer); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	Py_RETURN_NONE; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-10-03 23:34:27 -03:00
										 |  |  | PyDoc_STRVAR(bpygpu_shader_uniform_bool_doc, | 
					
						
							|  |  |  | ".. method:: uniform_bool(name, seq)\n" | 
					
						
							|  |  |  | "\n" | 
					
						
							|  |  |  | "   Specify the value of a uniform variable for the current program object.\n" | 
					
						
							|  |  |  | "\n" | 
					
						
							|  |  |  | "   :param name: name of the uniform variable whose location is to be queried.\n" | 
					
						
							| 
									
										
										
										
											2018-10-04 13:08:04 +10:00
										 |  |  | "   :type name: str\n" | 
					
						
							| 
									
										
										
										
											2018-10-03 23:34:27 -03:00
										 |  |  | "   :param seq: values that will be used to update the specified uniform variable.\n" | 
					
						
							|  |  |  | "   :type seq: sequence of bools\n" | 
					
						
							|  |  |  | ); | 
					
						
							|  |  |  | static PyObject *bpygpu_shader_uniform_bool( | 
					
						
							|  |  |  |         BPyGPUShader *self, PyObject *args) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	const char *error_prefix = "GPUShader.uniform_bool"; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	struct { | 
					
						
							|  |  |  | 		const char *id; | 
					
						
							|  |  |  | 		PyObject *seq; | 
					
						
							|  |  |  | 	} params; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if (!PyArg_ParseTuple( | 
					
						
							|  |  |  | 	        args, "sO:GPUShader.uniform_bool", | 
					
						
							|  |  |  | 	        ¶ms.id, ¶ms.seq)) | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 		return NULL; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	int values[4]; | 
					
						
							|  |  |  | 	int length; | 
					
						
							|  |  |  | 	int ret; | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 		PyObject *seq_fast = PySequence_Fast(params.seq, error_prefix); | 
					
						
							|  |  |  | 		if (seq_fast == NULL) { | 
					
						
							| 
									
										
										
										
											2018-10-04 13:48:08 -03:00
										 |  |  | 			PyErr_Format(PyExc_TypeError, | 
					
						
							|  |  |  | 			             "%s: expected a sequence, got %s", | 
					
						
							|  |  |  | 			             error_prefix, Py_TYPE(params.seq)->tp_name); | 
					
						
							| 
									
										
										
										
											2018-10-03 23:34:27 -03:00
										 |  |  | 			ret = -1; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		else { | 
					
						
							| 
									
										
										
										
											2018-10-04 13:48:08 -03:00
										 |  |  | 			length = PySequence_Fast_GET_SIZE(seq_fast); | 
					
						
							| 
									
										
										
										
											2018-10-03 23:34:27 -03:00
										 |  |  | 			if (length == 0 || length > 4) { | 
					
						
							|  |  |  | 				PyErr_Format(PyExc_TypeError, | 
					
						
							|  |  |  | 				             "%s: invalid sequence length. expected 1..4, got %d", | 
					
						
							|  |  |  | 				             error_prefix, length); | 
					
						
							|  |  |  | 				ret = -1; | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 			else { | 
					
						
							|  |  |  | 				ret = PyC_AsArray_FAST( | 
					
						
							|  |  |  | 				        values, seq_fast, length, &PyLong_Type, | 
					
						
							|  |  |  | 				        false, error_prefix); | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 			Py_DECREF(seq_fast); | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	if (ret == -1) { | 
					
						
							|  |  |  | 		return NULL; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-10-12 15:48:22 -03:00
										 |  |  | 	const int location = bpygpu_uniform_location_get( | 
					
						
							|  |  |  | 	        self->shader, params.id, error_prefix); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-10-03 23:34:27 -03:00
										 |  |  | 	if (location == -1) { | 
					
						
							|  |  |  | 		return NULL; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	GPU_shader_uniform_vector_int(self->shader, location, length, 1, values); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	Py_RETURN_NONE; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-09-20 19:51:02 +00:00
										 |  |  | PyDoc_STRVAR(bpygpu_shader_uniform_float_doc, | 
					
						
							| 
									
										
										
										
											2018-10-23 10:17:38 +02:00
										 |  |  | ".. method:: uniform_float(name, value)\n" | 
					
						
							| 
									
										
										
										
											2018-10-03 23:34:27 -03:00
										 |  |  | "\n" | 
					
						
							|  |  |  | "   Specify the value of a uniform variable for the current program object.\n" | 
					
						
							|  |  |  | "\n" | 
					
						
							|  |  |  | "   :param name: name of the uniform variable whose location is to be queried.\n" | 
					
						
							| 
									
										
										
										
											2018-10-04 13:08:04 +10:00
										 |  |  | "   :type name: str\n" | 
					
						
							| 
									
										
										
										
											2018-10-23 10:17:38 +02:00
										 |  |  | "   :param value: values that will be used to update the specified uniform variable.\n" | 
					
						
							|  |  |  | "   :type value: single number or sequence of numbers\n" | 
					
						
							| 
									
										
										
										
											2018-09-20 19:51:02 +00:00
										 |  |  | ); | 
					
						
							|  |  |  | static PyObject *bpygpu_shader_uniform_float( | 
					
						
							| 
									
										
										
										
											2018-10-03 23:34:27 -03:00
										 |  |  |         BPyGPUShader *self, PyObject *args) | 
					
						
							| 
									
										
										
										
											2018-09-20 19:51:02 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2018-10-03 23:34:27 -03:00
										 |  |  | 	const char *error_prefix = "GPUShader.uniform_float"; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	struct { | 
					
						
							|  |  |  | 		const char *id; | 
					
						
							|  |  |  | 		PyObject *seq; | 
					
						
							|  |  |  | 	} params; | 
					
						
							| 
									
										
										
										
											2018-09-20 19:51:02 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	if (!PyArg_ParseTuple( | 
					
						
							| 
									
										
										
										
											2018-10-03 23:34:27 -03:00
										 |  |  | 	        args, "sO:GPUShader.uniform_float", | 
					
						
							|  |  |  | 	        ¶ms.id, ¶ms.seq)) | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 		return NULL; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	float values[16]; | 
					
						
							|  |  |  | 	int length; | 
					
						
							| 
									
										
										
										
											2018-10-23 10:17:38 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	if (PyFloat_Check(params.seq)) { | 
					
						
							|  |  |  | 		values[0] = (float)PyFloat_AsDouble(params.seq); | 
					
						
							|  |  |  | 		length = 1; | 
					
						
							| 
									
										
										
										
											2018-10-03 23:34:27 -03:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2018-10-23 10:17:38 +02:00
										 |  |  | 	else if (PyLong_Check(params.seq)) { | 
					
						
							|  |  |  | 		values[0] = (float)PyLong_AsDouble(params.seq); | 
					
						
							|  |  |  | 		length = 1; | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2018-10-24 18:45:47 +11:00
										 |  |  | 	else if (MatrixObject_Check(params.seq)) { | 
					
						
							|  |  |  | 		MatrixObject *mat = (MatrixObject *)params.seq; | 
					
						
							|  |  |  | 		if (BaseMath_ReadCallback(mat) == -1) { | 
					
						
							|  |  |  | 			return NULL; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		if ((mat->num_row != mat->num_col) || !ELEM(mat->num_row, 3, 4)) { | 
					
						
							|  |  |  | 			PyErr_SetString(PyExc_ValueError, | 
					
						
							|  |  |  | 			                "Expected 3x3 or 4x4 matrix"); | 
					
						
							|  |  |  | 			return NULL; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		length = mat->num_row * mat->num_col; | 
					
						
							|  |  |  | 		memcpy(values, mat->matrix, sizeof(float) * length); | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2018-10-23 10:17:38 +02:00
										 |  |  | 	else { | 
					
						
							|  |  |  | 		length = mathutils_array_parse(values, 2, 16, params.seq, ""); | 
					
						
							| 
									
										
										
										
											2018-10-24 18:45:47 +11:00
										 |  |  | 		if (length == -1) { | 
					
						
							|  |  |  | 			return NULL; | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2018-10-23 10:17:38 +02:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if (!ELEM(length, 1, 2, 3, 4, 9, 16)) { | 
					
						
							|  |  |  | 		PyErr_SetString(PyExc_TypeError, | 
					
						
							|  |  |  | 		                "Expected a single float or a sequence of floats of length 1..4, 9 or 16."); | 
					
						
							| 
									
										
										
										
											2018-10-03 23:34:27 -03:00
										 |  |  | 		return NULL; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-10-12 15:48:22 -03:00
										 |  |  | 	const int location = bpygpu_uniform_location_get( | 
					
						
							|  |  |  | 	        self->shader, params.id, error_prefix); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-10-03 23:34:27 -03:00
										 |  |  | 	if (location == -1) { | 
					
						
							| 
									
										
										
										
											2018-09-20 19:51:02 +00:00
										 |  |  | 		return NULL; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-10-03 23:34:27 -03:00
										 |  |  | 	GPU_shader_uniform_vector(self->shader, location, length, 1, values); | 
					
						
							| 
									
										
										
										
											2018-09-20 19:51:02 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	Py_RETURN_NONE; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-09-14 09:32:19 -03:00
										 |  |  | PyDoc_STRVAR(bpygpu_shader_uniform_int_doc, | 
					
						
							| 
									
										
										
										
											2018-10-03 23:34:27 -03:00
										 |  |  | ".. method:: uniform_int(name, seq)\n" | 
					
						
							| 
									
										
										
										
											2018-09-14 09:32:19 -03:00
										 |  |  | "\n" | 
					
						
							| 
									
										
										
										
											2018-10-03 23:34:27 -03:00
										 |  |  | "   Specify the value of a uniform variable for the current program object.\n" | 
					
						
							| 
									
										
										
										
											2018-09-14 09:32:19 -03:00
										 |  |  | "\n" | 
					
						
							| 
									
										
										
										
											2018-10-03 23:34:27 -03:00
										 |  |  | "   :param name: name of the uniform variable whose location is to be queried.\n" | 
					
						
							| 
									
										
										
										
											2018-10-04 13:08:04 +10:00
										 |  |  | "   :type name: str\n" | 
					
						
							| 
									
										
										
										
											2018-10-03 23:34:27 -03:00
										 |  |  | "   :param seq: values that will be used to update the specified uniform variable.\n" | 
					
						
							|  |  |  | "   :type seq: sequence of numbers\n" | 
					
						
							| 
									
										
										
										
											2018-09-14 09:32:19 -03:00
										 |  |  | ); | 
					
						
							|  |  |  | static PyObject *bpygpu_shader_uniform_int( | 
					
						
							|  |  |  |         BPyGPUShader *self, PyObject *args) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2018-10-03 23:34:27 -03:00
										 |  |  | 	const char *error_prefix = "GPUShader.uniform_int"; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	struct { | 
					
						
							|  |  |  | 		const char *id; | 
					
						
							|  |  |  | 		PyObject *seq; | 
					
						
							|  |  |  | 	} params; | 
					
						
							| 
									
										
										
										
											2018-09-14 09:32:19 -03:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	if (!PyArg_ParseTuple( | 
					
						
							| 
									
										
										
										
											2018-10-03 23:34:27 -03:00
										 |  |  | 	        args, "sO:GPUShader.uniform_int", | 
					
						
							|  |  |  | 	        ¶ms.id, ¶ms.seq)) | 
					
						
							| 
									
										
										
										
											2018-09-14 09:32:19 -03:00
										 |  |  | 	{ | 
					
						
							|  |  |  | 		return NULL; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-10-03 23:34:27 -03:00
										 |  |  | 	int values[4]; | 
					
						
							|  |  |  | 	int length; | 
					
						
							|  |  |  | 	int ret; | 
					
						
							| 
									
										
										
										
											2018-10-26 11:59:49 +11:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	if (PyLong_Check(params.seq)) { | 
					
						
							|  |  |  | 		values[0] = PyC_Long_AsI32(params.seq); | 
					
						
							|  |  |  | 		length = 1; | 
					
						
							| 
									
										
										
										
											2018-10-28 17:22:26 +01:00
										 |  |  | 		ret = 0; | 
					
						
							| 
									
										
										
										
											2018-10-26 11:59:49 +11:00
										 |  |  | 	} | 
					
						
							|  |  |  | 	else { | 
					
						
							| 
									
										
										
										
											2018-10-03 23:34:27 -03:00
										 |  |  | 		PyObject *seq_fast = PySequence_Fast(params.seq, error_prefix); | 
					
						
							|  |  |  | 		if (seq_fast == NULL) { | 
					
						
							| 
									
										
										
										
											2018-10-04 13:48:08 -03:00
										 |  |  | 			PyErr_Format(PyExc_TypeError, | 
					
						
							|  |  |  | 			             "%s: expected a sequence, got %s", | 
					
						
							|  |  |  | 			             error_prefix, Py_TYPE(params.seq)->tp_name); | 
					
						
							| 
									
										
										
										
											2018-10-03 23:34:27 -03:00
										 |  |  | 			ret = -1; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		else { | 
					
						
							| 
									
										
										
										
											2018-10-04 13:48:08 -03:00
										 |  |  | 			length = PySequence_Fast_GET_SIZE(seq_fast); | 
					
						
							| 
									
										
										
										
											2018-10-03 23:34:27 -03:00
										 |  |  | 			if (length == 0 || length > 4) { | 
					
						
							|  |  |  | 				PyErr_Format(PyExc_TypeError, | 
					
						
							|  |  |  | 				             "%s: invalid sequence length. expected 1..4, got %d", | 
					
						
							|  |  |  | 				             error_prefix, length); | 
					
						
							|  |  |  | 				ret = -1; | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 			else { | 
					
						
							|  |  |  | 				ret = PyC_AsArray_FAST( | 
					
						
							|  |  |  | 				        values, seq_fast, length, &PyLong_Type, | 
					
						
							|  |  |  | 				        false, error_prefix); | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 			Py_DECREF(seq_fast); | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	if (ret == -1) { | 
					
						
							|  |  |  | 		return NULL; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-10-12 15:48:22 -03:00
										 |  |  | 	const int location = bpygpu_uniform_location_get( | 
					
						
							|  |  |  | 	        self->shader, params.id, error_prefix); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-10-03 23:34:27 -03:00
										 |  |  | 	if (location == -1) { | 
					
						
							|  |  |  | 		return NULL; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	GPU_shader_uniform_vector_int(self->shader, location, length, 1, values); | 
					
						
							| 
									
										
										
										
											2018-09-14 09:32:19 -03:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	Py_RETURN_NONE; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | PyDoc_STRVAR(bpygpu_shader_attr_from_name_doc, | 
					
						
							|  |  |  | ".. method:: attr_from_name(name)\n" | 
					
						
							|  |  |  | "\n" | 
					
						
							|  |  |  | "   Get attribute location by name.\n" | 
					
						
							|  |  |  | "\n" | 
					
						
							|  |  |  | "   :param name: the name of the attribute variable whose location is to be queried.\n" | 
					
						
							| 
									
										
										
										
											2018-10-04 13:08:04 +10:00
										 |  |  | "   :type name: str\n" | 
					
						
							| 
									
										
										
										
											2018-09-14 09:32:19 -03:00
										 |  |  | "   :return: the location of an attribute variable.\n" | 
					
						
							| 
									
										
										
										
											2018-10-04 13:08:04 +10:00
										 |  |  | "   :rtype: int\n" | 
					
						
							| 
									
										
										
										
											2018-09-14 09:32:19 -03:00
										 |  |  | ); | 
					
						
							|  |  |  | static PyObject *bpygpu_shader_attr_from_name( | 
					
						
							|  |  |  |         BPyGPUShader *self, PyObject *arg) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	const char *name = PyUnicode_AsUTF8(arg); | 
					
						
							|  |  |  | 	if (name == NULL) { | 
					
						
							|  |  |  | 		return NULL; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-10-23 10:49:36 +11:00
										 |  |  | 	int attr = GPU_shader_get_attribute(self->shader, name); | 
					
						
							| 
									
										
										
										
											2018-09-14 09:32:19 -03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-10-23 10:49:36 +11:00
										 |  |  | 	if (attr == -1) { | 
					
						
							| 
									
										
										
										
											2018-10-12 15:48:22 -03:00
										 |  |  | 		PyErr_Format(PyExc_ValueError, | 
					
						
							|  |  |  | 		             "GPUShader.attr_from_name: attribute %.32s not found", name); | 
					
						
							| 
									
										
										
										
											2018-09-14 09:32:19 -03:00
										 |  |  | 		return NULL; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-10-23 10:49:36 +11:00
										 |  |  | 	return PyLong_FromLong(attr); | 
					
						
							| 
									
										
										
										
											2018-09-14 09:32:19 -03:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-10-09 11:17:29 +02:00
										 |  |  | PyDoc_STRVAR(bpygpu_shader_calc_format_doc, | 
					
						
							|  |  |  | ".. method:: calc_format()\n" | 
					
						
							|  |  |  | "\n" | 
					
						
							|  |  |  | "   Build a new format based on the attributes of the shader.\n" | 
					
						
							|  |  |  | "\n" | 
					
						
							|  |  |  | "   :return: vertex attribute format for the shader\n" | 
					
						
							|  |  |  | "   :rtype: GPUVertFormat\n" | 
					
						
							|  |  |  | ); | 
					
						
							|  |  |  | static PyObject *bpygpu_shader_calc_format(BPyGPUShader *self, PyObject *UNUSED(arg)) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	BPyGPUVertFormat *ret = (BPyGPUVertFormat *)BPyGPUVertFormat_CreatePyObject(NULL); | 
					
						
							|  |  |  | 	GPU_vertformat_from_interface(&ret->fmt, GPU_shader_get_interface(self->shader)); | 
					
						
							|  |  |  | 	return (PyObject *)ret; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-09-14 09:32:19 -03:00
										 |  |  | static struct PyMethodDef bpygpu_shader_methods[] = { | 
					
						
							|  |  |  | 	{"bind", (PyCFunction)bpygpu_shader_bind, | 
					
						
							|  |  |  | 	 METH_NOARGS, bpygpu_shader_bind_doc}, | 
					
						
							|  |  |  | 	{"transform_feedback_enable", | 
					
						
							|  |  |  | 	 (PyCFunction)bpygpu_shader_transform_feedback_enable, | 
					
						
							|  |  |  | 	 METH_O, bpygpu_shader_transform_feedback_enable_doc}, | 
					
						
							|  |  |  | 	{"transform_feedback_disable", | 
					
						
							|  |  |  | 	 (PyCFunction)bpygpu_transform_feedback_disable, | 
					
						
							|  |  |  | 	 METH_NOARGS, bpygpu_shader_transform_feedback_disable_doc}, | 
					
						
							|  |  |  | 	{"uniform_from_name", | 
					
						
							|  |  |  | 	 (PyCFunction)bpygpu_shader_uniform_from_name, | 
					
						
							|  |  |  | 	 METH_O, bpygpu_shader_uniform_from_name_doc}, | 
					
						
							|  |  |  | 	{"uniform_block_from_name", | 
					
						
							|  |  |  | 	 (PyCFunction)bpygpu_shader_uniform_block_from_name, | 
					
						
							|  |  |  | 	 METH_O, bpygpu_shader_uniform_block_from_name_doc}, | 
					
						
							|  |  |  | 	{"uniform_vector_float", | 
					
						
							|  |  |  | 	 (PyCFunction)bpygpu_shader_uniform_vector_float, | 
					
						
							|  |  |  | 	 METH_VARARGS, bpygpu_shader_uniform_vector_float_doc}, | 
					
						
							|  |  |  | 	{"uniform_vector_int", | 
					
						
							|  |  |  | 	 (PyCFunction)bpygpu_shader_uniform_vector_int, | 
					
						
							|  |  |  | 	 METH_VARARGS, bpygpu_shader_uniform_vector_int_doc}, | 
					
						
							| 
									
										
										
										
											2018-10-03 23:34:27 -03:00
										 |  |  | 	{"uniform_bool", | 
					
						
							|  |  |  | 	 (PyCFunction)bpygpu_shader_uniform_bool, | 
					
						
							|  |  |  | 	 METH_VARARGS, bpygpu_shader_uniform_bool_doc}, | 
					
						
							| 
									
										
										
										
											2018-09-20 19:51:02 +00:00
										 |  |  | 	{"uniform_float", | 
					
						
							|  |  |  | 	 (PyCFunction)bpygpu_shader_uniform_float, | 
					
						
							|  |  |  | 	 METH_VARARGS, bpygpu_shader_uniform_float_doc}, | 
					
						
							| 
									
										
										
										
											2018-09-14 09:32:19 -03:00
										 |  |  | 	{"uniform_int", | 
					
						
							|  |  |  | 	 (PyCFunction)bpygpu_shader_uniform_int, | 
					
						
							|  |  |  | 	 METH_VARARGS, bpygpu_shader_uniform_int_doc}, | 
					
						
							|  |  |  | 	{"attr_from_name", | 
					
						
							|  |  |  | 	 (PyCFunction)bpygpu_shader_attr_from_name, | 
					
						
							|  |  |  | 	 METH_O, bpygpu_shader_attr_from_name_doc}, | 
					
						
							| 
									
										
										
										
											2018-10-09 11:17:29 +02:00
										 |  |  | 	{"format_calc", | 
					
						
							|  |  |  | 	 (PyCFunction)bpygpu_shader_calc_format, | 
					
						
							|  |  |  | 	 METH_NOARGS, bpygpu_shader_calc_format_doc}, | 
					
						
							| 
									
										
										
										
											2018-09-14 09:32:19 -03:00
										 |  |  | 	{NULL, NULL, 0, NULL} | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-10-03 23:34:27 -03:00
										 |  |  | PyDoc_STRVAR(bpygpu_shader_program_doc, | 
					
						
							|  |  |  | "The name of the program object for use by the OpenGL API (read-only).\n\n:type: int" | 
					
						
							|  |  |  | ); | 
					
						
							|  |  |  | static PyObject *bpygpu_shader_program_get(BPyGPUShader *self, void *UNUSED(closure)) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	return PyLong_FromLong(GPU_shader_get_program(self->shader)); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-09-14 09:32:19 -03:00
										 |  |  | static PyGetSetDef bpygpu_shader_getseters[] = { | 
					
						
							| 
									
										
										
										
											2018-10-28 17:22:26 +01:00
										 |  |  | 	{(char *)"program", | 
					
						
							| 
									
										
										
										
											2018-09-14 09:32:19 -03:00
										 |  |  | 	 (getter)bpygpu_shader_program_get, (setter)NULL, | 
					
						
							|  |  |  | 	 bpygpu_shader_program_doc, NULL}, | 
					
						
							|  |  |  | 	{NULL, NULL, NULL, NULL, NULL} /* Sentinel */ | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static void bpygpu_shader_dealloc(BPyGPUShader *self) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2018-09-20 15:21:59 -03:00
										 |  |  | 	if (self->is_builtin == false) { | 
					
						
							|  |  |  | 		GPU_shader_free(self->shader); | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2018-09-14 09:32:19 -03:00
										 |  |  | 	Py_TYPE(self)->tp_free((PyObject *)self); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | PyDoc_STRVAR(bpygpu_shader_doc, | 
					
						
							|  |  |  | "GPUShader(vertexcode, fragcode, geocode=None, libcode=None, defines=None)\n" | 
					
						
							|  |  |  | "\n" | 
					
						
							|  |  |  | "GPUShader combines multiple GLSL shaders into a program used for drawing.\n" | 
					
						
							|  |  |  | "It must contain a vertex and fragment shaders, with an optional geometry shader.\n" | 
					
						
							|  |  |  | "\n" | 
					
						
							|  |  |  | "The GLSL #version directive is automatically included at the top of shaders, and set to 330.\n" | 
					
						
							|  |  |  | "\n" | 
					
						
							|  |  |  | "Some preprocessor directives are automatically added according to the Operating System or availability.\n" | 
					
						
							|  |  |  | "\n" | 
					
						
							| 
									
										
										
										
											2018-09-15 08:00:47 +10:00
										 |  |  | "These are::\n" | 
					
						
							|  |  |  | "\n" | 
					
						
							|  |  |  | "   \"#define GPU_ATI\\n\"\n" | 
					
						
							|  |  |  | "   \"#define GPU_NVIDIA\\n\"\n" | 
					
						
							|  |  |  | "   \"#define GPU_INTEL\\n\"\n" | 
					
						
							|  |  |  | "\n" | 
					
						
							|  |  |  | "The following extensions are enabled by default if supported by the GPU::\n" | 
					
						
							|  |  |  | "\n" | 
					
						
							|  |  |  | "   \"#extension GL_ARB_texture_gather: enable\\n\"\n" | 
					
						
							|  |  |  | "   \"#extension GL_ARB_texture_query_lod: enable\\n\"\n" | 
					
						
							| 
									
										
										
										
											2018-09-14 09:32:19 -03:00
										 |  |  | "\n" | 
					
						
							|  |  |  | "To debug shaders, use the --debug-gpu-shaders command line option" | 
					
						
							|  |  |  | " to see full GLSL shader compilation and linking errors.\n" | 
					
						
							|  |  |  | "\n" | 
					
						
							|  |  |  | "   :param vertexcode: vertex Shader Code.\n" | 
					
						
							| 
									
										
										
										
											2018-10-04 13:08:04 +10:00
										 |  |  | "   :type vertexcode: str\n" | 
					
						
							| 
									
										
										
										
											2018-09-14 09:32:19 -03:00
										 |  |  | "   :param fragcode: fragment Shader Code.\n" | 
					
						
							| 
									
										
										
										
											2018-10-04 13:08:04 +10:00
										 |  |  | "   :type value: str\n" | 
					
						
							| 
									
										
										
										
											2018-09-14 09:32:19 -03:00
										 |  |  | "   :param geocode: geometry Shader Code.\n" | 
					
						
							| 
									
										
										
										
											2018-10-04 13:08:04 +10:00
										 |  |  | "   :type value: str\n" | 
					
						
							| 
									
										
										
										
											2018-09-14 09:32:19 -03:00
										 |  |  | "   :param libcode: code with functions and presets to be shared between shaders.\n" | 
					
						
							| 
									
										
										
										
											2018-10-04 13:08:04 +10:00
										 |  |  | "   :type value: str\n" | 
					
						
							| 
									
										
										
										
											2018-09-14 09:32:19 -03:00
										 |  |  | "   :param defines: preprocessor directives.\n" | 
					
						
							| 
									
										
										
										
											2018-10-04 13:08:04 +10:00
										 |  |  | "   :type value: str\n" | 
					
						
							| 
									
										
										
										
											2018-09-14 09:32:19 -03:00
										 |  |  | ); | 
					
						
							|  |  |  | PyTypeObject BPyGPUShader_Type = { | 
					
						
							|  |  |  | 	PyVarObject_HEAD_INIT(NULL, 0) | 
					
						
							|  |  |  | 	.tp_name = "GPUShader", | 
					
						
							|  |  |  | 	.tp_basicsize = sizeof(BPyGPUShader), | 
					
						
							|  |  |  | 	.tp_dealloc = (destructor)bpygpu_shader_dealloc, | 
					
						
							|  |  |  | 	.tp_flags = Py_TPFLAGS_DEFAULT, | 
					
						
							|  |  |  | 	.tp_doc = bpygpu_shader_doc, | 
					
						
							|  |  |  | 	.tp_methods = bpygpu_shader_methods, | 
					
						
							|  |  |  | 	.tp_getset = bpygpu_shader_getseters, | 
					
						
							|  |  |  | 	.tp_new = bpygpu_shader_new, | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /** \} */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* -------------------------------------------------------------------- */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /** \name gpu.shader Module API
 | 
					
						
							|  |  |  |  * \{ */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | PyDoc_STRVAR(bpygpu_shader_unbind_doc, | 
					
						
							|  |  |  | ".. function:: unbind()\n" | 
					
						
							|  |  |  | "\n" | 
					
						
							|  |  |  | "   Unbind the bound shader object.\n" | 
					
						
							|  |  |  | ); | 
					
						
							|  |  |  | static PyObject *bpygpu_shader_unbind(BPyGPUShader *UNUSED(self)) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	GPU_shader_unbind(); | 
					
						
							|  |  |  | 	Py_RETURN_NONE; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | PyDoc_STRVAR(bpygpu_shader_from_builtin_doc, | 
					
						
							| 
									
										
										
										
											2018-10-22 15:01:25 +02:00
										 |  |  | ".. function:: from_builtin(shader_name)\n" | 
					
						
							| 
									
										
										
										
											2018-10-09 12:18:28 -03:00
										 |  |  | "\n" | 
					
						
							| 
									
										
										
										
											2018-10-30 11:38:42 -03:00
										 |  |  | "Shaders that are embedded in the blender internal code.\n" | 
					
						
							|  |  |  | "They all read the uniform 'mat4 ModelViewProjectionMatrix', which can be edited by the 'gpu.matrix' module.\n" | 
					
						
							|  |  |  | "For more details, you can check the shader code with the function 'gpu.shader.code_from_builtin';\n" | 
					
						
							|  |  |  | "\n" | 
					
						
							| 
									
										
										
										
											2018-10-09 12:18:28 -03:00
										 |  |  | "   :param shader_name: One of these builtin shader names: {\n" | 
					
						
							|  |  |  | "       '2D_UNIFORM_COLOR',\n" | 
					
						
							|  |  |  | "       '2D_FLAT_COLOR',\n" | 
					
						
							|  |  |  | "       '2D_SMOOTH_COLOR',\n" | 
					
						
							|  |  |  | "       '2D_IMAGE',\n" | 
					
						
							|  |  |  | "       '3D_UNIFORM_COLOR',\n" | 
					
						
							|  |  |  | "       '3D_FLAT_COLOR',\n" | 
					
						
							|  |  |  | "       '3D_SMOOTH_COLOR'}\n" | 
					
						
							|  |  |  | "   :type shader_name: str\n" | 
					
						
							| 
									
										
										
										
											2018-10-22 15:01:25 +02:00
										 |  |  | "   :return: the shader object\n" | 
					
						
							|  |  |  | "   :rtype: bpy.types.GPUShader\n" | 
					
						
							| 
									
										
										
										
											2018-09-14 09:32:19 -03:00
										 |  |  | ); | 
					
						
							|  |  |  | static PyObject *bpygpu_shader_from_builtin(PyObject *UNUSED(self), PyObject *arg) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2018-10-09 12:06:42 -03:00
										 |  |  | 	GPUBuiltinShader shader_id; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if (!bpygpu_ParseBultinShaderEnum(arg, &shader_id)) { | 
					
						
							| 
									
										
										
										
											2018-09-14 09:32:19 -03:00
										 |  |  | 		return NULL; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	GPUShader *shader = GPU_shader_get_builtin_shader(shader_id); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-09-20 15:21:59 -03:00
										 |  |  | 	return BPyGPUShader_CreatePyObject(shader, true); | 
					
						
							| 
									
										
										
										
											2018-09-14 09:32:19 -03:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | PyDoc_STRVAR(bpygpu_shader_code_from_builtin_doc, | 
					
						
							| 
									
										
										
										
											2018-10-22 15:01:25 +02:00
										 |  |  | ".. function:: code_from_builtin(shader_name)\n" | 
					
						
							| 
									
										
										
										
											2018-10-09 12:18:28 -03:00
										 |  |  | "\n" | 
					
						
							| 
									
										
										
										
											2018-10-30 11:38:42 -03:00
										 |  |  | "Exposes the internal shader code for query.\n" | 
					
						
							|  |  |  | "\n" | 
					
						
							| 
									
										
										
										
											2018-10-09 12:18:28 -03:00
										 |  |  | "   :param shader_name: One of these builtin shader names: {\n" | 
					
						
							|  |  |  | "       '2D_UNIFORM_COLOR',\n" | 
					
						
							|  |  |  | "       '2D_FLAT_COLOR',\n" | 
					
						
							|  |  |  | "       '2D_SMOOTH_COLOR',\n" | 
					
						
							|  |  |  | "       '2D_IMAGE',\n" | 
					
						
							|  |  |  | "       '3D_UNIFORM_COLOR',\n" | 
					
						
							|  |  |  | "       '3D_FLAT_COLOR',\n" | 
					
						
							|  |  |  | "       '3D_SMOOTH_COLOR'}\n" | 
					
						
							|  |  |  | "   :type shader_name: str\n" | 
					
						
							| 
									
										
										
										
											2018-09-14 09:32:19 -03:00
										 |  |  | "   :return: vertex, fragment and geometry shader codes.\n" | 
					
						
							| 
									
										
										
										
											2018-10-04 13:08:04 +10:00
										 |  |  | "   :rtype: dict\n" | 
					
						
							| 
									
										
										
										
											2018-09-14 09:32:19 -03:00
										 |  |  | ); | 
					
						
							|  |  |  | static PyObject *bpygpu_shader_code_from_builtin(BPyGPUShader *UNUSED(self), PyObject *arg) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2018-10-09 12:06:42 -03:00
										 |  |  | 	GPUBuiltinShader shader_id; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-09-14 09:32:19 -03:00
										 |  |  | 	const char *vert; | 
					
						
							|  |  |  | 	const char *frag; | 
					
						
							|  |  |  | 	const char *geom; | 
					
						
							|  |  |  | 	const char *defines; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	PyObject *item, *r_dict; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-10-09 12:06:42 -03:00
										 |  |  | 	if (!bpygpu_ParseBultinShaderEnum(arg, &shader_id)) { | 
					
						
							| 
									
										
										
										
											2018-09-14 09:32:19 -03:00
										 |  |  | 		return NULL; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	GPU_shader_get_builtin_shader_code( | 
					
						
							|  |  |  | 	        shader_id, &vert, &frag, &geom, &defines); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	r_dict = PyDict_New(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	PyDict_SetItemString(r_dict, "vertex_shader", item = PyUnicode_FromString(vert)); | 
					
						
							|  |  |  | 	Py_DECREF(item); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	PyDict_SetItemString(r_dict, "fragment_shader", item = PyUnicode_FromString(frag)); | 
					
						
							|  |  |  | 	Py_DECREF(item); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if (geom) { | 
					
						
							|  |  |  | 		PyDict_SetItemString(r_dict, "geometry_shader", item = PyUnicode_FromString(geom)); | 
					
						
							|  |  |  | 		Py_DECREF(item); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	if (defines) { | 
					
						
							|  |  |  | 		PyDict_SetItemString(r_dict, "defines", item = PyUnicode_FromString(defines)); | 
					
						
							|  |  |  | 		Py_DECREF(item); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	return r_dict; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static struct PyMethodDef bpygpu_shader_module_methods[] = { | 
					
						
							|  |  |  | 	{"unbind", | 
					
						
							|  |  |  | 	 (PyCFunction)bpygpu_shader_unbind, | 
					
						
							|  |  |  | 	 METH_NOARGS, bpygpu_shader_unbind_doc}, | 
					
						
							| 
									
										
										
										
											2018-10-04 13:51:21 -03:00
										 |  |  | 	{"from_builtin", | 
					
						
							| 
									
										
										
										
											2018-09-14 09:32:19 -03:00
										 |  |  | 	 (PyCFunction)bpygpu_shader_from_builtin, | 
					
						
							|  |  |  | 	 METH_O, bpygpu_shader_from_builtin_doc}, | 
					
						
							| 
									
										
										
										
											2018-10-04 13:51:21 -03:00
										 |  |  | 	{"code_from_builtin", | 
					
						
							| 
									
										
										
										
											2018-09-14 09:32:19 -03:00
										 |  |  | 	 (PyCFunction)bpygpu_shader_code_from_builtin, | 
					
						
							|  |  |  | 	 METH_O, bpygpu_shader_code_from_builtin_doc}, | 
					
						
							|  |  |  | 	{NULL, NULL, 0, NULL} | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | PyDoc_STRVAR(bpygpu_shader_module_doc, | 
					
						
							|  |  |  | "This module provides access to GPUShader internal functions." | 
					
						
							|  |  |  | ); | 
					
						
							|  |  |  | static PyModuleDef BPyGPU_shader_module_def = { | 
					
						
							|  |  |  | 	PyModuleDef_HEAD_INIT, | 
					
						
							|  |  |  | 	.m_name = "gpu.shader", | 
					
						
							|  |  |  | 	.m_doc = bpygpu_shader_module_doc, | 
					
						
							|  |  |  | 	.m_methods = bpygpu_shader_module_methods, | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /** \} */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* -------------------------------------------------------------------- */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /** \name Public API
 | 
					
						
							|  |  |  |  * \{ */ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-09-20 15:21:59 -03:00
										 |  |  | PyObject *BPyGPUShader_CreatePyObject(GPUShader *shader, bool is_builtin) | 
					
						
							| 
									
										
										
										
											2018-09-14 09:32:19 -03:00
										 |  |  | { | 
					
						
							|  |  |  | 	BPyGPUShader *self; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	self = PyObject_New(BPyGPUShader, &BPyGPUShader_Type); | 
					
						
							|  |  |  | 	self->shader = shader; | 
					
						
							| 
									
										
										
										
											2018-09-20 15:21:59 -03:00
										 |  |  | 	self->is_builtin = is_builtin; | 
					
						
							| 
									
										
										
										
											2018-09-14 09:32:19 -03:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	return (PyObject *)self; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | PyObject *BPyInit_gpu_shader(void) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	PyObject *submodule; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	submodule = PyModule_Create(&BPyGPU_shader_module_def); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return submodule; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /** \} */ |