From dab5f521ad21f95aeedde39f0625541fe39d8bdf Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Michael=20M=C3=BCller?= <michael@fds-team.de>
Date: Fri, 7 Jul 2017 23:56:16 +0200
Subject: [PATCH] nvapi: Implement NvAPI_D3D11_SetDepthBoundsTest. (v2)

---
 dlls/d3d11/device.c      | 11 +++++++++++
 dlls/nvapi/nvapi.c       | 29 +++++++++++++++++++++++++++++
 dlls/nvapi/tests/nvapi.c | 17 +++++++++++++++++
 include/wine/wined3d.h   |  2 ++
 4 files changed, 59 insertions(+)

diff --git a/dlls/d3d11/device.c b/dlls/d3d11/device.c
index 751afc1..ad91cdb 100644
--- a/dlls/d3d11/device.c
+++ b/dlls/d3d11/device.c
@@ -49,6 +49,7 @@ static HRESULT STDMETHODCALLTYPE d3d11_immediate_context_QueryInterface(ID3D11De
         REFIID iid, void **out)
 {
     struct d3d11_immediate_context *context = impl_from_ID3D11DeviceContext1(iface);
+    struct d3d_device *device = device_from_immediate_ID3D11DeviceContext1( (ID3D11DeviceContext1*)iface);
 
     TRACE("iface %p, iid %s, out %p.\n", iface, debugstr_guid(iid), out);
 
@@ -63,6 +64,11 @@ static HRESULT STDMETHODCALLTYPE d3d11_immediate_context_QueryInterface(ID3D11De
     {
         *out = &context->ID3D11Multithread_iface;
     }
+    else if (IsEqualGUID(iid, &IID_IWineD3DDevice))
+    {
+        *out = device->wined3d_device;
+        return S_OK;
+    }
     else
     {
         WARN("%s not implemented, returning E_NOINTERFACE.\n", debugstr_guid(iid));
@@ -3942,6 +3948,11 @@ static HRESULT STDMETHODCALLTYPE d3d_device_inner_QueryInterface(IUnknown *iface
     {
         *out = &device->IWineDXGIDeviceParent_iface;
     }
+    else if (IsEqualGUID(riid, &IID_IWineD3DDevice))
+    {
+        *out = device->wined3d_device;
+        return S_OK;
+    }
     else
     {
         WARN("%s not implemented, returning E_NOINTERFACE.\n", debugstr_guid(riid));
diff --git a/dlls/nvapi/nvapi.c b/dlls/nvapi/nvapi.c
index b67b414..ad8266b 100644
--- a/dlls/nvapi/nvapi.c
+++ b/dlls/nvapi/nvapi.c
@@ -23,6 +23,7 @@
 #include <stdarg.h>
 
 #define COBJMACROS
+#include "initguid.h"
 #include "windef.h"
 #include "winbase.h"
 #include "winternl.h"
@@ -682,6 +683,33 @@ static NvAPI_Status CDECL NvAPI_GPU_GetGpuCoreCount(NvPhysicalGpuHandle hPhysica
     return NVAPI_OK;
 }
 
+static NvAPI_Status CDECL NvAPI_D3D11_SetDepthBoundsTest(IUnknown *pDeviceOrContext, NvU32 bEnable, float fMinDepth, float fMaxDepth)
+{
+    struct wined3d_device *device;
+    union { DWORD d; float f; } z;
+
+    TRACE("(%p, %u, %f, %f)\n", pDeviceOrContext, bEnable, fMinDepth, fMaxDepth);
+
+    if (!pDeviceOrContext)
+        return NVAPI_INVALID_ARGUMENT;
+
+    if (FAILED(IUnknown_QueryInterface(pDeviceOrContext, &IID_IWineD3DDevice, (void **)&device)))
+    {
+        ERR("Failed to get wined3d device handle!\n");
+        return NVAPI_ERROR;
+    }
+
+    wined3d_mutex_lock();
+    wined3d_device_set_render_state(device, WINED3D_RS_ADAPTIVETESS_X, bEnable ? WINED3DFMT_NVDB : 0);
+    z.f = fMinDepth;
+    wined3d_device_set_render_state(device, WINED3D_RS_ADAPTIVETESS_Z, z.d);
+    z.f = fMaxDepth;
+    wined3d_device_set_render_state(device, WINED3D_RS_ADAPTIVETESS_W, z.d);
+    wined3d_mutex_unlock();
+
+    return NVAPI_OK;
+}
+
 void* CDECL nvapi_QueryInterface(unsigned int offset)
 {
     static const struct
@@ -727,6 +755,7 @@ void* CDECL nvapi_QueryInterface(unsigned int offset)
         {0x46fbeb03, NvAPI_GPU_GetPhysicalFrameBufferSize},
         {0x5a04b644, NvAPI_GPU_GetVirtualFrameBufferSize},
         {0xc7026a87, NvAPI_GPU_GetGpuCoreCount},
+        {0x7aaf7a04, NvAPI_D3D11_SetDepthBoundsTest},
     };
     unsigned int i;
     TRACE("(%x)\n", offset);
diff --git a/dlls/nvapi/tests/nvapi.c b/dlls/nvapi/tests/nvapi.c
index c8b66ac..87327c0 100644
--- a/dlls/nvapi/tests/nvapi.c
+++ b/dlls/nvapi/tests/nvapi.c
@@ -45,6 +45,7 @@ static NvAPI_Status (CDECL* pNvAPI_EnumNvidiaDisplayHandle)(NvU32 thisEnum, NvDi
 static NvAPI_Status (CDECL* pNvAPI_SYS_GetDriverAndBranchVersion)(NvU32* pDriverVersion, NvAPI_ShortString szBuildBranchString);
 static NvAPI_Status (CDECL* pNvAPI_D3D_GetCurrentSLIState)(IUnknown *pDevice, NV_GET_CURRENT_SLI_STATE *pSliState);
 static NvAPI_Status (CDECL* pNvAPI_GetLogicalGPUFromDisplay)(NvDisplayHandle hNvDisp, NvLogicalGpuHandle *pLogicalGPU);
+static NvAPI_Status (CDECL* pNvAPI_D3D11_SetDepthBoundsTest)(IUnknown*, NvU32, float, float);
 
 static const struct
 {
@@ -68,6 +69,7 @@ function_list[] =
     {0x2926aaad, (void**) &pNvAPI_SYS_GetDriverAndBranchVersion},
     {0x4b708b54, (void**) &pNvAPI_D3D_GetCurrentSLIState},
     {0xee1370cf, (void**) &pNvAPI_GetLogicalGPUFromDisplay},
+    {0x7aaf7a04, (void**) &pNvAPI_D3D11_SetDepthBoundsTest},
 };
 
 static BOOL init(void)
@@ -705,6 +707,20 @@ cleanup:
     if (window) DestroyWindow(window);
 }
 
+static void test_NvAPI_D3D11_SetDepthBoundsTest(void)
+{
+    NvAPI_Status status;
+
+    if (!pNvAPI_D3D11_SetDepthBoundsTest)
+    {
+        win_skip("NvAPI_D3D11_SetDepthBoundsTest export not found.\n");
+        return;
+    }
+
+    status = pNvAPI_D3D11_SetDepthBoundsTest(NULL, 0, 0.0, 0.0);
+    ok(status == NVAPI_INVALID_ARGUMENT, "Expected status NVAPI_INVALID_ARGUMENT, got %d\n", status);
+}
+
 START_TEST( nvapi )
 {
     WNDCLASSA wc = {0};
@@ -724,6 +740,7 @@ START_TEST( nvapi )
     test_NvAPI_EnumNvidiaDisplayHandle();
     test_NvAPI_SYS_GetDriverAndBranchVersion();
     test_NvAPI_GetLogicalGPUFromDisplay();
+    test_NvAPI_D3D11_SetDepthBoundsTest();
 
     /* d3d9 tests */
     wc.lpfnWndProc = DefWindowProcA;
diff --git a/include/wine/wined3d.h b/include/wine/wined3d.h
index 958ade1..4828f9c 100644
--- a/include/wine/wined3d.h
+++ b/include/wine/wined3d.h
@@ -32,6 +32,8 @@
 
 #include "wine/list.h"
 
+DEFINE_GUID(IID_IWineD3DDevice, 0xd56e2a4c, 0x5127, 0x8437, 0x65, 0x8a, 0x98, 0xc5, 0xbb, 0x78, 0x94, 0x98);
+
 #define WINED3D_OK                                              S_OK
 
 #define _FACWINED3D                                             0x876
-- 
1.9.1

