This repository has been archived on 2023-10-09. You can view files and clone it. You cannot open issues or pull requests or push a commit.
Files
blender-archive/source/blender/windowmanager/xr/intern/wm_xr.c
Campbell Barton c434782e3a File headers: SPDX License migration
Use a shorter/simpler license convention, stops the header taking so
much space.

Follow the SPDX license specification: https://spdx.org/licenses

- C/C++/objc/objc++
- Python
- Shell Scripts
- CMake, GNUmakefile

While most of the source tree has been included

- `./extern/` was left out.
- `./intern/cycles` & `./intern/atomic` are also excluded because they
  use different header conventions.

doc/license/SPDX-license-identifiers.txt has been added to list SPDX all
used identifiers.

See P2788 for the script that automated these edits.

Reviewed By: brecht, mont29, sergey

Ref D14069
2022-02-11 09:14:36 +11:00

179 lines
5.0 KiB
C

/* SPDX-License-Identifier: GPL-2.0-or-later */
/** \file
* \ingroup wm
*
* All XR functionality is accessed through a #GHOST_XrContext handle.
* The lifetime of this context also determines the lifetime of the OpenXR instance, which is the
* representation of the OpenXR runtime connection within the application.
*/
#include "BKE_global.h"
#include "BKE_idprop.h"
#include "BKE_main.h"
#include "BKE_report.h"
#include "DEG_depsgraph.h"
#include "DNA_scene_types.h"
#include "DNA_windowmanager_types.h"
#include "ED_screen.h"
#include "GHOST_C-api.h"
#include "GPU_platform.h"
#include "MEM_guardedalloc.h"
#include "WM_api.h"
#include "wm_surface.h"
#include "wm_xr_intern.h"
typedef struct {
wmWindowManager *wm;
} wmXrErrorHandlerData;
/* -------------------------------------------------------------------- */
static void wm_xr_error_handler(const GHOST_XrError *error)
{
wmXrErrorHandlerData *handler_data = error->customdata;
wmWindowManager *wm = handler_data->wm;
BKE_reports_clear(&wm->reports);
WM_report(RPT_ERROR, error->user_message);
WM_report_banner_show();
if (wm->xr.runtime) {
/* Just play safe and destroy the entire runtime data, including context. */
wm_xr_runtime_data_free(&wm->xr.runtime);
}
}
bool wm_xr_init(wmWindowManager *wm)
{
if (wm->xr.runtime && wm->xr.runtime->context) {
return true;
}
static wmXrErrorHandlerData error_customdata;
/* Set up error handling */
error_customdata.wm = wm;
GHOST_XrErrorHandler(wm_xr_error_handler, &error_customdata);
{
const GHOST_TXrGraphicsBinding gpu_bindings_candidates[] = {
GHOST_kXrGraphicsOpenGL,
#ifdef WIN32
GHOST_kXrGraphicsD3D11,
#endif
};
GHOST_XrContextCreateInfo create_info = {
.gpu_binding_candidates = gpu_bindings_candidates,
.gpu_binding_candidates_count = ARRAY_SIZE(gpu_bindings_candidates),
};
GHOST_XrContextHandle context;
if (G.debug & G_DEBUG_XR) {
create_info.context_flag |= GHOST_kXrContextDebug;
}
if (G.debug & G_DEBUG_XR_TIME) {
create_info.context_flag |= GHOST_kXrContextDebugTime;
}
#ifdef WIN32
if (GPU_type_matches(GPU_DEVICE_NVIDIA, GPU_OS_WIN, GPU_DRIVER_ANY)) {
create_info.context_flag |= GHOST_kXrContextGpuNVIDIA;
}
#endif
if (!(context = GHOST_XrContextCreate(&create_info))) {
return false;
}
/* Set up context callbacks */
GHOST_XrGraphicsContextBindFuncs(context,
wm_xr_session_gpu_binding_context_create,
wm_xr_session_gpu_binding_context_destroy);
GHOST_XrDrawViewFunc(context, wm_xr_draw_view);
if (!wm->xr.runtime) {
wm->xr.runtime = wm_xr_runtime_data_create();
wm->xr.runtime->context = context;
}
}
BLI_assert(wm->xr.runtime && wm->xr.runtime->context);
return true;
}
void wm_xr_exit(wmWindowManager *wm)
{
if (wm->xr.runtime != NULL) {
wm_xr_runtime_data_free(&wm->xr.runtime);
}
if (wm->xr.session_settings.shading.prop) {
IDP_FreeProperty(wm->xr.session_settings.shading.prop);
wm->xr.session_settings.shading.prop = NULL;
}
}
bool wm_xr_events_handle(wmWindowManager *wm)
{
if (wm->xr.runtime && wm->xr.runtime->context) {
GHOST_XrEventsHandle(wm->xr.runtime->context);
/* Process OpenXR action events. */
if (WM_xr_session_is_ready(&wm->xr)) {
wm_xr_session_actions_update(wm);
}
/* wm_window_process_events() uses the return value to determine if it can put the main thread
* to sleep for some milliseconds. We never want that to happen while the VR session runs on
* the main thread. So always return true. */
return true;
}
return false;
}
/* -------------------------------------------------------------------- */
/** \name XR Runtime Data
* \{ */
wmXrRuntimeData *wm_xr_runtime_data_create(void)
{
wmXrRuntimeData *runtime = MEM_callocN(sizeof(*runtime), __func__);
return runtime;
}
void wm_xr_runtime_data_free(wmXrRuntimeData **runtime)
{
/* Note that this function may be called twice, because of an indirect recursion: If a session is
* running while WM-XR calls this function, calling GHOST_XrContextDestroy() will call this
* again, because it's also set as the session exit callback. So NULL-check and NULL everything
* that is freed here. */
/* We free all runtime XR data here, so if the context is still alive, destroy it. */
if ((*runtime)->context != NULL) {
GHOST_XrContextHandle context = (*runtime)->context;
/* Prevent recursive GHOST_XrContextDestroy() call by NULL'ing the context pointer before the
* first call, see comment above. */
(*runtime)->context = NULL;
if ((*runtime)->area) {
wmWindowManager *wm = G_MAIN->wm.first;
wmWindow *win = wm_xr_session_root_window_or_fallback_get(wm, (*runtime));
ED_area_offscreen_free(wm, win, (*runtime)->area);
(*runtime)->area = NULL;
}
wm_xr_session_data_free(&(*runtime)->session_state);
WM_xr_actionmaps_clear(*runtime);
GHOST_XrContextDestroy(context);
}
MEM_SAFE_FREE(*runtime);
}
/** \} */ /* XR Runtime Data */