From e0e77d995edd90bdc3d67cd60cf870d6c4a68b18 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Michael=20M=C3=BCller?= <michael@fds-team.de>
Date: Sat, 21 Feb 2015 15:06:03 +0100
Subject: [PATCH] dxva2: Implement stubbed DirectX Software VideoProcessor
 interface.

---
 dlls/dxva2/Makefile.in         |   3 +-
 dlls/dxva2/dxva2_private.h     |   3 +
 dlls/dxva2/softwareprocessor.c | 209 +++++++++++++++++++++++++++++++++
 dlls/dxva2/videoservices.c     |  17 ++-
 4 files changed, 229 insertions(+), 3 deletions(-)
 create mode 100644 dlls/dxva2/softwareprocessor.c

diff --git a/dlls/dxva2/Makefile.in b/dlls/dxva2/Makefile.in
index c86b165e890..e4c90b5231e 100644
--- a/dlls/dxva2/Makefile.in
+++ b/dlls/dxva2/Makefile.in
@@ -6,4 +6,5 @@ EXTRADLLFLAGS = -mno-cygwin
 C_SRCS = \
 	devicemanager.c \
 	main.c \
-	videoservices.c
+	videoservices.c \
+	softwareprocessor.c
diff --git a/dlls/dxva2/dxva2_private.h b/dlls/dxva2/dxva2_private.h
index a88809cf7ec..f0068b68891 100644
--- a/dlls/dxva2/dxva2_private.h
+++ b/dlls/dxva2/dxva2_private.h
@@ -20,3 +20,6 @@
 
 extern HRESULT videoservice_create( IDirect3DDevice9 *device, REFIID riid, void **ppv ) DECLSPEC_HIDDEN;
 extern HRESULT devicemanager_create( UINT *resetToken, void **ppv ) DECLSPEC_HIDDEN;
