diff options
author | Brecht Van Lommel <brechtvanlommel@gmail.com> | 2018-07-10 00:33:20 +0300 |
---|---|---|
committer | Brecht Van Lommel <brechtvanlommel@gmail.com> | 2018-07-10 00:57:19 +0300 |
commit | 8373544df30a0e24b080a03c4d4c0b5108c4932d (patch) | |
tree | 70a25bd48e8573710aa9a14ba02b925644f125c3 /source/blender/windowmanager/intern/wm_window.c | |
parent | 845899d373df4fa5e692c828d6af151309169c87 (diff) |
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.
Diffstat (limited to 'source/blender/windowmanager/intern/wm_window.c')
-rw-r--r-- | source/blender/windowmanager/intern/wm_window.c | 83 |
1 files changed, 46 insertions, 37 deletions
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); } } |