From: Zebediah Figura zfigura@codeweavers.com
--- dlls/d3dx10_43/async.c | 41 ++++++++ dlls/d3dx10_43/d3dx10_43.spec | 4 +- dlls/d3dx10_43/tests/d3dx10.c | 183 ++++++++++++++++++++++++++++++++++ include/d3dx10async.h | 8 ++ 4 files changed, 234 insertions(+), 2 deletions(-)
diff --git a/dlls/d3dx10_43/async.c b/dlls/d3dx10_43/async.c index 62627886804..aeb5d3f214a 100644 --- a/dlls/d3dx10_43/async.c +++ b/dlls/d3dx10_43/async.c @@ -396,6 +396,47 @@ HRESULT WINAPI D3DX10CompileFromMemory(const char *data, SIZE_T data_size, const sflags, eflags, shader, error_messages); }
+HRESULT WINAPI D3DX10CompileFromFileA(const char *filename, const D3D10_SHADER_MACRO *defines, + ID3D10Include *include, const char *entry_point, const char *target, UINT sflags, UINT eflags, + ID3DX10ThreadPump *pump, ID3D10Blob **shader, ID3D10Blob **error_messages, HRESULT *hresult) +{ + WCHAR filename_w[MAX_PATH]; + + TRACE("filename %s, defines %p, include %p, entry_point %s, target %s, sflags %#x, " + "eflags %#x, pump %p, shader %p, error_messages %p, hresult %p.\n", + debugstr_a(filename), defines, include, debugstr_a(entry_point), debugstr_a(target), + sflags, eflags, pump, shader, error_messages, hresult); + + MultiByteToWideChar(CP_ACP, 0, filename, -1, filename_w, ARRAY_SIZE(filename_w)); + + return D3DX10CompileFromFileW(filename_w, defines, include, entry_point, target, + sflags, eflags, pump, shader, error_messages, hresult); +} + +HRESULT WINAPI D3DX10CompileFromFileW(const WCHAR *filename, const D3D10_SHADER_MACRO *defines, + ID3D10Include *include, const char *entry_point, const char *target, UINT sflags, UINT eflags, + ID3DX10ThreadPump *pump, ID3D10Blob **shader, ID3D10Blob **error_messages, HRESULT *hresult) +{ + HRESULT hr; + + TRACE("filename %s, defines %p, include %p, entry_point %s, target %s, sflags %#x, " + "eflags %#x, pump %p, shader %p, error_messages %p, hresult %p.\n", + debugstr_w(filename), defines, include, debugstr_a(entry_point), debugstr_a(target), + sflags, eflags, pump, shader, error_messages, hresult); + + if (pump) + FIXME("Unimplemented ID3DX10ThreadPump handling.\n"); + + if (!include) + include = D3D_COMPILE_STANDARD_FILE_INCLUDE; + + hr = D3DCompileFromFile(filename, defines, include, entry_point, target, sflags, eflags, shader, error_messages); + if (hresult) + *hresult = hr; + + return hr; +} + HRESULT WINAPI D3DX10CreateEffectPoolFromFileA(const char *filename, const D3D10_SHADER_MACRO *defines, ID3D10Include *include, const char *profile, UINT hlslflags, UINT fxflags, ID3D10Device *device, ID3DX10ThreadPump *pump, ID3D10EffectPool **effectpool, ID3D10Blob **errors, HRESULT *hresult) diff --git a/dlls/d3dx10_43/d3dx10_43.spec b/dlls/d3dx10_43/d3dx10_43.spec index 2359c7c6f02..899d1fb64e8 100644 --- a/dlls/d3dx10_43/d3dx10_43.spec +++ b/dlls/d3dx10_43/d3dx10_43.spec @@ -1,7 +1,7 @@ @ stdcall D3DX10CreateThreadPump(long long ptr) @ stdcall D3DX10CheckVersion(long long) -@ stub D3DX10CompileFromFileA(str ptr ptr str str long long ptr ptr ptr ptr) -@ stub D3DX10CompileFromFileW(wstr ptr ptr str str long long ptr ptr ptr ptr) +@ stdcall D3DX10CompileFromFileA(str ptr ptr str str long long ptr ptr ptr ptr) +@ stdcall D3DX10CompileFromFileW(wstr ptr ptr str str long long ptr ptr ptr ptr) @ stdcall D3DX10CompileFromMemory(ptr long str ptr ptr str str long long ptr ptr ptr ptr) @ stub D3DX10CompileFromResourceA(long str str ptr ptr str str long long ptr ptr ptr ptr) @ stub D3DX10CompileFromResourceW(long wstr wstr ptr ptr str str long long ptr ptr ptr ptr) diff --git a/dlls/d3dx10_43/tests/d3dx10.c b/dlls/d3dx10_43/tests/d3dx10.c index 8257ab1e919..78b615ffe25 100644 --- a/dlls/d3dx10_43/tests/d3dx10.c +++ b/dlls/d3dx10_43/tests/d3dx10.c @@ -1181,6 +1181,24 @@ static BOOL delete_file(const WCHAR *filename) return DeleteFileW(path); }
+static BOOL create_directory(const WCHAR *dir) +{ + WCHAR path[MAX_PATH]; + + lstrcpyW(path, temp_dir); + lstrcatW(path, dir); + return CreateDirectoryW(path, NULL); +} + +static void delete_directory(const WCHAR *dir) +{ + WCHAR path[MAX_PATH]; + + lstrcpyW(path, temp_dir); + lstrcatW(path, dir); + RemoveDirectoryW(path); +} + static ID3D10Device *create_device(void) { ID3D10Device *device; @@ -4636,6 +4654,170 @@ static void test_preprocess_shader(void) ID3D10Blob_Release(preprocessed); }
+static HRESULT WINAPI test_d3dinclude_open(ID3DInclude *iface, D3D_INCLUDE_TYPE include_type, + const char *filename, const void *parent_data, const void **data, UINT *bytes) +{ + static const char include1[] = + "#define LIGHT float4(0.0f, 0.2f, 0.5f, 1.0f)\n"; + static const char include2[] = + "#include "include1.h"\n" + "float4 light_color = LIGHT;\n"; + char *buffer; + + trace("filename %s.\n", filename); + trace("parent_data %p: %s.\n", parent_data, parent_data ? (char *)parent_data : "(null)"); + + if (!strcmp(filename, "include1.h")) + { + buffer = malloc(strlen(include1)); + memcpy(buffer, include1, strlen(include1)); + *bytes = strlen(include1); + ok(include_type == D3D_INCLUDE_LOCAL, "Unexpected include type %d.\n", include_type); + ok(!strncmp(include2, parent_data, strlen(include2)), + "Unexpected parent_data value.\n"); + } + else if (!strcmp(filename, "include\include2.h")) + { + buffer = malloc(strlen(include2)); + memcpy(buffer, include2, strlen(include2)); + *bytes = strlen(include2); + ok(!parent_data, "Unexpected parent_data value.\n"); + ok(include_type == D3D_INCLUDE_LOCAL, "Unexpected include type %d.\n", include_type); + } + else + { + ok(0, "Unexpected #include for file %s.\n", filename); + return E_INVALIDARG; + } + + *data = buffer; + return S_OK; +} + +static HRESULT WINAPI test_d3dinclude_close(ID3DInclude *iface, const void *data) +{ + free((void *)data); + return S_OK; +} + +static const struct ID3DIncludeVtbl test_d3dinclude_vtbl = +{ + test_d3dinclude_open, + test_d3dinclude_close +}; + +struct test_d3dinclude +{ + ID3DInclude ID3DInclude_iface; +}; + +static void test_compile_from_file(void) +{ + struct test_d3dinclude include = {{&test_d3dinclude_vtbl}}; + WCHAR filename[MAX_PATH], directory[MAX_PATH]; + ID3D10Blob *blob = NULL, *errors = NULL; + CHAR filename_a[MAX_PATH]; + HRESULT hr, result; + DWORD len; + static const char ps_code[] = + "#include "include\include2.h"\n" + "\n" + "float4 main() : COLOR\n" + "{\n" + " return light_color;\n" + "}"; + static const char include1[] = + "#define LIGHT float4(0.0f, 0.2f, 0.5f, 1.0f)\n"; + static const char include1_wrong[] = + "#define LIGHT nope\n"; + static const char include2[] = + "#include "include1.h"\n" + "float4 light_color = LIGHT;\n"; + + create_file(L"source.ps", ps_code, strlen(ps_code), filename); + create_directory(L"include"); + create_file(L"include\include1.h", include1_wrong, strlen(include1_wrong), NULL); + create_file(L"include1.h", include1, strlen(include1), NULL); + create_file(L"include\include2.h", include2, strlen(include2), NULL); + + hr = D3DX10CompileFromFileW(filename, NULL, &include.ID3DInclude_iface, + "main", "ps_2_0", 0, 0, NULL, &blob, &errors, &result); + todo_wine ok(hr == S_OK && hr == result, "Got unexpected hr %#lx, result %#lx.\n", hr, result); + todo_wine ok(!!blob, "Got unexpected blob.\n"); + todo_wine ok(!errors, "Got unexpected errors.\n"); + if (errors) + { + ID3D10Blob_Release(errors); + errors = NULL; + } + if (blob) + { + ID3D10Blob_Release(blob); + blob = NULL; + } + + /* Windows always seems to resolve includes from the initial file location + * instead of using the immediate parent, as it would be the case for + * standard C preprocessor includes. */ + hr = D3DX10CompileFromFileW(filename, NULL, NULL, "main", "ps_2_0", 0, 0, NULL, &blob, &errors, &result); + todo_wine ok(hr == S_OK && hr == result, "Got unexpected hr %#lx, result %#lx.\n", hr, result); + todo_wine ok(!!blob, "Got unexpected blob.\n"); + todo_wine ok(!errors, "Got unexpected errors.\n"); + if (errors) + { + ID3D10Blob_Release(errors); + errors = NULL; + } + if (blob) + { + ID3D10Blob_Release(blob); + blob = NULL; + } + + len = WideCharToMultiByte(CP_ACP, 0, filename, -1, NULL, 0, NULL, NULL); + WideCharToMultiByte(CP_ACP, 0, filename, -1, filename_a, len, NULL, NULL); + hr = D3DX10CompileFromFileA(filename_a, NULL, NULL, "main", "ps_2_0", 0, 0, NULL, &blob, &errors, &result); + todo_wine ok(hr == S_OK && hr == result, "Got unexpected hr %#lx, result %#lx.\n", hr, result); + todo_wine ok(!!blob, "Got unexpected blob.\n"); + todo_wine ok(!errors, "Got unexpected errors.\n"); + if (errors) + { + ID3D10Blob_Release(errors); + errors = NULL; + } + if (blob) + { + ID3D10Blob_Release(blob); + blob = NULL; + } + + GetCurrentDirectoryW(MAX_PATH, directory); + SetCurrentDirectoryW(temp_dir); + + hr = D3DX10CompileFromFileW(L"source.ps", NULL, NULL, "main", "ps_2_0", 0, 0, NULL, &blob, &errors, &result); + todo_wine ok(hr == S_OK && hr == result, "Got unexpected hr %#lx, result %#lx.\n", hr, result); + todo_wine ok(!!blob, "Got unexpected blob.\n"); + todo_wine ok(!errors, "Got unexpected errors.\n"); + if (errors) + { + ID3D10Blob_Release(errors); + errors = NULL; + } + if (blob) + { + ID3D10Blob_Release(blob); + blob = NULL; + } + + SetCurrentDirectoryW(directory); + + delete_file(L"source.ps"); + delete_file(L"include\include1.h"); + delete_file(L"include1.h"); + delete_file(L"include\include2.h"); + delete_directory(L"include"); +} + START_TEST(d3dx10) { test_D3DX10UnsetAllDeviceObjects(); @@ -4653,4 +4835,5 @@ START_TEST(d3dx10) test_create_effect_from_file(); test_create_effect_from_resource(); test_preprocess_shader(); + test_compile_from_file(); } diff --git a/include/d3dx10async.h b/include/d3dx10async.h index 931458f4813..6d453f26d60 100644 --- a/include/d3dx10async.h +++ b/include/d3dx10async.h @@ -21,6 +21,14 @@
#include "d3dx10.h"
+HRESULT WINAPI D3DX10CompileFromFileA(const char *filename, const D3D10_SHADER_MACRO *defines, + ID3D10Include *include, const char *entry_point, const char *target, UINT sflags, UINT eflags, + ID3DX10ThreadPump *pump, ID3D10Blob **shader, ID3D10Blob **error_messages, HRESULT *hresult); + +HRESULT WINAPI D3DX10CompileFromFileW(const WCHAR *filename, const D3D10_SHADER_MACRO *defines, + ID3D10Include *include, const char *entry_point, const char *target, UINT sflags, UINT eflags, + ID3DX10ThreadPump *pump, ID3D10Blob **shader, ID3D10Blob **error_messages, HRESULT *hresult); + HRESULT WINAPI D3DX10CompileFromMemory(const char *data, SIZE_T data_size, const char *filename, const D3D10_SHADER_MACRO *defines, ID3D10Include *include, const char *entry_point, const char *target, UINT sflags, UINT eflags, ID3DX10ThreadPump *pump, ID3D10Blob **shader,