Bugfix #26195
authorTon Roosendaal <ton@blender.org>
Fri, 25 Mar 2011 17:11:32 +0000 (17:11 +0000)
committerTon Roosendaal <ton@blender.org>
Fri, 25 Mar 2011 17:11:32 +0000 (17:11 +0000)
When rendering, during processing scene data, drawing in 3d window
is now locked. Can get extended to more areas in UI easily.

At least this solves all crashes with conflicting memory access in
render && 3d drawing. Deleting objects via operators or delete
modifiers isn't locked yet.

Also fixed: crash on quitting a renderwindow when it was rendering.

source/blender/blenkernel/BKE_screen.h
source/blender/blenkernel/intern/screen.c
source/blender/editors/render/render_internal.c
source/blender/editors/screen/area.c
source/blender/editors/space_view3d/space_view3d.c
source/blender/render/extern/include/RE_pipeline.h
source/blender/render/intern/include/render_types.h
source/blender/render/intern/source/pipeline.c
source/blender/windowmanager/intern/wm_window.c

index 0a7d9780a6bd5ebcda4e31a78a13503405176cad..56b0cd63e0109a07cf691bcc16df91e60c8505b3 100644 (file)
@@ -112,7 +112,7 @@ typedef struct SpaceType {
 typedef struct ARegionType {
        struct ARegionType *next, *prev;
        
-       int                     regionid;       /* unique identifier within this space */
+       int                     regionid;       /* unique identifier within this space, defines RGN_TYPE_xxxx */
        
        /* add handlers, stuff you only do once or on area/region type/size changes */
        void            (*init)(struct wmWindowManager *, struct ARegion *);
@@ -152,6 +152,8 @@ typedef struct ARegionType {
        int                     prefsizex, prefsizey;
        /* default keymaps to add */
        int                     keymapflag;
+       /* return without drawing. lock is set by region definition, and copied to do_lock by render. can become flag */
+       short           do_lock, lock;
 } ARegionType;
 
 /* panel types */
@@ -231,6 +233,7 @@ void BKE_spacetypes_free(void);     /* only for quitting blender */
 /* spacedata */
 void BKE_spacedata_freelist(ListBase *lb);
 void BKE_spacedata_copylist(ListBase *lb1, ListBase *lb2);
+void BKE_spacedata_draw_locks(int set);
 
 /* area/regions */
 struct ARegion *BKE_area_region_copy(struct SpaceType *st, struct ARegion *ar);
index d8219b61816ed43927112728361a953e620d6e3f..63e35408381eefe2ddf652c996cac34b80682941 100644 (file)
@@ -236,6 +236,26 @@ void BKE_spacedata_copylist(ListBase *lb1, ListBase *lb2)
        }
 }
 
+/* facility to set locks for drawing to survive (render) threads accessing drawing data */
+/* lock can become bitflag too */
+/* should be replaced in future by better local data handling for threads */
+void BKE_spacedata_draw_locks(int set)
+{
+       SpaceType *st;
+       
+       for(st= spacetypes.first; st; st= st->next) {
+               ARegionType *art;
+       
+               for(art= st->regiontypes.first; art; art= art->next) {
+                       if(set) 
+                               art->do_lock= art->lock;
+                       else 
+                               art->do_lock= 0;
+               }
+       }
+}
+
+
 /* not region itself */
 void BKE_area_region_free(SpaceType *st, ARegion *ar)
 {
@@ -395,3 +415,4 @@ void BKE_screen_view3d_main_sync(ListBase *screen_lb, Scene *scene)
                                        BKE_screen_view3d_sync((View3D*)sl, scene);
        }
 }
+
index 75c9846460172a2d545906612d0a877e66b9cd3a..a2d88cb2222570a0d911eb86956ace4858d68969 100644 (file)
@@ -53,6 +53,7 @@
 #include "BKE_multires.h"
 #include "BKE_report.h"
 #include "BKE_sequencer.h"
+#include "BKE_screen.h"
 
 #include "WM_api.h"
 #include "WM_types.h"
@@ -636,6 +637,13 @@ static int render_breakjob(void *rjv)
        return 0;
 }
 
