33 #include "../generic/py_capi_utils.h"
34 #include "../generic/python_utildefines.h"
35 #include "../mathutils/mathutils.h"
49 PyErr_SetString(PyExc_ReferenceError,
51 "GPU framebuffer was freed, no further access is valid"
53 "GPU framebuffer: internal error"
61 #define PYGPU_FRAMEBUFFER_CHECK_OBJ(bpygpu) \
63 if (UNLIKELY(pygpu_framebuffer_valid_check(bpygpu) == -1)) { \
79 printf(
"PyFramebuffer freed after the context has been destroyed.\n");
84 #define GPU_PY_FRAMEBUFFER_STACK_LEN 16
102 PyErr_SetString(PyExc_RuntimeError,
"Minimum framebuffer stack depth reached");
107 PyErr_SetString(PyExc_RuntimeError,
"Framebuffer is not bound");
133 Py_DECREF(
self->py_fb);
142 if (
self->level != -1) {
143 PyErr_SetString(PyExc_RuntimeError,
"Already in use");
161 if (
self->level == -1) {
162 fprintf(stderr,
"Not yet in use\n");
167 if (level !=
self->level) {
168 fprintf(stderr,
"Level of bind mismatch, expected %d, got %d\n",
self->level, level);
184 PyVarObject_HEAD_INIT(
NULL, 0).tp_name =
"GPUFrameBufferStackContext",
187 .tp_flags = Py_TPFLAGS_DEFAULT,
192 ".. function:: bind()\n"
194 " Context manager to ensure balanced bind calls, even in the case of an error.\n");
202 return (PyObject *)
ret;
220 if (!o || o == Py_None) {
229 const char *c_texture =
"texture";
230 const char *c_layer =
"layer";
231 const char *c_mip =
"mip";
232 PyObject *key, *value;
234 while (PyDict_Next(o, &
pos, &key, &value)) {
235 if (!PyUnicode_Check(key)) {
236 PyErr_SetString(PyExc_TypeError,
"keywords must be strings");
240 if (c_texture && _PyUnicode_EqualToASCIIString(key, c_texture)) {
247 else if (c_layer && _PyUnicode_EqualToASCIIString(key, c_layer)) {
250 tmp_attach.
layer = PyLong_AsLong(value);
251 if (tmp_attach.
layer == -1 && PyErr_Occurred()) {
255 else if (c_mip && _PyUnicode_EqualToASCIIString(key, c_mip)) {
258 tmp_attach.
mip = PyLong_AsLong(value);
259 if (tmp_attach.
mip == -1 && PyErr_Occurred()) {
265 PyExc_TypeError,
"'%U' is an invalid keyword argument for this attribute", key);
271 *r_attach = tmp_attach;
281 PyErr_SetString(PyExc_RuntimeError,
"No active GPU context found");
285 PyObject *depth_attachment =
NULL;
286 PyObject *color_attachements =
NULL;
287 static const char *_keywords[] = {
"depth_slot",
"color_slots",
NULL};
288 static _PyArg_Parser _parser = {
"|$OO:GPUFrameBuffer.__new__", _keywords, 0};
289 if (!_PyArg_ParseTupleAndKeywordsFast(
290 args, kwds, &_parser, &depth_attachment, &color_attachements)) {
296 #define BPYGPU_FB_MAX_COLOR_ATTACHMENT 6
304 PyErr_SetString(PyExc_ValueError,
"Depth texture with incompatible format");
308 int color_attachements_len = 0;
309 if (color_attachements && color_attachements != Py_None) {
310 if (PySequence_Check(color_attachements)) {
311 color_attachements_len = PySequence_Size(color_attachements);
314 PyExc_AttributeError,
319 for (
int i = 0; i < color_attachements_len; i++) {
320 PyObject *o = PySequence_GetItem(color_attachements, i);
332 color_attachements_len = 1;
343 "Checks if this is the active framebuffer in the context.");
351 ".. method:: clear(color=None, depth=None, stencil=None)\n"
353 " Fill color, depth and stencil textures with specific value.\n"
354 " Common values: color=(0.0, 0.0, 0.0, 1.0), depth=1.0, stencil=0.\n"
356 " :arg color: float sequence each representing ``(r, g, b, a)``.\n"
357 " :type color: sequence of 3 or 4 floats\n"
358 " :arg depth: depth value.\n"
359 " :type depth: float\n"
360 " :arg stencil: stencil value.\n"
361 " :type stencil: int\n");
370 PyObject *py_col =
NULL;
371 PyObject *py_depth =
NULL;
372 PyObject *py_stencil =
NULL;
374 static const char *_keywords[] = {
"color",
"depth",
"stencil",
NULL};
375 static _PyArg_Parser _parser = {
"|$OOO:clear", _keywords, 0};
376 if (!_PyArg_ParseTupleAndKeywordsFast(args, kwds, &_parser, &py_col, &py_depth, &py_stencil)) {
381 float col[4] = {0.0f, 0.0f, 0.0f, 1.0f};
385 if (py_col && py_col != Py_None) {
393 if (py_depth && py_depth != Py_None) {
394 depth = PyFloat_AsDouble(py_depth);
395 if (PyErr_Occurred()) {
401 if (py_stencil && py_stencil != Py_None) {
413 ".. function:: viewport_set(x, y, xsize, ysize)\n"
415 " Set the viewport for this framebuffer object.\n"
416 " Note: The viewport state is not saved upon framebuffer rebind.\n"
418 " :param x, y: lower left corner of the viewport_set rectangle, in pixels.\n"
419 " :param xsize, ysize: width and height of the viewport_set.\n"
420 " :type x, y, xsize, ysize: int\n");
425 int x,
y, xsize, ysize;
426 if (!PyArg_ParseTuple(args,
"iiii:viewport_set", &
x, &
y, &xsize, &ysize)) {
435 ".. function:: viewport_get()\n"
437 " Returns position and dimension to current viewport.\n");
444 PyObject *
ret = PyTuple_New(4);
446 PyLong_FromLong(viewport[0]),
447 PyLong_FromLong(viewport[1]),
448 PyLong_FromLong(viewport[2]),
449 PyLong_FromLong(viewport[3]));
453 #ifdef BPYGPU_USE_GPUOBJ_FREE_METHOD
455 ".. method:: free()\n"
457 " Free the framebuffer object.\n"
458 " The framebuffer will no longer be accessible.\n");
471 Py_TYPE(
self)->tp_free((PyObject *)
self);
478 pygpu_framebuffer_is_bound_doc,
487 METH_VARARGS | METH_KEYWORDS,
488 pygpu_framebuffer_clear_doc},
492 pygpu_framebuffer_viewport_set_doc},
496 pygpu_framebuffer_viewport_get_doc},
497 #ifdef BPYGPU_USE_GPUOBJ_FREE_METHOD
498 {
"free", (PyCFunction)pygpu_framebuffer_free, METH_NOARGS, pygpu_framebuffer_free_doc},
504 ".. class:: GPUFrameBuffer(depth_slot=None, color_slots=None)\n"
506 " This object gives access to framebuffer functionallities.\n"
507 " When a 'layer' is specified in a argument, a single layer of a 3D or array "
508 "texture is attached to the frame-buffer.\n"
509 " For cube map textures, layer is translated into a cube map face.\n"
511 " :arg depth_slot: GPUTexture to attach or a `dict` containing keywords: "
512 "'texture', 'layer' and 'mip'.\n"
513 " :type depth_slot: :class:`gpu.types.GPUTexture`, dict or Nonetype\n"
514 " :arg color_slots: Tuple where each item can be a GPUTexture or a `dict` "
515 "containing keywords: 'texture', 'layer' and 'mip'.\n"
516 " :type color_slots: tuple or Nonetype\n");
518 PyVarObject_HEAD_INIT(
NULL, 0).tp_name =
"GPUFrameBuffer",
521 .tp_flags = Py_TPFLAGS_DEFAULT,
522 .tp_doc = pygpu_framebuffer__tp_doc,
541 return (PyObject *)
self;
546 #undef PYGPU_FRAMEBUFFER_CHECK_OBJ
GPUContext * GPU_context_active_get(void)
struct GPUFrameBuffer GPUFrameBuffer
GPUFrameBuffer * GPU_framebuffer_active_get(void)
void GPU_framebuffer_free(GPUFrameBuffer *fb)
void GPU_framebuffer_bind(GPUFrameBuffer *fb)
bool GPU_framebuffer_bound(GPUFrameBuffer *fb)
GPUFrameBuffer * GPU_framebuffer_create(const char *name)
_GL_VOID GLfloat value _GL_VOID_RET _GL_VOID const GLuint GLboolean *residences _GL_BOOL_RET _GL_VOID GLsizei GLfloat GLfloat GLfloat GLfloat const GLubyte *bitmap _GL_VOID_RET _GL_VOID GLenum type
_GL_VOID GLfloat value _GL_VOID_RET _GL_VOID const GLuint GLboolean *residences _GL_BOOL_RET _GL_VOID GLsizei GLfloat GLfloat GLfloat GLfloat const GLubyte *bitmap _GL_VOID_RET _GL_VOID GLenum const void *lists _GL_VOID_RET _GL_VOID const GLdouble *equation _GL_VOID_RET _GL_VOID GLdouble GLdouble blue _GL_VOID_RET _GL_VOID GLfloat GLfloat blue _GL_VOID_RET _GL_VOID GLint GLint blue _GL_VOID_RET _GL_VOID GLshort GLshort blue _GL_VOID_RET _GL_VOID GLubyte GLubyte blue _GL_VOID_RET _GL_VOID GLuint GLuint blue _GL_VOID_RET _GL_VOID GLushort GLushort blue _GL_VOID_RET _GL_VOID GLbyte GLbyte GLbyte alpha _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble alpha _GL_VOID_RET _GL_VOID GLfloat GLfloat GLfloat alpha _GL_VOID_RET _GL_VOID GLint GLint GLint alpha _GL_VOID_RET _GL_VOID GLshort GLshort GLshort alpha _GL_VOID_RET _GL_VOID GLubyte GLubyte GLubyte alpha _GL_VOID_RET _GL_VOID GLuint GLuint GLuint alpha _GL_VOID_RET _GL_VOID GLushort GLushort GLushort alpha _GL_VOID_RET _GL_VOID GLenum mode _GL_VOID_RET _GL_VOID GLint y
bool GPU_texture_depth(const GPUTexture *tex)
void GPU_framebuffer_clear(GPUFrameBuffer *gpu_fb, eGPUFrameBufferBits buffers, const float clear_col[4], float clear_depth, uint clear_stencil)
uint GPU_framebuffer_stack_level_get(void)
void GPU_framebuffer_config_array(GPUFrameBuffer *gpu_fb, const GPUAttachment *config, int config_len)
GPUFrameBuffer * GPU_framebuffer_pop(void)
void GPU_framebuffer_viewport_get(GPUFrameBuffer *gpu_fb, int r_viewport[4])
void GPU_framebuffer_push(GPUFrameBuffer *fb)
void GPU_framebuffer_viewport_set(GPUFrameBuffer *gpu_fb, int x, int y, int width, int height)
#define BPYGPU_IS_INIT_OR_ERROR_OBJ
static bool pygpu_framebuffer_stack_pop_and_restore_or_error(GPUFrameBuffer *fb)
static PyObject * pygpu_framebuffer_clear(BPyGPUFrameBuffer *self, PyObject *args, PyObject *kwds)
static PyObject * pygpu_framebuffer_viewport_get(BPyGPUFrameBuffer *self, void *UNUSED(type))
static PyTypeObject FramebufferStackContext_Type
static PyObject * pygpu_framebuffer_is_bound(BPyGPUFrameBuffer *self, void *UNUSED(type))
#define PYGPU_FRAMEBUFFER_CHECK_OBJ(bpygpu)
static void pygpu_framebuffer_stack_context__tp_dealloc(PyFrameBufferStackContext *self)
static void pygpu_framebuffer_free_if_possible(GPUFrameBuffer *fb)
#define BPYGPU_FB_MAX_COLOR_ATTACHMENT
static PyObject * pygpu_framebuffer_viewport_set(BPyGPUFrameBuffer *self, PyObject *args, void *UNUSED(type))
static PyObject * pygpu_framebuffer_bind(BPyGPUFrameBuffer *self)
static bool pygpu_framebuffer_stack_push_and_bind_or_error(GPUFrameBuffer *fb)
static struct PyMethodDef pygpu_framebuffer__tp_methods[]
#define GPU_PY_FRAMEBUFFER_STACK_LEN
static PyObject * pygpu_framebuffer_stack_context_enter(PyFrameBufferStackContext *self)
PyObject * BPyGPUFrameBuffer_CreatePyObject(GPUFrameBuffer *fb)
static PyObject * pygpu_framebuffer_stack_context_exit(PyFrameBufferStackContext *self, PyObject *UNUSED(args))
static bool pygpu_framebuffer_new_parse_arg(PyObject *o, GPUAttachment *r_attach)
static PyGetSetDef pygpu_framebuffer__tp_getseters[]
PyDoc_STRVAR(pygpu_framebuffer_bind_doc, ".. function:: bind()\n" "\n" " Context manager to ensure balanced bind calls, even in the case of an error.\n")
static int pygpu_framebuffer_valid_check(BPyGPUFrameBuffer *bpygpu_fb)
static void BPyGPUFrameBuffer__tp_dealloc(BPyGPUFrameBuffer *self)
static PyMethodDef pygpu_framebuffer_stack_context__tp_methods[]
static PyObject * pygpu_framebuffer__tp_new(PyTypeObject *UNUSED(self), PyObject *args, PyObject *kwds)
PyTypeObject BPyGPUFrameBuffer_Type
struct BPyGPUFrameBuffer BPyGPUFrameBuffer
#define BPYGPU_USE_GPUOBJ_FREE_METHOD
int bpygpu_ParseTexture(PyObject *o, void *p)
#define BPyGPUTexture_Check(v)
BLI_INLINE float fb(float length, float L)
int mathutils_array_parse(float *array, int array_min, int array_max, PyObject *value, const char *error_prefix)
uint32_t PyC_Long_AsU32(PyObject *value)
#define PyTuple_SET_ITEMS(op_arg,...)
PyObject_HEAD struct GPUFrameBuffer * fb
PyObject_HEAD BPyGPUFrameBuffer * py_fb