[Bf-blender-cvs] [8373544df30] blender2.8: Fix T55776: crash with multiple windows and reload new.

Brecht Van Lommel noreply at git.blender.org
Mon Jul 9 23:58:19 CEST 2018


Commit: 8373544df30a0e24b080a03c4d4c0b5108c4932d
Author: Brecht Van Lommel
Date:   Mon Jul 9 23:33:20 2018 +0200
Branches: blender2.8
https://developer.blender.org/rB8373544df30a0e24b080a03c4d4c0b5108c4932d

Fix T55776: crash with multiple windows and reload new.

There were a number of cases where immActivate() and immDeactivate() could
get out of sync, causing crashes due to using a freed mutex lock. Refactor
the code now to hopefully avoid this always.

===================================================================

M	intern/gawain/src/gwn_immediate.c
M	source/blender/makesrna/intern/rna_userdef.c
M	source/blender/windowmanager/intern/wm_files.c
M	source/blender/windowmanager/intern/wm_init_exit.c
M	source/blender/windowmanager/intern/wm_playanim.c
M	source/blender/windowmanager/intern/wm_window.c

===================================================================

diff --git a/intern/gawain/src/gwn_immediate.c b/intern/gawain/src/gwn_immediate.c
index c57564fce06..d43e52cc525 100644
--- a/intern/gawain/src/gwn_immediate.c
+++ b/intern/gawain/src/gwn_immediate.c
@@ -77,8 +77,6 @@ void immInit(void)
 
 	glBindBuffer(GL_ARRAY_BUFFER, 0);
 	initialized = true;
-
-	immActivate();
 	}
 
 void immActivate(void)
@@ -106,7 +104,6 @@ void immDeactivate(void)
 
 void immDestroy(void)
 	{
-	immDeactivate();
 	GWN_buf_id_free(imm.vbo_id);
 	initialized = false;
 	}
diff --git a/source/blender/makesrna/intern/rna_userdef.c b/source/blender/makesrna/intern/rna_userdef.c
index 9ac93efe347..f088ac9f442 100644
--- a/source/blender/makesrna/intern/rna_userdef.c
+++ b/source/blender/makesrna/intern/rna_userdef.c
@@ -143,17 +143,11 @@ static void rna_userdef_update(Main *UNUSED(bmain), Scene *UNUSED(scene), Pointe
 }
 
 /* also used by buffer swap switching */
-static void rna_userdef_dpi_update(Main *bmain, Scene *UNUSED(scene), PointerRNA *UNUSED(ptr))
+static void rna_userdef_dpi_update(Main *UNUSED(bmain), Scene *UNUSED(scene), PointerRNA *UNUSED(ptr))
 {
 	/* font's are stored at each DPI level, without this we can easy load 100's of fonts */
 	BLF_cache_clear();
 
-	/* force setting drawable again */
-	wmWindowManager *wm = bmain->wm.first;
-	if (wm) {
-		wm->windrawable = NULL;
-	}
-
 	WM_main_add_notifier(NC_WINDOW, NULL);      /* full redraw */
 	WM_main_add_notifier(NC_SCREEN | NA_EDITED, NULL);    /* refresh region sizes */
 }
diff --git a/source/blender/windowmanager/intern/wm_files.c b/source/blender/windowmanager/intern/wm_files.c
index 6b727a57370..0c3f4fb5181 100644
--- a/source/blender/windowmanager/intern/wm_files.c
+++ b/source/blender/windowmanager/intern/wm_files.c
@@ -186,13 +186,18 @@ static void wm_window_match_init(bContext *C, ListBase *wmlist)
 	ED_editors_exit(C);
 }
 
-static void wm_window_substitute_old(wmWindowManager *wm, wmWindow *oldwin, wmWindow *win)
+static void wm_window_substitute_old(wmWindowManager *oldwm, wmWindowManager *wm, wmWindow *oldwin, wmWindow *win)
 {
 	win->ghostwin = oldwin->ghostwin;
 	win->gwnctx = oldwin->gwnctx;
 	win->active = oldwin->active;
-	if (win->active)
+	if (win->active) {
 		wm->winactive = win;
+	}
+	if (oldwm->windrawable == oldwin) {
+		oldwm->windrawable = NULL;
+		wm->windrawable = win;
+	}
 
 	if (!G.background) /* file loading in background mode still calls this */
 		GHOST_SetWindowUserData(win->ghostwin, win);    /* pointer back */
@@ -281,13 +286,13 @@ static void wm_window_match_replace_by_file_wm(
 			if (oldwin->winid == win->winid) {
 				has_match = true;
 
-				wm_window_substitute_old(wm, oldwin, win);
+				wm_window_substitute_old(oldwm, wm, oldwin, win);
 			}
 		}
 	}
 	/* make sure at least one window is kept open so we don't lose the context, check T42303 */
 	if (!has_match) {
-		wm_window_substitute_old(wm, oldwm->windows.first, wm->windows.first);
+		wm_window_substitute_old(oldwm, wm, oldwm->windows.first, wm->windows.first);
 	}
 
 	wm_close_and_free_all(C, current_wm_list);
