[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