Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJulian Eisel <julian@blender.org>2020-08-10 18:29:35 +0300
committerJulian Eisel <julian@blender.org>2020-08-10 18:39:36 +0300
commit9c093a5d9ac43a103f81d91f9f32ec5efccaff6a (patch)
tree2c9cd1006bd111c315b977ee5cc0bb985333ae91 /source/blender/windowmanager
parentc0340ec89393055bbb0ba0432b9edb5d70b3711c (diff)
Fix T79324: Crash when changing View Layer while VR session runs
Proper handling of View Layers for the VR session was never implemented. Now the View Layer of the VR session follows the window the session was started in. Note that if this window is closed, we fallback to another window. This is done to avoid the overhead it would take to maintain a separate depsgraph for the VR view. Instead we always share some already visible View Layer (and hence the depsgraph).
Diffstat (limited to 'source/blender/windowmanager')
-rw-r--r--source/blender/windowmanager/intern/wm_operators.c3
-rw-r--r--source/blender/windowmanager/xr/intern/wm_xr_intern.h6
-rw-r--r--source/blender/windowmanager/xr/intern/wm_xr_session.c53
-rw-r--r--source/blender/windowmanager/xr/wm_xr.h2
4 files changed, 58 insertions, 6 deletions
diff --git a/source/blender/windowmanager/intern/wm_operators.c b/source/blender/windowmanager/intern/wm_operators.c
index d1f65b6271b..e14b59d77b2 100644
--- a/source/blender/windowmanager/intern/wm_operators.c
+++ b/source/blender/windowmanager/intern/wm_operators.c
@@ -3722,6 +3722,7 @@ static int wm_xr_session_toggle_exec(bContext *C, wmOperator *UNUSED(op))
{
Main *bmain = CTX_data_main(C);
wmWindowManager *wm = CTX_wm_manager(C);
+ wmWindow *win = CTX_wm_window(C);
View3D *v3d = CTX_wm_view3d(C);
/* Lazy-create xr context - tries to dynlink to the runtime, reading active_runtime.json. */
@@ -3730,7 +3731,7 @@ static int wm_xr_session_toggle_exec(bContext *C, wmOperator *UNUSED(op))
}
v3d->runtime.flag |= V3D_RUNTIME_XR_SESSION_ROOT;
- wm_xr_session_toggle(wm, wm_xr_session_update_screen_on_exit_cb);
+ wm_xr_session_toggle(wm, win, wm_xr_session_update_screen_on_exit_cb);
wm_xr_session_update_screen(bmain, &wm->xr);
WM_event_add_notifier(C, NC_WM | ND_XR_DATA_CHANGED, NULL);
diff --git a/source/blender/windowmanager/xr/intern/wm_xr_intern.h b/source/blender/windowmanager/xr/intern/wm_xr_intern.h
index c49e9e534b6..25e3da3ffb4 100644
--- a/source/blender/windowmanager/xr/intern/wm_xr_intern.h
+++ b/source/blender/windowmanager/xr/intern/wm_xr_intern.h
@@ -49,7 +49,11 @@ typedef struct wmXrSessionState {
typedef struct wmXrRuntimeData {
GHOST_XrContextHandle context;
- /* Although this struct is internal, RNA gets a handle to this for state information queries. */
+ /** The window the session was started in. Stored to be able to follow its view-layer. This may
+ * be an invalid reference, i.e. the window may have been closed. */
+ wmWindow *session_root_win;
+
+ /** Although this struct is internal, RNA gets a handle to this for state information queries. */
wmXrSessionState session_state;
wmXrSessionExitFn exit_fn;
} wmXrRuntimeData;
diff --git a/source/blender/windowmanager/xr/intern/wm_xr_session.c b/source/blender/windowmanager/xr/intern/wm_xr_session.c
index 4b991f69355..9c6b8e8fbda 100644
--- a/source/blender/windowmanager/xr/intern/wm_xr_session.c
+++ b/source/blender/windowmanager/xr/intern/wm_xr_session.c
@@ -19,7 +19,10 @@
*/
#include "BKE_context.h"
+#include "BKE_main.h"
+#include "BKE_scene.h"
+#include "BLI_listbase.h"
#include "BLI_math.h"
#include "DEG_depsgraph.h"
@@ -68,7 +71,9 @@ static void wm_xr_session_begin_info_create(wmXrData *xr_data,
r_begin_info->exit_customdata = xr_data;
}
-void wm_xr_session_toggle(wmWindowManager *wm, wmXrSessionExitFn session_exit_fn)
+void wm_xr_session_toggle(wmWindowManager *wm,
+ wmWindow *session_root_win,
+ wmXrSessionExitFn session_exit_fn)
{
wmXrData *xr_data = &wm->xr;
@@ -78,6 +83,7 @@ void wm_xr_session_toggle(wmWindowManager *wm, wmXrSessionExitFn session_exit_fn
else {
GHOST_XrSessionBeginInfo begin_info;
+ xr_data->runtime->session_root_win = session_root_win;
xr_data->runtime->session_state.is_started = true;
xr_data->runtime->exit_fn = session_exit_fn;
@@ -159,6 +165,43 @@ static void wm_xr_session_draw_data_populate(wmXrData *xr_data,
wm_xr_session_base_pose_calc(r_draw_data->scene, settings, &r_draw_data->base_pose);
}
+static wmWindow *wm_xr_session_root_window_or_fallback_get(const wmWindowManager *wm,
+ const wmXrRuntimeData *runtime_data)
+{
+ if (runtime_data->session_root_win &&
+ BLI_findindex(&wm->windows, runtime_data->session_root_win) != -1) {
+ /* Root window is still valid, use it. */
+ return runtime_data->session_root_win;
+ }
+ /* Otherwise, fallback. */
+ return wm->windows.first;
+}
+
+/**
+ * Get the scene and depsgraph shown in the VR session's root window (the window the session was
+ * started from) if still available. If it's not available, use some fallback window.
+ *
+ * It's important that the VR session follows some existing window, otherwise it would need to have
+ * an own depsgraph, which is an expense we should avoid.
+ */
+static void wm_xr_session_scene_and_evaluated_depsgraph_get(Main *bmain,
+ const wmWindowManager *wm,
+ Scene **r_scene,
+ Depsgraph **r_depsgraph)
+{
+ const wmWindow *root_win = wm_xr_session_root_window_or_fallback_get(wm, wm->xr.runtime);
+
+ /* Follow the scene & view layer shown in the root 3D View. */
+ Scene *scene = WM_window_get_active_scene(root_win);
+ ViewLayer *view_layer = WM_window_get_active_view_layer(root_win);
+
+ Depsgraph *depsgraph = BKE_scene_get_depsgraph(bmain, scene, view_layer, false);
+ BLI_assert(scene && view_layer && depsgraph);
+ BKE_scene_graph_evaluated_ensure(depsgraph, bmain);
+ *r_scene = scene;
+ *r_depsgraph = depsgraph;
+}
+
typedef enum wmXrSessionStateEvent {
SESSION_STATE_EVENT_NONE = 0,
SESSION_STATE_EVENT_START,
@@ -345,13 +388,17 @@ static void wm_xr_session_surface_draw(bContext *C)
{
wmXrSurfaceData *surface_data = g_xr_surface->customdata;
wmWindowManager *wm = CTX_wm_manager(C);
+ Main *bmain = CTX_data_main(C);
wmXrDrawData draw_data;
if (!GHOST_XrSessionIsRunning(wm->xr.runtime->context)) {
return;
}
- wm_xr_session_draw_data_populate(
- &wm->xr, CTX_data_scene(C), CTX_data_ensure_evaluated_depsgraph(C), &draw_data);
+
+ Scene *scene;
+ Depsgraph *depsgraph;
+ wm_xr_session_scene_and_evaluated_depsgraph_get(bmain, wm, &scene, &depsgraph);
+ wm_xr_session_draw_data_populate(&wm->xr, scene, depsgraph, &draw_data);
GHOST_XrSessionDrawViews(wm->xr.runtime->context, &draw_data);
diff --git a/source/blender/windowmanager/xr/wm_xr.h b/source/blender/windowmanager/xr/wm_xr.h
index 886f1315e8c..0f0fbe8bc00 100644
--- a/source/blender/windowmanager/xr/wm_xr.h
+++ b/source/blender/windowmanager/xr/wm_xr.h
@@ -28,5 +28,5 @@ typedef void (*wmXrSessionExitFn)(const wmXrData *xr_data);
/* wm_xr.c */
bool wm_xr_init(wmWindowManager *wm);
void wm_xr_exit(wmWindowManager *wm);
-void wm_xr_session_toggle(wmWindowManager *wm, wmXrSessionExitFn session_exit_fn);
+void wm_xr_session_toggle(wmWindowManager *wm, wmWindow *win, wmXrSessionExitFn session_exit_fn);
bool wm_xr_events_handle(wmWindowManager *wm);