diff --git a/dlls/dxgi/device.c b/dlls/dxgi/device.c index 195c502d61..fddc535a5a 100644 --- a/dlls/dxgi/device.c +++ b/dlls/dxgi/device.c @@ -28,6 +28,8 @@ WINE_DEFAULT_DEBUG_CHANNEL(dxgi); static HRESULT STDMETHODCALLTYPE dxgi_device_QueryInterface(IDXGIDevice *iface, REFIID riid, void **object) { + struct dxgi_device *This = (struct dxgi_device *)iface; + TRACE("iface %p, riid %s, object %p\n", iface, debugstr_guid(riid), object); if (IsEqualGUID(riid, &IID_IUnknown) @@ -39,6 +41,12 @@ static HRESULT STDMETHODCALLTYPE dxgi_device_QueryInterface(IDXGIDevice *iface, return S_OK; } + if (This->child_layer) + { + TRACE("forwarding to child layer %p\n", This->child_layer); + return IUnknown_QueryInterface(This->child_layer, riid, object); + } + WARN("%s not implemented, returning E_NOINTERFACE\n", debugstr_guid(riid)); *object = NULL; @@ -64,6 +72,7 @@ static ULONG STDMETHODCALLTYPE dxgi_device_Release(IDXGIDevice *iface) if (!refcount) { + if (This->child_layer) IUnknown_Release(This->child_layer); HeapFree(GetProcessHeap(), 0, This); } diff --git a/dlls/dxgi/dxgi.spec b/dlls/dxgi/dxgi.spec index 974b830a22..d7f8aba61d 100644 --- a/dlls/dxgi/dxgi.spec +++ b/dlls/dxgi/dxgi.spec @@ -1,2 +1,3 @@ @ stdcall CreateDXGIFactory(ptr ptr) +@ stdcall DXGID3D10CreateDevice(ptr ptr ptr long long ptr) @ stdcall DXGID3D10RegisterLayers(ptr long) diff --git a/dlls/dxgi/dxgi_main.c b/dlls/dxgi/dxgi_main.c index 507eb04c87..d2de584aa6 100644 --- a/dlls/dxgi/dxgi_main.c +++ b/dlls/dxgi/dxgi_main.c @@ -36,6 +36,7 @@ static CRITICAL_SECTION dxgi_cs = {&dxgi_cs_debug, -1, 0, 0, 0, 0}; struct dxgi_main { + HMODULE d3d10core; struct dxgi_device_layer *device_layers; UINT layer_count; LONG refcount; @@ -50,6 +51,9 @@ static void dxgi_main_cleanup(void) dxgi_main.device_layers = NULL; dxgi_main.layer_count = 0; + FreeLibrary(dxgi_main.d3d10core); + dxgi_main.d3d10core = NULL; + LeaveCriticalSection(&dxgi_cs); } @@ -97,6 +101,135 @@ HRESULT WINAPI CreateDXGIFactory(REFIID riid, void **factory) return hr; } +static BOOL get_layer(enum dxgi_device_layer_id id, struct dxgi_device_layer *layer) +{ + UINT i; + + EnterCriticalSection(&dxgi_cs); + + for (i = 0; i < dxgi_main.layer_count; ++i) + { + if (dxgi_main.device_layers[i].id == id) + { + *layer = dxgi_main.device_layers[i]; + LeaveCriticalSection(&dxgi_cs); + return TRUE; + } + } + + LeaveCriticalSection(&dxgi_cs); + return FALSE; +} + +static HRESULT register_d3d10core_layers(HMODULE d3d10core) +{ + EnterCriticalSection(&dxgi_cs); + + if (!dxgi_main.d3d10core) + { + HRESULT hr; + HRESULT (WINAPI *d3d10core_register_layers)(void); + HMODULE mod; + BOOL ret; + + ret = GetModuleHandleExA(GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS, (LPCSTR)d3d10core, &mod); + if (!ret) + { + LeaveCriticalSection(&dxgi_cs); + return E_FAIL; + } + + d3d10core_register_layers = (HRESULT (WINAPI *)(void))GetProcAddress(mod, "D3D10CoreRegisterLayers"); + hr = d3d10core_register_layers(); + if (FAILED(hr)) + { + ERR("Failed to register d3d10core layers, returning %#x\n", hr); + LeaveCriticalSection(&dxgi_cs); + return hr; + } + + dxgi_main.d3d10core = mod; + } + + LeaveCriticalSection(&dxgi_cs); + + return S_OK; +} + +HRESULT WINAPI DXGID3D10CreateDevice(HMODULE d3d10core, IDXGIFactory *factory, IDXGIAdapter *adapter, + UINT flags, DWORD unknown0, void **device) +{ + struct layer_get_size_args get_size_args; + struct dxgi_device *dxgi_device; + struct dxgi_device_layer d3d10_layer; + void *layer_base; + UINT device_size; + DWORD count; + HRESULT hr; + + TRACE("d3d10core %p, factory %p, adapter %p, flags %#x, unknown0 %#x, device %p\n", + d3d10core, factory, adapter, flags, unknown0, device); + + hr = register_d3d10core_layers(d3d10core); + if (FAILED(hr)) + { + ERR("Failed to register d3d10core layers, returning %#x\n", hr); + return hr; + } + + if (!get_layer(DXGI_DEVICE_LAYER_D3D10_DEVICE, &d3d10_layer)) + { + ERR("Failed to get D3D10 device layer\n"); + return E_FAIL; + } + + count = 0; + hr = d3d10_layer.init(d3d10_layer.id, &count, NULL); + if (FAILED(hr)) + { + WARN("Failed to initialize D3D10 device layer\n"); + return E_FAIL; + } + + get_size_args.unknown0 = 0; + get_size_args.unknown1 = 0; + get_size_args.unknown2 = NULL; + get_size_args.unknown3 = NULL; + get_size_args.adapter = adapter; + get_size_args.interface_major = 10; + get_size_args.interface_minor = 1; + get_size_args.version_build = 4; + get_size_args.version_revision = 6000; + + device_size = d3d10_layer.get_size(d3d10_layer.id, &get_size_args, 0); + device_size += sizeof(*dxgi_device); + + dxgi_device = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, device_size); + if (!dxgi_device) + { + ERR("Failed to allocate device memory\n"); + return E_OUTOFMEMORY; + } + + dxgi_device->vtbl = &dxgi_device_vtbl; + dxgi_device->refcount = 1; + layer_base = dxgi_device + 1; + + hr = d3d10_layer.create(d3d10_layer.id, &layer_base, 0, + dxgi_device, &IID_IUnknown, (void **)&dxgi_device->child_layer); + if (FAILED(hr)) + { + WARN("Failed to create device, returning %#x\n", hr); + HeapFree(GetProcessHeap(), 0, dxgi_device); + *device = NULL; + return hr; + } + + *device = (IUnknown *)dxgi_device; + + return hr; +} + HRESULT WINAPI DXGID3D10RegisterLayers(const struct dxgi_device_layer *layers, UINT layer_count) { UINT i; diff --git a/dlls/dxgi/dxgi_private.h b/dlls/dxgi/dxgi_private.h index 051cd87b23..27d7271195 100644 --- a/dlls/dxgi/dxgi_private.h +++ b/dlls/dxgi/dxgi_private.h @@ -44,6 +44,7 @@ extern const struct IDXGIDeviceVtbl dxgi_device_vtbl; struct dxgi_device { const struct IDXGIDeviceVtbl *vtbl; + IUnknown *child_layer; LONG refcount; };