Merging r58112 through r58124 from trunk into soc-2013-depsgraph_mt
authorSergey Sharybin <sergey.vfx@gmail.com>
Tue, 9 Jul 2013 19:22:26 +0000 (19:22 +0000)
committerSergey Sharybin <sergey.vfx@gmail.com>
Tue, 9 Jul 2013 19:22:26 +0000 (19:22 +0000)
55 files changed:
release/datafiles/startup.blend
release/scripts/startup/bl_ui/properties_render.py
source/blender/blenkernel/BKE_anim.h
source/blender/blenkernel/BKE_curve.h
source/blender/blenkernel/BKE_depsgraph.h
source/blender/blenkernel/BKE_mball.h
source/blender/blenkernel/BKE_modifier.h
source/blender/blenkernel/BKE_object.h
source/blender/blenkernel/depsgraph_private.h
source/blender/blenkernel/intern/DerivedMesh.c
source/blender/blenkernel/intern/anim.c
source/blender/blenkernel/intern/armature.c
source/blender/blenkernel/intern/cdderivedmesh.c
source/blender/blenkernel/intern/constraint.c
source/blender/blenkernel/intern/curve.c
source/blender/blenkernel/intern/depsgraph.c
source/blender/blenkernel/intern/displist.c
source/blender/blenkernel/intern/effect.c
source/blender/blenkernel/intern/font.c
source/blender/blenkernel/intern/lattice.c
source/blender/blenkernel/intern/material.c
source/blender/blenkernel/intern/mball.c
source/blender/blenkernel/intern/mesh.c
source/blender/blenkernel/intern/modifier.c
source/blender/blenkernel/intern/object.c
source/blender/blenkernel/intern/object_deform.c
source/blender/blenkernel/intern/scene.c
source/blender/blenlib/BLI_task.h [new file with mode: 0644]
source/blender/blenlib/BLI_threads.h
source/blender/blenlib/CMakeLists.txt
source/blender/blenlib/intern/task.c [new file with mode: 0644]
source/blender/blenlib/intern/threads.c
source/blender/blenloader/intern/readfile.c
source/blender/editors/interface/interface_templates.c
source/blender/editors/object/object_add.c
source/blender/editors/object/object_modifier.c
source/blender/editors/render/render_internal.c
source/blender/editors/sculpt_paint/sculpt.c
source/blender/editors/space_image/image_ops.c
source/blender/editors/space_info/info_stats.c
source/blender/editors/space_view3d/drawobject.c
source/blender/editors/space_view3d/view3d_iterators.c
source/blender/editors/util/crazyspace.c
source/blender/makesdna/DNA_curve_types.h
source/blender/makesdna/DNA_object_types.h
source/blender/makesdna/DNA_scene_types.h
source/blender/makesdna/DNA_windowmanager_types.h
source/blender/makesrna/intern/rna_main_api.c
source/blender/makesrna/intern/rna_scene.c
source/blender/modifiers/intern/MOD_array.c
source/blender/windowmanager/WM_api.h
source/blender/windowmanager/WM_types.h
source/blender/windowmanager/intern/wm_event_system.c
source/creator/creator.c
source/gameengine/GamePlayer/ghost/GPG_ghost.cpp

index c604d16829ce6a5106e895002102e33bd2a83707..8b58493fe3a4a1b8e404ee214d1610104aabbab8 100644 (file)
Binary files a/release/datafiles/startup.blend and b/release/datafiles/startup.blend differ
index 799c109ae0cd0606ce2260c4dc6b786277538132..bf4975f2e43ab4f3b2f54e6cc41cc3a507a76e21 100644 (file)
@@ -70,6 +70,7 @@ class RENDER_PT_render(RenderButtonsPanel, Panel):
         row.operator("render.play_rendered_anim", text="Play", icon='PLAY')
 
         layout.prop(rd, "display_mode", text="Display")
+        layout.prop(rd, "use_lock_interface")
 
 
 class RENDER_PT_dimensions(RenderButtonsPanel, Panel):
index 539c5780cd51ace7cd09ee131f20232217ff288e..7de7a745ed638f57ad1e95f33ca5454de2f0c23c 100644 (file)
@@ -59,7 +59,7 @@ void animviz_calc_motionpaths(struct Scene *scene, ListBase *targets);
 /* Curve Paths */
 
 void free_path(struct Path *path);
-void calc_curvepath(struct Object *ob);
+void calc_curvepath(struct Object *ob, struct ListBase *nurbs);
 int where_on_path(struct Object *ob, float ctime, float vec[4], float dir[3], float quat[4], float *radius, float *weight);
 
 /* ---------------------------------------------------- */
index 3be77086336b44c34a97a315229763076f4e3373..de60e1447dd44a64d29c49b99f444b421ea629bf 100644 (file)
@@ -42,6 +42,13 @@ struct Main;
 struct Nurb;
 struct Object;
 struct Scene;
+struct Path;
+
+typedef struct CurveCache {
+       ListBase disp;
+       ListBase bev;
+       struct Path *path;
+} CurveCache;
 
 #define KNOTSU(nu)      ( (nu)->orderu + (nu)->pntsu + (((nu)->flagu & CU_NURB_CYCLIC) ? ((nu)->orderu - 1) : 0) )
 #define KNOTSV(nu)      ( (nu)->orderv + (nu)->pntsv + (((nu)->flagv & CU_NURB_CYCLIC) ? ((nu)->orderv - 1) : 0) )
@@ -73,11 +80,11 @@ void BKE_curve_delete_material_index(struct Curve *cu, int index);
 
 ListBase *BKE_curve_nurbs_get(struct Curve *cu);
 
-float (*BKE_curve_vertexCos_get(struct Curve *cu, struct ListBase *lb, int *numVerts_r))[3];
-void BK_curve_vertexCos_apply(struct Curve *cu, struct ListBase *lb, float (*vertexCos)[3]);
+float (*BKE_curve_nurbs_vertexCos_get(struct ListBase *lb, int *numVerts_r))[3];
+void BK_curve_nurbs_vertexCos_apply(struct ListBase *lb, float (*vertexCos)[3]);
 
-float (*BKE_curve_keyVertexCos_get(struct Curve *cu, struct ListBase *lb, float *key))[3];
-void BKE_curve_keyVertexTilts_apply(struct Curve *cu, struct ListBase *lb, float *key);
+float (*BKE_curve_nurbs_keyVertexCos_get(struct ListBase *lb, float *key))[3];
+void BKE_curve_nurbs_keyVertexTilts_apply(struct ListBase *lb, float *key);
 
 void BKE_curve_editNurb_keyIndex_free(struct EditNurb *editnurb);
 void BKE_curve_editNurb_free(struct Curve *cu);
@@ -86,7 +93,7 @@ struct ListBase *BKE_curve_editNurbs_get(struct Curve *cu);
 float *BKE_curve_make_orco(struct Scene *scene, struct Object *ob, int *r_numVerts);
 float *BKE_curve_surf_make_orco(struct Object *ob);
 
-void BKE_curve_bevelList_make(struct Object *ob);
+void BKE_curve_bevelList_make(struct Object *ob, struct ListBase *nurbs, bool for_render);
 void BKE_curve_bevel_make(struct Scene *scene, struct Object *ob,  struct ListBase *disp, int forRender, int renderResolution);
 
 void BKE_curve_forward_diff_bezier(float q0, float q1, float q2, float q3, float *p, int it, int stride);
index 6baf20aeb2c89e4423cbbe35cbd57c9d8c23cef4..f58790c4a1f826a7fa45912891393838ceab842a 100644 (file)
@@ -48,6 +48,7 @@ struct ID;
 struct Main;
 struct Object;
 struct Scene;
+struct ListBase;
 
 /* Build and Update
  *
@@ -115,6 +116,24 @@ 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);
+
+/* Run a callback for every node which is ready for update. */
+void DAG_threaded_update_foreach_ready_node(struct Scene *scene,
+                                            void (*func)(void *node, void *user_data),
+                                            void *user_data);
+
+struct Object *DAG_threaded_update_get_node_object(void *node_v);
+
+const char *DAG_threaded_update_get_node_name(void *node_v);
+
+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);
index 44459300c5640b8d7f6574e373b3b0e4ed97636e..7665e1b54dc6df497daf6cb9ff84889f9f329a38 100644 (file)
@@ -47,7 +47,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);
+void BKE_mball_polygonize(struct Scene *scene, struct Object *ob, struct ListBase *dispbase, bool for_render);
 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);
index 0727e11f3978a6f81812aa76e3c316cc3e40e0b5..8f0d612d473f48effe1113cbec5f1c63bcd8eec4 100644 (file)
@@ -304,6 +304,9 @@ typedef struct ModifierTypeInfo {
                               TexWalkFunc walk, void *userData);
 } ModifierTypeInfo;
 
+/* Initialize modifier's global data (type info and some common global storages). */
+void BKE_modifier_init(void);
+
 ModifierTypeInfo *modifierType_getInfo(ModifierType type);
 
 /* Modifier utility calls, do call through type pointer and return
@@ -377,7 +380,15 @@ struct CDMaskLink *modifiers_calcDataMasks(struct Scene *scene,
 struct ModifierData *modifiers_getLastPreview(struct Scene *scene,
                                               struct ModifierData *md,
                                               int required_mode);
-struct ModifierData  *modifiers_getVirtualModifierList(struct Object *ob);
+
+typedef struct VirtualModifierData {
+       ArmatureModifierData amd;
+       CurveModifierData cmd;
+       LatticeModifierData lmd;
+       ShapeKeyModifierData smd;
+} VirtualModifierData;
+
+struct ModifierData  *modifiers_getVirtualModifierList(struct Object *ob, struct VirtualModifierData *data);
 
 /* ensure modifier correctness when changing ob->data */
 void test_object_modifiers(struct Object *ob);
index 463720fb8cfdd8ed25785d6b038502656ed963d3..0f390e618712cf1f7068135fc21d7f3e8c9d5a82 100644 (file)
@@ -60,6 +60,7 @@ void BKE_object_copy_softbody(struct Object *obn, struct Object *ob);
 void BKE_object_free_particlesystems(struct Object *ob);
 void BKE_object_free_softbody(struct Object *ob);
 void BKE_object_free_bulletsoftbody(struct Object *ob);
+void BKE_object_free_curve_cache(struct Object *ob);
 void BKE_object_update_base_layer(struct Scene *scene, struct Object *ob);
 
 void BKE_object_free(struct Object *ob);
