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)
1  2 
source/blender/blenkernel/intern/scene.c
source/blender/blenlib/BLI_threads.h
source/blender/editors/space_view3d/drawobject.c

index 3ccd7b6e67489010d45fe80783c2e49d68a72848,744a8247233ce316d4d94f8101da4c744d787886..0735ff63606c5c5a21db2207caf9b7b26dcc3dce
@@@ -57,7 -57,6 +57,7 @@@
  #include "BLI_callbacks.h"
  #include "BLI_string.h"
  #include "BLI_threads.h"
 +#include "BLI_task.h"
  
  #include "BLF_translation.h"
  
@@@ -749,7 -748,7 +749,7 @@@ void BKE_scene_unlink(Main *bmain, Scen
   */
  int BKE_scene_base_iter_next(SceneBaseIter *iter, Scene **scene, int val, Base **base, Object **ob)
  {
-       static ThreadVariable int in_next_object = 0;
+       static int in_next_object = 0;
        int run_again = 1;
        
        /* init */
@@@ -1163,235 -1162,32 +1163,235 @@@ static void scene_do_rb_simulation_recu
                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);
  
index 329cc2959ca4808a038ef5ac54f6226058b459e3,154986936a29f5416f2ba95d73b759e932ed96e4..d2ad8e3ec9f9ed3444289f4124b840891d7aa4da
@@@ -100,7 -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 */
@@@ -183,23 -182,6 +183,16 @@@ int BLI_thread_queue_size(ThreadQueue *
  void BLI_thread_queue_wait_finish(ThreadQueue *queue);
  void BLI_thread_queue_nowait(ThreadQueue *queue);
  
- /* Thread Local Storage */
- #ifdef _MSC_VER
- #  define ThreadVariable  __declspec(thread)
- #else
- #  define ThreadVariable  __thread
- #endif
 +/* 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 cef4e1880ab99b07ef84b43adc922f97c10aca0a,55e1fae38e48927ccdf74d9cd283dbe7220269d2..d5860606b65ee8d4d2cb278d2ad2cc9d3f95917c
@@@ -1900,9 -1900,9 +1900,9 @@@ static void drawlattice(Scene *scene, V
        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;
@@@ -2699,7 -2699,10 +2699,10 @@@ static void draw_em_measure_stats(ARegi
        const bool do_global = (v3d->flag & V3D_GLOBAL_STATS) != 0;
        const bool do_moving = (G.moving & G_TRANSFORM_EDIT) != 0;
        float clip_planes[4][4];
+       /* allow for displaying shape keys and deform mods */
+       DerivedMesh *dm = ((em->derivedFinal != NULL) &&
+                          (em->derivedFinal->type == DM_TYPE_EDITBMESH) &&
+                          (em->derivedFinal->deformedOnly != false)) ? em->derivedFinal : NULL;
        BMIter iter;
        int i;
  
  
                UI_GetThemeColor3ubv(TH_DRAWEXTRA_EDGELEN, col);
  
-               eed = BM_iter_new(&iter, em->bm, BM_EDGES_OF_MESH, NULL);
-               for (; eed; eed = BM_iter_step(&iter)) {
+               if (dm) {
+                       BM_mesh_elem_index_ensure(em->bm, BM_VERT);
+               }
+               BM_ITER_MESH (eed, &iter, em->bm, BM_EDGES_OF_MESH) {
                        /* draw selected edges, or edges next to selected verts while draging */
                        if (BM_elem_flag_test(eed, BM_ELEM_SELECT) ||
                            (do_moving && (BM_elem_flag_test(eed->v1, BM_ELEM_SELECT) ||
                                           BM_elem_flag_test(eed->v2, BM_ELEM_SELECT))))
                        {
+                               float v1_clip[3], v2_clip[3];
  
-                               copy_v3_v3(v1, eed->v1->co);
-                               copy_v3_v3(v2, eed->v2->co);
+                               if (dm) {
+                                       dm->getVertCo(dm, BM_elem_index_get(eed->v1), v1);
+                                       dm->getVertCo(dm, BM_elem_index_get(eed->v2), v2);
+                               }
+                               else {
+                                       copy_v3_v3(v1, eed->v1->co);
+                                       copy_v3_v3(v2, eed->v2->co);
+                               }
  
-                               if (clip_segment_v3_plane_n(v1, v2, clip_planes, 4)) {
+                               copy_v3_v3(v1_clip, v1);
+                               copy_v3_v3(v2_clip, v2);
  
-                                       mid_v3_v3v3(vmid, v1, v2);
+                               if (clip_segment_v3_plane_n(v1_clip, v2_clip, clip_planes, 4)) {
  
-                                       copy_v3_v3(v1, eed->v1->co);
-                                       copy_v3_v3(v2, eed->v2->co);
+                                       mid_v3_v3v3(vmid, v1_clip, v2_clip);
  
                                        if (do_global) {
                                                mul_mat3_m4_v3(ob->obmat, v1);
  
                UI_GetThemeColor3ubv(TH_DRAWEXTRA_EDGEANG, col);
  
+               if (dm) {
+                       BM_mesh_elem_index_ensure(em->bm, BM_VERT | BM_FACE);
+               }
                // invert_m4_m4(ob->imat, ob->obmat);  // this is already called
  
-               eed = BM_iter_new(&iter, em->bm, BM_EDGES_OF_MESH, NULL);
-               for (; eed; eed = BM_iter_step(&iter)) {
+               BM_ITER_MESH (eed, &iter, em->bm, BM_EDGES_OF_MESH) {
                        BMLoop *l_a, *l_b;
                        if (BM_edge_loop_pair(eed, &l_a, &l_b)) {
                                /* draw selected edges, or edges next to selected verts while draging */
                                                   BM_elem_flag_test(l_b->prev->v, BM_ELEM_SELECT)
                                                   )))
                                {
-                                       copy_v3_v3(v1, eed->v1->co);
-                                       copy_v3_v3(v2, eed->v2->co);
-                                       if (clip_segment_v3_plane_n(v1, v2, clip_planes, 4)) {
-                                               float angle;
-                                               mid_v3_v3v3(vmid, v1, v2);
+                                       float v1_clip[3], v2_clip[3];
  
+                                       if (dm) {
+                                               dm->getVertCo(dm, BM_elem_index_get(eed->v1), v1);
+                                               dm->getVertCo(dm, BM_elem_index_get(eed->v2), v2);
+                                       }
+                                       else {
                                                copy_v3_v3(v1, eed->v1->co);
                                                copy_v3_v3(v2, eed->v2->co);
+                                       }
  
-                                               if (do_global) {
-                                                       float no_a[3];
-                                                       float no_b[3];
+                                       copy_v3_v3(v1_clip, v1);
+                                       copy_v3_v3(v2_clip, v2);
+                                       if (clip_segment_v3_plane_n(v1_clip, v2_clip, clip_planes, 4)) {
+                                               float no_a[3], no_b[3];
+                                               float angle;
+                                               mid_v3_v3v3(vmid, v1_clip, v2_clip);
+                                               if (dm) {
+                                                       dm->getPolyNo(dm, BM_elem_index_get(l_a->f), no_a);
+                                                       dm->getPolyNo(dm, BM_elem_index_get(l_b->f), no_b);
+                                               }
+                                               else {
                                                        copy_v3_v3(no_a, l_a->f->no);
                                                        copy_v3_v3(no_b, l_b->f->no);
+                                               }
+                                               if (do_global) {
                                                        mul_mat3_m4_v3(ob->imat, no_a);
                                                        mul_mat3_m4_v3(ob->imat, no_b);
-                                                       angle = angle_v3v3(no_a, no_b);
-                                               }
-                                               else {
-                                                       angle = angle_normalized_v3v3(l_a->f->no, l_b->f->no);
+                                                       normalize_v3(no_a);
+                                                       normalize_v3(no_b);
                                                }
  
+                                               angle = angle_normalized_v3v3(no_a, no_b);
                                                BLI_snprintf(numstr, sizeof(numstr), "%.3f", is_rad ? angle : RAD2DEGF(angle));
  
                                                view3d_cached_text_draw_add(vmid, numstr, 0, txt_flag, col);
  
                UI_GetThemeColor3ubv(TH_DRAWEXTRA_FACEAREA, col);
                
+               if (dm) {
+                       BM_mesh_elem_index_ensure(em->bm, BM_VERT);
+               }
                f = NULL;
                area = 0.0;
                zero_v3(vmid);
                        }
  
                        f = l[0]->f;
-                       copy_v3_v3(v1, l[0]->v->co);
-                       copy_v3_v3(v2, l[1]->v->co);
-                       copy_v3_v3(v3, l[2]->v->co);
+                       if (dm) {
+                               dm->getVertCo(dm, BM_elem_index_get(l[0]->v), v1);
+                               dm->getVertCo(dm, BM_elem_index_get(l[1]->v), v2);
+                               dm->getVertCo(dm, BM_elem_index_get(l[2]->v), v3);
+                       }
+                       else {
+                               copy_v3_v3(v1, l[0]->v->co);
+                               copy_v3_v3(v2, l[1]->v->co);
+                               copy_v3_v3(v3, l[2]->v->co);
+                       }
                        add_v3_v3(vmid, v1);
                        add_v3_v3(vmid, v2);
                        add_v3_v3(vmid, v3);
  
                UI_GetThemeColor3ubv(TH_DRAWEXTRA_FACEANG, col);
  
+               if (dm) {
+                       BM_mesh_elem_index_ensure(em->bm, BM_VERT);
+               }
  
                BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) {
                        const int is_face_sel = BM_elem_flag_test(efa, BM_ELEM_SELECT);
                                BM_ITER_ELEM (loop, &liter, efa, BM_LOOPS_OF_FACE) {
                                        if (is_face_sel || (do_moving && BM_elem_flag_test(loop->v, BM_ELEM_SELECT))) {
                                                float angle;
+                                               float v2_local[3];
  
                                                /* lazy init center calc */
                                                if (is_first) {
-                                                       BM_face_calc_center_bounds(efa, vmid);
-                                                       /* Avoid triple matrix multiply every vertex for 'global' */
-                                                       if (do_global) {
-                                                               copy_v3_v3(v1, loop->prev->v->co);
-                                                               copy_v3_v3(v2, loop->v->co);
-                                                               mul_mat3_m4_v3(ob->obmat, v1);
-                                                               mul_mat3_m4_v3(ob->obmat, v2);
+                                                       if (dm) {
+                                                               BMLoop *l_iter, *l_first;
+                                                               float tvec[3];
+                                                               zero_v3(vmid);
+                                                               l_iter = l_first = BM_FACE_FIRST_LOOP(efa);
+                                                               do {
+                                                                       dm->getVertCo(dm, BM_elem_index_get(l_iter->v), tvec);
+                                                                       add_v3_v3(vmid, tvec);
+                                                               } while ((l_iter = l_iter->next) != l_first);
+                                                               mul_v3_fl(vmid, 1.0f / (float)efa->len);
+                                                       }
+                                                       else {
+                                                               BM_face_calc_center_bounds(efa, vmid);
                                                        }
                                                        is_first = false;
                                                }
  
-                                               if (do_global) {
+                                               if (dm) {
+                                                       dm->getVertCo(dm, BM_elem_index_get(loop->prev->v), v1);
+                                                       dm->getVertCo(dm, BM_elem_index_get(loop->v),       v2);
+                                                       dm->getVertCo(dm, BM_elem_index_get(loop->next->v), v3);
+                                               }
+                                               else {
+                                                       copy_v3_v3(v1, loop->prev->v->co);
+                                                       copy_v3_v3(v2, loop->v->co);
                                                        copy_v3_v3(v3, loop->next->v->co);
+                                               }
  
-                                                       mul_mat3_m4_v3(ob->obmat, v3);
+                                               copy_v3_v3(v2_local, v2);
  
-                                                       angle = angle_v3v3v3(v1, v2, v3);
-                                                       copy_v3_v3(v1, v2);
-                                                       copy_v3_v3(v2, v3);
-                                               }
-                                               else {
-                                                       angle = angle_v3v3v3(loop->prev->v->co, loop->v->co, loop->next->v->co);
+                                               if (do_global) {
+                                                       mul_mat3_m4_v3(ob->obmat, v1);
+                                                       mul_mat3_m4_v3(ob->obmat, v2);
+                                                       mul_mat3_m4_v3(ob->obmat, v3);
                                                }
  
+                                               angle = angle_v3v3v3(v1, v2, v3);
                                                BLI_snprintf(numstr, sizeof(numstr), "%.3f", is_rad ? angle : RAD2DEGF(angle));
-                                               interp_v3_v3v3(fvec, vmid, loop->v->co, 0.8f);
+                                               interp_v3_v3v3(fvec, vmid, v2_local, 0.8f);
                                                view3d_cached_text_draw_add(fvec, numstr, 0, txt_flag, col);
                                        }
                                }
@@@ -3885,7 -3946,7 +3946,7 @@@ static bool drawDispList_nobackface(Sce
                case OB_CURVE:
                        cu = ob->data;
  
 -                      lb = &ob->disp;
 +                      lb = &ob->curve_cache->disp;
  
                        if (solid) {
                                dl = lb->first;
                        break;
                case OB_SURF:
  
 -                      lb = &ob->disp;
 +                      lb = &ob->curve_cache->disp;
  
                        if (solid) {
                                dl = lb->first;
                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;
                                }
@@@ -5557,7 -5615,7 +5618,7 @@@ static void drawnurb(Scene *scene, View
        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;
@@@ -5980,7 -6038,7 +6041,7 @@@ static void draw_forcefield(Object *ob
        }
        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))
@@@ -6238,6 -6296,7 +6299,6 @@@ static void drawObjectSelect(Scene *sce
        glDepthMask(0);
        
        if (ELEM3(ob->type, OB_FONT, OB_CURVE, OB_SURF)) {
 -              Curve *cu = ob->data;
                DerivedMesh *dm = ob->derivedFinal;
                bool has_faces = false;
  
                        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;
                }
        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) {
@@@ -6289,7 -6348,8 +6350,7 @@@ static void draw_wire_extra(Scene *scen
                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;
  
                                        drawCurveDMWired(ob);
                                }
                                else {
 -                                      drawDispListwire(&ob->disp);
 +                                      drawDispListwire(&ob->curve_cache->disp);
                                }
  
                                if (ob->type == OB_CURVE)
                }
                else if (ob->type == OB_MBALL) {
                        if (BKE_mball_is_basis(ob)) {
 -                              drawDispListwire(&ob->disp);
 +                              drawDispListwire(&ob->curve_cache->disp);
                        }
                }
  
@@@ -6616,9 -6676,7 +6677,9 @@@ void draw_object(Scene *scene, ARegion 
        /* 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 */
                                        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);
                        }
  
                                        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)