[vlc-devel] [PATCH] direct3d11: fix video position on Windows Phone and WinRT

Steve Lhomme robux4 at gmail.com
Tue Jun 23 13:47:39 CEST 2015


From: Steve Lhomme <robux4 at gmail.com>

the SwapChain dimensions are read from shared private data in the DXGI swap chain
---
 modules/video_output/msw/common.c     | 431 ++++++++++++++++++----------------
 modules/video_output/msw/common.h     |   5 +
 modules/video_output/msw/direct3d11.c | 217 ++++++++++-------
 3 files changed, 364 insertions(+), 289 deletions(-)

diff --git a/modules/video_output/msw/common.c b/modules/video_output/msw/common.c
index 1e5b5f7..1f9ee0b 100644
--- a/modules/video_output/msw/common.c
+++ b/modules/video_output/msw/common.c
@@ -38,12 +38,14 @@
 #include <windows.h>
 #include <assert.h>
 
+#define COBJMACROS
+
 #include "common.h"
 
 #include <vlc_windows_interfaces.h>
 
-#if !VLC_WINSTORE_APP
 static void CommonChangeThumbnailClip(vout_display_t *, bool show);
+#if !VLC_WINSTORE_APP
 static int  CommonControlSetFullscreen(vout_display_t *, bool is_fullscreen);
 
 static void DisableScreensaver(vout_display_t *);
@@ -118,6 +120,229 @@ picture_pool_t *CommonPool(vout_display_t *vd, unsigned count)
     return vd->sys->pool;
 }
 
