[vlc-commits] [Git][videolan/vlc][3.0.x] 14 commits: d3d9: move the pool creation in libd3d9_common

Steve Lhomme (@robUx4) gitlab at videolan.org
Fri Apr 7 09:04:48 UTC 2023



Steve Lhomme pushed to branch 3.0.x at VideoLAN / VLC


Commits:
26652727 by Steve Lhomme at 2023-04-07T08:10:54+00:00
d3d9: move the pool creation in libd3d9_common

- - - - -
3341404c by Steve Lhomme at 2023-04-07T08:10:54+00:00
d3d9_fmt: keep the adapter info while it's loaded

No need to reload the same thing many times.

(cherry picked from commit 60c0cb10694c9fc4314dbed080fe802fbb5a4fef) (edited)

edited:
* 3.0 doesn't use a decoder device/video context
* 3.0 didn't show the driver version in dxva2

Signed-off-by: Steve Lhomme <robux4 at ycbcr.xyz>

- - - - -
02f5fac7 by Steve Lhomme at 2023-04-07T08:10:54+00:00
direct3d9: move the DXVA2 OpenGL Interop module in its own file

It shares nothing with the D3D9 module and will never be loaded at the same time.

No functional changes.

(cherry picked from commit 886587dc8591ee3bada2bdef660cd0461d7249e7) (edited)

edited:
* 3.0 had a different name for the DXVA2 interop module
* the OpenGL interop name in 3.0 is "glconv", not "glinterop"
* 3.0 has the interop declarations in opengl/converter.h
* 3.0 uses opengl_tex_converter_t instead of vlc_gl_interop

Signed-off-by: Steve Lhomme <robux4 at ycbcr.xyz>

- - - - -
16769e26 by Steve Lhomme at 2023-04-07T08:10:54+00:00
opengl: dxva2: make sure we can handle the conversion in StretchRect

(cherry picked from commit b7a56bc889e4cc02f3bc626c20abb01ee5b394d8) (edited)

edited:
* 3.0 doesn't use a decoder device/video context
* 3.0 doesn't know the exact D3DFORMAT on open but we deduce it from the chroma

Signed-off-by: Steve Lhomme <robux4 at ycbcr.xyz>

- - - - -
3e33bcd4 by Steve Lhomme at 2023-04-07T08:10:54+00:00
opengl: dxva2: always use the IDIRECT3DDEVICE9EX with DXVA interop

(cherry picked from commit 15132bbffb0f89bfa9ef7dd79221235e501ee8e6) (edited)

edited:
* adapted patch as we don't use a decoder device/video context

Signed-off-by: Steve Lhomme <robux4 at ycbcr.xyz>

- - - - -
cf08970c by Steve Lhomme at 2023-04-07T08:10:54+00:00
opengl: dxva2: use DXVA-HD instead of StretchRect for NVIDIA GPUs

The StretchRect we're using has the same issue as with the D3D9 vout.

(cherry picked from commit e595beb4e97391fd0b86caa1cc02955238908cb3) (edited)

edited:
* 3.0 uses opengl_tex_converter_t and not vlc_gl_interop
* 3.0 uses b_color_range_full and not color_range

Signed-off-by: Steve Lhomme <robux4 at ycbcr.xyz>

- - - - -
a2c6fd94 by Steve Lhomme at 2023-04-07T08:10:54+00:00
opengl: dxva2: fix indentation after previous commits

No functional changes

(cherry picked from commit f707c6f002defa3f093b028014a4b3af90e65d14)

Signed-off-by: Steve Lhomme <robux4 at ycbcr.xyz>

- - - - -
f007cf9a by Steve Lhomme at 2023-04-07T08:10:54+00:00
contrib: mingw64: patch dxvahd.h before mingw-w64 11

The releases before 11 had bogus dxvahd
DXVAHD_STREAM_STATE_xxx_COLOR_SPACE_DATA structures. This was confusing the
initialization with LLVM.

(cherry picked from commit 96a19e9410ea372d735a352b33fb6ad5a3ce5760) (edited)

edited:
* in 3.0 the mingw-w64 files are still in the pthreads directory

Signed-off-by: Steve Lhomme <robux4 at ycbcr.xyz>

- - - - -
c41bbfd5 by Steve Lhomme at 2023-04-07T08:10:54+00:00
d3d9: fully initialize DXVAHD_BLT_STATE_OUTPUT_COLOR_SPACE_DATA

Although we set all known usable bits, it seems that leaving reserved bits
"uninitialized" doesn't work in some case. In particular with LLVM builds,
which results in bogus output.

Co-authored-by: Pierre Lamot <pierre at videolabs.io>
(cherry picked from commit a7de762a710debc733f2b2ce5720f92ccab7f566) (edited)

edited:
* 3.0 doesn't have the GPU callbacks to tweak the output format colorimetry

Signed-off-by: Steve Lhomme <robux4 at ycbcr.xyz>

- - - - -
de34414d by Steve Lhomme at 2023-04-07T08:10:54+00:00
d3d9: fully initialize DXVAHD_BLT_STATE_INPUT_COLOR_SPACE_DATA

Although we set all known usable bits, it seems that leaving reserved bits
"uninitialized" doesn't work in some case. In particular with LLVM builds,
which results in bogus output.

(cherry picked from commit 367b7e8eeafcd36e876be2d4e0ec2dfd978cc2cb) (edited)

edited:
* 3.0 uses b_color_range_full instead of color_range

Signed-off-by: Steve Lhomme <robux4 at ycbcr.xyz>

- - - - -
55bfc1ad by Steve Lhomme at 2023-04-07T08:10:54+00:00
d3d9: explicitly set the processing input type

We do the processing on video files, not "graphics" generated sources.

(cherry picked from commit b86fbe2e7a40caab99aab8a41dce657ed11a91db) (rebased)

rebased:
* 3.0 uses b_color_range_full instead of color_range

Signed-off-by: Steve Lhomme <robux4 at ycbcr.xyz>

- - - - -
111f34d3 by Steve Lhomme at 2023-04-07T08:10:54+00:00
d3d9: use the official typedef for DXVAHD_CreateDevice()

It doesn't exist in mingw so we define it in that case.

(cherry picked from commit dd8297d27a67d9bfa0a9a217c8ad37db45620e24)

Signed-off-by: Steve Lhomme <robux4 at ycbcr.xyz>

- - - - -
d803f6aa by Steve Lhomme at 2023-04-07T08:10:54+00:00
interop_dxva2: add comments about the processor output values

The same code in direct3d9 uses an output format that can vary.

(cherry picked from commit 2e335eba28ebe1bcf0028385f70838dcf310e847)

Signed-off-by: Steve Lhomme <robux4 at ycbcr.xyz>

- - - - -
f9e125db by Steve Lhomme at 2023-04-07T08:10:54+00:00
interop_dxva2: force win7 API compatibility

Otherwise in 3.0 builds we target WinXP and the API is not available.

Similar to 8241910b7bac3781ea0c4eb1503a23560a7a9412

- - - - -


10 changed files:

- + contrib/src/pthreads/0001-headers-Update-to-Wine-master-and-regenerate-H-from-.patch
- + contrib/src/pthreads/0002-headers-dxvahd-Regenerate-H-from-IDL.patch
- contrib/src/pthreads/rules.mak
- modules/codec/Makefile.am
- modules/codec/avcodec/dxva2.c
- modules/video_chroma/d3d9_fmt.c
- modules/video_chroma/d3d9_fmt.h
- modules/video_output/Makefile.am
- + modules/video_output/opengl/interop_dxva2.c
- modules/video_output/win32/direct3d9.c


Changes:

=====================================
contrib/src/pthreads/0001-headers-Update-to-Wine-master-and-regenerate-H-from-.patch
=====================================
@@ -0,0 +1,62 @@
+From d4249c712991ab191f05968470b34587cc716a53 Mon Sep 17 00:00:00 2001
+From: LIU Hao <lh_mouse at 126.com>
+Date: Sat, 18 Mar 2023 14:59:38 +0800
+Subject: [PATCH 1/2] headers: Update to Wine master and regenerate H from IDL
+ (edited)
+
+Signed-off-by: LIU Hao <lh_mouse at 126.com>
+
+edited:
+* only kept the dxvahd.h changes
+---
+ mingw-w64-headers/include/dxvahd.h | 27 +++++++++++++++++++--------
+ 1 file changed, 19 insertions(+), 8 deletions(-)
+
+diff --git a/mingw-w64-headers/include/dxvahd.h b/mingw-w64-headers/include/dxvahd.h
+index 71b027863..aaff9400c 100644
+--- a/mingw-w64-headers/include/dxvahd.h
++++ b/mingw-w64-headers/include/dxvahd.h
+@@ -251,10 +251,16 @@ typedef struct _DXVAHD_BLT_STATE_CONSTRICTION_DATA {
+     SIZE Size;
+ } DXVAHD_BLT_STATE_CONSTRICTION_DATA;
+ typedef struct _DXVAHD_BLT_STATE_OUTPUT_COLOR_SPACE_DATA {
+-    UINT Usage : 1;
+-    UINT RGB_Range : 1;
+-    UINT YCbCr_Matrix : 1;
+-    UINT YCbCr_xvYCC : 1;
++    __C89_NAMELESS union {
++        __C89_NAMELESS struct {
++            UINT Usage : 1;
++            UINT RGB_Range : 1;
++            UINT YCbCr_Matrix : 1;
++            UINT YCbCr_xvYCC : 1;
++            UINT Reserved : 28;
++        } __C89_NAMELESSSTRUCTNAME;
++        UINT Value;
++    } __C89_NAMELESSUNIONNAME;
+ } DXVAHD_BLT_STATE_OUTPUT_COLOR_SPACE_DATA;
+ typedef struct _DXVAHD_BLT_STATE_PRIVATE_DATA {
+     GUID Guid;
+@@ -332,10 +338,15 @@ typedef struct _DXVAHD_STREAM_STATE_FRAME_FORMAT_DATA {
+     DXVAHD_FRAME_FORMAT FrameFormat;
+ } DXVAHD_STREAM_STATE_FRAME_FORMAT_DATA;
+ typedef struct _DXVAHD_STREAM_STATE_INPUT_COLOR_SPACE_DATA {
+-    UINT Type : 1;
+-    UINT RGB_Range : 1;
+-    UINT YCbCr_Matrix : 1;
+-    UINT YCbCr_xvYCC : 1;
++    __C89_NAMELESS union {
++        __C89_NAMELESS struct {
++            UINT Type : 1;
++            UINT RGB_Range : 1;
++            UINT YCbCr_Matrix : 1;
++            UINT YCbCr_xvYCC : 1;
++        } __C89_NAMELESSSTRUCTNAME;
++        UINT Value;
++    } __C89_NAMELESSUNIONNAME;
+ } DXVAHD_STREAM_STATE_INPUT_COLOR_SPACE_DATA;
+ typedef struct _DXVAHD_STREAM_STATE_LUMA_KEY_DATA {
+     WINBOOL Enable;
+-- 
+2.37.3.windows.1
+


=====================================
contrib/src/pthreads/0002-headers-dxvahd-Regenerate-H-from-IDL.patch
=====================================
@@ -0,0 +1,25 @@
+From d12847294d570acc97790c7a02fb44a73850f347 Mon Sep 17 00:00:00 2001
+From: LIU Hao <lh_mouse at 126.com>
+Date: Sat, 18 Mar 2023 17:19:02 +0800
+Subject: [PATCH 2/2] headers/dxvahd: Regenerate H from IDL
+
+Signed-off-by: LIU Hao <lh_mouse at 126.com>
+---
+ mingw-w64-headers/include/dxvahd.h | 1 +
+ 1 file changed, 1 insertion(+)
+
+diff --git a/mingw-w64-headers/include/dxvahd.h b/mingw-w64-headers/include/dxvahd.h
+index aaff9400c..6bcd753dd 100644
+--- a/mingw-w64-headers/include/dxvahd.h
++++ b/mingw-w64-headers/include/dxvahd.h
+@@ -344,6 +344,7 @@ typedef struct _DXVAHD_STREAM_STATE_INPUT_COLOR_SPACE_DATA {
+             UINT RGB_Range : 1;
+             UINT YCbCr_Matrix : 1;
+             UINT YCbCr_xvYCC : 1;
++            UINT Reserved : 28;
+         } __C89_NAMELESSSTRUCTNAME;
+         UINT Value;
+     } __C89_NAMELESSUNIONNAME;
+-- 
+2.37.3.windows.1
+


=====================================
contrib/src/pthreads/rules.mak
=====================================
@@ -11,12 +11,12 @@ PKGS += pthreads
 ifndef HAVE_VISUALSTUDIO
 PKGS += dxva dxvahd
 PKGS_ALL += dxva dxvahd
-ifeq ($(call mingw_at_least, 8), true)
-PKGS_FOUND += dxvahd
-endif # MINGW 8
 ifeq ($(call mingw_at_least, 10), true)
 PKGS_FOUND += dxva
 endif # MINGW 10
+ifeq ($(call mingw_at_least, 11), true)
+PKGS_FOUND += dxvahd
+endif # MINGW 11
 ifeq ($(HAVE_WINPTHREAD),)
 PKGS_FOUND += pthreads
 endif
@@ -35,6 +35,8 @@ $(TARBALLS)/mingw-w64-v$(MINGW64_VERSION).tar.bz2:
 # pthreads: mingw-w64-v$(MINGW64_VERSION).tar.bz2 .sum-pthreads
 pthreads: mingw-w64-$(MINGW64_HASH).tar.xz .sum-pthreads
 	$(UNPACK)
+	$(APPLY) $(SRC)/pthreads/0001-headers-Update-to-Wine-master-and-regenerate-H-from-.patch
+	$(APPLY) $(SRC)/pthreads/0002-headers-dxvahd-Regenerate-H-from-IDL.patch
 	$(MOVE)
 
 .pthreads: pthreads


=====================================
modules/codec/Makefile.am
=====================================
@@ -431,7 +431,7 @@ libdxva2_plugin_la_SOURCES = \
 	packetizer/h264_nal.c packetizer/h264_nal.h \
 	packetizer/hevc_nal.c packetizer/hevc_nal.h \
 	codec/avcodec/dxva_blacklist.c
-libdxva2_plugin_la_LIBADD = libd3d9_common.la $(LIBCOM) -lshlwapi -luuid
+libdxva2_plugin_la_LIBADD = libd3d9_common.la libchroma_copy.la $(LIBCOM) -lshlwapi -luuid
 if HAVE_AVCODEC_DXVA2
 codec_LTLIBRARIES += libdxva2_plugin.la
 endif
@@ -503,7 +503,7 @@ libmediacodec_plugin_la_SOURCES = codec/omxil/mediacodec.c codec/omxil/mediacode
 	packetizer/hxxx_nal.h packetizer/hxxx_nal.c \
 	packetizer/h264_nal.c packetizer/h264_nal.h \
 	packetizer/hevc_nal.c packetizer/hevc_nal.h
-libmediacodec_plugin_la_LIBADD = libchroma_copy.la 
+libmediacodec_plugin_la_LIBADD = libchroma_copy.la
 codec_LTLIBRARIES += $(LTLIBomxil) $(LTLIBomxil_vout)
 EXTRA_LTLIBRARIES += libomxil_plugin.la libomxil_vout_plugin.la
 if HAVE_ANDROID


=====================================
modules/codec/avcodec/dxva2.c
=====================================
@@ -3,7 +3,7 @@
  *****************************************************************************
  * Copyright (C) 2009 Geoffroy Couprie
  * Copyright (C) 2009 Laurent Aimar
- * $Id$
+ * $Id: 26cb48dc887acd90eba53d9a30d60a3cbed212d9 $
  *
  * Authors: Geoffroy Couprie <geal at videolan.org>
  *          Laurent Aimar <fenrir _AT_ videolan _DOT_ org>
@@ -82,12 +82,6 @@ DEFINE_GUID(DXVA2_NoEncrypt,                        0x1b81bed0, 0xa0c7, 0x11d3,
 DEFINE_GUID(DXVA_Intel_H264_NoFGT_ClearVideo,       0x604F8E68, 0x4951, 0x4c54, 0x88, 0xFE, 0xAB, 0xD2, 0x5C, 0x15, 0xB3, 0xD6);
 
 
-/* */
-typedef struct {
-    const char   *name;
-    D3DFORMAT    format;
-    vlc_fourcc_t codec;
-} d3d9_format_t;
 /* XXX Preferred format must come first */
 static const d3d9_format_t d3d_formats[] = {
     { "YV12",   MAKEFOURCC('Y','V','1','2'),    VLC_CODEC_YV12 },
@@ -501,18 +495,14 @@ static int DxSetupOutput(vlc_va_t *va, const GUID *input, const video_format_t *
     VLC_UNUSED(fmt);
     vlc_va_sys_t *sys = va->sys;
 
-    D3DADAPTER_IDENTIFIER9 identifier;
-    HRESULT hr = IDirect3D9_GetAdapterIdentifier(sys->hd3d.obj, sys->d3d_dev.adapterId, 0, &identifier);
-    if (FAILED(hr))
-        return VLC_EGENERIC;
-
-    UINT driverBuild = identifier.DriverVersion.LowPart & 0xFFFF;
-    if (identifier.VendorId == GPU_MANUFACTURER_INTEL && (identifier.DriverVersion.LowPart >> 16) >= 100)
+    const D3DADAPTER_IDENTIFIER9 *identifier = &sys->d3d_dev.identifier;
+    UINT driverBuild = identifier->DriverVersion.LowPart & 0xFFFF;
+    if (identifier->VendorId == GPU_MANUFACTURER_INTEL && (identifier->DriverVersion.LowPart >> 16) >= 100)
     {
         /* new Intel driver format */
-        driverBuild += ((identifier.DriverVersion.LowPart >> 16) - 100) * 1000;
+        driverBuild += ((identifier->DriverVersion.LowPart >> 16) - 100) * 1000;
     }
-    if (!directx_va_canUseDecoder(va, identifier.VendorId, identifier.DeviceId,
+    if (!directx_va_canUseDecoder(va, identifier->VendorId, identifier->DeviceId,
                                   input, driverBuild))
     {
         char* psz_decoder_name = directx_va_GetDecoderName(input);


=====================================
modules/video_chroma/d3d9_fmt.c
=====================================
@@ -28,6 +28,9 @@
 #include "d3d9_fmt.h"
 
 #include "../codec/avcodec/va_surface.h"
+#include "copy.h"
+
+#include <vlc_picture_pool.h>
 
 picture_sys_t *ActivePictureSys(picture_t *p_pic)
 {
@@ -94,12 +97,11 @@ HRESULT D3D9_CreateDevice(vlc_object_t *o, d3d9_handle_t *hd3d, HWND hwnd,
     }
 
     /* */
-    D3DADAPTER_IDENTIFIER9 d3dai;
-    if (FAILED(IDirect3D9_GetAdapterIdentifier(hd3d->obj, AdapterToUse,0, &d3dai))) {
+    if (FAILED(IDirect3D9_GetAdapterIdentifier(hd3d->obj, AdapterToUse,0, &out->identifier))) {
         msg_Warn(o, "IDirect3D9_GetAdapterIdentifier failed");
     } else {
-        msg_Dbg(o, "Direct3d9 Device: %s %lx %lx %lx", d3dai.Description,
-                d3dai.VendorId, d3dai.DeviceId, d3dai.Revision );
+        msg_Dbg(o, "Direct3d9 Device: %s %lx %lx %lx", out->identifier.Description,
+                out->identifier.VendorId, out->identifier.DeviceId, out->identifier.Revision );
     }
 
     DWORD thread_modes[] = { D3DCREATE_MULTITHREADED, 0 };
@@ -255,3 +257,116 @@ error:
     D3D9_Destroy( hd3d );
     return VLC_EGENERIC;
 }
+
+
+static void DestroyPicture(picture_t *picture)
+{
+    ReleasePictureSys(picture->p_sys);
+
+    free(picture->p_sys);
+    free(picture);
+}
+
+int Direct3D9LockSurface(picture_t *picture)
+{
+    /* Lock the surface to get a valid pointer to the picture buffer */
+    D3DLOCKED_RECT d3drect;
+    HRESULT hr = IDirect3DSurface9_LockRect(picture->p_sys->surface, &d3drect, NULL, 0);
+    if (FAILED(hr)) {
+        return VLC_EGENERIC;
+    }
+
+    return picture_UpdatePlanes(picture, d3drect.pBits, d3drect.Pitch);
+}
+
+void Direct3D9UnlockSurface(picture_t *picture)
+{
+    /* Unlock the Surface */
+    HRESULT hr = IDirect3DSurface9_UnlockRect(picture->p_sys->surface);
+    if (FAILED(hr)) {
+        //msg_Dbg(vd, "Failed IDirect3DSurface9_UnlockRect: 0x%0lx", hr);
+    }
+}
+
+/* */
+picture_pool_t *Direct3D9CreatePicturePool(vlc_object_t *o,
+    d3d9_device_t *p_d3d9_dev, const d3d9_format_t *default_d3dfmt, const video_format_t *fmt, unsigned count)
+{
+    picture_pool_t*   pool = NULL;
+    picture_t**       pictures = NULL;
+    unsigned          picture_count = 0;
+
+    pictures = calloc(count, sizeof(*pictures));
+    if (!pictures)
+        goto error;
+
+    D3DFORMAT format;
+    switch (fmt->i_chroma)
+    {
+    case VLC_CODEC_D3D9_OPAQUE_10B:
+        format = MAKEFOURCC('P','0','1','0');
+        break;
+    case VLC_CODEC_D3D9_OPAQUE:
+        format = MAKEFOURCC('N','V','1','2');
+        break;
+    default:
+        if (!default_d3dfmt)
+            goto error;
+        format = default_d3dfmt->format;
+        break;
+    }
+
+    for (picture_count = 0; picture_count < count; ++picture_count)
+    {
+        picture_sys_t *picsys = malloc(sizeof(*picsys));
+        if (unlikely(picsys == NULL))
+            goto error;
+        memset(picsys, 0, sizeof(*picsys));
+
+        HRESULT hr = IDirect3DDevice9_CreateOffscreenPlainSurface(p_d3d9_dev->dev,
+                                                          fmt->i_width,
+                                                          fmt->i_height,
+                                                          format,
+                                                          D3DPOOL_DEFAULT,
+                                                          &picsys->surface,
+                                                          NULL);
+        if (FAILED(hr)) {
+           msg_Err(o, "Failed to allocate surface %d (hr=0x%0lx)", picture_count, hr);
+           free(picsys);
+           goto error;
+        }
+
+        picture_resource_t resource = {
+            .p_sys = picsys,
+            .pf_destroy = DestroyPicture,
+        };
+
+        picture_t *picture = picture_NewFromResource(fmt, &resource);
+        if (unlikely(picture == NULL)) {
+            free(picsys);
+            goto error;
+        }
+
+        pictures[picture_count] = picture;
+    }
+
+    picture_pool_configuration_t pool_cfg;
+    memset(&pool_cfg, 0, sizeof(pool_cfg));
+    pool_cfg.picture_count = count;
+    pool_cfg.picture       = pictures;
+    if( !is_d3d9_opaque( fmt->i_chroma ) )
+    {
+        pool_cfg.lock = Direct3D9LockSurface;
+        pool_cfg.unlock = Direct3D9UnlockSurface;
+    }
+
+    pool = picture_pool_NewExtended( &pool_cfg );
+
+error:
+    if (pool == NULL && pictures) {
+        for (unsigned i=0;i<picture_count; ++i)
+            DestroyPicture(pictures[i]);
+    }
+    free(pictures);
+    return pool;
+}


=====================================
modules/video_chroma/d3d9_fmt.h
=====================================
@@ -65,8 +65,19 @@ typedef struct
     UINT                    adapterId;
     HWND                    hwnd;
     D3DCAPS9                caps;
+    D3DADAPTER_IDENTIFIER9  identifier;
 } d3d9_device_t;
 
+typedef struct
+{
+    const char   *name;
+    D3DFORMAT    format;    /* D3D format */
+    vlc_fourcc_t fourcc;    /* VLC fourcc */
+    uint32_t     rmask;
+    uint32_t     gmask;
+    uint32_t     bmask;
+} d3d9_format_t;
+
 #include "../codec/avcodec/va_surface.h"
 
 picture_sys_t *ActivePictureSys(picture_t *p_pic);
@@ -87,6 +98,18 @@ static inline void ReleasePictureSys(picture_sys_t *p_sys)
     FreeLibrary(p_sys->dxva2_dll);
 }
 
+static inline bool is_d3d9_opaque(vlc_fourcc_t chroma)
+{
+    switch (chroma)
+    {
+    case VLC_CODEC_D3D9_OPAQUE:
+    case VLC_CODEC_D3D9_OPAQUE_10B:
+        return true;
+    default:
+        return false;
+    }
+}
+
 HRESULT D3D9_CreateDevice(vlc_object_t *, d3d9_handle_t *, HWND,
                           const video_format_t *, d3d9_device_t *out);
 #define D3D9_CreateDevice(a,b,c,d,e) D3D9_CreateDevice( VLC_OBJECT(a), b, c, d, e )
@@ -99,4 +122,21 @@ void D3D9_Destroy(d3d9_handle_t *);
 
 int D3D9_FillPresentationParameters(d3d9_handle_t *, const video_format_t *, d3d9_device_t *);
 
+/**
+ * It locks the surface associated to the picture and get the surface
+ * descriptor which amongst other things has the pointer to the picture
+ * data and its pitch.
+ */
+int Direct3D9LockSurface(picture_t *picture);
+
+/**
+ * It unlocks the surface associated to the picture.
+ */
+void Direct3D9UnlockSurface(picture_t *picture);
+
+struct picture_pool_t *Direct3D9CreatePicturePool(vlc_object_t *, d3d9_device_t *,
+     const d3d9_format_t *, const video_format_t *, unsigned);
+
+
+
 #endif /* VLC_VIDEOCHROMA_D3D9_FMT_H_ */


=====================================
modules/video_output/Makefile.am
=====================================
@@ -261,9 +261,18 @@ libdirect3d9_plugin_la_CPPFLAGS = $(AM_CPPFLAGS) \
 	-DMODULE_NAME_IS_direct3d9
 libdirect3d9_plugin_la_LIBADD = libchroma_copy.la libd3d9_common.la -lgdi32 $(LIBCOM) -luuid
 libdirect3d9_plugin_la_LDFLAGS = $(AM_LDFLAGS) -rpath '$(voutdir)'
+
+libglinterop_dxva2_plugin_la_SOURCES = video_output/opengl/interop_dxva2.c \
+	video_output/opengl/converter.h
+libglinterop_dxva2_plugin_la_CFLAGS = $(AM_CFLAGS) $(GL_CFLAGS)
+libglinterop_dxva2_plugin_la_LIBADD = libchroma_copy.la libd3d9_common.la
+
 if HAVE_WIN32_DESKTOP
 vout_LTLIBRARIES += $(LTLIBdirect3d9)
 EXTRA_LTLIBRARIES += libdirect3d9_plugin.la
+if HAVE_GL
+vout_LTLIBRARIES += libglinterop_dxva2_plugin.la
+endif
 endif
 
 libdirect3d11_plugin_la_SOURCES = video_output/win32/direct3d11.c \


=====================================
modules/video_output/opengl/interop_dxva2.c
=====================================
@@ -0,0 +1,543 @@
+/*****************************************************************************
+ * direct3d9.c: Windows Direct3D9 video output module
+ *****************************************************************************
+ * Copyright (C) 2006-2014 VLC authors and VideoLAN
+ *
+ * Authors: Martell Malone <martellmalone at gmail.com>,
+ *          Damien Fouilleul <damienf at videolan.org>,
+ *          Sasha Koruga <skoruga at gmail.com>,
+ *          Felix Abecassis <felix.abecassis at gmail.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation; either version 2.1 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 Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser 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.
+ *****************************************************************************/
+
+/*****************************************************************************
+ * Preamble:
+ *
+ * This plugin will use YUV surface if supported, using YUV will result in
+ * the best video quality (hardware filtering when rescaling the picture)
+ * and the fastest display as it requires less processing.
+ *
+ * If YUV overlay is not supported this plugin will use RGB offscreen video
+ * surfaces that will be blitted onto the primary surface (display) to
+ * effectively display the pictures.
+ *
+ *****************************************************************************/
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+// For dynamic use of DXVA-HD
+#if _WIN32_WINNT < 0x0601 // _WIN32_WINNT_WIN7
+# undef _WIN32_WINNT
+# define _WIN32_WINNT _WIN32_WINNT_WIN7
+#endif
+
+#include <vlc_common.h>
+#include <vlc_plugin.h>
+#include <vlc_vout_display.h>
+
+#include <windows.h>
+#include <d3d9.h>
+#include "../../video_chroma/d3d9_fmt.h"
+#include <dxvahd.h>
+
+#include "../opengl/converter.h"
+#include <GL/wglew.h>
+
+/*****************************************************************************
+ * Module descriptor
+ *****************************************************************************/
+static int  GLConvOpen(vlc_object_t *);
+static void GLConvClose(vlc_object_t *);
+
+vlc_module_begin ()
+    set_shortname("dxva2")
+    set_category(CAT_VIDEO)
+    set_subcategory(SUBCAT_VIDEO_VOUT)
+    set_description("DX OpenGL surface converter for D3D9")
+    set_capability("glconv", 1)
+    set_callbacks(GLConvOpen, GLConvClose)
+vlc_module_end ()
+
+struct wgl_vt {
+    PFNWGLDXSETRESOURCESHAREHANDLENVPROC DXSetResourceShareHandleNV;
+    PFNWGLDXOPENDEVICENVPROC             DXOpenDeviceNV;
+    PFNWGLDXCLOSEDEVICENVPROC            DXCloseDeviceNV;
+    PFNWGLDXREGISTEROBJECTNVPROC         DXRegisterObjectNV;
+    PFNWGLDXUNREGISTEROBJECTNVPROC       DXUnregisterObjectNV;
+    PFNWGLDXLOCKOBJECTSNVPROC            DXLockObjectsNV;
+    PFNWGLDXUNLOCKOBJECTSNVPROC          DXUnlockObjectsNV;
+};
+struct glpriv
+{
+    struct wgl_vt vt;
+    d3d9_handle_t hd3d;
+    d3d9_device_t d3d_dev;
+    HANDLE gl_handle_d3d;
+    HANDLE gl_render;
+    IDirect3DSurface9 *dx_render;
+
+    D3DFORMAT OutputFormat;
+
+    /* range converter */
+    struct {
+        HMODULE                 dll;
+        IDXVAHD_VideoProcessor *proc;
+    } processor;
+};
+
+static int
+GLConvUpdate(const opengl_tex_converter_t *tc, GLuint *textures,
+             const GLsizei *tex_width, const GLsizei *tex_height,
+             picture_t *pic, const size_t *plane_offset)
+{
+    VLC_UNUSED(textures); VLC_UNUSED(tex_width); VLC_UNUSED(tex_height); VLC_UNUSED(plane_offset);
+    struct glpriv *priv = tc->priv;
+    HRESULT hr;
+
+    picture_sys_t *picsys = ActivePictureSys(pic);
+    if (unlikely(!picsys || !priv->gl_render))
+        return VLC_EGENERIC;
+
+    if (!priv->vt.DXUnlockObjectsNV(priv->gl_handle_d3d, 1, &priv->gl_render))
+    {
+        msg_Warn(tc->gl, "DXUnlockObjectsNV failed");
+        return VLC_EGENERIC;
+    }
+
+    if (priv->processor.proc)
+    {
+        DXVAHD_STREAM_DATA inputStream = { 0 };
+        inputStream.Enable = TRUE;
+        inputStream.pInputSurface = picsys->surface;
+        hr = IDXVAHD_VideoProcessor_VideoProcessBltHD( priv->processor.proc, priv->dx_render, 0, 1, &inputStream );
+        if (FAILED(hr)) {
+            D3DSURFACE_DESC srcDesc, dstDesc;
+            IDirect3DSurface9_GetDesc(picsys->surface, &srcDesc);
+            IDirect3DSurface9_GetDesc(priv->dx_render, &dstDesc);
+
+            msg_Dbg(tc->gl, "Failed VideoProcessBltHD src:%4.4s (%d) dst:%4.4s (%d) (hr=0x%lX)",
+                    (const char*)&srcDesc.Format, srcDesc.Format,
+                    (const char*)&dstDesc.Format, dstDesc.Format, hr);
+            return VLC_EGENERIC;
+        }
+    }
+    else
+    {
+        const RECT rect = {
+            .left = 0,
+            .top = 0,
+            .right = pic->format.i_visible_width,
+            .bottom = pic->format.i_visible_height
+        };
+        hr = IDirect3DDevice9Ex_StretchRect(priv->d3d_dev.devex, picsys->surface,
+                                            &rect, priv->dx_render, NULL, D3DTEXF_NONE);
+        if (FAILED(hr))
+        {
+            msg_Warn(tc->gl, "IDirect3DDevice9Ex_StretchRect failed");
+            return VLC_EGENERIC;
+        }
+    }
+
+    if (!priv->vt.DXLockObjectsNV(priv->gl_handle_d3d, 1, &priv->gl_render))
+    {
+        msg_Warn(tc->gl, "DXLockObjectsNV failed");
+        priv->vt.DXUnregisterObjectNV(priv->gl_handle_d3d, priv->gl_render);
+        priv->gl_render = NULL;
+        return VLC_EGENERIC;
+    }
+
+    return VLC_SUCCESS;
+}
+
+static picture_pool_t *
+GLConvGetPool(const opengl_tex_converter_t *tc, unsigned requested_count)
+{
+    struct glpriv *priv = tc->priv;
+    return Direct3D9CreatePicturePool(VLC_OBJECT(tc->gl), &priv->d3d_dev, NULL,
+                                      &tc->fmt, requested_count);
+}
+
+static int
+GLConvAllocateTextures(const opengl_tex_converter_t *tc, GLuint *textures,
+                       const GLsizei *tex_width, const GLsizei *tex_height)
+{
+    VLC_UNUSED(tex_width); VLC_UNUSED(tex_height);
+    struct glpriv *priv = tc->priv;
+
+    priv->gl_render =
+        priv->vt.DXRegisterObjectNV(priv->gl_handle_d3d, priv->dx_render,
+                                    textures[0], GL_TEXTURE_2D, WGL_ACCESS_WRITE_DISCARD_NV);
+    if (!priv->gl_render)
+    {
+        msg_Warn(tc->gl, "DXRegisterObjectNV failed: %lu", GetLastError());
+        return VLC_EGENERIC;
+    }
+
+    if (!priv->vt.DXLockObjectsNV(priv->gl_handle_d3d, 1, &priv->gl_render))
+    {
+        msg_Warn(tc->gl, "DXLockObjectsNV failed");
+        priv->vt.DXUnregisterObjectNV(priv->gl_handle_d3d, priv->gl_render);
+        priv->gl_render = NULL;
+        return VLC_EGENERIC;
+    }
+
+    return VLC_SUCCESS;
+}
+
+static void
+GLConvClose(vlc_object_t *obj)
+{
+    opengl_tex_converter_t *tc = (void *)obj;
+    struct glpriv *priv = tc->priv;
+
+    if (priv->gl_handle_d3d)
+    {
+        if (priv->gl_render)
+        {
+            priv->vt.DXUnlockObjectsNV(priv->gl_handle_d3d, 1, &priv->gl_render);
+            priv->vt.DXUnregisterObjectNV(priv->gl_handle_d3d, priv->gl_render);
+        }
+
+        priv->vt.DXCloseDeviceNV(priv->gl_handle_d3d);
+    }
+    if (priv->processor.proc)
+    {
+        IDXVAHD_VideoProcessor_Release(priv->processor.proc);
+        FreeLibrary(priv->processor.dll);
+    }
+
+    if (priv->dx_render)
+        IDirect3DSurface9_Release(priv->dx_render);
+
+    D3D9_ReleaseDevice(&priv->d3d_dev);
+    D3D9_Destroy(&priv->hd3d);
+    free(tc->priv);
+}
+
+static void SetupProcessorInput(opengl_tex_converter_t *interop, const video_format_t *fmt, D3DFORMAT src_format)
+{
+    struct glpriv *sys = interop->priv;
+    HRESULT hr;
+    DXVAHD_STREAM_STATE_D3DFORMAT_DATA d3dformat = { src_format };
+    hr = IDXVAHD_VideoProcessor_SetVideoProcessStreamState( sys->processor.proc, 0, DXVAHD_STREAM_STATE_D3DFORMAT, sizeof(d3dformat), &d3dformat );
+
+    DXVAHD_STREAM_STATE_FRAME_FORMAT_DATA frame_format = { DXVAHD_FRAME_FORMAT_PROGRESSIVE };
+    hr = IDXVAHD_VideoProcessor_SetVideoProcessStreamState( sys->processor.proc, 0, DXVAHD_STREAM_STATE_FRAME_FORMAT, sizeof(frame_format), &frame_format );
+
+    DXVAHD_STREAM_STATE_INPUT_COLOR_SPACE_DATA colorspace = {
+        .Type = 0, // video, not graphics
+        .RGB_Range = fmt->b_color_range_full ? 0 : 1,
+        .YCbCr_xvYCC = fmt->b_color_range_full ? 1 : 0,
+        .YCbCr_Matrix = fmt->space == COLOR_SPACE_BT601 ? 0 : 1,
+    };
+    hr = IDXVAHD_VideoProcessor_SetVideoProcessStreamState( sys->processor.proc, 0, DXVAHD_STREAM_STATE_INPUT_COLOR_SPACE, sizeof(colorspace), &colorspace );
+
+    DXVAHD_STREAM_STATE_SOURCE_RECT_DATA srcRect;
+    srcRect.Enable = TRUE;
+    srcRect.SourceRect = (RECT) {
+        .left   = interop->fmt.i_x_offset,
+        .right  = interop->fmt.i_x_offset + interop->fmt.i_visible_width,
+        .top    = interop->fmt.i_y_offset,
+        .bottom = interop->fmt.i_y_offset + interop->fmt.i_visible_height,
+    };;
+    hr = IDXVAHD_VideoProcessor_SetVideoProcessStreamState( sys->processor.proc, 0, DXVAHD_STREAM_STATE_SOURCE_RECT, sizeof(srcRect), &srcRect );
+
+    DXVAHD_BLT_STATE_TARGET_RECT_DATA dstRect;
+    dstRect.Enable = TRUE;
+    dstRect.TargetRect = (RECT) {
+        .left   = 0,
+        .right  = interop->fmt.i_visible_width,
+        .top    = 0,
+        .bottom = interop->fmt.i_visible_height,
+    };
+    hr = IDXVAHD_VideoProcessor_SetVideoProcessBltState( sys->processor.proc, DXVAHD_BLT_STATE_TARGET_RECT, sizeof(dstRect), &dstRect);
+}
+
+static void GetFrameRate(DXVAHD_RATIONAL *r, const video_format_t *fmt)
+{
+    if (fmt->i_frame_rate && fmt->i_frame_rate_base)
+    {
+        r->Numerator   = fmt->i_frame_rate;
+        r->Denominator = fmt->i_frame_rate_base;
+    }
+    else
+    {
+        r->Numerator   = 0;
+        r->Denominator = 0;
+    }
+}
+
+static int InitRangeProcessor(opengl_tex_converter_t *interop, IDirect3DDevice9Ex *devex, D3DFORMAT src_format)
+{
+    struct glpriv *sys = interop->priv;
+
+    HRESULT hr;
+
+    sys->processor.dll = LoadLibrary(TEXT("DXVA2.DLL"));
+    if (unlikely(!sys->processor.dll))
+    {
+        msg_Err(interop, "Failed to load DXVA2.DLL");
+        return VLC_EGENERIC;
+    }
+
+    D3DFORMAT *formatsList = NULL;
+    DXVAHD_VPCAPS *capsList = NULL;
+    IDXVAHD_Device *hd_device = NULL;
+
+#ifdef __MINGW64_VERSION_MAJOR
+    typedef HRESULT (WINAPI* PDXVAHD_CreateDevice)(IDirect3DDevice9Ex *,const DXVAHD_CONTENT_DESC *,DXVAHD_DEVICE_USAGE,PDXVAHDSW_Plugin,IDXVAHD_Device **);
+#endif
+    PDXVAHD_CreateDevice CreateDevice;
+    CreateDevice = (PDXVAHD_CreateDevice)GetProcAddress(sys->processor.dll, "DXVAHD_CreateDevice");
+    if (CreateDevice == NULL)
+    {
+        msg_Err(interop, "Can't create HD device (not Windows 7+)");
+        goto error;
+    }
+
+    DXVAHD_CONTENT_DESC desc;
+    desc.InputFrameFormat = DXVAHD_FRAME_FORMAT_PROGRESSIVE;
+    GetFrameRate( &desc.InputFrameRate, &interop->fmt );
+    desc.InputWidth       = interop->fmt.i_visible_width;
+    desc.InputHeight      = interop->fmt.i_visible_height;
+    desc.OutputFrameRate  = desc.InputFrameRate;
+    desc.OutputWidth      = interop->fmt.i_visible_width;
+    desc.OutputHeight     = interop->fmt.i_visible_height;
+
+    hr = CreateDevice(devex, &desc, DXVAHD_DEVICE_USAGE_PLAYBACK_NORMAL, NULL, &hd_device);
+    if (FAILED(hr))
+    {
+        msg_Dbg(interop, "Failed to create the device (error 0x%lX)", hr);
+        goto error;
+    }
+
+    DXVAHD_VPDEVCAPS devcaps = { 0 };
+    hr = IDXVAHD_Device_GetVideoProcessorDeviceCaps( hd_device, &devcaps );
+    if (unlikely(FAILED(hr)))
+    {
+        msg_Err(interop, "Failed to get the device capabilities (error 0x%lX)", hr);
+        goto error;
+    }
+    if (devcaps.VideoProcessorCount == 0)
+    {
+        msg_Warn(interop, "No good video processor found for range conversion");
+        goto error;
+    }
+
+    formatsList = malloc(devcaps.InputFormatCount * sizeof(*formatsList));
+    if (unlikely(formatsList == NULL))
+    {
+        msg_Dbg(interop, "Failed to allocate %u input formats", devcaps.InputFormatCount);
+        goto error;
+    }
+
+    hr = IDXVAHD_Device_GetVideoProcessorInputFormats( hd_device, devcaps.InputFormatCount, formatsList);
+    UINT i;
+    for (i=0; i<devcaps.InputFormatCount; i++)
+    {
+        if (formatsList[i] == src_format)
+            break;
+    }
+    if (i == devcaps.InputFormatCount)
+    {
+        msg_Warn(interop, "Input format %4.4s not supported for range conversion", (const char*)&src_format);
+        goto error;
+    }
+
+    free(formatsList);
+    formatsList = malloc(devcaps.OutputFormatCount * sizeof(*formatsList));
+    if (unlikely(formatsList == NULL))
+    {
+        msg_Dbg(interop, "Failed to allocate %u output formats", devcaps.OutputFormatCount);
+        goto error;
+    }
+
+    hr = IDXVAHD_Device_GetVideoProcessorOutputFormats( hd_device, devcaps.OutputFormatCount, formatsList);
+    for (i=0; i<devcaps.OutputFormatCount; i++)
+    {
+        if (formatsList[i] == sys->OutputFormat)
+            break;
+    }
+    if (i == devcaps.OutputFormatCount)
+    {
+        msg_Warn(interop, "Output format %d not supported for range conversion", sys->OutputFormat);
+        goto error;
+    }
+
+    capsList = malloc(devcaps.VideoProcessorCount * sizeof(*capsList));
+    if (unlikely(capsList == NULL))
+    {
+        msg_Dbg(interop, "Failed to allocate %u video processors", devcaps.VideoProcessorCount);
+        goto error;
+    }
+    hr = IDXVAHD_Device_GetVideoProcessorCaps( hd_device, devcaps.VideoProcessorCount, capsList);
+    if (FAILED(hr))
+    {
+        msg_Dbg(interop, "Failed to get the processor caps (error 0x%lX)", hr);
+        goto error;
+    }
+
+    hr = IDXVAHD_Device_CreateVideoProcessor( hd_device, &capsList->VPGuid, &sys->processor.proc );
+    if (FAILED(hr))
+    {
+        msg_Dbg(interop, "Failed to create the processor (error 0x%lX)", hr);
+        goto error;
+    }
+    IDXVAHD_Device_Release( hd_device );
+
+    SetupProcessorInput(interop, &interop->fmt, src_format);
+
+    DXVAHD_BLT_STATE_OUTPUT_COLOR_SPACE_DATA colorspace = {
+        .Usage = 0, // playback
+        .RGB_Range = /* full range */true ? 0 : 1,
+        .YCbCr_xvYCC = /* full range */true ? 1 : 0,
+        .YCbCr_Matrix = /* BT601 colorspace */ false ? 0 : 1,
+    };
+    hr = IDXVAHD_VideoProcessor_SetVideoProcessBltState( sys->processor.proc, DXVAHD_BLT_STATE_OUTPUT_COLOR_SPACE, sizeof(colorspace), &colorspace);
+
+    return VLC_SUCCESS;
+
+error:
+    free(capsList);
+    free(formatsList);
+    if (hd_device)
+        IDXVAHD_Device_Release(hd_device);
+    FreeLibrary(sys->processor.dll);
+    return VLC_EGENERIC;
+}
+
+static int
+GLConvOpen(vlc_object_t *obj)
+{
+    opengl_tex_converter_t *tc = (void *) obj;
+
+    if (tc->fmt.i_chroma != VLC_CODEC_D3D9_OPAQUE
+     && tc->fmt.i_chroma != VLC_CODEC_D3D9_OPAQUE_10B)
+        return VLC_EGENERIC;
+
+    if (tc->gl->ext != VLC_GL_EXT_WGL || !tc->gl->wgl.getExtensionsString)
+        return VLC_EGENERIC;
+
+    const char *wglExt = tc->gl->wgl.getExtensionsString(tc->gl);
+
+    if (wglExt == NULL || !HasExtension(wglExt, "WGL_NV_DX_interop"))
+        return VLC_EGENERIC;
+
+    struct wgl_vt vt;
+#define LOAD_EXT(name, type) do { \
+    vt.name = (type) vlc_gl_GetProcAddress(tc->gl, "wgl" #name); \
+    if (!vt.name) { \
+        msg_Warn(obj, "'wgl " #name "' could not be loaded"); \
+        return VLC_EGENERIC; \
+    } \
+} while(0)
+
+    LOAD_EXT(DXSetResourceShareHandleNV, PFNWGLDXSETRESOURCESHAREHANDLENVPROC);
+    LOAD_EXT(DXOpenDeviceNV, PFNWGLDXOPENDEVICENVPROC);
+    LOAD_EXT(DXCloseDeviceNV, PFNWGLDXCLOSEDEVICENVPROC);
+    LOAD_EXT(DXRegisterObjectNV, PFNWGLDXREGISTEROBJECTNVPROC);
+    LOAD_EXT(DXUnregisterObjectNV, PFNWGLDXUNREGISTEROBJECTNVPROC);
+    LOAD_EXT(DXLockObjectsNV, PFNWGLDXLOCKOBJECTSNVPROC);
+    LOAD_EXT(DXUnlockObjectsNV, PFNWGLDXUNLOCKOBJECTSNVPROC);
+
+    struct glpriv *priv = calloc(1, sizeof(struct glpriv));
+    if (!priv)
+        return VLC_ENOMEM;
+    tc->priv = priv;
+    priv->OutputFormat = D3DFMT_X8R8G8B8;
+    priv->vt = vt;
+
+    if (D3D9_Create(obj, &priv->hd3d) != VLC_SUCCESS)
+        goto error;
+
+    if (!priv->hd3d.use_ex)
+    {
+        msg_Warn(obj, "DX/GL interrop only working on d3d9x");
+        goto error;
+    }
+
+    if (FAILED(D3D9_CreateDevice(obj, &priv->hd3d, tc->gl->surface->handle.hwnd,
+                                 &tc->fmt, &priv->d3d_dev)))
+        goto error;
+
+    D3DFORMAT format = tc->fmt.i_chroma == VLC_CODEC_D3D9_OPAQUE_10B ?
+                       MAKEFOURCC('P','0','1','0') : MAKEFOURCC('N','V','1','2');
+
+    HRESULT hr;
+    bool force_dxva_hd = false;
+    if ( !tc->fmt.b_color_range_full &&
+         priv->d3d_dev.identifier.VendorId == GPU_MANUFACTURER_NVIDIA )
+    {
+        // NVIDIA bug, YUV to RGB internal conversion in StretchRect always converts from limited to limited range
+        msg_Dbg(tc->gl, "init DXVA-HD processor from %4.4s to RGB", (const char*)&format);
+        int err = InitRangeProcessor(tc, priv->d3d_dev.devex, format);
+        if (err == VLC_SUCCESS)
+            force_dxva_hd = true;
+    }
+    if (!force_dxva_hd)
+    {
+        // test whether device can perform color-conversion from that format to target format
+        hr = IDirect3D9_CheckDeviceFormatConversion(priv->hd3d.obj,
+                                                    priv->d3d_dev.adapterId,
+                                                    D3DDEVTYPE_HAL,
+                                                    format, priv->OutputFormat);
+        if (FAILED(hr))
+        {
+            msg_Dbg(tc->gl, "Unsupported conversion from %4.4s to RGB", (const char*)&format );
+            goto error;
+        }
+        msg_Dbg(tc->gl, "using StrecthRect from %4.4s to RGB", (const char*)&format );
+    }
+
+    HANDLE shared_handle = NULL;
+    hr = IDirect3DDevice9Ex_CreateRenderTarget(priv->d3d_dev.devex,
+                                               tc->fmt.i_visible_width,
+                                               tc->fmt.i_visible_height,
+                                               priv->OutputFormat,
+                                               D3DMULTISAMPLE_NONE, 0, FALSE,
+                                               &priv->dx_render, &shared_handle);
+    if (FAILED(hr))
+    {
+        msg_Warn(obj, "IDirect3DDevice9_CreateOffscreenPlainSurface failed");
+        goto error;
+    }
+
+   if (shared_handle)
+        priv->vt.DXSetResourceShareHandleNV(priv->dx_render, shared_handle);
+
+    priv->gl_handle_d3d = priv->vt.DXOpenDeviceNV(priv->d3d_dev.devex);
+    if (!priv->gl_handle_d3d)
+    {
+        msg_Warn(obj, "DXOpenDeviceNV failed: %lu", GetLastError());
+        goto error;
+    }
+
+    tc->pf_update  = GLConvUpdate;
+    tc->pf_get_pool = GLConvGetPool;
+    tc->pf_allocate_textures = GLConvAllocateTextures;
+
+    tc->fshader = opengl_fragment_shader_init(tc, GL_TEXTURE_2D, VLC_CODEC_RGB32,
+                                              COLOR_SPACE_UNDEF);
+    if (tc->fshader == 0)
+        goto error;
+
+    return VLC_SUCCESS;
+
+error:
+    GLConvClose(obj);
+    return VLC_EGENERIC;
+}


=====================================
modules/video_output/win32/direct3d9.c
=====================================
@@ -70,9 +70,6 @@
 static int  Open(vlc_object_t *);
 static void Close(vlc_object_t *);
 
-static int  GLConvOpen(vlc_object_t *);
-static void GLConvClose(vlc_object_t *);
-
 #define DESKTOP_LONGTEXT N_(\
     "The desktop mode allows you to display the video on the desktop.")
 
@@ -109,13 +106,6 @@ vlc_module_begin ()
     set_capability("vout display", 280)
     add_shortcut("direct3d9", "direct3d")
     set_callbacks(Open, Close)
-
-#ifdef HAVE_GL
-    add_submodule()
-    set_description("DX OpenGL surface converter for D3D9")
-    set_capability("glconv", 1)
-    set_callbacks(GLConvOpen, GLConvClose)
-#endif
 vlc_module_end ()
 
 /*****************************************************************************
@@ -126,16 +116,6 @@ static const vlc_fourcc_t d3d_subpicture_chromas[] = {
     0
 };
 
-typedef struct
-{
-    const char   *name;
-    D3DFORMAT    format;    /* D3D format */
-    vlc_fourcc_t fourcc;    /* VLC fourcc */
-    uint32_t     rmask;
-    uint32_t     gmask;
-    uint32_t     bmask;
-} d3d9_format_t;
-
 struct vout_display_sys_t
 {
     vout_display_sys_win32_t sys;
@@ -188,9 +168,6 @@ static const d3d9_format_t *FindBufferFormat(vout_display_t *, D3DFORMAT);
 
 static int  Open(vlc_object_t *);
 
-static picture_pool_t *Direct3D9CreatePicturePool  (vlc_object_t *, d3d9_device_t *,
-     const d3d9_format_t *, const video_format_t *, unsigned);
-
 static void           Prepare(vout_display_t *, picture_t *, subpicture_t *subpicture);
 static void           Display(vout_display_t *, picture_t *, subpicture_t *subpicture);
 static picture_pool_t*DisplayPool(vout_display_t *, unsigned);
@@ -231,18 +208,6 @@ static void Direct3D9RenderScene(vout_display_t *vd, d3d_region_t *, int, d3d_re
 /* */
 static int DesktopCallback(vlc_object_t *, char const *, vlc_value_t, vlc_value_t, void *);
 
-static bool is_d3d9_opaque(vlc_fourcc_t chroma)
-{
-    switch (chroma)
-    {
-    case VLC_CODEC_D3D9_OPAQUE:
-    case VLC_CODEC_D3D9_OPAQUE_10B:
-        return true;
-    default:
-        return false;
-    }
-}
-
 static HINSTANCE Direct3D9LoadShaderLibrary(void)
 {
     HINSTANCE instance = NULL;
@@ -404,126 +369,6 @@ static void Close(vlc_object_t *object)
     free(vd->sys);
 }
 
-static void DestroyPicture(picture_t *picture)
-{
-    ReleasePictureSys(picture->p_sys);
-
-    free(picture->p_sys);
-    free(picture);
-}
-
-/**
- * It locks the surface associated to the picture and get the surface
- * descriptor which amongst other things has the pointer to the picture
- * data and its pitch.
- */
-static int Direct3D9LockSurface(picture_t *picture)
-{
-    /* Lock the surface to get a valid pointer to the picture buffer */
-    D3DLOCKED_RECT d3drect;
-    HRESULT hr = IDirect3DSurface9_LockRect(picture->p_sys->surface, &d3drect, NULL, 0);
-    if (FAILED(hr)) {
-        return VLC_EGENERIC;
-    }
-
-    CommonUpdatePicture(picture, NULL, d3drect.pBits, d3drect.Pitch);
-    return VLC_SUCCESS;
-}
-/**
- * It unlocks the surface associated to the picture.
- */
-static void Direct3D9UnlockSurface(picture_t *picture)
-{
-    /* Unlock the Surface */
-    HRESULT hr = IDirect3DSurface9_UnlockRect(picture->p_sys->surface);
-    if (FAILED(hr)) {
-        //msg_Dbg(vd, "Failed IDirect3DSurface9_UnlockRect: 0x%0lx", hr);
-    }
-}
-
-/* */
-static picture_pool_t *Direct3D9CreatePicturePool(vlc_object_t *o,
-    d3d9_device_t *p_d3d9_dev, const d3d9_format_t *default_d3dfmt, const video_format_t *fmt, unsigned count)
-{
-    picture_pool_t*   pool = NULL;
-    picture_t**       pictures = NULL;
-    unsigned          picture_count = 0;
-
-    pictures = calloc(count, sizeof(*pictures));
-    if (!pictures)
-        goto error;
-
-    D3DFORMAT format;
-    switch (fmt->i_chroma)
-    {
-    case VLC_CODEC_D3D9_OPAQUE_10B:
-        format = MAKEFOURCC('P','0','1','0');
-        break;
-    case VLC_CODEC_D3D9_OPAQUE:
-        format = MAKEFOURCC('N','V','1','2');
-        break;
-    default:
-        if (!default_d3dfmt)
-            goto error;
-        format = default_d3dfmt->format;
-        break;
-    }
-
-    for (picture_count = 0; picture_count < count; ++picture_count)
-    {
-        picture_sys_t *picsys = malloc(sizeof(*picsys));
-        if (unlikely(picsys == NULL))
-            goto error;
-        memset(picsys, 0, sizeof(*picsys));
-
-        HRESULT hr = IDirect3DDevice9_CreateOffscreenPlainSurface(p_d3d9_dev->dev,
-                                                          fmt->i_width,
-                                                          fmt->i_height,
-                                                          format,
-                                                          D3DPOOL_DEFAULT,
-                                                          &picsys->surface,
-                                                          NULL);
-        if (FAILED(hr)) {
-           msg_Err(o, "Failed to allocate surface %d (hr=0x%0lx)", picture_count, hr);
-           free(picsys);
-           goto error;
-        }
-
-        picture_resource_t resource = {
-            .p_sys = picsys,
-            .pf_destroy = DestroyPicture,
-        };
-
-        picture_t *picture = picture_NewFromResource(fmt, &resource);
-        if (unlikely(picture == NULL)) {
-            free(picsys);
-            goto error;
-        }
-
-        pictures[picture_count] = picture;
-    }
-
-    picture_pool_configuration_t pool_cfg;
-    memset(&pool_cfg, 0, sizeof(pool_cfg));
-    pool_cfg.picture_count = count;
-    pool_cfg.picture       = pictures;
-    if( !is_d3d9_opaque( fmt->i_chroma ) )
-    {
-        pool_cfg.lock = Direct3D9LockSurface;
-        pool_cfg.unlock = Direct3D9UnlockSurface;
-    }
-
-    pool = picture_pool_NewExtended( &pool_cfg );
-
-error:
-    if (pool == NULL && pictures) {
-        for (unsigned i=0;i<picture_count; ++i)
-            DestroyPicture(pictures[i]);
-    }
-    free(pictures);
-    return pool;
-}
-
 static picture_pool_t *DisplayPool(vout_display_t *vd, unsigned count)
 {
     if ( vd->sys->sys.pool != NULL )
@@ -815,10 +660,12 @@ static void SetupProcessorInput(vout_display_t *vd, const video_format_t *fmt, c
     DXVAHD_STREAM_STATE_FRAME_FORMAT_DATA frame_format = { DXVAHD_FRAME_FORMAT_PROGRESSIVE };
     hr = IDXVAHD_VideoProcessor_SetVideoProcessStreamState( sys->processor.proc, 0, DXVAHD_STREAM_STATE_FRAME_FORMAT, sizeof(frame_format), &frame_format );
 
-    DXVAHD_STREAM_STATE_INPUT_COLOR_SPACE_DATA colorspace = { 0 };
-    colorspace.RGB_Range = fmt->b_color_range_full ? 0 : 1;
-    colorspace.YCbCr_xvYCC = fmt->b_color_range_full ? 1 : 0;
-    colorspace.YCbCr_Matrix = fmt->space == COLOR_SPACE_BT601 ? 0 : 1;
+    DXVAHD_STREAM_STATE_INPUT_COLOR_SPACE_DATA colorspace = {
+        .Type = 0, // video, not graphics
+        .RGB_Range = fmt->b_color_range_full ? 0 : 1,
+        .YCbCr_xvYCC = fmt->b_color_range_full ? 1 : 0,
+        .YCbCr_Matrix = fmt->space == COLOR_SPACE_BT601 ? 0 : 1,
+    };
     hr = IDXVAHD_VideoProcessor_SetVideoProcessStreamState( sys->processor.proc, 0, DXVAHD_STREAM_STATE_INPUT_COLOR_SPACE, sizeof(colorspace), &colorspace );
 
     DXVAHD_STREAM_STATE_SOURCE_RECT_DATA srcRect;
@@ -870,8 +717,11 @@ static int InitRangeProcessor(vout_display_t *vd, const d3d9_format_t *d3dfmt)
     DXVAHD_VPCAPS *capsList = NULL;
     IDXVAHD_Device *hd_device = NULL;
 
-    HRESULT (WINAPI *CreateDevice)(IDirect3DDevice9Ex *,const DXVAHD_CONTENT_DESC *,DXVAHD_DEVICE_USAGE,PDXVAHDSW_Plugin,IDXVAHD_Device **);
-    CreateDevice = (void *)GetProcAddress(sys->processor.dll, "DXVAHD_CreateDevice");
+#ifdef __MINGW64_VERSION_MAJOR
+    typedef HRESULT (WINAPI* PDXVAHD_CreateDevice)(IDirect3DDevice9Ex *,const DXVAHD_CONTENT_DESC *,DXVAHD_DEVICE_USAGE,PDXVAHDSW_Plugin,IDXVAHD_Device **);
+#endif
+    PDXVAHD_CreateDevice CreateDevice;
+    CreateDevice = (PDXVAHD_CreateDevice)GetProcAddress(sys->processor.dll, "DXVAHD_CreateDevice");
     if (CreateDevice == NULL)
     {
         msg_Err(vd, "Can't create HD device (not Windows 7+)");
@@ -961,11 +811,12 @@ static int InitRangeProcessor(vout_display_t *vd, const d3d9_format_t *d3dfmt)
 
     SetupProcessorInput(vd, &vd->source, d3dfmt);
 
-    DXVAHD_BLT_STATE_OUTPUT_COLOR_SPACE_DATA colorspace;
-    colorspace.Usage = 0; // playback
-    colorspace.RGB_Range = 0; // full range display
-    colorspace.YCbCr_xvYCC = 1;
-    colorspace.YCbCr_Matrix = 1; // BT.709
+    DXVAHD_BLT_STATE_OUTPUT_COLOR_SPACE_DATA colorspace = {
+        .Usage = 0, // playback
+        .RGB_Range = 0, // full range display
+        .YCbCr_xvYCC = 1,
+        .YCbCr_Matrix = 1, // BT.709
+    };
     hr = IDXVAHD_VideoProcessor_SetVideoProcessBltState( sys->processor.proc, DXVAHD_BLT_STATE_OUTPUT_COLOR_SPACE, sizeof(colorspace), &colorspace);
 
     return VLC_SUCCESS;
@@ -2057,224 +1908,3 @@ static int FindShadersCallback(vlc_object_t *object, const char *name,
     return ctx.count;
 
 }
-
-#ifdef HAVE_GL
-#include "../opengl/converter.h"
-#include <GL/wglew.h>
-
-struct wgl_vt {
-    PFNWGLDXSETRESOURCESHAREHANDLENVPROC DXSetResourceShareHandleNV;
-    PFNWGLDXOPENDEVICENVPROC             DXOpenDeviceNV;
-    PFNWGLDXCLOSEDEVICENVPROC            DXCloseDeviceNV;
-    PFNWGLDXREGISTEROBJECTNVPROC         DXRegisterObjectNV;
-    PFNWGLDXUNREGISTEROBJECTNVPROC       DXUnregisterObjectNV;
-    PFNWGLDXLOCKOBJECTSNVPROC            DXLockObjectsNV;
-    PFNWGLDXUNLOCKOBJECTSNVPROC          DXUnlockObjectsNV;
-};
-struct glpriv
-{
-    struct wgl_vt vt;
-    d3d9_handle_t hd3d;
-    d3d9_device_t d3d_dev;
-    HANDLE gl_handle_d3d;
-    HANDLE gl_render;
-    IDirect3DSurface9 *dx_render;
-};
-
-static int
-GLConvUpdate(const opengl_tex_converter_t *tc, GLuint *textures,
-             const GLsizei *tex_width, const GLsizei *tex_height,
-             picture_t *pic, const size_t *plane_offset)
-{
-    VLC_UNUSED(textures); VLC_UNUSED(tex_width); VLC_UNUSED(tex_height); VLC_UNUSED(plane_offset);
-    struct glpriv *priv = tc->priv;
-    HRESULT hr;
-
-    picture_sys_t *picsys = ActivePictureSys(pic);
-    if (unlikely(!picsys || !priv->gl_render))
-        return VLC_EGENERIC;
-
-    if (!priv->vt.DXUnlockObjectsNV(priv->gl_handle_d3d, 1, &priv->gl_render))
-    {
-        msg_Warn(tc->gl, "DXUnlockObjectsNV failed");
-        return VLC_EGENERIC;
-    }
-
-    const RECT rect = {
-        .left = 0,
-        .top = 0,
-        .right = pic->format.i_visible_width,
-        .bottom = pic->format.i_visible_height
-    };
-    hr = IDirect3DDevice9Ex_StretchRect(priv->d3d_dev.devex, picsys->surface,
-                                        &rect, priv->dx_render, NULL, D3DTEXF_NONE);
-    if (FAILED(hr))
-    {
-        msg_Warn(tc->gl, "IDirect3DDevice9Ex_StretchRect failed");
-        return VLC_EGENERIC;
-    }
-
-    if (!priv->vt.DXLockObjectsNV(priv->gl_handle_d3d, 1, &priv->gl_render))
-    {
-        msg_Warn(tc->gl, "DXLockObjectsNV failed");
-        priv->vt.DXUnregisterObjectNV(priv->gl_handle_d3d, priv->gl_render);
-        priv->gl_render = NULL;
-        return VLC_EGENERIC;
-    }
-
-    return VLC_SUCCESS;
-}
-
-static picture_pool_t *
-GLConvGetPool(const opengl_tex_converter_t *tc, unsigned requested_count)
-{
-    struct glpriv *priv = tc->priv;
-    return Direct3D9CreatePicturePool(VLC_OBJECT(tc->gl), &priv->d3d_dev, NULL,
-                                      &tc->fmt, requested_count);
-}
-
-static int
-GLConvAllocateTextures(const opengl_tex_converter_t *tc, GLuint *textures,
-                       const GLsizei *tex_width, const GLsizei *tex_height)
-{
-    VLC_UNUSED(tex_width); VLC_UNUSED(tex_height);
-    struct glpriv *priv = tc->priv;
-
-    priv->gl_render =
-        priv->vt.DXRegisterObjectNV(priv->gl_handle_d3d, priv->dx_render,
-                                    textures[0], GL_TEXTURE_2D, WGL_ACCESS_WRITE_DISCARD_NV);
-    if (!priv->gl_render)
-    {
-        msg_Warn(tc->gl, "DXRegisterObjectNV failed: %lu", GetLastError());
-        return VLC_EGENERIC;
-    }
-
-    if (!priv->vt.DXLockObjectsNV(priv->gl_handle_d3d, 1, &priv->gl_render))
-    {
-        msg_Warn(tc->gl, "DXLockObjectsNV failed");
-        priv->vt.DXUnregisterObjectNV(priv->gl_handle_d3d, priv->gl_render);
-        priv->gl_render = NULL;
-        return VLC_EGENERIC;
-    }
-
-    return VLC_SUCCESS;
-}
-
-static void
-GLConvClose(vlc_object_t *obj)
-{
-    opengl_tex_converter_t *tc = (void *)obj;
-    struct glpriv *priv = tc->priv;
-
-    if (priv->gl_handle_d3d)
-    {
-        if (priv->gl_render)
-        {
-            priv->vt.DXUnlockObjectsNV(priv->gl_handle_d3d, 1, &priv->gl_render);
-            priv->vt.DXUnregisterObjectNV(priv->gl_handle_d3d, priv->gl_render);
-        }
-
-        priv->vt.DXCloseDeviceNV(priv->gl_handle_d3d);
-    }
-
-    if (priv->dx_render)
-        IDirect3DSurface9_Release(priv->dx_render);
-
-    D3D9_ReleaseDevice(&priv->d3d_dev);
-    D3D9_Destroy(&priv->hd3d);
-    free(tc->priv);
-}
-
-static int
-GLConvOpen(vlc_object_t *obj)
-{
-    opengl_tex_converter_t *tc = (void *) obj;
-
-    if (tc->fmt.i_chroma != VLC_CODEC_D3D9_OPAQUE
-     && tc->fmt.i_chroma != VLC_CODEC_D3D9_OPAQUE_10B)
-        return VLC_EGENERIC;
-
-    if (tc->gl->ext != VLC_GL_EXT_WGL || !tc->gl->wgl.getExtensionsString)
-        return VLC_EGENERIC;
-
-    const char *wglExt = tc->gl->wgl.getExtensionsString(tc->gl);
-
-    if (wglExt == NULL || !HasExtension(wglExt, "WGL_NV_DX_interop"))
-        return VLC_EGENERIC;
-
-    struct wgl_vt vt;
-#define LOAD_EXT(name, type) do { \
-    vt.name = (type) vlc_gl_GetProcAddress(tc->gl, "wgl" #name); \
-    if (!vt.name) { \
-        msg_Warn(obj, "'wgl " #name "' could not be loaded"); \
-        return VLC_EGENERIC; \
-    } \
-} while(0)
-
-    LOAD_EXT(DXSetResourceShareHandleNV, PFNWGLDXSETRESOURCESHAREHANDLENVPROC);
-    LOAD_EXT(DXOpenDeviceNV, PFNWGLDXOPENDEVICENVPROC);
-    LOAD_EXT(DXCloseDeviceNV, PFNWGLDXCLOSEDEVICENVPROC);
-    LOAD_EXT(DXRegisterObjectNV, PFNWGLDXREGISTEROBJECTNVPROC);
-    LOAD_EXT(DXUnregisterObjectNV, PFNWGLDXUNREGISTEROBJECTNVPROC);
-    LOAD_EXT(DXLockObjectsNV, PFNWGLDXLOCKOBJECTSNVPROC);
-    LOAD_EXT(DXUnlockObjectsNV, PFNWGLDXUNLOCKOBJECTSNVPROC);
-
-    struct glpriv *priv = calloc(1, sizeof(struct glpriv));
-    if (!priv)
-        return VLC_ENOMEM;
-    tc->priv = priv;
-    priv->vt = vt;
-
-    if (D3D9_Create(obj, &priv->hd3d) != VLC_SUCCESS)
-        goto error;
-
-    if (!priv->hd3d.use_ex)
-    {
-        msg_Warn(obj, "DX/GL interrop only working on d3d9x");
-        goto error;
-    }
-
-    if (FAILED(D3D9_CreateDevice(obj, &priv->hd3d, tc->gl->surface->handle.hwnd,
-                                 &tc->fmt, &priv->d3d_dev)))
-        goto error;
-
-    HRESULT hr;
-    HANDLE shared_handle = NULL;
-    hr = IDirect3DDevice9Ex_CreateRenderTarget(priv->d3d_dev.devex,
-                                               tc->fmt.i_visible_width,
-                                               tc->fmt.i_visible_height,
-                                               D3DFMT_X8R8G8B8,
-                                               D3DMULTISAMPLE_NONE, 0, FALSE,
-                                               &priv->dx_render, &shared_handle);
-    if (FAILED(hr))
-    {
-        msg_Warn(obj, "IDirect3DDevice9_CreateOffscreenPlainSurface failed");
-        goto error;
-    }
-
-   if (shared_handle)
-        priv->vt.DXSetResourceShareHandleNV(priv->dx_render, shared_handle);
-
-    priv->gl_handle_d3d = priv->vt.DXOpenDeviceNV(priv->d3d_dev.dev);
-    if (!priv->gl_handle_d3d)
-    {
-        msg_Warn(obj, "DXOpenDeviceNV failed: %lu", GetLastError());
-        goto error;
-    }
-
-    tc->pf_update  = GLConvUpdate;
-    tc->pf_get_pool = GLConvGetPool;
-    tc->pf_allocate_textures = GLConvAllocateTextures;
-
-    tc->fshader = opengl_fragment_shader_init(tc, GL_TEXTURE_2D, VLC_CODEC_RGB32,
-                                              COLOR_SPACE_UNDEF);
-    if (tc->fshader == 0)
-        goto error;
-
-    return VLC_SUCCESS;
-
-error:
-    GLConvClose(obj);
-    return VLC_EGENERIC;
-}
-#endif



View it on GitLab: https://code.videolan.org/videolan/vlc/-/compare/e8b689c0c1288a4921834029292333169d9ceff5...f9e125db29f9f0d57e6ed3398a80f825e6710dab

-- 
View it on GitLab: https://code.videolan.org/videolan/vlc/-/compare/e8b689c0c1288a4921834029292333169d9ceff5...f9e125db29f9f0d57e6ed3398a80f825e6710dab
You're receiving this email because of your account on code.videolan.org.


VideoLAN code repository instance


More information about the vlc-commits mailing list