From 846276f3caf5325297eeeb722c592c5311b86bba Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9mi=20Bernon?= Date: Tue, 26 Jan 2021 12:14:25 +0100 Subject: [PATCH] d3d11: Add initial implementation of CreateDeviceContextState. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: RĂ©mi Bernon Signed-off-by: Henri Verbeet Signed-off-by: Alexandre Julliard --- dlls/d3d11/d3d11_private.h | 12 ++++ dlls/d3d11/device.c | 142 ++++++++++++++++++++++++++++++++++++- dlls/d3d11/tests/d3d11.c | 74 +++++++++++++------ 3 files changed, 206 insertions(+), 22 deletions(-) diff --git a/dlls/d3d11/d3d11_private.h b/dlls/d3d11/d3d11_private.h index 3248285fcda..77078a07545 100644 --- a/dlls/d3d11/d3d11_private.h +++ b/dlls/d3d11/d3d11_private.h @@ -516,6 +516,18 @@ struct d3d_query *unsafe_impl_from_ID3D11Query(ID3D11Query *iface) DECLSPEC_HIDD struct d3d_query *unsafe_impl_from_ID3D10Query(ID3D10Query *iface) DECLSPEC_HIDDEN; struct d3d_query *unsafe_impl_from_ID3D11Asynchronous(ID3D11Asynchronous *iface) DECLSPEC_HIDDEN; +/* ID3DDeviceContextState */ +struct d3d_device_context_state +{ + ID3DDeviceContextState ID3DDeviceContextState_iface; + LONG refcount; + + struct wined3d_private_store private_store; + + GUID emulated_interface; + ID3D11Device2 *device; +}; + /* ID3D11DeviceContext - immediate context */ struct d3d11_immediate_context { diff --git a/dlls/d3d11/device.c b/dlls/d3d11/device.c index 50e8cd58fe2..e870399a83e 100644 --- a/dlls/d3d11/device.c +++ b/dlls/d3d11/device.c @@ -29,6 +29,127 @@ static const struct wined3d_parent_ops d3d_null_wined3d_parent_ops = d3d_null_wined3d_object_destroyed, }; +/* ID3DDeviceContextState methods */ + +static inline struct d3d_device_context_state *impl_from_ID3DDeviceContextState(ID3DDeviceContextState *iface) +{ + return CONTAINING_RECORD(iface, struct d3d_device_context_state, ID3DDeviceContextState_iface); +} + +static HRESULT STDMETHODCALLTYPE d3d_device_context_state_QueryInterface(ID3DDeviceContextState *iface, + REFIID iid, void **out) +{ + TRACE("iface %p, iid %s, out %p.\n", iface, debugstr_guid(iid), out); + + if (IsEqualGUID(iid, &IID_ID3DDeviceContextState) + || IsEqualGUID(iid, &IID_ID3D11DeviceChild) + || IsEqualGUID(iid, &IID_IUnknown)) + { + ID3DDeviceContextState_AddRef(iface); + *out = iface; + return S_OK; + } + + WARN("%s not implemented, returning E_NOINTERFACE.\n", debugstr_guid(iid)); + *out = NULL; + + return E_NOINTERFACE; +} + +static ULONG STDMETHODCALLTYPE d3d_device_context_state_AddRef(ID3DDeviceContextState *iface) +{ + struct d3d_device_context_state *state = impl_from_ID3DDeviceContextState(iface); + ULONG refcount = InterlockedIncrement(&state->refcount); + + TRACE("%p increasing refcount to %u.\n", state, refcount); + + return refcount; +} + +static ULONG STDMETHODCALLTYPE d3d_device_context_state_Release(ID3DDeviceContextState *iface) +{ + struct d3d_device_context_state *state = impl_from_ID3DDeviceContextState(iface); + ULONG refcount = InterlockedDecrement(&state->refcount); + + TRACE("%p decreasing refcount to %u.\n", state, refcount); + + if (!refcount) + { + wined3d_private_store_cleanup(&state->private_store); + ID3D11Device2_Release(state->device); + heap_free(state); + } + + return refcount; +} + +static void STDMETHODCALLTYPE d3d_device_context_state_GetDevice(ID3DDeviceContextState *iface, ID3D11Device **device) +{ + struct d3d_device_context_state *state = impl_from_ID3DDeviceContextState(iface); + + TRACE("iface %p, device %p.\n", iface, device); + + *device = (ID3D11Device *)state->device; + ID3D11Device_AddRef(*device); +} + +static HRESULT STDMETHODCALLTYPE d3d_device_context_state_GetPrivateData(ID3DDeviceContextState *iface, REFGUID guid, + UINT *data_size, void *data) +{ + struct d3d_device_context_state *state = impl_from_ID3DDeviceContextState(iface); + + TRACE("iface %p, guid %s, data_size %p, data %p.\n", iface, debugstr_guid(guid), data_size, data); + + return d3d_get_private_data(&state->private_store, guid, data_size, data); +} + +static HRESULT STDMETHODCALLTYPE d3d_device_context_state_SetPrivateData(ID3DDeviceContextState *iface, REFGUID guid, + UINT data_size, const void *data) +{ + struct d3d_device_context_state *state = impl_from_ID3DDeviceContextState(iface); + + TRACE("iface %p, guid %s, data_size %u, data %p.\n", iface, debugstr_guid(guid), data_size, data); + + return d3d_set_private_data(&state->private_store, guid, data_size, data); +} + +static HRESULT STDMETHODCALLTYPE d3d_device_context_state_SetPrivateDataInterface(ID3DDeviceContextState *iface, + REFGUID guid, const IUnknown *data) +{ + struct d3d_device_context_state *state = impl_from_ID3DDeviceContextState(iface); + + TRACE("iface %p, guid %s, data %p.\n", iface, debugstr_guid(guid), data); + + return d3d_set_private_data_interface(&state->private_store, guid, data); +} + +static const struct ID3DDeviceContextStateVtbl d3d_device_context_state_vtbl = +{ + /* IUnknown methods */ + d3d_device_context_state_QueryInterface, + d3d_device_context_state_AddRef, + d3d_device_context_state_Release, + /* ID3D11DeviceChild methods */ + d3d_device_context_state_GetDevice, + d3d_device_context_state_GetPrivateData, + d3d_device_context_state_SetPrivateData, + d3d_device_context_state_SetPrivateDataInterface, + /* ID3DDeviceContextState methods */ +}; + +static void d3d_device_context_state_init(struct d3d_device_context_state *state, struct d3d_device *device, + REFIID emulated_interface) +{ + state->ID3DDeviceContextState_iface.lpVtbl = &d3d_device_context_state_vtbl; + state->refcount = 1; + + wined3d_private_store_init(&state->private_store); + + state->emulated_interface = *emulated_interface; + state->device = &device->ID3D11Device2_iface; + ID3D11Device2_AddRef(state->device); +} + /* ID3D11DeviceContext - immediate context methods */ static inline struct d3d11_immediate_context *impl_from_ID3D11DeviceContext1(ID3D11DeviceContext1 *iface) @@ -3738,11 +3859,28 @@ static HRESULT STDMETHODCALLTYPE d3d11_device_CreateDeviceContextState(ID3D11Dev const D3D_FEATURE_LEVEL *feature_levels, UINT feature_levels_count, UINT sdk_version, REFIID emulated_interface, D3D_FEATURE_LEVEL *chosen_feature_level, ID3DDeviceContextState **state) { + struct d3d_device *device = impl_from_ID3D11Device2(iface); + struct d3d_device_context_state *state_impl; + FIXME("iface %p, flags %#x, feature_levels %p, feature_level_count %u, sdk_version %u, " - "emulated_interface %s, chosen_feature_level %p, state %p stub!\n", iface, flags, feature_levels, + "emulated_interface %s, chosen_feature_level %p, state %p semi-stub!\n", iface, flags, feature_levels, feature_levels_count, sdk_version, debugstr_guid(emulated_interface), chosen_feature_level, state); - return E_NOTIMPL; + if (chosen_feature_level) + FIXME("Device context state feature level not implemented yet.\n"); + + if (state) + { + *state = NULL; + if (!(state_impl = heap_alloc(sizeof(*state_impl)))) + return E_OUTOFMEMORY; + d3d_device_context_state_init(state_impl, device, emulated_interface); + *state = &state_impl->ID3DDeviceContextState_iface; + } + + device->d3d11_only = FALSE; + if (chosen_feature_level) *chosen_feature_level = ID3D11Device2_GetFeatureLevel(iface); + return state ? S_OK : S_FALSE; } static HRESULT STDMETHODCALLTYPE d3d11_device_OpenSharedResource1(ID3D11Device2 *iface, HANDLE handle, diff --git a/dlls/d3d11/tests/d3d11.c b/dlls/d3d11/tests/d3d11.c index 9fc09a5ec83..fde7a11766d 100644 --- a/dlls/d3d11/tests/d3d11.c +++ b/dlls/d3d11/tests/d3d11.c @@ -6683,10 +6683,9 @@ static void test_device_context_state(void) ok(tmp_sampler == sampler, "Got sampler %p, expected %p.\n", tmp_sampler, sampler); ID3D11SamplerState_Release(tmp_sampler); - feature_level = min(feature_level, D3D_FEATURE_LEVEL_10_1); + feature_level = min(feature_level, D3D_FEATURE_LEVEL_11_1); hr = ID3D11Device1_CreateDeviceContextState(device, 0, &feature_level, 1, D3D11_SDK_VERSION, - &IID_ID3D10Device, NULL, &context_state); -todo_wine + &IID_ID3D11Device1, NULL, &context_state); ok(SUCCEEDED(hr), "Failed to create device context state, hr %#x.\n", hr); if (FAILED(hr)) { @@ -6700,6 +6699,24 @@ todo_wine context_type = ID3D11DeviceContext1_GetType(context); ok(context_type == D3D11_DEVICE_CONTEXT_IMMEDIATE, "Unexpected context type %u.\n", context_type); + check_interface(device, &IID_ID3D10Device, TRUE, FALSE); + check_interface(device, &IID_ID3D10Device1, TRUE, FALSE); + check_interface(device, &IID_ID3D11Device, TRUE, FALSE); + check_interface(device, &IID_ID3D11Device1, TRUE, FALSE); + + refcount = ID3DDeviceContextState_Release(context_state); + ok(!refcount, "Got refcount %u, expected 0.\n", refcount); + + feature_level = min(feature_level, D3D_FEATURE_LEVEL_10_1); + hr = ID3D11Device1_CreateDeviceContextState(device, 0, &feature_level, 1, D3D11_SDK_VERSION, + &IID_ID3D10Device, NULL, &context_state); + ok(SUCCEEDED(hr), "Failed to create device context state, hr %#x.\n", hr); + refcount = get_refcount(context_state); + ok(refcount == 1, "Got refcount %u, expected 1.\n", refcount); + + context_type = ID3D11DeviceContext1_GetType(context); + ok(context_type == D3D11_DEVICE_CONTEXT_IMMEDIATE, "Unexpected context type %u.\n", context_type); + cb = create_buffer((ID3D11Device *)device, D3D11_BIND_CONSTANT_BUFFER, sizeof(constant), NULL); ID3D11DeviceContext1_CSSetConstantBuffers(context, 0, 1, &cb); @@ -6743,73 +6760,90 @@ todo_wine ID3D11DeviceContext1_SwapDeviceContextState(context, context_state, &previous_context_state); refcount = ID3DDeviceContextState_Release(context_state); ok(!refcount, "Got refcount %u, expected 0.\n", refcount); + todo_wine ok(previous_context_state != NULL, "Failed to get previous context state\n"); + + context_type = ID3D11DeviceContext1_GetType(context); + ok(context_type == D3D11_DEVICE_CONTEXT_IMMEDIATE, "Unexpected context type %u.\n", context_type); ID3D11DeviceContext1_PSSetSamplers(context, 0, 1, &sampler); tmp_sampler = (ID3D11SamplerState *)0xdeadbeef; ID3D11DeviceContext1_PSGetSamplers(context, 0, 1, &tmp_sampler); - ok(tmp_sampler == (ID3D11SamplerState *)0xdeadbeef, "Got unexpected sampler %p.\n", tmp_sampler); + todo_wine ok(tmp_sampler == (ID3D11SamplerState *)0xdeadbeef, "Got unexpected sampler %p.\n", tmp_sampler); + if (tmp_sampler && tmp_sampler != (ID3D11SamplerState *)0xdeadbeef) + ID3D11SamplerState_Release(tmp_sampler); if (!enable_debug_layer) ID3D11DeviceContext1_PSSetSamplers(context, 0, 1, &tmp_sampler); ID3D11DeviceContext1_CSSetSamplers(context, 0, 1, &sampler); tmp_sampler = (ID3D11SamplerState *)0xdeadbeef; ID3D11DeviceContext1_CSGetSamplers(context, 0, 1, &tmp_sampler); - ok(!tmp_sampler, "Got unexpected sampler %p.\n", tmp_sampler); + todo_wine ok(!tmp_sampler, "Got unexpected sampler %p.\n", tmp_sampler); + if (tmp_sampler) ID3D11SamplerState_Release(tmp_sampler); ID3D11DeviceContext1_DSSetSamplers(context, 0, 1, &sampler); tmp_sampler = (ID3D11SamplerState *)0xdeadbeef; ID3D11DeviceContext1_DSGetSamplers(context, 0, 1, &tmp_sampler); - ok(!tmp_sampler, "Got unexpected sampler %p.\n", tmp_sampler); + todo_wine ok(!tmp_sampler, "Got unexpected sampler %p.\n", tmp_sampler); + if (tmp_sampler) ID3D11SamplerState_Release(tmp_sampler); ID3D11DeviceContext1_GSSetSamplers(context, 0, 1, &sampler); tmp_sampler = (ID3D11SamplerState *)0xdeadbeef; ID3D11DeviceContext1_GSGetSamplers(context, 0, 1, &tmp_sampler); - ok(!tmp_sampler, "Got unexpected sampler %p.\n", tmp_sampler); + todo_wine ok(!tmp_sampler, "Got unexpected sampler %p.\n", tmp_sampler); + if (tmp_sampler) ID3D11SamplerState_Release(tmp_sampler); ID3D11DeviceContext1_HSSetSamplers(context, 0, 1, &sampler); tmp_sampler = (ID3D11SamplerState *)0xdeadbeef; ID3D11DeviceContext1_HSGetSamplers(context, 0, 1, &tmp_sampler); - ok(!tmp_sampler, "Got unexpected sampler %p.\n", tmp_sampler); + todo_wine ok(!tmp_sampler, "Got unexpected sampler %p.\n", tmp_sampler); + if (tmp_sampler) ID3D11SamplerState_Release(tmp_sampler); ID3D11DeviceContext1_VSSetSamplers(context, 0, 1, &sampler); tmp_sampler = (ID3D11SamplerState *)0xdeadbeef; ID3D11DeviceContext1_VSGetSamplers(context, 0, 1, &tmp_sampler); - ok(!tmp_sampler, "Got unexpected sampler %p.\n", tmp_sampler); - - context_type = ID3D11DeviceContext1_GetType(context); - ok(context_type == D3D11_DEVICE_CONTEXT_IMMEDIATE, "Unexpected context type %u.\n", context_type); + todo_wine ok(!tmp_sampler, "Got unexpected sampler %p.\n", tmp_sampler); + if (tmp_sampler) ID3D11SamplerState_Release(tmp_sampler); tmp_cb = (ID3D11Buffer *)0xdeadbeef; ID3D11DeviceContext1_CSGetConstantBuffers(context, 0, 1, &tmp_cb); - ok(!tmp_cb, "Got unexpected buffer %p.\n", tmp_cb); + todo_wine ok(!tmp_cb, "Got unexpected buffer %p.\n", tmp_cb); + if (tmp_cb) ID3D11Buffer_Release(tmp_cb); tmp_cb = (ID3D11Buffer *)0xdeadbeef; ID3D11DeviceContext1_PSGetConstantBuffers(context, 0, 1, &tmp_cb); - ok(!tmp_cb, "Got unexpected buffer %p.\n", tmp_cb); + todo_wine ok(!tmp_cb, "Got unexpected buffer %p.\n", tmp_cb); + if (tmp_cb) ID3D11Buffer_Release(tmp_cb); tmp_cb = (ID3D11Buffer *)0xdeadbeef; ID3D11DeviceContext1_VSGetConstantBuffers(context, 0, 1, &tmp_cb); - ok(!tmp_cb, "Got unexpected buffer %p.\n", tmp_cb); + todo_wine ok(!tmp_cb, "Got unexpected buffer %p.\n", tmp_cb); + if (tmp_cb) ID3D11Buffer_Release(tmp_cb); tmp_cb = (ID3D11Buffer *)0xdeadbeef; ID3D11DeviceContext1_DSGetConstantBuffers(context, 0, 1, &tmp_cb); - ok(!tmp_cb, "Got unexpected buffer %p.\n", tmp_cb); + todo_wine ok(!tmp_cb, "Got unexpected buffer %p.\n", tmp_cb); + if (tmp_cb) ID3D11Buffer_Release(tmp_cb); tmp_cb = (ID3D11Buffer *)0xdeadbeef; ID3D11DeviceContext1_GSGetConstantBuffers(context, 0, 1, &tmp_cb); - ok(!tmp_cb, "Got unexpected buffer %p.\n", tmp_cb); + todo_wine ok(!tmp_cb, "Got unexpected buffer %p.\n", tmp_cb); + if (tmp_cb) ID3D11Buffer_Release(tmp_cb); tmp_cb = (ID3D11Buffer *)0xdeadbeef; ID3D11DeviceContext1_HSGetConstantBuffers(context, 0, 1, &tmp_cb); - ok(!tmp_cb, "Got unexpected buffer %p.\n", tmp_cb); + todo_wine ok(!tmp_cb, "Got unexpected buffer %p.\n", tmp_cb); + if (tmp_cb) ID3D11Buffer_Release(tmp_cb); check_interface(device, &IID_ID3D10Device, TRUE, FALSE); check_interface(device, &IID_ID3D10Device1, TRUE, FALSE); + context_state = NULL; ID3D11DeviceContext1_SwapDeviceContextState(context, previous_context_state, &context_state); - refcount = ID3DDeviceContextState_Release(context_state); + if (!context_state) refcount = 0; + else refcount = ID3DDeviceContextState_Release(context_state); ok(!refcount, "Got refcount %u, expected 0.\n", refcount); - refcount = ID3DDeviceContextState_Release(previous_context_state); + if (!previous_context_state) refcount = 0; + else refcount = ID3DDeviceContextState_Release(previous_context_state); ok(!refcount, "Got refcount %u, expected 0.\n", refcount); /* ID3DDeviceContextState retains the previous state. */