[RFC PATCH v2 2/3] dxva2: Introduce IDXVAHD_Device interface.

Jeff Smith whydoubt at gmail.com
Mon Aug 10 11:33:52 CDT 2020


Signed-off-by: Jeff Smith <whydoubt at gmail.com>
---
 dlls/dxva2/dxvahd.c          | 263 ++++++++++++++++++++++++++++++++++-
 dlls/dxva2/tests/Makefile.in |   3 +-
 dlls/dxva2/tests/dxvahd.c    | 210 ++++++++++++++++++++++++++++
 include/dxvahd.idl           | 162 +++++++++++++++++++++
 4 files changed, 634 insertions(+), 4 deletions(-)
 create mode 100644 dlls/dxva2/tests/dxvahd.c

diff --git a/dlls/dxva2/dxvahd.c b/dlls/dxva2/dxvahd.c
index ac67f9e5a7..2feb7eb323 100644
--- a/dlls/dxva2/dxvahd.c
+++ b/dlls/dxva2/dxvahd.c
@@ -16,18 +16,99 @@
  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
  */
 
+#define COBJMACROS
+
 #include "d3d9.h"
+#include "initguid.h"
 #include "dxvahd.h"
 
 #include "wine/debug.h"
+#include "wine/heap.h"
 
 WINE_DEFAULT_DEBUG_CHANNEL(dxva2);
 
 
+#define MAX_INPUT_STREAMS 1
+#define MAX_STREAM_STATES 1
+
+static const D3DFORMAT output_formats[] = {
+    D3DFMT_X8R8G8B8
+};
+
+static const D3DFORMAT input_formats[] = {
+    MAKEFOURCC('N','V','1','2')
+};
+
+static const DXVAHD_VPCAPS video_processors[] = {
+    {{0x00000000,0x0000,0x0000,{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}}, 0, 0, 0, 0, 0}
+};
+
+static const DXVAHD_VPDEVCAPS dev_caps = {
+    DXVAHD_DEVICE_TYPE_HARDWARE,
+    0,  /* DeviceCaps */
+    0,  /* FeatureCaps */
+    0,  /* FilterCaps */
+    0,  /* InputFormatCaps */
+    D3DPOOL_DEFAULT,
+    ARRAY_SIZE(output_formats),
+    ARRAY_SIZE(input_formats),
+    ARRAY_SIZE(video_processors),
+    MAX_INPUT_STREAMS,
+    MAX_STREAM_STATES
+};
+
+
+struct dxvahd_device
+{
+    IDXVAHD_Device IDXVAHD_Device_iface;
+    LONG refcount;
+    IDirect3DDevice9Ex *d3d_device;
+};
+
+
 /********************************************
  * Utility functions
  */
 
+static struct dxvahd_device *impl_from_IDXVAHD_Device(IDXVAHD_Device *iface)
+{
+    return CONTAINING_RECORD(iface, struct dxvahd_device, IDXVAHD_Device_iface);
+}
+
+static const char *debug_dxvahd_surface_type(DXVAHD_SURFACE_TYPE surface_type)
+{
+    switch (surface_type)
+    {
+#define SURFACE_TYPE_TO_STR(e) case e: return #e
+        SURFACE_TYPE_TO_STR(DXVAHD_SURFACE_TYPE_VIDEO_INPUT);
+        SURFACE_TYPE_TO_STR(DXVAHD_SURFACE_TYPE_VIDEO_INPUT_PRIVATE);
+        SURFACE_TYPE_TO_STR(DXVAHD_SURFACE_TYPE_VIDEO_OUTPUT);
+#undef SURFACE_TYPE_TO_STR
+        default:
+            FIXME("Unrecognized surface type %#x.\n", surface_type);
+            return "unrecognized";
+    }
+}
+
+static const char *debug_dxvahd_filter(DXVAHD_FILTER filter)
+{
+    switch (filter)
+    {
+#define FILTER_TO_STR(e) case e: return #e
+        FILTER_TO_STR(DXVAHD_FILTER_BRIGHTNESS);
+        FILTER_TO_STR(DXVAHD_FILTER_CONTRAST);
+        FILTER_TO_STR(DXVAHD_FILTER_HUE);
+        FILTER_TO_STR(DXVAHD_FILTER_SATURATION);
+        FILTER_TO_STR(DXVAHD_FILTER_NOISE_REDUCTION);
+        FILTER_TO_STR(DXVAHD_FILTER_EDGE_ENHANCEMENT);
+        FILTER_TO_STR(DXVAHD_FILTER_ANAMORPHIC_SCALING);
+#undef FILTER_TO_STR
+        default:
+            FIXME("Unrecognized surface type %#x.\n", filter);
+            return "unrecognized";
+    }
+}
+
 static const char *debug_dxvahd_device_usage(DXVAHD_DEVICE_USAGE usage)
 {
     switch (usage)
@@ -44,6 +125,173 @@ static const char *debug_dxvahd_device_usage(DXVAHD_DEVICE_USAGE usage)
 }
 
 
