[Bf-blender-cvs] [71c7d618089] soc-2019-openxr: Draw OpenGL framebuffer upside down in DirectX windows

Julian Eisel noreply at git.blender.org
Sun Jun 16 21:48:11 CEST 2019


Commit: 71c7d61808957eb301cdd313feae134b13936942
Author: Julian Eisel
Date:   Sun Jun 16 21:34:43 2019 +0200
Branches: soc-2019-openxr
https://developer.blender.org/rB71c7d61808957eb301cdd313feae134b13936942

Draw OpenGL framebuffer upside down in DirectX windows

DirectX is Y coordinates top to bottom, while OpenGL is the opposite.
For the final window manager on-screen drawing, draw to a texture first
and draw that upside down if needed.

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

M	intern/ghost/GHOST_C-api.h
M	intern/ghost/GHOST_IWindow.h
M	intern/ghost/intern/GHOST_C-api.cpp
M	intern/ghost/intern/GHOST_Context.h
M	intern/ghost/intern/GHOST_ContextD3D.h
M	intern/ghost/intern/GHOST_Window.cpp
M	intern/ghost/intern/GHOST_Window.h
M	source/blender/windowmanager/intern/wm_draw.c

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

diff --git a/intern/ghost/GHOST_C-api.h b/intern/ghost/GHOST_C-api.h
index 2ae94318ed8..fb59918d417 100644
--- a/intern/ghost/GHOST_C-api.h
+++ b/intern/ghost/GHOST_C-api.h
@@ -212,6 +212,11 @@ extern GHOST_TUserDataPtr GHOST_GetWindowUserData(GHOST_WindowHandle windowhandl
  */
 extern void GHOST_SetWindowUserData(GHOST_WindowHandle windowhandle, GHOST_TUserDataPtr userdata);
 
+/**
+ * Returns whether a window is rendered upside down compared to OpenGL.
+ */
+extern int GHOST_isUpsideDownWindow(GHOST_WindowHandle windowhandle);
+
 /**
  * Dispose a window.
  * \param systemhandle The handle to the system
diff --git a/intern/ghost/GHOST_IWindow.h b/intern/ghost/GHOST_IWindow.h
index 902af107bdf..d0ac770d0ac 100644
--- a/intern/ghost/GHOST_IWindow.h
+++ b/intern/ghost/GHOST_IWindow.h
@@ -245,6 +245,11 @@ class GHOST_IWindow {
    */
   virtual void setUserData(const GHOST_TUserDataPtr userData) = 0;
 
+  /**
+   * Returns if the window is rendered upside down compared to OpenGL.
+   */
+  virtual bool isUpsideDown() const = 0;
+
   /**
    * Returns the tablet data (pressure etc).
    * \return The tablet data (pressure etc).
diff --git a/intern/ghost/intern/GHOST_C-api.cpp b/intern/ghost/intern/GHOST_C-api.cpp
index 1de5fee30c7..1d2f5e0c5ed 100644
--- a/intern/ghost/intern/GHOST_C-api.cpp
+++ b/intern/ghost/intern/GHOST_C-api.cpp
@@ -171,6 +171,13 @@ void GHOST_SetWindowUserData(GHOST_WindowHandle windowhandle, GHOST_TUserDataPtr
   window->setUserData(userdata);
 }
 
+int GHOST_isUpsideDownWindow(GHOST_WindowHandle windowhandle)
+{
+  GHOST_IWindow *window = (GHOST_IWindow *)windowhandle;
+
+  return window->isUpsideDown();
+}
+
 GHOST_TSuccess GHOST_DisposeWindow(GHOST_SystemHandle systemhandle,
                                    GHOST_WindowHandle windowhandle)
 {
diff --git a/intern/ghost/intern/GHOST_Context.h b/intern/ghost/intern/GHOST_Context.h
index 5127aed6c15..cd32f250967 100644
--- a/intern/ghost/intern/GHOST_Context.h
+++ b/intern/ghost/intern/GHOST_Context.h
@@ -120,6 +120,11 @@ class GHOST_Context : public GHOST_IContext {
     return m_stereoVisual;
   }
 
+  inline virtual bool isUpsideDown() const
+  {
+    return false;
+  }
+
   /**
    * Gets the OpenGL framebuffer associated with the OpenGL context
    * \return The ID of an OpenGL framebuffer object.
diff --git a/intern/ghost/intern/GHOST_ContextD3D.h b/intern/ghost/intern/GHOST_ContextD3D.h
index 9223bf52e61..9f067fa23ce 100644
--- a/intern/ghost/intern/GHOST_ContextD3D.h
+++ b/intern/ghost/intern/GHOST_ContextD3D.h
@@ -108,6 +108,11 @@ class GHOST_ContextD3D : public GHOST_Context {
                                             GHOST_TInt32 width,
                                             GHOST_TInt32 height);
 
+  bool isUpsideDown() const
+  {
+    return true;
+  }
+
  private:
   friend class SharedOpenGLContext;
 
diff --git a/intern/ghost/intern/GHOST_Window.cpp b/intern/ghost/intern/GHOST_Window.cpp
index bbeb675524c..12955c252b0 100644
--- a/intern/ghost/intern/GHOST_Window.cpp
+++ b/intern/ghost/intern/GHOST_Window.cpp
@@ -124,6 +124,11 @@ GHOST_TSuccess GHOST_Window::blitOpenGLOffscreenContext(GHOST_IContext *offscree
       (GHOST_Context *)offscreen_ctx, rect.getWidth(), rect.getHeight());
 }
 
+bool GHOST_Window::isUpsideDown() const
+{
+  return m_context->isUpsideDown();
+}
+
 GHOST_TSuccess GHOST_Window::activateDrawingContext()
 {
   return m_context->activateDrawingContext();
diff --git a/intern/ghost/intern/GHOST_Window.h b/intern/ghost/intern/GHOST_Window.h
index 4d4501242e6..ec8433b8aa6 100644
--- a/intern/ghost/intern/GHOST_Window.h
+++ b/intern/ghost/intern/GHOST_Window.h
@@ -292,6 +292,8 @@ class GHOST_Window : public GHOST_IWindow {
     m_userData = userData;
   }
 
+  bool isUpsideDown() const;
+
   float getNativePixelSize(void)
   {
     if (m_nativePixelSize > 0.0f)
diff --git a/source/blender/windowmanager/intern/wm_draw.c b/source/blender/windowmanager/intern/wm_draw.c
index 0ec35aaeb8c..7fa1b16a425 100644
--- a/source/blender/windowmanager/intern/wm_draw.c
+++ b/source/blender/windowmanager/intern/wm_draw.c
@@ -722,6 +722,73 @@ static void wm_draw_window_onscreen(bContext *C, wmWindow *win, int view)
   }
 }
 
+static void wm_draw_upside_down(wmWindow *win)
+{
+  GPUVertFormat *format = immVertexFormat();
+  uint texcoord = GPU_vertformat_attr_add(format, "texCoord", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
+  uint pos = GPU_vertformat_attr_add(format, "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
+
+  immBindBuiltinProgram(GPU_SHADER_2D_IMAGE);
+
+  const int sizex = WM_window_pixels_x(win);
+  const int sizey = WM_window_pixels_y(win);
+
+  /* wmOrtho for the screen has this same offset */
+  const float halfx = GLA_PIXEL_OFS / sizex;
+  const float halfy = GLA_PIXEL_OFS / sizex;
+
+  immUniform1i("image", 0); /* texture is already bound to GL_TEXTURE0 unit */
+
+  immBegin(GPU_PRIM_TRI_FAN, 4);
+
+  immAttr2f(texcoord, halfx, 1.0f + halfy);
+  immVertex2f(pos, 0.0f, 0.0f);
+
+  immAttr2f(texcoord, 1.0f + halfx, 1.0f + halfy);
+  immVertex2f(pos, sizex, 0.0f);
+
+  immAttr2f(texcoord, 1.0f + halfx, halfy);
+  immVertex2f(pos, sizex, sizey);
+
+  immAttr2f(texcoord, halfx, halfy);
+  immVertex2f(pos, 0.0f, sizey);
+
+  immEnd();
+
+  immUnbindProgram();
+}
+
+static void wm_draw_window_upside_down_onscreen(bContext *C, wmWindow *win)
+{
+  const int width = WM_window_pixels_x(win);
+  const int height = WM_window_pixels_y(win);
+  GPUOffScreen *offscreen = GPU_offscreen_create(width, height, 0, false, false, NULL);
+
+  /* Upside down rendering only implemented for non-stereo. Easy to add but makes code messy. */
+  BLI_assert(
+      !(WM_stereo3d_enabled(win, false) && GHOST_isUpsideDownWindow(win->offscreen_context)));
+
+  if (offscreen) {
+    GPUTexture *texture = GPU_offscreen_color_texture(offscreen);
+    wm_draw_offscreen_texture_parameters(offscreen);
+
+    /* Draw view into offscreen buffer. */
+    GPU_offscreen_bind(offscreen, false);
+    wm_draw_window_onscreen(C, win, -1);
+    GPU_offscreen_unbind(offscreen, false);
+
+    /* Draw offscreen buffer to screen. */
+    glActiveTexture(GL_TEXTURE0);
+    glBindTexture(GL_TEXTURE_2D, GPU_texture_opengl_bindcode(texture));
+
+    wm_draw_upside_down(win);
+
+    glBindTexture(GL_TEXTURE_2D, 0);
+
+    GPU_offscreen_free(offscreen);
+  }
+}
+
 static void wm_draw_window(bContext *C, wmWindow *win)
 {
   bScreen *screen = WM_window_get_active_screen(win);
@@ -733,8 +800,13 @@ static void wm_draw_window(bContext *C, wmWindow *win)
 
   /* Now we draw into the window framebuffer, in full window coordinates. */
   if (!stereo) {
-    /* Regular mono drawing. */
-    wm_draw_window_onscreen(C, win, -1);
+    if (GHOST_isUpsideDownWindow(win->ghostwin)) {
+      wm_draw_window_upside_down_onscreen(C, win);
+    }
+    else {
+      /* Regular mono drawing. */
+      wm_draw_window_onscreen(C, win, -1);
+    }
   }
   else if (win->stereo3d_format->display_mode == S3D_DISPLAY_PAGEFLIP) {
     /* For pageflip we simply draw to both back buffers. */



More information about the Bf-blender-cvs mailing list