+/*****************************************************************************
+* UpdateRects: update clipping rectangles
+*****************************************************************************
+* This function is called when the window position or size are changed, and
+* its job is to update the source and destination RECTs used to display the
+* picture.
+*****************************************************************************/
+void UpdateRects(vout_display_t *vd,
+    const vout_display_cfg_t *cfg,
+    const video_format_t *source,
+    bool is_forced)
+{
+    vout_display_sys_t *sys = vd->sys;
+#define rect_src sys->rect_src
+#define rect_src_clipped sys->rect_src_clipped
+#define rect_dest sys->rect_dest
+#define rect_dest_clipped sys->rect_dest_clipped
+
+    RECT  rect;
+    POINT point;
+
+    /* */
+    if (!cfg)
+        cfg = vd->cfg;
+    if (!source)
+        source = &vd->source;
+
+    /* Retrieve the window size */
+#if VLC_WINSTORE_APP
+    rect.left   = 0;
+    rect.top    = 0;
+    uint32_t i_width;
+    uint32_t i_height;
+    UINT dataSize = sizeof(i_width);
+    HRESULT hr = IDXGISwapChain_GetPrivateData(sys->dxgiswapChain, &GUID_SWAPCHAIN_WIDTH, &dataSize, &i_width);
+    if (FAILED(hr)) {
+        msg_Err(vd, "Can't get swapchain width, size %d. (hr=0x%lX)", hr, dataSize);
+        return;
+    }
+    dataSize = sizeof(i_height);
+    hr = IDXGISwapChain_GetPrivateData(sys->dxgiswapChain, &GUID_SWAPCHAIN_HEIGHT, &dataSize, &i_height);
+    if (FAILED(hr)) {
+        msg_Err(vd, "Can't get swapchain height, size %d. (hr=0x%lX)", hr, dataSize);
+        return;
+    }
+    rect.right  = i_width;
+    rect.bottom = i_height;
+#else
+    GetClientRect(sys->hwnd, &rect);
+#endif
+
+    /* Retrieve the window position */
+    point.x = point.y = 0;
+#if !VLC_WINSTORE_APP
+    ClientToScreen(sys->hwnd, &point);
+#endif
+
+    /* If nothing changed, we can return */
+    bool has_moved;
+    bool is_resized;
+#if VLC_WINSTORE_APP
+    has_moved = false;
+    is_resized = rect.right != (sys->rect_display.right - sys->rect_display.left) ||
+        rect.bottom != (sys->rect_display.bottom - sys->rect_display.top);
+    sys->rect_display = rect;
+#else
+    EventThreadUpdateWindowPosition(sys->event, &has_moved, &is_resized,
+        point.x, point.y,
+        rect.right, rect.bottom);
+#endif
+    if (is_resized)
+        vout_display_SendEventDisplaySize(vd, rect.right, rect.bottom);
+    if (!is_forced && !has_moved && !is_resized)
+        return;
+
+    /* Update the window position and size */
+    vout_display_cfg_t place_cfg = *cfg;
+    place_cfg.display.width = rect.right;
+    place_cfg.display.height = rect.bottom;
+
+    vout_display_place_t place;
+    vout_display_PlacePicture(&place, source, &place_cfg, false);
+
+#if !VLC_WINSTORE_APP
+    EventThreadUpdateSourceAndPlace(sys->event, source, &place);
+
+    if (sys->hvideownd)
+        SetWindowPos(sys->hvideownd, 0,
+            place.x, place.y, place.width, place.height,
+            SWP_NOCOPYBITS | SWP_NOZORDER | SWP_ASYNCWINDOWPOS);
+#endif
+
+    /* Destination image position and dimensions */
+#if (defined(MODULE_NAME_IS_direct3d9) || defined(MODULE_NAME_IS_direct3d11) || defined(MODULE_NAME_IS_direct2d)) && !VLC_WINSTORE_APP
+    rect_dest.left = 0;
+    rect_dest.right = place.width;
+    rect_dest.top = 0;
+    rect_dest.bottom = place.height;
+#else
+    rect_dest.left = point.x + place.x;
+    rect_dest.right = rect_dest.left + place.width;
+    rect_dest.top = point.y + place.y;
+    rect_dest.bottom = rect_dest.top + place.height;
+
+#ifdef MODULE_NAME_IS_directdraw
+    /* Apply overlay hardware constraints */
+    if (sys->use_overlay)
+        AlignRect(&rect_dest, sys->i_align_dest_boundary, sys->i_align_dest_size);
+#endif
+
+#endif
+
+#if defined(MODULE_NAME_IS_directdraw)
+    /* UpdateOverlay directdraw function doesn't automatically clip to the
+    * display size so we need to do it otherwise it will fail */
+
+    /* Clip the destination window */
+    if (!IntersectRect(&rect_dest_clipped, &rect_dest,
+        &sys->rect_display)) {
+        SetRectEmpty(&rect_src_clipped);
+        goto exit;
+    }
+
+#ifndef NDEBUG
+    msg_Dbg(vd, "DirectXUpdateRects image_dst_clipped coords:"
+        " %li,%li,%li,%li",
+        rect_dest_clipped.left, rect_dest_clipped.top,
+        rect_dest_clipped.right, rect_dest_clipped.bottom);
+#endif
+
+#else
+
+    /* AFAIK, there are no clipping constraints in Direct3D, OpenGL and GDI */
+    rect_dest_clipped = rect_dest;
+
+#endif
+
+    /* the 2 following lines are to fix a bug when clicking on the desktop */
+    if ((rect_dest_clipped.right - rect_dest_clipped.left) == 0 ||
+        (rect_dest_clipped.bottom - rect_dest_clipped.top) == 0) {
+#if !VLC_WINSTORE_APP
+        SetRectEmpty(&rect_src_clipped);
+#endif
+        goto exit;
+    }
+
+    /* src image dimensions */
+    rect_src.left = 0;
+    rect_src.top = 0;
+    rect_src.right = vd->fmt.i_visible_width;
+    rect_src.bottom = vd->fmt.i_visible_height;
+
+    /* Clip the source image */
+    rect_src_clipped.left = source->i_x_offset +
+        (rect_dest_clipped.left - rect_dest.left) *
+        source->i_visible_width / (rect_dest.right - rect_dest.left);
+    rect_src_clipped.right = source->i_x_offset +
+        source->i_visible_width -
+        (rect_dest.right - rect_dest_clipped.right) *
+        source->i_visible_width / (rect_dest.right - rect_dest.left);
+    rect_src_clipped.top = source->i_y_offset +
+        (rect_dest_clipped.top - rect_dest.top) *
+        source->i_visible_height / (rect_dest.bottom - rect_dest.top);
+    rect_src_clipped.bottom = source->i_y_offset +
+        source->i_visible_height -
+        (rect_dest.bottom - rect_dest_clipped.bottom) *
+        source->i_visible_height / (rect_dest.bottom - rect_dest.top);
+
+#ifdef MODULE_NAME_IS_directdraw
+    /* Apply overlay hardware constraints */
+    if (sys->use_overlay)
+        AlignRect(&rect_src_clipped, sys->i_align_src_boundary, sys->i_align_src_size);
+#elif defined(MODULE_NAME_IS_direct3d9) || defined(MODULE_NAME_IS_direct3d11) || defined(MODULE_NAME_IS_direct2d)
+    /* Needed at least with YUV content */
+    rect_src_clipped.left &= ~1;
+    rect_src_clipped.right &= ~1;
+    rect_src_clipped.top &= ~1;
+    rect_src_clipped.bottom &= ~1;
+#endif
+
+#ifndef NDEBUG
+    msg_Dbg(vd, "DirectXUpdateRects souce"
+        " offset: %i,%i visible: %ix%i",
+        source->i_x_offset, source->i_y_offset,
+        source->i_visible_width, source->i_visible_height);
+    msg_Dbg(vd, "DirectXUpdateRects image_src"
+        " coords: %li,%li,%li,%li",
+        rect_src.left, rect_src.top,
+        rect_src.right, rect_src.bottom);
+    msg_Dbg(vd, "DirectXUpdateRects image_src_clipped"
+        " coords: %li,%li,%li,%li",
+        rect_src_clipped.left, rect_src_clipped.top,
+        rect_src_clipped.right, rect_src_clipped.bottom);
+    msg_Dbg(vd, "DirectXUpdateRects image_dst"
+        " coords: %li,%li,%li,%li",
+        rect_dest.left, rect_dest.top,
+        rect_dest.right, rect_dest.bottom);
+    msg_Dbg(vd, "DirectXUpdateRects image_dst_clipped"
+        " coords: %li,%li,%li,%li",
+        rect_dest_clipped.left, rect_dest_clipped.top,
+        rect_dest_clipped.right, rect_dest_clipped.bottom);
+#endif
+
+#ifdef MODULE_NAME_IS_directdraw
+    /* The destination coordinates need to be relative to the current
+    * directdraw primary surface (display) */
+    rect_dest_clipped.left -= sys->rect_display.left;
+    rect_dest_clipped.right -= sys->rect_display.left;
+    rect_dest_clipped.top -= sys->rect_display.top;
+    rect_dest_clipped.bottom -= sys->rect_display.top;
+#endif
+
+    CommonChangeThumbnailClip(vd, true);
+
+exit:
+    /* Signal the change in size/position */
+    sys->changes |= DX_POSITION_CHANGE;
+
+#undef rect_src
+#undef rect_src_clipped
+#undef rect_dest
+#undef rect_dest_clipped
+}
 
 #if !VLC_WINSTORE_APP
 /* */