+/********************************************
+ * IDXVAHD_Device functions
+ */
+
+static HRESULT WINAPI dxvahd_device_QueryInterface(IDXVAHD_Device *iface, REFIID riid, void **obj)
+{
+    TRACE("%p, %s, %p.\n", iface, debugstr_guid(riid), obj);
+
+    WARN("Unsupported interface %s.\n", debugstr_guid(riid));
+    *obj = NULL;
+    return E_NOINTERFACE;
+}
+
+static ULONG WINAPI dxvahd_device_AddRef(IDXVAHD_Device *iface)
+{
+    struct dxvahd_device *dev = impl_from_IDXVAHD_Device(iface);
+    ULONG refcount = InterlockedIncrement(&dev->refcount);
+
+    TRACE("%p, refcount %u.\n", iface, refcount);
+
+    return refcount;
+}
+
+static ULONG WINAPI dxvahd_device_Release(IDXVAHD_Device *iface)
+{
+    struct dxvahd_device *dev = impl_from_IDXVAHD_Device(iface);
+    ULONG refcount = InterlockedDecrement(&dev->refcount);
+
+    TRACE("%p, refcount %u.\n", iface, refcount);
+
+    if (!refcount)
+    {
+        heap_free(dev);
+    }
+
+    return refcount;
+}
+
+static HRESULT WINAPI dxvahd_device_CreateVideoSurface(IDXVAHD_Device *iface, UINT width, UINT height,
+        D3DFORMAT format, D3DPOOL pool, DWORD usage, DXVAHD_SURFACE_TYPE type, UINT num_surfaces,
+        IDirect3DSurface9 **ppSurface, HANDLE *pSharedHandle)
+{
+    struct dxvahd_device *dev = impl_from_IDXVAHD_Device(iface);
+    UINT i;
+
+    FIXME("%p, %u, %u, %#x, %#x, %#x, %s, %u, %p, %p.\n", iface, width, height, format, pool, usage,
+            debug_dxvahd_surface_type(type), num_surfaces, ppSurface, pSharedHandle);
+
+    if (pool != dev_caps.InputPool || num_surfaces < 1)
+        return E_INVALIDARG;
+
+    /* FIXME: Return error result (D3DERR_INVALIDCALL or E_INVALIDARG) on invalid format.
+     *        The formats returned by GetVideoProcessor[Input|Output]Formats functions
+     *        may not comprise the entire set of valid formats. */
+
+    for (i = 0; i < num_surfaces; i++)
+    {
+        /* TODO: Determine if CreateOffscreenPlainSurface is sufficient to the task,
+         *       or if a separate implementation of IDirect3DSurface9 is warranted. */
+        IDirect3DDevice9Ex_CreateOffscreenPlainSurface(dev->d3d_device, width, height, format, pool,
+                ppSurface + i, pSharedHandle);
+        TRACE("Created surface %d: %p.\n", i, ppSurface[i]);
+    }
+
+    return S_OK;
+}
+
+static HRESULT WINAPI dxvahd_device_GetVideoProcessorDeviceCaps(IDXVAHD_Device *iface,
+        DXVAHD_VPDEVCAPS *pCaps)
+{
+    FIXME("%p, %p.\n", iface, pCaps);
+
+    /* TODO: use driver D3DDDICAPS_DXVAHD_GETVPDEVCAPS */
+
+    memcpy(pCaps, &dev_caps, sizeof(dev_caps));
+
+    return S_OK;
+}
+
+static HRESULT WINAPI dxvahd_device_GetVideoProcessorOutputFormats(IDXVAHD_Device *iface, UINT count,
+        D3DFORMAT *pFormats)
+{
+    FIXME("%p, %u, %p.\n", iface, count, pFormats);
+
+    /* TODO: use driver D3DDDICAPS_DXVAHD_GETVPOUTPUTFORMATS */
+
+    if (count != dev_caps.OutputFormatCount)
+        return E_INVALIDARG;
+    memcpy(pFormats, output_formats, sizeof(output_formats));
+
+    return S_OK;
+}
+
+static HRESULT WINAPI dxvahd_device_GetVideoProcessorInputFormats(IDXVAHD_Device *iface, UINT count,
+        D3DFORMAT *pFormats)
+{
+    FIXME("%p, %u, %p.\n", iface, count, pFormats);
+
+    /* TODO: use driver D3DDDICAPS_DXVAHD_GETVPINPUTFORMATS */
+
+    if (count != dev_caps.InputFormatCount)
+        return E_INVALIDARG;
+    memcpy(pFormats, input_formats, sizeof(input_formats));
+
+    return S_OK;
+}
+
+static HRESULT WINAPI dxvahd_device_GetVideoProcessorCaps(IDXVAHD_Device *iface, UINT count,
+        DXVAHD_VPCAPS *pCaps)
+{
+    FIXME("%p, %u, %p.\n", iface, count, pCaps);
+
+    /* TODO: use driver D3DDDICAPS_DXVAHD_GETVPCAPS */
+
+    if (count != dev_caps.VideoProcessorCount)
+        return E_INVALIDARG;
+    memcpy(pCaps, video_processors, sizeof(video_processors));
+
+    return S_OK;
+}
+
+static HRESULT WINAPI dxvahd_device_GetVideoProcessorCustomRates(IDXVAHD_Device *iface,
+        const GUID *pVPGuid, UINT count, DXVAHD_CUSTOM_RATE_DATA *pRates)
+{
+    FIXME("%p, %s, %u, %p.\n", iface, debugstr_guid(pVPGuid), count, pRates);
+
+    /* TODO: use driver D3DDDICAPS_DXVAHD_GETVPCUSTOMRATES */
+
+    return (!!count) ? E_INVALIDARG : S_OK;
+}
+
+static HRESULT WINAPI dxvahd_device_GetVideoProcessorFilterRange(IDXVAHD_Device *iface,
+        DXVAHD_FILTER filter, DXVAHD_FILTER_RANGE_DATA *pRange)
+{
+    FIXME("%p, %s, %p.\n", iface, debug_dxvahd_filter(filter), pRange);
+
+    /* TODO: use driver D3DDDICAPS_DXVAHD_GETVPFILTERRANGE */
+
+    return E_INVALIDARG;
+}
+
+static HRESULT WINAPI dxvahd_device_CreateVideoProcessor(IDXVAHD_Device *iface, const GUID *pVPGuid,
+        IDXVAHD_VideoProcessor **ppVideoProcessor)
+{
+    FIXME("%p, %s, %p. stub.\n", iface, debugstr_guid(pVPGuid), ppVideoProcessor);
+
+    *ppVideoProcessor = NULL;
+
+    return E_NOINTERFACE;
+}
+
+static const IDXVAHD_DeviceVtbl dxvahd_device_vtbl =
+{
+    dxvahd_device_QueryInterface,
+    dxvahd_device_AddRef,
+    dxvahd_device_Release,
+    dxvahd_device_CreateVideoSurface,
+    dxvahd_device_GetVideoProcessorDeviceCaps,
+    dxvahd_device_GetVideoProcessorOutputFormats,
+    dxvahd_device_GetVideoProcessorInputFormats,
+    dxvahd_device_GetVideoProcessorCaps,
+    dxvahd_device_GetVideoProcessorCustomRates,
+    dxvahd_device_GetVideoProcessorFilterRange,
+    dxvahd_device_CreateVideoProcessor,
+};
+
+
 /********************************************
  * DXVA-HD device creation function
  */
