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