@@ -323,196 +548,6 @@ static void CommonChangeThumbnailClip(vout_display_t *vd, bool show)
     CoUninitialize();
 }
 
-/*****************************************************************************
- * UpdateRects: update clipping rectangles
- *****************************************************************************
- * This function is called when the window position or size are changed, and
- * its job is to update the source and destination RECTs used to display the
- * picture.
- *****************************************************************************/
-void UpdateRects(vout_display_t *vd,
-                  const vout_display_cfg_t *cfg,
-                  const video_format_t *source,
-                  bool is_forced)
-{
-    vout_display_sys_t *sys = vd->sys;
-#define rect_src sys->rect_src
-#define rect_src_clipped sys->rect_src_clipped
-#define rect_dest sys->rect_dest
-#define rect_dest_clipped sys->rect_dest_clipped
-
-    RECT  rect;
-    POINT point;
-
-    /* */
-    if (!cfg)
-        cfg = vd->cfg;
-    if (!source)
-        source = &vd->source;
-
-    /* Retrieve the window size */
-    GetClientRect(sys->hwnd, &rect);
-
-    /* Retrieve the window position */
-    point.x = point.y = 0;
-    ClientToScreen(sys->hwnd, &point);
-
-    /* If nothing changed, we can return */
-    bool has_moved;
-    bool is_resized;
-    EventThreadUpdateWindowPosition(sys->event, &has_moved, &is_resized,
-                                    point.x, point.y,
-                                    rect.right, rect.bottom);
-    if (is_resized)
-        vout_display_SendEventDisplaySize(vd, rect.right, rect.bottom);
-    if (!is_forced && !has_moved && !is_resized)
-        return;
-
-    /* Update the window position and size */
-    vout_display_cfg_t place_cfg = *cfg;
-    place_cfg.display.width  = rect.right;
-    place_cfg.display.height = rect.bottom;
-
-    vout_display_place_t place;
-    vout_display_PlacePicture(&place, source, &place_cfg, false);
-
-    EventThreadUpdateSourceAndPlace(sys->event, source, &place);
-
-    if (sys->hvideownd)
-        SetWindowPos(sys->hvideownd, 0,
-                     place.x, place.y, place.width, place.height,
-                     SWP_NOCOPYBITS|SWP_NOZORDER|SWP_ASYNCWINDOWPOS);
-
-    /* Destination image position and dimensions */
-#if defined(MODULE_NAME_IS_direct3d9) || defined(MODULE_NAME_IS_direct3d11) || defined(MODULE_NAME_IS_direct2d)
-    rect_dest.left   = 0;
-    rect_dest.right  = place.width;
-    rect_dest.top    = 0;
-    rect_dest.bottom = place.height;
-#else
-    rect_dest.left = point.x + place.x;
-    rect_dest.right = rect_dest.left + place.width;
-    rect_dest.top = point.y + place.y;
-    rect_dest.bottom = rect_dest.top + place.height;
-
-#ifdef MODULE_NAME_IS_directdraw
-    /* Apply overlay hardware constraints */
-    if (sys->use_overlay)
-        AlignRect(&rect_dest, sys->i_align_dest_boundary, sys->i_align_dest_size);
-#endif
-
-#endif
-
-#if defined(MODULE_NAME_IS_directdraw)
-    /* UpdateOverlay directdraw function doesn't automatically clip to the
-     * display size so we need to do it otherwise it will fail */
-
-    /* Clip the destination window */
-    if (!IntersectRect(&rect_dest_clipped, &rect_dest,
-                       &sys->rect_display)) {
-        SetRectEmpty(&rect_src_clipped);
-        goto exit;
-    }
-
-#ifndef NDEBUG
-    msg_Dbg(vd, "DirectXUpdateRects image_dst_clipped coords:"
-                " %li,%li,%li,%li",
-                rect_dest_clipped.left, rect_dest_clipped.top,
-                rect_dest_clipped.right, rect_dest_clipped.bottom);
-#endif
-
-#else
-
-    /* AFAIK, there are no clipping constraints in Direct3D, OpenGL and GDI */
-    rect_dest_clipped = rect_dest;
-
-#endif
-
-    /* the 2 following lines are to fix a bug when clicking on the desktop */
-    if ((rect_dest_clipped.right - rect_dest_clipped.left) == 0 ||
-        (rect_dest_clipped.bottom - rect_dest_clipped.top) == 0) {
-        SetRectEmpty(&rect_src_clipped);
-        goto exit;
-    }
-
-    /* src image dimensions */
-    rect_src.left   = 0;
-    rect_src.top    = 0;
-    rect_src.right  = vd->fmt.i_visible_width;
-    rect_src.bottom = vd->fmt.i_visible_height;
-
-    /* Clip the source image */
-    rect_src_clipped.left = source->i_x_offset +
-      (rect_dest_clipped.left - rect_dest.left) *
-      source->i_visible_width / (rect_dest.right - rect_dest.left);
-    rect_src_clipped.right = source->i_x_offset +
-      source->i_visible_width -
-      (rect_dest.right - rect_dest_clipped.right) *
-      source->i_visible_width / (rect_dest.right - rect_dest.left);
-    rect_src_clipped.top = source->i_y_offset +
-      (rect_dest_clipped.top - rect_dest.top) *
-      source->i_visible_height / (rect_dest.bottom - rect_dest.top);
-    rect_src_clipped.bottom = source->i_y_offset +
-      source->i_visible_height -
-      (rect_dest.bottom - rect_dest_clipped.bottom) *
-      source->i_visible_height / (rect_dest.bottom - rect_dest.top);
-
-#ifdef MODULE_NAME_IS_directdraw
-    /* Apply overlay hardware constraints */
-    if (sys->use_overlay)
-        AlignRect(&rect_src_clipped, sys->i_align_src_boundary, sys->i_align_src_size);
-#elif defined(MODULE_NAME_IS_direct3d9) || defined(MODULE_NAME_IS_direct3d11) || defined(MODULE_NAME_IS_direct2d)
-    /* Needed at least with YUV content */
-    rect_src_clipped.left &= ~1;
-    rect_src_clipped.right &= ~1;
-    rect_src_clipped.top &= ~1;
-    rect_src_clipped.bottom &= ~1;
-#endif
-
-#ifndef NDEBUG
-    msg_Dbg(vd, "DirectXUpdateRects souce"
-                " offset: %i,%i visible: %ix%i",
-                source->i_x_offset, source->i_y_offset,
-                source->i_visible_width, source->i_visible_height);
-    msg_Dbg(vd, "DirectXUpdateRects image_src"
-                " coords: %li,%li,%li,%li",
-                rect_src.left, rect_src.top,
-                rect_src.right, rect_src.bottom);
-    msg_Dbg(vd, "DirectXUpdateRects image_src_clipped"
-                " coords: %li,%li,%li,%li",
-                rect_src_clipped.left, rect_src_clipped.top,
-                rect_src_clipped.right, rect_src_clipped.bottom);
-    msg_Dbg(vd, "DirectXUpdateRects image_dst"
-                " coords: %li,%li,%li,%li",
-                rect_dest.left, rect_dest.top,
-                rect_dest.right, rect_dest.bottom);
-    msg_Dbg(vd, "DirectXUpdateRects image_dst_clipped"
-                " coords: %li,%li,%li,%li",
-                rect_dest_clipped.left, rect_dest_clipped.top,
-                rect_dest_clipped.right, rect_dest_clipped.bottom);
-#endif
-
-#ifdef MODULE_NAME_IS_directdraw
-    /* The destination coordinates need to be relative to the current
-     * directdraw primary surface (display) */
-    rect_dest_clipped.left -= sys->rect_display.left;
-    rect_dest_clipped.right -= sys->rect_display.left;
-    rect_dest_clipped.top -= sys->rect_display.top;
-    rect_dest_clipped.bottom -= sys->rect_display.top;
-#endif
-
-    CommonChangeThumbnailClip(vd, true);
-
-exit:
-    /* Signal the change in size/position */
-    sys->changes |= DX_POSITION_CHANGE;
-
-#undef rect_src
-#undef rect_src_clipped
-#undef rect_dest
-#undef rect_dest_clipped
-}
-
 static int CommonControlSetFullscreen(vout_display_t *vd, bool is_fullscreen)
 {
     vout_display_sys_t *sys = vd->sys;
@@ -729,12 +764,10 @@ int CommonControl(vout_display_t *vd, int query, va_list args)
     }
 }
 
