Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
path: root/intern
diff options
context:
space:
mode:
Diffstat (limited to 'intern')
-rw-r--r--intern/cycles/blender/addon/properties.py6
-rw-r--r--intern/cycles/blender/blender_mesh.cpp22
-rw-r--r--intern/cycles/blender/blender_sync.cpp49
-rw-r--r--intern/cycles/blender/blender_util.h28
-rw-r--r--intern/cycles/kernel/CMakeLists.txt1
-rw-r--r--intern/cycles/kernel/bvh/bvh.h157
-rw-r--r--intern/cycles/kernel/bvh/bvh_shadow_all.h16
-rw-r--r--intern/cycles/kernel/bvh/bvh_types.h73
-rw-r--r--intern/cycles/kernel/bvh/bvh_volume_all.h5
-rw-r--r--intern/cycles/kernel/bvh/qbvh_shadow_all.h22
-rw-r--r--intern/cycles/kernel/bvh/qbvh_volume.h3
-rw-r--r--intern/cycles/kernel/bvh/qbvh_volume_all.h12
-rw-r--r--intern/cycles/kernel/kernel_shadow.h14
-rw-r--r--intern/cycles/kernel/kernel_types.h2
-rw-r--r--intern/cycles/kernel/split/kernel_background_buffer_update.h3
-rw-r--r--intern/cycles/kernel/split/kernel_data_init.h3
-rw-r--r--intern/cycles/kernel/split/kernel_holdout_emission_blurring_pathtermination_ao.h3
-rw-r--r--intern/cycles/kernel/split/kernel_next_iteration_setup.h2
-rw-r--r--intern/cycles/render/image.cpp6
-rw-r--r--intern/cycles/render/mesh.cpp6
-rw-r--r--intern/cycles/render/mesh_subdivision.cpp40
-rw-r--r--intern/ghost/intern/GHOST_ContextCGL.h2
-rw-r--r--intern/ghost/intern/GHOST_ContextCGL.mm88
-rw-r--r--intern/ghost/intern/GHOST_SystemCocoa.mm2
-rw-r--r--intern/ghost/intern/GHOST_SystemWin32.cpp2
-rw-r--r--intern/ghost/intern/GHOST_WindowCocoa.h4
-rw-r--r--intern/ghost/intern/GHOST_WindowCocoa.mm5
-rw-r--r--intern/mikktspace/mikktspace.c11
28 files changed, 358 insertions, 229 deletions
diff --git a/intern/cycles/blender/addon/properties.py b/intern/cycles/blender/addon/properties.py
index 938794f09ec..0c1784f8a3c 100644
--- a/intern/cycles/blender/addon/properties.py
+++ b/intern/cycles/blender/addon/properties.py
@@ -367,14 +367,14 @@ class CyclesRenderSettings(bpy.types.PropertyGroup):
cls.dicing_rate = FloatProperty(
name="Dicing Rate",
description="Size of a micropolygon in pixels",
- min=0.1, max=1000.0,
+ min=0.1, max=1000.0, soft_min=0.5,
default=1.0,
subtype="PIXEL"
)
cls.preview_dicing_rate = FloatProperty(
name="Preview Dicing Rate",
description="Size of a micropolygon in pixels during preview render",
- min=0.1, max=1000.0,
+ min=0.1, max=1000.0, soft_min=0.5,
default=8.0,
subtype="PIXEL"
)
@@ -1011,7 +1011,7 @@ class CyclesObjectSettings(bpy.types.PropertyGroup):
cls.dicing_rate = FloatProperty(
name="Dicing Scale",
description="Multiplier for scene dicing rate (located in the Geometry Panel)",
- min=0.1, max=1000.0,
+ min=0.1, max=1000.0, soft_min=0.5,
default=1.0,
)
diff --git a/intern/cycles/blender/blender_mesh.cpp b/intern/cycles/blender/blender_mesh.cpp
index c33bc4c263f..ff1d49ffd12 100644
--- a/intern/cycles/blender/blender_mesh.cpp
+++ b/intern/cycles/blender/blender_mesh.cpp
@@ -606,7 +606,7 @@ static void create_mesh(Scene *scene,
int numtris = 0;
int numcorners = 0;
int numngons = 0;
- bool use_loop_normals = b_mesh.use_auto_smooth();
+ bool use_loop_normals = b_mesh.use_auto_smooth() && (mesh->subdivision_type != Mesh::SUBDIVISION_CATMULL_CLARK);
BL::Mesh::vertices_iterator v;
BL::Mesh::tessfaces_iterator f;
@@ -959,25 +959,7 @@ Mesh *BlenderSync::sync_mesh(BL::Object& b_ob,
bool need_undeformed = mesh->need_attribute(scene, ATTR_STD_GENERATED);
- mesh->subdivision_type = Mesh::SUBDIVISION_NONE;
-
- PointerRNA cobj = RNA_pointer_get(&b_ob.ptr, "cycles");
-
- if(cobj.data && b_ob.modifiers.length() > 0 && experimental) {
- BL::Modifier mod = b_ob.modifiers[b_ob.modifiers.length()-1];
- bool enabled = preview ? mod.show_viewport() : mod.show_render();
-
- if(enabled && mod.type() == BL::Modifier::type_SUBSURF && RNA_boolean_get(&cobj, "use_adaptive_subdivision")) {
- BL::SubsurfModifier subsurf(mod);
-
- if(subsurf.subdivision_type() == BL::SubsurfModifier::subdivision_type_CATMULL_CLARK) {
- mesh->subdivision_type = Mesh::SUBDIVISION_CATMULL_CLARK;
- }
- else {
- mesh->subdivision_type = Mesh::SUBDIVISION_LINEAR;
- }
- }
- }
+ mesh->subdivision_type = object_subdivision_type(b_ob, preview, experimental);
BL::Mesh b_mesh = object_to_mesh(b_data, b_ob, b_scene, true, !preview, need_undeformed, mesh->subdivision_type);
diff --git a/intern/cycles/blender/blender_sync.cpp b/intern/cycles/blender/blender_sync.cpp
index be395b9f253..e77cc122cc5 100644
--- a/intern/cycles/blender/blender_sync.cpp
+++ b/intern/cycles/blender/blender_sync.cpp
@@ -102,26 +102,6 @@ bool BlenderSync::sync_recalc()
if(b_lamp->is_updated() || (b_lamp->node_tree() && b_lamp->node_tree().is_updated()))
shader_map.set_recalc(*b_lamp);
- BL::BlendData::objects_iterator b_ob;
-
- for(b_data.objects.begin(b_ob); b_ob != b_data.objects.end(); ++b_ob) {
- if(b_ob->is_updated()) {
- object_map.set_recalc(*b_ob);
- light_map.set_recalc(*b_ob);
- }
-
- if(object_is_mesh(*b_ob)) {
- if(b_ob->is_updated_data() || b_ob->data().is_updated()) {
- BL::ID key = BKE_object_is_modified(*b_ob)? *b_ob: b_ob->data();
- mesh_map.set_recalc(key);
- }
- }
- else if(object_is_light(*b_ob)) {
- if(b_ob->is_updated_data() || b_ob->data().is_updated())
- light_map.set_recalc(*b_ob);
- }
- }
-
bool dicing_prop_changed = false;
if(experimental) {
@@ -143,21 +123,36 @@ bool BlenderSync::sync_recalc()
}
}
+ BL::BlendData::objects_iterator b_ob;
+
+ for(b_data.objects.begin(b_ob); b_ob != b_data.objects.end(); ++b_ob) {
+ if(b_ob->is_updated()) {
+ object_map.set_recalc(*b_ob);
+ light_map.set_recalc(*b_ob);
+ }
+
+ if(object_is_mesh(*b_ob)) {
+ if(b_ob->is_updated_data() || b_ob->data().is_updated() ||
+ (dicing_prop_changed && object_subdivision_type(*b_ob, preview, experimental) != Mesh::SUBDIVISION_NONE))
+ {
+ BL::ID key = BKE_object_is_modified(*b_ob)? *b_ob: b_ob->data();
+ mesh_map.set_recalc(key);
+ }
+ }
+ else if(object_is_light(*b_ob)) {
+ if(b_ob->is_updated_data() || b_ob->data().is_updated())
+ light_map.set_recalc(*b_ob);
+ }
+ }
+
BL::BlendData::meshes_iterator b_mesh;
for(b_data.meshes.begin(b_mesh); b_mesh != b_data.meshes.end(); ++b_mesh) {
if(b_mesh->is_updated()) {
mesh_map.set_recalc(*b_mesh);
}
- else if(dicing_prop_changed) {
- PointerRNA cmesh = RNA_pointer_get(&b_mesh->ptr, "cycles");
-
- if(RNA_enum_get(&cmesh, "subdivision_type"))
- mesh_map.set_recalc(*b_mesh);
- }
}
-
BL::BlendData::worlds_iterator b_world;
for(b_data.worlds.begin(b_world); b_world != b_data.worlds.end(); ++b_world) {
diff --git a/intern/cycles/blender/blender_util.h b/intern/cycles/blender/blender_util.h
index 348cc5edce8..ba696a83867 100644
--- a/intern/cycles/blender/blender_util.h
+++ b/intern/cycles/blender/blender_util.h
@@ -17,6 +17,8 @@
#ifndef __BLENDER_UTIL_H__
#define __BLENDER_UTIL_H__
+#include "mesh.h"
+
#include "util_map.h"
#include "util_path.h"
#include "util_set.h"
@@ -55,11 +57,10 @@ static inline BL::Mesh object_to_mesh(BL::BlendData& data,
BL::Modifier subsurf_mod = object.modifiers[object.modifiers.length()-1];
subsurf_mod_show_render = subsurf_mod.show_render();
- subsurf_mod_show_viewport = subsurf_mod.show_render();
+ subsurf_mod_show_viewport = subsurf_mod.show_viewport();
subsurf_mod.show_render(false);
subsurf_mod.show_viewport(false);
-
}
BL::Mesh me = data.meshes.new_from_object(scene, object, apply_modifiers, (render)? 2: 1, false, calc_undeformed);
@@ -561,6 +562,29 @@ static inline BL::DomainFluidSettings object_fluid_domain_find(BL::Object b_ob)
return BL::DomainFluidSettings(PointerRNA_NULL);
}
+static inline Mesh::SubdivisionType object_subdivision_type(BL::Object& b_ob, bool preview, bool experimental)
+{
+ PointerRNA cobj = RNA_pointer_get(&b_ob.ptr, "cycles");
+
+ if(cobj.data && b_ob.modifiers.length() > 0 && experimental) {
+ BL::Modifier mod = b_ob.modifiers[b_ob.modifiers.length()-1];
+ bool enabled = preview ? mod.show_viewport() : mod.show_render();
+
+ if(enabled && mod.type() == BL::Modifier::type_SUBSURF && RNA_boolean_get(&cobj, "use_adaptive_subdivision")) {
+ BL::SubsurfModifier subsurf(mod);
+
+ if(subsurf.subdivision_type() == BL::SubsurfModifier::subdivision_type_CATMULL_CLARK) {
+ return Mesh::SUBDIVISION_CATMULL_CLARK;
+ }
+ else {
+ return Mesh::SUBDIVISION_LINEAR;
+ }
+ }
+ }
+
+ return Mesh::SUBDIVISION_NONE;
+}
+
/* ID Map
*
* Utility class to keep in sync with blender data.
diff --git a/intern/cycles/kernel/CMakeLists.txt b/intern/cycles/kernel/CMakeLists.txt
index 3c37bc0b045..06089b4014a 100644
--- a/intern/cycles/kernel/CMakeLists.txt
+++ b/intern/cycles/kernel/CMakeLists.txt
@@ -34,6 +34,7 @@ set(SRC_BVH_HEADERS
bvh/bvh_shadow_all.h
bvh/bvh_subsurface.h
bvh/bvh_traversal.h
+ bvh/bvh_types.h
bvh/bvh_volume.h
bvh/bvh_volume_all.h
bvh/qbvh_nodes.h
diff --git a/intern/cycles/kernel/bvh/bvh.h b/intern/cycles/kernel/bvh/bvh.h
index 59881738195..85bfd931e6e 100644
--- a/intern/cycles/kernel/bvh/bvh.h
+++ b/intern/cycles/kernel/bvh/bvh.h
@@ -28,54 +28,7 @@
CCL_NAMESPACE_BEGIN
-/* Don't inline intersect functions on GPU, this is faster */
-#ifdef __KERNEL_GPU__
-# define ccl_device_intersect ccl_device_noinline
-#else
-# define ccl_device_intersect ccl_device_inline
-#endif
-
-/* bottom-most stack entry, indicating the end of traversal */
-#define ENTRYPOINT_SENTINEL 0x76543210
-
-/* 64 object BVH + 64 mesh BVH + 64 object node splitting */
-#define BVH_STACK_SIZE 192
-#define BVH_QSTACK_SIZE 384
-
-/* BVH intersection function variations */
-
-#define BVH_INSTANCING 1
-#define BVH_MOTION 2
-#define BVH_HAIR 4
-#define BVH_HAIR_MINIMUM_WIDTH 8
-
-#define BVH_NAME_JOIN(x,y) x ## _ ## y
-#define BVH_NAME_EVAL(x,y) BVH_NAME_JOIN(x,y)
-#define BVH_FUNCTION_FULL_NAME(prefix) BVH_NAME_EVAL(prefix, BVH_FUNCTION_NAME)
-
-#define BVH_FEATURE(f) (((BVH_FUNCTION_FEATURES) & (f)) != 0)
-
-/* Debugging heleprs */
-#ifdef __KERNEL_DEBUG__
-# define BVH_DEBUG_INIT() \
- do { \
- isect->num_traversal_steps = 0; \
- isect->num_traversed_instances = 0; \
- } while(0)
-# define BVH_DEBUG_NEXT_STEP() \
- do { \
- ++isect->num_traversal_steps; \
- } while(0)
-# define BVH_DEBUG_NEXT_INSTANCE() \
- do { \
- ++isect->num_traversed_instances; \
- } while(0)
-#else /* __KERNEL_DEBUG__ */
-# define BVH_DEBUG_INIT()
-# define BVH_DEBUG_NEXT_STEP()
-# define BVH_DEBUG_NEXT_INSTANCE()
-#endif /* __KERNEL_DEBUG__ */
-
+#include "bvh_types.h"
/* Common QBVH functions. */
#ifdef __QBVH__
@@ -120,13 +73,13 @@ CCL_NAMESPACE_BEGIN
# define BVH_FUNCTION_NAME bvh_intersect_subsurface
# define BVH_FUNCTION_FEATURES BVH_HAIR
# include "bvh_subsurface.h"
-#endif
-#if defined(__SUBSURFACE__) && defined(__OBJECT_MOTION__)
-# define BVH_FUNCTION_NAME bvh_intersect_subsurface_motion
-# define BVH_FUNCTION_FEATURES BVH_MOTION|BVH_HAIR
-# include "bvh_subsurface.h"
-#endif
+# if defined(__OBJECT_MOTION__)
+# define BVH_FUNCTION_NAME bvh_intersect_subsurface_motion
+# define BVH_FUNCTION_FEATURES BVH_MOTION|BVH_HAIR
+# include "bvh_subsurface.h"
+# endif
+#endif /* __SUBSURFACE__ */
/* Volume BVH traversal */
@@ -134,19 +87,19 @@ CCL_NAMESPACE_BEGIN
# define BVH_FUNCTION_NAME bvh_intersect_volume
# define BVH_FUNCTION_FEATURES BVH_HAIR
# include "bvh_volume.h"
-#endif
-
-#if defined(__VOLUME__) && defined(__INSTANCING__)
-# define BVH_FUNCTION_NAME bvh_intersect_volume_instancing
-# define BVH_FUNCTION_FEATURES BVH_INSTANCING|BVH_HAIR
-# include "bvh_volume.h"
-#endif
-#if defined(__VOLUME__) && defined(__OBJECT_MOTION__)
-# define BVH_FUNCTION_NAME bvh_intersect_volume_motion
-# define BVH_FUNCTION_FEATURES BVH_INSTANCING|BVH_MOTION|BVH_HAIR
-# include "bvh_volume.h"
-#endif
+# if defined(__INSTANCING__)
+# define BVH_FUNCTION_NAME bvh_intersect_volume_instancing
+# define BVH_FUNCTION_FEATURES BVH_INSTANCING|BVH_HAIR
+# include "bvh_volume.h"
+# endif
+
+# if defined(__OBJECT_MOTION__)
+# define BVH_FUNCTION_NAME bvh_intersect_volume_motion
+# define BVH_FUNCTION_FEATURES BVH_INSTANCING|BVH_MOTION|BVH_HAIR
+# include "bvh_volume.h"
+# endif
+#endif /* __VOLUME__ */
/* Record all intersections - Shadow BVH traversal */
@@ -154,31 +107,31 @@ CCL_NAMESPACE_BEGIN
# define BVH_FUNCTION_NAME bvh_intersect_shadow_all
# define BVH_FUNCTION_FEATURES 0
# include "bvh_shadow_all.h"
-#endif
-
-#if defined(__SHADOW_RECORD_ALL__) && defined(__INSTANCING__)
-# define BVH_FUNCTION_NAME bvh_intersect_shadow_all_instancing
-# define BVH_FUNCTION_FEATURES BVH_INSTANCING
-# include "bvh_shadow_all.h"
-#endif
-#if defined(__SHADOW_RECORD_ALL__) && defined(__HAIR__)
-# define BVH_FUNCTION_NAME bvh_intersect_shadow_all_hair
-# define BVH_FUNCTION_FEATURES BVH_INSTANCING|BVH_HAIR
-# include "bvh_shadow_all.h"
-#endif
-
-#if defined(__SHADOW_RECORD_ALL__) && defined(__OBJECT_MOTION__)
-# define BVH_FUNCTION_NAME bvh_intersect_shadow_all_motion
-# define BVH_FUNCTION_FEATURES BVH_INSTANCING|BVH_MOTION
-# include "bvh_shadow_all.h"
-#endif
-
-#if defined(__SHADOW_RECORD_ALL__) && defined(__HAIR__) && defined(__OBJECT_MOTION__)
-# define BVH_FUNCTION_NAME bvh_intersect_shadow_all_hair_motion
-# define BVH_FUNCTION_FEATURES BVH_INSTANCING|BVH_HAIR|BVH_MOTION
-# include "bvh_shadow_all.h"
-#endif
+# if defined(__INSTANCING__)
+# define BVH_FUNCTION_NAME bvh_intersect_shadow_all_instancing
+# define BVH_FUNCTION_FEATURES BVH_INSTANCING
+# include "bvh_shadow_all.h"
+# endif
+
+# if defined(__HAIR__)
+# define BVH_FUNCTION_NAME bvh_intersect_shadow_all_hair
+# define BVH_FUNCTION_FEATURES BVH_INSTANCING|BVH_HAIR
+# include "bvh_shadow_all.h"
+# endif
+
+# if defined(__OBJECT_MOTION__)
+# define BVH_FUNCTION_NAME bvh_intersect_shadow_all_motion
+# define BVH_FUNCTION_FEATURES BVH_INSTANCING|BVH_MOTION
+# include "bvh_shadow_all.h"
+# endif
+
+# if defined(__HAIR__) && defined(__OBJECT_MOTION__)
+# define BVH_FUNCTION_NAME bvh_intersect_shadow_all_hair_motion
+# define BVH_FUNCTION_FEATURES BVH_INSTANCING|BVH_HAIR|BVH_MOTION
+# include "bvh_shadow_all.h"
+# endif
+#endif /* __SHADOW_RECORD_ALL__ */
/* Record all intersections - Volume BVH traversal */
@@ -186,19 +139,19 @@ CCL_NAMESPACE_BEGIN
# define BVH_FUNCTION_NAME bvh_intersect_volume_all
# define BVH_FUNCTION_FEATURES BVH_HAIR
# include "bvh_volume_all.h"
-#endif
-#if defined(__VOLUME_RECORD_ALL__) && defined(__INSTANCING__)
-# define BVH_FUNCTION_NAME bvh_intersect_volume_all_instancing
-# define BVH_FUNCTION_FEATURES BVH_INSTANCING|BVH_HAIR
-# include "bvh_volume_all.h"
-#endif
-
-#if defined(__VOLUME_RECORD_ALL__) && defined(__OBJECT_MOTION__)
-# define BVH_FUNCTION_NAME bvh_intersect_volume_all_motion
-# define BVH_FUNCTION_FEATURES BVH_INSTANCING|BVH_MOTION|BVH_HAIR
-# include "bvh_volume_all.h"
-#endif
+# if defined(__INSTANCING__)
+# define BVH_FUNCTION_NAME bvh_intersect_volume_all_instancing
+# define BVH_FUNCTION_FEATURES BVH_INSTANCING|BVH_HAIR
+# include "bvh_volume_all.h"
+# endif
+
+# if defined(__OBJECT_MOTION__)
+# define BVH_FUNCTION_NAME bvh_intersect_volume_all_motion
+# define BVH_FUNCTION_FEATURES BVH_INSTANCING|BVH_MOTION|BVH_HAIR
+# include "bvh_volume_all.h"
+# endif
+#endif /* __VOLUME_RECORD_ALL__ */
#undef BVH_FEATURE
#undef BVH_NAME_JOIN
diff --git a/intern/cycles/kernel/bvh/bvh_shadow_all.h b/intern/cycles/kernel/bvh/bvh_shadow_all.h
index f9da2a3caaa..294362ea995 100644
--- a/intern/cycles/kernel/bvh/bvh_shadow_all.h
+++ b/intern/cycles/kernel/bvh/bvh_shadow_all.h
@@ -108,7 +108,7 @@ bool BVH_FUNCTION_FULL_NAME(BVH)(KernelGlobals *kg,
do {
/* traverse internal nodes */
while(node_addr >= 0 && node_addr != ENTRYPOINT_SENTINEL) {
- int node_addr_ahild1, traverse_mask;
+ int node_addr_child1, traverse_mask;
float dist[2];
float4 cnodes = kernel_tex_fetch(__bvh_nodes, node_addr+0);
@@ -141,25 +141,25 @@ bool BVH_FUNCTION_FULL_NAME(BVH)(KernelGlobals *kg,
#endif // __KERNEL_SSE2__
node_addr = __float_as_int(cnodes.z);
- node_addr_ahild1 = __float_as_int(cnodes.w);
+ node_addr_child1 = __float_as_int(cnodes.w);
if(traverse_mask == 3) {
/* Both children were intersected, push the farther one. */
bool is_closest_child1 = (dist[1] < dist[0]);
if(is_closest_child1) {
int tmp = node_addr;
- node_addr = node_addr_ahild1;
- node_addr_ahild1 = tmp;
+ node_addr = node_addr_child1;
+ node_addr_child1 = tmp;
}
++stack_ptr;
kernel_assert(stack_ptr < BVH_STACK_SIZE);
- traversal_stack[stack_ptr] = node_addr_ahild1;
+ traversal_stack[stack_ptr] = node_addr_child1;
}
else {
/* One child was intersected. */
if(traverse_mask == 2) {
- node_addr = node_addr_ahild1;
+ node_addr = node_addr_child1;
}
else if(traverse_mask == 0) {
/* Neither child was intersected. */
@@ -343,6 +343,7 @@ bool BVH_FUNCTION_FULL_NAME(BVH)(KernelGlobals *kg,
if(stack_ptr >= 0) {
kernel_assert(object != OBJECT_NONE);
+ /* Instance pop. */
if(num_hits_in_instance) {
float t_fac;
@@ -355,8 +356,9 @@ bool BVH_FUNCTION_FULL_NAME(BVH)(KernelGlobals *kg,
triangle_intersect_precalc(dir, &isect_precalc);
/* scale isect->t to adjust for instancing */
- for(int i = 0; i < num_hits_in_instance; i++)
+ for(int i = 0; i < num_hits_in_instance; i++) {
(isect_array-i-1)->t *= t_fac;
+ }
}
else {
float ignore_t = FLT_MAX;
diff --git a/intern/cycles/kernel/bvh/bvh_types.h b/intern/cycles/kernel/bvh/bvh_types.h
new file mode 100644
index 00000000000..bcba6e65fe5
--- /dev/null
+++ b/intern/cycles/kernel/bvh/bvh_types.h
@@ -0,0 +1,73 @@
+/*
+ * Adapted from code Copyright 2009-2010 NVIDIA Corporation
+ * Modifications Copyright 2011, Blender Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef __BVH_TYPES__
+#define __BVH_TYPES__
+
+CCL_NAMESPACE_BEGIN
+
+/* Don't inline intersect functions on GPU, this is faster */
+#ifdef __KERNEL_GPU__
+# define ccl_device_intersect ccl_device_noinline
+#else
+# define ccl_device_intersect ccl_device_inline
+#endif
+
+/* bottom-most stack entry, indicating the end of traversal */
+#define ENTRYPOINT_SENTINEL 0x76543210
+
+/* 64 object BVH + 64 mesh BVH + 64 object node splitting */
+#define BVH_STACK_SIZE 192
+#define BVH_QSTACK_SIZE 384
+
+/* BVH intersection function variations */
+
+#define BVH_INSTANCING 1
+#define BVH_MOTION 2
+#define BVH_HAIR 4
+#define BVH_HAIR_MINIMUM_WIDTH 8
+
+#define BVH_NAME_JOIN(x,y) x ## _ ## y
+#define BVH_NAME_EVAL(x,y) BVH_NAME_JOIN(x,y)
+#define BVH_FUNCTION_FULL_NAME(prefix) BVH_NAME_EVAL(prefix, BVH_FUNCTION_NAME)
+
+#define BVH_FEATURE(f) (((BVH_FUNCTION_FEATURES) & (f)) != 0)
+
+/* Debugging heleprs */
+#ifdef __KERNEL_DEBUG__
+# define BVH_DEBUG_INIT() \
+ do { \
+ isect->num_traversal_steps = 0; \
+ isect->num_traversed_instances = 0; \
+ } while(0)
+# define BVH_DEBUG_NEXT_STEP() \
+ do { \
+ ++isect->num_traversal_steps; \
+ } while(0)
+# define BVH_DEBUG_NEXT_INSTANCE() \
+ do { \
+ ++isect->num_traversed_instances; \
+ } while(0)
+#else /* __KERNEL_DEBUG__ */
+# define BVH_DEBUG_INIT()
+# define BVH_DEBUG_NEXT_STEP()
+# define BVH_DEBUG_NEXT_INSTANCE()
+#endif /* __KERNEL_DEBUG__ */
+
+CCL_NAMESPACE_END
+
+#endif /* __BVH_TYPES__ */
diff --git a/intern/cycles/kernel/bvh/bvh_volume_all.h b/intern/cycles/kernel/bvh/bvh_volume_all.h
index 1f6515c9862..529848ebe7b 100644
--- a/intern/cycles/kernel/bvh/bvh_volume_all.h
+++ b/intern/cycles/kernel/bvh/bvh_volume_all.h
@@ -99,7 +99,7 @@ uint BVH_FUNCTION_FULL_NAME(BVH)(KernelGlobals *kg,
ssef tsplat(0.0f, 0.0f, -isect_t, -isect_t);
gen_idirsplat_swap(pn, shuf_identity, shuf_swap, idir, idirsplat, shufflexyz);
-#endif
+#endif /* __KERNEL_SSE2__ */
IsectPrecalc isect_precalc;
triangle_intersect_precalc(dir, &isect_precalc);
@@ -334,6 +334,7 @@ uint BVH_FUNCTION_FULL_NAME(BVH)(KernelGlobals *kg,
if(stack_ptr >= 0) {
kernel_assert(object != OBJECT_NONE);
+ /* Instance pop. */
if(num_hits_in_instance) {
float t_fac;
# if BVH_FEATURE(BVH_MOTION)
@@ -377,7 +378,7 @@ uint BVH_FUNCTION_FULL_NAME(BVH)(KernelGlobals *kg,
node_addr = traversal_stack[stack_ptr];
--stack_ptr;
}
-#endif /* FEATURE(BVH_MOTION) */
+#endif /* FEATURE(BVH_INSTANCING) */
} while(node_addr != ENTRYPOINT_SENTINEL);
return num_hits;
diff --git a/intern/cycles/kernel/bvh/qbvh_shadow_all.h b/intern/cycles/kernel/bvh/qbvh_shadow_all.h
index 5043965c979..3136c495b38 100644
--- a/intern/cycles/kernel/bvh/qbvh_shadow_all.h
+++ b/intern/cycles/kernel/bvh/qbvh_shadow_all.h
@@ -40,6 +40,7 @@ ccl_device bool BVH_FUNCTION_FULL_NAME(QBVH)(KernelGlobals *kg,
uint *num_hits)
{
/* TODO(sergey):
+ * - Test if pushing distance on the stack helps.
* - Likely and unlikely for if() statements.
* - Test restrict attribute for pointers.
*/
@@ -77,7 +78,7 @@ ccl_device bool BVH_FUNCTION_FULL_NAME(QBVH)(KernelGlobals *kg,
int num_hits_in_instance = 0;
#endif
- ssef tnear(0.0f), tfar(tmax);
+ ssef tnear(0.0f), tfar(isect_t);
#if BVH_FEATURE(BVH_HAIR)
sse3f dir4(ssef(dir.x), ssef(dir.y), ssef(dir.z));
#endif
@@ -125,12 +126,12 @@ ccl_device bool BVH_FUNCTION_FULL_NAME(QBVH)(KernelGlobals *kg,
#ifdef __KERNEL_AVX2__
P_idir4,
#endif
-# if BVH_FEATURE(BVH_HAIR) || !defined(__KERNEL_AVX2__)
+#if BVH_FEATURE(BVH_HAIR) || !defined(__KERNEL_AVX2__)
org4,
-# endif
-# if BVH_FEATURE(BVH_HAIR)
+#endif
+#if BVH_FEATURE(BVH_HAIR)
dir4,
-# endif
+#endif
idir4,
near_x, near_y, near_z,
far_x, far_y, far_z,
@@ -427,22 +428,21 @@ ccl_device bool BVH_FUNCTION_FULL_NAME(QBVH)(KernelGlobals *kg,
if(stack_ptr >= 0) {
kernel_assert(object != OBJECT_NONE);
+ /* Instance pop. */
if(num_hits_in_instance) {
float t_fac;
-
# if BVH_FEATURE(BVH_MOTION)
bvh_instance_motion_pop_factor(kg, object, ray, &P, &dir, &idir, &t_fac, &ob_itfm);
# else
bvh_instance_pop_factor(kg, object, ray, &P, &dir, &idir, &t_fac);
# endif
-
- /* scale isect->t to adjust for instancing */
- for(int i = 0; i < num_hits_in_instance; i++)
+ /* Scale isect->t to adjust for instancing. */
+ for(int i = 0; i < num_hits_in_instance; i++) {
(isect_array-i-1)->t *= t_fac;
+ }
}
else {
float ignore_t = FLT_MAX;
-
# if BVH_FEATURE(BVH_MOTION)
bvh_instance_motion_pop(kg, object, ray, &P, &dir, &idir, &ignore_t, &ob_itfm);
# else
@@ -456,7 +456,7 @@ ccl_device bool BVH_FUNCTION_FULL_NAME(QBVH)(KernelGlobals *kg,
if(idir.x >= 0.0f) { near_x = 0; far_x = 1; } else { near_x = 1; far_x = 0; }
if(idir.y >= 0.0f) { near_y = 2; far_y = 3; } else { near_y = 3; far_y = 2; }
if(idir.z >= 0.0f) { near_z = 4; far_z = 5; } else { near_z = 5; far_z = 4; }
- tfar = ssef(tmax);
+ tfar = ssef(isect_t);
# if BVH_FEATURE(BVH_HAIR)
dir4 = sse3f(ssef(dir.x), ssef(dir.y), ssef(dir.z));
# endif
diff --git a/intern/cycles/kernel/bvh/qbvh_volume.h b/intern/cycles/kernel/bvh/qbvh_volume.h
index 847a11d8ad4..aff9f559ab8 100644
--- a/intern/cycles/kernel/bvh/qbvh_volume.h
+++ b/intern/cycles/kernel/bvh/qbvh_volume.h
@@ -103,8 +103,9 @@ ccl_device bool BVH_FUNCTION_FULL_NAME(QBVH)(KernelGlobals *kg,
do {
/* Traverse internal nodes. */
while(node_addr >= 0 && node_addr != ENTRYPOINT_SENTINEL) {
-#ifdef __VISIBILITY_FLAG__
float4 inodes = kernel_tex_fetch(__bvh_nodes, node_addr+0);
+
+#ifdef __VISIBILITY_FLAG__
if((__float_as_uint(inodes.x) & visibility) == 0) {
/* Pop. */
node_addr = traversal_stack[stack_ptr].addr;
diff --git a/intern/cycles/kernel/bvh/qbvh_volume_all.h b/intern/cycles/kernel/bvh/qbvh_volume_all.h
index ab4b70085e8..5d9b2edb4ba 100644
--- a/intern/cycles/kernel/bvh/qbvh_volume_all.h
+++ b/intern/cycles/kernel/bvh/qbvh_volume_all.h
@@ -69,7 +69,7 @@ ccl_device uint BVH_FUNCTION_FULL_NAME(QBVH)(KernelGlobals *kg,
#ifndef __KERNEL_SSE41__
if(!isfinite(P.x)) {
- return false;
+ return 0;
}
#endif
@@ -107,8 +107,9 @@ ccl_device uint BVH_FUNCTION_FULL_NAME(QBVH)(KernelGlobals *kg,
do {
/* Traverse internal nodes. */
while(node_addr >= 0 && node_addr != ENTRYPOINT_SENTINEL) {
-#ifdef __VISIBILITY_FLAG__
float4 inodes = kernel_tex_fetch(__bvh_nodes, node_addr+0);
+
+#ifdef __VISIBILITY_FLAG__
if((__float_as_uint(inodes.x) & visibility) == 0) {
/* Pop. */
node_addr = traversal_stack[stack_ptr].addr;
@@ -405,7 +406,6 @@ ccl_device uint BVH_FUNCTION_FULL_NAME(QBVH)(KernelGlobals *kg,
# else
bvh_instance_pop_factor(kg, object, ray, &P, &dir, &idir, &t_fac);
# endif
- triangle_intersect_precalc(dir, &isect_precalc);
/* Scale isect->t to adjust for instancing. */
for(int i = 0; i < num_hits_in_instance; i++) {
(isect_array-i-1)->t *= t_fac;
@@ -418,9 +418,11 @@ ccl_device uint BVH_FUNCTION_FULL_NAME(QBVH)(KernelGlobals *kg,
# else
bvh_instance_pop(kg, object, ray, &P, &dir, &idir, &ignore_t);
# endif
- triangle_intersect_precalc(dir, &isect_precalc);
}
+ isect_t = tmax;
+ isect_array->t = isect_t;
+
if(idir.x >= 0.0f) { near_x = 0; far_x = 1; } else { near_x = 1; far_x = 0; }
if(idir.y >= 0.0f) { near_y = 2; far_y = 3; } else { near_y = 3; far_y = 2; }
if(idir.z >= 0.0f) { near_z = 4; far_z = 5; } else { near_z = 5; far_z = 4; }
@@ -438,8 +440,6 @@ ccl_device uint BVH_FUNCTION_FULL_NAME(QBVH)(KernelGlobals *kg,
# endif
triangle_intersect_precalc(dir, &isect_precalc);
- isect_t = tmax;
- isect_array->t = isect_t;
object = OBJECT_NONE;
node_addr = traversal_stack[stack_ptr].addr;
diff --git a/intern/cycles/kernel/kernel_shadow.h b/intern/cycles/kernel/kernel_shadow.h
index db2fc84834a..95b57404a77 100644
--- a/intern/cycles/kernel/kernel_shadow.h
+++ b/intern/cycles/kernel/kernel_shadow.h
@@ -125,14 +125,14 @@ ccl_device_inline bool shadow_blocked(KernelGlobals *kg, ShaderData *shadow_sd,
/* stop if all light is blocked */
if(is_zero(throughput)) {
- /* free dynamic storage */
return true;
}
/* move ray forward */
ray->P = shadow_sd->P;
- if(ray->t != FLT_MAX)
+ if(ray->t != FLT_MAX) {
ray->D = normalize_len(Pend - ray->P, &ray->t);
+ }
#ifdef __VOLUME__
/* exit/enter volume */
@@ -234,8 +234,9 @@ ccl_device_noinline bool shadow_blocked(KernelGlobals *kg,
return false;
}
- if(!shader_transparent_shadow(kg, isect))
+ if(!shader_transparent_shadow(kg, isect)) {
return true;
+ }
#ifdef __VOLUME__
/* attenuation between last surface and next surface */
@@ -258,13 +259,16 @@ ccl_device_noinline bool shadow_blocked(KernelGlobals *kg,
throughput *= shader_bsdf_transparency(kg, shadow_sd);
}
- if(is_zero(throughput))
+ /* stop if all light is blocked */
+ if(is_zero(throughput)) {
return true;
+ }
/* move ray forward */
ray->P = ray_offset(ccl_fetch(shadow_sd, P), -ccl_fetch(shadow_sd, Ng));
- if(ray->t != FLT_MAX)
+ if(ray->t != FLT_MAX) {
ray->D = normalize_len(Pend - ray->P, &ray->t);
+ }
#ifdef __VOLUME__
/* exit/enter volume */
diff --git a/intern/cycles/kernel/kernel_types.h b/intern/cycles/kernel/kernel_types.h
index 548bc1c1ccc..734b4462a91 100644
--- a/intern/cycles/kernel/kernel_types.h
+++ b/intern/cycles/kernel/kernel_types.h
@@ -829,7 +829,7 @@ typedef ccl_addr_space struct ShaderData {
ccl_soa_member(differential3, ray_dP);
#ifdef __OSL__
- struct KernelGlobals * osl_globals;
+ struct KernelGlobals *osl_globals;
struct PathState *osl_path_state;
#endif
} ShaderData;
diff --git a/intern/cycles/kernel/split/kernel_background_buffer_update.h b/intern/cycles/kernel/split/kernel_background_buffer_update.h
index f42d0a985bb..9bfa71c75ef 100644
--- a/intern/cycles/kernel/split/kernel_background_buffer_update.h
+++ b/intern/cycles/kernel/split/kernel_background_buffer_update.h
@@ -232,7 +232,8 @@ ccl_device char kernel_background_buffer_update(
#endif
ASSIGN_RAY_STATE(ray_state, ray_index, RAY_REGENERATED);
enqueue_flag = 1;
- } else {
+ }
+ else {
/* These rays do not participate in path-iteration. */
float4 L_rad = make_float4(0.0f, 0.0f, 0.0f, 0.0f);
/* Accumulate result in output buffer. */
diff --git a/intern/cycles/kernel/split/kernel_data_init.h b/intern/cycles/kernel/split/kernel_data_init.h
index e3dbc43757e..6e158d53d23 100644
--- a/intern/cycles/kernel/split/kernel_data_init.h
+++ b/intern/cycles/kernel/split/kernel_data_init.h
@@ -215,7 +215,8 @@ ccl_device void kernel_data_init(
#ifdef __KERNEL_DEBUG__
debug_data_init(&debugdata_coop[ray_index]);
#endif
- } else {
+ }
+ else {
/* These rays do not participate in path-iteration. */
float4 L_rad = make_float4(0.0f, 0.0f, 0.0f, 0.0f);
/* Accumulate result in output buffer. */
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 78dada82d89..435d1171d5c 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
@@ -212,7 +212,8 @@ ccl_device void kernel_holdout_emission_blurring_pathtermination_ao(
if(terminate >= probability) {
ASSIGN_RAY_STATE(ray_state, ray_index, RAY_UPDATE_BUFFER);
*enqueue_flag = 1;
- } else {
+ }
+ else {
throughput_coop[ray_index] = throughput/probability;
}
}
diff --git a/intern/cycles/kernel/split/kernel_next_iteration_setup.h b/intern/cycles/kernel/split/kernel_next_iteration_setup.h
index 74da80b52cc..816f3a6fbff 100644
--- a/intern/cycles/kernel/split/kernel_next_iteration_setup.h
+++ b/intern/cycles/kernel/split/kernel_next_iteration_setup.h
@@ -126,7 +126,7 @@ ccl_device char kernel_next_iteration_setup(
if(IS_STATE(ray_state, ray_index, RAY_ACTIVE)) {
ccl_global float3 *throughput = &throughput_coop[ray_index];
ccl_global Ray *ray = &Ray_coop[ray_index];
- ccl_global RNG* rng = &rng_coop[ray_index];
+ ccl_global RNG *rng = &rng_coop[ray_index];
state = &PathState_coop[ray_index];
L = &PathRadiance_coop[ray_index];
diff --git a/intern/cycles/render/image.cpp b/intern/cycles/render/image.cpp
index b387c2c2f98..7e24664b3fe 100644
--- a/intern/cycles/render/image.cpp
+++ b/intern/cycles/render/image.cpp
@@ -587,8 +587,7 @@ bool ImageManager::file_load_float_image(Image *img, ImageDataType type, device_
}
if(depth <= 1) {
- int scanlinesize = width*components*sizeof(float);
-
+ size_t scanlinesize = ((size_t)width)*components*sizeof(float);
in->read_image(TypeDesc::FLOAT,
(uchar*)readpixels + (height-1)*scanlinesize,
AutoStride,
@@ -696,8 +695,7 @@ bool ImageManager::file_load_half_image(Image *img, ImageDataType type, device_v
}
if(depth <= 1) {
- int scanlinesize = width*components*sizeof(half);
-
+ size_t scanlinesize = ((size_t)width)*components*sizeof(half);
in->read_image(TypeDesc::HALF,
(uchar*)readpixels + (height-1)*scanlinesize,
AutoStride,
diff --git a/intern/cycles/render/mesh.cpp b/intern/cycles/render/mesh.cpp
index 2d297c33446..3eff35bae9e 100644
--- a/intern/cycles/render/mesh.cpp
+++ b/intern/cycles/render/mesh.cpp
@@ -601,6 +601,12 @@ void Mesh::add_undisplaced()
/* copy verts */
size_t size = attr->buffer_size(this, (subdivision_type == SUBDIVISION_NONE) ? ATTR_PRIM_TRIANGLE : ATTR_PRIM_SUBD);
+
+ /* Center points for ngons aren't stored in Mesh::verts but are included in size since they will be
+ * calculated later, we subtract them from size here so we don't have an overflow while copying.
+ */
+ size -= num_ngons * attr->data_sizeof();
+
if(size) {
memcpy(data, verts.data(), size);
}
diff --git a/intern/cycles/render/mesh_subdivision.cpp b/intern/cycles/render/mesh_subdivision.cpp
index 3b4841f5b20..0ae5ff742c2 100644
--- a/intern/cycles/render/mesh_subdivision.cpp
+++ b/intern/cycles/render/mesh_subdivision.cpp
@@ -16,12 +16,14 @@
#include "mesh.h"
#include "attribute.h"
+#include "camera.h"
#include "subd_split.h"
#include "subd_patch.h"
#include "subd_patch_table.h"
#include "util_foreach.h"
+#include "util_algorithm.h"
CCL_NAMESPACE_BEGIN
@@ -177,7 +179,7 @@ public:
Far::TopologyRefinerFactory<Mesh>::Options(type, options));
/* adaptive refinement */
- int max_isolation = 10;
+ int max_isolation = calculate_max_isolation();
refiner->RefineAdaptive(Far::TopologyRefiner::AdaptiveOptions(max_isolation));
/* create patch table */
@@ -248,6 +250,42 @@ public:
}
}
+ int calculate_max_isolation()
+ {
+ /* loop over all edges to find longest in screen space */
+ const Far::TopologyLevel& level = refiner->GetLevel(0);
+ Transform objecttoworld = mesh->subd_params->objecttoworld;
+ Camera* cam = mesh->subd_params->camera;
+
+ float longest_edge = 0.0f;
+
+ for(size_t i = 0; i < level.GetNumEdges(); i++) {
+ Far::ConstIndexArray verts = level.GetEdgeVertices(i);
+
+ float3 a = mesh->verts[verts[0]];
+ float3 b = mesh->verts[verts[1]];
+
+ float edge_len;
+
+ if(cam) {
+ a = transform_point(&objecttoworld, a);
+ b = transform_point(&objecttoworld, b);
+
+ edge_len = len(a - b) / cam->world_to_raster_size((a + b) * 0.5f);
+ }
+ else {
+ edge_len = len(a - b);
+ }
+
+ longest_edge = max(longest_edge, edge_len);
+ }
+
+ /* calculate isolation level */
+ int isolation = (int)(log2f(max(longest_edge / mesh->subd_params->dicing_rate, 1.0f)) + 1.0f);
+
+ return min(isolation, 10);
+ }
+
friend struct OsdPatch;
friend class Mesh;
};
diff --git a/intern/ghost/intern/GHOST_ContextCGL.h b/intern/ghost/intern/GHOST_ContextCGL.h
index c2f1ce176ad..8186eaa759d 100644
--- a/intern/ghost/intern/GHOST_ContextCGL.h
+++ b/intern/ghost/intern/GHOST_ContextCGL.h
@@ -138,6 +138,8 @@ private:
//static CGLEWContext *s_cglewContext;
+ const bool m_debug;
+
/** The first created OpenGL context (for sharing display lists) */
static NSOpenGLContext *s_sharedOpenGLContext;
static int s_sharedCount;
diff --git a/intern/ghost/intern/GHOST_ContextCGL.mm b/intern/ghost/intern/GHOST_ContextCGL.mm
index 6a39d76e752..1ab0301f7b2 100644
--- a/intern/ghost/intern/GHOST_ContextCGL.mm
+++ b/intern/ghost/intern/GHOST_ContextCGL.mm
@@ -59,7 +59,8 @@ GHOST_ContextCGL::GHOST_ContextCGL(
int contextResetNotificationStrategy)
: GHOST_Context(stereoVisual, numOfAASamples),
m_openGLView(openGLView),
- m_openGLContext(nil)
+ m_openGLContext(nil),
+ m_debug(contextFlags)
{
assert(openGLView != nil);
@@ -186,27 +187,27 @@ GHOST_TSuccess GHOST_ContextCGL::updateDrawingContext()
static void makeAttribList(
std::vector<NSOpenGLPixelFormatAttribute>& attribs,
- bool coreProfile,
bool stereoVisual,
int numOfAASamples,
bool needAlpha,
- bool needStencil)
+ bool needStencil,
+ bool softwareGL)
{
+ attribs.clear();
+
attribs.push_back(NSOpenGLPFAOpenGLProfile);
attribs.push_back(coreProfile ? NSOpenGLProfileVersion3_2Core : NSOpenGLProfileVersionLegacy);
// Pixel Format Attributes for the windowed NSOpenGLContext
attribs.push_back(NSOpenGLPFADoubleBuffer);
- // Force software OpenGL, for debugging
- /* XXX jwilkins: fixed this to work on Intel macs? useful feature for Windows and Linux too?
- * Maybe a command line flag is better... */
- if (getenv("BLENDER_SOFTWAREGL")) {
+ if (softwareGL) {
attribs.push_back(NSOpenGLPFARendererID);
attribs.push_back(kCGLRendererGenericFloatID);
}
else {
attribs.push_back(NSOpenGLPFAAccelerated);
+ attribs.push_back(NSOpenGLPFANoRecovery);
}
attribs.push_back(NSOpenGLPFAAllowOfflineRenderers); // for automatic GPU switching
@@ -239,13 +240,21 @@ static void makeAttribList(
attribs.push_back(NSOpenGLPFASamples);
attribs.push_back((NSOpenGLPixelFormatAttribute) numOfAASamples);
-
- attribs.push_back(NSOpenGLPFANoRecovery);
}
attribs.push_back((NSOpenGLPixelFormatAttribute) 0);
}
+// TODO(merwin): make this available to all platforms
+static void getVersion(int *major, int *minor)
+{
+#if 1 // legacy GL
+ sscanf((const char*)glGetString(GL_VERSION), "%d.%d", major, minor);
+#else // 3.0+
+ glGetIntegerv(GL_MAJOR_VERSION, major);
+ glGetIntegerv(GL_MINOR_VERSION, minor);
+#endif
+}
GHOST_TSuccess GHOST_ContextCGL::initializeDrawingContext()
{
@@ -268,9 +277,12 @@ GHOST_TSuccess GHOST_ContextCGL::initializeDrawingContext()
static const bool needStencil = false;
#endif
- makeAttribList(attribs, m_coreProfile, m_stereoVisual, m_numOfAASamples, needAlpha, needStencil);
-
+ static bool softwareGL = getenv("BLENDER_SOFTWAREGL"); // command-line argument would be better
+ GLint major = 0, minor = 0;
NSOpenGLPixelFormat *pixelFormat;
+ // TODO: keep pixel format for subsequent windows/contexts instead of recreating each time
+
+ makeAttribList(attribs, coreProfile, m_stereoVisual, m_numOfAASamples, needAlpha, needStencil, softwareGL);
pixelFormat = [[NSOpenGLPixelFormat alloc] initWithAttributes:&attribs[0]];
@@ -281,7 +293,7 @@ GHOST_TSuccess GHOST_ContextCGL::initializeDrawingContext()
// (Now that I think about it, does WGL really require the code that it has for finding a lesser match?)
attribs.clear();
- makeAttribList(attribs, m_coreProfile, m_stereoVisual, 0, needAlpha, needStencil);
+ makeAttribList(attribs, coreProfile, m_stereoVisual, 0, needAlpha, needStencil, softwareGL);
pixelFormat = [[NSOpenGLPixelFormat alloc] initWithAttributes:&attribs[0]];
}
@@ -302,25 +314,47 @@ GHOST_TSuccess GHOST_ContextCGL::initializeDrawingContext()
}
}
- [m_openGLView setPixelFormat:pixelFormat];
+ m_openGLContext = [[NSOpenGLContext alloc] initWithFormat:pixelFormat shareContext:s_sharedOpenGLContext];
+ [pixelFormat release];
- m_openGLContext = [[NSOpenGLContext alloc] initWithFormat:pixelFormat shareContext:s_sharedOpenGLContext]; // +1 refCount to pixelFormat
+ [m_openGLContext makeCurrentContext];
- if (m_openGLContext == nil)
- goto error;
+ getVersion(&major, &minor);
+ if (m_debug) {
+ fprintf(stderr, "OpenGL version %d.%d%s\n", major, minor, softwareGL ? " (software)" : "");
+ fprintf(stderr, "Renderer: %s\n", glGetString(GL_RENDERER));
+ }
- if (s_sharedCount == 0)
- s_sharedOpenGLContext = m_openGLContext;
-
- [pixelFormat release]; // -1 refCount to pixelFormat
-
- s_sharedCount++;
+ if (major < 2 || (major == 2 && minor < 1)) {
+ // fall back to software renderer if GL < 2.1
+ fprintf(stderr, "OpenGL 2.1 is not supported on your hardware, falling back to software");
+ softwareGL = true;
+
+ // discard hardware GL context
+ [NSOpenGLContext clearCurrentContext];
+ [m_openGLContext release];
+
+ // create software GL context
+ makeAttribList(attribs, m_stereoVisual, m_numOfAASamples, needAlpha, needStencil, softwareGL);
+ pixelFormat = [[NSOpenGLPixelFormat alloc] initWithAttributes:&attribs[0]];
+ m_openGLContext = [[NSOpenGLContext alloc] initWithFormat:pixelFormat shareContext:s_sharedOpenGLContext];
+ [pixelFormat release];
+
+ [m_openGLContext makeCurrentContext];
+
+ getVersion(&major, &minor);
+ if (m_debug) {
+ fprintf(stderr, "OpenGL version %d.%d%s\n", major, minor, softwareGL ? " (software)" : "");
+ fprintf(stderr, "Renderer: %s\n", glGetString(GL_RENDERER));
+ }
+ }
#ifdef GHOST_MULTITHREADED_OPENGL
//Switch openGL to multhreaded mode
CGLContextObj cglCtx = (CGLContextObj)[tmpOpenGLContext CGLContextObj];
if (CGLEnable(cglCtx, kCGLCEMPEngine) == kCGLNoError)
- printf("\nSwitched openGL to multithreaded mode\n");
+ if (m_debug)
+ fprintf(stderr, "\nSwitched OpenGL to multithreaded mode\n");
#endif
#ifdef GHOST_WAIT_FOR_VSYNC
@@ -331,10 +365,16 @@ GHOST_TSuccess GHOST_ContextCGL::initializeDrawingContext()
}
#endif
+ initContextGLEW();
+
[m_openGLView setOpenGLContext:m_openGLContext];
[m_openGLContext setView:m_openGLView];
- initContextGLEW();
+ if (s_sharedCount == 0)
+ s_sharedOpenGLContext = m_openGLContext;
+
+ s_sharedCount++;
+
initClearGL();
[m_openGLContext flushBuffer];
diff --git a/intern/ghost/intern/GHOST_SystemCocoa.mm b/intern/ghost/intern/GHOST_SystemCocoa.mm
index b0d5ab31ce3..f31cba498e5 100644
--- a/intern/ghost/intern/GHOST_SystemCocoa.mm
+++ b/intern/ghost/intern/GHOST_SystemCocoa.mm
@@ -562,7 +562,7 @@ GHOST_IWindow* GHOST_SystemCocoa::createWindow(
// Add contentRect.origin.y to respect docksize
bottom = bottom > contentRect.origin.y ? bottom + contentRect.origin.y : contentRect.origin.y;
- window = new GHOST_WindowCocoa (this, title, left, bottom, width, height, state, type, ((glSettings.flags & GHOST_glStereoVisual) != 0), glSettings.numOfAASamples);
+ window = new GHOST_WindowCocoa(this, title, left, bottom, width, height, state, type, glSettings.flags & GHOST_glStereoVisual, glSettings.numOfAASamples, glSettings.flags & GHOST_glDebugContext);
if (window->getValid()) {
// Store the pointer to the window
diff --git a/intern/ghost/intern/GHOST_SystemWin32.cpp b/intern/ghost/intern/GHOST_SystemWin32.cpp
index f884b0fadb1..60e7815ccbb 100644
--- a/intern/ghost/intern/GHOST_SystemWin32.cpp
+++ b/intern/ghost/intern/GHOST_SystemWin32.cpp
@@ -41,7 +41,7 @@
#include <shlobj.h>
#include <tlhelp32.h>
-#include <Psapi.h>
+#include <psapi.h>
#include <windowsx.h>
#include "utfconv.h"
diff --git a/intern/ghost/intern/GHOST_WindowCocoa.h b/intern/ghost/intern/GHOST_WindowCocoa.h
index 3ed88086184..b234291396b 100644
--- a/intern/ghost/intern/GHOST_WindowCocoa.h
+++ b/intern/ghost/intern/GHOST_WindowCocoa.h
@@ -74,7 +74,8 @@ public:
GHOST_TWindowState state,
GHOST_TDrawingContextType type = GHOST_kDrawingContextTypeNone,
const bool stereoVisual = false,
- const GHOST_TUns16 numOfAASamples = 0
+ const GHOST_TUns16 numOfAASamples = 0,
+ bool is_debug = false
);
/**
@@ -305,6 +306,7 @@ protected:
bool m_lionStyleFullScreen;
bool m_immediateDraw;
+ bool m_debug_context; // for debug messages during context setup
};
#endif // __GHOST_WINDOWCOCOA_H__
diff --git a/intern/ghost/intern/GHOST_WindowCocoa.mm b/intern/ghost/intern/GHOST_WindowCocoa.mm
index 383734be3e6..b0feb11a6af 100644
--- a/intern/ghost/intern/GHOST_WindowCocoa.mm
+++ b/intern/ghost/intern/GHOST_WindowCocoa.mm
@@ -528,10 +528,11 @@ GHOST_WindowCocoa::GHOST_WindowCocoa(
GHOST_TUns32 height,
GHOST_TWindowState state,
GHOST_TDrawingContextType type,
- const bool stereoVisual, const GHOST_TUns16 numOfAASamples
+ const bool stereoVisual, const GHOST_TUns16 numOfAASamples, bool is_debug
) :
GHOST_Window(width, height, state, stereoVisual, false, numOfAASamples),
- m_customCursor(0)
+ m_customCursor(0),
+ m_debug_context(is_debug)
{
m_systemCocoa = systemCocoa;
m_fullScreen = false;
diff --git a/intern/mikktspace/mikktspace.c b/intern/mikktspace/mikktspace.c
index 7e5861ea9ed..8d51816b132 100644
--- a/intern/mikktspace/mikktspace.c
+++ b/intern/mikktspace/mikktspace.c
@@ -579,11 +579,10 @@ static void MergeVertsFast(int piTriList_in_and_out[], STmpVert pTmpVert[], cons
{
// make bbox
int c=0, l=0, channel=0;
- float fvMin[3], fvMax[3];
+ float fvMin[3] = {INFINITY, INFINITY, INFINITY};
+ float fvMax[3] = {-INFINITY, -INFINITY, -INFINITY};
float dx=0, dy=0, dz=0, fSep=0;
- for (c=0; c<3; c++)
- { fvMin[c]=pTmpVert[iL_in].vert[c]; fvMax[c]=fvMin[c]; }
- for (l=(iL_in+1); l<=iR_in; l++)
+ for (l=iL_in; l<=iR_in; l++)
for (c=0; c<3; c++)
if (fvMin[c]>pTmpVert[l].vert[c]) fvMin[c]=pTmpVert[l].vert[c];
else if (fvMax[c]<pTmpVert[l].vert[c]) fvMax[c]=pTmpVert[l].vert[c];
@@ -598,6 +597,10 @@ static void MergeVertsFast(int piTriList_in_and_out[], STmpVert pTmpVert[], cons
fSep = 0.5f*(fvMax[channel]+fvMin[channel]);
+ // stop if all vertices are NaNs
+ if (!isfinite(fSep))
+ return;
+
// terminate recursion when the separation/average value
// is no longer strictly between fMin and fMax values.
if (fSep>=fvMax[channel] || fSep<=fvMin[channel])