[Bf-blender-cvs] [cf4799e299b] soc-2019-openxr: Add wmSurface for non-Window offscreen VR session drawing
Julian Eisel
noreply at git.blender.org
Fri Jun 28 13:57:44 CEST 2019
Commit: cf4799e299b89fb9fb7d4b1293e0074c2b1dd6ae
Author: Julian Eisel
Date: Fri Jun 28 13:28:53 2019 +0200
Branches: soc-2019-openxr
https://developer.blender.org/rBcf4799e299b89fb9fb7d4b1293e0074c2b1dd6ae
Add wmSurface for non-Window offscreen VR session drawing
Adds a wmSurface type which acts as a container for non-Window (offscreen)
draw surfaces. Ideally wmWindow would of course also just do C-style
inheritance from wmSurface, but I guess they can co-exist too.
For the VR session a surface is created on Linux and passed to the
graphics binding to use.
Note this is not used on Windows yet, it still opens a window there.
===================================================================
M source/blender/windowmanager/CMakeLists.txt
M source/blender/windowmanager/intern/wm_draw.c
M source/blender/windowmanager/intern/wm_init_exit.c
M source/blender/windowmanager/intern/wm_operators.c
A source/blender/windowmanager/intern/wm_surface.c
M source/blender/windowmanager/intern/wm_window.c
M source/blender/windowmanager/intern/wm_xr.c
M source/blender/windowmanager/wm.h
A source/blender/windowmanager/wm_surface.h
===================================================================
diff --git a/source/blender/windowmanager/CMakeLists.txt b/source/blender/windowmanager/CMakeLists.txt
index 0669129d55c..f05ea317832 100644
--- a/source/blender/windowmanager/CMakeLists.txt
+++ b/source/blender/windowmanager/CMakeLists.txt
@@ -71,6 +71,7 @@ set(SRC
intern/wm_playanim.c
intern/wm_stereo.c
intern/wm_subwindow.c
+ intern/wm_surface.c
intern/wm_toolsystem.c
intern/wm_tooltip.c
intern/wm_uilist_type.c
@@ -98,6 +99,7 @@ set(SRC
wm_event_system.h
wm_event_types.h
wm_files.h
+ wm_surface.h
wm_window.h
gizmo/WM_gizmo_api.h
gizmo/WM_gizmo_types.h
diff --git a/source/blender/windowmanager/intern/wm_draw.c b/source/blender/windowmanager/intern/wm_draw.c
index 401ef25af53..cd4a906f34f 100644
--- a/source/blender/windowmanager/intern/wm_draw.c
+++ b/source/blender/windowmanager/intern/wm_draw.c
@@ -72,6 +72,7 @@
#include "wm_draw.h"
#include "wm_window.h"
#include "wm_event_system.h"
+#include "wm_surface.h"
#ifdef WITH_OPENSUBDIV
# include "BKE_subsurf.h"
@@ -866,19 +867,16 @@ static void wm_draw_window(bContext *C, wmWindow *win)
/**
* Draw offscreen contexts not bound to a specific window.
- *
- * For now keeping it simple by handling all possible cases here directly (only VR view drawing
- * currently). Could generalize this by something like a wmSurface type.
*/
-static void wm_draw_non_window_surfaces(bContext *C, wmWindowManager *wm)
+static void wm_draw_surface(bContext *C, wmSurface *surface)
{
-#ifdef WITH_OPENXR
- if (wm->xr_context) {
- wm_xr_session_draw(C, wm->xr_context);
- }
-#else
- UNUSED_VARS(wm);
-#endif
+ wm_window_clear_drawable(CTX_wm_manager(C));
+ wm_surface_make_drawable(surface);
+
+ surface->draw(C);
+
+ /* Avoid interference with window drawable */
+ wm_surface_clear_drawable();
}
/****************** main update call **********************/
@@ -993,7 +991,8 @@ void wm_draw_update(bContext *C)
}
}
- wm_draw_non_window_surfaces(C, wm);
+ /* Draw non-windows (surfaces) */
+ wm_surfaces_iter(C, wm_draw_surface);
}
void wm_draw_region_clear(wmWindow *win, ARegion *UNUSED(ar))
diff --git a/source/blender/windowmanager/intern/wm_init_exit.c b/source/blender/windowmanager/intern/wm_init_exit.c
index 2b4187913ff..ece97d50950 100644
--- a/source/blender/windowmanager/intern/wm_init_exit.c
+++ b/source/blender/windowmanager/intern/wm_init_exit.c
@@ -97,6 +97,7 @@
#include "wm_event_system.h"
#include "wm.h"
#include "wm_files.h"
+#include "wm_surface.h"
#include "wm_window.h"
#include "ED_anim_api.h"
@@ -523,6 +524,7 @@ void WM_exit_ext(bContext *C, const bool do_python)
BKE_keyconfig_pref_type_free();
wm_operatortype_free();
+ wm_surfaces_free();
wm_dropbox_free();
WM_menutype_free();
WM_uilisttype_free();
diff --git a/source/blender/windowmanager/intern/wm_operators.c b/source/blender/windowmanager/intern/wm_operators.c
index 329b716a0ff..8ef243b8bfb 100644
--- a/source/blender/windowmanager/intern/wm_operators.c
+++ b/source/blender/windowmanager/intern/wm_operators.c
@@ -115,6 +115,7 @@
#include "wm_event_system.h"
#include "wm_event_types.h"
#include "wm_files.h"
+#include "wm_surface.h"
#include "wm_window.h"
#define UNDOCUMENTED_OPERATOR_TIP N_("(undocumented operator)")
@@ -3539,43 +3540,41 @@ static void WM_OT_stereo3d_set(wmOperatorType *ot)
}
#ifdef WITH_OPENXR
-static void *xr_session_gpu_binding_context_create(GHOST_TXrGraphicsBinding graphics_lib)
+static void *xr_session_gpu_binding_context_create(GHOST_TXrGraphicsBinding graphics_binding)
{
# ifndef WIN32
- BLI_assert(graphics_lib == GHOST_kXrGraphicsOpenGL);
-# endif
+ wmSurface *surface = wm_xr_session_surface_create(G_MAIN->wm.first, graphics_binding);
- switch (graphics_lib) {
- case GHOST_kXrGraphicsOpenGL:
- return WM_opengl_context_create();
-# ifdef WIN32
- case GHOST_kXrGraphicsD3D11: {
- wmWindowManager *wm = G_MAIN->wm.first;
- for (wmWindow *win = wm->windows.first; win; win = win->next) {
- /* TODO better lookup? For now only one D3D window possible, but later? */
- if (GHOST_GetDrawingContextType(win->ghostwin) == GHOST_kDrawingContextTypeD3D) {
- return GHOST_GetWindowContext(win->ghostwin);
- }
+ wm_surface_add(surface);
+
+ return surface->ghost_ctx;
+
+# else
+# ifdef WIN32
+ if (graphics_binding == GHOST_kXrGraphicsD3D11) {
+ wmWindowManager *wm = G_MAIN->wm.first;
+ for (wmWindow *win = wm->windows.first; win; win = win->next) {
+ /* TODO better lookup? For now only one D3D window possible, but later? */
+ if (GHOST_GetDrawingContextType(win->ghostwin) == GHOST_kDrawingContextTypeD3D) {
+ return GHOST_GetWindowContext(win->ghostwin);
}
- return NULL;
}
-# endif
- default:
- return NULL;
+ return NULL;
}
+# endif
+# endif
}
-static void xr_session_gpu_binding_context_destroy(GHOST_TXrGraphicsBinding graphics_lib,
- void *context)
+static void xr_session_gpu_binding_context_destroy(GHOST_TXrGraphicsBinding UNUSED(graphics_lib),
+ void *UNUSED(context))
{
- GHOST_ContextHandle ghost_context = context;
+# ifndef WIN32
+ wmSurface *surface = wm_xr_session_surface_get();
- switch (graphics_lib) {
- case GHOST_kXrGraphicsOpenGL:
- WM_opengl_context_dispose(ghost_context);
- default:
- return;
+ if (surface) { /* Might have been freed already */
+ wm_surface_remove(surface);
}
+# endif
}
# ifdef WIN32
@@ -3645,33 +3644,12 @@ static void wm_xr_draw_view_fn(const GHOST_XrDrawViewInfo *UNUSED(draw_view), vo
(void)C;
}
-static bool wm_xr_ensure_context(wmWindowManager *wm)
-{
- if (wm->xr_context) {
- return true;
- }
-
- const GHOST_TXrGraphicsBinding gpu_bindings_candidates[] = {
- GHOST_kXrGraphicsOpenGL,
-# ifdef WIN32
- GHOST_kXrGraphicsD3D11,
-# endif
- };
- const GHOST_XrContextCreateInfo create_info = {
- .gpu_binding_candidates = gpu_bindings_candidates,
- .gpu_binding_candidates_count = ARRAY_SIZE(gpu_bindings_candidates)};
-
- wm->xr_context = GHOST_XrContextCreate(&create_info);
-
- return wm->xr_context != NULL;
-}
-
static int wm_xr_session_toggle_exec(bContext *C, wmOperator *UNUSED(op))
{
wmWindowManager *wm = CTX_wm_manager(C);
/* Lazy-create xr context - tries to dynlink to the runtime, reading active_runtime.json. */
- if (wm_xr_ensure_context(wm) == false) {
+ if (wm_xr_context_ensure(wm) == false) {
return OPERATOR_CANCELLED;
}
if (GHOST_XrSessionIsRunning(wm->xr_context)) {
diff --git a/source/blender/windowmanager/intern/wm_surface.c b/source/blender/windowmanager/intern/wm_surface.c
new file mode 100644
index 00000000000..cb575cc8f7d
--- /dev/null
+++ b/source/blender/windowmanager/intern/wm_surface.c
@@ -0,0 +1,118 @@
+/*
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+/** \file
+ * \ingroup wm
+ */
+
+#include "BKE_context.h"
+
+#include "BLF_api.h"
+
+#include "BLI_listbase.h"
+#include "BLI_threads.h"
+
+#include "GHOST_C-api.h"
+
+#include "GPU_batch_presets.h"
+#include "GPU_framebuffer.h"
+#include "GPU_immediate.h"
+#include "GPU_context.h"
+
+#include "MEM_guardedalloc.h"
+
+#include "WM_types.h"
+#include "WM_api.h"
+#include "wm.h"
+
+#include "wm_surface.h"
+
+static ListBase global_surface_list = {NULL, NULL};
+static wmSurface *g_drawable = NULL;
+
+void wm_surfaces_iter(bContext *C, void (*cb)(bContext *C, wmSurface *))
+{
+ for (wmSurface *surf = global_surface_list.first; surf; surf = surf->next) {
+ cb(C, surf);
+ }
+}
+
+void wm_surface_clear_drawable(void)
+{
+ if (g_drawable) {
+ BLF_batch_reset();
+ gpu_batch_presets_reset();
+ immDeactivate();
+
+ g_drawable = NULL;
+ }
+}
+
+void wm_surface_set_drawable(wmSurface *surface, bool activate)
+{
+ BLI_assert(ELEM(g_drawable, NULL, surface));
+
+ g_drawable = surface;
+ if (activate) {
+ GHOST_ActivateOpenGLContext(surface->ghost_ctx);
+ }
+
+ GPU_context_active_set(surface->gpu_ctx);
+ immActivate();
+}
+
+void wm_surface_make_drawable(wmSurface *surface)
+{
+ BLI_assert(GPU_framebuffer_active_get() == NULL);
+
+ if (surface != g_drawable) {
+ wm_surface_clear_drawable();
+ wm_surface_set_drawable(surface, true);
+ }
+}
+
+void wm_surface_reset_drawable(void)
+{
+ BLI_assert(BLI_thread_is_main());
+ BLI_assert(GPU_framebuffer_active_get() == NULL);
+
+ if (g_drawable) {
+ wm_surface_clear_drawable();
+ wm_surface_set_drawable(g_drawable, true);
+ }
+}
+
+void wm_surface_add(wmSurface *surface)
+{
+ BLI_addtail(&global_surface_list, surface);
+}
+
+void wm_surface_remove(wmSurface *surface)
+{
+ BLI_remlink(&global_surface_list, surface);
+ surface->free_data(surface);
+ MEM_freeN(surface);
+}
+
+void wm_surfaces_free(void)
+{
+ for (wmSurface *surf = global_surface_list.first, *surf_next; surf; surf = surf_next) {
+ surf_next = surf->next;
+ wm_surface_remove(surf);
+ }
+
+ BLI_assert(BLI_listbase_is_empty(&global_surface_list));
+}
diff --git a/source/blender/windowmanager/intern/wm_window.c b/source/blender/windowmanager/intern/wm_window.c
index cd636bbe4a3..b48186ae226 100644
--- a/source/blender/windowmanager/intern/wm_window.c
+++ b/source/blender/windowmanager/intern/wm_window.c
@@ -621,7 +621,6 @@ static void wm_window_ghostwindow_add(wmWindowManager *wm,
default_fb = GHOST_GetContextDefaultOpenGLFramebuffer(win->offscreen_context);
win->gpuctx = GPU_context
@@ Diff output truncated at 10240 characters. @@
More information about the Bf-blender-cvs
mailing list