-void CommonManage(vout_display_t *vd) {};
-void CommonClean(vout_display_t *vd) {};
-void CommonDisplay(vout_display_t *vd) {};
-void UpdateRects(vout_display_t *vd,
-                  const vout_display_cfg_t *cfg,
-                  const video_format_t *source,
-                  bool is_forced)
-{};
+void CommonManage(vout_display_t *vd) {
+    UpdateRects(vd, NULL, NULL, false);
+}
+void CommonClean(vout_display_t *vd) {}
+void CommonDisplay(vout_display_t *vd) {}
+void CommonChangeThumbnailClip(vout_display_t *vd, bool show) {}
 #endif
diff --git a/modules/video_output/msw/common.h b/modules/video_output/msw/common.h
index 4f7389d..7064dd8 100644
--- a/modules/video_output/msw/common.h
+++ b/modules/video_output/msw/common.h
@@ -69,6 +69,11 @@ typedef struct
 } d3d_quad_t;
 #endif
 
+#if VLC_WINSTORE_APP
+extern const GUID GUID_SWAPCHAIN_WIDTH;
+extern const GUID GUID_SWAPCHAIN_HEIGHT;
+#endif
+
 /*****************************************************************************
  * vout_sys_t: video output method descriptor
  *****************************************************************************
diff --git a/modules/video_output/msw/direct3d11.c b/modules/video_output/msw/direct3d11.c
index 481a673..f5d33bb 100644
--- a/modules/video_output/msw/direct3d11.c
+++ b/modules/video_output/msw/direct3d11.c
@@ -32,7 +32,6 @@
 #define COBJMACROS
 #define INITGUID
 #include <d3d11.h>
-#include <d3dtypes.h>
 
 /* avoided until we can pass ISwapchainPanel without c++/cx mode
 # include <windows.ui.xaml.media.dxinterop.h> */