@@ -51,7 +299,9 @@ static const char *debug_dxvahd_device_usage(DXVAHD_DEVICE_USAGE usage)
 HRESULT WINAPI DXVAHD_CreateDevice(IDirect3DDevice9Ex *d3d_device, const DXVAHD_CONTENT_DESC *desc,
         DXVAHD_DEVICE_USAGE usage, PDXVAHDSW_Plugin plugin, IDXVAHD_Device **device)
 {
-    FIXME("%p, %p, %s, %p, %p. stub.\n", d3d_device, desc, debug_dxvahd_device_usage(usage), plugin, device);
+    struct dxvahd_device *object;
+
+    TRACE("%p, %p, %s, %p, %p.\n", d3d_device, desc, debug_dxvahd_device_usage(usage), plugin, device);
 
     TRACE("Frame Format %d  Input %ux%u @%.2f  Output %ux%u @%.2f\n",
             desc->InputFrameFormat, desc->InputWidth, desc->InputHeight,
@@ -59,7 +309,14 @@ HRESULT WINAPI DXVAHD_CreateDevice(IDirect3DDevice9Ex *d3d_device, const DXVAHD_
             desc->OutputWidth, desc->OutputHeight,
             (double)desc->OutputFrameRate.Numerator / desc->OutputFrameRate.Denominator);
 
-    *device = NULL;
+    if (!(object = heap_alloc_zero(sizeof(*object))))
+        return E_OUTOFMEMORY;
 
-    return E_NOINTERFACE;
+    object->IDXVAHD_Device_iface.lpVtbl = &dxvahd_device_vtbl;
+    object->refcount = 1;
+    object->d3d_device = d3d_device;
+
+    *device = &object->IDXVAHD_Device_iface;
+
+    return S_OK;
 }
diff --git a/dlls/dxva2/tests/Makefile.in b/dlls/dxva2/tests/Makefile.in
index c86c5ab42f..b5d70cd94f 100644
--- a/dlls/dxva2/tests/Makefile.in
+++ b/dlls/dxva2/tests/Makefile.in
@@ -2,4 +2,5 @@ TESTDLL   = dxva2.dll
 IMPORTS   = dxva2 user32 d3d9
 
 C_SRCS = \
-	dxva2.c
+	dxva2.c \
+	dxvahd.c
diff --git a/dlls/dxva2/tests/dxvahd.c b/dlls/dxva2/tests/dxvahd.c
new file mode 100644
index 0000000000..b99dc15796
--- /dev/null
+++ b/dlls/dxva2/tests/dxvahd.c
@@ -0,0 +1,210 @@
+/*
+ * Copyright 2020 Jeff Smith
+ *
+ * This library 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 library 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 library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+#define COBJMACROS
+#include "initguid.h"
+#include "d3d9.h"
+#include "dxvahd.h"
+
+#include "wine/test.h"
+#include "wine/heap.h"
+
+IDirect3DDevice9Ex *d3d_device;
+
+static HWND create_window(void)
+{
+    RECT r = {0, 0, 640, 480};
+
+    AdjustWindowRect(&r, WS_OVERLAPPEDWINDOW | WS_VISIBLE, FALSE);
+
+    return CreateWindowA("static", "d3d9_test", WS_OVERLAPPEDWINDOW | WS_VISIBLE,
+            0, 0, r.right - r.left, r.bottom - r.top, NULL, NULL, NULL, NULL);
+}
+
+static IDirect3DDevice9Ex *create_device(IDirect3D9Ex *d3d9, HWND focus_window)
+{
+    D3DPRESENT_PARAMETERS present_parameters = {0};
+    IDirect3DDevice9Ex *device = NULL;
+
+    present_parameters.BackBufferWidth = 640;
+    present_parameters.BackBufferHeight = 480;
+    present_parameters.BackBufferFormat = D3DFMT_A8R8G8B8;
+    present_parameters.SwapEffect = D3DSWAPEFFECT_DISCARD;
+    present_parameters.hDeviceWindow = focus_window;
+    present_parameters.Windowed = TRUE;
+    present_parameters.EnableAutoDepthStencil = TRUE;
+    present_parameters.AutoDepthStencilFormat = D3DFMT_D24S8;
+
+    IDirect3D9Ex_CreateDeviceEx(d3d9, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, focus_window,
+            D3DCREATE_HARDWARE_VERTEXPROCESSING, &present_parameters, NULL, &device);
+
+    return device;
+}
+
+static void init_desc(DXVAHD_CONTENT_DESC *desc)
+{
+    desc->InputFrameFormat = DXVAHD_FRAME_FORMAT_PROGRESSIVE;
+    desc->InputFrameRate.Numerator = 30;
+    desc->InputFrameRate.Denominator = 1;
+    desc->InputWidth = 640;
+    desc->InputHeight = 480;
+    desc->OutputFrameRate.Numerator = 30;
+    desc->OutputFrameRate.Denominator = 1;
+    desc->OutputWidth = 640;
+    desc->OutputHeight = 480;
+}
+
+static void test_dxvahd_device(void)
+{
+    IDXVAHD_Device *device, *device2;
+    IDirect3DSurface9 *surfaces[2];
+    HRESULT hr;
+    DXVAHD_CONTENT_DESC desc = {0};
+    DXVAHD_VPDEVCAPS caps = {0};
+    D3DFORMAT *input_formats;
+    D3DFORMAT *output_formats;
+    DXVAHD_VPCAPS *vp_caps;
+    int i;
+
+    init_desc(&desc);
+    hr = DXVAHD_CreateDevice(d3d_device, &desc, DXVAHD_DEVICE_USAGE_PLAYBACK_NORMAL, NULL, &device);
+    ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
+    ok(!!device, "Failed to create DXVA-HD device.\n");
+
+    hr = IDXVAHD_Device_QueryInterface(device, &IID_IDXVAHD_Device, (void **)&device2);
+    ok(hr == E_NOINTERFACE, "IDXVAHD_Device::QueryInterface for IID_IDXVAHD_Device returned %08x, expected E_NOINTERFACE\n", hr);
+    ok(device2 == NULL, "QueryInterface returned interface %p, expected NULL\n", device2);
+
+    hr = IDXVAHD_Device_QueryInterface(device, &IID_IUnknown, (void **)&device2);
+    ok(hr == E_NOINTERFACE, "IDXVAHD_Device::QueryInterface for IID_IUnknown returned %08x, expected E_NOINTERFACE\n", hr);
+    ok(device2 == NULL, "QueryInterface returned interface %p, expected NULL\n", device2);
+
+
+    hr = IDXVAHD_Device_GetVideoProcessorDeviceCaps(device, &caps);
+    ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
+
+    output_formats = heap_alloc_zero(caps.OutputFormatCount * sizeof(*output_formats));
+    hr = IDXVAHD_Device_GetVideoProcessorOutputFormats(device, caps.OutputFormatCount, output_formats);
+    ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
+    hr = IDXVAHD_Device_GetVideoProcessorOutputFormats(device, caps.OutputFormatCount + 1, output_formats);
+    ok(hr == E_INVALIDARG, "Unexpected hr %#x.\n", hr);
+    if (caps.OutputFormatCount >= 1)
+    {
+        hr = IDXVAHD_Device_GetVideoProcessorOutputFormats(device, caps.OutputFormatCount - 1, output_formats);
+        ok(hr == E_INVALIDARG, "Unexpected hr %#x.\n", hr);
+    }
+
+    input_formats = heap_alloc_zero(caps.InputFormatCount * sizeof(*input_formats));
+    hr = IDXVAHD_Device_GetVideoProcessorInputFormats(device, caps.InputFormatCount, input_formats);
+    ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
+    hr = IDXVAHD_Device_GetVideoProcessorInputFormats(device, caps.InputFormatCount + 1, input_formats);
+    ok(hr == E_INVALIDARG, "Unexpected hr %#x.\n", hr);
+    if (caps.InputFormatCount >= 1)
+    {
+        hr = IDXVAHD_Device_GetVideoProcessorInputFormats(device, caps.InputFormatCount - 1, input_formats);
+        ok(hr == E_INVALIDARG, "Unexpected hr %#x.\n", hr);
+    }
+
+    vp_caps = heap_alloc_zero(caps.VideoProcessorCount * sizeof(*vp_caps));
+    hr = IDXVAHD_Device_GetVideoProcessorCaps(device, caps.VideoProcessorCount, vp_caps);
+    ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
+    hr = IDXVAHD_Device_GetVideoProcessorCaps(device, caps.VideoProcessorCount + 1, vp_caps);
+    ok(hr == E_INVALIDARG, "Unexpected hr %#x.\n", hr);
+    if (caps.VideoProcessorCount >= 1)
+    {
+        hr = IDXVAHD_Device_GetVideoProcessorCaps(device, caps.VideoProcessorCount - 1, vp_caps);
+        ok(hr == E_INVALIDARG, "Unexpected hr %#x.\n", hr);
+    }
+
+
+    /* CreateVideoSurface: Try each input format */
+    for (i = 0; i < caps.InputFormatCount; i++)
+    {
+        hr = IDXVAHD_Device_CreateVideoSurface(device, 2, 2, input_formats[i], caps.InputPool, 0,
+                DXVAHD_SURFACE_TYPE_VIDEO_INPUT, 1, surfaces, NULL);
+        ok(hr == S_OK, "Unexpected hr %#x for input format %#x.\n", hr, input_formats[i]);
+        IDirect3DSurface9_Release(surfaces[0]);
+    }
+
+    /* NOTE: some video surface formats besides those returned by
+     * GetVideoProcessor[Input|Output]Formats may be allowed by CreateVideoSurface. */
+
+    /* CreateVideoSurface: Invalid input format */
+    hr = IDXVAHD_Device_CreateVideoSurface(device, 2, 2, 0xdeadbeef, caps.InputPool, 0,
+            DXVAHD_SURFACE_TYPE_VIDEO_INPUT, 1, surfaces, NULL);
+    todo_wine ok(hr == D3DERR_INVALIDCALL, "Unexpected hr %#x for input format %#x.\n", hr, 0xdeadbeef);
+
+    if (caps.InputFormatCount >= 1)
+    {
+        /* CreateVideoSurface: Request 0 surfaces */
+        hr = IDXVAHD_Device_CreateVideoSurface(device, 2, 2, input_formats[0], caps.InputPool, 0,
+                DXVAHD_SURFACE_TYPE_VIDEO_INPUT, 0, surfaces, NULL);
+        ok(hr == E_INVALIDARG, "Unexpected hr %#x.\n", hr);
+        /* CreateVideoSurface: Wrong pool */
+        hr = IDXVAHD_Device_CreateVideoSurface(device, 2, 2, input_formats[0], caps.InputPool + 1, 0,
+                DXVAHD_SURFACE_TYPE_VIDEO_INPUT, 1, surfaces, NULL);
+        ok(hr == E_INVALIDARG, "Unexpected hr %#x.\n", hr);
+    }
+
+
+    heap_free(output_formats);
+    heap_free(input_formats);
+    heap_free(vp_caps);
+    IDXVAHD_Device_Release(device);
+}
+
+START_TEST(dxvahd)
+{
+    IDXVAHD_Device *device = NULL;
+    IDirect3D9Ex *d3d;
+    HWND window;
+    HRESULT hr;
+    DXVAHD_CONTENT_DESC desc = {0};
+
+    hr = Direct3DCreate9Ex(D3D_SDK_VERSION, &d3d);
+    if (hr != S_OK)
+    {
+        skip("Failed to create a D3D object, skipping tests.\n");
+        return;
+    }
+
+    window = create_window();
+
+    if (!(d3d_device = create_device(d3d, window)))
+    {
+        skip("Failed to create a D3D device, skipping tests.\n");
+        IDirect3D9_Release(d3d);
+        DestroyWindow(window);
+    }
+
+    init_desc(&desc);
+    hr = DXVAHD_CreateDevice(d3d_device, &desc, DXVAHD_DEVICE_USAGE_PLAYBACK_NORMAL, NULL, &device);
+    if (hr == E_NOINTERFACE)
+    {
+        skip("Device does not support DXVA-HD, skipping tests.\n");
+        goto done;
+    }
+    IDXVAHD_Device_Release(device);
+
+    test_dxvahd_device();
+
+done:
+    IDirect3DDevice9_Release(d3d_device);
+    IDirect3D9_Release(d3d);
+    DestroyWindow(window);
+}
diff --git a/include/dxvahd.idl b/include/dxvahd.idl
index cd6de6eab3..76913c0547 100644
--- a/include/dxvahd.idl
+++ b/include/dxvahd.idl
@@ -20,6 +20,10 @@ import "unknwn.idl";
 
 cpp_quote("#if 0")
 interface IDirect3DDevice9Ex;
