Fix crash clicking in the 3D view on startup
authorCampbell Barton <ideasman42@gmail.com>
Tue, 30 Jul 2019 11:40:42 +0000 (21:40 +1000)
committerCampbell Barton <ideasman42@gmail.com>
Tue, 30 Jul 2019 11:43:40 +0000 (21:43 +1000)
Setting the 3D view cursor on startup could crash because the
viewport hasn't been assigned to the region.

source/blender/draw/DRW_engine.h
source/blender/draw/intern/draw_manager.c
source/blender/editors/space_view3d/view3d_draw.c
source/blender/windowmanager/WM_api.h
source/blender/windowmanager/intern/wm_draw.c

index 64a02f3931bb42f7118810f1e87ec8242e22e55a..e31200ae82f1b595f1063add16b7ae4b80b5de27 100644 (file)
@@ -129,7 +129,8 @@ void DRW_draw_select_loop(struct Depsgraph *depsgraph,
 void DRW_draw_depth_loop(struct Depsgraph *depsgraph,
                          struct ARegion *ar,
                          struct View3D *v3d,
-                         struct GPUViewport *viewport);
+                         struct GPUViewport *viewport,
+                         bool use_opengl_context);
 void DRW_draw_depth_loop_gpencil(struct Depsgraph *depsgraph,
                                  struct ARegion *ar,
                                  struct View3D *v3d,
index 320a6f6aaaafe24ec08d7fe7453a7f2ae395fa7f..af61063335bfd0c71673f519f560b60d5f036e8f 100644 (file)
@@ -2452,14 +2452,17 @@ static void drw_draw_depth_loop_imp(void)
 void DRW_draw_depth_loop(struct Depsgraph *depsgraph,
                          ARegion *ar,
                          View3D *v3d,
-                         GPUViewport *viewport)
+                         GPUViewport *viewport,
+                         bool use_opengl_context)
 {
   Scene *scene = DEG_get_evaluated_scene(depsgraph);
   RenderEngineType *engine_type = ED_view3d_engine_type(scene, v3d->shading.type);
   ViewLayer *view_layer = DEG_get_evaluated_view_layer(depsgraph);
   RegionView3D *rv3d = ar->regiondata;
 
-  DRW_opengl_context_enable();
+  if (use_opengl_context) {
+    DRW_opengl_context_enable();
+  }
 
   /* Reset before using it. */
   drw_state_prepare_clean_for_draw(&DST);
@@ -2498,7 +2501,9 @@ void DRW_draw_depth_loop(struct Depsgraph *depsgraph,
 #endif
 
   /* Changin context */
-  DRW_opengl_context_disable();
+  if (use_opengl_context) {
+    DRW_opengl_context_disable();
+  }
 }
 
 /**
index eef36dae86a2c866f1e52b858bab321ae7dc7d23..9bbfee9f77170cc4262453ca6f8f01386c820e74 100644 (file)
@@ -803,13 +803,19 @@ void ED_view3d_draw_depth(Depsgraph *depsgraph, ARegion *ar, View3D *v3d, bool a
 
   GPU_depth_test(true);
 
+  /* Needed in cases the view-port isn't already setup. */
+  WM_draw_region_viewport_ensure(ar, SPACE_VIEW3D);
+  WM_draw_region_viewport_bind(ar);
+
   GPUViewport *viewport = WM_draw_region_get_viewport(ar, 0);
   /* When Blender is starting, a click event can trigger a depth test while the viewport is not
    * yet available. */
   if (viewport != NULL) {
-    DRW_draw_depth_loop(depsgraph, ar, v3d, viewport);
+    DRW_draw_depth_loop(depsgraph, ar, v3d, viewport, false);
   }
 
+  WM_draw_region_viewport_unbind(ar);
+
   if (rv3d->rflag & RV3D_CLIPPING) {
     ED_view3d_clipping_disable();
   }
index 04e3f7e88dca9f3b1fa8baab2c8c79b9d46031a0..fdf65d857fc4e26f049905484a5e9539acdd52a0 100644 (file)
@@ -741,6 +741,10 @@ void *WM_draw_cb_activate(struct wmWindow *win,
 void WM_draw_cb_exit(struct wmWindow *win, void *handle);
 void WM_redraw_windows(struct bContext *C);
 
+void WM_draw_region_viewport_ensure(struct ARegion *ar, short space_type);
+void WM_draw_region_viewport_bind(struct ARegion *ar);
+void WM_draw_region_viewport_unbind(struct ARegion *ar);
+
 /* Region drawing */
 void WM_draw_region_free(struct ARegion *ar);
 struct GPUViewport *WM_draw_region_get_viewport(struct ARegion *ar, int view);
index fc669c9543e0999e3b08073e2db3a8aa1dfd5b9b..3bcb955c2b296fd5a4d31b47b2357e3000dc5229 100644 (file)
@@ -239,9 +239,14 @@ static void wm_region_test_render_do_draw(const Scene *scene,
   }
 }
 
+static bool wm_region_use_viewport_by_type(short space_type, short region_type)
+{
+  return (ELEM(space_type, SPACE_VIEW3D, SPACE_IMAGE) && region_type == RGN_TYPE_WINDOW);
+}
+
 static bool wm_region_use_viewport(ScrArea *sa, ARegion *ar)
 {
-  return (ELEM(sa->spacetype, SPACE_VIEW3D, SPACE_IMAGE) && ar->regiontype == RGN_TYPE_WINDOW);
+  return wm_region_use_viewport_by_type(sa->spacetype, ar->regiontype);
 }
 
 /********************** draw all **************************/
@@ -976,3 +981,31 @@ void WM_redraw_windows(bContext *C)
   CTX_wm_area_set(C, area_prev);
   CTX_wm_region_set(C, ar_prev);
 }
+
+/* -------------------------------------------------------------------- */
+/** \name Region Viewport Drawing
+ *
+ * This is needed for viewport drawing for operator use
+ * (where the viewport may not have drawn yet).
+ *
+ * Otherwise avoid using these sine they're exposing low level logic externally.
+ *
+ * \{ */
+
+void WM_draw_region_viewport_ensure(ARegion *ar, short space_type)
+{
+  bool use_viewport = wm_region_use_viewport_by_type(space_type, ar->regiontype);
+  wm_draw_region_buffer_create(ar, false, use_viewport);
+}
+
+void WM_draw_region_viewport_bind(ARegion *ar)
+{
+  wm_draw_region_bind(ar, 0);
+}
+
+void WM_draw_region_viewport_unbind(ARegion *ar)
+{
+  wm_draw_region_unbind(ar, 0);
+}
+
+/** \} */