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);
172#if (defined(__GNUC__) && !defined(__clang__))
173# pragma GCC diagnostic push
174# pragma GCC diagnostic ignored "-Wcast-function-type"
183#if (defined(__GNUC__) && !defined(__clang__))
184# pragma GCC diagnostic pop
188 PyVarObject_HEAD_INIT(
nullptr, 0)
189 "GPUFrameBufferStackContext",
241 pygpu_framebuffer_bind_doc,
242 ".. function:: bind()\n"
244 " Context manager to ensure balanced bind calls, even in the case of an error.\n");
252 return (PyObject *)
ret;
269 if (!o || o == Py_None) {
278 const char *c_texture =
"texture";
279 const char *c_layer =
"layer";
280 const char *c_mip =
"mip";
281 PyObject *key, *value;
283 while (PyDict_Next(o, &
pos, &key, &value)) {
284 if (!PyUnicode_Check(key)) {
285 PyErr_SetString(PyExc_TypeError,
"keywords must be strings");
289 if (c_texture && _PyUnicode_EqualToASCIIString(key, c_texture)) {
296 else if (c_layer && _PyUnicode_EqualToASCIIString(key, c_layer)) {
299 tmp_attach.
layer = PyLong_AsLong(value);
300 if (tmp_attach.
layer == -1 && PyErr_Occurred()) {
304 else if (c_mip && _PyUnicode_EqualToASCIIString(key, c_mip)) {
307 tmp_attach.
mip = PyLong_AsLong(value);
308 if (tmp_attach.
mip == -1 && PyErr_Occurred()) {
314 PyExc_TypeError,
"'%U' is an invalid keyword argument for this attribute", key);
320 *r_attach = tmp_attach;
329 PyErr_SetString(PyExc_RuntimeError,
"No active GPU context found");
333 PyObject *depth_attachment =
nullptr;
334 PyObject *color_attachements =
nullptr;
335 static const char *_keywords[] = {
"depth_slot",
"color_slots",
nullptr};
336 static _PyArg_Parser _parser = {
341 ":GPUFrameBuffer.__new__",
345 if (!_PyArg_ParseTupleAndKeywordsFast(
346 args, kwds, &_parser, &depth_attachment, &color_attachements))
353#define BPYGPU_FB_MAX_COLOR_ATTACHMENT 6
361 PyErr_SetString(PyExc_ValueError,
"Depth texture with incompatible format");
365 int color_attachements_len = 0;
366 if (color_attachements && color_attachements != Py_None) {
367 if (PySequence_Check(color_attachements)) {
368 color_attachements_len = PySequence_Size(color_attachements);
370 PyErr_SetString(PyExc_AttributeError,
375 for (
int i = 0; i < color_attachements_len; i++) {
376 PyObject *o = PySequence_GetItem(color_attachements, i);
388 color_attachements_len = 1;
400 pygpu_framebuffer_is_bound_doc,
401 "Checks if this is the active framebuffer in the context.");
410 pygpu_framebuffer_clear_doc,
411 ".. method:: clear(color=None, depth=None, stencil=None)\n"
413 " Fill color, depth and stencil textures with specific value.\n"
414 " Common values: color=(0.0, 0.0, 0.0, 1.0), depth=1.0, stencil=0.\n"
416 " :arg color: Sequence of 3 or 4 floats representing ``(r, g, b, a)``.\n"
417 " :type color: Sequence[float]\n"
418 " :arg depth: depth value.\n"
419 " :type depth: float\n"
420 " :arg stencil: stencil value.\n"
421 " :type stencil: int\n");
430 PyObject *py_col =
nullptr;
431 PyObject *py_depth =
nullptr;
432 PyObject *py_stencil =
nullptr;
434 static const char *_keywords[] = {
"color",
"depth",
"stencil",
nullptr};
435 static _PyArg_Parser _parser = {
445 if (!_PyArg_ParseTupleAndKeywordsFast(args, kwds, &_parser, &py_col, &py_depth, &py_stencil)) {
450 float col[4] = {0.0f, 0.0f, 0.0f, 1.0f};
454 if (py_col && py_col != Py_None) {
463 if (py_depth && py_depth != Py_None) {
464 depth = PyFloat_AsDouble(py_depth);
465 if (PyErr_Occurred()) {
471 if (py_stencil && py_stencil != Py_None) {
484 pygpu_framebuffer_viewport_set_doc,
485 ".. function:: viewport_set(x, y, xsize, ysize)\n"
487 " Set the viewport for this framebuffer object.\n"
488 " Note: The viewport state is not saved upon framebuffer rebind.\n"
490 " :arg x, y: lower left corner of the viewport_set rectangle, in pixels.\n"
492 " :arg xsize, ysize: width and height of the viewport_set.\n"
493 " :type xsize, ysize: int\n");
498 int x,
y, xsize, ysize;
499 if (!PyArg_ParseTuple(args,
"iiii:viewport_set", &x, &y, &xsize, &ysize)) {
509 pygpu_framebuffer_viewport_get_doc,
510 ".. function:: viewport_get()\n"
512 " Returns position and dimension to current viewport.\n");
519 PyObject *
ret = PyTuple_New(4);
521 PyLong_FromLong(viewport[0]),
522 PyLong_FromLong(viewport[1]),
523 PyLong_FromLong(viewport[2]),
524 PyLong_FromLong(viewport[3]));
530 pygpu_framebuffer_read_color_doc,
531 ".. function:: read_color(x, y, xsize, ysize, channels, slot, format, data=data)\n"
533 " Read a block of pixels from the frame buffer.\n"
535 " :arg x, y: Lower left corner of a rectangular block of pixels.\n"
536 " :arg xsize, ysize: Dimensions of the pixel rectangle.\n"
537 " :type x, y, xsize, ysize: int\n"
538 " :arg channels: Number of components to read.\n"
539 " :type channels: int\n"
540 " :arg slot: The framebuffer slot to read data from.\n"
542 " :arg format: The format that describes the content of a single channel.\n"
543 " Possible values are `FLOAT`, `INT`, `UINT`, `UBYTE`, `UINT_24_8` and `10_11_11_REV`.\n"
544 " :type format: str\n"
545 " :arg data: Optional Buffer object to fill with the pixels values.\n"
546 " :type data: :class:`gpu.types.Buffer`\n"
547 " :return: The Buffer with the read pixels.\n"
548 " :rtype: :class:`gpu.types.Buffer`\n");
559 static const char *_keywords[] = {
560 "x",
"y",
"xsize",
"ysize",
"channels",
"slot",
"format",
"data",
nullptr};
561 static _PyArg_Parser _parser = {
576 if (!_PyArg_ParseTupleAndKeywordsFast(args,
594 PyErr_SetString(PyExc_AttributeError,
"Color channels must be 1, 2, 3 or 4");
599 PyErr_SetString(PyExc_ValueError,
"slot overflow");
605 PyErr_SetString(PyExc_AttributeError,
606 "the format of the buffer is different from that specified");
611 size_t size_expected =
w * h * channels *
614 if (size_curr < size_expected) {
615 PyErr_SetString(PyExc_BufferError,
"the buffer size is smaller than expected");
618 Py_INCREF(py_buffer);
621 const Py_ssize_t shape[3] = {h,
w, channels};
638 return (PyObject *)py_buffer;
643 pygpu_framebuffer_read_depth_doc,
644 ".. function:: read_depth(x, y, xsize, ysize, data=data)\n"
646 " Read a pixel depth block from the frame buffer.\n"
648 " :arg x, y: Lower left corner of a rectangular block of pixels.\n"
650 " :arg xsize, ysize: Dimensions of the pixel rectangle.\n"
651 " :type xsize, ysize: int\n"
652 " :arg data: Optional Buffer object to fill with the pixels values.\n"
653 " :type data: :class:`gpu.types.Buffer`\n"
654 " :return: The Buffer with the read pixels.\n"
655 " :rtype: :class:`gpu.types.Buffer`\n");
664 static const char *_keywords[] = {
"x",
"y",
"xsize",
"ysize",
"data",
nullptr};
665 static _PyArg_Parser _parser = {
677 if (!_PyArg_ParseTupleAndKeywordsFast(
685 PyErr_SetString(PyExc_AttributeError,
"the format of the buffer must be 'GPU_DATA_FLOAT'");
691 if (size_curr < size_expected) {
692 PyErr_SetString(PyExc_BufferError,
"the buffer size is smaller than expected");
695 Py_INCREF(py_buffer);
698 const Py_ssize_t shape[2] = {h,
w};
706 return (PyObject *)py_buffer;
709#ifdef BPYGPU_USE_GPUOBJ_FREE_METHOD
712 pygpu_framebuffer_free_doc,
713 ".. method:: free()\n"
715 " Free the framebuffer object.\n"
716 " The framebuffer will no longer be accessible.\n");
728 Py_TYPE(
self)->tp_free((PyObject *)
self);
735 pygpu_framebuffer_is_bound_doc,
737 {
nullptr,
nullptr,
nullptr,
nullptr,
nullptr}
740#if (defined(__GNUC__) && !defined(__clang__))
741# pragma GCC diagnostic push
742# pragma GCC diagnostic ignored "-Wcast-function-type"
749 METH_VARARGS | METH_KEYWORDS,
750 pygpu_framebuffer_clear_doc},
754 pygpu_framebuffer_viewport_set_doc},
758 pygpu_framebuffer_viewport_get_doc},
761 METH_VARARGS | METH_KEYWORDS,
762 pygpu_framebuffer_read_color_doc},
765 METH_VARARGS | METH_KEYWORDS,
766 pygpu_framebuffer_read_depth_doc},
767#ifdef BPYGPU_USE_GPUOBJ_FREE_METHOD
768 {
"free", (PyCFunction)pygpu_framebuffer_free, METH_NOARGS, pygpu_framebuffer_free_doc},
770 {
nullptr,
nullptr, 0,
nullptr},
773#if (defined(__GNUC__) && !defined(__clang__))
774# pragma GCC diagnostic pop
781 pygpu_framebuffer__tp_doc,
782 ".. class:: GPUFrameBuffer(depth_slot=None, color_slots=None)\n"
784 " This object gives access to framebuffer functionalities.\n"
785 " When a 'layer' is specified in a argument, a single layer of a 3D or array "
786 "texture is attached to the frame-buffer.\n"
787 " For cube map textures, layer is translated into a cube map face.\n"
789 " :arg depth_slot: GPUTexture to attach or a `dict` containing keywords: "
790 "'texture', 'layer' and 'mip'.\n"
791 " :type depth_slot: :class:`gpu.types.GPUTexture` | dict[] | None\n"
792 " :arg color_slots: Tuple where each item can be a GPUTexture or a `dict` "
793 "containing keywords: 'texture', 'layer' and 'mip'.\n"
794 " :type color_slots: :class:`gpu.types.GPUTexture` | "
795 "dict[str, int | :class:`gpu.types.GPUTexture`] | "
796 "Sequence[:class:`gpu.types.GPUTexture` | dict[str, int | :class:`gpu.types.GPUTexture`]] | "
799 PyVarObject_HEAD_INIT(
nullptr, 0)
819 pygpu_framebuffer__tp_doc,
860#ifndef GPU_NO_USE_PY_REFERENCES
861 if (shared_reference) {
868 return (PyObject *)
self;
878#ifndef GPU_NO_USE_PY_REFERENCES
879 self->shared_reference = shared_reference;
885 return (PyObject *)
self;
890#undef PYGPU_FRAMEBUFFER_CHECK_OBJ
#define POINTER_OFFSET(v, ofs)
#define IN_RANGE_INCL(a, b, c)
GPUContext * GPU_context_active_get()
GPUFrameBuffer * GPU_framebuffer_create(const char *name)
void GPU_framebuffer_push(GPUFrameBuffer *framebuffer)
void GPU_framebuffer_config_array(GPUFrameBuffer *framebuffer, const GPUAttachment *config, int config_len)
GPUFrameBuffer * GPU_framebuffer_active_get()
void GPU_framebuffer_viewport_get(GPUFrameBuffer *framebuffer, int r_viewport[4])
bool GPU_framebuffer_bound(GPUFrameBuffer *framebuffer)
void GPU_framebuffer_py_reference_set(GPUFrameBuffer *framebuffer, void **py_ref)
void ** GPU_framebuffer_py_reference_get(GPUFrameBuffer *framebuffer)
void GPU_framebuffer_read_depth(GPUFrameBuffer *framebuffer, 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_clear(GPUFrameBuffer *framebuffer, eGPUFrameBufferBits buffers, const float clear_col[4], float clear_depth, unsigned int clear_stencil)
void GPU_framebuffer_bind(GPUFrameBuffer *framebuffer)
void GPU_framebuffer_read_color(GPUFrameBuffer *framebuffer, int x, int y, int width, int height, int channels, int slot, eGPUDataFormat data_format, void *r_data)
void GPU_framebuffer_viewport_set(GPUFrameBuffer *framebuffer, int x, int y, int width, int height)
GPUFrameBuffer * GPU_framebuffer_pop()
void GPU_framebuffer_free(GPUFrameBuffer *framebuffer)
size_t GPU_texture_dataformat_size(eGPUDataFormat data_format)
bool GPU_texture_has_depth_format(const GPUTexture *texture)
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 Brightness Control the brightness and contrast of the input color Vector Map input vector components with curves 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 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.
RAYTRACE_GROUP_SIZE additional_info("eevee_shared", "eevee_gbuffer_data", "eevee_global_ubo", "eevee_sampling_data", "eevee_utility_texture", "eevee_hiz_data", "draw_view") .specialization_constant(Type RAYTRACE_GROUP_SIZE in_sh_0_tx in_sh_2_tx screen_normal_tx GPU_RGBA8
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)
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::@1342 buf
PyObject_HEAD GPUFrameBuffer * fb
PyObject_HEAD BPyGPUFrameBuffer * py_fb