39 PyErr_SetString(PyExc_ReferenceError,
"GPU framebuffer was freed, no further access is valid");
45#define PYGPU_FRAMEBUFFER_CHECK_OBJ(bpygpu) \
47 if (UNLIKELY(pygpu_framebuffer_valid_check(bpygpu) == -1)) { \
59 printf(
"PyFramebuffer freed after the context has been destroyed.\n");
66#ifndef GPU_NO_USE_PY_REFERENCES
68 if (!
self->shared_reference)
79#define GPU_PY_FRAMEBUFFER_STACK_LEN 16
97 PyErr_SetString(PyExc_RuntimeError,
"Minimum framebuffer stack depth reached");
102 PyErr_SetString(PyExc_RuntimeError,
"Framebuffer is not bound");
128 Py_DECREF(
self->py_fb);
137 if (
self->level != -1) {
138 PyErr_SetString(PyExc_RuntimeError,
"Already in use");
156 if (
self->level == -1) {
157 fprintf(stderr,
"Not yet in use\n");
162 if (level !=
self->level) {
163 fprintf(stderr,
"Level of bind mismatch, expected %d, got %d\n",
self->level, level);
174# pragma clang diagnostic push
175# pragma clang diagnostic ignored "-Wcast-function-type"
177# pragma GCC diagnostic push
178# pragma GCC diagnostic ignored "-Wcast-function-type"
190# pragma clang diagnostic pop
192# pragma GCC diagnostic pop
197 PyVarObject_HEAD_INIT(
nullptr, 0)
198 "GPUFrameBufferStackContext",
250 pygpu_framebuffer_bind_doc,
251 ".. function:: bind()\n"
253 " Context manager to ensure balanced bind calls, even in the case of an error.\n");
261 return (PyObject *)
ret;
278 if (!o || o == Py_None) {
287 const char *c_texture =
"texture";
288 const char *c_layer =
"layer";
289 const char *c_mip =
"mip";
290 PyObject *key, *value;
292 while (PyDict_Next(o, &
pos, &key, &value)) {
293 if (!PyUnicode_Check(key)) {
294 PyErr_SetString(PyExc_TypeError,
"keywords must be strings");
308 tmp_attach.
layer = PyLong_AsLong(value);
309 if (tmp_attach.
layer == -1 && PyErr_Occurred()) {
316 tmp_attach.
mip = PyLong_AsLong(value);
317 if (tmp_attach.
mip == -1 && PyErr_Occurred()) {
323 PyExc_TypeError,
"'%U' is an invalid keyword argument for this attribute", key);
329 *r_attach = tmp_attach;
338 PyErr_SetString(PyExc_RuntimeError,
"No active GPU context found");
342 PyObject *depth_attachment =
nullptr;
343 PyObject *color_attachements =
nullptr;
344 static const char *_keywords[] = {
"depth_slot",
"color_slots",
nullptr};
345 static _PyArg_Parser _parser = {
350 ":GPUFrameBuffer.__new__",
354 if (!_PyArg_ParseTupleAndKeywordsFast(
355 args, kwds, &_parser, &depth_attachment, &color_attachements))
362#define BPYGPU_FB_MAX_COLOR_ATTACHMENT 6
370 PyErr_SetString(PyExc_ValueError,
"Depth texture with incompatible format");
374 int color_attachements_len = 0;
375 if (color_attachements && color_attachements != Py_None) {
376 if (PySequence_Check(color_attachements)) {
377 color_attachements_len = PySequence_Size(color_attachements);
379 PyErr_SetString(PyExc_AttributeError,
384 for (
int i = 0;
i < color_attachements_len;
i++) {
385 PyObject *o = PySequence_GetItem(color_attachements,
i);
397 color_attachements_len = 1;
409 pygpu_framebuffer_is_bound_doc,
410 "Checks if this is the active framebuffer in the context.");
419 pygpu_framebuffer_clear_doc,
420 ".. method:: clear(color=None, depth=None, stencil=None)\n"
422 " Fill color, depth and stencil textures with specific value.\n"
423 " Common values: color=(0.0, 0.0, 0.0, 1.0), depth=1.0, stencil=0.\n"
425 " :arg color: Sequence of 3 or 4 floats representing ``(r, g, b, a)``.\n"
426 " :type color: Sequence[float]\n"
427 " :arg depth: depth value.\n"
428 " :type depth: float\n"
429 " :arg stencil: stencil value.\n"
430 " :type stencil: int\n");
439 PyObject *py_col =
nullptr;
440 PyObject *py_depth =
nullptr;
441 PyObject *py_stencil =
nullptr;
443 static const char *_keywords[] = {
"color",
"depth",
"stencil",
nullptr};
444 static _PyArg_Parser _parser = {
454 if (!_PyArg_ParseTupleAndKeywordsFast(args, kwds, &_parser, &py_col, &py_depth, &py_stencil)) {
459 float col[4] = {0.0f, 0.0f, 0.0f, 1.0f};
463 if (py_col && py_col != Py_None) {
472 if (py_depth && py_depth != Py_None) {
473 depth = PyFloat_AsDouble(py_depth);
474 if (PyErr_Occurred()) {
480 if (py_stencil && py_stencil != Py_None) {
493 pygpu_framebuffer_viewport_set_doc,
494 ".. function:: viewport_set(x, y, xsize, ysize)\n"
496 " Set the viewport for this framebuffer object.\n"
497 " Note: The viewport state is not saved upon framebuffer rebind.\n"
499 " :arg x, y: lower left corner of the viewport_set rectangle, in pixels.\n"
501 " :arg xsize, ysize: width and height of the viewport_set.\n"
502 " :type xsize, ysize: int\n");
507 int x,
y, xsize, ysize;
508 if (!PyArg_ParseTuple(args,
"iiii:viewport_set", &
x, &
y, &xsize, &ysize)) {
518 pygpu_framebuffer_viewport_get_doc,
519 ".. function:: viewport_get()\n"
521 " Returns position and dimension to current viewport.\n");
528 PyObject *
ret = PyTuple_New(4);
530 PyLong_FromLong(viewport[0]),
531 PyLong_FromLong(viewport[1]),
532 PyLong_FromLong(viewport[2]),
533 PyLong_FromLong(viewport[3]));
539 pygpu_framebuffer_read_color_doc,
540 ".. function:: read_color(x, y, xsize, ysize, channels, slot, format, data=data)\n"
542 " Read a block of pixels from the frame buffer.\n"
544 " :arg x, y: Lower left corner of a rectangular block of pixels.\n"
545 " :arg xsize, ysize: Dimensions of the pixel rectangle.\n"
546 " :type x, y, xsize, ysize: int\n"
547 " :arg channels: Number of components to read.\n"
548 " :type channels: int\n"
549 " :arg slot: The framebuffer slot to read data from.\n"
551 " :arg format: The format that describes the content of a single channel.\n"
552 " Possible values are `FLOAT`, `INT`, `UINT`, `UBYTE`, `UINT_24_8` and `10_11_11_REV`.\n"
553 " :type format: str\n"
554 " :arg data: Optional Buffer object to fill with the pixels values.\n"
555 " :type data: :class:`gpu.types.Buffer`\n"
556 " :return: The Buffer with the read pixels.\n"
557 " :rtype: :class:`gpu.types.Buffer`\n");
563 int x,
y,
w, h, channels;
568 static const char *_keywords[] = {
569 "x",
"y",
"xsize",
"ysize",
"channels",
"slot",
"format",
"data",
nullptr};
570 static _PyArg_Parser _parser = {
585 if (!_PyArg_ParseTupleAndKeywordsFast(args,
603 PyErr_SetString(PyExc_AttributeError,
"Color channels must be 1, 2, 3 or 4");
608 PyErr_SetString(PyExc_ValueError,
"slot overflow");
614 PyErr_SetString(PyExc_AttributeError,
615 "the format of the buffer is different from that specified");
620 size_t size_expected =
w * h * channels *
623 if (size_curr < size_expected) {
624 PyErr_SetString(PyExc_BufferError,
"the buffer size is smaller than expected");
627 Py_INCREF(py_buffer);
630 const Py_ssize_t shape[3] = {h,
w, channels};
647 return (PyObject *)py_buffer;
652 pygpu_framebuffer_read_depth_doc,
653 ".. function:: read_depth(x, y, xsize, ysize, data=data)\n"
655 " Read a pixel depth block from the frame buffer.\n"
657 " :arg x, y: Lower left corner of a rectangular block of pixels.\n"
659 " :arg xsize, ysize: Dimensions of the pixel rectangle.\n"
660 " :type xsize, ysize: int\n"
661 " :arg data: Optional Buffer object to fill with the pixels values.\n"
662 " :type data: :class:`gpu.types.Buffer`\n"
663 " :return: The Buffer with the read pixels.\n"
664 " :rtype: :class:`gpu.types.Buffer`\n");
673 static const char *_keywords[] = {
"x",
"y",
"xsize",
"ysize",
"data",
nullptr};
674 static _PyArg_Parser _parser = {
686 if (!_PyArg_ParseTupleAndKeywordsFast(
694 PyErr_SetString(PyExc_AttributeError,
"the format of the buffer must be 'GPU_DATA_FLOAT'");
700 if (size_curr < size_expected) {
701 PyErr_SetString(PyExc_BufferError,
"the buffer size is smaller than expected");
704 Py_INCREF(py_buffer);
707 const Py_ssize_t shape[2] = {h,
w};
715 return (PyObject *)py_buffer;
718#ifdef BPYGPU_USE_GPUOBJ_FREE_METHOD
721 pygpu_framebuffer_free_doc,
722 ".. method:: free()\n"
724 " Free the framebuffer object.\n"
725 " The framebuffer will no longer be accessible.\n");
737 Py_TYPE(
self)->tp_free((PyObject *)
self);
744 pygpu_framebuffer_is_bound_doc,
746 {
nullptr,
nullptr,
nullptr,
nullptr,
nullptr}
751# pragma clang diagnostic push
752# pragma clang diagnostic ignored "-Wcast-function-type"
754# pragma GCC diagnostic push
755# pragma GCC diagnostic ignored "-Wcast-function-type"
763 METH_VARARGS | METH_KEYWORDS,
764 pygpu_framebuffer_clear_doc},
768 pygpu_framebuffer_viewport_set_doc},
772 pygpu_framebuffer_viewport_get_doc},
775 METH_VARARGS | METH_KEYWORDS,
776 pygpu_framebuffer_read_color_doc},
779 METH_VARARGS | METH_KEYWORDS,
780 pygpu_framebuffer_read_depth_doc},
781#ifdef BPYGPU_USE_GPUOBJ_FREE_METHOD
782 {
"free", (PyCFunction)pygpu_framebuffer_free, METH_NOARGS, pygpu_framebuffer_free_doc},
784 {
nullptr,
nullptr, 0,
nullptr},
789# pragma clang diagnostic pop
791# pragma GCC diagnostic pop
799 pygpu_framebuffer__tp_doc,
800 ".. class:: GPUFrameBuffer(depth_slot=None, color_slots=None)\n"
802 " This object gives access to framebuffer functionalities.\n"
803 " When a 'layer' is specified in a argument, a single layer of a 3D or array "
804 "texture is attached to the frame-buffer.\n"
805 " For cube map textures, layer is translated into a cube map face.\n"
807 " :arg depth_slot: GPUTexture to attach or a `dict` containing keywords: "
808 "'texture', 'layer' and 'mip'.\n"
809 " :type depth_slot: :class:`gpu.types.GPUTexture` | dict[] | None\n"
810 " :arg color_slots: Tuple where each item can be a GPUTexture or a `dict` "
811 "containing keywords: 'texture', 'layer' and 'mip'.\n"
812 " :type color_slots: :class:`gpu.types.GPUTexture` | "
813 "dict[str, int | :class:`gpu.types.GPUTexture`] | "
814 "Sequence[:class:`gpu.types.GPUTexture` | dict[str, int | :class:`gpu.types.GPUTexture`]] | "
817 PyVarObject_HEAD_INIT(
nullptr, 0)
837 pygpu_framebuffer__tp_doc,
878#ifndef GPU_NO_USE_PY_REFERENCES
879 if (shared_reference) {
886 return (PyObject *)
self;
896#ifndef GPU_NO_USE_PY_REFERENCES
897 self->shared_reference = shared_reference;
903 return (PyObject *)
self;
908#undef PYGPU_FRAMEBUFFER_CHECK_OBJ
#define POINTER_OFFSET(v, ofs)
#define IN_RANGE_INCL(a, b, c)
GPUContext * GPU_context_active_get()
void GPU_framebuffer_read_color(GPUFrameBuffer *fb, int x, int y, int width, int height, int channels, int slot, eGPUDataFormat data_format, void *r_data)
void GPU_framebuffer_viewport_get(GPUFrameBuffer *fb, int r_viewport[4])
GPUFrameBuffer * GPU_framebuffer_create(const char *name)
GPUFrameBuffer * GPU_framebuffer_active_get()
void GPU_framebuffer_viewport_set(GPUFrameBuffer *fb, int x, int y, int width, int height)
void ** GPU_framebuffer_py_reference_get(GPUFrameBuffer *fb)
void GPU_framebuffer_read_depth(GPUFrameBuffer *fb, int x, int y, int width, int height, eGPUDataFormat data_format, void *r_data)
#define GPU_ATTACHMENT_NONE
uint GPU_framebuffer_stack_level_get()
void GPU_framebuffer_py_reference_set(GPUFrameBuffer *fb, void **py_ref)
void GPU_framebuffer_free(GPUFrameBuffer *fb)
void GPU_framebuffer_bind(GPUFrameBuffer *fb)
void GPU_framebuffer_config_array(GPUFrameBuffer *fb, const GPUAttachment *config, int config_len)
void GPU_framebuffer_push(GPUFrameBuffer *fb)
GPUFrameBuffer * GPU_framebuffer_pop()
void GPU_framebuffer_clear(GPUFrameBuffer *fb, eGPUFrameBufferBits buffers, const float clear_col[4], float clear_depth, unsigned int clear_stencil)
bool GPU_framebuffer_bound(GPUFrameBuffer *fb)
size_t GPU_texture_dataformat_size(eGPUDataFormat data_format)
bool GPU_texture_has_depth_format(const GPUTexture *texture)
SIMD_FORCE_INLINE const btScalar & w() const
Return the w value.
PyC_StringEnumItems bpygpu_dataformat_items[]
#define BPYGPU_IS_INIT_OR_ERROR_OBJ
PyTypeObject BPyGPU_BufferType
BPyGPUBuffer * BPyGPU_Buffer_CreatePyObject(const int format, const Py_ssize_t *shape, const int shape_len, void *buffer)
size_t bpygpu_Buffer_size(BPyGPUBuffer *buffer)
static bool pygpu_framebuffer_stack_pop_and_restore_or_error(GPUFrameBuffer *fb)
static PyObject * pygpu_framebuffer_viewport_get(BPyGPUFrameBuffer *self, void *)
static PyTypeObject FramebufferStackContext_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_is_bound(BPyGPUFrameBuffer *self, void *)
static bool pygpu_framebuffer_stack_push_and_bind_or_error(GPUFrameBuffer *fb)
static PyObject * pygpu_framebuffer_stack_context_enter(PyFrameBufferStackContext *self)
PyObject * BPyGPUFrameBuffer_CreatePyObject(GPUFrameBuffer *fb, bool shared_reference)
static PyObject * pygpu_framebuffer_clear(BPyGPUFrameBuffer *self, PyObject *args, PyObject *kwds)
static PyMethodDef pygpu_framebuffer__tp_methods[]
#define GPU_PY_FRAMEBUFFER_STACK_LEN
static PyObject * pygpu_framebuffer_stack_context_exit(PyFrameBufferStackContext *self, PyObject *)
static void pygpu_framebuffer_free_safe(BPyGPUFrameBuffer *self)
static PyObject * pygpu_framebuffer_bind(BPyGPUFrameBuffer *self)
static PyObject * pygpu_framebuffer__tp_new(PyTypeObject *, PyObject *args, PyObject *kwds)
static PyObject * pygpu_framebuffer_viewport_set(BPyGPUFrameBuffer *self, PyObject *args, void *)
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_read_color(BPyGPUFrameBuffer *self, PyObject *args, PyObject *kwds)
PyTypeObject BPyGPUFrameBuffer_Type
static PyObject * pygpu_framebuffer_read_depth(BPyGPUFrameBuffer *self, PyObject *args, PyObject *kwds)
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)
#define PyUnicode_CompareWithASCIIString
int PyC_ParseStringEnum(PyObject *o, void *p)
uint32_t PyC_Long_AsU32(PyObject *value)
header-only compatibility defines.
#define PY_ARG_PARSER_HEAD_COMPAT()
#define PyTuple_SET_ITEMS(op_arg,...)
union BPyGPUBuffer::@200046006214133143166056243172340141057075323053 buf
PyObject_HEAD GPUFrameBuffer * fb
PyObject_HEAD BPyGPUFrameBuffer * py_fb