Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=38086 Signed-off-by: Alistair Leslie-Hughes leslie_alistair@hotmail.com --- dlls/d3dx9_36/shader.c | 232 +++++++++++++++++++++++++++++++++-- dlls/d3dx9_36/tests/shader.c | 100 +++++++++++++++ 2 files changed, 324 insertions(+), 8 deletions(-)
diff --git a/dlls/d3dx9_36/shader.c b/dlls/d3dx9_36/shader.c index c59fc791ea..8284d50ec1 100644 --- a/dlls/d3dx9_36/shader.c +++ b/dlls/d3dx9_36/shader.c @@ -2069,27 +2069,243 @@ HRESULT WINAPI D3DXGetShaderConstantTable(const DWORD *byte_code, ID3DXConstantT return D3DXGetShaderConstantTableEx(byte_code, 0, constant_table); }
-HRESULT WINAPI D3DXCreateFragmentLinker(IDirect3DDevice9 *device, UINT size, ID3DXFragmentLinker **linker) +struct d3dx9_fragment_linker +{ + ID3DXFragmentLinker ID3DXFragmentLinker_iface; + LONG ref; + + struct IDirect3DDevice9 *device; + DWORD flags; +}; + +static inline struct d3dx9_fragment_linker *impl_from_ID3DXFragmentLinker(ID3DXFragmentLinker *iface) +{ + return CONTAINING_RECORD(iface, struct d3dx9_fragment_linker, ID3DXFragmentLinker_iface); +} + +static HRESULT WINAPI d3dx9_fragment_linker_QueryInterface(ID3DXFragmentLinker *iface, REFIID riid, void **out) +{ + TRACE("iface %p, riid %s, out %p.\n", iface, debugstr_guid(riid), out); + + if (IsEqualGUID(riid, &IID_IUnknown) || + IsEqualGUID(riid, &IID_ID3DXFragmentLinker)) + { + iface->lpVtbl->AddRef(iface); + *out = iface; + return D3D_OK; + } + + WARN("%s not implemented, returning E_NOINTERFACE.\n", debugstr_guid(riid)); + *out = NULL; + return E_NOINTERFACE; +} + +static ULONG WINAPI d3dx9_fragment_linker_AddRef(ID3DXFragmentLinker *iface) +{ + struct d3dx9_fragment_linker *fragment = impl_from_ID3DXFragmentLinker(iface); + ULONG refcount = InterlockedIncrement(&fragment->ref); + + TRACE("%p increasing refcount to %u.\n", fragment, refcount); + + return refcount; +} + +static ULONG WINAPI d3dx9_fragment_linker_Release(ID3DXFragmentLinker *iface) +{ + struct d3dx9_fragment_linker *fragment = impl_from_ID3DXFragmentLinker(iface); + ULONG refcount = InterlockedDecrement(&fragment->ref); + + TRACE("%p decreasing refcount to %u.\n", fragment, refcount); + + if (!refcount) + { + IDirect3DDevice9_Release(fragment->device); + heap_free(fragment); + } + + return refcount; +} + +static HRESULT WINAPI d3dx9_fragment_linker_GetDevice(ID3DXFragmentLinker *iface, struct IDirect3DDevice9 **device) { - FIXME("device %p, size %u, linker %p: stub.\n", device, size, linker); + struct d3dx9_fragment_linker *fragment = impl_from_ID3DXFragmentLinker(iface); + + TRACE("iface %p, device %p.\n", fragment, device); + + if (!device) + { + WARN("Invalid argument supplied.\n"); + return D3DERR_INVALIDCALL; + } + + IDirect3DDevice9_AddRef(fragment->device); + + *device = fragment->device; + + TRACE("Returning device %p.\n", *device);
- if (linker) - *linker = NULL; + return S_OK; +} + +static UINT WINAPI d3dx9_fragment_linker_GetNumberOfFragments(ID3DXFragmentLinker *iface) +{ + struct d3dx9_fragment_linker *fragment = impl_from_ID3DXFragmentLinker(iface);
+ FIXME("iface %p: stub.\n", fragment);
return E_NOTIMPL; }
-HRESULT WINAPI D3DXCreateFragmentLinkerEx(IDirect3DDevice9 *device, UINT size, DWORD flags, ID3DXFragmentLinker **linker) +static D3DXHANDLE WINAPI d3dx9_fragment_linker_GetFragmentHandleByIndex(ID3DXFragmentLinker *iface, UINT index) +{ + struct d3dx9_fragment_linker *fragment = impl_from_ID3DXFragmentLinker(iface); + + FIXME("iface %p, index %u: stub.\n", fragment, index); + + return NULL; +} + +static D3DXHANDLE WINAPI d3dx9_fragment_linker_GetFragmentHandleByName(ID3DXFragmentLinker *iface, + const char *name) +{ + struct d3dx9_fragment_linker *fragment = impl_from_ID3DXFragmentLinker(iface); + + FIXME("iface %p, name %s: stub.\n", fragment, debugstr_a(name)); + + return NULL; +} + +static HRESULT WINAPI d3dx9_fragment_linker_GetFragmentDesc(ID3DXFragmentLinker *iface, D3DXHANDLE name, + D3DXFRAGMENT_DESC *frag_desc) +{ + struct d3dx9_fragment_linker *fragment = impl_from_ID3DXFragmentLinker(iface); + + FIXME("iface %p, name %p, frag_desc %p: stub.\n", fragment, name, frag_desc); + + return E_NOTIMPL; +} + +static HRESULT WINAPI d3dx9_fragment_linker_AddFragments(ID3DXFragmentLinker *iface, const DWORD *fragments) +{ + struct d3dx9_fragment_linker *fragment = impl_from_ID3DXFragmentLinker(iface); + + FIXME("iface %p, fragments %p: stub.\n", fragment, fragments); + + return E_NOTIMPL; +} + +static HRESULT WINAPI d3dx9_fragment_linker_GetAllFragments(ID3DXFragmentLinker *iface, ID3DXBuffer **buffer) +{ + struct d3dx9_fragment_linker *fragment = impl_from_ID3DXFragmentLinker(iface); + + FIXME("iface %p, buffer %p: stub.\n", fragment, buffer); + + return E_NOTIMPL; +} + +static HRESULT WINAPI d3dx9_fragment_linker_GetFragment(ID3DXFragmentLinker *iface, D3DXHANDLE name, + ID3DXBuffer **buffer) +{ + struct d3dx9_fragment_linker *fragment = impl_from_ID3DXFragmentLinker(iface); + + FIXME("iface %p, name %p, buffer %p: stub.\n", fragment, name, buffer); + + return E_NOTIMPL; +} + +static HRESULT WINAPI d3dx9_fragment_linker_LinkShader(ID3DXFragmentLinker *iface, const char *profile, + DWORD flags, const D3DXHANDLE *fragmenthandles, UINT fragments, ID3DXBuffer **buffer, + ID3DXBuffer **errors) +{ + struct d3dx9_fragment_linker *fragment = impl_from_ID3DXFragmentLinker(iface); + + FIXME("iface %p, profile %s, flags 0x%x, fragmenthandles %p,fragments %u, buffer %p, errors %p: stub.\n", + fragment, debugstr_a(profile), flags, fragmenthandles, fragments, buffer, errors); + + return E_NOTIMPL; +} + +static HRESULT WINAPI d3dx9_fragment_linker_LinkVertexShader(ID3DXFragmentLinker *iface, const char *profile, + DWORD flags, const D3DXHANDLE *fragmenthandles, UINT fragments, IDirect3DVertexShader9 **shader, + ID3DXBuffer **errors) +{ + struct d3dx9_fragment_linker *fragment = impl_from_ID3DXFragmentLinker(iface); + + FIXME("iface %p, profile %s, flags 0x%x, fragmenthandles %p,fragments %u, shader %p, errors %p: stub.\n", + fragment, debugstr_a(profile), flags, fragmenthandles, fragments, shader, errors); + + return E_NOTIMPL; +} + +static HRESULT WINAPI d3dx9_fragment_linker_LinkPixelShader(ID3DXFragmentLinker *iface, const char *profile, + DWORD flags, const D3DXHANDLE *fragmenthandles, UINT fragments, IDirect3DPixelShader9 **shader, + ID3DXBuffer **errors) +{ + struct d3dx9_fragment_linker *fragment = impl_from_ID3DXFragmentLinker(iface); + + FIXME("iface %p, profile %s, flags 0x%x, fragmenthandles %p,fragments %u, shader %p, errors %p: stub.\n", + fragment, debugstr_a(profile), flags, fragmenthandles, fragments, shader, errors); + + return E_NOTIMPL; +} + +static HRESULT WINAPI d3dx9_fragment_linker_ClearCache(ID3DXFragmentLinker *iface) { - FIXME("device %p, size %u, flags %#x, linker %p: stub.\n", device, size, flags, linker); + struct d3dx9_fragment_linker *fragment = impl_from_ID3DXFragmentLinker(iface);
- if (linker) - *linker = NULL; + FIXME("iface %p): stub.\n", fragment);
return E_NOTIMPL; }
+static const struct ID3DXFragmentLinkerVtbl d3dx9_fragment_linker_vtbl = +{ + d3dx9_fragment_linker_QueryInterface, + d3dx9_fragment_linker_AddRef, + d3dx9_fragment_linker_Release, + d3dx9_fragment_linker_GetDevice, + d3dx9_fragment_linker_GetNumberOfFragments, + d3dx9_fragment_linker_GetFragmentHandleByIndex, + d3dx9_fragment_linker_GetFragmentHandleByName, + d3dx9_fragment_linker_GetFragmentDesc, + d3dx9_fragment_linker_AddFragments, + d3dx9_fragment_linker_GetAllFragments, + d3dx9_fragment_linker_GetFragment, + d3dx9_fragment_linker_LinkShader, + d3dx9_fragment_linker_LinkVertexShader, + d3dx9_fragment_linker_LinkPixelShader, + d3dx9_fragment_linker_ClearCache +}; + +HRESULT WINAPI D3DXCreateFragmentLinkerEx(IDirect3DDevice9 *device, UINT size, DWORD flags, ID3DXFragmentLinker **linker) +{ + struct d3dx9_fragment_linker *object; + + TRACE("device %p, size %u, flags %#x, linker %p.\n", device, size, flags, linker); + + object = heap_alloc(sizeof(*object)); + if (!object) + return E_OUTOFMEMORY; + + object->ID3DXFragmentLinker_iface.lpVtbl = &d3dx9_fragment_linker_vtbl; + object->ref = 1; + + IDirect3DDevice9_AddRef(device); + object->device = device; + object->flags = flags; + + *linker = &object->ID3DXFragmentLinker_iface; + + return S_OK; +} + +HRESULT WINAPI D3DXCreateFragmentLinker(IDirect3DDevice9 *device, UINT size, ID3DXFragmentLinker **linker) +{ + TRACE("device %p, size %u, linker %p.\n", device, size, linker); + + return D3DXCreateFragmentLinkerEx(device, size, 0, linker); +} + HRESULT WINAPI D3DXGetShaderSamplers(const DWORD *byte_code, const char **samplers, UINT *count) { UINT i, sampler_count = 0; diff --git a/dlls/d3dx9_36/tests/shader.c b/dlls/d3dx9_36/tests/shader.c index e6326bc411..7fb8de7e65 100644 --- a/dlls/d3dx9_36/tests/shader.c +++ b/dlls/d3dx9_36/tests/shader.c @@ -6575,6 +6575,104 @@ static void test_shader_semantics(void) } }
+static void test_fragment_linker(void) +{ + HWND wnd; + IDirect3D9 *d3d; + IDirect3DDevice9 *device; + D3DPRESENT_PARAMETERS d3dpp; + HRESULT hr; + ULONG count; + ID3DXFragmentLinker *linker; + + if (!(wnd = CreateWindowA("static", "d3dx9_test", WS_OVERLAPPEDWINDOW, 0, 0, + 640, 480, NULL, NULL, NULL, NULL))) + { + skip("Couldn't create application window\n"); + return; + } + if (!(d3d = Direct3DCreate9(D3D_SDK_VERSION))) + { + skip("Couldn't create IDirect3D9 object\n"); + DestroyWindow(wnd); + return; + } + + ZeroMemory(&d3dpp, sizeof(d3dpp)); + d3dpp.Windowed = TRUE; + d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD; + hr = IDirect3D9_CreateDevice(d3d, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, wnd, D3DCREATE_MIXED_VERTEXPROCESSING, &d3dpp, &device); + if (FAILED(hr)) + { + skip("Failed to create IDirect3DDevice9 object %#x\n", hr); + IDirect3D9_Release(d3d); + DestroyWindow(wnd); + return; + } + + hr = D3DXCreateFragmentLinker(device, 1024, &linker); + ok(hr == D3D_OK, "Unexpected hr %#x.\n", hr); + ok(linker != NULL, "D3DXCreateFragmentLinker() failed, got NULL\n"); + linker->lpVtbl->Release(linker); + + count = IDirect3DDevice9_Release(device); + ok(!count, "The Direct3D device reference count was %u, should be 0\n", count); + + count = IDirect3D9_Release(d3d); + ok(!count, "The Direct3D object reference count was %u, should be 0\n", count); + + if (wnd) DestroyWindow(wnd); +} + +static void test_fragment_linkerex(void) +{ + HWND wnd; + IDirect3D9 *d3d; + IDirect3DDevice9 *device; + D3DPRESENT_PARAMETERS d3dpp; + HRESULT hr; + ULONG count; + ID3DXFragmentLinker *linker; + + if (!(wnd = CreateWindowA("static", "d3dx9_test", WS_OVERLAPPEDWINDOW, 0, 0, + 640, 480, NULL, NULL, NULL, NULL))) + { + skip("Couldn't create application window\n"); + return; + } + if (!(d3d = Direct3DCreate9(D3D_SDK_VERSION))) + { + skip("Couldn't create IDirect3D9 object\n"); + DestroyWindow(wnd); + return; + } + + ZeroMemory(&d3dpp, sizeof(d3dpp)); + d3dpp.Windowed = TRUE; + d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD; + hr = IDirect3D9_CreateDevice(d3d, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, wnd, D3DCREATE_MIXED_VERTEXPROCESSING, &d3dpp, &device); + if (FAILED(hr)) + { + skip("Failed to create IDirect3DDevice9 object %#x\n", hr); + IDirect3D9_Release(d3d); + DestroyWindow(wnd); + return; + } + + hr = D3DXCreateFragmentLinkerEx(device, 1024, 0, &linker); + ok(hr == D3D_OK, "Unexpected hr %#x.\n", hr); + ok(linker != NULL, "D3DXCreateFragmentLinkerEx() failed, got NULL\n"); + linker->lpVtbl->Release(linker); + + count = IDirect3DDevice9_Release(device); + ok(!count, "The Direct3D device reference count was %u, should be 0\n", count); + + count = IDirect3D9_Release(d3d); + ok(!count, "The Direct3D object reference count was %u, should be 0\n", count); + + if (wnd) DestroyWindow(wnd); +} + START_TEST(shader) { test_get_shader_size(); @@ -6589,4 +6687,6 @@ START_TEST(shader) test_registerset(); test_registerset_defaults(); test_shader_semantics(); + test_fragment_linker(); + test_fragment_linkerex(); }