Partial fix for T37604: Deadlock when stopping rendered viewport (Blender Internal)
[blender.git] / source / blender / editors / space_view3d / space_view3d.c
index d332fb9f8b3cc599f8c9a30d2f01212b913eb368..03b89972e559d52c39aaad429bd127728f4495b6 100644 (file)
 
 #include "BLI_blenlib.h"
 #include "BLI_math.h"
-#include "BLI_rand.h"
 #include "BLI_utildefines.h"
 
 #include "BKE_context.h"
 #include "BKE_icons.h"
+#include "BKE_main.h"
 #include "BKE_object.h"
+#include "BKE_scene.h"
 #include "BKE_screen.h"
 
 #include "ED_render.h"
 #include "WM_types.h"
 
 #include "RE_engine.h"
+#include "RE_pipeline.h"
 
 #include "RNA_access.h"
 
 #include "UI_resources.h"
 
+#ifdef WITH_PYTHON
+#  include "BPY_extern.h"
+#endif
+
 #include "view3d_intern.h"  /* own include */
 
 /* ******************** manage regions ********************* */
@@ -159,12 +165,12 @@ RegionView3D *ED_view3d_context_rv3d(bContext *C)
 
 /* ideally would return an rv3d but in some cases the region is needed too
  * so return that, the caller can then access the ar->regiondata */
-int ED_view3d_context_user_region(bContext *C, View3D **v3d_r, ARegion **ar_r)
+bool ED_view3d_context_user_region(bContext *C, View3D **r_v3d, ARegion **r_ar)
 {
        ScrArea *sa = CTX_wm_area(C);
 
-       *v3d_r = NULL;
-       *ar_r = NULL;
+       *r_v3d = NULL;
+       *r_ar = NULL;
 
        if (sa && sa->spacetype == SPACE_VIEW3D) {
                ARegion *ar = CTX_wm_region(C);
@@ -173,9 +179,9 @@ int ED_view3d_context_user_region(bContext *C, View3D **v3d_r, ARegion **ar_r)
                if (ar) {
                        RegionView3D *rv3d = ar->regiondata;
                        if (rv3d && rv3d->viewlock == 0) {
-                               *v3d_r = v3d;
-                               *ar_r = ar;
-                               return 1;
+                               *r_v3d = v3d;
+                               *r_ar = ar;
+                               return true;
                        }
                        else {
                                ARegion *ar_unlock_user = NULL;
@@ -196,21 +202,21 @@ int ED_view3d_context_user_region(bContext *C, View3D **v3d_r, ARegion **ar_r)
 
                                /* camera/perspective view get priority when the active region is locked */
                                if (ar_unlock_user) {
-                                       *v3d_r = v3d;
-                                       *ar_r = ar_unlock_user;
-                                       return 1;
+                                       *r_v3d = v3d;
+                                       *r_ar = ar_unlock_user;
+                                       return true;
                                }
 
                                if (ar_unlock) {
-                                       *v3d_r = v3d;
-                                       *ar_r = ar_unlock;
-                                       return 1;
+                                       *r_v3d = v3d;
+                                       *r_ar = ar_unlock;
+                                       return true;
                                }
                        }
                }
        }
 
-       return 0;
+       return false;
 }
 
 /* Most of the time this isn't needed since you could assume the view matrix was
@@ -227,8 +233,8 @@ int ED_view3d_context_user_region(bContext *C, View3D **v3d_r, ARegion **ar_r)
 void ED_view3d_init_mats_rv3d(struct Object *ob, struct RegionView3D *rv3d)
 {
        /* local viewmat and persmat, to calculate projections */
-       mult_m4_m4m4(rv3d->viewmatob, rv3d->viewmat, ob->obmat);
-       mult_m4_m4m4(rv3d->persmatob, rv3d->persmat, ob->obmat);
+       mul_m4_m4m4(rv3d->viewmatob, rv3d->viewmat, ob->obmat);
+       mul_m4_m4m4(rv3d->persmatob, rv3d->persmat, ob->obmat);
 
        /* initializes object space clipping, speeds up clip tests */
        ED_view3d_clipping_local(rv3d, ob->obmat);
@@ -244,6 +250,57 @@ void ED_view3d_init_mats_rv3d_gl(struct Object *ob, struct RegionView3D *rv3d)
        glMultMatrixf(ob->obmat);
 }
 
