[Bf-blender-cvs] [6ae2979d05d] soc-2019-openxr: Ghost DirectX compatibility from GSoC OpenXR branch

Julian Eisel noreply at git.blender.org
Fri Nov 15 11:29:39 CET 2019


Commit: 6ae2979d05d846440dcaf2e7cd1ca81905fded06
Author: Julian Eisel
Date:   Tue Nov 5 13:01:15 2019 +0100
Branches: soc-2019-openxr
https://developer.blender.org/rB6ae2979d05d846440dcaf2e7cd1ca81905fded06

Ghost DirectX compatibility from GSoC OpenXR branch

Needed for DirectX-only OpenXR runtimes (e.g. Windows Mixed Reality).

Adds a minimal DirectX 11 Ghost context, plus some shared DirectX-OpenGL resource interface using the NV_DX_interop2 WGL extension.
I know that the current implementation fails on some systems, which is something I'll have to fix at some point. Don't know if this is a showstopper though, I can fix that in master too. For now this isn't going to be used by many people anyway. Recently I also learned that OSVR uses the same extension, see https://github.com/sensics/OSVR-RenderManager/blob/master/osvr/RenderKit/RenderManagerD3DOpenGL.cpp. Their implementation may be useful to fix the issue, according to a OSVR dev, it wo [...]

Note: Didn't actually test just this patch on Windows yet.

Differential Revision: https://developer.blender.org/D6190

===================================================================

M	intern/ghost/CMakeLists.txt
M	intern/ghost/GHOST_C-api.h
M	intern/ghost/GHOST_ISystem.h
M	intern/ghost/GHOST_Types.h
M	intern/ghost/intern/GHOST_C-api.cpp
A	intern/ghost/intern/GHOST_ContextD3D.cpp
A	intern/ghost/intern/GHOST_ContextD3D.h
M	intern/ghost/intern/GHOST_System.cpp
M	intern/ghost/intern/GHOST_System.h
M	intern/ghost/intern/GHOST_SystemWin32.cpp
M	intern/ghost/intern/GHOST_SystemWin32.h
M	intern/ghost/intern/GHOST_WindowWin32.cpp

===================================================================

