[PATCH v2 1/2] dxgi: Implement dxgi_output_ReleaseOwnership.

Zhiyi Zhang zzhang at codeweavers.com
Thu Oct 24 07:46:39 CDT 2019


Signed-off-by: Zhiyi Zhang <zzhang at codeweavers.com>
---
v2: Fix a typo. Supersede 171911~171912

 dlls/dxgi/dxgi_private.h       |  1 +
 dlls/dxgi/output.c             | 22 +++++++++---
 dlls/wined3d/directx.c         | 62 ++++++++++++++++++++++++++++++++++
 dlls/wined3d/wined3d.spec      |  3 ++
 dlls/wined3d/wined3d_private.h |  7 ++++
 include/wine/wined3d.h         |  4 +++
 6 files changed, 95 insertions(+), 4 deletions(-)

diff --git a/dlls/dxgi/dxgi_private.h b/dlls/dxgi/dxgi_private.h
index 5b93449834..6506b3a392 100644
--- a/dlls/dxgi/dxgi_private.h
+++ b/dlls/dxgi/dxgi_private.h
@@ -146,6 +146,7 @@ struct dxgi_output
     LONG refcount;
     struct wined3d_private_store private_store;
     struct dxgi_adapter *adapter;
+    struct wined3d_output *wined3d_output;
 };
 
 HRESULT dxgi_output_create(struct dxgi_adapter *adapter, struct dxgi_output **output) DECLSPEC_HIDDEN;
