Cycles: Fallback to bottom-top tile order when rendering from the command line
[blender-staging.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 "CCL_api.h"
20
21 #include "blender_sync.h"
22 #include "blender_session.h"
23
24 #include "util_foreach.h"
25 #include "util_md5.h"
26 #include "util_opengl.h"
27 #include "util_path.h"
28
29 #ifdef WITH_OSL
30 #include "osl.h"
31
32 #include <OSL/oslquery.h>
33 #include <OSL/oslconfig.h>
34 #endif
35
36 CCL_NAMESPACE_BEGIN
37
38 static void *pylong_as_voidptr_typesafe(PyObject *object)
39 {
40         if(object == Py_None)
41                 return NULL;
42         return PyLong_AsVoidPtr(object);
43 }
44
45 void python_thread_state_save(void **python_thread_state)
46 {
47         *python_thread_state = (void*)PyEval_SaveThread();
48 }
49
50 void python_thread_state_restore(void **python_thread_state)
51 {
52         PyEval_RestoreThread((PyThreadState*)*python_thread_state);
53         *python_thread_state = NULL;
54 }
55
56 static const char *PyC_UnicodeAsByte(PyObject *py_str, PyObject **coerce)
57 {
58 #ifdef WIN32
59         /* bug [#31856] oddly enough, Python3.2 --> 3.3 on Windows will throw an
60          * exception here this needs to be fixed in python:
61          * see: bugs.python.org/issue15859 */
62         if(!PyUnicode_Check(py_str)) {
63                 PyErr_BadArgument();
64                 return "";
65         }
66 #endif
67         if((*coerce = PyUnicode_EncodeFSDefault(py_str))) {
68                 return PyBytes_AS_STRING(*coerce);
69         }
70         return "";
71 }
72
73 static PyObject *init_func(PyObject *self, PyObject *args)
74 {
75         PyObject *path, *user_path;
76
77         if(!PyArg_ParseTuple(args, "OO", &path, &user_path)) {
78                 return NULL;
79         }
80
81         PyObject *path_coerce = NULL, *user_path_coerce = NULL;
82         path_init(PyC_UnicodeAsByte(path, &path_coerce),
83                   PyC_UnicodeAsByte(user_path, &user_path_coerce));
84         Py_XDECREF(path_coerce);
85         Py_XDECREF(user_path_coerce);
86
87         Py_RETURN_NONE;
88 }
89
90 static PyObject *create_func(PyObject *self, PyObject *args)
91 {
92         PyObject *pyengine, *pyuserpref, *pydata, *pyscene, *pyregion, *pyv3d, *pyrv3d;
93         int preview_osl, background;
94
95         if(!PyArg_ParseTuple(args, "OOOOOOOii", &pyengine, &pyuserpref, &pydata, &pyscene,
96                              &pyregion, &pyv3d, &pyrv3d, &preview_osl, &background))
97         {
98                 return NULL;
99         }
100
101         /* RNA */
102         PointerRNA engineptr;
103         RNA_pointer_create(NULL, &RNA_RenderEngine, (void*)PyLong_AsVoidPtr(pyengine), &engineptr);
104         BL::RenderEngine engine(engineptr);
105
106         PointerRNA userprefptr;
107         RNA_pointer_create(NULL, &RNA_UserPreferences, (void*)PyLong_AsVoidPtr(pyuserpref), &userprefptr);
108         BL::UserPreferences userpref(userprefptr);
109
110         PointerRNA dataptr;
111         RNA_main_pointer_create((Main*)PyLong_AsVoidPtr(pydata), &dataptr);
112         BL::BlendData data(dataptr);
113
114         PointerRNA sceneptr;
115         RNA_id_pointer_create((ID*)PyLong_AsVoidPtr(pyscene), &sceneptr);
116         BL::Scene scene(sceneptr);
117
118         PointerRNA regionptr;
119         RNA_pointer_create(NULL, &RNA_Region, pylong_as_voidptr_typesafe(pyregion), &regionptr);
120         BL::Region region(regionptr);
121
122         PointerRNA v3dptr;
123         RNA_pointer_create(NULL, &RNA_SpaceView3D, pylong_as_voidptr_typesafe(pyv3d), &v3dptr);
124         BL::SpaceView3D v3d(v3dptr);
125
126         PointerRNA rv3dptr;
127         RNA_pointer_create(NULL, &RNA_RegionView3D, pylong_as_voidptr_typesafe(pyrv3d), &rv3dptr);
128         BL::RegionView3D rv3d(rv3dptr);
129
130         /* create session */
131         BlenderSession *session;
132
133         if(rv3d) {
134                 /* interactive viewport session */
135                 int width = region.width();
136                 int height = region.height();
137
138                 session = new BlenderSession(engine, userpref, data, scene, v3d, rv3d, width, height);
139         }
140         else {
141                 /* override some settings for preview */
142                 if(engine.is_preview()) {
143                         PointerRNA cscene = RNA_pointer_get(&sceneptr, "cycles");
144
145                         RNA_boolean_set(&cscene, "shading_system", preview_osl);
146                         RNA_boolean_set(&cscene, "use_progressive_refine", true);
147                 }
148
149                 /* Use more optimal tile order when rendering from the command line. */
150                 if(background) {
151                         PointerRNA cscene = RNA_pointer_get(&sceneptr, "cycles");
152                         RNA_enum_set(&cscene, "tile_order", (int)TILE_BOTTOM_TO_TOP);
153                 }
154
155                 /* offline session or preview render */
156                 session = new BlenderSession(engine, userpref, data, scene);
157         }
158
159         python_thread_state_save(&session->python_thread_state);
160
161         session->create();
162
163         python_thread_state_restore(&session->python_thread_state);
164
165         return PyLong_FromVoidPtr(session);
166 }
167
168 static PyObject *free_func(PyObject *self, PyObject *value)
169 {
170         delete (BlenderSession*)PyLong_AsVoidPtr(value);
171
172         Py_RETURN_NONE;
173 }
174
175 static PyObject *render_func(PyObject *self, PyObject *value)
176 {
177         BlenderSession *session = (BlenderSession*)PyLong_AsVoidPtr(value);
178
179         python_thread_state_save(&session->python_thread_state);
180
181         session->render();
182
183         python_thread_state_restore(&session->python_thread_state);
184
185         Py_RETURN_NONE;
186 }
187
188 /* pixel_array and result passed as pointers */
189 static PyObject *bake_func(PyObject *self, PyObject *args)
190 {
191         PyObject *pysession, *pyobject;
192         PyObject *pypixel_array, *pyresult;
193         const char *pass_type;
194         int num_pixels, depth;
195
196         if(!PyArg_ParseTuple(args, "OOsOiiO", &pysession, &pyobject, &pass_type, &pypixel_array,  &num_pixels, &depth, &pyresult))
197                 return NULL;
198
199         BlenderSession *session = (BlenderSession*)PyLong_AsVoidPtr(pysession);
200
201         PointerRNA objectptr;
202         RNA_id_pointer_create((ID*)PyLong_AsVoidPtr(pyobject), &objectptr);
203         BL::Object b_object(objectptr);
204
205         void *b_result = PyLong_AsVoidPtr(pyresult);
206
207         PointerRNA bakepixelptr;
208         RNA_pointer_create(NULL, &RNA_BakePixel, PyLong_AsVoidPtr(pypixel_array), &bakepixelptr);
209         BL::BakePixel b_bake_pixel(bakepixelptr);
210
211         python_thread_state_save(&session->python_thread_state);
212
213         session->bake(b_object, pass_type, b_bake_pixel, (size_t)num_pixels, depth, (float *)b_result);
214
215         python_thread_state_restore(&session->python_thread_state);
216
217         Py_RETURN_NONE;
218 }
219
220 static PyObject *draw_func(PyObject *self, PyObject *args)
221 {
222         PyObject *pysession, *pyv3d, *pyrv3d;
223
224         if(!PyArg_ParseTuple(args, "OOO", &pysession, &pyv3d, &pyrv3d))
225                 return NULL;
226         
227         BlenderSession *session = (BlenderSession*)PyLong_AsVoidPtr(pysession);
228
229         if(PyLong_AsVoidPtr(pyrv3d)) {
230                 /* 3d view drawing */
231                 int viewport[4];
232                 glGetIntegerv(GL_VIEWPORT, viewport);
233
234                 session->draw(viewport[2], viewport[3]);
235         }
236
237         Py_RETURN_NONE;
238 }
239
240 static PyObject *reset_func(PyObject *self, PyObject *args)
241 {
242         PyObject *pysession, *pydata, *pyscene;
243
244         if(!PyArg_ParseTuple(args, "OOO", &pysession, &pydata, &pyscene))
245                 return NULL;
246
247         BlenderSession *session = (BlenderSession*)PyLong_AsVoidPtr(pysession);
248
249         PointerRNA dataptr;
250         RNA_main_pointer_create((Main*)PyLong_AsVoidPtr(pydata), &dataptr);
251         BL::BlendData b_data(dataptr);
252
253         PointerRNA sceneptr;
254         RNA_id_pointer_create((ID*)PyLong_AsVoidPtr(pyscene), &sceneptr);
255         BL::Scene b_scene(sceneptr);
256
257         python_thread_state_save(&session->python_thread_state);
258
259         session->reset_session(b_data, b_scene);
260
261         python_thread_state_restore(&session->python_thread_state);
262
263         Py_RETURN_NONE;
264 }
265
266 static PyObject *sync_func(PyObject *self, PyObject *value)
267 {
268         BlenderSession *session = (BlenderSession*)PyLong_AsVoidPtr(value);
269
270         python_thread_state_save(&session->python_thread_state);
271
272         session->synchronize();
273
274         python_thread_state_restore(&session->python_thread_state);
275
276         Py_RETURN_NONE;
277 }
278
279 static PyObject *available_devices_func(PyObject *self, PyObject *args)
280 {
281         vector<DeviceInfo>& devices = Device::available_devices();
282         PyObject *ret = PyTuple_New(devices.size());
283
284         for(size_t i = 0; i < devices.size(); i++) {
285                 DeviceInfo& device = devices[i];
286                 PyTuple_SET_ITEM(ret, i, PyUnicode_FromString(device.description.c_str()));
287         }
288
289         return ret;
290 }
291
292 #ifdef WITH_OSL
293
294 static PyObject *osl_update_node_func(PyObject *self, PyObject *args)
295 {
296         PyObject *pynodegroup, *pynode;
297         const char *filepath = NULL;
298
299         if(!PyArg_ParseTuple(args, "OOs", &pynodegroup, &pynode, &filepath))
300                 return NULL;
301
302         /* RNA */
303         PointerRNA nodeptr;
304         RNA_pointer_create((ID*)PyLong_AsVoidPtr(pynodegroup), &RNA_ShaderNodeScript, (void*)PyLong_AsVoidPtr(pynode), &nodeptr);
305         BL::ShaderNodeScript b_node(nodeptr);
306
307         /* update bytecode hash */
308         string bytecode = b_node.bytecode();
309
310         if(!bytecode.empty()) {
311                 MD5Hash md5;
312                 md5.append((const uint8_t*)bytecode.c_str(), bytecode.size());
313                 b_node.bytecode_hash(md5.get_hex().c_str());
314         }
315         else
316                 b_node.bytecode_hash("");
317
318         /* query from file path */
319         OSL::OSLQuery query;
320
321         if(!OSLShaderManager::osl_query(query, filepath))
322                 Py_RETURN_FALSE;
323
324         /* add new sockets from parameters */
325         set<void*> used_sockets;
326
327         for(int i = 0; i < query.nparams(); i++) {
328                 const OSL::OSLQuery::Parameter *param = query.getparam(i);
329
330                 /* skip unsupported types */
331                 if(param->varlenarray || param->isstruct || param->type.arraylen > 1)
332                         continue;
333
334                 /* determine socket type */
335                 std::string socket_type;
336                 BL::NodeSocket::type_enum data_type = BL::NodeSocket::type_VALUE;
337                 float4 default_float4 = make_float4(0.0f, 0.0f, 0.0f, 1.0f);
338                 float default_float = 0.0f;
339                 int default_int = 0;
340                 std::string default_string = "";
341                 
342                 if(param->isclosure) {
343                         socket_type = "NodeSocketShader";
344                         data_type = BL::NodeSocket::type_SHADER;
345                 }
346                 else if(param->type.vecsemantics == TypeDesc::COLOR) {
347                         socket_type = "NodeSocketColor";
348                         data_type = BL::NodeSocket::type_RGBA;
349
350                         if(param->validdefault) {
351                                 default_float4[0] = param->fdefault[0];
352                                 default_float4[1] = param->fdefault[1];
353                                 default_float4[2] = param->fdefault[2];
354                         }
355                 }
356                 else if(param->type.vecsemantics == TypeDesc::POINT ||
357                         param->type.vecsemantics == TypeDesc::VECTOR ||
358                         param->type.vecsemantics == TypeDesc::NORMAL)
359                 {
360                         socket_type = "NodeSocketVector";
361                         data_type = BL::NodeSocket::type_VECTOR;
362
363                         if(param->validdefault) {
364                                 default_float4[0] = param->fdefault[0];
365                                 default_float4[1] = param->fdefault[1];
366                                 default_float4[2] = param->fdefault[2];
367                         }
368                 }
369                 else if(param->type.aggregate == TypeDesc::SCALAR) {
370                         if(param->type.basetype == TypeDesc::INT) {
371                                 socket_type = "NodeSocketInt";
372                                 data_type = BL::NodeSocket::type_INT;
373                                 if(param->validdefault)
374                                         default_int = param->idefault[0];
375                         }
376                         else if(param->type.basetype == TypeDesc::FLOAT) {
377                                 socket_type = "NodeSocketFloat";
378                                 data_type = BL::NodeSocket::type_VALUE;
379                                 if(param->validdefault)
380                                         default_float = param->fdefault[0];
381                         }
382                         else if(param->type.basetype == TypeDesc::STRING) {
383                                 socket_type = "NodeSocketString";
384                                 data_type = BL::NodeSocket::type_STRING;
385                                 if(param->validdefault)
386                                         default_string = param->sdefault[0];
387                         }
388                         else
389                                 continue;
390                 }
391                 else
392                         continue;
393
394                 /* find socket socket */
395                 BL::NodeSocket b_sock(PointerRNA_NULL);
396                 if (param->isoutput) {
397                         b_sock = b_node.outputs[param->name.string()];
398                         /* remove if type no longer matches */
399                         if(b_sock && b_sock.bl_idname() != socket_type) {
400                                 b_node.outputs.remove(b_sock);
401                                 b_sock = BL::NodeSocket(PointerRNA_NULL);
402                         }
403                 }
404                 else {
405                         b_sock = b_node.inputs[param->name.string()];
406                         /* remove if type no longer matches */
407                         if(b_sock && b_sock.bl_idname() != socket_type) {
408                                 b_node.inputs.remove(b_sock);
409                                 b_sock = BL::NodeSocket(PointerRNA_NULL);
410                         }
411                 }
412
413                 if(!b_sock) {
414                         /* create new socket */
415                         if(param->isoutput)
416                                 b_sock = b_node.outputs.create(socket_type.c_str(), param->name.c_str(), param->name.c_str());
417                         else
418                                 b_sock = b_node.inputs.create(socket_type.c_str(), param->name.c_str(), param->name.c_str());
419
420                         /* set default value */
421                         if(data_type == BL::NodeSocket::type_VALUE) {
422                                 set_float(b_sock.ptr, "default_value", default_float);
423                         }
424                         else if(data_type == BL::NodeSocket::type_INT) {
425                                 set_int(b_sock.ptr, "default_value", default_int);
426                         }
427                         else if(data_type == BL::NodeSocket::type_RGBA) {
428                                 set_float4(b_sock.ptr, "default_value", default_float4);
429                         }
430                         else if(data_type == BL::NodeSocket::type_VECTOR) {
431                                 set_float3(b_sock.ptr, "default_value", float4_to_float3(default_float4));
432                         }
433                         else if(data_type == BL::NodeSocket::type_STRING) {
434                                 set_string(b_sock.ptr, "default_value", default_string);
435                         }
436                 }
437
438                 used_sockets.insert(b_sock.ptr.data);
439         }
440
441         /* remove unused parameters */
442         bool removed;
443
444         do {
445                 BL::Node::inputs_iterator b_input;
446                 BL::Node::outputs_iterator b_output;
447
448                 removed = false;
449
450                 for (b_node.inputs.begin(b_input); b_input != b_node.inputs.end(); ++b_input) {
451                         if(used_sockets.find(b_input->ptr.data) == used_sockets.end()) {
452                                 b_node.inputs.remove(*b_input);
453                                 removed = true;
454                                 break;
455                         }
456                 }
457
458                 for (b_node.outputs.begin(b_output); b_output != b_node.outputs.end(); ++b_output) {
459                         if(used_sockets.find(b_output->ptr.data) == used_sockets.end()) {
460                                 b_node.outputs.remove(*b_output);
461                                 removed = true;
462                                 break;
463                         }
464                 }
465         } while(removed);
466
467         Py_RETURN_TRUE;
468 }
469
470 static PyObject *osl_compile_func(PyObject *self, PyObject *args)
471 {
472         const char *inputfile = NULL, *outputfile = NULL;
473
474         if(!PyArg_ParseTuple(args, "ss", &inputfile, &outputfile))
475                 return NULL;
476         
477         /* return */
478         if(!OSLShaderManager::osl_compile(inputfile, outputfile))
479                 Py_RETURN_FALSE;
480
481         Py_RETURN_TRUE;
482 }
483 #endif
484
485 static PyObject *system_info_func(PyObject *self, PyObject *value)
486 {
487         string system_info = Device::device_capabilities();
488         return PyUnicode_FromString(system_info.c_str());
489 }
490
491 static PyMethodDef methods[] = {
492         {"init", init_func, METH_VARARGS, ""},
493         {"create", create_func, METH_VARARGS, ""},
494         {"free", free_func, METH_O, ""},
495         {"render", render_func, METH_O, ""},
496         {"bake", bake_func, METH_VARARGS, ""},
497         {"draw", draw_func, METH_VARARGS, ""},
498         {"sync", sync_func, METH_O, ""},
499         {"reset", reset_func, METH_VARARGS, ""},
500 #ifdef WITH_OSL
501         {"osl_update_node", osl_update_node_func, METH_VARARGS, ""},
502         {"osl_compile", osl_compile_func, METH_VARARGS, ""},
503 #endif
504         {"available_devices", available_devices_func, METH_NOARGS, ""},
505         {"system_info", system_info_func, METH_NOARGS, ""},
506         {NULL, NULL, 0, NULL},
507 };
508
509 static struct PyModuleDef module = {
510         PyModuleDef_HEAD_INIT,
511         "_cycles",
512         "Blender cycles render integration",
513         -1,
514         methods,
515         NULL, NULL, NULL, NULL
516 };
517
518 static CCLDeviceInfo *compute_device_list(DeviceType type)
519 {
520         /* device list stored static */
521         static ccl::vector<CCLDeviceInfo> device_list;
522         static ccl::DeviceType device_type = DEVICE_NONE;
523
524         /* create device list if it's not already done */
525         if(type != device_type) {
526                 ccl::vector<DeviceInfo>& devices = ccl::Device::available_devices();
527
528                 device_type = type;
529                 device_list.clear();
530
531                 /* add devices */
532                 int i = 0;
533
534                 foreach(DeviceInfo& info, devices) {
535                         if(info.type == type ||
536                            (info.type == DEVICE_MULTI && info.multi_devices[0].type == type))
537                         {
538                                 CCLDeviceInfo cinfo;
539
540                                 strncpy(cinfo.identifier, info.id.c_str(), sizeof(cinfo.identifier));
541                                 cinfo.identifier[info.id.length()] = '\0';
542
543                                 strncpy(cinfo.name, info.description.c_str(), sizeof(cinfo.name));
544                                 cinfo.name[info.description.length()] = '\0';
545
546                                 cinfo.value = i++;
547
548                                 device_list.push_back(cinfo);
549                         }
550                 }
551
552                 /* null terminate */
553                 if(!device_list.empty()) {
554                         CCLDeviceInfo cinfo = {"", "", 0};
555                         device_list.push_back(cinfo);
556                 }
557         }
558
559         return (device_list.empty())? NULL: &device_list[0];
560 }
561
562
563 CCL_NAMESPACE_END
564
565 void *CCL_python_module_init()
566 {
567         PyObject *mod = PyModule_Create(&ccl::module);
568
569 #ifdef WITH_OSL
570         /* TODO(sergey): This gives us library we've been linking against.
571          *               In theory with dynamic OSL library it might not be
572          *               accurate, but there's nothing in OSL API which we
573          *               might use to get version in runtime.
574          */
575         int curversion = OSL_LIBRARY_VERSION_CODE;
576         PyModule_AddObject(mod, "with_osl", Py_True);
577         Py_INCREF(Py_True);
578         PyModule_AddObject(mod, "osl_version",
579                            Py_BuildValue("(iii)",
580                                           curversion / 10000, (curversion / 100) % 100, curversion % 100));
581         PyModule_AddObject(mod, "osl_version_string",
582                            PyUnicode_FromFormat("%2d, %2d, %2d",
583                                                 curversion / 10000, (curversion / 100) % 100, curversion % 100));
584 #else
585         PyModule_AddObject(mod, "with_osl", Py_False);
586         Py_INCREF(Py_False);
587         PyModule_AddStringConstant(mod, "osl_version", "unknown");
588         PyModule_AddStringConstant(mod, "osl_version_string", "unknown");
589 #endif
590
591 #ifdef WITH_NETWORK
592         PyModule_AddObject(mod, "with_network", Py_True);
593         Py_INCREF(Py_True);
594 #else /* WITH_NETWORK */
595         PyModule_AddObject(mod, "with_network", Py_False);
596         Py_INCREF(Py_False);
597 #endif /* WITH_NETWORK */
598
599         return (void*)mod;
600 }
601
602 CCLDeviceInfo *CCL_compute_device_list(int device_type)
603 {
604         ccl::DeviceType type;
605         switch(device_type) {
606                 case 0:
607                         type = ccl::DEVICE_CUDA;
608                         break;
609                 case 1:
610                         type = ccl::DEVICE_OPENCL;
611                         break;
612                 case 2:
613                         type = ccl::DEVICE_NETWORK;
614                         break;
615                 default:
616                         type = ccl::DEVICE_NONE;
617                         break;
618         }
619         return ccl::compute_device_list(type);
620 }
621