From: Mohamad Al-Jaf mohamadaljaf@gmail.com
Needed by Orbiter Space Flight Simulator and Train Simulator Classic. --- dlls/d3d9/d3d9.spec | 1 + dlls/d3d9/d3d9_main.c | 22 +++++++ dlls/d3d9/d3d9_private.h | 6 ++ dlls/d3d9/device.c | 123 +++++++++++++++++++++++++++++++++++++++ 4 files changed, 152 insertions(+)
diff --git a/dlls/d3d9/d3d9.spec b/dlls/d3d9/d3d9.spec index a33cba51e77..11ad26b64c6 100644 --- a/dlls/d3d9/d3d9.spec +++ b/dlls/d3d9/d3d9.spec @@ -12,3 +12,4 @@ @ stdcall DebugSetMute() @ stdcall Direct3DCreate9(long) @ stdcall Direct3DCreate9Ex(long ptr) +@ stdcall Direct3DCreate9On12(long ptr long) diff --git a/dlls/d3d9/d3d9_main.c b/dlls/d3d9/d3d9_main.c index 5bdf05409aa..c393ca738ea 100644 --- a/dlls/d3d9/d3d9_main.c +++ b/dlls/d3d9/d3d9_main.c @@ -75,6 +75,28 @@ HRESULT WINAPI DECLSPEC_HOTPATCH Direct3DCreate9Ex(UINT sdk_version, IDirect3D9E return D3D_OK; }
+IDirect3D9 * WINAPI DECLSPEC_HOTPATCH Direct3DCreate9On12(UINT sdk_version, D3D9ON12_ARGS *d3d9on12_args, UINT override_entries) +{ + struct d3d9 *object; + + TRACE("sdk_version %#x, d3d9on12_args %p, override_entries %#x.\n", sdk_version, d3d9on12_args, override_entries); + + if (!(object = calloc(1, sizeof(*object)))) + return NULL; + + if (!d3d9_init(object, TRUE)) + { + WARN("Failed to initialize d3d9.\n"); + free(object); + return NULL; + } + + d3d9on12_init(object, d3d9on12_args, override_entries); + + TRACE("Created d3d9 object %p.\n", object); + return (IDirect3D9 *)&object->IDirect3D9Ex_iface; +} + /* The callback is called on any error encountered during validation, including * improper IDirect3DShaderValidator9 method calls. * - "file" and "line" are passed through directly from Instruction(). "line" diff --git a/dlls/d3d9/d3d9_private.h b/dlls/d3d9/d3d9_private.h index a5f059c5aef..279c2bfbea6 100644 --- a/dlls/d3d9/d3d9_private.h +++ b/dlls/d3d9/d3d9_private.h @@ -34,6 +34,7 @@ #include "wine/debug.h"
#include "d3d9.h" +#include "d3d9on12.h" #include "wine/wined3d.h"
#define D3D9_MAX_VERTEX_SHADER_CONSTANTF 256 @@ -65,11 +66,15 @@ struct d3d9 struct wined3d_output **wined3d_outputs; unsigned int wined3d_output_count; BOOL extended; + BOOL d3d9on12; + struct D3D9ON12_ARGS *d3d9on12_args; + UINT override_entries; };
void d3d9_caps_from_wined3dcaps(const struct d3d9 *d3d9, unsigned int adapter_ordinal, D3DCAPS9 *caps, const struct wined3d_caps *wined3d_caps); BOOL d3d9_init(struct d3d9 *d3d9, BOOL extended); +void d3d9on12_init(struct d3d9 *d3d9, D3D9ON12_ARGS *d3d9on12_args, UINT override_entries);
struct fvf_declaration { @@ -87,6 +92,7 @@ enum d3d9_device_state struct d3d9_device { IDirect3DDevice9Ex IDirect3DDevice9Ex_iface; + IDirect3DDevice9On12 IDirect3DDevice9On12_iface; struct wined3d_device_parent device_parent; LONG refcount; struct wined3d_device *wined3d_device; diff --git a/dlls/d3d9/device.c b/dlls/d3d9/device.c index 408dace48ad..86415509467 100644 --- a/dlls/d3d9/device.c +++ b/dlls/d3d9/device.c @@ -593,6 +593,111 @@ static void device_reset_viewport_state(struct d3d9_device *device) wined3d_stateblock_set_scissor_rect(device->state, &rect); }
+static inline struct d3d9_device *impl_from_IDirect3DDevice9On12( IDirect3DDevice9On12 *iface ) +{ + return CONTAINING_RECORD( iface, struct d3d9_device, IDirect3DDevice9On12_iface ); +} + +static HRESULT WINAPI d3d9on12_QueryInterface( IDirect3DDevice9On12 *iface, REFIID iid, void **out ) +{ + struct d3d9_device *device = impl_from_IDirect3DDevice9On12(iface); + + TRACE( "iface %p, iid %s, out %p.\n", iface, debugstr_guid(iid), out ); + + if (IsEqualGUID( iid, &IID_IUnknown ) || + IsEqualGUID( iid, &IID_IDirect3DDevice9On12 )) + { + IDirect3DDevice9On12_AddRef( &device->IDirect3DDevice9On12_iface ); + *out = &device->IDirect3DDevice9On12_iface; + return S_OK; + } + + WARN( "%s not implemented, returning E_NOINTERFACE.\n", debugstr_guid(iid) ); + + *out = NULL; + return E_NOINTERFACE; +} + +static ULONG WINAPI d3d9on12_AddRef( IDirect3DDevice9On12 *iface ) +{ + struct d3d9_device *device = impl_from_IDirect3DDevice9On12(iface); + ULONG refcount = InterlockedIncrement(&device->refcount); + TRACE( "%p increasing refcount to %lu.\n", iface, refcount ); + return refcount; +} + +static ULONG WINAPI d3d9on12_Release( IDirect3DDevice9On12 *iface ) +{ + struct d3d9_device *device = impl_from_IDirect3DDevice9On12(iface); + ULONG refcount = InterlockedDecrement(&device->refcount); + + TRACE( "%p decreasing refcount to %lu.\n", iface, refcount ); + + if (!refcount) + { + if (device->d3d_parent->d3d9on12_args) + { + if (device->d3d_parent->d3d9on12_args->pD3D12Device) + ID3D12Device_Release( (ID3D12Device *)device->d3d_parent->d3d9on12_args->pD3D12Device ); + + for ( int i = 0; i < device->d3d_parent->d3d9on12_args->NumQueues; i++ ) + { + if (device->d3d_parent->d3d9on12_args->ppD3D12Queues[i]) + ID3D12CommandQueue_Release( (ID3D12CommandQueue *)device->d3d_parent->d3d9on12_args->ppD3D12Queues[i] ); + } + + free( device->d3d_parent->d3d9on12_args ); + } + } + + return refcount; +} + +static HRESULT WINAPI d3d9on12_GetD3D12Device( IDirect3DDevice9On12 *iface, REFIID iid, void **out ) +{ + FIXME( "iface %p, iid %s, out %p stub!\n", iface, debugstr_guid(iid), out ); + + if (!out) return E_INVALIDARG; + + *out = NULL; + return E_NOINTERFACE; +} + +static HRESULT WINAPI d3d9on12_UnwrapUnderlyingResource( IDirect3DDevice9On12 *iface, IDirect3DResource9 *resource, ID3D12CommandQueue *queue, REFIID iid, void **out ) +{ + FIXME( "iface %p, resource %p, queue %p, iid %s, out %p stub!\n", iface, resource, queue, debugstr_guid(iid), out ); + return E_NOTIMPL; +} + +static HRESULT WINAPI d3d9on12_ReturnUnderlyingResource( IDirect3DDevice9On12 *iface, IDirect3DResource9 *resource, UINT num_sync, UINT64 *signal_values, ID3D12Fence **fences ) +{ + FIXME( "iface %p, resource %p, num_sync %#x, signal_values %p, fences %p stub!\n", iface, resource, num_sync, signal_values, fences ); + return E_NOTIMPL; +} + +static const struct IDirect3DDevice9On12Vtbl d3d9on12_vtbl = +{ + /* IUnknown */ + d3d9on12_QueryInterface, + d3d9on12_AddRef, + d3d9on12_Release, + /* IDirect3DDevice9On12 */ + d3d9on12_GetD3D12Device, + d3d9on12_UnwrapUnderlyingResource, + d3d9on12_ReturnUnderlyingResource, +}; + +void d3d9on12_init( struct d3d9 *d3d9, D3D9ON12_ARGS *d3d9on12_args, UINT override_entries ) +{ + if (!override_entries || !d3d9on12_args || !d3d9on12_args->Enable9On12) return; + + FIXME( "ignoring d3d9on12_args %p\n", d3d9on12_args ); + + d3d9->d3d9on12 = TRUE; + d3d9->d3d9on12_args = NULL; + d3d9->override_entries = override_entries; +} + static HRESULT WINAPI d3d9_device_QueryInterface(IDirect3DDevice9Ex *iface, REFIID riid, void **out) { TRACE("iface %p, riid %s, out %p.\n", iface, debugstr_guid(riid), out); @@ -623,6 +728,24 @@ static HRESULT WINAPI d3d9_device_QueryInterface(IDirect3DDevice9Ex *iface, REFI return S_OK; }
+ if (IsEqualGUID(riid, &IID_IDirect3DDevice9On12)) + { + struct d3d9_device *device = impl_from_IDirect3DDevice9Ex(iface); + + if (!device->d3d_parent->d3d9on12) + { + WARN("IDirect3D9 instance wasn't created with D3D9On12 enabled, returning E_NOINTERFACE.\n"); + *out = NULL; + return E_NOINTERFACE; + } + + FIXME("pD3D12Device value is not being checked if it matches the d3d9 device\n"); + + device->IDirect3DDevice9On12_iface.lpVtbl = &d3d9on12_vtbl; + IDirect3DDevice9On12_QueryInterface(&device->IDirect3DDevice9On12_iface, riid, out); + return S_OK; + } + WARN("%s not implemented, returning E_NOINTERFACE.\n", debugstr_guid(riid));
*out = NULL;