+interface IDirect3DSurface9;
+
+typedef DWORD D3DFORMAT;
+typedef DWORD D3DPOOL;
 cpp_quote("#endif")
 
 
@@ -37,6 +41,73 @@ typedef enum _DXVAHD_DEVICE_USAGE
     DXVAHD_DEVICE_USAGE_OPTIMAL_QUALITY = 2
 } DXVAHD_DEVICE_USAGE;
 
+typedef enum _DXVAHD_FILTER
+{
+    DXVAHD_FILTER_BRIGHTNESS         = 0,
+    DXVAHD_FILTER_CONTRAST           = 1,
+    DXVAHD_FILTER_HUE                = 2,
+    DXVAHD_FILTER_SATURATION         = 3,
+    DXVAHD_FILTER_NOISE_REDUCTION    = 4,
+    DXVAHD_FILTER_EDGE_ENHANCEMENT   = 5,
+    DXVAHD_FILTER_ANAMORPHIC_SCALING = 6
+} DXVAHD_FILTER;
+
+typedef enum _DXVAHD_SURFACE_TYPE
+{
+    DXVAHD_SURFACE_TYPE_VIDEO_INPUT         = 0,
+    DXVAHD_SURFACE_TYPE_VIDEO_INPUT_PRIVATE = 1,
+    DXVAHD_SURFACE_TYPE_VIDEO_OUTPUT        = 2
+} DXVAHD_SURFACE_TYPE;
+
+typedef enum _DXVAHD_DEVICE_TYPE
+{
+    DXVAHD_DEVICE_TYPE_HARDWARE  = 0,
+    DXVAHD_DEVICE_TYPE_SOFTWARE  = 1,
+    DXVAHD_DEVICE_TYPE_REFERENCE = 2,
+    DXVAHD_DEVICE_TYPE_OTHER     = 3
+} DXVAHD_DEVICE_TYPE;
+
+typedef enum _DXVAHD_DEVICE_CAPS
+{
+    DXVAHD_DEVICE_CAPS_LINEAR_SPACE            = 0x01,
+    DXVAHD_DEVICE_CAPS_xvYCC                   = 0x02,
+    DXVAHD_DEVICE_CAPS_RGB_RANGE_CONVERSION    = 0x04,
+    DXVAHD_DEVICE_CAPS_YCbCr_MATRIX_CONVERSION = 0x08
+    /* Based on DDI, Windows 8.1+ should also support:
+     * ..._NOMINAL_RANGE = 0x10
+     */
+} DXVAHD_DEVICE_CAPS;
+
+typedef enum _DXVAHD_FEATURE_CAPS
+{
+    DXVAHD_FEATURE_CAPS_ALPHA_FILL    = 0x01,
+    DXVAHD_FEATURE_CAPS_CONSTRICTION  = 0x02,
+    DXVAHD_FEATURE_CAPS_LUMA_KEY      = 0x04,
+    DXVAHD_FEATURE_CAPS_ALPHA_PALETTE = 0x08
+    /* Based on DDI, Windows 8+ should also support:
+     * ..._ROTATION = 0x10
+     */
+} DXVAHD_FEATURE_CAPS;
+
+typedef enum _DXVAHD_FILTER_CAPS
+{
+    DXVAHD_FILTER_CAPS_BRIGHTNESS         = 0x01,
+    DXVAHD_FILTER_CAPS_CONTRAST           = 0x02,
+    DXVAHD_FILTER_CAPS_HUE                = 0x04,
+    DXVAHD_FILTER_CAPS_SATURATION         = 0x08,
+    DXVAHD_FILTER_CAPS_NOISE_REDUCTION    = 0x10,
+    DXVAHD_FILTER_CAPS_EDGE_ENHANCEMENT   = 0x20,
+    DXVAHD_FILTER_CAPS_ANAMORPHIC_SCALING = 0x40
+} DXVAHD_FILTER_CAPS;
+
+typedef enum _DXVAHD_INPUT_FORMAT_CAPS
+{
+    DXVAHD_INPUT_FORMAT_CAPS_RGB_INTERLACED     = 0x01,
+    DXVAHD_INPUT_FORMAT_CAPS_RGB_PROCAMP        = 0x02,
+    DXVAHD_INPUT_FORMAT_CAPS_RGB_LUMA_KEY       = 0x04,
+    DXVAHD_INPUT_FORMAT_CAPS_PALETTE_INTERLACED = 0x08
+} DXVAHD_INPUT_FORMAT_CAPS;
+
 
 typedef struct _DXVAHD_RATIONAL
 {
@@ -55,6 +126,47 @@ typedef struct _DXVAHD_CONTENT_DESC
     UINT                OutputHeight;
 } DXVAHD_CONTENT_DESC;
 