@@ -48,6 +47,9 @@
 # define D3DCompile(args...)                    sys->OurD3DCompile(args)
 #endif
 
+DEFINE_GUID(GUID_SWAPCHAIN_WIDTH,  0xf1b59347, 0x1643, 0x411a, 0xad, 0x6b, 0xc7, 0x80, 0x17, 0x7a, 0x06, 0xb6);
+DEFINE_GUID(GUID_SWAPCHAIN_HEIGHT, 0x6ea976a0, 0x9d60, 0x4bb7, 0xa5, 0xa9, 0x7d, 0xd1, 0x18, 0x7f, 0xc9, 0xbd);
+
 static int  Open(vlc_object_t *);
 static void Close(vlc_object_t *);
 
@@ -66,9 +68,9 @@ vlc_module_begin ()
     add_bool("direct3d11-hw-blending", true, HW_BLENDING_TEXT, HW_BLENDING_LONGTEXT, true)
 
 #if VLC_WINSTORE_APP
-    add_integer("winrt-d3ddevice",     0x0, NULL, NULL, true);
-    add_integer("winrt-d3dcontext",    0x0, NULL, NULL, true);
-    add_integer("winrt-dxgiswapchain", 0x0, NULL, NULL, true);
+    add_integer("winrt-d3ddevice",     0x0, NULL, NULL, true); /* ID3D11Device*        */
+    add_integer("winrt-d3dcontext",    0x0, NULL, NULL, true); /* ID3D11DeviceContext* */
+    add_integer("winrt-swapchain",     0x0, NULL, NULL, true); /* IDXGISwapChain1*     */
 #endif
 
     set_capability("vout display", 240)
@@ -128,10 +130,14 @@ typedef struct
 
 /* matches the D3D11_INPUT_ELEMENT_DESC we setup */
 typedef struct d3d_vertex_t {
-    D3DVECTOR   position;
     struct {
-        D3DVALUE x;
-        D3DVALUE y;
+        FLOAT x;
+        FLOAT y;
+        FLOAT z;
+    } position;
+    struct {
+        FLOAT x;
+        FLOAT y;
     } texture;
     FLOAT       opacity;
 } d3d_vertex_t;
@@ -166,9 +172,10 @@ static void Direct3D11DeleteRegions(int, picture_t **);
 static int Direct3D11MapSubpicture(vout_display_t *, int *, picture_t ***, subpicture_t *);
 
 static int AllocQuad(vout_display_t *, const video_format_t *, d3d_quad_t *,
-                     d3d_quad_cfg_t *, ID3D11PixelShader *,
-                     const float vertices[4 * sizeof(d3d_vertex_t)]);
+                     d3d_quad_cfg_t *, ID3D11PixelShader *);
 static void ReleaseQuad(d3d_quad_t *);
+static void UpdatePicQuadPosition(vout_display_t *);
+static void UpdateQuadPosition(vout_display_t *, const d3d_quad_t *, const RECT *, int w, int h, float o);
 
 static void Manage(vout_display_t *vd);
 
@@ -396,7 +403,7 @@ static int Open(vlc_object_t *object)
 # endif
 
 #else
-    IDXGISwapChain1* dxgiswapChain  = var_InheritInteger(vd, "winrt-dxgiswapchain");
+    IDXGISwapChain1* dxgiswapChain  = var_InheritInteger(vd, "winrt-swapchain");
     if (!dxgiswapChain)
         return VLC_EGENERIC;
     ID3D11Device* d3ddevice         = var_InheritInteger(vd, "winrt-d3ddevice");