index c8ce2bb2a773376e2bfc10280bf235db020c0178..a47d94f1e7275e513e094bda04470e6ae6ed75c7 100644 (file)
@@ -92,6 +92,13 @@ typedef struct DagNode {
        struct DagAdjList *child;
        struct DagAdjList *parent;
        struct DagNode *next;
+
+       /* Threaded evaluation routines */
+       int valency;        /* valency of the node is a 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.
+                            */
 } DagNode;
 
 typedef struct DagNodeQueueElem {
index 6bde0a501f3902d07929cd06704e925df63ad690..9260a1063087cc0b6552db7cc1ca19b59ee6472a 100644 (file)
@@ -49,6 +49,7 @@
 #include "BLI_array.h"
 #include "BLI_utildefines.h"
 #include "BLI_linklist.h"
+#include "BLI_threads.h"
 
 #include "BKE_pbvh.h"
 #include "BKE_cdderivedmesh.h"
@@ -1442,6 +1443,8 @@ static void mesh_calc_modifiers(Scene *scene, Object *ob, float (*inputVertexCos
        /* XXX Same as above... For now, only weights preview in WPaint mode. */
        const int do_mod_wmcol = do_init_wmcol;
 
+       VirtualModifierData virtualModifierData;
+
        ModifierApplyFlag app_flags = useRenderParams ? MOD_APPLY_RENDER : 0;
        ModifierApplyFlag deform_app_flags = app_flags;
        if (useCache)
@@ -1453,7 +1456,7 @@ static void mesh_calc_modifiers(Scene *scene, Object *ob, float (*inputVertexCos
                has_multires = 0;
 
        if (!skipVirtualArmature) {
-               firstmd = modifiers_getVirtualModifierList(ob);
+               firstmd = modifiers_getVirtualModifierList(ob, &virtualModifierData);
        }
        else {
                /* game engine exception */
@@ -1963,6 +1966,7 @@ static void editbmesh_calc_modifiers(Scene *scene, Object *ob, BMEditMesh *em, D
        int do_init_wmcol = ((((Mesh *)ob->data)->drawflag & ME_DRAWEIGHT) && !do_final_wmcol);
        int do_init_statvis = ((((Mesh *)ob->data)->drawflag & ME_DRAW_STATVIS) && !do_init_wmcol);
        const int do_mod_wmcol = do_init_wmcol;
+       VirtualModifierData virtualModifierData;
 
        modifiers_clearErrors(ob);
 
@@ -1971,7 +1975,7 @@ static void editbmesh_calc_modifiers(Scene *scene, Object *ob, BMEditMesh *em, D
        }
 
        dm = NULL;
-       md = modifiers_getVirtualModifierList(ob);
+       md = modifiers_getVirtualModifierList(ob, &virtualModifierData);
 
        /* copied from mesh_calc_modifiers */
        if (do_mod_wmcol) {
index 9fea3d2e13f507d7dbfa8053844c80b3a4c05db8..290e3ee5433111a7986114990136c9f789192a3c 100644 (file)
@@ -488,7 +488,7 @@ void free_path(Path *path)
 /* calculate a curve-deform path for a curve 
  *  - only called from displist.c -> do_makeDispListCurveTypes
  */
-void calc_curvepath(Object *ob)
+void calc_curvepath(Object *ob, ListBase *nurbs)
 {
        BevList *bl;
        BevPoint *bevp, *bevpn, *bevpfirst, *bevplast;
@@ -499,7 +499,6 @@ void calc_curvepath(Object *ob)
        float *fp, *dist, *maxdist, xyz[3];
        float fac, d = 0, fac1, fac2;
        int a, tot, cycl = 0;
-       ListBase *nurbs;
        
        /* in a path vertices are with equal differences: path->len = number of verts */
        /* NOW WITH BEVELCURVE!!! */
@@ -509,19 +508,18 @@ void calc_curvepath(Object *ob)
        }
        cu = ob->data;
 
-       if (cu->path) free_path(cu->path);
-       cu->path = NULL;
+       if (ob->curve_cache->path) free_path(ob->curve_cache->path);
+       ob->curve_cache->path = NULL;
        
        /* weak! can only use first curve */
-       bl = cu->bev.first;
+       bl = ob->curve_cache->bev.first;
        if (bl == NULL || !bl->nr) {
                return;
        }
 
-       nurbs = BKE_curve_nurbs_get(cu);
        nu = nurbs->first;
 
-       cu->path = path = MEM_callocN(sizeof(Path), "calc_curvepath");
+       ob->curve_cache->path = path = MEM_callocN(sizeof(Path), "calc_curvepath");
        
        /* if POLY: last vertice != first vertice */
        cycl = (bl->poly != -1);
@@ -630,15 +628,15 @@ int where_on_path(Object *ob, float ctime, float vec[4], float dir[3], float qua
 
        if (ob == NULL || ob->type != OB_CURVE) return 0;
        cu = ob->data;
-       if (cu->path == NULL || cu->path->data == NULL) {
+       if (ob->curve_cache == NULL || ob->curve_cache->path == NULL || ob->curve_cache->path->data == NULL) {
                printf("no path!\n");
                return 0;
        }
-       path = cu->path;
+       path = ob->curve_cache->path;
        pp = path->data;
        
        /* test for cyclic */
-       bl = cu->bev.first;
+       bl = ob->curve_cache->bev.first;
        if (!bl) return 0;
        if (!bl->nr) return 0;
        if (bl->poly > -1) cycl = 1;
index 8fae35864390a21d3324c789f3a5d6c4f17535e9..196d4dfb2564df9a59a38746e6c5713486e3c916 100644 (file)
@@ -1816,18 +1816,16 @@ static void splineik_init_tree_from_pchan(Scene *scene, Object *UNUSED(ob), bPos
         *     - this is a workaround for a depsgraph bug...
         */
        if (ikData->tar) {
-               Curve *cu = ikData->tar->data;
-
                /* note: when creating constraints that follow path, the curve gets the CU_PATH set now,
                 *       currently for paths to work it needs to go through the bevlist/displist system (ton)
                 */
 
                /* only happens on reload file, but violates depsgraph still... fix! */
-               if (ELEM(NULL, cu->path, cu->path->data)) {
+               if (ELEM3(NULL,  ikData->tar->curve_cache, ikData->tar->curve_cache->path, ikData->tar->curve_cache->path->data)) {
                        BKE_displist_make_curveTypes(scene, ikData->tar, 0);
                        
                        /* path building may fail in EditMode after removing verts [#33268]*/
-                       if (ELEM(NULL, cu->path, cu->path->data)) {
+                       if (ELEM(NULL, ikData->tar->curve_cache->path, ikData->tar->curve_cache->path->data)) {
                                /* BLI_assert(cu->path != NULL); */
                                return;
                        }
@@ -1891,7 +1889,6 @@ static void splineik_init_tree_from_pchan(Scene *scene, Object *UNUSED(ob), bPos
         * since it's easier to determine the positions of all the joints beforehand this way
         */
        if ((ikData->flag & CONSTRAINT_SPLINEIK_SCALE_LIMITED) && (totLength != 0.0f)) {
-               Curve *cu = (Curve *)ikData->tar->data;
                float splineLen, maxScale;
                int i;
 
@@ -1904,7 +1901,7 @@ static void splineik_init_tree_from_pchan(Scene *scene, Object *UNUSED(ob), bPos
 
                /* get the current length of the curve */
                /* NOTE: this is assumed to be correct even after the curve was resized */
-               splineLen = cu->path->totdist;
+               splineLen = ikData->tar->curve_cache->path->totdist;
 
                /* calculate the scale factor to multiply all the path values by so that the
                 * bone chain retains its current length, such that
index 7f6dc680a7468172e4150a2f3781c5e3e029fe7e..711ea791cbb0bd68244ac6abff1ef34c6c5b5ba6 100644 (file)
@@ -1818,7 +1818,13 @@ DerivedMesh *CDDM_from_mesh(Mesh *mesh, Object *UNUSED(ob))
 
 DerivedMesh *CDDM_from_curve(Object *ob)
 {
-       return CDDM_from_curve_displist(ob, &ob->disp);
+       ListBase disp = {NULL, NULL};
+
+       if (ob->curve_cache) {
+               disp = ob->curve_cache->disp;
+       }
+
+       return CDDM_from_curve_displist(ob, &disp);
 }
 
 DerivedMesh *CDDM_from_curve_displist(Object *ob, ListBase *dispbase)
index 0cd13d528d559fba45a2364f33da23aadd1ede93..7ead1da02d8ebbef1922367fc81a6dca1189cdde 100644 (file)
@@ -69,6 +69,7 @@
 #include "BKE_bvhutils.h"
 #include "BKE_camera.h"
 #include "BKE_constraint.h"
+#include "BKE_curve.h"
 #include "BKE_displist.h"
 #include "BKE_deform.h"
 #include "BKE_DerivedMesh.h"    /* for geometry targets */
@@ -449,7 +450,7 @@ static void contarget_get_lattice_mat(Object *ob, const char *substring, float m
 {
        Lattice *lt = (Lattice *)ob->data;
        
-       DispList *dl = BKE_displist_find(&ob->disp, DL_VERTS);
+       DispList *dl = ob->curve_cache ? BKE_displist_find(&ob->curve_cache->disp, DL_VERTS) : NULL;
        float *co = dl ? dl->verts : NULL;
        BPoint *bp = lt->def;
        
@@ -1164,10 +1165,10 @@ static void followpath_get_tarmat(bConstraint *con, bConstraintOb *cob, bConstra
                 */
                
                /* only happens on reload file, but violates depsgraph still... fix! */
-               if (cu->path == NULL || cu->path->data == NULL)
+               if (ct->tar->curve_cache == NULL || ct->tar->curve_cache->path == NULL || ct->tar->curve_cache->path->data == NULL)
                        BKE_displist_make_curveTypes(cob->scene, ct->tar, 0);
                
-               if (cu->path && cu->path->data) {
+               if (ct->tar->curve_cache->path && ct->tar->curve_cache->path->data) {
                        float quat[4];
                        if ((data->followflag & FOLLOWPATH_STATIC) == 0) {
                                /* animated position along curve depending on time */
@@ -1934,10 +1935,8 @@ static void pycon_get_tarmat(bConstraint *con, bConstraintOb *cob, bConstraintTa
        if (VALID_CONS_TARGET(ct)) {
                /* special exception for curves - depsgraph issues */
                if (ct->tar->type == OB_CURVE) {
-                       Curve *cu = ct->tar->data;
-                       
                        /* this check is to make sure curve objects get updated on file load correctly.*/
-                       if (cu->path == NULL || cu->path->data == NULL) /* only happens on reload file, but violates depsgraph still... fix! */
+                       if (ct->tar->curve_cache == NULL || ct->tar->curve_cache->path == NULL || ct->tar->curve_cache->path->data == NULL) /* only happens on reload file, but violates depsgraph still... fix! */
                                BKE_displist_make_curveTypes(cob->scene, ct->tar, 0);
                }
                
@@ -3008,14 +3007,12 @@ static void clampto_flush_tars(bConstraint *con, ListBase *list, short nocopy)
 static void clampto_get_tarmat(bConstraint *UNUSED(con), bConstraintOb *cob, bConstraintTarget *ct, float UNUSED(ctime))
 {
        if (VALID_CONS_TARGET(ct)) {
-               Curve *cu = ct->tar->data;
-               
                /* note: when creating constraints that follow path, the curve gets the CU_PATH set now,
                 *              currently for paths to work it needs to go through the bevlist/displist system (ton) 
                 */
                
                /* only happens on reload file, but violates depsgraph still... fix! */
-               if (cu->path == NULL || cu->path->data == NULL)
+               if (ct->tar->curve_cache == NULL || ct->tar->curve_cache->path == NULL || ct->tar->curve_cache->path->data == NULL)
                        BKE_displist_make_curveTypes(cob->scene, ct->tar, 0);
        }
        
@@ -3033,7 +3030,6 @@ static void clampto_evaluate(bConstraint *con, bConstraintOb *cob, ListBase *tar
        
        /* only evaluate if there is a target and it is a curve */
        if (VALID_CONS_TARGET(ct) && (ct->tar->type == OB_CURVE)) {
-               Curve *cu = data->tar->data;
                float obmat[4][4], ownLoc[3];
                float curveMin[3], curveMax[3];
                float targetMatrix[4][4] = MAT4_UNITY;
@@ -3046,7 +3042,7 @@ static void clampto_evaluate(bConstraint *con, bConstraintOb *cob, ListBase *tar
                BKE_object_minmax(ct->tar, curveMin, curveMax, TRUE);
                
                /* get targetmatrix */
-               if (cu->path && cu->path->data) {
+               if (data->tar->curve_cache &&  data->tar->curve_cache->path && data->tar->curve_cache->path->data) {
                        float vec[4], dir[3], totmat[4][4];
                        float curvetime;
                        short clamp_axis;
@@ -3649,14 +3645,12 @@ static void splineik_flush_tars(bConstraint *con, ListBase *list, short nocopy)
 static void splineik_get_tarmat(bConstraint *UNUSED(con), bConstraintOb *cob, bConstraintTarget *ct, float UNUSED(ctime))
 {
        if (VALID_CONS_TARGET(ct)) {
-               Curve *cu = ct->tar->data;
-               
                /* note: when creating constraints that follow path, the curve gets the CU_PATH set now,
                 *              currently for paths to work it needs to go through the bevlist/displist system (ton) 
                 */
                
                /* only happens on reload file, but violates depsgraph still... fix! */
-               if (cu->path == NULL || cu->path->data == NULL)
+               if (ct->tar->curve_cache == NULL || ct->tar->curve_cache->path == NULL || ct->tar->curve_cache->path->data == NULL)
                        BKE_displist_make_curveTypes(cob->scene, ct->tar, 0);
        }
        
index 3b9fbbb1c4d98948dfbb57ee9ff707250fbc7089..8950a8c72e6c932c30870f5e2a4b15d0464fd4ca 100644 (file)
@@ -145,8 +145,6 @@ void BKE_curve_editNurb_free(Curve *cu)
 void BKE_curve_free(Curve *cu)
 {
        BKE_nurbList_free(&cu->nurb);
-       BLI_freelistN(&cu->bev);
-       BKE_displist_free(&cu->disp);
        BKE_curve_editfont_free(cu);
 
        BKE_curve_editNurb_free(cu);
@@ -161,8 +159,6 @@ void BKE_curve_free(Curve *cu)
                MEM_freeN(cu->strinfo);
        if (cu->bb)
                MEM_freeN(cu->bb);
-       if (cu->path)
-               free_path(cu->path);
        if (cu->tb)
                MEM_freeN(cu->tb);
 }
@@ -228,10 +224,6 @@ Curve *BKE_curve_copy(Curve *cu)
        cun->key = BKE_key_copy(cu->key);
        if (cun->key) cun->key->from = (ID *)cun;
 
-       cun->disp.first = cun->disp.last = NULL;
-       cun->bev.first = cun->bev.last = NULL;
-       cun->path = NULL;
-
        cun->editnurb = NULL;
        cun->editfont = NULL;
        cun->selboxes = NULL;
@@ -374,36 +366,14 @@ void BKE_curve_type_test(Object *ob)
 
 void BKE_curve_texspace_calc(Curve *cu)
 {
-       DispList *dl;
-       BoundBox *bb;
-       float *fp, min[3], max[3];
-       int tot, do_it = FALSE;
-
-       if (cu->bb == NULL)
-               cu->bb = MEM_callocN(sizeof(BoundBox), "boundbox");
-       bb = cu->bb;
-
-       INIT_MINMAX(min, max);
-
-       dl = cu->disp.first;
-       while (dl) {
-               tot = ELEM(dl->type, DL_INDEX3, DL_INDEX4) ? dl->nr : dl->nr * dl->parts;
-
-               if (tot) do_it = TRUE;
-               fp = dl->verts;
-               while (tot--) {
-                       minmax_v3v3_v3(min, max, fp);
-                       fp += 3;
-               }
-               dl = dl->next;
-       }
-
-       if (do_it == FALSE) {
-               min[0] = min[1] = min[2] = -1.0f;
-               max[0] = max[1] = max[2] = 1.0f;
-       }
+       BoundBox *bb = cu->bb;
+       float min[3], max[3];
 
-       BKE_boundbox_init_from_minmax(bb, min, max);
+       /* Curve's undeformed bounding box is calculated in displist.c,
+        * as a part of display list calculation.
+        */
+       copy_v3_v3(min, bb->vec[0]);
+       copy_v3_v3(max, bb->vec[6]);
 
        if (cu->texflag & CU_AUTOSPACE) {
                mid_v3_v3v3(cu->loc, min, max);
@@ -1449,10 +1419,10 @@ void BKE_curve_bevel_make(Scene *scene, Object *ob, ListBase *disp, int forRende
                                dl = bevdisp.first;
                        }
                        else {
-                               dl = cu->bevobj->disp.first;
+                               dl = cu->bevobj->curve_cache ? cu->bevobj->curve_cache->disp.first : NULL;
                                if (dl == NULL) {
                                        BKE_displist_make_curveTypes(scene, cu->bevobj, 0);
-                                       dl = cu->bevobj->disp.first;
+                                       dl = cu->bevobj->curve_cache->disp.first;
                                }
                        }
 
@@ -2269,7 +2239,7 @@ static void make_bevel_list_2D(BevList *bl)
        }
 }
 
-void BKE_curve_bevelList_make(Object *ob)
+void BKE_curve_bevelList_make(Object *ob, ListBase *nurbs, bool for_render)
 {
        /*
         * - convert all curves to polys, with indication of resol and flags for double-vertices
@@ -2288,24 +2258,23 @@ void BKE_curve_bevelList_make(Object *ob)
        int a, b, nr, poly, resolu = 0, len = 0;
        int do_tilt, do_radius, do_weight;
        int is_editmode = 0;
+       ListBase *bev;
 
        /* this function needs an object, because of tflag and upflag */
        cu = ob->data;
 
+       bev = &ob->curve_cache->bev;
+
        /* do we need to calculate the radius for each point? */
        /* do_radius = (cu->bevobj || cu->taperobj || (cu->flag & CU_FRONT) || (cu->flag & CU_BACK)) ? 0 : 1; */
 
        /* STEP 1: MAKE POLYS  */
 
-       BLI_freelistN(&(cu->bev));
+       BLI_freelistN(&(ob->curve_cache->bev));
+       nu = nurbs->first;
        if (cu->editnurb && ob->type != OB_FONT) {
-               ListBase *nurbs = BKE_curve_editNurbs_get(cu);
-               nu = nurbs->first;
                is_editmode = 1;
        }
-       else {
-               nu = cu->nurb.first;
-       }
 
        for (; nu; nu = nu->next) {
                
@@ -2321,11 +2290,11 @@ void BKE_curve_bevelList_make(Object *ob)
                 * enforced in the UI but can go wrong possibly */
                if (!BKE_nurb_check_valid_u(nu)) {
                        bl = MEM_callocN(sizeof(BevList) + 1 * sizeof(BevPoint), "makeBevelList1");
-                       BLI_addtail(&(cu->bev), bl);
+                       BLI_addtail(bev, bl);
                        bl->nr = 0;
                }
                else {
-                       if (G.is_rendering && cu->resolu_ren != 0)
+                       if (for_render && cu->resolu_ren != 0)
                                resolu = cu->resolu_ren;
                        else
                                resolu = nu->resolu;
@@ -2333,7 +2302,7 @@ void BKE_curve_bevelList_make(Object *ob)
                        if (nu->type == CU_POLY) {
                                len = nu->pntsu;
                                bl = MEM_callocN(sizeof(BevList) + len * sizeof(BevPoint), "makeBevelList2");
-                               BLI_addtail(&(cu->bev), bl);
+                               BLI_addtail(bev, bl);
 
                                if (nu->flagu & CU_NURB_CYCLIC) bl->poly = 0;
                                else bl->poly = -1;
@@ -2356,7 +2325,7 @@ void BKE_curve_bevelList_make(Object *ob)
                                /* in case last point is not cyclic */
                                len = resolu * (nu->pntsu + (nu->flagu & CU_NURB_CYCLIC) - 1) + 1;
                                bl = MEM_callocN(sizeof(BevList) + len * sizeof(BevPoint), "makeBevelBPoints");
-                               BLI_addtail(&(cu->bev), bl);
+                               BLI_addtail(bev, bl);
 
                                if (nu->flagu & CU_NURB_CYCLIC) bl->poly = 0;
                                else bl->poly = -1;
@@ -2442,7 +2411,7 @@ void BKE_curve_bevelList_make(Object *ob)
                                        len = (resolu * SEGMENTSU(nu));
 
                                        bl = MEM_callocN(sizeof(BevList) + len * sizeof(BevPoint), "makeBevelList3");
-                                       BLI_addtail(&(cu->bev), bl);
+                                       BLI_addtail(bev, bl);
                                        bl->nr = len;
                                        bl->dupe_nr = 0;
                                        if (nu->flagu & CU_NURB_CYCLIC) bl->poly = 0;
@@ -2460,7 +2429,7 @@ void BKE_curve_bevelList_make(Object *ob)
        }
 
        /* STEP 2: DOUBLE POINTS AND AUTOMATIC RESOLUTION, REDUCE DATABLOCKS */
-       bl = cu->bev.first;
+       bl = bev->first;
        while (bl) {
                if (bl->nr) { /* null bevel items come from single points */
                        nr = bl->nr;
@@ -2482,7 +2451,7 @@ void BKE_curve_bevelList_make(Object *ob)
                }
                bl = bl->next;
        }
-       bl = cu->bev.first;
+       bl = bev->first;
        while (bl) {
                blnext = bl->next;
                if (bl->nr && bl->dupe_nr) {
@@ -2490,8 +2459,8 @@ void BKE_curve_bevelList_make(Object *ob)
                        blnew = MEM_mallocN(sizeof(BevList) + nr * sizeof(BevPoint), "makeBevelList4");
                        memcpy(blnew, bl, sizeof(BevList));
                        blnew->nr = 0;
-                       BLI_remlink(&(cu->bev), bl);
-                       BLI_insertlinkbefore(&(cu->bev), blnext, blnew);    /* to make sure bevlijst is tuned with nurblist */
+                       BLI_remlink(bev, bl);
+                       BLI_insertlinkbefore(bev, blnext, blnew);    /* to make sure bevlijst is tuned with nurblist */
                        bevp0 = (BevPoint *)(bl + 1);
                        bevp1 = (BevPoint *)(blnew + 1);
                        nr = bl->nr;
@@ -2510,7 +2479,7 @@ void BKE_curve_bevelList_make(Object *ob)
        }
 
        /* STEP 3: POLYS COUNT AND AUTOHOLE */
-       bl = cu->bev.first;
+       bl = bev->first;
        poly = 0;
        while (bl) {
                if (bl->nr && bl->poly >= 0) {
@@ -2524,7 +2493,7 @@ void BKE_curve_bevelList_make(Object *ob)
        /* find extreme left points, also test (turning) direction */
        if (poly > 0) {
                sd = sortdata = MEM_mallocN(sizeof(struct bevelsort) * poly, "makeBevelList5");
-               bl = cu->bev.first;
+               bl = bev->first;
                while (bl) {
                        if (bl->poly > 0) {
 
@@ -2602,7 +2571,7 @@ void BKE_curve_bevelList_make(Object *ob)
        /* STEP 4: 2D-COSINES or 3D ORIENTATION */
        if ((cu->flag & CU_3D) == 0) {
                /* 2D Curves */
-               for (bl = cu->bev.first; bl; bl = bl->next) {
+               for (bl = bev->first; bl; bl = bl->next) {
                        if (bl->nr < 2) {
                                /* do nothing */
                        }
@@ -2616,7 +2585,7 @@ void BKE_curve_bevelList_make(Object *ob)
        }
        else {
                /* 3D Curves */
-               for (bl = cu->bev.first; bl; bl = bl->next) {
+               for (bl = bev->first; bl; bl = bl->next) {
                        if (bl->nr < 2) {
                                /* do nothing */
                        }
@@ -3205,7 +3174,7 @@ void BKE_nurb_direction_switch(Nurb *nu)
 }
 
 
-float (*BKE_curve_vertexCos_get(Curve *UNUSED(cu), ListBase *lb, int *numVerts_r))[3]
+float (*BKE_curve_nurbs_vertexCos_get(ListBase *lb, int *numVerts_r))[3]
 {
        int i, numVerts = *numVerts_r = BKE_nurbList_verts_count(lb);
        float *co, (*cos)[3] = MEM_mallocN(sizeof(*cos) * numVerts, "cu_vcos");
@@ -3234,7 +3203,7 @@ float (*BKE_curve_vertexCos_get(Curve *UNUSED(cu), ListBase *lb, int *numVerts_r
        return cos;
 }
 
-void BK_curve_vertexCos_apply(Curve *UNUSED(cu), ListBase *lb, float (*vertexCos)[3])
+void BK_curve_nurbs_vertexCos_apply(ListBase *lb, float (*vertexCos)[3])
 {
        float *co = vertexCos[0];
        Nurb *nu;
@@ -3262,7 +3231,7 @@ void BK_curve_vertexCos_apply(Curve *UNUSED(cu), ListBase *lb, float (*vertexCos
        }
 }
 
-float (*BKE_curve_keyVertexCos_get(Curve *UNUSED(cu), ListBase *lb, float *key))[3]
+float (*BKE_curve_nurbs_keyVertexCos_get(ListBase *lb, float *key))[3]
 {
        int i, numVerts = BKE_nurbList_verts_count(lb);
        float *co, (*cos)[3] = MEM_mallocN(sizeof(*cos) * numVerts, "cu_vcos");
@@ -3293,7 +3262,7 @@ float (*BKE_curve_keyVertexCos_get(Curve *UNUSED(cu), ListBase *lb, float *key))
        return cos;
 }
 
-void BKE_curve_keyVertexTilts_apply(Curve *UNUSED(cu), ListBase *lb, float *key)
+void BKE_curve_nurbs_keyVertexTilts_apply(ListBase *lb, float *key)
 {
        Nurb *nu;
        int i;
index 2206770dfbd7b064bf54aac0d46f211c9f62e398..14cbca8a9a014abf96b7653ebfc03e57678c40e6 100644 (file)
@@ -29,6 +29,7 @@
 
  
 #include <stdio.h>
+#include <stdlib.h>
 #include <string.h>
 #include <math.h>
 
@@ -2652,6 +2653,98 @@ void DAG_pose_sort(Object *ob)
        ugly_hack_sorry = 1;
 }
 
+/* ************************  DAG FOR THREADED UPDATE  ********************* */
+
+/* Initialize the DAG for threaded update.
+ *
+ * Sets up all the data needed for faster check whether DAG node is
+ * updatable already (whether all the dependencies are met).
+ */
+void DAG_threaded_update_begin(Scene *scene)
+{
+       DagNode *node;
+
+       /* We reset valency to zero first... */
+       for (node = scene->theDag->DagNode.first; node; node = node->next) {
+               node->valency = 0;
+       }
+
+       /* ... and then iterate over all the nodes and
+        * increase valency 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->valency++;
+                       }
+               }
+       }
+}
+
+/* Call functor for every node in the graph which is ready for
+ * update (all it's dependencies are met). Quick check for this
+ * is valency == 0.
+ */
+void DAG_threaded_update_foreach_ready_node(Scene *scene,
+                                            void (*func)(void *node, void *user_data),
+                                            void *user_data)
+{
+       DagNode *node;
+
+       for (node = scene->theDag->DagNode.first; node; node = node->next) {
+               if (node->valency == 0) {
+                       func(node, user_data);
+               }
+       }
+}
+
+/* Will return Object ID if node represents Object,
+ * and will return NULL otherwise.
+ */
+Object *DAG_threaded_update_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_threaded_update_get_node_name(void *node_v)
+{
+       DagNode *node = node_v;
+
+       return dag_node_name(node);
+}
+
+/* This function is called when handling node is done.
+ *
+ * This function updates valency 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) {
+               if (itA->node != node) {
+                       itA->node->valency--;
+
+                       if (itA->node->valency == 0) {
+                               func(itA->node, user_data);
+                       }
+               }
+       }
+}
+
 /* ************************ DAG DEBUGGING ********************* */
 
 void DAG_print_dependencies(Main *bmain, Scene *scene, Object *ob)
@@ -2670,4 +2763,3 @@ void DAG_print_dependencies(Main *bmain, Scene *scene, Object *ob)
        
        dag_print_dependencies = 0;
 }
-
index 38a0b8483397a4e9c588b7e0a60e1f08146a307e..ddccb2fa783a0c194810bd37d74f7765895ded83 100644 (file)
@@ -62,8 +62,8 @@
 
 #include "BLI_sys_types.h" // for intptr_t support
 
-static void boundbox_displist(Object *ob);
 static void boundbox_dispbase(BoundBox *bb, ListBase *dispbase);
+static void boundbox_displist_object(Object *ob);
 
 void BKE_displist_elem_free(DispList *dl)
 {
@@ -667,10 +667,10 @@ static float displist_calc_taper(Scene *scene, Object *taperobj, float fac)
        if (taperobj == NULL || taperobj->type != OB_CURVE)
                return 1.0;
 
-       dl = taperobj->disp.first;
+       dl = taperobj->curve_cache ? taperobj->curve_cache->disp.first : NULL;
        if (dl == NULL) {
                BKE_displist_make_curveTypes(scene, taperobj, 0);
-               dl = taperobj->disp.first;
+               dl = taperobj->curve_cache->disp.first;
        }
        if (dl) {
                float minx, dx, *fp;
@@ -712,29 +712,28 @@ void BKE_displist_make_mball(Scene *scene, Object *ob)
        if (!ob || ob->type != OB_MBALL)
                return;
 
-       /* XXX: mball stuff uses plenty of global variables
-        *      while this is unchanged updating during render is unsafe
-        */
-       if (G.is_rendering)
-               return;
-
-       BKE_displist_free(&(ob->disp));
+       if (ob->curve_cache) {
+               BKE_displist_free(&(ob->curve_cache->disp));
+       }
+       else {
+               ob->curve_cache = MEM_callocN(sizeof(CurveCache), "CurveCache for MBall");
+       }
 
        if (ob->type == OB_MBALL) {
                if (ob == BKE_mball_basis_find(scene, ob)) {
-                       BKE_mball_polygonize(scene, ob, &ob->disp);
+                       BKE_mball_polygonize(scene, ob, &ob->curve_cache->disp, false);
                        BKE_mball_texspace_calc(ob);
 
-                       object_deform_mball(ob, &ob->disp);
+                       object_deform_mball(ob, &ob->curve_cache->disp);
                }
-       }
 
-       boundbox_displist(ob);
+               boundbox_displist_object(ob);
+       }
 }
 
 void BKE_displist_make_mball_forRender(Scene *scene, Object *ob, ListBase *dispbase)
 {
-       BKE_mball_polygonize(scene, ob, dispbase);
+       BKE_mball_polygonize(scene, ob, dispbase, true);
        BKE_mball_texspace_calc(ob);
 
        object_deform_mball(ob, dispbase);
@@ -742,7 +741,8 @@ void BKE_displist_make_mball_forRender(Scene *scene, Object *ob, ListBase *dispb
 
 static ModifierData *curve_get_tessellate_point(Scene *scene, Object *ob, int renderResolution, int editmode)
 {
-       ModifierData *md = modifiers_getVirtualModifierList(ob);
+       VirtualModifierData virtualModifierData;
+       ModifierData *md = modifiers_getVirtualModifierList(ob, &virtualModifierData);
        ModifierData *pretessellatePoint;
        int required_mode;
 
@@ -780,18 +780,16 @@ static ModifierData *curve_get_tessellate_point(Scene *scene, Object *ob, int re
        return pretessellatePoint;
 }
 
-static void curve_calc_modifiers_pre(Scene *scene, Object *ob, int forRender, int renderResolution,
-                                     float (**originalVerts_r)[3],
-                                     float (**deformedVerts_r)[3], int *numVerts_r)
+static void curve_calc_modifiers_pre(Scene *scene, Object *ob, ListBase *nurb,
+                                     int forRender, int renderResolution)
 {
-       ModifierData *md = modifiers_getVirtualModifierList(ob);
+       VirtualModifierData virtualModifierData;
+       ModifierData *md = modifiers_getVirtualModifierList(ob, &virtualModifierData);
        ModifierData *pretessellatePoint;
        Curve *cu = ob->data;
-       ListBase *nurb = BKE_curve_nurbs_get(cu);
        int numVerts = 0;
        const int editmode = (!forRender && (cu->editnurb || cu->editfont));
        ModifierApplyFlag app_flag = 0;
-       float (*originalVerts)[3] = NULL;
        float (*deformedVerts)[3] = NULL;
        float *keyVerts = NULL;
        int required_mode;
@@ -818,8 +816,7 @@ static void curve_calc_modifiers_pre(Scene *scene, Object *ob, int forRender, in
                         * tilts, which is passed through in the modifier stack.
                         * this is also the reason curves do not use a virtual
                         * shape key modifier yet. */
-                       deformedVerts = BKE_curve_keyVertexCos_get(cu, nurb, keyVerts);
-                       originalVerts = MEM_dupallocN(deformedVerts);
+                       deformedVerts = BKE_curve_nurbs_keyVertexCos_get(nurb, keyVerts);
                        BLI_assert(BKE_nurbList_verts_count(nurb) == numVerts);
                }
        }
@@ -836,8 +833,7 @@ static void curve_calc_modifiers_pre(Scene *scene, Object *ob, int forRender, in
                                continue;
 
                        if (!deformedVerts) {
-                               deformedVerts = BKE_curve_vertexCos_get(cu, nurb, &numVerts);
-                               originalVerts = MEM_dupallocN(deformedVerts);
+                               deformedVerts = BKE_curve_nurbs_vertexCos_get(nurb, &numVerts);
                        }
 
                        mti->deformVerts(md, ob, NULL, deformedVerts, numVerts, app_flag);
@@ -847,17 +843,15 @@ static void curve_calc_modifiers_pre(Scene *scene, Object *ob, int forRender, in
                }
        }
 
-       if (deformedVerts)
-               BK_curve_vertexCos_apply(cu, nurb, deformedVerts);
+       if (deformedVerts) {
+               BK_curve_nurbs_vertexCos_apply(nurb, deformedVerts);
+               MEM_freeN(deformedVerts);
+       }
        if (keyVerts) /* these are not passed through modifier stack */
-               BKE_curve_keyVertexTilts_apply(cu, nurb, keyVerts);
+               BKE_curve_nurbs_keyVertexTilts_apply(nurb, keyVerts);
 
        if (keyVerts)
                MEM_freeN(keyVerts);
-
-       *originalVerts_r = originalVerts;
-       *deformedVerts_r = deformedVerts;
-       *numVerts_r = numVerts;
 }
 
 static float (*displist_get_allverts(ListBase *dispbase, int *totvert))[3]
@@ -894,14 +888,14 @@ static void displist_apply_allverts(ListBase *dispbase, float (*allverts)[3])
        }
 }
 
-static void curve_calc_modifiers_post(Scene *scene, Object *ob, ListBase *dispbase, DerivedMesh **derivedFinal,
-                                      int forRender, int renderResolution,
-                                      float (*originalVerts)[3], float (*deformedVerts)[3])
+static void curve_calc_modifiers_post(Scene *scene, Object *ob, ListBase *nurb,
+                                      ListBase *dispbase, DerivedMesh **derivedFinal,
+                                      int forRender, int renderResolution)
 {
-       ModifierData *md = modifiers_getVirtualModifierList(ob);
+       VirtualModifierData virtualModifierData;
+       ModifierData *md = modifiers_getVirtualModifierList(ob, &virtualModifierData);
        ModifierData *pretessellatePoint;
        Curve *cu = ob->data;
-       ListBase *nurb = BKE_curve_nurbs_get(cu);
        int required_mode = 0, totvert = 0;
        int editmode = (!forRender && (cu->editnurb || cu->editfont));
        DerivedMesh *dm = NULL, *ndm;
@@ -1046,12 +1040,6 @@ static void curve_calc_modifiers_post(Scene *scene, Object *ob, ListBase *dispba
                }
                (*derivedFinal) = dm;
        }
-
-       if (deformedVerts) {
-               BK_curve_vertexCos_apply(ob->data, nurb, originalVerts);
-               MEM_freeN(originalVerts);
-               MEM_freeN(deformedVerts);
-       }
 }
 
 static void displist_surf_indices(DispList *dl)
@@ -1142,8 +1130,8 @@ static void curve_calc_orcodm(Scene *scene, Object *ob, DerivedMesh *derivedFina
        /* this function represents logic of mesh's orcodm calculation
         * for displist-based objects
         */
-
-       ModifierData *md = modifiers_getVirtualModifierList(ob);
+       VirtualModifierData virtualModifierData;
+       ModifierData *md = modifiers_getVirtualModifierList(ob, &virtualModifierData);
        ModifierData *pretessellatePoint;
        Curve *cu = ob->data;
        int required_mode;
@@ -1201,25 +1189,24 @@ static void curve_calc_orcodm(Scene *scene, Object *ob, DerivedMesh *derivedFina
 void BKE_displist_make_surf(Scene *scene, Object *ob, ListBase *dispbase,
                             DerivedMesh **derivedFinal, int forRender, int forOrco, int renderResolution)
 {
-       ListBase *nubase;
+       ListBase nubase = {NULL, NULL};
        Nurb *nu;
        Curve *cu = ob->data;
        DispList *dl;
        float *data;
        int len;
-       int numVerts;
-       float (*originalVerts)[3];
-       float (*deformedVerts)[3];
 
-       if (!forRender && cu->editnurb)
-               nubase = BKE_curve_editNurbs_get(cu);
-       else
-               nubase = &cu->nurb;
+       if (!forRender && cu->editnurb) {
+               BKE_nurbList_duplicate(&nubase, BKE_curve_editNurbs_get(cu));
+       }
+       else {
+               BKE_nurbList_duplicate(&nubase, &cu->nurb);
+       }
 
        if (!forOrco)
-               curve_calc_modifiers_pre(scene, ob, forRender, renderResolution, &originalVerts, &deformedVerts, &numVerts);
+               curve_calc_modifiers_pre(scene, ob, &nubase, forRender, renderResolution);
 
-       for (nu = nubase->first; nu; nu = nu->next) {
+       for (nu = nubase.first; nu; nu = nu->next) {
                if (forRender || nu->hide == 0) {
                        int resolu = nu->resolu, resolv = nu->resolv;
 
@@ -1282,20 +1269,23 @@ void BKE_displist_make_surf(Scene *scene, Object *ob, ListBase *dispbase,
                }
        }
 
-       /* make copy of 'undeformed" displist for texture space calculation
-        * actually, it's not totally undeformed -- pre-tessellation modifiers are
-        * already applied, thats how it worked for years, so keep for compatibility (sergey) */
-       BKE_displist_copy(&cu->disp, dispbase);
+       /* Calculate curve's boundig box from non-modified display list. */
+       /* TODO(sergey): not thread-safe. */
+       if (cu->bb == NULL) {
+               cu->bb = MEM_callocN(sizeof(BoundBox), "boundbox");
+       }
+       boundbox_dispbase(cu->bb, dispbase);
 
        if (!forRender) {
                BKE_curve_texspace_calc(cu);
        }
 
        if (!forOrco) {
-               curve_calc_modifiers_post(scene, ob, dispbase, derivedFinal,
-                                         forRender, renderResolution,
-                                         originalVerts, deformedVerts);
+               curve_calc_modifiers_post(scene, ob, &nubase, dispbase, derivedFinal,
+                                         forRender, renderResolution);
        }
+
+       BKE_nurbList_free(&nubase);
 }
 
 static void rotateBevelPiece(Curve *cu, BevPoint *bevp, BevPoint *nbevp, DispList *dlb, float bev_blend, float widfac, float fac, float **data_r)
@@ -1389,37 +1379,34 @@ static void do_makeDispListCurveTypes(Scene *scene, Object *ob, ListBase *dispba
        }
        else if (ELEM(ob->type, OB_CURVE, OB_FONT)) {
                ListBase dlbev;
-               ListBase *nubase;
-               float (*originalVerts)[3];
-               float (*deformedVerts)[3];
-               int numVerts;
+               ListBase nubase = {NULL, NULL};
 
-               nubase = BKE_curve_nurbs_get(cu);
+               BKE_nurbList_duplicate(&nubase, BKE_curve_nurbs_get(cu));
 
-               BLI_freelistN(&(cu->bev));
+               BLI_freelistN(&(ob->curve_cache->bev));
 
-               if (cu->path) free_path(cu->path);
-               cu->path = NULL;
+               if (ob->curve_cache->path) free_path(ob->curve_cache->path);
+               ob->curve_cache->path = NULL;
 
                if (ob->type == OB_FONT)
                        BKE_vfont_to_curve(G.main, scene, ob, 0);
 
                if (!forOrco)
-                       curve_calc_modifiers_pre(scene, ob, forRender, renderResolution, &originalVerts, &deformedVerts, &numVerts);
+                       curve_calc_modifiers_pre(scene, ob, &nubase, forRender, renderResolution);
 
-               BKE_curve_bevelList_make(ob);
+               BKE_curve_bevelList_make(ob, &nubase, forRender != FALSE);
 
                /* If curve has no bevel will return nothing */
                BKE_curve_bevel_make(scene, ob, &dlbev, forRender, renderResolution);
 
                /* no bevel or extrude, and no width correction? */
                if (!dlbev.first && cu->width == 1.0f) {
-                       curve_to_displist(cu, nubase, dispbase, forRender, renderResolution);
+                       curve_to_displist(cu, &nubase, dispbase, forRender, renderResolution);
                }
                else {
                        float widfac = cu->width - 1.0f;
-                       BevList *bl = cu->bev.first;
-                       Nurb *nu = nubase->first;
+                       BevList *bl = ob->curve_cache->bev.first;
+                       Nurb *nu = nubase.first;
 
                        for (; bl && nu; bl = bl->next, nu = nu->next) {
                                DispList *dl;
@@ -1586,33 +1573,37 @@ static void do_makeDispListCurveTypes(Scene *scene, Object *ob, ListBase *dispba
                }
 
                if (!(cu->flag & CU_DEFORM_FILL)) {
-                       curve_to_filledpoly(cu, nubase, dispbase);
+                       curve_to_filledpoly(cu, &nubase, dispbase);
                }
 
                if ((cu->flag & CU_PATH) && !forOrco)
-                       calc_curvepath(ob);
+                       calc_curvepath(ob, &nubase);
+
+               /* Calculate curve's boundig box from non-modified display list. */
+               /* TODO(sergey): not thread-safe. */
+               if (cu->bb == NULL) {
+                       cu->bb = MEM_callocN(sizeof(BoundBox), "boundbox");
+               }
 
-               /* make copy of 'undeformed" displist for texture space calculation
-                * actually, it's not totally undeformed -- pre-tessellation modifiers are
-                * already applied, thats how it worked for years, so keep for compatibility (sergey) */
-               BKE_displist_copy(&cu->disp, dispbase);
+               boundbox_dispbase(cu->bb, dispbase);
 
                if (!forRender) {
                        BKE_curve_texspace_calc(cu);
                }
 
                if (!forOrco)
-                       curve_calc_modifiers_post(scene, ob, dispbase, derivedFinal, forRender, renderResolution, originalVerts, deformedVerts);
+                       curve_calc_modifiers_post(scene, ob, &nubase, dispbase, derivedFinal, forRender, renderResolution);
 
                if (cu->flag & CU_DEFORM_FILL && !ob->derivedFinal) {
-                       curve_to_filledpoly(cu, nubase, dispbase);
+                       curve_to_filledpoly(cu, &nubase, dispbase);
                }
+
+               BKE_nurbList_free(&nubase);
        }
 }
 
 void BKE_displist_make_curveTypes(Scene *scene, Object *ob, int forOrco)
 {
-       Curve *cu = ob->data;
        ListBase *dispbase;
 
        /* The same check for duplis as in do_makeDispListCurveTypes.
@@ -1621,27 +1612,18 @@ void BKE_displist_make_curveTypes(Scene *scene, Object *ob, int forOrco)
        if (!ELEM3(ob->type, OB_SURF, OB_CURVE, OB_FONT))
                return;
 
-       BKE_displist_free(&(ob->disp));
-       dispbase = &(ob->disp);
-       BKE_displist_free(dispbase);
+       if (ob->curve_cache) {
+               BKE_displist_free(&(ob->curve_cache->disp));
+       }
+       else {
+               ob->curve_cache = MEM_callocN(sizeof(CurveCache), "CurveCache for curve types");
+       }
 
-       /* free displist used for textspace */
-       BKE_displist_free(&cu->disp);
+       dispbase = &(ob->curve_cache->disp);
 
        do_makeDispListCurveTypes(scene, ob, dispbase, &ob->derivedFinal, 0, forOrco, 0);
 
-       if (ob->derivedFinal) {
-               DM_set_object_boundbox(ob, ob->derivedFinal);
-
-               /* always keep curve's  BB in sync with non-deformed displist */
-               if (cu->bb == NULL)
-                       cu->bb = MEM_callocN(sizeof(BoundBox), "boundbox");
-
-               boundbox_dispbase(cu->bb, &cu->disp);
-       }
-       else {
-               boundbox_displist(ob);
-       }
+       boundbox_displist_object(ob);
 }
 
 void BKE_displist_make_curveTypes_forRender(Scene *scene, Object *ob, ListBase *dispbase,
@@ -1705,21 +1687,22 @@ static void boundbox_dispbase(BoundBox *bb, ListBase *dispbase)
 }
 
 /* this is confusing, there's also min_max_object, appplying the obmat... */
-static void boundbox_displist(Object *ob)
+static void boundbox_displist_object(Object *ob)
 {
        if (ELEM3(ob->type, OB_CURVE, OB_SURF, OB_FONT)) {
-               Curve *cu = ob->data;
-
-               /* calculate curve's BB based on non-deformed displist */
-               if (cu->bb == NULL)
-                       cu->bb = MEM_callocN(sizeof(BoundBox), "boundbox");
-
-               boundbox_dispbase(cu->bb, &cu->disp);
+               /* Curver's BB is already calculated as a part of modifier stack,
+                * here we only calculate object BB based on final display list.
+                */
 
                /* object's BB is calculated from final displist */
                if (ob->bb == NULL)
                        ob->bb = MEM_callocN(sizeof(BoundBox), "boundbox");
 
-               boundbox_dispbase(ob->bb, &ob->disp);
+               if (ob->derivedFinal) {
+                       DM_set_object_boundbox(ob, ob->derivedFinal);
+               }
+               else {
+                       boundbox_dispbase(ob->bb, &ob->curve_cache->disp);
+               }
        }
 }
index 02d1621e408b0fe547fe9de1e6c178e9fee99bb7..8d58caf8769134005970a343853e59767d47c1c0 100644 (file)
@@ -67,6 +67,7 @@
 #include "BKE_blender.h"
 #include "BKE_collision.h"
 #include "BKE_constraint.h"
+#include "BKE_curve.h"
 #include "BKE_deform.h"
 #include "BKE_depsgraph.h"
 #include "BKE_displist.h"
@@ -176,10 +177,10 @@ static void precalculate_effector(EffectorCache *eff)
        if (eff->pd->forcefield == PFIELD_GUIDE && eff->ob->type==OB_CURVE) {
                Curve *cu= eff->ob->data;
                if (cu->flag & CU_PATH) {
-                       if (cu->path==NULL || cu->path->data==NULL)
+                       if (eff->ob->curve_cache == NULL || eff->ob->curve_cache->path==NULL || eff->ob->curve_cache->path->data==NULL)
                                BKE_displist_make_curveTypes(eff->scene, eff->ob, 0);
 
-                       if (cu->path && cu->path->data) {
+                       if (eff->ob->curve_cache->path && eff->ob->curve_cache->path->data) {
                                where_on_path(eff->ob, 0.0, eff->guide_loc, eff->guide_dir, NULL, &eff->guide_radius, NULL);
                                mul_m4_v3(eff->ob->obmat, eff->guide_loc);
                                mul_mat3_m4_v3(eff->ob->obmat, eff->guide_dir);
index b3edeb67928355faa610ad118e8bb3c0598243d3..60c00f821135f9ff41f3d8e6069a74fff7f622c2 100644 (file)
@@ -819,8 +819,10 @@ makebreak:
                
                cucu->flag |= (CU_PATH + CU_FOLLOW);
                
-               if (cucu->path == NULL) BKE_displist_make_curveTypes(scene, cu->textoncurve, 0);
-               if (cucu->path) {
+               if (cu->textoncurve->curve_cache == NULL || cu->textoncurve->curve_cache->path == NULL) {
+                       BKE_displist_make_curveTypes(scene, cu->textoncurve, 0);
+               }
+               if (cu->textoncurve->curve_cache->path) {
                        float distfac, imat[4][4], imat3[3][3], cmat[3][3];
                        float minx, maxx, miny, maxy;
                        float timeofs, sizefac;
@@ -845,7 +847,7 @@ makebreak:
                        /* we put the x-coordinaat exact at the curve, the y is rotated */
                        
                        /* length correction */
-                       distfac = sizefac * cucu->path->totdist / (maxx - minx);
+                       distfac = sizefac * cu->textoncurve->curve_cache->path->totdist / (maxx - minx);
                        timeofs = 0.0f;
                        
                        if (distfac > 1.0f) {
index c9b904e76ac3bb47e7704bc64020e61826d71512..30b2970bb2e2ca78e2586a9421fcfa7421e82ab2 100644 (file)
@@ -51,6 +51,7 @@
 #include "BKE_animsys.h"
 #include "BKE_anim.h"
 #include "BKE_cdderivedmesh.h"
+#include "BKE_curve.h"
 #include "BKE_displist.h"
 #include "BKE_global.h"
 #include "BKE_key.h"
@@ -164,7 +165,7 @@ void BKE_lattice_resize(Lattice *lt, int uNew, int vNew, int wNew, Object *ltOb)
                lt->typeu = lt->typev = lt->typew = KEY_LINEAR;
 
                /* prevent using deformed locations */
-               BKE_displist_free(&ltOb->disp);
+               BKE_displist_free(&ltOb->curve_cache->disp);
 
                copy_m4_m4(mat, ltOb->obmat);
                unit_m4(ltOb->obmat);
@@ -311,7 +312,7 @@ void init_latt_deform(Object *oblatt, Object *ob)
        /* we make an array with all differences */
        Lattice *lt = oblatt->data;
        BPoint *bp;
-       DispList *dl = BKE_displist_find(&oblatt->disp, DL_VERTS);
+       DispList *dl = oblatt->curve_cache ? BKE_displist_find(&oblatt->curve_cache->disp, DL_VERTS) : NULL;
        float *co = dl ? dl->verts : NULL;
        float *fp, imat[4][4];
        float fu, fv, fw;
@@ -506,13 +507,12 @@ static void init_curve_deform(Object *par, Object *ob, CurveDeform *cd)
  */
 static int where_on_path_deform(Object *ob, float ctime, float vec[4], float dir[3], float quat[4], float *radius)
 {
-       Curve *cu = ob->data;
        BevList *bl;
        float ctime1;
        int cycl = 0;
        
        /* test for cyclic */
-       bl = cu->bev.first;
+       bl = ob->curve_cache->bev.first;
        if (!bl->nr) return 0;
        if (bl->poly > -1) cycl = 1;
 
@@ -527,7 +527,7 @@ static int where_on_path_deform(Object *ob, float ctime, float vec[4], float dir
        if (where_on_path(ob, ctime1, vec, dir, quat, radius, NULL)) {
                
                if (cycl == 0) {
-                       Path *path = cu->path;
+                       Path *path = ob->curve_cache->path;
                        float dvec[3];
                        
                        if (ctime < 0.0f) {
@@ -565,9 +565,9 @@ static int calc_curve_deform(Scene *scene, Object *par, float co[3],
        const int is_neg_axis = (axis > 2);
 
        /* to be sure, mostly after file load */
-       if (cu->path == NULL) {
+       if (ELEM(NULL, par->curve_cache, par->curve_cache->path)) {
                BKE_displist_make_curveTypes(scene, par, 0);
-               if (cu->path == NULL) return 0;  // happens on append...
+               if (par->curve_cache->path == NULL) return 0;  // happens on append...
        }
        
        /* options */
@@ -576,14 +576,14 @@ static int calc_curve_deform(Scene *scene, Object *par, float co[3],
                if (cu->flag & CU_STRETCH)
                        fac = (-co[index] - cd->dmax[index]) / (cd->dmax[index] - cd->dmin[index]);
                else
-                       fac = -(co[index] - cd->dmax[index]) / (cu->path->totdist);
+                       fac = -(co[index] - cd->dmax[index]) / (par->curve_cache->path->totdist);
        }
        else {
                index = axis;
                if (cu->flag & CU_STRETCH)
                        fac = (co[index] - cd->dmin[index]) / (cd->dmax[index] - cd->dmin[index]);
                else
-                       fac = +(co[index] - cd->dmin[index]) / (cu->path->totdist);
+                       fac = +(co[index] - cd->dmin[index]) / (par->curve_cache->path->totdist);
        }
        
        if (where_on_path_deform(par, fac, loc, dir, new_quat, &radius)) {  /* returns OK */
@@ -991,11 +991,17 @@ void BKE_lattice_vertexcos_apply(struct Object *ob, float (*vertexCos)[3])
 void BKE_lattice_modifiers_calc(Scene *scene, Object *ob)
 {
        Lattice *lt = ob->data;
-       ModifierData *md = modifiers_getVirtualModifierList(ob);
+       VirtualModifierData virtualModifierData;
+       ModifierData *md = modifiers_getVirtualModifierList(ob, &virtualModifierData);
        float (*vertexCos)[3] = NULL;
        int numVerts, editmode = (lt->editlatt != NULL);
 
-       BKE_displist_free(&ob->disp);
+       if (ob->curve_cache) {
+               BKE_displist_free(&ob->curve_cache->disp);
+       }
+       else {
+               ob->curve_cache = MEM_callocN(sizeof(CurveCache), "CurveCache for lattice");
+       }
 
        for (; md; md = md->next) {
                ModifierTypeInfo *mti = modifierType_getInfo(md->type);
@@ -1021,7 +1027,7 @@ void BKE_lattice_modifiers_calc(Scene *scene, Object *ob)
                dl->nr = numVerts;
                dl->verts = (float *) vertexCos;
                
-               BLI_addtail(&ob->disp, dl);
+               BLI_addtail(&ob->curve_cache->disp, dl);
        }
 }
 
index c8cd65e94773948018984168642b4faecab4da12..017158a9a010583cd64fa7cad209c583a48d6111 100644 (file)
@@ -1275,7 +1275,9 @@ int object_remove_material_slot(Object *ob)
        /* check indices from mesh */
        if (ELEM4(ob->type, OB_MESH, OB_CURVE, OB_SURF, OB_FONT)) {
                data_delete_material_index_id((ID *)ob->data, actcol - 1);
-               BKE_displist_free(&ob->disp);
+               if (ob->curve_cache) {
+                       BKE_displist_free(&ob->curve_cache->disp);
+               }
        }
 
        return TRUE;
index 55b1a65a73e6e3cb583704b8eff7bd6b046446de..e10dbe7f41b6595e8bace2cf74a745575535490b 100644 (file)
@@ -56,6 +56,7 @@
 
 /*  #include "BKE_object.h" */
 #include "BKE_animsys.h"
+#include "BKE_curve.h"
 #include "BKE_scene.h"
 #include "BKE_library.h"
 #include "BKE_displist.h"
@@ -366,7 +367,7 @@ void BKE_mball_texspace_calc(Object *ob)
        (min)[0] = (min)[1] = (min)[2] = 1.0e30f;
        (max)[0] = (max)[1] = (max)[2] = -1.0e30f;
 
-       dl = ob->disp.first;
+       dl = ob->curve_cache->disp.first;
        while (dl) {
                tot = dl->nr;
                if (tot) do_it = TRUE;
@@ -2273,7 +2274,7 @@ static void mball_count(PROCESS *process, Scene *scene, Object *basis)
        }
 }
 
-void BKE_mball_polygonize(Scene *scene, Object *ob, ListBase *dispbase)
+void BKE_mball_polygonize(Scene *scene, Object *ob, ListBase *dispbase, bool for_render)
 {
        MetaBall *mb;
        DispList *dl;
@@ -2286,7 +2287,7 @@ void BKE_mball_polygonize(Scene *scene, Object *ob, ListBase *dispbase)
        mball_count(&process, scene, ob);
 
        if (process.totelem == 0) return;
-       if ((G.is_rendering == FALSE) && (mb->flag == MB_UPDATE_NEVER)) return;
+       if ((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;
@@ -2324,7 +2325,7 @@ void BKE_mball_polygonize(Scene *scene, Object *ob, ListBase *dispbase)
        }
 
        /* width is size per polygonize cube */
-       if (G.is_rendering) {
+       if (for_render) {
                width = mb->rendersize;
        }
        else {
index b40c3475df523e3f2488ac04b93e4072578586d4..ca0688887441c7f8b108e6a33fae619e0913bc24 100644 (file)
@@ -1293,7 +1293,13 @@ int BKE_mesh_nurbs_to_mdata(Object *ob, MVert **allvert, int *totvert,
                             MEdge **alledge, int *totedge, MLoop **allloop, MPoly **allpoly,
                             int *totloop, int *totpoly)
 {
-       return BKE_mesh_nurbs_displist_to_mdata(ob, &ob->disp,
+       ListBase disp = {NULL, NULL};
+
+       if (ob->curve_cache) {
+               disp = ob->curve_cache->disp;
+       }
+
+       return BKE_mesh_nurbs_displist_to_mdata(ob, &disp,
                                                allvert, totvert,
                                                alledge, totedge,
                                                allloop, allpoly, NULL,
@@ -1639,8 +1645,13 @@ void BKE_mesh_from_nurbs(Object *ob)
 {
        Curve *cu = (Curve *) ob->data;
        bool use_orco_uv = (cu->flag & CU_UV_ORCO) != 0;
+       ListBase disp = {NULL, NULL};
+
+       if (ob->curve_cache) {
+               disp = ob->curve_cache->disp;
+       }
 
-       BKE_mesh_from_nurbs_displist(ob, &ob->disp, use_orco_uv);
+       BKE_mesh_from_nurbs_displist(ob, &disp, use_orco_uv);
 }
 
 typedef struct EdgeLink {
index 41e0acf9f7a3bf2290b815d624edb597a32b11fa..780bd9733f5f7a708391d91869335622d07da1fc 100644 (file)
 
 #include "MOD_modifiertypes.h"
 
-ModifierTypeInfo *modifierType_getInfo(ModifierType type)
+static ModifierTypeInfo *modifier_types[NUM_MODIFIER_TYPES] = {NULL};
+static VirtualModifierData virtualModifierCommonData;
+
+void BKE_modifier_init(void)
 {
-       static ModifierTypeInfo *types[NUM_MODIFIER_TYPES] = {NULL};
-       static int types_init = 1;
+       ModifierData *md;
 
-       if (types_init) {
-               modifier_type_init(types); /* MOD_utils.c */
-               types_init = 0;
-       }
+       /* Initialize modifier types */
+       modifier_type_init(modifier_types); /* MOD_utils.c */
+
+       /* Initialize global cmmon storage used for virtual modifier list */
+       md = modifier_new(eModifierType_Armature);
+       virtualModifierCommonData.amd = *((ArmatureModifierData *) md);
+       modifier_free(md);
+
+       md = modifier_new(eModifierType_Curve);
+       virtualModifierCommonData.cmd = *((CurveModifierData *) md);
+       modifier_free(md);
 
+       md = modifier_new(eModifierType_Lattice);
+       virtualModifierCommonData.lmd = *((LatticeModifierData *) md);
+       modifier_free(md);
+
+       md = modifier_new(eModifierType_ShapeKey);
+       virtualModifierCommonData.smd = *((ShapeKeyModifierData *) md);
+       modifier_free(md);
+
+       virtualModifierCommonData.amd.modifier.mode |= eModifierMode_Virtual;
+       virtualModifierCommonData.cmd.modifier.mode |= eModifierMode_Virtual;
+       virtualModifierCommonData.lmd.modifier.mode |= eModifierMode_Virtual;
+       virtualModifierCommonData.smd.modifier.mode |= eModifierMode_Virtual;
+}
+
+ModifierTypeInfo *modifierType_getInfo(ModifierType type)
+{
        /* type unsigned, no need to check < 0 */
-       if (type < NUM_MODIFIER_TYPES && types[type]->name[0] != '\0') {
-               return types[type];
+       if (type < NUM_MODIFIER_TYPES && modifier_types[type]->name[0] != '\0') {
+               return modifier_types[type];
        }
        else {
                return NULL;
@@ -289,7 +314,8 @@ void modifier_setError(ModifierData *md, const char *_format, ...)
  */
 int modifiers_getCageIndex(struct Scene *scene, Object *ob, int *lastPossibleCageIndex_r, int virtual_)
 {
-       ModifierData *md = (virtual_) ? modifiers_getVirtualModifierList(ob) : ob->modifiers.first;
+       VirtualModifierData virtualModifierData;
+       ModifierData *md = (virtual_) ? modifiers_getVirtualModifierList(ob, &virtualModifierData) : ob->modifiers.first;
        int i, cageIndex = -1;
 
        if (lastPossibleCageIndex_r) {
@@ -435,74 +461,43 @@ ModifierData *modifiers_getLastPreview(struct Scene *scene, ModifierData *md, in
 /* NOTE: This is to support old files from before Blender supported modifiers,
  * in some cases versioning code updates these so for new files this will
  * return an empty list. */
-ModifierData *modifiers_getVirtualModifierList(Object *ob)
+ModifierData *modifiers_getVirtualModifierList(Object *ob, VirtualModifierData *virtualModifierData)
 {
-       /* Kinda hacky, but should be fine since we are never
-        * re-entrant and avoid free hassles.
-        */
-       static ArmatureModifierData amd;
-       static CurveModifierData cmd;
-       static LatticeModifierData lmd;
-       static ShapeKeyModifierData smd;
-       static int init = 1;
        ModifierData *md;
 
-       if (init) {
-               md = modifier_new(eModifierType_Armature);
-               amd = *((ArmatureModifierData *) md);
-               modifier_free(md);
-
-               md = modifier_new(eModifierType_Curve);
-               cmd = *((CurveModifierData *) md);
-               modifier_free(md);
-
-               md = modifier_new(eModifierType_Lattice);
-               lmd = *((LatticeModifierData *) md);
-               modifier_free(md);
-
-               md = modifier_new(eModifierType_ShapeKey);
-               smd = *((ShapeKeyModifierData *) md);
-               modifier_free(md);
-
-               amd.modifier.mode |= eModifierMode_Virtual;
-               cmd.modifier.mode |= eModifierMode_Virtual;
-               lmd.modifier.mode |= eModifierMode_Virtual;
-               smd.modifier.mode |= eModifierMode_Virtual;
-
-               init = 0;
-       }
-
        md = ob->modifiers.first;
 
+       *virtualModifierData = virtualModifierCommonData;
+
        if (ob->parent) {
                if (ob->parent->type == OB_ARMATURE && ob->partype == PARSKEL) {
-                       amd.object = ob->parent;
-                       amd.modifier.next = md;
-                       amd.deformflag = ((bArmature *)(ob->parent->data))->deformflag;
-                       md = &amd.modifier;
+                       virtualModifierData->amd.object = ob->parent;
+                       virtualModifierData->amd.modifier.next = md;
+                       virtualModifierData->amd.deformflag = ((bArmature *)(ob->parent->data))->deformflag;
+                       md = &virtualModifierData->amd.modifier;
                }
                else if (ob->parent->type == OB_CURVE && ob->partype == PARSKEL) {
-                       cmd.object = ob->parent;
-                       cmd.defaxis = ob->trackflag + 1;
-                       cmd.modifier.next = md;
-                       md = &cmd.modifier;
+                       virtualModifierData->cmd.object = ob->parent;
+                       virtualModifierData->cmd.defaxis = ob->trackflag + 1;
+                       virtualModifierData->cmd.modifier.next = md;
+                       md = &virtualModifierData->cmd.modifier;
                }
                else if (ob->parent->type == OB_LATTICE && ob->partype == PARSKEL) {
-                       lmd.object = ob->parent;
-                       lmd.modifier.next = md;
-                       md = &lmd.modifier;
+                       virtualModifierData->lmd.object = ob->parent;
+                       virtualModifierData->lmd.modifier.next = md;
+                       md = &virtualModifierData->lmd.modifier;
                }
        }
 
        /* shape key modifier, not yet for curves */
        if (ELEM(ob->type, OB_MESH, OB_LATTICE) && BKE_key_from_object(ob)) {
                if (ob->type == OB_MESH && (ob->shapeflag & OB_SHAPE_EDIT_MODE))
-                       smd.modifier.mode |= eModifierMode_Editmode | eModifierMode_OnCage;
+                       virtualModifierData->smd.modifier.mode |= eModifierMode_Editmode | eModifierMode_OnCage;
                else
-                       smd.modifier.mode &= ~eModifierMode_Editmode | eModifierMode_OnCage;
+                       virtualModifierData->smd.modifier.mode &= ~eModifierMode_Editmode | eModifierMode_OnCage;
 
-               smd.modifier.next = md;
-               md = &smd.modifier;
+               virtualModifierData->smd.modifier.next = md;
+               md = &virtualModifierData->smd.modifier;
        }
 
        return md;
@@ -513,7 +508,8 @@ ModifierData *modifiers_getVirtualModifierList(Object *ob)
  */
 Object *modifiers_isDeformedByArmature(Object *ob)
 {
-       ModifierData *md = modifiers_getVirtualModifierList(ob);
+       VirtualModifierData virtualModifierData;
+       ModifierData *md = modifiers_getVirtualModifierList(ob, &virtualModifierData);
        ArmatureModifierData *amd = NULL;
        
        /* return the first selected armature, this lets us use multiple armatures */
@@ -536,7 +532,8 @@ Object *modifiers_isDeformedByArmature(Object *ob)
  */
 Object *modifiers_isDeformedByLattice(Object *ob)
 {
-       ModifierData *md = modifiers_getVirtualModifierList(ob);
+       VirtualModifierData virtualModifierData;
+       ModifierData *md = modifiers_getVirtualModifierList(ob, &virtualModifierData);
        LatticeModifierData *lmd = NULL;
        
        /* return the first selected lattice, this lets us use multiple lattices */
@@ -559,7 +556,8 @@ Object *modifiers_isDeformedByLattice(Object *ob)
  */
 Object *modifiers_isDeformedByCurve(Object *ob)
 {
-       ModifierData *md = modifiers_getVirtualModifierList(ob);
+       VirtualModifierData virtualModifierData;
+       ModifierData *md = modifiers_getVirtualModifierList(ob, &virtualModifierData);
        CurveModifierData *cmd = NULL;
        
        /* return the first selected curve, this lets us use multiple curves */
@@ -579,7 +577,8 @@ Object *modifiers_isDeformedByCurve(Object *ob)
 
 bool modifiers_usesArmature(Object *ob, bArmature *arm)
 {
-       ModifierData *md = modifiers_getVirtualModifierList(ob);
+       VirtualModifierData virtualModifierData;
+       ModifierData *md = modifiers_getVirtualModifierList(ob, &virtualModifierData);
 
        for (; md; md = md->next) {
                if (md->type == eModifierType_Armature) {
@@ -604,7 +603,8 @@ bool modifier_isCorrectableDeformed(ModifierData *md)
 
 bool modifiers_isCorrectableDeformed(Object *ob)
 {
-       ModifierData *md = modifiers_getVirtualModifierList(ob);
+       VirtualModifierData virtualModifierData;
+       ModifierData *md = modifiers_getVirtualModifierList(ob, &virtualModifierData);
        
        for (; md; md = md->next) {
                if (ob->mode == OB_MODE_EDIT && (md->mode & eModifierMode_Editmode) == 0) {
index f1183868e8b3b28e06594fda4dff0c6594d76e8d..77e9839293a8bb23111718b1769021a5999353fe 100644 (file)
@@ -170,6 +170,19 @@ void BKE_object_free_bulletsoftbody(Object *ob)
        }
 }
 
+void BKE_object_free_curve_cache(Object *ob)
+{
+       if (ob->curve_cache) {
+               BKE_displist_free(&ob->curve_cache->disp);
+               BLI_freelistN(&ob->curve_cache->bev);
+               if (ob->curve_cache->path) {
+                       free_path(ob->curve_cache->path);
+               }
+               MEM_freeN(ob->curve_cache);
+               ob->curve_cache = NULL;
+       }
+}
+
 void BKE_object_free_modifiers(Object *ob)
 {
        while (ob->modifiers.first) {
@@ -270,7 +283,9 @@ void BKE_object_free_derived_caches(Object *ob)
                ob->derivedDeform = NULL;
        }
        
-       BKE_displist_free(&ob->disp);
+       if (ob->curve_cache) {
+               BKE_displist_free(&ob->curve_cache->disp);
+       }
 }
 
 /* do not free object itself */
@@ -340,6 +355,14 @@ void BKE_object_free(Object *ob)
        free_sculptsession(ob);
 
        if (ob->pc_ids.first) BLI_freelistN(&ob->pc_ids);
+
+       /* Free runtime curves data. */
+       if (ob->curve_cache) {
+               BLI_freelistN(&ob->curve_cache->bev);
+               if (ob->curve_cache->path)
+                       free_path(ob->curve_cache->path);
+               MEM_freeN(ob->curve_cache);
+       }
 }
 
 static void unlink_object__unlinkModifierLinks(void *userData, Object *ob, Object **obpoin)
@@ -1250,8 +1273,6 @@ Object *BKE_object_copy_ex(Main *bmain, Object *ob, int copy_caches)
 
        for (a = 0; a < obn->totcol; a++) id_us_plus((ID *)obn->mat[a]);
        
-       obn->disp.first = obn->disp.last = NULL;
-       
        if (ob->pd) {
                obn->pd = MEM_dupallocN(ob->pd);
                if (obn->pd->tex)
@@ -1273,7 +1294,10 @@ Object *BKE_object_copy_ex(Main *bmain, Object *ob, int copy_caches)
        obn->pc_ids.first = obn->pc_ids.last = NULL;
 
        obn->mpath = NULL;
-       
+
+       /* Copy runtime surve data. */
+       obn->curve_cache = NULL;
+
        return obn;
 }
 
@@ -1751,9 +1775,9 @@ static void ob_parcurve(Scene *scene, Object *ob, Object *par, float mat[4][4])
        unit_m4(mat);
        
        cu = par->data;
-       if (cu->path == NULL || cu->path->data == NULL) /* only happens on reload file, but violates depsgraph still... fix! */
+       if (ELEM3(NULL, par->curve_cache, par->curve_cache->path, par->curve_cache->path->data)) /* only happens on reload file, but violates depsgraph still... fix! */
                BKE_displist_make_curveTypes(scene, par, 0);
-       if (cu->path == NULL) return;
+       if (par->curve_cache->path == NULL) return;
        
        /* catch exceptions: feature for nla stride editing */
        if (ob->ipoflag & OB_DISABLE_PATH) {
@@ -1784,7 +1808,7 @@ static void ob_parcurve(Scene *scene, Object *ob, Object *par, float mat[4][4])
        
        /* time calculus is correct, now apply distance offset */
        if (cu->flag & CU_OFFS_PATHDIST) {
-               ctime += timeoffs / cu->path->totdist;
+               ctime += timeoffs / par->curve_cache->path->totdist;
 
                /* restore */
                SWAP(float, sf_orig, ob->sf);
@@ -1941,7 +1965,7 @@ static void give_parvert(Object *par, int nr, float vec[3])
        }
        else if (par->type == OB_LATTICE) {
                Lattice *latt  = par->data;
-               DispList *dl   = BKE_displist_find(&par->disp, DL_VERTS);
+               DispList *dl   = par->curve_cache ? BKE_displist_find(&par->curve_cache->disp, DL_VERTS) : NULL;
                float (*co)[3] = dl ? (float (*)[3])dl->verts : NULL;
                int tot;
 
@@ -2494,10 +2518,10 @@ void BKE_object_foreach_display_point(
                        func_cb(co, user_data);
                }
        }
-       else if (ob->disp.first) {
+       else if (ob->curve_cache && ob->curve_cache->disp.first) {
                DispList *dl;
 
-               for (dl = ob->disp.first; dl; dl = dl->next) {
+               for (dl = ob->curve_cache->disp.first; dl; dl = dl->next) {
                        float *v3 = dl->verts;
                        int totvert = dl->nr;
                        int i;
@@ -3135,8 +3159,9 @@ int BKE_object_is_modified(Scene *scene, Object *ob)
        }
        else {
                ModifierData *md;
+               VirtualModifierData virtualModifierData;
                /* cloth */
-               for (md = modifiers_getVirtualModifierList(ob);
+               for (md = modifiers_getVirtualModifierList(ob, &virtualModifierData);
                     md && (flag != (eModifierMode_Render | eModifierMode_Realtime));
                     md = md->next)
                {
@@ -3157,10 +3182,11 @@ int BKE_object_is_modified(Scene *scene, Object *ob)
 int BKE_object_is_deform_modified(Scene *scene, Object *ob)
 {
        ModifierData *md;
+       VirtualModifierData virtualModifierData;
        int flag = 0;
 
        /* cloth */
-       for (md = modifiers_getVirtualModifierList(ob);
+       for (md = modifiers_getVirtualModifierList(ob, &virtualModifierData);
             md && (flag != (eModifierMode_Render | eModifierMode_Realtime));
             md = md->next)
        {
@@ -3182,8 +3208,9 @@ int BKE_object_is_deform_modified(Scene *scene, Object *ob)
 bool BKE_object_is_animated(Scene *scene, Object *ob)
 {
        ModifierData *md;
+       VirtualModifierData virtualModifierData;
 
-       for (md = modifiers_getVirtualModifierList(ob); md; md = md->next)
+       for (md = modifiers_getVirtualModifierList(ob, &virtualModifierData); md; md = md->next)
                if (modifier_dependsOnTime(md) &&
                    (modifier_isEnabled(scene, md, eModifierMode_Realtime) ||
                     modifier_isEnabled(scene, md, eModifierMode_Render)))
index bfec38419f18657f9c2e7f2678276df1cad9c76d..0294ff5645712f6d6c017a4f86e92819092a0d44 100644 (file)
@@ -73,6 +73,7 @@ bool *BKE_objdef_validmap_get(Object *ob, const int defbase_tot)
        GHash *gh;
        int i, step1 = 1;
        //int defbase_tot = BLI_countlist(&ob->defbase);
+       VirtualModifierData virtualModifierData;
 
        if (ob->defbase.first == NULL) {
                return NULL;
@@ -88,7 +89,7 @@ bool *BKE_objdef_validmap_get(Object *ob, const int defbase_tot)
        BLI_assert(BLI_ghash_size(gh) == defbase_tot);
 
        /* now loop through the armature modifiers and identify deform bones */
-       for (md = ob->modifiers.first; md; md = !md->next && step1 ? (step1 = 0), modifiers_getVirtualModifierList(ob) : md->next) {
+       for (md = ob->modifiers.first; md; md = !md->next && step1 ? (step1 = 0), modifiers_getVirtualModifierList(ob, &virtualModifierData) : md->next) {
                if (!(md->mode & (eModifierMode_Realtime | eModifierMode_Virtual)))
                        continue;
 
index 744a8247233ce316d4d94f8101da4c744d787886..0735ff63606c5c5a21db2207caf9b7b26dcc3dce 100644 (file)
@@ -57,6 +57,7 @@
 #include "BLI_callbacks.h"
 #include "BLI_string.h"
 #include "BLI_threads.h"
+#include "BLI_task.h"
 
 #include "BLF_translation.h"
 
@@ -1162,32 +1163,235 @@ 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)
+typedef struct ThreadedObjectUpdateState {
+       Scene *scene;
+       Scene *scene_parent;
+       SpinLock lock;
+} ThreadedObjectUpdateState;
+
+static void scene_update_object_add_task(void *node, void *user_data);
+
+static void scene_update_all_bases(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(scene_parent, object, scene->rigidbody_world);
+
+               if (object->dup_group && (object->transflag & OB_DUPLIGROUP))
+                       BKE_group_handle_recalc_and_update(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)
+{
+#define PRINT if (G.debug & G_DEBUG) printf
+
+       ThreadedObjectUpdateState *state = (ThreadedObjectUpdateState *) BLI_task_pool_userdata(pool);
+       void *node = taskdata;
+       Object *object = DAG_threaded_update_get_node_object(node);
+       Scene *scene = state->scene;
+       Scene *scene_parent = state->scene_parent;
+
+       if (object) {
+               PRINT("Thread %d: update object %s\n", threadid, object->id.name);
+
+               /* 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(scene_parent, object, scene->rigidbody_world);
+       }
+       else {
+               PRINT("Threda %d: update node %s\n", threadid,
+                       DAG_threaded_update_get_node_name(node));
+       }
+
+       BLI_spin_lock(&state->lock);
+       /* 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);
+       BLI_spin_unlock(&state->lock);
+
+#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 scene_update_objects_threaded(Scene *scene, Scene *scene_parent)
+{
+       TaskScheduler *task_scheduler;
+       TaskPool *task_pool;
+       ThreadedObjectUpdateState state;
+       int tot_thread = BLI_system_thread_count();
+
+       if (tot_thread == 1) {
+               /* If only one thread is possible we don't bother self with
+                * task pool, which would be an overhead in cas e of single
+                * CPU core.
+                */
+               scene_update_all_bases(scene, scene_parent);
+               return;
+       }
+
+       /* Ensure malloc will go go fine from threads,
+        * this is needed because we could be in main thread here
+        * and malloc could be non-threda safe at this point because
+        * no other jobs are running.
+        */
+       BLI_begin_threaded_malloc();
+
+       /* XXX: Releasing DrawObject is not thread safe, but adding lock
+        *      around it is gonna to harm even more. So for now let's
+        *      free all caches from main thread.
+        *
+        * TODO(sergey): Making DrawObject thread-safe is a nice task on
+        *               it's own and it'll also make it possible to remove
+        *               this hack.
+        */
+       {
+               Base *base;
+               for (base = scene->base.first; base; base = base->next) {
+                       Object *ob = base->object;
+
+                       if (ob->recalc & OB_RECALC_ALL) {
+                               BKE_object_free_derived_caches(ob);
+
+                               if (ob->dup_group && (ob->transflag & OB_DUPLIGROUP)) {
+                                       GroupObject *go;
+                                       for (go = ob->dup_group->gobject.first; go; go = go->next) {
+                                               if (go->ob && go->ob->recalc) {
+                                                       BKE_object_free_derived_caches(go->ob);
+                                               }
+                                       }
+                               }
+                       }
+               }
+       }
+
+       state.scene = scene;
+       state.scene_parent = scene_parent;
+       BLI_spin_init(&state.lock);
+
+       task_scheduler = BLI_task_scheduler_create(tot_thread);
+       task_pool = BLI_task_pool_create(task_scheduler, &state);
+
+       /* Initialize run-time data in the graph needed for traversing it
+        * from multiple threads.
+        *
+        * This will mark DAG nodes as object/non-object and will calculate
+        * "valency" of nodes (which is how many non-updated parents node
+        * have, which helps a lot checking whether node could be scheduled
+        * already or not).
+        */
+       DAG_threaded_update_begin(scene);
+
+       /* Put all nodes which are already ready for schedule to the task pool.
+        * usually its just a Scene node.
+        *
+        * We do lock here so no tthreads will start updating nodes valency
+        * while we're still fillign the queue in. Otherwise it's possible
+        * to run into situations when the same task is adding twice to the
+        * queue due to non-safe nature of function below.
+        */
+       BLI_spin_lock(&state.lock);
+       DAG_threaded_update_foreach_ready_node(scene, scene_update_object_add_task, task_pool);
+       BLI_spin_unlock(&state.lock);
+
+       /* work and wait until tasks are done */
+       BLI_task_pool_work_and_wait(task_pool);
+
+       /* free */
+       BLI_task_pool_free(task_pool);
+       BLI_task_scheduler_free(task_scheduler);
+
+       BLI_end_threaded_malloc();
+
+       BLI_spin_end(&state.lock);
+
+       /* XXX: Weak, very weak!
+        *
+        * We update dupligroups in single thread! :S
+        *
+        * This is because we've got absolutely no idea about dependencies
+        * inside the group and we only know order of objects in which we
+        * need to perform objects update.
+        *
+        * We even can not update different groups in different threads,
+        * because groups could share the objects and detecting whether
+        * object is updating in multiple threads is not so much easy.
+        *
+        * This is solvable with local group dependency graph or expanding
+        * current dependency graph to be aware of dependencies inside
+        * groups.
+        *
+        * P.S. Objects from the dup_group are very much likely in scene's
+        *      dependency graph and were alreayd updated in threaded tasks
+        *      scheduler already.
+        *
+        *      So objects from the dupli_groups are likely don't have
+        *      OB_RECALC_ALL flag here, but it seems they still do have
+        *      non-zero recalc flags, and here we make sure things are
+        *      100% by calling BKE_group_handle_recalc_and_update.
+        */
+       {
+               Base *base;
+               for (base = scene->base.first; base; base = base->next) {
+                       Object *object = base->object;
+
+                       if (object->dup_group && (object->transflag & OB_DUPLIGROUP))
+                               BKE_group_handle_recalc_and_update(scene_parent, object, object->dup_group);
+               }
+       }
+}
+
+static void scene_update_objects(Scene *scene, Scene *scene_parent)
+{
+       Base *base;
+       int update_count = 0;
+
+       /* Optimization thing: don't do threads if no modifier
+        * stack need to be evaluated.
+        */
+       for (base = scene->base.first; base; base = base->next) {
+               Object *ob = base->object;
+
+               if (ob->recalc & OB_RECALC_ALL) {
+                       update_count++;
+               }
+       }
+
+       if (update_count > 1) {
+               scene_update_objects_threaded(scene, scene_parent);
+       }
+       else {
+               scene_update_all_bases(scene, scene_parent);
+       }
+}
+
+static void scene_update_tagged_recursive(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(bmain, scene->set, scene_parent);
+
+       /* scene objects */
+       scene_update_objects(scene, scene_parent);
+
        /* scene drivers... */
        scene_update_drivers(bmain, scene);
 
diff --git a/source/blender/blenlib/BLI_task.h b/source/blender/blenlib/BLI_task.h
new file mode 100644 (file)
index 0000000..f57d428
--- /dev/null
@@ -0,0 +1,108 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#ifndef __BLI_TASK_H__
+#define __BLI_TASK_H__ 
+
+/** \file BLI_task.h
+ *  \ingroup bli
+ */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include "BLI_threads.h"
+#include "BLI_utildefines.h"
+
+/* Task Scheduler
+ * 
+ * Central scheduler that holds running threads ready to execute tasks. A single
+ * queue holds the task from all pools.
+ *
+ * Init/exit must be called before/after any task pools are created/freed, and
+ * must be called from the main threads. All other scheduler and pool functions
+ * are thread-safe. */
+
+typedef struct TaskScheduler TaskScheduler;
+
+enum {
+       TASK_SCHEDULER_AUTO_THREADS = 0,
+       TASK_SCHEDULER_SINGLE_THREAD = 1
+};
+
+TaskScheduler *BLI_task_scheduler_create(int num_threads);
+void BLI_task_scheduler_free(TaskScheduler *scheduler);
+
+int BLI_task_scheduler_num_threads(TaskScheduler *scheduler);
+
+/* Task Pool
+ *
+ * Pool of tasks that will be executed by the central TaskScheduler. For each
+ * pool, we can wait for all tasks to be done, or cancel them before they are
+ * done.
+ *
+ * Running tasks may spawn new tasks.
+ *
+ * Pools may be nested, i.e. a thread running a task can create another task
+ * pool with smaller tasks. When other threads are busy they will continue
+ * working on their own tasks, if not they will join in, no new threads will
+ * be launched.
+ */
+
+typedef enum TaskPriority {
+       TASK_PRIORITY_LOW,
+       TASK_PRIORITY_HIGH
+} TaskPriority;
+
+typedef struct TaskPool TaskPool;
+typedef void (*TaskRunFunction)(TaskPool *pool, void *taskdata, int threadid);
+
+TaskPool *BLI_task_pool_create(TaskScheduler *scheduler, void *userdata);
+void BLI_task_pool_free(TaskPool *pool);
+
+void BLI_task_pool_push(TaskPool *pool, TaskRunFunction run,
+       void *taskdata, bool free_taskdata, TaskPriority priority);
+
+/* work and wait until all tasks are done */
+void BLI_task_pool_work_and_wait(TaskPool *pool);
+/* cancel all tasks, keep worker threads running */
+void BLI_task_pool_cancel(TaskPool *pool);
+/* stop all worker threads */
+void BLI_task_pool_stop(TaskPool *pool);
+
+/* for worker threads, test if cancelled */
+bool BLI_task_pool_cancelled(TaskPool *pool);
+
+/* optional userdata pointer to pass along to run function */
+void *BLI_task_pool_userdata(TaskPool *pool);
+
+/* optional mutex to use from run function */
+ThreadMutex *BLI_task_pool_user_mutex(TaskPool *pool);
+
+/* number of tasks done, for stats, don't use this to make decisions */
+size_t BLI_task_pool_tasks_done(TaskPool *pool);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+
index 154986936a29f5416f2ba95d73b759e932ed96e4..d2ad8e3ec9f9ed3444289f4124b840891d7aa4da 100644 (file)
@@ -100,6 +100,7 @@ ThreadMutex *BLI_mutex_alloc(void);
 void BLI_mutex_free(ThreadMutex *mutex);
 
 void BLI_mutex_lock(ThreadMutex *mutex);
+bool BLI_mutex_trylock(ThreadMutex *mutex);
 void BLI_mutex_unlock(ThreadMutex *mutex);
 
 /* Spin Lock */
@@ -182,6 +183,16 @@ int BLI_thread_queue_size(ThreadQueue *queue);
 void BLI_thread_queue_wait_finish(ThreadQueue *queue);
 void BLI_thread_queue_nowait(ThreadQueue *queue);
 
+/* Condition */
+
+typedef pthread_cond_t ThreadCondition;
+
+void BLI_condition_init(ThreadCondition *cond);
+void BLI_condition_wait(ThreadCondition *cond, ThreadMutex *mutex);
+void BLI_condition_notify_one(ThreadCondition *cond);
+void BLI_condition_notify_all(ThreadCondition *cond);
+void BLI_condition_end(ThreadCondition *cond);
+
 #ifdef __cplusplus
 }
 #endif
index 1d94ca9afbca3a7cbfc9b5deaaa6476efd662266..3ae6e8f96564451b539ead86155591e52a9c5a67 100644 (file)
@@ -91,6 +91,7 @@ set(SRC
        intern/string.c
        intern/string_cursor_utf8.c
        intern/string_utf8.c
+       intern/task.c
        intern/threads.c
        intern/time.c
        intern/uvproject.c
@@ -150,6 +151,7 @@ set(SRC
        BLI_string_cursor_utf8.h
        BLI_string_utf8.h
        BLI_sys_types.h
+       BLI_task.h
        BLI_threads.h
        BLI_utildefines.h
        BLI_uvproject.h
diff --git a/source/blender/blenlib/intern/task.c b/source/blender/blenlib/intern/task.c
new file mode 100644 (file)
index 0000000..63ea315
--- /dev/null
@@ -0,0 +1,404 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#include <stdlib.h>
+
+#include "MEM_guardedalloc.h"
+
+#include "BLI_listbase.h"
+#include "BLI_task.h"
+#include "BLI_threads.h"
+
+/* Types */
+
+typedef struct Task {
+       struct Task *next, *prev;
+
+       TaskRunFunction run;
+       void *taskdata;
+       bool free_taskdata;
+       TaskPool *pool;
+} Task;
+
+struct TaskPool {
+       TaskScheduler *scheduler;
+
+       volatile size_t num;
+       volatile size_t done;
+       ThreadMutex num_mutex;
+       ThreadCondition num_cond;
+
+       void *userdata;
+       ThreadMutex user_mutex;
+
+       volatile bool do_cancel;
+};
+
+struct TaskScheduler {
+       pthread_t *threads;
+       int num_threads;
+
+       ListBase queue;
+       ThreadMutex queue_mutex;
+       ThreadCondition queue_cond;
+
+       volatile bool do_exit;
+};
+
+typedef struct TaskThread {
+       TaskScheduler *scheduler;
+       int id;
+} TaskThread;
+
+/* Task Scheduler */
+
+static void task_pool_num_decrease(TaskPool *pool, size_t done)
+{
+       BLI_mutex_lock(&pool->num_mutex);
+       pool->num -= done;
+       pool->done += done;
+
+       BLI_assert(pool->num >= 0);
+       if(pool->num == 0)
+               BLI_condition_notify_all(&pool->num_cond);
+
+       BLI_mutex_unlock(&pool->num_mutex);
+}
+
+static void task_pool_num_increase(TaskPool *pool)
+{
+       BLI_mutex_lock(&pool->num_mutex);
+
+       pool->num++;
+       BLI_condition_notify_all(&pool->num_cond);
+
+       BLI_mutex_unlock(&pool->num_mutex);
+}
+
+static bool task_scheduler_thread_wait_pop(TaskScheduler *scheduler, Task **task)
+{
+       BLI_mutex_lock(&scheduler->queue_mutex);
+
+       while(!scheduler->queue.first && !scheduler->do_exit)
+               BLI_condition_wait(&scheduler->queue_cond, &scheduler->queue_mutex);
+
+       if(!scheduler->queue.first) {
+               BLI_mutex_unlock(&scheduler->queue_mutex);
+               BLI_assert(scheduler->do_exit);
+               return false;
+       }
+       
+       *task = scheduler->queue.first;
+       BLI_remlink(&scheduler->queue, *task);
+
+       BLI_mutex_unlock(&scheduler->queue_mutex);
+
+       return true;
+}
+
+static void *task_scheduler_thread_run(void *thread_p)
+{
+       TaskThread *thread = (TaskThread*)thread_p;
+       TaskScheduler *scheduler = thread->scheduler;
+       int thread_id = thread->id;
+       Task *task;
+
+       /* keep popping off tasks */
+       while(task_scheduler_thread_wait_pop(scheduler, &task)) {
+               /* run task */
+               task->run(task->pool, task->taskdata, thread_id);
+
+               /* notify pool task was done */
+               task_pool_num_decrease(task->pool, 1);
+
+               /* delete task */
+               if(task->free_taskdata)
+                       MEM_freeN(task->taskdata);
+               MEM_freeN(task);
+       }
+
+       MEM_freeN(thread);
+
+       return NULL;
+}
+
+TaskScheduler *BLI_task_scheduler_create(int num_threads)
+{
+       TaskScheduler *scheduler = MEM_callocN(sizeof(TaskScheduler), "TaskScheduler");
+
+       /* multiple places can use this task scheduler, sharing the same
+        * threads, so we keep track of the number of users. */
+       scheduler->do_exit = false;
+
+       scheduler->queue.first = scheduler->queue.last = NULL;
+       BLI_mutex_init(&scheduler->queue_mutex);
+       BLI_condition_init(&scheduler->queue_cond);
+
+       if(num_threads == 0) {
+               /* automatic number of threads will be main thread + num cores */
+               num_threads = BLI_system_thread_count();
+       }
+
+       /* main thread will also work, so we count it too */
+       num_threads -= 1;
+
+       /* launch threads that will be waiting for work */
+       if(num_threads > 0) {
+               int i;
+
+               scheduler->num_threads = num_threads;
+               scheduler->threads = MEM_callocN(sizeof(pthread_t)*num_threads, "TaskScheduler threads");
+
+               for(i = 0; i < num_threads; i++) {
+                       TaskThread *thread = MEM_callocN(sizeof(TaskThread), "TaskThread");
+                       thread->scheduler = scheduler;
+                       thread->id = i+1;
+
+                       if(pthread_create(&scheduler->threads[i], NULL, task_scheduler_thread_run, thread) != 0) {
+                               fprintf(stderr, "TaskScheduler failed to launch thread %d/%d\n", i, num_threads);
+                               MEM_freeN(thread);
+                       }
+               }
+       }
+       
+       return scheduler;
+}
+
+void BLI_task_scheduler_free(TaskScheduler *scheduler)
+{
+       Task *task;
+
+       /* stop all waiting threads */
+       BLI_mutex_lock(&scheduler->queue_mutex);
+       scheduler->do_exit = true;
+       BLI_condition_notify_all(&scheduler->queue_cond);
+       BLI_mutex_unlock(&scheduler->queue_mutex);
+
+       /* delete threads */
+       if(scheduler->threads) {
+               int i;
+
+               for(i = 0; i < scheduler->num_threads; i++) {
+                       if(pthread_join(scheduler->threads[i], NULL) != 0)
+                               fprintf(stderr, "TaskScheduler failed to join thread %d/%d\n", i, scheduler->num_threads);
+               }
+
+               MEM_freeN(scheduler->threads);
+       }
+
+       /* delete leftover tasks */
+       for(task = scheduler->queue.first; task; task = task->next)
+               if(task->free_taskdata)
+                       MEM_freeN(task->taskdata);
+       BLI_freelistN(&scheduler->queue);
+
+       /* delete mutex/condition */
+       BLI_mutex_end(&scheduler->queue_mutex);
+       BLI_condition_end(&scheduler->queue_cond);
+
+       MEM_freeN(scheduler);
+}
+
+int BLI_task_scheduler_num_threads(TaskScheduler *scheduler)
+{
+       return scheduler->num_threads + 1;
+}
+
+static void task_scheduler_push(TaskScheduler *scheduler, Task *task, TaskPriority priority)
+{
+       task_pool_num_increase(task->pool);
+
+       /* add task to queue */
+       BLI_mutex_lock(&scheduler->queue_mutex);
+
+       if(priority == TASK_PRIORITY_HIGH)
+               BLI_addhead(&scheduler->queue, task);
+       else
+               BLI_addtail(&scheduler->queue, task);
+
+       BLI_condition_notify_one(&scheduler->queue_cond);
+       BLI_mutex_unlock(&scheduler->queue_mutex);
+}
+
+static void task_scheduler_clear(TaskScheduler *scheduler, TaskPool *pool)
+{
+       Task *task, *nexttask;
+       size_t done = 0;
+
+       BLI_mutex_lock(&scheduler->queue_mutex);
+
+       /* free all tasks from this pool from the queue */
+       for(task = scheduler->queue.first; task; task = nexttask) {
+               nexttask = task->next;
+
+               if(task->pool == pool) {
+                       if(task->free_taskdata)
+                               MEM_freeN(task->taskdata);
+                       BLI_freelinkN(&scheduler->queue, task);
+
+                       done++;
+               }
+       }
+
+       BLI_mutex_unlock(&scheduler->queue_mutex);
+
+       /* notify done */
+       task_pool_num_decrease(pool, done);
+}
+
+/* Task Pool */
+
+TaskPool *BLI_task_pool_create(TaskScheduler *scheduler, void *userdata)
+{
+       TaskPool *pool = MEM_callocN(sizeof(TaskPool), "TaskPool");
+
+       pool->scheduler = scheduler;
+       pool->num = 0;
+       pool->do_cancel = false;
+
+       BLI_mutex_init(&pool->num_mutex);
+       BLI_condition_init(&pool->num_cond);
+
+       pool->userdata = userdata;
+       BLI_mutex_init(&pool->user_mutex);
+
+       return pool;
+}
+
+void BLI_task_pool_free(TaskPool *pool)
+{
+       BLI_task_pool_stop(pool);
+
+       BLI_mutex_end(&pool->num_mutex);
+       BLI_condition_end(&pool->num_cond);
+
+       BLI_mutex_end(&pool->user_mutex);
+
+       MEM_freeN(pool);
+}
+
+void BLI_task_pool_push(TaskPool *pool, TaskRunFunction run,
+       void *taskdata, bool free_taskdata, TaskPriority priority)
+{
+       Task *task = MEM_callocN(sizeof(Task), "Task");
+
+       task->run = run;
+       task->taskdata = taskdata;
+       task->free_taskdata = free_taskdata;
+       task->pool = pool;
+
+       task_scheduler_push(pool->scheduler, task, priority);
+}
+
+void BLI_task_pool_work_and_wait(TaskPool *pool)
+{
+       TaskScheduler *scheduler = pool->scheduler;
+
+       BLI_mutex_lock(&pool->num_mutex);
+
+       while(pool->num != 0) {
+               Task *task, *work_task = NULL;
+               bool found_task = false;
+
+               BLI_mutex_unlock(&pool->num_mutex);
+
+               BLI_mutex_lock(&scheduler->queue_mutex);
+
+               /* find task from this pool. if we get a task from another pool,
+                * we can get into deadlock */
+
+               for(task = scheduler->queue.first; task; task = task->next) {
+                       if(task->pool == pool) {
+                               work_task = task;
+                               found_task = true;
+                               BLI_remlink(&scheduler->queue, task);
+                               break;
+                       }
+               }
+
+               BLI_mutex_unlock(&scheduler->queue_mutex);
+
+               /* if found task, do it, otherwise wait until other tasks are done */
+               if(found_task) {
+                       /* run task */
+                       work_task->run(pool, work_task->taskdata, 0);
+
+                       /* delete task */
+                       if(work_task->free_taskdata)
+                               MEM_freeN(work_task->taskdata);
+                       MEM_freeN(work_task);
+
+                       /* notify pool task was done */
+                       task_pool_num_decrease(pool, 1);
+               }
+
+               BLI_mutex_lock(&pool->num_mutex);
+               if(pool->num == 0)
+                       break;
+
+               if(!found_task)
+                       BLI_condition_wait(&pool->num_cond, &pool->num_mutex);
+       }
+
+       BLI_mutex_unlock(&pool->num_mutex);
+}
+
+void BLI_task_pool_cancel(TaskPool *pool)
+{
+       pool->do_cancel = true;
+
+       task_scheduler_clear(pool->scheduler, pool);
+
+       /* wait until all entries are cleared */
+       BLI_mutex_lock(&pool->num_mutex);
+       while(pool->num)
+               BLI_condition_wait(&pool->num_cond, &pool->num_mutex);
+       BLI_mutex_unlock(&pool->num_mutex);
+
+       pool->do_cancel = false;
+}
+
+void BLI_task_pool_stop(TaskPool *pool)
+{
+       task_scheduler_clear(pool->scheduler, pool);
+
+       BLI_assert(pool->num == 0);
+}
+
+bool BLI_task_pool_cancelled(TaskPool *pool)
+{
+       return pool->do_cancel;
+}
+
+void *BLI_task_pool_userdata(TaskPool *pool)
+{
+       return pool->userdata;
+}
+
+ThreadMutex *BLI_task_pool_user_mutex(TaskPool *pool)
+{
+       return &pool->user_mutex;
+}
+
+size_t BLI_task_pool_tasks_done(TaskPool *pool)
+{
+       return pool->done;
+}
+
index 2b6fb52c49c296f9debda3c421d271669383870d..033213dff5d3ec9ea4b2d75c847937fd6fba13cf 100644 (file)
@@ -412,6 +412,11 @@ void BLI_mutex_unlock(ThreadMutex *mutex)
        pthread_mutex_unlock(mutex);
 }
 
+bool BLI_mutex_trylock(ThreadMutex *mutex)
+{
+       return (pthread_mutex_trylock(mutex) == 0);
+}
+
 void BLI_mutex_end(ThreadMutex *mutex)
 {
        pthread_mutex_destroy(mutex);
@@ -818,6 +823,32 @@ void BLI_thread_queue_wait_finish(ThreadQueue *queue)
        pthread_mutex_unlock(&queue->mutex);
 }
 
+/* Condition */
+void BLI_condition_init(ThreadCondition *cond)
+{
+       pthread_cond_init(cond, NULL);
+}
+
+void BLI_condition_wait(ThreadCondition *cond, ThreadMutex *mutex)
+{
+       pthread_cond_wait(cond, mutex);
+}
+
+void BLI_condition_notify_one(ThreadCondition *cond)
+{
+       pthread_cond_signal(cond);
+}
+
+void BLI_condition_notify_all(ThreadCondition *cond)
+{
+       pthread_cond_broadcast(cond);
+}
+
+void BLI_condition_end(ThreadCondition *cond)
+{
+       pthread_cond_destroy(cond);
+}
+
 /* ************************************************ */
 
 void BLI_begin_threaded_malloc(void)
index a6da0762b1c68adb60794aa1e7e99bfce71af21c..5381bfebf2e873097cc9e10142efee1afdad4f78 100644 (file)
@@ -3391,11 +3391,8 @@ static void direct_link_curve(FileData *fd, Curve *cu)
                if (cu->wordspace == 0.0f) cu->wordspace = 1.0f;
        }
 
-       cu->bev.first = cu->bev.last = NULL;
-       cu->disp.first = cu->disp.last = NULL;
        cu->editnurb = NULL;
        cu->lastsel = NULL;
-       cu->path = NULL;
        cu->editfont = NULL;
        
        for (nu = cu->nurb.first; nu; nu = nu->next) {
@@ -4821,8 +4818,6 @@ static void direct_link_object(FileData *fd, Object *ob)
                ob->mode &= ~(OB_MODE_EDIT | OB_MODE_PARTICLE_EDIT);
        }
        
-       ob->disp.first = ob->disp.last = NULL;
-       
        ob->adt = newdataadr(fd, ob->adt);
        direct_link_animdata(fd, ob->adt);
        
@@ -5017,6 +5012,9 @@ static void direct_link_object(FileData *fd, Object *ob)
        ob->gpulamp.first= ob->gpulamp.last = NULL;
        link_list(fd, &ob->pc_ids);
 
+       /* Runtime curve data  */
+       ob->curve_cache = NULL;
+
        /* in case this value changes in future, clamp else we get undefined behavior */
        CLAMP(ob->rotmode, ROT_MODE_MIN, ROT_MODE_MAX);
 
@@ -5519,6 +5517,7 @@ static void direct_link_windowmanager(FileData *fd, wmWindowManager *wm)
        wm->winactive = NULL;
        wm->initialized = 0;
        wm->op_undo_depth = 0;
+       wm->is_interface_locked = 0;
 }
 
 static void lib_link_windowmanager(FileData *fd, Main *main)
index e061ff3502569a66e576b13aca5dac7fde607f16..8caa059d168cbea45459857da5385f2c0bd8f748 100644 (file)
@@ -1,4 +1,5 @@
 /*
+
  * ***** BEGIN GPL LICENSE BLOCK *****
  *
  * This program is free software; you can redistribute it and/or
@@ -1017,6 +1018,7 @@ uiLayout *uiTemplateModifier(uiLayout *layout, bContext *C, PointerRNA *ptr)
        Scene *scene = CTX_data_scene(C);
        Object *ob;
        ModifierData *md, *vmd;
+       VirtualModifierData virtualModifierData;
        int i, lastCageIndex, cageIndex;
 
        /* verify we have valid data */
@@ -1039,7 +1041,7 @@ uiLayout *uiTemplateModifier(uiLayout *layout, bContext *C, PointerRNA *ptr)
        cageIndex = modifiers_getCageIndex(scene, ob, &lastCageIndex, 0);
 
        /* XXX virtual modifiers are not accesible for python */
-       vmd = modifiers_getVirtualModifierList(ob);
+       vmd = modifiers_getVirtualModifierList(ob, &virtualModifierData);
 
        for (i = 0; vmd; i++, vmd = vmd->next) {
                if (md == vmd)
index 1e0a8cefb8745a2c95085d24f452b4d2909f73f8..f911495d5b4c0a3a4d535584343e62368dd699d8 100644 (file)
@@ -1243,7 +1243,7 @@ static void make_object_duplilist_real(bContext *C, Scene *scene, Base *base,
 
                ob->parent = NULL;
                ob->constraints.first = ob->constraints.last = NULL;
-               ob->disp.first = ob->disp.last = NULL;
+               ob->curve_cache = NULL;
                ob->transflag &= ~OB_DUPLI;
                ob->lay = base->lay;
 
@@ -1385,7 +1385,7 @@ static EnumPropertyItem convert_target_items[] = {
 
 static void curvetomesh(Scene *scene, Object *ob) 
 {
-       if (ob->disp.first == NULL)
+       if (ELEM(NULL, ob->curve_cache, ob->curve_cache->disp.first))
                BKE_displist_make_curveTypes(scene, ob, 0);  /* force creation */
 
        BKE_mesh_from_nurbs(ob); /* also does users */
@@ -1553,7 +1553,7 @@ static int convert_exec(bContext *C, wmOperator *op)
 
                        cu = newob->data;
 
-                       if (!newob->disp.first)
+                       if ( !newob->curve_cache || !newob->curve_cache->disp.first)
                                BKE_displist_make_curveTypes(scene, newob, 0);
 
                        newob->type = OB_CURVE;
@@ -1595,7 +1595,7 @@ static int convert_exec(bContext *C, wmOperator *op)
                                curvetomesh(scene, newob);
 
                                /* meshes doesn't use displist */
-                               BKE_displist_free(&newob->disp);
+                               BKE_object_free_curve_cache(newob);
                        }
                }
                else if (ELEM(ob->type, OB_CURVE, OB_SURF)) {
@@ -1616,7 +1616,7 @@ static int convert_exec(bContext *C, wmOperator *op)
                                        newob = ob;
 
                                        /* meshes doesn't use displist */
-                                       BKE_displist_free(&newob->disp);
+                                       BKE_object_free_curve_cache(newob);
                                }
 
                                curvetomesh(scene, newob);
@@ -1635,7 +1635,7 @@ static int convert_exec(bContext *C, wmOperator *op)
                                ob->flag |= OB_DONE;
                        }
 
-                       if (!baseob->disp.first) {
+                       if (!baseob->curve_cache || !baseob->curve_cache->disp.first) {
                                BKE_displist_make_mball(scene, baseob);
                        }
 
@@ -1658,7 +1658,7 @@ static int convert_exec(bContext *C, wmOperator *op)
                                        for (a = 0; a < newob->totcol; a++) id_us_plus((ID *)me->mat[a]);
                                }
 
-                               BKE_mesh_from_metaball(&baseob->disp, newob->data);
+                               BKE_mesh_from_metaball(&baseob->curve_cache->disp, newob->data);
 
                                if (obact->type == OB_MBALL) {
                                        basact = basen;
index b1f1f73f493dba44a342965f51f96a62fff52712..91c80a7083858a8167a73066fa7b843b7c963d0a 100644 (file)
@@ -637,9 +637,9 @@ static int modifier_apply_obdata(ReportList *reports, Scene *scene, Object *ob,
                cu = ob->data;
                BKE_report(reports, RPT_INFO, "Applied modifier only changed CV points, not tessellated/bevel vertices");
 
-               vertexCos = BKE_curve_vertexCos_get(cu, &cu->nurb, &numVerts);
+               vertexCos = BKE_curve_nurbs_vertexCos_get(&cu->nurb, &numVerts);
                mti->deformVerts(md, ob, NULL, vertexCos, numVerts, 0);
-               BK_curve_vertexCos_apply(cu, &cu->nurb, vertexCos);
+               BK_curve_nurbs_vertexCos_apply(&cu->nurb, vertexCos);
 
                MEM_freeN(vertexCos);
 
index 7a2ece66ba4e6d601a96f332884f2c676dc62dfa..fbb8ceae6070b304afe9ff52c9726de73f294a4a 100644 (file)
@@ -273,6 +273,7 @@ typedef struct RenderJob {
        short *do_update;
        float *progress;
        ReportList *reports;
+       bool interface_locked;
 } RenderJob;
 
 static void render_freejob(void *rjv)
@@ -498,6 +499,15 @@ static void render_endjob(void *rjv)
 
                BKE_image_release_ibuf(ima, ibuf, lock);
        }
+
+       /* Finally unlock the user interface (if it was locked). */
+       if (rj->interface_locked) {
+               /* Interface was locked, so window manager couldn't have been changed
+                * and using one from Global will unlock exactly the same manager as
+                * was locked before running the job.
+                */
+               WM_set_locked_interface(G.main->wm.first, false);
+       }
 }
 
 /* called by render, check job 'stop' value or the global */
@@ -523,10 +533,14 @@ static int render_break(void *UNUSED(rjv))
 
 /* runs in thread, no cursor setting here works. careful with notifiers too (malloc conflicts) */
 /* maybe need a way to get job send notifer? */
-static void render_drawlock(void *UNUSED(rjv), int lock)
+static void render_drawlock(void *rjv, int lock)
 {
-       BKE_spacedata_draw_locks(lock);
-       
+       RenderJob *rj = rjv;
+
+       /* If interface is locked, renderer callback shall do nothing. */
+       if (!rj->interface_locked) {
+               BKE_spacedata_draw_locks(lock);
+       }
 }
 
 /* catch esc */
@@ -649,6 +663,23 @@ static int screen_render_invoke(bContext *C, wmOperator *op, const wmEvent *even
                        rj->lay |= v3d->localvd->lay;
        }
 
+       /* Lock the user interface depending on render settings. */
+       if (scene->r.use_lock_interface) {
+               WM_set_locked_interface(CTX_wm_manager(C), true);
+
+               /* Set flag interface need to be unlocked.
+                *
+                * This is so because we don't have copy of render settings
+                * accessible from render job and copy is needed in case
+                * of non-locked rendering, so we wouldn't try to unlock
+                * anything if option was initially unset but then was
+                * enabled during rendering.
+                */
+               rj->interface_locked = true;
+
+               /* TODO(sergey): clean memory used by viewport? */
+       }
+
        /* setup job */
        if (RE_seq_render_active(scene, &scene->r)) name = "Sequence Render";
        else name = "Render";
index 8e2a29964ee4f6e7b4459680db7693ace8ac23a4..79fab72b770dd491fcca12526fb9c90daa5a089b 100644 (file)
@@ -150,6 +150,7 @@ MultiresModifierData *sculpt_multires_active(Scene *scene, Object *ob)
 {
        Mesh *me = (Mesh *)ob->data;
        ModifierData *md;
+       VirtualModifierData virtualModifierData;
 
        if (ob->sculpt && ob->sculpt->bm) {
                /* can't combine multires and dynamic topology */
@@ -161,7 +162,7 @@ MultiresModifierData *sculpt_multires_active(Scene *scene, Object *ob)
                return NULL;
        }
 
-       for (md = modifiers_getVirtualModifierList(ob); md; md = md->next) {
+       for (md = modifiers_getVirtualModifierList(ob, &virtualModifierData); md; md = md->next) {
                if (md->type == eModifierType_Multires) {
                        MultiresModifierData *mmd = (MultiresModifierData *)md;
 
@@ -180,8 +181,9 @@ MultiresModifierData *sculpt_multires_active(Scene *scene, Object *ob)
 static int sculpt_has_active_modifiers(Scene *scene, Object *ob)
 {
        ModifierData *md;
+       VirtualModifierData virtualModifierData;
 
-       md = modifiers_getVirtualModifierList(ob);
+       md = modifiers_getVirtualModifierList(ob, &virtualModifierData);
 
        /* exception for shape keys because we can edit those */
        for (; md; md = md->next) {
@@ -198,6 +200,7 @@ static int sculpt_modifiers_active(Scene *scene, Sculpt *sd, Object *ob)
        ModifierData *md;
        Mesh *me = (Mesh *)ob->data;
        MultiresModifierData *mmd = sculpt_multires_active(scene, ob);
+       VirtualModifierData virtualModifierData;
 
        if (mmd || ob->sculpt->bm)
                return 0;
@@ -206,7 +209,7 @@ static int sculpt_modifiers_active(Scene *scene, Sculpt *sd, Object *ob)
        if ((ob->shapeflag & OB_SHAPE_LOCK) == 0 && me->key && ob->shapenr)
                return 1;
 
-       md = modifiers_getVirtualModifierList(ob);
+       md = modifiers_getVirtualModifierList(ob, &virtualModifierData);
 
        /* exception for shape keys because we can edit those */
        for (; md; md = md->next) {
index 88f67def30a56fd310ad8a265ff2a4bf23a6c8f1..fa39ccf4bcaa5791a6e0337bd9e8caa8d9727ea5 100644 (file)
@@ -360,7 +360,7 @@ void IMAGE_OT_view_pan(wmOperatorType *ot)
        ot->poll = space_image_main_area_poll;
 
        /* flags */
-       ot->flag = OPTYPE_BLOCKING | OPTYPE_GRAB_POINTER;
+       ot->flag = OPTYPE_BLOCKING | OPTYPE_GRAB_POINTER | OPTYPE_ALLOW_LOCKED;
        
        /* properties */
        RNA_def_float_vector(ot->srna, "offset", 2, NULL, -FLT_MAX, FLT_MAX,
@@ -575,7 +575,7 @@ void IMAGE_OT_view_zoom(wmOperatorType *ot)
        ot->poll = space_image_main_area_poll;
 
        /* flags */
-       ot->flag = OPTYPE_BLOCKING;
+       ot->flag = OPTYPE_BLOCKING | OPTYPE_ALLOW_LOCKED;
        
        /* properties */
        RNA_def_float(ot->srna, "factor", 0.0f, -FLT_MAX, FLT_MAX,
@@ -638,6 +638,9 @@ void IMAGE_OT_view_ndof(wmOperatorType *ot)
        
        /* api callbacks */
        ot->invoke = image_view_ndof_invoke;
+
+       /* flags */
+       ot->flag = OPTYPE_ALLOW_LOCKED;
 }
 
 /********************** view all operator *********************/
@@ -693,6 +696,9 @@ void IMAGE_OT_view_all(wmOperatorType *ot)
        /* api callbacks */
        ot->exec = image_view_all_exec;
        ot->poll = space_image_main_area_poll;
+
+       /* flags */
+       ot->flag = OPTYPE_GRAB_POINTER;
 }
 
 /********************** view selected operator *********************/
@@ -755,6 +761,9 @@ void IMAGE_OT_view_selected(wmOperatorType *ot)
        /* api callbacks */
        ot->exec = image_view_selected_exec;
        ot->poll = image_view_selected_poll;
+
+       /* flags */
+       ot->flag = OPTYPE_GRAB_POINTER;
 }
 
 /********************** view zoom in/out operator *********************/
@@ -797,6 +806,9 @@ void IMAGE_OT_view_zoom_in(wmOperatorType *ot)
        ot->exec = image_view_zoom_in_exec;
        ot->poll = space_image_main_area_poll;
 
+       /* flags */
+       ot->flag = OPTYPE_ALLOW_LOCKED;
+
        /* properties */
        RNA_def_float_vector(ot->srna, "location", 2, NULL, -FLT_MAX, FLT_MAX, "Location", "Cursor location in screen coordinates", -10.0f, 10.0f);
 }
@@ -839,6 +851,9 @@ void IMAGE_OT_view_zoom_out(wmOperatorType *ot)
        ot->exec = image_view_zoom_out_exec;
        ot->poll = space_image_main_area_poll;
 
+       /* flags */
+       ot->flag = OPTYPE_ALLOW_LOCKED;
+
        /* properties */
        RNA_def_float_vector(ot->srna, "location", 2, NULL, -FLT_MAX, FLT_MAX, "Location", "Cursor location in screen coordinates", -10.0f, 10.0f);
 }
@@ -880,7 +895,10 @@ void IMAGE_OT_view_zoom_ratio(wmOperatorType *ot)
        /* api callbacks */
        ot->exec = image_view_zoom_ratio_exec;
        ot->poll = space_image_main_area_poll;
-       
+
+       /* flags */
+       ot->flag = OPTYPE_ALLOW_LOCKED;
+
        /* 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);
index 98c9c8d15fe3a2a459bec6dea1b5cd8b3836ff16..c1cddf092aa0429a577f3b3119a70c748667414d 100644 (file)
@@ -115,8 +115,8 @@ static void stats_object(Object *ob, int sel, int totob, SceneStats *stats)
                {
                        int totv = 0, totf = 0, tottri = 0;
 
-                       if (ob->disp.first)
-                               BKE_displist_count(&ob->disp, &totv, &totf, &tottri);
+                       if (ob->curve_cache && ob->curve_cache->disp.first)
+                               BKE_displist_count(&ob->curve_cache->disp, &totv, &totf, &tottri);
 
                        totv   *= totob;
                        totf   *= totob;
index 55e1fae38e48927ccdf74d9cd283dbe7220269d2..d5860606b65ee8d4d2cb278d2ad2cc9d3f95917c 100644 (file)
@@ -1900,9 +1900,9 @@ static void drawlattice(Scene *scene, View3D *v3d, Object *ob)
        const bool is_edit = (lt->editlatt != NULL);
 
        /* now we default make displist, this will modifiers work for non animated case */
-       if (ob->disp.first == NULL)
+       if (ELEM(NULL, ob->curve_cache, ob->curve_cache->disp.first))
                BKE_lattice_modifiers_calc(scene, ob);
-       dl = BKE_displist_find(&ob->disp, DL_VERTS);
+       dl = BKE_displist_find(&ob->curve_cache->disp, DL_VERTS);
        
        if (is_edit) {
                lt = lt->editlatt->latt;
@@ -3946,7 +3946,7 @@ static bool drawDispList_nobackface(Scene *scene, View3D *v3d, RegionView3D *rv3
                case OB_CURVE:
                        cu = ob->data;
 
-                       lb = &ob->disp;
+                       lb = &ob->curve_cache->disp;
 
                        if (solid) {
                                dl = lb->first;
@@ -3996,7 +3996,7 @@ static bool drawDispList_nobackface(Scene *scene, View3D *v3d, RegionView3D *rv3
                        break;
                case OB_SURF:
 
-                       lb = &ob->disp;
+                       lb = &ob->curve_cache->disp;
 
                        if (solid) {
                                dl = lb->first;
@@ -4024,8 +4024,11 @@ static bool drawDispList_nobackface(Scene *scene, View3D *v3d, RegionView3D *rv3
                case OB_MBALL:
 
                        if (BKE_mball_is_basis(ob)) {
-                               lb = &ob->disp;
-                               if (lb->first == NULL) BKE_displist_make_mball(scene, ob);
+                               lb = ob->curve_cache ? &ob->curve_cache->disp : NULL;
+                               if (lb->first == NULL) {
+                                       BKE_displist_make_mball(scene, ob);
+                                       lb = &ob->curve_cache->disp;
+                               }
                                if (lb->first == NULL) {
                                        return true;
                                }
@@ -5615,7 +5618,7 @@ static void drawnurb(Scene *scene, View3D *v3d, RegionView3D *rv3d, Base *base,
        if ((cu->flag & CU_3D) && (ts->normalsize > 0.0015f) && (cu->drawflag & CU_HIDE_NORMALS) == 0) {
 
                UI_ThemeColor(TH_WIRE_EDIT);
-               for (bl = cu->bev.first, nu = nurb; nu && bl; bl = bl->next, nu = nu->next) {
+               for (bl = ob->curve_cache->bev.first, nu = nurb; nu && bl; bl = bl->next, nu = nu->next) {
                        BevPoint *bevp = (BevPoint *)(bl + 1);
                        int nr = bl->nr;
                        int skip = nu->resolu / 16;
@@ -6038,7 +6041,7 @@ static void draw_forcefield(Object *ob, RegionView3D *rv3d,
        }
        else if (pd->forcefield == PFIELD_GUIDE && ob->type == OB_CURVE) {
                Curve *cu = ob->data;
-               if ((cu->flag & CU_PATH) && cu->path && cu->path->data) {
+               if ((cu->flag & CU_PATH) && ob->curve_cache->path && ob->curve_cache->path->data) {
                        float mindist, guidevec1[4], guidevec2[3];
 
                        //if (has_ipo_code(ob->ipo, OB_PD_FSTR))
@@ -6296,7 +6299,6 @@ static void drawObjectSelect(Scene *scene, View3D *v3d, ARegion *ar, Base *base,
        glDepthMask(0);
        
        if (ELEM3(ob->type, OB_FONT, OB_CURVE, OB_SURF)) {
-               Curve *cu = ob->data;
                DerivedMesh *dm = ob->derivedFinal;
                bool has_faces = false;
 
@@ -6304,16 +6306,16 @@ static void drawObjectSelect(Scene *scene, View3D *v3d, ARegion *ar, Base *base,
                        has_faces = dm->getNumTessFaces(dm);
                }
                else {
-                       has_faces = BKE_displist_has_faces(&ob->disp);
+                       has_faces = BKE_displist_has_faces(&ob->curve_cache->disp);
                }
 
-               if (has_faces && ED_view3d_boundbox_clip(rv3d, ob->obmat, ob->bb ? ob->bb : cu->bb)) {
+               if (has_faces && ED_view3d_boundbox_clip(rv3d, ob->obmat, ob->bb)) {
                        draw_index_wire = false;
                        if (dm) {
                                draw_mesh_object_outline(v3d, ob, dm);
                        }
                        else {
-                               drawDispListwire(&ob->disp);
+                               drawDispListwire(&ob->curve_cache->disp);
                        }
                        draw_index_wire = true;
                }
@@ -6321,7 +6323,7 @@ static void drawObjectSelect(Scene *scene, View3D *v3d, ARegion *ar, Base *base,
        else if (ob->type == OB_MBALL) {
                if (BKE_mball_is_basis(ob)) {
                        if ((base->flag & OB_FROMDUPLI) == 0)
-                               drawDispListwire(&ob->disp);
+                               drawDispListwire(&ob->curve_cache->disp);
                }
        }
        else if (ob->type == OB_ARMATURE) {
@@ -6348,8 +6350,7 @@ static void draw_wire_extra(Scene *scene, RegionView3D *rv3d, Object *ob, unsign
                glDepthMask(0);  /* disable write in zbuffer, selected edge wires show better */
 
                if (ELEM3(ob->type, OB_FONT, OB_CURVE, OB_SURF)) {
-                       Curve *cu = ob->data;
-                       if (ED_view3d_boundbox_clip(rv3d, ob->obmat, ob->bb ? ob->bb : cu->bb)) {
+                       if (ED_view3d_boundbox_clip(rv3d, ob->obmat, ob->bb)) {
                                if (ob->type == OB_CURVE)
                                        draw_index_wire = false;
 
@@ -6357,7 +6358,7 @@ static void draw_wire_extra(Scene *scene, RegionView3D *rv3d, Object *ob, unsign
                                        drawCurveDMWired(ob);
                                }
                                else {
-                                       drawDispListwire(&ob->disp);
+                                       drawDispListwire(&ob->curve_cache->disp);
                                }
 
                                if (ob->type == OB_CURVE)
@@ -6366,7 +6367,7 @@ static void draw_wire_extra(Scene *scene, RegionView3D *rv3d, Object *ob, unsign
                }
                else if (ob->type == OB_MBALL) {
                        if (BKE_mball_is_basis(ob)) {
-                               drawDispListwire(&ob->disp);
+                               drawDispListwire(&ob->curve_cache->disp);
                        }
                }
 
@@ -6676,7 +6677,9 @@ void draw_object(Scene *scene, ARegion *ar, View3D *v3d, Base *base, const short
        /* bad exception, solve this! otherwise outline shows too late */
        if (ELEM3(ob->type, OB_CURVE, OB_SURF, OB_FONT)) {
                /* still needed for curves hidden in other layers. depgraph doesnt handle that yet */
-               if (ob->disp.first == NULL) BKE_displist_make_curveTypes(scene, ob, 0);
+               if (ELEM(NULL, ob->curve_cache, ob->curve_cache->disp.first)) {
+                       BKE_displist_make_curveTypes(scene, ob, 0);
+               }
        }
        
        /* draw outline for selected objects, mesh does itself */
@@ -6780,7 +6783,7 @@ void draw_object(Scene *scene, ARegion *ar, View3D *v3d, Base *base, const short
                                        draw_bounding_volume(scene, ob, ob->boundtype);
                                }
                        }
-                       else if (ED_view3d_boundbox_clip(rv3d, ob->obmat, ob->bb ? ob->bb : cu->bb)) {
+                       else if (ED_view3d_boundbox_clip(rv3d, ob->obmat, ob->bb)) {
                                empty_object = drawDispList(scene, v3d, rv3d, base, dt, dflag, ob_wire_col);
                        }
 
@@ -6798,7 +6801,7 @@ void draw_object(Scene *scene, ARegion *ar, View3D *v3d, Base *base, const short
                                        draw_bounding_volume(scene, ob, ob->boundtype);
                                }
                        }
-                       else if (ED_view3d_boundbox_clip(rv3d, ob->obmat, ob->bb ? ob->bb : cu->bb)) {
+                       else if (ED_view3d_boundbox_clip(rv3d, ob->obmat, ob->bb)) {
                                empty_object = drawDispList(scene, v3d, rv3d, base, dt, dflag, ob_wire_col);
 
 //XXX old animsys                              if (cu->path)
index 0490d8763d8ff43616a42be4bd72347ec1639544..9f922f12976cb13b5d371e798d4bb565d4ce69f8 100644 (file)
@@ -368,7 +368,7 @@ void lattice_foreachScreenVert(
        Object *obedit = vc->obedit;
        Lattice *lt = obedit->data;
        BPoint *bp = lt->editlatt->latt->def;
-       DispList *dl = BKE_displist_find(&obedit->disp, DL_VERTS);
+       DispList *dl = obedit->curve_cache ? BKE_displist_find(&obedit->curve_cache->disp, DL_VERTS) : NULL;
        float *co = dl ? dl->verts : NULL;
        int i, N = lt->editlatt->latt->pntsu * lt->editlatt->latt->pntsv * lt->editlatt->latt->pntsw;
 
index ea3687ad7157e5ae878074534440f23a68abbb63..1f9ef5f5bc5588a94d39c273e4e98260c652b3c5 100644 (file)
@@ -259,11 +259,12 @@ int editbmesh_get_first_deform_matrices(Scene *scene, Object *ob, BMEditMesh *em
        int i, a, numleft = 0, numVerts = 0;
        int cageIndex = modifiers_getCageIndex(scene, ob, NULL, 1);
        float (*defmats)[3][3] = NULL, (*deformedVerts)[3] = NULL;
+       VirtualModifierData virtualModifierData;
 
        modifiers_clearErrors(ob);
 
        dm = NULL;
-       md = modifiers_getVirtualModifierList(ob);
+       md = modifiers_getVirtualModifierList(ob, &virtualModifierData);
 
        /* compute the deformation matrices and coordinates for the first
         * modifiers with on cage editing that are enabled and support computing
@@ -313,6 +314,7 @@ int sculpt_get_first_deform_matrices(Scene *scene, Object *ob, float (**deformma
        MultiresModifierData *mmd = get_multires_modifier(scene, ob, 0);
        int has_multires = mmd != NULL && mmd->sculptlvl > 0;
        int numleft = 0;
+       VirtualModifierData virtualModifierData;
 
        if (has_multires) {
                *deformmats = NULL;
@@ -321,7 +323,7 @@ int sculpt_get_first_deform_matrices(Scene *scene, Object *ob, float (**deformma
        }
 
        dm = NULL;
-       md = modifiers_getVirtualModifierList(ob);
+       md = modifiers_getVirtualModifierList(ob, &virtualModifierData);
 
        for (; md; md = md->next) {
                ModifierTypeInfo *mti = modifierType_getInfo(md->type);
@@ -374,7 +376,8 @@ void crazyspace_build_sculpt(Scene *scene, Object *ob, float (**deformmats)[3][3
                float (*origVerts)[3] = MEM_dupallocN(deformedVerts);
                float *quats = NULL;
                int i, deformed = 0;
-               ModifierData *md = modifiers_getVirtualModifierList(ob);
+               VirtualModifierData virtualModifierData;
+               ModifierData *md = modifiers_getVirtualModifierList(ob, &virtualModifierData);
                Mesh *me = (Mesh *)ob->data;
 
                for (; md; md = md->next) {
index 964fa11b0a24a0344d999cf52a894fb17e91e349..38cbd95b61fba138cf0bf6baf9530757b10241cb 100644 (file)
@@ -177,18 +177,14 @@ typedef struct Curve {
        struct BoundBox *bb;
        
        ListBase nurb;          /* actual data, called splines in rna */
-       ListBase disp;          /* undeformed display list, used mostly for texture space calculation */
        
        EditNurb *editnurb;     /* edited data, not in file, use pointer so we can check for it */
        
        struct Object *bevobj, *taperobj, *textoncurve;
        struct Ipo *ipo    DNA_DEPRECATED;  /* old animation system, deprecated for 2.5 */
-       Path *path;
        struct Key *key;
        struct Material **mat;
        
-       ListBase bev;
-       
        /* texture space, copied as one block in editobject.c */
        float loc[3];
        float size[3];
index de34f101c3155c11a1eb44c0632f95314371560a..1e844d2a6fb9b0e46739adc5a113582e2deb4cd6 100644 (file)
@@ -130,7 +130,6 @@ typedef struct Object {
        
        ListBase constraintChannels  DNA_DEPRECATED; // XXX deprecated... old animation system
        ListBase effect  DNA_DEPRECATED;             // XXX deprecated... keep for readfile
-       ListBase disp;      /* list of DispList, used by lattice, metaballs curve & surfaces */
        ListBase defbase;   /* list of bDeformGroup (vertex groups) names and flag only */
        ListBase modifiers; /* list of ModifierData structures */
 
@@ -276,6 +275,9 @@ typedef struct Object {
        struct RigidBodyCon *rigidbody_constraint;      /* settings for Bullet constraint */
 
        float ima_ofs[2];               /* offset for image empties */
+
+       /* Runtime valuated curve-specific data, not stored in the file */
+       struct CurveCache *curve_cache;
 } Object;
 
 /* Warning, this is not used anymore because hooks are now modifiers */
index 5e877ed697b35a43cb0dee974d7c1847a61b867c..ac38578b981b8e1b9907d9c661860352405385e2 100644 (file)
@@ -428,7 +428,8 @@ typedef struct RenderData {
         * Render to image editor, fullscreen or to new window.
         */
        short displaymode;
-       short pad7;
+       char use_lock_interface;
+       char pad7;
 
        /**
         * Flags for render settings. Use bit-masking to access the settings.
index 27aef3b8ec63715969d37b88dfa05bdc4dd999d8..29fac36ddd078030b854496a8c44a605704b2474 100644 (file)
@@ -151,6 +151,9 @@ typedef struct wmWindowManager {
 
        ListBase timers;                                        /* active timers */
        struct wmTimer *autosavetimer;          /* timer for auto save */
+
+       char is_interface_locked;               /* indicates whether interface is locked for user interaction */
+       char par[7];
 } wmWindowManager;
 
 /* wmWindowManager.initialized */
index 4c652770e3f89a5a9ea685f51b6efaffbebe9749..5d69ccd2d3f64199b3b0755e59f0bdfe427689ae 100644 (file)
@@ -359,8 +359,13 @@ Mesh *rna_Main_meshes_new_from_object(
                                BKE_mesh_from_metaball(&disp, tmpmesh);
                                BKE_displist_free(&disp);
                        }
-                       else
-                               BKE_mesh_from_metaball(&ob->disp, tmpmesh);
+                       else {
+                               ListBase disp = {NULL, NULL};
+                               if (ob->curve_cache) {
+                                       disp = ob->curve_cache->disp;
+                               }
+                               BKE_mesh_from_metaball(&disp, tmpmesh);
+                       }
 
                        break;
 
index 5ae4400a19cdd2f7f8064890d398f205794945eb..cefb812f0cf540be5d8a507b1550f46364870cd2 100644 (file)
@@ -4521,7 +4521,12 @@ 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, "use_lock_interface", PROP_BOOLEAN, PROP_NONE);
+       RNA_def_property_boolean_sdna(prop, NULL, "use_lock_interface", 1);
+       RNA_def_property_ui_text(prop, "Lock Interface", "Lock interface during rendering in favor of giving more memory to the renderer");
+       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",
index e09fa18ffc5ff85a53d24f676a78475264788031..3478ec6e3b4221c4914147a5d468e2fd0a8e1b79 100644 (file)
@@ -50,6 +50,7 @@
 
 #include "BKE_cdderivedmesh.h"
 #include "BKE_displist.h"
+#include "BKE_curve.h"
 #include "BKE_mesh.h"
 #include "BKE_modifier.h"
 #include "BKE_object.h"
@@ -387,12 +388,12 @@ static DerivedMesh *arrayModifier_doArray(ArrayModifierData *amd,
                        BKE_object_to_mat3(amd->curve_ob, tmp_mat);
                        scale = mat3_to_scale(tmp_mat);
                                
-                       if (!cu->path) {
+                       if (!amd->curve_ob->curve_cache || !amd->curve_ob->curve_cache->path) {
                                cu->flag |= CU_PATH; // needed for path & bevlist
                                BKE_displist_make_curveTypes(scene, amd->curve_ob, 0);
                        }
-                       if (cu->path)
-                               length = scale * cu->path->totdist;
+                       if (amd->curve_ob->curve_cache->path)
+                               length = scale * amd->curve_ob->curve_cache->path->totdist;
                }
        }
 
index 7cb24daaaefa55287a522e75303881d108f4b052..d293ca07c5a9f34186412362dcdb5c88f5dea643 100644 (file)
@@ -423,6 +423,9 @@ void        WM_main_playanim(int argc, const char **argv);
 /* debugging only, convenience function to write on crash */
 int write_crash_blend(void);
 
+                       /* Lock the interface for any communication */
+void        WM_set_locked_interface(struct wmWindowManager *wm, bool lock);
+
 #ifdef __cplusplus
 }
 #endif
index f1932c8aa97f2bbb6a205482150c2403765d581d..2364c4b13bb71ad78f53d54732224d1093275400 100644 (file)
@@ -133,6 +133,7 @@ struct ImBuf;
                                                                 * and don't make sense to be accessed from the
                                                                 * search menu, even if poll() returns TRUE.
                                                                 * currently only used for the search toolbox */
+#define OPTYPE_ALLOW_LOCKED    128     /* Allow operator to run when interface is locked */
 
 /* context to call operator in for WM_operator_name_call */
 /* rna_ui.c contains EnumPropertyItem's of these, keep in sync */
index dc2f19eded72f7e0b6e39bccac4770b085633277..4df3557b3eaf500f20f981c8b82aac65003fe67c 100644 (file)
@@ -1475,6 +1475,22 @@ static void wm_event_modalkeymap(const bContext *C, wmOperator *op, wmEvent *eve
        }
 }
 
+/* Check whether operator is allowed to run in case interface is locked,
+ * If interface is unlocked, will always return truth.
+ */
+static bool wm_operator_check_locked_interface(bContext *C, wmOperatorType *ot)
+{
+       wmWindowManager *wm = CTX_wm_manager(C);
+
+       if (wm->is_interface_locked) {
+               if ((ot->flag & OPTYPE_ALLOW_LOCKED) == 0) {
+                       return false;
+               }
+       }
+
+       return true;
+}
+
 /* bad hacking event system... better restore event type for checking of KM_CLICK for example */
 /* XXX modal maps could use different method (ton) */
 static void wm_event_modalmap_end(wmEvent *event)
@@ -1501,7 +1517,12 @@ static int wm_handler_operator_call(bContext *C, ListBase *handlers, wmEventHand
                wmOperator *op = handler->op;
                wmOperatorType *ot = op->type;
 
-               if (ot->modal) {
+               if (!wm_operator_check_locked_interface(C, ot)) {
+                       /* Interface is locked and pperator is not allowed to run,
+                        * nothing to do in this case.
+                        */
+               }
+               else if (ot->modal) {
                        /* we set context to where modal handler came from */
                        wmWindowManager *wm = CTX_wm_manager(C);
                        ScrArea *area = CTX_wm_area(C);
@@ -1573,7 +1594,9 @@ static int wm_handler_operator_call(bContext *C, ListBase *handlers, wmEventHand
                wmOperatorType *ot = WM_operatortype_find(event->keymap_idname, 0);
 
                if (ot) {
-                       retval = wm_operator_invoke(C, ot, event, properties, NULL, FALSE);
+                       if (wm_operator_check_locked_interface(C, ot)) {
+                               retval = wm_operator_invoke(C, ot, event, properties, NULL, FALSE);
+                       }
                }
        }
        /* Finished and pass through flag as handled */
@@ -1779,7 +1802,11 @@ static int wm_handlers_do_intern(bContext *C, wmEvent *event, ListBase *handlers
                /* comment this out to flood the console! (if you really want to test) */
                !ELEM(event->type, MOUSEMOVE, INBETWEEN_MOUSEMOVE)
                ;
+#    define PRINT if (do_debug_handler) printf
+#else
+#  define PRINT(format, ...)
 #endif
+
        wmWindowManager *wm = CTX_wm_manager(C);
        wmEventHandler *handler, *nexthandler;
        int action = WM_HANDLER_CONTINUE;
@@ -1815,28 +1842,16 @@ static int wm_handlers_do_intern(bContext *C, wmEvent *event, ListBase *handlers
                                wmKeyMap *keymap = WM_keymap_active(wm, handler->keymap);
                                wmKeyMapItem *kmi;
 
-#ifndef NDEBUG
-                               if (do_debug_handler) {
-                                       printf("%s:   checking '%s' ...", __func__, keymap->idname);
-                               }
-#endif
+                               PRINT("%s:   checking '%s' ...", __func__, keymap->idname);
 
                                if (!keymap->poll || keymap->poll(C)) {
 
-#ifndef NDEBUG
-                                       if (do_debug_handler) {
-                                               printf("pass\n");
-                                       }
-#endif
+                                       PRINT("pass\n");
 
                                        for (kmi = keymap->items.first; kmi; kmi = kmi->next) {
                                                if (wm_eventmatch(event, kmi)) {
 
-#ifndef NDEBUG
-                                                       if (do_debug_handler) {
-                                                               printf("%s:     item matched '%s'\n", __func__, kmi->idname);
-                                                       }
-#endif
+                                                       PRINT("%s:     item matched '%s'\n", __func__, kmi->idname);
 
                                                        /* weak, but allows interactive callback to not use rawkey */
                                                        event->keymap_idname = kmi->idname;
@@ -1855,32 +1870,28 @@ static int wm_handlers_do_intern(bContext *C, wmEvent *event, ListBase *handlers
                                                                        if (G.debug & (G_DEBUG_EVENTS | G_DEBUG_HANDLERS))
                                                                                printf("%s:       handled - and pass on! '%s'\n", __func__, kmi->idname);
                                                                
-#ifndef NDEBUG
-                                                               if (do_debug_handler) {
-                                                                       printf("%s:       un-handled '%s'...", __func__, kmi->idname);
-                                                               }
-#endif
+                                                                       PRINT("%s:       un-handled '%s'...", __func__, kmi->idname);
                                                        }
                                                }
                                        }
                                }
                                else {
-#ifndef NDEBUG
-                                       if (do_debug_handler) {
-                                               printf("fail\n");
-                                       }
-#endif
+                                       PRINT("fail\n");
                                }
                        }
                        else if (handler->ui_handle) {
-                               action |= wm_handler_ui_call(C, handler, event, always_pass);
+                               if (!wm->is_interface_locked) {
+                                       action |= wm_handler_ui_call(C, handler, event, always_pass);
+                               }
                        }
                        else if (handler->type == WM_HANDLER_FILESELECT) {
-                               /* screen context changes here */
-                               action |= wm_handler_fileselect_call(C, handlers, handler, event);
+                               if (!wm->is_interface_locked) {
+                                       /* screen context changes here */
+                                       action |= wm_handler_fileselect_call(C, handlers, handler, event);
+                               }
                        }
                        else if (handler->dropboxes) {
-                               if (event->type == EVT_DROP) {
+                               if (!wm->is_interface_locked && event->type == EVT_DROP) {
                                        wmDropBox *drop = handler->dropboxes->first;
                                        for (; drop; drop = drop->next) {
                                                /* other drop custom types allowed */
@@ -1946,6 +1957,8 @@ static int wm_handlers_do_intern(bContext *C, wmEvent *event, ListBase *handlers
        if (action == (WM_HANDLER_BREAK | WM_HANDLER_MODAL))
                wm_cursor_arrow_move(CTX_wm_window(C), event);
 
+#undef PRINT
+
        return action;
 }
 
@@ -3255,3 +3268,24 @@ void wm_event_add_ghostevent(wmWindowManager *wm, wmWindow *win, int type, int U
        WM_event_print(&event);
 #endif
 }
+
+void WM_set_locked_interface(wmWindowManager *wm, bool lock)
+{
+       /* This will prevent events from being handled while interface is locked
+        *
+        * Use a "local" flag for now, because currently no other areas could
+        * benefit of locked interface anyway (aka using G.is_interface_locked
+        * wouldn't be useful anywhere outside of window manager, so let's not
+        * pollute global context with such an information for now).
+        */
+       wm->is_interface_locked = lock ? 1 : 0;
+
+       /* This will prevent drawing regions which uses non-threadsafe data.
+        * Currently it'll be just a 3D viewport.
+        *
+        * TODO(sergey): Make it different locked states, so different jobs
+        *               could lock different areas of blender and allow
+        *               interation with others?
+        */
+       BKE_spacedata_draw_locks(lock);
+}
index 4dea09ee433f96c5379d03e6e5d5db71f9e6ddbf..32502e2bcb0fcc4ea58299dca7e7537bbc4f53d3 100644 (file)
@@ -92,6 +92,7 @@
 #include "BKE_library.h"
 #include "BKE_main.h"
 #include "BKE_material.h"
+#include "BKE_modifier.h"
 #include "BKE_packedFile.h"
 #include "BKE_scene.h"
 #include "BKE_node.h"
@@ -1517,6 +1518,7 @@ int main(int argc, const char **argv)
 
        IMB_init();
        BKE_images_init();
+       BKE_modifier_init();
 
        BKE_brush_system_init();
 
index 2c642d4bd0484ba849182de950e553412fbdddd1..69137bc7842ea1ac34aea88ee4635df2f87479e6 100644 (file)
@@ -64,6 +64,7 @@ extern "C"
 #include "BKE_node.h"
 #include "BKE_report.h"
 #include "BKE_library.h"
+#include "BKE_modifier.h"
 #include "BLI_threads.h"
 #include "BLI_blenlib.h"
 #include "DNA_scene_types.h"
@@ -448,6 +449,7 @@ int main(int argc, char** argv)
 
        IMB_init();
        BKE_images_init();
+       BKE_modifier_init();
 
 #ifdef WITH_FFMPEG
        IMB_ffmpeg_init();