General minor fixes and cleanup
authorJulian Eisel <eiseljulian@gmail.com>
Thu, 11 Jul 2019 14:30:21 +0000 (16:30 +0200)
committerJulian Eisel <eiseljulian@gmail.com>
Thu, 11 Jul 2019 14:36:04 +0000 (16:36 +0200)
* Initialize all class member variables
* Add version to runtime name printing
* Separate functionality code from debug prints
* Improve code structure using Doxygen groups
* Make accessors const functions
* Add (Doxygen) comments
* Naming
* Reorder functions

intern/ghost/intern/GHOST_XrContext.cpp
intern/ghost/intern/GHOST_XrContext.h
intern/ghost/intern/GHOST_XrSession.cpp
intern/ghost/intern/GHOST_XrSession.h
intern/ghost/intern/GHOST_Xr_intern.h

index bf08adcd25db95a2f731d0506b5ab287254898b3..e4502ae1e99617ad2a711a71168a6eda531df67d 100644 (file)
@@ -38,7 +38,7 @@ struct OpenXRInstanceData {
   static PFN_xrCreateDebugUtilsMessengerEXT s_xrCreateDebugUtilsMessengerEXT_fn;
   static PFN_xrDestroyDebugUtilsMessengerEXT s_xrDestroyDebugUtilsMessengerEXT_fn;
 
-  XrDebugUtilsMessengerEXT debug_messenger;
+  XrDebugUtilsMessengerEXT debug_messenger{XR_NULL_HANDLE};
 };
 
 PFN_xrCreateDebugUtilsMessengerEXT OpenXRInstanceData::s_xrCreateDebugUtilsMessengerEXT_fn =
@@ -46,6 +46,11 @@ PFN_xrCreateDebugUtilsMessengerEXT OpenXRInstanceData::s_xrCreateDebugUtilsMesse
 PFN_xrDestroyDebugUtilsMessengerEXT OpenXRInstanceData::s_xrDestroyDebugUtilsMessengerEXT_fn =
     nullptr;
 