@@ -636,8 +643,22 @@ static HRESULT UpdateBackBuffer(vout_display_t *vd)
     HRESULT hr;
     ID3D11Texture2D* pDepthStencil;
     ID3D11Texture2D* pBackBuffer;
-    int i_width  = RECTWidth(sys->rect_dest_clipped);
-    int i_height = RECTHeight(sys->rect_dest_clipped);
+    uint32_t i_width  = RECTWidth(sys->rect_dest_clipped);
+    uint32_t i_height = RECTHeight(sys->rect_dest_clipped);
+#if VLC_WINSTORE_APP
+    UINT dataSize = sizeof(i_width);
+    hr = IDXGISwapChain_GetPrivateData(sys->dxgiswapChain, &GUID_SWAPCHAIN_WIDTH, &dataSize, &i_width);
+    if (FAILED(hr)) {
+        msg_Err(vd, "Can't get swapchain width, size %d. (hr=0x%lX)", hr, dataSize);
+        return hr;
+    }
+    dataSize = sizeof(i_height);
+    hr = IDXGISwapChain_GetPrivateData(sys->dxgiswapChain, &GUID_SWAPCHAIN_HEIGHT, &dataSize, &i_height);
+    if (FAILED(hr)) {
+        msg_Err(vd, "Can't get swapchain height, size %d. (hr=0x%lX)", hr, dataSize);
+        return hr;
+    }
+#endif
 
     if (sys->d3drenderTargetView) {
         ID3D11RenderTargetView_Release(sys->d3drenderTargetView);
@@ -648,13 +669,6 @@ static HRESULT UpdateBackBuffer(vout_display_t *vd)
         sys->d3ddepthStencilView = NULL;
     }
 
-#if VLC_WINSTORE_APP
-    DXGI_SWAP_CHAIN_DESC1 swapDesc;
-    hr = IDXGISwapChain1_GetDesc1(sys->dxgiswapChain, &swapDesc);
-    i_width = swapDesc.Width;
-    i_height = swapDesc.Height;
-#endif
-
     hr = IDXGISwapChain_ResizeBuffers(sys->dxgiswapChain, 0, i_width, i_height,
         DXGI_FORMAT_UNKNOWN, 0);
     if (FAILED(hr)) {
@@ -737,6 +751,8 @@ static void Manage(vout_display_t *vd)
                 RECTHeight(sys->rect_dest_clipped));
 
         UpdateBackBuffer(vd);
+
+        UpdatePicQuadPosition(vd);
     }
 }
 
@@ -1145,6 +1161,30 @@ static void Direct3D11Close(vout_display_t *vd)
     msg_Dbg(vd, "Direct3D11 device adapter closed");
 }
 
+static void UpdatePicQuadPosition(vout_display_t *vd)
+{
+    vout_display_sys_t *sys = vd->sys;
+    int i_width  = RECTWidth(sys->rect_dest_clipped);
+    int i_height = RECTHeight(sys->rect_dest_clipped);
+#if VLC_WINSTORE_APP
+    UINT dataSize = sizeof(i_width);
+    HRESULT hr = IDXGISwapChain_GetPrivateData(sys->dxgiswapChain, &GUID_SWAPCHAIN_WIDTH, &dataSize, &i_width);
+    if (FAILED(hr)) {
+        msg_Err(vd, "Can't get swapchain width, size %d. (hr=0x%lX)", hr, dataSize);
+        return hr;
+    }
+    dataSize = sizeof(i_height);
+    hr = IDXGISwapChain_GetPrivateData(sys->dxgiswapChain, &GUID_SWAPCHAIN_HEIGHT, &dataSize, &i_height);
+    if (FAILED(hr)) {
+        msg_Err(vd, "Can't get swapchain height, size %d. (hr=0x%lX)", hr, dataSize);
+        return hr;
+    }
+#endif
+
+    /* Map the subpicture to sys->rect_dest_clipped */
+    UpdateQuadPosition(vd, &sys->picQuad, &sys->rect_dest_clipped, i_width, i_height, 1.0f);
+}
+
 /* TODO : handle errors better
    TODO : seperate out into smaller functions like createshaders */
 static int Direct3D11CreateResources(vout_display_t *vd, video_format_t *fmt)
@@ -1333,20 +1373,15 @@ static int Direct3D11CreateResources(vout_display_t *vd, video_format_t *fmt)
         }
     }
 
