Signed-off-by: Zhiyi Zhang zzhang@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);