[vlc-devel] [PATCH] direct3d9: support rendering of D3D9 surfaces coming out of DXVA2

Steve Lhomme robUx4 at videolabs.io
Tue Apr 28 16:56:02 CEST 2015


---
 modules/video_output/msw/direct3d9.c | 160 +++++++++++++++++------------------
 1 file changed, 80 insertions(+), 80 deletions(-)

diff --git a/modules/video_output/msw/direct3d9.c b/modules/video_output/msw/direct3d9.c
index db96275..3f01d70 100644
--- a/modules/video_output/msw/direct3d9.c
+++ b/modules/video_output/msw/direct3d9.c
@@ -50,6 +50,7 @@
 
 #include "common.h"
 #include "builtin_shaders.h"
+#include "../../src/win32/direct3d9_pool.h"
 
 /*****************************************************************************
  * Module descriptor
@@ -202,10 +203,10 @@ static int Open(vlc_object_t *object)
 
     /* */
     vout_display_info_t info = vd->info;
-    info.is_slow = true;
+    info.is_slow = fmt.i_chroma != VLC_CODEC_D3D9_OPAQUE;
     info.has_double_click = true;
     info.has_hide_mouse = false;
-    info.has_pictures_invalid = true;
+    info.has_pictures_invalid = fmt.i_chroma != VLC_CODEC_D3D9_OPAQUE;
     info.has_event_thread = true;
     if (var_InheritBool(vd, "direct3d9-hw-blending") &&
         sys->d3dregion_format != D3DFMT_UNKNOWN &&
@@ -274,7 +275,8 @@ static void Close(vlc_object_t *object)
 /* */
 static picture_pool_t *Pool(vout_display_t *vd, unsigned count)
 {
-    VLC_UNUSED(count);
+    if ( vd->sys->pool == NULL )
+        vd->sys->pool = AllocPoolD3D9Ex( VLC_OBJECT(vd), vd->sys->d3ddev, &vd->fmt, count );
     return vd->sys->pool;
 }
 
@@ -283,21 +285,18 @@ static void Direct3D9UnlockSurface(picture_t *);
 
 static void Prepare(vout_display_t *vd, picture_t *picture, subpicture_t *subpicture)
 {
+    VLC_UNUSED(subpicture);
+
     vout_display_sys_t *sys = vd->sys;
     LPDIRECT3DSURFACE9 surface = picture->p_sys->surface;
-#if 0
-    picture_Release(picture);
-    VLC_UNUSED(subpicture);
-#else
+
     /* FIXME it is a bit ugly, we need the surface to be unlocked for
      * rendering.
      *  The clean way would be to release the picture (and ensure that
      * the vout doesn't keep a reference). But because of the vout
      * wrapper, we can't */
-
-    Direct3D9UnlockSurface(picture);
-    VLC_UNUSED(subpicture);
-#endif
+    if ( picture->format.i_chroma != VLC_CODEC_D3D9_OPAQUE )
+        Direct3D9UnlockSurface(picture);
 
     /* check if device is still available */
     HRESULT hr = IDirect3DDevice9_TestCooperativeLevel(sys->d3ddev);
@@ -335,6 +334,8 @@ static void Prepare(vout_display_t *vd, picture_t *picture, subpicture_t *subpic
 
 static void Display(vout_display_t *vd, picture_t *picture, subpicture_t *subpicture)
 {
+    VLC_UNUSED(subpicture);
+
     vout_display_sys_t *sys = vd->sys;
     LPDIRECT3DDEVICE9 d3ddev = sys->d3ddev;
 
@@ -354,14 +355,10 @@ static void Display(vout_display_t *vd, picture_t *picture, subpicture_t *subpic
         msg_Dbg(vd, "Failed IDirect3DDevice9_Present: 0x%0lx", hr);
     }
 
-#if 0
-    VLC_UNUSED(picture);
-    VLC_UNUSED(subpicture);
-#else
     /* XXX See Prepare() */
-    Direct3D9LockSurface(picture);
+    if ( picture->format.i_chroma != VLC_CODEC_D3D9_OPAQUE )
+        Direct3D9LockSurface(picture);
     picture_Release(picture);
-#endif
     if (subpicture)
         subpicture_Delete(subpicture);
 
@@ -860,6 +857,7 @@ static const d3d_format_t d3d_formats[] = {
     { "YV12",       MAKEFOURCC('Y','V','1','2'),    VLC_CODEC_I420,  0,0,0 },
     { "YV12",       MAKEFOURCC('Y','V','1','2'),    VLC_CODEC_J420,  0,0,0 },
     { "NV12",       MAKEFOURCC('N','V','1','2'),    VLC_CODEC_NV12,  0,0,0 },
+    { "DXVANV12",   MAKEFOURCC('N','V','1','2'),    VLC_CODEC_D3D9_OPAQUE,  0,0,0 },
     { "UYVY",       D3DFMT_UYVY,    VLC_CODEC_UYVY,  0,0,0 },
     { "YUY2",       D3DFMT_YUY2,    VLC_CODEC_YUYV,  0,0,0 },
     { "X8R8G8B8",   D3DFMT_X8R8G8B8,VLC_CODEC_RGB32, 0xff0000, 0x00ff00, 0x0000ff },
@@ -879,8 +877,11 @@ static const d3d_format_t *Direct3DFindFormat(vout_display_t *vd, vlc_fourcc_t c
 
     for (unsigned pass = 0; pass < 2; pass++) {
         const vlc_fourcc_t *list;
+        const vlc_fourcc_t dxva_chroma[] = {chroma, 0};
 
-        if (pass == 0 && sys->allow_hw_yuv && vlc_fourcc_IsYUV(chroma))
+        if (pass == 0 && chroma == VLC_CODEC_D3D9_OPAQUE)
+            list = dxva_chroma;
+        else if (pass == 0 && sys->allow_hw_yuv && vlc_fourcc_IsYUV(chroma))
             list = vlc_fourcc_GetYUVFallback(chroma);
         else if (pass == 1)
             list = vlc_fourcc_GetRGBFallback(chroma);
@@ -968,64 +969,66 @@ static int Direct3D9CreatePool(vout_display_t *vd, video_format_t *fmt)
 
     /* We create one picture.
      * It is useless to create more as we can't be used for direct rendering */
-
-    /* Create a surface */
-    LPDIRECT3DSURFACE9 surface;
-    HRESULT hr = IDirect3DDevice9_CreateOffscreenPlainSurface(d3ddev,
-                                                              fmt->i_visible_width,
-                                                              fmt->i_visible_height,
-                                                              d3dfmt->format,
-                                                              D3DPOOL_DEFAULT,
-                                                              &surface,
-                                                              NULL);
-    if (FAILED(hr)) {
-        msg_Err(vd, "Failed to create picture surface. (hr=0x%lx)", hr);
-        return VLC_EGENERIC;
-    }
+    if ( fmt->i_chroma != VLC_CODEC_D3D9_OPAQUE )
+    {
+        /* Create a surface */
+        LPDIRECT3DSURFACE9 surface;
+        HRESULT hr = IDirect3DDevice9_CreateOffscreenPlainSurface(d3ddev,
+                                                                  fmt->i_visible_width,
+                                                                  fmt->i_visible_height,
+                                                                  d3dfmt->format,
+                                                                  D3DPOOL_DEFAULT,
+                                                                  &surface,
+                                                                  NULL);
+        if (FAILED(hr)) {
+            msg_Err(vd, "Failed to create picture surface. (hr=0x%lx)", hr);
+            return VLC_EGENERIC;
+        }
 
 #ifndef NDEBUG
-    msg_Dbg(vd, "Direct3D created offscreen surface: %ix%i",
-                fmt->i_visible_width, fmt->i_visible_height);
+        msg_Dbg(vd, "Direct3D created offscreen surface: %ix%i",
+                    fmt->i_visible_width, fmt->i_visible_height);
 #endif
 
-    /* fill surface with black color */
-    IDirect3DDevice9_ColorFill(d3ddev, surface, NULL, D3DCOLOR_ARGB(0xFF, 0, 0, 0));
+        /* fill surface with black color */
+        IDirect3DDevice9_ColorFill(d3ddev, surface, NULL, D3DCOLOR_ARGB(0xFF, 0, 0, 0));
 
-    /* Create the associated picture */
-    picture_sys_t *picsys = malloc(sizeof(*picsys));
-    if (unlikely(picsys == NULL)) {
-        IDirect3DSurface9_Release(surface);
-        return VLC_ENOMEM;
-    }
-    picsys->surface = surface;
-    picsys->fallback = NULL;
-
-    picture_resource_t resource = { .p_sys = picsys };
-    for (int i = 0; i < PICTURE_PLANE_MAX; i++)
-        resource.p[i].i_lines = fmt->i_visible_height / (i > 0 ? 2 : 1);
-
-    picture_t *picture = picture_NewFromResource(fmt, &resource);
-    if (!picture) {
-        msg_Err(vd, "Failed to create a picture from resources.");
-        IDirect3DSurface9_Release(surface);
-        free(picsys);
-        return VLC_ENOMEM;
-    }
-    sys->picsys = picsys;
-
-    /* Wrap it into a picture pool */
-    picture_pool_configuration_t pool_cfg;
-    memset(&pool_cfg, 0, sizeof(pool_cfg));
-    pool_cfg.picture_count = 1;
-    pool_cfg.picture       = &picture;
-    pool_cfg.lock          = Direct3D9LockSurface;
-    pool_cfg.unlock        = Direct3D9UnlockSurface;
-
-    sys->pool = picture_pool_NewExtended(&pool_cfg);
-    if (!sys->pool) {
-        picture_Release(picture);
-        IDirect3DSurface9_Release(surface);
-        return VLC_ENOMEM;
+        /* Create the associated picture */
+        picture_sys_t *picsys = malloc(sizeof(*picsys));
+        if (unlikely(picsys == NULL)) {
+            IDirect3DSurface9_Release(surface);
+            return VLC_ENOMEM;
+        }
+        picsys->surface = surface;
+        picsys->fallback = NULL;
+
+        picture_resource_t resource = { .p_sys = picsys };
+        for (int i = 0; i < PICTURE_PLANE_MAX; i++)
+            resource.p[i].i_lines = fmt->i_visible_height / (i > 0 ? 2 : 1);
+
+        picture_t *picture = picture_NewFromResource(fmt, &resource);
+        if (!picture) {
+            msg_Err(vd, "Failed to create a picture from resources.");
+            IDirect3DSurface9_Release(surface);
+            free(picsys);
+            return VLC_ENOMEM;
+        }
+        sys->picsys = picsys;
+
+        /* Wrap it into a picture pool */
+        picture_pool_configuration_t pool_cfg;
+        memset(&pool_cfg, 0, sizeof(pool_cfg));
+        pool_cfg.picture_count = 1;
+        pool_cfg.picture       = &picture;
+        pool_cfg.lock      = Direct3D9LockSurface;
+        pool_cfg.unlock    = Direct3D9UnlockSurface;
+
+        sys->pool = picture_pool_NewExtended(&pool_cfg);
+        if (!sys->pool) {
+            picture_Release(picture);
+            IDirect3DSurface9_Release(surface);
+            return VLC_ENOMEM;
+        }
     }
     return VLC_SUCCESS;
 }
@@ -1038,9 +1041,11 @@ static void Direct3D9DestroyPool(vout_display_t *vd)
 
     if (sys->pool) {
         picture_sys_t *picsys = sys->picsys;
-        IDirect3DSurface9_Release(picsys->surface);
-        if (picsys->fallback)
-            picture_Release(picsys->fallback);
+        if ( picsys != NULL ) {
+            IDirect3DSurface9_Release(picsys->surface);
+            if (picsys->fallback)
+                picture_Release(picsys->fallback);
+        }
         picture_pool_Release(sys->pool);
     }
     sys->pool = NULL;
@@ -1481,12 +1486,7 @@ static int Direct3D9ImportPicture(vout_display_t *vd,
 
     /* Copy picture surface into texture surface
      * color space conversion happen here */
-    RECT cropSource;
-    cropSource.left = 0;
-    cropSource.top = 0;
-    cropSource.right = vd->fmt.i_visible_width;
-    cropSource.bottom = vd->fmt.i_visible_height;
-    hr = IDirect3DDevice9_StretchRect(sys->d3ddev, source, &cropSource, destination, NULL, D3DTEXF_LINEAR);
+    hr = IDirect3DDevice9_StretchRect(sys->d3ddev, source, NULL, destination, NULL, D3DTEXF_LINEAR);
     IDirect3DSurface9_Release(destination);
     if (FAILED(hr)) {
         msg_Dbg(vd, "Failed IDirect3DDevice9_StretchRect: source 0x%p 0x%0lx", source, hr);
-- 
2.3.2




More information about the vlc-devel mailing list