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
committerJeroen Bakker <jeroen@blender.org>2020-08-12 10:38:13 +0300
commitfa2a13bcb958ee038ab85c4a413282accceedd1f (patch)
tree0b9c71c0e9b977a90e2c996ed048511114a108c1
parent112416e4fb8ca85b6a2fa3d619eddd18b62ab0c2 (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).
-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 a7578291a21..e3c7bca0e8c 100644
--- a/source/blender/windowmanager/intern/wm_operators.c
+++ b/source/blender/windowmanager/intern/wm_operators.c
@@ -3734,6 +3734,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. */
@@ -3742,7 +3743,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 b53ae45a29f..8d249f8c55d 100644
--- a/source/blender/windowmanager/xr/intern/wm_xr_intern.h
+++ b/source/blender/windowmanager/xr/intern/wm_xr_intern.h
@@ -45,7 +45,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 4eb0599a609..5c90bd6331a 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;
@@ -154,6 +160,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;
+}
+
void wm_xr_session_draw_data_update(const wmXrSessionState *state,
const XrSessionSettings *settings,
const GHOST_XrDrawViewInfo *draw_view,
@@ -288,13 +331,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 33f79bc75b2..b4c58d3f139 100644
--- a/source/blender/windowmanager/xr/wm_xr.h
+++ b/source/blender/windowmanager/xr/wm_xr.h
@@ -29,7 +29,7 @@ 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);
#endif