Merge branch 'blender2.7'
[blender.git] / intern / cycles / blender / blender_python.cpp
1 /*
2  * Copyright 2011-2013 Blender Foundation
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16
17 #include <Python.h>
18
19 #include "blender/CCL_api.h"
20
21 #include "blender/blender_device.h"
22 #include "blender/blender_sync.h"
23 #include "blender/blender_session.h"
24
25 #include "render/denoising.h"
26
27 #include "util/util_debug.h"
28 #include "util/util_foreach.h"
29 #include "util/util_logging.h"
30 #include "util/util_md5.h"
31 #include "util/util_opengl.h"
32 #include "util/util_path.h"
33 #include "util/util_string.h"
34 #include "util/util_types.h"
35
36 #ifdef WITH_OSL
37 #include "render/osl.h"
38
39 #include <OSL/oslquery.h>
40 #include <OSL/oslconfig.h>
41 #endif
42
43 CCL_NAMESPACE_BEGIN
44
45 namespace {
46
47 /* Flag describing whether debug flags were synchronized from scene. */
48 bool debug_flags_set = false;
49
50 void *pylong_as_voidptr_typesafe(PyObject *object)
51 {
52         if(object == Py_None)
53                 return NULL;
54         return PyLong_AsVoidPtr(object);
55 }
56
57 /* Synchronize debug flags from a given Blender scene.
58  * Return truth when device list needs invalidation.
59  */
60 bool debug_flags_sync_from_scene(BL::Scene b_scene)
61 {
62         DebugFlagsRef flags = DebugFlags();
63         PointerRNA cscene = RNA_pointer_get(&b_scene.ptr, "cycles");
64         /* Backup some settings for comparison. */
65         DebugFlags::OpenCL::DeviceType opencl_device_type = flags.opencl.device_type;
66         DebugFlags::OpenCL::KernelType opencl_kernel_type = flags.opencl.kernel_type;
67         /* Synchronize shared flags. */
68         flags.viewport_static_bvh = get_enum(cscene, "debug_bvh_type");
69         /* Synchronize CPU flags. */
70         flags.cpu.avx2 = get_boolean(cscene, "debug_use_cpu_avx2");
71         flags.cpu.avx = get_boolean(cscene, "debug_use_cpu_avx");
72         flags.cpu.sse41 = get_boolean(cscene, "debug_use_cpu_sse41");
73         flags.cpu.sse3 = get_boolean(cscene, "debug_use_cpu_sse3");
74         flags.cpu.sse2 = get_boolean(cscene, "debug_use_cpu_sse2");
75         flags.cpu.bvh_layout = (BVHLayout)get_enum(cscene, "debug_bvh_layout");
76         flags.cpu.split_kernel = get_boolean(cscene, "debug_use_cpu_split_kernel");
77         /* Synchronize CUDA flags. */
78         flags.cuda.adaptive_compile = get_boolean(cscene, "debug_use_cuda_adaptive_compile");
79         flags.cuda.split_kernel = get_boolean(cscene, "debug_use_cuda_split_kernel");
80         /* Synchronize OpenCL kernel type. */
81         switch(get_enum(cscene, "debug_opencl_kernel_type")) {
82                 case 0:
83                         flags.opencl.kernel_type = DebugFlags::OpenCL::KERNEL_DEFAULT;
84                         break;
85                 case 1:
86                         flags.opencl.kernel_type = DebugFlags::OpenCL::KERNEL_MEGA;
87                         break;
88                 case 2:
89                         flags.opencl.kernel_type = DebugFlags::OpenCL::KERNEL_SPLIT;
90                         break;
91         }
92         /* Synchronize OpenCL device type. */
93         switch(get_enum(cscene, "debug_opencl_device_type")) {
94                 case 0:
95                         flags.opencl.device_type = DebugFlags::OpenCL::DEVICE_NONE;
96                         break;
97                 case 1:
98                         flags.opencl.device_type = DebugFlags::OpenCL::DEVICE_ALL;
99                         break;
100                 case 2:
101                         flags.opencl.device_type = DebugFlags::OpenCL::DEVICE_DEFAULT;
102                         break;
103                 case 3:
104                         flags.opencl.device_type = DebugFlags::OpenCL::DEVICE_CPU;
105                         break;
106                 case 4:
107                         flags.opencl.device_type = DebugFlags::OpenCL::DEVICE_GPU;
108                         break;
109                 case 5:
110                         flags.opencl.device_type = DebugFlags::OpenCL::DEVICE_ACCELERATOR;
111                         break;
112         }
113         /* Synchronize other OpenCL flags. */
114         flags.opencl.debug = get_boolean(cscene, "debug_use_opencl_debug");
115         flags.opencl.mem_limit = ((size_t)get_int(cscene, "debug_opencl_mem_limit"))*1024*1024;
116         flags.opencl.single_program = get_boolean(cscene, "debug_opencl_kernel_single_program");
117         return flags.opencl.device_type != opencl_device_type ||
118                flags.opencl.kernel_type != opencl_kernel_type;
119 }
120
121 /* Reset debug flags to default values.
122  * Return truth when device list needs invalidation.
123  */
124 bool debug_flags_reset()
125 {
126         DebugFlagsRef flags = DebugFlags();
127         /* Backup some settings for comparison. */
128         DebugFlags::OpenCL::DeviceType opencl_device_type = flags.opencl.device_type;
129         DebugFlags::OpenCL::KernelType opencl_kernel_type = flags.opencl.kernel_type;
130         flags.reset();
131         return flags.opencl.device_type != opencl_device_type ||
132                flags.opencl.kernel_type != opencl_kernel_type;
133 }
134
135 }  /* namespace */
136
137 void python_thread_state_save(void **python_thread_state)
138 {
139         *python_thread_state = (void*)PyEval_SaveThread();
140 }
141
142 void python_thread_state_restore(void **python_thread_state)
143 {
144         PyEval_RestoreThread((PyThreadState*)*python_thread_state);
145         *python_thread_state = NULL;
146 }
147
148 static const char *PyC_UnicodeAsByte(PyObject *py_str, PyObject **coerce)
149 {
150         const char *result = _PyUnicode_AsString(py_str);
151         if(result) {
152                 /* 99% of the time this is enough but we better support non unicode
153                  * chars since blender doesnt limit this.
154                  */
155                 return result;
156         }
157         else {
158                 PyErr_Clear();
159                 if(PyBytes_Check(py_str)) {
160                         return PyBytes_AS_STRING(py_str);
161                 }
162                 else if((*coerce = PyUnicode_EncodeFSDefault(py_str))) {
163                         return PyBytes_AS_STRING(*coerce);
164                 }
165                 else {
166                         /* Clear the error, so Cycles can be at leadt used without
167                          * GPU and OSL support,
168                          */
169                         PyErr_Clear();
170                         return "";
171                 }
172         }
173 }
174
175 static PyObject *init_func(PyObject * /*self*/, PyObject *args)
176 {
177         PyObject *path, *user_path;
178         int headless;
179
180         if(!PyArg_ParseTuple(args, "OOi", &path, &user_path, &headless)) {
181                 return NULL;
182         }
183
184         PyObject *path_coerce = NULL, *user_path_coerce = NULL;
185         path_init(PyC_UnicodeAsByte(path, &path_coerce),
186                   PyC_UnicodeAsByte(user_path, &user_path_coerce));
187         Py_XDECREF(path_coerce);
188         Py_XDECREF(user_path_coerce);
189
190         BlenderSession::headless = headless;
191
192         VLOG(2) << "Debug flags initialized to:\n"
193                 << DebugFlags();
194
195         Py_RETURN_NONE;
196 }
197
198
199 static PyObject *exit_func(PyObject * /*self*/, PyObject * /*args*/)
200 {
201         ShaderManager::free_memory();
202         TaskScheduler::free_memory();
203         Device::free_memory();
204         Py_RETURN_NONE;
205 }
206
207 static PyObject *create_func(PyObject * /*self*/, PyObject *args)
208 {
209         PyObject *pyengine, *pypreferences, *pydata, *pyregion, *pyv3d, *pyrv3d;
210         int preview_osl;
211
212         if(!PyArg_ParseTuple(args, "OOOOOOi", &pyengine, &pypreferences, &pydata,
213                              &pyregion, &pyv3d, &pyrv3d, &preview_osl))
214         {
215                 return NULL;
216         }
217
218         /* RNA */
219         PointerRNA engineptr;
220         RNA_pointer_create(NULL, &RNA_RenderEngine, (void*)PyLong_AsVoidPtr(pyengine), &engineptr);
221         BL::RenderEngine engine(engineptr);
222
223         PointerRNA preferencesptr;
224         RNA_pointer_create(NULL, &RNA_Preferences, (void*)PyLong_AsVoidPtr(pypreferences), &preferencesptr);
225         BL::Preferences preferences(preferencesptr);
226
227         PointerRNA dataptr;
228         RNA_main_pointer_create((Main*)PyLong_AsVoidPtr(pydata), &dataptr);
229         BL::BlendData data(dataptr);
230
231         PointerRNA regionptr;
232         RNA_pointer_create(NULL, &RNA_Region, pylong_as_voidptr_typesafe(pyregion), &regionptr);
233         BL::Region region(regionptr);
234
235         PointerRNA v3dptr;
236         RNA_pointer_create(NULL, &RNA_SpaceView3D, pylong_as_voidptr_typesafe(pyv3d), &v3dptr);
237         BL::SpaceView3D v3d(v3dptr);
238
239         PointerRNA rv3dptr;
240         RNA_pointer_create(NULL, &RNA_RegionView3D, pylong_as_voidptr_typesafe(pyrv3d), &rv3dptr);
241         BL::RegionView3D rv3d(rv3dptr);
242
243         /* create session */
244         BlenderSession *session;
245
246         if(rv3d) {
247                 /* interactive viewport session */
248                 int width = region.width();
249                 int height = region.height();
250
251                 session = new BlenderSession(engine, preferences, data, v3d, rv3d, width, height);
252         }
253         else {
254                 /* offline session or preview render */
255                 session = new BlenderSession(engine, preferences, data, preview_osl);
256         }
257
258         return PyLong_FromVoidPtr(session);
259 }
260
261 static PyObject *free_func(PyObject * /*self*/, PyObject *value)
262 {
263         delete (BlenderSession*)PyLong_AsVoidPtr(value);
264
265         Py_RETURN_NONE;
266 }
267
268 static PyObject *render_func(PyObject * /*self*/, PyObject *args)
269 {
270         PyObject *pysession, *pydepsgraph;
271
272         if(!PyArg_ParseTuple(args, "OO", &pysession, &pydepsgraph))
273                 return NULL;
274
275         BlenderSession *session = (BlenderSession*)PyLong_AsVoidPtr(pysession);
276
277         PointerRNA depsgraphptr;
278         RNA_pointer_create(NULL, &RNA_Depsgraph, (ID*)PyLong_AsVoidPtr(pydepsgraph), &depsgraphptr);
279         BL::Depsgraph b_depsgraph(depsgraphptr);
280
281         python_thread_state_save(&session->python_thread_state);
282
283         session->render(b_depsgraph);
284
285         python_thread_state_restore(&session->python_thread_state);
286
287         Py_RETURN_NONE;
288 }
289
290 /* pixel_array and result passed as pointers */
291 static PyObject *bake_func(PyObject * /*self*/, PyObject *args)
292 {
293         PyObject *pysession, *pydepsgraph, *pyobject;
294         PyObject *pypixel_array, *pyresult;
295         const char *pass_type;
296         int num_pixels, depth, object_id, pass_filter;
297
298         if(!PyArg_ParseTuple(args, "OOOsiiOiiO", &pysession, &pydepsgraph, &pyobject, &pass_type, &pass_filter, &object_id, &pypixel_array, &num_pixels, &depth, &pyresult))
299                 return NULL;
300
301         BlenderSession *session = (BlenderSession*)PyLong_AsVoidPtr(pysession);
302
303         PointerRNA depsgraphptr;
304         RNA_pointer_create(NULL, &RNA_Depsgraph, PyLong_AsVoidPtr(pydepsgraph), &depsgraphptr);
305         BL::Depsgraph b_depsgraph(depsgraphptr);
306
307         PointerRNA objectptr;
308         RNA_id_pointer_create((ID*)PyLong_AsVoidPtr(pyobject), &objectptr);
309         BL::Object b_object(objectptr);
310
311         void *b_result = PyLong_AsVoidPtr(pyresult);
312
313         PointerRNA bakepixelptr;
314         RNA_pointer_create(NULL, &RNA_BakePixel, PyLong_AsVoidPtr(pypixel_array), &bakepixelptr);
315         BL::BakePixel b_bake_pixel(bakepixelptr);
316
317         python_thread_state_save(&session->python_thread_state);
318
319         session->bake(b_depsgraph, b_object, pass_type, pass_filter, object_id, b_bake_pixel, (size_t)num_pixels, depth, (float *)b_result);
320
321         python_thread_state_restore(&session->python_thread_state);
322
323         Py_RETURN_NONE;
324 }
325
326 static PyObject *draw_func(PyObject * /*self*/, PyObject *args)
327 {
328         PyObject *pysession, *pygraph, *pyv3d, *pyrv3d;
329
330         if(!PyArg_ParseTuple(args, "OOOO", &pysession, &pygraph, &pyv3d, &pyrv3d))
331                 return NULL;
332
333         BlenderSession *session = (BlenderSession*)PyLong_AsVoidPtr(pysession);
334
335         if(PyLong_AsVoidPtr(pyrv3d)) {
336                 /* 3d view drawing */
337                 int viewport[4];
338                 glGetIntegerv(GL_VIEWPORT, viewport);
339
340                 session->draw(viewport[2], viewport[3]);
341         }
342
343         Py_RETURN_NONE;
344 }
345
346 static PyObject *reset_func(PyObject * /*self*/, PyObject *args)
347 {
348         PyObject *pysession, *pydata, *pydepsgraph;
349
350         if(!PyArg_ParseTuple(args, "OOO", &pysession, &pydata, &pydepsgraph))
351                 return NULL;
352
353         BlenderSession *session = (BlenderSession*)PyLong_AsVoidPtr(pysession);
354
355         PointerRNA dataptr;
356         RNA_main_pointer_create((Main*)PyLong_AsVoidPtr(pydata), &dataptr);
357         BL::BlendData b_data(dataptr);
358
359         PointerRNA depsgraphptr;
360         RNA_pointer_create(NULL, &RNA_Depsgraph, PyLong_AsVoidPtr(pydepsgraph), &depsgraphptr);
361         BL::Depsgraph b_depsgraph(depsgraphptr);
362
363         python_thread_state_save(&session->python_thread_state);
364
365         session->reset_session(b_data, b_depsgraph);
366
367         python_thread_state_restore(&session->python_thread_state);
368
369         Py_RETURN_NONE;
370 }
371
372 static PyObject *sync_func(PyObject * /*self*/, PyObject *args)
373 {
374         PyObject *pysession, *pydepsgraph;
375
376         if(!PyArg_ParseTuple(args, "OO", &pysession, &pydepsgraph))
377                 return NULL;
378
379         BlenderSession *session = (BlenderSession*)PyLong_AsVoidPtr(pysession);
380
381         PointerRNA depsgraphptr;
382         RNA_pointer_create(NULL, &RNA_Depsgraph, PyLong_AsVoidPtr(pydepsgraph), &depsgraphptr);
383         BL::Depsgraph b_depsgraph(depsgraphptr);
384
385         python_thread_state_save(&session->python_thread_state);
386
387         session->synchronize(b_depsgraph);
388
389         python_thread_state_restore(&session->python_thread_state);
390
391         Py_RETURN_NONE;
392 }
393
394 static PyObject *available_devices_func(PyObject * /*self*/, PyObject * args)
395 {
396         const char *type_name;
397         if(!PyArg_ParseTuple(args, "s", &type_name)) {
398                 return NULL;
399         }
400
401         DeviceType type = Device::type_from_string(type_name);
402         uint mask = (type == DEVICE_NONE) ? DEVICE_MASK_ALL : DEVICE_MASK(type);
403         mask |= DEVICE_MASK_CPU;
404
405         vector<DeviceInfo> devices = Device::available_devices(mask);
406         PyObject *ret = PyTuple_New(devices.size());
407
408         for(size_t i = 0; i < devices.size(); i++) {
409                 DeviceInfo& device = devices[i];
410                 string type_name = Device::string_from_type(device.type);
411                 PyObject *device_tuple = PyTuple_New(3);
412                 PyTuple_SET_ITEM(device_tuple, 0, PyUnicode_FromString(device.description.c_str()));
413                 PyTuple_SET_ITEM(device_tuple, 1, PyUnicode_FromString(type_name.c_str()));
414                 PyTuple_SET_ITEM(device_tuple, 2, PyUnicode_FromString(device.id.c_str()));
415                 PyTuple_SET_ITEM(ret, i, device_tuple);
416         }
417
418         return ret;
419 }
420
421 #ifdef WITH_OSL
422
423 static PyObject *osl_update_node_func(PyObject * /*self*/, PyObject *args)
424 {
425         PyObject *pydata, *pynodegroup, *pynode;
426         const char *filepath = NULL;
427
428         if(!PyArg_ParseTuple(args, "OOOs", &pydata, &pynodegroup, &pynode, &filepath))
429                 return NULL;
430
431         /* RNA */
432         PointerRNA dataptr;
433         RNA_main_pointer_create((Main*)PyLong_AsVoidPtr(pydata), &dataptr);
434         BL::BlendData b_data(dataptr);
435
436         PointerRNA nodeptr;
437         RNA_pointer_create((ID*)PyLong_AsVoidPtr(pynodegroup), &RNA_ShaderNodeScript, (void*)PyLong_AsVoidPtr(pynode), &nodeptr);
438         BL::ShaderNodeScript b_node(nodeptr);
439
440         /* update bytecode hash */
441         string bytecode = b_node.bytecode();
442
443         if(!bytecode.empty()) {
444                 MD5Hash md5;
445                 md5.append((const uint8_t*)bytecode.c_str(), bytecode.size());
446                 b_node.bytecode_hash(md5.get_hex().c_str());
447         }
448         else
449                 b_node.bytecode_hash("");
450
451         /* query from file path */
452         OSL::OSLQuery query;
453
454         if(!OSLShaderManager::osl_query(query, filepath))
455                 Py_RETURN_FALSE;
456
457         /* add new sockets from parameters */
458         set<void*> used_sockets;
459
460         for(int i = 0; i < query.nparams(); i++) {
461                 const OSL::OSLQuery::Parameter *param = query.getparam(i);
462
463                 /* skip unsupported types */
464                 if(param->varlenarray || param->isstruct || param->type.arraylen > 1)
465                         continue;
466
467                 /* determine socket type */
468                 string socket_type;
469                 BL::NodeSocket::type_enum data_type = BL::NodeSocket::type_VALUE;
470                 float4 default_float4 = make_float4(0.0f, 0.0f, 0.0f, 1.0f);
471                 float default_float = 0.0f;
472                 int default_int = 0;
473                 string default_string = "";
474
475                 if(param->isclosure) {
476                         socket_type = "NodeSocketShader";
477                         data_type = BL::NodeSocket::type_SHADER;
478                 }
479                 else if(param->type.vecsemantics == TypeDesc::COLOR) {
480                         socket_type = "NodeSocketColor";
481                         data_type = BL::NodeSocket::type_RGBA;
482
483                         if(param->validdefault) {
484                                 default_float4[0] = param->fdefault[0];
485                                 default_float4[1] = param->fdefault[1];
486                                 default_float4[2] = param->fdefault[2];
487                         }
488                 }
489                 else if(param->type.vecsemantics == TypeDesc::POINT ||
490                         param->type.vecsemantics == TypeDesc::VECTOR ||
491                         param->type.vecsemantics == TypeDesc::NORMAL)
492                 {
493                         socket_type = "NodeSocketVector";
494                         data_type = BL::NodeSocket::type_VECTOR;
495
496                         if(param->validdefault) {
497                                 default_float4[0] = param->fdefault[0];
498                                 default_float4[1] = param->fdefault[1];
499                                 default_float4[2] = param->fdefault[2];
500                         }
501                 }
502                 else if(param->type.aggregate == TypeDesc::SCALAR) {
503                         if(param->type.basetype == TypeDesc::INT) {
504                                 socket_type = "NodeSocketInt";
505                                 data_type = BL::NodeSocket::type_INT;
506                                 if(param->validdefault)
507                                         default_int = param->idefault[0];
508                         }
509                         else if(param->type.basetype == TypeDesc::FLOAT) {
510                                 socket_type = "NodeSocketFloat";
511                                 data_type = BL::NodeSocket::type_VALUE;
512                                 if(param->validdefault)
513                                         default_float = param->fdefault[0];
514                         }
515                         else if(param->type.basetype == TypeDesc::STRING) {
516                                 socket_type = "NodeSocketString";
517                                 data_type = BL::NodeSocket::type_STRING;
518                                 if(param->validdefault)
519                                         default_string = param->sdefault[0].string();
520                         }
521                         else
522                                 continue;
523                 }
524                 else
525                         continue;
526
527                 /* find socket socket */
528                 BL::NodeSocket b_sock(PointerRNA_NULL);
529                 if(param->isoutput) {
530                         b_sock = b_node.outputs[param->name.string()];
531                         /* remove if type no longer matches */
532                         if(b_sock && b_sock.bl_idname() != socket_type) {
533                                 b_node.outputs.remove(b_data, b_sock);
534                                 b_sock = BL::NodeSocket(PointerRNA_NULL);
535                         }
536                 }
537                 else {
538                         b_sock = b_node.inputs[param->name.string()];
539                         /* remove if type no longer matches */
540                         if(b_sock && b_sock.bl_idname() != socket_type) {
541                                 b_node.inputs.remove(b_data, b_sock);
542                                 b_sock = BL::NodeSocket(PointerRNA_NULL);
543                         }
544                 }
545
546                 if(!b_sock) {
547                         /* create new socket */
548                         if(param->isoutput)
549                                 b_sock = b_node.outputs.create(b_data, socket_type.c_str(), param->name.c_str(), param->name.c_str());
550                         else
551                                 b_sock = b_node.inputs.create(b_data, socket_type.c_str(), param->name.c_str(), param->name.c_str());
552
553                         /* set default value */
554                         if(data_type == BL::NodeSocket::type_VALUE) {
555                                 set_float(b_sock.ptr, "default_value", default_float);
556                         }
557                         else if(data_type == BL::NodeSocket::type_INT) {
558                                 set_int(b_sock.ptr, "default_value", default_int);
559                         }
560                         else if(data_type == BL::NodeSocket::type_RGBA) {
561                                 set_float4(b_sock.ptr, "default_value", default_float4);
562                         }
563                         else if(data_type == BL::NodeSocket::type_VECTOR) {
564                                 set_float3(b_sock.ptr, "default_value", float4_to_float3(default_float4));
565                         }
566                         else if(data_type == BL::NodeSocket::type_STRING) {
567                                 set_string(b_sock.ptr, "default_value", default_string);
568                         }
569                 }
570
571                 used_sockets.insert(b_sock.ptr.data);
572         }
573
574         /* remove unused parameters */
575         bool removed;
576
577         do {
578                 BL::Node::inputs_iterator b_input;
579                 BL::Node::outputs_iterator b_output;
580
581                 removed = false;
582
583                 for(b_node.inputs.begin(b_input); b_input != b_node.inputs.end(); ++b_input) {
584                         if(used_sockets.find(b_input->ptr.data) == used_sockets.end()) {
585                                 b_node.inputs.remove(b_data, *b_input);
586                                 removed = true;
587                                 break;
588                         }
589                 }
590
591                 for(b_node.outputs.begin(b_output); b_output != b_node.outputs.end(); ++b_output) {
592                         if(used_sockets.find(b_output->ptr.data) == used_sockets.end()) {
593                                 b_node.outputs.remove(b_data, *b_output);
594                                 removed = true;
595                                 break;
596                         }
597                 }
598         } while(removed);
599
600         Py_RETURN_TRUE;
601 }
602
603 static PyObject *osl_compile_func(PyObject * /*self*/, PyObject *args)
604 {
605         const char *inputfile = NULL, *outputfile = NULL;
606
607         if(!PyArg_ParseTuple(args, "ss", &inputfile, &outputfile))
608                 return NULL;
609
610         /* return */
611         if(!OSLShaderManager::osl_compile(inputfile, outputfile))
612                 Py_RETURN_FALSE;
613
614         Py_RETURN_TRUE;
615 }
616 #endif
617
618 static PyObject *system_info_func(PyObject * /*self*/, PyObject * /*value*/)
619 {
620         string system_info = Device::device_capabilities();
621         return PyUnicode_FromString(system_info.c_str());
622 }
623
624 #ifdef WITH_OPENCL
625 static PyObject *opencl_disable_func(PyObject * /*self*/, PyObject * /*value*/)
626 {
627         VLOG(2) << "Disabling OpenCL platform.";
628         DebugFlags().opencl.device_type = DebugFlags::OpenCL::DEVICE_NONE;
629         Py_RETURN_NONE;
630 }
631 #endif
632
633 static bool denoise_parse_filepaths(PyObject *pyfilepaths, vector<string>& filepaths)
634 {
635
636         if(PyUnicode_Check(pyfilepaths)) {
637                 const char *filepath = PyUnicode_AsUTF8(pyfilepaths);
638                 filepaths.push_back(filepath);
639                 return true;
640         }
641
642         PyObject *sequence = PySequence_Fast(pyfilepaths, "File paths must be a string or sequence of strings");
643         if(sequence == NULL) {
644                 return false;
645         }
646
647         for(Py_ssize_t i = 0; i < PySequence_Fast_GET_SIZE(sequence); i++) {
648                 PyObject *item = PySequence_Fast_GET_ITEM(sequence, i);
649                 const char *filepath = PyUnicode_AsUTF8(item);
650                 if(filepath == NULL) {
651                         PyErr_SetString(PyExc_ValueError, "File paths must be a string or sequence of strings.");
652                         Py_DECREF(sequence);
653                         return false;
654                 }
655                 filepaths.push_back(filepath);
656         }
657         Py_DECREF(sequence);
658
659         return true;
660 }
661
662 static PyObject *denoise_func(PyObject * /*self*/, PyObject *args, PyObject *keywords)
663 {
664         static const char *keyword_list[] = {"preferences", "scene", "view_layer",
665                                              "input", "output",
666                                              "tile_size", "samples", NULL};
667         PyObject *pypreferences, *pyscene, *pyviewlayer;
668         PyObject *pyinput, *pyoutput = NULL;
669         int tile_size = 0, samples = 0;
670
671         if (!PyArg_ParseTupleAndKeywords(args, keywords, "OOOO|Oii", (char**)keyword_list,
672                                          &pypreferences, &pyscene, &pyviewlayer,
673                                                                          &pyinput, &pyoutput,
674                                          &tile_size, &samples)) {
675                 return NULL;
676         }
677
678         /* Get device specification from preferences and scene. */
679         PointerRNA preferencesptr;
680         RNA_pointer_create(NULL, &RNA_Preferences, (void*)PyLong_AsVoidPtr(pypreferences), &preferencesptr);
681         BL::Preferences b_preferences(preferencesptr);
682
683         PointerRNA sceneptr;
684         RNA_id_pointer_create((ID*)PyLong_AsVoidPtr(pyscene), &sceneptr);
685         BL::Scene b_scene(sceneptr);
686
687         DeviceInfo device = blender_device_info(b_preferences, b_scene, true);
688
689         /* Get denoising parameters from view layer. */
690         PointerRNA viewlayerptr;
691         RNA_pointer_create((ID*)PyLong_AsVoidPtr(pyscene), &RNA_ViewLayer, PyLong_AsVoidPtr(pyviewlayer), &viewlayerptr);
692         PointerRNA cviewlayer = RNA_pointer_get(&viewlayerptr, "cycles");
693
694         DenoiseParams params;
695         params.radius = get_int(cviewlayer, "denoising_radius");
696         params.strength = get_float(cviewlayer, "denoising_strength");
697         params.feature_strength = get_float(cviewlayer, "denoising_feature_strength");
698         params.relative_pca = get_boolean(cviewlayer, "denoising_relative_pca");
699         params.neighbor_frames = get_int(cviewlayer, "denoising_neighbor_frames");
700
701         /* Parse file paths list. */
702         vector<string> input, output;
703
704         if(!denoise_parse_filepaths(pyinput, input)) {
705                 return NULL;
706         }
707
708         if(pyoutput) {
709                 if(!denoise_parse_filepaths(pyoutput, output)) {
710                         return NULL;
711                 }
712         }
713         else {
714                 output = input;
715         }
716
717         if(input.empty()) {
718                 PyErr_SetString(PyExc_ValueError, "No input file paths specified.");
719                 return NULL;
720         }
721         if(input.size() != output.size()) {
722                 PyErr_SetString(PyExc_ValueError, "Number of input and output file paths does not match.");
723                 return NULL;
724         }
725
726         /* Create denoiser. */
727         Denoiser denoiser(device);
728         denoiser.params = params;
729         denoiser.input = input;
730         denoiser.output = output;
731
732         if (tile_size > 0) {
733                 denoiser.tile_size = make_int2(tile_size, tile_size);
734         }
735         if (samples > 0) {
736                 denoiser.samples_override = samples;
737         }
738
739         /* Run denoiser. */
740         if(!denoiser.run()) {
741                 PyErr_SetString(PyExc_ValueError, denoiser.error.c_str());
742                 return NULL;
743         }
744
745         Py_RETURN_NONE;
746 }
747
748 static PyObject *debug_flags_update_func(PyObject * /*self*/, PyObject *args)
749 {
750         PyObject *pyscene;
751         if(!PyArg_ParseTuple(args, "O", &pyscene)) {
752                 return NULL;
753         }
754
755         PointerRNA sceneptr;
756         RNA_id_pointer_create((ID*)PyLong_AsVoidPtr(pyscene), &sceneptr);
757         BL::Scene b_scene(sceneptr);
758
759         if(debug_flags_sync_from_scene(b_scene)) {
760                 VLOG(2) << "Tagging device list for update.";
761                 Device::tag_update();
762         }
763
764         VLOG(2) << "Debug flags set to:\n"
765                 << DebugFlags();
766
767         debug_flags_set = true;
768
769         Py_RETURN_NONE;
770 }
771
772 static PyObject *debug_flags_reset_func(PyObject * /*self*/, PyObject * /*args*/)
773 {
774         if(debug_flags_reset()) {
775                 VLOG(2) << "Tagging device list for update.";
776                 Device::tag_update();
777         }
778         if(debug_flags_set) {
779                 VLOG(2) << "Debug flags reset to:\n"
780                         << DebugFlags();
781                 debug_flags_set = false;
782         }
783         Py_RETURN_NONE;
784 }
785
786 static PyObject *set_resumable_chunk_func(PyObject * /*self*/, PyObject *args)
787 {
788         int num_resumable_chunks, current_resumable_chunk;
789         if(!PyArg_ParseTuple(args, "ii",
790                              &num_resumable_chunks,
791                              &current_resumable_chunk)) {
792                 Py_RETURN_NONE;
793         }
794
795         if(num_resumable_chunks <= 0) {
796                 fprintf(stderr, "Cycles: Bad value for number of resumable chunks.\n");
797                 abort();
798                 Py_RETURN_NONE;
799         }
800         if(current_resumable_chunk < 1 ||
801            current_resumable_chunk > num_resumable_chunks)
802         {
803                 fprintf(stderr, "Cycles: Bad value for current resumable chunk number.\n");
804                 abort();
805                 Py_RETURN_NONE;
806         }
807
808         VLOG(1) << "Initialized resumable render: "
809                 << "num_resumable_chunks=" << num_resumable_chunks << ", "
810                 << "current_resumable_chunk=" << current_resumable_chunk;
811         BlenderSession::num_resumable_chunks = num_resumable_chunks;
812         BlenderSession::current_resumable_chunk = current_resumable_chunk;
813
814         printf("Cycles: Will render chunk %d of %d\n",
815                current_resumable_chunk,
816                num_resumable_chunks);
817
818         Py_RETURN_NONE;
819 }
820
821 static PyObject *set_resumable_chunk_range_func(PyObject * /*self*/, PyObject *args)
822 {
823         int num_chunks, start_chunk, end_chunk;
824         if(!PyArg_ParseTuple(args, "iii",
825                              &num_chunks,
826                              &start_chunk,
827                              &end_chunk)) {
828                 Py_RETURN_NONE;
829         }
830
831         if(num_chunks <= 0) {
832                 fprintf(stderr, "Cycles: Bad value for number of resumable chunks.\n");
833                 abort();
834                 Py_RETURN_NONE;
835         }
836         if(start_chunk < 1 || start_chunk > num_chunks) {
837                 fprintf(stderr, "Cycles: Bad value for start chunk number.\n");
838                 abort();
839                 Py_RETURN_NONE;
840         }
841         if(end_chunk < 1 || end_chunk > num_chunks) {
842                 fprintf(stderr, "Cycles: Bad value for start chunk number.\n");
843                 abort();
844                 Py_RETURN_NONE;
845         }
846         if(start_chunk > end_chunk) {
847                 fprintf(stderr, "Cycles: End chunk should be higher than start one.\n");
848                 abort();
849                 Py_RETURN_NONE;
850         }
851
852         VLOG(1) << "Initialized resumable render: "
853                 << "num_resumable_chunks=" << num_chunks << ", "
854                 << "start_resumable_chunk=" << start_chunk
855                 << "end_resumable_chunk=" << end_chunk;
856         BlenderSession::num_resumable_chunks = num_chunks;
857         BlenderSession::start_resumable_chunk = start_chunk;
858         BlenderSession::end_resumable_chunk = end_chunk;
859
860         printf("Cycles: Will render chunks %d to %d of %d\n",
861                start_chunk,
862                end_chunk,
863                num_chunks);
864
865         Py_RETURN_NONE;
866 }
867
868 static PyObject *enable_print_stats_func(PyObject * /*self*/, PyObject * /*args*/)
869 {
870         BlenderSession::print_render_stats = true;
871         Py_RETURN_NONE;
872 }
873
874 static PyObject *get_device_types_func(PyObject * /*self*/, PyObject * /*args*/)
875 {
876         vector<DeviceType> device_types = Device::available_types();
877         bool has_cuda = false, has_opencl = false;
878         foreach(DeviceType device_type, device_types) {
879                 has_cuda   |= (device_type == DEVICE_CUDA);
880                 has_opencl |= (device_type == DEVICE_OPENCL);
881         }
882         PyObject *list = PyTuple_New(2);
883         PyTuple_SET_ITEM(list, 0, PyBool_FromLong(has_cuda));
884         PyTuple_SET_ITEM(list, 1, PyBool_FromLong(has_opencl));
885         return list;
886 }
887
888 static PyMethodDef methods[] = {
889         {"init", init_func, METH_VARARGS, ""},
890         {"exit", exit_func, METH_VARARGS, ""},
891         {"create", create_func, METH_VARARGS, ""},
892         {"free", free_func, METH_O, ""},
893         {"render", render_func, METH_VARARGS, ""},
894         {"bake", bake_func, METH_VARARGS, ""},
895         {"draw", draw_func, METH_VARARGS, ""},
896         {"sync", sync_func, METH_VARARGS, ""},
897         {"reset", reset_func, METH_VARARGS, ""},
898 #ifdef WITH_OSL
899         {"osl_update_node", osl_update_node_func, METH_VARARGS, ""},
900         {"osl_compile", osl_compile_func, METH_VARARGS, ""},
901 #endif
902         {"available_devices", available_devices_func, METH_VARARGS, ""},
903         {"system_info", system_info_func, METH_NOARGS, ""},
904 #ifdef WITH_OPENCL
905         {"opencl_disable", opencl_disable_func, METH_NOARGS, ""},
906 #endif
907
908         /* Standalone denoising */
909         {"denoise", (PyCFunction)denoise_func, METH_VARARGS|METH_KEYWORDS, ""},
910
911         /* Debugging routines */
912         {"debug_flags_update", debug_flags_update_func, METH_VARARGS, ""},
913         {"debug_flags_reset", debug_flags_reset_func, METH_NOARGS, ""},
914
915         /* Statistics. */
916         {"enable_print_stats", enable_print_stats_func, METH_NOARGS, ""},
917
918         /* Resumable render */
919         {"set_resumable_chunk", set_resumable_chunk_func, METH_VARARGS, ""},
920         {"set_resumable_chunk_range", set_resumable_chunk_range_func, METH_VARARGS, ""},
921
922         /* Compute Device selection */
923         {"get_device_types", get_device_types_func, METH_VARARGS, ""},
924
925         {NULL, NULL, 0, NULL},
926 };
927
928 static struct PyModuleDef module = {
929         PyModuleDef_HEAD_INIT,
930         "_cycles",
931         "Blender cycles render integration",
932         -1,
933         methods,
934         NULL, NULL, NULL, NULL,
935 };
936
937 CCL_NAMESPACE_END
938
939 void *CCL_python_module_init()
940 {
941         PyObject *mod = PyModule_Create(&ccl::module);
942
943 #ifdef WITH_OSL
944         /* TODO(sergey): This gives us library we've been linking against.
945          *               In theory with dynamic OSL library it might not be
946          *               accurate, but there's nothing in OSL API which we
947          *               might use to get version in runtime.
948          */
949         int curversion = OSL_LIBRARY_VERSION_CODE;
950         PyModule_AddObject(mod, "with_osl", Py_True);
951         Py_INCREF(Py_True);
952         PyModule_AddObject(mod, "osl_version",
953                            Py_BuildValue("(iii)",
954                                           curversion / 10000, (curversion / 100) % 100, curversion % 100));
955         PyModule_AddObject(mod, "osl_version_string",
956                            PyUnicode_FromFormat("%2d, %2d, %2d",
957                                                 curversion / 10000, (curversion / 100) % 100, curversion % 100));
958 #else
959         PyModule_AddObject(mod, "with_osl", Py_False);
960         Py_INCREF(Py_False);
961         PyModule_AddStringConstant(mod, "osl_version", "unknown");
962         PyModule_AddStringConstant(mod, "osl_version_string", "unknown");
963 #endif
964
965 #ifdef WITH_CYCLES_DEBUG
966         PyModule_AddObject(mod, "with_cycles_debug", Py_True);
967         Py_INCREF(Py_True);
968 #else
969         PyModule_AddObject(mod, "with_cycles_debug", Py_False);
970         Py_INCREF(Py_False);
971 #endif
972
973 #ifdef WITH_NETWORK
974         PyModule_AddObject(mod, "with_network", Py_True);
975         Py_INCREF(Py_True);
976 #else  /* WITH_NETWORK */
977         PyModule_AddObject(mod, "with_network", Py_False);
978         Py_INCREF(Py_False);
979 #endif  /* WITH_NETWORK */
980
981 #ifdef WITH_EMBREE
982         PyModule_AddObject(mod, "with_embree", Py_True);
983         Py_INCREF(Py_True);
984 #else  /* WITH_EMBREE */
985         PyModule_AddObject(mod, "with_embree", Py_False);
986         Py_INCREF(Py_False);
987 #endif  /* WITH_EMBREE */
988
989         return (void*)mod;
990 }