[Bf-blender-cvs] [be7b41df3ff] soc-2019-openxr: Bring back vertically mirrored drawing for DirectX compatibility

Julian Eisel noreply at git.blender.org
Mon Mar 2 17:13:47 CET 2020


Commit: be7b41df3ff45c08ce79d4d4c8aca8416ac39a9d
Author: Julian Eisel
Date:   Wed Feb 19 14:48:23 2020 +0100
Branches: soc-2019-openxr
https://developer.blender.org/rBbe7b41df3ff45c08ce79d4d4c8aca8416ac39a9d

Bring back vertically mirrored drawing for DirectX compatibility

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

M	source/blender/gpu/intern/gpu_viewport.c
M	source/blender/windowmanager/intern/wm_xr.c

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

diff --git a/source/blender/gpu/intern/gpu_viewport.c b/source/blender/gpu/intern/gpu_viewport.c
index a3ee2d11e56..8db9102de7c 100644
--- a/source/blender/gpu/intern/gpu_viewport.c
+++ b/source/blender/gpu/intern/gpu_viewport.c
@@ -532,6 +532,13 @@ static void gpu_viewport_draw_colormanaged(GPUViewport *viewport,
   }
 }
 
+/**
+ * Merge and draw the buffers of \a viewport into the currently active framebuffer, performing
+ * color transform to display space.
+ *
+ * \param rect: Coordinates to draw into. By swapping min and max values, drawing can be done with
+ *              inversed axis coordinates (upside down or sideways).
+ */
 void GPU_viewport_draw_to_screen(GPUViewport *viewport, const rcti *rect)
 {
   DefaultFramebufferList *dfbl = viewport->fbl;
@@ -545,18 +552,22 @@ void GPU_viewport_draw_to_screen(GPUViewport *viewport, const rcti *rect)
   const float w = (float)GPU_texture_width(color);
   const float h = (float)GPU_texture_height(color);
 
-  BLI_assert(w == BLI_rcti_size_x(rect) + 1);
-  BLI_assert(h == BLI_rcti_size_y(rect) + 1);
+  /* We allow rects with min/max swapped, but we also need coorectly assigned coordinates. */
+  rcti sanitized_rect = *rect;
+  BLI_rcti_sanitize(&sanitized_rect);
+
+  BLI_assert(w == BLI_rcti_size_x(&sanitized_rect) + 1);
+  BLI_assert(h == BLI_rcti_size_y(&sanitized_rect) + 1);
 
   /* wmOrtho for the screen has this same offset */
   const float halfx = GLA_PIXEL_OFS / w;
   const float halfy = GLA_PIXEL_OFS / h;
 
   rctf pos_rect = {
-      .xmin = rect->xmin,
-      .ymin = rect->ymin,
-      .xmax = rect->xmin + w,
-      .ymax = rect->ymin + h,
+      .xmin = sanitized_rect.xmin,
+      .ymin = sanitized_rect.ymin,
+      .xmax = sanitized_rect.xmin + w,
+      .ymax = sanitized_rect.ymin + h,
   };
 
   rctf uv_rect = {
@@ -565,6 +576,14 @@ void GPU_viewport_draw_to_screen(GPUViewport *viewport, const rcti *rect)
       .xmax = halfx + 1.0f,
       .ymax = halfy + 1.0f,
   };
+  /* Mirror the UV rect in case axis-swapped drawing is requested (by passing a rect with min and
+   * max values swapped). */
+  if (BLI_rcti_size_x(rect) < 0) {
+    SWAP(int, uv_rect.xmin, uv_rect.xmax);
+  }
+  if (BLI_rcti_size_y(rect) < 0) {
+    SWAP(int, uv_rect.ymin, uv_rect.ymax);
+  }
 
   gpu_viewport_draw_colormanaged(viewport, &pos_rect, &uv_rect, true);
 }
diff --git a/source/blender/windowmanager/intern/wm_xr.c b/source/blender/windowmanager/intern/wm_xr.c
index b1a038a48c3..a3a0b692ac5 100644
--- a/source/blender/windowmanager/intern/wm_xr.c
+++ b/source/blender/windowmanager/intern/wm_xr.c
@@ -240,6 +240,7 @@ void wm_xr_session_toggle(bContext *C, void *xr_context_ptr)
  */
 static void wm_xr_session_surface_draw(bContext *C)
 {
+  wmXrSurfaceData *surface_data = g_xr_surface->customdata;
   wmWindowManager *wm = CTX_wm_manager(C);
 
   if (!GHOST_XrSessionIsRunning(wm->xr.context)) {
@@ -247,7 +248,7 @@ static void wm_xr_session_surface_draw(bContext *C)
   }
   GHOST_XrSessionDrawViews(wm->xr.context, C);
 
-  GPU_framebuffer_restore();
+  GPU_offscreen_unbind(surface_data->offscreen, false);
 }
 
 static void wm_xr_session_free_data(wmSurface *surface)