diff --git a/dlls/dxgi/output.c b/dlls/dxgi/output.c
index abe1aef950..1faf202e24 100644
--- a/dlls/dxgi/output.c
+++ b/dlls/dxgi/output.c
@@ -203,6 +203,7 @@ static ULONG STDMETHODCALLTYPE dxgi_output_Release(IDXGIOutput4 *iface)
 
     if (!refcount)
     {
+        wined3d_output_destroy(output->wined3d_output);
         wined3d_private_store_cleanup(&output->private_store);
         IWineDXGIAdapter_Release(&output->adapter->IWineDXGIAdapter_iface);
         heap_free(output);
@@ -342,7 +343,13 @@ static HRESULT STDMETHODCALLTYPE dxgi_output_TakeOwnership(IDXGIOutput4 *iface,
 
 static void STDMETHODCALLTYPE dxgi_output_ReleaseOwnership(IDXGIOutput4 *iface)
 {
-    FIXME("iface %p stub!\n", iface);
+    struct dxgi_output *output = impl_from_IDXGIOutput4(iface);
+
+    TRACE("iface %p.\n", iface);
+
+    wined3d_mutex_lock();
+    wined3d_output_release_ownership(output->wined3d_output);
+    wined3d_mutex_unlock();
 }
 
 static HRESULT STDMETHODCALLTYPE dxgi_output_GetGammaControlCapabilities(IDXGIOutput4 *iface,
@@ -530,13 +537,21 @@ struct dxgi_output *unsafe_impl_from_IDXGIOutput(IDXGIOutput *iface)
     return CONTAINING_RECORD(iface, struct dxgi_output, IDXGIOutput4_iface);
 }
 
-static void dxgi_output_init(struct dxgi_output *output, struct dxgi_adapter *adapter)
+static HRESULT dxgi_output_init(struct dxgi_output *output, struct dxgi_adapter *adapter)
 {
+    struct wined3d_output_desc wined3d_desc;
+
     output->IDXGIOutput4_iface.lpVtbl = &dxgi_output_vtbl;
     output->refcount = 1;
     wined3d_private_store_init(&output->private_store);
     output->adapter = adapter;
     IWineDXGIAdapter_AddRef(&output->adapter->IWineDXGIAdapter_iface);
+
+    wined3d_mutex_lock();
+    wined3d_get_output_desc(output->adapter->factory->wined3d, output->adapter->ordinal, &wined3d_desc);
+    wined3d_mutex_unlock();
+
+    return wined3d_output_create(wined3d_desc.device_name, &output->wined3d_output);
 }
 
 HRESULT dxgi_output_create(struct dxgi_adapter *adapter, struct dxgi_output **output)
@@ -544,6 +559,5 @@ HRESULT dxgi_output_create(struct dxgi_adapter *adapter, struct dxgi_output **ou
     if (!(*output = heap_alloc_zero(sizeof(**output))))
         return E_OUTOFMEMORY;
 
-    dxgi_output_init(*output, adapter);
-    return S_OK;
+    return dxgi_output_init(*output, adapter);
 }
diff --git a/dlls/wined3d/directx.c b/dlls/wined3d/directx.c
index 726b1e3775..03c8781386 100644
--- a/dlls/wined3d/directx.c
+++ b/dlls/wined3d/directx.c
@@ -827,6 +827,68 @@ HRESULT CDECL wined3d_get_output_desc(const struct wined3d *wined3d, unsigned in
     return WINED3D_OK;
 }
 
+HRESULT CDECL wined3d_output_create(const WCHAR *display_name, struct wined3d_output **target)
+{
+    D3DKMT_OPENADAPTERFROMGDIDISPLAYNAME open_adapter_desc;
+    D3DKMT_CREATEDEVICE create_device_desc = {0};
+    D3DKMT_DESTROYDEVICE destroy_device_desc;
+    D3DKMT_CLOSEADAPTER close_adapter_desc;
+    struct wined3d_output *output;
+
+    TRACE("display_name %s, target %p.\n", wine_dbgstr_w(display_name), target);
+
+    lstrcpyW(open_adapter_desc.DeviceName, display_name);
+    if (D3DKMTOpenAdapterFromGdiDisplayName(&open_adapter_desc))
+        return E_INVALIDARG;
+
+    create_device_desc.u.hAdapter = open_adapter_desc.hAdapter;
+    if (D3DKMTCreateDevice(&create_device_desc))
+    {
+        close_adapter_desc.hAdapter = open_adapter_desc.hAdapter;
+        D3DKMTCloseAdapter(&close_adapter_desc);
+        return E_FAIL;
+    }
+
+    if (!(output = heap_alloc(sizeof(*output))))
+    {
+        destroy_device_desc.hDevice = create_device_desc.hDevice;
+        D3DKMTDestroyDevice(&destroy_device_desc);
+        close_adapter_desc.hAdapter = open_adapter_desc.hAdapter;
+        D3DKMTCloseAdapter(&close_adapter_desc);
+        return E_OUTOFMEMORY;
+    }
+
+    output->kmt_adapter = open_adapter_desc.hAdapter;
+    output->kmt_device = create_device_desc.hDevice;
+    output->vidpn_source_id = open_adapter_desc.VidPnSourceId;
+    *target = output;
+    return WINED3D_OK;
+}
+
+void CDECL wined3d_output_destroy(struct wined3d_output *output)
+{
+    D3DKMT_CLOSEADAPTER close_adapter_desc;
+    D3DKMT_DESTROYDEVICE destroy_device_desc;
+
+    TRACE("output %p.\n",  output);
+
+    destroy_device_desc.hDevice = output->kmt_device;
+    D3DKMTDestroyDevice(&destroy_device_desc);
+    close_adapter_desc.hAdapter = output->kmt_adapter;
+    D3DKMTCloseAdapter(&close_adapter_desc);
+    heap_free(output);
+}
+
+void CDECL wined3d_output_release_ownership(const struct wined3d_output *output)
+{
+    D3DKMT_SETVIDPNSOURCEOWNER set_owner_desc = {0};
+
+    TRACE("output %p.\n", output);
+
+    set_owner_desc.hDevice = output->kmt_device;
+    D3DKMTSetVidPnSourceOwner(&set_owner_desc);
+}
+
 /* FIXME: GetAdapterModeCount and EnumAdapterModes currently only returns modes
      of the same bpp but different resolutions                                  */
 
diff --git a/dlls/wined3d/wined3d.spec b/dlls/wined3d/wined3d.spec
index 2df6c510b1..2e3a642813 100644
--- a/dlls/wined3d/wined3d.spec
+++ b/dlls/wined3d/wined3d.spec
@@ -19,6 +19,9 @@
 @ cdecl wined3d_get_device_caps(ptr long long ptr)
 @ cdecl wined3d_get_output_desc(ptr long ptr)
 @ cdecl wined3d_incref(ptr)
+@ cdecl wined3d_output_create(str ptr)
+@ cdecl wined3d_output_destroy(ptr)
+@ cdecl wined3d_output_release_ownership(ptr)
 @ cdecl wined3d_register_software_device(ptr ptr)
 @ cdecl wined3d_register_window(ptr ptr ptr long)
 @ cdecl wined3d_set_adapter_display_mode(ptr long ptr)
diff --git a/dlls/wined3d/wined3d_private.h b/dlls/wined3d/wined3d_private.h
index 307f7a42ad..de99b2a8d0 100644
--- a/dlls/wined3d/wined3d_private.h
+++ b/dlls/wined3d/wined3d_private.h
@@ -2952,6 +2952,13 @@ BOOL wined3d_caps_gl_ctx_test_viewport_subpixel_bits(struct wined3d_caps_gl_ctx
 
 void install_gl_compat_wrapper(struct wined3d_gl_info *gl_info, enum wined3d_gl_extension ext) DECLSPEC_HIDDEN;
 
+struct wined3d_output
+{
+    D3DKMT_HANDLE kmt_adapter;
+    D3DKMT_HANDLE kmt_device;
+    D3DDDI_VIDEO_PRESENT_SOURCE_ID vidpn_source_id;
+};
+
 enum wined3d_projection_type
 {
     WINED3D_PROJECTION_NONE    = 0,
diff --git a/include/wine/wined3d.h b/include/wine/wined3d.h
index 57f5775409..b75b544d11 100644
--- a/include/wine/wined3d.h
+++ b/include/wine/wined3d.h
@@ -2120,6 +2120,7 @@ struct wined3d_device;
 struct wined3d_palette;
 struct wined3d_query;
 struct wined3d_blend_state;
+struct wined3d_output;
 struct wined3d_rasterizer_state;
 struct wined3d_rendertarget_view;
 struct wined3d_resource;
@@ -2212,6 +2213,9 @@ HRESULT __cdecl wined3d_get_device_caps(const struct wined3d *wined3d, unsigned
 HRESULT __cdecl wined3d_get_output_desc(const struct wined3d *wined3d, unsigned int adapter_idx,
         struct wined3d_output_desc *desc);
 ULONG __cdecl wined3d_incref(struct wined3d *wined3d);
+HRESULT __cdecl wined3d_output_create(const WCHAR *display_name, struct wined3d_output **target);
+void __cdecl wined3d_output_destroy(struct wined3d_output *output);
+void __cdecl wined3d_output_release_ownership(const struct wined3d_output *output);
 HRESULT __cdecl wined3d_register_software_device(struct wined3d *wined3d, void *init_function);
 BOOL __cdecl wined3d_register_window(struct wined3d *wined3d, HWND window,
         struct wined3d_device *device, unsigned int flags);
-- 
2.23.0




More information about the wine-devel mailing list