+/* -------------------------------------------------------------------- */
+/** \name Create, Initialize and Destruct
+ *
+ * \{ */
+
 GHOST_XrContext::GHOST_XrContext(const GHOST_XrContextCreateInfo *create_info)
     : m_oxr(new OpenXRInstanceData()), m_debug(create_info->context_flag & GHOST_kXrContextDebug)
 {
@@ -63,29 +68,25 @@ GHOST_XrContext::~GHOST_XrContext()
 
 GHOST_TSuccess GHOST_XrContext::initialize(const GHOST_XrContextCreateInfo *create_info)
 {
-  XR_DEBUG_PRINTF(this, "Available OpenXR API-layers/extensions:\n");
   if (!enumerateApiLayers() || !enumerateExtensions()) {
     return GHOST_kFailure;
   }
-  XR_DEBUG_PRINTF(this, "Done printing OpenXR API-layers/extensions.\n");
+  XR_DEBUG_ONLY_CALL(this, printAvailableAPILayersAndExtensionsInfo());
 
   m_gpu_binding_type = determineGraphicsBindingTypeToEnable(create_info);
 
   assert(m_oxr->instance == XR_NULL_HANDLE);
   createOpenXRInstance();
   printInstanceInfo();
-  XR_DEBUG_ONLY_BEGIN(this);
-  initDebugMessenger();
-  XR_DEBUG_ONLY_END;
+  XR_DEBUG_ONLY_CALL(this, initDebugMessenger());
 
   return GHOST_kSuccess;
 }
 
 void GHOST_XrContext::createOpenXRInstance()
 {
-  XrInstanceCreateInfo create_info{};
+  XrInstanceCreateInfo create_info{XR_TYPE_INSTANCE_CREATE_INFO};
 
-  create_info.type = XR_TYPE_INSTANCE_CREATE_INFO;
   std::string("Blender").copy(create_info.applicationInfo.applicationName,
                               XR_MAX_APPLICATION_NAME_SIZE);
   create_info.applicationInfo.apiVersion = XR_CURRENT_API_VERSION;
@@ -96,28 +97,108 @@ void GHOST_XrContext::createOpenXRInstance()
   create_info.enabledApiLayerNames = m_enabled_layers.data();
   create_info.enabledExtensionCount = m_enabled_extensions.size();
   create_info.enabledExtensionNames = m_enabled_extensions.data();
+  XR_DEBUG_ONLY_CALL(this, printExtensionsAndAPILayersToEnable());
 
   xrCreateInstance(&create_info, &m_oxr->instance);
 }
 
+/** \} */ /* Create, Initialize and Destruct */
+
+/* -------------------------------------------------------------------- */
+/** \name Debug Printing
+ *
+ * \{ */
+
 void GHOST_XrContext::printInstanceInfo()
 {
   assert(m_oxr->instance != XR_NULL_HANDLE);
 
-  XrInstanceProperties instanceProperties{};
-  instanceProperties.type = XR_TYPE_INSTANCE_PROPERTIES;
-  xrGetInstanceProperties(m_oxr->instance, &instanceProperties);
+  XrInstanceProperties instance_properties{XR_TYPE_INSTANCE_PROPERTIES};
+  xrGetInstanceProperties(m_oxr->instance, &instance_properties);
+
+  printf("Connected to OpenXR runtime: %s (Version %i.%i.%i)\n",
+         instance_properties.runtimeName,
+         XR_VERSION_MAJOR(instance_properties.runtimeVersion),
+         XR_VERSION_MINOR(instance_properties.runtimeVersion),
+         XR_VERSION_PATCH(instance_properties.runtimeVersion));
+}
+
+void GHOST_XrContext::printAvailableAPILayersAndExtensionsInfo()
+{
+  puts("Available OpenXR API-layers/extensions:");
+  for (XrApiLayerProperties &layer_info : m_oxr->layers) {
+    printf("Layer: %s\n", layer_info.layerName);
+  }
+  for (XrExtensionProperties &ext_info : m_oxr->extensions) {
+    printf("Extension: %s\n", ext_info.extensionName);
+  }
+}
+
+void GHOST_XrContext::printExtensionsAndAPILayersToEnable()
+{
+  for (const char *layer_name : m_enabled_layers) {
+    printf("Enabling OpenXR API-Layer: %s\n", layer_name);
+  }
+  for (const char *ext_name : m_enabled_extensions) {
+    printf("Enabling OpenXR Extension: %s\n", ext_name);
+  }
+}
+
+static XrBool32 debug_messenger_func(XrDebugUtilsMessageSeverityFlagsEXT /*messageSeverity*/,
+                                     XrDebugUtilsMessageTypeFlagsEXT /*messageTypes*/,
+                                     const XrDebugUtilsMessengerCallbackDataEXT *callbackData,
+                                     void * /*userData*/)
+{
+  puts("OpenXR Debug Message:");
+  puts(callbackData->message);
+  return XR_FALSE;  // OpenXR spec suggests always returning false.
+}
+
+void GHOST_XrContext::initDebugMessenger()
+{
+  XrDebugUtilsMessengerCreateInfoEXT create_info{XR_TYPE_DEBUG_UTILS_MESSENGER_CREATE_INFO_EXT};
+
+  /* Extension functions need to be obtained through xrGetInstanceProcAddr */
+  if (XR_FAILED(xrGetInstanceProcAddr(
+          m_oxr->instance,
+          "xrCreateDebugUtilsMessengerEXT",
+          (PFN_xrVoidFunction *)&m_oxr->s_xrCreateDebugUtilsMessengerEXT_fn)) ||
+      XR_FAILED(xrGetInstanceProcAddr(
+          m_oxr->instance,
+          "xrDestroyDebugUtilsMessengerEXT",
+          (PFN_xrVoidFunction *)&m_oxr->s_xrDestroyDebugUtilsMessengerEXT_fn))) {
+    fprintf(stderr, "Could not use XR_EXT_debug_utils to enable debug prints.\n");
+    m_oxr->s_xrCreateDebugUtilsMessengerEXT_fn = nullptr;
+    m_oxr->s_xrDestroyDebugUtilsMessengerEXT_fn = nullptr;
+    return;
+  }
+
+  create_info.messageSeverities = XR_DEBUG_UTILS_MESSAGE_SEVERITY_VERBOSE_BIT_EXT |
+                                  XR_DEBUG_UTILS_MESSAGE_SEVERITY_INFO_BIT_EXT |
+                                  XR_DEBUG_UTILS_MESSAGE_SEVERITY_WARNING_BIT_EXT |
+                                  XR_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT;
+  create_info.messageTypes = XR_DEBUG_UTILS_MESSAGE_TYPE_GENERAL_BIT_EXT |
+                             XR_DEBUG_UTILS_MESSAGE_TYPE_VALIDATION_BIT_EXT |
+                             XR_DEBUG_UTILS_MESSAGE_TYPE_PERFORMANCE_BIT_EXT;
+  create_info.userCallback = debug_messenger_func;
 
-  XR_DEBUG_PRINTF(this, "Connected to OpenXR runtime: %s\n", instanceProperties.runtimeName);
+  m_oxr->s_xrCreateDebugUtilsMessengerEXT_fn(
+      m_oxr->instance, &create_info, &m_oxr->debug_messenger);
 }
 
+/** \} */ /* Debug Printing */
+
+/* -------------------------------------------------------------------- */
+/** \name OpenXR API-Layers and Extensions
+ *
+ * \{ */
+
 /**
  * \param layer_name May be NULL for extensions not belonging to a specific layer.
  */
 GHOST_TSuccess GHOST_XrContext::enumerateExtensionsEx(
     std::vector<XrExtensionProperties> &extensions, const char *layer_name)
 {
-  const unsigned long old_extension_count = extensions.size();
   uint32_t extension_count = 0;
 
   /* Get count for array creation/init first. */
@@ -136,18 +217,9 @@ GHOST_TSuccess GHOST_XrContext::enumerateExtensionsEx(
     extensions.push_back(ext);
   }
 
-  if (layer_name) {
-    XR_DEBUG_PRINTF(this, "Layer: %s\n", layer_name);
-  }
-
   /* Actually get the extensions. */
   xrEnumerateInstanceExtensionProperties(
       layer_name, extension_count, &extension_count, extensions.data());
-  XR_DEBUG_ONLY_BEGIN(this);
-  for (uint32_t i = 0; i < extension_count; i++) {
-    XR_DEBUG_PRINTF(this, "Extension: %s\n", extensions[i + old_extension_count].extensionName);
-  }
-  XR_DEBUG_ONLY_END;
 
   return GHOST_kSuccess;
 }
@@ -178,8 +250,6 @@ GHOST_TSuccess GHOST_XrContext::enumerateApiLayers()
   /* Actually get the layers. */
   xrEnumerateApiLayerProperties(layer_count, &layer_count, m_oxr->layers.data());
   for (XrApiLayerProperties &layer : m_oxr->layers) {
-    XR_DEBUG_PRINTF(this, "Layer: %s\n", layer.layerName);
-
     /* Each layer may have own extensions */
     enumerateExtensionsEx(m_oxr->extensions, layer.layerName);
   }
@@ -217,16 +287,13 @@ void GHOST_XrContext::getAPILayersToEnable(std::vector<const char *> &r_ext_name
 {
   static std::vector<std::string> try_layers;
 
-  XR_DEBUG_ONLY_BEGIN(this);
-  try_layers.push_back("XR_APILAYER_LUNARG_core_validation");
-  XR_DEBUG_ONLY_END;
+  XR_DEBUG_ONLY_CALL(this, try_layers.push_back("XR_APILAYER_LUNARG_core_validation"));
 
   r_ext_names.reserve(try_layers.size());
 
   for (const std::string &layer : try_layers) {
     if (openxr_layer_is_available(m_oxr->layers, layer)) {
       r_ext_names.push_back(layer.c_str());
-      XR_DEBUG_PRINTF(this, "Enabling OpenXR API-Layer %s\n", layer.c_str());
     }
   }
 }
@@ -257,26 +324,20 @@ void GHOST_XrContext::getExtensionsToEnable(std::vector<const char *> &r_ext_nam
 
   const char *gpu_binding = openxr_ext_name_from_wm_gpu_binding(m_gpu_binding_type);
   static std::vector<std::string> try_ext;
-  const auto add_ext = [this, &r_ext_names](const char *ext_name) {
-    r_ext_names.push_back(ext_name);
-    XR_DEBUG_PRINTF(this, "Enabling OpenXR Extension: %s\n", ext_name);
-  };
 
-  XR_DEBUG_ONLY_BEGIN(this);
   /* Try enabling debug extension */
-  try_ext.push_back(XR_EXT_DEBUG_UTILS_EXTENSION_NAME);
-  XR_DEBUG_ONLY_END;
+  XR_DEBUG_ONLY_CALL(this, try_ext.push_back(XR_EXT_DEBUG_UTILS_EXTENSION_NAME));
 
   r_ext_names.reserve(try_ext.size() + 1); /* + 1 for graphics binding extension. */
 
   /* Add graphics binding extension. */
   assert(gpu_binding);
   assert(openxr_extension_is_available(m_oxr->extensions, gpu_binding));
-  add_ext(gpu_binding);
+  r_ext_names.push_back(gpu_binding);
 
   for (const std::string &ext : try_ext) {
     if (openxr_extension_is_available(m_oxr->extensions, ext)) {
-      add_ext(ext.c_str());
+      r_ext_names.push_back(ext.c_str());
     }
   }
 }
@@ -303,47 +364,13 @@ GHOST_TXrGraphicsBinding GHOST_XrContext::determineGraphicsBindingTypeToEnable(
   return GHOST_kXrGraphicsUnknown;
 }
 
-static XrBool32 debug_messenger_func(XrDebugUtilsMessageSeverityFlagsEXT /*messageSeverity*/,
-                                     XrDebugUtilsMessageTypeFlagsEXT /*messageTypes*/,
-                                     const XrDebugUtilsMessengerCallbackDataEXT *callbackData,
-                                     void * /*userData*/)
-{
-  puts("OpenXR Debug Message:");
-  puts(callbackData->message);
-  return XR_FALSE;  // OpenXR spec suggests always returning false.
-}
-
-void GHOST_XrContext::initDebugMessenger()
-{
-  XrDebugUtilsMessengerCreateInfoEXT create_info{XR_TYPE_DEBUG_UTILS_MESSENGER_CREATE_INFO_EXT};
+/** \} */ /* OpenXR API-Layers and Extensions */
 
-  /* Extension functions need to be obtained through xrGetInstanceProcAddr */
-  if (XR_FAILED(xrGetInstanceProcAddr(
-          m_oxr->instance,
-          "xrCreateDebugUtilsMessengerEXT",
-          (PFN_xrVoidFunction *)&m_oxr->s_xrCreateDebugUtilsMessengerEXT_fn)) ||
-      XR_FAILED(xrGetInstanceProcAddr(
-          m_oxr->instance,
-          "xrDestroyDebugUtilsMessengerEXT",
-          (PFN_xrVoidFunction *)&m_oxr->s_xrDestroyDebugUtilsMessengerEXT_fn))) {
-    fprintf(stderr, "Could not use XR_EXT_debug_utils to enable debug prints.");
-    m_oxr->s_xrCreateDebugUtilsMessengerEXT_fn = nullptr;
-    m_oxr->s_xrDestroyDebugUtilsMessengerEXT_fn = nullptr;
-    return;
-  }
-
-  create_info.messageSeverities = XR_DEBUG_UTILS_MESSAGE_SEVERITY_VERBOSE_BIT_EXT |
-                                  XR_DEBUG_UTILS_MESSAGE_SEVERITY_INFO_BIT_EXT |
-                                  XR_DEBUG_UTILS_MESSAGE_SEVERITY_WARNING_BIT_EXT |
-                                  XR_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT;
-  create_info.messageTypes = XR_DEBUG_UTILS_MESSAGE_TYPE_GENERAL_BIT_EXT |
-                             XR_DEBUG_UTILS_MESSAGE_TYPE_VALIDATION_BIT_EXT |
-                             XR_DEBUG_UTILS_MESSAGE_TYPE_PERFORMANCE_BIT_EXT;
-  create_info.userCallback = debug_messenger_func;
-
-  m_oxr->s_xrCreateDebugUtilsMessengerEXT_fn(
-      m_oxr->instance, &create_info, &m_oxr->debug_messenger);
-}
+/* -------------------------------------------------------------------- */
+/** \name Session management
+ *
+ * Manage session lifetime and delegate public calls to #GHOST_XrSession.
+ * \{ */
 
 void GHOST_XrContext::startSession(const GHOST_XrSessionBeginInfo *begin_info)
 {
@@ -380,6 +407,14 @@ void GHOST_XrContext::handleSessionStateChange(const XrEventDataSessionStateChan
   }
 }
 
+/** \} */ /* Session Management */
+
+/* -------------------------------------------------------------------- */
+/** \name Public Accessors and Mutators
+ *
+ * Public as in, exposed in the Ghost API.
+ * \{ */
+
 /**
  * Set context for binding and unbinding a graphics context for a session. The binding callback
  * may create a new context thereby. In fact that's the sole reason for this callback approach to
@@ -403,12 +438,19 @@ void GHOST_XrContext::setDrawViewFunc(GHOST_XrDrawViewFn draw_view_fn)
   m_custom_funcs.draw_view_fn = draw_view_fn;
 }
 
-GHOST_XrCustomFuncs *GHOST_XrContext::getCustomFuncs()
+/** \} */ /* Public Accessors and Mutators */
+
+/* -------------------------------------------------------------------- */
+/** \name Ghost Internal Accessors and Mutators
+ *
+ * \{ */
+
+const GHOST_XrCustomFuncs *GHOST_XrContext::getCustomFuncs() const
 {
   return &m_custom_funcs;
 }
 
-GHOST_TXrGraphicsBinding GHOST_XrContext::getGraphicsBindingType()
+GHOST_TXrGraphicsBinding GHOST_XrContext::getGraphicsBindingType() const
 {
   return m_gpu_binding_type;
 }
@@ -422,3 +464,5 @@ bool GHOST_XrContext::isDebugMode() const
 {
   return m_debug;
 }
+
+/** \} */ /* Ghost Internal Accessors and Mutators */
index 614aac1a8a5987105380f98998624426f1892eef..50551926a52bfd0901a129438073a233b4c09f06 100644 (file)
@@ -59,8 +59,8 @@ class GHOST_XrContext : public GHOST_IXrContext {
                                    GHOST_XrGraphicsContextUnbindFn unbind_fn) override;
   void setDrawViewFunc(GHOST_XrDrawViewFn draw_view_fn) override;
 
-  GHOST_XrCustomFuncs *getCustomFuncs();
-  GHOST_TXrGraphicsBinding getGraphicsBindingType();
+  const GHOST_XrCustomFuncs *getCustomFuncs() const;
+  GHOST_TXrGraphicsBinding getGraphicsBindingType() const;
   XrInstance getInstance() const;
   bool isDebugMode() const;
 
@@ -71,7 +71,7 @@ class GHOST_XrContext : public GHOST_IXrContext {
   std::unique_ptr<class GHOST_XrSession> m_session;
 
   /** Active graphics binding type. */
-  GHOST_TXrGraphicsBinding m_gpu_binding_type;
+  GHOST_TXrGraphicsBinding m_gpu_binding_type{GHOST_kXrGraphicsUnknown};
 
   /** Names of enabled extensions */
   std::vector<const char *> m_enabled_extensions;
@@ -84,9 +84,12 @@ class GHOST_XrContext : public GHOST_IXrContext {
   bool m_debug{false};
 
   void createOpenXRInstance();
-  void printInstanceInfo();
   void initDebugMessenger();
 
+  void printInstanceInfo();
+  void printAvailableAPILayersAndExtensionsInfo();
+  void printExtensionsAndAPILayersToEnable();
+
   GHOST_TSuccess enumerateApiLayers();
   GHOST_TSuccess enumerateExtensions();
   GHOST_TSuccess enumerateExtensionsEx(std::vector<XrExtensionProperties> &extensions,
index 58fc1638db543836242ea854f1be5055237c4bc1..0c5a332f7e0357bc57d11ad7b6bb6e2953d2eb76 100644 (file)
@@ -48,6 +48,11 @@ struct GHOST_XrDrawFrame {
   XrFrameState frame_state;
 };
 
+/* -------------------------------------------------------------------- */
+/** \name Create, Initialize and Destruct
+ *
+ * \{ */
+
 GHOST_XrSession::GHOST_XrSession(GHOST_XrContext *xr_context)
     : m_context(xr_context), m_oxr(new OpenXRSessionData())
 {
@@ -70,34 +75,6 @@ GHOST_XrSession::~GHOST_XrSession()
   m_oxr->session_state = XR_SESSION_STATE_UNKNOWN;
 }
 
-bool GHOST_XrSession::isRunning()
-{
-  if (m_oxr->session == XR_NULL_HANDLE) {
-    return false;
-  }
-  switch (m_oxr->session_state) {
-    case XR_SESSION_STATE_RUNNING:
-    case XR_SESSION_STATE_VISIBLE:
-    case XR_SESSION_STATE_FOCUSED:
-      return true;
-    default:
-      return false;
-  }
-}
-bool GHOST_XrSession::isVisible()
-{
-  if (m_oxr->session == XR_NULL_HANDLE) {
-    return false;
-  }
-  switch (m_oxr->session_state) {
-    case XR_SESSION_STATE_VISIBLE:
-    case XR_SESSION_STATE_FOCUSED:
-      return true;
-    default:
-      return false;
-  }
-}
-
 /**
  * A system in OpenXR the combination of some sort of HMD plus controllers and whatever other
  * devices are managed through OpenXR. So this attempts to init the HMD and the other devices.
@@ -114,96 +91,12 @@ void GHOST_XrSession::initSystem()
   xrGetSystem(m_context->getInstance(), &system_info, &m_oxr->system_id);
 }
 
-void GHOST_XrSession::bindGraphicsContext()
-{
-  GHOST_XrCustomFuncs *custom_funcs = m_context->getCustomFuncs();
-  assert(custom_funcs->gpu_ctx_bind_fn);
-  m_gpu_ctx = static_cast<GHOST_Context *>(
-      custom_funcs->gpu_ctx_bind_fn(m_context->getGraphicsBindingType()));
-}
-void GHOST_XrSession::unbindGraphicsContext()
-{
-  GHOST_XrCustomFuncs *custom_funcs = m_context->getCustomFuncs();
-  if (custom_funcs->gpu_ctx_unbind_fn) {
-    custom_funcs->gpu_ctx_unbind_fn(m_context->getGraphicsBindingType(), m_gpu_ctx);
-  }
-  m_gpu_ctx = nullptr;
-}
-
-static std::vector<XrSwapchainImageBaseHeader *> swapchain_images_create(
-    XrSwapchain swapchain, GHOST_IXrGraphicsBinding *gpu_binding)
-{
-  std::vector<XrSwapchainImageBaseHeader *> images;
-  uint32_t image_count;
-
-  xrEnumerateSwapchainImages(swapchain, 0, &image_count, nullptr);
-  images = gpu_binding->createSwapchainImages(image_count);
-  xrEnumerateSwapchainImages(swapchain, images.size(), &image_count, images[0]);
-
-  return images;
-}
+/** \} */ /* Create, Initialize and Destruct */
 
-static XrSwapchain swapchain_create(const XrSession session,
-                                    GHOST_IXrGraphicsBinding *gpu_binding,
-                                    const XrViewConfigurationView *xr_view)
-{
-  XrSwapchainCreateInfo create_info{XR_TYPE_SWAPCHAIN_CREATE_INFO};
-  XrSwapchain swapchain;
-  uint32_t format_count = 0;
-  int64_t chosen_format;
-
-  xrEnumerateSwapchainFormats(session, 0, &format_count, nullptr);
-  std::vector<int64_t> swapchain_formats(format_count);
-  xrEnumerateSwapchainFormats(
-      session, swapchain_formats.size(), &format_count, swapchain_formats.data());
-  assert(swapchain_formats.size() == format_count);
-
-  if (!gpu_binding->chooseSwapchainFormat(swapchain_formats, &chosen_format)) {
-    fprintf(stderr, "Error: No format matching OpenXR runtime supported swapchain formats found.");
-    return nullptr;
-  }
-
-  create_info.usageFlags = XR_SWAPCHAIN_USAGE_SAMPLED_BIT |
-                           XR_SWAPCHAIN_USAGE_COLOR_ATTACHMENT_BIT;
-  create_info.format = chosen_format;
-  create_info.sampleCount = xr_view->recommendedSwapchainSampleCount;
-  create_info.width = xr_view->recommendedImageRectWidth;
-  create_info.height = xr_view->recommendedImageRectHeight;
-  create_info.faceCount = 1;
-  create_info.arraySize = 1;
-  create_info.mipCount = 1;
-  xrCreateSwapchain(session, &create_info, &swapchain);
-
-  return swapchain;
-}
-
-void GHOST_XrSession::prepareDrawing()
-{
-  std::vector<XrViewConfigurationView> view_configs;
-  uint32_t view_count;
-
-  xrEnumerateViewConfigurationViews(
-      m_context->getInstance(), m_oxr->system_id, m_oxr->view_type, 0, &view_count, nullptr);
-  view_configs.resize(view_count, {XR_TYPE_VIEW_CONFIGURATION_VIEW});
-  xrEnumerateViewConfigurationViews(m_context->getInstance(),
-                                    m_oxr->system_id,
-                                    m_oxr->view_type,
-                                    view_configs.size(),
-                                    &view_count,
-                                    view_configs.data());
-
-  for (const XrViewConfigurationView &view : view_configs) {
-    XrSwapchain swapchain = swapchain_create(m_oxr->session, m_gpu_binding.get(), &view);
-    auto images = swapchain_images_create(swapchain, m_gpu_binding.get());
-
-    m_oxr->swapchain_image_width = view.recommendedImageRectWidth;
-    m_oxr->swapchain_image_height = view.recommendedImageRectHeight;
-    m_oxr->swapchains.push_back(swapchain);
-    m_oxr->swapchain_images.insert(std::make_pair(swapchain, std::move(images)));
-  }
-
-  m_oxr->views.resize(view_count, {XR_TYPE_VIEW});
-}
+/* -------------------------------------------------------------------- */
+/** \name State Management
+ *
+ * \{ */
 
 static void create_reference_space(OpenXRSessionData *oxr, const GHOST_XrPose *base_pose)
 {
@@ -300,6 +193,87 @@ GHOST_XrSession::eLifeExpectancy GHOST_XrSession::handleStateChangeEvent(
 
   return SESSION_KEEP_ALIVE;
 }
+/** \} */ /* State Management */
+
+/* -------------------------------------------------------------------- */
+/** \name Drawing
+ *
+ * \{ */
+
+static std::vector<XrSwapchainImageBaseHeader *> swapchain_images_create(
+    XrSwapchain swapchain, GHOST_IXrGraphicsBinding *gpu_binding)
+{
+  std::vector<XrSwapchainImageBaseHeader *> images;
+  uint32_t image_count;
+
+  xrEnumerateSwapchainImages(swapchain, 0, &image_count, nullptr);
+  images = gpu_binding->createSwapchainImages(image_count);
+  xrEnumerateSwapchainImages(swapchain, images.size(), &image_count, images[0]);
+
+  return images;
+}
+
+static XrSwapchain swapchain_create(const XrSession session,
+                                    GHOST_IXrGraphicsBinding *gpu_binding,
+                                    const XrViewConfigurationView *xr_view)
+{
+  XrSwapchainCreateInfo create_info{XR_TYPE_SWAPCHAIN_CREATE_INFO};
+  XrSwapchain swapchain;
+  uint32_t format_count = 0;
+  int64_t chosen_format;
+
+  xrEnumerateSwapchainFormats(session, 0, &format_count, nullptr);
+  std::vector<int64_t> swapchain_formats(format_count);
+  xrEnumerateSwapchainFormats(
+      session, swapchain_formats.size(), &format_count, swapchain_formats.data());
+  assert(swapchain_formats.size() == format_count);
+
+  if (!gpu_binding->chooseSwapchainFormat(swapchain_formats, &chosen_format)) {
+    fprintf(stderr, "Error: No format matching OpenXR runtime supported swapchain formats found.");
+    return nullptr;
+  }
+
+  create_info.usageFlags = XR_SWAPCHAIN_USAGE_SAMPLED_BIT |
+                           XR_SWAPCHAIN_USAGE_COLOR_ATTACHMENT_BIT;
+  create_info.format = chosen_format;
+  create_info.sampleCount = xr_view->recommendedSwapchainSampleCount;
+  create_info.width = xr_view->recommendedImageRectWidth;
+  create_info.height = xr_view->recommendedImageRectHeight;
+  create_info.faceCount = 1;
+  create_info.arraySize = 1;
+  create_info.mipCount = 1;
+  xrCreateSwapchain(session, &create_info, &swapchain);
+
+  return swapchain;
+}
+
+void GHOST_XrSession::prepareDrawing()
+{
+  std::vector<XrViewConfigurationView> view_configs;
+  uint32_t view_count;
+
+  xrEnumerateViewConfigurationViews(
+      m_context->getInstance(), m_oxr->system_id, m_oxr->view_type, 0, &view_count, nullptr);
+  view_configs.resize(view_count, {XR_TYPE_VIEW_CONFIGURATION_VIEW});
+  xrEnumerateViewConfigurationViews(m_context->getInstance(),
+                                    m_oxr->system_id,
+                                    m_oxr->view_type,
+                                    view_configs.size(),
+                                    &view_count,
+                                    view_configs.data());
+
+  for (const XrViewConfigurationView &view : view_configs) {
+    XrSwapchain swapchain = swapchain_create(m_oxr->session, m_gpu_binding.get(), &view);
+    auto images = swapchain_images_create(swapchain, m_gpu_binding.get());
+
+    m_oxr->swapchain_image_width = view.recommendedImageRectWidth;
+    m_oxr->swapchain_image_height = view.recommendedImageRectHeight;
+    m_oxr->swapchains.push_back(swapchain);
+    m_oxr->swapchain_images.insert(std::make_pair(swapchain, std::move(images)));
+  }
+
+  m_oxr->views.resize(view_count, {XR_TYPE_VIEW});
+}
 
 void GHOST_XrSession::beginFrameDrawing()
 {
@@ -447,3 +421,68 @@ XrCompositionLayerProjection GHOST_XrSession::drawLayer(
 
   return layer;
 }
+
+/** \} */ /* Drawing */
+
+/* -------------------------------------------------------------------- */
+/** \name State Queries
+ *
+ * \{ */
+
+bool GHOST_XrSession::isRunning() const
+{
+  if (m_oxr->session == XR_NULL_HANDLE) {
+    return false;
+  }
+  switch (m_oxr->session_state) {
+    case XR_SESSION_STATE_RUNNING:
+    case XR_SESSION_STATE_VISIBLE:
+    case XR_SESSION_STATE_FOCUSED:
+      return true;
+    default:
+      return false;
+  }
+}
+bool GHOST_XrSession::isVisible() const
+{
+  if (m_oxr->session == XR_NULL_HANDLE) {
+    return false;
+  }
+  switch (m_oxr->session_state) {
+    case XR_SESSION_STATE_VISIBLE:
+    case XR_SESSION_STATE_FOCUSED:
+      return true;
+    default:
+      return false;
+  }
+}
+
+/** \} */ /* State Queries */
+
+/* -------------------------------------------------------------------- */
+/** \name Graphics Context Injection
+ *
+ * Sessions need access to Ghost graphics context information. Additionally, this API allows
+ * creating contexts on the fly (created on start, destructed on end). For this, callbacks to bind
+ * (potentially create) and unbind (potentially destruct) a Ghost graphics context have to be set,
+ * which will be called on session start and end respectively.
+ *
+ * \{ */
+
+void GHOST_XrSession::bindGraphicsContext()
+{
+  const GHOST_XrCustomFuncs *custom_funcs = m_context->getCustomFuncs();
+  assert(custom_funcs->gpu_ctx_bind_fn);
+  m_gpu_ctx = static_cast<GHOST_Context *>(
+      custom_funcs->gpu_ctx_bind_fn(m_context->getGraphicsBindingType()));
+}
+void GHOST_XrSession::unbindGraphicsContext()
+{
+  const GHOST_XrCustomFuncs *custom_funcs = m_context->getCustomFuncs();
+  if (custom_funcs->gpu_ctx_unbind_fn) {
+    custom_funcs->gpu_ctx_unbind_fn(m_context->getGraphicsBindingType(), m_gpu_ctx);
+  }
+  m_gpu_ctx = nullptr;
+}
+
+/** \} */ /* Graphics Context Injection */
index e87674ffaf706f386075fec5fffeaa994d3b636a..f427d4a89c5a71c38d55e3f06f5ca61ab7a9d514 100644 (file)
@@ -39,8 +39,8 @@ class GHOST_XrSession {
 
   eLifeExpectancy handleStateChangeEvent(const struct XrEventDataSessionStateChanged *lifecycle);
 
-  bool isRunning();
-  bool isVisible();
+  bool isRunning() const;
+  bool isVisible() const;
 
   void unbindGraphicsContext(); /* public so context can ensure it's unbound as needed. */
 
@@ -54,7 +54,7 @@ class GHOST_XrSession {
   std::unique_ptr<struct OpenXRSessionData> m_oxr; /* Could use stack, but PImpl is preferable */
 
   /** Active Ghost graphic context. Owned by Blender, not GHOST. */
-  class GHOST_Context *m_gpu_ctx;
+  class GHOST_Context *m_gpu_ctx{nullptr};
   std::unique_ptr<class GHOST_IXrGraphicsBinding> m_gpu_binding;
 
   /** Information on the currently drawn frame. Set while drawing only. */
index ee46a15e4508986e8b3923148e3150d9178df5b7..ec554899f4a49bb613f0e6827124e379ef1ad864 100644 (file)
   } \
   (void)0
 
+#define XR_DEBUG_ONLY_CALL(ctx, call) \
+  if ((ctx)->isDebugMode()) { \
+    call; \
+  } \
+  (void)0
+
 #endif /* __GHOST_XR_INTERN_H__ */