@@ -399,6 +400,22 @@ static void wm_xr_draw_matrices_create(const Scene *scene,
   }
 }
 
+static void wm_xr_draw_viewport_buffers_to_active_framebuffer(
+    const wmXrSurfaceData *surface_data, const GHOST_XrDrawViewInfo *draw_view)
+{
+  const bool is_upside_down = surface_data->secondary_ghost_ctx &&
+                              GHOST_isUpsideDownContext(surface_data->secondary_ghost_ctx);
+  rcti rect = {.xmin = 0, .ymin = 0, .xmax = draw_view->width - 1, .ymax = draw_view->height - 1};
+
+  wmViewport(&rect);
+
+  /* For upside down contexts, draw with inverted y-values. */
+  if (is_upside_down) {
+    SWAP(int, rect.ymin, rect.ymax);
+  }
+  GPU_viewport_draw_to_screen(surface_data->viewport, &rect);
+}
+
 /**
  * \brief Draw a viewport for a single eye.
  *
@@ -412,11 +429,7 @@ void wm_xr_draw_view(const GHOST_XrDrawViewInfo *draw_view, void *customdata)
   wmXrSurfaceData *surface_data = g_xr_surface->customdata;
   bXrSessionSettings *settings = &wm->xr.session_settings;
   const float display_flags = V3D_OFSDRAW_OVERRIDE_SCENE_SETTINGS | settings->draw_flags;
-  const rcti rect = {
-      .xmin = 0, .ymin = 0, .xmax = draw_view->width - 1, .ymax = draw_view->height - 1};
 
-  GPUOffScreen *offscreen;
-  GPUViewport *viewport;
   View3DShading shading;
   float viewmat[4][4], winmat[4][4];
 
@@ -427,9 +440,6 @@ void wm_xr_draw_view(const GHOST_XrDrawViewInfo *draw_view, void *customdata)
     return;
   }
 
-  offscreen = surface_data->offscreen;
-  viewport = surface_data->viewport;
-  glClear(GL_DEPTH_BUFFER_BIT);
   /* In case a framebuffer is still bound from drawing the last eye. */
   GPU_framebuffer_restore();
 
@@ -438,6 +448,7 @@ void wm_xr_draw_view(const GHOST_XrDrawViewInfo *draw_view, void *customdata)
   shading.flag &= ~V3D_SHADING_SPECULAR_HIGHLIGHT;
   shading.background_type = V3D_SHADING_BACKGROUND_WORLD;
 
+  /* Draws the view into the surface_data->viewport's framebuffers */
   ED_view3d_draw_offscreen_simple(CTX_data_ensure_evaluated_depsgraph(C),
                                   CTX_data_scene(C),
                                   &shading,
@@ -453,22 +464,14 @@ void wm_xr_draw_view(const GHOST_XrDrawViewInfo *draw_view, void *customdata)
                                   true,
                                   NULL,
                                   false,
-                                  offscreen,
-                                  viewport);
+                                  surface_data->offscreen,
+                                  surface_data->viewport);
 
-  BLI_assert(GPU_context_active_get() == DRW_gpu_context_get());
+  /* Re-use the offscreen framebuffer to render the composited viewport into. Keep it bound,
+   * Ghost-XR will then blit from the currently bound framebuffer into the OpenXR swapchain. */
+  GPU_offscreen_bind(surface_data->offscreen, false);
 
-  // TODO
-  //  const bool is_upside_down = surface_data->secondary_ghost_ctx &&
-  //                              GHOST_isUpsideDownContext(surface_data->secondary_ghost_ctx);
-
-  DefaultFramebufferList *dfl = GPU_viewport_framebuffer_list_get(viewport);
-
-  /* Draw into viewport default framebuffer and leave it bound when exiting this function. Ghost-XR
-   * will blit from the currently bound framebuffer into the OpenXR swapchain. */
-  GPU_framebuffer_bind(dfl->default_fb);
-  wmViewport(&rect);
-  GPU_viewport_draw_to_screen(viewport, &rect);
+  wm_xr_draw_viewport_buffers_to_active_framebuffer(surface_data, draw_view);
 }
 
 /** \} */ /* XR Drawing */



More information about the Bf-blender-cvs mailing list