-    float vertices[4 * sizeof(d3d_vertex_t)] = {
-    -1.0f, -1.0f, -1.0f,  0.0f, 1.0f,  1.0f, // bottom left
-     1.0f, -1.0f, -1.0f,  1.0f, 1.0f,  1.0f, // bottom right
-     1.0f,  1.0f, -1.0f,  1.0f, 0.0f,  1.0f, // top right
-    -1.0f,  1.0f, -1.0f,  0.0f, 0.0f,  1.0f, // top left
-    };
-
-    if (AllocQuad( vd, fmt, &sys->picQuad, &sys->picQuadConfig, pPicQuadShader, vertices )!=VLC_SUCCESS) {
+    if (AllocQuad( vd, fmt, &sys->picQuad, &sys->picQuadConfig, pPicQuadShader) != VLC_SUCCESS) {
         ID3D11PixelShader_Release(pPicQuadShader);
         msg_Err(vd, "Could not Create the main quad picture. (hr=0x%lX)", hr);
         return VLC_EGENERIC;
     }
     ID3D11PixelShader_Release(pPicQuadShader);
 
+    UpdatePicQuadPosition(vd);
+
     D3D11_SAMPLER_DESC sampDesc;
     memset(&sampDesc, 0, sizeof(sampDesc));
     sampDesc.Filter = D3D11_FILTER_MIN_MAG_LINEAR_MIP_POINT;
@@ -1430,24 +1465,19 @@ static void Direct3D11DestroyPool(vout_display_t *vd)
 }
 
 static int AllocQuad(vout_display_t *vd, const video_format_t *fmt, d3d_quad_t *quad,
-                     d3d_quad_cfg_t *cfg, ID3D11PixelShader *d3dpixelShader,
-                     const float vertices[4 * sizeof(d3d_vertex_t)])
+                     d3d_quad_cfg_t *cfg, ID3D11PixelShader *d3dpixelShader)
 {
     vout_display_sys_t *sys = vd->sys;
     HRESULT hr;
 
     D3D11_BUFFER_DESC bd;
     memset(&bd, 0, sizeof(bd));
-    bd.Usage = vertices==NULL ? D3D11_USAGE_DYNAMIC : D3D11_USAGE_DEFAULT;
+    bd.Usage = D3D11_USAGE_DYNAMIC;
     bd.ByteWidth = sizeof(d3d_vertex_t) * 4;
     bd.BindFlags = D3D11_BIND_VERTEX_BUFFER;
-    bd.CPUAccessFlags = vertices==NULL ? D3D11_CPU_ACCESS_WRITE : 0;
-
-    D3D11_SUBRESOURCE_DATA InitData = {
-        .pSysMem = vertices,
-    };
+    bd.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE;
 
-    hr = ID3D11Device_CreateBuffer(sys->d3ddevice, &bd, vertices==NULL ? NULL : &InitData, &quad->pVertexBuffer);
+    hr = ID3D11Device_CreateBuffer(sys->d3ddevice, &bd, NULL, &quad->pVertexBuffer);
     if(FAILED(hr)) {
       msg_Err(vd, "Failed to create vertex buffer.");
       goto error;
@@ -1571,6 +1601,60 @@ static void DestroyPictureQuad(picture_t *p_picture)
     free( p_picture );
 }
 
+static void UpdateQuadPosition(vout_display_t *vd, const d3d_quad_t *quad, const RECT *dst, int i_width, int i_height, float opacity)
+{
+    vout_display_sys_t *sys = vd->sys;
+    D3D11_MAPPED_SUBRESOURCE mappedResource;
+
+    // adjust with the center at 0,0 and the edges at -1/1
+    float left   = -1.0f + 2.0f * ((float) dst->left   / i_width );
+    float right  = -1.0f + 2.0f * ((float) dst->right  / i_width );
+    float top    =  1.0f - 2.0f * ((float) dst->top    / i_height );
+    float bottom =  1.0f - 2.0f * ((float) dst->bottom / i_height );
+
+    HRESULT hr = ID3D11DeviceContext_Map(sys->d3dcontext, (ID3D11Resource *)quad->pVertexBuffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &mappedResource);
+    if (SUCCEEDED(hr)) {
+        d3d_vertex_t *dst_data = mappedResource.pData;
+
+        // bottom left
+        dst_data[0].position.x = left;
+        dst_data[0].position.y = bottom;
+        dst_data[0].position.z = 0.0f;
+        dst_data[0].texture.x = 0.0f;
+        dst_data[0].texture.y = 1.0f;
+        dst_data[0].opacity = opacity;
+
+        // bottom right
+        dst_data[1].position.x = right;
+        dst_data[1].position.y = bottom;
+        dst_data[1].position.z = 0.0f;
+        dst_data[1].texture.x = 1.0f;
+        dst_data[1].texture.y = 1.0f;
+        dst_data[1].opacity = opacity;
+
+        // top right
+        dst_data[2].position.x = right;
+        dst_data[2].position.y = top;
+        dst_data[2].position.z = 0.0f;
+        dst_data[2].texture.x = 1.0f;
+        dst_data[2].texture.y = 0.0f;
+        dst_data[2].opacity = opacity;
+
+        // top left
+        dst_data[3].position.x = left;
+        dst_data[3].position.y = top;
+        dst_data[3].position.z = 0.0f;
+        dst_data[3].texture.x = 0.0f;
+        dst_data[3].texture.y = 0.0f;
+        dst_data[3].opacity = opacity;
+
+        ID3D11DeviceContext_Unmap(sys->d3dcontext, (ID3D11Resource *)quad->pVertexBuffer, 0);
+    }
+    else {
+        msg_Err(vd, "Failed to lock the subpicture vertex buffer (hr=0x%lX)", hr);
+    }
+}
+
 static int Direct3D11MapSubpicture(vout_display_t *vd, int *subpicture_region_count,
                                    picture_t ***region, subpicture_t *subpicture)
 {
@@ -1619,7 +1703,7 @@ static int Direct3D11MapSubpicture(vout_display_t *vd, int *subpicture_region_co
                 .textureFormat      = sys->d3dregion_format,
                 .resourceFormatYRGB = sys->d3dregion_format,
             };
-            err = AllocQuad(vd, &r->fmt, d3dquad, &rgbaCfg, sys->pSPUPixelShader, NULL);
+            err = AllocQuad(vd, &r->fmt, d3dquad, &rgbaCfg, sys->pSPUPixelShader);
             if (err != VLC_SUCCESS) {
                 msg_Err(vd, "Failed to create %dx%d texture for OSD",
                         r->fmt.i_visible_width, r->fmt.i_visible_height);
@@ -1661,15 +1745,12 @@ static int Direct3D11MapSubpicture(vout_display_t *vd, int *subpicture_region_co
         picture_CopyPixels(quad_picture, r->p_picture);
 
         /* Map the subpicture to sys->rect_dest */
-        RECT src;
-        src.left   = 0;
-        src.right  = src.left + r->fmt.i_visible_width;
-        src.top    = 0;
-        src.bottom = src.top  + r->fmt.i_visible_height;
+        int i_original_width  = subpicture->i_original_picture_width;
+        int i_original_height = subpicture->i_original_picture_height;
 
         const RECT video = sys->rect_dest;
-        const float scale_w = (float)(video.right  - video.left) / subpicture->i_original_picture_width;
-        const float scale_h = (float)(video.bottom - video.top)  / subpicture->i_original_picture_height;
+        const float scale_w = (float)(video.right  - video.left) / i_original_width;
+        const float scale_h = (float)(video.bottom - video.top)  / i_original_height;
 
         RECT dst;
         dst.left   = video.left + scale_w * r->i_x,
@@ -1677,54 +1758,10 @@ static int Direct3D11MapSubpicture(vout_display_t *vd, int *subpicture_region_co
         dst.top    = video.top  + scale_h * r->i_y,
         dst.bottom = dst.top  + scale_h * r->fmt.i_visible_height;
 
-        // adjust with the center at 0,0 and the edges at -1/1
-        float left   = ((float)dst.left   / subpicture->i_original_picture_width ) * 2.0f - 1.0f;
-        float right  = ((float)dst.right  / subpicture->i_original_picture_width ) * 2.0f - 1.0f;
-        float top    = 1.0f - 2.0f * dst.top    / subpicture->i_original_picture_height;
-        float bottom = 1.0f - 2.0f * dst.bottom / subpicture->i_original_picture_height;
-
         float opacity = (float)r->i_alpha / 255.0f;
 
-        hr = ID3D11DeviceContext_Map(sys->d3dcontext, (ID3D11Resource *)((d3d_quad_t *) quad_picture->p_sys)->pVertexBuffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &mappedResource);
-        if( SUCCEEDED(hr) ) {
-            d3d_vertex_t *dst_data = mappedResource.pData;
-
-            // bottom left
-            dst_data[0].position.x = left;
-            dst_data[0].position.y = bottom;
-            dst_data[0].position.z = 0.0f;
-            dst_data[0].texture.x = 0.0f;
-            dst_data[0].texture.y = 1.0f;
-            dst_data[0].opacity   = opacity;
-
-            // bottom right
-            dst_data[1].position.x = right;
-            dst_data[1].position.y = bottom;
-            dst_data[1].position.z = 0.0f;
-            dst_data[1].texture.x = 1.0f;
-            dst_data[1].texture.y = 1.0f;
-            dst_data[1].opacity   = opacity;
-
-            // top right
-            dst_data[2].position.x = right;
-            dst_data[2].position.y = top;
-            dst_data[2].position.z = 0.0f;
-            dst_data[2].texture.x = 1.0f;
-            dst_data[2].texture.y = 0.0f;
-            dst_data[2].opacity   = opacity;
-
-            // top left
-            dst_data[3].position.x = left;
-            dst_data[3].position.y = top;
-            dst_data[3].position.z = 0.0f;
-            dst_data[3].texture.x = 0.0f;
-            dst_data[3].texture.y = 0.0f;
-            dst_data[3].opacity   = opacity;
-
-            ID3D11DeviceContext_Unmap(sys->d3dcontext, (ID3D11Resource *)((d3d_quad_t *) quad_picture->p_sys)->pVertexBuffer, 0);
-        } else {
-            msg_Err(vd, "Failed to lock the subpicture vertex buffer (hr=0x%lX)", hr );
-        }
+        UpdateQuadPosition(vd, (d3d_quad_t *)quad_picture->p_sys, &dst,
+                           i_original_width, i_original_height, opacity);
     }
     return VLC_SUCCESS;
 }
-- 
2.4.2




More information about the vlc-devel mailing list