+typedef struct _DXVAHD_VPCAPS
+{
+    GUID VPGuid;
+    UINT PastFrames;
+    UINT FutureFrames;
+    UINT ProcessorCaps;
+    UINT ITelecineCaps;
+    UINT CustomRateCount;
+} DXVAHD_VPCAPS;
+
+typedef struct _DXVAHD_CUSTOM_RATE_DATA
+{
+    DXVAHD_RATIONAL CustomRate;
+    UINT            OutputFrames;
+    BOOL            InputInterlaced;
+    UINT            InputFramesOrFields;
+} DXVAHD_CUSTOM_RATE_DATA;
+
+typedef struct _DXVAHD_FILTER_RANGE_DATA
+{
+    INT   Minimum;
+    INT   Maximum;
+    INT   Default;
+    FLOAT Multiplier;
+} DXVAHD_FILTER_RANGE_DATA;
+
+typedef struct _DXVAHD_VPDEVCAPS
+{
+    DXVAHD_DEVICE_TYPE DeviceType;
+    UINT               DeviceCaps;
+    UINT               FeatureCaps;
+    UINT               FilterCaps;
+    UINT               InputFormatCaps;
+    D3DPOOL            InputPool;
+    UINT               OutputFormatCount;
+    UINT               InputFormatCount;
+    UINT               VideoProcessorCount;
+    UINT               MaxInputStreams;
+    UINT               MaxStreamStates;
+} DXVAHD_VPDEVCAPS;
+
 
 /* FIXME */
 typedef void* PDXVAHDSW_Plugin;