diff --git a/source/blender/windowmanager/intern/wm_init_exit.c b/source/blender/windowmanager/intern/wm_init_exit.c
index c1af7153b62..183e58e5a15 100644
--- a/source/blender/windowmanager/intern/wm_init_exit.c
+++ b/source/blender/windowmanager/intern/wm_init_exit.c
@@ -491,8 +491,6 @@ void WM_exit_ext(bContext *C, const bool do_python)
 #endif
 
 		GPU_free_unused_buffers(G_MAIN);
-
-		GPU_exit();
 	}
 
 	BKE_blender_free();  /* blender.c, does entire library and spacetypes */
@@ -515,6 +513,7 @@ void WM_exit_ext(bContext *C, const bool do_python)
 	if (opengl_is_init) {
 		GPU_pass_cache_free();
 		DRW_opengl_context_destroy();
+		GPU_exit();
 	}
 
 #ifdef WITH_INTERNATIONAL
diff --git a/source/blender/windowmanager/intern/wm_playanim.c b/source/blender/windowmanager/intern/wm_playanim.c
index ef7992dcb8c..003932930ed 100644
--- a/source/blender/windowmanager/intern/wm_playanim.c
+++ b/source/blender/windowmanager/intern/wm_playanim.c
@@ -1283,6 +1283,7 @@ static char *wm_main_playanim_intern(int argc, const char **argv)
 	/* initialize OpenGL immediate mode */
 	g_WS.gwn_context =  GWN_context_create();
 	GPU_init();
+	immActivate();
 
 	/* initialize the font */
 	BLF_init();
@@ -1551,8 +1552,6 @@ static char *wm_main_playanim_intern(int argc, const char **argv)
 
 	GPU_shader_free_builtin_shaders();
 
-	GPU_exit();
-
 	if (g_WS.gwn_context) {
 		GWN_context_active_set(g_WS.gwn_context);
 		GWN_context_discard(g_WS.gwn_context);
@@ -1561,6 +1560,9 @@ static char *wm_main_playanim_intern(int argc, const char **argv)
 
 	BLF_exit();
 
+	immDeactivate();
+	GPU_exit();
+
 	GHOST_DisposeWindow(g_WS.ghost_system, g_WS.ghost_window);
 
 	/* early exit, IMB and BKE should be exited only in end */
diff --git a/source/blender/windowmanager/intern/wm_window.c b/source/blender/windowmanager/intern/wm_window.c
index e4ccf074bab..4f86d05d515 100644
--- a/source/blender/windowmanager/intern/wm_window.c
+++ b/source/blender/windowmanager/intern/wm_window.c
@@ -122,6 +122,9 @@ static struct WMInitStruct {
 
 /* ******** win open & close ************ */
 
+static void wm_window_set_drawable(wmWindowManager *wm, wmWindow *win, bool activate);
+static void wm_window_clear_drawable(wmWindowManager *wm);
+
 /* XXX this one should correctly check for apple top header...
  * done for Cocoa : returns window contents (and not frame) max size*/
 void wm_get_screensize(int *r_width, int *r_height)
@@ -176,10 +179,19 @@ static void wm_window_check_position(rcti *rect)
 	if (rect->ymin < 0) rect->ymin = 0;
 }
 
-
 static void wm_ghostwindow_destroy(wmWindowManager *wm, wmWindow *win)
 {
 	if (win->ghostwin) {
+		if (win == wm->windrawable) {
+			/* Prevents non-drawable state of main windows (bugs #22967,
+			 * #25071 and possibly #22477 too). */
+			wm_window_clear_drawable(wm);
+		}
+
+		if (win == wm->winactive) {
+			wm->winactive = NULL;
+		}
+
 		/* We need this window's opengl context active to discard it. */
 		GHOST_ActivateWindowDrawingContext(win->ghostwin);
 		GWN_context_active_set(win->gwnctx);
@@ -191,9 +203,6 @@ static void wm_ghostwindow_destroy(wmWindowManager *wm, wmWindow *win)
 		win->ghostwin = NULL;
 		win->gwnctx = NULL;
 
-		/* prevents non-drawable state of main windows (bugs #22967 and #25071, possibly #22477 too) */
-		wm->windrawable = NULL;
-		wm->winactive = NULL;
 	}
 }
 
@@ -513,21 +522,8 @@ void wm_window_close(bContext *C, wmWindowManager *wm, wmWindow *win)
 		ED_screen_exit(C, win, screen);
 	}
 