+#ifdef DEBUG
+/* ensure we correctly initialize */
+void ED_view3d_clear_mats_rv3d(struct RegionView3D *rv3d)
+{
+       zero_m4(rv3d->viewmatob);
+       zero_m4(rv3d->persmatob);
+}
+
+void ED_view3d_check_mats_rv3d(struct RegionView3D *rv3d)
+{
+       BLI_ASSERT_ZERO_M4(rv3d->viewmatob);
+       BLI_ASSERT_ZERO_M4(rv3d->persmatob);
+}
+#endif
+
+static void view3d_stop_render_preview(wmWindowManager *wm, ARegion *ar)
+{
+       RegionView3D *rv3d = ar->regiondata;
+
+       if (rv3d->render_engine) {
+#ifdef WITH_PYTHON
+               BPy_BEGIN_ALLOW_THREADS;
+#endif
+
+               WM_jobs_kill_type(wm, ar, WM_JOB_TYPE_RENDER_PREVIEW);
+
+#ifdef WITH_PYTHON
+               BPy_END_ALLOW_THREADS;
+#endif
+
+               if (rv3d->render_engine->re)
+                       RE_Database_Free(rv3d->render_engine->re);
+               RE_engine_free(rv3d->render_engine);
+               rv3d->render_engine = NULL;
+       }
+}
+
+void ED_view3d_shade_update(Main *bmain, View3D *v3d, ScrArea *sa)
+{
+       wmWindowManager *wm = bmain->wm.first;
+
+       if (v3d->drawtype != OB_RENDER) {
+               ARegion *ar;
+
+               for (ar = sa->regionbase.first; ar; ar = ar->next) {
+                       if (ar->regiondata)
+                               view3d_stop_render_preview(wm, ar);
+               }
+       }
+}
+
 /* ******************** default callbacks for view3d space ***************** */
 
 static SpaceLink *view3d_new(const bContext *C)
@@ -366,11 +423,10 @@ static SpaceLink *view3d_duplicate(SpaceLink *sl)
        
 // XXX BIF_view3d_previewrender_free(v3do);
        
-       if (v3do->localvd) {
-               v3do->localvd = NULL;
-               v3do->properties_storage = NULL;
-               v3do->lay = v3dn->localvd->lay;
-               v3do->lay &= 0xFFFFFF;
+       if (v3dn->localvd) {
+               v3dn->localvd = NULL;
+               v3dn->properties_storage = NULL;
+               v3dn->lay = v3do->localvd->lay & 0xFFFFFF;
        }
 
        if (v3dn->drawtype == OB_RENDER)
@@ -471,14 +527,11 @@ static void view3d_main_area_init(wmWindowManager *wm, ARegion *ar)
        
 }
 