diff --git a/intern/ghost/CMakeLists.txt b/intern/ghost/CMakeLists.txt
index ec2e84268be..4779ca6d306 100644
--- a/intern/ghost/CMakeLists.txt
+++ b/intern/ghost/CMakeLists.txt
@@ -272,11 +272,13 @@ elseif(WIN32)
   )
 
   list(APPEND SRC
+    intern/GHOST_ContextD3D.cpp
     intern/GHOST_DisplayManagerWin32.cpp
     intern/GHOST_DropTargetWin32.cpp
     intern/GHOST_SystemWin32.cpp
     intern/GHOST_WindowWin32.cpp
 
+    intern/GHOST_ContextD3D.h
     intern/GHOST_DisplayManagerWin32.h
     intern/GHOST_DropTargetWin32.h
     intern/GHOST_SystemWin32.h
diff --git a/intern/ghost/GHOST_C-api.h b/intern/ghost/GHOST_C-api.h
index 720929ce945..0f96b6aac27 100644
--- a/intern/ghost/GHOST_C-api.h
+++ b/intern/ghost/GHOST_C-api.h
@@ -224,6 +224,25 @@ extern GHOST_ContextHandle GHOST_CreateOpenGLContext(GHOST_SystemHandle systemha
 extern GHOST_TSuccess GHOST_DisposeOpenGLContext(GHOST_SystemHandle systemhandle,
                                                  GHOST_ContextHandle contexthandle);
 
+#ifdef WIN32
+/**
+ * Create a new offscreen context.
+ * Never explicitly delete the context, use disposeContext() instead.
+ * \param systemhandle The handle to the system
+ * \return A handle to the new context ( == NULL if creation failed).
+ */
+GHOST_ContextHandle GHOST_CreateDirectXContext(GHOST_SystemHandle systemhandle);
+
+/**
+ * Dispose of a context.
+ * \param systemhandle The handle to the system
+ * \param contexthandle Handle to the context to be disposed.
+ * \return Indication of success.
+ */
+GHOST_TSuccess GHOST_DisposeDirectXContext(GHOST_SystemHandle systemhandle,
+                                           GHOST_ContextHandle contexthandle);
+#endif
+
 /**
  * Returns the window user data.
  * \param windowhandle The handle to the window
diff --git a/intern/ghost/GHOST_ISystem.h b/intern/ghost/GHOST_ISystem.h
index b781de266bc..17ece27ebf8 100644
--- a/intern/ghost/GHOST_ISystem.h
+++ b/intern/ghost/GHOST_ISystem.h
@@ -266,6 +266,12 @@ class GHOST_ISystem {
    */
   virtual GHOST_IContext *createOffscreenContext() = 0;
 
+  /**
+   * Overload to allow requesting a different context type. By default only OpenGL is supported.
+   * However by explicitly overloading this a system may add support for others.
+   */
+  virtual GHOST_IContext *createOffscreenContext(GHOST_TDrawingContextType type) = 0;
+
   /**
    * Dispose of a context.
    * \param   context Pointer to the context to be disposed.
diff --git a/intern/ghost/GHOST_Types.h b/intern/ghost/GHOST_Types.h
index 32472373b17..3971914033d 100644
--- a/intern/ghost/GHOST_Types.h
+++ b/intern/ghost/GHOST_Types.h
@@ -134,7 +134,10 @@ typedef enum { GHOST_kWindowOrderTop = 0, GHOST_kWindowOrderBottom } GHOST_TWind
 
 typedef enum {
   GHOST_kDrawingContextTypeNone = 0,
-  GHOST_kDrawingContextTypeOpenGL
+  GHOST_kDrawingContextTypeOpenGL,
+#ifdef WIN32
+  GHOST_kDrawingContextTypeD3D,
+#endif
 } GHOST_TDrawingContextType;
 
 typedef enum {
diff --git a/intern/ghost/intern/GHOST_C-api.cpp b/intern/ghost/intern/GHOST_C-api.cpp
index eeb23ea7471..360724aba33 100644
--- a/intern/ghost/intern/GHOST_C-api.cpp
+++ b/intern/ghost/intern/GHOST_C-api.cpp
@@ -139,6 +139,25 @@ GHOST_TSuccess GHOST_DisposeOpenGLContext(GHOST_SystemHandle systemhandle,
   return system->disposeContext(context);
 }
 
+#ifdef WIN32
+GHOST_ContextHandle GHOST_CreateDirectXContext(GHOST_SystemHandle systemhandle)
+{
+  GHOST_ISystem *system = (GHOST_ISystem *)systemhandle;
+
+  return (GHOST_ContextHandle)system->createOffscreenContext(GHOST_kDrawingContextTypeD3D);
+}
+
+GHOST_TSuccess GHOST_DisposeDirectXContext(GHOST_SystemHandle systemhandle,
+                                           GHOST_ContextHandle contexthandle)
+{
+  GHOST_ISystem *system = (GHOST_ISystem *)systemhandle;
+  GHOST_IContext *context = (GHOST_IContext *)contexthandle;
+
+  return system->disposeContext(context);
+}
+
+#endif
+
 GHOST_WindowHandle GHOST_CreateWindow(GHOST_SystemHandle systemhandle,
                                       const char *title,
                                       GHOST_TInt32 left,
diff --git a/intern/ghost/intern/GHOST_ContextD3D.cpp b/intern/ghost/intern/GHOST_ContextD3D.cpp
new file mode 100644
index 00000000000..605a52905b1
--- /dev/null
+++ b/intern/ghost/intern/GHOST_ContextD3D.cpp
@@ -0,0 +1,446 @@
+/*
+ * 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 GHOST
+ */
+
+#include <iostream>
+#include <string>
+
+#include <GL/glew.h>
+#include <GL/wglew.h>
+
+#include "GHOST_ContextWGL.h" /* For shared drawing */
+#include "GHOST_ContextD3D.h"
+
+//#define USE_DRAW_D3D_TEST_TRIANGLE
+
+HMODULE GHOST_ContextD3D::s_d3d_lib = NULL;
+PFN_D3D11_CREATE_DEVICE GHOST_ContextD3D::s_D3D11CreateDeviceFn = NULL;
+
+#ifdef USE_DRAW_D3D_TEST_TRIANGLE
+static void drawTestTriangle(ID3D11Device *m_device,
+                             ID3D11DeviceContext *m_device_ctx,
+                             GHOST_TInt32 width,
+                             GHOST_TInt32 height);
+#endif
+
+GHOST_ContextD3D::GHOST_ContextD3D(bool stereoVisual, HWND hWnd)
+    : GHOST_Context(stereoVisual), m_hWnd(hWnd)
+{
+}
+
+GHOST_ContextD3D::~GHOST_ContextD3D()
+{
+  m_device->Release();
+  m_device_ctx->ClearState();
+  m_device_ctx->Release();
+}
+
+GHOST_TSuccess GHOST_ContextD3D::swapBuffers()
+{
+  return GHOST_kSuccess;
+}
+
+GHOST_TSuccess GHOST_ContextD3D::activateDrawingContext()
+{
+  return GHOST_kFailure;
+}
+
+GHOST_TSuccess GHOST_ContextD3D::releaseDrawingContext()
+{
+  return GHOST_kFailure;
+}
+
+GHOST_TSuccess GHOST_ContextD3D::setupD3DLib()
+{
+  if (s_d3d_lib == NULL) {
+    s_d3d_lib = LoadLibraryA("d3d11.dll");
+
+    WIN32_CHK(s_d3d_lib != NULL);
+
+    if (s_d3d_lib == NULL) {
+      fprintf(stderr, "LoadLibrary(\"d3d11.dll\") failed!\n");
+      return GHOST_kFailure;
+    }
+  }
+
+  if (s_D3D11CreateDeviceFn == NULL) {
+    s_D3D11CreateDeviceFn = (PFN_D3D11_CREATE_DEVICE)GetProcAddress(s_d3d_lib,
+                                                                    "D3D11CreateDevice");
+
+    WIN32_CHK(s_D3D11CreateDeviceFn != NULL);
+
+    if (s_D3D11CreateDeviceFn == NULL) {
+      fprintf(stderr, "GetProcAddress(s_d3d_lib, \"D3D11CreateDevice\") failed!\n");
+      return GHOST_kFailure;
+    }
+  }
+
+  return GHOST_kSuccess;
+}
+
+GHOST_TSuccess GHOST_ContextD3D::initializeDrawingContext()
+{
+  if (setupD3DLib() == GHOST_kFailure) {
+    return GHOST_kFailure;
+  }
+
+  HRESULT hres = s_D3D11CreateDeviceFn(NULL,
+                                       D3D_DRIVER_TYPE_HARDWARE,
+                                       NULL,
+                                       // D3D11_CREATE_DEVICE_DEBUG,
+                                       0,
+                                       NULL,
+                                       0,
+                                       D3D11_SDK_VERSION,
+                                       &m_device,
+                                       NULL,
+                                       &m_device_ctx);
+
+  WIN32_CHK(hres == S_OK);
+
+  return GHOST_kSuccess;
+}
+
+GHOST_TSuccess GHOST_ContextD3D::releaseNativeHandles()
+{
+  return GHOST_kFailure;
+}
+
+class GHOST_SharedOpenGLResource {
+  struct SharedData {
+    HANDLE device;
+    GLuint fbo;
+    HANDLE render_buf{nullptr};
+  } m_shared;
+
+ public:
+  GHOST_SharedOpenGLResource(ID3D11Device *device,
+                             ID3D11DeviceContext *device_ctx,
+                             unsigned int width,
+                             unsigned int height,
+                             ID3D11RenderTargetView *render_target = nullptr)
+      : m_device(device), m_device_ctx(device_ctx), m_cur_width(width), m_cur_height(height)
+  {
+    ID3D11Resource *backbuffer_res;
+
+    if (!render_target) {
+      D3D11_TEXTURE2D_DESC texDesc{};
+      D3D11_RENDER_TARGET_VIEW_DESC renderTargetViewDesc{};
+      ID3D11Texture2D *tex;
+
+      texDesc.Width = width;
+      texDesc.Height = height;
+      texDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
+      texDesc.SampleDesc.Count = 1;
+      texDesc.ArraySize = 1;
+      texDesc.MipLevels = 1;
+      texDesc.BindFlags = D3D11_BIND_SHADER_RESOURCE | D3D11_BIND_RENDER_TARGET;
+
+      device->CreateTexture2D(&texDesc, NULL, &tex);
+
+      renderTargetViewDesc.Format = texDesc.Format;
+      renderTargetViewDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2D;
+      renderTargetViewDesc.Texture2D.MipSlice = 0;
+
+      device->CreateRenderTargetView(tex, &renderTargetViewDesc, &render_target);
+
+      tex->Release();
+    }
+
+    m_render_target = render_target;
+    m_render_target->GetResource(&backbuffer_res);
+    backbuffer_res->QueryInterface<ID3D11Texture2D>(&m_render_target_tex);
+    backbuffer_res->Release();
+  }
+
+  ~GHOST_SharedOpenGLResource()
+  {
+    m_render_target_tex->Release();
+    m_render_target->Release();
+
+    if (m_is_initialized) {
+      if (m_shared.render_buf) {
+        wglDXUnregisterObjectNV(m_shared.device, m_shared.render_buf);
+      }
+      if (m_shared.device) {
+        wglDXCloseDeviceNV(m_shared.device);
+      }
+      glDeleteFramebuffers(1, &m_shared.fbo);
+      glDeleteRenderbuffers(1, &m_gl_render_buf);
+    }
+  }
+
+  void reregisterSharedObject()
+  {
+    if (m_shared.render_buf) {
+      wglDXUnregisterObjectNV(m_shared.device, m_shared.render_buf);
+    }
+
+    m_shared.render_buf = wglDXRegisterObjectNV(m_shared.device,
+                                                m_render_target_tex,
+                                               

@@ Diff output truncated at 10240 characters. @@



More information about the Bf-blender-cvs mailing list