From: Mohamad Al-Jaf mohamadaljaf@gmail.com
--- dlls/dxcore/Makefile.in | 3 +- dlls/dxcore/dxcore.c | 329 ++++++++++++++++++++++++++++++++++++- dlls/dxcore/tests/dxcore.c | 11 -- 3 files changed, 329 insertions(+), 14 deletions(-)
diff --git a/dlls/dxcore/Makefile.in b/dlls/dxcore/Makefile.in index 579cceded7e..fdeac08127f 100644 --- a/dlls/dxcore/Makefile.in +++ b/dlls/dxcore/Makefile.in @@ -1,4 +1,5 @@ -MODULE = dxcore.dll +MODULE = dxcore.dll +IMPORTS = dxgi
EXTRADLLFLAGS = -Wb,--prefer-native
diff --git a/dlls/dxcore/dxcore.c b/dlls/dxcore/dxcore.c index a07fe0c49e8..1dc984b57b8 100644 --- a/dlls/dxcore/dxcore.c +++ b/dlls/dxcore/dxcore.c @@ -21,11 +21,255 @@ #define COBJMACROS #include "initguid.h" #include "dxcore.h" +#include "dxgi1_6.h"
#include "wine/debug.h"
WINE_DEFAULT_DEBUG_CHANNEL(dxcore);
+struct dxcore_adapter +{ + IDXCoreAdapter IDXCoreAdapter_iface; + LONG ref; + + DXGI_ADAPTER_DESC3 desc; +}; + +static inline struct dxcore_adapter *impl_from_IDXCoreAdapter( IDXCoreAdapter *iface ) +{ + return CONTAINING_RECORD( iface, struct dxcore_adapter, IDXCoreAdapter_iface ); +} + +static HRESULT WINAPI dxcore_adapter_QueryInterface( IDXCoreAdapter *iface, REFIID iid, void **out ) +{ + struct dxcore_adapter *impl = impl_from_IDXCoreAdapter( iface ); + + TRACE( "iface %p, iid %s, out %p.\n", iface, debugstr_guid( iid ), out ); + + if (IsEqualGUID( iid, &IID_IUnknown ) || + IsEqualGUID( iid, &IID_IDXCoreAdapter )) + { + *out = &impl->IDXCoreAdapter_iface; + IUnknown_AddRef( (IUnknown *)*out ); + return S_OK; + } + + FIXME( "%s not implemented, returning E_NOINTERFACE.\n", debugstr_guid( iid ) ); + *out = NULL; + return E_NOINTERFACE; +} + +static ULONG WINAPI dxcore_adapter_AddRef( IDXCoreAdapter *iface ) +{ + struct dxcore_adapter *impl = impl_from_IDXCoreAdapter( iface ); + ULONG ref = InterlockedIncrement( &impl->ref ); + TRACE( "iface %p, ref %lu.\n", iface, ref ); + return ref; +} + +static ULONG WINAPI dxcore_adapter_Release( IDXCoreAdapter *iface ) +{ + struct dxcore_adapter *impl = impl_from_IDXCoreAdapter( iface ); + ULONG ref = InterlockedDecrement( &impl->ref ); + + TRACE( "iface %p, ref %lu.\n", iface, ref ); + + if (!ref) free( impl ); + return ref; +} + +static BOOL WINAPI dxcore_adapter_IsValid( IDXCoreAdapter *iface ) +{ + FIXME( "iface %p stub!\n", iface ); + return FALSE; +} + +static BOOL WINAPI dxcore_adapter_IsAttributeSupported( IDXCoreAdapter *iface, REFGUID attribute ) +{ + FIXME( "iface %p, attribute %s stub!\n", iface, debugstr_guid( attribute ) ); + return FALSE; +} + +static BOOL WINAPI dxcore_adapter_IsPropertySupported( IDXCoreAdapter *iface, DXCoreAdapterProperty property ) +{ + FIXME( "iface %p, property %u stub!\n", iface, property ); + return FALSE; +} + +static HRESULT WINAPI dxcore_adapter_GetProperty( IDXCoreAdapter *iface, DXCoreAdapterProperty property, size_t buffer_size, void *buffer ) +{ + FIXME( "iface %p, property %u, buffer_size %Iu, buffer %p stub!\n", iface, property, buffer_size, buffer ); + return E_NOTIMPL; +} + +static HRESULT WINAPI dxcore_adapter_GetPropertySize( IDXCoreAdapter *iface, DXCoreAdapterProperty property, size_t *buffer_size ) +{ + FIXME( "iface %p, property %u, buffer_size %p stub!\n", iface, property, buffer_size ); + return E_NOTIMPL; +} + +static BOOL WINAPI dxcore_adapter_IsQueryStateSupported( IDXCoreAdapter *iface, DXCoreAdapterState property ) +{ + FIXME( "iface %p, property %u stub!\n", iface, property ); + return FALSE; +} + +static HRESULT WINAPI dxcore_adapter_QueryState( IDXCoreAdapter *iface, DXCoreAdapterState state, size_t state_details_size, + const void *state_details, size_t buffer_size, void *buffer ) +{ + FIXME( "iface %p, state %u, state_details_size %Iu, state_details %p, buffer_size %Iu, buffer %p stub!\n", + iface, state, state_details_size, state_details, buffer_size, buffer ); + return E_NOTIMPL; +} + +static BOOL WINAPI dxcore_adapter_IsSetStateSupported( IDXCoreAdapter *iface, DXCoreAdapterState property ) +{ + FIXME( "iface %p, property %u stub!\n", iface, property ); + return FALSE; +} + +static HRESULT WINAPI dxcore_adapter_SetState( IDXCoreAdapter *iface, DXCoreAdapterState state, size_t state_details_size, + const void *state_details, size_t buffer_size, const void *buffer ) +{ + FIXME( "iface %p, state %u, state_details_size %Iu, state_details %p, buffer_size %Iu, buffer %p stub!\n", + iface, state, state_details_size, state_details, buffer_size, buffer ); + return E_NOTIMPL; +} + +static HRESULT WINAPI dxcore_adapter_GetFactory( IDXCoreAdapter *iface, REFIID riid, void **ppv ) +{ + FIXME( "iface %p, riid %s, ppv %p stub!\n", iface, debugstr_guid( riid ), ppv ); + return E_NOTIMPL; +} + +static const struct IDXCoreAdapterVtbl dxcore_adapter_vtbl = +{ + /* IUnknown methods */ + dxcore_adapter_QueryInterface, + dxcore_adapter_AddRef, + dxcore_adapter_Release, + /* IDXCoreAdapter methods */ + dxcore_adapter_IsValid, + dxcore_adapter_IsAttributeSupported, + dxcore_adapter_IsPropertySupported, + dxcore_adapter_GetProperty, + dxcore_adapter_GetPropertySize, + dxcore_adapter_IsQueryStateSupported, + dxcore_adapter_QueryState, + dxcore_adapter_IsSetStateSupported, + dxcore_adapter_SetState, + dxcore_adapter_GetFactory, +}; + +struct dxcore_adapter_list +{ + IDXCoreAdapterList IDXCoreAdapterList_iface; + LONG ref; + + struct dxcore_adapter **adapters; + uint32_t adapter_count; +}; + +static inline struct dxcore_adapter_list *impl_from_IDXCoreAdapterList( IDXCoreAdapterList *iface ) +{ + return CONTAINING_RECORD( iface, struct dxcore_adapter_list, IDXCoreAdapterList_iface ); +} + +static HRESULT WINAPI dxcore_adapter_list_QueryInterface( IDXCoreAdapterList *iface, REFIID iid, void **out ) +{ + struct dxcore_adapter_list *impl = impl_from_IDXCoreAdapterList( iface ); + + TRACE( "iface %p, iid %s, out %p.\n", iface, debugstr_guid( iid ), out ); + + if (IsEqualGUID( iid, &IID_IUnknown ) || + IsEqualGUID( iid, &IID_IDXCoreAdapterList )) + { + *out = &impl->IDXCoreAdapterList_iface; + IUnknown_AddRef( (IUnknown *)*out ); + return S_OK; + } + + FIXME( "%s not implemented, returning E_NOINTERFACE.\n", debugstr_guid( iid ) ); + *out = NULL; + return E_NOINTERFACE; +} + +static ULONG WINAPI dxcore_adapter_list_AddRef( IDXCoreAdapterList *iface ) +{ + struct dxcore_adapter_list *impl = impl_from_IDXCoreAdapterList( iface ); + ULONG ref = InterlockedIncrement( &impl->ref ); + TRACE( "iface %p, ref %lu.\n", iface, ref ); + return ref; +} + +static ULONG WINAPI dxcore_adapter_list_Release( IDXCoreAdapterList *iface ) +{ + struct dxcore_adapter_list *impl = impl_from_IDXCoreAdapterList( iface ); + ULONG ref = InterlockedDecrement( &impl->ref ); + + TRACE( "iface %p, ref %lu.\n", iface, ref ); + + if (!ref) + { + for (UINT i = 0; i < impl->adapter_count; i++) + if (impl->adapters[i]) IDXCoreAdapter_Release( &impl->adapters[i]->IDXCoreAdapter_iface ); + free( impl->adapters ); + free( impl ); + } + return ref; +} + +static HRESULT WINAPI dxcore_adapter_list_GetAdapter( IDXCoreAdapterList *iface, uint32_t index, REFIID riid, void **ppv ) +{ + FIXME( "iface %p, index %u, riid %s, ppv %p stub!\n", iface, index, debugstr_guid( riid ), ppv ); + return E_NOTIMPL; +} + +static uint32_t WINAPI dxcore_adapter_list_GetAdapterCount( IDXCoreAdapterList *iface ) +{ + FIXME( "iface %p stub!\n", iface ); + return 0; +} + +static BOOL WINAPI dxcore_adapter_list_IsStale( IDXCoreAdapterList *iface ) +{ + FIXME( "iface %p stub!\n", iface ); + return FALSE; +} + +static HRESULT WINAPI dxcore_adapter_list_GetFactory( IDXCoreAdapterList *iface, REFIID riid, void **ppv ) +{ + FIXME( "iface %p, riid %s, ppv %p stub!\n", iface, debugstr_guid( riid ), ppv ); + return E_NOTIMPL; +} + +static HRESULT WINAPI dxcore_adapter_list_Sort( IDXCoreAdapterList *iface, uint32_t num_preferences, const DXCoreAdapterPreference *preferences ) +{ + FIXME( "iface %p, num_preferences %u, preferences %p stub!\n", iface, num_preferences, preferences ); + return E_NOTIMPL; +} + +static BOOL WINAPI dxcore_adapter_list_IsAdapterPreferenceSupported( IDXCoreAdapterList *iface, DXCoreAdapterPreference preference ) +{ + FIXME( "iface %p, preference %u stub!\n", iface, preference ); + return FALSE; +} + +static const struct IDXCoreAdapterListVtbl dxcore_adapter_list_vtbl = +{ + /* IUnknown methods */ + dxcore_adapter_list_QueryInterface, + dxcore_adapter_list_AddRef, + dxcore_adapter_list_Release, + /* IDXCoreAdapterList methods */ + dxcore_adapter_list_GetAdapter, + dxcore_adapter_list_GetAdapterCount, + dxcore_adapter_list_IsStale, + dxcore_adapter_list_GetFactory, + dxcore_adapter_list_Sort, + dxcore_adapter_list_IsAdapterPreferenceSupported, +}; + struct dxcore_adapter_factory_statics { IDXCoreAdapterFactory IDXCoreAdapterFactory_iface; @@ -75,11 +319,92 @@ static ULONG WINAPI dxcore_adapter_factory_statics_Release( IDXCoreAdapterFactor return ref; }
+static HRESULT get_adapters( struct dxcore_adapter_list *impl ) +{ + IDXGIFactory6 *factory6 = NULL; + IDXGIAdapter4 *adapter4 = NULL; + HRESULT hr = CreateDXGIFactory2( 0, &IID_IDXGIFactory6, (void **)&factory6 ); + + if (FAILED(hr)) return hr; + + while (SUCCEEDED(IDXGIFactory6_EnumAdapterByGpuPreference( factory6, impl->adapter_count, DXGI_GPU_PREFERENCE_UNSPECIFIED, &IID_IDXGIAdapter4, (void **)&adapter4 ))) + { + impl->adapter_count++; + IDXGIAdapter4_Release( adapter4 ); + } + + if (!impl->adapter_count) + { + IDXGIFactory6_Release( factory6 ); + return S_OK; + } + + if (!(impl->adapters = calloc( impl->adapter_count, sizeof( *impl->adapters ) ))) + { + IDXGIFactory6_Release( factory6 ); + return E_OUTOFMEMORY; + } + + for (UINT i = 0; i < impl->adapter_count; i++) + { + struct dxcore_adapter *adapter = calloc( 1, sizeof( *adapter ) ); + DXGI_ADAPTER_DESC3 desc; + + if (!adapter) + { + hr = E_OUTOFMEMORY; + break; + } + if (FAILED(hr = IDXGIFactory6_EnumAdapterByGpuPreference( factory6, i, DXGI_GPU_PREFERENCE_UNSPECIFIED, &IID_IDXGIAdapter4, (void **)&adapter4 ))) + { + break; + } + if (FAILED(hr = IDXGIAdapter4_GetDesc3( adapter4, &desc ))) + { + IDXGIAdapter4_Release( adapter4 ); + break; + } + + adapter->IDXCoreAdapter_iface.lpVtbl = &dxcore_adapter_vtbl; + adapter->ref = 1; + adapter->desc = desc; + + impl->adapters[i] = adapter; + IDXGIAdapter4_Release( adapter4 ); + } + + IDXGIFactory6_Release( factory6 ); + return hr; +} + static HRESULT WINAPI dxcore_adapter_factory_statics_CreateAdapterList( IDXCoreAdapterFactory *iface, uint32_t num_attributes, const GUID *filter_attributes, REFIID riid, void **ppv ) { - FIXME( "iface %p, num_attributes %u, filter_attributes %p, riid %s, ppv %p stub!\n", iface, num_attributes, filter_attributes, debugstr_guid( riid ), ppv ); - return E_NOTIMPL; + struct dxcore_adapter_list *impl; + HRESULT hr; + + FIXME( "iface %p, num_attributes %u, filter_attributes %p, riid %s, ppv %p semi-stub!\n", iface, num_attributes, filter_attributes, debugstr_guid( riid ), ppv ); + + if (!ppv) return E_POINTER; + if (!num_attributes || !filter_attributes) + { + *ppv = NULL; + return E_INVALIDARG; + } + if (!(impl = calloc( 1, sizeof( *impl ) ))) return E_OUTOFMEMORY; + + impl->IDXCoreAdapterList_iface.lpVtbl = &dxcore_adapter_list_vtbl; + impl->ref = 1; + if (FAILED(hr = get_adapters( impl ))) + { + IDXCoreAdapterList_Release( &impl->IDXCoreAdapterList_iface ); + return hr; + } + + hr = IDXCoreAdapterList_QueryInterface( &impl->IDXCoreAdapterList_iface, riid, ppv ); + IDXCoreAdapterList_Release( &impl->IDXCoreAdapterList_iface ); + TRACE( "created IDXCoreAdapterList %p.\n", *ppv ); + return hr; }
static HRESULT WINAPI dxcore_adapter_factory_statics_GetAdapterByLuid( IDXCoreAdapterFactory *iface, REFLUID adapter_luid, REFIID riid, void **ppv ) diff --git a/dlls/dxcore/tests/dxcore.c b/dlls/dxcore/tests/dxcore.c index d809dcc8f34..796ce11fe00 100644 --- a/dlls/dxcore/tests/dxcore.c +++ b/dlls/dxcore/tests/dxcore.c @@ -75,30 +75,20 @@ static void test_DXCoreCreateAdapterFactory(void) check_interface( adapter_factory, &IID_IDXCoreAdapterList, FALSE );
hr = IDXCoreAdapterFactory_CreateAdapterList( adapter_factory, 0, &DXCORE_ADAPTER_ATTRIBUTE_D3D12_GRAPHICS, &IID_IDXCoreAdapterList, (void **)&adapter_list ); - todo_wine ok( hr == E_INVALIDARG, "got hr %#lx.\n", hr ); - todo_wine ok( adapter_list == NULL, "got adapter_list %p.\n", adapter_list ); hr = IDXCoreAdapterFactory_CreateAdapterList( adapter_factory, 1, &DXCORE_ADAPTER_ATTRIBUTE_D3D12_GRAPHICS, &IID_IDXCoreAdapterFactory, (void **)&adapter_list ); - todo_wine ok( hr == E_NOINTERFACE, "got hr %#lx.\n", hr ); hr = IDXCoreAdapterFactory_CreateAdapterList( adapter_factory, 1, NULL, &IID_IDXCoreAdapterFactory, (void **)&adapter_list ); - todo_wine ok( hr == E_INVALIDARG, "got hr %#lx.\n", hr ); hr = IDXCoreAdapterFactory_CreateAdapterList( adapter_factory, 1, &DXCORE_ADAPTER_ATTRIBUTE_D3D12_GRAPHICS, &IID_IDXCoreAdapterFactory, NULL ); - todo_wine ok( hr == E_POINTER, "got hr %#lx.\n", hr );
hr = IDXCoreAdapterFactory_CreateAdapterList( adapter_factory, 1, &DXCORE_ADAPTER_ATTRIBUTE_D3D12_GRAPHICS, &IID_IDXCoreAdapterList, (void **)&adapter_list ); - todo_wine ok( hr == S_OK, "got hr %#lx.\n", hr ); hr = IDXCoreAdapterFactory_CreateAdapterList( adapter_factory, 1, &DXCORE_ADAPTER_ATTRIBUTE_D3D12_GRAPHICS, &IID_IDXCoreAdapterList, (void **)&adapter_list2 ); - todo_wine ok( hr == S_OK, "got hr %#lx.\n", hr ); - todo_wine ok( adapter_list != adapter_list2, "got same adapter_list %p, adapter_list2 %p.\n", adapter_list, adapter_list ); - if (SUCCEEDED(hr)) - { ref = IDXCoreAdapterList_Release( adapter_list2 ); ok( ref == 0, "got ref %ld.\n", ref );
@@ -108,7 +98,6 @@ static void test_DXCoreCreateAdapterFactory(void)
ref = IDXCoreAdapterList_Release( adapter_list ); ok( ref == 0, "got ref %ld.\n", ref ); - } ref = IDXCoreAdapterFactory_Release( adapter_factory ); ok( ref == 0, "got ref %ld.\n", ref ); }