-static void view3d_main_area_exit(wmWindowManager *UNUSED(wm), ARegion *ar)
+static void view3d_main_area_exit(wmWindowManager *wm, ARegion *ar)
 {
        RegionView3D *rv3d = ar->regiondata;
 
-       if (rv3d->render_engine) {
-               RE_engine_free(rv3d->render_engine);
-               rv3d->render_engine = NULL;
-       }
+       view3d_stop_render_preview(wm, ar);
 
        if (rv3d->gpuoffscreen) {
                GPU_offscreen_free(rv3d->gpuoffscreen);
@@ -696,8 +749,10 @@ static void view3d_recalc_used_layers(ARegion *ar, wmNotifier *wmn, Scene *scene
        }
 }
 
-static void view3d_main_area_listener(ARegion *ar, wmNotifier *wmn)
+static void view3d_main_area_listener(bScreen *sc, ScrArea *sa, ARegion *ar, wmNotifier *wmn)
 {
+       Scene *scene = sc->scene;
+       View3D *v3d = sa->spacedata.first;
        
        /* context changes */
        switch (wmn->category) {
@@ -732,6 +787,7 @@ static void view3d_main_area_listener(ARegion *ar, wmNotifier *wmn)
                                case ND_OB_VISIBLE:
                                case ND_LAYER:
                                case ND_RENDER_OPTIONS:
+                               case ND_MARKERS:
                                case ND_MODE:
                                        ED_region_tag_redraw(ar);
                                        break;
@@ -786,6 +842,16 @@ static void view3d_main_area_listener(ARegion *ar, wmNotifier *wmn)
                        break;
                case NC_MATERIAL:
                        switch (wmn->data) {
+                               case ND_SHADING:
+                               case ND_NODES:
+                                       if ((v3d->drawtype == OB_MATERIAL) ||
+                                           (v3d->drawtype == OB_TEXTURE &&
+                                                (scene->gm.matmode == GAME_MAT_GLSL ||
+                                                 BKE_scene_use_new_shading_nodes(scene))))
+                                       {
+                                               ED_region_tag_redraw(ar);
+                                       }
+                                       break;
                                case ND_SHADING_DRAW:
                                case ND_SHADING_LINKS:
                                        ED_region_tag_redraw(ar);
@@ -797,17 +863,17 @@ static void view3d_main_area_listener(ARegion *ar, wmNotifier *wmn)
                                case ND_WORLD_DRAW:
                                        /* handled by space_view3d_listener() for v3d access */
                                        break;
-                               case ND_WORLD_STARS:
-                               {
-                                       RegionView3D *rv3d = ar->regiondata;
-                                       if (rv3d->persp == RV3D_CAMOB) {
-                                               ED_region_tag_redraw(ar);
-                                       }
-                               }
                        }
                        break;
                case NC_LAMP:
                        switch (wmn->data) {
+                               case ND_LIGHTING:
+                                       if ((v3d->drawtype == OB_MATERIAL) ||
+                                           (v3d->drawtype == OB_TEXTURE && (scene->gm.matmode == GAME_MAT_GLSL)))
+                                       {
+                                               ED_region_tag_redraw(ar);
+                                       }
+                                       break;
                                case ND_LIGHTING_DRAW:
                                        ED_region_tag_redraw(ar);
                                        break;
@@ -851,8 +917,8 @@ static void view3d_main_area_listener(ARegion *ar, wmNotifier *wmn)
                                        /* screen was changed, need to update used layers due to NC_SCENE|ND_LAYER_CONTENT */
                                        /* updates used layers only for View3D in active screen */
                                        if (wmn->reference) {
-                                               bScreen *sc = wmn->reference;
-                                               view3d_recalc_used_layers(ar, wmn, sc->scene);
+                                               bScreen *sc_ref = wmn->reference;
+                                               view3d_recalc_used_layers(ar, wmn, sc_ref->scene);
                                        }
                                        ED_region_tag_redraw(ar);
                                        break;
@@ -894,7 +960,7 @@ static void view3d_header_area_draw(const bContext *C, ARegion *ar)
        ED_region_header(C, ar);
 }
 
-static void view3d_header_area_listener(ARegion *ar, wmNotifier *wmn)
+static void view3d_header_area_listener(bScreen *UNUSED(sc), ScrArea *UNUSED(sa), ARegion *ar, wmNotifier *wmn)
 {
        /* context changes */
        switch (wmn->category) {
@@ -935,7 +1001,7 @@ static void view3d_buttons_area_draw(const bContext *C, ARegion *ar)
        ED_region_panels(C, ar, 1, NULL, -1);
 }
 
-static void view3d_buttons_area_listener(ARegion *ar, wmNotifier *wmn)
+static void view3d_buttons_area_listener(bScreen *UNUSED(sc), ScrArea *UNUSED(sa), ARegion *ar, wmNotifier *wmn)
 {
        /* context changes */
        switch (wmn->category) {
@@ -1035,7 +1101,7 @@ static void view3d_tools_area_draw(const bContext *C, ARegion *ar)
        ED_region_panels(C, ar, 1, CTX_data_mode_string(C), -1);
 }
 
-static void view3d_props_area_listener(ARegion *ar, wmNotifier *wmn)
+static void view3d_props_area_listener(bScreen *UNUSED(sc), ScrArea *UNUSED(sa), ARegion *ar, wmNotifier *wmn)
 {
        /* context changes */
        switch (wmn->category) {
@@ -1055,7 +1121,7 @@ static void view3d_props_area_listener(ARegion *ar, wmNotifier *wmn)
 }
 
 /*area (not region) level listener*/
-static void space_view3d_listener(ScrArea *sa, struct wmNotifier *wmn)
+static void space_view3d_listener(bScreen *UNUSED(sc), ScrArea *sa, struct wmNotifier *wmn)
 {
        View3D *v3d = sa->spacedata.first;
 
@@ -1111,17 +1177,17 @@ const char *view3d_context_dir[] = {
 
 static int view3d_context(const bContext *C, const char *member, bContextDataResult *result)
 {
-       View3D *v3d = CTX_wm_view3d(C);
-       Scene *scene = CTX_data_scene(C);
-       Base *base;
        /* fallback to the scene layer, allows duplicate and other object operators to run outside the 3d view */
-       unsigned int lay = v3d ? v3d->lay : scene->lay;
 
        if (CTX_data_dir(member)) {
                CTX_data_dir_set(result, view3d_context_dir);
        }
        else if (CTX_data_equals(member, "selected_objects") || CTX_data_equals(member, "selected_bases")) {
-               int selected_objects = CTX_data_equals(member, "selected_objects");
+               View3D *v3d = CTX_wm_view3d(C);
+               Scene *scene = CTX_data_scene(C);
+               const unsigned int lay = v3d ? v3d->lay : scene->lay;
+               Base *base;
+               const bool selected_objects = CTX_data_equals(member, "selected_objects");
 
                for (base = scene->base.first; base; base = base->next) {
                        if ((base->flag & SELECT) && (base->lay & lay)) {
@@ -1137,7 +1203,11 @@ static int view3d_context(const bContext *C, const char *member, bContextDataRes
                return 1;
        }
        else if (CTX_data_equals(member, "selected_editable_objects") || CTX_data_equals(member, "selected_editable_bases")) {
-               int selected_editable_objects = CTX_data_equals(member, "selected_editable_objects");
+               View3D *v3d = CTX_wm_view3d(C);
+               Scene *scene = CTX_data_scene(C);
+               const unsigned int lay = v3d ? v3d->lay : scene->lay;
+               Base *base;
+               const bool selected_editable_objects = CTX_data_equals(member, "selected_editable_objects");
 
                for (base = scene->base.first; base; base = base->next) {
                        if ((base->flag & SELECT) && (base->lay & lay)) {
@@ -1155,7 +1225,11 @@ static int view3d_context(const bContext *C, const char *member, bContextDataRes
                return 1;
        }
        else if (CTX_data_equals(member, "visible_objects") || CTX_data_equals(member, "visible_bases")) {
-               int visible_objects = CTX_data_equals(member, "visible_objects");
+               View3D *v3d = CTX_wm_view3d(C);
+               Scene *scene = CTX_data_scene(C);
+               const unsigned int lay = v3d ? v3d->lay : scene->lay;
+               Base *base;
+               const bool visible_objects = CTX_data_equals(member, "visible_objects");
 
                for (base = scene->base.first; base; base = base->next) {
                        if (base->lay & lay) {
@@ -1171,7 +1245,11 @@ static int view3d_context(const bContext *C, const char *member, bContextDataRes
                return 1;
        }
        else if (CTX_data_equals(member, "selectable_objects") || CTX_data_equals(member, "selectable_bases")) {
-               int selectable_objects = CTX_data_equals(member, "selectable_objects");
+               View3D *v3d = CTX_wm_view3d(C);
+               Scene *scene = CTX_data_scene(C);
+               const unsigned int lay = v3d ? v3d->lay : scene->lay;
+               Base *base;
+               const bool selectable_objects = CTX_data_equals(member, "selectable_objects");
 
                for (base = scene->base.first; base; base = base->next) {
                        if (base->lay & lay) {
@@ -1187,6 +1265,9 @@ static int view3d_context(const bContext *C, const char *member, bContextDataRes
                return 1;
        }
        else if (CTX_data_equals(member, "active_base")) {
+               View3D *v3d = CTX_wm_view3d(C);
+               Scene *scene = CTX_data_scene(C);
+               const unsigned int lay = v3d ? v3d->lay : scene->lay;
                if (scene->basact && (scene->basact->lay & lay)) {
                        Object *ob = scene->basact->object;
                        /* if hidden but in edit mode, we still display, can happen with animation */
@@ -1197,6 +1278,9 @@ static int view3d_context(const bContext *C, const char *member, bContextDataRes
                return 1;
        }
        else if (CTX_data_equals(member, "active_object")) {
+               View3D *v3d = CTX_wm_view3d(C);
+               Scene *scene = CTX_data_scene(C);
+               const unsigned int lay = v3d ? v3d->lay : scene->lay;
                if (scene->basact && (scene->basact->lay & lay)) {
                        Object *ob = scene->basact->object;
                        if ((ob->restrictflag & OB_RESTRICT_VIEW) == 0 || (ob->mode & OB_MODE_EDIT))