[PATCH v2] d3dx9: Implement D3DXCreateFragmentLinker/Ex
Alistair Leslie-Hughes
leslie_alistair at hotmail.com
Wed Nov 27 20:40:05 CST 2019
Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=38086
Signed-off-by: Alistair Leslie-Hughes <leslie_alistair at 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();
}
--
2.17.1
More information about the wine-devel
mailing list