@@ -63,3 +175,53 @@ typedef void* PDXVAHDSW_Plugin;
 interface IDXVAHD_Device;
 
 cpp_quote("HRESULT WINAPI DXVAHD_CreateDevice(IDirect3DDevice9Ex *d3d_device, const DXVAHD_CONTENT_DESC *desc, DXVAHD_DEVICE_USAGE usage, PDXVAHDSW_Plugin plugin, IDXVAHD_Device **device);")
+
+/*****************************************************************************
+ * IDXVAHD_Device interface
+ */
+[
+    object,
+    uuid(95f12dfd-d77e-49be-815f-57d579634d6d),
+    local
+]
+interface IDXVAHD_Device : IUnknown
+{
+    HRESULT CreateVideoSurface(
+        [in] UINT width,
+        [in] UINT height,
+        [in] D3DFORMAT format,
+        [in] D3DPOOL pool,
+        [in] DWORD usage,
+        [in] DXVAHD_SURFACE_TYPE type,
+        [in] UINT num_surfaces,
+        [out] IDirect3DSurface9 **ppSurface,
+        [in, out] HANDLE *pSharedHandle);
+
+    HRESULT GetVideoProcessorDeviceCaps(
+        [out] DXVAHD_VPDEVCAPS *pCaps);
+
+    HRESULT GetVideoProcessorOutputFormats(
+        [in] UINT count,
+        [out] D3DFORMAT *pFormats);
+
+    HRESULT GetVideoProcessorInputFormats(
+        [in] UINT count,
+        [out] D3DFORMAT *pFormats);
+
+    HRESULT GetVideoProcessorCaps(
+        [in] UINT count,
+        [out] DXVAHD_VPCAPS *pCaps);
+
+    HRESULT GetVideoProcessorCustomRates(
+        [in] const GUID *pVPGuid,
+        [in] UINT count,
+        [out] DXVAHD_CUSTOM_RATE_DATA *pRates);
+
+    HRESULT GetVideoProcessorFilterRange(
+        [in] DXVAHD_FILTER filter,
+        [out] DXVAHD_FILTER_RANGE_DATA *pRange);
+
+    HRESULT CreateVideoProcessor(
+        [in] const GUID *pVPGuid,
+        [out] IDXVAHD_VideoProcessor **ppVideoProcessor);
+}
-- 
2.23.0




More information about the wine-devel mailing list