+/* 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)
+{
+       BKE_spacedata_draw_locks(lock);
+}
+
 /* catch esc */
 static int screen_render_modal(bContext *C, wmOperator *UNUSED(op), wmEvent *event)
 {
@@ -769,6 +777,7 @@ static int screen_render_invoke(bContext *C, wmOperator *op, wmEvent *event)
        /* setup new render */
        re= RE_NewRender(scene->id.name);
        RE_test_break_cb(re, rj, render_breakjob);
+       RE_draw_lock_cb(re, rj, render_drawlock);
        RE_display_draw_cb(re, rj, image_rect_update);
        RE_stats_draw_cb(re, rj, image_renderinfo_cb);
        RE_progress_cb(re, rj, render_progress_update);
index 4a54b0ab0e460bc67ab0bda14e49f1c113117825..f272352c1831786b9366e139a9f1d0839e997c7d 100644 (file)
@@ -314,6 +314,10 @@ void ED_region_do_draw(bContext *C, ARegion *ar)
        ARegionType *at= ar->type;
        rcti winrct;
        
+       /* see BKE_spacedata_draw_locks() */
+       if(at->do_lock)
+               return;
+       
        /* checks other overlapping regions */
        region_scissor_winrct(ar, &winrct);
        
index 86b15a922a8e9cb72f7ef455fb108fd4e6394da3..5d75d6456950618682cf1799ac387dc42173883d 100644 (file)
@@ -1087,6 +1087,7 @@ void ED_spacetype_view3d(void)
        art->duplicate= view3d_main_area_duplicate;
        art->listener= view3d_main_area_listener;
        art->cursor= view3d_main_area_cursor;
+       art->lock= 1;   /* can become flag, see BKE_spacedata_draw_locks */
        BLI_addhead(&st->regiontypes, art);
        
        /* regions: listview/buttons */
index b64538cb45216b09c8485bc96c19f755ccaa9c66..4cc3207a05e3e088853cb1f8d3f96b6fa5f406d1 100644 (file)
@@ -239,6 +239,7 @@ void RE_display_clear_cb(struct Render *re, void *handle, void (*f)(void *handle
 void RE_display_draw_cb        (struct Render *re, void *handle, void (*f)(void *handle, RenderResult *rr, volatile struct rcti *rect));
 void RE_stats_draw_cb  (struct Render *re, void *handle, void (*f)(void *handle, RenderStats *rs));
 void RE_progress_cb    (struct Render *re, void *handle, void (*f)(void *handle, float));
+void RE_draw_lock_cb           (struct Render *re, void *handle, void (*f)(void *handle, int));
 void RE_test_break_cb  (struct Render *re, void *handle, int (*f)(void *handle));
 void RE_error_cb               (struct Render *re, void *handle, void (*f)(void *handle, const char *str));
 
index 7a1d7190b83658ab3285110e6fe638023723e915..672b5080fbfab6629ebe56dbeb8bcff10fc314ed 100644 (file)
@@ -246,6 +246,8 @@ struct Render
        void (*progress)(void *handle, float i);
        void *prh;
        
+       void (*draw_lock)(void *handle, int i);
+       void *dlh;
        int (*test_break)(void *handle);
        void *tbh;
        
index 9511392116f76a2c486f9f8f959f67bc6321cfe9..68ed956781d61a27668ae03a1142c5c2a7b97120 100644 (file)
 
 #include "MEM_guardedalloc.h"
 
-#include "BKE_utildefines.h"
+#include "BKE_animsys.h"       /* <------ should this be here?, needed for sequencer update */
 #include "BKE_global.h"
 #include "BKE_image.h"
 #include "BKE_main.h"
 #include "BKE_node.h"
 #include "BKE_object.h"
+#include "BKE_pointcache.h"
 #include "BKE_report.h"
 #include "BKE_scene.h"
-#include "BKE_writeavi.h"      /* <------ should be replaced once with generic movie module */
 #include "BKE_sequencer.h"
-#include "BKE_pointcache.h"
-#include "BKE_animsys.h"       /* <------ should this be here?, needed for sequencer update */
+#include "BKE_utildefines.h"
+#include "BKE_writeavi.h"      /* <------ should be replaced once with generic movie module */
 
 #include "BLI_math.h"
 #include "BLI_blenlib.h"
@@ -1404,6 +1404,12 @@ void RE_progress_cb(Render *re, void *handle, void (*f)(void *handle, float))
        re->prh= handle;
 }
 
+void RE_draw_lock_cb(Render *re, void *handle, void (*f)(void *handle, int i))
+{
+       re->draw_lock= f;
+       re->tbh= handle;
+}
+
 void RE_test_break_cb(Render *re, void *handle, int (*f)(void *handle))
 {
        re->test_break= f;
@@ -1790,12 +1796,20 @@ static void do_render_3d(Render *re)
 //     re->cfra= cfra; /* <- unused! */
        re->scene->r.subframe = re->mblur_offs + re->field_offs;
        
+       /* lock drawing in UI during data phase */
+       if(re->draw_lock)
+               re->draw_lock(re->dlh, 1);
+       
        /* make render verts/faces/halos/lamps */
        if(render_scene_needs_vector(re))
                RE_Database_FromScene_Vectors(re, re->main, re->scene, re->lay);
        else
           RE_Database_FromScene(re, re->main, re->scene, re->lay, 1);
        
+       /* clear UI drawing locks */
+       if(re->draw_lock)
+               re->draw_lock(re->dlh, 0);
+       
        threaded_tile_processor(re);
        
        /* do left-over 3d post effects (flares) */
index a02ce3fe554ee2ff37ad9c32c4452860b5e4a67b..5cf2f8932f573a6f0faee30ea8d888e71ae64daa 100644 (file)
@@ -238,6 +238,8 @@ wmWindow *wm_window_copy(bContext *C, wmWindow *winorig)
 /* this is event from ghost, or exit-blender op */
 void wm_window_close(bContext *C, wmWindowManager *wm, wmWindow *win)
 {
+       bScreen *screen= win->screen;
+       
        BLI_remlink(&wm->windows, win);
        
        wm_draw_window_clear(win);
@@ -246,14 +248,14 @@ void wm_window_close(bContext *C, wmWindowManager *wm, wmWindow *win)
        WM_event_remove_handlers(C, &win->modalhandlers);
        ED_screen_exit(C, win, win->screen); 
        
-       /* if temp screen, delete it */
-       if(win->screen->temp) {
+       wm_window_free(C, wm, win);
+       
+       /* if temp screen, delete it after window free (it stops jobs that can access it) */
+       if(screen->temp) {
                Main *bmain= CTX_data_main(C);
-               free_libblock(&bmain->screen, win->screen);
+               free_libblock(&bmain->screen, screen);
        }
        
-       wm_window_free(C, wm, win);
-       
        /* check remaining windows */
        if(wm->windows.first) {
                for(win= wm->windows.first; win; win= win->next)