+extern HRESULT processor_software_create( IDirectXVideoProcessorService *processor_service, IDirect3DDevice9 *device,
+                                          const DXVA2_VideoDesc *pVideoDesc, D3DFORMAT RenderTargetFormat,
+                                          UINT MaxNumSubStreams, IDirectXVideoProcessor **processor ) DECLSPEC_HIDDEN;
diff --git a/dlls/dxva2/softwareprocessor.c b/dlls/dxva2/softwareprocessor.c
new file mode 100644
index 00000000000..d3962484149
--- /dev/null
+++ b/dlls/dxva2/softwareprocessor.c
@@ -0,0 +1,209 @@
+/*
+ * Copyright 2015 Michael Müller for Pipelight
+ *
+ * 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
+ */
+
+#include <stdarg.h>
+#include "windef.h"
+#include "winbase.h"
+
+#include "wine/debug.h"
+
+#define COBJMACROS
+#include "d3d9.h"
+#include "dxva2api.h"
+#include "dxva2_private.h"
+
+WINE_DEFAULT_DEBUG_CHANNEL(dxva2);
+
+typedef struct
+{
+    IDirectXVideoProcessor IDirectXVideoProcessor_iface;
+    LONG refCount;
+
+    IDirectXVideoProcessorService *service;
+    IDirect3DDevice9 *device;
+} DirectXVideoProcessorImpl;
+
+static inline DirectXVideoProcessorImpl *impl_from_IDirectXVideoProcessor( IDirectXVideoProcessor *iface )
+{
+    return CONTAINING_RECORD(iface, DirectXVideoProcessorImpl, IDirectXVideoProcessor_iface);
+}
+
+static HRESULT WINAPI DirectXVideoProcessor_QueryInterface( IDirectXVideoProcessor *iface, REFIID riid, LPVOID *ppv )
+{
+    DirectXVideoProcessorImpl *This = impl_from_IDirectXVideoProcessor(iface);
+    TRACE("(%p/%p)->(%s, %p)\n", iface, This, debugstr_guid(riid), ppv);
+
+    *ppv = NULL;
+
+    if (IsEqualIID(riid, &IID_IUnknown) || IsEqualIID(riid, &IID_IDirectXVideoProcessor))
+        *ppv = (LPVOID)iface;
+
+    if (*ppv)
+    {
+        IUnknown_AddRef((IUnknown *)(*ppv));
+        return S_OK;
+    }
+
+    FIXME("No interface for %s\n", debugstr_guid(riid));
+    return E_NOINTERFACE;
+}
+
+static ULONG WINAPI DirectXVideoProcessor_AddRef( IDirectXVideoProcessor *iface )
+{
+    DirectXVideoProcessorImpl *This = impl_from_IDirectXVideoProcessor(iface);
+    ULONG refCount = InterlockedIncrement(&This->refCount);
+
+    TRACE("(%p)->() AddRef from %d\n", This, refCount - 1);
+
+    return refCount;
+}
+
+static ULONG WINAPI DirectXVideoProcessor_Release( IDirectXVideoProcessor *iface )
+{
+    DirectXVideoProcessorImpl *This = impl_from_IDirectXVideoProcessor(iface);
+    ULONG refCount = InterlockedDecrement(&This->refCount);
+
+    TRACE("(%p)->() Release from %d\n", This, refCount + 1);
+
+    if (!refCount)
+    {
+        TRACE("Destroying\n");
+
+        IDirectXVideoProcessorService_Release(This->service);
+        IDirect3DDevice9_Release(This->device);
+
+        CoTaskMemFree(This);
+    }
+
+    return refCount;
+}
+
+static HRESULT WINAPI DirectXVideoProcessor_GetVideoProcessorService(IDirectXVideoProcessor *iface,
+                                                                     IDirectXVideoProcessorService** ppService)
+{
+    DirectXVideoProcessorImpl *This = impl_from_IDirectXVideoProcessor(iface);
+
+    FIXME("(%p)->(%p): stub\n", This, ppService);
+
+    if (!ppService)
+        return E_INVALIDARG;
+
+    IDirectXVideoProcessorService_AddRef(This->service);
+    *ppService = This->service;
+
+    return S_OK;
+}
+
+static HRESULT WINAPI DirectXVideoProcessor_GetCreationParameters(IDirectXVideoProcessor *iface,
+                                                                  GUID* pDeviceGuid, DXVA2_VideoDesc* pVideoDesc,
+                                                                  D3DFORMAT* pRenderTargetFormat,
+                                                                  UINT* pMaxNumSubStreams)
+{
+    DirectXVideoProcessorImpl *This = impl_from_IDirectXVideoProcessor(iface);
+
+    FIXME("(%p)->(%p, %p, %p, %p): stub\n", This, pDeviceGuid, pVideoDesc, pRenderTargetFormat, pMaxNumSubStreams);
+
+    return E_NOTIMPL;
+}
+
+static HRESULT WINAPI DirectXVideoProcessor_GetVideoProcessorCaps(IDirectXVideoProcessor *iface,
+                                                                  DXVA2_VideoProcessorCaps* pCaps)
+{
+    DirectXVideoProcessorImpl *This = impl_from_IDirectXVideoProcessor(iface);
+
+    FIXME("(%p)->(%p): stub\n", This, pCaps);
+
+    return E_NOTIMPL;
+}
+
+static HRESULT WINAPI DirectXVideoProcessor_GetProcAmpRange(IDirectXVideoProcessor *iface, UINT ProcAmpCap,
+                                                            DXVA2_ValueRange* pRange)
+{
+    DirectXVideoProcessorImpl *This = impl_from_IDirectXVideoProcessor(iface);
+
+    FIXME("(%p)->(%u, %p): stub\n", This, ProcAmpCap, pRange);
+
+    return E_NOTIMPL;
+}
+
+static HRESULT WINAPI DirectXVideoProcessor_GetFilterPropertyRange(IDirectXVideoProcessor *iface,
+                                                                   UINT FilterSetting, DXVA2_ValueRange* pRange)
+{
+    DirectXVideoProcessorImpl *This = impl_from_IDirectXVideoProcessor(iface);
+
+    FIXME("(%p)->(%u, %p): stub\n", This, FilterSetting, pRange);
+
+    return E_NOTIMPL;
+}
+
+static HRESULT WINAPI DirectXVideoProcessor_VideoProcessBlt(IDirectXVideoProcessor *iface, IDirect3DSurface9* pRenderTarget,
+                                                            const DXVA2_VideoProcessBltParams* pBltParams,
+                                                            const DXVA2_VideoSample* pSamples, UINT NumSamples,
+                                                            HANDLE* complete)
+{
+    DirectXVideoProcessorImpl *This = impl_from_IDirectXVideoProcessor(iface);
+
+    TRACE("(%p)->(%p, %p, %p, %u, %p)\n", This, pRenderTarget, pBltParams, pSamples, NumSamples, complete);
+
+    if (!pRenderTarget || !pBltParams || !pSamples)
+        return E_INVALIDARG;
+
+    if (NumSamples > 1)
+        FIXME("Deinterlacing not implemented, expect horrible video output!\n");
+
+    return IDirect3DDevice9_StretchRect(This->device, pSamples[0].SrcSurface, &pSamples[0].SrcRect,
+                                        pRenderTarget, &pSamples[0].DstRect, D3DTEXF_LINEAR);
+}
+
+static const IDirectXVideoProcessorVtbl DirectXVideoProcessor_VTable =
+{
+    DirectXVideoProcessor_QueryInterface,
+    DirectXVideoProcessor_AddRef,
+    DirectXVideoProcessor_Release,
+    DirectXVideoProcessor_GetVideoProcessorService,
+    DirectXVideoProcessor_GetCreationParameters,
+    DirectXVideoProcessor_GetVideoProcessorCaps,
+    DirectXVideoProcessor_GetProcAmpRange,
+    DirectXVideoProcessor_GetFilterPropertyRange,
+    DirectXVideoProcessor_VideoProcessBlt
+};
+
+HRESULT processor_software_create( IDirectXVideoProcessorService *processor_service, IDirect3DDevice9 *device,
+                                   const DXVA2_VideoDesc *pVideoDesc, D3DFORMAT RenderTargetFormat,
+                                   UINT MaxNumSubStreams, IDirectXVideoProcessor **processor )
+{
+    DirectXVideoProcessorImpl *software_processor;
+
+    if (!processor_service || !pVideoDesc)
+        return E_INVALIDARG;
+
+    software_processor = CoTaskMemAlloc(sizeof(*software_processor));
+    if (!software_processor)
+        return E_OUTOFMEMORY;
+
+    software_processor->IDirectXVideoProcessor_iface.lpVtbl = &DirectXVideoProcessor_VTable;
+    software_processor->refCount = 1;
+    software_processor->service = processor_service;
+    software_processor->device = device;
+
+    IDirectXVideoProcessorService_AddRef(processor_service);
+    IDirect3DDevice9_AddRef(device);
+
+    *processor = &software_processor->IDirectXVideoProcessor_iface;
+    return S_OK;
+}
diff --git a/dlls/dxva2/videoservices.c b/dlls/dxva2/videoservices.c
index 936aa37b43c..46e431a7f29 100644
--- a/dlls/dxva2/videoservices.c
+++ b/dlls/dxva2/videoservices.c
@@ -341,10 +341,20 @@ static HRESULT WINAPI DirectXVideoProcessorService_GetVideoProcessorDeviceGuids(
                                                                                  const DXVA2_VideoDesc *pVideoDesc, UINT *pCount, GUID **pGuids )
 {
     DirectXVideoAccelerationServiceImpl *This = impl_from_IDirectXVideoProcessorService(iface);
+    GUID *guids;
 
     FIXME("(%p/%p)->(%p, %p, %p): stub\n", iface, This, pVideoDesc, pCount, pGuids);
 
-    return E_NOTIMPL;
+    guids = CoTaskMemAlloc(sizeof(GUID));
+    if(!guids)
+        return E_OUTOFMEMORY;
+
+    memcpy(guids, &DXVA2_VideoProcSoftwareDevice, sizeof(GUID));
+
+    *pGuids = guids;
+    *pCount = 1;
+
+    return S_OK;
 }
 
 static HRESULT WINAPI DirectXVideoProcessorService_GetVideoProcessorRenderTargets( IDirectXVideoProcessorService *iface,
@@ -407,9 +417,12 @@ static HRESULT WINAPI DirectXVideoProcessorService_CreateVideoProcessor( IDirect
 {
     DirectXVideoAccelerationServiceImpl *This = impl_from_IDirectXVideoProcessorService(iface);
 
-    FIXME("(%p/%p)->(%s, %#x, %u, %p): stub\n",
+    FIXME("(%p/%p)->(%s, %#x, %u, %p): semi-stub\n",
         iface, This, debugstr_guid(VideoProcDeviceGuid), RenderTargetFormat, MaxNumSubStreams, ppVidProcess);
 
+    if (IsEqualIID(VideoProcDeviceGuid, &DXVA2_VideoProcSoftwareDevice))
+        return processor_software_create(iface, This->device, pVideoDesc, RenderTargetFormat, MaxNumSubStreams, ppVidProcess);
+
     return E_NOTIMPL;
 }
 
-- 
2.17.1

