19 #include "../generic/py_capi_utils.h"
20 #include "../generic/python_utildefines.h"
21 #include "../mathutils/mathutils.h"
35 PyErr_SetString(PyExc_ReferenceError,
"GPU framebuffer was freed, no further access is valid");
41 #define PYGPU_FRAMEBUFFER_CHECK_OBJ(bpygpu) \
43 if (UNLIKELY(pygpu_framebuffer_valid_check(bpygpu) == -1)) { \
55 printf(
"PyFramebuffer freed after the context has been destroyed.\n");
62 #ifndef GPU_NO_USE_PY_REFERENCES
64 if (!
self->shared_reference)
75 #define GPU_PY_FRAMEBUFFER_STACK_LEN 16
93 PyErr_SetString(PyExc_RuntimeError,
"Minimum framebuffer stack depth reached");
98 PyErr_SetString(PyExc_RuntimeError,
"Framebuffer is not bound");
124 Py_DECREF(
self->py_fb);
133 if (
self->level != -1) {
134 PyErr_SetString(PyExc_RuntimeError,
"Already in use");
152 if (
self->level == -1) {
153 fprintf(stderr,
"Not yet in use\n");
158 if (level !=
self->level) {
159 fprintf(stderr,
"Level of bind mismatch, expected %d, got %d\n",
self->level, level);
175 PyVarObject_HEAD_INIT(
NULL, 0).tp_name =
"GPUFrameBufferStackContext",
178 .tp_flags = Py_TPFLAGS_DEFAULT,
183 ".. function:: bind()\n"
185 " Context manager to ensure balanced bind calls, even in the case of an error.\n");
193 return (PyObject *)
ret;
211 if (!o || o == Py_None) {
220 const char *c_texture =
"texture";
221 const char *c_layer =
"layer";
222 const char *c_mip =
"mip";
223 PyObject *key, *value;
225 while (PyDict_Next(o, &
pos, &key, &value)) {
226 if (!PyUnicode_Check(key)) {
227 PyErr_SetString(PyExc_TypeError,
"keywords must be strings");
231 if (c_texture && _PyUnicode_EqualToASCIIString(key, c_texture)) {
238 else if (c_layer && _PyUnicode_EqualToASCIIString(key, c_layer)) {
241 tmp_attach.
layer = PyLong_AsLong(value);
242 if (tmp_attach.
layer == -1 && PyErr_Occurred()) {
246 else if (c_mip && _PyUnicode_EqualToASCIIString(key, c_mip)) {
249 tmp_attach.
mip = PyLong_AsLong(value);
250 if (tmp_attach.
mip == -1 && PyErr_Occurred()) {
256 PyExc_TypeError,
"'%U' is an invalid keyword argument for this attribute", key);
262 *r_attach = tmp_attach;
272 PyErr_SetString(PyExc_RuntimeError,
"No active GPU context found");
276 PyObject *depth_attachment =
NULL;
277 PyObject *color_attachements =
NULL;
278 static const char *_keywords[] = {
"depth_slot",
"color_slots",
NULL};
279 static _PyArg_Parser _parser = {
283 ":GPUFrameBuffer.__new__",
287 if (!_PyArg_ParseTupleAndKeywordsFast(
288 args, kwds, &_parser, &depth_attachment, &color_attachements)) {
294 #define BPYGPU_FB_MAX_COLOR_ATTACHMENT 6
302 PyErr_SetString(PyExc_ValueError,
"Depth texture with incompatible format");
306 int color_attachements_len = 0;
307 if (color_attachements && color_attachements != Py_None) {
308 if (PySequence_Check(color_attachements)) {
309 color_attachements_len = PySequence_Size(color_attachements);
312 PyExc_AttributeError,
317 for (
int i = 0; i < color_attachements_len; i++) {
318 PyObject *o = PySequence_GetItem(color_attachements, i);
330 color_attachements_len = 1;
341 "Checks if this is the active framebuffer in the context.");
349 ".. method:: clear(color=None, depth=None, stencil=None)\n"
351 " Fill color, depth and stencil textures with specific value.\n"
352 " Common values: color=(0.0, 0.0, 0.0, 1.0), depth=1.0, stencil=0.\n"
354 " :arg color: float sequence each representing ``(r, g, b, a)``.\n"
355 " :type color: sequence of 3 or 4 floats\n"
356 " :arg depth: depth value.\n"
357 " :type depth: float\n"
358 " :arg stencil: stencil value.\n"
359 " :type stencil: int\n");
368 PyObject *py_col =
NULL;
369 PyObject *py_depth =
NULL;
370 PyObject *py_stencil =
NULL;
372 static const char *_keywords[] = {
"color",
"depth",
"stencil",
NULL};
373 static _PyArg_Parser _parser = {
382 if (!_PyArg_ParseTupleAndKeywordsFast(args, kwds, &_parser, &py_col, &py_depth, &py_stencil)) {
387 float col[4] = {0.0f, 0.0f, 0.0f, 1.0f};
391 if (py_col && py_col != Py_None) {
399 if (py_depth && py_depth != Py_None) {
400 depth = PyFloat_AsDouble(py_depth);
401 if (PyErr_Occurred()) {
407 if (py_stencil && py_stencil != Py_None) {
419 ".. function:: viewport_set(x, y, xsize, ysize)\n"
421 " Set the viewport for this framebuffer object.\n"
422 " Note: The viewport state is not saved upon framebuffer rebind.\n"
424 " :param x, y: lower left corner of the viewport_set rectangle, in pixels.\n"
425 " :param xsize, ysize: width and height of the viewport_set.\n"
426 " :type x, y, xsize, ysize: int\n");
431 int x,
y, xsize, ysize;
432 if (!PyArg_ParseTuple(args,
"iiii:viewport_set", &
x, &
y, &xsize, &ysize)) {
441 ".. function:: viewport_get()\n"
443 " Returns position and dimension to current viewport.\n");
450 PyObject *
ret = PyTuple_New(4);
452 PyLong_FromLong(viewport[0]),
453 PyLong_FromLong(viewport[1]),
454 PyLong_FromLong(viewport[2]),
455 PyLong_FromLong(viewport[3]));
460 pygpu_framebuffer_read_color_doc,
461 ".. function:: read_color(x, y, xsize, ysize, channels, slot, format, data=data)\n"
463 " Read a block of pixels from the frame buffer.\n"
465 " :param x, y: Lower left corner of a rectangular block of pixels.\n"
466 " :param xsize, ysize: Dimensions of the pixel rectangle.\n"
467 " :type x, y, xsize, ysize: int\n"
468 " :param channels: Number of components to read.\n"
469 " :type channels: int\n"
470 " :param slot: The framebuffer slot to read data from.\n"
472 " :param format: The format that describes the content of a single channel.\n"
473 " Possible values are `FLOAT`, `INT`, `UINT`, `UBYTE`, `UINT_24_8` and `10_11_11_REV`.\n"
475 " :arg data: Optional Buffer object to fill with the pixels values.\n"
476 " :type data: :class:`gpu.types.Buffer`\n"
477 " :return: The Buffer with the read pixels.\n"
478 " :rtype: :class:`gpu.types.Buffer`\n");
489 static const char *_keywords[] = {
490 "x",
"y",
"xsize",
"ysize",
"channels",
"slot",
"format",
"data",
NULL};
491 static _PyArg_Parser _parser = {
505 if (!_PyArg_ParseTupleAndKeywordsFast(args,
522 PyErr_SetString(PyExc_AttributeError,
"Color channels must be 1, 2, 3 or 4");
527 PyErr_SetString(PyExc_ValueError,
"slot overflow");
533 PyErr_SetString(PyExc_AttributeError,
534 "the format of the buffer is different from that specified");
539 size_t size_expected =
w * h *
channels *
541 if (size_curr < size_expected) {
542 PyErr_SetString(PyExc_BufferError,
"the buffer size is smaller than expected");
545 Py_INCREF(py_buffer);
549 pygpu_dataformat.
value_found, (Py_ssize_t[3]){h, w, channels}, 3,
NULL);
564 return (PyObject *)py_buffer;
568 ".. function:: read_depth(x, y, xsize, ysize, data=data)\n"
570 " Read a pixel depth block from the frame buffer.\n"
572 " :param x, y: Lower left corner of a rectangular block of pixels.\n"
573 " :param xsize, ysize: Dimensions of the pixel rectangle.\n"
574 " :type x, y, xsize, ysize: int\n"
575 " :arg data: Optional Buffer object to fill with the pixels values.\n"
576 " :type data: :class:`gpu.types.Buffer`\n"
577 " :return: The Buffer with the read pixels.\n"
578 " :rtype: :class:`gpu.types.Buffer`\n");
587 static const char *_keywords[] = {
"x",
"y",
"xsize",
"ysize",
"data",
NULL};
588 static _PyArg_Parser _parser = {
599 if (!_PyArg_ParseTupleAndKeywordsFast(
606 PyErr_SetString(PyExc_AttributeError,
"the format of the buffer must be 'GPU_DATA_FLOAT'");
612 if (size_curr < size_expected) {
613 PyErr_SetString(PyExc_BufferError,
"the buffer size is smaller than expected");
616 Py_INCREF(py_buffer);
626 return (PyObject *)py_buffer;
629 #ifdef BPYGPU_USE_GPUOBJ_FREE_METHOD
631 ".. method:: free()\n"
633 " Free the framebuffer object.\n"
634 " The framebuffer will no longer be accessible.\n");
646 Py_TYPE(
self)->tp_free((PyObject *)
self);
653 pygpu_framebuffer_is_bound_doc,
662 METH_VARARGS | METH_KEYWORDS,
663 pygpu_framebuffer_clear_doc},
667 pygpu_framebuffer_viewport_set_doc},
671 pygpu_framebuffer_viewport_get_doc},
674 METH_VARARGS | METH_KEYWORDS,
675 pygpu_framebuffer_read_color_doc},
678 METH_VARARGS | METH_KEYWORDS,
679 pygpu_framebuffer_read_depth_doc},
680 #ifdef BPYGPU_USE_GPUOBJ_FREE_METHOD
681 {
"free", (PyCFunction)pygpu_framebuffer_free, METH_NOARGS, pygpu_framebuffer_free_doc},
687 ".. class:: GPUFrameBuffer(depth_slot=None, color_slots=None)\n"
689 " This object gives access to framebuffer functionallities.\n"
690 " When a 'layer' is specified in a argument, a single layer of a 3D or array "
691 "texture is attached to the frame-buffer.\n"
692 " For cube map textures, layer is translated into a cube map face.\n"
694 " :arg depth_slot: GPUTexture to attach or a `dict` containing keywords: "
695 "'texture', 'layer' and 'mip'.\n"
696 " :type depth_slot: :class:`gpu.types.GPUTexture`, dict or Nonetype\n"
697 " :arg color_slots: Tuple where each item can be a GPUTexture or a `dict` "
698 "containing keywords: 'texture', 'layer' and 'mip'.\n"
699 " :type color_slots: tuple or Nonetype\n");
701 PyVarObject_HEAD_INIT(
NULL, 0).tp_name =
"GPUFrameBuffer",
704 .tp_flags = Py_TPFLAGS_DEFAULT,
705 .tp_doc = pygpu_framebuffer__tp_doc,
721 #ifndef GPU_NO_USE_PY_REFERENCES
722 if (shared_reference) {
729 return (PyObject *)
self;
739 #ifndef GPU_NO_USE_PY_REFERENCES
740 self->shared_reference = shared_reference;
746 return (PyObject *)
self;
751 #undef PYGPU_FRAMEBUFFER_CHECK_OBJ
#define POINTER_OFFSET(v, ofs)
#define IN_RANGE_INCL(a, b, c)
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 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
_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
size_t GPU_texture_dataformat_size(eGPUDataFormat data_format)
bool GPU_texture_depth(const GPUTexture *tex)
Group Output data from inside of a node group A color picker Mix two input colors RGB to Convert a color s luminance to a grayscale value Generate a normal vector and a dot product Bright Control the brightness and contrast of the input color Vector Map an input vectors to used to fine tune the interpolation of the input Camera Retrieve information about the camera and how it relates to the current shading point s position Clamp a value between a minimum and a maximum Vector Perform vector math operation Invert a producing a negative Combine Generate a color from its and blue channels(Deprecated)") DefNode(ShaderNode
SIMD_FORCE_INLINE const btScalar & w() const
Return the w value.
void GPU_framebuffer_clear(GPUFrameBuffer *gpu_fb, eGPUFrameBufferBits buffers, const float clear_col[4], float clear_depth, uint clear_stencil)
void GPU_framebuffer_config_array(GPUFrameBuffer *gpu_fb, const GPUAttachment *config, int config_len)
void GPU_framebuffer_read_color(GPUFrameBuffer *gpu_fb, int x, int y, int w, int h, int channels, int slot, eGPUDataFormat format, void *data)
void GPU_framebuffer_py_reference_set(GPUFrameBuffer *gpu_fb, void **py_ref)
void ** GPU_framebuffer_py_reference_get(GPUFrameBuffer *gpu_fb)
void GPU_framebuffer_viewport_get(GPUFrameBuffer *gpu_fb, int r_viewport[4])
uint GPU_framebuffer_stack_level_get()
void GPU_framebuffer_push(GPUFrameBuffer *fb)
void GPU_framebuffer_viewport_set(GPUFrameBuffer *gpu_fb, int x, int y, int width, int height)
void GPU_framebuffer_read_depth(GPUFrameBuffer *gpu_fb, int x, int y, int w, int h, eGPUDataFormat format, void *data)
GPUFrameBuffer * GPU_framebuffer_pop()
struct PyC_StringEnumItems bpygpu_dataformat_items[]
#define BPYGPU_IS_INIT_OR_ERROR_OBJ
BPyGPUBuffer * BPyGPU_Buffer_CreatePyObject(const int format, const Py_ssize_t *shape, const int shape_len, void *buffer)
PyTypeObject BPyGPU_BufferType
size_t bpygpu_Buffer_size(BPyGPUBuffer *buffer)
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
PyObject * BPyGPUFrameBuffer_CreatePyObject(GPUFrameBuffer *fb, bool shared_reference)
static PyObject * pygpu_framebuffer_read_depth(BPyGPUFrameBuffer *self, PyObject *args, PyObject *kwds)
static PyObject * pygpu_framebuffer_stack_context_enter(PyFrameBufferStackContext *self)
static void pygpu_framebuffer_free_safe(BPyGPUFrameBuffer *self)
static PyObject * pygpu_framebuffer_read_color(BPyGPUFrameBuffer *self, PyObject *args, PyObject *kwds)
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
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_num_min, int array_num_max, PyObject *value, const char *error_prefix)
int PyC_ParseStringEnum(PyObject *o, void *p)
uint32_t PyC_Long_AsU32(PyObject *value)
#define PyTuple_SET_ITEMS(op_arg,...)
union BPyGPUBuffer::@1155 buf
PyObject_HEAD struct GPUFrameBuffer * fb
PyObject_HEAD BPyGPUFrameBuffer * py_fb