-	if (win_other) {
-		BLF_batch_reset();
-		gpu_batch_presets_reset();
-		immDeactivate();
-	}
-
 	wm_window_free(C, wm, win);
 
-	/* keep imediatemode active before the next `wm_window_make_drawable` call */
-	if (win_other) {
-		GHOST_ActivateWindowDrawingContext(win_other->ghostwin);
-		GWN_context_active_set(win_other->gwnctx);
-		immActivate();
-	}
-
 	/* if temp screen, delete it after window free (it stops jobs that can access it) */
 	if (screen && screen->temp) {
 		Main *bmain = CTX_data_main(C);
@@ -646,19 +642,19 @@ static void wm_window_ghostwindow_add(wmWindowManager *wm, const char *title, wm
 	if (ghostwin) {
 		GHOST_RectangleHandle bounds;
 
-		/* XXX Fix crash when a new window is created.
-		 * However this should be move somewhere else. (fclem) */
-		BLF_batch_reset();
-		gpu_batch_presets_reset();
+		/* Clear drawable so we can set the new window. */
+		wm_window_clear_drawable(wm);
 
 		win->gwnctx = GWN_context_create();
 
-		/* the new window has already been made drawable upon creation */
-		wm->windrawable = win;
-
 		/* needed so we can detect the graphics card below */
 		GPU_init();
 
+		/* Set window as drawable upon creation. Note this has already been
+		 * it has already been activated by GHOST_CreateWindow. */
+		bool activate = false;
+		wm_window_set_drawable(wm, win, activate);
+
 		win->ghostwin = ghostwin;
 		GHOST_SetWindowUserData(ghostwin, win); /* pointer back */
 
@@ -1095,24 +1091,41 @@ static int query_qual(modifierKeyType qual)
 	return val;
 }
 
+static void wm_window_set_drawable(wmWindowManager *wm, wmWindow *win, bool activate)
+{
+	BLI_assert(ELEM(wm->windrawable, NULL, win));
+
+	wm->windrawable = win;
+	if (activate) {
+		GHOST_ActivateWindowDrawingContext(win->ghostwin);
+	}
+	GWN_context_active_set(win->gwnctx);
+	immActivate();
+}
+
+static void wm_window_clear_drawable(wmWindowManager *wm)
+{
+	if (wm->windrawable) {
+		BLF_batch_reset();
+		gpu_batch_presets_reset();
+		immDeactivate();
+		wm->windrawable = NULL;
+	}
+}
+
 void wm_window_make_drawable(wmWindowManager *wm, wmWindow *win)
 {
 	BLI_assert(GPU_framebuffer_current_get() == 0);
 
 	if (win != wm->windrawable && win->ghostwin) {
 //		win->lmbut = 0;	/* keeps hanging when mousepressed while other window opened */
+		wm_window_clear_drawable(wm);
 
-		wm->windrawable = win;
 		if (G.debug & G_DEBUG_EVENTS) {
 			printf("%s: set drawable %d\n", __func__, win->winid);
 		}
 
-		BLF_batch_reset();
-		gpu_batch_presets_reset();
-		immDeactivate();
-		GHOST_ActivateWindowDrawingContext(win->ghostwin);
-		GWN_context_active_set(win->gwnctx);
-		immActivate();
+		wm_window_set_drawable(wm, win, true);
 
 		/* this can change per window */
 		WM_window_set_dpi(win);
@@ -1132,12 +1145,8 @@ void wm_window_reset_drawable(void)
 	wmWindow *win = wm->windrawable;
 
 	if (win && win->ghostwin) {
-		BLF_batch_reset();
-		gpu_batch_presets_reset();
-		immDeactivate();
-		GHOST_ActivateWindowDrawingContext(win->ghostwin);
-		GWN_context_active_set(win->gwnctx);
-		immActivate();
+		wm_window_clear_drawable(wm);
+		wm_window_set_drawable(wm, win, true);
 	}
 }



More information about the Bf-blender-cvs mailing list