diff options
author | Bastien Montagne <montagne29@wanadoo.fr> | 2017-03-28 11:41:10 +0300 |
---|---|---|
committer | Bastien Montagne <montagne29@wanadoo.fr> | 2017-03-28 11:41:10 +0300 |
commit | 885260117d6a9080ce073a1fb402b7af060f8645 (patch) | |
tree | 1769a4c180115a0fdda86d5554159c43691f461b | |
parent | 6d21970aa06a31398ed4a78b1c596f30a0b9ee87 (diff) | |
parent | e1909958d9ec48333a7bfd0d34aede66efc9b1ad (diff) |
Merge branch 'master' into blender2.8
Conflicts:
source/blender/blenloader/intern/readfile.c
source/blender/windowmanager/intern/wm_window.c
73 files changed, 1414 insertions, 693 deletions
diff --git a/intern/cycles/blender/addon/properties.py b/intern/cycles/blender/addon/properties.py index 6c5bcf09305..cbf469b3a89 100644 --- a/intern/cycles/blender/addon/properties.py +++ b/intern/cycles/blender/addon/properties.py @@ -1096,6 +1096,12 @@ class CyclesObjectSettings(bpy.types.PropertyGroup): default=1.0, ) + cls.is_shadow_catcher = BoolProperty( + name="Shadow Catcher", + description="Only render shadows on this object, for compositing renders into real footage", + default=False, + ) + @classmethod def unregister(cls): del bpy.types.Object.cycles diff --git a/intern/cycles/blender/addon/ui.py b/intern/cycles/blender/addon/ui.py index eec897474c5..4894b301606 100644 --- a/intern/cycles/blender/addon/ui.py +++ b/intern/cycles/blender/addon/ui.py @@ -268,7 +268,7 @@ class CyclesRender_PT_geometry(CyclesButtonsPanel, Panel): row = col.row() row.prop(ccscene, "minimum_width", text="Min Pixels") - row.prop(ccscene, "maximum_width", text="Max Ext.") + row.prop(ccscene, "maximum_width", text="Max Extension") class CyclesRender_PT_light_paths(CyclesButtonsPanel, Panel): @@ -786,6 +786,8 @@ class CyclesObject_PT_cycles_settings(CyclesButtonsPanel, Panel): if ob.type != 'LAMP': flow.prop(visibility, "shadow") + layout.prop(cob, "is_shadow_catcher") + col = layout.column() col.label(text="Performance:") row = col.row() diff --git a/intern/cycles/blender/blender_object.cpp b/intern/cycles/blender/blender_object.cpp index 637cf7abda8..968861391a2 100644 --- a/intern/cycles/blender/blender_object.cpp +++ b/intern/cycles/blender/blender_object.cpp @@ -343,6 +343,13 @@ Object *BlenderSync::sync_object(BL::Object& b_parent, object_updated = true; } + PointerRNA cobject = RNA_pointer_get(&b_ob.ptr, "cycles"); + bool is_shadow_catcher = get_boolean(cobject, "is_shadow_catcher"); + if(is_shadow_catcher != object->is_shadow_catcher) { + object->is_shadow_catcher = is_shadow_catcher; + object_updated = true; + } + /* object sync * transform comparison should not be needed, but duplis don't work perfect * in the depsgraph and may not signal changes, so this is a workaround */ diff --git a/intern/cycles/blender/blender_shader.cpp b/intern/cycles/blender/blender_shader.cpp index 8baa53fc2ec..f35565d8330 100644 --- a/intern/cycles/blender/blender_shader.cpp +++ b/intern/cycles/blender/blender_shader.cpp @@ -28,6 +28,7 @@ #include "util_debug.h" #include "util_string.h" +#include "util_task.h" CCL_NAMESPACE_BEGIN @@ -1164,6 +1165,8 @@ void BlenderSync::sync_materials(bool update_all) /* material loop */ BL::BlendData::materials_iterator b_mat; + TaskPool pool; + for(b_data.materials.begin(b_mat); b_mat != b_data.materials.end(); ++b_mat) { Shader *shader; @@ -1199,9 +1202,22 @@ void BlenderSync::sync_materials(bool update_all) shader->displacement_method = (experimental) ? get_displacement_method(cmat) : DISPLACE_BUMP; shader->set_graph(graph); + + /* By simplifying the shader graph as soon as possible, some redundant shader nodes + * might be removed which prevents loading unneccessary attributes later. + * + * However, since graph simplification also accounts for e.g. mix weight, this would + * cause frequent expensive resyncs in interactive sessions, so for those sessions + * optimization is only performed right before compiling. */ + if(!preview) { + pool.push(function_bind(&ShaderGraph::simplify, shader->graph, scene)); + } + shader->tag_update(scene); } } + + pool.wait_work(); } /* Sync World */ diff --git a/intern/cycles/device/device.cpp b/intern/cycles/device/device.cpp index 6b07b9d04bd..21eb3379694 100644 --- a/intern/cycles/device/device.cpp +++ b/intern/cycles/device/device.cpp @@ -48,11 +48,11 @@ std::ostream& operator <<(std::ostream &os, os << "Max nodes group: " << requested_features.max_nodes_group << std::endl; /* TODO(sergey): Decode bitflag into list of names. */ os << "Nodes features: " << requested_features.nodes_features << std::endl; - os << "Use hair: " + os << "Use Hair: " << string_from_bool(requested_features.use_hair) << std::endl; - os << "Use object motion: " + os << "Use Object Motion: " << string_from_bool(requested_features.use_object_motion) << std::endl; - os << "Use camera motion: " + os << "Use Camera Motion: " << string_from_bool(requested_features.use_camera_motion) << std::endl; os << "Use Baking: " << string_from_bool(requested_features.use_baking) << std::endl; diff --git a/intern/cycles/device/device.h b/intern/cycles/device/device.h index ec15a254f81..468a5b1515a 100644 --- a/intern/cycles/device/device.h +++ b/intern/cycles/device/device.h @@ -121,6 +121,9 @@ public: /* Use Transparent shadows */ bool use_transparent; + /* Use various shadow tricks, such as shadow catcher. */ + bool use_shadow_tricks; + DeviceRequestedFeatures() { /* TODO(sergey): Find more meaningful defaults. */ @@ -137,6 +140,7 @@ public: use_integrator_branched = false; use_patch_evaluation = false; use_transparent = false; + use_shadow_tricks = false; } bool modified(const DeviceRequestedFeatures& requested_features) @@ -153,7 +157,8 @@ public: use_volume == requested_features.use_volume && use_integrator_branched == requested_features.use_integrator_branched && use_patch_evaluation == requested_features.use_patch_evaluation && - use_transparent == requested_features.use_transparent); + use_transparent == requested_features.use_transparent && + use_shadow_tricks == requested_features.use_shadow_tricks); } /* Convert the requested features structure to a build options, @@ -197,6 +202,9 @@ public: if(!use_transparent && !use_volume) { build_options += " -D__NO_TRANSPARENT__"; } + if(!use_shadow_tricks) { + build_options += " -D__NO_SHADOW_TRICKS__"; + } return build_options; } }; diff --git a/intern/cycles/kernel/bvh/bvh.h b/intern/cycles/kernel/bvh/bvh.h index 598e138dbea..1358288f832 100644 --- a/intern/cycles/kernel/bvh/bvh.h +++ b/intern/cycles/kernel/bvh/bvh.h @@ -230,30 +230,63 @@ ccl_device_intersect void scene_intersect_subsurface(KernelGlobals *kg, #endif #ifdef __SHADOW_RECORD_ALL__ -ccl_device_intersect bool scene_intersect_shadow_all(KernelGlobals *kg, const Ray *ray, Intersection *isect, uint max_hits, uint *num_hits) +ccl_device_intersect bool scene_intersect_shadow_all(KernelGlobals *kg, + const Ray *ray, + Intersection *isect, + int skip_object, + uint max_hits, + uint *num_hits) { # ifdef __OBJECT_MOTION__ if(kernel_data.bvh.have_motion) { # ifdef __HAIR__ - if(kernel_data.bvh.have_curves) - return bvh_intersect_shadow_all_hair_motion(kg, ray, isect, max_hits, num_hits); + if(kernel_data.bvh.have_curves) { + return bvh_intersect_shadow_all_hair_motion(kg, + ray, + isect, + skip_object, + max_hits, + num_hits); + } # endif /* __HAIR__ */ - return bvh_intersect_shadow_all_motion(kg, ray, isect, max_hits, num_hits); + return bvh_intersect_shadow_all_motion(kg, + ray, + isect, + skip_object, + max_hits, + num_hits); } # endif /* __OBJECT_MOTION__ */ # ifdef __HAIR__ - if(kernel_data.bvh.have_curves) - return bvh_intersect_shadow_all_hair(kg, ray, isect, max_hits, num_hits); + if(kernel_data.bvh.have_curves) { + return bvh_intersect_shadow_all_hair(kg, + ray, + isect, + skip_object, + max_hits, + num_hits); + } # endif /* __HAIR__ */ # ifdef __INSTANCING__ - if(kernel_data.bvh.have_instancing) - return bvh_intersect_shadow_all_instancing(kg, ray, isect, max_hits, num_hits); + if(kernel_data.bvh.have_instancing) { + return bvh_intersect_shadow_all_instancing(kg, + ray, + isect, + skip_object, + max_hits, + num_hits); + } # endif /* __INSTANCING__ */ - return bvh_intersect_shadow_all(kg, ray, isect, max_hits, num_hits); + return bvh_intersect_shadow_all(kg, + ray, + isect, + skip_object, + max_hits, + num_hits); } #endif /* __SHADOW_RECORD_ALL__ */ diff --git a/intern/cycles/kernel/bvh/bvh_shadow_all.h b/intern/cycles/kernel/bvh/bvh_shadow_all.h index 8f7c005e961..b2555b3a6bb 100644 --- a/intern/cycles/kernel/bvh/bvh_shadow_all.h +++ b/intern/cycles/kernel/bvh/bvh_shadow_all.h @@ -45,6 +45,7 @@ ccl_device_inline bool BVH_FUNCTION_FULL_NAME(BVH)(KernelGlobals *kg, const Ray *ray, Intersection *isect_array, + const int skip_object, const uint max_hits, uint *num_hits) { @@ -189,6 +190,16 @@ bool BVH_FUNCTION_FULL_NAME(BVH)(KernelGlobals *kg, while(prim_addr < prim_addr2) { kernel_assert((kernel_tex_fetch(__prim_type, prim_addr) & PRIMITIVE_ALL) == p_type); +#ifdef __SHADOW_TRICKS__ + uint tri_object = (object == OBJECT_NONE) + ? kernel_tex_fetch(__prim_object, prim_addr) + : object; + if(tri_object == skip_object) { + ++prim_addr; + continue; + } +#endif + bool hit; /* todo: specialized intersect functions which don't fill in @@ -398,6 +409,7 @@ bool BVH_FUNCTION_FULL_NAME(BVH)(KernelGlobals *kg, ccl_device_inline bool BVH_FUNCTION_NAME(KernelGlobals *kg, const Ray *ray, Intersection *isect_array, + const int skip_object, const uint max_hits, uint *num_hits) { @@ -406,6 +418,7 @@ ccl_device_inline bool BVH_FUNCTION_NAME(KernelGlobals *kg, return BVH_FUNCTION_FULL_NAME(QBVH)(kg, ray, isect_array, + skip_object, max_hits, num_hits); } @@ -416,6 +429,7 @@ ccl_device_inline bool BVH_FUNCTION_NAME(KernelGlobals *kg, return BVH_FUNCTION_FULL_NAME(BVH)(kg, ray, isect_array, + skip_object, max_hits, num_hits); } diff --git a/intern/cycles/kernel/bvh/qbvh_shadow_all.h b/intern/cycles/kernel/bvh/qbvh_shadow_all.h index 5d960787134..1663e23c334 100644 --- a/intern/cycles/kernel/bvh/qbvh_shadow_all.h +++ b/intern/cycles/kernel/bvh/qbvh_shadow_all.h @@ -33,6 +33,7 @@ ccl_device bool BVH_FUNCTION_FULL_NAME(QBVH)(KernelGlobals *kg, const Ray *ray, Intersection *isect_array, + const int skip_object, const uint max_hits, uint *num_hits) { @@ -270,6 +271,16 @@ ccl_device bool BVH_FUNCTION_FULL_NAME(QBVH)(KernelGlobals *kg, while(prim_addr < prim_addr2) { kernel_assert((kernel_tex_fetch(__prim_type, prim_addr) & PRIMITIVE_ALL) == p_type); +#ifdef __SHADOW_TRICKS__ + uint tri_object = (object == OBJECT_NONE) + ? kernel_tex_fetch(__prim_object, prim_addr) + : object; + if(tri_object == skip_object) { + ++prim_addr; + continue; + } +#endif + bool hit; /* todo: specialized intersect functions which don't fill in diff --git a/intern/cycles/kernel/kernel_accumulate.h b/intern/cycles/kernel/kernel_accumulate.h index c589c112cc2..823d30dde78 100644 --- a/intern/cycles/kernel/kernel_accumulate.h +++ b/intern/cycles/kernel/kernel_accumulate.h @@ -52,10 +52,17 @@ ccl_device_inline void bsdf_eval_init(BsdfEval *eval, ClosureType type, float3 v { eval->diffuse = value; } +#ifdef __SHADOW_TRICKS__ + eval->sum_no_mis = make_float3(0.0f, 0.0f, 0.0f); +#endif } -ccl_device_inline void bsdf_eval_accum(BsdfEval *eval, ClosureType type, float3 value) +ccl_device_inline void bsdf_eval_accum(BsdfEval *eval, ClosureType type, float3 value, float mis_weight) { +#ifdef __SHADOW_TRICKS__ + eval->sum_no_mis += value; +#endif + value *= mis_weight; #ifdef __PASSES__ if(eval->use_light_pass) { if(CLOSURE_IS_BSDF_DIFFUSE(type)) @@ -96,7 +103,7 @@ ccl_device_inline bool bsdf_eval_is_zero(BsdfEval *eval) } } -ccl_device_inline void bsdf_eval_mul(BsdfEval *eval, float value) +ccl_device_inline void bsdf_eval_mis(BsdfEval *eval, float value) { #ifdef __PASSES__ if(eval->use_light_pass) { @@ -115,8 +122,19 @@ ccl_device_inline void bsdf_eval_mul(BsdfEval *eval, float value) } } +ccl_device_inline void bsdf_eval_mul(BsdfEval *eval, float value) +{ +#ifdef __SHADOW_TRICKS__ + eval->sum_no_mis *= value; +#endif + bsdf_eval_mis(eval, value); +} + ccl_device_inline void bsdf_eval_mul3(BsdfEval *eval, float3 value) { +#ifdef __SHADOW_TRICKS__ + eval->sum_no_mis *= value; +#endif #ifdef __PASSES__ if(eval->use_light_pass) { eval->diffuse *= value; @@ -134,7 +152,7 @@ ccl_device_inline void bsdf_eval_mul3(BsdfEval *eval, float3 value) #endif } -ccl_device_inline float3 bsdf_eval_sum(BsdfEval *eval) +ccl_device_inline float3 bsdf_eval_sum(const BsdfEval *eval) { #ifdef __PASSES__ if(eval->use_light_pass) { @@ -198,6 +216,12 @@ ccl_device_inline void path_radiance_init(PathRadiance *L, int use_light_pass) { L->emission = make_float3(0.0f, 0.0f, 0.0f); } + +#ifdef __SHADOW_TRICKS__ + L->path_total = make_float3(0.0f, 0.0f, 0.0f); + L->path_total_shaded = make_float3(0.0f, 0.0f, 0.0f); + L->shadow_color = make_float3(0.0f, 0.0f, 0.0f); +#endif } ccl_device_inline void path_radiance_bsdf_bounce(PathRadiance *L, ccl_addr_space float3 *throughput, @@ -252,7 +276,12 @@ ccl_device_inline void path_radiance_accum_emission(PathRadiance *L, float3 thro } } -ccl_device_inline void path_radiance_accum_ao(PathRadiance *L, float3 throughput, float3 alpha, float3 bsdf, float3 ao, int bounce) +ccl_device_inline void path_radiance_accum_ao(PathRadiance *L, + float3 throughput, + float3 alpha, + float3 bsdf, + float3 ao, + int bounce) { #ifdef __PASSES__ if(L->use_light_pass) { @@ -271,6 +300,26 @@ ccl_device_inline void path_radiance_accum_ao(PathRadiance *L, float3 throughput { L->emission += throughput*bsdf*ao; } + +#ifdef __SHADOW_TRICKS__ + float3 light = throughput * bsdf; + L->path_total += light; + L->path_total_shaded += ao * light; +#endif +} + +ccl_device_inline void path_radiance_accum_total_ao( + PathRadiance *L, + float3 throughput, + float3 bsdf) +{ +#ifdef __SHADOW_TRICKS__ + L->path_total += throughput * bsdf; +#else + (void) L; + (void) throughput; + (void) bsdf; +#endif } ccl_device_inline void path_radiance_accum_light(PathRadiance *L, float3 throughput, BsdfEval *bsdf_eval, float3 shadow, float shadow_fac, int bounce, bool is_lamp) @@ -301,15 +350,38 @@ ccl_device_inline void path_radiance_accum_light(PathRadiance *L, float3 through { L->emission += throughput*bsdf_eval->diffuse*shadow; } + +#ifdef __SHADOW_TRICKS__ + float3 light = throughput * bsdf_eval->sum_no_mis; + L->path_total += light; + L->path_total_shaded += shadow * light; +#endif +} + +ccl_device_inline void path_radiance_accum_total_light( + PathRadiance *L, + float3 throughput, + const BsdfEval *bsdf_eval) +{ +#ifdef __SHADOW_TRICKS__ + L->path_total += throughput * bsdf_eval->sum_no_mis; +#else + (void) L; + (void) throughput; + (void) bsdf_eval; +#endif } -ccl_device_inline void path_radiance_accum_background(PathRadiance *L, float3 throughput, float3 value, int bounce) +ccl_device_inline void path_radiance_accum_background(PathRadiance *L, + ccl_addr_space PathState *state, + float3 throughput, + float3 value) { #ifdef __PASSES__ if(L->use_light_pass) { - if(bounce == 0) + if(state->bounce == 0) L->background += throughput*value; - else if(bounce == 1) + else if(state->bounce == 1) L->direct_emission += throughput*value; else L->indirect += throughput*value; @@ -319,6 +391,13 @@ ccl_device_inline void path_radiance_accum_background(PathRadiance *L, float3 th { L->emission += throughput*value; } + +#ifdef __SHADOW_TRICKS__ + L->path_total += throughput * value; + if(state->flag & PATH_RAY_SHADOW_CATCHER_ONLY) { + L->path_total_shaded += throughput * value; + } +#endif } ccl_device_inline void path_radiance_sum_indirect(PathRadiance *L) @@ -501,5 +580,34 @@ ccl_device_inline void path_radiance_accum_sample(PathRadiance *L, PathRadiance L->emission += L_sample->emission * fac; } -CCL_NAMESPACE_END +#ifdef __SHADOW_TRICKS__ +/* Calculate current shadow of the path. */ +ccl_device_inline float path_radiance_sum_shadow(const PathRadiance *L) +{ + float path_total = average(L->path_total); + float path_total_shaded = average(L->path_total_shaded); + if(path_total != 0.0f) { + return path_total_shaded / path_total; + } + return 1.0f; +} +/* Calculate final light sum and transparency for shadow catcher object. */ +ccl_device_inline float3 path_radiance_sum_shadowcatcher(KernelGlobals *kg, + const PathRadiance *L, + ccl_addr_space float* L_transparent) +{ + const float shadow = path_radiance_sum_shadow(L); + float3 L_sum; + if(kernel_data.background.transparent) { + *L_transparent = shadow; + L_sum = make_float3(0.0f, 0.0f, 0.0f); + } + else { + L_sum = L->shadow_color * shadow; + } + return L_sum; +} +#endif + +CCL_NAMESPACE_END diff --git a/intern/cycles/kernel/kernel_emission.h b/intern/cycles/kernel/kernel_emission.h index cf14a159e47..9e7d51f23f5 100644 --- a/intern/cycles/kernel/kernel_emission.h +++ b/intern/cycles/kernel/kernel_emission.h @@ -156,7 +156,12 @@ ccl_device_noinline bool direct_emission(KernelGlobals *kg, if(bsdf_eval_is_zero(eval)) return false; - if(kernel_data.integrator.light_inv_rr_threshold > 0.0f) { + if(kernel_data.integrator.light_inv_rr_threshold > 0.0f +#ifdef __SHADOW_TRICKS__ + && (state->flag & PATH_RAY_SHADOW_CATCHER) == 0 +#endif + ) + { float probability = max3(fabs(bsdf_eval_sum(eval))) * kernel_data.integrator.light_inv_rr_threshold; if(probability < 1.0f) { if(rand_terminate >= probability) { diff --git a/intern/cycles/kernel/kernel_path.h b/intern/cycles/kernel/kernel_path.h index ebf03ad9778..31d5285796c 100644 --- a/intern/cycles/kernel/kernel_path.h +++ b/intern/cycles/kernel/kernel_path.h @@ -92,6 +92,9 @@ ccl_device_noinline void kernel_path_ao(KernelGlobals *kg, if(!shadow_blocked(kg, emission_sd, state, &light_ray, &ao_shadow)) { path_radiance_accum_ao(L, throughput, ao_alpha, ao_bsdf, ao_shadow, state->bounce); } + else { + path_radiance_accum_total_ao(L, throughput, ao_bsdf); + } } } @@ -290,9 +293,9 @@ ccl_device void kernel_path_indirect(KernelGlobals *kg, /* sample background shader */ float3 L_background = indirect_background(kg, emission_sd, state, ray); path_radiance_accum_background(L, + state, throughput, - L_background, - state->bounce); + L_background); #endif /* __BACKGROUND__ */ break; @@ -312,6 +315,12 @@ ccl_device void kernel_path_indirect(KernelGlobals *kg, shader_merge_closures(sd); #endif /* __BRANCHED_PATH__ */ +#ifdef __SHADOW_TRICKS__ + if(!(sd->object_flag & SD_OBJECT_SHADOW_CATCHER)) { + state->flag &= ~PATH_RAY_SHADOW_CATCHER_ONLY; + } +#endif /* __SHADOW_TRICKS__ */ + /* blurring of bsdf after bounces, for rays that have a small likelihood * of following this particular path (diffuse, rough glossy) */ if(kernel_data.integrator.filter_glossy != FLT_MAX) { @@ -374,7 +383,7 @@ ccl_device void kernel_path_indirect(KernelGlobals *kg, /* do bssrdf scatter step if we picked a bssrdf closure */ if(sc) { - uint lcg_state = lcg_state_init(rng, state, 0x68bc21eb); + uint lcg_state = lcg_state_init(rng, state->rng_offset, state->sample, 0x68bc21eb); float bssrdf_u, bssrdf_v; path_state_rng_2D(kg, @@ -396,7 +405,8 @@ ccl_device void kernel_path_indirect(KernelGlobals *kg, #if defined(__EMISSION__) && defined(__BRANCHED_PATH__) if(kernel_data.integrator.use_direct_light) { - int all = kernel_data.integrator.sample_all_lights_indirect; + int all = (kernel_data.integrator.sample_all_lights_indirect) || + (state->flag & PATH_RAY_SHADOW_CATCHER); kernel_branched_path_surface_connect_light(kg, rng, sd, @@ -466,7 +476,7 @@ ccl_device_inline float4 kernel_path_integrate(KernelGlobals *kg, } extmax = kernel_data.curve.maximum_width; - lcg_state = lcg_state_init(rng, &state, 0x51633e2d); + lcg_state = lcg_state_init(rng, state.rng_offset, state.sample, 0x51633e2d); } if(state.bounce > kernel_data.integrator.ao_bounces) { @@ -611,7 +621,7 @@ ccl_device_inline float4 kernel_path_integrate(KernelGlobals *kg, #ifdef __BACKGROUND__ /* sample background shader */ float3 L_background = indirect_background(kg, &emission_sd, &state, &ray); - path_radiance_accum_background(&L, throughput, L_background, state.bounce); + path_radiance_accum_background(&L, &state, throughput, L_background); #endif /* __BACKGROUND__ */ break; @@ -625,6 +635,21 @@ ccl_device_inline float4 kernel_path_integrate(KernelGlobals *kg, float rbsdf = path_state_rng_1D_for_decision(kg, rng, &state, PRNG_BSDF); shader_eval_surface(kg, &sd, rng, &state, rbsdf, state.flag, SHADER_CONTEXT_MAIN); +#ifdef __SHADOW_TRICKS__ + if((sd.object_flag & SD_OBJECT_SHADOW_CATCHER)) { + if(state.flag & PATH_RAY_CAMERA) { + state.flag |= (PATH_RAY_SHADOW_CATCHER | PATH_RAY_SHADOW_CATCHER_ONLY); + state.catcher_object = sd.object; + if(!kernel_data.background.transparent) { + L.shadow_color = indirect_background(kg, &emission_sd, &state, &ray); + } + } + } + else { + state.flag &= ~PATH_RAY_SHADOW_CATCHER_ONLY; + } +#endif /* __SHADOW_TRICKS__ */ + /* holdout */ #ifdef __HOLDOUT__ if(((sd.flag & SD_HOLDOUT) || @@ -742,7 +767,16 @@ ccl_device_inline float4 kernel_path_integrate(KernelGlobals *kg, } #endif /* __SUBSURFACE__ */ - float3 L_sum = path_radiance_clamp_and_sum(kg, &L); + float3 L_sum; +#ifdef __SHADOW_TRICKS__ + if(state.flag & PATH_RAY_SHADOW_CATCHER) { + L_sum = path_radiance_sum_shadowcatcher(kg, &L, &L_transparent); + } + else +#endif /* __SHADOW_TRICKS__ */ + { + L_sum = path_radiance_clamp_and_sum(kg, &L); + } kernel_write_light_passes(kg, buffer, &L, sample); diff --git a/intern/cycles/kernel/kernel_path_branched.h b/intern/cycles/kernel/kernel_path_branched.h index d58960cae4e..36fd6c95fe7 100644 --- a/intern/cycles/kernel/kernel_path_branched.h +++ b/intern/cycles/kernel/kernel_path_branched.h @@ -55,8 +55,12 @@ ccl_device_inline void kernel_branched_path_ao(KernelGlobals *kg, light_ray.dP = sd->dP; light_ray.dD = differential3_zero(); - if(!shadow_blocked(kg, emission_sd, state, &light_ray, &ao_shadow)) + if(!shadow_blocked(kg, emission_sd, state, &light_ray, &ao_shadow)) { path_radiance_accum_ao(L, throughput*num_samples_inv, ao_alpha, ao_bsdf, ao_shadow, state->bounce); + } + else { + path_radiance_accum_total_ao(L, throughput*num_samples_inv, ao_bsdf); + } } } } @@ -147,7 +151,7 @@ ccl_device void kernel_branched_path_subsurface_scatter(KernelGlobals *kg, continue; /* set up random number generator */ - uint lcg_state = lcg_state_init(rng, state, 0x68bc21eb); + uint lcg_state = lcg_state_init(rng, state->rng_offset, state->sample, 0x68bc21eb); int num_samples = kernel_data.integrator.subsurface_samples; float num_samples_inv = 1.0f/num_samples; RNG bssrdf_rng = cmj_hash(*rng, i); @@ -206,7 +210,8 @@ ccl_device void kernel_branched_path_subsurface_scatter(KernelGlobals *kg, #ifdef __EMISSION__ /* direct light */ if(kernel_data.integrator.use_direct_light) { - int all = kernel_data.integrator.sample_all_lights_direct; + int all = (kernel_data.integrator.sample_all_lights_direct) || + (state->flag & PATH_RAY_SHADOW_CATCHER); kernel_branched_path_surface_connect_light( kg, rng, @@ -280,7 +285,7 @@ ccl_device float4 kernel_branched_path_integrate(KernelGlobals *kg, RNG *rng, in } extmax = kernel_data.curve.maximum_width; - lcg_state = lcg_state_init(rng, &state, 0x51633e2d); + lcg_state = lcg_state_init(rng, state.rng_offset, state.sample, 0x51633e2d); } bool hit = scene_intersect(kg, ray, visibility, &isect, &lcg_state, difl, extmax); @@ -461,7 +466,7 @@ ccl_device float4 kernel_branched_path_integrate(KernelGlobals *kg, RNG *rng, in #ifdef __BACKGROUND__ /* sample background shader */ float3 L_background = indirect_background(kg, &emission_sd, &state, &ray); - path_radiance_accum_background(&L, throughput, L_background, state.bounce); + path_radiance_accum_background(&L, &state, throughput, L_background); #endif /* __BACKGROUND__ */ break; @@ -472,6 +477,21 @@ ccl_device float4 kernel_branched_path_integrate(KernelGlobals *kg, RNG *rng, in shader_eval_surface(kg, &sd, rng, &state, 0.0f, state.flag, SHADER_CONTEXT_MAIN); shader_merge_closures(&sd); +#ifdef __SHADOW_TRICKS__ + if((sd.object_flag & SD_OBJECT_SHADOW_CATCHER)) { + if(state.flag & PATH_RAY_CAMERA) { + state.flag |= (PATH_RAY_SHADOW_CATCHER | PATH_RAY_SHADOW_CATCHER_ONLY); + state.catcher_object = sd.object; + if(!kernel_data.background.transparent) { + L.shadow_color = indirect_background(kg, &emission_sd, &state, &ray); + } + } + } + else { + state.flag &= ~PATH_RAY_SHADOW_CATCHER_ONLY; + } +#endif /* __SHADOW_TRICKS__ */ + /* holdout */ #ifdef __HOLDOUT__ if((sd.flag & SD_HOLDOUT) || (sd.object_flag & SD_OBJECT_HOLDOUT_MASK)) { @@ -544,7 +564,8 @@ ccl_device float4 kernel_branched_path_integrate(KernelGlobals *kg, RNG *rng, in #ifdef __EMISSION__ /* direct light */ if(kernel_data.integrator.use_direct_light) { - int all = kernel_data.integrator.sample_all_lights_direct; + int all = (kernel_data.integrator.sample_all_lights_direct) || + (state.flag & PATH_RAY_SHADOW_CATCHER); kernel_branched_path_surface_connect_light(kg, rng, &sd, &emission_sd, &hit_state, throughput, 1.0f, &L, all); } @@ -581,7 +602,16 @@ ccl_device float4 kernel_branched_path_integrate(KernelGlobals *kg, RNG *rng, in #endif /* __VOLUME__ */ } - float3 L_sum = path_radiance_clamp_and_sum(kg, &L); + float3 L_sum; +#ifdef __SHADOW_TRICKS__ + if(state.flag & PATH_RAY_SHADOW_CATCHER) { + L_sum = path_radiance_sum_shadowcatcher(kg, &L, &L_transparent); + } + else +#endif /* __SHADOW_TRICKS__ */ + { + L_sum = path_radiance_clamp_and_sum(kg, &L); + } kernel_write_light_passes(kg, buffer, &L, sample); diff --git a/intern/cycles/kernel/kernel_path_common.h b/intern/cycles/kernel/kernel_path_common.h index 7b903556bf9..596210f442e 100644 --- a/intern/cycles/kernel/kernel_path_common.h +++ b/intern/cycles/kernel/kernel_path_common.h @@ -22,7 +22,7 @@ ccl_device_inline void kernel_path_trace_setup(KernelGlobals *kg, ccl_global uint *rng_state, int sample, int x, int y, - ccl_addr_space RNG *rng, + RNG *rng, ccl_addr_space Ray *ray) { float filter_u; diff --git a/intern/cycles/kernel/kernel_path_state.h b/intern/cycles/kernel/kernel_path_state.h index 661dc52fb31..c0cd2a63120 100644 --- a/intern/cycles/kernel/kernel_path_state.h +++ b/intern/cycles/kernel/kernel_path_state.h @@ -19,7 +19,7 @@ CCL_NAMESPACE_BEGIN ccl_device_inline void path_state_init(KernelGlobals *kg, ShaderData *stack_sd, ccl_addr_space PathState *state, - ccl_addr_space RNG *rng, + RNG *rng, int sample, ccl_addr_space Ray *ray) { @@ -54,6 +54,10 @@ ccl_device_inline void path_state_init(KernelGlobals *kg, state->volume_stack[0].shader = SHADER_NONE; } #endif + +#ifdef __SHADOW_TRICKS__ + state->catcher_object = OBJECT_NONE; +#endif } ccl_device_inline void path_state_next(KernelGlobals *kg, ccl_addr_space PathState *state, int label) diff --git a/intern/cycles/kernel/kernel_path_subsurface.h b/intern/cycles/kernel/kernel_path_subsurface.h index d22ec992074..10b568ac3dd 100644 --- a/intern/cycles/kernel/kernel_path_subsurface.h +++ b/intern/cycles/kernel/kernel_path_subsurface.h @@ -28,7 +28,7 @@ bool kernel_path_subsurface_scatter( ShaderData *emission_sd, PathRadiance *L, ccl_addr_space PathState *state, - ccl_addr_space RNG *rng, + RNG *rng, ccl_addr_space Ray *ray, ccl_addr_space float3 *throughput, ccl_addr_space SubsurfaceIndirectRays *ss_indirect) @@ -47,7 +47,7 @@ bool kernel_path_subsurface_scatter( */ kernel_assert(!ss_indirect->tracing); - uint lcg_state = lcg_state_init_addrspace(rng, state, 0x68bc21eb); + uint lcg_state = lcg_state_init(rng, state->rng_offset, state->sample, 0x68bc21eb); SubsurfaceIntersection ss_isect; float bssrdf_u, bssrdf_v; diff --git a/intern/cycles/kernel/kernel_path_surface.h b/intern/cycles/kernel/kernel_path_surface.h index efa23038089..076c82f3853 100644 --- a/intern/cycles/kernel/kernel_path_surface.h +++ b/intern/cycles/kernel/kernel_path_surface.h @@ -16,12 +16,18 @@ CCL_NAMESPACE_BEGIN -#if (defined(__BRANCHED_PATH__) || defined(__SUBSURFACE__)) && !defined(__SPLIT_KERNEL__) - +#if defined(__BRANCHED_PATH__) || defined(__SUBSURFACE__) || defined(__SHADOW_TRICKS__) /* branched path tracing: connect path directly to position on one or more lights and add it to L */ -ccl_device_noinline void kernel_branched_path_surface_connect_light(KernelGlobals *kg, RNG *rng, - ShaderData *sd, ShaderData *emission_sd, PathState *state, float3 throughput, - float num_samples_adjust, PathRadiance *L, int sample_all_lights) +ccl_device_noinline void kernel_branched_path_surface_connect_light( + KernelGlobals *kg, + RNG *rng, + ShaderData *sd, + ShaderData *emission_sd, + ccl_addr_space PathState *state, + float3 throughput, + float num_samples_adjust, + PathRadiance *L, + int sample_all_lights) { #ifdef __EMISSION__ /* sample illumination from lights to find path contribution */ @@ -66,6 +72,9 @@ ccl_device_noinline void kernel_branched_path_surface_connect_light(KernelGlobal /* accumulate */ path_radiance_accum_light(L, throughput*num_samples_inv, &L_light, shadow, num_samples_inv, state->bounce, is_lamp); } + else { + path_radiance_accum_total_light(L, throughput*num_samples_inv, &L_light); + } } } } @@ -100,6 +109,9 @@ ccl_device_noinline void kernel_branched_path_surface_connect_light(KernelGlobal /* accumulate */ path_radiance_accum_light(L, throughput*num_samples_inv, &L_light, shadow, num_samples_inv, state->bounce, is_lamp); } + else { + path_radiance_accum_total_light(L, throughput*num_samples_inv, &L_light); + } } } } @@ -123,6 +135,9 @@ ccl_device_noinline void kernel_branched_path_surface_connect_light(KernelGlobal /* accumulate */ path_radiance_accum_light(L, throughput*num_samples_adjust, &L_light, shadow, num_samples_adjust, state->bounce, is_lamp); } + else { + path_radiance_accum_total_light(L, throughput*num_samples_adjust, &L_light); + } } } } @@ -130,9 +145,17 @@ ccl_device_noinline void kernel_branched_path_surface_connect_light(KernelGlobal } /* branched path tracing: bounce off or through surface to with new direction stored in ray */ -ccl_device bool kernel_branched_path_surface_bounce(KernelGlobals *kg, RNG *rng, - ShaderData *sd, const ShaderClosure *sc, int sample, int num_samples, - float3 *throughput, PathState *state, PathRadiance *L, Ray *ray) +ccl_device bool kernel_branched_path_surface_bounce( + KernelGlobals *kg, + RNG *rng, + ShaderData *sd, + const ShaderClosure *sc, + int sample, + int num_samples, + ccl_addr_space float3 *throughput, + ccl_addr_space PathState *state, + PathRadiance *L, + Ray *ray) { /* sample BSDF */ float bsdf_pdf; @@ -189,7 +212,7 @@ ccl_device bool kernel_branched_path_surface_bounce(KernelGlobals *kg, RNG *rng, #endif /* path tracing: connect path directly to position on a light and add it to L */ -ccl_device_inline void kernel_path_surface_connect_light(KernelGlobals *kg, ccl_addr_space RNG *rng, +ccl_device_inline void kernel_path_surface_connect_light(KernelGlobals *kg, RNG *rng, ShaderData *sd, ShaderData *emission_sd, float3 throughput, ccl_addr_space PathState *state, PathRadiance *L) { @@ -197,6 +220,21 @@ ccl_device_inline void kernel_path_surface_connect_light(KernelGlobals *kg, ccl_ if(!(kernel_data.integrator.use_direct_light && (sd->flag & SD_BSDF_HAS_EVAL))) return; +#ifdef __SHADOW_TRICKS__ + if(state->flag & PATH_RAY_SHADOW_CATCHER) { + kernel_branched_path_surface_connect_light(kg, + rng, + sd, + emission_sd, + state, + throughput, + 1.0f, + L, + 1); + return; + } +#endif + /* sample illumination from lights to find path contribution */ float light_t = path_state_rng_1D(kg, rng, state, PRNG_LIGHT); float light_u, light_v; @@ -221,6 +259,9 @@ ccl_device_inline void kernel_path_surface_connect_light(KernelGlobals *kg, ccl_ /* accumulate */ path_radiance_accum_light(L, throughput, &L_light, shadow, 1.0f, state->bounce, is_lamp); } + else { + path_radiance_accum_total_light(L, throughput, &L_light); + } } } #endif @@ -228,7 +269,7 @@ ccl_device_inline void kernel_path_surface_connect_light(KernelGlobals *kg, ccl_ /* path tracing: bounce off or through surface to with new direction stored in ray */ ccl_device bool kernel_path_surface_bounce(KernelGlobals *kg, - ccl_addr_space RNG *rng, + RNG *rng, ShaderData *sd, ccl_addr_space float3 *throughput, ccl_addr_space PathState *state, diff --git a/intern/cycles/kernel/kernel_path_volume.h b/intern/cycles/kernel/kernel_path_volume.h index 28e1b5ba98e..371f2c1c7cb 100644 --- a/intern/cycles/kernel/kernel_path_volume.h +++ b/intern/cycles/kernel/kernel_path_volume.h @@ -20,7 +20,7 @@ CCL_NAMESPACE_BEGIN ccl_device_inline void kernel_path_volume_connect_light( KernelGlobals *kg, - ccl_addr_space RNG *rng, + RNG *rng, ShaderData *sd, ShaderData *emission_sd, float3 throughput, @@ -69,7 +69,7 @@ ccl_device #endif bool kernel_path_volume_bounce( KernelGlobals *kg, - ccl_addr_space RNG *rng, + RNG *rng, ShaderData *sd, ccl_addr_space float3 *throughput, ccl_addr_space PathState *state, @@ -117,10 +117,18 @@ bool kernel_path_volume_bounce( return true; } -#ifdef __BRANCHED_PATH__ -ccl_device void kernel_branched_path_volume_connect_light(KernelGlobals *kg, RNG *rng, - ShaderData *sd, ShaderData *emission_sd, float3 throughput, PathState *state, PathRadiance *L, - bool sample_all_lights, Ray *ray, const VolumeSegment *segment) +#ifndef __SPLIT_KERNEL__ +ccl_device void kernel_branched_path_volume_connect_light( + KernelGlobals *kg, + RNG *rng, + ShaderData *sd, + ShaderData *emission_sd, + float3 throughput, + ccl_addr_space PathState *state, + PathRadiance *L, + bool sample_all_lights, + Ray *ray, + const VolumeSegment *segment) { #ifdef __EMISSION__ if(!kernel_data.integrator.use_direct_light) @@ -270,7 +278,7 @@ ccl_device void kernel_branched_path_volume_connect_light(KernelGlobals *kg, RNG } #endif /* __EMISSION__ */ } -#endif /* __BRANCHED_PATH__ */ +#endif /* __SPLIT_KERNEL__ */ #endif /* __VOLUME_SCATTER__ */ diff --git a/intern/cycles/kernel/kernel_random.h b/intern/cycles/kernel/kernel_random.h index ad3fa32a809..485b7b84fc8 100644 --- a/intern/cycles/kernel/kernel_random.h +++ b/intern/cycles/kernel/kernel_random.h @@ -98,7 +98,7 @@ ccl_device uint sobol_lookup(const uint m, const uint frame, const uint ex, cons return index; } -ccl_device_forceinline float path_rng_1D(KernelGlobals *kg, ccl_addr_space RNG *rng, int sample, int num_samples, int dimension) +ccl_device_forceinline float path_rng_1D(KernelGlobals *kg, RNG *rng, int sample, int num_samples, int dimension) { #ifdef __CMJ__ if(kernel_data.integrator.sampling_pattern == SAMPLING_PATTERN_CMJ) { @@ -130,7 +130,7 @@ ccl_device_forceinline float path_rng_1D(KernelGlobals *kg, ccl_addr_space RNG * #endif } -ccl_device_forceinline void path_rng_2D(KernelGlobals *kg, ccl_addr_space RNG *rng, int sample, int num_samples, int dimension, float *fx, float *fy) +ccl_device_forceinline void path_rng_2D(KernelGlobals *kg, RNG *rng, int sample, int num_samples, int dimension, float *fx, float *fy) { #ifdef __CMJ__ if(kernel_data.integrator.sampling_pattern == SAMPLING_PATTERN_CMJ) { @@ -147,7 +147,7 @@ ccl_device_forceinline void path_rng_2D(KernelGlobals *kg, ccl_addr_space RNG *r } } -ccl_device_inline void path_rng_init(KernelGlobals *kg, ccl_global uint *rng_state, int sample, int num_samples, ccl_addr_space RNG *rng, int x, int y, float *fx, float *fy) +ccl_device_inline void path_rng_init(KernelGlobals *kg, ccl_global uint *rng_state, int sample, int num_samples, RNG *rng, int x, int y, float *fx, float *fy) { #ifdef __SOBOL_FULL_SCREEN__ uint px, py; @@ -259,12 +259,12 @@ ccl_device uint lcg_init(uint seed) * For branches in the path we must be careful not to reuse the same number * in a sequence and offset accordingly. */ -ccl_device_inline float path_state_rng_1D(KernelGlobals *kg, ccl_addr_space RNG *rng, const ccl_addr_space PathState *state, int dimension) +ccl_device_inline float path_state_rng_1D(KernelGlobals *kg, RNG *rng, const ccl_addr_space PathState *state, int dimension) { return path_rng_1D(kg, rng, state->sample, state->num_samples, state->rng_offset + dimension); } -ccl_device_inline float path_state_rng_1D_for_decision(KernelGlobals *kg, ccl_addr_space RNG *rng, const ccl_addr_space PathState *state, int dimension) +ccl_device_inline float path_state_rng_1D_for_decision(KernelGlobals *kg, RNG *rng, const ccl_addr_space PathState *state, int dimension) { /* the rng_offset is not increased for transparent bounces. if we do then * fully transparent objects can become subtly visible by the different @@ -277,29 +277,29 @@ ccl_device_inline float path_state_rng_1D_for_decision(KernelGlobals *kg, ccl_ad return path_rng_1D(kg, rng, state->sample, state->num_samples, rng_offset + dimension); } -ccl_device_inline void path_state_rng_2D(KernelGlobals *kg, ccl_addr_space RNG *rng, const ccl_addr_space PathState *state, int dimension, float *fx, float *fy) +ccl_device_inline void path_state_rng_2D(KernelGlobals *kg, RNG *rng, const ccl_addr_space PathState *state, int dimension, float *fx, float *fy) { path_rng_2D(kg, rng, state->sample, state->num_samples, state->rng_offset + dimension, fx, fy); } -ccl_device_inline float path_branched_rng_1D(KernelGlobals *kg, ccl_addr_space RNG *rng, const PathState *state, int branch, int num_branches, int dimension) +ccl_device_inline float path_branched_rng_1D(KernelGlobals *kg, RNG *rng, const ccl_addr_space PathState *state, int branch, int num_branches, int dimension) { return path_rng_1D(kg, rng, state->sample*num_branches + branch, state->num_samples*num_branches, state->rng_offset + dimension); } -ccl_device_inline float path_branched_rng_1D_for_decision(KernelGlobals *kg, ccl_addr_space RNG *rng, const PathState *state, int branch, int num_branches, int dimension) +ccl_device_inline float path_branched_rng_1D_for_decision(KernelGlobals *kg, RNG *rng, const ccl_addr_space PathState *state, int branch, int num_branches, int dimension) { int rng_offset = state->rng_offset + state->transparent_bounce*PRNG_BOUNCE_NUM; return path_rng_1D(kg, rng, state->sample*num_branches + branch, state->num_samples*num_branches, rng_offset + dimension); } -ccl_device_inline void path_branched_rng_2D(KernelGlobals *kg, ccl_addr_space RNG *rng, const PathState *state, int branch, int num_branches, int dimension, float *fx, float *fy) +ccl_device_inline void path_branched_rng_2D(KernelGlobals *kg, RNG *rng, const ccl_addr_space PathState *state, int branch, int num_branches, int dimension, float *fx, float *fy) { path_rng_2D(kg, rng, state->sample*num_branches + branch, state->num_samples*num_branches, state->rng_offset + dimension, fx, fy); } /* Utitility functions to get light termination value, since it might not be needed in many cases. */ -ccl_device_inline float path_state_rng_light_termination(KernelGlobals *kg, ccl_addr_space RNG *rng, const ccl_addr_space PathState *state) +ccl_device_inline float path_state_rng_light_termination(KernelGlobals *kg, RNG *rng, const ccl_addr_space PathState *state) { if(kernel_data.integrator.light_inv_rr_threshold > 0.0f) { return path_state_rng_1D_for_decision(kg, rng, state, PRNG_LIGHT_TERMINATE); @@ -307,7 +307,7 @@ ccl_device_inline float path_state_rng_light_termination(KernelGlobals *kg, ccl_ return 0.0f; } -ccl_device_inline float path_branched_rng_light_termination(KernelGlobals *kg, ccl_addr_space RNG *rng, const PathState *state, int branch, int num_branches) +ccl_device_inline float path_branched_rng_light_termination(KernelGlobals *kg, RNG *rng, const ccl_addr_space PathState *state, int branch, int num_branches) { if(kernel_data.integrator.light_inv_rr_threshold > 0.0f) { return path_branched_rng_1D_for_decision(kg, rng, state, branch, num_branches, PRNG_LIGHT_TERMINATE); @@ -315,7 +315,7 @@ ccl_device_inline float path_branched_rng_light_termination(KernelGlobals *kg, c return 0.0f; } -ccl_device_inline void path_state_branch(PathState *state, int branch, int num_branches) +ccl_device_inline void path_state_branch(ccl_addr_space PathState *state, int branch, int num_branches) { /* path is splitting into a branch, adjust so that each branch * still gets a unique sample from the same sequence */ @@ -324,18 +324,9 @@ ccl_device_inline void path_state_branch(PathState *state, int branch, int num_b state->num_samples = state->num_samples*num_branches; } -ccl_device_inline uint lcg_state_init(RNG *rng, const PathState *state, uint scramble) -{ - return lcg_init(*rng + state->rng_offset + state->sample*scramble); -} - -/* TODO(sergey): For until we can use generic address space from OpenCL 2.0. */ - -ccl_device_inline uint lcg_state_init_addrspace(ccl_addr_space RNG *rng, - const ccl_addr_space PathState *state, - uint scramble) +ccl_device_inline uint lcg_state_init(RNG *rng, int rng_offset, int sample, uint scramble) { - return lcg_init(*rng + state->rng_offset + state->sample*scramble); + return lcg_init(*rng + rng_offset + sample*scramble); } ccl_device float lcg_step_float_addrspace(ccl_addr_space uint *rng) diff --git a/intern/cycles/kernel/kernel_shader.h b/intern/cycles/kernel/kernel_shader.h index 93a92c63a40..163777b713e 100644 --- a/intern/cycles/kernel/kernel_shader.h +++ b/intern/cycles/kernel/kernel_shader.h @@ -516,7 +516,7 @@ ccl_device_inline void _shader_bsdf_multi_eval(KernelGlobals *kg, ShaderData *sd float3 eval = bsdf_eval(kg, sd, sc, omega_in, &bsdf_pdf); if(bsdf_pdf != 0.0f) { - bsdf_eval_accum(result_eval, sc->type, eval*sc->weight); + bsdf_eval_accum(result_eval, sc->type, eval*sc->weight, 1.0f); sum_pdf += bsdf_pdf*sc->sample_weight; } @@ -544,7 +544,8 @@ ccl_device_inline void _shader_bsdf_multi_eval_branched(KernelGlobals *kg, float mis_weight = use_mis? power_heuristic(light_pdf, bsdf_pdf): 1.0f; bsdf_eval_accum(result_eval, sc->type, - eval * sc->weight * mis_weight); + eval * sc->weight, + mis_weight); } } } @@ -576,7 +577,7 @@ void shader_bsdf_eval(KernelGlobals *kg, _shader_bsdf_multi_eval(kg, sd, omega_in, &pdf, -1, eval, 0.0f, 0.0f); if(use_mis) { float weight = power_heuristic(light_pdf, pdf); - bsdf_eval_mul(eval, weight); + bsdf_eval_mis(eval, weight); } } } @@ -862,7 +863,7 @@ ccl_device float3 shader_holdout_eval(KernelGlobals *kg, ShaderData *sd) /* Surface Evaluation */ -ccl_device void shader_eval_surface(KernelGlobals *kg, ShaderData *sd, ccl_addr_space RNG *rng, +ccl_device void shader_eval_surface(KernelGlobals *kg, ShaderData *sd, RNG *rng, ccl_addr_space PathState *state, float randb, int path_flag, ShaderContext ctx) { sd->num_closure = 0; @@ -887,7 +888,7 @@ ccl_device void shader_eval_surface(KernelGlobals *kg, ShaderData *sd, ccl_addr_ } if(rng && (sd->flag & SD_BSDF_NEEDS_LCG)) { - sd->lcg_state = lcg_state_init_addrspace(rng, state, 0xb4bc3953); + sd->lcg_state = lcg_state_init(rng, state->rng_offset, state->sample, 0xb4bc3953); } } @@ -944,7 +945,7 @@ ccl_device_inline void _shader_volume_phase_multi_eval(const ShaderData *sd, con float3 eval = volume_phase_eval(sd, sc, omega_in, &phase_pdf); if(phase_pdf != 0.0f) { - bsdf_eval_accum(result_eval, sc->type, eval); + bsdf_eval_accum(result_eval, sc->type, eval, 1.0f); sum_pdf += phase_pdf*sc->sample_weight; } diff --git a/intern/cycles/kernel/kernel_shadow.h b/intern/cycles/kernel/kernel_shadow.h index 4efc6c8118d..0426e0a62c9 100644 --- a/intern/cycles/kernel/kernel_shadow.h +++ b/intern/cycles/kernel/kernel_shadow.h @@ -128,6 +128,7 @@ ccl_device bool shadow_blocked_opaque(KernelGlobals *kg, ccl_device bool shadow_blocked_transparent_all_loop(KernelGlobals *kg, ShaderData *shadow_sd, ccl_addr_space PathState *state, + const int skip_object, Ray *ray, Intersection *hits, uint max_hits, @@ -140,6 +141,7 @@ ccl_device bool shadow_blocked_transparent_all_loop(KernelGlobals *kg, const bool blocked = scene_intersect_shadow_all(kg, ray, hits, + skip_object, max_hits, &num_hits); /* If no opaque surface found but we did find transparent hits, @@ -216,6 +218,7 @@ ccl_device bool shadow_blocked_transparent_all_loop(KernelGlobals *kg, ccl_device bool shadow_blocked_transparent_all(KernelGlobals *kg, ShaderData *shadow_sd, ccl_addr_space PathState *state, + const int skip_object, Ray *ray, uint max_hits, float3 *shadow) @@ -250,6 +253,7 @@ ccl_device bool shadow_blocked_transparent_all(KernelGlobals *kg, return shadow_blocked_transparent_all_loop(kg, shadow_sd, state, + skip_object, ray, hits, max_hits, @@ -274,13 +278,14 @@ ccl_device bool shadow_blocked_transparent_stepped_loop( KernelGlobals *kg, ShaderData *shadow_sd, ccl_addr_space PathState *state, + const int skip_object, Ray *ray, Intersection *isect, const bool blocked, const bool is_transparent_isect, float3 *shadow) { - if(blocked && is_transparent_isect) { + if((blocked && is_transparent_isect) || skip_object != OBJECT_NONE) { float3 throughput = make_float3(1.0f, 1.0f, 1.0f); float3 Pend = ray->P + ray->D*ray->t; int bounce = state->transparent_bounce; @@ -306,6 +311,23 @@ ccl_device bool shadow_blocked_transparent_stepped_loop( { break; } +#ifdef __SHADOW_TRICKS__ + if(skip_object != OBJECT_NONE) { + const int isect_object = (isect->object == PRIM_NONE) + ? kernel_tex_fetch(__prim_object, isect->prim) + : isect->object; + if(isect_object == skip_object) { + shader_setup_from_ray(kg, shadow_sd, isect, ray); + /* Move ray forward. */ + ray->P = ray_offset(shadow_sd->P, -shadow_sd->Ng); + if(ray->t != FLT_MAX) { + ray->D = normalize_len(Pend - ray->P, &ray->t); + } + bounce++; + continue; + } + } +#endif if(!shader_transparent_shadow(kg, isect)) { return true; } @@ -351,22 +373,31 @@ ccl_device bool shadow_blocked_transparent_stepped( KernelGlobals *kg, ShaderData *shadow_sd, ccl_addr_space PathState *state, + const int skip_object, Ray *ray, Intersection *isect, float3 *shadow) { - const bool blocked = scene_intersect(kg, - *ray, - PATH_RAY_SHADOW_OPAQUE, - isect, - NULL, - 0.0f, 0.0f); - const bool is_transparent_isect = blocked - ? shader_transparent_shadow(kg, isect) - : false; + bool blocked, is_transparent_isect; + if (skip_object == OBJECT_NONE) { + blocked = scene_intersect(kg, + *ray, + PATH_RAY_SHADOW_OPAQUE, + isect, + NULL, + 0.0f, 0.0f); + is_transparent_isect = blocked + ? shader_transparent_shadow(kg, isect) + : false; + } + else { + blocked = false; + is_transparent_isect = false; + } return shadow_blocked_transparent_stepped_loop(kg, shadow_sd, state, + skip_object, ray, isect, blocked, @@ -390,12 +421,21 @@ ccl_device_inline bool shadow_blocked(KernelGlobals *kg, if(ray->t == 0.0f) { return false; } +#ifdef __SHADOW_TRICKS__ + const int skip_object = state->catcher_object; +#else + const int skip_object = OBJECT_NONE; +#endif /* Do actual shadow shading. */ /* First of all, we check if integrator requires transparent shadows. * if not, we use simplest and fastest ever way to calculate occlusion. + * + * NOTE: We can't do quick opaque test here if we are on shadow-catcher + * path because we don't want catcher object to be casting shadow here. */ #ifdef __TRANSPARENT_SHADOWS__ - if(!kernel_data.integrator.transparent_shadows) + if(!kernel_data.integrator.transparent_shadows && + skip_object == OBJECT_NONE) #endif { return shadow_blocked_opaque(kg, @@ -440,6 +480,7 @@ ccl_device_inline bool shadow_blocked(KernelGlobals *kg, return shadow_blocked_transparent_stepped_loop(kg, shadow_sd, state, + skip_object, ray, &isect, blocked, @@ -450,6 +491,7 @@ ccl_device_inline bool shadow_blocked(KernelGlobals *kg, return shadow_blocked_transparent_all(kg, shadow_sd, state, + skip_object, ray, max_hits, shadow); @@ -458,6 +500,7 @@ ccl_device_inline bool shadow_blocked(KernelGlobals *kg, return shadow_blocked_transparent_stepped(kg, shadow_sd, state, + skip_object, ray, &isect, shadow); diff --git a/intern/cycles/kernel/kernel_subsurface.h b/intern/cycles/kernel/kernel_subsurface.h index 64d240d779d..f75e9337bdb 100644 --- a/intern/cycles/kernel/kernel_subsurface.h +++ b/intern/cycles/kernel/kernel_subsurface.h @@ -223,7 +223,7 @@ ccl_device_inline int subsurface_scatter_multi_intersect( SubsurfaceIntersection *ss_isect, ShaderData *sd, ShaderClosure *sc, - uint *lcg_state, + RNG *lcg_state, float disk_u, float disk_v, bool all) diff --git a/intern/cycles/kernel/kernel_types.h b/intern/cycles/kernel/kernel_types.h index 245832ae163..1ae624e06c5 100644 --- a/intern/cycles/kernel/kernel_types.h +++ b/intern/cycles/kernel/kernel_types.h @@ -157,6 +157,7 @@ CCL_NAMESPACE_BEGIN #define __INTERSECTION_REFINE__ #define __CLAMP_SAMPLE__ #define __PATCH_EVAL__ +#define __SHADOW_TRICKS__ #ifdef __KERNEL_SHADING__ # define __SVM__ @@ -212,6 +213,9 @@ CCL_NAMESPACE_BEGIN #ifdef __NO_TRANSPARENT__ # undef __TRANSPARENT_SHADOWS__ #endif +#ifdef __NO_SHADOW_TRICKS__ +#undef __SHADOW_TRICKS__ +#endif /* Random Numbers */ @@ -316,6 +320,8 @@ enum PathRayFlag { PATH_RAY_MIS_SKIP = 4096, PATH_RAY_DIFFUSE_ANCESTOR = 8192, PATH_RAY_SINGLE_PASS_DONE = 16384, + PATH_RAY_SHADOW_CATCHER = 32768, + PATH_RAY_SHADOW_CATCHER_ONLY = 65536, }; /* Closure Label */ @@ -445,6 +451,20 @@ typedef ccl_addr_space struct PathRadiance { float4 shadow; float mist; #endif + +#ifdef __SHADOW_TRICKS__ + /* Total light reachable across the path, ignoring shadow blocked queries. */ + float3 path_total; + /* Total light reachable across the path with shadow blocked queries + * applied here. + * + * Dividing this figure by path_total will give estimate of shadow pass. + */ + float3 path_total_shaded; + + /* Color of the background on which shadow is alpha-overed. */ + float3 shadow_color; +#endif } PathRadiance; typedef struct BsdfEval { @@ -460,6 +480,9 @@ typedef struct BsdfEval { float3 subsurface; float3 scatter; #endif +#ifdef __SHADOW_TRICKS__ + float3 sum_no_mis; +#endif } BsdfEval; /* Shader Flag */ @@ -805,13 +828,16 @@ enum ShaderDataObjectFlag { SD_OBJECT_INTERSECTS_VOLUME = (1 << 5), /* Has position for motion vertices. */ SD_OBJECT_HAS_VERTEX_MOTION = (1 << 6), + /* object is used to catch shadows */ + SD_OBJECT_SHADOW_CATCHER = (1 << 7), SD_OBJECT_FLAGS = (SD_OBJECT_HOLDOUT_MASK | SD_OBJECT_MOTION | SD_OBJECT_TRANSFORM_APPLIED | SD_OBJECT_NEGATIVE_SCALE_APPLIED | SD_OBJECT_HAS_VOLUME | - SD_OBJECT_INTERSECTS_VOLUME) + SD_OBJECT_INTERSECTS_VOLUME | + SD_OBJECT_SHADOW_CATCHER) }; typedef ccl_addr_space struct ShaderData { @@ -930,6 +956,10 @@ typedef struct PathState { RNG rng_congruential; VolumeStack volume_stack[VOLUME_STACK_SIZE]; #endif + +#ifdef __SHADOW_TRICKS__ + int catcher_object; +#endif } PathState; /* Subsurface */ diff --git a/intern/cycles/kernel/kernel_volume.h b/intern/cycles/kernel/kernel_volume.h index dcab138dc84..9c0878249d4 100644 --- a/intern/cycles/kernel/kernel_volume.h +++ b/intern/cycles/kernel/kernel_volume.h @@ -360,7 +360,7 @@ ccl_device VolumeIntegrateResult kernel_volume_integrate_homogeneous( ShaderData *sd, PathRadiance *L, ccl_addr_space float3 *throughput, - ccl_addr_space RNG *rng, + RNG *rng, bool probalistic_scatter) { VolumeShaderCoefficients coeff; @@ -469,7 +469,7 @@ ccl_device VolumeIntegrateResult kernel_volume_integrate_heterogeneous_distance( ShaderData *sd, PathRadiance *L, ccl_addr_space float3 *throughput, - ccl_addr_space RNG *rng) + RNG *rng) { float3 tp = *throughput; const float tp_eps = 1e-6f; /* todo: this is likely not the right value */ @@ -610,7 +610,7 @@ ccl_device_noinline VolumeIntegrateResult kernel_volume_integrate( Ray *ray, PathRadiance *L, ccl_addr_space float3 *throughput, - ccl_addr_space RNG *rng, + RNG *rng, bool heterogeneous) { shader_setup_from_volume(kg, sd, ray); diff --git a/intern/cycles/kernel/split/kernel_buffer_update.h b/intern/cycles/kernel/split/kernel_buffer_update.h index f36899b884a..859c221d976 100644 --- a/intern/cycles/kernel/split/kernel_buffer_update.h +++ b/intern/cycles/kernel/split/kernel_buffer_update.h @@ -87,7 +87,7 @@ ccl_device void kernel_buffer_update(KernelGlobals *kg, ccl_global Ray *ray = &kernel_split_state.ray[ray_index]; ccl_global float3 *throughput = &kernel_split_state.throughput[ray_index]; ccl_global float *L_transparent = &kernel_split_state.L_transparent[ray_index]; - ccl_global uint *rng = &kernel_split_state.rng[ray_index]; + RNG rng = kernel_split_state.rng[ray_index]; ccl_global float *buffer = kernel_split_params.buffer; unsigned int work_index; @@ -111,7 +111,16 @@ ccl_device void kernel_buffer_update(KernelGlobals *kg, buffer += (kernel_split_params.offset + pixel_x + pixel_y*stride) * kernel_data.film.pass_stride; if(IS_STATE(ray_state, ray_index, RAY_UPDATE_BUFFER)) { - float3 L_sum = path_radiance_clamp_and_sum(kg, L); + float3 L_sum; +#ifdef __SHADOW_TRICKS__ + if(state->flag & PATH_RAY_SHADOW_CATCHER) { + L_sum = path_radiance_sum_shadowcatcher(kg, L, L_transparent); + } + else +#endif /* __SHADOW_TRICKS__ */ + { + L_sum = path_radiance_clamp_and_sum(kg, L); + } kernel_write_light_passes(kg, buffer, L, sample); #ifdef __KERNEL_DEBUG__ kernel_write_debug_passes(kg, buffer, state, debug_data, sample); @@ -120,7 +129,7 @@ ccl_device void kernel_buffer_update(KernelGlobals *kg, /* accumulate result in output buffer */ kernel_write_pass_float4(buffer, sample, L_rad); - path_rng_end(kg, rng_state, *rng); + path_rng_end(kg, rng_state, rng); ASSIGN_RAY_STATE(ray_state, ray_index, RAY_TO_REGENERATE); } @@ -146,7 +155,7 @@ ccl_device void kernel_buffer_update(KernelGlobals *kg, buffer += (kernel_split_params.offset + pixel_x + pixel_y*stride) * kernel_data.film.pass_stride; /* Initialize random numbers and ray. */ - kernel_path_trace_setup(kg, rng_state, sample, pixel_x, pixel_y, rng, ray); + kernel_path_trace_setup(kg, rng_state, sample, pixel_x, pixel_y, &rng, ray); if(ray->t != 0.0f) { /* Initialize throughput, L_transparent, Ray, PathState; @@ -155,7 +164,7 @@ ccl_device void kernel_buffer_update(KernelGlobals *kg, *throughput = make_float3(1.0f, 1.0f, 1.0f); *L_transparent = 0.0f; path_radiance_init(L, kernel_data.film.use_light_pass); - path_state_init(kg, &kernel_split_state.sd_DL_shadow[ray_index], state, rng, sample, ray); + path_state_init(kg, &kernel_split_state.sd_DL_shadow[ray_index], state, &rng, sample, ray); #ifdef __SUBSURFACE__ kernel_path_subsurface_init_indirect(&kernel_split_state.ss_rays[ray_index]); #endif @@ -170,12 +179,13 @@ ccl_device void kernel_buffer_update(KernelGlobals *kg, float4 L_rad = make_float4(0.0f, 0.0f, 0.0f, 0.0f); /* Accumulate result in output buffer. */ kernel_write_pass_float4(buffer, sample, L_rad); - path_rng_end(kg, rng_state, *rng); + path_rng_end(kg, rng_state, rng); ASSIGN_RAY_STATE(ray_state, ray_index, RAY_TO_REGENERATE); } } } + kernel_split_state.rng[ray_index] = rng; #ifndef __COMPUTE_DEVICE_GPU__ } diff --git a/intern/cycles/kernel/split/kernel_direct_lighting.h b/intern/cycles/kernel/split/kernel_direct_lighting.h index 3d062cf0e2b..bdbf7387b95 100644 --- a/intern/cycles/kernel/split/kernel_direct_lighting.h +++ b/intern/cycles/kernel/split/kernel_direct_lighting.h @@ -79,15 +79,32 @@ ccl_device void kernel_direct_lighting(KernelGlobals *kg, /* direct lighting */ #ifdef __EMISSION__ - if((kernel_data.integrator.use_direct_light && - (sd->flag & SD_BSDF_HAS_EVAL))) - { + RNG rng = kernel_split_state.rng[ray_index]; + bool flag = (kernel_data.integrator.use_direct_light && + (sd->flag & SD_BSDF_HAS_EVAL)); +# ifdef __SHADOW_TRICKS__ + if(flag && state->flag & PATH_RAY_SHADOW_CATCHER) { + flag = false; + ShaderData *emission_sd = &kernel_split_state.sd_DL_shadow[ray_index]; + float3 throughput = kernel_split_state.throughput[ray_index]; + PathRadiance *L = &kernel_split_state.path_radiance[ray_index]; + kernel_branched_path_surface_connect_light(kg, + &rng, + sd, + emission_sd, + state, + throughput, + 1.0f, + L, + 1); + } +# endif /* __SHADOW_TRICKS__ */ + if(flag) { /* Sample illumination from lights to find path contribution. */ - ccl_global RNG* rng = &kernel_split_state.rng[ray_index]; - float light_t = path_state_rng_1D(kg, rng, state, PRNG_LIGHT); + float light_t = path_state_rng_1D(kg, &rng, state, PRNG_LIGHT); float light_u, light_v; - path_state_rng_2D(kg, rng, state, PRNG_LIGHT_U, &light_u, &light_v); - float terminate = path_state_rng_light_termination(kg, rng, state); + path_state_rng_2D(kg, &rng, state, PRNG_LIGHT_U, &light_u, &light_v); + float terminate = path_state_rng_light_termination(kg, &rng, state); LightSample ls; if(light_sample(kg, @@ -98,9 +115,9 @@ ccl_device void kernel_direct_lighting(KernelGlobals *kg, &ls)) { Ray light_ray; -#ifdef __OBJECT_MOTION__ +# ifdef __OBJECT_MOTION__ light_ray.time = sd->time; -#endif +# endif BsdfEval L_light; bool is_lamp; @@ -117,6 +134,7 @@ ccl_device void kernel_direct_lighting(KernelGlobals *kg, } } } + kernel_split_state.rng[ray_index] = rng; #endif /* __EMISSION__ */ } diff --git a/intern/cycles/kernel/split/kernel_do_volume.h b/intern/cycles/kernel/split/kernel_do_volume.h index b1df45d6bb2..47d3c280831 100644 --- a/intern/cycles/kernel/split/kernel_do_volume.h +++ b/intern/cycles/kernel/split/kernel_do_volume.h @@ -50,7 +50,7 @@ ccl_device void kernel_do_volume(KernelGlobals *kg) ccl_global float3 *throughput = &kernel_split_state.throughput[ray_index]; ccl_global Ray *ray = &kernel_split_state.ray[ray_index]; - ccl_global RNG *rng = &kernel_split_state.rng[ray_index]; + RNG rng = kernel_split_state.rng[ray_index]; ccl_global Intersection *isect = &kernel_split_state.isect[ray_index]; ShaderData *sd = &kernel_split_state.sd[ray_index]; ShaderData *sd_input = &kernel_split_state.sd_DL_shadow[ray_index]; @@ -69,15 +69,15 @@ ccl_device void kernel_do_volume(KernelGlobals *kg) { /* integrate along volume segment with distance sampling */ VolumeIntegrateResult result = kernel_volume_integrate( - kg, state, sd, &volume_ray, L, throughput, rng, heterogeneous); + kg, state, sd, &volume_ray, L, throughput, &rng, heterogeneous); # ifdef __VOLUME_SCATTER__ if(result == VOLUME_PATH_SCATTERED) { /* direct lighting */ - kernel_path_volume_connect_light(kg, rng, sd, sd_input, *throughput, state, L); + kernel_path_volume_connect_light(kg, &rng, sd, sd_input, *throughput, state, L); /* indirect light bounce */ - if(kernel_path_volume_bounce(kg, rng, sd, throughput, state, L, ray)) + if(kernel_path_volume_bounce(kg, &rng, sd, throughput, state, L, ray)) ASSIGN_RAY_STATE(kernel_split_state.ray_state, ray_index, RAY_REGENERATED); else ASSIGN_RAY_STATE(kernel_split_state.ray_state, ray_index, RAY_UPDATE_BUFFER); @@ -85,6 +85,7 @@ ccl_device void kernel_do_volume(KernelGlobals *kg) # endif } } + kernel_split_state.rng[ray_index] = rng; } #endif diff --git a/intern/cycles/kernel/split/kernel_holdout_emission_blurring_pathtermination_ao.h b/intern/cycles/kernel/split/kernel_holdout_emission_blurring_pathtermination_ao.h index 1834a791b91..9fc853a84bf 100644 --- a/intern/cycles/kernel/split/kernel_holdout_emission_blurring_pathtermination_ao.h +++ b/intern/cycles/kernel/split/kernel_holdout_emission_blurring_pathtermination_ao.h @@ -98,7 +98,7 @@ ccl_device void kernel_holdout_emission_blurring_pathtermination_ao( unsigned int tile_y; unsigned int sample; - ccl_global RNG *rng = 0x0; + RNG rng = kernel_split_state.rng[ray_index]; ccl_global PathState *state = 0x0; float3 throughput; @@ -110,7 +110,6 @@ ccl_device void kernel_holdout_emission_blurring_pathtermination_ao( throughput = kernel_split_state.throughput[ray_index]; state = &kernel_split_state.path_state[ray_index]; - rng = &kernel_split_state.rng[ray_index]; work_index = kernel_split_state.work_array[ray_index]; sample = get_work_sample(kg, work_index, ray_index) + kernel_split_params.start_sample; @@ -121,6 +120,23 @@ ccl_device void kernel_holdout_emission_blurring_pathtermination_ao( buffer += (kernel_split_params.offset + pixel_x + pixel_y * stride) * kernel_data.film.pass_stride; +#ifdef __SHADOW_TRICKS__ + if((sd->object_flag & SD_OBJECT_SHADOW_CATCHER)) { + if (state->flag & PATH_RAY_CAMERA) { + state->flag |= (PATH_RAY_SHADOW_CATCHER | PATH_RAY_SHADOW_CATCHER_ONLY); + state->catcher_object = sd->object; + if(!kernel_data.background.transparent) { + PathRadiance *L = &kernel_split_state.path_radiance[ray_index]; + ccl_global Ray *ray = &kernel_split_state.ray[ray_index]; + L->shadow_color = indirect_background(kg, &kernel_split_state.sd_DL_shadow[ray_index], state, ray); + } + } + } + else { + state->flag &= ~PATH_RAY_SHADOW_CATCHER_ONLY; + } +#endif /* __SHADOW_TRICKS__ */ + /* holdout */ #ifdef __HOLDOUT__ if(((sd->flag & SD_HOLDOUT) || @@ -194,7 +210,7 @@ ccl_device void kernel_holdout_emission_blurring_pathtermination_ao( if(IS_STATE(ray_state, ray_index, RAY_ACTIVE)) { if(probability != 1.0f) { - float terminate = path_state_rng_1D_for_decision(kg, rng, state, PRNG_TERMINATE); + float terminate = path_state_rng_1D_for_decision(kg, &rng, state, PRNG_TERMINATE); if(terminate >= probability) { ASSIGN_RAY_STATE(ray_state, ray_index, RAY_UPDATE_BUFFER); enqueue_flag = 1; @@ -214,7 +230,7 @@ ccl_device void kernel_holdout_emission_blurring_pathtermination_ao( { /* todo: solve correlation */ float bsdf_u, bsdf_v; - path_state_rng_2D(kg, rng, state, PRNG_BSDF_U, &bsdf_u, &bsdf_v); + path_state_rng_2D(kg, &rng, state, PRNG_BSDF_U, &bsdf_u, &bsdf_v); float ao_factor = kernel_data.background.ao_factor; float3 ao_N; @@ -243,6 +259,8 @@ ccl_device void kernel_holdout_emission_blurring_pathtermination_ao( } } #endif /* __AO__ */ + kernel_split_state.rng[ray_index] = rng; + #ifndef __COMPUTE_DEVICE_GPU__ } diff --git a/intern/cycles/kernel/split/kernel_indirect_background.h b/intern/cycles/kernel/split/kernel_indirect_background.h index 100f5996f83..8192528622e 100644 --- a/intern/cycles/kernel/split/kernel_indirect_background.h +++ b/intern/cycles/kernel/split/kernel_indirect_background.h @@ -70,7 +70,7 @@ ccl_device void kernel_indirect_background(KernelGlobals *kg) #ifdef __BACKGROUND__ /* sample background shader */ float3 L_background = indirect_background(kg, &kernel_split_state.sd_DL_shadow[ray_index], state, ray); - path_radiance_accum_background(L, (*throughput), L_background, state->bounce); + path_radiance_accum_background(L, state, (*throughput), L_background); #endif ASSIGN_RAY_STATE(ray_state, ray_index, RAY_UPDATE_BUFFER); } diff --git a/intern/cycles/kernel/split/kernel_next_iteration_setup.h b/intern/cycles/kernel/split/kernel_next_iteration_setup.h index 056fb1d8c08..1bebc16e25b 100644 --- a/intern/cycles/kernel/split/kernel_next_iteration_setup.h +++ b/intern/cycles/kernel/split/kernel_next_iteration_setup.h @@ -117,6 +117,9 @@ ccl_device void kernel_next_iteration_setup(KernelGlobals *kg, shadow, state->bounce); } + else { + path_radiance_accum_total_ao(L, _throughput, kernel_split_state.ao_bsdf[ray_index]); + } REMOVE_RAY_FLAG(ray_state, ray_index, RAY_SHADOW_RAY_CAST_AO); } @@ -124,8 +127,8 @@ ccl_device void kernel_next_iteration_setup(KernelGlobals *kg, float3 shadow = kernel_split_state.light_ray[ray_index].P; // TODO(mai): investigate correctness here char update_path_radiance = (char)kernel_split_state.light_ray[ray_index].t; + BsdfEval L_light = kernel_split_state.bsdf_eval[ray_index]; if(update_path_radiance) { - BsdfEval L_light = kernel_split_state.bsdf_eval[ray_index]; path_radiance_accum_light(L, _throughput, &L_light, @@ -134,6 +137,9 @@ ccl_device void kernel_next_iteration_setup(KernelGlobals *kg, state->bounce, kernel_split_state.is_lamp[ray_index]); } + else { + path_radiance_accum_total_light(L, _throughput, &L_light); + } REMOVE_RAY_FLAG(ray_state, ray_index, RAY_SHADOW_RAY_CAST_DL); } } @@ -141,15 +147,16 @@ ccl_device void kernel_next_iteration_setup(KernelGlobals *kg, if(IS_STATE(ray_state, ray_index, RAY_ACTIVE)) { ccl_global float3 *throughput = &kernel_split_state.throughput[ray_index]; ccl_global Ray *ray = &kernel_split_state.ray[ray_index]; - ccl_global RNG *rng = &kernel_split_state.rng[ray_index]; + RNG rng = kernel_split_state.rng[ray_index]; state = &kernel_split_state.path_state[ray_index]; L = &kernel_split_state.path_radiance[ray_index]; /* Compute direct lighting and next bounce. */ - if(!kernel_path_surface_bounce(kg, rng, &kernel_split_state.sd[ray_index], throughput, state, L, ray)) { + if(!kernel_path_surface_bounce(kg, &rng, &kernel_split_state.sd[ray_index], throughput, state, L, ray)) { ASSIGN_RAY_STATE(ray_state, ray_index, RAY_UPDATE_BUFFER); enqueue_flag = 1; } + kernel_split_state.rng[ray_index] = rng; } #ifndef __COMPUTE_DEVICE_GPU__ diff --git a/intern/cycles/kernel/split/kernel_path_init.h b/intern/cycles/kernel/split/kernel_path_init.h index f879fca5009..a7ecde7c80d 100644 --- a/intern/cycles/kernel/split/kernel_path_init.h +++ b/intern/cycles/kernel/split/kernel_path_init.h @@ -60,12 +60,14 @@ ccl_device void kernel_path_init(KernelGlobals *kg) { ccl_global float *buffer = kernel_split_params.buffer; buffer += (kernel_split_params.offset + pixel_x + pixel_y * kernel_split_params.stride) * kernel_data.film.pass_stride; + RNG rng = kernel_split_state.rng[ray_index]; + /* Initialize random numbers and ray. */ kernel_path_trace_setup(kg, rng_state, my_sample, pixel_x, pixel_y, - &kernel_split_state.rng[ray_index], + &rng, &kernel_split_state.ray[ray_index]); if(kernel_split_state.ray[ray_index].t != 0.0f) { @@ -78,7 +80,7 @@ ccl_device void kernel_path_init(KernelGlobals *kg) { path_state_init(kg, &kernel_split_state.sd_DL_shadow[ray_index], &kernel_split_state.path_state[ray_index], - &kernel_split_state.rng[ray_index], + &rng, my_sample, &kernel_split_state.ray[ray_index]); #ifdef __SUBSURFACE__ @@ -97,6 +99,7 @@ ccl_device void kernel_path_init(KernelGlobals *kg) { path_rng_end(kg, rng_state, kernel_split_state.rng[ray_index]); ASSIGN_RAY_STATE(kernel_split_state.ray_state, ray_index, RAY_TO_REGENERATE); } + kernel_split_state.rng[ray_index] = rng; } CCL_NAMESPACE_END diff --git a/intern/cycles/kernel/split/kernel_scene_intersect.h b/intern/cycles/kernel/split/kernel_scene_intersect.h index 66f549f59b7..684760eedee 100644 --- a/intern/cycles/kernel/split/kernel_scene_intersect.h +++ b/intern/cycles/kernel/split/kernel_scene_intersect.h @@ -72,7 +72,7 @@ ccl_device void kernel_scene_intersect(KernelGlobals *kg) } extmax = kernel_data.curve.maximum_width; - lcg_state = lcg_state_init(&rng, &state, 0x51633e2d); + lcg_state = lcg_state_init(&rng, state.rng_offset, state.sample, 0x51633e2d); } if(state.bounce > kernel_data.integrator.ao_bounces) { diff --git a/intern/cycles/kernel/split/kernel_shader_eval.h b/intern/cycles/kernel/split/kernel_shader_eval.h index b739f86338c..0f1696e34a0 100644 --- a/intern/cycles/kernel/split/kernel_shader_eval.h +++ b/intern/cycles/kernel/split/kernel_shader_eval.h @@ -54,7 +54,7 @@ ccl_device void kernel_shader_eval(KernelGlobals *kg, /* Continue on with shader evaluation. */ if((ray_index != QUEUE_EMPTY_SLOT) && IS_STATE(kernel_split_state.ray_state, ray_index, RAY_ACTIVE)) { Intersection isect = kernel_split_state.isect[ray_index]; - ccl_global uint *rng = &kernel_split_state.rng[ray_index]; + RNG rng = kernel_split_state.rng[ray_index]; ccl_global PathState *state = &kernel_split_state.path_state[ray_index]; Ray ray = kernel_split_state.ray[ray_index]; @@ -62,8 +62,9 @@ ccl_device void kernel_shader_eval(KernelGlobals *kg, &kernel_split_state.sd[ray_index], &isect, &ray); - float rbsdf = path_state_rng_1D_for_decision(kg, rng, state, PRNG_BSDF); - shader_eval_surface(kg, &kernel_split_state.sd[ray_index], rng, state, rbsdf, state->flag, SHADER_CONTEXT_MAIN); + float rbsdf = path_state_rng_1D_for_decision(kg, &rng, state, PRNG_BSDF); + shader_eval_surface(kg, &kernel_split_state.sd[ray_index], &rng, state, rbsdf, state->flag, SHADER_CONTEXT_MAIN); + kernel_split_state.rng[ray_index] = rng; } } diff --git a/intern/cycles/kernel/split/kernel_subsurface_scatter.h b/intern/cycles/kernel/split/kernel_subsurface_scatter.h index 4eaa7f56332..0b4d50c70ee 100644 --- a/intern/cycles/kernel/split/kernel_subsurface_scatter.h +++ b/intern/cycles/kernel/split/kernel_subsurface_scatter.h @@ -55,7 +55,7 @@ ccl_device void kernel_subsurface_scatter(KernelGlobals *kg, ccl_global char *ray_state = kernel_split_state.ray_state; ccl_global PathState *state = &kernel_split_state.path_state[ray_index]; PathRadiance *L = &kernel_split_state.path_radiance[ray_index]; - ccl_global RNG *rng = &kernel_split_state.rng[ray_index]; + RNG rng = kernel_split_state.rng[ray_index]; ccl_global Ray *ray = &kernel_split_state.ray[ray_index]; ccl_global float3 *throughput = &kernel_split_state.throughput[ray_index]; ccl_global SubsurfaceIndirectRays *ss_indirect = &kernel_split_state.ss_rays[ray_index]; @@ -69,7 +69,7 @@ ccl_device void kernel_subsurface_scatter(KernelGlobals *kg, emission_sd, L, state, - rng, + &rng, ray, throughput, ss_indirect)) { @@ -77,6 +77,7 @@ ccl_device void kernel_subsurface_scatter(KernelGlobals *kg, enqueue_flag = 1; } } + kernel_split_state.rng[ray_index] = rng; } #ifndef __COMPUTE_DEVICE_GPU__ diff --git a/intern/cycles/kernel/svm/svm_voxel.h b/intern/cycles/kernel/svm/svm_voxel.h index a8b3604a8a7..9e826c8c23f 100644 --- a/intern/cycles/kernel/svm/svm_voxel.h +++ b/intern/cycles/kernel/svm/svm_voxel.h @@ -46,7 +46,7 @@ ccl_device void svm_node_tex_voxel(KernelGlobals *kg, # if defined(__KERNEL_CUDA__) # if __CUDA_ARCH__ >= 300 CUtexObject tex = kernel_tex_fetch(__bindless_mapping, id); - if(id < 2048) /* TODO(dingto): Make this a variable */ + if(id < TEX_START_HALF4_CUDA_KEPLER) r = kernel_tex_image_interp_3d_float4(tex, co.x, co.y, co.z); else { float f = kernel_tex_image_interp_3d_float(tex, co.x, co.y, co.z); diff --git a/intern/cycles/render/graph.cpp b/intern/cycles/render/graph.cpp index f6c83fb5c7e..0cfd08090c2 100644 --- a/intern/cycles/render/graph.cpp +++ b/intern/cycles/render/graph.cpp @@ -17,6 +17,7 @@ #include "attribute.h" #include "graph.h" #include "nodes.h" +#include "scene.h" #include "shader.h" #include "constant_fold.h" @@ -195,6 +196,7 @@ bool ShaderNode::equals(const ShaderNode& other) ShaderGraph::ShaderGraph() { finalized = false; + simplified = false; num_node_ids = 0; add(new OutputNode()); } @@ -207,6 +209,8 @@ ShaderGraph::~ShaderGraph() ShaderNode *ShaderGraph::add(ShaderNode *node) { assert(!finalized); + simplified = false; + node->id = num_node_ids++; nodes.push_back(node); return node; @@ -241,6 +245,7 @@ void ShaderGraph::connect(ShaderOutput *from, ShaderInput *to) { assert(!finalized); assert(from && to); + simplified = false; if(to->link) { fprintf(stderr, "Cycles shader graph connect: input already connected.\n"); @@ -273,6 +278,7 @@ void ShaderGraph::connect(ShaderOutput *from, ShaderInput *to) void ShaderGraph::disconnect(ShaderOutput *from) { assert(!finalized); + simplified = false; foreach(ShaderInput *sock, from->links) { sock->link = NULL; @@ -285,6 +291,7 @@ void ShaderGraph::disconnect(ShaderInput *to) { assert(!finalized); assert(to->link); + simplified = false; ShaderOutput *from = to->link; @@ -294,6 +301,8 @@ void ShaderGraph::disconnect(ShaderInput *to) void ShaderGraph::relink(ShaderNode *node, ShaderOutput *from, ShaderOutput *to) { + simplified = false; + /* Copy because disconnect modifies this list */ vector<ShaderInput*> outputs = from->links; @@ -310,9 +319,19 @@ void ShaderGraph::relink(ShaderNode *node, ShaderOutput *from, ShaderOutput *to) } } +void ShaderGraph::simplify(Scene *scene) +{ + if(!simplified) { + default_inputs(scene->shader_manager->use_osl()); + clean(scene); + refine_bump_nodes(); + + simplified = true; + } +} + void ShaderGraph::finalize(Scene *scene, bool do_bump, - bool do_osl, bool do_simplify, bool bump_in_object_space) { @@ -322,9 +341,7 @@ void ShaderGraph::finalize(Scene *scene, * modified afterwards. */ if(!finalized) { - default_inputs(do_osl); - clean(scene); - refine_bump_nodes(); + simplify(scene); if(do_bump) bump_from_displacement(bump_in_object_space); diff --git a/intern/cycles/render/graph.h b/intern/cycles/render/graph.h index 06524d3fa13..d22193d4e51 100644 --- a/intern/cycles/render/graph.h +++ b/intern/cycles/render/graph.h @@ -240,6 +240,7 @@ public: list<ShaderNode*> nodes; size_t num_node_ids; bool finalized; + bool simplified; ShaderGraph(); ~ShaderGraph(); @@ -255,9 +256,9 @@ public: void relink(ShaderNode *node, ShaderOutput *from, ShaderOutput *to); void remove_proxy_nodes(); + void simplify(Scene *scene); void finalize(Scene *scene, bool do_bump = false, - bool do_osl = false, bool do_simplify = false, bool bump_in_object_space = false); diff --git a/intern/cycles/render/object.cpp b/intern/cycles/render/object.cpp index 8342f376836..a3a8c6d68e4 100644 --- a/intern/cycles/render/object.cpp +++ b/intern/cycles/render/object.cpp @@ -49,6 +49,8 @@ NODE_DEFINE(Object) SOCKET_POINT(dupli_generated, "Dupli Generated", make_float3(0.0f, 0.0f, 0.0f)); SOCKET_POINT2(dupli_uv, "Dupli UV", make_float2(0.0f, 0.0f)); + SOCKET_BOOLEAN(is_shadow_catcher, "Shadow Catcher", false); + return type; } @@ -597,6 +599,12 @@ void ObjectManager::device_update_flags(Device *device, else { object_flag[object_index] &= ~SD_OBJECT_HAS_VOLUME; } + if(object->is_shadow_catcher) { + object_flag[object_index] |= SD_OBJECT_SHADOW_CATCHER; + } + else { + object_flag[object_index] &= ~SD_OBJECT_SHADOW_CATCHER; + } if(bounds_valid) { foreach(Object *volume_object, volume_objects) { diff --git a/intern/cycles/render/object.h b/intern/cycles/render/object.h index 3495849d149..dabe0f71662 100644 --- a/intern/cycles/render/object.h +++ b/intern/cycles/render/object.h @@ -53,6 +53,7 @@ public: bool use_motion; bool hide_on_missing_motion; bool use_holdout; + bool is_shadow_catcher; float3 dupli_generated; float2 dupli_uv; diff --git a/intern/cycles/render/osl.cpp b/intern/cycles/render/osl.cpp index 67b68e63cb2..68bd8d96bf9 100644 --- a/intern/cycles/render/osl.cpp +++ b/intern/cycles/render/osl.cpp @@ -1096,12 +1096,10 @@ void OSLCompiler::compile(Scene *scene, OSLGlobals *og, Shader *shader) /* finalize */ shader->graph->finalize(scene, false, - true, shader->has_integrator_dependency); if(shader->graph_bump) { shader->graph_bump->finalize(scene, true, - true, shader->has_integrator_dependency, shader->displacement_method == DISPLACE_BOTH); } diff --git a/intern/cycles/render/session.cpp b/intern/cycles/render/session.cpp index e7050f9ef37..bd664b35e19 100644 --- a/intern/cycles/render/session.cpp +++ b/intern/cycles/render/session.cpp @@ -637,6 +637,9 @@ DeviceRequestedFeatures Session::get_requested_device_features() requested_features.use_patch_evaluation = true; } #endif + if(object->is_shadow_catcher) { + requested_features.use_shadow_tricks = true; + } } BakeManager *bake_manager = scene->bake_manager; diff --git a/intern/cycles/render/svm.cpp b/intern/cycles/render/svm.cpp index 955b892f4c3..bbf14c24b56 100644 --- a/intern/cycles/render/svm.cpp +++ b/intern/cycles/render/svm.cpp @@ -813,7 +813,6 @@ void SVMCompiler::compile(Scene *scene, scoped_timer timer((summary != NULL)? &summary->time_finalize: NULL); shader->graph->finalize(scene, false, - false, shader->has_integrator_dependency); } @@ -821,7 +820,6 @@ void SVMCompiler::compile(Scene *scene, scoped_timer timer((summary != NULL)? &summary->time_finalize_bump: NULL); shader->graph_bump->finalize(scene, true, - false, shader->has_integrator_dependency, shader->displacement_method == DISPLACE_BOTH); } diff --git a/intern/cycles/util/util_math.h b/intern/cycles/util/util_math.h index 2af0e56325f..84a5c800357 100644 --- a/intern/cycles/util/util_math.h +++ b/intern/cycles/util/util_math.h @@ -774,6 +774,7 @@ template<size_t index_0, size_t index_1, size_t index_2, size_t index_3> __force return _mm_castsi128_ps(_mm_shuffle_epi32(_mm_castps_si128(b), _MM_SHUFFLE(index_3, index_2, index_1, index_0))); } +#if defined(__KERNEL_SSE3__) template<> __forceinline const float4 shuffle<0, 0, 2, 2>(const float4& b) { return _mm_moveldup_ps(b); @@ -783,6 +784,7 @@ template<> __forceinline const float4 shuffle<1, 1, 3, 3>(const float4& b) { return _mm_movehdup_ps(b); } +#endif template<> __forceinline const float4 shuffle<0, 1, 0, 1>(const float4& b) { diff --git a/intern/ghost/GHOST_C-api.h b/intern/ghost/GHOST_C-api.h index ff1922af4f3..6887063eae9 100644 --- a/intern/ghost/GHOST_C-api.h +++ b/intern/ghost/GHOST_C-api.h @@ -908,6 +908,11 @@ extern int GHOST_UseNativePixels(void); extern float GHOST_GetNativePixelSize(GHOST_WindowHandle windowhandle); /** + * Returns the suggested DPI for this window. + */ +extern GHOST_TUns16 GHOST_GetDPIHint(GHOST_WindowHandle windowhandle); + +/** * Enable IME attached to the given window, i.e. allows user-input * events to be dispatched to the IME. * \param windowhandle Window handle of the caller diff --git a/intern/ghost/GHOST_IWindow.h b/intern/ghost/GHOST_IWindow.h index 688ebecf557..4a4d6be5ced 100644 --- a/intern/ghost/GHOST_IWindow.h +++ b/intern/ghost/GHOST_IWindow.h @@ -332,6 +332,12 @@ public: virtual float getNativePixelSize(void) = 0; + /** + * Returns the recommended DPI for this window. + * \return The recommended DPI for this window. + */ + virtual GHOST_TUns16 getDPIHint() = 0; + #ifdef WITH_INPUT_IME /** * Enable IME attached to the given window, i.e. allows user-input diff --git a/intern/ghost/GHOST_Types.h b/intern/ghost/GHOST_Types.h index 9ee4599a4a6..02b5063e515 100644 --- a/intern/ghost/GHOST_Types.h +++ b/intern/ghost/GHOST_Types.h @@ -189,6 +189,7 @@ typedef enum { GHOST_kEventWindowUpdate, GHOST_kEventWindowSize, GHOST_kEventWindowMove, + GHOST_kEventWindowDPIHintChanged, GHOST_kEventDraggingEntered, GHOST_kEventDraggingUpdated, diff --git a/intern/ghost/intern/GHOST_C-api.cpp b/intern/ghost/intern/GHOST_C-api.cpp index 41bc735e1e2..ce653188760 100644 --- a/intern/ghost/intern/GHOST_C-api.cpp +++ b/intern/ghost/intern/GHOST_C-api.cpp @@ -914,6 +914,12 @@ float GHOST_GetNativePixelSize(GHOST_WindowHandle windowhandle) return 1.0f; } +GHOST_TUns16 GHOST_GetDPIHint(GHOST_WindowHandle windowhandle) +{ + GHOST_IWindow *window = (GHOST_IWindow *)windowhandle; + return window->getDPIHint(); +} + #ifdef WITH_INPUT_IME void GHOST_BeginIME(GHOST_WindowHandle windowhandle, diff --git a/intern/ghost/intern/GHOST_SystemWin32.cpp b/intern/ghost/intern/GHOST_SystemWin32.cpp index 7d55a973f91..240d7ccd2fe 100644 --- a/intern/ghost/intern/GHOST_SystemWin32.cpp +++ b/intern/ghost/intern/GHOST_SystemWin32.cpp @@ -111,6 +111,11 @@ #define VK_MEDIA_PLAY_PAUSE 0xB3 #endif // VK_MEDIA_PLAY_PAUSE +// Window message newer than Windows 7 +#ifndef WM_DPICHANGED +#define WM_DPICHANGED 0x02E0 +#endif // WM_DPICHANGED + /* Workaround for some laptop touchpads, some of which seems to * have driver issues which makes it so window function receives * the message, but PeekMessage doesn't pick those messages for @@ -152,6 +157,27 @@ static void initRawInput() #undef DEVICE_COUNT } +#ifndef DPI_ENUMS_DECLARED +typedef enum PROCESS_DPI_AWARENESS { + PROCESS_DPI_UNAWARE = 0, + PROCESS_SYSTEM_DPI_AWARE = 1, + PROCESS_PER_MONITOR_DPI_AWARE = 2 +} PROCESS_DPI_AWARENESS; + +typedef enum MONITOR_DPI_TYPE { + MDT_EFFECTIVE_DPI = 0, + MDT_ANGULAR_DPI = 1, + MDT_RAW_DPI = 2, + MDT_DEFAULT = MDT_EFFECTIVE_DPI +} MONITOR_DPI_TYPE; + +#define USER_DEFAULT_SCREEN_DPI 96 + +#define DPI_ENUMS_DECLARED +#endif +typedef HRESULT(API * GHOST_WIN32_SetProcessDpiAwareness)(PROCESS_DPI_AWARENESS); +typedef BOOL(API * GHOST_WIN32_EnableNonClientDpiScaling)(HWND); + GHOST_SystemWin32::GHOST_SystemWin32() : m_hasPerformanceCounter(false), m_freq(0), m_start(0) { @@ -161,6 +187,18 @@ GHOST_SystemWin32::GHOST_SystemWin32() m_consoleStatus = 1; + // Tell Windows we are per monitor DPI aware. This disables the default + // blurry scaling and enables WM_DPICHANGED to allow us to draw at proper DPI. + HMODULE m_shcore = ::LoadLibrary("Shcore.dll"); + if (m_shcore) { + GHOST_WIN32_SetProcessDpiAwareness fpSetProcessDpiAwareness = + (GHOST_WIN32_SetProcessDpiAwareness) ::GetProcAddress(m_shcore, "SetProcessDpiAwareness"); + + if (fpSetProcessDpiAwareness) { + fpSetProcessDpiAwareness(PROCESS_PER_MONITOR_DPI_AWARE); + } + } + // Check if current keyboard layout uses AltGr and save keylayout ID for // specialized handling if keys like VK_OEM_*. I.e. french keylayout // generates VK_OEM_8 for their exclamation key (key left of right shift) @@ -922,6 +960,20 @@ LRESULT WINAPI GHOST_SystemWin32::s_wndProc(HWND hwnd, UINT msg, WPARAM wParam, GHOST_ASSERT(system, "GHOST_SystemWin32::s_wndProc(): system not initialized"); if (hwnd) { + if(msg == WM_NCCREATE) { + // Tell Windows to automatically handle scaling of non-client areas + // such as the caption bar. EnableNonClientDpiScaling was introduced in Windows 10 + HMODULE m_user32 = ::LoadLibrary("User32.dll"); + if (m_user32) { + GHOST_WIN32_EnableNonClientDpiScaling fpEnableNonClientDpiScaling = + (GHOST_WIN32_EnableNonClientDpiScaling) ::GetProcAddress(m_user32, "EnableNonClientDpiScaling"); + + if (fpEnableNonClientDpiScaling) { + fpEnableNonClientDpiScaling(hwnd); + } + } + } + GHOST_WindowWin32 *window = (GHOST_WindowWin32 *)::GetWindowLongPtr(hwnd, GWLP_USERDATA); if (window) { switch (msg) { @@ -1294,6 +1346,32 @@ LRESULT WINAPI GHOST_SystemWin32::s_wndProc(HWND hwnd, UINT msg, WPARAM wParam, } break; + case WM_DPICHANGED: + /* The WM_DPICHANGED message is sent when the effective dots per inch (dpi) for a window has changed. + * The DPI is the scale factor for a window. There are multiple events that can cause the DPI to + * change such as when the window is moved to a monitor with a different DPI. + */ + { + WORD newYAxisDPI = HIWORD(wParam); + WORD newXAxisDPI = LOWORD(wParam); + // The suggested new size and position of the window. + RECT* const suggestedWindowRect = (RECT*)lParam; + + // Push DPI change event first + system->pushEvent(processWindowEvent(GHOST_kEventWindowDPIHintChanged, window)); + system->dispatchEvents(); + eventHandled = true; + + // Then move and resize window + SetWindowPos(hwnd, + NULL, + suggestedWindowRect->left, + suggestedWindowRect->top, + suggestedWindowRect->right - suggestedWindowRect->left, + suggestedWindowRect->bottom - suggestedWindowRect->top, + SWP_NOZORDER | SWP_NOACTIVATE); + } + break; //////////////////////////////////////////////////////////////////////// // Window events, ignored //////////////////////////////////////////////////////////////////////// diff --git a/intern/ghost/intern/GHOST_Window.h b/intern/ghost/intern/GHOST_Window.h index d778628ea37..2798bdf72f3 100644 --- a/intern/ghost/intern/GHOST_Window.h +++ b/intern/ghost/intern/GHOST_Window.h @@ -295,6 +295,15 @@ public: return 1.0f; } + /** + * Returns the recommended DPI for this window. + * \return The recommended DPI for this window. + */ + virtual inline GHOST_TUns16 getDPIHint() + { + return 96; + } + #ifdef WITH_INPUT_IME virtual void beginIME(GHOST_TInt32 x, GHOST_TInt32 y, diff --git a/intern/ghost/intern/GHOST_WindowSDL.cpp b/intern/ghost/intern/GHOST_WindowSDL.cpp index 1335c38d977..aeb6188daef 100644 --- a/intern/ghost/intern/GHOST_WindowSDL.cpp +++ b/intern/ghost/intern/GHOST_WindowSDL.cpp @@ -563,3 +563,19 @@ GHOST_WindowSDL::setWindowCursorVisibility(bool visible) SDL_ShowCursor(visible); return GHOST_kSuccess; } + +GHOST_TUns16 +GHOST_WindowSDL::getDPIHint() +{ + int displayIndex = SDL_GetWindowDisplayIndex(m_sdl_win); + if (displayIndex < 0) { + return 96; + } + + float ddpi; + if (SDL_GetDisplayDPI(displayIndex, &ddpi, NULL, NULL) != 0) { + return 96; + } + + return (int)ddpi; +} diff --git a/intern/ghost/intern/GHOST_WindowSDL.h b/intern/ghost/intern/GHOST_WindowSDL.h index 5f658e8ad01..96104ec28b4 100644 --- a/intern/ghost/intern/GHOST_WindowSDL.h +++ b/intern/ghost/intern/GHOST_WindowSDL.h @@ -168,6 +168,8 @@ protected: GHOST_TSuccess beginFullScreen() const { return GHOST_kFailure; } GHOST_TSuccess endFullScreen() const { return GHOST_kFailure; } + + GHOST_TUns16 getDPIHint(); }; diff --git a/intern/ghost/intern/GHOST_WindowWin32.cpp b/intern/ghost/intern/GHOST_WindowWin32.cpp index 58aa0b87045..2c82e3a3f71 100644 --- a/intern/ghost/intern/GHOST_WindowWin32.cpp +++ b/intern/ghost/intern/GHOST_WindowWin32.cpp @@ -92,6 +92,7 @@ GHOST_WindowWin32::GHOST_WindowWin32(GHOST_SystemWin32 *system, m_tablet(0), m_maxPressure(0), m_normal_state(GHOST_kWindowStateNormal), + m_user32(NULL), m_parentWindowHwnd(parentwindowhwnd), m_debug_context(is_debug) { @@ -905,6 +906,23 @@ void GHOST_WindowWin32::bringTabletContextToFront() } } +GHOST_TUns16 GHOST_WindowWin32::getDPIHint() +{ + if (!m_user32) { + m_user32 = ::LoadLibrary("user32.dll"); + } + + if (m_user32) { + GHOST_WIN32_GetDpiForWindow fpGetDpiForWindow = (GHOST_WIN32_GetDpiForWindow) ::GetProcAddress(m_user32, "GetDpiForWindow"); + + if (fpGetDpiForWindow) { + return fpGetDpiForWindow(this->m_hWnd); + } + } + + return USER_DEFAULT_SCREEN_DPI; +} + /** Reverse the bits in a GHOST_TUns8 */ static GHOST_TUns8 uns8ReverseBits(GHOST_TUns8 ch) { diff --git a/intern/ghost/intern/GHOST_WindowWin32.h b/intern/ghost/intern/GHOST_WindowWin32.h index a1cf58c9ceb..75a33951ff4 100644 --- a/intern/ghost/intern/GHOST_WindowWin32.h +++ b/intern/ghost/intern/GHOST_WindowWin32.h @@ -58,6 +58,12 @@ typedef BOOL (API * GHOST_WIN32_WTClose)(HCTX); typedef BOOL (API * GHOST_WIN32_WTPacket)(HCTX, UINT, LPVOID); typedef BOOL (API * GHOST_WIN32_WTOverlap)(HCTX, BOOL); +// typedefs for user32 functions to allow dynamic loading of Windows 10 DPI scaling functions +typedef UINT(API * GHOST_WIN32_GetDpiForWindow)(HWND); +#ifndef USER_DEFAULT_SCREEN_DPI +#define USER_DEFAULT_SCREEN_DPI 96 +#endif // USER_DEFAULT_SCREEN_DPI + /** * GHOST window on M$ Windows OSs. * \author Maarten Gribnau @@ -251,6 +257,8 @@ public: GHOST_TSuccess endFullScreen() const {return GHOST_kFailure;} + GHOST_TUns16 getDPIHint() override; + /** if the window currently resizing */ bool m_inLiveResize; @@ -351,6 +359,9 @@ private: GHOST_TWindowState m_normal_state; + /** user32 dll handle*/ + HMODULE m_user32; + /** Hwnd to parent window */ GHOST_TEmbedderWindowID m_parentWindowHwnd; diff --git a/intern/ghost/intern/GHOST_WindowX11.cpp b/intern/ghost/intern/GHOST_WindowX11.cpp index 8cee785cdf6..f39f4f52289 100644 --- a/intern/ghost/intern/GHOST_WindowX11.cpp +++ b/intern/ghost/intern/GHOST_WindowX11.cpp @@ -56,6 +56,9 @@ # include <X11/extensions/XInput2.h> #endif +//For DPI value +#include <X11/Xresource.h> + #if defined(__sun__) || defined(__sun) || defined(__sparc) || defined(__sparc__) || defined(_AIX) # include <strings.h> #endif @@ -68,6 +71,7 @@ #include <algorithm> #include <string> +#include <math.h> /* For obscure full screen mode stuff * lifted verbatim from blut. */ @@ -1661,3 +1665,44 @@ endFullScreen() const return GHOST_kSuccess; } + +GHOST_TUns16 +GHOST_WindowX11:: +getDPIHint() +{ + /* Try to read DPI setting set using xrdb */ + char* resMan = XResourceManagerString(m_display); + if (resMan) { + XrmDatabase xrdb = XrmGetStringDatabase(resMan); + if (xrdb) { + char* type = NULL; + XrmValue val; + + int success = XrmGetResource(xrdb, "Xft.dpi", "Xft.Dpi", &type, &val); + if (success && type) { + if (strcmp(type, "String") == 0) { + return atoi((char*)val.addr); + } + } + } + } + + /* Fallback to calculating DPI using X reported DPI, set using xrandr --dpi */ + XWindowAttributes attr; + if (!XGetWindowAttributes(m_display, m_window, &attr)) { + /* Failed to get window attributes, return X11 default DPI */ + return 96; + } + + Screen* screen = attr.screen; + int pixelWidth = WidthOfScreen(screen); + int pixelHeight = HeightOfScreen(screen); + int mmWidth = WidthMMOfScreen(screen); + int mmHeight = HeightMMOfScreen(screen); + + double pixelDiagonal = sqrt((pixelWidth * pixelWidth) + (pixelHeight * pixelHeight)); + double mmDiagonal = sqrt((mmWidth * mmWidth) + (mmHeight * mmHeight)); + float inchDiagonal = mmDiagonal * 0.039f; + int dpi = pixelDiagonal / inchDiagonal; + return dpi; +} diff --git a/intern/ghost/intern/GHOST_WindowX11.h b/intern/ghost/intern/GHOST_WindowX11.h index 9380aa9d631..5c54c1e8162 100644 --- a/intern/ghost/intern/GHOST_WindowX11.h +++ b/intern/ghost/intern/GHOST_WindowX11.h @@ -235,6 +235,8 @@ public: GHOST_TSuccess endFullScreen() const; + GHOST_TUns16 getDPIHint(); + protected: /** * \param type The type of rendering context create. diff --git a/release/scripts/modules/bl_app_override/__init__.py b/release/scripts/modules/bl_app_override/__init__.py index efd7c525e62..66857701669 100644 --- a/release/scripts/modules/bl_app_override/__init__.py +++ b/release/scripts/modules/bl_app_override/__init__.py @@ -47,7 +47,7 @@ def ui_draw_filter_register( ui_ignore_operator=None, ui_ignore_property=None, ui_ignore_menu=None, - ui_ignore_label=None, + ui_ignore_label=None ): import bpy diff --git a/release/scripts/modules/bpy/utils/__init__.py b/release/scripts/modules/bpy/utils/__init__.py index 65a2f278465..1d555ae7123 100644 --- a/release/scripts/modules/bpy/utils/__init__.py +++ b/release/scripts/modules/bpy/utils/__init__.py @@ -50,18 +50,18 @@ __all__ = ( "unregister_class", "unregister_module", "user_resource", - ) +) from _bpy import ( - _utils_units as units, - blend_paths, - escape_identifier, - register_class, - resource_path, - script_paths as _bpy_script_paths, - unregister_class, - user_resource as _user_resource, - ) + _utils_units as units, + blend_paths, + escape_identifier, + register_class, + resource_path, + script_paths as _bpy_script_paths, + unregister_class, + user_resource as _user_resource, +) import bpy as _bpy import os as _os @@ -143,7 +143,7 @@ def load_scripts(reload_scripts=False, refresh_scripts=False): as modules. :type refresh_scripts: bool """ - use_time = _bpy.app.debug_python + use_time = use_class_register_check = _bpy.app.debug_python if use_time: import time @@ -162,7 +162,8 @@ def load_scripts(reload_scripts=False, refresh_scripts=False): for module_name in [ext.module for ext in _user_preferences.addons]: _addon_utils.disable(module_name) - # *AFTER* unregistering all add-ons, otherwise all calls to unregister_module() will silently fail (do nothing). + # *AFTER* unregistering all add-ons, otherwise all calls to + # unregister_module() will silently fail (do nothing). _bpy_types.TypeMap.clear() def register_module_call(mod): @@ -276,13 +277,21 @@ def load_scripts(reload_scripts=False, refresh_scripts=False): if use_time: print("Python Script Load Time %.4f" % (time.time() - t_main)) + if use_class_register_check: + for cls in _bpy.types.bpy_struct.__subclasses__(): + if getattr(cls, "is_registered", False): + for subcls in cls.__subclasses__(): + if not subcls.is_registered: + print( + "Warning, unregistered class: %s(%s)" % + (subcls.__name__, cls.__name__) + ) + # base scripts -_scripts = _os.path.join(_os.path.dirname(__file__), - _os.path.pardir, - _os.path.pardir, - ) -_scripts = (_os.path.normpath(_scripts), ) +_scripts = ( + _os.path.dirname(_os.path.dirname(_os.path.dirname(__file__))), +) def script_path_user(): diff --git a/release/scripts/startup/bl_operators/wm.py b/release/scripts/startup/bl_operators/wm.py index 7827e7ab5e2..17ec778a275 100644 --- a/release/scripts/startup/bl_operators/wm.py +++ b/release/scripts/startup/bl_operators/wm.py @@ -2240,13 +2240,8 @@ class WM_OT_app_template_install(Operator): default=True, options={'HIDDEN'}, ) - filter_python = BoolProperty( - name="Filter python", - default=True, - options={'HIDDEN'}, - ) filter_glob = StringProperty( - default="*.py;*.zip", + default="*.zip", options={'HIDDEN'}, ) @@ -2256,7 +2251,7 @@ class WM_OT_app_template_install(Operator): import shutil import os - pyfile = self.filepath + filepath = self.filepath path_app_templates = bpy.utils.user_resource( 'SCRIPTS', os.path.join("startup", "bl_app_templates_user"), @@ -2276,9 +2271,9 @@ class WM_OT_app_template_install(Operator): app_templates_old = set(os.listdir(path_app_templates)) # check to see if the file is in compressed format (.zip) - if zipfile.is_zipfile(pyfile): + if zipfile.is_zipfile(filepath): try: - file_to_extract = zipfile.ZipFile(pyfile, 'r') + file_to_extract = zipfile.ZipFile(filepath, 'r') except: traceback.print_exc() return {'CANCELLED'} @@ -2300,20 +2295,9 @@ class WM_OT_app_template_install(Operator): return {'CANCELLED'} else: - path_dest = os.path.join(path_app_templates, os.path.basename(pyfile)) - - if self.overwrite: - module_filesystem_remove(path_app_templates, os.path.basename(pyfile)) - elif os.path.exists(path_dest): - self.report({'WARNING'}, "File already installed to %r\n" % path_dest) - return {'CANCELLED'} - - # if not compressed file just copy into the addon path - try: - shutil.copyfile(pyfile, path_dest) - except: - traceback.print_exc() - return {'CANCELLED'} + # Only support installing zipfiles + self.report({'WARNING'}, "Expected a zip-file %r\n" % filepath) + return {'CANCELLED'} app_templates_new = set(os.listdir(path_app_templates)) - app_templates_old @@ -2323,7 +2307,7 @@ class WM_OT_app_template_install(Operator): # print message msg = ( tip_("Template Installed (%s) from %r into %r") % - (", ".join(sorted(app_templates_new)), pyfile, path_app_templates) + (", ".join(sorted(app_templates_new)), filepath, path_app_templates) ) print(msg) self.report({'INFO'}, msg) diff --git a/release/scripts/startup/bl_ui/space_userpref.py b/release/scripts/startup/bl_ui/space_userpref.py index f4e2cf006b2..e50beba50d8 100644 --- a/release/scripts/startup/bl_ui/space_userpref.py +++ b/release/scripts/startup/bl_ui/space_userpref.py @@ -217,6 +217,7 @@ class USERPREF_PT_interface(Panel): col = row.column() col.label(text="Display:") + col.prop(view, "ui_scale", text="Scale") col.prop(view, "show_tooltips") col.prop(view, "show_tooltips_python") col.prop(view, "show_object_info", text="Object Info") @@ -467,11 +468,6 @@ class USERPREF_PT_system(Panel): col = colsplit.column() col.label(text="General:") - col.prop(system, "dpi") - col.label("Virtual Pixel Mode:") - col.prop(system, "virtual_pixel_mode", text="") - - col.separator() col.prop(system, "frame_server_port") col.prop(system, "scrollback", text="Console Scrollback") diff --git a/release/scripts/startup/bl_ui/space_view3d.py b/release/scripts/startup/bl_ui/space_view3d.py index 03c660807a9..1ede823e6d8 100644 --- a/release/scripts/startup/bl_ui/space_view3d.py +++ b/release/scripts/startup/bl_ui/space_view3d.py @@ -3870,6 +3870,7 @@ classes = ( INFO_MT_edit_armature_add, INFO_MT_armature_add, INFO_MT_lamp_add, + INFO_MT_camera_add, INFO_MT_add, VIEW3D_MT_object, VIEW3D_MT_object_animation, diff --git a/source/blender/blenkernel/intern/customdata.c b/source/blender/blenkernel/intern/customdata.c index d9269eb99df..7c3f0ac630d 100644 --- a/source/blender/blenkernel/intern/customdata.c +++ b/source/blender/blenkernel/intern/customdata.c @@ -44,6 +44,7 @@ #include "BLI_path_util.h" #include "BLI_string.h" #include "BLI_string_utils.h" +#include "BLI_math.h" #include "BLI_math_color_blend.h" #include "BLI_mempool.h" @@ -57,10 +58,11 @@ #include "BKE_mesh_remap.h" #include "BKE_multires.h" -#include "data_transfer_intern.h" - #include "bmesh.h" +/* only for customdata_data_transfer_interp_normal_normals */ +#include "data_transfer_intern.h" + /* number of layers to add when growing a CustomData object */ #define CUSTOMDATA_GROW 5 diff --git a/source/blender/blenloader/CMakeLists.txt b/source/blender/blenloader/CMakeLists.txt index e40692f4a88..d77c7388929 100644 --- a/source/blender/blenloader/CMakeLists.txt +++ b/source/blender/blenloader/CMakeLists.txt @@ -70,6 +70,12 @@ if(WITH_BUILDINFO) add_definitions(-DWITH_BUILDINFO) endif() +if(WITH_PYTHON) + if(WITH_PYTHON_SECURITY) + add_definitions(-DWITH_PYTHON_SECURITY) + endif() +endif() + if(WITH_INTERNATIONAL) add_definitions(-DWITH_INTERNATIONAL) endif() diff --git a/source/blender/blenloader/intern/readfile.c b/source/blender/blenloader/intern/readfile.c index efa3e09329f..81d72dce3a4 100644 --- a/source/blender/blenloader/intern/readfile.c +++ b/source/blender/blenloader/intern/readfile.c @@ -2194,19 +2194,19 @@ static void direct_link_curvemapping(FileData *fd, CurveMapping *cumap) /* library brush linking after fileread */ static void lib_link_brush(FileData *fd, Main *main) { - Brush *brush; - /* only link ID pointers */ - for (brush = main->brush.first; brush; brush = brush->id.next) { + for (Brush *brush = main->brush.first; brush; brush = brush->id.next) { if (brush->id.tag & LIB_TAG_NEED_LINK) { - brush->id.tag &= ~LIB_TAG_NEED_LINK; - + IDP_LibLinkProperty(brush->id.properties, (fd->flags & FD_FLAGS_SWITCH_ENDIAN), fd); + /* brush->(mask_)mtex.obj is ignored on purpose? */ brush->mtex.tex = newlibadr_us(fd, brush->id.lib, brush->mtex.tex); brush->mask_mtex.tex = newlibadr_us(fd, brush->id.lib, brush->mask_mtex.tex); brush->clone.image = newlibadr(fd, brush->id.lib, brush->clone.image); brush->toggle_brush = newlibadr(fd, brush->id.lib, brush->toggle_brush); brush->paint_curve = newlibadr_us(fd, brush->id.lib, brush->paint_curve); + + brush->id.tag &= ~LIB_TAG_NEED_LINK; } } } @@ -2229,13 +2229,13 @@ static void direct_link_brush(FileData *fd, Brush *brush) } /* ************ READ Palette *************** */ -static void lib_link_palette(FileData *UNUSED(fd), Main *main) +static void lib_link_palette(FileData *fd, Main *main) { - Palette *palette; - /* only link ID pointers */ - for (palette = main->palettes.first; palette; palette = palette->id.next) { + for (Palette *palette = main->palettes.first; palette; palette = palette->id.next) { if (palette->id.tag & LIB_TAG_NEED_LINK) { + IDP_LibLinkProperty(palette->id.properties, (fd->flags & FD_FLAGS_SWITCH_ENDIAN), fd); + palette->id.tag &= ~LIB_TAG_NEED_LINK; } } @@ -2247,13 +2247,13 @@ static void direct_link_palette(FileData *fd, Palette *palette) link_list(fd, &palette->colors); } -static void lib_link_paint_curve(FileData *UNUSED(fd), Main *main) +static void lib_link_paint_curve(FileData *fd, Main *main) { - PaintCurve *pc; - /* only link ID pointers */ - for (pc = main->paintcurves.first; pc; pc = pc->id.next) { + for (PaintCurve *pc = main->paintcurves.first; pc; pc = pc->id.next) { if (pc->id.tag & LIB_TAG_NEED_LINK) { + IDP_LibLinkProperty(pc->id.properties, (fd->flags & FD_FLAGS_SWITCH_ENDIAN), fd); + pc->id.tag &= ~LIB_TAG_NEED_LINK; } } @@ -2505,15 +2505,12 @@ static void direct_link_fcurves(FileData *fd, ListBase *list) static void lib_link_action(FileData *fd, Main *main) { - bAction *act; - bActionChannel *chan; - - for (act = main->action.first; act; act = act->id.next) { + for (bAction *act = main->action.first; act; act = act->id.next) { if (act->id.tag & LIB_TAG_NEED_LINK) { - act->id.tag &= ~LIB_TAG_NEED_LINK; + IDP_LibLinkProperty(act->id.properties, (fd->flags & FD_FLAGS_SWITCH_ENDIAN), fd); // XXX deprecated - old animation system <<< - for (chan=act->chanbase.first; chan; chan=chan->next) { + for (bActionChannel *chan = act->chanbase.first; chan; chan = chan->next) { chan->ipo = newlibadr_us(fd, act->id.lib, chan->ipo); lib_link_constraint_channels(fd, &act->id, &chan->constraintChannels); } @@ -2526,6 +2523,8 @@ static void lib_link_action(FileData *fd, Main *main) marker->camera = newlibadr(fd, act->id.lib, marker->camera); } } + + act->id.tag &= ~LIB_TAG_NEED_LINK; } } } @@ -2712,26 +2711,20 @@ static void direct_link_animdata(FileData *fd, AnimData *adt) static void lib_link_cachefiles(FileData *fd, Main *bmain) { - CacheFile *cache_file; - /* only link ID pointers */ - for (cache_file = bmain->cachefiles.first; cache_file; cache_file = cache_file->id.next) { + for (CacheFile *cache_file = bmain->cachefiles.first; cache_file; cache_file = cache_file->id.next) { if (cache_file->id.tag & LIB_TAG_NEED_LINK) { - cache_file->id.tag &= ~LIB_TAG_NEED_LINK; - } - - BLI_listbase_clear(&cache_file->object_paths); - cache_file->handle = NULL; - cache_file->handle_mutex = NULL; - - if (cache_file->adt) { + IDP_LibLinkProperty(cache_file->id.properties, (fd->flags & FD_FLAGS_SWITCH_ENDIAN), fd); lib_link_animdata(fd, &cache_file->id, cache_file->adt); + + cache_file->id.tag &= ~LIB_TAG_NEED_LINK; } } } static void direct_link_cachefile(FileData *fd, CacheFile *cache_file) { + BLI_listbase_clear(&cache_file->object_paths); cache_file->handle = NULL; cache_file->handle_mutex = NULL; @@ -2768,6 +2761,7 @@ static void lib_link_ntree(FileData *fd, ID *id, bNodeTree *ntree) bNode *node; bNodeSocket *sock; + IDP_LibLinkProperty(ntree->id.properties, (fd->flags & FD_FLAGS_SWITCH_ENDIAN), fd); lib_link_animdata(fd, &ntree->id, ntree->adt); ntree->gpd = newlibadr_us(fd, id->lib, ntree->gpd); @@ -2785,22 +2779,25 @@ static void lib_link_ntree(FileData *fd, ID *id, bNodeTree *ntree) lib_link_node_socket(fd, id, sock); } - for (sock = ntree->inputs.first; sock; sock = sock->next) + for (sock = ntree->inputs.first; sock; sock = sock->next) { + IDP_LibLinkProperty(sock->prop, (fd->flags & FD_FLAGS_SWITCH_ENDIAN), fd); lib_link_node_socket(fd, id, sock); - for (sock = ntree->outputs.first; sock; sock = sock->next) + } + for (sock = ntree->outputs.first; sock; sock = sock->next) { + IDP_LibLinkProperty(sock->prop, (fd->flags & FD_FLAGS_SWITCH_ENDIAN), fd); lib_link_node_socket(fd, id, sock); + } } /* library ntree linking after fileread */ static void lib_link_nodetree(FileData *fd, Main *main) { - bNodeTree *ntree; - /* only link ID pointers */ - for (ntree = main->nodetree.first; ntree; ntree = ntree->id.next) { + for (bNodeTree *ntree = main->nodetree.first; ntree; ntree = ntree->id.next) { if (ntree->id.tag & LIB_TAG_NEED_LINK) { - ntree->id.tag &= ~LIB_TAG_NEED_LINK; lib_link_ntree(fd, &ntree->id, ntree); + + ntree->id.tag &= ~LIB_TAG_NEED_LINK; } } } @@ -3315,11 +3312,11 @@ static void lib_link_pose(FileData *fd, Main *bmain, Object *ob, bPose *pose) static void lib_link_armature(FileData *fd, Main *main) { - bArmature *arm; - - for (arm = main->armature.first; arm; arm = arm->id.next) { + for (bArmature *arm = main->armature.first; arm; arm = arm->id.next) { if (arm->id.tag & LIB_TAG_NEED_LINK) { + IDP_LibLinkProperty(arm->id.properties, (fd->flags & FD_FLAGS_SWITCH_ENDIAN), fd); lib_link_animdata(fd, &arm->id, arm->adt); + arm->id.tag &= ~LIB_TAG_NEED_LINK; } } @@ -3364,14 +3361,13 @@ static void direct_link_armature(FileData *fd, bArmature *arm) static void lib_link_camera(FileData *fd, Main *main) { - Camera *ca; - - for (ca = main->camera.first; ca; ca = ca->id.next) { + for (Camera *ca = main->camera.first; ca; ca = ca->id.next) { if (ca->id.tag & LIB_TAG_NEED_LINK) { + IDP_LibLinkProperty(ca->id.properties, (fd->flags & FD_FLAGS_SWITCH_ENDIAN), fd); lib_link_animdata(fd, &ca->id, ca->adt); ca->ipo = newlibadr_us(fd, ca->id.lib, ca->ipo); // XXX deprecated - old animation system - + ca->dof_ob = newlibadr(fd, ca->id.lib, ca->dof_ob); ca->id.tag &= ~LIB_TAG_NEED_LINK; @@ -3390,16 +3386,13 @@ static void direct_link_camera(FileData *fd, Camera *ca) static void lib_link_lamp(FileData *fd, Main *main) { - Lamp *la; - MTex *mtex; - int a; - - for (la = main->lamp.first; la; la = la->id.next) { + for (Lamp *la = main->lamp.first; la; la = la->id.next) { if (la->id.tag & LIB_TAG_NEED_LINK) { + IDP_LibLinkProperty(la->id.properties, (fd->flags & FD_FLAGS_SWITCH_ENDIAN), fd); lib_link_animdata(fd, &la->id, la->adt); - for (a = 0; a < MAX_MTEX; a++) { - mtex = la->mtex[a]; + for (int a = 0; a < MAX_MTEX; a++) { + MTex *mtex = la->mtex[a]; if (mtex) { mtex->tex = newlibadr_us(fd, la->id.lib, mtex->tex); mtex->object = newlibadr(fd, la->id.lib, mtex->object); @@ -3456,17 +3449,11 @@ void blo_do_versions_key_uidgen(Key *key) static void lib_link_key(FileData *fd, Main *main) { - Key *key; - - for (key = main->key.first; key; key = key->id.next) { - /*check if we need to generate unique ids for the shapekeys*/ - if (!key->uidgen) { - blo_do_versions_key_uidgen(key); - } - + for (Key *key = main->key.first; key; key = key->id.next) { BLI_assert((key->id.tag & LIB_TAG_EXTERN) == 0); if (key->id.tag & LIB_TAG_NEED_LINK) { + IDP_LibLinkProperty(key->id.properties, (fd->flags & FD_FLAGS_SWITCH_ENDIAN), fd); lib_link_animdata(fd, &key->id, key->adt); key->ipo = newlibadr_us(fd, key->id.lib, key->ipo); // XXX deprecated - old animation system @@ -3529,15 +3516,14 @@ static void direct_link_key(FileData *fd, Key *key) static void lib_link_mball(FileData *fd, Main *main) { - MetaBall *mb; - int a; - - for (mb = main->mball.first; mb; mb = mb->id.next) { + for (MetaBall *mb = main->mball.first; mb; mb = mb->id.next) { if (mb->id.tag & LIB_TAG_NEED_LINK) { + IDP_LibLinkProperty(mb->id.properties, (fd->flags & FD_FLAGS_SWITCH_ENDIAN), fd); lib_link_animdata(fd, &mb->id, mb->adt); - for (a = 0; a < mb->totcol; a++) + for (int a = 0; a < mb->totcol; a++) { mb->mat[a] = newlibadr_us(fd, mb->id.lib, mb->mat[a]); + } mb->ipo = newlibadr_us(fd, mb->id.lib, mb->ipo); // XXX deprecated - old animation system @@ -3566,18 +3552,15 @@ static void direct_link_mball(FileData *fd, MetaBall *mb) static void lib_link_world(FileData *fd, Main *main) { - World *wrld; - MTex *mtex; - int a; - - for (wrld = main->world.first; wrld; wrld = wrld->id.next) { + for (World *wrld = main->world.first; wrld; wrld = wrld->id.next) { if (wrld->id.tag & LIB_TAG_NEED_LINK) { + IDP_LibLinkProperty(wrld->id.properties, (fd->flags & FD_FLAGS_SWITCH_ENDIAN), fd); lib_link_animdata(fd, &wrld->id, wrld->adt); wrld->ipo = newlibadr_us(fd, wrld->id.lib, wrld->ipo); // XXX deprecated - old animation system - for (a=0; a < MAX_MTEX; a++) { - mtex = wrld->mtex[a]; + for (int a = 0; a < MAX_MTEX; a++) { + MTex *mtex = wrld->mtex[a]; if (mtex) { mtex->tex = newlibadr_us(fd, wrld->id.lib, mtex->tex); mtex->object = newlibadr(fd, wrld->id.lib, mtex->object); @@ -3618,12 +3601,12 @@ static void direct_link_world(FileData *fd, World *wrld) /* ************ READ VFONT ***************** */ -static void lib_link_vfont(FileData *UNUSED(fd), Main *main) +static void lib_link_vfont(FileData *fd, Main *main) { - VFont *vf; - - for (vf = main->vfont.first; vf; vf = vf->id.next) { + for (VFont *vf = main->vfont.first; vf; vf = vf->id.next) { if (vf->id.tag & LIB_TAG_NEED_LINK) { + IDP_LibLinkProperty(vf->id.properties, (fd->flags & FD_FLAGS_SWITCH_ENDIAN), fd); + vf->id.tag &= ~LIB_TAG_NEED_LINK; } } @@ -3638,12 +3621,12 @@ static void direct_link_vfont(FileData *fd, VFont *vf) /* ************ READ TEXT ****************** */ -static void lib_link_text(FileData *UNUSED(fd), Main *main) +static void lib_link_text(FileData *fd, Main *main) { - Text *text; - - for (text = main->text.first; text; text = text->id.next) { + for (Text *text = main->text.first; text; text = text->id.next) { if (text->id.tag & LIB_TAG_NEED_LINK) { + IDP_LibLinkProperty(text->id.properties, (fd->flags & FD_FLAGS_SWITCH_ENDIAN), fd); + text->id.tag &= ~LIB_TAG_NEED_LINK; } } @@ -3692,9 +3675,7 @@ static void direct_link_text(FileData *fd, Text *text) static void lib_link_image(FileData *fd, Main *main) { - Image *ima; - - for (ima = main->image.first; ima; ima = ima->id.next) { + for (Image *ima = main->image.first; ima; ima = ima->id.next) { if (ima->id.tag & LIB_TAG_NEED_LINK) { IDP_LibLinkProperty(ima->id.properties, (fd->flags & FD_FLAGS_SWITCH_ENDIAN), fd); @@ -3761,15 +3742,14 @@ static void direct_link_image(FileData *fd, Image *ima) static void lib_link_curve(FileData *fd, Main *main) { - Curve *cu; - int a; - - for (cu = main->curve.first; cu; cu = cu->id.next) { + for (Curve *cu = main->curve.first; cu; cu = cu->id.next) { if (cu->id.tag & LIB_TAG_NEED_LINK) { + IDP_LibLinkProperty(cu->id.properties, (fd->flags & FD_FLAGS_SWITCH_ENDIAN), fd); lib_link_animdata(fd, &cu->id, cu->adt); - for (a = 0; a < cu->totcol; a++) + for (int a = 0; a < cu->totcol; a++) { cu->mat[a] = newlibadr_us(fd, cu->id.lib, cu->mat[a]); + } cu->bevobj = newlibadr(fd, cu->id.lib, cu->bevobj); cu->taperobj = newlibadr(fd, cu->id.lib, cu->taperobj); @@ -3854,10 +3834,9 @@ static void direct_link_curve(FileData *fd, Curve *cu) static void lib_link_texture(FileData *fd, Main *main) { - Tex *tex; - - for (tex = main->tex.first; tex; tex = tex->id.next) { + for (Tex *tex = main->tex.first; tex; tex = tex->id.next) { if (tex->id.tag & LIB_TAG_NEED_LINK) { + IDP_LibLinkProperty(tex->id.properties, (fd->flags & FD_FLAGS_SWITCH_ENDIAN), fd); lib_link_animdata(fd, &tex->id, tex->adt); tex->ima = newlibadr_us(fd, tex->id.lib, tex->ima); @@ -3933,12 +3912,9 @@ static void direct_link_texture(FileData *fd, Tex *tex) static void lib_link_material(FileData *fd, Main *main) { - Material *ma; - MTex *mtex; - int a; - - for (ma = main->mat.first; ma; ma = ma->id.next) { + for (Material *ma = main->mat.first; ma; ma = ma->id.next) { if (ma->id.tag & LIB_TAG_NEED_LINK) { + IDP_LibLinkProperty(ma->id.properties, (fd->flags & FD_FLAGS_SWITCH_ENDIAN), fd); lib_link_animdata(fd, &ma->id, ma->adt); /* Link ID Properties -- and copy this comment EXACTLY for easy finding @@ -3948,8 +3924,8 @@ static void lib_link_material(FileData *fd, Main *main) ma->ipo = newlibadr_us(fd, ma->id.lib, ma->ipo); // XXX deprecated - old animation system ma->group = newlibadr_us(fd, ma->id.lib, ma->group); - for (a = 0; a < MAX_MTEX; a++) { - mtex = ma->mtex[a]; + for (int a = 0; a < MAX_MTEX; a++) { + MTex *mtex = ma->mtex[a]; if (mtex) { mtex->tex = newlibadr_us(fd, ma->id.lib, mtex->tex); mtex->object = newlibadr(fd, ma->id.lib, mtex->object); @@ -4086,14 +4062,11 @@ static void lib_link_partdeflect(FileData *fd, ID *id, PartDeflect *pd) static void lib_link_particlesettings(FileData *fd, Main *main) { - ParticleSettings *part; - ParticleDupliWeight *dw; - MTex *mtex; - int a; - - for (part = main->particle.first; part; part = part->id.next) { + for (ParticleSettings *part = main->particle.first; part; part = part->id.next) { if (part->id.tag & LIB_TAG_NEED_LINK) { + IDP_LibLinkProperty(part->id.properties, (fd->flags & FD_FLAGS_SWITCH_ENDIAN), fd); lib_link_animdata(fd, &part->id, part->adt); + part->ipo = newlibadr_us(fd, part->id.lib, part->ipo); // XXX deprecated - old animation system part->dup_ob = newlibadr(fd, part->id.lib, part->dup_ob); @@ -4113,6 +4086,7 @@ static void lib_link_particlesettings(FileData *fd, Main *main) } if (part->dupliweights.first && part->dup_group) { + ParticleDupliWeight *dw; int index_ok = 0; /* check for old files without indices (all indexes 0) */ if (BLI_listbase_is_single(&part->dupliweights)) { @@ -4177,8 +4151,8 @@ static void lib_link_particlesettings(FileData *fd, Main *main) } } - for (a = 0; a < MAX_MTEX; a++) { - mtex= part->mtex[a]; + for (int a = 0; a < MAX_MTEX; a++) { + MTex *mtex= part->mtex[a]; if (mtex) { mtex->tex = newlibadr_us(fd, part->id.lib, mtex->tex); mtex->object = newlibadr(fd, part->id.lib, mtex->object); @@ -4686,10 +4660,9 @@ static void direct_link_mesh(FileData *fd, Mesh *mesh) static void lib_link_latt(FileData *fd, Main *main) { - Lattice *lt; - - for (lt = main->latt.first; lt; lt = lt->id.next) { + for (Lattice *lt = main->latt.first; lt; lt = lt->id.next) { if (lt->id.tag & LIB_TAG_NEED_LINK) { + IDP_LibLinkProperty(lt->id.properties, (fd->flags & FD_FLAGS_SWITCH_ENDIAN), fd); lib_link_animdata(fd, <->id, lt->adt); lt->ipo = newlibadr_us(fd, lt->id.lib, lt->ipo); // XXX deprecated - old animation system @@ -4733,16 +4706,12 @@ static void lib_link_modifiers(FileData *fd, Object *ob) static void lib_link_object(FileData *fd, Main *main) { - Object *ob; - PartEff *paf; - bSensor *sens; - bController *cont; - bActuator *act; - void *poin; - int warn=0, a; - - for (ob = main->object.first; ob; ob = ob->id.next) { + bool warn = false; + + for (Object *ob = main->object.first; ob; ob = ob->id.next) { if (ob->id.tag & LIB_TAG_NEED_LINK) { + int a; + IDP_LibLinkProperty(ob->id.properties, (fd->flags & FD_FLAGS_SWITCH_ENDIAN), fd); lib_link_animdata(fd, &ob->id, ob->adt); @@ -4775,17 +4744,17 @@ static void lib_link_object(FileData *fd, Main *main) } ob->proxy_group = newlibadr(fd, ob->id.lib, ob->proxy_group); - poin = ob->data; + void *poin = ob->data; ob->data = newlibadr_us(fd, ob->id.lib, ob->data); - if (ob->data==NULL && poin!=NULL) { + if (ob->data == NULL && poin != NULL) { if (ob->id.lib) printf("Can't find obdata of %s lib %s\n", ob->id.name + 2, ob->id.lib->name); else printf("Object %s lost data.\n", ob->id.name + 2); ob->type = OB_EMPTY; - warn = 1; + warn = true; if (ob->pose) { /* we can't call #BKE_pose_free() here because of library linking @@ -4831,13 +4800,13 @@ static void lib_link_object(FileData *fd, Main *main) lib_link_nlastrips(fd, &ob->id, &ob->nlastrips); // >>> XXX deprecated - old animation system - for (paf = ob->effect.first; paf; paf = paf->next) { + for (PartEff *paf = ob->effect.first; paf; paf = paf->next) { if (paf->type == EFF_PARTICLE) { paf->group = newlibadr_us(fd, ob->id.lib, paf->group); } } - for (sens = ob->sensors.first; sens; sens = sens->next) { + for (bSensor *sens = ob->sensors.first; sens; sens = sens->next) { for (a = 0; a < sens->totlinks; a++) sens->links[a] = newglobadr(fd, sens->links[a]); @@ -4848,7 +4817,7 @@ static void lib_link_object(FileData *fd, Main *main) } } - for (cont = ob->controllers.first; cont; cont = cont->next) { + for (bController *cont = ob->controllers.first; cont; cont = cont->next) { for (a=0; a < cont->totlinks; a++) cont->links[a] = newglobadr(fd, cont->links[a]); @@ -4860,86 +4829,117 @@ static void lib_link_object(FileData *fd, Main *main) cont->totslinks = 0; } - for (act = ob->actuators.first; act; act = act->next) { - if (act->type == ACT_SOUND) { - bSoundActuator *sa = act->data; - sa->sound= newlibadr_us(fd, ob->id.lib, sa->sound); - } - else if (act->type == ACT_GAME) { - /* bGameActuator *ga= act->data; */ - } - else if (act->type == ACT_CAMERA) { - bCameraActuator *ca = act->data; - ca->ob= newlibadr(fd, ob->id.lib, ca->ob); - } - /* leave this one, it's obsolete but necessary to read for conversion */ - else if (act->type == ACT_ADD_OBJECT) { - bAddObjectActuator *eoa = act->data; - if (eoa) eoa->ob= newlibadr(fd, ob->id.lib, eoa->ob); - } - else if (act->type == ACT_OBJECT) { - bObjectActuator *oa = act->data; - if (oa == NULL) { - init_actuator(act); + for (bActuator *act = ob->actuators.first; act; act = act->next) { + switch (act->type) { + case ACT_SOUND: + { + bSoundActuator *sa = act->data; + sa->sound = newlibadr_us(fd, ob->id.lib, sa->sound); + break; } - else { - oa->reference = newlibadr(fd, ob->id.lib, oa->reference); + case ACT_GAME: + /* bGameActuator *ga= act->data; */ + break; + case ACT_CAMERA: + { + bCameraActuator *ca = act->data; + ca->ob = newlibadr(fd, ob->id.lib, ca->ob); + break; } - } - else if (act->type == ACT_EDIT_OBJECT) { - bEditObjectActuator *eoa = act->data; - if (eoa == NULL) { - init_actuator(act); + /* leave this one, it's obsolete but necessary to read for conversion */ + case ACT_ADD_OBJECT: + { + bAddObjectActuator *eoa = act->data; + if (eoa) + eoa->ob = newlibadr(fd, ob->id.lib, eoa->ob); + break; } - else { - eoa->ob= newlibadr(fd, ob->id.lib, eoa->ob); - eoa->me= newlibadr(fd, ob->id.lib, eoa->me); + case ACT_OBJECT: + { + bObjectActuator *oa = act->data; + if (oa == NULL) { + init_actuator(act); + } + else { + oa->reference = newlibadr(fd, ob->id.lib, oa->reference); + } + break; } - } - else if (act->type == ACT_SCENE) { - bSceneActuator *sa = act->data; - sa->camera= newlibadr(fd, ob->id.lib, sa->camera); - sa->scene= newlibadr(fd, ob->id.lib, sa->scene); - } - else if (act->type == ACT_ACTION) { - bActionActuator *aa = act->data; - aa->act= newlibadr_us(fd, ob->id.lib, aa->act); - } - else if (act->type == ACT_SHAPEACTION) { - bActionActuator *aa = act->data; - aa->act= newlibadr_us(fd, ob->id.lib, aa->act); - } - else if (act->type == ACT_PROPERTY) { - bPropertyActuator *pa = act->data; - pa->ob= newlibadr(fd, ob->id.lib, pa->ob); - } - else if (act->type == ACT_MESSAGE) { - bMessageActuator *ma = act->data; - ma->toObject= newlibadr(fd, ob->id.lib, ma->toObject); - } - else if (act->type == ACT_2DFILTER) { - bTwoDFilterActuator *_2dfa = act->data; - _2dfa->text= newlibadr(fd, ob->id.lib, _2dfa->text); - } - else if (act->type == ACT_PARENT) { - bParentActuator *parenta = act->data; - parenta->ob = newlibadr(fd, ob->id.lib, parenta->ob); - } - else if (act->type == ACT_STATE) { - /* bStateActuator *statea = act->data; */ - } - else if (act->type == ACT_ARMATURE) { - bArmatureActuator *arma= act->data; - arma->target= newlibadr(fd, ob->id.lib, arma->target); - arma->subtarget= newlibadr(fd, ob->id.lib, arma->subtarget); - } - else if (act->type == ACT_STEERING) { - bSteeringActuator *steeringa = act->data; - steeringa->target = newlibadr(fd, ob->id.lib, steeringa->target); - steeringa->navmesh = newlibadr(fd, ob->id.lib, steeringa->navmesh); - } - else if (act->type == ACT_MOUSE) { - /* bMouseActuator *moa= act->data; */ + case ACT_EDIT_OBJECT: + { + bEditObjectActuator *eoa = act->data; + if (eoa == NULL) { + init_actuator(act); + } + else { + eoa->ob = newlibadr(fd, ob->id.lib, eoa->ob); + eoa->me = newlibadr(fd, ob->id.lib, eoa->me); + } + break; + } + case ACT_SCENE: + { + bSceneActuator *sa = act->data; + sa->camera = newlibadr(fd, ob->id.lib, sa->camera); + sa->scene = newlibadr(fd, ob->id.lib, sa->scene); + break; + } + case ACT_ACTION: + { + bActionActuator *aa = act->data; + aa->act = newlibadr_us(fd, ob->id.lib, aa->act); + break; + } + case ACT_SHAPEACTION: + { + bActionActuator *aa = act->data; + aa->act = newlibadr_us(fd, ob->id.lib, aa->act); + break; + } + case ACT_PROPERTY: + { + bPropertyActuator *pa = act->data; + pa->ob = newlibadr(fd, ob->id.lib, pa->ob); + break; + } + case ACT_MESSAGE: + { + bMessageActuator *ma = act->data; + ma->toObject = newlibadr(fd, ob->id.lib, ma->toObject); + break; + } + case ACT_2DFILTER: + { + bTwoDFilterActuator *_2dfa = act->data; + _2dfa->text = newlibadr(fd, ob->id.lib, _2dfa->text); + break; + } + case ACT_PARENT: + { + bParentActuator *parenta = act->data; + parenta->ob = newlibadr(fd, ob->id.lib, parenta->ob); + break; + } + case ACT_STATE: + /* bStateActuator *statea = act->data; */ + break; + case ACT_ARMATURE: + { + bArmatureActuator *arma= act->data; + arma->target = newlibadr(fd, ob->id.lib, arma->target); + arma->subtarget = newlibadr(fd, ob->id.lib, arma->subtarget); + break; + } + case ACT_STEERING: + { + bSteeringActuator *steeringa = act->data; + steeringa->target = newlibadr(fd, ob->id.lib, steeringa->target); + steeringa->navmesh = newlibadr(fd, ob->id.lib, steeringa->navmesh); + break; + } + case ACT_MOUSE: + /* bMouseActuator *moa = act->data; */ + break; } } @@ -5689,20 +5689,12 @@ static void lib_link_scene_collection(FileData *fd, Library *lib, SceneCollectio static void lib_link_scene(FileData *fd, Main *main) { - Scene *sce; - BaseLegacy *base_legacy, *base_legacy_next; - Sequence *seq; - SceneLayer *sl; - SceneRenderLayer *srl; - FreestyleModuleConfig *fmc; - FreestyleLineSet *fls; - #ifdef USE_SETSCENE_CHECK bool need_check_set = false; int totscene = 0; #endif - for (sce = main->scene.first; sce; sce = sce->id.next) { + for (Scene *sce = main->scene.first; sce; sce = sce->id.next) { if (sce->id.tag & LIB_TAG_NEED_LINK) { /* Link ID Properties -- and copy this comment EXACTLY for easy finding * of library blocks that implement this.*/ @@ -5742,7 +5734,7 @@ static void lib_link_scene(FileData *fd, Main *main) sce->toolsettings->particle.shape_object = newlibadr(fd, sce->id.lib, sce->toolsettings->particle.shape_object); - for (base_legacy = sce->base.first; base_legacy; base_legacy = base_legacy_next) { + for (BaseLegacy *base_legacy_next, *base_legacy = sce->base.first; base_legacy; base_legacy = base_legacy_next) { base_legacy_next = base_legacy->next; base_legacy->object = newlibadr_us(fd, sce->id.lib, base_legacy->object); @@ -5756,6 +5748,7 @@ static void lib_link_scene(FileData *fd, Main *main) } } + Sequence *seq; SEQ_BEGIN (sce->ed, seq) { if (seq->ipo) seq->ipo = newlibadr_us(fd, sce->id.lib, seq->ipo); // XXX deprecated - old animation system @@ -5821,13 +5814,13 @@ static void lib_link_scene(FileData *fd, Main *main) composite_patch(sce->nodetree, sce); } - for (srl = sce->r.layers.first; srl; srl = srl->next) { + for (SceneRenderLayer *srl = sce->r.layers.first; srl; srl = srl->next) { srl->mat_override = newlibadr_us(fd, sce->id.lib, srl->mat_override); srl->light_override = newlibadr_us(fd, sce->id.lib, srl->light_override); - for (fmc = srl->freestyleConfig.modules.first; fmc; fmc = fmc->next) { + for (FreestyleModuleConfig *fmc = srl->freestyleConfig.modules.first; fmc; fmc = fmc->next) { fmc->script = newlibadr(fd, sce->id.lib, fmc->script); } - for (fls = srl->freestyleConfig.linesets.first; fls; fls = fls->next) { + for (FreestyleLineSet *fls = srl->freestyleConfig.linesets.first; fls; fls = fls->next) { fls->linestyle = newlibadr_us(fd, sce->id.lib, fls->linestyle); fls->group = newlibadr_us(fd, sce->id.lib, fls->group); } @@ -5840,7 +5833,7 @@ static void lib_link_scene(FileData *fd, Main *main) lib_link_scene_collection(fd, sce->id.lib, sce->collection); - for (sl = sce->render_layers.first; sl; sl = sl->next) { + for (SceneLayer *sl = sce->render_layers.first; sl; sl = sl->next) { /* tag scene layer to update for collection tree evaluation */ sl->flag |= SCENE_LAYER_ENGINE_DIRTY; for (Base *base = sl->object_bases.first; base; base = base->next) { @@ -5873,7 +5866,7 @@ static void lib_link_scene(FileData *fd, Main *main) #ifdef USE_SETSCENE_CHECK if (need_check_set) { - for (sce = main->scene.first; sce; sce = sce->id.next) { + for (Scene *sce = main->scene.first; sce; sce = sce->id.next) { if (sce->id.tag & LIB_TAG_NEED_LINK) { sce->id.tag &= ~LIB_TAG_NEED_LINK; if (!scene_validate_setscene__liblink(sce, totscene)) { @@ -6347,8 +6340,10 @@ static void lib_link_windowmanager(FileData *fd, Main *main) for (wm = main->wm.first; wm; wm = wm->id.next) { if (wm->id.tag & LIB_TAG_NEED_LINK) { - for (win = wm->windows.first; win; win = win->next) + /* Note: WM IDProperties are never written to file, hence no need to read/link them here. */ + for (win = wm->windows.first; win; win = win->next) { win->screen = newlibadr(fd, NULL, win->screen); + } wm->id.tag &= ~LIB_TAG_NEED_LINK; } @@ -6360,13 +6355,12 @@ static void lib_link_windowmanager(FileData *fd, Main *main) /* relink's grease pencil data's refs */ static void lib_link_gpencil(FileData *fd, Main *main) { - bGPdata *gpd; - - for (gpd = main->gpencil.first; gpd; gpd = gpd->id.next) { + for (bGPdata *gpd = main->gpencil.first; gpd; gpd = gpd->id.next) { if (gpd->id.tag & LIB_TAG_NEED_LINK) { - gpd->id.tag &= ~LIB_TAG_NEED_LINK; - + IDP_LibLinkProperty(gpd->id.properties, (fd->flags & FD_FLAGS_SWITCH_ENDIAN), fd); lib_link_animdata(fd, &gpd->id, gpd->adt); + + gpd->id.tag &= ~LIB_TAG_NEED_LINK; } } } @@ -6428,12 +6422,11 @@ static void direct_link_gpencil(FileData *fd, bGPdata *gpd) * check lib pointers in call below */ static void lib_link_screen(FileData *fd, Main *main) { - bScreen *sc; - ScrArea *sa; - - for (sc = main->screen.first; sc; sc = sc->id.next) { + for (bScreen *sc = main->screen.first; sc; sc = sc->id.next) { if (sc->id.tag & LIB_TAG_NEED_LINK) { + IDP_LibLinkProperty(sc->id.properties, (fd->flags & FD_FLAGS_SWITCH_ENDIAN), fd); id_us_ensure_real(&sc->id); + sc->scene = newlibadr(fd, sc->id.lib, sc->scene); /* this should not happen, but apparently it does somehow. Until we figure out the cause, @@ -6444,177 +6437,204 @@ static void lib_link_screen(FileData *fd, Main *main) sc->animtimer = NULL; /* saved in rare cases */ sc->scrubbing = false; - for (sa = sc->areabase.first; sa; sa = sa->next) { - SpaceLink *sl; - + for (ScrArea *sa = sc->areabase.first; sa; sa = sa->next) { sa->full = newlibadr(fd, sc->id.lib, sa->full); - for (sl = sa->spacedata.first; sl; sl= sl->next) { - if (sl->spacetype == SPACE_VIEW3D) { - View3D *v3d = (View3D*) sl; - BGpic *bgpic = NULL; - - v3d->camera= newlibadr(fd, sc->id.lib, v3d->camera); - v3d->ob_centre= newlibadr(fd, sc->id.lib, v3d->ob_centre); - - /* should be do_versions but not easy adding into the listbase */ - if (v3d->bgpic) { - v3d->bgpic = newlibadr(fd, sc->id.lib, v3d->bgpic); - BLI_addtail(&v3d->bgpicbase, bgpic); - v3d->bgpic = NULL; + for (SpaceLink *sl = sa->spacedata.first; sl; sl= sl->next) { + switch (sl->spacetype) { + case SPACE_VIEW3D: + { + View3D *v3d = (View3D*) sl; + BGpic *bgpic = NULL; + + v3d->camera= newlibadr(fd, sc->id.lib, v3d->camera); + v3d->ob_centre= newlibadr(fd, sc->id.lib, v3d->ob_centre); + + /* should be do_versions but not easy adding into the listbase */ + if (v3d->bgpic) { + v3d->bgpic = newlibadr(fd, sc->id.lib, v3d->bgpic); + BLI_addtail(&v3d->bgpicbase, bgpic); + v3d->bgpic = NULL; + } + + for (bgpic = v3d->bgpicbase.first; bgpic; bgpic = bgpic->next) { + bgpic->ima = newlibadr_us(fd, sc->id.lib, bgpic->ima); + bgpic->clip = newlibadr_us(fd, sc->id.lib, bgpic->clip); + } + if (v3d->localvd) { + v3d->localvd->camera = newlibadr(fd, sc->id.lib, v3d->localvd->camera); + } + break; } - - for (bgpic = v3d->bgpicbase.first; bgpic; bgpic = bgpic->next) { - bgpic->ima = newlibadr_us(fd, sc->id.lib, bgpic->ima); - bgpic->clip = newlibadr_us(fd, sc->id.lib, bgpic->clip); + case SPACE_IPO: + { + SpaceIpo *sipo = (SpaceIpo *)sl; + bDopeSheet *ads = sipo->ads; + + if (ads) { + ads->source = newlibadr(fd, sc->id.lib, ads->source); + ads->filter_grp = newlibadr(fd, sc->id.lib, ads->filter_grp); + } + break; } - if (v3d->localvd) { - v3d->localvd->camera = newlibadr(fd, sc->id.lib, v3d->localvd->camera); + case SPACE_BUTS: + { + SpaceButs *sbuts = (SpaceButs *)sl; + sbuts->pinid = newlibadr(fd, sc->id.lib, sbuts->pinid); + if (sbuts->pinid == NULL) { + sbuts->flag &= ~SB_PIN_CONTEXT; + } + break; } - } - else if (sl->spacetype == SPACE_IPO) { - SpaceIpo *sipo = (SpaceIpo *)sl; - bDopeSheet *ads = sipo->ads; - - if (ads) { - ads->source = newlibadr(fd, sc->id.lib, ads->source); - ads->filter_grp = newlibadr(fd, sc->id.lib, ads->filter_grp); + case SPACE_FILE: + break; + case SPACE_ACTION: + { + SpaceAction *saction = (SpaceAction *)sl; + bDopeSheet *ads = &saction->ads; + + if (ads) { + ads->source = newlibadr(fd, sc->id.lib, ads->source); + ads->filter_grp = newlibadr(fd, sc->id.lib, ads->filter_grp); + } + + saction->action = newlibadr(fd, sc->id.lib, saction->action); + break; } - } - else if (sl->spacetype == SPACE_BUTS) { - SpaceButs *sbuts = (SpaceButs *)sl; - sbuts->pinid = newlibadr(fd, sc->id.lib, sbuts->pinid); - if (sbuts->pinid == NULL) { - sbuts->flag &= ~SB_PIN_CONTEXT; + case SPACE_IMAGE: + { + SpaceImage *sima = (SpaceImage *)sl; + + sima->image = newlibadr_real_us(fd, sc->id.lib, sima->image); + sima->mask_info.mask = newlibadr_real_us(fd, sc->id.lib, sima->mask_info.mask); + + /* NOTE: pre-2.5, this was local data not lib data, but now we need this as lib data + * so fingers crossed this works fine! + */ + sima->gpd = newlibadr_us(fd, sc->id.lib, sima->gpd); + break; } - } - else if (sl->spacetype == SPACE_FILE) { - ; - } - else if (sl->spacetype == SPACE_ACTION) { - SpaceAction *saction = (SpaceAction *)sl; - bDopeSheet *ads = &saction->ads; - - if (ads) { - ads->source = newlibadr(fd, sc->id.lib, ads->source); - ads->filter_grp = newlibadr(fd, sc->id.lib, ads->filter_grp); + case SPACE_SEQ: + { + SpaceSeq *sseq = (SpaceSeq *)sl; + + /* NOTE: pre-2.5, this was local data not lib data, but now we need this as lib data + * so fingers crossed this works fine! + */ + sseq->gpd = newlibadr_us(fd, sc->id.lib, sseq->gpd); + break; } - - saction->action = newlibadr(fd, sc->id.lib, saction->action); - } - else if (sl->spacetype == SPACE_IMAGE) { - SpaceImage *sima = (SpaceImage *)sl; - - sima->image = newlibadr_real_us(fd, sc->id.lib, sima->image); - sima->mask_info.mask = newlibadr_real_us(fd, sc->id.lib, sima->mask_info.mask); - - /* NOTE: pre-2.5, this was local data not lib data, but now we need this as lib data - * so fingers crossed this works fine! - */ - sima->gpd = newlibadr_us(fd, sc->id.lib, sima->gpd); - } - else if (sl->spacetype == SPACE_SEQ) { - SpaceSeq *sseq = (SpaceSeq *)sl; - - /* NOTE: pre-2.5, this was local data not lib data, but now we need this as lib data - * so fingers crossed this works fine! - */ - sseq->gpd = newlibadr_us(fd, sc->id.lib, sseq->gpd); + case SPACE_NLA: + { + SpaceNla *snla= (SpaceNla *)sl; + bDopeSheet *ads= snla->ads; + + if (ads) { + ads->source = newlibadr(fd, sc->id.lib, ads->source); + ads->filter_grp = newlibadr(fd, sc->id.lib, ads->filter_grp); + } + break; + } + case SPACE_TEXT: + { + SpaceText *st= (SpaceText *)sl; - } - else if (sl->spacetype == SPACE_NLA) { - SpaceNla *snla= (SpaceNla *)sl; - bDopeSheet *ads= snla->ads; - - if (ads) { - ads->source = newlibadr(fd, sc->id.lib, ads->source); - ads->filter_grp = newlibadr(fd, sc->id.lib, ads->filter_grp); + st->text= newlibadr(fd, sc->id.lib, st->text); + break; } - } - else if (sl->spacetype == SPACE_TEXT) { - SpaceText *st= (SpaceText *)sl; - - st->text= newlibadr(fd, sc->id.lib, st->text); - } - else if (sl->spacetype == SPACE_SCRIPT) { - SpaceScript *scpt = (SpaceScript *)sl; - /*scpt->script = NULL; - 2.45 set to null, better re-run the script */ - if (scpt->script) { - scpt->script = newlibadr(fd, sc->id.lib, scpt->script); + case SPACE_SCRIPT: + { + SpaceScript *scpt = (SpaceScript *)sl; + /*scpt->script = NULL; - 2.45 set to null, better re-run the script */ if (scpt->script) { - SCRIPT_SET_NULL(scpt->script); + scpt->script = newlibadr(fd, sc->id.lib, scpt->script); + if (scpt->script) { + SCRIPT_SET_NULL(scpt->script); + } } + break; } - } - else if (sl->spacetype == SPACE_OUTLINER) { - SpaceOops *so= (SpaceOops *)sl; - so->search_tse.id = newlibadr(fd, NULL, so->search_tse.id); - - if (so->treestore) { - TreeStoreElem *tselem; - BLI_mempool_iter iter; + case SPACE_OUTLINER: + { + SpaceOops *so= (SpaceOops *)sl; + so->search_tse.id = newlibadr(fd, NULL, so->search_tse.id); + + if (so->treestore) { + TreeStoreElem *tselem; + BLI_mempool_iter iter; + + BLI_mempool_iternew(so->treestore, &iter); + while ((tselem = BLI_mempool_iterstep(&iter))) { + tselem->id = newlibadr(fd, NULL, tselem->id); + } + if (so->treehash) { + /* rebuild hash table, because it depends on ids too */ + so->storeflag |= SO_TREESTORE_REBUILD; + } + } + break; + } + case SPACE_NODE: + { + SpaceNode *snode = (SpaceNode *)sl; + bNodeTreePath *path, *path_next; + bNodeTree *ntree; + + /* node tree can be stored locally in id too, link this first */ + snode->id = newlibadr(fd, sc->id.lib, snode->id); + snode->from = newlibadr(fd, sc->id.lib, snode->from); + + ntree = snode->id ? ntreeFromID(snode->id) : NULL; + snode->nodetree = ntree ? ntree : newlibadr_us(fd, sc->id.lib, snode->nodetree); + + for (path = snode->treepath.first; path; path = path->next) { + if (path == snode->treepath.first) { + /* first nodetree in path is same as snode->nodetree */ + path->nodetree = snode->nodetree; + } + else + path->nodetree = newlibadr_us(fd, sc->id.lib, path->nodetree); - BLI_mempool_iternew(so->treestore, &iter); - while ((tselem = BLI_mempool_iterstep(&iter))) { - tselem->id = newlibadr(fd, NULL, tselem->id); + if (!path->nodetree) + break; } - if (so->treehash) { - /* rebuild hash table, because it depends on ids too */ - so->storeflag |= SO_TREESTORE_REBUILD; + + /* remaining path entries are invalid, remove */ + for (; path; path = path_next) { + path_next = path->next; + + BLI_remlink(&snode->treepath, path); + MEM_freeN(path); } - } - } - else if (sl->spacetype == SPACE_NODE) { - SpaceNode *snode = (SpaceNode *)sl; - bNodeTreePath *path, *path_next; - bNodeTree *ntree; - - /* node tree can be stored locally in id too, link this first */ - snode->id = newlibadr(fd, sc->id.lib, snode->id); - snode->from = newlibadr(fd, sc->id.lib, snode->from); - - ntree = snode->id ? ntreeFromID(snode->id) : NULL; - snode->nodetree = ntree ? ntree : newlibadr_us(fd, sc->id.lib, snode->nodetree); - - for (path = snode->treepath.first; path; path = path->next) { - if (path == snode->treepath.first) { - /* first nodetree in path is same as snode->nodetree */ - path->nodetree = snode->nodetree; + + /* edittree is just the last in the path, + * set this directly since the path may have been shortened above */ + if (snode->treepath.last) { + path = snode->treepath.last; + snode->edittree = path->nodetree; } - else - path->nodetree = newlibadr_us(fd, sc->id.lib, path->nodetree); - - if (!path->nodetree) - break; + else { + snode->edittree = NULL; + } + break; } - - /* remaining path entries are invalid, remove */ - for (; path; path = path_next) { - path_next = path->next; - - BLI_remlink(&snode->treepath, path); - MEM_freeN(path); + case SPACE_CLIP: + { + SpaceClip *sclip = (SpaceClip *)sl; + + sclip->clip = newlibadr_real_us(fd, sc->id.lib, sclip->clip); + sclip->mask_info.mask = newlibadr_real_us(fd, sc->id.lib, sclip->mask_info.mask); + break; } - - /* edittree is just the last in the path, - * set this directly since the path may have been shortened above */ - if (snode->treepath.last) { - path = snode->treepath.last; - snode->edittree = path->nodetree; + case SPACE_LOGIC: + { + SpaceLogic *slogic = (SpaceLogic *)sl; + + slogic->gpd = newlibadr_us(fd, sc->id.lib, slogic->gpd); + break; } - else - snode->edittree = NULL; - } - else if (sl->spacetype == SPACE_CLIP) { - SpaceClip *sclip = (SpaceClip *)sl; - - sclip->clip = newlibadr_real_us(fd, sc->id.lib, sclip->clip); - sclip->mask_info.mask = newlibadr_real_us(fd, sc->id.lib, sclip->mask_info.mask); - } - else if (sl->spacetype == SPACE_LOGIC) { - SpaceLogic *slogic = (SpaceLogic *)sl; - - slogic->gpd = newlibadr_us(fd, sc->id.lib, slogic->gpd); + default: + break; } } } @@ -7492,13 +7512,13 @@ static void fix_relpaths_library(const char *basepath, Main *main) static void lib_link_speaker(FileData *fd, Main *main) { - Speaker *spk; - - for (spk = main->speaker.first; spk; spk = spk->id.next) { + for (Speaker *spk = main->speaker.first; spk; spk = spk->id.next) { if (spk->id.tag & LIB_TAG_NEED_LINK) { + IDP_LibLinkProperty(spk->id.properties, (fd->flags & FD_FLAGS_SWITCH_ENDIAN), fd); lib_link_animdata(fd, &spk->id, spk->adt); spk->sound = newlibadr_us(fd, spk->id.lib, spk->sound); + spk->id.tag &= ~LIB_TAG_NEED_LINK; } } @@ -7548,14 +7568,15 @@ static void direct_link_sound(FileData *fd, bSound *sound) static void lib_link_sound(FileData *fd, Main *main) { - bSound *sound; - - for (sound = main->sound.first; sound; sound = sound->id.next) { + for (bSound *sound = main->sound.first; sound; sound = sound->id.next) { if (sound->id.tag & LIB_TAG_NEED_LINK) { - sound->id.tag &= ~LIB_TAG_NEED_LINK; + IDP_LibLinkProperty(sound->id.properties, (fd->flags & FD_FLAGS_SWITCH_ENDIAN), fd); + sound->ipo = newlibadr_us(fd, sound->id.lib, sound->ipo); // XXX deprecated - old animation system BKE_sound_load(main, sound); + + sound->id.tag &= ~LIB_TAG_NEED_LINK; } } } @@ -7570,17 +7591,13 @@ static void direct_link_group(FileData *fd, Group *group) static void lib_link_group(FileData *fd, Main *main) { - Group *group; - GroupObject *go; - bool add_us; - - for (group = main->group.first; group; group = group->id.next) { + for (Group *group = main->group.first; group; group = group->id.next) { if (group->id.tag & LIB_TAG_NEED_LINK) { - group->id.tag &= ~LIB_TAG_NEED_LINK; + IDP_LibLinkProperty(group->id.properties, (fd->flags & FD_FLAGS_SWITCH_ENDIAN), fd); - add_us = false; + bool add_us = false; - for (go = group->gobject.first; go; go = go->next) { + for (GroupObject *go = group->gobject.first; go; go = go->next) { go->ob = newlibadr_real_us(fd, group->id.lib, go->ob); if (go->ob) { go->ob->flag |= OB_FROMGROUP; @@ -7592,6 +7609,8 @@ static void lib_link_group(FileData *fd, Main *main) id_us_ensure_real(&group->id); } BKE_group_object_unlink(group, NULL); /* removes NULL entries */ + + group->id.tag &= ~LIB_TAG_NEED_LINK; } } } @@ -7696,13 +7715,11 @@ static void lib_link_moviePlaneTracks(FileData *fd, MovieClip *clip, ListBase *t static void lib_link_movieclip(FileData *fd, Main *main) { - MovieClip *clip; - - for (clip = main->movieclip.first; clip; clip = clip->id.next) { + for (MovieClip *clip = main->movieclip.first; clip; clip = clip->id.next) { if (clip->id.tag & LIB_TAG_NEED_LINK) { MovieTracking *tracking = &clip->tracking; - MovieTrackingObject *object; + IDP_LibLinkProperty(clip->id.properties, (fd->flags & FD_FLAGS_SWITCH_ENDIAN), fd); lib_link_animdata(fd, &clip->id, clip->adt); clip->gpd = newlibadr_us(fd, clip->id.lib, clip->gpd); @@ -7710,7 +7727,7 @@ static void lib_link_movieclip(FileData *fd, Main *main) lib_link_movieTracks(fd, clip, &tracking->tracks); lib_link_moviePlaneTracks(fd, clip, &tracking->plane_tracks); - for (object = tracking->objects.first; object; object = object->next) { + for (MovieTrackingObject *object = tracking->objects.first; object; object = object->next) { lib_link_movieTracks(fd, clip, &object->tracks); lib_link_moviePlaneTracks(fd, clip, &object->plane_tracks); } @@ -7787,16 +7804,12 @@ static void lib_link_mask_parent(FileData *fd, Mask *mask, MaskParent *parent) static void lib_link_mask(FileData *fd, Main *main) { - Mask *mask; - - mask = main->mask.first; - while (mask) { + for (Mask *mask = main->mask.first; mask; mask = mask->id.next) { if (mask->id.tag & LIB_TAG_NEED_LINK) { - MaskLayer *masklay; - + IDP_LibLinkProperty(mask->id.properties, (fd->flags & FD_FLAGS_SWITCH_ENDIAN), fd); lib_link_animdata(fd, &mask->id, mask->adt); - for (masklay = mask->masklayers.first; masklay; masklay = masklay->next) { + for (MaskLayer *masklay = mask->masklayers.first; masklay; masklay = masklay->next) { MaskSpline *spline; spline = masklay->splines.first; @@ -7817,7 +7830,6 @@ static void lib_link_mask(FileData *fd, Main *main) mask->id.tag &= ~LIB_TAG_NEED_LINK; } - mask = mask->id.next; } } @@ -7825,18 +7837,13 @@ static void lib_link_mask(FileData *fd, Main *main) static void lib_link_linestyle(FileData *fd, Main *main) { - FreestyleLineStyle *linestyle; - LineStyleModifier *m; - MTex *mtex; - int a; - - linestyle = main->linestyle.first; - while (linestyle) { + for (FreestyleLineStyle *linestyle = main->linestyle.first; linestyle; linestyle = linestyle->id.next) { if (linestyle->id.tag & LIB_TAG_NEED_LINK) { - linestyle->id.tag &= ~LIB_TAG_NEED_LINK; + LineStyleModifier *m; IDP_LibLinkProperty(linestyle->id.properties, (fd->flags & FD_FLAGS_SWITCH_ENDIAN), fd); lib_link_animdata(fd, &linestyle->id, linestyle->adt); + for (m = linestyle->color_modifiers.first; m; m = m->next) { switch (m->type) { case LS_MODIFIER_DISTANCE_FROM_OBJECT: @@ -7867,8 +7874,8 @@ static void lib_link_linestyle(FileData *fd, Main *main) break; } } - for (a=0; a < MAX_MTEX; a++) { - mtex = linestyle->mtex[a]; + for (int a = 0; a < MAX_MTEX; a++) { + MTex *mtex = linestyle->mtex[a]; if (mtex) { mtex->tex = newlibadr_us(fd, linestyle->id.lib, mtex->tex); mtex->object = newlibadr(fd, linestyle->id.lib, mtex->object); @@ -7878,8 +7885,9 @@ static void lib_link_linestyle(FileData *fd, Main *main) lib_link_ntree(fd, &linestyle->id, linestyle->nodetree); linestyle->nodetree->id.lib = linestyle->id.lib; } + + linestyle->id.tag &= ~LIB_TAG_NEED_LINK; } - linestyle = linestyle->id.next; } } @@ -8535,6 +8543,7 @@ static void do_versions_after_linking(Main *main) { // printf("%s for %s (%s), %d.%d\n", __func__, main->curlib ? main->curlib->name : main->name, // main->curlib ? "LIB" : "MAIN", main->versionfile, main->subversionfile); + do_versions_after_linking_270(main); do_versions_after_linking_280(main); } @@ -8551,12 +8560,13 @@ static void lib_link_all(FileData *fd, Main *main) lib_link_screen(fd, main); lib_link_scene(fd, main); lib_link_object(fd, main); + lib_link_mesh(fd, main); lib_link_curve(fd, main); lib_link_mball(fd, main); lib_link_material(fd, main); lib_link_texture(fd, main); lib_link_image(fd, main); - lib_link_ipo(fd, main); // XXX deprecated... still needs to be maintained for version patches still + lib_link_ipo(fd, main); /* XXX deprecated... still needs to be maintained for version patches still */ lib_link_key(fd, main); lib_link_world(fd, main); lib_link_lamp(fd, main); @@ -8569,7 +8579,7 @@ static void lib_link_all(FileData *fd, Main *main) lib_link_armature(fd, main); lib_link_action(fd, main); lib_link_vfont(fd, main); - lib_link_nodetree(fd, main); /* has to be done after scene/materials, this will verify group nodes */ + lib_link_nodetree(fd, main); /* has to be done after scene/materials, this will verify group nodes */ lib_link_brush(fd, main); lib_link_palette(fd, main); lib_link_paint_curve(fd, main); @@ -8580,9 +8590,7 @@ static void lib_link_all(FileData *fd, Main *main) lib_link_gpencil(fd, main); lib_link_cachefiles(fd, main); - lib_link_mesh(fd, main); /* as last: tpage images with users at zero */ - - lib_link_library(fd, main); /* only init users */ + lib_link_library(fd, main); /* only init users */ } static void direct_link_keymapitem(FileData *fd, wmKeyMapItem *kmi) @@ -9525,7 +9533,7 @@ static void expand_object(FileData *fd, Main *mainvar, Object *ob) expand_doit(fd, mainvar, ob->proxy); if (ob->proxy_group) expand_doit(fd, mainvar, ob->proxy_group); - + for (psys = ob->particlesystem.first; psys; psys = psys->next) expand_doit(fd, mainvar, psys->part); diff --git a/source/blender/blenloader/intern/versioning_defaults.c b/source/blender/blenloader/intern/versioning_defaults.c index 99d9e140481..e34f12b1cf9 100644 --- a/source/blender/blenloader/intern/versioning_defaults.c +++ b/source/blender/blenloader/intern/versioning_defaults.c @@ -68,6 +68,18 @@ void BLO_update_defaults_userpref_blend(void) * but take care since some hardware has driver bugs here (T46962). * Further hardware workarounds should be made in gpu_extensions.c */ U.glalphaclip = (1.0f / 255); + + /* default so DPI is detected automatically */ + U.dpi = 0; + U.ui_scale = 1.0f; + +#ifdef WITH_PYTHON_SECURITY + /* use alternative setting for security nuts + * otherwise we'd need to patch the binary blob - startup.blend.c */ + U.flag |= USER_SCRIPT_AUTOEXEC_DISABLE; +#else + U.flag &= ~USER_SCRIPT_AUTOEXEC_DISABLE; +#endif } /** diff --git a/source/blender/editors/interface/interface.c b/source/blender/editors/interface/interface.c index 011786f6cdc..771f9d24e3c 100644 --- a/source/blender/editors/interface/interface.c +++ b/source/blender/editors/interface/interface.c @@ -1338,7 +1338,7 @@ static void ui_but_to_pixelrect(rcti *rect, const ARegion *ar, uiBlock *block, u rctf rectf; ui_block_to_window_rctf(ar, block, &rectf, (but) ? &but->rect : &block->rect); - BLI_rcti_rctf_copy_floor(rect, &rectf); + BLI_rcti_rctf_copy(rect, &rectf); BLI_rcti_translate(rect, -ar->winrct.xmin, -ar->winrct.ymin); } @@ -3909,7 +3909,7 @@ uiBut *uiDefIconTextButO_ptr(uiBlock *block, int type, wmOperatorType *ot, int o uiBut *uiDefIconTextButO(uiBlock *block, int type, const char *opname, int opcontext, int icon, const char *str, int x, int y, short width, short height, const char *tip) { wmOperatorType *ot = WM_operatortype_find(opname, 0); - if (str[0] == '\0') + if (str && str[0] == '\0') return uiDefIconButO_ptr(block, type, ot, opcontext, icon, x, y, width, height, tip); return uiDefIconTextButO_ptr(block, type, ot, opcontext, icon, str, x, y, width, height, tip); } diff --git a/source/blender/editors/interface/interface_layout.c b/source/blender/editors/interface/interface_layout.c index 76fa1720863..7b0921941e7 100644 --- a/source/blender/editors/interface/interface_layout.c +++ b/source/blender/editors/interface/interface_layout.c @@ -2171,7 +2171,16 @@ static void ui_litem_layout_row(uiLayout *litem) x += neww; - if ((neww < minw || itemw == minw || item->flag & UI_ITEM_MIN) && w != 0) { + bool min_flag = item->flag & UI_ITEM_MIN; + /* ignore min flag for rows with right or center alignment */ + if (item->type != ITEM_BUTTON && + ELEM(((uiLayout *)item)->alignment, UI_LAYOUT_ALIGN_RIGHT, UI_LAYOUT_ALIGN_CENTER) && + litem->alignment == UI_LAYOUT_ALIGN_EXPAND && + ((uiItem *)litem)->flag & UI_ITEM_MIN) { + min_flag = false; + } + + if ((neww < minw || min_flag) && w != 0) { /* fixed size */ item->flag |= UI_ITEM_FIXED; if (item->type != ITEM_BUTTON && item->flag & UI_ITEM_MIN) { @@ -2253,10 +2262,11 @@ static void ui_litem_layout_row(uiLayout *litem) } /* single-column layout */ -static void ui_litem_estimate_column(uiLayout *litem) +static void ui_litem_estimate_column(uiLayout *litem, bool is_box) { uiItem *item; int itemw, itemh; + bool min_size_flag = true; litem->w = 0; litem->h = 0; @@ -2264,15 +2274,21 @@ static void ui_litem_estimate_column(uiLayout *litem) for (item = litem->items.first; item; item = item->next) { ui_item_size(item, &itemw, &itemh); + min_size_flag = min_size_flag && (item->flag & UI_ITEM_MIN); + litem->w = MAX2(litem->w, itemw); litem->h += itemh; - if (item->next) + if (item->next && (!is_box || item != litem->items.first)) litem->h += litem->space; } + + if (min_size_flag) { + litem->item.flag |= UI_ITEM_MIN; + } } -static void ui_litem_layout_column(uiLayout *litem) +static void ui_litem_layout_column(uiLayout *litem, bool is_box) { uiItem *item; int itemh, x, y; @@ -2286,7 +2302,7 @@ static void ui_litem_layout_column(uiLayout *litem) y -= itemh; ui_item_position(item, x, y, litem->w, itemh); - if (item->next) + if (item->next && (!is_box || item != litem->items.first)) y -= litem->space; } @@ -2428,7 +2444,7 @@ static void ui_litem_layout_root(uiLayout *litem) else if (litem->root->type == UI_LAYOUT_PIEMENU) ui_litem_layout_root_radial(litem); else - ui_litem_layout_column(litem); + ui_litem_layout_column(litem, false); } /* box layout */ @@ -2436,9 +2452,10 @@ static void ui_litem_estimate_box(uiLayout *litem) { uiStyle *style = litem->root->style; - ui_litem_estimate_column(litem); + ui_litem_estimate_column(litem, true); + litem->item.flag &= ~UI_ITEM_MIN; litem->w += 2 * style->boxspace; - litem->h += style->boxspace; + litem->h += 2 * style->boxspace; } static void ui_litem_layout_box(uiLayout *litem) @@ -2452,17 +2469,18 @@ static void ui_litem_layout_box(uiLayout *litem) h = litem->h; litem->x += style->boxspace; + litem->y -= style->boxspace; if (w != 0) litem->w -= 2 * style->boxspace; if (h != 0) litem->h -= 2 * style->boxspace; - ui_litem_layout_column(litem); + ui_litem_layout_column(litem, true); litem->x -= style->boxspace; litem->y -= style->boxspace; if (w != 0) litem->w += 2 * style->boxspace; - if (h != 0) litem->h += style->boxspace; + if (h != 0) litem->h += 2 * style->boxspace; /* roundbox around the sublayout */ but = box->roundbox; @@ -3115,7 +3133,7 @@ static void ui_item_estimate(uiItem *item) switch (litem->item.type) { case ITEM_LAYOUT_COLUMN: - ui_litem_estimate_column(litem); + ui_litem_estimate_column(litem, false); break; case ITEM_LAYOUT_COLUMN_FLOW: ui_litem_estimate_column_flow(litem); @@ -3170,7 +3188,9 @@ static void ui_item_align(uiLayout *litem, short nr) } else if (item->type == ITEM_LAYOUT_BOX) { box = (uiLayoutItemBx *)item; - box->roundbox->alignnr = nr; + if (!box->roundbox->alignnr) { + box->roundbox->alignnr = nr; + } } else if (((uiLayout *)item)->align) { ui_item_align((uiLayout *)item, nr); @@ -3212,7 +3232,7 @@ static void ui_item_layout(uiItem *item) switch (litem->item.type) { case ITEM_LAYOUT_COLUMN: - ui_litem_layout_column(litem); + ui_litem_layout_column(litem, false); break; case ITEM_LAYOUT_COLUMN_FLOW: ui_litem_layout_column_flow(litem); diff --git a/source/blender/makesdna/DNA_userdef_types.h b/source/blender/makesdna/DNA_userdef_types.h index 4247f0b430c..82a56af9386 100644 --- a/source/blender/makesdna/DNA_userdef_types.h +++ b/source/blender/makesdna/DNA_userdef_types.h @@ -467,9 +467,11 @@ typedef struct UserDef { int audioformat; int audiochannels; - int scrollback; /* console scrollback limit */ - int dpi; /* range 48-128? */ - char node_margin; /* node insert offset (aka auto-offset) margin, but might be useful for later stuff as well */ + int scrollback; /* console scrollback limit */ + int dpi; /* range 48-128? */ + float ui_scale; /* interface scale */ + int pad1; + char node_margin; /* node insert offset (aka auto-offset) margin, but might be useful for later stuff as well */ char pad2; short transopts; short menuthreshold1, menuthreshold2; diff --git a/source/blender/makesrna/intern/rna_userdef.c b/source/blender/makesrna/intern/rna_userdef.c index 7b6eb5fef47..4d70b87843a 100644 --- a/source/blender/makesrna/intern/rna_userdef.c +++ b/source/blender/makesrna/intern/rna_userdef.c @@ -138,23 +138,11 @@ static void rna_userdef_update(Main *UNUSED(bmain), Scene *UNUSED(scene), Pointe } /* also used by buffer swap switching */ -static void rna_userdef_dpi_update(Main *UNUSED(bmain), Scene *UNUSED(scene), PointerRNA *UNUSED(ptr)) +static void rna_userdef_dpi_update(Main *bmain, Scene *UNUSED(scene), PointerRNA *UNUSED(ptr)) { /* font's are stored at each DPI level, without this we can easy load 100's of fonts */ BLF_cache_clear(); - BKE_blender_userdef_refresh(); - WM_main_add_notifier(NC_WINDOW, NULL); /* full redraw */ - WM_main_add_notifier(NC_SCREEN | NA_EDITED, NULL); /* refresh region sizes */ -} - -static void rna_userdef_virtual_pixel_update(Main *bmain, Scene *UNUSED(scene), PointerRNA *UNUSED(ptr)) -{ - /* font's are stored at each DPI level, without this we can easy load 100's of fonts */ - BLF_cache_clear(); - - BKE_blender_userdef_refresh(); - /* force setting drawable again */ wmWindowManager *wm = bmain->wm.first; if (wm) { @@ -3325,6 +3313,12 @@ static void rna_def_userdef_view(BlenderRNA *brna) RNA_def_struct_ui_text(srna, "View & Controls", "Preferences related to viewing data"); /* View */ + prop = RNA_def_property(srna, "ui_scale", PROP_FLOAT, PROP_FACTOR); + RNA_def_property_ui_text(prop, "UI Scale", "Changes the size of the fonts and buttons in the interface"); + RNA_def_property_range(prop, 0.25f, 4.0f); + RNA_def_property_ui_range(prop, 0.5f, 2.0f, 1, 1); + RNA_def_property_float_default(prop, 1.0f); + RNA_def_property_update(prop, 0, "rna_userdef_dpi_update"); /* display */ prop = RNA_def_property(srna, "show_tooltips", PROP_BOOLEAN, PROP_NONE); @@ -3916,12 +3910,6 @@ static void rna_def_userdef_system(BlenderRNA *brna) {0, NULL, 0, NULL, NULL} }; - static EnumPropertyItem virtual_pixel_mode_items[] = { - {VIRTUAL_PIXEL_NATIVE, "NATIVE", 0, "Native", "Use native pixel size of the display"}, - {VIRTUAL_PIXEL_DOUBLE, "DOUBLE", 0, "Double", "Use double the native pixel size of the display"}, - {0, NULL, 0, NULL, NULL} - }; - srna = RNA_def_struct(brna, "UserPreferencesSystem", NULL); RNA_def_struct_sdna(srna, "UserDef"); RNA_def_struct_nested(brna, srna, "UserPreferences"); @@ -3936,16 +3924,8 @@ static void rna_def_userdef_system(BlenderRNA *brna) RNA_def_property_update(prop, NC_WINDOW, "rna_userdef_language_update"); prop = RNA_def_property(srna, "dpi", PROP_INT, PROP_NONE); - RNA_def_property_int_sdna(prop, NULL, "dpi"); - RNA_def_property_range(prop, 48, 144); + RNA_def_property_clear_flag(prop, PROP_EDITABLE); RNA_def_property_ui_text(prop, "DPI", "Font size and resolution for display"); - RNA_def_property_update(prop, 0, "rna_userdef_dpi_update"); - - prop = RNA_def_property(srna, "virtual_pixel_mode", PROP_ENUM, PROP_NONE); - RNA_def_property_enum_sdna(prop, NULL, "virtual_pixel"); - RNA_def_property_enum_items(prop, virtual_pixel_mode_items); - RNA_def_property_ui_text(prop, "Virtual Pixel Mode", "Modify the pixel size for hi-res devices"); - RNA_def_property_update(prop, 0, "rna_userdef_virtual_pixel_update"); prop = RNA_def_property(srna, "pixel_size", PROP_FLOAT, PROP_NONE); RNA_def_property_clear_flag(prop, PROP_EDITABLE); diff --git a/source/blender/windowmanager/CMakeLists.txt b/source/blender/windowmanager/CMakeLists.txt index b5c19534b15..e0ac19259f5 100644 --- a/source/blender/windowmanager/CMakeLists.txt +++ b/source/blender/windowmanager/CMakeLists.txt @@ -139,10 +139,6 @@ if(WITH_PYTHON) ../python ) add_definitions(-DWITH_PYTHON) - - if(WITH_PYTHON_SECURITY) - add_definitions(-DWITH_PYTHON_SECURITY) - endif() endif() if(WITH_GAMEENGINE) diff --git a/source/blender/windowmanager/intern/wm_files.c b/source/blender/windowmanager/intern/wm_files.c index e00f7691a2c..8da3210d06e 100644 --- a/source/blender/windowmanager/intern/wm_files.c +++ b/source/blender/windowmanager/intern/wm_files.c @@ -777,11 +777,6 @@ int wm_homefile_read( if (BLI_listbase_is_empty(&wmbase)) { wm_clear_default_size(C); } -#ifdef WITH_PYTHON_SECURITY - /* use alternative setting for security nuts - * otherwise we'd need to patch the binary blob - startup.blend.c */ - U.flag |= USER_SCRIPT_AUTOEXEC_DISABLE; -#endif } /* Load template preferences, diff --git a/source/blender/windowmanager/intern/wm_operators.c b/source/blender/windowmanager/intern/wm_operators.c index 988d009681d..3d747e45fde 100644 --- a/source/blender/windowmanager/intern/wm_operators.c +++ b/source/blender/windowmanager/intern/wm_operators.c @@ -1807,7 +1807,7 @@ static uiBlock *wm_block_create_splash(bContext *C, ARegion *ar, void *UNUSED(ar (U.pixelsize == 2) ? "splash_2x.png" : "splash.png"); ibuf_template = IMB_loadiffname(splash_filepath, IB_rect, NULL); if (ibuf_template) { - const int x_expect = ibuf_template->x; + const int x_expect = ibuf->x; const int y_expect = 230 * (int)U.pixelsize; /* don't cover the header text */ if (ibuf_template->x == x_expect && ibuf_template->y == y_expect) { diff --git a/source/blender/windowmanager/intern/wm_window.c b/source/blender/windowmanager/intern/wm_window.c index b6f1b431009..49fe3a1d015 100644 --- a/source/blender/windowmanager/intern/wm_window.c +++ b/source/blender/windowmanager/intern/wm_window.c @@ -80,6 +80,7 @@ #include "GPU_extensions.h" #include "GPU_init_exit.h" #include "GPU_immediate.h" +#include "BLF_api.h" #include "UI_resources.h" @@ -398,14 +399,39 @@ void wm_window_title(wmWindowManager *wm, wmWindow *win) } } -static float wm_window_get_virtual_pixelsize(void) +static void wm_window_set_dpi(wmWindow *win) { - return ((U.virtual_pixel == VIRTUAL_PIXEL_NATIVE) ? 1.0f : 2.0f); -} + int auto_dpi = GHOST_GetDPIHint(win->ghostwin); -float wm_window_pixelsize(wmWindow *win) -{ - return (GHOST_GetNativePixelSize(win->ghostwin) * wm_window_get_virtual_pixelsize()); + /* Lazily init UI scale size, preserving backwards compatibility by + * computing UI scale from ratio of previous DPI and auto DPI */ + if (U.ui_scale == 0) { + int virtual_pixel = (U.virtual_pixel == VIRTUAL_PIXEL_NATIVE) ? 1 : 2; + + if (U.dpi == 0) { + U.ui_scale = virtual_pixel; + } + else { + U.ui_scale = (virtual_pixel * U.dpi * 96.0f) / (auto_dpi * 72.0f); + } + + CLAMP(U.ui_scale, 0.25f, 4.0f); + } + + /* Blender's UI drawing assumes DPI 72 as a good default following macOS + * while Windows and Linux use DPI 96. GHOST assumes a default 96 so we + * remap the DPI to Blender's convention. */ + int dpi = auto_dpi * U.ui_scale * (72.0/96.0f); + + /* Automatically set larger pixel size for high DPI. */ + int pixelsize = MAX2(1, dpi / 54); + + /* Set user preferences globals for drawing, and for forward compatibility. */ + U.pixelsize = GHOST_GetNativePixelSize(win->ghostwin) * pixelsize; + U.dpi = dpi / pixelsize; + U.virtual_pixel = (pixelsize == 1) ? VIRTUAL_PIXEL_NATIVE : VIRTUAL_PIXEL_DOUBLE; + + BKE_blender_userdef_refresh(); } /* belongs to below */ @@ -480,10 +506,8 @@ static void wm_window_ghostwindow_add(wmWindowManager *wm, const char *title, wm glClear(GL_COLOR_BUFFER_BIT); } - /* displays with larger native pixels, like Macbook. Used to scale dpi with */ /* needed here, because it's used before it reads userdef */ - U.pixelsize = wm_window_pixelsize(win); - BKE_blender_userdef_refresh(); + wm_window_set_dpi(win); wm_window_swap_buffers(win); @@ -650,7 +674,6 @@ wmWindow *WM_window_open_temp(bContext *C, const rcti *rect_init, int type) Scene *scene = CTX_data_scene(C); const char *title; rcti rect = *rect_init; - const short px_virtual = (short)wm_window_get_virtual_pixelsize(); /* changes rect to fit within desktop */ wm_window_check_position(&rect); @@ -668,9 +691,8 @@ wmWindow *WM_window_open_temp(bContext *C, const rcti *rect_init, int type) win->posy = rect.ymin; } - /* multiply with virtual pixelsize, ghost handles native one (e.g. for retina) */ - win->sizex = BLI_rcti_size_x(&rect) * px_virtual; - win->sizey = BLI_rcti_size_y(&rect) * px_virtual; + win->sizex = BLI_rcti_size_x(&rect); + win->sizey = BLI_rcti_size_y(&rect); if (win->ghostwin) { wm_window_set_size(win, win->sizex, win->sizey); @@ -913,7 +935,7 @@ void wm_window_make_drawable(wmWindowManager *wm, wmWindow *win) { if (win != wm->windrawable && win->ghostwin) { // win->lmbut = 0; /* keeps hanging when mousepressed while other window opened */ - + wm->windrawable = win; if (G.debug & G_DEBUG_EVENTS) { printf("%s: set drawable %d\n", __func__, win->winid); @@ -924,8 +946,7 @@ void wm_window_make_drawable(wmWindowManager *wm, wmWindow *win) immActivate(); /* this can change per window */ - U.pixelsize = wm_window_pixelsize(win); - BKE_blender_userdef_refresh(); + wm_window_set_dpi(win); } } @@ -1124,6 +1145,8 @@ static int ghost_event_proc(GHOST_EventHandle evt, GHOST_TUserDataPtr C_void_ptr if (type == GHOST_kEventWindowSize) { WM_jobs_stop(wm, win->screen, NULL); } + + wm_window_set_dpi(win); /* win32: gives undefined window size when minimized */ if (state != GHOST_kWindowStateMinimized) { @@ -1208,7 +1231,19 @@ static int ghost_event_proc(GHOST_EventHandle evt, GHOST_TUserDataPtr C_void_ptr } break; } - + + case GHOST_kEventWindowDPIHintChanged: + { + wm_window_set_dpi(win); + /* font's are stored at each DPI level, without this we can easy load 100's of fonts */ + BLF_cache_clear(); + + BKE_blender_userdef_refresh(); + WM_main_add_notifier(NC_WINDOW, NULL); /* full redraw */ + WM_main_add_notifier(NC_SCREEN | NA_EDITED, NULL); /* refresh region sizes */ + break; + } + case GHOST_kEventOpenMainFile: { PointerRNA props_ptr; @@ -1289,10 +1324,9 @@ static int ghost_event_proc(GHOST_EventHandle evt, GHOST_TUserDataPtr C_void_ptr { // only update if the actual pixel size changes float prev_pixelsize = U.pixelsize; - U.pixelsize = wm_window_pixelsize(win); + wm_window_set_dpi(win); if (U.pixelsize != prev_pixelsize) { - BKE_blender_userdef_refresh(); BKE_icon_changed(win->screen->id.icon_id); // close all popups since they are positioned with the pixel diff --git a/source/blender/windowmanager/wm_window.h b/source/blender/windowmanager/wm_window.h index 5a45cf718ec..089e2994d3d 100644 --- a/source/blender/windowmanager/wm_window.h +++ b/source/blender/windowmanager/wm_window.h @@ -67,8 +67,6 @@ void wm_window_swap_buffers (wmWindow *win); void wm_window_set_swap_interval(wmWindow *win, int interval); bool wm_window_get_swap_interval(wmWindow *win, int *intervalOut); -float wm_window_pixelsize(wmWindow *win); - void wm_get_cursor_position (wmWindow *win, int *x, int *y); void wm_cursor_position_from_ghost (wmWindow *win, int *x, int *y); void wm_cursor_position_to_ghost (wmWindow *win, int *x, int *y); |