Merge branch 'master' into blender2.8
[blender.git] / intern / cycles / blender / blender_sync.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 "render/background.h"
18 #include "render/camera.h"
19 #include "render/film.h"
20 #include "render/graph.h"
21 #include "render/integrator.h"
22 #include "render/light.h"
23 #include "render/mesh.h"
24 #include "render/nodes.h"
25 #include "render/object.h"
26 #include "render/scene.h"
27 #include "render/shader.h"
28 #include "render/curves.h"
29
30 #include "device/device.h"
31
32 #include "blender/blender_sync.h"
33 #include "blender/blender_session.h"
34 #include "blender/blender_util.h"
35
36 #include "util/util_debug.h"
37 #include "util/util_foreach.h"
38 #include "util/util_opengl.h"
39 #include "util/util_hash.h"
40
41 CCL_NAMESPACE_BEGIN
42
43 /* Constructor */
44
45 BlenderSync::BlenderSync(BL::RenderEngine& b_engine,
46                          BL::BlendData& b_data,
47                          BL::Depsgraph& b_depsgraph,
48                          BL::Scene& b_scene,
49                          Scene *scene,
50                          bool preview,
51                          Progress &progress,
52                          bool is_cpu)
53 : b_engine(b_engine),
54   b_data(b_data),
55   b_depsgraph(b_depsgraph),
56   b_scene(b_scene),
57   shader_map(&scene->shaders),
58   object_map(&scene->objects),
59   mesh_map(&scene->meshes),
60   light_map(&scene->lights),
61   particle_system_map(&scene->particle_systems),
62   world_map(NULL),
63   world_recalc(false),
64   scene(scene),
65   preview(preview),
66   experimental(false),
67   is_cpu(is_cpu),
68   dicing_rate(1.0f),
69   max_subdivisions(12),
70   progress(progress)
71 {
72         PointerRNA cscene = RNA_pointer_get(&b_scene.ptr, "cycles");
73         dicing_rate = preview ? RNA_float_get(&cscene, "preview_dicing_rate") : RNA_float_get(&cscene, "dicing_rate");
74         max_subdivisions = RNA_int_get(&cscene, "max_subdivisions");
75 }
76
77 BlenderSync::~BlenderSync()
78 {
79 }
80
81 /* Sync */
82
83 bool BlenderSync::sync_recalc()
84 {
85         /* sync recalc flags from blender to cycles. actual update is done separate,
86          * so we can do it later on if doing it immediate is not suitable */
87
88         BL::BlendData::materials_iterator b_mat;
89         bool has_updated_objects = b_data.objects.is_updated();
90         for(b_data.materials.begin(b_mat); b_mat != b_data.materials.end(); ++b_mat) {
91                 if(b_mat->is_updated() || (b_mat->node_tree() && b_mat->node_tree().is_updated())) {
92                         shader_map.set_recalc(*b_mat);
93                 }
94                 else {
95                         Shader *shader = shader_map.find(*b_mat);
96                         if(has_updated_objects && shader != NULL && shader->has_object_dependency) {
97                                 shader_map.set_recalc(*b_mat);
98                         }
99                 }
100         }
101
102         BL::BlendData::lamps_iterator b_lamp;
103
104         for(b_data.lamps.begin(b_lamp); b_lamp != b_data.lamps.end(); ++b_lamp)
105                 if(b_lamp->is_updated() || (b_lamp->node_tree() && b_lamp->node_tree().is_updated()))
106                         shader_map.set_recalc(*b_lamp);
107
108         bool dicing_prop_changed = false;
109
110         if(experimental) {
111                 PointerRNA cscene = RNA_pointer_get(&b_scene.ptr, "cycles");
112
113                 float updated_dicing_rate = preview ? RNA_float_get(&cscene, "preview_dicing_rate")
114                                                     : RNA_float_get(&cscene, "dicing_rate");
115
116                 if(dicing_rate != updated_dicing_rate) {
117                         dicing_rate = updated_dicing_rate;
118                         dicing_prop_changed = true;
119                 }
120
121                 int updated_max_subdivisions = RNA_int_get(&cscene, "max_subdivisions");
122
123                 if(max_subdivisions != updated_max_subdivisions) {
124                         max_subdivisions = updated_max_subdivisions;
125                         dicing_prop_changed = true;
126                 }
127         }
128
129         BL::BlendData::objects_iterator b_ob;
130
131         for(b_data.objects.begin(b_ob); b_ob != b_data.objects.end(); ++b_ob) {
132                 if(b_ob->is_updated()) {
133                         object_map.set_recalc(*b_ob);
134                         light_map.set_recalc(*b_ob);
135                 }
136
137                 if(object_is_mesh(*b_ob)) {
138                         if(b_ob->is_updated_data() || b_ob->data().is_updated() ||
139                            (dicing_prop_changed && object_subdivision_type(*b_ob, preview, experimental) != Mesh::SUBDIVISION_NONE))
140                         {
141                                 BL::ID key = BKE_object_is_modified(*b_ob)? *b_ob: b_ob->data();
142                                 mesh_map.set_recalc(key);
143                         }
144                 }
145                 else if(object_is_light(*b_ob)) {
146                         if(b_ob->is_updated_data() || b_ob->data().is_updated())
147                                 light_map.set_recalc(*b_ob);
148                 }
149                 
150                 if(b_ob->is_updated_data()) {
151                         BL::Object::particle_systems_iterator b_psys;
152                         for(b_ob->particle_systems.begin(b_psys); b_psys != b_ob->particle_systems.end(); ++b_psys)
153                                 particle_system_map.set_recalc(*b_ob);
154                 }
155         }
156
157         BL::BlendData::meshes_iterator b_mesh;
158
159         for(b_data.meshes.begin(b_mesh); b_mesh != b_data.meshes.end(); ++b_mesh) {
160                 if(b_mesh->is_updated()) {
161                         mesh_map.set_recalc(*b_mesh);
162                 }
163         }
164
165         BL::BlendData::worlds_iterator b_world;
166
167         for(b_data.worlds.begin(b_world); b_world != b_data.worlds.end(); ++b_world) {
168                 if(world_map == b_world->ptr.data) {
169                         if(b_world->is_updated() ||
170                            (b_world->node_tree() && b_world->node_tree().is_updated()))
171                         {
172                                 world_recalc = true;
173                         }
174                         else if(b_world->node_tree() && b_world->use_nodes()) {
175                                 Shader *shader = scene->default_background;
176                                 if(has_updated_objects && shader->has_object_dependency) {
177                                         world_recalc = true;
178                                 }
179                         }
180                 }
181         }
182
183         bool recalc =
184                 shader_map.has_recalc() ||
185                 object_map.has_recalc() ||
186                 light_map.has_recalc() ||
187                 mesh_map.has_recalc() ||
188                 particle_system_map.has_recalc() ||
189                 BlendDataObjects_is_updated_get(&b_data.ptr) ||
190                 world_recalc;
191
192         return recalc;
193 }
194
195 void BlenderSync::sync_data(BL::RenderSettings& b_render,
196                             BL::SpaceView3D& b_v3d,
197                             BL::Object& b_override,
198                             int width, int height,
199                             void **python_thread_state,
200                             const char *layer)
201 {
202         sync_render_layers(b_v3d, layer);
203         sync_integrator();
204         sync_film();
205         sync_shaders();
206         sync_images();
207         sync_curve_settings();
208
209         mesh_synced.clear(); /* use for objects and motion sync */
210
211         if(scene->need_motion() == Scene::MOTION_PASS ||
212            scene->need_motion() == Scene::MOTION_NONE ||
213            scene->camera->motion_position == Camera::MOTION_POSITION_CENTER)
214         {
215                 sync_objects();
216         }
217         sync_motion(b_render,
218                     b_override,
219                     width, height,
220                     python_thread_state);
221
222         mesh_synced.clear();
223 }
224
225 /* Integrator */
226
227 void BlenderSync::sync_integrator()
228 {
229 #ifdef __CAMERA_MOTION__
230         BL::RenderSettings r = b_scene.render();
231 #endif
232         PointerRNA cscene = RNA_pointer_get(&b_scene.ptr, "cycles");
233
234         experimental = (get_enum(cscene, "feature_set") != 0);
235
236         Integrator *integrator = scene->integrator;
237         Integrator previntegrator = *integrator;
238
239         integrator->min_bounce = get_int(cscene, "min_bounces");
240         integrator->max_bounce = get_int(cscene, "max_bounces");
241
242         integrator->max_diffuse_bounce = get_int(cscene, "diffuse_bounces");
243         integrator->max_glossy_bounce = get_int(cscene, "glossy_bounces");
244         integrator->max_transmission_bounce = get_int(cscene, "transmission_bounces");
245         integrator->max_volume_bounce = get_int(cscene, "volume_bounces");
246
247         integrator->transparent_max_bounce = get_int(cscene, "transparent_max_bounces");
248         integrator->transparent_min_bounce = get_int(cscene, "transparent_min_bounces");
249         integrator->transparent_shadows = get_boolean(cscene, "use_transparent_shadows");
250
251         integrator->volume_max_steps = get_int(cscene, "volume_max_steps");
252         integrator->volume_step_size = get_float(cscene, "volume_step_size");
253
254         integrator->caustics_reflective = get_boolean(cscene, "caustics_reflective");
255         integrator->caustics_refractive = get_boolean(cscene, "caustics_refractive");
256         integrator->filter_glossy = get_float(cscene, "blur_glossy");
257
258         integrator->seed = get_int(cscene, "seed");
259         if(get_boolean(cscene, "use_animated_seed")) {
260                 integrator->seed = hash_int_2d(b_scene.frame_current(),
261                                                get_int(cscene, "seed"));
262                 if(b_scene.frame_subframe() != 0.0f) {
263                         /* TODO(sergey): Ideally should be some sort of hash_merge,
264                          * but this is good enough for now.
265                          */
266                         integrator->seed += hash_int_2d((int)(b_scene.frame_subframe() * (float)INT_MAX),
267                                                         get_int(cscene, "seed"));
268                 }
269         }
270
271         integrator->sampling_pattern = (SamplingPattern)get_enum(
272                 cscene,
273                 "sampling_pattern",
274                 SAMPLING_NUM_PATTERNS,
275                 SAMPLING_PATTERN_SOBOL);
276
277         integrator->sample_clamp_direct = get_float(cscene, "sample_clamp_direct");
278         integrator->sample_clamp_indirect = get_float(cscene, "sample_clamp_indirect");
279 #ifdef __CAMERA_MOTION__
280         if(!preview) {
281                 if(integrator->motion_blur != r.use_motion_blur()) {
282                         scene->object_manager->tag_update(scene);
283                         scene->camera->tag_update();
284                 }
285
286                 integrator->motion_blur = r.use_motion_blur();
287         }
288 #endif
289
290         integrator->method = (Integrator::Method)get_enum(cscene,
291                                                           "progressive",
292                                                           Integrator::NUM_METHODS,
293                                                           Integrator::PATH);
294
295         integrator->sample_all_lights_direct = get_boolean(cscene, "sample_all_lights_direct");
296         integrator->sample_all_lights_indirect = get_boolean(cscene, "sample_all_lights_indirect");
297         integrator->light_sampling_threshold = get_float(cscene, "light_sampling_threshold");
298
299         int diffuse_samples = get_int(cscene, "diffuse_samples");
300         int glossy_samples = get_int(cscene, "glossy_samples");
301         int transmission_samples = get_int(cscene, "transmission_samples");
302         int ao_samples = get_int(cscene, "ao_samples");
303         int mesh_light_samples = get_int(cscene, "mesh_light_samples");
304         int subsurface_samples = get_int(cscene, "subsurface_samples");
305         int volume_samples = get_int(cscene, "volume_samples");
306
307         if(get_boolean(cscene, "use_square_samples")) {
308                 integrator->diffuse_samples = diffuse_samples * diffuse_samples;
309                 integrator->glossy_samples = glossy_samples * glossy_samples;
310                 integrator->transmission_samples = transmission_samples * transmission_samples;
311                 integrator->ao_samples = ao_samples * ao_samples;
312                 integrator->mesh_light_samples = mesh_light_samples * mesh_light_samples;
313                 integrator->subsurface_samples = subsurface_samples * subsurface_samples;
314                 integrator->volume_samples = volume_samples * volume_samples;
315         } 
316         else {
317                 integrator->diffuse_samples = diffuse_samples;
318                 integrator->glossy_samples = glossy_samples;
319                 integrator->transmission_samples = transmission_samples;
320                 integrator->ao_samples = ao_samples;
321                 integrator->mesh_light_samples = mesh_light_samples;
322                 integrator->subsurface_samples = subsurface_samples;
323                 integrator->volume_samples = volume_samples;
324         }
325
326         if(b_scene.render().use_simplify()) {
327                 if(preview) {
328                         integrator->ao_bounces = get_int(cscene, "ao_bounces");
329                 }
330                 else {
331                         integrator->ao_bounces = get_int(cscene, "ao_bounces_render");
332                 }
333         }
334
335         if(integrator->modified(previntegrator))
336                 integrator->tag_update(scene);
337 }
338
339 /* Film */
340
341 void BlenderSync::sync_film()
342 {
343         PointerRNA cscene = RNA_pointer_get(&b_scene.ptr, "cycles");
344
345         Film *film = scene->film;
346         Film prevfilm = *film;
347         
348         film->exposure = get_float(cscene, "film_exposure");
349         film->filter_type = (FilterType)get_enum(cscene,
350                                                  "pixel_filter_type",
351                                                  FILTER_NUM_TYPES,
352                                                  FILTER_BLACKMAN_HARRIS);
353         film->filter_width = (film->filter_type == FILTER_BOX)? 1.0f: get_float(cscene, "filter_width");
354
355         if(b_scene.world()) {
356                 BL::WorldMistSettings b_mist = b_scene.world().mist_settings();
357
358                 film->mist_start = b_mist.start();
359                 film->mist_depth = b_mist.depth();
360
361                 switch(b_mist.falloff()) {
362                         case BL::WorldMistSettings::falloff_QUADRATIC:
363                                 film->mist_falloff = 2.0f;
364                                 break;
365                         case BL::WorldMistSettings::falloff_LINEAR:
366                                 film->mist_falloff = 1.0f;
367                                 break;
368                         case BL::WorldMistSettings::falloff_INVERSE_QUADRATIC:
369                                 film->mist_falloff = 0.5f;
370                                 break;
371                 }
372         }
373
374         if(film->modified(prevfilm))
375                 film->tag_update(scene);
376 }
377
378 /* Render Layer */
379
380 void BlenderSync::sync_render_layers(BL::SpaceView3D& b_v3d, const char *layer)
381 {
382         PointerRNA cscene = RNA_pointer_get(&b_scene.ptr, "cycles");
383         string layername;
384
385         /* 3d view */
386         if(b_v3d) {
387                 if(RNA_boolean_get(&cscene, "preview_active_layer")) {
388                         BL::RenderLayers layers(b_scene.render().ptr);
389                         layername = layers.active().name();
390                         layer = layername.c_str();
391                 }
392                 else {
393                         render_layer.scene_layer = get_layer(b_v3d.layers(), b_v3d.layers_local_view());
394                         render_layer.layer = render_layer.scene_layer;
395                         render_layer.exclude_layer = 0;
396                         render_layer.holdout_layer = 0;
397                         render_layer.material_override = PointerRNA_NULL;
398                         render_layer.use_background_shader = true;
399                         render_layer.use_background_ao = true;
400                         render_layer.use_hair = true;
401                         render_layer.use_surfaces = true;
402                         render_layer.use_viewport_visibility = true;
403                         render_layer.samples = 0;
404                         render_layer.bound_samples = false;
405                         return;
406                 }
407         }
408
409         /* render layer */
410         BL::RenderSettings r = b_scene.render();
411         BL::RenderSettings::layers_iterator b_rlay;
412         int use_layer_samples = get_enum(cscene, "use_layer_samples");
413         bool first_layer = true;
414         uint layer_override = get_layer(b_engine.layer_override());
415         uint scene_layers = layer_override ? layer_override : get_layer(b_scene.layers());
416
417         for(r.layers.begin(b_rlay); b_rlay != r.layers.end(); ++b_rlay) {
418                 if((!layer && first_layer) || (layer && b_rlay->name() == layer)) {
419                         render_layer.name = b_rlay->name();
420
421                         render_layer.holdout_layer = get_layer(b_rlay->layers_zmask());
422                         render_layer.exclude_layer = get_layer(b_rlay->layers_exclude());
423
424                         render_layer.scene_layer = scene_layers & ~render_layer.exclude_layer;
425                         render_layer.scene_layer |= render_layer.exclude_layer & render_layer.holdout_layer;
426
427                         render_layer.layer = get_layer(b_rlay->layers());
428                         render_layer.layer |= render_layer.holdout_layer;
429
430                         render_layer.material_override = b_rlay->material_override();
431                         render_layer.use_background_shader = b_rlay->use_sky();
432                         render_layer.use_background_ao = b_rlay->use_ao();
433                         render_layer.use_surfaces = b_rlay->use_solid();
434                         render_layer.use_hair = b_rlay->use_strand();
435                         render_layer.use_viewport_visibility = false;
436
437                         render_layer.bound_samples = (use_layer_samples == 1);
438                         if(use_layer_samples != 2) {
439                                 int samples = b_rlay->samples();
440                                 if(get_boolean(cscene, "use_square_samples"))
441                                         render_layer.samples = samples * samples;
442                                 else
443                                         render_layer.samples = samples;
444                         }
445                 }
446
447                 first_layer = false;
448         }
449 }
450
451 /* Images */
452 void BlenderSync::sync_images()
453 {
454         /* Sync is a convention for this API, but currently it frees unused buffers. */
455
456         const bool is_interface_locked = b_engine.render() &&
457                                          b_engine.render().use_lock_interface();
458         if(is_interface_locked == false && BlenderSession::headless == false) {
459                 /* If interface is not locked, it's possible image is needed for
460                  * the display.
461                  */
462                 return;
463         }
464         /* Free buffers used by images which are not needed for render. */
465         BL::BlendData::images_iterator b_image;
466         for(b_data.images.begin(b_image);
467             b_image != b_data.images.end();
468             ++b_image)
469         {
470                 /* TODO(sergey): Consider making it an utility function to check
471                  * whether image is considered builtin.
472                  */
473                 const bool is_builtin = b_image->packed_file() ||
474                                         b_image->source() == BL::Image::source_GENERATED ||
475                                         b_image->source() == BL::Image::source_MOVIE ||
476                                         b_engine.is_preview();
477                 if(is_builtin == false) {
478                         b_image->buffers_free();
479                 }
480                 /* TODO(sergey): Free builtin images not used by any shader. */
481         }
482 }
483
484 /* Passes */
485 PassType BlenderSync::get_pass_type(BL::RenderPass& b_pass)
486 {
487         string name = b_pass.name();
488 #define MAP_PASS(passname, passtype) if(name == passname) return passtype;
489         /* NOTE: Keep in sync with defined names from DNA_scene_types.h */
490         MAP_PASS("Combined", PASS_COMBINED);
491         MAP_PASS("Depth", PASS_DEPTH);
492         MAP_PASS("Mist", PASS_MIST);
493         MAP_PASS("Normal", PASS_NORMAL);
494         MAP_PASS("IndexOB", PASS_OBJECT_ID);
495         MAP_PASS("UV", PASS_UV);
496         MAP_PASS("Vector", PASS_MOTION);
497         MAP_PASS("IndexMA", PASS_MATERIAL_ID);
498
499         MAP_PASS("DiffDir", PASS_DIFFUSE_DIRECT);
500         MAP_PASS("GlossDir", PASS_GLOSSY_DIRECT);
501         MAP_PASS("TransDir", PASS_TRANSMISSION_DIRECT);
502         MAP_PASS("SubsurfaceDir", PASS_SUBSURFACE_DIRECT);
503
504         MAP_PASS("DiffInd", PASS_DIFFUSE_INDIRECT);
505         MAP_PASS("GlossInd", PASS_GLOSSY_INDIRECT);
506         MAP_PASS("TransInd", PASS_TRANSMISSION_INDIRECT);
507         MAP_PASS("SubsurfaceInd", PASS_SUBSURFACE_INDIRECT);
508
509         MAP_PASS("DiffCol", PASS_DIFFUSE_COLOR);
510         MAP_PASS("GlossCol", PASS_GLOSSY_COLOR);
511         MAP_PASS("TransCol", PASS_TRANSMISSION_COLOR);
512         MAP_PASS("SubsurfaceCol", PASS_SUBSURFACE_COLOR);
513
514         MAP_PASS("Emit", PASS_EMISSION);
515         MAP_PASS("Env", PASS_BACKGROUND);
516         MAP_PASS("AO", PASS_AO);
517         MAP_PASS("Shadow", PASS_SHADOW);
518
519 #ifdef __KERNEL_DEBUG__
520         MAP_PASS("Debug BVH Traversed Nodes", PASS_BVH_TRAVERSED_NODES);
521         MAP_PASS("Debug BVH Traversed Instances", PASS_BVH_TRAVERSED_INSTANCES);
522         MAP_PASS("Debug BVH Intersections", PASS_BVH_INTERSECTIONS);
523         MAP_PASS("Debug Ray Bounces", PASS_RAY_BOUNCES);
524 #endif
525 #undef MAP_PASS
526
527         return PASS_NONE;
528 }
529
530 array<Pass> BlenderSync::sync_render_passes(BL::RenderLayer& b_rlay,
531                                             BL::SceneRenderLayer& b_srlay)
532 {
533         array<Pass> passes;
534         Pass::add(PASS_COMBINED, passes);
535
536         /* loop over passes */
537         BL::RenderLayer::passes_iterator b_pass_iter;
538
539         for(b_rlay.passes.begin(b_pass_iter); b_pass_iter != b_rlay.passes.end(); ++b_pass_iter) {
540                 BL::RenderPass b_pass(*b_pass_iter);
541                 PassType pass_type = get_pass_type(b_pass);
542
543                 if(pass_type == PASS_MOTION && scene->integrator->motion_blur)
544                         continue;
545                 if(pass_type != PASS_NONE)
546                         Pass::add(pass_type, passes);
547         }
548
549 #ifdef __KERNEL_DEBUG__
550         PointerRNA crp = RNA_pointer_get(&b_srlay.ptr, "cycles");
551         if(get_boolean(crp, "pass_debug_bvh_traversed_nodes")) {
552                 b_engine.add_pass("Debug BVH Traversed Nodes", 1, "X", b_srlay.name().c_str());
553                 Pass::add(PASS_BVH_TRAVERSED_NODES, passes);
554         }
555         if(get_boolean(crp, "pass_debug_bvh_traversed_instances")) {
556                 b_engine.add_pass("Debug BVH Traversed Instances", 1, "X", b_srlay.name().c_str());
557                 Pass::add(PASS_BVH_TRAVERSED_INSTANCES, passes);
558         }
559         if(get_boolean(crp, "pass_debug_bvh_intersections")) {
560                 b_engine.add_pass("Debug BVH Intersections", 1, "X", b_srlay.name().c_str());
561                 Pass::add(PASS_BVH_INTERSECTIONS, passes);
562         }
563         if(get_boolean(crp, "pass_debug_ray_bounces")) {
564                 b_engine.add_pass("Debug Ray Bounces", 1, "X", b_srlay.name().c_str());
565                 Pass::add(PASS_RAY_BOUNCES, passes);
566         }
567 #else
568         (void) b_srlay;  /* Ignored. */
569 #endif
570
571         return passes;
572 }
573
574 /* Scene Parameters */
575
576 SceneParams BlenderSync::get_scene_params(BL::Scene& b_scene,
577                                           bool background,
578                                           bool is_cpu)
579 {
580         BL::RenderSettings r = b_scene.render();
581         SceneParams params;
582         PointerRNA cscene = RNA_pointer_get(&b_scene.ptr, "cycles");
583         const bool shadingsystem = RNA_boolean_get(&cscene, "shading_system");
584
585         if(shadingsystem == 0)
586                 params.shadingsystem = SHADINGSYSTEM_SVM;
587         else if(shadingsystem == 1)
588                 params.shadingsystem = SHADINGSYSTEM_OSL;
589         
590         if(background)
591                 params.bvh_type = SceneParams::BVH_STATIC;
592         else
593                 params.bvh_type = (SceneParams::BVHType)get_enum(
594                         cscene,
595                         "debug_bvh_type",
596                         SceneParams::BVH_NUM_TYPES,
597                         SceneParams::BVH_STATIC);
598
599         params.use_bvh_spatial_split = RNA_boolean_get(&cscene, "debug_use_spatial_splits");
600         params.use_bvh_unaligned_nodes = RNA_boolean_get(&cscene, "debug_use_hair_bvh");
601         params.num_bvh_time_steps = RNA_int_get(&cscene, "debug_bvh_time_steps");
602
603         if(background && params.shadingsystem != SHADINGSYSTEM_OSL)
604                 params.persistent_data = r.use_persistent_data();
605         else
606                 params.persistent_data = false;
607
608         int texture_limit;
609         if(background) {
610                 texture_limit = RNA_enum_get(&cscene, "texture_limit_render");
611         }
612         else {
613                 texture_limit = RNA_enum_get(&cscene, "texture_limit");
614         }
615         if(texture_limit > 0 && b_scene.render().use_simplify()) {
616                 params.texture_limit = 1 << (texture_limit + 6);
617         }
618         else {
619                 params.texture_limit = 0;
620         }
621
622 #if !(defined(__GNUC__) && (defined(i386) || defined(_M_IX86)))
623         if(is_cpu) {
624                 params.use_qbvh = DebugFlags().cpu.qbvh && system_cpu_support_sse2();
625         }
626         else
627 #endif
628         {
629                 params.use_qbvh = false;
630         }
631
632         return params;
633 }
634
635 /* Session Parameters */
636
637 bool BlenderSync::get_session_pause(BL::Scene& b_scene, bool background)
638 {
639         PointerRNA cscene = RNA_pointer_get(&b_scene.ptr, "cycles");
640         return (background)? false: get_boolean(cscene, "preview_pause");
641 }
642
643 SessionParams BlenderSync::get_session_params(BL::RenderEngine& b_engine,
644                                               BL::UserPreferences& b_userpref,
645                                               BL::Scene& b_scene,
646                                               bool background)
647 {
648         SessionParams params;
649         PointerRNA cscene = RNA_pointer_get(&b_scene.ptr, "cycles");
650
651         /* feature set */
652         params.experimental = (get_enum(cscene, "feature_set") != 0);
653
654         /* device type */
655         vector<DeviceInfo>& devices = Device::available_devices();
656         
657         /* device default CPU */
658         foreach(DeviceInfo& device, devices) {
659                 if(device.type == DEVICE_CPU) {
660                         params.device = device;
661                         break;
662                 }
663         }
664
665         if(get_enum(cscene, "device") == 2) {
666                 /* find network device */
667                 foreach(DeviceInfo& info, devices)
668                         if(info.type == DEVICE_NETWORK)
669                                 params.device = info;
670         }
671         else if(get_enum(cscene, "device") == 1) {
672                 PointerRNA b_preferences;
673
674                 BL::UserPreferences::addons_iterator b_addon_iter;
675                 for(b_userpref.addons.begin(b_addon_iter); b_addon_iter != b_userpref.addons.end(); ++b_addon_iter) {
676                         if(b_addon_iter->module() == "cycles") {
677                                 b_preferences = b_addon_iter->preferences().ptr;
678                                 break;
679                         }
680                 }
681
682                 int compute_device = get_enum(b_preferences, "compute_device_type");
683
684                 if(compute_device != 0) {
685                         vector<DeviceInfo> used_devices;
686                         RNA_BEGIN(&b_preferences, device, "devices") {
687                                 if(get_enum(device, "type") == compute_device && get_boolean(device, "use")) {
688                                         string id = get_string(device, "id");
689                                         foreach(DeviceInfo& info, devices) {
690                                                 if(info.id == id) {
691                                                         used_devices.push_back(info);
692                                                         break;
693                                                 }
694                                         }
695                                 }
696                         } RNA_END
697
698                         if(used_devices.size() == 1) {
699                                 params.device = used_devices[0];
700                         }
701                         else if(used_devices.size() > 1) {
702                                 params.device = Device::get_multi_device(used_devices);
703                         }
704                         /* Else keep using the CPU device that was set before. */
705                 }
706         }
707
708         /* Background */
709         params.background = background;
710
711         /* samples */
712         int samples = get_int(cscene, "samples");
713         int aa_samples = get_int(cscene, "aa_samples");
714         int preview_samples = get_int(cscene, "preview_samples");
715         int preview_aa_samples = get_int(cscene, "preview_aa_samples");
716         
717         if(get_boolean(cscene, "use_square_samples")) {
718                 aa_samples = aa_samples * aa_samples;
719                 preview_aa_samples = preview_aa_samples * preview_aa_samples;
720
721                 samples = samples * samples;
722                 preview_samples = preview_samples * preview_samples;
723         }
724
725         if(get_enum(cscene, "progressive") == 0) {
726                 if(background) {
727                         params.samples = aa_samples;
728                 }
729                 else {
730                         params.samples = preview_aa_samples;
731                         if(params.samples == 0)
732                                 params.samples = INT_MAX;
733                 }
734         }
735         else {
736                 if(background) {
737                         params.samples = samples;
738                 }
739                 else {
740                         params.samples = preview_samples;
741                         if(params.samples == 0)
742                                 params.samples = INT_MAX;
743                 }
744         }
745
746         /* tiles */
747         if(params.device.type != DEVICE_CPU && !background) {
748                 /* currently GPU could be much slower than CPU when using tiles,
749                  * still need to be investigated, but meanwhile make it possible
750                  * to work in viewport smoothly
751                  */
752                 int debug_tile_size = get_int(cscene, "debug_tile_size");
753
754                 params.tile_size = make_int2(debug_tile_size, debug_tile_size);
755         }
756         else {
757                 int tile_x = b_engine.tile_x();
758                 int tile_y = b_engine.tile_y();
759
760                 params.tile_size = make_int2(tile_x, tile_y);
761         }
762
763         if((BlenderSession::headless == false) && background) {
764                 params.tile_order = (TileOrder)get_enum(cscene, "tile_order");
765         }
766         else {
767                 params.tile_order = TILE_BOTTOM_TO_TOP;
768         }
769
770         params.start_resolution = get_int(cscene, "preview_start_resolution");
771
772         /* other parameters */
773         if(b_scene.render().threads_mode() == BL::RenderSettings::threads_mode_FIXED)
774                 params.threads = b_scene.render().threads();
775         else
776                 params.threads = 0;
777
778         params.cancel_timeout = (double)get_float(cscene, "debug_cancel_timeout");
779         params.reset_timeout = (double)get_float(cscene, "debug_reset_timeout");
780         params.text_timeout = (double)get_float(cscene, "debug_text_timeout");
781
782         params.progressive_refine = get_boolean(cscene, "use_progressive_refine");
783
784         if(background) {
785                 if(params.progressive_refine)
786                         params.progressive = true;
787                 else
788                         params.progressive = false;
789
790                 params.start_resolution = INT_MAX;
791         }
792         else
793                 params.progressive = true;
794
795         /* shading system - scene level needs full refresh */
796         const bool shadingsystem = RNA_boolean_get(&cscene, "shading_system");
797
798         if(shadingsystem == 0)
799                 params.shadingsystem = SHADINGSYSTEM_SVM;
800         else if(shadingsystem == 1)
801                 params.shadingsystem = SHADINGSYSTEM_OSL;
802         
803         /* color managagement */
804         params.display_buffer_linear = GLEW_ARB_half_float_pixel &&
805                                        b_engine.support_display_space_shader(b_scene);
806
807         if(b_engine.is_preview()) {
808                 /* For preview rendering we're using same timeout as
809                  * blender's job update.
810                  */
811                 params.progressive_update_timeout = 0.1;
812         }
813
814         return params;
815 }
816
817 CCL_NAMESPACE_END
818