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
diff options
context:
space:
mode:
-rw-r--r--source/blender/blenkernel/BKE_anim.h5
-rw-r--r--source/blender/blenkernel/BKE_depsgraph.h35
-rw-r--r--source/blender/blenkernel/BKE_displist.h5
-rw-r--r--source/blender/blenkernel/BKE_group.h3
-rw-r--r--source/blender/blenkernel/BKE_library.h2
-rw-r--r--source/blender/blenkernel/BKE_main.h4
-rw-r--r--source/blender/blenkernel/BKE_mball.h3
-rw-r--r--source/blender/blenkernel/BKE_object.h6
-rw-r--r--source/blender/blenkernel/BKE_scene.h10
-rw-r--r--source/blender/blenkernel/BKE_sequencer.h6
-rw-r--r--source/blender/blenkernel/BKE_shrinkwrap.h4
-rw-r--r--source/blender/blenkernel/BKE_smoke.h2
-rw-r--r--source/blender/blenkernel/depsgraph_private.h8
-rw-r--r--source/blender/blenkernel/intern/anim.c60
-rw-r--r--source/blender/blenkernel/intern/blender.c3
-rw-r--r--source/blender/blenkernel/intern/constraint.c8
-rw-r--r--source/blender/blenkernel/intern/depsgraph.c230
-rw-r--r--source/blender/blenkernel/intern/displist.c10
-rw-r--r--source/blender/blenkernel/intern/dynamicpaint.c2
-rw-r--r--source/blender/blenkernel/intern/group.c7
-rw-r--r--source/blender/blenkernel/intern/library.c8
-rw-r--r--source/blender/blenkernel/intern/mball.c33
-rw-r--r--source/blender/blenkernel/intern/object.c33
-rw-r--r--source/blender/blenkernel/intern/pointcache.c10
-rw-r--r--source/blender/blenkernel/intern/scene.c290
-rw-r--r--source/blender/blenkernel/intern/sequencer.c22
-rw-r--r--source/blender/blenkernel/intern/shrinkwrap.c17
-rw-r--r--source/blender/blenkernel/intern/smoke.c30
-rw-r--r--source/blender/blenloader/intern/readfile.c8
-rw-r--r--source/blender/collada/AnimationExporter.cpp2
-rw-r--r--source/blender/editors/mesh/editmesh_extrude.c4
-rw-r--r--source/blender/editors/mesh/editmesh_utils.c5
-rw-r--r--source/blender/editors/object/object_add.c4
-rw-r--r--source/blender/editors/object/object_modifier.c2
-rw-r--r--source/blender/editors/render/render_opengl.c9
-rw-r--r--source/blender/editors/screen/screen_edit.c18
-rw-r--r--source/blender/editors/sound/sound_ops.c4
-rw-r--r--source/blender/editors/space_image/image_ops.c2
-rw-r--r--source/blender/editors/space_sequencer/sequencer_draw.c4
-rw-r--r--source/blender/editors/space_view3d/drawobject.c5
-rw-r--r--source/blender/editors/space_view3d/view3d_draw.c5
-rw-r--r--source/blender/editors/space_view3d/view3d_view.c4
-rw-r--r--source/blender/editors/transform/transform_conversions.c6
-rw-r--r--source/blender/editors/transform/transform_snap.c11
-rw-r--r--source/blender/gpu/intern/gpu_material.c2
-rw-r--r--source/blender/makesrna/SConscript1
-rw-r--r--source/blender/makesrna/intern/CMakeLists.txt3
-rw-r--r--source/blender/makesrna/intern/rna_main_api.c8
-rw-r--r--source/blender/makesrna/intern/rna_object_api.c8
-rw-r--r--source/blender/makesrna/intern/rna_scene.c2
-rw-r--r--source/blender/makesrna/intern/rna_scene_api.c25
-rw-r--r--source/blender/modifiers/intern/MOD_array.c12
-rw-r--r--source/blender/modifiers/intern/MOD_boolean.c23
-rw-r--r--source/blender/modifiers/intern/MOD_shrinkwrap.c7
-rw-r--r--source/blender/modifiers/intern/MOD_smoke.c3
-rw-r--r--source/blender/modifiers/intern/MOD_util.c14
-rw-r--r--source/blender/modifiers/intern/MOD_util.h1
-rw-r--r--source/blender/render/intern/include/render_types.h2
-rw-r--r--source/blender/render/intern/source/convertblender.c13
-rw-r--r--source/blender/render/intern/source/external_engine.c2
-rw-r--r--source/blender/render/intern/source/pipeline.c129
-rw-r--r--source/blender/windowmanager/intern/wm_event_system.c2
-rw-r--r--source/blender/windowmanager/intern/wm_operators.c4
-rw-r--r--source/blender/windowmanager/intern/wm_playanim.c2
-rw-r--r--source/creator/creator.c6
-rw-r--r--source/gameengine/GamePlayer/ghost/GPG_ghost.cpp2
66 files changed, 946 insertions, 274 deletions
diff --git a/source/blender/blenkernel/BKE_anim.h b/source/blender/blenkernel/BKE_anim.h
index 7de7a745ed6..e87fef1c864 100644
--- a/source/blender/blenkernel/BKE_anim.h
+++ b/source/blender/blenkernel/BKE_anim.h
@@ -32,6 +32,7 @@
* \author nzc
* \since March 2001
*/
+struct EvaluationContext;
struct Path;
struct Object;
struct PartEff;
@@ -65,8 +66,8 @@ int where_on_path(struct Object *ob, float ctime, float vec[4], float dir[3], fl
/* ---------------------------------------------------- */
/* Dupli-Geometry */
-struct ListBase *object_duplilist_ex(struct Scene *sce, struct Object *ob, bool update, bool for_render);
-struct ListBase *object_duplilist(struct Scene *sce, struct Object *ob, bool for_render);
+struct ListBase *object_duplilist_ex(struct EvaluationContext *eval_ctx, struct Scene *sce, struct Object *ob, bool update);
+struct ListBase *object_duplilist(struct EvaluationContext *eval_ctx, struct Scene *sce, struct Object *ob);
void free_object_duplilist(struct ListBase *lb);
int count_duplilist(struct Object *ob);
diff --git a/source/blender/blenkernel/BKE_depsgraph.h b/source/blender/blenkernel/BKE_depsgraph.h
index 6baf20aeb2c..be5ae7fc353 100644
--- a/source/blender/blenkernel/BKE_depsgraph.h
+++ b/source/blender/blenkernel/BKE_depsgraph.h
@@ -48,6 +48,21 @@ struct ID;
struct Main;
struct Object;
struct Scene;
+struct ListBase;
+
+/* Dependency graph evaluation context
+ *
+ * This structure stores all the local dependency graph data,
+ * which is needed for it's evaluation,
+ */
+typedef struct EvaluationContext {
+ bool for_render; /* Set to true if evaluation shall be performed for render purposes,
+ keep at false if update shall happen for the viewport. */
+} EvaluationContext;
+
+/* Global initialization/deinitialization */
+void DAG_init(void);
+void DAG_exit(void);
/* Build and Update
*
@@ -115,10 +130,30 @@ void DAG_pose_sort(struct Object *ob);
void DAG_editors_update_cb(void (*id_func)(struct Main *bmain, struct ID *id),
void (*scene_func)(struct Main *bmain, struct Scene *scene, int updated));
+/* ** Threaded update ** */
+
+/* Initialize the DAG for threaded update. */
+void DAG_threaded_update_begin(struct Scene *scene,
+ void (*func)(void *node, void *user_data),
+ void *user_data);
+
+void DAG_threaded_update_handle_node_updated(void *node_v,
+ void (*func)(void *node, void *user_data),
+ void *user_data);
+
/* Debugging: print dependency graph for scene or armature object to console */
void DAG_print_dependencies(struct Main *bmain, struct Scene *scene, struct Object *ob);
+/* Tagging and querying */
+void DAG_tag_clear_nodes(struct Scene *scene);
+void DAG_tag_node_for_object(struct Scene *scene, void *object);
+void DAG_tag_flush_nodes(struct Scene *scene);
+
+struct Object *DAG_get_node_object(void *node_v);
+const char *DAG_get_node_name(void *node_v);
+bool DAG_get_node_tag(void *node_v);
+
#ifdef __cplusplus
}
#endif
diff --git a/source/blender/blenkernel/BKE_displist.h b/source/blender/blenkernel/BKE_displist.h
index 2178f860825..dab552069f1 100644
--- a/source/blender/blenkernel/BKE_displist.h
+++ b/source/blender/blenkernel/BKE_displist.h
@@ -62,6 +62,7 @@ struct Material;
struct Bone;
struct Mesh;
struct DerivedMesh;
+struct EvaluationContext;
/* used for curves, nurbs, mball, importing */
typedef struct DispList {
@@ -91,8 +92,8 @@ void BKE_displist_make_surf(struct Scene *scene, struct Object *ob, struct ListB
void BKE_displist_make_curveTypes(struct Scene *scene, struct Object *ob, int forOrco);
void BKE_displist_make_curveTypes_forRender(struct Scene *scene, struct Object *ob, struct ListBase *dispbase, struct DerivedMesh **derivedFinal, int forOrco, int renderResolution);
void BKE_displist_make_curveTypes_forOrco(struct Scene *scene, struct Object *ob, struct ListBase *dispbase);
-void BKE_displist_make_mball(struct Scene *scene, struct Object *ob);
-void BKE_displist_make_mball_forRender(struct Scene *scene, struct Object *ob, struct ListBase *dispbase);
+void BKE_displist_make_mball(struct EvaluationContext *eval_ctx, struct Scene *scene, struct Object *ob);
+void BKE_displist_make_mball_forRender(struct EvaluationContext *eval_ctx, struct Scene *scene, struct Object *ob, struct ListBase *dispbase);
bool BKE_displist_surfindex_get(DispList *dl, int a, int *b, int *p1, int *p2, int *p3, int *p4);
void BKE_displist_fill(struct ListBase *dispbase, struct ListBase *to, const float normal_proj[3], const bool flipnormal);
diff --git a/source/blender/blenkernel/BKE_group.h b/source/blender/blenkernel/BKE_group.h
index 0f36b7a8cfc..f528fe8c7f9 100644
--- a/source/blender/blenkernel/BKE_group.h
+++ b/source/blender/blenkernel/BKE_group.h
@@ -34,6 +34,7 @@
*/
struct Base;
+struct EvaluationContext;
struct Group;
struct GroupObject;
struct Main;
@@ -52,6 +53,6 @@ bool BKE_group_object_exists(struct Group *group, struct Object *ob);
bool BKE_group_is_animated(struct Group *group, struct Object *parent);
void BKE_group_tag_recalc(struct Group *group);
-void BKE_group_handle_recalc_and_update(struct Scene *scene, struct Object *parent, struct Group *group);
+void BKE_group_handle_recalc_and_update(struct EvaluationContext *eval_ctx, struct Scene *scene, struct Object *parent, struct Group *group);
#endif /* __BKE_GROUP_H__ */
diff --git a/source/blender/blenkernel/BKE_library.h b/source/blender/blenkernel/BKE_library.h
index f97bb911a12..cad3f264fb8 100644
--- a/source/blender/blenkernel/BKE_library.h
+++ b/source/blender/blenkernel/BKE_library.h
@@ -77,6 +77,8 @@ void BKE_libblock_free(struct ListBase *lb, void *idv);
void BKE_libblock_free_ex(struct ListBase *lb, void *idv, bool do_id_user);
void BKE_libblock_free_us(struct ListBase *lb, void *idv);
void BKE_libblock_free_data(struct ID *id);
+
+struct Main *BKE_main_new(void);
void free_main(struct Main *mainvar);
void tag_main_idcode(struct Main *mainvar, const short type, const short tag);
diff --git a/source/blender/blenkernel/BKE_main.h b/source/blender/blenkernel/BKE_main.h
index 7b7b69034a9..721866daff5 100644
--- a/source/blender/blenkernel/BKE_main.h
+++ b/source/blender/blenkernel/BKE_main.h
@@ -46,6 +46,7 @@
extern "C" {
#endif
+struct EvaluationContext;
struct Library;
typedef struct Main {
@@ -92,6 +93,9 @@ typedef struct Main {
ListBase linestyle;
char id_tag_update[256];
+
+ /* Evaluation context used by viewport */
+ struct EvaluationContext *eval_ctx;
} Main;
#define MAIN_VERSION_ATLEAST(main, ver, subver) \
diff --git a/source/blender/blenkernel/BKE_mball.h b/source/blender/blenkernel/BKE_mball.h
index 7665e1b54dc..56ea44fa6e9 100644
--- a/source/blender/blenkernel/BKE_mball.h
+++ b/source/blender/blenkernel/BKE_mball.h
@@ -32,6 +32,7 @@
* \since March 2001
* \author nzc
*/
+struct EvaluationContext;
struct Main;
struct MetaBall;
struct Object;
@@ -47,7 +48,7 @@ void BKE_mball_make_local(struct MetaBall *mb);
void BKE_mball_cubeTable_free(void);
-void BKE_mball_polygonize(struct Scene *scene, struct Object *ob, struct ListBase *dispbase, bool for_render);
+void BKE_mball_polygonize(struct EvaluationContext *eval_ctx, struct Scene *scene, struct Object *ob, struct ListBase *dispbase);
bool BKE_mball_is_basis_for(struct Object *ob1, struct Object *ob2);
bool BKE_mball_is_basis(struct Object *ob);
struct Object *BKE_mball_basis_find(struct Scene *scene, struct Object *ob);
diff --git a/source/blender/blenkernel/BKE_object.h b/source/blender/blenkernel/BKE_object.h
index 94995404f2b..419b8de2bc3 100644
--- a/source/blender/blenkernel/BKE_object.h
+++ b/source/blender/blenkernel/BKE_object.h
@@ -34,6 +34,7 @@ extern "C" {
#endif
struct Base;
+struct EvaluationContext;
struct Scene;
struct Object;
struct Camera;
@@ -162,8 +163,9 @@ void BKE_object_tfm_protected_restore(struct Object *ob,
const ObjectTfmProtectedChannels *obtfm,
const short protectflag);
-void BKE_object_handle_update(struct Scene *scene, struct Object *ob);
-void BKE_object_handle_update_ex(struct Scene *scene, struct Object *ob,
+void BKE_object_handle_update(struct EvaluationContext *eval_ctx, struct Scene *scene, struct Object *ob);
+void BKE_object_handle_update_ex(struct EvaluationContext *eval_ctx,
+ struct Scene *scene, struct Object *ob,
struct RigidBodyWorld *rbw);
void BKE_object_sculpt_modifiers_changed(struct Object *ob);
diff --git a/source/blender/blenkernel/BKE_scene.h b/source/blender/blenkernel/BKE_scene.h
index 61f665be586..4ff1c8ba3a4 100644
--- a/source/blender/blenkernel/BKE_scene.h
+++ b/source/blender/blenkernel/BKE_scene.h
@@ -39,6 +39,7 @@ extern "C" {
struct AviCodecData;
struct Base;
+struct EvaluationContext;
struct bglMats;
struct Main;
struct Object;
@@ -85,7 +86,8 @@ typedef struct SceneBaseIter {
int fase;
} SceneBaseIter;
-int BKE_scene_base_iter_next(struct SceneBaseIter *iter, struct Scene **scene, int val, struct Base **base, struct Object **ob);
+int BKE_scene_base_iter_next(struct EvaluationContext *eval_ctx, struct SceneBaseIter *iter,
+ struct Scene **scene, int val, struct Base **base, struct Object **ob);
void BKE_scene_base_flag_to_objects(struct Scene *scene);
void BKE_scene_base_flag_from_objects(struct Scene *scene);
@@ -111,9 +113,9 @@ float BKE_scene_frame_get(struct Scene *scene);
float BKE_scene_frame_get_from_ctime(struct Scene *scene, const float frame);
void BKE_scene_frame_set(struct Scene *scene, double cfra);
-void BKE_scene_update_tagged(struct Main *bmain, struct Scene *sce);
-
-void BKE_scene_update_for_newframe(struct Main *bmain, struct Scene *sce, unsigned int lay);
+/* ** Scene evaluation ** */
+void BKE_scene_update_tagged(struct EvaluationContext *eval_ctx, struct Main *bmain, struct Scene *sce);
+void BKE_scene_update_for_newframe(struct EvaluationContext *eval_ctx, struct Main *bmain, struct Scene *sce, unsigned int lay);
struct SceneRenderLayer *BKE_scene_add_render_layer(struct Scene *sce, const char *name);
int BKE_scene_remove_render_layer(struct Main *main, struct Scene *scene, struct SceneRenderLayer *srl);
diff --git a/source/blender/blenkernel/BKE_sequencer.h b/source/blender/blenkernel/BKE_sequencer.h
index 12b6d18ab7c..0ca1d904d6f 100644
--- a/source/blender/blenkernel/BKE_sequencer.h
+++ b/source/blender/blenkernel/BKE_sequencer.h
@@ -31,6 +31,7 @@
*/
struct bContext;
+struct EvaluationContext;
struct StripColorBalance;
struct Editing;
struct ImBuf;
@@ -89,6 +90,7 @@ void BKE_sequence_iterator_end(SeqIterator *iter);
}
typedef struct SeqRenderData {
+ struct EvaluationContext *eval_ctx;
struct Main *bmain;
struct Scene *scene;
int rectx;
@@ -98,8 +100,8 @@ typedef struct SeqRenderData {
float motion_blur_shutter;
} SeqRenderData;
-SeqRenderData BKE_sequencer_new_render_data(struct Main *bmain, struct Scene *scene, int rectx, int recty,
- int preview_render_size);
+SeqRenderData BKE_sequencer_new_render_data(struct EvaluationContext *eval_ctx, struct Main *bmain,
+ struct Scene *scene, int rectx, int recty, int preview_render_size);
/* Wipe effect */
enum {
diff --git a/source/blender/blenkernel/BKE_shrinkwrap.h b/source/blender/blenkernel/BKE_shrinkwrap.h
index 323a926863c..6e85d9ee0a0 100644
--- a/source/blender/blenkernel/BKE_shrinkwrap.h
+++ b/source/blender/blenkernel/BKE_shrinkwrap.h
@@ -37,7 +37,7 @@
#include "BKE_customdata.h"
struct DerivedMesh;
struct Object;
-struct DerivedMesh *object_get_derived_final(struct Object *ob);
+struct DerivedMesh *object_get_derived_final(struct Object *ob, bool for_render);
/* SpaceTransform stuff */
@@ -122,7 +122,7 @@ typedef struct ShrinkwrapCalcData {
} ShrinkwrapCalcData;
void shrinkwrapModifier_deform(struct ShrinkwrapModifierData *smd, struct Object *ob, struct DerivedMesh *dm,
- float (*vertexCos)[3], int numVerts);
+ float (*vertexCos)[3], int numVerts, bool forRender);
/*
* This function casts a ray in the given BVHTree.. but it takes into consideration the space_transform, that is:
diff --git a/source/blender/blenkernel/BKE_smoke.h b/source/blender/blenkernel/BKE_smoke.h
index 20366f00df6..07d156cfa02 100644
--- a/source/blender/blenkernel/BKE_smoke.h
+++ b/source/blender/blenkernel/BKE_smoke.h
@@ -35,7 +35,7 @@
typedef float (*bresenham_callback)(float *result, float *input, int res[3], int *pixel, float *tRay, float correct);
-struct DerivedMesh *smokeModifier_do(struct SmokeModifierData *smd, struct Scene *scene, struct Object *ob, struct DerivedMesh *dm);
+struct DerivedMesh *smokeModifier_do(struct SmokeModifierData *smd, struct Scene *scene, struct Object *ob, struct DerivedMesh *dm, bool for_render);
void smoke_reallocate_fluid(struct SmokeDomainSettings *sds, float dx, int res[3], int free_old);
void smoke_reallocate_highres_fluid(struct SmokeDomainSettings *sds, float dx, int res[3], int free_old);
diff --git a/source/blender/blenkernel/depsgraph_private.h b/source/blender/blenkernel/depsgraph_private.h
index c8ce2bb2a77..f4a6e4417e0 100644
--- a/source/blender/blenkernel/depsgraph_private.h
+++ b/source/blender/blenkernel/depsgraph_private.h
@@ -92,6 +92,14 @@ typedef struct DagNode {
struct DagAdjList *child;
struct DagAdjList *parent;
struct DagNode *next;
+
+ /* Threaded evaluation routines */
+ uint32_t num_pending_parents; /* number of parents which are not updated yet
+ * this node has got.
+ * Used by threaded update for faster detect whether node could be
+ * updated aready.
+ */
+ bool tag, scheduled;
} DagNode;
typedef struct DagNodeQueueElem {
diff --git a/source/blender/blenkernel/intern/anim.c b/source/blender/blenkernel/intern/anim.c
index 1624a02e773..779593c2f76 100644
--- a/source/blender/blenkernel/intern/anim.c
+++ b/source/blender/blenkernel/intern/anim.c
@@ -76,7 +76,8 @@
/* --------------------- */
/* forward declarations */
-static void object_duplilist_recursive(ID *id, Scene *scene, Object *ob, ListBase *duplilist, float par_space_mat[4][4],
+static void object_duplilist_recursive(EvaluationContext *eval_ctx,
+ ID *id, Scene *scene, Object *ob, ListBase *duplilist, float par_space_mat[4][4],
int persistent_id[MAX_DUPLI_RECUR], int level, int index, short flag);
/* ******************************************************************** */
@@ -326,11 +327,10 @@ static void motionpaths_calc_optimise_depsgraph(Scene *scene, ListBase *targets)
static void motionpaths_calc_update_scene(Scene *scene)
{
#if 1 // 'production' optimizations always on
-
/* rigid body simulation needs complete update to work correctly for now */
/* RB_TODO investigate if we could avoid updating everything */
if (BKE_scene_check_rigidbody_active(scene)) {
- BKE_scene_update_for_newframe(G.main, scene, scene->lay);
+ BKE_scene_update_for_newframe(G.main->eval_ctx, G.main, scene, scene->lay);
}
else { /* otherwise we can optimize by restricting updates */
Base *base, *last = NULL;
@@ -352,7 +352,7 @@ static void motionpaths_calc_update_scene(Scene *scene)
* is animated but not attached to/updatable from objects */
for (base = scene->base.first; base; base = base->next) {
/* update this object */
- BKE_object_handle_update(scene, base->object);
+ BKE_object_handle_update(G.main->eval_ctx, scene, base->object);
/* if this is the last one we need to update, let's stop to save some time */
if (base == last)
@@ -365,7 +365,7 @@ static void motionpaths_calc_update_scene(Scene *scene)
* that doesn't force complete update, but for now, this is the
* most accurate way!
*/
- BKE_scene_update_for_newframe(G.main, scene, scene->lay); /* XXX this is the best way we can get anything moving */
+ BKE_scene_update_for_newframe(G.main->eval_ctx, G.main, scene, scene->lay); /* XXX this is the best way we can get anything moving */
#endif
}
@@ -745,7 +745,8 @@ static DupliObject *new_dupli_object(ListBase *lb, Object *ob, float mat[4][4],
return dob;
}
-static void group_duplilist(ListBase *lb, Scene *scene, Object *ob, int persistent_id[MAX_DUPLI_RECUR],
+static void group_duplilist(EvaluationContext *eval_ctx,
+ ListBase *lb, Scene *scene, Object *ob, int persistent_id[MAX_DUPLI_RECUR],
int level, short flag)
{
DupliObject *dob;
@@ -775,7 +776,7 @@ static void group_duplilist(ListBase *lb, Scene *scene, Object *ob, int persiste
if (flag & DUPLILIST_DO_UPDATE) {
/* note: update is optional because we don't always need object
* transformations to be correct. Also fixes bug [#29616]. */
- BKE_group_handle_recalc_and_update(scene, ob, group);
+ BKE_group_handle_recalc_and_update(eval_ctx, scene, ob, group);
}
if (BKE_group_is_animated(group, ob))
@@ -792,15 +793,15 @@ static void group_duplilist(ListBase *lb, Scene *scene, Object *ob, int persiste
/* check the group instance and object layers match, also that the object visible flags are ok. */
if ((dob->origlay & group->layer) == 0 ||
- ((G.is_rendering == FALSE) && dob->ob->restrictflag & OB_RESTRICT_VIEW) ||
- ((G.is_rendering == TRUE) && dob->ob->restrictflag & OB_RESTRICT_RENDER))
+ ((eval_ctx->for_render == false) && dob->ob->restrictflag & OB_RESTRICT_VIEW) ||
+ ((eval_ctx->for_render == true) && dob->ob->restrictflag & OB_RESTRICT_RENDER))
{
dob->no_draw = TRUE;
}
if (go->ob->transflag & OB_DUPLI) {
copy_m4_m4(dob->ob->obmat, dob->mat);
- object_duplilist_recursive(&group->id, scene, go->ob, lb, ob_obmat_ofs, persistent_id, level + 1, id, flag);
+ object_duplilist_recursive(eval_ctx, &group->id, scene, go->ob, lb, ob_obmat_ofs, persistent_id, level + 1, id, flag);
copy_m4_m4(dob->ob->obmat, dob->omat);
}
}
@@ -877,6 +878,7 @@ static void frames_duplilist(ListBase *lb, Scene *scene, Object *ob, int persist
}
typedef struct VertexDupliData {
+ EvaluationContext *eval_ctx;
ID *id; /* scene or group, for recursive loops */
int level;
short flag;
@@ -935,7 +937,7 @@ static void vertex_dupli__mapFunc(void *userData, int index, const float co[3],
float tmpmat[4][4];
copy_m4_m4(tmpmat, vdd->ob->obmat);
copy_m4_m4(vdd->ob->obmat, obmat); /* pretend we are really this mat */
- object_duplilist_recursive((ID *)vdd->id, vdd->scene, vdd->ob, vdd->lb, obmat, vdd->persistent_id, vdd->level + 1, index, vdd->flag);
+ object_duplilist_recursive(vdd->eval_ctx, (ID *)vdd->id, vdd->scene, vdd->ob, vdd->lb, obmat, vdd->persistent_id, vdd->level + 1, index, vdd->flag);
copy_m4_m4(vdd->ob->obmat, tmpmat);
}
}
@@ -1071,7 +1073,8 @@ static void vertex_duplilist(ListBase *lb, ID *id, Scene *scene, Object *par, fl
dm->release(dm);
}
-static void face_duplilist(ListBase *lb, ID *id, Scene *scene, Object *par, float par_space_mat[4][4], int persistent_id[MAX_DUPLI_RECUR],
+static void face_duplilist(EvaluationContext *eval_ctx,
+ ListBase *lb, ID *id, Scene *scene, Object *par, float par_space_mat[4][4], int persistent_id[MAX_DUPLI_RECUR],
int level, short flag)
{
Object *ob, *ob_iter;
@@ -1237,7 +1240,7 @@ static void face_duplilist(ListBase *lb, ID *id, Scene *scene, Object *par, floa
float tmpmat[4][4];
copy_m4_m4(tmpmat, ob->obmat);
copy_m4_m4(ob->obmat, obmat); /* pretend we are really this mat */
- object_duplilist_recursive((ID *)id, scene, ob, lb, ob->obmat, persistent_id, level + 1, a, flag);
+ object_duplilist_recursive(eval_ctx, (ID *)id, scene, ob, lb, ob->obmat, persistent_id, level + 1, a, flag);
copy_m4_m4(ob->obmat, tmpmat);
}
}
@@ -1254,7 +1257,8 @@ static void face_duplilist(ListBase *lb, ID *id, Scene *scene, Object *par, floa
dm->release(dm);
}
-static void new_particle_duplilist(ListBase *lb, ID *id, Scene *scene, Object *par, float par_space_mat[4][4],
+static void new_particle_duplilist(EvaluationContext *eval_ctx,
+ ListBase *lb, ID *id, Scene *scene, Object *par, float par_space_mat[4][4],
int persistent_id[MAX_DUPLI_RECUR], ParticleSystem *psys,
int level, short flag)
{
@@ -1289,7 +1293,7 @@ static void new_particle_duplilist(ListBase *lb, ID *id, Scene *scene, Object *p
if (!psys_check_enabled(par, psys))
return;
- if (G.is_rendering == FALSE)
+ if (eval_ctx->for_render == false)
no_draw_flag |= PARS_NO_DISP;
ctime = BKE_scene_frame_get(scene); /* NOTE: in old animsys, used parent object's timeoffset... */
@@ -1341,7 +1345,7 @@ static void new_particle_duplilist(ListBase *lb, ID *id, Scene *scene, Object *p
/* gather list of objects or single object */
if (part->ren_as == PART_DRAW_GR) {
if (flag & DUPLILIST_DO_UPDATE) {
- BKE_group_handle_recalc_and_update(scene, par, part->dup_group);
+ BKE_group_handle_recalc_and_update(eval_ctx, scene, par, part->dup_group);
}
if (part->draw & PART_DRAW_COUNT_GR) {
@@ -1650,14 +1654,15 @@ static void font_duplilist(ListBase *lb, Scene *scene, Object *par, int persiste
/* ------------- */
-static void object_duplilist_recursive(ID *id, Scene *scene, Object *ob, ListBase *duplilist, float par_space_mat[4][4],
+static void object_duplilist_recursive(EvaluationContext *eval_ctx,
+ ID *id, Scene *scene, Object *ob, ListBase *duplilist, float par_space_mat[4][4],
int persistent_id[MAX_DUPLI_RECUR], int level, int index, short flag)
{
if ((ob->transflag & OB_DUPLI) == 0)
return;
/* Should the dupli's be generated for this object? - Respect restrict flags */
- if (G.is_rendering) {
+ if (eval_ctx->for_render) {
if (ob->restrictflag & OB_RESTRICT_RENDER) {
return;
}
@@ -1679,7 +1684,7 @@ static void object_duplilist_recursive(ID *id, Scene *scene, Object *ob, ListBas
/* particle system take up one level in id, the particles another */
for (; psys; psys = psys->next, psysid++) {
persistent_id[level] = psysid;
- new_particle_duplilist(duplilist, id, scene, ob, par_space_mat, persistent_id, psys, level + 2, flag);
+ new_particle_duplilist(eval_ctx, duplilist, id, scene, ob, par_space_mat, persistent_id, psys, level + 2, flag);
}
persistent_id[level] = 0;
@@ -1696,7 +1701,7 @@ static void object_duplilist_recursive(ID *id, Scene *scene, Object *ob, ListBas
}
else if (ob->transflag & OB_DUPLIFACES) {
if (ob->type == OB_MESH)
- face_duplilist(duplilist, id, scene, ob, par_space_mat, persistent_id, level + 1, flag);
+ face_duplilist(eval_ctx, duplilist, id, scene, ob, par_space_mat, persistent_id, level + 1, flag);
}
else if (ob->transflag & OB_DUPLIFRAMES) {
if (GS(id->name) == ID_SCE) { /* TODO - support dupligroups */
@@ -1706,7 +1711,7 @@ static void object_duplilist_recursive(ID *id, Scene *scene, Object *ob, ListBas
else if (ob->transflag & OB_DUPLIGROUP) {
DupliObject *dob;
- group_duplilist(duplilist, scene, ob, persistent_id, level + 1, flag); /* now recursive */
+ group_duplilist(eval_ctx, duplilist, scene, ob, persistent_id, level + 1, flag); /* now recursive */
if (level == 0) {
for (dob = duplilist->first; dob; dob = dob->next)
@@ -1722,31 +1727,30 @@ static void object_duplilist_recursive(ID *id, Scene *scene, Object *ob, ListBas
/* Returns a list of DupliObject
* note; group dupli's already set transform matrix. see note in group_duplilist() */
-ListBase *object_duplilist_ex(Scene *sce, Object *ob, bool update, bool for_render)
+ListBase *object_duplilist_ex(EvaluationContext *eval_ctx, Scene *sce, Object *ob, bool update)
{
ListBase *duplilist = MEM_mallocN(sizeof(ListBase), "duplilist");
int persistent_id[MAX_DUPLI_RECUR] = {0};
int flag = 0;
/* don't allow BKE_object_handle_update for viewport during render, can crash */
- if (update && !(G.is_rendering && !for_render))
+ if (update && !(G.is_rendering && !eval_ctx->for_render))
flag |= DUPLILIST_DO_UPDATE;
- if (for_render)
+ if (eval_ctx->for_render)
flag |= DUPLILIST_FOR_RENDER;
duplilist->first = duplilist->last = NULL;
- object_duplilist_recursive((ID *)sce, sce, ob, duplilist, NULL, persistent_id, 0, 0, flag);
+ object_duplilist_recursive(eval_ctx, (ID *)sce, sce, ob, duplilist, NULL, persistent_id, 0, 0, flag);
return duplilist;
}
/* note: previously updating was always done, this is why it defaults to be on
* but there are likely places it can be called without updating */
-ListBase *object_duplilist(Scene *sce, Object *ob, bool for_render)
+ListBase *object_duplilist(EvaluationContext *eval_ctx, Scene *sce, Object *ob)
{
- return object_duplilist_ex(sce, ob, true, for_render);
+ return object_duplilist_ex(eval_ctx, sce, ob, true);
}
-
void free_object_duplilist(ListBase *lb)
{
DupliObject *dob;
diff --git a/source/blender/blenkernel/intern/blender.c b/source/blender/blenkernel/intern/blender.c
index 96adadebb48..5b40e3ae68e 100644
--- a/source/blender/blenkernel/intern/blender.c
+++ b/source/blender/blenkernel/intern/blender.c
@@ -120,6 +120,7 @@ void free_blender(void)
IMB_exit();
BKE_images_exit();
+ DAG_exit();
BKE_brush_system_exit();
@@ -137,7 +138,7 @@ void initglobals(void)
U.savetime = 1;
- G.main = MEM_callocN(sizeof(Main), "initglobals");
+ G.main = BKE_main_new();
strcpy(G.ima, "//");
diff --git a/source/blender/blenkernel/intern/constraint.c b/source/blender/blenkernel/intern/constraint.c
index 0dbb739e6f8..50e74dfba44 100644
--- a/source/blender/blenkernel/intern/constraint.c
+++ b/source/blender/blenkernel/intern/constraint.c
@@ -166,7 +166,7 @@ bConstraintOb *BKE_constraints_make_evalob(Scene *scene, Object *ob, void *subda
unit_m4(cob->startmat);
break;
}
-
+
return cob;
}
@@ -3351,7 +3351,8 @@ static void shrinkwrap_get_tarmat(bConstraint *con, bConstraintOb *cob, bConstra
float co[3] = {0.0f, 0.0f, 0.0f};
SpaceTransform transform;
- DerivedMesh *target = object_get_derived_final(ct->tar);
+ /* TODO(sergey): use proper for_render flag here when known. */
+ DerivedMesh *target = object_get_derived_final(ct->tar, false);
BVHTreeFromMesh treeData = {NULL};
@@ -4014,7 +4015,8 @@ static void followtrack_evaluate(bConstraint *con, bConstraintOb *cob, ListBase
if (data->depth_ob) {
Object *depth_ob = data->depth_ob;
- DerivedMesh *target = object_get_derived_final(depth_ob);
+ /* TODO(sergey): use proper for_render flag here when known. */
+ DerivedMesh *target = object_get_derived_final(depth_ob, false);
if (target) {
BVHTreeFromMesh treeData = NULL_BVHTreeFromMesh;
BVHTreeRayHit hit;
diff --git a/source/blender/blenkernel/intern/depsgraph.c b/source/blender/blenkernel/intern/depsgraph.c
index 6ef20ecc047..8074d6bceec 100644
--- a/source/blender/blenkernel/intern/depsgraph.c
+++ b/source/blender/blenkernel/intern/depsgraph.c
@@ -42,6 +42,7 @@
#include "BLI_utildefines.h"
#include "BLI_listbase.h"
#include "BLI_ghash.h"
+#include "BLI_threads.h"
#include "DNA_anim_types.h"
#include "DNA_camera_types.h"
@@ -78,8 +79,22 @@
#include "BKE_screen.h"
#include "BKE_tracking.h"
+#include "atomic_ops.h"
+
#include "depsgraph_private.h"
-
+
+static SpinLock threaded_update_lock;
+
+void DAG_init(void)
+{
+ BLI_spin_init(&threaded_update_lock);
+}
+
+void DAG_exit(void)
+{
+ BLI_spin_end(&threaded_update_lock);
+}
+
/* Queue and stack operations for dag traversal
*
* the queue store a list of freenodes to avoid successive alloc/dealloc
@@ -418,22 +433,47 @@ static void dag_add_lamp_driver_relations(DagForest *dag, DagNode *node, Lamp *l
la->id.flag &= ~LIB_DOIT;
}
+static void check_and_create_collision_relation(DagForest *dag, Object *ob, DagNode *node, Object *ob1, int skip_forcefield, bool no_collision)
+{
+ DagNode *node2;
+ if (ob1->pd && (ob1->pd->deflect || ob1->pd->forcefield) && (ob1 != ob)) {
+ if ((skip_forcefield && ob1->pd->forcefield == skip_forcefield) || (no_collision && ob1->pd->forcefield == 0))
+ return;
+ node2 = dag_get_node(dag, ob1);
+ dag_add_relation(dag, node2, node, DAG_RL_DATA_DATA | DAG_RL_OB_DATA, "Field Collision");
+ }
+}
+
static void dag_add_collision_field_relation(DagForest *dag, Scene *scene, Object *ob, DagNode *node, int skip_forcefield, bool no_collision)
{
Base *base;
- DagNode *node2;
+ ParticleSystem *particle_system;
+
+ for (particle_system = ob->particlesystem.first;
+ particle_system;
+ particle_system = particle_system->next)
+ {
+ EffectorWeights *effector_weights = particle_system->part->effector_weights;
+ if (effector_weights->group) {
+ GroupObject *group_object;
+
+ for (group_object = effector_weights->group->gobject.first;
+ group_object;
+ group_object = group_object->next)
+ {
+ if ((group_object->ob->lay & ob->lay)) {
+ check_and_create_collision_relation(dag, ob, node, group_object->ob, skip_forcefield, no_collision);
+ }
+ }
+ }
+ }
/* would be nice to have a list of colliders here
* so for now walk all objects in scene check 'same layer rule' */
for (base = scene->base.first; base; base = base->next) {
- if ((base->lay & ob->lay) && base->object->pd) {
+ if ((base->lay & ob->lay)) {
Object *ob1 = base->object;
- if ((ob1->pd->deflect || ob1->pd->forcefield) && (ob1 != ob)) {
- if ((skip_forcefield && ob1->pd->forcefield == skip_forcefield) || (no_collision && ob1->pd->forcefield == 0))
- continue;
- node2 = dag_get_node(dag, ob1);
- dag_add_relation(dag, node2, node, DAG_RL_DATA_DATA | DAG_RL_OB_DATA, "Field Collision");
- }
+ check_and_create_collision_relation(dag, ob, node, ob1, skip_forcefield, no_collision);
}
}
}
@@ -2680,6 +2720,81 @@ void DAG_pose_sort(Object *ob)
ugly_hack_sorry = 1;
}
+/* ************************ DAG FOR THREADED UPDATE ********************* */
+
+/* Initialize run-time data in the graph needed for traversing it
+ * from multiple threads and start threaded tree traversal by adding
+ * the root node to the queue.
+ *
+ * This will mark DAG nodes as object/non-object and will calculate
+ * num_pending_parents of nodes (which is how many non-updated parents node
+ * have, which helps a lot checking whether node could be scheduled
+ * already or not).
+ */
+void DAG_threaded_update_begin(Scene *scene,
+ void (*func)(void *node, void *user_data),
+ void *user_data)
+{
+ DagNode *node, *root_node;
+
+ /* We reset num_pending_parents to zero first and tag node as not scheduled yet... */
+ for (node = scene->theDag->DagNode.first; node; node = node->next) {
+ node->num_pending_parents = 0;
+ node->scheduled = false;
+ }
+
+ /* ... and then iterate over all the nodes and
+ * increase num_pending_parents for node childs.
+ */
+ for (node = scene->theDag->DagNode.first; node; node = node->next) {
+ DagAdjList *itA;
+
+ for (itA = node->child; itA; itA = itA->next) {
+ if (itA->node != node) {
+ itA->node->num_pending_parents++;
+ }
+ }
+ }
+
+ /* Add root node to the queue. */
+ root_node = scene->theDag->DagNode.first;
+ root_node->scheduled = true;
+ func(root_node, user_data);
+}
+
+/* This function is called when handling node is done.
+ *
+ * This function updates num_pending_parents for all childs and
+ * schedules them if they're ready.
+ */
+void DAG_threaded_update_handle_node_updated(void *node_v,
+ void (*func)(void *node, void *user_data),
+ void *user_data)
+{
+ DagNode *node = node_v;
+ DagAdjList *itA;
+
+ for (itA = node->child; itA; itA = itA->next) {
+ DagNode *child_node = itA->node;
+ if (child_node != node) {
+ atomic_sub_uint32(&child_node->num_pending_parents, 1);
+
+ if (child_node->num_pending_parents == 0) {
+ bool need_schedule;
+
+ BLI_spin_lock(&threaded_update_lock);
+ need_schedule = child_node->scheduled == false;
+ child_node->scheduled = true;
+ BLI_spin_unlock(&threaded_update_lock);
+
+ if (need_schedule) {
+ func(child_node, user_data);
+ }
+ }
+ }
+ }
+}
+
/* ************************ DAG DEBUGGING ********************* */
void DAG_print_dependencies(Main *bmain, Scene *scene, Object *ob)
@@ -2699,3 +2814,100 @@ void DAG_print_dependencies(Main *bmain, Scene *scene, Object *ob)
dag_print_dependencies = 0;
}
+/* ************************ DAG tagging and querying ********************* */
+
+void DAG_tag_clear_nodes(Scene *scene)
+{
+ DagNode *node;
+
+ for (node = scene->theDag->DagNode.first; node; node = node->next) {
+ node->tag = false;
+ }
+}
+
+void DAG_tag_node_for_object(Scene *scene, void *object)
+{
+ DagNode *node = dag_get_node(scene->theDag, object);
+
+ node->tag = true;
+}
+
+void DAG_tag_flush_nodes(Scene *scene)
+{
+ DagNodeQueue *node_queue;
+ DagNode *node, *root_node;
+
+ node_queue = queue_create(DAGQUEUEALLOC);
+
+ for (node = scene->theDag->DagNode.first; node; node = node->next) {
+ node->color = DAG_WHITE;
+ }
+
+ root_node = scene->theDag->DagNode.first;
+ root_node->color = DAG_GRAY;
+ push_stack(node_queue, root_node);
+
+ while (node_queue->count) {
+ DagAdjList *itA;
+ bool has_new_nodes = false;
+
+ node = get_top_node_queue(node_queue);
+
+ /* Schedule all child nodes. */
+ for (itA = node->child; itA; itA = itA->next) {
+ if (itA->node->color == DAG_WHITE) {
+ itA->node->color = DAG_GRAY;
+ push_stack(node_queue, itA->node);
+ has_new_nodes = true;
+ }
+ }
+
+ if (!has_new_nodes) {
+ node = pop_queue(node_queue);
+ if (node->ob == scene) {
+ break;
+ }
+
+ /* Flush tag from child to current node. */
+ for (itA = node->child; itA; itA = itA->next) {
+ if (itA->node->tag) {
+ node->tag = true;
+ break;
+ }
+ }
+
+ node->color = DAG_BLACK;
+ }
+ }
+
+ queue_delete(node_queue);
+}
+
+/* Will return Object ID if node represents Object,
+ * and will return NULL otherwise.
+ */
+Object *DAG_get_node_object(void *node_v)
+{
+ DagNode *node = node_v;
+
+ if (node->type == ID_OB) {
+ return node->ob;
+ }
+
+ return NULL;
+}
+
+/* Returns node name, used for debug output only, atm. */
+const char *DAG_get_node_name(void *node_v)
+{
+ DagNode *node = node_v;
+
+ return dag_node_name(node);
+}
+
+bool DAG_get_node_tag(void *node_v)
+{
+ DagNode *node = node_v;
+
+ return node->tag;
+}
diff --git a/source/blender/blenkernel/intern/displist.c b/source/blender/blenkernel/intern/displist.c
index 1abb738608e..7ad8e80665e 100644
--- a/source/blender/blenkernel/intern/displist.c
+++ b/source/blender/blenkernel/intern/displist.c
@@ -49,9 +49,11 @@
#include "BLI_utildefines.h"
#include "BKE_global.h"
+#include "BKE_depsgraph.h"
#include "BKE_displist.h"
#include "BKE_cdderivedmesh.h"
#include "BKE_object.h"
+#include "BKE_main.h"
#include "BKE_mball.h"
#include "BKE_material.h"
#include "BKE_curve.h"
@@ -709,7 +711,7 @@ float BKE_displist_calc_taper(Scene *scene, Object *taperobj, int cur, int tot)
return displist_calc_taper(scene, taperobj, fac);
}
-void BKE_displist_make_mball(Scene *scene, Object *ob)
+void BKE_displist_make_mball(EvaluationContext *eval_ctx, Scene *scene, Object *ob)
{
if (!ob || ob->type != OB_MBALL)
return;
@@ -723,7 +725,7 @@ void BKE_displist_make_mball(Scene *scene, Object *ob)
if (ob->type == OB_MBALL) {
if (ob == BKE_mball_basis_find(scene, ob)) {
- BKE_mball_polygonize(scene, ob, &ob->curve_cache->disp, false);
+ BKE_mball_polygonize(eval_ctx, scene, ob, &ob->curve_cache->disp);
BKE_mball_texspace_calc(ob);
object_deform_mball(ob, &ob->curve_cache->disp);
@@ -733,9 +735,9 @@ void BKE_displist_make_mball(Scene *scene, Object *ob)
}
}
-void BKE_displist_make_mball_forRender(Scene *scene, Object *ob, ListBase *dispbase)
+void BKE_displist_make_mball_forRender(EvaluationContext *eval_ctx, Scene *scene, Object *ob, ListBase *dispbase)
{
- BKE_mball_polygonize(scene, ob, dispbase, true);
+ BKE_mball_polygonize(eval_ctx, scene, ob, dispbase);
BKE_mball_texspace_calc(ob);
object_deform_mball(ob, dispbase);
diff --git a/source/blender/blenkernel/intern/dynamicpaint.c b/source/blender/blenkernel/intern/dynamicpaint.c
index e2b752ea352..5941e8b5703 100644
--- a/source/blender/blenkernel/intern/dynamicpaint.c
+++ b/source/blender/blenkernel/intern/dynamicpaint.c
@@ -560,7 +560,7 @@ static int subframe_updateObject(Scene *scene, Object *ob, int flags, int parent
/* ignore cache clear during subframe updates
* to not mess up cache validity */
object_cacheIgnoreClear(ob, 1);
- BKE_object_handle_update(scene, ob);
+ BKE_object_handle_update(G.main->eval_ctx, scene, ob);
object_cacheIgnoreClear(ob, 0);
}
else
diff --git a/source/blender/blenkernel/intern/group.c b/source/blender/blenkernel/intern/group.c
index a5cbf064bc2..06e63e9b754 100644
--- a/source/blender/blenkernel/intern/group.c
+++ b/source/blender/blenkernel/intern/group.c
@@ -47,6 +47,7 @@
#include "BLI_utildefines.h"
+#include "BKE_depsgraph.h"
#include "BKE_global.h"
#include "BKE_group.h"
#include "BKE_library.h"
@@ -334,7 +335,7 @@ static void group_replaces_nla(Object *parent, Object *target, char mode)
* you can draw everything, leaves tags in objects to signal it needs further updating */
/* note: does not work for derivedmesh and render... it recreates all again in convertblender.c */
-void BKE_group_handle_recalc_and_update(Scene *scene, Object *UNUSED(parent), Group *group)
+void BKE_group_handle_recalc_and_update(EvaluationContext *eval_ctx, Scene *scene, Object *UNUSED(parent), Group *group)
{
GroupObject *go;
@@ -356,7 +357,7 @@ void BKE_group_handle_recalc_and_update(Scene *scene, Object *UNUSED(parent), Gr
go->ob->recalc = go->recalc;
group_replaces_nla(parent, go->ob, 's');
- BKE_object_handle_update(scene, go->ob);
+ BKE_object_handle_update(eval_ctx, scene, go->ob);
group_replaces_nla(parent, go->ob, 'e');
/* leave recalc tags in case group members are in normal scene */
@@ -374,7 +375,7 @@ void BKE_group_handle_recalc_and_update(Scene *scene, Object *UNUSED(parent), Gr
for (go = group->gobject.first; go; go = go->next) {
if (go->ob) {
if (go->ob->recalc) {
- BKE_object_handle_update(scene, go->ob);
+ BKE_object_handle_update(eval_ctx, scene, go->ob);
}
}
}
diff --git a/source/blender/blenkernel/intern/library.c b/source/blender/blenkernel/intern/library.c
index 910ab0ffe1b..43bd6a0b36c 100644
--- a/source/blender/blenkernel/intern/library.c
+++ b/source/blender/blenkernel/intern/library.c
@@ -82,6 +82,7 @@
#include "BKE_camera.h"
#include "BKE_context.h"
#include "BKE_curve.h"
+#include "BKE_depsgraph.h"
#include "BKE_fcurve.h"
#include "BKE_font.h"
#include "BKE_global.h"
@@ -1009,6 +1010,12 @@ void BKE_libblock_free_us(ListBase *lb, void *idv) /* test users */
}
}
+Main *BKE_main_new(void)
+{
+ Main *bmain = MEM_callocN(sizeof(Main), "new main");
+ bmain->eval_ctx = MEM_callocN(sizeof(EvaluationContext), "EvaluationCintext");
+ return bmain;
+}
void free_main(Main *mainvar)
{
@@ -1069,6 +1076,7 @@ void free_main(Main *mainvar)
}
}
+ MEM_freeN(mainvar->eval_ctx);
MEM_freeN(mainvar);
}
diff --git a/source/blender/blenkernel/intern/mball.c b/source/blender/blenkernel/intern/mball.c
index 1128c3e55c7..603eb50122f 100644
--- a/source/blender/blenkernel/intern/mball.c
+++ b/source/blender/blenkernel/intern/mball.c
@@ -57,6 +57,7 @@
/* #include "BKE_object.h" */
#include "BKE_animsys.h"
#include "BKE_curve.h"
+#include "BKE_depsgraph.h"
#include "BKE_scene.h"
#include "BKE_library.h"
#include "BKE_displist.h"
@@ -485,14 +486,15 @@ void BKE_mball_properties_copy(Scene *scene, Object *active_object)
int basisnr, obnr;
char basisname[MAX_ID_NAME], obname[MAX_ID_NAME];
SceneBaseIter iter;
+ EvaluationContext *eval_ctx = G.main->eval_ctx;
BLI_split_name_num(basisname, &basisnr, active_object->id.name + 2, '.');
/* XXX recursion check, see scene.c, just too simple code this BKE_scene_base_iter_next() */
- if (F_ERROR == BKE_scene_base_iter_next(&iter, &sce_iter, 0, NULL, NULL))
+ if (F_ERROR == BKE_scene_base_iter_next(eval_ctx, &iter, &sce_iter, 0, NULL, NULL))
return;
- while (BKE_scene_base_iter_next(&iter, &sce_iter, 1, &base, &ob)) {
+ while (BKE_scene_base_iter_next(eval_ctx, &iter, &sce_iter, 1, &base, &ob)) {
if (ob->type == OB_MBALL) {
if (ob != active_object) {
BLI_split_name_num(obname, &obnr, ob->id.name + 2, '.');
@@ -530,14 +532,15 @@ Object *BKE_mball_basis_find(Scene *scene, Object *basis)
int basisnr, obnr;
char basisname[MAX_ID_NAME], obname[MAX_ID_NAME];
SceneBaseIter iter;
+ EvaluationContext *eval_ctx = G.main->eval_ctx;
BLI_split_name_num(basisname, &basisnr, basis->id.name + 2, '.');
/* XXX recursion check, see scene.c, just too simple code this BKE_scene_base_iter_next() */
- if (F_ERROR == BKE_scene_base_iter_next(&iter, &sce_iter, 0, NULL, NULL))
+ if (F_ERROR == BKE_scene_base_iter_next(eval_ctx, &iter, &sce_iter, 0, NULL, NULL))
return NULL;
- while (BKE_scene_base_iter_next(&iter, &sce_iter, 1, &base, &ob)) {
+ while (BKE_scene_base_iter_next(eval_ctx, &iter, &sce_iter, 1, &base, &ob)) {
if (ob->type == OB_MBALL) {
if (ob != bob) {
BLI_split_name_num(obname, &obnr, ob->id.name + 2, '.');
@@ -1637,7 +1640,7 @@ static void polygonize(PROCESS *process, MetaBall *mb)
}
}
-static float init_meta(PROCESS *process, Scene *scene, Object *ob) /* return totsize */
+static float init_meta(EvaluationContext *eval_ctx, PROCESS *process, Scene *scene, Object *ob) /* return totsize */
{
Scene *sce_iter = scene;
Base *base;
@@ -1657,8 +1660,8 @@ static float init_meta(PROCESS *process, Scene *scene, Object *ob) /* return
BLI_split_name_num(obname, &obnr, ob->id.name + 2, '.');
/* make main array */
- BKE_scene_base_iter_next(&iter, &sce_iter, 0, NULL, NULL);
- while (BKE_scene_base_iter_next(&iter, &sce_iter, 1, &base, &bob)) {
+ BKE_scene_base_iter_next(eval_ctx, &iter, &sce_iter, 0, NULL, NULL);
+ while (BKE_scene_base_iter_next(eval_ctx, &iter, &sce_iter, 1, &base, &bob)) {
if (bob->type == OB_MBALL) {
zero_size = 0;
@@ -2211,7 +2214,7 @@ static void init_metaball_octal_tree(PROCESS *process, int depth)
subdivide_metaball_octal_node(node, size[0], size[1], size[2], process->metaball_tree->depth);
}
-static void mball_count(PROCESS *process, Scene *scene, Object *basis)
+static void mball_count(EvaluationContext *eval_ctx, PROCESS *process, Scene *scene, Object *basis)
{
Scene *sce_iter = scene;
Base *base;
@@ -2225,10 +2228,10 @@ static void mball_count(PROCESS *process, Scene *scene, Object *basis)
process->totelem = 0;
/* XXX recursion check, see scene.c, just too simple code this BKE_scene_base_iter_next() */
- if (F_ERROR == BKE_scene_base_iter_next(&iter, &sce_iter, 0, NULL, NULL))
+ if (F_ERROR == BKE_scene_base_iter_next(eval_ctx, &iter, &sce_iter, 0, NULL, NULL))
return;
- while (BKE_scene_base_iter_next(&iter, &sce_iter, 1, &base, &ob)) {
+ while (BKE_scene_base_iter_next(eval_ctx, &iter, &sce_iter, 1, &base, &ob)) {
if (ob->type == OB_MBALL) {
if (ob == bob) {
MetaBall *mb = ob->data;
@@ -2264,7 +2267,7 @@ static void mball_count(PROCESS *process, Scene *scene, Object *basis)
}
}
-void BKE_mball_polygonize(Scene *scene, Object *ob, ListBase *dispbase, bool for_render)
+void BKE_mball_polygonize(EvaluationContext *eval_ctx, Scene *scene, Object *ob, ListBase *dispbase)
{
MetaBall *mb;
DispList *dl;
@@ -2274,10 +2277,10 @@ void BKE_mball_polygonize(Scene *scene, Object *ob, ListBase *dispbase, bool for
mb = ob->data;
- mball_count(&process, scene, ob);
+ mball_count(eval_ctx, &process, scene, ob);
if (process.totelem == 0) return;
- if ((for_render == false) && (mb->flag == MB_UPDATE_NEVER)) return;
+ if ((eval_ctx->for_render == false) && (mb->flag == MB_UPDATE_NEVER)) return;
if ((G.moving & (G_TRANSFORM_OBJ | G_TRANSFORM_EDIT)) && mb->flag == MB_UPDATE_FAST) return;
process.thresh = mb->thresh;
@@ -2286,7 +2289,7 @@ void BKE_mball_polygonize(Scene *scene, Object *ob, ListBase *dispbase, bool for
process.mainb = MEM_mallocN(sizeof(void *) * process.totelem, "mainb");
/* initialize all mainb (MetaElems) */
- totsize = init_meta(&process, scene, ob);
+ totsize = init_meta(eval_ctx, &process, scene, ob);
/* if scene includes more than one MetaElem, then octal tree optimization is used */
if ((process.totelem > 1) && (process.totelem <= 64)) init_metaball_octal_tree(&process, 1);
@@ -2315,7 +2318,7 @@ void BKE_mball_polygonize(Scene *scene, Object *ob, ListBase *dispbase, bool for
}
/* width is size per polygonize cube */
- if (for_render) {
+ if (eval_ctx->for_render) {
width = mb->rendersize;
}
else {
diff --git a/source/blender/blenkernel/intern/object.c b/source/blender/blenkernel/intern/object.c
index e480f1a6bf7..c069abfaf35 100644
--- a/source/blender/blenkernel/intern/object.c
+++ b/source/blender/blenkernel/intern/object.c
@@ -2369,7 +2369,6 @@ void BKE_object_where_is_calc_time_ex(Scene *scene, Object *ob, float ctime,
/* solve constraints */
if (ob->constraints.first && !(ob->transflag & OB_NO_CONSTRAINTS)) {
bConstraintOb *cob;
-
cob = BKE_constraints_make_evalob(scene, ob, NULL, CONSTRAINT_OBTYPE_OBJECT);
BKE_solve_constraints(&ob->constraints, cob, ctime);
BKE_constraints_clear_evalob(cob);
@@ -2686,8 +2685,7 @@ bool BKE_object_minmax_dupli(Scene *scene, Object *ob, float r_min[3], float r_m
else {
ListBase *lb;
DupliObject *dob;
-
- lb = object_duplilist(scene, ob, FALSE);
+ lb = object_duplilist(G.main->eval_ctx, scene, ob);
for (dob = lb->first; dob; dob = dob->next) {
if ((use_hidden == false) && (dob->no_draw != 0)) {
/* pass */
@@ -2764,7 +2762,7 @@ void BKE_scene_foreach_display_point(
ListBase *lb;
DupliObject *dob;
- lb = object_duplilist(scene, ob, FALSE);
+ lb = object_duplilist(G.main->eval_ctx, scene, ob);
for (dob = lb->first; dob; dob = dob->next) {
if (dob->no_draw == 0) {
BKE_object_foreach_display_point(dob->ob, dob->mat, func_cb, user_data);
@@ -2852,7 +2850,8 @@ bool BKE_object_parent_loop_check(const Object *par, const Object *ob)
/* the main object update call, for object matrix, constraints, keys and displist (modifiers) */
/* requires flags to be set! */
/* Ideally we shouldn't have to pass the rigid body world, but need bigger restructuring to avoid id */
-void BKE_object_handle_update_ex(Scene *scene, Object *ob,
+void BKE_object_handle_update_ex(EvaluationContext *eval_ctx,
+ Scene *scene, Object *ob,
RigidBodyWorld *rbw)
{
if (ob->recalc & OB_RECALC_ALL) {
@@ -2922,17 +2921,6 @@ void BKE_object_handle_update_ex(Scene *scene, Object *ob,
switch (ob->type) {
case OB_MESH:
{
-#if 0 // XXX, comment for 2.56a release, background wont set 'scene->customdata_mask'
- BMEditMesh *em = (ob == scene->obedit) ? BKE_editmesh_from_object(ob) : NULL;
- BLI_assert((scene->customdata_mask & CD_MASK_BAREMESH) == CD_MASK_BAREMESH);
- if (em) {
- makeDerivedMesh(scene, ob, em, scene->customdata_mask, 0); /* was CD_MASK_BAREMESH */
- }
- else {
- makeDerivedMesh(scene, ob, NULL, scene->customdata_mask, 0);
- }
-
-#else /* ensure CD_MASK_BAREMESH for now */
BMEditMesh *em = (ob == scene->obedit) ? BKE_editmesh_from_object(ob) : NULL;
uint64_t data_mask = scene->customdata_mask | CD_MASK_BAREMESH;
if (em) {
@@ -2941,7 +2929,6 @@ void BKE_object_handle_update_ex(Scene *scene, Object *ob,
else {
makeDerivedMesh(scene, ob, NULL, data_mask, 0);
}
-#endif
break;
}
case OB_ARMATURE:
@@ -2957,7 +2944,7 @@ void BKE_object_handle_update_ex(Scene *scene, Object *ob,
break;
case OB_MBALL:
- BKE_displist_make_mball(scene, ob);
+ BKE_displist_make_mball(eval_ctx, scene, ob);
break;
case OB_CURVE:
@@ -3001,7 +2988,7 @@ void BKE_object_handle_update_ex(Scene *scene, Object *ob,
while (psys) {
if (psys_check_enabled(ob, psys)) {
/* check use of dupli objects here */
- if (psys->part && (psys->part->draw_as == PART_DRAW_REND || G.is_rendering) &&
+ if (psys->part && (psys->part->draw_as == PART_DRAW_REND || eval_ctx->for_render) &&
((psys->part->ren_as == PART_DRAW_OB && psys->part->dup_ob) ||
(psys->part->ren_as == PART_DRAW_GR && psys->part->dup_group)))
{
@@ -3021,7 +3008,7 @@ void BKE_object_handle_update_ex(Scene *scene, Object *ob,
psys = psys->next;
}
- if (G.is_rendering && ob->transflag & OB_DUPLIPARTS) {
+ if (eval_ctx->for_render && ob->transflag & OB_DUPLIPARTS) {
/* this is to make sure we get render level duplis in groups:
* the derivedmesh must be created before init_render_mesh,
* since object_duplilist does dupliparticles before that */
@@ -3048,7 +3035,7 @@ void BKE_object_handle_update_ex(Scene *scene, Object *ob,
/* the no-group proxy case, we call update */
if (ob->proxy_group == NULL) {
// printf("call update, lib ob %s proxy %s\n", ob->proxy->id.name, ob->id.name);
- BKE_object_handle_update(scene, ob->proxy);
+ BKE_object_handle_update(eval_ctx, scene, ob->proxy);
}
}
}
@@ -3057,9 +3044,9 @@ void BKE_object_handle_update_ex(Scene *scene, Object *ob,
* e.g. "scene" <-- set 1 <-- set 2 ("ob" lives here) <-- set 3 <-- ... <-- set n
* rigid bodies depend on their world so use BKE_object_handle_update_ex() to also pass along the corrent rigid body world
*/
-void BKE_object_handle_update(Scene *scene, Object *ob)
+void BKE_object_handle_update(EvaluationContext *eval_ctx, Scene *scene, Object *ob)
{
- BKE_object_handle_update_ex(scene, ob, NULL);
+ BKE_object_handle_update_ex(eval_ctx, scene, ob, NULL);
}
void BKE_object_sculpt_modifiers_changed(Object *ob)
diff --git a/source/blender/blenkernel/intern/pointcache.c b/source/blender/blenkernel/intern/pointcache.c
index d2ef59b238f..7b3539db287 100644
--- a/source/blender/blenkernel/intern/pointcache.c
+++ b/source/blender/blenkernel/intern/pointcache.c
@@ -1408,9 +1408,8 @@ void BKE_ptcache_ids_from_object(ListBase *lb, Object *ob, Scene *scene, int dup
if (scene && (duplis-- > 0) && (ob->transflag & OB_DUPLI)) {
ListBase *lb_dupli_ob;
-
/* don't update the dupli groups, we only want their pid's */
- if ((lb_dupli_ob = object_duplilist_ex(scene, ob, FALSE, FALSE))) {
+ if ((lb_dupli_ob = object_duplilist_ex(G.main->eval_ctx, scene, ob, FALSE))) {
DupliObject *dob;
for (dob= lb_dupli_ob->first; dob; dob= dob->next) {
if (dob->ob != ob) { /* avoids recursive loops with dupliframes: bug 22988 */
@@ -3159,7 +3158,7 @@ static void *ptcache_bake_thread(void *ptr)
efra = data->endframe;
for (; (*data->cfra_ptr <= data->endframe) && !data->break_operation; *data->cfra_ptr+=data->step) {
- BKE_scene_update_for_newframe(data->main, data->scene, data->scene->lay);
+ BKE_scene_update_for_newframe(G.main->eval_ctx, data->main, data->scene, data->scene->lay);
if (G.background) {
printf("bake: frame %d :: %d\n", (int)*data->cfra_ptr, data->endframe);
}
@@ -3390,8 +3389,9 @@ void BKE_ptcache_bake(PTCacheBaker *baker)
scene->r.framelen = frameleno;
CFRA = cfrao;
- if (bake) /* already on cfra unless baking */
- BKE_scene_update_for_newframe(bmain, scene, scene->lay);
+ if (bake) { /* already on cfra unless baking */
+ BKE_scene_update_for_newframe(bmain->eval_ctx, bmain, scene, scene->lay);
+ }
if (thread_data.break_operation)
WM_cursor_wait(0);
diff --git a/source/blender/blenkernel/intern/scene.c b/source/blender/blenkernel/intern/scene.c
index 80fcee18513..a82bbb7ca37 100644
--- a/source/blender/blenkernel/intern/scene.c
+++ b/source/blender/blenkernel/intern/scene.c
@@ -58,6 +58,7 @@
#include "BLI_callbacks.h"
#include "BLI_string.h"
#include "BLI_threads.h"
+#include "BLI_task.h"
#include "BLF_translation.h"
@@ -87,6 +88,8 @@
#include "RE_engine.h"
+#include "PIL_time.h"
+
#include "IMB_colormanagement.h"
//XXX #include "BIF_previewrender.h"
@@ -736,9 +739,9 @@ void BKE_scene_unlink(Main *bmain, Scene *sce, Scene *newsce)
/* used by metaballs
* doesn't return the original duplicated object, only dupli's
*/
-int BKE_scene_base_iter_next(SceneBaseIter *iter, Scene **scene, int val, Base **base, Object **ob)
+int BKE_scene_base_iter_next(EvaluationContext *eval_ctx, SceneBaseIter *iter,
+ Scene **scene, int val, Base **base, Object **ob)
{
- static int in_next_object = 0;
int run_again = 1;
/* init */
@@ -746,18 +749,8 @@ int BKE_scene_base_iter_next(SceneBaseIter *iter, Scene **scene, int val, Base *
iter->fase = F_START;
iter->dupob = NULL;
iter->duplilist = NULL;
-
- /* XXX particle systems with metas+dupligroups call this recursively */
- /* see bug #18725 */
- if (in_next_object) {
- printf("ERROR: Metaball generation called recursively, not supported\n");
-
- return F_ERROR;
- }
}
else {
- in_next_object = 1;
-
/* run_again is set when a duplilist has been ended */
while (run_again) {
run_again = 0;
@@ -814,7 +807,7 @@ int BKE_scene_base_iter_next(SceneBaseIter *iter, Scene **scene, int val, Base *
* this enters eternal loop because of
* makeDispListMBall getting called inside of group_duplilist */
if ((*base)->object->dup_group == NULL) {
- iter->duplilist = object_duplilist((*scene), (*base)->object, FALSE);
+ iter->duplilist = object_duplilist_ex(eval_ctx, (*scene), (*base)->object, false);
iter->dupob = iter->duplilist->first;
@@ -856,9 +849,6 @@ int BKE_scene_base_iter_next(SceneBaseIter *iter, Scene **scene, int val, Base *
}
#endif
- /* reset recursion test */
- in_next_object = 0;
-
return iter->fase;
}
@@ -1128,7 +1118,7 @@ static void scene_update_drivers(Main *UNUSED(bmain), Scene *scene)
}
/* deps hack - do extra recalcs at end */
-static void scene_depsgraph_hack(Scene *scene, Scene *scene_parent)
+static void scene_depsgraph_hack(EvaluationContext *eval_ctx, Scene *scene, Scene *scene_parent)
{
Base *base;
@@ -1137,7 +1127,7 @@ static void scene_depsgraph_hack(Scene *scene, Scene *scene_parent)
/* sets first, we allow per definition current scene to have
* dependencies on sets, but not the other way around. */
if (scene->set)
- scene_depsgraph_hack(scene->set, scene_parent);
+ scene_depsgraph_hack(eval_ctx, scene->set, scene_parent);
for (base = scene->base.first; base; base = base->next) {
Object *ob = base->object;
@@ -1152,7 +1142,7 @@ static void scene_depsgraph_hack(Scene *scene, Scene *scene_parent)
recalc |= OB_RECALC_DATA;
ob->recalc |= recalc;
- BKE_object_handle_update(scene_parent, ob);
+ BKE_object_handle_update(eval_ctx, scene_parent, ob);
if (ob->dup_group && (ob->transflag & OB_DUPLIGROUP)) {
GroupObject *go;
@@ -1161,7 +1151,7 @@ static void scene_depsgraph_hack(Scene *scene, Scene *scene_parent)
if (go->ob)
go->ob->recalc |= recalc;
}
- BKE_group_handle_recalc_and_update(scene_parent, ob, ob->dup_group);
+ BKE_group_handle_recalc_and_update(eval_ctx, scene_parent, ob, ob->dup_group);
}
}
}
@@ -1186,32 +1176,240 @@ static void scene_do_rb_simulation_recursive(Scene *scene, float ctime)
BKE_rigidbody_do_simulation(scene, ctime);
}
-static void scene_update_tagged_recursive(Main *bmain, Scene *scene, Scene *scene_parent)
+/* Used to visualize CPU threads activity during threaded object update,
+ * would pollute STDERR with whole bunch of timing information which then
+ * could be parsed and nicely visualized.
+ */
+#undef DETAILED_ANALYSIS_OUTPUT
+
+/* Mballs evaluation uses BKE_scene_base_iter_next which calls
+ * duplilist for all objects in the scene. This leads to conflict
+ * accessing and writting same data from multipl threads.
+ *
+ * Ideally Mballs shouldn't do such an iteration and use DAG
+ * queries instead. For the time being we've got new DAG
+ * let's keep it simple and update mballs in a ingle thread.
+ */
+#define MBALL_SINGLETHREAD_HACK
+
+typedef struct StatisicsEntry {
+ struct StatisicsEntry *next, *prev;
+ Object *object;
+ double start_time;
+ double duration;
+} StatisicsEntry;
+
+typedef struct ThreadedObjectUpdateState {
+ /* TODO(sergey): We might want this to be per-thread object. */
+ EvaluationContext *eval_ctx;
+ Scene *scene;
+ Scene *scene_parent;
+ double base_time;
+
+ /* Execution statistics */
+ ListBase statistics[BLENDER_MAX_THREADS];
+ bool has_updated_objects;
+
+#ifdef MBALL_SINGLETHREAD_HACK
+ bool has_mballs;
+#endif
+} ThreadedObjectUpdateState;
+
+static void scene_update_object_add_task(void *node, void *user_data);
+
+static void scene_update_all_bases(EvaluationContext *eval_ctx, Scene *scene, Scene *scene_parent)
{
Base *base;
-
- scene->customdata_mask = scene_parent->customdata_mask;
- /* sets first, we allow per definition current scene to have
- * dependencies on sets, but not the other way around. */
- if (scene->set)
- scene_update_tagged_recursive(bmain, scene->set, scene_parent);
-
- /* scene objects */
for (base = scene->base.first; base; base = base->next) {
- Object *ob = base->object;
-
- BKE_object_handle_update_ex(scene_parent, ob, scene->rigidbody_world);
-
- if (ob->dup_group && (ob->transflag & OB_DUPLIGROUP))
- BKE_group_handle_recalc_and_update(scene_parent, ob, ob->dup_group);
-
+ Object *object = base->object;
+
+ BKE_object_handle_update_ex(eval_ctx, scene_parent, object, scene->rigidbody_world);
+
+ if (object->dup_group && (object->transflag & OB_DUPLIGROUP))
+ BKE_group_handle_recalc_and_update(eval_ctx, scene_parent, object, object->dup_group);
+
/* always update layer, so that animating layers works (joshua july 2010) */
/* XXX commented out, this has depsgraph issues anyway - and this breaks setting scenes
* (on scene-set, the base-lay is copied to ob-lay (ton nov 2012) */
// base->lay = ob->lay;
}
-
+}
+
+static void scene_update_object_func(TaskPool *pool, void *taskdata, int threadid)
+{
+/* Disable print for now in favor of summary statistics at the end of update. */
+#define PRINT if (false) printf
+
+ ThreadedObjectUpdateState *state = (ThreadedObjectUpdateState *) BLI_task_pool_userdata(pool);
+ void *node = taskdata;
+ Object *object = DAG_get_node_object(node);
+ EvaluationContext *eval_ctx = state->eval_ctx;
+ Scene *scene = state->scene;
+ Scene *scene_parent = state->scene_parent;
+
+#ifdef MBALL_SINGLETHREAD_HACK
+ if (object && object->type == OB_MBALL) {
+ state->has_mballs = true;
+ }
+ else
+#endif
+ if (object) {
+ double start_time = 0.0;
+ bool add_to_stats = false;
+
+ PRINT("Thread %d: update object %s\n", threadid, object->id.name);
+
+ if (G.debug & G_DEBUG) {
+ start_time = PIL_check_seconds_timer();
+
+ if (object->recalc & OB_RECALC_ALL) {
+ state->has_updated_objects = true;
+ add_to_stats = true;
+ }
+ }
+
+ /* We only update object itself here, dupli-group will be updated
+ * separately from main thread because of we've got no idea about
+ * dependnecies inside the group.
+ */
+ BKE_object_handle_update_ex(eval_ctx, scene_parent, object, scene->rigidbody_world);
+
+ /* Calculate statistics. */
+ if (add_to_stats) {
+ StatisicsEntry *entry;
+
+ entry = MEM_mallocN(sizeof(StatisicsEntry), "update thread statistics");
+ entry->object = object;
+ entry->start_time = start_time;
+ entry->duration = PIL_check_seconds_timer() - start_time;
+
+ BLI_addtail(&state->statistics[threadid], entry);
+ }
+ }
+ else {
+ PRINT("Threda %d: update node %s\n", threadid,
+ DAG_get_node_name(node));
+ }
+
+ /* Update will decrease child's valency and schedule child with zero valency. */
+ DAG_threaded_update_handle_node_updated(node,scene_update_object_add_task, pool);
+
+#undef PRINT
+}
+
+static void scene_update_object_add_task(void *node, void *user_data)
+{
+ TaskPool *task_pool = user_data;
+
+ BLI_task_pool_push(task_pool, scene_update_object_func, node, false, TASK_PRIORITY_LOW);
+}
+
+static void print_threads_statistics(ThreadedObjectUpdateState *state)
+{
+ int i, tot_thread;
+
+ if ((G.debug & G_DEBUG) == 0) {
+ return;
+ }
+
+#ifdef DETAILED_ANALYSIS_OUTPUT
+ if (state->has_updated_objects) {
+ tot_thread = BLI_system_thread_count();
+
+ fprintf(stderr, "objects update base time %f\n", state->base_time);
+
+ for (i = 0; i < tot_thread; i++) {
+ StatisicsEntry *entry;
+ for (entry = state->statistics[i].first;
+ entry;
+ entry = entry->next)
+ {
+ fprintf(stderr, "thread %d object %s start_time %f duration %f\n",
+ i, entry->object->id.name + 2,
+ entry->start_time, entry->duration);
+ }
+ BLI_freelistN(&state->statistics[i]);
+ }
+ }
+#else
+ tot_thread = BLI_system_thread_count();
+
+ for (i = 0; i < tot_thread; i++) {
+ int total_objects = 0;
+ double total_time = 0.0;
+ StatisicsEntry *entry;
+
+ if (state->has_updated_objects) {
+ /* Don't pollute output if no objects were updated. */
+ for (entry = state->statistics[i].first;
+ entry;
+ entry = entry->next)
+ {
+ total_objects++;
+ total_time += entry->duration;
+ }
+
+ printf("Thread %d: total %d objects in %f sec.\n", i, total_objects, total_time);
+
+ for (entry = state->statistics[i].first;
+ entry;
+ entry = entry->next)
+ {
+ printf(" %s in %f sec\n", entry->object->id.name + 2, entry->duration);
+ }
+ }
+
+ BLI_freelistN(&state->statistics[i]);
+ }
+#endif
+}
+
+static void scene_update_objects(EvaluationContext *eval_ctx, Scene *scene, Scene *scene_parent)
+{
+ TaskScheduler *task_scheduler = BLI_task_scheduler_get();
+ TaskPool *task_pool;
+ ThreadedObjectUpdateState state;
+
+ state.eval_ctx = eval_ctx;
+ state.scene = scene;
+ state.scene_parent = scene_parent;
+ memset(state.statistics, 0, sizeof(state.statistics));
+ state.has_updated_objects = false;
+ state.base_time = PIL_check_seconds_timer();
+#ifdef MBALL_SINGLETHREAD_HACK
+ state.has_mballs = false;
+#endif
+
+ task_pool = BLI_task_pool_create(task_scheduler, &state);
+
+ DAG_threaded_update_begin(scene, scene_update_object_add_task, task_pool);
+ BLI_task_pool_work_and_wait(task_pool);
+ BLI_task_pool_free(task_pool);
+
+ if (G.debug & G_DEBUG) {
+ print_threads_statistics(&state);
+ }
+
+#ifdef MBALL_SINGLETHREAD_HACK
+ if (state.has_mballs) {
+ scene_update_all_bases(eval_ctx, scene, scene_parent);
+ }
+#endif
+}
+
+static void scene_update_tagged_recursive(EvaluationContext *eval_ctx, Main *bmain, Scene *scene, Scene *scene_parent)
+{
+ scene->customdata_mask = scene_parent->customdata_mask;
+
+ /* sets first, we allow per definition current scene to have
+ * dependencies on sets, but not the other way around. */
+ if (scene->set)
+ scene_update_tagged_recursive(eval_ctx, bmain, scene->set, scene_parent);
+
+ /* scene objects */
+ scene_update_objects(eval_ctx, scene, scene_parent);
+
/* scene drivers... */
scene_update_drivers(bmain, scene);
@@ -1223,8 +1421,7 @@ static void scene_update_tagged_recursive(Main *bmain, Scene *scene, Scene *scen
}
-/* this is called in main loop, doing tagged updates before redraw */
-void BKE_scene_update_tagged(Main *bmain, Scene *scene)
+void BKE_scene_update_tagged(EvaluationContext *eval_ctx, Main *bmain, Scene *scene)
{
Scene *sce_iter;
@@ -1251,7 +1448,7 @@ void BKE_scene_update_tagged(Main *bmain, Scene *scene)
*
* in the future this should handle updates for all datablocks, not
* only objects and scenes. - brecht */
- scene_update_tagged_recursive(bmain, scene, scene);
+ scene_update_tagged_recursive(eval_ctx, bmain, scene, scene);
/* extra call here to recalc scene animation (for sequencer) */
{
@@ -1271,10 +1468,13 @@ void BKE_scene_update_tagged(Main *bmain, Scene *scene)
}
/* applies changes right away, does all sets too */
-void BKE_scene_update_for_newframe(Main *bmain, Scene *sce, unsigned int lay)
+void BKE_scene_update_for_newframe(EvaluationContext *eval_ctx, Main *bmain, Scene *sce, unsigned int lay)
{
float ctime = BKE_scene_frame_get(sce);
Scene *sce_iter;
+#ifdef DETAILED_ANALYSIS_OUTPUT
+ double start_time = PIL_check_seconds_timer();
+#endif
/* keep this first */
BLI_callback_exec(bmain, &sce->id, BLI_CB_EVT_FRAME_CHANGE_PRE);
@@ -1329,9 +1529,9 @@ void BKE_scene_update_for_newframe(Main *bmain, Scene *sce, unsigned int lay)
scene_do_rb_simulation_recursive(sce, ctime);
/* BKE_object_handle_update() on all objects, groups and sets */
- scene_update_tagged_recursive(bmain, sce, sce);
+ scene_update_tagged_recursive(eval_ctx, bmain, sce, sce);
- scene_depsgraph_hack(sce, sce);
+ scene_depsgraph_hack(eval_ctx, sce, sce);
/* notify editors and python about recalc */
BLI_callback_exec(bmain, &sce->id, BLI_CB_EVT_SCENE_UPDATE_POST);
@@ -1341,6 +1541,10 @@ void BKE_scene_update_for_newframe(Main *bmain, Scene *sce, unsigned int lay)
/* clear recalc flags */
DAG_ids_clear_recalc(bmain);
+
+#ifdef DETAILED_ANALYSIS_OUTPUT
+ fprintf(stderr, "frame update start_time %f duration %f\n", start_time, PIL_check_seconds_timer() - start_time);
+#endif
}
/* return default layer, also used to patch old files */
diff --git a/source/blender/blenkernel/intern/sequencer.c b/source/blender/blenkernel/intern/sequencer.c
index 49b237fc3ea..dd2bd4383b6 100644
--- a/source/blender/blenkernel/intern/sequencer.c
+++ b/source/blender/blenkernel/intern/sequencer.c
@@ -57,6 +57,7 @@
#include "BLF_translation.h"
#include "BKE_animsys.h"
+#include "BKE_depsgraph.h"
#include "BKE_global.h"
#include "BKE_image.h"
#include "BKE_main.h"
@@ -498,7 +499,9 @@ void BKE_sequencer_pixel_from_sequencer_space_v4(struct Scene *scene, float pixe
/*********************** sequencer pipeline functions *************************/
-SeqRenderData BKE_sequencer_new_render_data(Main *bmain, Scene *scene, int rectx, int recty, int preview_render_size)
+SeqRenderData BKE_sequencer_new_render_data(EvaluationContext *eval_ctx,
+ Main *bmain, Scene *scene, int rectx, int recty,
+ int preview_render_size)
{
SeqRenderData rval;
@@ -509,6 +512,7 @@ SeqRenderData BKE_sequencer_new_render_data(Main *bmain, Scene *scene, int rectx
rval.preview_render_size = preview_render_size;
rval.motion_blur_samples = 0;
rval.motion_blur_shutter = 0;
+ rval.eval_ctx = eval_ctx;
return rval;
}
@@ -1506,6 +1510,7 @@ void BKE_sequencer_proxy_rebuild(SeqIndexBuildContext *context, short *stop, sho
SeqRenderData render_context;
Sequence *seq = context->seq;
Scene *scene = context->scene;
+ Main *bmain = context->bmain;
int cfra;
if (seq->type == SEQ_TYPE_MOVIE) {
@@ -1527,7 +1532,7 @@ void BKE_sequencer_proxy_rebuild(SeqIndexBuildContext *context, short *stop, sho
/* fail safe code */
- render_context = BKE_sequencer_new_render_data(context->bmain, context->scene,
+ render_context = BKE_sequencer_new_render_data(bmain->eval_ctx, bmain, context->scene,
(scene->r.size * (float) scene->r.xsch) / 100.0f + 0.5f,
(scene->r.size * (float) scene->r.ysch) / 100.0f + 0.5f, 100);
@@ -2449,7 +2454,7 @@ static ImBuf *seq_render_scene_strip(SeqRenderData context, Sequence *seq, float
const short is_rendering = G.is_rendering;
const short is_background = G.background;
- const int do_seq_gl = G.is_rendering ?
+ const int do_seq_gl = is_rendering ?
0 /* (context.scene->r.seq_flag & R_SEQ_GL_REND) */ :
(context.scene->r.seq_flag & R_SEQ_GL_PREV);
int do_seq;
@@ -2505,7 +2510,7 @@ static ImBuf *seq_render_scene_strip(SeqRenderData context, Sequence *seq, float
context.scene->r.seq_prev_type = 3 /* == OB_SOLID */;
/* opengl offscreen render */
- BKE_scene_update_for_newframe(context.bmain, scene, scene->lay);
+ BKE_scene_update_for_newframe(context.eval_ctx, context.bmain, scene, scene->lay);
ibuf = sequencer_view3d_cb(scene, camera, context.rectx, context.recty, IB_rect,
context.scene->r.seq_prev_type, context.scene->r.seq_flag & R_SEQ_SOLID_TEX,
TRUE, scene->r.alphamode, err_out);
@@ -2528,8 +2533,8 @@ static ImBuf *seq_render_scene_strip(SeqRenderData context, Sequence *seq, float
if (!is_thread_main || is_rendering == FALSE || is_background) {
if (re == NULL)
re = RE_NewRender(scene->id.name);
-
- BKE_scene_update_for_newframe(context.bmain, scene, scene->lay);
+
+ BKE_scene_update_for_newframe(context.eval_ctx, context.bmain, scene, scene->lay);
RE_BlenderFrame(re, context.bmain, scene, NULL, camera, scene->lay, frame, FALSE);
/* restore previous state after it was toggled on & off by RE_BlenderFrame */
@@ -2564,8 +2569,9 @@ static ImBuf *seq_render_scene_strip(SeqRenderData context, Sequence *seq, float
scene->r.cfra = oldcfra;
- if (frame != oldcfra)
- BKE_scene_update_for_newframe(context.bmain, scene, scene->lay);
+ if (frame != oldcfra) {
+ BKE_scene_update_for_newframe(context.eval_ctx, context.bmain, scene, scene->lay);
+ }
#ifdef DURIAN_CAMERA_SWITCH
/* stooping to new low's in hackyness :( */
diff --git a/source/blender/blenkernel/intern/shrinkwrap.c b/source/blender/blenkernel/intern/shrinkwrap.c
index 3a6912157fd..6a7c16d1162 100644
--- a/source/blender/blenkernel/intern/shrinkwrap.c
+++ b/source/blender/blenkernel/intern/shrinkwrap.c
@@ -68,11 +68,16 @@
/* get derived mesh */
/* TODO is anyfunction that does this? returning the derivedFinal without we caring if its in edit mode or not? */
-DerivedMesh *object_get_derived_final(Object *ob)
+DerivedMesh *object_get_derived_final(Object *ob, bool for_render)
{
Mesh *me = ob->data;
BMEditMesh *em = me->edit_btmesh;
+ if (for_render) {
+ /* TODO(sergey): use proper derived render here in the future. */
+ return ob->derivedFinal;
+ }
+
if (em) {
DerivedMesh *dm = em->derivedFinal;
return dm;
@@ -271,7 +276,7 @@ int BKE_shrinkwrap_project_normal(char options, const float vert[3],
}
-static void shrinkwrap_calc_normal_projection(ShrinkwrapCalcData *calc)
+static void shrinkwrap_calc_normal_projection(ShrinkwrapCalcData *calc, bool forRender)
{
int i;
@@ -319,7 +324,7 @@ static void shrinkwrap_calc_normal_projection(ShrinkwrapCalcData *calc)
}
if (calc->smd->auxTarget) {
- auxMesh = object_get_derived_final(calc->smd->auxTarget);
+ auxMesh = object_get_derived_final(calc->smd->auxTarget, forRender);
if (!auxMesh)
return;
SPACE_TRANSFORM_SETUP(&local2aux, calc->ob, calc->smd->auxTarget);
@@ -500,7 +505,7 @@ static void shrinkwrap_calc_nearest_surface_point(ShrinkwrapCalcData *calc)
/* Main shrinkwrap function */
void shrinkwrapModifier_deform(ShrinkwrapModifierData *smd, Object *ob, DerivedMesh *dm,
- float (*vertexCos)[3], int numVerts)
+ float (*vertexCos)[3], int numVerts, bool forRender)
{
DerivedMesh *ss_mesh = NULL;
@@ -528,7 +533,7 @@ void shrinkwrapModifier_deform(ShrinkwrapModifierData *smd, Object *ob, DerivedM
if (smd->target) {
- calc.target = object_get_derived_final(smd->target);
+ calc.target = object_get_derived_final(smd->target, forRender);
/* TODO there might be several "bugs" on non-uniform scales matrixs
* because it will no longer be nearest surface, not sphere projection
@@ -579,7 +584,7 @@ void shrinkwrapModifier_deform(ShrinkwrapModifierData *smd, Object *ob, DerivedM
break;
case MOD_SHRINKWRAP_PROJECT:
- TIMEIT_BENCH(shrinkwrap_calc_normal_projection(&calc), deform_project);
+ TIMEIT_BENCH(shrinkwrap_calc_normal_projection(&calc, forRender), deform_project);
break;
case MOD_SHRINKWRAP_NEAREST_VERTEX:
diff --git a/source/blender/blenkernel/intern/smoke.c b/source/blender/blenkernel/intern/smoke.c
index bd9d20333e5..a08103d2446 100644
--- a/source/blender/blenkernel/intern/smoke.c
+++ b/source/blender/blenkernel/intern/smoke.c
@@ -77,7 +77,9 @@
#include "BKE_customdata.h"
#include "BKE_deform.h"
#include "BKE_DerivedMesh.h"
+#include "BKE_global.h"
#include "BKE_effect.h"
+#include "BKE_main.h"
#include "BKE_modifier.h"
#include "BKE_object.h"
#include "BKE_particle.h"
@@ -164,7 +166,7 @@ void smoke_initWaveletBlenderRNA(struct WTURBULENCE *UNUSED(wt), float *UNUSED(s
void smoke_initBlenderRNA(struct FLUID_3D *UNUSED(fluid), float *UNUSED(alpha), float *UNUSED(beta), float *UNUSED(dt_factor), float *UNUSED(vorticity),
int *UNUSED(border_colli), float *UNUSED(burning_rate), float *UNUSED(flame_smoke), float *UNUSED(flame_smoke_color),
float *UNUSED(flame_vorticity), float *UNUSED(flame_ignition_temp), float *UNUSED(flame_max_temp)) {}
-struct DerivedMesh *smokeModifier_do(SmokeModifierData *UNUSED(smd), Scene *UNUSED(scene), Object *UNUSED(ob), DerivedMesh *UNUSED(dm)) { return NULL; }
+struct DerivedMesh *smokeModifier_do(SmokeModifierData *UNUSED(smd), Scene *UNUSED(scene), Object *UNUSED(ob), DerivedMesh *UNUSED(dm), bool UNUSED(for_render)) { return NULL; }
float smoke_get_velocity_at(struct Object *UNUSED(ob), float UNUSED(position[3]), float UNUSED(velocity[3])) { return 0.0f; }
void flame_get_spectrum(unsigned char *UNUSED(spec), int UNUSED(width), float UNUSED(t1), float UNUSED(t2)) {}
@@ -943,7 +945,7 @@ static void object_cacheIgnoreClear(Object *ob, int state)
BLI_freelistN(&pidlist);
}
-static int subframe_updateObject(Scene *scene, Object *ob, int update_mesh, int parent_recursion, float frame)
+static int subframe_updateObject(Scene *scene, Object *ob, int update_mesh, int parent_recursion, float frame, bool for_render)
{
SmokeModifierData *smd = (SmokeModifierData *)modifiers_findByType(ob, eModifierType_Smoke);
bConstraint *con;
@@ -956,8 +958,8 @@ static int subframe_updateObject(Scene *scene, Object *ob, int update_mesh, int
if (parent_recursion) {
int recursion = parent_recursion - 1;
int is_domain = 0;
- if (ob->parent) is_domain += subframe_updateObject(scene, ob->parent, 0, recursion, frame);
- if (ob->track) is_domain += subframe_updateObject(scene, ob->track, 0, recursion, frame);
+ if (ob->parent) is_domain += subframe_updateObject(scene, ob->parent, 0, recursion, frame, for_render);
+ if (ob->track) is_domain += subframe_updateObject(scene, ob->track, 0, recursion, frame, for_render);
/* skip subframe if object is parented
* to vertex of a dynamic paint canvas */
@@ -974,7 +976,7 @@ static int subframe_updateObject(Scene *scene, Object *ob, int update_mesh, int
cti->get_constraint_targets(con, &targets);
for (ct = targets.first; ct; ct = ct->next) {
if (ct->tar)
- subframe_updateObject(scene, ct->tar, 0, recursion, frame);
+ subframe_updateObject(scene, ct->tar, 0, recursion, frame, for_render);
}
/* free temp targets */
if (cti->flush_constraint_targets)
@@ -990,7 +992,7 @@ static int subframe_updateObject(Scene *scene, Object *ob, int update_mesh, int
/* ignore cache clear during subframe updates
* to not mess up cache validity */
object_cacheIgnoreClear(ob, 1);
- BKE_object_handle_update(scene, ob);
+ BKE_object_handle_update(G.main->eval_ctx, scene, ob);
object_cacheIgnoreClear(ob, 0);
}
else
@@ -2014,7 +2016,7 @@ BLI_INLINE void apply_inflow_fields(SmokeFlowSettings *sfs, float emission_value
}
}
-static void update_flowsfluids(Scene *scene, Object *ob, SmokeDomainSettings *sds, float dt)
+static void update_flowsfluids(Scene *scene, Object *ob, SmokeDomainSettings *sds, float dt, bool for_render)
{
Object **flowobjs = NULL;
EmissionMap *emaps = NULL;
@@ -2117,7 +2119,7 @@ static void update_flowsfluids(Scene *scene, Object *ob, SmokeDomainSettings *sd
}
else { /* MOD_SMOKE_FLOW_SOURCE_MESH */
/* update flow object frame */
- subframe_updateObject(scene, collob, 1, 5, BKE_scene_frame_get(scene));
+ subframe_updateObject(scene, collob, 1, 5, BKE_scene_frame_get(scene), for_render);
/* apply flow */
emit_from_derivedmesh(collob, sds, sfs, &em_temp, sdt);
@@ -2427,7 +2429,7 @@ static void update_effectors(Scene *scene, Object *ob, SmokeDomainSettings *sds,
pdEndEffectors(&effectors);
}
-static void step(Scene *scene, Object *ob, SmokeModifierData *smd, DerivedMesh *domain_dm, float fps)
+static void step(Scene *scene, Object *ob, SmokeModifierData *smd, DerivedMesh *domain_dm, float fps, bool for_render)
{
SmokeDomainSettings *sds = smd->domain;
/* stability values copied from wturbulence.cpp */
@@ -2497,7 +2499,7 @@ static void step(Scene *scene, Object *ob, SmokeModifierData *smd, DerivedMesh *
for (substep = 0; substep < totalSubsteps; substep++)
{
// calc animated obstacle velocities
- update_flowsfluids(scene, ob, sds, dtSubdiv);
+ update_flowsfluids(scene, ob, sds, dtSubdiv, for_render);
update_obstacles(scene, ob, sds, dtSubdiv, substep, totalSubsteps);
if (sds->total_cells > 1) {
@@ -2594,7 +2596,7 @@ static DerivedMesh *createDomainGeometry(SmokeDomainSettings *sds, Object *ob)
return result;
}
-static void smokeModifier_process(SmokeModifierData *smd, Scene *scene, Object *ob, DerivedMesh *dm)
+static void smokeModifier_process(SmokeModifierData *smd, Scene *scene, Object *ob, DerivedMesh *dm, bool for_render)
{
if ((smd->type & MOD_SMOKE_TYPE_FLOW))
{
@@ -2716,7 +2718,7 @@ static void smokeModifier_process(SmokeModifierData *smd, Scene *scene, Object *
}
- step(scene, ob, smd, dm, scene->r.frs_sec / scene->r.frs_sec_base);
+ step(scene, ob, smd, dm, scene->r.frs_sec / scene->r.frs_sec_base, for_render);
}
// create shadows before writing cache so they get stored
@@ -2736,13 +2738,13 @@ static void smokeModifier_process(SmokeModifierData *smd, Scene *scene, Object *
}
}
-struct DerivedMesh *smokeModifier_do(SmokeModifierData *smd, Scene *scene, Object *ob, DerivedMesh *dm)
+struct DerivedMesh *smokeModifier_do(SmokeModifierData *smd, Scene *scene, Object *ob, DerivedMesh *dm, bool for_render)
{
/* lock so preview render does not read smoke data while it gets modified */
if ((smd->type & MOD_SMOKE_TYPE_DOMAIN) && smd->domain)
BLI_rw_mutex_lock(smd->domain->fluid_mutex, THREAD_LOCK_WRITE);
- smokeModifier_process(smd, scene, ob, dm);
+ smokeModifier_process(smd, scene, ob, dm, for_render);
if ((smd->type & MOD_SMOKE_TYPE_DOMAIN) && smd->domain)
BLI_rw_mutex_unlock(smd->domain->fluid_mutex);
diff --git a/source/blender/blenloader/intern/readfile.c b/source/blender/blenloader/intern/readfile.c
index ac69394a309..035a917d37f 100644
--- a/source/blender/blenloader/intern/readfile.c
+++ b/source/blender/blenloader/intern/readfile.c
@@ -492,7 +492,7 @@ void blo_split_main(ListBase *mainlist, Main *main)
return;
for (lib = main->library.first; lib; lib = lib->id.next) {
- Main *libmain = MEM_callocN(sizeof(Main), "libmain");
+ Main *libmain = BKE_main_new();
libmain->curlib = lib;
BLI_addtail(mainlist, libmain);
}
@@ -545,7 +545,7 @@ static Main *blo_find_main(FileData *fd, const char *filepath, const char *relab
}
}
- m = MEM_callocN(sizeof(Main), "find_main");
+ m = BKE_main_new();
BLI_addtail(mainlist, m);
lib = BKE_libblock_alloc(&m->library, ID_LI, "lib");
@@ -6548,7 +6548,7 @@ static void direct_link_library(FileData *fd, Library *lib, Main *main)
lib->packedfile = direct_link_packedfile(fd, lib->packedfile);
/* new main */
- newmain= MEM_callocN(sizeof(Main), "directlink");
+ newmain = BKE_main_new();
BLI_addtail(fd->mainlist, newmain);
newmain->curlib = lib;
@@ -7572,7 +7572,7 @@ BlendFileData *blo_read_file_internal(FileData *fd, const char *filepath)
ListBase mainlist = {NULL, NULL};
bfd = MEM_callocN(sizeof(BlendFileData), "blendfiledata");
- bfd->main = MEM_callocN(sizeof(Main), "readfile_Main");
+ bfd->main = BKE_main_new();
BLI_addtail(&mainlist, bfd->main);
fd->mainlist = &mainlist;
diff --git a/source/blender/collada/AnimationExporter.cpp b/source/blender/collada/AnimationExporter.cpp
index c1b6dc83139..559b180189f 100644
--- a/source/blender/collada/AnimationExporter.cpp
+++ b/source/blender/collada/AnimationExporter.cpp
@@ -942,7 +942,7 @@ std::string AnimationExporter::create_4x4_source(std::vector<float> &frames, Obj
float ctime = BKE_scene_frame_get_from_ctime(scene, *it);
CFRA = BKE_scene_frame_get_from_ctime(scene, *it);
- //BKE_scene_update_for_newframe(G.main,scene,scene->lay);
+ //BKE_scene_update_for_newframe(G.main->eval_ctx, G.main,scene,scene->lay);
BKE_animsys_evaluate_animdata(scene, &ob->id, ob->adt, ctime, ADT_RECALC_ALL);
if (bone) {
diff --git a/source/blender/editors/mesh/editmesh_extrude.c b/source/blender/editors/mesh/editmesh_extrude.c
index ef300fa9db6..5da33663897 100644
--- a/source/blender/editors/mesh/editmesh_extrude.c
+++ b/source/blender/editors/mesh/editmesh_extrude.c
@@ -35,6 +35,8 @@
#include "BLI_math.h"
#include "BKE_context.h"
+#include "BKE_global.h"
+#include "BKE_main.h"
#include "BKE_object.h"
#include "BKE_report.h"
#include "BKE_editmesh.h"
@@ -374,7 +376,7 @@ static int edbm_extrude_mesh(Scene *scene, Object *obedit, BMEditMesh *em, wmOpe
* automatically building this data if invalid. Or something.
*/
// DAG_object_flush_update(scene, obedit, OB_RECALC_DATA);
- BKE_object_handle_update(scene, obedit);
+ BKE_object_handle_update(G.main->eval_ctx, scene, obedit);
/* individual faces? */
if (nr == 2) {
diff --git a/source/blender/editors/mesh/editmesh_utils.c b/source/blender/editors/mesh/editmesh_utils.c
index 4982ce3571c..8475512cdaa 100644
--- a/source/blender/editors/mesh/editmesh_utils.c
+++ b/source/blender/editors/mesh/editmesh_utils.c
@@ -39,8 +39,10 @@
#include "BKE_DerivedMesh.h"
#include "BKE_context.h"
+#include "BKE_global.h"
#include "BKE_depsgraph.h"
#include "BKE_key.h"
+#include "BKE_main.h"
#include "BKE_mesh.h"
#include "BKE_mesh_mapping.h"
#include "BKE_report.h"
@@ -48,6 +50,7 @@
#include "BKE_editmesh_bvh.h"
#include "BKE_object.h" /* XXX. only for EDBM_mesh_ensure_valid_dm_hack() which will be removed */
+#include "BKE_scene.h" /* XXX, only for eval_ctx used in EDBM_mesh_ensure_valid_dm_hack */
#include "WM_api.h"
#include "WM_types.h"
@@ -111,7 +114,7 @@ void EDBM_mesh_ensure_valid_dm_hack(Scene *scene, BMEditMesh *em)
(em->ob->recalc & OB_RECALC_DATA))
{
em->ob->recalc |= OB_RECALC_DATA; /* since we may not have done selection flushing */
- BKE_object_handle_update(scene, em->ob);
+ BKE_object_handle_update(G.main->eval_ctx, scene, em->ob);
}
}
diff --git a/source/blender/editors/object/object_add.c b/source/blender/editors/object/object_add.c
index c67d389e5d0..669d762029a 100644
--- a/source/blender/editors/object/object_add.c
+++ b/source/blender/editors/object/object_add.c
@@ -1234,7 +1234,7 @@ static void make_object_duplilist_real(bContext *C, Scene *scene, Base *base,
if (!(base->object->transflag & OB_DUPLI))
return;
- lb = object_duplilist(scene, base->object, FALSE);
+ lb = object_duplilist(bmain->eval_ctx, scene, base->object);
if (use_hierarchy || use_base_parent) {
dupli_gh = BLI_ghash_ptr_new("make_object_duplilist_real dupli_gh");
@@ -1670,7 +1670,7 @@ static int convert_exec(bContext *C, wmOperator *op)
}
if (!baseob->curve_cache || !baseob->curve_cache->disp.first) {
- BKE_displist_make_mball(scene, baseob);
+ BKE_displist_make_mball(bmain->eval_ctx, scene, baseob);
}
if (!(baseob->flag & OB_DONE)) {
diff --git a/source/blender/editors/object/object_modifier.c b/source/blender/editors/object/object_modifier.c
index c06164203b6..d3b376fe1be 100644
--- a/source/blender/editors/object/object_modifier.c
+++ b/source/blender/editors/object/object_modifier.c
@@ -1907,7 +1907,7 @@ static int meshdeform_bind_exec(bContext *C, wmOperator *op)
BKE_lattice_modifiers_calc(scene, ob);
}
else if (ob->type == OB_MBALL) {
- BKE_displist_make_mball(scene, ob);
+ BKE_displist_make_mball(CTX_data_main(C)->eval_ctx, scene, ob);
}
else if (ELEM3(ob->type, OB_CURVE, OB_SURF, OB_FONT)) {
BKE_displist_make_curveTypes(scene, ob, 0);
diff --git a/source/blender/editors/render/render_opengl.c b/source/blender/editors/render/render_opengl.c
index a95e36d6480..a1d09963eb7 100644
--- a/source/blender/editors/render/render_opengl.c
+++ b/source/blender/editors/render/render_opengl.c
@@ -149,7 +149,8 @@ static void screen_opengl_render_apply(OGLRender *oglrender)
SeqRenderData context;
int chanshown = oglrender->sseq ? oglrender->sseq->chanshown : 0;
- context = BKE_sequencer_new_render_data(oglrender->bmain, scene, oglrender->sizex, oglrender->sizey, 100.0f);
+ context = BKE_sequencer_new_render_data(oglrender->bmain->eval_ctx, oglrender->bmain,
+ scene, oglrender->sizex, oglrender->sizey, 100.0f);
ibuf = BKE_sequencer_give_ibuf(context, CFRA, chanshown);
@@ -458,7 +459,7 @@ static void screen_opengl_render_end(bContext *C, OGLRender *oglrender)
if (oglrender->timer) { /* exec will not have a timer */
scene->r.cfra = oglrender->cfrao;
- BKE_scene_update_for_newframe(bmain, scene, screen_opengl_layers(oglrender));
+ BKE_scene_update_for_newframe(bmain->eval_ctx, bmain, scene, screen_opengl_layers(oglrender));
WM_event_remove_timer(oglrender->wm, oglrender->win, oglrender->timer);
}
@@ -531,7 +532,7 @@ static bool screen_opengl_render_anim_step(bContext *C, wmOperator *op)
if (lay & 0xFF000000)
lay &= 0xFF000000;
- BKE_scene_update_for_newframe(bmain, scene, lay);
+ BKE_scene_update_for_newframe(bmain->eval_ctx, bmain, scene, lay);
CFRA++;
}
@@ -549,7 +550,7 @@ static bool screen_opengl_render_anim_step(bContext *C, wmOperator *op)
WM_cursor_time(oglrender->win, scene->r.cfra);
- BKE_scene_update_for_newframe(bmain, scene, screen_opengl_layers(oglrender));
+ BKE_scene_update_for_newframe(bmain->eval_ctx, bmain, scene, screen_opengl_layers(oglrender));
if (view_context) {
if (oglrender->rv3d->persp == RV3D_CAMOB && oglrender->v3d->camera && oglrender->v3d->scenelock) {
diff --git a/source/blender/editors/screen/screen_edit.c b/source/blender/editors/screen/screen_edit.c
index e00f98c59e8..abf049ffc83 100644
--- a/source/blender/editors/screen/screen_edit.c
+++ b/source/blender/editors/screen/screen_edit.c
@@ -1505,6 +1505,7 @@ void ED_screen_set(bContext *C, bScreen *sc)
if (oldscreen != sc) {
wmTimer *wt = oldscreen->animtimer;
ScrArea *sa;
+ Scene *oldscene = oldscreen->scene;
/* remove handlers referencing areas in old screen */
for (sa = oldscreen->areabase.first; sa; sa = sa->next) {
@@ -1531,6 +1532,21 @@ void ED_screen_set(bContext *C, bScreen *sc)
/* makes button hilites work */
WM_event_add_mousemove(C);
+
+ /* Needed to make sure all the derivedMeshes are
+ * up-to-date before viewport starts acquiring this.
+ *
+ * This is needed in cases when, for example, boolean
+ * modifier uses operant from invisible layer.
+ * Without this trick boolean wouldn't apply correct.
+ *
+ * Quite the same happens when setting screen's scene,
+ * so perhaps this is in fact correct thing to do.
+ */
+ if (oldscene != sc->scene) {
+ BKE_scene_set_background(bmain, sc->scene);
+ DAG_on_visible_update(bmain, FALSE);
+ }
}
}
@@ -2016,7 +2032,7 @@ void ED_update_for_newframe(Main *bmain, Scene *scene, int UNUSED(mute))
layers |= BKE_screen_visible_layers(window->screen, scene);
/* this function applies the changes too */
- BKE_scene_update_for_newframe(bmain, scene, layers); /* BKE_scene.h */
+ BKE_scene_update_for_newframe(bmain->eval_ctx, bmain, scene, layers);
//if ( (CFRA>1) && (!mute) && (scene->r.audio.flag & AUDIO_SCRUB))
// audiostream_scrub( CFRA );
diff --git a/source/blender/editors/sound/sound_ops.c b/source/blender/editors/sound/sound_ops.c
index 81b0992c878..50a90d4428c 100644
--- a/source/blender/editors/sound/sound_ops.c
+++ b/source/blender/editors/sound/sound_ops.c
@@ -287,11 +287,11 @@ static int sound_bake_animation_exec(bContext *C, wmOperator *UNUSED(op))
for (cfra = (scene->r.sfra > 0) ? (scene->r.sfra - 1) : 0; cfra <= scene->r.efra + 1; cfra++) {
scene->r.cfra = cfra;
- BKE_scene_update_for_newframe(bmain, scene, scene->lay);
+ BKE_scene_update_for_newframe(bmain->eval_ctx, bmain, scene, scene->lay);
}
scene->r.cfra = oldfra;
- BKE_scene_update_for_newframe(bmain, scene, scene->lay);
+ BKE_scene_update_for_newframe(bmain->eval_ctx, bmain, scene, scene->lay);
return OPERATOR_FINISHED;
}
diff --git a/source/blender/editors/space_image/image_ops.c b/source/blender/editors/space_image/image_ops.c
index 7120a699f02..ea06e26fb5a 100644
--- a/source/blender/editors/space_image/image_ops.c
+++ b/source/blender/editors/space_image/image_ops.c
@@ -900,7 +900,7 @@ void IMAGE_OT_view_zoom_ratio(wmOperatorType *ot)
/* api callbacks */
ot->exec = image_view_zoom_ratio_exec;
ot->poll = space_image_main_area_poll;
-
+
/* properties */
RNA_def_float(ot->srna, "ratio", 0.0f, -FLT_MAX, FLT_MAX,
"Ratio", "Zoom ratio, 1.0 is 1:1, higher is zoomed in, lower is zoomed out", -FLT_MAX, FLT_MAX);
diff --git a/source/blender/editors/space_sequencer/sequencer_draw.c b/source/blender/editors/space_sequencer/sequencer_draw.c
index 267b070fd42..c6aec21f946 100644
--- a/source/blender/editors/space_sequencer/sequencer_draw.c
+++ b/source/blender/editors/space_sequencer/sequencer_draw.c
@@ -48,8 +48,8 @@
#include "BKE_context.h"
#include "BKE_global.h"
+#include "BKE_main.h"
#include "BKE_sequencer.h"
-
#include "BKE_sound.h"
#include "IMB_colormanagement.h"
@@ -838,7 +838,7 @@ ImBuf *sequencer_ibuf_get(struct Main *bmain, Scene *scene, SpaceSeq *sseq, int
rectx = (render_size * (float)scene->r.xsch) / 100.0f + 0.5f;
recty = (render_size * (float)scene->r.ysch) / 100.0f + 0.5f;
- context = BKE_sequencer_new_render_data(bmain, scene, rectx, recty, proxy_size);
+ context = BKE_sequencer_new_render_data(bmain->eval_ctx, bmain, scene, rectx, recty, proxy_size);
/* sequencer could start rendering, in this case we need to be sure it wouldn't be canceled
* by Esc pressed somewhere in the past
diff --git a/source/blender/editors/space_view3d/drawobject.c b/source/blender/editors/space_view3d/drawobject.c
index f825f7ecf9f..9eb3fb320be 100644
--- a/source/blender/editors/space_view3d/drawobject.c
+++ b/source/blender/editors/space_view3d/drawobject.c
@@ -59,6 +59,7 @@
#include "BKE_image.h"
#include "BKE_key.h"
#include "BKE_lattice.h"
+#include "BKE_main.h"
#include "BKE_mesh.h"
#include "BKE_material.h"
#include "BKE_mball.h"
@@ -4056,7 +4057,7 @@ static bool drawDispList_nobackface(Scene *scene, View3D *v3d, RegionView3D *rv3
if (BKE_mball_is_basis(ob)) {
lb = ob->curve_cache ? &ob->curve_cache->disp : NULL;
if (ELEM(NULL, lb, lb->first)) {
- BKE_displist_make_mball(scene, ob);
+ BKE_displist_make_mball(G.main->eval_ctx, scene, ob);
lb = &ob->curve_cache->disp;
}
if (lb->first == NULL) {
@@ -6268,7 +6269,7 @@ static void draw_bounding_volume(Scene *scene, Object *ob, char type)
if (BKE_mball_is_basis(ob)) {
bb = ob->bb;
if (bb == NULL) {
- BKE_displist_make_mball(scene, ob);
+ BKE_displist_make_mball(G.main->eval_ctx, scene, ob);
bb = ob->bb;
}
}
diff --git a/source/blender/editors/space_view3d/view3d_draw.c b/source/blender/editors/space_view3d/view3d_draw.c
index 701fb26a562..f0a943d593e 100644
--- a/source/blender/editors/space_view3d/view3d_draw.c
+++ b/source/blender/editors/space_view3d/view3d_draw.c
@@ -55,6 +55,7 @@
#include "BKE_customdata.h"
#include "BKE_image.h"
#include "BKE_key.h"
+#include "BKE_main.h"
#include "BKE_object.h"
#include "BKE_global.h"
#include "BKE_paint.h"
@@ -1968,7 +1969,7 @@ static void draw_dupli_objects_color(Scene *scene, ARegion *ar, View3D *v3d, Bas
if (base->object->restrictflag & OB_RESTRICT_VIEW) return;
tbase.flag = OB_FROMDUPLI | base->flag;
- lb = object_duplilist(scene, base->object, false);
+ lb = object_duplilist(G.main->eval_ctx, scene, base->object);
// BLI_sortlist(lb, dupli_ob_sort); /* might be nice to have if we have a dupli list with mixed objects. */
dob = dupli_step(lb->first);
@@ -2402,7 +2403,7 @@ static void gpu_update_lamps_shadows(Scene *scene, View3D *v3d)
if (ob->transflag & OB_DUPLI) {
DupliObject *dob;
- ListBase *lb = object_duplilist(scene, ob, false);
+ ListBase *lb = object_duplilist(G.main->eval_ctx, scene, ob);
for (dob = lb->first; dob; dob = dob->next)
if (dob->ob->type == OB_LAMP)
diff --git a/source/blender/editors/space_view3d/view3d_view.c b/source/blender/editors/space_view3d/view3d_view.c
index d81ab0319e6..dcbcb127f5c 100644
--- a/source/blender/editors/space_view3d/view3d_view.c
+++ b/source/blender/editors/space_view3d/view3d_view.c
@@ -984,7 +984,7 @@ short view3d_opengl_select(ViewContext *vc, unsigned int *buffer, unsigned int b
Base tbase;
tbase.flag = OB_FROMDUPLI;
- lb = object_duplilist(scene, base->object, false);
+ lb = object_duplilist(G.main->eval_ctx, scene, base->object);
for (dob = lb->first; dob; dob = dob->next) {
tbase.object = dob->ob;
@@ -1543,7 +1543,7 @@ static int game_engine_exec(bContext *C, wmOperator *op)
//XXX restore_all_scene_cfra(scene_cfra_store);
BKE_scene_set_background(CTX_data_main(C), startscene);
- //XXX BKE_scene_update_for_newframe(bmain, scene, scene->lay);
+ //XXX BKE_scene_update_for_newframe(bmain->eval_ctx, bmain, scene, scene->lay);
BLI_callback_exec(bmain, &startscene->id, BLI_CB_EVT_GAME_POST);
diff --git a/source/blender/editors/transform/transform_conversions.c b/source/blender/editors/transform/transform_conversions.c
index c06ccccf88d..4bd4db9849b 100644
--- a/source/blender/editors/transform/transform_conversions.c
+++ b/source/blender/editors/transform/transform_conversions.c
@@ -4906,8 +4906,10 @@ static void set_trans_object_base_flags(TransInfo *t)
/* handle pending update events, otherwise they got copied below */
for (base = scene->base.first; base; base = base->next) {
- if (base->object->recalc)
- BKE_object_handle_update(t->scene, base->object);
+ if (base->object->recalc) {
+ /* TODO(sergey): Ideally, it's not needed. */
+ BKE_object_handle_update(G.main->eval_ctx, t->scene, base->object);
+ }
}
for (base = scene->base.first; base; base = base->next) {
diff --git a/source/blender/editors/transform/transform_snap.c b/source/blender/editors/transform/transform_snap.c
index b614ee207c6..5b90cc93083 100644
--- a/source/blender/editors/transform/transform_snap.c
+++ b/source/blender/editors/transform/transform_snap.c
@@ -55,10 +55,12 @@
#include "BIF_gl.h"
#include "BKE_DerivedMesh.h"
+#include "BKE_global.h"
#include "BKE_object.h"
#include "BKE_anim.h" /* for duplis */
#include "BKE_context.h"
#include "BKE_editmesh.h"
+#include "BKE_main.h"
#include "BKE_mesh.h"
#include "BKE_tracking.h"
@@ -321,8 +323,9 @@ void applyProject(TransInfo *t)
mul_m4_v3(ob->obmat, iloc);
}
else if (t->flag & T_OBJECT) {
+ /* TODO(sergey): Ideally force update is not needed here. */
td->ob->recalc |= OB_RECALC_OB | OB_RECALC_DATA | OB_RECALC_TIME;
- BKE_object_handle_update(t->scene, td->ob);
+ BKE_object_handle_update(G.main->eval_ctx, t->scene, td->ob);
copy_v3_v3(iloc, td->ob->obmat[3]);
}
@@ -393,7 +396,7 @@ void applyGridAbsolute(TransInfo *t)
}
else if (t->flag & T_OBJECT) {
td->ob->recalc |= OB_RECALC_OB | OB_RECALC_DATA | OB_RECALC_TIME;
- BKE_object_handle_update(t->scene, td->ob);
+ BKE_object_handle_update(G.main->eval_ctx, t->scene, td->ob);
copy_v3_v3(iloc, td->ob->obmat[3]);
}
@@ -1872,7 +1875,7 @@ static bool snapObjectsRay(Scene *scene, short snap_mode, Base *base_act, View3D
if (ob->transflag & OB_DUPLI) {
DupliObject *dupli_ob;
- ListBase *lb = object_duplilist(scene, ob, FALSE);
+ ListBase *lb = object_duplilist(G.main->eval_ctx, scene, ob);
for (dupli_ob = lb->first; dupli_ob; dupli_ob = dupli_ob->next) {
retval |= snapObject(scene, snap_mode, ar, dupli_ob->ob, dupli_ob->mat, false,
@@ -2124,7 +2127,7 @@ static bool peelObjects(Scene *scene, View3D *v3d, ARegion *ar, Object *obedit,
if (ob->transflag & OB_DUPLI) {
DupliObject *dupli_ob;
- ListBase *lb = object_duplilist(scene, ob, FALSE);
+ ListBase *lb = object_duplilist(G.main->eval_ctx, scene, ob);
for (dupli_ob = lb->first; dupli_ob; dupli_ob = dupli_ob->next) {
Object *dob = dupli_ob->ob;
diff --git a/source/blender/gpu/intern/gpu_material.c b/source/blender/gpu/intern/gpu_material.c
index a3813ef4584..24c3291e283 100644
--- a/source/blender/gpu/intern/gpu_material.c
+++ b/source/blender/gpu/intern/gpu_material.c
@@ -851,7 +851,7 @@ static void material_lights(GPUShadeInput *shi, GPUShadeResult *shr)
if (ob->transflag & OB_DUPLI) {
DupliObject *dob;
- ListBase *lb = object_duplilist(shi->gpumat->scene, ob, FALSE);
+ ListBase *lb = object_duplilist(G.main->eval_ctx, shi->gpumat->scene, ob);
for (dob=lb->first; dob; dob=dob->next) {
Object *ob_iter = dob->ob;
diff --git a/source/blender/makesrna/SConscript b/source/blender/makesrna/SConscript
index 5053c8082e9..d74cf20c582 100644
--- a/source/blender/makesrna/SConscript
+++ b/source/blender/makesrna/SConscript
@@ -106,6 +106,7 @@ if env['BF_UNIT_TEST']:
if env['WITH_BF_PYTHON']:
defs.append('WITH_PYTHON')
+ incs += ' ../python'
if env['WITH_BF_COLLADA']:
defs.append('WITH_COLLADA')
diff --git a/source/blender/makesrna/intern/CMakeLists.txt b/source/blender/makesrna/intern/CMakeLists.txt
index a4deee5a2c3..26904cac17f 100644
--- a/source/blender/makesrna/intern/CMakeLists.txt
+++ b/source/blender/makesrna/intern/CMakeLists.txt
@@ -158,6 +158,9 @@ endif()
if(WITH_PYTHON)
add_definitions(-DWITH_PYTHON)
+ list(APPEND INC
+ ../../python
+ )
endif()
if(WITH_GAMEENGINE)
diff --git a/source/blender/makesrna/intern/rna_main_api.c b/source/blender/makesrna/intern/rna_main_api.c
index 861eca9bd9b..65453556523 100644
--- a/source/blender/makesrna/intern/rna_main_api.c
+++ b/source/blender/makesrna/intern/rna_main_api.c
@@ -358,7 +358,13 @@ Mesh *rna_Main_meshes_new_from_object(
if (render) {
ListBase disp = {NULL, NULL};
- BKE_displist_make_mball_forRender(sce, ob, &disp);
+ /* TODO(sergey): This is gonna to work for until EvaluationContext
+ * only contains for_render flag. As soon as CoW is
+ * implemented, this is to be rethinked.
+ */
+ EvaluationContext eval_ctx = {0};
+ eval_ctx.for_render = render;
+ BKE_displist_make_mball_forRender(&eval_ctx, sce, ob, &disp);
BKE_mesh_from_metaball(&disp, tmpmesh);
BKE_displist_free(&disp);
}
diff --git a/source/blender/makesrna/intern/rna_object_api.c b/source/blender/makesrna/intern/rna_object_api.c
index f29eb7800b5..85e0d91fc71 100644
--- a/source/blender/makesrna/intern/rna_object_api.c
+++ b/source/blender/makesrna/intern/rna_object_api.c
@@ -168,6 +168,8 @@ static void dupli_render_particle_set(Scene *scene, Object *ob, int level, int e
static void rna_Object_create_duplilist(Object *ob, ReportList *reports, Scene *sce, int settings)
{
int for_render = settings == eModifierMode_Render;
+ EvaluationContext eval_ctx = {0};
+ eval_ctx.for_render = for_render;
if (!(ob->transflag & OB_DUPLI)) {
BKE_report(reports, RPT_ERROR, "Object does not have duplis");
@@ -181,10 +183,10 @@ static void rna_Object_create_duplilist(Object *ob, ReportList *reports, Scene *
free_object_duplilist(ob->duplilist);
ob->duplilist = NULL;
}
- if (G.is_rendering)
+ if (for_render)
dupli_render_particle_set(sce, ob, 0, 1);
- ob->duplilist = object_duplilist(sce, ob, for_render);
- if (G.is_rendering)
+ ob->duplilist = object_duplilist(&eval_ctx, sce, ob);
+ if (for_render)
dupli_render_particle_set(sce, ob, 0, 0);
/* ob->duplilist should now be freed with Object.free_duplilist */
}
diff --git a/source/blender/makesrna/intern/rna_scene.c b/source/blender/makesrna/intern/rna_scene.c
index adc0f7ad892..82447c2e5b4 100644
--- a/source/blender/makesrna/intern/rna_scene.c
+++ b/source/blender/makesrna/intern/rna_scene.c
@@ -4514,7 +4514,7 @@ static void rna_def_scene_render_data(BlenderRNA *brna)
RNA_def_property_enum_items(prop, display_mode_items);
RNA_def_property_ui_text(prop, "Display", "Select where rendered images will be displayed");
RNA_def_property_update(prop, NC_SCENE | ND_RENDER_OPTIONS, NULL);
-
+
prop = RNA_def_property(srna, "filepath", PROP_STRING, PROP_FILEPATH);
RNA_def_property_string_sdna(prop, NULL, "pic");
RNA_def_property_ui_text(prop, "Output Path",
diff --git a/source/blender/makesrna/intern/rna_scene_api.c b/source/blender/makesrna/intern/rna_scene_api.c
index ae6c5e71e6e..a0a0ec96711 100644
--- a/source/blender/makesrna/intern/rna_scene_api.c
+++ b/source/blender/makesrna/intern/rna_scene_api.c
@@ -54,6 +54,10 @@
#include "ED_transform.h"
+#ifdef WITH_PYTHON
+# include "BPY_extern.h"
+#endif
+
static void rna_Scene_frame_set(Scene *scene, int frame, float subframe)
{
double cfra = (double)frame + (double)subframe;
@@ -61,7 +65,16 @@ static void rna_Scene_frame_set(Scene *scene, int frame, float subframe)
CLAMP(cfra, MINAFRAME, MAXFRAME);
BKE_scene_frame_set(scene, cfra);
- BKE_scene_update_for_newframe(G.main, scene, (1 << 20) - 1);
+#ifdef WITH_PYTHON
+ BPy_BEGIN_ALLOW_THREADS;
+#endif
+
+ BKE_scene_update_for_newframe(G.main->eval_ctx, G.main, scene, (1 << 20) - 1);
+
+#ifdef WITH_PYTHON
+ BPy_END_ALLOW_THREADS;
+#endif
+
BKE_scene_camera_switch_update(scene);
/* don't do notifier when we're rendering, avoid some viewport crashes
@@ -78,7 +91,15 @@ static void rna_Scene_frame_set(Scene *scene, int frame, float subframe)
static void rna_Scene_update_tagged(Scene *scene)
{
- BKE_scene_update_tagged(G.main, scene);
+#ifdef WITH_PYTHON
+ BPy_BEGIN_ALLOW_THREADS;
+#endif
+
+ BKE_scene_update_tagged(G.main->eval_ctx, G.main, scene);
+
+#ifdef WITH_PYTHON
+ BPy_END_ALLOW_THREADS;
+#endif
}
static void rna_SceneRender_get_frame_path(RenderData *rd, int frame, char *name)
diff --git a/source/blender/modifiers/intern/MOD_array.c b/source/blender/modifiers/intern/MOD_array.c
index 971b3f0cd14..80caa384086 100644
--- a/source/blender/modifiers/intern/MOD_array.c
+++ b/source/blender/modifiers/intern/MOD_array.c
@@ -55,6 +55,8 @@
#include "BKE_modifier.h"
#include "BKE_object.h"
+#include "MOD_util.h"
+
#include "bmesh.h"
#include "depsgraph_private.h"
@@ -320,7 +322,7 @@ static void merge_first_last(BMesh *bm,
static DerivedMesh *arrayModifier_doArray(ArrayModifierData *amd,
Scene *scene, Object *ob, DerivedMesh *dm,
- int UNUSED(initFlags))
+ ModifierApplyFlag flag)
{
DerivedMesh *result;
BMesh *bm = DM_to_bmesh(dm, false);
@@ -340,9 +342,9 @@ static DerivedMesh *arrayModifier_doArray(ArrayModifierData *amd,
/* need to avoid infinite recursion here */
if (amd->start_cap && amd->start_cap != ob && amd->start_cap->type == OB_MESH)
- start_cap = mesh_get_derived_final(scene, amd->start_cap, CD_MASK_MESH);
+ start_cap = get_dm_for_modifier(amd->start_cap, flag);
if (amd->end_cap && amd->end_cap != ob && amd->end_cap->type == OB_MESH)
- end_cap = mesh_get_derived_final(scene, amd->end_cap, CD_MASK_MESH);
+ end_cap = get_dm_for_modifier(amd->end_cap, flag);
unit_m4(offset);
@@ -571,12 +573,12 @@ static DerivedMesh *arrayModifier_doArray(ArrayModifierData *amd,
static DerivedMesh *applyModifier(ModifierData *md, Object *ob,
DerivedMesh *dm,
- ModifierApplyFlag UNUSED(flag))
+ ModifierApplyFlag flag)
{
DerivedMesh *result;
ArrayModifierData *amd = (ArrayModifierData *) md;
- result = arrayModifier_doArray(amd, md->scene, ob, dm, 0);
+ result = arrayModifier_doArray(amd, md->scene, ob, dm, flag);
return result;
}
diff --git a/source/blender/modifiers/intern/MOD_boolean.c b/source/blender/modifiers/intern/MOD_boolean.c
index bee7a32f6aa..71a8074c698 100644
--- a/source/blender/modifiers/intern/MOD_boolean.c
+++ b/source/blender/modifiers/intern/MOD_boolean.c
@@ -1,3 +1,4 @@
+
/*
* ***** BEGIN GPL LICENSE BLOCK *****
*
@@ -119,7 +120,7 @@ static DerivedMesh *get_quick_derivedMesh(DerivedMesh *derivedData, DerivedMesh
static DerivedMesh *applyModifier(ModifierData *md, Object *ob,
DerivedMesh *derivedData,
- ModifierApplyFlag UNUSED(flag))
+ ModifierApplyFlag flag)
{
BooleanModifierData *bmd = (BooleanModifierData *) md;
DerivedMesh *dm;
@@ -127,25 +128,7 @@ static DerivedMesh *applyModifier(ModifierData *md, Object *ob,
if (!bmd->object)
return derivedData;
-
- /* 2.63 used this... */
- /* dm = bmd->object->derivedFinal; */
-
- /* but we want to make sure we can get the object
- * in some cases the depsgraph fails us - especially for objects
- * in other scenes when compositing */
- if (bmd->object != ob) {
- /* weak! - but we can too easy end up with circular dep crash otherwise */
- if (bmd->object->type == OB_MESH && modifiers_findByType(bmd->object, eModifierType_Boolean) == NULL) {
- dm = mesh_get_derived_final(md->scene, bmd->object, CD_MASK_MESH);
- }
- else {
- dm = bmd->object->derivedFinal;
- }
- }
- else {
- dm = NULL;
- }
+ dm = get_dm_for_modifier(bmd->object, flag);
if (dm) {
DerivedMesh *result;
diff --git a/source/blender/modifiers/intern/MOD_shrinkwrap.c b/source/blender/modifiers/intern/MOD_shrinkwrap.c
index 6e96a160cd4..eebb687aa8d 100644
--- a/source/blender/modifiers/intern/MOD_shrinkwrap.c
+++ b/source/blender/modifiers/intern/MOD_shrinkwrap.c
@@ -108,17 +108,18 @@ static void deformVerts(ModifierData *md, Object *ob,
DerivedMesh *derivedData,
float (*vertexCos)[3],
int numVerts,
- ModifierApplyFlag UNUSED(flag))
+ ModifierApplyFlag flag)
{
DerivedMesh *dm = derivedData;
CustomDataMask dataMask = requiredDataMask(ob, md);
+ bool forRender = (flag & MOD_APPLY_RENDER) != 0;
/* ensure we get a CDDM with applied vertex coords */
if (dataMask) {
dm = get_cddm(ob, NULL, dm, vertexCos, dependsOnNormals(md));
}
- shrinkwrapModifier_deform((ShrinkwrapModifierData *)md, ob, dm, vertexCos, numVerts);
+ shrinkwrapModifier_deform((ShrinkwrapModifierData *)md, ob, dm, vertexCos, numVerts, forRender);
if (dm != derivedData)
dm->release(dm);
@@ -135,7 +136,7 @@ static void deformVertsEM(ModifierData *md, Object *ob, struct BMEditMesh *editD
dm = get_cddm(ob, editData, dm, vertexCos, dependsOnNormals(md));
}
- shrinkwrapModifier_deform((ShrinkwrapModifierData *)md, ob, dm, vertexCos, numVerts);
+ shrinkwrapModifier_deform((ShrinkwrapModifierData *)md, ob, dm, vertexCos, numVerts, false);
if (dm != derivedData)
dm->release(dm);
diff --git a/source/blender/modifiers/intern/MOD_smoke.c b/source/blender/modifiers/intern/MOD_smoke.c
index 22a4c8753d8..fcd4cc96410 100644
--- a/source/blender/modifiers/intern/MOD_smoke.c
+++ b/source/blender/modifiers/intern/MOD_smoke.c
@@ -104,11 +104,12 @@ static DerivedMesh *applyModifier(ModifierData *md, Object *ob,
ModifierApplyFlag flag)
{
SmokeModifierData *smd = (SmokeModifierData *) md;
+ bool for_render = (flag & MOD_APPLY_RENDER) != 0;
if (flag & MOD_APPLY_ORCO)
return dm;
- return smokeModifier_do(smd, md->scene, ob, dm);
+ return smokeModifier_do(smd, md->scene, ob, dm, for_render);
}
static bool dependsOnTime(ModifierData *UNUSED(md))
diff --git a/source/blender/modifiers/intern/MOD_util.c b/source/blender/modifiers/intern/MOD_util.c
index 62a02928920..bde30fb23ae 100644
--- a/source/blender/modifiers/intern/MOD_util.c
+++ b/source/blender/modifiers/intern/MOD_util.c
@@ -207,6 +207,20 @@ DerivedMesh *get_dm(Object *ob, struct BMEditMesh *em, DerivedMesh *dm,
return dm;
}
+/* Get derived mesh for other object, which is used as an operand for the modifier,
+ * i.e. second operand for boolean modifier.
+ */
+DerivedMesh *get_dm_for_modifier(Object *ob, ModifierApplyFlag flag)
+{
+ if (flag & MOD_APPLY_RENDER) {
+ /* TODO(sergey): Use proper derived render in the future. */
+ return ob->derivedFinal;
+ }
+ else {
+ return ob->derivedFinal;
+ }
+}
+
void modifier_get_vgroup(Object *ob, DerivedMesh *dm, const char *name, MDeformVert **dvert, int *defgrp_index)
{
*defgrp_index = defgroup_name_index(ob, name);
diff --git a/source/blender/modifiers/intern/MOD_util.h b/source/blender/modifiers/intern/MOD_util.h
index b4dcdc1721a..72077b5c000 100644
--- a/source/blender/modifiers/intern/MOD_util.h
+++ b/source/blender/modifiers/intern/MOD_util.h
@@ -48,6 +48,7 @@ struct DerivedMesh *get_cddm(struct Object *ob, struct BMEditMesh *em, struct De
float (*vertexCos)[3], bool use_normals);
struct DerivedMesh *get_dm(struct Object *ob, struct BMEditMesh *em, struct DerivedMesh *dm,
float (*vertexCos)[3], bool use_normals, bool use_orco);
+struct DerivedMesh *get_dm_for_modifier(struct Object *ob, ModifierApplyFlag flag);
void modifier_get_vgroup(struct Object *ob, struct DerivedMesh *dm,
const char *name, struct MDeformVert **dvert, int *defgrp_index);
diff --git a/source/blender/render/intern/include/render_types.h b/source/blender/render/intern/include/render_types.h
index 2a43cab7bce..02a9f1eb347 100644
--- a/source/blender/render/intern/include/render_types.h
+++ b/source/blender/render/intern/include/render_types.h
@@ -52,6 +52,7 @@
#include "BLI_sys_types.h" // for intptr_t support
+struct EvaluationContext;
struct Object;
struct MemArena;
struct VertTableNode;
@@ -270,6 +271,7 @@ struct Render
struct ReportList *reports;
struct ImagePool *pool;
+ struct EvaluationContext *eval_ctx;
};
/* ------------------------------------------------------------------------- */
diff --git a/source/blender/render/intern/source/convertblender.c b/source/blender/render/intern/source/convertblender.c
index 1f3e961c151..e3a8c57de66 100644
--- a/source/blender/render/intern/source/convertblender.c
+++ b/source/blender/render/intern/source/convertblender.c
@@ -39,8 +39,8 @@
#include "BLI_blenlib.h"
#include "BLI_utildefines.h"
#include "BLI_rand.h"
+#include "BLI_task.h"
#include "BLI_memarena.h"
-#include "BLI_ghash.h"
#include "BLI_linklist.h"
#ifdef WITH_FREESTYLE
# include "BLI_edgehash.h"
@@ -79,6 +79,7 @@
#include "BKE_constraint.h"
#include "BKE_displist.h"
#include "BKE_deform.h"
+#include "BKE_depsgraph.h"
#include "BKE_DerivedMesh.h"
#include "BKE_effect.h"
#include "BKE_global.h"
@@ -2221,7 +2222,7 @@ static void init_render_mball(Render *re, ObjectRen *obr)
need_orco= 1;
}
- BKE_displist_make_mball_forRender(re->scene, ob, &dispbase);
+ BKE_displist_make_mball_forRender(re->eval_ctx, re->scene, ob, &dispbase);
dl= dispbase.first;
if (dl == NULL) return;
@@ -4981,7 +4982,7 @@ static void database_init_objects(Render *re, unsigned int renderlay, int nolamp
/* create list of duplis generated by this object, particle
* system need to have render settings set for dupli particles */
dupli_render_particle_set(re, ob, timeoffset, 0, 1);
- lb= object_duplilist(re->scene, ob, TRUE);
+ lb= object_duplilist(re->eval_ctx, re->scene, ob);
dupli_render_particle_set(re, ob, timeoffset, 0, 0);
for (dob= lb->first; dob; dob= dob->next) {
@@ -5133,12 +5134,12 @@ void RE_Database_FromScene(Render *re, Main *bmain, Scene *scene, unsigned int l
/* applies changes fully */
if ((re->r.scemode & (R_NO_FRAME_UPDATE|R_BUTS_PREVIEW|R_VIEWPORT_PREVIEW))==0)
- BKE_scene_update_for_newframe(re->main, re->scene, lay);
+ BKE_scene_update_for_newframe(re->eval_ctx, re->main, re->scene, lay);
/* if no camera, viewmat should have been set! */
if (use_camera_view && camera) {
/* called before but need to call again in case of lens animation from the
- * above call to BKE_scene_update_for_newframe, fixes bug. [#22702].
+ * above call to BKE_scene_update_for_newframe_render, fixes bug. [#22702].
* following calls don't depend on 'RE_SetCamera' */
RE_SetCamera(re, camera);
@@ -5310,7 +5311,7 @@ static void database_fromscene_vectors(Render *re, Scene *scene, unsigned int la
/* applies changes fully */
scene->r.cfra += timeoffset;
- BKE_scene_update_for_newframe(re->main, re->scene, lay);
+ BKE_scene_update_for_newframe(re->eval_ctx, re->main, re->scene, lay);
/* if no camera, viewmat should have been set! */
if (camera) {
diff --git a/source/blender/render/intern/source/external_engine.c b/source/blender/render/intern/source/external_engine.c
index c3628e99d04..cccfeed6e47 100644
--- a/source/blender/render/intern/source/external_engine.c
+++ b/source/blender/render/intern/source/external_engine.c
@@ -459,7 +459,7 @@ int RE_engine_render(Render *re, int do_all)
lay &= non_excluded_lay;
}
- BKE_scene_update_for_newframe(re->main, re->scene, lay);
+ BKE_scene_update_for_newframe(re->eval_ctx, re->main, re->scene, lay);
}
/* create render result */
diff --git a/source/blender/render/intern/source/pipeline.c b/source/blender/render/intern/source/pipeline.c
index ba8265a83fe..4ec7ce1c0d2 100644
--- a/source/blender/render/intern/source/pipeline.c
+++ b/source/blender/render/intern/source/pipeline.c
@@ -59,9 +59,11 @@
#include "BKE_animsys.h" /* <------ should this be here?, needed for sequencer update */
#include "BKE_camera.h"
+#include "BKE_depsgraph.h"
#include "BKE_global.h"
#include "BKE_image.h"
#include "BKE_main.h"
+#include "BKE_modifier.h"
#include "BKE_node.h"
#include "BKE_pointcache.h"
#include "BKE_report.h"
@@ -373,6 +375,8 @@ Render *RE_NewRender(const char *name)
BLI_addtail(&RenderGlobal.renderlist, re);
BLI_strncpy(re->name, name, RE_MAXNAME);
BLI_rw_mutex_init(&re->resultmutex);
+ re->eval_ctx = MEM_callocN(sizeof(EvaluationContext), "re->eval_ctx");
+ re->eval_ctx->for_render = true;
}
RE_InitRenderCB(re);
@@ -420,6 +424,7 @@ void RE_FreeRender(Render *re)
render_result_free(re->pushedresult);
BLI_remlink(&RenderGlobal.renderlist, re);
+ MEM_freeN(re->eval_ctx);
MEM_freeN(re);
}
@@ -1320,8 +1325,9 @@ static void do_render_blur_3d(Render *re)
re->i.curblur = 0; /* stats */
/* make sure motion blur changes get reset to current frame */
- if ((re->r.scemode & (R_NO_FRAME_UPDATE|R_BUTS_PREVIEW|R_VIEWPORT_PREVIEW))==0)
- BKE_scene_update_for_newframe(re->main, re->scene, re->lay);
+ if ((re->r.scemode & (R_NO_FRAME_UPDATE|R_BUTS_PREVIEW|R_VIEWPORT_PREVIEW))==0) {
+ BKE_scene_update_for_newframe(re->eval_ctx, re->main, re->scene, re->lay);
+ }
/* weak... the display callback wants an active renderlayer pointer... */
re->result->renlay = render_get_active_layer(re, re->result);
@@ -1590,21 +1596,117 @@ static bool rlayer_node_uses_alpha(bNodeTree *ntree, bNode *node)
return false;
}
+/* Issue here is that it's possible that object which is used by boolean,
+ * array or shrinkwrap modifiers weren't displayed in the viewport before
+ * rendering. This leads to situations when apply() of this modifiers
+ * could not get ob->derivedFinal and modifiers are not being applied.
+ *
+ * This was worked around by direct call of get_derived_final() from those
+ * modifiers, but such approach leads to write conflicts with threaded
+ * update.
+ *
+ * Here we make sure derivedFinal will be calculated by update_for_newframe
+ * function later in the pipeline and all the modifiers are applied
+ * properly without hacks from their side.
+ * - sergey -
+ */
+#define DEPSGRAPH_WORKAROUND_HACK
+
+#ifdef DEPSGRAPH_WORKAROUND_HACK
+static bool allow_render_mesh_object(Object *ob)
+{
+ /* override not showing object when duplis are used with particles */
+ if (ob->transflag & OB_DUPLIPARTS) {
+ /* pass */ /* let particle system(s) handle showing vs. not showing */
+ }
+ else if ((ob->transflag & OB_DUPLI) && !(ob->transflag & OB_DUPLIFRAMES)) {
+ return false;
+ }
+ return true;
+}
+
+static void tag_dependend_objects_for_render(Scene *scene, int renderlay)
+{
+ Scene *sce_iter;
+ Base *base;
+ for (SETLOOPER(scene, sce_iter, base)) {
+ Object *object = base->object;
+
+ if ((base->lay & renderlay) == 0) {
+ continue;
+ }
+
+ if (object->type == OB_MESH) {
+ if (allow_render_mesh_object(object)) {
+ ModifierData *md;
+ VirtualModifierData virtualModifierData;
+
+ for (md = modifiers_getVirtualModifierList(object, &virtualModifierData);
+ md;
+ md = md->next)
+ {
+ if (!modifier_isEnabled(scene, md, eModifierMode_Render)) {
+ continue;
+ }
+
+ if (md->type == eModifierType_Boolean) {
+ BooleanModifierData *bmd = (BooleanModifierData *)md;
+ if (bmd->object && bmd->object->type == OB_MESH) {
+ DAG_id_tag_update(&bmd->object->id, OB_RECALC_DATA);
+ }
+ }
+ else if (md->type == eModifierType_Array) {
+ ArrayModifierData *amd = (ArrayModifierData *)md;
+ if (amd->start_cap && amd->start_cap->type == OB_MESH) {
+ DAG_id_tag_update(&amd->start_cap->id, OB_RECALC_DATA);
+ }
+ if (amd->end_cap && amd->end_cap->type == OB_MESH) {
+ DAG_id_tag_update(&amd->end_cap->id, OB_RECALC_DATA);
+ }
+ }
+ else if (md->type == eModifierType_Shrinkwrap) {
+ ShrinkwrapModifierData *smd = (ShrinkwrapModifierData *)md;
+ if (smd->target && smd->target->type == OB_MESH) {
+ DAG_id_tag_update(&smd->target->id, OB_RECALC_DATA);
+ }
+ }
+ }
+ }
+ }
+ }
+}
+#endif
+
static void tag_scenes_for_render(Render *re)
{
bNode *node;
Scene *sce;
+#ifdef DEPSGRAPH_WORKAROUND_HACK
+ int renderlay = re->lay;
+#endif
- for (sce = re->main->scene.first; sce; sce = sce->id.next)
+ for (sce = re->main->scene.first; sce; sce = sce->id.next) {
sce->id.flag &= ~LIB_DOIT;
+#ifdef DEPSGRAPH_WORKAROUND_HACK
+ tag_dependend_objects_for_render(sce, renderlay);
+#endif
+ }
#ifdef WITH_FREESTYLE
- for (sce = re->freestyle_bmain.scene.first; sce; sce = sce->id.next)
+ for (sce = re->freestyle_bmain.scene.first; sce; sce = sce->id.next) {
sce->id.flag &= ~LIB_DOIT;
+#ifdef DEPSGRAPH_WORKAROUND_HACK
+ tag_dependend_objects_for_render(sce, renderlay);
+#endif
+ }
#endif
- if (RE_GetCamera(re) && composite_needs_render(re->scene, 1))
+ if (RE_GetCamera(re) && composite_needs_render(re->scene, 1)) {
re->scene->id.flag |= LIB_DOIT;
+#ifdef DEPSGRAPH_WORKAROUND_HACK
+ tag_dependend_objects_for_render(re->scene, renderlay);
+#endif
+ }
if (re->scene->nodetree == NULL) return;
@@ -1632,6 +1734,9 @@ static void tag_scenes_for_render(Render *re)
if ((node->id->flag & LIB_DOIT) == 0) {
node->flag |= NODE_TEST;
node->id->flag |= LIB_DOIT;
+#ifdef DEPSGRAPH_WORKAROUND_HACK
+ tag_dependend_objects_for_render((Scene *) node->id, renderlay);
+#endif
}
}
}
@@ -2020,7 +2125,7 @@ static void do_render_composite_fields_blur_3d(Render *re)
R.stats_draw = re->stats_draw;
if (update_newframe)
- BKE_scene_update_for_newframe(re->main, re->scene, re->lay);
+ BKE_scene_update_for_newframe(re->eval_ctx, re->main, re->scene, re->lay);
if (re->r.scemode & R_FULL_SAMPLE)
do_merge_fullsample(re, ntree);
@@ -2095,14 +2200,12 @@ static void do_render_seq(Render *re)
if ((re->r.mode & R_BORDER) && (re->r.mode & R_CROP) == 0) {
/* if border rendering is used and cropping is disabled, final buffer should
* be as large as the whole frame */
- context = BKE_sequencer_new_render_data(re->main, re->scene,
- re->winx, re->winy,
- 100);
+ context = BKE_sequencer_new_render_data(re->eval_ctx, re->main, re->scene,
+ re->winx, re->winy, 100);
}
else {
- context = BKE_sequencer_new_render_data(re->main, re->scene,
- re->result->rectx, re->result->recty,
- 100);
+ context = BKE_sequencer_new_render_data(re->eval_ctx, re->main, re->scene,
+ re->result->rectx, re->result->recty, 100);
}
out = BKE_sequencer_give_ibuf(context, cfra, 0);
@@ -2704,7 +2807,7 @@ void RE_BlenderAnim(Render *re, Main *bmain, Scene *scene, Object *camera_overri
else
updatelay = re->lay;
- BKE_scene_update_for_newframe(bmain, scene, updatelay);
+ BKE_scene_update_for_newframe(re->eval_ctx, bmain, scene, updatelay);
continue;
}
else
diff --git a/source/blender/windowmanager/intern/wm_event_system.c b/source/blender/windowmanager/intern/wm_event_system.c
index 8ac8da93584..ee8ad08ad80 100644
--- a/source/blender/windowmanager/intern/wm_event_system.c
+++ b/source/blender/windowmanager/intern/wm_event_system.c
@@ -370,7 +370,7 @@ void wm_event_do_notifiers(bContext *C)
/* XXX, hack so operators can enforce datamasks [#26482], gl render */
win->screen->scene->customdata_mask |= win->screen->scene->customdata_mask_modal;
- BKE_scene_update_tagged(bmain, win->screen->scene);
+ BKE_scene_update_tagged(bmain->eval_ctx, bmain, win->screen->scene);
}
}
diff --git a/source/blender/windowmanager/intern/wm_operators.c b/source/blender/windowmanager/intern/wm_operators.c
index 120f7562f0f..c8c45b3f88a 100644
--- a/source/blender/windowmanager/intern/wm_operators.c
+++ b/source/blender/windowmanager/intern/wm_operators.c
@@ -4141,7 +4141,7 @@ static int redraw_timer_exec(bContext *C, wmOperator *op)
if (a & 1) scene->r.cfra--;
else scene->r.cfra++;
- BKE_scene_update_for_newframe(bmain, scene, scene->lay);
+ BKE_scene_update_for_newframe(bmain->eval_ctx, bmain, scene, scene->lay);
}
else if (type == 5) {
@@ -4156,7 +4156,7 @@ static int redraw_timer_exec(bContext *C, wmOperator *op)
if (scene->r.cfra > scene->r.efra)
scene->r.cfra = scene->r.sfra;
- BKE_scene_update_for_newframe(bmain, scene, scene->lay);
+ BKE_scene_update_for_newframe(bmain->eval_ctx, bmain, scene, scene->lay);
redraw_timer_window_swap(C);
}
}
diff --git a/source/blender/windowmanager/intern/wm_playanim.c b/source/blender/windowmanager/intern/wm_playanim.c
index af73ccc55bb..ab48e72562e 100644
--- a/source/blender/windowmanager/intern/wm_playanim.c
+++ b/source/blender/windowmanager/intern/wm_playanim.c
@@ -60,6 +60,7 @@
#include "IMB_imbuf.h"
#include "BKE_blender.h"
+#include "BKE_depsgraph.h"
#include "BKE_global.h"
#include "BKE_image.h"
@@ -1201,6 +1202,7 @@ static char *wm_main_playanim_intern(int argc, const char **argv)
IMB_exit();
BKE_images_exit();
+ DAG_exit();
totblock = MEM_get_memory_blocks_in_use();
if (totblock != 0) {
diff --git a/source/creator/creator.c b/source/creator/creator.c
index 3d0b558a502..d7cba36202e 100644
--- a/source/creator/creator.c
+++ b/source/creator/creator.c
@@ -1258,6 +1258,7 @@ static int load_file(int UNUSED(argc), const char **argv, void *data)
* pointcache works */
if (retval != BKE_READ_FILE_FAIL) {
wmWindowManager *wm = CTX_wm_manager(C);
+ Main *bmain = CTX_data_main(C);
/* special case, 2.4x files */
if (wm == NULL && CTX_data_main(C)->wm.first == NULL) {
@@ -1273,8 +1274,8 @@ static int load_file(int UNUSED(argc), const char **argv, void *data)
G.relbase_valid = 1;
if (CTX_wm_manager(C) == NULL) CTX_wm_manager_set(C, wm); /* reset wm */
- DAG_on_visible_update(CTX_data_main(C), TRUE);
- BKE_scene_update_tagged(CTX_data_main(C), CTX_data_scene(C));
+ DAG_on_visible_update(bmain, TRUE);
+ BKE_scene_update_tagged(bmain->eval_ctx, bmain, CTX_data_scene(C));
}
else {
/* failed to load file, stop processing arguments */
@@ -1582,6 +1583,7 @@ int main(int argc, const char **argv)
IMB_init();
BKE_images_init();
BKE_modifier_init();
+ DAG_init();
BKE_brush_system_init();
diff --git a/source/gameengine/GamePlayer/ghost/GPG_ghost.cpp b/source/gameengine/GamePlayer/ghost/GPG_ghost.cpp
index b04dbc75fe4..57aafede143 100644
--- a/source/gameengine/GamePlayer/ghost/GPG_ghost.cpp
+++ b/source/gameengine/GamePlayer/ghost/GPG_ghost.cpp
@@ -443,6 +443,7 @@ int main(int argc, char** argv)
IMB_init();
BKE_images_init();
BKE_modifier_init();
+ DAG_init();
#ifdef WITH_FFMPEG
IMB_ffmpeg_init();
@@ -1066,6 +1067,7 @@ int main(int argc, char** argv)
IMB_exit();
BKE_images_exit();
+ DAG_exit();
SYS_DeleteSystem(syshandle);