34 #include "../mathutils/mathutils.h"
36 #include "../generic/py_capi_utils.h"
44 #define BPYGPU_USE_GPUOBJ_FREE_METHOD
61 PyErr_SetString(PyExc_ReferenceError,
63 "GPU offscreen was freed, no further access is valid"
65 "GPU offscreen: internal error"
73 #define BPY_GPU_OFFSCREEN_CHECK_OBJ(bpygpu) \
75 if (UNLIKELY(pygpu_offscreen_valid_check(bpygpu) == -1)) { \
99 Py_DECREF(
self->py_offscreen);
107 if (!
self->is_explicitly_bound) {
108 if (
self->level != -1) {
109 PyErr_SetString(PyExc_RuntimeError,
"Already in use");
125 if (
self->level == -1) {
126 PyErr_SetString(PyExc_RuntimeError,
"Not yet in use\n");
131 if (level !=
self->level) {
133 PyExc_RuntimeError,
"Level of bind mismatch, expected %d, got %d\n",
self->level, level);
147 PyVarObject_HEAD_INIT(
NULL, 0).tp_name =
"GPUFrameBufferStackContext",
150 .tp_flags = Py_TPFLAGS_DEFAULT,
155 ".. function:: bind()\n"
157 " Context manager to ensure balanced bind calls, even in the case of an error.\n");
162 ret->py_offscreen =
self;
164 ret->is_explicitly_bound =
false;
168 ret->is_explicitly_bound =
true;
170 return (PyObject *)
ret;
174 ".. method:: unbind(restore=True)\n"
176 " Unbind the offscreen object.\n"
178 " :arg restore: Restore the OpenGL state, can only be used when the state has been "
180 " :type restore: bool\n");
187 static const char *_keywords[] = {
"restore",
NULL};
188 static _PyArg_Parser _parser = {
195 if (!_PyArg_ParseTupleAndKeywordsFast(args, kwds, &_parser,
PyC_ParseBool, &restore)) {
221 static const char *_keywords[] = {
"width",
"height",
"format",
NULL};
222 static _PyArg_Parser _parser = {
227 ":GPUOffScreen.__new__",
231 if (!_PyArg_ParseTupleAndKeywordsFast(
240 STRNCPY(err_out,
"No active GPU context found");
244 PyErr_Format(PyExc_RuntimeError,
245 "gpu.offscreen.new(...) failed with '%s'",
246 err_out[0] ? err_out :
"unknown error");
253 PyDoc_STRVAR(pygpu_offscreen_width_doc,
"Width of the texture.\n\n:type: `int`");
260 PyDoc_STRVAR(pygpu_offscreen_height_doc,
"Height of the texture.\n\n:type: `int`");
268 "OpenGL bindcode for the color texture.\n\n:type: `int`");
277 "The color texture attached.\n"
279 ":type: :class:`gpu.types.GPUTexture`");
288 pygpu_offscreen_draw_view3d_doc,
289 ".. method:: draw_view3d(scene, view_layer, view3d, region, view_matrix, projection_matrix, "
290 "do_color_management=False)\n"
292 " Draw the 3d viewport in the offscreen object.\n"
294 " :arg scene: Scene to draw.\n"
295 " :type scene: :class:`bpy.types.Scene`\n"
296 " :arg view_layer: View layer to draw.\n"
297 " :type view_layer: :class:`bpy.types.ViewLayer`\n"
298 " :arg view3d: 3D View to get the drawing settings from.\n"
299 " :type view3d: :class:`bpy.types.SpaceView3D`\n"
300 " :arg region: Region of the 3D View (required as temporary draw target).\n"
301 " :type region: :class:`bpy.types.Region`\n"
302 " :arg view_matrix: View Matrix (e.g. ``camera.matrix_world.inverted()``).\n"
303 " :type view_matrix: :class:`mathutils.Matrix`\n"
304 " :arg projection_matrix: Projection Matrix (e.g. ``camera.calc_matrix_camera(...)``).\n"
305 " :type projection_matrix: :class:`mathutils.Matrix`\n"
306 " :arg do_color_management: Color manage the output.\n"
307 " :type do_color_management: bool\n");
311 PyObject *py_scene, *py_view_layer, *py_region, *py_view3d;
319 bool do_color_management =
false;
323 static const char *_keywords[] = {
330 "do_color_management",
333 static _PyArg_Parser _parser = {
346 if (!_PyArg_ParseTupleAndKeywordsFast(args,
358 &do_color_management) ||
380 if (!
self->viewport) {
394 (
const float(*)[4])py_mat_view->matrix,
395 (
const float(*)[4])py_mat_projection->matrix,
413 #ifdef BPYGPU_USE_GPUOBJ_FREE_METHOD
415 ".. method:: free()\n"
417 " Free the offscreen object.\n"
418 " The framebuffer, texture and render objects will no longer be accessible.\n");
423 if (
self->viewport) {
425 self->viewport =
NULL;
436 if (
self->viewport) {
442 Py_TYPE(
self)->tp_free((PyObject *)
self);
449 pygpu_offscreen_color_texture_doc,
454 pygpu_offscreen_texture_color_doc,
465 METH_VARARGS | METH_KEYWORDS,
466 pygpu_offscreen_unbind_doc},
469 METH_VARARGS | METH_KEYWORDS,
470 pygpu_offscreen_draw_view3d_doc},
471 #ifdef BPYGPU_USE_GPUOBJ_FREE_METHOD
478 ".. class:: GPUOffScreen(width, height, *, format='RGBA8')\n"
480 " This object gives access to off screen buffers.\n"
482 " :arg width: Horizontal dimension of the buffer.\n"
483 " :type width: int\n"
484 " :arg height: Vertical dimension of the buffer.\n"
485 " :type height: int\n"
486 " :arg format: Internal data format inside GPU memory for color attachment "
487 "texture. Possible values are:\n"
492 " :type format: str\n");
494 PyVarObject_HEAD_INIT(
NULL, 0).tp_name =
"GPUOffScreen",
497 .tp_flags = Py_TPFLAGS_DEFAULT,
498 .tp_doc = pygpu_offscreen__tp_doc,
516 self->viewport =
NULL;
518 return (PyObject *)
self;
523 #undef BPY_GPU_OFFSCREEN_CHECK_OBJ
bool BKE_id_is_in_global_main(struct ID *id)
struct Depsgraph * BKE_scene_ensure_depsgraph(struct Main *bmain, struct Scene *scene, struct ViewLayer *view_layer)
#define STRNCPY(dst, src)
struct Depsgraph Depsgraph
void ED_view3d_draw_offscreen(struct Depsgraph *depsgraph, const struct Scene *scene, eDrawType drawtype, struct View3D *v3d, struct 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, struct GPUOffScreen *ofs, struct GPUViewport *viewport)
GPUContext * GPU_context_active_get(void)
_GL_VOID GLfloat value _GL_VOID_RET _GL_VOID const GLuint GLboolean *residences _GL_BOOL_RET _GL_VOID GLsizei height
_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 GLsizei width
void GPU_apply_state(void)
struct GPUTexture GPUTexture
int GPU_texture_opengl_bindcode(const GPUTexture *tex)
GPUViewport * GPU_viewport_create(void)
void GPU_viewport_free(GPUViewport *viewport)
void GPU_viewport_tag_update(GPUViewport *viewport)
const Depsgraph * depsgraph
depth_tx normal_tx diffuse_light_tx specular_light_tx volume_light_tx environment_tx ambient_occlusion_tx aov_value_tx in_weight_img GPU_RGBA16F
void GPU_offscreen_free(GPUOffScreen *ofs)
void GPU_offscreen_unbind(GPUOffScreen *UNUSED(ofs), bool restore)
GPUOffScreen * GPU_offscreen_create(int width, int height, bool depth, eGPUTextureFormat format, char err_out[256])
uint GPU_framebuffer_stack_level_get()
int GPU_offscreen_width(const GPUOffScreen *ofs)
void GPU_offscreen_bind(GPUOffScreen *ofs, bool save)
GPUTexture * GPU_offscreen_color_texture(const GPUOffScreen *ofs)
int GPU_offscreen_height(const GPUOffScreen *ofs)
#define BPYGPU_IS_INIT_OR_ERROR_OBJ
static PyMethodDef pygpu_offscreen_stack_context__tp_methods[]
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")
#define BPY_GPU_OFFSCREEN_CHECK_OBJ(bpygpu)
#define BPYGPU_USE_GPUOBJ_FREE_METHOD
static PyObject * pygpu_offscreen__tp_new(PyTypeObject *UNUSED(self), PyObject *args, PyObject *kwds)
static int pygpu_offscreen_valid_check(BPyGPUOffScreen *py_ofs)
static PyObject * pygpu_offscreen_stack_context_exit(OffScreenStackContext *self, PyObject *UNUSED(args))
static struct PyMethodDef pygpu_offscreen__tp_methods[]
static PyObject * pygpu_offscreen_width_get(BPyGPUOffScreen *self, void *UNUSED(type))
static void BPyGPUOffScreen__tp_dealloc(BPyGPUOffScreen *self)
static PyObject * pygpu_offscreen_texture_color_get(BPyGPUOffScreen *self, void *UNUSED(type))
static PyObject * pygpu_offscreen_unbind(BPyGPUOffScreen *self, PyObject *args, PyObject *kwds)
PyTypeObject BPyGPUOffScreen_Type
static PyObject * pygpu_offscreen_bind(BPyGPUOffScreen *self)
static PyObject * pygpu_offscreen_stack_context_enter(OffScreenStackContext *self)
static const struct PyC_StringEnumItems pygpu_framebuffer_color_texture_formats[]
static PyObject * pygpu_offscreen_height_get(BPyGPUOffScreen *self, void *UNUSED(type))
static PyObject * pygpu_offscreen_free(BPyGPUOffScreen *self)
static PyTypeObject PyGPUOffscreenStackContext_Type
static void pygpu_offscreen_stack_context__tp_dealloc(OffScreenStackContext *self)
static PyObject * pygpu_offscreen_color_texture_get(BPyGPUOffScreen *self, void *UNUSED(type))
static PyGetSetDef pygpu_offscreen__tp_getseters[]
PyObject * BPyGPUOffScreen_CreatePyObject(GPUOffScreen *ofs)
static PyObject * pygpu_offscreen_draw_view3d(BPyGPUOffScreen *self, PyObject *args, PyObject *kwds)
struct BPyGPUOffScreen BPyGPUOffScreen
PyObject * BPyGPUTexture_CreatePyObject(GPUTexture *tex, bool shared_reference)
int Matrix_Parse4x4(PyObject *o, void *p)
int PyC_ParseStringEnum(PyObject *o, void *p)
void * PyC_RNA_AsPointer(PyObject *value, const char *type_name)
int PyC_ParseBool(PyObject *o, void *p)
PyObject_HEAD struct GPUOffScreen * ofs
PyObject_HEAD BPyGPUOffScreen * py_offscreen