Blender V4.3
gpu_py_offscreen.cc
Go to the documentation of this file.
1/* SPDX-FileCopyrightText: 2015 Blender Authors
2 *
3 * SPDX-License-Identifier: GPL-2.0-or-later */
4
15#include <Python.h>
16
17#include "BLI_string.h"
18#include "BLI_utildefines.h"
19
20#include "BKE_global.hh"
21#include "BKE_lib_id.hh" /* For #BKE_id_is_in_global_main. */
22#include "BKE_scene.hh"
23
24#include "DNA_view3d_types.h"
25
26#include "GPU_context.hh"
27#include "GPU_framebuffer.hh"
28#include "GPU_texture.hh"
29#include "GPU_viewport.hh"
30
32
34
37
38#include "gpu_py.hh"
39#include "gpu_py_texture.hh"
40
41#include "gpu_py_offscreen.hh" /* own include */
42
43/* Define the free method to avoid breakage. */
44#define BPYGPU_USE_GPUOBJ_FREE_METHOD
45
46/* -------------------------------------------------------------------- */
51 {GPU_RGBA8, "RGBA8"},
52 {GPU_RGBA16, "RGBA16"},
53 {GPU_RGBA16F, "RGBA16F"},
54 {GPU_RGBA32F, "RGBA32F"},
55 {0, nullptr},
56};
57
59{
60 if (UNLIKELY(py_ofs->ofs == nullptr)) {
61 PyErr_SetString(PyExc_ReferenceError,
63 "GPU offscreen was freed, no further access is valid"
64#else
65 "GPU offscreen: internal error"
66#endif
67 );
68 return -1;
69 }
70 return 0;
71}
72
73#define BPY_GPU_OFFSCREEN_CHECK_OBJ(bpygpu) \
74 { \
75 if (UNLIKELY(pygpu_offscreen_valid_check(bpygpu) == -1)) { \
76 return nullptr; \
77 } \
78 } \
79 ((void)0)
80
83/* -------------------------------------------------------------------- */
91 PyObject_HEAD /* Required Python macro. */
93 int level;
94 bool is_explicitly_bound; /* Bound by "bind" method. */
95};
96
98{
99 Py_DECREF(self->py_offscreen);
100 PyObject_DEL(self);
101}
102
104{
106
107 BPY_GPU_OFFSCREEN_CHECK_OBJ(self->py_offscreen);
108
109 if (!self->is_explicitly_bound) {
110 if (self->level != -1) {
111 PyErr_SetString(PyExc_RuntimeError, "Already in use");
112 return nullptr;
113 }
114
115 GPU_offscreen_bind(self->py_offscreen->ofs, true);
117 }
118
119 Py_RETURN_NONE;
120}
121
123 PyObject * /*args*/)
124{
126
127 BPY_GPU_OFFSCREEN_CHECK_OBJ(self->py_offscreen);
128
129 if (self->level == -1) {
130 PyErr_SetString(PyExc_RuntimeError, "Not yet in use\n");
131 return nullptr;
132 }
133
134 const int level = GPU_framebuffer_stack_level_get();
135 if (level != self->level) {
136 PyErr_Format(
137 PyExc_RuntimeError, "Level of bind mismatch, expected %d, got %d\n", self->level, level);
138 }
139
140 GPU_offscreen_unbind(self->py_offscreen->ofs, true);
141 Py_RETURN_NONE;
142}
143
144#if (defined(__GNUC__) && !defined(__clang__))
145# pragma GCC diagnostic push
146# pragma GCC diagnostic ignored "-Wcast-function-type"
147#endif
148
150 {"__enter__", (PyCFunction)pygpu_offscreen_stack_context_enter, METH_NOARGS},
151 {"__exit__", (PyCFunction)pygpu_offscreen_stack_context_exit, METH_VARARGS},
152 {nullptr},
153};
154
155#if (defined(__GNUC__) && !defined(__clang__))
156# pragma GCC diagnostic pop
157#endif
158
159static PyTypeObject PyGPUOffscreenStackContext_Type = {
160 /*ob_base*/ PyVarObject_HEAD_INIT(nullptr, 0)
161 /*tp_name*/ "GPUFrameBufferStackContext",
162 /*tp_basicsize*/ sizeof(OffScreenStackContext),
163 /*tp_itemsize*/ 0,
164 /*tp_dealloc*/ (destructor)pygpu_offscreen_stack_context__tp_dealloc,
165 /*tp_vectorcall_offset*/ 0,
166 /*tp_getattr*/ nullptr,
167 /*tp_setattr*/ nullptr,
168 /*tp_as_async*/ nullptr,
169 /*tp_repr*/ nullptr,
170 /*tp_as_number*/ nullptr,
171 /*tp_as_sequence*/ nullptr,
172 /*tp_as_mapping*/ nullptr,
173 /*tp_hash*/ nullptr,
174 /*tp_call*/ nullptr,
175 /*tp_str*/ nullptr,
176 /*tp_getattro*/ nullptr,
177 /*tp_setattro*/ nullptr,
178 /*tp_as_buffer*/ nullptr,
179 /*tp_flags*/ Py_TPFLAGS_DEFAULT,
180 /*tp_doc*/ nullptr,
181 /*tp_traverse*/ nullptr,
182 /*tp_clear*/ nullptr,
183 /*tp_richcompare*/ nullptr,
184 /*tp_weaklistoffset*/ 0,
185 /*tp_iter*/ nullptr,
186 /*tp_iternext*/ nullptr,
188 /*tp_members*/ nullptr,
189 /*tp_getset*/ nullptr,
190 /*tp_base*/ nullptr,
191 /*tp_dict*/ nullptr,
192 /*tp_descr_get*/ nullptr,
193 /*tp_descr_set*/ nullptr,
194 /*tp_dictoffset*/ 0,
195 /*tp_init*/ nullptr,
196 /*tp_alloc*/ nullptr,
197 /*tp_new*/ nullptr,
198 /*tp_free*/ nullptr,
199 /*tp_is_gc*/ nullptr,
200 /*tp_bases*/ nullptr,
201 /*tp_mro*/ nullptr,
202 /*tp_cache*/ nullptr,
203 /*tp_subclasses*/ nullptr,
204 /*tp_weaklist*/ nullptr,
205 /*tp_del*/ nullptr,
206 /*tp_version_tag*/ 0,
207 /*tp_finalize*/ nullptr,
208 /*tp_vectorcall*/ nullptr,
209};
210
212 /* Wrap. */
213 pygpu_offscreen_bind_doc,
214 ".. function:: bind()\n"
215 "\n"
216 " Context manager to ensure balanced bind calls, even in the case of an error.\n");
218{
221 ret->py_offscreen = self;
222 ret->level = -1;
223 ret->is_explicitly_bound = false;
224 Py_INCREF(self);
225
227 ret->is_explicitly_bound = true;
228
229 return (PyObject *)ret;
230}
231
233 /* Wrap. */
234 pygpu_offscreen_unbind_doc,
235 ".. method:: unbind(restore=True)\n"
236 "\n"
237 " Unbind the offscreen object.\n"
238 "\n"
239 " :arg restore: Restore the OpenGL state, can only be used when the state has been "
240 "saved before.\n"
241 " :type restore: bool\n");
242static PyObject *pygpu_offscreen_unbind(BPyGPUOffScreen *self, PyObject *args, PyObject *kwds)
243{
244 bool restore = true;
245
247
248 static const char *_keywords[] = {"restore", nullptr};
249 static _PyArg_Parser _parser = {
251 "|$" /* Optional keyword only arguments. */
252 "O&" /* `restore` */
253 ":unbind",
254 _keywords,
255 nullptr,
256 };
257 if (!_PyArg_ParseTupleAndKeywordsFast(args, kwds, &_parser, PyC_ParseBool, &restore)) {
258 return nullptr;
259 }
260
261 GPU_offscreen_unbind(self->ofs, restore);
263 Py_RETURN_NONE;
264}
265
268/* -------------------------------------------------------------------- */
272static PyObject *pygpu_offscreen__tp_new(PyTypeObject * /*self*/, PyObject *args, PyObject *kwds)
273{
275
276 GPUOffScreen *ofs = nullptr;
277 int width, height;
279 char err_out[256];
280
281 static const char *_keywords[] = {"width", "height", "format", nullptr};
282 static _PyArg_Parser _parser = {
284 "i" /* `width` */
285 "i" /* `height` */
286 "|$" /* Optional keyword only arguments. */
287 "O&" /* `format` */
288 ":GPUOffScreen.__new__",
289 _keywords,
290 nullptr,
291 };
292 if (!_PyArg_ParseTupleAndKeywordsFast(
293 args, kwds, &_parser, &width, &height, PyC_ParseStringEnum, &pygpu_textureformat))
294 {
295 return nullptr;
296 }
297
299 ofs = GPU_offscreen_create(width,
300 height,
301 true,
302 eGPUTextureFormat(pygpu_textureformat.value_found),
304 err_out);
305 }
306 else {
307 STRNCPY(err_out, "No active GPU context found");
308 }
309
310 if (ofs == nullptr) {
311 PyErr_Format(PyExc_RuntimeError,
312 "gpu.offscreen.new(...) failed with '%s'",
313 err_out[0] ? err_out : "unknown error");
314 return nullptr;
315 }
316
318}
319
321 /* Wrap. */
322 pygpu_offscreen_width_doc,
323 "Width of the texture.\n"
324 "\n"
325 ":type: int");
326static PyObject *pygpu_offscreen_width_get(BPyGPUOffScreen *self, void * /*type*/)
327{
329 return PyLong_FromLong(GPU_offscreen_width(self->ofs));
330}
331
333 /* Wrap. */
334 pygpu_offscreen_height_doc,
335 "Height of the texture.\n"
336 "\n"
337 ":type: int");
338static PyObject *pygpu_offscreen_height_get(BPyGPUOffScreen *self, void * /*type*/)
339{
341 return PyLong_FromLong(GPU_offscreen_height(self->ofs));
342}
343
345 /* Wrap. */
346 pygpu_offscreen_color_texture_doc,
347 "OpenGL bindcode for the color texture.\n"
348 "\n"
349 ":type: int");
350static PyObject *pygpu_offscreen_color_texture_get(BPyGPUOffScreen *self, void * /*type*/)
351{
353 GPUTexture *texture = GPU_offscreen_color_texture(self->ofs);
354 return PyLong_FromLong(GPU_texture_opengl_bindcode(texture));
355}
356
358 /* Wrap. */
359 pygpu_offscreen_texture_color_doc,
360 "The color texture attached.\n"
361 "\n"
362 ":type: :class:`gpu.types.GPUTexture`");
363static PyObject *pygpu_offscreen_texture_color_get(BPyGPUOffScreen *self, void * /*type*/)
364{
366 GPUTexture *texture = GPU_offscreen_color_texture(self->ofs);
367 return BPyGPUTexture_CreatePyObject(texture, true);
368}
369
371 /* Wrap. */
372 pygpu_offscreen_draw_view3d_doc,
373 ".. method:: draw_view3d(scene, view_layer, view3d, region, view_matrix, projection_matrix, "
374 "do_color_management=False, draw_background=True)\n"
375 "\n"
376 " Draw the 3d viewport in the offscreen object.\n"
377 "\n"
378 " :arg scene: Scene to draw.\n"
379 " :type scene: :class:`bpy.types.Scene`\n"
380 " :arg view_layer: View layer to draw.\n"
381 " :type view_layer: :class:`bpy.types.ViewLayer`\n"
382 " :arg view3d: 3D View to get the drawing settings from.\n"
383 " :type view3d: :class:`bpy.types.SpaceView3D`\n"
384 " :arg region: Region of the 3D View (required as temporary draw target).\n"
385 " :type region: :class:`bpy.types.Region`\n"
386 " :arg view_matrix: View Matrix (e.g. ``camera.matrix_world.inverted()``).\n"
387 " :type view_matrix: :class:`mathutils.Matrix`\n"
388 " :arg projection_matrix: Projection Matrix (e.g. ``camera.calc_matrix_camera(...)``).\n"
389 " :type projection_matrix: :class:`mathutils.Matrix`\n"
390 " :arg do_color_management: Color manage the output.\n"
391 " :type do_color_management: bool\n"
392 " :arg draw_background: Draw background.\n"
393 " :type draw_background: bool\n");
394static PyObject *pygpu_offscreen_draw_view3d(BPyGPUOffScreen *self, PyObject *args, PyObject *kwds)
395{
396 MatrixObject *py_mat_view, *py_mat_projection;
397 PyObject *py_scene, *py_view_layer, *py_region, *py_view3d;
398
399 Depsgraph *depsgraph;
400 Scene *scene;
401 ViewLayer *view_layer;
402 View3D *v3d;
403 ARegion *region;
404
405 bool do_color_management = false;
406 bool draw_background = true;
407
409
410 static const char *_keywords[] = {
411 "scene",
412 "view_layer",
413 "view3d",
414 "region",
415 "view_matrix",
416 "projection_matrix",
417 "do_color_management",
418 "draw_background",
419 nullptr,
420 };
421 static _PyArg_Parser _parser = {
423 "O" /* `scene` */
424 "O" /* `view_layer` */
425 "O" /* `view3d` */
426 "O" /* `region` */
427 "O&" /* `view_matrix` */
428 "O&" /* `projection_matrix` */
429 "|$" /* Optional keyword only arguments. */
430 "O&" /* `do_color_management` */
431 "O&" /* `draw_background` */
432 ":draw_view3d",
433 _keywords,
434 nullptr,
435 };
436 if (!_PyArg_ParseTupleAndKeywordsFast(args,
437 kwds,
438 &_parser,
439 &py_scene,
440 &py_view_layer,
441 &py_view3d,
442 &py_region,
444 &py_mat_view,
446 &py_mat_projection,
448 &do_color_management,
450 &draw_background) ||
451 (!(scene = static_cast<Scene *>(PyC_RNA_AsPointer(py_scene, "Scene"))) ||
452 !(view_layer = static_cast<ViewLayer *>(PyC_RNA_AsPointer(py_view_layer, "ViewLayer"))) ||
453 !(v3d = static_cast<View3D *>(PyC_RNA_AsPointer(py_view3d, "SpaceView3D"))) ||
454 !(region = static_cast<ARegion *>(PyC_RNA_AsPointer(py_region, "Region")))))
455 {
456 return nullptr;
457 }
458
460 /* NOTE(@ideasman42): Nested draw calls could be supported.
461 * Adding support for this looks to be possible but non-trivial. */
462 PyErr_SetString(PyExc_RuntimeError, "Nested off-screen drawing not supported");
463 return nullptr;
464 }
465
467
468 depsgraph = BKE_scene_ensure_depsgraph(G_MAIN, scene, view_layer);
469
470 /* Disable 'bgl' state since it interfere with off-screen drawing, see: #84402. */
471 const bool is_bgl = GPU_bgl_get();
472 if (is_bgl) {
473 GPU_bgl_end();
474 }
475
476 GPU_offscreen_bind(self->ofs, true);
477
478 /* Cache the #GPUViewport so the frame-buffers and associated textures are
479 * not reallocated each time, see: #89204 */
480 if (!self->viewport) {
481 self->viewport = GPU_viewport_create();
482 }
483 else {
484 GPU_viewport_tag_update(self->viewport);
485 }
486
488 scene,
489 eDrawType(v3d->shading.type),
490 v3d,
491 region,
494 (const float(*)[4])py_mat_view->matrix,
495 (const float(*)[4])py_mat_projection->matrix,
496 true,
498 "",
499 do_color_management,
500 true,
501 self->ofs,
502 self->viewport);
503
504 GPU_offscreen_unbind(self->ofs, true);
505
506 if (is_bgl) {
508 }
509
510 Py_RETURN_NONE;
511}
512
513#ifdef BPYGPU_USE_GPUOBJ_FREE_METHOD
515 /* Wrap. */
516 pygpu_offscreen_free_doc,
517 ".. method:: free()\n"
518 "\n"
519 " Free the offscreen object.\n"
520 " The framebuffer, texture and render objects will no longer be accessible.\n");
522{
524
525 if (self->viewport) {
526 GPU_viewport_free(self->viewport);
527 self->viewport = nullptr;
528 }
529
531 self->ofs = nullptr;
532 Py_RETURN_NONE;
533}
534#endif
535
537{
538 if (self->viewport) {
539 GPU_viewport_free(self->viewport);
540 }
541 if (self->ofs) {
543 }
544 Py_TYPE(self)->tp_free((PyObject *)self);
545}
546
547static PyGetSetDef pygpu_offscreen__tp_getseters[] = {
548 {"color_texture",
550 (setter) nullptr,
551 pygpu_offscreen_color_texture_doc,
552 nullptr},
553 {"texture_color",
555 (setter) nullptr,
556 pygpu_offscreen_texture_color_doc,
557 nullptr},
558 {"width",
560 (setter) nullptr,
561 pygpu_offscreen_width_doc,
562 nullptr},
563 {"height",
565 (setter) nullptr,
566 pygpu_offscreen_height_doc,
567 nullptr},
568 {nullptr, nullptr, nullptr, nullptr, nullptr} /* Sentinel */
569};
570
571#if (defined(__GNUC__) && !defined(__clang__))
572# pragma GCC diagnostic push
573# pragma GCC diagnostic ignored "-Wcast-function-type"
574#endif
575
576static PyMethodDef pygpu_offscreen__tp_methods[] = {
577 {"bind", (PyCFunction)pygpu_offscreen_bind, METH_NOARGS, pygpu_offscreen_bind_doc},
578 {"unbind",
579 (PyCFunction)pygpu_offscreen_unbind,
580 METH_VARARGS | METH_KEYWORDS,
581 pygpu_offscreen_unbind_doc},
582 {"draw_view3d",
583 (PyCFunction)pygpu_offscreen_draw_view3d,
584 METH_VARARGS | METH_KEYWORDS,
585 pygpu_offscreen_draw_view3d_doc},
586#ifdef BPYGPU_USE_GPUOBJ_FREE_METHOD
587 {"free", (PyCFunction)pygpu_offscreen_free, METH_NOARGS, pygpu_offscreen_free_doc},
588#endif
589 {nullptr, nullptr, 0, nullptr},
590};
591
592#if (defined(__GNUC__) && !defined(__clang__))
593# pragma GCC diagnostic pop
594#endif
595
597 /* Wrap. */
598 pygpu_offscreen__tp_doc,
599 ".. class:: GPUOffScreen(width, height, *, format='RGBA8')\n"
600 "\n"
601 " This object gives access to off screen buffers.\n"
602 "\n"
603 " :arg width: Horizontal dimension of the buffer.\n"
604 " :type width: int\n"
605 " :arg height: Vertical dimension of the buffer.\n"
606 " :type height: int\n"
607 " :arg format: Internal data format inside GPU memory for color attachment "
608 "texture. Possible values are:\n"
609 " `RGBA8`,\n"
610 " `RGBA16`,\n"
611 " `RGBA16F`,\n"
612 " `RGBA32F`,\n"
613 " :type format: str\n");
614PyTypeObject BPyGPUOffScreen_Type = {
615 /*ob_base*/ PyVarObject_HEAD_INIT(nullptr, 0)
616 /*tp_name*/ "GPUOffScreen",
617 /*tp_basicsize*/ sizeof(BPyGPUOffScreen),
618 /*tp_itemsize*/ 0,
619 /*tp_dealloc*/ (destructor)BPyGPUOffScreen__tp_dealloc,
620 /*tp_vectorcall_offset*/ 0,
621 /*tp_getattr*/ nullptr,
622 /*tp_setattr*/ nullptr,
623 /*tp_compare*/ nullptr,
624 /*tp_repr*/ nullptr,
625 /*tp_as_number*/ nullptr,
626 /*tp_as_sequence*/ nullptr,
627 /*tp_as_mapping*/ nullptr,
628 /*tp_hash*/ nullptr,
629 /*tp_call*/ nullptr,
630 /*tp_str*/ nullptr,
631 /*tp_getattro*/ nullptr,
632 /*tp_setattro*/ nullptr,
633 /*tp_as_buffer*/ nullptr,
634 /*tp_flags*/ Py_TPFLAGS_DEFAULT,
635 /*tp_doc*/ pygpu_offscreen__tp_doc,
636 /*tp_traverse*/ nullptr,
637 /*tp_clear*/ nullptr,
638 /*tp_richcompare*/ nullptr,
639 /*tp_weaklistoffset*/ 0,
640 /*tp_iter*/ nullptr,
641 /*tp_iternext*/ nullptr,
642 /*tp_methods*/ pygpu_offscreen__tp_methods,
643 /*tp_members*/ nullptr,
644 /*tp_getset*/ pygpu_offscreen__tp_getseters,
645 /*tp_base*/ nullptr,
646 /*tp_dict*/ nullptr,
647 /*tp_descr_get*/ nullptr,
648 /*tp_descr_set*/ nullptr,
649 /*tp_dictoffset*/ 0,
650 /*tp_init*/ nullptr,
651 /*tp_alloc*/ nullptr,
652 /*tp_new*/ pygpu_offscreen__tp_new,
653 /*tp_free*/ nullptr,
654 /*tp_is_gc*/ nullptr,
655 /*tp_bases*/ nullptr,
656 /*tp_mro*/ nullptr,
657 /*tp_cache*/ nullptr,
658 /*tp_subclasses*/ nullptr,
659 /*tp_weaklist*/ nullptr,
660 /*tp_del*/ nullptr,
661 /*tp_version_tag*/ 0,
662 /*tp_finalize*/ nullptr,
663 /*tp_vectorcall*/ nullptr,
664};
665
668/* -------------------------------------------------------------------- */
673{
675
676 self = PyObject_New(BPyGPUOffScreen, &BPyGPUOffScreen_Type);
677 self->ofs = ofs;
678 self->viewport = nullptr;
679
680 return (PyObject *)self;
681}
682
685#undef BPY_GPU_OFFSCREEN_CHECK_OBJ
#define G_MAIN
bool BKE_id_is_in_global_main(ID *id)
Definition lib_id.cc:2433
Depsgraph * BKE_scene_ensure_depsgraph(Main *bmain, Scene *scene, ViewLayer *view_layer)
Definition scene.cc:3377
#define BLI_assert(a)
Definition BLI_assert.h:50
#define STRNCPY(dst, src)
Definition BLI_string.h:593
#define UNLIKELY(x)
eDrawType
bool ED_view3d_draw_offscreen_check_nested()
void ED_view3d_draw_offscreen(Depsgraph *depsgraph, const Scene *scene, eDrawType drawtype, View3D *v3d, ARegion *region, int winx, int winy, const float viewmat[4][4], const float winmat[4][4], bool is_image_render, bool draw_background, const char *viewname, bool do_color_management, bool restore_rv3d_mats, GPUOffScreen *ofs, GPUViewport *viewport)
GPUContext * GPU_context_active_get()
GPUOffScreen * GPU_offscreen_create(int width, int height, bool with_depth_buffer, eGPUTextureFormat format, eGPUTextureUsage usage, char err_out[256])
int GPU_offscreen_width(const GPUOffScreen *offscreen)
void GPU_offscreen_bind(GPUOffScreen *offscreen, bool save)
uint GPU_framebuffer_stack_level_get()
int GPU_offscreen_height(const GPUOffScreen *offscreen)
GPUTexture * GPU_offscreen_color_texture(const GPUOffScreen *offscreen)
void GPU_offscreen_free(GPUOffScreen *offscreen)
void GPU_offscreen_unbind(GPUOffScreen *offscreen, bool restore)
void GPU_bgl_start()
Definition gpu_state.cc:319
void GPU_bgl_end()
Definition gpu_state.cc:349
bool GPU_bgl_get()
Definition gpu_state.cc:363
void GPU_apply_state()
Definition gpu_state.cc:304
int GPU_texture_opengl_bindcode(const GPUTexture *texture)
@ GPU_TEXTURE_USAGE_SHADER_READ
@ GPU_TEXTURE_USAGE_HOST_READ
eGPUTextureFormat
@ GPU_RGBA16
GPUViewport * GPU_viewport_create()
void GPU_viewport_free(GPUViewport *viewport)
void GPU_viewport_tag_update(GPUViewport *viewport)
PyObject * self
additional_info("compositor_sum_float_shared") .push_constant(Type additional_info("compositor_sum_float_shared") .push_constant(Type GPU_RGBA32F
const Depsgraph * depsgraph
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
#define BPYGPU_IS_INIT_OR_ERROR_OBJ
Definition gpu_py.hh:18
static PyMethodDef pygpu_offscreen_stack_context__tp_methods[]
static PyObject * pygpu_offscreen_color_texture_get(BPyGPUOffScreen *self, void *)
PyDoc_STRVAR(pygpu_offscreen_bind_doc, ".. function:: bind()\n" "\n" " Context manager to ensure balanced bind calls, even in the case of an error.\n")
PyObject * BPyGPUOffScreen_CreatePyObject(GPUOffScreen *ofs)
#define BPY_GPU_OFFSCREEN_CHECK_OBJ(bpygpu)
static PyMethodDef pygpu_offscreen__tp_methods[]
#define BPYGPU_USE_GPUOBJ_FREE_METHOD
static int pygpu_offscreen_valid_check(BPyGPUOffScreen *py_ofs)
static void BPyGPUOffScreen__tp_dealloc(BPyGPUOffScreen *self)
static PyObject * pygpu_offscreen_texture_color_get(BPyGPUOffScreen *self, void *)
PyTypeObject BPyGPUOffScreen_Type
static PyObject * pygpu_offscreen_width_get(BPyGPUOffScreen *self, void *)
static PyObject * pygpu_offscreen__tp_new(PyTypeObject *, PyObject *args, PyObject *kwds)
static PyObject * pygpu_offscreen_draw_view3d(BPyGPUOffScreen *self, PyObject *args, PyObject *kwds)
static PyObject * pygpu_offscreen_bind(BPyGPUOffScreen *self)
static PyTypeObject PyGPUOffscreenStackContext_Type
static void pygpu_offscreen_stack_context__tp_dealloc(OffScreenStackContext *self)
static PyObject * pygpu_offscreen_unbind(BPyGPUOffScreen *self, PyObject *args, PyObject *kwds)
static PyObject * pygpu_offscreen_free(BPyGPUOffScreen *self)
static PyObject * pygpu_offscreen_height_get(BPyGPUOffScreen *self, void *)
static PyGetSetDef pygpu_offscreen__tp_getseters[]
static const PyC_StringEnumItems pygpu_framebuffer_color_texture_formats[]
static PyObject * pygpu_offscreen_stack_context_enter(OffScreenStackContext *self)
static PyObject * pygpu_offscreen_stack_context_exit(OffScreenStackContext *self, PyObject *)
PyObject * BPyGPUTexture_CreatePyObject(GPUTexture *tex, bool shared_reference)
int Matrix_Parse4x4(PyObject *o, void *p)
void * PyC_RNA_AsPointer(PyObject *value, const char *type_name)
int PyC_ParseStringEnum(PyObject *o, void *p)
int PyC_ParseBool(PyObject *o, void *p)
header-only compatibility defines.
#define PY_ARG_PARSER_HEAD_COMPAT()
return ret
static void draw_background()
PyObject_HEAD GPUOffScreen * ofs
PyObject_HEAD BPyGPUOffScreen * py_offscreen
View3DShading shading