Blender V4.3
python.cc
Go to the documentation of this file.
1/* SPDX-FileCopyrightText: 2011-2022 Blender Authors
2 *
3 * SPDX-License-Identifier: GPL-2.0-or-later */
4
5#include "final_engine.hh"
6#include "preview_engine.hh"
7#include "viewport_engine.hh"
8
9#include <Python.h>
10
11#include "RE_engine.h"
12
13#include "../generic/py_capi_utils.hh"
14#include "bpy_rna.hh"
15
16#include "BKE_context.hh"
17
18#include "RE_engine.h"
19
20#include "RNA_prototypes.hh"
21
22#include "hydra/image.hh"
23
24namespace blender::render::hydra {
25
26template<typename T> T *pyrna_to_pointer(PyObject *pyobject, const StructRNA *rnatype)
27{
28 const PointerRNA *ptr = pyrna_struct_as_ptr_or_null(pyobject, rnatype);
29 return (ptr) ? static_cast<T *>(ptr->data) : nullptr;
30}
31
32static PyObject *engine_create_func(PyObject * /*self*/, PyObject *args)
33{
34 PyObject *pyengine;
35 char *engine_type, *render_delegate_id;
36 if (!PyArg_ParseTuple(args, "Oss", &pyengine, &engine_type, &render_delegate_id)) {
37 return nullptr;
38 }
39
40 RenderEngine *bl_engine = pyrna_to_pointer<RenderEngine>(pyengine, &RNA_RenderEngine);
41
42 CLOG_INFO(LOG_HYDRA_RENDER, 1, "Engine %s", engine_type);
43 Engine *engine = nullptr;
44 try {
45 if (STREQ(engine_type, "VIEWPORT")) {
46 engine = new ViewportEngine(bl_engine, render_delegate_id);
47 }
48 else if (STREQ(engine_type, "PREVIEW")) {
49 engine = new PreviewEngine(bl_engine, render_delegate_id);
50 }
51 else {
52 engine = new FinalEngine(bl_engine, render_delegate_id);
53 }
54 }
55 catch (std::runtime_error &e) {
56 CLOG_ERROR(LOG_HYDRA_RENDER, "%s", e.what());
57 }
58
59 CLOG_INFO(LOG_HYDRA_RENDER, 1, "Engine %p", engine);
60 return PyLong_FromVoidPtr(engine);
61}
62
63static PyObject *engine_free_func(PyObject * /*self*/, PyObject *args)
64{
65 PyObject *pyengine;
66 if (!PyArg_ParseTuple(args, "O", &pyengine)) {
67 return nullptr;
68 }
69
70 Engine *engine = static_cast<Engine *>(PyLong_AsVoidPtr(pyengine));
71 CLOG_INFO(LOG_HYDRA_RENDER, 1, "Engine %p", engine);
72 delete engine;
73
74 Py_RETURN_NONE;
75}
76
77static PyObject *engine_update_func(PyObject * /*self*/, PyObject *args)
78{
79 PyObject *pyengine, *pydepsgraph, *pycontext;
80 if (!PyArg_ParseTuple(args, "OOO", &pyengine, &pydepsgraph, &pycontext)) {
81 return nullptr;
82 }
83
84 Engine *engine = static_cast<Engine *>(PyLong_AsVoidPtr(pyengine));
85 Depsgraph *depsgraph = pyrna_to_pointer<Depsgraph>(pydepsgraph, &RNA_Depsgraph);
86 bContext *context = pyrna_to_pointer<bContext>(pycontext, &RNA_Context);
87
88 CLOG_INFO(LOG_HYDRA_RENDER, 2, "Engine %p", engine);
89 engine->sync(depsgraph, context);
90
91 Py_RETURN_NONE;
92}
93
94static PyObject *engine_render_func(PyObject * /*self*/, PyObject *args)
95{
96 PyObject *pyengine;
97 if (!PyArg_ParseTuple(args, "O", &pyengine)) {
98 return nullptr;
99 }
100
101 Engine *engine = static_cast<Engine *>(PyLong_AsVoidPtr(pyengine));
102
103 CLOG_INFO(LOG_HYDRA_RENDER, 2, "Engine %p", engine);
104
105 /* Allow Blender to execute other Python scripts. */
106 Py_BEGIN_ALLOW_THREADS;
107 engine->render();
108 Py_END_ALLOW_THREADS;
109
110 Py_RETURN_NONE;
111}
112
113static PyObject *engine_view_draw_func(PyObject * /*self*/, PyObject *args)
114{
115 PyObject *pyengine, *pycontext;
116 if (!PyArg_ParseTuple(args, "OO", &pyengine, &pycontext)) {
117 return nullptr;
118 }
119
120 ViewportEngine *engine = static_cast<ViewportEngine *>(PyLong_AsVoidPtr(pyengine));
121 bContext *context = pyrna_to_pointer<bContext>(pycontext, &RNA_Context);
122
123 CLOG_INFO(LOG_HYDRA_RENDER, 3, "Engine %p", engine);
124
125 /* Allow Blender to execute other Python scripts. */
126 Py_BEGIN_ALLOW_THREADS;
127 engine->render(context);
128 Py_END_ALLOW_THREADS;
129
130 Py_RETURN_NONE;
131}
132
133static pxr::VtValue get_setting_val(PyObject *pyval)
134{
135 pxr::VtValue val;
136 if (PyBool_Check(pyval)) {
137 val = Py_IsTrue(pyval);
138 }
139 else if (PyLong_Check(pyval)) {
140 val = PyLong_AsLong(pyval);
141 }
142 else if (PyFloat_Check(pyval)) {
143 val = PyFloat_AsDouble(pyval);
144 }
145 else if (PyUnicode_Check(pyval)) {
146 val = std::string(PyUnicode_AsUTF8(pyval));
147 }
148 return val;
149}
150
151static PyObject *engine_set_render_setting_func(PyObject * /*self*/, PyObject *args)
152{
153 PyObject *pyengine, *pyval;
154 char *key;
155 if (!PyArg_ParseTuple(args, "OsO", &pyengine, &key, &pyval)) {
156 return nullptr;
157 }
158
159 Engine *engine = static_cast<Engine *>(PyLong_AsVoidPtr(pyengine));
160
161 CLOG_INFO(LOG_HYDRA_RENDER, 3, "Engine %p: %s", engine, key);
162 engine->set_render_setting(key, get_setting_val(pyval));
163
164 Py_RETURN_NONE;
165}
166
167static PyObject *cache_or_get_image_file_func(PyObject * /*self*/, PyObject *args)
168{
169 PyObject *pycontext, *pyimage;
170 if (!PyArg_ParseTuple(args, "OO", &pycontext, &pyimage)) {
171 return nullptr;
172 }
173
174 bContext *context = static_cast<bContext *>(PyLong_AsVoidPtr(pycontext));
175 Image *image = static_cast<Image *>(PyLong_AsVoidPtr(pyimage));
176
177 std::string image_path = io::hydra::cache_or_get_image_file(
178 CTX_data_main(context), CTX_data_scene(context), image, nullptr);
179 return PyC_UnicodeFromStdStr(image_path);
180}
181
182static PyMethodDef methods[] = {
183 {"engine_create", engine_create_func, METH_VARARGS, ""},
184 {"engine_free", engine_free_func, METH_VARARGS, ""},
185 {"engine_update", engine_update_func, METH_VARARGS, ""},
186 {"engine_render", engine_render_func, METH_VARARGS, ""},
187 {"engine_view_draw", engine_view_draw_func, METH_VARARGS, ""},
188 {"engine_set_render_setting", engine_set_render_setting_func, METH_VARARGS, ""},
189
190 {"cache_or_get_image_file", cache_or_get_image_file_func, METH_VARARGS, ""},
191
192 {nullptr, nullptr, 0, nullptr},
193};
194
195static PyModuleDef module = {
196 PyModuleDef_HEAD_INIT,
197 "_bpy_hydra",
198 "Hydra render API",
199 -1,
200 methods,
201 nullptr,
202 nullptr,
203 nullptr,
204 nullptr,
205};
206
207} // namespace blender::render::hydra
208
209PyObject *BPyInit_hydra();
210
211PyObject *BPyInit_hydra()
212{
213 PyObject *mod = PyModule_Create(&blender::render::hydra::module);
214 return mod;
215}
Scene * CTX_data_scene(const bContext *C)
Main * CTX_data_main(const bContext *C)
#define STREQ(a, b)
#define CLOG_ERROR(clg_ref,...)
Definition CLG_log.h:182
#define CLOG_INFO(clg_ref, level,...)
Definition CLG_log.h:179
ATTR_WARN_UNUSED_RESULT const BMVert const BMEdge * e
const PointerRNA * pyrna_struct_as_ptr_or_null(PyObject *py_obj, const StructRNA *srna)
Definition bpy_rna.cc:8191
void sync(Depsgraph *depsgraph, bContext *context)
virtual void set_render_setting(const std::string &key, const pxr::VtValue &val)
const Depsgraph * depsgraph
std::string cache_or_get_image_file(Main *bmain, Scene *scene, Image *image, ImageUser *iuser)
static pxr::VtValue get_setting_val(PyObject *pyval)
Definition python.cc:133
static PyObject * engine_view_draw_func(PyObject *, PyObject *args)
Definition python.cc:113
static PyObject * engine_set_render_setting_func(PyObject *, PyObject *args)
Definition python.cc:151
static PyObject * engine_free_func(PyObject *, PyObject *args)
Definition python.cc:63
static PyObject * engine_render_func(PyObject *, PyObject *args)
Definition python.cc:94
static PyObject * engine_update_func(PyObject *, PyObject *args)
Definition python.cc:77
static PyObject * cache_or_get_image_file_func(PyObject *, PyObject *args)
Definition python.cc:167
static PyObject * engine_create_func(PyObject *, PyObject *args)
Definition python.cc:32
struct CLG_LogRef * LOG_HYDRA_RENDER
T * pyrna_to_pointer(PyObject *pyobject, const StructRNA *rnatype)
Definition python.cc:26
static PyMethodDef methods[]
Definition python.cc:182
PyObject * PyC_UnicodeFromStdStr(const std::string &str)
PyObject * BPyInit_hydra()
Definition python.cc:211
static struct PyModuleDef module
Definition python.cpp:991
void * data
Definition RNA_types.hh:42
ccl_device_inline int mod(int x, int m)
Definition util/math.h:520
PointerRNA * ptr
Definition wm_files.cc:4126