From e404e9ee2f5d5b7e00a8b45fd5b2f7f143ff4ec4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=B4me=20Gardou?= Date: Tue, 24 Dec 2019 09:31:48 +0100 Subject: [PATCH] [D3DX9_36_WINETEST] Import from wine 4.0 --- modules/rostests/winetests/CMakeLists.txt | 1 + .../winetests/d3dx9_36/CMakeLists.txt | 25 + modules/rostests/winetests/d3dx9_36/asm.c | 583 + .../rostests/winetests/d3dx9_36/bmp1x1.bmp | Bin 0 -> 58 bytes modules/rostests/winetests/d3dx9_36/core.c | 1310 ++ modules/rostests/winetests/d3dx9_36/effect.c | 8030 +++++++++++ modules/rostests/winetests/d3dx9_36/line.c | 155 + modules/rostests/winetests/d3dx9_36/math.c | 3687 +++++ modules/rostests/winetests/d3dx9_36/mesh.c | 11256 ++++++++++++++++ modules/rostests/winetests/d3dx9_36/res.vsh | 2 + .../rostests/winetests/d3dx9_36/resources.h | 28 + modules/rostests/winetests/d3dx9_36/rsrc.rc | 31 + modules/rostests/winetests/d3dx9_36/shader.c | 6592 +++++++++ modules/rostests/winetests/d3dx9_36/surface.c | 1465 ++ .../rostests/winetests/d3dx9_36/testlist.c | 32 + modules/rostests/winetests/d3dx9_36/texture.c | 2264 ++++ modules/rostests/winetests/d3dx9_36/volume.c | 306 + modules/rostests/winetests/d3dx9_36/xfile.c | 389 + 18 files changed, 36156 insertions(+) create mode 100644 modules/rostests/winetests/d3dx9_36/CMakeLists.txt create mode 100644 modules/rostests/winetests/d3dx9_36/asm.c create mode 100644 modules/rostests/winetests/d3dx9_36/bmp1x1.bmp create mode 100644 modules/rostests/winetests/d3dx9_36/core.c create mode 100644 modules/rostests/winetests/d3dx9_36/effect.c create mode 100644 modules/rostests/winetests/d3dx9_36/line.c create mode 100644 modules/rostests/winetests/d3dx9_36/math.c create mode 100644 modules/rostests/winetests/d3dx9_36/mesh.c create mode 100644 modules/rostests/winetests/d3dx9_36/res.vsh create mode 100644 modules/rostests/winetests/d3dx9_36/resources.h create mode 100644 modules/rostests/winetests/d3dx9_36/rsrc.rc create mode 100644 modules/rostests/winetests/d3dx9_36/shader.c create mode 100644 modules/rostests/winetests/d3dx9_36/surface.c create mode 100644 modules/rostests/winetests/d3dx9_36/testlist.c create mode 100644 modules/rostests/winetests/d3dx9_36/texture.c create mode 100644 modules/rostests/winetests/d3dx9_36/volume.c create mode 100644 modules/rostests/winetests/d3dx9_36/xfile.c diff --git a/modules/rostests/winetests/CMakeLists.txt b/modules/rostests/winetests/CMakeLists.txt index 8bb0f90d9f4..c4553c5a09c 100644 --- a/modules/rostests/winetests/CMakeLists.txt +++ b/modules/rostests/winetests/CMakeLists.txt @@ -35,6 +35,7 @@ add_subdirectory(cryptnet) add_subdirectory(cryptui) add_subdirectory(d3dcompiler_43) add_subdirectory(d3drm) +add_subdirectory(d3dx9_36) add_subdirectory(devenum) add_subdirectory(dinput) add_subdirectory(dinput8) diff --git a/modules/rostests/winetests/d3dx9_36/CMakeLists.txt b/modules/rostests/winetests/d3dx9_36/CMakeLists.txt new file mode 100644 index 00000000000..2a1dab147b7 --- /dev/null +++ b/modules/rostests/winetests/d3dx9_36/CMakeLists.txt @@ -0,0 +1,25 @@ + +add_executable(d3dx9_36_winetest + asm.c + core.c + effect.c + line.c + math.c + mesh.c + shader.c + surface.c + texture.c + volume.c + xfile.c + testlist.c + rsrc.rc) +target_compile_definitions(d3dx9_36_winetest PRIVATE -DUSE_WINE_TODOS -D__WINESRC__ -Disnan=_isnan) +if(MSVC) + # Disable warning C4477 (printf format warnings) + target_compile_options(d3dx9_36_winetest PRIVATE "/wd4477") +endif() + +target_link_libraries(d3dx9_36_winetest uuid dxguid) +set_module_type(d3dx9_36_winetest win32cui) +add_importlibs(d3dx9_36_winetest d3dx9_36 d3d9 user32 gdi32 msvcrt kernel32) +add_rostests_file(TARGET d3dx9_36_winetest) diff --git a/modules/rostests/winetests/d3dx9_36/asm.c b/modules/rostests/winetests/d3dx9_36/asm.c new file mode 100644 index 00000000000..4087bd89b09 --- /dev/null +++ b/modules/rostests/winetests/d3dx9_36/asm.c @@ -0,0 +1,583 @@ +/* + * Copyright (C) 2008 Stefan Dösinger + * Copyright (C) 2009 Matteo Bruni + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA + */ +#define COBJMACROS +#define CONST_VTABLE +#include "wine/test.h" + +#include + +#include "resources.h" + +static char temp_path[MAX_PATH]; + +static BOOL create_file(const char *filename, const char *data, const unsigned int size, char *out_path) +{ + DWORD written; + HANDLE hfile; + char path[MAX_PATH]; + + if (!*temp_path) + GetTempPathA(sizeof(temp_path), temp_path); + + strcpy(path, temp_path); + strcat(path, filename); + hfile = CreateFileA(path, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, 0); + if (hfile == INVALID_HANDLE_VALUE) + return FALSE; + + if (WriteFile(hfile, data, size, &written, NULL)) + { + CloseHandle(hfile); + + if (out_path) + strcpy(out_path, path); + return TRUE; + } + + CloseHandle(hfile); + return FALSE; +} + +static void delete_file(const char *filename) +{ + char path[MAX_PATH]; + + strcpy(path, temp_path); + strcat(path, filename); + DeleteFileA(path); +} + +static BOOL create_directory(const char *name) +{ + char path[MAX_PATH]; + + strcpy(path, temp_path); + strcat(path, name); + return CreateDirectoryA(path, NULL); +} + +static void delete_directory(const char *name) +{ + char path[MAX_PATH]; + + strcpy(path, temp_path); + strcat(path, name); + RemoveDirectoryA(path); +} + +static HRESULT WINAPI testD3DXInclude_open(ID3DXInclude *iface, D3DXINCLUDE_TYPE include_type, + const char *filename, const void *parent_data, const void **data, UINT *bytes) +{ + char *buffer; + static const char shader[] = + "#include \"incl.vsh\"\n" + "mov REGISTER, v0\n"; + static const char include[] = "#define REGISTER r0\nvs.1.1\n"; + static const char include2[] = "#include \"incl3.vsh\"\n"; + static const char include3[] = "vs.1.1\n"; + + trace("filename %s.\n", filename); + trace("parent_data %p: %s.\n", parent_data, parent_data ? (char *)parent_data : "(null)"); + + if (!strcmp(filename, "shader.vsh")) + { + buffer = HeapAlloc(GetProcessHeap(), 0, sizeof(shader)); + memcpy(buffer, shader, sizeof(shader)); + *bytes = sizeof(shader); + } + else if (!strcmp(filename, "incl.vsh")) + { + buffer = HeapAlloc(GetProcessHeap(), 0, sizeof(include)); + memcpy(buffer, include, sizeof(include)); + *bytes = sizeof(include); + /* This is included from the first D3DXAssembleShader with non-null ID3DXInclude test + * (parent_data == NULL) and from shader.vsh / shader[] (with matching parent_data). + * Allow both cases. */ + ok(parent_data == NULL || !strncmp(shader, parent_data, strlen(shader)), "wrong parent_data value\n"); + } + else if (!strcmp(filename, "incl2.vsh")) + { + buffer = HeapAlloc(GetProcessHeap(), 0, sizeof(include2)); + memcpy(buffer, include2, sizeof(include2)); + *bytes = sizeof(include2); + } + else if (!strcmp(filename, "incl3.vsh")) + { + buffer = HeapAlloc(GetProcessHeap(), 0, sizeof(include3)); + memcpy(buffer, include3, sizeof(include3)); + *bytes = sizeof(include3); + /* Also check for the correct parent_data content */ + ok(parent_data != NULL && !strncmp(include2, parent_data, strlen(include2)), "wrong parent_data value\n"); + } + else if (!strcmp(filename, "include/incl3.vsh")) + { + buffer = HeapAlloc(GetProcessHeap(), 0, sizeof(include)); + memcpy(buffer, include, sizeof(include)); + *bytes = sizeof(include); + ok(!parent_data, "wrong parent_data value\n"); + } + else + { + ok(0, "Unexpected #include for file %s.\n", filename); + return D3DERR_INVALIDCALL; + } + *data = buffer; + return S_OK; +} + +static HRESULT WINAPI testD3DXInclude_close(ID3DXInclude *iface, const void *data) +{ + HeapFree(GetProcessHeap(), 0, (void *)data); + return S_OK; +} + +static const struct ID3DXIncludeVtbl D3DXInclude_Vtbl = { + testD3DXInclude_open, + testD3DXInclude_close +}; + +struct D3DXIncludeImpl { + ID3DXInclude ID3DXInclude_iface; +}; + +static void assembleshader_test(void) +{ + static const char test1[] = + "vs.1.1\n" + "mov DEF2, v0\n"; + static const char testincl[] = + "#define REGISTER r0\n" + "vs.1.1\n"; + static const char testshader[] = + "#include \"incl.vsh\"\n" + "mov REGISTER, v0\n"; + static const char testshader2[] = + "#include \"incl2.vsh\"\n" + "mov REGISTER, v0\n"; + static const char testshader3[] = + "#include \"include/incl3.vsh\"\n" + "mov REGISTER, v0\n"; + static const char testincl3[] = + "#include \"incl4.vsh\"\n"; + static const char testincl4_ok[] = + "#define REGISTER r0\n" + "vs.1.1\n"; + static const char testincl4_wrong[] = + "#error \"wrong include\"\n"; + HRESULT hr; + ID3DXBuffer *shader, *messages; + static const D3DXMACRO defines[] = { + { + "DEF1", "10 + 15" + }, + { + "DEF2", "r0" + }, + { + NULL, NULL + } + }; + struct D3DXIncludeImpl include; + char shader_vsh_path[MAX_PATH], shader3_vsh_path[MAX_PATH]; + static const WCHAR shader_filename_w[] = {'s','h','a','d','e','r','.','v','s','h',0}; + + /* pDefines test */ + shader = NULL; + messages = NULL; + hr = D3DXAssembleShader(test1, strlen(test1), + defines, NULL, D3DXSHADER_SKIPVALIDATION, + &shader, &messages); + ok(hr == D3D_OK, "pDefines test failed with error 0x%x - %d\n", hr, hr & 0x0000FFFF); + if(messages) { + trace("D3DXAssembleShader messages:\n%s", (char *)ID3DXBuffer_GetBufferPointer(messages)); + ID3DXBuffer_Release(messages); + } + if(shader) ID3DXBuffer_Release(shader); + + /* NULL messages test */ + shader = NULL; + hr = D3DXAssembleShader(test1, strlen(test1), + defines, NULL, D3DXSHADER_SKIPVALIDATION, + &shader, NULL); + ok(hr == D3D_OK, "NULL messages test failed with error 0x%x - %d\n", hr, hr & 0x0000FFFF); + if(shader) ID3DXBuffer_Release(shader); + + /* NULL shader test */ + messages = NULL; + hr = D3DXAssembleShader(test1, strlen(test1), + defines, NULL, D3DXSHADER_SKIPVALIDATION, + NULL, &messages); + ok(hr == D3D_OK, "NULL shader test failed with error 0x%x - %d\n", hr, hr & 0x0000FFFF); + if(messages) { + trace("D3DXAssembleShader messages:\n%s", (char *)ID3DXBuffer_GetBufferPointer(messages)); + ID3DXBuffer_Release(messages); + } + + /* pInclude test */ + shader = NULL; + messages = NULL; + include.ID3DXInclude_iface.lpVtbl = &D3DXInclude_Vtbl; + hr = D3DXAssembleShader(testshader, strlen(testshader), NULL, &include.ID3DXInclude_iface, + D3DXSHADER_SKIPVALIDATION, &shader, &messages); + ok(hr == D3D_OK, "pInclude test failed with error 0x%x - %d\n", hr, hr & 0x0000FFFF); + if(messages) { + trace("D3DXAssembleShader messages:\n%s", (char *)ID3DXBuffer_GetBufferPointer(messages)); + ID3DXBuffer_Release(messages); + } + if(shader) ID3DXBuffer_Release(shader); + + /* "unexpected #include file from memory" test */ + shader = NULL; + messages = NULL; + hr = D3DXAssembleShader(testshader, strlen(testshader), + NULL, NULL, D3DXSHADER_SKIPVALIDATION, + &shader, &messages); + ok(hr == D3DXERR_INVALIDDATA, "D3DXAssembleShader test failed with error 0x%x - %d\n", hr, hr & 0x0000FFFF); + if(messages) { + trace("D3DXAssembleShader messages:\n%s", (char *)ID3DXBuffer_GetBufferPointer(messages)); + ID3DXBuffer_Release(messages); + } + if(shader) ID3DXBuffer_Release(shader); + + /* recursive #include test */ + shader = NULL; + messages = NULL; + hr = D3DXAssembleShader(testshader2, strlen(testshader2), NULL, &include.ID3DXInclude_iface, + D3DXSHADER_SKIPVALIDATION, &shader, &messages); + ok(hr == D3D_OK, "D3DXAssembleShader test failed with error 0x%x - %d\n", hr, hr & 0x0000FFFF); + if(messages) { + trace("recursive D3DXAssembleShader messages:\n%s", (char *)ID3DXBuffer_GetBufferPointer(messages)); + ID3DXBuffer_Release(messages); + } + if(shader) ID3DXBuffer_Release(shader); + + /* #include with a path. */ + shader = NULL; + messages = NULL; + hr = D3DXAssembleShader(testshader3, strlen(testshader3), NULL, &include.ID3DXInclude_iface, + D3DXSHADER_SKIPVALIDATION, &shader, &messages); + ok(hr == D3D_OK, "D3DXAssembleShader test failed with error 0x%x - %d\n", hr, hr & 0x0000ffff); + if (messages) + { + trace("Path search D3DXAssembleShader messages:\n%s", (char *)ID3DXBuffer_GetBufferPointer(messages)); + ID3DXBuffer_Release(messages); + } + if (shader) + ID3DXBuffer_Release(shader); + + if (create_file("shader.vsh", testshader, sizeof(testshader) - 1, shader_vsh_path)) + { + create_file("incl.vsh", testincl, sizeof(testincl) - 1, NULL); + + /* D3DXAssembleShaderFromFile + #include test */ + shader = NULL; + messages = NULL; + hr = D3DXAssembleShaderFromFileA(shader_vsh_path, + NULL, NULL, D3DXSHADER_SKIPVALIDATION, + &shader, &messages); + ok(hr == D3D_OK, "D3DXAssembleShaderFromFile test failed with error 0x%x - %d\n", hr, hr & 0x0000FFFF); + if(messages) { + trace("D3DXAssembleShader messages:\n%s", (char *)ID3DXBuffer_GetBufferPointer(messages)); + ID3DXBuffer_Release(messages); + } + if(shader) ID3DXBuffer_Release(shader); + + /* D3DXAssembleShaderFromFile + pInclude test */ + shader = NULL; + messages = NULL; + hr = D3DXAssembleShaderFromFileA("shader.vsh", NULL, &include.ID3DXInclude_iface, + D3DXSHADER_SKIPVALIDATION, &shader, &messages); + ok(hr == D3D_OK, "D3DXAssembleShaderFromFile + pInclude test failed with error 0x%x - %d\n", hr, hr & 0x0000FFFF); + if(messages) { + trace("D3DXAssembleShader messages:\n%s", (char *)ID3DXBuffer_GetBufferPointer(messages)); + ID3DXBuffer_Release(messages); + } + if(shader) ID3DXBuffer_Release(shader); + + create_file("shader3.vsh", testshader3, sizeof(testshader3) - 1, shader3_vsh_path); + create_file("incl4.vsh", testincl4_wrong, sizeof(testincl4_wrong) - 1, NULL); + if (create_directory("include")) + { + create_file("include\\incl3.vsh", testincl3, sizeof(testincl3) - 1, NULL); + create_file("include\\incl4.vsh", testincl4_ok, sizeof(testincl4_ok) - 1, NULL); + + /* path search #include test */ + shader = NULL; + messages = NULL; + hr = D3DXAssembleShaderFromFileA(shader3_vsh_path, NULL, NULL, + D3DXSHADER_SKIPVALIDATION, + &shader, &messages); + ok(hr == D3D_OK, "D3DXAssembleShaderFromFile path search test failed with error 0x%x - %d\n", hr, hr & 0x0000FFFF); + if(messages) { + trace("D3DXAssembleShaderFromFile path search messages:\n%s", (char *)ID3DXBuffer_GetBufferPointer(messages)); + ID3DXBuffer_Release(messages); + } + if(shader) ID3DXBuffer_Release(shader); + } else skip("Couldn't create \"include\" directory\n"); + + delete_file("shader.vsh"); + delete_file("incl.vsh"); + delete_file("shader3.vsh"); + delete_file("incl4.vsh"); + delete_file("include\\incl3.vsh"); + delete_file("include\\incl4.vsh"); + delete_directory("include"); + + /* The main shader is also to be loaded through the ID3DXInclude object. */ + shader = NULL; + messages = NULL; + hr = D3DXAssembleShaderFromFileA("shader.vsh", NULL, &include.ID3DXInclude_iface, + D3DXSHADER_SKIPVALIDATION, &shader, &messages); + ok(hr == D3D_OK, "D3DXAssembleShaderFromFile + pInclude main shader test failed with error 0x%x - %d\n", + hr, hr & 0x0000ffff); + if (messages) + { + trace("D3DXAssembleShader messages:\n%s", (char *)ID3DXBuffer_GetBufferPointer(messages)); + ID3DXBuffer_Release(messages); + } + if (shader) + ID3DXBuffer_Release(shader); + + shader = NULL; + messages = NULL; + hr = D3DXAssembleShaderFromFileW(shader_filename_w, NULL, &include.ID3DXInclude_iface, + D3DXSHADER_SKIPVALIDATION, &shader, &messages); + ok(hr == D3D_OK, "D3DXAssembleShaderFromFile + pInclude main shader test failed with error 0x%x - %d\n", + hr, hr & 0x0000ffff); + if (messages) + { + trace("D3DXAssembleShader messages:\n%s", (char *)ID3DXBuffer_GetBufferPointer(messages)); + ID3DXBuffer_Release(messages); + } + if (shader) + ID3DXBuffer_Release(shader); + } else skip("Couldn't create \"shader.vsh\"\n"); + + /* NULL shader tests */ + shader = NULL; + messages = NULL; + hr = D3DXAssembleShader(NULL, 0, + NULL, NULL, D3DXSHADER_SKIPVALIDATION, + &shader, &messages); + ok(hr == D3DXERR_INVALIDDATA, "NULL shader test failed with error 0x%x - %d\n", hr, hr & 0x0000FFFF); + if(messages) { + trace("D3DXAssembleShader messages:\n%s", (char *)ID3DXBuffer_GetBufferPointer(messages)); + ID3DXBuffer_Release(messages); + } + if(shader) ID3DXBuffer_Release(shader); + + shader = NULL; + messages = NULL; + hr = D3DXAssembleShaderFromFileA("nonexistent.vsh", + NULL, NULL, D3DXSHADER_SKIPVALIDATION, + &shader, &messages); + ok(hr == D3DXERR_INVALIDDATA || hr == E_FAIL, /* I get this on WinXP */ + "D3DXAssembleShaderFromFile nonexistent file test failed with error 0x%x - %d\n", + hr, hr & 0x0000FFFF); + if(messages) { + trace("D3DXAssembleShaderFromFile messages:\n%s", (char *)ID3DXBuffer_GetBufferPointer(messages)); + ID3DXBuffer_Release(messages); + } + if(shader) ID3DXBuffer_Release(shader); + + /* D3DXAssembleShaderFromResource test */ + shader = NULL; + messages = NULL; + hr = D3DXAssembleShaderFromResourceA(NULL, MAKEINTRESOURCEA(IDB_ASMSHADER), + NULL, NULL, D3DXSHADER_SKIPVALIDATION, + &shader, &messages); + ok(hr == D3D_OK, "D3DXAssembleShaderFromResource test failed with error 0x%x - %d\n", hr, hr & 0x0000FFFF); + if(messages) { + trace("D3DXAssembleShaderFromResource messages:\n%s", (char *)ID3DXBuffer_GetBufferPointer(messages)); + ID3DXBuffer_Release(messages); + } + if(shader) ID3DXBuffer_Release(shader); + + /* D3DXAssembleShaderFromResource with missing shader resource test */ + shader = NULL; + messages = NULL; + hr = D3DXAssembleShaderFromResourceA(NULL, "notexisting", + NULL, NULL, D3DXSHADER_SKIPVALIDATION, + &shader, &messages); + ok(hr == D3DXERR_INVALIDDATA, "D3DXAssembleShaderFromResource NULL shader test failed with error 0x%x - %d\n", hr, hr & 0x0000FFFF); + if(messages) { + trace("D3DXAssembleShaderFromResource messages:\n%s", (char *)ID3DXBuffer_GetBufferPointer(messages)); + ID3DXBuffer_Release(messages); + } + if(shader) ID3DXBuffer_Release(shader); +} + +static void d3dxpreprocess_test(void) +{ + static const char testincl[] = + "#define REGISTER r0\n" + "vs.1.1\n"; + static const char testshader[] = + "#include \"incl.vsh\"\n" + "mov REGISTER, v0\n"; + static const char testshader3[] = + "#include \"include/incl3.vsh\"\n" + "mov REGISTER, v0\n"; + static const char testincl3[] = + "#include \"incl4.vsh\"\n"; + static const char testincl4_ok[] = + "#define REGISTER r0\n" + "vs.1.1\n"; + static const char testincl4_wrong[] = + "#error \"wrong include\"\n"; + HRESULT hr; + ID3DXBuffer *shader, *messages; + char shader_vsh_path[MAX_PATH], shader3_vsh_path[MAX_PATH]; + static struct D3DXIncludeImpl include = {{&D3DXInclude_Vtbl}}; + static const WCHAR shader_filename_w[] = {'s','h','a','d','e','r','.','v','s','h',0}; + + if (create_file("shader.vsh", testshader, sizeof(testshader) - 1, shader_vsh_path)) + { + create_file("incl.vsh", testincl, sizeof(testincl) - 1, NULL); + create_file("shader3.vsh", testshader3, sizeof(testshader3) - 1, shader3_vsh_path); + create_file("incl4.vsh", testincl4_wrong, sizeof(testincl4_wrong) - 1, NULL); + if (create_directory("include")) + { + create_file("include\\incl3.vsh", testincl3, sizeof(testincl3) - 1, NULL); + create_file("include\\incl4.vsh", testincl4_ok, sizeof(testincl4_ok) - 1, NULL); + + /* path search #include test */ + shader = NULL; + messages = NULL; + hr = D3DXPreprocessShaderFromFileA(shader3_vsh_path, NULL, NULL, + &shader, &messages); + ok(hr == D3D_OK, "D3DXPreprocessShaderFromFile path search test failed with error 0x%x - %d\n", hr, hr & 0x0000FFFF); + if(messages) { + trace("D3DXPreprocessShaderFromFile path search messages:\n%s", (char *)ID3DXBuffer_GetBufferPointer(messages)); + ID3DXBuffer_Release(messages); + } + if(shader) ID3DXBuffer_Release(shader); + } else skip("Couldn't create \"include\" directory\n"); + + /* D3DXPreprocessShaderFromFile + #include test */ + shader = NULL; + messages = NULL; + hr = D3DXPreprocessShaderFromFileA(shader_vsh_path, + NULL, NULL, + &shader, &messages); + ok(hr == D3D_OK, "D3DXPreprocessShaderFromFile test failed with error 0x%x - %d\n", hr, hr & 0x0000FFFF); + if(messages) { + trace("D3DXPreprocessShader messages:\n%s", (char *)ID3DXBuffer_GetBufferPointer(messages)); + ID3DXBuffer_Release(messages); + } + if(shader) ID3DXBuffer_Release(shader); + + /* D3DXPreprocessShaderFromFile + pInclude test */ + shader = NULL; + messages = NULL; + hr = D3DXPreprocessShaderFromFileA("shader.vsh", NULL, &include.ID3DXInclude_iface, + &shader, &messages); + ok(hr == D3D_OK, "D3DXPreprocessShaderFromFile + pInclude test failed with error 0x%x - %d\n", hr, hr & 0x0000FFFF); + if(messages) { + trace("D3DXPreprocessShader messages:\n%s", (char *)ID3DXBuffer_GetBufferPointer(messages)); + ID3DXBuffer_Release(messages); + } + if(shader) ID3DXBuffer_Release(shader); + + delete_file("shader.vsh"); + delete_file("incl.vsh"); + delete_file("shader3.vsh"); + delete_file("incl4.vsh"); + delete_file("include\\incl3.vsh"); + delete_file("include\\incl4.vsh"); + delete_directory("include"); + + /* The main shader is also to be loaded through the ID3DXInclude object. */ + shader = NULL; + messages = NULL; + hr = D3DXPreprocessShaderFromFileA("shader.vsh", NULL, &include.ID3DXInclude_iface, + &shader, &messages); + ok(hr == D3D_OK, "D3DXPreprocessShaderFromFile + pInclude main shader test failed with error 0x%x - %d\n", + hr, hr & 0x0000ffff); + if (messages) + { + trace("D3DXPreprocessShaderFromFile messages:\n%s", (char *)ID3DXBuffer_GetBufferPointer(messages)); + ID3DXBuffer_Release(messages); + } + if (shader) + ID3DXBuffer_Release(shader); + + shader = NULL; + messages = NULL; + hr = D3DXPreprocessShaderFromFileW(shader_filename_w, NULL, &include.ID3DXInclude_iface, + &shader, &messages); + ok(hr == D3D_OK, "D3DXPreprocessShaderFromFile + pInclude main shader test failed with error 0x%x - %d\n", + hr, hr & 0x0000ffff); + if (messages) + { + trace("D3DXPreprocessShaderFromFile messages:\n%s", (char *)ID3DXBuffer_GetBufferPointer(messages)); + ID3DXBuffer_Release(messages); + } + if (shader) + ID3DXBuffer_Release(shader); + } else skip("Couldn't create \"shader.vsh\"\n"); + + /* NULL shader tests */ + shader = NULL; + messages = NULL; + hr = D3DXPreprocessShaderFromFileA("nonexistent.vsh", + NULL, NULL, + &shader, &messages); + ok(hr == D3DXERR_INVALIDDATA || hr == E_FAIL, /* I get this on WinXP */ + "D3DXPreprocessShaderFromFile nonexistent file test failed with error 0x%x - %d\n", + hr, hr & 0x0000FFFF); + if(messages) { + trace("D3DXPreprocessShaderFromFile messages:\n%s", (char *)ID3DXBuffer_GetBufferPointer(messages)); + ID3DXBuffer_Release(messages); + } + if(shader) ID3DXBuffer_Release(shader); + + /* D3DXPreprocessShaderFromResource test */ + shader = NULL; + messages = NULL; + hr = D3DXPreprocessShaderFromResourceA(NULL, MAKEINTRESOURCEA(IDB_ASMSHADER), + NULL, NULL, + &shader, &messages); + ok(hr == D3D_OK, "D3DXPreprocessShaderFromResource test failed with error 0x%x - %d\n", hr, hr & 0x0000FFFF); + if(messages) { + trace("D3DXPreprocessShaderFromResource messages:\n%s", (char *)ID3DXBuffer_GetBufferPointer(messages)); + ID3DXBuffer_Release(messages); + } + if(shader) ID3DXBuffer_Release(shader); + + /* D3DXPreprocessShaderFromResource with missing shader resource test */ + shader = NULL; + messages = NULL; + hr = D3DXPreprocessShaderFromResourceA(NULL, "notexisting", + NULL, NULL, + &shader, &messages); + ok(hr == D3DXERR_INVALIDDATA, "D3DXPreprocessShaderFromResource NULL shader test failed with error 0x%x - %d\n", hr, hr & 0x0000FFFF); + if(messages) { + trace("D3DXPreprocessShaderFromResource messages:\n%s", (char *)ID3DXBuffer_GetBufferPointer(messages)); + ID3DXBuffer_Release(messages); + } + if(shader) ID3DXBuffer_Release(shader); +} + +START_TEST(asm) +{ + assembleshader_test(); + + d3dxpreprocess_test(); +} diff --git a/modules/rostests/winetests/d3dx9_36/bmp1x1.bmp b/modules/rostests/winetests/d3dx9_36/bmp1x1.bmp new file mode 100644 index 0000000000000000000000000000000000000000..7f87ecf450e083eac4872508b271b8c3e0a38f1b GIT binary patch literal 58 lcmZ?rwPJt(Ga#h_#Eft(0hV9^l1KO;7%TuJ{{R2a003wL1?T_( literal 0 HcmV?d00001 diff --git a/modules/rostests/winetests/d3dx9_36/core.c b/modules/rostests/winetests/d3dx9_36/core.c new file mode 100644 index 00000000000..fa874a5ef51 --- /dev/null +++ b/modules/rostests/winetests/d3dx9_36/core.c @@ -0,0 +1,1310 @@ +/* + * Tests for the D3DX9 core interfaces + * + * Copyright 2009 Tony Wasserka + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA + */ + +#define COBJMACROS +#include "wine/test.h" +#include +#include "d3dx9core.h" + +static inline int get_ref(IUnknown *obj) +{ + IUnknown_AddRef(obj); + return IUnknown_Release(obj); +} + +#define check_ref(obj, exp) _check_ref(__LINE__, obj, exp) +static inline void _check_ref(unsigned int line, IUnknown *obj, int exp) +{ + int ref = get_ref(obj); + ok_(__FILE__, line)(exp == ref, "Invalid refcount. Expected %d, got %d\n", exp, ref); +} + +#define check_release(obj, exp) _check_release(__LINE__, obj, exp) +static inline void _check_release(unsigned int line, IUnknown *obj, int exp) +{ + int ref = IUnknown_Release(obj); + ok_(__FILE__, line)(ref == exp, "Invalid refcount. Expected %d, got %d\n", exp, ref); +} + +#define admitted_error 0.0001f +static inline void check_mat(D3DXMATRIX got, D3DXMATRIX exp) +{ + int i, j, equal=1; + for (i=0; i<4; i++) + for (j=0; j<4; j++) + if (fabs(U(exp).m[i][j]-U(got).m[i][j]) > admitted_error) + equal=0; + + ok(equal, "Got matrix\n\t(%f,%f,%f,%f\n\t %f,%f,%f,%f\n\t %f,%f,%f,%f\n\t %f,%f,%f,%f)\n" + "Expected matrix=\n\t(%f,%f,%f,%f\n\t %f,%f,%f,%f\n\t %f,%f,%f,%f\n\t %f,%f,%f,%f)\n", + U(got).m[0][0],U(got).m[0][1],U(got).m[0][2],U(got).m[0][3], + U(got).m[1][0],U(got).m[1][1],U(got).m[1][2],U(got).m[1][3], + U(got).m[2][0],U(got).m[2][1],U(got).m[2][2],U(got).m[2][3], + U(got).m[3][0],U(got).m[3][1],U(got).m[3][2],U(got).m[3][3], + U(exp).m[0][0],U(exp).m[0][1],U(exp).m[0][2],U(exp).m[0][3], + U(exp).m[1][0],U(exp).m[1][1],U(exp).m[1][2],U(exp).m[1][3], + U(exp).m[2][0],U(exp).m[2][1],U(exp).m[2][2],U(exp).m[2][3], + U(exp).m[3][0],U(exp).m[3][1],U(exp).m[3][2],U(exp).m[3][3]); +} + +static void test_ID3DXBuffer(void) +{ + ID3DXBuffer *buffer; + HRESULT hr; + ULONG count; + DWORD size; + + hr = D3DXCreateBuffer(10, NULL); + ok(hr == D3DERR_INVALIDCALL, "D3DXCreateBuffer failed, got %#x, expected %#x\n", hr, D3DERR_INVALIDCALL); + + hr = D3DXCreateBuffer(0, &buffer); + ok(hr == D3D_OK, "D3DXCreateBuffer failed, got %#x, expected %#x\n", hr, D3D_OK); + + size = ID3DXBuffer_GetBufferSize(buffer); + ok(!size, "GetBufferSize failed, got %u, expected %u\n", size, 0); + + count = ID3DXBuffer_Release(buffer); + ok(!count, "ID3DXBuffer has %u references left\n", count); + + hr = D3DXCreateBuffer(3, &buffer); + ok(hr == D3D_OK, "D3DXCreateBuffer failed, got %#x, expected %#x\n", hr, D3D_OK); + + size = ID3DXBuffer_GetBufferSize(buffer); + ok(size == 3, "GetBufferSize failed, got %u, expected %u\n", size, 3); + + count = ID3DXBuffer_Release(buffer); + ok(!count, "ID3DXBuffer has %u references left\n", count); +} + +static void test_ID3DXSprite(IDirect3DDevice9 *device) +{ + ID3DXSprite *sprite; + IDirect3D9 *d3d; + IDirect3DDevice9 *cmpdev; + IDirect3DTexture9 *tex1, *tex2; + D3DXMATRIX mat, cmpmat; + D3DVIEWPORT9 vp; + RECT rect; + D3DXVECTOR3 pos, center; + HRESULT hr; + + IDirect3DDevice9_GetDirect3D(device, &d3d); + hr = IDirect3D9_CheckDeviceFormat(d3d, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, D3DFMT_X8R8G8B8, D3DUSAGE_DYNAMIC, D3DRTYPE_TEXTURE, D3DFMT_A8R8G8B8); + IDirect3D9_Release(d3d); + ok (hr == D3D_OK, "D3DFMT_A8R8G8B8 not supported\n"); + if (FAILED(hr)) return; + + hr = IDirect3DDevice9_CreateTexture(device, 64, 64, 1, 0, D3DFMT_A8R8G8B8, D3DPOOL_DEFAULT, &tex1, NULL); + ok (hr == D3D_OK, "Failed to create first texture (error code: %#x)\n", hr); + if (FAILED(hr)) return; + + hr = IDirect3DDevice9_CreateTexture(device, 32, 32, 1, 0, D3DFMT_A8R8G8B8, D3DPOOL_DEFAULT, &tex2, NULL); + ok (hr == D3D_OK, "Failed to create second texture (error code: %#x)\n", hr); + if (FAILED(hr)) { + IDirect3DTexture9_Release(tex1); + return; + } + + /* Test D3DXCreateSprite */ + hr = D3DXCreateSprite(device, NULL); + ok (hr == D3DERR_INVALIDCALL, "D3DXCreateSprite returned %#x, expected %#x\n", hr, D3DERR_INVALIDCALL); + + hr = D3DXCreateSprite(NULL, &sprite); + ok (hr == D3DERR_INVALIDCALL, "D3DXCreateSprite returned %#x, expected %#x\n", hr, D3DERR_INVALIDCALL); + + hr = D3DXCreateSprite(device, &sprite); + ok (hr == D3D_OK, "D3DXCreateSprite returned %#x, expected %#x\n", hr, D3D_OK); + + + /* Test ID3DXSprite_GetDevice */ + hr = ID3DXSprite_GetDevice(sprite, NULL); + ok (hr == D3DERR_INVALIDCALL, "GetDevice returned %#x, expected %#x\n", hr, D3DERR_INVALIDCALL); + + hr = ID3DXSprite_GetDevice(sprite, &cmpdev); /* cmpdev == NULL */ + ok (hr == D3D_OK, "GetDevice returned %#x, expected %#x\n", hr, D3D_OK); + + hr = ID3DXSprite_GetDevice(sprite, &cmpdev); /* cmpdev != NULL */ + ok (hr == D3D_OK, "GetDevice returned %#x, expected %#x\n", hr, D3D_OK); + + IDirect3DDevice9_Release(device); + IDirect3DDevice9_Release(device); + + + /* Test ID3DXSprite_GetTransform */ + hr = ID3DXSprite_GetTransform(sprite, NULL); + ok (hr == D3DERR_INVALIDCALL, "GetTransform returned %#x, expected %#x\n", hr, D3DERR_INVALIDCALL); + hr = ID3DXSprite_GetTransform(sprite, &mat); + ok (hr == D3D_OK, "GetTransform returned %#x, expected %#x\n", hr, D3D_OK); + if(SUCCEEDED(hr)) { + D3DXMATRIX identity; + D3DXMatrixIdentity(&identity); + check_mat(mat, identity); + } + + /* Test ID3DXSprite_SetTransform */ + /* Set a transform and test if it gets returned correctly */ + U(mat).m[0][0]=2.1f; U(mat).m[0][1]=6.5f; U(mat).m[0][2]=-9.6f; U(mat).m[0][3]=1.7f; + U(mat).m[1][0]=4.2f; U(mat).m[1][1]=-2.5f; U(mat).m[1][2]=2.1f; U(mat).m[1][3]=5.5f; + U(mat).m[2][0]=-2.6f; U(mat).m[2][1]=0.3f; U(mat).m[2][2]=8.6f; U(mat).m[2][3]=8.4f; + U(mat).m[3][0]=6.7f; U(mat).m[3][1]=-5.1f; U(mat).m[3][2]=6.1f; U(mat).m[3][3]=2.2f; + + hr = ID3DXSprite_SetTransform(sprite, NULL); + ok (hr == D3DERR_INVALIDCALL, "SetTransform returned %#x, expected %#x\n", hr, D3DERR_INVALIDCALL); + + hr = ID3DXSprite_SetTransform(sprite, &mat); + ok (hr == D3D_OK, "SetTransform returned %#x, expected %#x\n", hr, D3D_OK); + if(SUCCEEDED(hr)) { + hr=ID3DXSprite_GetTransform(sprite, &cmpmat); + if(SUCCEEDED(hr)) check_mat(cmpmat, mat); + else skip("GetTransform returned %#x\n", hr); + } + + /* Test ID3DXSprite_SetWorldViewLH/RH */ + todo_wine { + hr = ID3DXSprite_SetWorldViewLH(sprite, &mat, &mat); + ok (hr == D3D_OK, "SetWorldViewLH returned %#x, expected %#x\n", hr, D3D_OK); + hr = ID3DXSprite_SetWorldViewLH(sprite, NULL, &mat); + ok (hr == D3D_OK, "SetWorldViewLH returned %#x, expected %#x\n", hr, D3D_OK); + hr = ID3DXSprite_SetWorldViewLH(sprite, &mat, NULL); + ok (hr == D3D_OK, "SetWorldViewLH returned %#x, expected %#x\n", hr, D3D_OK); + hr = ID3DXSprite_SetWorldViewLH(sprite, NULL, NULL); + ok (hr == D3D_OK, "SetWorldViewLH returned %#x, expected %#x\n", hr, D3D_OK); + + hr = ID3DXSprite_SetWorldViewRH(sprite, &mat, &mat); + ok (hr == D3D_OK, "SetWorldViewRH returned %#x, expected %#x\n", hr, D3D_OK); + hr = ID3DXSprite_SetWorldViewRH(sprite, NULL, &mat); + ok (hr == D3D_OK, "SetWorldViewRH returned %#x, expected %#x\n", hr, D3D_OK); + hr = ID3DXSprite_SetWorldViewRH(sprite, &mat, NULL); + ok (hr == D3D_OK, "SetWorldViewRH returned %#x, expected %#x\n", hr, D3D_OK); + hr = ID3DXSprite_SetWorldViewRH(sprite, NULL, NULL); + ok (hr == D3D_OK, "SetWorldViewRH returned %#x, expected %#x\n", hr, D3D_OK); + } + IDirect3DDevice9_BeginScene(device); + + /* Test ID3DXSprite_Begin*/ + hr = ID3DXSprite_Begin(sprite, 0); + ok (hr == D3D_OK, "Begin returned %#x, expected %#x\n", hr, D3D_OK); + + IDirect3DDevice9_GetTransform(device, D3DTS_WORLD, &mat); + D3DXMatrixIdentity(&cmpmat); + check_mat(mat, cmpmat); + + IDirect3DDevice9_GetTransform(device, D3DTS_VIEW, &mat); + check_mat(mat, cmpmat); + + IDirect3DDevice9_GetTransform(device, D3DTS_PROJECTION, &mat); + IDirect3DDevice9_GetViewport(device, &vp); + D3DXMatrixOrthoOffCenterLH(&cmpmat, vp.X+0.5f, (float)vp.Width+vp.X+0.5f, (float)vp.Height+vp.Y+0.5f, vp.Y+0.5f, vp.MinZ, vp.MaxZ); + check_mat(mat, cmpmat); + + /* Test ID3DXSprite_Flush and ID3DXSprite_End */ + hr = ID3DXSprite_Flush(sprite); + ok (hr == D3D_OK, "Flush returned %#x, expected %#x\n", hr, D3D_OK); + + hr = ID3DXSprite_End(sprite); + ok (hr == D3D_OK, "End returned %#x, expected %#x\n", hr, D3D_OK); + + hr = ID3DXSprite_Flush(sprite); /* May not be called before next Begin */ + ok (hr == D3DERR_INVALIDCALL, "Flush returned %#x, expected %#x\n", hr, D3DERR_INVALIDCALL); + hr = ID3DXSprite_End(sprite); + ok (hr == D3DERR_INVALIDCALL, "End returned %#x, expected %#x\n", hr, D3DERR_INVALIDCALL); + + /* Test ID3DXSprite_Draw */ + hr = ID3DXSprite_Begin(sprite, 0); + ok (hr == D3D_OK, "Begin returned %#x, expected %#x\n", hr, D3D_OK); + + if(FAILED(hr)) skip("Couldn't ID3DXSprite_Begin, can't test ID3DXSprite_Draw\n"); + else { /* Feed the sprite batch */ + int texref1, texref2; + + SetRect(&rect, 53, 12, 142, 165); + pos.x = 2.2f; pos.y = 4.5f; pos.z = 5.1f; + center.x = 11.3f; center.y = 3.4f; center.z = 1.2f; + + texref1 = get_ref((IUnknown*)tex1); + texref2 = get_ref((IUnknown*)tex2); + + hr = ID3DXSprite_Draw(sprite, NULL, &rect, ¢er, &pos, D3DCOLOR_XRGB(255, 255, 255)); + ok (hr == D3DERR_INVALIDCALL, "Draw returned %#x, expected %#x\n", hr, D3DERR_INVALIDCALL); + + hr = ID3DXSprite_Draw(sprite, tex1, &rect, ¢er, &pos, D3DCOLOR_XRGB(255, 255, 255)); + ok (hr == D3D_OK, "Draw returned %#x, expected %#x\n", hr, D3D_OK); + hr = ID3DXSprite_Draw(sprite, tex2, &rect, ¢er, &pos, D3DCOLOR_XRGB( 3, 45, 66)); + ok (hr == D3D_OK, "Draw returned %#x, expected %#x\n", hr, D3D_OK); + hr = ID3DXSprite_Draw(sprite, tex1, NULL, ¢er, &pos, D3DCOLOR_XRGB(255, 255, 255)); + ok (hr == D3D_OK, "Draw returned %#x, expected %#x\n", hr, D3D_OK); + hr = ID3DXSprite_Draw(sprite, tex1, &rect, NULL, &pos, D3DCOLOR_XRGB(255, 255, 255)); + ok (hr == D3D_OK, "Draw returned %#x, expected %#x\n", hr, D3D_OK); + hr = ID3DXSprite_Draw(sprite, tex1, &rect, ¢er, NULL, D3DCOLOR_XRGB(255, 255, 255)); + ok (hr == D3D_OK, "Draw returned %#x, expected %#x\n", hr, D3D_OK); + hr = ID3DXSprite_Draw(sprite, tex1, NULL, NULL, NULL, 0); + ok (hr == D3D_OK, "Draw returned %#x, expected %#x\n", hr, D3D_OK); + + check_ref((IUnknown*)tex1, texref1+5); check_ref((IUnknown*)tex2, texref2+1); + hr = ID3DXSprite_Flush(sprite); + ok (hr == D3D_OK, "Flush returned %#x, expected %#x\n", hr, D3D_OK); + hr = ID3DXSprite_Flush(sprite); /* Flushing twice should work */ + ok (hr == D3D_OK, "Flush returned %#x, expected %#x\n", hr, D3D_OK); + check_ref((IUnknown*)tex1, texref1); check_ref((IUnknown*)tex2, texref2); + + hr = ID3DXSprite_End(sprite); + ok (hr == D3D_OK, "End returned %#x, expected %#x\n", hr, D3D_OK); + } + + /* Test ID3DXSprite_OnLostDevice and ID3DXSprite_OnResetDevice */ + /* Both can be called twice */ + hr = ID3DXSprite_OnLostDevice(sprite); + ok (hr == D3D_OK, "OnLostDevice returned %#x, expected %#x\n", hr, D3D_OK); + hr = ID3DXSprite_OnLostDevice(sprite); + ok (hr == D3D_OK, "OnLostDevice returned %#x, expected %#x\n", hr, D3D_OK); + hr = ID3DXSprite_OnResetDevice(sprite); + ok (hr == D3D_OK, "OnResetDevice returned %#x, expected %#x\n", hr, D3D_OK); + hr = ID3DXSprite_OnResetDevice(sprite); + ok (hr == D3D_OK, "OnResetDevice returned %#x, expected %#x\n", hr, D3D_OK); + + /* Make sure everything works like before */ + hr = ID3DXSprite_Begin(sprite, 0); + ok (hr == D3D_OK, "Begin returned %#x, expected %#x\n", hr, D3D_OK); + hr = ID3DXSprite_Draw(sprite, tex2, &rect, ¢er, &pos, D3DCOLOR_XRGB(255, 255, 255)); + ok (hr == D3D_OK, "Draw returned %#x, expected %#x\n", hr, D3D_OK); + hr = ID3DXSprite_Flush(sprite); + ok (hr == D3D_OK, "Flush returned %#x, expected %#x\n", hr, D3D_OK); + hr = ID3DXSprite_End(sprite); + ok (hr == D3D_OK, "End returned %#x, expected %#x\n", hr, D3D_OK); + + /* OnResetDevice makes the interface "forget" the Begin call */ + hr = ID3DXSprite_Begin(sprite, 0); + ok (hr == D3D_OK, "Begin returned %#x, expected %#x\n", hr, D3D_OK); + hr = ID3DXSprite_OnResetDevice(sprite); + ok (hr == D3D_OK, "OnResetDevice returned %#x, expected %#x\n", hr, D3D_OK); + hr = ID3DXSprite_End(sprite); + ok (hr == D3DERR_INVALIDCALL, "End returned %#x, expected %#x\n", hr, D3DERR_INVALIDCALL); + + IDirect3DDevice9_EndScene(device); + check_release((IUnknown*)sprite, 0); + check_release((IUnknown*)tex2, 0); + check_release((IUnknown*)tex1, 0); +} + +static void test_ID3DXFont(IDirect3DDevice9 *device) +{ + static const WCHAR testW[] = {'t','e','s','t',0}; + static const struct + { + int font_height; + unsigned int expected_size; + unsigned int expected_levels; + } + tests[] = + { + { 6, 128, 4 }, + { 8, 128, 4 }, + { 10, 256, 5 }, + { 12, 256, 5 }, + { 72, 256, 8 }, + }; + const unsigned int size = ARRAY_SIZE(testW); + D3DXFONT_DESCA desc; + ID3DXSprite *sprite; + int ref, i, height; + ID3DXFont *font; + HRESULT hr; + RECT rect; + + /* D3DXCreateFont */ + ref = get_ref((IUnknown*)device); + hr = D3DXCreateFontA(device, 12, 0, FW_DONTCARE, 0, FALSE, DEFAULT_CHARSET, OUT_DEFAULT_PRECIS, DEFAULT_QUALITY, DEFAULT_PITCH, "Arial", &font); + ok(hr == D3D_OK, "D3DXCreateFont returned %#x, expected %#x\n", hr, D3D_OK); + check_ref((IUnknown*)device, ref + 1); + check_release((IUnknown*)font, 0); + check_ref((IUnknown*)device, ref); + + hr = D3DXCreateFontA(device, 0, 0, FW_DONTCARE, 0, FALSE, DEFAULT_CHARSET, OUT_DEFAULT_PRECIS, DEFAULT_QUALITY, DEFAULT_PITCH, "Arial", &font); + ok(hr == D3D_OK, "D3DXCreateFont returned %#x, expected %#x\n", hr, D3D_OK); + ID3DXFont_Release(font); + + hr = D3DXCreateFontA(device, 12, 0, FW_DONTCARE, 0, FALSE, DEFAULT_CHARSET, OUT_DEFAULT_PRECIS, DEFAULT_QUALITY, DEFAULT_PITCH, NULL, &font); + ok(hr == D3D_OK, "D3DXCreateFont returned %#x, expected %#x\n", hr, D3D_OK); + ID3DXFont_Release(font); + + hr = D3DXCreateFontA(device, 12, 0, FW_DONTCARE, 0, FALSE, DEFAULT_CHARSET, OUT_DEFAULT_PRECIS, DEFAULT_QUALITY, DEFAULT_PITCH, "", &font); + ok(hr == D3D_OK, "D3DXCreateFont returned %#x, expected %#x\n", hr, D3D_OK); + ID3DXFont_Release(font); + + hr = D3DXCreateFontA(NULL, 12, 0, FW_DONTCARE, 0, FALSE, DEFAULT_CHARSET, OUT_DEFAULT_PRECIS, DEFAULT_QUALITY, DEFAULT_PITCH, "Arial", &font); + ok(hr == D3DERR_INVALIDCALL, "D3DXCreateFont returned %#x, expected %#x\n", hr, D3DERR_INVALIDCALL); + + hr = D3DXCreateFontA(device, 12, 0, FW_DONTCARE, 0, FALSE, DEFAULT_CHARSET, OUT_DEFAULT_PRECIS, DEFAULT_QUALITY, DEFAULT_PITCH, "Arial", NULL); + ok(hr == D3DERR_INVALIDCALL, "D3DXCreateFont returned %#x, expected %#x\n", hr, D3DERR_INVALIDCALL); + + hr = D3DXCreateFontA(NULL, 12, 0, FW_DONTCARE, 0, FALSE, DEFAULT_CHARSET, OUT_DEFAULT_PRECIS, DEFAULT_QUALITY, DEFAULT_PITCH, "Arial", NULL); + ok(hr == D3DERR_INVALIDCALL, "D3DXCreateFont returned %#x, expected %#x\n", hr, D3DERR_INVALIDCALL); + + + /* D3DXCreateFontIndirect */ + desc.Height = 12; + desc.Width = 0; + desc.Weight = FW_DONTCARE; + desc.MipLevels = 0; + desc.Italic = FALSE; + desc.CharSet = DEFAULT_CHARSET; + desc.OutputPrecision = OUT_DEFAULT_PRECIS; + desc.Quality = DEFAULT_QUALITY; + desc.PitchAndFamily = DEFAULT_PITCH; + strcpy(desc.FaceName, "Arial"); + hr = D3DXCreateFontIndirectA(device, &desc, &font); + ok(hr == D3D_OK, "D3DXCreateFontIndirect returned %#x, expected %#x\n", hr, D3D_OK); + ID3DXFont_Release(font); + + hr = D3DXCreateFontIndirectA(NULL, &desc, &font); + ok(hr == D3DERR_INVALIDCALL, "D3DXCreateFontIndirect returned %#x, expected %#x\n", hr, D3DERR_INVALIDCALL); + + hr = D3DXCreateFontIndirectA(device, NULL, &font); + ok(hr == D3DERR_INVALIDCALL, "D3DXCreateFontIndirect returned %#x, expected %#x\n", hr, D3DERR_INVALIDCALL); + + hr = D3DXCreateFontIndirectA(device, &desc, NULL); + ok(hr == D3DERR_INVALIDCALL, "D3DXCreateFontIndirect returned %#x, expected %#x\n", hr, D3DERR_INVALIDCALL); + + + /* ID3DXFont_GetDevice */ + hr = D3DXCreateFontA(device, 12, 0, FW_DONTCARE, 0, FALSE, DEFAULT_CHARSET, OUT_DEFAULT_PRECIS, DEFAULT_QUALITY, DEFAULT_PITCH, "Arial", &font); + if(SUCCEEDED(hr)) { + IDirect3DDevice9 *bufdev; + + hr = ID3DXFont_GetDevice(font, NULL); + ok(hr == D3DERR_INVALIDCALL, "ID3DXFont_GetDevice returned %#x, expected %#x\n", hr, D3DERR_INVALIDCALL); + + ref = get_ref((IUnknown*)device); + hr = ID3DXFont_GetDevice(font, &bufdev); + ok(hr == D3D_OK, "ID3DXFont_GetDevice returned %#x, expected %#x\n", hr, D3D_OK); + check_release((IUnknown*)bufdev, ref); + + ID3DXFont_Release(font); + } else skip("Failed to create a ID3DXFont object\n"); + + + /* ID3DXFont_GetDesc */ + hr = D3DXCreateFontA(device, 12, 8, FW_BOLD, 2, TRUE, ANSI_CHARSET, OUT_RASTER_PRECIS, ANTIALIASED_QUALITY, VARIABLE_PITCH, "Arial", &font); + if(SUCCEEDED(hr)) { + hr = ID3DXFont_GetDescA(font, NULL); + ok(hr == D3DERR_INVALIDCALL, "ID3DXFont_GetDevice returned %#x, expected %#x\n", hr, D3DERR_INVALIDCALL); + + hr = ID3DXFont_GetDescA(font, &desc); + ok(hr == D3D_OK, "ID3DXFont_GetDevice returned %#x, expected %#x\n", hr, D3D_OK); + + ok(desc.Height == 12, "ID3DXFont_GetDesc returned font height %d, expected %d\n", desc.Height, 12); + ok(desc.Width == 8, "ID3DXFont_GetDesc returned font width %d, expected %d\n", desc.Width, 8); + ok(desc.Weight == FW_BOLD, "ID3DXFont_GetDesc returned font weight %d, expected %d\n", desc.Weight, FW_BOLD); + ok(desc.MipLevels == 2, "ID3DXFont_GetDesc returned font miplevels %d, expected %d\n", desc.MipLevels, 2); + ok(desc.Italic == TRUE, "ID3DXFont_GetDesc says Italic was %d, but Italic should be %d\n", desc.Italic, TRUE); + ok(desc.CharSet == ANSI_CHARSET, "ID3DXFont_GetDesc returned font charset %d, expected %d\n", desc.CharSet, ANSI_CHARSET); + ok(desc.OutputPrecision == OUT_RASTER_PRECIS, "ID3DXFont_GetDesc returned an output precision of %d, expected %d\n", desc.OutputPrecision, OUT_RASTER_PRECIS); + ok(desc.Quality == ANTIALIASED_QUALITY, "ID3DXFont_GetDesc returned font quality %d, expected %d\n", desc.Quality, ANTIALIASED_QUALITY); + ok(desc.PitchAndFamily == VARIABLE_PITCH, "ID3DXFont_GetDesc returned pitch and family %d, expected %d\n", desc.PitchAndFamily, VARIABLE_PITCH); + ok(strcmp(desc.FaceName, "Arial") == 0, "ID3DXFont_GetDesc returned facename \"%s\", expected \"%s\"\n", desc.FaceName, "Arial"); + + ID3DXFont_Release(font); + } else skip("Failed to create a ID3DXFont object\n"); + + + /* ID3DXFont_GetDC + ID3DXFont_GetTextMetrics */ + hr = D3DXCreateFontA(device, 12, 0, FW_DONTCARE, 0, FALSE, DEFAULT_CHARSET, OUT_DEFAULT_PRECIS, DEFAULT_QUALITY, DEFAULT_PITCH, "Arial", &font); + if(SUCCEEDED(hr)) { + HDC hdc; + + hdc = ID3DXFont_GetDC(font); + ok(hdc != NULL, "ID3DXFont_GetDC returned an invalid handle\n"); + if(hdc) { + TEXTMETRICA metrics, expmetrics; + BOOL ret; + + ret = ID3DXFont_GetTextMetricsA(font, &metrics); + ok(ret, "ID3DXFont_GetTextMetricsA failed\n"); + ret = GetTextMetricsA(hdc, &expmetrics); + ok(ret, "GetTextMetricsA failed\n"); + + ok(metrics.tmHeight == expmetrics.tmHeight, "Returned height %d, expected %d\n", metrics.tmHeight, expmetrics.tmHeight); + ok(metrics.tmAscent == expmetrics.tmAscent, "Returned ascent %d, expected %d\n", metrics.tmAscent, expmetrics.tmAscent); + ok(metrics.tmDescent == expmetrics.tmDescent, "Returned descent %d, expected %d\n", metrics.tmDescent, expmetrics.tmDescent); + ok(metrics.tmInternalLeading == expmetrics.tmInternalLeading, "Returned internal leading %d, expected %d\n", metrics.tmInternalLeading, expmetrics.tmInternalLeading); + ok(metrics.tmExternalLeading == expmetrics.tmExternalLeading, "Returned external leading %d, expected %d\n", metrics.tmExternalLeading, expmetrics.tmExternalLeading); + ok(metrics.tmAveCharWidth == expmetrics.tmAveCharWidth, "Returned average char width %d, expected %d\n", metrics.tmAveCharWidth, expmetrics.tmAveCharWidth); + ok(metrics.tmMaxCharWidth == expmetrics.tmMaxCharWidth, "Returned maximum char width %d, expected %d\n", metrics.tmMaxCharWidth, expmetrics.tmMaxCharWidth); + ok(metrics.tmWeight == expmetrics.tmWeight, "Returned weight %d, expected %d\n", metrics.tmWeight, expmetrics.tmWeight); + ok(metrics.tmOverhang == expmetrics.tmOverhang, "Returned overhang %d, expected %d\n", metrics.tmOverhang, expmetrics.tmOverhang); + ok(metrics.tmDigitizedAspectX == expmetrics.tmDigitizedAspectX, "Returned digitized x aspect %d, expected %d\n", metrics.tmDigitizedAspectX, expmetrics.tmDigitizedAspectX); + ok(metrics.tmDigitizedAspectY == expmetrics.tmDigitizedAspectY, "Returned digitized y aspect %d, expected %d\n", metrics.tmDigitizedAspectY, expmetrics.tmDigitizedAspectY); + ok(metrics.tmFirstChar == expmetrics.tmFirstChar, "Returned first char %d, expected %d\n", metrics.tmFirstChar, expmetrics.tmFirstChar); + ok(metrics.tmLastChar == expmetrics.tmLastChar, "Returned last char %d, expected %d\n", metrics.tmLastChar, expmetrics.tmLastChar); + ok(metrics.tmDefaultChar == expmetrics.tmDefaultChar, "Returned default char %d, expected %d\n", metrics.tmDefaultChar, expmetrics.tmDefaultChar); + ok(metrics.tmBreakChar == expmetrics.tmBreakChar, "Returned break char %d, expected %d\n", metrics.tmBreakChar, expmetrics.tmBreakChar); + ok(metrics.tmItalic == expmetrics.tmItalic, "Returned italic %d, expected %d\n", metrics.tmItalic, expmetrics.tmItalic); + ok(metrics.tmUnderlined == expmetrics.tmUnderlined, "Returned underlined %d, expected %d\n", metrics.tmUnderlined, expmetrics.tmUnderlined); + ok(metrics.tmStruckOut == expmetrics.tmStruckOut, "Returned struck out %d, expected %d\n", metrics.tmStruckOut, expmetrics.tmStruckOut); + ok(metrics.tmPitchAndFamily == expmetrics.tmPitchAndFamily, "Returned pitch and family %d, expected %d\n", metrics.tmPitchAndFamily, expmetrics.tmPitchAndFamily); + ok(metrics.tmCharSet == expmetrics.tmCharSet, "Returned charset %d, expected %d\n", metrics.tmCharSet, expmetrics.tmCharSet); + } + ID3DXFont_Release(font); + } else skip("Failed to create a ID3DXFont object\n"); + + + /* ID3DXFont_PreloadText */ + hr = D3DXCreateFontA(device, 12, 0, FW_DONTCARE, 0, FALSE, DEFAULT_CHARSET, OUT_DEFAULT_PRECIS, DEFAULT_QUALITY, DEFAULT_PITCH, "Arial", &font); + if(SUCCEEDED(hr)) { + todo_wine { + hr = ID3DXFont_PreloadTextA(font, NULL, -1); + ok(hr == D3DERR_INVALIDCALL, "ID3DXFont_PreloadTextA returned %#x, expected %#x\n", hr, D3DERR_INVALIDCALL); + hr = ID3DXFont_PreloadTextA(font, NULL, 0); + ok(hr == D3D_OK, "ID3DXFont_PreloadTextA returned %#x, expected %#x\n", hr, D3D_OK); + hr = ID3DXFont_PreloadTextA(font, NULL, 1); + ok(hr == D3DERR_INVALIDCALL, "ID3DXFont_PreloadTextA returned %#x, expected %#x\n", hr, D3DERR_INVALIDCALL); + hr = ID3DXFont_PreloadTextA(font, "test", -1); + ok(hr == D3D_OK, "ID3DXFont_PreloadTextA returned %#x, expected %#x\n", hr, D3D_OK); + + hr = ID3DXFont_PreloadTextW(font, NULL, -1); + ok(hr == D3DERR_INVALIDCALL, "ID3DXFont_PreloadTextW returned %#x, expected %#x\n", hr, D3DERR_INVALIDCALL); + hr = ID3DXFont_PreloadTextW(font, NULL, 0); + ok(hr == D3D_OK, "ID3DXFont_PreloadTextW returned %#x, expected %#x\n", hr, D3D_OK); + hr = ID3DXFont_PreloadTextW(font, NULL, 1); + ok(hr == D3DERR_INVALIDCALL, "ID3DXFont_PreloadTextW returned %#x, expected %#x\n", hr, D3DERR_INVALIDCALL); + hr = ID3DXFont_PreloadTextW(font, testW, -1); + ok(hr == D3D_OK, "ID3DXFont_PreloadTextW returned %#x, expected %#x\n", hr, D3D_OK); + } + + check_release((IUnknown*)font, 0); + } else skip("Failed to create a ID3DXFont object\n"); + + + /* ID3DXFont_GetGlyphData, ID3DXFont_PreloadGlyphs, ID3DXFont_PreloadCharacters */ + hr = D3DXCreateFontA(device, 12, 0, FW_DONTCARE, 0, FALSE, DEFAULT_CHARSET, OUT_DEFAULT_PRECIS, DEFAULT_QUALITY, DEFAULT_PITCH, "Arial", &font); + if(SUCCEEDED(hr)) { + char c; + HDC hdc; + DWORD ret; + HRESULT hr; + RECT blackbox; + POINT cellinc; + IDirect3DTexture9 *texture; + + hdc = ID3DXFont_GetDC(font); + + todo_wine { + hr = ID3DXFont_GetGlyphData(font, 0, NULL, &blackbox, &cellinc); + ok(hr == D3D_OK, "ID3DXFont_GetGlyphData returned %#x, expected %#x\n", hr, D3D_OK); + hr = ID3DXFont_GetGlyphData(font, 0, &texture, NULL, &cellinc); + if(SUCCEEDED(hr)) check_release((IUnknown*)texture, 1); + ok(hr == D3D_OK, "ID3DXFont_GetGlyphData returned %#x, expected %#x\n", hr, D3D_OK); + hr = ID3DXFont_GetGlyphData(font, 0, &texture, &blackbox, NULL); + if(SUCCEEDED(hr)) check_release((IUnknown*)texture, 1); + ok(hr == D3D_OK, "ID3DXFont_GetGlyphData returned %#x, expected %#x\n", hr, D3D_OK); + } + hr = ID3DXFont_PreloadCharacters(font, 'b', 'a'); + ok(hr == D3D_OK, "ID3DXFont_PreloadCharacters returned %#x, expected %#x\n", hr, D3D_OK); + hr = ID3DXFont_PreloadGlyphs(font, 1, 0); + todo_wine ok(hr == D3D_OK, "ID3DXFont_PreloadGlyphs returned %#x, expected %#x\n", hr, D3D_OK); + + hr = ID3DXFont_PreloadCharacters(font, 'a', 'a'); + ok(hr == D3D_OK, "ID3DXFont_PreloadCharacters returned %#x, expected %#x\n", hr, D3D_OK); + + for(c = 'b'; c <= 'z'; c++) { + WORD glyph; + + ret = GetGlyphIndicesA(hdc, &c, 1, &glyph, 0); + ok(ret != GDI_ERROR, "GetGlyphIndicesA failed\n"); + + hr = ID3DXFont_GetGlyphData(font, glyph, &texture, &blackbox, &cellinc); + todo_wine ok(hr == D3D_OK, "ID3DXFont_GetGlyphData returned %#x, expected %#x\n", hr, D3D_OK); + if(SUCCEEDED(hr)) { + DWORD levels; + D3DSURFACE_DESC desc; + + levels = IDirect3DTexture9_GetLevelCount(texture); + ok(levels == 5, "Got levels %u, expected %u\n", levels, 5); + hr = IDirect3DTexture9_GetLevelDesc(texture, 0, &desc); + ok(hr == D3D_OK, "IDirect3DTexture9_GetLevelDesc failed\n"); + ok(desc.Format == D3DFMT_A8R8G8B8, "Got format %#x, expected %#x\n", desc.Format, D3DFMT_A8R8G8B8); + ok(desc.Usage == 0, "Got usage %#x, expected %#x\n", desc.Usage, 0); + ok(desc.Width == 256, "Got width %u, expected %u\n", desc.Width, 256); + ok(desc.Height == 256, "Got height %u, expected %u\n", desc.Height, 256); + ok(desc.Pool == D3DPOOL_MANAGED, "Got pool %u, expected %u\n", desc.Pool, D3DPOOL_MANAGED); + + check_release((IUnknown*)texture, 1); + } + } + + hr = ID3DXFont_PreloadCharacters(font, 'a', 'z'); + ok(hr == D3D_OK, "ID3DXFont_PreloadCharacters returned %#x, expected %#x\n", hr, D3D_OK); + + check_release((IUnknown*)font, 0); + } else skip("Failed to create a ID3DXFont object\n"); + + for (i = 0; i < ARRAY_SIZE(tests); ++i) + { + HDC hdc; + DWORD ret; + HRESULT hr; + WORD glyph; + char c = 'a'; + IDirect3DTexture9 *texture; + + hr = D3DXCreateFontA(device, tests[i].font_height, 0, FW_DONTCARE, 0, FALSE, DEFAULT_CHARSET, + OUT_DEFAULT_PRECIS, DEFAULT_QUALITY, DEFAULT_PITCH, "Arial", &font); + if(FAILED(hr)) { + skip("Failed to create a ID3DXFont object\n"); + continue; + } + + hdc = ID3DXFont_GetDC(font); + + ret = GetGlyphIndicesA(hdc, &c, 1, &glyph, 0); + ok(ret != GDI_ERROR, "GetGlyphIndicesA failed\n"); + + hr = ID3DXFont_GetGlyphData(font, glyph, &texture, NULL, NULL); + todo_wine ok(hr == D3D_OK, "ID3DXFont_GetGlyphData returned %#x, expected %#x\n", hr, D3D_OK); + if(SUCCEEDED(hr)) { + DWORD levels; + D3DSURFACE_DESC desc; + + levels = IDirect3DTexture9_GetLevelCount(texture); + ok(levels == tests[i].expected_levels, "Got levels %u, expected %u\n", + levels, tests[i].expected_levels); + hr = IDirect3DTexture9_GetLevelDesc(texture, 0, &desc); + ok(hr == D3D_OK, "IDirect3DTexture9_GetLevelDesc failed\n"); + ok(desc.Format == D3DFMT_A8R8G8B8, "Got format %#x, expected %#x\n", desc.Format, D3DFMT_A8R8G8B8); + ok(desc.Usage == 0, "Got usage %#x, expected %#x\n", desc.Usage, 0); + ok(desc.Width == tests[i].expected_size, "Got width %u, expected %u\n", + desc.Width, tests[i].expected_size); + ok(desc.Height == tests[i].expected_size, "Got height %u, expected %u\n", + desc.Height, tests[i].expected_size); + ok(desc.Pool == D3DPOOL_MANAGED, "Got pool %u, expected %u\n", desc.Pool, D3DPOOL_MANAGED); + + IDirect3DTexture9_Release(texture); + } + + /* ID3DXFontImpl_DrawText */ + D3DXCreateSprite(device, &sprite); + SetRect(&rect, 0, 0, 640, 480); + + IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xff000000, 1.0f, 0); + + IDirect3DDevice9_BeginScene(device); + hr = ID3DXSprite_Begin(sprite, D3DXSPRITE_ALPHABLEND); + ok (hr == D3D_OK, "Got unexpected hr %#x.\n", hr); + + todo_wine + { + height = ID3DXFont_DrawTextW(font, sprite, testW, -1, &rect, DT_TOP, 0xffffffff); + ok(height == tests[i].font_height, "Got unexpected height %u.\n", height); + height = ID3DXFont_DrawTextW(font, sprite, testW, size, &rect, DT_TOP, 0xffffffff); + ok(height == tests[i].font_height, "Got unexpected height %u.\n", height); + height = ID3DXFont_DrawTextW(font, sprite, testW, size, &rect, DT_RIGHT, 0xffffffff); + ok(height == tests[i].font_height, "Got unexpected height %u.\n", height); + height = ID3DXFont_DrawTextW(font, sprite, testW, size, &rect, DT_LEFT | DT_NOCLIP, + 0xffffffff); + ok(height == tests[i].font_height, "Got unexpected height %u.\n", height); + } + + SetRectEmpty(&rect); + height = ID3DXFont_DrawTextW(font, sprite, testW, size, &rect, + DT_LEFT | DT_CALCRECT, 0xffffffff); + todo_wine ok(height == tests[i].font_height, "Got unexpected height %u.\n", height); + ok(!rect.left, "Got unexpected rect left %d.\n", rect.left); + ok(!rect.top, "Got unexpected rect top %d.\n", rect.top); + todo_wine ok(rect.right, "Got unexpected rect right %d.\n", rect.right); + todo_wine ok(rect.bottom == tests[i].font_height, "Got unexpected rect bottom %d.\n", rect.bottom); + + hr = ID3DXSprite_End(sprite); + ok (hr == D3D_OK, "Got unexpected hr %#x.\n", hr); + IDirect3DDevice9_EndScene(device); + ID3DXSprite_Release(sprite); + + ID3DXFont_Release(font); + } +} + +static void test_D3DXCreateRenderToSurface(IDirect3DDevice9 *device) +{ + int i; + HRESULT hr; + ULONG ref_count; + D3DXRTS_DESC desc; + ID3DXRenderToSurface *render = (void *)0xdeadbeef; + static const D3DXRTS_DESC tests[] = + { + { 0, 256, D3DFMT_A8R8G8B8, FALSE, D3DFMT_UNKNOWN }, + { 256, 0, D3DFMT_A8R8G8B8, FALSE, D3DFMT_UNKNOWN }, + { 256, 0, D3DFMT_A8R8G8B8, FALSE, D3DFMT_D24S8 }, + { 256, 256, D3DFMT_UNKNOWN, FALSE, D3DFMT_R8G8B8 }, + { 0, 0, D3DFMT_UNKNOWN, FALSE, D3DFMT_UNKNOWN }, + { -1, -1, MAKEFOURCC('B','A','D','F'), TRUE, MAKEFOURCC('B','A','D','F') } + }; + + hr = D3DXCreateRenderToSurface(NULL /* device */, 256, 256, D3DFMT_A8R8G8B8, FALSE, D3DFMT_UNKNOWN, &render); + ok(hr == D3DERR_INVALIDCALL, "D3DXCreateRenderToSurface returned %#x, expected %#x\n", hr, D3DERR_INVALIDCALL); + ok(render == (void *)0xdeadbeef, "Got %p, expected %p\n", render, (void *)0xdeadbeef); + + hr = D3DXCreateRenderToSurface(device, 256, 256, D3DFMT_A8R8G8B8, FALSE, D3DFMT_UNKNOWN, NULL /* out */); + ok(hr == D3DERR_INVALIDCALL, "D3DXCreateRenderToSurface returned %#x, expected %#x\n", hr, D3DERR_INVALIDCALL); + + for (i = 0; i < ARRAY_SIZE(tests); i++) + { + hr = D3DXCreateRenderToSurface(device, tests[i].Width, tests[i].Height, tests[i].Format, tests[i].DepthStencil, + tests[i].DepthStencilFormat, &render); + ok(hr == D3D_OK, "%d: D3DXCreateRenderToSurface returned %#x, expected %#x\n", i, hr, D3D_OK); + if (SUCCEEDED(hr)) + { + hr = ID3DXRenderToSurface_GetDesc(render, &desc); + ok(hr == D3D_OK, "%d: GetDesc failed %#x\n", i, hr); + if (SUCCEEDED(hr)) + { + ok(desc.Width == tests[i].Width, "%d: Got width %u, expected %u\n", i, desc.Width, tests[i].Width); + ok(desc.Height == tests[i].Height, "%d: Got height %u, expected %u\n", i, desc.Height, tests[i].Height); + ok(desc.Format == tests[i].Format, "%d: Got format %#x, expected %#x\n", i, desc.Format, tests[i].Format); + ok(desc.DepthStencil == tests[i].DepthStencil, "%d: Got depth stencil %d, expected %d\n", + i, desc.DepthStencil, tests[i].DepthStencil); + ok(desc.DepthStencilFormat == tests[i].DepthStencilFormat, "%d: Got depth stencil format %#x, expected %#x\n", + i, desc.DepthStencilFormat, tests[i].DepthStencilFormat); + } + ID3DXRenderToSurface_Release(render); + } + } + + /* check device ref count */ + ref_count = get_ref((IUnknown *)device); + hr = D3DXCreateRenderToSurface(device, 0, 0, D3DFMT_UNKNOWN, FALSE, D3DFMT_UNKNOWN, &render); + check_ref((IUnknown *)device, ref_count + 1); + if (SUCCEEDED(hr)) ID3DXRenderToSurface_Release(render); +} + +/* runs a set of tests for the ID3DXRenderToSurface interface created with given parameters */ +static void check_ID3DXRenderToSurface(IDirect3DDevice9 *device, UINT width, UINT height, D3DFORMAT format, + BOOL depth_stencil, D3DFORMAT depth_stencil_format, BOOL render_target) +{ + HRESULT hr; + D3DFORMAT fmt; + HRESULT expected_value; + IDirect3DSurface9 *surface; + ID3DXRenderToSurface *render; + D3DVIEWPORT9 viewport = { 0, 0, width, height, 0.0, 1.0 }; + + hr = D3DXCreateRenderToSurface(device, width, height, format, depth_stencil, depth_stencil_format, &render); + if (FAILED(hr)) + { + skip("Failed to create ID3DXRenderToSurface\n"); + return; + } + + if (render_target) + hr = IDirect3DDevice9_CreateRenderTarget(device, width, height, format, D3DMULTISAMPLE_NONE, 0, FALSE, &surface, NULL); + else + hr = IDirect3DDevice9_CreateOffscreenPlainSurface(device, width, height, format, D3DPOOL_DEFAULT, &surface, NULL); + if (FAILED(hr)) + { + skip("Failed to create surface\n"); + ID3DXRenderToSurface_Release(render); + return; + } + + /* viewport */ + hr = ID3DXRenderToSurface_BeginScene(render, surface, &viewport); + ok(hr == D3D_OK, "ID3DXRenderToSurface::BeginScene returned %#x, expected %#x\n", hr, D3D_OK); + check_ref((IUnknown *)surface, 2); + if (SUCCEEDED(hr)) ID3DXRenderToSurface_EndScene(render, D3DX_FILTER_NONE); + + /* invalid viewport */ + viewport.Width = 2 * width; + hr = ID3DXRenderToSurface_BeginScene(render, surface, &viewport); + ok(hr == D3DERR_INVALIDCALL, "ID3DXRenderToSurface::BeginScene returned %#x, expected %#x\n", hr, D3DERR_INVALIDCALL); + + viewport.X = width / 2; + viewport.Width = width; + hr = ID3DXRenderToSurface_BeginScene(render, surface, &viewport); + ok(hr == D3DERR_INVALIDCALL, "ID3DXRenderToSurface::BeginScene returned %#x, expected %#x\n", hr, D3DERR_INVALIDCALL); + + viewport.X = width; + viewport.Width = width; + hr = ID3DXRenderToSurface_BeginScene(render, surface, &viewport); + ok(hr == D3DERR_INVALIDCALL, "ID3DXRenderToSurface::BeginScene returned %#x, expected %#x\n", hr, D3DERR_INVALIDCALL); + + /* rendering to a part of a surface is only allowed for render target surfaces */ + expected_value = render_target ? D3D_OK : D3DERR_INVALIDCALL; + + viewport.X = 0; + viewport.Width = width / 2; + hr = ID3DXRenderToSurface_BeginScene(render, surface, &viewport); + ok(hr == expected_value, "ID3DXRenderToSurface::BeginScene returned %#x, expected %#x\n", hr, expected_value); + if (SUCCEEDED(hr)) ID3DXRenderToSurface_EndScene(render, D3DX_FILTER_NONE); + + viewport.X = width / 2; + viewport.Width = width - width / 2; + hr = ID3DXRenderToSurface_BeginScene(render, surface, &viewport); + ok(hr == expected_value, "ID3DXRenderToSurface::BeginScene returned %#x, expected %#x\n", hr, expected_value); + if (SUCCEEDED(hr)) ID3DXRenderToSurface_EndScene(render, D3DX_FILTER_NONE); + + check_release((IUnknown *)surface, 0); + + /* surfaces with different sizes */ + hr = IDirect3DDevice9_CreateOffscreenPlainSurface(device, width / 2, width / 2, format, D3DPOOL_DEFAULT, &surface, NULL); + if (FAILED(hr)) + { + skip("Failed to create surface\n"); + ID3DXRenderToSurface_Release(render); + return; + } + hr = ID3DXRenderToSurface_BeginScene(render, surface, NULL); + ok(hr == D3DERR_INVALIDCALL, "ID3DXRenderToSurface::BeginScene returned %#x, expected %#x\n", hr, D3DERR_INVALIDCALL); + check_release((IUnknown *)surface, 0); + + hr = IDirect3DDevice9_CreateOffscreenPlainSurface(device, 2 * width, 2 * height, format, D3DPOOL_DEFAULT, &surface, NULL); + if (FAILED(hr)) + { + skip("Failed to create surface\n"); + ID3DXRenderToSurface_Release(render); + return; + } + hr = ID3DXRenderToSurface_BeginScene(render, surface, NULL); + ok(hr == D3DERR_INVALIDCALL, "ID3DXRenderToSurface::BeginScene returned %#x, expected %#x\n", hr, D3DERR_INVALIDCALL); + viewport.X = 0; + viewport.Y = 0; + viewport.Width = width; + viewport.Height = height; + hr = ID3DXRenderToSurface_BeginScene(render, surface, &viewport); + ok(hr == D3DERR_INVALIDCALL, "ID3DXRenderToSurface::BeginScene returned %#x, expected %#x\n", hr, D3DERR_INVALIDCALL); + check_release((IUnknown *)surface, 0); + + /* surfaces with different formats */ + for (fmt = D3DFMT_A8R8G8B8; fmt <= D3DFMT_X8R8G8B8; fmt++) + { + HRESULT expected_result = (fmt != format) ? D3DERR_INVALIDCALL : D3D_OK; + + hr = IDirect3DDevice9_CreateOffscreenPlainSurface(device, width, height, fmt, D3DPOOL_DEFAULT, &surface, NULL); + if (FAILED(hr)) + { + skip("Failed to create surface\n"); + continue; + } + + hr = ID3DXRenderToSurface_BeginScene(render, surface, NULL); + ok(hr == expected_result, "ID3DXRenderToSurface::BeginScene returned %#x, expected %#x\n", hr, expected_result); + + if (SUCCEEDED(hr)) ID3DXRenderToSurface_EndScene(render, D3DX_FILTER_NONE); + check_release((IUnknown *)surface, 0); + } + + check_release((IUnknown *)render, 0); +} + +struct device_state +{ + IDirect3DSurface9 *render_target; + IDirect3DSurface9 *depth_stencil; + D3DVIEWPORT9 viewport; +}; + +static void release_device_state(struct device_state *state) +{ + if (state->render_target) IDirect3DSurface9_Release(state->render_target); + if (state->depth_stencil) IDirect3DSurface9_Release(state->depth_stencil); + memset(state, 0, sizeof(*state)); +} + +static HRESULT retrieve_device_state(IDirect3DDevice9 *device, struct device_state *state) +{ + HRESULT hr; + + memset(state, 0, sizeof(*state)); + + hr = IDirect3DDevice9_GetRenderTarget(device, 0, &state->render_target); + if (FAILED(hr)) goto cleanup; + + hr = IDirect3DDevice9_GetDepthStencilSurface(device, &state->depth_stencil); + if (hr == D3DERR_NOTFOUND) + state->depth_stencil = NULL; + else if (FAILED(hr)) + goto cleanup; + + hr = IDirect3DDevice9_GetViewport(device, &state->viewport); + if (SUCCEEDED(hr)) return hr; + +cleanup: + release_device_state(state); + return hr; +} + +static HRESULT apply_device_state(IDirect3DDevice9 *device, struct device_state *state) +{ + HRESULT hr; + HRESULT status = D3D_OK; + + hr = IDirect3DDevice9_SetRenderTarget(device, 0, state->render_target); + if (FAILED(hr)) status = hr; + + hr = IDirect3DDevice9_SetDepthStencilSurface(device, state->depth_stencil); + if (FAILED(hr)) status = hr; + + hr = IDirect3DDevice9_SetViewport(device, &state->viewport); + if (FAILED(hr)) status = hr; + + return status; +} + +static void compare_device_state(struct device_state *state1, struct device_state *state2, BOOL equal) +{ + BOOL cmp; + const char *message = equal ? "differs" : "is the same"; + + cmp = state1->render_target == state2->render_target; + ok(equal ? cmp : !cmp, "Render target %s %p, %p\n", message, state1->render_target, state2->render_target); + + cmp = state1->depth_stencil == state2->depth_stencil; + ok(equal ? cmp : !cmp, "Depth stencil surface %s %p, %p\n", message, state1->depth_stencil, state2->depth_stencil); + + cmp = state1->viewport.X == state2->viewport.X && state1->viewport.Y == state2->viewport.Y + && state1->viewport.Width == state2->viewport.Width && state1->viewport.Height == state2->viewport.Height; + ok(equal ? cmp : !cmp, "Viewport %s (%u, %u, %u, %u), (%u, %u, %u, %u)\n", message, + state1->viewport.X, state1->viewport.Y, state1->viewport.Width, state1->viewport.Height, + state2->viewport.X, state2->viewport.Y, state2->viewport.Width, state2->viewport.Height); +} + +static void test_ID3DXRenderToSurface_device_state(IDirect3DDevice9 *device) +{ + HRESULT hr; + IDirect3DSurface9 *surface = NULL; + ID3DXRenderToSurface *render = NULL; + struct device_state pre_state; + struct device_state current_state; + IDirect3DSurface9 *depth_stencil_surface; + + /* make sure there is a depth stencil surface present */ + hr = IDirect3DDevice9_GetDepthStencilSurface(device, &depth_stencil_surface); + if (SUCCEEDED(hr)) + { + IDirect3DSurface9_Release(depth_stencil_surface); + depth_stencil_surface = NULL; + } + else if (hr == D3DERR_NOTFOUND) + { + hr = IDirect3DDevice9_CreateDepthStencilSurface(device, 256, 256, D3DFMT_D24X8, + D3DMULTISAMPLE_NONE, 0, TRUE, &depth_stencil_surface, NULL); + if (SUCCEEDED(hr)) IDirect3DDevice9_SetDepthStencilSurface(device, depth_stencil_surface); + } + + if (FAILED(hr)) + { + skip("Failed to create depth stencil surface\n"); + return; + } + + hr = IDirect3DDevice9_CreateRenderTarget(device, 256, 256, D3DFMT_A8R8G8B8, D3DMULTISAMPLE_NONE, 0, + FALSE, &surface, NULL); + if (FAILED(hr)) + { + skip("Failed to create render target\n"); + goto cleanup; + } + + hr = retrieve_device_state(device, &pre_state); + ok(SUCCEEDED(hr), "Failed to retrieve device state\n"); + + hr = D3DXCreateRenderToSurface(device, 256, 256, D3DFMT_A8R8G8B8, TRUE, D3DFMT_D24X8, &render); + ok(hr == D3D_OK, "D3DXCreateRenderToSurface returned %#x, expected %#x\n", hr, D3D_OK); + if (SUCCEEDED(hr)) + { + hr = ID3DXRenderToSurface_BeginScene(render, surface, NULL); + ok(hr == D3D_OK, "ID3DXRenderToSurface::BeginScene returned %#x, expected %#x\n", hr, D3D_OK); + + hr = retrieve_device_state(device, ¤t_state); + ok(SUCCEEDED(hr), "Failed to retrieve device state\n"); + compare_device_state(¤t_state, &pre_state, FALSE); + release_device_state(¤t_state); + + hr = ID3DXRenderToSurface_EndScene(render, D3DX_FILTER_NONE); + ok(hr == D3D_OK, "ID3DXRenderToSurface::EndScene returned %#x, expected %#x\n", hr, D3D_OK); + + hr = retrieve_device_state(device, ¤t_state); + ok(SUCCEEDED(hr), "Failed to retrieve device state\n"); + compare_device_state(¤t_state, &pre_state, TRUE); + release_device_state(¤t_state); + + check_release((IUnknown *)render, 0); + } + + hr = D3DXCreateRenderToSurface(device, 256, 256, D3DFMT_A8R8G8B8, FALSE, D3DFMT_UNKNOWN, &render); + if (SUCCEEDED(hr)) + { + hr = ID3DXRenderToSurface_BeginScene(render, surface, NULL); + ok(hr == D3D_OK, "ID3DXRenderToSurface::BeginScene returned %#x, expected %#x\n", hr, D3D_OK); + + hr = retrieve_device_state(device, ¤t_state); + ok(SUCCEEDED(hr), "Failed to retrieve device state\n"); + compare_device_state(¤t_state, &pre_state, FALSE); + release_device_state(¤t_state); + + hr = ID3DXRenderToSurface_EndScene(render, D3DX_FILTER_NONE); + ok(hr == D3D_OK, "ID3DXRenderToSurface::EndScene returned %#x, expected %#x\n", hr, D3D_OK); + + hr = retrieve_device_state(device, ¤t_state); + ok(SUCCEEDED(hr), "Failed to retrieve device state\n"); + compare_device_state(¤t_state, &pre_state, TRUE); + release_device_state(¤t_state); + + hr = ID3DXRenderToSurface_BeginScene(render, surface, NULL); + ok(hr == D3D_OK, "ID3DXRenderToSurface::BeginScene returned %#x, expected %#x\n", hr, D3D_OK); + + hr = retrieve_device_state(device, ¤t_state); + ok(SUCCEEDED(hr), "Failed to retrieve device state\n"); + compare_device_state(¤t_state, &pre_state, FALSE); + release_device_state(¤t_state); + + check_release((IUnknown *)render, 0); + + /* if EndScene isn't called, the device state isn't restored */ + hr = retrieve_device_state(device, ¤t_state); + ok(SUCCEEDED(hr), "Failed to retrieve device state\n"); + compare_device_state(¤t_state, &pre_state, FALSE); + release_device_state(¤t_state); + + hr = apply_device_state(device, &pre_state); + ok(SUCCEEDED(hr), "Failed to restore previous device state\n"); + + IDirect3DDevice9_EndScene(device); + } + + release_device_state(&pre_state); + +cleanup: + if (depth_stencil_surface) + { + IDirect3DDevice9_SetDepthStencilSurface(device, NULL); + IDirect3DSurface9_Release(depth_stencil_surface); + } + + if (surface) check_release((IUnknown *)surface, 0); +} + +static void test_ID3DXRenderToSurface(IDirect3DDevice9 *device) +{ + int i; + HRESULT hr; + ULONG ref_count; + IDirect3DDevice9 *out_device; + ID3DXRenderToSurface *render; + IDirect3DSurface9 *surface; + D3DVIEWPORT9 viewport = { 0, 0, 256, 256, 0.0, 1.0 }; + D3DXRTS_DESC tests[] = { + { 256, 256, D3DFMT_A8R8G8B8, FALSE, D3DFMT_UNKNOWN }, + { 256, 256, D3DFMT_A8R8G8B8, TRUE, D3DFMT_D24S8 }, + { 256, 256, D3DFMT_A8R8G8B8, TRUE, D3DFMT_D24X8 }, + { 512, 512, D3DFMT_X8R8G8B8, FALSE, D3DFMT_X8R8G8B8 }, + { 1024, 1024, D3DFMT_X8R8G8B8, TRUE, D3DFMT_D24S8 } + }; + + hr = D3DXCreateRenderToSurface(device, 256, 256, D3DFMT_A8R8G8B8, FALSE, D3DFMT_UNKNOWN, &render); + ok(hr == D3D_OK, "D3DXCreateRenderToSurface returned %#x, expected %#x\n", hr, D3D_OK); + if (FAILED(hr)) return; + + hr = IDirect3DDevice9_CreateOffscreenPlainSurface(device, 256, 256, D3DFMT_A8R8G8B8, D3DPOOL_DEFAULT, &surface, NULL); + if (SUCCEEDED(hr)) + { + ID3DXRenderToSurface *render_surface; + + /* GetDevice */ + hr = ID3DXRenderToSurface_GetDevice(render, NULL /* device */); + ok(hr == D3DERR_INVALIDCALL, "ID3DXRenderToSurface::GetDevice returned %#x, expected %#x\n", hr, D3DERR_INVALIDCALL); + + ref_count = get_ref((IUnknown *)device); + hr = ID3DXRenderToSurface_GetDevice(render, &out_device); + ok(hr == D3D_OK, "ID3DXRenderToSurface::GetDevice returned %#x, expected %#x\n", hr, D3D_OK); + check_release((IUnknown *)out_device, ref_count); + + /* BeginScene and EndScene */ + hr = ID3DXRenderToSurface_EndScene(render, D3DX_FILTER_NONE); + ok(hr == D3DERR_INVALIDCALL, "ID3DXRenderToSurface::EndScene returned %#x, expected %#x\n", hr, D3DERR_INVALIDCALL); + + hr = ID3DXRenderToSurface_BeginScene(render, NULL /* surface */, &viewport); + ok(hr == D3DERR_INVALIDCALL, "ID3DXRenderToSurface::BeginScene returned %#x, expected %#x\n", hr, D3DERR_INVALIDCALL); + + ref_count = get_ref((IUnknown *)surface); + hr = ID3DXRenderToSurface_BeginScene(render, surface, NULL); + ok(hr == D3D_OK, "ID3DXRenderToSurface::BeginScene returned %#x, expected %#x\n", hr, D3D_OK); + if (SUCCEEDED(hr)) + { + check_ref((IUnknown *)surface, ref_count + 1); + + hr = ID3DXRenderToSurface_BeginScene(render, surface, NULL); + ok(hr == D3DERR_INVALIDCALL, "ID3DXRenderToSurface::BeginScene returned %#x, expected %#x\n", hr, D3DERR_INVALIDCALL); + + hr = ID3DXRenderToSurface_EndScene(render, D3DX_FILTER_NONE); + ok(hr == D3D_OK, "ID3DXRenderToSurface::EndScene returned %#x, expected %#x\n", hr, D3D_OK); + + check_ref((IUnknown *)surface, ref_count); + } + + /* error handling is deferred to BeginScene */ + hr = D3DXCreateRenderToSurface(device, 256, 256, D3DFMT_A8R8G8B8, TRUE, D3DFMT_UNKNOWN, &render_surface); + ok(hr == D3D_OK, "D3DXCreateRenderToSurface returned %#x, expected %#x\n", hr, D3D_OK); + hr = ID3DXRenderToSurface_BeginScene(render_surface, surface, NULL); + ok(hr == D3DERR_INVALIDCALL, "ID3DXRenderToSurface::BeginScene returned %#x, expected %#x\n", hr, D3DERR_INVALIDCALL); + check_release((IUnknown *)render_surface, 0); + + check_release((IUnknown *)surface, 0); + } + else skip("Failed to create surface\n"); + + check_release((IUnknown *)render, 0); + + for (i = 0; i < ARRAY_SIZE(tests); i++) + { + check_ID3DXRenderToSurface(device, tests[i].Width, tests[i].Height, tests[i].Format, tests[i].DepthStencil, tests[i].DepthStencilFormat, TRUE); + check_ID3DXRenderToSurface(device, tests[i].Width, tests[i].Height, tests[i].Format, tests[i].DepthStencil, tests[i].DepthStencilFormat, FALSE); + } + + test_ID3DXRenderToSurface_device_state(device); +} + +static void test_D3DXCreateRenderToEnvMap(IDirect3DDevice9 *device) +{ + int i; + HRESULT hr; + ULONG ref_count; + D3DXRTE_DESC desc; + ID3DXRenderToEnvMap *render; + static const struct { + D3DXRTE_DESC parameters; + D3DXRTE_DESC expected_values; + } tests[] = { + { { 0, 0, D3DFMT_A8R8G8B8, FALSE, D3DFMT_UNKNOWN }, { 1, 1, D3DFMT_A8R8G8B8, FALSE, D3DFMT_UNKNOWN } }, + { { 256, 0, D3DFMT_A8R8G8B8, FALSE, D3DFMT_UNKNOWN }, { 256, 9, D3DFMT_A8R8G8B8, FALSE, D3DFMT_UNKNOWN } }, + { { 256, 4, D3DFMT_A8R8G8B8, FALSE, D3DFMT_D24S8 }, { 256, 4, D3DFMT_A8R8G8B8, FALSE, D3DFMT_D24S8 } }, + { { 256, 256, D3DFMT_UNKNOWN, FALSE, D3DFMT_R8G8B8 }, { 256, 9, D3DFMT_A8R8G8B8, FALSE, D3DFMT_R8G8B8 } }, + { { -1, -1, D3DFMT_A8R8G8B8, TRUE, D3DFMT_DXT1 }, { 256, 9, D3DFMT_A8R8G8B8, TRUE, D3DFMT_DXT1 } }, + { { 256, 1, D3DFMT_X8R8G8B8, TRUE, D3DFMT_UNKNOWN }, { 256, 1, D3DFMT_X8R8G8B8, TRUE, D3DFMT_UNKNOWN } } + }; + + for (i = 0; i < ARRAY_SIZE(tests); i++) + { + const D3DXRTE_DESC *parameters = &tests[i].parameters; + const D3DXRTE_DESC *expected = &tests[i].expected_values; + hr = D3DXCreateRenderToEnvMap(device, parameters->Size, parameters->MipLevels, parameters->Format, + parameters->DepthStencil, parameters->DepthStencilFormat, &render); + ok(hr == D3D_OK, "%d: D3DXCreateRenderToEnvMap returned %#x, expected %#x\n", i, hr, D3D_OK); + if (SUCCEEDED(hr)) + { + hr = ID3DXRenderToEnvMap_GetDesc(render, &desc); + ok(hr == D3D_OK, "%d: GetDesc failed %#x\n", i, hr); + if (SUCCEEDED(hr)) + { + ok(desc.Size == expected->Size, "%d: Got size %u, expected %u\n", i, desc.Size, expected->Size); + ok(desc.MipLevels == expected->MipLevels, "%d: Got miplevels %u, expected %u\n", i, desc.MipLevels, expected->MipLevels); + ok(desc.Format == expected->Format, "%d: Got format %#x, expected %#x\n", i, desc.Format, expected->Format); + ok(desc.DepthStencil == expected->DepthStencil, "%d: Got depth stencil %d, expected %d\n", + i, expected->DepthStencil, expected->DepthStencil); + ok(desc.DepthStencilFormat == expected->DepthStencilFormat, "%d: Got depth stencil format %#x, expected %#x\n", + i, expected->DepthStencilFormat, expected->DepthStencilFormat); + } + check_release((IUnknown *)render, 0); + } + } + + /* check device ref count */ + ref_count = get_ref((IUnknown *)device); + hr = D3DXCreateRenderToEnvMap(device, 0, 0, D3DFMT_UNKNOWN, FALSE, D3DFMT_UNKNOWN, &render); + check_ref((IUnknown *)device, ref_count + 1); + if (SUCCEEDED(hr)) ID3DXRenderToEnvMap_Release(render); +} + +static void test_ID3DXRenderToEnvMap_cube_map(IDirect3DDevice9 *device) +{ + HRESULT hr; + IDirect3DCubeTexture9 *cube_texture = NULL; + ID3DXRenderToEnvMap *render = NULL; + struct device_state pre_state; + struct device_state current_state; + + hr = IDirect3DDevice9_CreateCubeTexture(device, 256, 0, D3DUSAGE_RENDERTARGET, D3DFMT_A8R8G8B8, D3DPOOL_DEFAULT, + &cube_texture, NULL); + if (FAILED(hr)) + { + skip("Failed to create cube texture\n"); + return; + } + + hr = retrieve_device_state(device, &pre_state); + ok(SUCCEEDED(hr), "Failed to retrieve device state\n"); + + hr = D3DXCreateRenderToEnvMap(device, 256, 0, D3DFMT_A8R8G8B8, TRUE, D3DFMT_D24X8, &render); + ok(hr == D3D_OK, "D3DCreateRenderToEnvMap returned %#x, expected %#x\n", hr, D3D_OK); + if (SUCCEEDED(hr)) + { + DWORD face; + + hr = ID3DXRenderToEnvMap_End(render, D3DX_FILTER_NONE); + ok(hr == D3DERR_INVALIDCALL, "ID3DXRenderToEnvMap::End returned %#x, expected %#x\n", hr, D3DERR_INVALIDCALL); + + hr = ID3DXRenderToEnvMap_BeginCube(render, cube_texture); + ok(hr == D3D_OK, "ID3DXRenderToEnvMap::BeginCube returned %#x, expected %#x\n", hr, D3D_OK); + + hr = retrieve_device_state(device, ¤t_state); + ok(SUCCEEDED(hr), "Failed to retrieve device state\n"); + compare_device_state(¤t_state, &pre_state, TRUE); + release_device_state(¤t_state); + + for (face = D3DCUBEMAP_FACE_POSITIVE_X; face <= D3DCUBEMAP_FACE_NEGATIVE_Z; face++) + { + hr = ID3DXRenderToEnvMap_Face(render, face, D3DX_FILTER_POINT); + ok(hr == D3D_OK, "ID3DXRenderToEnvMap::Face returned %#x, expected %#x\n", hr, D3D_OK); + + hr = retrieve_device_state(device, ¤t_state); + ok(SUCCEEDED(hr), "Failed to retrieve device state\n"); + compare_device_state(¤t_state, &pre_state, FALSE); + release_device_state(¤t_state); + } + + hr = ID3DXRenderToEnvMap_End(render, D3DX_FILTER_POINT); + ok(hr == D3D_OK, "ID3DXRenderToEnvMap::End returned %#x, expected %#x\n", hr, D3D_OK); + + hr = retrieve_device_state(device, ¤t_state); + ok(SUCCEEDED(hr), "Failed to retrieve device state\n"); + compare_device_state(¤t_state, &pre_state, TRUE); + release_device_state(¤t_state); + + check_release((IUnknown *)render, 0); + } + + release_device_state(&pre_state); + + check_release((IUnknown *)cube_texture, 0); +} + +static void test_ID3DXRenderToEnvMap(IDirect3DDevice9 *device) +{ + HRESULT hr; + ID3DXRenderToEnvMap *render; + IDirect3DSurface9 *depth_stencil_surface; + + hr = D3DXCreateRenderToEnvMap(device, 256, 0, D3DFMT_A8R8G8B8, FALSE, D3DFMT_UNKNOWN, &render); + if (SUCCEEDED(hr)) + { + ULONG ref_count; + IDirect3DDevice9 *out_device; + + hr = ID3DXRenderToEnvMap_GetDesc(render, NULL); + ok(hr == D3DERR_INVALIDCALL, "ID3DXRenderToEnvMap::GetDesc returned %#x, expected %#x\n", hr, D3DERR_INVALIDCALL); + + hr = ID3DXRenderToEnvMap_GetDevice(render, NULL); + ok(hr == D3DERR_INVALIDCALL, "ID3DXRenderToEnvMap::GetDevice returned %#x, expected %#x\n", hr, D3DERR_INVALIDCALL); + + ref_count = get_ref((IUnknown *)device); + hr = ID3DXRenderToEnvMap_GetDevice(render, &out_device); + ok(hr == D3D_OK, "ID3DXRenderToEnvMap::GetDevice returned %#x, expected %#x\n", hr, D3D_OK); + ok(out_device == device, "ID3DXRenderToEnvMap::GetDevice returned different device\n"); + check_release((IUnknown *)device, ref_count); + + hr = ID3DXRenderToEnvMap_End(render, D3DX_FILTER_NONE); + ok(hr == D3DERR_INVALIDCALL, "ID3DXRenderToEnvMap::End returned %#x, expected %#x\n", hr, D3D_OK); + + hr = ID3DXRenderToEnvMap_BeginCube(render, NULL); + ok(hr == D3DERR_INVALIDCALL, "ID3DXRenderToEnvMap::BeginCube returned %#x, expected %#x\n", hr, D3DERR_INVALIDCALL); + + hr = ID3DXRenderToEnvMap_BeginHemisphere(render, NULL, NULL); + todo_wine ok(hr == D3DERR_INVALIDCALL, "ID3DXRenderToEnvMap::BeginHemisphere returned %#x, expected %#x\n", hr, D3DERR_INVALIDCALL); + + hr = ID3DXRenderToEnvMap_BeginParabolic(render, NULL, NULL); + todo_wine ok(hr == D3DERR_INVALIDCALL, "ID3DXRenderToEnvMap::BeginParabolic returned %#x, expected %#x\n", hr, D3DERR_INVALIDCALL); + + hr = ID3DXRenderToEnvMap_BeginSphere(render, NULL); + todo_wine ok(hr == D3DERR_INVALIDCALL, "ID3DXRenderToEnvMap::BeginSphere returned %#x, expected %#x\n", hr, D3DERR_INVALIDCALL); + + check_release((IUnknown *)render, 0); + } else skip("Failed to create ID3DXRenderToEnvMap\n"); + + /* make sure there is a depth stencil surface present */ + hr = IDirect3DDevice9_GetDepthStencilSurface(device, &depth_stencil_surface); + if (SUCCEEDED(hr)) + { + IDirect3DSurface9_Release(depth_stencil_surface); + depth_stencil_surface = NULL; + } + else if (hr == D3DERR_NOTFOUND) + { + hr = IDirect3DDevice9_CreateDepthStencilSurface(device, 256, 256, D3DFMT_D24X8, + D3DMULTISAMPLE_NONE, 0, TRUE, &depth_stencil_surface, NULL); + if (SUCCEEDED(hr)) IDirect3DDevice9_SetDepthStencilSurface(device, depth_stencil_surface); + } + + if (FAILED(hr)) + { + skip("Failed to create depth stencil surface\n"); + return; + } + + test_ID3DXRenderToEnvMap_cube_map(device); + + if (depth_stencil_surface) + { + IDirect3DDevice9_SetDepthStencilSurface(device, NULL); + IDirect3DSurface9_Release(depth_stencil_surface); + } +} + +START_TEST(core) +{ + HWND wnd; + IDirect3D9 *d3d; + IDirect3DDevice9 *device; + D3DPRESENT_PARAMETERS d3dpp; + HRESULT hr; + + 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_SOFTWARE_VERTEXPROCESSING, &d3dpp, &device); + if(FAILED(hr)) { + skip("Failed to create IDirect3DDevice9 object %#x\n", hr); + IDirect3D9_Release(d3d); + DestroyWindow(wnd); + return; + } + + test_ID3DXBuffer(); + test_ID3DXSprite(device); + test_ID3DXFont(device); + test_D3DXCreateRenderToSurface(device); + test_ID3DXRenderToSurface(device); + test_D3DXCreateRenderToEnvMap(device); + test_ID3DXRenderToEnvMap(device); + + check_release((IUnknown*)device, 0); + check_release((IUnknown*)d3d, 0); + if (wnd) DestroyWindow(wnd); +} diff --git a/modules/rostests/winetests/d3dx9_36/effect.c b/modules/rostests/winetests/d3dx9_36/effect.c new file mode 100644 index 00000000000..423d3b8d5c6 --- /dev/null +++ b/modules/rostests/winetests/d3dx9_36/effect.c @@ -0,0 +1,8030 @@ +/* + * Copyright 2010 Christian Costa + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA + */ + +#define COBJMACROS +#include "initguid.h" +#include +#include "wine/test.h" +#include "d3dx9.h" + +#ifndef INFINITY +static inline float __port_infinity(void) +{ + static const unsigned __inf_bytes = 0x7f800000; + return *(const float *)&__inf_bytes; +} +#define INFINITY __port_infinity() +#endif /* INFINITY */ + +#ifndef NAN +static float get_nan(void) +{ + DWORD nan = 0x7fc00000; + + return *(float *)&nan; +} +#define NAN get_nan() +#endif + +/* helper functions */ +static BOOL compare_float(FLOAT f, FLOAT g, UINT ulps) +{ + INT x = *(INT *)&f; + INT y = *(INT *)&g; + + if (x < 0) + x = INT_MIN - x; + if (y < 0) + y = INT_MIN - y; + + if (abs(x - y) > ulps) + return FALSE; + + return TRUE; +} + +static inline INT get_int(D3DXPARAMETER_TYPE type, const void *data) +{ + INT i; + + switch (type) + { + case D3DXPT_FLOAT: + i = *(FLOAT *)data; + break; + + case D3DXPT_INT: + i = *(INT *)data; + break; + + case D3DXPT_BOOL: + i = *(BOOL *)data; + break; + + default: + i = 0; + ok(0, "Unhandled type %x.\n", type); + break; + } + + return i; +} + +static inline float get_float(D3DXPARAMETER_TYPE type, const void *data) +{ + float f; + + switch (type) + { + case D3DXPT_FLOAT: + f = *(FLOAT *)data; + break; + + case D3DXPT_INT: + f = *(INT *)data; + break; + + case D3DXPT_BOOL: + f = *(BOOL *)data; + break; + + default: + f = 0.0f; + ok(0, "Unhandled type %x.\n", type); + break; + } + + return f; +} + +static inline BOOL get_bool(const void *data) +{ + return !!*(BOOL *)data; +} + +static void set_number(void *outdata, D3DXPARAMETER_TYPE outtype, const void *indata, D3DXPARAMETER_TYPE intype) +{ + switch (outtype) + { + case D3DXPT_FLOAT: + *(FLOAT *)outdata = get_float(intype, indata); + break; + + case D3DXPT_BOOL: + *(BOOL *)outdata = get_bool(indata); + break; + + case D3DXPT_INT: + *(INT *)outdata = get_int(intype, indata); + break; + + case D3DXPT_PIXELSHADER: + case D3DXPT_VERTEXSHADER: + case D3DXPT_TEXTURE2D: + case D3DXPT_STRING: + *(INT *)outdata = 0x12345678; + break; + + default: + ok(0, "Unhandled type %x.\n", outtype); + *(INT *)outdata = 0; + break; + } +} + +static IDirect3DDevice9 *create_device(HWND *window) +{ + D3DPRESENT_PARAMETERS present_parameters = { 0 }; + IDirect3DDevice9 *device; + IDirect3D9 *d3d; + HRESULT hr; + HWND wnd; + + *window = NULL; + + if (!(wnd = CreateWindowA("static", "d3dx9_test", WS_OVERLAPPEDWINDOW, 0, 0, + 640, 480, NULL, NULL, NULL, NULL))) + { + skip("Couldn't create application window.\n"); + return NULL; + } + + if (!(d3d = Direct3DCreate9(D3D_SDK_VERSION))) + { + skip("Couldn't create IDirect3D9 object.\n"); + DestroyWindow(wnd); + return NULL; + } + + present_parameters.Windowed = TRUE; + present_parameters.SwapEffect = D3DSWAPEFFECT_DISCARD; + hr = IDirect3D9_CreateDevice(d3d, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, wnd, D3DCREATE_HARDWARE_VERTEXPROCESSING, + &present_parameters, &device); + IDirect3D9_Release(d3d); + if (FAILED(hr)) + { + skip("Failed to create IDirect3DDevice9 object %#x.\n", hr); + DestroyWindow(wnd); + return NULL; + } + + *window = wnd; + return device; +} + +static char temp_path[MAX_PATH]; + +static BOOL create_file(const char *filename, const char *data, const unsigned int size, char *out_path) +{ + DWORD written; + HANDLE hfile; + char path[MAX_PATH]; + + if (!*temp_path) + GetTempPathA(sizeof(temp_path), temp_path); + + strcpy(path, temp_path); + strcat(path, filename); + hfile = CreateFileA(path, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, 0); + if (hfile == INVALID_HANDLE_VALUE) + return FALSE; + + if (WriteFile(hfile, data, size, &written, NULL)) + { + CloseHandle(hfile); + + if (out_path) + strcpy(out_path, path); + return TRUE; + } + + CloseHandle(hfile); + return FALSE; +} + +static void delete_file(const char *filename) +{ + char path[MAX_PATH]; + + strcpy(path, temp_path); + strcat(path, filename); + DeleteFileA(path); +} + +static BOOL create_directory(const char *name) +{ + char path[MAX_PATH]; + + strcpy(path, temp_path); + strcat(path, name); + return CreateDirectoryA(path, NULL); +} + +static void delete_directory(const char *name) +{ + char path[MAX_PATH]; + + strcpy(path, temp_path); + strcat(path, name); + RemoveDirectoryA(path); +} + +static const char effect_desc[] = +"Technique\n" +"{\n" +"}\n"; + +static void test_create_effect_and_pool(IDirect3DDevice9 *device) +{ + HRESULT hr; + ID3DXEffect *effect; + ID3DXBaseEffect *base; + ULONG count; + IDirect3DDevice9 *device2; + ID3DXEffectStateManager *manager = (ID3DXEffectStateManager *)0xdeadbeef; + ID3DXEffectPool *pool = (ID3DXEffectPool *)0xdeadbeef, *pool2; + + hr = D3DXCreateEffect(NULL, effect_desc, sizeof(effect_desc), NULL, NULL, 0, NULL, NULL, NULL); + ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3D_INVALIDCALL)\n", hr, D3DERR_INVALIDCALL); + + hr = D3DXCreateEffect(device, NULL, 0, NULL, NULL, 0, NULL, NULL, NULL); + ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n", hr, D3DERR_INVALIDCALL); + + hr = D3DXCreateEffect(device, effect_desc, 0, NULL, NULL, 0, NULL, NULL, NULL); + ok(hr == E_FAIL, "Got result %x, expected %x (D3DXERR_INVALIDDATA)\n", hr, E_FAIL); + + hr = D3DXCreateEffect(device, effect_desc, sizeof(effect_desc), NULL, NULL, 0, NULL, NULL, NULL); + ok(hr == D3D_OK, "Got result %x, expected 0 (D3D_OK)\n", hr); + + hr = D3DXCreateEffect(device, effect_desc, sizeof(effect_desc), NULL, NULL, 0, NULL, &effect, NULL); + todo_wine ok(hr == D3D_OK, "Got result %x, expected 0 (D3D_OK)\n", hr); + if (FAILED(hr)) + { + skip("Failed to compile effect, skipping test.\n"); + return; + } + + hr = effect->lpVtbl->QueryInterface(effect, &IID_ID3DXBaseEffect, (void **)&base); + ok(hr == E_NOINTERFACE, "QueryInterface failed, got %x, expected %x (E_NOINTERFACE)\n", hr, E_NOINTERFACE); + + hr = effect->lpVtbl->GetStateManager(effect, NULL); + ok(hr == D3DERR_INVALIDCALL, "GetStateManager failed, got %x, expected %x (D3DERR_INVALIDCALL)\n", hr, D3DERR_INVALIDCALL); + + hr = effect->lpVtbl->GetStateManager(effect, &manager); + ok(hr == D3D_OK, "GetStateManager failed, got %x, expected 0 (D3D_OK)\n", hr); + ok(!manager, "GetStateManager failed, got %p\n", manager); + + /* this works, but it is not recommended! */ + hr = effect->lpVtbl->SetStateManager(effect, (ID3DXEffectStateManager *)device); + ok(hr == D3D_OK, "SetStateManager failed, got %x, expected 0 (D3D_OK)\n", hr); + + hr = effect->lpVtbl->GetStateManager(effect, &manager); + ok(hr == D3D_OK, "GetStateManager failed, got %x, expected 0 (D3D_OK)\n", hr); + ok(manager != NULL, "GetStateManager failed\n"); + + IDirect3DDevice9_AddRef(device); + count = IDirect3DDevice9_Release(device); + ok(count == 4, "Release failed, got %u, expected 4\n", count); + + count = IUnknown_Release(manager); + ok(count == 3, "Release failed, got %u, expected 3\n", count); + + hr = effect->lpVtbl->SetStateManager(effect, NULL); + ok(hr == D3D_OK, "SetStateManager failed, got %x, expected 0 (D3D_OK)\n", hr); + + hr = effect->lpVtbl->GetPool(effect, &pool); + ok(hr == D3D_OK, "GetPool failed, got %x, expected 0 (D3D_OK)\n", hr); + ok(!pool, "GetPool failed, got %p\n", pool); + + hr = effect->lpVtbl->GetPool(effect, NULL); + ok(hr == D3DERR_INVALIDCALL, "GetPool failed, got %x, expected %x (D3DERR_INVALIDCALL)\n", hr, D3DERR_INVALIDCALL); + + hr = effect->lpVtbl->GetDevice(effect, &device2); + ok(hr == D3D_OK, "Got result %x, expected 0 (D3D_OK)\n", hr); + + hr = effect->lpVtbl->GetDevice(effect, NULL); + ok(hr == D3DERR_INVALIDCALL, "GetDevice failed, got %x, expected %x (D3DERR_INVALIDCALL)\n", hr, D3DERR_INVALIDCALL); + + count = IDirect3DDevice9_Release(device2); + ok(count == 2, "Release failed, got %u, expected 2\n", count); + + count = effect->lpVtbl->Release(effect); + ok(count == 0, "Release failed %u\n", count); + + hr = D3DXCreateEffectPool(NULL); + ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3D_INVALIDCALL)\n", hr, D3DERR_INVALIDCALL); + + hr = D3DXCreateEffectPool(&pool); + ok(hr == S_OK, "Got result %x, expected 0 (S_OK)\n", hr); + + count = pool->lpVtbl->Release(pool); + ok(count == 0, "Release failed %u\n", count); + + hr = D3DXCreateEffectPool(&pool); + ok(hr == S_OK, "Got result %x, expected 0 (S_OK)\n", hr); + + hr = D3DXCreateEffect(device, effect_desc, sizeof(effect_desc), NULL, NULL, 0, pool, NULL, NULL); + ok(hr == D3D_OK, "Got result %x, expected 0 (D3D_OK)\n", hr); + + hr = pool->lpVtbl->QueryInterface(pool, &IID_ID3DXEffectPool, (void **)&pool2); + ok(hr == D3D_OK, "Got result %x, expected 0 (D3D_OK)\n", hr); + ok(pool == pool2, "Release failed, got %p, expected %p\n", pool2, pool); + + count = pool2->lpVtbl->Release(pool2); + ok(count == 1, "Release failed, got %u, expected 1\n", count); + + hr = IDirect3DDevice9_QueryInterface(device, &IID_IDirect3DDevice9, (void **)&device2); + ok(hr == D3D_OK, "Got result %x, expected 0 (D3D_OK)\n", hr); + + count = IDirect3DDevice9_Release(device2); + ok(count == 1, "Release failed, got %u, expected 1\n", count); + + hr = D3DXCreateEffect(device, effect_desc, sizeof(effect_desc), NULL, NULL, 0, pool, &effect, NULL); + ok(hr == D3D_OK, "Got result %x, expected 0 (D3D_OK)\n", hr); + + hr = effect->lpVtbl->GetPool(effect, &pool); + ok(hr == D3D_OK, "GetPool failed, got %x, expected 0 (D3D_OK)\n", hr); + ok(pool == pool2, "GetPool failed, got %p, expected %p\n", pool2, pool); + + count = pool2->lpVtbl->Release(pool2); + ok(count == 2, "Release failed, got %u, expected 2\n", count); + + count = effect->lpVtbl->Release(effect); + ok(count == 0, "Release failed %u\n", count); + + count = pool->lpVtbl->Release(pool); + ok(count == 0, "Release failed %u\n", count); +} + +static void test_create_effect_compiler(void) +{ + HRESULT hr; + ID3DXEffectCompiler *compiler, *compiler2; + ID3DXBaseEffect *base; + IUnknown *unknown; + ULONG count; + + hr = D3DXCreateEffectCompiler(NULL, 0, NULL, NULL, 0, &compiler, NULL); + ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3D_INVALIDCALL)\n", hr, D3DERR_INVALIDCALL); + + hr = D3DXCreateEffectCompiler(NULL, 0, NULL, NULL, 0, NULL, NULL); + ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3D_INVALIDCALL)\n", hr, D3DERR_INVALIDCALL); + + hr = D3DXCreateEffectCompiler(effect_desc, 0, NULL, NULL, 0, &compiler, NULL); + ok(hr == D3D_OK, "Got result %x, expected %x (D3D_OK)\n", hr, D3D_OK); + if (FAILED(hr)) + { + skip("D3DXCreateEffectCompiler failed, skipping test.\n"); + return; + } + + count = compiler->lpVtbl->Release(compiler); + ok(count == 0, "Release failed %u\n", count); + + hr = D3DXCreateEffectCompiler(effect_desc, 0, NULL, NULL, 0, NULL, NULL); + ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3D_INVALIDCALL)\n", hr, D3DERR_INVALIDCALL); + + hr = D3DXCreateEffectCompiler(NULL, sizeof(effect_desc), NULL, NULL, 0, &compiler, NULL); + ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3D_INVALIDCALL)\n", hr, D3DERR_INVALIDCALL); + + hr = D3DXCreateEffectCompiler(NULL, sizeof(effect_desc), NULL, NULL, 0, NULL, NULL); + ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3D_INVALIDCALL)\n", hr, D3DERR_INVALIDCALL); + + hr = D3DXCreateEffectCompiler(effect_desc, sizeof(effect_desc), NULL, NULL, 0, NULL, NULL); + ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n", hr, D3DERR_INVALIDCALL); + + hr = D3DXCreateEffectCompiler(effect_desc, sizeof(effect_desc), NULL, NULL, 0, &compiler, NULL); + ok(hr == D3D_OK, "Got result %x, expected %x (D3D_OK)\n", hr, D3D_OK); + + hr = compiler->lpVtbl->QueryInterface(compiler, &IID_ID3DXBaseEffect, (void **)&base); + ok(hr == E_NOINTERFACE, "QueryInterface failed, got %x, expected %x (E_NOINTERFACE)\n", hr, E_NOINTERFACE); + + hr = compiler->lpVtbl->QueryInterface(compiler, &IID_ID3DXEffectCompiler, (void **)&compiler2); + ok(hr == D3D_OK, "QueryInterface failed, got %x, expected %x (D3D_OK)\n", hr, D3D_OK); + + hr = compiler->lpVtbl->QueryInterface(compiler, &IID_IUnknown, (void **)&unknown); + ok(hr == D3D_OK, "QueryInterface failed, got %x, expected %x (D3D_OK)\n", hr, D3D_OK); + + count = unknown->lpVtbl->Release(unknown); + ok(count == 2, "Release failed, got %u, expected %u\n", count, 2); + + count = compiler2->lpVtbl->Release(compiler2); + ok(count == 1, "Release failed, got %u, expected %u\n", count, 1); + + count = compiler->lpVtbl->Release(compiler); + ok(count == 0, "Release failed %u\n", count); +} + +/* + * Parameter value test + */ +struct test_effect_parameter_value_result +{ + const char *full_name; + D3DXPARAMETER_DESC desc; + UINT value_offset; /* start position for the value in the blob */ +}; + +/* + * fxc.exe /Tfx_2_0 + */ +#if 0 +float f = 0.1; +float1 f1 = {1.1}; +float2 f2 = {2.1, 2.2}; +float3 f3 = {3.1, 3.2, 3.3}; +float4 f4 = {4.1, 4.2, 4.3, 4.4}; +float1x1 f11 = {11.1}; +float1x2 f12 = {12.1, 12.2}; +float1x3 f13 = {13.1, 13.2, 13.3}; +float1x4 f14 = {14.1, 14.2, 14.3, 14.4}; +float2x1 f21 = {{21.11, 21.21}}; +float2x2 f22 = {{22.11, 22.21}, {22.12, 22.22}}; +float2x3 f23 = {{23.11, 23.21}, {23.12, 23.22}, {23.13, 23.23}}; +float2x4 f24 = {{24.11, 24.21}, {24.12, 24.22}, {24.13, 24.23}, {24.14, 24.24}}; +float3x1 f31 = {{31.11, 31.21, 31.31}}; +float3x2 f32 = {{32.11, 32.21, 32.31}, {32.12, 32.22, 32.32}}; +float3x3 f33 = {{33.11, 33.21, 33.31}, {33.12, 33.22, 33.32}, + {33.13, 33.23, 33.33}}; +float3x4 f34 = {{34.11, 34.21, 34.31}, {34.12, 34.22, 34.32}, + {34.13, 34.23, 34.33}, {34.14, 34.24, 34.34}}; +float4x1 f41 = {{41.11, 41.21, 41.31, 41.41}}; +float4x2 f42 = {{42.11, 42.21, 42.31, 42.41}, {42.12, 42.22, 42.32, 42.42}}; +float4x3 f43 = {{43.11, 43.21, 43.31, 43.41}, {43.12, 43.22, 43.32, 43.42}, + {43.13, 43.23, 43.33, 43.43}}; +float4x4 f44 = {{44.11, 44.21, 44.31, 44.41}, {44.12, 44.22, 44.32, 44.42}, + {44.13, 44.23, 44.33, 44.43}, {44.14, 44.24, 44.34, 44.44}}; +float f_2[2] = {0.101, 0.102}; +float1 f1_2[2] = {{1.101}, {1.102}}; +float2 f2_2[2] = {{2.101, 2.201}, {2.102, 2.202}}; +float3 f3_2[2] = {{3.101, 3.201, 3.301}, {3.102, 3.202, 3.302}}; +float4 f4_2[2] = {{4.101, 4.201, 4.301, 4.401}, {4.102, 4.202, 4.302, 4.402}}; +float1x1 f11_2[2] = {{11.101}, {11.102}}; +float1x2 f12_2[2] = {{12.101, 12.201}, {12.102, 12.202}}; +float1x3 f13_2[2] = {{13.101, 13.201, 13.301}, {13.102, 13.202, 13.302}}; +float1x4 f14_2[2] = {{14.101, 14.201, 14.301, 14.401}, {14.102, 14.202, 14.302, 14.402}}; +float2x1 f21_2[2] = {{{21.1101, 21.2101}}, {{21.1102, 21.2102}}}; +float2x2 f22_2[2] = {{{22.1101, 22.2101}, {22.1201, 22.2201}}, {{22.1102, 22.2102}, {22.1202, 22.2202}}}; +float2x3 f23_2[2] = {{{23.1101, 23.2101}, {23.1201, 23.2201}, {23.1301, 23.2301}}, {{23.1102, 23.2102}, + {23.1202, 23.2202}, {23.1302, 23.2302}}}; +float2x4 f24_2[2] = {{{24.1101, 24.2101}, {24.1201, 24.2201}, {24.1301, 24.2301}, {24.1401, 24.2401}}, + {{24.1102, 24.2102}, {24.1202, 24.2202}, {24.1302, 24.2302}, {24.1402, 24.2402}}}; +float3x1 f31_2[2] = {{{31.1101, 31.2101, 31.3101}}, {{31.1102, 31.2102, 31.3102}}}; +float3x2 f32_2[2] = {{{32.1101, 32.2101, 32.3101}, {32.1201, 32.2201, 32.3201}}, + {{32.1102, 32.2102, 32.3102}, {32.1202, 32.2202, 32.3202}}}; +float3x3 f33_2[2] = {{{33.1101, 33.2101, 33.3101}, {33.1201, 33.2201, 33.3201}, + {33.1301, 33.2301, 33.3301}}, {{33.1102, 33.2102, 33.3102}, {33.1202, 33.2202, 33.3202}, + {33.1302, 33.2302, 33.3302}}}; +float3x4 f34_2[2] = {{{34.1101, 34.2101, 34.3101}, {34.1201, 34.2201, 34.3201}, + {34.1301, 34.2301, 34.3301}, {34.1401, 34.2401, 34.3401}}, {{34.1102, 34.2102, 34.3102}, + {34.1202, 34.2202, 34.3202}, {34.1302, 34.2302, 34.3302}, {34.1402, 34.2402, 34.3402}}}; +float4x1 f41_2[2] = {{{41.1101, 41.2101, 41.3101, 41.4101}}, {{41.1102, 41.2102, 41.3102, 41.4102}}}; +float4x2 f42_2[2] = {{{42.1101, 42.2101, 42.3101, 42.4101}, {42.1201, 42.2201, 42.3201, 42.4201}}, + {{42.1102, 42.2102, 42.3102, 42.4102}, {42.1202, 42.2202, 42.3202, 42.4202}}}; +float4x3 f43_2[2] = {{{43.1101, 43.2101, 43.3101, 43.4101}, {43.1201, 43.2201, 43.3201, 43.4201}, + {43.1301, 43.2301, 43.3301, 43.4301}}, {{43.1102, 43.2102, 43.3102, 43.4102}, + {43.1202, 43.2202, 43.3202, 43.4202}, {43.1302, 43.2302, 43.3302, 43.4302}}}; +float4x4 f44_2[2] = {{{44.1101, 44.2101, 44.3101, 44.4101}, {44.1201, 44.2201, 44.3201, 44.4201}, + {44.1301, 44.2301, 44.3301, 44.4301}, {44.1401, 44.2401, 44.3401, 44.4401}}, + {{44.1102, 44.2102, 44.3102, 44.4102}, {44.1202, 44.2202, 44.3202, 44.4202}, + {44.1302, 44.2302, 44.3302, 44.4302}, {44.1402, 44.2402, 44.3402, 44.4402}}}; +technique t { pass p { } } +#endif +static const DWORD test_effect_parameter_value_blob_float[] = +{ +0xfeff0901, 0x00000b80, 0x00000000, 0x00000003, 0x00000000, 0x00000024, 0x00000000, 0x00000000, +0x00000001, 0x00000001, 0x3dcccccd, 0x00000002, 0x00000066, 0x00000003, 0x00000001, 0x0000004c, +0x00000000, 0x00000000, 0x00000001, 0x00000001, 0x3f8ccccd, 0x00000003, 0x00003166, 0x00000003, +0x00000001, 0x00000078, 0x00000000, 0x00000000, 0x00000002, 0x00000001, 0x40066666, 0x400ccccd, +0x00000003, 0x00003266, 0x00000003, 0x00000001, 0x000000a8, 0x00000000, 0x00000000, 0x00000003, +0x00000001, 0x40466666, 0x404ccccd, 0x40533333, 0x00000003, 0x00003366, 0x00000003, 0x00000001, +0x000000dc, 0x00000000, 0x00000000, 0x00000004, 0x00000001, 0x40833333, 0x40866666, 0x4089999a, +0x408ccccd, 0x00000003, 0x00003466, 0x00000003, 0x00000002, 0x00000104, 0x00000000, 0x00000000, +0x00000001, 0x00000001, 0x4131999a, 0x00000004, 0x00313166, 0x00000003, 0x00000002, 0x00000130, +0x00000000, 0x00000000, 0x00000001, 0x00000002, 0x4141999a, 0x41433333, 0x00000004, 0x00323166, +0x00000003, 0x00000002, 0x00000160, 0x00000000, 0x00000000, 0x00000001, 0x00000003, 0x4151999a, +0x41533333, 0x4154cccd, 0x00000004, 0x00333166, 0x00000003, 0x00000002, 0x00000194, 0x00000000, +0x00000000, 0x00000001, 0x00000004, 0x4161999a, 0x41633333, 0x4164cccd, 0x41666666, 0x00000004, +0x00343166, 0x00000003, 0x00000002, 0x000001c0, 0x00000000, 0x00000000, 0x00000002, 0x00000001, +0x41a8e148, 0x41a9ae14, 0x00000004, 0x00313266, 0x00000003, 0x00000002, 0x000001f4, 0x00000000, +0x00000000, 0x00000002, 0x00000002, 0x41b0e148, 0x41b1ae14, 0x41b0f5c3, 0x41b1c28f, 0x00000004, +0x00323266, 0x00000003, 0x00000002, 0x00000230, 0x00000000, 0x00000000, 0x00000002, 0x00000003, +0x41b8e148, 0x41b9ae14, 0x41b8f5c3, 0x41b9c28f, 0x41b90a3d, 0x41b9d70a, 0x00000004, 0x00333266, +0x00000003, 0x00000002, 0x00000274, 0x00000000, 0x00000000, 0x00000002, 0x00000004, 0x41c0e148, +0x41c1ae14, 0x41c0f5c3, 0x41c1c28f, 0x41c10a3d, 0x41c1d70a, 0x41c11eb8, 0x41c1eb85, 0x00000004, +0x00343266, 0x00000003, 0x00000002, 0x000002a4, 0x00000000, 0x00000000, 0x00000003, 0x00000001, +0x41f8e148, 0x41f9ae14, 0x41fa7ae1, 0x00000004, 0x00313366, 0x00000003, 0x00000002, 0x000002e0, +0x00000000, 0x00000000, 0x00000003, 0x00000002, 0x420070a4, 0x4200d70a, 0x42013d71, 0x42007ae1, +0x4200e148, 0x420147ae, 0x00000004, 0x00323366, 0x00000003, 0x00000002, 0x00000328, 0x00000000, +0x00000000, 0x00000003, 0x00000003, 0x420470a4, 0x4204d70a, 0x42053d71, 0x42047ae1, 0x4204e148, +0x420547ae, 0x4204851f, 0x4204eb85, 0x420551ec, 0x00000004, 0x00333366, 0x00000003, 0x00000002, +0x0000037c, 0x00000000, 0x00000000, 0x00000003, 0x00000004, 0x420870a4, 0x4208d70a, 0x42093d71, +0x42087ae1, 0x4208e148, 0x420947ae, 0x4208851f, 0x4208eb85, 0x420951ec, 0x42088f5c, 0x4208f5c3, +0x42095c29, 0x00000004, 0x00343366, 0x00000003, 0x00000002, 0x000003b0, 0x00000000, 0x00000000, +0x00000004, 0x00000001, 0x422470a4, 0x4224d70a, 0x42253d71, 0x4225a3d7, 0x00000004, 0x00313466, +0x00000003, 0x00000002, 0x000003f4, 0x00000000, 0x00000000, 0x00000004, 0x00000002, 0x422870a4, +0x4228d70a, 0x42293d71, 0x4229a3d7, 0x42287ae1, 0x4228e148, 0x422947ae, 0x4229ae14, 0x00000004, +0x00323466, 0x00000003, 0x00000002, 0x00000448, 0x00000000, 0x00000000, 0x00000004, 0x00000003, +0x422c70a4, 0x422cd70a, 0x422d3d71, 0x422da3d7, 0x422c7ae1, 0x422ce148, 0x422d47ae, 0x422dae14, +0x422c851f, 0x422ceb85, 0x422d51ec, 0x422db852, 0x00000004, 0x00333466, 0x00000003, 0x00000002, +0x000004ac, 0x00000000, 0x00000000, 0x00000004, 0x00000004, 0x423070a4, 0x4230d70a, 0x42313d71, +0x4231a3d7, 0x42307ae1, 0x4230e148, 0x423147ae, 0x4231ae14, 0x4230851f, 0x4230eb85, 0x423151ec, +0x4231b852, 0x42308f5c, 0x4230f5c3, 0x42315c29, 0x4231c28f, 0x00000004, 0x00343466, 0x00000003, +0x00000000, 0x000004d8, 0x00000000, 0x00000002, 0x00000001, 0x00000001, 0x3dced917, 0x3dd0e560, +0x00000004, 0x00325f66, 0x00000003, 0x00000001, 0x00000504, 0x00000000, 0x00000002, 0x00000001, +0x00000001, 0x3f8ced91, 0x3f8d0e56, 0x00000005, 0x325f3166, 0x00000000, 0x00000003, 0x00000001, +0x0000053c, 0x00000000, 0x00000002, 0x00000002, 0x00000001, 0x400676c9, 0x400cdd2f, 0x4006872b, +0x400ced91, 0x00000005, 0x325f3266, 0x00000000, 0x00000003, 0x00000001, 0x0000057c, 0x00000000, +0x00000002, 0x00000003, 0x00000001, 0x404676c9, 0x404cdd2f, 0x40534396, 0x4046872b, 0x404ced91, +0x405353f8, 0x00000005, 0x325f3366, 0x00000000, 0x00000003, 0x00000001, 0x000005c4, 0x00000000, +0x00000002, 0x00000004, 0x00000001, 0x40833b64, 0x40866e98, 0x4089a1cb, 0x408cd4fe, 0x40834396, +0x408676c9, 0x4089a9fc, 0x408cdd2f, 0x00000005, 0x325f3466, 0x00000000, 0x00000003, 0x00000002, +0x000005f4, 0x00000000, 0x00000002, 0x00000001, 0x00000001, 0x41319db2, 0x4131a1cb, 0x00000006, +0x5f313166, 0x00000032, 0x00000003, 0x00000002, 0x0000062c, 0x00000000, 0x00000002, 0x00000001, +0x00000002, 0x41419db2, 0x4143374c, 0x4141a1cb, 0x41433b64, 0x00000006, 0x5f323166, 0x00000032, +0x00000003, 0x00000002, 0x0000066c, 0x00000000, 0x00000002, 0x00000001, 0x00000003, 0x41519db2, +0x4153374c, 0x4154d0e5, 0x4151a1cb, 0x41533b64, 0x4154d4fe, 0x00000006, 0x5f333166, 0x00000032, +0x00000003, 0x00000002, 0x000006b4, 0x00000000, 0x00000002, 0x00000001, 0x00000004, 0x41619db2, +0x4163374c, 0x4164d0e5, 0x41666a7f, 0x4161a1cb, 0x41633b64, 0x4164d4fe, 0x41666e98, 0x00000006, +0x5f343166, 0x00000032, 0x00000003, 0x00000002, 0x000006ec, 0x00000000, 0x00000002, 0x00000002, +0x00000001, 0x41a8e17c, 0x41a9ae49, 0x41a8e1b1, 0x41a9ae7d, 0x00000006, 0x5f313266, 0x00000032, +0x00000003, 0x00000002, 0x00000734, 0x00000000, 0x00000002, 0x00000002, 0x00000002, 0x41b0e17c, +0x41b1ae49, 0x41b0f5f7, 0x41b1c2c4, 0x41b0e1b1, 0x41b1ae7d, 0x41b0f62b, 0x41b1c2f8, 0x00000006, +0x5f323266, 0x00000032, 0x00000003, 0x00000002, 0x0000078c, 0x00000000, 0x00000002, 0x00000002, +0x00000003, 0x41b8e17c, 0x41b9ae49, 0x41b8f5f7, 0x41b9c2c4, 0x41b90a72, 0x41b9d73f, 0x41b8e1b1, +0x41b9ae7d, 0x41b8f62b, 0x41b9c2f8, 0x41b90aa6, 0x41b9d773, 0x00000006, 0x5f333266, 0x00000032, +0x00000003, 0x00000002, 0x000007f4, 0x00000000, 0x00000002, 0x00000002, 0x00000004, 0x41c0e17c, +0x41c1ae49, 0x41c0f5f7, 0x41c1c2c4, 0x41c10a72, 0x41c1d73f, 0x41c11eed, 0x41c1ebba, 0x41c0e1b1, +0x41c1ae7d, 0x41c0f62b, 0x41c1c2f8, 0x41c10aa6, 0x41c1d773, 0x41c11f21, 0x41c1ebee, 0x00000006, +0x5f343266, 0x00000032, 0x00000003, 0x00000002, 0x00000834, 0x00000000, 0x00000002, 0x00000003, +0x00000001, 0x41f8e17c, 0x41f9ae49, 0x41fa7b16, 0x41f8e1b1, 0x41f9ae7d, 0x41fa7b4a, 0x00000006, +0x5f313366, 0x00000032, 0x00000003, 0x00000002, 0x0000088c, 0x00000000, 0x00000002, 0x00000003, +0x00000002, 0x420070be, 0x4200d724, 0x42013d8b, 0x42007afb, 0x4200e162, 0x420147c8, 0x420070d8, +0x4200d73f, 0x42013da5, 0x42007b16, 0x4200e17c, 0x420147e3, 0x00000006, 0x5f323366, 0x00000032, +0x00000003, 0x00000002, 0x000008fc, 0x00000000, 0x00000002, 0x00000003, 0x00000003, 0x420470be, +0x4204d724, 0x42053d8b, 0x42047afb, 0x4204e162, 0x420547c8, 0x42048539, 0x4204eb9f, 0x42055206, +0x420470d8, 0x4204d73f, 0x42053da5, 0x42047b16, 0x4204e17c, 0x420547e3, 0x42048553, 0x4204ebba, +0x42055220, 0x00000006, 0x5f333366, 0x00000032, 0x00000003, 0x00000002, 0x00000984, 0x00000000, +0x00000002, 0x00000003, 0x00000004, 0x420870be, 0x4208d724, 0x42093d8b, 0x42087afb, 0x4208e162, +0x420947c8, 0x42088539, 0x4208eb9f, 0x42095206, 0x42088f76, 0x4208f5dd, 0x42095c43, 0x420870d8, +0x4208d73f, 0x42093da5, 0x42087b16, 0x4208e17c, 0x420947e3, 0x42088553, 0x4208ebba, 0x42095220, +0x42088f91, 0x4208f5f7, 0x42095c5d, 0x00000006, 0x5f343366, 0x00000032, 0x00000003, 0x00000002, +0x000009cc, 0x00000000, 0x00000002, 0x00000004, 0x00000001, 0x422470be, 0x4224d724, 0x42253d8b, +0x4225a3f1, 0x422470d8, 0x4224d73f, 0x42253da5, 0x4225a40b, 0x00000006, 0x5f313466, 0x00000032, +0x00000003, 0x00000002, 0x00000a34, 0x00000000, 0x00000002, 0x00000004, 0x00000002, 0x422870be, +0x4228d724, 0x42293d8b, 0x4229a3f1, 0x42287afb, 0x4228e162, 0x422947c8, 0x4229ae2f, 0x422870d8, +0x4228d73f, 0x42293da5, 0x4229a40b, 0x42287b16, 0x4228e17c, 0x422947e3, 0x4229ae49, 0x00000006, +0x5f323466, 0x00000032, 0x00000003, 0x00000002, 0x00000abc, 0x00000000, 0x00000002, 0x00000004, +0x00000003, 0x422c70be, 0x422cd724, 0x422d3d8b, 0x422da3f1, 0x422c7afb, 0x422ce162, 0x422d47c8, +0x422dae2f, 0x422c8539, 0x422ceb9f, 0x422d5206, 0x422db86c, 0x422c70d8, 0x422cd73f, 0x422d3da5, +0x422da40b, 0x422c7b16, 0x422ce17c, 0x422d47e3, 0x422dae49, 0x422c8553, 0x422cebba, 0x422d5220, +0x422db886, 0x00000006, 0x5f333466, 0x00000032, 0x00000003, 0x00000002, 0x00000b64, 0x00000000, +0x00000002, 0x00000004, 0x00000004, 0x423070be, 0x4230d724, 0x42313d8b, 0x4231a3f1, 0x42307afb, +0x4230e162, 0x423147c8, 0x4231ae2f, 0x42308539, 0x4230eb9f, 0x42315206, 0x4231b86c, 0x42308f76, +0x4230f5dd, 0x42315c43, 0x4231c2aa, 0x423070d8, 0x4230d73f, 0x42313da5, 0x4231a40b, 0x42307b16, +0x4230e17c, 0x423147e3, 0x4231ae49, 0x42308553, 0x4230ebba, 0x42315220, 0x4231b886, 0x42308f91, +0x4230f5f7, 0x42315c5d, 0x4231c2c4, 0x00000006, 0x5f343466, 0x00000032, 0x00000002, 0x00000070, +0x00000002, 0x00000074, 0x0000002a, 0x00000001, 0x00000001, 0x00000001, 0x00000004, 0x00000020, +0x00000000, 0x00000000, 0x0000002c, 0x00000048, 0x00000000, 0x00000000, 0x00000054, 0x00000070, +0x00000000, 0x00000000, 0x00000080, 0x0000009c, 0x00000000, 0x00000000, 0x000000b0, 0x000000cc, +0x00000000, 0x00000000, 0x000000e4, 0x00000100, 0x00000000, 0x00000000, 0x0000010c, 0x00000128, +0x00000000, 0x00000000, 0x00000138, 0x00000154, 0x00000000, 0x00000000, 0x00000168, 0x00000184, +0x00000000, 0x00000000, 0x0000019c, 0x000001b8, 0x00000000, 0x00000000, 0x000001c8, 0x000001e4, +0x00000000, 0x00000000, 0x000001fc, 0x00000218, 0x00000000, 0x00000000, 0x00000238, 0x00000254, +0x00000000, 0x00000000, 0x0000027c, 0x00000298, 0x00000000, 0x00000000, 0x000002ac, 0x000002c8, +0x00000000, 0x00000000, 0x000002e8, 0x00000304, 0x00000000, 0x00000000, 0x00000330, 0x0000034c, +0x00000000, 0x00000000, 0x00000384, 0x000003a0, 0x00000000, 0x00000000, 0x000003b8, 0x000003d4, +0x00000000, 0x00000000, 0x000003fc, 0x00000418, 0x00000000, 0x00000000, 0x00000450, 0x0000046c, +0x00000000, 0x00000000, 0x000004b4, 0x000004d0, 0x00000000, 0x00000000, 0x000004e0, 0x000004fc, +0x00000000, 0x00000000, 0x00000510, 0x0000052c, 0x00000000, 0x00000000, 0x00000548, 0x00000564, +0x00000000, 0x00000000, 0x00000588, 0x000005a4, 0x00000000, 0x00000000, 0x000005d0, 0x000005ec, +0x00000000, 0x00000000, 0x00000600, 0x0000061c, 0x00000000, 0x00000000, 0x00000638, 0x00000654, +0x00000000, 0x00000000, 0x00000678, 0x00000694, 0x00000000, 0x00000000, 0x000006c0, 0x000006dc, +0x00000000, 0x00000000, 0x000006f8, 0x00000714, 0x00000000, 0x00000000, 0x00000740, 0x0000075c, +0x00000000, 0x00000000, 0x00000798, 0x000007b4, 0x00000000, 0x00000000, 0x00000800, 0x0000081c, +0x00000000, 0x00000000, 0x00000840, 0x0000085c, 0x00000000, 0x00000000, 0x00000898, 0x000008b4, +0x00000000, 0x00000000, 0x00000908, 0x00000924, 0x00000000, 0x00000000, 0x00000990, 0x000009ac, +0x00000000, 0x00000000, 0x000009d8, 0x000009f4, 0x00000000, 0x00000000, 0x00000a40, 0x00000a5c, +0x00000000, 0x00000000, 0x00000ac8, 0x00000ae4, 0x00000000, 0x00000000, 0x00000b78, 0x00000000, +0x00000001, 0x00000b70, 0x00000000, 0x00000000, 0x00000000, 0x00000000, +}; + +struct test_effect_parameter_value_result test_effect_parameter_value_result_float[] = +{ + {"f", {"f", NULL, D3DXPC_SCALAR, D3DXPT_FLOAT, 1, 1, 0, 0, 0, 0, 4}, 10}, + {"f1", {"f1", NULL, D3DXPC_VECTOR, D3DXPT_FLOAT, 1, 1, 0, 0, 0, 0, 4}, 20}, + {"f2", {"f2", NULL, D3DXPC_VECTOR, D3DXPT_FLOAT, 1, 2, 0, 0, 0, 0, 8}, 30}, + {"f3", {"f3", NULL, D3DXPC_VECTOR, D3DXPT_FLOAT, 1, 3, 0, 0, 0, 0, 12}, 41}, + {"f4", {"f4", NULL, D3DXPC_VECTOR, D3DXPT_FLOAT, 1, 4, 0, 0, 0, 0, 16}, 53}, + {"f11", {"f11", NULL, D3DXPC_MATRIX_ROWS, D3DXPT_FLOAT, 1, 1, 0, 0, 0, 0, 4}, 66}, + {"f12", {"f12", NULL, D3DXPC_MATRIX_ROWS, D3DXPT_FLOAT, 1, 2, 0, 0, 0, 0, 8}, 76}, + {"f13", {"f13", NULL, D3DXPC_MATRIX_ROWS, D3DXPT_FLOAT, 1, 3, 0, 0, 0, 0, 12}, 87}, + {"f14", {"f14", NULL, D3DXPC_MATRIX_ROWS, D3DXPT_FLOAT, 1, 4, 0, 0, 0, 0, 16}, 99}, + {"f21", {"f21", NULL, D3DXPC_MATRIX_ROWS, D3DXPT_FLOAT, 2, 1, 0, 0, 0, 0, 8}, 112}, + {"f22", {"f22", NULL, D3DXPC_MATRIX_ROWS, D3DXPT_FLOAT, 2, 2, 0, 0, 0, 0, 16}, 123}, + {"f23", {"f23", NULL, D3DXPC_MATRIX_ROWS, D3DXPT_FLOAT, 2, 3, 0, 0, 0, 0, 24}, 136}, + {"f24", {"f24", NULL, D3DXPC_MATRIX_ROWS, D3DXPT_FLOAT, 2, 4, 0, 0, 0, 0, 32}, 151}, + {"f31", {"f31", NULL, D3DXPC_MATRIX_ROWS, D3DXPT_FLOAT, 3, 1, 0, 0, 0, 0, 12}, 168}, + {"f32", {"f32", NULL, D3DXPC_MATRIX_ROWS, D3DXPT_FLOAT, 3, 2, 0, 0, 0, 0, 24}, 180}, + {"f33", {"f33", NULL, D3DXPC_MATRIX_ROWS, D3DXPT_FLOAT, 3, 3, 0, 0, 0, 0, 36}, 195}, + {"f34", {"f34", NULL, D3DXPC_MATRIX_ROWS, D3DXPT_FLOAT, 3, 4, 0, 0, 0, 0, 48}, 213}, + {"f41", {"f41", NULL, D3DXPC_MATRIX_ROWS, D3DXPT_FLOAT, 4, 1, 0, 0, 0, 0, 16}, 234}, + {"f42", {"f42", NULL, D3DXPC_MATRIX_ROWS, D3DXPT_FLOAT, 4, 2, 0, 0, 0, 0, 32}, 247}, + {"f43", {"f43", NULL, D3DXPC_MATRIX_ROWS, D3DXPT_FLOAT, 4, 3, 0, 0, 0, 0, 48}, 264}, + {"f44", {"f44", NULL, D3DXPC_MATRIX_ROWS, D3DXPT_FLOAT, 4, 4, 0, 0, 0, 0, 64}, 285}, + {"f_2", {"f_2", NULL, D3DXPC_SCALAR, D3DXPT_FLOAT, 1, 1, 2, 0, 0, 0, 8}, 310}, + {"f1_2", {"f1_2", NULL, D3DXPC_VECTOR, D3DXPT_FLOAT, 1, 1, 2, 0, 0, 0, 8}, 321}, + {"f2_2", {"f2_2", NULL, D3DXPC_VECTOR, D3DXPT_FLOAT, 1, 2, 2, 0, 0, 0, 16}, 333}, + {"f3_2", {"f3_2", NULL, D3DXPC_VECTOR, D3DXPT_FLOAT, 1, 3, 2, 0, 0, 0, 24}, 347}, + {"f4_2", {"f4_2", NULL, D3DXPC_VECTOR, D3DXPT_FLOAT, 1, 4, 2, 0, 0, 0, 32}, 363}, + {"f11_2", {"f11_2", NULL, D3DXPC_MATRIX_ROWS, D3DXPT_FLOAT, 1, 1, 2, 0, 0, 0, 8}, 381}, + {"f12_2", {"f12_2", NULL, D3DXPC_MATRIX_ROWS, D3DXPT_FLOAT, 1, 2, 2, 0, 0, 0, 16}, 393}, + {"f13_2", {"f13_2", NULL, D3DXPC_MATRIX_ROWS, D3DXPT_FLOAT, 1, 3, 2, 0, 0, 0, 24}, 407}, + {"f14_2", {"f14_2", NULL, D3DXPC_MATRIX_ROWS, D3DXPT_FLOAT, 1, 4, 2, 0, 0, 0, 32}, 423}, + {"f21_2", {"f21_2", NULL, D3DXPC_MATRIX_ROWS, D3DXPT_FLOAT, 2, 1, 2, 0, 0, 0, 16}, 441}, + {"f22_2", {"f22_2", NULL, D3DXPC_MATRIX_ROWS, D3DXPT_FLOAT, 2, 2, 2, 0, 0, 0, 32}, 455}, + {"f23_2", {"f23_2", NULL, D3DXPC_MATRIX_ROWS, D3DXPT_FLOAT, 2, 3, 2, 0, 0, 0, 48}, 473}, + {"f24_2", {"f24_2", NULL, D3DXPC_MATRIX_ROWS, D3DXPT_FLOAT, 2, 4, 2, 0, 0, 0, 64}, 495}, + {"f31_2", {"f31_2", NULL, D3DXPC_MATRIX_ROWS, D3DXPT_FLOAT, 3, 1, 2, 0, 0, 0, 24}, 521}, + {"f32_2", {"f32_2", NULL, D3DXPC_MATRIX_ROWS, D3DXPT_FLOAT, 3, 2, 2, 0, 0, 0, 48}, 537}, + {"f33_2", {"f33_2", NULL, D3DXPC_MATRIX_ROWS, D3DXPT_FLOAT, 3, 3, 2, 0, 0, 0, 72}, 559}, + {"f34_2", {"f34_2", NULL, D3DXPC_MATRIX_ROWS, D3DXPT_FLOAT, 3, 4, 2, 0, 0, 0, 96}, 587}, + {"f41_2", {"f41_2", NULL, D3DXPC_MATRIX_ROWS, D3DXPT_FLOAT, 4, 1, 2, 0, 0, 0, 32}, 621}, + {"f42_2", {"f42_2", NULL, D3DXPC_MATRIX_ROWS, D3DXPT_FLOAT, 4, 2, 2, 0, 0, 0, 64}, 639}, + {"f43_2", {"f43_2", NULL, D3DXPC_MATRIX_ROWS, D3DXPT_FLOAT, 4, 3, 2, 0, 0, 0, 96}, 665}, + {"f44_2", {"f44_2", NULL, D3DXPC_MATRIX_ROWS, D3DXPT_FLOAT, 4, 4, 2, 0, 0, 0, 128}, 699}, +}; + +/* + * fxc.exe /Tfx_2_0 + */ +#if 0 +int i = 1; +int1 i1 = {11}; +int2 i2 = {21, 22}; +int3 i3 = {31, 32, 33}; +int4 i4 = {41, 42, 43, 44}; +int1x1 i11 = {111}; +int1x2 i12 = {121, 122}; +int1x3 i13 = {131, 132, 133}; +int1x4 i14 = {141, 142, 143, 144}; +int2x1 i21 = {{2111, 2121}}; +int2x2 i22 = {{2211, 2221}, {2212, 2222}}; +int2x3 i23 = {{2311, 2321}, {2312, 2322}, {2313, 2323}}; +int2x4 i24 = {{2411, 2421}, {2412, 2422}, {2413, 2423}, {2414, 2424}}; +int3x1 i31 = {{3111, 3121, 3131}}; +int3x2 i32 = {{3211, 3221, 3231}, {3212, 3222, 3232}}; +int3x3 i33 = {{3311, 3321, 3331}, {3312, 3322, 3332}, + {3313, 3323, 3333}}; +int3x4 i34 = {{3411, 3421, 3431}, {3412, 3422, 3432}, + {3413, 3423, 3433}, {3414, 3424, 3434}}; +int4x1 i41 = {{4111, 4121, 4131, 4141}}; +int4x2 i42 = {{4211, 4221, 4231, 4241}, {4212, 4222, 4232, 4242}}; +int4x3 i43 = {{4311, 4321, 4331, 4341}, {4312, 4322, 4332, 4342}, + {4313, 4323, 4333, 4343}}; +int4x4 i44 = {{4411, 4421, 4431, 4441}, {4412, 4422, 4432, 4442}, + {4413, 4423, 4433, 4443}, {4414, 4424, 4434, 4444}}; +int i_2[2] = {0101, 0102}; +int1 i1_2[2] = {{1101}, {1102}}; +int2 i2_2[2] = {{2101, 2201}, {2102, 2202}}; +int3 i3_2[2] = {{3101, 3201, 3301}, {3102, 3202, 3302}}; +int4 i4_2[2] = {{4101, 4201, 4301, 4401}, {4102, 4202, 4302, 4402}}; +int1x1 i11_2[2] = {{11101}, {11102}}; +int1x2 i12_2[2] = {{12101, 12201}, {12102, 12202}}; +int1x3 i13_2[2] = {{13101, 13201, 13301}, {13102, 13202, 13302}}; +int1x4 i14_2[2] = {{14101, 14201, 14301, 14401}, {14102, 14202, 14302, 14402}}; +int2x1 i21_2[2] = {{{211101, 212101}}, {{211102, 212102}}}; +int2x2 i22_2[2] = {{{221101, 222101}, {221201, 222201}}, {{221102, 222102}, {221202, 222202}}}; +int2x3 i23_2[2] = {{{231101, 232101}, {231201, 232201}, {231301, 232301}}, {{231102, 232102}, + {231202, 232202}, {231302, 232302}}}; +int2x4 i24_2[2] = {{{241101, 242101}, {241201, 242201}, {241301, 242301}, {241401, 242401}}, + {{241102, 242102}, {241202, 242202}, {241302, 242302}, {241402, 242402}}}; +int3x1 i31_2[2] = {{{311101, 312101, 313101}}, {{311102, 312102, 313102}}}; +int3x2 i32_2[2] = {{{321101, 322101, 323101}, {321201, 322201, 323201}}, + {{321102, 322102, 323102}, {321202, 322202, 323202}}}; +int3x3 i33_2[2] = {{{331101, 332101, 333101}, {331201, 332201, 333201}, + {331301, 332301, 333301}}, {{331102, 332102, 333102}, {331202, 332202, 333202}, + {331302, 332302, 333302}}}; +int3x4 i34_2[2] = {{{341101, 342101, 343101}, {341201, 342201, 343201}, + {341301, 342301, 343301}, {341401, 342401, 343401}}, {{341102, 342102, 343102}, + {341202, 342202, 343202}, {341302, 342302, 343302}, {341402, 342402, 343402}}}; +int4x1 i41_2[2] = {{{411101, 412101, 413101, 414101}}, {{411102, 412102, 413102, 414102}}}; +int4x2 i42_2[2] = {{{421101, 422101, 423101, 424101}, {421201, 422201, 423201, 424201}}, + {{421102, 422102, 423102, 424102}, {421202, 422202, 423202, 424202}}}; +int4x3 i43_2[2] = {{{431101, 432101, 433101, 434101}, {431201, 432201, 433201, 434201}, + {431301, 432301, 433301, 434301}}, {{431102, 432102, 433102, 434102}, + {431202, 432202, 433202, 434202}, {431302, 432302, 433302, 434302}}}; +int4x4 i44_2[2] = {{{441101, 442101, 443101, 444101}, {441201, 442201, 443201, 444201}, + {441301, 442301, 443301, 444301}, {441401, 442401, 443401, 444401}}, + {{441102, 442102, 443102, 444102}, {441202, 442202, 443202, 444202}, + {441302, 442302, 443302, 444302}, {441402, 442402, 443402, 444402}}}; +technique t { pass p { } } +#endif +static const DWORD test_effect_parameter_value_blob_int[] = +{ +0xfeff0901, 0x00000b80, 0x00000000, 0x00000002, 0x00000000, 0x00000024, 0x00000000, 0x00000000, +0x00000001, 0x00000001, 0x00000001, 0x00000002, 0x00000069, 0x00000002, 0x00000001, 0x0000004c, +0x00000000, 0x00000000, 0x00000001, 0x00000001, 0x0000000b, 0x00000003, 0x00003169, 0x00000002, +0x00000001, 0x00000078, 0x00000000, 0x00000000, 0x00000002, 0x00000001, 0x00000015, 0x00000016, +0x00000003, 0x00003269, 0x00000002, 0x00000001, 0x000000a8, 0x00000000, 0x00000000, 0x00000003, +0x00000001, 0x0000001f, 0x00000020, 0x00000021, 0x00000003, 0x00003369, 0x00000002, 0x00000001, +0x000000dc, 0x00000000, 0x00000000, 0x00000004, 0x00000001, 0x00000029, 0x0000002a, 0x0000002b, +0x0000002c, 0x00000003, 0x00003469, 0x00000002, 0x00000002, 0x00000104, 0x00000000, 0x00000000, +0x00000001, 0x00000001, 0x0000006f, 0x00000004, 0x00313169, 0x00000002, 0x00000002, 0x00000130, +0x00000000, 0x00000000, 0x00000001, 0x00000002, 0x00000079, 0x0000007a, 0x00000004, 0x00323169, +0x00000002, 0x00000002, 0x00000160, 0x00000000, 0x00000000, 0x00000001, 0x00000003, 0x00000083, +0x00000084, 0x00000085, 0x00000004, 0x00333169, 0x00000002, 0x00000002, 0x00000194, 0x00000000, +0x00000000, 0x00000001, 0x00000004, 0x0000008d, 0x0000008e, 0x0000008f, 0x00000090, 0x00000004, +0x00343169, 0x00000002, 0x00000002, 0x000001c0, 0x00000000, 0x00000000, 0x00000002, 0x00000001, +0x0000083f, 0x00000849, 0x00000004, 0x00313269, 0x00000002, 0x00000002, 0x000001f4, 0x00000000, +0x00000000, 0x00000002, 0x00000002, 0x000008a3, 0x000008ad, 0x000008a4, 0x000008ae, 0x00000004, +0x00323269, 0x00000002, 0x00000002, 0x00000230, 0x00000000, 0x00000000, 0x00000002, 0x00000003, +0x00000907, 0x00000911, 0x00000908, 0x00000912, 0x00000909, 0x00000913, 0x00000004, 0x00333269, +0x00000002, 0x00000002, 0x00000274, 0x00000000, 0x00000000, 0x00000002, 0x00000004, 0x0000096b, +0x00000975, 0x0000096c, 0x00000976, 0x0000096d, 0x00000977, 0x0000096e, 0x00000978, 0x00000004, +0x00343269, 0x00000002, 0x00000002, 0x000002a4, 0x00000000, 0x00000000, 0x00000003, 0x00000001, +0x00000c27, 0x00000c31, 0x00000c3b, 0x00000004, 0x00313369, 0x00000002, 0x00000002, 0x000002e0, +0x00000000, 0x00000000, 0x00000003, 0x00000002, 0x00000c8b, 0x00000c95, 0x00000c9f, 0x00000c8c, +0x00000c96, 0x00000ca0, 0x00000004, 0x00323369, 0x00000002, 0x00000002, 0x00000328, 0x00000000, +0x00000000, 0x00000003, 0x00000003, 0x00000cef, 0x00000cf9, 0x00000d03, 0x00000cf0, 0x00000cfa, +0x00000d04, 0x00000cf1, 0x00000cfb, 0x00000d05, 0x00000004, 0x00333369, 0x00000002, 0x00000002, +0x0000037c, 0x00000000, 0x00000000, 0x00000003, 0x00000004, 0x00000d53, 0x00000d5d, 0x00000d67, +0x00000d54, 0x00000d5e, 0x00000d68, 0x00000d55, 0x00000d5f, 0x00000d69, 0x00000d56, 0x00000d60, +0x00000d6a, 0x00000004, 0x00343369, 0x00000002, 0x00000002, 0x000003b0, 0x00000000, 0x00000000, +0x00000004, 0x00000001, 0x0000100f, 0x00001019, 0x00001023, 0x0000102d, 0x00000004, 0x00313469, +0x00000002, 0x00000002, 0x000003f4, 0x00000000, 0x00000000, 0x00000004, 0x00000002, 0x00001073, +0x0000107d, 0x00001087, 0x00001091, 0x00001074, 0x0000107e, 0x00001088, 0x00001092, 0x00000004, +0x00323469, 0x00000002, 0x00000002, 0x00000448, 0x00000000, 0x00000000, 0x00000004, 0x00000003, +0x000010d7, 0x000010e1, 0x000010eb, 0x000010f5, 0x000010d8, 0x000010e2, 0x000010ec, 0x000010f6, +0x000010d9, 0x000010e3, 0x000010ed, 0x000010f7, 0x00000004, 0x00333469, 0x00000002, 0x00000002, +0x000004ac, 0x00000000, 0x00000000, 0x00000004, 0x00000004, 0x0000113b, 0x00001145, 0x0000114f, +0x00001159, 0x0000113c, 0x00001146, 0x00001150, 0x0000115a, 0x0000113d, 0x00001147, 0x00001151, +0x0000115b, 0x0000113e, 0x00001148, 0x00001152, 0x0000115c, 0x00000004, 0x00343469, 0x00000002, +0x00000000, 0x000004d8, 0x00000000, 0x00000002, 0x00000001, 0x00000001, 0x00000041, 0x00000042, +0x00000004, 0x00325f69, 0x00000002, 0x00000001, 0x00000504, 0x00000000, 0x00000002, 0x00000001, +0x00000001, 0x0000044d, 0x0000044e, 0x00000005, 0x325f3169, 0x00000000, 0x00000002, 0x00000001, +0x0000053c, 0x00000000, 0x00000002, 0x00000002, 0x00000001, 0x00000835, 0x00000899, 0x00000836, +0x0000089a, 0x00000005, 0x325f3269, 0x00000000, 0x00000002, 0x00000001, 0x0000057c, 0x00000000, +0x00000002, 0x00000003, 0x00000001, 0x00000c1d, 0x00000c81, 0x00000ce5, 0x00000c1e, 0x00000c82, +0x00000ce6, 0x00000005, 0x325f3369, 0x00000000, 0x00000002, 0x00000001, 0x000005c4, 0x00000000, +0x00000002, 0x00000004, 0x00000001, 0x00001005, 0x00001069, 0x000010cd, 0x00001131, 0x00001006, +0x0000106a, 0x000010ce, 0x00001132, 0x00000005, 0x325f3469, 0x00000000, 0x00000002, 0x00000002, +0x000005f4, 0x00000000, 0x00000002, 0x00000001, 0x00000001, 0x00002b5d, 0x00002b5e, 0x00000006, +0x5f313169, 0x00000032, 0x00000002, 0x00000002, 0x0000062c, 0x00000000, 0x00000002, 0x00000001, +0x00000002, 0x00002f45, 0x00002fa9, 0x00002f46, 0x00002faa, 0x00000006, 0x5f323169, 0x00000032, +0x00000002, 0x00000002, 0x0000066c, 0x00000000, 0x00000002, 0x00000001, 0x00000003, 0x0000332d, +0x00003391, 0x000033f5, 0x0000332e, 0x00003392, 0x000033f6, 0x00000006, 0x5f333169, 0x00000032, +0x00000002, 0x00000002, 0x000006b4, 0x00000000, 0x00000002, 0x00000001, 0x00000004, 0x00003715, +0x00003779, 0x000037dd, 0x00003841, 0x00003716, 0x0000377a, 0x000037de, 0x00003842, 0x00000006, +0x5f343169, 0x00000032, 0x00000002, 0x00000002, 0x000006ec, 0x00000000, 0x00000002, 0x00000002, +0x00000001, 0x0003389d, 0x00033c85, 0x0003389e, 0x00033c86, 0x00000006, 0x5f313269, 0x00000032, +0x00000002, 0x00000002, 0x00000734, 0x00000000, 0x00000002, 0x00000002, 0x00000002, 0x00035fad, +0x00036395, 0x00036011, 0x000363f9, 0x00035fae, 0x00036396, 0x00036012, 0x000363fa, 0x00000006, +0x5f323269, 0x00000032, 0x00000002, 0x00000002, 0x0000078c, 0x00000000, 0x00000002, 0x00000002, +0x00000003, 0x000386bd, 0x00038aa5, 0x00038721, 0x00038b09, 0x00038785, 0x00038b6d, 0x000386be, +0x00038aa6, 0x00038722, 0x00038b0a, 0x00038786, 0x00038b6e, 0x00000006, 0x5f333269, 0x00000032, +0x00000002, 0x00000002, 0x000007f4, 0x00000000, 0x00000002, 0x00000002, 0x00000004, 0x0003adcd, +0x0003b1b5, 0x0003ae31, 0x0003b219, 0x0003ae95, 0x0003b27d, 0x0003aef9, 0x0003b2e1, 0x0003adce, +0x0003b1b6, 0x0003ae32, 0x0003b21a, 0x0003ae96, 0x0003b27e, 0x0003aefa, 0x0003b2e2, 0x00000006, +0x5f343269, 0x00000032, 0x00000002, 0x00000002, 0x00000834, 0x00000000, 0x00000002, 0x00000003, +0x00000001, 0x0004bf3d, 0x0004c325, 0x0004c70d, 0x0004bf3e, 0x0004c326, 0x0004c70e, 0x00000006, +0x5f313369, 0x00000032, 0x00000002, 0x00000002, 0x0000088c, 0x00000000, 0x00000002, 0x00000003, +0x00000002, 0x0004e64d, 0x0004ea35, 0x0004ee1d, 0x0004e6b1, 0x0004ea99, 0x0004ee81, 0x0004e64e, +0x0004ea36, 0x0004ee1e, 0x0004e6b2, 0x0004ea9a, 0x0004ee82, 0x00000006, 0x5f323369, 0x00000032, +0x00000002, 0x00000002, 0x000008fc, 0x00000000, 0x00000002, 0x00000003, 0x00000003, 0x00050d5d, +0x00051145, 0x0005152d, 0x00050dc1, 0x000511a9, 0x00051591, 0x00050e25, 0x0005120d, 0x000515f5, +0x00050d5e, 0x00051146, 0x0005152e, 0x00050dc2, 0x000511aa, 0x00051592, 0x00050e26, 0x0005120e, +0x000515f6, 0x00000006, 0x5f333369, 0x00000032, 0x00000002, 0x00000002, 0x00000984, 0x00000000, +0x00000002, 0x00000003, 0x00000004, 0x0005346d, 0x00053855, 0x00053c3d, 0x000534d1, 0x000538b9, +0x00053ca1, 0x00053535, 0x0005391d, 0x00053d05, 0x00053599, 0x00053981, 0x00053d69, 0x0005346e, +0x00053856, 0x00053c3e, 0x000534d2, 0x000538ba, 0x00053ca2, 0x00053536, 0x0005391e, 0x00053d06, +0x0005359a, 0x00053982, 0x00053d6a, 0x00000006, 0x5f343369, 0x00000032, 0x00000002, 0x00000002, +0x000009cc, 0x00000000, 0x00000002, 0x00000004, 0x00000001, 0x000645dd, 0x000649c5, 0x00064dad, +0x00065195, 0x000645de, 0x000649c6, 0x00064dae, 0x00065196, 0x00000006, 0x5f313469, 0x00000032, +0x00000002, 0x00000002, 0x00000a34, 0x00000000, 0x00000002, 0x00000004, 0x00000002, 0x00066ced, +0x000670d5, 0x000674bd, 0x000678a5, 0x00066d51, 0x00067139, 0x00067521, 0x00067909, 0x00066cee, +0x000670d6, 0x000674be, 0x000678a6, 0x00066d52, 0x0006713a, 0x00067522, 0x0006790a, 0x00000006, +0x5f323469, 0x00000032, 0x00000002, 0x00000002, 0x00000abc, 0x00000000, 0x00000002, 0x00000004, +0x00000003, 0x000693fd, 0x000697e5, 0x00069bcd, 0x00069fb5, 0x00069461, 0x00069849, 0x00069c31, +0x0006a019, 0x000694c5, 0x000698ad, 0x00069c95, 0x0006a07d, 0x000693fe, 0x000697e6, 0x00069bce, +0x00069fb6, 0x00069462, 0x0006984a, 0x00069c32, 0x0006a01a, 0x000694c6, 0x000698ae, 0x00069c96, +0x0006a07e, 0x00000006, 0x5f333469, 0x00000032, 0x00000002, 0x00000002, 0x00000b64, 0x00000000, +0x00000002, 0x00000004, 0x00000004, 0x0006bb0d, 0x0006bef5, 0x0006c2dd, 0x0006c6c5, 0x0006bb71, +0x0006bf59, 0x0006c341, 0x0006c729, 0x0006bbd5, 0x0006bfbd, 0x0006c3a5, 0x0006c78d, 0x0006bc39, +0x0006c021, 0x0006c409, 0x0006c7f1, 0x0006bb0e, 0x0006bef6, 0x0006c2de, 0x0006c6c6, 0x0006bb72, +0x0006bf5a, 0x0006c342, 0x0006c72a, 0x0006bbd6, 0x0006bfbe, 0x0006c3a6, 0x0006c78e, 0x0006bc3a, +0x0006c022, 0x0006c40a, 0x0006c7f2, 0x00000006, 0x5f343469, 0x00000032, 0x00000002, 0x00000070, +0x00000002, 0x00000074, 0x0000002a, 0x00000001, 0x00000001, 0x00000001, 0x00000004, 0x00000020, +0x00000000, 0x00000000, 0x0000002c, 0x00000048, 0x00000000, 0x00000000, 0x00000054, 0x00000070, +0x00000000, 0x00000000, 0x00000080, 0x0000009c, 0x00000000, 0x00000000, 0x000000b0, 0x000000cc, +0x00000000, 0x00000000, 0x000000e4, 0x00000100, 0x00000000, 0x00000000, 0x0000010c, 0x00000128, +0x00000000, 0x00000000, 0x00000138, 0x00000154, 0x00000000, 0x00000000, 0x00000168, 0x00000184, +0x00000000, 0x00000000, 0x0000019c, 0x000001b8, 0x00000000, 0x00000000, 0x000001c8, 0x000001e4, +0x00000000, 0x00000000, 0x000001fc, 0x00000218, 0x00000000, 0x00000000, 0x00000238, 0x00000254, +0x00000000, 0x00000000, 0x0000027c, 0x00000298, 0x00000000, 0x00000000, 0x000002ac, 0x000002c8, +0x00000000, 0x00000000, 0x000002e8, 0x00000304, 0x00000000, 0x00000000, 0x00000330, 0x0000034c, +0x00000000, 0x00000000, 0x00000384, 0x000003a0, 0x00000000, 0x00000000, 0x000003b8, 0x000003d4, +0x00000000, 0x00000000, 0x000003fc, 0x00000418, 0x00000000, 0x00000000, 0x00000450, 0x0000046c, +0x00000000, 0x00000000, 0x000004b4, 0x000004d0, 0x00000000, 0x00000000, 0x000004e0, 0x000004fc, +0x00000000, 0x00000000, 0x00000510, 0x0000052c, 0x00000000, 0x00000000, 0x00000548, 0x00000564, +0x00000000, 0x00000000, 0x00000588, 0x000005a4, 0x00000000, 0x00000000, 0x000005d0, 0x000005ec, +0x00000000, 0x00000000, 0x00000600, 0x0000061c, 0x00000000, 0x00000000, 0x00000638, 0x00000654, +0x00000000, 0x00000000, 0x00000678, 0x00000694, 0x00000000, 0x00000000, 0x000006c0, 0x000006dc, +0x00000000, 0x00000000, 0x000006f8, 0x00000714, 0x00000000, 0x00000000, 0x00000740, 0x0000075c, +0x00000000, 0x00000000, 0x00000798, 0x000007b4, 0x00000000, 0x00000000, 0x00000800, 0x0000081c, +0x00000000, 0x00000000, 0x00000840, 0x0000085c, 0x00000000, 0x00000000, 0x00000898, 0x000008b4, +0x00000000, 0x00000000, 0x00000908, 0x00000924, 0x00000000, 0x00000000, 0x00000990, 0x000009ac, +0x00000000, 0x00000000, 0x000009d8, 0x000009f4, 0x00000000, 0x00000000, 0x00000a40, 0x00000a5c, +0x00000000, 0x00000000, 0x00000ac8, 0x00000ae4, 0x00000000, 0x00000000, 0x00000b78, 0x00000000, +0x00000001, 0x00000b70, 0x00000000, 0x00000000, 0x00000000, 0x00000000, +}; + +struct test_effect_parameter_value_result test_effect_parameter_value_result_int[] = +{ + {"i", {"i", NULL, D3DXPC_SCALAR, D3DXPT_INT, 1, 1, 0, 0, 0, 0, 4}, 10}, + {"i1", {"i1", NULL, D3DXPC_VECTOR, D3DXPT_INT, 1, 1, 0, 0, 0, 0, 4}, 20}, + {"i2", {"i2", NULL, D3DXPC_VECTOR, D3DXPT_INT, 1, 2, 0, 0, 0, 0, 8}, 30}, + {"i3", {"i3", NULL, D3DXPC_VECTOR, D3DXPT_INT, 1, 3, 0, 0, 0, 0, 12}, 41}, + {"i4", {"i4", NULL, D3DXPC_VECTOR, D3DXPT_INT, 1, 4, 0, 0, 0, 0, 16}, 53}, + {"i11", {"i11", NULL, D3DXPC_MATRIX_ROWS, D3DXPT_INT, 1, 1, 0, 0, 0, 0, 4}, 66}, + {"i12", {"i12", NULL, D3DXPC_MATRIX_ROWS, D3DXPT_INT, 1, 2, 0, 0, 0, 0, 8}, 76}, + {"i13", {"i13", NULL, D3DXPC_MATRIX_ROWS, D3DXPT_INT, 1, 3, 0, 0, 0, 0, 12}, 87}, + {"i14", {"i14", NULL, D3DXPC_MATRIX_ROWS, D3DXPT_INT, 1, 4, 0, 0, 0, 0, 16}, 99}, + {"i21", {"i21", NULL, D3DXPC_MATRIX_ROWS, D3DXPT_INT, 2, 1, 0, 0, 0, 0, 8}, 112}, + {"i22", {"i22", NULL, D3DXPC_MATRIX_ROWS, D3DXPT_INT, 2, 2, 0, 0, 0, 0, 16}, 123}, + {"i23", {"i23", NULL, D3DXPC_MATRIX_ROWS, D3DXPT_INT, 2, 3, 0, 0, 0, 0, 24}, 136}, + {"i24", {"i24", NULL, D3DXPC_MATRIX_ROWS, D3DXPT_INT, 2, 4, 0, 0, 0, 0, 32}, 151}, + {"i31", {"i31", NULL, D3DXPC_MATRIX_ROWS, D3DXPT_INT, 3, 1, 0, 0, 0, 0, 12}, 168}, + {"i32", {"i32", NULL, D3DXPC_MATRIX_ROWS, D3DXPT_INT, 3, 2, 0, 0, 0, 0, 24}, 180}, + {"i33", {"i33", NULL, D3DXPC_MATRIX_ROWS, D3DXPT_INT, 3, 3, 0, 0, 0, 0, 36}, 195}, + {"i34", {"i34", NULL, D3DXPC_MATRIX_ROWS, D3DXPT_INT, 3, 4, 0, 0, 0, 0, 48}, 213}, + {"i41", {"i41", NULL, D3DXPC_MATRIX_ROWS, D3DXPT_INT, 4, 1, 0, 0, 0, 0, 16}, 234}, + {"i42", {"i42", NULL, D3DXPC_MATRIX_ROWS, D3DXPT_INT, 4, 2, 0, 0, 0, 0, 32}, 247}, + {"i43", {"i43", NULL, D3DXPC_MATRIX_ROWS, D3DXPT_INT, 4, 3, 0, 0, 0, 0, 48}, 264}, + {"i44", {"i44", NULL, D3DXPC_MATRIX_ROWS, D3DXPT_INT, 4, 4, 0, 0, 0, 0, 64}, 285}, + {"i_2", {"i_2", NULL, D3DXPC_SCALAR, D3DXPT_INT, 1, 1, 2, 0, 0, 0, 8}, 310}, + {"i1_2", {"i1_2", NULL, D3DXPC_VECTOR, D3DXPT_INT, 1, 1, 2, 0, 0, 0, 8}, 321}, + {"i2_2", {"i2_2", NULL, D3DXPC_VECTOR, D3DXPT_INT, 1, 2, 2, 0, 0, 0, 16}, 333}, + {"i3_2", {"i3_2", NULL, D3DXPC_VECTOR, D3DXPT_INT, 1, 3, 2, 0, 0, 0, 24}, 347}, + {"i4_2", {"i4_2", NULL, D3DXPC_VECTOR, D3DXPT_INT, 1, 4, 2, 0, 0, 0, 32}, 363}, + {"i11_2", {"i11_2", NULL, D3DXPC_MATRIX_ROWS, D3DXPT_INT, 1, 1, 2, 0, 0, 0, 8}, 381}, + {"i12_2", {"i12_2", NULL, D3DXPC_MATRIX_ROWS, D3DXPT_INT, 1, 2, 2, 0, 0, 0, 16}, 393}, + {"i13_2", {"i13_2", NULL, D3DXPC_MATRIX_ROWS, D3DXPT_INT, 1, 3, 2, 0, 0, 0, 24}, 407}, + {"i14_2", {"i14_2", NULL, D3DXPC_MATRIX_ROWS, D3DXPT_INT, 1, 4, 2, 0, 0, 0, 32}, 423}, + {"i21_2", {"i21_2", NULL, D3DXPC_MATRIX_ROWS, D3DXPT_INT, 2, 1, 2, 0, 0, 0, 16}, 441}, + {"i22_2", {"i22_2", NULL, D3DXPC_MATRIX_ROWS, D3DXPT_INT, 2, 2, 2, 0, 0, 0, 32}, 455}, + {"i23_2", {"i23_2", NULL, D3DXPC_MATRIX_ROWS, D3DXPT_INT, 2, 3, 2, 0, 0, 0, 48}, 473}, + {"i24_2", {"i24_2", NULL, D3DXPC_MATRIX_ROWS, D3DXPT_INT, 2, 4, 2, 0, 0, 0, 64}, 495}, + {"i31_2", {"i31_2", NULL, D3DXPC_MATRIX_ROWS, D3DXPT_INT, 3, 1, 2, 0, 0, 0, 24}, 521}, + {"i32_2", {"i32_2", NULL, D3DXPC_MATRIX_ROWS, D3DXPT_INT, 3, 2, 2, 0, 0, 0, 48}, 537}, + {"i33_2", {"i33_2", NULL, D3DXPC_MATRIX_ROWS, D3DXPT_INT, 3, 3, 2, 0, 0, 0, 72}, 559}, + {"i34_2", {"i34_2", NULL, D3DXPC_MATRIX_ROWS, D3DXPT_INT, 3, 4, 2, 0, 0, 0, 96}, 587}, + {"i41_2", {"i41_2", NULL, D3DXPC_MATRIX_ROWS, D3DXPT_INT, 4, 1, 2, 0, 0, 0, 32}, 621}, + {"i42_2", {"i42_2", NULL, D3DXPC_MATRIX_ROWS, D3DXPT_INT, 4, 2, 2, 0, 0, 0, 64}, 639}, + {"i43_2", {"i43_2", NULL, D3DXPC_MATRIX_ROWS, D3DXPT_INT, 4, 3, 2, 0, 0, 0, 96}, 665}, + {"i44_2", {"i44_2", NULL, D3DXPC_MATRIX_ROWS, D3DXPT_INT, 4, 4, 2, 0, 0, 0, 128}, 699}, +}; + +/* + * fxc.exe /Tfx_2_0 + */ +#if 0 +string s = "test"; +string s_2[2] = {"test1", "test2"}; +texture2D tex; +Vertexshader v; +Vertexshader v_2[2]; +Pixelshader p; +Pixelshader p_2[2]; +technique t { pass p { } } +#endif +static const DWORD test_effect_parameter_value_blob_object[] = +{ +0xfeff0901, 0x00000100, 0x00000000, 0x00000004, 0x00000004, 0x0000001c, 0x00000000, 0x00000000, +0x00000001, 0x00000002, 0x00000073, 0x00000004, 0x00000004, 0x00000040, 0x00000000, 0x00000002, +0x00000002, 0x00000003, 0x00000004, 0x00325f73, 0x00000007, 0x00000004, 0x00000060, 0x00000000, +0x00000000, 0x00000004, 0x00000004, 0x00786574, 0x00000010, 0x00000004, 0x00000080, 0x00000000, +0x00000000, 0x00000005, 0x00000002, 0x00000076, 0x00000010, 0x00000004, 0x000000a4, 0x00000000, +0x00000002, 0x00000006, 0x00000007, 0x00000004, 0x00325f76, 0x0000000f, 0x00000004, 0x000000c4, +0x00000000, 0x00000000, 0x00000008, 0x00000002, 0x00000070, 0x0000000f, 0x00000004, 0x000000e8, +0x00000000, 0x00000002, 0x00000009, 0x0000000a, 0x00000004, 0x00325f70, 0x00000002, 0x00000070, +0x00000002, 0x00000074, 0x00000007, 0x00000001, 0x00000007, 0x0000000b, 0x00000004, 0x00000018, +0x00000000, 0x00000000, 0x00000024, 0x00000038, 0x00000000, 0x00000000, 0x00000048, 0x0000005c, +0x00000000, 0x00000000, 0x00000068, 0x0000007c, 0x00000000, 0x00000000, 0x00000088, 0x0000009c, +0x00000000, 0x00000000, 0x000000ac, 0x000000c0, 0x00000000, 0x00000000, 0x000000cc, 0x000000e0, +0x00000000, 0x00000000, 0x000000f8, 0x00000000, 0x00000001, 0x000000f0, 0x00000000, 0x00000000, +0x0000000a, 0x00000000, 0x00000009, 0x00000000, 0x0000000a, 0x00000000, 0x00000008, 0x00000000, +0x00000006, 0x00000000, 0x00000007, 0x00000000, 0x00000005, 0x00000000, 0x00000004, 0x00000000, +0x00000002, 0x00000006, 0x74736574, 0x00000031, 0x00000003, 0x00000006, 0x74736574, 0x00000032, +0x00000001, 0x00000005, 0x74736574, 0x00000000, +}; + +struct test_effect_parameter_value_result test_effect_parameter_value_result_object[] = +{ + {"s", {"s", NULL, D3DXPC_OBJECT, D3DXPT_STRING, 0, 0, 0, 0, 0, 0, sizeof(void *)}, 0}, + {"s_2", {"s_2", NULL, D3DXPC_OBJECT, D3DXPT_STRING, 0, 0, 2, 0, 0, 0, 2 * sizeof(void *)}, 0}, + {"tex", {"tex", NULL, D3DXPC_OBJECT, D3DXPT_TEXTURE2D, 0, 0, 0, 0, 0, 0, sizeof(void *)}, 0}, + {"v", {"v", NULL, D3DXPC_OBJECT, D3DXPT_VERTEXSHADER, 0, 0, 0, 0, 0, 0, sizeof(void *)}, 0}, + {"v_2", {"v_2", NULL, D3DXPC_OBJECT, D3DXPT_VERTEXSHADER, 0, 0, 2, 0, 0, 0, 2 * sizeof(void *)}, 0}, + {"p", {"p", NULL, D3DXPC_OBJECT, D3DXPT_PIXELSHADER, 0, 0, 0, 0, 0, 0, sizeof(void *)}, 0}, + {"p_2", {"p_2", NULL, D3DXPC_OBJECT, D3DXPT_PIXELSHADER, 0, 0, 2, 0, 0, 0, 2 * sizeof(void *)}, 0}, +}; + +/* + * fxc.exe /Tfx_2_0 + */ +#if 0 +float3 f3 = {-3.1, 153.2, 283.3}; +float3 f3min = {-31.1, -31.2, -31.3}; +float3 f3max = {320.1, 320.2, 320.3}; +float4 f4 = {-4.1, 154.2, 284.3, 34.4}; +float4 f4min = {-41.1, -41.2, -41.3, -41.4}; +float4 f4max = {420.1, 42.20, 420.3, 420.4}; +technique t { pass p { } } +#endif +static const DWORD test_effect_parameter_value_blob_special[] = +{ +0xfeff0901, 0x00000150, 0x00000000, 0x00000003, 0x00000001, 0x0000002c, 0x00000000, 0x00000000, +0x00000003, 0x00000001, 0xc0466666, 0x43193333, 0x438da666, 0x00000003, 0x00003366, 0x00000003, +0x00000001, 0x0000005c, 0x00000000, 0x00000000, 0x00000003, 0x00000001, 0xc1f8cccd, 0xc1f9999a, +0xc1fa6666, 0x00000006, 0x696d3366, 0x0000006e, 0x00000003, 0x00000001, 0x00000090, 0x00000000, +0x00000000, 0x00000003, 0x00000001, 0x43a00ccd, 0x43a0199a, 0x43a02666, 0x00000006, 0x616d3366, +0x00000078, 0x00000003, 0x00000001, 0x000000c8, 0x00000000, 0x00000000, 0x00000004, 0x00000001, +0xc0833333, 0x431a3333, 0x438e2666, 0x4209999a, 0x00000003, 0x00003466, 0x00000003, 0x00000001, +0x000000fc, 0x00000000, 0x00000000, 0x00000004, 0x00000001, 0xc2246666, 0xc224cccd, 0xc2253333, +0xc225999a, 0x00000006, 0x696d3466, 0x0000006e, 0x00000003, 0x00000001, 0x00000134, 0x00000000, +0x00000000, 0x00000004, 0x00000001, 0x43d20ccd, 0x4228cccd, 0x43d22666, 0x43d23333, 0x00000006, +0x616d3466, 0x00000078, 0x00000002, 0x00000070, 0x00000002, 0x00000074, 0x00000006, 0x00000001, +0x00000001, 0x00000001, 0x00000004, 0x00000020, 0x00000000, 0x00000000, 0x00000034, 0x00000050, +0x00000000, 0x00000000, 0x00000068, 0x00000084, 0x00000000, 0x00000000, 0x0000009c, 0x000000b8, +0x00000000, 0x00000000, 0x000000d0, 0x000000ec, 0x00000000, 0x00000000, 0x00000108, 0x00000124, +0x00000000, 0x00000000, 0x00000148, 0x00000000, 0x00000001, 0x00000140, 0x00000000, 0x00000000, +0x00000000, 0x00000000, +}; + +struct test_effect_parameter_value_result test_effect_parameter_value_result_special[] = +{ + {"f3", {"f3", NULL, D3DXPC_VECTOR, D3DXPT_FLOAT, 1, 3, 0, 0, 0, 0, 12}, 10}, + {"f3min", {"f3min", NULL, D3DXPC_VECTOR, D3DXPT_FLOAT, 1, 3, 0, 0, 0, 0, 12}, 22}, + {"f3max", {"f3max", NULL, D3DXPC_VECTOR, D3DXPT_FLOAT, 1, 3, 0, 0, 0, 0, 12}, 35}, + {"f4", {"f4", NULL, D3DXPC_VECTOR, D3DXPT_FLOAT, 1, 4, 0, 0, 0, 0, 16}, 48}, + {"f4min", {"f4min", NULL, D3DXPC_VECTOR, D3DXPT_FLOAT, 1, 4, 0, 0, 0, 0, 16}, 61}, + {"f4max", {"f4max", NULL, D3DXPC_VECTOR, D3DXPT_FLOAT, 1, 4, 0, 0, 0, 0, 16}, 75}, +}; + +#define ADD_PARAMETER_VALUE(x) {\ + test_effect_parameter_value_blob_ ## x,\ + sizeof(test_effect_parameter_value_blob_ ## x),\ + test_effect_parameter_value_result_ ## x,\ + ARRAY_SIZE(test_effect_parameter_value_result_ ## x),\ +} + +static const struct +{ + const DWORD *blob; + UINT blob_size; + const struct test_effect_parameter_value_result *res; + UINT res_count; +} +test_effect_parameter_value_data[] = +{ + ADD_PARAMETER_VALUE(float), + ADD_PARAMETER_VALUE(int), + ADD_PARAMETER_VALUE(object), + ADD_PARAMETER_VALUE(special), +}; + +#undef ADD_PARAMETER_VALUE + +/* Multiple of 16 to cover complete matrices */ +#define EFFECT_PARAMETER_VALUE_ARRAY_SIZE 48 +/* Constants for special INT/FLOAT conversation */ +#define INT_FLOAT_MULTI 255.0f +#define INT_FLOAT_MULTI_INVERSE (1/INT_FLOAT_MULTI) + +static void test_effect_parameter_value_GetValue(const struct test_effect_parameter_value_result *res, + ID3DXEffect *effect, const DWORD *res_value, D3DXHANDLE parameter, UINT i) +{ + const D3DXPARAMETER_DESC *res_desc = &res->desc; + const char *res_full_name = res->full_name; + DWORD value[EFFECT_PARAMETER_VALUE_ARRAY_SIZE]; + HRESULT hr; + UINT l; + + memset(value, 0xab, sizeof(value)); + hr = effect->lpVtbl->GetValue(effect, parameter, value, res_desc->Bytes); + if (res_desc->Class == D3DXPC_SCALAR + || res_desc->Class == D3DXPC_VECTOR + || res_desc->Class == D3DXPC_MATRIX_ROWS) + { + ok(hr == D3D_OK, "%u - %s: GetValue failed, got %#x, expected %#x\n", i, res_full_name, hr, D3D_OK); + + for (l = 0; l < res_desc->Bytes / sizeof(*value); ++l) + { + ok(value[l] == res_value[l], "%u - %s: GetValue value[%u] failed, got %#x, expected %#x\n", + i, res_full_name, l, value[l], res_value[l]); + } + + for (l = res_desc->Bytes / sizeof(*value); l < EFFECT_PARAMETER_VALUE_ARRAY_SIZE; ++l) + { + ok(value[l] == 0xabababab, "%u - %s: GetValue value[%u] failed, got %#x, expected %#x\n", + i, res_full_name, l, value[l], 0xabababab); + } + } + else if (res_desc->Class == D3DXPC_OBJECT) + { + switch (res_desc->Type) + { + case D3DXPT_PIXELSHADER: + case D3DXPT_VERTEXSHADER: + case D3DXPT_TEXTURE2D: + ok(hr == D3D_OK, "%u - %s: GetValue failed, got %#x, expected %#x\n", i, res_full_name, hr, D3D_OK); + + for (l = 0; l < (res_desc->Elements ? res_desc->Elements : 1); ++l) + { + IUnknown *unk = *((IUnknown **)value + l); + if (unk) IUnknown_Release(unk); + } + break; + + case D3DXPT_STRING: + ok(hr == D3D_OK, "%u - %s: GetValue failed, got %#x, expected %#x\n", i, res_full_name, hr, D3D_OK); + break; + + default: + ok(0, "Type is %u, this should not happen!\n", res_desc->Type); + break; + } + } + else + { + ok(hr == D3DERR_INVALIDCALL, "%u - %s: GetValue failed, got %#x, expected %#x\n", + i, res_full_name, hr, D3DERR_INVALIDCALL); + + for (l = 0; l < EFFECT_PARAMETER_VALUE_ARRAY_SIZE; ++l) + { + ok(value[l] == 0xabababab, "%u - %s: GetValue value[%u] failed, got %#x, expected %#x\n", + i, res_full_name, l, value[l], 0xabababab); + } + } +} + +static void test_effect_parameter_value_GetBool(const struct test_effect_parameter_value_result *res, + ID3DXEffect *effect, const DWORD *res_value, D3DXHANDLE parameter, UINT i) +{ + const D3DXPARAMETER_DESC *res_desc = &res->desc; + const char *res_full_name = res->full_name; + BOOL bvalue = 0xabababab; + HRESULT hr; + + hr = effect->lpVtbl->GetBool(effect, parameter, &bvalue); + if (!res_desc->Elements && res_desc->Rows == 1 && res_desc->Columns == 1) + { + ok(hr == D3D_OK, "%u - %s: GetBool failed, got %#x, expected %#x\n", i, res_full_name, hr, D3D_OK); + ok(bvalue == get_bool(res_value), "%u - %s: GetBool bvalue failed, got %#x, expected %#x\n", + i, res_full_name, bvalue, get_bool(res_value)); + } + else + { + ok(hr == D3DERR_INVALIDCALL, "%u - %s: GetBool failed, got %#x, expected %#x\n", + i, res_full_name, hr, D3DERR_INVALIDCALL); + ok(bvalue == 0xabababab, "%u - %s: GetBool bvalue failed, got %#x, expected %#x\n", + i, res_full_name, bvalue, 0xabababab); + } +} + +static void test_effect_parameter_value_GetBoolArray(const struct test_effect_parameter_value_result *res, + ID3DXEffect *effect, const DWORD *res_value, D3DXHANDLE parameter, UINT i) +{ + const D3DXPARAMETER_DESC *res_desc = &res->desc; + const char *res_full_name = res->full_name; + BOOL bavalue[EFFECT_PARAMETER_VALUE_ARRAY_SIZE]; + HRESULT hr; + UINT l, err = 0; + + memset(bavalue, 0xab, sizeof(bavalue)); + hr = effect->lpVtbl->GetBoolArray(effect, parameter, bavalue, res_desc->Bytes / sizeof(*bavalue)); + if (res_desc->Class == D3DXPC_SCALAR + || res_desc->Class == D3DXPC_VECTOR + || res_desc->Class == D3DXPC_MATRIX_ROWS) + { + ok(hr == D3D_OK, "%u - %s: GetBoolArray failed, got %#x, expected %#x\n", i, res_full_name, hr, D3D_OK); + + for (l = 0; l < res_desc->Bytes / sizeof(*bavalue); ++l) + { + if (bavalue[l] != get_bool(&res_value[l])) ++err; + } + + for (l = res_desc->Bytes / sizeof(*bavalue); l < EFFECT_PARAMETER_VALUE_ARRAY_SIZE; ++l) + { + if (bavalue[l] != 0xabababab) ++err; + } + } + else + { + ok(hr == D3DERR_INVALIDCALL, "%u - %s: GetBoolArray failed, got %#x, expected %#x\n", + i, res_full_name, hr, D3DERR_INVALIDCALL); + + for (l = 0; l < EFFECT_PARAMETER_VALUE_ARRAY_SIZE; ++l) if (bavalue[l] != 0xabababab) ++err; + } + ok(!err, "%u - %s: GetBoolArray failed with %u errors\n", i, res_full_name, err); +} + +static void test_effect_parameter_value_GetInt(const struct test_effect_parameter_value_result *res, + ID3DXEffect *effect, const DWORD *res_value, D3DXHANDLE parameter, UINT i) +{ + const D3DXPARAMETER_DESC *res_desc = &res->desc; + const char *res_full_name = res->full_name; + INT ivalue = 0xabababab; + HRESULT hr; + + hr = effect->lpVtbl->GetInt(effect, parameter, &ivalue); + if (!res_desc->Elements && res_desc->Columns == 1 && res_desc->Rows == 1) + { + ok(hr == D3D_OK, "%u - %s: GetInt failed, got %#x, expected %#x\n", i, res_full_name, hr, D3D_OK); + ok(ivalue == get_int(res_desc->Type, res_value), "%u - %s: GetInt ivalue failed, got %i, expected %i\n", + i, res_full_name, ivalue, get_int(res_desc->Type, res_value)); + } + else if(!res_desc->Elements && res_desc->Type == D3DXPT_FLOAT && + ((res_desc->Class == D3DXPC_VECTOR && res_desc->Columns != 2) || + (res_desc->Class == D3DXPC_MATRIX_ROWS && res_desc->Rows != 2 && res_desc->Columns == 1))) + { + INT tmp; + + ok(hr == D3D_OK, "%u - %s: GetInt failed, got %#x, expected %#x\n", i, res_full_name, hr, D3D_OK); + + tmp = (INT)(min(max(0.0f, *((FLOAT *)res_value + 2)), 1.0f) * INT_FLOAT_MULTI); + tmp += ((INT)(min(max(0.0f, *((FLOAT *)res_value + 1)), 1.0f) * INT_FLOAT_MULTI)) << 8; + tmp += ((INT)(min(max(0.0f, *((FLOAT *)res_value + 0)), 1.0f) * INT_FLOAT_MULTI)) << 16; + if (res_desc->Columns * res_desc->Rows > 3) + { + tmp += ((INT)(min(max(0.0f, *((FLOAT *)res_value + 3)), 1.0f) * INT_FLOAT_MULTI)) << 24; + } + + ok(ivalue == tmp, "%u - %s: GetInt ivalue failed, got %x, expected %x\n", + i, res_full_name, ivalue, tmp); + } + else + { + ok(hr == D3DERR_INVALIDCALL, "%u - %s: GetInt failed, got %#x, expected %#x\n", + i, res_full_name, hr, D3DERR_INVALIDCALL); + ok(ivalue == 0xabababab, "%u - %s: GetInt ivalue failed, got %i, expected %i\n", + i, res_full_name, ivalue, 0xabababab); + } +} + +static void test_effect_parameter_value_GetIntArray(const struct test_effect_parameter_value_result *res, + ID3DXEffect *effect, const DWORD *res_value, D3DXHANDLE parameter, UINT i) +{ + const D3DXPARAMETER_DESC *res_desc = &res->desc; + const char *res_full_name = res->full_name; + INT iavalue[EFFECT_PARAMETER_VALUE_ARRAY_SIZE]; + HRESULT hr; + UINT l, err = 0; + + memset(iavalue, 0xab, sizeof(iavalue)); + hr = effect->lpVtbl->GetIntArray(effect, parameter, iavalue, res_desc->Bytes / sizeof(*iavalue)); + if (res_desc->Class == D3DXPC_SCALAR + || res_desc->Class == D3DXPC_VECTOR + || res_desc->Class == D3DXPC_MATRIX_ROWS) + { + ok(hr == D3D_OK, "%u - %s: GetIntArray failed, got %#x, expected %#x\n", i, res_full_name, hr, D3D_OK); + + for (l = 0; l < res_desc->Bytes / sizeof(*iavalue); ++l) + { + if (iavalue[l] != get_int(res_desc->Type, &res_value[l])) ++err; + } + + for (l = res_desc->Bytes / sizeof(*iavalue); l < EFFECT_PARAMETER_VALUE_ARRAY_SIZE; ++l) + { + if (iavalue[l] != 0xabababab) ++err; + } + } + else + { + ok(hr == D3DERR_INVALIDCALL, "%u - %s: GetIntArray failed, got %#x, expected %#x\n", + i, res_full_name, hr, D3DERR_INVALIDCALL); + + for (l = 0; l < EFFECT_PARAMETER_VALUE_ARRAY_SIZE; ++l) if (iavalue[l] != 0xabababab) ++err; + } + ok(!err, "%u - %s: GetIntArray failed with %u errors\n", i, res_full_name, err); +} + +static void test_effect_parameter_value_GetFloat(const struct test_effect_parameter_value_result *res, + ID3DXEffect *effect, const DWORD *res_value, D3DXHANDLE parameter, UINT i) +{ + const D3DXPARAMETER_DESC *res_desc = &res->desc; + const char *res_full_name = res->full_name; + HRESULT hr; + DWORD cmp = 0xabababab; + FLOAT fvalue = *(FLOAT *)&cmp; + + hr = effect->lpVtbl->GetFloat(effect, parameter, &fvalue); + if (!res_desc->Elements && res_desc->Columns == 1 && res_desc->Rows == 1) + { + ok(hr == D3D_OK, "%u - %s: GetFloat failed, got %#x, expected %#x\n", i, res_full_name, hr, D3D_OK); + ok(compare_float(fvalue, get_float(res_desc->Type, res_value), 512), "%u - %s: GetFloat fvalue failed, got %f, expected %f\n", + i, res_full_name, fvalue, get_float(res_desc->Type, res_value)); + } + else + { + ok(hr == D3DERR_INVALIDCALL, "%u - %s: GetFloat failed, got %#x, expected %#x\n", + i, res_full_name, hr, D3DERR_INVALIDCALL); + ok(fvalue == *(FLOAT *)&cmp, "%u - %s: GetFloat fvalue failed, got %f, expected %f\n", + i, res_full_name, fvalue, *(FLOAT *)&cmp); + } +} + +static void test_effect_parameter_value_GetFloatArray(const struct test_effect_parameter_value_result *res, + ID3DXEffect *effect, const DWORD *res_value, D3DXHANDLE parameter, UINT i) +{ + const D3DXPARAMETER_DESC *res_desc = &res->desc; + const char *res_full_name = res->full_name; + FLOAT favalue[EFFECT_PARAMETER_VALUE_ARRAY_SIZE]; + HRESULT hr; + UINT l, err = 0; + DWORD cmp = 0xabababab; + + memset(favalue, 0xab, sizeof(favalue)); + hr = effect->lpVtbl->GetFloatArray(effect, parameter, favalue, res_desc->Bytes / sizeof(*favalue)); + if (res_desc->Class == D3DXPC_SCALAR + || res_desc->Class == D3DXPC_VECTOR + || res_desc->Class == D3DXPC_MATRIX_ROWS) + { + ok(hr == D3D_OK, "%u - %s: GetFloatArray failed, got %#x, expected %#x\n", i, res_full_name, hr, D3D_OK); + + for (l = 0; l < res_desc->Bytes / sizeof(*favalue); ++l) + { + if (!compare_float(favalue[l], get_float(res_desc->Type, &res_value[l]), 512)) ++err; + } + + for (l = res_desc->Bytes / sizeof(*favalue); l < EFFECT_PARAMETER_VALUE_ARRAY_SIZE; ++l) + { + if (favalue[l] != *(FLOAT *)&cmp) ++err; + } + } + else + { + ok(hr == D3DERR_INVALIDCALL, "%u - %s: GetFloatArray failed, got %#x, expected %#x\n", + i, res_full_name, hr, D3DERR_INVALIDCALL); + + for (l = 0; l < EFFECT_PARAMETER_VALUE_ARRAY_SIZE; ++l) if (favalue[l] != *(FLOAT *)&cmp) ++err; + } + ok(!err, "%u - %s: GetFloatArray failed with %u errors\n", i, res_full_name, err); +} + +static void test_effect_parameter_value_GetVector(const struct test_effect_parameter_value_result *res, + ID3DXEffect *effect, const DWORD *res_value, D3DXHANDLE parameter, UINT i) +{ + const D3DXPARAMETER_DESC *res_desc = &res->desc; + const char *res_full_name = res->full_name; + HRESULT hr; + DWORD cmp = 0xabababab; + FLOAT fvalue[4]; + UINT l, err = 0; + + memset(fvalue, 0xab, sizeof(fvalue)); + hr = effect->lpVtbl->GetVector(effect, parameter, (D3DXVECTOR4 *)&fvalue); + if (!res_desc->Elements && + (res_desc->Class == D3DXPC_SCALAR || res_desc->Class == D3DXPC_VECTOR) && + res_desc->Type == D3DXPT_INT && res_desc->Bytes == 4) + { + DWORD tmp; + + ok(hr == D3D_OK, "%u - %s: GetVector failed, got %#x, expected %#x\n", i, res_full_name, hr, D3D_OK); + + tmp = (DWORD)(*(fvalue + 2) * INT_FLOAT_MULTI); + tmp += ((DWORD)(*(fvalue + 1) * INT_FLOAT_MULTI)) << 8; + tmp += ((DWORD)(*fvalue * INT_FLOAT_MULTI)) << 16; + tmp += ((DWORD)(*(fvalue + 3) * INT_FLOAT_MULTI)) << 24; + + if (*res_value != tmp) ++err; + } + else if (!res_desc->Elements && (res_desc->Class == D3DXPC_SCALAR || res_desc->Class == D3DXPC_VECTOR)) + { + ok(hr == D3D_OK, "%u - %s: GetVector failed, got %#x, expected %#x\n", i, res_full_name, hr, D3D_OK); + + for (l = 0; l < res_desc->Columns; ++l) + { + if (!compare_float(fvalue[l], get_float(res_desc->Type, &res_value[l]), 512)) ++err; + } + + for (l = res_desc->Columns; l < 4; ++l) if (fvalue[l] != 0.0f) ++err; + } + else + { + ok(hr == D3DERR_INVALIDCALL, "%u - %s: GetVector failed, got %#x, expected %#x\n", + i, res_full_name, hr, D3DERR_INVALIDCALL); + + for (l = 0; l < 4; ++l) if (fvalue[l] != *(FLOAT *)&cmp) ++err; + } + ok(!err, "%u - %s: GetVector failed with %u errors\n", i, res_full_name, err); +} + +static void test_effect_parameter_value_GetVectorArray(const struct test_effect_parameter_value_result *res, + ID3DXEffect *effect, const DWORD *res_value, D3DXHANDLE parameter, UINT i) +{ + const D3DXPARAMETER_DESC *res_desc = &res->desc; + const char *res_full_name = res->full_name; + HRESULT hr; + DWORD cmp = 0xabababab; + FLOAT fvalue[EFFECT_PARAMETER_VALUE_ARRAY_SIZE]; + UINT l, k, element, err = 0; + + for (element = 0; element <= res_desc->Elements + 1; ++element) + { + memset(fvalue, 0xab, sizeof(fvalue)); + hr = effect->lpVtbl->GetVectorArray(effect, parameter, (D3DXVECTOR4 *)&fvalue, element); + if (!element) + { + ok(hr == D3D_OK, "%u - %s[%u]: GetVectorArray failed, got %#x, expected %#x\n", i, res_full_name, element, hr, D3D_OK); + + for (l = 0; l < EFFECT_PARAMETER_VALUE_ARRAY_SIZE; ++l) if (fvalue[l] != *(FLOAT *)&cmp) ++err; + } + else if (element <= res_desc->Elements && res_desc->Class == D3DXPC_VECTOR) + { + ok(hr == D3D_OK, "%u - %s[%u]: GetVectorArray failed, got %#x, expected %#x\n", i, res_full_name, element, hr, D3D_OK); + + for (k = 0; k < element; ++k) + { + for (l = 0; l < res_desc->Columns; ++l) + { + if (!compare_float(fvalue[l + k * 4], get_float(res_desc->Type, + &res_value[l + k * res_desc->Columns]), 512)) + ++err; + } + + for (l = res_desc->Columns; l < 4; ++l) if (fvalue[l + k * 4] != 0.0f) ++err; + } + + for (l = element * 4; l < EFFECT_PARAMETER_VALUE_ARRAY_SIZE; ++l) if (fvalue[l] != *(FLOAT *)&cmp) ++err; + } + else + { + ok(hr == D3DERR_INVALIDCALL, "%u - %s[%u]: GetVectorArray failed, got %#x, expected %#x\n", + i, res_full_name, element, hr, D3DERR_INVALIDCALL); + + for (l = 0; l < EFFECT_PARAMETER_VALUE_ARRAY_SIZE; ++l) if (fvalue[l] != *(FLOAT *)&cmp) ++err; + } + ok(!err, "%u - %s[%u]: GetVectorArray failed with %u errors\n", i, res_full_name, element, err); + } +} + +static void test_effect_parameter_value_GetMatrix(const struct test_effect_parameter_value_result *res, + ID3DXEffect *effect, const DWORD *res_value, D3DXHANDLE parameter, UINT i) +{ + const D3DXPARAMETER_DESC *res_desc = &res->desc; + const char *res_full_name = res->full_name; + HRESULT hr; + union + { + DWORD d; + float f; + } cmp; + float fvalue[16]; + UINT l, k, err = 0; + + cmp.d = 0xabababab; + memset(fvalue, 0xab, sizeof(fvalue)); + hr = effect->lpVtbl->GetMatrix(effect, parameter, (D3DXMATRIX *)&fvalue); + if (!res_desc->Elements && res_desc->Class == D3DXPC_MATRIX_ROWS) + { + ok(hr == D3D_OK, "%u - %s: GetMatrix failed, got %#x, expected %#x.\n", i, res_full_name, hr, D3D_OK); + + for (k = 0; k < 4; ++k) + { + for (l = 0; l < 4; ++l) + { + if (k < res_desc->Columns && l < res_desc->Rows) + { + if (!compare_float(fvalue[l * 4 + k], get_float(res_desc->Type, + &res_value[l * res_desc->Columns + k]), 512)) + ++err; + } + else if (fvalue[l * 4 + k] != 0.0f) ++err; + } + } + } + else + { + ok(hr == D3DERR_INVALIDCALL, "%u - %s: GetMatrix failed, got %#x, expected %#x.\n", + i, res_full_name, hr, D3DERR_INVALIDCALL); + + for (l = 0; l < ARRAY_SIZE(fvalue); ++l) + if (fvalue[l] != cmp.f) + ++err; + } + ok(!err, "%u - %s: GetMatrix failed with %u errors.\n", i, res_full_name, err); +} + +static void test_effect_parameter_value_GetMatrixArray(const struct test_effect_parameter_value_result *res, + ID3DXEffect *effect, const DWORD *res_value, D3DXHANDLE parameter, UINT i) +{ + const D3DXPARAMETER_DESC *res_desc = &res->desc; + const char *res_full_name = res->full_name; + HRESULT hr; + DWORD cmp = 0xabababab; + FLOAT fvalue[EFFECT_PARAMETER_VALUE_ARRAY_SIZE]; + UINT l, k, m, element, err = 0; + + for (element = 0; element <= res_desc->Elements + 1; ++element) + { + memset(fvalue, 0xab, sizeof(fvalue)); + hr = effect->lpVtbl->GetMatrixArray(effect, parameter, (D3DXMATRIX *)&fvalue, element); + if (!element) + { + ok(hr == D3D_OK, "%u - %s[%u]: GetMatrixArray failed, got %#x, expected %#x\n", i, res_full_name, element, hr, D3D_OK); + + for (l = 0; l < EFFECT_PARAMETER_VALUE_ARRAY_SIZE; ++l) if (fvalue[l] != *(FLOAT *)&cmp) ++err; + } + else if (element <= res_desc->Elements && res_desc->Class == D3DXPC_MATRIX_ROWS) + { + ok(hr == D3D_OK, "%u - %s[%u]: GetMatrixArray failed, got %#x, expected %#x\n", i, res_full_name, element, hr, D3D_OK); + + for (m = 0; m < element; ++m) + { + for (k = 0; k < 4; ++k) + { + for (l = 0; l < 4; ++l) + { + if (k < res_desc->Columns && l < res_desc->Rows) + { + if (!compare_float(fvalue[m * 16 + l * 4 + k], get_float(res_desc->Type, + &res_value[m * res_desc->Columns * res_desc->Rows + l * res_desc->Columns + k]), 512)) + ++err; + } + else if (fvalue[m * 16 + l * 4 + k] != 0.0f) ++err; + } + } + } + + for (l = element * 16; l < EFFECT_PARAMETER_VALUE_ARRAY_SIZE; ++l) if (fvalue[l] != *(FLOAT *)&cmp) ++err; + } + else + { + ok(hr == D3DERR_INVALIDCALL, "%u - %s[%u]: GetMatrixArray failed, got %#x, expected %#x\n", + i, res_full_name, element, hr, D3DERR_INVALIDCALL); + + for (l = 0; l < EFFECT_PARAMETER_VALUE_ARRAY_SIZE; ++l) if (fvalue[l] != *(FLOAT *)&cmp) ++err; + } + ok(!err, "%u - %s[%u]: GetMatrixArray failed with %u errors\n", i, res_full_name, element, err); + } +} + +static void test_effect_parameter_value_GetMatrixPointerArray(const struct test_effect_parameter_value_result *res, + ID3DXEffect *effect, const DWORD *res_value, D3DXHANDLE parameter, UINT i) +{ + const D3DXPARAMETER_DESC *res_desc = &res->desc; + const char *res_full_name = res->full_name; + HRESULT hr; + DWORD cmp = 0xabababab; + FLOAT fvalue[EFFECT_PARAMETER_VALUE_ARRAY_SIZE]; + D3DXMATRIX *matrix_pointer_array[sizeof(fvalue)/sizeof(D3DXMATRIX)]; + UINT l, k, m, element, err = 0; + + for (element = 0; element <= res_desc->Elements + 1; ++element) + { + memset(fvalue, 0xab, sizeof(fvalue)); + for (l = 0; l < element; ++l) + { + matrix_pointer_array[l] = (D3DXMATRIX *)&fvalue[l * sizeof(**matrix_pointer_array) / sizeof(FLOAT)]; + } + hr = effect->lpVtbl->GetMatrixPointerArray(effect, parameter, matrix_pointer_array, element); + if (!element) + { + ok(hr == D3D_OK, "%u - %s[%u]: GetMatrixPointerArray failed, got %#x, expected %#x\n", + i, res_full_name, element, hr, D3D_OK); + + for (l = 0; l < EFFECT_PARAMETER_VALUE_ARRAY_SIZE; ++l) if (fvalue[l] != *(FLOAT *)&cmp) ++err; + } + else if (element <= res_desc->Elements && res_desc->Class == D3DXPC_MATRIX_ROWS) + { + ok(hr == D3D_OK, "%u - %s[%u]: GetMatrixPointerArray failed, got %#x, expected %#x\n", + i, res_full_name, element, hr, D3D_OK); + + for (m = 0; m < element; ++m) + { + for (k = 0; k < 4; ++k) + { + for (l = 0; l < 4; ++l) + { + if (k < res_desc->Columns && l < res_desc->Rows) + { + if (!compare_float(fvalue[m * 16 + l * 4 + k], get_float(res_desc->Type, + &res_value[m * res_desc->Columns * res_desc->Rows + l * res_desc->Columns + k]), 512)) + ++err; + } + else if (fvalue[m * 16 + l * 4 + k] != 0.0f) ++err; + } + } + } + + for (l = element * 16; l < EFFECT_PARAMETER_VALUE_ARRAY_SIZE; ++l) if (fvalue[l] != *(FLOAT *)&cmp) ++err; + } + else + { + for (l = 0; l < EFFECT_PARAMETER_VALUE_ARRAY_SIZE; ++l) if (fvalue[l] != *(FLOAT *)&cmp) ++err; + + ok(hr == D3DERR_INVALIDCALL, "%u - %s[%u]: GetMatrixPointerArray failed, got %#x, expected %#x\n", + i, res_full_name, element, hr, D3DERR_INVALIDCALL); + } + ok(!err, "%u - %s[%u]: GetMatrixPointerArray failed with %u errors\n", i, res_full_name, element, err); + } +} + +static void test_effect_parameter_value_GetMatrixTranspose(const struct test_effect_parameter_value_result *res, + ID3DXEffect *effect, const DWORD *res_value, D3DXHANDLE parameter, UINT i) +{ + const D3DXPARAMETER_DESC *res_desc = &res->desc; + const char *res_full_name = res->full_name; + HRESULT hr; + union + { + DWORD d; + float f; + } cmp; + float fvalue[16]; + UINT l, k, err = 0; + + cmp.d = 0xabababab; + memset(fvalue, 0xab, sizeof(fvalue)); + hr = effect->lpVtbl->GetMatrixTranspose(effect, parameter, (D3DXMATRIX *)&fvalue); + if (!res_desc->Elements && res_desc->Class == D3DXPC_MATRIX_ROWS) + { + ok(hr == D3D_OK, "%u - %s: GetMatrixTranspose failed, got %#x, expected %#x.\n", i, res_full_name, hr, D3D_OK); + + for (k = 0; k < 4; ++k) + { + for (l = 0; l < 4; ++l) + { + if (k < res_desc->Columns && l < res_desc->Rows) + { + if (!compare_float(fvalue[l + k * 4], get_float(res_desc->Type, + &res_value[l * res_desc->Columns + k]), 512)) + ++err; + } + else if (fvalue[l + k * 4] != 0.0f) ++err; + } + } + } + else if (!res_desc->Elements && (res_desc->Class == D3DXPC_VECTOR || res_desc->Class == D3DXPC_SCALAR)) + { + ok(hr == D3D_OK, "%u - %s: GetMatrixTranspose failed, got %#x, expected %#x.\n", i, res_full_name, hr, D3D_OK); + + for (k = 0; k < 4; ++k) + { + for (l = 0; l < 4; ++l) + { + if (k < res_desc->Columns && l < res_desc->Rows) + { + if (!compare_float(fvalue[l * 4 + k], get_float(res_desc->Type, + &res_value[l * res_desc->Columns + k]), 512)) + ++err; + } + else if (fvalue[l * 4 + k] != 0.0f) ++err; + } + } + } + else + { + ok(hr == D3DERR_INVALIDCALL, "%u - %s: GetMatrixTranspose failed, got %#x, expected %#x.\n", + i, res_full_name, hr, D3DERR_INVALIDCALL); + + for (l = 0; l < ARRAY_SIZE(fvalue); ++l) + if (fvalue[l] != cmp.f) + ++err; + } + ok(!err, "%u - %s: GetMatrixTranspose failed with %u errors.\n", i, res_full_name, err); +} + +static void test_effect_parameter_value_GetMatrixTransposeArray(const struct test_effect_parameter_value_result *res, + ID3DXEffect *effect, const DWORD *res_value, D3DXHANDLE parameter, UINT i) +{ + const D3DXPARAMETER_DESC *res_desc = &res->desc; + const char *res_full_name = res->full_name; + HRESULT hr; + DWORD cmp = 0xabababab; + FLOAT fvalue[EFFECT_PARAMETER_VALUE_ARRAY_SIZE]; + UINT l, k, m, element, err = 0; + + for (element = 0; element <= res_desc->Elements + 1; ++element) + { + memset(fvalue, 0xab, sizeof(fvalue)); + hr = effect->lpVtbl->GetMatrixTransposeArray(effect, parameter, (D3DXMATRIX *)&fvalue, element); + if (!element) + { + ok(hr == D3D_OK, "%u - %s[%u]: GetMatrixTransposeArray failed, got %#x, expected %#x\n", + i, res_full_name, element, hr, D3D_OK); + + for (l = 0; l < EFFECT_PARAMETER_VALUE_ARRAY_SIZE; ++l) if (fvalue[l] != *(FLOAT *)&cmp) ++err; + } + else if (element <= res_desc->Elements && res_desc->Class == D3DXPC_MATRIX_ROWS) + { + ok(hr == D3D_OK, "%u - %s[%u]: GetMatrixTransposeArray failed, got %#x, expected %#x\n", + i, res_full_name, element, hr, D3D_OK); + + for (m = 0; m < element; ++m) + { + for (k = 0; k < 4; ++k) + { + for (l = 0; l < 4; ++l) + { + if (k < res_desc->Columns && l < res_desc->Rows) + { + if (!compare_float(fvalue[m * 16 + l + k * 4], get_float(res_desc->Type, + &res_value[m * res_desc->Columns * res_desc->Rows + l * res_desc->Columns + k]), 512)) + ++err; + } + else if (fvalue[m * 16 + l + k * 4] != 0.0f) ++err; + } + } + } + + for (l = element * 16; l < EFFECT_PARAMETER_VALUE_ARRAY_SIZE; ++l) if (fvalue[l] != *(FLOAT *)&cmp) ++err; + } + else + { + ok(hr == D3DERR_INVALIDCALL, "%u - %s[%u]: GetMatrixTransposeArray failed, got %#x, expected %#x\n", + i, res_full_name, element, hr, D3DERR_INVALIDCALL); + + for (l = 0; l < EFFECT_PARAMETER_VALUE_ARRAY_SIZE; ++l) if (fvalue[l] != *(FLOAT *)&cmp) ++err; + } + ok(!err, "%u - %s[%u]: GetMatrixTransposeArray failed with %u errors\n", i, res_full_name, element, err); + } +} + +static void test_effect_parameter_value_GetMatrixTransposePointerArray(const struct test_effect_parameter_value_result *res, + ID3DXEffect *effect, const DWORD *res_value, D3DXHANDLE parameter, UINT i) +{ + const D3DXPARAMETER_DESC *res_desc = &res->desc; + const char *res_full_name = res->full_name; + HRESULT hr; + DWORD cmp = 0xabababab; + FLOAT fvalue[EFFECT_PARAMETER_VALUE_ARRAY_SIZE]; + D3DXMATRIX *matrix_pointer_array[sizeof(fvalue)/sizeof(D3DXMATRIX)]; + UINT l, k, m, element, err = 0; + + for (element = 0; element <= res_desc->Elements + 1; ++element) + { + memset(fvalue, 0xab, sizeof(fvalue)); + for (l = 0; l < element; ++l) + { + matrix_pointer_array[l] = (D3DXMATRIX *)&fvalue[l * sizeof(**matrix_pointer_array) / sizeof(FLOAT)]; + } + hr = effect->lpVtbl->GetMatrixTransposePointerArray(effect, parameter, matrix_pointer_array, element); + if (!element) + { + ok(hr == D3D_OK, "%u - %s[%u]: GetMatrixTransposePointerArray failed, got %#x, expected %#x\n", + i, res_full_name, element, hr, D3D_OK); + + for (l = 0; l < EFFECT_PARAMETER_VALUE_ARRAY_SIZE; ++l) if (fvalue[l] != *(FLOAT *)&cmp) ++err; + } + else if (element <= res_desc->Elements && res_desc->Class == D3DXPC_MATRIX_ROWS) + { + ok(hr == D3D_OK, "%u - %s[%u]: GetMatrixTransposePointerArray failed, got %#x, expected %#x\n", + i, res_full_name, element, hr, D3D_OK); + + for (m = 0; m < element; ++m) + { + for (k = 0; k < 4; ++k) + { + for (l = 0; l < 4; ++l) + { + if (k < res_desc->Columns && l < res_desc->Rows) + { + if (!compare_float(fvalue[m * 16 + l + k * 4], get_float(res_desc->Type, + &res_value[m * res_desc->Columns * res_desc->Rows + l * res_desc->Columns + k]), 512)) + ++err; + } + else if (fvalue[m * 16 + l + k * 4] != 0.0f) ++err; + } + } + } + + for (l = element * 16; l < EFFECT_PARAMETER_VALUE_ARRAY_SIZE; ++l) if (fvalue[l] != *(FLOAT *)&cmp) ++err; + } + else + { + ok(hr == D3DERR_INVALIDCALL, "%u - %s[%u]: GetMatrixTransposePointerArray failed, got %#x, expected %#x\n", + i, res_full_name, element, hr, D3DERR_INVALIDCALL); + + for (l = 0; l < EFFECT_PARAMETER_VALUE_ARRAY_SIZE; ++l) if (fvalue[l] != *(FLOAT *)&cmp) ++err; + } + ok(!err, "%u - %s[%u]: GetMatrixTransposePointerArray failed with %u errors\n", i, res_full_name, element, err); + } +} + +static void test_effect_parameter_value_GetTestGroup(const struct test_effect_parameter_value_result *res, + ID3DXEffect *effect, const DWORD *res_value, D3DXHANDLE parameter, UINT i) +{ + test_effect_parameter_value_GetValue(res, effect, res_value, parameter, i); + test_effect_parameter_value_GetBool(res, effect, res_value, parameter, i); + test_effect_parameter_value_GetBoolArray(res, effect, res_value, parameter, i); + test_effect_parameter_value_GetInt(res, effect, res_value, parameter, i); + test_effect_parameter_value_GetIntArray(res, effect, res_value, parameter, i); + test_effect_parameter_value_GetFloat(res, effect, res_value, parameter, i); + test_effect_parameter_value_GetFloatArray(res, effect, res_value, parameter, i); + test_effect_parameter_value_GetVector(res, effect, res_value, parameter, i); + test_effect_parameter_value_GetVectorArray(res, effect, res_value, parameter, i); + test_effect_parameter_value_GetMatrix(res, effect, res_value, parameter, i); + test_effect_parameter_value_GetMatrixArray(res, effect, res_value, parameter, i); + test_effect_parameter_value_GetMatrixPointerArray(res, effect, res_value, parameter, i); + test_effect_parameter_value_GetMatrixTranspose(res, effect, res_value, parameter, i); + test_effect_parameter_value_GetMatrixTransposeArray(res, effect, res_value, parameter, i); + test_effect_parameter_value_GetMatrixTransposePointerArray(res, effect, res_value, parameter, i); +} + +static void test_effect_parameter_value_ResetValue(const struct test_effect_parameter_value_result *res, + ID3DXEffect *effect, const DWORD *res_value, D3DXHANDLE parameter, UINT i) +{ + const D3DXPARAMETER_DESC *res_desc = &res->desc; + const char *res_full_name = res->full_name; + HRESULT hr; + + if (res_desc->Class == D3DXPC_SCALAR + || res_desc->Class == D3DXPC_VECTOR + || res_desc->Class == D3DXPC_MATRIX_ROWS) + { + hr = effect->lpVtbl->SetValue(effect, parameter, res_value, res_desc->Bytes); + ok(hr == D3D_OK, "%u - %s: SetValue failed, got %#x, expected %#x\n", i, res_full_name, hr, D3D_OK); + } + else + { + /* nothing to do */ + switch (res_desc->Type) + { + case D3DXPT_PIXELSHADER: + case D3DXPT_VERTEXSHADER: + case D3DXPT_TEXTURE2D: + case D3DXPT_STRING: + break; + + default: + ok(0, "Type is %u, this should not happen!\n", res_desc->Type); + break; + } + } +} + +static void test_effect_parameter_value(IDirect3DDevice9 *device) +{ + unsigned int effect_count = ARRAY_SIZE(test_effect_parameter_value_data), i; + + for (i = 0; i < effect_count; ++i) + { + const struct test_effect_parameter_value_result *res = test_effect_parameter_value_data[i].res; + UINT res_count = test_effect_parameter_value_data[i].res_count; + const DWORD *blob = test_effect_parameter_value_data[i].blob; + UINT blob_size = test_effect_parameter_value_data[i].blob_size; + HRESULT hr; + ID3DXEffect *effect; + D3DXEFFECT_DESC edesc; + ULONG count; + UINT k; + + hr = D3DXCreateEffect(device, blob, blob_size, NULL, NULL, 0, NULL, &effect, NULL); + ok(hr == D3D_OK, "%u: D3DXCreateEffect failed, got %#x, expected %#x\n", i, hr, D3D_OK); + + hr = effect->lpVtbl->GetDesc(effect, &edesc); + ok(hr == D3D_OK, "%u: GetDesc failed, got %#x, expected %#x\n", i, hr, D3D_OK); + ok(edesc.Parameters == res_count, "%u: Parameters failed, got %u, expected %u\n", + i, edesc.Parameters, res_count); + + for (k = 0; k < res_count; ++k) + { + const D3DXPARAMETER_DESC *res_desc = &res[k].desc; + const char *res_full_name = res[k].full_name; + UINT res_value_offset = res[k].value_offset; + D3DXHANDLE parameter; + D3DXPARAMETER_DESC pdesc; + BOOL bvalue = TRUE; + INT ivalue = 42; + FLOAT fvalue = 2.71828f; + DWORD input_value[EFFECT_PARAMETER_VALUE_ARRAY_SIZE]; + DWORD expected_value[EFFECT_PARAMETER_VALUE_ARRAY_SIZE]; + UINT l, n, m, element; + const D3DXMATRIX *matrix_pointer_array[sizeof(input_value)/sizeof(D3DXMATRIX)]; + + parameter = effect->lpVtbl->GetParameterByName(effect, NULL, res_full_name); + ok(parameter != NULL, "%u - %s: GetParameterByName failed\n", i, res_full_name); + + hr = effect->lpVtbl->GetParameterDesc(effect, parameter, &pdesc); + ok(hr == D3D_OK, "%u - %s: GetParameterDesc failed, got %#x, expected %#x\n", i, res_full_name, hr, D3D_OK); + + ok(res_desc->Name ? !strcmp(pdesc.Name, res_desc->Name) : !pdesc.Name, + "%u - %s: GetParameterDesc Name failed, got \"%s\", expected \"%s\"\n", + i, res_full_name, pdesc.Name, res_desc->Name); + ok(res_desc->Semantic ? !strcmp(pdesc.Semantic, res_desc->Semantic) : !pdesc.Semantic, + "%u - %s: GetParameterDesc Semantic failed, got \"%s\", expected \"%s\"\n", + i, res_full_name, pdesc.Semantic, res_desc->Semantic); + ok(res_desc->Class == pdesc.Class, "%u - %s: GetParameterDesc Class failed, got %#x, expected %#x\n", + i, res_full_name, pdesc.Class, res_desc->Class); + ok(res_desc->Type == pdesc.Type, "%u - %s: GetParameterDesc Type failed, got %#x, expected %#x\n", + i, res_full_name, pdesc.Type, res_desc->Type); + ok(res_desc->Rows == pdesc.Rows, "%u - %s: GetParameterDesc Rows failed, got %u, expected %u\n", + i, res_full_name, pdesc.Rows, res_desc->Rows); + ok(res_desc->Columns == pdesc.Columns, "%u - %s: GetParameterDesc Columns failed, got %u, expected %u\n", + i, res_full_name, pdesc.Columns, res_desc->Columns); + ok(res_desc->Elements == pdesc.Elements, "%u - %s: GetParameterDesc Elements failed, got %u, expected %u\n", + i, res_full_name, pdesc.Elements, res_desc->Elements); + ok(res_desc->Annotations == pdesc.Annotations, "%u - %s: GetParameterDesc Annotations failed, got %u, expected %u\n", + i, res_full_name, pdesc.Annotations, res_desc->Annotations); + ok(res_desc->StructMembers == pdesc.StructMembers, "%u - %s: GetParameterDesc StructMembers failed, got %u, expected %u\n", + i, res_full_name, pdesc.StructMembers, res_desc->StructMembers); + ok(res_desc->Flags == pdesc.Flags, "%u - %s: GetParameterDesc Flags failed, got %u, expected %u\n", + i, res_full_name, pdesc.Flags, res_desc->Flags); + ok(res_desc->Bytes == pdesc.Bytes, "%u - %s: GetParameterDesc Bytes, got %u, expected %u\n", + i, res_full_name, pdesc.Bytes, res_desc->Bytes); + + /* check size */ + ok(EFFECT_PARAMETER_VALUE_ARRAY_SIZE >= res_desc->Bytes / 4 + + (res_desc->Elements ? res_desc->Bytes / 4 / res_desc->Elements : 0), + "%u - %s: Warning: Array size too small\n", i, res_full_name); + + test_effect_parameter_value_GetTestGroup(&res[k], effect, &blob[res_value_offset], parameter, i); + test_effect_parameter_value_ResetValue(&res[k], effect, &blob[res_value_offset], parameter, i); + test_effect_parameter_value_GetTestGroup(&res[k], effect, &blob[res_value_offset], parameter, i); + + /* + * check invalid calls + * These will crash: + * effect->lpVtbl->SetBoolArray(effect, parameter, NULL, res_desc->Bytes / sizeof(BOOL)); + * effect->lpVtbl->SetIntArray(effect, parameter, NULL, res_desc->Bytes / sizeof(INT)); + * effect->lpVtbl->SetFloatArray(effect, parameter, NULL, res_desc->Bytes / sizeof(FLOAT)); + * effect->lpVtbl->SetVector(effect, parameter, NULL); + * effect->lpVtbl->SetVectorArray(effect, parameter, NULL, res_desc->Elements ? res_desc->Elements : 1); + * effect->lpVtbl->SetMatrix(effect, parameter, NULL); + * effect->lpVtbl->GetMatrix(effect, parameter, NULL); + * effect->lpVtbl->SetMatrixArray(effect, parameter, NULL, res_desc->Elements ? res_desc->Elements : 1); + * effect->lpVtbl->SetMatrixPointerArray(effect, parameter, NULL, res_desc->Elements ? res_desc->Elements : 1); + * effect->lpVtbl->SetMatrixTranspose(effect, parameter, NULL); + * effect->lpVtbl->SetMatrixTransposeArray(effect, parameter, NULL, res_desc->Elements ? res_desc->Elements : 1); + * effect->lpVtbl->SetMatrixTransposePointerArray(effect, parameter, NULL, res_desc->Elements ? res_desc->Elements : 1); + * effect->lpVtbl->GetValue(effect, parameter, NULL, res_desc->Bytes); + * effect->lpVtbl->SetValue(effect, parameter, NULL, res_desc->Bytes); + */ + hr = effect->lpVtbl->SetBool(effect, NULL, bvalue); + ok(hr == D3DERR_INVALIDCALL, "%u - %s: SetBool failed, got %#x, expected %#x\n", + i, res_full_name, hr, D3DERR_INVALIDCALL); + + hr = effect->lpVtbl->GetBool(effect, NULL, &bvalue); + ok(hr == D3DERR_INVALIDCALL, "%u - %s: GetBool failed, got %#x, expected %#x\n", + i, res_full_name, hr, D3DERR_INVALIDCALL); + + hr = effect->lpVtbl->GetBool(effect, parameter, NULL); + ok(hr == D3DERR_INVALIDCALL, "%u - %s: GetBool failed, got %#x, expected %#x\n", + i, res_full_name, hr, D3DERR_INVALIDCALL); + + hr = effect->lpVtbl->SetBoolArray(effect, NULL, (BOOL *)input_value, res_desc->Bytes / sizeof(BOOL)); + ok(hr == D3DERR_INVALIDCALL, "%u - %s: SetBoolArray failed, got %#x, expected %#x\n", + i, res_full_name, hr, D3DERR_INVALIDCALL); + + hr = effect->lpVtbl->GetBoolArray(effect, NULL, (BOOL *)input_value, res_desc->Bytes / sizeof(BOOL)); + ok(hr == D3DERR_INVALIDCALL, "%u - %s: GetBoolArray failed, got %#x, expected %#x\n", + i, res_full_name, hr, D3DERR_INVALIDCALL); + + hr = effect->lpVtbl->GetBoolArray(effect, parameter, NULL, res_desc->Bytes / sizeof(BOOL)); + ok(hr == D3DERR_INVALIDCALL, "%u - %s: GetBoolArray failed, got %#x, expected %#x\n", + i, res_full_name, hr, D3DERR_INVALIDCALL); + + hr = effect->lpVtbl->SetInt(effect, NULL, ivalue); + ok(hr == D3DERR_INVALIDCALL, "%u - %s: SetInt failed, got %#x, expected %#x\n", + i, res_full_name, hr, D3DERR_INVALIDCALL); + + hr = effect->lpVtbl->GetInt(effect, NULL, &ivalue); + ok(hr == D3DERR_INVALIDCALL, "%u - %s: GetInt failed, got %#x, expected %#x\n", + i, res_full_name, hr, D3DERR_INVALIDCALL); + + hr = effect->lpVtbl->GetInt(effect, parameter, NULL); + ok(hr == D3DERR_INVALIDCALL, "%u - %s: GetInt failed, got %#x, expected %#x\n", + i, res_full_name, hr, D3DERR_INVALIDCALL); + + hr = effect->lpVtbl->SetIntArray(effect, NULL, (INT *)input_value, res_desc->Bytes / sizeof(INT)); + ok(hr == D3DERR_INVALIDCALL, "%u - %s: SetIntArray failed, got %#x, expected %#x\n", + i, res_full_name, hr, D3DERR_INVALIDCALL); + + hr = effect->lpVtbl->GetIntArray(effect, NULL, (INT *)input_value, res_desc->Bytes / sizeof(INT)); + ok(hr == D3DERR_INVALIDCALL, "%u - %s: GetIntArray failed, got %#x, expected %#x\n", + i, res_full_name, hr, D3DERR_INVALIDCALL); + + hr = effect->lpVtbl->GetIntArray(effect, parameter, NULL, res_desc->Bytes / sizeof(INT)); + ok(hr == D3DERR_INVALIDCALL, "%u - %s: GetIntArray failed, got %#x, expected %#x\n", + i, res_full_name, hr, D3DERR_INVALIDCALL); + + hr = effect->lpVtbl->SetFloat(effect, NULL, fvalue); + ok(hr == D3DERR_INVALIDCALL, "%u - %s: SetFloat failed, got %#x, expected %#x\n", + i, res_full_name, hr, D3DERR_INVALIDCALL); + + hr = effect->lpVtbl->GetFloat(effect, NULL, &fvalue); + ok(hr == D3DERR_INVALIDCALL, "%u - %s: GetFloat failed, got %#x, expected %#x\n", + i, res_full_name, hr, D3DERR_INVALIDCALL); + + hr = effect->lpVtbl->GetFloat(effect, parameter, NULL); + ok(hr == D3DERR_INVALIDCALL, "%u - %s: GetFloat failed, got %#x, expected %#x\n", + i, res_full_name, hr, D3DERR_INVALIDCALL); + + hr = effect->lpVtbl->SetFloatArray(effect, NULL, (FLOAT *)input_value, res_desc->Bytes / sizeof(FLOAT)); + ok(hr == D3DERR_INVALIDCALL, "%u - %s: SetFloatArray failed, got %#x, expected %#x\n", + i, res_full_name, hr, D3DERR_INVALIDCALL); + + hr = effect->lpVtbl->GetFloatArray(effect, NULL, (FLOAT *)input_value, res_desc->Bytes / sizeof(FLOAT)); + ok(hr == D3DERR_INVALIDCALL, "%u - %s: GetFloatArray failed, got %#x, expected %#x\n", + i, res_full_name, hr, D3DERR_INVALIDCALL); + + hr = effect->lpVtbl->GetFloatArray(effect, parameter, NULL, res_desc->Bytes / sizeof(FLOAT)); + ok(hr == D3DERR_INVALIDCALL, "%u - %s: GetFloatArray failed, got %#x, expected %#x\n", + i, res_full_name, hr, D3DERR_INVALIDCALL); + + hr = effect->lpVtbl->SetVector(effect, NULL, (D3DXVECTOR4 *)input_value); + ok(hr == D3DERR_INVALIDCALL, "%u - %s: SetVector failed, got %#x, expected %#x\n", + i, res_full_name, hr, D3DERR_INVALIDCALL); + + hr = effect->lpVtbl->GetVector(effect, NULL, (D3DXVECTOR4 *)input_value); + ok(hr == D3DERR_INVALIDCALL, "%u - %s: GetVector failed, got %#x, expected %#x\n", + i, res_full_name, hr, D3DERR_INVALIDCALL); + + hr = effect->lpVtbl->GetVector(effect, parameter, NULL); + ok(hr == D3DERR_INVALIDCALL, "%u - %s: GetVector failed, got %#x, expected %#x\n", + i, res_full_name, hr, D3DERR_INVALIDCALL); + + hr = effect->lpVtbl->SetVectorArray(effect, NULL, (D3DXVECTOR4 *)input_value, res_desc->Elements ? res_desc->Elements : 1); + ok(hr == D3DERR_INVALIDCALL, "%u - %s: SetVectorArray failed, got %#x, expected %#x\n", + i, res_full_name, hr, D3DERR_INVALIDCALL); + + hr = effect->lpVtbl->GetVectorArray(effect, NULL, (D3DXVECTOR4 *)input_value, res_desc->Elements ? res_desc->Elements : 1); + ok(hr == D3DERR_INVALIDCALL, "%u - %s: GetVectorArray failed, got %#x, expected %#x\n", + i, res_full_name, hr, D3DERR_INVALIDCALL); + + hr = effect->lpVtbl->GetVectorArray(effect, parameter, NULL, res_desc->Elements ? res_desc->Elements : 1); + ok(hr == D3DERR_INVALIDCALL, "%u - %s: GetVectorArray failed, got %#x, expected %#x\n", + i, res_full_name, hr, D3DERR_INVALIDCALL); + + hr = effect->lpVtbl->SetMatrix(effect, NULL, (D3DXMATRIX *)input_value); + ok(hr == D3DERR_INVALIDCALL, "%u - %s: SetMatrix failed, got %#x, expected %#x\n", + i, res_full_name, hr, D3DERR_INVALIDCALL); + + hr = effect->lpVtbl->GetMatrix(effect, NULL, (D3DXMATRIX *)input_value); + ok(hr == D3DERR_INVALIDCALL, "%u - %s: GetMatrix failed, got %#x, expected %#x\n", + i, res_full_name, hr, D3DERR_INVALIDCALL); + + hr = effect->lpVtbl->SetMatrixArray(effect, NULL, (D3DXMATRIX *)input_value, res_desc->Elements ? res_desc->Elements : 1); + ok(hr == D3DERR_INVALIDCALL, "%u - %s: SetMatrixArray failed, got %#x, expected %#x\n", + i, res_full_name, hr, D3DERR_INVALIDCALL); + + hr = effect->lpVtbl->GetMatrixArray(effect, NULL, (D3DXMATRIX *)input_value, res_desc->Elements ? res_desc->Elements : 1); + ok(hr == D3DERR_INVALIDCALL, "%u - %s: GetMatrixArray failed, got %#x, expected %#x\n", + i, res_full_name, hr, D3DERR_INVALIDCALL); + + hr = effect->lpVtbl->GetMatrixArray(effect, parameter, NULL, res_desc->Elements ? res_desc->Elements : 1); + ok(hr == D3DERR_INVALIDCALL, "%u - %s: GetMatrixArray failed, got %#x, expected %#x\n", + i, res_full_name, hr, D3DERR_INVALIDCALL); + + hr = effect->lpVtbl->SetMatrixPointerArray(effect, NULL, matrix_pointer_array, res_desc->Elements ? res_desc->Elements : 1); + ok(hr == D3DERR_INVALIDCALL, "%u - %s: SetMatrixPointerArray failed, got %#x, expected %#x\n", + i, res_full_name, hr, D3DERR_INVALIDCALL); + + hr = effect->lpVtbl->SetMatrixPointerArray(effect, NULL, matrix_pointer_array, 0); + ok(hr == D3DERR_INVALIDCALL, "%u - %s: SetMatrixPointerArray failed, got %#x, expected %#x\n", + i, res_full_name, hr, D3DERR_INVALIDCALL); + + hr = effect->lpVtbl->GetMatrixPointerArray(effect, NULL, NULL, 0); + ok(hr == D3D_OK, "%u - %s: GetMatrixPointerArray failed, got %#x, expected %#x\n", + i, res_full_name, hr, D3D_OK); + + hr = effect->lpVtbl->GetMatrixPointerArray(effect, NULL, NULL, res_desc->Elements ? res_desc->Elements : 1); + ok(hr == D3DERR_INVALIDCALL, "%u - %s: GetMatrixPointerArray failed, got %#x, expected %#x\n", + i, res_full_name, hr, D3DERR_INVALIDCALL); + + hr = effect->lpVtbl->GetMatrixPointerArray(effect, parameter, NULL, res_desc->Elements ? res_desc->Elements : 1); + ok(hr == D3DERR_INVALIDCALL, "%u - %s: GetMatrixPointerArray failed, got %#x, expected %#x\n", + i, res_full_name, hr, D3DERR_INVALIDCALL); + + hr = effect->lpVtbl->SetMatrixTranspose(effect, NULL, (D3DXMATRIX *)input_value); + ok(hr == D3DERR_INVALIDCALL, "%u - %s: SetMatrixTranspose failed, got %#x, expected %#x\n", + i, res_full_name, hr, D3DERR_INVALIDCALL); + + hr = effect->lpVtbl->GetMatrixTranspose(effect, NULL, (D3DXMATRIX *)input_value); + ok(hr == D3DERR_INVALIDCALL, "%u - %s: GetMatrixTranspose failed, got %#x, expected %#x\n", + i, res_full_name, hr, D3DERR_INVALIDCALL); + + hr = effect->lpVtbl->GetMatrixTranspose(effect, parameter, NULL); + ok(hr == D3DERR_INVALIDCALL, "%u - %s: GetMatrixTranspose failed, got %#x, expected %#x\n", + i, res_full_name, hr, D3DERR_INVALIDCALL); + + hr = effect->lpVtbl->SetMatrixTransposeArray(effect, NULL, (D3DXMATRIX *)input_value, res_desc->Elements ? res_desc->Elements : 1); + ok(hr == D3DERR_INVALIDCALL, "%u - %s: SetMatrixTransposeArray failed, got %#x, expected %#x\n", + i, res_full_name, hr, D3DERR_INVALIDCALL); + + hr = effect->lpVtbl->GetMatrixTransposeArray(effect, NULL, (D3DXMATRIX *)input_value, res_desc->Elements ? res_desc->Elements : 1); + ok(hr == D3DERR_INVALIDCALL, "%u - %s: GetMatrixTransposeArray failed, got %#x, expected %#x\n", + i, res_full_name, hr, D3DERR_INVALIDCALL); + + hr = effect->lpVtbl->GetMatrixTransposeArray(effect, parameter, NULL, res_desc->Elements ? res_desc->Elements : 1); + ok(hr == D3DERR_INVALIDCALL, "%u - %s: GetMatrixTransposeArray failed, got %#x, expected %#x\n", + i, res_full_name, hr, D3DERR_INVALIDCALL); + + hr = effect->lpVtbl->SetMatrixTransposePointerArray(effect, NULL, matrix_pointer_array, res_desc->Elements ? res_desc->Elements : 1); + ok(hr == D3DERR_INVALIDCALL, "%u - %s: SetMatrixTransposePointerArray failed, got %#x, expected %#x\n", + i, res_full_name, hr, D3DERR_INVALIDCALL); + + hr = effect->lpVtbl->SetMatrixTransposePointerArray(effect, NULL, matrix_pointer_array, 0); + ok(hr == D3DERR_INVALIDCALL, "%u - %s: SetMatrixTransposePointerArray failed, got %#x, expected %#x\n", + i, res_full_name, hr, D3DERR_INVALIDCALL); + + hr = effect->lpVtbl->GetMatrixTransposePointerArray(effect, NULL, NULL, 0); + ok(hr == D3D_OK, "%u - %s: GetMatrixTransposePointerArray failed, got %#x, expected %#x\n", + i, res_full_name, hr, D3D_OK); + + hr = effect->lpVtbl->GetMatrixTransposePointerArray(effect, NULL, NULL, res_desc->Elements ? res_desc->Elements : 1); + ok(hr == D3DERR_INVALIDCALL, "%u - %s: GetMatrixTransposePointerArray failed, got %#x, expected %#x\n", + i, res_full_name, hr, D3DERR_INVALIDCALL); + + hr = effect->lpVtbl->GetMatrixTransposePointerArray(effect, parameter, NULL, res_desc->Elements ? res_desc->Elements : 1); + ok(hr == D3DERR_INVALIDCALL, "%u - %s: GetMatrixTransposePointerArray failed, got %#x, expected %#x\n", + i, res_full_name, hr, D3DERR_INVALIDCALL); + + hr = effect->lpVtbl->SetValue(effect, NULL, input_value, res_desc->Bytes); + ok(hr == D3DERR_INVALIDCALL, "%u - %s: SetValue failed, got %#x, expected %#x\n", + i, res_full_name, hr, D3DERR_INVALIDCALL); + + hr = effect->lpVtbl->SetValue(effect, parameter, input_value, res_desc->Bytes - 1); + ok(hr == D3DERR_INVALIDCALL, "%u - %s: SetValue failed, got %#x, expected %#x\n", + i, res_full_name, hr, D3DERR_INVALIDCALL); + + hr = effect->lpVtbl->GetValue(effect, NULL, input_value, res_desc->Bytes); + ok(hr == D3DERR_INVALIDCALL, "%u - %s: GetValue failed, got %#x, expected %#x\n", + i, res_full_name, hr, D3DERR_INVALIDCALL); + + hr = effect->lpVtbl->GetValue(effect, parameter, input_value, res_desc->Bytes - 1); + ok(hr == D3DERR_INVALIDCALL, "%u - %s: GetValue failed, got %#x, expected %#x\n", + i, res_full_name, hr, D3DERR_INVALIDCALL); + + test_effect_parameter_value_GetTestGroup(&res[k], effect, &blob[res_value_offset], parameter, i); + + /* SetBool */ + bvalue = 5; + memcpy(expected_value, &blob[res_value_offset], res_desc->Bytes); + hr = effect->lpVtbl->SetBool(effect, parameter, bvalue); + if (!res_desc->Elements && res_desc->Rows == 1 && res_desc->Columns == 1) + { + bvalue = TRUE; + set_number(expected_value, res_desc->Type, &bvalue, D3DXPT_BOOL); + ok(hr == D3D_OK, "%u - %s: SetBool failed, got %#x, expected %#x\n", i, res_full_name, hr, D3D_OK); + } + else + { + ok(hr == D3DERR_INVALIDCALL, "%u - %s: SetBool failed, got %#x, expected %#x\n", + i, res_full_name, hr, D3DERR_INVALIDCALL); + } + test_effect_parameter_value_GetTestGroup(&res[k], effect, expected_value, parameter, i); + test_effect_parameter_value_ResetValue(&res[k], effect, &blob[res_value_offset], parameter, i); + + /* SetBoolArray */ + *input_value = 1; + for (l = 1; l < res_desc->Bytes / sizeof(*input_value); ++l) + { + *(input_value + l) = *(input_value + l - 1) + 1; + } + memcpy(expected_value, &blob[res_value_offset], res_desc->Bytes); + hr = effect->lpVtbl->SetBoolArray(effect, parameter, (BOOL *)input_value, res_desc->Bytes / sizeof(*input_value)); + if (res_desc->Class == D3DXPC_SCALAR + || res_desc->Class == D3DXPC_VECTOR + || res_desc->Class == D3DXPC_MATRIX_ROWS) + { + for (l = 0; l < res_desc->Bytes / sizeof(*input_value); ++l) + { + set_number(expected_value + l, res_desc->Type, input_value + l, D3DXPT_BOOL); + } + ok(hr == D3D_OK, "%u - %s: SetBoolArray failed, got %#x, expected %#x\n", i, res_full_name, hr, D3D_OK); + } + else + { + ok(hr == D3DERR_INVALIDCALL, "%u - %s: SetBoolArray failed, got %#x, expected %#x\n", + i, res_full_name, hr, D3DERR_INVALIDCALL); + } + test_effect_parameter_value_GetTestGroup(&res[k], effect, expected_value, parameter, i); + test_effect_parameter_value_ResetValue(&res[k], effect, &blob[res_value_offset], parameter, i); + + /* SetInt */ + ivalue = 0x1fbf02ff; + memcpy(expected_value, &blob[res_value_offset], res_desc->Bytes); + hr = effect->lpVtbl->SetInt(effect, parameter, ivalue); + if (!res_desc->Elements && res_desc->Rows == 1 && res_desc->Columns == 1) + { + set_number(expected_value, res_desc->Type, &ivalue, D3DXPT_INT); + ok(hr == D3D_OK, "%u - %s: SetInt failed, got %#x, expected %#x\n", i, res_full_name, hr, D3D_OK); + } + else if(!res_desc->Elements && res_desc->Type == D3DXPT_FLOAT && + ((res_desc->Class == D3DXPC_VECTOR && res_desc->Columns != 2) || + (res_desc->Class == D3DXPC_MATRIX_ROWS && res_desc->Rows != 2 && res_desc->Columns == 1))) + { + FLOAT tmp = ((ivalue & 0xff0000) >> 16) * INT_FLOAT_MULTI_INVERSE; + set_number(expected_value, res_desc->Type, &tmp, D3DXPT_FLOAT); + tmp = ((ivalue & 0xff00) >> 8) * INT_FLOAT_MULTI_INVERSE; + set_number(expected_value + 1, res_desc->Type, &tmp, D3DXPT_FLOAT); + tmp = (ivalue & 0xff) * INT_FLOAT_MULTI_INVERSE; + set_number(expected_value + 2, res_desc->Type, &tmp, D3DXPT_FLOAT); + tmp = ((ivalue & 0xff000000) >> 24) * INT_FLOAT_MULTI_INVERSE; + set_number(expected_value + 3, res_desc->Type, &tmp, D3DXPT_FLOAT); + + ok(hr == D3D_OK, "%u - %s: SetInt failed, got %#x, expected %#x\n", + i, res_full_name, hr, D3D_OK); + } + else + { + ok(hr == D3DERR_INVALIDCALL, "%u - %s: SetInt failed, got %#x, expected %#x\n", + i, res_full_name, hr, D3DERR_INVALIDCALL); + } + test_effect_parameter_value_GetTestGroup(&res[k], effect, expected_value, parameter, i); + test_effect_parameter_value_ResetValue(&res[k], effect, &blob[res_value_offset], parameter, i); + + /* SetIntArray */ + *input_value = 123456; + for (l = 0; l < res_desc->Bytes / sizeof(*input_value); ++l) + { + *(input_value + l) = *(input_value + l - 1) + 23; + } + memcpy(expected_value, &blob[res_value_offset], res_desc->Bytes); + hr = effect->lpVtbl->SetIntArray(effect, parameter, (INT *)input_value, res_desc->Bytes / sizeof(*input_value)); + if (res_desc->Class == D3DXPC_SCALAR + || res_desc->Class == D3DXPC_VECTOR + || res_desc->Class == D3DXPC_MATRIX_ROWS) + { + for (l = 0; l < res_desc->Bytes / sizeof(*input_value); ++l) + { + set_number(expected_value + l, res_desc->Type, input_value + l, D3DXPT_INT); + } + ok(hr == D3D_OK, "%u - %s: SetIntArray failed, got %#x, expected %#x\n", i, res_full_name, hr, D3D_OK); + } + else + { + ok(hr == D3DERR_INVALIDCALL, "%u - %s: SetIntArray failed, got %#x, expected %#x\n", + i, res_full_name, hr, D3DERR_INVALIDCALL); + } + test_effect_parameter_value_GetTestGroup(&res[k], effect, expected_value, parameter, i); + test_effect_parameter_value_ResetValue(&res[k], effect, &blob[res_value_offset], parameter, i); + + /* SetFloat */ + fvalue = 1.33; + memcpy(expected_value, &blob[res_value_offset], res_desc->Bytes); + hr = effect->lpVtbl->SetFloat(effect, parameter, fvalue); + if (!res_desc->Elements && res_desc->Rows == 1 && res_desc->Columns == 1) + { + set_number(expected_value, res_desc->Type, &fvalue, D3DXPT_FLOAT); + ok(hr == D3D_OK, "%u - %s: SetFloat failed, got %#x, expected %#x\n", i, res_full_name, hr, D3D_OK); + } + else + { + ok(hr == D3DERR_INVALIDCALL, "%u - %s: SetFloat failed, got %#x, expected %#x\n", + i, res_full_name, hr, D3DERR_INVALIDCALL); + } + test_effect_parameter_value_GetTestGroup(&res[k], effect, expected_value, parameter, i); + test_effect_parameter_value_ResetValue(&res[k], effect, &blob[res_value_offset], parameter, i); + + /* SetFloatArray */ + fvalue = 1.33; + for (l = 0; l < res_desc->Bytes / sizeof(fvalue); ++l) + { + *(input_value + l) = *(DWORD *)&fvalue; + fvalue += 1.12; + } + memcpy(expected_value, &blob[res_value_offset], res_desc->Bytes); + hr = effect->lpVtbl->SetFloatArray(effect, parameter, (FLOAT *)input_value, res_desc->Bytes / sizeof(*input_value)); + if (res_desc->Class == D3DXPC_SCALAR + || res_desc->Class == D3DXPC_VECTOR + || res_desc->Class == D3DXPC_MATRIX_ROWS) + { + for (l = 0; l < res_desc->Bytes / sizeof(*input_value); ++l) + { + set_number(expected_value + l, res_desc->Type, input_value + l, D3DXPT_FLOAT); + } + ok(hr == D3D_OK, "%u - %s: SetFloatArray failed, got %#x, expected %#x\n", i, res_full_name, hr, D3D_OK); + } + else + { + ok(hr == D3DERR_INVALIDCALL, "%u - %s: SetFloatArray failed, got %#x, expected %#x\n", + i, res_full_name, hr, D3DERR_INVALIDCALL); + } + test_effect_parameter_value_GetTestGroup(&res[k], effect, expected_value, parameter, i); + test_effect_parameter_value_ResetValue(&res[k], effect, &blob[res_value_offset], parameter, i); + + /* SetVector */ + fvalue = -1.33; + for (l = 0; l < 4; ++l) + { + *(input_value + l) = *(DWORD *)&fvalue; + fvalue += 1.12; + } + memcpy(expected_value, &blob[res_value_offset], res_desc->Bytes); + hr = effect->lpVtbl->SetVector(effect, parameter, (D3DXVECTOR4 *)input_value); + if (!res_desc->Elements && + (res_desc->Class == D3DXPC_SCALAR + || res_desc->Class == D3DXPC_VECTOR)) + { + /* only values between 0 and INT_FLOAT_MULTI are valid */ + if (res_desc->Type == D3DXPT_INT && res_desc->Bytes == 4) + { + *expected_value = (DWORD)(max(min(*(FLOAT *)(input_value + 2), 1.0f), 0.0f) * INT_FLOAT_MULTI); + *expected_value += ((DWORD)(max(min(*(FLOAT *)(input_value + 1), 1.0f), 0.0f) * INT_FLOAT_MULTI)) << 8; + *expected_value += ((DWORD)(max(min(*(FLOAT *)input_value, 1.0f), 0.0f) * INT_FLOAT_MULTI)) << 16; + *expected_value += ((DWORD)(max(min(*(FLOAT *)(input_value + 3), 1.0f), 0.0f) * INT_FLOAT_MULTI)) << 24; + } + else + { + for (l = 0; l < 4; ++l) + { + set_number(expected_value + l, res_desc->Type, input_value + l, D3DXPT_FLOAT); + } + } + ok(hr == D3D_OK, "%u - %s: SetVector failed, got %#x, expected %#x\n", i, res_full_name, hr, D3D_OK); + } + else + { + ok(hr == D3DERR_INVALIDCALL, "%u - %s: SetVector failed, got %#x, expected %#x\n", + i, res_full_name, hr, D3DERR_INVALIDCALL); + } + test_effect_parameter_value_GetTestGroup(&res[k], effect, expected_value, parameter, i); + test_effect_parameter_value_ResetValue(&res[k], effect, &blob[res_value_offset], parameter, i); + + /* SetVectorArray */ + for (element = 0; element < res_desc->Elements + 1; ++element) + { + fvalue = 1.33; + for (l = 0; l < element * 4; ++l) + { + *(input_value + l) = *(DWORD *)&fvalue; + fvalue += 1.12; + } + memcpy(expected_value, &blob[res_value_offset], res_desc->Bytes); + hr = effect->lpVtbl->SetVectorArray(effect, parameter, (D3DXVECTOR4 *)input_value, element); + if (res_desc->Elements && res_desc->Class == D3DXPC_VECTOR && element <= res_desc->Elements) + { + for (m = 0; m < element; ++m) + { + for (l = 0; l < res_desc->Columns; ++l) + { + set_number(expected_value + m * res_desc->Columns + l, res_desc->Type, input_value + m * 4 + l, D3DXPT_FLOAT); + } + } + ok(hr == D3D_OK, "%u - %s: SetVectorArray failed, got %#x, expected %#x\n", i, res_full_name, hr, D3D_OK); + } + else + { + ok(hr == D3DERR_INVALIDCALL, "%u - %s: SetVectorArray failed, got %#x, expected %#x\n", + i, res_full_name, hr, D3DERR_INVALIDCALL); + } + test_effect_parameter_value_GetTestGroup(&res[k], effect, expected_value, parameter, i); + test_effect_parameter_value_ResetValue(&res[k], effect, &blob[res_value_offset], parameter, i); + } + + /* SetMatrix */ + fvalue = 1.33; + for (l = 0; l < 16; ++l) + { + *(input_value + l) = *(DWORD *)&fvalue; + fvalue += 1.12; + } + memcpy(expected_value, &blob[res_value_offset], res_desc->Bytes); + hr = effect->lpVtbl->SetMatrix(effect, parameter, (D3DXMATRIX *)input_value); + if (!res_desc->Elements && res_desc->Class == D3DXPC_MATRIX_ROWS) + { + for (l = 0; l < 4; ++l) + { + for (m = 0; m < 4; ++m) + { + if (m < res_desc->Rows && l < res_desc->Columns) + set_number(expected_value + l + m * res_desc->Columns, res_desc->Type, + input_value + l + m * 4, D3DXPT_FLOAT); + } + + } + ok(hr == D3D_OK, "%u - %s: SetMatrix failed, got %#x, expected %#x\n", i, res_full_name, hr, D3D_OK); + } + else + { + ok(hr == D3DERR_INVALIDCALL, "%u - %s: SetMatrix failed, got %#x, expected %#x\n", + i, res_full_name, hr, D3DERR_INVALIDCALL); + } + test_effect_parameter_value_GetTestGroup(&res[k], effect, expected_value, parameter, i); + test_effect_parameter_value_ResetValue(&res[k], effect, &blob[res_value_offset], parameter, i); + + /* SetMatrixArray */ + for (element = 0; element < res_desc->Elements + 1; ++element) + { + fvalue = 1.33; + for (l = 0; l < element * 16; ++l) + { + *(input_value + l) = *(DWORD *)&fvalue; + fvalue += 1.12; + } + memcpy(expected_value, &blob[res_value_offset], res_desc->Bytes); + hr = effect->lpVtbl->SetMatrixArray(effect, parameter, (D3DXMATRIX *)input_value, element); + if (res_desc->Class == D3DXPC_MATRIX_ROWS && element <= res_desc->Elements) + { + for (n = 0; n < element; ++n) + { + for (l = 0; l < 4; ++l) + { + for (m = 0; m < 4; ++m) + { + if (m < res_desc->Rows && l < res_desc->Columns) + set_number(expected_value + l + m * res_desc->Columns + n * res_desc->Columns * res_desc->Rows, + res_desc->Type, input_value + l + m * 4 + n * 16, D3DXPT_FLOAT); + } + + } + } + ok(hr == D3D_OK, "%u - %s: SetMatrixArray failed, got %#x, expected %#x\n", i, res_full_name, hr, D3D_OK); + } + else + { + ok(hr == D3DERR_INVALIDCALL, "%u - %s: SetMatrixArray failed, got %#x, expected %#x\n", + i, res_full_name, hr, D3DERR_INVALIDCALL); + } + test_effect_parameter_value_GetTestGroup(&res[k], effect, expected_value, parameter, i); + test_effect_parameter_value_ResetValue(&res[k], effect, &blob[res_value_offset], parameter, i); + } + + /* SetMatrixPointerArray */ + for (element = 0; element < res_desc->Elements + 1; ++element) + { + fvalue = 1.33; + for (l = 0; l < EFFECT_PARAMETER_VALUE_ARRAY_SIZE; ++l) + { + *(input_value + l) = *(DWORD *)&fvalue; + fvalue += 1.12; + } + memcpy(expected_value, &blob[res_value_offset], res_desc->Bytes); + for (l = 0; l < element; ++l) + { + matrix_pointer_array[l] = (D3DXMATRIX *)&input_value[l * sizeof(**matrix_pointer_array) / sizeof(FLOAT)]; + } + hr = effect->lpVtbl->SetMatrixPointerArray(effect, parameter, matrix_pointer_array, element); + if (res_desc->Class == D3DXPC_MATRIX_ROWS && res_desc->Elements >= element) + { + for (n = 0; n < element; ++n) + { + for (l = 0; l < 4; ++l) + { + for (m = 0; m < 4; ++m) + { + if (m < res_desc->Rows && l < res_desc->Columns) + set_number(expected_value + l + m * res_desc->Columns + n * res_desc->Columns * res_desc->Rows, + res_desc->Type, input_value + l + m * 4 + n * 16, D3DXPT_FLOAT); + } + + } + } + ok(hr == D3D_OK, "%u - %s: SetMatrixPointerArray failed, got %#x, expected %#x\n", + i, res_full_name, hr, D3D_OK); + } + else + { + ok(hr == D3DERR_INVALIDCALL, "%u - %s: SetMatrixPointerArray failed, got %#x, expected %#x\n", + i, res_full_name, hr, D3DERR_INVALIDCALL); + } + test_effect_parameter_value_GetTestGroup(&res[k], effect, expected_value, parameter, i); + test_effect_parameter_value_ResetValue(&res[k], effect, &blob[res_value_offset], parameter, i); + } + + /* SetMatrixTranspose */ + fvalue = 1.33; + for (l = 0; l < 16; ++l) + { + *(input_value + l) = *(DWORD *)&fvalue; + fvalue += 1.12; + } + memcpy(expected_value, &blob[res_value_offset], res_desc->Bytes); + hr = effect->lpVtbl->SetMatrixTranspose(effect, parameter, (D3DXMATRIX *)input_value); + if (!res_desc->Elements && res_desc->Class == D3DXPC_MATRIX_ROWS) + { + for (l = 0; l < 4; ++l) + { + for (m = 0; m < 4; ++m) + { + if (m < res_desc->Rows && l < res_desc->Columns) + set_number(expected_value + l + m * res_desc->Columns, res_desc->Type, + input_value + l * 4 + m, D3DXPT_FLOAT); + } + + } + ok(hr == D3D_OK, "%u - %s: SetMatrixTranspose failed, got %#x, expected %#x\n", i, res_full_name, hr, D3D_OK); + } + else + { + ok(hr == D3DERR_INVALIDCALL, "%u - %s: SetMatrixTranspose failed, got %#x, expected %#x\n", + i, res_full_name, hr, D3DERR_INVALIDCALL); + } + test_effect_parameter_value_GetTestGroup(&res[k], effect, expected_value, parameter, i); + test_effect_parameter_value_ResetValue(&res[k], effect, &blob[res_value_offset], parameter, i); + + /* SetMatrixTransposeArray */ + for (element = 0; element < res_desc->Elements + 1; ++element) + { + fvalue = 1.33; + for (l = 0; l < element * 16; ++l) + { + *(input_value + l) = *(DWORD *)&fvalue; + fvalue += 1.12; + } + memcpy(expected_value, &blob[res_value_offset], res_desc->Bytes); + hr = effect->lpVtbl->SetMatrixTransposeArray(effect, parameter, (D3DXMATRIX *)input_value, element); + if (res_desc->Class == D3DXPC_MATRIX_ROWS && element <= res_desc->Elements) + { + for (n = 0; n < element; ++n) + { + for (l = 0; l < 4; ++l) + { + for (m = 0; m < 4; ++m) + { + if (m < res_desc->Rows && l < res_desc->Columns) + set_number(expected_value + l + m * res_desc->Columns + n * res_desc->Columns * res_desc->Rows, + res_desc->Type, input_value + l * 4 + m + n * 16, D3DXPT_FLOAT); + } + + } + } + ok(hr == D3D_OK, "%u - %s: SetMatrixTransposeArray failed, got %#x, expected %#x\n", i, res_full_name, hr, D3D_OK); + } + else + { + ok(hr == D3DERR_INVALIDCALL, "%u - %s: SetMatrixTransposeArray failed, got %#x, expected %#x\n", + i, res_full_name, hr, D3DERR_INVALIDCALL); + } + test_effect_parameter_value_GetTestGroup(&res[k], effect, expected_value, parameter, i); + test_effect_parameter_value_ResetValue(&res[k], effect, &blob[res_value_offset], parameter, i); + } + + /* SetMatrixTransposePointerArray */ + for (element = 0; element < res_desc->Elements + 1; ++element) + { + fvalue = 1.33; + for (l = 0; l < EFFECT_PARAMETER_VALUE_ARRAY_SIZE; ++l) + { + *(input_value + l) = *(DWORD *)&fvalue; + fvalue += 1.12; + } + memcpy(expected_value, &blob[res_value_offset], res_desc->Bytes); + for (l = 0; l < element; ++l) + { + matrix_pointer_array[l] = (D3DXMATRIX *)&input_value[l * sizeof(**matrix_pointer_array) / sizeof(FLOAT)]; + } + hr = effect->lpVtbl->SetMatrixTransposePointerArray(effect, parameter, matrix_pointer_array, element); + if (res_desc->Class == D3DXPC_MATRIX_ROWS && res_desc->Elements >= element) + { + for (n = 0; n < element; ++n) + { + for (l = 0; l < 4; ++l) + { + for (m = 0; m < 4; ++m) + { + if (m < res_desc->Rows && l < res_desc->Columns) + set_number(expected_value + l + m * res_desc->Columns + n * res_desc->Columns * res_desc->Rows, + res_desc->Type, input_value + l * 4 + m + n * 16, D3DXPT_FLOAT); + } + + } + } + ok(hr == D3D_OK, "%u - %s: SetMatrixTransposePointerArray failed, got %#x, expected %#x\n", + i, res_full_name, hr, D3D_OK); + } + else + { + ok(hr == D3DERR_INVALIDCALL, "%u - %s: SetMatrixTransposePointerArray failed, got %#x, expected %#x\n", + i, res_full_name, hr, D3DERR_INVALIDCALL); + } + test_effect_parameter_value_GetTestGroup(&res[k], effect, expected_value, parameter, i); + test_effect_parameter_value_ResetValue(&res[k], effect, &blob[res_value_offset], parameter, i); + } + } + + count = effect->lpVtbl->Release(effect); + ok(!count, "Release failed %u\n", count); + } +} + +static void test_effect_setvalue_object(IDirect3DDevice9 *device) +{ + static const char expected_string[] = "test_string_1"; + static const char expected_string2[] = "test_longer_string_2"; + static const char *expected_string_array[] = {expected_string, expected_string2}; + const char *string_array[ARRAY_SIZE(expected_string_array)]; + const char *string, *string2; + IDirect3DTexture9 *texture_set; + IDirect3DTexture9 *texture; + D3DXHANDLE parameter; + ID3DXEffect *effect; + unsigned int i; + ULONG count; + HRESULT hr; + + hr = D3DXCreateEffect(device, test_effect_parameter_value_blob_object, + sizeof(test_effect_parameter_value_blob_object), NULL, NULL, 0, NULL, &effect, NULL); + ok(hr == D3D_OK, "Got result %#x, expected 0 (D3D_OK).\n", hr); + + parameter = effect->lpVtbl->GetParameterByName(effect, NULL, "tex"); + ok(parameter != NULL, "GetParameterByName failed, got %p\n", parameter); + + texture = NULL; + hr = D3DXCreateTexture(device, D3DX_DEFAULT, D3DX_DEFAULT, D3DX_DEFAULT, 0, 0, D3DPOOL_DEFAULT, &texture); + ok(hr == D3D_OK, "Got result %#x, expected 0 (D3D_OK).\n", hr); + hr = effect->lpVtbl->SetValue(effect, parameter, &texture, sizeof(texture)); + ok(hr == D3D_OK, "Got result %#x, expected 0 (D3D_OK).\n", hr); + texture_set = NULL; + hr = effect->lpVtbl->GetValue(effect, parameter, &texture_set, sizeof(texture_set)); + ok(hr == D3D_OK, "Got result %#x, expected 0 (D3D_OK).\n", hr); + ok(texture == texture_set, "Texture does not match.\n"); + + count = IDirect3DTexture9_Release(texture_set); + ok(count == 2, "Got reference count %u, expected 2.\n", count); + texture_set = NULL; + hr = effect->lpVtbl->SetValue(effect, parameter, &texture_set, sizeof(texture_set)); + ok(hr == D3D_OK, "Got result %#x, expected 0 (D3D_OK).\n", hr); + count = IDirect3DTexture9_Release(texture); + ok(!count, "Got reference count %u, expected 0.\n", count); + + hr = effect->lpVtbl->SetString(effect, "s", expected_string); + ok(hr == D3D_OK, "Got result %#x.\n", hr); + string = NULL; + hr = effect->lpVtbl->GetString(effect, "s", &string); + ok(hr == D3D_OK, "Got result %#x.\n", hr); + hr = effect->lpVtbl->GetString(effect, "s", &string2); + ok(hr == D3D_OK, "Got result %#x.\n", hr); + + ok(string != expected_string, "String pointers are the same.\n"); + ok(string == string2, "String pointers differ.\n"); + ok(!strcmp(string, expected_string), "Unexpected string '%s'.\n", string); + + string = expected_string2; + hr = effect->lpVtbl->SetValue(effect, "s", &string, sizeof(string) - 1); + ok(hr == D3DERR_INVALIDCALL, "Got result %#x.\n", hr); + hr = effect->lpVtbl->SetValue(effect, "s", &string, sizeof(string)); + ok(hr == D3D_OK, "Got result %#x.\n", hr); + hr = effect->lpVtbl->SetValue(effect, "s", &string, sizeof(string) * 2); + ok(hr == D3D_OK, "Got result %#x.\n", hr); + string = NULL; + hr = effect->lpVtbl->GetValue(effect, "s", &string, sizeof(string)); + ok(hr == D3D_OK, "Got result %#x.\n", hr); + + ok(string != expected_string2, "String pointers are the same.\n"); + ok(!strcmp(string, expected_string2), "Unexpected string '%s'.\n", string); + + hr = effect->lpVtbl->SetValue(effect, "s_2", expected_string_array, + sizeof(expected_string_array)); + ok(hr == D3D_OK, "Got result %#x.\n", hr); + hr = effect->lpVtbl->GetValue(effect, "s_2", string_array, + sizeof(string_array)); + ok(hr == D3D_OK, "Got result %#x.\n", hr); + for (i = 0; i < ARRAY_SIZE(expected_string_array); ++i) + { + ok(!strcmp(string_array[i], expected_string_array[i]), "Unexpected string '%s', i %u.\n", + string_array[i], i); + } + effect->lpVtbl->Release(effect); +} + +/* + * fxc.exe /Tfx_2_0 + */ +#if 0 +float a = 2.1; +float b[1]; +float c ; +struct {float e;} f; +float g ; +struct s {float j;}; +float i ; +technique t { pass p { } } +#endif +static const DWORD test_effect_variable_names_blob[] = +{ +0xfeff0901, 0x0000024c, 0x00000000, 0x00000003, 0x00000000, 0x00000024, 0x00000000, 0x00000000, +0x00000001, 0x00000001, 0x40066666, 0x00000002, 0x00000061, 0x00000003, 0x00000000, 0x0000004c, +0x00000000, 0x00000001, 0x00000001, 0x00000001, 0x00000000, 0x00000002, 0x00000062, 0x00000003, +0x00000000, 0x0000009c, 0x00000000, 0x00000000, 0x00000001, 0x00000001, 0x00000000, 0x40400000, +0x00000003, 0x00000000, 0x00000094, 0x00000000, 0x00000000, 0x00000001, 0x00000001, 0x00000002, +0x00000064, 0x00000002, 0x00000063, 0x00000000, 0x00000005, 0x000000dc, 0x00000000, 0x00000000, +0x00000001, 0x00000003, 0x00000000, 0x000000e4, 0x00000000, 0x00000000, 0x00000001, 0x00000001, +0x00000000, 0x00000002, 0x00000066, 0x00000002, 0x00000065, 0x00000003, 0x00000000, 0x00000134, +0x00000000, 0x00000000, 0x00000001, 0x00000001, 0x00000000, 0x40400000, 0x00000003, 0x00000000, +0x0000012c, 0x00000000, 0x00000001, 0x00000001, 0x00000001, 0x00000002, 0x00000068, 0x00000002, +0x00000067, 0x00000003, 0x00000000, 0x000001a4, 0x00000000, 0x00000000, 0x00000001, 0x00000001, +0x00000000, 0x40800000, 0x00000000, 0x00000005, 0x00000194, 0x00000000, 0x00000001, 0x00000001, +0x00000003, 0x00000000, 0x0000019c, 0x00000000, 0x00000000, 0x00000001, 0x00000001, 0x00000002, +0x0000006b, 0x00000002, 0x0000006a, 0x00000002, 0x00000069, 0x40a00000, 0x00000000, 0x00000005, +0x000001e4, 0x00000000, 0x00000001, 0x00000001, 0x00000003, 0x00000000, 0x000001ec, 0x00000000, +0x00000000, 0x00000001, 0x00000001, 0x00000002, 0x0000006c, 0x00000002, 0x0000006a, 0x40c00000, +0x00000000, 0x00000005, 0x0000022c, 0x00000000, 0x00000001, 0x00000001, 0x00000003, 0x00000000, +0x00000234, 0x00000000, 0x00000000, 0x00000001, 0x00000001, 0x00000002, 0x0000006d, 0x00000002, +0x0000006a, 0x00000002, 0x00000070, 0x00000002, 0x00000074, 0x00000006, 0x00000001, 0x00000001, +0x00000001, 0x00000004, 0x00000020, 0x00000000, 0x00000000, 0x0000002c, 0x00000048, 0x00000000, +0x00000000, 0x00000054, 0x00000070, 0x00000000, 0x00000001, 0x00000078, 0x00000074, 0x000000a4, +0x000000d8, 0x00000000, 0x00000000, 0x000000ec, 0x00000108, 0x00000000, 0x00000001, 0x00000110, +0x0000010c, 0x0000013c, 0x00000158, 0x00000000, 0x00000001, 0x00000160, 0x0000015c, 0x00000244, +0x00000001, 0x00000001, 0x000001b0, 0x000001ac, 0x0000023c, 0x00000001, 0x00000000, 0x000001f8, +0x000001f4, 0x00000000, 0x00000000, +}; + +static void test_effect_variable_names(IDirect3DDevice9 *device) +{ + ID3DXEffect *effect; + ULONG count; + HRESULT hr; + D3DXHANDLE parameter, p; + + hr = D3DXCreateEffect(device, test_effect_variable_names_blob, + sizeof(test_effect_variable_names_blob), NULL, NULL, 0, NULL, &effect, NULL); + ok(hr == D3D_OK, "D3DXCreateEffect failed, got %#x, expected %#x\n", hr, D3D_OK); + + /* + * check invalid calls + * This will crash: + * effect->lpVtbl->GetAnnotationByName(effect, "invalid1", "invalid2"); + */ + p = effect->lpVtbl->GetParameterByName(effect, NULL, NULL); + ok(p == NULL, "GetParameterByName failed, got %p, expected %p\n", p, NULL); + + p = effect->lpVtbl->GetParameterByName(effect, NULL, "invalid1"); + ok(p == NULL, "GetParameterByName failed, got %p\n", p); + + p = effect->lpVtbl->GetParameterByName(effect, "invalid1", NULL); + ok(p == NULL, "GetParameterByName failed, got %p\n", p); + + p = effect->lpVtbl->GetParameterByName(effect, "invalid1", "invalid2"); + ok(p == NULL, "GetParameterByName failed, got %p, expected %p\n", p, NULL); + + /* float a; */ + parameter = effect->lpVtbl->GetParameterByName(effect, NULL, "a"); + ok(parameter != NULL, "GetParameterByName failed, got %p\n", parameter); + + p = effect->lpVtbl->GetParameterByName(effect, "a", NULL); + ok(parameter == p, "GetParameterByName failed, got %p, expected %p\n", p, parameter); + + /* members */ + p = effect->lpVtbl->GetParameterByName(effect, NULL, "a."); + ok(p == NULL, "GetParameterByName failed, got %p\n", p); + + p = effect->lpVtbl->GetParameterByName(effect, "a.", NULL); + ok(p == NULL, "GetParameterByName failed, got %p\n", p); + + p = effect->lpVtbl->GetParameterByName(effect, "a", "."); + ok(p == NULL, "GetParameterByName failed, got %p\n", p); + + p = effect->lpVtbl->GetParameterByName(effect, NULL, "a.invalid"); + ok(p == NULL, "GetParameterByName failed, got %p\n", p); + + p = effect->lpVtbl->GetParameterByName(effect, "a.invalid", NULL); + ok(p == NULL, "GetParameterByName failed, got %p\n", p); + + p = effect->lpVtbl->GetParameterByName(effect, "a", ".invalid"); + ok(p == NULL, "GetParameterByName failed, got %p\n", p); + + p = effect->lpVtbl->GetParameterByName(effect, "a.", "invalid"); + ok(p == NULL, "GetParameterByName failed, got %p\n", p); + + p = effect->lpVtbl->GetParameterByName(effect, "a", "invalid"); + ok(p == NULL, "GetParameterByName failed, got %p\n", p); + + /* elements */ + p = effect->lpVtbl->GetParameterByName(effect, NULL, "a[]"); + ok(p == NULL, "GetParameterByName failed, got %p\n", p); + + p = effect->lpVtbl->GetParameterByName(effect, "a[]", NULL); + ok(p == NULL, "GetParameterByName failed, got %p\n", p); + + p = effect->lpVtbl->GetParameterByName(effect, NULL, "a[0]"); + ok(p == NULL, "GetParameterByName failed, got %p\n", p); + + p = effect->lpVtbl->GetParameterByName(effect, "a[0]", NULL); + ok(p == NULL, "GetParameterByName failed, got %p\n", p); + + p = effect->lpVtbl->GetParameterByName(effect, "a", "[0]"); + ok(p == NULL, "GetParameterByName failed, got %p\n", p); + + p = effect->lpVtbl->GetParameterElement(effect, "a", 0); + ok(p == NULL, "GetParameterElement failed, got %p\n", p); + + /* annotations */ + p = effect->lpVtbl->GetParameterByName(effect, NULL, "a@"); + ok(p == NULL, "GetParameterByName failed, got %p\n", p); + + p = effect->lpVtbl->GetParameterByName(effect, "a@", NULL); + ok(p == NULL, "GetParameterByName failed, got %p\n", p); + + p = effect->lpVtbl->GetParameterByName(effect, "a", "@invalid"); + ok(p == NULL, "GetParameterByName failed, got %p\n", p); + + p = effect->lpVtbl->GetParameterByName(effect, "a@", "invalid"); + ok(p == NULL, "GetParameterByName failed, got %p\n", p); + + p = effect->lpVtbl->GetParameterByName(effect, NULL, "a@invalid"); + ok(p == NULL, "GetParameterByName failed, got %p\n", p); + + p = effect->lpVtbl->GetParameterByName(effect, "a@invalid", NULL); + ok(p == NULL, "GetParameterByName failed, got %p\n", p); + + p = effect->lpVtbl->GetAnnotationByName(effect, "a", NULL); + ok(p == NULL, "GetAnnotationByName failed, got %p\n", p); + + p = effect->lpVtbl->GetAnnotationByName(effect, "a", "invalid"); + ok(p == NULL, "GetAnnotationByName failed, got %p\n", p); + + p = effect->lpVtbl->GetAnnotation(effect, "a", 0); + ok(p == NULL, "GetAnnotation failed, got %p\n", p); + + /* float b[1]; */ + parameter = effect->lpVtbl->GetParameterByName(effect, NULL, "b"); + ok(parameter != NULL, "GetParameterByName failed, got %p\n", parameter); + + p = effect->lpVtbl->GetParameterByName(effect, "b", NULL); + ok(parameter == p, "GetParameterByName failed, got %p, expected %p\n", p, parameter); + + /* elements */ + p = effect->lpVtbl->GetParameterByName(effect, NULL, "b[]"); + ok(p == NULL, "GetParameterByName failed, got %p\n", p); + + parameter = effect->lpVtbl->GetParameterByName(effect, NULL, "b[0]"); + ok(parameter != NULL, "GetParameterByName failed, got %p\n", parameter); + + p = effect->lpVtbl->GetParameterByName(effect, "b[0]", NULL); + ok(parameter == p, "GetParameterByName failed, got %p, expected %p\n", p, parameter); + + p = effect->lpVtbl->GetParameterElement(effect, "b", 0); + ok(parameter == p, "GetParameterElement failed, got %p, expected %p\n", p, parameter); + + p = effect->lpVtbl->GetParameterByName(effect, "b", "[0]"); + ok(p == NULL, "GetParameterByName failed, got %p\n", p); + + p = effect->lpVtbl->GetParameterByName(effect, NULL, "b[1]"); + ok(p == NULL, "GetParameterByName failed, got %p\n", p); + + p = effect->lpVtbl->GetParameterElement(effect, "b", 1); + ok(p == NULL, "GetParameterElement failed, got %p\n", p); + + /* float c ; */ + parameter = effect->lpVtbl->GetParameterByName(effect, NULL, "c"); + ok(parameter != NULL, "GetParameterByName failed, got %p\n", parameter); + + p = effect->lpVtbl->GetParameterByName(effect, "c", NULL); + ok(parameter == p, "GetParameterByName failed, got %p, expected %p\n", p, parameter); + + /* annotations */ + p = effect->lpVtbl->GetParameterByName(effect, "c", "@d"); + ok(p == NULL, "GetParameterByName failed, got %p\n", p); + + p = effect->lpVtbl->GetParameterByName(effect, "c@", "d"); + ok(p == NULL, "GetParameterByName failed, got %p\n", p); + + p = effect->lpVtbl->GetParameterByName(effect, NULL, "c@invalid"); + ok(p == NULL, "GetParameterByName failed, got %p\n", p); + + p = effect->lpVtbl->GetParameterByName(effect, "c@invalid", NULL); + ok(p == NULL, "GetParameterByName failed, got %p\n", p); + + p = effect->lpVtbl->GetAnnotationByName(effect, "c", NULL); + ok(p == NULL, "GetAnnotationByName failed, got %p\n", p); + + p = effect->lpVtbl->GetAnnotationByName(effect, "c", "invalid"); + ok(p == NULL, "GetAnnotationByName failed, got %p\n", p); + + parameter = effect->lpVtbl->GetParameterByName(effect, NULL, "c@d"); + ok(parameter != NULL, "GetParameterByName failed, got %p\n", parameter); + + p = effect->lpVtbl->GetParameterByName(effect, "c@d", NULL); + ok(parameter == p, "GetParameterByName failed, got %p, expected %p\n", p, parameter); + + p = effect->lpVtbl->GetAnnotationByName(effect, "c", "d"); + ok(parameter == p, "GetAnnotationByName failed, got %p, expected %p\n", p, parameter); + + p = effect->lpVtbl->GetAnnotation(effect, "c", 0); + ok(parameter == p, "GetAnnotation failed, got %p, expected %p\n", p, parameter); + + p = effect->lpVtbl->GetAnnotation(effect, "c", 1); + ok(p == NULL, "GetAnnotation failed, got %p\n", p); + + /* struct {float e;} f; */ + parameter = effect->lpVtbl->GetParameterByName(effect, NULL, "f"); + ok(parameter != NULL, "GetParameterByName failed, got %p\n", parameter); + + p = effect->lpVtbl->GetParameterByName(effect, "f", NULL); + ok(parameter == p, "GetParameterByName failed, got %p, expected %p\n", p, parameter); + + /* members */ + parameter = effect->lpVtbl->GetParameterByName(effect, NULL, "f.e"); + ok(parameter != NULL, "GetParameterByName failed, got %p\n", parameter); + + p = effect->lpVtbl->GetParameterByName(effect, "f.e", NULL); + ok(parameter == p, "GetParameterByName failed, got %p, expected %p\n", p, parameter); + + p = effect->lpVtbl->GetParameterByName(effect, "f", "e"); + ok(parameter == p, "GetParameterByName failed, got %p, expected %p\n", p, parameter); + + p = effect->lpVtbl->GetParameterByName(effect, "f", ".e"); + ok(p == NULL, "GetParameterByName failed, got %p\n", p); + + p = effect->lpVtbl->GetParameterByName(effect, "f.", "e"); + ok(p == NULL, "GetParameterByName failed, got %p\n", p); + + p = effect->lpVtbl->GetParameterByName(effect, "f.invalid", NULL); + ok(p == NULL, "GetParameterByName failed, got %p\n", p); + + p = effect->lpVtbl->GetParameterByName(effect, NULL, "f.invalid"); + ok(p == NULL, "GetParameterByName failed, got %p\n", p); + + /* float g ; */ + parameter = effect->lpVtbl->GetParameterByName(effect, NULL, "g@h[0]"); + ok(parameter != NULL, "GetParameterByName failed, got %p\n", parameter); + + p = effect->lpVtbl->GetAnnotationByName(effect, "g", "h[0]"); + ok(parameter == p, "GetAnnotationByName failed, got %p, expected %p\n", p, parameter); + + p = effect->lpVtbl->GetParameterElement(effect, "g@h", 0); + ok(parameter == p, "GetParameterElement failed, got %p, expected %p\n", p, parameter); + + p = effect->lpVtbl->GetParameterElement(effect, effect->lpVtbl->GetAnnotation(effect, "g", 0), 0); + ok(parameter == p, "GetParameterElement failed, got %p, expected %p\n", p, parameter); + + /* struct s {float j;}; float i ; */ + parameter = effect->lpVtbl->GetParameterByName(effect, NULL, "i@k[0].j"); + ok(parameter != NULL, "GetParameterByName failed, got %p\n", parameter); + + p = effect->lpVtbl->GetAnnotationByName(effect, "i", "k[0].j"); + ok(parameter == p, "GetAnnotationByName failed, got %p, expected %p\n", p, parameter); + + p = effect->lpVtbl->GetParameterByName(effect, effect->lpVtbl->GetParameterElement(effect, "i@k", 0), "j"); + ok(parameter == p, "GetParameterElement failed, got %p, expected %p\n", p, parameter); + + /* technique t */ + parameter = effect->lpVtbl->GetAnnotationByName(effect, "t", "l[0].j"); + ok(parameter != NULL, "GetParameterByName failed, got %p\n", parameter); + + /* pass p */ + parameter = effect->lpVtbl->GetAnnotationByName(effect, effect->lpVtbl->GetPassByName(effect, "t", "p"), "m[0].j"); + ok(parameter != NULL, "GetParameterByName failed, got %p\n", parameter); + + count = effect->lpVtbl->Release(effect); + ok(!count, "Release failed %u\n", count); +} + +static void test_effect_compilation_errors(IDirect3DDevice9 *device) +{ + ID3DXEffect *effect; + ID3DXBuffer *compilation_errors; + HRESULT hr; + + /* Test binary effect */ + compilation_errors = (ID3DXBuffer*)0xdeadbeef; + hr = D3DXCreateEffect(NULL, NULL, 0, NULL, NULL, 0, NULL, NULL, &compilation_errors); + ok(hr == D3DERR_INVALIDCALL, "D3DXCreateEffect failed, got %#x, expected %#x\n", hr, D3DERR_INVALIDCALL); + ok(!compilation_errors, "Returned %p\n", compilation_errors); + + compilation_errors = (ID3DXBuffer*)0xdeadbeef; + hr = D3DXCreateEffect(device, test_effect_variable_names_blob, + sizeof(test_effect_variable_names_blob), NULL, NULL, 0, NULL, &effect, &compilation_errors); + ok(hr == D3D_OK, "D3DXCreateEffect failed, got %#x, expected %#x\n", hr, D3D_OK); + ok(!compilation_errors, "Returned %p\n", compilation_errors); + effect->lpVtbl->Release(effect); +} + +/* + * fxc.exe /Tfx_2_0 + */ +#if 0 +vertexshader vs_arr1[2] = +{ + asm + { + vs_1_1 + def c0, 1, 1, 1, 1 + mov oPos, c0 + }, + asm + { + vs_2_0 + def c0, 2, 2, 2, 2 + mov oPos, c0 + } +}; + +sampler sampler1 = + sampler_state + { + MipFilter = LINEAR; + }; + +float4x4 camera : VIEW = {4.0,0.0,0.0,0.0, 0.0,0.0,0.0,0.0, 0.0,0.0,0.0,0.0, 0.0,0.0,0.0,6.0}; +technique tech0 +{ + pass p0 + { + vertexshader = vs_arr1[1]; + VertexShaderConstant1[3] = {2,2,2,2}; + BlendOp = 2; + AlphaOp[3] = 4; + ZEnable = true; + WorldTransform[1]={2.0,0.0,0.0,0.0, 0.0,0.0,0.0,0.0, 0.0,0.0,0.0,0.0, 0.0,0.0,0.0,4.0}; + ViewTransform=(camera); + LightEnable[2] = TRUE; + LightType[2] = POINT; + LightPosition[2] = {4.0f, 5.0f, 6.0f}; + Sampler[1] = sampler1; + } +} +#endif +static const DWORD test_effect_states_effect_blob[] = +{ + 0xfeff0901, 0x000002e8, 0x00000000, 0x00000010, 0x00000004, 0x00000020, 0x00000000, 0x00000002, + 0x00000001, 0x00000002, 0x00000008, 0x615f7376, 0x00317272, 0x0000000a, 0x00000004, 0x00000074, + 0x00000000, 0x00000000, 0x00000002, 0x00000002, 0x00000002, 0x00000000, 0x00000000, 0x00000000, + 0x00000001, 0x00000001, 0x00000001, 0x000000ab, 0x00000100, 0x00000044, 0x00000040, 0x00000009, + 0x706d6173, 0x3172656c, 0x00000000, 0x00000003, 0x00000002, 0x000000e0, 0x000000ec, 0x00000000, + 0x00000004, 0x00000004, 0x40800000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x40c00000, 0x00000007, 0x656d6163, 0x00006172, 0x00000005, 0x57454956, 0x00000000, + 0x00000003, 0x00000010, 0x00000004, 0x00000000, 0x00000000, 0x00000000, 0x40000000, 0x40000000, + 0x40000000, 0x40000000, 0x00000003, 0x00000003, 0x00000000, 0x00000000, 0x00000000, 0x00000004, + 0x00000001, 0x00000002, 0x00000002, 0x00000002, 0x00000000, 0x00000000, 0x00000000, 0x00000001, + 0x00000001, 0x00000004, 0x00000002, 0x00000002, 0x00000000, 0x00000000, 0x00000000, 0x00000001, + 0x00000001, 0x00000001, 0x00000002, 0x00000002, 0x00000000, 0x00000000, 0x00000000, 0x00000001, + 0x00000001, 0x40000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x40800000, 0x00000003, 0x00000002, 0x00000000, 0x00000000, 0x00000000, 0x00000010, 0x00000001, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000003, 0x00000002, 0x00000000, 0x00000000, 0x00000000, 0x00000004, 0x00000004, 0x00000001, + 0x00000002, 0x00000002, 0x00000000, 0x00000000, 0x00000000, 0x00000001, 0x00000001, 0x00000001, + 0x00000002, 0x00000002, 0x00000000, 0x00000000, 0x00000000, 0x00000001, 0x00000001, 0x40800000, + 0x40a00000, 0x40c00000, 0x00000003, 0x00000002, 0x00000000, 0x00000000, 0x00000000, 0x00000003, + 0x00000001, 0x00000000, 0x0000000a, 0x00000004, 0x00000000, 0x00000000, 0x00000000, 0x00000003, + 0x00003070, 0x00000006, 0x68636574, 0x00000030, 0x00000003, 0x00000001, 0x00000005, 0x00000004, + 0x00000004, 0x00000018, 0x00000000, 0x00000000, 0x0000002c, 0x00000060, 0x00000000, 0x00000000, + 0x00000084, 0x000000a0, 0x00000000, 0x00000000, 0x000002dc, 0x00000000, 0x00000001, 0x000002d4, + 0x00000000, 0x0000000b, 0x00000092, 0x00000000, 0x000000fc, 0x000000f8, 0x00000098, 0x00000003, + 0x00000120, 0x00000110, 0x0000004b, 0x00000000, 0x00000140, 0x0000013c, 0x0000006b, 0x00000003, + 0x00000160, 0x0000015c, 0x00000000, 0x00000000, 0x00000180, 0x0000017c, 0x0000007d, 0x00000001, + 0x000001dc, 0x0000019c, 0x0000007c, 0x00000000, 0x00000238, 0x000001f8, 0x00000091, 0x00000002, + 0x00000258, 0x00000254, 0x00000084, 0x00000002, 0x00000278, 0x00000274, 0x00000088, 0x00000002, + 0x000002a0, 0x00000294, 0x000000b2, 0x00000001, 0x000002c0, 0x000002bc, 0x00000002, 0x00000003, + 0x00000001, 0x0000002c, 0xfffe0101, 0x00000051, 0xa00f0000, 0x3f800000, 0x3f800000, 0x3f800000, + 0x3f800000, 0x00000001, 0xc00f0000, 0xa0e40000, 0x0000ffff, 0x00000002, 0x0000002c, 0xfffe0200, + 0x05000051, 0xa00f0000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x02000001, 0xc00f0000, + 0xa0e40000, 0x0000ffff, 0x00000000, 0x00000000, 0xffffffff, 0x0000000a, 0x00000001, 0x00000009, + 0x706d6173, 0x3172656c, 0x00000000, 0x00000000, 0x00000000, 0xffffffff, 0x00000006, 0x00000000, + 0x0000016c, 0x46580200, 0x0030fffe, 0x42415443, 0x0000001c, 0x0000008b, 0x46580200, 0x00000001, + 0x0000001c, 0x20000100, 0x00000088, 0x00000030, 0x00000002, 0x00000004, 0x00000038, 0x00000048, + 0x656d6163, 0xab006172, 0x00030003, 0x00040004, 0x00000001, 0x00000000, 0x40800000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x40c00000, 0x4d007874, 0x6f726369, + 0x74666f73, 0x29522820, 0x534c4820, 0x6853204c, 0x72656461, 0x6d6f4320, 0x656c6970, 0x2e392072, + 0x392e3932, 0x332e3235, 0x00313131, 0x0002fffe, 0x54494c43, 0x00000000, 0x0024fffe, 0x434c5846, + 0x00000004, 0x10000004, 0x00000001, 0x00000000, 0x00000002, 0x00000000, 0x00000000, 0x00000004, + 0x00000000, 0x10000004, 0x00000001, 0x00000000, 0x00000002, 0x00000004, 0x00000000, 0x00000004, + 0x00000004, 0x10000004, 0x00000001, 0x00000000, 0x00000002, 0x00000008, 0x00000000, 0x00000004, + 0x00000008, 0x10000004, 0x00000001, 0x00000000, 0x00000002, 0x0000000c, 0x00000000, 0x00000004, + 0x0000000c, 0xf0f0f0f0, 0x0f0f0f0f, 0x0000ffff, 0x00000000, 0x00000000, 0xffffffff, 0x00000000, + 0x00000001, 0x0000000b, 0x615f7376, 0x5b317272, 0x00005d31, +}; +#define TEST_EFFECT_STATES_VSHADER_POS 271 + +static void test_effect_states(IDirect3DDevice9 *device) +{ + D3DMATRIX test_mat = + {{{ + -1.0f, 0.0f, 0.0f, 0.0f, + 0.0f, 0.0f, 0.0f, 0.0f, + 0.0f, 0.0f, 0.0f, 0.0f, + 0.0f, 0.0f, 0.0f, 0.0f + }}}; + D3DMATRIX test_mat_camera = + {{{ + 4.0f, 0.0f, 0.0f, 0.0f, + 0.0f, 0.0f, 0.0f, 0.0f, + 0.0f, 0.0f, 0.0f, 0.0f, + 0.0f, 0.0f, 0.0f, 6.0f + }}}; + D3DMATRIX test_mat_world1 = + {{{ + 2.0f, 0.0f, 0.0f, 0.0f, + 0.0f, 0.0f, 0.0f, 0.0f, + 0.0f, 0.0f, 0.0f, 0.0f, + 0.0f, 0.0f, 0.0f, 4.0f + }}}; + D3DMATRIX mat; + HRESULT hr; + ID3DXEffect *effect; + UINT npasses; + DWORD value; + IDirect3DVertexShader9 *vshader; + void *byte_code; + UINT byte_code_size; + BOOL bval; + D3DLIGHT9 light; + float float_data[4]; + + hr = D3DXCreateEffect(device, test_effect_states_effect_blob, sizeof(test_effect_states_effect_blob), + NULL, NULL, 0, NULL, &effect, NULL); + ok(hr == D3D_OK, "Got result %x, expected 0 (D3D_OK).\n", hr); + + /* State affected in passes saved/restored even if no pass + was performed. States not present in passes are not saved & + restored */ + hr = IDirect3DDevice9_SetRenderState(device, D3DRS_BLENDOP, 1); + ok(hr == D3D_OK, "Got result %x, expected 0 (D3D_OK).\n", hr); + hr = IDirect3DDevice9_SetRenderState(device, D3DRS_ALPHAFUNC, 1); + ok(hr == D3D_OK, "Got result %x, expected 0 (D3D_OK).\n", hr); + + hr = effect->lpVtbl->Begin(effect, &npasses, 0); + ok(hr == D3D_OK, "Got result %x, expected 0 (D3D_OK).\n", hr); + ok(npasses == 1, "Expected 1 pass, got %u\n", npasses); + + hr = IDirect3DDevice9_SetRenderState(device, D3DRS_BLENDOP, 3); + ok(hr == D3D_OK, "Got result %x, expected 0 (D3D_OK).\n", hr); + hr = IDirect3DDevice9_SetRenderState(device, D3DRS_ALPHAFUNC, 2); + ok(hr == D3D_OK, "Got result %x, expected 0 (D3D_OK).\n", hr); + + hr = effect->lpVtbl->End(effect); + ok(hr == D3D_OK, "Got result %x, expected 0 (D3D_OK).\n", hr); + + hr = IDirect3DDevice9_GetRenderState(device, D3DRS_BLENDOP, &value); + ok(hr == D3D_OK, "Got result %x, expected 0 (D3D_OK).\n", hr); + ok(value == 1, "Got result %u, expected %u.\n", value, 1); + hr = IDirect3DDevice9_GetRenderState(device, D3DRS_ALPHAFUNC, &value); + ok(value == 2, "Got result %u, expected %u.\n", value, 2); + + /* Test states application in BeginPass. No states are restored + on EndPass. */ + hr = IDirect3DDevice9_SetSamplerState(device, 1, D3DSAMP_MIPFILTER, 0); + ok(hr == D3D_OK, "Got result %x, expected 0 (D3D_OK).\n", hr); + hr = IDirect3DDevice9_SetRenderState(device, D3DRS_ZENABLE, 0); + ok(hr == D3D_OK, "Got result %x, expected 0 (D3D_OK).\n", hr); + + hr = IDirect3DDevice9_GetLightEnable(device, 2, &bval); + ok(hr == D3D_OK, "Got result %x, expected 0 (D3D_OK).\n", hr); + if (hr == D3D_OK) + ok(!bval, "Got result %u, expected 0.\n", bval); + + hr = IDirect3DDevice9_SetTransform(device, D3DTS_WORLDMATRIX(1), &test_mat); + hr = effect->lpVtbl->Begin(effect, NULL, 0); + ok(hr == D3D_OK, "Got result %x, expected 0 (D3D_OK).\n", hr); + + hr = IDirect3DDevice9_GetTransform(device, D3DTS_WORLDMATRIX(1), &mat); + ok(hr == D3D_OK, "Got result %x, expected 0 (D3D_OK).\n", hr); + ok(!memcmp(mat.m, test_mat.m, sizeof(mat)), "World matrix does not match.\n"); + + hr = effect->lpVtbl->BeginPass(effect, 0); + ok(hr == D3D_OK, "Got result %x, expected 0 (D3D_OK).\n", hr); + + hr = IDirect3DDevice9_GetTransform(device, D3DTS_WORLDMATRIX(1), &mat); + ok(hr == D3D_OK, "Got result %x, expected 0 (D3D_OK).\n", hr); + ok(!memcmp(mat.m, test_mat_world1.m, sizeof(mat)), "World matrix does not match.\n"); + + hr = IDirect3DDevice9_GetTransform(device, D3DTS_VIEW, &mat); + ok(hr == D3D_OK, "Got result %x, expected 0 (D3D_OK).\n", hr); + ok(!memcmp(mat.m, test_mat_camera.m, sizeof(mat)), "View matrix does not match.\n"); + + hr = IDirect3DDevice9_GetRenderState(device, D3DRS_BLENDOP, &value); + ok(hr == D3D_OK, "Got result %x, expected 0 (D3D_OK).\n", hr); + ok(value == 2, "Got result %u, expected %u\n", value, 2); + + hr = IDirect3DDevice9_GetVertexShader(device, &vshader); + ok(hr == D3D_OK, "Got result %x, expected 0 (D3D_OK).\n", hr); + ok(vshader != NULL, "Got NULL vshader.\n"); + if (vshader) + { + hr = IDirect3DVertexShader9_GetFunction(vshader, NULL, &byte_code_size); + ok(hr == D3D_OK, "Got result %x, expected 0 (D3D_OK).\n", hr); + byte_code = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, byte_code_size); + hr = IDirect3DVertexShader9_GetFunction(vshader, byte_code, &byte_code_size); + ok(hr == D3D_OK, "Got result %x, expected 0 (D3D_OK).\n", hr); + ok(byte_code_size > 1, "Got unexpected byte code size %u.\n", byte_code_size); + ok(!memcmp(byte_code, &test_effect_states_effect_blob[TEST_EFFECT_STATES_VSHADER_POS], byte_code_size), + "Incorrect shader selected.\n"); + HeapFree(GetProcessHeap(), 0, byte_code); + IDirect3DVertexShader9_Release(vshader); + } + + hr = IDirect3DDevice9_GetLightEnable(device, 2, &bval); + ok(hr == D3D_OK, "Got result %x, expected 0 (D3D_OK).\n", hr); + if (hr == D3D_OK) + ok(bval, "Got result %u, expected TRUE.\n", bval); + hr = IDirect3DDevice9_GetLight(device, 2, &light); + ok(hr == D3D_OK, "Got result %x, expected 0 (D3D_OK).\n", hr); + if (hr == D3D_OK) + ok(light.Position.x == 4.0f && light.Position.y == 5.0f && light.Position.z == 6.0f, + "Got unexpected light position (%f, %f, %f).\n", light.Position.x, light.Position.y, light.Position.z); + hr = IDirect3DDevice9_GetVertexShaderConstantF(device, 3, float_data, 1); + ok(hr == D3D_OK, "Got result %x, expected 0 (D3D_OK).\n", hr); + ok(float_data[0] == 2.0f && float_data[1] == 2.0f && float_data[2] == 2.0f && float_data[3] == 2.0f, + "Got unexpected vertex shader floats: (%f %f %f %f).\n", + float_data[0], float_data[1], float_data[2], float_data[3]); + + hr = effect->lpVtbl->EndPass(effect); + ok(hr == D3D_OK, "Got result %x, expected 0 (D3D_OK).\n", hr); + hr = IDirect3DDevice9_GetRenderState(device, D3DRS_BLENDOP, &value); + ok(hr == D3D_OK, "Got result %x, expected 0 (D3D_OK).\n", hr); + ok(value == 2, "Got result %u, expected %u\n", value, 2); + + hr = IDirect3DDevice9_GetRenderState(device, D3DRS_ZENABLE, &value); + ok(hr == D3D_OK, "Got result %x, expected 0 (D3D_OK).\n", hr); + ok(value, "Got result %u, expected TRUE.\n", value); + + hr = IDirect3DDevice9_GetSamplerState(device, 1, D3DSAMP_MIPFILTER, &value); + ok(hr == D3D_OK, "Got result %x, expected 0 (D3D_OK).\n", hr); + ok(value == D3DTEXF_LINEAR, "Unexpected sampler 1 mipfilter %u.\n", value); + + hr = IDirect3DDevice9_GetTextureStageState(device, 3, D3DTSS_ALPHAOP, &value); + ok(hr == D3D_OK, "Got result %x, expected 0 (D3D_OK).\n", hr); + ok(value == 4, "Unexpected texture stage 3 AlphaOp %u.\n", value); + + hr = effect->lpVtbl->End(effect); + ok(hr == D3D_OK, "Got result %x, expected 0 (D3D_OK).\n", hr); + + hr = IDirect3DDevice9_GetTransform(device, D3DTS_WORLDMATRIX(1), &mat); + ok(hr == D3D_OK, "Got result %x, expected 0 (D3D_OK).\n", hr); + ok(!memcmp(mat.m, test_mat.m, sizeof(mat)), "World matrix not restored.\n"); + + hr = IDirect3DDevice9_GetLightEnable(device, 2, &bval); + ok(hr == D3D_OK, "Got result %x, expected 0 (D3D_OK).\n", hr); + if (hr == D3D_OK) + ok(!bval, "Got result %u, expected 0.\n", bval); + + /* State is not restored if effect is released without End call */ + hr = IDirect3DDevice9_SetRenderState(device, D3DRS_BLENDOP, 1); + ok(hr == D3D_OK, "Got result %x, expected 0 (D3D_OK).\n", hr); + + hr = effect->lpVtbl->Begin(effect, &npasses, 0); + ok(hr == D3D_OK, "Got result %x, expected 0 (D3D_OK).\n", hr); + + hr = IDirect3DDevice9_SetRenderState(device, D3DRS_BLENDOP, 3); + ok(hr == D3D_OK, "Got result %x, expected 0 (D3D_OK).\n", hr); + + effect->lpVtbl->Release(effect); + + hr = IDirect3DDevice9_GetRenderState(device, D3DRS_BLENDOP, &value); + ok(hr == D3D_OK, "Got result %x, expected 0 (D3D_OK).\n", hr); + ok(value == 3, "Got result %u, expected %u.\n", value, 1); +} + +/* + * fxc.exe /Tfx_2_0 + */ +#if 0 +float4 g_Pos1; +float4 g_Pos2; +float4 g_Selector[3] = {{0, 0, 0, 0}, {10, 10, 10, 10}, {5001, 5002, 5003, 5004}}; + +float4 opvect1 = {0.0, -0.0, -2.2, 3.402823466e+38F}; +float4 opvect2 = {1.0, 2.0, -3.0, 4.0}; +float4 opvect3 = {0.0, -0.0, -2.2, 3.402823466e+38F}; + +float4 vect_sampler = {1, 2, 3, 4}; + +float3 vec3 = {1001, 1002, 1003}; + +int4 g_iVect = {4, 3, 2, 1}; + +vertexshader vs_arr[3] = +{ + asm + { + vs_1_0 + def c0, 1, 1, 1, 1 + mov oPos, c0 + }, + asm + { + vs_1_1 + def c0, 2, 2, 2, 2 + mov oPos, c0 + }, + asm + { + vs_2_0 + def c0, 3, 3, 3, 3 + mov oPos, c0 + } +}; + +float4x4 m4x4 = {{11, 12, 13, 14}, {21, 22, 23, 24}, {31, 32, 33, 34}, {41, 42, 43, 44}}; + +row_major float4x3 m4x3row = {{11, 12, 13}, {21, 22, 23}, {31, 32, 33}, {41, 42, 43}}; +row_major float3x4 m3x4row = {{11, 12, 13, 14}, {21, 22, 23, 24}, {31, 32, 33, 34}}; +column_major float4x3 m4x3column = {{11, 12, 13},{21, 22, 23},{31, 32, 33},{41, 42, 43}}; +column_major float3x4 m3x4column = {{11, 12, 13, 14}, {21, 22, 23, 24}, {31, 32, 33, 34}}; +row_major float2x2 m2x2row = {{11, 12}, {21, 22}}; +column_major float2x2 m2x2column = {{11, 12}, {21, 22}}; +row_major float2x3 m2x3row = {{11, 12, 13}, {21, 22, 23}}; +column_major float2x3 m2x3column = {{11, 12, 13}, {21, 22, 23}}; +row_major float3x2 m3x2row = {{11, 12}, {21, 22}, {31, 32}}; +column_major float3x2 m3x2column = {{11, 12}, {21, 22}, {31, 32}}; + +row_major bool2x3 mb2x3row = {{true, false, true}, {false, true, true}}; +column_major bool2x3 mb2x3column = {{true, false, true}, {false, true, true}}; + +struct test_struct +{ + float3 v1; + float fv; + float4 v2; +}; + +struct struct_array +{ + test_struct ts[2]; +}; + +test_struct ts1[1] = {{{9, 10, 11}, 12, {13, 14, 15, 16}}}; +shared test_struct ts2[2] = {{{0, 0, 0}, 0, {0, 0, 0, 0}}, {{1, 2, 3}, 4, {5, 6, 7, 8}}}; +struct_array ts3 = {{{1, 2, 3}, 4, {5, 6, 7, 8}}, {{9, 10, 11}, 12, {13, 14, 15, 16}}}; + +float arr1[1] = {91}; +shared float arr2[2] = {92, 93}; + +Texture2D tex1; +Texture2D tex2; +sampler sampler1 = +sampler_state +{ + Texture = tex1; + MinFilter = g_iVect.y; + MagFilter = vect_sampler.x + vect_sampler.y; +}; + +sampler samplers_array[2] = +{ + sampler_state + { + MinFilter = 1; + MagFilter = vect_sampler.x; + }, + sampler_state + { + MinFilter = 2; + MagFilter = vect_sampler.y; + } +}; + +struct VS_OUTPUT +{ + float4 Position : POSITION; + float2 TextureUV : TEXCOORD0; + float4 Diffuse : COLOR0; +}; +VS_OUTPUT RenderSceneVS(float4 vPos : POSITION, + float3 vNormal : NORMAL, + float2 vTexCoord0 : TEXCOORD0, + uniform int nNumLights, + uniform bool bTexture) +{ + VS_OUTPUT Output; + + if (g_Selector[1].y > float4(0.5, 0.5, 0.5, 0.5).y) + Output.Position = -g_Pos1 * 2 - float4(-4, -5, -6, -7); + else + Output.Position = -g_Pos2 * 3 - float4(-4, -5, -6, -7); + Output.TextureUV = float2(0, 0); + Output.Diffuse = 0; + Output.Diffuse.xyz = mul(vPos, m4x3column); + Output.Diffuse += mul(vPos, m3x4column); + Output.Diffuse += mul(vPos, m3x4row); + Output.Diffuse.xyz += mul(vPos, m4x3row); + Output.Diffuse += mul(vPos, ts1[0].fv); + Output.Diffuse += mul(vPos, ts1[0].v2); + Output.Diffuse += mul(vPos, ts2[1].fv); + Output.Diffuse += mul(vPos, ts2[1].v2); + Output.Diffuse += mul(vPos, arr1[0]); + Output.Diffuse += mul(vPos, arr2[1]); + Output.Diffuse += mul(vPos, ts3.ts[1].fv); + Output.Diffuse += mul(vPos, ts3.ts[1].v2); + Output.Diffuse += tex2Dlod(sampler1, g_Pos1); + Output.Diffuse += tex2Dlod(samplers_array[1], g_Pos1); + return Output; +} + +VS_OUTPUT RenderSceneVS2(float4 vPos : POSITION) +{ + VS_OUTPUT Output; + + Output.Position = g_Pos1; + Output.TextureUV = float2(0, 0); + Output.Diffuse = 0; + return Output; +} + +struct PS_OUTPUT +{ + float4 RGBColor : COLOR0; /* Pixel color */ +}; +PS_OUTPUT RenderScenePS( VS_OUTPUT In, uniform bool2x3 mb) +{ + PS_OUTPUT Output; + int i; + + Output.RGBColor = In.Diffuse; + Output.RGBColor.xy += mul(In.Diffuse, m2x2row); + Output.RGBColor.xy += mul(In.Diffuse, m2x2column); + Output.RGBColor.xy += mul(In.Diffuse, m3x2row); + Output.RGBColor.xy += mul(In.Diffuse, m3x2column); + Output.RGBColor.xyz += mul(In.Diffuse, m2x3row); + Output.RGBColor.xyz += mul(In.Diffuse, m2x3column); + for (i = 0; i < g_iVect.x; ++i) + Output.RGBColor.xyz += mul(In.Diffuse, m2x3column); + if (mb[1][1]) + { + Output.RGBColor += sin(Output.RGBColor); + Output.RGBColor += cos(Output.RGBColor); + Output.RGBColor.xyz += mul(Output.RGBColor, m2x3column); + Output.RGBColor.xyz += mul(Output.RGBColor, m2x3row); + Output.RGBColor.xy += mul(Output.RGBColor, m3x2column); + Output.RGBColor.xy += mul(Output.RGBColor, m3x2row); + } + if (mb2x3column[0][0]) + { + Output.RGBColor += sin(Output.RGBColor); + Output.RGBColor += cos(Output.RGBColor); + Output.RGBColor.xyz += mul(Output.RGBColor, m2x3column); + Output.RGBColor.xyz += mul(Output.RGBColor, m2x3row); + Output.RGBColor.xy += mul(Output.RGBColor, m3x2column); + Output.RGBColor.xy += mul(Output.RGBColor, m3x2row); + } + Output.RGBColor += tex2D(sampler1, In.TextureUV); + Output.RGBColor += tex2D(samplers_array[0], In.TextureUV); + return Output; +} + +shared vertexshader vs_arr2[2] = {compile vs_3_0 RenderSceneVS(1, true), compile vs_3_0 RenderSceneVS2()}; +pixelshader ps_arr[1] = {compile ps_3_0 RenderScenePS(mb2x3row)}; + +technique tech0 +{ + pass p0 + { + VertexShader = vs_arr2[g_iVect.w - 1]; + PixelShader = ps_arr[g_iVect.w - 1]; + + LightEnable[0] = TRUE; + LightEnable[1] = TRUE; + LightEnable[2] = TRUE; + LightEnable[3] = TRUE; + LightEnable[4] = TRUE; + LightEnable[5] = TRUE; + LightEnable[6] = TRUE; + LightEnable[7] = TRUE; + LightType[0] = POINT; + LightType[1] = POINT; + LightType[2] = POINT; + LightType[3] = POINT; + LightType[4] = POINT; + LightType[5] = POINT; + LightType[6] = POINT; + LightType[7] = POINT; + LightDiffuse[0] = 1 / opvect1; + LightDiffuse[1] = rsqrt(opvect1); + LightDiffuse[2] = opvect1 * opvect2; + LightDiffuse[3] = opvect1 + opvect2; + LightDiffuse[4] = float4(opvect1 < opvect2); + LightDiffuse[5] = float4(opvect1 >= opvect2); + LightDiffuse[6] = -opvect1; + LightDiffuse[7] = rcp(opvect1); + + LightAmbient[0] = frac(opvect1); + LightAmbient[1] = min(opvect1, opvect2); + LightAmbient[2] = max(opvect1, opvect2); + LightAmbient[3] = sin(opvect1); + LightAmbient[4] = cos(opvect1); + LightAmbient[5] = 1e-2 / opvect1; + LightAmbient[6] = float4(0, dot(opvect1, opvect2), dot(opvect2, opvect2), 0); + LightAmbient[7] = opvect1 + 1e-12 * opvect2 - opvect3; + + LightSpecular[0] = float4(dot(opvect1.zx, opvect2.xy), dot(opvect1.zzx, opvect2.xyz), + dot(opvect1.zzzx, opvect2.xxyy), 0); + LightSpecular[1] = float4(opvect1[g_iVect.z], g_iVect[opvect2.y + 1], + g_Selector[4 + g_iVect.w].x + g_Selector[7 + g_iVect.w].y, + g_Selector[g_iVect.w].x + g_Selector[g_iVect.x].y); + LightSpecular[2] = float4(dot(m4x4[3 + g_iVect.z], m4x4[g_iVect.w * 2]), ts3.ts[g_iVect.x].fv, + vec3[g_iVect.z], float3(1, 2, 3)[g_iVect.w]); + + FogEnable = TRUE; + FogDensity = ts2[0].fv; + FogStart = ts2[1].fv; + PointScale_A = ts3.ts[0].fv; + PointScale_B = ts3.ts[1].fv; + } + pass p1 + { + VertexShader = vs_arr[g_iVect.z]; + } +} +#endif +static const DWORD test_effect_preshader_effect_blob[] = +{ + 0xfeff0901, 0x00001160, 0x00000000, 0x00000003, 0x00000001, 0x00000030, 0x00000000, 0x00000000, + 0x00000004, 0x00000001, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000007, 0x6f505f67, + 0x00003173, 0x00000003, 0x00000001, 0x00000068, 0x00000000, 0x00000000, 0x00000004, 0x00000001, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000007, 0x6f505f67, 0x00003273, 0x00000003, + 0x00000001, 0x000000c0, 0x00000000, 0x00000003, 0x00000004, 0x00000001, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x41200000, 0x41200000, 0x41200000, 0x41200000, 0x459c4800, 0x459c5000, + 0x459c5800, 0x459c6000, 0x0000000b, 0x65535f67, 0x7463656c, 0x0000726f, 0x00000003, 0x00000001, + 0x000000fc, 0x00000000, 0x00000000, 0x00000004, 0x00000001, 0x00000000, 0x80000000, 0xc00ccccd, + 0x7f7fffff, 0x00000008, 0x6576706f, 0x00317463, 0x00000003, 0x00000001, 0x00000134, 0x00000000, + 0x00000000, 0x00000004, 0x00000001, 0x3f800000, 0x40000000, 0xc0400000, 0x40800000, 0x00000008, + 0x6576706f, 0x00327463, 0x00000003, 0x00000001, 0x0000016c, 0x00000000, 0x00000000, 0x00000004, + 0x00000001, 0x00000000, 0x80000000, 0xc00ccccd, 0x7f7fffff, 0x00000008, 0x6576706f, 0x00337463, + 0x00000003, 0x00000001, 0x000001a4, 0x00000000, 0x00000000, 0x00000004, 0x00000001, 0x3f800000, + 0x40000000, 0x40400000, 0x40800000, 0x0000000d, 0x74636576, 0x6d61735f, 0x72656c70, 0x00000000, + 0x00000003, 0x00000001, 0x000001e0, 0x00000000, 0x00000000, 0x00000003, 0x00000001, 0x447a4000, + 0x447a8000, 0x447ac000, 0x00000005, 0x33636576, 0x00000000, 0x00000002, 0x00000001, 0x00000218, + 0x00000000, 0x00000000, 0x00000004, 0x00000001, 0x00000004, 0x00000003, 0x00000002, 0x00000001, + 0x00000008, 0x56695f67, 0x00746365, 0x00000010, 0x00000004, 0x00000244, 0x00000000, 0x00000003, + 0x00000001, 0x00000002, 0x00000003, 0x00000007, 0x615f7376, 0x00007272, 0x00000003, 0x00000002, + 0x000002ac, 0x00000000, 0x00000000, 0x00000004, 0x00000004, 0x41300000, 0x41400000, 0x41500000, + 0x41600000, 0x41a80000, 0x41b00000, 0x41b80000, 0x41c00000, 0x41f80000, 0x42000000, 0x42040000, + 0x42080000, 0x42240000, 0x42280000, 0x422c0000, 0x42300000, 0x00000005, 0x3478346d, 0x00000000, + 0x00000003, 0x00000002, 0x00000304, 0x00000000, 0x00000000, 0x00000004, 0x00000003, 0x41300000, + 0x41400000, 0x41500000, 0x41a80000, 0x41b00000, 0x41b80000, 0x41f80000, 0x42000000, 0x42040000, + 0x42240000, 0x42280000, 0x422c0000, 0x00000008, 0x3378346d, 0x00776f72, 0x00000003, 0x00000002, + 0x0000035c, 0x00000000, 0x00000000, 0x00000003, 0x00000004, 0x41300000, 0x41400000, 0x41500000, + 0x41600000, 0x41a80000, 0x41b00000, 0x41b80000, 0x41c00000, 0x41f80000, 0x42000000, 0x42040000, + 0x42080000, 0x00000008, 0x3478336d, 0x00776f72, 0x00000003, 0x00000002, 0x000003b4, 0x00000000, + 0x00000000, 0x00000004, 0x00000003, 0x41300000, 0x41400000, 0x41500000, 0x41a80000, 0x41b00000, + 0x41b80000, 0x41f80000, 0x42000000, 0x42040000, 0x42240000, 0x42280000, 0x422c0000, 0x0000000b, + 0x3378346d, 0x756c6f63, 0x00006e6d, 0x00000003, 0x00000002, 0x00000410, 0x00000000, 0x00000000, + 0x00000003, 0x00000004, 0x41300000, 0x41400000, 0x41500000, 0x41600000, 0x41a80000, 0x41b00000, + 0x41b80000, 0x41c00000, 0x41f80000, 0x42000000, 0x42040000, 0x42080000, 0x0000000b, 0x3478336d, + 0x756c6f63, 0x00006e6d, 0x00000003, 0x00000002, 0x0000044c, 0x00000000, 0x00000000, 0x00000002, + 0x00000002, 0x41300000, 0x41400000, 0x41a80000, 0x41b00000, 0x00000008, 0x3278326d, 0x00776f72, + 0x00000003, 0x00000002, 0x00000484, 0x00000000, 0x00000000, 0x00000002, 0x00000002, 0x41300000, + 0x41400000, 0x41a80000, 0x41b00000, 0x0000000b, 0x3278326d, 0x756c6f63, 0x00006e6d, 0x00000003, + 0x00000002, 0x000004c8, 0x00000000, 0x00000000, 0x00000002, 0x00000003, 0x41300000, 0x41400000, + 0x41500000, 0x41a80000, 0x41b00000, 0x41b80000, 0x00000008, 0x3378326d, 0x00776f72, 0x00000003, + 0x00000002, 0x00000508, 0x00000000, 0x00000000, 0x00000002, 0x00000003, 0x41300000, 0x41400000, + 0x41500000, 0x41a80000, 0x41b00000, 0x41b80000, 0x0000000b, 0x3378326d, 0x756c6f63, 0x00006e6d, + 0x00000003, 0x00000002, 0x0000054c, 0x00000000, 0x00000000, 0x00000003, 0x00000002, 0x41300000, + 0x41400000, 0x41a80000, 0x41b00000, 0x41f80000, 0x42000000, 0x00000008, 0x3278336d, 0x00776f72, + 0x00000003, 0x00000002, 0x0000058c, 0x00000000, 0x00000000, 0x00000003, 0x00000002, 0x41300000, + 0x41400000, 0x41a80000, 0x41b00000, 0x41f80000, 0x42000000, 0x0000000b, 0x3278336d, 0x756c6f63, + 0x00006e6d, 0x00000001, 0x00000002, 0x000005d0, 0x00000000, 0x00000000, 0x00000002, 0x00000003, + 0x00000001, 0x00000000, 0x00000001, 0x00000000, 0x00000001, 0x00000001, 0x00000009, 0x7832626d, + 0x776f7233, 0x00000000, 0x00000001, 0x00000002, 0x00000614, 0x00000000, 0x00000000, 0x00000002, + 0x00000003, 0x00000001, 0x00000000, 0x00000001, 0x00000000, 0x00000001, 0x00000001, 0x0000000c, + 0x7832626d, 0x6c6f6333, 0x006e6d75, 0x00000000, 0x00000005, 0x000006b0, 0x00000000, 0x00000001, + 0x00000003, 0x00000003, 0x00000001, 0x000006b8, 0x00000000, 0x00000000, 0x00000003, 0x00000001, + 0x00000003, 0x00000000, 0x000006c0, 0x00000000, 0x00000000, 0x00000001, 0x00000001, 0x00000003, + 0x00000001, 0x000006c8, 0x00000000, 0x00000000, 0x00000004, 0x00000001, 0x41100000, 0x41200000, + 0x41300000, 0x41400000, 0x41500000, 0x41600000, 0x41700000, 0x41800000, 0x00000004, 0x00317374, + 0x00000003, 0x00003176, 0x00000003, 0x00007666, 0x00000003, 0x00003276, 0x00000000, 0x00000005, + 0x0000077c, 0x00000000, 0x00000002, 0x00000003, 0x00000003, 0x00000001, 0x00000784, 0x00000000, + 0x00000000, 0x00000003, 0x00000001, 0x00000003, 0x00000000, 0x0000078c, 0x00000000, 0x00000000, + 0x00000001, 0x00000001, 0x00000003, 0x00000001, 0x00000794, 0x00000000, 0x00000000, 0x00000004, + 0x00000001, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x3f800000, 0x40000000, 0x40400000, 0x40800000, 0x40a00000, 0x40c00000, 0x40e00000, + 0x41000000, 0x00000004, 0x00327374, 0x00000003, 0x00003176, 0x00000003, 0x00007666, 0x00000003, + 0x00003276, 0x00000000, 0x00000005, 0x00000860, 0x00000000, 0x00000000, 0x00000001, 0x00000000, + 0x00000005, 0x00000868, 0x00000000, 0x00000002, 0x00000003, 0x00000003, 0x00000001, 0x00000870, + 0x00000000, 0x00000000, 0x00000003, 0x00000001, 0x00000003, 0x00000000, 0x00000878, 0x00000000, + 0x00000000, 0x00000001, 0x00000001, 0x00000003, 0x00000001, 0x00000880, 0x00000000, 0x00000000, + 0x00000004, 0x00000001, 0x3f800000, 0x40000000, 0x40400000, 0x40800000, 0x40a00000, 0x40c00000, + 0x40e00000, 0x41000000, 0x41100000, 0x41200000, 0x41300000, 0x41400000, 0x41500000, 0x41600000, + 0x41700000, 0x41800000, 0x00000004, 0x00337374, 0x00000003, 0x00007374, 0x00000003, 0x00003176, + 0x00000003, 0x00007666, 0x00000003, 0x00003276, 0x00000003, 0x00000000, 0x000008a8, 0x00000000, + 0x00000001, 0x00000001, 0x00000001, 0x42b60000, 0x00000005, 0x31727261, 0x00000000, 0x00000003, + 0x00000000, 0x000008d8, 0x00000000, 0x00000002, 0x00000001, 0x00000001, 0x42b80000, 0x42ba0000, + 0x00000005, 0x32727261, 0x00000000, 0x00000007, 0x00000004, 0x000008fc, 0x00000000, 0x00000000, + 0x00000004, 0x00000005, 0x31786574, 0x00000000, 0x00000007, 0x00000004, 0x00000920, 0x00000000, + 0x00000000, 0x00000005, 0x00000005, 0x32786574, 0x00000000, 0x0000000a, 0x00000004, 0x000009cc, + 0x00000000, 0x00000000, 0x00000006, 0x00000007, 0x00000004, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000002, 0x00000002, 0x00000000, 0x00000000, 0x00000000, 0x00000001, 0x00000001, + 0x00000000, 0x00000003, 0x00000002, 0x00000000, 0x00000000, 0x00000000, 0x00000001, 0x00000001, + 0x00000003, 0x000000a4, 0x00000100, 0x00000944, 0x00000940, 0x000000aa, 0x00000100, 0x0000095c, + 0x00000958, 0x000000a9, 0x00000100, 0x0000097c, 0x00000978, 0x00000009, 0x706d6173, 0x3172656c, + 0x00000000, 0x0000000a, 0x00000004, 0x00000ab8, 0x00000000, 0x00000002, 0x00000001, 0x00000002, + 0x00000002, 0x00000000, 0x00000000, 0x00000000, 0x00000001, 0x00000001, 0x00000000, 0x00000003, + 0x00000002, 0x00000000, 0x00000000, 0x00000000, 0x00000001, 0x00000001, 0x00000002, 0x00000002, + 0x00000002, 0x00000000, 0x00000000, 0x00000000, 0x00000001, 0x00000001, 0x00000000, 0x00000003, + 0x00000002, 0x00000000, 0x00000000, 0x00000000, 0x00000001, 0x00000001, 0x00000002, 0x000000aa, + 0x00000100, 0x000009f4, 0x000009f0, 0x000000a9, 0x00000100, 0x00000a14, 0x00000a10, 0x00000002, + 0x000000aa, 0x00000100, 0x00000a34, 0x00000a30, 0x000000a9, 0x00000100, 0x00000a54, 0x00000a50, + 0x0000000f, 0x706d6173, 0x7372656c, 0x7272615f, 0x00007961, 0x00000010, 0x00000004, 0x00000ae8, + 0x00000000, 0x00000002, 0x00000007, 0x00000008, 0x00000008, 0x615f7376, 0x00327272, 0x0000000f, + 0x00000004, 0x00000b0c, 0x00000000, 0x00000001, 0x00000009, 0x00000007, 0x615f7370, 0x00007272, + 0x0000000a, 0x00000010, 0x00000004, 0x00000000, 0x00000000, 0x00000000, 0x0000000b, 0x0000000f, + 0x00000004, 0x00000000, 0x00000000, 0x00000000, 0x00000001, 0x00000002, 0x00000002, 0x00000000, + 0x00000000, 0x00000000, 0x00000001, 0x00000001, 0x00000001, 0x00000002, 0x00000002, 0x00000000, + 0x00000000, 0x00000000, 0x00000001, 0x00000001, 0x00000001, 0x00000002, 0x00000002, 0x00000000, + 0x00000000, 0x00000000, 0x00000001, 0x00000001, 0x00000001, 0x00000002, 0x00000002, 0x00000000, + 0x00000000, 0x00000000, 0x00000001, 0x00000001, 0x00000001, 0x00000002, 0x00000002, 0x00000000, + 0x00000000, 0x00000000, 0x00000001, 0x00000001, 0x00000001, 0x00000002, 0x00000002, 0x00000000, + 0x00000000, 0x00000000, 0x00000001, 0x00000001, 0x00000001, 0x00000002, 0x00000002, 0x00000000, + 0x00000000, 0x00000000, 0x00000001, 0x00000001, 0x00000001, 0x00000002, 0x00000002, 0x00000000, + 0x00000000, 0x00000000, 0x00000001, 0x00000001, 0x00000001, 0x00000002, 0x00000002, 0x00000000, + 0x00000000, 0x00000000, 0x00000001, 0x00000001, 0x00000001, 0x00000002, 0x00000002, 0x00000000, + 0x00000000, 0x00000000, 0x00000001, 0x00000001, 0x00000001, 0x00000002, 0x00000002, 0x00000000, + 0x00000000, 0x00000000, 0x00000001, 0x00000001, 0x00000001, 0x00000002, 0x00000002, 0x00000000, + 0x00000000, 0x00000000, 0x00000001, 0x00000001, 0x00000001, 0x00000002, 0x00000002, 0x00000000, + 0x00000000, 0x00000000, 0x00000001, 0x00000001, 0x00000001, 0x00000002, 0x00000002, 0x00000000, + 0x00000000, 0x00000000, 0x00000001, 0x00000001, 0x00000001, 0x00000002, 0x00000002, 0x00000000, + 0x00000000, 0x00000000, 0x00000001, 0x00000001, 0x00000001, 0x00000002, 0x00000002, 0x00000000, + 0x00000000, 0x00000000, 0x00000001, 0x00000001, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000003, 0x00000002, 0x00000000, 0x00000000, 0x00000000, 0x00000004, 0x00000001, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000003, 0x00000002, 0x00000000, 0x00000000, 0x00000000, + 0x00000004, 0x00000001, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000003, 0x00000002, + 0x00000000, 0x00000000, 0x00000000, 0x00000004, 0x00000001, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000003, 0x00000002, 0x00000000, 0x00000000, 0x00000000, 0x00000004, 0x00000001, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000003, 0x00000002, 0x00000000, 0x00000000, + 0x00000000, 0x00000004, 0x00000001, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000003, + 0x00000002, 0x00000000, 0x00000000, 0x00000000, 0x00000004, 0x00000001, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000003, 0x00000002, 0x00000000, 0x00000000, 0x00000000, 0x00000004, + 0x00000001, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000003, 0x00000002, 0x00000000, + 0x00000000, 0x00000000, 0x00000004, 0x00000001, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000003, 0x00000002, 0x00000000, 0x00000000, 0x00000000, 0x00000004, 0x00000001, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000003, 0x00000002, 0x00000000, 0x00000000, 0x00000000, + 0x00000004, 0x00000001, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000003, 0x00000002, + 0x00000000, 0x00000000, 0x00000000, 0x00000004, 0x00000001, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000003, 0x00000002, 0x00000000, 0x00000000, 0x00000000, 0x00000004, 0x00000001, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000003, 0x00000002, 0x00000000, 0x00000000, + 0x00000000, 0x00000004, 0x00000001, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000003, + 0x00000002, 0x00000000, 0x00000000, 0x00000000, 0x00000004, 0x00000001, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000003, 0x00000002, 0x00000000, 0x00000000, 0x00000000, 0x00000004, + 0x00000001, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000003, 0x00000002, 0x00000000, + 0x00000000, 0x00000000, 0x00000004, 0x00000001, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000003, 0x00000002, 0x00000000, 0x00000000, 0x00000000, 0x00000004, 0x00000001, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000003, 0x00000002, 0x00000000, 0x00000000, 0x00000000, + 0x00000004, 0x00000001, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000003, 0x00000002, + 0x00000000, 0x00000000, 0x00000000, 0x00000004, 0x00000001, 0x00000001, 0x00000002, 0x00000002, + 0x00000000, 0x00000000, 0x00000000, 0x00000001, 0x00000001, 0x00000000, 0x00000003, 0x00000002, + 0x00000000, 0x00000000, 0x00000000, 0x00000001, 0x00000001, 0x00000000, 0x00000003, 0x00000002, + 0x00000000, 0x00000000, 0x00000000, 0x00000001, 0x00000001, 0x00000000, 0x00000003, 0x00000002, + 0x00000000, 0x00000000, 0x00000000, 0x00000001, 0x00000001, 0x00000000, 0x00000003, 0x00000002, + 0x00000000, 0x00000000, 0x00000000, 0x00000001, 0x00000001, 0x00000003, 0x00003070, 0x0000000c, + 0x00000010, 0x00000004, 0x00000000, 0x00000000, 0x00000000, 0x00000003, 0x00003170, 0x00000006, + 0x68636574, 0x00000030, 0x00000022, 0x00000001, 0x0000000e, 0x0000000d, 0x00000004, 0x00000020, + 0x00000000, 0x00000000, 0x0000003c, 0x00000058, 0x00000000, 0x00000000, 0x00000074, 0x00000090, + 0x00000000, 0x00000000, 0x000000d0, 0x000000ec, 0x00000000, 0x00000000, 0x00000108, 0x00000124, + 0x00000000, 0x00000000, 0x00000140, 0x0000015c, 0x00000000, 0x00000000, 0x00000178, 0x00000194, + 0x00000000, 0x00000000, 0x000001b8, 0x000001d4, 0x00000000, 0x00000000, 0x000001ec, 0x00000208, + 0x00000000, 0x00000000, 0x00000224, 0x00000238, 0x00000000, 0x00000000, 0x00000250, 0x0000026c, + 0x00000000, 0x00000000, 0x000002b8, 0x000002d4, 0x00000000, 0x00000000, 0x00000310, 0x0000032c, + 0x00000000, 0x00000000, 0x00000368, 0x00000384, 0x00000000, 0x00000000, 0x000003c4, 0x000003e0, + 0x00000000, 0x00000000, 0x00000420, 0x0000043c, 0x00000000, 0x00000000, 0x00000458, 0x00000474, + 0x00000000, 0x00000000, 0x00000494, 0x000004b0, 0x00000000, 0x00000000, 0x000004d4, 0x000004f0, + 0x00000000, 0x00000000, 0x00000518, 0x00000534, 0x00000000, 0x00000000, 0x00000558, 0x00000574, + 0x00000000, 0x00000000, 0x0000059c, 0x000005b8, 0x00000000, 0x00000000, 0x000005e0, 0x000005fc, + 0x00000000, 0x00000000, 0x00000624, 0x00000690, 0x00000000, 0x00000000, 0x000006d0, 0x0000073c, + 0x00000001, 0x00000000, 0x0000079c, 0x00000820, 0x00000000, 0x00000000, 0x00000888, 0x000008a4, + 0x00000000, 0x00000000, 0x000008b4, 0x000008d0, 0x00000001, 0x00000000, 0x000008e4, 0x000008f8, + 0x00000000, 0x00000000, 0x00000908, 0x0000091c, 0x00000000, 0x00000000, 0x0000092c, 0x00000998, + 0x00000000, 0x00000000, 0x000009dc, 0x00000a70, 0x00000000, 0x00000000, 0x00000acc, 0x00000ae0, + 0x00000001, 0x00000000, 0x00000af4, 0x00000b08, 0x00000000, 0x00000000, 0x00001154, 0x00000000, + 0x00000002, 0x0000112c, 0x00000000, 0x0000002a, 0x00000092, 0x00000000, 0x00000b1c, 0x00000b18, + 0x00000093, 0x00000000, 0x00000b34, 0x00000b30, 0x00000091, 0x00000000, 0x00000b4c, 0x00000b48, + 0x00000091, 0x00000001, 0x00000b6c, 0x00000b68, 0x00000091, 0x00000002, 0x00000b8c, 0x00000b88, + 0x00000091, 0x00000003, 0x00000bac, 0x00000ba8, 0x00000091, 0x00000004, 0x00000bcc, 0x00000bc8, + 0x00000091, 0x00000005, 0x00000bec, 0x00000be8, 0x00000091, 0x00000006, 0x00000c0c, 0x00000c08, + 0x00000091, 0x00000007, 0x00000c2c, 0x00000c28, 0x00000084, 0x00000000, 0x00000c4c, 0x00000c48, + 0x00000084, 0x00000001, 0x00000c6c, 0x00000c68, 0x00000084, 0x00000002, 0x00000c8c, 0x00000c88, + 0x00000084, 0x00000003, 0x00000cac, 0x00000ca8, 0x00000084, 0x00000004, 0x00000ccc, 0x00000cc8, + 0x00000084, 0x00000005, 0x00000cec, 0x00000ce8, 0x00000084, 0x00000006, 0x00000d0c, 0x00000d08, + 0x00000084, 0x00000007, 0x00000d2c, 0x00000d28, 0x00000085, 0x00000000, 0x00000d58, 0x00000d48, + 0x00000085, 0x00000001, 0x00000d84, 0x00000d74, 0x00000085, 0x00000002, 0x00000db0, 0x00000da0, + 0x00000085, 0x00000003, 0x00000ddc, 0x00000dcc, 0x00000085, 0x00000004, 0x00000e08, 0x00000df8, + 0x00000085, 0x00000005, 0x00000e34, 0x00000e24, 0x00000085, 0x00000006, 0x00000e60, 0x00000e50, + 0x00000085, 0x00000007, 0x00000e8c, 0x00000e7c, 0x00000087, 0x00000000, 0x00000eb8, 0x00000ea8, + 0x00000087, 0x00000001, 0x00000ee4, 0x00000ed4, 0x00000087, 0x00000002, 0x00000f10, 0x00000f00, + 0x00000087, 0x00000003, 0x00000f3c, 0x00000f2c, 0x00000087, 0x00000004, 0x00000f68, 0x00000f58, + 0x00000087, 0x00000005, 0x00000f94, 0x00000f84, 0x00000087, 0x00000006, 0x00000fc0, 0x00000fb0, + 0x00000087, 0x00000007, 0x00000fec, 0x00000fdc, 0x00000086, 0x00000000, 0x00001018, 0x00001008, + 0x00000086, 0x00000001, 0x00001044, 0x00001034, 0x00000086, 0x00000002, 0x00001070, 0x00001060, + 0x0000000e, 0x00000000, 0x00001090, 0x0000108c, 0x00000014, 0x00000000, 0x000010b0, 0x000010ac, + 0x00000012, 0x00000000, 0x000010d0, 0x000010cc, 0x00000041, 0x00000000, 0x000010f0, 0x000010ec, + 0x00000042, 0x00000000, 0x00001110, 0x0000110c, 0x0000114c, 0x00000000, 0x00000001, 0x00000092, + 0x00000000, 0x00001138, 0x00001134, 0x00000008, 0x0000001f, 0x00000009, 0x00000ad0, 0xffff0300, + 0x00d9fffe, 0x42415443, 0x0000001c, 0x0000032f, 0xffff0300, 0x0000000b, 0x0000001c, 0x00000000, + 0x00000328, 0x000000f8, 0x00000001, 0x00000001, 0x00000100, 0x00000110, 0x00000120, 0x00080002, + 0x00000002, 0x0000012c, 0x0000013c, 0x0000015c, 0x00060002, 0x00000002, 0x00000164, 0x00000174, + 0x00000194, 0x00000002, 0x00000003, 0x000001a0, 0x000001b0, 0x000001e0, 0x000a0002, 0x00000002, + 0x000001e8, 0x000001f8, 0x00000218, 0x000c0002, 0x00000002, 0x00000224, 0x00000234, 0x00000254, + 0x00030002, 0x00000003, 0x0000025c, 0x0000026c, 0x0000029c, 0x00050000, 0x00000001, 0x000002a8, + 0x000002b8, 0x000002d0, 0x00000000, 0x00000005, 0x000002dc, 0x000002b8, 0x000002ec, 0x00000003, + 0x00000001, 0x000002f8, 0x00000000, 0x00000308, 0x00010003, 0x00000001, 0x00000318, 0x00000000, + 0x56695f67, 0x00746365, 0x00020001, 0x00040001, 0x00000001, 0x00000000, 0x00000004, 0x00000003, + 0x00000002, 0x00000001, 0x3278326d, 0x756c6f63, 0xab006e6d, 0x00030003, 0x00020002, 0x00000001, + 0x00000000, 0x41300000, 0x41a80000, 0x00000000, 0x00000000, 0x41400000, 0x41b00000, 0x00000000, + 0x00000000, 0x3278326d, 0x00776f72, 0x00030002, 0x00020002, 0x00000001, 0x00000000, 0x41300000, + 0x41400000, 0x00000000, 0x00000000, 0x41a80000, 0x41b00000, 0x00000000, 0x00000000, 0x3378326d, + 0x756c6f63, 0xab006e6d, 0x00030003, 0x00030002, 0x00000001, 0x00000000, 0x41300000, 0x41a80000, + 0x00000000, 0x00000000, 0x41400000, 0x41b00000, 0x00000000, 0x00000000, 0x41500000, 0x41b80000, + 0x00000000, 0x00000000, 0x3378326d, 0x00776f72, 0x00030002, 0x00030002, 0x00000001, 0x00000000, + 0x41300000, 0x41400000, 0x41500000, 0x00000000, 0x41a80000, 0x41b00000, 0x41b80000, 0x00000000, + 0x3278336d, 0x756c6f63, 0xab006e6d, 0x00030003, 0x00020003, 0x00000001, 0x00000000, 0x41300000, + 0x41a80000, 0x41f80000, 0x00000000, 0x41400000, 0x41b00000, 0x42000000, 0x00000000, 0x3278336d, + 0x00776f72, 0x00030002, 0x00020003, 0x00000001, 0x00000000, 0x41300000, 0x41400000, 0x00000000, + 0x00000000, 0x41a80000, 0x41b00000, 0x00000000, 0x00000000, 0x41f80000, 0x42000000, 0x00000000, + 0x00000000, 0x7832626d, 0x6c6f6333, 0x006e6d75, 0x00010003, 0x00030002, 0x00000001, 0x00000000, + 0xffffffff, 0x00000000, 0xffffffff, 0x00000000, 0xffffffff, 0xffffffff, 0x7832626d, 0x776f7233, + 0xababab00, 0x00010002, 0x00030002, 0x00000001, 0x00000000, 0x706d6173, 0x3172656c, 0xababab00, + 0x000c0004, 0x00010001, 0x00000001, 0x00000000, 0x706d6173, 0x7372656c, 0x7272615f, 0xab007961, + 0x000c0004, 0x00010001, 0x00000002, 0x00000000, 0x335f7370, 0x4d00305f, 0x6f726369, 0x74666f73, + 0x29522820, 0x534c4820, 0x6853204c, 0x72656461, 0x6d6f4320, 0x656c6970, 0x2e392072, 0x392e3932, + 0x332e3235, 0x00313131, 0x05000051, 0xa00f000e, 0x3d2aaaa4, 0xbf000000, 0x3f800000, 0xbe22f983, + 0x05000051, 0xa00f000f, 0x40c90fdb, 0xc0490fdb, 0xb4878163, 0x37cfb5a1, 0x05000051, 0xa00f0010, + 0x00000000, 0x3e22f983, 0x3e800000, 0xbab609ba, 0x0200001f, 0x80000005, 0x90030000, 0x0200001f, + 0x8000000a, 0x900f0001, 0x0200001f, 0x90000000, 0xa00f0800, 0x0200001f, 0x90000000, 0xa00f0801, + 0x03000005, 0x80030000, 0xa0e40007, 0x90550001, 0x04000004, 0x80030000, 0x90000001, 0xa0e40006, + 0x80e40000, 0x03000002, 0x80030000, 0x80e40000, 0x90e40001, 0x02000001, 0x80010001, 0xa0000010, + 0x0400005a, 0x80010002, 0x90e40001, 0xa0e40008, 0x80000001, 0x0400005a, 0x80020002, 0x90e40001, + 0xa0e40009, 0x80000001, 0x03000002, 0x80030000, 0x80e40000, 0x80e40002, 0x03000005, 0x800c0000, + 0xa0440004, 0x90550001, 0x04000004, 0x800c0000, 0x90000001, 0xa0440003, 0x80e40000, 0x04000004, + 0x800c0000, 0x90aa0001, 0xa0440005, 0x80e40000, 0x03000002, 0x80030000, 0x80ee0000, 0x80e40000, + 0x03000008, 0x80010002, 0x90e40001, 0xa0e4000c, 0x03000008, 0x80020002, 0x90e40001, 0xa0e4000d, + 0x03000002, 0x80030000, 0x80e40000, 0x80e40002, 0x03000005, 0x800e0001, 0xa090000b, 0x90550001, + 0x04000004, 0x800e0001, 0x90000001, 0xa090000a, 0x80e40001, 0x02000001, 0x80040000, 0x90aa0001, + 0x03000002, 0x80070000, 0x80e40000, 0x80f90001, 0x0400005a, 0x80010002, 0x90e40001, 0xa0e40000, + 0x80000001, 0x0400005a, 0x80020002, 0x90e40001, 0xa0e40001, 0x80000001, 0x0400005a, 0x80040002, + 0x90e40001, 0xa0e40002, 0x80000001, 0x03000002, 0x80070000, 0x80e40000, 0x80e40002, 0x02000001, + 0x80070003, 0x80e40000, 0x01000026, 0xf0e40000, 0x03000002, 0x80070003, 0x80e40002, 0x80e40003, + 0x00000027, 0x01000028, 0xe0e40804, 0x02000001, 0x80080003, 0x90ff0001, 0x04000004, 0x800f0000, + 0x80e40003, 0xa0550010, 0xa0aa0010, 0x02000013, 0x800f0000, 0x80e40000, 0x04000004, 0x800f0000, + 0x80e40000, 0xa000000f, 0xa055000f, 0x03000005, 0x800f0000, 0x80e40000, 0x80e40000, 0x04000004, + 0x800f0002, 0x80e40000, 0xa0aa000f, 0xa0ff000f, 0x04000004, 0x800f0002, 0x80e40000, 0x80e40002, + 0xa0ff0010, 0x04000004, 0x800f0002, 0x80e40000, 0x80e40002, 0xa000000e, 0x04000004, 0x800f0002, + 0x80e40000, 0x80e40002, 0xa055000e, 0x04000004, 0x800f0000, 0x80e40000, 0x80e40002, 0x80e40003, + 0x03000002, 0x800f0000, 0x80e40000, 0xa0aa000e, 0x04000004, 0x800f0002, 0x80e40000, 0xa1ff000e, + 0xa155000e, 0x02000013, 0x800f0002, 0x80e40002, 0x04000004, 0x800f0002, 0x80e40002, 0xa000000f, + 0xa055000f, 0x03000005, 0x800f0002, 0x80e40002, 0x80e40002, 0x04000004, 0x800f0004, 0x80e40002, + 0xa0aa000f, 0xa0ff000f, 0x04000004, 0x800f0004, 0x80e40002, 0x80e40004, 0xa0ff0010, 0x04000004, + 0x800f0004, 0x80e40002, 0x80e40004, 0xa000000e, 0x04000004, 0x800f0004, 0x80e40002, 0x80e40004, + 0xa055000e, 0x04000004, 0x800f0000, 0x80e40002, 0x80e40004, 0x80e40000, 0x03000002, 0x800f0003, + 0x80e40000, 0xa0aa000e, 0x0400005a, 0x80010000, 0x80e40003, 0xa0e40000, 0x80000001, 0x0400005a, + 0x80020000, 0x80e40003, 0xa0e40001, 0x80000001, 0x0400005a, 0x80040000, 0x80e40003, 0xa0e40002, + 0x80000001, 0x03000002, 0x80070000, 0x80e40000, 0x80e40003, 0x03000005, 0x800e0001, 0x80550000, + 0xa090000b, 0x04000004, 0x800e0001, 0x80000000, 0xa090000a, 0x80e40001, 0x03000002, 0x80070003, + 0x80e40000, 0x80f90001, 0x03000008, 0x80010000, 0x80e40003, 0xa0e4000c, 0x03000008, 0x80020000, + 0x80e40003, 0xa0e4000d, 0x03000002, 0x80030000, 0x80e40000, 0x80e40003, 0x03000005, 0x800c0000, + 0x80550000, 0xa0440004, 0x04000004, 0x800c0000, 0x80000000, 0xa0440003, 0x80e40000, 0x04000004, + 0x800c0000, 0x80aa0003, 0xa0440005, 0x80e40000, 0x03000002, 0x80030003, 0x80ee0000, 0x80e40000, + 0x0000002a, 0x02000001, 0x80080003, 0x90ff0001, 0x0000002b, 0x01000028, 0xe0e40805, 0x04000004, + 0x800f0000, 0x80e40003, 0xa0550010, 0xa0aa0010, 0x02000013, 0x800f0000, 0x80e40000, 0x04000004, + 0x800f0000, 0x80e40000, 0xa000000f, 0xa055000f, 0x03000005, 0x800f0000, 0x80e40000, 0x80e40000, + 0x04000004, 0x800f0002, 0x80e40000, 0xa0aa000f, 0xa0ff000f, 0x04000004, 0x800f0002, 0x80e40000, + 0x80e40002, 0xa0ff0010, 0x04000004, 0x800f0002, 0x80e40000, 0x80e40002, 0xa000000e, 0x04000004, + 0x800f0002, 0x80e40000, 0x80e40002, 0xa055000e, 0x04000004, 0x800f0000, 0x80e40000, 0x80e40002, + 0x80e40003, 0x03000002, 0x800f0000, 0x80e40000, 0xa0aa000e, 0x04000004, 0x800f0002, 0x80e40000, + 0xa1ff000e, 0xa155000e, 0x02000013, 0x800f0002, 0x80e40002, 0x04000004, 0x800f0002, 0x80e40002, + 0xa000000f, 0xa055000f, 0x03000005, 0x800f0002, 0x80e40002, 0x80e40002, 0x04000004, 0x800f0004, + 0x80e40002, 0xa0aa000f, 0xa0ff000f, 0x04000004, 0x800f0004, 0x80e40002, 0x80e40004, 0xa0ff0010, + 0x04000004, 0x800f0004, 0x80e40002, 0x80e40004, 0xa000000e, 0x04000004, 0x800f0004, 0x80e40002, + 0x80e40004, 0xa055000e, 0x04000004, 0x800f0000, 0x80e40002, 0x80e40004, 0x80e40000, 0x03000002, + 0x800f0003, 0x80e40000, 0xa0aa000e, 0x0400005a, 0x80010000, 0x80e40003, 0xa0e40000, 0x80000001, + 0x0400005a, 0x80020000, 0x80e40003, 0xa0e40001, 0x80000001, 0x0400005a, 0x80040000, 0x80e40003, + 0xa0e40002, 0x80000001, 0x03000002, 0x80070000, 0x80e40000, 0x80e40003, 0x03000005, 0x80070001, + 0x80550000, 0xa0e4000b, 0x04000004, 0x80070001, 0x80000000, 0xa0e4000a, 0x80e40001, 0x03000002, + 0x80070003, 0x80e40000, 0x80e40001, 0x03000008, 0x80010000, 0x80e40003, 0xa0e4000c, 0x03000008, + 0x80020000, 0x80e40003, 0xa0e4000d, 0x03000002, 0x80030000, 0x80e40000, 0x80e40003, 0x03000005, + 0x800c0000, 0x80550000, 0xa0440004, 0x04000004, 0x800c0000, 0x80000000, 0xa0440003, 0x80e40000, + 0x04000004, 0x800c0000, 0x80aa0003, 0xa0440005, 0x80e40000, 0x03000002, 0x80030003, 0x80ee0000, + 0x80e40000, 0x0000002b, 0x03000042, 0x800f0000, 0x90e40000, 0xa0e40800, 0x03000002, 0x800f0000, + 0x80e40000, 0x80e40003, 0x03000042, 0x800f0001, 0x90e40000, 0xa0e40801, 0x03000002, 0x800f0800, + 0x80e40000, 0x80e40001, 0x0000ffff, 0x00000007, 0x00000b6c, 0xfffe0300, 0x013cfffe, 0x42415443, + 0x0000001c, 0x000004bb, 0xfffe0300, 0x0000000c, 0x0000001c, 0x00000000, 0x000004b4, 0x0000010c, + 0x00200002, 0x00000001, 0x00000114, 0x00000124, 0x00000134, 0x001d0002, 0x00000002, 0x0000013c, + 0x0000014c, 0x0000016c, 0x001f0002, 0x00000001, 0x00000174, 0x00000184, 0x00000194, 0x00100002, + 0x00000004, 0x000001a0, 0x000001b0, 0x000001f0, 0x00140002, 0x00000003, 0x000001f8, 0x00000208, + 0x00000238, 0x00170002, 0x00000003, 0x00000244, 0x00000254, 0x00000284, 0x000c0002, 0x00000004, + 0x0000028c, 0x0000029c, 0x000002dc, 0x00020003, 0x00000001, 0x000002e8, 0x00000000, 0x000002f8, + 0x00000003, 0x00000002, 0x00000308, 0x00000000, 0x00000318, 0x001a0002, 0x00000003, 0x00000370, + 0x00000380, 0x000003b0, 0x00000002, 0x00000006, 0x000003b4, 0x000003c4, 0x00000424, 0x00060002, + 0x00000006, 0x00000444, 0x00000454, 0x31727261, 0xababab00, 0x00030000, 0x00010001, 0x00000001, + 0x00000000, 0x42b60000, 0x00000000, 0x00000000, 0x00000000, 0x32727261, 0xababab00, 0x00030000, + 0x00010001, 0x00000002, 0x00000000, 0x42b80000, 0x00000000, 0x00000000, 0x00000000, 0x42ba0000, + 0x00000000, 0x00000000, 0x00000000, 0x6f505f67, 0xab003173, 0x00030001, 0x00040001, 0x00000001, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x3478336d, 0x756c6f63, 0xab006e6d, + 0x00030003, 0x00040003, 0x00000001, 0x00000000, 0x41300000, 0x41a80000, 0x41f80000, 0x00000000, + 0x41400000, 0x41b00000, 0x42000000, 0x00000000, 0x41500000, 0x41b80000, 0x42040000, 0x00000000, + 0x41600000, 0x41c00000, 0x42080000, 0x00000000, 0x3478336d, 0x00776f72, 0x00030002, 0x00040003, + 0x00000001, 0x00000000, 0x41300000, 0x41400000, 0x41500000, 0x41600000, 0x41a80000, 0x41b00000, + 0x41b80000, 0x41c00000, 0x41f80000, 0x42000000, 0x42040000, 0x42080000, 0x3378346d, 0x756c6f63, + 0xab006e6d, 0x00030003, 0x00030004, 0x00000001, 0x00000000, 0x41300000, 0x41a80000, 0x41f80000, + 0x42240000, 0x41400000, 0x41b00000, 0x42000000, 0x42280000, 0x41500000, 0x41b80000, 0x42040000, + 0x422c0000, 0x3378346d, 0x00776f72, 0x00030002, 0x00030004, 0x00000001, 0x00000000, 0x41300000, + 0x41400000, 0x41500000, 0x00000000, 0x41a80000, 0x41b00000, 0x41b80000, 0x00000000, 0x41f80000, + 0x42000000, 0x42040000, 0x00000000, 0x42240000, 0x42280000, 0x422c0000, 0x00000000, 0x706d6173, + 0x3172656c, 0xababab00, 0x000c0004, 0x00010001, 0x00000001, 0x00000000, 0x706d6173, 0x7372656c, + 0x7272615f, 0xab007961, 0x000c0004, 0x00010001, 0x00000002, 0x00000000, 0x00317374, 0xab003176, + 0x00030001, 0x00030001, 0x00000001, 0x00000000, 0xab007666, 0x00030000, 0x00010001, 0x00000001, + 0x00000000, 0xab003276, 0x00030001, 0x00040001, 0x00000001, 0x00000000, 0x0000031c, 0x00000320, + 0x00000330, 0x00000334, 0x00000344, 0x00000348, 0x00000005, 0x00080001, 0x00030001, 0x00000358, + 0x41100000, 0x41200000, 0x41300000, 0x00000000, 0x41400000, 0x00000000, 0x00000000, 0x00000000, + 0x41500000, 0x41600000, 0x41700000, 0x41800000, 0x00327374, 0x00000005, 0x00080001, 0x00030002, + 0x00000358, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x3f800000, 0x40000000, 0x40400000, + 0x00000000, 0x40800000, 0x00000000, 0x00000000, 0x00000000, 0x40a00000, 0x40c00000, 0x40e00000, + 0x41000000, 0x00337374, 0xab007374, 0x00000005, 0x00080001, 0x00030002, 0x00000358, 0x00000428, + 0x0000042c, 0x00000005, 0x00100001, 0x00010001, 0x0000043c, 0x3f800000, 0x40000000, 0x40400000, + 0x00000000, 0x40800000, 0x00000000, 0x00000000, 0x00000000, 0x40a00000, 0x40c00000, 0x40e00000, + 0x41000000, 0x41100000, 0x41200000, 0x41300000, 0x00000000, 0x41400000, 0x00000000, 0x00000000, + 0x00000000, 0x41500000, 0x41600000, 0x41700000, 0x41800000, 0x335f7376, 0x4d00305f, 0x6f726369, + 0x74666f73, 0x29522820, 0x534c4820, 0x6853204c, 0x72656461, 0x6d6f4320, 0x656c6970, 0x2e392072, + 0x392e3932, 0x332e3235, 0x00313131, 0x00f0fffe, 0x53455250, 0x46580201, 0x0047fffe, 0x42415443, + 0x0000001c, 0x000000e7, 0x46580201, 0x00000003, 0x0000001c, 0x00000100, 0x000000e4, 0x00000058, + 0x00020002, 0x00000001, 0x00000060, 0x00000070, 0x00000080, 0x00030002, 0x00000001, 0x00000088, + 0x00000070, 0x00000098, 0x00000002, 0x00000002, 0x000000a4, 0x000000b4, 0x6f505f67, 0xab003173, + 0x00030001, 0x00040001, 0x00000001, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x6f505f67, 0xab003273, 0x00030001, 0x00040001, 0x00000001, 0x00000000, 0x65535f67, 0x7463656c, + 0xab00726f, 0x00030001, 0x00040001, 0x00000003, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x41200000, 0x41200000, 0x41200000, 0x41200000, 0x459c4800, 0x459c5000, 0x459c5800, + 0x459c6000, 0x4d007874, 0x6f726369, 0x74666f73, 0x29522820, 0x534c4820, 0x6853204c, 0x72656461, + 0x6d6f4320, 0x656c6970, 0x2e392072, 0x392e3932, 0x332e3235, 0x00313131, 0x000cfffe, 0x49535250, + 0x00000021, 0x00000000, 0x00000000, 0x00000001, 0x00000000, 0x00000000, 0x00000001, 0x00000021, + 0x00000001, 0x00000000, 0x00000000, 0x0032fffe, 0x54494c43, 0x00000018, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x3fe00000, + 0x00000000, 0xc0000000, 0x00000000, 0xc0080000, 0x00000000, 0x00000000, 0x00000000, 0x40100000, + 0x00000000, 0x40140000, 0x00000000, 0x40180000, 0x00000000, 0x401c0000, 0x0064fffe, 0x434c5846, + 0x00000009, 0xa0500004, 0x00000002, 0x00000000, 0x00000001, 0x00000011, 0x00000000, 0x00000002, + 0x00000008, 0x00000000, 0x00000007, 0x00000000, 0x20400004, 0x00000002, 0x00000000, 0x00000007, + 0x00000000, 0x00000000, 0x00000001, 0x00000014, 0x00000000, 0x00000007, 0x00000004, 0xa0500004, + 0x00000002, 0x00000000, 0x00000001, 0x00000012, 0x00000000, 0x00000002, 0x0000000c, 0x00000000, + 0x00000007, 0x00000000, 0x20400004, 0x00000002, 0x00000000, 0x00000007, 0x00000000, 0x00000000, + 0x00000001, 0x00000014, 0x00000000, 0x00000007, 0x00000008, 0x10100004, 0x00000001, 0x00000000, + 0x00000007, 0x00000008, 0x00000000, 0x00000007, 0x00000000, 0x20400004, 0x00000002, 0x00000000, + 0x00000007, 0x00000000, 0x00000000, 0x00000007, 0x00000004, 0x00000000, 0x00000007, 0x0000000c, + 0xa0200001, 0x00000002, 0x00000000, 0x00000001, 0x00000010, 0x00000000, 0x00000002, 0x00000005, + 0x00000000, 0x00000007, 0x00000000, 0xa0500004, 0x00000002, 0x00000000, 0x00000007, 0x00000000, + 0x00000000, 0x00000007, 0x0000000c, 0x00000000, 0x00000007, 0x00000004, 0x20400004, 0x00000002, + 0x00000000, 0x00000007, 0x00000004, 0x00000000, 0x00000007, 0x00000008, 0x00000000, 0x00000004, + 0x00000084, 0xf0f0f0f0, 0x0f0f0f0f, 0x0000ffff, 0x05000051, 0xa00f0022, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x0200001f, 0x80000000, 0x900f0000, 0x0200001f, 0x90000000, 0xa00f0801, + 0x0200001f, 0x90000000, 0xa00f0802, 0x0200001f, 0x80000000, 0xe00f0000, 0x0200001f, 0x80000005, + 0xe0030001, 0x0200001f, 0x8000000a, 0xe00f0002, 0x03000009, 0x80010000, 0x90e40000, 0xa0e40017, + 0x03000009, 0x80020000, 0x90e40000, 0xa0e40018, 0x03000009, 0x80040000, 0x90e40000, 0xa0e40019, + 0x03000008, 0x80010001, 0x90e40000, 0xa0e40010, 0x03000008, 0x80020001, 0x90e40000, 0xa0e40011, + 0x03000008, 0x80040001, 0x90e40000, 0xa0e40012, 0x03000008, 0x80080001, 0x90e40000, 0xa0e40013, + 0x02000001, 0x80080000, 0xa0000022, 0x03000002, 0x800f0000, 0x80e40000, 0x80e40001, 0x03000005, + 0x800f0001, 0xa0e40015, 0x90550000, 0x04000004, 0x800f0001, 0x90000000, 0xa0e40014, 0x80e40001, + 0x04000004, 0x800f0001, 0x90aa0000, 0xa0e40016, 0x80e40001, 0x03000002, 0x800f0000, 0x80e40000, + 0x80e40001, 0x03000005, 0x80070001, 0xa0e4000d, 0x90550000, 0x04000004, 0x80070001, 0x90000000, + 0xa0e4000c, 0x80e40001, 0x04000004, 0x80070001, 0x90aa0000, 0xa0e4000e, 0x80e40001, 0x04000004, + 0x80070001, 0x90ff0000, 0xa0e4000f, 0x80e40001, 0x03000002, 0x80070000, 0x80e40000, 0x80e40001, + 0x04000004, 0x800f0000, 0x90e40000, 0xa000001b, 0x80e40000, 0x03000009, 0x80010001, 0x90e40000, + 0xa0e4001c, 0x03000002, 0x800f0000, 0x80e40000, 0x80000001, 0x04000004, 0x800f0000, 0x90e40000, + 0xa0000004, 0x80e40000, 0x03000009, 0x80010001, 0x90e40000, 0xa0e40005, 0x03000002, 0x800f0000, + 0x80e40000, 0x80000001, 0x04000004, 0x800f0000, 0x90e40000, 0xa0000020, 0x80e40000, 0x04000004, + 0x800f0000, 0x90e40000, 0xa000001e, 0x80e40000, 0x04000004, 0x800f0000, 0x90e40000, 0xa000000a, + 0x80e40000, 0x03000009, 0x80010001, 0x90e40000, 0xa0e4000b, 0x03000002, 0x800f0000, 0x80e40000, + 0x80000001, 0x0300005f, 0x800f0001, 0xa0e4001f, 0xa0e40802, 0x03000002, 0x800f0000, 0x80e40000, + 0x80e40001, 0x0300005f, 0x800f0001, 0xa0e4001f, 0xa0e40801, 0x03000002, 0xe00f0002, 0x80e40000, + 0x80e40001, 0x02000001, 0xe00f0000, 0xa0e40021, 0x02000001, 0xe0030001, 0xa0000022, 0x0000ffff, + 0x00000008, 0x000001dc, 0xfffe0300, 0x0016fffe, 0x42415443, 0x0000001c, 0x00000023, 0xfffe0300, + 0x00000000, 0x00000000, 0x00000000, 0x0000001c, 0x335f7376, 0x4d00305f, 0x6f726369, 0x74666f73, + 0x29522820, 0x534c4820, 0x6853204c, 0x72656461, 0x6d6f4320, 0x656c6970, 0x2e392072, 0x392e3932, + 0x332e3235, 0x00313131, 0x0045fffe, 0x53455250, 0x46580201, 0x0024fffe, 0x42415443, 0x0000001c, + 0x0000005b, 0x46580201, 0x00000001, 0x0000001c, 0x00000100, 0x00000058, 0x00000030, 0x00000002, + 0x00000001, 0x00000038, 0x00000048, 0x6f505f67, 0xab003173, 0x00030001, 0x00040001, 0x00000001, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x4d007874, 0x6f726369, 0x74666f73, + 0x29522820, 0x534c4820, 0x6853204c, 0x72656461, 0x6d6f4320, 0x656c6970, 0x2e392072, 0x392e3932, + 0x332e3235, 0x00313131, 0x000cfffe, 0x49535250, 0x00000000, 0x00000000, 0x00000000, 0x00000001, + 0x00000000, 0x00000000, 0x00000001, 0x00000000, 0x00000001, 0x00000000, 0x00000000, 0x0002fffe, + 0x54494c43, 0x00000000, 0x000cfffe, 0x434c5846, 0x00000001, 0x10000004, 0x00000001, 0x00000000, + 0x00000002, 0x00000000, 0x00000000, 0x00000004, 0x00000000, 0xf0f0f0f0, 0x0f0f0f0f, 0x0000ffff, + 0x05000051, 0xa00f0001, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x0200001f, 0x80000000, + 0xe00f0000, 0x0200001f, 0x80000005, 0xe0030001, 0x0200001f, 0x8000000a, 0xe00f0002, 0x02000001, + 0xe00f0000, 0xa0e40000, 0x02000001, 0xe0030001, 0xa0000001, 0x02000001, 0xe00f0002, 0xa0000001, + 0x0000ffff, 0x00000005, 0x00000000, 0x00000004, 0x00000000, 0x00000001, 0x0000002c, 0xfffe0101, + 0x00000051, 0xa00f0000, 0x3f800000, 0x3f800000, 0x3f800000, 0x3f800000, 0x00000001, 0xc00f0000, + 0xa0e40000, 0x0000ffff, 0x00000002, 0x0000002c, 0xfffe0101, 0x00000051, 0xa00f0000, 0x40000000, + 0x40000000, 0x40000000, 0x40000000, 0x00000001, 0xc00f0000, 0xa0e40000, 0x0000ffff, 0x00000003, + 0x0000002c, 0xfffe0200, 0x05000051, 0xa00f0000, 0x40400000, 0x40400000, 0x40400000, 0x40400000, + 0x02000001, 0xc00f0000, 0xa0e40000, 0x0000ffff, 0x00000000, 0x00000001, 0xffffffff, 0x00000000, + 0x00000002, 0x000000e8, 0x00000008, 0x615f7376, 0x00007272, 0x46580200, 0x0024fffe, 0x42415443, + 0x0000001c, 0x0000005b, 0x46580200, 0x00000001, 0x0000001c, 0x00000100, 0x00000058, 0x00000030, + 0x00000002, 0x00000001, 0x00000038, 0x00000048, 0x56695f67, 0x00746365, 0x00020001, 0x00040001, + 0x00000001, 0x00000000, 0x40800000, 0x40400000, 0x40000000, 0x3f800000, 0x4d007874, 0x6f726369, + 0x74666f73, 0x29522820, 0x534c4820, 0x6853204c, 0x72656461, 0x6d6f4320, 0x656c6970, 0x2e392072, + 0x392e3932, 0x332e3235, 0x00313131, 0x0002fffe, 0x54494c43, 0x00000000, 0x000cfffe, 0x434c5846, + 0x00000001, 0x10000001, 0x00000001, 0x00000000, 0x00000002, 0x00000002, 0x00000000, 0x00000004, + 0x00000000, 0xf0f0f0f0, 0x0f0f0f0f, 0x0000ffff, 0x00000000, 0x00000000, 0xffffffff, 0x00000029, + 0x00000000, 0x00000198, 0x46580200, 0x0053fffe, 0x42415443, 0x0000001c, 0x00000117, 0x46580200, + 0x00000001, 0x0000001c, 0x20000100, 0x00000114, 0x00000030, 0x00000002, 0x00000005, 0x000000a4, + 0x000000b4, 0x00337374, 0x76007374, 0xabab0031, 0x00030001, 0x00030001, 0x00000001, 0x00000000, + 0xab007666, 0x00030000, 0x00010001, 0x00000001, 0x00000000, 0xab003276, 0x00030001, 0x00040001, + 0x00000001, 0x00000000, 0x00000037, 0x0000003c, 0x0000004c, 0x00000050, 0x00000060, 0x00000064, + 0x00000005, 0x00080001, 0x00030002, 0x00000074, 0x00000034, 0x0000008c, 0x00000005, 0x00100001, + 0x00010001, 0x0000009c, 0x3f800000, 0x40000000, 0x40400000, 0x00000000, 0x40800000, 0x00000000, + 0x00000000, 0x00000000, 0x40a00000, 0x40c00000, 0x40e00000, 0x41000000, 0x41100000, 0x41200000, + 0x41300000, 0x00000000, 0x41400000, 0x00000000, 0x00000000, 0x00000000, 0x41500000, 0x41600000, + 0x41700000, 0x41800000, 0x4d007874, 0x6f726369, 0x74666f73, 0x29522820, 0x534c4820, 0x6853204c, + 0x72656461, 0x6d6f4320, 0x656c6970, 0x2e392072, 0x392e3932, 0x332e3235, 0x00313131, 0x0002fffe, + 0x54494c43, 0x00000000, 0x000cfffe, 0x434c5846, 0x00000001, 0x10000001, 0x00000001, 0x00000000, + 0x00000002, 0x00000010, 0x00000000, 0x00000004, 0x00000000, 0xf0f0f0f0, 0x0f0f0f0f, 0x0000ffff, + 0x00000000, 0x00000000, 0xffffffff, 0x00000028, 0x00000000, 0x00000198, 0x46580200, 0x0053fffe, + 0x42415443, 0x0000001c, 0x00000117, 0x46580200, 0x00000001, 0x0000001c, 0x20000100, 0x00000114, + 0x00000030, 0x00000002, 0x00000002, 0x000000a4, 0x000000b4, 0x00337374, 0x76007374, 0xabab0031, + 0x00030001, 0x00030001, 0x00000001, 0x00000000, 0xab007666, 0x00030000, 0x00010001, 0x00000001, + 0x00000000, 0xab003276, 0x00030001, 0x00040001, 0x00000001, 0x00000000, 0x00000037, 0x0000003c, + 0x0000004c, 0x00000050, 0x00000060, 0x00000064, 0x00000005, 0x00080001, 0x00030002, 0x00000074, + 0x00000034, 0x0000008c, 0x00000005, 0x00100001, 0x00010001, 0x0000009c, 0x3f800000, 0x40000000, + 0x40400000, 0x00000000, 0x40800000, 0x00000000, 0x00000000, 0x00000000, 0x40a00000, 0x40c00000, + 0x40e00000, 0x41000000, 0x41100000, 0x41200000, 0x41300000, 0x00000000, 0x41400000, 0x00000000, + 0x00000000, 0x00000000, 0x41500000, 0x41600000, 0x41700000, 0x41800000, 0x4d007874, 0x6f726369, + 0x74666f73, 0x29522820, 0x534c4820, 0x6853204c, 0x72656461, 0x6d6f4320, 0x656c6970, 0x2e392072, + 0x392e3932, 0x332e3235, 0x00313131, 0x0002fffe, 0x54494c43, 0x00000000, 0x000cfffe, 0x434c5846, + 0x00000001, 0x10000001, 0x00000001, 0x00000000, 0x00000002, 0x00000004, 0x00000000, 0x00000004, + 0x00000000, 0xf0f0f0f0, 0x0f0f0f0f, 0x0000ffff, 0x00000000, 0x00000000, 0xffffffff, 0x00000027, + 0x00000000, 0x0000017c, 0x46580200, 0x004cfffe, 0x42415443, 0x0000001c, 0x000000fb, 0x46580200, + 0x00000001, 0x0000001c, 0x20000100, 0x000000f8, 0x00000030, 0x00000002, 0x00000005, 0x00000088, + 0x00000098, 0x00327374, 0xab003176, 0x00030001, 0x00030001, 0x00000001, 0x00000000, 0xab007666, + 0x00030000, 0x00010001, 0x00000001, 0x00000000, 0xab003276, 0x00030001, 0x00040001, 0x00000001, + 0x00000000, 0x00000034, 0x00000038, 0x00000048, 0x0000004c, 0x0000005c, 0x00000060, 0x00000005, + 0x00080001, 0x00030002, 0x00000070, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x3f800000, + 0x40000000, 0x40400000, 0x00000000, 0x40800000, 0x00000000, 0x00000000, 0x00000000, 0x40a00000, + 0x40c00000, 0x40e00000, 0x41000000, 0x4d007874, 0x6f726369, 0x74666f73, 0x29522820, 0x534c4820, + 0x6853204c, 0x72656461, 0x6d6f4320, 0x656c6970, 0x2e392072, 0x392e3932, 0x332e3235, 0x00313131, + 0x0002fffe, 0x54494c43, 0x00000000, 0x000cfffe, 0x434c5846, 0x00000001, 0x10000001, 0x00000001, + 0x00000000, 0x00000002, 0x00000010, 0x00000000, 0x00000004, 0x00000000, 0xf0f0f0f0, 0x0f0f0f0f, + 0x0000ffff, 0x00000000, 0x00000000, 0xffffffff, 0x00000026, 0x00000000, 0x0000017c, 0x46580200, + 0x004cfffe, 0x42415443, 0x0000001c, 0x000000fb, 0x46580200, 0x00000001, 0x0000001c, 0x20000100, + 0x000000f8, 0x00000030, 0x00000002, 0x00000002, 0x00000088, 0x00000098, 0x00327374, 0xab003176, + 0x00030001, 0x00030001, 0x00000001, 0x00000000, 0xab007666, 0x00030000, 0x00010001, 0x00000001, + 0x00000000, 0xab003276, 0x00030001, 0x00040001, 0x00000001, 0x00000000, 0x00000034, 0x00000038, + 0x00000048, 0x0000004c, 0x0000005c, 0x00000060, 0x00000005, 0x00080001, 0x00030002, 0x00000070, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x3f800000, 0x40000000, 0x40400000, 0x00000000, + 0x40800000, 0x00000000, 0x00000000, 0x00000000, 0x40a00000, 0x40c00000, 0x40e00000, 0x41000000, + 0x4d007874, 0x6f726369, 0x74666f73, 0x29522820, 0x534c4820, 0x6853204c, 0x72656461, 0x6d6f4320, + 0x656c6970, 0x2e392072, 0x392e3932, 0x332e3235, 0x00313131, 0x0002fffe, 0x54494c43, 0x00000000, + 0x000cfffe, 0x434c5846, 0x00000001, 0x10000001, 0x00000001, 0x00000000, 0x00000002, 0x00000004, + 0x00000000, 0x00000004, 0x00000000, 0xf0f0f0f0, 0x0f0f0f0f, 0x0000ffff, 0x00000000, 0x00000000, + 0xffffffff, 0x00000024, 0x00000000, 0x00000770, 0x46580200, 0x008cfffe, 0x42415443, 0x0000001c, + 0x000001fb, 0x46580200, 0x00000004, 0x0000001c, 0x20000100, 0x000001f8, 0x0000006c, 0x000b0002, + 0x00000001, 0x00000074, 0x00000084, 0x00000094, 0x00060002, 0x00000004, 0x0000009c, 0x000000ac, + 0x000000ec, 0x00000002, 0x00000006, 0x00000160, 0x00000170, 0x000001d0, 0x000a0002, 0x00000001, + 0x000001d8, 0x000001e8, 0x56695f67, 0x00746365, 0x00020001, 0x00040001, 0x00000001, 0x00000000, + 0x40800000, 0x40400000, 0x40000000, 0x3f800000, 0x3478346d, 0xababab00, 0x00030003, 0x00040004, + 0x00000001, 0x00000000, 0x41300000, 0x41a80000, 0x41f80000, 0x42240000, 0x41400000, 0x41b00000, + 0x42000000, 0x42280000, 0x41500000, 0x41b80000, 0x42040000, 0x422c0000, 0x41600000, 0x41c00000, + 0x42080000, 0x42300000, 0x00337374, 0x76007374, 0xabab0031, 0x00030001, 0x00030001, 0x00000001, + 0x00000000, 0xab007666, 0x00030000, 0x00010001, 0x00000001, 0x00000000, 0xab003276, 0x00030001, + 0x00040001, 0x00000001, 0x00000000, 0x000000f3, 0x000000f8, 0x00000108, 0x0000010c, 0x0000011c, + 0x00000120, 0x00000005, 0x00080001, 0x00030002, 0x00000130, 0x000000f0, 0x00000148, 0x00000005, + 0x00100001, 0x00010001, 0x00000158, 0x3f800000, 0x40000000, 0x40400000, 0x00000000, 0x40800000, + 0x00000000, 0x00000000, 0x00000000, 0x40a00000, 0x40c00000, 0x40e00000, 0x41000000, 0x41100000, + 0x41200000, 0x41300000, 0x00000000, 0x41400000, 0x00000000, 0x00000000, 0x00000000, 0x41500000, + 0x41600000, 0x41700000, 0x41800000, 0x33636576, 0xababab00, 0x00030001, 0x00030001, 0x00000001, + 0x00000000, 0x447a4000, 0x447a8000, 0x447ac000, 0x00000000, 0x4d007874, 0x6f726369, 0x74666f73, + 0x29522820, 0x534c4820, 0x6853204c, 0x72656461, 0x6d6f4320, 0x656c6970, 0x2e392072, 0x392e3932, + 0x332e3235, 0x00313131, 0x008afffe, 0x54494c43, 0x00000044, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x3ff00000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x3ff00000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x3ff00000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x3ff00000, 0x00000000, 0x40080000, 0x00000000, + 0x3ff00000, 0x00000000, 0x40000000, 0x00000000, 0x00000000, 0x00c1fffe, 0x434c5846, 0x0000000e, + 0x50000004, 0x00000002, 0x00000000, 0x00000002, 0x00000018, 0x00000001, 0x00000002, 0x0000002e, + 0x00000001, 0x0000003c, 0x00000000, 0x00000007, 0x00000000, 0x50000004, 0x00000002, 0x00000000, + 0x00000002, 0x0000001c, 0x00000001, 0x00000002, 0x0000002e, 0x00000001, 0x0000003c, 0x00000000, + 0x00000007, 0x00000001, 0x50000004, 0x00000002, 0x00000000, 0x00000002, 0x00000020, 0x00000001, + 0x00000002, 0x0000002e, 0x00000001, 0x0000003c, 0x00000000, 0x00000007, 0x00000002, 0x50000004, + 0x00000002, 0x00000000, 0x00000002, 0x00000024, 0x00000001, 0x00000002, 0x0000002e, 0x00000001, + 0x0000003c, 0x00000000, 0x00000007, 0x00000003, 0xa0400001, 0x00000002, 0x00000000, 0x00000002, + 0x0000002f, 0x00000000, 0x00000002, 0x0000002f, 0x00000000, 0x00000007, 0x00000004, 0x50000004, + 0x00000002, 0x00000000, 0x00000002, 0x00000018, 0x00000001, 0x00000007, 0x00000004, 0x00000001, + 0x00000030, 0x00000000, 0x00000007, 0x00000008, 0x50000004, 0x00000002, 0x00000000, 0x00000002, + 0x0000001c, 0x00000001, 0x00000007, 0x00000004, 0x00000001, 0x00000030, 0x00000000, 0x00000007, + 0x00000009, 0x50000004, 0x00000002, 0x00000000, 0x00000002, 0x00000020, 0x00000001, 0x00000007, + 0x00000004, 0x00000001, 0x00000030, 0x00000000, 0x00000007, 0x0000000a, 0x50000004, 0x00000002, + 0x00000000, 0x00000002, 0x00000024, 0x00000001, 0x00000007, 0x00000004, 0x00000001, 0x00000030, + 0x00000000, 0x00000007, 0x0000000b, 0x50000004, 0x00000002, 0x00000000, 0x00000007, 0x00000000, + 0x00000000, 0x00000007, 0x00000008, 0x00000000, 0x00000004, 0x00000000, 0x50000003, 0x00000002, + 0x00000000, 0x00000002, 0x00000028, 0x00000001, 0x00000002, 0x0000002e, 0x00000001, 0x00000030, + 0x00000000, 0x00000004, 0x00000002, 0x70e00001, 0x00000006, 0x00000000, 0x00000001, 0x00000041, + 0x00000000, 0x00000001, 0x00000042, 0x00000000, 0x00000001, 0x00000040, 0x00000001, 0x00000002, + 0x0000002f, 0x00000001, 0x00000030, 0x00000001, 0x00000002, 0x0000002f, 0x00000001, 0x00000031, + 0x00000001, 0x00000002, 0x0000002f, 0x00000001, 0x00000032, 0x00000000, 0x00000004, 0x00000003, + 0xa0500001, 0x00000002, 0x00000000, 0x00000002, 0x0000002c, 0x00000000, 0x00000001, 0x00000040, + 0x00000000, 0x00000007, 0x00000000, 0x10000001, 0x00000001, 0x00000001, 0x00000007, 0x00000000, + 0x00000002, 0x00000004, 0x00000000, 0x00000004, 0x00000001, 0xf0f0f0f0, 0x0f0f0f0f, 0x0000ffff, + 0x00000000, 0x00000000, 0xffffffff, 0x00000023, 0x00000000, 0x000004ec, 0x46580200, 0x005afffe, + 0x42415443, 0x0000001c, 0x00000133, 0x46580200, 0x00000004, 0x0000001c, 0x20000100, 0x00000130, + 0x0000006c, 0x00000002, 0x00000003, 0x00000078, 0x00000088, 0x000000b8, 0x000a0002, 0x00000001, + 0x000000c0, 0x000000d0, 0x000000e0, 0x00080002, 0x00000001, 0x000000e8, 0x000000f8, 0x00000108, + 0x00090002, 0x00000001, 0x00000110, 0x00000120, 0x65535f67, 0x7463656c, 0xab00726f, 0x00030001, + 0x00040001, 0x00000003, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x41200000, + 0x41200000, 0x41200000, 0x41200000, 0x459c4800, 0x459c5000, 0x459c5800, 0x459c6000, 0x56695f67, + 0x00746365, 0x00020001, 0x00040001, 0x00000001, 0x00000000, 0x40800000, 0x40400000, 0x40000000, + 0x3f800000, 0x6576706f, 0x00317463, 0x00030001, 0x00040001, 0x00000001, 0x00000000, 0x00000000, + 0x80000000, 0xc00ccccd, 0x7f7fffff, 0x6576706f, 0x00327463, 0x00030001, 0x00040001, 0x00000001, + 0x00000000, 0x3f800000, 0x40000000, 0xc0400000, 0x40800000, 0x4d007874, 0x6f726369, 0x74666f73, + 0x29522820, 0x534c4820, 0x6853204c, 0x72656461, 0x6d6f4320, 0x656c6970, 0x2e392072, 0x392e3932, + 0x332e3235, 0x00313131, 0x007afffe, 0x54494c43, 0x0000003c, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x3ff00000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x3ff00000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x3ff00000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x3ff00000, 0x0062fffe, 0x434c5846, 0x00000008, + 0x50000004, 0x00000002, 0x00000000, 0x00000002, 0x00000020, 0x00000001, 0x00000002, 0x0000002a, + 0x00000001, 0x0000002c, 0x00000000, 0x00000004, 0x00000000, 0x10400001, 0x00000001, 0x00000000, + 0x00000002, 0x00000025, 0x00000000, 0x00000007, 0x00000000, 0x10100001, 0x00000001, 0x00000000, + 0x00000007, 0x00000000, 0x00000000, 0x00000007, 0x00000004, 0xa0400001, 0x00000002, 0x00000000, + 0x00000002, 0x00000025, 0x00000000, 0x00000001, 0x0000002c, 0x00000000, 0x00000007, 0x00000000, + 0xa0400001, 0x00000002, 0x00000000, 0x00000007, 0x00000000, 0x00000000, 0x00000007, 0x00000004, + 0x00000000, 0x00000007, 0x00000008, 0x50000004, 0x00000002, 0x00000000, 0x00000002, 0x00000028, + 0x00000001, 0x00000007, 0x00000008, 0x00000001, 0x0000002c, 0x00000000, 0x00000004, 0x00000001, + 0xa0400001, 0x00000002, 0x00000001, 0x00000002, 0x0000002b, 0x00000002, 0x00000010, 0x00000001, + 0x00000002, 0x0000002b, 0x00000002, 0x0000001d, 0x00000000, 0x00000004, 0x00000002, 0xa0400001, + 0x00000002, 0x00000001, 0x00000002, 0x00000028, 0x00000002, 0x00000001, 0x00000001, 0x00000002, + 0x0000002b, 0x00000002, 0x00000000, 0x00000000, 0x00000004, 0x00000003, 0xf0f0f0f0, 0x0f0f0f0f, + 0x0000ffff, 0x00000000, 0x00000000, 0xffffffff, 0x00000022, 0x00000000, 0x000002cc, 0x46580200, + 0x0033fffe, 0x42415443, 0x0000001c, 0x00000097, 0x46580200, 0x00000002, 0x0000001c, 0x20000100, + 0x00000094, 0x00000044, 0x00000002, 0x00000001, 0x0000004c, 0x0000005c, 0x0000006c, 0x00010002, + 0x00000001, 0x00000074, 0x00000084, 0x6576706f, 0x00317463, 0x00030001, 0x00040001, 0x00000001, + 0x00000000, 0x00000000, 0x80000000, 0xc00ccccd, 0x7f7fffff, 0x6576706f, 0x00327463, 0x00030001, + 0x00040001, 0x00000001, 0x00000000, 0x3f800000, 0x40000000, 0xc0400000, 0x40800000, 0x4d007874, + 0x6f726369, 0x74666f73, 0x29522820, 0x534c4820, 0x6853204c, 0x72656461, 0x6d6f4320, 0x656c6970, + 0x2e392072, 0x392e3932, 0x332e3235, 0x00313131, 0x001afffe, 0x54494c43, 0x0000000c, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x0061fffe, + 0x434c5846, 0x00000006, 0xa0500001, 0x00000002, 0x00000000, 0x00000002, 0x00000002, 0x00000000, + 0x00000002, 0x00000004, 0x00000000, 0x00000007, 0x00000000, 0xa0500001, 0x00000002, 0x00000000, + 0x00000002, 0x00000000, 0x00000000, 0x00000002, 0x00000005, 0x00000000, 0x00000007, 0x00000001, + 0xa0400001, 0x00000002, 0x00000000, 0x00000007, 0x00000001, 0x00000000, 0x00000007, 0x00000000, + 0x00000000, 0x00000004, 0x00000000, 0x70e00001, 0x00000006, 0x00000000, 0x00000002, 0x00000002, + 0x00000000, 0x00000002, 0x00000002, 0x00000000, 0x00000002, 0x00000000, 0x00000000, 0x00000002, + 0x00000004, 0x00000000, 0x00000002, 0x00000005, 0x00000000, 0x00000002, 0x00000006, 0x00000000, + 0x00000004, 0x00000001, 0x70e00001, 0x00000008, 0x00000000, 0x00000002, 0x00000002, 0x00000000, + 0x00000002, 0x00000002, 0x00000000, 0x00000002, 0x00000002, 0x00000000, 0x00000002, 0x00000000, + 0x00000000, 0x00000002, 0x00000004, 0x00000000, 0x00000002, 0x00000004, 0x00000000, 0x00000002, + 0x00000005, 0x00000000, 0x00000002, 0x00000005, 0x00000000, 0x00000004, 0x00000002, 0x10000001, + 0x00000001, 0x00000000, 0x00000001, 0x00000008, 0x00000000, 0x00000004, 0x00000003, 0xf0f0f0f0, + 0x0f0f0f0f, 0x0000ffff, 0x00000000, 0x00000000, 0xffffffff, 0x00000021, 0x00000000, 0x00000248, + 0x46580200, 0x003efffe, 0x42415443, 0x0000001c, 0x000000c3, 0x46580200, 0x00000003, 0x0000001c, + 0x20000100, 0x000000c0, 0x00000058, 0x00000002, 0x00000001, 0x00000060, 0x00000070, 0x00000080, + 0x00010002, 0x00000001, 0x00000088, 0x00000098, 0x000000a8, 0x00020002, 0x00000001, 0x000000b0, + 0x00000070, 0x6576706f, 0x00317463, 0x00030001, 0x00040001, 0x00000001, 0x00000000, 0x00000000, + 0x80000000, 0xc00ccccd, 0x7f7fffff, 0x6576706f, 0x00327463, 0x00030001, 0x00040001, 0x00000001, + 0x00000000, 0x3f800000, 0x40000000, 0xc0400000, 0x40800000, 0x6576706f, 0x00337463, 0x00030001, + 0x00040001, 0x00000001, 0x00000000, 0x4d007874, 0x6f726369, 0x74666f73, 0x29522820, 0x534c4820, + 0x6853204c, 0x72656461, 0x6d6f4320, 0x656c6970, 0x2e392072, 0x392e3932, 0x332e3235, 0x00313131, + 0x0022fffe, 0x54494c43, 0x00000010, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x812dea11, 0x3d719799, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x002dfffe, 0x434c5846, 0x00000004, 0xa0500004, 0x00000002, + 0x00000000, 0x00000001, 0x0000000c, 0x00000000, 0x00000002, 0x00000004, 0x00000000, 0x00000007, + 0x00000000, 0x20400004, 0x00000002, 0x00000000, 0x00000007, 0x00000000, 0x00000000, 0x00000002, + 0x00000000, 0x00000000, 0x00000007, 0x00000004, 0x10100004, 0x00000001, 0x00000000, 0x00000002, + 0x00000008, 0x00000000, 0x00000007, 0x00000000, 0x20400004, 0x00000002, 0x00000000, 0x00000007, + 0x00000000, 0x00000000, 0x00000007, 0x00000004, 0x00000000, 0x00000004, 0x00000000, 0xf0f0f0f0, + 0x0f0f0f0f, 0x0000ffff, 0x00000000, 0x00000000, 0xffffffff, 0x00000020, 0x00000000, 0x000001f0, + 0x46580200, 0x0033fffe, 0x42415443, 0x0000001c, 0x00000097, 0x46580200, 0x00000002, 0x0000001c, + 0x20000100, 0x00000094, 0x00000044, 0x00000002, 0x00000001, 0x0000004c, 0x0000005c, 0x0000006c, + 0x00010002, 0x00000001, 0x00000074, 0x00000084, 0x6576706f, 0x00317463, 0x00030001, 0x00040001, + 0x00000001, 0x00000000, 0x00000000, 0x80000000, 0xc00ccccd, 0x7f7fffff, 0x6576706f, 0x00327463, + 0x00030001, 0x00040001, 0x00000001, 0x00000000, 0x3f800000, 0x40000000, 0xc0400000, 0x40800000, + 0x4d007874, 0x6f726369, 0x74666f73, 0x29522820, 0x534c4820, 0x6853204c, 0x72656461, 0x6d6f4320, + 0x656c6970, 0x2e392072, 0x392e3932, 0x332e3235, 0x00313131, 0x001afffe, 0x54494c43, 0x0000000c, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x002afffe, 0x434c5846, 0x00000004, 0x50000004, 0x00000002, 0x00000000, 0x00000002, 0x00000000, + 0x00000000, 0x00000002, 0x00000004, 0x00000000, 0x00000004, 0x00000001, 0x50000004, 0x00000002, + 0x00000000, 0x00000002, 0x00000004, 0x00000000, 0x00000002, 0x00000004, 0x00000000, 0x00000004, + 0x00000002, 0x10000001, 0x00000001, 0x00000000, 0x00000001, 0x00000008, 0x00000000, 0x00000004, + 0x00000000, 0x10000001, 0x00000001, 0x00000000, 0x00000001, 0x00000008, 0x00000000, 0x00000004, + 0x00000003, 0xf0f0f0f0, 0x0f0f0f0f, 0x0000ffff, 0x00000000, 0x00000000, 0xffffffff, 0x0000001f, + 0x00000000, 0x000001a8, 0x46580200, 0x0024fffe, 0x42415443, 0x0000001c, 0x0000005b, 0x46580200, + 0x00000001, 0x0000001c, 0x20000100, 0x00000058, 0x00000030, 0x00000002, 0x00000001, 0x00000038, + 0x00000048, 0x6576706f, 0x00317463, 0x00030001, 0x00040001, 0x00000001, 0x00000000, 0x00000000, + 0x80000000, 0xc00ccccd, 0x7f7fffff, 0x4d007874, 0x6f726369, 0x74666f73, 0x29522820, 0x534c4820, + 0x6853204c, 0x72656461, 0x6d6f4320, 0x656c6970, 0x2e392072, 0x392e3932, 0x332e3235, 0x00313131, + 0x0012fffe, 0x54494c43, 0x00000008, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x47ae147b, 0x3f847ae1, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x002ffffe, 0x434c5846, 0x00000005, 0x10300001, 0x00000001, + 0x00000000, 0x00000002, 0x00000000, 0x00000000, 0x00000007, 0x00000000, 0x10300001, 0x00000001, + 0x00000000, 0x00000002, 0x00000001, 0x00000000, 0x00000007, 0x00000001, 0x10300001, 0x00000001, + 0x00000000, 0x00000002, 0x00000002, 0x00000000, 0x00000007, 0x00000002, 0x10300001, 0x00000001, + 0x00000000, 0x00000002, 0x00000003, 0x00000000, 0x00000007, 0x00000003, 0xa0500004, 0x00000002, + 0x00000000, 0x00000001, 0x00000004, 0x00000000, 0x00000007, 0x00000000, 0x00000000, 0x00000004, + 0x00000000, 0xf0f0f0f0, 0x0f0f0f0f, 0x0000ffff, 0x00000000, 0x00000000, 0xffffffff, 0x0000001e, + 0x00000000, 0x000000dc, 0x46580200, 0x0024fffe, 0x42415443, 0x0000001c, 0x0000005b, 0x46580200, + 0x00000001, 0x0000001c, 0x20000100, 0x00000058, 0x00000030, 0x00000002, 0x00000001, 0x00000038, + 0x00000048, 0x6576706f, 0x00317463, 0x00030001, 0x00040001, 0x00000001, 0x00000000, 0x00000000, + 0x80000000, 0xc00ccccd, 0x7f7fffff, 0x4d007874, 0x6f726369, 0x74666f73, 0x29522820, 0x534c4820, + 0x6853204c, 0x72656461, 0x6d6f4320, 0x656c6970, 0x2e392072, 0x392e3932, 0x332e3235, 0x00313131, + 0x0002fffe, 0x54494c43, 0x00000000, 0x000cfffe, 0x434c5846, 0x00000001, 0x10900004, 0x00000001, + 0x00000000, 0x00000002, 0x00000000, 0x00000000, 0x00000004, 0x00000000, 0xf0f0f0f0, 0x0f0f0f0f, + 0x0000ffff, 0x00000000, 0x00000000, 0xffffffff, 0x0000001d, 0x00000000, 0x000000dc, 0x46580200, + 0x0024fffe, 0x42415443, 0x0000001c, 0x0000005b, 0x46580200, 0x00000001, 0x0000001c, 0x20000100, + 0x00000058, 0x00000030, 0x00000002, 0x00000001, 0x00000038, 0x00000048, 0x6576706f, 0x00317463, + 0x00030001, 0x00040001, 0x00000001, 0x00000000, 0x00000000, 0x80000000, 0xc00ccccd, 0x7f7fffff, + 0x4d007874, 0x6f726369, 0x74666f73, 0x29522820, 0x534c4820, 0x6853204c, 0x72656461, 0x6d6f4320, + 0x656c6970, 0x2e392072, 0x392e3932, 0x332e3235, 0x00313131, 0x0002fffe, 0x54494c43, 0x00000000, + 0x000cfffe, 0x434c5846, 0x00000001, 0x10800004, 0x00000001, 0x00000000, 0x00000002, 0x00000000, + 0x00000000, 0x00000004, 0x00000000, 0xf0f0f0f0, 0x0f0f0f0f, 0x0000ffff, 0x00000000, 0x00000000, + 0xffffffff, 0x0000001c, 0x00000000, 0x00000124, 0x46580200, 0x0033fffe, 0x42415443, 0x0000001c, + 0x00000097, 0x46580200, 0x00000002, 0x0000001c, 0x20000100, 0x00000094, 0x00000044, 0x00000002, + 0x00000001, 0x0000004c, 0x0000005c, 0x0000006c, 0x00010002, 0x00000001, 0x00000074, 0x00000084, + 0x6576706f, 0x00317463, 0x00030001, 0x00040001, 0x00000001, 0x00000000, 0x00000000, 0x80000000, + 0xc00ccccd, 0x7f7fffff, 0x6576706f, 0x00327463, 0x00030001, 0x00040001, 0x00000001, 0x00000000, + 0x3f800000, 0x40000000, 0xc0400000, 0x40800000, 0x4d007874, 0x6f726369, 0x74666f73, 0x29522820, + 0x534c4820, 0x6853204c, 0x72656461, 0x6d6f4320, 0x656c6970, 0x2e392072, 0x392e3932, 0x332e3235, + 0x00313131, 0x0002fffe, 0x54494c43, 0x00000000, 0x000ffffe, 0x434c5846, 0x00000001, 0x20100004, + 0x00000002, 0x00000000, 0x00000002, 0x00000000, 0x00000000, 0x00000002, 0x00000004, 0x00000000, + 0x00000004, 0x00000000, 0xf0f0f0f0, 0x0f0f0f0f, 0x0000ffff, 0x00000000, 0x00000000, 0xffffffff, + 0x0000001b, 0x00000000, 0x00000124, 0x46580200, 0x0033fffe, 0x42415443, 0x0000001c, 0x00000097, + 0x46580200, 0x00000002, 0x0000001c, 0x20000100, 0x00000094, 0x00000044, 0x00000002, 0x00000001, + 0x0000004c, 0x0000005c, 0x0000006c, 0x00010002, 0x00000001, 0x00000074, 0x00000084, 0x6576706f, + 0x00317463, 0x00030001, 0x00040001, 0x00000001, 0x00000000, 0x00000000, 0x80000000, 0xc00ccccd, + 0x7f7fffff, 0x6576706f, 0x00327463, 0x00030001, 0x00040001, 0x00000001, 0x00000000, 0x3f800000, + 0x40000000, 0xc0400000, 0x40800000, 0x4d007874, 0x6f726369, 0x74666f73, 0x29522820, 0x534c4820, + 0x6853204c, 0x72656461, 0x6d6f4320, 0x656c6970, 0x2e392072, 0x392e3932, 0x332e3235, 0x00313131, + 0x0002fffe, 0x54494c43, 0x00000000, 0x000ffffe, 0x434c5846, 0x00000001, 0x20000004, 0x00000002, + 0x00000000, 0x00000002, 0x00000000, 0x00000000, 0x00000002, 0x00000004, 0x00000000, 0x00000004, + 0x00000000, 0xf0f0f0f0, 0x0f0f0f0f, 0x0000ffff, 0x00000000, 0x00000000, 0xffffffff, 0x0000001a, + 0x00000000, 0x000000dc, 0x46580200, 0x0024fffe, 0x42415443, 0x0000001c, 0x0000005b, 0x46580200, + 0x00000001, 0x0000001c, 0x20000100, 0x00000058, 0x00000030, 0x00000002, 0x00000001, 0x00000038, + 0x00000048, 0x6576706f, 0x00317463, 0x00030001, 0x00040001, 0x00000001, 0x00000000, 0x00000000, + 0x80000000, 0xc00ccccd, 0x7f7fffff, 0x4d007874, 0x6f726369, 0x74666f73, 0x29522820, 0x534c4820, + 0x6853204c, 0x72656461, 0x6d6f4320, 0x656c6970, 0x2e392072, 0x392e3932, 0x332e3235, 0x00313131, + 0x0002fffe, 0x54494c43, 0x00000000, 0x000cfffe, 0x434c5846, 0x00000001, 0x10400004, 0x00000001, + 0x00000000, 0x00000002, 0x00000000, 0x00000000, 0x00000004, 0x00000000, 0xf0f0f0f0, 0x0f0f0f0f, + 0x0000ffff, 0x00000000, 0x00000000, 0xffffffff, 0x00000019, 0x00000000, 0x0000013c, 0x46580200, + 0x0024fffe, 0x42415443, 0x0000001c, 0x0000005b, 0x46580200, 0x00000001, 0x0000001c, 0x20000100, + 0x00000058, 0x00000030, 0x00000002, 0x00000001, 0x00000038, 0x00000048, 0x6576706f, 0x00317463, + 0x00030001, 0x00040001, 0x00000001, 0x00000000, 0x00000000, 0x80000000, 0xc00ccccd, 0x7f7fffff, + 0x4d007874, 0x6f726369, 0x74666f73, 0x29522820, 0x534c4820, 0x6853204c, 0x72656461, 0x6d6f4320, + 0x656c6970, 0x2e392072, 0x392e3932, 0x332e3235, 0x00313131, 0x0002fffe, 0x54494c43, 0x00000000, + 0x0024fffe, 0x434c5846, 0x00000004, 0x10300001, 0x00000001, 0x00000000, 0x00000002, 0x00000000, + 0x00000000, 0x00000004, 0x00000000, 0x10300001, 0x00000001, 0x00000000, 0x00000002, 0x00000001, + 0x00000000, 0x00000004, 0x00000001, 0x10300001, 0x00000001, 0x00000000, 0x00000002, 0x00000002, + 0x00000000, 0x00000004, 0x00000002, 0x10300001, 0x00000001, 0x00000000, 0x00000002, 0x00000003, + 0x00000000, 0x00000004, 0x00000003, 0xf0f0f0f0, 0x0f0f0f0f, 0x0000ffff, 0x00000000, 0x00000000, + 0xffffffff, 0x00000018, 0x00000000, 0x000000dc, 0x46580200, 0x0024fffe, 0x42415443, 0x0000001c, + 0x0000005b, 0x46580200, 0x00000001, 0x0000001c, 0x20000100, 0x00000058, 0x00000030, 0x00000002, + 0x00000001, 0x00000038, 0x00000048, 0x6576706f, 0x00317463, 0x00030001, 0x00040001, 0x00000001, + 0x00000000, 0x00000000, 0x80000000, 0xc00ccccd, 0x7f7fffff, 0x4d007874, 0x6f726369, 0x74666f73, + 0x29522820, 0x534c4820, 0x6853204c, 0x72656461, 0x6d6f4320, 0x656c6970, 0x2e392072, 0x392e3932, + 0x332e3235, 0x00313131, 0x0002fffe, 0x54494c43, 0x00000000, 0x000cfffe, 0x434c5846, 0x00000001, + 0x10100004, 0x00000001, 0x00000000, 0x00000002, 0x00000000, 0x00000000, 0x00000004, 0x00000000, + 0xf0f0f0f0, 0x0f0f0f0f, 0x0000ffff, 0x00000000, 0x00000000, 0xffffffff, 0x00000017, 0x00000000, + 0x00000124, 0x46580200, 0x0033fffe, 0x42415443, 0x0000001c, 0x00000097, 0x46580200, 0x00000002, + 0x0000001c, 0x20000100, 0x00000094, 0x00000044, 0x00000002, 0x00000001, 0x0000004c, 0x0000005c, + 0x0000006c, 0x00010002, 0x00000001, 0x00000074, 0x00000084, 0x6576706f, 0x00317463, 0x00030001, + 0x00040001, 0x00000001, 0x00000000, 0x00000000, 0x80000000, 0xc00ccccd, 0x7f7fffff, 0x6576706f, + 0x00327463, 0x00030001, 0x00040001, 0x00000001, 0x00000000, 0x3f800000, 0x40000000, 0xc0400000, + 0x40800000, 0x4d007874, 0x6f726369, 0x74666f73, 0x29522820, 0x534c4820, 0x6853204c, 0x72656461, + 0x6d6f4320, 0x656c6970, 0x2e392072, 0x392e3932, 0x332e3235, 0x00313131, 0x0002fffe, 0x54494c43, + 0x00000000, 0x000ffffe, 0x434c5846, 0x00000001, 0x20300004, 0x00000002, 0x00000000, 0x00000002, + 0x00000000, 0x00000000, 0x00000002, 0x00000004, 0x00000000, 0x00000004, 0x00000000, 0xf0f0f0f0, + 0x0f0f0f0f, 0x0000ffff, 0x00000000, 0x00000000, 0xffffffff, 0x00000016, 0x00000000, 0x00000124, + 0x46580200, 0x0033fffe, 0x42415443, 0x0000001c, 0x00000097, 0x46580200, 0x00000002, 0x0000001c, + 0x20000100, 0x00000094, 0x00000044, 0x00000002, 0x00000001, 0x0000004c, 0x0000005c, 0x0000006c, + 0x00010002, 0x00000001, 0x00000074, 0x00000084, 0x6576706f, 0x00317463, 0x00030001, 0x00040001, + 0x00000001, 0x00000000, 0x00000000, 0x80000000, 0xc00ccccd, 0x7f7fffff, 0x6576706f, 0x00327463, + 0x00030001, 0x00040001, 0x00000001, 0x00000000, 0x3f800000, 0x40000000, 0xc0400000, 0x40800000, + 0x4d007874, 0x6f726369, 0x74666f73, 0x29522820, 0x534c4820, 0x6853204c, 0x72656461, 0x6d6f4320, + 0x656c6970, 0x2e392072, 0x392e3932, 0x332e3235, 0x00313131, 0x0002fffe, 0x54494c43, 0x00000000, + 0x000ffffe, 0x434c5846, 0x00000001, 0x20200004, 0x00000002, 0x00000000, 0x00000002, 0x00000000, + 0x00000000, 0x00000002, 0x00000004, 0x00000000, 0x00000004, 0x00000000, 0xf0f0f0f0, 0x0f0f0f0f, + 0x0000ffff, 0x00000000, 0x00000000, 0xffffffff, 0x00000015, 0x00000000, 0x00000124, 0x46580200, + 0x0033fffe, 0x42415443, 0x0000001c, 0x00000097, 0x46580200, 0x00000002, 0x0000001c, 0x20000100, + 0x00000094, 0x00000044, 0x00000002, 0x00000001, 0x0000004c, 0x0000005c, 0x0000006c, 0x00010002, + 0x00000001, 0x00000074, 0x00000084, 0x6576706f, 0x00317463, 0x00030001, 0x00040001, 0x00000001, + 0x00000000, 0x00000000, 0x80000000, 0xc00ccccd, 0x7f7fffff, 0x6576706f, 0x00327463, 0x00030001, + 0x00040001, 0x00000001, 0x00000000, 0x3f800000, 0x40000000, 0xc0400000, 0x40800000, 0x4d007874, + 0x6f726369, 0x74666f73, 0x29522820, 0x534c4820, 0x6853204c, 0x72656461, 0x6d6f4320, 0x656c6970, + 0x2e392072, 0x392e3932, 0x332e3235, 0x00313131, 0x0002fffe, 0x54494c43, 0x00000000, 0x000ffffe, + 0x434c5846, 0x00000001, 0x20400004, 0x00000002, 0x00000000, 0x00000002, 0x00000000, 0x00000000, + 0x00000002, 0x00000004, 0x00000000, 0x00000004, 0x00000000, 0xf0f0f0f0, 0x0f0f0f0f, 0x0000ffff, + 0x00000000, 0x00000000, 0xffffffff, 0x00000014, 0x00000000, 0x00000124, 0x46580200, 0x0033fffe, + 0x42415443, 0x0000001c, 0x00000097, 0x46580200, 0x00000002, 0x0000001c, 0x20000100, 0x00000094, + 0x00000044, 0x00000002, 0x00000001, 0x0000004c, 0x0000005c, 0x0000006c, 0x00010002, 0x00000001, + 0x00000074, 0x00000084, 0x6576706f, 0x00317463, 0x00030001, 0x00040001, 0x00000001, 0x00000000, + 0x00000000, 0x80000000, 0xc00ccccd, 0x7f7fffff, 0x6576706f, 0x00327463, 0x00030001, 0x00040001, + 0x00000001, 0x00000000, 0x3f800000, 0x40000000, 0xc0400000, 0x40800000, 0x4d007874, 0x6f726369, + 0x74666f73, 0x29522820, 0x534c4820, 0x6853204c, 0x72656461, 0x6d6f4320, 0x656c6970, 0x2e392072, + 0x392e3932, 0x332e3235, 0x00313131, 0x0002fffe, 0x54494c43, 0x00000000, 0x000ffffe, 0x434c5846, + 0x00000001, 0x20500004, 0x00000002, 0x00000000, 0x00000002, 0x00000000, 0x00000000, 0x00000002, + 0x00000004, 0x00000000, 0x00000004, 0x00000000, 0xf0f0f0f0, 0x0f0f0f0f, 0x0000ffff, 0x00000000, + 0x00000000, 0xffffffff, 0x00000013, 0x00000000, 0x0000013c, 0x46580200, 0x0024fffe, 0x42415443, + 0x0000001c, 0x0000005b, 0x46580200, 0x00000001, 0x0000001c, 0x20000100, 0x00000058, 0x00000030, + 0x00000002, 0x00000001, 0x00000038, 0x00000048, 0x6576706f, 0x00317463, 0x00030001, 0x00040001, + 0x00000001, 0x00000000, 0x00000000, 0x80000000, 0xc00ccccd, 0x7f7fffff, 0x4d007874, 0x6f726369, + 0x74666f73, 0x29522820, 0x534c4820, 0x6853204c, 0x72656461, 0x6d6f4320, 0x656c6970, 0x2e392072, + 0x392e3932, 0x332e3235, 0x00313131, 0x0002fffe, 0x54494c43, 0x00000000, 0x0024fffe, 0x434c5846, + 0x00000004, 0x10700001, 0x00000001, 0x00000000, 0x00000002, 0x00000000, 0x00000000, 0x00000004, + 0x00000000, 0x10700001, 0x00000001, 0x00000000, 0x00000002, 0x00000001, 0x00000000, 0x00000004, + 0x00000001, 0x10700001, 0x00000001, 0x00000000, 0x00000002, 0x00000002, 0x00000000, 0x00000004, + 0x00000002, 0x10700001, 0x00000001, 0x00000000, 0x00000002, 0x00000003, 0x00000000, 0x00000004, + 0x00000003, 0xf0f0f0f0, 0x0f0f0f0f, 0x0000ffff, 0x00000000, 0x00000000, 0xffffffff, 0x00000012, + 0x00000000, 0x0000013c, 0x46580200, 0x0024fffe, 0x42415443, 0x0000001c, 0x0000005b, 0x46580200, + 0x00000001, 0x0000001c, 0x20000100, 0x00000058, 0x00000030, 0x00000002, 0x00000001, 0x00000038, + 0x00000048, 0x6576706f, 0x00317463, 0x00030001, 0x00040001, 0x00000001, 0x00000000, 0x00000000, + 0x80000000, 0xc00ccccd, 0x7f7fffff, 0x4d007874, 0x6f726369, 0x74666f73, 0x29522820, 0x534c4820, + 0x6853204c, 0x72656461, 0x6d6f4320, 0x656c6970, 0x2e392072, 0x392e3932, 0x332e3235, 0x00313131, + 0x0002fffe, 0x54494c43, 0x00000000, 0x0024fffe, 0x434c5846, 0x00000004, 0x10300001, 0x00000001, + 0x00000000, 0x00000002, 0x00000000, 0x00000000, 0x00000004, 0x00000000, 0x10300001, 0x00000001, + 0x00000000, 0x00000002, 0x00000001, 0x00000000, 0x00000004, 0x00000001, 0x10300001, 0x00000001, + 0x00000000, 0x00000002, 0x00000002, 0x00000000, 0x00000004, 0x00000002, 0x10300001, 0x00000001, + 0x00000000, 0x00000002, 0x00000003, 0x00000000, 0x00000004, 0x00000003, 0xf0f0f0f0, 0x0f0f0f0f, + 0x0000ffff, 0x00000000, 0x00000000, 0xffffffff, 0x00000001, 0x00000002, 0x00000134, 0x00000008, + 0x615f7370, 0x00007272, 0x46580200, 0x0024fffe, 0x42415443, 0x0000001c, 0x0000005b, 0x46580200, + 0x00000001, 0x0000001c, 0x00000100, 0x00000058, 0x00000030, 0x00000002, 0x00000001, 0x00000038, + 0x00000048, 0x56695f67, 0x00746365, 0x00020001, 0x00040001, 0x00000001, 0x00000000, 0x40800000, + 0x40400000, 0x40000000, 0x3f800000, 0x4d007874, 0x6f726369, 0x74666f73, 0x29522820, 0x534c4820, + 0x6853204c, 0x72656461, 0x6d6f4320, 0x656c6970, 0x2e392072, 0x392e3932, 0x332e3235, 0x00313131, + 0x0012fffe, 0x54494c43, 0x00000008, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0xbff00000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x000ffffe, 0x434c5846, 0x00000001, 0xa0400001, 0x00000002, + 0x00000000, 0x00000002, 0x00000003, 0x00000000, 0x00000001, 0x00000004, 0x00000000, 0x00000004, + 0x00000000, 0xf0f0f0f0, 0x0f0f0f0f, 0x0000ffff, 0x00000000, 0x00000000, 0xffffffff, 0x00000000, + 0x00000002, 0x00000134, 0x00000008, 0x615f7376, 0x00327272, 0x46580200, 0x0024fffe, 0x42415443, + 0x0000001c, 0x0000005b, 0x46580200, 0x00000001, 0x0000001c, 0x00000100, 0x00000058, 0x00000030, + 0x00000002, 0x00000001, 0x00000038, 0x00000048, 0x56695f67, 0x00746365, 0x00020001, 0x00040001, + 0x00000001, 0x00000000, 0x40800000, 0x40400000, 0x40000000, 0x3f800000, 0x4d007874, 0x6f726369, + 0x74666f73, 0x29522820, 0x534c4820, 0x6853204c, 0x72656461, 0x6d6f4320, 0x656c6970, 0x2e392072, + 0x392e3932, 0x332e3235, 0x00313131, 0x0012fffe, 0x54494c43, 0x00000008, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0xbff00000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x000ffffe, 0x434c5846, + 0x00000001, 0xa0400001, 0x00000002, 0x00000000, 0x00000002, 0x00000003, 0x00000000, 0x00000001, + 0x00000004, 0x00000000, 0x00000004, 0x00000000, 0xf0f0f0f0, 0x0f0f0f0f, 0x0000ffff, 0xffffffff, + 0x0000001f, 0x00000001, 0x00000001, 0x00000000, 0x000000e4, 0x46580200, 0x0026fffe, 0x42415443, + 0x0000001c, 0x00000063, 0x46580200, 0x00000001, 0x0000001c, 0x20000100, 0x00000060, 0x00000030, + 0x00000002, 0x00000001, 0x00000040, 0x00000050, 0x74636576, 0x6d61735f, 0x72656c70, 0xababab00, + 0x00030001, 0x00040001, 0x00000001, 0x00000000, 0x3f800000, 0x40000000, 0x40400000, 0x40800000, + 0x4d007874, 0x6f726369, 0x74666f73, 0x29522820, 0x534c4820, 0x6853204c, 0x72656461, 0x6d6f4320, + 0x656c6970, 0x2e392072, 0x392e3932, 0x332e3235, 0x00313131, 0x0002fffe, 0x54494c43, 0x00000000, + 0x000cfffe, 0x434c5846, 0x00000001, 0x10000001, 0x00000001, 0x00000000, 0x00000002, 0x00000001, + 0x00000000, 0x00000004, 0x00000000, 0xf0f0f0f0, 0x0f0f0f0f, 0x0000ffff, 0xffffffff, 0x0000001f, + 0x00000000, 0x00000001, 0x00000000, 0x000000e4, 0x46580200, 0x0026fffe, 0x42415443, 0x0000001c, + 0x00000063, 0x46580200, 0x00000001, 0x0000001c, 0x20000100, 0x00000060, 0x00000030, 0x00000002, + 0x00000001, 0x00000040, 0x00000050, 0x74636576, 0x6d61735f, 0x72656c70, 0xababab00, 0x00030001, + 0x00040001, 0x00000001, 0x00000000, 0x3f800000, 0x40000000, 0x40400000, 0x40800000, 0x4d007874, + 0x6f726369, 0x74666f73, 0x29522820, 0x534c4820, 0x6853204c, 0x72656461, 0x6d6f4320, 0x656c6970, + 0x2e392072, 0x392e3932, 0x332e3235, 0x00313131, 0x0002fffe, 0x54494c43, 0x00000000, 0x000cfffe, + 0x434c5846, 0x00000001, 0x10000001, 0x00000001, 0x00000000, 0x00000002, 0x00000000, 0x00000000, + 0x00000004, 0x00000000, 0xf0f0f0f0, 0x0f0f0f0f, 0x0000ffff, 0xffffffff, 0x0000001e, 0x00000000, + 0x00000002, 0x00000000, 0x000000f0, 0x46580200, 0x0026fffe, 0x42415443, 0x0000001c, 0x00000063, + 0x46580200, 0x00000001, 0x0000001c, 0x20000100, 0x00000060, 0x00000030, 0x00000002, 0x00000001, + 0x00000040, 0x00000050, 0x74636576, 0x6d61735f, 0x72656c70, 0xababab00, 0x00030001, 0x00040001, + 0x00000001, 0x00000000, 0x3f800000, 0x40000000, 0x40400000, 0x40800000, 0x4d007874, 0x6f726369, + 0x74666f73, 0x29522820, 0x534c4820, 0x6853204c, 0x72656461, 0x6d6f4320, 0x656c6970, 0x2e392072, + 0x392e3932, 0x332e3235, 0x00313131, 0x0002fffe, 0x54494c43, 0x00000000, 0x000ffffe, 0x434c5846, + 0x00000001, 0xa0400001, 0x00000002, 0x00000000, 0x00000002, 0x00000001, 0x00000000, 0x00000002, + 0x00000000, 0x00000000, 0x00000004, 0x00000000, 0xf0f0f0f0, 0x0f0f0f0f, 0x0000ffff, 0xffffffff, + 0x0000001e, 0x00000000, 0x00000001, 0x00000000, 0x000000dc, 0x46580200, 0x0024fffe, 0x42415443, + 0x0000001c, 0x0000005b, 0x46580200, 0x00000001, 0x0000001c, 0x20000100, 0x00000058, 0x00000030, + 0x00000002, 0x00000001, 0x00000038, 0x00000048, 0x56695f67, 0x00746365, 0x00020001, 0x00040001, + 0x00000001, 0x00000000, 0x40800000, 0x40400000, 0x40000000, 0x3f800000, 0x4d007874, 0x6f726369, + 0x74666f73, 0x29522820, 0x534c4820, 0x6853204c, 0x72656461, 0x6d6f4320, 0x656c6970, 0x2e392072, + 0x392e3932, 0x332e3235, 0x00313131, 0x0002fffe, 0x54494c43, 0x00000000, 0x000cfffe, 0x434c5846, + 0x00000001, 0x10000001, 0x00000001, 0x00000000, 0x00000002, 0x00000001, 0x00000000, 0x00000004, + 0x00000000, 0xf0f0f0f0, 0x0f0f0f0f, 0x0000ffff, 0xffffffff, 0x0000001e, 0x00000000, 0x00000000, + 0x00000001, 0x00000005, 0x31786574, 0x00000000, +}; +#define TEST_EFFECT_PRESHADER_VSHADER_POS 2991 +#define TEST_EFFECT_PRESHADER_VSHADER_LEN 13 + +#define test_effect_preshader_compare_shader_bytecode(a, b, c, d) \ + test_effect_preshader_compare_shader_bytecode_(__LINE__, a, b, c, d) +static void test_effect_preshader_compare_shader_bytecode_(unsigned int line, + const DWORD *bytecode, unsigned int bytecode_size, int expected_shader_index, BOOL todo) +{ + unsigned int i = 0; + + todo_wine_if(todo) + ok_(__FILE__, line)(!!bytecode, "NULL shader bytecode.\n"); + + if (!bytecode) + return; + + while (bytecode[i++] != 0x0000ffff) + ; + + if (!bytecode_size) + bytecode_size = i * sizeof(*bytecode); + else + ok(i * sizeof(*bytecode) == bytecode_size, "Unexpected byte code size %u.\n", bytecode_size); + + todo_wine_if(todo) + ok_(__FILE__, line)(!memcmp(bytecode, &test_effect_preshader_effect_blob[TEST_EFFECT_PRESHADER_VSHADER_POS + + expected_shader_index * TEST_EFFECT_PRESHADER_VSHADER_LEN], bytecode_size), + "Incorrect shader selected.\n"); +} + +#define test_effect_preshader_compare_shader(a, b, c) \ + test_effect_preshader_compare_shader_(__LINE__, a, b, c) +static void test_effect_preshader_compare_shader_(unsigned int line, IDirect3DDevice9 *device, + int expected_shader_index, BOOL todo) +{ + IDirect3DVertexShader9 *vshader; + void *byte_code; + unsigned int byte_code_size; + HRESULT hr; + + hr = IDirect3DDevice9_GetVertexShader(device, &vshader); + ok_(__FILE__, line)(hr == D3D_OK, "IDirect3DDevice9_GetVertexShader result %#x.\n", hr); + + todo_wine_if(todo) + ok_(__FILE__, line)(!!vshader, "Got NULL vshader.\n"); + if (!vshader) + return; + + hr = IDirect3DVertexShader9_GetFunction(vshader, NULL, &byte_code_size); + ok_(__FILE__, line)(hr == D3D_OK, "IDirect3DVertexShader9_GetFunction %#x.\n", hr); + ok_(__FILE__, line)(byte_code_size > 1, "Got unexpected byte code size %u.\n", byte_code_size); + + byte_code = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, byte_code_size); + hr = IDirect3DVertexShader9_GetFunction(vshader, byte_code, &byte_code_size); + ok_(__FILE__, line)(hr == D3D_OK, "Got result %#x.\n", hr); + + test_effect_preshader_compare_shader_bytecode_(line, byte_code, + byte_code_size, expected_shader_index, todo); + + HeapFree(GetProcessHeap(), 0, byte_code); + IDirect3DVertexShader9_Release(vshader); + } + +static const struct +{ + const char *comment; + BOOL todo[4]; + unsigned int result[4]; + unsigned int ulps; +} +test_effect_preshader_op_expected[] = +{ + {"1 / op", {FALSE, FALSE, FALSE, FALSE}, {0x7f800000, 0xff800000, 0xbee8ba2e, 0x00200000}}, + {"rsq", {FALSE, FALSE, FALSE, FALSE}, {0x7f800000, 0x7f800000, 0x3f2c985c, 0x1f800001}, 1}, + {"mul", {FALSE, FALSE, FALSE, FALSE}, {0x00000000, 0x80000000, 0x40d33334, 0x7f800000}}, + {"add", {FALSE, FALSE, FALSE, FALSE}, {0x3f800000, 0x40000000, 0xc0a66666, 0x7f7fffff}}, + {"lt", {FALSE, FALSE, FALSE, FALSE}, {0x3f800000, 0x3f800000, 0x00000000, 0x00000000}}, + {"ge", {FALSE, FALSE, FALSE, FALSE}, {0x00000000, 0x00000000, 0x3f800000, 0x3f800000}}, + {"neg", {FALSE, FALSE, FALSE, FALSE}, {0x80000000, 0x00000000, 0x400ccccd, 0xff7fffff}}, + {"rcp", {FALSE, FALSE, FALSE, FALSE}, {0x7f800000, 0xff800000, 0xbee8ba2e, 0x00200000}}, + + {"frac", {FALSE, FALSE, FALSE, FALSE}, {0x00000000, 0x00000000, 0x3f4ccccc, 0x00000000}}, + {"min", {FALSE, FALSE, FALSE, FALSE}, {0x00000000, 0x80000000, 0xc0400000, 0x40800000}}, + {"max", {FALSE, FALSE, FALSE, FALSE}, {0x3f800000, 0x40000000, 0xc00ccccd, 0x7f7fffff}}, +#if __x86_64__ + {"sin", {FALSE, FALSE, FALSE, FALSE}, {0x00000000, 0x80000000, 0xbf4ef99e, 0xbf0599b3}}, + {"cos", {FALSE, FALSE, FALSE, FALSE}, {0x3f800000, 0x3f800000, 0xbf16a803, 0x3f5a5f96}}, +#else + {"sin", {FALSE, FALSE, FALSE, TRUE}, {0x00000000, 0x80000000, 0xbf4ef99e, 0x3f792dc4}}, + {"cos", {FALSE, FALSE, FALSE, TRUE}, {0x3f800000, 0x3f800000, 0xbf16a803, 0xbe6acefc}}, +#endif + {"den mul",{FALSE, FALSE, FALSE, FALSE}, {0x7f800000, 0xff800000, 0xbb94f209, 0x000051ec}}, + {"dot", {FALSE, FALSE, FALSE, FALSE}, {0x00000000, 0x7f800000, 0x41f00000, 0x00000000}}, + {"prec", {FALSE, FALSE, TRUE, FALSE}, {0x2b8cbccc, 0x2c0cbccc, 0xac531800, 0x00000000}}, + + {"dotswiz", {FALSE, FALSE, FALSE, FALSE}, {0xc00ccccd, 0xc0d33334, 0xc10ccccd, 0}}, + {"reladdr", {FALSE, FALSE, FALSE, FALSE}, {0xc00ccccd, 0x3f800000, 0, 0x41200000}}, + {"reladdr2", {FALSE, FALSE, FALSE, FALSE}, {0, 0, 0x447ac000, 0x40000000}}, +}; + +enum expected_state_update +{ + EXPECTED_STATE_ZERO, + EXPECTED_STATE_UPDATED, + EXPECTED_STATE_ANYTHING +}; + +#define test_effect_preshader_op_results(a, b, c) test_effect_preshader_op_results_(__LINE__, a, b, c) +static void test_effect_preshader_op_results_(unsigned int line, IDirect3DDevice9 *device, + const enum expected_state_update *expected_state, const char *updated_param) +{ + static const D3DCOLORVALUE black = {0.0f}; + unsigned int i, j; + D3DLIGHT9 light; + const float *v; + HRESULT hr; + + for (i = 0; i < ARRAY_SIZE(test_effect_preshader_op_expected); ++i) + { + hr = IDirect3DDevice9_GetLight(device, i % 8, &light); + ok_(__FILE__, line)(hr == D3D_OK, "Got result %#x.\n", hr); + + v = i < 8 ? &light.Diffuse.r : (i < 16 ? &light.Ambient.r : &light.Specular.r); + if (!expected_state || expected_state[i] == EXPECTED_STATE_UPDATED) + { + for (j = 0; j < 4; ++j) + { + todo_wine_if(test_effect_preshader_op_expected[i].todo[j]) + ok_(__FILE__, line)(compare_float(v[j], + ((const float *)test_effect_preshader_op_expected[i].result)[j], + test_effect_preshader_op_expected[i].ulps), + "Operation %s, component %u, expected %#x, got %#x (%g).\n", + test_effect_preshader_op_expected[i].comment, j, + test_effect_preshader_op_expected[i].result[j], + ((const unsigned int *)v)[j], v[j]); + } + } + else if (expected_state[i] == EXPECTED_STATE_ZERO) + { + ok_(__FILE__, line)(!memcmp(v, &black, sizeof(black)), + "Parameter %s, test %d, operation %s, state updated unexpectedly.\n", + updated_param, i, test_effect_preshader_op_expected[i].comment); + } + } +} + +static const D3DXVECTOR4 fvect_filler = {-9999.0f, -9999.0f, -9999.0f, -9999.0f}; + +static void test_effect_preshader_clear_vconsts(IDirect3DDevice9 *device) +{ + unsigned int i; + HRESULT hr; + + for (i = 0; i < 256; ++i) + { + hr = IDirect3DDevice9_SetVertexShaderConstantF(device, i, &fvect_filler.x, 1); + ok(hr == D3D_OK, "Got result %#x.\n", hr); + } +} + +static const D3DXVECTOR4 test_effect_preshader_fvect_v[] = +{ + {0.0f, 0.0f, 0.0f, 0.0f}, + {0.0f, 0.0f, 0.0f, 0.0f}, + {0.0f, 0.0f, 0.0f, 0.0f}, + {1.0f, 2.0f, 3.0f, 0.0f}, + {4.0f, 0.0f, 0.0f, 0.0f}, + {5.0f, 6.0f, 7.0f, 8.0f}, + {1.0f, 2.0f, 3.0f, 0.0f}, + {4.0f, 0.0f, 0.0f, 0.0f}, + {5.0f, 6.0f, 7.0f, 8.0f}, + {9.0f, 10.0f, 11.0f, 0.0f}, + {12.0f, 0.0f, 0.0f, 0.0f}, + {13.0f, 14.0f, 15.0f, 16.0f}, + {11.0f, 12.0f, 13.0f, 0.0f}, + {21.0f, 22.0f, 23.0f, 0.0f}, + {31.0f, 32.0f, 33.0f, 0.0f}, + {41.0f, 42.0f, 43.0f, 0.0f}, + {11.0f, 21.0f, 31.0f, 0.0f}, + {12.0f, 22.0f, 32.0f, 0.0f}, + {13.0f, 23.0f, 33.0f, 0.0f}, + {14.0f, 24.0f, 34.0f, 0.0f}, + {11.0f, 12.0f, 13.0f, 14.0f}, + {21.0f, 22.0f, 23.0f, 24.0f}, + {31.0f, 32.0f, 33.0f, 34.0f}, + {11.0f, 21.0f, 31.0f, 41.0f}, + {12.0f, 22.0f, 32.0f, 42.0f}, + {13.0f, 23.0f, 33.0f, 43.0f}, + {9.0f, 10.0f, 11.0f, 0.0f}, + {12.0f, 0.0f, 0.0f, 0.0f}, + {13.0f, 14.0f, 15.0f, 16.0f}, + {92.0f, 0.0f, 0.0f, 0.0f}, + {93.0f, 0.0f, 0.0f, 0.0f}, + {0.0f, 0.0f, 0.0f, 0.0f}, + {91.0f, 0.0f, 0.0f, 0.0f}, + {4.0f, 5.0f, 6.0f, 7.0f}, +}; +#define TEST_EFFECT_BITMASK_BLOCK_SIZE (sizeof(unsigned int) * 8) + +#define test_effect_preshader_compare_vconsts(a, b, c) \ + test_effect_preshader_compare_vconsts_(__LINE__, a, b, c) +static void test_effect_preshader_compare_vconsts_(unsigned int line, IDirect3DDevice9 *device, + const unsigned int *const_updated_mask, const char *updated_param) +{ + HRESULT hr; + unsigned int i; + D3DXVECTOR4 fdata[ARRAY_SIZE(test_effect_preshader_fvect_v)]; + + hr = IDirect3DDevice9_GetVertexShaderConstantF(device, 0, &fdata[0].x, + ARRAY_SIZE(test_effect_preshader_fvect_v)); + ok_(__FILE__, line)(hr == D3D_OK, "Got result %#x.\n", hr); + + if (!const_updated_mask) + { + ok_(__FILE__, line)(!memcmp(fdata, test_effect_preshader_fvect_v, sizeof(test_effect_preshader_fvect_v)), + "Vertex shader float constants do not match.\n"); + } + else + { + for (i = 0; i < ARRAY_SIZE(test_effect_preshader_fvect_v); ++i) + { + if (const_updated_mask[i / TEST_EFFECT_BITMASK_BLOCK_SIZE] + & (1u << (i % TEST_EFFECT_BITMASK_BLOCK_SIZE))) + { + ok_(__FILE__, line)(!memcmp(&fdata[i], &test_effect_preshader_fvect_v[i], sizeof(fdata[i])), + "Vertex shader float constants do not match, expected (%g, %g, %g, %g), " + "got (%g, %g, %g, %g), parameter %s.\n", + test_effect_preshader_fvect_v[i].x, test_effect_preshader_fvect_v[i].y, + test_effect_preshader_fvect_v[i].z, test_effect_preshader_fvect_v[i].w, + fdata[i].x, fdata[i].y, fdata[i].z, fdata[i].w, updated_param); + } + else + { + ok_(__FILE__, line)(!memcmp(&fdata[i], &fvect_filler, sizeof(fdata[i])), + "Vertex shader float constants updated unexpectedly, parameter %s.\n", updated_param); + } + } + } + + for (i = ARRAY_SIZE(test_effect_preshader_fvect_v); i < 256; ++i) + { + hr = IDirect3DDevice9_GetVertexShaderConstantF(device, i, &fdata[0].x, 1); + ok_(__FILE__, line)(hr == D3D_OK, "Got result %#x.\n", hr); + ok_(__FILE__, line)(!memcmp(fdata, &fvect_filler, sizeof(fvect_filler)), + "Vertex shader float constants do not match.\n"); + } +} + +static const BOOL test_effect_preshader_bconsts[] = +{ + TRUE, FALSE, TRUE, FALSE, TRUE, TRUE +}; + +static void test_effect_preshader_clear_pbool_consts(IDirect3DDevice9 *device) +{ + BOOL bval; + unsigned int i; + HRESULT hr; + + for (i = 0; i < 16; ++i) + { + bval = i < ARRAY_SIZE(test_effect_preshader_bconsts) ? !test_effect_preshader_bconsts[i] : FALSE; + hr = IDirect3DDevice9_SetPixelShaderConstantB(device, i, &bval, 1); + ok(hr == D3D_OK, "Got result %#x.\n", hr); + } +} + +#define test_effect_preshader_compare_pbool_consts(a, b, c) \ + test_effect_preshader_compare_pbool_consts_(__LINE__, a, b, c) +static void test_effect_preshader_compare_pbool_consts_(unsigned int line, IDirect3DDevice9 *device, + const unsigned int *const_updated_mask, const char *updated_param) +{ + unsigned int i; + BOOL bdata[16]; + HRESULT hr; + + hr = IDirect3DDevice9_GetPixelShaderConstantB(device, 0, bdata, ARRAY_SIZE(bdata)); + ok_(__FILE__, line)(hr == D3D_OK, "Got result %#x.\n", hr); + + if (!const_updated_mask) + { + for (i = 0; i < ARRAY_SIZE(test_effect_preshader_bconsts); ++i) + { + /* The negation on both sides is actually needed, sometimes you + * get 0xffffffff instead of 1 on native. */ + ok_(__FILE__, line)(!bdata[i] == !test_effect_preshader_bconsts[i], + "Pixel shader boolean constants do not match, expected %#x, got %#x, i %u.\n", + test_effect_preshader_bconsts[i], bdata[i], i); + } + } + else + { + for (i = 0; i < ARRAY_SIZE(test_effect_preshader_bconsts); ++i) + { + if (const_updated_mask[i / TEST_EFFECT_BITMASK_BLOCK_SIZE] + & (1u << (i % TEST_EFFECT_BITMASK_BLOCK_SIZE))) + { + /* The negation on both sides is actually needed, sometimes + * you get 0xffffffff instead of 1 on native. */ + ok_(__FILE__, line)(!bdata[i] == !test_effect_preshader_bconsts[i], + "Pixel shader boolean constants do not match, expected %#x, got %#x, i %u, parameter %s.\n", + test_effect_preshader_bconsts[i], bdata[i], i, updated_param); + } + else + { + ok_(__FILE__, line)(bdata[i] == !test_effect_preshader_bconsts[i], + "Pixel shader boolean constants updated unexpectedly, parameter %s.\n", updated_param); + } + } + } + + for (; i < 16; ++i) + { + ok_(__FILE__, line)(!bdata[i], "Got result %#x, boolean register value %u.\n", hr, bdata[i]); + } +} + +static void test_effect_preshader(IDirect3DDevice9 *device) +{ + static const D3DXVECTOR4 test_effect_preshader_fvect_p[] = + { + {11.0f, 21.0f, 0.0f, 0.0f}, + {12.0f, 22.0f, 0.0f, 0.0f}, + {13.0f, 23.0f, 0.0f, 0.0f}, + {11.0f, 12.0f, 0.0f, 0.0f}, + {21.0f, 22.0f, 0.0f, 0.0f}, + {31.0f, 32.0f, 0.0f, 0.0f}, + {11.0f, 12.0f, 0.0f, 0.0f}, + {21.0f, 22.0f, 0.0f, 0.0f}, + {11.0f, 21.0f, 0.0f, 0.0f}, + {12.0f, 22.0f, 0.0f, 0.0f}, + {11.0f, 12.0f, 13.0f, 0.0f}, + {21.0f, 22.0f, 23.0f, 0.0f}, + {11.0f, 21.0f, 31.0f, 0.0f}, + {12.0f, 22.0f, 32.0f, 0.0f} + }; + static const int test_effect_preshader_iconsts[][4] = + { + {4, 3, 2, 1} + }; + static const D3DXVECTOR4 fvect1 = {28.0f, 29.0f, 30.0f, 31.0f}; + static const D3DXVECTOR4 fvect2 = {0.0f, 0.0f, 1.0f, 0.0f}; + static const int ivect_empty[4] = {-1, -1, -1, -1}; + HRESULT hr; + ID3DXEffect *effect; + D3DXHANDLE par; + unsigned int npasses; + DWORD value; + D3DXVECTOR4 fdata[ARRAY_SIZE(test_effect_preshader_fvect_p)]; + int idata[ARRAY_SIZE(test_effect_preshader_iconsts)][4]; + IDirect3DVertexShader9 *vshader; + unsigned int i; + D3DCAPS9 caps; + + hr = IDirect3DDevice9_GetDeviceCaps(device, &caps); + ok(SUCCEEDED(hr), "Failed to get device caps, hr %#x.\n", hr); + if (caps.VertexShaderVersion < D3DVS_VERSION(3, 0) + || caps.PixelShaderVersion < D3DPS_VERSION(3, 0)) + { + skip("Test requires VS >= 3 and PS >= 3, skipping.\n"); + return; + } + + hr = D3DXCreateEffect(device, test_effect_preshader_effect_blob, sizeof(test_effect_preshader_effect_blob), + NULL, NULL, 0, NULL, &effect, NULL); + ok(hr == D3D_OK, "Got result %#x.\n", hr); + + test_effect_preshader_clear_vconsts(device); + + for (i = 0; i < 224; ++i) + { + hr = IDirect3DDevice9_SetPixelShaderConstantF(device, i, &fvect_filler.x, 1); + ok(hr == D3D_OK, "Got result %#x.\n", hr); + } + + test_effect_preshader_clear_pbool_consts(device); + + for (i = 0; i < 16; ++i) + { + hr = IDirect3DDevice9_SetPixelShaderConstantI(device, i, ivect_empty, 1); + ok(hr == D3D_OK, "Got result %#x.\n", hr); + } + + hr = effect->lpVtbl->Begin(effect, &npasses, 0); + ok(hr == D3D_OK, "Got result %#x.\n", hr); + + par = effect->lpVtbl->GetParameterByName(effect, NULL, "g_Pos2"); + ok(par != NULL, "GetParameterByName failed.\n"); + + hr = effect->lpVtbl->SetVector(effect, par, &fvect1); + ok(hr == D3D_OK, "SetVector failed, hr %#x.\n", hr); + + hr = effect->lpVtbl->BeginPass(effect, 0); + ok(hr == D3D_OK, "Got result %#x.\n", hr); + + hr = effect->lpVtbl->BeginPass(effect, 0); + ok(hr == D3DERR_INVALIDCALL, "Got result %#x.\n", hr); + + hr = effect->lpVtbl->BeginPass(effect, 1); + ok(hr == D3DERR_INVALIDCALL, "Got result %#x.\n", hr); + + test_effect_preshader_compare_vconsts(device, NULL, NULL); + + hr = IDirect3DDevice9_GetPixelShaderConstantF(device, 0, &fdata[0].x, + ARRAY_SIZE(test_effect_preshader_fvect_p)); + ok(hr == D3D_OK, "Got result %#x.\n", hr); + ok(!memcmp(fdata, test_effect_preshader_fvect_p, sizeof(test_effect_preshader_fvect_p)), + "Pixel shader float constants do not match.\n"); + for (i = ARRAY_SIZE(test_effect_preshader_fvect_p); i < 224; ++i) + { + hr = IDirect3DDevice9_GetPixelShaderConstantF(device, i, &fdata[0].x, 1); + ok(hr == D3D_OK, "Got result %#x.\n", hr); + ok(!memcmp(fdata, &fvect_filler, sizeof(fvect_filler)), + "Pixel shader float constants do not match.\n"); + } + hr = IDirect3DDevice9_GetPixelShaderConstantI(device, 0, idata[0], + ARRAY_SIZE(test_effect_preshader_iconsts)); + ok(hr == D3D_OK, "Got result %#x.\n", hr); + ok(!memcmp(idata, test_effect_preshader_iconsts, sizeof(test_effect_preshader_iconsts)), + "Pixel shader integer constants do not match.\n"); + for (i = ARRAY_SIZE(test_effect_preshader_iconsts); i < 16; ++i) + { + hr = IDirect3DDevice9_GetPixelShaderConstantI(device, i, idata[0], 1); + ok(hr == D3D_OK, "Got result %#x.\n", hr); + ok(!memcmp(idata[0], ivect_empty, sizeof(ivect_empty)), + "Pixel shader integer constants do not match.\n"); + } + + test_effect_preshader_compare_pbool_consts(device, NULL, NULL); + + test_effect_preshader_op_results(device, NULL, NULL); + + hr = IDirect3DDevice9_GetSamplerState(device, 0, D3DSAMP_MINFILTER, &value); + ok(hr == D3D_OK, "Got result %#x.\n", hr); + ok(value == 3, "Unexpected sampler 0 minfilter %u.\n", value); + hr = IDirect3DDevice9_GetSamplerState(device, 0, D3DSAMP_MAGFILTER, &value); + ok(hr == D3D_OK, "Got result %#x.\n", hr); + todo_wine ok(value == 3, "Unexpected sampler 0 magfilter %u.\n", value); + + hr = IDirect3DDevice9_GetSamplerState(device, 1, D3DSAMP_MINFILTER, &value); + ok(hr == D3D_OK, "Got result %#x.\n", hr); + ok(value == 1, "Unexpected sampler 1 minfilter %u.\n", value); + hr = IDirect3DDevice9_GetSamplerState(device, 1, D3DSAMP_MAGFILTER, &value); + ok(hr == D3D_OK, "Got result %#x.\n", hr); + todo_wine + ok(value == 1, "Unexpected sampler 1 magfilter %u.\n", value); + + hr = IDirect3DDevice9_GetSamplerState(device, D3DVERTEXTEXTURESAMPLER0, D3DSAMP_MINFILTER, &value); + ok(hr == D3D_OK, "Got result %#x.\n", hr); + ok(value == 1, "Unexpected vertex sampler 0 minfilter %u.\n", value); + hr = IDirect3DDevice9_GetSamplerState(device, D3DVERTEXTEXTURESAMPLER0, D3DSAMP_MAGFILTER, &value); + ok(hr == D3D_OK, "Got result %#x.\n", hr); + todo_wine + ok(value == 1, "Unexpected vertex sampler 0 magfilter %u.\n", value); + + hr = IDirect3DDevice9_GetSamplerState(device, D3DVERTEXTEXTURESAMPLER1, D3DSAMP_MINFILTER, &value); + ok(hr == D3D_OK, "Got result %#x.\n", hr); + todo_wine + ok(value == 0, "Unexpected vertex sampler 1 minfilter %u.\n", value); + hr = IDirect3DDevice9_GetSamplerState(device, D3DVERTEXTEXTURESAMPLER1, D3DSAMP_MAGFILTER, &value); + ok(hr == D3D_OK, "Got result %#x.\n", hr); + todo_wine + ok(value == 0, "Unexpected vertex sampler 1 magfilter %u.\n", value); + + hr = IDirect3DDevice9_GetSamplerState(device, D3DVERTEXTEXTURESAMPLER2, D3DSAMP_MINFILTER, &value); + ok(hr == D3D_OK, "Got result %#x.\n", hr); + ok(value == 3, "Unexpected vertex sampler 2 minfilter %u.\n", value); + hr = IDirect3DDevice9_GetSamplerState(device, D3DVERTEXTEXTURESAMPLER2, D3DSAMP_MAGFILTER, &value); + ok(hr == D3D_OK, "Got result %#x.\n", hr); + todo_wine ok(value == 3, "Unexpected vertex sampler 2 magfilter %u.\n", value); + + hr = IDirect3DDevice9_GetRenderState(device, D3DRS_FOGDENSITY, &value); + ok(hr == D3D_OK, "Got result %#x.\n", hr); + ok(value == 0, "Unexpected fog density %g.\n", *(float *)&value); + hr = IDirect3DDevice9_GetRenderState(device, D3DRS_FOGSTART, &value); + ok(hr == D3D_OK, "Got result %#x.\n", hr); + ok(*(float *)&value == 4.0f, "Unexpected fog start %g.\n", *(float *)&value); + hr = IDirect3DDevice9_GetRenderState(device, D3DRS_POINTSCALE_A, &value); + ok(hr == D3D_OK, "Got result %#x.\n", hr); + ok(*(float *)&value == 4.0f, "Unexpected point scale A %g.\n", *(float *)&value); + hr = IDirect3DDevice9_GetRenderState(device, D3DRS_POINTSCALE_B, &value); + ok(hr == D3D_OK, "Got result %#x.\n", hr); + ok(*(float *)&value == 12.0f, "Unexpected point scale B %g.\n", *(float *)&value); + + hr = effect->lpVtbl->EndPass(effect); + + par = effect->lpVtbl->GetParameterByName(effect, NULL, "g_iVect"); + ok(par != NULL, "GetParameterByName failed.\n"); + hr = effect->lpVtbl->SetVector(effect, par, &fvect2); + ok(hr == D3D_OK, "SetVector failed, hr %#x.\n", hr); + hr = effect->lpVtbl->BeginPass(effect, 1); + ok(hr == D3D_OK, "Got result %#x.\n", hr); + + test_effect_preshader_compare_shader(device, 1, FALSE); + + hr = IDirect3DDevice9_SetVertexShader(device, NULL); + ok(hr == D3D_OK, "Got result %#x.\n", hr); + + hr = effect->lpVtbl->SetVector(effect, par, &fvect1); + ok(hr == D3D_OK, "SetVector failed, hr %#x.\n", hr); + hr = effect->lpVtbl->CommitChanges(effect); + ok(hr == D3D_OK, "Got result %#x.\n", hr); + hr = IDirect3DDevice9_GetVertexShader(device, &vshader); + ok(hr == D3D_OK, "Got result %#x.\n", hr); + ok(!vshader, "Incorrect shader selected.\n"); + + hr = effect->lpVtbl->EndPass(effect); + ok(hr == D3D_OK, "Got result %#x.\n", hr); + + hr = effect->lpVtbl->End(effect); + ok(hr == D3D_OK, "Got result %#x.\n", hr); + + effect->lpVtbl->Release(effect); + + hr = D3DXCreateEffect(device, test_effect_preshader_effect_blob, sizeof(test_effect_preshader_effect_blob), + NULL, NULL, 0, NULL, &effect, NULL); + ok(hr == D3D_OK, "Got result %#x.\n", hr); + + hr = effect->lpVtbl->Begin(effect, &npasses, D3DXFX_DONOTSAVESTATE); + ok(hr == D3D_OK, "Got result %#x.\n", hr); + + hr = effect->lpVtbl->BeginPass(effect, 0); + ok(hr == D3D_OK, "Got result %#x.\n", hr); + + hr = IDirect3DDevice9_GetSamplerState(device, 0, D3DSAMP_MINFILTER, &value); + ok(hr == D3D_OK, "Got result %#x.\n", hr); + ok(value == 3, "Unexpected sampler 0 minfilter %u.\n", value); + hr = IDirect3DDevice9_GetSamplerState(device, 0, D3DSAMP_MAGFILTER, &value); + ok(hr == D3D_OK, "Got result %#x.\n", hr); + todo_wine ok(value == 3, "Unexpected sampler 0 magfilter %u.\n", value); + + hr = IDirect3DDevice9_GetSamplerState(device, 1, D3DSAMP_MINFILTER, &value); + ok(hr == D3D_OK, "Got result %#x.\n", hr); + ok(value == 1, "Unexpected sampler 1 minfilter %u.\n", value); + hr = IDirect3DDevice9_GetSamplerState(device, 1, D3DSAMP_MAGFILTER, &value); + ok(hr == D3D_OK, "Got result %#x.\n", hr); + todo_wine + ok(value == 1, "Unexpected sampler 1 magfilter %u.\n", value); + + hr = IDirect3DDevice9_GetSamplerState(device, D3DVERTEXTEXTURESAMPLER0, D3DSAMP_MINFILTER, &value); + ok(hr == D3D_OK, "Got result %#x.\n", hr); + ok(value == 1, "Unexpected vertex sampler 0 minfilter %u.\n", value); + hr = IDirect3DDevice9_GetSamplerState(device, D3DVERTEXTEXTURESAMPLER0, D3DSAMP_MAGFILTER, &value); + ok(hr == D3D_OK, "Got result %#x.\n", hr); + todo_wine + ok(value == 1, "Unexpected vertex sampler 0 magfilter %u.\n", value); + + hr = IDirect3DDevice9_GetSamplerState(device, D3DVERTEXTEXTURESAMPLER1, D3DSAMP_MINFILTER, &value); + ok(hr == D3D_OK, "Got result %#x.\n", hr); + ok(value == 2, "Unexpected vertex sampler 1 minfilter %u.\n", value); + hr = IDirect3DDevice9_GetSamplerState(device, D3DVERTEXTEXTURESAMPLER1, D3DSAMP_MAGFILTER, &value); + ok(hr == D3D_OK, "Got result %#x.\n", hr); + todo_wine + ok(value == 2, "Unexpected vertex sampler 1 magfilter %u.\n", value); + + hr = IDirect3DDevice9_GetSamplerState(device, D3DVERTEXTEXTURESAMPLER2, D3DSAMP_MINFILTER, &value); + ok(hr == D3D_OK, "Got result %#x.\n", hr); + ok(value == 3, "Unexpected vertex sampler 2 minfilter %u.\n", value); + hr = IDirect3DDevice9_GetSamplerState(device, D3DVERTEXTEXTURESAMPLER2, D3DSAMP_MAGFILTER, &value); + ok(hr == D3D_OK, "Got result %#x.\n", hr); + todo_wine + ok(value == 3, "Unexpected vertex sampler 2 magfilter %u.\n", value); + + hr = effect->lpVtbl->EndPass(effect); + ok(hr == D3D_OK, "Got result %#x.\n", hr); + hr = effect->lpVtbl->End(effect); + ok(hr == D3D_OK, "Got result %#x.\n", hr); + effect->lpVtbl->Release(effect); +} + +/* + * fxc.exe /Tfx_2_0 + */ +#if 0 +float4 opvect1; +float4 opvect2; +float4 opvect3; + +technique tech0 +{ + pass p0 + { + LightEnable[0] = TRUE; + LightEnable[1] = TRUE; + LightEnable[2] = TRUE; + LightEnable[3] = TRUE; + LightEnable[4] = TRUE; + LightEnable[5] = TRUE; + LightEnable[6] = TRUE; + LightEnable[7] = TRUE; + LightType[0] = POINT; + LightType[1] = POINT; + LightType[2] = POINT; + LightType[3] = POINT; + LightType[4] = POINT; + LightType[5] = POINT; + LightType[6] = POINT; + LightType[7] = POINT; + + LightDiffuse[0] = exp(opvect1); + LightDiffuse[1] = log(opvect1); + LightDiffuse[2] = asin(opvect1); + LightDiffuse[3] = acos(opvect1); + LightDiffuse[4] = atan(opvect1); + LightDiffuse[5] = atan2(opvect1, opvect2); + LightDiffuse[6] = opvect1 * opvect2; + + /* Placeholder for 'div' instruction manually edited in binary blob. */ + LightDiffuse[7] = opvect1 * opvect2; + + /* Placeholder for 'cmp' instruction manually edited in binary blob. */ + LightAmbient[0] = opvect1 + opvect2 + opvect3; + } +} +#endif +static const DWORD test_effect_preshader_ops_blob[] = +{ + 0xfeff0901, 0x0000044c, 0x00000000, 0x00000003, 0x00000001, 0x00000030, 0x00000000, 0x00000000, + 0x00000004, 0x00000001, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000008, 0x6576706f, + 0x00317463, 0x00000003, 0x00000001, 0x00000068, 0x00000000, 0x00000000, 0x00000004, 0x00000001, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000008, 0x6576706f, 0x00327463, 0x00000003, + 0x00000001, 0x000000a0, 0x00000000, 0x00000000, 0x00000004, 0x00000001, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000008, 0x6576706f, 0x00337463, 0x00000001, 0x00000002, 0x00000002, + 0x00000000, 0x00000000, 0x00000000, 0x00000001, 0x00000001, 0x00000001, 0x00000002, 0x00000002, + 0x00000000, 0x00000000, 0x00000000, 0x00000001, 0x00000001, 0x00000001, 0x00000002, 0x00000002, + 0x00000000, 0x00000000, 0x00000000, 0x00000001, 0x00000001, 0x00000001, 0x00000002, 0x00000002, + 0x00000000, 0x00000000, 0x00000000, 0x00000001, 0x00000001, 0x00000001, 0x00000002, 0x00000002, + 0x00000000, 0x00000000, 0x00000000, 0x00000001, 0x00000001, 0x00000001, 0x00000002, 0x00000002, + 0x00000000, 0x00000000, 0x00000000, 0x00000001, 0x00000001, 0x00000001, 0x00000002, 0x00000002, + 0x00000000, 0x00000000, 0x00000000, 0x00000001, 0x00000001, 0x00000001, 0x00000002, 0x00000002, + 0x00000000, 0x00000000, 0x00000000, 0x00000001, 0x00000001, 0x00000001, 0x00000002, 0x00000002, + 0x00000000, 0x00000000, 0x00000000, 0x00000001, 0x00000001, 0x00000001, 0x00000002, 0x00000002, + 0x00000000, 0x00000000, 0x00000000, 0x00000001, 0x00000001, 0x00000001, 0x00000002, 0x00000002, + 0x00000000, 0x00000000, 0x00000000, 0x00000001, 0x00000001, 0x00000001, 0x00000002, 0x00000002, + 0x00000000, 0x00000000, 0x00000000, 0x00000001, 0x00000001, 0x00000001, 0x00000002, 0x00000002, + 0x00000000, 0x00000000, 0x00000000, 0x00000001, 0x00000001, 0x00000001, 0x00000002, 0x00000002, + 0x00000000, 0x00000000, 0x00000000, 0x00000001, 0x00000001, 0x00000001, 0x00000002, 0x00000002, + 0x00000000, 0x00000000, 0x00000000, 0x00000001, 0x00000001, 0x00000001, 0x00000002, 0x00000002, + 0x00000000, 0x00000000, 0x00000000, 0x00000001, 0x00000001, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000003, 0x00000002, 0x00000000, 0x00000000, 0x00000000, 0x00000004, 0x00000001, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000003, 0x00000002, 0x00000000, 0x00000000, + 0x00000000, 0x00000004, 0x00000001, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000003, + 0x00000002, 0x00000000, 0x00000000, 0x00000000, 0x00000004, 0x00000001, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000003, 0x00000002, 0x00000000, 0x00000000, 0x00000000, 0x00000004, + 0x00000001, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000003, 0x00000002, 0x00000000, + 0x00000000, 0x00000000, 0x00000004, 0x00000001, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000003, 0x00000002, 0x00000000, 0x00000000, 0x00000000, 0x00000004, 0x00000001, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000003, 0x00000002, 0x00000000, 0x00000000, 0x00000000, + 0x00000004, 0x00000001, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000003, 0x00000002, + 0x00000000, 0x00000000, 0x00000000, 0x00000004, 0x00000001, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000003, 0x00000002, 0x00000000, 0x00000000, 0x00000000, 0x00000004, 0x00000001, + 0x00000003, 0x00003070, 0x00000006, 0x68636574, 0x00000030, 0x00000003, 0x00000001, 0x00000001, + 0x00000001, 0x00000004, 0x00000020, 0x00000000, 0x00000000, 0x0000003c, 0x00000058, 0x00000000, + 0x00000000, 0x00000074, 0x00000090, 0x00000000, 0x00000000, 0x00000440, 0x00000000, 0x00000001, + 0x00000438, 0x00000000, 0x00000019, 0x00000091, 0x00000000, 0x000000b0, 0x000000ac, 0x00000091, + 0x00000001, 0x000000d0, 0x000000cc, 0x00000091, 0x00000002, 0x000000f0, 0x000000ec, 0x00000091, + 0x00000003, 0x00000110, 0x0000010c, 0x00000091, 0x00000004, 0x00000130, 0x0000012c, 0x00000091, + 0x00000005, 0x00000150, 0x0000014c, 0x00000091, 0x00000006, 0x00000170, 0x0000016c, 0x00000091, + 0x00000007, 0x00000190, 0x0000018c, 0x00000084, 0x00000000, 0x000001b0, 0x000001ac, 0x00000084, + 0x00000001, 0x000001d0, 0x000001cc, 0x00000084, 0x00000002, 0x000001f0, 0x000001ec, 0x00000084, + 0x00000003, 0x00000210, 0x0000020c, 0x00000084, 0x00000004, 0x00000230, 0x0000022c, 0x00000084, + 0x00000005, 0x00000250, 0x0000024c, 0x00000084, 0x00000006, 0x00000270, 0x0000026c, 0x00000084, + 0x00000007, 0x00000290, 0x0000028c, 0x00000085, 0x00000000, 0x000002bc, 0x000002ac, 0x00000085, + 0x00000001, 0x000002e8, 0x000002d8, 0x00000085, 0x00000002, 0x00000314, 0x00000304, 0x00000085, + 0x00000003, 0x00000340, 0x00000330, 0x00000085, 0x00000004, 0x0000036c, 0x0000035c, 0x00000085, + 0x00000005, 0x00000398, 0x00000388, 0x00000085, 0x00000006, 0x000003c4, 0x000003b4, 0x00000085, + 0x00000007, 0x000003f0, 0x000003e0, 0x00000087, 0x00000000, 0x0000041c, 0x0000040c, 0x00000000, + 0x00000009, 0x00000000, 0x00000000, 0xffffffff, 0x00000018, 0x00000000, 0x0000016c, 0x46580200, + 0x003afffe, 0x42415443, 0x0000001c, 0x000000b3, 0x46580200, 0x00000003, 0x0000001c, 0x20000100, + 0x000000b0, 0x00000058, 0x00000002, 0x00000001, 0x00000060, 0x00000070, 0x00000080, 0x00010002, + 0x00000001, 0x00000088, 0x00000070, 0x00000098, 0x00020002, 0x00000001, 0x000000a0, 0x00000070, + 0x6576706f, 0x00317463, 0x00030001, 0x00040001, 0x00000001, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x6576706f, 0x00327463, 0x00030001, 0x00040001, 0x00000001, 0x00000000, + 0x6576706f, 0x00337463, 0x00030001, 0x00040001, 0x00000001, 0x00000000, 0x4d007874, 0x6f726369, + 0x74666f73, 0x29522820, 0x534c4820, 0x6853204c, 0x72656461, 0x6d6f4320, 0x656c6970, 0x2e392072, + 0x392e3932, 0x332e3235, 0x00313131, 0x0002fffe, 0x54494c43, 0x00000000, + /* FXLC for LightAmbient[0] start. */ + 0x001afffe, 0x434c5846, + 0x00000001, /* Instruction count, set to 1. */ + 0x30000004, /* Operation code (bits 20-30) set to 'cmp' opcode 0x300. */ + 0x00000003, /* Input arguments count set to 3. */ + /* Argument 1. */ + 0x00000000, /* Relative addressing flag. */ + 0x00000002, /* Register table ("c", float constants). */ + 0x00000000, /* Register offset. */ + /* Argument 2. */ + 0x00000000, 0x00000002, 0x00000004, + /* Argument 3. */ + 0x00000000, 0x00000002, 0x00000008, + /* Output register. */ + 0x00000000, 0x00000004, 0x00000000, + /* End mark. */ + 0xf0f0f0f0, 0x0f0f0f0f, 0x0000ffff, + /* Padding to match placeholder length. */ + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + /* FXLC for LightAmbient[0] end. */ + 0x00000000, 0x00000000, 0xffffffff, 0x00000017, 0x00000000, 0x00000114, + 0x46580200, 0x002ffffe, 0x42415443, 0x0000001c, 0x00000087, 0x46580200, 0x00000002, 0x0000001c, + 0x20000100, 0x00000084, 0x00000044, 0x00000002, 0x00000001, 0x0000004c, 0x0000005c, 0x0000006c, + 0x00010002, 0x00000001, 0x00000074, 0x0000005c, 0x6576706f, 0x00317463, 0x00030001, 0x00040001, + 0x00000001, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x6576706f, 0x00327463, + 0x00030001, 0x00040001, 0x00000001, 0x00000000, 0x4d007874, 0x6f726369, 0x74666f73, 0x29522820, + 0x534c4820, 0x6853204c, 0x72656461, 0x6d6f4320, 0x656c6970, 0x2e392072, 0x392e3932, 0x332e3235, + 0x00313131, 0x0002fffe, 0x54494c43, 0x00000000, + /* FXLC for LightDiffuse[7] start. */ + 0x000ffffe, 0x434c5846, + 0x00000001, /* Instruction count. */ + 0x20800004, /* Operation code (bits 20-30) set to 'div' opcode 0x208. */ + 0x00000002, 0x00000000, 0x00000002, 0x00000000, 0x00000000, 0x00000002, 0x00000004, 0x00000000, + 0x00000004, 0x00000000, 0xf0f0f0f0, 0x0f0f0f0f, 0x0000ffff, + /* FXLC for LightDiffuse[7] end. */ + 0x00000000, 0x00000000, 0xffffffff, + 0x00000016, 0x00000000, 0x00000114, 0x46580200, 0x002ffffe, 0x42415443, 0x0000001c, 0x00000087, + 0x46580200, 0x00000002, 0x0000001c, 0x20000100, 0x00000084, 0x00000044, 0x00000002, 0x00000001, + 0x0000004c, 0x0000005c, 0x0000006c, 0x00010002, 0x00000001, 0x00000074, 0x0000005c, 0x6576706f, + 0x00317463, 0x00030001, 0x00040001, 0x00000001, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x6576706f, 0x00327463, 0x00030001, 0x00040001, 0x00000001, 0x00000000, 0x4d007874, + 0x6f726369, 0x74666f73, 0x29522820, 0x534c4820, 0x6853204c, 0x72656461, 0x6d6f4320, 0x656c6970, + 0x2e392072, 0x392e3932, 0x332e3235, 0x00313131, 0x0002fffe, 0x54494c43, 0x00000000, 0x000ffffe, + 0x434c5846, 0x00000001, 0x20500004, 0x00000002, 0x00000000, 0x00000002, 0x00000000, 0x00000000, + 0x00000002, 0x00000004, 0x00000000, 0x00000004, 0x00000000, 0xf0f0f0f0, 0x0f0f0f0f, 0x0000ffff, + 0x00000000, 0x00000000, 0xffffffff, 0x00000015, 0x00000000, 0x00000114, 0x46580200, 0x002ffffe, + 0x42415443, 0x0000001c, 0x00000087, 0x46580200, 0x00000002, 0x0000001c, 0x20000100, 0x00000084, + 0x00000044, 0x00000002, 0x00000001, 0x0000004c, 0x0000005c, 0x0000006c, 0x00010002, 0x00000001, + 0x00000074, 0x0000005c, 0x6576706f, 0x00317463, 0x00030001, 0x00040001, 0x00000001, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x6576706f, 0x00327463, 0x00030001, 0x00040001, + 0x00000001, 0x00000000, 0x4d007874, 0x6f726369, 0x74666f73, 0x29522820, 0x534c4820, 0x6853204c, + 0x72656461, 0x6d6f4320, 0x656c6970, 0x2e392072, 0x392e3932, 0x332e3235, 0x00313131, 0x0002fffe, + 0x54494c43, 0x00000000, 0x000ffffe, 0x434c5846, 0x00000001, 0x20600004, 0x00000002, 0x00000000, + 0x00000002, 0x00000000, 0x00000000, 0x00000002, 0x00000004, 0x00000000, 0x00000004, 0x00000000, + 0xf0f0f0f0, 0x0f0f0f0f, 0x0000ffff, 0x00000000, 0x00000000, 0xffffffff, 0x00000014, 0x00000000, + 0x000000dc, 0x46580200, 0x0024fffe, 0x42415443, 0x0000001c, 0x0000005b, 0x46580200, 0x00000001, + 0x0000001c, 0x20000100, 0x00000058, 0x00000030, 0x00000002, 0x00000001, 0x00000038, 0x00000048, + 0x6576706f, 0x00317463, 0x00030001, 0x00040001, 0x00000001, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x4d007874, 0x6f726369, 0x74666f73, 0x29522820, 0x534c4820, 0x6853204c, + 0x72656461, 0x6d6f4320, 0x656c6970, 0x2e392072, 0x392e3932, 0x332e3235, 0x00313131, 0x0002fffe, + 0x54494c43, 0x00000000, 0x000cfffe, 0x434c5846, 0x00000001, 0x10c00004, 0x00000001, 0x00000000, + 0x00000002, 0x00000000, 0x00000000, 0x00000004, 0x00000000, 0xf0f0f0f0, 0x0f0f0f0f, 0x0000ffff, + 0x00000000, 0x00000000, 0xffffffff, 0x00000013, 0x00000000, 0x000000dc, 0x46580200, 0x0024fffe, + 0x42415443, 0x0000001c, 0x0000005b, 0x46580200, 0x00000001, 0x0000001c, 0x20000100, 0x00000058, + 0x00000030, 0x00000002, 0x00000001, 0x00000038, 0x00000048, 0x6576706f, 0x00317463, 0x00030001, + 0x00040001, 0x00000001, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x4d007874, + 0x6f726369, 0x74666f73, 0x29522820, 0x534c4820, 0x6853204c, 0x72656461, 0x6d6f4320, 0x656c6970, + 0x2e392072, 0x392e3932, 0x332e3235, 0x00313131, 0x0002fffe, 0x54494c43, 0x00000000, 0x000cfffe, + 0x434c5846, 0x00000001, 0x10b00004, 0x00000001, 0x00000000, 0x00000002, 0x00000000, 0x00000000, + 0x00000004, 0x00000000, 0xf0f0f0f0, 0x0f0f0f0f, 0x0000ffff, 0x00000000, 0x00000000, 0xffffffff, + 0x00000012, 0x00000000, 0x000000dc, 0x46580200, 0x0024fffe, 0x42415443, 0x0000001c, 0x0000005b, + 0x46580200, 0x00000001, 0x0000001c, 0x20000100, 0x00000058, 0x00000030, 0x00000002, 0x00000001, + 0x00000038, 0x00000048, 0x6576706f, 0x00317463, 0x00030001, 0x00040001, 0x00000001, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x4d007874, 0x6f726369, 0x74666f73, 0x29522820, + 0x534c4820, 0x6853204c, 0x72656461, 0x6d6f4320, 0x656c6970, 0x2e392072, 0x392e3932, 0x332e3235, + 0x00313131, 0x0002fffe, 0x54494c43, 0x00000000, 0x000cfffe, 0x434c5846, 0x00000001, 0x10a00004, + 0x00000001, 0x00000000, 0x00000002, 0x00000000, 0x00000000, 0x00000004, 0x00000000, 0xf0f0f0f0, + 0x0f0f0f0f, 0x0000ffff, 0x00000000, 0x00000000, 0xffffffff, 0x00000011, 0x00000000, 0x0000013c, + 0x46580200, 0x0024fffe, 0x42415443, 0x0000001c, 0x0000005b, 0x46580200, 0x00000001, 0x0000001c, + 0x20000100, 0x00000058, 0x00000030, 0x00000002, 0x00000001, 0x00000038, 0x00000048, 0x6576706f, + 0x00317463, 0x00030001, 0x00040001, 0x00000001, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x4d007874, 0x6f726369, 0x74666f73, 0x29522820, 0x534c4820, 0x6853204c, 0x72656461, + 0x6d6f4320, 0x656c6970, 0x2e392072, 0x392e3932, 0x332e3235, 0x00313131, 0x0002fffe, 0x54494c43, + 0x00000000, 0x0024fffe, 0x434c5846, 0x00000004, 0x10600001, 0x00000001, 0x00000000, 0x00000002, + 0x00000000, 0x00000000, 0x00000004, 0x00000000, 0x10600001, 0x00000001, 0x00000000, 0x00000002, + 0x00000001, 0x00000000, 0x00000004, 0x00000001, 0x10600001, 0x00000001, 0x00000000, 0x00000002, + 0x00000002, 0x00000000, 0x00000004, 0x00000002, 0x10600001, 0x00000001, 0x00000000, 0x00000002, + 0x00000003, 0x00000000, 0x00000004, 0x00000003, 0xf0f0f0f0, 0x0f0f0f0f, 0x0000ffff, 0x00000000, + 0x00000000, 0xffffffff, 0x00000010, 0x00000000, 0x0000013c, 0x46580200, 0x0024fffe, 0x42415443, + 0x0000001c, 0x0000005b, 0x46580200, 0x00000001, 0x0000001c, 0x20000100, 0x00000058, 0x00000030, + 0x00000002, 0x00000001, 0x00000038, 0x00000048, 0x6576706f, 0x00317463, 0x00030001, 0x00040001, + 0x00000001, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x4d007874, 0x6f726369, + 0x74666f73, 0x29522820, 0x534c4820, 0x6853204c, 0x72656461, 0x6d6f4320, 0x656c6970, 0x2e392072, + 0x392e3932, 0x332e3235, 0x00313131, 0x0002fffe, 0x54494c43, 0x00000000, 0x0024fffe, 0x434c5846, + 0x00000004, 0x10500001, 0x00000001, 0x00000000, 0x00000002, 0x00000000, 0x00000000, 0x00000004, + 0x00000000, 0x10500001, 0x00000001, 0x00000000, 0x00000002, 0x00000001, 0x00000000, 0x00000004, + 0x00000001, 0x10500001, 0x00000001, 0x00000000, 0x00000002, 0x00000002, 0x00000000, 0x00000004, + 0x00000002, 0x10500001, 0x00000001, 0x00000000, 0x00000002, 0x00000003, 0x00000000, 0x00000004, + 0x00000003, 0xf0f0f0f0, 0x0f0f0f0f, 0x0000ffff, +}; + +static void test_effect_preshader_ops(IDirect3DDevice9 *device) +{ + static D3DLIGHT9 light; + const struct + { + const char *mnem; + unsigned int expected_result[4]; + unsigned int result_index; + float *result; + D3DXVECTOR4 opvect1, opvect2, opvect3; + unsigned int ulps; + BOOL todo[4]; + } + op_tests[] = + { + {"exp", {0x3f800000, 0x3f800000, 0x3e5edc66, 0x7f800000}, 0, &light.Diffuse.r, + {0.0f, -0.0f, -2.2f, 3.402823466e+38f}, {1.0f, 2.0f, -3.0f, 4.0f}}, + {"log", {0, 0x40000000, 0x3f9199b7, 0x43000000}, 1, &light.Diffuse.r, + {0.0f, 4.0f, -2.2f, 3.402823466e+38f}, {1.0f, 2.0f, -3.0f, 4.0f}}, + {"asin", {0xbe9c00ad, 0xffc00000, 0xffc00000, 0xffc00000}, 2, &light.Diffuse.r, + {-0.3f, 4.0f, -2.2f, 3.402823466e+38f}, {1.0f, 2.0f, -3.0f, 4.0f}}, + {"acos", {0x3ff01006, 0xffc00000, 0xffc00000, 0xffc00000}, 3, &light.Diffuse.r, + {-0.3f, 4.0f, -2.2f, 3.402823466e+38f}, {1.0f, 2.0f, -3.0f, 4.0f}}, + {"atan", {0xbe9539d4, 0x3fa9b465, 0xbf927420, 0x3fc90fdb}, 4, &light.Diffuse.r, + {-0.3f, 4.0f, -2.2f, 3.402823466e+38f}, {1.0f, 2.0f, -3.0f, 4.0f}}, + {"atan2 test #1", {0xbfc90fdb, 0x40490fdb, 0x80000000, 0x7fc00000}, 5, &light.Diffuse.r, + {-0.3f, 0.0f, -0.0f, NAN}, {0.0f, -0.0f, 0.0f, 1.0f}}, + {"atan2 test #2", {0xbfc90fdb, 0, 0xc0490fdb, 0}, 5, &light.Diffuse.r, + {-0.3f, 0.0f, -0.0f, -0.0f}, {-0.0f, 0.0f, -0.0f, 1.0f}}, + {"div", {0, 0, 0, 0}, 7, &light.Diffuse.r, + {-0.3f, 0.0f, -2.2f, NAN}, {0.0f, -0.0f, -3.0f, 1.0f}}, + {"cmp", {0x40a00000, 0x40000000, 0x40400000, 0x41000000}, 0, &light.Ambient.r, + {-0.3f, 0.0f, 2.2f, NAN}, {1.0f, 2.0f, 3.0f, 4.0f}, {5.0f, 6.0f, 7.0f, 8.0f}}, + {"0 * INF", {0xffc00000, 0xffc00000, 0xc0d33334, 0x7f800000}, 6, &light.Diffuse.r, + {0.0f, -0.0f, -2.2f, 3.402823466e+38f}, {INFINITY, INFINITY, 3.0f, 4.0f}}, + }; + unsigned int i, j, passes_count; + ID3DXEffect *effect; + HRESULT hr; + + hr = D3DXCreateEffect(device, test_effect_preshader_ops_blob, sizeof(test_effect_preshader_ops_blob), + NULL, NULL, 0, NULL, &effect, NULL); + ok(hr == D3D_OK, "Got result %#x.\n", hr); + hr = effect->lpVtbl->Begin(effect, &passes_count, 0); + ok(hr == D3D_OK, "Got result %#x.\n", hr); + hr = effect->lpVtbl->BeginPass(effect, 0); + ok(hr == D3D_OK, "Got result %#x.\n", hr); + + for (i = 0; i < ARRAY_SIZE(op_tests); ++i) + { + const float *result = op_tests[i].result; + const float *expected_float = (float *)op_tests[i].expected_result; + + hr = effect->lpVtbl->SetVector(effect, "opvect1", &op_tests[i].opvect1); + ok(hr == D3D_OK, "SetVector failed, hr %#x.\n", hr); + hr = effect->lpVtbl->SetVector(effect, "opvect2", &op_tests[i].opvect2); + ok(hr == D3D_OK, "SetVector failed, hr %#x.\n", hr); + hr = effect->lpVtbl->SetVector(effect, "opvect3", &op_tests[i].opvect3); + ok(hr == D3D_OK, "SetVector failed, hr %#x.\n", hr); + hr = effect->lpVtbl->CommitChanges(effect); + ok(hr == D3D_OK, "Got result %#x.\n", hr); + + hr = IDirect3DDevice9_GetLight(device, op_tests[i].result_index, &light); + ok(hr == D3D_OK, "Got result %#x.\n", hr); + for (j = 0; j < 4; ++j) + { + todo_wine_if(op_tests[i].todo[j]) + ok(compare_float(result[j], expected_float[j], op_tests[i].ulps), + "Operation %s, component %u, expected %#x (%.8e), got %#x (%.8e).\n", op_tests[i].mnem, + j, op_tests[i].expected_result[j], expected_float[j], + ((unsigned int *)result)[j], result[j]); + } + } + + hr = effect->lpVtbl->End(effect); + ok(hr == D3D_OK, "Got result %#x.\n", hr); + effect->lpVtbl->Release(effect); +} + +static void test_isparameterused_children(unsigned int line, ID3DXEffect *effect, + D3DXHANDLE tech, D3DXHANDLE param) +{ + D3DXPARAMETER_DESC desc; + D3DXHANDLE param_child; + unsigned int i, child_count; + HRESULT hr; + + hr = effect->lpVtbl->GetParameterDesc(effect, param, &desc); + ok_(__FILE__, line)(hr == D3D_OK, "GetParameterDesc failed, result %#x.\n", hr); + child_count = desc.Elements ? desc.Elements : desc.StructMembers; + for (i = 0; i < child_count; ++i) + { + param_child = desc.Elements ? effect->lpVtbl->GetParameterElement(effect, param, i) + : effect->lpVtbl->GetParameter(effect, param, i); + ok_(__FILE__, line)(!!param_child, "Failed getting child parameter %s[%u].\n", desc.Name, i); + ok_(__FILE__, line)(!effect->lpVtbl->IsParameterUsed(effect, param_child, tech), + "Unexpected IsParameterUsed() result for %s[%u].\n", desc.Name, i); + test_isparameterused_children(line, effect, tech, param_child); + } +} + +#ifdef __REACTOS__ +#define test_isparameterused_param_with_children(...) \ + test_isparameterused_param_with_children_(__LINE__, __VA_ARGS__) +#else +#define test_isparameterused_param_with_children(args...) \ + test_isparameterused_param_with_children_(__LINE__, args) +#endif +static void test_isparameterused_param_with_children_(unsigned int line, ID3DXEffect *effect, + ID3DXEffect *effect2, D3DXHANDLE tech, const char *name, BOOL expected_result) +{ + D3DXHANDLE param; + + ok_(__FILE__, line)(effect->lpVtbl->IsParameterUsed(effect, (D3DXHANDLE)name, tech) + == expected_result, "Unexpected IsParameterUsed() result for %s (referenced by name).\n", name); + + if (effect2) + param = effect2->lpVtbl->GetParameterByName(effect2, NULL, name); + else + param = effect->lpVtbl->GetParameterByName(effect, NULL, name); + ok_(__FILE__, line)(!!param, "GetParameterByName failed for %s.\n", name); + + ok_(__FILE__, line)(effect->lpVtbl->IsParameterUsed(effect, param, tech) == expected_result, + "Unexpected IsParameterUsed() result for %s (referenced by handle).\n", name); + + test_isparameterused_children(line, effect, tech, param); +} + +static void test_effect_isparameterused(IDirect3DDevice9 *device) +{ + static const struct + { + const char *name; + BOOL expected_result; + } + check_parameters[] = + { + {"g_Pos1", TRUE}, + {"g_Pos2", TRUE}, + {"g_Selector", TRUE}, + {"opvect1", TRUE}, + {"opvect2", TRUE}, + {"opvect3", TRUE}, + {"arr2", TRUE}, + {"vs_arr", TRUE}, + {"g_iVect", TRUE}, + {"vect_sampler", TRUE}, + {"tex1", TRUE}, + {"tex2", FALSE}, + {"sampler1", TRUE}, + {"ts1", TRUE}, + {"ts2", TRUE}, + {"ts3", TRUE}, + }; + ID3DXEffect *effect, *effect2; + HRESULT hr; + D3DXHANDLE tech; + unsigned int i; + + hr = D3DXCreateEffect(device, test_effect_preshader_effect_blob, sizeof(test_effect_preshader_effect_blob), + NULL, NULL, 0, NULL, &effect, NULL); + ok(hr == D3D_OK, "Got result %#x.\n", hr); + + tech = effect->lpVtbl->GetTechniqueByName(effect, "tech0"); + ok(!!tech, "GetTechniqueByName failed.\n"); + + for (i = 0; i < ARRAY_SIZE(check_parameters); ++i) + test_isparameterused_param_with_children(effect, NULL, tech, check_parameters[i].name, + check_parameters[i].expected_result); + + hr = D3DXCreateEffect(device, test_effect_preshader_effect_blob, sizeof(test_effect_preshader_effect_blob), + NULL, NULL, 0, NULL, &effect2, NULL); + ok(hr == D3D_OK, "Got result %#x.\n", hr); + + for (i = 0; i < ARRAY_SIZE(check_parameters); ++i) + test_isparameterused_param_with_children(effect, effect2, tech, check_parameters[i].name, + check_parameters[i].expected_result); + + effect2->lpVtbl->Release(effect2); + + hr = D3DXCreateEffect(device, test_effect_states_effect_blob, sizeof(test_effect_states_effect_blob), + NULL, NULL, 0, NULL, &effect2, NULL); + ok(hr == D3D_OK, "Got result %#x.\n", hr); + + test_isparameterused_param_with_children(effect, effect2, tech, "sampler1", TRUE); + effect2->lpVtbl->Release(effect2); + + effect->lpVtbl->Release(effect); +} + +static void test_effect_out_of_bounds_selector(IDirect3DDevice9 *device) +{ + ID3DXEffect *effect; + HRESULT hr; + D3DXHANDLE param; + int ivect[4]; + unsigned int passes_count; + IDirect3DVertexShader9 *vshader; + + hr = D3DXCreateEffect(device, test_effect_preshader_effect_blob, sizeof(test_effect_preshader_effect_blob), + NULL, NULL, 0, NULL, &effect, NULL); + + hr = effect->lpVtbl->Begin(effect, &passes_count, 0); + ok(hr == D3D_OK, "Got result %#x.\n", hr); + + ivect[0] = ivect[1] = ivect[3] = 1; + + param = effect->lpVtbl->GetParameterByName(effect, NULL, "g_iVect"); + ok(!!param, "GetParameterByName failed.\n"); + ivect[2] = 3; + hr = effect->lpVtbl->SetValue(effect, param, ivect, sizeof(ivect)); + ok(hr == D3D_OK, "Got result %#x.\n", hr); + + hr = effect->lpVtbl->BeginPass(effect, 0); + ok(hr == D3D_OK, "Got result %#x.\n", hr); + hr = effect->lpVtbl->EndPass(effect); + ok(hr == D3D_OK, "Got result %#x.\n", hr); + + hr = IDirect3DDevice9_SetVertexShader(device, NULL); + ok(hr == D3D_OK, "Got result %#x.\n", hr); + + hr = effect->lpVtbl->BeginPass(effect, 1); + ok(hr == E_FAIL, "Got result %#x.\n", hr); + + /* Second try reports success and selects array element used previously. + * Probably array index is not recomputed and previous index value is used. */ + hr = effect->lpVtbl->BeginPass(effect, 1); + ok(hr == D3D_OK, "Got result %#x.\n", hr); + test_effect_preshader_compare_shader(device, 2, FALSE); + + /* Confirm that array element selected is the previous good one and does not depend + * on computed (out of bound) index value. */ + ivect[2] = 1; + hr = effect->lpVtbl->SetValue(effect, param, ivect, sizeof(ivect)); + ok(hr == D3D_OK, "Got result %#x.\n", hr); + hr = IDirect3DDevice9_SetVertexShader(device, NULL); + ok(hr == D3D_OK, "Got result %#x.\n", hr); + hr = effect->lpVtbl->CommitChanges(effect); + ok(hr == D3D_OK, "Got result %#x.\n", hr); + test_effect_preshader_compare_shader(device, 1, FALSE); + hr = effect->lpVtbl->EndPass(effect); + ok(hr == D3D_OK, "Got result %#x.\n", hr); + ivect[2] = 3; + hr = effect->lpVtbl->SetValue(effect, param, ivect, sizeof(ivect)); + ok(hr == D3D_OK, "Got result %#x.\n", hr); + hr = IDirect3DDevice9_SetVertexShader(device, NULL); + ok(hr == D3D_OK, "Got result %#x.\n", hr); + hr = effect->lpVtbl->BeginPass(effect, 1); + ok(hr == E_FAIL, "Got result %#x.\n", hr); + hr = effect->lpVtbl->BeginPass(effect, 1); + ok(hr == D3D_OK, "Got result %#x.\n", hr); + test_effect_preshader_compare_shader(device, 1, FALSE); + + /* End and begin effect again to ensure it will not trigger array + * index recompute and error return from BeginPass. */ + hr = effect->lpVtbl->EndPass(effect); + ok(hr == D3D_OK, "Got result %#x.\n", hr); + hr = effect->lpVtbl->End(effect); + ok(hr == D3D_OK, "Got result %#x.\n", hr); + hr = effect->lpVtbl->Begin(effect, &passes_count, 0); + ok(hr == D3D_OK, "Got result %#x.\n", hr); + hr = effect->lpVtbl->BeginPass(effect, 1); + ok(hr == D3D_OK, "Got result %#x.\n", hr); + test_effect_preshader_compare_shader(device, 1, FALSE); + hr = effect->lpVtbl->EndPass(effect); + ok(hr == D3D_OK, "Got result %#x.\n", hr); + + + hr = IDirect3DDevice9_SetVertexShader(device, NULL); + ok(hr == D3D_OK, "Got result %#x.\n", hr); + + ivect[2] = -2; + hr = effect->lpVtbl->SetValue(effect, param, ivect, sizeof(ivect)); + ok(hr == D3D_OK, "Got result %#x.\n", hr); + + hr = effect->lpVtbl->BeginPass(effect, 1); + ok(hr == E_FAIL, "Got result %#x.\n", hr); + + hr = IDirect3DDevice9_GetVertexShader(device, &vshader); + ok(hr == D3D_OK, "Got result %#x.\n", hr); + ok(!vshader, "Got non NULL vshader.\n"); + + hr = effect->lpVtbl->BeginPass(effect, 1); + ok(hr == D3D_OK, "Got result %#x.\n", hr); + + test_effect_preshader_compare_shader(device, 1, FALSE); + + hr = effect->lpVtbl->EndPass(effect); + ok(hr == D3D_OK, "Got result %#x.\n", hr); + + ivect[2] = -1; + hr = effect->lpVtbl->SetValue(effect, param, ivect, sizeof(ivect)); + ok(hr == D3D_OK, "Got result %#x.\n", hr); + + hr = effect->lpVtbl->BeginPass(effect, 1); + ok(hr == D3D_OK, "Got result %#x.\n", hr); + + test_effect_preshader_compare_shader(device, 0, FALSE); + + hr = IDirect3DDevice9_SetVertexShader(device, NULL); + ok(hr == D3D_OK, "Got result %#x.\n", hr); + + ivect[2] = 3; + hr = effect->lpVtbl->SetValue(effect, param, ivect, sizeof(ivect)); + ok(hr == D3D_OK, "Got result %#x.\n", hr); + hr = effect->lpVtbl->CommitChanges(effect); + ok(hr == D3D_OK, "Got result %#x.\n", hr); + + hr = IDirect3DDevice9_GetVertexShader(device, &vshader); + ok(hr == D3D_OK, "Got result %#x.\n", hr); + ok(!vshader, "Got non NULL vshader.\n"); + + ivect[2] = -1; + hr = effect->lpVtbl->SetValue(effect, param, ivect, sizeof(ivect)); + ok(hr == D3D_OK, "Got result %#x.\n", hr); + hr = effect->lpVtbl->CommitChanges(effect); + ok(hr == D3D_OK, "Got result %#x.\n", hr); + + hr = IDirect3DDevice9_GetVertexShader(device, &vshader); + ok(hr == D3D_OK, "Got result %#x.\n", hr); + ok(!vshader, "Got non NULL vshader.\n"); + + ivect[2] = 1; + hr = effect->lpVtbl->SetValue(effect, param, ivect, sizeof(ivect)); + ok(hr == D3D_OK, "Got result %#x.\n", hr); + hr = effect->lpVtbl->CommitChanges(effect); + ok(hr == D3D_OK, "Got result %#x.\n", hr); + + test_effect_preshader_compare_shader(device, 1, FALSE); + + hr = effect->lpVtbl->EndPass(effect); + ok(hr == D3D_OK, "Got result %#x.\n", hr); + + hr = effect->lpVtbl->End(effect); + ok(hr == D3D_OK, "Got result %#x.\n", hr); + + effect->lpVtbl->Release(effect); +} + +static void test_effect_commitchanges(IDirect3DDevice9 *device) +{ + static const struct + { + const char *param_name; + enum expected_state_update state_updated[ARRAY_SIZE(test_effect_preshader_op_expected)]; + } + check_op_parameters[] = + { + {"opvect1", {EXPECTED_STATE_UPDATED, EXPECTED_STATE_UPDATED, EXPECTED_STATE_UPDATED, EXPECTED_STATE_UPDATED, + EXPECTED_STATE_UPDATED, EXPECTED_STATE_UPDATED, EXPECTED_STATE_UPDATED, EXPECTED_STATE_UPDATED, + EXPECTED_STATE_UPDATED, EXPECTED_STATE_UPDATED, EXPECTED_STATE_UPDATED, EXPECTED_STATE_UPDATED, + EXPECTED_STATE_UPDATED, EXPECTED_STATE_UPDATED, EXPECTED_STATE_UPDATED, EXPECTED_STATE_ANYTHING, + EXPECTED_STATE_UPDATED, EXPECTED_STATE_UPDATED, EXPECTED_STATE_UPDATED}}, + {"opvect2", {EXPECTED_STATE_UPDATED, EXPECTED_STATE_UPDATED, EXPECTED_STATE_UPDATED, EXPECTED_STATE_UPDATED, + EXPECTED_STATE_UPDATED, EXPECTED_STATE_UPDATED, EXPECTED_STATE_UPDATED, EXPECTED_STATE_UPDATED, + EXPECTED_STATE_UPDATED, EXPECTED_STATE_UPDATED, EXPECTED_STATE_UPDATED, EXPECTED_STATE_UPDATED, + EXPECTED_STATE_UPDATED, EXPECTED_STATE_UPDATED, EXPECTED_STATE_UPDATED, EXPECTED_STATE_ANYTHING, + EXPECTED_STATE_UPDATED, EXPECTED_STATE_UPDATED, EXPECTED_STATE_UPDATED}}, + {"opvect3", {EXPECTED_STATE_ZERO, EXPECTED_STATE_ZERO, EXPECTED_STATE_ZERO, EXPECTED_STATE_ZERO, + EXPECTED_STATE_ZERO, EXPECTED_STATE_ZERO, EXPECTED_STATE_ZERO, EXPECTED_STATE_UPDATED, + EXPECTED_STATE_ZERO, EXPECTED_STATE_ZERO, EXPECTED_STATE_ZERO, EXPECTED_STATE_ZERO, + EXPECTED_STATE_ZERO, EXPECTED_STATE_ZERO, EXPECTED_STATE_ZERO, EXPECTED_STATE_ANYTHING, + EXPECTED_STATE_ZERO, EXPECTED_STATE_ZERO, EXPECTED_STATE_ZERO}}, + }; + static const struct + { + const char *param_name; + const unsigned int const_updated_mask[(ARRAY_SIZE(test_effect_preshader_fvect_v) + + TEST_EFFECT_BITMASK_BLOCK_SIZE - 1) / TEST_EFFECT_BITMASK_BLOCK_SIZE]; + } + check_vconsts_parameters[] = + { + {"g_Selector", {0x00000000, 0x00000002}}, + {"g_Pos1", {0x80000000, 0x00000002}}, + {"g_Pos2", {0x00000000, 0x00000002}}, + {"m4x3column", {0x03800000, 0x00000000}}, + {"m3x4column", {0x000f0000, 0x00000000}}, + {"m4x3row", {0x0000f000, 0x00000000}}, + {"m3x4row", {0x00700000, 0x00000000}}, + {"ts1", {0x1c000000, 0x00000000}}, + {"ts2", {0x0000003f, 0x00000000}}, + {"arr1", {0x00000000, 0x00000001}}, + {"arr2", {0x60000000, 0x00000000}}, + {"ts3", {0x00000fc0, 0x00000000}}, + }; + static const struct + { + const char *param_name; + const unsigned int const_updated_mask[(ARRAY_SIZE(test_effect_preshader_bconsts) + + TEST_EFFECT_BITMASK_BLOCK_SIZE - 1) / TEST_EFFECT_BITMASK_BLOCK_SIZE]; + } + check_bconsts_parameters[] = + { + {"mb2x3row", {0x0000001f}}, + {"mb2x3column", {0x00000060}}, + }; + static const unsigned int const_no_update_mask[(ARRAY_SIZE(test_effect_preshader_fvect_v) + + TEST_EFFECT_BITMASK_BLOCK_SIZE - 1) / TEST_EFFECT_BITMASK_BLOCK_SIZE]; + static const D3DLIGHT9 light_filler = {D3DLIGHT_POINT}; + + ID3DXEffect *effect; + HRESULT hr; + D3DXHANDLE param; + unsigned int i, passes_count, value; + int ivect[4]; + D3DXVECTOR4 fvect; + IDirect3DVertexShader9 *vshader; + unsigned char buffer[256]; + + + hr = D3DXCreateEffect(device, test_effect_preshader_effect_blob, sizeof(test_effect_preshader_effect_blob), + NULL, NULL, 0, NULL, &effect, NULL); + ok(hr == D3D_OK, "Got result %#x.\n", hr); + + param = effect->lpVtbl->GetParameterByName(effect, NULL, "g_iVect"); + ok(!!param, "GetParameterByName failed.\n"); + + hr = effect->lpVtbl->Begin(effect, &passes_count, 0); + ok(hr == D3D_OK, "Got result %#x.\n", hr); + + hr = IDirect3DDevice9_SetVertexShader(device, NULL); + ok(hr == D3D_OK, "Got result %#x.\n", hr); + + hr = effect->lpVtbl->BeginPass(effect, 0); + ok(hr == D3D_OK, "Got result %#x.\n", hr); + + for (i = 0; i < ARRAY_SIZE(check_op_parameters); ++i) + { + unsigned int j; + + for (j = 0; j < 8; ++j) + { + hr = IDirect3DDevice9_SetLight(device, j, &light_filler); + ok(hr == D3D_OK, "Got result %#x, i %u, j %u.\n", hr, i, j); + } + param = effect->lpVtbl->GetParameterByName(effect, NULL, check_op_parameters[i].param_name); + ok(!!param, "Failed to get parameter (test %u).\n", i); + hr = effect->lpVtbl->GetValue(effect, param, &fvect, sizeof(fvect)); + ok(hr == D3D_OK, "Failed to get parameter value, hr %#x (test %u).\n", hr, i); + hr = effect->lpVtbl->SetValue(effect, param, &fvect, sizeof(fvect)); + ok(hr == D3D_OK, "Failed to set parameter value, hr %#x (test %u).\n", hr, i); + hr = effect->lpVtbl->CommitChanges(effect); + ok(hr == D3D_OK, "Failed to commit changes, hr %#x (test %u).\n", hr, i); + + test_effect_preshader_op_results(device, check_op_parameters[i].state_updated, + check_op_parameters[i].param_name); + } + + for (i = 0; i < ARRAY_SIZE(check_vconsts_parameters); ++i) + { + test_effect_preshader_clear_vconsts(device); + param = effect->lpVtbl->GetParameterByName(effect, NULL, check_vconsts_parameters[i].param_name); + ok(!!param, "GetParameterByName failed.\n"); + hr = effect->lpVtbl->GetValue(effect, param, buffer, sizeof(buffer)); + ok(hr == D3D_OK, "Got result %#x.\n", hr); + hr = effect->lpVtbl->SetValue(effect, param, buffer, sizeof(buffer)); + ok(hr == D3D_OK, "Got result %#x.\n", hr); + hr = effect->lpVtbl->CommitChanges(effect); + ok(hr == D3D_OK, "Got result %#x.\n", hr); + + test_effect_preshader_compare_vconsts(device, check_vconsts_parameters[i].const_updated_mask, + check_vconsts_parameters[i].param_name); + } + + for (i = 0; i < ARRAY_SIZE(check_bconsts_parameters); ++i) + { + test_effect_preshader_clear_pbool_consts(device); + param = effect->lpVtbl->GetParameterByName(effect, NULL, check_bconsts_parameters[i].param_name); + ok(!!param, "GetParameterByName failed.\n"); + hr = effect->lpVtbl->GetValue(effect, param, buffer, sizeof(buffer)); + ok(hr == D3D_OK, "Got result %#x.\n", hr); + hr = effect->lpVtbl->SetValue(effect, param, buffer, sizeof(buffer)); + ok(hr == D3D_OK, "Got result %#x.\n", hr); + hr = effect->lpVtbl->CommitChanges(effect); + ok(hr == D3D_OK, "Got result %#x.\n", hr); + + test_effect_preshader_compare_pbool_consts(device, check_bconsts_parameters[i].const_updated_mask, + check_bconsts_parameters[i].param_name); + } + + test_effect_preshader_clear_vconsts(device); + param = effect->lpVtbl->GetParameterByName(effect, NULL, "g_Selector"); + ok(!!param, "GetParameterByName failed.\n"); + fvect.x = fvect.y = fvect.z = fvect.w = 0.0f; + hr = effect->lpVtbl->SetVectorArray(effect, param, &fvect, 1); + ok(hr == D3D_OK, "Got result %#x.\n", hr); + hr = effect->lpVtbl->CommitChanges(effect); + ok(hr == D3D_OK, "Got result %#x.\n", hr); + test_effect_preshader_compare_vconsts(device, check_vconsts_parameters[0].const_updated_mask, + check_vconsts_parameters[0].param_name); + + test_effect_preshader_clear_vconsts(device); + param = effect->lpVtbl->GetParameterByName(effect, NULL, "arr2"); + ok(!!param, "GetParameterByName failed.\n"); + param = effect->lpVtbl->GetParameterElement(effect, param, 0); + ok(!!param, "GetParameterElement failed.\n"); + hr = effect->lpVtbl->SetFloat(effect, param, 92.0f); + ok(hr == D3D_OK, "Got result %#x.\n", hr); + hr = effect->lpVtbl->CommitChanges(effect); + ok(hr == D3D_OK, "Got result %#x.\n", hr); + test_effect_preshader_compare_vconsts(device, const_no_update_mask, + check_vconsts_parameters[10].param_name); + + test_effect_preshader_clear_vconsts(device); + param = effect->lpVtbl->GetParameterByName(effect, NULL, "arr2"); + ok(!!param, "GetParameterByName failed.\n"); + param = effect->lpVtbl->GetParameterElement(effect, param, 1); + ok(!!param, "GetParameterElement failed.\n"); + fvect.x = 93.0f; + hr = effect->lpVtbl->SetValue(effect, param, &fvect.x, sizeof(fvect.x)); + ok(hr == D3D_OK, "Got result %#x.\n", hr); + hr = effect->lpVtbl->CommitChanges(effect); + ok(hr == D3D_OK, "Got result %#x.\n", hr); + test_effect_preshader_compare_vconsts(device, check_vconsts_parameters[10].const_updated_mask, + check_vconsts_parameters[10].param_name); + + test_effect_preshader_clear_vconsts(device); + param = effect->lpVtbl->GetParameterByName(effect, NULL, "arr2"); + ok(!!param, "GetParameterByName failed.\n"); + fvect.x = 92.0f; + hr = effect->lpVtbl->SetFloatArray(effect, param, &fvect.x, 1); + ok(hr == D3D_OK, "Got result %#x.\n", hr); + hr = effect->lpVtbl->CommitChanges(effect); + ok(hr == D3D_OK, "Got result %#x.\n", hr); + test_effect_preshader_compare_vconsts(device, check_vconsts_parameters[10].const_updated_mask, + check_vconsts_parameters[10].param_name); + + test_effect_preshader_clear_vconsts(device); + param = effect->lpVtbl->GetParameterByName(effect, NULL, "arr2"); + ok(!!param, "GetParameterByName failed.\n"); + param = effect->lpVtbl->GetParameterElement(effect, param, 1); + ok(!!param, "GetParameterElement failed.\n"); + hr = effect->lpVtbl->SetInt(effect, param, 93); + ok(hr == D3D_OK, "Got result %#x.\n", hr); + hr = effect->lpVtbl->CommitChanges(effect); + ok(hr == D3D_OK, "Got result %#x.\n", hr); + test_effect_preshader_compare_vconsts(device, const_no_update_mask, + check_vconsts_parameters[10].param_name); + + test_effect_preshader_clear_vconsts(device); + param = effect->lpVtbl->GetParameterByName(effect, NULL, "g_Pos1"); + ok(!!param, "GetParameterByName failed.\n"); + fvect.x = fvect.y = fvect.z = fvect.w = 0.0f; + hr = effect->lpVtbl->SetVector(effect, param, &fvect); + ok(hr == D3D_OK, "Got result %#x.\n", hr); + hr = effect->lpVtbl->CommitChanges(effect); + ok(hr == D3D_OK, "Got result %#x.\n", hr); + test_effect_preshader_compare_vconsts(device, check_vconsts_parameters[1].const_updated_mask, + check_vconsts_parameters[1].param_name); + + test_effect_preshader_clear_vconsts(device); + param = effect->lpVtbl->GetParameterByName(effect, NULL, "ts1"); + ok(!!param, "GetParameterByName failed.\n"); + param = effect->lpVtbl->GetParameterElement(effect, param, 0); + ok(!!param, "GetParameterByName failed.\n"); + param = effect->lpVtbl->GetParameterByName(effect, param, "fv"); + ok(!!param, "GetParameterByName failed.\n"); + fvect.x = 12; + hr = effect->lpVtbl->SetValue(effect, param, &fvect.x, sizeof(float)); + ok(hr == D3D_OK, "Got result %#x.\n", hr); + hr = effect->lpVtbl->CommitChanges(effect); + ok(hr == D3D_OK, "Got result %#x.\n", hr); + test_effect_preshader_compare_vconsts(device, check_vconsts_parameters[7].const_updated_mask, + check_vconsts_parameters[7].param_name); + + *(float *)&value = 9999.0f; + hr = IDirect3DDevice9_SetRenderState(device, D3DRS_FOGDENSITY, value); + ok(hr == D3D_OK, "Got result %#x.\n", hr); + hr = IDirect3DDevice9_SetRenderState(device, D3DRS_FOGSTART, value); + ok(hr == D3D_OK, "Got result %#x.\n", hr); + hr = IDirect3DDevice9_SetRenderState(device, D3DRS_POINTSCALE_A, value); + ok(hr == D3D_OK, "Got result %#x.\n", hr); + hr = IDirect3DDevice9_SetRenderState(device, D3DRS_POINTSCALE_B, value); + ok(hr == D3D_OK, "Got result %#x.\n", hr); + test_effect_preshader_clear_vconsts(device); + param = effect->lpVtbl->GetParameterByName(effect, NULL, "ts2"); + ok(!!param, "GetParameterByName failed.\n"); + param = effect->lpVtbl->GetParameterElement(effect, param, 0); + ok(!!param, "GetParameterByName failed.\n"); + param = effect->lpVtbl->GetParameterByName(effect, param, "v1"); + ok(!!param, "GetParameterByName failed.\n"); + hr = effect->lpVtbl->GetValue(effect, param, &fvect, sizeof(float) * 3); + ok(hr == D3D_OK, "Got result %#x.\n", hr); + hr = effect->lpVtbl->SetValue(effect, param, &fvect, sizeof(float) * 3); + ok(hr == D3D_OK, "Got result %#x.\n", hr); + hr = effect->lpVtbl->CommitChanges(effect); + ok(hr == D3D_OK, "Got result %#x.\n", hr); + hr = IDirect3DDevice9_GetRenderState(device, D3DRS_FOGDENSITY, &value); + ok(hr == D3D_OK, "Got result %#x.\n", hr); + ok(value == 0, "Unexpected fog density %g.\n", *(float *)&value); + hr = IDirect3DDevice9_GetRenderState(device, D3DRS_FOGSTART, &value); + ok(hr == D3D_OK, "Got result %#x.\n", hr); + ok(*(float *)&value == 4.0f, "Unexpected fog start %g.\n", *(float *)&value); + hr = IDirect3DDevice9_GetRenderState(device, D3DRS_POINTSCALE_A, &value); + ok(hr == D3D_OK, "Got result %#x.\n", hr); + ok(*(float *)&value == 9999.0f, "Unexpected point scale A %g.\n", *(float *)&value); + hr = IDirect3DDevice9_GetRenderState(device, D3DRS_POINTSCALE_B, &value); + ok(hr == D3D_OK, "Got result %#x.\n", hr); + ok(*(float *)&value == 9999.0f, "Unexpected point scale B %g.\n", *(float *)&value); + test_effect_preshader_compare_vconsts(device, check_vconsts_parameters[8].const_updated_mask, + check_vconsts_parameters[8].param_name); + + *(float *)&value = 9999.0f; + hr = IDirect3DDevice9_SetRenderState(device, D3DRS_FOGDENSITY, value); + ok(hr == D3D_OK, "Got result %#x.\n", hr); + hr = IDirect3DDevice9_SetRenderState(device, D3DRS_FOGSTART, value); + ok(hr == D3D_OK, "Got result %#x.\n", hr); + hr = IDirect3DDevice9_SetRenderState(device, D3DRS_POINTSCALE_A, value); + ok(hr == D3D_OK, "Got result %#x.\n", hr); + hr = IDirect3DDevice9_SetRenderState(device, D3DRS_POINTSCALE_B, value); + ok(hr == D3D_OK, "Got result %#x.\n", hr); + test_effect_preshader_clear_vconsts(device); + param = effect->lpVtbl->GetParameterByName(effect, NULL, "ts3"); + ok(!!param, "GetParameterByName failed.\n"); + param = effect->lpVtbl->GetParameterByName(effect, param, "ts"); + ok(!!param, "GetParameterByName failed.\n"); + param = effect->lpVtbl->GetParameterElement(effect, param, 1); + ok(!!param, "GetParameterByName failed.\n"); + param = effect->lpVtbl->GetParameterByName(effect, param, "fv"); + ok(!!param, "GetParameterByName failed.\n"); + hr = effect->lpVtbl->GetValue(effect, param, &fvect.x, sizeof(float)); + ok(hr == D3D_OK, "Got result %#x.\n", hr); + hr = effect->lpVtbl->SetValue(effect, param, &fvect.x, sizeof(float)); + ok(hr == D3D_OK, "Got result %#x.\n", hr); + hr = effect->lpVtbl->CommitChanges(effect); + ok(hr == D3D_OK, "Got result %#x.\n", hr); + hr = IDirect3DDevice9_GetRenderState(device, D3DRS_FOGDENSITY, &value); + ok(hr == D3D_OK, "Got result %#x.\n", hr); + ok(*(float *)&value == 9999.0f, "Unexpected fog density %g.\n", *(float *)&value); + hr = IDirect3DDevice9_GetRenderState(device, D3DRS_FOGSTART, &value); + ok(hr == D3D_OK, "Got result %#x.\n", hr); + ok(*(float *)&value == 9999.0f, "Unexpected fog start %g.\n", *(float *)&value); + hr = IDirect3DDevice9_GetRenderState(device, D3DRS_POINTSCALE_A, &value); + ok(hr == D3D_OK, "Got result %#x.\n", hr); + ok(*(float *)&value == 4.0f, "Unexpected point scale A %g.\n", *(float *)&value); + hr = IDirect3DDevice9_GetRenderState(device, D3DRS_POINTSCALE_B, &value); + ok(hr == D3D_OK, "Got result %#x.\n", hr); + ok(*(float *)&value == 12.0f, "Unexpected point scale B %g.\n", *(float *)&value); + test_effect_preshader_compare_vconsts(device, check_vconsts_parameters[11].const_updated_mask, + check_vconsts_parameters[11].param_name); + + hr = IDirect3DDevice9_GetSamplerState(device, D3DVERTEXTEXTURESAMPLER0, D3DSAMP_MINFILTER, &value); + ok(hr == D3D_OK, "Got result %#x.\n", hr); + ok(value == 1, "Unexpected sampler 0 minfilter %u.\n", value); + hr = IDirect3DDevice9_GetSamplerState(device, D3DVERTEXTEXTURESAMPLER1, D3DSAMP_MINFILTER, &value); + ok(hr == D3D_OK, "Got result %#x.\n", hr); + todo_wine + ok(value == 0, "Unexpected sampler 1 minfilter %u.\n", value); + hr = IDirect3DDevice9_GetSamplerState(device, D3DVERTEXTEXTURESAMPLER2, D3DSAMP_MINFILTER, &value); + ok(hr == D3D_OK, "Got result %#x.\n", hr); + ok(value == 3, "Unexpected sampler 2 minfilter %u.\n", value); + + param = effect->lpVtbl->GetParameterByName(effect, NULL, "g_iVect"); + ok(!!param, "GetParameterByName failed.\n"); + ivect[0] = ivect[1] = ivect[2] = ivect[3] = 1; + hr = effect->lpVtbl->SetValue(effect, param, ivect, sizeof(ivect)); + ok(hr == D3D_OK, "Got result %#x.\n", hr); + + for (i = 0; i < 3; ++i) + { + hr = IDirect3DDevice9_SetSamplerState(device, D3DVERTEXTEXTURESAMPLER0 + i, D3DSAMP_MINFILTER, 0); + ok(hr == D3D_OK, "Got result %#x.\n", hr); + hr = IDirect3DDevice9_SetSamplerState(device, D3DVERTEXTEXTURESAMPLER0 + i, D3DSAMP_MAGFILTER, 0); + ok(hr == D3D_OK, "Got result %#x.\n", hr); + } + + hr = IDirect3DDevice9_SetSamplerState(device, 0, D3DSAMP_MINFILTER, 0); + ok(hr == D3D_OK, "Got result %#x.\n", hr); + hr = IDirect3DDevice9_SetSamplerState(device, 0, D3DSAMP_MAGFILTER, 0); + ok(hr == D3D_OK, "Got result %#x.\n", hr); + + hr = IDirect3DDevice9_SetVertexShader(device, NULL); + ok(hr == D3D_OK, "Got result %#x.\n", hr); + test_effect_preshader_clear_vconsts(device); + + hr = effect->lpVtbl->CommitChanges(effect); + ok(hr == D3D_OK, "Got result %#x.\n", hr); + + hr = IDirect3DDevice9_GetVertexShader(device, &vshader); + ok(hr == D3D_OK, "Got result %#x.\n", hr); + ok(!vshader, "Got non NULL vshader.\n"); + test_effect_preshader_compare_vconsts(device, const_no_update_mask, + "selector g_iVect"); + + hr = IDirect3DDevice9_GetSamplerState(device, D3DVERTEXTEXTURESAMPLER0, D3DSAMP_MINFILTER, &value); + ok(hr == D3D_OK, "Got result %#x.\n", hr); + ok(value == 0, "Unexpected sampler 0 minfilter %u.\n", value); + hr = IDirect3DDevice9_GetSamplerState(device, D3DVERTEXTEXTURESAMPLER1, D3DSAMP_MINFILTER, &value); + ok(hr == D3D_OK, "Got result %#x.\n", hr); + ok(value == 0, "Unexpected sampler 1 minfilter %u.\n", value); + + hr = IDirect3DDevice9_GetSamplerState(device, D3DVERTEXTEXTURESAMPLER2, D3DSAMP_MINFILTER, &value); + ok(hr == D3D_OK, "Got result %#x.\n", hr); + ok(value == 1, "Unexpected sampler 2 minfilter %u.\n", value); + hr = IDirect3DDevice9_GetSamplerState(device, D3DVERTEXTEXTURESAMPLER2, D3DSAMP_MAGFILTER, &value); + ok(hr == D3D_OK, "Got result %#x.\n", hr); + ok(value == 0, "Unexpected sampler 2 minfilter %u.\n", value); + hr = IDirect3DDevice9_GetSamplerState(device, 0, D3DSAMP_MINFILTER, &value); + ok(hr == D3D_OK, "Got result %#x.\n", hr); + ok(value == 1, "Unexpected sampler 0 minfilter %u.\n", value); + hr = IDirect3DDevice9_GetSamplerState(device, 0, D3DSAMP_MAGFILTER, &value); + ok(hr == D3D_OK, "Got result %#x.\n", hr); + ok(value == 0, "Unexpected sampler 0 minfilter %u.\n", value); + + ivect[3] = 2; + hr = effect->lpVtbl->SetValue(effect, param, ivect, sizeof(ivect)); + ok(hr == D3D_OK, "Got result %#x.\n", hr); + ivect[3] = 1; + hr = effect->lpVtbl->SetValue(effect, param, ivect, sizeof(ivect)); + ok(hr == D3D_OK, "Got result %#x.\n", hr); + hr = effect->lpVtbl->CommitChanges(effect); + ok(hr == D3D_OK, "Got result %#x.\n", hr); + hr = IDirect3DDevice9_GetVertexShader(device, &vshader); + ok(hr == D3D_OK, "Got result %#x.\n", hr); + ok(!vshader, "Got non NULL vshader.\n"); + test_effect_preshader_compare_vconsts(device, const_no_update_mask, + "selector g_iVect"); + ivect[3] = 2; + hr = effect->lpVtbl->SetValue(effect, param, ivect, sizeof(ivect)); + ok(hr == D3D_OK, "Got result %#x.\n", hr); + hr = effect->lpVtbl->CommitChanges(effect); + ok(hr == D3D_OK, "Got result %#x.\n", hr); + hr = IDirect3DDevice9_GetVertexShader(device, &vshader); + ok(hr == D3D_OK, "Got result %#x.\n", hr); + ok(!!vshader, "Got NULL vshader.\n"); + IDirect3DVertexShader9_Release(vshader); + hr = IDirect3DDevice9_GetVertexShaderConstantF(device, 0, &fvect.x, 1); + ok(hr == D3D_OK, "Got result %#x.\n", hr); + ok(fvect.x == 0.0f && fvect.y == 0.0f && fvect.z == 0.0f && fvect.w == 0.0f, + "Vertex shader float constants do not match.\n"); + hr = IDirect3DDevice9_SetVertexShaderConstantF(device, 0, &fvect_filler.x, 1); + ok(hr == D3D_OK, "Got result %#x.\n", hr); + test_effect_preshader_compare_vconsts(device, const_no_update_mask, + "selector g_iVect"); + ivect[3] = 1; + hr = effect->lpVtbl->SetValue(effect, param, ivect, sizeof(ivect)); + ok(hr == D3D_OK, "Got result %#x.\n", hr); + hr = effect->lpVtbl->CommitChanges(effect); + ok(hr == D3D_OK, "Got result %#x.\n", hr); + test_effect_preshader_compare_vconsts(device, NULL, NULL); + + hr = effect->lpVtbl->EndPass(effect); + ok(hr == D3D_OK, "Got result %#x.\n", hr); + + hr = effect->lpVtbl->End(effect); + ok(hr == D3D_OK, "Got result %#x.\n", hr); + + effect->lpVtbl->Release(effect); +} + +static void test_effect_preshader_relative_addressing(IDirect3DDevice9 *device) +{ + static const struct + { + D3DXVECTOR4 opvect2; + D3DXVECTOR4 g_ivect; + unsigned int expected[4]; + } + test_out_of_bounds_index[] = + { + {{1.0f, 2.0f, 3.0f, 4.0f}, {101.0f, 101.0f, 101.0f, 101.0f}, {0, 0x42ca0000, 0x3f800000, 0}}, + {{1.0f, 2.0f, 3.0f, 4.0f}, {3333.0f, 1094.0f, 2222.0f, 3333.0f}, + {0x447ac000, 0x45505000, 0x3f800000, 0}}, + {{1.0f, 2.0f, 3.0f, 4.0f}, {3333.0f, 1094.0f, 2222.0f, 1.0f}, + {0x447ac000, 0x3f800000, 0x447a8000, 0x453b9000}}, + {{1.0f, 2.0f, 3.0f, 4.0f}, {1.0f, 1094.0f, 2222.0f, 3333.0f}, + {0x447ac000, 0x45505000, 0x3f800000, 0x453ba000}}, + {{1.0f, 2.0f, 3.0f, 4.0f}, {1111.0f, 1094.0f, 2222.0f, 1111.0f}, + {0x447ac000, 0x448ae000, 0, 0}}, + {{1.0f, 2.0f, 3.0f, 4.0f}, {1111.0f, 1094.0f, 2222.0f, 3333.0f}, + {0x447ac000, 0x45505000, 0x3f800000, 0}}, + {{-1111.0f, 1094.0f, -2222.0f, -3333.0f}, {4.0f, 3.0f, 2.0f, 1.0f}, + {0x447ac000, 0x40800000, 0x447a8000, 0x453b9000}}, + {{1.0f, 2.0f, 3.0f, 4.0f}, {-1.0f, -1.0f, -1.0f, -1.0f}, {0, 0xbf800000, 0, 0}}, + {{1.0f, 2.0f, 3.0f, 4.0f}, {-2.0f, -2.0f, -2.0f, -2.0f}, {0, 0xc0000000, 0x459c4800, 0}}, + {{1.0f, 2.0f, 3.0f, 4.0f}, {-3.0f, -3.0f, -3.0f, -3.0f}, {0, 0xc0400000, 0x453b9000, 0}}, + {{1.0f, 2.0f, 3.0f, 4.0f}, {-4.0f, -4.0f, -4.0f, -4.0f}, {0, 0xc0800000, 0x44fa2000, 0}}, + {{1.0f, 2.0f, 3.0f, 4.0f}, {-5.0f, -5.0f, -5.0f, -5.0f}, {0, 0xc0a00000, 0x459c5000, 0}}, + {{1.0f, 2.0f, 3.0f, 4.0f}, {-6.0f, -6.0f, -6.0f, -6.0f}, {0, 0xc0c00000, 0x453ba000, 0xc1400000}}, + {{1.0f, 2.0f, 3.0f, 4.0f}, {-7.0f, -7.0f, -7.0f, -7.0f}, {0, 0xc0e00000, 0x44fa4000, 0x40400000}}, + {{1.0f, 2.0f, 3.0f, 4.0f}, {-8.0f, -8.0f, -8.0f, -8.0f}, {0, 0xc1000000, 0, 0x44fa6000}}, + {{1.0f, 2.0f, 3.0f, 4.0f}, {-9.0f, -9.0f, -9.0f, -9.0f}, {0, 0xc1100000, 0, 0}}, + {{1.0f, 2.0f, 3.0f, 4.0f}, {-10.0f, -10.0f, -10.0f, -10.0f}, {0, 0xc1200000, 0xc1200000, 0}}, + {{1.0f, 2.0f, 3.0f, 4.0f}, {-11.0f, -11.0f, -11.0f, -11.0f}, {0, 0xc1300000, 0x3f800000, 0}}, + {{1.0f, 2.0f, 3.0f, 4.0f}, {-12.0f, -12.0f, -12.0f, -12.0f}, {0, 0xc1400000, 0x447a4000, 0}}, + {{1.0f, 2.0f, 3.0f, 4.0f}, {5.0f, 5.0f, 5.0f, 5.0f}, {0, 0x40a00000, 0x3f800000, 0}}, + {{1.0f, 2.0f, 3.0f, 4.0f}, {-1111.0f, 1094.0f, -2222.0f, -3333.0f}, + {0x447ac000, 0xc5505000, 0x459c5000, 0x40000000}}, + {{1.0f, 2.0f, 3.0f, 4.0f}, {-3333.0f, 1094.0f, -2222.0f, -1111.0f}, + {0x447ac000, 0xc48ae000, 0x44fa4000, 0x3f800000}}, + {{1.0f, 2.0f, 3.0f, 4.0f}, {-3333.0f, 1094.0f, -2222.0f, -3333.0f}, + {0x447ac000, 0xc5505000, 0x459c5000, 0}}, + {{1.0f, 2.0f, 3.0f, 4.0f}, {-1111.0f, 1094.0f, -2222.0f, -1111.0f}, + {0x447ac000, 0xc48ae000, 0x44fa4000, 0x40400000}}, + }; + static const struct + { + unsigned int zw[2]; + } + expected_light_specular[] = + { + {{0, 0x44fa2000}}, + {{0x447a8000, 0x453b9000}}, + {{0x40000000, 0x459c4800}}, + {{0xbf800000, 0}}, + {{0x447a4000, 0}}, + {{0x3f800000, 0}}, + {{0xbf800000, 0}}, + {{0, 0}}, + {{0, 0x447a4000}}, + {{0x44fa4000, 0x3f800000}}, + {{0x453ba000, 0xbf800000}}, + {{0x459c5000, 0}}, + {{0x44fa2000, 0}}, + {{0x453b9000, 0}}, + {{0x459c4800, 0}}, + {{0, 0}}, + }; + static const struct + { + int index_value; + unsigned int expected[4]; + } + test_index_to_immediate_table[] = + { + {-1000000, {0, 0x40800000, 0x45bbd800, 0x41300000}}, + {-1001, {0x448d4000, 0x41300000, 0, 0}}, + {-32, {0x448d4000, 0x40800000, 0, 0}}, + {-31, {0x45843000, 0x41400000, 0, 0}}, + {-30, {0x46a64000, 0x41400000, 0x447a4000, 0x3f800000}}, + {-29, {0, 0x447a4000, 0x447a8000, 0x40000000}}, + {-28, {0, 0, 0x447ac000, 0x40400000}}, + {-27, {0, 0x3f800000, 0, 0}}, + {-26, {0, 0x41100000, 0x45bbd800, 0x41300000}}, + {-25, {0, 0x41300000, 0, 0}}, + {-24, {0, 0x41600000, 0, 0}}, + {-23, {0, 0, 0, 0}}, + {-22, {0, 0, 0, 0}}, + {-21, {0, 0x40a00000, 0, 0}}, + {-20, {0, 0x41500000, 0, 0}}, + {-19, {0, 0x41500000, 0, 0}}, + {-18, {0, 0xc1900000, 0, 0}}, + {-17, {0, 0, 0, 0}}, + {-16, {0, 0x40800000, 0, 0}}, + {-15, {0, 0x41400000, 0, 0}}, + {-14, {0, 0x41400000, 0, 0}}, + {-13, {0, 0x447a4000, 0x447a4000, 0x3f800000}}, + {-12, {0, 0, 0, 0}}, + {-11, {0, 0x3f800000, 0, 0}}, + {-10, {0, 0x41100000, 0, 0}}, + {-9, {0, 0x41300000, 0, 0}}, + {-8, {0, 0x41600000, 0, 0}}, + {-7, {0, 0, 0, 0}}, + {-6, {0, 0, 0, 0}}, + {-5, {0, 0x40a00000, 0, 0}}, + {-4, {0, 0x41500000, 0, 0}}, + {-3, {0, 0x41500000, 0, 0}}, + {-2, {0, 0xc0000000, 0, 0}}, + {-1, {0, 0, 0, 0}}, + {0, {0x45052000, 0x40800000, 0x447a4000, 0x3f800000}}, + {1, {0x467e6000, 0x41400000, 0x447a8000, 0x40000000}}, + {2, {0, 0x41400000, 0x447ac000, 0x40400000}}, + {3, {0, 0x447a4000, 0, 0}}, + {4, {0, 0, 0x45bbd800, 0x41300000}}, + {5, {0, 0x3f800000, 0, 0}}, + {6, {0, 0x41100000, 0, 0}}, + {7, {0, 0x41300000, 0, 0}}, + {8, {0, 0x41600000, 0, 0}}, + {9, {0, 0, 0, 0}}, + {10, {0, 0, 0, 0}}, + {11, {0, 0x40a00000, 0, 0}}, + {12, {0, 0x41500000, 0, 0}}, + {13, {0, 0x41500000, 0, 0}}, + {14, {0, 0x41600000, 0, 0}}, + {15, {0, 0, 0, 0}}, + {16, {0, 0x40800000, 0, 0}}, + {17, {0x45052000, 0x41400000, 0x447a4000, 0x3f800000}}, + {18, {0x467e6000, 0x41400000, 0x447a8000, 0x40000000}}, + {19, {0, 0x447a4000, 0x447ac000, 0x40400000}}, + {20, {0, 0, 0, 0}}, + {21, {0, 0x3f800000, 0x45bbd800, 0x41300000}}, + {22, {0, 0x41100000, 0, 0}}, + {23, {0, 0x41300000, 0, 0}}, + {24, {0, 0x41600000, 0, 0}}, + {25, {0, 0, 0, 0}}, + {26, {0, 0, 0, 0}}, + {27, {0, 0x40a00000, 0, 0}}, + {28, {0, 0x41500000, 0, 0}}, + {29, {0, 0x41500000, 0, 0}}, + {30, {0, 0x41f00000, 0, 0}}, + {31, {0, 0, 0, 0}}, + {1001, {0, 0, 0, 0}}, + {1000000, {0, 0x40800000, 0, 0}}, + }; + static const D3DLIGHT9 light_filler = {D3DLIGHT_POINT, {1.0f, 1.0f, 1.0f, 1.0f}, {1.0f, 1.0f, 1.0f, 1.0f}, + {1.0f, 1.0f, 1.0f, 1.0f}}; + unsigned int j, passes_count; + const unsigned int *expected; + const float *expected_float; + ID3DXEffect *effect; + D3DXVECTOR4 fvect; + D3DLIGHT9 light; + const float *v; + HRESULT hr; + int i; + + hr = D3DXCreateEffect(device, test_effect_preshader_effect_blob, sizeof(test_effect_preshader_effect_blob), + NULL, NULL, 0, NULL, &effect, NULL); + ok(hr == D3D_OK, "Got result %#x.\n", hr); + + hr = effect->lpVtbl->Begin(effect, &passes_count, 0); + ok(hr == D3D_OK, "Got result %#x.\n", hr); + hr = effect->lpVtbl->BeginPass(effect, 0); + ok(hr == D3D_OK, "Got result %#x.\n", hr); + + fvect.x = 1001.0f; fvect.y = 1002.0f; fvect.z = 1003.0f; fvect.w = 1004.0f; + hr = effect->lpVtbl->SetVector(effect, "opvect1", &fvect); + ok(hr == D3D_OK, "Got result %#x.\n", hr); + + fvect.x = 2001.0f; fvect.y = 2002.0f; fvect.z = 2003.0f; fvect.w = 2004.0f; + hr = effect->lpVtbl->SetVector(effect, "g_Selector[0]", &fvect); + ok(hr == D3D_OK, "Got result %#x.\n", hr); + + fvect.x = 3001.0f; fvect.y = 3002.0f; fvect.z = 3003.0f; fvect.w = 3004.0f; + hr = effect->lpVtbl->SetVector(effect, "g_Selector[1]", &fvect); + ok(hr == D3D_OK, "Got result %#x.\n", hr); + + v = &light.Specular.r; + for (i = 0; i < ARRAY_SIZE(test_out_of_bounds_index); ++i) + { + hr = effect->lpVtbl->SetVector(effect, "opvect2", &test_out_of_bounds_index[i].opvect2); + ok(hr == D3D_OK, "Got result %#x.\n", hr); + hr = effect->lpVtbl->SetVector(effect, "g_iVect", &test_out_of_bounds_index[i].g_ivect); + ok(hr == D3D_OK, "Got result %#x.\n", hr); + + hr = IDirect3DDevice9_SetLight(device, 1, &light_filler); + ok(hr == D3D_OK, "Got result %#x.\n", hr); + + hr = effect->lpVtbl->CommitChanges(effect); + ok(hr == D3D_OK, "Got result %#x.\n", hr); + + hr = IDirect3DDevice9_GetLight(device, 1, &light); + ok(hr == D3D_OK, "Got result %#x.\n", hr); + + expected = test_out_of_bounds_index[i].expected; + expected_float = (const float *)expected; + + for (j = 0; j < 4; ++j) + { + ok(compare_float(v[j], expected_float[j], 0), + "Test %d, component %u, expected %#x (%g), got %#x (%g).\n", + i, j, expected[j], expected_float[j], ((const unsigned int *)v)[j], v[j]); + } + } + + hr = effect->lpVtbl->SetVector(effect, "opvect2", &test_out_of_bounds_index[7].opvect2); + ok(hr == D3D_OK, "Got result %#x.\n", hr); + hr = effect->lpVtbl->SetVector(effect, "g_iVect", &test_out_of_bounds_index[7].g_ivect); + ok(hr == D3D_OK, "Got result %#x.\n", hr); + + hr = IDirect3DDevice9_SetLight(device, 1, &light_filler); + ok(hr == D3D_OK, "Got result %#x.\n", hr); + + fvect = test_out_of_bounds_index[7].g_ivect; + v = &light.Specular.b; + for (i = -100; i < 100; ++i) + { + fvect.w = i; + hr = effect->lpVtbl->SetVector(effect, "g_iVect", &fvect); + ok(hr == D3D_OK, "Got result %#x.\n", hr); + hr = effect->lpVtbl->CommitChanges(effect); + ok(hr == D3D_OK, "Got result %#x.\n", hr); + + hr = IDirect3DDevice9_GetLight(device, 1, &light); + ok(hr == D3D_OK, "Got result %#x.\n", hr); + + expected = expected_light_specular[(unsigned int)i % ARRAY_SIZE(expected_light_specular)].zw; + expected_float = (const float *)expected; + + for (j = 0; j < 2; ++j) + { + ok(compare_float(v[j], expected_float[j], 0), + "i %d, component %u, expected %#x (%g), got %#x (%g).\n", + i, j + 2, expected[j], expected_float[j], ((const unsigned int *)v)[j], v[j]); + } + } + + v = &light.Specular.r; + for (i = 0; i < ARRAY_SIZE(test_index_to_immediate_table); ++i) + { + fvect.x = fvect.y = fvect.z = fvect.w = test_index_to_immediate_table[i].index_value; + hr = effect->lpVtbl->SetVector(effect, "g_iVect", &fvect); + ok(hr == D3D_OK, "Got result %#x.\n", hr); + hr = effect->lpVtbl->CommitChanges(effect); + ok(hr == D3D_OK, "Got result %#x.\n", hr); + + hr = IDirect3DDevice9_GetLight(device, 2, &light); + ok(hr == D3D_OK, "Got result %#x.\n", hr); + + expected = test_index_to_immediate_table[i].expected; + expected_float = (const float *)expected; + + for (j = 0; j < 4; ++j) + { + ok(compare_float(v[j], expected_float[j], 0), + "Test %d, component %u, expected %#x (%g), got %#x (%g).\n", + i, j, expected[j], expected_float[j], ((const unsigned int *)v)[j], v[j]); + } + } + + hr = effect->lpVtbl->EndPass(effect); + ok(hr == D3D_OK, "Got result %#x.\n", hr); + hr = effect->lpVtbl->End(effect); + ok(hr == D3D_OK, "Got result %#x.\n", hr); + + effect->lpVtbl->Release(effect); +} + +struct test_state_manager_update +{ + unsigned int state_op; + DWORD param1; + DWORD param2; +}; + +struct test_manager +{ + ID3DXEffectStateManager ID3DXEffectStateManager_iface; + LONG ref; + + IDirect3DDevice9 *device; + struct test_state_manager_update *update_record; + unsigned int update_record_count; + unsigned int update_record_size; +}; + +#define INITIAL_UPDATE_RECORD_SIZE 64 + +static struct test_manager *impl_from_ID3DXEffectStateManager(ID3DXEffectStateManager *iface) +{ + return CONTAINING_RECORD(iface, struct test_manager, ID3DXEffectStateManager_iface); +} + +static void free_test_effect_state_manager(struct test_manager *state_manager) +{ + HeapFree(GetProcessHeap(), 0, state_manager->update_record); + state_manager->update_record = NULL; + + IDirect3DDevice9_Release(state_manager->device); +} + +static ULONG WINAPI test_manager_AddRef(ID3DXEffectStateManager *iface) +{ + struct test_manager *state_manager = impl_from_ID3DXEffectStateManager(iface); + + return InterlockedIncrement(&state_manager->ref); +} + +static ULONG WINAPI test_manager_Release(ID3DXEffectStateManager *iface) +{ + struct test_manager *state_manager = impl_from_ID3DXEffectStateManager(iface); + ULONG ref = InterlockedDecrement(&state_manager->ref); + + if (!ref) + { + free_test_effect_state_manager(state_manager); + HeapFree(GetProcessHeap(), 0, state_manager); + } + return ref; +} + +static HRESULT test_process_set_state(ID3DXEffectStateManager *iface, + unsigned int state_op, DWORD param1, DWORD param2) +{ + struct test_manager *state_manager = impl_from_ID3DXEffectStateManager(iface); + + if (state_manager->update_record_count == state_manager->update_record_size) + { + if (!state_manager->update_record_size) + { + state_manager->update_record_size = INITIAL_UPDATE_RECORD_SIZE; + state_manager->update_record = HeapAlloc(GetProcessHeap(), 0, + sizeof(*state_manager->update_record) * state_manager->update_record_size); + } + else + { + state_manager->update_record_size *= 2; + state_manager->update_record = HeapReAlloc(GetProcessHeap(), 0, state_manager->update_record, + sizeof(*state_manager->update_record) * state_manager->update_record_size); + } + } + state_manager->update_record[state_manager->update_record_count].state_op = state_op; + state_manager->update_record[state_manager->update_record_count].param1 = param1; + state_manager->update_record[state_manager->update_record_count].param2 = param2; + ++state_manager->update_record_count; + return D3D_OK; +} + +static HRESULT WINAPI test_manager_SetTransform(ID3DXEffectStateManager *iface, + D3DTRANSFORMSTATETYPE state, const D3DMATRIX *matrix) +{ + return test_process_set_state(iface, 0, state, 0); +} + +static HRESULT WINAPI test_manager_SetMaterial(ID3DXEffectStateManager *iface, + const D3DMATERIAL9 *material) +{ + return test_process_set_state(iface, 1, 0, 0); +} + +static HRESULT WINAPI test_manager_SetLight(ID3DXEffectStateManager *iface, + DWORD index, const D3DLIGHT9 *light) +{ + struct test_manager *state_manager = impl_from_ID3DXEffectStateManager(iface); + + IDirect3DDevice9_SetLight(state_manager->device, index, light); + return test_process_set_state(iface, 2, index, 0); +} + +static HRESULT WINAPI test_manager_LightEnable(ID3DXEffectStateManager *iface, + DWORD index, BOOL enable) +{ + struct test_manager *state_manager = impl_from_ID3DXEffectStateManager(iface); + + IDirect3DDevice9_LightEnable(state_manager->device, index, enable); + return test_process_set_state(iface, 3, index, 0); +} + +static HRESULT WINAPI test_manager_SetRenderState(ID3DXEffectStateManager *iface, + D3DRENDERSTATETYPE state, DWORD value) +{ + return test_process_set_state(iface, 4, state, 0); +} + +static HRESULT WINAPI test_manager_SetTexture(ID3DXEffectStateManager *iface, + DWORD stage, struct IDirect3DBaseTexture9 *texture) +{ + return test_process_set_state(iface, 5, stage, 0); +} + +static HRESULT WINAPI test_manager_SetTextureStageState(ID3DXEffectStateManager *iface, + DWORD stage, D3DTEXTURESTAGESTATETYPE type, DWORD value) +{ + return test_process_set_state(iface, 6, stage, type); +} + +static HRESULT WINAPI test_manager_SetSamplerState(ID3DXEffectStateManager *iface, + DWORD sampler, D3DSAMPLERSTATETYPE type, DWORD value) +{ + return test_process_set_state(iface, 7, sampler, type); +} + +static HRESULT WINAPI test_manager_SetNPatchMode(ID3DXEffectStateManager *iface, + FLOAT num_segments) +{ + return test_process_set_state(iface, 8, 0, 0); +} + +static HRESULT WINAPI test_manager_SetFVF(ID3DXEffectStateManager *iface, + DWORD format) +{ + return test_process_set_state(iface, 9, 0, 0); +} + +static HRESULT WINAPI test_manager_SetVertexShader(ID3DXEffectStateManager *iface, + struct IDirect3DVertexShader9 *shader) +{ + return test_process_set_state(iface, 10, 0, 0); +} + +static HRESULT WINAPI test_manager_SetVertexShaderConstantF(ID3DXEffectStateManager *iface, + UINT register_index, const FLOAT *constant_data, UINT register_count) +{ + return test_process_set_state(iface, 11, register_index, register_count); +} + +static HRESULT WINAPI test_manager_SetVertexShaderConstantI(ID3DXEffectStateManager *iface, + UINT register_index, const INT *constant_data, UINT register_count) +{ + return test_process_set_state(iface, 12, register_index, register_count); +} + +static HRESULT WINAPI test_manager_SetVertexShaderConstantB(ID3DXEffectStateManager *iface, + UINT register_index, const BOOL *constant_data, UINT register_count) +{ + return test_process_set_state(iface, 13, register_index, register_count); +} + +static HRESULT WINAPI test_manager_SetPixelShader(ID3DXEffectStateManager *iface, + struct IDirect3DPixelShader9 *shader) +{ + return test_process_set_state(iface, 14, 0, 0); +} + +static HRESULT WINAPI test_manager_SetPixelShaderConstantF(ID3DXEffectStateManager *iface, + UINT register_index, const FLOAT *constant_data, UINT register_count) +{ + return test_process_set_state(iface, 15, register_index, register_count); +} + +static HRESULT WINAPI test_manager_SetPixelShaderConstantI(ID3DXEffectStateManager *iface, + UINT register_index, const INT *constant_data, UINT register_count) +{ + return test_process_set_state(iface, 16, register_index, register_count); +} + +static HRESULT WINAPI test_manager_SetPixelShaderConstantB(ID3DXEffectStateManager *iface, + UINT register_index, const BOOL *constant_data, UINT register_count) +{ + return test_process_set_state(iface, 17, register_index, register_count); +} + +static void test_effect_state_manager_init(struct test_manager *state_manager, + IDirect3DDevice9 *device) +{ + static const struct ID3DXEffectStateManagerVtbl test_ID3DXEffectStateManager_Vtbl = + { + /*** IUnknown methods ***/ + NULL, + test_manager_AddRef, + test_manager_Release, + /*** ID3DXEffectStateManager methods ***/ + test_manager_SetTransform, + test_manager_SetMaterial, + test_manager_SetLight, + test_manager_LightEnable, + test_manager_SetRenderState, + test_manager_SetTexture, + test_manager_SetTextureStageState, + test_manager_SetSamplerState, + test_manager_SetNPatchMode, + test_manager_SetFVF, + test_manager_SetVertexShader, + test_manager_SetVertexShaderConstantF, + test_manager_SetVertexShaderConstantI, + test_manager_SetVertexShaderConstantB, + test_manager_SetPixelShader, + test_manager_SetPixelShaderConstantF, + test_manager_SetPixelShaderConstantI, + test_manager_SetPixelShaderConstantB, + }; + + state_manager->ID3DXEffectStateManager_iface.lpVtbl = &test_ID3DXEffectStateManager_Vtbl; + state_manager->ref = 1; + + IDirect3DDevice9_AddRef(device); + state_manager->device = device; +} + +static const char *test_effect_state_manager_state_names[] = +{ + "SetTransform", + "SetMaterial", + "SetLight", + "LightEnable", + "SetRenderState", + "SetTexture", + "SetTextureStageState", + "SetSamplerState", + "SetNPatchMode", + "SetFVF", + "SetVertexShader", + "SetVertexShaderConstantF", + "SetVertexShaderConstantI", + "SetVertexShaderConstantB", + "SetPixelShader", + "SetPixelShaderConstantF", + "SetPixelShaderConstantI", + "SetPixelShaderConstantB", +}; + +static int compare_update_record(const void *a, const void *b) +{ + const struct test_state_manager_update *r1 = (const struct test_state_manager_update *)a; + const struct test_state_manager_update *r2 = (const struct test_state_manager_update *)b; + + if (r1->state_op != r2->state_op) + return r1->state_op - r2->state_op; + if (r1->param1 != r2->param1) + return r1->param1 - r2->param1; + return r1->param2 - r2->param2; +} + +static void test_effect_state_manager(IDirect3DDevice9 *device) +{ + static const struct test_state_manager_update expected_updates[] = + { + {2, 0, 0}, + {2, 1, 0}, + {2, 2, 0}, + {2, 3, 0}, + {2, 4, 0}, + {2, 5, 0}, + {2, 6, 0}, + {2, 7, 0}, + {3, 0, 0}, + {3, 1, 0}, + {3, 2, 0}, + {3, 3, 0}, + {3, 4, 0}, + {3, 5, 0}, + {3, 6, 0}, + {3, 7, 0}, + {4, 28, 0}, + {4, 36, 0}, + {4, 38, 0}, + {4, 158, 0}, + {4, 159, 0}, + {5, 0, 0}, + {5, 259, 0}, + {7, 0, 5}, + {7, 0, 6}, + {7, 1, 5}, + {7, 1, 6}, + {7, 257, 5}, + {7, 257, 6}, + {7, 258, 5}, + {7, 258, 6}, + {7, 259, 5}, + {7, 259, 6}, + {10, 0, 0}, + {11, 0, 34}, + {14, 0, 0}, + {15, 0, 14}, + {16, 0, 1}, + {17, 0, 6}, + }; + static D3DLIGHT9 light_filler = + {D3DLIGHT_DIRECTIONAL, {0.5f, 0.5f, 0.5f, 0.5f}, {0.5f, 0.5f, 0.5f, 0.5f}, {0.5f, 0.5f, 0.5f, 0.5f}}; + struct test_manager *state_manager; + unsigned int passes_count, i, n; + ID3DXEffect *effect; + ULONG refcount; + HRESULT hr; + + state_manager = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*state_manager)); + test_effect_state_manager_init(state_manager, device); + + for (i = 0; i < 8; ++i) + { + hr = IDirect3DDevice9_SetLight(device, i, &light_filler); + ok(hr == D3D_OK, "Got result %#x.\n", hr); + } + + hr = D3DXCreateEffect(device, test_effect_preshader_effect_blob, sizeof(test_effect_preshader_effect_blob), + NULL, NULL, 0, NULL, &effect, NULL); + ok(hr == D3D_OK, "Got result %#x.\n", hr); + + hr = effect->lpVtbl->SetStateManager(effect, &state_manager->ID3DXEffectStateManager_iface); + ok(hr == D3D_OK, "Got result %#x.\n", hr); + + hr = effect->lpVtbl->Begin(effect, &passes_count, 0); + ok(hr == D3D_OK, "Got result %#x.\n", hr); + + hr = effect->lpVtbl->BeginPass(effect, 0); + ok(hr == D3D_OK, "Got result %#x.\n", hr); + + hr = effect->lpVtbl->EndPass(effect); + ok(hr == D3D_OK, "Got result %#x.\n", hr); + + hr = effect->lpVtbl->End(effect); + ok(hr == D3D_OK, "Got result %#x.\n", hr); + + effect->lpVtbl->Release(effect); + + qsort(state_manager->update_record, state_manager->update_record_count, + sizeof(*state_manager->update_record), compare_update_record); + + ok(ARRAY_SIZE(expected_updates) == state_manager->update_record_count, + "Got %u update records.\n", state_manager->update_record_count); + n = min(ARRAY_SIZE(expected_updates), state_manager->update_record_count); + for (i = 0; i < n; ++i) + { + ok(!memcmp(&expected_updates[i], &state_manager->update_record[i], + sizeof(expected_updates[i])), + "Update record mismatch, expected %s, %u, %u, got %s, %u, %u.\n", + test_effect_state_manager_state_names[expected_updates[i].state_op], + expected_updates[i].param1, expected_updates[i].param2, + test_effect_state_manager_state_names[state_manager->update_record[i].state_op], + state_manager->update_record[i].param1, state_manager->update_record[i].param2); + } + + for (i = 0; i < 8; ++i) + { + D3DLIGHT9 light; + + hr = IDirect3DDevice9_GetLight(device, i, &light); + ok(hr == D3D_OK, "Got result %#x.\n", hr); + ok(!memcmp(&light, &light_filler, sizeof(light)), "Light %u mismatch.\n", i); + } + + refcount = state_manager->ID3DXEffectStateManager_iface.lpVtbl->Release( + &state_manager->ID3DXEffectStateManager_iface); + ok(!refcount, "State manager was not properly freed, refcount %u.\n", refcount); +} + +static void test_cross_effect_handle(IDirect3DDevice9 *device) +{ + ID3DXEffect *effect1, *effect2; + D3DXHANDLE param1, param2; + static int expected_ivect[4] = {28, 29, 30, 31}; + int ivect[4]; + HRESULT hr; + + hr = D3DXCreateEffect(device, test_effect_preshader_effect_blob, sizeof(test_effect_preshader_effect_blob), + NULL, NULL, 0, NULL, &effect1, NULL); + ok(hr == D3D_OK, "Got result %#x.\n", hr); + hr = D3DXCreateEffect(device, test_effect_preshader_effect_blob, sizeof(test_effect_preshader_effect_blob), + NULL, NULL, 0, NULL, &effect2, NULL); + ok(hr == D3D_OK, "Got result %#x.\n", hr); + + ok(effect1 != effect2, "Got same effect unexpectedly.\n"); + + param1 = effect1->lpVtbl->GetParameterByName(effect1, NULL, "g_iVect"); + ok(!!param1, "GetParameterByName failed.\n"); + + param2 = effect2->lpVtbl->GetParameterByName(effect2, NULL, "g_iVect"); + ok(!!param2, "GetParameterByName failed.\n"); + + ok(param1 != param2, "Got same parameter handle unexpectedly.\n"); + + hr = effect2->lpVtbl->SetValue(effect2, param1, expected_ivect, sizeof(expected_ivect)); + ok(hr == D3D_OK, "Got result %#x.\n", hr); + + hr = effect1->lpVtbl->GetValue(effect1, param1, ivect, sizeof(ivect)); + ok(hr == D3D_OK, "Got result %#x.\n", hr); + + ok(!memcmp(ivect, expected_ivect, sizeof(expected_ivect)), "Vector value mismatch.\n"); + + effect2->lpVtbl->Release(effect2); + effect1->lpVtbl->Release(effect1); +} + +#if 0 +struct test_struct +{ + float3 v1_2; + float fv_2; + float4 v2_2; +}; + +shared float arr2[1]; +shared test_struct ts2[2] = {{{0, 0, 0}, 0, {0, 0, 0, 0}}, {{1, 2, 3}, 4, {5, 6, 7, 8}}}; + +struct VS_OUTPUT +{ + float4 Position : POSITION; +}; + +VS_OUTPUT RenderSceneVS(float4 vPos : POSITION) +{ + VS_OUTPUT Output; + + Output.Position = arr2[0] * vPos; + return Output; +} + +shared vertexshader vs_arr2[2] = {compile vs_3_0 RenderSceneVS(), NULL}; + +technique tech0 +{ + pass p0 + { + FogEnable = TRUE; + FogDensity = arr2[0]; + PointScale_A = ts2[0].fv_2; + VertexShader = vs_arr2[0]; + } + + pass p1 + { + VertexShader = vs_arr2[1]; + } +} +#endif +static const DWORD test_effect_shared_parameters_blob[] = +{ + 0xfeff0901, 0x000001dc, 0x00000000, 0x00000003, 0x00000000, 0x00000024, 0x00000000, 0x00000001, + 0x00000001, 0x00000001, 0x00000000, 0x00000005, 0x32727261, 0x00000000, 0x00000000, 0x00000005, + 0x000000dc, 0x00000000, 0x00000002, 0x00000003, 0x00000003, 0x00000001, 0x000000e4, 0x00000000, + 0x00000000, 0x00000003, 0x00000001, 0x00000003, 0x00000000, 0x000000f0, 0x00000000, 0x00000000, + 0x00000001, 0x00000001, 0x00000003, 0x00000001, 0x000000fc, 0x00000000, 0x00000000, 0x00000004, + 0x00000001, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x3f800000, 0x40000000, 0x40400000, 0x40800000, 0x40a00000, 0x40c00000, 0x40e00000, + 0x41000000, 0x00000004, 0x00327374, 0x00000005, 0x325f3176, 0x00000000, 0x00000005, 0x325f7666, + 0x00000000, 0x00000005, 0x325f3276, 0x00000000, 0x00000010, 0x00000004, 0x00000124, 0x00000000, + 0x00000002, 0x00000001, 0x00000002, 0x00000008, 0x615f7376, 0x00327272, 0x00000001, 0x00000002, + 0x00000002, 0x00000000, 0x00000000, 0x00000000, 0x00000001, 0x00000001, 0x00000000, 0x00000003, + 0x00000002, 0x00000000, 0x00000000, 0x00000000, 0x00000001, 0x00000001, 0x00000000, 0x00000003, + 0x00000002, 0x00000000, 0x00000000, 0x00000000, 0x00000001, 0x00000001, 0x00000003, 0x00000010, + 0x00000004, 0x00000000, 0x00000000, 0x00000000, 0x00000003, 0x00003070, 0x00000004, 0x00000010, + 0x00000004, 0x00000000, 0x00000000, 0x00000000, 0x00000003, 0x00003170, 0x00000006, 0x68636574, + 0x00000030, 0x00000003, 0x00000001, 0x00000006, 0x00000005, 0x00000004, 0x00000020, 0x00000001, + 0x00000000, 0x00000030, 0x0000009c, 0x00000001, 0x00000000, 0x00000108, 0x0000011c, 0x00000001, + 0x00000000, 0x000001d0, 0x00000000, 0x00000002, 0x000001a8, 0x00000000, 0x00000004, 0x0000000e, + 0x00000000, 0x00000134, 0x00000130, 0x00000014, 0x00000000, 0x00000154, 0x00000150, 0x00000041, + 0x00000000, 0x00000174, 0x00000170, 0x00000092, 0x00000000, 0x00000194, 0x00000190, 0x000001c8, + 0x00000000, 0x00000001, 0x00000092, 0x00000000, 0x000001b4, 0x000001b0, 0x00000002, 0x00000004, + 0x00000001, 0x000000c8, 0xfffe0300, 0x0025fffe, 0x42415443, 0x0000001c, 0x0000005f, 0xfffe0300, + 0x00000001, 0x0000001c, 0x00000000, 0x00000058, 0x00000030, 0x00000002, 0x00000001, 0x00000038, + 0x00000048, 0x32727261, 0xababab00, 0x00030000, 0x00010001, 0x00000001, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x335f7376, 0x4d00305f, 0x6f726369, 0x74666f73, 0x29522820, + 0x534c4820, 0x6853204c, 0x72656461, 0x6d6f4320, 0x656c6970, 0x2e392072, 0x392e3932, 0x332e3235, + 0x00313131, 0x0200001f, 0x80000000, 0x900f0000, 0x0200001f, 0x80000000, 0xe00f0000, 0x03000005, + 0xe00f0000, 0xa0000000, 0x90e40000, 0x0000ffff, 0x00000002, 0x00000000, 0x00000000, 0x00000001, + 0xffffffff, 0x00000000, 0x00000001, 0x0000000b, 0x615f7376, 0x5b327272, 0x00005d31, 0x00000000, + 0x00000000, 0xffffffff, 0x00000003, 0x00000001, 0x0000000b, 0x615f7376, 0x5b327272, 0x00005d30, + 0x00000000, 0x00000000, 0xffffffff, 0x00000002, 0x00000000, 0x00000188, 0x46580200, 0x004ffffe, + 0x42415443, 0x0000001c, 0x00000107, 0x46580200, 0x00000001, 0x0000001c, 0x20000100, 0x00000104, + 0x00000030, 0x00000002, 0x00000002, 0x00000094, 0x000000a4, 0x00327374, 0x325f3176, 0xababab00, + 0x00030001, 0x00030001, 0x00000001, 0x00000000, 0x325f7666, 0xababab00, 0x00030000, 0x00010001, + 0x00000001, 0x00000000, 0x325f3276, 0xababab00, 0x00030001, 0x00040001, 0x00000001, 0x00000000, + 0x00000034, 0x0000003c, 0x0000004c, 0x00000054, 0x00000064, 0x0000006c, 0x00000005, 0x00080001, + 0x00030002, 0x0000007c, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x3f800000, 0x40000000, + 0x40400000, 0x00000000, 0x40800000, 0x00000000, 0x00000000, 0x00000000, 0x40a00000, 0x40c00000, + 0x40e00000, 0x41000000, 0x4d007874, 0x6f726369, 0x74666f73, 0x29522820, 0x534c4820, 0x6853204c, + 0x72656461, 0x6d6f4320, 0x656c6970, 0x2e392072, 0x392e3932, 0x332e3235, 0x00313131, 0x0002fffe, + 0x54494c43, 0x00000000, 0x000cfffe, 0x434c5846, 0x00000001, 0x10000001, 0x00000001, 0x00000000, + 0x00000002, 0x00000004, 0x00000000, 0x00000004, 0x00000000, 0xf0f0f0f0, 0x0f0f0f0f, 0x0000ffff, + 0x00000000, 0x00000000, 0xffffffff, 0x00000001, 0x00000000, 0x000000dc, 0x46580200, 0x0024fffe, + 0x42415443, 0x0000001c, 0x0000005b, 0x46580200, 0x00000001, 0x0000001c, 0x20000100, 0x00000058, + 0x00000030, 0x00000002, 0x00000001, 0x00000038, 0x00000048, 0x32727261, 0xababab00, 0x00030000, + 0x00010001, 0x00000001, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x4d007874, + 0x6f726369, 0x74666f73, 0x29522820, 0x534c4820, 0x6853204c, 0x72656461, 0x6d6f4320, 0x656c6970, + 0x2e392072, 0x392e3932, 0x332e3235, 0x00313131, 0x0002fffe, 0x54494c43, 0x00000000, 0x000cfffe, + 0x434c5846, 0x00000001, 0x10000001, 0x00000001, 0x00000000, 0x00000002, 0x00000000, 0x00000000, + 0x00000004, 0x00000000, 0xf0f0f0f0, 0x0f0f0f0f, 0x0000ffff, +}; + +#ifdef __REACTOS__ +#define test_effect_shared_vs_arr_compare_helper(...) \ + test_effect_shared_vs_arr_compare_helper_(__LINE__, __VA_ARGS__) +#else +#define test_effect_shared_vs_arr_compare_helper(args...) \ + test_effect_shared_vs_arr_compare_helper_(__LINE__, args) +#endif +static void test_effect_shared_vs_arr_compare_helper_(unsigned int line, ID3DXEffect *effect, + D3DXHANDLE param_child, struct IDirect3DVertexShader9 *vshader1, unsigned int element, + BOOL todo) +{ + struct IDirect3DVertexShader9 *vshader2; + D3DXHANDLE param_child2; + HRESULT hr; + + param_child2 = effect->lpVtbl->GetParameterElement(effect, "vs_arr2", element); + ok_(__FILE__, line)(!!param_child2, "GetParameterElement failed.\n"); + ok_(__FILE__, line)(param_child != param_child2, "Got same parameter handle unexpectedly.\n"); + hr = effect->lpVtbl->GetVertexShader(effect, param_child2, &vshader2); + ok_(__FILE__, line)(hr == D3D_OK, "Got result %#x.\n", hr); + todo_wine_if(todo) + ok_(__FILE__, line)(vshader1 == vshader2, "Shared shader interface pointers differ.\n"); + if (vshader2) + IDirect3DVertexShader9_Release(vshader2); +} + +#ifdef __REACTOS__ +#define test_effect_shared_parameters_compare_vconst(...) \ + test_effect_shared_parameters_compare_vconst_(__LINE__, __VA_ARGS__) +#else +#define test_effect_shared_parameters_compare_vconst(args...) \ + test_effect_shared_parameters_compare_vconst_(__LINE__, args) +#endif +static void test_effect_shared_parameters_compare_vconst_(unsigned int line, IDirect3DDevice9 *device, + unsigned int index, const D3DXVECTOR4 *expected_fvect, BOOL todo) +{ + D3DXVECTOR4 fvect; + HRESULT hr; + + hr = IDirect3DDevice9_GetVertexShaderConstantF(device, index, &fvect.x, 1); + ok_(__FILE__, line)(hr == D3D_OK, "Got result %#x.\n", hr); + todo_wine_if(todo) + ok_(__FILE__, line)(!memcmp(&fvect, expected_fvect, sizeof(fvect)), + "Unexpected constant value %g, %g, %g, %g.\n", fvect.x, fvect.y, fvect.z, fvect.w); +} + +static void test_effect_shared_parameters(IDirect3DDevice9 *device) +{ + ID3DXEffect *effect1, *effect2, *effect3, *effect4; + ID3DXEffectPool *pool; + HRESULT hr; + D3DXHANDLE param, param_child, param2, param_child2; + unsigned int i, passes_count; + ULONG refcount; + D3DXVECTOR4 fvect; + float fval[2]; + + hr = D3DXCreateEffectPool(&pool); + ok(hr == D3D_OK, "Got result %#x.\n", hr); + + hr = D3DXCreateEffect(device, test_effect_preshader_effect_blob, sizeof(test_effect_preshader_effect_blob), + NULL, NULL, 0, pool, &effect2, NULL); + ok(hr == D3D_OK, "Got result %#x.\n", hr); + effect2->lpVtbl->SetFloat(effect2, "arr2[0]", 28.0f); + effect2->lpVtbl->Release(effect2); + + hr = D3DXCreateEffect(device, test_effect_preshader_effect_blob, sizeof(test_effect_preshader_effect_blob), + NULL, NULL, 0, pool, &effect2, NULL); + ok(hr == D3D_OK, "Got result %#x.\n", hr); + effect2->lpVtbl->GetFloat(effect2, "arr2[0]", &fvect.x); + ok(fvect.x == 92.0f, "Unexpected parameter value %g.\n", fvect.x); + effect2->lpVtbl->SetFloat(effect2, "arr2[0]", 28.0f); + + hr = D3DXCreateEffect(device, test_effect_preshader_effect_blob, sizeof(test_effect_preshader_effect_blob), + NULL, NULL, 0, pool, &effect1, NULL); + ok(hr == D3D_OK, "Got result %#x.\n", hr); + + effect1->lpVtbl->GetFloat(effect1, "arr2[0]", &fvect.x); + ok(fvect.x == 28.0f, "Unexpected parameter value %g.\n", fvect.x); + + hr = D3DXCreateEffect(device, test_effect_shared_parameters_blob, sizeof(test_effect_shared_parameters_blob), + NULL, NULL, 0, pool, &effect3, NULL); + ok(hr == D3D_OK, "Got result %#x.\n", hr); + hr = D3DXCreateEffect(device, test_effect_shared_parameters_blob, sizeof(test_effect_shared_parameters_blob), + NULL, NULL, 0, pool, &effect4, NULL); + ok(hr == D3D_OK, "Got result %#x.\n", hr); + + effect2->lpVtbl->SetFloat(effect2, "arr2[0]", 3.0f); + effect2->lpVtbl->SetFloat(effect2, "ts2[0].fv", 3.0f); + + effect3->lpVtbl->GetFloat(effect3, "arr2[0]", &fvect.x); + ok(fvect.x == 0.0f, "Unexpected parameter value %g.\n", fvect.x); + effect4->lpVtbl->SetFloat(effect4, "arr2[0]", 28.0f); + effect3->lpVtbl->GetFloat(effect3, "arr2[0]", &fvect.x); + ok(fvect.x == 28.0f, "Unexpected parameter value %g.\n", fvect.x); + effect1->lpVtbl->GetFloat(effect1, "arr2[0]", &fvect.x); + ok(fvect.x == 3.0f, "Unexpected parameter value %g.\n", fvect.x); + + param = effect3->lpVtbl->GetParameterByName(effect3, NULL, "ts2[0].fv_2"); + ok(!!param, "GetParameterByName failed.\n"); + effect3->lpVtbl->GetFloat(effect3, param, &fvect.x); + ok(fvect.x == 0.0f, "Unexpected parameter value %g.\n", fvect.x); + + param = effect1->lpVtbl->GetParameterByName(effect1, NULL, "arr2"); + ok(!!param, "GetParameterByName failed.\n"); + ok(!effect3->lpVtbl->IsParameterUsed(effect3, param, "tech0"), + "Unexpected IsParameterUsed result.\n"); + + param = effect3->lpVtbl->GetParameterByName(effect3, NULL, "arr2"); + ok(!!param, "GetParameterByName failed.\n"); + ok(effect3->lpVtbl->IsParameterUsed(effect3, param, "tech0"), + "Unexpected IsParameterUsed result.\n"); + + param = effect1->lpVtbl->GetParameterByName(effect1, NULL, "vs_arr2"); + ok(!!param, "GetParameterByName failed.\n"); + todo_wine + ok(!effect3->lpVtbl->IsParameterUsed(effect3, param, "tech0"), + "Unexpected IsParameterUsed result.\n"); + + ok(effect3->lpVtbl->IsParameterUsed(effect3, "vs_arr2", "tech0"), + "Unexpected IsParameterUsed result.\n"); + ok(!effect3->lpVtbl->IsParameterUsed(effect3, "vs_arr2[0]", "tech0"), + "Unexpected IsParameterUsed result.\n"); + ok(!effect3->lpVtbl->IsParameterUsed(effect3, "vs_arr2[1]", "tech0"), + "Unexpected IsParameterUsed result.\n"); + + ok(effect1->lpVtbl->IsParameterUsed(effect1, param, "tech0"), + "Unexpected IsParameterUsed result.\n"); + + hr = effect3->lpVtbl->Begin(effect3, &passes_count, 0); + ok(hr == D3D_OK, "Got result %#x.\n", hr); + + if (0) + { + /* Native d3dx crashes in BeginPass(). This is the case of shader array declared shared + * but initialized with different shaders using different parameters. */ + hr = effect3->lpVtbl->BeginPass(effect3, 0); + ok(hr == D3D_OK, "Got result %#x.\n", hr); + + hr = effect3->lpVtbl->EndPass(effect3); + ok(hr == D3D_OK, "Got result %#x.\n", hr); + } + + test_effect_preshader_clear_vconsts(device); + fvect.x = fvect.y = fvect.z = fvect.w = 28.0f; + hr = effect2->lpVtbl->SetVector(effect2, "g_Pos1", &fvect); + ok(hr == D3D_OK, "Got result %#x.\n", hr); + hr = effect1->lpVtbl->SetVector(effect1, "g_Pos1", &fvect); + ok(hr == D3D_OK, "Got result %#x.\n", hr); + + hr = effect3->lpVtbl->BeginPass(effect3, 1); + todo_wine + ok(hr == D3D_OK, "Got result %#x.\n", hr); + + hr = IDirect3DDevice9_GetVertexShaderConstantF(device, 0, &fvect.x, 1); + ok(hr == D3D_OK, "Got result %#x.\n", hr); + todo_wine + ok(fvect.x == 0.0f && fvect.y == 0.0f && fvect.z == 0.0f && fvect.w == 0.0f, + "Unexpected vector %g, %g, %g, %g.\n", fvect.x, fvect.y, fvect.z, fvect.w); + + hr = effect3->lpVtbl->EndPass(effect3); + todo_wine + ok(hr == D3D_OK, "Got result %#x.\n", hr); + + hr = effect3->lpVtbl->End(effect3); + ok(hr == D3D_OK, "Got result %#x.\n", hr); + + for (i = 0; i < 2; ++i) + { + struct IDirect3DVertexShader9 *vshader1; + + param_child = effect1->lpVtbl->GetParameterElement(effect1, "vs_arr2", i); + ok(!!param_child, "GetParameterElement failed.\n"); + hr = effect1->lpVtbl->GetVertexShader(effect1, param_child, &vshader1); + ok(hr == D3D_OK, "Got result %#x.\n", hr); + + test_effect_shared_vs_arr_compare_helper(effect2, param_child, vshader1, i, FALSE); + test_effect_shared_vs_arr_compare_helper(effect3, param_child, vshader1, i, FALSE); + test_effect_shared_vs_arr_compare_helper(effect4, param_child, vshader1, i, FALSE); + IDirect3DVertexShader9_Release(vshader1); + } + + effect3->lpVtbl->Release(effect3); + effect4->lpVtbl->Release(effect4); + + fval[0] = 1.0f; + hr = effect1->lpVtbl->SetFloatArray(effect1, "arr1", fval, 1); + ok(hr == D3D_OK, "Got result %#x.\n", hr); + fval[0] = 0.0f; + hr = effect2->lpVtbl->GetFloatArray(effect2, "arr1", fval, 1); + ok(hr == D3D_OK, "Got result %#x.\n", hr); + ok(fval[0] == 91.0f, "Unexpected value %g.\n", fval[0]); + + param = effect1->lpVtbl->GetParameterByName(effect1, NULL, "arr2"); + ok(!!param, "GetParameterByName failed.\n"); + param2 = effect2->lpVtbl->GetParameterByName(effect2, NULL, "arr2"); + ok(!!param, "GetParameterByName failed.\n"); + ok(param != param2, "Got same parameter handle unexpectedly.\n"); + param_child = effect1->lpVtbl->GetParameterElement(effect1, param, 0); + ok(!!param_child, "GetParameterElement failed.\n"); + param_child2 = effect1->lpVtbl->GetParameterElement(effect2, param2, 0); + ok(!!param_child2, "GetParameterElement failed.\n"); + ok(param_child != param_child2, "Got same parameter handle unexpectedly.\n"); + + fval[0] = 33.0f; + hr = effect1->lpVtbl->SetFloatArray(effect1, "arr2", fval, 1); + ok(hr == D3D_OK, "Got result %#x.\n", hr); + fval[0] = 0.0f; + hr = effect1->lpVtbl->GetFloatArray(effect1, "arr2", fval, 2); + ok(hr == D3D_OK, "Got result %#x.\n", hr); + ok(fval[0] == 33.0f && fval[1] == 93.0f, "Unexpected values %g, %g.\n", fval[0], fval[1]); + fval[0] = 0.0f; + hr = effect2->lpVtbl->GetFloatArray(effect2, "arr2", fval, 2); + ok(hr == D3D_OK, "Got result %#x.\n", hr); + ok(fval[0] == 33.0f && fval[1] == 93.0f, "Unexpected values %g, %g.\n", fval[0], fval[1]); + + hr = effect1->lpVtbl->Begin(effect1, &passes_count, 0); + ok(hr == D3D_OK, "Got result %#x.\n", hr); + + hr = effect2->lpVtbl->Begin(effect2, &passes_count, 0); + ok(hr == D3D_OK, "Got result %#x.\n", hr); + + hr = effect1->lpVtbl->BeginPass(effect1, 0); + ok(hr == D3D_OK, "Got result %#x.\n", hr); + + fvect.x = 1.0f; + fvect.y = fvect.z = fvect.w = 0.0f; + test_effect_shared_parameters_compare_vconst(device, 32, &fvect, FALSE); + + hr = effect1->lpVtbl->BeginPass(effect2, 0); + ok(hr == D3D_OK, "Got result %#x.\n", hr); + + fvect.x = 91.0f; + test_effect_shared_parameters_compare_vconst(device, 32, &fvect, FALSE); + fvect.x = 33.0f; + test_effect_shared_parameters_compare_vconst(device, 29, &fvect, FALSE); + + fval[0] = 28.0f; + fval[1] = -1.0f; + hr = effect1->lpVtbl->SetFloatArray(effect1, "arr2", fval, 2); + ok(hr == D3D_OK, "Got result %#x.\n", hr); + + test_effect_preshader_clear_vconsts(device); + + hr = effect1->lpVtbl->CommitChanges(effect1); + ok(hr == D3D_OK, "Got result %#x.\n", hr); + + fvect.x = 28.0f; + test_effect_shared_parameters_compare_vconst(device, 29, &fvect, FALSE); + fvect.x = -1.0f; + test_effect_shared_parameters_compare_vconst(device, 30, &fvect, FALSE); + + test_effect_preshader_clear_vconsts(device); + + hr = effect1->lpVtbl->CommitChanges(effect1); + ok(hr == D3D_OK, "Got result %#x.\n", hr); + + test_effect_shared_parameters_compare_vconst(device, 29, &fvect_filler, FALSE); + test_effect_shared_parameters_compare_vconst(device, 30, &fvect_filler, FALSE); + + hr = effect2->lpVtbl->CommitChanges(effect2); + ok(hr == D3D_OK, "Got result %#x.\n", hr); + + fvect.x = 28.0f; + test_effect_shared_parameters_compare_vconst(device, 29, &fvect, FALSE); + fvect.x = -1.0f; + test_effect_shared_parameters_compare_vconst(device, 30, &fvect, FALSE); + + fval[0] = -2.0f; + hr = effect2->lpVtbl->SetFloat(effect2, "arr2[0]", fval[0]); + ok(hr == D3D_OK, "Got result %#x.\n", hr); + hr = effect1->lpVtbl->CommitChanges(effect1); + ok(hr == D3D_OK, "Got result %#x.\n", hr); + + fvect.x = -2.0f; + test_effect_shared_parameters_compare_vconst(device, 29, &fvect, FALSE); + fvect.x = -1.0f; + test_effect_shared_parameters_compare_vconst(device, 30, &fvect, FALSE); + + fvect.x = fvect.y = fvect.z = fvect.w = 1111.0f; + hr = effect2->lpVtbl->SetVector(effect2, "g_Pos1", &fvect); + ok(hr == D3D_OK, "Got result %#x.\n", hr); + + hr = effect1->lpVtbl->CommitChanges(effect1); + ok(hr == D3D_OK, "Got result %#x.\n", hr); + test_effect_shared_parameters_compare_vconst(device, 31, &fvect_filler, FALSE); + + hr = effect1->lpVtbl->CommitChanges(effect2); + ok(hr == D3D_OK, "Got result %#x.\n", hr); + test_effect_shared_parameters_compare_vconst(device, 31, &fvect, FALSE); + + hr = effect1->lpVtbl->End(effect1); + ok(hr == D3D_OK, "Got result %#x.\n", hr); + + hr = effect2->lpVtbl->End(effect2); + ok(hr == D3D_OK, "Got result %#x.\n", hr); + + if (0) + { + refcount = pool->lpVtbl->Release(pool); + ok(refcount == 2, "Unexpected refcount %u.\n", refcount); + + refcount = pool->lpVtbl->Release(pool); + ok(refcount == 1, "Unexpected refcount %u.\n", refcount); + + refcount = pool->lpVtbl->Release(pool); + ok(!refcount, "Unexpected refcount %u.\n", refcount); + + /* Native d3dx crashes in GetFloat(). */ + effect2->lpVtbl->GetFloat(effect2, "arr2[0]", &fvect.x); + } + + effect1->lpVtbl->Release(effect1); + effect2->lpVtbl->Release(effect2); + + refcount = pool->lpVtbl->Release(pool); + ok(!refcount, "Effect pool was not properly freed, refcount %u.\n", refcount); +} + +static void test_effect_large_address_aware_flag(IDirect3DDevice9 *device) +{ + ID3DXEffect *effect; + D3DXHANDLE param; + static int expected_ivect[4] = {28, 29, 30, 31}; + int ivect[4]; + HRESULT hr; + + hr = D3DXCreateEffect(device, test_effect_preshader_effect_blob, sizeof(test_effect_preshader_effect_blob), + NULL, NULL, D3DXFX_LARGEADDRESSAWARE, NULL, &effect, NULL); + ok(hr == D3D_OK, "Got result %#x.\n", hr); + + param = effect->lpVtbl->GetParameterByName(effect, NULL, "g_iVect"); + ok(!!param, "GetParameterByName failed.\n"); + + hr = effect->lpVtbl->SetValue(effect, param, expected_ivect, sizeof(expected_ivect)); + ok(hr == D3D_OK, "Got result %#x.\n", hr); + + hr = effect->lpVtbl->GetValue(effect, param, ivect, sizeof(ivect)); + ok(hr == D3D_OK, "Got result %#x.\n", hr); + + ok(!memcmp(ivect, expected_ivect, sizeof(expected_ivect)), "Vector value mismatch.\n"); + + if (0) + { + /* Native d3dx crashes in GetValue(). */ + hr = effect->lpVtbl->GetValue(effect, "g_iVect", ivect, sizeof(ivect)); + ok(hr == D3DERR_INVALIDCALL, "Got result %#x.\n", hr); + } + + effect->lpVtbl->Release(effect); +} + +static void test_effect_get_pass_desc(IDirect3DDevice9 *device) +{ + unsigned int passes_count; + ID3DXEffect *effect; + D3DXPASS_DESC desc; + D3DXVECTOR4 fvect; + D3DXHANDLE pass; + HRESULT hr; + + hr = D3DXCreateEffect(device, test_effect_preshader_effect_blob, sizeof(test_effect_preshader_effect_blob), + NULL, NULL, 0, NULL, &effect, NULL); + ok(hr == D3D_OK, "Got result %#x.\n", hr); + + pass = effect->lpVtbl->GetPass(effect, "tech0", 1); + ok(!!pass, "GetPass() failed.\n"); + + hr = effect->lpVtbl->GetPassDesc(effect, pass, &desc); + ok(hr == D3D_OK, "Got result %#x.\n", hr); + test_effect_preshader_compare_shader_bytecode(desc.pVertexShaderFunction, 0, 2, FALSE); + + fvect.x = fvect.y = fvect.w = 0.0f; + fvect.z = 0.0f; + hr = effect->lpVtbl->SetVector(effect, "g_iVect", &fvect); + ok(hr == D3D_OK, "Got result %#x.\n", hr); + + hr = effect->lpVtbl->GetPassDesc(effect, pass, &desc); + ok(hr == D3D_OK, "Got result %#x.\n", hr); + ok(!desc.pPixelShaderFunction, "Unexpected non null desc.pPixelShaderFunction.\n"); + + test_effect_preshader_compare_shader_bytecode(desc.pVertexShaderFunction, 0, 0, FALSE); + + fvect.z = 3.0f; + hr = effect->lpVtbl->SetVector(effect, "g_iVect", &fvect); + ok(hr == D3D_OK, "Got result %#x.\n", hr); + + hr = effect->lpVtbl->GetPassDesc(effect, pass, &desc); + ok(hr == E_FAIL, "Got result %#x.\n", hr); + ok(!desc.pVertexShaderFunction, "Unexpected non null desc.pVertexShaderFunction.\n"); + + /* Repeating call to confirm GetPassDesc() returns same error on the second call, + * as it is not the case sometimes for BeginPass() with out of bound access. */ + hr = effect->lpVtbl->GetPassDesc(effect, pass, &desc); + ok(hr == E_FAIL, "Got result %#x.\n", hr); + ok(!desc.pVertexShaderFunction, "Unexpected non null desc.pVertexShaderFunction.\n"); + + hr = effect->lpVtbl->Begin(effect, &passes_count, 0); + ok(hr == D3D_OK, "Got result %#x.\n", hr); + + hr = effect->lpVtbl->BeginPass(effect, 1); + ok(hr == D3D_OK, "Got result %#x.\n", hr); + + hr = effect->lpVtbl->GetPassDesc(effect, pass, &desc); + ok(hr == D3D_OK, "Got result %#x.\n", hr); + + test_effect_preshader_compare_shader_bytecode(desc.pVertexShaderFunction, 0, 0, FALSE); + + fvect.z = 2.0f; + hr = effect->lpVtbl->SetVector(effect, "g_iVect", &fvect); + hr = effect->lpVtbl->GetPassDesc(effect, pass, &desc); + ok(hr == D3D_OK, "Got result %#x.\n", hr); + test_effect_preshader_compare_shader_bytecode(desc.pVertexShaderFunction, 0, 2, FALSE); + + effect->lpVtbl->Release(effect); + + hr = D3DXCreateEffect(device, test_effect_preshader_effect_blob, sizeof(test_effect_preshader_effect_blob), + NULL, NULL, D3DXFX_NOT_CLONEABLE, NULL, &effect, NULL); + ok(hr == D3D_OK, "Got result %#x.\n", hr); + + pass = effect->lpVtbl->GetPass(effect, "tech0", 1); + ok(!!pass, "GetPass() failed.\n"); + + hr = effect->lpVtbl->GetPassDesc(effect, pass, &desc); + ok(hr == D3D_OK, "Got result %#x.\n", hr); + + ok(!desc.pVertexShaderFunction, "Unexpected non null desc.pVertexShaderFunction.\n"); + ok(!desc.pPixelShaderFunction, "Unexpected non null desc.pPixelShaderFunction.\n"); + + effect->lpVtbl->Release(effect); +} + +#if 0 +float v1 : register(c2); +float v2 : register(c3); +float v3; +float v4 : register(c4); +float v5; +float v6[2] : register(c5) = {11, 22}; + +struct VS_OUTPUT +{ + float4 Position : POSITION; +}; + +VS_OUTPUT RenderSceneVS(float4 vPos : POSITION) +{ + VS_OUTPUT Output; + + Output.Position = v1 * v2 * vPos + v2 + v3 + v4; + Output.Position += v6[0] + v6[1]; + return Output; +} + +technique tech0 +{ + pass p0 + { + PointScale_A = v4; + VertexShader = compile vs_3_0 RenderSceneVS(); + } +} +#endif +static const DWORD test_effect_skip_constants_blob[] = +{ + 0xfeff0901, 0x00000144, 0x00000000, 0x00000003, 0x00000000, 0x00000024, 0x00000000, 0x00000000, + 0x00000001, 0x00000001, 0x00000000, 0x00000003, 0x00003176, 0x00000003, 0x00000000, 0x0000004c, + 0x00000000, 0x00000000, 0x00000001, 0x00000001, 0x00000000, 0x00000003, 0x00003276, 0x00000003, + 0x00000000, 0x00000074, 0x00000000, 0x00000000, 0x00000001, 0x00000001, 0x00000000, 0x00000003, + 0x00003376, 0x00000003, 0x00000000, 0x0000009c, 0x00000000, 0x00000000, 0x00000001, 0x00000001, + 0x00000000, 0x00000003, 0x00003476, 0x00000003, 0x00000000, 0x000000c4, 0x00000000, 0x00000000, + 0x00000001, 0x00000001, 0x00000000, 0x00000003, 0x00003576, 0x00000003, 0x00000000, 0x000000f0, + 0x00000000, 0x00000002, 0x00000001, 0x00000001, 0x41300000, 0x41b00000, 0x00000003, 0x00003676, + 0x00000000, 0x00000003, 0x00000002, 0x00000000, 0x00000000, 0x00000000, 0x00000001, 0x00000001, + 0x00000001, 0x00000010, 0x00000004, 0x00000000, 0x00000000, 0x00000000, 0x00000003, 0x00003070, + 0x00000006, 0x68636574, 0x00000030, 0x00000006, 0x00000001, 0x00000002, 0x00000002, 0x00000004, + 0x00000020, 0x00000000, 0x00000000, 0x0000002c, 0x00000048, 0x00000000, 0x00000000, 0x00000054, + 0x00000070, 0x00000000, 0x00000000, 0x0000007c, 0x00000098, 0x00000000, 0x00000000, 0x000000a4, + 0x000000c0, 0x00000000, 0x00000000, 0x000000cc, 0x000000e8, 0x00000000, 0x00000000, 0x00000138, + 0x00000000, 0x00000001, 0x00000130, 0x00000000, 0x00000002, 0x00000041, 0x00000000, 0x000000fc, + 0x000000f8, 0x00000092, 0x00000000, 0x0000011c, 0x00000118, 0x00000000, 0x00000002, 0x00000000, + 0x00000000, 0xffffffff, 0x00000001, 0x00000000, 0x000001bc, 0xfffe0300, 0x0047fffe, 0x42415443, + 0x0000001c, 0x000000e7, 0xfffe0300, 0x00000005, 0x0000001c, 0x20000000, 0x000000e0, 0x00000080, + 0x00020002, 0x000a0001, 0x00000084, 0x00000094, 0x000000a4, 0x00030002, 0x000e0001, 0x00000084, + 0x00000094, 0x000000a7, 0x00000002, 0x00000001, 0x00000084, 0x00000094, 0x000000aa, 0x00040002, + 0x00120001, 0x00000084, 0x00000094, 0x000000ad, 0x00050002, 0x00160002, 0x000000b0, 0x000000c0, + 0xab003176, 0x00030000, 0x00010001, 0x00000001, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x76003276, 0x34760033, 0x00367600, 0x00030000, 0x00010001, 0x00000002, 0x00000000, + 0x41300000, 0x00000000, 0x00000000, 0x00000000, 0x41b00000, 0x00000000, 0x00000000, 0x00000000, + 0x335f7376, 0x4d00305f, 0x6f726369, 0x74666f73, 0x29522820, 0x534c4820, 0x6853204c, 0x72656461, + 0x6d6f4320, 0x656c6970, 0x2e392072, 0x392e3932, 0x332e3235, 0x00313131, 0x0200001f, 0x80000000, + 0x900f0000, 0x0200001f, 0x80000000, 0xe00f0000, 0x02000001, 0x80010000, 0xa0000003, 0x03000005, + 0x80010000, 0x80000000, 0xa0000002, 0x04000004, 0x800f0000, 0x80000000, 0x90e40000, 0xa0000003, + 0x03000002, 0x800f0000, 0x80e40000, 0xa0000000, 0x03000002, 0x800f0000, 0x80e40000, 0xa0000004, + 0x02000001, 0x80010001, 0xa0000005, 0x03000002, 0x80010001, 0x80000001, 0xa0000006, 0x03000002, + 0xe00f0000, 0x80e40000, 0x80000001, 0x0000ffff, 0x00000000, 0x00000000, 0xffffffff, 0x00000000, + 0x00000000, 0x000000d8, 0x46580200, 0x0023fffe, 0x42415443, 0x0000001c, 0x00000057, 0x46580200, + 0x00000001, 0x0000001c, 0x20000100, 0x00000054, 0x00000030, 0x00040002, 0x00120001, 0x00000034, + 0x00000044, 0xab003476, 0x00030000, 0x00010001, 0x00000001, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x4d007874, 0x6f726369, 0x74666f73, 0x29522820, 0x534c4820, 0x6853204c, + 0x72656461, 0x6d6f4320, 0x656c6970, 0x2e392072, 0x392e3932, 0x332e3235, 0x00313131, 0x0002fffe, + 0x54494c43, 0x00000000, 0x000cfffe, 0x434c5846, 0x00000001, 0x10000001, 0x00000001, 0x00000000, + 0x00000002, 0x00000010, 0x00000000, 0x00000004, 0x00000000, 0xf0f0f0f0, 0x0f0f0f0f, 0x0000ffff, +}; + +static void test_effect_skip_constants(IDirect3DDevice9 *device) +{ + HRESULT hr; + ID3DXEffect *effect; + unsigned int passes_count; + D3DXVECTOR4 fvect; + unsigned int i; + + hr = D3DXCreateEffectEx(device, test_effect_skip_constants_blob, sizeof(test_effect_skip_constants_blob), + NULL, NULL, "v3", 0, NULL, &effect, NULL); + ok(hr == D3DERR_INVALIDCALL, "Got result %#x.\n", hr); + hr = D3DXCreateEffectEx(device, test_effect_skip_constants_blob, sizeof(test_effect_skip_constants_blob), + NULL, NULL, "v4", 0, NULL, &effect, NULL); + ok(hr == D3DERR_INVALIDCALL, "Got result %#x.\n", hr); + hr = D3DXCreateEffectEx(device, test_effect_skip_constants_blob, sizeof(test_effect_skip_constants_blob), + NULL, NULL, "v1;v5;v4", 0, NULL, &effect, NULL); + ok(hr == D3DERR_INVALIDCALL, "Got result %#x.\n", hr); + + hr = D3DXCreateEffectEx(device, test_effect_skip_constants_blob, sizeof(test_effect_skip_constants_blob), + NULL, NULL, " v1#,.+-= &\t\nv2*/!\"'v5 v6[1]", 0, NULL, &effect, NULL); + ok(hr == D3D_OK, "Got result %#x.\n", hr); + + ok(!effect->lpVtbl->IsParameterUsed(effect, "v1", "tech0"), + "Unexpected IsParameterUsed result.\n"); + ok(!effect->lpVtbl->IsParameterUsed(effect, "v2", "tech0"), + "Unexpected IsParameterUsed result.\n"); + ok(effect->lpVtbl->IsParameterUsed(effect, "v3", "tech0"), + "Unexpected IsParameterUsed result.\n"); + ok(effect->lpVtbl->IsParameterUsed(effect, "v4", "tech0"), + "Unexpected IsParameterUsed result.\n"); + ok(!effect->lpVtbl->IsParameterUsed(effect, "v5", "tech0"), + "Unexpected IsParameterUsed result.\n"); + ok(!effect->lpVtbl->IsParameterUsed(effect, "v6", "tech0"), + "Unexpected IsParameterUsed result.\n"); + + hr = effect->lpVtbl->SetFloat(effect, "v1", 28.0f); + ok(hr == D3D_OK, "Got result %#x.\n", hr); + hr = effect->lpVtbl->SetFloat(effect, "v2", 29.0f); + ok(hr == D3D_OK, "Got result %#x.\n", hr); + hr = effect->lpVtbl->SetFloat(effect, "v3", 30.0f); + ok(hr == D3D_OK, "Got result %#x.\n", hr); + hr = effect->lpVtbl->SetFloat(effect, "v4", 31.0f); + ok(hr == D3D_OK, "Got result %#x.\n", hr); + hr = effect->lpVtbl->SetFloat(effect, "v5", 32.0f); + ok(hr == D3D_OK, "Got result %#x.\n", hr); + + test_effect_preshader_clear_vconsts(device); + + hr = effect->lpVtbl->Begin(effect, &passes_count, 0); + ok(hr == D3D_OK, "Got result %#x.\n", hr); + hr = effect->lpVtbl->BeginPass(effect, 0); + ok(hr == D3D_OK, "Got result %#x.\n", hr); + + fvect.y = fvect.z = fvect.w = 0.0f; + fvect.x = 30.0f; + test_effect_shared_parameters_compare_vconst(device, 0, &fvect, FALSE); + for (i = 1; i < 4; ++i) + test_effect_shared_parameters_compare_vconst(device, i, &fvect_filler, FALSE); + fvect.x = 31.0f; + test_effect_shared_parameters_compare_vconst(device, 4, &fvect, FALSE); + for (i = 5; i < 256; ++i) + test_effect_shared_parameters_compare_vconst(device, i, &fvect_filler, FALSE); + + hr = effect->lpVtbl->EndPass(effect); + ok(hr == D3D_OK, "Got result %#x.\n", hr); + hr = effect->lpVtbl->End(effect); + ok(hr == D3D_OK, "Got result %#x.\n", hr); + + effect->lpVtbl->Release(effect); +} + +#if 0 +vertexshader vs_arr[2] = +{ + asm + { + vs_3_0 + def c0, 1, 1, 1, 1 + dcl_position o0 + mov o0, c0 + }, + + asm + { + vs_3_sw + def c256, 1, 1, 1, 1 + dcl_position o0 + mov o0, c256 + }, +}; + +int i; + +technique tech0 +{ + pass p0 + { + VertexShader = vs_arr[1]; + } +} +technique tech1 +{ + pass p0 + { + VertexShader = vs_arr[i]; + } +} +#endif +static const DWORD test_effect_unsupported_shader_blob[] = +{ + 0xfeff0901, 0x000000ac, 0x00000000, 0x00000010, 0x00000004, 0x00000020, 0x00000000, 0x00000002, + 0x00000001, 0x00000002, 0x00000007, 0x615f7376, 0x00007272, 0x00000002, 0x00000000, 0x0000004c, + 0x00000000, 0x00000000, 0x00000001, 0x00000001, 0x00000000, 0x00000002, 0x00000069, 0x00000003, + 0x00000010, 0x00000004, 0x00000000, 0x00000000, 0x00000000, 0x00000003, 0x00003070, 0x00000006, + 0x68636574, 0x00000030, 0x00000004, 0x00000010, 0x00000004, 0x00000000, 0x00000000, 0x00000000, + 0x00000003, 0x00003070, 0x00000006, 0x68636574, 0x00000031, 0x00000002, 0x00000002, 0x00000006, + 0x00000005, 0x00000004, 0x00000018, 0x00000000, 0x00000000, 0x0000002c, 0x00000048, 0x00000000, + 0x00000000, 0x00000074, 0x00000000, 0x00000001, 0x0000006c, 0x00000000, 0x00000001, 0x00000092, + 0x00000000, 0x00000058, 0x00000054, 0x000000a0, 0x00000000, 0x00000001, 0x00000098, 0x00000000, + 0x00000001, 0x00000092, 0x00000000, 0x00000084, 0x00000080, 0x00000002, 0x00000002, 0x00000001, + 0x00000038, 0xfffe0300, 0x05000051, 0xa00f0000, 0x3f800000, 0x3f800000, 0x3f800000, 0x3f800000, + 0x0200001f, 0x80000000, 0xe00f0000, 0x02000001, 0xe00f0000, 0xa0e40000, 0x0000ffff, 0x00000002, + 0x00000038, 0xfffe03ff, 0x05000051, 0xa00f0100, 0x3f800000, 0x3f800000, 0x3f800000, 0x3f800000, + 0x0200001f, 0x80000000, 0xe00f0000, 0x02000001, 0xe00f0000, 0xa0e40100, 0x0000ffff, 0x00000001, + 0x00000000, 0xffffffff, 0x00000000, 0x00000002, 0x000000e4, 0x00000008, 0x615f7376, 0x00007272, + 0x46580200, 0x0023fffe, 0x42415443, 0x0000001c, 0x00000057, 0x46580200, 0x00000001, 0x0000001c, + 0x00000100, 0x00000054, 0x00000030, 0x00000002, 0x00000001, 0x00000034, 0x00000044, 0xabab0069, + 0x00020000, 0x00010001, 0x00000001, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x4d007874, 0x6f726369, 0x74666f73, 0x29522820, 0x534c4820, 0x6853204c, 0x72656461, 0x6d6f4320, + 0x656c6970, 0x2e392072, 0x392e3932, 0x332e3235, 0x00313131, 0x0002fffe, 0x54494c43, 0x00000000, + 0x000cfffe, 0x434c5846, 0x00000001, 0x10000001, 0x00000001, 0x00000000, 0x00000002, 0x00000000, + 0x00000000, 0x00000004, 0x00000000, 0xf0f0f0f0, 0x0f0f0f0f, 0x0000ffff, 0x00000000, 0x00000000, + 0xffffffff, 0x00000000, 0x00000001, 0x0000000a, 0x615f7376, 0x315b7272, 0x0000005d, +}; + +#define TEST_EFFECT_UNSUPPORTED_SHADER_BYTECODE_VS_3_0_POS 81 +#define TEST_EFFECT_UNSUPPORTED_SHADER_BYTECODE_VS_3_0_LEN 14 + +static void test_effect_unsupported_shader(void) +{ + IDirect3DVertexShader9 *vshader; + unsigned int passes_count; + IDirect3DDevice9 *device; + UINT byte_code_size; + ID3DXEffect *effect; + void *byte_code; + ULONG refcount; + HWND window; + HRESULT hr; + + if (!(device = create_device(&window))) + return; + + hr = D3DXCreateEffectEx(device, test_effect_unsupported_shader_blob, sizeof(test_effect_unsupported_shader_blob), + NULL, NULL, NULL, 0, NULL, &effect, NULL); + ok(hr == D3D_OK, "Got result %#x.\n", hr); + + hr = effect->lpVtbl->ValidateTechnique(effect, "missing_technique"); + ok(hr == D3DERR_INVALIDCALL, "Got result %#x.\n", hr); + hr = effect->lpVtbl->ValidateTechnique(effect, "tech0"); + ok(hr == E_FAIL, "Got result %#x.\n", hr); + + hr = effect->lpVtbl->ValidateTechnique(effect, "tech1"); + ok(hr == D3D_OK, "Got result %#x.\n", hr); + effect->lpVtbl->SetInt(effect, "i", 1); + ok(hr == D3D_OK, "Got result %#x.\n", hr); + hr = effect->lpVtbl->ValidateTechnique(effect, "tech1"); + ok(hr == E_FAIL, "Got result %#x.\n", hr); + effect->lpVtbl->SetInt(effect, "i", 0); + hr = effect->lpVtbl->ValidateTechnique(effect, "tech1"); + ok(hr == D3D_OK, "Got result %#x.\n", hr); + + hr = effect->lpVtbl->SetTechnique(effect, "tech0"); + ok(hr == D3D_OK, "Got result %#x.\n", hr); + hr = effect->lpVtbl->Begin(effect, &passes_count, 0); + ok(hr == D3D_OK, "Got result %#x.\n", hr); + hr = effect->lpVtbl->BeginPass(effect, 0); + ok(hr == D3D_OK, "Got result %#x.\n", hr); + + hr = IDirect3DDevice9_GetVertexShader(device, &vshader); + ok(hr == D3D_OK, "Got result %x, expected 0 (D3D_OK).\n", hr); + ok(!vshader, "Got non NULL vshader.\n"); + + hr = effect->lpVtbl->EndPass(effect); + ok(hr == D3D_OK, "Got result %#x.\n", hr); + hr = effect->lpVtbl->End(effect); + ok(hr == D3D_OK, "Got result %#x.\n", hr); + + hr = effect->lpVtbl->SetTechnique(effect, "tech1"); + ok(hr == D3D_OK, "Got result %#x.\n", hr); + hr = effect->lpVtbl->Begin(effect, &passes_count, 0); + ok(hr == D3D_OK, "Got result %#x.\n", hr); + hr = effect->lpVtbl->BeginPass(effect, 0); + ok(hr == D3D_OK, "Got result %#x.\n", hr); + + hr = IDirect3DDevice9_GetVertexShader(device, &vshader); + ok(hr == D3D_OK, "Got result %x, expected 0 (D3D_OK).\n", hr); + ok(!!vshader, "Got NULL vshader.\n"); + hr = IDirect3DVertexShader9_GetFunction(vshader, NULL, &byte_code_size); + ok(hr == D3D_OK, "Got result %x.\n", hr); + byte_code = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, byte_code_size); + hr = IDirect3DVertexShader9_GetFunction(vshader, byte_code, &byte_code_size); + ok(hr == D3D_OK, "Got result %x.\n", hr); + ok(byte_code_size == TEST_EFFECT_UNSUPPORTED_SHADER_BYTECODE_VS_3_0_LEN * sizeof(DWORD), + "Got unexpected byte code size %u.\n", byte_code_size); + ok(!memcmp(byte_code, + &test_effect_unsupported_shader_blob[TEST_EFFECT_UNSUPPORTED_SHADER_BYTECODE_VS_3_0_POS], + byte_code_size), "Incorrect shader selected.\n"); + HeapFree(GetProcessHeap(), 0, byte_code); + IDirect3DVertexShader9_Release(vshader); + + effect->lpVtbl->SetInt(effect, "i", 1); + ok(hr == D3D_OK, "Got result %#x.\n", hr); + hr = effect->lpVtbl->CommitChanges(effect); + ok(hr == D3D_OK, "Got result %#x.\n", hr); + hr = IDirect3DDevice9_GetVertexShader(device, &vshader); + ok(hr == D3D_OK, "Got result %x.\n", hr); + ok(!vshader, "Got non NULL vshader.\n"); + + effect->lpVtbl->Release(effect); + + refcount = IDirect3DDevice9_Release(device); + ok(!refcount, "Device has %u references left.\n", refcount); + DestroyWindow(window); +} + +#if 0 +vertexshader vs_arr[2]; + +int i; + +technique tech0 +{ + pass p0 + { + VertexShader = null; + } +} +technique tech1 +{ + pass p0 + { + VertexShader = vs_arr[i]; + } +} +#endif +static const DWORD test_effect_null_shader_blob[] = +{ + 0xfeff0901, 0x000000b4, 0x00000000, 0x00000010, 0x00000004, 0x00000020, 0x00000000, 0x00000002, + 0x00000001, 0x00000002, 0x00000007, 0x615f7376, 0x00007272, 0x00000002, 0x00000000, 0x0000004c, + 0x00000000, 0x00000000, 0x00000001, 0x00000001, 0x00000000, 0x00000002, 0x00000069, 0x00000000, + 0x00000002, 0x00000002, 0x00000000, 0x00000000, 0x00000000, 0x00000001, 0x00000001, 0x00000003, + 0x00003070, 0x00000006, 0x68636574, 0x00000030, 0x00000003, 0x00000010, 0x00000004, 0x00000000, + 0x00000000, 0x00000000, 0x00000003, 0x00003070, 0x00000006, 0x68636574, 0x00000031, 0x00000002, + 0x00000002, 0x00000005, 0x00000004, 0x00000004, 0x00000018, 0x00000000, 0x00000000, 0x0000002c, + 0x00000048, 0x00000000, 0x00000000, 0x0000007c, 0x00000000, 0x00000001, 0x00000074, 0x00000000, + 0x00000001, 0x00000092, 0x00000000, 0x00000058, 0x00000054, 0x000000a8, 0x00000000, 0x00000001, + 0x000000a0, 0x00000000, 0x00000001, 0x00000092, 0x00000000, 0x0000008c, 0x00000088, 0x00000002, + 0x00000001, 0x00000001, 0x00000000, 0x00000002, 0x00000000, 0x00000001, 0x00000000, 0xffffffff, + 0x00000000, 0x00000002, 0x000000e4, 0x00000008, 0x615f7376, 0x00007272, 0x46580200, 0x0023fffe, + 0x42415443, 0x0000001c, 0x00000057, 0x46580200, 0x00000001, 0x0000001c, 0x00000100, 0x00000054, + 0x00000030, 0x00000002, 0x00000001, 0x00000034, 0x00000044, 0xabab0069, 0x00020000, 0x00010001, + 0x00000001, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x4d007874, 0x6f726369, + 0x74666f73, 0x29522820, 0x534c4820, 0x6853204c, 0x72656461, 0x6d6f4320, 0x656c6970, 0x2e392072, + 0x392e3932, 0x332e3235, 0x00313131, 0x0002fffe, 0x54494c43, 0x00000000, 0x000cfffe, 0x434c5846, + 0x00000001, 0x10000001, 0x00000001, 0x00000000, 0x00000002, 0x00000000, 0x00000000, 0x00000004, + 0x00000000, 0xf0f0f0f0, 0x0f0f0f0f, 0x0000ffff, +}; + +static void test_effect_null_shader(void) +{ + IDirect3DDevice9 *device; + ID3DXEffect *effect; + D3DXPASS_DESC desc; + D3DXHANDLE pass; + ULONG refcount; + HWND window; + HRESULT hr; + + /* Creating a fresh device because the existing device can have invalid + * render states from previous tests. If IDirect3DDevice9_ValidateDevice() + * returns certain error codes, native ValidateTechnique() fails. */ + if (!(device = create_device(&window))) + return; + + hr = D3DXCreateEffectEx(device, test_effect_null_shader_blob, + sizeof(test_effect_null_shader_blob), NULL, NULL, NULL, 0, NULL, &effect, NULL); + ok(hr == D3D_OK, "Failed to create effect, hr %#x.\n", hr); + + pass = effect->lpVtbl->GetPass(effect, "tech0", 0); + ok(!!pass, "GetPass() failed.\n"); + hr = effect->lpVtbl->GetPassDesc(effect, pass, &desc); + ok(hr == D3D_OK, "Got result %#x.\n", hr); + ok(!desc.pVertexShaderFunction, "Got non NULL vertex function.\n"); + + pass = effect->lpVtbl->GetPass(effect, "tech1", 0); + ok(!!pass, "GetPass() failed.\n"); + hr = effect->lpVtbl->GetPassDesc(effect, pass, &desc); + ok(hr == D3D_OK, "Got result %#x.\n", hr); + ok(!desc.pVertexShaderFunction, "Got non NULL vertex function.\n"); + + hr = effect->lpVtbl->ValidateTechnique(effect, "tech0"); + ok(hr == D3D_OK, "Got result %#x.\n", hr); + effect->lpVtbl->SetInt(effect, "i", 0); + ok(hr == D3D_OK, "Failed to set parameter, hr %#x.\n", hr); + hr = effect->lpVtbl->ValidateTechnique(effect, "tech1"); + ok(hr == D3D_OK, "Got result %#x.\n", hr); + effect->lpVtbl->SetInt(effect, "i", 1); + ok(hr == D3D_OK, "Failed to set parameter, hr %#x.\n", hr); + hr = effect->lpVtbl->ValidateTechnique(effect, "tech1"); + ok(hr == D3D_OK, "Got result %#x.\n", hr); + + effect->lpVtbl->SetInt(effect, "i", 2); + ok(hr == D3D_OK, "Failed to set parameter, hr %#x.\n", hr); + hr = effect->lpVtbl->ValidateTechnique(effect, "tech1"); + ok(hr == E_FAIL, "Got result %#x.\n", hr); + + effect->lpVtbl->Release(effect); + + refcount = IDirect3DDevice9_Release(device); + ok(!refcount, "Device has %u references left.\n", refcount); + DestroyWindow(window); +} + +static void test_effect_clone(void) +{ + IDirect3DDevice9 *device, *device2, *device3; + ID3DXEffect *effect, *cloned; + HWND window, window2; + ULONG refcount; + HRESULT hr; + + if (!(device = create_device(&window))) + return; + + /* D3DXFX_NOT_CLONEABLE */ + hr = D3DXCreateEffect(device, test_effect_preshader_effect_blob, sizeof(test_effect_preshader_effect_blob), + NULL, NULL, D3DXFX_NOT_CLONEABLE, NULL, &effect, NULL); + ok(hr == D3D_OK, "Got result %#x.\n", hr); + + hr = effect->lpVtbl->CloneEffect(effect, NULL, NULL); + ok(hr == D3DERR_INVALIDCALL, "Got result %#x.\n", hr); + + cloned = (void *)0xdeadbeef; + hr = effect->lpVtbl->CloneEffect(effect, NULL, &cloned); + ok(hr == E_FAIL, "Got result %#x.\n", hr); + ok(cloned == (void *)0xdeadbeef, "Unexpected effect pointer.\n"); + + hr = effect->lpVtbl->CloneEffect(effect, device, NULL); + ok(hr == D3DERR_INVALIDCALL, "Got result %#x.\n", hr); + + cloned = (void *)0xdeadbeef; + hr = effect->lpVtbl->CloneEffect(effect, device, &cloned); + ok(hr == E_FAIL, "Got result %#x.\n", hr); + ok(cloned == (void *)0xdeadbeef, "Unexpected effect pointer.\n"); + + effect->lpVtbl->Release(effect); + + hr = D3DXCreateEffect(device, test_effect_preshader_effect_blob, sizeof(test_effect_preshader_effect_blob), + NULL, NULL, 0, NULL, &effect, NULL); + ok(hr == D3D_OK, "Got result %#x.\n", hr); + + hr = effect->lpVtbl->CloneEffect(effect, NULL, NULL); + ok(hr == D3DERR_INVALIDCALL, "Got result %#x.\n", hr); + + cloned = (void *)0xdeadbeef; + hr = effect->lpVtbl->CloneEffect(effect, NULL, &cloned); + ok(hr == D3DERR_INVALIDCALL, "Got result %#x.\n", hr); + ok(cloned == (void *)0xdeadbeef, "Unexpected effect pointer.\n"); + + hr = effect->lpVtbl->CloneEffect(effect, device, NULL); + ok(hr == D3DERR_INVALIDCALL, "Got result %#x.\n", hr); + + hr = effect->lpVtbl->CloneEffect(effect, device, &cloned); +todo_wine + ok(hr == D3D_OK, "Got result %#x.\n", hr); +if (hr == D3D_OK) +{ + ok(cloned != effect, "Expected new effect instance.\n"); + cloned->lpVtbl->Release(cloned); +} + /* Try with different device. */ + device2 = create_device(&window2); + hr = effect->lpVtbl->CloneEffect(effect, device2, &cloned); +todo_wine + ok(hr == D3D_OK, "Got result %#x.\n", hr); +if (hr == D3D_OK) +{ + ok(cloned != effect, "Expected new effect instance.\n"); + + hr = cloned->lpVtbl->GetDevice(cloned, &device3); + ok(hr == S_OK, "Failed to get effect device.\n"); + ok(device3 == device2, "Unexpected device instance.\n"); + IDirect3DDevice9_Release(device3); + + cloned->lpVtbl->Release(cloned); +} + IDirect3DDevice9_Release(device2); + DestroyWindow(window2); + effect->lpVtbl->Release(effect); + refcount = IDirect3DDevice9_Release(device); + ok(!refcount, "Device has %u references left.\n", refcount); + DestroyWindow(window); +} + +static unsigned int get_texture_refcount(IDirect3DTexture9 *iface) +{ + IDirect3DTexture9_AddRef(iface); + return IDirect3DTexture9_Release(iface); +} + +static void test_refcount(void) +{ + IDirect3DTexture9 *texture, *cur_texture, *managed_texture, *sysmem_texture; + unsigned int passes_count; + IDirect3DDevice9 *device; + ID3DXEffect *effect; + ULONG refcount; + HWND window; + HRESULT hr; + + if (!(device = create_device(&window))) + return; + + hr = IDirect3DDevice9_CreateTexture(device, 16, 16, 1, 0, D3DFMT_X8R8G8B8, D3DPOOL_DEFAULT, &texture, NULL); + ok(hr == D3D_OK, "Failed to create texture, hr %#x.\n", hr); + + hr = D3DXCreateEffect(device, test_effect_preshader_effect_blob, + sizeof(test_effect_preshader_effect_blob), NULL, NULL, + D3DXFX_DONOTSAVESTATE, NULL, &effect, NULL); + ok(hr == D3D_OK, "Failed to create effect, hr %#x.\n", hr); + + hr = effect->lpVtbl->SetTexture(effect, "tex1", (IDirect3DBaseTexture9 *)texture); + ok(hr == D3D_OK, "Failed to set texture parameter, hr %#x.\n", hr); + + hr = effect->lpVtbl->Begin(effect, &passes_count, D3DXFX_DONOTSAVESTATE); + ok(hr == D3D_OK, "Begin() failed, hr %#x.\n", hr); + + hr = effect->lpVtbl->BeginPass(effect, 0); + ok(hr == D3D_OK, "BeginPass() failed, hr %#x.\n", hr); + + IDirect3DDevice9_GetTexture(device, 0, (IDirect3DBaseTexture9 **)&cur_texture); + ok(cur_texture == texture, "Unexpected current texture %p.\n", cur_texture); + IDirect3DTexture9_Release(cur_texture); + + IDirect3DDevice9_SetTexture(device, 0, NULL); + effect->lpVtbl->CommitChanges(effect); + + IDirect3DDevice9_GetTexture(device, 0, (IDirect3DBaseTexture9 **)&cur_texture); + ok(cur_texture == NULL, "Unexpected current texture %p.\n", cur_texture); + + hr = effect->lpVtbl->EndPass(effect); + ok(hr == D3D_OK, "EndPass() failed, hr %#x.\n", hr); + + hr = effect->lpVtbl->BeginPass(effect, 0); + ok(hr == D3D_OK, "BeginPass() failed, hr %#x.\n", hr); + + IDirect3DDevice9_GetTexture(device, 0, (IDirect3DBaseTexture9 **)&cur_texture); + ok(cur_texture == texture, "Unexpected current texture %p.\n", cur_texture); + IDirect3DTexture9_Release(cur_texture); + + hr = effect->lpVtbl->EndPass(effect); + ok(hr == D3D_OK, "EndPass() failed, hr %#x.\n", hr); + hr = effect->lpVtbl->End(effect); + ok(hr == D3D_OK, "End() failed, hr %#x.\n", hr); + + IDirect3DDevice9_GetTexture(device, 0, (IDirect3DBaseTexture9 **)&cur_texture); + ok(cur_texture == texture, "Unexpected current texture %p.\n", cur_texture); + IDirect3DTexture9_Release(cur_texture); + refcount = get_texture_refcount(texture); + ok(refcount == 2, "Unexpected texture refcount %u.\n", refcount); + + hr = effect->lpVtbl->OnLostDevice(effect); + ok(hr == D3D_OK, "OnLostDevice() failed, hr %#x.\n", hr); + refcount = get_texture_refcount(texture); + ok(refcount == 1, "Unexpected texture refcount %u.\n", refcount); + + hr = IDirect3DDevice9_CreateTexture(device, 16, 16, 1, 0, D3DFMT_X8R8G8B8, D3DPOOL_MANAGED, + &managed_texture, NULL); + ok(hr == D3D_OK, "Failed to create texture, hr %#x.\n", hr); + effect->lpVtbl->SetTexture(effect, "tex1", (IDirect3DBaseTexture9 *)managed_texture); + + refcount = get_texture_refcount(managed_texture); + ok(refcount == 2, "Unexpected texture refcount %u.\n", refcount); + hr = effect->lpVtbl->OnLostDevice(effect); + ok(hr == D3D_OK, "OnLostDevice() failed, hr %#x.\n", hr); + refcount = get_texture_refcount(managed_texture); + ok(refcount == 2, "Unexpected texture refcount %u.\n", refcount); + + hr = IDirect3DDevice9_CreateTexture(device, 16, 16, 1, 0, D3DFMT_X8R8G8B8, D3DPOOL_SYSTEMMEM, + &sysmem_texture, NULL); + ok(hr == D3D_OK, "Failed to create texture, hr %#x.\n", hr); + effect->lpVtbl->SetTexture(effect, "tex1", (IDirect3DBaseTexture9 *)sysmem_texture); + + refcount = get_texture_refcount(managed_texture); + ok(refcount == 1, "Unexpected texture refcount %u.\n", refcount); + IDirect3DTexture9_Release(managed_texture); + refcount = get_texture_refcount(sysmem_texture); + ok(refcount == 2, "Unexpected texture refcount %u.\n", refcount); + hr = effect->lpVtbl->OnLostDevice(effect); + ok(hr == D3D_OK, "OnLostDevice() failed, hr %#x.\n", hr); + refcount = get_texture_refcount(sysmem_texture); + ok(refcount == 2, "Unexpected texture refcount %u.\n", refcount); + + effect->lpVtbl->Release(effect); + + refcount = get_texture_refcount(sysmem_texture); + ok(refcount == 1, "Unexpected texture refcount %u.\n", refcount); + IDirect3DTexture9_Release(sysmem_texture); + + IDirect3DDevice9_GetTexture(device, 0, (IDirect3DBaseTexture9 **)&cur_texture); + ok(cur_texture == texture, "Unexpected current texture %p.\n", cur_texture); + IDirect3DTexture9_Release(cur_texture); + refcount = get_texture_refcount(texture); + ok(refcount == 1, "Unexpected texture refcount %u.\n", refcount); + IDirect3DTexture9_Release(texture); + + refcount = IDirect3DDevice9_Release(device); + ok(!refcount, "Device has %u references left.\n", refcount); + DestroyWindow(window); +} + +static HRESULT WINAPI d3dxinclude_open(ID3DXInclude *iface, D3DXINCLUDE_TYPE include_type, + const char *filename, const void *parent_data, const void **data, UINT *bytes) +{ + static const char include1[] = + "float4 light;\n" + "float4x4 mat;\n" + "float4 color;\n" + "\n" + "struct vs_input\n" + "{\n" + " float4 position : POSITION;\n" + " float3 normal : NORMAL;\n" + "};\n" + "\n" + "struct vs_output\n" + "{\n" + " float4 position : POSITION;\n" + " float4 diffuse : COLOR;\n" + "};\n"; + static const char include2[] = + "#include \"include1.h\"\n" + "\n" + "vs_output vs_main(const vs_input v)\n" + "{\n" + " vs_output o;\n" + " const float4 scaled_color = 0.5 * color;\n" + "\n" + " o.position = mul(v.position, mat);\n" + " o.diffuse = dot((float3)light, v.normal) * scaled_color;\n" + "\n" + " return o;\n" + "}\n"; + static const char effect2[] = + "#include \"include\\include2.h\"\n" + "\n" + "technique t\n" + "{\n" + " pass p\n" + " {\n" + " VertexShader = compile vs_2_0 vs_main();\n" + " }\n" + "}\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, "effect2.fx")) + { + buffer = HeapAlloc(GetProcessHeap(), 0, sizeof(effect2)); + memcpy(buffer, effect2, sizeof(effect2)); + *bytes = sizeof(effect2); + ok(!parent_data, "Unexpected parent_data value.\n"); + } + else if (!strcmp(filename, "include1.h")) + { + buffer = HeapAlloc(GetProcessHeap(), 0, sizeof(include1)); + memcpy(buffer, include1, sizeof(include1)); + *bytes = sizeof(include1); + ok(!strncmp(parent_data, include2, strlen(include2)), "Unexpected parent_data value.\n"); + } + else if (!strcmp(filename, "include\\include2.h")) + { + buffer = HeapAlloc(GetProcessHeap(), 0, sizeof(include2)); + memcpy(buffer, include2, sizeof(include2)); + *bytes = sizeof(include2); + todo_wine ok(parent_data && !strncmp(parent_data, effect2, strlen(effect2)), + "unexpected parent_data value.\n"); + } + else + { + ok(0, "Unexpected #include for file %s.\n", filename); + return D3DERR_INVALIDCALL; + } + *data = buffer; + return S_OK; +} + +static HRESULT WINAPI d3dxinclude_close(ID3DXInclude *iface, const void *data) +{ + HeapFree(GetProcessHeap(), 0, (void *)data); + return S_OK; +} + +static const struct ID3DXIncludeVtbl d3dxinclude_vtbl = +{ + d3dxinclude_open, + d3dxinclude_close +}; + +struct d3dxinclude +{ + ID3DXInclude ID3DXInclude_iface; +}; + +static void test_create_effect_from_file(void) +{ + static const char effect1[] = + "float4 light;\n" + "float4x4 mat;\n" + "float4 color;\n" + "\n" + "struct vs_input\n" + "{\n" + " float4 position : POSITION;\n" + " float3 normal : NORMAL;\n" + "};\n" + "\n" + "struct vs_output\n" + "{\n" + " float4 position : POSITION;\n" + " float4 diffuse : COLOR;\n" + "};\n" + "\n" + "vs_output vs_main(const vs_input v)\n" + "{\n" + " vs_output o;\n" + " const float4 scaled_color = 0.5 * color;\n" + "\n" + " o.position = mul(v.position, mat);\n" + " o.diffuse = dot((float3)light, v.normal) * scaled_color;\n" + "\n" + " return o;\n" + "}\n" + "\n" + "technique t\n" + "{\n" + " pass p\n" + " {\n" + " VertexShader = compile vs_2_0 vs_main();\n" + " }\n" + "}\n"; + static const char include1[] = + "float4 light;\n" + "float4x4 mat;\n" + "float4 color;\n" + "\n" + "struct vs_input\n" + "{\n" + " float4 position : POSITION;\n" + " float3 normal : NORMAL;\n" + "};\n" + "\n" + "struct vs_output\n" + "{\n" + " float4 position : POSITION;\n" + " float4 diffuse : COLOR;\n" + "};\n"; + static const char include1_wrong[] = + "#error \"wrong include\"\n"; + static const char include2[] = + "#include \"include1.h\"\n" + "\n" + "vs_output vs_main(const vs_input v)\n" + "{\n" + " vs_output o;\n" + " const float4 scaled_color = 0.5 * color;\n" + "\n" + " o.position = mul(v.position, mat);\n" + " o.diffuse = dot((float3)light, v.normal) * scaled_color;\n" + "\n" + " return o;\n" + "}\n"; + static const char effect2[] = + "#include \"include\\include2.h\"\n" + "\n" + "technique t\n" + "{\n" + " pass p\n" + " {\n" + " VertexShader = compile vs_2_0 vs_main();\n" + " }\n" + "}\n"; + static const WCHAR effect1_filename_w[] = {'e','f','f','e','c','t','1','.','f','x',0}; + static const WCHAR effect2_filename_w[] = {'e','f','f','e','c','t','2','.','f','x',0}; + WCHAR effect_path_w[MAX_PATH], filename_w[MAX_PATH]; + char effect_path[MAX_PATH], filename[MAX_PATH]; + D3DPRESENT_PARAMETERS present_parameters = {0}; + unsigned int filename_size; + struct d3dxinclude include; + IDirect3DDevice9 *device; + ID3DXBuffer *messages; + ID3DXEffect *effect; + IDirect3D9 *d3d; + ULONG refcount; + HWND window; + HRESULT hr; + + if (!(window = CreateWindowA("static", "d3dx9_test", WS_OVERLAPPEDWINDOW, 0, 0, + 640, 480, NULL, NULL, NULL, NULL))) + { + skip("Failed to create window.\n"); + return; + } + if (!(d3d = Direct3DCreate9(D3D_SDK_VERSION))) + { + skip("Failed to create IDirect3D9 object.\n"); + DestroyWindow(window); + return; + } + present_parameters.Windowed = TRUE; + present_parameters.SwapEffect = D3DSWAPEFFECT_DISCARD; + hr = IDirect3D9_CreateDevice(d3d, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, window, + D3DCREATE_HARDWARE_VERTEXPROCESSING, &present_parameters, &device); + if (FAILED(hr)) + { + skip("Failed to create IDirect3DDevice9 object, hr %#x.\n", hr); + IDirect3D9_Release(d3d); + DestroyWindow(window); + return; + } + + if (!create_file("effect1.fx", effect1, sizeof(effect1) - 1, filename)) + { + skip("Couldn't create temporary file, skipping test.\n"); + return; + } + + filename_size = strlen(filename); + filename_size -= sizeof("effect1.fx") - 1; + memcpy(effect_path, filename, filename_size); + effect_path[filename_size] = 0; + MultiByteToWideChar(CP_ACP, 0, effect_path, -1, effect_path_w, ARRAY_SIZE(effect_path_w)); + + create_directory("include"); + create_file("effect2.fx", effect2, sizeof(effect2) - 1, NULL); + create_file("include\\include1.h", include1, sizeof(include1) - 1, NULL); + create_file("include\\include2.h", include2, sizeof(include2) - 1, NULL); + create_file("include1.h", include1_wrong, sizeof(include1_wrong) - 1, NULL); + + lstrcpyW(filename_w, effect_path_w); + lstrcatW(filename_w, effect1_filename_w); + effect = NULL; + messages = NULL; + hr = D3DXCreateEffectFromFileExW(device, filename_w, NULL, NULL, NULL, + 0, NULL, &effect, &messages); + todo_wine ok(hr == D3D_OK, "Unexpected hr %#x.\n", hr); + if (messages) + { + trace("D3DXCreateEffectFromFileExW messages:\n%s", (char *)ID3DXBuffer_GetBufferPointer(messages)); + ID3DXBuffer_Release(messages); + } + if (effect) + effect->lpVtbl->Release(effect); + + lstrcpyW(filename_w, effect_path_w); + lstrcatW(filename_w, effect2_filename_w); + effect = NULL; + messages = NULL; + /* This is apparently broken on native, it ends up using the wrong include. */ + hr = D3DXCreateEffectFromFileExW(device, filename_w, NULL, NULL, NULL, + 0, NULL, &effect, &messages); + todo_wine ok(hr == E_FAIL, "Unexpected error, hr %#x.\n", hr); + if (messages) + { + trace("D3DXCreateEffectFromFileExW messages:\n%s", (char *)ID3DXBuffer_GetBufferPointer(messages)); + ID3DXBuffer_Release(messages); + } + if (effect) + effect->lpVtbl->Release(effect); + + delete_file("effect1.fx"); + delete_file("effect2.fx"); + delete_file("include\\include1.h"); + delete_file("include\\include2.h"); + delete_file("include2.h"); + delete_directory("include"); + + lstrcpyW(filename_w, effect2_filename_w); + effect = NULL; + messages = NULL; + include.ID3DXInclude_iface.lpVtbl = &d3dxinclude_vtbl; + /* This is actually broken in native d3dx9 (manually tried multiple + * versions, all are affected). For reference, the message printed below + * is "ID3DXEffectCompiler: There were no techniques" */ + hr = D3DXCreateEffectFromFileExW(device, filename_w, NULL, &include.ID3DXInclude_iface, NULL, + 0, NULL, &effect, &messages); + todo_wine ok(hr == E_FAIL, "D3DXInclude test failed with error %#x.\n", hr); + if (messages) + { + trace("D3DXCreateEffectFromFileExW messages:\n%s", (char *)ID3DXBuffer_GetBufferPointer(messages)); + ID3DXBuffer_Release(messages); + } + + refcount = IDirect3DDevice9_Release(device); + ok(!refcount, "Device has %u references left.\n", refcount); + IDirect3D9_Release(d3d); + DestroyWindow(window); +} + +#if 0 +technique tech0 +{ + pass p0 + { + LightEnable[0] = FALSE; + FogEnable = FALSE; + } +} +technique tech1 +{ + pass p0 + { + LightEnable[0] = TRUE; + FogEnable = TRUE; + } +} +#endif +static const DWORD test_two_techniques_blob[] = +{ + 0xfeff0901, 0x000000ac, 0x00000000, 0x00000000, 0x00000002, 0x00000002, 0x00000000, 0x00000000, + 0x00000000, 0x00000001, 0x00000001, 0x00000000, 0x00000002, 0x00000002, 0x00000000, 0x00000000, + 0x00000000, 0x00000001, 0x00000001, 0x00000003, 0x00003070, 0x00000006, 0x68636574, 0x00000030, + 0x00000001, 0x00000002, 0x00000002, 0x00000000, 0x00000000, 0x00000000, 0x00000001, 0x00000001, + 0x00000001, 0x00000002, 0x00000002, 0x00000000, 0x00000000, 0x00000000, 0x00000001, 0x00000001, + 0x00000003, 0x00003070, 0x00000006, 0x68636574, 0x00000031, 0x00000000, 0x00000002, 0x00000002, + 0x00000001, 0x0000004c, 0x00000000, 0x00000001, 0x00000044, 0x00000000, 0x00000002, 0x00000091, + 0x00000000, 0x00000008, 0x00000004, 0x0000000e, 0x00000000, 0x00000028, 0x00000024, 0x000000a0, + 0x00000000, 0x00000001, 0x00000098, 0x00000000, 0x00000002, 0x00000091, 0x00000000, 0x0000005c, + 0x00000058, 0x0000000e, 0x00000000, 0x0000007c, 0x00000078, 0x00000000, 0x00000000, +}; + +static void test_effect_find_next_valid_technique(void) +{ + D3DPRESENT_PARAMETERS present_parameters = {0}; + IDirect3DDevice9 *device; + D3DXTECHNIQUE_DESC desc; + ID3DXEffect *effect; + IDirect3D9 *d3d; + D3DXHANDLE tech; + ULONG refcount; + HWND window; + HRESULT hr; + + if (!(window = CreateWindowA("static", "d3dx9_test", WS_OVERLAPPEDWINDOW, 0, 0, + 640, 480, NULL, NULL, NULL, NULL))) + { + skip("Failed to create window.\n"); + return; + } + if (!(d3d = Direct3DCreate9(D3D_SDK_VERSION))) + { + skip("Failed to create IDirect3D9 object.\n"); + DestroyWindow(window); + return; + } + present_parameters.Windowed = TRUE; + present_parameters.SwapEffect = D3DSWAPEFFECT_DISCARD; + hr = IDirect3D9_CreateDevice(d3d, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, window, + D3DCREATE_HARDWARE_VERTEXPROCESSING, &present_parameters, &device); + if (FAILED(hr)) + { + skip("Failed to create IDirect3DDevice9 object, hr %#x.\n", hr); + IDirect3D9_Release(d3d); + DestroyWindow(window); + return; + } + + hr = D3DXCreateEffectEx(device, test_two_techniques_blob, sizeof(test_two_techniques_blob), + NULL, NULL, NULL, 0, NULL, &effect, NULL); + ok(hr == D3D_OK, "Got result %#x.\n", hr); + + hr = effect->lpVtbl->FindNextValidTechnique(effect, NULL, &tech); + ok(hr == D3D_OK, "Got result %#x.\n", hr); + hr = effect->lpVtbl->GetTechniqueDesc(effect, tech, &desc); + ok(hr == D3D_OK, "Got result %#x.\n", hr); + ok(!strcmp(desc.Name, "tech0"), "Got unexpected technique %s.\n", desc.Name); + + hr = effect->lpVtbl->FindNextValidTechnique(effect, tech, &tech); + ok(hr == D3D_OK, "Got result %#x.\n", hr); + hr = effect->lpVtbl->GetTechniqueDesc(effect, tech, &desc); + ok(hr == D3D_OK, "Got result %#x.\n", hr); + ok(!strcmp(desc.Name, "tech1"), "Got unexpected technique %s.\n", desc.Name); + + hr = effect->lpVtbl->FindNextValidTechnique(effect, tech, &tech); + ok(hr == S_FALSE, "Got result %#x.\n", hr); + hr = effect->lpVtbl->GetTechniqueDesc(effect, tech, &desc); + ok(hr == D3D_OK, "Got result %#x.\n", hr); + ok(!strcmp(desc.Name, "tech0"), "Got unexpected technique %s.\n", desc.Name); + + effect->lpVtbl->Release(effect); + + hr = D3DXCreateEffectEx(device, test_effect_unsupported_shader_blob, sizeof(test_effect_unsupported_shader_blob), + NULL, NULL, NULL, 0, NULL, &effect, NULL); + ok(hr == D3D_OK, "Got result %#x.\n", hr); + + hr = effect->lpVtbl->FindNextValidTechnique(effect, NULL, &tech); + ok(hr == D3D_OK, "Got result %#x.\n", hr); + hr = effect->lpVtbl->GetTechniqueDesc(effect, tech, &desc); + ok(hr == D3D_OK, "Got result %#x.\n", hr); + ok(!strcmp(desc.Name, "tech1"), "Got unexpected technique %s.\n", desc.Name); + + hr = effect->lpVtbl->FindNextValidTechnique(effect, tech, &tech); + ok(hr == S_FALSE, "Got result %#x.\n", hr); + hr = effect->lpVtbl->GetTechniqueDesc(effect, tech, &desc); + ok(hr == D3D_OK, "Got result %#x.\n", hr); + ok(!strcmp(desc.Name, "tech0"), "Got unexpected technique %s.\n", desc.Name); + + effect->lpVtbl->SetInt(effect, "i", 1); + ok(hr == D3D_OK, "Got result %#x.\n", hr); + + tech = (D3DXHANDLE)0xdeadbeef; + hr = effect->lpVtbl->FindNextValidTechnique(effect, NULL, &tech); + ok(hr == S_FALSE, "Got result %#x.\n", hr); + hr = effect->lpVtbl->GetTechniqueDesc(effect, tech, &desc); + ok(hr == D3D_OK, "Got result %#x.\n", hr); + ok(!strcmp(desc.Name, "tech0"), "Got unexpected technique %s.\n", desc.Name); + + hr = effect->lpVtbl->FindNextValidTechnique(effect, tech, &tech); + ok(hr == S_FALSE, "Got result %#x.\n", hr); + + effect->lpVtbl->SetInt(effect, "i", 0); + + hr = effect->lpVtbl->FindNextValidTechnique(effect, tech, &tech); + ok(hr == D3D_OK, "Got result %#x.\n", hr); + hr = effect->lpVtbl->GetTechniqueDesc(effect, tech, &desc); + ok(hr == D3D_OK, "Got result %#x.\n", hr); + ok(!strcmp(desc.Name, "tech1"), "Got unexpected technique %s.\n", desc.Name); + + hr = effect->lpVtbl->FindNextValidTechnique(effect, tech, &tech); + ok(hr == S_FALSE, "Got result %#x.\n", hr); + + hr = effect->lpVtbl->FindNextValidTechnique(effect, "nope", &tech); + ok(hr == D3DERR_INVALIDCALL, "Got result %#x.\n", hr); + + effect->lpVtbl->Release(effect); + + refcount = IDirect3DDevice9_Release(device); + ok(!refcount, "Device has %u references left.\n", refcount); + IDirect3D9_Release(d3d); + DestroyWindow(window); +} + +START_TEST(effect) +{ + IDirect3DDevice9 *device; + ULONG refcount; + HWND wnd; + + if (!(device = create_device(&wnd))) + return; + + test_create_effect_and_pool(device); + test_create_effect_compiler(); + test_effect_parameter_value(device); + test_effect_setvalue_object(device); + test_effect_variable_names(device); + test_effect_compilation_errors(device); + test_effect_states(device); + test_effect_preshader(device); + test_effect_preshader_ops(device); + test_effect_isparameterused(device); + test_effect_out_of_bounds_selector(device); + test_effect_commitchanges(device); + test_effect_preshader_relative_addressing(device); + test_effect_state_manager(device); + test_cross_effect_handle(device); + test_effect_shared_parameters(device); + test_effect_large_address_aware_flag(device); + test_effect_get_pass_desc(device); + test_effect_skip_constants(device); + + refcount = IDirect3DDevice9_Release(device); + ok(!refcount, "Device has %u references left.\n", refcount); + DestroyWindow(wnd); + + test_effect_unsupported_shader(); + test_effect_null_shader(); + test_effect_clone(); + test_refcount(); + test_create_effect_from_file(); + test_effect_find_next_valid_technique(); +} diff --git a/modules/rostests/winetests/d3dx9_36/line.c b/modules/rostests/winetests/d3dx9_36/line.c new file mode 100644 index 00000000000..ae8d07e0623 --- /dev/null +++ b/modules/rostests/winetests/d3dx9_36/line.c @@ -0,0 +1,155 @@ +/* + * Copyright 2010 Christian Costa + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA + */ + +#include "wine/test.h" +#include "d3dx9.h" + +#define admitted_error 0.0001f + +#define relative_error(exp, out) ((exp == 0.0f) ? fabs(exp - out) : (fabs(1.0f - out/ exp) )) + +static inline BOOL compare_matrix(const D3DXMATRIX *m1, const D3DXMATRIX *m2) +{ + int i, j; + + for (i = 0; i < 4; ++i) + { + for (j = 0; j < 4; ++j) + { + if (relative_error(U(*m1).m[i][j], U(*m2).m[i][j]) > admitted_error) + return FALSE; + } + } + + return TRUE; +} + +#define expect_mat(expectedmat, gotmat) \ +do { \ + const D3DXMATRIX *__m1 = (expectedmat); \ + const D3DXMATRIX *__m2 = (gotmat); \ + ok(compare_matrix(__m1, __m2), "Expected matrix=\n(%f,%f,%f,%f\n %f,%f,%f,%f\n %f,%f,%f,%f\n %f,%f,%f,%f\n)\n\n" \ + "Got matrix=\n(%f,%f,%f,%f\n %f,%f,%f,%f\n %f,%f,%f,%f\n %f,%f,%f,%f)\n", \ + U(*__m1).m[0][0], U(*__m1).m[0][1], U(*__m1).m[0][2], U(*__m1).m[0][3], \ + U(*__m1).m[1][0], U(*__m1).m[1][1], U(*__m1).m[1][2], U(*__m1).m[1][3], \ + U(*__m1).m[2][0], U(*__m1).m[2][1], U(*__m1).m[2][2], U(*__m1).m[2][3], \ + U(*__m1).m[3][0], U(*__m1).m[3][1], U(*__m1).m[3][2], U(*__m1).m[3][3], \ + U(*__m2).m[0][0], U(*__m2).m[0][1], U(*__m2).m[0][2], U(*__m2).m[0][3], \ + U(*__m2).m[1][0], U(*__m2).m[1][1], U(*__m2).m[1][2], U(*__m2).m[1][3], \ + U(*__m2).m[2][0], U(*__m2).m[2][1], U(*__m2).m[2][2], U(*__m2).m[2][3], \ + U(*__m2).m[3][0], U(*__m2).m[3][1], U(*__m2).m[3][2], U(*__m2).m[3][3]); \ +} while(0) + +static void test_create_line(IDirect3DDevice9* device) +{ + HRESULT hr; + ID3DXLine *line = NULL; + struct IDirect3DDevice9 *return_device; + D3DXMATRIX world, identity, result; + FLOAT r11, r12, r13, r14; + ULONG ref; + + /* Arbitrary values for matrix tests. */ + r11 = 0.1421; r12 = 0.2114; r13 = 0.8027; r14 = 0.4587; + + hr = D3DXCreateLine(NULL, &line); + ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3D_INVALIDCALL)\n", hr, D3DERR_INVALIDCALL); + + hr = D3DXCreateLine(device, NULL); + ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3D_INVALIDCALL)\n", hr, D3DERR_INVALIDCALL); + + hr = D3DXCreateLine(device, &line); + ok(hr == D3D_OK, "Got result %x, expected 0 (D3D_OK)\n", hr); + + if (FAILED(hr)) + { + return; + } + + hr = ID3DXLine_GetDevice(line, NULL); + ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3D_INVALIDCALL)\n", hr, D3DERR_INVALIDCALL); + + hr = ID3DXLine_GetDevice(line, &return_device); + ok(hr == D3D_OK, "Got result %x, expected %x (D3D_OK)\n", hr, D3D_OK); + ok(return_device == device, "Expected line device %p, got %p\n", device, return_device); + + D3DXMatrixIdentity(&world); + D3DXMatrixIdentity(&identity); + S(U(world))._11 = r11; S(U(world))._12 = r12; S(U(world))._13 = r13; S(U(world))._14 = r14; + + hr = IDirect3DDevice9_SetTransform(device, D3DTS_WORLD, &world); + ok(hr == D3D_OK, "Got result %x, expected %x (D3D_OK)\n", hr, D3D_OK); + + hr = ID3DXLine_Begin(line); + ok(hr == D3D_OK, "Got result %x, expected %x (D3D_OK)\n", hr, D3D_OK); + + hr = IDirect3DDevice9_GetTransform(device, D3DTS_WORLD, &result); + ok(hr == D3D_OK, "Got result %x, expected %x (D3D_OK)\n", hr, D3D_OK); + expect_mat(&identity, &result); + + hr = ID3DXLine_End(line); + ok(hr == D3D_OK, "Got result %x, expected %x (D3D_OK)\n", hr, D3D_OK); + + hr = IDirect3DDevice9_GetTransform(device, D3DTS_WORLD, &result); + ok(hr == D3D_OK, "Got result %x, expected %x (D3D_OK)\n", hr, D3D_OK); + expect_mat(&world, &result); + + IDirect3DDevice9_Release(return_device); + + ref = ID3DXLine_Release(line); + ok(ref == 0, "Got %x references to line %p, expected 0\n", ref, line); +} + +START_TEST(line) +{ + HWND wnd; + IDirect3D9* d3d; + IDirect3DDevice9* device; + D3DPRESENT_PARAMETERS d3dpp; + HRESULT hr; + + 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_SOFTWARE_VERTEXPROCESSING, &d3dpp, &device); + if (FAILED(hr)) { + skip("Failed to create IDirect3DDevice9 object %#x\n", hr); + IDirect3D9_Release(d3d); + DestroyWindow(wnd); + return; + } + + test_create_line(device); + + IDirect3DDevice9_Release(device); + IDirect3D9_Release(d3d); + DestroyWindow(wnd); +} diff --git a/modules/rostests/winetests/d3dx9_36/math.c b/modules/rostests/winetests/d3dx9_36/math.c new file mode 100644 index 00000000000..5ce5b2b58a9 --- /dev/null +++ b/modules/rostests/winetests/d3dx9_36/math.c @@ -0,0 +1,3687 @@ +/* + * Copyright 2008 David Adam + * Copyright 2008 Luis Busquets + * Copyright 2008 Philip Nilsson + * Copyright 2008 Henri Verbeet + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA + */ + +#include "wine/test.h" +#include "d3dx9.h" +#include + +static BOOL compare_float(float f, float g, unsigned int ulps) +{ + int x = *(int *)&f; + int y = *(int *)&g; + + if (x < 0) + x = INT_MIN - x; + if (y < 0) + y = INT_MIN - y; + + if (abs(x - y) > ulps) + return FALSE; + + return TRUE; +} + +static BOOL compare_vec2(const D3DXVECTOR2 *v1, const D3DXVECTOR2 *v2, unsigned int ulps) +{ + return compare_float(v1->x, v2->x, ulps) && compare_float(v1->y, v2->y, ulps); +} + +static BOOL compare_vec3(const D3DXVECTOR3 *v1, const D3DXVECTOR3 *v2, unsigned int ulps) +{ + return compare_float(v1->x, v2->x, ulps) + && compare_float(v1->y, v2->y, ulps) + && compare_float(v1->z, v2->z, ulps); +} + +static BOOL compare_vec4(const D3DXVECTOR4 *v1, const D3DXVECTOR4 *v2, unsigned int ulps) +{ + return compare_float(v1->x, v2->x, ulps) + && compare_float(v1->y, v2->y, ulps) + && compare_float(v1->z, v2->z, ulps) + && compare_float(v1->w, v2->w, ulps); +} + +static BOOL compare_color(const D3DXCOLOR *c1, const D3DXCOLOR *c2, unsigned int ulps) +{ + return compare_float(c1->r, c2->r, ulps) + && compare_float(c1->g, c2->g, ulps) + && compare_float(c1->b, c2->b, ulps) + && compare_float(c1->a, c2->a, ulps); +} + +static BOOL compare_plane(const D3DXPLANE *p1, const D3DXPLANE *p2, unsigned int ulps) +{ + return compare_float(p1->a, p2->a, ulps) + && compare_float(p1->b, p2->b, ulps) + && compare_float(p1->c, p2->c, ulps) + && compare_float(p1->d, p2->d, ulps); +} + +static BOOL compare_quaternion(const D3DXQUATERNION *q1, const D3DXQUATERNION *q2, unsigned int ulps) +{ + return compare_float(q1->x, q2->x, ulps) + && compare_float(q1->y, q2->y, ulps) + && compare_float(q1->z, q2->z, ulps) + && compare_float(q1->w, q2->w, ulps); +} + +static BOOL compare_matrix(const D3DXMATRIX *m1, const D3DXMATRIX *m2, unsigned int ulps) +{ + unsigned int i, j; + + for (i = 0; i < 4; ++i) + { + for (j = 0; j < 4; ++j) + { + if (!compare_float(U(*m1).m[i][j], U(*m2).m[i][j], ulps)) + return FALSE; + } + } + + return TRUE; +} + +#define expect_vec2(expected, vector, ulps) expect_vec2_(__LINE__, expected, vector, ulps) +static void expect_vec2_(unsigned int line, const D3DXVECTOR2 *expected, const D3DXVECTOR2 *vector, unsigned int ulps) +{ + BOOL equal = compare_vec2(expected, vector, ulps); + ok_(__FILE__, line)(equal, + "Got unexpected vector {%.8e, %.8e}, expected {%.8e, %.8e}.\n", + vector->x, vector->y, expected->x, expected->y); +} + +#define expect_vec3(expected, vector, ulps) expect_vec3_(__LINE__, expected, vector, ulps) +static void expect_vec3_(unsigned int line, const D3DXVECTOR3 *expected, const D3DXVECTOR3 *vector, unsigned int ulps) +{ + BOOL equal = compare_vec3(expected, vector, ulps); + ok_(__FILE__, line)(equal, + "Got unexpected vector {%.8e, %.8e, %.8e}, expected {%.8e, %.8e, %.8e}.\n", + vector->x, vector->y, vector->z, expected->x, expected->y, expected->z); +} + +#define expect_vec4(expected, vector, ulps) expect_vec4_(__LINE__, expected, vector, ulps) +static void expect_vec4_(unsigned int line, const D3DXVECTOR4 *expected, const D3DXVECTOR4 *vector, unsigned int ulps) +{ + BOOL equal = compare_vec4(expected, vector, ulps); + ok_(__FILE__, line)(equal, + "Got unexpected vector {%.8e, %.8e, %.8e, %.8e}, expected {%.8e, %.8e, %.8e, %.8e}.\n", + vector->x, vector->y, vector->z, vector->w, expected->x, expected->y, expected->z, expected->w); +} + +#define expect_color(expected, color, ulps) expect_color_(__LINE__, expected, color, ulps) +static void expect_color_(unsigned int line, const D3DXCOLOR *expected, const D3DXCOLOR *color, unsigned int ulps) +{ + BOOL equal = compare_color(expected, color, ulps); + ok_(__FILE__, line)(equal, + "Got unexpected color {%.8e, %.8e, %.8e, %.8e}, expected {%.8e, %.8e, %.8e, %.8e}.\n", + color->r, color->g, color->b, color->a, expected->r, expected->g, expected->b, expected->a); +} + +#define expect_plane(expected, plane, ulps) expect_plane_(__LINE__, expected, plane, ulps) +static void expect_plane_(unsigned int line, const D3DXPLANE *expected, const D3DXPLANE *plane, unsigned int ulps) +{ + BOOL equal = compare_plane(expected, plane, ulps); + ok_(__FILE__, line)(equal, + "Got unexpected plane {%.8e, %.8e, %.8e, %.8e}, expected {%.8e, %.8e, %.8e, %.8e}.\n", + plane->a, plane->b, plane->c, plane->d, expected->a, expected->b, expected->c, expected->d); +} + +#define expect_quaternion(expected, quaternion, ulps) expect_quaternion_(__LINE__, expected, quaternion, ulps) +static void expect_quaternion_(unsigned int line, const D3DXQUATERNION *expected, + const D3DXQUATERNION *quaternion, unsigned int ulps) +{ + BOOL equal = compare_quaternion(expected, quaternion, ulps); + ok_(__FILE__, line)(equal, + "Got unexpected quaternion {%.8e, %.8e, %.8e, %.8e}, expected {%.8e, %.8e, %.8e, %.8e}.\n", + quaternion->x, quaternion->y, quaternion->z, quaternion->w, + expected->x, expected->y, expected->z, expected->w); +} + +#define expect_matrix(expected, matrix, ulps) expect_matrix_(__LINE__, expected, matrix, ulps) +static void expect_matrix_(unsigned int line, const D3DXMATRIX *expected, const D3DXMATRIX *matrix, unsigned int ulps) +{ + BOOL equal = compare_matrix(expected, matrix, ulps); + ok_(__FILE__, line)(equal, + "Got unexpected matrix {%.8e, %.8e, %.8e, %.8e, %.8e, %.8e, %.8e, %.8e, " + "%.8e, %.8e, %.8e, %.8e, %.8e, %.8e, %.8e, %.8e}, " + "expected {%.8e, %.8e, %.8e, %.8e, %.8e, %.8e, %.8e, %.8e, " + "%.8e, %.8e, %.8e, %.8e, %.8e, %.8e, %.8e, %.8e}.\n", + U(*matrix).m[0][0], U(*matrix).m[0][1], U(*matrix).m[0][2], U(*matrix).m[0][3], + U(*matrix).m[1][0], U(*matrix).m[1][1], U(*matrix).m[1][2], U(*matrix).m[1][3], + U(*matrix).m[2][0], U(*matrix).m[2][1], U(*matrix).m[2][2], U(*matrix).m[2][3], + U(*matrix).m[3][0], U(*matrix).m[3][1], U(*matrix).m[3][2], U(*matrix).m[3][3], + U(*expected).m[0][0], U(*expected).m[0][1], U(*expected).m[0][2], U(*expected).m[0][3], + U(*expected).m[1][0], U(*expected).m[1][1], U(*expected).m[1][2], U(*expected).m[1][3], + U(*expected).m[2][0], U(*expected).m[2][1], U(*expected).m[2][2], U(*expected).m[2][3], + U(*expected).m[3][0], U(*expected).m[3][1], U(*expected).m[3][2], U(*expected).m[3][3]); +} + +#define expect_vec4_array(count, expected, vector, ulps) expect_vec4_array_(__LINE__, count, expected, vector, ulps) +static void expect_vec4_array_(unsigned int line, unsigned int count, const D3DXVECTOR4 *expected, + const D3DXVECTOR4 *vector, unsigned int ulps) +{ + BOOL equal; + unsigned int i; + + for (i = 0; i < count; ++i) + { + equal = compare_vec4(&expected[i], &vector[i], ulps); + ok_(__FILE__, line)(equal, + "Got unexpected vector {%.8e, %.8e, %.8e, %.8e} at index %u, expected {%.8e, %.8e, %.8e, %.8e}.\n", + vector[i].x, vector[i].y, vector[i].z, vector[i].w, i, + expected[i].x, expected[i].y, expected[i].z, expected[i].w); + if (!equal) + break; + } +} + +static void set_matrix(D3DXMATRIX* mat, + float m00, float m01, float m02, float m03, + float m10, float m11, float m12, float m13, + float m20, float m21, float m22, float m23, + float m30, float m31, float m32, float m33) +{ + U(mat)->m[0][0] = m00; U(mat)->m[0][1] = m01; U(mat)->m[0][2] = m02; U(mat)->m[0][3] = m03; + U(mat)->m[1][0] = m10; U(mat)->m[1][1] = m11; U(mat)->m[1][2] = m12; U(mat)->m[1][3] = m13; + U(mat)->m[2][0] = m20; U(mat)->m[2][1] = m21; U(mat)->m[2][2] = m22; U(mat)->m[2][3] = m23; + U(mat)->m[3][0] = m30; U(mat)->m[3][1] = m31; U(mat)->m[3][2] = m32; U(mat)->m[3][3] = m33; +} + +static void D3DXColorTest(void) +{ + D3DXCOLOR color, color1, color2, expected, got; + LPD3DXCOLOR funcpointer; + FLOAT scale; + + color.r = 0.2f; color.g = 0.75f; color.b = 0.41f; color.a = 0.93f; + color1.r = 0.6f; color1.g = 0.55f; color1.b = 0.23f; color1.a = 0.82f; + color2.r = 0.3f; color2.g = 0.5f; color2.b = 0.76f; color2.a = 0.11f; + + scale = 0.3f; + +/*_______________D3DXColorAdd________________*/ + expected.r = 0.9f; expected.g = 1.05f; expected.b = 0.99f, expected.a = 0.93f; + D3DXColorAdd(&got,&color1,&color2); + expect_color(&expected, &got, 1); + /* Test the NULL case */ + funcpointer = D3DXColorAdd(&got,NULL,&color2); + ok(funcpointer == NULL, "Expected: %p, Got: %p\n", NULL, funcpointer); + funcpointer = D3DXColorAdd(NULL,NULL,&color2); + ok(funcpointer == NULL, "Expected: %p, Got: %p\n", NULL, funcpointer); + funcpointer = D3DXColorAdd(NULL,NULL,NULL); + ok(funcpointer == NULL, "Expected: %p, Got: %p\n", NULL, funcpointer); + +/*_______________D3DXColorAdjustContrast______*/ + expected.r = 0.41f; expected.g = 0.575f; expected.b = 0.473f, expected.a = 0.93f; + D3DXColorAdjustContrast(&got,&color,scale); + expect_color(&expected, &got, 0); + +/*_______________D3DXColorAdjustSaturation______*/ + expected.r = 0.486028f; expected.g = 0.651028f; expected.b = 0.549028f, expected.a = 0.93f; + D3DXColorAdjustSaturation(&got,&color,scale); + expect_color(&expected, &got, 16); + +/*_______________D3DXColorLerp________________*/ + expected.r = 0.32f; expected.g = 0.69f; expected.b = 0.356f; expected.a = 0.897f; + D3DXColorLerp(&got,&color,&color1,scale); + expect_color(&expected, &got, 0); + /* Test the NULL case */ + funcpointer = D3DXColorLerp(&got,NULL,&color1,scale); + ok(funcpointer == NULL, "Expected: %p, Got: %p\n", NULL, funcpointer); + funcpointer = D3DXColorLerp(NULL,NULL,&color1,scale); + ok(funcpointer == NULL, "Expected: %p, Got: %p\n", NULL, funcpointer); + funcpointer = D3DXColorLerp(NULL,NULL,NULL,scale); + ok(funcpointer == NULL, "Expected: %p, Got: %p\n", NULL, funcpointer); + +/*_______________D3DXColorModulate________________*/ + expected.r = 0.18f; expected.g = 0.275f; expected.b = 0.1748f; expected.a = 0.0902f; + D3DXColorModulate(&got,&color1,&color2); + expect_color(&expected, &got, 0); + /* Test the NULL case */ + funcpointer = D3DXColorModulate(&got,NULL,&color2); + ok(funcpointer == NULL, "Expected: %p, Got: %p\n", NULL, funcpointer); + funcpointer = D3DXColorModulate(NULL,NULL,&color2); + ok(funcpointer == NULL, "Expected: %p, Got: %p\n", NULL, funcpointer); + funcpointer = D3DXColorModulate(NULL,NULL,NULL); + ok(funcpointer == NULL, "Expected: %p, Got: %p\n", NULL, funcpointer); + +/*_______________D3DXColorNegative________________*/ + expected.r = 0.8f; expected.g = 0.25f; expected.b = 0.59f; expected.a = 0.93f; + D3DXColorNegative(&got,&color); + expect_color(&expected, &got, 1); + /* Test the greater than 1 case */ + color1.r = 0.2f; color1.g = 1.75f; color1.b = 0.41f; color1.a = 0.93f; + expected.r = 0.8f; expected.g = -0.75f; expected.b = 0.59f; expected.a = 0.93f; + D3DXColorNegative(&got,&color1); + expect_color(&expected, &got, 1); + /* Test the negative case */ + color1.r = 0.2f; color1.g = -0.75f; color1.b = 0.41f; color1.a = 0.93f; + expected.r = 0.8f; expected.g = 1.75f; expected.b = 0.59f; expected.a = 0.93f; + D3DXColorNegative(&got,&color1); + expect_color(&expected, &got, 1); + /* Test the NULL case */ + funcpointer = D3DXColorNegative(&got,NULL); + ok(funcpointer == NULL, "Expected: %p, Got: %p\n", NULL, funcpointer); + funcpointer = D3DXColorNegative(NULL,NULL); + ok(funcpointer == NULL, "Expected: %p, Got: %p\n", NULL, funcpointer); + +/*_______________D3DXColorScale________________*/ + expected.r = 0.06f; expected.g = 0.225f; expected.b = 0.123f; expected.a = 0.279f; + D3DXColorScale(&got,&color,scale); + expect_color(&expected, &got, 1); + /* Test the NULL case */ + funcpointer = D3DXColorScale(&got,NULL,scale); + ok(funcpointer == NULL, "Expected: %p, Got: %p\n", NULL, funcpointer); + funcpointer = D3DXColorScale(NULL,NULL,scale); + ok(funcpointer == NULL, "Expected: %p, Got: %p\n", NULL, funcpointer); + +/*_______________D3DXColorSubtract_______________*/ + expected.r = -0.1f; expected.g = 0.25f; expected.b = -0.35f, expected.a = 0.82f; + D3DXColorSubtract(&got,&color,&color2); + expect_color(&expected, &got, 1); + /* Test the NULL case */ + funcpointer = D3DXColorSubtract(&got,NULL,&color2); + ok(funcpointer == NULL, "Expected: %p, Got: %p\n", NULL, funcpointer); + funcpointer = D3DXColorSubtract(NULL,NULL,&color2); + ok(funcpointer == NULL, "Expected: %p, Got: %p\n", NULL, funcpointer); + funcpointer = D3DXColorSubtract(NULL,NULL,NULL); + ok(funcpointer == NULL, "Expected: %p, Got: %p\n", NULL, funcpointer); +} + +static void D3DXFresnelTest(void) +{ + float fresnel; + BOOL equal; + + fresnel = D3DXFresnelTerm(0.5f, 1.5f); + equal = compare_float(fresnel, 8.91867128e-02f, 1); + ok(equal, "Got unexpected Fresnel term %.8e.\n", fresnel); +} + +static void D3DXMatrixTest(void) +{ + D3DXMATRIX expectedmat, gotmat, mat, mat2, mat3; + BOOL expected, got, equal; + float angle, determinant; + D3DXMATRIX *funcpointer; + D3DXPLANE plane; + D3DXQUATERNION q, r; + D3DXVECTOR3 at, axis, eye, last; + D3DXVECTOR4 light; + + U(mat).m[0][1] = 5.0f; U(mat).m[0][2] = 7.0f; U(mat).m[0][3] = 8.0f; + U(mat).m[1][0] = 11.0f; U(mat).m[1][2] = 16.0f; U(mat).m[1][3] = 33.0f; + U(mat).m[2][0] = 19.0f; U(mat).m[2][1] = -21.0f; U(mat).m[2][3] = 43.0f; + U(mat).m[3][0] = 2.0f; U(mat).m[3][1] = 3.0f; U(mat).m[3][2] = -4.0f; + U(mat).m[0][0] = 10.0f; U(mat).m[1][1] = 20.0f; U(mat).m[2][2] = 30.0f; + U(mat).m[3][3] = -40.0f; + + U(mat2).m[0][0] = 1.0f; U(mat2).m[1][0] = 2.0f; U(mat2).m[2][0] = 3.0f; + U(mat2).m[3][0] = 4.0f; U(mat2).m[0][1] = 5.0f; U(mat2).m[1][1] = 6.0f; + U(mat2).m[2][1] = 7.0f; U(mat2).m[3][1] = 8.0f; U(mat2).m[0][2] = -8.0f; + U(mat2).m[1][2] = -7.0f; U(mat2).m[2][2] = -6.0f; U(mat2).m[3][2] = -5.0f; + U(mat2).m[0][3] = -4.0f; U(mat2).m[1][3] = -3.0f; U(mat2).m[2][3] = -2.0f; + U(mat2).m[3][3] = -1.0f; + + plane.a = -3.0f; plane.b = -1.0f; plane.c = 4.0f; plane.d = 7.0f; + + q.x = 1.0f; q.y = -4.0f; q.z =7.0f; q.w = -11.0f; + r.x = 0.87f; r.y = 0.65f; r.z =0.43f; r.w= 0.21f; + + at.x = -2.0f; at.y = 13.0f; at.z = -9.0f; + axis.x = 1.0f; axis.y = -3.0f; axis.z = 7.0f; + eye.x = 8.0f; eye.y = -5.0f; eye.z = 5.75f; + last.x = 9.7f; last.y = -8.6; last.z = 1.3f; + + light.x = 9.6f; light.y = 8.5f; light.z = 7.4; light.w = 6.3; + + angle = D3DX_PI/3.0f; + +/*____________D3DXMatrixAffineTransformation______*/ + set_matrix(&expectedmat, + -459.239990f, -576.719971f, -263.440002f, 0.0f, + 519.760010f, -352.440002f, -277.679993f, 0.0f, + 363.119995f, -121.040001f, -117.479996f, 0.0f, + -1239.0f, 667.0f, 567.0f, 1.0f); + D3DXMatrixAffineTransformation(&gotmat, 3.56f, &at, &q, &axis); + expect_matrix(&expectedmat, &gotmat, 0); + + /* Test the NULL case */ + U(expectedmat).m[3][0] = 1.0f; U(expectedmat).m[3][1] = -3.0f; U(expectedmat).m[3][2] = 7.0f; U(expectedmat).m[3][3] = 1.0f; + D3DXMatrixAffineTransformation(&gotmat, 3.56f, NULL, &q, &axis); + expect_matrix(&expectedmat, &gotmat, 0); + + U(expectedmat).m[3][0] = -1240.0f; U(expectedmat).m[3][1] = 670.0f; U(expectedmat).m[3][2] = 560.0f; U(expectedmat).m[3][3] = 1.0f; + D3DXMatrixAffineTransformation(&gotmat, 3.56f, &at, &q, NULL); + expect_matrix(&expectedmat, &gotmat, 0); + + U(expectedmat).m[3][0] = 0.0f; U(expectedmat).m[3][1] = 0.0f; U(expectedmat).m[3][2] = 0.0f; U(expectedmat).m[3][3] = 1.0f; + D3DXMatrixAffineTransformation(&gotmat, 3.56f, NULL, &q, NULL); + expect_matrix(&expectedmat, &gotmat, 0); + + set_matrix(&expectedmat, + 3.56f, 0.0f, 0.0f, 0.0f, + 0.0f, 3.56f, 0.0f, 0.0f, + 0.0f, 0.0f, 3.56f, 0.0f, + 1.0f, -3.0f, 7.0f, 1.0f); + D3DXMatrixAffineTransformation(&gotmat, 3.56f, NULL, NULL, &axis); + expect_matrix(&expectedmat, &gotmat, 0); + + D3DXMatrixAffineTransformation(&gotmat, 3.56f, &at, NULL, &axis); + expect_matrix(&expectedmat, &gotmat, 0); + + U(expectedmat).m[3][0] = 0.0f; U(expectedmat).m[3][1] = 0.0f; U(expectedmat).m[3][2] = 0.0f; U(expectedmat).m[3][3] = 1.0f; + D3DXMatrixAffineTransformation(&gotmat, 3.56f, &at, NULL, NULL); + expect_matrix(&expectedmat, &gotmat, 0); + + D3DXMatrixAffineTransformation(&gotmat, 3.56f, NULL, NULL, NULL); + expect_matrix(&expectedmat, &gotmat, 0); + +/*____________D3DXMatrixfDeterminant_____________*/ + determinant = D3DXMatrixDeterminant(&mat); + equal = compare_float(determinant, -147888.0f, 0); + ok(equal, "Got unexpected determinant %.8e.\n", determinant); + +/*____________D3DXMatrixInverse______________*/ + set_matrix(&expectedmat, + 16067.0f/73944.0f, -10165.0f/147888.0f, -2729.0f/147888.0f, -1631.0f/49296.0f, + -565.0f/36972.0f, 2723.0f/73944.0f, -1073.0f/73944.0f, 289.0f/24648.0f, + -389.0f/2054.0f, 337.0f/4108.0f, 181.0f/4108.0f, 317.0f/4108.0f, + 163.0f/5688.0f, -101.0f/11376.0f, -73.0f/11376.0f, -127.0f/3792.0f); + D3DXMatrixInverse(&gotmat, &determinant, &mat); + expect_matrix(&expectedmat, &gotmat, 1); + equal = compare_float(determinant, -147888.0f, 0); + ok(equal, "Got unexpected determinant %.8e.\n", determinant); + funcpointer = D3DXMatrixInverse(&gotmat,NULL,&mat2); + ok(funcpointer == NULL, "Expected: %p, Got: %p\n", NULL, funcpointer); + +/*____________D3DXMatrixIsIdentity______________*/ + expected = FALSE; + memset(&mat3, 0, sizeof(mat3)); + got = D3DXMatrixIsIdentity(&mat3); + ok(expected == got, "Expected : %d, Got : %d\n", expected, got); + D3DXMatrixIdentity(&mat3); + expected = TRUE; + got = D3DXMatrixIsIdentity(&mat3); + ok(expected == got, "Expected : %d, Got : %d\n", expected, got); + U(mat3).m[0][0] = 0.000009f; + expected = FALSE; + got = D3DXMatrixIsIdentity(&mat3); + ok(expected == got, "Expected : %d, Got : %d\n", expected, got); + /* Test the NULL case */ + expected = FALSE; + got = D3DXMatrixIsIdentity(NULL); + ok(expected == got, "Expected : %d, Got : %d\n", expected, got); + +/*____________D3DXMatrixLookAtLH_______________*/ + set_matrix(&expectedmat, + -0.82246518f, -0.40948939f, -0.39480308f, 0.0f, + -0.55585691f, 0.43128574f, 0.71064550f, 0.0f, + -0.12072885f, 0.80393475f, -0.58233452f, 0.0f, + 4.4946337f, 0.80971903f, 10.060076f, 1.0f); + D3DXMatrixLookAtLH(&gotmat, &eye, &at, &axis); + expect_matrix(&expectedmat, &gotmat, 32); + +/*____________D3DXMatrixLookAtRH_______________*/ + set_matrix(&expectedmat, + 0.82246518f, -0.40948939f, 0.39480308f, 0.0f, + 0.55585691f, 0.43128574f, -0.71064550f, 0.0f, + 0.12072885f, 0.80393475f, 0.58233452f, 0.0f, + -4.4946337f, 0.80971903f, -10.060076f, 1.0f); + D3DXMatrixLookAtRH(&gotmat, &eye, &at, &axis); + expect_matrix(&expectedmat, &gotmat, 32); + +/*____________D3DXMatrixMultiply______________*/ + set_matrix(&expectedmat, + 73.0f, 193.0f, -197.0f, -77.0f, + 231.0f, 551.0f, -489.0f, -169.0f, + 239.0f, 523.0f, -400.0f, -116.0f, + -164.0f, -320.0f, 187.0f, 31.0f); + D3DXMatrixMultiply(&gotmat, &mat, &mat2); + expect_matrix(&expectedmat, &gotmat, 0); + +/*____________D3DXMatrixMultiplyTranspose____*/ + set_matrix(&expectedmat, + 73.0f, 231.0f, 239.0f, -164.0f, + 193.0f, 551.0f, 523.0f, -320.0f, + -197.0f, -489.0f, -400.0f, 187.0f, + -77.0f, -169.0f, -116.0f, 31.0f); + D3DXMatrixMultiplyTranspose(&gotmat, &mat, &mat2); + expect_matrix(&expectedmat, &gotmat, 0); + +/*____________D3DXMatrixOrthoLH_______________*/ + set_matrix(&expectedmat, + 0.8f, 0.0f, 0.0f, 0.0f, + 0.0f, 0.27027027f, 0.0f, 0.0f, + 0.0f, 0.0f, -0.15151515f, 0.0f, + 0.0f, 0.0f, -0.48484848f, 1.0f); + D3DXMatrixOrthoLH(&gotmat, 2.5f, 7.4f, -3.2f, -9.8f); + expect_matrix(&expectedmat, &gotmat, 16); + +/*____________D3DXMatrixOrthoOffCenterLH_______________*/ + set_matrix(&expectedmat, + 3.6363636f, 0.0f, 0.0f, 0.0f, + 0.0f, 0.18018018f, 0.0f, 0.0f, + 0.0f, 0.0f, -0.045662100f, 0.0f, + -1.7272727f, -0.56756757f, 0.42465753f, 1.0f); + D3DXMatrixOrthoOffCenterLH(&gotmat, 0.2f, 0.75f, -2.4f, 8.7f, 9.3, -12.6); + expect_matrix(&expectedmat, &gotmat, 32); + +/*____________D3DXMatrixOrthoOffCenterRH_______________*/ + set_matrix(&expectedmat, + 3.6363636f, 0.0f, 0.0f, 0.0f, + 0.0f, 0.18018018f, 0.0f, 0.0f, + 0.0f, 0.0f, 0.045662100f, 0.0f, + -1.7272727f, -0.56756757f, 0.42465753f, 1.0f); + D3DXMatrixOrthoOffCenterRH(&gotmat, 0.2f, 0.75f, -2.4f, 8.7f, 9.3, -12.6); + expect_matrix(&expectedmat, &gotmat, 32); + +/*____________D3DXMatrixOrthoRH_______________*/ + set_matrix(&expectedmat, + 0.8f, 0.0f, 0.0f, 0.0f, + 0.0f, 0.27027027f, 0.0f, 0.0f, + 0.0f, 0.0f, 0.15151515f, 0.0f, + 0.0f, 0.0f, -0.48484848f, 1.0f); + D3DXMatrixOrthoRH(&gotmat, 2.5f, 7.4f, -3.2f, -9.8f); + expect_matrix(&expectedmat, &gotmat, 16); + +/*____________D3DXMatrixPerspectiveFovLH_______________*/ + set_matrix(&expectedmat, + 13.288858f, 0.0f, 0.0f, 0.0f, + 0.0f, 9.9666444f, 0.0f, 0.0f, + 0.0f, 0.0f, 0.78378378f, 1.0f, + 0.0f, 0.0f, 1.8810811f, 0.0f); + D3DXMatrixPerspectiveFovLH(&gotmat, 0.2f, 0.75f, -2.4f, 8.7f); + expect_matrix(&expectedmat, &gotmat, 4); + +/*____________D3DXMatrixPerspectiveFovRH_______________*/ + set_matrix(&expectedmat, + 13.288858f, 0.0f, 0.0f, 0.0f, + 0.0f, 9.9666444f, 0.0f, 0.0f, + 0.0f, 0.0f, -0.78378378f, -1.0f, + 0.0f, 0.0f, 1.8810811f, 0.0f); + D3DXMatrixPerspectiveFovRH(&gotmat, 0.2f, 0.75f, -2.4f, 8.7f); + expect_matrix(&expectedmat, &gotmat, 4); + +/*____________D3DXMatrixPerspectiveLH_______________*/ + set_matrix(&expectedmat, + -24.0f, 0.0f, 0.0f, 0.0f, + 0.0f, -6.4f, 0.0f, 0.0f, + 0.0f, 0.0f, 0.78378378f, 1.0f, + 0.0f, 0.0f, 1.8810811f, 0.0f); + D3DXMatrixPerspectiveLH(&gotmat, 0.2f, 0.75f, -2.4f, 8.7f); + expect_matrix(&expectedmat, &gotmat, 4); + +/*____________D3DXMatrixPerspectiveOffCenterLH_______________*/ + set_matrix(&expectedmat, + 11.636364f, 0.0f, 0.0f, 0.0f, + 0.0f, 0.57657658f, 0.0f, 0.0f, + -1.7272727f, -0.56756757f, 0.84079602f, 1.0f, + 0.0f, 0.0f, -2.6905473f, 0.0f); + D3DXMatrixPerspectiveOffCenterLH(&gotmat, 0.2f, 0.75f, -2.4f, 8.7f, 3.2f, -16.9f); + expect_matrix(&expectedmat, &gotmat, 8); + +/*____________D3DXMatrixPerspectiveOffCenterRH_______________*/ + set_matrix(&expectedmat, + 11.636364f, 0.0f, 0.0f, 0.0f, + 0.0f, 0.57657658f, 0.0f, 0.0f, + 1.7272727f, 0.56756757f, -0.84079602f, -1.0f, + 0.0f, 0.0f, -2.6905473f, 0.0f); + D3DXMatrixPerspectiveOffCenterRH(&gotmat, 0.2f, 0.75f, -2.4f, 8.7f, 3.2f, -16.9f); + expect_matrix(&expectedmat, &gotmat, 8); + +/*____________D3DXMatrixPerspectiveRH_______________*/ + set_matrix(&expectedmat, + -24.0f, -0.0f, 0.0f, 0.0f, + 0.0f, -6.4f, 0.0f, 0.0f, + 0.0f, 0.0f, -0.78378378f, -1.0f, + 0.0f, 0.0f, 1.8810811f, 0.0f); + D3DXMatrixPerspectiveRH(&gotmat, 0.2f, 0.75f, -2.4f, 8.7f); + expect_matrix(&expectedmat, &gotmat, 4); + +/*____________D3DXMatrixReflect______________*/ + set_matrix(&expectedmat, + 0.30769235f, -0.23076922f, 0.92307687f, 0.0f, + -0.23076922, 0.92307693f, 0.30769232f, 0.0f, + 0.92307687f, 0.30769232f, -0.23076922f, 0.0f, + 1.6153846f, 0.53846157f, -2.1538463f, 1.0f); + D3DXMatrixReflect(&gotmat, &plane); + expect_matrix(&expectedmat, &gotmat, 32); + +/*____________D3DXMatrixRotationAxis_____*/ + set_matrix(&expectedmat, + 0.50847453f, 0.76380461f, 0.39756277f, 0.0f, + -0.81465209f, 0.57627118f, -0.065219201f, 0.0f, + -0.27891868f, -0.29071301f, 0.91525424f, 0.0f, + 0.0f, 0.0f, 0.0f, 1.0f); + D3DXMatrixRotationAxis(&gotmat, &axis, angle); + expect_matrix(&expectedmat, &gotmat, 32); + +/*____________D3DXMatrixRotationQuaternion______________*/ + set_matrix(&expectedmat, + -129.0f, -162.0f, -74.0f, 0.0f, + 146.0f, -99.0f, -78.0f, 0.0f, + 102.0f, -34.0f, -33.0f, 0.0f, + 0.0f, 0.0f, 0.0f, 1.0f); + D3DXMatrixRotationQuaternion(&gotmat, &q); + expect_matrix(&expectedmat, &gotmat, 0); + +/*____________D3DXMatrixRotationX______________*/ + set_matrix(&expectedmat, + 1.0f, 0.0f, 0.0f, 0.0f, + 0.0f, 0.5f, sqrt(3.0f)/2.0f, 0.0f, + 0.0f, -sqrt(3.0f)/2.0f, 0.5f, 0.0f, + 0.0f, 0.0f, 0.0f, 1.0f); + D3DXMatrixRotationX(&gotmat, angle); + expect_matrix(&expectedmat, &gotmat, 1); + +/*____________D3DXMatrixRotationY______________*/ + set_matrix(&expectedmat, + 0.5f, 0.0f, -sqrt(3.0f)/2.0f, 0.0f, + 0.0f, 1.0f, 0.0f, 0.0f, + sqrt(3.0f)/2.0f, 0.0f, 0.5f, 0.0f, + 0.0f, 0.0f, 0.0f, 1.0f); + D3DXMatrixRotationY(&gotmat, angle); + expect_matrix(&expectedmat, &gotmat, 1); + +/*____________D3DXMatrixRotationYawPitchRoll____*/ + set_matrix(&expectedmat, + 0.88877726f, 0.091874748f, -0.44903678f, 0.0f, + 0.35171318f, 0.49148652f, 0.79670501f, 0.0f, + 0.29389259f, -0.86602545f, 0.40450847f, 0.0f, + 0.0f, 0.0f, 0.0f, 1.0f); + D3DXMatrixRotationYawPitchRoll(&gotmat, 3.0f * angle / 5.0f, angle, 3.0f * angle / 17.0f); + expect_matrix(&expectedmat, &gotmat, 64); + +/*____________D3DXMatrixRotationZ______________*/ + set_matrix(&expectedmat, + 0.5f, sqrt(3.0f)/2.0f, 0.0f, 0.0f, + -sqrt(3.0f)/2.0f, 0.5f, 0.0f, 0.0f, + 0.0f, 0.0f, 1.0f, 0.0f, + 0.0f, 0.0f, 0.0f, 1.0f); + D3DXMatrixRotationZ(&gotmat, angle); + expect_matrix(&expectedmat, &gotmat, 1); + +/*____________D3DXMatrixScaling______________*/ + set_matrix(&expectedmat, + 0.69f, 0.0f, 0.0f, 0.0f, + 0.0f, 0.53f, 0.0f, 0.0f, + 0.0f, 0.0f, 4.11f, 0.0f, + 0.0f, 0.0f, 0.0f, 1.0f); + D3DXMatrixScaling(&gotmat, 0.69f, 0.53f, 4.11f); + expect_matrix(&expectedmat, &gotmat, 0); + +/*____________D3DXMatrixShadow______________*/ + set_matrix(&expectedmat, + 12.786773f, 5.0009613f, 4.3537784f, 3.7065949f, + 1.8827150f, 8.8056154f, 1.4512594f, 1.2355317f, + -7.5308599f, -6.6679487f, 1.3335901f, -4.9421268f, + -13.179006f, -11.668910f, -10.158816f, -1.5100943f); + D3DXMatrixShadow(&gotmat, &light, &plane); + expect_matrix(&expectedmat, &gotmat, 8); + +/*____________D3DXMatrixTransformation______________*/ + set_matrix(&expectedmat, + -0.21480007f, 1.3116000f, 0.47520003f, 0.0f, + 0.95040143f, -0.88360137f, 0.92439979f, 0.0f, + 1.0212044f, 0.19359307f, -1.3588026f, 0.0f, + 18.298532f, -29.624001f, 15.683499f, 1.0f); + D3DXMatrixTransformation(&gotmat, &at, &q, NULL, &eye, &r, &last); + expect_matrix(&expectedmat, &gotmat, 512); + +/*____________D3DXMatrixTranslation______________*/ + set_matrix(&expectedmat, + 1.0f, 0.0f, 0.0f, 0.0f, + 0.0f, 1.0f, 0.0f, 0.0f, + 0.0f, 0.0f, 1.0f, 0.0f, + 0.69f, 0.53f, 4.11f, 1.0f); + D3DXMatrixTranslation(&gotmat, 0.69f, 0.53f, 4.11f); + expect_matrix(&expectedmat, &gotmat, 0); + +/*____________D3DXMatrixTranspose______________*/ + set_matrix(&expectedmat, + 10.0f, 11.0f, 19.0f, 2.0f, + 5.0f, 20.0f, -21.0f, 3.0f, + 7.0f, 16.0f, 30.f, -4.0f, + 8.0f, 33.0f, 43.0f, -40.0f); + D3DXMatrixTranspose(&gotmat, &mat); + expect_matrix(&expectedmat, &gotmat, 0); +} + +static void D3DXPlaneTest(void) +{ + D3DXMATRIX mat; + D3DXPLANE expectedplane, gotplane, nulplane, plane; + D3DXVECTOR3 expectedvec, gotvec, vec1, vec2, vec3; + LPD3DXVECTOR3 funcpointer; + D3DXVECTOR4 vec; + FLOAT expected, got; + + U(mat).m[0][1] = 5.0f; U(mat).m[0][2] = 7.0f; U(mat).m[0][3] = 8.0f; + U(mat).m[1][0] = 11.0f; U(mat).m[1][2] = 16.0f; U(mat).m[1][3] = 33.0f; + U(mat).m[2][0] = 19.0f; U(mat).m[2][1] = -21.0f; U(mat).m[2][3] = 43.0f; + U(mat).m[3][0] = 2.0f; U(mat).m[3][1] = 3.0f; U(mat).m[3][2] = -4.0f; + U(mat).m[0][0] = 10.0f; U(mat).m[1][1] = 20.0f; U(mat).m[2][2] = 30.0f; + U(mat).m[3][3] = -40.0f; + + plane.a = -3.0f; plane.b = -1.0f; plane.c = 4.0f; plane.d = 7.0f; + + vec.x = 2.0f; vec.y = 5.0f; vec.z = -6.0f; vec.w = 11.0f; + +/*_______________D3DXPlaneDot________________*/ + expected = 42.0f; + got = D3DXPlaneDot(&plane,&vec), + ok( expected == got, "Expected : %f, Got : %f\n",expected, got); + expected = 0.0f; + got = D3DXPlaneDot(NULL,&vec), + ok( expected == got, "Expected : %f, Got : %f\n",expected, got); + expected = 0.0f; + got = D3DXPlaneDot(NULL,NULL), + ok( expected == got, "Expected : %f, Got : %f\n",expected, got); + +/*_______________D3DXPlaneDotCoord________________*/ + expected = -28.0f; + got = D3DXPlaneDotCoord(&plane,&vec), + ok( expected == got, "Expected : %f, Got : %f\n",expected, got); + expected = 0.0f; + got = D3DXPlaneDotCoord(NULL,&vec), + ok( expected == got, "Expected : %f, Got : %f\n",expected, got); + expected = 0.0f; + got = D3DXPlaneDotCoord(NULL,NULL), + ok( expected == got, "Expected : %f, Got : %f\n",expected, got); + +/*_______________D3DXPlaneDotNormal______________*/ + expected = -35.0f; + got = D3DXPlaneDotNormal(&plane,&vec), + ok( expected == got, "Expected : %f, Got : %f\n",expected, got); + expected = 0.0f; + got = D3DXPlaneDotNormal(NULL,&vec), + ok( expected == got, "Expected : %f, Got : %f\n",expected, got); + expected = 0.0f; + got = D3DXPlaneDotNormal(NULL,NULL), + ok( expected == got, "Expected : %f, Got : %f\n",expected, got); + +/*_______________D3DXPlaneFromPointNormal_______*/ + vec1.x = 11.0f; vec1.y = 13.0f; vec1.z = 15.0f; + vec2.x = 17.0f; vec2.y = 31.0f; vec2.z = 24.0f; + expectedplane.a = 17.0f; expectedplane.b = 31.0f; expectedplane.c = 24.0f; expectedplane.d = -950.0f; + D3DXPlaneFromPointNormal(&gotplane, &vec1, &vec2); + expect_plane(&expectedplane, &gotplane, 0); + gotplane.a = vec2.x; gotplane.b = vec2.y; gotplane.c = vec2.z; + D3DXPlaneFromPointNormal(&gotplane, &vec1, (D3DXVECTOR3 *)&gotplane); + expect_plane(&expectedplane, &gotplane, 0); + gotplane.a = vec1.x; gotplane.b = vec1.y; gotplane.c = vec1.z; + expectedplane.d = -1826.0f; + D3DXPlaneFromPointNormal(&gotplane, (D3DXVECTOR3 *)&gotplane, &vec2); + expect_plane(&expectedplane, &gotplane, 0); + +/*_______________D3DXPlaneFromPoints_______*/ + vec1.x = 1.0f; vec1.y = 2.0f; vec1.z = 3.0f; + vec2.x = 1.0f; vec2.y = -6.0f; vec2.z = -5.0f; + vec3.x = 83.0f; vec3.y = 74.0f; vec3.z = 65.0f; + expectedplane.a = 0.085914f; expectedplane.b = -0.704492f; expectedplane.c = 0.704492f; expectedplane.d = -0.790406f; + D3DXPlaneFromPoints(&gotplane,&vec1,&vec2,&vec3); + expect_plane(&expectedplane, &gotplane, 64); + +/*_______________D3DXPlaneIntersectLine___________*/ + vec1.x = 9.0f; vec1.y = 6.0f; vec1.z = 3.0f; + vec2.x = 2.0f; vec2.y = 5.0f; vec2.z = 8.0f; + expectedvec.x = 20.0f/3.0f; expectedvec.y = 17.0f/3.0f; expectedvec.z = 14.0f/3.0f; + D3DXPlaneIntersectLine(&gotvec,&plane,&vec1,&vec2); + expect_vec3(&expectedvec, &gotvec, 1); + /* Test a parallel line */ + vec1.x = 11.0f; vec1.y = 13.0f; vec1.z = 15.0f; + vec2.x = 17.0f; vec2.y = 31.0f; vec2.z = 24.0f; + expectedvec.x = 20.0f/3.0f; expectedvec.y = 17.0f/3.0f; expectedvec.z = 14.0f/3.0f; + funcpointer = D3DXPlaneIntersectLine(&gotvec,&plane,&vec1,&vec2); + ok(funcpointer == NULL, "Expected: %p, Got: %p\n", NULL, funcpointer); + +/*_______________D3DXPlaneNormalize______________*/ + expectedplane.a = -3.0f/sqrt(26.0f); expectedplane.b = -1.0f/sqrt(26.0f); expectedplane.c = 4.0f/sqrt(26.0f); expectedplane.d = 7.0/sqrt(26.0f); + D3DXPlaneNormalize(&gotplane, &plane); + expect_plane(&expectedplane, &gotplane, 2); + nulplane.a = 0.0; nulplane.b = 0.0f, nulplane.c = 0.0f; nulplane.d = 0.0f; + expectedplane.a = 0.0f; expectedplane.b = 0.0f; expectedplane.c = 0.0f; expectedplane.d = 0.0f; + D3DXPlaneNormalize(&gotplane, &nulplane); + expect_plane(&expectedplane, &gotplane, 0); + +/*_______________D3DXPlaneTransform____________*/ + expectedplane.a = 49.0f; expectedplane.b = -98.0f; expectedplane.c = 55.0f; expectedplane.d = -165.0f; + D3DXPlaneTransform(&gotplane,&plane,&mat); + expect_plane(&expectedplane, &gotplane, 0); +} + +static void D3DXQuaternionTest(void) +{ + D3DXMATRIX mat; + D3DXQUATERNION expectedquat, gotquat, Nq, Nq1, nul, smallq, smallr, q, r, s, t, u; + BOOL expectedbool, gotbool, equal; + float angle, got, scale, scale2; + LPD3DXQUATERNION funcpointer; + D3DXVECTOR3 axis, expectedvec; + + nul.x = 0.0f; nul.y = 0.0f; nul.z = 0.0f; nul.w = 0.0f; + q.x = 1.0f, q.y = 2.0f; q.z = 4.0f; q.w = 10.0f; + r.x = -3.0f; r.y = 4.0f; r.z = -5.0f; r.w = 7.0; + t.x = -1111.0f, t.y = 111.0f; t.z = -11.0f; t.w = 1.0f; + u.x = 91.0f; u.y = - 82.0f; u.z = 7.3f; u.w = -6.4f; + smallq.x = 0.1f; smallq.y = 0.2f; smallq.z= 0.3f; smallq.w = 0.4f; + smallr.x = 0.5f; smallr.y = 0.6f; smallr.z= 0.7f; smallr.w = 0.8f; + + scale = 0.3f; + scale2 = 0.78f; + +/*_______________D3DXQuaternionBaryCentric________________________*/ + expectedquat.x = -867.444458; expectedquat.y = 87.851111f; expectedquat.z = -9.937778f; expectedquat.w = 3.235555f; + D3DXQuaternionBaryCentric(&gotquat,&q,&r,&t,scale,scale2); + expect_quaternion(&expectedquat, &gotquat, 1); + +/*_______________D3DXQuaternionConjugate________________*/ + expectedquat.x = -1.0f; expectedquat.y = -2.0f; expectedquat.z = -4.0f; expectedquat.w = 10.0f; + D3DXQuaternionConjugate(&gotquat,&q); + expect_quaternion(&expectedquat, &gotquat, 0); + /* Test the NULL case */ + funcpointer = D3DXQuaternionConjugate(&gotquat,NULL); + ok(funcpointer == NULL, "Expected: %p, Got: %p\n", NULL, funcpointer); + funcpointer = D3DXQuaternionConjugate(NULL,NULL); + ok(funcpointer == NULL, "Expected: %p, Got: %p\n", NULL, funcpointer); + +/*_______________D3DXQuaternionDot______________________*/ + got = D3DXQuaternionDot(&q,&r); + equal = compare_float(got, 55.0f, 0); + ok(equal, "Got unexpected dot %.8e.\n", got); + /* Tests the case NULL */ + got = D3DXQuaternionDot(NULL,&r); + equal = compare_float(got, 0.0f, 0); + ok(equal, "Got unexpected dot %.8e.\n", got); + got = D3DXQuaternionDot(NULL,NULL); + equal = compare_float(got, 0.0f, 0); + ok(equal, "Got unexpected dot %.8e.\n", got); + +/*_______________D3DXQuaternionExp______________________________*/ + expectedquat.x = -0.216382f; expectedquat.y = -0.432764f; expectedquat.z = -0.8655270f; expectedquat.w = -0.129449f; + D3DXQuaternionExp(&gotquat,&q); + expect_quaternion(&expectedquat, &gotquat, 16); + /* Test the null quaternion */ + expectedquat.x = 0.0f; expectedquat.y = 0.0f; expectedquat.z = 0.0f; expectedquat.w = 1.0f; + D3DXQuaternionExp(&gotquat,&nul); + expect_quaternion(&expectedquat, &gotquat, 0); + /* Test the case where the norm of the quaternion is <1 */ + Nq1.x = 0.2f; Nq1.y = 0.1f; Nq1.z = 0.3; Nq1.w= 0.9f; + expectedquat.x = 0.195366; expectedquat.y = 0.097683f; expectedquat.z = 0.293049f; expectedquat.w = 0.930813f; + D3DXQuaternionExp(&gotquat,&Nq1); + expect_quaternion(&expectedquat, &gotquat, 8); + +/*_______________D3DXQuaternionIdentity________________*/ + expectedquat.x = 0.0f; expectedquat.y = 0.0f; expectedquat.z = 0.0f; expectedquat.w = 1.0f; + D3DXQuaternionIdentity(&gotquat); + expect_quaternion(&expectedquat, &gotquat, 0); + /* Test the NULL case */ + funcpointer = D3DXQuaternionIdentity(NULL); + ok(funcpointer == NULL, "Expected: %p, Got: %p\n", NULL, funcpointer); + +/*_______________D3DXQuaternionInverse________________________*/ + expectedquat.x = -1.0f/121.0f; expectedquat.y = -2.0f/121.0f; expectedquat.z = -4.0f/121.0f; expectedquat.w = 10.0f/121.0f; + D3DXQuaternionInverse(&gotquat,&q); + expect_quaternion(&expectedquat, &gotquat, 0); + + expectedquat.x = 1.0f; expectedquat.y = 2.0f; expectedquat.z = 4.0f; expectedquat.w = 10.0f; + D3DXQuaternionInverse(&gotquat,&gotquat); + expect_quaternion(&expectedquat, &gotquat, 1); + + +/*_______________D3DXQuaternionIsIdentity________________*/ + s.x = 0.0f; s.y = 0.0f; s.z = 0.0f; s.w = 1.0f; + expectedbool = TRUE; + gotbool = D3DXQuaternionIsIdentity(&s); + ok( expectedbool == gotbool, "Expected boolean : %d, Got bool : %d\n", expectedbool, gotbool); + s.x = 2.3f; s.y = -4.2f; s.z = 1.2f; s.w=0.2f; + expectedbool = FALSE; + gotbool = D3DXQuaternionIsIdentity(&q); + ok( expectedbool == gotbool, "Expected boolean : %d, Got bool : %d\n", expectedbool, gotbool); + /* Test the NULL case */ + gotbool = D3DXQuaternionIsIdentity(NULL); + ok(gotbool == FALSE, "Expected boolean: %d, Got boolean: %d\n", FALSE, gotbool); + +/*_______________D3DXQuaternionLength__________________________*/ + got = D3DXQuaternionLength(&q); + equal = compare_float(got, 11.0f, 0); + ok(equal, "Got unexpected length %.8e.\n", got); + /* Tests the case NULL. */ + got = D3DXQuaternionLength(NULL); + equal = compare_float(got, 0.0f, 0); + ok(equal, "Got unexpected length %.8e.\n", got); + +/*_______________D3DXQuaternionLengthSq________________________*/ + got = D3DXQuaternionLengthSq(&q); + equal = compare_float(got, 121.0f, 0); + ok(equal, "Got unexpected length %.8e.\n", got); + /* Tests the case NULL */ + got = D3DXQuaternionLengthSq(NULL); + equal = compare_float(got, 0.0f, 0); + ok(equal, "Got unexpected length %.8e.\n", got); + +/*_______________D3DXQuaternionLn______________________________*/ + expectedquat.x = 1.0f; expectedquat.y = 2.0f; expectedquat.z = 4.0f; expectedquat.w = 0.0f; + D3DXQuaternionLn(&gotquat,&q); + expect_quaternion(&expectedquat, &gotquat, 0); + expectedquat.x = -3.0f; expectedquat.y = 4.0f; expectedquat.z = -5.0f; expectedquat.w = 0.0f; + D3DXQuaternionLn(&gotquat,&r); + expect_quaternion(&expectedquat, &gotquat, 0); + Nq.x = 1.0f/11.0f; Nq.y = 2.0f/11.0f; Nq.z = 4.0f/11.0f; Nq.w=10.0f/11.0f; + expectedquat.x = 0.093768f; expectedquat.y = 0.187536f; expectedquat.z = 0.375073f; expectedquat.w = 0.0f; + D3DXQuaternionLn(&gotquat,&Nq); + expect_quaternion(&expectedquat, &gotquat, 32); + Nq.x = 0.0f; Nq.y = 0.0f; Nq.z = 0.0f; Nq.w = 1.0f; + expectedquat.x = 0.0f; expectedquat.y = 0.0f; expectedquat.z = 0.0f; expectedquat.w = 0.0f; + D3DXQuaternionLn(&gotquat,&Nq); + expect_quaternion(&expectedquat, &gotquat, 0); + Nq.x = 5.4f; Nq.y = 1.2f; Nq.z = -0.3f; Nq.w = -0.3f; + expectedquat.x = 10.616652f; expectedquat.y = 2.359256f; expectedquat.z = -0.589814f; expectedquat.w = 0.0f; + D3DXQuaternionLn(&gotquat,&Nq); + expect_quaternion(&expectedquat, &gotquat, 1); + /* Test the case where the norm of the quaternion is <1 */ + Nq1.x = 0.2f; Nq1.y = 0.1f; Nq1.z = 0.3; Nq1.w = 0.9f; + expectedquat.x = 0.206945f; expectedquat.y = 0.103473f; expectedquat.z = 0.310418f; expectedquat.w = 0.0f; + D3DXQuaternionLn(&gotquat,&Nq1); + expect_quaternion(&expectedquat, &gotquat, 64); + /* Test the case where the real part of the quaternion is -1.0f */ + Nq1.x = 0.2f; Nq1.y = 0.1f; Nq1.z = 0.3; Nq1.w = -1.0f; + expectedquat.x = 0.2f; expectedquat.y = 0.1f; expectedquat.z = 0.3f; expectedquat.w = 0.0f; + D3DXQuaternionLn(&gotquat,&Nq1); + expect_quaternion(&expectedquat, &gotquat, 0); + +/*_______________D3DXQuaternionMultiply________________________*/ + expectedquat.x = 3.0f; expectedquat.y = 61.0f; expectedquat.z = -32.0f; expectedquat.w = 85.0f; + D3DXQuaternionMultiply(&gotquat,&q,&r); + expect_quaternion(&expectedquat, &gotquat, 0); + +/*_______________D3DXQuaternionNormalize________________________*/ + expectedquat.x = 1.0f/11.0f; expectedquat.y = 2.0f/11.0f; expectedquat.z = 4.0f/11.0f; expectedquat.w = 10.0f/11.0f; + D3DXQuaternionNormalize(&gotquat,&q); + expect_quaternion(&expectedquat, &gotquat, 1); + +/*_______________D3DXQuaternionRotationAxis___________________*/ + axis.x = 2.0f; axis.y = 7.0; axis.z = 13.0f; + angle = D3DX_PI/3.0f; + expectedquat.x = 0.067116; expectedquat.y = 0.234905f; expectedquat.z = 0.436251f; expectedquat.w = 0.866025f; + D3DXQuaternionRotationAxis(&gotquat,&axis,angle); + expect_quaternion(&expectedquat, &gotquat, 64); + /* Test the nul quaternion */ + axis.x = 0.0f; axis.y = 0.0; axis.z = 0.0f; + expectedquat.x = 0.0f; expectedquat.y = 0.0f; expectedquat.z = 0.0f; expectedquat.w = 0.866025f; + D3DXQuaternionRotationAxis(&gotquat,&axis,angle); + expect_quaternion(&expectedquat, &gotquat, 8); + +/*_______________D3DXQuaternionRotationMatrix___________________*/ + /* test when the trace is >0 */ + U(mat).m[0][1] = 5.0f; U(mat).m[0][2] = 7.0f; U(mat).m[0][3] = 8.0f; + U(mat).m[1][0] = 11.0f; U(mat).m[1][2] = 16.0f; U(mat).m[1][3] = 33.0f; + U(mat).m[2][0] = 19.0f; U(mat).m[2][1] = -21.0f; U(mat).m[2][3] = 43.0f; + U(mat).m[3][0] = 2.0f; U(mat).m[3][1] = 3.0f; U(mat).m[3][2] = -4.0f; + U(mat).m[0][0] = 10.0f; U(mat).m[1][1] = 20.0f; U(mat).m[2][2] = 30.0f; + U(mat).m[3][3] = 48.0f; + expectedquat.x = 2.368682f; expectedquat.y = 0.768221f; expectedquat.z = -0.384111f; expectedquat.w = 3.905125f; + D3DXQuaternionRotationMatrix(&gotquat,&mat); + expect_quaternion(&expectedquat, &gotquat, 16); + /* test the case when the greater element is (2,2) */ + U(mat).m[0][1] = 5.0f; U(mat).m[0][2] = 7.0f; U(mat).m[0][3] = 8.0f; + U(mat).m[1][0] = 11.0f; U(mat).m[1][2] = 16.0f; U(mat).m[1][3] = 33.0f; + U(mat).m[2][0] = 19.0f; U(mat).m[2][1] = -21.0f; U(mat).m[2][3] = 43.0f; + U(mat).m[3][0] = 2.0f; U(mat).m[3][1] = 3.0f; U(mat).m[3][2] = -4.0f; + U(mat).m[0][0] = -10.0f; U(mat).m[1][1] = -60.0f; U(mat).m[2][2] = 40.0f; + U(mat).m[3][3] = 48.0f; + expectedquat.x = 1.233905f; expectedquat.y = -0.237290f; expectedquat.z = 5.267827f; expectedquat.w = -0.284747f; + D3DXQuaternionRotationMatrix(&gotquat,&mat); + expect_quaternion(&expectedquat, &gotquat, 64); + /* test the case when the greater element is (1,1) */ + U(mat).m[0][1] = 5.0f; U(mat).m[0][2] = 7.0f; U(mat).m[0][3] = 8.0f; + U(mat).m[1][0] = 11.0f; U(mat).m[1][2] = 16.0f; U(mat).m[1][3] = 33.0f; + U(mat).m[2][0] = 19.0f; U(mat).m[2][1] = -21.0f; U(mat).m[2][3] = 43.0f; + U(mat).m[3][0] = 2.0f; U(mat).m[3][1] = 3.0f; U(mat).m[3][2] = -4.0f; + U(mat).m[0][0] = -10.0f; U(mat).m[1][1] = 60.0f; U(mat).m[2][2] = -80.0f; + U(mat).m[3][3] = 48.0f; + expectedquat.x = 0.651031f; expectedquat.y = 6.144103f; expectedquat.z = -0.203447f; expectedquat.w = 0.488273f; + D3DXQuaternionRotationMatrix(&gotquat,&mat); + expect_quaternion(&expectedquat, &gotquat, 8); + /* test the case when the trace is near 0 in a matrix which is not a rotation */ + U(mat).m[0][1] = 5.0f; U(mat).m[0][2] = 7.0f; U(mat).m[0][3] = 8.0f; + U(mat).m[1][0] = 11.0f; U(mat).m[1][2] = 16.0f; U(mat).m[1][3] = 33.0f; + U(mat).m[2][0] = 19.0f; U(mat).m[2][1] = -21.0f; U(mat).m[2][3] = 43.0f; + U(mat).m[3][0] = 2.0f; U(mat).m[3][1] = 3.0f; U(mat).m[3][2] = -4.0f; + U(mat).m[0][0] = -10.0f; U(mat).m[1][1] = 10.0f; U(mat).m[2][2] = -0.9f; + U(mat).m[3][3] = 48.0f; + expectedquat.x = 1.709495f; expectedquat.y = 2.339872f; expectedquat.z = -0.534217f; expectedquat.w = 1.282122f; + D3DXQuaternionRotationMatrix(&gotquat,&mat); + expect_quaternion(&expectedquat, &gotquat, 8); + /* test the case when the trace is 0.49 in a matrix which is not a rotation */ + U(mat).m[0][1] = 5.0f; U(mat).m[0][2] = 7.0f; U(mat).m[0][3] = 8.0f; + U(mat).m[1][0] = 11.0f; U(mat).m[1][2] = 16.0f; U(mat).m[1][3] = 33.0f; + U(mat).m[2][0] = 19.0f; U(mat).m[2][1] = -21.0f; U(mat).m[2][3] = 43.0f; + U(mat).m[3][0] = 2.0f; U(mat).m[3][1] = 3.0f; U(mat).m[3][2] = -4.0f; + U(mat).m[0][0] = -10.0f; U(mat).m[1][1] = 10.0f; U(mat).m[2][2] = -0.51f; + U(mat).m[3][3] = 48.0f; + expectedquat.x = 1.724923f; expectedquat.y = 2.318944f; expectedquat.z = -0.539039f; expectedquat.w = 1.293692f; + D3DXQuaternionRotationMatrix(&gotquat,&mat); + expect_quaternion(&expectedquat, &gotquat, 8); + /* test the case when the trace is 0.51 in a matrix which is not a rotation */ + U(mat).m[0][1] = 5.0f; U(mat).m[0][2] = 7.0f; U(mat).m[0][3] = 8.0f; + U(mat).m[1][0] = 11.0f; U(mat).m[1][2] = 16.0f; U(mat).m[1][3] = 33.0f; + U(mat).m[2][0] = 19.0f; U(mat).m[2][1] = -21.0f; U(mat).m[2][3] = 43.0f; + U(mat).m[3][0] = 2.0f; U(mat).m[3][1] = 3.0f; U(mat).m[3][2] = -4.0f; + U(mat).m[0][0] = -10.0f; U(mat).m[1][1] = 10.0f; U(mat).m[2][2] = -0.49f; + U(mat).m[3][3] = 48.0f; + expectedquat.x = 1.725726f; expectedquat.y = 2.317865f; expectedquat.z = -0.539289f; expectedquat.w = 1.294294f; + D3DXQuaternionRotationMatrix(&gotquat,&mat); + expect_quaternion(&expectedquat, &gotquat, 8); + /* test the case when the trace is 0.99 in a matrix which is not a rotation */ + U(mat).m[0][1] = 5.0f; U(mat).m[0][2] = 7.0f; U(mat).m[0][3] = 8.0f; + U(mat).m[1][0] = 11.0f; U(mat).m[1][2] = 16.0f; U(mat).m[1][3] = 33.0f; + U(mat).m[2][0] = 19.0f; U(mat).m[2][1] = -21.0f; U(mat).m[2][3] = 43.0f; + U(mat).m[3][0] = 2.0f; U(mat).m[3][1] = 3.0f; U(mat).m[3][2] = -4.0f; + U(mat).m[0][0] = -10.0f; U(mat).m[1][1] = 10.0f; U(mat).m[2][2] = -0.01f; + U(mat).m[3][3] = 48.0f; + expectedquat.x = 1.745328f; expectedquat.y = 2.291833f; expectedquat.z = -0.545415f; expectedquat.w = 1.308996f; + D3DXQuaternionRotationMatrix(&gotquat,&mat); + expect_quaternion(&expectedquat, &gotquat, 4); + /* test the case when the trace is 1.0 in a matrix which is not a rotation */ + U(mat).m[0][1] = 5.0f; U(mat).m[0][2] = 7.0f; U(mat).m[0][3] = 8.0f; + U(mat).m[1][0] = 11.0f; U(mat).m[1][2] = 16.0f; U(mat).m[1][3] = 33.0f; + U(mat).m[2][0] = 19.0f; U(mat).m[2][1] = -21.0f; U(mat).m[2][3] = 43.0f; + U(mat).m[3][0] = 2.0f; U(mat).m[3][1] = 3.0f; U(mat).m[3][2] = -4.0f; + U(mat).m[0][0] = -10.0f; U(mat).m[1][1] = 10.0f; U(mat).m[2][2] = 0.0f; + U(mat).m[3][3] = 48.0f; + expectedquat.x = 1.745743f; expectedquat.y = 2.291288f; expectedquat.z = -0.545545f; expectedquat.w = 1.309307f; + D3DXQuaternionRotationMatrix(&gotquat,&mat); + expect_quaternion(&expectedquat, &gotquat, 8); + /* test the case when the trace is 1.01 in a matrix which is not a rotation */ + U(mat).m[0][1] = 5.0f; U(mat).m[0][2] = 7.0f; U(mat).m[0][3] = 8.0f; + U(mat).m[1][0] = 11.0f; U(mat).m[1][2] = 16.0f; U(mat).m[1][3] = 33.0f; + U(mat).m[2][0] = 19.0f; U(mat).m[2][1] = -21.0f; U(mat).m[2][3] = 43.0f; + U(mat).m[3][0] = 2.0f; U(mat).m[3][1] = 3.0f; U(mat).m[3][2] = -4.0f; + U(mat).m[0][0] = -10.0f; U(mat).m[1][1] = 10.0f; U(mat).m[2][2] = 0.01f; + U(mat).m[3][3] = 48.0f; + expectedquat.x = 18.408188f; expectedquat.y = 5.970223f; expectedquat.z = -2.985111f; expectedquat.w = 0.502494f; + D3DXQuaternionRotationMatrix(&gotquat,&mat); + expect_quaternion(&expectedquat, &gotquat, 4); + /* test the case when the trace is 1.5 in a matrix which is not a rotation */ + U(mat).m[0][1] = 5.0f; U(mat).m[0][2] = 7.0f; U(mat).m[0][3] = 8.0f; + U(mat).m[1][0] = 11.0f; U(mat).m[1][2] = 16.0f; U(mat).m[1][3] = 33.0f; + U(mat).m[2][0] = 19.0f; U(mat).m[2][1] = -21.0f; U(mat).m[2][3] = 43.0f; + U(mat).m[3][0] = 2.0f; U(mat).m[3][1] = 3.0f; U(mat).m[3][2] = -4.0f; + U(mat).m[0][0] = -10.0f; U(mat).m[1][1] = 10.0f; U(mat).m[2][2] = 0.5f; + U(mat).m[3][3] = 48.0f; + expectedquat.x = 15.105186f; expectedquat.y = 4.898980f; expectedquat.z = -2.449490f; expectedquat.w = 0.612372f; + D3DXQuaternionRotationMatrix(&gotquat,&mat); + expect_quaternion(&expectedquat, &gotquat, 8); + /* test the case when the trace is 1.7 in a matrix which is not a rotation */ + U(mat).m[0][1] = 5.0f; U(mat).m[0][2] = 7.0f; U(mat).m[0][3] = 8.0f; + U(mat).m[1][0] = 11.0f; U(mat).m[1][2] = 16.0f; U(mat).m[1][3] = 33.0f; + U(mat).m[2][0] = 19.0f; U(mat).m[2][1] = -21.0f; U(mat).m[2][3] = 43.0f; + U(mat).m[3][0] = 2.0f; U(mat).m[3][1] = 3.0f; U(mat).m[3][2] = -4.0f; + U(mat).m[0][0] = -10.0f; U(mat).m[1][1] = 10.0f; U(mat).m[2][2] = 0.70f; + U(mat).m[3][3] = 48.0f; + expectedquat.x = 14.188852f; expectedquat.y = 4.601790f; expectedquat.z = -2.300895f; expectedquat.w = 0.651920f; + D3DXQuaternionRotationMatrix(&gotquat,&mat); + expect_quaternion(&expectedquat, &gotquat, 4); + /* test the case when the trace is 1.99 in a matrix which is not a rotation */ + U(mat).m[0][1] = 5.0f; U(mat).m[0][2] = 7.0f; U(mat).m[0][3] = 8.0f; + U(mat).m[1][0] = 11.0f; U(mat).m[1][2] = 16.0f; U(mat).m[1][3] = 33.0f; + U(mat).m[2][0] = 19.0f; U(mat).m[2][1] = -21.0f; U(mat).m[2][3] = 43.0f; + U(mat).m[3][0] = 2.0f; U(mat).m[3][1] = 3.0f; U(mat).m[3][2] = -4.0f; + U(mat).m[0][0] = -10.0f; U(mat).m[1][1] = 10.0f; U(mat).m[2][2] = 0.99f; + U(mat).m[3][3] = 48.0f; + expectedquat.x = 13.114303f; expectedquat.y = 4.253287f; expectedquat.z = -2.126644f; expectedquat.w = 0.705337f; + D3DXQuaternionRotationMatrix(&gotquat,&mat); + expect_quaternion(&expectedquat, &gotquat, 4); + /* test the case when the trace is 2.0 in a matrix which is not a rotation */ + U(mat).m[0][1] = 5.0f; U(mat).m[0][2] = 7.0f; U(mat).m[0][3] = 8.0f; + U(mat).m[1][0] = 11.0f; U(mat).m[1][2] = 16.0f; U(mat).m[1][3] = 33.0f; + U(mat).m[2][0] = 19.0f; U(mat).m[2][1] = -21.0f; U(mat).m[2][3] = 43.0f; + U(mat).m[3][0] = 2.0f; U(mat).m[3][1] = 3.0f; U(mat).m[3][2] = -4.0f; + U(mat).m[0][0] = -10.0f; U(mat).m[1][1] = 10.0f; U(mat).m[2][2] = 2.0f; + U(mat).m[3][3] = 48.0f; + expectedquat.x = 10.680980f; expectedquat.y = 3.464102f; expectedquat.z = -1.732051f; expectedquat.w = 0.866025f; + D3DXQuaternionRotationMatrix(&gotquat,&mat); + expect_quaternion(&expectedquat, &gotquat, 8); + +/*_______________D3DXQuaternionRotationYawPitchRoll__________*/ + expectedquat.x = 0.303261f; expectedquat.y = 0.262299f; expectedquat.z = 0.410073f; expectedquat.w = 0.819190f; + D3DXQuaternionRotationYawPitchRoll(&gotquat,D3DX_PI/4.0f,D3DX_PI/11.0f,D3DX_PI/3.0f); + expect_quaternion(&expectedquat, &gotquat, 16); + +/*_______________D3DXQuaternionSlerp________________________*/ + expectedquat.x = -0.2f; expectedquat.y = 2.6f; expectedquat.z = 1.3f; expectedquat.w = 9.1f; + D3DXQuaternionSlerp(&gotquat,&q,&r,scale); + expect_quaternion(&expectedquat, &gotquat, 4); + expectedquat.x = 334.0f; expectedquat.y = -31.9f; expectedquat.z = 6.1f; expectedquat.w = 6.7f; + D3DXQuaternionSlerp(&gotquat,&q,&t,scale); + expect_quaternion(&expectedquat, &gotquat, 2); + expectedquat.x = 0.239485f; expectedquat.y = 0.346580f; expectedquat.z = 0.453676f; expectedquat.w = 0.560772f; + D3DXQuaternionSlerp(&gotquat,&smallq,&smallr,scale); + expect_quaternion(&expectedquat, &gotquat, 32); + +/*_______________D3DXQuaternionSquad________________________*/ + expectedquat.x = -156.296f; expectedquat.y = 30.242f; expectedquat.z = -2.5022f; expectedquat.w = 7.3576f; + D3DXQuaternionSquad(&gotquat,&q,&r,&t,&u,scale); + expect_quaternion(&expectedquat, &gotquat, 2); + +/*_______________D3DXQuaternionSquadSetup___________________*/ + r.x = 1.0f, r.y = 2.0f; r.z = 4.0f; r.w = 10.0f; + s.x = -3.0f; s.y = 4.0f; s.z = -5.0f; s.w = 7.0; + t.x = -1111.0f, t.y = 111.0f; t.z = -11.0f; t.w = 1.0f; + u.x = 91.0f; u.y = - 82.0f; u.z = 7.3f; u.w = -6.4f; + D3DXQuaternionSquadSetup(&gotquat, &Nq, &Nq1, &r, &s, &t, &u); + expectedquat.x = 7.121285f; expectedquat.y = 2.159964f; expectedquat.z = -3.855094f; expectedquat.w = 5.362844f; + expect_quaternion(&expectedquat, &gotquat, 2); + expectedquat.x = -1113.492920f; expectedquat.y = 82.679260f; expectedquat.z = -6.696645f; expectedquat.w = -4.090050f; + expect_quaternion(&expectedquat, &Nq, 2); + expectedquat.x = -1111.0f; expectedquat.y = 111.0f; expectedquat.z = -11.0f; expectedquat.w = 1.0f; + expect_quaternion(&expectedquat, &Nq1, 0); + gotquat = s; + D3DXQuaternionSquadSetup(&gotquat, &Nq, &Nq1, &r, &gotquat, &t, &u); + expectedquat.x = -1113.492920f; expectedquat.y = 82.679260f; expectedquat.z = -6.696645f; expectedquat.w = -4.090050f; + expect_quaternion(&expectedquat, &Nq, 2); + Nq1 = u; + D3DXQuaternionSquadSetup(&gotquat, &Nq, &Nq1, &r, &s, &t, &Nq1); + expect_quaternion(&expectedquat, &Nq, 2); + r.x = 0.2f; r.y = 0.3f; r.z = 1.3f; r.w = -0.6f; + s.x = -3.0f; s.y =-2.0f; s.z = 4.0f; s.w = 0.2f; + t.x = 0.4f; t.y = 8.3f; t.z = -3.1f; t.w = -2.7f; + u.x = 1.1f; u.y = -0.7f; u.z = 9.2f; u.w = 0.0f; + D3DXQuaternionSquadSetup(&gotquat, &Nq, &Nq1, &r, &s, &u, &t); + expectedquat.x = -4.139569f; expectedquat.y = -2.469115f; expectedquat.z = 2.364477f; expectedquat.w = 0.465494f; + expect_quaternion(&expectedquat, &gotquat, 16); + expectedquat.x = 2.342533f; expectedquat.y = 2.365127f; expectedquat.z = 8.628538f; expectedquat.w = -0.898356f; + expect_quaternion(&expectedquat, &Nq, 16); + expectedquat.x = 1.1f; expectedquat.y = -0.7f; expectedquat.z = 9.2f; expectedquat.w = 0.0f; + expect_quaternion(&expectedquat, &Nq1, 0); + D3DXQuaternionSquadSetup(&gotquat, &Nq, &Nq1, &r, &s, &t, &u); + expectedquat.x = -3.754567f; expectedquat.y = -0.586085f; expectedquat.z = 3.815818f; expectedquat.w = -0.198150f; + expect_quaternion(&expectedquat, &gotquat, 32); + expectedquat.x = 0.140773f; expectedquat.y = -8.737090f; expectedquat.z = -0.516593f; expectedquat.w = 3.053942f; + expect_quaternion(&expectedquat, &Nq, 16); + expectedquat.x = -0.4f; expectedquat.y = -8.3f; expectedquat.z = 3.1f; expectedquat.w = 2.7f; + expect_quaternion(&expectedquat, &Nq1, 0); + r.x = -1.0f; r.y = 0.0f; r.z = 0.0f; r.w = 0.0f; + s.x = 1.0f; s.y =0.0f; s.z = 0.0f; s.w = 0.0f; + t.x = 1.0f; t.y = 0.0f; t.z = 0.0f; t.w = 0.0f; + u.x = -1.0f; u.y = 0.0f; u.z = 0.0f; u.w = 0.0f; + D3DXQuaternionSquadSetup(&gotquat, &Nq, &Nq1, &r, &s, &t, &u); + expectedquat.x = 1.0f; expectedquat.y = 0.0f; expectedquat.z = 0.0f; expectedquat.w = 0.0f; + expect_quaternion(&expectedquat, &gotquat, 0); + expectedquat.x = 1.0f; expectedquat.y = 0.0f; expectedquat.z = 0.0f; expectedquat.w = 0.0f; + expect_quaternion(&expectedquat, &Nq, 0); + expectedquat.x = 1.0f; expectedquat.y = 0.0f; expectedquat.z = 0.0f; expectedquat.w = 0.0f; + expect_quaternion(&expectedquat, &Nq1, 0); + +/*_______________D3DXQuaternionToAxisAngle__________________*/ + Nq.x = 1.0f/22.0f; Nq.y = 2.0f/22.0f; Nq.z = 4.0f/22.0f; Nq.w = 10.0f/22.0f; + expectedvec.x = 1.0f/22.0f; expectedvec.y = 2.0f/22.0f; expectedvec.z = 4.0f/22.0f; + D3DXQuaternionToAxisAngle(&Nq,&axis,&angle); + expect_vec3(&expectedvec, &axis, 0); + equal = compare_float(angle, 2.197869f, 1); + ok(equal, "Got unexpected angle %.8e.\n", angle); + /* Test if |w|>1.0f */ + expectedvec.x = 1.0f; expectedvec.y = 2.0f; expectedvec.z = 4.0f; + D3DXQuaternionToAxisAngle(&q,&axis,&angle); + expect_vec3(&expectedvec, &axis, 0); + /* Test the null quaternion */ + expectedvec.x = 0.0f; expectedvec.y = 0.0f; expectedvec.z = 0.0f; + D3DXQuaternionToAxisAngle(&nul, &axis, &angle); + expect_vec3(&expectedvec, &axis, 0); + equal = compare_float(angle, 3.14159274e+00f, 0); + ok(equal, "Got unexpected angle %.8e.\n", angle); + + D3DXQuaternionToAxisAngle(&nul, &axis, NULL); + D3DXQuaternionToAxisAngle(&nul, NULL, &angle); + expect_vec3(&expectedvec, &axis, 0); + equal = compare_float(angle, 3.14159274e+00f, 0); + ok(equal, "Got unexpected angle %.8e.\n", angle); +} + +static void D3DXVector2Test(void) +{ + D3DXVECTOR2 expectedvec, gotvec, nul, u, v, w, x; + LPD3DXVECTOR2 funcpointer; + D3DXVECTOR4 expectedtrans, gottrans; + float coeff1, coeff2, got, scale; + D3DXMATRIX mat; + BOOL equal; + + nul.x = 0.0f; nul.y = 0.0f; + u.x = 3.0f; u.y = 4.0f; + v.x = -7.0f; v.y = 9.0f; + w.x = 4.0f; w.y = -3.0f; + x.x = 2.0f; x.y = -11.0f; + + set_matrix(&mat, + 1.0f, 2.0f, 3.0f, 4.0f, + 5.0f, 6.0f, 7.0f, 8.0f, + 9.0f, 10.0f, 11.0f, 12.0f, + 13.0f, 14.0f, 15.0f, 16.0f); + + coeff1 = 2.0f; coeff2 = 5.0f; + scale = -6.5f; + +/*_______________D3DXVec2Add__________________________*/ + expectedvec.x = -4.0f; expectedvec.y = 13.0f; + D3DXVec2Add(&gotvec,&u,&v); + expect_vec2(&expectedvec, &gotvec, 0); + /* Tests the case NULL */ + funcpointer = D3DXVec2Add(&gotvec,NULL,&v); + ok(funcpointer == NULL, "Expected: %p, Got: %p\n", NULL, funcpointer); + funcpointer = D3DXVec2Add(NULL,NULL,NULL); + ok(funcpointer == NULL, "Expected: %p, Got: %p\n", NULL, funcpointer); + +/*_______________D3DXVec2BaryCentric___________________*/ + expectedvec.x = -12.0f; expectedvec.y = -21.0f; + D3DXVec2BaryCentric(&gotvec,&u,&v,&w,coeff1,coeff2); + expect_vec2(&expectedvec, &gotvec, 0); + +/*_______________D3DXVec2CatmullRom____________________*/ + expectedvec.x = 5820.25f; expectedvec.y = -3654.5625f; + D3DXVec2CatmullRom(&gotvec,&u,&v,&w,&x,scale); + expect_vec2(&expectedvec, &gotvec, 0); + +/*_______________D3DXVec2CCW__________________________*/ + got = D3DXVec2CCW(&u, &v); + equal = compare_float(got, 55.0f, 0); + ok(equal, "Got unexpected ccw %.8e.\n", got); + /* Tests the case NULL. */ + got = D3DXVec2CCW(NULL, &v); + equal = compare_float(got, 0.0f, 0); + ok(equal, "Got unexpected ccw %.8e.\n", got); + got = D3DXVec2CCW(NULL, NULL); + equal = compare_float(got, 0.0f, 0); + ok(equal, "Got unexpected ccw %.8e.\n", got); + +/*_______________D3DXVec2Dot__________________________*/ + got = D3DXVec2Dot(&u, &v); + equal = compare_float(got, 15.0f, 0); + ok(equal, "Got unexpected dot %.8e.\n", got); + /* Tests the case NULL */ + got = D3DXVec2Dot(NULL, &v); + equal = compare_float(got, 0.0f, 0); + ok(equal, "Got unexpected dot %.8e.\n", got); + got = D3DXVec2Dot(NULL, NULL); + equal = compare_float(got, 0.0f, 0); + ok(equal, "Got unexpected dot %.8e.\n", got); + +/*_______________D3DXVec2Hermite__________________________*/ + expectedvec.x = 2604.625f; expectedvec.y = -4533.0f; + D3DXVec2Hermite(&gotvec,&u,&v,&w,&x,scale); + expect_vec2(&expectedvec, &gotvec, 0); + +/*_______________D3DXVec2Length__________________________*/ + got = D3DXVec2Length(&u); + equal = compare_float(got, 5.0f, 0); + ok(equal, "Got unexpected length %.8e.\n", got); + /* Tests the case NULL. */ + got = D3DXVec2Length(NULL); + equal = compare_float(got, 0.0f, 0); + ok(equal, "Got unexpected length %.8e.\n", got); + +/*_______________D3DXVec2LengthSq________________________*/ + got = D3DXVec2LengthSq(&u); + equal = compare_float(got, 25.0f, 0); + ok(equal, "Got unexpected length %.8e.\n", got); + /* Tests the case NULL. */ + got = D3DXVec2LengthSq(NULL); + equal = compare_float(got, 0.0f, 0); + ok(equal, "Got unexpected length %.8e.\n", got); + +/*_______________D3DXVec2Lerp__________________________*/ + expectedvec.x = 68.0f; expectedvec.y = -28.5f; + D3DXVec2Lerp(&gotvec, &u, &v, scale); + expect_vec2(&expectedvec, &gotvec, 0); + /* Tests the case NULL. */ + funcpointer = D3DXVec2Lerp(&gotvec,NULL,&v,scale); + ok(funcpointer == NULL, "Expected: %p, Got: %p\n", NULL, funcpointer); + funcpointer = D3DXVec2Lerp(NULL,NULL,NULL,scale); + ok(funcpointer == NULL, "Expected: %p, Got: %p\n", NULL, funcpointer); + +/*_______________D3DXVec2Maximize__________________________*/ + expectedvec.x = 3.0f; expectedvec.y = 9.0f; + D3DXVec2Maximize(&gotvec, &u, &v); + expect_vec2(&expectedvec, &gotvec, 0); + /* Tests the case NULL. */ + funcpointer = D3DXVec2Maximize(&gotvec,NULL,&v); + ok(funcpointer == NULL, "Expected: %p, Got: %p\n", NULL, funcpointer); + funcpointer = D3DXVec2Maximize(NULL,NULL,NULL); + ok(funcpointer == NULL, "Expected: %p, Got: %p\n", NULL, funcpointer); + +/*_______________D3DXVec2Minimize__________________________*/ + expectedvec.x = -7.0f; expectedvec.y = 4.0f; + D3DXVec2Minimize(&gotvec,&u,&v); + expect_vec2(&expectedvec, &gotvec, 0); + /* Tests the case NULL */ + funcpointer = D3DXVec2Minimize(&gotvec,NULL,&v); + ok(funcpointer == NULL, "Expected: %p, Got: %p\n", NULL, funcpointer); + funcpointer = D3DXVec2Minimize(NULL,NULL,NULL); + ok(funcpointer == NULL, "Expected: %p, Got: %p\n", NULL, funcpointer); + +/*_______________D3DXVec2Normalize_________________________*/ + expectedvec.x = 0.6f; expectedvec.y = 0.8f; + D3DXVec2Normalize(&gotvec,&u); + expect_vec2(&expectedvec, &gotvec, 0); + /* Test the nul vector */ + expectedvec.x = 0.0f; expectedvec.y = 0.0f; + D3DXVec2Normalize(&gotvec,&nul); + expect_vec2(&expectedvec, &gotvec, 0); + +/*_______________D3DXVec2Scale____________________________*/ + expectedvec.x = -19.5f; expectedvec.y = -26.0f; + D3DXVec2Scale(&gotvec,&u,scale); + expect_vec2(&expectedvec, &gotvec, 0); + /* Tests the case NULL */ + funcpointer = D3DXVec2Scale(&gotvec,NULL,scale); + ok(funcpointer == NULL, "Expected: %p, Got: %p\n", NULL, funcpointer); + funcpointer = D3DXVec2Scale(NULL,NULL,scale); + ok(funcpointer == NULL, "Expected: %p, Got: %p\n", NULL, funcpointer); + +/*_______________D3DXVec2Subtract__________________________*/ + expectedvec.x = 10.0f; expectedvec.y = -5.0f; + D3DXVec2Subtract(&gotvec, &u, &v); + expect_vec2(&expectedvec, &gotvec, 0); + /* Tests the case NULL. */ + funcpointer = D3DXVec2Subtract(&gotvec,NULL,&v); + ok(funcpointer == NULL, "Expected: %p, Got: %p\n", NULL, funcpointer); + funcpointer = D3DXVec2Subtract(NULL,NULL,NULL); + ok(funcpointer == NULL, "Expected: %p, Got: %p\n", NULL, funcpointer); + +/*_______________D3DXVec2Transform_______________________*/ + expectedtrans.x = 36.0f; expectedtrans.y = 44.0f; expectedtrans.z = 52.0f; expectedtrans.w = 60.0f; + D3DXVec2Transform(&gottrans, &u, &mat); + expect_vec4(&expectedtrans, &gottrans, 0); + gottrans.x = u.x; gottrans.y = u.y; + D3DXVec2Transform(&gottrans, (D3DXVECTOR2 *)&gottrans, &mat); + expect_vec4(&expectedtrans, &gottrans, 0); + +/*_______________D3DXVec2TransformCoord_______________________*/ + expectedvec.x = 0.6f; expectedvec.y = 11.0f/15.0f; + D3DXVec2TransformCoord(&gotvec, &u, &mat); + expect_vec2(&expectedvec, &gotvec, 1); + gotvec.x = u.x; gotvec.y = u.y; + D3DXVec2TransformCoord(&gotvec, (D3DXVECTOR2 *)&gotvec, &mat); + expect_vec2(&expectedvec, &gotvec, 1); + + /*_______________D3DXVec2TransformNormal______________________*/ + expectedvec.x = 23.0f; expectedvec.y = 30.0f; + D3DXVec2TransformNormal(&gotvec,&u,&mat); + expect_vec2(&expectedvec, &gotvec, 0); +} + +static void D3DXVector3Test(void) +{ + D3DVIEWPORT9 viewport; + D3DXVECTOR3 expectedvec, gotvec, nul, u, v, w, x; + LPD3DXVECTOR3 funcpointer; + D3DXVECTOR4 expectedtrans, gottrans; + D3DXMATRIX mat, projection, view, world; + float coeff1, coeff2, got, scale; + BOOL equal; + + nul.x = 0.0f; nul.y = 0.0f; nul.z = 0.0f; + u.x = 9.0f; u.y = 6.0f; u.z = 2.0f; + v.x = 2.0f; v.y = -3.0f; v.z = -4.0; + w.x = 3.0f; w.y = -5.0f; w.z = 7.0f; + x.x = 4.0f; x.y = 1.0f; x.z = 11.0f; + + viewport.Width = 800; viewport.MinZ = 0.2f; viewport.X = 10; + viewport.Height = 680; viewport.MaxZ = 0.9f; viewport.Y = 5; + + set_matrix(&mat, + 1.0f, 2.0f, 3.0f, 4.0f, + 5.0f, 6.0f, 7.0f, 8.0f, + 9.0f, 10.0f, 11.0f, 12.0f, + 13.0f, 14.0f, 15.0f, 16.0f); + + U(view).m[0][1] = 5.0f; U(view).m[0][2] = 7.0f; U(view).m[0][3] = 8.0f; + U(view).m[1][0] = 11.0f; U(view).m[1][2] = 16.0f; U(view).m[1][3] = 33.0f; + U(view).m[2][0] = 19.0f; U(view).m[2][1] = -21.0f; U(view).m[2][3] = 43.0f; + U(view).m[3][0] = 2.0f; U(view).m[3][1] = 3.0f; U(view).m[3][2] = -4.0f; + U(view).m[0][0] = 10.0f; U(view).m[1][1] = 20.0f; U(view).m[2][2] = 30.0f; + U(view).m[3][3] = -40.0f; + + set_matrix(&world, + 21.0f, 2.0f, 3.0f, 4.0f, + 5.0f, 23.0f, 7.0f, 8.0f, + -8.0f, -7.0f, 25.0f, -5.0f, + -4.0f, -3.0f, -2.0f, 27.0f); + + coeff1 = 2.0f; coeff2 = 5.0f; + scale = -6.5f; + +/*_______________D3DXVec3Add__________________________*/ + expectedvec.x = 11.0f; expectedvec.y = 3.0f; expectedvec.z = -2.0f; + D3DXVec3Add(&gotvec,&u,&v); + expect_vec3(&expectedvec, &gotvec, 0); + /* Tests the case NULL */ + funcpointer = D3DXVec3Add(&gotvec,NULL,&v); + ok(funcpointer == NULL, "Expected: %p, Got: %p\n", NULL, funcpointer); + funcpointer = D3DXVec3Add(NULL,NULL,NULL); + ok(funcpointer == NULL, "Expected: %p, Got: %p\n", NULL, funcpointer); + +/*_______________D3DXVec3BaryCentric___________________*/ + expectedvec.x = -35.0f; expectedvec.y = -67.0; expectedvec.z = 15.0f; + D3DXVec3BaryCentric(&gotvec,&u,&v,&w,coeff1,coeff2); + expect_vec3(&expectedvec, &gotvec, 0); + +/*_______________D3DXVec3CatmullRom____________________*/ + expectedvec.x = 1458.0f; expectedvec.y = 22.1875f; expectedvec.z = 4141.375f; + D3DXVec3CatmullRom(&gotvec,&u,&v,&w,&x,scale); + expect_vec3(&expectedvec, &gotvec, 0); + +/*_______________D3DXVec3Cross________________________*/ + expectedvec.x = -18.0f; expectedvec.y = 40.0f; expectedvec.z = -39.0f; + D3DXVec3Cross(&gotvec,&u,&v); + expect_vec3(&expectedvec, &gotvec, 0); + expectedvec.x = -277.0f; expectedvec.y = -150.0f; expectedvec.z = -26.0f; + D3DXVec3Cross(&gotvec,&gotvec,&v); + expect_vec3(&expectedvec, &gotvec, 0); + /* Tests the case NULL */ + funcpointer = D3DXVec3Cross(&gotvec,NULL,&v); + ok(funcpointer == NULL, "Expected: %p, Got: %p\n", NULL, funcpointer); + funcpointer = D3DXVec3Cross(NULL,NULL,NULL); + ok(funcpointer == NULL, "Expected: %p, Got: %p\n", NULL, funcpointer); + +/*_______________D3DXVec3Dot__________________________*/ + got = D3DXVec3Dot(&u, &v); + equal = compare_float(got, -8.0f, 0); + ok(equal, "Got unexpected dot %.8e.\n", got); + /* Tests the case NULL */ + got = D3DXVec3Dot(NULL, &v); + equal = compare_float(got, 0.0f, 0); + ok(equal, "Got unexpected dot %.8e.\n", got); + got = D3DXVec3Dot(NULL, NULL); + equal = compare_float(got, 0.0f, 0); + ok(equal, "Got unexpected dot %.8e.\n", got); + +/*_______________D3DXVec3Hermite__________________________*/ + expectedvec.x = -6045.75f; expectedvec.y = -6650.0f; expectedvec.z = 1358.875f; + D3DXVec3Hermite(&gotvec,&u,&v,&w,&x,scale); + expect_vec3(&expectedvec, &gotvec, 0); + +/*_______________D3DXVec3Length__________________________*/ + got = D3DXVec3Length(&u); + equal = compare_float(got, 11.0f, 0); + ok(equal, "Got unexpected length %.8e.\n", got); + /* Tests the case NULL. */ + got = D3DXVec3Length(NULL); + equal = compare_float(got, 0.0f, 0); + ok(equal, "Got unexpected length %.8e.\n", got); + +/*_______________D3DXVec3LengthSq________________________*/ + got = D3DXVec3LengthSq(&u); + equal = compare_float(got, 121.0f, 0); + ok(equal, "Got unexpected length %.8e.\n", got); + /* Tests the case NULL. */ + got = D3DXVec3LengthSq(NULL); + equal = compare_float(got, 0.0f, 0); + ok(equal, "Got unexpected length %.8e.\n", got); + +/*_______________D3DXVec3Lerp__________________________*/ + expectedvec.x = 54.5f; expectedvec.y = 64.5f, expectedvec.z = 41.0f ; + D3DXVec3Lerp(&gotvec,&u,&v,scale); + expect_vec3(&expectedvec, &gotvec, 0); + /* Tests the case NULL */ + funcpointer = D3DXVec3Lerp(&gotvec,NULL,&v,scale); + ok(funcpointer == NULL, "Expected: %p, Got: %p\n", NULL, funcpointer); + funcpointer = D3DXVec3Lerp(NULL,NULL,NULL,scale); + ok(funcpointer == NULL, "Expected: %p, Got: %p\n", NULL, funcpointer); + +/*_______________D3DXVec3Maximize__________________________*/ + expectedvec.x = 9.0f; expectedvec.y = 6.0f; expectedvec.z = 2.0f; + D3DXVec3Maximize(&gotvec,&u,&v); + expect_vec3(&expectedvec, &gotvec, 0); + /* Tests the case NULL */ + funcpointer = D3DXVec3Maximize(&gotvec,NULL,&v); + ok(funcpointer == NULL, "Expected: %p, Got: %p\n", NULL, funcpointer); + funcpointer = D3DXVec3Maximize(NULL,NULL,NULL); + ok(funcpointer == NULL, "Expected: %p, Got: %p\n", NULL, funcpointer); + +/*_______________D3DXVec3Minimize__________________________*/ + expectedvec.x = 2.0f; expectedvec.y = -3.0f; expectedvec.z = -4.0f; + D3DXVec3Minimize(&gotvec,&u,&v); + expect_vec3(&expectedvec, &gotvec, 0); + /* Tests the case NULL */ + funcpointer = D3DXVec3Minimize(&gotvec,NULL,&v); + ok(funcpointer == NULL, "Expected: %p, Got: %p\n", NULL, funcpointer); + funcpointer = D3DXVec3Minimize(NULL,NULL,NULL); + ok(funcpointer == NULL, "Expected: %p, Got: %p\n", NULL, funcpointer); + +/*_______________D3DXVec3Normalize_________________________*/ + expectedvec.x = 9.0f/11.0f; expectedvec.y = 6.0f/11.0f; expectedvec.z = 2.0f/11.0f; + D3DXVec3Normalize(&gotvec,&u); + expect_vec3(&expectedvec, &gotvec, 1); + /* Test the nul vector */ + expectedvec.x = 0.0f; expectedvec.y = 0.0f; expectedvec.z = 0.0f; + D3DXVec3Normalize(&gotvec,&nul); + expect_vec3(&expectedvec, &gotvec, 0); + +/*_______________D3DXVec3Scale____________________________*/ + expectedvec.x = -58.5f; expectedvec.y = -39.0f; expectedvec.z = -13.0f; + D3DXVec3Scale(&gotvec,&u,scale); + expect_vec3(&expectedvec, &gotvec, 0); + /* Tests the case NULL */ + funcpointer = D3DXVec3Scale(&gotvec,NULL,scale); + ok(funcpointer == NULL, "Expected: %p, Got: %p\n", NULL, funcpointer); + funcpointer = D3DXVec3Scale(NULL,NULL,scale); + ok(funcpointer == NULL, "Expected: %p, Got: %p\n", NULL, funcpointer); + +/*_______________D3DXVec3Subtract_______________________*/ + expectedvec.x = 7.0f; expectedvec.y = 9.0f; expectedvec.z = 6.0f; + D3DXVec3Subtract(&gotvec,&u,&v); + expect_vec3(&expectedvec, &gotvec, 0); + /* Tests the case NULL */ + funcpointer = D3DXVec3Subtract(&gotvec,NULL,&v); + ok(funcpointer == NULL, "Expected: %p, Got: %p\n", NULL, funcpointer); + funcpointer = D3DXVec3Subtract(NULL,NULL,NULL); + ok(funcpointer == NULL, "Expected: %p, Got: %p\n", NULL, funcpointer); + +/*_______________D3DXVec3Transform_______________________*/ + expectedtrans.x = 70.0f; expectedtrans.y = 88.0f; expectedtrans.z = 106.0f; expectedtrans.w = 124.0f; + D3DXVec3Transform(&gottrans, &u, &mat); + expect_vec4(&expectedtrans, &gottrans, 0); + + gottrans.x = u.x; gottrans.y = u.y; gottrans.z = u.z; + D3DXVec3Transform(&gottrans, (D3DXVECTOR3 *)&gottrans, &mat); + expect_vec4(&expectedtrans, &gottrans, 0); + +/*_______________D3DXVec3TransformCoord_______________________*/ + expectedvec.x = 70.0f/124.0f; expectedvec.y = 88.0f/124.0f; expectedvec.z = 106.0f/124.0f; + D3DXVec3TransformCoord(&gotvec,&u,&mat); + expect_vec3(&expectedvec, &gotvec, 1); + +/*_______________D3DXVec3TransformNormal______________________*/ + expectedvec.x = 57.0f; expectedvec.y = 74.0f; expectedvec.z = 91.0f; + D3DXVec3TransformNormal(&gotvec,&u,&mat); + expect_vec3(&expectedvec, &gotvec, 0); + +/*_______________D3DXVec3Project_________________________*/ + expectedvec.x = 1135.721924f; expectedvec.y = 147.086914f; expectedvec.z = 0.153412f; + D3DXMatrixPerspectiveFovLH(&projection,D3DX_PI/4.0f,20.0f/17.0f,1.0f,1000.0f); + D3DXVec3Project(&gotvec,&u,&viewport,&projection,&view,&world); + expect_vec3(&expectedvec, &gotvec, 32); + /* World matrix can be omitted */ + D3DXMatrixMultiply(&mat,&world,&view); + D3DXVec3Project(&gotvec,&u,&viewport,&projection,&mat,NULL); + expect_vec3(&expectedvec, &gotvec, 32); + /* Projection matrix can be omitted */ + D3DXMatrixMultiply(&mat,&view,&projection); + D3DXVec3Project(&gotvec,&u,&viewport,NULL,&mat,&world); + expect_vec3(&expectedvec, &gotvec, 32); + /* View matrix can be omitted */ + D3DXMatrixMultiply(&mat,&world,&view); + D3DXVec3Project(&gotvec,&u,&viewport,&projection,NULL,&mat); + expect_vec3(&expectedvec, &gotvec, 32); + /* All matrices can be omitted */ + expectedvec.x = 4010.000000f; expectedvec.y = -1695.000000f; expectedvec.z = 1.600000f; + D3DXVec3Project(&gotvec,&u,&viewport,NULL,NULL,NULL); + expect_vec3(&expectedvec, &gotvec, 2); + /* Viewport can be omitted */ + expectedvec.x = 1.814305f; expectedvec.y = 0.582097f; expectedvec.z = -0.066555f; + D3DXVec3Project(&gotvec,&u,NULL,&projection,&view,&world); + expect_vec3(&expectedvec, &gotvec, 64); + +/*_______________D3DXVec3Unproject_________________________*/ + expectedvec.x = -2.913411f; expectedvec.y = 1.593215f; expectedvec.z = 0.380724f; + D3DXMatrixPerspectiveFovLH(&projection,D3DX_PI/4.0f,20.0f/17.0f,1.0f,1000.0f); + D3DXVec3Unproject(&gotvec,&u,&viewport,&projection,&view,&world); + expect_vec3(&expectedvec, &gotvec, 16); + /* World matrix can be omitted */ + D3DXMatrixMultiply(&mat,&world,&view); + D3DXVec3Unproject(&gotvec,&u,&viewport,&projection,&mat,NULL); + expect_vec3(&expectedvec, &gotvec, 16); + /* Projection matrix can be omitted */ + D3DXMatrixMultiply(&mat,&view,&projection); + D3DXVec3Unproject(&gotvec,&u,&viewport,NULL,&mat,&world); + expect_vec3(&expectedvec, &gotvec, 32); + /* View matrix can be omitted */ + D3DXMatrixMultiply(&mat,&world,&view); + D3DXVec3Unproject(&gotvec,&u,&viewport,&projection,NULL,&mat); + expect_vec3(&expectedvec, &gotvec, 16); + /* All matrices can be omitted */ + expectedvec.x = -1.002500f; expectedvec.y = 0.997059f; expectedvec.z = 2.571429f; + D3DXVec3Unproject(&gotvec,&u,&viewport,NULL,NULL,NULL); + expect_vec3(&expectedvec, &gotvec, 4); + /* Viewport can be omitted */ + expectedvec.x = -11.018396f; expectedvec.y = 3.218991f; expectedvec.z = 1.380329f; + D3DXVec3Unproject(&gotvec,&u,NULL,&projection,&view,&world); + expect_vec3(&expectedvec, &gotvec, 8); +} + +static void D3DXVector4Test(void) +{ + D3DXVECTOR4 expectedvec, gotvec, u, v, w, x; + LPD3DXVECTOR4 funcpointer; + D3DXVECTOR4 expectedtrans, gottrans; + float coeff1, coeff2, got, scale; + D3DXMATRIX mat; + BOOL equal; + + u.x = 1.0f; u.y = 2.0f; u.z = 4.0f; u.w = 10.0; + v.x = -3.0f; v.y = 4.0f; v.z = -5.0f; v.w = 7.0; + w.x = 4.0f; w.y =6.0f; w.z = -2.0f; w.w = 1.0f; + x.x = 6.0f; x.y = -7.0f; x.z =8.0f; x.w = -9.0f; + + set_matrix(&mat, + 1.0f, 2.0f, 3.0f, 4.0f, + 5.0f, 6.0f, 7.0f, 8.0f, + 9.0f, 10.0f, 11.0f, 12.0f, + 13.0f, 14.0f, 15.0f, 16.0f); + + coeff1 = 2.0f; coeff2 = 5.0; + scale = -6.5f; + +/*_______________D3DXVec4Add__________________________*/ + expectedvec.x = -2.0f; expectedvec.y = 6.0f; expectedvec.z = -1.0f; expectedvec.w = 17.0f; + D3DXVec4Add(&gotvec,&u,&v); + expect_vec4(&expectedvec, &gotvec, 0); + /* Tests the case NULL */ + funcpointer = D3DXVec4Add(&gotvec,NULL,&v); + ok(funcpointer == NULL, "Expected: %p, Got: %p\n", NULL, funcpointer); + funcpointer = D3DXVec4Add(NULL,NULL,NULL); + ok(funcpointer == NULL, "Expected: %p, Got: %p\n", NULL, funcpointer); + +/*_______________D3DXVec4BaryCentric____________________*/ + expectedvec.x = 8.0f; expectedvec.y = 26.0; expectedvec.z = -44.0f; expectedvec.w = -41.0f; + D3DXVec4BaryCentric(&gotvec,&u,&v,&w,coeff1,coeff2); + expect_vec4(&expectedvec, &gotvec, 0); + +/*_______________D3DXVec4CatmullRom____________________*/ + expectedvec.x = 2754.625f; expectedvec.y = 2367.5625f; expectedvec.z = 1060.1875f; expectedvec.w = 131.3125f; + D3DXVec4CatmullRom(&gotvec,&u,&v,&w,&x,scale); + expect_vec4(&expectedvec, &gotvec, 0); + +/*_______________D3DXVec4Cross_________________________*/ + expectedvec.x = 390.0f; expectedvec.y = -393.0f; expectedvec.z = -316.0f; expectedvec.w = 166.0f; + D3DXVec4Cross(&gotvec,&u,&v,&w); + expect_vec4(&expectedvec, &gotvec, 0); + +/*_______________D3DXVec4Dot__________________________*/ + got = D3DXVec4Dot(&u, &v); + equal = compare_float(got, 55.0f, 0); + ok(equal, "Got unexpected dot %.8e.\n", got); + /* Tests the case NULL. */ + got = D3DXVec4Dot(NULL, &v); + equal = compare_float(got, 0.0f, 0); + ok(equal, "Got unexpected dot %.8e.\n", got); + got = D3DXVec4Dot(NULL, NULL); + equal = compare_float(got, 0.0f, 0); + ok(equal, "Got unexpected dot %.8e.\n", got); + +/*_______________D3DXVec4Hermite_________________________*/ + expectedvec.x = 1224.625f; expectedvec.y = 3461.625f; expectedvec.z = -4758.875f; expectedvec.w = -5781.5f; + D3DXVec4Hermite(&gotvec,&u,&v,&w,&x,scale); + expect_vec4(&expectedvec, &gotvec, 0); + +/*_______________D3DXVec4Length__________________________*/ + got = D3DXVec4Length(&u); + equal = compare_float(got, 11.0f, 0); + ok(equal, "Got unexpected length %.8e.\n", got); + /* Tests the case NULL. */ + got = D3DXVec4Length(NULL); + equal = compare_float(got, 0.0f, 0); + ok(equal, "Got unexpected length %.8e.\n", got); + +/*_______________D3DXVec4LengthSq________________________*/ + got = D3DXVec4LengthSq(&u); + equal = compare_float(got, 121.0f, 0); + ok(equal, "Got unexpected length %.8e.\n", got); + /* Tests the case NULL. */ + got = D3DXVec4LengthSq(NULL); + equal = compare_float(got, 0.0f, 0); + ok(equal, "Got unexpected length %.8e.\n", got); + +/*_______________D3DXVec4Lerp__________________________*/ + expectedvec.x = 27.0f; expectedvec.y = -11.0f; expectedvec.z = 62.5; expectedvec.w = 29.5; + D3DXVec4Lerp(&gotvec,&u,&v,scale); + expect_vec4(&expectedvec, &gotvec, 0); + /* Tests the case NULL */ + funcpointer = D3DXVec4Lerp(&gotvec,NULL,&v,scale); + ok(funcpointer == NULL, "Expected: %p, Got: %p\n", NULL, funcpointer); + funcpointer = D3DXVec4Lerp(NULL,NULL,NULL,scale); + ok(funcpointer == NULL, "Expected: %p, Got: %p\n", NULL, funcpointer); + +/*_______________D3DXVec4Maximize__________________________*/ + expectedvec.x = 1.0f; expectedvec.y = 4.0f; expectedvec.z = 4.0f; expectedvec.w = 10.0; + D3DXVec4Maximize(&gotvec,&u,&v); + expect_vec4(&expectedvec, &gotvec, 0); + /* Tests the case NULL */ + funcpointer = D3DXVec4Maximize(&gotvec,NULL,&v); + ok(funcpointer == NULL, "Expected: %p, Got: %p\n", NULL, funcpointer); + funcpointer = D3DXVec4Maximize(NULL,NULL,NULL); + ok(funcpointer == NULL, "Expected: %p, Got: %p\n", NULL, funcpointer); + +/*_______________D3DXVec4Minimize__________________________*/ + expectedvec.x = -3.0f; expectedvec.y = 2.0f; expectedvec.z = -5.0f; expectedvec.w = 7.0; + D3DXVec4Minimize(&gotvec,&u,&v); + expect_vec4(&expectedvec, &gotvec, 0); + /* Tests the case NULL */ + funcpointer = D3DXVec4Minimize(&gotvec,NULL,&v); + ok(funcpointer == NULL, "Expected: %p, Got: %p\n", NULL, funcpointer); + funcpointer = D3DXVec4Minimize(NULL,NULL,NULL); + ok(funcpointer == NULL, "Expected: %p, Got: %p\n", NULL, funcpointer); + +/*_______________D3DXVec4Normalize_________________________*/ + expectedvec.x = 1.0f/11.0f; expectedvec.y = 2.0f/11.0f; expectedvec.z = 4.0f/11.0f; expectedvec.w = 10.0f/11.0f; + D3DXVec4Normalize(&gotvec,&u); + expect_vec4(&expectedvec, &gotvec, 1); + +/*_______________D3DXVec4Scale____________________________*/ + expectedvec.x = -6.5f; expectedvec.y = -13.0f; expectedvec.z = -26.0f; expectedvec.w = -65.0f; + D3DXVec4Scale(&gotvec,&u,scale); + expect_vec4(&expectedvec, &gotvec, 0); + /* Tests the case NULL */ + funcpointer = D3DXVec4Scale(&gotvec,NULL,scale); + ok(funcpointer == NULL, "Expected: %p, Got: %p\n", NULL, funcpointer); + funcpointer = D3DXVec4Scale(NULL,NULL,scale); + ok(funcpointer == NULL, "Expected: %p, Got: %p\n", NULL, funcpointer); + +/*_______________D3DXVec4Subtract__________________________*/ + expectedvec.x = 4.0f; expectedvec.y = -2.0f; expectedvec.z = 9.0f; expectedvec.w = 3.0f; + D3DXVec4Subtract(&gotvec,&u,&v); + expect_vec4(&expectedvec, &gotvec, 0); + /* Tests the case NULL */ + funcpointer = D3DXVec4Subtract(&gotvec,NULL,&v); + ok(funcpointer == NULL, "Expected: %p, Got: %p\n", NULL, funcpointer); + funcpointer = D3DXVec4Subtract(NULL,NULL,NULL); + ok(funcpointer == NULL, "Expected: %p, Got: %p\n", NULL, funcpointer); + +/*_______________D3DXVec4Transform_______________________*/ + expectedtrans.x = 177.0f; expectedtrans.y = 194.0f; expectedtrans.z = 211.0f; expectedtrans.w = 228.0f; + D3DXVec4Transform(&gottrans,&u,&mat); + expect_vec4(&expectedtrans, &gottrans, 0); +} + +static void test_matrix_stack(void) +{ + ID3DXMatrixStack *stack; + ULONG refcount; + HRESULT hr; + + const D3DXMATRIX mat1 = {{{ + 1.0f, 2.0f, 3.0f, 4.0f, + 5.0f, 6.0f, 7.0f, 8.0f, + 9.0f, 10.0f, 11.0f, 12.0f, + 13.0f, 14.0f, 15.0f, 16.0f + }}}; + + const D3DXMATRIX mat2 = {{{ + 17.0f, 18.0f, 19.0f, 20.0f, + 21.0f, 22.0f, 23.0f, 24.0f, + 25.0f, 26.0f, 27.0f, 28.0f, + 29.0f, 30.0f, 31.0f, 32.0f + }}}; + + hr = D3DXCreateMatrixStack(0, &stack); + ok(SUCCEEDED(hr), "Failed to create a matrix stack, hr %#x\n", hr); + if (FAILED(hr)) return; + + ok(D3DXMatrixIsIdentity(ID3DXMatrixStack_GetTop(stack)), + "The top of an empty matrix stack should be an identity matrix\n"); + + hr = ID3DXMatrixStack_Pop(stack); + ok(SUCCEEDED(hr), "Pop failed, hr %#x\n", hr); + + hr = ID3DXMatrixStack_Push(stack); + ok(SUCCEEDED(hr), "Push failed, hr %#x\n", hr); + ok(D3DXMatrixIsIdentity(ID3DXMatrixStack_GetTop(stack)), "The top should be an identity matrix\n"); + + hr = ID3DXMatrixStack_Push(stack); + ok(SUCCEEDED(hr), "Push failed, hr %#x\n", hr); + + hr = ID3DXMatrixStack_LoadMatrix(stack, &mat1); + ok(SUCCEEDED(hr), "LoadMatrix failed, hr %#x\n", hr); + expect_matrix(&mat1, ID3DXMatrixStack_GetTop(stack), 0); + + hr = ID3DXMatrixStack_Push(stack); + ok(SUCCEEDED(hr), "Push failed, hr %#x\n", hr); + expect_matrix(&mat1, ID3DXMatrixStack_GetTop(stack), 0); + + hr = ID3DXMatrixStack_LoadMatrix(stack, &mat2); + ok(SUCCEEDED(hr), "LoadMatrix failed, hr %#x\n", hr); + expect_matrix(&mat2, ID3DXMatrixStack_GetTop(stack), 0); + + hr = ID3DXMatrixStack_Push(stack); + ok(SUCCEEDED(hr), "Push failed, hr %#x\n", hr); + expect_matrix(&mat2, ID3DXMatrixStack_GetTop(stack), 0); + + hr = ID3DXMatrixStack_LoadIdentity(stack); + ok(SUCCEEDED(hr), "LoadIdentity failed, hr %#x\n", hr); + ok(D3DXMatrixIsIdentity(ID3DXMatrixStack_GetTop(stack)), "The top should be an identity matrix\n"); + + hr = ID3DXMatrixStack_Pop(stack); + ok(SUCCEEDED(hr), "Pop failed, hr %#x\n", hr); + expect_matrix(&mat2, ID3DXMatrixStack_GetTop(stack), 0); + + hr = ID3DXMatrixStack_Pop(stack); + ok(SUCCEEDED(hr), "Pop failed, hr %#x\n", hr); + expect_matrix(&mat1, ID3DXMatrixStack_GetTop(stack), 0); + + hr = ID3DXMatrixStack_Pop(stack); + ok(SUCCEEDED(hr), "Pop failed, hr %#x\n", hr); + ok(D3DXMatrixIsIdentity(ID3DXMatrixStack_GetTop(stack)), "The top should be an identity matrix\n"); + + hr = ID3DXMatrixStack_Pop(stack); + ok(SUCCEEDED(hr), "Pop failed, hr %#x\n", hr); + ok(D3DXMatrixIsIdentity(ID3DXMatrixStack_GetTop(stack)), "The top should be an identity matrix\n"); + + refcount = ID3DXMatrixStack_Release(stack); + ok(!refcount, "Matrix stack has %u references left.\n", refcount); +} + +static void test_Matrix_AffineTransformation2D(void) +{ + D3DXMATRIX exp_mat, got_mat; + D3DXVECTOR2 center, position; + FLOAT angle, scale; + + center.x = 3.0f; + center.y = 4.0f; + + position.x = -6.0f; + position.y = 7.0f; + + angle = D3DX_PI/3.0f; + + scale = 20.0f; + + U(exp_mat).m[0][0] = 10.0f; + U(exp_mat).m[1][0] = -17.320507f; + U(exp_mat).m[2][0] = 0.0f; + U(exp_mat).m[3][0] = -1.035898f; + U(exp_mat).m[0][1] = 17.320507f; + U(exp_mat).m[1][1] = 10.0f; + U(exp_mat).m[2][1] = 0.0f; + U(exp_mat).m[3][1] = 6.401924f; + U(exp_mat).m[0][2] = 0.0f; + U(exp_mat).m[1][2] = 0.0f; + U(exp_mat).m[2][2] = 1.0f; + U(exp_mat).m[3][2] = 0.0f; + U(exp_mat).m[0][3] = 0.0f; + U(exp_mat).m[1][3] = 0.0f; + U(exp_mat).m[2][3] = 0.0f; + U(exp_mat).m[3][3] = 1.0f; + + D3DXMatrixAffineTransformation2D(&got_mat, scale, ¢er, angle, &position); + expect_matrix(&exp_mat, &got_mat, 2); + +/*______________*/ + + center.x = 3.0f; + center.y = 4.0f; + + angle = D3DX_PI/3.0f; + + scale = 20.0f; + + U(exp_mat).m[0][0] = 10.0f; + U(exp_mat).m[1][0] = -17.320507f; + U(exp_mat).m[2][0] = 0.0f; + U(exp_mat).m[3][0] = 4.964102f; + U(exp_mat).m[0][1] = 17.320507f; + U(exp_mat).m[1][1] = 10.0f; + U(exp_mat).m[2][1] = 0.0f; + U(exp_mat).m[3][1] = -0.598076f; + U(exp_mat).m[0][2] = 0.0f; + U(exp_mat).m[1][2] = 0.0f; + U(exp_mat).m[2][2] = 1.0f; + U(exp_mat).m[3][2] = 0.0f; + U(exp_mat).m[0][3] = 0.0f; + U(exp_mat).m[1][3] = 0.0f; + U(exp_mat).m[2][3] = 0.0f; + U(exp_mat).m[3][3] = 1.0f; + + D3DXMatrixAffineTransformation2D(&got_mat, scale, ¢er, angle, NULL); + expect_matrix(&exp_mat, &got_mat, 8); + +/*______________*/ + + position.x = -6.0f; + position.y = 7.0f; + + angle = D3DX_PI/3.0f; + + scale = 20.0f; + + U(exp_mat).m[0][0] = 10.0f; + U(exp_mat).m[1][0] = -17.320507f; + U(exp_mat).m[2][0] = 0.0f; + U(exp_mat).m[3][0] = -6.0f; + U(exp_mat).m[0][1] = 17.320507f; + U(exp_mat).m[1][1] = 10.0f; + U(exp_mat).m[2][1] = 0.0f; + U(exp_mat).m[3][1] = 7.0f; + U(exp_mat).m[0][2] = 0.0f; + U(exp_mat).m[1][2] = 0.0f; + U(exp_mat).m[2][2] = 1.0f; + U(exp_mat).m[3][2] = 0.0f; + U(exp_mat).m[0][3] = 0.0f; + U(exp_mat).m[1][3] = 0.0f; + U(exp_mat).m[2][3] = 0.0f; + U(exp_mat).m[3][3] = 1.0f; + + D3DXMatrixAffineTransformation2D(&got_mat, scale, NULL, angle, &position); + expect_matrix(&exp_mat, &got_mat, 1); + +/*______________*/ + + angle = 5.0f * D3DX_PI/4.0f; + + scale = -20.0f; + + U(exp_mat).m[0][0] = 14.142133f; + U(exp_mat).m[1][0] = -14.142133f; + U(exp_mat).m[2][0] = 0.0f; + U(exp_mat).m[3][0] = 0.0f; + U(exp_mat).m[0][1] = 14.142133; + U(exp_mat).m[1][1] = 14.142133f; + U(exp_mat).m[2][1] = 0.0f; + U(exp_mat).m[3][1] = 0.0f; + U(exp_mat).m[0][2] = 0.0f; + U(exp_mat).m[1][2] = 0.0f; + U(exp_mat).m[2][2] = 1.0f; + U(exp_mat).m[3][2] = 0.0f; + U(exp_mat).m[0][3] = 0.0f; + U(exp_mat).m[1][3] = 0.0f; + U(exp_mat).m[2][3] = 0.0f; + U(exp_mat).m[3][3] = 1.0f; + + D3DXMatrixAffineTransformation2D(&got_mat, scale, NULL, angle, NULL); + expect_matrix(&exp_mat, &got_mat, 8); +} + +static void test_Matrix_Decompose(void) +{ + D3DXMATRIX pm; + D3DXQUATERNION exp_rotation, got_rotation; + D3DXVECTOR3 exp_scale, got_scale, exp_translation, got_translation; + HRESULT hr; + BOOL equal; + +/*___________*/ + + U(pm).m[0][0] = -9.23879206e-01f; + U(pm).m[1][0] = -2.70598412e-01f; + U(pm).m[2][0] = 2.70598441e-01f; + U(pm).m[3][0] = -5.00000000e+00f; + U(pm).m[0][1] = 2.70598471e-01f; + U(pm).m[1][1] = 3.80604863e-02f; + U(pm).m[2][1] = 9.61939573e-01f; + U(pm).m[3][1] = 0.00000000e+00f; + U(pm).m[0][2] = -2.70598441e-01f; + U(pm).m[1][2] = 9.61939573e-01f; + U(pm).m[2][2] = 3.80603075e-02f; + U(pm).m[3][2] = 1.00000000e+01f; + U(pm).m[0][3] = 0.00000000e+00f; + U(pm).m[1][3] = 0.00000000e+00f; + U(pm).m[2][3] = 0.00000000e+00f; + U(pm).m[3][3] = 1.00000000e+00f; + + exp_scale.x = 9.99999881e-01f; + exp_scale.y = 9.99999881e-01f; + exp_scale.z = 9.99999881e-01f; + + exp_rotation.x = 2.14862776e-08f; + exp_rotation.y = 6.93519890e-01f; + exp_rotation.z = 6.93519890e-01f; + exp_rotation.w = 1.95090637e-01f; + + exp_translation.x = -5.0f; + exp_translation.y = 0.0f; + exp_translation.z = 10.0f; + + D3DXMatrixDecompose(&got_scale, &got_rotation, &got_translation, &pm); + expect_vec3(&exp_scale, &got_scale, 1); + expect_quaternion(&exp_rotation, &got_rotation, 1); + expect_vec3(&exp_translation, &got_translation, 0); + +/*_________*/ + + U(pm).m[0][0] = -2.255813f; + U(pm).m[1][0] = 1.302324f; + U(pm).m[2][0] = 1.488373f; + U(pm).m[3][0] = 1.0f; + U(pm).m[0][1] = 1.302327f; + U(pm).m[1][1] = -0.7209296f; + U(pm).m[2][1] = 2.60465f; + U(pm).m[3][1] = 2.0f; + U(pm).m[0][2] = 1.488371f; + U(pm).m[1][2] = 2.604651f; + U(pm).m[2][2] = -0.02325551f; + U(pm).m[3][2] = 3.0f; + U(pm).m[0][3] = 0.0f; + U(pm).m[1][3] = 0.0f; + U(pm).m[2][3] = 0.0f; + U(pm).m[3][3] = 1.0f; + + exp_scale.x = 2.99999928e+00f; + exp_scale.y = 2.99999905e+00f; + exp_scale.z = 2.99999952e+00f; + + exp_rotation.x = 3.52180451e-01f; + exp_rotation.y = 6.16315663e-01f; + exp_rotation.z = 7.04360664e-01f; + exp_rotation.w = 3.38489343e-07f; + + exp_translation.x = 1.0f; + exp_translation.y = 2.0f; + exp_translation.z = 3.0f; + + D3DXMatrixDecompose(&got_scale, &got_rotation, &got_translation, &pm); + expect_vec3(&exp_scale, &got_scale, 0); + expect_quaternion(&exp_rotation, &got_rotation, 2); + expect_vec3(&exp_translation, &got_translation, 0); + +/*_____________*/ + + U(pm).m[0][0] = 2.427051f; + U(pm).m[1][0] = 0.0f; + U(pm).m[2][0] = 1.763355f; + U(pm).m[3][0] = 5.0f; + U(pm).m[0][1] = 0.0f; + U(pm).m[1][1] = 3.0f; + U(pm).m[2][1] = 0.0f; + U(pm).m[3][1] = 5.0f; + U(pm).m[0][2] = -1.763355f; + U(pm).m[1][2] = 0.0f; + U(pm).m[2][2] = 2.427051f; + U(pm).m[3][2] = 5.0f; + U(pm).m[0][3] = 0.0f; + U(pm).m[1][3] = 0.0f; + U(pm).m[2][3] = 0.0f; + U(pm).m[3][3] = 1.0f; + + exp_scale.x = 2.99999976e+00f; + exp_scale.y = 3.00000000e+00f; + exp_scale.z = 2.99999976e+00f; + + exp_rotation.x = 0.00000000e+00f; + exp_rotation.y = 3.09016883e-01f; + exp_rotation.z = 0.00000000e+00f; + exp_rotation.w = 9.51056540e-01f; + + exp_translation.x = 5.0f; + exp_translation.y = 5.0f; + exp_translation.z = 5.0f; + + D3DXMatrixDecompose(&got_scale, &got_rotation, &got_translation, &pm); + expect_vec3(&exp_scale, &got_scale, 1); + expect_quaternion(&exp_rotation, &got_rotation, 1); + expect_vec3(&exp_translation, &got_translation, 0); + +/*_____________*/ + + U(pm).m[0][0] = -9.23879206e-01f; + U(pm).m[1][0] = -2.70598412e-01f; + U(pm).m[2][0] = 2.70598441e-01f; + U(pm).m[3][0] = -5.00000000e+00f; + U(pm).m[0][1] = 2.70598471e-01f; + U(pm).m[1][1] = 3.80604863e-02f; + U(pm).m[2][1] = 9.61939573e-01f; + U(pm).m[3][1] = 0.00000000e+00f; + U(pm).m[0][2] = -2.70598441e-01f; + U(pm).m[1][2] = 9.61939573e-01f; + U(pm).m[2][2] = 3.80603075e-02f; + U(pm).m[3][2] = 1.00000000e+01f; + U(pm).m[0][3] = 0.00000000e+00f; + U(pm).m[1][3] = 0.00000000e+00f; + U(pm).m[2][3] = 0.00000000e+00f; + U(pm).m[3][3] = 1.00000000e+00f; + + exp_scale.x = 9.99999881e-01f; + exp_scale.y = 9.99999881e-01f; + exp_scale.z = 9.99999881e-01f; + + exp_rotation.x = 2.14862776e-08f; + exp_rotation.y = 6.93519890e-01f; + exp_rotation.z = 6.93519890e-01f; + exp_rotation.w = 1.95090637e-01f; + + exp_translation.x = -5.0f; + exp_translation.y = 0.0f; + exp_translation.z = 10.0f; + + D3DXMatrixDecompose(&got_scale, &got_rotation, &got_translation, &pm); + expect_vec3(&exp_scale, &got_scale, 1); + expect_quaternion(&exp_rotation, &got_rotation, 1); + expect_vec3(&exp_translation, &got_translation, 0); + +/*__________*/ + + U(pm).m[0][0] = -9.23878908e-01f; + U(pm).m[1][0] = -5.41196704e-01f; + U(pm).m[2][0] = 8.11795175e-01f; + U(pm).m[3][0] = -5.00000000e+00f; + U(pm).m[0][1] = 2.70598322e-01f; + U(pm).m[1][1] = 7.61209577e-02f; + U(pm).m[2][1] = 2.88581824e+00f; + U(pm).m[3][1] = 0.00000000e+00f; + U(pm).m[0][2] = -2.70598352e-01f; + U(pm).m[1][2] = 1.92387879e+00f; + U(pm).m[2][2] = 1.14180908e-01f; + U(pm).m[3][2] = 1.00000000e+01f; + U(pm).m[0][3] = 0.00000000e+00f; + U(pm).m[1][3] = 0.00000000e+00f; + U(pm).m[2][3] = 0.00000000e+00f; + U(pm).m[3][3] = 1.00000000e+00f; + + exp_scale.x = 9.99999583e-01f; + exp_scale.y = 1.99999940e+00f; + exp_scale.z = 2.99999928e+00f; + + exp_rotation.x = 1.07431388e-08f; + exp_rotation.y = 6.93519890e-01f; + exp_rotation.z = 6.93519831e-01f; + exp_rotation.w = 1.95090622e-01f; + + exp_translation.x = -5.0f; + exp_translation.y = 0.0f; + exp_translation.z = 10.0f; + + D3DXMatrixDecompose(&got_scale, &got_rotation, &got_translation, &pm); + expect_vec3(&exp_scale, &got_scale, 1); + equal = compare_quaternion(&exp_rotation, &got_rotation, 1); + exp_rotation.x = 0.0f; + equal |= compare_quaternion(&exp_rotation, &got_rotation, 2); + ok(equal, "Got unexpected quaternion {%.8e, %.8e, %.8e, %.8e}.\n", + got_rotation.x, got_rotation.y, got_rotation.z, got_rotation.w); + expect_vec3(&exp_translation, &got_translation, 0); + +/*__________*/ + + U(pm).m[0][0] = 0.7156004f; + U(pm).m[1][0] = -0.5098283f; + U(pm).m[2][0] = -0.4774843f; + U(pm).m[3][0] = -5.0f; + U(pm).m[0][1] = -0.6612288f; + U(pm).m[1][1] = -0.7147621f; + U(pm).m[2][1] = -0.2277977f; + U(pm).m[3][1] = 0.0f; + U(pm).m[0][2] = -0.2251499f; + U(pm).m[1][2] = 0.4787385f; + U(pm).m[2][2] = -0.8485972f; + U(pm).m[3][2] = 10.0f; + U(pm).m[0][3] = 0.0f; + U(pm).m[1][3] = 0.0f; + U(pm).m[2][3] = 0.0f; + U(pm).m[3][3] = 1.0f; + + exp_scale.x = 9.99999940e-01f; + exp_scale.y = 1.00000012e+00f; + exp_scale.z = 1.00000012e+00f; + + exp_rotation.x = 9.05394852e-01f; + exp_rotation.y = -3.23355347e-01f; + exp_rotation.z = -1.94013178e-01f; + exp_rotation.w = 1.95090592e-01f; + + exp_translation.x = -5.0f; + exp_translation.y = 0.0f; + exp_translation.z = 10.0f; + + D3DXMatrixDecompose(&got_scale, &got_rotation, &got_translation, &pm); + expect_vec3(&exp_scale, &got_scale, 0); + expect_quaternion(&exp_rotation, &got_rotation, 1); + expect_vec3(&exp_translation, &got_translation, 0); + +/*_____________*/ + + U(pm).m[0][0] = 0.06554436f; + U(pm).m[1][0] = -0.6873012f; + U(pm).m[2][0] = 0.7234092f; + U(pm).m[3][0] = -5.0f; + U(pm).m[0][1] = -0.9617381f; + U(pm).m[1][1] = -0.2367795f; + U(pm).m[2][1] = -0.1378230f; + U(pm).m[3][1] = 0.0f; + U(pm).m[0][2] = 0.2660144f; + U(pm).m[1][2] = -0.6866967f; + U(pm).m[2][2] = -0.6765233f; + U(pm).m[3][2] = 10.0f; + U(pm).m[0][3] = 0.0f; + U(pm).m[1][3] = 0.0f; + U(pm).m[2][3] = 0.0f; + U(pm).m[3][3] = 1.0f; + + exp_scale.x = 9.99999940e-01f; + exp_scale.y = 9.99999940e-01f; + exp_scale.z = 9.99999881e-01f; + + exp_rotation.x = 7.03357518e-01f; + exp_rotation.y = -5.86131275e-01f; + exp_rotation.z = 3.51678789e-01f; + exp_rotation.w = -1.95090577e-01f; + + exp_translation.x = -5.0f; + exp_translation.y = 0.0f; + exp_translation.z = 10.0f; + + D3DXMatrixDecompose(&got_scale, &got_rotation, &got_translation, &pm); + expect_vec3(&exp_scale, &got_scale, 1); + expect_quaternion(&exp_rotation, &got_rotation, 2); + expect_vec3(&exp_translation, &got_translation, 0); + +/*_________*/ + + U(pm).m[0][0] = 7.12104797e+00f; + U(pm).m[1][0] = -5.88348627e+00f; + U(pm).m[2][0] = 1.18184204e+01f; + U(pm).m[3][0] = -5.00000000e+00f; + U(pm).m[0][1] = 5.88348627e+00f; + U(pm).m[1][1] = -1.06065865e+01f; + U(pm).m[2][1] = -8.82523251e+00f; + U(pm).m[3][1] = 0.00000000e+00f; + U(pm).m[0][2] = 1.18184204e+01f; + U(pm).m[1][2] = 8.82523155e+00f; + U(pm).m[2][2] = -2.72764111e+00f; + U(pm).m[3][2] = 2.00000000e+00f; + U(pm).m[0][3] = 0.00000000e+00f; + U(pm).m[1][3] = 0.00000000e+00f; + U(pm).m[2][3] = 0.00000000e+00f; + U(pm).m[3][3] = 1.00000000e+00f; + + exp_scale.x = 1.49999933e+01f; + exp_scale.y = 1.49999933e+01f; + exp_scale.z = 1.49999943e+01f; + + exp_rotation.x = 7.68714130e-01f; + exp_rotation.y = 0.00000000e+00f; + exp_rotation.z = 5.12475967e-01f; + exp_rotation.w = 3.82683903e-01f; + + exp_translation.x = -5.0f; + exp_translation.y = 0.0f; + exp_translation.z = 2.0f; + + D3DXMatrixDecompose(&got_scale, &got_rotation, &got_translation, &pm); + expect_vec3(&exp_scale, &got_scale, 0); + expect_quaternion(&exp_rotation, &got_rotation, 1); + expect_vec3(&exp_translation, &got_translation, 0); + +/*__________*/ + + U(pm).m[0][0] = 0.0f; + U(pm).m[1][0] = 4.0f; + U(pm).m[2][0] = 5.0f; + U(pm).m[3][0] = -5.0f; + U(pm).m[0][1] = 0.0f; + U(pm).m[1][1] = -10.60660f; + U(pm).m[2][1] = -8.825232f; + U(pm).m[3][1] = 6.0f; + U(pm).m[0][2] = 0.0f; + U(pm).m[1][2] = 8.8252320f; + U(pm).m[2][2] = 2.727645; + U(pm).m[3][2] = 3.0f; + U(pm).m[0][3] = 0.0f; + U(pm).m[1][3] = 0.0f; + U(pm).m[2][3] = 0.0f; + U(pm).m[3][3] = 1.0f; + + hr = D3DXMatrixDecompose(&got_scale, &got_rotation, &got_translation, &pm); + ok(hr == D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, got %x\n", hr); +} + +static void test_Matrix_Transformation2D(void) +{ + D3DXMATRIX exp_mat, got_mat; + D3DXVECTOR2 rot_center, sca, sca_center, trans; + FLOAT rot, sca_rot; + + rot_center.x = 3.0f; + rot_center.y = 4.0f; + + sca.x = 12.0f; + sca.y = -3.0f; + + sca_center.x = 9.0f; + sca_center.y = -5.0f; + + trans.x = -6.0f; + trans.y = 7.0f; + + rot = D3DX_PI/3.0f; + + sca_rot = 5.0f*D3DX_PI/4.0f; + + U(exp_mat).m[0][0] = -4.245192f; + U(exp_mat).m[1][0] = -0.147116f; + U(exp_mat).m[2][0] = 0.0f; + U(exp_mat).m[3][0] = 45.265373f; + U(exp_mat).m[0][1] = 7.647113f; + U(exp_mat).m[1][1] = 8.745192f; + U(exp_mat).m[2][1] = 0.0f; + U(exp_mat).m[3][1] = -13.401899f; + U(exp_mat).m[0][2] = 0.0f; + U(exp_mat).m[1][2] = 0.0f; + U(exp_mat).m[2][2] = 1.0f; + U(exp_mat).m[3][2] = 0.0f; + U(exp_mat).m[0][3] = 0.0f; + U(exp_mat).m[1][3] = 0.0f; + U(exp_mat).m[2][3] = 0.0f; + U(exp_mat).m[3][3] = 1.0f; + + D3DXMatrixTransformation2D(&got_mat, &sca_center, sca_rot, &sca, &rot_center, rot, &trans); + expect_matrix(&exp_mat, &got_mat, 64); + +/*_________*/ + + sca_center.x = 9.0f; + sca_center.y = -5.0f; + + trans.x = -6.0f; + trans.y = 7.0f; + + rot = D3DX_PI/3.0f; + + sca_rot = 5.0f*D3DX_PI/4.0f; + + U(exp_mat).m[0][0] = 0.50f; + U(exp_mat).m[1][0] = -0.866025f; + U(exp_mat).m[2][0] = 0.0f; + U(exp_mat).m[3][0] = -6.0f; + U(exp_mat).m[0][1] = 0.866025f; + U(exp_mat).m[1][1] = 0.50f; + U(exp_mat).m[2][1] = 0.0f; + U(exp_mat).m[3][1] = 7.0f; + U(exp_mat).m[0][2] = 0.0f; + U(exp_mat).m[1][2] = 0.0f; + U(exp_mat).m[2][2] = 1.0f; + U(exp_mat).m[3][2] = 0.0f; + U(exp_mat).m[0][3] = 0.0f; + U(exp_mat).m[1][3] = 0.0f; + U(exp_mat).m[2][3] = 0.0f; + U(exp_mat).m[3][3] = 1.0f; + + D3DXMatrixTransformation2D(&got_mat, &sca_center, sca_rot, NULL, NULL, rot, &trans); + expect_matrix(&exp_mat, &got_mat, 8); + +/*_________*/ + + U(exp_mat).m[0][0] = 0.50f; + U(exp_mat).m[1][0] = -0.866025f; + U(exp_mat).m[2][0] = 0.0f; + U(exp_mat).m[3][0] = 0.0f; + U(exp_mat).m[0][1] = 0.866025f; + U(exp_mat).m[1][1] = 0.50f; + U(exp_mat).m[2][1] = 0.0f; + U(exp_mat).m[3][1] = 0.0f; + U(exp_mat).m[0][2] = 0.0f; + U(exp_mat).m[1][2] = 0.0f; + U(exp_mat).m[2][2] = 1.0f; + U(exp_mat).m[3][2] = 0.0f; + U(exp_mat).m[0][3] = 0.0f; + U(exp_mat).m[1][3] = 0.0f; + U(exp_mat).m[2][3] = 0.0f; + U(exp_mat).m[3][3] = 1.0f; + + D3DXMatrixTransformation2D(&got_mat, NULL, sca_rot, NULL, NULL, rot, NULL); + expect_matrix(&exp_mat, &got_mat, 8); +} + +static void test_D3DXVec_Array(void) +{ + D3DXPLANE inp_plane[5], out_plane[7], exp_plane[7]; + D3DXVECTOR4 inp_vec[5], out_vec[7], exp_vec[7]; + D3DXMATRIX mat, projection, view, world; + D3DVIEWPORT9 viewport; + unsigned int i; + + viewport.Width = 800; viewport.MinZ = 0.2f; viewport.X = 10; + viewport.Height = 680; viewport.MaxZ = 0.9f; viewport.Y = 5; + + memset(out_vec, 0, sizeof(out_vec)); + memset(exp_vec, 0, sizeof(exp_vec)); + memset(out_plane, 0, sizeof(out_plane)); + memset(exp_plane, 0, sizeof(exp_plane)); + + for (i = 0; i < ARRAY_SIZE(inp_vec); ++i) + { + inp_plane[i].a = inp_plane[i].c = inp_vec[i].x = inp_vec[i].z = i; + inp_plane[i].b = inp_plane[i].d = inp_vec[i].y = inp_vec[i].w = ARRAY_SIZE(inp_vec) - i; + } + + set_matrix(&mat, + 1.0f, 2.0f, 3.0f, 4.0f, + 5.0f, 6.0f, 7.0f, 8.0f, + 9.0f, 10.0f, 11.0f, 12.0f, + 13.0f, 14.0f, 15.0f, 16.0f); + + D3DXMatrixPerspectiveFovLH(&projection, D3DX_PI / 4.0f, 20.0f / 17.0f, 1.0f, 1000.0f); + + U(view).m[0][1] = 5.0f; U(view).m[0][2] = 7.0f; U(view).m[0][3] = 8.0f; + U(view).m[1][0] = 11.0f; U(view).m[1][2] = 16.0f; U(view).m[1][3] = 33.0f; + U(view).m[2][0] = 19.0f; U(view).m[2][1] = -21.0f; U(view).m[2][3] = 43.0f; + U(view).m[3][0] = 2.0f; U(view).m[3][1] = 3.0f; U(view).m[3][2] = -4.0f; + U(view).m[0][0] = 10.0f; U(view).m[1][1] = 20.0f; U(view).m[2][2] = 30.0f; + U(view).m[3][3] = -40.0f; + + set_matrix(&world, + 21.0f, 2.0f, 3.0f, 4.0f, + 5.0f, 23.0f, 7.0f, 8.0f, + -8.0f, -7.0f, 25.0f, -5.0f, + -4.0f, -3.0f, -2.0f, 27.0f); + + /* D3DXVec2TransformCoordArray */ + exp_vec[1].x = 6.78571403e-01f; exp_vec[1].y = 7.85714269e-01f; + exp_vec[2].x = 6.53846204e-01f; exp_vec[2].y = 7.69230783e-01f; + exp_vec[3].x = 6.25000000e-01f; exp_vec[3].y = 7.50000000e-01f; + exp_vec[4].x = 5.90909123e-01f; exp_vec[4].y = 7.27272749e-01f; + exp_vec[5].x = 5.49999952e-01f; exp_vec[5].y = 6.99999928e-01f; + D3DXVec2TransformCoordArray((D3DXVECTOR2 *)&out_vec[1], sizeof(*out_vec), + (D3DXVECTOR2 *)inp_vec, sizeof(*inp_vec), &mat, ARRAY_SIZE(inp_vec)); + expect_vec4_array(ARRAY_SIZE(exp_vec), exp_vec, out_vec, 1); + + /* D3DXVec2TransformNormalArray */ + exp_vec[1].x = 25.0f; exp_vec[1].y = 30.0f; + exp_vec[2].x = 21.0f; exp_vec[2].y = 26.0f; + exp_vec[3].x = 17.0f; exp_vec[3].y = 22.0f; + exp_vec[4].x = 13.0f; exp_vec[4].y = 18.0f; + exp_vec[5].x = 9.0f; exp_vec[5].y = 14.0f; + D3DXVec2TransformNormalArray((D3DXVECTOR2 *)&out_vec[1], sizeof(*out_vec), + (D3DXVECTOR2 *)inp_vec, sizeof(*inp_vec), &mat, ARRAY_SIZE(inp_vec)); + expect_vec4_array(ARRAY_SIZE(exp_vec), exp_vec, out_vec, 0); + + /* D3DXVec3TransformCoordArray */ + exp_vec[1].x = 6.78571403e-01f; exp_vec[1].y = 7.85714269e-01f; exp_vec[1].z = 8.92857075e-01f; + exp_vec[2].x = 6.71874940e-01f; exp_vec[2].y = 7.81249940e-01f; exp_vec[2].z = 8.90624940e-01f; + exp_vec[3].x = 6.66666627e-01f; exp_vec[3].y = 7.77777731e-01f; exp_vec[3].z = 8.88888836e-01f; + exp_vec[4].x = 6.62499964e-01f; exp_vec[4].y = 7.74999976e-01f; exp_vec[4].z = 8.87499928e-01f; + exp_vec[5].x = 6.59090877e-01f; exp_vec[5].y = 7.72727251e-01f; exp_vec[5].z = 8.86363566e-01f; + D3DXVec3TransformCoordArray((D3DXVECTOR3 *)&out_vec[1], sizeof(*out_vec), + (D3DXVECTOR3 *)inp_vec, sizeof(*inp_vec), &mat, ARRAY_SIZE(inp_vec)); + expect_vec4_array(ARRAY_SIZE(exp_vec), exp_vec, out_vec, 1); + + /* D3DXVec3TransformNormalArray */ + exp_vec[1].x = 25.0f; exp_vec[1].y = 30.0f; exp_vec[1].z = 35.0f; + exp_vec[2].x = 30.0f; exp_vec[2].y = 36.0f; exp_vec[2].z = 42.0f; + exp_vec[3].x = 35.0f; exp_vec[3].y = 42.0f; exp_vec[3].z = 49.0f; + exp_vec[4].x = 40.0f; exp_vec[4].y = 48.0f; exp_vec[4].z = 56.0f; + exp_vec[5].x = 45.0f; exp_vec[5].y = 54.0f; exp_vec[5].z = 63.0f; + D3DXVec3TransformNormalArray((D3DXVECTOR3 *)&out_vec[1], sizeof(*out_vec), + (D3DXVECTOR3 *)inp_vec, sizeof(*inp_vec), &mat, ARRAY_SIZE(inp_vec)); + expect_vec4_array(ARRAY_SIZE(exp_vec), exp_vec, out_vec, 0); + + /* D3DXVec3ProjectArray */ + exp_vec[1].x = 1.08955420e+03f; exp_vec[1].y = -2.26590622e+02f; exp_vec[1].z = 2.15272754e-01f; + exp_vec[2].x = 1.06890344e+03f; exp_vec[2].y = 1.03085144e+02f; exp_vec[2].z = 1.83049560e-01f; + exp_vec[3].x = 1.05177905e+03f; exp_vec[3].y = 3.76462280e+02f; exp_vec[3].z = 1.56329080e-01f; + exp_vec[4].x = 1.03734888e+03f; exp_vec[4].y = 6.06827393e+02f; exp_vec[4].z = 1.33812696e-01f; + exp_vec[5].x = 1.02502356e+03f; exp_vec[5].y = 8.03591248e+02f; exp_vec[5].z = 1.14580572e-01f; + D3DXVec3ProjectArray((D3DXVECTOR3 *)&out_vec[1], sizeof(*out_vec), (D3DXVECTOR3 *)inp_vec, + sizeof(*inp_vec), &viewport, &projection, &view, &world, ARRAY_SIZE(inp_vec)); + expect_vec4_array(ARRAY_SIZE(exp_vec), exp_vec, out_vec, 8); + + /* D3DXVec3UnprojectArray */ + exp_vec[1].x = -6.12403107e+00f; exp_vec[1].y = 3.22536016e+00f; exp_vec[1].z = 6.20571136e-01f; + exp_vec[2].x = -3.80710936e+00f; exp_vec[2].y = 2.04657936e+00f; exp_vec[2].z = 4.46894377e-01f; + exp_vec[3].x = -2.92283988e+00f; exp_vec[3].y = 1.59668946e+00f; exp_vec[3].z = 3.80609393e-01f; + exp_vec[4].x = -2.45622563e+00f; exp_vec[4].y = 1.35928988e+00f; exp_vec[4].z = 3.45631927e-01f; + exp_vec[5].x = -2.16789746e+00f; exp_vec[5].y = 1.21259713e+00f; exp_vec[5].z = 3.24018806e-01f; + D3DXVec3UnprojectArray((D3DXVECTOR3 *)&out_vec[1], sizeof(*out_vec), (D3DXVECTOR3 *)inp_vec, + sizeof(*inp_vec), &viewport, &projection, &view, &world, ARRAY_SIZE(inp_vec)); + expect_vec4_array(ARRAY_SIZE(exp_vec), exp_vec, out_vec, 4); + + /* D3DXVec2TransformArray */ + exp_vec[1].x = 38.0f; exp_vec[1].y = 44.0f; exp_vec[1].z = 50.0f; exp_vec[1].w = 56.0f; + exp_vec[2].x = 34.0f; exp_vec[2].y = 40.0f; exp_vec[2].z = 46.0f; exp_vec[2].w = 52.0f; + exp_vec[3].x = 30.0f; exp_vec[3].y = 36.0f; exp_vec[3].z = 42.0f; exp_vec[3].w = 48.0f; + exp_vec[4].x = 26.0f; exp_vec[4].y = 32.0f; exp_vec[4].z = 38.0f; exp_vec[4].w = 44.0f; + exp_vec[5].x = 22.0f; exp_vec[5].y = 28.0f; exp_vec[5].z = 34.0f; exp_vec[5].w = 40.0f; + D3DXVec2TransformArray(&out_vec[1], sizeof(*out_vec), (D3DXVECTOR2 *)inp_vec, + sizeof(*inp_vec), &mat, ARRAY_SIZE(inp_vec)); + expect_vec4_array(ARRAY_SIZE(exp_vec), exp_vec, out_vec, 0); + + /* D3DXVec3TransformArray */ + exp_vec[1].x = 38.0f; exp_vec[1].y = 44.0f; exp_vec[1].z = 50.0f; exp_vec[1].w = 56.0f; + exp_vec[2].x = 43.0f; exp_vec[2].y = 50.0f; exp_vec[2].z = 57.0f; exp_vec[2].w = 64.0f; + exp_vec[3].x = 48.0f; exp_vec[3].y = 56.0f; exp_vec[3].z = 64.0f; exp_vec[3].w = 72.0f; + exp_vec[4].x = 53.0f; exp_vec[4].y = 62.0f; exp_vec[4].z = 71.0f; exp_vec[4].w = 80.0f; + exp_vec[5].x = 58.0f; exp_vec[5].y = 68.0f; exp_vec[5].z = 78.0f; exp_vec[5].w = 88.0f; + D3DXVec3TransformArray(&out_vec[1], sizeof(*out_vec), (D3DXVECTOR3 *)inp_vec, + sizeof(*inp_vec), &mat, ARRAY_SIZE(inp_vec)); + expect_vec4_array(ARRAY_SIZE(exp_vec), exp_vec, out_vec, 0); + + /* D3DXVec4TransformArray */ + exp_vec[1].x = 90.0f; exp_vec[1].y = 100.0f; exp_vec[1].z = 110.0f; exp_vec[1].w = 120.0f; + exp_vec[2].x = 82.0f; exp_vec[2].y = 92.0f; exp_vec[2].z = 102.0f; exp_vec[2].w = 112.0f; + exp_vec[3].x = 74.0f; exp_vec[3].y = 84.0f; exp_vec[3].z = 94.0f; exp_vec[3].w = 104.0f; + exp_vec[4].x = 66.0f; exp_vec[4].y = 76.0f; exp_vec[4].z = 86.0f; exp_vec[4].w = 96.0f; + exp_vec[5].x = 58.0f; exp_vec[5].y = 68.0f; exp_vec[5].z = 78.0f; exp_vec[5].w = 88.0f; + D3DXVec4TransformArray(&out_vec[1], sizeof(*out_vec), inp_vec, sizeof(*inp_vec), &mat, ARRAY_SIZE(inp_vec)); + expect_vec4_array(ARRAY_SIZE(exp_vec), exp_vec, out_vec, 0); + + /* D3DXPlaneTransformArray */ + exp_plane[1].a = 90.0f; exp_plane[1].b = 100.0f; exp_plane[1].c = 110.0f; exp_plane[1].d = 120.0f; + exp_plane[2].a = 82.0f; exp_plane[2].b = 92.0f; exp_plane[2].c = 102.0f; exp_plane[2].d = 112.0f; + exp_plane[3].a = 74.0f; exp_plane[3].b = 84.0f; exp_plane[3].c = 94.0f; exp_plane[3].d = 104.0f; + exp_plane[4].a = 66.0f; exp_plane[4].b = 76.0f; exp_plane[4].c = 86.0f; exp_plane[4].d = 96.0f; + exp_plane[5].a = 58.0f; exp_plane[5].b = 68.0f; exp_plane[5].c = 78.0f; exp_plane[5].d = 88.0f; + D3DXPlaneTransformArray(&out_plane[1], sizeof(*out_plane), inp_plane, + sizeof(*inp_plane), &mat, ARRAY_SIZE(inp_plane)); + for (i = 0; i < ARRAY_SIZE(exp_plane); ++i) + { + BOOL equal = compare_plane(&exp_plane[i], &out_plane[i], 0); + ok(equal, "Got unexpected plane {%.8e, %.8e, %.8e, %.8e} at index %u, expected {%.8e, %.8e, %.8e, %.8e}.\n", + out_plane[i].a, out_plane[i].b, out_plane[i].c, out_plane[i].d, i, + exp_plane[i].a, exp_plane[i].b, exp_plane[i].c, exp_plane[i].d); + if (!equal) + break; + } +} + +static void test_D3DXFloat_Array(void) +{ + unsigned int i; + void *out = NULL; + D3DXFLOAT16 half; + BOOL equal; + + /* Input floats through bit patterns because compilers do not generate reliable INF and NaN values. */ + union convert + { + DWORD d; + float f; + } single; + + struct + { + union convert single_in; + + /* half_ver2 occurs on WXPPROSP3 (32 bit math), WVISTAADM (32/64 bit math), W7PRO (32 bit math) */ + WORD half_ver1, half_ver2; + + /* single_out_ver2 confirms that half -> single conversion is consistent across platforms */ + union convert single_out_ver1, single_out_ver2; + } + testdata[] = + { + { { 0x479c4000 }, 0x7c00, 0x7ce2, { 0x47800000 }, { 0x479c4000 } }, /* 80000.0f */ + { { 0x477fdf00 }, 0x7bff, 0x7bff, { 0x477fe000 }, { 0x477fe000 } }, /* 65503.0f */ + { { 0x477fe000 }, 0x7bff, 0x7bff, { 0x477fe000 }, { 0x477fe000 } }, /* 65504.0f */ + { { 0x477ff000 }, 0x7bff, 0x7c00, { 0x477fe000 }, { 0x47800000 } }, /* 65520.0f */ + { { 0x477ff100 }, 0x7c00, 0x7c00, { 0x47800000 }, { 0x47800000 } }, /* 65521.0f */ + + { { 0x477ffe00 }, 0x7c00, 0x7c00, { 0x47800000 }, { 0x47800000 } }, /* 65534.0f */ + { { 0x477fff00 }, 0x7c00, 0x7c00, { 0x47800000 }, { 0x47800000 } }, /* 65535.0f */ + { { 0x47800000 }, 0x7c00, 0x7c00, { 0x47800000 }, { 0x47800000 } }, /* 65536.0f */ + { { 0xc79c4000 }, 0xfc00, 0xfce2, { 0xc7800000 }, { 0xc79c4000 } }, /* -80000.0f */ + { { 0xc77fdf00 }, 0xfbff, 0xfbff, { 0xc77fe000 }, { 0xc77fe000 } }, /* -65503.0f */ + + { { 0xc77fe000 }, 0xfbff, 0xfbff, { 0xc77fe000 }, { 0xc77fe000 } }, /* -65504.0f */ + { { 0xc77ff000 }, 0xfbff, 0xfc00, { 0xc77fe000 }, { 0xc7800000 } }, /* -65520.0f */ + { { 0xc77ff100 }, 0xfc00, 0xfc00, { 0xc7800000 }, { 0xc7800000 } }, /* -65521.0f */ + { { 0xc77ffe00 }, 0xfc00, 0xfc00, { 0xc7800000 }, { 0xc7800000 } }, /* -65534.0f */ + { { 0xc77fff00 }, 0xfc00, 0xfc00, { 0xc7800000 }, { 0xc7800000 } }, /* -65535.0f */ + + { { 0xc7800000 }, 0xfc00, 0xfc00, { 0xc7800000 }, { 0xc7800000 } }, /* -65536.0f */ + { { 0x7f800000 }, 0x7c00, 0x7fff, { 0x47800000 }, { 0x47ffe000 } }, /* INF */ + { { 0xff800000 }, 0xffff, 0xffff, { 0xc7ffe000 }, { 0xc7ffe000 } }, /* -INF */ + { { 0x7fc00000 }, 0x7fff, 0xffff, { 0x47ffe000 }, { 0xc7ffe000 } }, /* NaN */ + { { 0xffc00000 }, 0xffff, 0xffff, { 0xc7ffe000 }, { 0xc7ffe000 } }, /* -NaN */ + + { { 0x00000000 }, 0x0000, 0x0000, { 0x00000000 }, { 0x00000000 } }, /* 0.0f */ + { { 0x80000000 }, 0x8000, 0x8000, { 0x80000000 }, { 0x80000000 } }, /* -0.0f */ + { { 0x330007ff }, 0x0000, 0x0000, { 0x00000000 }, { 0x00000000 } }, /* 2.9809595e-08f */ + { { 0xb30007ff }, 0x8000, 0x8000, { 0x80000000 }, { 0x80000000 } }, /* -2.9809595e-08f */ + { { 0x33000800 }, 0x0001, 0x0000, { 0x33800000 }, { 0x00000000 } }, /* 2.9809598e-08f */ + + { { 0xb3000800 }, 0x8001, 0x8000, { 0xb3800000 }, { 0x80000000 } }, /* -2.9809598e-08f */ + { { 0x33c00000 }, 0x0002, 0x0001, { 0x34000000 }, { 0x33800000 } }, /* 8.9406967e-08f */ + }; + + /* exception on NULL out or in parameter */ + out = D3DXFloat32To16Array(&half, &single.f, 0); + ok(out == &half, "Got %p, expected %p.\n", out, &half); + + out = D3DXFloat16To32Array(&single.f, &half, 0); + ok(out == &single.f, "Got %p, expected %p.\n", out, &single.f); + + for (i = 0; i < ARRAY_SIZE(testdata); ++i) + { + out = D3DXFloat32To16Array(&half, &testdata[i].single_in.f, 1); + ok(out == &half, "Got %p, expected %p.\n", out, &half); + ok(half.value == testdata[i].half_ver1 || half.value == testdata[i].half_ver2, + "Got %x, expected %x or %x for index %d.\n", half.value, testdata[i].half_ver1, + testdata[i].half_ver2, i); + + out = D3DXFloat16To32Array(&single.f, (D3DXFLOAT16 *)&testdata[i].half_ver1, 1); + ok(out == &single.f, "Got %p, expected %p.\n", out, &single.f); + equal = compare_float(single.f, testdata[i].single_out_ver1.f, 0); + ok(equal, "Got %#x, expected %#x at index %u.\n", single.d, testdata[i].single_out_ver1.d, i); + + out = D3DXFloat16To32Array(&single.f, (D3DXFLOAT16 *)&testdata[i].half_ver2, 1); + ok(out == &single.f, "Got %p, expected %p.\n", out, &single.f); + equal = compare_float(single.f, testdata[i].single_out_ver2.f, 0); + ok(equal, "Got %#x, expected %#x at index %u.\n", single.d, testdata[i].single_out_ver2.d, i); + } +} + +static void test_D3DXSHAdd(void) +{ + float out[50] = {0.0f}; + unsigned int i, k; + float *ret; + BOOL equal; + + static const float in1[50] = + { + 1.11f, 1.12f, 1.13f, 1.14f, 1.15f, 1.16f, 1.17f, 1.18f, + 1.19f, 1.20f, 1.21f, 1.22f, 1.23f, 1.24f, 1.25f, 1.26f, + 1.27f, 1.28f, 1.29f, 1.30f, 1.31f, 1.32f, 1.33f, 1.34f, + 1.35f, 1.36f, 1.37f, 1.38f, 1.39f, 1.40f, 1.41f, 1.42f, + 1.43f, 1.44f, 1.45f, 1.46f, 1.47f, 1.48f, 1.49f, 1.50f, + 1.51f, 1.52f, 1.53f, 1.54f, 1.55f, 1.56f, 1.57f, 1.58f, + 1.59f, 1.60f, + }; + static const float in2[50] = + { + 2.11f, 2.12f, 2.13f, 2.14f, 2.15f, 2.16f, 2.17f, 2.18f, + 2.19f, 2.20f, 2.21f, 2.22f, 2.23f, 2.24f, 2.25f, 2.26f, + 2.27f, 2.28f, 2.29f, 2.30f, 2.31f, 2.32f, 2.33f, 2.34f, + 2.35f, 2.36f, 2.37f, 2.38f, 2.39f, 2.40f, 2.41f, 2.42f, + 2.43f, 2.44f, 2.45f, 2.46f, 2.47f, 2.48f, 2.49f, 2.50f, + 2.51f, 2.52f, 2.53f, 2.54f, 2.55f, 2.56f, 2.57f, 2.58f, + 2.59f, 2.60f, + }; + + /* + * Order is not limited by D3DXSH_MINORDER and D3DXSH_MAXORDER! + * All values will work, test from 0-7 [D3DXSH_MINORDER = 2, D3DXSH_MAXORDER = 6] + * Exceptions will show up when out, in1 or in2 is NULL + */ + for (k = 0; k <= D3DXSH_MAXORDER + 1; k++) + { + UINT count = k * k; + + ret = D3DXSHAdd(&out[0], k, &in1[0], &in2[0]); + ok(ret == out, "%u: D3DXSHAdd() failed, got %p, expected %p\n", k, out, ret); + + for (i = 0; i < count; ++i) + { + equal = compare_float(in1[i] + in2[i], out[i], 0); + ok(equal, "%u-%u: Got %.8e, expected %.8e.\n", k, i, out[i], in1[i] + in2[i]); + } + equal = compare_float(out[count], 0.0f, 0); + ok(equal, "%u-%u: Got %.8e, expected 0.0.\n", k, k * k, out[count]); + } +} + +static void test_D3DXSHDot(void) +{ + float a[49], b[49], got; + unsigned int i; + BOOL equal; + + static const float expected[] = {0.5f, 0.5f, 25.0f, 262.5f, 1428.0f, 5362.5f, 15873.0f, 39812.5f}; + + for (i = 0; i < ARRAY_SIZE(a); ++i) + { + a[i] = i + 1.0f; + b[i] = i + 0.5f; + } + + /* D3DXSHDot computes by using order * order elements */ + for (i = 0; i <= D3DXSH_MAXORDER + 1; i++) + { + got = D3DXSHDot(i, a, b); + equal = compare_float(got, expected[i], 0); + ok(equal, "order %u: Got %.8e, expected %.8e.\n", i, got, expected[i]); + } +} + +static void test_D3DXSHEvalConeLight(void) +{ + float bout[49], expected, gout[49], rout[49]; + unsigned int j, l, order; + D3DXVECTOR3 dir; + HRESULT hr; + BOOL equal; + + static const float table[] = + { + /* Red colour */ + 1.604815f, -3.131381f, 7.202175f, -2.870432f, 6.759296f, -16.959688f, + 32.303082f, -15.546381f, -0.588878f, -5.902123f, 40.084042f, -77.423569f, + 137.556320f, -70.971603f, -3.492171f, 7.683092f, -2.129311f, -35.971344f, + 183.086548f, -312.414948f, 535.091064f, -286.380371f, -15.950727f, 46.825714f, + -12.127637f, 11.289261f, -12.417809f, -155.039566f, 681.182556f, -1079.733643f, + 1807.650513f, -989.755798f, -59.345467f, 201.822815f, -70.726486f, 7.206529f, + + 3.101155f, -3.128710f, 7.196033f, -2.867984f, -0.224708f, 0.563814f, + -1.073895f, 0.516829f, 0.019577f, 2.059788f, -13.988971f, 27.020128f, + -48.005917f, 24.768450f, 1.218736f, -2.681329f, -0.088639f, -1.497410f, + 7.621501f, -13.005165f, 22.274696f, -11.921401f, -0.663995f, 1.949254f, + -0.504848f, 4.168484f, -4.585193f, -57.247314f, 251.522095f, -398.684387f, + 667.462891f, -365.460693f, -21.912912f, 74.521721f, -26.115280f, 2.660963f, + /* Green colour */ + 2.454422f, -4.789170f, 11.015091f, -4.390072f, 10.337747f, -25.938347f, + 49.404713f, -23.776817f, -0.900637f, -9.026776f, 61.305000f, -118.412514f, + 210.380249f, -108.544792f, -5.340967f, 11.750610f, -3.256593f, -55.014996f, + 280.014709f, -477.811066f, 818.374512f, -437.993469f, -24.395227f, 71.615799f, + -18.548151f, 17.265928f, -18.991943f, -237.119324f, 1041.808594f, -1651.357300f, + 2764.642090f, -1513.744141f, -90.763657f, 308.670197f, -108.169922f, 11.021750f, + + 4.742942f, -4.785086f, 11.005697f, -4.386329f, -0.343672f, 0.862303f, + -1.642427f, 0.790444f, 0.029941f, 3.150264f, -21.394896f, 41.324898f, + -73.420807f, 37.881153f, 1.863950f, -4.100857f, -0.135565f, -2.290156f, + 11.656413f, -19.890251f, 34.067181f, -18.232729f, -1.015521f, 2.981212f, + -0.772120f, 6.375328f, -7.012648f, -87.554710f, 384.680817f, -609.752563f, + 1020.825500f, -558.939819f, -33.513863f, 113.974388f, -39.941013f, 4.069707f, + /* Blue colour */ + 3.304030f, -6.446959f, 14.828006f, -5.909713f, 13.916198f, -34.917004f, + 66.506340f, -32.007256f, -1.212396f, -12.151429f, 82.525963f, -159.401459f, + 283.204193f, -146.117996f, -7.189764f, 15.818130f, -4.383876f, -74.058655f, + 376.942871f, -643.207214f, 1101.658081f, -589.606628f, -32.839729f, 96.405884f, + -24.968664f, 23.242596f, -25.566080f, -319.199097f, 1402.434692f, -2222.980957f, + 3721.633545f, -2037.732544f, -122.181847f, 415.517578f, -145.613358f, 14.836972f, + + 6.384730f, -6.441462f, 14.815362f, -5.904673f, -0.462635f, 1.160793f, + -2.210959f, 1.064060f, 0.040305f, 4.240739f, -28.800821f, 55.629673f, + -98.835709f, 50.993862f, 2.509163f, -5.520384f, -0.182491f, -3.082903f, + 15.691326f, -26.775339f, 45.859665f, -24.544060f, -1.367048f, 4.013170f, + -1.039392f, 8.582172f, -9.440103f, -117.862114f, 517.839600f, -820.820740f, + 1374.188232f, -752.419067f, -45.114819f, 153.427063f, -53.766754f, 5.478452f, }; + const struct + { + float *red_received, *green_received, *blue_received; + const float *red_expected, *green_expected, *blue_expected; + float radius, roffset, goffset, boffset; + } + test[] = + { + { rout, gout, bout, table, &table[72], &table[144], 0.5f, 1.01f, 1.02f, 1.03f, }, + { rout, gout, bout, &table[36], &table[108], &table[180], 1.6f, 1.01f, 1.02f, 1.03f, }, + { rout, rout, rout, &table[144], &table[144], &table[144], 0.5f, 1.03f, 1.03f, 1.03f, }, + { rout, rout, bout, &table[72], &table[72], &table[144], 0.5, 1.02f, 1.02f, 1.03f, }, + { rout, gout, gout, table, &table[144], &table[144], 0.5f, 1.01f, 1.03f, 1.03f, }, + { rout, gout, rout, &table[144], &table[72], &table[144], 0.5f, 1.03f, 1.02f, 1.03f, }, + /* D3DXSHEvalConeLight accepts NULL green or blue colour. */ + { rout, NULL, bout, table, NULL, &table[144], 0.5f, 1.01f, 0.0f, 1.03f, }, + { rout, gout, NULL, table, &table[72], NULL, 0.5f, 1.01f, 1.02f, 0.0f, }, + { rout, NULL, NULL, table, NULL, NULL, 0.5f, 1.01f, 0.0f, 0.0f, }, + }; + + dir.x = 1.1f; dir.y = 1.2f; dir.z = 2.76f; + + for (l = 0; l < ARRAY_SIZE(test); ++l) + { + for (order = D3DXSH_MINORDER; order <= D3DXSH_MAXORDER; order++) + { + for (j = 0; j < 49; j++) + { + test[l].red_received[j] = 1.01f + j; + if (test[l].green_received) + test[l].green_received[j] = 1.02f + j; + if (test[l].blue_received) + test[l].blue_received[j] = 1.03f + j; + } + + hr = D3DXSHEvalConeLight(order, &dir, test[l].radius, 1.7f, 2.6f, 3.5f, test[l].red_received, test[l].green_received, test[l].blue_received); + ok(hr == D3D_OK, "Expected %#x, got %#x\n", D3D_OK, hr); + + for (j = 0; j < 49; j++) + { + if (j >= order * order) + expected = j + test[l].roffset; + else + expected = test[l].red_expected[j]; + equal = compare_float(test[l].red_received[j], expected, 128); + ok(equal, "Red: case %u, order %u: expected[%u] = %.8e, received %.8e.\n", + l, order, j, expected, test[l].red_received[j]); + + if (test[l].green_received) + { + if (j >= order * order) + expected = j + test[l].goffset; + else + expected = test[l].green_expected[j]; + equal = compare_float(test[l].green_received[j], expected, 64); + ok(equal, "Green: case %u, order %u: expected[%u] = %.8e, received %.8e.\n", + l, order, j, expected, test[l].green_received[j]); + } + + if (test[l].blue_received) + { + if (j >= order * order) + expected = j + test[l].boffset; + else + expected = test[l].blue_expected[j]; + equal = compare_float(test[l].blue_received[j], expected, 128); + ok(equal, "Blue: case %u, order %u: expected[%u] = %.8e, received %.8e.\n", + l, order, j, expected, test[l].blue_received[j]); + } + } + } + } + + /* Cone light with radius <= 0.0f behaves as a directional light */ + for (order = D3DXSH_MINORDER; order <= D3DXSH_MAXORDER; order++) + { + FLOAT blue[49], green[49], red[49]; + + for (j = 0; j < 49; j++) + { + rout[j] = 1.01f + j; + gout[j] = 1.02f + j; + bout[j] = 1.03f + j; + red[j] = 1.01f + j; + green[j] = 1.02f + j; + blue[j] = 1.03f + j; + } + + hr = D3DXSHEvalConeLight(order, &dir, -0.1f, 1.7f, 2.6f, 3.5f, rout, gout, bout); + ok(hr == D3D_OK, "Expected %#x, got %#x\n", D3D_OK, hr); + D3DXSHEvalDirectionalLight(order, &dir, 1.7f, 2.6f, 3.5f, red, green, blue); + + for (j = 0; j < 49; j++) + { + equal = compare_float(red[j], rout[j], 0); + ok(equal, "Red: case %u, order %u: expected[%u] = %.8e, received %.8e.\n", + l, order, j, red[j], rout[j]); + + equal = compare_float(green[j], gout[j], 0); + ok(equal, "Green: case %u, order %u: expected[%u] = %.8e, received %.8e.\n", + l, order, j, green[j], gout[j]); + + equal = compare_float(blue[j], bout[j], 0); + ok(equal, "Blue: case %u, order %u: expected[%u] = %.8e, received %.8e.\n", + l, order, j, blue[j], bout[j]); + } + } + + /* D3DXSHEvalConeLight accepts order < D3DXSH_MINORDER or order > D3DXSH_MAXORDER. But tests in native windows show that the colour outputs are not set */ + hr = D3DXSHEvalConeLight(7, &dir, 0.5f, 1.0f, 2.0f, 3.0f, rout, gout, bout); + ok(hr == D3D_OK, "Expected %#x, got %#x\n", D3D_OK, hr); + hr = D3DXSHEvalConeLight(0, &dir, 0.5f, 1.0f, 2.0f, 3.0f, rout, gout, bout); + ok(hr == D3D_OK, "Expected %#x, got %#x\n", D3D_OK, hr); + hr = D3DXSHEvalConeLight(1, &dir, 0.5f, 1.0f, 2.0f, 3.0f, rout, gout, bout); + ok(hr == D3D_OK, "Expected %#x, got %#x\n", D3D_OK, hr); +} + +static void test_D3DXSHEvalDirection(void) +{ + float a[49], expected, *received_ptr; + unsigned int i, order; + D3DXVECTOR3 d; + BOOL equal; + + static const float table[36] = + { + 2.82094806e-01f, -9.77205038e-01f, 1.46580756e+00f, -4.88602519e-01f, 2.18509698e+00f, -6.55529118e+00f, + 8.20018101e+00f, -3.27764559e-00f, -1.63882279e+00f, 1.18008721e+00f, 1.73436680e+01f, -4.02200317e+01f, + 4.70202179e+01f, -2.01100159e+01f, -1.30077515e+01f, 6.49047947e+00f, -1.50200577e+01f, 1.06207848e+01f, + 1.17325661e+02f, -2.40856750e+02f, 2.71657288e+02f, -1.20428375e+02f, -8.79942474e+01f, 5.84143143e+01f, + -4.38084984e+00f, 2.49425201e+01f, -1.49447693e+02f, 7.82781296e+01f, 7.47791748e+02f, -1.42768787e+03f, + 1.57461914e+03f, -7.13843933e+02f, -5.60843811e+02f, 4.30529724e+02f, -4.35889091e+01f, -2.69116650e+01f, + }; + + d.x = 1.0; d.y = 2.0f; d.z = 3.0f; + + for (order = 0; order <= D3DXSH_MAXORDER + 1; order++) + { + for (i = 0; i < ARRAY_SIZE(a); ++i) + a[i] = 1.5f + i; + + received_ptr = D3DXSHEvalDirection(a, order, &d); + ok(received_ptr == a, "Expected %p, received %p\n", a, received_ptr); + + for (i = 0; i < ARRAY_SIZE(a); ++i) + { + /* if the order is < D3DXSH_MINORDER or order > D3DXSH_MAXORDER or + * the index of the element is greater than order * order - 1, + * D3DXSHEvalDirection() does not modify the output. */ + if ((order < D3DXSH_MINORDER) || (order > D3DXSH_MAXORDER) || (i >= order * order)) + expected = 1.5f + i; + else + expected = table[i]; + + equal = compare_float(a[i], expected, 2); + ok(equal, "order %u, index %u: Got unexpected result %.8e, expected %.8e.\n", + order, i, a[i], expected); + } + } +} + +static void test_D3DXSHEvalDirectionalLight(void) +{ + float *blue_out, bout[49], expected, gout[49], *green_out, *red_out, rout[49]; + unsigned int j, l, order, startindex; + D3DXVECTOR3 dir; + HRESULT hr; + BOOL equal; + + static const float table[] = + { + /* Red colour */ + 2.008781f, -4.175174f, 9.602900f, -3.827243f, 1.417963f, -2.947181f, + 6.778517f, -2.701583f, 7.249108f, -18.188671f, 34.643921f, -16.672949f, + -0.631551f, 1.417963f, -2.947181f, 6.778517f, -2.701583f, 7.249108f, + -18.188671f, 34.643921f, -16.672949f, -0.631551f, -7.794341f, 52.934967f, + -102.245529f, 181.656815f, -93.725060f, -4.611760f, 10.146287f, 1.555186f, + -3.232392f, 7.434503f, -2.963026f, 7.950634f, -19.948866f, 37.996559f, + -18.286459f, -0.692669f, -8.548632f, 58.057705f, -112.140251f, 199.236496f, + -102.795227f, -5.058059f, 11.128186f, -4.189955f, -70.782669f, 360.268829f, + -614.755005f, 1052.926270f, -563.525391f, -31.387066f, 92.141365f, -23.864176f, + 1.555186f, -3.232392f, 7.434503f, -2.963026f, 7.950634f, -19.948866f, + 37.996559f, -18.286459f, -0.692669f, -8.548632f, 58.057705f, -112.140251f, + 199.236496f, -102.795227f, -5.058059f, 11.128186f, -4.189955f, -70.782669f, + 360.268829f, -614.755005f, 1052.926270f, -563.525391f, -31.387066f, 92.141365f, + -23.864176f, 34.868664f, -38.354366f, -478.864166f, 2103.939941f, -3334.927734f, + 5583.213867f, -3057.017090f, -183.297836f, 623.361633f, -218.449921f, 22.258503f, + /* Green colour */ + 3.072254f, -6.385560f, 14.686787f, -5.853429f, 2.168650f, -4.507453f, + 10.367143f, -4.131832f, 11.086870f, -27.817965f, 52.984818f, -25.499800f, + -0.965902f, 2.168650f, -4.507453f, 10.367143f, -4.131832f, 11.086870f, + -27.817965f, 52.984818f, -25.499800f, -0.965902f, -11.920755f, 80.959351f, + -156.375488f, 277.828033f, -143.344193f, -7.053278f, 15.517849f, 2.378519f, + -4.943659f, 11.370415f, -4.531687f, 12.159794f, -30.510029f, 58.112385f, + -27.967525f, -1.059376f, -13.074378f, 88.794136f, -171.508621f, 304.714630f, + -157.216217f, -7.735855f, 17.019577f, -6.408166f, -108.255844f, 550.999390f, + -940.213501f, 1610.357788f, -861.862305f, -48.003746f, 140.922089f, -36.498150f, + 2.378519f, -4.943659f, 11.370415f, -4.531687f, 12.159794f, -30.510029f, + 58.112385f, -27.967525f, -1.059376f, -13.074378f, 88.794136f, -171.508621f, + 304.714630f, -157.216217f, -7.735855f, 17.019577f, -6.408166f, -108.255844f, + 550.999390f, -940.213501f, 1610.357788f, -861.862305f, -48.003746f, 140.922089f, + -36.498150f, 53.328545f, -58.659618f, -732.380493f, 3217.790283f, -5100.477539f, + 8539.033203f, -4675.437500f, -280.337860f, 953.376587f, -334.099884f, 34.042416f, + /* Blue colour */ + 4.135726f, -8.595945f, 19.770674f, -7.879617f, 2.919336f, -6.067726f, + 13.955770f, -5.562082f, 14.924634f, -37.447262f, 71.325722f, -34.326656f, + -1.300252f, 2.919336f, -6.067726f, 13.955770f, -5.562082f, 14.924634f, + -37.447262f, 71.325722f, -34.326656f, -1.300252f, -16.047173f, 108.983749f, + -210.505493f, 373.999298f, -192.963348f, -9.494799f, 20.889414f, 3.201853f, + -6.654925f, 15.306328f, -6.100348f, 16.368954f, -41.071194f, 78.228210f, + -37.648590f, -1.426083f, -17.600124f, 119.530563f, -230.876984f, 410.192780f, + -211.637222f, -10.413651f, 22.910971f, -8.626378f, -145.729019f, 741.729919f, + -1265.671997f, 2167.789307f, -1160.199219f, -64.620430f, 189.702820f, -49.132126f, + 3.201853f, -6.654925f, 15.306328f, -6.100348f, 16.368954f, -41.071194f, + 78.228210f, -37.648590f, -1.426083f, -17.600124f, 119.530563f, -230.876984f, + 410.192780f, -211.637222f, -10.413651f, 22.910971f, -8.626378f, -145.729019f, + 741.729919f, -1265.671997f, 2167.789307f, -1160.199219f, -64.620430f, 189.702820f, + -49.132126f, 71.788422f, -78.964867f, -985.896790f, 4331.640625f, -6866.027344f, + 11494.852539f, -6293.858398f, -377.377899f, 1283.391479f, -449.749817f, 45.826328f, }; + const struct + { + float *red_in, *green_in, *blue_in; + const float *red_out, *green_out, *blue_out; + float roffset, goffset, boffset; + } + test[] = + { + { rout, gout, bout, table, &table[90], &table[180], 1.01f, 1.02f, 1.03f, }, + { rout, rout, rout, &table[180], &table[180], &table[180], 1.03f, 1.03f, 1.03f, }, + { rout, rout, bout, &table[90], &table[90], &table[180], 1.02f, 1.02f, 1.03f, }, + { rout, gout, gout, table, &table[180], &table[180], 1.01f, 1.03f, 1.03f, }, + { rout, gout, rout, &table[180], &table[90], &table[180], 1.03f, 1.02f, 1.03f, }, + /* D3DXSHEvalDirectionaLight accepts NULL green or blue colour. */ + { rout, NULL, bout, table, NULL, &table[180], 1.01f, 0.0f, 1.03f, }, + { rout, gout, NULL, table, &table[90], NULL, 1.01f, 1.02f, 0.0f, }, + { rout, NULL, NULL, table, NULL, NULL, 1.01f, 0.0f, 0.0f, }, + }; + + dir.x = 1.1f; dir.y= 1.2f; dir.z = 2.76f; + + for (l = 0; l < ARRAY_SIZE(test); ++l) + { + startindex = 0; + + for (order = D3DXSH_MINORDER; order <= D3DXSH_MAXORDER; order++) + { + red_out = test[l].red_in; + green_out = test[l].green_in; + blue_out = test[l].blue_in; + + for (j = 0; j < ARRAY_SIZE(rout); ++j) + { + red_out[j] = 1.01f + j; + if ( green_out ) + green_out[j] = 1.02f + j; + if ( blue_out ) + blue_out[j] = 1.03f + j; + } + + hr = D3DXSHEvalDirectionalLight(order, &dir, 1.7f, 2.6f, 3.5f, red_out, green_out, blue_out); + ok(hr == D3D_OK, "Expected %#x, got %#x\n", D3D_OK, hr); + + for (j = 0; j < ARRAY_SIZE(rout); ++j) + { + if ( j >= order * order ) + expected = j + test[l].roffset; + else + expected = test[l].red_out[startindex + j]; + equal = compare_float(expected, red_out[j], 8); + ok(equal, "Red: case %u, order %u: expected[%u] = %.8e, received %.8e.\n", + l, order, j, expected, red_out[j]); + + if ( green_out ) + { + if ( j >= order * order ) + expected = j + test[l].goffset; + else + expected = test[l].green_out[startindex + j]; + equal = compare_float(expected, green_out[j], 8); + ok(equal, "Green: case %u, order %u: expected[%u] = %.8e, received %.8e.\n", + l, order, j, expected, green_out[j]); + } + + if ( blue_out ) + { + if ( j >= order * order ) + expected = j + test[l].boffset; + else + expected = test[l].blue_out[startindex + j]; + equal = compare_float(expected, blue_out[j], 4); + ok(equal, "Blue: case %u, order %u: expected[%u] = %.8e, received %.8e.\n", + l, order, j, expected, blue_out[j]); + } + } + + startindex += order * order; + } + } + + /* D3DXSHEvalDirectionalLight accepts order < D3DXSH_MINORDER or order > D3DXSH_MAXORDER. But tests in native windows show that the colour outputs are not set*/ + hr = D3DXSHEvalDirectionalLight(7, &dir, 1.0f, 2.0f, 3.0f, rout, gout, bout); + ok(hr == D3D_OK, "Expected %#x, got %#x\n", D3D_OK, hr); + hr = D3DXSHEvalDirectionalLight(0, &dir, 1.0f, 2.0f, 3.0f, rout, gout, bout); + ok(hr == D3D_OK, "Expected %#x, got %#x\n", D3D_OK, hr); + hr = D3DXSHEvalDirectionalLight(1, &dir, 1.0f, 2.0f, 3.0f, rout, gout, bout); + ok(hr == D3D_OK, "Expected %#x, got %#x\n", D3D_OK, hr); +} + +static void test_D3DXSHEvalHemisphereLight(void) +{ + float bout[49], expected, gout[49], rout[49]; + unsigned int j, l, order; + D3DXCOLOR bottom, top; + D3DXVECTOR3 dir; + HRESULT hr; + BOOL equal; + + static const float table[] = + { + /* Red colour. */ + 23.422981f, 15.859521f, -36.476898f, 14.537894f, + /* Green colour. */ + 19.966694f, 6.096982f, -14.023058f, 5.588900f, + /* Blue colour. */ + 24.566214f, 8.546826f, -19.657701f, 7.834591f, + }; + const struct + { + float *red_received, *green_received, *blue_received; + const float *red_expected, *green_expected, *blue_expected; + const float roffset, goffset, boffset; + } + test[] = + { + { rout, gout, bout, table, &table[4], &table[8], 1.01f, 1.02f, 1.03f, }, + { rout, rout, rout, &table[8], &table[8], &table[8], 1.03f, 1.03f, 1.03f, }, + { rout, rout, bout, &table[4], &table[4], &table[8], 1.02f, 1.02f, 1.03f, }, + { rout, gout, gout, table, &table[8], &table[8], 1.01f, 1.03f, 1.03f, }, + { rout, gout, rout, &table[8], &table[4], &table[8], 1.03f, 1.02f, 1.03f, }, + /* D3DXSHEvalHemisphereLight accepts NULL green or blue colour. */ + { rout, NULL, bout, table, NULL, &table[8], 1.01f, 1.02f, 1.03f, }, + { rout, gout, NULL, table, &table[4], NULL, 1.01f, 1.02f, 1.03f, }, + { rout, NULL, NULL, table, NULL, NULL, 1.01f, 1.02f, 1.03f, }, + }; + + dir.x = 1.1f; dir.y = 1.2f; dir.z = 2.76f; + top.r = 0.1f; top.g = 2.1f; top.b = 2.3f; top.a = 4.3f; + bottom.r = 8.71f; bottom.g = 5.41f; bottom.b = 6.94f; bottom.a = 8.43f; + + for (l = 0; l < ARRAY_SIZE(test); ++l) + for (order = D3DXSH_MINORDER; order <= D3DXSH_MAXORDER + 1; order++) + { + for (j = 0; j < 49; j++) + { + test[l].red_received[j] = 1.01f + j; + if (test[l].green_received) + test[l].green_received[j] = 1.02f + j; + if (test[l].blue_received) + test[l].blue_received[j] = 1.03f + j; + } + + hr = D3DXSHEvalHemisphereLight(order, &dir, top, bottom, test[l].red_received, test[l].green_received, test[l].blue_received); + ok(hr == D3D_OK, "Expected %#x, got %#x\n", D3D_OK, hr); + + for (j = 0; j < 49; j++) + { + if (j < 4) + expected = test[l].red_expected[j]; + else if (j < order * order) + expected = 0.0f; + else + expected = test[l].roffset + j; + equal = compare_float(test[l].red_received[j], expected, 4); + ok(equal, "Red: case %u, order %u: expected[%u] = %.8e, received %.8e.\n", + l, order, j, expected, test[l].red_received[j]); + + if (test[l].green_received) + { + if (j < 4) + expected = test[l].green_expected[j]; + else if (j < order * order) + expected = 0.0f; + else + expected = test[l].goffset + j; + equal = compare_float(expected, test[l].green_received[j], 4); + ok(equal, "Green: case %u, order %u: expected[%u] = %.8e, received %.8e.\n", + l, order, j, expected, test[l].green_received[j]); + } + + if (test[l].blue_received) + { + if (j < 4) + expected = test[l].blue_expected[j]; + else if (j < order * order) + expected = 0.0f; + else + expected = test[l].boffset + j; + equal = compare_float(expected, test[l].blue_received[j], 4); + ok(equal, "Blue: case %u, order %u: expected[%u] = %.8e, received %.8e.\n", + l, order, j, expected, test[l].blue_received[j]); + } + } + } +} + +static void test_D3DXSHEvalSphericalLight(void) +{ + float bout[49], expected, gout[49], rout[49]; + unsigned int j, l, order; + D3DXVECTOR3 dir; + HRESULT hr; + BOOL equal; + + static const float table[] = + { + /* Red colour. */ + 3.01317163e+00f, -9.77240128e-01f, 2.24765220e+00f, -8.95803434e-01f, 3.25255224e-35f, -8.16094904e-35f, + 8.95199460e-35f, -7.48086982e-35f, -2.83366352e-36f, 6.29281376e-02f, -4.27374053e-01f, 6.19212543e-01f, + -3.04508915e-01f, 5.67611487e-01f, 3.72333533e-02f, -8.19167317e-02f, 1.25205729e-36f, 2.11515287e-35f, + -8.85884025e-35f, 8.22100105e-35f, -1.41290744e-37f, 7.53591749e-35f, 7.71793061e-36f, -2.75340121e-35f, + 7.13117824e-36f, 1.24992691e-02f, -1.37487792e-02f, -1.48109290e-01f, 4.34345843e-01f, -2.45986100e-01f, + -1.51757946e-01f, -2.25487254e-01f, -3.78407442e-02f, 1.92801335e-01f, -7.83071154e-02f, 7.97894137e-03f, + + 4.02519645e-01f, -2.43653315e-01f, 5.60402600e-01f, -2.23348868e-01f, 1.62046875e-01f, -4.06590330e-01f, + 4.46001368e-01f, -3.72707796e-01f, -1.41177231e-02f, -4.31995198e-02f, 2.93387896e-01f, -4.25083048e-01f, + 2.09042241e-01f, -3.89659453e-01f, -2.55603144e-02f, 5.62349945e-02f, -4.68822967e-03f, -7.92002290e-02f, + 3.31712278e-01f, -3.07828893e-01f, 5.29052032e-04f, -2.82176480e-01f, -2.88991817e-02f, 1.03098934e-01f, + -2.67021338e-02f, 7.24339502e-03f, -7.96749298e-03f, -8.58301461e-02f, 2.51705799e-01f, -1.42550295e-01f, + -8.79445626e-02f, -1.30671101e-01f, -2.19289189e-02f, 1.11729432e-01f, -4.53794030e-02f, 4.62384030e-03f, + + 1.95445306e+00f, -8.56593659e-01f, 1.97016533e+00f, -7.85210840e-01f, 2.31033385e-01f, -5.79683751e-01f, + 6.35872835e-01f, -5.31376762e-01f, -2.01279127e-02f, 2.11104646e-02f, -1.43370917e-01f, 2.07726860e-01f, + -1.02153423e-01f, 1.90416285e-01f, 1.24906507e-02f, -2.74805568e-02f, 6.33162467e-03f, 1.06962790e-01f, + -4.47989495e-01f, 4.15734115e-01f, -7.14504011e-04f, 3.81089599e-01f, 3.90293960e-02f, -1.39238860e-01f, + 3.60622028e-02f, -4.47359268e-03f, 4.92080277e-03f, 5.30095505e-02f, -1.55456001e-01f, 8.80404774e-02f, + 5.43154350e-02f, 8.07037695e-02f, 1.35435180e-02f, -6.90052063e-02f, 2.80267699e-02f, -2.85572968e-03f, + /* Green colour. */ + 4.60837984e+00f, -1.49460245e+00f, 3.43758549e+00f, -1.37005222e+00f, 4.97449134e-35f, -1.24814507e-34f, + 1.36912850e-34f, -1.14413296e-34f, -4.33383805e-36f, 9.62430278e-02f, -6.53630863e-01f, 9.47030887e-01f, + -4.65719486e-01f, 8.68111630e-01f, 5.69451249e-02f, -1.25284405e-01f, 1.91491103e-36f, 3.23493947e-35f, + -1.35488136e-34f, 1.25732949e-34f, -2.16091711e-37f, 1.15255201e-34f, 1.18038931e-35f, -4.21108392e-35f, + 1.09065072e-35f, 1.91165280e-02f, -2.10275433e-02f, -2.26520076e-01f, 6.64293599e-01f, -3.76214011e-01f, + -2.32100374e-01f, -3.44862837e-01f, -5.78740756e-02f, 2.94872611e-01f, -1.19763816e-01f, 1.22030860e-02f, + + 6.15618240e-01f, -3.72646222e-01f, 8.57086273e-01f, -3.41592364e-01f, 2.47836381e-01f, -6.21843994e-01f, + 6.82119695e-01f, -5.70023651e-01f, -2.15918104e-02f, -6.60698496e-02f, 4.48710870e-01f, -6.50126972e-01f, + 3.19711642e-01f, -5.95949713e-01f, -3.90922430e-02f, 8.60064566e-02f, -7.17023314e-03f, -1.21129754e-01f, + 5.07324627e-01f, -4.70797100e-01f, 8.09138350e-04f, -4.31564000e-01f, -4.41987457e-02f, 1.57680712e-01f, + -4.08385549e-02f, 1.10781328e-02f, -1.21855767e-02f, -1.31269627e-01f, 3.84961785e-01f, -2.18018084e-01f, + -1.34503440e-01f, -1.99849906e-01f, -3.35383443e-02f, 1.70880296e-01f, -6.94037884e-02f, 7.07175529e-03f, + + 2.98916331e+00f, -1.31008433e+00f, 3.01319384e+00f, -1.20091062e+00f, 3.53345154e-01f, -8.86575090e-01f, + 9.72511332e-01f, -8.12693818e-01f, -3.07838645e-02f, 3.22865908e-02f, -2.19273153e-01f, 3.17699883e-01f, + -1.56234637e-01f, 2.91224888e-01f, 1.91033469e-02f, -4.20290842e-02f, 9.68366064e-03f, 1.63590138e-01f, + -6.85160360e-01f, 6.35828606e-01f, -1.09277077e-03f, 5.82842878e-01f, 5.96920135e-02f, -2.12953537e-01f, + 5.51539537e-02f, -6.84196484e-03f, 7.52593316e-03f, 8.10734249e-02f, -2.37756221e-01f, 1.34650133e-01f, + 8.30706600e-02f, 1.23429287e-01f, 2.07136145e-02f, -1.05537368e-01f, 4.28644688e-02f, -4.36758628e-03f, + /* Blue colour. */ + 6.20358848e+00f, -2.01196491e+00f, 4.62751910e+00f, -1.84430114e+00f, 6.69643089e-35f, -1.68019534e-34f, + 1.84305766e-34f, -1.54017904e-34f, -5.83401297e-36f, 1.29557927e-01f, -8.79887732e-01f, 1.27484932e+00f, + -6.26930101e-01f, 1.16861185e+00f, 7.66569017e-02f, -1.68652090e-01f, 2.57776494e-36f, 4.35472637e-35f, + -1.82387882e-34f, 1.69255899e-34f, -2.90892699e-37f, 1.55151238e-34f, 1.58898567e-35f, -5.66876703e-35f, + 1.46818371e-35f, 2.57337886e-02f, -2.83063093e-02f, -3.04930882e-01f, 8.94241416e-01f, -5.06441957e-01f, + -3.12442822e-01f, -4.64238452e-01f, -7.79074123e-02f, 3.96943914e-01f, -1.61220527e-01f, 1.64272318e-02f, + + 8.28716892e-01f, -5.01639163e-01f, 1.15377003e+00f, -4.59835891e-01f, 3.33625909e-01f, -8.37097715e-01f, + 9.18238085e-01f, -7.67339558e-01f, -2.90658997e-02f, -8.89401854e-02f, 6.04033886e-01f, -8.75170956e-01f, + 4.30381072e-01f, -8.02240028e-01f, -5.26241753e-02f, 1.15777927e-01f, -9.65223728e-03f, -1.63059290e-01f, + 6.82937023e-01f, -6.33765350e-01f, 1.08922474e-03f, -5.80951560e-01f, -5.94983136e-02f, 2.12262505e-01f, + -5.49749798e-02f, 1.49128717e-02f, -1.64036616e-02f, -1.76709119e-01f, 5.18217807e-01f, -2.93485893e-01f, + -1.81062330e-01f, -2.69028730e-01f, -4.51477729e-02f, 2.30031176e-01f, -9.34281801e-02f, 9.51967094e-03f, + + 4.02387383e+00f, -1.76357513e+00f, 4.05622263e+00f, -1.61661051e+00f, 4.75656955e-01f, -1.19346651e+00f, + 1.30914992e+00f, -1.09401095e+00f, -4.14398191e-02f, 4.34627200e-02f, -2.95175409e-01f, 4.27672935e-01f, + -2.10315865e-01f, 3.92033517e-01f, 2.57160448e-02f, -5.65776154e-02f, 1.30356975e-02f, 2.20217502e-01f, + -9.22331288e-01f, 8.55923154e-01f, -1.47103763e-03f, 7.84596211e-01f, 8.03546365e-02f, -2.86668233e-01f, + 7.42457096e-02f, -9.21033762e-03f, 1.01310642e-02f, 1.09137307e-01f, -3.20056463e-01f, 1.81259801e-01f, + 1.11825893e-01f, 1.66154815e-01f, 2.78837128e-02f, -1.42069538e-01f, 5.77021717e-02f, -5.87944329e-03f, + }; + const struct + { + float *red_received, *green_received, *blue_received; + const float *red_expected, *green_expected, *blue_expected; + float radius, roffset, goffset, boffset; + } + test[] = + { + { rout, gout, bout, table, &table[108], &table[216], 17.4f, 1.01f, 1.02f, 1.03f, }, + { rout, gout, bout, &table[36], &table[144], &table[252], 1.6f, 1.01f, 1.02f, 1.03f, }, + { rout, gout, bout, &table[72], &table[180], &table[288], -3.0f, 1.01f, 1.02f, 1.03f, }, + { rout, rout, rout, &table[216], &table[216], &table[216], 17.4f, 1.03f, 1.03f, 1.03f, }, + { rout, rout, bout, &table[108], &table[108], &table[216], 17.4, 1.02f, 1.02f, 1.03f, }, + { rout, gout, gout, table, &table[216], &table[216], 17.4f, 1.01f, 1.03f, 1.03f, }, + { rout, gout, rout, &table[216], &table[108], &table[216], 17.4f, 1.03f, 1.02f, 1.03f, }, + /* D3DXSHEvalSphericalLight accepts NULL green or blue colour. */ + { rout, NULL, bout, table, NULL, &table[216], 17.4f, 1.01f, 0.0f, 1.03f, }, + { rout, gout, NULL, table, &table[108], NULL, 17.4f, 1.01f, 1.02f, 0.0f, }, + { rout, NULL, NULL, table, NULL, NULL, 17.4f, 1.01f, 0.0f, 0.0f, }, + }; + + dir.x = 1.1f; dir.y = 1.2f; dir.z = 2.76f; + + for (l = 0; l < ARRAY_SIZE(test); ++l) + { + for (order = D3DXSH_MINORDER; order <= D3DXSH_MAXORDER; order++) + { + for (j = 0; j < 49; j++) + { + test[l].red_received[j] = 1.01f + j; + if (test[l].green_received) + test[l].green_received[j] = 1.02f + j; + if (test[l].blue_received) + test[l].blue_received[j] = 1.03f + j; + } + + hr = D3DXSHEvalSphericalLight(order, &dir, test[l].radius, 1.7f, 2.6f, 3.5f, test[l].red_received, test[l].green_received, test[l].blue_received); + ok(hr == D3D_OK, "Expected %#x, got %#x\n", D3D_OK, hr); + + for (j = 0; j < 49; j++) + { + if (j >= order * order) + expected = j + test[l].roffset; + else + expected = test[l].red_expected[j]; + equal = compare_float(expected, test[l].red_received[j], 4096); + ok(equal || (fabs(expected) < 1.0e-6f && fabs(test[l].red_received[j]) < 1.0e-6f), + "Red: case %u, order %u: expected[%u] = %.8e, received %.8e.\n", + l, order, j, expected, test[l].red_received[j]); + + if (test[l].green_received) + { + if (j >= order * order) + expected = j + test[l].goffset; + else + expected = test[l].green_expected[j]; + equal = compare_float(expected, test[l].green_received[j], 4096); + ok(equal || (fabs(expected) < 1.0e-6f && fabs(test[l].green_received[j]) < 1.0e-6f), + "Green: case %u, order %u: expected[%u] = %.8e, received %.8e.\n", + l, order, j, expected, test[l].green_received[j]); + } + + if (test[l].blue_received) + { + if (j >= order * order) + expected = j + test[l].boffset; + else + expected = test[l].blue_expected[j]; + equal = compare_float(expected, test[l].blue_received[j], 4096); + ok(equal || (fabs(expected) < 1.0e-6f && fabs(test[l].blue_received[j]) < 1.0e-6f), + "Blue: case %u, order %u: expected[%u] = %.8e, received %.8e.\n", + l, order, j, expected, test[l].blue_received[j]); + } + } + } + } + + /* D3DXSHEvalSphericalLight accepts order < D3DXSH_MINORDER or order > D3DXSH_MAXORDER. But tests in native windows show that the colour outputs are not set */ + hr = D3DXSHEvalSphericalLight(7, &dir, 17.4f, 1.0f, 2.0f, 3.0f, rout, gout, bout); + ok(hr == D3D_OK, "Expected %#x, got %#x\n", D3D_OK, hr); + hr = D3DXSHEvalSphericalLight(0, &dir, 17.4f, 1.0f, 2.0f, 3.0f, rout, gout, bout); + ok(hr == D3D_OK, "Expected %#x, got %#x\n", D3D_OK, hr); + hr = D3DXSHEvalSphericalLight(1, &dir, 17.4f, 1.0f, 2.0f, 3.0f, rout, gout, bout); + ok(hr == D3D_OK, "Expected %#x, got %#x\n", D3D_OK, hr); +} + +static void test_D3DXSHMultiply2(void) +{ + float a[20], b[20], c[20]; + unsigned int i; + BOOL equal; + + /* D3DXSHMultiply2() only modifies the first 4 elements of the array. */ + static const float expected[20] = + { + 3.41859412f, 1.69821072f, 1.70385253f, 1.70949447f, 4.0f, 5.0f, 6.0f, + 7.0f, 8.0f, 9.0f, 10.0f, 11.0f, 12.0f, 13.0f, + 14.0f, 15.0f, 16.0f, 17.0f, 18.0f, 19.0f, + }; + + for (i = 0; i < ARRAY_SIZE(a); ++i) + { + a[i] = 1.0f + i / 100.0f; + b[i] = 3.0f - i / 100.0f; + c[i] = i; + } + + D3DXSHMultiply2(c, a, b); + for (i = 0; i < ARRAY_SIZE(expected); ++i) + { + equal = compare_float(c[i], expected[i], 2); + ok(equal, "Expected[%u] = %.8e, received = %.8e.\n", i, expected[i], c[i]); + } +} + +static void test_D3DXSHMultiply3(void) +{ + float a[20], b[20], c[20]; + unsigned int i; + BOOL equal; + + /* D3DXSHMultiply3() only modifies the first 9 elements of the array. */ + static const float expected[20] = + { + 7.81391382e+00f, 2.25605774e+00f, 5.94839954e+00f, 4.97089481e+00f, 2.89985824e+00f, 3.59894633e+00f, + 1.72657156e+00f, 5.57353783e+00f, 6.22063160e-01f, 9.00000000e+00f, 1.00000000e+01f, 1.10000000e+01f, + 1.20000000e+01f, 1.30000000e+01f, 1.40000000e+01f, 1.50000000e+01f, 1.60000000e+01f, 1.70000000e+01f, + 1.80000000e+01f, 1.90000000e+01f, + }; + static const float expected_aliased[20] = + { + 4.54092499e+02f, 2.12640405e+00f, 5.57040071e+00f, 1.53303785e+01f, 2.27960873e+01f, 4.36041260e+01f, + 4.27384138e+00f, 1.75772034e+02f, 2.37672729e+02f, 1.09000003e+00f, 1.10000002e+00f, 1.11000001e+00f, + 1.12000000e+00f, 1.13000000e+00f, 1.13999999e+00f, 1.14999998e+00f, 1.15999997e+00f, 1.16999996e+00f, + 1.17999995e+00f, 1.19000006e+00f, + }; + + for (i = 0; i < ARRAY_SIZE(a); ++i) + { + a[i] = 1.0f + i / 100.0f; + b[i] = 3.0f - i / 100.0f; + c[i] = i; + } + + D3DXSHMultiply3(c, a, b); + for (i = 0; i < ARRAY_SIZE(expected); ++i) + { + equal = compare_float(c[i], expected[i], 4); + ok(equal, "Expected[%u] = %.8e, received = %.8e.\n", i, expected[i], c[i]); + } + + memcpy(c, a, sizeof(c)); + D3DXSHMultiply3(c, c, b); + for (i = 0; i < ARRAY_SIZE(expected_aliased); ++i) + { + equal = compare_float(c[i], expected_aliased[i], 32); + ok(equal, "Expected[%u] = %.8e, received = %.8e.\n", i, expected_aliased[i], c[i]); + } +} + +static void test_D3DXSHMultiply4(void) +{ + float a[20], b[20], c[20]; + unsigned int i; + BOOL equal; + + /* D3DXSHMultiply4() only modifies the first 16 elements of the array. */ + static const float expected[] = + { + /* c, a, b */ + 1.41825991e+01f, 2.61570334e+00f, 1.28286009e+01f, 9.82059574e+00f, 3.03969646e+00f, 4.53044176e+00f, + 5.82058382e+00f, 1.22498465e+01f, 2.19434643e+00f, 3.90015244e+00f, 5.41660881e+00f, 5.60181284e+00f, + 9.59981740e-01f, 7.03754997e+00f, 3.62523031e+00f, 4.63601470e-01f, 1.60000000e+01f, 1.70000000e+01f, + 1.80000000e+01f, 1.90000000e+01f, + /* c, c, b */ + -2.11441266e+05f, -2.52915771e+03f, -1.00233936e+04f, -4.41277191e+02f, -1.63994385e+02f, -5.26305115e+02f, + 2.96361875e+04f, -3.93183081e+03f, -1.35771113e+04f, -3.97897388e+03f, -1.03303418e+04f, -1.37797871e+04f, + -1.66851094e+04f, -4.49813750e+04f, -7.32697422e+04f, -9.52373359e+04f, 1.60000000e+01f, 1.70000000e+01f, + 1.80000000e+01f, 1.90000000e+01f, + /* c, c, c */ + 2.36682415e-01f, -7.17648506e-01f, -1.80499524e-01f, -7.71235973e-02f, 1.44830629e-01f, 5.73285699e-01f, + -3.37959230e-01f, 5.56938872e-02f, -4.42100227e-01f, 1.47701755e-01f, -5.51566519e-02f, 8.43374059e-02f, + 1.79876596e-01f, 9.09878965e-03f, 2.32199892e-01f, 7.41420984e-02f, 1.60000002e+00f, 1.70000005e+00f, + 1.80000007e+00f, 1.89999998e+00f, + }; + + for (i = 0; i < ARRAY_SIZE(a); ++i) + { + a[i] = 1.0f + i / 100.0f; + b[i] = 3.0f - i / 100.0f; + c[i] = i; + } + + D3DXSHMultiply4(c, a, b); + for (i = 0; i < ARRAY_SIZE(c); ++i) + { + equal = compare_float(c[i], expected[i], 16); + ok(equal, "Expected[%u] = %.8e, received = %.8e.\n", i, expected[i], c[i]); + } + + for (i = 0; i < ARRAY_SIZE(b); ++i) + { + b[i] = 3.0f - i / 100.0f; + c[i] = i; + } + + D3DXSHMultiply4(c, c, b); + for (i = 0; i < ARRAY_SIZE(c); ++i) + { + equal = compare_float(c[i], expected[20 + i], 32); + ok(equal, "Expected[%u] = %.8e, received = %.8e.\n", i, expected[20 + i], c[i]); + } + + for (i = 0; i < ARRAY_SIZE(c); ++i) + c[i] = 0.1f * i; + + D3DXSHMultiply4(c, c, c); + for (i = 0; i < ARRAY_SIZE(c); ++i) + { + equal = compare_float(c[i], expected[40 + i], 8); + ok(equal, "Expected[%u] = %.8e, received = %.8e.\n", i, expected[40 + i], c[i]); + } +} + +static void test_D3DXSHRotate(void) +{ + float expected, in[49], out[49], *out_temp, *received_ptr; + unsigned int i, j, l, order; + D3DXMATRIX m[4]; + BOOL equal; + + static const float table[]= + { + /* Rotation around the x-axis, Ï€/2. */ + 1.00999999e+00f, -3.00999999e+00f, 2.00999975e+00f, 4.01000023e+00f, -8.01000023e+00f, -6.00999928e+00f, + -1.13078899e+01f, 5.00999975e+00f, -1.56583869e+00f, 1.09359801e+00f, -1.10099983e+01f, 1.98334141e+01f, + -1.52681913e+01f, -1.90041180e+01f, -3.36488891e+00f, -9.56262684e+00f, 1.20996542e+01f, -2.72131383e-01f, + 3.02410126e+01f, 2.69199905e+01f, 3.92368774e+01f, -2.26324463e+01f, 6.70738792e+00f, -1.17682819e+01f, + 3.44367194e+00f, -6.07445812e+00f, 1.16183939e+01f, 1.52756083e+00f, 3.78963356e+01f, -5.69012184e+01f, + 4.74228935e+01f, 5.03915329e+01f, 1.06181908e+01f, 2.55010109e+01f, 4.92456071e-02f, 1.69833069e+01f, + + 1.00999999e+00f, -3.00999999e+00f, -3.01000023e+00f, 4.01000023e+00f, -8.01000023e+00f, -6.00999928e+00f, + -1.13078890e+01f, -8.01000023e+00f, 1.42979193e+01f, + /* Rotation around the x-axis, -Ï€/2. */ + 1.00999999e+00f, 3.00999999e+00f, -2.01000023e+00f, 4.01000023e+00f, 8.01000023e+00f, -6.01000118e+00f, + -1.13078880e+01f, -5.01000071e+00f, -1.56583774e+00f, -1.09359753e+00f, -1.10100021e+01f, -1.98334103e+01f, + 1.52681961e+01f, -1.90041142e+01f, 3.36489248e+00f, -9.56262398e+00f, -1.20996523e+01f, -2.72129118e-01f, + -3.02410049e+01f, 2.69200020e+01f, 3.92368736e+01f, 2.26324520e+01f, 6.70738268e+00f, 1.17682877e+01f, + 3.44367099e+00f, 6.07445717e+00f, 1.16183996e+01f, -1.52756333e+00f, 3.78963509e+01f, 5.69011993e+01f, + -4.74229126e+01f, 5.03915253e+01f, -1.06182041e+01f, 2.55009995e+01f, -4.92481887e-02f, 1.69833050e+01f, + + 1.00999999e+00f, 3.00999999e+00f, -3.01000023e+00f, 4.01000023e+00f, 8.01000023e+00f, -6.01000118e+00f, + -1.13078899e+01f, -8.01000023e+00f, 1.42979193e+01f, + /* Yaw Ï€/3, pitch Ï€/4, roll Ï€/5. */ + 1.00999999e+00f, 4.94489908e+00f, 1.44230127e+00f, 1.62728095e+00f, 2.19220325e-01f, 1.05408239e+01f, + -9.13690281e+00f, 2.76374960e+00f, -7.30904531e+00f, -5.87572050e+00f, 5.30312395e+00f, -8.68215370e+00f, + -2.56833839e+01f, 1.68027866e+00f, -1.88083878e+01f, 7.65365601e+00f, 1.69391327e+01f, -1.73280182e+01f, + 1.46297951e+01f, -5.44671021e+01f, -1.22310352e+01f, -4.08985710e+00f, -9.44422245e+00f, 3.05603528e+00f, + 1.79257303e-01f, -1.00418749e+01f, 2.30900917e+01f, -2.31887093e+01f, 1.17270985e+01f, -6.51830902e+01f, + 4.86715775e+01f, -1.50732088e+01f, 3.87931709e+01f, -2.60395355e+01f, 6.19276857e+00f, -1.76722469e+01f, + + 1.00999999e+00f, 4.94489908e+00f, -8.91142070e-01f, 4.60769463e+00f, 2.19218358e-01f, 1.07733250e+01f, + -8.20476913e+00f, 1.35638294e+01f, -1.20077667e+01f, + /* Rotation around the z-axis, Ï€/6. */ + 1.00999999e+00f, 3.74571109e+00f, 3.00999999e+00f, 2.46776199e+00f, 1.03078890e+01f, 9.20981312e+00f, + 7.01000023e+00f, 3.93186355e+00f, 1.66212186e-01f, 1.60099983e+01f, 1.85040417e+01f, 1.74059658e+01f, + 1.30100002e+01f, 6.12801647e+00f, -2.02994061e+00f, -1.00100012e+01f, 1.31542921e+01f, 2.40099964e+01f, + 2.94322453e+01f, 2.83341675e+01f, 2.10100021e+01f, 9.05622101e+00f, -4.95814323e+00f, -1.80100002e+01f, + -2.72360935e+01f, -4.52033186e+00f, 1.68145428e+01f, 3.40099945e+01f, 4.30924950e+01f, 4.19944229e+01f, + 3.10100002e+01f, 1.27164707e+01f, -8.61839962e+00f, -2.80100021e+01f, -4.08963470e+01f, -4.41905708e+01f, + + 1.00999999e+00f, 3.74571109e+00f, 3.00999999e+00f, 1.59990644e+00f, 1.03078890e+01f, 9.20981312e+00f, + 7.01000023e+00f, 2.33195710e+00f, -4.42189360e+00f, + }; + + D3DXMatrixRotationX(&m[0], -D3DX_PI / 2.0f); + D3DXMatrixRotationX(&m[1], D3DX_PI / 2.0f); + D3DXMatrixRotationYawPitchRoll(&m[2], D3DX_PI / 3.0f, D3DX_PI / 4.0f, D3DX_PI / 5.0f); + D3DXMatrixRotationZ(&m[3], D3DX_PI / 6.0f); + + for (l = 0; l < 2; l++) + { + if (l == 0) + out_temp = out; + else + out_temp = in; + + for (j = 0; j < ARRAY_SIZE(m); ++j) + { + for (order = 0; order <= D3DXSH_MAXORDER; order++) + { + for (i = 0; i < ARRAY_SIZE(out); ++i) + { + out[i] = ( i + 1.0f ) * ( i + 1.0f ); + in[i] = i + 1.01f; + } + + received_ptr = D3DXSHRotate(out_temp, order, &m[j], in); + ok(received_ptr == out_temp, "Order %u, expected %p, received %p.\n", + order, out, received_ptr); + + for (i = 0; i < ARRAY_SIZE(out); ++i) + { + if ((i > 0) && ((i >= order * order) || (order > D3DXSH_MAXORDER))) + { + if (l == 0) + expected = ( i + 1.0f ) * ( i + 1.0f ); + else + expected = i + 1.01f; + } + else if ((l == 0) || (order > 3)) + expected = table[45 * j + i]; + else + expected = table[45 * j + 36 +i]; + equal = compare_float(out_temp[i], expected, 4096); + ok(equal, "Order %u index %u, expected %.8e, received %.8e.\n", + order, i, expected, out_temp[i]); + } + } + } + } +} + +static void test_D3DXSHRotateZ(void) +{ + float expected, in[49], out[49], *out_temp, *received_ptr; + unsigned int end, i, j, l, order, square; + BOOL equal; + + static const float angle[] = {D3DX_PI / 3.0f, -D3DX_PI / 3.0f, 4.0f * D3DX_PI / 3.0f}; + static const float table[] = + { + /* Angle Ï€/3. */ + 1.00999999e+00f, 4.47776222e+00f, 3.00999999e+00f, 2.64288902e-01f, 5.29788828e+00f, 9.94186401e+00f, + 7.01000023e+00f, -1.19981313e+00f, -8.84378910e+00f, -1.00100021e+01f, 7.49403954e+00f, 1.81380157e+01f, + 1.30100002e+01f, -3.39596605e+00f, -1.70399418e+01f, -1.60099983e+01f, -3.01642971e+01f, -1.80100040e+01f, + 1.04222422e+01f, 2.90662193e+01f, 2.10100002e+01f, -6.32417059e+00f, -2.79681454e+01f, -2.40099983e+01f, + 2.22609901e+00f, -1.81805649e+01f, -4.38245506e+01f, -2.80100040e+01f, 1.40824928e+01f, 4.27264709e+01f, + 3.10100002e+01f, -9.98442554e+00f, -4.16283989e+01f, -3.40099945e+01f, 5.88635778e+00f, 4.05303307e+01f, + + 1.00999999e+00f, 4.47776222e+00f, 0.00000000e+00f, -5.81678391e+00f, 5.29788828e+00f, 6.93686390e+00f, + 0.00000000e+00f, -9.01125050e+00f, -2.29405236e+00f, -1.00100021e+01f, 1.29990416e+01f, 1.21330166e+01f, + 0.00000000e+00f, -1.57612505e+01f, -5.62874842e+00f, 0.00000000e+00f, -3.01642971e+01f, -3.29017075e-06f, + 1.99272442e+01f, 1.90612202e+01f, 0.00000000e+00f, -2.47612514e+01f, -8.62874794e+00f, 0.00000000e+00f, + -1.30615301e+01f, -1.81805649e+01f, -3.03195534e+01f, -4.66050415e-06f, 2.85874958e+01f, 2.77214737e+01f, + 0.00000000e+00f, -3.60112534e+01f, -1.23787460e+01f, 0.00000000e+00f, -1.31287584e+01f, -2.36172504e+01f, + + 1.00999999e+00f, 3.97776222e+00f, 3.97776222e+00f, 1.11419535e+00f, 7.24579096e+00f, 1.05597591e+01f, + 1.05597591e+01f, -9.95159924e-01f, -4.67341393e-01f, 4.67339337e-01f, 1.27653713e+01f, 1.85157013e+01f, + 1.85157013e+01f, -1.79728663e+00f, 4.93915796e-01f, -4.93915856e-01f, -2.14123421e+01f, 2.14123383e+01f, + 9.22107220e+00f, 2.36717567e+01f, 2.36717567e+01f, 3.85019469e+00f, -2.04687271e+01f, 2.04687233e+01f, + -1.06621027e+01f, -3.65166283e+01f, -1.20612450e+01f, 1.20612402e+01f, 2.25568752e+01f, 3.89999084e+01f, + 3.89999084e+01f, -3.48751247e-02f, -1.04279022e+01f, 1.04279003e+01f, -3.68382835e+01f, -2.76528034e+01f, + /* Angle -Ï€/3. */ + 1.00999999e+00f, -2.46776247e+00f, 3.00999999e+00f, 3.74571109e+00f, -1.03078899e+01f, -3.93186426e+00f, + 7.01000023e+00f, 9.20981312e+00f, -1.66213632e-01f, -1.00099983e+01f, -1.85040436e+01f, -6.12801695e+00f, + 1.30100002e+01f, 1.74059658e+01f, 2.02993774e+00f, -1.60100021e+01f, 1.31543026e+01f, -1.80099964e+01f, + -2.94322472e+01f, -9.05622101e+00f, 2.10100002e+01f, 2.83341694e+01f, 4.95813942e+00f, -2.40100021e+01f, + -2.72360916e+01f, 4.41905823e+01f, 1.68145580e+01f, -2.80099964e+01f, -4.30924988e+01f, -1.27164736e+01f, + 3.10100002e+01f, 4.19944229e+01f, 8.61839294e+00f, -3.40100021e+01f, -4.08963470e+01f, -4.52030993e+00f, + + 1.00999999e+00f, -2.46776247e+00f, 0.00000000e+00f, -3.20571756e+00f, -1.03078899e+01f, -6.93686390e+00f, + 0.00000000e+00f, -9.01125050e+00f, -4.46344614e+00f, -1.00099983e+01f, -1.29990416e+01f, -1.21330166e+01f, + 0.00000000e+00f, -1.57612505e+01f, -5.62874842e+00f, 0.00000000e+00f, 1.31543026e+01f, 3.29017075e-06f, + -1.99272442e+01f, -1.90612202e+01f, 0.00000000e+00f, -2.47612514e+01f, -8.62874794e+00f, 0.00000000e+00f, + -5.69598293e+00f, 4.41905823e+01f, 3.03195534e+01f, 4.66050415e-06f, -2.85874958e+01f, -2.77214737e+01f, + 0.00000000e+00f, -3.60112534e+01f, -1.23787460e+01f, 0.00000000e+00f, -1.31287584e+01f, -5.74052582e+01f, + + 1.00999999e+00f, -2.96776223e+00f, -2.96776223e+00f, -6.09195352e-01f, -7.49829102e+00f, -1.06860094e+01f, + -1.06860094e+01f, -1.18367157e+01f, 5.39078045e+00f, -5.39077854e+00f, -1.03036509e+01f, -1.72848415e+01f, + -1.72848415e+01f, -1.75656433e+01f, 4.11427259e+00f, -4.11427307e+00f, 2.37164364e+01f, -2.37164326e+01f, + -8.06902504e+00f, -2.30957317e+01f, -2.30957317e+01f, -1.85358467e+01f, -1.12711067e+01f, 1.12711039e+01f, + -2.07248449e+00f, 3.01493301e+01f, 1.52448931e+01f, -1.52448883e+01f, -2.09650497e+01f, -3.82039986e+01f, + -3.82039986e+01f, -3.72582664e+01f, 5.42667723e+00f, -5.42667913e+00f, -2.33967514e+01f, -9.90355873e+00f, + /* Angle 4Ï€/3. */ + 1.00999999e+00f, -4.47776222e+00f, 3.00999999e+00f, -2.64288664e-01f, 5.29788685e+00f, -9.94186401e+00f, + 7.01000023e+00f, 1.19981360e+00f, -8.84378815e+00f, 1.00100040e+01f, 7.49403811e+00f, -1.81380157e+01f, + 1.30100002e+01f, 3.39596677e+00f, -1.70399399e+01f, 1.60099964e+01f, -3.01642933e+01f, 1.80100060e+01f, + 1.04222393e+01f, -2.90662193e+01f, 2.10100002e+01f, 6.32417202e+00f, -2.79681435e+01f, 2.40099926e+01f, + 2.22610497e+00f, 1.81805515e+01f, -4.38245430e+01f, 2.80100079e+01f, 1.40824890e+01f, -4.27264709e+01f, + 3.10100002e+01f, 9.98442745e+00f, -4.16283989e+01f, 3.40099869e+01f, 5.88636589e+00f, -4.05303268e+01f, + + 1.00999999e+00f, -4.47776222e+00f, 0.00000000e+00f, -1.93892837e+00f, 5.29788685e+00f, -6.93686390e+00f, + 0.00000000e+00f, -3.00375080e+00f, -2.29405141e+00f, 1.00100040e+01f, 1.29990396e+01f, -1.21330166e+01f, + 0.00000000e+00f, -5.25375128e+00f, -5.62874699e+00f, -5.68378528e-06f, -3.01642933e+01f, 7.00829787e-06f, + 1.99272423e+01f, -1.90612202e+01f, 0.00000000e+00f, -8.25375271e+00f, -8.62874603e+00f, -4.09131496e-12f, + -1.30615349e+01f, 1.81805515e+01f, -3.03195534e+01f, 9.92720470e-06f, 2.85874920e+01f, -2.77214737e+01f, + 0.00000000e+00f, -1.20037527e+01f, -1.23787422e+01f, -5.79531909e-12f, -1.31287651e+01f, -7.87240028e+00f, + + 1.00999999e+00f, -3.97776222e+00f, -3.97776222e+00f, 2.86356640e+00f, 6.37110424e+00f, -1.01224155e+01f, + -1.01224155e+01f, 1.05787458e+01f, -7.76929522e+00f, -7.76928997e+00f, 1.68836861e+01f, -2.05748577e+01f, + -2.05748577e+01f, 2.49091301e+01f, -5.72616625e+00f, -5.72616386e+00f, -1.87962208e+01f, -1.87962112e+01f, + 2.93253498e+01f, -3.37238922e+01f, -3.37238922e+01f, 4.22584419e+01f, -4.85123205e+00f, -4.85122633e+00f, + -2.53339314e+00f, 3.24522591e+01f, -4.65456696e+01f, -4.65456543e+01f, 5.18603249e+01f, -5.36516304e+01f, + -5.36516304e+01f, 7.17381744e+01f, 4.44061565e+00f, 4.44062901e+00f, 2.58841743e+01f, -1.07481155e+01f, + }; + + for (l = 0; l < 3; l++) + { + if (l == 0) + out_temp = out; + else + out_temp = &in[l - 1]; + + if (l < 2) + end = 49; + else + end = 48; + + for (j = 0; j < ARRAY_SIZE(angle); ++j) + { + for (order = 0; order <= D3DXSH_MAXORDER + 1; order++) + { + for (i = 0; i < ARRAY_SIZE(out); ++i) + { + out[i] = ( i + 1.0f ) * ( i + 1.0f ); + in[i] = i + 1.01f; + } + + received_ptr = D3DXSHRotateZ(out_temp, order, angle[j], in); + ok(received_ptr == out_temp, "angle %f, order %u, expected %p, received %p\n", angle[j], order, out_temp, received_ptr); + + for (i = 0; i < end; i++) + { + /* order = 0 or order = 1 behaves like order = D3DXSH_MINORDER */ + square = (order <= D3DXSH_MINORDER) ? D3DXSH_MINORDER * D3DXSH_MINORDER : order * order; + if (i >= square || ((order >= D3DXSH_MAXORDER) && (i >= D3DXSH_MAXORDER * D3DXSH_MAXORDER))) + if (l > 0) + expected = i + l + 0.01f; + else + expected = ( i + 1.0f ) * ( i + 1.0f ); + else + expected = table[36 * (l + 3 * j) + i]; + equal = compare_float(expected, out_temp[i], 256); + ok(equal || (fabs(expected) < 2.0e-5f && fabs(out_temp[i]) < 2.0e-5f), + "angle %.8e, order %u index %u, expected %.8e, received %.8e.\n", + angle[j], order, i, expected, out_temp[i]); + } + } + } + } +} + +static void test_D3DXSHScale(void) +{ + float a[49], b[49], expected, *received_array; + unsigned int i, order; + BOOL equal; + + for (i = 0; i < ARRAY_SIZE(a); ++i) + { + a[i] = i; + b[i] = i; + } + + for (order = 0; order <= D3DXSH_MAXORDER + 1; order++) + { + received_array = D3DXSHScale(b, order, a, 5.0f); + ok(received_array == b, "Expected %p, received %p\n", b, received_array); + + for (i = 0; i < ARRAY_SIZE(b); ++i) + { + if (i < order * order) + expected = 5.0f * a[i]; + /* D3DXSHScale does not modify the elements of the array after the order * order-th element */ + else + expected = a[i]; + equal = compare_float(b[i], expected, 0); + ok(equal, "order %u, element %u, expected %.8e, received %.8e.\n", order, i, expected, b[i]); + } + } +} + +START_TEST(math) +{ + D3DXColorTest(); + D3DXFresnelTest(); + D3DXMatrixTest(); + D3DXPlaneTest(); + D3DXQuaternionTest(); + D3DXVector2Test(); + D3DXVector3Test(); + D3DXVector4Test(); + test_matrix_stack(); + test_Matrix_AffineTransformation2D(); + test_Matrix_Decompose(); + test_Matrix_Transformation2D(); + test_D3DXVec_Array(); + test_D3DXFloat_Array(); + test_D3DXSHAdd(); + test_D3DXSHDot(); + test_D3DXSHEvalConeLight(); + test_D3DXSHEvalDirection(); + test_D3DXSHEvalDirectionalLight(); + test_D3DXSHEvalHemisphereLight(); + test_D3DXSHEvalSphericalLight(); + test_D3DXSHMultiply2(); + test_D3DXSHMultiply3(); + test_D3DXSHMultiply4(); + test_D3DXSHRotate(); + test_D3DXSHRotateZ(); + test_D3DXSHScale(); +} diff --git a/modules/rostests/winetests/d3dx9_36/mesh.c b/modules/rostests/winetests/d3dx9_36/mesh.c new file mode 100644 index 00000000000..1b0f86ef170 --- /dev/null +++ b/modules/rostests/winetests/d3dx9_36/mesh.c @@ -0,0 +1,11256 @@ +/* + * Copyright 2008 David Adam + * Copyright 2008 Luis Busquets + * Copyright 2009 Henri Verbeet for CodeWeavers + * Copyright 2011 Michael Mc Donnell + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA + */ + +#define COBJMACROS +#include +#include +#include +#include "wine/test.h" +#include "d3dx9.h" + +#ifndef NAN +/* From wine/port.h */ +static inline float __port_nan(void) +{ + static const unsigned __nan_bytes = 0x7fc00000; + return *(const float *)&__nan_bytes; +} +#define NAN __port_nan() +#endif + +/* Set the WINETEST_DEBUG environment variable to be greater than 1 for verbose + * function call traces of ID3DXAllocateHierarchy callbacks. */ +#define TRACECALLBACK if(winetest_debug > 1) trace + +#define admitted_error 0.0001f + +#define compare_vertex_sizes(type, exp) \ + got=D3DXGetFVFVertexSize(type); \ + ok(got==exp, "Expected: %d, Got: %d\n", exp, got); + +#define compare_float(got, exp) \ + do { \ + float _got = (got); \ + float _exp = (exp); \ + ok(_got == _exp, "Expected: %g, Got: %g\n", _exp, _got); \ + } while (0) + +static BOOL compare(FLOAT u, FLOAT v) +{ + return (fabs(u-v) < admitted_error); +} + +static BOOL compare_vec3(D3DXVECTOR3 u, D3DXVECTOR3 v) +{ + return ( compare(u.x, v.x) && compare(u.y, v.y) && compare(u.z, v.z) ); +} + +static BOOL compare_vec4(D3DXVECTOR4 u, D3DXVECTOR4 v) +{ + return compare(u.x, v.x) && compare(u.y, v.y) && compare(u.z, v.z) && compare(u.w, v.w); +} + +#define check_floats(got, exp, dim) check_floats_(__LINE__, "", got, exp, dim) +static void check_floats_(int line, const char *prefix, const float *got, const float *exp, int dim) +{ + int i; + char exp_buffer[256] = ""; + char got_buffer[256] = ""; + char *exp_buffer_ptr = exp_buffer; + char *got_buffer_ptr = got_buffer; + BOOL equal = TRUE; + + for (i = 0; i < dim; i++) { + if (i) { + exp_buffer_ptr += sprintf(exp_buffer_ptr, ", "); + got_buffer_ptr += sprintf(got_buffer_ptr, ", "); + } + equal = equal && compare(*exp, *got); + exp_buffer_ptr += sprintf(exp_buffer_ptr, "%g", *exp); + got_buffer_ptr += sprintf(got_buffer_ptr, "%g", *got); + exp++, got++; + } + ok_(__FILE__,line)(equal, "%sExpected (%s), got (%s)", prefix, exp_buffer, got_buffer); +} + +struct vertex +{ + D3DXVECTOR3 position; + D3DXVECTOR3 normal; +}; + +typedef WORD face[3]; + +static BOOL compare_face(face a, face b) +{ + return (a[0]==b[0] && a[1] == b[1] && a[2] == b[2]); +} + +struct test_context +{ + HWND hwnd; + IDirect3D9 *d3d; + IDirect3DDevice9 *device; +}; + +/* Initializes a test context struct. Use it to initialize DirectX. + * + * Returns NULL if an error occurred. + */ +static struct test_context *new_test_context(void) +{ + HRESULT hr; + HWND hwnd = NULL; + IDirect3D9 *d3d = NULL; + IDirect3DDevice9 *device = NULL; + D3DPRESENT_PARAMETERS d3dpp = {0}; + struct test_context *test_context; + + if (!(hwnd = CreateWindowA("static", "d3dx9_test", WS_OVERLAPPEDWINDOW, 0, 0, + 640, 480, NULL, NULL, NULL, NULL))) + { + skip("Couldn't create application window\n"); + goto error; + } + + d3d = Direct3DCreate9(D3D_SDK_VERSION); + if (!d3d) + { + skip("Couldn't create IDirect3D9 object\n"); + goto error; + } + + memset(&d3dpp, 0, sizeof(d3dpp)); + d3dpp.Windowed = TRUE; + d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD; + hr = IDirect3D9_CreateDevice(d3d, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, hwnd, + D3DCREATE_SOFTWARE_VERTEXPROCESSING, &d3dpp, &device); + if (FAILED(hr)) + { + skip("Couldn't create IDirect3DDevice9 object %#x\n", hr); + goto error; + } + + test_context = HeapAlloc(GetProcessHeap(), 0, sizeof(*test_context)); + if (!test_context) + { + skip("Couldn't allocate memory for test_context\n"); + goto error; + } + test_context->hwnd = hwnd; + test_context->d3d = d3d; + test_context->device = device; + + return test_context; + +error: + if (device) + IDirect3DDevice9_Release(device); + + if (d3d) + IDirect3D9_Release(d3d); + + if (hwnd) + DestroyWindow(hwnd); + + return NULL; +} + +static void free_test_context(struct test_context *test_context) +{ + if (!test_context) + return; + + if (test_context->device) + IDirect3DDevice9_Release(test_context->device); + + if (test_context->d3d) + IDirect3D9_Release(test_context->d3d); + + if (test_context->hwnd) + DestroyWindow(test_context->hwnd); + + HeapFree(GetProcessHeap(), 0, test_context); +} + +struct mesh +{ + DWORD number_of_vertices; + struct vertex *vertices; + + DWORD number_of_faces; + face *faces; + + DWORD fvf; + UINT vertex_size; +}; + +static void free_mesh(struct mesh *mesh) +{ + HeapFree(GetProcessHeap(), 0, mesh->faces); + HeapFree(GetProcessHeap(), 0, mesh->vertices); +} + +static BOOL new_mesh(struct mesh *mesh, DWORD number_of_vertices, DWORD number_of_faces) +{ + mesh->vertices = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, number_of_vertices * sizeof(*mesh->vertices)); + if (!mesh->vertices) + { + return FALSE; + } + mesh->number_of_vertices = number_of_vertices; + + mesh->faces = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, number_of_faces * sizeof(*mesh->faces)); + if (!mesh->faces) + { + HeapFree(GetProcessHeap(), 0, mesh->vertices); + return FALSE; + } + mesh->number_of_faces = number_of_faces; + + return TRUE; +} + +static void compare_mesh(const char *name, ID3DXMesh *d3dxmesh, struct mesh *mesh) +{ + HRESULT hr; + DWORD number_of_vertices, number_of_faces; + IDirect3DVertexBuffer9 *vertex_buffer; + IDirect3DIndexBuffer9 *index_buffer; + D3DVERTEXBUFFER_DESC vertex_buffer_description; + D3DINDEXBUFFER_DESC index_buffer_description; + struct vertex *vertices; + face *faces; + int expected, i; + + number_of_vertices = d3dxmesh->lpVtbl->GetNumVertices(d3dxmesh); + ok(number_of_vertices == mesh->number_of_vertices, "Test %s, result %u, expected %d\n", + name, number_of_vertices, mesh->number_of_vertices); + + number_of_faces = d3dxmesh->lpVtbl->GetNumFaces(d3dxmesh); + ok(number_of_faces == mesh->number_of_faces, "Test %s, result %u, expected %d\n", + name, number_of_faces, mesh->number_of_faces); + + /* vertex buffer */ + hr = d3dxmesh->lpVtbl->GetVertexBuffer(d3dxmesh, &vertex_buffer); + ok(hr == D3D_OK, "Test %s, result %x, expected 0 (D3D_OK)\n", name, hr); + + if (hr != D3D_OK) + { + skip("Couldn't get vertex buffer\n"); + } + else + { + hr = IDirect3DVertexBuffer9_GetDesc(vertex_buffer, &vertex_buffer_description); + ok(hr == D3D_OK, "Test %s, result %x, expected 0 (D3D_OK)\n", name, hr); + + if (hr != D3D_OK) + { + skip("Couldn't get vertex buffer description\n"); + } + else + { + ok(vertex_buffer_description.Format == D3DFMT_VERTEXDATA, "Test %s, result %x, expected %x (D3DFMT_VERTEXDATA)\n", + name, vertex_buffer_description.Format, D3DFMT_VERTEXDATA); + ok(vertex_buffer_description.Type == D3DRTYPE_VERTEXBUFFER, "Test %s, result %x, expected %x (D3DRTYPE_VERTEXBUFFER)\n", + name, vertex_buffer_description.Type, D3DRTYPE_VERTEXBUFFER); + ok(vertex_buffer_description.Usage == 0, "Test %s, result %x, expected %x\n", name, vertex_buffer_description.Usage, 0); + ok(vertex_buffer_description.Pool == D3DPOOL_MANAGED, "Test %s, result %x, expected %x (D3DPOOL_MANAGED)\n", + name, vertex_buffer_description.Pool, D3DPOOL_MANAGED); + ok(vertex_buffer_description.FVF == mesh->fvf, "Test %s, result %x, expected %x\n", + name, vertex_buffer_description.FVF, mesh->fvf); + if (mesh->fvf == 0) + { + expected = number_of_vertices * mesh->vertex_size; + } + else + { + expected = number_of_vertices * D3DXGetFVFVertexSize(mesh->fvf); + } + ok(vertex_buffer_description.Size == expected, "Test %s, result %x, expected %x\n", + name, vertex_buffer_description.Size, expected); + } + + /* specify offset and size to avoid potential overruns */ + hr = IDirect3DVertexBuffer9_Lock(vertex_buffer, 0, number_of_vertices * sizeof(D3DXVECTOR3) * 2, + (void **)&vertices, D3DLOCK_DISCARD); + ok(hr == D3D_OK, "Test %s, result %x, expected 0 (D3D_OK)\n", name, hr); + + if (hr != D3D_OK) + { + skip("Couldn't lock vertex buffer\n"); + } + else + { + for (i = 0; i < number_of_vertices; i++) + { + ok(compare_vec3(vertices[i].position, mesh->vertices[i].position), + "Test %s, vertex position %d, result (%g, %g, %g), expected (%g, %g, %g)\n", name, i, + vertices[i].position.x, vertices[i].position.y, vertices[i].position.z, + mesh->vertices[i].position.x, mesh->vertices[i].position.y, mesh->vertices[i].position.z); + ok(compare_vec3(vertices[i].normal, mesh->vertices[i].normal), + "Test %s, vertex normal %d, result (%g, %g, %g), expected (%g, %g, %g)\n", name, i, + vertices[i].normal.x, vertices[i].normal.y, vertices[i].normal.z, + mesh->vertices[i].normal.x, mesh->vertices[i].normal.y, mesh->vertices[i].normal.z); + } + + IDirect3DVertexBuffer9_Unlock(vertex_buffer); + } + + IDirect3DVertexBuffer9_Release(vertex_buffer); + } + + /* index buffer */ + hr = d3dxmesh->lpVtbl->GetIndexBuffer(d3dxmesh, &index_buffer); + ok(hr == D3D_OK, "Test %s, result %x, expected 0 (D3D_OK)\n", name, hr); + + if (!index_buffer) + { + skip("Couldn't get index buffer\n"); + } + else + { + hr = IDirect3DIndexBuffer9_GetDesc(index_buffer, &index_buffer_description); + ok(hr == D3D_OK, "Test %s, result %x, expected 0 (D3D_OK)\n", name, hr); + + if (hr != D3D_OK) + { + skip("Couldn't get index buffer description\n"); + } + else + { + ok(index_buffer_description.Format == D3DFMT_INDEX16, "Test %s, result %x, expected %x (D3DFMT_INDEX16)\n", + name, index_buffer_description.Format, D3DFMT_INDEX16); + ok(index_buffer_description.Type == D3DRTYPE_INDEXBUFFER, "Test %s, result %x, expected %x (D3DRTYPE_INDEXBUFFER)\n", + name, index_buffer_description.Type, D3DRTYPE_INDEXBUFFER); + ok(index_buffer_description.Usage == 0, "Test %s, result %#x, expected %#x.\n", + name, index_buffer_description.Usage, 0); + ok(index_buffer_description.Pool == D3DPOOL_MANAGED, "Test %s, result %x, expected %x (D3DPOOL_MANAGED)\n", + name, index_buffer_description.Pool, D3DPOOL_MANAGED); + expected = number_of_faces * sizeof(WORD) * 3; + ok(index_buffer_description.Size == expected, "Test %s, result %x, expected %x\n", + name, index_buffer_description.Size, expected); + } + + /* specify offset and size to avoid potential overruns */ + hr = IDirect3DIndexBuffer9_Lock(index_buffer, 0, number_of_faces * sizeof(WORD) * 3, + (void **)&faces, D3DLOCK_DISCARD); + ok(hr == D3D_OK, "Test %s, result %x, expected 0 (D3D_OK)\n", name, hr); + + if (hr != D3D_OK) + { + skip("Couldn't lock index buffer\n"); + } + else + { + for (i = 0; i < number_of_faces; i++) + { + ok(compare_face(faces[i], mesh->faces[i]), + "Test %s, face %d, result (%u, %u, %u), expected (%u, %u, %u)\n", name, i, + faces[i][0], faces[i][1], faces[i][2], + mesh->faces[i][0], mesh->faces[i][1], mesh->faces[i][2]); + } + + IDirect3DIndexBuffer9_Unlock(index_buffer); + } + + IDirect3DIndexBuffer9_Release(index_buffer); + } +} + +static void D3DXBoundProbeTest(void) +{ + BOOL result; + D3DXVECTOR3 bottom_point, center, top_point, raydirection, rayposition; + FLOAT radius; + +/*____________Test the Box case___________________________*/ + bottom_point.x = -3.0f; bottom_point.y = -2.0f; bottom_point.z = -1.0f; + top_point.x = 7.0f; top_point.y = 8.0f; top_point.z = 9.0f; + + raydirection.x = -4.0f; raydirection.y = -5.0f; raydirection.z = -6.0f; + rayposition.x = 5.0f; rayposition.y = 5.0f; rayposition.z = 11.0f; + result = D3DXBoxBoundProbe(&bottom_point, &top_point, &rayposition, &raydirection); + ok(result == TRUE, "expected TRUE, received FALSE\n"); + + raydirection.x = 4.0f; raydirection.y = 5.0f; raydirection.z = 6.0f; + rayposition.x = 5.0f; rayposition.y = 5.0f; rayposition.z = 11.0f; + result = D3DXBoxBoundProbe(&bottom_point, &top_point, &rayposition, &raydirection); + ok(result == FALSE, "expected FALSE, received TRUE\n"); + + rayposition.x = -4.0f; rayposition.y = 1.0f; rayposition.z = -2.0f; + result = D3DXBoxBoundProbe(&bottom_point, &top_point, &rayposition, &raydirection); + ok(result == TRUE, "expected TRUE, received FALSE\n"); + + bottom_point.x = 1.0f; bottom_point.y = 0.0f; bottom_point.z = 0.0f; + top_point.x = 1.0f; top_point.y = 0.0f; top_point.z = 0.0f; + rayposition.x = 0.0f; rayposition.y = 1.0f; rayposition.z = 0.0f; + raydirection.x = 0.0f; raydirection.y = 3.0f; raydirection.z = 0.0f; + result = D3DXBoxBoundProbe(&bottom_point, &top_point, &rayposition, &raydirection); + ok(result == FALSE, "expected FALSE, received TRUE\n"); + + bottom_point.x = 1.0f; bottom_point.y = 2.0f; bottom_point.z = 3.0f; + top_point.x = 10.0f; top_point.y = 15.0f; top_point.z = 20.0f; + + raydirection.x = 7.0f; raydirection.y = 8.0f; raydirection.z = 9.0f; + rayposition.x = 3.0f; rayposition.y = 7.0f; rayposition.z = -6.0f; + result = D3DXBoxBoundProbe(&bottom_point, &top_point, &rayposition, &raydirection); + ok(result == TRUE, "expected TRUE, received FALSE\n"); + + bottom_point.x = 0.0f; bottom_point.y = 0.0f; bottom_point.z = 0.0f; + top_point.x = 1.0f; top_point.y = 1.0f; top_point.z = 1.0f; + + raydirection.x = 0.0f; raydirection.y = 1.0f; raydirection.z = .0f; + rayposition.x = -3.0f; rayposition.y = 0.0f; rayposition.z = 0.0f; + result = D3DXBoxBoundProbe(&bottom_point, &top_point, &rayposition, &raydirection); + ok(result == FALSE, "expected FALSE, received TRUE\n"); + + raydirection.x = 1.0f; raydirection.y = 0.0f; raydirection.z = .0f; + rayposition.x = -3.0f; rayposition.y = 0.0f; rayposition.z = 0.0f; + result = D3DXBoxBoundProbe(&bottom_point, &top_point, &rayposition, &raydirection); + ok(result == TRUE, "expected TRUE, received FALSE\n"); + +/*____________Test the Sphere case________________________*/ + radius = sqrt(77.0f); + center.x = 1.0f; center.y = 2.0f; center.z = 3.0f; + raydirection.x = 2.0f; raydirection.y = -4.0f; raydirection.z = 2.0f; + + rayposition.x = 5.0f; rayposition.y = 5.0f; rayposition.z = 9.0f; + result = D3DXSphereBoundProbe(¢er, radius, &rayposition, &raydirection); + ok(result == TRUE, "expected TRUE, received FALSE\n"); + + rayposition.x = 45.0f; rayposition.y = -75.0f; rayposition.z = 49.0f; + result = D3DXSphereBoundProbe(¢er, radius, &rayposition, &raydirection); + ok(result == FALSE, "expected FALSE, received TRUE\n"); + + rayposition.x = 5.0f; rayposition.y = 11.0f; rayposition.z = 9.0f; + result = D3DXSphereBoundProbe(¢er, radius, &rayposition, &raydirection); + ok(result == FALSE, "expected FALSE, received TRUE\n"); +} + +static void D3DXComputeBoundingBoxTest(void) +{ + D3DXVECTOR3 exp_max, exp_min, got_max, got_min, vertex[5]; + HRESULT hr; + + vertex[0].x = 1.0f; vertex[0].y = 1.0f; vertex[0].z = 1.0f; + vertex[1].x = 1.0f; vertex[1].y = 1.0f; vertex[1].z = 1.0f; + vertex[2].x = 1.0f; vertex[2].y = 1.0f; vertex[2].z = 1.0f; + vertex[3].x = 1.0f; vertex[3].y = 1.0f; vertex[3].z = 1.0f; + vertex[4].x = 9.0f; vertex[4].y = 9.0f; vertex[4].z = 9.0f; + + exp_min.x = 1.0f; exp_min.y = 1.0f; exp_min.z = 1.0f; + exp_max.x = 9.0f; exp_max.y = 9.0f; exp_max.z = 9.0f; + + hr = D3DXComputeBoundingBox(&vertex[3],2,D3DXGetFVFVertexSize(D3DFVF_XYZ),&got_min,&got_max); + + ok( hr == D3D_OK, "Expected D3D_OK, got %#x\n", hr); + ok( compare_vec3(exp_min,got_min), "Expected min: (%f, %f, %f), got: (%f, %f, %f)\n", exp_min.x,exp_min.y,exp_min.z,got_min.x,got_min.y,got_min.z); + ok( compare_vec3(exp_max,got_max), "Expected max: (%f, %f, %f), got: (%f, %f, %f)\n", exp_max.x,exp_max.y,exp_max.z,got_max.x,got_max.y,got_max.z); + +/*________________________*/ + + vertex[0].x = 2.0f; vertex[0].y = 5.9f; vertex[0].z = -1.2f; + vertex[1].x = -1.87f; vertex[1].y = 7.9f; vertex[1].z = 7.4f; + vertex[2].x = 7.43f; vertex[2].y = -0.9f; vertex[2].z = 11.9f; + vertex[3].x = -6.92f; vertex[3].y = 6.3f; vertex[3].z = -3.8f; + vertex[4].x = 11.4f; vertex[4].y = -8.1f; vertex[4].z = 4.5f; + + exp_min.x = -6.92f; exp_min.y = -8.1f; exp_min.z = -3.80f; + exp_max.x = 11.4f; exp_max.y = 7.90f; exp_max.z = 11.9f; + + hr = D3DXComputeBoundingBox(&vertex[0],5,D3DXGetFVFVertexSize(D3DFVF_XYZ),&got_min,&got_max); + + ok( hr == D3D_OK, "Expected D3D_OK, got %#x\n", hr); + ok( compare_vec3(exp_min,got_min), "Expected min: (%f, %f, %f), got: (%f, %f, %f)\n", exp_min.x,exp_min.y,exp_min.z,got_min.x,got_min.y,got_min.z); + ok( compare_vec3(exp_max,got_max), "Expected max: (%f, %f, %f), got: (%f, %f, %f)\n", exp_max.x,exp_max.y,exp_max.z,got_max.x,got_max.y,got_max.z); + +/*________________________*/ + + vertex[0].x = 2.0f; vertex[0].y = 5.9f; vertex[0].z = -1.2f; + vertex[1].x = -1.87f; vertex[1].y = 7.9f; vertex[1].z = 7.4f; + vertex[2].x = 7.43f; vertex[2].y = -0.9f; vertex[2].z = 11.9f; + vertex[3].x = -6.92f; vertex[3].y = 6.3f; vertex[3].z = -3.8f; + vertex[4].x = 11.4f; vertex[4].y = -8.1f; vertex[4].z = 4.5f; + + exp_min.x = -6.92f; exp_min.y = -0.9f; exp_min.z = -3.8f; + exp_max.x = 7.43f; exp_max.y = 7.90f; exp_max.z = 11.9f; + + hr = D3DXComputeBoundingBox(&vertex[0],4,D3DXGetFVFVertexSize(D3DFVF_XYZ),&got_min,&got_max); + + ok( hr == D3D_OK, "Expected D3D_OK, got %#x\n", hr); + ok( compare_vec3(exp_min,got_min), "Expected min: (%f, %f, %f), got: (%f, %f, %f)\n", exp_min.x,exp_min.y,exp_min.z,got_min.x,got_min.y,got_min.z); + ok( compare_vec3(exp_max,got_max), "Expected max: (%f, %f, %f), got: (%f, %f, %f)\n", exp_max.x,exp_max.y,exp_max.z,got_max.x,got_max.y,got_max.z); + +/*________________________*/ + hr = D3DXComputeBoundingBox(NULL,5,D3DXGetFVFVertexSize(D3DFVF_XYZ),&got_min,&got_max); + ok( hr == D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, got %#x\n", hr); + +/*________________________*/ + hr = D3DXComputeBoundingBox(&vertex[3],5,D3DXGetFVFVertexSize(D3DFVF_XYZ),NULL,&got_max); + ok( hr == D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, got %#x\n", hr); + +/*________________________*/ + hr = D3DXComputeBoundingBox(&vertex[3],5,D3DXGetFVFVertexSize(D3DFVF_XYZ),&got_min,NULL); + ok( hr == D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, got %#x\n", hr); +} + +static void D3DXComputeBoundingSphereTest(void) +{ + D3DXVECTOR3 exp_cen, got_cen, vertex[5]; + FLOAT exp_rad, got_rad; + HRESULT hr; + + vertex[0].x = 1.0f; vertex[0].y = 1.0f; vertex[0].z = 1.0f; + vertex[1].x = 1.0f; vertex[1].y = 1.0f; vertex[1].z = 1.0f; + vertex[2].x = 1.0f; vertex[2].y = 1.0f; vertex[2].z = 1.0f; + vertex[3].x = 1.0f; vertex[3].y = 1.0f; vertex[3].z = 1.0f; + vertex[4].x = 9.0f; vertex[4].y = 9.0f; vertex[4].z = 9.0f; + + exp_rad = 6.928203f; + exp_cen.x = 5.0; exp_cen.y = 5.0; exp_cen.z = 5.0; + + hr = D3DXComputeBoundingSphere(&vertex[3],2,D3DXGetFVFVertexSize(D3DFVF_XYZ),&got_cen,&got_rad); + + ok( hr == D3D_OK, "Expected D3D_OK, got %#x\n", hr); + ok( compare(exp_rad, got_rad), "Expected radius: %f, got radius: %f\n", exp_rad, got_rad); + ok( compare_vec3(exp_cen,got_cen), "Expected center: (%f, %f, %f), got center: (%f, %f, %f)\n", exp_cen.x,exp_cen.y,exp_cen.z,got_cen.x,got_cen.y,got_cen.z); + +/*________________________*/ + + vertex[0].x = 2.0f; vertex[0].y = 5.9f; vertex[0].z = -1.2f; + vertex[1].x = -1.87f; vertex[1].y = 7.9f; vertex[1].z = 7.4f; + vertex[2].x = 7.43f; vertex[2].y = -0.9f; vertex[2].z = 11.9f; + vertex[3].x = -6.92f; vertex[3].y = 6.3f; vertex[3].z = -3.8f; + vertex[4].x = 11.4f; vertex[4].y = -8.1f; vertex[4].z = 4.5f; + + exp_rad = 13.707883f; + exp_cen.x = 2.408f; exp_cen.y = 2.22f; exp_cen.z = 3.76f; + + hr = D3DXComputeBoundingSphere(&vertex[0],5,D3DXGetFVFVertexSize(D3DFVF_XYZ),&got_cen,&got_rad); + + ok( hr == D3D_OK, "Expected D3D_OK, got %#x\n", hr); + ok( compare(exp_rad, got_rad), "Expected radius: %f, got radius: %f\n", exp_rad, got_rad); + ok( compare_vec3(exp_cen,got_cen), "Expected center: (%f, %f, %f), got center: (%f, %f, %f)\n", exp_cen.x,exp_cen.y,exp_cen.z,got_cen.x,got_cen.y,got_cen.z); + +/*________________________*/ + hr = D3DXComputeBoundingSphere(NULL,5,D3DXGetFVFVertexSize(D3DFVF_XYZ),&got_cen,&got_rad); + ok( hr == D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, got %#x\n", hr); + +/*________________________*/ + hr = D3DXComputeBoundingSphere(&vertex[3],5,D3DXGetFVFVertexSize(D3DFVF_XYZ),NULL,&got_rad); + ok( hr == D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, got %#x\n", hr); + +/*________________________*/ + hr = D3DXComputeBoundingSphere(&vertex[3],5,D3DXGetFVFVertexSize(D3DFVF_XYZ),&got_cen,NULL); + ok( hr == D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, got %#x\n", hr); +} + +static void print_elements(const D3DVERTEXELEMENT9 *elements) +{ + D3DVERTEXELEMENT9 last = D3DDECL_END(); + const D3DVERTEXELEMENT9 *ptr = elements; + int count = 0; + + while (memcmp(ptr, &last, sizeof(D3DVERTEXELEMENT9))) + { + trace( + "[Element %d] Stream = %d, Offset = %d, Type = %d, Method = %d, Usage = %d, UsageIndex = %d\n", + count, ptr->Stream, ptr->Offset, ptr->Type, ptr->Method, ptr->Usage, ptr->UsageIndex); + ptr++; + count++; + } +} + +static void compare_elements(const D3DVERTEXELEMENT9 *elements, const D3DVERTEXELEMENT9 *expected_elements, + unsigned int line, unsigned int test_id) +{ + D3DVERTEXELEMENT9 last = D3DDECL_END(); + unsigned int i; + + for (i = 0; i < MAX_FVF_DECL_SIZE; i++) + { + int end1 = memcmp(&elements[i], &last, sizeof(last)); + int end2 = memcmp(&expected_elements[i], &last, sizeof(last)); + int status; + + if (!end1 && !end2) break; + + status = !end1 ^ !end2; + ok(!status, "Line %u, test %u: Mismatch in size, test declaration is %s than expected.\n", + line, test_id, end1 ? "shorter" : "longer"); + if (status) + { + print_elements(elements); + break; + } + + status = memcmp(&elements[i], &expected_elements[i], sizeof(D3DVERTEXELEMENT9)); + ok(!status, "Line %u, test %u: Mismatch in element %u.\n", line, test_id, i); + if (status) + { + print_elements(elements); + break; + } + } +} + +static void test_fvf_to_decl(DWORD test_fvf, const D3DVERTEXELEMENT9 expected_elements[], + HRESULT expected_hr, unsigned int line, unsigned int test_id) +{ + HRESULT hr; + D3DVERTEXELEMENT9 decl[MAX_FVF_DECL_SIZE]; + + hr = D3DXDeclaratorFromFVF(test_fvf, decl); + ok(hr == expected_hr, + "Line %u, test %u: D3DXDeclaratorFromFVF returned %#x, expected %#x.\n", + line, test_id, hr, expected_hr); + if (SUCCEEDED(hr)) compare_elements(decl, expected_elements, line, test_id); +} + +static void test_decl_to_fvf(const D3DVERTEXELEMENT9 *decl, DWORD expected_fvf, + HRESULT expected_hr, unsigned int line, unsigned int test_id) +{ + HRESULT hr; + DWORD result_fvf = 0xdeadbeef; + + hr = D3DXFVFFromDeclarator(decl, &result_fvf); + ok(hr == expected_hr, + "Line %u, test %u: D3DXFVFFromDeclarator returned %#x, expected %#x.\n", + line, test_id, hr, expected_hr); + if (SUCCEEDED(hr)) + { + ok(expected_fvf == result_fvf, "Line %u, test %u: Got FVF %#x, expected %#x.\n", + line, test_id, result_fvf, expected_fvf); + } +} + +static void test_fvf_decl_conversion(void) +{ + static const struct + { + D3DVERTEXELEMENT9 decl[MAXD3DDECLLENGTH + 1]; + DWORD fvf; + } + test_data[] = + { + {{ + D3DDECL_END(), + }, 0}, + {{ + {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0}, + D3DDECL_END(), + }, D3DFVF_XYZ}, + {{ + {0, 0, D3DDECLTYPE_FLOAT4, 0, D3DDECLUSAGE_POSITIONT, 0}, + D3DDECL_END(), + }, D3DFVF_XYZRHW}, + {{ + {0, 0, D3DDECLTYPE_FLOAT4, 0, D3DDECLUSAGE_POSITIONT, 0}, + D3DDECL_END(), + }, D3DFVF_XYZRHW}, + {{ + {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0}, + {0, 12, D3DDECLTYPE_FLOAT1, 0, D3DDECLUSAGE_BLENDWEIGHT, 0}, + D3DDECL_END(), + }, D3DFVF_XYZB1}, + {{ + {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0}, + {0, 12, D3DDECLTYPE_UBYTE4, 0, D3DDECLUSAGE_BLENDINDICES, 0}, + D3DDECL_END(), + }, D3DFVF_XYZB1 | D3DFVF_LASTBETA_UBYTE4}, + {{ + {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0}, + {0, 12, D3DDECLTYPE_D3DCOLOR, 0, D3DDECLUSAGE_BLENDINDICES, 0}, + D3DDECL_END(), + }, D3DFVF_XYZB1 | D3DFVF_LASTBETA_D3DCOLOR}, + {{ + {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0}, + {0, 12, D3DDECLTYPE_FLOAT2, 0, D3DDECLUSAGE_BLENDWEIGHT, 0}, + D3DDECL_END(), + }, D3DFVF_XYZB2}, + {{ + {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0}, + {0, 12, D3DDECLTYPE_FLOAT1, 0, D3DDECLUSAGE_BLENDWEIGHT, 0}, + {0, 16, D3DDECLTYPE_UBYTE4, 0, D3DDECLUSAGE_BLENDINDICES, 0}, + D3DDECL_END(), + }, D3DFVF_XYZB2 | D3DFVF_LASTBETA_UBYTE4}, + {{ + {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0}, + {0, 12, D3DDECLTYPE_FLOAT1, 0, D3DDECLUSAGE_BLENDWEIGHT, 0}, + {0, 16, D3DDECLTYPE_D3DCOLOR, 0, D3DDECLUSAGE_BLENDINDICES, 0}, + D3DDECL_END(), + }, D3DFVF_XYZB2 | D3DFVF_LASTBETA_D3DCOLOR}, + {{ + {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0}, + {0, 12, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_BLENDWEIGHT, 0}, + D3DDECL_END(), + }, D3DFVF_XYZB3}, + {{ + {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0}, + {0, 12, D3DDECLTYPE_FLOAT2, 0, D3DDECLUSAGE_BLENDWEIGHT, 0}, + {0, 20, D3DDECLTYPE_UBYTE4, 0, D3DDECLUSAGE_BLENDINDICES, 0}, + D3DDECL_END(), + }, D3DFVF_XYZB3 | D3DFVF_LASTBETA_UBYTE4}, + {{ + {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0}, + {0, 12, D3DDECLTYPE_FLOAT2, 0, D3DDECLUSAGE_BLENDWEIGHT, 0}, + {0, 20, D3DDECLTYPE_D3DCOLOR, 0, D3DDECLUSAGE_BLENDINDICES, 0}, + D3DDECL_END(), + }, D3DFVF_XYZB3 | D3DFVF_LASTBETA_D3DCOLOR}, + {{ + {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0}, + {0, 12, D3DDECLTYPE_FLOAT4, 0, D3DDECLUSAGE_BLENDWEIGHT, 0}, + D3DDECL_END(), + }, D3DFVF_XYZB4}, + {{ + {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0}, + {0, 12, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_BLENDWEIGHT, 0}, + {0, 24, D3DDECLTYPE_UBYTE4, 0, D3DDECLUSAGE_BLENDINDICES, 0}, + D3DDECL_END(), + }, D3DFVF_XYZB4 | D3DFVF_LASTBETA_UBYTE4}, + {{ + {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0}, + {0, 12, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_BLENDWEIGHT, 0}, + {0, 24, D3DDECLTYPE_D3DCOLOR, 0, D3DDECLUSAGE_BLENDINDICES, 0}, + D3DDECL_END(), + }, D3DFVF_XYZB4 | D3DFVF_LASTBETA_D3DCOLOR}, + {{ + {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0}, + {0, 12, D3DDECLTYPE_FLOAT4, 0, D3DDECLUSAGE_BLENDWEIGHT, 0}, + {0, 28, D3DDECLTYPE_UBYTE4, 0, D3DDECLUSAGE_BLENDINDICES, 0}, + D3DDECL_END(), + }, D3DFVF_XYZB5 | D3DFVF_LASTBETA_UBYTE4}, + {{ + {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0}, + {0, 12, D3DDECLTYPE_FLOAT4, 0, D3DDECLUSAGE_BLENDWEIGHT, 0}, + {0, 28, D3DDECLTYPE_D3DCOLOR, 0, D3DDECLUSAGE_BLENDINDICES, 0}, + D3DDECL_END(), + }, D3DFVF_XYZB5 | D3DFVF_LASTBETA_D3DCOLOR}, + {{ + {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_NORMAL, 0}, + D3DDECL_END(), + }, D3DFVF_NORMAL}, + {{ + {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_NORMAL, 0}, + {0, 12, D3DDECLTYPE_D3DCOLOR, 0, D3DDECLUSAGE_COLOR, 0}, + D3DDECL_END(), + }, D3DFVF_NORMAL | D3DFVF_DIFFUSE}, + {{ + {0, 0, D3DDECLTYPE_FLOAT1, 0, D3DDECLUSAGE_PSIZE, 0}, + D3DDECL_END(), + }, D3DFVF_PSIZE}, + {{ + {0, 0, D3DDECLTYPE_D3DCOLOR, 0, D3DDECLUSAGE_COLOR, 0}, + D3DDECL_END(), + }, D3DFVF_DIFFUSE}, + {{ + {0, 0, D3DDECLTYPE_D3DCOLOR, 0, D3DDECLUSAGE_COLOR, 1}, + D3DDECL_END(), + }, D3DFVF_SPECULAR}, + /* Make sure textures of different sizes work. */ + {{ + {0, 0, D3DDECLTYPE_FLOAT1, 0, D3DDECLUSAGE_TEXCOORD, 0}, + D3DDECL_END(), + }, D3DFVF_TEXCOORDSIZE1(0) | D3DFVF_TEX1}, + {{ + {0, 0, D3DDECLTYPE_FLOAT2, 0, D3DDECLUSAGE_TEXCOORD, 0}, + D3DDECL_END(), + }, D3DFVF_TEXCOORDSIZE2(0) | D3DFVF_TEX1}, + {{ + {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_TEXCOORD, 0}, + D3DDECL_END(), + }, D3DFVF_TEXCOORDSIZE3(0) | D3DFVF_TEX1}, + {{ + {0, 0, D3DDECLTYPE_FLOAT4, 0, D3DDECLUSAGE_TEXCOORD, 0}, + D3DDECL_END(), + }, D3DFVF_TEXCOORDSIZE4(0) | D3DFVF_TEX1}, + /* Make sure the TEXCOORD index works correctly - try several textures. */ + {{ + {0, 0, D3DDECLTYPE_FLOAT1, 0, D3DDECLUSAGE_TEXCOORD, 0}, + {0, 4, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_TEXCOORD, 1}, + {0, 16, D3DDECLTYPE_FLOAT2, 0, D3DDECLUSAGE_TEXCOORD, 2}, + {0, 24, D3DDECLTYPE_FLOAT4, 0, D3DDECLUSAGE_TEXCOORD, 3}, + D3DDECL_END(), + }, D3DFVF_TEX4 | D3DFVF_TEXCOORDSIZE1(0) | D3DFVF_TEXCOORDSIZE3(1) + | D3DFVF_TEXCOORDSIZE2(2) | D3DFVF_TEXCOORDSIZE4(3)}, + /* Now try some combination tests. */ + {{ + {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0}, + {0, 12, D3DDECLTYPE_FLOAT4, 0, D3DDECLUSAGE_BLENDWEIGHT, 0}, + {0, 28, D3DDECLTYPE_D3DCOLOR, 0, D3DDECLUSAGE_COLOR, 0}, + {0, 32, D3DDECLTYPE_D3DCOLOR, 0, D3DDECLUSAGE_COLOR, 1}, + {0, 36, D3DDECLTYPE_FLOAT2, 0, D3DDECLUSAGE_TEXCOORD, 0}, + {0, 44, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_TEXCOORD, 1}, + D3DDECL_END(), + }, D3DFVF_XYZB4 | D3DFVF_DIFFUSE | D3DFVF_SPECULAR | D3DFVF_TEX2 + | D3DFVF_TEXCOORDSIZE2(0) | D3DFVF_TEXCOORDSIZE3(1)}, + {{ + {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0}, + {0, 12, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_NORMAL, 0}, + {0, 24, D3DDECLTYPE_FLOAT1, 0, D3DDECLUSAGE_PSIZE, 0}, + {0, 28, D3DDECLTYPE_D3DCOLOR, 0, D3DDECLUSAGE_COLOR, 1}, + {0, 32, D3DDECLTYPE_FLOAT1, 0, D3DDECLUSAGE_TEXCOORD, 0}, + {0, 36, D3DDECLTYPE_FLOAT4, 0, D3DDECLUSAGE_TEXCOORD, 1}, + D3DDECL_END(), + }, D3DFVF_XYZ | D3DFVF_NORMAL | D3DFVF_PSIZE | D3DFVF_SPECULAR | D3DFVF_TEX2 + | D3DFVF_TEXCOORDSIZE1(0) | D3DFVF_TEXCOORDSIZE4(1)}, + }; + unsigned int i; + + for (i = 0; i < ARRAY_SIZE(test_data); ++i) + { + test_decl_to_fvf(test_data[i].decl, test_data[i].fvf, D3D_OK, __LINE__, i); + test_fvf_to_decl(test_data[i].fvf, test_data[i].decl, D3D_OK, __LINE__, i); + } + + /* Usage indices for position and normal are apparently ignored. */ + { + const D3DVERTEXELEMENT9 decl[] = + { + {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 1}, + D3DDECL_END(), + }; + test_decl_to_fvf(decl, D3DFVF_XYZ, D3D_OK, __LINE__, 0); + } + { + const D3DVERTEXELEMENT9 decl[] = + { + {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_NORMAL, 1}, + D3DDECL_END(), + }; + test_decl_to_fvf(decl, D3DFVF_NORMAL, D3D_OK, __LINE__, 0); + } + /* D3DFVF_LASTBETA_UBYTE4 and D3DFVF_LASTBETA_D3DCOLOR are ignored if + * there are no blend matrices. */ + { + const D3DVERTEXELEMENT9 decl[] = + { + {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0}, + D3DDECL_END(), + }; + test_fvf_to_decl(D3DFVF_XYZ | D3DFVF_LASTBETA_UBYTE4, decl, D3D_OK, __LINE__, 0); + } + { + const D3DVERTEXELEMENT9 decl[] = + { + {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0}, + D3DDECL_END(), + }; + test_fvf_to_decl(D3DFVF_XYZ | D3DFVF_LASTBETA_D3DCOLOR, decl, D3D_OK, __LINE__, 0); + } + /* D3DFVF_LASTBETA_UBYTE4 takes precedence over D3DFVF_LASTBETA_D3DCOLOR. */ + { + const D3DVERTEXELEMENT9 decl[] = + { + {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0}, + {0, 12, D3DDECLTYPE_FLOAT4, 0, D3DDECLUSAGE_BLENDWEIGHT, 0}, + {0, 28, D3DDECLTYPE_UBYTE4, 0, D3DDECLUSAGE_BLENDINDICES, 0}, + D3DDECL_END(), + }; + test_fvf_to_decl(D3DFVF_XYZB5 | D3DFVF_LASTBETA_D3DCOLOR | D3DFVF_LASTBETA_UBYTE4, + decl, D3D_OK, __LINE__, 0); + } + /* These are supposed to fail, both ways. */ + { + const D3DVERTEXELEMENT9 decl[] = + { + {0, 0, D3DDECLTYPE_FLOAT4, 0, D3DDECLUSAGE_POSITION, 0}, + D3DDECL_END(), + }; + test_decl_to_fvf(decl, D3DFVF_XYZW, D3DERR_INVALIDCALL, __LINE__, 0); + test_fvf_to_decl(D3DFVF_XYZW, decl, D3DERR_INVALIDCALL, __LINE__, 0); + } + { + const D3DVERTEXELEMENT9 decl[] = + { + {0, 0, D3DDECLTYPE_FLOAT4, 0, D3DDECLUSAGE_POSITION, 0}, + {0, 16, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_NORMAL, 0}, + D3DDECL_END(), + }; + test_decl_to_fvf(decl, D3DFVF_XYZW | D3DFVF_NORMAL, D3DERR_INVALIDCALL, __LINE__, 0); + test_fvf_to_decl(D3DFVF_XYZW | D3DFVF_NORMAL, decl, D3DERR_INVALIDCALL, __LINE__, 0); + } + { + const D3DVERTEXELEMENT9 decl[] = + { + {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0}, + {0, 12, D3DDECLTYPE_FLOAT4, 0, D3DDECLUSAGE_BLENDWEIGHT, 0}, + {0, 28, D3DDECLTYPE_FLOAT1, 0, D3DDECLUSAGE_BLENDINDICES, 0}, + D3DDECL_END(), + }; + test_decl_to_fvf(decl, D3DFVF_XYZB5, D3DERR_INVALIDCALL, __LINE__, 0); + test_fvf_to_decl(D3DFVF_XYZB5, decl, D3DERR_INVALIDCALL, __LINE__, 0); + } + /* Test a declaration that can't be converted to an FVF. */ + { + const D3DVERTEXELEMENT9 decl[] = + { + {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0}, + {0, 12, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_NORMAL, 0}, + {0, 24, D3DDECLTYPE_FLOAT1, 0, D3DDECLUSAGE_PSIZE, 0}, + {0, 28, D3DDECLTYPE_D3DCOLOR, 0, D3DDECLUSAGE_COLOR, 1}, + {0, 32, D3DDECLTYPE_FLOAT1, 0, D3DDECLUSAGE_TEXCOORD, 0}, + /* 8 bytes padding */ + {0, 44, D3DDECLTYPE_FLOAT4, 0, D3DDECLUSAGE_TEXCOORD, 1}, + D3DDECL_END(), + }; + test_decl_to_fvf(decl, 0, D3DERR_INVALIDCALL, __LINE__, 0); + } + /* Elements must be ordered by offset. */ + { + const D3DVERTEXELEMENT9 decl[] = + { + {0, 12, D3DDECLTYPE_D3DCOLOR, 0, D3DDECLUSAGE_COLOR, 0}, + {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0}, + D3DDECL_END(), + }; + test_decl_to_fvf(decl, 0, D3DERR_INVALIDCALL, __LINE__, 0); + } + /* Basic tests for element order. */ + { + const D3DVERTEXELEMENT9 decl[] = + { + {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0}, + {0, 12, D3DDECLTYPE_D3DCOLOR, 0, D3DDECLUSAGE_COLOR, 0}, + {0, 16, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_NORMAL, 0}, + D3DDECL_END(), + }; + test_decl_to_fvf(decl, 0, D3DERR_INVALIDCALL, __LINE__, 0); + } + { + const D3DVERTEXELEMENT9 decl[] = + { + {0, 0, D3DDECLTYPE_D3DCOLOR, 0, D3DDECLUSAGE_COLOR, 0}, + {0, 4, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0}, + D3DDECL_END(), + }; + test_decl_to_fvf(decl, 0, D3DERR_INVALIDCALL, __LINE__, 0); + } + { + const D3DVERTEXELEMENT9 decl[] = + { + {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_NORMAL, 0}, + {0, 12, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0}, + D3DDECL_END(), + }; + test_decl_to_fvf(decl, 0, D3DERR_INVALIDCALL, __LINE__, 0); + } + /* Textures must be ordered by texcoords. */ + { + const D3DVERTEXELEMENT9 decl[] = + { + {0, 0, D3DDECLTYPE_FLOAT1, 0, D3DDECLUSAGE_TEXCOORD, 0}, + {0, 4, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_TEXCOORD, 2}, + {0, 16, D3DDECLTYPE_FLOAT2, 0, D3DDECLUSAGE_TEXCOORD, 1}, + {0, 24, D3DDECLTYPE_FLOAT4, 0, D3DDECLUSAGE_TEXCOORD, 3}, + D3DDECL_END(), + }; + test_decl_to_fvf(decl, 0, D3DERR_INVALIDCALL, __LINE__, 0); + } + /* Duplicate elements are not allowed. */ + { + const D3DVERTEXELEMENT9 decl[] = + { + {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0}, + {0, 12, D3DDECLTYPE_D3DCOLOR, 0, D3DDECLUSAGE_COLOR, 0}, + {0, 16, D3DDECLTYPE_D3DCOLOR, 0, D3DDECLUSAGE_COLOR, 0}, + D3DDECL_END(), + }; + test_decl_to_fvf(decl, 0, D3DERR_INVALIDCALL, __LINE__, 0); + } + /* Invalid FVFs cannot be converted to a declarator. */ + test_fvf_to_decl(0xdeadbeef, NULL, D3DERR_INVALIDCALL, __LINE__, 0); +} + +static void D3DXGetFVFVertexSizeTest(void) +{ + UINT got; + + compare_vertex_sizes (D3DFVF_XYZ, 12); + + compare_vertex_sizes (D3DFVF_XYZB3, 24); + + compare_vertex_sizes (D3DFVF_XYZB5, 32); + + compare_vertex_sizes (D3DFVF_XYZ | D3DFVF_NORMAL, 24); + + compare_vertex_sizes (D3DFVF_XYZ | D3DFVF_DIFFUSE, 16); + + compare_vertex_sizes ( + D3DFVF_XYZ | + D3DFVF_TEX1 | + D3DFVF_TEXCOORDSIZE1(0), 16); + compare_vertex_sizes ( + D3DFVF_XYZ | + D3DFVF_TEX2 | + D3DFVF_TEXCOORDSIZE1(0) | + D3DFVF_TEXCOORDSIZE1(1), 20); + + compare_vertex_sizes ( + D3DFVF_XYZ | + D3DFVF_TEX1 | + D3DFVF_TEXCOORDSIZE2(0), 20); + + compare_vertex_sizes ( + D3DFVF_XYZ | + D3DFVF_TEX2 | + D3DFVF_TEXCOORDSIZE2(0) | + D3DFVF_TEXCOORDSIZE2(1), 28); + + compare_vertex_sizes ( + D3DFVF_XYZ | + D3DFVF_TEX6 | + D3DFVF_TEXCOORDSIZE2(0) | + D3DFVF_TEXCOORDSIZE2(1) | + D3DFVF_TEXCOORDSIZE2(2) | + D3DFVF_TEXCOORDSIZE2(3) | + D3DFVF_TEXCOORDSIZE2(4) | + D3DFVF_TEXCOORDSIZE2(5), 60); + + compare_vertex_sizes ( + D3DFVF_XYZ | + D3DFVF_TEX8 | + D3DFVF_TEXCOORDSIZE2(0) | + D3DFVF_TEXCOORDSIZE2(1) | + D3DFVF_TEXCOORDSIZE2(2) | + D3DFVF_TEXCOORDSIZE2(3) | + D3DFVF_TEXCOORDSIZE2(4) | + D3DFVF_TEXCOORDSIZE2(5) | + D3DFVF_TEXCOORDSIZE2(6) | + D3DFVF_TEXCOORDSIZE2(7), 76); + + compare_vertex_sizes ( + D3DFVF_XYZ | + D3DFVF_TEX1 | + D3DFVF_TEXCOORDSIZE3(0), 24); + + compare_vertex_sizes ( + D3DFVF_XYZ | + D3DFVF_TEX4 | + D3DFVF_TEXCOORDSIZE3(0) | + D3DFVF_TEXCOORDSIZE3(1) | + D3DFVF_TEXCOORDSIZE3(2) | + D3DFVF_TEXCOORDSIZE3(3), 60); + + compare_vertex_sizes ( + D3DFVF_XYZ | + D3DFVF_TEX1 | + D3DFVF_TEXCOORDSIZE4(0), 28); + + compare_vertex_sizes ( + D3DFVF_XYZ | + D3DFVF_TEX2 | + D3DFVF_TEXCOORDSIZE4(0) | + D3DFVF_TEXCOORDSIZE4(1), 44); + + compare_vertex_sizes ( + D3DFVF_XYZ | + D3DFVF_TEX3 | + D3DFVF_TEXCOORDSIZE4(0) | + D3DFVF_TEXCOORDSIZE4(1) | + D3DFVF_TEXCOORDSIZE4(2), 60); + + compare_vertex_sizes ( + D3DFVF_XYZB5 | + D3DFVF_NORMAL | + D3DFVF_DIFFUSE | + D3DFVF_SPECULAR | + D3DFVF_TEX8 | + D3DFVF_TEXCOORDSIZE4(0) | + D3DFVF_TEXCOORDSIZE4(1) | + D3DFVF_TEXCOORDSIZE4(2) | + D3DFVF_TEXCOORDSIZE4(3) | + D3DFVF_TEXCOORDSIZE4(4) | + D3DFVF_TEXCOORDSIZE4(5) | + D3DFVF_TEXCOORDSIZE4(6) | + D3DFVF_TEXCOORDSIZE4(7), 180); +} + +static void D3DXIntersectTriTest(void) +{ + BOOL exp_res, got_res; + D3DXVECTOR3 position, ray, vertex[3]; + FLOAT exp_dist, got_dist, exp_u, got_u, exp_v, got_v; + + vertex[0].x = 1.0f; vertex[0].y = 0.0f; vertex[0].z = 0.0f; + vertex[1].x = 2.0f; vertex[1].y = 0.0f; vertex[1].z = 0.0f; + vertex[2].x = 1.0f; vertex[2].y = 1.0f; vertex[2].z = 0.0f; + + position.x = -14.5f; position.y = -23.75f; position.z = -32.0f; + + ray.x = 2.0f; ray.y = 3.0f; ray.z = 4.0f; + + exp_res = TRUE; exp_u = 0.5f; exp_v = 0.25f; exp_dist = 8.0f; + + got_res = D3DXIntersectTri(&vertex[0], &vertex[1], &vertex[2], &position, &ray, &got_u, &got_v, &got_dist); + ok(got_res == exp_res, "Expected result %d, got %d.\n", exp_res, got_res); + ok(compare(exp_u, got_u), "Expected u %f, got %f.\n", exp_u, got_u); + ok(compare(exp_v, got_v), "Expected v %f, got %f.\n", exp_v, got_v); + ok(compare(exp_dist, got_dist), "Expected distance %f, got %f.\n", exp_dist, got_dist); + + got_res = D3DXIntersectTri(&vertex[0], &vertex[1], &vertex[2], &position, &ray, NULL, NULL, NULL); + ok(got_res == exp_res, "Expected result %d, got %d.\n", exp_res, got_res); + + vertex[2].x = 1.0f; vertex[2].y = 0.0f; vertex[2].z = 0.0f; + vertex[1].x = 2.0f; vertex[1].y = 0.0f; vertex[1].z = 0.0f; + vertex[0].x = 1.0f; vertex[0].y = 1.0f; vertex[0].z = 0.0f; + + got_u = got_v = got_dist = 0.0f; + got_res = D3DXIntersectTri(&vertex[0], &vertex[1], &vertex[2], &position, &ray, &got_u, &got_v, &got_dist); + ok(got_res == exp_res, "Expected result %d, got %d.\n", exp_res, got_res); + ok(compare(exp_u, got_u), "Expected u %f, got %f.\n", exp_u, got_u); + ok(compare(exp_v, got_v), "Expected v %f, got %f.\n", exp_v, got_v); + ok(compare(exp_dist, got_dist), "Expected distance %f, got %f.\n", exp_dist, got_dist); + + vertex[2].x = 1.0f; vertex[2].y = 0.0f; vertex[2].z = 0.0f; + vertex[1].x = 2.0f; vertex[1].y = 0.0f; vertex[1].z = -0.5f; + vertex[0].x = 1.0f; vertex[0].y = 1.0f; vertex[0].z = -1.0f; + exp_u = 0.375f; + exp_v = 0.5625f; + exp_dist = 7.9375f; + got_u = got_v = got_dist = 0.0f; + got_res = D3DXIntersectTri(&vertex[0], &vertex[1], &vertex[2], &position, &ray, &got_u, &got_v, &got_dist); + ok(got_res == exp_res, "Expected result %d, got %d.\n", exp_res, got_res); + ok(compare(exp_u, got_u), "Expected u %f, got %f.\n", exp_u, got_u); + ok(compare(exp_v, got_v), "Expected v %f, got %f.\n", exp_v, got_v); + ok(compare(exp_dist, got_dist), "Expected distance %f, got %f.\n", exp_dist, got_dist); + + +/*Only positive ray is taken in account*/ + + vertex[0].x = 1.0f; vertex[0].y = 0.0f; vertex[0].z = 0.0f; + vertex[1].x = 2.0f; vertex[1].y = 0.0f; vertex[1].z = 0.0f; + vertex[2].x = 1.0f; vertex[2].y = 1.0f; vertex[2].z = 0.0f; + + position.x = 17.5f; position.y = 24.25f; position.z = 32.0f; + + ray.x = 2.0f; ray.y = 3.0f; ray.z = 4.0f; + + exp_res = FALSE; + + got_res = D3DXIntersectTri(&vertex[0],&vertex[1],&vertex[2],&position,&ray,&got_u,&got_v,&got_dist); + ok( got_res == exp_res, "Expected result = %d, got %d\n",exp_res,got_res); + + got_res = D3DXIntersectTri(&vertex[0], &vertex[1], &vertex[2], &position, &ray, NULL, NULL, NULL); + ok(got_res == exp_res, "Expected result = %d, got %d\n", exp_res, got_res); + +/*Intersection between ray and triangle in a same plane is considered as empty*/ + + vertex[0].x = 4.0f; vertex[0].y = 0.0f; vertex[0].z = 0.0f; + vertex[1].x = 6.0f; vertex[1].y = 0.0f; vertex[1].z = 0.0f; + vertex[2].x = 4.0f; vertex[2].y = 2.0f; vertex[2].z = 0.0f; + + position.x = 1.0f; position.y = 1.0f; position.z = 0.0f; + + ray.x = 1.0f; ray.y = 0.0f; ray.z = 0.0f; + + exp_res = FALSE; + + got_res = D3DXIntersectTri(&vertex[0],&vertex[1],&vertex[2],&position,&ray,&got_u,&got_v,&got_dist); + ok( got_res == exp_res, "Expected result = %d, got %d\n",exp_res,got_res); + + got_res = D3DXIntersectTri(&vertex[0], &vertex[1], &vertex[2], &position, &ray, NULL, NULL, NULL); + ok(got_res == exp_res, "Expected result = %d, got %d\n", exp_res, got_res); +} + +static void D3DXCreateMeshTest(void) +{ + HRESULT hr; + IDirect3DDevice9 *device, *test_device; + ID3DXMesh *d3dxmesh; + int i, size; + D3DVERTEXELEMENT9 test_decl[MAX_FVF_DECL_SIZE]; + DWORD options; + struct mesh mesh; + struct test_context *test_context; + + static const D3DVERTEXELEMENT9 decl1[] = + { + {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0}, + {0, 12, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL, 0}, + D3DDECL_END(), + }; + + static const D3DVERTEXELEMENT9 decl2[] = + { + {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0}, + {0, 12, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL, 0}, + {0, 24, D3DDECLTYPE_FLOAT1, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_PSIZE, 0}, + {0, 28, D3DDECLTYPE_D3DCOLOR, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_COLOR, 1}, + {0, 32, D3DDECLTYPE_FLOAT1, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0}, + /* 8 bytes padding */ + {0, 44, D3DDECLTYPE_FLOAT4, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 1}, + D3DDECL_END(), + }; + + static const D3DVERTEXELEMENT9 decl3[] = + { + {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0}, + {1, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL, 0}, + D3DDECL_END(), + }; + + hr = D3DXCreateMesh(0, 0, 0, NULL, NULL, NULL); + ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n", hr, D3DERR_INVALIDCALL); + + hr = D3DXCreateMesh(1, 3, D3DXMESH_MANAGED, decl1, NULL, &d3dxmesh); + ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n", hr, D3DERR_INVALIDCALL); + + test_context = new_test_context(); + if (!test_context) + { + skip("Couldn't create test context\n"); + return; + } + device = test_context->device; + + hr = D3DXCreateMesh(0, 3, D3DXMESH_MANAGED, decl1, device, &d3dxmesh); + ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n", hr, D3DERR_INVALIDCALL); + + hr = D3DXCreateMesh(1, 0, D3DXMESH_MANAGED, decl1, device, &d3dxmesh); + ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n", hr, D3DERR_INVALIDCALL); + + hr = D3DXCreateMesh(1, 3, 0, decl1, device, &d3dxmesh); + ok(hr == D3D_OK, "Got result %x, expected %x (D3D_OK)\n", hr, D3D_OK); + + if (hr == D3D_OK) + { + d3dxmesh->lpVtbl->Release(d3dxmesh); + } + + hr = D3DXCreateMesh(1, 3, D3DXMESH_MANAGED, 0, device, &d3dxmesh); + ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n", hr, D3DERR_INVALIDCALL); + + hr = D3DXCreateMesh(1, 3, D3DXMESH_MANAGED, decl1, device, NULL); + ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n", hr, D3DERR_INVALIDCALL); + + hr = D3DXCreateMesh(1, 3, D3DXMESH_MANAGED, decl1, device, &d3dxmesh); + ok(hr == D3D_OK, "Got result %x, expected 0 (D3D_OK)\n", hr); + + if (hr == D3D_OK) + { + /* device */ + hr = d3dxmesh->lpVtbl->GetDevice(d3dxmesh, NULL); + ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n", hr, D3DERR_INVALIDCALL); + + hr = d3dxmesh->lpVtbl->GetDevice(d3dxmesh, &test_device); + ok(hr == D3D_OK, "Got result %x, expected %x (D3D_OK)\n", hr, D3D_OK); + ok(test_device == device, "Got result %p, expected %p\n", test_device, device); + + if (hr == D3D_OK) + { + IDirect3DDevice9_Release(device); + } + + /* declaration */ + hr = d3dxmesh->lpVtbl->GetDeclaration(d3dxmesh, NULL); + ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n", hr, D3DERR_INVALIDCALL); + + hr = d3dxmesh->lpVtbl->GetDeclaration(d3dxmesh, test_decl); + ok(hr == D3D_OK, "Got result %x, expected 0 (D3D_OK)\n", hr); + + if (hr == D3D_OK) + { + size = ARRAY_SIZE(decl1); + for (i = 0; i < size - 1; i++) + { + ok(test_decl[i].Stream == decl1[i].Stream, "Returned stream %d, expected %d\n", test_decl[i].Stream, decl1[i].Stream); + ok(test_decl[i].Type == decl1[i].Type, "Returned type %d, expected %d\n", test_decl[i].Type, decl1[i].Type); + ok(test_decl[i].Method == decl1[i].Method, "Returned method %d, expected %d\n", test_decl[i].Method, decl1[i].Method); + ok(test_decl[i].Usage == decl1[i].Usage, "Returned usage %d, expected %d\n", test_decl[i].Usage, decl1[i].Usage); + ok(test_decl[i].UsageIndex == decl1[i].UsageIndex, "Returned usage index %d, expected %d\n", test_decl[i].UsageIndex, decl1[i].UsageIndex); + ok(test_decl[i].Offset == decl1[i].Offset, "Returned offset %d, expected %d\n", test_decl[i].Offset, decl1[i].Offset); + } + ok(decl1[size-1].Stream == 0xFF, "Returned too long vertex declaration\n"); /* end element */ + } + + /* options */ + options = d3dxmesh->lpVtbl->GetOptions(d3dxmesh); + ok(options == D3DXMESH_MANAGED, "Got result %x, expected %x (D3DXMESH_MANAGED)\n", options, D3DXMESH_MANAGED); + + /* rest */ + if (!new_mesh(&mesh, 3, 1)) + { + skip("Couldn't create mesh\n"); + } + else + { + memset(mesh.vertices, 0, mesh.number_of_vertices * sizeof(*mesh.vertices)); + memset(mesh.faces, 0, mesh.number_of_faces * sizeof(*mesh.faces)); + mesh.fvf = D3DFVF_XYZ | D3DFVF_NORMAL; + + compare_mesh("createmesh1", d3dxmesh, &mesh); + + free_mesh(&mesh); + } + + d3dxmesh->lpVtbl->Release(d3dxmesh); + } + + /* Test a declaration that can't be converted to an FVF. */ + hr = D3DXCreateMesh(1, 3, D3DXMESH_MANAGED, decl2, device, &d3dxmesh); + ok(hr == D3D_OK, "Got result %x, expected 0 (D3D_OK)\n", hr); + + if (hr == D3D_OK) + { + /* device */ + hr = d3dxmesh->lpVtbl->GetDevice(d3dxmesh, NULL); + ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n", hr, D3DERR_INVALIDCALL); + + hr = d3dxmesh->lpVtbl->GetDevice(d3dxmesh, &test_device); + ok(hr == D3D_OK, "Got result %x, expected %x (D3D_OK)\n", hr, D3D_OK); + ok(test_device == device, "Got result %p, expected %p\n", test_device, device); + + if (hr == D3D_OK) + { + IDirect3DDevice9_Release(device); + } + + /* declaration */ + hr = d3dxmesh->lpVtbl->GetDeclaration(d3dxmesh, test_decl); + ok(hr == D3D_OK, "Got result %x, expected 0 (D3D_OK)\n", hr); + + if (hr == D3D_OK) + { + size = ARRAY_SIZE(decl2); + for (i = 0; i < size - 1; i++) + { + ok(test_decl[i].Stream == decl2[i].Stream, "Returned stream %d, expected %d\n", test_decl[i].Stream, decl2[i].Stream); + ok(test_decl[i].Type == decl2[i].Type, "Returned type %d, expected %d\n", test_decl[i].Type, decl2[i].Type); + ok(test_decl[i].Method == decl2[i].Method, "Returned method %d, expected %d\n", test_decl[i].Method, decl2[i].Method); + ok(test_decl[i].Usage == decl2[i].Usage, "Returned usage %d, expected %d\n", test_decl[i].Usage, decl2[i].Usage); + ok(test_decl[i].UsageIndex == decl2[i].UsageIndex, "Returned usage index %d, expected %d\n", test_decl[i].UsageIndex, decl2[i].UsageIndex); + ok(test_decl[i].Offset == decl2[i].Offset, "Returned offset %d, expected %d\n", test_decl[i].Offset, decl2[i].Offset); + } + ok(decl2[size-1].Stream == 0xFF, "Returned too long vertex declaration\n"); /* end element */ + } + + /* options */ + options = d3dxmesh->lpVtbl->GetOptions(d3dxmesh); + ok(options == D3DXMESH_MANAGED, "Got result %x, expected %x (D3DXMESH_MANAGED)\n", options, D3DXMESH_MANAGED); + + /* rest */ + if (!new_mesh(&mesh, 3, 1)) + { + skip("Couldn't create mesh\n"); + } + else + { + memset(mesh.vertices, 0, mesh.number_of_vertices * sizeof(*mesh.vertices)); + memset(mesh.faces, 0, mesh.number_of_faces * sizeof(*mesh.faces)); + mesh.fvf = 0; + mesh.vertex_size = 60; + + compare_mesh("createmesh2", d3dxmesh, &mesh); + + free_mesh(&mesh); + } + + mesh.vertex_size = d3dxmesh->lpVtbl->GetNumBytesPerVertex(d3dxmesh); + ok(mesh.vertex_size == 60, "Got vertex size %u, expected %u\n", mesh.vertex_size, 60); + + d3dxmesh->lpVtbl->Release(d3dxmesh); + } + + /* Test a declaration with multiple streams. */ + hr = D3DXCreateMesh(1, 3, D3DXMESH_MANAGED, decl3, device, &d3dxmesh); + ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n", hr, D3DERR_INVALIDCALL); + + free_test_context(test_context); +} + +static void D3DXCreateMeshFVFTest(void) +{ + HRESULT hr; + IDirect3DDevice9 *device, *test_device; + ID3DXMesh *d3dxmesh; + int i, size; + D3DVERTEXELEMENT9 test_decl[MAX_FVF_DECL_SIZE]; + DWORD options; + struct mesh mesh; + struct test_context *test_context; + + static const D3DVERTEXELEMENT9 decl[] = + { + {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0}, + {0, 12, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL, 0}, + D3DDECL_END(), + }; + + hr = D3DXCreateMeshFVF(0, 0, 0, 0, NULL, NULL); + ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n", hr, D3DERR_INVALIDCALL); + + hr = D3DXCreateMeshFVF(1, 3, D3DXMESH_MANAGED, D3DFVF_XYZ | D3DFVF_NORMAL, NULL, &d3dxmesh); + ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n", hr, D3DERR_INVALIDCALL); + + test_context = new_test_context(); + if (!test_context) + { + skip("Couldn't create test context\n"); + return; + } + device = test_context->device; + + hr = D3DXCreateMeshFVF(0, 3, D3DXMESH_MANAGED, D3DFVF_XYZ | D3DFVF_NORMAL, device, &d3dxmesh); + ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n", hr, D3DERR_INVALIDCALL); + + hr = D3DXCreateMeshFVF(1, 0, D3DXMESH_MANAGED, D3DFVF_XYZ | D3DFVF_NORMAL, device, &d3dxmesh); + ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n", hr, D3DERR_INVALIDCALL); + + hr = D3DXCreateMeshFVF(1, 3, 0, D3DFVF_XYZ | D3DFVF_NORMAL, device, &d3dxmesh); + ok(hr == D3D_OK, "Got result %x, expected %x (D3D_OK)\n", hr, D3D_OK); + + if (hr == D3D_OK) + { + d3dxmesh->lpVtbl->Release(d3dxmesh); + } + + hr = D3DXCreateMeshFVF(1, 3, D3DXMESH_MANAGED, 0xdeadbeef, device, &d3dxmesh); + ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n", hr, D3DERR_INVALIDCALL); + + hr = D3DXCreateMeshFVF(1, 3, D3DXMESH_MANAGED, D3DFVF_XYZ | D3DFVF_NORMAL, device, NULL); + ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n", hr, D3DERR_INVALIDCALL); + + hr = D3DXCreateMeshFVF(1, 3, D3DXMESH_MANAGED, D3DFVF_XYZ | D3DFVF_NORMAL, device, &d3dxmesh); + ok(hr == D3D_OK, "Got result %x, expected 0 (D3D_OK)\n", hr); + + if (hr == D3D_OK) + { + /* device */ + hr = d3dxmesh->lpVtbl->GetDevice(d3dxmesh, NULL); + ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n", hr, D3DERR_INVALIDCALL); + + hr = d3dxmesh->lpVtbl->GetDevice(d3dxmesh, &test_device); + ok(hr == D3D_OK, "Got result %x, expected %x (D3D_OK)\n", hr, D3D_OK); + ok(test_device == device, "Got result %p, expected %p\n", test_device, device); + + if (hr == D3D_OK) + { + IDirect3DDevice9_Release(device); + } + + /* declaration */ + hr = d3dxmesh->lpVtbl->GetDeclaration(d3dxmesh, NULL); + ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n", hr, D3DERR_INVALIDCALL); + + hr = d3dxmesh->lpVtbl->GetDeclaration(d3dxmesh, test_decl); + ok(hr == D3D_OK, "Got result %x, expected 0 (D3D_OK)\n", hr); + + if (hr == D3D_OK) + { + size = ARRAY_SIZE(decl); + for (i = 0; i < size - 1; i++) + { + ok(test_decl[i].Stream == decl[i].Stream, "Returned stream %d, expected %d\n", test_decl[i].Stream, decl[i].Stream); + ok(test_decl[i].Type == decl[i].Type, "Returned type %d, expected %d\n", test_decl[i].Type, decl[i].Type); + ok(test_decl[i].Method == decl[i].Method, "Returned method %d, expected %d\n", test_decl[i].Method, decl[i].Method); + ok(test_decl[i].Usage == decl[i].Usage, "Returned usage %d, expected %d\n", test_decl[i].Usage, decl[i].Usage); + ok(test_decl[i].UsageIndex == decl[i].UsageIndex, "Returned usage index %d, expected %d\n", + test_decl[i].UsageIndex, decl[i].UsageIndex); + ok(test_decl[i].Offset == decl[i].Offset, "Returned offset %d, expected %d\n", test_decl[i].Offset, decl[i].Offset); + } + ok(decl[size-1].Stream == 0xFF, "Returned too long vertex declaration\n"); /* end element */ + } + + /* options */ + options = d3dxmesh->lpVtbl->GetOptions(d3dxmesh); + ok(options == D3DXMESH_MANAGED, "Got result %x, expected %x (D3DXMESH_MANAGED)\n", options, D3DXMESH_MANAGED); + + /* rest */ + if (!new_mesh(&mesh, 3, 1)) + { + skip("Couldn't create mesh\n"); + } + else + { + memset(mesh.vertices, 0, mesh.number_of_vertices * sizeof(*mesh.vertices)); + memset(mesh.faces, 0, mesh.number_of_faces * sizeof(*mesh.faces)); + mesh.fvf = D3DFVF_XYZ | D3DFVF_NORMAL; + + compare_mesh("createmeshfvf", d3dxmesh, &mesh); + + free_mesh(&mesh); + } + + d3dxmesh->lpVtbl->Release(d3dxmesh); + } + + free_test_context(test_context); +} + +#define check_vertex_buffer(mesh, vertices, num_vertices, fvf) \ + check_vertex_buffer_(__LINE__, mesh, vertices, num_vertices, fvf) +static void check_vertex_buffer_(int line, ID3DXMesh *mesh, const void *vertices, DWORD num_vertices, DWORD fvf) +{ + DWORD mesh_num_vertices = mesh->lpVtbl->GetNumVertices(mesh); + DWORD mesh_fvf = mesh->lpVtbl->GetFVF(mesh); + const void *mesh_vertices; + HRESULT hr; + + ok_(__FILE__,line)(fvf == mesh_fvf, "expected FVF %x, got %x\n", fvf, mesh_fvf); + ok_(__FILE__,line)(num_vertices == mesh_num_vertices, + "Expected %u vertices, got %u\n", num_vertices, mesh_num_vertices); + + hr = mesh->lpVtbl->LockVertexBuffer(mesh, D3DLOCK_READONLY, (void**)&mesh_vertices); + ok_(__FILE__,line)(hr == D3D_OK, "LockVertexBuffer returned %x, expected %x (D3D_OK)\n", hr, D3D_OK); + if (FAILED(hr)) + return; + + if (mesh_fvf == fvf) { + DWORD vertex_size = D3DXGetFVFVertexSize(fvf), i; + + for (i = 0; i < min(num_vertices, mesh_num_vertices); i++) + { + const FLOAT *exp_float = vertices; + const FLOAT *got_float = mesh_vertices; + DWORD texcount; + DWORD pos_dim = 0; + int j; + BOOL last_beta_dword = FALSE; + char prefix[128]; + + switch (fvf & D3DFVF_POSITION_MASK) { + case D3DFVF_XYZ: pos_dim = 3; break; + case D3DFVF_XYZRHW: pos_dim = 4; break; + case D3DFVF_XYZB1: + case D3DFVF_XYZB2: + case D3DFVF_XYZB3: + case D3DFVF_XYZB4: + case D3DFVF_XYZB5: + pos_dim = (fvf & D3DFVF_POSITION_MASK) - D3DFVF_XYZB1 + 1; + if (fvf & (D3DFVF_LASTBETA_UBYTE4 | D3DFVF_LASTBETA_D3DCOLOR)) + { + pos_dim--; + last_beta_dword = TRUE; + } + break; + case D3DFVF_XYZW: pos_dim = 4; break; + } + sprintf(prefix, "vertex[%u] position, ", i); + check_floats_(line, prefix, got_float, exp_float, pos_dim); + exp_float += pos_dim; + got_float += pos_dim; + + if (last_beta_dword) { + ok_(__FILE__,line)(*(DWORD*)exp_float == *(DWORD*)got_float, + "Vertex[%u]: Expected last beta %08x, got %08x\n", i, *(DWORD*)exp_float, *(DWORD*)got_float); + exp_float++; + got_float++; + } + + if (fvf & D3DFVF_NORMAL) { + sprintf(prefix, "vertex[%u] normal, ", i); + check_floats_(line, prefix, got_float, exp_float, 3); + exp_float += 3; + got_float += 3; + } + if (fvf & D3DFVF_PSIZE) { + ok_(__FILE__,line)(compare(*exp_float, *got_float), + "Vertex[%u]: Expected psize %g, got %g\n", i, *exp_float, *got_float); + exp_float++; + got_float++; + } + if (fvf & D3DFVF_DIFFUSE) { + ok_(__FILE__,line)(*(DWORD*)exp_float == *(DWORD*)got_float, + "Vertex[%u]: Expected diffuse %08x, got %08x\n", i, *(DWORD*)exp_float, *(DWORD*)got_float); + exp_float++; + got_float++; + } + if (fvf & D3DFVF_SPECULAR) { + ok_(__FILE__,line)(*(DWORD*)exp_float == *(DWORD*)got_float, + "Vertex[%u]: Expected specular %08x, got %08x\n", i, *(DWORD*)exp_float, *(DWORD*)got_float); + exp_float++; + got_float++; + } + + texcount = (fvf & D3DFVF_TEXCOUNT_MASK) >> D3DFVF_TEXCOUNT_SHIFT; + for (j = 0; j < texcount; j++) { + DWORD dim = (((fvf >> (16 + 2 * j)) + 1) & 0x03) + 1; + sprintf(prefix, "vertex[%u] texture, ", i); + check_floats_(line, prefix, got_float, exp_float, dim); + exp_float += dim; + got_float += dim; + } + + vertices = (BYTE*)vertices + vertex_size; + mesh_vertices = (BYTE*)mesh_vertices + vertex_size; + } + } + + mesh->lpVtbl->UnlockVertexBuffer(mesh); +} + +#define check_index_buffer(mesh, indices, num_indices, index_size) \ + check_index_buffer_(__LINE__, mesh, indices, num_indices, index_size) +static void check_index_buffer_(int line, ID3DXMesh *mesh, const void *indices, DWORD num_indices, DWORD index_size) +{ + DWORD mesh_index_size = (mesh->lpVtbl->GetOptions(mesh) & D3DXMESH_32BIT) ? 4 : 2; + DWORD mesh_num_indices = mesh->lpVtbl->GetNumFaces(mesh) * 3; + const void *mesh_indices; + HRESULT hr; + DWORD i; + + ok_(__FILE__,line)(index_size == mesh_index_size, + "Expected index size %u, got %u\n", index_size, mesh_index_size); + ok_(__FILE__,line)(num_indices == mesh_num_indices, + "Expected %u indices, got %u\n", num_indices, mesh_num_indices); + + hr = mesh->lpVtbl->LockIndexBuffer(mesh, D3DLOCK_READONLY, (void**)&mesh_indices); + ok_(__FILE__,line)(hr == D3D_OK, "LockIndexBuffer returned %x, expected %x (D3D_OK)\n", hr, D3D_OK); + if (FAILED(hr)) + return; + + if (mesh_index_size == index_size) { + for (i = 0; i < min(num_indices, mesh_num_indices); i++) + { + if (index_size == 4) + ok_(__FILE__,line)(*(DWORD*)indices == *(DWORD*)mesh_indices, + "Index[%u]: expected %u, got %u\n", i, *(DWORD*)indices, *(DWORD*)mesh_indices); + else + ok_(__FILE__,line)(*(WORD*)indices == *(WORD*)mesh_indices, + "Index[%u]: expected %u, got %u\n", i, *(WORD*)indices, *(WORD*)mesh_indices); + indices = (BYTE*)indices + index_size; + mesh_indices = (BYTE*)mesh_indices + index_size; + } + } + mesh->lpVtbl->UnlockIndexBuffer(mesh); +} + +#define check_matrix(got, expected) check_matrix_(__LINE__, got, expected) +static void check_matrix_(int line, const D3DXMATRIX *got, const D3DXMATRIX *expected) +{ + int i, j; + for (i = 0; i < 4; i++) { + for (j = 0; j < 4; j++) { + ok_(__FILE__,line)(compare(U(*expected).m[i][j], U(*got).m[i][j]), + "matrix[%u][%u]: expected %g, got %g\n", + i, j, U(*expected).m[i][j], U(*got).m[i][j]); + } + } +} + +static void check_colorvalue_(int line, const char *prefix, const D3DCOLORVALUE got, const D3DCOLORVALUE expected) +{ + ok_(__FILE__,line)(expected.r == got.r && expected.g == got.g && expected.b == got.b && expected.a == got.a, + "%sExpected (%g, %g, %g, %g), got (%g, %g, %g, %g)\n", prefix, + expected.r, expected.g, expected.b, expected.a, got.r, got.g, got.b, got.a); +} + +#define check_materials(got, got_count, expected, expected_count) \ + check_materials_(__LINE__, got, got_count, expected, expected_count) +static void check_materials_(int line, const D3DXMATERIAL *got, DWORD got_count, const D3DXMATERIAL *expected, DWORD expected_count) +{ + int i; + ok_(__FILE__,line)(expected_count == got_count, "Expected %u materials, got %u\n", expected_count, got_count); + if (!expected) { + ok_(__FILE__,line)(got == NULL, "Expected NULL material ptr, got %p\n", got); + return; + } + for (i = 0; i < min(expected_count, got_count); i++) + { + if (!expected[i].pTextureFilename) + ok_(__FILE__,line)(got[i].pTextureFilename == NULL, + "Expected NULL pTextureFilename, got %p\n", got[i].pTextureFilename); + else + ok_(__FILE__,line)(!strcmp(expected[i].pTextureFilename, got[i].pTextureFilename), + "Expected '%s' for pTextureFilename, got '%s'\n", expected[i].pTextureFilename, got[i].pTextureFilename); + check_colorvalue_(line, "Diffuse: ", got[i].MatD3D.Diffuse, expected[i].MatD3D.Diffuse); + check_colorvalue_(line, "Ambient: ", got[i].MatD3D.Ambient, expected[i].MatD3D.Ambient); + check_colorvalue_(line, "Specular: ", got[i].MatD3D.Specular, expected[i].MatD3D.Specular); + check_colorvalue_(line, "Emissive: ", got[i].MatD3D.Emissive, expected[i].MatD3D.Emissive); + ok_(__FILE__,line)(expected[i].MatD3D.Power == got[i].MatD3D.Power, + "Power: Expected %g, got %g\n", expected[i].MatD3D.Power, got[i].MatD3D.Power); + } +} + +#define check_generated_adjacency(mesh, got, epsilon) check_generated_adjacency_(__LINE__, mesh, got, epsilon) +static void check_generated_adjacency_(int line, ID3DXMesh *mesh, const DWORD *got, FLOAT epsilon) +{ + DWORD *expected; + DWORD num_faces = mesh->lpVtbl->GetNumFaces(mesh); + HRESULT hr; + + expected = HeapAlloc(GetProcessHeap(), 0, num_faces * sizeof(DWORD) * 3); + if (!expected) { + skip_(__FILE__, line)("Out of memory\n"); + return; + } + hr = mesh->lpVtbl->GenerateAdjacency(mesh, epsilon, expected); + ok_(__FILE__, line)(hr == D3D_OK, "Expected D3D_OK, got %#x\n", hr); + if (SUCCEEDED(hr)) + { + int i; + for (i = 0; i < num_faces; i++) + { + ok_(__FILE__, line)(expected[i * 3] == got[i * 3] && + expected[i * 3 + 1] == got[i * 3 + 1] && + expected[i * 3 + 2] == got[i * 3 + 2], + "Face %u adjacencies: Expected (%u, %u, %u), got (%u, %u, %u)\n", i, + expected[i * 3], expected[i * 3 + 1], expected[i * 3 + 2], + got[i * 3], got[i * 3 + 1], got[i * 3 + 2]); + } + } + HeapFree(GetProcessHeap(), 0, expected); +} + +#define check_generated_effects(materials, num_materials, effects) \ + check_generated_effects_(__LINE__, materials, num_materials, effects) +static void check_generated_effects_(int line, const D3DXMATERIAL *materials, DWORD num_materials, const D3DXEFFECTINSTANCE *effects) +{ + int i; + static const struct { + const char *name; + DWORD name_size; + DWORD num_bytes; + DWORD value_offset; + } params[] = { +#define EFFECT_TABLE_ENTRY(str, field) \ + {str, sizeof(str), sizeof(materials->MatD3D.field), offsetof(D3DXMATERIAL, MatD3D.field)} + EFFECT_TABLE_ENTRY("Diffuse", Diffuse), + EFFECT_TABLE_ENTRY("Power", Power), + EFFECT_TABLE_ENTRY("Specular", Specular), + EFFECT_TABLE_ENTRY("Emissive", Emissive), + EFFECT_TABLE_ENTRY("Ambient", Ambient), +#undef EFFECT_TABLE_ENTRY + }; + + if (!num_materials) { + ok_(__FILE__, line)(effects == NULL, "Expected NULL effects, got %p\n", effects); + return; + } + for (i = 0; i < num_materials; i++) + { + int j; + DWORD expected_num_defaults = ARRAY_SIZE(params) + (materials[i].pTextureFilename ? 1 : 0); + + ok_(__FILE__,line)(expected_num_defaults == effects[i].NumDefaults, + "effect[%u] NumDefaults: Expected %u, got %u\n", i, + expected_num_defaults, effects[i].NumDefaults); + for (j = 0; j < min(ARRAY_SIZE(params), effects[i].NumDefaults); j++) + { + int k; + D3DXEFFECTDEFAULT *got_param = &effects[i].pDefaults[j]; + ok_(__FILE__,line)(!strcmp(params[j].name, got_param->pParamName), + "effect[%u].pDefaults[%u].pParamName: Expected '%s', got '%s'\n", i, j, + params[j].name, got_param->pParamName); + ok_(__FILE__,line)(D3DXEDT_FLOATS == got_param->Type, + "effect[%u].pDefaults[%u].Type: Expected %u, got %u\n", i, j, + D3DXEDT_FLOATS, got_param->Type); + ok_(__FILE__,line)(params[j].num_bytes == got_param->NumBytes, + "effect[%u].pDefaults[%u].NumBytes: Expected %u, got %u\n", i, j, + params[j].num_bytes, got_param->NumBytes); + for (k = 0; k < min(params[j].num_bytes, got_param->NumBytes) / 4; k++) + { + FLOAT expected = ((FLOAT*)((BYTE*)&materials[i] + params[j].value_offset))[k]; + FLOAT got = ((FLOAT*)got_param->pValue)[k]; + ok_(__FILE__,line)(compare(expected, got), + "effect[%u].pDefaults[%u] float value %u: Expected %g, got %g\n", i, j, k, expected, got); + } + } + if (effects[i].NumDefaults > ARRAY_SIZE(params)) { + D3DXEFFECTDEFAULT *got_param = &effects[i].pDefaults[j]; + static const char *expected_name = "Texture0@Name"; + + ok_(__FILE__,line)(!strcmp(expected_name, got_param->pParamName), + "effect[%u].pDefaults[%u].pParamName: Expected '%s', got '%s'\n", i, j, + expected_name, got_param->pParamName); + ok_(__FILE__,line)(D3DXEDT_STRING == got_param->Type, + "effect[%u].pDefaults[%u].Type: Expected %u, got %u\n", i, j, + D3DXEDT_STRING, got_param->Type); + if (materials[i].pTextureFilename) { + ok_(__FILE__,line)(strlen(materials[i].pTextureFilename) + 1 == got_param->NumBytes, + "effect[%u] texture filename length: Expected %u, got %u\n", i, + (DWORD)strlen(materials[i].pTextureFilename) + 1, got_param->NumBytes); + ok_(__FILE__,line)(!strcmp(materials[i].pTextureFilename, got_param->pValue), + "effect[%u] texture filename: Expected '%s', got '%s'\n", i, + materials[i].pTextureFilename, (char*)got_param->pValue); + } + } + } +} + +static char *strdupA(const char *p) +{ + char *ret; + if (!p) return NULL; + ret = HeapAlloc(GetProcessHeap(), 0, strlen(p) + 1); + if (ret) strcpy(ret, p); + return ret; +} + +static HRESULT CALLBACK ID3DXAllocateHierarchyImpl_DestroyFrame(ID3DXAllocateHierarchy *iface, LPD3DXFRAME frame) +{ + TRACECALLBACK("ID3DXAllocateHierarchyImpl_DestroyFrame(%p, %p)\n", iface, frame); + if (frame) { + HeapFree(GetProcessHeap(), 0, frame->Name); + HeapFree(GetProcessHeap(), 0, frame); + } + return D3D_OK; +} + +static HRESULT CALLBACK ID3DXAllocateHierarchyImpl_CreateFrame(ID3DXAllocateHierarchy *iface, + const char *name, D3DXFRAME **new_frame) +{ + D3DXFRAME *frame; + + TRACECALLBACK("ID3DXAllocateHierarchyImpl_CreateFrame(%p, '%s', %p)\n", iface, name, new_frame); + frame = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*frame)); + if (!frame) + return E_OUTOFMEMORY; + if (name) { + frame->Name = strdupA(name); + if (!frame->Name) { + HeapFree(GetProcessHeap(), 0, frame); + return E_OUTOFMEMORY; + } + } + *new_frame = frame; + return D3D_OK; +} + +static HRESULT destroy_mesh_container(LPD3DXMESHCONTAINER mesh_container) +{ + int i; + + if (!mesh_container) + return D3D_OK; + HeapFree(GetProcessHeap(), 0, mesh_container->Name); + if (U(mesh_container->MeshData).pMesh) + IUnknown_Release(U(mesh_container->MeshData).pMesh); + if (mesh_container->pMaterials) { + for (i = 0; i < mesh_container->NumMaterials; i++) + HeapFree(GetProcessHeap(), 0, mesh_container->pMaterials[i].pTextureFilename); + HeapFree(GetProcessHeap(), 0, mesh_container->pMaterials); + } + if (mesh_container->pEffects) { + for (i = 0; i < mesh_container->NumMaterials; i++) { + HeapFree(GetProcessHeap(), 0, mesh_container->pEffects[i].pEffectFilename); + if (mesh_container->pEffects[i].pDefaults) { + int j; + for (j = 0; j < mesh_container->pEffects[i].NumDefaults; j++) { + HeapFree(GetProcessHeap(), 0, mesh_container->pEffects[i].pDefaults[j].pParamName); + HeapFree(GetProcessHeap(), 0, mesh_container->pEffects[i].pDefaults[j].pValue); + } + HeapFree(GetProcessHeap(), 0, mesh_container->pEffects[i].pDefaults); + } + } + HeapFree(GetProcessHeap(), 0, mesh_container->pEffects); + } + HeapFree(GetProcessHeap(), 0, mesh_container->pAdjacency); + if (mesh_container->pSkinInfo) + IUnknown_Release(mesh_container->pSkinInfo); + HeapFree(GetProcessHeap(), 0, mesh_container); + return D3D_OK; +} + +static HRESULT CALLBACK ID3DXAllocateHierarchyImpl_DestroyMeshContainer(ID3DXAllocateHierarchy *iface, LPD3DXMESHCONTAINER mesh_container) +{ + TRACECALLBACK("ID3DXAllocateHierarchyImpl_DestroyMeshContainer(%p, %p)\n", iface, mesh_container); + return destroy_mesh_container(mesh_container); +} + +static HRESULT CALLBACK ID3DXAllocateHierarchyImpl_CreateMeshContainer(ID3DXAllocateHierarchy *iface, + const char *name, const D3DXMESHDATA *mesh_data, const D3DXMATERIAL *materials, + const D3DXEFFECTINSTANCE *effects, DWORD num_materials, const DWORD *adjacency, + ID3DXSkinInfo *skin_info, D3DXMESHCONTAINER **new_mesh_container) +{ + LPD3DXMESHCONTAINER mesh_container = NULL; + int i; + + TRACECALLBACK("ID3DXAllocateHierarchyImpl_CreateMeshContainer(%p, '%s', %u, %p, %p, %p, %d, %p, %p, %p)\n", + iface, name, mesh_data->Type, U(*mesh_data).pMesh, materials, effects, + num_materials, adjacency, skin_info, *new_mesh_container); + + mesh_container = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*mesh_container)); + if (!mesh_container) + return E_OUTOFMEMORY; + + if (name) { + mesh_container->Name = strdupA(name); + if (!mesh_container->Name) + goto error; + } + + mesh_container->NumMaterials = num_materials; + if (num_materials) { + mesh_container->pMaterials = HeapAlloc(GetProcessHeap(), 0, num_materials * sizeof(*materials)); + if (!mesh_container->pMaterials) + goto error; + + memcpy(mesh_container->pMaterials, materials, num_materials * sizeof(*materials)); + for (i = 0; i < num_materials; i++) + mesh_container->pMaterials[i].pTextureFilename = NULL; + for (i = 0; i < num_materials; i++) { + if (materials[i].pTextureFilename) { + mesh_container->pMaterials[i].pTextureFilename = strdupA(materials[i].pTextureFilename); + if (!mesh_container->pMaterials[i].pTextureFilename) + goto error; + } + } + + mesh_container->pEffects = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, num_materials * sizeof(*effects)); + if (!mesh_container->pEffects) + goto error; + for (i = 0; i < num_materials; i++) { + int j; + const D3DXEFFECTINSTANCE *effect_src = &effects[i]; + D3DXEFFECTINSTANCE *effect_dest = &mesh_container->pEffects[i]; + + if (effect_src->pEffectFilename) { + effect_dest->pEffectFilename = strdupA(effect_src->pEffectFilename); + if (!effect_dest->pEffectFilename) + goto error; + } + effect_dest->pDefaults = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, + effect_src->NumDefaults * sizeof(*effect_src->pDefaults)); + if (!effect_dest->pDefaults) + goto error; + effect_dest->NumDefaults = effect_src->NumDefaults; + for (j = 0; j < effect_src->NumDefaults; j++) { + const D3DXEFFECTDEFAULT *default_src = &effect_src->pDefaults[j]; + D3DXEFFECTDEFAULT *default_dest = &effect_dest->pDefaults[j]; + + if (default_src->pParamName) { + default_dest->pParamName = strdupA(default_src->pParamName); + if (!default_dest->pParamName) + goto error; + } + default_dest->NumBytes = default_src->NumBytes; + default_dest->Type = default_src->Type; + default_dest->pValue = HeapAlloc(GetProcessHeap(), 0, default_src->NumBytes); + memcpy(default_dest->pValue, default_src->pValue, default_src->NumBytes); + } + } + } + + ok(adjacency != NULL, "Expected non-NULL adjacency, got NULL\n"); + if (adjacency) { + if (mesh_data->Type == D3DXMESHTYPE_MESH || mesh_data->Type == D3DXMESHTYPE_PMESH) { + ID3DXBaseMesh *basemesh = (ID3DXBaseMesh*)U(*mesh_data).pMesh; + DWORD num_faces = basemesh->lpVtbl->GetNumFaces(basemesh); + size_t size = num_faces * sizeof(DWORD) * 3; + mesh_container->pAdjacency = HeapAlloc(GetProcessHeap(), 0, size); + if (!mesh_container->pAdjacency) + goto error; + memcpy(mesh_container->pAdjacency, adjacency, size); + } else { + ok(mesh_data->Type == D3DXMESHTYPE_PATCHMESH, "Unknown mesh type %u\n", mesh_data->Type); + if (mesh_data->Type == D3DXMESHTYPE_PATCHMESH) + trace("FIXME: copying adjacency data for patch mesh not implemented\n"); + } + } + + memcpy(&mesh_container->MeshData, mesh_data, sizeof(*mesh_data)); + if (U(*mesh_data).pMesh) + IUnknown_AddRef(U(*mesh_data).pMesh); + if (skin_info) { + mesh_container->pSkinInfo = skin_info; + skin_info->lpVtbl->AddRef(skin_info); + } + *new_mesh_container = mesh_container; + + return S_OK; +error: + destroy_mesh_container(mesh_container); + return E_OUTOFMEMORY; +} + +static ID3DXAllocateHierarchyVtbl ID3DXAllocateHierarchyImpl_Vtbl = { + ID3DXAllocateHierarchyImpl_CreateFrame, + ID3DXAllocateHierarchyImpl_CreateMeshContainer, + ID3DXAllocateHierarchyImpl_DestroyFrame, + ID3DXAllocateHierarchyImpl_DestroyMeshContainer, +}; +static ID3DXAllocateHierarchy alloc_hier = { &ID3DXAllocateHierarchyImpl_Vtbl }; + +#define test_LoadMeshFromX(device, xfile_str, vertex_array, fvf, index_array, materials_array, check_adjacency) \ + test_LoadMeshFromX_(__LINE__, device, xfile_str, sizeof(xfile_str) - 1, vertex_array, ARRAY_SIZE(vertex_array), fvf, \ + index_array, ARRAY_SIZE(index_array), sizeof(*index_array), materials_array, ARRAY_SIZE(materials_array), \ + check_adjacency); +static void test_LoadMeshFromX_(int line, IDirect3DDevice9 *device, const char *xfile_str, size_t xfile_strlen, + const void *vertices, DWORD num_vertices, DWORD fvf, const void *indices, DWORD num_indices, size_t index_size, + const D3DXMATERIAL *expected_materials, DWORD expected_num_materials, BOOL check_adjacency) +{ + HRESULT hr; + ID3DXBuffer *materials = NULL; + ID3DXBuffer *effects = NULL; + ID3DXBuffer *adjacency = NULL; + ID3DXMesh *mesh = NULL; + DWORD num_materials = 0; + + /* Adjacency is not checked when the X file contains multiple meshes, + * since calling GenerateAdjacency on the merged mesh is not equivalent + * to calling GenerateAdjacency on the individual meshes and then merging + * the adjacency data. */ + hr = D3DXLoadMeshFromXInMemory(xfile_str, xfile_strlen, D3DXMESH_MANAGED, device, + check_adjacency ? &adjacency : NULL, &materials, &effects, &num_materials, &mesh); + ok_(__FILE__,line)(hr == D3D_OK, "Expected D3D_OK, got %#x\n", hr); + if (SUCCEEDED(hr)) { + D3DXMATERIAL *materials_ptr = materials ? ID3DXBuffer_GetBufferPointer(materials) : NULL; + D3DXEFFECTINSTANCE *effects_ptr = effects ? ID3DXBuffer_GetBufferPointer(effects) : NULL; + DWORD *adjacency_ptr = check_adjacency ? ID3DXBuffer_GetBufferPointer(adjacency) : NULL; + + check_vertex_buffer_(line, mesh, vertices, num_vertices, fvf); + check_index_buffer_(line, mesh, indices, num_indices, index_size); + check_materials_(line, materials_ptr, num_materials, expected_materials, expected_num_materials); + check_generated_effects_(line, materials_ptr, num_materials, effects_ptr); + if (check_adjacency) + check_generated_adjacency_(line, mesh, adjacency_ptr, 0.0f); + + if (materials) ID3DXBuffer_Release(materials); + if (effects) ID3DXBuffer_Release(effects); + if (adjacency) ID3DXBuffer_Release(adjacency); + IUnknown_Release(mesh); + } +} + +static void D3DXLoadMeshTest(void) +{ + static const char empty_xfile[] = "xof 0303txt 0032"; + /*________________________*/ + static const char simple_xfile[] = + "xof 0303txt 0032" + "Mesh {" + "3;" + "0.0; 0.0; 0.0;," + "0.0; 1.0; 0.0;," + "1.0; 1.0; 0.0;;" + "1;" + "3; 0, 1, 2;;" + "}"; + static const WORD simple_index_buffer[] = {0, 1, 2}; + static const D3DXVECTOR3 simple_vertex_buffer[] = { + {0.0, 0.0, 0.0}, {0.0, 1.0, 0.0}, {1.0, 1.0, 0.0} + }; + const DWORD simple_fvf = D3DFVF_XYZ; + static const char framed_xfile[] = + "xof 0303txt 0032" + "Frame {" + "Mesh { 3; 0.0; 0.0; 0.0;, 0.0; 1.0; 0.0;, 1.0; 1.0; 0.0;; 1; 3; 0, 1, 2;; }" + "FrameTransformMatrix {" /* translation (0.0, 0.0, 2.0) */ + "1.0, 0.0, 0.0, 0.0," + "0.0, 1.0, 0.0, 0.0," + "0.0, 0.0, 1.0, 0.0," + "0.0, 0.0, 2.0, 1.0;;" + "}" + "Mesh { 3; 0.0; 0.0; 0.0;, 0.0; 1.0; 0.0;, 2.0; 1.0; 0.0;; 1; 3; 0, 1, 2;; }" + "FrameTransformMatrix {" /* translation (0.0, 0.0, 3.0) */ + "1.0, 0.0, 0.0, 0.0," + "0.0, 1.0, 0.0, 0.0," + "0.0, 0.0, 1.0, 0.0," + "0.0, 0.0, 3.0, 1.0;;" + "}" + "Mesh { 3; 0.0; 0.0; 0.0;, 0.0; 1.0; 0.0;, 3.0; 1.0; 0.0;; 1; 3; 0, 1, 2;; }" + "}"; + static const WORD framed_index_buffer[] = { 0, 1, 2 }; + static const D3DXVECTOR3 framed_vertex_buffers[3][3] = { + {{0.0, 0.0, 0.0}, {0.0, 1.0, 0.0}, {1.0, 1.0, 0.0}}, + {{0.0, 0.0, 0.0}, {0.0, 1.0, 0.0}, {2.0, 1.0, 0.0}}, + {{0.0, 0.0, 0.0}, {0.0, 1.0, 0.0}, {3.0, 1.0, 0.0}}, + }; + static const WORD merged_index_buffer[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8 }; + /* frame transforms accumulates for D3DXLoadMeshFromX */ + static const D3DXVECTOR3 merged_vertex_buffer[] = { + {0.0, 0.0, 0.0}, {0.0, 1.0, 0.0}, {1.0, 1.0, 0.0}, + {0.0, 0.0, 2.0}, {0.0, 1.0, 2.0}, {2.0, 1.0, 2.0}, + {0.0, 0.0, 5.0}, {0.0, 1.0, 5.0}, {3.0, 1.0, 5.0}, + }; + const DWORD framed_fvf = D3DFVF_XYZ; + /*________________________*/ + static const char box_xfile[] = + "xof 0303txt 0032" + "Mesh {" + "8;" /* DWORD nVertices; */ + /* array Vector vertices[nVertices]; */ + "0.0; 0.0; 0.0;," + "0.0; 0.0; 1.0;," + "0.0; 1.0; 0.0;," + "0.0; 1.0; 1.0;," + "1.0; 0.0; 0.0;," + "1.0; 0.0; 1.0;," + "1.0; 1.0; 0.0;," + "1.0; 1.0; 1.0;;" + "6;" /* DWORD nFaces; */ + /* array MeshFace faces[nFaces]; */ + "4; 0, 1, 3, 2;," /* (left side) */ + "4; 2, 3, 7, 6;," /* (top side) */ + "4; 6, 7, 5, 4;," /* (right side) */ + "4; 1, 0, 4, 5;," /* (bottom side) */ + "4; 1, 5, 7, 3;," /* (back side) */ + "4; 0, 2, 6, 4;;" /* (front side) */ + "MeshNormals {" + "6;" /* DWORD nNormals; */ + /* array Vector normals[nNormals]; */ + "-1.0; 0.0; 0.0;," + "0.0; 1.0; 0.0;," + "1.0; 0.0; 0.0;," + "0.0; -1.0; 0.0;," + "0.0; 0.0; 1.0;," + "0.0; 0.0; -1.0;;" + "6;" /* DWORD nFaceNormals; */ + /* array MeshFace faceNormals[nFaceNormals]; */ + "4; 0, 0, 0, 0;," + "4; 1, 1, 1, 1;," + "4; 2, 2, 2, 2;," + "4; 3, 3, 3, 3;," + "4; 4, 4, 4, 4;," + "4; 5, 5, 5, 5;;" + "}" + "MeshMaterialList materials {" + "2;" /* DWORD nMaterials; */ + "6;" /* DWORD nFaceIndexes; */ + /* array DWORD faceIndexes[nFaceIndexes]; */ + "0, 0, 0, 1, 1, 1;;" + "Material {" + /* ColorRGBA faceColor; */ + "0.0; 0.0; 1.0; 1.0;;" + /* FLOAT power; */ + "0.5;" + /* ColorRGB specularColor; */ + "1.0; 1.0; 1.0;;" + /* ColorRGB emissiveColor; */ + "0.0; 0.0; 0.0;;" + "}" + "Material {" + /* ColorRGBA faceColor; */ + "1.0; 1.0; 1.0; 1.0;;" + /* FLOAT power; */ + "1.0;" + /* ColorRGB specularColor; */ + "1.0; 1.0; 1.0;;" + /* ColorRGB emissiveColor; */ + "0.0; 0.0; 0.0;;" + "TextureFilename { \"texture.jpg\"; }" + "}" + "}" + "MeshVertexColors {" + "8;" /* DWORD nVertexColors; */ + /* array IndexedColor vertexColors[nVertexColors]; */ + "0; 0.0; 0.0; 0.0; 0.0;;" + "1; 0.0; 0.0; 1.0; 0.1;;" + "2; 0.0; 1.0; 0.0; 0.2;;" + "3; 0.0; 1.0; 1.0; 0.3;;" + "4; 1.0; 0.0; 0.0; 0.4;;" + "5; 1.0; 0.0; 1.0; 0.5;;" + "6; 1.0; 1.0; 0.0; 0.6;;" + "7; 1.0; 1.0; 1.0; 0.7;;" + "}" + "MeshTextureCoords {" + "8;" /* DWORD nTextureCoords; */ + /* array Coords2d textureCoords[nTextureCoords]; */ + "0.0; 1.0;," + "1.0; 1.0;," + "0.0; 0.0;," + "1.0; 0.0;," + "1.0; 1.0;," + "0.0; 1.0;," + "1.0; 0.0;," + "0.0; 0.0;;" + "}" + "}"; + static const WORD box_index_buffer[] = { + 0, 1, 3, + 0, 3, 2, + 8, 9, 7, + 8, 7, 6, + 10, 11, 5, + 10, 5, 4, + 12, 13, 14, + 12, 14, 15, + 16, 17, 18, + 16, 18, 19, + 20, 21, 22, + 20, 22, 23, + }; + static const struct { + D3DXVECTOR3 position; + D3DXVECTOR3 normal; + D3DCOLOR diffuse; + D3DXVECTOR2 tex_coords; + } box_vertex_buffer[] = { + {{0.0, 0.0, 0.0}, {-1.0, 0.0, 0.0}, 0x00000000, {0.0, 1.0}}, + {{0.0, 0.0, 1.0}, {-1.0, 0.0, 0.0}, 0x1a0000ff, {1.0, 1.0}}, + {{0.0, 1.0, 0.0}, {-1.0, 0.0, 0.0}, 0x3300ff00, {0.0, 0.0}}, + {{0.0, 1.0, 1.0}, {-1.0, 0.0, 0.0}, 0x4d00ffff, {1.0, 0.0}}, + {{1.0, 0.0, 0.0}, {1.0, 0.0, 0.0}, 0x66ff0000, {1.0, 1.0}}, + {{1.0, 0.0, 1.0}, {1.0, 0.0, 0.0}, 0x80ff00ff, {0.0, 1.0}}, + {{1.0, 1.0, 0.0}, {0.0, 1.0, 0.0}, 0x99ffff00, {1.0, 0.0}}, + {{1.0, 1.0, 1.0}, {0.0, 1.0, 0.0}, 0xb3ffffff, {0.0, 0.0}}, + {{0.0, 1.0, 0.0}, {0.0, 1.0, 0.0}, 0x3300ff00, {0.0, 0.0}}, + {{0.0, 1.0, 1.0}, {0.0, 1.0, 0.0}, 0x4d00ffff, {1.0, 0.0}}, + {{1.0, 1.0, 0.0}, {1.0, 0.0, 0.0}, 0x99ffff00, {1.0, 0.0}}, + {{1.0, 1.0, 1.0}, {1.0, 0.0, 0.0}, 0xb3ffffff, {0.0, 0.0}}, + {{0.0, 0.0, 1.0}, {0.0, -1.0, 0.0}, 0x1a0000ff, {1.0, 1.0}}, + {{0.0, 0.0, 0.0}, {0.0, -1.0, 0.0}, 0x00000000, {0.0, 1.0}}, + {{1.0, 0.0, 0.0}, {0.0, -1.0, 0.0}, 0x66ff0000, {1.0, 1.0}}, + {{1.0, 0.0, 1.0}, {0.0, -1.0, 0.0}, 0x80ff00ff, {0.0, 1.0}}, + {{0.0, 0.0, 1.0}, {0.0, 0.0, 1.0}, 0x1a0000ff, {1.0, 1.0}}, + {{1.0, 0.0, 1.0}, {0.0, 0.0, 1.0}, 0x80ff00ff, {0.0, 1.0}}, + {{1.0, 1.0, 1.0}, {0.0, 0.0, 1.0}, 0xb3ffffff, {0.0, 0.0}}, + {{0.0, 1.0, 1.0}, {0.0, 0.0, 1.0}, 0x4d00ffff, {1.0, 0.0}}, + {{0.0, 0.0, 0.0}, {0.0, 0.0, -1.0}, 0x00000000, {0.0, 1.0}}, + {{0.0, 1.0, 0.0}, {0.0, 0.0, -1.0}, 0x3300ff00, {0.0, 0.0}}, + {{1.0, 1.0, 0.0}, {0.0, 0.0, -1.0}, 0x99ffff00, {1.0, 0.0}}, + {{1.0, 0.0, 0.0}, {0.0, 0.0, -1.0}, 0x66ff0000, {1.0, 1.0}}, + }; + static const D3DXMATERIAL box_materials[] = { + { + { + {0.0, 0.0, 1.0, 1.0}, /* Diffuse */ + {0.0, 0.0, 0.0, 1.0}, /* Ambient */ + {1.0, 1.0, 1.0, 1.0}, /* Specular */ + {0.0, 0.0, 0.0, 1.0}, /* Emissive */ + 0.5, /* Power */ + }, + NULL, /* pTextureFilename */ + }, + { + { + {1.0, 1.0, 1.0, 1.0}, /* Diffuse */ + {0.0, 0.0, 0.0, 1.0}, /* Ambient */ + {1.0, 1.0, 1.0, 1.0}, /* Specular */ + {0.0, 0.0, 0.0, 1.0}, /* Emissive */ + 1.0, /* Power */ + }, + (char *)"texture.jpg", /* pTextureFilename */ + }, + }; + static const char box_anim_xfile[] = + "xof 0303txt 0032" + "Mesh CubeMesh {" + "8;" /* DWORD nVertices; */ + /* array Vector vertices[nVertices]; */ + "0.0; 0.0; 0.0;," + "0.0; 0.0; 1.0;," + "0.0; 1.0; 0.0;," + "0.0; 1.0; 1.0;," + "1.0; 0.0; 0.0;," + "1.0; 0.0; 1.0;," + "1.0; 1.0; 0.0;," + "1.0; 1.0; 1.0;;" + "6;" /* DWORD nFaces; */ + /* array MeshFace faces[nFaces]; */ + "4; 0, 1, 3, 2;," /* left side */ + "4; 2, 3, 7, 6;," /* top side */ + "4; 6, 7, 5, 4;," /* right side */ + "4; 1, 0, 4, 5;," /* bottom side */ + "4; 1, 5, 7, 3;," /* back side */ + "4; 0, 2, 6, 4;;" /* front side */ + "MeshNormals {" + "6;" /* DWORD nNormals; */ + /* array Vector normals[nNormals]; */ + "-1.0; 0.0; 0.0;," + "0.0; 1.0; 0.0;," + "1.0; 0.0; 0.0;," + "0.0; -1.0; 0.0;," + "0.0; 0.0; 1.0;," + "0.0; 0.0; -1.0;;" + "6;" /* DWORD nFaceNormals; */ + /* array MeshFace faceNormals[nFaceNormals]; */ + "4; 0, 0, 0, 0;," + "4; 1, 1, 1, 1;," + "4; 2, 2, 2, 2;," + "4; 3, 3, 3, 3;," + "4; 4, 4, 4, 4;," + "4; 5, 5, 5, 5;;" + "}" + "MeshMaterialList materials {" + "2;" /* DWORD nMaterials; */ + "6;" /* DWORD nFaceIndexes; */ + /* array DWORD faceIndexes[nFaceIndexes]; */ + "0, 0, 0, 1, 1, 1;;" + "Material {" + /* ColorRGBA faceColor; */ + "0.0; 0.0; 1.0; 1.0;;" + /* FLOAT power; */ + "0.5;" + /* ColorRGB specularColor; */ + "1.0; 1.0; 1.0;;" + /* ColorRGB emissiveColor; */ + "0.0; 0.0; 0.0;;" + "}" + "Material {" + /* ColorRGBA faceColor; */ + "1.0; 1.0; 1.0; 1.0;;" + /* FLOAT power; */ + "1.0;" + /* ColorRGB specularColor; */ + "1.0; 1.0; 1.0;;" + /* ColorRGB emissiveColor; */ + "0.0; 0.0; 0.0;;" + "TextureFilename { \"texture.jpg\"; }" + "}" + "}" + "MeshVertexColors {" + "8;" /* DWORD nVertexColors; */ + /* array IndexedColor vertexColors[nVertexColors]; */ + "0; 0.0; 0.0; 0.0; 0.0;;" + "1; 0.0; 0.0; 1.0; 0.1;;" + "2; 0.0; 1.0; 0.0; 0.2;;" + "3; 0.0; 1.0; 1.0; 0.3;;" + "4; 1.0; 0.0; 0.0; 0.4;;" + "5; 1.0; 0.0; 1.0; 0.5;;" + "6; 1.0; 1.0; 0.0; 0.6;;" + "7; 1.0; 1.0; 1.0; 0.7;;" + "}" + "MeshTextureCoords {" + "8;" /* DWORD nTextureCoords; */ + /* array Coords2d textureCoords[nTextureCoords]; */ + "0.0; 1.0;," + "1.0; 1.0;," + "0.0; 0.0;," + "1.0; 0.0;," + "1.0; 1.0;," + "0.0; 1.0;," + "1.0; 0.0;," + "0.0; 0.0;;" + "}" + "}" + "Frame CubeFrame {" + "FrameTransformMatrix {" + /* Matrix4x4 frameMatrix; */ + "1.0, 0.0, 0.0, 0.0," + "0.0, 1.0, 0.0, 0.0," + "0.0, 0.0, 1.0, 0.0," + "0.0, 0.0, 0.0, 1.0;;" + "}" + "{CubeMesh}" + "}" + "AnimationSet AnimationSet0 {" + "Animation Animation0 {" + "{CubeFrame}" + "AnimationKey {" + "2;" /* DWORD keyType; */ + "9;" /* DWORD nKeys; */ + /* array TimedFloatKeys keys[nKeys]; */ + "10; 3; -100.0, 0.0, 0.0;;," + "20; 3; -75.0, 0.0, 0.0;;," + "30; 3; -50.0, 0.0, 0.0;;," + "40; 3; -25.5, 0.0, 0.0;;," + "50; 3; 0.0, 0.0, 0.0;;," + "60; 3; 25.5, 0.0, 0.0;;," + "70; 3; 50.0, 0.0, 0.0;;," + "80; 3; 75.5, 0.0, 0.0;;," + "90; 3; 100.0, 0.0, 0.0;;;" + "}" + "}" + "}"; + + const DWORD box_fvf = D3DFVF_XYZ | D3DFVF_NORMAL | D3DFVF_DIFFUSE | D3DFVF_TEX1; + /*________________________*/ + static const D3DXMATERIAL default_materials[] = { + { + { + {0.5, 0.5, 0.5, 0.0}, /* Diffuse */ + {0.0, 0.0, 0.0, 0.0}, /* Ambient */ + {0.5, 0.5, 0.5, 0.0}, /* Specular */ + {0.0, 0.0, 0.0, 0.0}, /* Emissive */ + 0.0, /* Power */ + }, + NULL, /* pTextureFilename */ + } + }; + HRESULT hr; + IDirect3DDevice9 *device = NULL; + ID3DXMesh *mesh = NULL; + D3DXFRAME *frame_hier = NULL; + D3DXMATRIX transform; + struct test_context *test_context; + ID3DXAnimationController *controller; + + if (!(test_context = new_test_context())) + { + skip("Couldn't create test context\n"); + return; + } + device = test_context->device; + + hr = D3DXLoadMeshHierarchyFromXInMemory(NULL, sizeof(simple_xfile) - 1, + D3DXMESH_MANAGED, device, &alloc_hier, NULL, &frame_hier, NULL); + ok(hr == D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, got %#x\n", hr); + + hr = D3DXLoadMeshHierarchyFromXInMemory(simple_xfile, 0, + D3DXMESH_MANAGED, device, &alloc_hier, NULL, &frame_hier, NULL); + ok(hr == D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, got %#x\n", hr); + + hr = D3DXLoadMeshHierarchyFromXInMemory(simple_xfile, sizeof(simple_xfile) - 1, + D3DXMESH_MANAGED, NULL, &alloc_hier, NULL, &frame_hier, NULL); + ok(hr == D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, got %#x\n", hr); + + hr = D3DXLoadMeshHierarchyFromXInMemory(simple_xfile, sizeof(simple_xfile) - 1, + D3DXMESH_MANAGED, device, NULL, NULL, &frame_hier, NULL); + ok(hr == D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, got %#x\n", hr); + + hr = D3DXLoadMeshHierarchyFromXInMemory(empty_xfile, sizeof(empty_xfile) - 1, + D3DXMESH_MANAGED, device, &alloc_hier, NULL, &frame_hier, NULL); + ok(hr == E_FAIL, "Expected E_FAIL, got %#x\n", hr); + + hr = D3DXLoadMeshHierarchyFromXInMemory(simple_xfile, sizeof(simple_xfile) - 1, + D3DXMESH_MANAGED, device, &alloc_hier, NULL, NULL, NULL); + ok(hr == D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, got %#x\n", hr); + + hr = D3DXLoadMeshHierarchyFromXInMemory(simple_xfile, sizeof(simple_xfile) - 1, + D3DXMESH_MANAGED, device, &alloc_hier, NULL, &frame_hier, NULL); + ok(hr == D3D_OK, "Expected D3D_OK, got %#x\n", hr); + if (SUCCEEDED(hr)) { + D3DXMESHCONTAINER *container = frame_hier->pMeshContainer; + + ok(frame_hier->Name == NULL, "Expected NULL, got '%s'\n", frame_hier->Name); + D3DXMatrixIdentity(&transform); + check_matrix(&frame_hier->TransformationMatrix, &transform); + + ok(!strcmp(container->Name, ""), "Expected '', got '%s'\n", container->Name); + ok(container->MeshData.Type == D3DXMESHTYPE_MESH, "Expected %d, got %d\n", + D3DXMESHTYPE_MESH, container->MeshData.Type); + mesh = U(container->MeshData).pMesh; + check_vertex_buffer(mesh, simple_vertex_buffer, ARRAY_SIZE(simple_vertex_buffer), simple_fvf); + check_index_buffer(mesh, simple_index_buffer, ARRAY_SIZE(simple_index_buffer), sizeof(*simple_index_buffer)); + check_materials(container->pMaterials, container->NumMaterials, NULL, 0); + check_generated_effects(container->pMaterials, container->NumMaterials, container->pEffects); + check_generated_adjacency(mesh, container->pAdjacency, 0.0f); + hr = D3DXFrameDestroy(frame_hier, &alloc_hier); + ok(hr == D3D_OK, "Expected D3D_OK, got %#x\n", hr); + frame_hier = NULL; + } + + controller = (ID3DXAnimationController *)0xdeadbeef; + hr = D3DXLoadMeshHierarchyFromXInMemory(box_anim_xfile, sizeof(box_anim_xfile) - 1, + D3DXMESH_MANAGED, device, &alloc_hier, NULL, &frame_hier, &controller); + todo_wine ok(hr == D3D_OK, "Expected D3D_OK, got %#x.\n", hr); + if (SUCCEEDED(hr)) + { + ok(controller != NULL, "Animation Controller NULL.\n"); + + hr = D3DXFrameDestroy(frame_hier, &alloc_hier); + ok(hr == D3D_OK, "Expected D3D_OK, got %#x.\n", hr); + if (controller) + controller->lpVtbl->Release(controller); + + frame_hier = NULL; + } + + controller = (ID3DXAnimationController *)0xdeadbeef; + hr = D3DXLoadMeshHierarchyFromXInMemory(box_xfile, sizeof(box_xfile) - 1, + D3DXMESH_MANAGED, device, &alloc_hier, NULL, &frame_hier, &controller); + ok(hr == D3D_OK, "Expected D3D_OK, got %#x\n", hr); + if (SUCCEEDED(hr)) + { + D3DXMESHCONTAINER *container = frame_hier->pMeshContainer; + + ok(!controller, "Animation Controller returned.\n"); + ok(frame_hier->Name == NULL, "Expected NULL, got '%s'\n", frame_hier->Name); + D3DXMatrixIdentity(&transform); + check_matrix(&frame_hier->TransformationMatrix, &transform); + + ok(!strcmp(container->Name, ""), "Expected '', got '%s'\n", container->Name); + ok(container->MeshData.Type == D3DXMESHTYPE_MESH, "Expected %d, got %d\n", + D3DXMESHTYPE_MESH, container->MeshData.Type); + mesh = U(container->MeshData).pMesh; + check_vertex_buffer(mesh, box_vertex_buffer, ARRAY_SIZE(box_vertex_buffer), box_fvf); + check_index_buffer(mesh, box_index_buffer, ARRAY_SIZE(box_index_buffer), sizeof(*box_index_buffer)); + check_materials(container->pMaterials, container->NumMaterials, box_materials, ARRAY_SIZE(box_materials)); + check_generated_effects(container->pMaterials, container->NumMaterials, container->pEffects); + check_generated_adjacency(mesh, container->pAdjacency, 0.0f); + hr = D3DXFrameDestroy(frame_hier, &alloc_hier); + ok(hr == D3D_OK, "Expected D3D_OK, got %#x\n", hr); + frame_hier = NULL; + } + + hr = D3DXLoadMeshHierarchyFromXInMemory(framed_xfile, sizeof(framed_xfile) - 1, + D3DXMESH_MANAGED, device, &alloc_hier, NULL, &frame_hier, NULL); + ok(hr == D3D_OK, "Expected D3D_OK, got %#x\n", hr); + if (SUCCEEDED(hr)) { + D3DXMESHCONTAINER *container = frame_hier->pMeshContainer; + int i; + + ok(!strcmp(frame_hier->Name, ""), "Expected '', got '%s'\n", frame_hier->Name); + /* last frame transform replaces the first */ + D3DXMatrixIdentity(&transform); + U(transform).m[3][2] = 3.0; + check_matrix(&frame_hier->TransformationMatrix, &transform); + + for (i = 0; i < 3; i++) { + ok(!strcmp(container->Name, ""), "Expected '', got '%s'\n", container->Name); + ok(container->MeshData.Type == D3DXMESHTYPE_MESH, "Expected %d, got %d\n", + D3DXMESHTYPE_MESH, container->MeshData.Type); + mesh = U(container->MeshData).pMesh; + check_vertex_buffer(mesh, framed_vertex_buffers[i], ARRAY_SIZE(framed_vertex_buffers[0]), framed_fvf); + check_index_buffer(mesh, framed_index_buffer, ARRAY_SIZE(framed_index_buffer), sizeof(*framed_index_buffer)); + check_materials(container->pMaterials, container->NumMaterials, NULL, 0); + check_generated_effects(container->pMaterials, container->NumMaterials, container->pEffects); + check_generated_adjacency(mesh, container->pAdjacency, 0.0f); + container = container->pNextMeshContainer; + } + ok(container == NULL, "Expected NULL, got %p\n", container); + hr = D3DXFrameDestroy(frame_hier, &alloc_hier); + ok(hr == D3D_OK, "Expected D3D_OK, got %#x\n", hr); + frame_hier = NULL; + } + + + hr = D3DXLoadMeshFromXInMemory(NULL, 0, D3DXMESH_MANAGED, + device, NULL, NULL, NULL, NULL, &mesh); + ok(hr == D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, got %#x\n", hr); + + hr = D3DXLoadMeshFromXInMemory(NULL, sizeof(simple_xfile) - 1, D3DXMESH_MANAGED, + device, NULL, NULL, NULL, NULL, &mesh); + ok(hr == D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, got %#x\n", hr); + + hr = D3DXLoadMeshFromXInMemory(simple_xfile, 0, D3DXMESH_MANAGED, + device, NULL, NULL, NULL, NULL, &mesh); + ok(hr == D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, got %#x\n", hr); + + hr = D3DXLoadMeshFromXInMemory(simple_xfile, sizeof(simple_xfile) - 1, D3DXMESH_MANAGED, + device, NULL, NULL, NULL, NULL, NULL); + ok(hr == D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, got %#x\n", hr); + + hr = D3DXLoadMeshFromXInMemory(simple_xfile, sizeof(simple_xfile) - 1, D3DXMESH_MANAGED, + NULL, NULL, NULL, NULL, NULL, &mesh); + ok(hr == D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, got %#x\n", hr); + + hr = D3DXLoadMeshFromXInMemory(empty_xfile, sizeof(empty_xfile) - 1, D3DXMESH_MANAGED, + device, NULL, NULL, NULL, NULL, &mesh); + ok(hr == E_FAIL, "Expected E_FAIL, got %#x\n", hr); + + hr = D3DXLoadMeshFromXInMemory(simple_xfile, sizeof(simple_xfile) - 1, D3DXMESH_MANAGED, + device, NULL, NULL, NULL, NULL, &mesh); + ok(hr == D3D_OK, "Expected D3D_OK, got %#x\n", hr); + if (SUCCEEDED(hr)) + IUnknown_Release(mesh); + + test_LoadMeshFromX(device, simple_xfile, simple_vertex_buffer, simple_fvf, simple_index_buffer, default_materials, TRUE); + test_LoadMeshFromX(device, box_xfile, box_vertex_buffer, box_fvf, box_index_buffer, box_materials, TRUE); + test_LoadMeshFromX(device, framed_xfile, merged_vertex_buffer, framed_fvf, merged_index_buffer, default_materials, FALSE); + + free_test_context(test_context); +} + +static BOOL compute_box(struct mesh *mesh, float width, float height, float depth) +{ + unsigned int i, face; + static const D3DXVECTOR3 unit_box[] = + { + {-1.0f, -1.0f, -1.0f}, {-1.0f, -1.0f, 1.0f}, {-1.0f, 1.0f, 1.0f}, {-1.0f, 1.0f, -1.0f}, + {-1.0f, 1.0f, -1.0f}, {-1.0f, 1.0f, 1.0f}, { 1.0f, 1.0f, 1.0f}, { 1.0f, 1.0f, -1.0f}, + { 1.0f, 1.0f, -1.0f}, { 1.0f, 1.0f, 1.0f}, { 1.0f, -1.0f, 1.0f}, { 1.0f, -1.0f, -1.0f}, + {-1.0f, -1.0f, 1.0f}, {-1.0f, -1.0f, -1.0f}, { 1.0f, -1.0f, -1.0f}, { 1.0f, -1.0f, 1.0f}, + {-1.0f, -1.0f, 1.0f}, { 1.0f, -1.0f, 1.0f}, { 1.0f, 1.0f, 1.0f}, {-1.0f, 1.0f, 1.0f}, + {-1.0f, -1.0f, -1.0f}, {-1.0f, 1.0f, -1.0f}, { 1.0f, 1.0f, -1.0f}, { 1.0f, -1.0f, -1.0f} + }; + static const D3DXVECTOR3 normals[] = + { + {-1.0f, 0.0f, 0.0f}, { 0.0f, 1.0f, 0.0f}, { 1.0f, 0.0f, 0.0f}, + { 0.0f, -1.0f, 0.0f}, { 0.0f, 0.0f, 1.0f}, { 0.0f, 0.0f, -1.0f} + }; + + if (!new_mesh(mesh, 24, 12)) + { + return FALSE; + } + + width /= 2.0f; + height /= 2.0f; + depth /= 2.0f; + + for (i = 0; i < 24; i++) + { + mesh->vertices[i].position.x = width * unit_box[i].x; + mesh->vertices[i].position.y = height * unit_box[i].y; + mesh->vertices[i].position.z = depth * unit_box[i].z; + mesh->vertices[i].normal.x = normals[i / 4].x; + mesh->vertices[i].normal.y = normals[i / 4].y; + mesh->vertices[i].normal.z = normals[i / 4].z; + } + + face = 0; + for (i = 0; i < 12; i++) + { + mesh->faces[i][0] = face++; + mesh->faces[i][1] = face++; + mesh->faces[i][2] = (i % 2) ? face - 4 : face; + } + + return TRUE; +} + +static void test_box(IDirect3DDevice9 *device, float width, float height, float depth) +{ + HRESULT hr; + ID3DXMesh *box; + struct mesh mesh; + char name[256]; + + hr = D3DXCreateBox(device, width, height, depth, &box, NULL); + ok(hr == D3D_OK, "Got result %x, expected 0 (D3D_OK)\n", hr); + if (hr != D3D_OK) + { + skip("Couldn't create box\n"); + return; + } + + if (!compute_box(&mesh, width, height, depth)) + { + skip("Couldn't create mesh\n"); + box->lpVtbl->Release(box); + return; + } + + mesh.fvf = D3DFVF_XYZ | D3DFVF_NORMAL; + + sprintf(name, "box (%g, %g, %g)", width, height, depth); + compare_mesh(name, box, &mesh); + + free_mesh(&mesh); + + box->lpVtbl->Release(box); +} +static void D3DXCreateBoxTest(void) +{ + HRESULT hr; + IDirect3DDevice9* device; + ID3DXMesh* box; + ID3DXBuffer* ppBuffer; + DWORD *buffer; + static const DWORD adjacency[36]= + {6, 9, 1, 2, 10, 0, + 1, 9, 3, 4, 10, 2, + 3, 8, 5, 7, 11, 4, + 0, 11, 7, 5, 8, 6, + 7, 4, 9, 2, 0, 8, + 1, 3, 11, 5, 6, 10}; + unsigned int i; + struct test_context *test_context; + + if (!(test_context = new_test_context())) + { + skip("Couldn't create test context\n"); + return; + } + device = test_context->device; + + hr = D3DXCreateBox(device,2.0f,20.0f,4.9f,NULL, &ppBuffer); + ok(hr==D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, received %#x\n", hr); + + hr = D3DXCreateBox(NULL,22.0f,20.0f,4.9f,&box, &ppBuffer); + ok(hr==D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, received %#x\n", hr); + + hr = D3DXCreateBox(device,-2.0f,20.0f,4.9f,&box, &ppBuffer); + ok(hr==D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, received %#x\n", hr); + + hr = D3DXCreateBox(device,22.0f,-20.0f,4.9f,&box, &ppBuffer); + ok(hr==D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, received %#x\n", hr); + + hr = D3DXCreateBox(device,22.0f,20.0f,-4.9f,&box, &ppBuffer); + ok(hr==D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, received %#x\n", hr); + + ppBuffer = NULL; + hr = D3DXCreateBox(device,10.9f,20.0f,4.9f,&box, &ppBuffer); + ok(hr==D3D_OK, "Expected D3D_OK, received %#x\n", hr); + + buffer = ID3DXBuffer_GetBufferPointer(ppBuffer); + for(i=0; i<36; i++) + ok(adjacency[i]==buffer[i], "expected adjacency %d: %#x, received %#x\n",i,adjacency[i], buffer[i]); + + box->lpVtbl->Release(box); + ID3DXBuffer_Release(ppBuffer); + + test_box(device, 10.9f, 20.0f, 4.9f); + + free_test_context(test_context); +} + +static BOOL compute_polygon(struct mesh *mesh, float length, unsigned int sides) +{ + unsigned int i; + float angle, scale; + + if (!new_mesh(mesh, sides + 1, sides)) + return FALSE; + + angle = D3DX_PI / sides; + scale = 0.5f * length / sinf(angle); + angle *= 2.0f; + + mesh->vertices[0].position.x = 0.0f; + mesh->vertices[0].position.y = 0.0f; + mesh->vertices[0].position.z = 0.0f; + mesh->vertices[0].normal.x = 0.0f; + mesh->vertices[0].normal.y = 0.0f; + mesh->vertices[0].normal.z = 1.0f; + + for (i = 0; i < sides; ++i) + { + mesh->vertices[i + 1].position.x = cosf(angle * i) * scale; + mesh->vertices[i + 1].position.y = sinf(angle * i) * scale; + mesh->vertices[i + 1].position.z = 0.0f; + mesh->vertices[i + 1].normal.x = 0.0f; + mesh->vertices[i + 1].normal.y = 0.0f; + mesh->vertices[i + 1].normal.z = 1.0f; + + mesh->faces[i][0] = 0; + mesh->faces[i][1] = i + 1; + mesh->faces[i][2] = i + 2; + } + + mesh->faces[sides - 1][2] = 1; + + return TRUE; +} + +static void test_polygon(IDirect3DDevice9 *device, float length, unsigned int sides) +{ + HRESULT hr; + ID3DXMesh *polygon; + struct mesh mesh; + char name[64]; + + hr = D3DXCreatePolygon(device, length, sides, &polygon, NULL); + ok(hr == D3D_OK, "Got result %x, expected 0 (D3D_OK)\n", hr); + if (hr != D3D_OK) + { + skip("Couldn't create polygon\n"); + return; + } + + if (!compute_polygon(&mesh, length, sides)) + { + skip("Couldn't create mesh\n"); + polygon->lpVtbl->Release(polygon); + return; + } + + mesh.fvf = D3DFVF_XYZ | D3DFVF_NORMAL; + + sprintf(name, "polygon (%g, %u)", length, sides); + compare_mesh(name, polygon, &mesh); + + free_mesh(&mesh); + + polygon->lpVtbl->Release(polygon); +} + +static void D3DXCreatePolygonTest(void) +{ + HRESULT hr; + IDirect3DDevice9 *device; + ID3DXMesh *polygon; + ID3DXBuffer *adjacency; + DWORD (*buffer)[3], buffer_size; + unsigned int i; + struct test_context *test_context; + + if (!(test_context = new_test_context())) + { + skip("Couldn't create test context\n"); + return; + } + device = test_context->device; + + hr = D3DXCreatePolygon(device, 2.0f, 11, NULL, &adjacency); + ok(hr == D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, received %#x\n", hr); + + hr = D3DXCreatePolygon(NULL, 2.0f, 11, &polygon, &adjacency); + ok(hr == D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, received %#x\n", hr); + + hr = D3DXCreatePolygon(device, -2.0f, 11, &polygon, &adjacency); + ok(hr == D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, received %#x\n", hr); + + polygon = (void *)0xdeadbeef; + adjacency = (void *)0xdeadbeef; + hr = D3DXCreatePolygon(device, 2.0f, 0, &polygon, &adjacency); + ok(hr == D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, received %#x\n", hr); + ok(polygon == (void *)0xdeadbeef, "Polygon was changed to %p\n", polygon); + ok(adjacency == (void *)0xdeadbeef, "Adjacency was changed to %p\n", adjacency); + + hr = D3DXCreatePolygon(device, 2.0f, 2, &polygon, &adjacency); + ok(hr == D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, received %#x\n", hr); + + adjacency = NULL; + hr = D3DXCreatePolygon(device, 3.0f, 11, &polygon, &adjacency); + ok(hr == D3D_OK, "Expected D3D_OK, received %#x\n", hr); + + buffer_size = ID3DXBuffer_GetBufferSize(adjacency); + ok(buffer_size == 33 * sizeof(DWORD), "Wrong adjacency buffer size %u\n", buffer_size); + + buffer = ID3DXBuffer_GetBufferPointer(adjacency); + for (i = 0; i < 11; ++i) + { + ok(buffer[i][0] == (i + 10) % 11, "Wrong adjacency[%d][0] = %u\n", i, buffer[i][0]); + ok(buffer[i][1] == ~0U, "Wrong adjacency[%d][1] = %u\n", i, buffer[i][1]); + ok(buffer[i][2] == (i + 1) % 11, "Wrong adjacency[%d][2] = %u\n", i, buffer[i][2]); + } + + polygon->lpVtbl->Release(polygon); + ID3DXBuffer_Release(adjacency); + + test_polygon(device, 2.0f, 3); + test_polygon(device, 10.0f, 3); + test_polygon(device, 10.0f, 5); + test_polygon(device, 10.0f, 10); + test_polygon(device, 20.0f, 10); + test_polygon(device, 20.0f, 32000); + + free_test_context(test_context); +} + +struct sincos_table +{ + float *sin; + float *cos; +}; + +static void free_sincos_table(struct sincos_table *sincos_table) +{ + HeapFree(GetProcessHeap(), 0, sincos_table->cos); + HeapFree(GetProcessHeap(), 0, sincos_table->sin); +} + +/* pre compute sine and cosine tables; caller must free */ +static BOOL compute_sincos_table(struct sincos_table *sincos_table, float angle_start, float angle_step, int n) +{ + float angle; + int i; + + sincos_table->sin = HeapAlloc(GetProcessHeap(), 0, n * sizeof(*sincos_table->sin)); + if (!sincos_table->sin) + { + return FALSE; + } + sincos_table->cos = HeapAlloc(GetProcessHeap(), 0, n * sizeof(*sincos_table->cos)); + if (!sincos_table->cos) + { + HeapFree(GetProcessHeap(), 0, sincos_table->sin); + return FALSE; + } + + angle = angle_start; + for (i = 0; i < n; i++) + { + sincos_table->sin[i] = sin(angle); + sincos_table->cos[i] = cos(angle); + angle += angle_step; + } + + return TRUE; +} + +static WORD vertex_index(UINT slices, int slice, int stack) +{ + return stack*slices+slice+1; +} + +/* slices = subdivisions along xy plane, stacks = subdivisions along z axis */ +static BOOL compute_sphere(struct mesh *mesh, FLOAT radius, UINT slices, UINT stacks) +{ + float theta_step, theta_start; + struct sincos_table theta; + float phi_step, phi_start; + struct sincos_table phi; + DWORD number_of_vertices, number_of_faces; + DWORD vertex, face; + int slice, stack; + + /* theta = angle on xy plane wrt x axis */ + theta_step = D3DX_PI / stacks; + theta_start = theta_step; + + /* phi = angle on xz plane wrt z axis */ + phi_step = -2 * D3DX_PI / slices; + phi_start = D3DX_PI / 2; + + if (!compute_sincos_table(&theta, theta_start, theta_step, stacks)) + { + return FALSE; + } + if (!compute_sincos_table(&phi, phi_start, phi_step, slices)) + { + free_sincos_table(&theta); + return FALSE; + } + + number_of_vertices = 2 + slices * (stacks-1); + number_of_faces = 2 * slices + (stacks - 2) * (2 * slices); + + if (!new_mesh(mesh, number_of_vertices, number_of_faces)) + { + free_sincos_table(&phi); + free_sincos_table(&theta); + return FALSE; + } + + vertex = 0; + face = 0; + + mesh->vertices[vertex].normal.x = 0.0f; + mesh->vertices[vertex].normal.y = 0.0f; + mesh->vertices[vertex].normal.z = 1.0f; + mesh->vertices[vertex].position.x = 0.0f; + mesh->vertices[vertex].position.y = 0.0f; + mesh->vertices[vertex].position.z = radius; + vertex++; + + for (stack = 0; stack < stacks - 1; stack++) + { + for (slice = 0; slice < slices; slice++) + { + mesh->vertices[vertex].normal.x = theta.sin[stack] * phi.cos[slice]; + mesh->vertices[vertex].normal.y = theta.sin[stack] * phi.sin[slice]; + mesh->vertices[vertex].normal.z = theta.cos[stack]; + mesh->vertices[vertex].position.x = radius * theta.sin[stack] * phi.cos[slice]; + mesh->vertices[vertex].position.y = radius * theta.sin[stack] * phi.sin[slice]; + mesh->vertices[vertex].position.z = radius * theta.cos[stack]; + vertex++; + + if (slice > 0) + { + if (stack == 0) + { + /* top stack is triangle fan */ + mesh->faces[face][0] = 0; + mesh->faces[face][1] = slice + 1; + mesh->faces[face][2] = slice; + face++; + } + else + { + /* stacks in between top and bottom are quad strips */ + mesh->faces[face][0] = vertex_index(slices, slice-1, stack-1); + mesh->faces[face][1] = vertex_index(slices, slice, stack-1); + mesh->faces[face][2] = vertex_index(slices, slice-1, stack); + face++; + + mesh->faces[face][0] = vertex_index(slices, slice, stack-1); + mesh->faces[face][1] = vertex_index(slices, slice, stack); + mesh->faces[face][2] = vertex_index(slices, slice-1, stack); + face++; + } + } + } + + if (stack == 0) + { + mesh->faces[face][0] = 0; + mesh->faces[face][1] = 1; + mesh->faces[face][2] = slice; + face++; + } + else + { + mesh->faces[face][0] = vertex_index(slices, slice-1, stack-1); + mesh->faces[face][1] = vertex_index(slices, 0, stack-1); + mesh->faces[face][2] = vertex_index(slices, slice-1, stack); + face++; + + mesh->faces[face][0] = vertex_index(slices, 0, stack-1); + mesh->faces[face][1] = vertex_index(slices, 0, stack); + mesh->faces[face][2] = vertex_index(slices, slice-1, stack); + face++; + } + } + + mesh->vertices[vertex].position.x = 0.0f; + mesh->vertices[vertex].position.y = 0.0f; + mesh->vertices[vertex].position.z = -radius; + mesh->vertices[vertex].normal.x = 0.0f; + mesh->vertices[vertex].normal.y = 0.0f; + mesh->vertices[vertex].normal.z = -1.0f; + + /* bottom stack is triangle fan */ + for (slice = 1; slice < slices; slice++) + { + mesh->faces[face][0] = vertex_index(slices, slice-1, stack-1); + mesh->faces[face][1] = vertex_index(slices, slice, stack-1); + mesh->faces[face][2] = vertex; + face++; + } + + mesh->faces[face][0] = vertex_index(slices, slice-1, stack-1); + mesh->faces[face][1] = vertex_index(slices, 0, stack-1); + mesh->faces[face][2] = vertex; + + free_sincos_table(&phi); + free_sincos_table(&theta); + + return TRUE; +} + +static void test_sphere(IDirect3DDevice9 *device, FLOAT radius, UINT slices, UINT stacks) +{ + HRESULT hr; + ID3DXMesh *sphere; + struct mesh mesh; + char name[256]; + + hr = D3DXCreateSphere(device, radius, slices, stacks, &sphere, NULL); + ok(hr == D3D_OK, "Got result %x, expected 0 (D3D_OK)\n", hr); + if (hr != D3D_OK) + { + skip("Couldn't create sphere\n"); + return; + } + + if (!compute_sphere(&mesh, radius, slices, stacks)) + { + skip("Couldn't create mesh\n"); + sphere->lpVtbl->Release(sphere); + return; + } + + mesh.fvf = D3DFVF_XYZ | D3DFVF_NORMAL; + + sprintf(name, "sphere (%g, %u, %u)", radius, slices, stacks); + compare_mesh(name, sphere, &mesh); + + free_mesh(&mesh); + + sphere->lpVtbl->Release(sphere); +} + +static void D3DXCreateSphereTest(void) +{ + HRESULT hr; + IDirect3DDevice9* device; + ID3DXMesh* sphere = NULL; + struct test_context *test_context; + + hr = D3DXCreateSphere(NULL, 0.0f, 0, 0, NULL, NULL); + ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n",hr,D3DERR_INVALIDCALL); + + hr = D3DXCreateSphere(NULL, 0.1f, 0, 0, NULL, NULL); + ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n",hr,D3DERR_INVALIDCALL); + + hr = D3DXCreateSphere(NULL, 0.0f, 1, 0, NULL, NULL); + ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n",hr,D3DERR_INVALIDCALL); + + hr = D3DXCreateSphere(NULL, 0.0f, 0, 1, NULL, NULL); + ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n",hr,D3DERR_INVALIDCALL); + + if (!(test_context = new_test_context())) + { + skip("Couldn't create test context\n"); + return; + } + device = test_context->device; + + hr = D3DXCreateSphere(device, 1.0f, 1, 1, &sphere, NULL); + ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n",hr,D3DERR_INVALIDCALL); + + hr = D3DXCreateSphere(device, 1.0f, 2, 1, &sphere, NULL); + ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n", hr, D3DERR_INVALIDCALL); + + hr = D3DXCreateSphere(device, 1.0f, 1, 2, &sphere, NULL); + ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n", hr, D3DERR_INVALIDCALL); + + hr = D3DXCreateSphere(device, -0.1f, 1, 2, &sphere, NULL); + ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n", hr, D3DERR_INVALIDCALL); + + test_sphere(device, 0.0f, 2, 2); + test_sphere(device, 1.0f, 2, 2); + test_sphere(device, 1.0f, 3, 2); + test_sphere(device, 1.0f, 4, 4); + test_sphere(device, 1.0f, 3, 4); + test_sphere(device, 5.0f, 6, 7); + test_sphere(device, 10.0f, 11, 12); + + free_test_context(test_context); +} + +static BOOL compute_cylinder(struct mesh *mesh, FLOAT radius1, FLOAT radius2, FLOAT length, UINT slices, UINT stacks) +{ + float theta_step, theta_start; + struct sincos_table theta; + FLOAT delta_radius, radius, radius_step; + FLOAT z, z_step, z_normal; + DWORD number_of_vertices, number_of_faces; + DWORD vertex, face; + int slice, stack; + + /* theta = angle on xy plane wrt x axis */ + theta_step = -2 * D3DX_PI / slices; + theta_start = D3DX_PI / 2; + + if (!compute_sincos_table(&theta, theta_start, theta_step, slices)) + { + return FALSE; + } + + number_of_vertices = 2 + (slices * (3 + stacks)); + number_of_faces = 2 * slices + stacks * (2 * slices); + + if (!new_mesh(mesh, number_of_vertices, number_of_faces)) + { + free_sincos_table(&theta); + return FALSE; + } + + vertex = 0; + face = 0; + + delta_radius = radius1 - radius2; + radius = radius1; + radius_step = delta_radius / stacks; + + z = -length / 2; + z_step = length / stacks; + z_normal = delta_radius / length; + if (isnan(z_normal)) + { + z_normal = 0.0f; + } + + mesh->vertices[vertex].normal.x = 0.0f; + mesh->vertices[vertex].normal.y = 0.0f; + mesh->vertices[vertex].normal.z = -1.0f; + mesh->vertices[vertex].position.x = 0.0f; + mesh->vertices[vertex].position.y = 0.0f; + mesh->vertices[vertex++].position.z = z; + + for (slice = 0; slice < slices; slice++, vertex++) + { + mesh->vertices[vertex].normal.x = 0.0f; + mesh->vertices[vertex].normal.y = 0.0f; + mesh->vertices[vertex].normal.z = -1.0f; + mesh->vertices[vertex].position.x = radius * theta.cos[slice]; + mesh->vertices[vertex].position.y = radius * theta.sin[slice]; + mesh->vertices[vertex].position.z = z; + + if (slice > 0) + { + mesh->faces[face][0] = 0; + mesh->faces[face][1] = slice; + mesh->faces[face++][2] = slice + 1; + } + } + + mesh->faces[face][0] = 0; + mesh->faces[face][1] = slice; + mesh->faces[face++][2] = 1; + + for (stack = 1; stack <= stacks+1; stack++) + { + for (slice = 0; slice < slices; slice++, vertex++) + { + mesh->vertices[vertex].normal.x = theta.cos[slice]; + mesh->vertices[vertex].normal.y = theta.sin[slice]; + mesh->vertices[vertex].normal.z = z_normal; + D3DXVec3Normalize(&mesh->vertices[vertex].normal, &mesh->vertices[vertex].normal); + mesh->vertices[vertex].position.x = radius * theta.cos[slice]; + mesh->vertices[vertex].position.y = radius * theta.sin[slice]; + mesh->vertices[vertex].position.z = z; + + if (stack > 1 && slice > 0) + { + mesh->faces[face][0] = vertex_index(slices, slice-1, stack-1); + mesh->faces[face][1] = vertex_index(slices, slice-1, stack); + mesh->faces[face++][2] = vertex_index(slices, slice, stack-1); + + mesh->faces[face][0] = vertex_index(slices, slice, stack-1); + mesh->faces[face][1] = vertex_index(slices, slice-1, stack); + mesh->faces[face++][2] = vertex_index(slices, slice, stack); + } + } + + if (stack > 1) + { + mesh->faces[face][0] = vertex_index(slices, slice-1, stack-1); + mesh->faces[face][1] = vertex_index(slices, slice-1, stack); + mesh->faces[face++][2] = vertex_index(slices, 0, stack-1); + + mesh->faces[face][0] = vertex_index(slices, 0, stack-1); + mesh->faces[face][1] = vertex_index(slices, slice-1, stack); + mesh->faces[face++][2] = vertex_index(slices, 0, stack); + } + + if (stack < stacks + 1) + { + z += z_step; + radius -= radius_step; + } + } + + for (slice = 0; slice < slices; slice++, vertex++) + { + mesh->vertices[vertex].normal.x = 0.0f; + mesh->vertices[vertex].normal.y = 0.0f; + mesh->vertices[vertex].normal.z = 1.0f; + mesh->vertices[vertex].position.x = radius * theta.cos[slice]; + mesh->vertices[vertex].position.y = radius * theta.sin[slice]; + mesh->vertices[vertex].position.z = z; + + if (slice > 0) + { + mesh->faces[face][0] = vertex_index(slices, slice-1, stack); + mesh->faces[face][1] = number_of_vertices - 1; + mesh->faces[face++][2] = vertex_index(slices, slice, stack); + } + } + + mesh->vertices[vertex].position.x = 0.0f; + mesh->vertices[vertex].position.y = 0.0f; + mesh->vertices[vertex].position.z = z; + mesh->vertices[vertex].normal.x = 0.0f; + mesh->vertices[vertex].normal.y = 0.0f; + mesh->vertices[vertex].normal.z = 1.0f; + + mesh->faces[face][0] = vertex_index(slices, slice-1, stack); + mesh->faces[face][1] = number_of_vertices - 1; + mesh->faces[face][2] = vertex_index(slices, 0, stack); + + free_sincos_table(&theta); + + return TRUE; +} + +static void test_cylinder(IDirect3DDevice9 *device, FLOAT radius1, FLOAT radius2, FLOAT length, UINT slices, UINT stacks) +{ + HRESULT hr; + ID3DXMesh *cylinder; + struct mesh mesh; + char name[256]; + + hr = D3DXCreateCylinder(device, radius1, radius2, length, slices, stacks, &cylinder, NULL); + ok(hr == D3D_OK, "Got result %x, expected 0 (D3D_OK)\n", hr); + if (hr != D3D_OK) + { + skip("Couldn't create cylinder\n"); + return; + } + + if (!compute_cylinder(&mesh, radius1, radius2, length, slices, stacks)) + { + skip("Couldn't create mesh\n"); + cylinder->lpVtbl->Release(cylinder); + return; + } + + mesh.fvf = D3DFVF_XYZ | D3DFVF_NORMAL; + + sprintf(name, "cylinder (%g, %g, %g, %u, %u)", radius1, radius2, length, slices, stacks); + compare_mesh(name, cylinder, &mesh); + + free_mesh(&mesh); + + cylinder->lpVtbl->Release(cylinder); +} + +static void D3DXCreateCylinderTest(void) +{ + HRESULT hr; + IDirect3DDevice9* device; + ID3DXMesh* cylinder = NULL; + struct test_context *test_context; + + hr = D3DXCreateCylinder(NULL, 0.0f, 0.0f, 0.0f, 0, 0, NULL, NULL); + ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n",hr,D3DERR_INVALIDCALL); + + hr = D3DXCreateCylinder(NULL, 1.0f, 1.0f, 1.0f, 2, 1, &cylinder, NULL); + ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n",hr,D3DERR_INVALIDCALL); + + if (!(test_context = new_test_context())) + { + skip("Couldn't create test context\n"); + return; + } + device = test_context->device; + + hr = D3DXCreateCylinder(device, -0.1f, 1.0f, 1.0f, 2, 1, &cylinder, NULL); + ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n",hr,D3DERR_INVALIDCALL); + + hr = D3DXCreateCylinder(device, 0.0f, 1.0f, 1.0f, 2, 1, &cylinder, NULL); + ok(hr == D3D_OK, "Got result %x, expected 0 (D3D_OK)\n",hr); + + if (SUCCEEDED(hr) && cylinder) + { + cylinder->lpVtbl->Release(cylinder); + } + + hr = D3DXCreateCylinder(device, 1.0f, -0.1f, 1.0f, 2, 1, &cylinder, NULL); + ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n",hr,D3DERR_INVALIDCALL); + + hr = D3DXCreateCylinder(device, 1.0f, 0.0f, 1.0f, 2, 1, &cylinder, NULL); + ok(hr == D3D_OK, "Got result %x, expected 0 (D3D_OK)\n",hr); + + if (SUCCEEDED(hr) && cylinder) + { + cylinder->lpVtbl->Release(cylinder); + } + + hr = D3DXCreateCylinder(device, 1.0f, 1.0f, -0.1f, 2, 1, &cylinder, NULL); + ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n",hr,D3DERR_INVALIDCALL); + + /* Test with length == 0.0f succeeds */ + hr = D3DXCreateCylinder(device, 1.0f, 1.0f, 0.0f, 2, 1, &cylinder, NULL); + ok(hr == D3D_OK, "Got result %x, expected 0 (D3D_OK)\n",hr); + + if (SUCCEEDED(hr) && cylinder) + { + cylinder->lpVtbl->Release(cylinder); + } + + hr = D3DXCreateCylinder(device, 1.0f, 1.0f, 1.0f, 1, 1, &cylinder, NULL); + ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n",hr,D3DERR_INVALIDCALL); + + hr = D3DXCreateCylinder(device, 1.0f, 1.0f, 1.0f, 2, 0, &cylinder, NULL); + ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n",hr,D3DERR_INVALIDCALL); + + hr = D3DXCreateCylinder(device, 1.0f, 1.0f, 1.0f, 2, 1, NULL, NULL); + ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n",hr,D3DERR_INVALIDCALL); + + test_cylinder(device, 0.0f, 0.0f, 0.0f, 2, 1); + test_cylinder(device, 1.0f, 1.0f, 1.0f, 2, 1); + test_cylinder(device, 1.0f, 1.0f, 2.0f, 3, 4); + test_cylinder(device, 3.0f, 2.0f, 4.0f, 3, 4); + test_cylinder(device, 2.0f, 3.0f, 4.0f, 3, 4); + test_cylinder(device, 3.0f, 4.0f, 5.0f, 11, 20); + + free_test_context(test_context); +} + +static BOOL compute_torus(struct mesh *mesh, float innerradius, float outerradius, UINT sides, UINT rings) +{ + float phi, phi_step, sin_phi, cos_phi; + float theta, theta_step, sin_theta, cos_theta; + unsigned int numvert, numfaces, i, j; + + numvert = sides * rings; + numfaces = numvert * 2; + + if (!new_mesh(mesh, numvert, numfaces)) + return FALSE; + + phi_step = D3DX_PI / sides * 2.0f; + theta_step = D3DX_PI / rings * -2.0f; + + theta = 0.0f; + + for (i = 0; i < rings; ++i) + { + phi = 0.0f; + + cos_theta = cosf(theta); + sin_theta = sinf(theta); + + for (j = 0; j < sides; ++j) + { + sin_phi = sinf(phi); + cos_phi = cosf(phi); + + mesh->vertices[i * sides + j].position.x = (innerradius * cos_phi + outerradius) * cos_theta; + mesh->vertices[i * sides + j].position.y = (innerradius * cos_phi + outerradius) * sin_theta; + mesh->vertices[i * sides + j].position.z = innerradius * sin_phi; + mesh->vertices[i * sides + j].normal.x = cos_phi * cos_theta; + mesh->vertices[i * sides + j].normal.y = cos_phi * sin_theta; + mesh->vertices[i * sides + j].normal.z = sin_phi; + + phi += phi_step; + } + + theta += theta_step; + } + + for (i = 0; i < numfaces - sides * 2; ++i) + { + mesh->faces[i][0] = i % 2 ? i / 2 + sides : i / 2; + mesh->faces[i][1] = (i / 2 + 1) % sides ? i / 2 + 1 : i / 2 + 1 - sides; + mesh->faces[i][2] = (i + 1) % (sides * 2) ? (i + 1) / 2 + sides : (i + 1) / 2; + } + + for (j = 0; i < numfaces; ++i, ++j) + { + mesh->faces[i][0] = i % 2 ? j / 2 : i / 2; + mesh->faces[i][1] = (i / 2 + 1) % sides ? i / 2 + 1 : i / 2 + 1 - sides; + mesh->faces[i][2] = i == numfaces - 1 ? 0 : (j + 1) / 2; + } + + return TRUE; +} + +static void test_torus(IDirect3DDevice9 *device, float innerradius, float outerradius, UINT sides, UINT rings) +{ + HRESULT hr; + ID3DXMesh *torus; + struct mesh mesh; + char name[256]; + + hr = D3DXCreateTorus(device, innerradius, outerradius, sides, rings, &torus, NULL); + ok(hr == D3D_OK, "Got result %#x, expected 0 (D3D_OK)\n", hr); + if (hr != D3D_OK) + { + skip("Couldn't create torus\n"); + return; + } + + if (!compute_torus(&mesh, innerradius, outerradius, sides, rings)) + { + skip("Couldn't create mesh\n"); + torus->lpVtbl->Release(torus); + return; + } + + mesh.fvf = D3DFVF_XYZ | D3DFVF_NORMAL; + + sprintf(name, "torus (%g, %g, %u, %u)", innerradius, outerradius, sides, rings); + compare_mesh(name, torus, &mesh); + + free_mesh(&mesh); + + torus->lpVtbl->Release(torus); +} + +static void D3DXCreateTorusTest(void) +{ + HRESULT hr; + IDirect3DDevice9* device; + ID3DXMesh* torus = NULL; + struct test_context *test_context; + + if (!(test_context = new_test_context())) + { + skip("Couldn't create test context\n"); + return; + } + device = test_context->device; + + hr = D3DXCreateTorus(NULL, 0.0f, 0.0f, 3, 3, &torus, NULL); + ok(hr == D3DERR_INVALIDCALL, "Got result %#x, expected %#x (D3DERR_INVALIDCALL)\n", hr, D3DERR_INVALIDCALL); + + hr = D3DXCreateTorus(device, -1.0f, 0.0f, 3, 3, &torus, NULL); + ok(hr == D3DERR_INVALIDCALL, "Got result %#x, expected %#x (D3DERR_INVALIDCALL)\n", hr, D3DERR_INVALIDCALL); + + hr = D3DXCreateTorus(device, 0.0f, -1.0f, 3, 3, &torus, NULL); + ok(hr == D3DERR_INVALIDCALL, "Got result %#x, expected %#x (D3DERR_INVALIDCALL)\n", hr, D3DERR_INVALIDCALL); + + hr = D3DXCreateTorus(device, 0.0f, 0.0f, 2, 3, &torus, NULL); + ok(hr == D3DERR_INVALIDCALL, "Got result %#x, expected %#x (D3DERR_INVALIDCALL)\n", hr, D3DERR_INVALIDCALL); + + hr = D3DXCreateTorus(device, 0.0f, 0.0f, 3, 2, &torus, NULL); + ok(hr == D3DERR_INVALIDCALL, "Got result %#x, expected %#x (D3DERR_INVALIDCALL)\n", hr, D3DERR_INVALIDCALL); + + hr = D3DXCreateTorus(device, 0.0f, 0.0f, 3, 3, NULL, NULL); + ok(hr == D3DERR_INVALIDCALL, "Got result %#x, expected %#x (D3DERR_INVALIDCALL)\n", hr, D3DERR_INVALIDCALL); + + test_torus(device, 0.0f, 0.0f, 3, 3); + test_torus(device, 1.0f, 1.0f, 3, 3); + test_torus(device, 1.0f, 1.0f, 32, 64); + test_torus(device, 0.0f, 1.0f, 5, 5); + test_torus(device, 1.0f, 0.0f, 5, 5); + test_torus(device, 5.0f, 0.2f, 8, 8); + test_torus(device, 0.2f, 1.0f, 60, 3); + test_torus(device, 0.2f, 1.0f, 8, 70); + + free_test_context(test_context); +} + +struct dynamic_array +{ + int count, capacity; + void *items; +}; + +enum pointtype { + POINTTYPE_CURVE = 0, + POINTTYPE_CORNER, + POINTTYPE_CURVE_START, + POINTTYPE_CURVE_END, + POINTTYPE_CURVE_MIDDLE, +}; + +struct point2d +{ + D3DXVECTOR2 pos; + enum pointtype corner; +}; + +/* is a dynamic_array */ +struct outline +{ + int count, capacity; + struct point2d *items; +}; + +/* is a dynamic_array */ +struct outline_array +{ + int count, capacity; + struct outline *items; +}; + +struct glyphinfo +{ + struct outline_array outlines; + float offset_x; +}; + +static BOOL reserve(struct dynamic_array *array, int count, int itemsize) +{ + if (count > array->capacity) { + void *new_buffer; + int new_capacity; + if (array->items && array->capacity) { + new_capacity = max(array->capacity * 2, count); + new_buffer = HeapReAlloc(GetProcessHeap(), 0, array->items, new_capacity * itemsize); + } else { + new_capacity = max(16, count); + new_buffer = HeapAlloc(GetProcessHeap(), 0, new_capacity * itemsize); + } + if (!new_buffer) + return FALSE; + array->items = new_buffer; + array->capacity = new_capacity; + } + return TRUE; +} + +static struct point2d *add_point(struct outline *array) +{ + struct point2d *item; + + if (!reserve((struct dynamic_array *)array, array->count + 1, sizeof(array->items[0]))) + return NULL; + + item = &array->items[array->count++]; + ZeroMemory(item, sizeof(*item)); + return item; +} + +static struct outline *add_outline(struct outline_array *array) +{ + struct outline *item; + + if (!reserve((struct dynamic_array *)array, array->count + 1, sizeof(array->items[0]))) + return NULL; + + item = &array->items[array->count++]; + ZeroMemory(item, sizeof(*item)); + return item; +} + +static inline D3DXVECTOR2 *convert_fixed_to_float(POINTFX *pt, int count, float emsquare) +{ + D3DXVECTOR2 *ret = (D3DXVECTOR2*)pt; + while (count--) { + D3DXVECTOR2 *pt_flt = (D3DXVECTOR2*)pt; + pt_flt->x = (pt->x.value + pt->x.fract / (float)0x10000) / emsquare; + pt_flt->y = (pt->y.value + pt->y.fract / (float)0x10000) / emsquare; + pt++; + } + return ret; +} + +static HRESULT add_bezier_points(struct outline *outline, const D3DXVECTOR2 *p1, + const D3DXVECTOR2 *p2, const D3DXVECTOR2 *p3, + float max_deviation) +{ + D3DXVECTOR2 split1 = {0, 0}, split2 = {0, 0}, middle, vec; + float deviation; + + D3DXVec2Scale(&split1, D3DXVec2Add(&split1, p1, p2), 0.5f); + D3DXVec2Scale(&split2, D3DXVec2Add(&split2, p2, p3), 0.5f); + D3DXVec2Scale(&middle, D3DXVec2Add(&middle, &split1, &split2), 0.5f); + + deviation = D3DXVec2Length(D3DXVec2Subtract(&vec, &middle, p2)); + if (deviation < max_deviation) { + struct point2d *pt = add_point(outline); + if (!pt) return E_OUTOFMEMORY; + pt->pos = *p2; + pt->corner = POINTTYPE_CURVE; + /* the end point is omitted because the end line merges into the next segment of + * the split bezier curve, and the end of the split bezier curve is added outside + * this recursive function. */ + } else { + HRESULT hr = add_bezier_points(outline, p1, &split1, &middle, max_deviation); + if (hr != S_OK) return hr; + hr = add_bezier_points(outline, &middle, &split2, p3, max_deviation); + if (hr != S_OK) return hr; + } + + return S_OK; +} + +static inline BOOL is_direction_similar(D3DXVECTOR2 *dir1, D3DXVECTOR2 *dir2, float cos_theta) +{ + /* dot product = cos(theta) */ + return D3DXVec2Dot(dir1, dir2) > cos_theta; +} + +static inline D3DXVECTOR2 *unit_vec2(D3DXVECTOR2 *dir, const D3DXVECTOR2 *pt1, const D3DXVECTOR2 *pt2) +{ + return D3DXVec2Normalize(D3DXVec2Subtract(dir, pt2, pt1), dir); +} + +static BOOL attempt_line_merge(struct outline *outline, + int pt_index, + const D3DXVECTOR2 *nextpt, + BOOL to_curve) +{ + D3DXVECTOR2 curdir, lastdir; + struct point2d *prevpt, *pt; + BOOL ret = FALSE; + const float cos_half = cos(D3DXToRadian(0.5f)); + + pt = &outline->items[pt_index]; + pt_index = (pt_index - 1 + outline->count) % outline->count; + prevpt = &outline->items[pt_index]; + + if (to_curve) + pt->corner = pt->corner != POINTTYPE_CORNER ? POINTTYPE_CURVE_MIDDLE : POINTTYPE_CURVE_START; + + if (outline->count < 2) + return FALSE; + + /* remove last point if the next line continues the last line */ + unit_vec2(&lastdir, &prevpt->pos, &pt->pos); + unit_vec2(&curdir, &pt->pos, nextpt); + if (is_direction_similar(&lastdir, &curdir, cos_half)) + { + outline->count--; + if (pt->corner == POINTTYPE_CURVE_END) + prevpt->corner = pt->corner; + if (prevpt->corner == POINTTYPE_CURVE_END && to_curve) + prevpt->corner = POINTTYPE_CURVE_MIDDLE; + pt = prevpt; + + ret = TRUE; + if (outline->count < 2) + return ret; + + pt_index = (pt_index - 1 + outline->count) % outline->count; + prevpt = &outline->items[pt_index]; + unit_vec2(&lastdir, &prevpt->pos, &pt->pos); + unit_vec2(&curdir, &pt->pos, nextpt); + } + return ret; +} + +static HRESULT create_outline(struct glyphinfo *glyph, void *raw_outline, int datasize, + float max_deviation, float emsquare) +{ + const float cos_45 = cos(D3DXToRadian(45.0f)); + const float cos_90 = cos(D3DXToRadian(90.0f)); + TTPOLYGONHEADER *header = (TTPOLYGONHEADER *)raw_outline; + + while ((char *)header < (char *)raw_outline + datasize) + { + TTPOLYCURVE *curve = (TTPOLYCURVE *)(header + 1); + struct point2d *lastpt, *pt; + D3DXVECTOR2 lastdir; + D3DXVECTOR2 *pt_flt; + int j; + struct outline *outline = add_outline(&glyph->outlines); + + if (!outline) + return E_OUTOFMEMORY; + + pt = add_point(outline); + if (!pt) + return E_OUTOFMEMORY; + pt_flt = convert_fixed_to_float(&header->pfxStart, 1, emsquare); + pt->pos = *pt_flt; + pt->corner = POINTTYPE_CORNER; + + if (header->dwType != TT_POLYGON_TYPE) + trace("Unknown header type %d\n", header->dwType); + + while ((char *)curve < (char *)header + header->cb) + { + D3DXVECTOR2 bezier_start = outline->items[outline->count - 1].pos; + BOOL to_curve = curve->wType != TT_PRIM_LINE && curve->cpfx > 1; + + if (!curve->cpfx) { + curve = (TTPOLYCURVE *)&curve->apfx[curve->cpfx]; + continue; + } + + pt_flt = convert_fixed_to_float(curve->apfx, curve->cpfx, emsquare); + + attempt_line_merge(outline, outline->count - 1, &pt_flt[0], to_curve); + + if (to_curve) + { + HRESULT hr; + int count = curve->cpfx; + j = 0; + + while (count > 2) + { + D3DXVECTOR2 bezier_end; + + D3DXVec2Scale(&bezier_end, D3DXVec2Add(&bezier_end, &pt_flt[j], &pt_flt[j+1]), 0.5f); + hr = add_bezier_points(outline, &bezier_start, &pt_flt[j], &bezier_end, max_deviation); + if (hr != S_OK) + return hr; + bezier_start = bezier_end; + count--; + j++; + } + hr = add_bezier_points(outline, &bezier_start, &pt_flt[j], &pt_flt[j+1], max_deviation); + if (hr != S_OK) + return hr; + + pt = add_point(outline); + if (!pt) + return E_OUTOFMEMORY; + j++; + pt->pos = pt_flt[j]; + pt->corner = POINTTYPE_CURVE_END; + } else { + for (j = 0; j < curve->cpfx; j++) + { + pt = add_point(outline); + if (!pt) + return E_OUTOFMEMORY; + pt->pos = pt_flt[j]; + pt->corner = POINTTYPE_CORNER; + } + } + + curve = (TTPOLYCURVE *)&curve->apfx[curve->cpfx]; + } + + /* remove last point if the next line continues the last line */ + if (outline->count >= 3) { + BOOL to_curve; + + lastpt = &outline->items[outline->count - 1]; + pt = &outline->items[0]; + if (pt->pos.x == lastpt->pos.x && pt->pos.y == lastpt->pos.y) { + if (lastpt->corner == POINTTYPE_CURVE_END) + { + if (pt->corner == POINTTYPE_CURVE_START) + pt->corner = POINTTYPE_CURVE_MIDDLE; + else + pt->corner = POINTTYPE_CURVE_END; + } + outline->count--; + } else { + /* outline closed with a line from end to start point */ + attempt_line_merge(outline, outline->count - 1, &pt->pos, FALSE); + } + lastpt = &outline->items[0]; + to_curve = lastpt->corner != POINTTYPE_CORNER && lastpt->corner != POINTTYPE_CURVE_END; + if (lastpt->corner == POINTTYPE_CURVE_START) + lastpt->corner = POINTTYPE_CORNER; + pt = &outline->items[1]; + if (attempt_line_merge(outline, 0, &pt->pos, to_curve)) + *lastpt = outline->items[outline->count]; + } + + lastpt = &outline->items[outline->count - 1]; + pt = &outline->items[0]; + unit_vec2(&lastdir, &lastpt->pos, &pt->pos); + for (j = 0; j < outline->count; j++) + { + D3DXVECTOR2 curdir; + + lastpt = pt; + pt = &outline->items[(j + 1) % outline->count]; + unit_vec2(&curdir, &lastpt->pos, &pt->pos); + + switch (lastpt->corner) + { + case POINTTYPE_CURVE_START: + case POINTTYPE_CURVE_END: + if (!is_direction_similar(&lastdir, &curdir, cos_45)) + lastpt->corner = POINTTYPE_CORNER; + break; + case POINTTYPE_CURVE_MIDDLE: + if (!is_direction_similar(&lastdir, &curdir, cos_90)) + lastpt->corner = POINTTYPE_CORNER; + else + lastpt->corner = POINTTYPE_CURVE; + break; + default: + break; + } + lastdir = curdir; + } + + header = (TTPOLYGONHEADER *)((char *)header + header->cb); + } + return S_OK; +} + +static void free_outline(struct outline *outline) +{ + HeapFree(GetProcessHeap(), 0, outline->items); +} + +static void free_glyphinfo(struct glyphinfo *glyph) +{ + unsigned int i; + + for (i = 0; i < glyph->outlines.count; ++i) + free_outline(&glyph->outlines.items[i]); + HeapFree(GetProcessHeap(), 0, glyph->outlines.items); +} + +static void compute_text_mesh(struct mesh *mesh, const char *text, + float deviation, float extrusion, float otmEMSquare, const struct glyphinfo *glyphs) +{ + DWORD nb_vertices, nb_faces; + DWORD nb_corners, nb_outline_points; + int textlen = 0; + int i; + struct vertex *vertex_ptr; + face *face_ptr; + + textlen = strlen(text); + + /* corner points need an extra vertex for the different side faces normals */ + nb_corners = 0; + nb_outline_points = 0; + for (i = 0; i < textlen; i++) + { + int j; + for (j = 0; j < glyphs[i].outlines.count; j++) + { + int k; + struct outline *outline = &glyphs[i].outlines.items[j]; + nb_outline_points += outline->count; + nb_corners++; /* first outline point always repeated as a corner */ + for (k = 1; k < outline->count; k++) + if (outline->items[k].corner) + nb_corners++; + } + } + + nb_vertices = (nb_outline_points + nb_corners) * 2 + textlen; + nb_faces = nb_outline_points * 2; + + ok(new_mesh(mesh, nb_vertices, nb_faces), "Failed to create reference text mesh.\n"); + + /* convert 2D vertices and faces into 3D mesh */ + vertex_ptr = mesh->vertices; + face_ptr = mesh->faces; + for (i = 0; i < textlen; i++) + { + int j; + + /* side vertices and faces */ + for (j = 0; j < glyphs[i].outlines.count; j++) + { + struct vertex *outline_vertices = vertex_ptr; + struct outline *outline = &glyphs[i].outlines.items[j]; + int k; + struct point2d *prevpt = &outline->items[outline->count - 1]; + struct point2d *pt = &outline->items[0]; + + for (k = 1; k <= outline->count; k++) + { + struct vertex vtx; + struct point2d *nextpt = &outline->items[k % outline->count]; + WORD vtx_idx = vertex_ptr - mesh->vertices; + D3DXVECTOR2 vec; + + if (pt->corner == POINTTYPE_CURVE_START) + D3DXVec2Subtract(&vec, &pt->pos, &prevpt->pos); + else if (pt->corner) + D3DXVec2Subtract(&vec, &nextpt->pos, &pt->pos); + else + D3DXVec2Subtract(&vec, &nextpt->pos, &prevpt->pos); + D3DXVec2Normalize(&vec, &vec); + vtx.normal.x = -vec.y; + vtx.normal.y = vec.x; + vtx.normal.z = 0; + + vtx.position.x = pt->pos.x + glyphs[i].offset_x; + vtx.position.y = pt->pos.y; + vtx.position.z = 0; + *vertex_ptr++ = vtx; + + vtx.position.z = -extrusion; + *vertex_ptr++ = vtx; + + vtx.position.x = nextpt->pos.x + glyphs[i].offset_x; + vtx.position.y = nextpt->pos.y; + if (pt->corner && nextpt->corner && nextpt->corner != POINTTYPE_CURVE_END) { + vtx.position.z = -extrusion; + *vertex_ptr++ = vtx; + vtx.position.z = 0; + *vertex_ptr++ = vtx; + + (*face_ptr)[0] = vtx_idx; + (*face_ptr)[1] = vtx_idx + 2; + (*face_ptr)[2] = vtx_idx + 1; + face_ptr++; + + (*face_ptr)[0] = vtx_idx; + (*face_ptr)[1] = vtx_idx + 3; + (*face_ptr)[2] = vtx_idx + 2; + face_ptr++; + } else { + if (nextpt->corner) { + if (nextpt->corner == POINTTYPE_CURVE_END) { + struct point2d *nextpt2 = &outline->items[(k + 1) % outline->count]; + D3DXVec2Subtract(&vec, &nextpt2->pos, &nextpt->pos); + } else { + D3DXVec2Subtract(&vec, &nextpt->pos, &pt->pos); + } + D3DXVec2Normalize(&vec, &vec); + vtx.normal.x = -vec.y; + vtx.normal.y = vec.x; + + vtx.position.z = 0; + *vertex_ptr++ = vtx; + vtx.position.z = -extrusion; + *vertex_ptr++ = vtx; + } + + (*face_ptr)[0] = vtx_idx; + (*face_ptr)[1] = vtx_idx + 3; + (*face_ptr)[2] = vtx_idx + 1; + face_ptr++; + + (*face_ptr)[0] = vtx_idx; + (*face_ptr)[1] = vtx_idx + 2; + (*face_ptr)[2] = vtx_idx + 3; + face_ptr++; + } + + prevpt = pt; + pt = nextpt; + } + if (!pt->corner) { + *vertex_ptr++ = *outline_vertices++; + *vertex_ptr++ = *outline_vertices++; + } + } + + /* FIXME: compute expected faces */ + /* Add placeholder to separate glyph outlines */ + vertex_ptr->position.x = 0; + vertex_ptr->position.y = 0; + vertex_ptr->position.z = 0; + vertex_ptr->normal.x = 0; + vertex_ptr->normal.y = 0; + vertex_ptr->normal.z = 1; + vertex_ptr++; + } +} + +static void compare_text_outline_mesh(const char *name, ID3DXMesh *d3dxmesh, struct mesh *mesh, + size_t textlen, float extrusion, const struct glyphinfo *glyphs) +{ + HRESULT hr; + DWORD number_of_vertices, number_of_faces; + IDirect3DVertexBuffer9 *vertex_buffer = NULL; + IDirect3DIndexBuffer9 *index_buffer = NULL; + D3DVERTEXBUFFER_DESC vertex_buffer_description; + D3DINDEXBUFFER_DESC index_buffer_description; + struct vertex *vertices = NULL; + face *faces = NULL; + int expected, i; + int vtx_idx1, face_idx1, vtx_idx2, face_idx2; + + number_of_vertices = d3dxmesh->lpVtbl->GetNumVertices(d3dxmesh); + number_of_faces = d3dxmesh->lpVtbl->GetNumFaces(d3dxmesh); + + hr = d3dxmesh->lpVtbl->GetVertexBuffer(d3dxmesh, &vertex_buffer); + ok(hr == D3D_OK, "Test %s, unexpected hr %#x.\n", name, hr); + hr = IDirect3DVertexBuffer9_GetDesc(vertex_buffer, &vertex_buffer_description); + ok(hr == D3D_OK, "Test %s, unexpected hr %#x.\n", name, hr); + ok(vertex_buffer_description.Format == D3DFMT_VERTEXDATA, "Test %s, unexpected format %u.\n", + name, vertex_buffer_description.Format); + ok(vertex_buffer_description.Type == D3DRTYPE_VERTEXBUFFER, "Test %s, unexpected resource type %u.\n", + name, vertex_buffer_description.Type); + ok(!vertex_buffer_description.Usage, "Test %s, unexpected usage %#x.\n", name, vertex_buffer_description.Usage); + ok(vertex_buffer_description.Pool == D3DPOOL_MANAGED, "Test %s, unexpected pool %u.\n", + name, vertex_buffer_description.Pool); + ok(vertex_buffer_description.FVF == mesh->fvf, "Test %s, unexpected FVF %#x (expected %#x).\n", + name, vertex_buffer_description.FVF, mesh->fvf); + if (!mesh->fvf) + expected = number_of_vertices * mesh->vertex_size; + else + expected = number_of_vertices * D3DXGetFVFVertexSize(mesh->fvf); + ok(vertex_buffer_description.Size == expected, "Test %s, unexpected size %u (expected %u).\n", + name, vertex_buffer_description.Size, expected); + + hr = d3dxmesh->lpVtbl->GetIndexBuffer(d3dxmesh, &index_buffer); + ok(hr == D3D_OK, "Test %s, unexpected hr %#x.\n", name, hr); + hr = IDirect3DIndexBuffer9_GetDesc(index_buffer, &index_buffer_description); + ok(hr == D3D_OK, "Test %s, unexpected hr %#x.\n", name, hr); + ok(index_buffer_description.Format == D3DFMT_INDEX16, "Test %s, unexpected format %u.\n", + name, index_buffer_description.Format); + ok(index_buffer_description.Type == D3DRTYPE_INDEXBUFFER, "Test %s, unexpected resource type %u.\n", + name, index_buffer_description.Type); + ok(!index_buffer_description.Usage, "Test %s, unexpected usage %#x.\n", + name, index_buffer_description.Usage); + ok(index_buffer_description.Pool == D3DPOOL_MANAGED, "Test %s, unexpected pool %u.\n", + name, index_buffer_description.Pool); + expected = number_of_faces * sizeof(WORD) * 3; + ok(index_buffer_description.Size == expected, "Test %s, unexpected size %u.\n", + name, index_buffer_description.Size); + + hr = IDirect3DVertexBuffer9_Lock(vertex_buffer, 0, number_of_vertices * sizeof(D3DXVECTOR3) * 2, + (void **)&vertices, D3DLOCK_DISCARD); + ok(hr == D3D_OK, "Test %s, unexpected hr %#x.\n", name, hr); + hr = IDirect3DIndexBuffer9_Lock(index_buffer, 0, number_of_faces * sizeof(WORD) * 3, + (void **)&faces, D3DLOCK_DISCARD); + ok(hr == D3D_OK, "Test %s, unexpected hr %#x.\n", name, hr); + face_idx1 = 0; + vtx_idx2 = 0; + face_idx2 = 0; + vtx_idx1 = 0; + for (i = 0; i < textlen; i++) + { + int nb_outline_vertices1, nb_outline_faces1; + int nb_outline_vertices2, nb_outline_faces2; + int nb_back_vertices, nb_back_faces; + int first_vtx1, first_vtx2; + int first_face1, first_face2; + int j; + + first_vtx1 = vtx_idx1; + first_vtx2 = vtx_idx2; + /* Glyphs without outlines do not generate any vertices. */ + if (glyphs[i].outlines.count > 0) + { + for (; vtx_idx1 < number_of_vertices; vtx_idx1++) + { + if (vertices[vtx_idx1].normal.z != 0) + break; + } + + for (; vtx_idx2 < mesh->number_of_vertices; vtx_idx2++) + { + if (mesh->vertices[vtx_idx2].normal.z != 0) + break; + } + } + nb_outline_vertices1 = vtx_idx1 - first_vtx1; + nb_outline_vertices2 = vtx_idx2 - first_vtx2; + ok(nb_outline_vertices1 == nb_outline_vertices2, + "Test %s, glyph %d, outline vertex count result %d, expected %d\n", name, i, + nb_outline_vertices1, nb_outline_vertices2); + + for (j = 0; j < min(nb_outline_vertices1, nb_outline_vertices2); j++) + { + vtx_idx1 = first_vtx1 + j; + vtx_idx2 = first_vtx2 + j; + ok(compare_vec3(vertices[vtx_idx1].position, mesh->vertices[vtx_idx2].position), + "Test %s, glyph %d, vertex position %d, result (%g, %g, %g), expected (%g, %g, %g)\n", name, i, vtx_idx1, + vertices[vtx_idx1].position.x, vertices[vtx_idx1].position.y, vertices[vtx_idx1].position.z, + mesh->vertices[vtx_idx2].position.x, mesh->vertices[vtx_idx2].position.y, mesh->vertices[vtx_idx2].position.z); + ok(compare_vec3(vertices[vtx_idx1].normal, mesh->vertices[first_vtx2 + j].normal), + "Test %s, glyph %d, vertex normal %d, result (%g, %g, %g), expected (%g, %g, %g)\n", name, i, vtx_idx1, + vertices[vtx_idx1].normal.x, vertices[vtx_idx1].normal.y, vertices[vtx_idx1].normal.z, + mesh->vertices[vtx_idx2].normal.x, mesh->vertices[vtx_idx2].normal.y, mesh->vertices[vtx_idx2].normal.z); + } + vtx_idx1 = first_vtx1 + nb_outline_vertices1; + vtx_idx2 = first_vtx2 + nb_outline_vertices2; + + first_face1 = face_idx1; + first_face2 = face_idx2; + for (; face_idx1 < number_of_faces; face_idx1++) + { + if (faces[face_idx1][0] >= vtx_idx1 || + faces[face_idx1][1] >= vtx_idx1 || + faces[face_idx1][2] >= vtx_idx1) + break; + } + for (; face_idx2 < mesh->number_of_faces; face_idx2++) + { + if (mesh->faces[face_idx2][0] >= vtx_idx2 || + mesh->faces[face_idx2][1] >= vtx_idx2 || + mesh->faces[face_idx2][2] >= vtx_idx2) + break; + } + nb_outline_faces1 = face_idx1 - first_face1; + nb_outline_faces2 = face_idx2 - first_face2; + ok(nb_outline_faces1 == nb_outline_faces2, + "Test %s, glyph %d, outline face count result %d, expected %d\n", name, i, + nb_outline_faces1, nb_outline_faces2); + + for (j = 0; j < min(nb_outline_faces1, nb_outline_faces2); j++) + { + face_idx1 = first_face1 + j; + face_idx2 = first_face2 + j; + ok(faces[face_idx1][0] - first_vtx1 == mesh->faces[face_idx2][0] - first_vtx2 && + faces[face_idx1][1] - first_vtx1 == mesh->faces[face_idx2][1] - first_vtx2 && + faces[face_idx1][2] - first_vtx1 == mesh->faces[face_idx2][2] - first_vtx2, + "Test %s, glyph %d, face %d, result (%d, %d, %d), expected (%d, %d, %d)\n", name, i, face_idx1, + faces[face_idx1][0], faces[face_idx1][1], faces[face_idx1][2], + mesh->faces[face_idx2][0] - first_vtx2 + first_vtx1, + mesh->faces[face_idx2][1] - first_vtx2 + first_vtx1, + mesh->faces[face_idx2][2] - first_vtx2 + first_vtx1); + } + face_idx1 = first_face1 + nb_outline_faces1; + face_idx2 = first_face2 + nb_outline_faces2; + + /* partial test on back vertices and faces */ + first_vtx1 = vtx_idx1; + for (; vtx_idx1 < number_of_vertices; vtx_idx1++) { + struct vertex vtx; + + if (vertices[vtx_idx1].normal.z != 1.0f) + break; + + vtx.position.z = 0.0f; + vtx.normal.x = 0.0f; + vtx.normal.y = 0.0f; + vtx.normal.z = 1.0f; + ok(compare(vertices[vtx_idx1].position.z, vtx.position.z), + "Test %s, glyph %d, vertex position.z %d, result %g, expected %g\n", name, i, vtx_idx1, + vertices[vtx_idx1].position.z, vtx.position.z); + ok(compare_vec3(vertices[vtx_idx1].normal, vtx.normal), + "Test %s, glyph %d, vertex normal %d, result (%g, %g, %g), expected (%g, %g, %g)\n", name, i, vtx_idx1, + vertices[vtx_idx1].normal.x, vertices[vtx_idx1].normal.y, vertices[vtx_idx1].normal.z, + vtx.normal.x, vtx.normal.y, vtx.normal.z); + } + nb_back_vertices = vtx_idx1 - first_vtx1; + first_face1 = face_idx1; + for (; face_idx1 < number_of_faces; face_idx1++) + { + const D3DXVECTOR3 *vtx1, *vtx2, *vtx3; + D3DXVECTOR3 normal; + D3DXVECTOR3 v1 = {0, 0, 0}; + D3DXVECTOR3 v2 = {0, 0, 0}; + D3DXVECTOR3 forward = {0.0f, 0.0f, 1.0f}; + + if (faces[face_idx1][0] >= vtx_idx1 || + faces[face_idx1][1] >= vtx_idx1 || + faces[face_idx1][2] >= vtx_idx1) + break; + + vtx1 = &vertices[faces[face_idx1][0]].position; + vtx2 = &vertices[faces[face_idx1][1]].position; + vtx3 = &vertices[faces[face_idx1][2]].position; + + D3DXVec3Subtract(&v1, vtx2, vtx1); + D3DXVec3Subtract(&v2, vtx3, vtx2); + D3DXVec3Cross(&normal, &v1, &v2); + D3DXVec3Normalize(&normal, &normal); + ok(!D3DXVec3Length(&normal) || compare_vec3(normal, forward), + "Test %s, glyph %d, face %d normal, result (%g, %g, %g), expected (%g, %g, %g)\n", name, i, face_idx1, + normal.x, normal.y, normal.z, forward.x, forward.y, forward.z); + } + nb_back_faces = face_idx1 - first_face1; + + /* compare front and back faces & vertices */ + if (extrusion == 0.0f) { + /* Oddly there are only back faces in this case */ + nb_back_vertices /= 2; + nb_back_faces /= 2; + face_idx1 -= nb_back_faces; + vtx_idx1 -= nb_back_vertices; + } + for (j = 0; j < nb_back_vertices; j++) + { + struct vertex vtx = vertices[first_vtx1]; + vtx.position.z = -extrusion; + vtx.normal.x = 0.0f; + vtx.normal.y = 0.0f; + vtx.normal.z = extrusion == 0.0f ? 1.0f : -1.0f; + ok(compare_vec3(vertices[vtx_idx1].position, vtx.position), + "Test %s, glyph %d, vertex position %d, result (%g, %g, %g), expected (%g, %g, %g)\n", name, i, vtx_idx1, + vertices[vtx_idx1].position.x, vertices[vtx_idx1].position.y, vertices[vtx_idx1].position.z, + vtx.position.x, vtx.position.y, vtx.position.z); + ok(compare_vec3(vertices[vtx_idx1].normal, vtx.normal), + "Test %s, glyph %d, vertex normal %d, result (%g, %g, %g), expected (%g, %g, %g)\n", name, i, vtx_idx1, + vertices[vtx_idx1].normal.x, vertices[vtx_idx1].normal.y, vertices[vtx_idx1].normal.z, + vtx.normal.x, vtx.normal.y, vtx.normal.z); + vtx_idx1++; + first_vtx1++; + } + for (j = 0; j < nb_back_faces; j++) + { + int f1, f2; + if (extrusion == 0.0f) { + f1 = 1; + f2 = 2; + } else { + f1 = 2; + f2 = 1; + } + ok(faces[face_idx1][0] == faces[first_face1][0] + nb_back_vertices && + faces[face_idx1][1] == faces[first_face1][f1] + nb_back_vertices && + faces[face_idx1][2] == faces[first_face1][f2] + nb_back_vertices, + "Test %s, glyph %d, face %d, result (%d, %d, %d), expected (%d, %d, %d)\n", name, i, face_idx1, + faces[face_idx1][0], faces[face_idx1][1], faces[face_idx1][2], + faces[first_face1][0] - nb_back_faces, + faces[first_face1][f1] - nb_back_faces, + faces[first_face1][f2] - nb_back_faces); + first_face1++; + face_idx1++; + } + + /* skip to the outline for the next glyph */ + for (; vtx_idx2 < mesh->number_of_vertices; vtx_idx2++) { + if (mesh->vertices[vtx_idx2].normal.z == 0) + break; + } + for (; face_idx2 < mesh->number_of_faces; face_idx2++) + { + if (mesh->faces[face_idx2][0] >= vtx_idx2 || + mesh->faces[face_idx2][1] >= vtx_idx2 || + mesh->faces[face_idx2][2] >= vtx_idx2) break; + } + } + + IDirect3DIndexBuffer9_Unlock(index_buffer); + IDirect3DVertexBuffer9_Unlock(vertex_buffer); + IDirect3DIndexBuffer9_Release(index_buffer); + IDirect3DVertexBuffer9_Release(vertex_buffer); +} + +static void test_createtext(IDirect3DDevice9 *device, HDC hdc, const char *text, float deviation, float extrusion) +{ + static const MAT2 identity = {{0, 1}, {0, 0}, {0, 0}, {0, 1}}; + HRESULT hr; + ID3DXMesh *d3dxmesh = NULL; + struct mesh mesh = {0}; + char name[256]; + OUTLINETEXTMETRICA otm; + GLYPHMETRICS gm; + struct glyphinfo *glyphs; + GLYPHMETRICSFLOAT *glyphmetrics_float = HeapAlloc(GetProcessHeap(), 0, sizeof(GLYPHMETRICSFLOAT) * strlen(text)); + int i; + LOGFONTA lf; + float offset_x; + size_t textlen; + HFONT font = NULL, oldfont = NULL; + char *raw_outline; + + sprintf(name, "text ('%s', %f, %f)", text, deviation, extrusion); + + hr = D3DXCreateTextA(device, hdc, text, deviation, extrusion, &d3dxmesh, NULL, glyphmetrics_float); + ok(hr == D3D_OK, "Got result %x, expected 0 (D3D_OK)\n", hr); + + /* must select a modified font having lfHeight = otm.otmEMSquare before + * calling GetGlyphOutline to get the expected values */ + ok(GetObjectA(GetCurrentObject(hdc, OBJ_FONT), sizeof(lf), &lf), "Failed to get current DC font.\n"); + ok(GetOutlineTextMetricsA(hdc, sizeof(otm), &otm), "Failed to get DC font outline.\n"); + lf.lfHeight = otm.otmEMSquare; + lf.lfWidth = 0; + ok(!!(font = CreateFontIndirectA(&lf)), "Failed to create font.\n"); + + textlen = strlen(text); + glyphs = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, textlen * sizeof(*glyphs)); + oldfont = SelectObject(hdc, font); + + for (i = 0; i < textlen; i++) + { + GetGlyphOutlineA(hdc, text[i], GGO_NATIVE, &gm, 0, NULL, &identity); + compare_float(glyphmetrics_float[i].gmfBlackBoxX, gm.gmBlackBoxX / (float)otm.otmEMSquare); + compare_float(glyphmetrics_float[i].gmfBlackBoxY, gm.gmBlackBoxY / (float)otm.otmEMSquare); + compare_float(glyphmetrics_float[i].gmfptGlyphOrigin.x, gm.gmptGlyphOrigin.x / (float)otm.otmEMSquare); + compare_float(glyphmetrics_float[i].gmfptGlyphOrigin.y, gm.gmptGlyphOrigin.y / (float)otm.otmEMSquare); + compare_float(glyphmetrics_float[i].gmfCellIncX, gm.gmCellIncX / (float)otm.otmEMSquare); + compare_float(glyphmetrics_float[i].gmfCellIncY, gm.gmCellIncY / (float)otm.otmEMSquare); + } + + if (deviation == 0.0f) + deviation = 1.0f / otm.otmEMSquare; + + offset_x = 0.0f; + for (i = 0; i < textlen; i++) + { + DWORD datasize; + + glyphs[i].offset_x = offset_x; + + datasize = GetGlyphOutlineA(hdc, text[i], GGO_NATIVE, &gm, 0, NULL, &identity); + ok(datasize != GDI_ERROR, "Failed to retrieve GDI glyph outline size.\n"); + raw_outline = HeapAlloc(GetProcessHeap(), 0, datasize); + datasize = GetGlyphOutlineA(hdc, text[i], GGO_NATIVE, &gm, datasize, raw_outline, &identity); + ok(datasize != GDI_ERROR, "Failed to retrieve GDI glyph outline.\n"); + create_outline(&glyphs[i], raw_outline, datasize, deviation, otm.otmEMSquare); + HeapFree(GetProcessHeap(), 0, raw_outline); + + offset_x += gm.gmCellIncX / (float)otm.otmEMSquare; + } + + SelectObject(hdc, oldfont); + + compute_text_mesh(&mesh, text, deviation, extrusion, otm.otmEMSquare, glyphs); + mesh.fvf = D3DFVF_XYZ | D3DFVF_NORMAL; + + compare_text_outline_mesh(name, d3dxmesh, &mesh, textlen, extrusion, glyphs); + + free_mesh(&mesh); + d3dxmesh->lpVtbl->Release(d3dxmesh); + DeleteObject(font); + HeapFree(GetProcessHeap(), 0, glyphmetrics_float); + + for (i = 0; i < textlen; i++) + free_glyphinfo(&glyphs[i]); + HeapFree(GetProcessHeap(), 0, glyphs); +} + +static void D3DXCreateTextTest(void) +{ + HRESULT hr; + HDC hdc; + IDirect3DDevice9* device; + ID3DXMesh* d3dxmesh = NULL; + HFONT hFont; + OUTLINETEXTMETRICA otm; + int number_of_vertices; + int number_of_faces; + struct test_context *test_context; + + if (!(test_context = new_test_context())) + { + skip("Couldn't create test context\n"); + return; + } + device = test_context->device; + + hdc = CreateCompatibleDC(NULL); + + hFont = CreateFontA(12, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, DEFAULT_CHARSET, OUT_DEFAULT_PRECIS, + CLIP_DEFAULT_PRECIS, DEFAULT_QUALITY, DEFAULT_PITCH | FF_DONTCARE, "Arial"); + SelectObject(hdc, hFont); + GetOutlineTextMetricsA(hdc, sizeof(otm), &otm); + + hr = D3DXCreateTextA(device, hdc, "wine", 0.001f, 0.4f, NULL, NULL, NULL); + ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n", hr, D3DERR_INVALIDCALL); + + /* D3DXCreateTextA page faults from passing NULL text */ + + hr = D3DXCreateTextW(device, hdc, NULL, 0.001f, 0.4f, &d3dxmesh, NULL, NULL); + ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n", hr, D3DERR_INVALIDCALL); + + hr = D3DXCreateTextA(device, hdc, "", 0.001f, 0.4f, &d3dxmesh, NULL, NULL); + ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n", hr, D3DERR_INVALIDCALL); + + hr = D3DXCreateTextA(device, hdc, " ", 0.001f, 0.4f, &d3dxmesh, NULL, NULL); + ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n", hr, D3DERR_INVALIDCALL); + + hr = D3DXCreateTextA(NULL, hdc, "wine", 0.001f, 0.4f, &d3dxmesh, NULL, NULL); + ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n", hr, D3DERR_INVALIDCALL); + + hr = D3DXCreateTextA(device, NULL, "wine", 0.001f, 0.4f, &d3dxmesh, NULL, NULL); + ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n", hr, D3DERR_INVALIDCALL); + + hr = D3DXCreateTextA(device, hdc, "wine", -FLT_MIN, 0.4f, &d3dxmesh, NULL, NULL); + ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n", hr, D3DERR_INVALIDCALL); + + hr = D3DXCreateTextA(device, hdc, "wine", 0.001f, -FLT_MIN, &d3dxmesh, NULL, NULL); + ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n", hr, D3DERR_INVALIDCALL); + + /* deviation = 0.0f treated as if deviation = 1.0f / otm.otmEMSquare */ + hr = D3DXCreateTextA(device, hdc, "wine", 1.0f / otm.otmEMSquare, 0.4f, &d3dxmesh, NULL, NULL); + ok(hr == D3D_OK, "Got result %x, expected %x (D3D_OK)\n", hr, D3D_OK); + number_of_vertices = d3dxmesh->lpVtbl->GetNumVertices(d3dxmesh); + number_of_faces = d3dxmesh->lpVtbl->GetNumFaces(d3dxmesh); + d3dxmesh->lpVtbl->Release(d3dxmesh); + + hr = D3DXCreateTextA(device, hdc, "wine", 0.0f, 0.4f, &d3dxmesh, NULL, NULL); + ok(hr == D3D_OK, "Got result %x, expected %x (D3D_OK)\n", hr, D3D_OK); + ok(number_of_vertices == d3dxmesh->lpVtbl->GetNumVertices(d3dxmesh), + "Got %d vertices, expected %d\n", + d3dxmesh->lpVtbl->GetNumVertices(d3dxmesh), number_of_vertices); + ok(number_of_faces == d3dxmesh->lpVtbl->GetNumFaces(d3dxmesh), + "Got %d faces, expected %d\n", + d3dxmesh->lpVtbl->GetNumVertices(d3dxmesh), number_of_faces); + d3dxmesh->lpVtbl->Release(d3dxmesh); + +if (0) +{ + /* too much detail requested, so will appear to hang */ + trace("Waiting for D3DXCreateText to finish with deviation = FLT_MIN ...\n"); + hr = D3DXCreateTextA(device, hdc, "wine", FLT_MIN, 0.4f, &d3dxmesh, NULL, NULL); + ok(hr == D3D_OK, "Got result %x, expected %x (D3D_OK)\n", hr, D3D_OK); + if (SUCCEEDED(hr) && d3dxmesh) d3dxmesh->lpVtbl->Release(d3dxmesh); + trace("D3DXCreateText finish with deviation = FLT_MIN\n"); +} + + hr = D3DXCreateTextA(device, hdc, "wine", 0.001f, 0.4f, &d3dxmesh, NULL, NULL); + ok(hr == D3D_OK, "Got result %x, expected %x (D3D_OK)\n", hr, D3D_OK); + if (SUCCEEDED(hr) && d3dxmesh) d3dxmesh->lpVtbl->Release(d3dxmesh); + + test_createtext(device, hdc, "wine", FLT_MAX, 0.4f); + test_createtext(device, hdc, "wine", 0.001f, FLT_MIN); + test_createtext(device, hdc, "wine", 0.001f, 0.0f); + test_createtext(device, hdc, "wine", 0.001f, FLT_MAX); + test_createtext(device, hdc, "wine", 0.0f, 1.0f); + test_createtext(device, hdc, " wine", 1.0f, 0.0f); + test_createtext(device, hdc, "wine ", 1.0f, 0.0f); + test_createtext(device, hdc, "wi ne", 1.0f, 0.0f); + + DeleteDC(hdc); + DeleteObject(hFont); + + free_test_context(test_context); +} + +static void test_get_decl_length(void) +{ + static const D3DVERTEXELEMENT9 declaration1[] = + { + {0, 0, D3DDECLTYPE_FLOAT1, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0}, + {1, 0, D3DDECLTYPE_FLOAT2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0}, + {2, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0}, + {3, 0, D3DDECLTYPE_FLOAT4, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0}, + {4, 0, D3DDECLTYPE_D3DCOLOR, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0}, + {5, 0, D3DDECLTYPE_UBYTE4, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0}, + {6, 0, D3DDECLTYPE_SHORT2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0}, + {7, 0, D3DDECLTYPE_SHORT4, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0}, + {8, 0, D3DDECLTYPE_UBYTE4N, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0}, + {9, 0, D3DDECLTYPE_SHORT2N, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0}, + {10, 0, D3DDECLTYPE_SHORT4N, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0}, + {11, 0, D3DDECLTYPE_UDEC3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0}, + {12, 0, D3DDECLTYPE_DEC3N, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0}, + {13, 0, D3DDECLTYPE_FLOAT16_2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0}, + {14, 0, D3DDECLTYPE_FLOAT16_4, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0}, + D3DDECL_END(), + }; + static const D3DVERTEXELEMENT9 declaration2[] = + { + {0, 8, D3DDECLTYPE_FLOAT1, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0}, + {1, 8, D3DDECLTYPE_FLOAT2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0}, + {2, 8, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0}, + {3, 8, D3DDECLTYPE_FLOAT4, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0}, + {4, 8, D3DDECLTYPE_D3DCOLOR, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0}, + {5, 8, D3DDECLTYPE_UBYTE4, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0}, + {6, 8, D3DDECLTYPE_SHORT2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0}, + {7, 8, D3DDECLTYPE_SHORT4, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0}, + {0, 8, D3DDECLTYPE_UBYTE4N, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0}, + {1, 8, D3DDECLTYPE_SHORT2N, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0}, + {2, 8, D3DDECLTYPE_SHORT4N, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0}, + {3, 8, D3DDECLTYPE_UDEC3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0}, + {4, 8, D3DDECLTYPE_DEC3N, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0}, + {5, 8, D3DDECLTYPE_FLOAT16_2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0}, + {6, 8, D3DDECLTYPE_FLOAT16_4, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0}, + {7, 8, D3DDECLTYPE_FLOAT1, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0}, + D3DDECL_END(), + }; + UINT size; + + size = D3DXGetDeclLength(declaration1); + ok(size == 15, "Got size %u, expected 15.\n", size); + + size = D3DXGetDeclLength(declaration2); + ok(size == 16, "Got size %u, expected 16.\n", size); +} + +static void test_get_decl_vertex_size(void) +{ + static const D3DVERTEXELEMENT9 declaration1[] = + { + {0, 0, D3DDECLTYPE_FLOAT1, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0}, + {1, 0, D3DDECLTYPE_FLOAT2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0}, + {2, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0}, + {3, 0, D3DDECLTYPE_FLOAT4, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0}, + {4, 0, D3DDECLTYPE_D3DCOLOR, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0}, + {5, 0, D3DDECLTYPE_UBYTE4, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0}, + {6, 0, D3DDECLTYPE_SHORT2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0}, + {7, 0, D3DDECLTYPE_SHORT4, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0}, + {8, 0, D3DDECLTYPE_UBYTE4N, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0}, + {9, 0, D3DDECLTYPE_SHORT2N, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0}, + {10, 0, D3DDECLTYPE_SHORT4N, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0}, + {11, 0, D3DDECLTYPE_UDEC3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0}, + {12, 0, D3DDECLTYPE_DEC3N, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0}, + {13, 0, D3DDECLTYPE_FLOAT16_2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0}, + {14, 0, D3DDECLTYPE_FLOAT16_4, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0}, + D3DDECL_END(), + }; + static const D3DVERTEXELEMENT9 declaration2[] = + { + {0, 8, D3DDECLTYPE_FLOAT1, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0}, + {1, 8, D3DDECLTYPE_FLOAT2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0}, + {2, 8, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0}, + {3, 8, D3DDECLTYPE_FLOAT4, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0}, + {4, 8, D3DDECLTYPE_D3DCOLOR, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0}, + {5, 8, D3DDECLTYPE_UBYTE4, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0}, + {6, 8, D3DDECLTYPE_SHORT2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0}, + {7, 8, D3DDECLTYPE_SHORT4, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0}, + {0, 8, D3DDECLTYPE_UBYTE4N, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0}, + {1, 8, D3DDECLTYPE_SHORT2N, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0}, + {2, 8, D3DDECLTYPE_SHORT4N, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0}, + {3, 8, D3DDECLTYPE_UDEC3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0}, + {4, 8, D3DDECLTYPE_DEC3N, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0}, + {5, 8, D3DDECLTYPE_FLOAT16_2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0}, + {6, 8, D3DDECLTYPE_FLOAT16_4, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0}, + {7, 8, D3DDECLTYPE_FLOAT1, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0}, + D3DDECL_END(), + }; + static const UINT sizes1[] = + { + 4, 8, 12, 16, + 4, 4, 4, 8, + 4, 4, 8, 4, + 4, 4, 8, 0, + }; + static const UINT sizes2[] = + { + 12, 16, 20, 24, + 12, 12, 16, 16, + }; + unsigned int i; + UINT size; + + size = D3DXGetDeclVertexSize(NULL, 0); + ok(size == 0, "Got size %#x, expected 0.\n", size); + + for (i = 0; i < 16; ++i) + { + size = D3DXGetDeclVertexSize(declaration1, i); + ok(size == sizes1[i], "Got size %u for stream %u, expected %u.\n", size, i, sizes1[i]); + } + + for (i = 0; i < 8; ++i) + { + size = D3DXGetDeclVertexSize(declaration2, i); + ok(size == sizes2[i], "Got size %u for stream %u, expected %u.\n", size, i, sizes2[i]); + } +} + +static void D3DXGenerateAdjacencyTest(void) +{ + HRESULT hr; + IDirect3DDevice9 *device; + ID3DXMesh *d3dxmesh = NULL; + D3DXVECTOR3 *vertices = NULL; + WORD *indices = NULL; + int i; + struct { + DWORD num_vertices; + D3DXVECTOR3 vertices[6]; + DWORD num_faces; + WORD indices[3 * 3]; + FLOAT epsilon; + DWORD adjacency[3 * 3]; + } test_data[] = { + { /* for epsilon < 0, indices must match for faces to be adjacent */ + 4, {{0.0, 0.0, 0.0}, {1.0, 0.0, 0.0}, {1.0, 1.0, 0.0}, {0.0, 1.0, 0.0}}, + 2, {0, 1, 2, 0, 2, 3}, + -1.0, + {-1, -1, 1, 0, -1, -1}, + }, + { + 6, {{0.0, 0.0, 0.0}, {1.0, 0.0, 0.0}, {1.0, 1.0, 0.0}, {0.0, 0.0, 0.0}, {1.0, 1.0, 0.0}, {0.0, 1.0, 0.0}}, + 2, {0, 1, 2, 3, 4, 5}, + -1.0, + {-1, -1, -1, -1, -1, -1}, + }, + { /* for epsilon == 0, indices or vertices must match for faces to be adjacent */ + 6, {{0.0, 0.0, 0.0}, {1.0, 0.0, 0.0}, {1.0, 1.0, 0.0}, {0.0, 0.0, 0.0}, {1.0, 1.0, 0.0}, {0.0, 1.0, 0.0}}, + 2, {0, 1, 2, 3, 4, 5}, + 0.0, + {-1, -1, 1, 0, -1, -1}, + }, + { /* for epsilon > 0, vertices must be less than (but NOT equal to) epsilon distance away */ + 6, {{0.0, 0.0, 0.0}, {1.0, 0.0, 0.0}, {1.0, 1.0, 0.0}, {0.0, 0.0, 0.25}, {1.0, 1.0, 0.25}, {0.0, 1.0, 0.25}}, + 2, {0, 1, 2, 3, 4, 5}, + 0.25, + {-1, -1, -1, -1, -1, -1}, + }, + { /* for epsilon > 0, vertices must be less than (but NOT equal to) epsilon distance away */ + 6, {{0.0, 0.0, 0.0}, {1.0, 0.0, 0.0}, {1.0, 1.0, 0.0}, {0.0, 0.0, 0.25}, {1.0, 1.0, 0.25}, {0.0, 1.0, 0.25}}, + 2, {0, 1, 2, 3, 4, 5}, + 0.250001, + {-1, -1, 1, 0, -1, -1}, + }, + { /* length between vertices are compared to epsilon, not the individual dimension deltas */ + 6, {{0.0, 0.0, 0.0}, {1.0, 0.0, 0.0}, {1.0, 1.0, 0.0}, {0.0, 0.25, 0.25}, {1.0, 1.25, 0.25}, {0.0, 1.25, 0.25}}, + 2, {0, 1, 2, 3, 4, 5}, + 0.353, /* < sqrt(0.25*0.25 + 0.25*0.25) */ + {-1, -1, -1, -1, -1, -1}, + }, + { + 6, {{0.0, 0.0, 0.0}, {1.0, 0.0, 0.0}, {1.0, 1.0, 0.0}, {0.0, 0.25, 0.25}, {1.0, 1.25, 0.25}, {0.0, 1.25, 0.25}}, + 2, {0, 1, 2, 3, 4, 5}, + 0.354, /* > sqrt(0.25*0.25 + 0.25*0.25) */ + {-1, -1, 1, 0, -1, -1}, + }, + { /* adjacent faces must have opposite winding orders at the shared edge */ + 4, {{0.0, 0.0, 0.0}, {1.0, 0.0, 0.0}, {1.0, 1.0, 0.0}, {0.0, 1.0, 0.0}}, + 2, {0, 1, 2, 0, 3, 2}, + 0.0, + {-1, -1, -1, -1, -1, -1}, + }, + }; + struct test_context *test_context; + + if (!(test_context = new_test_context())) + { + skip("Couldn't create test context\n"); + return; + } + device = test_context->device; + + for (i = 0; i < ARRAY_SIZE(test_data); i++) + { + DWORD adjacency[ARRAY_SIZE(test_data[0].adjacency)]; + int j; + + if (d3dxmesh) d3dxmesh->lpVtbl->Release(d3dxmesh); + d3dxmesh = NULL; + + hr = D3DXCreateMeshFVF(test_data[i].num_faces, test_data[i].num_vertices, 0, D3DFVF_XYZ, device, &d3dxmesh); + ok(hr == D3D_OK, "Got result %x, expected %x (D3D_OK)\n", hr, D3D_OK); + + hr = d3dxmesh->lpVtbl->LockVertexBuffer(d3dxmesh, D3DLOCK_DISCARD, (void**)&vertices); + ok(hr == D3D_OK, "test %d: Got result %x, expected %x (D3D_OK)\n", i, hr, D3D_OK); + if (FAILED(hr)) continue; + CopyMemory(vertices, test_data[i].vertices, test_data[i].num_vertices * sizeof(test_data[0].vertices[0])); + d3dxmesh->lpVtbl->UnlockVertexBuffer(d3dxmesh); + + hr = d3dxmesh->lpVtbl->LockIndexBuffer(d3dxmesh, D3DLOCK_DISCARD, (void**)&indices); + ok(hr == D3D_OK, "test %d: Got result %x, expected %x (D3D_OK)\n", i, hr, D3D_OK); + if (FAILED(hr)) continue; + CopyMemory(indices, test_data[i].indices, test_data[i].num_faces * 3 * sizeof(test_data[0].indices[0])); + d3dxmesh->lpVtbl->UnlockIndexBuffer(d3dxmesh); + + if (i == 0) { + hr = d3dxmesh->lpVtbl->GenerateAdjacency(d3dxmesh, 0.0f, NULL); + ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n", hr, D3DERR_INVALIDCALL); + } + + hr = d3dxmesh->lpVtbl->GenerateAdjacency(d3dxmesh, test_data[i].epsilon, adjacency); + ok(hr == D3D_OK, "Got result %x, expected %x (D3D_OK)\n", hr, D3D_OK); + if (FAILED(hr)) continue; + + for (j = 0; j < test_data[i].num_faces * 3; j++) + ok(adjacency[j] == test_data[i].adjacency[j], + "Test %d adjacency %d: Got result %u, expected %u\n", i, j, + adjacency[j], test_data[i].adjacency[j]); + } + if (d3dxmesh) d3dxmesh->lpVtbl->Release(d3dxmesh); + + free_test_context(test_context); +} + +static void test_update_semantics(void) +{ + HRESULT hr; + struct test_context *test_context = NULL; + ID3DXMesh *mesh = NULL; + D3DVERTEXELEMENT9 declaration0[] = + { + {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0}, + {0, 24, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL, 0}, + {0, 36, D3DDECLTYPE_D3DCOLOR, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_COLOR, 0}, + D3DDECL_END() + }; + D3DVERTEXELEMENT9 declaration_pos_type_color[] = + { + {0, 0, D3DDECLTYPE_D3DCOLOR, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0}, + {0, 24, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL, 0}, + {0, 36, D3DDECLTYPE_D3DCOLOR, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_COLOR, 0}, + D3DDECL_END() + }; + D3DVERTEXELEMENT9 declaration_smaller[] = + { + {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0}, + {0, 24, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL, 0}, + D3DDECL_END() + }; + D3DVERTEXELEMENT9 declaration_larger[] = + { + {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0}, + {0, 24, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL, 0}, + {0, 36, D3DDECLTYPE_D3DCOLOR, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_COLOR, 0}, + {0, 40, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TANGENT, 0}, + D3DDECL_END() + }; + D3DVERTEXELEMENT9 declaration_multiple_streams[] = + { + {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0}, + {1, 12, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TANGENT, 0}, + {0, 24, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL, 0}, + {0, 36, D3DDECLTYPE_D3DCOLOR, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_COLOR, 0}, + + D3DDECL_END() + }; + D3DVERTEXELEMENT9 declaration_double_usage[] = + { + {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0}, + {0, 12, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0}, + {0, 24, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL, 0}, + {0, 36, D3DDECLTYPE_D3DCOLOR, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_COLOR, 0}, + D3DDECL_END() + }; + D3DVERTEXELEMENT9 declaration_undefined_type[] = + { + {0, 0, D3DDECLTYPE_UNUSED+1, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0}, + {0, 24, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL, 0}, + {0, 36, D3DDECLTYPE_D3DCOLOR, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_COLOR, 0}, + D3DDECL_END() + }; + D3DVERTEXELEMENT9 declaration_not_4_byte_aligned_offset[] = + { + {0, 3, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0}, + {0, 24, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL, 0}, + {0, 36, D3DDECLTYPE_D3DCOLOR, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_COLOR, 0}, + D3DDECL_END() + }; + static const struct + { + D3DXVECTOR3 position0; + D3DXVECTOR3 position1; + D3DXVECTOR3 normal; + DWORD color; + } + vertices[] = + { + { { 0.0f, 1.0f, 0.f}, { 1.0f, 0.0f, 0.f}, {0.0f, 0.0f, 1.0f}, 0xffff0000 }, + { { 1.0f, -1.0f, 0.f}, {-1.0f, -1.0f, 0.f}, {0.0f, 0.0f, 1.0f}, 0xff00ff00 }, + { {-1.0f, -1.0f, 0.f}, {-1.0f, 1.0f, 0.f}, {0.0f, 0.0f, 1.0f}, 0xff0000ff }, + }; + unsigned int faces[] = {0, 1, 2}; + unsigned int attributes[] = {0}; + unsigned int num_faces = ARRAY_SIZE(faces) / 3; + unsigned int num_vertices = ARRAY_SIZE(vertices); + int offset = sizeof(D3DXVECTOR3); + DWORD options = D3DXMESH_32BIT | D3DXMESH_SYSTEMMEM; + void *vertex_buffer; + void *index_buffer; + DWORD *attributes_buffer; + D3DVERTEXELEMENT9 declaration[MAX_FVF_DECL_SIZE]; + D3DVERTEXELEMENT9 *decl_ptr; + DWORD exp_vertex_size = sizeof(*vertices); + DWORD vertex_size = 0; + int equal; + int i = 0; + int *decl_mem; + int filler_a = 0xaaaaaaaa; + int filler_b = 0xbbbbbbbb; + + test_context = new_test_context(); + if (!test_context) + { + skip("Couldn't create a test_context\n"); + goto cleanup; + } + + hr = D3DXCreateMesh(num_faces, num_vertices, options, declaration0, + test_context->device, &mesh); + if (FAILED(hr)) + { + skip("Couldn't create test mesh %#x\n", hr); + goto cleanup; + } + + mesh->lpVtbl->LockVertexBuffer(mesh, 0, &vertex_buffer); + memcpy(vertex_buffer, vertices, sizeof(vertices)); + mesh->lpVtbl->UnlockVertexBuffer(mesh); + + mesh->lpVtbl->LockIndexBuffer(mesh, 0, &index_buffer); + memcpy(index_buffer, faces, sizeof(faces)); + mesh->lpVtbl->UnlockIndexBuffer(mesh); + + mesh->lpVtbl->LockAttributeBuffer(mesh, 0, &attributes_buffer); + memcpy(attributes_buffer, attributes, sizeof(attributes)); + mesh->lpVtbl->UnlockAttributeBuffer(mesh); + + /* Get the declaration and try to change it */ + hr = mesh->lpVtbl->GetDeclaration(mesh, declaration); + if (FAILED(hr)) + { + skip("Couldn't get vertex declaration %#x\n", hr); + goto cleanup; + } + equal = memcmp(declaration, declaration0, sizeof(declaration0)); + ok(equal == 0, "Vertex declarations were not equal\n"); + + for (decl_ptr = declaration; decl_ptr->Stream != 0xFF; decl_ptr++) + { + if (decl_ptr->Usage == D3DDECLUSAGE_POSITION) + { + /* Use second vertex position instead of first */ + decl_ptr->Offset = offset; + } + } + + hr = mesh->lpVtbl->UpdateSemantics(mesh, declaration); + ok(hr == D3D_OK, "Test UpdateSemantics, got %#x expected %#x\n", hr, D3D_OK); + + /* Check that declaration was written by getting it again */ + memset(declaration, 0, sizeof(declaration)); + hr = mesh->lpVtbl->GetDeclaration(mesh, declaration); + if (FAILED(hr)) + { + skip("Couldn't get vertex declaration %#x\n", hr); + goto cleanup; + } + + for (decl_ptr = declaration; decl_ptr->Stream != 0xFF; decl_ptr++) + { + if (decl_ptr->Usage == D3DDECLUSAGE_POSITION) + { + ok(decl_ptr->Offset == offset, "Test UpdateSemantics, got offset %d expected %d\n", + decl_ptr->Offset, offset); + } + } + + /* Check that GetDeclaration only writes up to the D3DDECL_END() marker and + * not the full MAX_FVF_DECL_SIZE elements. + */ + memset(declaration, filler_a, sizeof(declaration)); + memcpy(declaration, declaration0, sizeof(declaration0)); + hr = mesh->lpVtbl->UpdateSemantics(mesh, declaration); + ok(hr == D3D_OK, "Test UpdateSemantics, " + "got %#x expected D3D_OK\n", hr); + memset(declaration, filler_b, sizeof(declaration)); + hr = mesh->lpVtbl->GetDeclaration(mesh, declaration); + ok(hr == D3D_OK, "Couldn't get vertex declaration. Got %#x, expected D3D_OK\n", hr); + decl_mem = (int*)declaration; + for (i = sizeof(declaration0)/sizeof(*decl_mem); i < sizeof(declaration)/sizeof(*decl_mem); i++) + { + equal = memcmp(&decl_mem[i], &filler_b, sizeof(filler_b)); + ok(equal == 0, + "GetDeclaration wrote past the D3DDECL_END() marker. " + "Got %#x, expected %#x\n", decl_mem[i], filler_b); + if (equal != 0) break; + } + + /* UpdateSemantics does not check for overlapping fields */ + memset(declaration, 0, sizeof(declaration)); + hr = mesh->lpVtbl->GetDeclaration(mesh, declaration); + if (FAILED(hr)) + { + skip("Couldn't get vertex declaration %#x\n", hr); + goto cleanup; + } + + for (decl_ptr = declaration; decl_ptr->Stream != 0xFF; decl_ptr++) + { + if (decl_ptr->Type == D3DDECLTYPE_FLOAT3) + { + decl_ptr->Type = D3DDECLTYPE_FLOAT4; + } + } + + hr = mesh->lpVtbl->UpdateSemantics(mesh, declaration); + ok(hr == D3D_OK, "Test UpdateSemantics for overlapping fields, " + "got %#x expected D3D_OK\n", hr); + + /* Set the position type to color instead of float3 */ + hr = mesh->lpVtbl->UpdateSemantics(mesh, declaration_pos_type_color); + ok(hr == D3D_OK, "Test UpdateSemantics position type color, " + "got %#x expected D3D_OK\n", hr); + + /* The following test cases show that NULL, smaller or larger declarations, + * and declarations with non-zero Stream values are not accepted. + * UpdateSemantics returns D3DERR_INVALIDCALL and the previously set + * declaration will be used by DrawSubset, GetNumBytesPerVertex, and + * GetDeclaration. + */ + + /* Null declaration (invalid declaration) */ + mesh->lpVtbl->UpdateSemantics(mesh, declaration0); /* Set a valid declaration */ + hr = mesh->lpVtbl->UpdateSemantics(mesh, NULL); + ok(hr == D3DERR_INVALIDCALL, "Test UpdateSemantics null pointer declaration, " + "got %#x expected D3DERR_INVALIDCALL\n", hr); + vertex_size = mesh->lpVtbl->GetNumBytesPerVertex(mesh); + ok(vertex_size == exp_vertex_size, "Got vertex declaration size %u, expected %u\n", + vertex_size, exp_vertex_size); + memset(declaration, 0, sizeof(declaration)); + hr = mesh->lpVtbl->GetDeclaration(mesh, declaration); + ok(hr == D3D_OK, "Couldn't get vertex declaration. Got %#x, expected D3D_OK\n", hr); + equal = memcmp(declaration, declaration0, sizeof(declaration0)); + ok(equal == 0, "Vertex declarations were not equal\n"); + + /* Smaller vertex declaration (invalid declaration) */ + mesh->lpVtbl->UpdateSemantics(mesh, declaration0); /* Set a valid declaration */ + hr = mesh->lpVtbl->UpdateSemantics(mesh, declaration_smaller); + ok(hr == D3DERR_INVALIDCALL, "Test UpdateSemantics for smaller vertex declaration, " + "got %#x expected D3DERR_INVALIDCALL\n", hr); + vertex_size = mesh->lpVtbl->GetNumBytesPerVertex(mesh); + ok(vertex_size == exp_vertex_size, "Got vertex declaration size %u, expected %u\n", + vertex_size, exp_vertex_size); + memset(declaration, 0, sizeof(declaration)); + hr = mesh->lpVtbl->GetDeclaration(mesh, declaration); + ok(hr == D3D_OK, "Couldn't get vertex declaration. Got %#x, expected D3D_OK\n", hr); + equal = memcmp(declaration, declaration0, sizeof(declaration0)); + ok(equal == 0, "Vertex declarations were not equal\n"); + + /* Larger vertex declaration (invalid declaration) */ + mesh->lpVtbl->UpdateSemantics(mesh, declaration0); /* Set a valid declaration */ + hr = mesh->lpVtbl->UpdateSemantics(mesh, declaration_larger); + ok(hr == D3DERR_INVALIDCALL, "Test UpdateSemantics for larger vertex declaration, " + "got %#x expected D3DERR_INVALIDCALL\n", hr); + vertex_size = mesh->lpVtbl->GetNumBytesPerVertex(mesh); + ok(vertex_size == exp_vertex_size, "Got vertex declaration size %u, expected %u\n", + vertex_size, exp_vertex_size); + memset(declaration, 0, sizeof(declaration)); + hr = mesh->lpVtbl->GetDeclaration(mesh, declaration); + ok(hr == D3D_OK, "Couldn't get vertex declaration. Got %#x, expected D3D_OK\n", hr); + equal = memcmp(declaration, declaration0, sizeof(declaration0)); + ok(equal == 0, "Vertex declarations were not equal\n"); + + /* Use multiple streams and keep the same vertex size (invalid declaration) */ + mesh->lpVtbl->UpdateSemantics(mesh, declaration0); /* Set a valid declaration */ + hr = mesh->lpVtbl->UpdateSemantics(mesh, declaration_multiple_streams); + ok(hr == D3DERR_INVALIDCALL, "Test UpdateSemantics using multiple streams, " + "got %#x expected D3DERR_INVALIDCALL\n", hr); + vertex_size = mesh->lpVtbl->GetNumBytesPerVertex(mesh); + ok(vertex_size == exp_vertex_size, "Got vertex declaration size %u, expected %u\n", + vertex_size, exp_vertex_size); + memset(declaration, 0, sizeof(declaration)); + hr = mesh->lpVtbl->GetDeclaration(mesh, declaration); + ok(hr == D3D_OK, "Couldn't get vertex declaration. Got %#x, expected D3D_OK\n", hr); + equal = memcmp(declaration, declaration0, sizeof(declaration0)); + ok(equal == 0, "Vertex declarations were not equal\n"); + + /* The next following test cases show that some invalid declarations are + * accepted with a D3D_OK. An access violation is thrown on Windows if + * DrawSubset is called. The methods GetNumBytesPerVertex and GetDeclaration + * are not affected, which indicates that the declaration is cached. + */ + + /* Double usage (invalid declaration) */ + mesh->lpVtbl->UpdateSemantics(mesh, declaration0); /* Set a valid declaration */ + hr = mesh->lpVtbl->UpdateSemantics(mesh, declaration_double_usage); + ok(hr == D3D_OK, "Test UpdateSemantics double usage, " + "got %#x expected D3D_OK\n", hr); + vertex_size = mesh->lpVtbl->GetNumBytesPerVertex(mesh); + ok(vertex_size == exp_vertex_size, "Got vertex declaration size %u, expected %u\n", + vertex_size, exp_vertex_size); + memset(declaration, 0, sizeof(declaration)); + hr = mesh->lpVtbl->GetDeclaration(mesh, declaration); + ok(hr == D3D_OK, "Couldn't get vertex declaration. Got %#x, expected D3D_OK\n", hr); + equal = memcmp(declaration, declaration_double_usage, sizeof(declaration_double_usage)); + ok(equal == 0, "Vertex declarations were not equal\n"); + + /* Set the position to an undefined type (invalid declaration) */ + mesh->lpVtbl->UpdateSemantics(mesh, declaration0); /* Set a valid declaration */ + hr = mesh->lpVtbl->UpdateSemantics(mesh, declaration_undefined_type); + ok(hr == D3D_OK, "Test UpdateSemantics undefined type, " + "got %#x expected D3D_OK\n", hr); + vertex_size = mesh->lpVtbl->GetNumBytesPerVertex(mesh); + ok(vertex_size == exp_vertex_size, "Got vertex declaration size %u, expected %u\n", + vertex_size, exp_vertex_size); + memset(declaration, 0, sizeof(declaration)); + hr = mesh->lpVtbl->GetDeclaration(mesh, declaration); + ok(hr == D3D_OK, "Couldn't get vertex declaration. Got %#x, expected D3D_OK\n", hr); + equal = memcmp(declaration, declaration_undefined_type, sizeof(declaration_undefined_type)); + ok(equal == 0, "Vertex declarations were not equal\n"); + + /* Use a not 4 byte aligned offset (invalid declaration) */ + mesh->lpVtbl->UpdateSemantics(mesh, declaration0); /* Set a valid declaration */ + hr = mesh->lpVtbl->UpdateSemantics(mesh, declaration_not_4_byte_aligned_offset); + ok(hr == D3D_OK, "Test UpdateSemantics not 4 byte aligned offset, " + "got %#x expected D3D_OK\n", hr); + vertex_size = mesh->lpVtbl->GetNumBytesPerVertex(mesh); + ok(vertex_size == exp_vertex_size, "Got vertex declaration size %u, expected %u\n", + vertex_size, exp_vertex_size); + memset(declaration, 0, sizeof(declaration)); + hr = mesh->lpVtbl->GetDeclaration(mesh, declaration); + ok(hr == D3D_OK, "Couldn't get vertex declaration. Got %#x, expected D3D_OK\n", hr); + equal = memcmp(declaration, declaration_not_4_byte_aligned_offset, + sizeof(declaration_not_4_byte_aligned_offset)); + ok(equal == 0, "Vertex declarations were not equal\n"); + +cleanup: + if (mesh) + mesh->lpVtbl->Release(mesh); + + free_test_context(test_context); +} + +static void test_create_skin_info(void) +{ + HRESULT hr; + ID3DXSkinInfo *skininfo = NULL; + D3DVERTEXELEMENT9 empty_declaration[] = { D3DDECL_END() }; + D3DVERTEXELEMENT9 declaration_out[MAX_FVF_DECL_SIZE]; + const D3DVERTEXELEMENT9 declaration_with_nonzero_stream[] = { + {1, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0}, + D3DDECL_END() + }; + + hr = D3DXCreateSkinInfo(0, empty_declaration, 0, &skininfo); + ok(hr == D3D_OK, "Expected D3D_OK, got %#x\n", hr); + if (skininfo) IUnknown_Release(skininfo); + skininfo = NULL; + + hr = D3DXCreateSkinInfo(1, NULL, 1, &skininfo); + ok(hr == D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, got %#x\n", hr); + + hr = D3DXCreateSkinInfo(1, declaration_with_nonzero_stream, 1, &skininfo); + ok(hr == D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, got %#x\n", hr); + + hr = D3DXCreateSkinInfoFVF(1, 0, 1, &skininfo); + ok(hr == D3D_OK, "Expected D3D_OK, got %#x\n", hr); + if (skininfo) + { + DWORD dword_result; + float flt_result; + const char *string_result; + D3DXMATRIX *transform; + D3DXMATRIX identity_matrix; + + /* test initial values */ + hr = skininfo->lpVtbl->GetDeclaration(skininfo, declaration_out); + ok(hr == D3D_OK, "Expected D3D_OK, got %#x\n", hr); + if (SUCCEEDED(hr)) + compare_elements(declaration_out, empty_declaration, __LINE__, 0); + + dword_result = skininfo->lpVtbl->GetNumBones(skininfo); + ok(dword_result == 1, "Expected 1, got %u\n", dword_result); + + flt_result = skininfo->lpVtbl->GetMinBoneInfluence(skininfo); + ok(flt_result == 0.0f, "Expected 0.0, got %g\n", flt_result); + + string_result = skininfo->lpVtbl->GetBoneName(skininfo, 0); + ok(string_result == NULL, "Expected NULL, got %p\n", string_result); + + dword_result = skininfo->lpVtbl->GetFVF(skininfo); + ok(dword_result == 0, "Expected 0, got %u\n", dword_result); + + dword_result = skininfo->lpVtbl->GetNumBoneInfluences(skininfo, 0); + ok(dword_result == 0, "Expected 0, got %u\n", dword_result); + + dword_result = skininfo->lpVtbl->GetNumBoneInfluences(skininfo, 1); + ok(dword_result == 0, "Expected 0, got %u\n", dword_result); + + transform = skininfo->lpVtbl->GetBoneOffsetMatrix(skininfo, -1); + ok(transform == NULL, "Expected NULL, got %p\n", transform); + + { + /* test [GS]etBoneOffsetMatrix */ + hr = skininfo->lpVtbl->SetBoneOffsetMatrix(skininfo, 1, &identity_matrix); + ok(hr == D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, got %#x\n", hr); + + hr = skininfo->lpVtbl->SetBoneOffsetMatrix(skininfo, 0, NULL); + ok(hr == D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, got %#x\n", hr); + + D3DXMatrixIdentity(&identity_matrix); + hr = skininfo->lpVtbl->SetBoneOffsetMatrix(skininfo, 0, &identity_matrix); + ok(hr == D3D_OK, "Expected D3D_OK, got %#x\n", hr); + + transform = skininfo->lpVtbl->GetBoneOffsetMatrix(skininfo, 0); + check_matrix(transform, &identity_matrix); + } + + { + /* test [GS]etBoneName */ + const char *name_in = "testBoneName"; + const char *string_result2; + + hr = skininfo->lpVtbl->SetBoneName(skininfo, 1, name_in); + ok(hr == D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, got %#x\n", hr); + + hr = skininfo->lpVtbl->SetBoneName(skininfo, 0, NULL); + ok(hr == D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, got %#x\n", hr); + + hr = skininfo->lpVtbl->SetBoneName(skininfo, 0, name_in); + ok(hr == D3D_OK, "Expected D3D_OK, got %#x\n", hr); + + string_result = skininfo->lpVtbl->GetBoneName(skininfo, 0); + ok(string_result != NULL, "Expected non-NULL string, got %p\n", string_result); + ok(!strcmp(string_result, name_in), "Expected '%s', got '%s'\n", name_in, string_result); + + string_result2 = skininfo->lpVtbl->GetBoneName(skininfo, 0); + ok(string_result == string_result2, "Expected %p, got %p\n", string_result, string_result2); + + string_result = skininfo->lpVtbl->GetBoneName(skininfo, 1); + ok(string_result == NULL, "Expected NULL, got %p\n", string_result); + } + + { + /* test [GS]etBoneInfluence */ + DWORD vertices[2]; + FLOAT weights[2]; + int i; + DWORD num_influences; + DWORD exp_vertices[2]; + FLOAT exp_weights[2]; + + /* vertex and weight arrays untouched when num_influences is 0 */ + vertices[0] = 0xdeadbeef; + weights[0] = FLT_MAX; + hr = skininfo->lpVtbl->GetBoneInfluence(skininfo, 0, vertices, weights); + ok(hr == D3D_OK, "Expected D3D_OK, got %#x\n", hr); + ok(vertices[0] == 0xdeadbeef, "expected 0xdeadbeef, got %#x\n", vertices[0]); + ok(weights[0] == FLT_MAX, "expected %g, got %g\n", FLT_MAX, weights[0]); + + hr = skininfo->lpVtbl->GetBoneInfluence(skininfo, 1, vertices, weights); + ok(hr == D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, got %#x\n", hr); + + hr = skininfo->lpVtbl->GetBoneInfluence(skininfo, 0, NULL, NULL); + ok(hr == D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, got %#x\n", hr); + + hr = skininfo->lpVtbl->GetBoneInfluence(skininfo, 0, vertices, NULL); + ok(hr == D3D_OK, "Expected D3D_OK, got %#x\n", hr); + + hr = skininfo->lpVtbl->GetBoneInfluence(skininfo, 0, NULL, weights); + ok(hr == D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, got %#x\n", hr); + + + /* no vertex or weight value checking */ + exp_vertices[0] = 0; + exp_vertices[1] = 0x87654321; + exp_weights[0] = 0.5; + exp_weights[1] = NAN; + num_influences = 2; + + hr = skininfo->lpVtbl->SetBoneInfluence(skininfo, 1, num_influences, vertices, weights); + ok(hr == D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, got %#x\n", hr); + + hr = skininfo->lpVtbl->SetBoneInfluence(skininfo, 0, num_influences, NULL, weights); + ok(hr == D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, got %#x\n", hr); + + hr = skininfo->lpVtbl->SetBoneInfluence(skininfo, 0, num_influences, vertices, NULL); + ok(hr == D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, got %#x\n", hr); + + hr = skininfo->lpVtbl->SetBoneInfluence(skininfo, 0, num_influences, NULL, NULL); + ok(hr == D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, got %#x\n", hr); + + hr = skininfo->lpVtbl->SetBoneInfluence(skininfo, 0, num_influences, exp_vertices, exp_weights); + ok(hr == D3D_OK, "Expected D3D_OK, got %#x\n", hr); + + memset(vertices, 0, sizeof(vertices)); + memset(weights, 0, sizeof(weights)); + hr = skininfo->lpVtbl->GetBoneInfluence(skininfo, 0, vertices, weights); + ok(hr == D3D_OK, "Expected D3D_OK, got %#x\n", hr); + for (i = 0; i < num_influences; i++) { + ok(exp_vertices[i] == vertices[i], + "influence[%d]: expected vertex %u, got %u\n", i, exp_vertices[i], vertices[i]); + ok((isnan(exp_weights[i]) && isnan(weights[i])) || exp_weights[i] == weights[i], + "influence[%d]: expected weights %g, got %g\n", i, exp_weights[i], weights[i]); + } + + /* vertices and weights aren't returned after setting num_influences to 0 */ + memset(vertices, 0, sizeof(vertices)); + memset(weights, 0, sizeof(weights)); + hr = skininfo->lpVtbl->SetBoneInfluence(skininfo, 0, 0, vertices, weights); + ok(hr == D3D_OK, "Expected D3D_OK, got %#x\n", hr); + + vertices[0] = 0xdeadbeef; + weights[0] = FLT_MAX; + hr = skininfo->lpVtbl->GetBoneInfluence(skininfo, 0, vertices, weights); + ok(hr == D3D_OK, "Expected D3D_OK, got %#x\n", hr); + ok(vertices[0] == 0xdeadbeef, "expected vertex 0xdeadbeef, got %u\n", vertices[0]); + ok(weights[0] == FLT_MAX, "expected weight %g, got %g\n", FLT_MAX, weights[0]); + } + + { + /* test [GS]etFVF and [GS]etDeclaration */ + D3DVERTEXELEMENT9 declaration_in[MAX_FVF_DECL_SIZE]; + DWORD fvf = D3DFVF_XYZ; + DWORD got_fvf; + + hr = skininfo->lpVtbl->SetDeclaration(skininfo, NULL); + ok(hr == D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, got %#x\n", hr); + + hr = skininfo->lpVtbl->SetDeclaration(skininfo, declaration_with_nonzero_stream); + ok(hr == D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, got %#x\n", hr); + + hr = skininfo->lpVtbl->SetFVF(skininfo, 0); + ok(hr == D3D_OK, "Expected D3D_OK, got %#x\n", hr); + + hr = D3DXDeclaratorFromFVF(fvf, declaration_in); + ok(hr == D3D_OK, "Expected D3D_OK, got %#x\n", hr); + hr = skininfo->lpVtbl->SetDeclaration(skininfo, declaration_in); + ok(hr == D3D_OK, "Expected D3D_OK, got %#x\n", hr); + got_fvf = skininfo->lpVtbl->GetFVF(skininfo); + ok(fvf == got_fvf, "Expected %#x, got %#x\n", fvf, got_fvf); + hr = skininfo->lpVtbl->GetDeclaration(skininfo, declaration_out); + ok(hr == D3D_OK, "Expected D3D_OK, got %#x\n", hr); + compare_elements(declaration_out, declaration_in, __LINE__, 0); + + hr = skininfo->lpVtbl->SetDeclaration(skininfo, empty_declaration); + ok(hr == D3D_OK, "Expected D3D_OK, got %#x\n", hr); + got_fvf = skininfo->lpVtbl->GetFVF(skininfo); + ok(got_fvf == 0, "Expected 0, got %#x\n", got_fvf); + hr = skininfo->lpVtbl->GetDeclaration(skininfo, declaration_out); + ok(hr == D3D_OK, "Expected D3D_OK, got %#x\n", hr); + compare_elements(declaration_out, empty_declaration, __LINE__, 0); + + hr = skininfo->lpVtbl->SetFVF(skininfo, fvf); + ok(hr == D3D_OK, "Expected D3D_OK, got %#x\n", hr); + got_fvf = skininfo->lpVtbl->GetFVF(skininfo); + ok(fvf == got_fvf, "Expected %#x, got %#x\n", fvf, got_fvf); + hr = skininfo->lpVtbl->GetDeclaration(skininfo, declaration_out); + ok(hr == D3D_OK, "Expected D3D_OK, got %#x\n", hr); + compare_elements(declaration_out, declaration_in, __LINE__, 0); + } + } + if (skininfo) IUnknown_Release(skininfo); + skininfo = NULL; + + hr = D3DXCreateSkinInfoFVF(1, D3DFVF_XYZ, 1, NULL); + ok(hr == D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, got %#x\n", hr); + + hr = D3DXCreateSkinInfo(1, NULL, 1, &skininfo); + ok(hr == D3DERR_INVALIDCALL, "Expected D3DERR_INVALIDCALL, got %#x\n", hr); +} + +static void test_convert_adjacency_to_point_reps(void) +{ + HRESULT hr; + struct test_context *test_context = NULL; + const DWORD options = D3DXMESH_32BIT | D3DXMESH_SYSTEMMEM; + const DWORD options_16bit = D3DXMESH_SYSTEMMEM; + const D3DVERTEXELEMENT9 declaration[] = + { + {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0}, + {0, 12, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL, 0}, + {0, 24, D3DDECLTYPE_D3DCOLOR, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_COLOR, 0}, + D3DDECL_END() + }; + const unsigned int VERTS_PER_FACE = 3; + void *vertex_buffer; + void *index_buffer; + DWORD *attributes_buffer; + int i, j; + enum color { RED = 0xffff0000, GREEN = 0xff00ff00, BLUE = 0xff0000ff}; + struct vertex_pnc + { + D3DXVECTOR3 position; + D3DXVECTOR3 normal; + enum color color; /* In case of manual visual inspection */ + }; +#ifndef __REACTOS__ + D3DXVECTOR3 up = {0.0f, 0.0f, 1.0f}; +#else +#define up {0.0f, 0.0f, 1.0f} +#endif + /* mesh0 (one face) + * + * 0--1 + * | / + * |/ + * 2 + */ + const struct vertex_pnc vertices0[] = + { + {{ 0.0f, 3.0f, 0.f}, up, RED}, + {{ 2.0f, 3.0f, 0.f}, up, GREEN}, + {{ 0.0f, 0.0f, 0.f}, up, BLUE}, + }; + const DWORD indices0[] = {0, 1, 2}; + const unsigned int num_vertices0 = ARRAY_SIZE(vertices0); + const unsigned int num_faces0 = ARRAY_SIZE(indices0) / VERTS_PER_FACE; + const DWORD adjacency0[] = {-1, -1, -1}; + const DWORD exp_point_rep0[] = {0, 1, 2}; + /* mesh1 (right) + * + * 0--1 3 + * | / /| + * |/ / | + * 2 5--4 + */ + const struct vertex_pnc vertices1[] = + { + {{ 0.0f, 3.0f, 0.f}, up, RED}, + {{ 2.0f, 3.0f, 0.f}, up, GREEN}, + {{ 0.0f, 0.0f, 0.f}, up, BLUE}, + + {{ 3.0f, 3.0f, 0.f}, up, GREEN}, + {{ 3.0f, 0.0f, 0.f}, up, RED}, + {{ 1.0f, 0.0f, 0.f}, up, BLUE}, + }; + const DWORD indices1[] = {0, 1, 2, 3, 4, 5}; + const unsigned int num_vertices1 = ARRAY_SIZE(vertices1); + const unsigned int num_faces1 = ARRAY_SIZE(indices1) / VERTS_PER_FACE; + const DWORD adjacency1[] = {-1, 1, -1, -1, -1, 0}; + const DWORD exp_point_rep1[] = {0, 1, 2, 1, 4, 2}; + /* mesh2 (left) + * + * 3 0--1 + * /| | / + * / | |/ + * 5--4 2 + */ + const struct vertex_pnc vertices2[] = + { + {{ 0.0f, 3.0f, 0.f}, up, RED}, + {{ 2.0f, 3.0f, 0.f}, up, GREEN}, + {{ 0.0f, 0.0f, 0.f}, up, BLUE}, + + {{-1.0f, 3.0f, 0.f}, up, RED}, + {{-1.0f, 0.0f, 0.f}, up, GREEN}, + {{-3.0f, 0.0f, 0.f}, up, BLUE}, + }; + const DWORD indices2[] = {0, 1, 2, 3, 4, 5}; + const unsigned int num_vertices2 = ARRAY_SIZE(vertices2); + const unsigned int num_faces2 = ARRAY_SIZE(indices2) / VERTS_PER_FACE; + const DWORD adjacency2[] = {-1, -1, 1, 0, -1, -1}; + const DWORD exp_point_rep2[] = {0, 1, 2, 0, 2, 5}; + /* mesh3 (above) + * + * 3 + * /| + * / | + * 5--4 + * 0--1 + * | / + * |/ + * 2 + */ + struct vertex_pnc vertices3[] = + { + {{ 0.0f, 3.0f, 0.f}, up, RED}, + {{ 2.0f, 3.0f, 0.f}, up, GREEN}, + {{ 0.0f, 0.0f, 0.f}, up, BLUE}, + + {{ 2.0f, 7.0f, 0.f}, up, BLUE}, + {{ 2.0f, 4.0f, 0.f}, up, GREEN}, + {{ 0.0f, 4.0f, 0.f}, up, RED}, + }; + const DWORD indices3[] = {0, 1, 2, 3, 4, 5}; + const unsigned int num_vertices3 = ARRAY_SIZE(vertices3); + const unsigned int num_faces3 = ARRAY_SIZE(indices3) / VERTS_PER_FACE; + const DWORD adjacency3[] = {1, -1, -1, -1, 0, -1}; + const DWORD exp_point_rep3[] = {0, 1, 2, 3, 1, 0}; + /* mesh4 (below, tip against tip) + * + * 0--1 + * | / + * |/ + * 2 + * 3 + * |\ + * | \ + * 5--4 + */ + struct vertex_pnc vertices4[] = + { + {{ 0.0f, 3.0f, 0.f}, up, RED}, + {{ 2.0f, 3.0f, 0.f}, up, GREEN}, + {{ 0.0f, 0.0f, 0.f}, up, BLUE}, + + {{ 0.0f, -4.0f, 0.f}, up, BLUE}, + {{ 2.0f, -7.0f, 0.f}, up, GREEN}, + {{ 0.0f, -7.0f, 0.f}, up, RED}, + }; + const DWORD indices4[] = {0, 1, 2, 3, 4, 5}; + const unsigned int num_vertices4 = ARRAY_SIZE(vertices4); + const unsigned int num_faces4 = ARRAY_SIZE(indices4) / VERTS_PER_FACE; + const DWORD adjacency4[] = {-1, -1, -1, -1, -1, -1}; + const DWORD exp_point_rep4[] = {0, 1, 2, 3, 4, 5}; + /* mesh5 (gap in mesh) + * + * 0 3-----4 15 + * / \ \ / / \ + * / \ \ / / \ + * 2-----1 5 17-----16 + * 6-----7 9 12-----13 + * \ / / \ \ / + * \ / / \ \ / + * 8 10-----11 14 + * + */ + const struct vertex_pnc vertices5[] = + { + {{ 0.0f, 1.0f, 0.f}, up, RED}, + {{ 1.0f, -1.0f, 0.f}, up, GREEN}, + {{-1.0f, -1.0f, 0.f}, up, BLUE}, + + {{ 0.1f, 1.0f, 0.f}, up, RED}, + {{ 2.1f, 1.0f, 0.f}, up, BLUE}, + {{ 1.1f, -1.0f, 0.f}, up, GREEN}, + + {{-1.0f, -1.1f, 0.f}, up, BLUE}, + {{ 1.0f, -1.1f, 0.f}, up, GREEN}, + {{ 0.0f, -3.1f, 0.f}, up, RED}, + + {{ 1.1f, -1.1f, 0.f}, up, GREEN}, + {{ 2.1f, -3.1f, 0.f}, up, BLUE}, + {{ 0.1f, -3.1f, 0.f}, up, RED}, + + {{ 1.2f, -1.1f, 0.f}, up, GREEN}, + {{ 3.2f, -1.1f, 0.f}, up, RED}, + {{ 2.2f, -3.1f, 0.f}, up, BLUE}, + + {{ 2.2f, 1.0f, 0.f}, up, BLUE}, + {{ 3.2f, -1.0f, 0.f}, up, RED}, + {{ 1.2f, -1.0f, 0.f}, up, GREEN}, + }; + const DWORD indices5[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17}; + const unsigned int num_vertices5 = ARRAY_SIZE(vertices5); + const unsigned int num_faces5 = ARRAY_SIZE(indices5) / VERTS_PER_FACE; + const DWORD adjacency5[] = {-1, 2, -1, -1, 5, -1, 0, -1, -1, 4, -1, -1, 5, -1, 3, -1, 4, 1}; + const DWORD exp_point_rep5[] = {0, 1, 2, 3, 4, 5, 2, 1, 8, 5, 10, 11, 5, 13, 10, 4, 13, 5}; + const WORD indices5_16bit[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17}; + /* mesh6 (indices re-ordering) + * + * 0--1 6 3 + * | / /| |\ + * |/ / | | \ + * 2 8--7 5--4 + */ + const struct vertex_pnc vertices6[] = + { + {{ 0.0f, 3.0f, 0.f}, up, RED}, + {{ 2.0f, 3.0f, 0.f}, up, GREEN}, + {{ 0.0f, 0.0f, 0.f}, up, BLUE}, + + {{ 3.0f, 3.0f, 0.f}, up, GREEN}, + {{ 3.0f, 0.0f, 0.f}, up, RED}, + {{ 1.0f, 0.0f, 0.f}, up, BLUE}, + + {{ 4.0f, 3.0f, 0.f}, up, GREEN}, + {{ 6.0f, 0.0f, 0.f}, up, BLUE}, + {{ 4.0f, 0.0f, 0.f}, up, RED}, + }; + const DWORD indices6[] = {0, 1, 2, 6, 7, 8, 3, 4, 5}; + const unsigned int num_vertices6 = ARRAY_SIZE(vertices6); + const unsigned int num_faces6 = ARRAY_SIZE(indices6) / VERTS_PER_FACE; + const DWORD adjacency6[] = {-1, 1, -1, 2, -1, 0, -1, -1, 1}; + const DWORD exp_point_rep6[] = {0, 1, 2, 1, 4, 5, 1, 5, 2}; + /* mesh7 (expands collapsed triangle) + * + * 0--1 3 + * | / /| + * |/ / | + * 2 5--4 + */ + const struct vertex_pnc vertices7[] = + { + {{ 0.0f, 3.0f, 0.f}, up, RED}, + {{ 2.0f, 3.0f, 0.f}, up, GREEN}, + {{ 0.0f, 0.0f, 0.f}, up, BLUE}, + + {{ 3.0f, 3.0f, 0.f}, up, GREEN}, + {{ 3.0f, 0.0f, 0.f}, up, RED}, + {{ 1.0f, 0.0f, 0.f}, up, BLUE}, + }; + const DWORD indices7[] = {0, 1, 2, 3, 3, 3}; /* Face 1 is collapsed*/ + const unsigned int num_vertices7 = ARRAY_SIZE(vertices7); + const unsigned int num_faces7 = ARRAY_SIZE(indices7) / VERTS_PER_FACE; + const DWORD adjacency7[] = {-1, -1, -1, -1, -1, -1}; + const DWORD exp_point_rep7[] = {0, 1, 2, 3, 4, 5}; + /* mesh8 (indices re-ordering and double replacement) + * + * 0--1 9 6 + * | / /| |\ + * |/ / | | \ + * 2 11-10 8--7 + * 3--4 + * | / + * |/ + * 5 + */ + const struct vertex_pnc vertices8[] = + { + {{ 0.0f, 3.0f, 0.f}, up, RED}, + {{ 2.0f, 3.0f, 0.f}, up, GREEN}, + {{ 0.0f, 0.0f, 0.f}, up, BLUE}, + + {{ 4.0, -4.0, 0.f}, up, RED}, + {{ 6.0, -4.0, 0.f}, up, BLUE}, + {{ 4.0, -7.0, 0.f}, up, GREEN}, + + {{ 4.0f, 3.0f, 0.f}, up, GREEN}, + {{ 6.0f, 0.0f, 0.f}, up, BLUE}, + {{ 4.0f, 0.0f, 0.f}, up, RED}, + + {{ 3.0f, 3.0f, 0.f}, up, GREEN}, + {{ 3.0f, 0.0f, 0.f}, up, RED}, + {{ 1.0f, 0.0f, 0.f}, up, BLUE}, + }; + const DWORD indices8[] = {0, 1, 2, 9, 10, 11, 6, 7, 8, 3, 4, 5}; + const unsigned int num_vertices8 = ARRAY_SIZE(vertices8); + const unsigned int num_faces8 = ARRAY_SIZE(indices8) / VERTS_PER_FACE; + const DWORD adjacency8[] = {-1, 1, -1, 2, -1, 0, -1, 3, 1, 2, -1, -1}; + const DWORD exp_point_rep8[] = {0, 1, 2, 3, 4, 5, 1, 4, 3, 1, 3, 2}; + /* mesh9 (right, shared vertices) + * + * 0--1 + * | /| + * |/ | + * 2--3 + */ + const struct vertex_pnc vertices9[] = + { + {{ 0.0f, 3.0f, 0.f}, up, RED}, + {{ 2.0f, 3.0f, 0.f}, up, GREEN}, + {{ 0.0f, 0.0f, 0.f}, up, BLUE}, + + {{ 2.0f, 0.0f, 0.f}, up, RED}, + }; + const DWORD indices9[] = {0, 1, 2, 1, 3, 2}; + const unsigned int num_vertices9 = ARRAY_SIZE(vertices9); + const unsigned int num_faces9 = ARRAY_SIZE(indices9) / VERTS_PER_FACE; + const DWORD adjacency9[] = {-1, 1, -1, -1, -1, 0}; + const DWORD exp_point_rep9[] = {0, 1, 2, 3}; + /* All mesh data */ + ID3DXMesh *mesh = NULL; + ID3DXMesh *mesh_null_check = NULL; + unsigned int attributes[] = {0}; + struct + { + const struct vertex_pnc *vertices; + const DWORD *indices; + const DWORD num_vertices; + const DWORD num_faces; + const DWORD *adjacency; + const DWORD *exp_point_reps; + const DWORD options; + } + tc[] = + { + { + vertices0, + indices0, + num_vertices0, + num_faces0, + adjacency0, + exp_point_rep0, + options + }, + { + vertices1, + indices1, + num_vertices1, + num_faces1, + adjacency1, + exp_point_rep1, + options + }, + { + vertices2, + indices2, + num_vertices2, + num_faces2, + adjacency2, + exp_point_rep2, + options + }, + { + vertices3, + indices3, + num_vertices3, + num_faces3, + adjacency3, + exp_point_rep3, + options + }, + { + vertices4, + indices4, + num_vertices4, + num_faces4, + adjacency4, + exp_point_rep4, + options + }, + { + vertices5, + indices5, + num_vertices5, + num_faces5, + adjacency5, + exp_point_rep5, + options + }, + { + vertices6, + indices6, + num_vertices6, + num_faces6, + adjacency6, + exp_point_rep6, + options + }, + { + vertices7, + indices7, + num_vertices7, + num_faces7, + adjacency7, + exp_point_rep7, + options + }, + { + vertices8, + indices8, + num_vertices8, + num_faces8, + adjacency8, + exp_point_rep8, + options + }, + { + vertices9, + indices9, + num_vertices9, + num_faces9, + adjacency9, + exp_point_rep9, + options + }, + { + vertices5, + (DWORD*)indices5_16bit, + num_vertices5, + num_faces5, + adjacency5, + exp_point_rep5, + options_16bit + }, + }; + DWORD *point_reps = NULL; + + test_context = new_test_context(); + if (!test_context) + { + skip("Couldn't create test context\n"); + goto cleanup; + } + + for (i = 0; i < ARRAY_SIZE(tc); i++) + { + hr = D3DXCreateMesh(tc[i].num_faces, tc[i].num_vertices, tc[i].options, declaration, + test_context->device, &mesh); + if (FAILED(hr)) + { + skip("Couldn't create mesh %d. Got %x expected D3D_OK\n", i, hr); + goto cleanup; + } + + if (i == 0) /* Save first mesh for later NULL checks */ + mesh_null_check = mesh; + + point_reps = HeapAlloc(GetProcessHeap(), 0, tc[i].num_vertices * sizeof(*point_reps)); + if (!point_reps) + { + skip("Couldn't allocate point reps array.\n"); + goto cleanup; + } + + hr = mesh->lpVtbl->LockVertexBuffer(mesh, 0, &vertex_buffer); + if (FAILED(hr)) + { + skip("Couldn't lock vertex buffer.\n"); + goto cleanup; + } + memcpy(vertex_buffer, tc[i].vertices, tc[i].num_vertices * sizeof(*tc[i].vertices)); + hr = mesh->lpVtbl->UnlockVertexBuffer(mesh); + if (FAILED(hr)) + { + skip("Couldn't unlock vertex buffer.\n"); + goto cleanup; + } + + hr = mesh->lpVtbl->LockIndexBuffer(mesh, 0, &index_buffer); + if (FAILED(hr)) + { + skip("Couldn't lock index buffer.\n"); + goto cleanup; + } + if (tc[i].options & D3DXMESH_32BIT) + { + memcpy(index_buffer, tc[i].indices, VERTS_PER_FACE * tc[i].num_faces * sizeof(DWORD)); + } + else + { + memcpy(index_buffer, tc[i].indices, VERTS_PER_FACE * tc[i].num_faces * sizeof(WORD)); + } + hr = mesh->lpVtbl->UnlockIndexBuffer(mesh); + if (FAILED(hr)) { + skip("Couldn't unlock index buffer.\n"); + goto cleanup; + } + + hr = mesh->lpVtbl->LockAttributeBuffer(mesh, 0, &attributes_buffer); + if (FAILED(hr)) + { + skip("Couldn't lock attributes buffer.\n"); + goto cleanup; + } + memcpy(attributes_buffer, attributes, sizeof(attributes)); + hr = mesh->lpVtbl->UnlockAttributeBuffer(mesh); + if (FAILED(hr)) + { + skip("Couldn't unlock attributes buffer.\n"); + goto cleanup; + } + + /* Convert adjacency to point representation */ + for (j = 0; j < tc[i].num_vertices; j++) point_reps[j] = -1; + hr = mesh->lpVtbl->ConvertAdjacencyToPointReps(mesh, tc[i].adjacency, point_reps); + ok(hr == D3D_OK, "ConvertAdjacencyToPointReps failed case %d. " + "Got %x expected D3D_OK\n", i, hr); + + /* Check point representation */ + for (j = 0; j < tc[i].num_vertices; j++) + { + ok(point_reps[j] == tc[i].exp_point_reps[j], + "Unexpected point representation at (%d, %d)." + " Got %d expected %d\n", + i, j, point_reps[j], tc[i].exp_point_reps[j]); + } + + HeapFree(GetProcessHeap(), 0, point_reps); + point_reps = NULL; + + if (i != 0) /* First mesh will be freed during cleanup */ + mesh->lpVtbl->Release(mesh); + } + + /* NULL checks */ + hr = mesh_null_check->lpVtbl->ConvertAdjacencyToPointReps(mesh_null_check, tc[0].adjacency, NULL); + ok(hr == D3DERR_INVALIDCALL, "ConvertAdjacencyToPointReps point_reps NULL. " + "Got %x expected D3DERR_INVALIDCALL\n", hr); + hr = mesh_null_check->lpVtbl->ConvertAdjacencyToPointReps(mesh_null_check, NULL, NULL); + ok(hr == D3DERR_INVALIDCALL, "ConvertAdjacencyToPointReps adjacency and point_reps NULL. " + "Got %x expected D3DERR_INVALIDCALL\n", hr); + +cleanup: + if (mesh_null_check) + mesh_null_check->lpVtbl->Release(mesh_null_check); + HeapFree(GetProcessHeap(), 0, point_reps); + free_test_context(test_context); +#ifdef __REACTOS__ +#undef up +#endif +} + +static void test_convert_point_reps_to_adjacency(void) +{ + HRESULT hr; + struct test_context *test_context = NULL; + const DWORD options = D3DXMESH_32BIT | D3DXMESH_SYSTEMMEM; + const DWORD options_16bit = D3DXMESH_SYSTEMMEM; + const D3DVERTEXELEMENT9 declaration[] = + { + {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0}, + {0, 12, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL, 0}, + {0, 24, D3DDECLTYPE_D3DCOLOR, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_COLOR, 0}, + D3DDECL_END() + }; + const unsigned int VERTS_PER_FACE = 3; + void *vertex_buffer; + void *index_buffer; + DWORD *attributes_buffer; + int i, j; + enum color { RED = 0xffff0000, GREEN = 0xff00ff00, BLUE = 0xff0000ff}; + struct vertex_pnc + { + D3DXVECTOR3 position; + D3DXVECTOR3 normal; + enum color color; /* In case of manual visual inspection */ + }; +#ifndef __REACTOS__ + D3DXVECTOR3 up = {0.0f, 0.0f, 1.0f}; +#else +#define up {0.0f, 0.0f, 1.0f} +#endif + + /* mesh0 (one face) + * + * 0--1 + * | / + * |/ + * 2 + */ + const struct vertex_pnc vertices0[] = + { + {{ 0.0f, 3.0f, 0.f}, up, RED}, + {{ 2.0f, 3.0f, 0.f}, up, GREEN}, + {{ 0.0f, 0.0f, 0.f}, up, BLUE}, + }; + const DWORD indices0[] = {0, 1, 2}; + const unsigned int num_vertices0 = ARRAY_SIZE(vertices0); + const unsigned int num_faces0 = num_vertices0 / VERTS_PER_FACE; + const DWORD exp_adjacency0[] = {-1, -1, -1}; + const DWORD exp_id_adjacency0[] = {-1, -1, -1}; + const DWORD point_rep0[] = {0, 1, 2}; + /* mesh1 (right) + * + * 0--1 3 + * | / /| + * |/ / | + * 2 5--4 + */ + const struct vertex_pnc vertices1[] = + { + {{ 0.0f, 3.0f, 0.f}, up, RED}, + {{ 2.0f, 3.0f, 0.f}, up, GREEN}, + {{ 0.0f, 0.0f, 0.f}, up, BLUE}, + + {{ 3.0f, 3.0f, 0.f}, up, GREEN}, + {{ 3.0f, 0.0f, 0.f}, up, RED}, + {{ 1.0f, 0.0f, 0.f}, up, BLUE}, + }; + const DWORD indices1[] = {0, 1, 2, 3, 4, 5}; + const unsigned int num_vertices1 = ARRAY_SIZE(vertices1); + const unsigned int num_faces1 = num_vertices1 / VERTS_PER_FACE; + const DWORD exp_adjacency1[] = {-1, 1, -1, -1, -1, 0}; + const DWORD exp_id_adjacency1[] = {-1, -1, -1, -1, -1, -1}; + const DWORD point_rep1[] = {0, 1, 2, 1, 4, 2}; + /* mesh2 (left) + * + * 3 0--1 + * /| | / + * / | |/ + * 5--4 2 + */ + const struct vertex_pnc vertices2[] = + { + {{ 0.0f, 3.0f, 0.f}, up, RED}, + {{ 2.0f, 3.0f, 0.f}, up, GREEN}, + {{ 0.0f, 0.0f, 0.f}, up, BLUE}, + + {{-1.0f, 3.0f, 0.f}, up, RED}, + {{-1.0f, 0.0f, 0.f}, up, GREEN}, + {{-3.0f, 0.0f, 0.f}, up, BLUE}, + }; + const DWORD indices2[] = {0, 1, 2, 3, 4, 5}; + const unsigned int num_vertices2 = ARRAY_SIZE(vertices2); + const unsigned int num_faces2 = num_vertices2 / VERTS_PER_FACE; + const DWORD exp_adjacency2[] = {-1, -1, 1, 0, -1, -1}; + const DWORD exp_id_adjacency2[] = {-1, -1, -1, -1, -1, -1}; + const DWORD point_rep2[] = {0, 1, 2, 0, 2, 5}; + /* mesh3 (above) + * + * 3 + * /| + * / | + * 5--4 + * 0--1 + * | / + * |/ + * 2 + */ + struct vertex_pnc vertices3[] = + { + {{ 0.0f, 3.0f, 0.f}, up, RED}, + {{ 2.0f, 3.0f, 0.f}, up, GREEN}, + {{ 0.0f, 0.0f, 0.f}, up, BLUE}, + + {{ 2.0f, 7.0f, 0.f}, up, BLUE}, + {{ 2.0f, 4.0f, 0.f}, up, GREEN}, + {{ 0.0f, 4.0f, 0.f}, up, RED}, + }; + const DWORD indices3[] = {0, 1, 2, 3, 4, 5}; + const unsigned int num_vertices3 = ARRAY_SIZE(vertices3); + const unsigned int num_faces3 = num_vertices3 / VERTS_PER_FACE; + const DWORD exp_adjacency3[] = {1, -1, -1, -1, 0, -1}; + const DWORD exp_id_adjacency3[] = {-1, -1, -1, -1, -1, -1}; + const DWORD point_rep3[] = {0, 1, 2, 3, 1, 0}; + /* mesh4 (below, tip against tip) + * + * 0--1 + * | / + * |/ + * 2 + * 3 + * |\ + * | \ + * 5--4 + */ + struct vertex_pnc vertices4[] = + { + {{ 0.0f, 3.0f, 0.f}, up, RED}, + {{ 2.0f, 3.0f, 0.f}, up, GREEN}, + {{ 0.0f, 0.0f, 0.f}, up, BLUE}, + + {{ 0.0f, -4.0f, 0.f}, up, BLUE}, + {{ 2.0f, -7.0f, 0.f}, up, GREEN}, + {{ 0.0f, -7.0f, 0.f}, up, RED}, + }; + const DWORD indices4[] = {0, 1, 2, 3, 4, 5}; + const unsigned int num_vertices4 = ARRAY_SIZE(vertices4); + const unsigned int num_faces4 = num_vertices4 / VERTS_PER_FACE; + const DWORD exp_adjacency4[] = {-1, -1, -1, -1, -1, -1}; + const DWORD exp_id_adjacency4[] = {-1, -1, -1, -1, -1, -1}; + const DWORD point_rep4[] = {0, 1, 2, 3, 4, 5}; + /* mesh5 (gap in mesh) + * + * 0 3-----4 15 + * / \ \ / / \ + * / \ \ / / \ + * 2-----1 5 17-----16 + * 6-----7 9 12-----13 + * \ / / \ \ / + * \ / / \ \ / + * 8 10-----11 14 + * + */ + const struct vertex_pnc vertices5[] = + { + {{ 0.0f, 1.0f, 0.f}, up, RED}, + {{ 1.0f, -1.0f, 0.f}, up, GREEN}, + {{-1.0f, -1.0f, 0.f}, up, BLUE}, + + {{ 0.1f, 1.0f, 0.f}, up, RED}, + {{ 2.1f, 1.0f, 0.f}, up, BLUE}, + {{ 1.1f, -1.0f, 0.f}, up, GREEN}, + + {{-1.0f, -1.1f, 0.f}, up, BLUE}, + {{ 1.0f, -1.1f, 0.f}, up, GREEN}, + {{ 0.0f, -3.1f, 0.f}, up, RED}, + + {{ 1.1f, -1.1f, 0.f}, up, GREEN}, + {{ 2.1f, -3.1f, 0.f}, up, BLUE}, + {{ 0.1f, -3.1f, 0.f}, up, RED}, + + {{ 1.2f, -1.1f, 0.f}, up, GREEN}, + {{ 3.2f, -1.1f, 0.f}, up, RED}, + {{ 2.2f, -3.1f, 0.f}, up, BLUE}, + + {{ 2.2f, 1.0f, 0.f}, up, BLUE}, + {{ 3.2f, -1.0f, 0.f}, up, RED}, + {{ 1.2f, -1.0f, 0.f}, up, GREEN}, + }; + const DWORD indices5[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17}; + const unsigned int num_vertices5 = ARRAY_SIZE(vertices5); + const unsigned int num_faces5 = num_vertices5 / VERTS_PER_FACE; + const DWORD exp_adjacency5[] = {-1, 2, -1, -1, 5, -1, 0, -1, -1, 4, -1, -1, 5, -1, 3, -1, 4, 1}; + const DWORD exp_id_adjacency5[] = {-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}; + const DWORD point_rep5[] = {0, 1, 2, 3, 4, 5, 2, 1, 8, 5, 10, 11, 5, 13, 10, 4, 13, 5}; + /* mesh6 (indices re-ordering) + * + * 0--1 6 3 + * | / /| |\ + * |/ / | | \ + * 2 8--7 5--4 + */ + const struct vertex_pnc vertices6[] = + { + {{ 0.0f, 3.0f, 0.f}, up, RED}, + {{ 2.0f, 3.0f, 0.f}, up, GREEN}, + {{ 0.0f, 0.0f, 0.f}, up, BLUE}, + + {{ 3.0f, 3.0f, 0.f}, up, GREEN}, + {{ 3.0f, 0.0f, 0.f}, up, RED}, + {{ 1.0f, 0.0f, 0.f}, up, BLUE}, + + {{ 4.0f, 3.0f, 0.f}, up, GREEN}, + {{ 6.0f, 0.0f, 0.f}, up, BLUE}, + {{ 4.0f, 0.0f, 0.f}, up, RED}, + }; + const DWORD indices6[] = {0, 1, 2, 6, 7, 8, 3, 4, 5}; + const unsigned int num_vertices6 = ARRAY_SIZE(vertices6); + const unsigned int num_faces6 = num_vertices6 / VERTS_PER_FACE; + const DWORD exp_adjacency6[] = {-1, 1, -1, 2, -1, 0, -1, -1, 1}; + const DWORD exp_id_adjacency6[] = {-1, -1, -1, -1, -1, -1, -1, -1, -1}; + const DWORD point_rep6[] = {0, 1, 2, 1, 4, 5, 1, 5, 2}; + /* mesh7 (expands collapsed triangle) + * + * 0--1 3 + * | / /| + * |/ / | + * 2 5--4 + */ + const struct vertex_pnc vertices7[] = + { + {{ 0.0f, 3.0f, 0.f}, up, RED}, + {{ 2.0f, 3.0f, 0.f}, up, GREEN}, + {{ 0.0f, 0.0f, 0.f}, up, BLUE}, + + {{ 3.0f, 3.0f, 0.f}, up, GREEN}, + {{ 3.0f, 0.0f, 0.f}, up, RED}, + {{ 1.0f, 0.0f, 0.f}, up, BLUE}, + }; + const DWORD indices7[] = {0, 1, 2, 3, 3, 3}; /* Face 1 is collapsed*/ + const unsigned int num_vertices7 = ARRAY_SIZE(vertices7); + const unsigned int num_faces7 = num_vertices7 / VERTS_PER_FACE; + const DWORD exp_adjacency7[] = {-1, -1, -1, -1, -1, -1}; + const DWORD exp_id_adjacency7[] = {-1, -1, -1, -1, -1, -1}; + const DWORD point_rep7[] = {0, 1, 2, 3, 4, 5}; + /* mesh8 (indices re-ordering and double replacement) + * + * 0--1 9 6 + * | / /| |\ + * |/ / | | \ + * 2 11-10 8--7 + * 3--4 + * | / + * |/ + * 5 + */ + const struct vertex_pnc vertices8[] = + { + {{ 0.0f, 3.0f, 0.f}, up, RED}, + {{ 2.0f, 3.0f, 0.f}, up, GREEN}, + {{ 0.0f, 0.0f, 0.f}, up, BLUE}, + + {{ 4.0, -4.0, 0.f}, up, RED}, + {{ 6.0, -4.0, 0.f}, up, BLUE}, + {{ 4.0, -7.0, 0.f}, up, GREEN}, + + {{ 4.0f, 3.0f, 0.f}, up, GREEN}, + {{ 6.0f, 0.0f, 0.f}, up, BLUE}, + {{ 4.0f, 0.0f, 0.f}, up, RED}, + + {{ 3.0f, 3.0f, 0.f}, up, GREEN}, + {{ 3.0f, 0.0f, 0.f}, up, RED}, + {{ 1.0f, 0.0f, 0.f}, up, BLUE}, + }; + const DWORD indices8[] = {0, 1, 2, 9, 10, 11, 6, 7, 8, 3, 4, 5}; + const WORD indices8_16bit[] = {0, 1, 2, 9, 10, 11, 6, 7, 8, 3, 4, 5}; + const unsigned int num_vertices8 = ARRAY_SIZE(vertices8); + const unsigned int num_faces8 = num_vertices8 / VERTS_PER_FACE; + const DWORD exp_adjacency8[] = {-1, 1, -1, 2, -1, 0, -1, 3, 1, 2, -1, -1}; + const DWORD exp_id_adjacency8[] = {-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}; + const DWORD point_rep8[] = {0, 1, 2, 3, 4, 5, 1, 4, 3, 1, 3, 2}; + /* mesh9 (right, shared vertices) + * + * 0--1 + * | /| + * |/ | + * 2--3 + */ + const struct vertex_pnc vertices9[] = + { + {{ 0.0f, 3.0f, 0.f}, up, RED}, + {{ 2.0f, 3.0f, 0.f}, up, GREEN}, + {{ 0.0f, 0.0f, 0.f}, up, BLUE}, + + {{ 2.0f, 0.0f, 0.f}, up, RED}, + }; + const DWORD indices9[] = {0, 1, 2, 1, 3, 2}; + const unsigned int num_vertices9 = ARRAY_SIZE(vertices9); + const unsigned int num_faces9 = 2; + const DWORD exp_adjacency9[] = {-1, 1, -1, -1, -1, 0}; + const DWORD exp_id_adjacency9[] = {-1, 1, -1, -1, -1, 0}; + const DWORD point_rep9[] = {0, 1, 2, 3}; + /* All mesh data */ + ID3DXMesh *mesh = NULL; + ID3DXMesh *mesh_null_check = NULL; + unsigned int attributes[] = {0}; + struct + { + const struct vertex_pnc *vertices; + const DWORD *indices; + const DWORD num_vertices; + const DWORD num_faces; + const DWORD *point_reps; + const DWORD *exp_adjacency; + const DWORD *exp_id_adjacency; + const DWORD options; + } + tc[] = + { + { + vertices0, + indices0, + num_vertices0, + num_faces0, + point_rep0, + exp_adjacency0, + exp_id_adjacency0, + options + }, + { + vertices1, + indices1, + num_vertices1, + num_faces1, + point_rep1, + exp_adjacency1, + exp_id_adjacency1, + options + }, + { + vertices2, + indices2, + num_vertices2, + num_faces2, + point_rep2, + exp_adjacency2, + exp_id_adjacency2, + options + }, + { + vertices3, + indices3, + num_vertices3, + num_faces3, + point_rep3, + exp_adjacency3, + exp_id_adjacency3, + options + }, + { + vertices4, + indices4, + num_vertices4, + num_faces4, + point_rep4, + exp_adjacency4, + exp_id_adjacency4, + options + }, + { + vertices5, + indices5, + num_vertices5, + num_faces5, + point_rep5, + exp_adjacency5, + exp_id_adjacency5, + options + }, + { + vertices6, + indices6, + num_vertices6, + num_faces6, + point_rep6, + exp_adjacency6, + exp_id_adjacency6, + options + }, + { + vertices7, + indices7, + num_vertices7, + num_faces7, + point_rep7, + exp_adjacency7, + exp_id_adjacency7, + options + }, + { + vertices8, + indices8, + num_vertices8, + num_faces8, + point_rep8, + exp_adjacency8, + exp_id_adjacency8, + options + }, + { + vertices9, + indices9, + num_vertices9, + num_faces9, + point_rep9, + exp_adjacency9, + exp_id_adjacency9, + options + }, + { + vertices8, + (DWORD*)indices8_16bit, + num_vertices8, + num_faces8, + point_rep8, + exp_adjacency8, + exp_id_adjacency8, + options_16bit + }, + }; + DWORD *adjacency = NULL; +#ifdef __REACTOS__ +#undef up +#endif + + test_context = new_test_context(); + if (!test_context) + { + skip("Couldn't create test context\n"); + goto cleanup; + } + + for (i = 0; i < ARRAY_SIZE(tc); i++) + { + hr = D3DXCreateMesh(tc[i].num_faces, tc[i].num_vertices, tc[i].options, + declaration, test_context->device, &mesh); + if (FAILED(hr)) + { + skip("Couldn't create mesh %d. Got %x expected D3D_OK\n", i, hr); + goto cleanup; + } + + if (i == 0) /* Save first mesh for later NULL checks */ + mesh_null_check = mesh; + + adjacency = HeapAlloc(GetProcessHeap(), 0, VERTS_PER_FACE * tc[i].num_faces * sizeof(*adjacency)); + if (!adjacency) + { + skip("Couldn't allocate adjacency array.\n"); + goto cleanup; + } + + hr = mesh->lpVtbl->LockVertexBuffer(mesh, 0, &vertex_buffer); + if (FAILED(hr)) + { + skip("Couldn't lock vertex buffer.\n"); + goto cleanup; + } + memcpy(vertex_buffer, tc[i].vertices, tc[i].num_vertices * sizeof(*tc[i].vertices)); + hr = mesh->lpVtbl->UnlockVertexBuffer(mesh); + if (FAILED(hr)) + { + skip("Couldn't unlock vertex buffer.\n"); + goto cleanup; + } + hr = mesh->lpVtbl->LockIndexBuffer(mesh, 0, &index_buffer); + if (FAILED(hr)) + { + skip("Couldn't lock index buffer.\n"); + goto cleanup; + } + if (tc[i].options & D3DXMESH_32BIT) + { + memcpy(index_buffer, tc[i].indices, VERTS_PER_FACE * tc[i].num_faces * sizeof(DWORD)); + } + else + { + memcpy(index_buffer, tc[i].indices, VERTS_PER_FACE * tc[i].num_faces * sizeof(WORD)); + } + hr = mesh->lpVtbl->UnlockIndexBuffer(mesh); + if (FAILED(hr)) { + skip("Couldn't unlock index buffer.\n"); + goto cleanup; + } + + hr = mesh->lpVtbl->LockAttributeBuffer(mesh, 0, &attributes_buffer); + if (FAILED(hr)) + { + skip("Couldn't lock attributes buffer.\n"); + goto cleanup; + } + memcpy(attributes_buffer, attributes, sizeof(attributes)); + hr = mesh->lpVtbl->UnlockAttributeBuffer(mesh); + if (FAILED(hr)) + { + skip("Couldn't unlock attributes buffer.\n"); + goto cleanup; + } + + /* Convert point representation to adjacency*/ + for (j = 0; j < VERTS_PER_FACE * tc[i].num_faces; j++) adjacency[j] = -2; + + hr = mesh->lpVtbl->ConvertPointRepsToAdjacency(mesh, tc[i].point_reps, adjacency); + ok(hr == D3D_OK, "ConvertPointRepsToAdjacency failed case %d. " + "Got %x expected D3D_OK\n", i, hr); + /* Check adjacency */ + for (j = 0; j < VERTS_PER_FACE * tc[i].num_faces; j++) + { + ok(adjacency[j] == tc[i].exp_adjacency[j], + "Unexpected adjacency information at (%d, %d)." + " Got %d expected %d\n", + i, j, adjacency[j], tc[i].exp_adjacency[j]); + } + + /* NULL point representation is considered identity. */ + for (j = 0; j < VERTS_PER_FACE * tc[i].num_faces; j++) adjacency[j] = -2; + hr = mesh_null_check->lpVtbl->ConvertPointRepsToAdjacency(mesh, NULL, adjacency); + ok(hr == D3D_OK, "ConvertPointRepsToAdjacency NULL point_reps. " + "Got %x expected D3D_OK\n", hr); + for (j = 0; j < VERTS_PER_FACE * tc[i].num_faces; j++) + { + ok(adjacency[j] == tc[i].exp_id_adjacency[j], + "Unexpected adjacency information (id) at (%d, %d)." + " Got %d expected %d\n", + i, j, adjacency[j], tc[i].exp_id_adjacency[j]); + } + + HeapFree(GetProcessHeap(), 0, adjacency); + adjacency = NULL; + if (i != 0) /* First mesh will be freed during cleanup */ + mesh->lpVtbl->Release(mesh); + } + + /* NULL checks */ + hr = mesh_null_check->lpVtbl->ConvertPointRepsToAdjacency(mesh_null_check, tc[0].point_reps, NULL); + ok(hr == D3DERR_INVALIDCALL, "ConvertPointRepsToAdjacency NULL adjacency. " + "Got %x expected D3DERR_INVALIDCALL\n", hr); + hr = mesh_null_check->lpVtbl->ConvertPointRepsToAdjacency(mesh_null_check, NULL, NULL); + ok(hr == D3DERR_INVALIDCALL, "ConvertPointRepsToAdjacency NULL point_reps and adjacency. " + "Got %x expected D3DERR_INVALIDCALL\n", hr); + +cleanup: + if (mesh_null_check) + mesh_null_check->lpVtbl->Release(mesh_null_check); + HeapFree(GetProcessHeap(), 0, adjacency); + free_test_context(test_context); +} + +static HRESULT init_test_mesh(const DWORD num_faces, const DWORD num_vertices, + const DWORD options, + const D3DVERTEXELEMENT9 *declaration, + IDirect3DDevice9 *device, ID3DXMesh **mesh_ptr, + const void *vertices, const DWORD vertex_size, + const DWORD *indices, const DWORD *attributes) +{ + HRESULT hr; + void *vertex_buffer; + void *index_buffer; + DWORD *attributes_buffer; + ID3DXMesh *mesh = NULL; + + hr = D3DXCreateMesh(num_faces, num_vertices, options, declaration, device, mesh_ptr); + if (FAILED(hr)) + { + skip("Couldn't create mesh. Got %x expected D3D_OK\n", hr); + goto cleanup; + } + mesh = *mesh_ptr; + + hr = mesh->lpVtbl->LockVertexBuffer(mesh, 0, &vertex_buffer); + if (FAILED(hr)) + { + skip("Couldn't lock vertex buffer.\n"); + goto cleanup; + } + memcpy(vertex_buffer, vertices, num_vertices * vertex_size); + hr = mesh->lpVtbl->UnlockVertexBuffer(mesh); + if (FAILED(hr)) + { + skip("Couldn't unlock vertex buffer.\n"); + goto cleanup; + } + + hr = mesh->lpVtbl->LockIndexBuffer(mesh, 0, &index_buffer); + if (FAILED(hr)) + { + skip("Couldn't lock index buffer.\n"); + goto cleanup; + } + if (options & D3DXMESH_32BIT) + { + if (indices) + memcpy(index_buffer, indices, 3 * num_faces * sizeof(DWORD)); + else + { + /* Fill index buffer with 0, 1, 2, ...*/ + DWORD *indices_32bit = (DWORD*)index_buffer; + UINT i; + for (i = 0; i < 3 * num_faces; i++) + indices_32bit[i] = i; + } + } + else + { + if (indices) + memcpy(index_buffer, indices, 3 * num_faces * sizeof(WORD)); + else + { + /* Fill index buffer with 0, 1, 2, ...*/ + WORD *indices_16bit = (WORD*)index_buffer; + UINT i; + for (i = 0; i < 3 * num_faces; i++) + indices_16bit[i] = i; + } + } + hr = mesh->lpVtbl->UnlockIndexBuffer(mesh); + if (FAILED(hr)) { + skip("Couldn't unlock index buffer.\n"); + goto cleanup; + } + + hr = mesh->lpVtbl->LockAttributeBuffer(mesh, 0, &attributes_buffer); + if (FAILED(hr)) + { + skip("Couldn't lock attributes buffer.\n"); + goto cleanup; + } + + if (attributes) + memcpy(attributes_buffer, attributes, num_faces * sizeof(*attributes)); + else + memset(attributes_buffer, 0, num_faces * sizeof(*attributes)); + + hr = mesh->lpVtbl->UnlockAttributeBuffer(mesh); + if (FAILED(hr)) + { + skip("Couldn't unlock attributes buffer.\n"); + goto cleanup; + } + + hr = D3D_OK; +cleanup: + return hr; +} + +/* Using structs instead of bit-fields in order to avoid compiler issues. */ +struct udec3 +{ + UINT x; + UINT y; + UINT z; + UINT w; +}; + +struct dec3n +{ + INT x; + INT y; + INT z; + INT w; +}; + +static DWORD init_udec3_dword(UINT x, UINT y, UINT z, UINT w) +{ + DWORD d = 0; + + d |= x & 0x3ff; + d |= (y << 10) & 0xffc00; + d |= (z << 20) & 0x3ff00000; + d |= (w << 30) & 0xc0000000; + + return d; +} + +static DWORD init_dec3n_dword(INT x, INT y, INT z, INT w) +{ + DWORD d = 0; + + d |= x & 0x3ff; + d |= (y << 10) & 0xffc00; + d |= (z << 20) & 0x3ff00000; + d |= (w << 30) & 0xc0000000; + + return d; +} + +static struct udec3 dword_to_udec3(DWORD d) +{ + struct udec3 v; + + v.x = d & 0x3ff; + v.y = (d & 0xffc00) >> 10; + v.z = (d & 0x3ff00000) >> 20; + v.w = (d & 0xc0000000) >> 30; + + return v; +} + +static struct dec3n dword_to_dec3n(DWORD d) +{ + struct dec3n v; + + v.x = d & 0x3ff; + v.y = (d & 0xffc00) >> 10; + v.z = (d & 0x3ff00000) >> 20; + v.w = (d & 0xc0000000) >> 30; + + return v; +} + +static void check_vertex_components(int line, int mesh_number, int vertex_number, BYTE *got_ptr, const BYTE *exp_ptr, D3DVERTEXELEMENT9 *declaration) +{ + const char *usage_strings[] = + { + "position", + "blend weight", + "blend indices", + "normal", + "point size", + "texture coordinates", + "tangent", + "binormal", + "tessellation factor", + "position transformed", + "color", + "fog", + "depth", + "sample" + }; + D3DVERTEXELEMENT9 *decl_ptr; + const float PRECISION = 1e-5f; + + for (decl_ptr = declaration; decl_ptr->Stream != 0xFF; decl_ptr++) + { + switch (decl_ptr->Type) + { + case D3DDECLTYPE_FLOAT1: + { + FLOAT *got = (FLOAT*)(got_ptr + decl_ptr->Offset); + FLOAT *exp = (FLOAT*)(exp_ptr + decl_ptr->Offset); + FLOAT diff = fabsf(*got - *exp); + ok_(__FILE__,line)(diff <= PRECISION, "Mesh %d: Got %f for vertex %d %s, expected %f.\n", + mesh_number, *got, vertex_number, usage_strings[decl_ptr->Usage], *exp); + break; + } + case D3DDECLTYPE_FLOAT2: + { + D3DXVECTOR2 *got = (D3DXVECTOR2*)(got_ptr + decl_ptr->Offset); + D3DXVECTOR2 *exp = (D3DXVECTOR2*)(exp_ptr + decl_ptr->Offset); + FLOAT diff = max(fabsf(got->x - exp->x), fabsf(got->y - exp->y)); + ok_(__FILE__,line)(diff <= PRECISION, "Mesh %d: Got (%f, %f) for vertex %d %s, expected (%f, %f).\n", + mesh_number, got->x, got->y, vertex_number, usage_strings[decl_ptr->Usage], exp->x, exp->y); + break; + } + case D3DDECLTYPE_FLOAT3: + { + D3DXVECTOR3 *got = (D3DXVECTOR3*)(got_ptr + decl_ptr->Offset); + D3DXVECTOR3 *exp = (D3DXVECTOR3*)(exp_ptr + decl_ptr->Offset); + FLOAT diff = max(fabsf(got->x - exp->x), fabsf(got->y - exp->y)); + diff = max(diff, fabsf(got->z - exp->z)); + ok_(__FILE__,line)(diff <= PRECISION, "Mesh %d: Got (%f, %f, %f) for vertex %d %s, expected (%f, %f, %f).\n", + mesh_number, got->x, got->y, got->z, vertex_number, usage_strings[decl_ptr->Usage], exp->x, exp->y, exp->z); + break; + } + case D3DDECLTYPE_FLOAT4: + { + D3DXVECTOR4 *got = (D3DXVECTOR4*)(got_ptr + decl_ptr->Offset); + D3DXVECTOR4 *exp = (D3DXVECTOR4*)(exp_ptr + decl_ptr->Offset); + FLOAT diff = max(fabsf(got->x - exp->x), fabsf(got->y - exp->y)); + diff = max(diff, fabsf(got->z - exp->z)); + diff = max(diff, fabsf(got->w - exp->w)); + ok_(__FILE__,line)(diff <= PRECISION, "Mesh %d: Got (%f, %f, %f, %f) for vertex %d %s, expected (%f, %f, %f, %f).\n", + mesh_number, got->x, got->y, got->z, got->w, vertex_number, usage_strings[decl_ptr->Usage], exp->x, exp->y, exp->z, got->w); + break; + } + case D3DDECLTYPE_D3DCOLOR: + { + BYTE *got = got_ptr + decl_ptr->Offset; + const BYTE *exp = exp_ptr + decl_ptr->Offset; + BOOL same_color = got[0] == exp[0] && got[1] == exp[1] + && got[2] == exp[2] && got[3] == exp[3]; + const char *color_types[] = {"diffuse", "specular", "undefined color"}; + BYTE usage_index = decl_ptr->UsageIndex; + if (usage_index > 1) usage_index = 2; + ok_(__FILE__,line)(same_color, "Mesh %d: Got (%u, %u, %u, %u) for vertex %d %s, expected (%u, %u, %u, %u).\n", + mesh_number, got[0], got[1], got[2], got[3], vertex_number, color_types[usage_index], exp[0], exp[1], exp[2], exp[3]); + break; + } + case D3DDECLTYPE_UBYTE4: + case D3DDECLTYPE_UBYTE4N: + { + BYTE *got = got_ptr + decl_ptr->Offset; + const BYTE *exp = exp_ptr + decl_ptr->Offset; + BOOL same = got[0] == exp[0] && got[1] == exp[1] + && got[2] == exp[2] && got[3] == exp[3]; + ok_(__FILE__,line)(same, "Mesh %d: Got (%u, %u, %u, %u) for vertex %d %s, expected (%u, %u, %u, %u).\n", + mesh_number, got[0], got[1], got[2], got[3], vertex_number, usage_strings[decl_ptr->Usage], exp[0], exp[1], exp[2], exp[3]); + break; + } + case D3DDECLTYPE_SHORT2: + case D3DDECLTYPE_SHORT2N: + { + SHORT *got = (SHORT*)(got_ptr + decl_ptr->Offset); + SHORT *exp = (SHORT*)(exp_ptr + decl_ptr->Offset); + BOOL same = got[0] == exp[0] && got[1] == exp[1]; + ok_(__FILE__,line)(same, "Mesh %d: Got (%hd, %hd) for vertex %d %s, expected (%hd, %hd).\n", + mesh_number, got[0], got[1], vertex_number, usage_strings[decl_ptr->Usage], exp[0], exp[1]); + break; + } + case D3DDECLTYPE_SHORT4: + case D3DDECLTYPE_SHORT4N: + { + SHORT *got = (SHORT*)(got_ptr + decl_ptr->Offset); + SHORT *exp = (SHORT*)(exp_ptr + decl_ptr->Offset); + BOOL same = got[0] == exp[0] && got[1] == exp[1] + && got[2] == exp[2] && got[3] == exp[3]; + ok_(__FILE__,line)(same, "Mesh %d: Got (%hd, %hd, %hd, %hd) for vertex %d %s, expected (%hd, %hd, %hd, %hd).\n", + mesh_number, got[0], got[1], got[2], got[3], vertex_number, usage_strings[decl_ptr->Usage], exp[0], exp[1], exp[2], exp[3]); + break; + } + case D3DDECLTYPE_USHORT2N: + { + USHORT *got = (USHORT*)(got_ptr + decl_ptr->Offset); + USHORT *exp = (USHORT*)(exp_ptr + decl_ptr->Offset); + BOOL same = got[0] == exp[0] && got[1] == exp[1]; + ok_(__FILE__,line)(same, "Mesh %d: Got (%hu, %hu) for vertex %d %s, expected (%hu, %hu).\n", + mesh_number, got[0], got[1], vertex_number, usage_strings[decl_ptr->Usage], exp[0], exp[1]); + break; + } + case D3DDECLTYPE_USHORT4N: + { + USHORT *got = (USHORT*)(got_ptr + decl_ptr->Offset); + USHORT *exp = (USHORT*)(exp_ptr + decl_ptr->Offset); + BOOL same = got[0] == exp[0] && got[1] == exp[1] + && got[2] == exp[2] && got[3] == exp[3]; + ok_(__FILE__,line)(same, "Mesh %d: Got (%hu, %hu, %hu, %hu) for vertex %d %s, expected (%hu, %hu, %hu, %hu).\n", + mesh_number, got[0], got[1], got[2], got[3], vertex_number, usage_strings[decl_ptr->Usage], exp[0], exp[1], exp[2], exp[3]); + break; + } + case D3DDECLTYPE_UDEC3: + { + DWORD *got = (DWORD*)(got_ptr + decl_ptr->Offset); + DWORD *exp = (DWORD*)(exp_ptr + decl_ptr->Offset); + BOOL same = memcmp(got, exp, sizeof(*got)) == 0; + struct udec3 got_udec3 = dword_to_udec3(*got); + struct udec3 exp_udec3 = dword_to_udec3(*exp); + ok_(__FILE__,line)(same, "Mesh %d: Got (%u, %u, %u, %u) for vertex %d %s, expected (%u, %u, %u, %u).\n", + mesh_number, got_udec3.x, got_udec3.y, got_udec3.z, got_udec3.w, vertex_number, usage_strings[decl_ptr->Usage], exp_udec3.x, exp_udec3.y, exp_udec3.z, exp_udec3.w); + + break; + } + case D3DDECLTYPE_DEC3N: + { + DWORD *got = (DWORD*)(got_ptr + decl_ptr->Offset); + DWORD *exp = (DWORD*)(exp_ptr + decl_ptr->Offset); + BOOL same = memcmp(got, exp, sizeof(*got)) == 0; + struct dec3n got_dec3n = dword_to_dec3n(*got); + struct dec3n exp_dec3n = dword_to_dec3n(*exp); + ok_(__FILE__,line)(same, "Mesh %d: Got (%d, %d, %d, %d) for vertex %d %s, expected (%d, %d, %d, %d).\n", + mesh_number, got_dec3n.x, got_dec3n.y, got_dec3n.z, got_dec3n.w, vertex_number, usage_strings[decl_ptr->Usage], exp_dec3n.x, exp_dec3n.y, exp_dec3n.z, exp_dec3n.w); + break; + } + case D3DDECLTYPE_FLOAT16_2: + { + WORD *got = (WORD*)(got_ptr + decl_ptr->Offset); + WORD *exp = (WORD*)(exp_ptr + decl_ptr->Offset); + BOOL same = got[0] == exp[0] && got[1] == exp[1]; + ok_(__FILE__,line)(same, "Mesh %d: Got (%hx, %hx) for vertex %d %s, expected (%hx, %hx).\n", + mesh_number, got[0], got[1], vertex_number, usage_strings[decl_ptr->Usage], exp[0], exp[1]); + break; + } + case D3DDECLTYPE_FLOAT16_4: + { + WORD *got = (WORD*)(got_ptr + decl_ptr->Offset); + WORD *exp = (WORD*)(exp_ptr + decl_ptr->Offset); + BOOL same = got[0] == exp[0] && got[1] == exp[1] + && got[2] == exp[2] && got[3] == exp[3]; + ok_(__FILE__,line)(same, "Mesh %d: Got (%hx, %hx, %hx, %hx) for vertex %d %s, expected (%hx, %hx, %hx, %hx).\n", + mesh_number, got[0], got[1], got[2], got[3], vertex_number, usage_strings[decl_ptr->Usage], exp[0], exp[1], exp[3], exp[4]); + break; + } + default: + break; + } + } +} + +static void test_weld_vertices(void) +{ + HRESULT hr; + struct test_context *test_context = NULL; + DWORD i; + const DWORD options = D3DXMESH_32BIT | D3DXMESH_SYSTEMMEM; + const DWORD options_16bit = D3DXMESH_SYSTEMMEM; + BYTE *vertices = NULL; + DWORD *indices = NULL; + WORD *indices_16bit = NULL; + const UINT VERTS_PER_FACE = 3; +#ifndef __REACTOS__ + const D3DXVECTOR3 up = {0.0f, 0.0f, 1.0f}; +#else +#define up {0.0f, 0.0f, 1.0f} +#endif + struct vertex_normal + { + D3DXVECTOR3 position; + D3DXVECTOR3 normal; + }; + struct vertex_blendweight + { + D3DXVECTOR3 position; + FLOAT blendweight; + }; + struct vertex_texcoord + { + D3DXVECTOR3 position; + D3DXVECTOR2 texcoord; + }; + struct vertex_color + { + D3DXVECTOR3 position; + DWORD color; + }; + struct vertex_color_ubyte4 + { + D3DXVECTOR3 position; + BYTE color[4]; + }; + struct vertex_texcoord_short2 + { + D3DXVECTOR3 position; + SHORT texcoord[2]; + }; + struct vertex_texcoord_ushort2n + { + D3DXVECTOR3 position; + USHORT texcoord[2]; + }; + struct vertex_normal_short4 + { + D3DXVECTOR3 position; + SHORT normal[4]; + }; + struct vertex_texcoord_float16_2 + { + D3DXVECTOR3 position; + WORD texcoord[2]; + }; + struct vertex_texcoord_float16_4 + { + D3DXVECTOR3 position; + WORD texcoord[4]; + }; + struct vertex_normal_udec3 + { + D3DXVECTOR3 position; + DWORD normal; + }; + struct vertex_normal_dec3n + { + D3DXVECTOR3 position; + DWORD normal; + }; + UINT vertex_size_normal = sizeof(struct vertex_normal); + UINT vertex_size_blendweight = sizeof(struct vertex_blendweight); + UINT vertex_size_texcoord = sizeof(struct vertex_texcoord); + UINT vertex_size_color = sizeof(struct vertex_color); + UINT vertex_size_color_ubyte4 = sizeof(struct vertex_color_ubyte4); + UINT vertex_size_texcoord_short2 = sizeof(struct vertex_texcoord_short2); + UINT vertex_size_normal_short4 = sizeof(struct vertex_normal_short4); + UINT vertex_size_texcoord_float16_2 = sizeof(struct vertex_texcoord_float16_2); + UINT vertex_size_texcoord_float16_4 = sizeof(struct vertex_texcoord_float16_4); + UINT vertex_size_normal_udec3 = sizeof(struct vertex_normal_udec3); + UINT vertex_size_normal_dec3n = sizeof(struct vertex_normal_dec3n); + D3DVERTEXELEMENT9 declaration_normal[] = + { + {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0}, + {0, 12, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL, 0}, + D3DDECL_END() + }; + D3DVERTEXELEMENT9 declaration_normal3[] = + { + {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 3}, + {0, 12, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL, 0}, + D3DDECL_END() + }; + D3DVERTEXELEMENT9 declaration_blendweight[] = + { + {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0}, + {0, 12, D3DDECLTYPE_FLOAT1, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_BLENDWEIGHT, 0}, + D3DDECL_END() + }; + D3DVERTEXELEMENT9 declaration_texcoord[] = + { + {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0}, + {0, 12, D3DDECLTYPE_FLOAT2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0}, + D3DDECL_END() + }; + D3DVERTEXELEMENT9 declaration_color[] = + { + {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0}, + {0, 12, D3DDECLTYPE_D3DCOLOR, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_COLOR, 0}, + D3DDECL_END() + }; + D3DVERTEXELEMENT9 declaration_color_ubyte4n[] = + { + {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0}, + {0, 12, D3DDECLTYPE_UBYTE4N, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_COLOR, 0}, + D3DDECL_END() + }; + D3DVERTEXELEMENT9 declaration_color_ubyte4[] = + { + {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0}, + {0, 12, D3DDECLTYPE_UBYTE4, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_COLOR, 0}, + D3DDECL_END() + }; + D3DVERTEXELEMENT9 declaration_texcoord_short2[] = + { + {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0}, + {0, 12, D3DDECLTYPE_SHORT2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0}, + D3DDECL_END() + }; + D3DVERTEXELEMENT9 declaration_texcoord_short2n[] = + { + {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0}, + {0, 12, D3DDECLTYPE_SHORT2N, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0}, + D3DDECL_END() + }; + D3DVERTEXELEMENT9 declaration_texcoord_ushort2n[] = + { + {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0}, + {0, 12, D3DDECLTYPE_USHORT2N, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0}, + D3DDECL_END() + }; + D3DVERTEXELEMENT9 declaration_normal_short4[] = + { + {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0}, + {0, 12, D3DDECLTYPE_SHORT4, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL, 0}, + D3DDECL_END() + }; + D3DVERTEXELEMENT9 declaration_normal_short4n[] = + { + {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0}, + {0, 12, D3DDECLTYPE_SHORT4N, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL, 0}, + D3DDECL_END() + }; + D3DVERTEXELEMENT9 declaration_normal_ushort4n[] = + { + {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0}, + {0, 12, D3DDECLTYPE_USHORT4N, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL, 0}, + D3DDECL_END() + }; + D3DVERTEXELEMENT9 declaration_texcoord10[] = + { + {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0}, + {0, 12, D3DDECLTYPE_FLOAT2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 10}, + D3DDECL_END() + }; + D3DVERTEXELEMENT9 declaration_color2[] = + { + {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0}, + {0, 12, D3DDECLTYPE_D3DCOLOR, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_COLOR, 2}, + D3DDECL_END() + }; + D3DVERTEXELEMENT9 declaration_color1[] = + { + {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0}, + {0, 12, D3DDECLTYPE_D3DCOLOR, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_COLOR, 1}, + D3DDECL_END() + }; + D3DVERTEXELEMENT9 declaration_texcoord_float16_2[] = + { + {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0}, + {0, 12, D3DDECLTYPE_FLOAT16_2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0}, + D3DDECL_END() + }; + D3DVERTEXELEMENT9 declaration_texcoord_float16_4[] = + { + {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0}, + {0, 12, D3DDECLTYPE_FLOAT16_4, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0}, + D3DDECL_END() + }; + D3DVERTEXELEMENT9 declaration_normal_udec3[] = + { + {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0}, + {0, 12, D3DDECLTYPE_UDEC3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL, 0}, + D3DDECL_END() + }; + D3DVERTEXELEMENT9 declaration_normal_dec3n[] = + { + {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0}, + {0, 12, D3DDECLTYPE_DEC3N, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL, 0}, + D3DDECL_END() + }; + /* Test 0. One face and no welding. + * + * 0--1 + * | / + * |/ + * 2 + */ + const struct vertex vertices0[] = + { + {{ 0.0f, 3.0f, 0.f}, up}, + {{ 2.0f, 3.0f, 0.f}, up}, + {{ 0.0f, 0.0f, 0.f}, up}, + }; + const DWORD indices0[] = {0, 1, 2}; + const DWORD attributes0[] = {0}; + const DWORD exp_indices0[] = {0, 1, 2}; + const UINT num_vertices0 = ARRAY_SIZE(vertices0); + const UINT num_faces0 = ARRAY_SIZE(indices0) / VERTS_PER_FACE; + const DWORD flags0 = D3DXWELDEPSILONS_WELDALL; + /* epsilons0 is NULL */ + const DWORD adjacency0[] = {-1, -1, -1}; + const struct vertex exp_vertices0[] = + { + {{ 0.0f, 3.0f, 0.f}, up}, + {{ 2.0f, 3.0f, 0.f}, up}, + {{ 0.0f, 0.0f, 0.f}, up}, + }; + const DWORD exp_face_remap0[] = {0}; + const DWORD exp_vertex_remap0[] = {0, 1, 2}; + const DWORD exp_new_num_vertices0 = ARRAY_SIZE(exp_vertices0); + /* Test 1. Two vertices should be removed without regard to epsilon. + * + * 0--1 3 + * | / /| + * |/ / | + * 2 5--4 + */ + const struct vertex_normal vertices1[] = + { + {{ 0.0f, 3.0f, 0.f}, up}, + {{ 2.0f, 3.0f, 0.f}, up}, + {{ 0.0f, 0.0f, 0.f}, up}, + + {{ 3.0f, 3.0f, 0.f}, up}, + {{ 3.0f, 0.0f, 0.f}, up}, + {{ 1.0f, 0.0f, 0.f}, up}, + }; + const DWORD indices1[] = {0, 1, 2, 3, 4, 5}; + const DWORD attributes1[] = {0, 0}; + const UINT num_vertices1 = ARRAY_SIZE(vertices1); + const UINT num_faces1 = ARRAY_SIZE(indices1) / VERTS_PER_FACE; + const DWORD flags1 = D3DXWELDEPSILONS_WELDALL; + /* epsilons1 is NULL */ + const DWORD adjacency1[] = {-1, 1, -1, -1, -1, 0}; + const struct vertex_normal exp_vertices1[] = + { + {{ 0.0f, 3.0f, 0.f}, up}, + {{ 2.0f, 3.0f, 0.f}, up}, + {{ 0.0f, 0.0f, 0.f}, up}, + + {{ 3.0f, 0.0f, 0.f}, up} + }; + const DWORD exp_indices1[] = {0, 1, 2, 1, 3, 2}; + const DWORD exp_face_remap1[] = {0, 1}; + const DWORD exp_vertex_remap1[] = {0, 1, 2, 4, -1, -1}; + const DWORD exp_new_num_vertices1 = ARRAY_SIZE(exp_vertices1); + /* Test 2. Two faces. No vertices should be removed because of normal + * epsilon, but the positions should be replaced. */ + const struct vertex_normal vertices2[] = + { + {{ 0.0f, 3.0f, 0.f}, up}, + {{ 2.0f, 3.0f, 0.f}, up}, + {{ 0.0f, 0.0f, 0.f}, up}, + + {{ 3.0f, 3.0f, 0.f}, {0.0f, 0.5f, 0.5f}}, + {{ 3.0f, 0.0f, 0.f}, up}, + {{ 1.0f, 0.0f, 0.f}, {0.2f, 0.4f, 0.4f}}, + }; + const DWORD indices2[] = {0, 1, 2, 3, 4, 5}; + const DWORD attributes2[] = {0, 0}; + const UINT num_vertices2 = ARRAY_SIZE(vertices2); + const UINT num_faces2 = ARRAY_SIZE(indices2) / VERTS_PER_FACE; + DWORD flags2 = D3DXWELDEPSILONS_WELDPARTIALMATCHES; + const D3DXWELDEPSILONS epsilons2 = {1.0f, 0.0f, 0.499999f, 0.0f, 0.0f, 0.0f, {0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f}, 0.0f, 0.0f, 0.0f}; + const DWORD adjacency2[] = {-1, 1, -1, -1, -1, 0}; + const struct vertex_normal exp_vertices2[] = + { + {{ 0.0f, 3.0f, 0.f}, up}, + {{ 2.0f, 3.0f, 0.f}, up}, + {{ 0.0f, 0.0f, 0.f}, up}, + + {{ 2.0f, 3.0f, 0.f}, {0.0f, 0.5f, 0.5f}}, + {{ 3.0f, 0.0f, 0.f}, up}, + {{ 0.0f, 0.0f, 0.f}, {0.2f, 0.4f, 0.4f}}, + }; + const DWORD exp_indices2[] = {0, 1, 2, 3, 4, 5}; + const DWORD exp_face_remap2[] = {0, 1}; + const DWORD exp_vertex_remap2[] = {0, 1, 2, 3, 4, 5}; + const DWORD exp_new_num_vertices2 = ARRAY_SIZE(exp_vertices2); + /* Test 3. Two faces. One vertex should be removed because of normal epsilon. */ + const struct vertex_normal vertices3[] = + { + {{ 0.0f, 3.0f, 0.f}, up}, + {{ 2.0f, 3.0f, 0.f}, up}, + {{ 0.0f, 0.0f, 0.f}, up}, + + {{ 3.0f, 3.0f, 0.f}, {0.0f, 0.5f, 0.5f}}, + {{ 3.0f, 0.0f, 0.f}, up}, + {{ 1.0f, 0.0f, 0.f}, {0.2f, 0.4f, 0.4f}}, + }; + const DWORD indices3[] = {0, 1, 2, 3, 4, 5}; + const DWORD attributes3[] = {0, 0}; + const UINT num_vertices3 = ARRAY_SIZE(vertices3); + const UINT num_faces3 = ARRAY_SIZE(indices3) / VERTS_PER_FACE; + DWORD flags3 = D3DXWELDEPSILONS_WELDPARTIALMATCHES; + const D3DXWELDEPSILONS epsilons3 = {1.0f, 0.0f, 0.5f, 0.0f, 0.0f, 0.0f, {0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f}, 0.0f, 0.0f, 0.0f}; + const DWORD adjacency3[] = {-1, 1, -1, -1, -1, 0}; + const struct vertex_normal exp_vertices3[] = + { + {{ 0.0f, 3.0f, 0.f}, up}, + {{ 2.0f, 3.0f, 0.f}, up}, + {{ 0.0f, 0.0f, 0.f}, up}, + + {{ 3.0f, 0.0f, 0.f}, up}, + {{ 0.0f, 0.0f, 0.f}, {0.2f, 0.4f, 0.4f}}, + }; + const DWORD exp_indices3[] = {0, 1, 2, 1, 3, 4}; + const DWORD exp_face_remap3[] = {0, 1}; + const DWORD exp_vertex_remap3[] = {0, 1, 2, 4, 5, -1}; + const DWORD exp_new_num_vertices3 = ARRAY_SIZE(exp_vertices3); + /* Test 4 Two faces. Two vertices should be removed. */ + const struct vertex_normal vertices4[] = + { + {{ 0.0f, 3.0f, 0.f}, up}, + {{ 2.0f, 3.0f, 0.f}, up}, + {{ 0.0f, 0.0f, 0.f}, up}, + + {{ 3.0f, 3.0f, 0.f}, {0.0f, 0.5f, 0.5f}}, + {{ 3.0f, 0.0f, 0.f}, up}, + {{ 1.0f, 0.0f, 0.f}, {0.2f, 0.4f, 0.4f}}, + }; + const DWORD indices4[] = {0, 1, 2, 3, 4, 5}; + const DWORD attributes4[] = {0, 0}; + const UINT num_vertices4 = ARRAY_SIZE(vertices4); + const UINT num_faces4 = ARRAY_SIZE(indices4) / VERTS_PER_FACE; + DWORD flags4 = D3DXWELDEPSILONS_WELDPARTIALMATCHES; + const D3DXWELDEPSILONS epsilons4 = {1.0f, 0.0f, 0.6f, 0.0f, 0.0f, 0.0f, {0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f}, 0.0f, 0.0f, 0.0f}; + const DWORD adjacency4[] = {-1, 1, -1, -1, -1, 0}; + const struct vertex_normal exp_vertices4[] = + { + {{ 0.0f, 3.0f, 0.f}, up}, + {{ 2.0f, 3.0f, 0.f}, up}, + {{ 0.0f, 0.0f, 0.f}, up}, + + {{ 3.0f, 0.0f, 0.f}, up}, + }; + const DWORD exp_indices4[] = {0, 1, 2, 1, 3, 2}; + const DWORD exp_face_remap4[] = {0, 1}; + const DWORD exp_vertex_remap4[] = {0, 1, 2, 4, -1, -1}; + const DWORD exp_new_num_vertices4 = ARRAY_SIZE(exp_vertices4); + /* Test 5. Odd face ordering. + * + * 0--1 6 3 + * | / /| |\ + * |/ / | | \ + * 2 8--7 5--4 + */ + const struct vertex_normal vertices5[] = + { + {{ 0.0f, 3.0f, 0.f}, up}, + {{ 2.0f, 3.0f, 0.f}, up}, + {{ 0.0f, 0.0f, 0.f}, up}, + + {{ 3.0f, 3.0f, 0.f}, up}, + {{ 3.0f, 0.0f, 0.f}, up}, + {{ 1.0f, 0.0f, 0.f}, up}, + + {{ 4.0f, 3.0f, 0.f}, up}, + {{ 6.0f, 0.0f, 0.f}, up}, + {{ 4.0f, 0.0f, 0.f}, up}, + }; + const DWORD indices5[] = {0, 1, 2, 6, 7, 8, 3, 4, 5}; + const DWORD exp_indices5[] = {0, 1, 2, 1, 4, 2, 1, 3, 4}; + const DWORD attributes5[] = {0, 0, 0}; + const UINT num_vertices5 = ARRAY_SIZE(vertices5); + const UINT num_faces5 = ARRAY_SIZE(indices5) / VERTS_PER_FACE; + DWORD flags5 = D3DXWELDEPSILONS_WELDALL; + const DWORD adjacency5[] = {-1, 1, -1, 2, -1, 0, -1, -1, 1}; + const struct vertex_normal exp_vertices5[] = + { + {{ 0.0f, 3.0f, 0.f}, up}, + {{ 2.0f, 3.0f, 0.f}, up}, + {{ 0.0f, 0.0f, 0.f}, up}, + + {{ 3.0f, 0.0f, 0.f}, up}, + {{ 1.0f, 0.0f, 0.f}, up}, + }; + const DWORD exp_face_remap5[] = {0, 1, 2}; + const DWORD exp_vertex_remap5[] = {0, 1, 2, 4, 5, -1, -1, -1, -1}; + const DWORD exp_new_num_vertices5 = ARRAY_SIZE(exp_vertices5); + /* Test 6. Two faces. Do not remove flag is used, so no vertices should be + * removed. */ + const struct vertex_normal vertices6[] = + { + {{ 0.0f, 3.0f, 0.f}, up}, + {{ 2.0f, 3.0f, 0.f}, up}, + {{ 0.0f, 0.0f, 0.f}, up}, + + {{ 3.0f, 3.0f, 0.f}, {0.0f, 0.5f, 0.5f}}, + {{ 3.0f, 0.0f, 0.f}, up}, + {{ 1.0f, 0.0f, 0.f}, {0.2f, 0.4f, 0.4f}}, + }; + const DWORD indices6[] = {0, 1, 2, 3, 4, 5}; + const DWORD attributes6[] = {0, 0}; + const UINT num_vertices6 = ARRAY_SIZE(vertices6); + const UINT num_faces6 = ARRAY_SIZE(indices6) / VERTS_PER_FACE; + DWORD flags6 = D3DXWELDEPSILONS_WELDPARTIALMATCHES | D3DXWELDEPSILONS_DONOTREMOVEVERTICES; + const D3DXWELDEPSILONS epsilons6 = {1.0f, 0.0f, 0.6f, 0.0f, 0.0f, 0.0f, {0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f}, 0.0f, 0.0f, 0.0f}; + const DWORD adjacency6[] = {-1, 1, -1, -1, -1, 0}; + const struct vertex_normal exp_vertices6[] = + { + {{ 0.0f, 3.0f, 0.f}, up}, + {{ 2.0f, 3.0f, 0.f}, up}, + {{ 0.0f, 0.0f, 0.f}, up}, + + {{ 2.0f, 3.0f, 0.f}, up}, + {{ 3.0f, 0.0f, 0.f}, up}, + {{ 0.0f, 0.0f, 0.f}, up}, + + }; + const DWORD exp_indices6[] = {0, 1, 2, 3, 4, 5}; + const DWORD exp_face_remap6[] = {0, 1}; + const DWORD exp_vertex_remap6[] = {0, 1, 2, 3, 4, 5}; + const DWORD exp_new_num_vertices6 = ARRAY_SIZE(exp_vertices6); + /* Test 7. Same as test 6 but with 16 bit indices. */ + const WORD indices6_16bit[] = {0, 1, 2, 3, 4, 5}; + /* Test 8. No flags. Same result as D3DXWELDEPSILONS_WELDPARTIALMATCHES. */ + const struct vertex_normal vertices8[] = + { + {{ 0.0f, 3.0f, 0.f}, up}, + {{ 2.0f, 3.0f, 0.f}, up}, + {{ 0.0f, 0.0f, 0.f}, up}, + + {{ 3.0f, 3.0f, 0.f}, {0.0f, 0.5f, 0.5f}}, + {{ 3.0f, 0.0f, 0.f}, up}, + {{ 1.0f, 0.0f, 0.f}, {0.2f, 0.4f, 0.4f}}, + }; + const DWORD indices8[] = {0, 1, 2, 1, 3, 4}; + const DWORD attributes8[] = {0, 0}; + const UINT num_vertices8 = ARRAY_SIZE(vertices8); + const UINT num_faces8 = ARRAY_SIZE(indices8) / VERTS_PER_FACE; + DWORD flags8 = 0; + const D3DXWELDEPSILONS epsilons8 = {1.0f, 0.0f, 0.5f, 0.0f, 0.0f, 0.0f, {0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f}, 0.0f, 0.0f, 0.0f}; + const DWORD adjacency8[] = {-1, 1, -1, -1, -1, 0}; + const struct vertex_normal exp_vertices8[] = + { + {{ 0.0f, 3.0f, 0.f}, up}, + {{ 2.0f, 3.0f, 0.f}, up}, + {{ 0.0f, 0.0f, 0.f}, up}, + + {{ 3.0f, 3.0f, 0.f}, {0.0f, 0.5f, 0.5f}}, + {{ 3.0f, 0.0f, 0.f}, up}, + }; + const DWORD exp_indices8[] = {0, 1, 2, 1, 3, 4}; + const DWORD exp_face_remap8[] = {0, 1}; + const DWORD exp_vertex_remap8[] = {0, 1, 2, 3, 4, -1}; + const DWORD exp_new_num_vertices8 = ARRAY_SIZE(exp_vertices8); + /* Test 9. Vertices are removed even though they belong to separate + * attribute groups if D3DXWELDEPSILONS_DONOTSPLIT is set. */ + const struct vertex_normal vertices9[] = + { + {{ 0.0f, 3.0f, 0.f}, up}, + {{ 2.0f, 3.0f, 0.f}, up}, + {{ 0.0f, 0.0f, 0.f}, up}, + + {{ 3.0f, 3.0f, 0.f}, {0.0f, 0.5f, 0.5f}}, + {{ 3.0f, 0.0f, 0.f}, up}, + {{ 1.0f, 0.0f, 0.f}, {0.2f, 0.4f, 0.4f}}, + }; + const DWORD indices9[] = {0, 1, 2, 3, 4, 5}; + const DWORD attributes9[] = {0, 1}; + const UINT num_vertices9 = ARRAY_SIZE(vertices9); + const UINT num_faces9 = ARRAY_SIZE(indices9) / VERTS_PER_FACE; + DWORD flags9 = D3DXWELDEPSILONS_WELDPARTIALMATCHES | D3DXWELDEPSILONS_DONOTSPLIT; + const D3DXWELDEPSILONS epsilons9 = {1.0f, 0.0f, 0.6f, 0.0f, 0.0f, 0.0f, {0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f}, 0.0f, 0.0f, 0.0f}; + const DWORD adjacency9[] = {-1, 1, -1, -1, -1, 0}; + const struct vertex_normal exp_vertices9[] = + { + {{ 0.0f, 3.0f, 0.f}, up}, + {{ 2.0f, 3.0f, 0.f}, up}, + {{ 0.0f, 0.0f, 0.f}, up}, + + {{ 3.0f, 0.0f, 0.f}, up}, + }; + const DWORD exp_indices9[] = {0, 1, 2, 1, 3, 2}; + const DWORD exp_face_remap9[] = {0, 1}; + const DWORD exp_vertex_remap9[] = {0, 1, 2, 4, -1, -1}; + const DWORD exp_new_num_vertices9 = ARRAY_SIZE(exp_vertices9); + /* Test 10. Weld blendweight (FLOAT1). */ + const struct vertex_blendweight vertices10[] = + { + {{ 0.0f, 3.0f, 0.f}, 1.0f}, + {{ 2.0f, 3.0f, 0.f}, 1.0f}, + {{ 0.0f, 0.0f, 0.f}, 1.0f}, + + {{ 3.0f, 3.0f, 0.f}, 0.9}, + {{ 3.0f, 0.0f, 0.f}, 1.0}, + {{ 1.0f, 0.0f, 0.f}, 0.4}, + }; + const DWORD indices10[] = {0, 1, 2, 3, 4, 5}; + const DWORD attributes10[] = {0, 0}; + const UINT num_vertices10 = ARRAY_SIZE(vertices10); + const UINT num_faces10 = ARRAY_SIZE(indices10) / VERTS_PER_FACE; + DWORD flags10 = D3DXWELDEPSILONS_WELDPARTIALMATCHES; + const D3DXWELDEPSILONS epsilons10 = {1.0f, 0.1f + FLT_EPSILON, 0.0f, 0.0f, 0.0f, 0.0f, {0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f}, 0.0f, 0.0f, 0.0f}; + const DWORD adjacency10[] = {-1, 1, -1, -1, -1, 0}; + const struct vertex_blendweight exp_vertices10[] = + { + {{ 0.0f, 3.0f, 0.f}, 1.0f}, + {{ 2.0f, 3.0f, 0.f}, 1.0f}, + {{ 0.0f, 0.0f, 0.f}, 1.0f}, + + {{ 3.0f, 0.0f, 0.f}, 1.0}, + {{ 0.0f, 0.0f, 0.f}, 0.4}, + }; + const DWORD exp_indices10[] = {0, 1, 2, 1, 3, 4}; + const DWORD exp_face_remap10[] = {0, 1}; + const DWORD exp_vertex_remap10[] = {0, 1, 2, 4, 5, -1}; + const DWORD exp_new_num_vertices10 = ARRAY_SIZE(exp_vertices10); + /* Test 11. Weld texture coordinates. */ + const struct vertex_texcoord vertices11[] = + { + {{ 0.0f, 3.0f, 0.f}, {1.0f, 1.0f}}, + {{ 2.0f, 3.0f, 0.f}, {0.5f, 0.7f}}, + {{ 0.0f, 0.0f, 0.f}, {-0.2f, -0.3f}}, + + {{ 3.0f, 3.0f, 0.f}, {0.2f, 0.3f}}, + {{ 3.0f, 0.0f, 0.f}, {1.0f, 1.0f}}, + {{ 1.0f, 0.0f, 0.f}, {0.1f, 0.2f}} + }; + const DWORD indices11[] = {0, 1, 2, 3, 4, 5}; + const DWORD attributes11[] = {0, 0}; + const UINT num_vertices11 = ARRAY_SIZE(vertices11); + const UINT num_faces11 = ARRAY_SIZE(indices11) / VERTS_PER_FACE; + DWORD flags11 = D3DXWELDEPSILONS_WELDPARTIALMATCHES; + const D3DXWELDEPSILONS epsilons11 = {1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, {0.4f + FLT_EPSILON, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f}, 0.0f, 0.0f, 0.0f}; + const DWORD adjacency11[] = {-1, 1, -1, -1, -1, 0}; + const struct vertex_texcoord exp_vertices11[] = + { + {{ 0.0f, 3.0f, 0.f}, {1.0f, 1.0f}}, + {{ 2.0f, 3.0f, 0.f}, {0.5f, 0.7f}}, + {{ 0.0f, 0.0f, 0.f}, {-0.2f, -0.3f}}, + + {{ 3.0f, 0.0f, 0.f}, {1.0f, 1.0f}}, + {{ 0.0f, 0.0f, 0.f}, {0.1f, 0.2f}}, + }; + const DWORD exp_indices11[] = {0, 1, 2, 1, 3, 4}; + const DWORD exp_face_remap11[] = {0, 1}; + const DWORD exp_vertex_remap11[] = {0, 1, 2, 4, 5, -1}; + const DWORD exp_new_num_vertices11 = ARRAY_SIZE(exp_vertices11); + /* Test 12. Weld with color. */ + const struct vertex_color vertices12[] = + { + {{ 0.0f, 3.0f, 0.f}, 0xFFFFFFFF}, + {{ 2.0f, 3.0f, 0.f}, 0xFFFFFFFF}, + {{ 0.0f, 0.0f, 0.f}, 0xFFFFFFFF}, + + {{ 3.0f, 3.0f, 0.f}, 0x00000000}, + {{ 3.0f, 0.0f, 0.f}, 0xFFFFFFFF}, + {{ 1.0f, 0.0f, 0.f}, 0x88888888}, + }; + const DWORD indices12[] = {0, 1, 2, 3, 4, 5}; + const DWORD attributes12[] = {0, 0}; + const UINT num_vertices12 = ARRAY_SIZE(vertices12); + const UINT num_faces12 = ARRAY_SIZE(indices12) / VERTS_PER_FACE; + DWORD flags12 = D3DXWELDEPSILONS_WELDPARTIALMATCHES; + const D3DXWELDEPSILONS epsilons12 = {1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.5f, {0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f}, 0.0f, 0.0f, 0.0f}; + const DWORD adjacency12[] = {-1, 1, -1, -1, -1, 0}; + const struct vertex_color exp_vertices12[] = + { + {{ 0.0f, 3.0f, 0.f}, 0xFFFFFFFF}, + {{ 2.0f, 3.0f, 0.f}, 0xFFFFFFFF}, + {{ 0.0f, 0.0f, 0.f}, 0xFFFFFFFF}, + + {{ 2.0f, 3.0f, 0.f}, 0x00000000}, + {{ 3.0f, 0.0f, 0.f}, 0xFFFFFFFF}, + }; + const DWORD exp_indices12[] = {0, 1, 2, 3, 4, 2}; + const DWORD exp_face_remap12[] = {0, 1}; + const DWORD exp_vertex_remap12[] = {0, 1, 2, 3, 4, -1}; + const DWORD exp_new_num_vertices12 = ARRAY_SIZE(exp_vertices12); + /* Test 13. Two faces. One vertex should be removed because of normal epsilon. + * This is similar to test 3, but the declaration has been changed to NORMAL3. + */ + const struct vertex_normal vertices13[] = + { + {{ 0.0f, 3.0f, 0.f}, up}, + {{ 2.0f, 3.0f, 0.f}, up}, + {{ 0.0f, 0.0f, 0.f}, up}, + + {{ 3.0f, 3.0f, 0.f}, {0.0f, 0.5f, 0.5f}}, + {{ 3.0f, 0.0f, 0.f}, up}, + {{ 1.0f, 0.0f, 0.f}, {0.2f, 0.4f, 0.4f}}, + }; + const DWORD indices13[] = {0, 1, 2, 3, 4, 5}; + const DWORD attributes13[] = {0, 0}; + const UINT num_vertices13 = ARRAY_SIZE(vertices3); + const UINT num_faces13 = ARRAY_SIZE(indices3) / VERTS_PER_FACE; + DWORD flags13 = D3DXWELDEPSILONS_WELDPARTIALMATCHES; + const D3DXWELDEPSILONS epsilons13 = {1.0f, 0.0f, 0.5f, 0.0f, 0.0f, 0.0f, {0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f}, 0.0f, 0.0f, 0.0f}; + const DWORD adjacency13[] = {-1, 1, -1, -1, -1, 0}; + const struct vertex_normal exp_vertices13[] = + { + {{ 0.0f, 3.0f, 0.f}, up}, + {{ 2.0f, 3.0f, 0.f}, up}, + {{ 0.0f, 0.0f, 0.f}, up}, + + {{ 3.0f, 0.0f, 0.f}, up}, + {{ 0.0f, 0.0f, 0.f}, {0.2f, 0.4f, 0.4f}}, + }; + const DWORD exp_indices13[] = {0, 1, 2, 1, 3, 4}; + const DWORD exp_face_remap13[] = {0, 1}; + const DWORD exp_vertex_remap13[] = {0, 1, 2, 4, 5, -1}; + const DWORD exp_new_num_vertices13 = ARRAY_SIZE(exp_vertices13); + /* Test 14. Another test for welding with color. */ + const struct vertex_color vertices14[] = + { + {{ 0.0f, 3.0f, 0.f}, 0xFFFFFFFF}, + {{ 2.0f, 3.0f, 0.f}, 0xFFFFFFFF}, + {{ 0.0f, 0.0f, 0.f}, 0xFFFFFFFF}, + + {{ 3.0f, 3.0f, 0.f}, 0x00000000}, + {{ 3.0f, 0.0f, 0.f}, 0xFFFFFFFF}, + {{ 1.0f, 0.0f, 0.f}, 0x01010101}, + }; + const DWORD indices14[] = {0, 1, 2, 3, 4, 5}; + const DWORD attributes14[] = {0, 0}; + const UINT num_vertices14 = ARRAY_SIZE(vertices14); + const UINT num_faces14 = ARRAY_SIZE(indices14) / VERTS_PER_FACE; + DWORD flags14 = D3DXWELDEPSILONS_WELDPARTIALMATCHES; + const D3DXWELDEPSILONS epsilons14 = {1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 254.0f/255.0f, {0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f}, 0.0f, 0.0f, 0.0f}; + const DWORD adjacency14[] = {-1, 1, -1, -1, -1, 0}; + const struct vertex_color exp_vertices14[] = + { + {{ 0.0f, 3.0f, 0.f}, 0xFFFFFFFF}, + {{ 2.0f, 3.0f, 0.f}, 0xFFFFFFFF}, + {{ 0.0f, 0.0f, 0.f}, 0xFFFFFFFF}, + + {{ 2.0f, 3.0f, 0.f}, 0x00000000}, + {{ 3.0f, 0.0f, 0.f}, 0xFFFFFFFF}, + }; + const DWORD exp_indices14[] = {0, 1, 2, 3, 4, 2}; + const DWORD exp_face_remap14[] = {0, 1}; + const DWORD exp_vertex_remap14[] = {0, 1, 2, 3, 4, -1}; + const DWORD exp_new_num_vertices14 = ARRAY_SIZE(exp_vertices14); + /* Test 15. Weld with color, but as UBYTE4N instead of D3DCOLOR. It shows + * that UBYTE4N and D3DCOLOR are compared the same way. + */ + const struct vertex_color_ubyte4 vertices15[] = + { + {{ 0.0f, 3.0f, 0.f}, {255, 255, 255, 255}}, + {{ 2.0f, 3.0f, 0.f}, {255, 255, 255, 255}}, + {{ 0.0f, 0.0f, 0.f}, {255, 255, 255, 255}}, + + {{ 3.0f, 3.0f, 0.f}, { 0, 0, 0, 0}}, + {{ 3.0f, 0.0f, 0.f}, {255, 255, 255, 255}}, + {{ 1.0f, 0.0f, 0.f}, { 1, 1, 1, 1}}, + }; + const DWORD indices15[] = {0, 1, 2, 3, 4, 5}; + const DWORD attributes15[] = {0, 0}; + const UINT num_vertices15 = ARRAY_SIZE(vertices15); + const UINT num_faces15 = ARRAY_SIZE(indices15) / VERTS_PER_FACE; + DWORD flags15 = D3DXWELDEPSILONS_WELDPARTIALMATCHES; + const D3DXWELDEPSILONS epsilons15 = {1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 254.0f/255.0f, {0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f}, 0.0f, 0.0f, 0.0f}; + const DWORD adjacency15[] = {-1, 1, -1, -1, -1, 0}; + const struct vertex_color_ubyte4 exp_vertices15[] = + { + {{ 0.0f, 3.0f, 0.f}, {255, 255, 255, 255}}, + {{ 2.0f, 3.0f, 0.f}, {255, 255, 255, 255}}, + {{ 0.0f, 0.0f, 0.f}, {255, 255, 255, 255}}, + + {{ 2.0f, 3.0f, 0.f}, { 0, 0, 0, 0}}, + {{ 3.0f, 0.0f, 0.f}, {255, 255, 255, 255}}, + }; + const DWORD exp_indices15[] = {0, 1, 2, 3, 4, 2}; + const DWORD exp_face_remap15[] = {0, 1}; + const DWORD exp_vertex_remap15[] = {0, 1, 2, 3, 4, -1}; + const DWORD exp_new_num_vertices15 = ARRAY_SIZE(exp_vertices15); + /* Test 16. Weld with color, but as UBYTE4 instead of D3DCOLOR. It shows + * that UBYTE4 is not normalized and that epsilon is truncated and compared + * directly to each of the four bytes. + */ + const struct vertex_color_ubyte4 vertices16[] = + { + {{ 0.0f, 3.0f, 0.f}, {255, 255, 255, 255}}, + {{ 2.0f, 3.0f, 0.f}, {255, 255, 255, 255}}, + {{ 0.0f, 0.0f, 0.f}, {255, 255, 255, 255}}, + + {{ 3.0f, 3.0f, 0.f}, { 0, 0, 0, 0}}, + {{ 3.0f, 0.0f, 0.f}, {255, 255, 255, 255}}, + {{ 1.0f, 0.0f, 0.f}, { 1, 1, 1, 1}}, + }; + const DWORD indices16[] = {0, 1, 2, 3, 4, 5}; + const DWORD attributes16[] = {0, 0}; + const UINT num_vertices16 = ARRAY_SIZE(vertices16); + const UINT num_faces16 = ARRAY_SIZE(indices16) / VERTS_PER_FACE; + DWORD flags16 = D3DXWELDEPSILONS_WELDPARTIALMATCHES; + const D3DXWELDEPSILONS epsilons16 = {1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 254.9f, {0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f}, 0.0f, 0.0f, 0.0f}; + const DWORD adjacency16[] = {-1, 1, -1, -1, -1, 0}; + const struct vertex_color_ubyte4 exp_vertices16[] = + { + {{ 0.0f, 3.0f, 0.f}, {255, 255, 255, 255}}, + {{ 2.0f, 3.0f, 0.f}, {255, 255, 255, 255}}, + {{ 0.0f, 0.0f, 0.f}, {255, 255, 255, 255}}, + + {{ 2.0f, 3.0f, 0.f}, { 0, 0, 0, 0}}, + {{ 3.0f, 0.0f, 0.f}, {255, 255, 255, 255}}, + }; + const DWORD exp_indices16[] = {0, 1, 2, 3, 4, 2}; + const DWORD exp_face_remap16[] = {0, 1}; + const DWORD exp_vertex_remap16[] = {0, 1, 2, 3, 4, -1}; + const DWORD exp_new_num_vertices16 = ARRAY_SIZE(exp_vertices16); + /* Test 17. Weld texture coordinates but as SHORT2 instead of D3DXVECTOR2.*/ + const struct vertex_texcoord_short2 vertices17[] = + { + {{ 0.0f, 3.0f, 0.f}, { 0, 0}}, + {{ 2.0f, 3.0f, 0.f}, { 0, 0}}, + {{ 0.0f, 0.0f, 0.f}, { 0, 0}}, + + {{ 3.0f, 3.0f, 0.f}, {32767, 32767}}, + {{ 3.0f, 0.0f, 0.f}, {0, 0}}, + {{ 1.0f, 0.0f, 0.f}, {32766, 32766}}, + }; + const DWORD indices17[] = {0, 1, 2, 3, 4, 5}; + const DWORD attributes17[] = {0, 0}; + const UINT num_vertices17 = ARRAY_SIZE(vertices17); + const UINT num_faces17 = ARRAY_SIZE(indices17) / VERTS_PER_FACE; + DWORD flags17 = D3DXWELDEPSILONS_WELDPARTIALMATCHES; + const D3DXWELDEPSILONS epsilons17 = {1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, {32766.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f}, 0.0f, 0.0f, 0.0f}; + const DWORD adjacency17[] = {-1, 1, -1, -1, -1, 0}; + const struct vertex_texcoord_short2 exp_vertices17[] = + { + {{ 0.0f, 3.0f, 0.f}, { 0, 0}}, + {{ 2.0f, 3.0f, 0.f}, { 0, 0}}, + {{ 0.0f, 0.0f, 0.f}, { 0, 0}}, + + {{ 2.0f, 3.0f, 0.f}, {32767, 32767}}, + {{ 3.0f, 0.0f, 0.f}, {0, 0}}, + }; + const DWORD exp_indices17[] = {0, 1, 2, 3, 4, 2}; + const DWORD exp_face_remap17[] = {0, 1}; + const DWORD exp_vertex_remap17[] = {0, 1, 2, 3, 4, -1}; + const DWORD exp_new_num_vertices17 = ARRAY_SIZE(exp_vertices17); + /* Test 18. Weld texture coordinates but as SHORT2N instead of D3DXVECTOR2. */ + const struct vertex_texcoord_short2 vertices18[] = + { + {{ 0.0f, 3.0f, 0.f}, { 0, 0}}, + {{ 2.0f, 3.0f, 0.f}, { 0, 0}}, + {{ 0.0f, 0.0f, 0.f}, { 0, 0}}, + + {{ 3.0f, 3.0f, 0.f}, {32767, 32767}}, + {{ 3.0f, 0.0f, 0.f}, {0, 0}}, + {{ 1.0f, 0.0f, 0.f}, {32766, 32766}}, + }; + const DWORD indices18[] = {0, 1, 2, 3, 4, 5}; + const DWORD attributes18[] = {0, 0}; + const UINT num_vertices18 = ARRAY_SIZE(vertices18); + const UINT num_faces18 = ARRAY_SIZE(indices18) / VERTS_PER_FACE; + DWORD flags18 = D3DXWELDEPSILONS_WELDPARTIALMATCHES; + const D3DXWELDEPSILONS epsilons18 = {1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, {32766.0f/32767.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f}, 0.0f, 0.0f, 0.0f}; + const DWORD adjacency18[] = {-1, 1, -1, -1, -1, 0}; + const struct vertex_texcoord_short2 exp_vertices18[] = + { + {{ 0.0f, 3.0f, 0.f}, { 0, 0}}, + {{ 2.0f, 3.0f, 0.f}, { 0, 0}}, + {{ 0.0f, 0.0f, 0.f}, { 0, 0}}, + + {{ 2.0f, 3.0f, 0.f}, {32767, 32767}}, + {{ 3.0f, 0.0f, 0.f}, {0, 0}}, + }; + const DWORD exp_indices18[] = {0, 1, 2, 3, 4, 2}; + const DWORD exp_face_remap18[] = {0, 1}; + const DWORD exp_vertex_remap18[] = {0, 1, 2, 3, 4, -1}; + const DWORD exp_new_num_vertices18 = ARRAY_SIZE(exp_vertices18); + /* Test 19. Weld texture coordinates but as USHORT2N instead of D3DXVECTOR2. */ + const struct vertex_texcoord_ushort2n vertices19[] = + { + {{ 0.0f, 3.0f, 0.f}, { 0, 0}}, + {{ 2.0f, 3.0f, 0.f}, { 0, 0}}, + {{ 0.0f, 0.0f, 0.f}, { 0, 0}}, + + {{ 3.0f, 3.0f, 0.f}, {65535, 65535}}, + {{ 3.0f, 0.0f, 0.f}, {0, 0}}, + {{ 1.0f, 0.0f, 0.f}, {65534, 65534}}, + }; + const DWORD indices19[] = {0, 1, 2, 3, 4, 5}; + const DWORD attributes19[] = {0, 0}; + const UINT num_vertices19 = ARRAY_SIZE(vertices19); + const UINT num_faces19 = ARRAY_SIZE(indices19) / VERTS_PER_FACE; + DWORD flags19 = D3DXWELDEPSILONS_WELDPARTIALMATCHES; + const D3DXWELDEPSILONS epsilons19 = {1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, {65534.0f/65535.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f}, 0.0f, 0.0f, 0.0f}; + const DWORD adjacency19[] = {-1, 1, -1, -1, -1, 0}; + const struct vertex_texcoord_ushort2n exp_vertices19[] = + { + {{ 0.0f, 3.0f, 0.f}, { 0, 0}}, + {{ 2.0f, 3.0f, 0.f}, { 0, 0}}, + {{ 0.0f, 0.0f, 0.f}, { 0, 0}}, + + {{ 2.0f, 3.0f, 0.f}, {65535, 65535}}, + {{ 3.0f, 0.0f, 0.f}, {0, 0}}, + }; + const DWORD exp_indices19[] = {0, 1, 2, 3, 4, 2}; + const DWORD exp_face_remap19[] = {0, 1}; + const DWORD exp_vertex_remap19[] = {0, 1, 2, 3, 4, -1}; + const DWORD exp_new_num_vertices19 = ARRAY_SIZE(exp_vertices19); + /* Test 20. Weld normal as SHORT4 instead of D3DXVECTOR3. */ + const struct vertex_normal_short4 vertices20[] = + { + {{ 0.0f, 3.0f, 0.f}, {0, 0, 0, 0}}, + {{ 2.0f, 3.0f, 0.f}, {0, 0, 0, 0}}, + {{ 0.0f, 0.0f, 0.f}, {0, 0, 0, 0}}, + + {{ 3.0f, 3.0f, 0.f}, {32767, 32767, 32767, 32767}}, + {{ 3.0f, 0.0f, 0.f}, {0, 0, 0, 0}}, + {{ 1.0f, 0.0f, 0.f}, {32766, 32766, 32766, 32766}}, + }; + const DWORD indices20[] = {0, 1, 2, 3, 4, 5}; + const DWORD attributes20[] = {0, 0}; + const UINT num_vertices20 = ARRAY_SIZE(vertices20); + const UINT num_faces20 = ARRAY_SIZE(indices20) / VERTS_PER_FACE; + DWORD flags20 = D3DXWELDEPSILONS_WELDPARTIALMATCHES; + const D3DXWELDEPSILONS epsilons20 = {1.0f, 0.0f, 32766.0f, 0.0f, 0.0f, 0.0f, {0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f}, 0.0f, 0.0f, 0.0f}; + const DWORD adjacency20[] = {-1, 1, -1, -1, -1, 0}; + const struct vertex_normal_short4 exp_vertices20[] = + { + {{ 0.0f, 3.0f, 0.f}, {0, 0, 0, 0}}, + {{ 2.0f, 3.0f, 0.f}, {0, 0, 0, 0}}, + {{ 0.0f, 0.0f, 0.f}, {0, 0, 0, 0}}, + + {{ 2.0f, 3.0f, 0.f}, {32767, 32767, 32767, 32767}}, + {{ 3.0f, 0.0f, 0.f}, {0, 0, 0, 0}}, + }; + const DWORD exp_indices20[] = {0, 1, 2, 3, 4, 2}; + const DWORD exp_face_remap20[] = {0, 1}; + const DWORD exp_vertex_remap20[] = {0, 1, 2, 3, 4, -1}; + const DWORD exp_new_num_vertices20 = ARRAY_SIZE(exp_vertices20); + /* Test 21. Weld normal as SHORT4N instead of D3DXVECTOR3. */ + const struct vertex_normal_short4 vertices21[] = + { + {{ 0.0f, 3.0f, 0.f}, {0, 0, 0, 0}}, + {{ 2.0f, 3.0f, 0.f}, {0, 0, 0, 0}}, + {{ 0.0f, 0.0f, 0.f}, {0, 0, 0, 0}}, + + {{ 3.0f, 3.0f, 0.f}, {32767, 32767, 32767, 32767}}, + {{ 3.0f, 0.0f, 0.f}, {0, 0, 0, 0}}, + {{ 1.0f, 0.0f, 0.f}, {32766, 32766, 32766, 32766}}, + }; + const DWORD indices21[] = {0, 1, 2, 3, 4, 5}; + const DWORD attributes21[] = {0, 0}; + const UINT num_vertices21 = ARRAY_SIZE(vertices21); + const UINT num_faces21 = ARRAY_SIZE(indices21) / VERTS_PER_FACE; + DWORD flags21 = D3DXWELDEPSILONS_WELDPARTIALMATCHES; + const D3DXWELDEPSILONS epsilons21 = {1.0f, 0.0f, 32766.0f/32767.0f, 0.0f, 0.0f, 0.0f, {0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f}, 0.0f, 0.0f, 0.0f}; + const DWORD adjacency21[] = {-1, 1, -1, -1, -1, 0}; + const struct vertex_normal_short4 exp_vertices21[] = + { + {{ 0.0f, 3.0f, 0.f}, {0, 0, 0, 0}}, + {{ 2.0f, 3.0f, 0.f}, {0, 0, 0, 0}}, + {{ 0.0f, 0.0f, 0.f}, {0, 0, 0, 0}}, + + {{ 2.0f, 3.0f, 0.f}, {32767, 32767, 32767, 32767}}, + {{ 3.0f, 0.0f, 0.f}, {0, 0, 0, 0}}, + }; + const DWORD exp_indices21[] = {0, 1, 2, 3, 4, 2}; + const DWORD exp_face_remap21[] = {0, 1}; + const DWORD exp_vertex_remap21[] = {0, 1, 2, 3, 4, -1}; + const DWORD exp_new_num_vertices21 = ARRAY_SIZE(exp_vertices21); + /* Test 22. Weld normal as USHORT4N instead of D3DXVECTOR3. */ + const struct vertex_normal_short4 vertices22[] = + { + {{ 0.0f, 3.0f, 0.f}, {0, 0, 0, 0}}, + {{ 2.0f, 3.0f, 0.f}, {0, 0, 0, 0}}, + {{ 0.0f, 0.0f, 0.f}, {0, 0, 0, 0}}, + + {{ 3.0f, 3.0f, 0.f}, {65535, 65535, 65535, 65535}}, + {{ 3.0f, 0.0f, 0.f}, {0, 0, 0, 0}}, + {{ 1.0f, 0.0f, 0.f}, {65534, 65534, 65534, 65534}}, + }; + const DWORD indices22[] = {0, 1, 2, 3, 4, 5}; + const DWORD attributes22[] = {0, 0}; + const UINT num_vertices22 = ARRAY_SIZE(vertices22); + const UINT num_faces22 = ARRAY_SIZE(indices22) / VERTS_PER_FACE; + DWORD flags22 = D3DXWELDEPSILONS_WELDPARTIALMATCHES; + const D3DXWELDEPSILONS epsilons22 = {1.0f, 0.0f, 65534.0f/65535.0f, 0.0f, 0.0f, 0.0f, {0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f}, 0.0f, 0.0f, 0.0f}; + const DWORD adjacency22[] = {-1, 1, -1, -1, -1, 0}; + const struct vertex_normal_short4 exp_vertices22[] = + { + {{ 0.0f, 3.0f, 0.f}, {0, 0, 0, 0}}, + {{ 2.0f, 3.0f, 0.f}, {0, 0, 0, 0}}, + {{ 0.0f, 0.0f, 0.f}, {0, 0, 0, 0}}, + + {{ 2.0f, 3.0f, 0.f}, {65535, 65535, 65535, 65535}}, + {{ 3.0f, 0.0f, 0.f}, {0, 0, 0, 0}}, + }; + const DWORD exp_indices22[] = {0, 1, 2, 3, 4, 2}; + const DWORD exp_face_remap22[] = {0, 1}; + const DWORD exp_vertex_remap22[] = {0, 1, 2, 3, 4, -1}; + const DWORD exp_new_num_vertices22 = ARRAY_SIZE(exp_vertices22); + /* Test 23. Weld texture coordinates as FLOAT16_2. Similar to test 11, but + * with texture coordinates converted to float16 in hex. */ + const struct vertex_texcoord_float16_2 vertices23[] = + { + {{ 0.0f, 3.0f, 0.f}, {0x3c00, 0x3c00}}, /* {1.0f, 1.0f} */ + {{ 2.0f, 3.0f, 0.f}, {0x3800, 0x399a}}, /* {0.5f, 0.7f} */ + {{ 0.0f, 0.0f, 0.f}, {0xb266, 0xb4cd}}, /* {-0.2f, -0.3f} */ + + {{ 3.0f, 3.0f, 0.f}, {0x3266, 0x34cd}}, /* {0.2f, 0.3f} */ + {{ 3.0f, 0.0f, 0.f}, {0x3c00, 0x3c00}}, /* {1.0f, 1.0f} */ + {{ 1.0f, 0.0f, 0.f}, {0x2e66, 0x3266}}, /* {0.1f, 0.2f} */ + }; + const DWORD indices23[] = {0, 1, 2, 3, 4, 5}; + const DWORD attributes23[] = {0, 0}; + const UINT num_vertices23 = ARRAY_SIZE(vertices23); + const UINT num_faces23 = ARRAY_SIZE(indices23) / VERTS_PER_FACE; + DWORD flags23 = D3DXWELDEPSILONS_WELDPARTIALMATCHES; + const D3DXWELDEPSILONS epsilons23 = {1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, {0.41f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f}, 0.0f, 0.0f, 0.0f}; + const DWORD adjacency23[] = {-1, 1, -1, -1, -1, 0}; + const struct vertex_texcoord_float16_2 exp_vertices23[] = + { + {{ 0.0f, 3.0f, 0.f}, {0x3c00, 0x3c00}}, /* {1.0f, 1.0f} */ + {{ 2.0f, 3.0f, 0.f}, {0x3800, 0x399a}}, /* {0.5f, 0.7f} */ + {{ 0.0f, 0.0f, 0.f}, {0xb266, 0xb4cd}}, /* {-0.2f, -0.3f} */ + + {{ 3.0f, 0.0f, 0.f}, {0x3c00, 0x3c00}}, /* {1.0f, 1.0f} */ + {{ 0.0f, 0.0f, 0.f}, {0x2e66, 0x3266}}, /* {0.1f, 0.2f} */ + }; + const DWORD exp_indices23[] = {0, 1, 2, 1, 3, 4}; + const DWORD exp_face_remap23[] = {0, 1}; + const DWORD exp_vertex_remap23[] = {0, 1, 2, 4, 5, -1}; + const DWORD exp_new_num_vertices23 = ARRAY_SIZE(exp_vertices23); + /* Test 24. Weld texture coordinates as FLOAT16_4. Similar to test 24. */ + const struct vertex_texcoord_float16_4 vertices24[] = + { + {{ 0.0f, 3.0f, 0.f}, {0x3c00, 0x3c00, 0x3c00, 0x3c00}}, + {{ 2.0f, 3.0f, 0.f}, {0x3800, 0x399a, 0x3800, 0x399a}}, + {{ 0.0f, 0.0f, 0.f}, {0xb266, 0xb4cd, 0xb266, 0xb4cd}}, + + {{ 3.0f, 3.0f, 0.f}, {0x3266, 0x34cd, 0x3266, 0x34cd}}, + {{ 3.0f, 0.0f, 0.f}, {0x3c00, 0x3c00, 0x3c00, 0x3c00}}, + {{ 1.0f, 0.0f, 0.f}, {0x2e66, 0x3266, 0x2e66, 0x3266}}, + }; + const DWORD indices24[] = {0, 1, 2, 3, 4, 5}; + const DWORD attributes24[] = {0, 0}; + const UINT num_vertices24 = ARRAY_SIZE(vertices24); + const UINT num_faces24 = ARRAY_SIZE(indices24) / VERTS_PER_FACE; + DWORD flags24 = D3DXWELDEPSILONS_WELDPARTIALMATCHES; + const D3DXWELDEPSILONS epsilons24 = {1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, {0.41f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f}, 0.0f, 0.0f, 0.0f}; + const DWORD adjacency24[] = {-1, 1, -1, -1, -1, 0}; + const struct vertex_texcoord_float16_4 exp_vertices24[] = + { + {{ 0.0f, 3.0f, 0.f}, {0x3c00, 0x3c00, 0x3c00, 0x3c00}}, + {{ 2.0f, 3.0f, 0.f}, {0x3800, 0x399a, 0x3800, 0x399a}}, + {{ 0.0f, 0.0f, 0.f}, {0xb266, 0xb4cd, 0xb266, 0xb4cd}}, + + {{ 3.0f, 0.0f, 0.f}, {0x3c00, 0x3c00, 0x3c00, 0x3c00}}, + {{ 0.0f, 0.0f, 0.f}, {0x2e66, 0x3266, 0x2e66, 0x3266}}, + }; + const DWORD exp_indices24[] = {0, 1, 2, 1, 3, 4}; + const DWORD exp_face_remap24[] = {0, 1}; + const DWORD exp_vertex_remap24[] = {0, 1, 2, 4, 5, -1}; + const DWORD exp_new_num_vertices24 = ARRAY_SIZE(exp_vertices24); + /* Test 25. Weld texture coordinates with usage index 10 (TEXCOORD10). The + * usage index is capped at 7, so the epsilon for TEXCOORD7 is used instead. + */ + const struct vertex_texcoord vertices25[] = + { + {{ 0.0f, 3.0f, 0.f}, {1.0f, 1.0f}}, + {{ 2.0f, 3.0f, 0.f}, {0.5f, 0.7f}}, + {{ 0.0f, 0.0f, 0.f}, {-0.2f, -0.3f}}, + + {{ 3.0f, 3.0f, 0.f}, {0.2f, 0.3f}}, + {{ 3.0f, 0.0f, 0.f}, {1.0f, 1.0f}}, + {{ 1.0f, 0.0f, 0.f}, {0.1f, 0.2f}} + }; + const DWORD indices25[] = {0, 1, 2, 3, 4, 5}; + const DWORD attributes25[] = {0, 0}; + const UINT num_vertices25 = ARRAY_SIZE(vertices25); + const UINT num_faces25 = ARRAY_SIZE(indices25) / VERTS_PER_FACE; + DWORD flags25 = D3DXWELDEPSILONS_WELDPARTIALMATCHES; + const D3DXWELDEPSILONS epsilons25 = {1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, {0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.4f + FLT_EPSILON}, 0.0f, 0.0f, 0.0f}; + const DWORD adjacency25[] = {-1, 1, -1, -1, -1, 0}; + const struct vertex_texcoord exp_vertices25[] = + { + {{ 0.0f, 3.0f, 0.f}, {1.0f, 1.0f}}, + {{ 2.0f, 3.0f, 0.f}, {0.5f, 0.7f}}, + {{ 0.0f, 0.0f, 0.f}, {-0.2f, -0.3f}}, + + {{ 3.0f, 0.0f, 0.f}, {1.0f, 1.0f}}, + {{ 0.0f, 0.0f, 0.f}, {0.1f, 0.2f}}, + }; + const DWORD exp_indices25[] = {0, 1, 2, 1, 3, 4}; + const DWORD exp_face_remap25[] = {0, 1}; + const DWORD exp_vertex_remap25[] = {0, 1, 2, 4, 5, -1}; + const DWORD exp_new_num_vertices25 = ARRAY_SIZE(exp_vertices25); + /* Test 26. Weld color with usage index larger than 1. Shows that none of + * the epsilon values are used. */ + const struct vertex_color vertices26[] = + { + {{ 0.0f, 3.0f, 0.f}, 0xFFFFFFFF}, + {{ 2.0f, 3.0f, 0.f}, 0xFFFFFFFF}, + {{ 0.0f, 0.0f, 0.f}, 0xFFFFFFFF}, + + {{ 3.0f, 3.0f, 0.f}, 0x00000000}, + {{ 3.0f, 0.0f, 0.f}, 0xFFFFFFFF}, + {{ 1.0f, 0.0f, 0.f}, 0x01010101}, + }; + const DWORD indices26[] = {0, 1, 2, 3, 4, 5}; + const DWORD attributes26[] = {0, 0}; + const UINT num_vertices26 = ARRAY_SIZE(vertices26); + const UINT num_faces26 = ARRAY_SIZE(indices26) / VERTS_PER_FACE; + DWORD flags26 = D3DXWELDEPSILONS_WELDPARTIALMATCHES; + const D3DXWELDEPSILONS epsilons26 = {1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, {1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f}, 1.0f, 1.0f, 1.0f}; + const DWORD adjacency26[] = {-1, 1, -1, -1, -1, 0}; + const struct vertex_color exp_vertices26[] = + { + {{ 0.0f, 3.0f, 0.f}, 0xFFFFFFFF}, + {{ 2.0f, 3.0f, 0.f}, 0xFFFFFFFF}, + {{ 0.0f, 0.0f, 0.f}, 0xFFFFFFFF}, + + {{ 2.0f, 3.0f, 0.f}, 0x00000000}, + {{ 3.0f, 0.0f, 0.f}, 0xFFFFFFFF}, + {{ 0.0f, 0.0f, 0.f}, 0x01010101}, + }; + const DWORD exp_indices26[] = {0, 1, 2, 3, 4, 5}; + const DWORD exp_face_remap26[] = {0, 1}; + const DWORD exp_vertex_remap26[] = {0, 1, 2, 3, 4, 5}; + const DWORD exp_new_num_vertices26 = ARRAY_SIZE(exp_vertices26); + /* Test 27. Weld color with usage index 1 (specular). */ + /* Previously this test used float color values and index > 1 but that case + * appears to be effectively unhandled in native so the test gave + * inconsistent results. */ + const struct vertex_color vertices27[] = + { + {{ 0.0f, 3.0f, 0.0f}, 0x00000000}, + {{ 2.0f, 3.0f, 0.0f}, 0x10203040}, + {{ 0.0f, 0.0f, 0.0f}, 0x50607080}, + + {{ 3.0f, 3.0f, 0.0f}, 0x11213141}, + {{ 3.0f, 0.0f, 0.0f}, 0xffffffff}, + {{ 1.0f, 0.0f, 0.0f}, 0x51617181}, + }; + const DWORD indices27[] = {0, 1, 2, 3, 4, 5}; + const DWORD attributes27[] = {0, 0}; + const UINT num_vertices27 = ARRAY_SIZE(vertices27); + const UINT num_faces27 = ARRAY_SIZE(indices27) / VERTS_PER_FACE; + DWORD flags27 = D3DXWELDEPSILONS_WELDPARTIALMATCHES; + const D3DXWELDEPSILONS epsilons27 = + { + 1.1f, 0.0f, 0.0f, 0.0f, 2.0f / 255.0f, 0.0f, + {0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f}, 0.0f, 0.0f, 0.0f + }; + const DWORD adjacency27[] = {-1, 1, -1, -1, -1, 0}; + const struct vertex_color exp_vertices27[] = + { + {{ 0.0f, 3.0f, 0.0f}, 0x00000000}, + {{ 2.0f, 3.0f, 0.0f}, 0x10203040}, + {{ 0.0f, 0.0f, 0.0f}, 0x50607080}, + + {{ 3.0f, 0.0f, 0.0f}, 0xffffffff}, + }; + const DWORD exp_indices27[] = {0, 1, 2, 1, 3, 2}; + const DWORD exp_face_remap27[] = {0, 1}; + const DWORD exp_vertex_remap27[] = {0, 1, 2, 4, -1, -1}; + const DWORD exp_new_num_vertices27 = ARRAY_SIZE(exp_vertices27); + /* Test 28. Weld one normal with UDEC3. */ + const DWORD dword_udec3_zero = init_udec3_dword(0, 0, 0, 1); + const DWORD dword_udec3_1023 = init_udec3_dword(1023, 1023, 1023, 1); + const DWORD dword_udec3_1022 = init_udec3_dword(1022, 1022, 1022, 1); + const struct vertex_normal_udec3 vertices28[] = + { + {{ 0.0f, 3.0f, 0.f}, dword_udec3_zero}, + {{ 2.0f, 3.0f, 0.f}, dword_udec3_zero}, + {{ 0.0f, 0.0f, 0.f}, dword_udec3_zero}, + + {{ 3.0f, 3.0f, 0.f}, dword_udec3_1023}, + {{ 3.0f, 0.0f, 0.f}, dword_udec3_zero}, + {{ 1.0f, 0.0f, 0.f}, dword_udec3_1022}, + }; + const DWORD indices28[] = {0, 1, 2, 3, 4, 5}; + const DWORD attributes28[] = {0, 0}; + const UINT num_vertices28 = ARRAY_SIZE(vertices28); + const UINT num_faces28 = ARRAY_SIZE(indices28) / VERTS_PER_FACE; + DWORD flags28 = D3DXWELDEPSILONS_WELDPARTIALMATCHES; + const D3DXWELDEPSILONS epsilons28 = {1.0f, 0.0f, 1022.0f, 0.0f, 0.0f, 0.0f, {0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f}, 0.0f, 0.0f, 0.0f}; + const DWORD adjacency28[] = {-1, 1, -1, -1, -1, 0}; + const struct vertex_normal_udec3 exp_vertices28[] = + { + {{ 0.0f, 3.0f, 0.f}, dword_udec3_zero}, + {{ 2.0f, 3.0f, 0.f}, dword_udec3_zero}, + {{ 0.0f, 0.0f, 0.f}, dword_udec3_zero}, + + {{ 2.0f, 3.0f, 0.f}, dword_udec3_1023}, + {{ 3.0f, 0.0f, 0.f}, dword_udec3_zero}, + }; + const DWORD exp_indices28[] = {0, 1, 2, 3, 4, 2}; + const DWORD exp_face_remap28[] = {0, 1}; + const DWORD exp_vertex_remap28[] = {0, 1, 2, 3, 4, -1}; + const DWORD exp_new_num_vertices28 = ARRAY_SIZE(exp_vertices28); + /* Test 29. Weld one normal with DEC3N. */ + const DWORD dword_dec3n_zero = init_dec3n_dword(0, 0, 0, 1); + const DWORD dword_dec3n_511 = init_dec3n_dword(511, 511, 511, 1); + const DWORD dword_dec3n_510 = init_dec3n_dword(510, 510, 510, 1); + const struct vertex_normal_dec3n vertices29[] = + { + {{ 0.0f, 3.0f, 0.f}, dword_dec3n_zero}, + {{ 2.0f, 3.0f, 0.f}, dword_dec3n_zero}, + {{ 0.0f, 0.0f, 0.f}, dword_dec3n_zero}, + + {{ 3.0f, 3.0f, 0.f}, dword_dec3n_511}, + {{ 3.0f, 0.0f, 0.f}, dword_dec3n_zero}, + {{ 1.0f, 0.0f, 0.f}, dword_dec3n_510}, + }; + const DWORD indices29[] = {0, 1, 2, 3, 4, 5}; + const DWORD attributes29[] = {0, 0}; + const UINT num_vertices29 = ARRAY_SIZE(vertices29); + const UINT num_faces29 = ARRAY_SIZE(indices29) / VERTS_PER_FACE; + DWORD flags29 = D3DXWELDEPSILONS_WELDPARTIALMATCHES; + const D3DXWELDEPSILONS epsilons29 = {1.0f, 0.0f, 510.0f/511.0f, 0.0f, 0.0f, 0.0f, {0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, .0f}, 0.0f, 0.0f, 0.0f}; + const DWORD adjacency29[] = {-1, 1, -1, -1, -1, 0}; + const struct vertex_normal_dec3n exp_vertices29[] = + { + {{ 0.0f, 3.0f, 0.f}, dword_dec3n_zero}, + {{ 2.0f, 3.0f, 0.f}, dword_dec3n_zero}, + {{ 0.0f, 0.0f, 0.f}, dword_dec3n_zero}, + + {{ 2.0f, 3.0f, 0.f}, dword_dec3n_511}, + {{ 3.0f, 0.0f, 0.f}, dword_dec3n_zero}, + }; + const DWORD exp_indices29[] = {0, 1, 2, 3, 4, 2}; + const DWORD exp_face_remap29[] = {0, 1}; + const DWORD exp_vertex_remap29[] = {0, 1, 2, 3, 4, -1}; + const DWORD exp_new_num_vertices29 = ARRAY_SIZE(exp_vertices29); + /* All mesh data */ + DWORD *adjacency_out = NULL; + DWORD *face_remap = NULL; + ID3DXMesh *mesh = NULL; + ID3DXBuffer *vertex_remap = NULL; + struct + { + const BYTE *vertices; + const DWORD *indices; + const DWORD *attributes; + const DWORD num_vertices; + const DWORD num_faces; + const DWORD options; + D3DVERTEXELEMENT9 *declaration; + const UINT vertex_size; + const DWORD flags; + const D3DXWELDEPSILONS *epsilons; + const DWORD *adjacency; + const BYTE *exp_vertices; + const DWORD *exp_indices; + const DWORD *exp_face_remap; + const DWORD *exp_vertex_remap; + const DWORD exp_new_num_vertices; + } + tc[] = + { + { + (BYTE*)vertices0, + indices0, + attributes0, + num_vertices0, + num_faces0, + options, + declaration_normal, + vertex_size_normal, + flags0, + NULL, + adjacency0, + (BYTE*)exp_vertices0, + exp_indices0, + exp_face_remap0, + exp_vertex_remap0, + exp_new_num_vertices0 + }, + { + (BYTE*)vertices1, + indices1, + attributes1, + num_vertices1, + num_faces1, + options, + declaration_normal, + vertex_size_normal, + flags1, + NULL, + adjacency1, + (BYTE*)exp_vertices1, + exp_indices1, + exp_face_remap1, + exp_vertex_remap1, + exp_new_num_vertices1 + }, + { + (BYTE*)vertices2, + indices2, + attributes2, + num_vertices2, + num_faces2, + options, + declaration_normal, + vertex_size_normal, + flags2, + &epsilons2, + adjacency2, + (BYTE*)exp_vertices2, + exp_indices2, + exp_face_remap2, + exp_vertex_remap2, + exp_new_num_vertices2 + }, + { + (BYTE*)vertices3, + indices3, + attributes3, + num_vertices3, + num_faces3, + options, + declaration_normal, + vertex_size_normal, + flags3, + &epsilons3, + adjacency3, + (BYTE*)exp_vertices3, + exp_indices3, + exp_face_remap3, + exp_vertex_remap3, + exp_new_num_vertices3 + }, + { + (BYTE*)vertices4, + indices4, + attributes4, + num_vertices4, + num_faces4, + options, + declaration_normal, + vertex_size_normal, + flags4, + &epsilons4, + adjacency4, + (BYTE*)exp_vertices4, + exp_indices4, + exp_face_remap4, + exp_vertex_remap4, + exp_new_num_vertices4 + }, + /* Unusual ordering. */ + { + (BYTE*)vertices5, + indices5, + attributes5, + num_vertices5, + num_faces5, + options, + declaration_normal, + vertex_size_normal, + flags5, + NULL, + adjacency5, + (BYTE*)exp_vertices5, + exp_indices5, + exp_face_remap5, + exp_vertex_remap5, + exp_new_num_vertices5 + }, + { + (BYTE*)vertices6, + indices6, + attributes6, + num_vertices6, + num_faces6, + options, + declaration_normal, + vertex_size_normal, + flags6, + &epsilons6, + adjacency6, + (BYTE*)exp_vertices6, + exp_indices6, + exp_face_remap6, + exp_vertex_remap6, + exp_new_num_vertices6 + }, + { + (BYTE*)vertices6, + (DWORD*)indices6_16bit, + attributes6, + num_vertices6, + num_faces6, + options_16bit, + declaration_normal, + vertex_size_normal, + flags6, + &epsilons6, + adjacency6, + (BYTE*)exp_vertices6, + exp_indices6, + exp_face_remap6, + exp_vertex_remap6, + exp_new_num_vertices6 + }, + { + (BYTE*)vertices8, + indices8, + attributes8, + num_vertices8, + num_faces8, + options, + declaration_normal, + vertex_size_normal, + flags8, + &epsilons8, + adjacency8, + (BYTE*)exp_vertices8, + exp_indices8, + exp_face_remap8, + exp_vertex_remap8, + exp_new_num_vertices8 + }, + { + (BYTE*)vertices9, + indices9, + attributes9, + num_vertices9, + num_faces9, + options, + declaration_normal, + vertex_size_normal, + flags9, + &epsilons9, + adjacency9, + (BYTE*)exp_vertices9, + exp_indices9, + exp_face_remap9, + exp_vertex_remap9, + exp_new_num_vertices9 + }, + { + (BYTE*)vertices10, + indices10, + attributes10, + num_vertices10, + num_faces10, + options, + declaration_blendweight, + vertex_size_blendweight, + flags10, + &epsilons10, + adjacency10, + (BYTE*)exp_vertices10, + exp_indices10, + exp_face_remap10, + exp_vertex_remap10, + exp_new_num_vertices10 + }, + { + (BYTE*)vertices11, + indices11, + attributes11, + num_vertices11, + num_faces11, + options, + declaration_texcoord, + vertex_size_texcoord, + flags11, + &epsilons11, + adjacency11, + (BYTE*)exp_vertices11, + exp_indices11, + exp_face_remap11, + exp_vertex_remap11, + exp_new_num_vertices11 + }, + { + (BYTE*)vertices12, + indices12, + attributes12, + num_vertices12, + num_faces12, + options, + declaration_color, + vertex_size_color, + flags12, + &epsilons12, + adjacency12, + (BYTE*)exp_vertices12, + exp_indices12, + exp_face_remap12, + exp_vertex_remap12, + exp_new_num_vertices12 + }, + { + (BYTE*)vertices13, + indices13, + attributes13, + num_vertices13, + num_faces13, + options, + declaration_normal3, + vertex_size_normal, + flags13, + &epsilons13, + adjacency13, + (BYTE*)exp_vertices13, + exp_indices13, + exp_face_remap13, + exp_vertex_remap13, + exp_new_num_vertices13 + }, + { + (BYTE*)vertices14, + indices14, + attributes14, + num_vertices14, + num_faces14, + options, + declaration_color, + vertex_size_color, + flags14, + &epsilons14, + adjacency14, + (BYTE*)exp_vertices14, + exp_indices14, + exp_face_remap14, + exp_vertex_remap14, + exp_new_num_vertices14 + }, + { + (BYTE*)vertices15, + indices15, + attributes15, + num_vertices15, + num_faces15, + options, + declaration_color_ubyte4n, + vertex_size_color_ubyte4, /* UBYTE4 same size as UBYTE4N */ + flags15, + &epsilons15, + adjacency15, + (BYTE*)exp_vertices15, + exp_indices15, + exp_face_remap15, + exp_vertex_remap15, + exp_new_num_vertices15 + }, + { + (BYTE*)vertices16, + indices16, + attributes16, + num_vertices16, + num_faces16, + options, + declaration_color_ubyte4, + vertex_size_color_ubyte4, + flags16, + &epsilons16, + adjacency16, + (BYTE*)exp_vertices16, + exp_indices16, + exp_face_remap16, + exp_vertex_remap16, + exp_new_num_vertices16 + }, + { + (BYTE*)vertices17, + indices17, + attributes17, + num_vertices17, + num_faces17, + options, + declaration_texcoord_short2, + vertex_size_texcoord_short2, + flags17, + &epsilons17, + adjacency17, + (BYTE*)exp_vertices17, + exp_indices17, + exp_face_remap17, + exp_vertex_remap17, + exp_new_num_vertices17 + }, + { + (BYTE*)vertices18, + indices18, + attributes18, + num_vertices18, + num_faces18, + options, + declaration_texcoord_short2n, + vertex_size_texcoord_short2, /* SHORT2 same size as SHORT2N */ + flags18, + &epsilons18, + adjacency18, + (BYTE*)exp_vertices18, + exp_indices18, + exp_face_remap18, + exp_vertex_remap18, + exp_new_num_vertices18 + }, + { + (BYTE*)vertices19, + indices19, + attributes19, + num_vertices19, + num_faces19, + options, + declaration_texcoord_ushort2n, + vertex_size_texcoord_short2, /* SHORT2 same size as USHORT2N */ + flags19, + &epsilons19, + adjacency19, + (BYTE*)exp_vertices19, + exp_indices19, + exp_face_remap19, + exp_vertex_remap19, + exp_new_num_vertices19 + }, + { + (BYTE*)vertices20, + indices20, + attributes20, + num_vertices20, + num_faces20, + options, + declaration_normal_short4, + vertex_size_normal_short4, + flags20, + &epsilons20, + adjacency20, + (BYTE*)exp_vertices20, + exp_indices20, + exp_face_remap20, + exp_vertex_remap20, + exp_new_num_vertices20 + }, + { + (BYTE*)vertices21, + indices21, + attributes21, + num_vertices21, + num_faces21, + options, + declaration_normal_short4n, + vertex_size_normal_short4, /* SHORT4 same size as SHORT4N */ + flags21, + &epsilons21, + adjacency21, + (BYTE*)exp_vertices21, + exp_indices21, + exp_face_remap21, + exp_vertex_remap21, + exp_new_num_vertices21 + }, + { + (BYTE*)vertices22, + indices22, + attributes22, + num_vertices22, + num_faces22, + options, + declaration_normal_ushort4n, + vertex_size_normal_short4, /* SHORT4 same size as USHORT4N */ + flags22, + &epsilons22, + adjacency22, + (BYTE*)exp_vertices22, + exp_indices22, + exp_face_remap22, + exp_vertex_remap22, + exp_new_num_vertices22 + }, + { + (BYTE*)vertices23, + indices23, + attributes23, + num_vertices23, + num_faces23, + options, + declaration_texcoord_float16_2, + vertex_size_texcoord_float16_2, + flags23, + &epsilons23, + adjacency23, + (BYTE*)exp_vertices23, + exp_indices23, + exp_face_remap23, + exp_vertex_remap23, + exp_new_num_vertices23 + }, + { + (BYTE*)vertices24, + indices24, + attributes24, + num_vertices24, + num_faces24, + options, + declaration_texcoord_float16_4, + vertex_size_texcoord_float16_4, + flags24, + &epsilons24, + adjacency24, + (BYTE*)exp_vertices24, + exp_indices24, + exp_face_remap24, + exp_vertex_remap24, + exp_new_num_vertices24 + }, + { + (BYTE*)vertices25, + indices25, + attributes25, + num_vertices25, + num_faces25, + options, + declaration_texcoord10, + vertex_size_texcoord, + flags25, + &epsilons25, + adjacency25, + (BYTE*)exp_vertices25, + exp_indices25, + exp_face_remap25, + exp_vertex_remap25, + exp_new_num_vertices25 + }, + { + (BYTE*)vertices26, + indices26, + attributes26, + num_vertices26, + num_faces26, + options, + declaration_color2, + vertex_size_color, + flags26, + &epsilons26, + adjacency26, + (BYTE*)exp_vertices26, + exp_indices26, + exp_face_remap26, + exp_vertex_remap26, + exp_new_num_vertices26 + }, + { + (BYTE*)vertices27, + indices27, + attributes27, + num_vertices27, + num_faces27, + options, + declaration_color1, + vertex_size_color, + flags27, + &epsilons27, + adjacency27, + (BYTE*)exp_vertices27, + exp_indices27, + exp_face_remap27, + exp_vertex_remap27, + exp_new_num_vertices27 + }, + { + (BYTE*)vertices28, + indices28, + attributes28, + num_vertices28, + num_faces28, + options, + declaration_normal_udec3, + vertex_size_normal_udec3, + flags28, + &epsilons28, + adjacency28, + (BYTE*)exp_vertices28, + exp_indices28, + exp_face_remap28, + exp_vertex_remap28, + exp_new_num_vertices28 + }, + { + (BYTE*)vertices29, + indices29, + attributes29, + num_vertices29, + num_faces29, + options, + declaration_normal_dec3n, + vertex_size_normal_dec3n, + flags29, + &epsilons29, + adjacency29, + (BYTE*)exp_vertices29, + exp_indices29, + exp_face_remap29, + exp_vertex_remap29, + exp_new_num_vertices29 + } + }; +#ifdef __REACTOS__ +#undef up +#endif + + test_context = new_test_context(); + if (!test_context) + { + skip("Couldn't create test context\n"); + goto cleanup; + } + + for (i = 0; i < ARRAY_SIZE(tc); i++) + { + DWORD j; + DWORD *vertex_remap_ptr; + DWORD new_num_vertices; + + hr = init_test_mesh(tc[i].num_faces, tc[i].num_vertices, tc[i].options, + tc[i].declaration, test_context->device, &mesh, + tc[i].vertices, tc[i].vertex_size, + tc[i].indices, tc[i].attributes); + if (FAILED(hr)) + { + skip("Couldn't initialize test mesh %d.\n", i); + goto cleanup; + } + + /* Allocate out parameters */ + adjacency_out = HeapAlloc(GetProcessHeap(), 0, VERTS_PER_FACE * tc[i].num_faces * sizeof(*adjacency_out)); + if (!adjacency_out) + { + skip("Couldn't allocate adjacency_out array.\n"); + goto cleanup; + } + face_remap = HeapAlloc(GetProcessHeap(), 0, tc[i].num_faces * sizeof(*face_remap)); + if (!face_remap) + { + skip("Couldn't allocate face_remap array.\n"); + goto cleanup; + } + + hr = D3DXWeldVertices(mesh, tc[i].flags, tc[i].epsilons, tc[i].adjacency, + adjacency_out, face_remap, &vertex_remap); + ok(hr == D3D_OK, "Expected D3D_OK, got %#x\n", hr); + /* Check number of vertices*/ + new_num_vertices = mesh->lpVtbl->GetNumVertices(mesh); + ok(new_num_vertices == tc[i].exp_new_num_vertices, + "Mesh %d: new_num_vertices == %d, expected %d.\n", + i, new_num_vertices, tc[i].exp_new_num_vertices); + /* Check index buffer */ + if (tc[i].options & D3DXMESH_32BIT) + { + hr = mesh->lpVtbl->LockIndexBuffer(mesh, 0, (void**)&indices); + if (FAILED(hr)) + { + skip("Couldn't lock index buffer.\n"); + goto cleanup; + } + for (j = 0; j < VERTS_PER_FACE * tc[i].num_faces; j++) + { + ok(indices[j] == tc[i].exp_indices[j], + "Mesh %d: indices[%d] == %d, expected %d\n", + i, j, indices[j], tc[i].exp_indices[j]); + } + } + else + { + hr = mesh->lpVtbl->LockIndexBuffer(mesh, 0, (void**)&indices_16bit); + if (FAILED(hr)) + { + skip("Couldn't lock index buffer.\n"); + goto cleanup; + } + for (j = 0; j < VERTS_PER_FACE * tc[i].num_faces; j++) + { + ok(indices_16bit[j] == tc[i].exp_indices[j], + "Mesh %d: indices_16bit[%d] == %d, expected %d\n", + i, j, indices_16bit[j], tc[i].exp_indices[j]); + } + } + mesh->lpVtbl->UnlockIndexBuffer(mesh); + indices = NULL; + indices_16bit = NULL; + /* Check adjacency_out */ + for (j = 0; j < VERTS_PER_FACE * tc[i].num_faces; j++) + { + ok(adjacency_out[j] == tc[i].adjacency[j], + "Mesh %d: adjacency_out[%d] == %d, expected %d\n", + i, j, adjacency_out[j], tc[i].adjacency[j]); + } + /* Check face_remap */ + for (j = 0; j < tc[i].num_faces; j++) + { + ok(face_remap[j] == tc[i].exp_face_remap[j], + "Mesh %d: face_remap[%d] == %d, expected %d\n", + i, j, face_remap[j], tc[i].exp_face_remap[j]); + } + /* Check vertex_remap */ + vertex_remap_ptr = vertex_remap->lpVtbl->GetBufferPointer(vertex_remap); + for (j = 0; j < VERTS_PER_FACE * tc[i].num_faces; j++) + { + ok(vertex_remap_ptr[j] == tc[i].exp_vertex_remap[j], + "Mesh %d: vertex_remap_ptr[%d] == %d, expected %d\n", + i, j, vertex_remap_ptr[j], tc[i].exp_vertex_remap[j]); + } + /* Check vertex buffer */ + hr = mesh->lpVtbl->LockVertexBuffer(mesh, 0, (void*)&vertices); + if (FAILED(hr)) + { + skip("Couldn't lock vertex buffer.\n"); + goto cleanup; + } + /* Check contents of re-ordered vertex buffer */ + for (j = 0; j < tc[i].exp_new_num_vertices; j++) + { + int index = tc[i].vertex_size*j; + check_vertex_components(__LINE__, i, j, &vertices[index], &tc[i].exp_vertices[index], tc[i].declaration); + } + mesh->lpVtbl->UnlockVertexBuffer(mesh); + vertices = NULL; + + /* Free mesh and output data */ + HeapFree(GetProcessHeap(), 0, adjacency_out); + adjacency_out = NULL; + HeapFree(GetProcessHeap(), 0, face_remap); + face_remap = NULL; + vertex_remap->lpVtbl->Release(vertex_remap); + vertex_remap = NULL; + mesh->lpVtbl->Release(mesh); + mesh = NULL; + } + +cleanup: + HeapFree(GetProcessHeap(), 0, adjacency_out); + HeapFree(GetProcessHeap(), 0, face_remap); + if (indices) mesh->lpVtbl->UnlockIndexBuffer(mesh); + if (indices_16bit) mesh->lpVtbl->UnlockIndexBuffer(mesh); + if (mesh) mesh->lpVtbl->Release(mesh); + if (vertex_remap) vertex_remap->lpVtbl->Release(vertex_remap); + if (vertices) mesh->lpVtbl->UnlockVertexBuffer(mesh); + free_test_context(test_context); +} + +static void test_clone_mesh(void) +{ + HRESULT hr; + struct test_context *test_context = NULL; + const DWORD options = D3DXMESH_32BIT | D3DXMESH_SYSTEMMEM; + D3DVERTEXELEMENT9 declaration_pn[] = + { + {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0}, + {0, 12, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL, 0}, + D3DDECL_END() + }; + D3DVERTEXELEMENT9 declaration_pntc[] = + { + {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0}, + {0, 12, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL, 0}, + {0, 24, D3DDECLTYPE_FLOAT2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0}, + D3DDECL_END() + }; + D3DVERTEXELEMENT9 declaration_ptcn[] = + { + {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0}, + {0, 12, D3DDECLTYPE_FLOAT2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0}, + {0, 20, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL, 0}, + D3DDECL_END() + }; + D3DVERTEXELEMENT9 declaration_ptc[] = + { + {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0}, + {0, 12, D3DDECLTYPE_FLOAT2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0}, + D3DDECL_END() + }; + D3DVERTEXELEMENT9 declaration_ptc_float16_2[] = + { + {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0}, + {0, 12, D3DDECLTYPE_FLOAT16_2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0}, + D3DDECL_END() + }; + D3DVERTEXELEMENT9 declaration_ptc_float16_4[] = + { + {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0}, + {0, 12, D3DDECLTYPE_FLOAT16_4, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0}, + D3DDECL_END() + }; + D3DVERTEXELEMENT9 declaration_ptc_float1[] = + { + {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0}, + {0, 12, D3DDECLTYPE_FLOAT1, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0}, + D3DDECL_END() + }; + D3DVERTEXELEMENT9 declaration_ptc_float3[] = + { + {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0}, + {0, 12, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0}, + D3DDECL_END() + }; + D3DVERTEXELEMENT9 declaration_ptc_float4[] = + { + {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0}, + {0, 12, D3DDECLTYPE_FLOAT4, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0}, + D3DDECL_END() + }; + D3DVERTEXELEMENT9 declaration_ptc_d3dcolor[] = + { + {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0}, + {0, 12, D3DDECLTYPE_D3DCOLOR, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0}, + D3DDECL_END() + }; + D3DVERTEXELEMENT9 declaration_ptc_ubyte4[] = + { + {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0}, + {0, 12, D3DDECLTYPE_UBYTE4, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0}, + D3DDECL_END() + }; + D3DVERTEXELEMENT9 declaration_ptc_ubyte4n[] = + { + {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0}, + {0, 12, D3DDECLTYPE_UBYTE4N, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0}, + D3DDECL_END() + }; + D3DVERTEXELEMENT9 declaration_ptc_short2[] = + { + {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0}, + {0, 12, D3DDECLTYPE_SHORT2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0}, + D3DDECL_END() + }; + D3DVERTEXELEMENT9 declaration_ptc_short4[] = + { + {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0}, + {0, 12, D3DDECLTYPE_SHORT4, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0}, + D3DDECL_END() + }; + D3DVERTEXELEMENT9 declaration_ptc_short2n[] = + { + {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0}, + {0, 12, D3DDECLTYPE_SHORT2N, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0}, + D3DDECL_END() + }; + D3DVERTEXELEMENT9 declaration_ptc_short4n[] = + { + {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0}, + {0, 12, D3DDECLTYPE_SHORT4N, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0}, + D3DDECL_END() + }; + D3DVERTEXELEMENT9 declaration_ptc_ushort2n[] = + { + {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0}, + {0, 12, D3DDECLTYPE_USHORT2N, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0}, + D3DDECL_END() + }; + D3DVERTEXELEMENT9 declaration_ptc_ushort4n[] = + { + {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0}, + {0, 12, D3DDECLTYPE_USHORT4N, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0}, + D3DDECL_END() + }; + D3DVERTEXELEMENT9 declaration_ptc_float16_2_partialu[] = + { + {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0}, + {0, 12, D3DDECLTYPE_FLOAT16_2, D3DDECLMETHOD_PARTIALU, D3DDECLUSAGE_TEXCOORD, 0}, + D3DDECL_END() + }; + D3DVERTEXELEMENT9 declaration_pntc1[] = + { + {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0}, + {0, 12, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL, 0}, + {0, 24, D3DDECLTYPE_FLOAT2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 1}, + D3DDECL_END() + }; + const unsigned int VERTS_PER_FACE = 3; + BYTE *vertices = NULL; + INT i; + struct vertex_pn + { + D3DXVECTOR3 position; + D3DXVECTOR3 normal; + }; + struct vertex_pntc + { + D3DXVECTOR3 position; + D3DXVECTOR3 normal; + D3DXVECTOR2 texcoords; + }; + struct vertex_ptcn + { + D3DXVECTOR3 position; + D3DXVECTOR2 texcoords; + D3DXVECTOR3 normal; + }; + struct vertex_ptc + { + D3DXVECTOR3 position; + D3DXVECTOR2 texcoords; + }; + struct vertex_ptc_float16_2 + { + D3DXVECTOR3 position; + WORD texcoords[2]; /* float16_2 */ + }; + struct vertex_ptc_float16_4 + { + D3DXVECTOR3 position; + WORD texcoords[4]; /* float16_4 */ + }; + struct vertex_ptc_float1 + { + D3DXVECTOR3 position; + FLOAT texcoords; + }; + struct vertex_ptc_float3 + { + D3DXVECTOR3 position; + FLOAT texcoords[3]; + }; + struct vertex_ptc_float4 + { + D3DXVECTOR3 position; + FLOAT texcoords[4]; + }; + struct vertex_ptc_d3dcolor + { + D3DXVECTOR3 position; + BYTE texcoords[4]; + }; + struct vertex_ptc_ubyte4 + { + D3DXVECTOR3 position; + BYTE texcoords[4]; + }; + struct vertex_ptc_ubyte4n + { + D3DXVECTOR3 position; + BYTE texcoords[4]; + }; + struct vertex_ptc_short2 + { + D3DXVECTOR3 position; + SHORT texcoords[2]; + }; + struct vertex_ptc_short4 + { + D3DXVECTOR3 position; + SHORT texcoords[4]; + }; + struct vertex_ptc_ushort2n + { + D3DXVECTOR3 position; + USHORT texcoords[2]; + }; + struct vertex_ptc_ushort4n + { + D3DXVECTOR3 position; + USHORT texcoords[4]; + }; + struct vertex_ptc_udec3 + { + D3DXVECTOR3 position; + DWORD texcoords; + }; + struct vertex_ptc_dec3n + { + D3DXVECTOR3 position; + DWORD texcoords; + }; +#ifndef __REACTOS__ + D3DXVECTOR3 up = {0.0f, 0.0f, 1.0f}; + D3DXVECTOR2 zero_vec2 = {0.0f, 0.0f}; +#else +#define up {0.0f, 0.0f, 1.0f} +#define zero_vec2 {0.0f, 0.0f} +#endif + /* Test 0. Check that a mesh can be cloned if the new declaration is the + * same as the one used to create the mesh. + * + * 0--1 3 + * | / /| + * |/ / | + * 2 5--4 + */ + const struct vertex_pn vertices0[] = + { + {{ 0.0f, 3.0f, 0.f}, up}, + {{ 2.0f, 3.0f, 0.f}, up}, + {{ 0.0f, 0.0f, 0.f}, up}, + + {{ 3.0f, 3.0f, 0.f}, up}, + {{ 3.0f, 0.0f, 0.f}, up}, + {{ 1.0f, 0.0f, 0.f}, up}, + }; + const UINT num_vertices0 = ARRAY_SIZE(vertices0); + const UINT num_faces0 = ARRAY_SIZE(vertices0) / VERTS_PER_FACE; + const UINT vertex_size0 = sizeof(*vertices0); + /* Test 1. Check that 16-bit indices are handled. */ + const DWORD options_16bit = D3DXMESH_SYSTEMMEM; + /* Test 2. Check that the size of each vertex is increased and the data + * moved if the new declaration adds an element after the original elements. + */ + const struct vertex_pntc exp_vertices2[] = + { + {{ 0.0f, 3.0f, 0.f}, up, zero_vec2}, + {{ 2.0f, 3.0f, 0.f}, up, zero_vec2}, + {{ 0.0f, 0.0f, 0.f}, up, zero_vec2}, + + {{ 3.0f, 3.0f, 0.f}, up, zero_vec2}, + {{ 3.0f, 0.0f, 0.f}, up, zero_vec2}, + {{ 1.0f, 0.0f, 0.f}, up, zero_vec2}, + }; + const UINT exp_vertex_size2 = sizeof(*exp_vertices2); + /* Test 3. Check that the size of each vertex is increased and the data + * moved if the new declaration adds an element between the original + * elements. + */ + const struct vertex_ptcn exp_vertices3[] = + { + {{ 0.0f, 3.0f, 0.f}, zero_vec2, up}, + {{ 2.0f, 3.0f, 0.f}, zero_vec2, up}, + {{ 0.0f, 0.0f, 0.f}, zero_vec2, up}, + + {{ 3.0f, 3.0f, 0.f}, zero_vec2, up}, + {{ 3.0f, 0.0f, 0.f}, zero_vec2, up}, + {{ 1.0f, 0.0f, 0.f}, zero_vec2, up}, + }; + const UINT exp_vertex_size3 = sizeof(*exp_vertices3); + /* Test 4. Test that data types can be converted, e.g. FLOAT2 to FLOAT16_2. */ + const struct vertex_ptc vertices4[] = + { + {{ 0.0f, 3.0f, 0.f}, { 1.0f, 1.0f}}, + {{ 2.0f, 3.0f, 0.f}, { 0.5f, 0.7f}}, + {{ 0.0f, 0.0f, 0.f}, {-0.2f, -0.3f}}, + + {{ 3.0f, 3.0f, 0.f}, { 0.2f, 0.3f}}, + {{ 3.0f, 0.0f, 0.f}, { 1.0f, 1.0f}}, + {{ 1.0f, 0.0f, 0.f}, { 0.1f, 0.2f}}, + }; + const UINT num_vertices4 = ARRAY_SIZE(vertices4); + const UINT num_faces4 = ARRAY_SIZE(vertices4) / VERTS_PER_FACE; + const UINT vertex_size4 = sizeof(*vertices4); + const struct vertex_ptc_float16_2 exp_vertices4[] = + { + {{ 0.0f, 3.0f, 0.f}, {0x3c00, 0x3c00}}, /* {1.0f, 1.0f} */ + {{ 2.0f, 3.0f, 0.f}, {0x3800, 0x399a}}, /* {0.5f, 0.7f} */ + {{ 0.0f, 0.0f, 0.f}, {0xb266, 0xb4cd}}, /* {-0.2f, -0.3f} */ + + {{ 3.0f, 3.0f, 0.f}, {0x3266, 0x34cd}}, /* {0.2f, 0.3f} */ + {{ 3.0f, 0.0f, 0.f}, {0x3c00, 0x3c00}}, /* {1.0f, 1.0f} */ + {{ 1.0f, 0.0f, 0.f}, {0x2e66, 0x3266}}, /* {0.1f, 0.2f} */ + }; + const UINT exp_vertex_size4 = sizeof(*exp_vertices4); + /* Test 5. Convert FLOAT2 to FLOAT16_4. */ + const struct vertex_ptc vertices5[] = + { + {{ 0.0f, 3.0f, 0.f}, { 1.0f, 1.0f}}, + {{ 2.0f, 3.0f, 0.f}, { 0.5f, 0.7f}}, + {{ 0.0f, 0.0f, 0.f}, {-0.2f, -0.3f}}, + + {{ 3.0f, 3.0f, 0.f}, { 0.2f, 0.3f}}, + {{ 3.0f, 0.0f, 0.f}, { 1.0f, 1.0f}}, + {{ 1.0f, 0.0f, 0.f}, { 0.1f, 0.2f}}, + }; + const UINT num_vertices5 = ARRAY_SIZE(vertices5); + const UINT num_faces5 = ARRAY_SIZE(vertices5) / VERTS_PER_FACE; + const UINT vertex_size5 = sizeof(*vertices5); + const struct vertex_ptc_float16_4 exp_vertices5[] = + { + {{ 0.0f, 3.0f, 0.f}, {0x3c00, 0x3c00, 0, 0x3c00}}, /* {1.0f, 1.0f, 0.0f, 1.0f} */ + {{ 2.0f, 3.0f, 0.f}, {0x3800, 0x399a, 0, 0x3c00}}, /* {0.5f, 0.7f, 0.0f, 1.0f} */ + {{ 0.0f, 0.0f, 0.f}, {0xb266, 0xb4cd, 0, 0x3c00}}, /* {-0.2f, -0.3f, 0.0f, 1.0f} */ + + {{ 3.0f, 3.0f, 0.f}, {0x3266, 0x34cd, 0, 0x3c00}}, /* {0.2f, 0.3f, 0.0f, 1.0f} */ + {{ 3.0f, 0.0f, 0.f}, {0x3c00, 0x3c00, 0, 0x3c00}}, /* {1.0f, 1.0f, 0.0f, 1.0f} */ + {{ 1.0f, 0.0f, 0.f}, {0x2e66, 0x3266, 0, 0x3c00}}, /* {0.1f, 0.2f, 0.0f, 1.0f} */ + }; + const UINT exp_vertex_size5 = sizeof(*exp_vertices5); + /* Test 6. Convert FLOAT2 to FLOAT1. */ + const struct vertex_ptc vertices6[] = + { + {{ 0.0f, 3.0f, 0.f}, { 1.0f, 1.0f}}, + {{ 2.0f, 3.0f, 0.f}, { 0.5f, 0.7f}}, + {{ 0.0f, 0.0f, 0.f}, {-0.2f, -0.3f}}, + + {{ 3.0f, 3.0f, 0.f}, { 0.2f, 0.3f}}, + {{ 3.0f, 0.0f, 0.f}, { 1.0f, 1.0f}}, + {{ 1.0f, 0.0f, 0.f}, { 0.1f, 0.2f}}, + }; + const UINT num_vertices6 = ARRAY_SIZE(vertices6); + const UINT num_faces6 = ARRAY_SIZE(vertices6) / VERTS_PER_FACE; + const UINT vertex_size6 = sizeof(*vertices6); + const struct vertex_ptc_float1 exp_vertices6[] = + { + {{ 0.0f, 3.0f, 0.f}, 1.0f}, + {{ 2.0f, 3.0f, 0.f}, 0.5f}, + {{ 0.0f, 0.0f, 0.f}, -0.2f}, + + {{ 3.0f, 3.0f, 0.f}, 0.2f}, + {{ 3.0f, 0.0f, 0.f}, 1.0f}, + {{ 1.0f, 0.0f, 0.f}, 0.1f}, + }; + const UINT exp_vertex_size6 = sizeof(*exp_vertices6); + /* Test 7. Convert FLOAT2 to FLOAT3. */ + const struct vertex_ptc vertices7[] = + { + {{ 0.0f, 3.0f, 0.f}, { 1.0f, 1.0f}}, + {{ 2.0f, 3.0f, 0.f}, { 0.5f, 0.7f}}, + {{ 0.0f, 0.0f, 0.f}, {-0.2f, -0.3f}}, + + {{ 3.0f, 3.0f, 0.f}, { 0.2f, 0.3f}}, + {{ 3.0f, 0.0f, 0.f}, { 1.0f, 1.0f}}, + {{ 1.0f, 0.0f, 0.f}, { 0.1f, 0.2f}}, + }; + const UINT num_vertices7 = ARRAY_SIZE(vertices7); + const UINT num_faces7 = ARRAY_SIZE(vertices7) / VERTS_PER_FACE; + const UINT vertex_size7 = sizeof(*vertices7); + const struct vertex_ptc_float3 exp_vertices7[] = + { + {{ 0.0f, 3.0f, 0.f}, { 1.0f, 1.0f, 0.0f}}, + {{ 2.0f, 3.0f, 0.f}, { 0.5f, 0.7f, 0.0f}}, + {{ 0.0f, 0.0f, 0.f}, {-0.2f, -0.3f, 0.0f}}, + + {{ 3.0f, 3.0f, 0.f}, { 0.2f, 0.3f, 0.0f}}, + {{ 3.0f, 0.0f, 0.f}, { 1.0f, 1.0f, 0.0f}}, + {{ 1.0f, 0.0f, 0.f}, { 0.1f, 0.2f, 0.0f}}, + }; + const UINT exp_vertex_size7 = sizeof(*exp_vertices7); + /* Test 8. Convert FLOAT2 to FLOAT4. */ + const struct vertex_ptc vertices8[] = + { + {{ 0.0f, 3.0f, 0.f}, { 1.0f, 1.0f}}, + {{ 2.0f, 3.0f, 0.f}, { 0.5f, 0.7f}}, + {{ 0.0f, 0.0f, 0.f}, {-0.2f, -0.3f}}, + + {{ 3.0f, 3.0f, 0.f}, { 0.2f, 0.3f}}, + {{ 3.0f, 0.0f, 0.f}, { 1.0f, 1.0f}}, + {{ 1.0f, 0.0f, 0.f}, { 0.1f, 0.2f}}, + }; + const UINT num_vertices8 = ARRAY_SIZE(vertices8); + const UINT num_faces8 = ARRAY_SIZE(vertices8) / VERTS_PER_FACE; + const UINT vertex_size8 = sizeof(*vertices8); + const struct vertex_ptc_float4 exp_vertices8[] = + { + {{ 0.0f, 3.0f, 0.f}, { 1.0f, 1.0f, 0.0f, 1.0f}}, + {{ 2.0f, 3.0f, 0.f}, { 0.5f, 0.7f, 0.0f, 1.0f}}, + {{ 0.0f, 0.0f, 0.f}, {-0.2f, -0.3f, 0.0f, 1.0f}}, + + {{ 3.0f, 3.0f, 0.f}, { 0.2f, 0.3f, 0.0f, 1.0f}}, + {{ 3.0f, 0.0f, 0.f}, { 1.0f, 1.0f, 0.0f, 1.0f}}, + {{ 1.0f, 0.0f, 0.f}, { 0.1f, 0.2f, 0.0f, 1.0f}}, + }; + const UINT exp_vertex_size8 = sizeof(*exp_vertices8); + /* Test 9. Convert FLOAT2 to D3DCOLOR. */ + const struct vertex_ptc vertices9[] = + { + {{ 0.0f, 3.0f, 0.f}, { 1.0f, 1.0f}}, + {{ 2.0f, 3.0f, 0.f}, { 0.5f, 0.7f}}, + {{ 0.0f, 0.0f, 0.f}, {-0.4f, -0.6f}}, + + {{ 3.0f, 3.0f, 0.f}, { 0.2f, 0.3f}}, + {{ 3.0f, 0.0f, 0.f}, { 2.0f, 256.0f}}, + {{ 1.0f, 0.0f, 0.f}, { 0.11f, 0.2f}}, + }; + const UINT num_vertices9 = ARRAY_SIZE(vertices9); + const UINT num_faces9 = ARRAY_SIZE(vertices9) / VERTS_PER_FACE; + const UINT vertex_size9 = sizeof(*vertices9); + const struct vertex_ptc_d3dcolor exp_vertices9[] = + { + {{ 0.0f, 3.0f, 0.f}, {0, 255, 255, 255}}, + {{ 2.0f, 3.0f, 0.f}, {0, 179, 128, 255}}, + {{ 0.0f, 0.0f, 0.f}, {0, 0, 0, 255}}, + + {{ 3.0f, 3.0f, 0.f}, {0, 77, 51, 255}}, + {{ 3.0f, 0.0f, 0.f}, {0, 255, 255, 255}}, + {{ 1.0f, 0.0f, 0.f}, {0, 51, 28, 255}}, + }; + const UINT exp_vertex_size9 = sizeof(*exp_vertices9); + /* Test 10. Convert FLOAT2 to UBYTE4. */ + const struct vertex_ptc vertices10[] = + { + {{ 0.0f, 3.0f, 0.f}, { 0.0f, 1.0f}}, + {{ 2.0f, 3.0f, 0.f}, { 2.0f, 3.0f}}, + {{ 0.0f, 0.0f, 0.f}, { 254.0f, 255.0f}}, + + {{ 3.0f, 3.0f, 0.f}, { 256.0f, 257.0f}}, + {{ 3.0f, 0.0f, 0.f}, { 1.4f, 1.5f}}, + {{ 1.0f, 0.0f, 0.f}, {-4.0f, -5.0f}}, + }; + const UINT num_vertices10 = ARRAY_SIZE(vertices10); + const UINT num_faces10 = ARRAY_SIZE(vertices10) / VERTS_PER_FACE; + const UINT vertex_size10 = sizeof(*vertices10); + const struct vertex_ptc_ubyte4 exp_vertices10[] = + { + {{ 0.0f, 3.0f, 0.f}, {0, 1, 0, 1}}, + {{ 2.0f, 3.0f, 0.f}, {2, 3, 0, 1}}, + {{ 0.0f, 0.0f, 0.f}, {254, 255, 0, 1}}, + + {{ 3.0f, 3.0f, 0.f}, {0, 1, 0, 1}}, + {{ 3.0f, 0.0f, 0.f}, {1, 2, 0, 1}}, + {{ 1.0f, 0.0f, 0.f}, {0, 0, 0, 1}}, + }; + const UINT exp_vertex_size10 = sizeof(*exp_vertices10); + /* Test 11. Convert FLOAT2 to SHORT2. */ + const struct vertex_ptc vertices11[] = + { + {{ 0.0f, 3.0f, 0.f}, { 1.0f, -1.0f}}, + {{ 2.0f, 3.0f, 0.f}, { 0.4f, 0.5f}}, + {{ 0.0f, 0.0f, 0.f}, {-0.5f, -5.0f}}, + + {{ 3.0f, 3.0f, 0.f}, {SHRT_MAX, SHRT_MIN}}, + {{ 3.0f, 0.0f, 0.f}, {SHRT_MAX + 1.0f, SHRT_MIN - 1.0f}}, + {{ 1.0f, 0.0f, 0.f}, {SHRT_MAX + 2.0f, SHRT_MIN - 2.0f}}, + + {{ 4.0f, 3.0f, 0.f}, {2 * SHRT_MAX, 2 * SHRT_MIN}}, + {{ 6.0f, 0.0f, 0.f}, {3 * SHRT_MAX, 3 * SHRT_MIN}}, + {{ 4.0f, 0.0f, 0.f}, {4 * SHRT_MAX, 4 * SHRT_MIN}}, + }; + const UINT num_vertices11 = ARRAY_SIZE(vertices11); + const UINT num_faces11 = ARRAY_SIZE(vertices11) / VERTS_PER_FACE; + const UINT vertex_size11 = sizeof(*vertices11); + const struct vertex_ptc_short2 exp_vertices11[] = + { + {{ 0.0f, 3.0f, 0.f}, {1, 0}}, + {{ 2.0f, 3.0f, 0.f}, {0, 1}}, + {{ 0.0f, 0.0f, 0.f}, {0, -4}}, + + {{ 3.0f, 3.0f, 0.f}, {SHRT_MAX, SHRT_MIN + 1}}, + {{ 3.0f, 0.0f, 0.f}, {SHRT_MIN, SHRT_MIN}}, + {{ 1.0f, 0.0f, 0.f}, {SHRT_MIN + 1, SHRT_MAX}}, + + {{ 4.0f, 3.0f, 0.f}, {-2, 1}}, + {{ 6.0f, 0.0f, 0.f}, {32765, -32767}}, + {{ 4.0f, 0.0f, 0.f}, {-4, 1}}, + }; + const UINT exp_vertex_size11 = sizeof(*exp_vertices11); + /* Test 12. Convert FLOAT2 to SHORT4. */ + const struct vertex_ptc vertices12[] = + { + {{ 0.0f, 3.0f, 0.f}, { 1.0f, -1.0f}}, + {{ 2.0f, 3.0f, 0.f}, { 0.4f, 0.5f}}, + {{ 0.0f, 0.0f, 0.f}, {-0.5f, -5.0f}}, + + {{ 3.0f, 3.0f, 0.f}, {SHRT_MAX, SHRT_MIN}}, + {{ 3.0f, 0.0f, 0.f}, {SHRT_MAX + 1.0f, SHRT_MIN - 1.0f}}, + {{ 1.0f, 0.0f, 0.f}, {SHRT_MAX + 2.0f, SHRT_MIN - 2.0f}}, + + {{ 4.0f, 3.0f, 0.f}, {2 * SHRT_MAX, 2 * SHRT_MIN}}, + {{ 6.0f, 0.0f, 0.f}, {3 * SHRT_MAX, 3 * SHRT_MIN}}, + {{ 4.0f, 0.0f, 0.f}, {4 * SHRT_MAX, 4 * SHRT_MIN}}, + }; + const UINT num_vertices12 = ARRAY_SIZE(vertices12); + const UINT num_faces12 = ARRAY_SIZE(vertices12) / VERTS_PER_FACE; + const UINT vertex_size12 = sizeof(*vertices12); + const struct vertex_ptc_short4 exp_vertices12[] = + { + {{ 0.0f, 3.0f, 0.f}, {1, 0, 0, 1}}, + {{ 2.0f, 3.0f, 0.f}, {0, 1, 0, 1}}, + {{ 0.0f, 0.0f, 0.f}, {0, -4, 0, 1}}, + + {{ 3.0f, 3.0f, 0.f}, {SHRT_MAX, SHRT_MIN + 1, 0, 1}}, + {{ 3.0f, 0.0f, 0.f}, {SHRT_MIN, SHRT_MIN, 0, 1}}, + {{ 1.0f, 0.0f, 0.f}, {SHRT_MIN + 1, SHRT_MAX, 0, 1}}, + + {{ 4.0f, 3.0f, 0.f}, {-2, 1, 0, 1}}, + {{ 6.0f, 0.0f, 0.f}, {32765, -32767, 0, 1}}, + {{ 4.0f, 0.0f, 0.f}, {-4, 1, 0, 1}}, + }; + const UINT exp_vertex_size12 = sizeof(*exp_vertices12); + /* Test 13. Convert FLOAT2 to UBYTE4N. */ + const struct vertex_ptc vertices13[] = + { + {{ 0.0f, 3.0f, 0.f}, { 1.0f, 2.0f}}, + {{ 2.0f, 3.0f, 0.f}, { 0.5f, 0.7f}}, + {{ 0.0f, 0.0f, 0.f}, {-0.4f, -0.5f}}, + + {{ 3.0f, 3.0f, 0.f}, {-0.6f, -1.0f}}, + {{ 3.0f, 0.0f, 0.f}, {UCHAR_MAX, UCHAR_MAX + 1}}, + {{ 1.0f, 0.0f, 0.f}, {2 * UCHAR_MAX, -UCHAR_MAX}}, + }; + const UINT num_vertices13 = ARRAY_SIZE(vertices13); + const UINT num_faces13 = ARRAY_SIZE(vertices13) / VERTS_PER_FACE; + const UINT vertex_size13 = sizeof(*vertices13); + const struct vertex_ptc_ubyte4n exp_vertices13[] = + { + {{ 0.0f, 3.0f, 0.f}, {255, 255, 0, 255}}, + {{ 2.0f, 3.0f, 0.f}, {128, 179, 0, 255}}, + {{ 0.0f, 0.0f, 0.f}, {0, 0, 0, 255}}, + + {{ 3.0f, 3.0f, 0.f}, {0, 0, 0, 255}}, + {{ 3.0f, 0.0f, 0.f}, {255, 255, 0, 255}}, + {{ 1.0f, 0.0f, 0.f}, {255, 0, 0, 255}}, + }; + const UINT exp_vertex_size13 = sizeof(*exp_vertices13); + /* Test 14. Convert FLOAT2 to SHORT2N. */ + const struct vertex_ptc vertices14[] = + { + {{ 0.0f, 3.0f, 0.f}, {1.0f, 2.0f}}, + {{ 2.0f, 3.0f, 0.f}, {0.4f, 0.5f}}, + {{ 0.0f, 0.0f, 0.f}, {0.6f, -1.0f}}, + + {{ 3.0f, 3.0f, 0.f}, {-0.4f, -0.5f}}, + {{ 3.0f, 0.0f, 0.f}, {-0.9f, -0.99997}}, + {{ 1.0f, 0.0f, 0.f}, {SHRT_MAX, SHRT_MIN}}, + }; + const UINT num_vertices14 = ARRAY_SIZE(vertices14); + const UINT num_faces14 = ARRAY_SIZE(vertices14) / VERTS_PER_FACE; + const UINT vertex_size14 = sizeof(*vertices14); + const struct vertex_ptc_short2 exp_vertices14[] = + { + {{ 0.0f, 3.0f, 0.f}, {SHRT_MAX, SHRT_MAX}}, + {{ 2.0f, 3.0f, 0.f}, {13107, 16384}}, + {{ 0.0f, 0.0f, 0.f}, {19660, SHRT_MIN + 2}}, + + {{ 3.0f, 3.0f, 0.f}, {-13106, -16383}}, + {{ 3.0f, 0.0f, 0.f}, {-29489, SHRT_MIN + 3}}, + {{ 1.0f, 0.0f, 0.f}, {SHRT_MAX, SHRT_MIN + 2}}, + }; + const UINT exp_vertex_size14 = sizeof(*exp_vertices14); + /* Test 15. Convert FLOAT2 to SHORT4N. */ + const struct vertex_ptc vertices15[] = + { + {{ 0.0f, 3.0f, 0.f}, {1.0f, 2.0f}}, + {{ 2.0f, 3.0f, 0.f}, {0.4f, 0.5f}}, + {{ 0.0f, 0.0f, 0.f}, {0.6f, -1.0f}}, + + {{ 3.0f, 3.0f, 0.f}, {-0.4f, -0.5f}}, + {{ 3.0f, 0.0f, 0.f}, {-0.9f, -0.99997}}, + {{ 1.0f, 0.0f, 0.f}, {SHRT_MAX, SHRT_MIN}}, + }; + const UINT num_vertices15 = ARRAY_SIZE(vertices15); + const UINT num_faces15 = ARRAY_SIZE(vertices15) / VERTS_PER_FACE; + const UINT vertex_size15 = sizeof(*vertices15); + const struct vertex_ptc_short4 exp_vertices15[] = + { + {{ 0.0f, 3.0f, 0.f}, {SHRT_MAX, SHRT_MAX, 0, SHRT_MAX}}, + {{ 2.0f, 3.0f, 0.f}, {13107, 16384, 0, SHRT_MAX}}, + {{ 0.0f, 0.0f, 0.f}, {19660, SHRT_MIN + 2, 0, SHRT_MAX}}, + + {{ 3.0f, 3.0f, 0.f}, {-13106, -16383, 0, SHRT_MAX}}, + {{ 3.0f, 0.0f, 0.f}, {-29489, SHRT_MIN + 3, 0, SHRT_MAX}}, + {{ 1.0f, 0.0f, 0.f}, {SHRT_MAX, SHRT_MIN + 2, 0, SHRT_MAX}}, + }; + const UINT exp_vertex_size15 = sizeof(*exp_vertices15); + /* Test 16. Convert FLOAT2 to USHORT2N. */ + const struct vertex_ptc vertices16[] = + { + {{ 0.0f, 3.0f, 0.f}, {1.0f, 2.0f}}, + {{ 2.0f, 3.0f, 0.f}, {0.4f, 0.5f}}, + {{ 0.0f, 0.0f, 0.f}, {0.6f, -1.0f}}, + + {{ 3.0f, 3.0f, 0.f}, {-0.4f, -0.5f}}, + {{ 3.0f, 0.0f, 0.f}, {-0.9f, 0.99998f}}, + {{ 1.0f, 0.0f, 0.f}, {USHRT_MAX, 0.0f}}, + }; + const UINT num_vertices16 = ARRAY_SIZE(vertices16); + const UINT num_faces16 = ARRAY_SIZE(vertices16) / VERTS_PER_FACE; + const UINT vertex_size16 = sizeof(*vertices16); + const struct vertex_ptc_ushort2n exp_vertices16[] = + { + {{ 0.0f, 3.0f, 0.f}, {USHRT_MAX, USHRT_MAX}}, + {{ 2.0f, 3.0f, 0.f}, {26214, 32768}}, + {{ 0.0f, 0.0f, 0.f}, {39321, 0}}, + + {{ 3.0f, 3.0f, 0.f}, {0, 0}}, + {{ 3.0f, 0.0f, 0.f}, {0, USHRT_MAX - 1}}, + {{ 1.0f, 0.0f, 0.f}, {USHRT_MAX, 0}}, + }; + const UINT exp_vertex_size16 = sizeof(*exp_vertices16); + /* Test 17. Convert FLOAT2 to USHORT4N. */ + const struct vertex_ptc vertices17[] = + { + {{ 0.0f, 3.0f, 0.f}, {1.0f, 2.0f}}, + {{ 2.0f, 3.0f, 0.f}, {0.4f, 0.5f}}, + {{ 0.0f, 0.0f, 0.f}, {0.6f, -1.0f}}, + + {{ 3.0f, 3.0f, 0.f}, {-0.4f, -0.5f}}, + {{ 3.0f, 0.0f, 0.f}, {-0.9f, 0.99998f}}, + {{ 1.0f, 0.0f, 0.f}, {USHRT_MAX, 0.0f}}, + }; + const UINT num_vertices17 = ARRAY_SIZE(vertices17); + const UINT num_faces17 = ARRAY_SIZE(vertices17) / VERTS_PER_FACE; + const UINT vertex_size17 = sizeof(*vertices17); + const struct vertex_ptc_ushort4n exp_vertices17[] = + { + {{ 0.0f, 3.0f, 0.f}, {USHRT_MAX, USHRT_MAX, 0, USHRT_MAX}}, + {{ 2.0f, 3.0f, 0.f}, {26214, 32768, 0, USHRT_MAX}}, + {{ 0.0f, 0.0f, 0.f}, {39321, 0, 0, USHRT_MAX}}, + + {{ 3.0f, 3.0f, 0.f}, {0, 0, 0, USHRT_MAX}}, + {{ 3.0f, 0.0f, 0.f}, {0, USHRT_MAX - 1, 0, USHRT_MAX}}, + {{ 1.0f, 0.0f, 0.f}, {USHRT_MAX, 0, 0, USHRT_MAX}}, + }; + const UINT exp_vertex_size17 = sizeof(*exp_vertices17); + /* Test 18. Test that the method field is compared by converting a FLOAT2 to + * FLOAT16_2. where the method field has been change from + * D3DDECLMETHOD_DEFAULT to D3DDECLMETHOD_PARTIALU. */ + const struct vertex_ptc vertices18[] = + { + {{ 0.0f, 3.0f, 0.f}, { 1.0f, 1.0f}}, + {{ 2.0f, 3.0f, 0.f}, { 0.5f, 0.7f}}, + {{ 0.0f, 0.0f, 0.f}, {-0.2f, -0.3f}}, + + {{ 3.0f, 3.0f, 0.f}, { 0.2f, 0.3f}}, + {{ 3.0f, 0.0f, 0.f}, { 1.0f, 1.0f}}, + {{ 1.0f, 0.0f, 0.f}, { 0.1f, 0.2f}}, + }; + const UINT num_vertices18 = ARRAY_SIZE(vertices18); + const UINT num_faces18 = ARRAY_SIZE(vertices18) / VERTS_PER_FACE; + const UINT vertex_size18 = sizeof(*vertices18); + const struct vertex_ptc_float16_2 exp_vertices18[] = + { + {{ 0.0f, 3.0f, 0.f}, {0x3c00, 0x3c00}}, /* {1.0f, 1.0f} */ + {{ 2.0f, 3.0f, 0.f}, {0x3800, 0x399a}}, /* {0.5f, 0.7f} */ + {{ 0.0f, 0.0f, 0.f}, {0xb266, 0xb4cd}}, /* {-0.2f, -0.3f} */ + + {{ 3.0f, 3.0f, 0.f}, {0x3266, 0x34cd}}, /* {0.2f, 0.3f} */ + {{ 3.0f, 0.0f, 0.f}, {0x3c00, 0x3c00}}, /* {1.0f, 1.0f} */ + {{ 1.0f, 0.0f, 0.f}, {0x2e66, 0x3266}}, /* {0.1f, 0.2f} */ + }; + const UINT exp_vertex_size18 = sizeof(*exp_vertices18); + /* Test 19. Test that data is lost if usage index changes, e.g. TEXCOORD0 + * TEXCOORD1. */ + const struct vertex_pntc vertices19[] = + { + {{ 0.0f, 3.0f, 0.f}, up, { 1.0f, 1.0f}}, + {{ 2.0f, 3.0f, 0.f}, up, { 0.5f, 0.7f}}, + {{ 0.0f, 0.0f, 0.f}, up, {-0.2f, -0.3f}}, + + {{ 3.0f, 3.0f, 0.f}, up, { 0.2f, 0.3f}}, + {{ 3.0f, 0.0f, 0.f}, up, { 1.0f, 1.0f}}, + {{ 1.0f, 0.0f, 0.f}, up, { 0.1f, 0.2f}}, + }; + const UINT num_vertices19 = ARRAY_SIZE(vertices19); + const UINT num_faces19 = ARRAY_SIZE(vertices19) / VERTS_PER_FACE; + const UINT vertex_size19 = sizeof(*vertices19); + const struct vertex_pntc exp_vertices19[] = + { + {{ 0.0f, 3.0f, 0.f}, up, zero_vec2}, + {{ 2.0f, 3.0f, 0.f}, up, zero_vec2}, + {{ 0.0f, 0.0f, 0.f}, up, zero_vec2}, + + {{ 3.0f, 3.0f, 0.f}, up, zero_vec2}, + {{ 3.0f, 0.0f, 0.f}, up, zero_vec2}, + {{ 1.0f, 0.0f, 0.f}, up, zero_vec2}, + }; + const UINT exp_vertex_size19 = sizeof(*exp_vertices19); + /* Test 20. Another test that data is lost if usage index changes, e.g. + * TEXCOORD1 to TEXCOORD0. */ + const struct vertex_pntc vertices20[] = + { + {{ 0.0f, 3.0f, 0.f}, up, { 1.0f, 1.0f}}, + {{ 2.0f, 3.0f, 0.f}, up, { 0.5f, 0.7f}}, + {{ 0.0f, 0.0f, 0.f}, up, {-0.2f, -0.3f}}, + + {{ 3.0f, 3.0f, 0.f}, up, { 0.2f, 0.3f}}, + {{ 3.0f, 0.0f, 0.f}, up, { 1.0f, 1.0f}}, + {{ 1.0f, 0.0f, 0.f}, up, { 0.1f, 0.2f}}, + }; + const UINT num_vertices20 = ARRAY_SIZE(vertices20); + const UINT num_faces20 = ARRAY_SIZE(vertices20) / VERTS_PER_FACE; + const UINT vertex_size20 = sizeof(*vertices20); + const struct vertex_pntc exp_vertices20[] = + { + {{ 0.0f, 3.0f, 0.f}, up, zero_vec2}, + {{ 2.0f, 3.0f, 0.f}, up, zero_vec2}, + {{ 0.0f, 0.0f, 0.f}, up, zero_vec2}, + + {{ 3.0f, 3.0f, 0.f}, up, zero_vec2}, + {{ 3.0f, 0.0f, 0.f}, up, zero_vec2}, + {{ 1.0f, 0.0f, 0.f}, up, zero_vec2}, + }; + const UINT exp_vertex_size20 = sizeof(*exp_vertices20); + /* Test 21. Convert FLOAT1 to FLOAT2. */ + const struct vertex_ptc_float1 vertices21[] = + { + {{ 0.0f, 3.0f, 0.f}, 1.0f}, + {{ 2.0f, 3.0f, 0.f}, 0.5f}, + {{ 0.0f, 0.0f, 0.f}, -0.2f}, + + {{ 3.0f, 3.0f, 0.f}, 0.2f}, + {{ 3.0f, 0.0f, 0.f}, 1.0f}, + {{ 1.0f, 0.0f, 0.f}, 0.1f}, + }; + const UINT num_vertices21 = ARRAY_SIZE(vertices21); + const UINT num_faces21 = ARRAY_SIZE(vertices21) / VERTS_PER_FACE; + const UINT vertex_size21 = sizeof(*vertices21); + const struct vertex_ptc exp_vertices21[] = + { + {{ 0.0f, 3.0f, 0.f}, { 1.0f, 0.0f}}, + {{ 2.0f, 3.0f, 0.f}, { 0.5f, 0.0f}}, + {{ 0.0f, 0.0f, 0.f}, {-0.2f, 0.0f}}, + + {{ 3.0f, 3.0f, 0.f}, { 0.2f, 0.0f}}, + {{ 3.0f, 0.0f, 0.f}, { 1.0f, 0.0f}}, + {{ 1.0f, 0.0f, 0.f}, { 0.1f, 0.0f}}, + }; + const UINT exp_vertex_size21 = sizeof(*exp_vertices21); + /* Test 22. Convert FLOAT1 to FLOAT3. */ + const struct vertex_ptc_float1 vertices22[] = + { + {{ 0.0f, 3.0f, 0.f}, 1.0f}, + {{ 2.0f, 3.0f, 0.f}, 0.5f}, + {{ 0.0f, 0.0f, 0.f}, -0.2f}, + + {{ 3.0f, 3.0f, 0.f}, 0.2f}, + {{ 3.0f, 0.0f, 0.f}, 1.0f}, + {{ 1.0f, 0.0f, 0.f}, 0.1f}, + }; + const UINT num_vertices22 = ARRAY_SIZE(vertices22); + const UINT num_faces22 = ARRAY_SIZE(vertices22) / VERTS_PER_FACE; + const UINT vertex_size22 = sizeof(*vertices22); + const struct vertex_ptc_float3 exp_vertices22[] = + { + {{ 0.0f, 3.0f, 0.f}, { 1.0f, 0.0f, 0.0f}}, + {{ 2.0f, 3.0f, 0.f}, { 0.5f, 0.0f, 0.0f}}, + {{ 0.0f, 0.0f, 0.f}, {-0.2f, 0.0f, 0.0f}}, + + {{ 3.0f, 3.0f, 0.f}, { 0.2f, 0.0f, 0.0f}}, + {{ 3.0f, 0.0f, 0.f}, { 1.0f, 0.0f, 0.0f}}, + {{ 1.0f, 0.0f, 0.f}, { 0.1f, 0.0f, 0.0f}}, + }; + const UINT exp_vertex_size22 = sizeof(*exp_vertices22); + /* Test 23. Convert FLOAT1 to FLOAT4. */ + const struct vertex_ptc_float1 vertices23[] = + { + {{ 0.0f, 3.0f, 0.f}, 1.0f}, + {{ 2.0f, 3.0f, 0.f}, 0.5f}, + {{ 0.0f, 0.0f, 0.f}, -0.2f}, + + {{ 3.0f, 3.0f, 0.f}, 0.2f}, + {{ 3.0f, 0.0f, 0.f}, 1.0f}, + {{ 1.0f, 0.0f, 0.f}, 0.1f}, + }; + const UINT num_vertices23 = ARRAY_SIZE(vertices23); + const UINT num_faces23 = ARRAY_SIZE(vertices23) / VERTS_PER_FACE; + const UINT vertex_size23 = sizeof(*vertices23); + const struct vertex_ptc_float4 exp_vertices23[] = + { + {{ 0.0f, 3.0f, 0.f}, { 1.0f, 0.0f, 0.0f, 1.0f}}, + {{ 2.0f, 3.0f, 0.f}, { 0.5f, 0.0f, 0.0f, 1.0f}}, + {{ 0.0f, 0.0f, 0.f}, {-0.2f, 0.0f, 0.0f, 1.0f}}, + + {{ 3.0f, 3.0f, 0.f}, { 0.2f, 0.0f, 0.0f, 1.0f}}, + {{ 3.0f, 0.0f, 0.f}, { 1.0f, 0.0f, 0.0f, 1.0f}}, + {{ 1.0f, 0.0f, 0.f}, { 0.1f, 0.0f, 0.0f, 1.0f}}, + }; + const UINT exp_vertex_size23 = sizeof(*exp_vertices23); + /* Test 24. Convert FLOAT1 to D3DCOLOR. */ + const struct vertex_ptc_float1 vertices24[] = + { + {{ 0.0f, 3.0f, 0.f}, 1.0f}, + {{ 2.0f, 3.0f, 0.f}, 0.5f}, + {{ 0.0f, 0.0f, 0.f}, -0.2f}, + + {{ 3.0f, 3.0f, 0.f}, 0.2f}, + {{ 3.0f, 0.0f, 0.f}, 1.0f}, + {{ 1.0f, 0.0f, 0.f}, 0.11f}, + }; + const UINT num_vertices24 = ARRAY_SIZE(vertices24); + const UINT num_faces24 = ARRAY_SIZE(vertices24) / VERTS_PER_FACE; + const UINT vertex_size24 = sizeof(*vertices24); + const struct vertex_ptc_d3dcolor exp_vertices24[] = + { + {{ 0.0f, 3.0f, 0.f}, {0, 0, 255, 255}}, + {{ 2.0f, 3.0f, 0.f}, {0, 0, 128, 255}}, + {{ 0.0f, 0.0f, 0.f}, {0, 0, 0, 255}}, + + {{ 3.0f, 3.0f, 0.f}, {0, 0, 51, 255}}, + {{ 3.0f, 0.0f, 0.f}, {0, 0, 255, 255}}, + {{ 1.0f, 0.0f, 0.f}, {0, 0, 28, 255}}, + }; + const UINT exp_vertex_size24 = sizeof(*exp_vertices24); + /* Test 25. Convert FLOAT1 to ubyte4. */ + const struct vertex_ptc_float1 vertices25[] = + { + {{ 0.0f, 3.0f, 0.f}, 0.0f}, + {{ 2.0f, 3.0f, 0.f}, 1.4f}, + {{ 0.0f, 0.0f, 0.f}, 1.5f}, + + {{ 3.0f, 3.0f, 0.f}, 255.0f}, + {{ 3.0f, 0.0f, 0.f}, 256.0f}, + {{ 1.0f, 0.0f, 0.f}, -1.0f}, + }; + const UINT num_vertices25 = ARRAY_SIZE(vertices25); + const UINT num_faces25 = ARRAY_SIZE(vertices25) / VERTS_PER_FACE; + const UINT vertex_size25 = sizeof(*vertices25); + const struct vertex_ptc_ubyte4 exp_vertices25[] = + { + {{ 0.0f, 3.0f, 0.f}, {0, 0, 0, 1}}, + {{ 2.0f, 3.0f, 0.f}, {1, 0, 0, 1}}, + {{ 0.0f, 0.0f, 0.f}, {2, 0, 0, 1}}, + + {{ 3.0f, 3.0f, 0.f}, {255, 0, 0, 1}}, + {{ 3.0f, 0.0f, 0.f}, {0, 0, 0, 1}}, + {{ 1.0f, 0.0f, 0.f}, {0, 0, 0, 1}}, + }; + const UINT exp_vertex_size25 = sizeof(*exp_vertices25); + /* Test 26. Convert FLOAT4 to D3DCOLOR. */ + const struct vertex_ptc_float4 vertices26[] = + { + {{ 0.0f, 3.0f, 0.f}, {0.0f, 1.0f, 0.4f, 0.5f}}, + {{ 2.0f, 3.0f, 0.f}, {-0.4f, -0.5f, -1.0f, -2.0f}}, + {{ 0.0f, 0.0f, 0.f}, {254.0f, 255.0f, 256.0f, 257.0f}}, + + {{ 3.0f, 3.0f, 0.f}, {0.1f, 0.2f, 0.3f, 0.4f}}, + {{ 3.0f, 0.0f, 0.f}, {0.5f, 0.6f, 0.7f, 0.8f}}, + {{ 1.0f, 0.0f, 0.f}, {0.9f, 0.99f, 0.995f, 0.999f}}, + }; + const UINT num_vertices26 = ARRAY_SIZE(vertices26); + const UINT num_faces26 = ARRAY_SIZE(vertices26) / VERTS_PER_FACE; + const UINT vertex_size26 = sizeof(*vertices26); + const struct vertex_ptc_d3dcolor exp_vertices26[] = + { + {{ 0.0f, 3.0f, 0.f}, {102, 255, 0, 128}}, + {{ 2.0f, 3.0f, 0.f}, {0, 0, 0, 0}}, + {{ 0.0f, 0.0f, 0.f}, {255, 255, 255, 255}}, + + {{ 3.0f, 3.0f, 0.f}, {77, 51, 26, 102}}, + {{ 3.0f, 0.0f, 0.f}, {179, 153, 128, 204}}, + {{ 1.0f, 0.0f, 0.f}, {254, 252, 230, 255}}, + }; + const UINT exp_vertex_size26 = sizeof(*exp_vertices26); + /* Test 27. Convert D3DCOLOR to FLOAT4. */ + const struct vertex_ptc_d3dcolor vertices27[] = + { + {{ 0.0f, 3.0f, 0.f}, {102, 255, 0, 128}}, + {{ 2.0f, 3.0f, 0.f}, {0, 0, 0, 0}}, + {{ 0.0f, 0.0f, 0.f}, {255, 255, 255, 255}}, + + {{ 3.0f, 3.0f, 0.f}, {77, 51, 26, 102}}, + {{ 3.0f, 0.0f, 0.f}, {179, 153, 128, 204}}, + {{ 1.0f, 0.0f, 0.f}, {254, 252, 230, 255}}, + }; + const UINT num_vertices27 = ARRAY_SIZE(vertices27); + const UINT num_faces27 = ARRAY_SIZE(vertices27) / VERTS_PER_FACE; + const UINT vertex_size27 = sizeof(*vertices27); + const struct vertex_ptc_float4 exp_vertices27[] = + { + {{ 0.0f, 3.0f, 0.f}, {0.0f, 1.0f, 0.4f, 0.501961f}}, + {{ 2.0f, 3.0f, 0.f}, {0.0f, 0.0f, 0.0f, 0.0f}}, + {{ 0.0f, 0.0f, 0.f}, {1.0f, 1.0f, 1.0f, 1.0f}}, + + {{ 3.0f, 3.0f, 0.f}, {0.101961f, 0.2f, 0.301961f, 0.4f}}, + {{ 3.0f, 0.0f, 0.f}, {0.501961f, 0.6f, 0.701961f, 0.8f}}, + {{ 1.0f, 0.0f, 0.f}, {0.901961f, 0.988235f, 0.996078f, 1.0f}}, + }; + const UINT exp_vertex_size27 = sizeof(*exp_vertices27); + /* Test 28. Convert UBYTE4 to FLOAT4. */ + const struct vertex_ptc_ubyte4 vertices28[] = + { + {{ 0.0f, 3.0f, 0.f}, {0, 0, 0, 0}}, + {{ 2.0f, 3.0f, 0.f}, {1, 1, 1, 1}}, + {{ 0.0f, 0.0f, 0.f}, {1, 0, 1, 0}}, + + {{ 3.0f, 3.0f, 0.f}, {0, 1, 0, 1}}, + {{ 3.0f, 0.0f, 0.f}, {10, 20, 30, 40}}, + {{ 1.0f, 0.0f, 0.f}, {50, 60, 127, 255}}, + }; + const UINT num_vertices28 = ARRAY_SIZE(vertices28); + const UINT num_faces28 = ARRAY_SIZE(vertices28) / VERTS_PER_FACE; + const UINT vertex_size28 = sizeof(*vertices28); + const struct vertex_ptc_float4 exp_vertices28[] = + { + {{ 0.0f, 3.0f, 0.f}, {0.0f, 0.0f, 0.0f, 0.0f}}, + {{ 2.0f, 3.0f, 0.f}, {1.0f, 1.0f, 1.0f, 1.0f}}, + {{ 0.0f, 0.0f, 0.f}, {1.0f, 0.0f, 1.0f, 0.0f}}, + + {{ 3.0f, 3.0f, 0.f}, {0.0f, 1.0f, 0.0f, 1.0f}}, + {{ 3.0f, 0.0f, 0.f}, {10.0f, 20.0f, 30.0f, 40.0f}}, + {{ 1.0f, 0.0f, 0.f}, {50.0f, 60.0f, 127.0f, 255.0f}}, + }; + const UINT exp_vertex_size28 = sizeof(*exp_vertices28); + /* Test 29. Convert SHORT2 to FLOAT4. */ + const struct vertex_ptc_short2 vertices29[] = + { + {{ 0.0f, 3.0f, 0.f}, {0, 0}}, + {{ 2.0f, 3.0f, 0.f}, {0, 1}}, + {{ 0.0f, 0.0f, 0.f}, {1, 0}}, + + {{ 3.0f, 3.0f, 0.f}, {1, 1}}, + {{ 3.0f, 0.0f, 0.f}, {SHRT_MIN, SHRT_MAX}}, + {{ 1.0f, 0.0f, 0.f}, {-42, 42}}, + }; + const UINT num_vertices29 = ARRAY_SIZE(vertices29); + const UINT num_faces29 = ARRAY_SIZE(vertices29) / VERTS_PER_FACE; + const UINT vertex_size29 = sizeof(*vertices29); + const struct vertex_ptc_float4 exp_vertices29[] = + { + {{ 0.0f, 3.0f, 0.f}, {0.0f, 0.0f, 0.0f, 1.0f}}, + {{ 2.0f, 3.0f, 0.f}, {0.0f, 1.0f, 0.0f, 1.0f }}, + {{ 0.0f, 0.0f, 0.f}, {1.0f, 0.0f, 0.0f, 1.0f}}, + + {{ 3.0f, 3.0f, 0.f}, {1.0f, 1.0f, 0.0f, 1.0f}}, + {{ 3.0f, 0.0f, 0.f}, {SHRT_MIN, SHRT_MAX, 0.0f, 1.0f}}, + {{ 1.0f, 0.0f, 0.f}, {-42.0f, 42.0f, 0.0f, 1.0f}}, + }; + const UINT exp_vertex_size29 = sizeof(*exp_vertices29); + /* Test 29. Convert SHORT4 to FLOAT4. */ + const struct vertex_ptc_short4 vertices30[] = + { + {{ 0.0f, 3.0f, 0.f}, {0, 0, 0, 0}}, + {{ 2.0f, 3.0f, 0.f}, {0, 1, 0, 1}}, + {{ 0.0f, 0.0f, 0.f}, {1, 0, 1, 0}}, + + {{ 3.0f, 3.0f, 0.f}, {1, 1, 1, 1}}, + {{ 3.0f, 0.0f, 0.f}, {SHRT_MIN, SHRT_MAX, 1, 0}}, + {{ 1.0f, 0.0f, 0.f}, {-42, 42, SHRT_MAX, SHRT_MIN}}, + }; + const UINT num_vertices30 = ARRAY_SIZE(vertices30); + const UINT num_faces30 = ARRAY_SIZE(vertices30) / VERTS_PER_FACE; + const UINT vertex_size30 = sizeof(*vertices30); + const struct vertex_ptc_float4 exp_vertices30[] = + { + {{ 0.0f, 3.0f, 0.f}, {0.0f, 0.0f, 0.0f, 0.0f}}, + {{ 2.0f, 3.0f, 0.f}, {0.0f, 1.0f, 0.0f, 1.0f }}, + {{ 0.0f, 0.0f, 0.f}, {1.0f, 0.0f, 1.0f, 0.0f}}, + + {{ 3.0f, 3.0f, 0.f}, {1.0f, 1.0f, 1.0f, 1.0f}}, + {{ 3.0f, 0.0f, 0.f}, {SHRT_MIN, SHRT_MAX, 1.0f, 0.0f}}, + {{ 1.0f, 0.0f, 0.f}, {-42.0f, 42.0f, SHRT_MAX, SHRT_MIN}}, + }; + const UINT exp_vertex_size30 = sizeof(*exp_vertices30); + /* Test 31. Convert UBYTE4N to FLOAT4. */ + const struct vertex_ptc_ubyte4n vertices31[] = + { + {{ 0.0f, 3.0f, 0.f}, {0, 0, 0, 0}}, + {{ 2.0f, 3.0f, 0.f}, {1, 1, 1, 1}}, + {{ 0.0f, 0.0f, 0.f}, {1, 0, 1, 0}}, + + {{ 3.0f, 3.0f, 0.f}, {0, 1, 0, 1}}, + {{ 3.0f, 0.0f, 0.f}, {10, 20, 30, 40}}, + {{ 1.0f, 0.0f, 0.f}, {50, 60, 70, UCHAR_MAX}}, + }; + const UINT num_vertices31 = ARRAY_SIZE(vertices31); + const UINT num_faces31 = ARRAY_SIZE(vertices31) / VERTS_PER_FACE; + const UINT vertex_size31 = sizeof(*vertices31); + const struct vertex_ptc_float4 exp_vertices31[] = + { + {{ 0.0f, 3.0f, 0.f}, {0.0f, 0.0f, 0.0f, 0.0f}}, + {{ 2.0f, 3.0f, 0.f}, {(FLOAT)1/UCHAR_MAX, (FLOAT)1/UCHAR_MAX, (FLOAT)1/UCHAR_MAX, (FLOAT)1/UCHAR_MAX}}, + {{ 0.0f, 0.0f, 0.f}, {(FLOAT)1/UCHAR_MAX, 0.0f, (FLOAT)1/UCHAR_MAX, 0.0f}}, + + {{ 3.0f, 3.0f, 0.f}, {0.0f, (FLOAT)1/UCHAR_MAX, 0.0f, (FLOAT)1/UCHAR_MAX}}, + {{ 3.0f, 0.0f, 0.f}, {(FLOAT)10/UCHAR_MAX, (FLOAT)20/UCHAR_MAX, (FLOAT)30/UCHAR_MAX, (FLOAT)40/UCHAR_MAX}}, + {{ 1.0f, 0.0f, 0.f}, {(FLOAT)50/UCHAR_MAX, (FLOAT)60/UCHAR_MAX, (FLOAT)70/UCHAR_MAX, 1.0f}}, + }; + const UINT exp_vertex_size31 = sizeof(*exp_vertices31); + /* Test 32. Convert SHORT2N to FLOAT4. */ + const struct vertex_ptc_short2 vertices32[] = + { + {{ 0.0f, 3.0f, 0.f}, {0, 0}}, + {{ 2.0f, 3.0f, 0.f}, {0, 1}}, + {{ 0.0f, 0.0f, 0.f}, {1, 0}}, + + {{ 3.0f, 3.0f, 0.f}, {1, 1}}, + {{ 3.0f, 0.0f, 0.f}, {SHRT_MIN + 1, SHRT_MAX}}, + {{ 1.0f, 0.0f, 0.f}, {-42, 42}}, + }; + const UINT num_vertices32 = ARRAY_SIZE(vertices32); + const UINT num_faces32 = ARRAY_SIZE(vertices32) / VERTS_PER_FACE; + const UINT vertex_size32 = sizeof(*vertices32); + const struct vertex_ptc_float4 exp_vertices32[] = + { + {{ 0.0f, 3.0f, 0.f}, {0.0f, 0.0f, 0.0f, 1.0f}}, + {{ 2.0f, 3.0f, 0.f}, {0.0f, 1.0f/SHRT_MAX, 0.0f, 1.0f}}, + {{ 0.0f, 0.0f, 0.f}, {1.0f/SHRT_MAX, 0.0f, 0.0f, 1.0f}}, + + {{ 3.0f, 3.0f, 0.f}, {1.0f/SHRT_MAX, 1.0f/SHRT_MAX, 0.0f, 1.0f}}, + {{ 3.0f, 0.0f, 0.f}, {-1.0f, 1.0f, 0.0f, 1.0f}}, + {{ 1.0f, 0.0f, 0.f}, {-42.0f/SHRT_MAX, 42.0f/SHRT_MAX, 0.0f, 1.0f}}, + }; + const UINT exp_vertex_size32 = sizeof(*exp_vertices32); + /* Test 33. Convert SHORT4N to FLOAT4. */ + const struct vertex_ptc_short4 vertices33[] = + { + {{ 0.0f, 3.0f, 0.f}, {0, 0, 0, 0}}, + {{ 2.0f, 3.0f, 0.f}, {0, 1, 0, 1}}, + {{ 0.0f, 0.0f, 0.f}, {1, 0, 1, 0}}, + + {{ 3.0f, 3.0f, 0.f}, {1, 1, 1, 1}}, + {{ 3.0f, 0.0f, 0.f}, {SHRT_MIN + 1, SHRT_MAX, SHRT_MIN + 1, SHRT_MAX}}, + {{ 1.0f, 0.0f, 0.f}, {-42, 42, 1, 1}}, + }; + const UINT num_vertices33 = ARRAY_SIZE(vertices33); + const UINT num_faces33 = ARRAY_SIZE(vertices33) / VERTS_PER_FACE; + const UINT vertex_size33 = sizeof(*vertices33); + const struct vertex_ptc_float4 exp_vertices33[] = + { + {{ 0.0f, 3.0f, 0.f}, {0.0f, 0.0f, 0.0f, 0.0f}}, + {{ 2.0f, 3.0f, 0.f}, {0.0f, 1.0f/SHRT_MAX, 0.0f, 1.0f/SHRT_MAX}}, + {{ 0.0f, 0.0f, 0.f}, {1.0f/SHRT_MAX, 0.0f, 1.0f/SHRT_MAX, 0.0f}}, + + {{ 3.0f, 3.0f, 0.f}, {1.0f/SHRT_MAX, 1.0f/SHRT_MAX, 1.0f/SHRT_MAX, 1.0f/SHRT_MAX}}, + {{ 3.0f, 0.0f, 0.f}, {-1.0f, 1.0f, -1.0f, 1.0f}}, + {{ 1.0f, 0.0f, 0.f}, {-42.0f/SHRT_MAX, 42.0f/SHRT_MAX, 1.0f/SHRT_MAX, 1.0f/SHRT_MAX}}, + }; + const UINT exp_vertex_size33 = sizeof(*exp_vertices33); + /* Test 34. Convert FLOAT16_2 to FLOAT4. */ + const struct vertex_ptc_float16_2 vertices34[] = + { + {{ 0.0f, 3.0f, 0.f}, {0x3c00, 0x3c00}}, /* {1.0f, 1.0f} */ + {{ 2.0f, 3.0f, 0.f}, {0x3800, 0x399a}}, /* {0.5f, 0.7f} */ + {{ 0.0f, 0.0f, 0.f}, {0xb266, 0xb4cd}}, /* {-0.2f, -0.3f} */ + + {{ 3.0f, 3.0f, 0.f}, {0x3266, 0x34cd}}, /* {0.2f, 0.3f} */ + {{ 3.0f, 0.0f, 0.f}, {0x3c00, 0x3c00}}, /* {1.0f, 1.0f} */ + {{ 1.0f, 0.0f, 0.f}, {0x2e66, 0x3266}}, /* {0.1f, 0.2f} */ + }; + const UINT num_vertices34 = ARRAY_SIZE(vertices34); + const UINT num_faces34 = ARRAY_SIZE(vertices34) / VERTS_PER_FACE; + const UINT vertex_size34 = sizeof(*vertices34); + const struct vertex_ptc_float4 exp_vertices34[] = + { + {{ 0.0f, 3.0f, 0.f}, {1.0f, 1.0f, 0.0f, 1.0f}}, + {{ 2.0f, 3.0f, 0.f}, {0.5f, 0.700195f, 0.0f, 1.0f}}, + {{ 0.0f, 0.0f, 0.f}, {-0.199951f, -0.300049f, 0.0f, 1.0f}}, + + {{ 3.0f, 3.0f, 0.f}, {0.199951f, 0.300049f, 0.0f, 1.0f}}, + {{ 3.0f, 0.0f, 0.f}, {1.0f, 1.0f, 0.0f, 1.0f}}, + {{ 1.0f, 0.0f, 0.f}, {0.099976f, 0.199951f, 0.0f, 1.0f}}, + }; + const UINT exp_vertex_size34 = sizeof(*exp_vertices34); + /* Test 35. Convert FLOAT16_4 to FLOAT4. */ + const struct vertex_ptc_float16_4 vertices35[] = + { + {{ 0.0f, 3.0f, 0.f}, {0x0000, 0x0000, 0x0000, 0x0000}}, + {{ 2.0f, 3.0f, 0.f}, {0x3c00, 0x3c00, 0x3c00, 0x3c00}}, + {{ 0.0f, 0.0f, 0.f}, {0x3c00, 0x0000, 0x3c00, 0x0000}}, + + {{ 3.0f, 3.0f, 0.f}, {0x0000, 0x3c00, 0x0000, 0x3c00}}, + {{ 3.0f, 0.0f, 0.f}, {0x3800, 0x399a, 0xb266, 0xb4cd}}, + {{ 1.0f, 0.0f, 0.f}, {0x2e66, 0x3266, 0x2e66, 0x3266}}, + }; + const UINT num_vertices35 = ARRAY_SIZE(vertices35); + const UINT num_faces35 = ARRAY_SIZE(vertices35) / VERTS_PER_FACE; + const UINT vertex_size35 = sizeof(*vertices35); + const struct vertex_ptc_float4 exp_vertices35[] = + { + {{ 0.0f, 3.0f, 0.f}, {0.0f, 0.0f, 0.0f, 0.0f}}, + {{ 2.0f, 3.0f, 0.f}, {1.0f, 1.0f, 1.0f, 1.0f}}, + {{ 0.0f, 0.0f, 0.f}, {1.0f, 0.0f, 1.0f, 0.0f}}, + + {{ 3.0f, 3.0f, 0.f}, {0.0f, 1.0f, 0.0f, 1.0f}}, + {{ 3.0f, 0.0f, 0.f}, {0.5f, 0.700195f, -0.199951f, -0.300049f}}, + {{ 1.0f, 0.0f, 0.f}, {0.099976f, 0.199951f, 0.099976f, 0.199951f}}, + }; + const UINT exp_vertex_size35 = sizeof(*exp_vertices35); + /* Test 36. Check that vertex buffer sharing is ok. */ + const struct vertex_pn vertices36[] = + { + {{ 0.0f, 3.0f, 0.f}, up}, + {{ 2.0f, 3.0f, 0.f}, up}, + {{ 0.0f, 0.0f, 0.f}, up}, + }; + const UINT num_vertices36 = ARRAY_SIZE(vertices36); + const UINT num_faces36 = ARRAY_SIZE(vertices36) / VERTS_PER_FACE; + const UINT vertex_size36 = sizeof(*vertices36); + const DWORD clone_options36 = options | D3DXMESH_VB_SHARE; + /* Common mesh data */ + ID3DXMesh *mesh = NULL; + ID3DXMesh *mesh_clone = NULL; + struct + { + const BYTE *vertices; + const DWORD *indices; + const DWORD *attributes; + const UINT num_vertices; + const UINT num_faces; + const UINT vertex_size; + const DWORD create_options; + const DWORD clone_options; + D3DVERTEXELEMENT9 *declaration; + D3DVERTEXELEMENT9 *new_declaration; + const BYTE *exp_vertices; + const UINT exp_vertex_size; + } + tc[] = + { + { + (BYTE*)vertices0, + NULL, + NULL, + num_vertices0, + num_faces0, + vertex_size0, + options, + options, + declaration_pn, + declaration_pn, + (BYTE*)vertices0, + vertex_size0 + }, + { + (BYTE*)vertices0, + NULL, + NULL, + num_vertices0, + num_faces0, + vertex_size0, + options_16bit, + options_16bit, + declaration_pn, + declaration_pn, + (BYTE*)vertices0, + vertex_size0 + }, + { + (BYTE*)vertices0, + NULL, + NULL, + num_vertices0, + num_faces0, + vertex_size0, + options, + options, + declaration_pn, + declaration_pntc, + (BYTE*)exp_vertices2, + exp_vertex_size2 + }, + { + (BYTE*)vertices0, + NULL, + NULL, + num_vertices0, + num_faces0, + vertex_size0, + options, + options, + declaration_pn, + declaration_ptcn, + (BYTE*)exp_vertices3, + exp_vertex_size3 + }, + { + (BYTE*)vertices4, + NULL, + NULL, + num_vertices4, + num_faces4, + vertex_size4, + options, + options, + declaration_ptc, + declaration_ptc_float16_2, + (BYTE*)exp_vertices4, + exp_vertex_size4 + }, + { + (BYTE*)vertices5, + NULL, + NULL, + num_vertices5, + num_faces5, + vertex_size5, + options, + options, + declaration_ptc, + declaration_ptc_float16_4, + (BYTE*)exp_vertices5, + exp_vertex_size5 + }, + { + (BYTE*)vertices6, + NULL, + NULL, + num_vertices6, + num_faces6, + vertex_size6, + options, + options, + declaration_ptc, + declaration_ptc_float1, + (BYTE*)exp_vertices6, + exp_vertex_size6 + }, + { + (BYTE*)vertices7, + NULL, + NULL, + num_vertices7, + num_faces7, + vertex_size7, + options, + options, + declaration_ptc, + declaration_ptc_float3, + (BYTE*)exp_vertices7, + exp_vertex_size7 + }, + { + (BYTE*)vertices8, + NULL, + NULL, + num_vertices8, + num_faces8, + vertex_size8, + options, + options, + declaration_ptc, + declaration_ptc_float4, + (BYTE*)exp_vertices8, + exp_vertex_size8 + }, + { + (BYTE*)vertices9, + NULL, + NULL, + num_vertices9, + num_faces9, + vertex_size9, + options, + options, + declaration_ptc, + declaration_ptc_d3dcolor, + (BYTE*)exp_vertices9, + exp_vertex_size9 + }, + { + (BYTE*)vertices10, + NULL, + NULL, + num_vertices10, + num_faces10, + vertex_size10, + options, + options, + declaration_ptc, + declaration_ptc_ubyte4, + (BYTE*)exp_vertices10, + exp_vertex_size10 + }, + { + (BYTE*)vertices11, + NULL, + NULL, + num_vertices11, + num_faces11, + vertex_size11, + options, + options, + declaration_ptc, + declaration_ptc_short2, + (BYTE*)exp_vertices11, + exp_vertex_size11 + }, + { + (BYTE*)vertices12, + NULL, + NULL, + num_vertices12, + num_faces12, + vertex_size12, + options, + options, + declaration_ptc, + declaration_ptc_short4, + (BYTE*)exp_vertices12, + exp_vertex_size12 + }, + { + (BYTE*)vertices13, + NULL, + NULL, + num_vertices13, + num_faces13, + vertex_size13, + options, + options, + declaration_ptc, + declaration_ptc_ubyte4n, + (BYTE*)exp_vertices13, + exp_vertex_size13 + }, + { + (BYTE*)vertices14, + NULL, + NULL, + num_vertices14, + num_faces14, + vertex_size14, + options, + options, + declaration_ptc, + declaration_ptc_short2n, + (BYTE*)exp_vertices14, + exp_vertex_size14 + }, + { + (BYTE*)vertices15, + NULL, + NULL, + num_vertices15, + num_faces15, + vertex_size15, + options, + options, + declaration_ptc, + declaration_ptc_short4n, + (BYTE*)exp_vertices15, + exp_vertex_size15 + }, + { + (BYTE*)vertices16, + NULL, + NULL, + num_vertices16, + num_faces16, + vertex_size16, + options, + options, + declaration_ptc, + declaration_ptc_ushort2n, + (BYTE*)exp_vertices16, + exp_vertex_size16 + }, + { + (BYTE*)vertices17, + NULL, + NULL, + num_vertices17, + num_faces17, + vertex_size17, + options, + options, + declaration_ptc, + declaration_ptc_ushort4n, + (BYTE*)exp_vertices17, + exp_vertex_size17 + }, + { + (BYTE*)vertices18, + NULL, + NULL, + num_vertices18, + num_faces18, + vertex_size18, + options, + options, + declaration_ptc, + declaration_ptc_float16_2_partialu, + (BYTE*)exp_vertices18, + exp_vertex_size18 + }, + { + (BYTE*)vertices19, + NULL, + NULL, + num_vertices19, + num_faces19, + vertex_size19, + options, + options, + declaration_pntc, + declaration_pntc1, + (BYTE*)exp_vertices19, + exp_vertex_size19 + }, + { + (BYTE*)vertices20, + NULL, + NULL, + num_vertices20, + num_faces20, + vertex_size20, + options, + options, + declaration_pntc1, + declaration_pntc, + (BYTE*)exp_vertices20, + exp_vertex_size20 + }, + { + (BYTE*)vertices21, + NULL, + NULL, + num_vertices21, + num_faces21, + vertex_size21, + options, + options, + declaration_ptc_float1, + declaration_ptc, + (BYTE*)exp_vertices21, + exp_vertex_size21 + }, + { + (BYTE*)vertices22, + NULL, + NULL, + num_vertices22, + num_faces22, + vertex_size22, + options, + options, + declaration_ptc_float1, + declaration_ptc_float3, + (BYTE*)exp_vertices22, + exp_vertex_size22 + }, + { + (BYTE*)vertices23, + NULL, + NULL, + num_vertices23, + num_faces23, + vertex_size23, + options, + options, + declaration_ptc_float1, + declaration_ptc_float4, + (BYTE*)exp_vertices23, + exp_vertex_size23 + }, + { + (BYTE*)vertices24, + NULL, + NULL, + num_vertices24, + num_faces24, + vertex_size24, + options, + options, + declaration_ptc_float1, + declaration_ptc_d3dcolor, + (BYTE*)exp_vertices24, + exp_vertex_size24 + }, + { + (BYTE*)vertices25, + NULL, + NULL, + num_vertices25, + num_faces25, + vertex_size25, + options, + options, + declaration_ptc_float1, + declaration_ptc_ubyte4, + (BYTE*)exp_vertices25, + exp_vertex_size25 + }, + { + (BYTE*)vertices26, + NULL, + NULL, + num_vertices26, + num_faces26, + vertex_size26, + options, + options, + declaration_ptc_float4, + declaration_ptc_d3dcolor, + (BYTE*)exp_vertices26, + exp_vertex_size26 + }, + { + (BYTE*)vertices27, + NULL, + NULL, + num_vertices27, + num_faces27, + vertex_size27, + options, + options, + declaration_ptc_d3dcolor, + declaration_ptc_float4, + (BYTE*)exp_vertices27, + exp_vertex_size27 + }, + { + (BYTE*)vertices28, + NULL, + NULL, + num_vertices28, + num_faces28, + vertex_size28, + options, + options, + declaration_ptc_ubyte4, + declaration_ptc_float4, + (BYTE*)exp_vertices28, + exp_vertex_size28 + }, + { + (BYTE*)vertices29, + NULL, + NULL, + num_vertices29, + num_faces29, + vertex_size29, + options, + options, + declaration_ptc_short2, + declaration_ptc_float4, + (BYTE*)exp_vertices29, + exp_vertex_size29 + }, + { + (BYTE*)vertices30, + NULL, + NULL, + num_vertices30, + num_faces30, + vertex_size30, + options, + options, + declaration_ptc_short4, + declaration_ptc_float4, + (BYTE*)exp_vertices30, + exp_vertex_size30 + }, + { + (BYTE*)vertices31, + NULL, + NULL, + num_vertices31, + num_faces31, + vertex_size31, + options, + options, + declaration_ptc_ubyte4n, + declaration_ptc_float4, + (BYTE*)exp_vertices31, + exp_vertex_size31 + }, + { + (BYTE*)vertices32, + NULL, + NULL, + num_vertices32, + num_faces32, + vertex_size32, + options, + options, + declaration_ptc_short2n, + declaration_ptc_float4, + (BYTE*)exp_vertices32, + exp_vertex_size32 + }, + { + (BYTE*)vertices33, + NULL, + NULL, + num_vertices33, + num_faces33, + vertex_size33, + options, + options, + declaration_ptc_short4n, + declaration_ptc_float4, + (BYTE*)exp_vertices33, + exp_vertex_size33 + }, + { + (BYTE*)vertices34, + NULL, + NULL, + num_vertices34, + num_faces34, + vertex_size34, + options, + options, + declaration_ptc_float16_2, + declaration_ptc_float4, + (BYTE*)exp_vertices34, + exp_vertex_size34 + }, + { + (BYTE*)vertices35, + NULL, + NULL, + num_vertices35, + num_faces35, + vertex_size35, + options, + options, + declaration_ptc_float16_4, + declaration_ptc_float4, + (BYTE*)exp_vertices35, + exp_vertex_size35 + }, + { + (BYTE*)vertices36, + NULL, + NULL, + num_vertices36, + num_faces36, + vertex_size36, + options, + clone_options36, + declaration_pn, + declaration_pn, + (BYTE*)vertices36, + vertex_size36 + }, + }; +#ifdef __REACTOS__ +#undef up +#undef zero_vec2 +#endif + + test_context = new_test_context(); + if (!test_context) + { + skip("Couldn't create test context\n"); + goto cleanup; + } + + for (i = 0; i < ARRAY_SIZE(tc); i++) + { + UINT j; + D3DVERTEXELEMENT9 new_declaration[MAX_FVF_DECL_SIZE]; + UINT exp_new_decl_length, new_decl_length; + UINT exp_new_decl_size, new_decl_size; + + hr = init_test_mesh(tc[i].num_faces, tc[i].num_vertices, + tc[i].create_options, + tc[i].declaration, + test_context->device, &mesh, + tc[i].vertices, tc[i].vertex_size, + tc[i].indices, tc[i].attributes); + if (FAILED(hr)) + { + skip("Couldn't initialize test mesh %d. Got %x expected D3D_OK\n", i, hr); + goto cleanup; + } + + hr = mesh->lpVtbl->CloneMesh(mesh, tc[i].clone_options, tc[i].new_declaration, + test_context->device, &mesh_clone); + ok(hr == D3D_OK, "CloneMesh test case %d failed. Got %x\n, expected D3D_OK\n", i, hr); + + hr = mesh_clone->lpVtbl->GetDeclaration(mesh_clone, new_declaration); + ok(hr == D3D_OK, "GetDeclaration test case %d failed. Got %x\n, expected D3D_OK\n", i, hr); + /* Check declaration elements */ + for (j = 0; tc[i].new_declaration[j].Stream != 0xFF; j++) + { + ok(memcmp(&tc[i].new_declaration[j], &new_declaration[j], sizeof(*new_declaration)) == 0, + "Test case %d failed. Declaration element %d did not match.\n", i, j); + } + + /* Check declaration length */ + exp_new_decl_length = D3DXGetDeclLength(tc[i].new_declaration); + new_decl_length = D3DXGetDeclLength(new_declaration); + ok(new_decl_length == exp_new_decl_length, + "Test case %d failed. Got new declaration length %d, expected %d\n", + i, new_decl_length, exp_new_decl_length); + + /* Check declaration size */ + exp_new_decl_size = D3DXGetDeclVertexSize(tc[i].new_declaration, 0); + new_decl_size = D3DXGetDeclVertexSize(new_declaration, 0); + ok(new_decl_size == exp_new_decl_size, + "Test case %d failed. Got new declaration size %d, expected %d\n", + i, new_decl_size, exp_new_decl_size); + + /* Check vertex data in cloned mesh */ + hr = mesh_clone->lpVtbl->LockVertexBuffer(mesh_clone, 0, (void**)&vertices); + if (FAILED(hr)) + { + skip("Couldn't lock cloned vertex buffer.\n"); + goto cleanup; + } + for (j = 0; j < tc[i].num_vertices; j++) + { + UINT index = tc[i].exp_vertex_size * j; + check_vertex_components(__LINE__, i, j, &vertices[index], &tc[i].exp_vertices[index], tc[i].new_declaration); + } + hr = mesh_clone->lpVtbl->UnlockVertexBuffer(mesh_clone); + if (FAILED(hr)) + { + skip("Couldn't unlock vertex buffer.\n"); + goto cleanup; + } + vertices = NULL; + mesh->lpVtbl->Release(mesh); + mesh = NULL; + mesh_clone->lpVtbl->Release(mesh_clone); + mesh_clone = NULL; + } + + /* The following test shows that it is not possible to share a vertex buffer + * with D3DXMESH_VB_SHARE and change the vertex declaration at the same + * time. It reuses the test data from test 2. + */ + hr = init_test_mesh(tc[2].num_faces, tc[2].num_vertices, + tc[2].create_options, + tc[2].declaration, + test_context->device, &mesh, + tc[2].vertices, tc[2].vertex_size, + tc[2].indices, tc[2].attributes); + if (FAILED(hr)) + { + skip("Couldn't initialize test mesh for D3DXMESH_VB_SHARE case." + " Got %x expected D3D_OK\n", hr); + goto cleanup; + } + + hr = mesh->lpVtbl->CloneMesh(mesh, tc[2].create_options | D3DXMESH_VB_SHARE, + tc[2].new_declaration, test_context->device, + &mesh_clone); + ok(hr == D3DERR_INVALIDCALL, "CloneMesh D3DXMESH_VB_SHARE with new" + " declaration. Got %x, expected D3DERR_INVALIDCALL\n", + hr); + mesh->lpVtbl->Release(mesh); + mesh = NULL; + mesh_clone = NULL; + +cleanup: + if (vertices) mesh->lpVtbl->UnlockVertexBuffer(mesh); + if (mesh) mesh->lpVtbl->Release(mesh); + if (mesh_clone) mesh_clone->lpVtbl->Release(mesh_clone); + free_test_context(test_context); +} + +static void test_valid_mesh(void) +{ + HRESULT hr; + struct test_context *test_context = NULL; + UINT i; + const DWORD options = D3DXMESH_32BIT | D3DXMESH_SYSTEMMEM; + const D3DVERTEXELEMENT9 declaration[] = + { + {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0}, + D3DDECL_END() + }; + const unsigned int VERTS_PER_FACE = 3; + /* mesh0 (one face) + * + * 0--1 + * | / + * |/ + * 2 + */ + const D3DXVECTOR3 vertices0[] = + { + { 0.0f, 3.0f, 0.f}, + { 2.0f, 3.0f, 0.f}, + { 0.0f, 0.0f, 0.f}, + }; + const DWORD indices0[] = {0, 1, 2}; + const unsigned int num_vertices0 = ARRAY_SIZE(vertices0); + const unsigned int num_faces0 = ARRAY_SIZE(indices0) / VERTS_PER_FACE; + const DWORD adjacency0[] = {-1, -1, -1}; + const HRESULT exp_hr0 = D3D_OK; + /* mesh1 (Simple bow-tie) + * + * 0--1 1--3 + * | / \ | + * |/ \| + * 2 4 + */ + const D3DXVECTOR3 vertices1[] = + { + { 0.0f, 3.0f, 0.f}, + { 2.0f, 3.0f, 0.f}, + { 0.0f, 0.0f, 0.f}, + + { 4.0f, 3.0f, 0.f}, + { 4.0f, 0.0f, 0.f}, + }; + const DWORD indices1[] = {0, 1, 2, 1, 3, 4}; + const unsigned int num_vertices1 = ARRAY_SIZE(vertices1); + const unsigned int num_faces1 = ARRAY_SIZE(indices1) / VERTS_PER_FACE; + const DWORD adjacency1[] = {-1, -1, -1, -1, -1, -1}; + const HRESULT exp_hr1 = D3DXERR_INVALIDMESH; + /* Common mesh data */ + ID3DXMesh *mesh = NULL; + UINT vertex_size = sizeof(D3DXVECTOR3); + ID3DXBuffer *errors_and_warnings = NULL; + struct + { + const D3DXVECTOR3 *vertices; + const DWORD *indices; + const UINT num_vertices; + const UINT num_faces; + const DWORD *adjacency; + const HRESULT exp_hr; + } + tc[] = + { + { + vertices0, + indices0, + num_vertices0, + num_faces0, + adjacency0, + exp_hr0, + }, + { + vertices1, + indices1, + num_vertices1, + num_faces1, + adjacency1, + exp_hr1, + }, + }; + + test_context = new_test_context(); + if (!test_context) + { + skip("Couldn't create test context\n"); + goto cleanup; + } + + for (i = 0; i < ARRAY_SIZE(tc); i++) + { + hr = init_test_mesh(tc[i].num_faces, tc[i].num_vertices, + options, declaration, + test_context->device, &mesh, + tc[i].vertices, vertex_size, + tc[i].indices, NULL); + if (FAILED(hr)) + { + skip("Couldn't initialize test mesh %d. Got %x expected D3D_OK\n", i, hr); + goto cleanup; + } + + hr = D3DXValidMesh(mesh, tc[i].adjacency, &errors_and_warnings); + todo_wine ok(hr == tc[i].exp_hr, "D3DXValidMesh test case %d failed. " + "Got %x\n, expected %x\n", i, hr, tc[i].exp_hr); + + /* Note errors_and_warnings is deliberately not checked because that + * would require copying wast amounts of the text output. */ + if (errors_and_warnings) + { + ID3DXBuffer_Release(errors_and_warnings); + errors_and_warnings = NULL; + } + mesh->lpVtbl->Release(mesh); + mesh = NULL; + } + +cleanup: + if (mesh) mesh->lpVtbl->Release(mesh); + free_test_context(test_context); +} + +static void test_optimize_faces(void) +{ + HRESULT hr; + UINT i; + DWORD smallest_face_remap; + /* mesh0 + * + * 0--1 + * | / + * |/ + * 2 + */ + const DWORD indices0[] = {0, 1, 2}; + const UINT num_faces0 = 1; + const UINT num_vertices0 = 3; + const DWORD exp_face_remap0[] = {0}; + /* mesh1 + * + * 0--1 3 + * | / /| + * |/ / | + * 2 5--4 + */ + const DWORD indices1[] = {0, 1, 2, 3, 4, 5}; + const UINT num_faces1 = 2; + const UINT num_vertices1 = 6; + const DWORD exp_face_remap1[] = {1, 0}; + /* mesh2 + * + * 0--1 + * | /| + * |/ | + * 2--3 + */ + const DWORD indices2[] = {0, 1, 2, 1, 3, 2}; + const UINT num_faces2 = 2; + const UINT num_vertices2 = 4; + const DWORD exp_face_remap2[] = {1, 0}; + /* mesh3 + * + * 0--1 + * | /| + * |/ | + * 2--3 + * | /| + * |/ | + * 4--5 + */ + const DWORD indices3[] = {0, 1, 2, 1, 3, 2, 2, 3, 4, 3, 4, 5}; + const UINT num_faces3 = 4; + const UINT num_vertices3 = 6; + const DWORD exp_face_remap3[] = {3, 2, 1, 0}; + /* mesh4 + * + * 0--1 + * | /| + * |/ | + * 2--3 + * | /| + * |/ | + * 4--5 + */ + const WORD indices4[] = {0, 1, 2, 1, 3, 2, 2, 3, 4, 3, 4, 5}; + const UINT num_faces4 = 4; + const UINT num_vertices4 = 6; + const DWORD exp_face_remap4[] = {3, 2, 1, 0}; + /* Test cases are stored in the tc array */ + struct + { + const VOID *indices; + const UINT num_faces; + const UINT num_vertices; + const BOOL indices_are_32bit; + const DWORD *exp_face_remap; + } + tc[] = + { + { + indices0, + num_faces0, + num_vertices0, + TRUE, + exp_face_remap0 + }, + { + indices1, + num_faces1, + num_vertices1, + TRUE, + exp_face_remap1 + }, + { + indices2, + num_faces2, + num_vertices2, + TRUE, + exp_face_remap2 + }, + { + indices3, + num_faces3, + num_vertices3, + TRUE, + exp_face_remap3 + }, + { + indices4, + num_faces4, + num_vertices4, + FALSE, + exp_face_remap4 + }, + }; + + /* Go through all test cases */ + for (i = 0; i < ARRAY_SIZE(tc); i++) + { + DWORD j; + DWORD *face_remap; + face_remap = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, + tc[i].num_faces*sizeof(*face_remap)); + + hr = D3DXOptimizeFaces(tc[i].indices, tc[i].num_faces, + tc[i].num_vertices, tc[i].indices_are_32bit, + face_remap); + ok(hr == D3D_OK, "D3DXOptimizeFaces test case %d failed. " + "Got %x\n, expected D3D_OK\n", i, hr); + + /* Compare face remap with expected face remap */ + for (j = 0; j < tc[i].num_faces; j++) + { + ok(tc[i].exp_face_remap[j] == face_remap[j], + "Test case %d: Got face %d at %d, expected %d\n", i, + face_remap[j], j, tc[i].exp_face_remap[j]); + } + + HeapFree(GetProcessHeap(), 0, face_remap); + } + + /* face_remap must not be NULL */ + hr = D3DXOptimizeFaces(tc[0].indices, tc[0].num_faces, + tc[0].num_vertices, tc[0].indices_are_32bit, + NULL); + ok(hr == D3DERR_INVALIDCALL, "D3DXOptimizeFaces passed NULL face_remap " + "pointer. Got %x\n, expected D3DERR_INVALIDCALL\n", hr); + + /* Number of faces must be smaller than 2^15 */ + hr = D3DXOptimizeFaces(tc[0].indices, 2 << 15, + tc[0].num_vertices, FALSE, + &smallest_face_remap); + ok(hr == D3DERR_INVALIDCALL, "D3DXOptimizeFaces should not accept 2^15 " + "faces when using 16-bit indices. Got %x\n, expected D3DERR_INVALIDCALL\n", hr); +} + +static HRESULT clear_normals(ID3DXMesh *mesh) +{ + HRESULT hr; + BYTE *vertices; + size_t normal_size; + DWORD i, num_vertices, vertex_stride; + const D3DXVECTOR4 normal = {NAN, NAN, NAN, NAN}; + D3DVERTEXELEMENT9 *normal_declaration = NULL; + D3DVERTEXELEMENT9 declaration[MAX_FVF_DECL_SIZE] = {D3DDECL_END()}; + + if (FAILED(hr = mesh->lpVtbl->GetDeclaration(mesh, declaration))) + return hr; + + for (i = 0; declaration[i].Stream != 0xff; i++) + { + if (declaration[i].Usage == D3DDECLUSAGE_NORMAL && !declaration[i].UsageIndex) + { + normal_declaration = &declaration[i]; + break; + } + } + + if (!normal_declaration) + return D3DERR_INVALIDCALL; + + if (normal_declaration->Type == D3DDECLTYPE_FLOAT3) + { + normal_size = sizeof(D3DXVECTOR3); + } + else if (normal_declaration->Type == D3DDECLTYPE_FLOAT4) + { + normal_size = sizeof(D3DXVECTOR4); + } + else + { + trace("Cannot clear normals\n"); + return E_NOTIMPL; + } + + num_vertices = mesh->lpVtbl->GetNumVertices(mesh); + vertex_stride = mesh->lpVtbl->GetNumBytesPerVertex(mesh); + + if (FAILED(hr = mesh->lpVtbl->LockVertexBuffer(mesh, 0, (void **)&vertices))) + return hr; + + vertices += normal_declaration->Offset; + + for (i = 0; i < num_vertices; i++, vertices += vertex_stride) + memcpy(vertices, &normal, normal_size); + + return mesh->lpVtbl->UnlockVertexBuffer(mesh); +} + +static void compare_normals(unsigned int line, const char *test_name, + ID3DXMesh *mesh, const D3DXVECTOR3 *normals, unsigned int num_normals) +{ + unsigned int i; + BYTE *vertices; + DWORD num_vertices, vertex_stride; + D3DVERTEXELEMENT9 *normal_declaration = NULL; + D3DVERTEXELEMENT9 declaration[MAX_FVF_DECL_SIZE] = {D3DDECL_END()}; + + if (FAILED(mesh->lpVtbl->GetDeclaration(mesh, declaration))) + { + ok_(__FILE__, line)(0, "%s: Failed to get declaration\n", test_name); + return; + } + + for (i = 0; declaration[i].Stream != 0xff; i++) + { + if (declaration[i].Usage == D3DDECLUSAGE_NORMAL && !declaration[i].UsageIndex) + { + normal_declaration = &declaration[i]; + break; + } + } + + if (!normal_declaration) + { + ok_(__FILE__, line)(0, "%s: Mesh has no normals\n", test_name); + return; + } + + if (normal_declaration->Type != D3DDECLTYPE_FLOAT3 && normal_declaration->Type != D3DDECLTYPE_FLOAT4) + { + ok_(__FILE__, line)(0, "%s: Mesh has invalid normals type\n", test_name); + return; + } + + num_vertices = mesh->lpVtbl->GetNumVertices(mesh); + vertex_stride = mesh->lpVtbl->GetNumBytesPerVertex(mesh); + + ok_(__FILE__, line)(num_vertices == num_normals, "%s: Expected %u vertices, got %u\n", test_name, + num_normals, num_vertices); + + if (FAILED(mesh->lpVtbl->LockVertexBuffer(mesh, 0, (void **)&vertices))) + { + ok_(__FILE__, line)(0, "%s: Failed to compare normals\n", test_name); + return; + } + + vertices += normal_declaration->Offset; + + for (i = 0; i < min(num_vertices, num_normals); i++, vertices += vertex_stride) + { + if (normal_declaration->Type == D3DDECLTYPE_FLOAT3) + { + const D3DXVECTOR3 *n = (D3DXVECTOR3 *)vertices; + ok_(__FILE__, line)(compare_vec3(*n, normals[i]), + "%s: normal %2u, expected (%f, %f, %f), got (%f, %f, %f)\n", + test_name, i, normals[i].x, normals[i].y, normals[i].z, n->x, n->y, n->z); + } + else + { + const D3DXVECTOR4 *n = (D3DXVECTOR4 *)vertices; + const D3DXVECTOR4 normal = {normals[i].x, normals[i].y, normals[i].z, 1.0f}; + ok_(__FILE__, line)(compare_vec4(*n, normal), + "%s: normal %2u, expected (%f, %f, %f, %f), got (%f, %f, %f, %f)\n", + test_name, i, normals[i].x, normals[i].y, normals[i].z, 1.0f, + n->x, n->y, n->z, n->w); + } + } + + mesh->lpVtbl->UnlockVertexBuffer(mesh); +} + +static HRESULT compute_normals_D3DXComputeNormals(ID3DXMesh *mesh, const DWORD *adjacency) +{ + return D3DXComputeNormals((ID3DXBaseMesh *)mesh, adjacency); +} + +static HRESULT compute_normals_D3DXComputeTangentFrameEx(ID3DXMesh *mesh, const DWORD *adjacency) +{ + return D3DXComputeTangentFrameEx(mesh, D3DX_DEFAULT, 0, D3DX_DEFAULT, 0, D3DX_DEFAULT, 0, + D3DDECLUSAGE_NORMAL, 0, D3DXTANGENT_GENERATE_IN_PLACE | D3DXTANGENT_CALCULATE_NORMALS, + adjacency, -1.01f, -0.01f, -1.01f, NULL, NULL); +} + +static void test_compute_normals(void) +{ + HRESULT hr; + ULONG refcount; + ID3DXMesh *mesh, *cloned_mesh; + ID3DXBuffer *adjacency; + IDirect3DDevice9 *device; + struct test_context *test_context; + unsigned int i; + + static const struct compute_normals_func + { + const char *name; + HRESULT (*apply)(ID3DXMesh *mesh, const DWORD *adjacency); + } + compute_normals_funcs[] = + { + {"D3DXComputeNormals", compute_normals_D3DXComputeNormals }, + {"D3DXComputeTangentFrameEx", compute_normals_D3DXComputeTangentFrameEx} + }; + + static const D3DXVECTOR3 box_normals[24] = + { + {-1.0f, 0.0f, 0.0f}, {-1.0f, 0.0f, 0.0f}, {-1.0f, 0.0f, 0.0f}, {-1.0f, 0.0f, 0.0f}, + { 0.0f, 1.0f, 0.0f}, { 0.0f, 1.0f, 0.0f}, { 0.0f, 1.0f, 0.0f}, { 0.0f, 1.0f, 0.0f}, + { 1.0f, 0.0f, 0.0f}, { 1.0f, 0.0f, 0.0f}, { 1.0f, 0.0f, 0.0f}, { 1.0f, 0.0f, 0.0f}, + { 0.0f,-1.0f, 0.0f}, { 0.0f,-1.0f, 0.0f}, { 0.0f,-1.0f, 0.0f}, { 0.0f,-1.0f, 0.0f}, + { 0.0f, 0.0f, 1.0f}, { 0.0f, 0.0f, 1.0f}, { 0.0f, 0.0f, 1.0f}, { 0.0f, 0.0f, 1.0f}, + { 0.0f, 0.0f,-1.0f}, { 0.0f, 0.0f,-1.0f}, { 0.0f, 0.0f,-1.0f}, { 0.0f, 0.0f,-1.0f} + }; + const float box_normal_component = 1.0f / sqrtf(3.0f); + const D3DXVECTOR3 box_normals_adjacency[24] = + { + {-box_normal_component, -box_normal_component, -box_normal_component}, + {-box_normal_component, -box_normal_component, box_normal_component}, + {-box_normal_component, box_normal_component, box_normal_component}, + {-box_normal_component, box_normal_component, -box_normal_component}, + {-box_normal_component, box_normal_component, -box_normal_component}, + {-box_normal_component, box_normal_component, box_normal_component}, + { box_normal_component, box_normal_component, box_normal_component}, + { box_normal_component, box_normal_component, -box_normal_component}, + { box_normal_component, box_normal_component, -box_normal_component}, + { box_normal_component, box_normal_component, box_normal_component}, + { box_normal_component, -box_normal_component, box_normal_component}, + { box_normal_component, -box_normal_component, -box_normal_component}, + {-box_normal_component, -box_normal_component, box_normal_component}, + {-box_normal_component, -box_normal_component, -box_normal_component}, + { box_normal_component, -box_normal_component, -box_normal_component}, + { box_normal_component, -box_normal_component, box_normal_component}, + {-box_normal_component, -box_normal_component, box_normal_component}, + { box_normal_component, -box_normal_component, box_normal_component}, + { box_normal_component, box_normal_component, box_normal_component}, + {-box_normal_component, box_normal_component, box_normal_component}, + {-box_normal_component, -box_normal_component, -box_normal_component}, + {-box_normal_component, box_normal_component, -box_normal_component}, + { box_normal_component, box_normal_component, -box_normal_component}, + { box_normal_component, -box_normal_component, -box_normal_component} + }; + static const D3DXVECTOR3 box_normals_adjacency_area[24] = + { + {-0.666667f, -0.333333f, -0.666667f}, {-0.333333f, -0.666667f, 0.666667f}, + {-0.816496f, 0.408248f, 0.408248f}, {-0.408248f, 0.816496f, -0.408248f}, + {-0.408248f, 0.816496f, -0.408248f}, {-0.816496f, 0.408248f, 0.408248f}, + { 0.333333f, 0.666667f, 0.666667f}, { 0.666667f, 0.333333f, -0.666667f}, + { 0.666667f, 0.333333f, -0.666667f}, { 0.333333f, 0.666667f, 0.666667f}, + { 0.816496f, -0.408248f, 0.408248f}, { 0.408248f, -0.816496f, -0.408248f}, + {-0.333333f, -0.666667f, 0.666667f}, {-0.666667f, -0.333333f, -0.666667f}, + { 0.408248f, -0.816496f, -0.408248f}, { 0.816496f, -0.408248f, 0.408248f}, + {-0.333333f, -0.666667f, 0.666667f}, { 0.816497f, -0.408248f, 0.408248f}, + { 0.333333f, 0.666667f, 0.666667f}, {-0.816497f, 0.408248f, 0.408248f}, + {-0.666667f, -0.333333f, -0.666667f}, {-0.408248f, 0.816497f, -0.408248f}, + { 0.666667f, 0.333333f, -0.666667f}, { 0.408248f, -0.816496f, -0.408248f} + }; + static const D3DXVECTOR3 box_normals_position1f[24] = {{0}}; + static const D3DXVECTOR3 box_normals_position2f[24] = + { + {0.0f, 0.0f, -1.0f}, {0.0f, 0.0f, 1.0f}, {0.0f, 0.0f, 1.0f}, + {0.0f, 0.0f, -1.0f}, {0.0f, 0.0f, -1.0f}, {0.0f, 0.0f, 1.0f}, + {0.0f, 0.0f, 1.0f}, {0.0f, 0.0f, -1.0f}, {0.0f, 0.0f, -1.0f}, + {0.0f, 0.0f, 1.0f}, {0.0f, 0.0f, 1.0f}, {0.0f, 0.0f, -1.0f}, + {0.0f, 0.0f, 1.0f}, {0.0f, 0.0f, -1.0f}, {0.0f, 0.0f, -1.0f}, + {0.0f, 0.0f, 1.0f}, {0.0f, 0.0f, 1.0f}, {0.0f, 0.0f, 1.0f}, + {0.0f, 0.0f, 1.0f}, {0.0f, 0.0f, 1.0f}, {0.0f, 0.0f, -1.0f}, + {0.0f, 0.0f, -1.0f}, {0.0f, 0.0f, -1.0f}, {0.0f, 0.0f, -1.0f} + }; + + static const D3DXVECTOR3 sphere_normals[22] = + { + { 0.000000f, -0.000000f, 1.000000f}, { 0.000000f, 0.582244f, 0.813014f}, + { 0.582244f, -0.000000f, 0.813014f}, {-0.000000f, -0.582244f, 0.813014f}, + {-0.582244f, 0.000000f, 0.813014f}, {-0.000000f, 0.890608f, 0.454772f}, + { 0.890608f, 0.000000f, 0.454772f}, { 0.000000f, -0.890608f, 0.454772f}, + {-0.890608f, -0.000000f, 0.454772f}, { 0.000000f, 1.000000f, -0.000000f}, + { 1.000000f, -0.000000f, -0.000000f}, {-0.000000f, -1.000000f, -0.000000f}, + {-1.000000f, 0.000000f, -0.000000f}, { 0.000000f, 0.890608f, -0.454773f}, + { 0.890608f, -0.000000f, -0.454772f}, {-0.000000f, -0.890608f, -0.454773f}, + {-0.890608f, 0.000000f, -0.454773f}, { 0.000000f, 0.582244f, -0.813015f}, + { 0.582244f, -0.000000f, -0.813015f}, { 0.000000f, -0.582244f, -0.813015f}, + {-0.582243f, 0.000000f, -0.813015f}, { 0.000000f, 0.000000f, -1.000000f} + }; + static const D3DXVECTOR3 sphere_normals_area[22] = + { + { 0.000000f, -0.000000f, 1.000000f}, {-0.215311f, 0.554931f, 0.803550f}, + { 0.554931f, 0.215311f, 0.803550f}, { 0.215311f, -0.554931f, 0.803550f}, + {-0.554931f, -0.215311f, 0.803550f}, {-0.126638f, 0.872121f, 0.472618f}, + { 0.872121f, 0.126638f, 0.472618f}, { 0.126638f, -0.872121f, 0.472618f}, + {-0.872121f, -0.126637f, 0.472618f}, { 0.000000f, 1.000000f, -0.000000f}, + { 1.000000f, -0.000000f, -0.000000f}, {-0.000000f, -1.000000f, -0.000000f}, + {-1.000000f, 0.000000f, -0.000000f}, { 0.126638f, 0.872121f, -0.472618f}, + { 0.872121f, -0.126638f, -0.472618f}, {-0.126638f, -0.872121f, -0.472618f}, + {-0.872121f, 0.126638f, -0.472618f}, { 0.215311f, 0.554931f, -0.803550f}, + { 0.554931f, -0.215311f, -0.803550f}, {-0.215311f, -0.554931f, -0.803550f}, + {-0.554931f, 0.215311f, -0.803550f}, { 0.000000f, 0.000000f, -1.000000f} + }; + static const D3DXVECTOR3 sphere_normals_equal[22] = + { + { 0.000000f, -0.000000f, 1.000000f}, {-0.134974f, 0.522078f, 0.842150f}, + { 0.522078f, 0.134974f, 0.842150f}, { 0.134974f, -0.522078f, 0.842150f}, + {-0.522078f, -0.134974f, 0.842150f}, {-0.026367f, 0.857121f, 0.514440f}, + { 0.857121f, 0.026367f, 0.514440f}, { 0.026367f, -0.857121f, 0.514440f}, + {-0.857121f, -0.026367f, 0.514440f}, { 0.000000f, 1.000000f, -0.000000f}, + { 1.000000f, -0.000000f, -0.000000f}, {-0.000000f, -1.000000f, -0.000000f}, + {-1.000000f, 0.000000f, -0.000000f}, { 0.026367f, 0.857121f, -0.514440f}, + { 0.857121f, -0.026367f, -0.514440f}, {-0.026367f, -0.857121f, -0.514440f}, + {-0.857121f, 0.026367f, -0.514440f}, { 0.134975f, 0.522078f, -0.842150f}, + { 0.522078f, -0.134975f, -0.842150f}, {-0.134974f, -0.522078f, -0.842150f}, + {-0.522078f, 0.134974f, -0.842150f}, { 0.000000f, 0.000000f, -1.000000f} + }; + + static const D3DVERTEXELEMENT9 position3f_normal1f_declaration[] = + { + {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0}, + {0, sizeof(D3DXVECTOR3), D3DDECLTYPE_FLOAT1, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL, 0}, + D3DDECL_END() + }; + static const D3DVERTEXELEMENT9 position3f_normal2f_declaration[] = + { + {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0}, + {0, sizeof(D3DXVECTOR3), D3DDECLTYPE_FLOAT2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL, 0}, + D3DDECL_END() + }; + static const D3DVERTEXELEMENT9 normal4f_position3f_declaration[] = + { + {0, 0, D3DDECLTYPE_FLOAT4, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL, 0}, + {0, sizeof(D3DXVECTOR4), D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0}, + D3DDECL_END() + }; + static const D3DVERTEXELEMENT9 position1f_normal3f_declaration[] = + { + {0, 0, D3DDECLTYPE_FLOAT1, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0}, + {0, sizeof(float), D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL, 0}, + D3DDECL_END() + }; + static const D3DVERTEXELEMENT9 position2f_normal3f_declaration[] = + { + {0, 0, D3DDECLTYPE_FLOAT2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0}, + {0, sizeof(D3DXVECTOR2), D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL, 0}, + D3DDECL_END() + }; + static const D3DVERTEXELEMENT9 position4f_normal3f_declaration[] = + { + {0, 0, D3DDECLTYPE_FLOAT4, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0}, + {0, sizeof(D3DXVECTOR4), D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL, 0}, + D3DDECL_END() + }; + + for (i = 0; i < ARRAY_SIZE(compute_normals_funcs); i++) + { + hr = compute_normals_funcs[i].apply(NULL, NULL); + ok(hr == D3DERR_INVALIDCALL, "%s returned %#x, expected D3DERR_INVALIDCALL\n", compute_normals_funcs[i].name, hr); + } + + if (!(test_context = new_test_context())) + { + skip("Couldn't create test context\n"); + return; + } + device = test_context->device; + + hr = D3DXCreateBox(device, 1.0f, 1.0f, 1.0f, &mesh, &adjacency); + ok(SUCCEEDED(hr), "D3DXCreateBox failed %#x\n", hr); + + /* Check wrong input */ + hr = D3DXComputeTangentFrameEx(mesh, D3DX_DEFAULT, 0, D3DX_DEFAULT, 0, D3DX_DEFAULT, 0, + D3DDECLUSAGE_NORMAL, 0, D3DXTANGENT_GENERATE_IN_PLACE, NULL, -1.01f, -0.01f, -1.01f, NULL, NULL); + todo_wine ok(hr == D3DERR_INVALIDCALL, "D3DXComputeTangentFrameEx returned %#x, expected D3DERR_INVALIDCALL\n", hr); + + hr = D3DXComputeTangentFrameEx(mesh, D3DX_DEFAULT, 0, D3DX_DEFAULT, 0, D3DX_DEFAULT, 0, D3DDECLUSAGE_NORMAL, 0, + D3DXTANGENT_GENERATE_IN_PLACE | D3DXTANGENT_CALCULATE_NORMALS | D3DXTANGENT_WEIGHT_BY_AREA | D3DXTANGENT_WEIGHT_EQUAL, + NULL, -1.01f, -0.01f, -1.01f, NULL, NULL); + ok(hr == D3DERR_INVALIDCALL, "D3DXComputeTangentFrameEx returned %#x, expected D3DERR_INVALIDCALL\n", hr); + + hr = D3DXComputeTangentFrameEx(mesh, D3DX_DEFAULT, 0, D3DX_DEFAULT, 0, D3DX_DEFAULT, 0, + D3DDECLUSAGE_NORMAL, 0, 0, NULL, -1.01f, -0.01f, -1.01f, NULL, NULL); + todo_wine ok(hr == D3DERR_INVALIDCALL, "D3DXComputeTangentFrameEx returned %#x, expected D3DERR_INVALIDCALL\n", hr); + + hr = D3DXComputeTangentFrameEx(mesh, D3DX_DEFAULT, 0, D3DX_DEFAULT, 0, D3DX_DEFAULT, 0, + D3DDECLUSAGE_NORMAL, 1, D3DXTANGENT_GENERATE_IN_PLACE | D3DXTANGENT_CALCULATE_NORMALS, + NULL, -1.01f, -0.01f, -1.01f, NULL, NULL); + ok(hr == D3DERR_INVALIDCALL, "D3DXComputeTangentFrameEx returned %#x, expected D3DERR_INVALIDCALL\n", hr); + + hr = D3DXComputeTangentFrameEx(mesh, D3DX_DEFAULT, 0, D3DX_DEFAULT, 0, D3DX_DEFAULT, 0, + D3DX_DEFAULT, 0, D3DXTANGENT_GENERATE_IN_PLACE | D3DXTANGENT_CALCULATE_NORMALS, + NULL, -1.01f, -0.01f, -1.01f, NULL, NULL); + ok(hr == D3DERR_INVALIDCALL, "D3DXComputeTangentFrameEx returned %#x, expected D3DERR_INVALIDCALL\n", hr); + + hr = D3DXComputeTangentFrameEx(mesh, D3DX_DEFAULT, 0, D3DX_DEFAULT, 0, D3DX_DEFAULT, 0, + D3DDECLUSAGE_NORMAL, 0, D3DXTANGENT_CALCULATE_NORMALS, + NULL, -1.01f, -0.01f, -1.01f, NULL, NULL); + todo_wine ok(hr == D3DERR_INVALIDCALL, "D3DXComputeTangentFrameEx returned %#x, expected D3DERR_INVALIDCALL\n", hr); + + for (i = 0; i < ARRAY_SIZE(compute_normals_funcs); i++) + { + const struct compute_normals_func *func = &compute_normals_funcs[i]; + + /* Mesh without normals */ + hr = mesh->lpVtbl->CloneMeshFVF(mesh, 0, D3DFVF_XYZ, device, &cloned_mesh); + ok(SUCCEEDED(hr), "CloneMeshFVF failed %#x\n", hr); + + hr = func->apply(cloned_mesh, NULL); + ok(hr == D3DERR_INVALIDCALL, "%s returned %#x, expected D3DERR_INVALIDCALL\n", func->name, hr); + + refcount = cloned_mesh->lpVtbl->Release(cloned_mesh); + ok(!refcount, "Mesh has %u references left\n", refcount); + + /* Mesh without positions */ + hr = mesh->lpVtbl->CloneMeshFVF(mesh, 0, D3DFVF_NORMAL, device, &cloned_mesh); + ok(SUCCEEDED(hr), "CloneMeshFVF failed %#x\n", hr); + + hr = func->apply(cloned_mesh, NULL); + ok(hr == D3DERR_INVALIDCALL, "%s returned %#x, expected D3DERR_INVALIDCALL\n", func->name, hr); + + refcount = cloned_mesh->lpVtbl->Release(cloned_mesh); + ok(!refcount, "Mesh has %u references left\n", refcount); + + /* Mesh with D3DDECLTYPE_FLOAT1 normals */ + hr = mesh->lpVtbl->CloneMesh(mesh, 0, position3f_normal1f_declaration, device, &cloned_mesh); + ok(SUCCEEDED(hr), "CloneMesh failed %#x\n", hr); + + hr = func->apply(cloned_mesh, NULL); + ok(hr == D3DERR_INVALIDCALL, "%s returned %#x, expected D3DERR_INVALIDCALL\n", func->name, hr); + + refcount = cloned_mesh->lpVtbl->Release(cloned_mesh); + ok(!refcount, "Mesh has %u references left\n", refcount); + + /* Mesh with D3DDECLTYPE_FLOAT2 normals */ + hr = mesh->lpVtbl->CloneMesh(mesh, 0, position3f_normal2f_declaration, device, &cloned_mesh); + ok(SUCCEEDED(hr), "CloneMesh failed %#x\n", hr); + + hr = func->apply(cloned_mesh, NULL); + ok(hr == D3DERR_INVALIDCALL, "%s returned %#x, expected D3DERR_INVALIDCALL\n", func->name, hr); + + refcount = cloned_mesh->lpVtbl->Release(cloned_mesh); + ok(!refcount, "Mesh has %u references left\n", refcount); + + /* Mesh without adjacency data */ + hr = clear_normals(mesh); + ok(SUCCEEDED(hr), "Failed to clear normals, returned %#x\n", hr); + + hr = func->apply(mesh, NULL); + ok(hr == D3D_OK, "%s returned %#x, expected D3D_OK\n", func->name, hr); + + compare_normals(__LINE__, func->name, mesh, box_normals, ARRAY_SIZE(box_normals)); + + /* Mesh with adjacency data */ + hr = clear_normals(mesh); + ok(SUCCEEDED(hr), "Failed to clear normals, returned %#x\n", hr); + + hr = func->apply(mesh, ID3DXBuffer_GetBufferPointer(adjacency)); + ok(hr == D3D_OK, "%s returned %#x, expected D3D_OK\n", func->name, hr); + + compare_normals(__LINE__, func->name, mesh, box_normals_adjacency, ARRAY_SIZE(box_normals_adjacency)); + + /* Mesh with custom vertex format, D3DDECLTYPE_FLOAT4 normals and adjacency */ + hr = mesh->lpVtbl->CloneMesh(mesh, 0, normal4f_position3f_declaration, device, &cloned_mesh); + ok(SUCCEEDED(hr), "CloneMesh failed %#x\n", hr); + + hr = clear_normals(cloned_mesh); + ok(SUCCEEDED(hr), "Failed to clear normals, returned %#x\n", hr); + + hr = func->apply(cloned_mesh, ID3DXBuffer_GetBufferPointer(adjacency)); + ok(hr == D3D_OK, "%s returned %#x, expected D3D_OK\n", func->name, hr); + + compare_normals(__LINE__, func->name, cloned_mesh, box_normals_adjacency, ARRAY_SIZE(box_normals_adjacency)); + + refcount = cloned_mesh->lpVtbl->Release(cloned_mesh); + ok(!refcount, "Mesh has %u references left\n", refcount); + + /* Mesh with D3DDECLTYPE_FLOAT1 positions and D3DDECLTYPE_FLOAT3 normals */ + hr = mesh->lpVtbl->CloneMesh(mesh, 0, position1f_normal3f_declaration, device, &cloned_mesh); + ok(SUCCEEDED(hr), "CloneMesh failed %#x\n", hr); + + hr = clear_normals(cloned_mesh); + ok(SUCCEEDED(hr), "Failed to clear normals, returned %#x\n", hr); + + hr = func->apply(cloned_mesh, ID3DXBuffer_GetBufferPointer(adjacency)); + ok(hr == D3D_OK, "%s returned %#x, expected D3D_OK\n", func->name, hr); + + compare_normals(__LINE__, func->name, cloned_mesh, box_normals_position1f, ARRAY_SIZE(box_normals_position1f)); + + refcount = cloned_mesh->lpVtbl->Release(cloned_mesh); + ok(!refcount, "Mesh has %u references left\n", refcount); + + /* Mesh with D3DDECLTYPE_FLOAT2 positions and D3DDECLTYPE_FLOAT3 normals */ + hr = mesh->lpVtbl->CloneMesh(mesh, 0, position2f_normal3f_declaration, device, &cloned_mesh); + ok(SUCCEEDED(hr), "CloneMesh failed %#x\n", hr); + + hr = clear_normals(cloned_mesh); + ok(SUCCEEDED(hr), "Failed to clear normals, returned %#x\n", hr); + + hr = func->apply(cloned_mesh, ID3DXBuffer_GetBufferPointer(adjacency)); + ok(hr == D3D_OK, "%s returned %#x, expected D3D_OK\n", func->name, hr); + + compare_normals(__LINE__, func->name, cloned_mesh, box_normals_position2f, ARRAY_SIZE(box_normals_position2f)); + + refcount = cloned_mesh->lpVtbl->Release(cloned_mesh); + ok(!refcount, "Mesh has %u references left\n", refcount); + + /* Mesh with D3DDECLTYPE_FLOAT4 positions and D3DDECLTYPE_FLOAT3 normals */ + hr = mesh->lpVtbl->CloneMesh(mesh, 0, position4f_normal3f_declaration, device, &cloned_mesh); + ok(SUCCEEDED(hr), "CloneMesh failed %#x\n", hr); + + hr = clear_normals(cloned_mesh); + ok(SUCCEEDED(hr), "Failed to clear normals, returned %#x\n", hr); + + hr = func->apply(cloned_mesh, ID3DXBuffer_GetBufferPointer(adjacency)); + ok(hr == D3D_OK, "%s returned %#x, expected D3D_OK\n", func->name, hr); + + compare_normals(__LINE__, func->name, cloned_mesh, box_normals_adjacency, ARRAY_SIZE(box_normals_adjacency)); + + refcount = cloned_mesh->lpVtbl->Release(cloned_mesh); + ok(!refcount, "Mesh has %u references left\n", refcount); + } + + hr = D3DXComputeTangentFrameEx(mesh, D3DX_DEFAULT, 0, D3DX_DEFAULT, 0, D3DX_DEFAULT, 0, + D3DDECLUSAGE_NORMAL, 0, D3DXTANGENT_GENERATE_IN_PLACE | D3DXTANGENT_CALCULATE_NORMALS | D3DXTANGENT_WEIGHT_BY_AREA, + NULL, -1.01f, -0.01f, -1.01f, NULL, NULL); + ok(hr == D3D_OK, "D3DXComputeTangentFrameEx returned %#x, expected D3D_OK\n", hr); + + compare_normals(__LINE__, "D3DXComputeTangentFrameEx", mesh, box_normals, ARRAY_SIZE(box_normals)); + + hr = D3DXComputeTangentFrameEx(mesh, D3DX_DEFAULT, 0, D3DX_DEFAULT, 0, D3DX_DEFAULT, 0, + D3DDECLUSAGE_NORMAL, 0, D3DXTANGENT_GENERATE_IN_PLACE | D3DXTANGENT_CALCULATE_NORMALS | D3DXTANGENT_WEIGHT_BY_AREA, + ID3DXBuffer_GetBufferPointer(adjacency), -1.01f, -0.01f, -1.01f, NULL, NULL); + ok(hr == D3D_OK, "D3DXComputeTangentFrameEx returned %#x, expected D3D_OK\n", hr); + + compare_normals(__LINE__, "D3DXComputeTangentFrameEx", mesh, box_normals_adjacency_area, ARRAY_SIZE(box_normals_adjacency_area)); + + hr = D3DXComputeTangentFrameEx(mesh, D3DX_DEFAULT, 0, D3DX_DEFAULT, 0, D3DX_DEFAULT, 0, + D3DDECLUSAGE_NORMAL, 0, D3DXTANGENT_GENERATE_IN_PLACE | D3DXTANGENT_CALCULATE_NORMALS | D3DXTANGENT_WEIGHT_EQUAL, + NULL, -1.01f, -0.01f, -1.01f, NULL, NULL); + ok(hr == D3D_OK, "D3DXComputeTangentFrameEx returned %#x, expected D3D_OK\n", hr); + + compare_normals(__LINE__, "D3DXComputeTangentFrameEx", mesh, box_normals, ARRAY_SIZE(box_normals)); + + hr = D3DXComputeTangentFrameEx(mesh, D3DX_DEFAULT, 0, D3DX_DEFAULT, 0, D3DX_DEFAULT, 0, + D3DDECLUSAGE_NORMAL, 0, D3DXTANGENT_GENERATE_IN_PLACE | D3DXTANGENT_CALCULATE_NORMALS | D3DXTANGENT_WEIGHT_EQUAL, + ID3DXBuffer_GetBufferPointer(adjacency), -1.01f, -0.01f, -1.01f, NULL, NULL); + ok(hr == D3D_OK, "D3DXComputeTangentFrameEx returned %#x, expected D3D_OK\n", hr); + + compare_normals(__LINE__, "D3DXComputeTangentFrameEx", mesh, box_normals_adjacency_area, ARRAY_SIZE(box_normals_adjacency_area)); + + refcount = mesh->lpVtbl->Release(mesh); + ok(!refcount, "Mesh has %u references left\n", refcount); + refcount = ID3DXBuffer_Release(adjacency); + ok(!refcount, "Buffer has %u references left\n", refcount); + + hr = D3DXCreateSphere(device, 1.0f, 4, 6, &mesh, &adjacency); + ok(SUCCEEDED(hr), "D3DXCreateSphere failed %#x\n", hr); + + for (i = 0; i < ARRAY_SIZE(compute_normals_funcs); i++) + { + const struct compute_normals_func *func = &compute_normals_funcs[i]; + + /* Sphere without adjacency data */ + hr = clear_normals(mesh); + ok(SUCCEEDED(hr), "Failed to clear normals, returned %#x\n", hr); + + hr = func->apply(mesh, NULL); + ok(hr == D3D_OK, "%s returned %#x, expected D3D_OK\n", func->name, hr); + + compare_normals(__LINE__, func->name, mesh, sphere_normals, ARRAY_SIZE(sphere_normals)); + + /* Sphere with adjacency data */ + hr = clear_normals(mesh); + ok(SUCCEEDED(hr), "Failed to clear normals, returned %#x\n", hr); + + hr = func->apply(mesh, ID3DXBuffer_GetBufferPointer(adjacency)); + ok(hr == D3D_OK, "%s returned %#x, expected D3D_OK\n", func->name, hr); + + compare_normals(__LINE__, func->name, mesh, sphere_normals, ARRAY_SIZE(sphere_normals)); + } + + hr = D3DXComputeTangentFrameEx(mesh, D3DX_DEFAULT, 0, D3DX_DEFAULT, 0, D3DX_DEFAULT, 0, + D3DDECLUSAGE_NORMAL, 0, D3DXTANGENT_GENERATE_IN_PLACE | D3DXTANGENT_CALCULATE_NORMALS | D3DXTANGENT_WEIGHT_BY_AREA, + NULL, -1.01f, -0.01f, -1.01f, NULL, NULL); + ok(hr == D3D_OK, "D3DXComputeTangentFrameEx returned %#x, expected D3D_OK\n", hr); + + compare_normals(__LINE__, "D3DXComputeTangentFrameEx", mesh, sphere_normals_area, ARRAY_SIZE(sphere_normals_area)); + + hr = D3DXComputeTangentFrameEx(mesh, D3DX_DEFAULT, 0, D3DX_DEFAULT, 0, D3DX_DEFAULT, 0, + D3DDECLUSAGE_NORMAL, 0, D3DXTANGENT_GENERATE_IN_PLACE | D3DXTANGENT_CALCULATE_NORMALS | D3DXTANGENT_WEIGHT_BY_AREA, + ID3DXBuffer_GetBufferPointer(adjacency), -1.01f, -0.01f, -1.01f, NULL, NULL); + ok(hr == D3D_OK, "D3DXComputeTangentFrameEx returned %#x, expected D3D_OK\n", hr); + + compare_normals(__LINE__, "D3DXComputeTangentFrameEx", mesh, sphere_normals_area, ARRAY_SIZE(sphere_normals_area)); + + hr = D3DXComputeTangentFrameEx(mesh, D3DX_DEFAULT, 0, D3DX_DEFAULT, 0, D3DX_DEFAULT, 0, + D3DDECLUSAGE_NORMAL, 0, D3DXTANGENT_GENERATE_IN_PLACE | D3DXTANGENT_CALCULATE_NORMALS | D3DXTANGENT_WEIGHT_EQUAL, + NULL, -1.01f, -0.01f, -1.01f, NULL, NULL); + ok(hr == D3D_OK, "D3DXComputeTangentFrameEx returned %#x, expected D3D_OK\n", hr); + + compare_normals(__LINE__, "D3DXComputeTangentFrameEx", mesh, sphere_normals_equal, ARRAY_SIZE(sphere_normals_equal)); + + hr = D3DXComputeTangentFrameEx(mesh, D3DX_DEFAULT, 0, D3DX_DEFAULT, 0, D3DX_DEFAULT, 0, + D3DDECLUSAGE_NORMAL, 0, D3DXTANGENT_GENERATE_IN_PLACE | D3DXTANGENT_CALCULATE_NORMALS | D3DXTANGENT_WEIGHT_EQUAL, + ID3DXBuffer_GetBufferPointer(adjacency), -1.01f, -0.01f, -1.01f, NULL, NULL); + ok(hr == D3D_OK, "D3DXComputeTangentFrameEx returned %#x, expected D3D_OK\n", hr); + + compare_normals(__LINE__, "D3DXComputeTangentFrameEx", mesh, sphere_normals_equal, ARRAY_SIZE(sphere_normals_equal)); + + refcount = mesh->lpVtbl->Release(mesh); + ok(!refcount, "Mesh has %u references left\n", refcount); + refcount = ID3DXBuffer_Release(adjacency); + ok(!refcount, "Buffer has %u references left\n", refcount); + + free_test_context(test_context); +} + +static void D3DXCreateAnimationControllerTest(void) +{ + HRESULT hr; + ID3DXAnimationController *animation; + UINT value; + + hr = D3DXCreateAnimationController(0, 0, 0, 0, NULL); + ok(hr == D3D_OK, "Got unexpected hr returned %#x.\n", hr); + + animation = (void*)0xdeadbeef; + hr = D3DXCreateAnimationController(0, 1, 1, 1, &animation); + ok(hr == D3D_OK, "Got unexpected hr returned %#x.\n", hr); + ok(animation == (void*)0xdeadbeef, "Got unexpected animation %p.\n", animation); + + animation = (void*)0xdeadbeef; + hr = D3DXCreateAnimationController(1, 0, 1, 1, &animation); + ok(hr == D3D_OK, "Got unexpected hr returned %#x.\n", hr); + ok(animation == (void*)0xdeadbeef, "Got unexpected animation %p.\n", animation); + + animation = (void*)0xdeadbeef; + hr = D3DXCreateAnimationController(1, 1, 0, 1, &animation); + ok(hr == D3D_OK, "Got unexpected hr returned %#x.\n", hr); + ok(animation == (void*)0xdeadbeef, "Got unexpected animation %p.\n", animation); + + animation = (void*)0xdeadbeef; + hr = D3DXCreateAnimationController(1, 1, 1, 0, &animation); + ok(hr == D3D_OK, "Got unexpected hr returned %#x.\n", hr); + ok(animation == (void*)0xdeadbeef, "Got unexpected animation %p.\n", animation); + + hr = D3DXCreateAnimationController(1, 1, 1, 1, &animation); + ok(hr == D3D_OK, "Got unexpected hr returned %#x.\n", hr); + + value = animation->lpVtbl->GetMaxNumAnimationOutputs(animation); + ok(value == 1, "Got unexpected value %u.\n", value); + + value = animation->lpVtbl->GetMaxNumAnimationSets(animation); + ok(value == 1, "Got unexpected value %u.\n", value); + + value = animation->lpVtbl->GetMaxNumTracks(animation); + ok(value == 1, "Got unexpected value %u.\n", value); + + value = animation->lpVtbl->GetMaxNumEvents(animation); + ok(value == 1, "Got unexpected value %u.\n", value); + + animation->lpVtbl->Release(animation); + + hr = D3DXCreateAnimationController(100, 101, 102, 103, &animation); + ok(hr == D3D_OK, "Got unexpected hr returned %#x.\n", hr); + + value = animation->lpVtbl->GetMaxNumAnimationOutputs(animation); + ok(value == 100, "Got unexpected value %u.\n", value); + + value = animation->lpVtbl->GetMaxNumAnimationSets(animation); + ok(value == 101, "Got unexpected value %u.\n", value); + + value = animation->lpVtbl->GetMaxNumTracks(animation); + ok(value == 102, "Got unexpected value %u.\n", value); + + value = animation->lpVtbl->GetMaxNumEvents(animation); + ok(value == 103, "Got unexpected value %u.\n", value); + + animation->lpVtbl->Release(animation); +} + +static void test_D3DXFrameFind(void) +{ + static char n1[] = "name1"; + static char n2[] = "name2"; + static char n3[] = "name3"; + static char n4[] = "name4"; + static char n5[] = "name5"; + static char n6[] = "name6"; + static char N1[] = "Name1"; + D3DXFRAME root, sibling, sibling2, child, *ret; + D3DXFRAME child2, child3; + + ret = D3DXFrameFind(NULL, NULL); + ok(ret == NULL, "Unexpected frame, %p.\n", ret); + + ret = D3DXFrameFind(NULL, "test"); + ok(ret == NULL, "Unexpected frame, %p.\n", ret); + + memset(&root, 0, sizeof(root)); + + ret = D3DXFrameFind(&root, NULL); + ok(ret == &root, "Unexpected frame, %p.\n", ret); + + root.Name = n1; + ret = D3DXFrameFind(&root, NULL); + ok(ret == NULL, "Unexpected frame, %p.\n", ret); + + ret = D3DXFrameFind(&root, n1); + ok(ret == &root, "Unexpected frame, %p.\n", ret); + + ret = D3DXFrameFind(&root, N1); + ok(ret == NULL, "Unexpected frame, %p.\n", ret); + + /* Test siblings order traversal. */ + memset(&sibling, 0, sizeof(sibling)); + sibling.Name = n2; + root.pFrameSibling = &sibling; + ret = D3DXFrameFind(&root, n2); + ok(ret == &sibling, "Unexpected frame, %p.\n", ret); + + memset(&sibling2, 0, sizeof(sibling2)); + sibling2.Name = n2; + sibling.pFrameSibling = &sibling2; + ret = D3DXFrameFind(&root, n2); + ok(ret == &sibling, "Unexpected frame, %p.\n", ret); + + sibling2.Name = n3; + ret = D3DXFrameFind(&root, n3); + ok(ret == &sibling2, "Unexpected frame, %p.\n", ret); + + /* Siblings first. */ + memset(&child, 0, sizeof(child)); + child.Name = n2; + root.pFrameFirstChild = &child; + ret = D3DXFrameFind(&root, n2); + ok(ret == &sibling, "Unexpected frame, %p.\n", ret); + + child.Name = n4; + ret = D3DXFrameFind(&root, n4); + ok(ret == &child, "Unexpected frame, %p.\n", ret); + + /* Link a grandchild and another one for sibling. */ + memset(&child2, 0, sizeof(child2)); + memset(&child3, 0, sizeof(child3)); + child2.Name = child3.Name = n5; + sibling.pFrameFirstChild = &child2; + child.pFrameFirstChild = &child3; + ret = D3DXFrameFind(&root, n5); + ok(ret == &child2, "Unexpected frame, %p.\n", ret); + + child3.Name = n6; + ret = D3DXFrameFind(&root, n6); + ok(ret == &child3, "Unexpected frame, %p.\n", ret); +} + +START_TEST(mesh) +{ + D3DXBoundProbeTest(); + D3DXComputeBoundingBoxTest(); + D3DXComputeBoundingSphereTest(); + D3DXGetFVFVertexSizeTest(); + D3DXIntersectTriTest(); + D3DXCreateMeshTest(); + D3DXCreateMeshFVFTest(); + D3DXLoadMeshTest(); + D3DXCreateBoxTest(); + D3DXCreatePolygonTest(); + D3DXCreateSphereTest(); + D3DXCreateCylinderTest(); + D3DXCreateTextTest(); + D3DXCreateTorusTest(); + D3DXCreateAnimationControllerTest(); + test_get_decl_length(); + test_get_decl_vertex_size(); + test_fvf_decl_conversion(); + D3DXGenerateAdjacencyTest(); + test_update_semantics(); + test_create_skin_info(); + test_convert_adjacency_to_point_reps(); + test_convert_point_reps_to_adjacency(); + test_weld_vertices(); + test_clone_mesh(); + test_valid_mesh(); + test_optimize_faces(); + test_compute_normals(); + test_D3DXFrameFind(); +} diff --git a/modules/rostests/winetests/d3dx9_36/res.vsh b/modules/rostests/winetests/d3dx9_36/res.vsh new file mode 100644 index 00000000000..9683748c112 --- /dev/null +++ b/modules/rostests/winetests/d3dx9_36/res.vsh @@ -0,0 +1,2 @@ +#define REGISTER r0 +vs.1.1 diff --git a/modules/rostests/winetests/d3dx9_36/resources.h b/modules/rostests/winetests/d3dx9_36/resources.h new file mode 100644 index 00000000000..44e64b371f0 --- /dev/null +++ b/modules/rostests/winetests/d3dx9_36/resources.h @@ -0,0 +1,28 @@ +/* + * Copyright 2009 Tony Wasserka + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA + */ + +#ifndef __WINE_D3DX9_36_TEST_RESOURCES_H +#define __WINE_D3DX9_36_TEST_RESOURCES_H + +#define IDB_BITMAP_1x1 10 +#define IDD_BITMAPDATA_1x1 11 +#define IDS_STRING 12 + +#define IDB_ASMSHADER 20 + +#endif /* __WINE_D3DX9_36_TEST_RESOURCES_H */ diff --git a/modules/rostests/winetests/d3dx9_36/rsrc.rc b/modules/rostests/winetests/d3dx9_36/rsrc.rc new file mode 100644 index 00000000000..6b282a2c1ea --- /dev/null +++ b/modules/rostests/winetests/d3dx9_36/rsrc.rc @@ -0,0 +1,31 @@ +/* + * Copyright 2009 Tony Wasserka + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA + */ + +#include "resources.h" + +STRINGTABLE +{ + IDS_STRING "nobitmap" +} + +/* @makedep: bmp1x1.bmp */ +IDB_BITMAP_1x1 BITMAP bmp1x1.bmp +IDD_BITMAPDATA_1x1 RCDATA bmp1x1.bmp + +/* @makedep: res.vsh */ +IDB_ASMSHADER RCDATA res.vsh diff --git a/modules/rostests/winetests/d3dx9_36/shader.c b/modules/rostests/winetests/d3dx9_36/shader.c new file mode 100644 index 00000000000..b67ffb209c4 --- /dev/null +++ b/modules/rostests/winetests/d3dx9_36/shader.c @@ -0,0 +1,6592 @@ +/* + * Copyright 2008 Luis Busquets + * Copyright 2011 Travis Athougies + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA + */ + +#include "wine/test.h" +#include "d3dx9.h" + +#define FCC_TEXT MAKEFOURCC('T','E','X','T') +#define FCC_CTAB MAKEFOURCC('C','T','A','B') + +static const DWORD shader_zero[] = {0x0}; + +static const DWORD shader_invalid[] = {0xeeee0100}; + +static const DWORD shader_empty[] = {0xfffe0200, 0x0000ffff}; + +static const DWORD simple_fx[] = {0x46580000, 0x0002fffe, FCC_TEXT, 0x00000000, 0x0000ffff}; + +static const DWORD simple_tx[] = {0x54580000, 0x0002fffe, FCC_TEXT, 0x00000000, 0x0000ffff}; + +static const DWORD simple_7ffe[] = {0x7ffe0000, 0x0002fffe, FCC_TEXT, 0x00000000, 0x0000ffff}; + +static const DWORD simple_7fff[] = {0x7fff0000, 0x0002fffe, FCC_TEXT, 0x00000000, 0x0000ffff}; + +static const DWORD simple_vs[] = { + 0xfffe0101, /* vs_1_1 */ + 0x0000001f, 0x80000000, 0x900f0000, /* dcl_position0 v0 */ + 0x00000009, 0xc0010000, 0x90e40000, 0xa0e40000, /* dp4 oPos.x, v0, c0 */ + 0x00000009, 0xc0020000, 0x90e40000, 0xa0e40001, /* dp4 oPos.y, v0, c1 */ + 0x00000009, 0xc0040000, 0x90e40000, 0xa0e40002, /* dp4 oPos.z, v0, c2 */ + 0x00000009, 0xc0080000, 0x90e40000, 0xa0e40003, /* dp4 oPos.w, v0, c3 */ + 0x0000ffff}; /* END */ + +static const DWORD simple_ps[] = { + 0xffff0101, /* ps_1_1 */ + 0x00000051, 0xa00f0001, 0x3f800000, 0x00000000, 0x00000000, 0x00000000, /* def c1 = 1.0, 0.0, 0.0, 0.0 */ + 0x00000042, 0xb00f0000, /* tex t0 */ + 0x00000008, 0x800f0000, 0xa0e40001, 0xa0e40000, /* dp3 r0, c1, c0 */ + 0x00000005, 0x800f0000, 0x90e40000, 0x80e40000, /* mul r0, v0, r0 */ + 0x00000005, 0x800f0000, 0xb0e40000, 0x80e40000, /* mul r0, t0, r0 */ + 0x0000ffff}; /* END */ + +static const DWORD shader_with_ctab[] = { + 0xfffe0300, /* vs_3_0 */ + 0x0002fffe, FCC_TEXT, 0x00000000, /* TEXT comment */ + 0x0008fffe, FCC_CTAB, 0x0000001c, 0x00000010, 0xfffe0300, 0x00000000, /* CTAB comment */ + 0x00000000, 0x00000000, 0x00000000, + 0x0004fffe, FCC_TEXT, 0x00000000, 0x00000000, 0x00000000, /* TEXT comment */ + 0x0000ffff}; /* END */ + +static const DWORD shader_with_invalid_ctab[] = { + 0xfffe0300, /* vs_3_0 */ + 0x0005fffe, FCC_CTAB, /* CTAB comment */ + 0x0000001c, 0x000000a9, 0xfffe0300, + 0x00000000, 0x00000000, + 0x0000ffff}; /* END */ + +static const DWORD shader_with_ctab_constants[] = { + 0xfffe0300, /* vs_3_0 */ + 0x002efffe, FCC_CTAB, /* CTAB comment */ + 0x0000001c, 0x000000a4, 0xfffe0300, 0x00000003, 0x0000001c, 0x20008100, /* Header */ + 0x0000009c, + 0x00000058, 0x00070002, 0x00000001, 0x00000064, 0x00000000, /* Constant 1 desc */ + 0x00000074, 0x00000002, 0x00000004, 0x00000080, 0x00000000, /* Constant 2 desc */ + 0x00000090, 0x00040002, 0x00000003, 0x00000080, 0x00000000, /* Constant 3 desc */ + 0x736e6f43, 0x746e6174, 0xabab0031, /* Constant 1 name string */ + 0x00030001, 0x00040001, 0x00000001, 0x00000000, /* Constant 1 type desc */ + 0x736e6f43, 0x746e6174, 0xabab0032, /* Constant 2 name string */ + 0x00030003, 0x00040004, 0x00000001, 0x00000000, /* Constant 2 & 3 type desc */ + 0x736e6f43, 0x746e6174, 0xabab0033, /* Constant 3 name string */ + 0x335f7376, 0xab00305f, /* Target name string */ + 0x656e6957, 0x6f727020, 0x7463656a, 0xababab00, /* Creator name string */ + 0x0000ffff}; /* END */ + +static const DWORD ctab_basic[] = { + 0xfffe0300, /* vs_3_0 */ + 0x0040fffe, FCC_CTAB, /* CTAB comment */ + 0x0000001c, 0x000000ec, 0xfffe0300, 0x00000005, 0x0000001c, 0x20008100, /* Header */ + 0x000000e4, + 0x00000080, 0x00060002, 0x00000001, 0x00000084, 0x00000000, /* Constant 1 desc (f) */ + 0x00000094, 0x00070002, 0x00000001, 0x00000098, 0x00000000, /* Constant 2 desc (f4) */ + 0x000000A8, 0x00040002, 0x00000001, 0x000000AC, 0x00000000, /* Constant 3 desc (i) */ + 0x000000BC, 0x00050002, 0x00000001, 0x000000C0, 0x00000000, /* Constant 4 desc (i4) */ + 0x000000D0, 0x00000002, 0x00000004, 0x000000D4, 0x00000000, /* Constant 5 desc (mvp) */ + 0xabab0066, 0x00030000, 0x00010001, 0x00000001, 0x00000000, /* Constant 1 name/type desc */ + 0xab003466, 0x00030001, 0x00040001, 0x00000001, 0x00000000, /* Constant 2 name/type desc */ + 0xabab0069, 0x00020000, 0x00010001, 0x00000001, 0x00000000, /* Constant 3 name/type desc */ + 0xab003469, 0x00020001, 0x00040001, 0x00000001, 0x00000000, /* Constant 4 name/type desc */ + 0x0070766d, 0x00030003, 0x00040004, 0x00000001, 0x00000000, /* Constant 5 name/type desc */ + 0x335f7376, 0xab00305f, /* Target name string */ + 0x656e6957, 0x6f727020, 0x7463656a, 0xababab00, /* Creator name string */ + 0x0000ffff}; /* END */ + +static const D3DXCONSTANT_DESC ctab_basic_expected[] = { + {"mvp", D3DXRS_FLOAT4, 0, 4, D3DXPC_MATRIX_COLUMNS, D3DXPT_FLOAT, 4, 4, 1, 0, 64, NULL}, + {"i", D3DXRS_FLOAT4, 4, 1, D3DXPC_SCALAR, D3DXPT_INT, 1, 1, 1, 0, 4, NULL}, + {"i4", D3DXRS_FLOAT4, 5, 1, D3DXPC_VECTOR, D3DXPT_INT, 1, 4, 1, 0, 16, NULL}, + {"f", D3DXRS_FLOAT4, 6, 1, D3DXPC_SCALAR, D3DXPT_FLOAT, 1, 1, 1, 0, 4, NULL}, + {"f4", D3DXRS_FLOAT4, 7, 1, D3DXPC_VECTOR, D3DXPT_FLOAT, 1, 4, 1, 0, 16, NULL}}; + +static const DWORD ctab_matrices[] = { + 0xfffe0300, /* vs_3_0 */ + 0x0032fffe, FCC_CTAB, /* CTAB comment */ + 0x0000001c, 0x000000b4, 0xfffe0300, 0x00000003, 0x0000001c, 0x20008100, /* Header */ + 0x000000ac, + 0x00000058, 0x00070002, 0x00000001, 0x00000064, 0x00000000, /* Constant 1 desc (fmatrix3x1) */ + 0x00000074, 0x00000002, 0x00000004, 0x00000080, 0x00000000, /* Constant 2 desc (fmatrix4x4) */ + 0x00000090, 0x00040002, 0x00000002, 0x0000009c, 0x00000000, /* Constant 3 desc (imatrix2x3) */ + 0x74616D66, 0x33786972, 0xab003178, /* Constant 1 name */ + 0x00030003, 0x00010003, 0x00000001, 0x00000000, /* Constant 1 type desc */ + 0x74616D66, 0x34786972, 0xab003478, /* Constant 2 name */ + 0x00030003, 0x00040004, 0x00000001, 0x00000000, /* Constant 2 type desc */ + 0x74616D69, 0x32786972, 0xab003378, /* Constant 3 name */ + 0x00020002, 0x00030002, 0x00000001, 0x00000000, /* Constant 3 type desc */ + 0x335f7376, 0xab00305f, /* Target name string */ + 0x656e6957, 0x6f727020, 0x7463656a, 0xababab00, /* Creator name string */ + 0x0000ffff}; /* END */ + +static const D3DXCONSTANT_DESC ctab_matrices_expected[] = { + {"fmatrix4x4", D3DXRS_FLOAT4, 0, 4, D3DXPC_MATRIX_COLUMNS, D3DXPT_FLOAT, 4, 4, 1, 0, 64, NULL}, + {"imatrix2x3", D3DXRS_FLOAT4, 4, 2, D3DXPC_MATRIX_ROWS, D3DXPT_INT, 2, 3, 1, 0, 24, NULL}, + {"fmatrix3x1", D3DXRS_FLOAT4, 7, 1, D3DXPC_MATRIX_COLUMNS, D3DXPT_FLOAT, 3, 1, 1, 0, 12, NULL}, +}; + +static const DWORD ctab_matrices2[] = { + 0xfffe0200, /* vs_2_0 */ + 0x0058fffe, FCC_CTAB, /* CTAB comment */ + 0x0000001c, 0x0000012b, 0xfffe0200, 0x00000006, 0x0000001c, 0x00000100, /* Header */ + 0x00000124, + 0x00000094, 0x00070002, 0x00000003, 0x0000009c, 0x00000000, /* Constant 1 desc (c2x3) */ + 0x000000ac, 0x000d0002, 0x00000002, 0x000000b4, 0x00000000, /* Constant 2 desc (c3x2) */ + 0x000000c4, 0x000a0002, 0x00000003, 0x000000cc, 0x00000000, /* Constant 3 desc (c3x3) */ + 0x000000dc, 0x000f0002, 0x00000002, 0x000000e4, 0x00000000, /* Constant 4 desc (r2x3) */ + 0x000000f4, 0x00040002, 0x00000003, 0x000000fc, 0x00000000, /* Constant 5 desc (r3x2) */ + 0x0000010c, 0x00000002, 0x00000004, 0x00000114, 0x00000000, /* Constant 6 desc (r4x4) */ + 0x33783263, 0xababab00, /* Constant 1 name */ + 0x00030003, 0x00030002, 0x00000001, 0x00000000, /* Constant 1 type desc */ + 0x32783363, 0xababab00, /* Constant 2 name */ + 0x00030003, 0x00020003, 0x00000001, 0x00000000, /* Constant 2 type desc */ + 0x33783363, 0xababab00, /* Constant 3 name */ + 0x00030003, 0x00030003, 0x00000001, 0x00000000, /* Constant 3 type desc */ + 0x33783272, 0xababab00, /* Constant 4 name */ + 0x00030002, 0x00030002, 0x00000001, 0x00000000, /* Constant 4 type desc */ + 0x32783372, 0xababab00, /* Constant 5 name */ + 0x00030002, 0x00020003, 0x00000001, 0x00000000, /* Constant 5 type desc */ + 0x34783472, 0xababab00, /* Constant 6 name */ + 0x00030002, 0x00040004, 0x00000001, 0x00000000, /* Constant 6 type desc */ + 0x325f7376, 0x4100305f, 0x41414141, 0x00414141, /* Target and Creator name */ + 0x0000ffff}; /* END */ + +static const D3DXCONSTANT_DESC ctab_matrices2_expected[] = { + {"c2x3", D3DXRS_FLOAT4, 7, 3, D3DXPC_MATRIX_COLUMNS, D3DXPT_FLOAT, 2, 3, 1, 0, 24, NULL}, + {"c3x2", D3DXRS_FLOAT4, 13, 2, D3DXPC_MATRIX_COLUMNS, D3DXPT_FLOAT, 3, 2, 1, 0, 24, NULL}, + {"c3x3", D3DXRS_FLOAT4, 10, 3, D3DXPC_MATRIX_COLUMNS, D3DXPT_FLOAT, 3, 3, 1, 0, 36, NULL}, + {"r2x3", D3DXRS_FLOAT4, 15, 2, D3DXPC_MATRIX_ROWS, D3DXPT_FLOAT, 2, 3, 1, 0, 24, NULL}, + {"r3x2", D3DXRS_FLOAT4, 4, 3, D3DXPC_MATRIX_ROWS, D3DXPT_FLOAT, 3, 2, 1, 0, 24, NULL}, + {"r4x4", D3DXRS_FLOAT4, 0, 4, D3DXPC_MATRIX_ROWS, D3DXPT_FLOAT, 4, 4, 1, 0, 64, NULL}}; + +static const DWORD ctab_arrays[] = { + 0xfffe0300, /* vs_3_0 */ + 0x0052fffe, FCC_CTAB, /* CTAB comment */ + 0x0000001c, 0x0000013c, 0xfffe0300, 0x00000006, 0x0000001c, 0x20008100, /* Header */ + 0x00000134, + 0x00000094, 0x000E0002, 0x00000002, 0x0000009c, 0x00000000, /* Constant 1 desc (barray) */ + 0x000000ac, 0x00100002, 0x00000002, 0x000000b8, 0x00000000, /* Constant 2 desc (bvecarray) */ + 0x000000c8, 0x00080002, 0x00000004, 0x000000d0, 0x00000000, /* Constant 3 desc (farray) */ + 0x000000e0, 0x00000002, 0x00000008, 0x000000ec, 0x00000000, /* Constant 4 desc (fmtxarray) */ + 0x000000fc, 0x000C0002, 0x00000002, 0x00000108, 0x00000000, /* Constant 5 desc (fvecarray) */ + 0x00000118, 0x00120002, 0x00000001, 0x00000124, 0x00000000, /* Constant 6 desc (ivecarray) */ + 0x72726162, 0xab007961, /* Constant 1 name */ + 0x00010000, 0x00010001, 0x00000002, 0x00000000, /* Constant 1 type desc */ + 0x63657662, 0x61727261, 0xabab0079, /* Constant 2 name */ + 0x00010001, 0x00030001, 0x00000003, 0x00000000, /* Constant 2 type desc */ + 0x72726166, 0xab007961, /* Constant 3 name */ + 0x00030000, 0x00010001, 0x00000004, 0x00000000, /* constant 3 type desc */ + 0x78746d66, 0x61727261, 0xabab0079, /* Constant 4 name */ + 0x00030002, 0x00040004, 0x00000002, 0x00000000, /* Constant 4 type desc */ + 0x63657666, 0x61727261, 0xabab0079, /* Constant 5 name */ + 0x00030001, 0x00040001, 0x00000002, 0x00000000, /* Constant 5 type desc */ + 0x63657669, 0x61727261, 0xabab0079, /* Constant 6 name */ + 0x00020001, 0x00040001, 0x00000001, 0x00000000, /* Constant 6 type desc */ + 0x335f7376, 0xab00305f, /* Target name string */ + 0x656e6957, 0x6f727020, 0x7463656a, 0xababab00, /* Creator name string */ + 0x0000ffff}; /* END */ + +static const D3DXCONSTANT_DESC ctab_arrays_expected[] = { + {"fmtxarray", D3DXRS_FLOAT4, 0, 8, D3DXPC_MATRIX_ROWS, D3DXPT_FLOAT, 4, 4, 2, 0, 128, NULL}, + {"farray", D3DXRS_FLOAT4, 8, 4, D3DXPC_SCALAR, D3DXPT_FLOAT, 1, 1, 4, 0, 16, NULL}, + {"fvecarray", D3DXRS_FLOAT4, 12, 2, D3DXPC_VECTOR, D3DXPT_FLOAT, 1, 4, 2, 0, 32, NULL}, + {"barray", D3DXRS_FLOAT4, 14, 2, D3DXPC_SCALAR, D3DXPT_BOOL, 1, 1, 2, 0, 8, NULL}, + {"bvecarray", D3DXRS_FLOAT4, 16, 2, D3DXPC_VECTOR, D3DXPT_BOOL, 1, 3, 3, 0, 36, NULL}, + {"ivecarray", D3DXRS_FLOAT4, 18, 1, D3DXPC_VECTOR, D3DXPT_INT, 1, 4, 1, 0, 16, NULL}}; + +static const DWORD ctab_with_default_values[] = { + 0xfffe0200, /* vs_2_0 */ + 0x007bfffe, FCC_CTAB, /* CTAB comment */ + 0x0000001c, 0x000001b7, 0xfffe0200, 0x00000005, 0x0000001c, /* header */ + 0x00000100, 0x000001b0, + 0x00000080, 0x00080002, 0x00000003, 0x00000084, 0x00000094, /* constant 1 desc (arr) */ + 0x000000c4, 0x000c0002, 0x00000001, 0x000000c8, 0x000000d8, /* constant 2 desc (flt) */ + 0x000000e8, 0x00040002, 0x00000004, 0x000000f0, 0x00000100, /* constant 3 desc (mat3) */ + 0x00000140, 0x00000002, 0x00000004, 0x000000f0, 0x00000148, /* constant 4 desc (mat4) */ + 0x00000188, 0x000b0002, 0x00000001, 0x00000190, 0x000001a0, /* constant 5 desc (vec4) */ + 0x00727261, /* constant 1 name */ + 0x00030000, 0x00010001, 0x00000003, 0x00000000, /* constant 1 type desc */ + 0x42c80000, 0x00000000, 0x00000000, 0x00000000, /* constant 1 default value */ + 0x43480000, 0x00000000, 0x00000000, 0x00000000, + 0x43960000, 0x00000000, 0x00000000, 0x00000000, + 0x00746c66, /* constant 2 name */ + 0x00030000, 0x00010001, 0x00000001, 0x00000000, /* constant 2 type desc */ + 0x411fd70a, 0x00000000, 0x00000000, 0x00000000, /* constant 2 default value */ + 0x3374616d, /* constant 3 name */ + 0xababab00, + 0x00030003, 0x00040004, 0x00000001, 0x00000000, /* constant 3 & 4 type desc */ + 0x41300000, 0x425c0000, 0x42c60000, 0x44a42000, /* constat 3 default value */ + 0x41b00000, 0x42840000, 0x447c8000, 0x44b0c000, + 0x42040000, 0x429a0000, 0x448ae000, 0x44bd6000, + 0x42300000, 0x42b00000, 0x44978000, 0x44ca0000, + 0x3474616d, /* constant 4 name */ + 0xababab00, + 0x3f800000, 0x40a00000, 0x41100000, 0x41500000, /* constant 4 default value */ + 0x40000000, 0x40c00000, 0x41200000, 0x41600000, + 0x40400000, 0x40e00000, 0x41300000, 0x41700000, + 0x40800000, 0x41000000, 0x41400000, 0x41800000, + 0x34636576, /* constant 5 name */ + 0xababab00, + 0x00030001, 0x00040001, 0x00000001, 0x00000000, /* constant 5 type desc */ + 0x41200000, 0x41a00000, 0x41f00000, 0x42200000, /* constant 5 default value */ + 0x325f7376, 0x4d004141, 0x41414141, 0x00000000, /* target & creator string */ + 0x0000ffff}; /* END */ + +static const float mat4_default_value[] = {1, 5, 9, 13, 2, 6, 10, 14, 3, 7, 11, 15, 4, 8, 12, 16}; +static const float mat3_default_value[] = {11, 55, 99, 1313, 22, 66, 1010, 1414, 33, 77, 1111, 1515, 44, 88, 1212, 1616}; +static const float arr_default_value[] = {100, 0, 0, 0, 200, 0, 0, 0, 300, 0, 0, 0}; +static const float vec4_default_value[] = {10, 20, 30, 40}; +static const float flt_default_value[] = {9.99, 0, 0, 0}; + +static const D3DXCONSTANT_DESC ctab_with_default_values_expected[] = { + {"mat4", D3DXRS_FLOAT4, 0, 4, D3DXPC_MATRIX_COLUMNS, D3DXPT_FLOAT, 4, 4, 1, 0, 64, mat4_default_value}, + {"mat3", D3DXRS_FLOAT4, 4, 4, D3DXPC_MATRIX_COLUMNS, D3DXPT_FLOAT, 4, 4, 1, 0, 64, mat3_default_value}, + {"arr", D3DXRS_FLOAT4, 8, 3, D3DXPC_SCALAR, D3DXPT_FLOAT, 1, 1, 3, 0, 12, arr_default_value}, + {"vec4", D3DXRS_FLOAT4, 11, 1, D3DXPC_VECTOR, D3DXPT_FLOAT, 1, 4, 1, 0, 16, vec4_default_value}, + {"flt", D3DXRS_FLOAT4, 12, 1, D3DXPC_SCALAR, D3DXPT_FLOAT, 1, 1, 1, 0, 4, flt_default_value}}; + +static const DWORD ctab_samplers[] = { + 0xfffe0300, /* vs_3_0 */ + 0x0032fffe, FCC_CTAB, /* CTAB comment */ + 0x0000001c, 0x000000b4, 0xfffe0300, 0x00000003, 0x0000001c, 0x20008100, /* Header */ + 0x000000ac, + 0x00000058, 0x00020002, 0x00000001, 0x00000064, 0x00000000, /* Constant 1 desc (notsampler) */ + 0x00000074, 0x00000003, 0x00000001, 0x00000080, 0x00000000, /* Constant 2 desc (sampler1) */ + 0x00000090, 0x00030003, 0x00000001, 0x0000009c, 0x00000000, /* Constant 3 desc (sampler2) */ + 0x73746f6e, 0x6c706d61, 0xab007265, /* Constant 1 name */ + 0x00030001, 0x00040001, 0x00000001, 0x00000000, /* Constant 1 type desc */ + 0x706d6173, 0x3172656c, 0xababab00, /* Constant 2 name */ + 0x000c0004, 0x00010001, 0x00000001, 0x00000000, /* Constant 2 type desc */ + 0x706d6173, 0x3272656c, 0xababab00, /* Constant 3 name */ + 0x000d0004, 0x00010001, 0x00000001, 0x00000000, /* Constant 3 type desc */ + 0x335f7376, 0xab00305f, /* Target name string */ + 0x656e6957, 0x6f727020, 0x7463656a, 0xababab00, /* Creator name string */ + 0x0000ffff}; /* END */ + +static const D3DXCONSTANT_DESC ctab_samplers_expected[] = { + {"sampler1", D3DXRS_SAMPLER, 0, 1, D3DXPC_OBJECT, D3DXPT_SAMPLER2D, 1, 1, 1, 0, 4, NULL}, + {"sampler2", D3DXRS_SAMPLER, 3, 1, D3DXPC_OBJECT, D3DXPT_SAMPLER3D, 1, 1, 1, 0, 4, NULL}, + {"notsampler", D3DXRS_FLOAT4, 2, 1, D3DXPC_VECTOR, D3DXPT_FLOAT, 1, 4, 1, 0, 16, NULL}}; + +static const DWORD fx_shader_with_ctab[] = +{ + 0x46580200, /* FX20 */ + 0x002efffe, FCC_CTAB, /* CTAB comment */ + 0x0000001c, 0x000000a4, 0xfffe0300, 0x00000003, 0x0000001c, 0x20008100, /* Header */ + 0x0000009c, + 0x00000058, 0x00070002, 0x00000001, 0x00000064, 0x00000000, /* Constant 1 desc */ + 0x00000074, 0x00000002, 0x00000004, 0x00000080, 0x00000000, /* Constant 2 desc */ + 0x00000090, 0x00040002, 0x00000003, 0x00000080, 0x00000000, /* Constant 3 desc */ + 0x736e6f43, 0x746e6174, 0xabab0031, /* Constant 1 name string */ + 0x00030001, 0x00040001, 0x00000001, 0x00000000, /* Constant 1 type desc */ + 0x736e6f43, 0x746e6174, 0xabab0032, /* Constant 2 name string */ + 0x00030003, 0x00040004, 0x00000001, 0x00000000, /* Constant 2 & 3 type desc */ + 0x736e6f43, 0x746e6174, 0xabab0033, /* Constant 3 name string */ + 0x335f7376, 0xab00305f, /* Target name string */ + 0x656e6957, 0x6f727020, 0x7463656a, 0xababab00, /* Creator name string */ + 0x0000ffff /* END */ +}; + +static void test_get_shader_size(void) +{ + UINT shader_size, expected; + + shader_size = D3DXGetShaderSize(simple_vs); + expected = sizeof(simple_vs); + ok(shader_size == expected, "Got shader size %u, expected %u\n", shader_size, expected); + + shader_size = D3DXGetShaderSize(simple_ps); + expected = sizeof(simple_ps); + ok(shader_size == expected, "Got shader size %u, expected %u\n", shader_size, expected); + + shader_size = D3DXGetShaderSize(NULL); + ok(shader_size == 0, "Got shader size %u, expected 0\n", shader_size); +} + +static void test_get_shader_version(void) +{ + DWORD shader_version; + + shader_version = D3DXGetShaderVersion(simple_vs); + ok(shader_version == D3DVS_VERSION(1, 1), "Got shader version 0x%08x, expected 0x%08x\n", + shader_version, D3DVS_VERSION(1, 1)); + + shader_version = D3DXGetShaderVersion(simple_ps); + ok(shader_version == D3DPS_VERSION(1, 1), "Got shader version 0x%08x, expected 0x%08x\n", + shader_version, D3DPS_VERSION(1, 1)); + + shader_version = D3DXGetShaderVersion(NULL); + ok(shader_version == 0, "Got shader version 0x%08x, expected 0\n", shader_version); +} + +static void test_find_shader_comment(void) +{ + const void *data = (void *)0xdeadbeef; + HRESULT hr; + UINT size = 100; + + hr = D3DXFindShaderComment(NULL, MAKEFOURCC('C','T','A','B'), &data, &size); + ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n", hr, D3DERR_INVALIDCALL); + ok(!data, "Got %p, expected NULL\n", data); + ok(!size, "Got %u, expected 0\n", size); + + hr = D3DXFindShaderComment(shader_with_ctab, MAKEFOURCC('C','T','A','B'), NULL, &size); + ok(hr == D3D_OK, "Got result %x, expected 0 (D3D_OK)\n", hr); + ok(size == 28, "Got %u, expected 28\n", size); + + hr = D3DXFindShaderComment(shader_with_ctab, MAKEFOURCC('C','T','A','B'), &data, NULL); + ok(hr == D3D_OK, "Got result %x, expected 0 (D3D_OK)\n", hr); + ok(data == shader_with_ctab + 6, "Got result %p, expected %p\n", data, shader_with_ctab + 6); + + hr = D3DXFindShaderComment(shader_with_ctab, 0, &data, &size); + ok(hr == S_FALSE, "Got result %x, expected 1 (S_FALSE)\n", hr); + ok(!data, "Got %p, expected NULL\n", data); + ok(!size, "Got %u, expected 0\n", size); + + hr = D3DXFindShaderComment(shader_with_ctab, MAKEFOURCC('X','X','X','X'), &data, &size); + ok(hr == S_FALSE, "Got result %x, expected 1 (S_FALSE)\n", hr); + ok(!data, "Got %p, expected NULL\n", data); + ok(!size, "Got %u, expected 0\n", size); + + hr = D3DXFindShaderComment(shader_with_ctab, MAKEFOURCC('C','T','A','B'), &data, &size); + ok(hr == D3D_OK, "Got result %x, expected 0 (D3D_OK)\n", hr); + ok(data == shader_with_ctab + 6, "Got result %p, expected %p\n", data, shader_with_ctab + 6); + ok(size == 28, "Got result %u, expected 28\n", size); + + hr = D3DXFindShaderComment(shader_zero, MAKEFOURCC('C','T','A','B'), &data, &size); + ok(hr == D3DXERR_INVALIDDATA, "Got result %x, expected %x (D3DXERR_INVALIDDATA)\n", hr, D3DXERR_INVALIDDATA); + ok(!data, "Got %p, expected NULL\n", data); + ok(!size, "Got %u, expected 0\n", size); + + hr = D3DXFindShaderComment(shader_invalid, MAKEFOURCC('C','T','A','B'), &data, &size); + ok(hr == D3DXERR_INVALIDDATA, "Got result %x, expected %x (D3DXERR_INVALIDDATA)\n", hr, D3DXERR_INVALIDDATA); + ok(!data, "Got %p, expected NULL\n", data); + ok(!size, "Got %u, expected 0\n", size); + + hr = D3DXFindShaderComment(shader_empty, MAKEFOURCC('C','T','A','B'), &data, &size); + ok(hr == S_FALSE, "Got result %x, expected %x (S_FALSE)\n", hr, S_FALSE); + ok(!data, "Got %p, expected NULL\n", data); + ok(!size, "Got %u, expected 0\n", size); + + hr = D3DXFindShaderComment(simple_fx, FCC_TEXT, &data, &size); + ok(hr == D3D_OK, "Got result %x, expected 0 (D3D_OK)\n", hr); + ok(data == simple_fx + 3, "Got result %p, expected %p\n", data, simple_fx + 3); + ok(size == 4, "Got result %u, expected 4\n", size); + + hr = D3DXFindShaderComment(simple_tx, FCC_TEXT, &data, &size); + ok(hr == D3D_OK, "Got result %x, expected 0 (D3D_OK)\n", hr); + ok(data == simple_tx + 3, "Got result %p, expected %p\n", data, simple_tx + 3); + ok(size == 4, "Got result %u, expected 4\n", size); + + hr = D3DXFindShaderComment(simple_7ffe, FCC_TEXT, &data, &size); + ok(hr == D3D_OK, "Got result %x, expected 0 (D3D_OK)\n", hr); + ok(data == simple_7ffe + 3, "Got result %p, expected %p\n", data, simple_7ffe + 3); + ok(size == 4, "Got result %u, expected 4\n", size); + + hr = D3DXFindShaderComment(simple_7fff, FCC_TEXT, &data, &size); + ok(hr == D3D_OK, "Got result %x, expected 0 (D3D_OK)\n", hr); + ok(data == simple_7fff + 3, "Got result %p, expected %p\n", data, simple_7fff + 3); + ok(size == 4, "Got result %u, expected 4\n", size); +} + +static void test_get_shader_constant_table_ex(void) +{ + ID3DXConstantTable *constant_table; + HRESULT hr; + void *data; + DWORD size; + D3DXCONSTANTTABLE_DESC desc; + + constant_table = (ID3DXConstantTable *)0xdeadbeef; + hr = D3DXGetShaderConstantTableEx(NULL, 0, &constant_table); + ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n", hr, D3DERR_INVALIDCALL); + ok(constant_table == NULL, "D3DXGetShaderConstantTableEx() failed, got %p\n", constant_table); + + constant_table = (ID3DXConstantTable *)0xdeadbeef; + hr = D3DXGetShaderConstantTableEx(shader_zero, 0, &constant_table); + ok(hr == D3D_OK, "Got result %x, expected %x (D3D_OK)\n", hr, D3D_OK); + ok(constant_table == NULL, "D3DXGetShaderConstantTableEx() failed, got %p\n", constant_table); + + constant_table = (ID3DXConstantTable *)0xdeadbeef; + hr = D3DXGetShaderConstantTableEx(shader_invalid, 0, &constant_table); + ok(hr == D3D_OK, "Got result %x, expected %x (D3D_OK)\n", hr, D3D_OK); + ok(constant_table == NULL, "D3DXGetShaderConstantTableEx() failed, got %p\n", constant_table); + + constant_table = (ID3DXConstantTable *)0xdeadbeef; + hr = D3DXGetShaderConstantTableEx(shader_empty, 0, &constant_table); + ok(hr == D3DXERR_INVALIDDATA, "Got result %x, expected %x (D3DXERR_INVALIDDATA)\n", hr, D3DXERR_INVALIDDATA); + ok(constant_table == NULL, "D3DXGetShaderConstantTableEx() failed, got %p\n", constant_table); + + /* No CTAB data */ + constant_table = (ID3DXConstantTable *)0xdeadbeef; + hr = D3DXGetShaderConstantTableEx(simple_ps, 0, &constant_table); + ok(hr == D3DXERR_INVALIDDATA, "Got result %x, expected %x (D3DXERR_INVALIDDATA)\n", hr, D3DXERR_INVALIDDATA); + ok(constant_table == NULL, "D3DXGetShaderConstantTableEx() failed, got %p\n", constant_table); + + /* With invalid CTAB data */ + hr = D3DXGetShaderConstantTableEx(shader_with_invalid_ctab, 0, &constant_table); + ok(hr == D3DXERR_INVALIDDATA || broken(hr == D3D_OK), /* winxp 64-bit, w2k3 64-bit */ + "Got result %x, expected %x (D3DXERR_INVALIDDATA)\n", hr, D3DXERR_INVALIDDATA); + if (constant_table) ID3DXConstantTable_Release(constant_table); + + hr = D3DXGetShaderConstantTableEx(simple_fx, 0, &constant_table); + ok(hr == D3D_OK, "Got result %x, expected 0 (D3D_OK).\n", hr); + ok(!constant_table, "D3DXGetShaderConstantTableEx() returned a non-NULL constant table.\n"); + + hr = D3DXGetShaderConstantTableEx(simple_tx, 0, &constant_table); + ok(hr == D3D_OK, "Got result %x, expected 0 (D3D_OK).\n", hr); + ok(!constant_table, "D3DXGetShaderConstantTableEx() returned a non-NULL constant table.\n"); + + hr = D3DXGetShaderConstantTableEx(shader_with_ctab, 0, &constant_table); + ok(hr == D3D_OK, "Got result %x, expected 0 (D3D_OK)\n", hr); + ok(constant_table != NULL, "D3DXGetShaderConstantTableEx() failed, got NULL\n"); + + if (constant_table) + { + size = ID3DXConstantTable_GetBufferSize(constant_table); + ok(size == 28, "Got result %x, expected 28\n", size); + + data = ID3DXConstantTable_GetBufferPointer(constant_table); + ok(!memcmp(data, shader_with_ctab + 6, size), "Retrieved wrong CTAB data\n"); + + hr = ID3DXConstantTable_GetDesc(constant_table, NULL); + ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n", hr, D3DERR_INVALIDCALL); + + hr = ID3DXConstantTable_GetDesc(constant_table, &desc); + ok(hr == D3D_OK, "Got result %x, expected 0 (D3D_OK)\n", hr); + ok(desc.Creator == (const char *)data + 0x10, "Got result %p, expected %p\n", + desc.Creator, (const char *)data + 0x10); + ok(desc.Version == D3DVS_VERSION(3, 0), "Got result %x, expected %x\n", desc.Version, D3DVS_VERSION(3, 0)); + ok(desc.Constants == 0, "Got result %x, expected 0\n", desc.Constants); + + ID3DXConstantTable_Release(constant_table); + } + + hr = D3DXGetShaderConstantTableEx(shader_with_ctab_constants, 0, &constant_table); + ok(hr == D3D_OK, "Got result %x, expected 0 (D3D_OK)\n", hr); + ok(constant_table != NULL, "D3DXGetShaderConstantTableEx() failed, got NULL\n"); + + if (constant_table) + { + D3DXHANDLE constant; + D3DXCONSTANT_DESC constant_desc; + D3DXCONSTANT_DESC constant_desc_save; + UINT nb; + + /* Test GetDesc */ + hr = ID3DXConstantTable_GetDesc(constant_table, &desc); + ok(hr == D3D_OK, "Got result %x, expected 0 (D3D_OK)\n", hr); + ok(!strcmp(desc.Creator, "Wine project"), "Got result '%s', expected 'Wine project'\n", desc.Creator); + ok(desc.Version == D3DVS_VERSION(3, 0), "Got result %x, expected %x\n", desc.Version, D3DVS_VERSION(3, 0)); + ok(desc.Constants == 3, "Got result %x, expected 3\n", desc.Constants); + + /* Test GetConstant */ + constant = ID3DXConstantTable_GetConstant(constant_table, NULL, 0); + ok(constant != NULL, "No constant found\n"); + hr = ID3DXConstantTable_GetConstantDesc(constant_table, constant, &constant_desc, &nb); + ok(hr == D3D_OK, "Got result %x, expected 0 (D3D_OK)\n", hr); + ok(!strcmp(constant_desc.Name, "Constant1"), "Got result '%s', expected 'Constant1'\n", + constant_desc.Name); + ok(constant_desc.Class == D3DXPC_VECTOR, "Got result %x, expected %u (D3DXPC_VECTOR)\n", + constant_desc.Class, D3DXPC_VECTOR); + ok(constant_desc.Type == D3DXPT_FLOAT, "Got result %x, expected %u (D3DXPT_FLOAT)\n", + constant_desc.Type, D3DXPT_FLOAT); + ok(constant_desc.Rows == 1, "Got result %x, expected 1\n", constant_desc.Rows); + ok(constant_desc.Columns == 4, "Got result %x, expected 4\n", constant_desc.Columns); + + constant = ID3DXConstantTable_GetConstant(constant_table, NULL, 1); + ok(constant != NULL, "No constant found\n"); + hr = ID3DXConstantTable_GetConstantDesc(constant_table, constant, &constant_desc, &nb); + ok(hr == D3D_OK, "Got result %x, expected 0 (D3D_OK)\n", hr); + ok(!strcmp(constant_desc.Name, "Constant2"), "Got result '%s', expected 'Constant2'\n", + constant_desc.Name); + ok(constant_desc.Class == D3DXPC_MATRIX_COLUMNS, "Got result %x, expected %u (D3DXPC_MATRIX_COLUMNS)\n", + constant_desc.Class, D3DXPC_MATRIX_COLUMNS); + ok(constant_desc.Type == D3DXPT_FLOAT, "Got result %x, expected %u (D3DXPT_FLOAT)\n", + constant_desc.Type, D3DXPT_FLOAT); + ok(constant_desc.Rows == 4, "Got result %x, expected 1\n", constant_desc.Rows); + ok(constant_desc.Columns == 4, "Got result %x, expected 4\n", constant_desc.Columns); + + constant = ID3DXConstantTable_GetConstant(constant_table, NULL, 2); + ok(constant != NULL, "No constant found\n"); + hr = ID3DXConstantTable_GetConstantDesc(constant_table, constant, &constant_desc, &nb); + ok(hr == D3D_OK, "Got result %x, expected 0 (D3D_OK)\n", hr); + ok(!strcmp(constant_desc.Name, "Constant3"), "Got result '%s', expected 'Constant3'\n", + constant_desc.Name); + ok(constant_desc.Class == D3DXPC_MATRIX_COLUMNS, "Got result %x, expected %u (D3DXPC_MATRIX_COLUMNS)\n", + constant_desc.Class, D3DXPC_MATRIX_COLUMNS); + ok(constant_desc.Type == D3DXPT_FLOAT, "Got result %x, expected %u (D3DXPT_FLOAT)\n", + constant_desc.Type, D3DXPT_FLOAT); + ok(constant_desc.Rows == 4, "Got result %x, expected 1\n", constant_desc.Rows); + ok(constant_desc.Columns == 4, "Got result %x, expected 4\n", constant_desc.Columns); + constant_desc_save = constant_desc; /* For GetConstantDesc test */ + + constant = ID3DXConstantTable_GetConstant(constant_table, NULL, 3); + ok(constant == NULL, "Got result %p, expected NULL\n", constant); + + /* Test GetConstantByName */ + constant = ID3DXConstantTable_GetConstantByName(constant_table, NULL, "Constant unknown"); + ok(constant == NULL, "Got result %p, expected NULL\n", constant); + constant = ID3DXConstantTable_GetConstantByName(constant_table, NULL, "Constant3"); + ok(constant != NULL, "No constant found\n"); + hr = ID3DXConstantTable_GetConstantDesc(constant_table, constant, &constant_desc, &nb); + ok(hr == D3D_OK, "Got result %x, expected 0 (D3D_OK)\n", hr); + ok(!memcmp(&constant_desc, &constant_desc_save, sizeof(D3DXCONSTANT_DESC)), "Got different constant data\n"); + + /* Test GetConstantDesc */ + constant = ID3DXConstantTable_GetConstant(constant_table, NULL, 0); + ok(constant != NULL, "No constant found\n"); + hr = ID3DXConstantTable_GetConstantDesc(constant_table, NULL, &constant_desc, &nb); + ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n", hr, D3DERR_INVALIDCALL); + hr = ID3DXConstantTable_GetConstantDesc(constant_table, constant, NULL, &nb); + ok(hr == D3D_OK, "Got result %x, expected 0 (D3D_OK)\n", hr); + hr = ID3DXConstantTable_GetConstantDesc(constant_table, constant, &constant_desc, NULL); + ok(hr == D3D_OK, "Got result %x, expected 0 (D3D_OK)\n", hr); + hr = ID3DXConstantTable_GetConstantDesc(constant_table, "Constant unknown", &constant_desc, &nb); + ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n", hr, D3DERR_INVALIDCALL); + hr = ID3DXConstantTable_GetConstantDesc(constant_table, "Constant3", &constant_desc, &nb); + ok(hr == D3D_OK, "Got result %x, expected 0 (D3D_OK)\n", hr); + ok(!memcmp(&constant_desc, &constant_desc_save, sizeof(D3DXCONSTANT_DESC)), "Got different constant data\n"); + + ID3DXConstantTable_Release(constant_table); + } + + hr = D3DXGetShaderConstantTableEx(fx_shader_with_ctab, 0, &constant_table); + ok(hr == D3D_OK, "Got result %x, expected 0 (D3D_OK).\n", hr); + ok(!constant_table, "D3DXGetShaderConstantTableEx() returned a non-NULL constant table.\n"); +} + +static void test_constant_table(const char *test_name, const DWORD *ctable_fn, + const D3DXCONSTANT_DESC *expecteds, UINT count) +{ + UINT i; + ID3DXConstantTable *ctable; + + HRESULT res; + + /* Get the constant table from the shader itself */ + res = D3DXGetShaderConstantTable(ctable_fn, &ctable); + ok(res == D3D_OK, "D3DXGetShaderConstantTable failed on %s: got %08x\n", test_name, res); + + for (i = 0; i < count; i++) + { + const D3DXCONSTANT_DESC *expected = &expecteds[i]; + D3DXHANDLE const_handle; + D3DXCONSTANT_DESC actual; + UINT pCount = 1; + + const_handle = ID3DXConstantTable_GetConstantByName(ctable, NULL, expected->Name); + + res = ID3DXConstantTable_GetConstantDesc(ctable, const_handle, &actual, &pCount); + ok(SUCCEEDED(res), "%s in %s: ID3DXConstantTable_GetConstantDesc returned %08x\n", expected->Name, + test_name, res); + ok(pCount == 1, "%s in %s: Got more or less descriptions: %d\n", expected->Name, test_name, pCount); + + ok(strcmp(actual.Name, expected->Name) == 0, + "%s in %s: Got different names: Got %s, expected %s\n", expected->Name, + test_name, actual.Name, expected->Name); + ok(actual.RegisterSet == expected->RegisterSet, + "%s in %s: Got different register sets: Got %d, expected %d\n", + expected->Name, test_name, actual.RegisterSet, expected->RegisterSet); + ok(actual.RegisterIndex == expected->RegisterIndex, + "%s in %s: Got different register indices: Got %d, expected %d\n", + expected->Name, test_name, actual.RegisterIndex, expected->RegisterIndex); + ok(actual.RegisterCount == expected->RegisterCount, + "%s in %s: Got different register counts: Got %d, expected %d\n", + expected->Name, test_name, actual.RegisterCount, expected->RegisterCount); + ok(actual.Class == expected->Class, + "%s in %s: Got different classes: Got %d, expected %d\n", expected->Name, + test_name, actual.Class, expected->Class); + ok(actual.Type == expected->Type, + "%s in %s: Got different types: Got %d, expected %d\n", expected->Name, + test_name, actual.Type, expected->Type); + ok(actual.Rows == expected->Rows && actual.Columns == expected->Columns, + "%s in %s: Got different dimensions: Got (%d, %d), expected (%d, %d)\n", + expected->Name, test_name, actual.Rows, actual.Columns, expected->Rows, + expected->Columns); + ok(actual.Elements == expected->Elements, + "%s in %s: Got different element count: Got %d, expected %d\n", + expected->Name, test_name, actual.Elements, expected->Elements); + ok(actual.StructMembers == expected->StructMembers, + "%s in %s: Got different struct member count: Got %d, expected %d\n", + expected->Name, test_name, actual.StructMembers, expected->StructMembers); + ok(actual.Bytes == expected->Bytes, + "%s in %s: Got different byte count: Got %d, expected %d\n", + expected->Name, test_name, actual.Bytes, expected->Bytes); + + if (!expected->DefaultValue) + { + ok(actual.DefaultValue == NULL, + "%s in %s: Got different default value: expected NULL\n", + expected->Name, test_name); + } + else + { + ok(actual.DefaultValue != NULL, + "%s in %s: Got different default value: expected non-NULL\n", + expected->Name, test_name); + ok(memcmp(actual.DefaultValue, expected->DefaultValue, expected->Bytes) == 0, + "%s in %s: Got different default value\n", expected->Name, test_name); + } + } + + /* Finally, release the constant table */ + ID3DXConstantTable_Release(ctable); +} + +static void test_constant_tables(void) +{ + test_constant_table("test_basic", ctab_basic, ctab_basic_expected, + ARRAY_SIZE(ctab_basic_expected)); + test_constant_table("test_matrices", ctab_matrices, ctab_matrices_expected, + ARRAY_SIZE(ctab_matrices_expected)); + test_constant_table("test_matrices2", ctab_matrices2, ctab_matrices2_expected, + ARRAY_SIZE(ctab_matrices2_expected)); + test_constant_table("test_arrays", ctab_arrays, ctab_arrays_expected, + ARRAY_SIZE(ctab_arrays_expected)); + test_constant_table("test_default_values", ctab_with_default_values, ctab_with_default_values_expected, + ARRAY_SIZE(ctab_with_default_values_expected)); + test_constant_table("test_samplers", ctab_samplers, ctab_samplers_expected, + ARRAY_SIZE(ctab_samplers_expected)); +} + +static void test_setting_basic_table(IDirect3DDevice9 *device) +{ + static const D3DXMATRIX mvp = {{{ + 0.514f, 0.626f, 0.804f, 0.786f, + 0.238f, 0.956f, 0.374f, 0.483f, + 0.109f, 0.586f, 0.900f, 0.255f, + 0.898f, 0.411f, 0.932f, 0.275f}}}; + static const D3DXVECTOR4 f4 = {0.350f, 0.526f, 0.925f, 0.021f}; + static const float f = 0.12543f; + static const int i = 321; + static const D3DXMATRIX *matrix_pointer[] = {&mvp}; + + ID3DXConstantTable *ctable; + + HRESULT res; + float out[16]; + ULONG refcnt; + + /* Get the constant table from the shader itself */ + res = D3DXGetShaderConstantTable(ctab_basic, &ctable); + ok(res == D3D_OK, "D3DXGetShaderConstantTable failed: got 0x%08x\n", res); + + /* Set constants */ + res = ID3DXConstantTable_SetMatrix(ctable, device, "mvp", &mvp); + ok(res == D3D_OK, "ID3DXConstantTable_SetMatrix failed on variable mvp: got 0x%08x\n", res); + + res = ID3DXConstantTable_SetInt(ctable, device, "i", i + 1); + ok(res == D3D_OK, "ID3DXConstantTable_SetInt failed on variable i: got 0x%08x\n", res); + + /* Check that setting i again will overwrite the previous value */ + res = ID3DXConstantTable_SetInt(ctable, device, "i", i); + ok(res == D3D_OK, "ID3DXConstantTable_SetInt failed on variable i: got 0x%08x\n", res); + + res = ID3DXConstantTable_SetFloat(ctable, device, "f", f); + ok(res == D3D_OK, "ID3DXConstantTable_SetFloat failed on variable f: got 0x%08x\n", res); + + res = ID3DXConstantTable_SetVector(ctable, device, "f4", &f4); + ok(res == D3D_OK, "ID3DXConstantTable_SetVector failed on variable f4: got 0x%08x\n", res); + + /* Get constants back and validate */ + IDirect3DDevice9_GetVertexShaderConstantF(device, 0, out, 4); + ok(out[0] == S(U(mvp))._11 && out[4] == S(U(mvp))._12 && out[8] == S(U(mvp))._13 && out[12] == S(U(mvp))._14, + "The first row of mvp was not set correctly, got {%f, %f, %f, %f}, should be {%f, %f, %f, %f}\n", + out[0], out[4], out[8], out[12], S(U(mvp))._11, S(U(mvp))._12, S(U(mvp))._13, S(U(mvp))._14); + ok(out[1] == S(U(mvp))._21 && out[5] == S(U(mvp))._22 && out[9] == S(U(mvp))._23 && out[13] == S(U(mvp))._24, + "The second row of mvp was not set correctly, got {%f, %f, %f, %f}, should be {%f, %f, %f, %f}\n", + out[1], out[5], out[9], out[13], S(U(mvp))._21, S(U(mvp))._22, S(U(mvp))._23, S(U(mvp))._24); + ok(out[2] == S(U(mvp))._31 && out[6] == S(U(mvp))._32 && out[10] == S(U(mvp))._33 && out[14] == S(U(mvp))._34, + "The third row of mvp was not set correctly, got {%f, %f, %f, %f}, should be {%f, %f, %f, %f}\n", + out[2], out[6], out[10], out[14], S(U(mvp))._31, S(U(mvp))._32, S(U(mvp))._33, S(U(mvp))._34); + ok(out[3] == S(U(mvp))._41 && out[7] == S(U(mvp))._42 && out[11] == S(U(mvp))._43 && out[15] == S(U(mvp))._44, + "The fourth row of mvp was not set correctly, got {%f, %f, %f, %f}, should be {%f, %f, %f, %f}\n", + out[3], out[7], out[11], out[15], S(U(mvp))._41, S(U(mvp))._42, S(U(mvp))._43, S(U(mvp))._44); + + IDirect3DDevice9_GetVertexShaderConstantF(device, 4, out, 1); + ok(out[0] == (float)i && out[1] == 0.0f && out[2] == 0.0f && out[3] == 0.0f, + "The variable i was not set correctly, out={%f, %f, %f, %f}, should be {%d, 0.0, 0.0, 0.0}\n", + out[0], out[1], out[2], out[3], i); + + IDirect3DDevice9_GetVertexShaderConstantF(device, 6, out, 1); + ok(out[0] == f && out[1] == 0.0f && out[2] == 0.0f && out[3] == 0.0f, + "The variable f was not set correctly, out={%f, %f, %f, %f}, should be {%f, 0.0, 0.0, 0.0}\n", + out[0], out[1], out[2], out[3], f); + + IDirect3DDevice9_GetVertexShaderConstantF(device, 7, out, 1); + ok(memcmp(out, &f4, sizeof(f4)) == 0, + "The variable f4 was not set correctly, out={%f, %f, %f, %f}, should be {%f, %f, %f, %f}\n", + out[0], out[1], out[2], out[3], f4.x, f4.y, f4.z, f4.w); + + /* Finally test using a set* function for one type to set a variable of another type (should succeed) */ + res = ID3DXConstantTable_SetVector(ctable, device, "f", &f4); + ok(res == D3D_OK, "ID3DXConstantTable_SetVector failed on variable f: 0x%08x\n", res); + + IDirect3DDevice9_GetVertexShaderConstantF(device, 6, out, 1); + ok(out[0] == f4.x && out[1] == 0.0f && out[2] == 0.0f && out[3] == 0.0f, + "The variable f was not set correctly by ID3DXConstantTable_SetVector, got %f, should be %f\n", + out[0], f4.x); + + memset(out, 0, sizeof(out)); + IDirect3DDevice9_SetVertexShaderConstantF(device, 6, out, 1); + res = ID3DXConstantTable_SetMatrix(ctable, device, "f", &mvp); + ok(res == D3D_OK, "ID3DXConstantTable_SetMatrix failed on variable f: 0x%08x\n", res); + + IDirect3DDevice9_GetVertexShaderConstantF(device, 6, out, 1); + ok(out[0] == S(U(mvp))._11 && out[1] == 0.0f && out[2] == 0.0f && out[3] == 0.0f, + "The variable f was not set correctly by ID3DXConstantTable_SetMatrix, got %f, should be %f\n", + out[0], S(U(mvp))._11); + + /* Clear registers */ + memset(out, 0, sizeof(out)); + IDirect3DDevice9_SetVertexShaderConstantF(device, 0, out, 4); + IDirect3DDevice9_SetVertexShaderConstantF(device, 6, out, 1); + IDirect3DDevice9_SetVertexShaderConstantF(device, 7, out, 1); + + /* SetVector shouldn't change the value of a matrix constant */ + res = ID3DXConstantTable_SetVector(ctable, device, "mvp", &f4); + ok(res == D3D_OK, "ID3DXConstantTable_SetVector failed on variable f: 0x%08x\n", res); + + IDirect3DDevice9_GetVertexShaderConstantF(device, 0, out, 4); + ok(out[0] == 0.0f && out[1] == 0.0f && out[2] == 0.0f && out[3] == 0.0f + && out[4] == 0.0f && out[5] == 0.0f && out[6] == 0.0f && out[7] == 0.0f + && out[8] == 0.0f && out[9] == 0.0f && out[10] == 0.0f && out[11] == 0.0f + && out[12] == 0.0f && out[13] == 0.0f && out[14] == 0.0f && out[15] == 0.0f, + "The variable mvp was not set correctly by ID3DXConstantTable_SetVector, " + "got {%f, %f, %f, %f; %f, %f, %f, %f; %f, %f, %f %f; %f, %f, %f, %f}, " + "should be all 0.0f\n", + out[0], out[1], out[2], out[3], + out[4], out[5], out[6], out[7], + out[8], out[9], out[10], out[11], + out[12], out[13], out[14], out[15]); + + res = ID3DXConstantTable_SetFloat(ctable, device, "mvp", f); + ok(res == D3D_OK, "ID3DXConstantTable_SetFloat failed on variable mvp: 0x%08x\n", res); + + IDirect3DDevice9_GetVertexShaderConstantF(device, 0, out, 4); + ok(out[0] == 0.0f && out[1] == 0.0f && out[2] == 0.0f && out[3] == 0.0f + && out[4] == 0.0f && out[5] == 0.0f && out[6] == 0.0f && out[7] == 0.0f + && out[8] == 0.0f && out[9] == 0.0f && out[10] == 0.0f && out[11] == 0.0f + && out[12] == 0.0f && out[13] == 0.0f && out[14] == 0.0f && out[15] == 0.0f, + "The variable mvp was not set correctly by ID3DXConstantTable_SetFloat, " + "got {%f, %f, %f, %f; %f, %f, %f, %f; %f, %f, %f %f; %f, %f, %f, %f}, " + "should be all 0.0f\n", + out[0], out[1], out[2], out[3], + out[4], out[5], out[6], out[7], + out[8], out[9], out[10], out[11], + out[12], out[13], out[14], out[15]); + + res = ID3DXConstantTable_SetFloat(ctable, device, "f4", f); + ok(res == D3D_OK, "ID3DXConstantTable_SetFloat failed on variable f4: 0x%08x\n", res); + + IDirect3DDevice9_GetVertexShaderConstantF(device, 7, out, 1); + ok(out[0] == 0.0f && out[1] == 0.0f && out[2] == 0.0f && out[3] == 0.0f, + "The variable f4 was not set correctly by ID3DXConstantTable_SetFloat, " + "got {%f, %f, %f, %f}, should be all 0.0f\n", + out[0], out[1], out[2], out[3]); + + res = ID3DXConstantTable_SetMatrixTranspose(ctable, device, "f", &mvp); + ok(res == D3D_OK, "ID3DXConstantTable_SetMatrixTranspose failed on variable f: 0x%08x\n", res); + + IDirect3DDevice9_GetVertexShaderConstantF(device, 6, out, 1); + ok(out[0] == S(U(mvp))._11 && out[1] == 0.0f && out[2] == 0.0f && out[3] == 0.0f, + "The variable f was not set correctly by ID3DXConstantTable_SetMatrixTranspose, got %f, should be %f\n", + out[0], S(U(mvp))._11); + + res = ID3DXConstantTable_SetMatrixTranspose(ctable, device, "f4", &mvp); + ok(res == D3D_OK, "ID3DXConstantTable_SetMatrixTranspose failed on variable f4: 0x%08x\n", res); + + IDirect3DDevice9_GetVertexShaderConstantF(device, 7, out, 1); + ok(out[0] == S(U(mvp))._11 && out[1] == S(U(mvp))._21 && out[2] == S(U(mvp))._31 && out[3] == S(U(mvp))._41, + "The variable f4 was not set correctly by ID3DXConstantTable_SetMatrixTranspose, " + "got {%f, %f, %f, %f}, should be {%f, %f, %f, %f}\n", + out[0], out[1], out[2], out[3], + S(U(mvp))._11, S(U(mvp))._21, S(U(mvp))._31, S(U(mvp))._41); + + memset(out, 0, sizeof(out)); + IDirect3DDevice9_SetVertexShaderConstantF(device, 6, out, 1); + res = ID3DXConstantTable_SetMatrixPointerArray(ctable, device, "f", matrix_pointer, 1); + ok(res == D3D_OK, "ID3DXConstantTable_SetMatrixPointerArray failed on variable f: got %#x\n", res); + + IDirect3DDevice9_GetVertexShaderConstantF(device, 6, out, 1); + ok(out[0] == S(U(mvp))._11 && out[1] == 0.0f && out[2] == 0.0f && out[3] == 0.0f, + "The variable f was not set correctly by ID3DXConstantTable_SetMatrixPointerArray, " + "got %f, should be %f\n", + out[0], S(U(mvp))._11); + + res = ID3DXConstantTable_SetMatrixPointerArray(ctable, device, "f4", matrix_pointer, 1); + ok(res == D3D_OK, "ID3DXConstantTable_SetMatrixPointerArray failed on variable f4: got %#x\n", res); + + IDirect3DDevice9_GetVertexShaderConstantF(device, 7, out, 1); + ok(out[0] == S(U(mvp))._11 && out[1] == S(U(mvp))._12 && out[2] == S(U(mvp))._13 && out[3] == S(U(mvp))._14, + "The variable f4 was not set correctly by ID3DXConstantTable_SetMatrixPointerArray, " + "got {%f, %f, %f, %f}, should be {%f, %f, %f, %f}\n", + out[0], out[1], out[2], out[3], + S(U(mvp))._11, S(U(mvp))._12, S(U(mvp))._13, S(U(mvp))._14); + + memset(out, 0, sizeof(out)); + IDirect3DDevice9_SetVertexShaderConstantF(device, 6, out, 1); + res = ID3DXConstantTable_SetMatrixTransposePointerArray(ctable, device, "f", matrix_pointer, 1); + ok(res == D3D_OK, "ID3DXConstantTable_SetMatrixTransposePointerArray failed on variable f: got %#x\n", res); + + IDirect3DDevice9_GetVertexShaderConstantF(device, 6, out, 1); + ok(out[0] == S(U(mvp))._11 && out[1] == 0.0f && out[2] == 0.0f && out[3] == 0.0f, + "The variable f was not set correctly by ID3DXConstantTable_SetMatrixTransposePointerArray, " + "got %f, should be %f\n", + out[0], S(U(mvp))._11); + + res = ID3DXConstantTable_SetMatrixTransposePointerArray(ctable, device, "f4", matrix_pointer, 1); + ok(res == D3D_OK, "ID3DXConstantTable_SetMatrixTransposePointerArray failed on variable f4: got %#x\n", res); + + IDirect3DDevice9_GetVertexShaderConstantF(device, 7, out, 1); + ok(out[0] == S(U(mvp))._11 && out[1] == S(U(mvp))._21 && out[2] == S(U(mvp))._31 && out[3] == S(U(mvp))._41, + "The variable f4 was not set correctly by ID3DXConstantTable_SetMatrixTransposePointerArray, " + "got {%f, %f, %f, %f}, should be {%f, %f, %f, %f}\n", + out[0], out[1], out[2], out[3], + S(U(mvp))._11, S(U(mvp))._21, S(U(mvp))._31, S(U(mvp))._41); + + refcnt = ID3DXConstantTable_Release(ctable); + ok(refcnt == 0, "The constant table reference count was %u, should be 0\n", refcnt); +} + +static void test_setting_matrices_table(IDirect3DDevice9 *device) +{ + static const D3DXMATRIX fmatrix = + {{{2.001f, 1.502f, 9.003f, 1.004f, + 5.005f, 3.006f, 3.007f, 6.008f, + 9.009f, 5.010f, 7.011f, 1.012f, + 5.013f, 5.014f, 5.015f, 9.016f}}}; + static const D3DXMATRIX *matrix_pointer[] = {&fmatrix}; + + ID3DXConstantTable *ctable; + + HRESULT res; + float out[32]; + + res = D3DXGetShaderConstantTable(ctab_matrices, &ctable); + ok(res == D3D_OK, "D3DXGetShaderConstantTable failed: got %#x\n", res); + + res = ID3DXConstantTable_SetMatrix(ctable, device, "imatrix2x3", &fmatrix); + ok(res == D3D_OK, "ID3DXConstantTable_SetMatrix failed on variable imatrix2x3: got %#x\n", res); + + res = ID3DXConstantTable_SetMatrix(ctable, device, "fmatrix3x1", &fmatrix); + ok(res == D3D_OK, "ID3DXConstantTable_SetMatrix failed on variable fmatrix3x1: got %#x\n", res); + + IDirect3DDevice9_GetVertexShaderConstantF(device, 4, out, 2); + ok(out[0] == (int)S(U(fmatrix))._11 && out[1] == (int)S(U(fmatrix))._12 && out[2] == (int)S(U(fmatrix))._13 + && out[3] == 0 + && out[4] == (int)S(U(fmatrix))._21 && out[5] == (int)S(U(fmatrix))._22 && out[6] == (int)S(U(fmatrix))._23 + && out[7] == 0, + "The variable imatrix2x3 was not set correctly, out={%f, %f, %f, %f; %f, %f, %f, %f}, " + "should be {%d, %d, %d, %d; %d, %d, %d, %d}\n", + out[0], out[1], out[2], out[3], out[4], out[5], out[6], out[7], + (int)S(U(fmatrix))._11, (int)S(U(fmatrix))._12, (int)S(U(fmatrix))._13, 0, + (int)S(U(fmatrix))._21, (int)S(U(fmatrix))._22, (int)S(U(fmatrix))._23, 0); + + IDirect3DDevice9_GetVertexShaderConstantF(device, 7, out, 1); + ok(out[0] == S(U(fmatrix))._11 && out[1] == S(U(fmatrix))._21 && out[2] == S(U(fmatrix))._31 && out[3] == 0.0f, + "The variable fmatrix3x1 was not set correctly, out={%f, %f, %f, %f}, should be {%f, %f, %f, %f}\n", + out[0], out[1], out[2], out[3], + S(U(fmatrix))._11, S(U(fmatrix))._21, S(U(fmatrix))._31, 0.0f); + + ID3DXConstantTable_Release(ctable); + + res = D3DXGetShaderConstantTable(ctab_matrices2, &ctable); + ok(res == D3D_OK, "D3DXGetShaderConstantTable failed: got %#x\n", res); + + /* SetMatrix */ + res = ID3DXConstantTable_SetMatrix(ctable, device, "c2x3", &fmatrix); + ok(res == D3D_OK, "ID3DXConstantTable_SetMatrix failed on variable c2x3: got %#x\n", res); + + res = ID3DXConstantTable_SetMatrix(ctable, device, "r2x3", &fmatrix); + ok(res == D3D_OK, "ID3DXConstantTable_SetMatrix failed on variable r2x3: got %#x\n", res); + + res = ID3DXConstantTable_SetMatrix(ctable, device, "c3x2", &fmatrix); + ok(res == D3D_OK, "ID3DXConstantTable_SetMatrix failed on variable c3x2: got %#x\n", res); + + res = ID3DXConstantTable_SetMatrix(ctable, device, "r3x2", &fmatrix); + ok(res == D3D_OK, "ID3DXConstantTable_SetMatrix failed on variable r3x2: got %#x\n", res); + + res = ID3DXConstantTable_SetMatrix(ctable, device, "c3x3", &fmatrix); + ok(res == D3D_OK, "ID3DXConstantTable_SetMatrix failed on variable c3x3: got %#x\n", res); + + IDirect3DDevice9_GetVertexShaderConstantF(device, 7, out, 3); + ok(out[0] == S(U(fmatrix))._11 && out[1] == S(U(fmatrix))._21 && out[2] == 0.0f && out[3] == 0.0f + && out[4] == S(U(fmatrix))._12 && out[5] == S(U(fmatrix))._22 && out[6] == 0.0f && out[7] == 0.0f + && out[8] == S(U(fmatrix))._13 && out[9] == S(U(fmatrix))._23 && out[10] == 0.0f && out[11] == 0.0f, + "The variable c2x3 was not set correctly, out={%f, %f, %f, %f; %f, %f, %f, %f; %f, %f, %f, %f}, " + "should be {%f, %f, %f, %f; %f, %f, %f, %f; %f, %f, %f, %f}\n", + out[0], out[1], out[2], out[3], + out[4], out[5], out[6], out[7], + out[8], out[9], out[10], out[11], + S(U(fmatrix))._11, S(U(fmatrix))._21, 0.0f, 0.0f, + S(U(fmatrix))._12, S(U(fmatrix))._22, 0.0f, 0.0f, + S(U(fmatrix))._13, S(U(fmatrix))._23, 0.0f, 0.0f); + + res = ID3DXConstantTable_SetMatrix(ctable, device, "r4x4", &fmatrix); + ok(res == D3D_OK, "ID3DXConstantTable_SetMatrix failed on variable r4x4: got %#x\n", res); + + IDirect3DDevice9_GetVertexShaderConstantF(device, 15, out, 2); + ok(out[0] == S(U(fmatrix))._11 && out[1] == S(U(fmatrix))._12 && out[2] == S(U(fmatrix))._13 && out[3] == 0.0f + && out[4] == S(U(fmatrix))._21 && out[5] == S(U(fmatrix))._22 && out[6] == S(U(fmatrix))._23 && out[7] == 0.0f, + "The variable r2x3 was not set correctly, out={%f, %f, %f, %f; %f, %f, %f, %f}, " + "should be {%f, %f, %f, %f; %f, %f, %f, %f}\n", + out[0], out[1], out[2], out[3], out[4], out[5], out[6], out[7], + S(U(fmatrix))._11, S(U(fmatrix))._12, S(U(fmatrix))._13, 0.0f, + S(U(fmatrix))._21, S(U(fmatrix))._22, S(U(fmatrix))._23, 0.0f); + + IDirect3DDevice9_GetVertexShaderConstantF(device, 13, out, 2); + ok(out[0] == S(U(fmatrix))._11 && out[1] == S(U(fmatrix))._21 && out[2] == S(U(fmatrix))._31 && out[3] == 0.0f + && out[4] == S(U(fmatrix))._12 && out[5] == S(U(fmatrix))._22 && out[6] == S(U(fmatrix))._32 && out[7] == 0.0f, + "The variable c3x2 was not set correctly, out={%f, %f, %f, %f; %f, %f, %f, %f}, " + "should be {%f, %f, %f, %f; %f, %f, %f, %f}\n", + out[0], out[1], out[2], out[3], out[4], out[5], out[6], out[7], + S(U(fmatrix))._11, S(U(fmatrix))._21, S(U(fmatrix))._31, 0.0f, + S(U(fmatrix))._12, S(U(fmatrix))._22, S(U(fmatrix))._32, 0.0f); + + IDirect3DDevice9_GetVertexShaderConstantF(device, 4, out, 3); + ok(out[0] == S(U(fmatrix))._11 && out[1] == S(U(fmatrix))._12 && out[2] == 0.0f && out[3] == 0.0f + && out[4] == S(U(fmatrix))._21 && out[5] == S(U(fmatrix))._22 && out[6] == 0.0f && out[7] == 0.0f + && out[8] == S(U(fmatrix))._31 && out[9] == S(U(fmatrix))._32 && out[10] == 0.0f && out[11] == 0.0f, + "The variable r3x2 was not set correctly, out={%f, %f, %f, %f; %f, %f, %f, %f; %f, %f, %f, %f}, " + "should be {%f, %f, %f, %f; %f, %f, %f, %f; %f, %f, %f, %f}\n", + out[0], out[1], out[2], out[3], out[4], out[5], out[6], out[7], out[8], out[9], out[10], out[11], + S(U(fmatrix))._11, S(U(fmatrix))._12, 0.0f, 0.0f, + S(U(fmatrix))._21, S(U(fmatrix))._22, 0.0f, 0.0f, + S(U(fmatrix))._31, S(U(fmatrix))._32, 0.0f, 0.0f); + + IDirect3DDevice9_GetVertexShaderConstantF(device, 10, out, 3); + ok(out[0] == S(U(fmatrix))._11 && out[1] == S(U(fmatrix))._21 && out[2] == S(U(fmatrix))._31 && out[3] == 0.0f + && out[4] == S(U(fmatrix))._12 && out[5] == S(U(fmatrix))._22 && out[6] == S(U(fmatrix))._32 && out[7] == 0.0f + && out[8] == S(U(fmatrix))._13 && out[9] == S(U(fmatrix))._23 && out[10] == S(U(fmatrix))._33 && out[11] == 0.0f, + "The variable c3x3 was not set correctly, out={%f, %f, %f, %f; %f, %f, %f, %f; %f, %f, %f, %f}, " + "should be {%f, %f, %f, %f; %f, %f, %f, %f; %f, %f, %f, %f}\n", + out[0], out[1], out[2], out[3], out[4], out[5], out[6], out[7], out[8], out[9], out[10], out[11], + S(U(fmatrix))._11, S(U(fmatrix))._21, S(U(fmatrix))._31, 0.0f, + S(U(fmatrix))._12, S(U(fmatrix))._22, S(U(fmatrix))._32, 0.0f, + S(U(fmatrix))._13, S(U(fmatrix))._23, S(U(fmatrix))._33, 0.0f); + + IDirect3DDevice9_GetVertexShaderConstantF(device, 0, out, 4); + ok(out[0] == S(U(fmatrix))._11 && out[1] == S(U(fmatrix))._12 && out[2] == S(U(fmatrix))._13 && out[3] == S(U(fmatrix))._14 + && out[4] == S(U(fmatrix))._21 && out[5] == S(U(fmatrix))._22 && out[6] == S(U(fmatrix))._23 && out[7] == S(U(fmatrix))._24 + && out[8] == S(U(fmatrix))._31 && out[9] == S(U(fmatrix))._32 && out[10] == S(U(fmatrix))._33 && out[11] == S(U(fmatrix))._34 + && out[12] == S(U(fmatrix))._41 && out[13] == S(U(fmatrix))._42 && out[14] == S(U(fmatrix))._43 && out[15] == S(U(fmatrix))._44, + "The variable r4x4 was not set correctly, out={%f, %f, %f, %f; %f, %f, %f, %f; %f, %f, %f, %f; %f, %f, %f, %f}, " + "should be {%f, %f, %f, %f; %f, %f, %f, %f; %f, %f, %f, %f; %f, %f, %f, %f}\n", + out[0], out[1], out[2], out[3], out[4], out[5], out[6], out[7], + out[8], out[9], out[10], out[11], out[12], out[13], out[14], out[15], + S(U(fmatrix))._11, S(U(fmatrix))._12, S(U(fmatrix))._13, S(U(fmatrix))._14, + S(U(fmatrix))._21, S(U(fmatrix))._22, S(U(fmatrix))._23, S(U(fmatrix))._24, + S(U(fmatrix))._31, S(U(fmatrix))._32, S(U(fmatrix))._33, S(U(fmatrix))._34, + S(U(fmatrix))._41, S(U(fmatrix))._42, S(U(fmatrix))._43, S(U(fmatrix))._44); + + /* SetMatrixTranspose */ + res = ID3DXConstantTable_SetMatrixTranspose(ctable, device, "c2x3", &fmatrix); + ok(res == D3D_OK, "ID3DXConstantTable_SetMatrixTranspose failed on variable c2x3: got %#x\n", res); + + res = ID3DXConstantTable_SetMatrixTranspose(ctable, device, "r2x3", &fmatrix); + ok(res == D3D_OK, "ID3DXConstantTable_SetMatrixTranspose failed on variable r2x3: got %#x\n", res); + + IDirect3DDevice9_GetVertexShaderConstantF(device, 7, out, 3); + ok(out[0] == S(U(fmatrix))._11 && out[1] == S(U(fmatrix))._12 && out[2] == 0.0f && out[3] == 0.0f + && out[4] == S(U(fmatrix))._21 && out[5] == S(U(fmatrix))._22 && out[6] == 0.0f && out[7] == 0.0f + && out[8] == S(U(fmatrix))._31 && out[9] == S(U(fmatrix))._32 && out[10] == 0.0f && out[11] == 0.0f, + "The variable c2x3 was not set correctly, out={%f, %f, %f, %f; %f, %f, %f, %f; %f, %f, %f, %f}, " + "should be {%f, %f, %f, %f; %f, %f, %f, %f; %f, %f, %f, %f}\n", + out[0], out[1], out[2], out[3], + out[4], out[5], out[6], out[7], + out[8], out[9], out[10], out[11], + S(U(fmatrix))._11, S(U(fmatrix))._12, 0.0f, 0.0f, + S(U(fmatrix))._21, S(U(fmatrix))._22, 0.0f, 0.0f, + S(U(fmatrix))._31, S(U(fmatrix))._32, 0.0f, 0.0f); + + IDirect3DDevice9_GetVertexShaderConstantF(device, 15, out, 2); + ok(out[0] == S(U(fmatrix))._11 && out[1] == S(U(fmatrix))._21 && out[2] == S(U(fmatrix))._31 && out[3] == 0.0f + && out[4] == S(U(fmatrix))._12 && out[5] == S(U(fmatrix))._22 && out[6] == S(U(fmatrix))._32 && out[7] == 0.0f, + "The variable r2x3 was not set correctly, out={%f, %f, %f, %f; %f, %f, %f, %f}, " + "should be {%f, %f, %f, %f; %f, %f, %f, %f}\n", + out[0], out[1], out[2], out[3], out[4], out[5], out[6], out[7], + S(U(fmatrix))._11, S(U(fmatrix))._21, S(U(fmatrix))._31, 0.0f, + S(U(fmatrix))._12, S(U(fmatrix))._22, S(U(fmatrix))._32, 0.0f); + + /* SetMatrixPointerArray */ + res = ID3DXConstantTable_SetMatrixPointerArray(ctable, device, "c2x3", matrix_pointer, 1); + ok(res == D3D_OK, "ID3DXConstantTable_SetMatrixPointerArray failed on variable c2x3: got %#x\n", res); + + res = ID3DXConstantTable_SetMatrixPointerArray(ctable, device, "r2x3", matrix_pointer, 1); + ok(res == D3D_OK, "ID3DXConstantTable_SetMatrixPointerArray failed on variable r2x3: got %#x\n", res); + + IDirect3DDevice9_GetVertexShaderConstantF(device, 7, out, 3); + ok(out[0] == S(U(fmatrix))._11 && out[1] == S(U(fmatrix))._21 && out[2] == 0.0f && out[3] == 0.0f + && out[4] == S(U(fmatrix))._12 && out[5] == S(U(fmatrix))._22 && out[6] == 0.0f && out[7] == 0.0f + && out[8] == S(U(fmatrix))._13 && out[9] == S(U(fmatrix))._23 && out[10] == 0.0f && out[11] == 0.0f, + "The variable c2x3 was not set correctly, out={%f, %f, %f, %f; %f, %f, %f, %f; %f, %f, %f, %f}, " + "should be {%f, %f, %f, %f; %f, %f, %f, %f; %f, %f, %f, %f}\n", + out[0], out[1], out[2], out[3], + out[4], out[5], out[6], out[7], + out[8], out[9], out[10], out[11], + S(U(fmatrix))._11, S(U(fmatrix))._21, 0.0f, 0.0f, + S(U(fmatrix))._12, S(U(fmatrix))._22, 0.0f, 0.0f, + S(U(fmatrix))._13, S(U(fmatrix))._23, 0.0f, 0.0f); + + IDirect3DDevice9_GetVertexShaderConstantF(device, 15, out, 2); + ok(out[0] == S(U(fmatrix))._11 && out[1] == S(U(fmatrix))._12 && out[2] == S(U(fmatrix))._13 && out[3] == 0.0f + && out[4] == S(U(fmatrix))._21 && out[5] == S(U(fmatrix))._22 && out[6] == S(U(fmatrix))._23 && out[7] == 0.0f, + "The variable r2x3 was not set correctly, out={%f, %f, %f, %f; %f, %f, %f, %f}, " + "should be {%f, %f, %f, %f; %f, %f, %f, %f}\n", + out[0], out[1], out[2], out[3], out[4], out[5], out[6], out[7], + S(U(fmatrix))._11, S(U(fmatrix))._12, S(U(fmatrix))._13, 0.0f, + S(U(fmatrix))._21, S(U(fmatrix))._22, S(U(fmatrix))._23, 0.0f); + + /* SetMatrixTransposePointerArray */ + res = ID3DXConstantTable_SetMatrixTransposePointerArray(ctable, device, "c2x3", matrix_pointer, 1); + ok(res == D3D_OK, "ID3DXConstantTable_SetMatrixTransposePointerArray failed on variable c2x3: got %#x\n", res); + + res = ID3DXConstantTable_SetMatrixTransposePointerArray(ctable, device, "r2x3", matrix_pointer, 1); + ok(res == D3D_OK, "ID3DXConstantTable_SetMatrixTransposePointerArray failed on variable r2x3: got %#x\n", res); + + IDirect3DDevice9_GetVertexShaderConstantF(device, 7, out, 3); + ok(out[0] == S(U(fmatrix))._11 && out[1] == S(U(fmatrix))._12 && out[2] == 0.0f && out[3] == 0.0f + && out[4] == S(U(fmatrix))._21 && out[5] == S(U(fmatrix))._22 && out[6] == 0.0f && out[7] == 0.0f + && out[8] == S(U(fmatrix))._31 && out[9] == S(U(fmatrix))._32 && out[10] == 0.0f && out[11] == 0.0f, + "The variable c2x3 was not set correctly, out={%f, %f, %f, %f; %f, %f, %f, %f; %f, %f, %f, %f}, " + "should be {%f, %f, %f, %f; %f, %f, %f, %f; %f, %f, %f, %f}\n", + out[0], out[1], out[2], out[3], + out[4], out[5], out[6], out[7], + out[8], out[9], out[10], out[11], + S(U(fmatrix))._11, S(U(fmatrix))._12, 0.0f, 0.0f, + S(U(fmatrix))._21, S(U(fmatrix))._22, 0.0f, 0.0f, + S(U(fmatrix))._31, S(U(fmatrix))._32, 0.0f, 0.0f); + + IDirect3DDevice9_GetVertexShaderConstantF(device, 15, out, 2); + ok(out[0] == S(U(fmatrix))._11 && out[1] == S(U(fmatrix))._21 && out[2] == S(U(fmatrix))._31 && out[3] == 0.0f + && out[4] == S(U(fmatrix))._12 && out[5] == S(U(fmatrix))._22 && out[6] == S(U(fmatrix))._32 && out[7] == 0.0f, + "The variable r2x3 was not set correctly, out={%f, %f, %f, %f; %f, %f, %f, %f}, " + "should be {%f, %f, %f, %f; %f, %f, %f, %f}\n", + out[0], out[1], out[2], out[3], out[4], out[5], out[6], out[7], + S(U(fmatrix))._11, S(U(fmatrix))._21, S(U(fmatrix))._31, 0.0f, + S(U(fmatrix))._12, S(U(fmatrix))._22, S(U(fmatrix))._32, 0.0f); + + ID3DXConstantTable_Release(ctable); +} + +static void test_setting_arrays_table(IDirect3DDevice9 *device) +{ + static const float farray[8] = { + 0.005f, 0.745f, 0.973f, 0.264f, + 0.010f, 0.020f, 0.030f, 0.040f}; + static const D3DXMATRIX fmtxarray[2] = { + {{{0.001f, 0.002f, 0.003f, 0.004f, + 0.005f, 0.006f, 0.007f, 0.008f, + 0.009f, 0.010f, 0.011f, 0.012f, + 0.013f, 0.014f, 0.015f, 0.016f}}}, + {{{0.010f, 0.020f, 0.030f, 0.040f, + 0.050f, 0.060f, 0.070f, 0.080f, + 0.090f, 0.100f, 0.110f, 0.120f, + 0.130f, 0.140f, 0.150f, 0.160f}}}}; + static const int iarray[4] = {1, 2, 3, 4}; + static const D3DXVECTOR4 fvecarray[2] = { + {0.745f, 0.997f, 0.353f, 0.237f}, + {0.060f, 0.455f, 0.333f, 0.983f}}; + static BOOL barray[4] = {FALSE, 100, TRUE, TRUE}; + + ID3DXConstantTable *ctable; + + HRESULT res; + float out[32]; + ULONG refcnt; + + /* Clear registers */ + memset(out, 0, sizeof(out)); + IDirect3DDevice9_SetVertexShaderConstantF(device, 8, out, 4); + IDirect3DDevice9_SetVertexShaderConstantF(device, 12, out, 4); + + /* Get the constant table from the shader */ + res = D3DXGetShaderConstantTable(ctab_arrays, &ctable); + ok(res == D3D_OK, "D3DXGetShaderConstantTable failed: got 0x%08x\n", res); + + /* Set constants */ + + /* Make sure that we cannot set registers that do not belong to this constant */ + res = ID3DXConstantTable_SetFloatArray(ctable, device, "farray", farray, 8); + ok(res == D3D_OK, "ID3DXConstantTable_SetFloatArray failed: got 0x%08x\n", res); + + IDirect3DDevice9_GetVertexShaderConstantF(device, 8, out, 8); + ok(out[0] == farray[0] && out[4] == farray[1] && out[8] == farray[2] && out[12] == farray[3], + "The in-bounds elements of the array were not set, out={%f, %f, %f, %f}, should be {%f, %f, %f, %f}\n", + out[0], out[4], out[8], out[12], farray[0], farray[1], farray[2], farray[3]); + ok(out[16] == 0.0f && out[20] == 0.0f && out[24] == 0.0f && out[28] == 0.0f, + "The excess elements of the array were set, out={%f, %f, %f, %f}, should be all 0.0f\n", + out[16], out[20], out[24], out[28]); + + /* ivecarray takes up only 1 register, but a matrix takes up 4, so no elements should be set */ + res = ID3DXConstantTable_SetMatrix(ctable, device, "ivecarray", &fmtxarray[0]); + ok(res == D3D_OK, "ID3DXConstantTable_SetMatrix failed: got 0x%08x\n", res); + + IDirect3DDevice9_GetVertexShaderConstantF(device, 18, out, 4); + ok(out[0] == 0.0f && out[1] == 0.0f && out[2] == 0.0f && out[3] == 0.0f, + "The array was set, out={%f, %f, %f, %f}, should be all 0.0f\n", out[0], out[1], out[2], out[3]); + + /* Try setting an integer array to an array declared as a float array */ + res = ID3DXConstantTable_SetIntArray(ctable, device, "farray", iarray, 4); + ok(res == D3D_OK, "ID3DXConstantTable_SetIntArray failed: got 0x%08x\n", res); + + IDirect3DDevice9_GetVertexShaderConstantF(device, 8, out, 4); + ok(out[0] == iarray[0] && out[4] == iarray[1] && out[8] == iarray[2] && out[12] == iarray[3], + "SetIntArray did not properly set a float array: out={%f, %f, %f, %f}, should be {%d, %d, %d, %d}\n", + out[0], out[4], out[8], out[12], iarray[0], iarray[1], iarray[2], iarray[3]); + + res = ID3DXConstantTable_SetFloatArray(ctable, device, "farray", farray, 4); + ok(res == D3D_OK, "ID3DXConstantTable_SetFloatArray failed: got x0%08x\n", res); + + res = ID3DXConstantTable_SetVectorArray(ctable, device, "fvecarray", fvecarray, 2); + ok(res == D3D_OK, "ID3DXConstantTable_SetVectorArray failed: got 0x%08x\n", res); + + res = ID3DXConstantTable_SetMatrixArray(ctable, device, "fmtxarray", fmtxarray, 2); + ok(res == D3D_OK, "ID3DXConstantTable_SetMatrixArray failed: got 0x%08x\n", res); + + res = ID3DXConstantTable_SetBoolArray(ctable, device, "barray", barray, 2); + ok(res == D3D_OK, "ID3DXConstantTable_SetBoolArray failed: got 0x%08x\n", res); + + /* Read back constants */ + IDirect3DDevice9_GetVertexShaderConstantF(device, 8, out, 4); + ok(out[0] == farray[0] && out[4] == farray[1] && out[8] == farray[2] && out[12] == farray[3], + "The variable farray was not set correctly, out={%f, %f, %f, %f}, should be {%f, %f, %f, %f}\n", + out[0], out[4], out[8], out[12], farray[0], farray[1], farray[2], farray[3]); + + IDirect3DDevice9_GetVertexShaderConstantF(device, 12, out, 2); + ok(out[0] == fvecarray[0].x && out[1] == fvecarray[0].y && out[2] == fvecarray[0].z && out[3] == fvecarray[0].w && + out[4] == fvecarray[1].x && out[5] == fvecarray[1].y && out[6] == fvecarray[1].z && out[7] == fvecarray[1].w, + "The variable fvecarray was not set correctly, out={{%f, %f, %f, %f}, {%f, %f, %f, %f}}, should be " + "{{%f, %f, %f, %f}, {%f, %f, %f, %f}}\n", out[0], out[1], out[2], out[3], out[4], out[5], out[6], out[7], + fvecarray[0].x, fvecarray[0].y, fvecarray[0].z, fvecarray[0].w, fvecarray[1].x, fvecarray[1].y, + fvecarray[1].z, fvecarray[1].w); + + IDirect3DDevice9_GetVertexShaderConstantF(device, 14, out, 2); + ok(out[0] == 0.0f && out[1] == 0.0f && out[2] == 0.0f && out[3] == 0.0f + && out[4] == 1.0f && out[5] == 0.0f && out[6] == 0.0f && out[7] == 0.0f, + "The variable barray was not set correctly, out={%f, %f %f, %f; %f, %f, %f, %f}, should be {%f, %f, %f, %f; %f, %f, %f, %f}\n", + out[0], out[1], out[2], out[3], out[4], out[5], out[6], out[7], + 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f); + + IDirect3DDevice9_GetVertexShaderConstantF(device, 0, out, 8); + /* Just check a few elements in each matrix to make sure fmtxarray was set row-major */ + ok(out[0] == S(U(fmtxarray[0]))._11 && out[1] == S(U(fmtxarray[0]))._12 && out[2] == S(U(fmtxarray[0]))._13 && out[3] == S(U(fmtxarray[0]))._14, + "The variable fmtxarray was not set row-major, out={%f, %f, %f, %f}, should be {%f, %f, %f, %f}\n", + out[0], out[1], out[2], out[3], S(U(fmtxarray[0]))._11, S(U(fmtxarray[0]))._12, S(U(fmtxarray[0]))._13, S(U(fmtxarray[0]))._14); + ok(out[16] == S(U(fmtxarray[1]))._11 && out[17] == S(U(fmtxarray[1]))._12 && out[18] == S(U(fmtxarray[1]))._13 && out[19] == S(U(fmtxarray[1]))._14, + "The variable fmtxarray was not set row-major, out={%f, %f, %f, %f}, should be {%f, %f, %f, %f}\n", + out[16], out[17], out[18], out[19], S(U(fmtxarray[1]))._11, S(U(fmtxarray[1]))._12, S(U(fmtxarray[1]))._13, S(U(fmtxarray[1]))._14); + + refcnt = ID3DXConstantTable_Release(ctable); + ok(refcnt == 0, "The constant table reference count was %u, should be 0\n", refcnt); +} + +static void test_SetDefaults(IDirect3DDevice9 *device) +{ + static const D3DXMATRIX mvp = {{{ + 0.51f, 0.62f, 0.80f, 0.78f, + 0.23f, 0.95f, 0.37f, 0.48f, + 0.10f, 0.58f, 0.90f, 0.25f, + 0.89f, 0.41f, 0.93f, 0.27f}}}; + static const D3DXVECTOR4 f4 = {0.2f, 0.4f, 0.8f, 1.2f}; + + float out[16]; + + HRESULT res; + ID3DXConstantTable *ctable; + + res = D3DXGetShaderConstantTable(ctab_basic, &ctable); + ok(res == D3D_OK, "D3DXGetShaderConstantTable failed: got %08x\n", res); + + res = ID3DXConstantTable_SetVector(ctable, device, "f4", &f4); + ok(res == D3D_OK, "ID3DXConstantTable_SetVector failed: got %08x\n", res); + + res = ID3DXConstantTable_SetMatrix(ctable, device, "mvp", &mvp); + ok(res == D3D_OK, "ID3DXConstantTable_SetMatrix failed: got %08x\n", res); + + res = ID3DXConstantTable_SetDefaults(ctable, device); + ok(res == D3D_OK, "ID3dXConstantTable_SetDefaults failed: got %08x\n", res); + + /* SetDefaults doesn't change constants without default values */ + IDirect3DDevice9_GetVertexShaderConstantF(device, 0, out, 4); + ok(out[0] == S(U(mvp))._11 && out[4] == S(U(mvp))._12 && out[8] == S(U(mvp))._13 && out[12] == S(U(mvp))._14, + "The first row of mvp was not set correctly, got {%f, %f, %f, %f}, should be {%f, %f, %f, %f}\n", + out[0], out[4], out[8], out[12], S(U(mvp))._11, S(U(mvp))._12, S(U(mvp))._13, S(U(mvp))._14); + ok(out[1] == S(U(mvp))._21 && out[5] == S(U(mvp))._22 && out[9] == S(U(mvp))._23 && out[13] == S(U(mvp))._24, + "The second row of mvp was not set correctly, got {%f, %f, %f, %f}, should be {%f, %f, %f, %f}\n", + out[1], out[5], out[9], out[13], S(U(mvp))._21, S(U(mvp))._22, S(U(mvp))._23, S(U(mvp))._24); + ok(out[2] == S(U(mvp))._31 && out[6] == S(U(mvp))._32 && out[10] == S(U(mvp))._33 && out[14] == S(U(mvp))._34, + "The third row of mvp was not set correctly, got {%f, %f, %f, %f}, should be {%f, %f, %f, %f}\n", + out[2], out[6], out[10], out[14], S(U(mvp))._31, S(U(mvp))._32, S(U(mvp))._33, S(U(mvp))._34); + ok(out[3] == S(U(mvp))._41 && out[7] == S(U(mvp))._42 && out[11] == S(U(mvp))._43 && out[15] == S(U(mvp))._44, + "The fourth row of mvp was not set correctly, got {%f, %f, %f, %f}, should be {%f, %f, %f, %f}\n", + out[3], out[7], out[11], out[15], S(U(mvp))._41, S(U(mvp))._42, S(U(mvp))._43, S(U(mvp))._44); + + IDirect3DDevice9_GetVertexShaderConstantF(device, 7, out, 1); + ok(memcmp(out, &f4, sizeof(f4)) == 0, + "The variable f4 was not set correctly, out={%f, %f, %f, %f}, should be {%f, %f, %f, %f}\n", + out[0], out[1], out[2], out[3], f4.x, f4.y, f4.z, f4.w); + + ID3DXConstantTable_Release(ctable); + + res = D3DXGetShaderConstantTable(ctab_with_default_values, &ctable); + ok(res == D3D_OK, "D3DXGetShaderConstantTable failed: got %08x\n", res); + + res = ID3DXConstantTable_SetDefaults(ctable, device); + ok(res == D3D_OK, "ID3DXConstantTable_SetDefaults failed: got %08x\n", res); + + IDirect3DDevice9_GetVertexShaderConstantF(device, 0, out, 4); + ok(memcmp(out, mat4_default_value, sizeof(mat4_default_value)) == 0, + "The variable mat4 was not set correctly to default value\n"); + + IDirect3DDevice9_GetVertexShaderConstantF(device, 4, out, 4); + ok(memcmp(out, mat3_default_value, sizeof(mat3_default_value)) == 0, + "The variable mat3 was not set correctly to default value\n"); + + IDirect3DDevice9_GetVertexShaderConstantF(device, 8, out, 3); + ok(memcmp(out, arr_default_value, sizeof(arr_default_value)) == 0, + "The variable array was not set correctly to default value\n"); + + IDirect3DDevice9_GetVertexShaderConstantF(device, 11, out, 1); + ok(memcmp(out, vec4_default_value, sizeof(vec4_default_value)) == 0, + "The variable vec4 was not set correctly to default value\n"); + + IDirect3DDevice9_GetVertexShaderConstantF(device, 12, out, 1); + ok(memcmp(out, flt_default_value, sizeof(flt_default_value)) == 0, + "The variable flt was not set correctly to default value\n"); + + ID3DXConstantTable_Release(ctable); +} + +static void test_SetValue(IDirect3DDevice9 *device) +{ + static const D3DXMATRIX mvp = {{{ + 0.51f, 0.62f, 0.80f, 0.78f, + 0.23f, 0.95f, 0.37f, 0.48f, + 0.10f, 0.58f, 0.90f, 0.25f, + 0.89f, 0.41f, 0.93f, 0.27f}}}; + static const D3DXVECTOR4 f4 = {0.2f, 0.4f, 0.8f, 1.2f}; + static const FLOAT arr[] = {0.33f, 0.55f, 0.96f, 1.00f, + 1.00f, 1.00f, 1.00f, 1.00f, + 1.00f, 1.00f, 1.00f, 1.00f}; + static int imatrix[] = {1, 2, 3, 4, 5, 6}; + static float fmatrix[] = {1.1f, 2.2f, 3.3f, 4.4f}; + static BOOL barray[] = {TRUE, FALSE}; + static float fvecarray[] = {9.1f, 9.2f, 9.3f, 9.4f, 9.5f, 9.6f, 9.7f, 9.8f}; + static float farray[] = {2.2f, 3.3f}; + + static const float def[16] = {5.5f, 5.5f, 5.5f, 5.5f, + 5.5f, 5.5f, 5.5f, 5.5f, + 5.5f, 5.5f, 5.5f, 5.5f, + 5.5f, 5.5f, 5.5f, 5.5f}; + float out[16]; + + HRESULT res; + ID3DXConstantTable *ctable; + + res = D3DXGetShaderConstantTable(ctab_basic, &ctable); + ok(res == D3D_OK, "D3DXGetShaderConstantTable failed: got %08x\n", res); + + IDirect3DDevice9_SetVertexShaderConstantF(device, 7, def, 1); + + /* SetValue called with 0 bytes size doesn't change value */ + res = ID3DXConstantTable_SetValue(ctable, device, "f4", &f4, 0); + ok(res == D3D_OK, "ID3DXConstantTable_SetValue failed: got %08x\n", res); + + IDirect3DDevice9_GetVertexShaderConstantF(device, 7, out, 1); + ok(memcmp(out, def, sizeof(f4)) == 0, + "The variable f4 was not set correctly, out={%f, %f, %f, %f}, should be {%f, %f, %f, %f}\n", + out[0], out[1], out[2], out[3], def[0], def[1], def[2], def[3]); + + res = ID3DXConstantTable_SetValue(ctable, device, "f4", &f4, sizeof(f4)); + ok(res == D3D_OK, "ID3DXConstantTable_SetValue failed: got %08x\n", res); + + IDirect3DDevice9_GetVertexShaderConstantF(device, 7, out, 1); + ok(memcmp(out, &f4, sizeof(f4)) == 0, + "The variable f4 was not set correctly, out={%f, %f, %f, %f}, should be {%f, %f, %f, %f}\n", + out[0], out[1], out[2], out[3], f4.x, f4.y, f4.z, f4.w); + + IDirect3DDevice9_SetVertexShaderConstantF(device, 0, def, 4); + + /* SetValue called with size smaller than constant size doesn't change value */ + res = ID3DXConstantTable_SetValue(ctable, device, "mvp", &mvp, sizeof(mvp) / 2); + ok(res == D3D_OK, "ID3DXConstantTable_SetValue returned %08x\n", res); + + IDirect3DDevice9_GetVertexShaderConstantF(device, 0, out, 4); + ok(memcmp(out, def, sizeof(def)) == 0, + "The variable mvp was not set correctly, out={%f, %f, %f, %f; %f, %f, %f, %f; %f, %f, %f, %f; %f, %f, %f, %f}, " + "should be {%f, %f, %f, %f; %f, %f, %f, %f; %f, %f, %f, %f; %f, %f, %f, %f}\n", + out[0], out[4], out[ 8], out[12], + out[1], out[5], out[ 9], out[13], + out[2], out[6], out[10], out[14], + out[3], out[7], out[11], out[15], + def[0], def[4], def[ 8], def[12], + def[1], def[5], def[ 9], def[13], + def[2], def[6], def[10], def[14], + def[3], def[7], def[11], def[15]); + + res = ID3DXConstantTable_SetValue(ctable, device, "mvp", &mvp, sizeof(mvp)); + ok(res == D3D_OK, "ID3DXConstantTable_SetValue failed: got %08x\n", res); + + IDirect3DDevice9_GetVertexShaderConstantF(device, 0, out, 4); + ok(out[0] == S(U(mvp))._11 && out[4] == S(U(mvp))._12 && out[8] == S(U(mvp))._13 && out[12] == S(U(mvp))._14, + "The first row of mvp was not set correctly, got {%f, %f, %f, %f}, should be {%f, %f, %f, %f}\n", + out[0], out[4], out[8], out[12], S(U(mvp))._11, S(U(mvp))._12, S(U(mvp))._13, S(U(mvp))._14); + ok(out[1] == S(U(mvp))._21 && out[5] == S(U(mvp))._22 && out[9] == S(U(mvp))._23 && out[13] == S(U(mvp))._24, + "The second row of mvp was not set correctly, got {%f, %f, %f, %f}, should be {%f, %f, %f, %f}\n", + out[1], out[5], out[9], out[13], S(U(mvp))._21, S(U(mvp))._22, S(U(mvp))._23, S(U(mvp))._24); + ok(out[2] == S(U(mvp))._31 && out[6] == S(U(mvp))._32 && out[10] == S(U(mvp))._33 && out[14] == S(U(mvp))._34, + "The third row of mvp was not set correctly, got {%f, %f, %f, %f}, should be {%f, %f, %f, %f}\n", + out[2], out[6], out[10], out[14], S(U(mvp))._31, S(U(mvp))._32, S(U(mvp))._33, S(U(mvp))._34); + ok(out[3] == S(U(mvp))._41 && out[7] == S(U(mvp))._42 && out[11] == S(U(mvp))._43 && out[15] == S(U(mvp))._44, + "The fourth row of mvp was not set correctly, got {%f, %f, %f, %f}, should be {%f, %f, %f, %f}\n", + out[3], out[7], out[11], out[15], S(U(mvp))._41, S(U(mvp))._42, S(U(mvp))._43, S(U(mvp))._44); + + ID3DXConstantTable_Release(ctable); + + res = D3DXGetShaderConstantTable(ctab_with_default_values, &ctable); + ok(res == D3D_OK, "D3DXGetShaderConstantTable failed: got %08x\n", res); + + res = ID3DXConstantTable_SetValue(ctable, device, "arr", arr, sizeof(arr)); + ok(res == D3D_OK, "ID3DXConstantTable_SetValue failed: got %08x\n", res); + + IDirect3DDevice9_GetVertexShaderConstantF(device, 8, out, 3); + ok(out[0] == arr[0] && out[4] == arr[1] && out[8] == arr[2] + && out[1] == 0 && out[2] == 0 && out[3] == 0 && out[5] == 0 && out[6] == 0 && out[7] == 0 + && out[9] == 0 && out[10] == 0 && out[11] == 0, + "The variable arr was not set correctly, out={%f, %f, %f, %f, %f, %f, %f, %f, %f, %f, %f, %f}, " + "should be {0.33, 0, 0, 0, 0.55, 0, 0, 0, 0.96, 0, 0, 0}\n", + out[0], out[1], out[2], out[3], out[4], out[5], out[6], out[7], out[8], out[9], out[10], out[11]); + + ID3DXConstantTable_Release(ctable); + + res = D3DXGetShaderConstantTable(ctab_matrices, &ctable); + ok(res == D3D_OK, "D3DXGetShaderConstantTable failed: got %08x\n", res); + + res = ID3DXConstantTable_SetValue(ctable, device, "fmatrix3x1", fmatrix, sizeof(fmatrix)); + ok(res == D3D_OK, "ID3DXConstantTable_SetValue failed: got %08x\n", res); + + res = ID3DXConstantTable_SetValue(ctable, device, "imatrix2x3", imatrix, sizeof(imatrix)); + ok(res == D3D_OK, "ID3DXConstantTable_SetValue failed: got %08x\n", res); + + IDirect3DDevice9_GetVertexShaderConstantF(device, 4, out, 2); + ok(out[0] == imatrix[0] && out[1] == imatrix[1] && out[2] == imatrix[2] && out[3] == 0.0f + && out[4] == imatrix[3] && out[5] == imatrix[4] && out[6] == imatrix[5] && out[7] == 0.0f, + "The variable imatrix2x3 was not set correctly, out={%f, %f, %f, %f, %f, %f, %f, %f}, " + "should be {%d, %d, %d, 0, %d, %d, %d, 0}\n", + out[0], out[1], out[2], out[3], out[4], out[5], out[6], out[7], + imatrix[0], imatrix[1], imatrix[2], imatrix[3], imatrix[4], imatrix[5]); + + IDirect3DDevice9_GetVertexShaderConstantF(device, 7, out, 2); + ok(out[0] == fmatrix[0] && out[1] == fmatrix[1] && out[2] == fmatrix[2] && out[3] == 0.0f, + "The variable fmatrix3x1 was not set correctly, out={%f, %f, %f, %f}, should be {%f, %f, %f, %f}\n", + out[0], out[1] ,out[2], out[4], + fmatrix[0], fmatrix[1], fmatrix[2], 0.0f); + + ID3DXConstantTable_Release(ctable); + + res = D3DXGetShaderConstantTable(ctab_arrays, &ctable); + ok(res == D3D_OK, "D3DXGetShaderConstantTable failed: got %08x\n", res); + + res = ID3DXConstantTable_SetValue(ctable, device, "barray", barray, sizeof(barray)); + ok(res == D3D_OK, "ID3DXConstantTable_SetValue failed: got %08x\n", res); + + res = ID3DXConstantTable_SetValue(ctable, device, "fvecarray", fvecarray, sizeof(fvecarray)); + ok(res == D3D_OK, "ID3DXConstantTable_SetValue failed: got %08x\n", res); + + IDirect3DDevice9_SetVertexShaderConstantF(device, 8, def, 4); + res = ID3DXConstantTable_SetValue(ctable, device, "farray", farray, sizeof(farray)); + ok(res == D3D_OK, "ID3DXConstantTable_SetValue failed: got %08x\n", res); + + /* 2 elements of farray were set */ + IDirect3DDevice9_GetVertexShaderConstantF(device, 8, out, 4); + ok(out[0] == farray[0] && out[1] == 0.0f && out[2] == 0.0f && out[3] == 0.0f + && out[4] == farray[1] && out[5] == 0.0f && out[6] == 0.0f && out[7] == 0.0f + && out[8] == def[8] && out[9] == def[9] && out[10] == def[10] && out[11] == def[11] + && out[12] == def[12] && out[13] == def[13] && out[14] == def[14] && out[15] == def[15], + "The variable farray was not set correctly, should be {%f, %f, %f, %f; %f, %f, %f, %f; %f, %f, %f, %f; %f, %f, %f, %f}, " + "should be {%f, %f, %f, %f; %f, %f, %f, %f; %f, %f, %f, %f; %f, %f, %f, %f}\n", + out[0], out[1], out[2], out[3], out[4], out[5], out[6], out[7], + out[8], out[9], out[10], out[11], out[12], out[13], out[14], out[15], + farray[0], 0.0f, 0.0f, 0.0f, + farray[1], 0.0f, 0.0f, 0.0f, + def[8], def[9], def[10], def[11], + def[12], def[13], def[14], def[15]); + + IDirect3DDevice9_GetVertexShaderConstantF(device, 12, out, 2); + ok(out[0] == fvecarray[0] && out[1] == fvecarray[1] && out[2] == fvecarray[2] && out[3] == fvecarray[3] + && out[4] == fvecarray[4] && out[5] == fvecarray[5] && out[6] == fvecarray[6] && out[7] == fvecarray[7], + "The variable fvecarray was not set correctly, out ={%f, %f, %f, %f, %f, %f, %f, %f}, " + "should be {%f, %f, %f, %f, %f, %f, %f, %f}\n", + out[0], out[1], out[2], out[3], out[4], out[5], out[6], out[7], + fvecarray[0], fvecarray[1], fvecarray[2], fvecarray[3], fvecarray[4], fvecarray[5], fvecarray[6], fvecarray[7]); + + IDirect3DDevice9_GetVertexShaderConstantF(device, 14, out, 2); + ok(out[0] == 1.0f && out[1] == 0.0f && out[2] == 0.0f && out[3] == 0.0f + && out[4] == 0.0f && out[5] == 0.0f && out[6] == 0.0f && out[7] == 0.0f, + "The variable barray was not set correctly, out={%f, %f, %f, %f, %f, %f, %f, %f}, " + "should be {%f, %f, %f, %f, %f, %f, %f, %f}\n", + out[0], out[1], out[2], out[3], out[4], out[5], out[6], out[7], + 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f); + + ID3DXConstantTable_Release(ctable); +} + +static void test_setting_constants(void) +{ + HWND wnd; + IDirect3D9 *d3d; + IDirect3DDevice9 *device; + D3DPRESENT_PARAMETERS d3dpp; + HRESULT hr; + ULONG refcnt; + + 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_SOFTWARE_VERTEXPROCESSING, &d3dpp, &device); + if (FAILED(hr)) + { + skip("Failed to create IDirect3DDevice9 object %#x\n", hr); + IDirect3D9_Release(d3d); + DestroyWindow(wnd); + return; + } + + test_setting_basic_table(device); + test_setting_matrices_table(device); + test_setting_arrays_table(device); + test_SetDefaults(device); + test_SetValue(device); + + /* Release resources */ + refcnt = IDirect3DDevice9_Release(device); + ok(refcnt == 0, "The Direct3D device reference count was %u, should be 0\n", refcnt); + + refcnt = IDirect3D9_Release(d3d); + ok(refcnt == 0, "The Direct3D object referenct count was %u, should be 0\n", refcnt); + + if (wnd) DestroyWindow(wnd); +} + +static void test_get_sampler_index(void) +{ + ID3DXConstantTable *ctable; + + HRESULT res; + UINT index; + + ULONG refcnt; + + res = D3DXGetShaderConstantTable(ctab_samplers, &ctable); + ok(res == D3D_OK, "D3DXGetShaderConstantTable failed on ctab_samplers: got %08x\n", res); + + index = ID3DXConstantTable_GetSamplerIndex(ctable, "sampler1"); + ok(index == 0, "ID3DXConstantTable_GetSamplerIndex returned wrong index: Got %d, expected 0\n", index); + + index = ID3DXConstantTable_GetSamplerIndex(ctable, "sampler2"); + ok(index == 3, "ID3DXConstantTable_GetSamplerIndex returned wrong index: Got %d, expected 3\n", index); + + index = ID3DXConstantTable_GetSamplerIndex(ctable, "nonexistent"); + ok(index == -1, "ID3DXConstantTable_GetSamplerIndex found nonexistent sampler: Got %d\n", + index); + + index = ID3DXConstantTable_GetSamplerIndex(ctable, "notsampler"); + ok(index == -1, "ID3DXConstantTable_GetSamplerIndex succeeded on non-sampler constant: Got %d\n", + index); + + refcnt = ID3DXConstantTable_Release(ctable); + ok(refcnt == 0, "The ID3DXConstantTable reference count was %u, should be 0\n", refcnt); +} + +/* + * fxc.exe /Tps_3_0 + */ +#if 0 +sampler s; +sampler1D s1D; +sampler2D s2D; +sampler3D s3D; +samplerCUBE scube; +float4 init; +float4 main(float3 tex : TEXCOORD0) : COLOR +{ + float4 tmp = init; + tmp = tmp + tex1D(s1D, tex.x); + tmp = tmp + tex1D(s1D, tex.y); + tmp = tmp + tex3D(s3D, tex.xyz); + tmp = tmp + tex1D(s, tex.x); + tmp = tmp + tex2D(s2D, tex.xy); + tmp = tmp + texCUBE(scube, tex.xyz); + return tmp; +} +#endif +static const DWORD get_shader_samplers_blob[] = +{ + 0xffff0300, /* ps_3_0 */ + 0x0054fffe, FCC_CTAB, /* CTAB comment */ + 0x0000001c, 0x0000011b, 0xffff0300, 0x00000006, 0x0000001c, 0x00000100, /* Header */ + 0x00000114, + 0x00000094, 0x00000002, 0x00000001, 0x0000009c, 0x00000000, /* Constant 1 desc (init) */ + 0x000000ac, 0x00040003, 0x00000001, 0x000000b0, 0x00000000, /* Constant 2 desc (s) */ + 0x000000c0, 0x00000003, 0x00000001, 0x000000c4, 0x00000000, /* Constant 3 desc (s1D) */ + 0x000000d4, 0x00010003, 0x00000001, 0x000000d8, 0x00000000, /* Constant 4 desc (s2D) */ + 0x000000e8, 0x00030003, 0x00000001, 0x000000ec, 0x00000000, /* Constant 5 desc (s3D) */ + 0x000000fc, 0x00020003, 0x00000001, 0x00000104, 0x00000000, /* Constant 6 desc (scube) */ + 0x74696e69, 0xababab00, /* Constant 1 name */ + 0x00030001, 0x00040001, 0x00000001, 0x00000000, /* Constant 1 type desc */ + 0xabab0073, /* Constant 2 name */ + 0x000c0004, 0x00010001, 0x00000001, 0x00000000, /* Constant 2 type desc */ + 0x00443173, /* Constant 3 name */ + 0x000b0004, 0x00010001, 0x00000001, 0x00000000, /* Constant 3 type desc */ + 0x00443273, /* Constant 4 name */ + 0x000c0004, 0x00010001, 0x00000001, 0x00000000, /* Constant 4 type desc */ + 0x00443373, /* Constant 5 name */ + 0x000d0004, 0x00010001, 0x00000001, 0x00000000, /* Constant 5 type desc */ + 0x62756373, 0xabab0065, /* Constant 6 name */ + 0x000e0004, 0x00010001, 0x00000001, 0x00000000, /* Constant 6 type desc */ + 0x335f7370, 0x4d00305f, 0x6f726369, 0x74666f73, 0x29522820, 0x534c4820, /* Target/Creator name string */ + 0x6853204c, 0x72656461, 0x6d6f4320, 0x656c6970, 0x2e392072, 0x392e3932, + 0x332e3235, 0x00313131, + 0x0200001f, 0x80000005, 0x90070000, 0x0200001f, 0x90000000, 0xa00f0800, /* shader */ + 0x0200001f, 0x90000000, 0xa00f0801, 0x0200001f, 0x98000000, 0xa00f0802, + 0x0200001f, 0xa0000000, 0xa00f0803, 0x0200001f, 0x90000000, 0xa00f0804, + 0x03000042, 0x800f0000, 0x90e40000, 0xa0e40800, 0x03000002, 0x800f0000, + 0x80e40000, 0xa0e40000, 0x03000042, 0x800f0001, 0x90550000, 0xa0e40800, + 0x03000002, 0x800f0000, 0x80e40000, 0x80e40001, 0x03000042, 0x800f0001, + 0x90e40000, 0xa0e40803, 0x03000002, 0x800f0000, 0x80e40000, 0x80e40001, + 0x03000042, 0x800f0001, 0x90e40000, 0xa0e40804, 0x03000002, 0x800f0000, + 0x80e40000, 0x80e40001, 0x03000042, 0x800f0001, 0x90e40000, 0xa0e40801, + 0x03000002, 0x800f0000, 0x80e40000, 0x80e40001, 0x03000042, 0x800f0001, + 0x90e40000, 0xa0e40802, 0x03000002, 0x800f0800, 0x80e40000, 0x80e40001, + 0x0000ffff, /* END */ +}; + +static void test_get_shader_samplers(void) +{ + const char *samplers[16] = {NULL}; /* maximum number of sampler registers v/ps 3.0 = 16 */ + const char *sampler_orig; + UINT count = 2; + HRESULT hr; + +if (0) +{ + /* crashes if bytecode is NULL */ + hr = D3DXGetShaderSamplers(NULL, NULL, &count); + ok(hr == D3D_OK, "D3DXGetShaderSamplers failed, got %x, expected %x\n", hr, D3D_OK); +} + + hr = D3DXGetShaderSamplers(get_shader_samplers_blob, NULL, NULL); + ok(hr == D3D_OK, "D3DXGetShaderSamplers failed, got %x, expected %x\n", hr, D3D_OK); + + samplers[5] = "dummy"; + + hr = D3DXGetShaderSamplers(get_shader_samplers_blob, samplers, NULL); + ok(hr == D3D_OK, "D3DXGetShaderSamplers failed, got %x, expected %x\n", hr, D3D_OK); + + /* check that sampler points to shader blob */ + sampler_orig = (const char *)&get_shader_samplers_blob[0x2e]; + ok(sampler_orig == samplers[0], "D3DXGetShaderSamplers failed, got %p, expected %p\n", samplers[0], sampler_orig); + + sampler_orig = (const char *)&get_shader_samplers_blob[0x33]; + ok(sampler_orig == samplers[1], "D3DXGetShaderSamplers failed, got %p, expected %p\n", samplers[1], sampler_orig); + + sampler_orig = (const char *)&get_shader_samplers_blob[0x38]; + ok(sampler_orig == samplers[2], "D3DXGetShaderSamplers failed, got %p, expected %p\n", samplers[2], sampler_orig); + + sampler_orig = (const char *)&get_shader_samplers_blob[0x3d]; + ok(sampler_orig == samplers[3], "D3DXGetShaderSamplers failed, got %p, expected %p\n", samplers[3], sampler_orig); + + sampler_orig = (const char *)&get_shader_samplers_blob[0x42]; + ok(sampler_orig == samplers[4], "D3DXGetShaderSamplers failed, got %p, expected %p\n", samplers[4], sampler_orig); + + ok(!strcmp(samplers[5], "dummy"), "D3DXGetShaderSamplers failed, got \"%s\", expected \"%s\"\n", samplers[5], "dummy"); + + /* reset samplers */ + memset(samplers, 0, sizeof(samplers)); + samplers[5] = "dummy"; + + hr = D3DXGetShaderSamplers(get_shader_samplers_blob, NULL, &count); + ok(hr == D3D_OK, "D3DXGetShaderSamplers failed, got %x, expected %x\n", hr, D3D_OK); + ok(count == 5, "D3DXGetShaderSamplers failed, got %u, expected %u\n", count, 5); + + hr = D3DXGetShaderSamplers(get_shader_samplers_blob, samplers, &count); + ok(hr == D3D_OK, "D3DXGetShaderSamplers failed, got %x, expected %x\n", hr, D3D_OK); + ok(count == 5, "D3DXGetShaderSamplers failed, got %u, expected %u\n", count, 5); + + /* check that sampler points to shader blob */ + sampler_orig = (const char *)&get_shader_samplers_blob[0x2e]; + ok(sampler_orig == samplers[0], "D3DXGetShaderSamplers failed, got %p, expected %p\n", samplers[0], sampler_orig); + + sampler_orig = (const char *)&get_shader_samplers_blob[0x33]; + ok(sampler_orig == samplers[1], "D3DXGetShaderSamplers failed, got %p, expected %p\n", samplers[1], sampler_orig); + + sampler_orig = (const char *)&get_shader_samplers_blob[0x38]; + ok(sampler_orig == samplers[2], "D3DXGetShaderSamplers failed, got %p, expected %p\n", samplers[2], sampler_orig); + + sampler_orig = (const char *)&get_shader_samplers_blob[0x3d]; + ok(sampler_orig == samplers[3], "D3DXGetShaderSamplers failed, got %p, expected %p\n", samplers[3], sampler_orig); + + sampler_orig = (const char *)&get_shader_samplers_blob[0x42]; + ok(sampler_orig == samplers[4], "D3DXGetShaderSamplers failed, got %p, expected %p\n", samplers[4], sampler_orig); + + ok(!strcmp(samplers[5], "dummy"), "D3DXGetShaderSamplers failed, got \"%s\", expected \"%s\"\n", samplers[5], "dummy"); + + /* check without ctab */ + hr = D3DXGetShaderSamplers(simple_vs, samplers, &count); + ok(hr == D3D_OK, "D3DXGetShaderSamplers failed, got %x, expected %x\n", hr, D3D_OK); + ok(count == 0, "D3DXGetShaderSamplers failed, got %u, expected %u\n", count, 0); + + /* check invalid ctab */ + hr = D3DXGetShaderSamplers(shader_with_invalid_ctab, samplers, &count); + ok(hr == D3D_OK, "D3DXGetShaderSamplers failed, got %x, expected %x\n", hr, D3D_OK); + ok(count == 0, "D3DXGetShaderSamplers failed, got %u, expected %u\n", count, 0); +} + +/* + * fxc.exe /Tvs_3_0 + */ +#if 0 +float f = {1.1f}, f_2[2] = {2.1f, 2.2f}; +struct {float f; int i;} s = {3.1f, 31}, +s_2[2] = {{4.1f, 41}, {4.2f, 42}}, +s_3[3] = {{5.1f, 51}, {5.2f, 52}, {5.3f, 53}}; +struct {int i1; int i2; float2 f_2; row_major float3x1 r[2];} +p[2] = {{11, 12, {13.1, 14.1}, {{3.11, 3.21, 3.31}, {3.41, 3.51, 3.61}}}, + {15, 16, {17.1, 18.1}, {{4.11, 4.21, 4.31}, {4.41, 4.51, 4.61}}}}; +int i[1] = {6}; +float2x3 f23[2] = {{0.11, 0.21, 0.31, 0.41, 0.51, 0.61}, {0.12, 0.22, 0.32, 0.42, 0.52, 0.62}}; +float3x2 f32[2] = {{1.11, 1.21, 1.31, 1.41, 1.51, 1.61}, {1.12, 1.22, 1.32, 1.42, 1.52, 1.62}}; +float3 v[2] = {{2.11, 2.21, 2.31}, {2.41, 2.51, 2.61}}; +row_major float3x1 r31[2] = {{3.11, 3.21, 3.31}, {3.41, 3.51, 3.61}}; +row_major float1x3 r13[2] = {{4.11, 4.21, 4.31}, {4.41, 4.51, 4.61}}; +float4 main(float4 pos : POSITION) : POSITION +{ + float4 tmp = 0.0f; + tmp.zyw = v[1] + r13[1] + r31[1] + p[1].r[1]; + tmp.x += f * f_2[1] * pos.x * p[1].f_2.y; + tmp.y += s.f * pos.y * s_2[0].i; + tmp.z += s_3[0].f * pos.z * s_3[2].f * i[0] * f23[1]._11 * f32[1]._32; + return tmp; +} +#endif +static const DWORD test_get_shader_constant_variables_blob[] = +{ +0xfffe0300, 0x0185fffe, 0x42415443, 0x0000001c, 0x000005df, 0xfffe0300, 0x0000000c, 0x0000001c, +0x00000100, 0x000005d8, 0x0000010c, 0x002d0002, 0x00000001, 0x00000110, 0x00000120, 0x00000130, +0x001d0002, 0x00000004, 0x00000134, 0x00000144, 0x000001a4, 0x00210002, 0x00000004, 0x000001a8, +0x000001b8, 0x000001f8, 0x00250002, 0x00000002, 0x000001fc, 0x0000020c, 0x0000022c, 0x002f0002, +0x00000001, 0x00000230, 0x00000240, 0x00000250, 0x00000002, 0x00000012, 0x000002b0, 0x000002c0, +0x000003e0, 0x002b0002, 0x00000002, 0x000003e4, 0x000003f4, 0x00000414, 0x00120002, 0x00000006, +0x00000418, 0x00000428, 0x00000488, 0x002e0002, 0x00000001, 0x000004ac, 0x000004bc, 0x000004dc, +0x00270002, 0x00000002, 0x000004e0, 0x000004f0, 0x00000530, 0x00180002, 0x00000005, 0x00000534, +0x00000544, 0x000005a4, 0x00290002, 0x00000002, 0x000005a8, 0x000005b8, 0xabab0066, 0x00030000, +0x00010001, 0x00000001, 0x00000000, 0x3f8ccccd, 0x00000000, 0x00000000, 0x00000000, 0x00333266, +0x00030003, 0x00030002, 0x00000002, 0x00000000, 0x3de147ae, 0x3ed1eb85, 0x00000000, 0x00000000, +0x3e570a3d, 0x3f028f5c, 0x00000000, 0x00000000, 0x3e9eb852, 0x3f1c28f6, 0x00000000, 0x00000000, +0x3df5c28f, 0x3ed70a3d, 0x00000000, 0x00000000, 0x3e6147ae, 0x3f051eb8, 0x00000000, 0x00000000, +0x3ea3d70a, 0x3f1eb852, 0x00000000, 0x00000000, 0x00323366, 0x00030003, 0x00020003, 0x00000002, +0x00000000, 0x3f8e147b, 0x3fa7ae14, 0x3fc147ae, 0x00000000, 0x3f9ae148, 0x3fb47ae1, 0x3fce147b, +0x00000000, 0x3f8f5c29, 0x3fa8f5c3, 0x3fc28f5c, 0x00000000, 0x3f9c28f6, 0x3fb5c28f, 0x3fcf5c29, +0x00000000, 0x00325f66, 0x00030000, 0x00010001, 0x00000002, 0x00000000, 0x40066666, 0x00000000, +0x00000000, 0x00000000, 0x400ccccd, 0x00000000, 0x00000000, 0x00000000, 0xabab0069, 0x00020000, +0x00010001, 0x00000001, 0x00000000, 0x40c00000, 0x00000000, 0x00000000, 0x00000000, 0x31690070, +0xababab00, 0x00020000, 0x00010001, 0x00000001, 0x00000000, 0xab003269, 0x00030001, 0x00020001, +0x00000001, 0x00000000, 0xabab0072, 0x00030002, 0x00010003, 0x00000002, 0x00000000, 0x00000252, +0x00000258, 0x00000268, 0x00000258, 0x000001f8, 0x0000026c, 0x0000027c, 0x00000280, 0x00000005, +0x000a0001, 0x00040002, 0x00000290, 0x41300000, 0x00000000, 0x00000000, 0x00000000, 0x41400000, +0x00000000, 0x00000000, 0x00000000, 0x4151999a, 0x4161999a, 0x00000000, 0x00000000, 0x40470a3d, +0x00000000, 0x00000000, 0x00000000, 0x404d70a4, 0x00000000, 0x00000000, 0x00000000, 0x4053d70a, +0x00000000, 0x00000000, 0x00000000, 0x405a3d71, 0x00000000, 0x00000000, 0x00000000, 0x4060a3d7, +0x00000000, 0x00000000, 0x00000000, 0x40670a3d, 0x00000000, 0x00000000, 0x00000000, 0x41700000, +0x00000000, 0x00000000, 0x00000000, 0x41800000, 0x00000000, 0x00000000, 0x00000000, 0x4188cccd, +0x4190cccd, 0x00000000, 0x00000000, 0x4083851f, 0x00000000, 0x00000000, 0x00000000, 0x4086b852, +0x00000000, 0x00000000, 0x00000000, 0x4089eb85, 0x00000000, 0x00000000, 0x00000000, 0x408d1eb8, +0x00000000, 0x00000000, 0x00000000, 0x409051ec, 0x00000000, 0x00000000, 0x00000000, 0x4093851f, +0x00000000, 0x00000000, 0x00000000, 0x00333172, 0x00030002, 0x00030001, 0x00000002, 0x00000000, +0x4083851f, 0x4086b852, 0x4089eb85, 0x00000000, 0x408d1eb8, 0x409051ec, 0x4093851f, 0x00000000, +0x00313372, 0x00030002, 0x00010003, 0x00000002, 0x00000000, 0x40470a3d, 0x00000000, 0x00000000, +0x00000000, 0x404d70a4, 0x00000000, 0x00000000, 0x00000000, 0x4053d70a, 0x00000000, 0x00000000, +0x00000000, 0x405a3d71, 0x00000000, 0x00000000, 0x00000000, 0x4060a3d7, 0x00000000, 0x00000000, +0x00000000, 0x40670a3d, 0x00000000, 0x00000000, 0x00000000, 0xabab0073, 0x00030000, 0x00010001, +0x00000001, 0x00000000, 0x0000010c, 0x0000048c, 0x0000022c, 0x00000258, 0x00000005, 0x00020001, +0x00020001, 0x0000049c, 0x40466666, 0x00000000, 0x00000000, 0x00000000, 0x41f80000, 0x00000000, +0x00000000, 0x00000000, 0x00325f73, 0x00000005, 0x00020001, 0x00020002, 0x0000049c, 0x40833333, +0x00000000, 0x00000000, 0x00000000, 0x42240000, 0x00000000, 0x00000000, 0x00000000, 0x40866666, +0x00000000, 0x00000000, 0x00000000, 0x42280000, 0x00000000, 0x00000000, 0x00000000, 0x00335f73, +0x00000005, 0x00020001, 0x00020003, 0x0000049c, 0x40a33333, 0x00000000, 0x00000000, 0x00000000, +0x424c0000, 0x00000000, 0x00000000, 0x00000000, 0x40a66666, 0x00000000, 0x00000000, 0x00000000, +0x42500000, 0x00000000, 0x00000000, 0x00000000, 0x40a9999a, 0x00000000, 0x00000000, 0x00000000, +0x42540000, 0x00000000, 0x00000000, 0x00000000, 0xabab0076, 0x00030001, 0x00030001, 0x00000002, +0x00000000, 0x40070a3d, 0x400d70a4, 0x4013d70a, 0x00000000, 0x401a3d71, 0x4020a3d7, 0x40270a3d, +0x00000000, 0x335f7376, 0x4d00305f, 0x6f726369, 0x74666f73, 0x29522820, 0x534c4820, 0x6853204c, +0x72656461, 0x6d6f4320, 0x656c6970, 0x2e392072, 0x392e3932, 0x332e3235, 0x00313131, 0x0200001f, +0x80000000, 0x900f0000, 0x0200001f, 0x80000000, 0xe00f0000, 0x02000001, 0x80070000, 0xa0e4002a, +0x03000002, 0x80070000, 0x80e40000, 0xa0e4002c, 0x03000002, 0x80040000, 0x80aa0000, 0xa0000017, +0x03000002, 0xe0080000, 0x80aa0000, 0xa0000011, 0x02000001, 0x80010001, 0xa000002d, 0x03000005, +0x80040000, 0x80000001, 0xa0000026, 0x03000005, 0x80040000, 0x80aa0000, 0x90000000, 0x03000005, +0xe0010000, 0x80aa0000, 0xa055000b, 0x03000002, 0x80020000, 0x80550000, 0xa0000016, 0x03000002, +0x80010000, 0x80000000, 0xa0000015, 0x03000002, 0x80010000, 0x80000000, 0xa000000f, 0x03000002, +0x80020000, 0x80550000, 0xa0000010, 0x03000005, 0x80040000, 0xa000002e, 0x90550000, 0x04000004, +0xe0020000, 0x80aa0000, 0xa0000028, 0x80550000, 0x03000005, 0x80020000, 0xa0000018, 0x90aa0000, +0x03000005, 0x80020000, 0x80550000, 0xa000001c, 0x03000005, 0x80020000, 0x80550000, 0xa000002f, +0x03000005, 0x80020000, 0x80550000, 0xa0000020, 0x04000004, 0xe0040000, 0x80550000, 0xa0aa0024, +0x80000000, 0x0000ffff, +}; + +const struct +{ + const char *fullname; + D3DXCONSTANT_DESC desc; + UINT ctaboffset; +} +test_get_shader_constant_variables_data[] = +{ + {"f", {"f", D3DXRS_FLOAT4, 45, 1, D3DXPC_SCALAR, D3DXPT_FLOAT, 1, 1, 1, 0, 4, NULL}, 72}, + {"f23", {"f23", D3DXRS_FLOAT4, 29, 4, D3DXPC_MATRIX_COLUMNS, D3DXPT_FLOAT, 2, 3, 2, 0, 48, NULL}, 81}, + {"f23[0]", {"f23", D3DXRS_FLOAT4, 29, 3, D3DXPC_MATRIX_COLUMNS, D3DXPT_FLOAT, 2, 3, 1, 0, 24, NULL}, 81}, + {"f23[1]", {"f23", D3DXRS_FLOAT4, 32, 1, D3DXPC_MATRIX_COLUMNS, D3DXPT_FLOAT, 2, 3, 1, 0, 24, NULL}, 93}, + {"f32", {"f32", D3DXRS_FLOAT4, 33, 4, D3DXPC_MATRIX_COLUMNS, D3DXPT_FLOAT, 3, 2, 2, 0, 48, NULL}, 110}, + {"f32[0]", {"f32", D3DXRS_FLOAT4, 33, 2, D3DXPC_MATRIX_COLUMNS, D3DXPT_FLOAT, 3, 2, 1, 0, 24, NULL}, 110}, + {"f32[1]", {"f32", D3DXRS_FLOAT4, 35, 2, D3DXPC_MATRIX_COLUMNS, D3DXPT_FLOAT, 3, 2, 1, 0, 24, NULL}, 118}, + {"f_2", {"f_2", D3DXRS_FLOAT4, 37, 2, D3DXPC_SCALAR, D3DXPT_FLOAT, 1, 1, 2, 0, 8, NULL}, 131}, + {"f_2[0]", {"f_2", D3DXRS_FLOAT4, 37, 1, D3DXPC_SCALAR, D3DXPT_FLOAT, 1, 1, 1, 0, 4, NULL}, 131}, + {"f_2[1]", {"f_2", D3DXRS_FLOAT4, 38, 1, D3DXPC_SCALAR, D3DXPT_FLOAT, 1, 1, 1, 0, 4, NULL}, 135}, + {"i", {"i", D3DXRS_FLOAT4, 47, 1, D3DXPC_SCALAR, D3DXPT_INT, 1, 1, 1, 0, 4, NULL}, 144}, + {"i[0]", {"i", D3DXRS_FLOAT4, 47, 1, D3DXPC_SCALAR, D3DXPT_INT, 1, 1, 1, 0, 4, NULL}, 144}, + {"p", {"p", D3DXRS_FLOAT4, 0, 18, D3DXPC_STRUCT, D3DXPT_VOID, 1, 10, 2, 4, 80, NULL}, 176}, + {"p[0]", {"p", D3DXRS_FLOAT4, 0, 9, D3DXPC_STRUCT, D3DXPT_VOID, 1, 10, 1, 4, 40, NULL}, 176}, + {"p[0].i1", {"i1", D3DXRS_FLOAT4, 0, 1, D3DXPC_SCALAR, D3DXPT_INT, 1, 1, 1, 0, 4, NULL}, 176}, + {"p[0].i2", {"i2", D3DXRS_FLOAT4, 1, 1, D3DXPC_SCALAR, D3DXPT_INT, 1, 1, 1, 0, 4, NULL}, 180}, + {"p[0].f_2", {"f_2", D3DXRS_FLOAT4, 2, 1, D3DXPC_VECTOR, D3DXPT_FLOAT, 1, 2, 1, 0, 8, NULL}, 184}, + {"p[0].r", {"r", D3DXRS_FLOAT4, 3, 6, D3DXPC_MATRIX_ROWS, D3DXPT_FLOAT, 3, 1, 2, 0, 24, NULL}, 188}, + {"p[0].r[0]", {"r", D3DXRS_FLOAT4, 3, 3, D3DXPC_MATRIX_ROWS, D3DXPT_FLOAT, 3, 1, 1, 0, 12, NULL}, 188}, + {"p[0].r[1]", {"r", D3DXRS_FLOAT4, 6, 3, D3DXPC_MATRIX_ROWS, D3DXPT_FLOAT, 3, 1, 1, 0, 12, NULL}, 200}, + {"p[1]", {"p", D3DXRS_FLOAT4, 9, 9, D3DXPC_STRUCT, D3DXPT_VOID, 1, 10, 1, 4, 40, NULL}, 212}, + {"p[1].i1", {"i1", D3DXRS_FLOAT4, 9, 1, D3DXPC_SCALAR, D3DXPT_INT, 1, 1, 1, 0, 4, NULL}, 212}, + {"p[1].i2", {"i2", D3DXRS_FLOAT4, 10, 1, D3DXPC_SCALAR, D3DXPT_INT, 1, 1, 1, 0, 4, NULL}, 216}, + {"p[1].f_2", {"f_2", D3DXRS_FLOAT4, 11, 1, D3DXPC_VECTOR, D3DXPT_FLOAT, 1, 2, 1, 0, 8, NULL}, 220}, + {"p[1].r", {"r", D3DXRS_FLOAT4, 12, 6, D3DXPC_MATRIX_ROWS, D3DXPT_FLOAT, 3, 1, 2, 0, 24, NULL}, 224}, + {"p[1].r[0]", {"r", D3DXRS_FLOAT4, 12, 3, D3DXPC_MATRIX_ROWS, D3DXPT_FLOAT, 3, 1, 1, 0, 12, NULL}, 224}, + {"p[1].r[1]", {"r", D3DXRS_FLOAT4, 15, 3, D3DXPC_MATRIX_ROWS, D3DXPT_FLOAT, 3, 1, 1, 0, 12, NULL}, 236}, + {"r13", {"r13", D3DXRS_FLOAT4, 43, 2, D3DXPC_MATRIX_ROWS, D3DXPT_FLOAT, 1, 3, 2, 0, 24, NULL}, 253}, + {"r13[0]", {"r13", D3DXRS_FLOAT4, 43, 1, D3DXPC_MATRIX_ROWS, D3DXPT_FLOAT, 1, 3, 1, 0, 12, NULL}, 253}, + {"r13[1]", {"r13", D3DXRS_FLOAT4, 44, 1, D3DXPC_MATRIX_ROWS, D3DXPT_FLOAT, 1, 3, 1, 0, 12, NULL}, 257}, + {"r31", {"r31", D3DXRS_FLOAT4, 18, 6, D3DXPC_MATRIX_ROWS, D3DXPT_FLOAT, 3, 1, 2, 0, 24, NULL}, 266}, + {"r31[0]", {"r31", D3DXRS_FLOAT4, 18, 3, D3DXPC_MATRIX_ROWS, D3DXPT_FLOAT, 3, 1, 1, 0, 12, NULL}, 266}, + {"r31[1]", {"r31", D3DXRS_FLOAT4, 21, 3, D3DXPC_MATRIX_ROWS, D3DXPT_FLOAT, 3, 1, 1, 0, 12, NULL}, 278}, + {"s", {"s", D3DXRS_FLOAT4, 46, 1, D3DXPC_STRUCT, D3DXPT_VOID, 1, 2, 1, 2, 8, NULL}, 303}, + {"s.f", {"f", D3DXRS_FLOAT4, 46, 1, D3DXPC_SCALAR, D3DXPT_FLOAT, 1, 1, 1, 0, 4, NULL}, 303}, + {"s.i", {"i", D3DXRS_FLOAT4, 47, 0, D3DXPC_SCALAR, D3DXPT_INT, 1, 1, 1, 0, 4, NULL}, 307}, + {"s_2", {"s_2", D3DXRS_FLOAT4, 39, 2, D3DXPC_STRUCT, D3DXPT_VOID, 1, 2, 2, 2, 16, NULL}, 316}, + {"s_2[0]", {"s_2", D3DXRS_FLOAT4, 39, 2, D3DXPC_STRUCT, D3DXPT_VOID, 1, 2, 1, 2, 8, NULL}, 316}, + {"s_2[0].f", {"f", D3DXRS_FLOAT4, 39, 1, D3DXPC_SCALAR, D3DXPT_FLOAT, 1, 1, 1, 0, 4, NULL}, 316}, + {"s_2[0].i", {"i", D3DXRS_FLOAT4, 40, 1, D3DXPC_SCALAR, D3DXPT_INT, 1, 1, 1, 0, 4, NULL}, 320}, + {"s_2[1]", {"s_2", D3DXRS_FLOAT4, 41, 0, D3DXPC_STRUCT, D3DXPT_VOID, 1, 2, 1, 2, 8, NULL}, 324}, + {"s_2[1].f", {"f", D3DXRS_FLOAT4, 41, 0, D3DXPC_SCALAR, D3DXPT_FLOAT, 1, 1, 1, 0, 4, NULL}, 324}, + {"s_2[1].i", {"i", D3DXRS_FLOAT4, 41, 0, D3DXPC_SCALAR, D3DXPT_INT, 1, 1, 1, 0, 4, NULL}, 328}, + {"s_3", {"s_3", D3DXRS_FLOAT4, 24, 5, D3DXPC_STRUCT, D3DXPT_VOID, 1, 2, 3, 2, 24, NULL}, 337}, + {"s_3[0]", {"s_3", D3DXRS_FLOAT4, 24, 2, D3DXPC_STRUCT, D3DXPT_VOID, 1, 2, 1, 2, 8, NULL}, 337}, + {"s_3[0].f", {"f", D3DXRS_FLOAT4, 24, 1, D3DXPC_SCALAR, D3DXPT_FLOAT, 1, 1, 1, 0, 4, NULL}, 337}, + {"s_3[0].i", {"i", D3DXRS_FLOAT4, 25, 1, D3DXPC_SCALAR, D3DXPT_INT, 1, 1, 1, 0, 4, NULL}, 341}, + {"s_3[1]", {"s_3", D3DXRS_FLOAT4, 26, 2, D3DXPC_STRUCT, D3DXPT_VOID, 1, 2, 1, 2, 8, NULL}, 345}, + {"s_3[1].f", {"f", D3DXRS_FLOAT4, 26, 1, D3DXPC_SCALAR, D3DXPT_FLOAT, 1, 1, 1, 0, 4, NULL}, 345}, + {"s_3[1].i", {"i", D3DXRS_FLOAT4, 27, 1, D3DXPC_SCALAR, D3DXPT_INT, 1, 1, 1, 0, 4, NULL}, 349}, + {"s_3[2]", {"s_3", D3DXRS_FLOAT4, 28, 1, D3DXPC_STRUCT, D3DXPT_VOID, 1, 2, 1, 2, 8, NULL}, 353}, + {"s_3[2].f", {"f", D3DXRS_FLOAT4, 28, 1, D3DXPC_SCALAR, D3DXPT_FLOAT, 1, 1, 1, 0, 4, NULL}, 353}, + {"s_3[2].i", {"i", D3DXRS_FLOAT4, 29, 0, D3DXPC_SCALAR, D3DXPT_INT, 1, 1, 1, 0, 4, NULL}, 357}, + {"v", {"v", D3DXRS_FLOAT4, 41, 2, D3DXPC_VECTOR, D3DXPT_FLOAT, 1, 3, 2, 0, 24, NULL}, 366}, + {"v[0]", {"v", D3DXRS_FLOAT4, 41, 1, D3DXPC_VECTOR, D3DXPT_FLOAT, 1, 3, 1, 0, 12, NULL}, 366}, + {"v[1]", {"v", D3DXRS_FLOAT4, 42, 1, D3DXPC_VECTOR, D3DXPT_FLOAT, 1, 3, 1, 0, 12, NULL}, 370}, +}; + +static void test_get_shader_constant_variables(void) +{ + ID3DXConstantTable *ctable; + HRESULT hr; + ULONG count; + UINT i; + UINT nr = 1; + D3DXHANDLE constant, element; + D3DXCONSTANT_DESC desc; + DWORD *ctab; + + hr = D3DXGetShaderConstantTable(test_get_shader_constant_variables_blob, &ctable); + ok(hr == D3D_OK, "D3DXGetShaderConstantTable failed, got %08x, expected %08x\n", hr, D3D_OK); + + ctab = ID3DXConstantTable_GetBufferPointer(ctable); + ok(ctab[0] == test_get_shader_constant_variables_blob[3], "ID3DXConstantTable_GetBufferPointer failed\n"); + + for (i = 0; i < ARRAY_SIZE(test_get_shader_constant_variables_data); ++i) + { + const char *fullname = test_get_shader_constant_variables_data[i].fullname; + const D3DXCONSTANT_DESC *expected_desc = &test_get_shader_constant_variables_data[i].desc; + UINT ctaboffset = test_get_shader_constant_variables_data[i].ctaboffset; + + constant = ID3DXConstantTable_GetConstantByName(ctable, NULL, fullname); + ok(constant != NULL, "GetConstantByName \"%s\" failed\n", fullname); + + hr = ID3DXConstantTable_GetConstantDesc(ctable, constant, &desc, &nr); + ok(hr == D3D_OK, "GetConstantDesc \"%s\" failed, got %08x, expected %08x\n", fullname, hr, D3D_OK); + + ok(!strcmp(expected_desc->Name, desc.Name), "GetConstantDesc \"%s\" failed, got \"%s\", expected \"%s\"\n", + fullname, desc.Name, expected_desc->Name); + ok(expected_desc->RegisterSet == desc.RegisterSet, "GetConstantDesc \"%s\" failed, got %#x, expected %#x\n", + fullname, desc.RegisterSet, expected_desc->RegisterSet); + ok(expected_desc->RegisterIndex == desc.RegisterIndex, "GetConstantDesc \"%s\" failed, got %u, expected %u\n", + fullname, desc.RegisterIndex, expected_desc->RegisterIndex); + ok(expected_desc->RegisterCount == desc.RegisterCount, "GetConstantDesc \"%s\" failed, got %u, expected %u\n", + fullname, desc.RegisterCount, expected_desc->RegisterCount); + ok(expected_desc->Class == desc.Class, "GetConstantDesc \"%s\" failed, got %u, expected %u\n", + fullname, desc.Class, expected_desc->Class); + ok(expected_desc->Type == desc.Type, "GetConstantDesc \"%s\" failed, got %#x, expected %#x\n", + fullname, desc.Type, expected_desc->Type); + ok(expected_desc->Rows == desc.Rows, "GetConstantDesc \"%s\" failed, got %#x, expected %#x\n", + fullname, desc.Rows, expected_desc->Rows); + ok(expected_desc->Columns == desc.Columns, "GetConstantDesc \"%s\" failed, got %u, expected %u\n", + fullname, desc.Columns, expected_desc->Columns); + ok(expected_desc->Elements == desc.Elements, "GetConstantDesc \"%s\" failed, got %u, expected %u\n", + fullname, desc.Elements, expected_desc->Elements); + ok(expected_desc->StructMembers == desc.StructMembers, "GetConstantDesc \"%s\" failed, got %u, expected %u\n", + fullname, desc.StructMembers, expected_desc->StructMembers); + ok(expected_desc->Bytes == desc.Bytes, "GetConstantDesc \"%s\" failed, got %u, expected %u\n", + fullname, desc.Bytes, expected_desc->Bytes); + ok(ctaboffset == (DWORD *)desc.DefaultValue - ctab, "GetConstantDesc \"%s\" failed, got %u, expected %u\n", + fullname, (UINT)((DWORD *)desc.DefaultValue - ctab), ctaboffset); + } + + element = ID3DXConstantTable_GetConstantElement(ctable, NULL, 0); + ok(element == NULL, "GetConstantElement failed\n"); + + constant = ID3DXConstantTable_GetConstantByName(ctable, NULL, "i"); + ok(constant != NULL, "GetConstantByName failed\n"); + + element = ID3DXConstantTable_GetConstantByName(ctable, NULL, "i[0]"); + ok(constant == element, "GetConstantByName failed, got %p, expected %p\n", element, constant); + + element = ID3DXConstantTable_GetConstantElement(ctable, "i", 0); + ok(element == constant, "GetConstantElement failed, got %p, expected %p\n", element, constant); + + constant = ID3DXConstantTable_GetConstantByName(ctable, NULL, "f"); + ok(constant != NULL, "GetConstantByName failed\n"); + + element = ID3DXConstantTable_GetConstant(ctable, NULL, 0); + ok(element == constant, "GetConstant failed, got %p, expected %p\n", element, constant); + + element = ID3DXConstantTable_GetConstant(ctable, "invalid", 0); + ok(element == NULL, "GetConstant failed\n"); + + element = ID3DXConstantTable_GetConstant(ctable, "f", 0); + ok(element == NULL, "GetConstant failed\n"); + + element = ID3DXConstantTable_GetConstantByName(ctable, NULL, "f[0]"); + ok(constant == element, "GetConstantByName failed, got %p, expected %p\n", element, constant); + + element = ID3DXConstantTable_GetConstantByName(ctable, NULL, "f[1]"); + ok(NULL == element, "GetConstantByName failed\n"); + + element = ID3DXConstantTable_GetConstantByName(ctable, NULL, "f[0][0]"); + ok(constant == element, "GetConstantByName failed, got %p, expected %p\n", element, constant); + + element = ID3DXConstantTable_GetConstantByName(ctable, NULL, "f."); + ok(element == NULL, "GetConstantByName failed\n"); + + element = ID3DXConstantTable_GetConstantElement(ctable, "f", 0); + ok(element == constant, "GetConstantElement failed, got %p, expected %p\n", element, constant); + + element = ID3DXConstantTable_GetConstantElement(ctable, "f", 1); + ok(element == NULL, "GetConstantElement failed\n"); + + constant = ID3DXConstantTable_GetConstantByName(ctable, NULL, "f_2[0]"); + ok(constant != NULL, "GetConstantByName failed\n"); + + element = ID3DXConstantTable_GetConstantByName(ctable, NULL, "f_2"); + ok(element != constant, "GetConstantByName failed, got %p, expected %p\n", element, constant); + + element = ID3DXConstantTable_GetConstantElement(ctable, "f_2", 0); + ok(element == constant, "GetConstantElement failed, got %p, expected %p\n", element, constant); + + constant = ID3DXConstantTable_GetConstantByName(ctable, NULL, "f_2[1]"); + ok(constant != NULL, "GetConstantByName failed\n"); + + element = ID3DXConstantTable_GetConstantElement(ctable, "f_2", 1); + ok(element == constant, "GetConstantElement failed, got %p, expected %p\n", element, constant); + + constant = ID3DXConstantTable_GetConstantByName(ctable, NULL, "s_2[0].f"); + ok(constant != NULL, "GetConstantByName failed\n"); + + element = ID3DXConstantTable_GetConstant(ctable, "s_2[0]", 0); + ok(element == constant, "GetConstant failed, got %p, expected %p\n", element, constant); + + element = ID3DXConstantTable_GetConstantByName(ctable, "s_2[0]", "f"); + ok(element == constant, "GetConstantByName failed, got %p, expected %p\n", element, constant); + + element = ID3DXConstantTable_GetConstantByName(ctable, "s_2[0]", "invalid"); + ok(element == NULL, "GetConstantByName failed\n"); + + constant = ID3DXConstantTable_GetConstantByName(ctable, NULL, "s_2[0]"); + ok(constant != NULL, "GetConstantByName failed\n"); + + element = ID3DXConstantTable_GetConstantElement(ctable, "s_2[0]", 0); + ok(constant == element, "GetConstantByName failed, got %p, expected %p\n", element, constant); + + count = ID3DXConstantTable_Release(ctable); + ok(count == 0, "Release failed, got %u, expected %u\n", count, 0); +} + +#define REGISTER_OUTPUT_SIZE 48 + +enum Type {SetFloat, SetInt, SetBool, SetIntArray, SetBoolArray, SetFloatArray, SetMatrix, + SetMatrixTranspose, SetMatrixArray, SetMatrixTransposeArray, SetVector, SetVectorArray, + SetValue, SetMatrixPointerArray, SetMatrixTransposePointerArray}; + +struct registerset_test +{ + enum Type type; + UINT in_index; + UINT in_count_min; + UINT in_count_max; + UINT out_count; + DWORD out[REGISTER_OUTPUT_SIZE]; +}; + +struct registerset_constants +{ + const char *fullname; + D3DXCONSTANT_DESC desc; + UINT ctaboffset; +}; + +static const DWORD registerset_test_input[][REGISTER_OUTPUT_SIZE] = +{ + /* float */ + {0x40000123, 0x00000000, 0x40800123, 0x40a00123, + 0x40c00123, 0x40e00123, 0x41000123, 0x41100123, + 0x41200123, 0x41300123, 0x41400123, 0x41500123, + 0x41600123, 0x41700123, 0x41800123, 0x41900123, + 0x41a00123, 0x41b00123, 0x41c00123, 0x41d00123, + 0x00000000, 0x41f00123, 0x42000123, 0x42100123, + 0x00000000, 0x42300123, 0x42400123, 0x42500123, + 0x42600123, 0x42700123, 0x42800123, 0x42900123, + 0x43000123, 0x43100123, 0x43200123, 0x43300123, + 0x43400123, 0x43500123, 0x43600123, 0x43700123, + 0x43800123, 0x43900123, 0x43a00123, 0x43b00123, + 0x43c00123, 0x43d00123, 0x43e00123, 0x43f00123}, + /* int */ + {0x00000002, 0x00000003, 0x00000004, 0x00000005, + 0x00000000, 0x00000007, 0x00000008, 0x00000009, + 0x0000000a, 0x0000000b, 0x0000000c, 0x0000000d, + 0x0000000e, 0x0000000f, 0x00000010, 0x00000011, + 0x00000012, 0x00000000, 0x00000000, 0x00000015, + 0x00000016, 0x00000017, 0x00000018, 0x00000019, + 0x0000001a, 0x0000001b, 0x0000001c, 0x0000001d, + 0x0000001e, 0x0000001f, 0x00000020, 0x00000021, + 0x00000022, 0x00000023, 0x00000024, 0x00000025, + 0x00000026, 0x00000027, 0x00000028, 0x00000029, + 0x0000002a, 0x0000002b, 0x0000002c, 0x0000002d, + 0x0000002e, 0x0000002f, 0x00000030, 0x00000031}, +}; + +/* + * fxc.exe /Tvs_3_0 + */ +#if 0 +bool b = 1; +int n = 8; +float f = 5.1; +int nf = 11; +bool bf = 1; +float4 main(float4 pos : POSITION) : POSITION +{ + float4 tmp = 0; + int i; + if (b) for (i = 0; i < n; i++) tmp.x += pos.z * f * nf; + else for (i = 0; i < n; i++) tmp.y += pos.y * f * bf; + return tmp; +} +#endif +static const DWORD registerset_blob_scalar[] = +{ +0xfffe0300, 0x0051fffe, 0x42415443, 0x0000001c, 0x0000010f, 0xfffe0300, 0x00000005, 0x0000001c, +0x00000100, 0x00000108, 0x00000080, 0x00000000, 0x00000001, 0x00000084, 0x00000094, 0x00000098, +0x00020002, 0x00000001, 0x00000084, 0x0000009c, 0x000000ac, 0x00000002, 0x00000001, 0x000000b0, +0x000000c0, 0x000000d0, 0x00000001, 0x00000001, 0x000000d4, 0x000000e4, 0x000000f4, 0x00010002, +0x00000001, 0x000000d4, 0x000000f8, 0xabab0062, 0x00010000, 0x00010001, 0x00000001, 0x00000000, +0xffffffff, 0xab006662, 0x3f800000, 0x00000000, 0x00000000, 0x00000000, 0xabab0066, 0x00030000, +0x00010001, 0x00000001, 0x00000000, 0x40a33333, 0x00000000, 0x00000000, 0x00000000, 0xabab006e, +0x00020000, 0x00010001, 0x00000001, 0x00000000, 0x00000008, 0x00000000, 0x00000001, 0x00000000, +0xab00666e, 0x41300000, 0x00000000, 0x00000000, 0x00000000, 0x335f7376, 0x4d00305f, 0x6f726369, +0x74666f73, 0x29522820, 0x534c4820, 0x6853204c, 0x72656461, 0x6d6f4320, 0x656c6970, 0x2e392072, +0x392e3932, 0x332e3235, 0x00313131, 0x05000051, 0xa00f0003, 0x00000000, 0x00000000, 0x00000000, +0x00000000, 0x0200001f, 0x80000000, 0x900f0000, 0x0200001f, 0x80000000, 0xe00f0000, 0x01000028, +0xe0e40800, 0x03000005, 0x80010000, 0xa0000000, 0x90aa0000, 0x02000001, 0x80010001, 0xa0000003, +0x01000026, 0xf0e40000, 0x04000004, 0x80010001, 0x80000000, 0xa0000001, 0x80000001, 0x00000027, +0x02000001, 0x80020001, 0xa0000003, 0x0000002a, 0x03000005, 0x80010000, 0xa0000000, 0x90550000, +0x02000001, 0x80020001, 0xa0000003, 0x01000026, 0xf0e40000, 0x04000004, 0x80020001, 0x80000000, +0xa0000002, 0x80550001, 0x00000027, 0x02000001, 0x80010001, 0xa0000003, 0x0000002b, 0x02000001, +0xe0030000, 0x80e40001, 0x02000001, 0xe00c0000, 0xa0000003, 0x0000ffff, +}; + +static const struct registerset_constants registerset_constants_scalar_float[] = +{ + {"f", {"f", D3DXRS_FLOAT4, 0, 1, D3DXPC_SCALAR, D3DXPT_FLOAT, 1, 1, 1, 0, 4, NULL}, 48}, +}; + +static const struct registerset_test registerset_test_scalar_float[] = +{ + {SetFloat, 0, 0, 0, 4, {0x40000123}}, + {SetInt, 1, 0, 0, 4, {0x40000000}}, + {SetBool, 1, 0, 0, 4, {0x3f800000}}, + {SetIntArray}, + {SetIntArray, 1, 1, REGISTER_OUTPUT_SIZE, 4, {0x40000000}}, + {SetBoolArray}, + {SetBoolArray, 1, 1, REGISTER_OUTPUT_SIZE, 4, {0x3f800000}}, + {SetFloatArray}, + {SetFloatArray, 0, 1, REGISTER_OUTPUT_SIZE, 4, {0x40000123}}, + {SetValue, 0, 0, 3}, + {SetValue, 0, 4, REGISTER_OUTPUT_SIZE * 4, 4, {0x40000123}}, + {SetVector, 0, 0, 0, 4, {0x40000123}}, + {SetVectorArray}, + {SetVectorArray, 0, 1, REGISTER_OUTPUT_SIZE / 4, 4, {0x40000123}}, + {SetMatrix, 0, 0, 0, 4, {0x40000123},}, + {SetMatrixArray}, + {SetMatrixArray, 0, 1, REGISTER_OUTPUT_SIZE / 16, 4, {0x40000123}}, + {SetMatrixTranspose, 0, 0, 0, 4, {0x40000123},}, + {SetMatrixTransposeArray}, + {SetMatrixTransposeArray, 0, 1, REGISTER_OUTPUT_SIZE / 16, 4, {0x40000123}}, + {SetMatrixPointerArray}, + {SetMatrixPointerArray, 0, 1, REGISTER_OUTPUT_SIZE / 16, 4, {0x40000123}}, + {SetMatrixTransposePointerArray}, + {SetMatrixTransposePointerArray, 0, 1, REGISTER_OUTPUT_SIZE / 16, 4, {0x40000123}}, +}; + +static const struct registerset_constants registerset_constants_scalar_int[] = +{ + {"n", {"n", D3DXRS_INT4, 0, 1, D3DXPC_SCALAR, D3DXPT_INT, 1, 1, 1, 0, 4, NULL}, 57}, +}; + +static const struct registerset_test registerset_test_scalar_int[] = +{ + {SetFloat, 0, 0, 0, 4, + {0x00000002, 0x00000000, 0x00000001}}, + {SetInt, 1, 0, 0, 4, + {0x00000002, 0x00000000, 0x00000001}}, + {SetBool, 1, 0, 0, 4, + {0x00000001, 0x00000000, 0x00000001}}, + {SetIntArray}, + {SetIntArray, 1, 1, REGISTER_OUTPUT_SIZE, 4, + {0x00000002, 0x00000000, 0x00000001}}, + {SetBoolArray}, + {SetBoolArray, 1, 1, REGISTER_OUTPUT_SIZE, 4, + {0x00000001, 0x00000000, 0x00000001}}, + {SetFloatArray}, + {SetFloatArray, 0, 1, REGISTER_OUTPUT_SIZE, 4, + {0x00000002, 0x00000000, 0x00000001}}, + {SetValue, 1, 0, 3}, + {SetValue, 1, 4, REGISTER_OUTPUT_SIZE * 4, 4, + {0x00000002, 0x00000000, 0x00000001}}, + {SetVector, 0, 0, 0, 4, + {0x00000002, 0x00000000, 0x00000001},}, + {SetVectorArray}, + {SetVectorArray, 0, 1, REGISTER_OUTPUT_SIZE / 4, 4, + {0x00000002, 0x00000000, 0x00000001}}, + {SetMatrix, 0, 0, 0, 4, + {0x00000002, 0x00000000, 0x00000001}}, + {SetMatrixArray}, + {SetMatrixArray, 0, 1, REGISTER_OUTPUT_SIZE / 16, 4, + {0x00000002, 0x00000000, 0x00000001}}, + {SetMatrixTranspose, 0, 0, 0, 4, + {0x00000002, 0x00000000, 0x00000001}}, + {SetMatrixTransposeArray}, + {SetMatrixTransposeArray, 0, 1, REGISTER_OUTPUT_SIZE / 16, 4, + {0x00000002, 0x00000000, 0x00000001}}, + {SetMatrixPointerArray}, + {SetMatrixPointerArray, 0, 1, REGISTER_OUTPUT_SIZE / 16, 4, + {0x00000002, 0x00000000, 0x00000001}}, + {SetMatrixTransposePointerArray}, + {SetMatrixTransposePointerArray, 0, 1, REGISTER_OUTPUT_SIZE / 16, 4, + {0x00000002, 0x00000000, 0x00000001}}, +}; + +static const struct registerset_constants registerset_constants_scalar_int_float[] = +{ + {"nf", {"nf", D3DXRS_FLOAT4, 1, 1, D3DXPC_SCALAR, D3DXPT_INT, 1, 1, 1, 0, 4, NULL}, 62}, +}; + +static const struct registerset_test registerset_test_scalar_int_float[] = +{ + {SetFloat, 0, 0, 0, 4, {0x40000000}}, + {SetInt, 1, 0, 0, 4, {0x40000000}}, + {SetBool, 1, 0, 0, 4, {0x3f800000}}, + {SetIntArray}, + {SetIntArray, 1, 1, REGISTER_OUTPUT_SIZE, 4, {0x40000000}}, + {SetBoolArray}, + {SetBoolArray, 1, 1, REGISTER_OUTPUT_SIZE, 4, {0x3f800000}}, + {SetFloatArray}, + {SetFloatArray, 0, 1, REGISTER_OUTPUT_SIZE, 4, {0x40000000}}, + {SetValue, 1, 0, 3}, + {SetValue, 1, 4, REGISTER_OUTPUT_SIZE * 4, 4, {0x40000000}}, + {SetVector, 0, 0, 0, 4, {0x40000000}}, + {SetVectorArray}, + {SetVectorArray, 0, 1, REGISTER_OUTPUT_SIZE / 4, 4, {0x40000000}}, + {SetMatrix, 0, 0, 0, 4, {0x40000000}}, + {SetMatrixArray}, + {SetMatrixArray, 0, 1, REGISTER_OUTPUT_SIZE / 16, 4, {0x40000000}}, + {SetMatrixTranspose, 0, 0, 0, 4, {0x40000000}}, + {SetMatrixTransposeArray}, + {SetMatrixTransposeArray, 0, 1, REGISTER_OUTPUT_SIZE / 16, 4, {0x40000000}}, + {SetMatrixPointerArray}, + {SetMatrixPointerArray, 0, 1, REGISTER_OUTPUT_SIZE / 16, 4, {0x40000000}}, + {SetMatrixTransposePointerArray}, + {SetMatrixTransposePointerArray, 0, 1, REGISTER_OUTPUT_SIZE / 16, 4, {0x40000000}}, +}; + +static const struct registerset_constants registerset_constants_scalar_bool_float[] = +{ + {"bf", {"bf", D3DXRS_FLOAT4, 2, 1, D3DXPC_SCALAR, D3DXPT_BOOL, 1, 1, 1, 0, 4, NULL}, 39}, +}; + +static const struct registerset_test registerset_test_scalar_bool_float[] = +{ + {SetFloat, 0, 0, 0, 4, {0x3f800000}}, + {SetInt, 1, 0, 0, 4, {0x3f800000}}, + {SetBool, 1, 0, 0, 4, {0x3f800000}}, + {SetIntArray}, + {SetIntArray, 1, 1, REGISTER_OUTPUT_SIZE, 4, {0x3f800000}}, + {SetBoolArray}, + {SetBoolArray, 1, 1, REGISTER_OUTPUT_SIZE, 4, {0x3f800000}}, + {SetFloatArray}, + {SetFloatArray, 0, 1, REGISTER_OUTPUT_SIZE, 4, {0x3f800000}}, + {SetValue, 1, 0, 3}, + {SetValue, 1, 4, REGISTER_OUTPUT_SIZE * 4, 4, {0x3f800000}}, + {SetVector, 0, 0, 0, 4, {0x3f800000}}, + {SetVectorArray}, + {SetVectorArray, 0, 1, REGISTER_OUTPUT_SIZE / 4, 4, {0x3f800000}}, + {SetMatrix, 0, 0, 0, 4, {0x3f800000}}, + {SetMatrixArray}, + {SetMatrixArray, 0, 1, REGISTER_OUTPUT_SIZE / 16, 4, {0x3f800000}}, + {SetMatrixTranspose, 0, 0, 0, 4, {0x3f800000}}, + {SetMatrixTransposeArray}, + {SetMatrixTransposeArray, 0, 1, REGISTER_OUTPUT_SIZE / 16, 4, {0x3f800000}}, + {SetMatrixPointerArray}, + {SetMatrixPointerArray, 0, 1, REGISTER_OUTPUT_SIZE / 16, 4, {0x3f800000}}, + {SetMatrixTransposePointerArray}, + {SetMatrixTransposePointerArray, 0, 1, REGISTER_OUTPUT_SIZE / 16, 4, {0x3f800000}}, +}; + +static const struct registerset_constants registerset_constants_scalar_bool[] = +{ + {"b", {"b", D3DXRS_BOOL, 0, 1, D3DXPC_SCALAR, D3DXPT_BOOL, 1, 1, 1, 0, 4, NULL}, 37}, +}; + +static const struct registerset_test registerset_test_scalar_bool[] = +{ + {SetFloat, 0, 0, 0, 1, {0x00000001}}, + {SetInt, 1, 0, 0, 1, {0x00000001}}, + {SetBool, 1, 0, 0, 1, {0x00000002}}, + {SetIntArray}, + {SetIntArray, 1, 1, REGISTER_OUTPUT_SIZE, 1, {0x00000001}}, + {SetBoolArray}, + {SetBoolArray, 1, 1, REGISTER_OUTPUT_SIZE, 1, {0x00000002}}, + {SetFloatArray}, + {SetFloatArray, 0, 1, REGISTER_OUTPUT_SIZE, 1, {0x00000001}}, + {SetValue, 1, 0, 3}, + {SetValue, 1, 4, REGISTER_OUTPUT_SIZE * 4, 1, {0x00000002}}, + {SetVector, 0, 0, 0, 1, {0x00000001}}, + {SetVectorArray}, + {SetVectorArray, 0, 1, REGISTER_OUTPUT_SIZE / 4, 1, {0x00000001}}, + {SetMatrix, 0, 0, 0, 1, {0x00000001}}, + {SetMatrixArray}, + {SetMatrixArray, 0, 1, REGISTER_OUTPUT_SIZE / 16, 1, {0x00000001}}, + {SetMatrixTranspose, 0, 0, 0, 1, {0x00000001}}, + {SetMatrixTransposeArray}, + {SetMatrixTransposeArray, 0, 1, REGISTER_OUTPUT_SIZE / 16, 1, {0x00000001}}, + {SetMatrixPointerArray}, + {SetMatrixPointerArray, 0, 1, REGISTER_OUTPUT_SIZE / 16, 1, {0x00000001}}, + {SetMatrixTransposePointerArray}, + {SetMatrixTransposePointerArray, 0, 1, REGISTER_OUTPUT_SIZE / 16, 1, {0x00000001}}, +}; + +/* + * fxc.exe /Tvs_3_0 + */ +#if 0 +bool ab[2] = {1, 0}; +int an[2] = {32, 33}; +float af[2] = {3.1, 3.2}; +int anf[2] = {14, 15}; +bool abf[2] = {1, 1}; +float4 main(float4 pos : POSITION) : POSITION +{ + float4 tmp = 0; + int i; + if (ab[1]) for (i = 0; i < an[1]; i++) tmp.x += pos.z * af[0] * anf[1]; + else for (i = 0; i < an[0]; i++) tmp.y += pos.y * af[1] * abf[1]; + return tmp; +} +#endif +static const DWORD registerset_blob_scalar_array[] = +{ +0xfffe0300, 0x006afffe, 0x42415443, 0x0000001c, 0x00000173, 0xfffe0300, 0x00000005, 0x0000001c, +0x00000100, 0x0000016c, 0x00000080, 0x00000000, 0x00000002, 0x00000084, 0x00000094, 0x0000009c, +0x00040002, 0x00000002, 0x000000a0, 0x000000b0, 0x000000d0, 0x00000002, 0x00000002, 0x000000d4, +0x000000e4, 0x00000104, 0x00000001, 0x00000002, 0x00000108, 0x00000118, 0x00000138, 0x00020002, +0x00000002, 0x0000013c, 0x0000014c, 0xab006261, 0x00010000, 0x00010001, 0x00000002, 0x00000000, +0xffffffff, 0x00000000, 0x00666261, 0x00010000, 0x00010001, 0x00000002, 0x00000000, 0x3f800000, +0x00000000, 0x00000000, 0x00000000, 0x3f800000, 0x00000000, 0x00000000, 0x00000000, 0xab006661, +0x00030000, 0x00010001, 0x00000002, 0x00000000, 0x40466666, 0x00000000, 0x00000000, 0x00000000, +0x404ccccd, 0x00000000, 0x00000000, 0x00000000, 0xab006e61, 0x00020000, 0x00010001, 0x00000002, +0x00000000, 0x00000020, 0x00000000, 0x00000001, 0x00000000, 0x00000021, 0x00000000, 0x00000001, +0x00000000, 0x00666e61, 0x00020000, 0x00010001, 0x00000002, 0x00000000, 0x41600000, 0x00000000, +0x00000000, 0x00000000, 0x41700000, 0x00000000, 0x00000000, 0x00000000, 0x335f7376, 0x4d00305f, +0x6f726369, 0x74666f73, 0x29522820, 0x534c4820, 0x6853204c, 0x72656461, 0x6d6f4320, 0x656c6970, +0x2e392072, 0x392e3932, 0x332e3235, 0x00313131, 0x05000051, 0xa00f0006, 0x00000000, 0x00000000, +0x00000000, 0x00000000, 0x0200001f, 0x80000000, 0x900f0000, 0x0200001f, 0x80000000, 0xe00f0000, +0x01000028, 0xe0e40801, 0x03000005, 0x80010000, 0xa0000000, 0x90aa0000, 0x02000001, 0x80010001, +0xa0000006, 0x01000026, 0xf0e40001, 0x04000004, 0x80010001, 0x80000000, 0xa0000003, 0x80000001, +0x00000027, 0x02000001, 0x80020001, 0xa0000006, 0x0000002a, 0x03000005, 0x80010000, 0xa0000001, +0x90550000, 0x02000001, 0x80020001, 0xa0000006, 0x01000026, 0xf0e40000, 0x04000004, 0x80020001, +0x80000000, 0xa0000005, 0x80550001, 0x00000027, 0x02000001, 0x80010001, 0xa0000006, 0x0000002b, +0x02000001, 0xe0030000, 0x80e40001, 0x02000001, 0xe00c0000, 0xa0000006, 0x0000ffff, +}; + +static const struct registerset_constants registerset_constants_scalar_array_float[] = +{ + {"af", {"af", D3DXRS_FLOAT4, 0, 2, D3DXPC_SCALAR, D3DXPT_FLOAT, 1, 1, 2, 0, 8, NULL}, 57}, + {"af[0]", {"af", D3DXRS_FLOAT4, 0, 1, D3DXPC_SCALAR, D3DXPT_FLOAT, 1, 1, 1, 0, 4, NULL}, 57}, + {"af[1]", {"af", D3DXRS_FLOAT4, 1, 1, D3DXPC_SCALAR, D3DXPT_FLOAT, 1, 1, 1, 0, 4, NULL}, 61}, +}; + +static const struct registerset_test registerset_test_scalar_array_float[] = +{ + {SetFloat, 0, 0, 0, 4, {0x40000123}}, + {SetInt, 1, 0, 0, 4, {0x40000000}}, + {SetBool, 1, 0, 0, 4, {0x3f800000}}, + {SetIntArray}, + {SetIntArray, 1, 1, 1, 4, {0x40000000}}, + {SetIntArray, 1, 2, REGISTER_OUTPUT_SIZE, 8, + {0x40000000, 0x00000000, 0x00000000, 0x00000000, 0x40400000}}, + {SetBoolArray}, + {SetBoolArray, 1, 1, 1, 4, {0x3f800000}}, + {SetBoolArray, 1, 2, REGISTER_OUTPUT_SIZE, 8, + {0x3f800000, 0x00000000, 0x00000000, 0x00000000, 0x3f800000}}, + {SetFloatArray}, + {SetFloatArray, 0, 1, 1, 4, {0x40000123}}, + {SetFloatArray, 0, 2, REGISTER_OUTPUT_SIZE, 8, + {0x40000123, 0x00000000, 0x00000000, 0x00000000, 0x00000000}}, + {SetValue, 0, 0, 3}, + {SetValue, 0, 4, 7, 4, {0x40000123}}, + {SetValue, 0, 8, REGISTER_OUTPUT_SIZE * 4, 8, + {0x40000123, 0x00000000, 0x00000000, 0x00000000, 0x00000000}}, + {SetVector, 0, 0, 0, 8, + {0x40000123, 0x00000000, 0x00000000, 0x00000000, 0x00000000}}, + {SetVectorArray}, + {SetVectorArray, 0, 1, REGISTER_OUTPUT_SIZE / 4, 8, + {0x40000123, 0x00000000, 0x00000000, 0x00000000, 0x00000000}}, + {SetMatrix, 0, 0, 0, 8, + {0x40000123, 0x00000000, 0x00000000, 0x00000000, 0x00000000}}, + {SetMatrixArray}, + {SetMatrixArray, 0, 1, REGISTER_OUTPUT_SIZE / 16, 8, + {0x40000123, 0x00000000, 0x00000000, 0x00000000, 0x00000000}}, + {SetMatrixTranspose, 0, 0, 0, 8, + {0x40000123, 0x00000000, 0x00000000, 0x00000000, 0x40c00123}}, + {SetMatrixTransposeArray}, + {SetMatrixTransposeArray, 0, 1, REGISTER_OUTPUT_SIZE / 16, 8, + {0x40000123, 0x00000000, 0x00000000, 0x00000000, 0x40c00123}}, + {SetMatrixPointerArray}, + {SetMatrixPointerArray, 0, 1, REGISTER_OUTPUT_SIZE / 16, 8, + {0x40000123, 0x00000000, 0x00000000, 0x00000000, 0x00000000}}, + {SetMatrixTransposePointerArray}, + {SetMatrixTransposePointerArray, 0, 1, REGISTER_OUTPUT_SIZE / 16, 8, + {0x40000123, 0x00000000, 0x00000000, 0x00000000, 0x40c00123}}, +}; + +static const struct registerset_constants registerset_constants_scalar_array_int[] = +{ + {"an", {"an", D3DXRS_INT4, 0, 2, D3DXPC_SCALAR, D3DXPT_INT, 1, 1, 2, 0, 8, NULL}, 70}, + {"an[0]", {"an", D3DXRS_INT4, 0, 1, D3DXPC_SCALAR, D3DXPT_INT, 1, 1, 1, 0, 4, NULL}, 70}, + {"an[1]", {"an", D3DXRS_INT4, 1, 1, D3DXPC_SCALAR, D3DXPT_INT, 1, 1, 1, 0, 4, NULL}, 74}, +}; + +static const struct registerset_test registerset_test_scalar_array_int[] = +{ + {SetFloat, 0, 0, 0, 4, {0x00000002, 0x00000000, 0x00000001}}, + {SetInt, 1, 0, 0, 4, {0x00000002, 0x00000000, 0x00000001}}, + {SetBool, 1, 0, 0, 4, {0x00000001, 0x00000000, 0x00000001}}, + {SetIntArray}, + {SetIntArray, 1, 1, 1, 4, {0x00000002, 0x00000000, 0x00000001}}, + {SetIntArray, 1, 2, REGISTER_OUTPUT_SIZE, 8, + {0x00000002, 0x00000000, 0x00000001, 0x00000000, 0x00000003, 0x00000000, 0x00000001}}, + {SetBoolArray}, + {SetBoolArray, 1, 1, 1, 4, {0x00000001, 0x00000000, 0x00000001}}, + {SetBoolArray, 1, 2, REGISTER_OUTPUT_SIZE, 8, + {0x00000001, 0x00000000, 0x00000001, 0x00000000, 0x00000001, 0x00000000, 0x00000001}}, + {SetFloatArray}, + {SetFloatArray, 0, 1, 1, 4, {0x00000002, 0x00000000, 0x00000001}}, + {SetFloatArray, 0, 2, REGISTER_OUTPUT_SIZE, 8, + {0x00000002, 0x00000000, 0x00000001, 0x00000000, 0x00000000, 0x00000000, 0x00000001}}, + {SetValue, 1, 0, 3}, + {SetValue, 1, 4, 7, 4, {0x00000002, 0x00000000, 0x00000001}}, + {SetValue, 1, 8, REGISTER_OUTPUT_SIZE * 4, 8, + {0x00000002, 0x00000000, 0x00000001, 0x00000000, 0x00000003, 0x00000000, 0x00000001}}, + {SetVector, 0, 0, 0, 8, + {0x00000002, 0x00000000, 0x00000001, 0x00000000, 0x00000000, 0x00000000, 0x00000001}}, + {SetVectorArray}, + {SetVectorArray, 0, 1, REGISTER_OUTPUT_SIZE / 4, 8, + {0x00000002, 0x00000000, 0x00000001, 0x00000000, 0x00000000, 0x00000000, 0x00000001}}, + {SetMatrix, 0, 0, 0, 8, + {0x00000002, 0x00000000, 0x00000001, 0x00000000, 0x00000000, 0x00000000, 0x00000001}}, + {SetMatrixArray}, + {SetMatrixArray, 0, 1, REGISTER_OUTPUT_SIZE / 16, 8, + {0x00000002, 0x00000000, 0x00000001, 0x00000000, 0x00000000, 0x00000000, 0x00000001}}, + {SetMatrixTranspose, 0, 0, 0, 8, + {0x00000002, 0x00000000, 0x00000001, 0x00000000, 0x00000006, 0x00000000, 0x00000001}}, + {SetMatrixTransposeArray}, + {SetMatrixTransposeArray, 0, 1, REGISTER_OUTPUT_SIZE / 16, 8, + {0x00000002, 0x00000000, 0x00000001, 0x00000000, 0x00000006, 0x00000000, 0x00000001}}, + {SetMatrixPointerArray}, + {SetMatrixPointerArray, 0, 1, REGISTER_OUTPUT_SIZE / 16, 8, + {0x00000002, 0x00000000, 0x00000001, 0x00000000, 0x00000000, 0x00000000, 0x00000001}}, + {SetMatrixTransposePointerArray}, + {SetMatrixTransposePointerArray, 0, 1, REGISTER_OUTPUT_SIZE / 16, 8, + {0x00000002, 0x00000000, 0x00000001, 0x00000000, 0x00000006, 0x00000000, 0x00000001}}, +}; + +static const struct registerset_constants registerset_constants_scalar_array_bool[] = +{ + {"ab", {"ab", D3DXRS_BOOL, 0, 2, D3DXPC_SCALAR, D3DXPT_BOOL, 1, 1, 2, 0, 8, NULL}, 37}, + {"ab[0]", {"ab", D3DXRS_BOOL, 0, 1, D3DXPC_SCALAR, D3DXPT_BOOL, 1, 1, 1, 0, 4, NULL}, 37}, + {"ab[1]", {"ab", D3DXRS_BOOL, 1, 1, D3DXPC_SCALAR, D3DXPT_BOOL, 1, 1, 1, 0, 4, NULL}, 38}, +}; + +static const struct registerset_test registerset_test_scalar_array_bool[] = +{ + {SetFloat, 0, 0, 0, 1, {0x00000001}}, + {SetInt, 1, 0, 0, 1, {0x00000001}}, + {SetBool, 1, 0, 0, 1, {0x00000002}}, + {SetIntArray}, + {SetIntArray, 1, 1, 1, 1, {0x00000001}}, + {SetIntArray, 1, 2, REGISTER_OUTPUT_SIZE, 2, {0x00000001, 0x00000001}}, + {SetBoolArray}, + {SetBoolArray, 1, 1, 1, 1, {0x00000002}}, + {SetBoolArray, 1, 2, REGISTER_OUTPUT_SIZE, 2, {0x00000002, 0x00000003}}, + {SetFloatArray}, + {SetFloatArray, 0, 1, 1, 1, {0x00000001}}, + {SetFloatArray, 0, 2, REGISTER_OUTPUT_SIZE, 2, {0x00000001, 0x00000000}}, + {SetValue, 1, 0, 3}, + {SetValue, 1, 4, 7, 1, {0x00000002}}, + {SetValue, 1, 8, REGISTER_OUTPUT_SIZE * 4, 2, {0x00000002, 0x00000003}}, + {SetVector, 0, 0, 0, 2, {0x00000001, 0x00000000}}, + {SetVectorArray}, + {SetVectorArray, 0, 1, REGISTER_OUTPUT_SIZE / 4, 2, {0x00000001, 0x00000000}}, + {SetMatrix, 0, 0, 0, 2, {0x00000001, 0x00000000}}, + {SetMatrixArray}, + {SetMatrixArray, 0, 1, REGISTER_OUTPUT_SIZE / 16, 2, {0x00000001, 0x00000000}}, + {SetMatrixTranspose, 0, 0, 0, 2, {0x00000001, 0x00000001}}, + {SetMatrixTransposeArray}, + {SetMatrixTransposeArray, 0, 1, REGISTER_OUTPUT_SIZE / 16, 2, {0x00000001, 0x00000001}}, + {SetMatrixPointerArray}, + {SetMatrixPointerArray, 0, 1, REGISTER_OUTPUT_SIZE / 16, 2, {0x00000001, 0x00000000}}, + {SetMatrixTransposePointerArray}, + {SetMatrixTransposePointerArray, 0, 1, REGISTER_OUTPUT_SIZE / 16, 2, {0x00000001, 0x00000001}}, +}; + +static const struct registerset_constants registerset_constants_scalar_array_bool_float[] = +{ + {"abf", {"abf", D3DXRS_FLOAT4, 4, 2, D3DXPC_SCALAR, D3DXPT_BOOL, 1, 1, 2, 0, 8, NULL}, 44}, + {"abf[0]", {"abf", D3DXRS_FLOAT4, 4, 1, D3DXPC_SCALAR, D3DXPT_BOOL, 1, 1, 1, 0, 4, NULL}, 44}, + {"abf[1]", {"abf", D3DXRS_FLOAT4, 5, 1, D3DXPC_SCALAR, D3DXPT_BOOL, 1, 1, 1, 0, 4, NULL}, 48}, +}; + +static const struct registerset_test registerset_test_scalar_array_bool_float[] = +{ + {SetFloat, 0, 0, 0, 4, {0x3f800000}}, + {SetInt, 1, 0, 0, 4, {0x3f800000}}, + {SetBool, 1, 0, 0, 4, {0x3f800000}}, + {SetIntArray}, + {SetIntArray, 1, 1, 1, 4, {0x3f800000}}, + {SetIntArray, 1, 2, REGISTER_OUTPUT_SIZE, 8, + {0x3f800000, 0x00000000, 0x00000000, 0x00000000, 0x3f800000}}, + {SetBoolArray}, + {SetBoolArray, 1, 1, 1, 4, {0x3f800000}}, + {SetBoolArray, 1, 2, REGISTER_OUTPUT_SIZE, 8, + {0x3f800000, 0x00000000, 0x00000000, 0x00000000, 0x3f800000}}, + {SetFloatArray}, + {SetFloatArray, 0, 1, 1, 4, {0x3f800000}}, + {SetFloatArray, 0, 2, REGISTER_OUTPUT_SIZE, 8, + {0x3f800000, 0x00000000, 0x00000000, 0x00000000, 0x00000000}}, + {SetValue, 1, 0, 3}, + {SetValue, 1, 4, 7, 4, {0x3f800000}}, + {SetValue, 1, 8, REGISTER_OUTPUT_SIZE * 4, 8, + {0x3f800000, 0x00000000, 0x00000000, 0x00000000, 0x3f800000}}, + {SetVector, 0, 0, 0, 8, + {0x3f800000, 0x00000000, 0x00000000, 0x00000000, 0x00000000}}, + {SetVectorArray}, + {SetVectorArray, 0, 1, REGISTER_OUTPUT_SIZE / 4, 8, + {0x3f800000, 0x00000000, 0x00000000, 0x00000000, 0x00000000}}, + {SetMatrix, 0, 0, 0, 8, + {0x3f800000, 0x00000000, 0x00000000, 0x00000000, 0x00000000}}, + {SetVectorArray}, + {SetMatrixArray, 0, 1, REGISTER_OUTPUT_SIZE / 16, 8, + {0x3f800000, 0x00000000, 0x00000000, 0x00000000, 0x00000000}}, + {SetMatrixTranspose, 0, 0, 0, 8, + {0x3f800000, 0x00000000, 0x00000000, 0x00000000, 0x3f800000}}, + {SetMatrixTransposeArray}, + {SetMatrixTransposeArray, 0, 1, REGISTER_OUTPUT_SIZE / 16, 8, + {0x3f800000, 0x00000000, 0x00000000, 0x00000000, 0x3f800000}}, + {SetMatrixPointerArray}, + {SetMatrixPointerArray, 0, 1, REGISTER_OUTPUT_SIZE / 16, 8, + {0x3f800000, 0x00000000, 0x00000000, 0x00000000, 0x00000000}}, + {SetMatrixTransposePointerArray}, + {SetMatrixTransposePointerArray, 0, 1, REGISTER_OUTPUT_SIZE / 16, 8, + {0x3f800000, 0x00000000, 0x00000000, 0x00000000, 0x3f800000}}, +}; + +static const struct registerset_constants registerset_constants_scalar_array_int_float[] = +{ + {"anf", {"anf", D3DXRS_FLOAT4, 2, 2, D3DXPC_SCALAR, D3DXPT_INT, 1, 1, 2, 0, 8, NULL}, 83}, + {"anf[0]", {"anf", D3DXRS_FLOAT4, 2, 1, D3DXPC_SCALAR, D3DXPT_INT, 1, 1, 1, 0, 4, NULL}, 83}, + {"anf[1]", {"anf", D3DXRS_FLOAT4, 3, 1, D3DXPC_SCALAR, D3DXPT_INT, 1, 1, 1, 0, 4, NULL}, 87}, +}; + +static const struct registerset_test registerset_test_scalar_array_int_float[] = +{ + {SetFloat, 0, 0, 0, 4, {0x40000000}}, + {SetInt, 1, 0, 0, 4, {0x40000000}}, + {SetBool, 1, 0, 0, 4, {0x3f800000}}, + {SetIntArray}, + {SetIntArray, 1, 1, 1, 4, {0x40000000}}, + {SetIntArray, 1, 2, REGISTER_OUTPUT_SIZE, 8, + {0x40000000, 0x00000000, 0x00000000, 0x00000000, 0x40400000}}, + {SetBoolArray}, + {SetBoolArray, 1, 1, 1, 4, {0x3f800000}}, + {SetBoolArray, 1, 2, REGISTER_OUTPUT_SIZE, 8, + {0x3f800000, 0x00000000, 0x00000000, 0x00000000, 0x3f800000}}, + {SetFloatArray}, + {SetFloatArray, 0, 1, 1, 4, {0x40000000}}, + {SetFloatArray, 0, 2, REGISTER_OUTPUT_SIZE, 8, + {0x40000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000}}, + {SetValue, 1, 0, 3}, + {SetValue, 1, 4, 7, 4, {0x40000000}}, + {SetValue, 1, 8, REGISTER_OUTPUT_SIZE * 4, 8, + {0x40000000, 0x00000000, 0x00000000, 0x00000000, 0x40400000}}, + {SetVector, 0, 0, 0, 8, + {0x40000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000}}, + {SetVectorArray}, + {SetVectorArray, 0, 1, REGISTER_OUTPUT_SIZE / 4, 8, + {0x40000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000}}, + {SetMatrix, 0, 0, 0, 8, + {0x40000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000}}, + {SetMatrixArray}, + {SetMatrixArray, 0, 1, REGISTER_OUTPUT_SIZE / 16, 8, + {0x40000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000}}, + {SetMatrixTranspose, 0, 0, 0, 8, + {0x40000000, 0x00000000, 0x00000000, 0x00000000, 0x40c00000}}, + {SetMatrixTransposeArray}, + {SetMatrixTransposeArray, 0, 1, REGISTER_OUTPUT_SIZE / 16, 8, + {0x40000000, 0x00000000, 0x00000000, 0x00000000, 0x40c00000}}, + {SetMatrixPointerArray}, + {SetMatrixPointerArray, 0, 1, REGISTER_OUTPUT_SIZE / 16, 8, + {0x40000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000}}, + {SetMatrixTransposePointerArray}, + {SetMatrixTransposePointerArray, 0, 1, REGISTER_OUTPUT_SIZE / 16, 8, + {0x40000000, 0x00000000, 0x00000000, 0x00000000, 0x40c00000}}, +}; + +/* + * fxc.exe /Tvs_3_0 + */ +#if 0 +bool3 vb = {1, 0, 1}; +int3 vn = {7, 8, 9}; +float3 vf = {5.1, 5.2, 5.3}; +int3 vnf = {11, 85, 62}; +bool3 vbf = {1, 1, 1}; +float4 main(float4 pos : POSITION) : POSITION +{ + float4 tmp = 0; + int i; + if (vb.z) for (i = 0; i < vn.z; i++) tmp.x += pos.z * vf.z * vnf.z; + else for (i = 0; i < vn.y; i++) tmp.y += pos.y * vf.y * vbf.z; + return tmp; +} +#endif +static const DWORD registerset_blob_vector[] = +{ +0xfffe0300, 0x0053fffe, 0x42415443, 0x0000001c, 0x00000117, 0xfffe0300, 0x00000005, 0x0000001c, +0x00000100, 0x00000110, 0x00000080, 0x00000000, 0x00000003, 0x00000084, 0x00000094, 0x000000a0, +0x00020002, 0x00000001, 0x00000084, 0x000000a4, 0x000000b4, 0x00000002, 0x00000001, 0x000000b8, +0x000000c8, 0x000000d8, 0x00000001, 0x00000003, 0x000000dc, 0x000000ec, 0x000000fc, 0x00010002, +0x00000001, 0x000000dc, 0x00000100, 0xab006276, 0x00010001, 0x00030001, 0x00000001, 0x00000000, +0xffffffff, 0x00000000, 0xffffffff, 0x00666276, 0x3f800000, 0x3f800000, 0x3f800000, 0x00000000, +0xab006676, 0x00030001, 0x00030001, 0x00000001, 0x00000000, 0x40a33333, 0x40a66666, 0x40a9999a, +0x00000000, 0xab006e76, 0x00020001, 0x00030001, 0x00000001, 0x00000000, 0x00000007, 0x00000008, +0x00000009, 0x00000000, 0x00666e76, 0x41300000, 0x42aa0000, 0x42780000, 0x00000000, 0x335f7376, +0x4d00305f, 0x6f726369, 0x74666f73, 0x29522820, 0x534c4820, 0x6853204c, 0x72656461, 0x6d6f4320, +0x656c6970, 0x2e392072, 0x392e3932, 0x332e3235, 0x00313131, 0x05000051, 0xa00f0003, 0x00000000, +0x00000000, 0x00000000, 0x00000000, 0x0200001f, 0x80000000, 0x900f0000, 0x0200001f, 0x80000000, +0xe00f0000, 0x01000028, 0xe0e40802, 0x03000005, 0x80010000, 0xa0aa0000, 0x90aa0000, 0x02000001, +0x80010001, 0xa0000003, 0x01000026, 0xf0e40002, 0x04000004, 0x80010001, 0x80000000, 0xa0aa0001, +0x80000001, 0x00000027, 0x02000001, 0x80020001, 0xa0000003, 0x0000002a, 0x03000005, 0x80010000, +0xa0550000, 0x90550000, 0x02000001, 0x80020001, 0xa0000003, 0x01000026, 0xf0e40001, 0x04000004, +0x80020001, 0x80000000, 0xa0aa0002, 0x80550001, 0x00000027, 0x02000001, 0x80010001, 0xa0000003, +0x0000002b, 0x02000001, 0xe0030000, 0x80e40001, 0x02000001, 0xe00c0000, 0xa0000003, 0x0000ffff, +}; + +static const struct registerset_constants registerset_constants_vector_float[] = +{ + {"vf", {"vf", D3DXRS_FLOAT4, 0, 1, D3DXPC_VECTOR, D3DXPT_FLOAT, 1, 3, 1, 0, 12, NULL}, 50}, +}; + +static const struct registerset_test registerset_test_vector_float[] = +{ + {SetInt}, + {SetBool}, + {SetFloat}, + {SetIntArray, 1, 0, 2}, + {SetIntArray, 1, 3, REGISTER_OUTPUT_SIZE, 4, {0x40000000, 0x40400000, 0x40800000}}, + {SetBoolArray, 1, 0, 2}, + {SetBoolArray, 1, 3, REGISTER_OUTPUT_SIZE, 4, {0x3f800000, 0x3f800000, 0x3f800000}}, + {SetFloatArray, 0, 0, 2}, + {SetFloatArray, 0, 3, REGISTER_OUTPUT_SIZE, 4, {0x40000123, 0x00000000, 0x40800123}}, + {SetValue, 0, 0, 11}, + {SetValue, 0, 12, REGISTER_OUTPUT_SIZE * 4, 4, {0x40000123, 0x00000000, 0x40800123}}, + {SetVector, 0, 0, 0, 4, {0x40000123, 0x00000000, 0x40800123}}, + {SetVectorArray}, + {SetVectorArray, 0, 1, REGISTER_OUTPUT_SIZE / 4, 4, {0x40000123, 0x00000000, 0x40800123}}, + {SetMatrix, 0, 0, 0, 4, {0x40000123, 0x00000000, 0x40800123}}, + {SetMatrixArray}, + {SetMatrixArray, 0, 1, REGISTER_OUTPUT_SIZE / 16, 4, {0x40000123, 0x00000000, 0x40800123}}, + {SetMatrixTranspose, 0, 0, 0, 4, {0x40000123, 0x40c00123, 0x41200123}}, + {SetMatrixTransposeArray}, + {SetMatrixTransposeArray, 0, 1, REGISTER_OUTPUT_SIZE / 16, 4, {0x40000123, 0x40c00123, 0x41200123}}, + {SetMatrixPointerArray}, + {SetMatrixPointerArray, 0, 1, REGISTER_OUTPUT_SIZE / 16, 4, {0x40000123, 0x00000000, 0x40800123}}, + {SetMatrixTransposePointerArray}, + {SetMatrixTransposePointerArray, 0, 1, REGISTER_OUTPUT_SIZE / 16, 4, {0x40000123, 0x40c00123, 0x41200123}}, +}; + +static const struct registerset_constants registerset_constants_vector_int[] = +{ + {"vn", {"vn", D3DXRS_INT4, 0, 3, D3DXPC_VECTOR, D3DXPT_INT, 1, 3, 1, 0, 12, NULL}, 59}, +}; + +static const struct registerset_test registerset_test_vector_int[] = +{ + {SetInt}, + {SetBool}, + {SetFloat}, + {SetIntArray, 1, 0, 2}, + {SetIntArray, 1, 3, REGISTER_OUTPUT_SIZE, 4, {0x00000002, 0x00000003, 0x00000004}}, + {SetBoolArray, 1, 0, 2}, + {SetBoolArray, 1, 3, REGISTER_OUTPUT_SIZE, 4, {0x00000001, 0x00000001, 0x00000001}}, + {SetFloatArray, 0, 0, 2}, + {SetFloatArray, 0, 3, REGISTER_OUTPUT_SIZE, 4, {0x00000002, 0x00000000, 0x00000004}}, + {SetValue, 1, 0, 11}, + {SetValue, 1, 12, REGISTER_OUTPUT_SIZE * 4, 4, {0x00000002, 0x00000003, 0x00000004}}, + {SetVector, 0, 0, 0, 4, {0x00000002, 0x00000000, 0x00000004}}, + {SetVectorArray}, + {SetVectorArray, 0, 1, REGISTER_OUTPUT_SIZE / 4, 4, {0x00000002, 0x00000000, 0x00000004}}, + {SetMatrix, 0, 0, 0, 4, {0x00000002, 0x00000000, 0x00000004}}, + {SetMatrixArray}, + {SetMatrixArray, 0, 1, REGISTER_OUTPUT_SIZE / 16, 4, {0x00000002, 0x00000000, 0x00000004}}, + {SetMatrixTranspose, 0, 0, 0, 4, {0x00000002, 0x00000006, 0x0000000a}}, + {SetMatrixTransposeArray}, + {SetMatrixTransposeArray, 0, 1, REGISTER_OUTPUT_SIZE / 16, 4, {0x00000002, 0x00000006, 0x0000000a}}, + {SetMatrixPointerArray}, + {SetMatrixPointerArray, 0, 1, REGISTER_OUTPUT_SIZE / 16, 4, {0x00000002, 0x00000000, 0x00000004}}, + {SetMatrixTransposePointerArray}, + {SetMatrixTransposePointerArray, 0, 1, REGISTER_OUTPUT_SIZE / 16, 4, {0x00000002, 0x00000006, 0x0000000a}}, +}; + +static const struct registerset_constants registerset_constants_vector_bool[] = +{ + {"vb", {"vb", D3DXRS_BOOL, 0, 3, D3DXPC_VECTOR, D3DXPT_BOOL, 1, 3, 1, 0, 12, NULL}, 37}, +}; + +static const struct registerset_test registerset_test_vector_bool[] = +{ + {SetInt}, + {SetBool}, + {SetFloat}, + {SetIntArray, 1, 0, 2}, + {SetIntArray, 1, 3, REGISTER_OUTPUT_SIZE, 3, {0x00000001, 0x00000001, 0x00000001}}, + {SetBoolArray, 1, 0, 2}, + {SetBoolArray, 1, 3, REGISTER_OUTPUT_SIZE, 3, {0x00000002, 0x00000003, 0x00000004}}, + {SetFloatArray, 0, 0, 2}, + {SetFloatArray, 0, 3, REGISTER_OUTPUT_SIZE, 3, {0x00000001, 0x00000000, 0x00000001}}, + {SetValue, 1, 0, 11}, + {SetValue, 1, 12, REGISTER_OUTPUT_SIZE * 4, 3, {0x00000002, 0x00000003, 0x00000004}}, + {SetVector, 0, 0, 0, 3, {0x00000001, 0x00000000, 0x00000001}}, + {SetVectorArray}, + {SetVectorArray, 0, 1, REGISTER_OUTPUT_SIZE / 4, 3, {0x00000001, 0x00000000, 0x00000001}}, + {SetMatrix, 0, 0, 0, 3, {0x00000001, 0x00000000, 0x00000001}}, + {SetMatrixArray}, + {SetMatrixArray, 0, 1, REGISTER_OUTPUT_SIZE / 16, 3, {0x00000001, 0x00000000, 0x00000001}}, + {SetMatrixTranspose, 0, 0, 0, 3, {0x00000001, 0x00000001, 0x00000001}}, + {SetMatrixTransposeArray}, + {SetMatrixTransposeArray, 0, 1, REGISTER_OUTPUT_SIZE / 16, 3, {0x00000001, 0x00000001, 0x00000001}}, + {SetMatrixPointerArray}, + {SetMatrixPointerArray, 0, 1, REGISTER_OUTPUT_SIZE / 16, 3, {0x00000001, 0x00000000, 0x00000001}}, + {SetMatrixTransposePointerArray}, + {SetMatrixTransposePointerArray, 0, 1, REGISTER_OUTPUT_SIZE / 16, 3, {0x00000001, 0x00000001, 0x00000001}}, +}; + +static const struct registerset_constants registerset_constants_vector_bool_float[] = +{ + {"vbf", {"vbf", D3DXRS_FLOAT4, 2, 1, D3DXPC_VECTOR, D3DXPT_BOOL, 1, 3, 1, 0, 12, NULL}, 41}, +}; + +static const struct registerset_test registerset_test_vector_bool_float[] = +{ + {SetInt}, + {SetBool}, + {SetFloat}, + {SetIntArray, 1, 0, 2}, + {SetIntArray, 1, 3, REGISTER_OUTPUT_SIZE, 4, {0x3f800000, 0x3f800000, 0x3f800000}}, + {SetBoolArray, 1, 0, 2}, + {SetBoolArray, 1, 3, REGISTER_OUTPUT_SIZE, 4, {0x3f800000, 0x3f800000, 0x3f800000}}, + {SetFloatArray, 0, 0, 2}, + {SetFloatArray, 0, 3, REGISTER_OUTPUT_SIZE, 4, {0x3f800000, 0x00000000, 0x3f800000}}, + {SetValue, 1, 0, 11}, + {SetValue, 1, 12, REGISTER_OUTPUT_SIZE * 4, 4, {0x3f800000, 0x3f800000, 0x3f800000}}, + {SetVector, 0, 0, 0, 4, {0x3f800000, 0x00000000, 0x3f800000}}, + {SetVectorArray}, + {SetVectorArray, 0, 1, REGISTER_OUTPUT_SIZE / 4, 4, {0x3f800000, 0x00000000, 0x3f800000}}, + {SetMatrix, 0, 0, 0, 4, {0x3f800000, 0x00000000, 0x3f800000}}, + {SetMatrixArray}, + {SetMatrixArray, 0, 1, REGISTER_OUTPUT_SIZE / 16, 4, {0x3f800000, 0x00000000, 0x3f800000}}, + {SetMatrixTranspose, 0, 0, 0, 4, {0x3f800000, 0x3f800000, 0x3f800000}}, + {SetMatrixTransposeArray}, + {SetMatrixTransposeArray, 0, 1, REGISTER_OUTPUT_SIZE / 16, 4, {0x3f800000, 0x3f800000, 0x3f800000}}, + {SetMatrixPointerArray}, + {SetMatrixPointerArray, 0, 1, REGISTER_OUTPUT_SIZE / 16, 4, {0x3f800000, 0x00000000, 0x3f800000}}, + {SetMatrixTransposePointerArray}, + {SetMatrixTransposePointerArray, 0, 1, REGISTER_OUTPUT_SIZE / 16, 4, {0x3f800000, 0x3f800000, 0x3f800000}}, +}; + +static const struct registerset_constants registerset_constants_vector_int_float[] = +{ + {"vnf", {"vnf", D3DXRS_FLOAT4, 1, 1, D3DXPC_VECTOR, D3DXPT_INT, 1, 3, 1, 0, 12, NULL}, 64}, +}; + +static const struct registerset_test registerset_test_vector_int_float[] = +{ + {SetInt}, + {SetBool}, + {SetFloat}, + {SetIntArray, 1, 0, 2}, + {SetIntArray, 1, 3, REGISTER_OUTPUT_SIZE, 4, {0x40000000, 0x40400000, 0x40800000}}, + {SetBoolArray, 1, 0, 2}, + {SetBoolArray, 1, 3, REGISTER_OUTPUT_SIZE, 4, {0x3f800000, 0x3f800000, 0x3f800000}}, + {SetFloatArray, 0, 0, 2}, + {SetFloatArray, 0, 3, REGISTER_OUTPUT_SIZE, 4, {0x40000000, 0x00000000, 0x40800000}}, + {SetValue, 1, 0, 11}, + {SetValue, 1, 12, REGISTER_OUTPUT_SIZE * 4, 4, {0x40000000, 0x40400000, 0x40800000}}, + {SetVector, 0, 0, 0, 4, {0x40000000, 0x00000000, 0x40800000}}, + {SetVectorArray}, + {SetVectorArray, 0, 1, REGISTER_OUTPUT_SIZE / 4, 4, {0x40000000, 0x00000000, 0x40800000}}, + {SetMatrix, 0, 0, 0, 4, {0x40000000, 0x00000000, 0x40800000}}, + {SetMatrixArray}, + {SetMatrixArray, 0, 1, REGISTER_OUTPUT_SIZE / 16, 4, {0x40000000, 0x00000000, 0x40800000}}, + {SetMatrixTranspose, 0, 0, 0, 4, {0x40000000, 0x40c00000, 0x41200000}}, + {SetMatrixTransposeArray}, + {SetMatrixTransposeArray, 0, 1, REGISTER_OUTPUT_SIZE / 16, 4, {0x40000000, 0x40c00000, 0x41200000}}, + {SetMatrixPointerArray}, + {SetMatrixPointerArray, 0, 1, REGISTER_OUTPUT_SIZE / 16, 4, {0x40000000, 0x00000000, 0x40800000}}, + {SetMatrixTransposePointerArray}, + {SetMatrixTransposePointerArray, 0, 1, REGISTER_OUTPUT_SIZE / 16, 4, {0x40000000, 0x40c00000, 0x41200000}}, +}; + +/* + * fxc.exe /Tvs_3_0 + */ +#if 0 +bool3 vab[2] = {1, 0, 1, 1, 0, 1}; +int3 van[2] = {70, 80, 90, 100, 110, 120}; +float3 vaf[2] = {55.1, 55.2, 55.3, 55.4, 55.5, 55.6}; +int3 vanf[2] = {130, 140, 150, 160, 170, 180}; +bool3 vabf[2] = {1, 1, 1, 1, 1, 1}; +float4 main(float4 pos : POSITION) : POSITION +{ + float4 tmp = 0; + int i; + if (vab[1].z) for (i = 0; i < van[1].z; i++) tmp.x += pos.z * vaf[1].z * vanf[1].z; + else for (i = 0; i < van[1].y; i++) tmp.y += pos.y * vaf[0].y * vabf[1].z; + return tmp; +} +#endif +static const DWORD registerset_blob_vector_array[] = +{ +0xfffe0300, 0x0070fffe, 0x42415443, 0x0000001c, 0x0000018b, 0xfffe0300, 0x00000005, 0x0000001c, +0x00000100, 0x00000184, 0x00000080, 0x00000000, 0x00000006, 0x00000084, 0x00000094, 0x000000ac, +0x00040002, 0x00000002, 0x000000b4, 0x000000c4, 0x000000e4, 0x00000002, 0x00000002, 0x000000e8, +0x000000f8, 0x00000118, 0x00000001, 0x00000006, 0x0000011c, 0x0000012c, 0x0000014c, 0x00020002, +0x00000002, 0x00000154, 0x00000164, 0x00626176, 0x00010001, 0x00030001, 0x00000002, 0x00000000, +0xffffffff, 0x00000000, 0xffffffff, 0xffffffff, 0x00000000, 0xffffffff, 0x66626176, 0xababab00, +0x00010001, 0x00030001, 0x00000002, 0x00000000, 0x3f800000, 0x3f800000, 0x3f800000, 0x00000000, +0x3f800000, 0x3f800000, 0x3f800000, 0x00000000, 0x00666176, 0x00030001, 0x00030001, 0x00000002, +0x00000000, 0x425c6666, 0x425ccccd, 0x425d3333, 0x00000000, 0x425d999a, 0x425e0000, 0x425e6666, +0x00000000, 0x006e6176, 0x00020001, 0x00030001, 0x00000002, 0x00000000, 0x00000046, 0x00000050, +0x0000005a, 0x00000000, 0x00000064, 0x0000006e, 0x00000078, 0x00000000, 0x666e6176, 0xababab00, +0x00020001, 0x00030001, 0x00000002, 0x00000000, 0x43020000, 0x430c0000, 0x43160000, 0x00000000, +0x43200000, 0x432a0000, 0x43340000, 0x00000000, 0x335f7376, 0x4d00305f, 0x6f726369, 0x74666f73, +0x29522820, 0x534c4820, 0x6853204c, 0x72656461, 0x6d6f4320, 0x656c6970, 0x2e392072, 0x392e3932, +0x332e3235, 0x00313131, 0x05000051, 0xa00f0006, 0x00000000, 0x00000000, 0x00000000, 0x00000000, +0x0200001f, 0x80000000, 0x900f0000, 0x0200001f, 0x80000000, 0xe00f0000, 0x01000028, 0xe0e40805, +0x03000005, 0x80010000, 0xa0aa0001, 0x90aa0000, 0x02000001, 0x80010001, 0xa0000006, 0x01000026, +0xf0e40005, 0x04000004, 0x80010001, 0x80000000, 0xa0aa0003, 0x80000001, 0x00000027, 0x02000001, +0x80020001, 0xa0000006, 0x0000002a, 0x03000005, 0x80010000, 0xa0550000, 0x90550000, 0x02000001, +0x80020001, 0xa0000006, 0x01000026, 0xf0e40004, 0x04000004, 0x80020001, 0x80000000, 0xa0aa0005, +0x80550001, 0x00000027, 0x02000001, 0x80010001, 0xa0000006, 0x0000002b, 0x02000001, 0xe0030000, +0x80e40001, 0x02000001, 0xe00c0000, 0xa0000006, 0x0000ffff, +}; + +static const struct registerset_constants registerset_constants_vector_array_float[] = +{ + {"vaf", {"vaf", D3DXRS_FLOAT4, 0, 2, D3DXPC_VECTOR, D3DXPT_FLOAT, 1, 3, 2, 0, 24, NULL}, 62}, + {"vaf[0]", {"vaf", D3DXRS_FLOAT4, 0, 1, D3DXPC_VECTOR, D3DXPT_FLOAT, 1, 3, 1, 0, 12, NULL}, 62}, + {"vaf[1]", {"vaf", D3DXRS_FLOAT4, 1, 1, D3DXPC_VECTOR, D3DXPT_FLOAT, 1, 3, 1, 0, 12, NULL}, 66}, +}; + +static const struct registerset_test registerset_test_vector_array_float[] = +{ + {SetInt}, + {SetBool}, + {SetFloat}, + {SetIntArray, 1, 0, 2}, + {SetIntArray, 1, 3, 5, 4, {0x40000000, 0x40400000, 0x40800000}}, + {SetIntArray, 1, 6, REGISTER_OUTPUT_SIZE, 8, + {0x40000000, 0x40400000, 0x40800000, 0x00000000, 0x40a00000, 0x00000000, 0x40e00000}}, + {SetBoolArray, 1, 0, 2}, + {SetBoolArray, 1, 3, 5, 4, {0x3f800000, 0x3f800000, 0x3f800000}}, + {SetBoolArray, 1, 6, REGISTER_OUTPUT_SIZE, 8, + {0x3f800000, 0x3f800000, 0x3f800000, 0x00000000, 0x3f800000, 0x00000000, 0x3f800000}}, + {SetFloatArray, 0, 0, 2}, + {SetFloatArray, 0, 3, 5, 4, {0x40000123, 0x00000000, 0x40800123}}, + {SetFloatArray, 0, 6, REGISTER_OUTPUT_SIZE, 8, + {0x40000123, 0x00000000, 0x40800123, 0x00000000, 0x40a00123, 0x40c00123, 0x40e00123}}, + {SetValue, 0, 0, 11}, + {SetValue, 0, 12, 23, 4, {0x40000123, 0x00000000, 0x40800123}}, + {SetValue, 0, 24, REGISTER_OUTPUT_SIZE * 4, 8, + {0x40000123, 0x00000000, 0x40800123, 0x00000000, 0x40a00123, 0x40c00123, 0x40e00123}}, + {SetVector, 0, 0, 0, 4, {0x40000123, 0x00000000, 0x40800123}}, + {SetVectorArray}, + {SetVectorArray, 0, 1, 1, 4, {0x40000123, 0x00000000, 0x40800123}}, + {SetVectorArray, 0, 2, REGISTER_OUTPUT_SIZE / 4, 8, + {0x40000123, 0x00000000, 0x40800123, 0x00000000, 0x40c00123, 0x40e00123, 0x41000123}}, + {SetMatrix, 0, 0, 0, 8, + {0x40000123, 0x00000000, 0x40800123, 0x00000000, 0x40c00123, 0x40e00123, 0x41000123}}, + {SetMatrixArray}, + {SetMatrixArray, 0, 1, REGISTER_OUTPUT_SIZE / 16, 8, + {0x40000123, 0x00000000, 0x40800123, 0x00000000, 0x40c00123, 0x40e00123, 0x41000123}}, + {SetMatrixTranspose, 0, 0, 0, 8, + {0x40000123, 0x40c00123, 0x41200123, 0x00000000, 0x00000000, 0x40e00123, 0x41300123}}, + {SetMatrixTransposeArray}, + {SetMatrixTransposeArray, 0, 1, REGISTER_OUTPUT_SIZE / 16, 8, + {0x40000123, 0x40c00123, 0x41200123, 0x00000000, 0x00000000, 0x40e00123, 0x41300123}}, + {SetMatrixPointerArray}, + {SetMatrixPointerArray, 0, 1, REGISTER_OUTPUT_SIZE / 16, 8, + {0x40000123, 0x00000000, 0x40800123, 0x00000000, 0x40c00123, 0x40e00123, 0x41000123}}, + {SetMatrixTransposePointerArray}, + {SetMatrixTransposePointerArray, 0, 1, REGISTER_OUTPUT_SIZE / 16, 8, + {0x40000123, 0x40c00123, 0x41200123, 0x00000000, 0x00000000, 0x40e00123, 0x41300123}}, +}; + +static const struct registerset_constants registerset_constants_vector_array_int[] = +{ + {"van", {"van", D3DXRS_INT4, 0, 6, D3DXPC_VECTOR, D3DXPT_INT, 1, 3, 2, 0, 24, NULL}, 75}, + {"van[0]", {"van", D3DXRS_INT4, 0, 1, D3DXPC_VECTOR, D3DXPT_INT, 1, 3, 1, 0, 12, NULL}, 75}, + {"van[1]", {"van", D3DXRS_INT4, 1, 1, D3DXPC_VECTOR, D3DXPT_INT, 1, 3, 1, 0, 12, NULL}, 79}, +}; + +static const struct registerset_test registerset_test_vector_array_int[] = +{ + {SetInt}, + {SetBool}, + {SetFloat}, + {SetIntArray, 1, 0, 2}, + {SetIntArray, 1, 3, 5, 4, {0x00000002, 0x00000003, 0x00000004}}, + {SetIntArray, 1, 6, REGISTER_OUTPUT_SIZE, 8, + {0x00000002, 0x00000003, 0x00000004, 0x00000000, 0x00000005, 0x00000000, 0x00000007}}, + {SetBoolArray, 1, 0, 2}, + {SetBoolArray, 1, 3, 5, 4, {0x00000001, 0x00000001, 0x00000001}}, + {SetBoolArray, 1, 6, REGISTER_OUTPUT_SIZE, 8, + {0x00000001, 0x00000001, 0x00000001, 0x00000000, 0x00000001, 0x00000000, 0x00000001}}, + {SetFloatArray, 0, 0, 2}, + {SetFloatArray, 0, 3, 5, 4, {0x00000002, 0x00000000, 0x00000004}}, + {SetFloatArray, 0, 6, REGISTER_OUTPUT_SIZE, 8, + {0x00000002, 0x00000000, 0x00000004, 0x00000000, 0x00000005, 0x00000006, 0x00000007}}, + {SetValue, 1, 0, 11}, + {SetValue, 1, 12, 23, 4, {0x00000002, 0x00000003, 0x00000004}}, + {SetValue, 1, 24, REGISTER_OUTPUT_SIZE * 4, 8, + {0x00000002, 0x00000003, 0x00000004, 0x00000000, 0x00000005, 0x00000000, 0x00000007}}, + {SetVector, 0, 0, 0, 4, {0x00000002, 0x00000000, 0x00000004}}, + {SetVectorArray, 0, 0, 0}, + {SetVectorArray, 0, 1, 1, 4, {0x00000002, 0x00000000, 0x00000004}}, + {SetVectorArray, 0, 2, REGISTER_OUTPUT_SIZE / 4, 8, + {0x00000002, 0x00000000, 0x00000004, 0x00000000, 0x00000006, 0x00000007, 0x00000008}}, + {SetMatrix, 0, 0, 0, 8, + {0x00000002, 0x00000000, 0x00000004, 0x00000000, 0x00000006, 0x00000007, 0x00000008}}, + {SetMatrixArray}, + {SetMatrixArray, 0, 1, REGISTER_OUTPUT_SIZE / 16, 8, + {0x00000002, 0x00000000, 0x00000004, 0x00000000, 0x00000006, 0x00000007, 0x00000008}}, + {SetMatrixTranspose, 0, 0, 0, 8, + {0x00000002, 0x00000006, 0x0000000a, 0x00000000, 0x00000000, 0x00000007, 0x0000000b}}, + {SetMatrixTransposeArray}, + {SetMatrixTransposeArray, 0, 1, REGISTER_OUTPUT_SIZE / 16, 8, + {0x00000002, 0x00000006, 0x0000000a, 0x00000000, 0x00000000, 0x00000007, 0x0000000b}}, + {SetMatrixPointerArray}, + {SetMatrixPointerArray, 0, 1, REGISTER_OUTPUT_SIZE / 16, 8, + {0x00000002, 0x00000000, 0x00000004, 0x00000000, 0x00000006, 0x00000007, 0x00000008}}, + {SetMatrixTransposePointerArray}, + {SetMatrixTransposePointerArray, 0, 1, REGISTER_OUTPUT_SIZE / 16, 8, + {0x00000002, 0x00000006, 0x0000000a, 0x00000000, 0x00000000, 0x00000007, 0x0000000b}}, +}; + +static const struct registerset_constants registerset_constants_vector_array_bool[] = +{ + {"vab", {"vab", D3DXRS_BOOL, 0, 6, D3DXPC_VECTOR, D3DXPT_BOOL, 1, 3, 2, 0, 24, NULL}, 37}, + {"vab[0]", {"vab", D3DXRS_BOOL, 0, 3, D3DXPC_VECTOR, D3DXPT_BOOL, 1, 3, 1, 0, 12, NULL}, 37}, + {"vab[1]", {"vab", D3DXRS_BOOL, 3, 3, D3DXPC_VECTOR, D3DXPT_BOOL, 1, 3, 1, 0, 12, NULL}, 40}, +}; + +static const struct registerset_test registerset_test_vector_array_bool[] = +{ + {SetInt}, + {SetBool}, + {SetFloat}, + {SetIntArray, 1, 0, 2}, + {SetIntArray, 1, 3, 5, 3, {0x00000001, 0x00000001, 0x00000001}}, + {SetIntArray, 1, 6, REGISTER_OUTPUT_SIZE, 6, + {0x00000001, 0x00000001, 0x00000001, 0x00000001, 0x00000000, 0x00000001}}, + {SetBoolArray, 1, 0}, + {SetBoolArray, 1, 3, 5, 3, {0x00000002, 0x00000003, 0x00000004}}, + {SetBoolArray, 1, 6, REGISTER_OUTPUT_SIZE, 6, + {0x00000002, 0x00000003, 0x00000004, 0x00000005, 0x00000000, 0x00000007}}, + {SetFloatArray, 0, 0, 2}, + {SetFloatArray, 0, 3, 5, 3, {0x00000001, 0x00000000, 0x00000001}}, + {SetFloatArray, 0, 6, REGISTER_OUTPUT_SIZE, 6, + {0x00000001, 0x00000000, 0x00000001, 0x00000001, 0x00000001, 0x00000001}}, + {SetValue, 1, 0, 11}, + {SetValue, 1, 12, 23, 3, {0x00000002, 0x00000003, 0x00000004}}, + {SetValue, 1, 24, REGISTER_OUTPUT_SIZE * 4, 6, + {0x00000002, 0x00000003, 0x00000004, 0x00000005, 0x00000000, 0x00000007}}, + {SetVector, 0, 0, 0, 3, {0x00000001, 0x00000000, 0x00000001}}, + {SetVectorArray}, + {SetVectorArray, 0, 1, 1, 3, {0x00000001, 0x00000000, 0x00000001}}, + {SetVectorArray, 0, 2, REGISTER_OUTPUT_SIZE / 4, 6, + {0x00000001, 0x00000000, 0x00000001, 0x00000001, 0x00000001, 0x00000001}}, + {SetMatrix, 0, 0, 0, 6, + {0x00000001, 0x00000000, 0x00000001, 0x00000001, 0x00000001, 0x00000001}}, + {SetMatrixArray}, + {SetMatrixArray, 0, 1, REGISTER_OUTPUT_SIZE / 16, 6, + {0x00000001, 0x00000000, 0x00000001, 0x00000001, 0x00000001, 0x00000001}}, + {SetMatrixTranspose, 0, 0, 0, 6, + {0x00000001, 0x00000001, 0x00000001, 0x00000000, 0x00000001, 0x00000001}}, + {SetMatrixTransposeArray}, + {SetMatrixTransposeArray, 0, 1, REGISTER_OUTPUT_SIZE / 16, 6, + {0x00000001, 0x00000001, 0x00000001, 0x00000000, 0x00000001, 0x00000001}}, + {SetMatrixPointerArray}, + {SetMatrixPointerArray, 0, 1, REGISTER_OUTPUT_SIZE / 16, 6, + {0x00000001, 0x00000000, 0x00000001, 0x00000001, 0x00000001, 0x00000001}}, + {SetMatrixTransposePointerArray}, + {SetMatrixTransposePointerArray, 0, 1, REGISTER_OUTPUT_SIZE / 16, 6, + {0x00000001, 0x00000001, 0x00000001, 0x00000000, 0x00000001, 0x00000001}}, +}; + +static const struct registerset_constants registerset_constants_vector_array_bool_float[] = +{ + {"vabf", {"vabf", D3DXRS_FLOAT4, 4, 2, D3DXPC_VECTOR, D3DXPT_BOOL, 1, 3, 2, 0, 24, NULL}, 49}, + {"vabf[0]", {"vabf", D3DXRS_FLOAT4, 4, 1, D3DXPC_VECTOR, D3DXPT_BOOL, 1, 3, 1, 0, 12, NULL}, 49}, + {"vabf[1]", {"vabf", D3DXRS_FLOAT4, 5, 1, D3DXPC_VECTOR, D3DXPT_BOOL, 1, 3, 1, 0, 12, NULL}, 53}, +}; + +static const struct registerset_test registerset_test_vector_array_bool_float[] = +{ + {SetInt}, + {SetBool}, + {SetFloat}, + {SetIntArray, 1, 0, 2}, + {SetIntArray, 1, 3, 5, 4, {0x3f800000, 0x3f800000, 0x3f800000}}, + {SetIntArray, 1, 6, REGISTER_OUTPUT_SIZE, 8, + {0x3f800000, 0x3f800000, 0x3f800000, 0x00000000, 0x3f800000, 0x00000000, 0x3f800000}}, + {SetBoolArray, 1, 0, 2}, + {SetBoolArray, 1, 3, 5, 4, {0x3f800000, 0x3f800000, 0x3f800000}}, + {SetBoolArray, 1, 6, REGISTER_OUTPUT_SIZE, 8, + {0x3f800000, 0x3f800000, 0x3f800000, 0x00000000, 0x3f800000, 0x00000000, 0x3f800000}}, + {SetFloatArray, 0, 0, 2}, + {SetFloatArray, 0, 3, 5, 4, {0x3f800000, 0x00000000, 0x3f800000}}, + {SetFloatArray, 0, 6, REGISTER_OUTPUT_SIZE, 8, + {0x3f800000, 0x00000000, 0x3f800000, 0x00000000, 0x3f800000, 0x3f800000, 0x3f800000}}, + {SetValue, 1, 0, 11}, + {SetValue, 1, 12, 23, 4, {0x3f800000, 0x3f800000, 0x3f800000}}, + {SetValue, 1, 24, REGISTER_OUTPUT_SIZE * 4, 8, + {0x3f800000, 0x3f800000, 0x3f800000, 0x00000000, 0x3f800000, 0x00000000, 0x3f800000}}, + {SetVector, 0, 0, 0, 4, {0x3f800000, 0x00000000, 0x3f800000},}, + {SetVectorArray}, + {SetVectorArray, 0, 1, 1, 4, {0x3f800000, 0x00000000, 0x3f800000}}, + {SetVectorArray, 0, 2, REGISTER_OUTPUT_SIZE / 4, 8, + {0x3f800000, 0x00000000, 0x3f800000, 0x00000000, 0x3f800000, 0x3f800000, 0x3f800000}}, + {SetMatrix, 0, 0, 0, 8, + {0x3f800000, 0x00000000, 0x3f800000, 0x00000000, 0x3f800000, 0x3f800000, 0x3f800000}}, + {SetMatrixArray}, + {SetMatrixArray, 0, 1, REGISTER_OUTPUT_SIZE / 16, 8, + {0x3f800000, 0x00000000, 0x3f800000, 0x00000000, 0x3f800000, 0x3f800000, 0x3f800000}}, + {SetMatrixTranspose, 0, 0, 0, 8, + {0x3f800000, 0x3f800000, 0x3f800000, 0x00000000, 0x00000000, 0x3f800000, 0x3f800000}}, + {SetMatrixTransposeArray}, + {SetMatrixTransposeArray, 0, 1, REGISTER_OUTPUT_SIZE / 16, 8, + {0x3f800000, 0x3f800000, 0x3f800000, 0x00000000, 0x00000000, 0x3f800000, 0x3f800000}}, + {SetMatrixPointerArray}, + {SetMatrixPointerArray, 0, 1, REGISTER_OUTPUT_SIZE / 16, 8, + {0x3f800000, 0x00000000, 0x3f800000, 0x00000000, 0x3f800000, 0x3f800000, 0x3f800000}}, + {SetMatrixTransposePointerArray}, + {SetMatrixTransposePointerArray, 0, 1, REGISTER_OUTPUT_SIZE / 16, 8, + {0x3f800000, 0x3f800000, 0x3f800000, 0x00000000, 0x00000000, 0x3f800000, 0x3f800000}}, +}; + +static const struct registerset_constants registerset_constants_vector_array_int_float[] = +{ + {"vanf", {"vanf", D3DXRS_FLOAT4, 2, 2, D3DXPC_VECTOR, D3DXPT_INT, 1, 3, 2, 0, 24, NULL}, 89}, + {"vanf[0]", {"vanf", D3DXRS_FLOAT4, 2, 1, D3DXPC_VECTOR, D3DXPT_INT, 1, 3, 1, 0, 12, NULL}, 89}, + {"vanf[1]", {"vanf", D3DXRS_FLOAT4, 3, 1, D3DXPC_VECTOR, D3DXPT_INT, 1, 3, 1, 0, 12, NULL}, 93}, +}; + +static const struct registerset_test registerset_test_vector_array_int_float[] = +{ + {SetInt}, + {SetBool}, + {SetFloat}, + {SetIntArray, 1, 0, 2}, + {SetIntArray, 1, 3, 5, 4, {0x40000000, 0x40400000, 0x40800000}}, + {SetIntArray, 1, 6, REGISTER_OUTPUT_SIZE, 8, + {0x40000000, 0x40400000, 0x40800000, 0x00000000, 0x40a00000, 0x00000000, 0x40e00000}}, + {SetBoolArray, 1, 0, 2}, + {SetBoolArray, 1, 3, 5, 4, {0x3f800000, 0x3f800000, 0x3f800000}}, + {SetBoolArray, 1, 6, REGISTER_OUTPUT_SIZE, 8, + {0x3f800000, 0x3f800000, 0x3f800000, 0x00000000, 0x3f800000, 0x00000000, 0x3f800000}}, + {SetFloatArray, 2, 0, 2,}, + {SetFloatArray, 0, 3, 5, 4, {0x40000000, 0x00000000, 0x40800000}}, + {SetFloatArray, 0, 6, REGISTER_OUTPUT_SIZE, 8, + {0x40000000, 0x00000000, 0x40800000, 0x00000000, 0x40a00000, 0x40c00000, 0x40e00000}}, + {SetValue, 1, 0, 11}, + {SetValue, 1, 12, 23, 4, {0x40000000, 0x40400000, 0x40800000}}, + {SetValue, 1, 24, REGISTER_OUTPUT_SIZE * 4, 8, + {0x40000000, 0x40400000, 0x40800000, 0x00000000, 0x40a00000, 0x00000000, 0x40e00000}}, + {SetVector, 0, 0, 0, 4, {0x40000000, 0x00000000, 0x40800000}}, + {SetVectorArray}, + {SetVectorArray, 0, 1, 1, 4, {0x40000000, 0x00000000, 0x40800000}}, + {SetVectorArray, 0, 2, REGISTER_OUTPUT_SIZE / 4, 8, + {0x40000000, 0x00000000, 0x40800000, 0x00000000, 0x40c00000, 0x40e00000, 0x41000000}}, + {SetMatrix, 0, 0, 0, 8, + {0x40000000, 0x00000000, 0x40800000, 0x00000000, 0x40c00000, 0x40e00000, 0x41000000}}, + {SetMatrixArray}, + {SetMatrixArray, 0, 1, REGISTER_OUTPUT_SIZE / 16, 8, + {0x40000000, 0x00000000, 0x40800000, 0x00000000, 0x40c00000, 0x40e00000, 0x41000000}}, + {SetMatrixTranspose, 0, 0, 0, 8, + {0x40000000, 0x40c00000, 0x41200000, 0x00000000, 0x00000000, 0x40e00000, 0x41300000}}, + {SetMatrixTransposeArray}, + {SetMatrixTransposeArray, 0, 1, REGISTER_OUTPUT_SIZE / 16, 8, + {0x40000000, 0x40c00000, 0x41200000, 0x00000000, 0x00000000, 0x40e00000, 0x41300000}}, + {SetMatrixPointerArray}, + {SetMatrixPointerArray, 0, 1, REGISTER_OUTPUT_SIZE / 16, 8, + {0x40000000, 0x00000000, 0x40800000, 0x00000000, 0x40c00000, 0x40e00000, 0x41000000}}, + {SetMatrixTransposePointerArray}, + {SetMatrixTransposePointerArray, 0, 1, REGISTER_OUTPUT_SIZE / 16, 8, + {0x40000000, 0x40c00000, 0x41200000, 0x00000000, 0x00000000, 0x40e00000, 0x41300000}}, +}; + +/* + * fxc.exe /Tvs_3_0 + */ +#if 0 +bool3x2 cb = {1, 0, 1, 1, 0, 1}; +int3x2 cn = {4, 5, 6, 7, 8, 9}; +float3x2 cf = {15.1, 15.2, 15.3, 15.4, 15.5, 15.6}; +bool3x2 cbf = {1, 1, 0, 1, 0, 1}; +int3x2 cnf = {30, 31, 33, 32, 34, 36}; +float4 main(float4 pos : POSITION) : POSITION +{ + float4 tmp = 0; + int i; + if (cb._32) for (i = 0; i < cn._31; i++) tmp.x += pos.z * cf._31 * cbf._32; + else for (i = 0; i < cn._32; i++) tmp.y += pos.y * cf._32 * cnf._32; + return tmp; +} +#endif +static const DWORD registerset_blob_column[] = +{ +0xfffe0300, 0x0066fffe, 0x42415443, 0x0000001c, 0x00000163, 0xfffe0300, 0x00000005, 0x0000001c, +0x00000100, 0x0000015c, 0x00000080, 0x00000000, 0x00000006, 0x00000084, 0x00000094, 0x000000ac, +0x00020002, 0x00000002, 0x00000084, 0x000000b0, 0x000000d0, 0x00000002, 0x00000002, 0x000000d4, +0x000000e4, 0x00000104, 0x00000001, 0x00000006, 0x00000108, 0x00000118, 0x00000138, 0x00040002, +0x00000002, 0x00000108, 0x0000013c, 0xab006263, 0x00010003, 0x00020003, 0x00000001, 0x00000000, +0xffffffff, 0x00000000, 0xffffffff, 0xffffffff, 0x00000000, 0xffffffff, 0x00666263, 0x3f800000, +0x00000000, 0x00000000, 0x00000000, 0x3f800000, 0x3f800000, 0x3f800000, 0x00000000, 0xab006663, +0x00030003, 0x00020003, 0x00000001, 0x00000000, 0x4171999a, 0x4174cccd, 0x41780000, 0x00000000, +0x41733333, 0x41766666, 0x4179999a, 0x00000000, 0xab006e63, 0x00020003, 0x00020003, 0x00000001, +0x00000000, 0x00000004, 0x00000006, 0x00000008, 0x00000000, 0x00000005, 0x00000007, 0x00000009, +0x00000000, 0x00666e63, 0x41f00000, 0x42040000, 0x42080000, 0x00000000, 0x41f80000, 0x42000000, +0x42100000, 0x00000000, 0x335f7376, 0x4d00305f, 0x6f726369, 0x74666f73, 0x29522820, 0x534c4820, +0x6853204c, 0x72656461, 0x6d6f4320, 0x656c6970, 0x2e392072, 0x392e3932, 0x332e3235, 0x00313131, +0x05000051, 0xa00f0006, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x0200001f, 0x80000000, +0x900f0000, 0x0200001f, 0x80000000, 0xe00f0000, 0x01000028, 0xe0e40805, 0x03000005, 0x80010000, +0xa0aa0000, 0x90aa0000, 0x02000001, 0x80010001, 0xa0000006, 0x01000026, 0xf0e40004, 0x04000004, +0x80010001, 0x80000000, 0xa0aa0003, 0x80000001, 0x00000027, 0x02000001, 0x80020001, 0xa0000006, +0x0000002a, 0x03000005, 0x80010000, 0xa0aa0001, 0x90550000, 0x02000001, 0x80020001, 0xa0000006, +0x01000026, 0xf0e40005, 0x04000004, 0x80020001, 0x80000000, 0xa0aa0005, 0x80550001, 0x00000027, +0x02000001, 0x80010001, 0xa0000006, 0x0000002b, 0x02000001, 0xe0030000, 0x80e40001, 0x02000001, +0xe00c0000, 0xa0000006, 0x0000ffff, +}; + +static const struct registerset_constants registerset_constants_column_float[] = +{ + {"cf", {"cf", D3DXRS_FLOAT4, 0, 2, D3DXPC_MATRIX_COLUMNS, D3DXPT_FLOAT, 3, 2, 1, 0, 24, NULL}, 57}, +}; + +static const struct registerset_test registerset_test_column_float[] = +{ + {SetInt}, + {SetBool}, + {SetFloat}, + {SetIntArray, 1, 0, 5}, + {SetIntArray, 1, 6, REGISTER_OUTPUT_SIZE, 8, + {0x40000000, 0x40800000, 0x00000000, 0x00000000, 0x40400000, 0x40a00000, 0x40e00000}}, + {SetBoolArray, 1, 0, 5}, + {SetBoolArray, 1, 6, REGISTER_OUTPUT_SIZE, 8, + {0x3f800000, 0x3f800000, 0x00000000, 0x00000000, 0x3f800000, 0x3f800000, 0x3f800000}}, + {SetFloatArray, 0, 0, 5}, + {SetFloatArray, 0, 6, REGISTER_OUTPUT_SIZE, 8, + {0x40000123, 0x40800123, 0x40c00123, 0x00000000, 0x00000000, 0x40a00123, 0x40e00123}}, + {SetValue, 0, 0, 23}, + {SetValue, 0, 24, REGISTER_OUTPUT_SIZE * 4, 8, + {0x40000123, 0x40800123, 0x40c00123, 0x00000000, 0x00000000, 0x40a00123, 0x40e00123}}, + {SetVector}, + {SetVectorArray, 0, 0, 1}, + {SetVectorArray, 0, 2, REGISTER_OUTPUT_SIZE / 4, 8, + {0x40000123, 0x40c00123, 0x41200123, 0x00000000, 0x00000000, 0x40e00123, 0x41300123}}, + {SetMatrix, 0, 0, 0, 8, + {0x40000123, 0x40c00123, 0x41200123, 0x00000000, 0x00000000, 0x40e00123, 0x41300123}}, + {SetMatrixArray}, + {SetMatrixArray, 0, 1, REGISTER_OUTPUT_SIZE / 16, 8, + {0x40000123, 0x40c00123, 0x41200123, 0x00000000, 0x00000000, 0x40e00123, 0x41300123}}, + {SetMatrixTranspose, 0, 0, 0, 8, + {0x40000123, 0x00000000, 0x40800123, 0x00000000, 0x40c00123, 0x40e00123, 0x41000123}}, + {SetMatrixTransposeArray}, + {SetMatrixTransposeArray, 0, 1, REGISTER_OUTPUT_SIZE / 16, 8, + {0x40000123, 0x00000000, 0x40800123, 0x00000000, 0x40c00123, 0x40e00123, 0x41000123}}, + {SetMatrixPointerArray}, + {SetMatrixPointerArray, 0, 1, REGISTER_OUTPUT_SIZE / 16, 8, + {0x40000123, 0x40c00123, 0x41200123, 0x00000000, 0x00000000, 0x40e00123, 0x41300123}}, + {SetMatrixTransposePointerArray}, + {SetMatrixTransposePointerArray, 0, 1, REGISTER_OUTPUT_SIZE / 16, 8, + {0x40000123, 0x00000000, 0x40800123, 0x00000000, 0x40c00123, 0x40e00123, 0x41000123}}, +}; + +static const struct registerset_constants registerset_constants_column_int[] = +{ + {"cn", {"cn", D3DXRS_INT4, 0, 6, D3DXPC_MATRIX_COLUMNS, D3DXPT_INT, 3, 2, 1, 0, 24, NULL}, 70}, +}; + +static const struct registerset_test registerset_test_column_int[] = +{ + {SetInt}, + {SetBool}, + {SetFloat}, + {SetIntArray, 1, 0, 5}, + {SetIntArray, 1, 6, REGISTER_OUTPUT_SIZE, 8, + {0x00000002, 0x00000004, 0x00000000, 0x00000000, 0x00000003, 0x00000005, 0x00000007}}, + {SetBoolArray, 1, 0, 5}, + {SetBoolArray, 1, 6, REGISTER_OUTPUT_SIZE, 8, + {0x00000001, 0x00000001, 0x00000000, 0x00000000, 0x00000001, 0x00000001, 0x00000001}}, + {SetFloatArray, 0, 0, 5}, + {SetFloatArray, 0, 6, REGISTER_OUTPUT_SIZE, 8, + {0x00000002, 0x00000004, 0x00000006, 0x00000000, 0x00000000, 0x00000005, 0x00000007}}, + {SetValue, 1, 0, 23}, + {SetValue, 1, 24, REGISTER_OUTPUT_SIZE * 4, 8, + {0x00000002, 0x00000004, 0x00000000, 0x00000000, 0x00000003, 0x00000005, 0x00000007}}, + {SetVector}, + {SetVectorArray, 0, 0, 1}, + {SetVectorArray, 0, 2, REGISTER_OUTPUT_SIZE / 4, 8, + {0x00000002, 0x00000006, 0x0000000a, 0x00000000, 0x00000000, 0x00000007, 0x0000000b}}, + {SetMatrix, 0, 0, 0, 8, + {0x00000002, 0x00000006, 0x0000000a, 0x00000000, 0x00000000, 0x00000007, 0x0000000b}}, + {SetMatrixArray}, + {SetMatrixArray, 0, 1, REGISTER_OUTPUT_SIZE / 16, 8, + {0x00000002, 0x00000006, 0x0000000a, 0x00000000, 0x00000000, 0x00000007, 0x0000000b}}, + {SetMatrixTranspose, 0, 0, 0, 8, + {0x00000002, 0x00000000, 0x00000004, 0x00000000, 0x00000006, 0x00000007, 0x00000008}}, + {SetMatrixTransposeArray}, + {SetMatrixTransposeArray, 0, 1, REGISTER_OUTPUT_SIZE / 16, 8, + {0x00000002, 0x00000000, 0x00000004, 0x00000000, 0x00000006, 0x00000007, 0x00000008}}, + {SetMatrixPointerArray}, + {SetMatrixPointerArray, 0, 1, REGISTER_OUTPUT_SIZE / 16, 8, + {0x00000002, 0x00000006, 0x0000000a, 0x00000000, 0x00000000, 0x00000007, 0x0000000b}}, + {SetMatrixTransposePointerArray}, + {SetMatrixTransposePointerArray, 0, 1, REGISTER_OUTPUT_SIZE / 16, 8, + {0x00000002, 0x00000000, 0x00000004, 0x00000000, 0x00000006, 0x00000007, 0x00000008}}, +}; + +static const struct registerset_constants registerset_constants_column_bool[] = +{ + {"cb", {"cb", D3DXRS_BOOL, 0, 6, D3DXPC_MATRIX_COLUMNS, D3DXPT_BOOL, 3, 2, 1, 0, 24, NULL}, 37}, +}; + +static const struct registerset_test registerset_test_column_bool[] = +{ + {SetInt}, + {SetBool}, + {SetFloat}, + {SetIntArray, 1, 0, 5}, + {SetIntArray, 1, 6, REGISTER_OUTPUT_SIZE, 6, + {0x00000001, 0x00000001, 0x00000000, 0x00000001, 0x00000001, 0x00000001}}, + {SetBoolArray, 1, 0, 5}, + {SetBoolArray, 1, 6, REGISTER_OUTPUT_SIZE, 6, + {0x00000002, 0x00000004, 0x00000000, 0x00000003, 0x00000005, 0x00000007}}, + {SetFloatArray, 0, 0, 5}, + {SetFloatArray, 0, 6, REGISTER_OUTPUT_SIZE, 6, + {0x00000001, 0x00000001, 0x00000001, 0x00000000, 0x00000001, 0x00000001}}, + {SetValue, 1, 0, 23}, + {SetValue, 1, 24, REGISTER_OUTPUT_SIZE * 4, 6, + {0x00000002, 0x00000004, 0x00000000, 0x00000003, 0x00000005, 0x00000007}}, + {SetVector}, + {SetVectorArray, 0, 0, 1}, + {SetVectorArray, 0, 2, REGISTER_OUTPUT_SIZE / 4, 6, + {0x00000001, 0x00000001, 0x00000001, 0x00000000, 0x00000001, 0x00000001}}, + {SetMatrix, 0, 0, 0, 6, + {0x00000001, 0x00000001, 0x00000001, 0x00000000, 0x00000001, 0x00000001}}, + {SetMatrixArray}, + {SetMatrixArray, 0, 1, REGISTER_OUTPUT_SIZE / 16, 6, + {0x00000001, 0x00000001, 0x00000001, 0x00000000, 0x00000001, 0x00000001}}, + {SetMatrixTranspose, 0, 0, 0, 6, + {0x00000001, 0x00000000, 0x00000001, 0x00000001, 0x00000001, 0x00000001}}, + {SetMatrixTransposeArray}, + {SetMatrixTransposeArray, 0, 1, REGISTER_OUTPUT_SIZE / 4, 6, + {0x00000001, 0x00000000, 0x00000001, 0x00000001, 0x00000001, 0x00000001}}, + {SetMatrixPointerArray}, + {SetMatrixPointerArray, 0, 1, REGISTER_OUTPUT_SIZE / 16, 6, + {0x00000001, 0x00000001, 0x00000001, 0x00000000, 0x00000001, 0x00000001}}, + {SetMatrixTransposePointerArray}, + {SetMatrixTransposePointerArray, 0, 1, REGISTER_OUTPUT_SIZE / 16, 6, + {0x00000001, 0x00000000, 0x00000001, 0x00000001, 0x00000001, 0x00000001}}, +}; + +static const struct registerset_constants registerset_constants_column_int_float[] = +{ + {"cnf", {"cnf", D3DXRS_FLOAT4, 4, 2, D3DXPC_MATRIX_COLUMNS, D3DXPT_INT, 3, 2, 1, 0, 24, NULL}, 79}, +}; + +static const struct registerset_test registerset_test_column_int_float[] = +{ + {SetInt}, + {SetBool}, + {SetFloat}, + {SetIntArray, 1, 0, 5}, + {SetIntArray, 1, 6, REGISTER_OUTPUT_SIZE, 8, + {0x40000000, 0x40800000, 0x00000000, 0x00000000, 0x40400000, 0x40a00000, 0x40e00000}}, + {SetBoolArray, 1, 0, 5}, + {SetBoolArray, 1, 6, REGISTER_OUTPUT_SIZE, 8, + {0x3f800000, 0x3f800000, 0x00000000, 0x00000000, 0x3f800000, 0x3f800000, 0x3f800000}}, + {SetFloatArray, 0, 0, 5}, + {SetFloatArray, 0, 6, REGISTER_OUTPUT_SIZE, 8, + {0x40000000, 0x40800000, 0x40c00000, 0x00000000, 0x00000000, 0x40a00000, 0x40e00000}}, + {SetValue, 1, 0, 23}, + {SetValue, 1, 24, REGISTER_OUTPUT_SIZE * 4, 8, + {0x40000000, 0x40800000, 0x00000000, 0x00000000, 0x40400000, 0x40a00000, 0x40e00000}}, + {SetVector}, + {SetVectorArray, 0, 0, 1}, + {SetValue, 0, 0, 23}, + {SetVectorArray, 0, 2, REGISTER_OUTPUT_SIZE / 4, 8, + {0x40000000, 0x40c00000, 0x41200000, 0x00000000, 0x00000000, 0x40e00000, 0x41300000}}, + {SetMatrix, 0, 0, 0, 8, + {0x40000000, 0x40c00000, 0x41200000, 0x00000000, 0x00000000, 0x40e00000, 0x41300000}}, + {SetMatrixArray}, + {SetMatrixArray, 0, 1, REGISTER_OUTPUT_SIZE / 16, 8, + {0x40000000, 0x40c00000, 0x41200000, 0x00000000, 0x00000000, 0x40e00000, 0x41300000}}, + {SetMatrixTranspose, 0, 0, 0, 8, + {0x40000000, 0x00000000, 0x40800000, 0x00000000, 0x40c00000, 0x40e00000, 0x41000000}}, + {SetMatrixTransposeArray}, + {SetMatrixTransposeArray, 0, 1, REGISTER_OUTPUT_SIZE / 16, 8, + {0x40000000, 0x00000000, 0x40800000, 0x00000000, 0x40c00000, 0x40e00000, 0x41000000}}, + {SetMatrixPointerArray}, + {SetMatrixPointerArray, 0, 1, REGISTER_OUTPUT_SIZE / 16, 8, + {0x40000000, 0x40c00000, 0x41200000, 0x00000000, 0x00000000, 0x40e00000, 0x41300000}}, + {SetMatrixTransposePointerArray}, + {SetMatrixTransposePointerArray, 0, 1, REGISTER_OUTPUT_SIZE / 16, 8, + {0x40000000, 0x00000000, 0x40800000, 0x00000000, 0x40c00000, 0x40e00000, 0x41000000}}, +}; + +static const struct registerset_constants registerset_constants_column_bool_float[] = +{ + {"cbf", {"cbf", D3DXRS_FLOAT4, 2, 2, D3DXPC_MATRIX_COLUMNS, D3DXPT_BOOL, 3, 2, 1, 0, 24, NULL}, 44}, +}; + +static const struct registerset_test registerset_test_column_bool_float[] = +{ + {SetInt}, + {SetBool}, + {SetFloat}, + {SetIntArray, 1, 0, 5}, + {SetIntArray, 1, 6, REGISTER_OUTPUT_SIZE, 8, + {0x3f800000, 0x3f800000, 0x00000000, 0x00000000, 0x3f800000, 0x3f800000, 0x3f800000}}, + {SetBoolArray, 1, 0, 5}, + {SetBoolArray, 1, 6, REGISTER_OUTPUT_SIZE, 8, + {0x3f800000, 0x3f800000, 0x00000000, 0x00000000, 0x3f800000, 0x3f800000, 0x3f800000}}, + {SetFloatArray, 0, 0, 5}, + {SetFloatArray, 0, 6, REGISTER_OUTPUT_SIZE, 8, + {0x3f800000, 0x3f800000, 0x3f800000, 0x00000000, 0x00000000, 0x3f800000, 0x3f800000}}, + {SetValue, 1, 0, 23}, + {SetValue, 1, 24, REGISTER_OUTPUT_SIZE * 4, 8, + {0x3f800000, 0x3f800000, 0x00000000, 0x00000000, 0x3f800000, 0x3f800000, 0x3f800000}}, + {SetVector}, + {SetVectorArray, 0, 0, 1}, + {SetVectorArray, 0, 2, REGISTER_OUTPUT_SIZE / 4, 8, + {0x3f800000, 0x3f800000, 0x3f800000, 0x00000000, 0x00000000, 0x3f800000, 0x3f800000}}, + {SetMatrix, 0, 0, 0, 8, + {0x3f800000, 0x3f800000, 0x3f800000, 0x00000000, 0x00000000, 0x3f800000, 0x3f800000}}, + {SetMatrixArray}, + {SetMatrixArray, 0, 1, REGISTER_OUTPUT_SIZE / 16, 8, + {0x3f800000, 0x3f800000, 0x3f800000, 0x00000000, 0x00000000, 0x3f800000, 0x3f800000}}, + {SetMatrixTranspose, 0, 0, 0, 8, + {0x3f800000, 0x00000000, 0x3f800000, 0x00000000, 0x3f800000, 0x3f800000, 0x3f800000}}, + {SetMatrixTransposeArray}, + {SetMatrixTransposeArray, 0, 1, REGISTER_OUTPUT_SIZE / 16, 8, + {0x3f800000, 0x00000000, 0x3f800000, 0x00000000, 0x3f800000, 0x3f800000, 0x3f800000}}, + {SetMatrixPointerArray}, + {SetMatrixPointerArray, 0, 1, REGISTER_OUTPUT_SIZE / 16, 8, + {0x3f800000, 0x3f800000, 0x3f800000, 0x00000000, 0x00000000, 0x3f800000, 0x3f800000}}, + {SetMatrixTransposePointerArray}, + {SetMatrixTransposePointerArray, 0, 1, REGISTER_OUTPUT_SIZE / 16, 8, + {0x3f800000, 0x00000000, 0x3f800000, 0x00000000, 0x3f800000, 0x3f800000, 0x3f800000}}, +}; + +/* + * fxc.exe /Tvs_3_0 + */ +#if 0 +bool3x2 cab[2] = {1, 0, 1, 1, 0, 1, 1, 0, 1, 1, 0, 1}; +int3x2 can[2] = {14, 15, 16, 71, 18, 19, 55, 63, 96, 96, 97, 13}; +float3x2 caf[2] = {1.1, 2.2, 3.3, 4.4, 5.5, 6.6, 7.7, 8.8, 9.9, 1.2, 1.3, 1.4}; +bool3x2 cabf[2] = {1, 1, 0, 1, 0, 1, 1, 1, 0, 1, 0, 1}; +int3x2 canf[2] = {300, 301, 303, 302, 304, 306, 350, 365, 654, 612, 326, 999}; +float4 main(float4 pos : POSITION) : POSITION +{ + float4 tmp = 0; + int i; + if (cab[1]._32) for (i = 0; i < can[1]._31; i++) tmp.x += pos.z * caf[1]._31 * cabf[1]._32; + else for (i = 0; i < can[1]._32; i++) tmp.y += pos.y * caf[1]._32 * canf[1]._32; + return tmp; +} +#endif +static const DWORD registerset_blob_column_array[] = +{ +0xfffe0300, 0x0096fffe, 0x42415443, 0x0000001c, 0x00000223, 0xfffe0300, 0x00000005, 0x0000001c, +0x00000100, 0x0000021c, 0x00000080, 0x00000000, 0x0000000c, 0x00000084, 0x00000094, 0x000000c4, +0x00040002, 0x00000004, 0x000000cc, 0x000000dc, 0x0000011c, 0x00000002, 0x00000004, 0x00000120, +0x00000130, 0x00000170, 0x00000001, 0x0000000c, 0x00000174, 0x00000184, 0x000001c4, 0x00080002, +0x00000004, 0x000001cc, 0x000001dc, 0x00626163, 0x00010003, 0x00020003, 0x00000002, 0x00000000, +0xffffffff, 0x00000000, 0xffffffff, 0xffffffff, 0x00000000, 0xffffffff, 0xffffffff, 0x00000000, +0xffffffff, 0xffffffff, 0x00000000, 0xffffffff, 0x66626163, 0xababab00, 0x00010003, 0x00020003, +0x00000002, 0x00000000, 0x3f800000, 0x00000000, 0x00000000, 0x00000000, 0x3f800000, 0x3f800000, +0x3f800000, 0x00000000, 0x3f800000, 0x00000000, 0x00000000, 0x00000000, 0x3f800000, 0x3f800000, +0x3f800000, 0x00000000, 0x00666163, 0x00030003, 0x00020003, 0x00000002, 0x00000000, 0x3f8ccccd, +0x40533333, 0x40b00000, 0x00000000, 0x400ccccd, 0x408ccccd, 0x40d33333, 0x00000000, 0x40f66666, +0x411e6666, 0x3fa66666, 0x00000000, 0x410ccccd, 0x3f99999a, 0x3fb33333, 0x00000000, 0x006e6163, +0x00020003, 0x00020003, 0x00000002, 0x00000000, 0x0000000e, 0x00000010, 0x00000012, 0x00000000, +0x0000000f, 0x00000047, 0x00000013, 0x00000000, 0x00000037, 0x00000060, 0x00000061, 0x00000000, +0x0000003f, 0x00000060, 0x0000000d, 0x00000000, 0x666e6163, 0xababab00, 0x00020003, 0x00020003, +0x00000002, 0x00000000, 0x43960000, 0x43978000, 0x43980000, 0x00000000, 0x43968000, 0x43970000, +0x43990000, 0x00000000, 0x43af0000, 0x44238000, 0x43a30000, 0x00000000, 0x43b68000, 0x44190000, +0x4479c000, 0x00000000, 0x335f7376, 0x4d00305f, 0x6f726369, 0x74666f73, 0x29522820, 0x534c4820, +0x6853204c, 0x72656461, 0x6d6f4320, 0x656c6970, 0x2e392072, 0x392e3932, 0x332e3235, 0x00313131, +0x05000051, 0xa00f000c, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x0200001f, 0x80000000, +0x900f0000, 0x0200001f, 0x80000000, 0xe00f0000, 0x01000028, 0xe0e4080b, 0x03000005, 0x80010000, +0xa0aa0002, 0x90aa0000, 0x02000001, 0x80010001, 0xa000000c, 0x01000026, 0xf0e4000a, 0x04000004, +0x80010001, 0x80000000, 0xa0aa0007, 0x80000001, 0x00000027, 0x02000001, 0x80020001, 0xa000000c, +0x0000002a, 0x03000005, 0x80010000, 0xa0aa0003, 0x90550000, 0x02000001, 0x80020001, 0xa000000c, +0x01000026, 0xf0e4000b, 0x04000004, 0x80020001, 0x80000000, 0xa0aa000b, 0x80550001, 0x00000027, +0x02000001, 0x80010001, 0xa000000c, 0x0000002b, 0x02000001, 0xe0030000, 0x80e40001, 0x02000001, +0xe00c0000, 0xa000000c, 0x0000ffff, +}; + +static const struct registerset_constants registerset_constants_column_array_float[] = +{ + {"caf", {"caf", D3DXRS_FLOAT4, 0, 4, D3DXPC_MATRIX_COLUMNS, D3DXPT_FLOAT, 3, 2, 2, 0, 48, NULL}, 76}, + {"caf[0]", {"caf", D3DXRS_FLOAT4, 0, 2, D3DXPC_MATRIX_COLUMNS, D3DXPT_FLOAT, 3, 2, 1, 0, 24, NULL}, 76}, + {"caf[1]", {"caf", D3DXRS_FLOAT4, 2, 2, D3DXPC_MATRIX_COLUMNS, D3DXPT_FLOAT, 3, 2, 1, 0, 24, NULL}, 84}, +}; + +static const struct registerset_test registerset_test_column_array_float[] = +{ + {SetInt}, + {SetBool}, + {SetFloat}, + {SetIntArray, 1, 0, 5}, + {SetIntArray, 1, 6, 11, 8, + {0x40000000, 0x40800000, 0x00000000, 0x00000000, 0x40400000, 0x40a00000, 0x40e00000}}, + {SetIntArray, 1, 12, REGISTER_OUTPUT_SIZE, 16, + {0x40000000, 0x40800000, 0x00000000, 0x00000000, 0x40400000, 0x40a00000, 0x40e00000, 0x00000000, + 0x41000000, 0x41200000, 0x41400000, 0x00000000, 0x41100000, 0x41300000, 0x41500000}}, + {SetBoolArray, 1, 0, 5}, + {SetBoolArray, 1, 6, 11, 8, + {0x3f800000, 0x3f800000, 0x00000000, 0x00000000, 0x3f800000, 0x3f800000, 0x3f800000}}, + {SetBoolArray, 1, 12, REGISTER_OUTPUT_SIZE, 16, + {0x3f800000, 0x3f800000, 0x00000000, 0x00000000, 0x3f800000, 0x3f800000, 0x3f800000, 0x00000000, + 0x3f800000, 0x3f800000, 0x3f800000, 0x00000000, 0x3f800000, 0x3f800000, 0x3f800000}}, + {SetFloatArray, 0, 0, 5}, + {SetFloatArray, 0, 6, 11, 8, + {0x40000123, 0x40800123, 0x40c00123, 0x00000000, 0x00000000, 0x40a00123, 0x40e00123}}, + {SetFloatArray, 0, 12, REGISTER_OUTPUT_SIZE, 16, + {0x40000123, 0x40800123, 0x40c00123, 0x00000000, 0x00000000, 0x40a00123, 0x40e00123, 0x00000000, + 0x41000123, 0x41200123, 0x41400123, 0x00000000, 0x41100123, 0x41300123, 0x41500123}}, + {SetValue, 0, 0, 23}, + {SetValue, 0, 24, 47, 8, + {0x40000123, 0x40800123, 0x40c00123, 0x00000000, 0x00000000, 0x40a00123, 0x40e00123}}, + {SetValue, 0, 48, REGISTER_OUTPUT_SIZE * 4, 16, + {0x40000123, 0x40800123, 0x40c00123, 0x00000000, 0x00000000, 0x40a00123, 0x40e00123, 0x00000000, + 0x41000123, 0x41200123, 0x41400123, 0x00000000, 0x41100123, 0x41300123, 0x41500123}}, + {SetVector}, + {SetVectorArray, 0, 0, 1}, + {SetVectorArray, 0, 2, 3, 8, + {0x40000123, 0x40c00123, 0x41200123, 0x00000000, 0x00000000, 0x40e00123, 0x41300123}}, + {SetVectorArray, 0, 4, REGISTER_OUTPUT_SIZE / 4, 16, + {0x40000123, 0x40c00123, 0x41200123, 0x00000000, 0x00000000, 0x40e00123, 0x41300123, 0x00000000, + 0x41600123, 0x41a00123, 0x00000000, 0x00000000, 0x41700123, 0x41b00123, 0x41f00123}}, + {SetMatrix, 0, 0, 0, 8, + {0x40000123, 0x40c00123, 0x41200123, 0x00000000, 0x00000000, 0x40e00123, 0x41300123}}, + {SetMatrixArray}, + {SetMatrixArray, 0, 1, 1, 8, + {0x40000123, 0x40c00123, 0x41200123, 0x00000000, 0x00000000, 0x40e00123, 0x41300123}}, + {SetMatrixArray, 0, 2, REGISTER_OUTPUT_SIZE / 16, 16, + {0x40000123, 0x40c00123, 0x41200123, 0x00000000, 0x00000000, 0x40e00123, 0x41300123, 0x00000000, + 0x41a00123, 0x00000000, 0x00000000, 0x00000000, 0x41b00123, 0x41f00123, 0x42300123}}, + {SetMatrixTranspose, 0, 0, 0, 8, + {0x40000123, 0x00000000, 0x40800123, 0x00000000, 0x40c00123, 0x40e00123, 0x41000123}}, + {SetMatrixTransposeArray}, + {SetMatrixTransposeArray, 0, 1, 1, 8, + {0x40000123, 0x00000000, 0x40800123, 0x00000000, 0x40c00123, 0x40e00123, 0x41000123}}, + {SetMatrixTransposeArray, 0, 2, REGISTER_OUTPUT_SIZE / 16, 16, + {0x40000123, 0x00000000, 0x40800123, 0x00000000, 0x40c00123, 0x40e00123, 0x41000123, 0x00000000, + 0x41a00123, 0x41b00123, 0x41c00123, 0x00000000, 0x00000000, 0x41f00123, 0x42000123}}, + {SetMatrixPointerArray}, + {SetMatrixPointerArray, 0, 1, 1, 8, + {0x40000123, 0x40c00123, 0x41200123, 0x00000000, 0x00000000, 0x40e00123, 0x41300123}}, + {SetMatrixPointerArray, 0, 2, REGISTER_OUTPUT_SIZE / 16, 16, + {0x40000123, 0x40c00123, 0x41200123, 0x00000000, 0x00000000, 0x40e00123, 0x41300123, 0x00000000, + 0x41900123, 0x41d00123, 0x42100123, 0x00000000, 0x41a00123, 0x00000000, 0x00000000}}, + {SetMatrixTransposePointerArray}, + {SetMatrixTransposePointerArray, 0, 1, 1, 8, + {0x40000123, 0x00000000, 0x40800123, 0x00000000, 0x40c00123, 0x40e00123, 0x41000123}}, + {SetMatrixTransposePointerArray, 0, 2, REGISTER_OUTPUT_SIZE / 16, 16, + {0x40000123, 0x00000000, 0x40800123, 0x00000000, 0x40c00123, 0x40e00123, 0x41000123, 0x00000000, + 0x41900123, 0x41a00123, 0x41b00123, 0x00000000, 0x41d00123, 0x00000000, 0x41f00123}}, +}; + +static const struct registerset_constants registerset_constants_column_array_int[] = +{ + {"can", {"can", D3DXRS_INT4, 0, 12, D3DXPC_MATRIX_COLUMNS, D3DXPT_INT, 3, 2, 2, 0, 48, NULL}, 97}, + {"can[0]", {"can", D3DXRS_INT4, 0, 2, D3DXPC_MATRIX_COLUMNS, D3DXPT_INT, 3, 2, 1, 0, 24, NULL}, 97}, + {"can[1]", {"can", D3DXRS_INT4, 2, 2, D3DXPC_MATRIX_COLUMNS, D3DXPT_INT, 3, 2, 1, 0, 24, NULL}, 105}, +}; + +static const struct registerset_test registerset_test_column_array_int[] = +{ + {SetInt}, + {SetBool}, + {SetFloat}, + {SetIntArray, 1, 0, 5}, + {SetIntArray, 1, 6, 11, 8, + {0x00000002, 0x00000004, 0x00000000, 0x00000000, 0x00000003, 0x00000005, 0x00000007}}, + {SetIntArray, 1, 12, REGISTER_OUTPUT_SIZE, 16, + {0x00000002, 0x00000004, 0x00000000, 0x00000000, 0x00000003, 0x00000005, 0x00000007, 0x00000000, + 0x00000008, 0x0000000a, 0x0000000c, 0x00000000, 0x00000009, 0x0000000b, 0x0000000d}}, + {SetBoolArray, 1, 0, 5}, + {SetBoolArray, 1, 6, 11, 8, + {0x00000001, 0x00000001, 0x00000000, 0x00000000, 0x00000001, 0x00000001, 0x00000001}}, + {SetBoolArray, 1, 12, REGISTER_OUTPUT_SIZE, 16, + {0x00000001, 0x00000001, 0x00000000, 0x00000000, 0x00000001, 0x00000001, 0x00000001, 0x00000000, + 0x00000001, 0x00000001, 0x00000001, 0x00000000, 0x00000001, 0x00000001, 0x00000001}}, + {SetFloatArray, 0, 0, 5}, + {SetFloatArray, 0, 6, 11, 8, + {0x00000002, 0x00000004, 0x00000006, 0x00000000, 0x00000000, 0x00000005, 0x00000007}}, + {SetFloatArray, 0, 12, REGISTER_OUTPUT_SIZE, 16, + {0x00000002, 0x00000004, 0x00000006, 0x00000000, 0x00000000, 0x00000005, 0x00000007, 0x00000000, + 0x00000008, 0x0000000a, 0x0000000c, 0x00000000, 0x00000009, 0x0000000b, 0x0000000d}}, + {SetValue, 1, 0, 23}, + {SetValue, 1, 24, 47, 8, + {0x00000002, 0x00000004, 0x00000000, 0x00000000, 0x00000003, 0x00000005, 0x00000007}}, + {SetValue, 1, 48, REGISTER_OUTPUT_SIZE * 4, 16, + {0x00000002, 0x00000004, 0x00000000, 0x00000000, 0x00000003, 0x00000005, 0x00000007, 0x00000000, + 0x00000008, 0x0000000a, 0x0000000c, 0x00000000, 0x00000009, 0x0000000b, 0x0000000d}}, + {SetVector}, + {SetVectorArray, 0, 0, 1}, + {SetVectorArray, 0, 2, 3, 8, + {0x00000002, 0x00000006, 0x0000000a, 0x00000000, 0x00000000, 0x00000007, 0x0000000b}}, + {SetVectorArray, 0, 4, REGISTER_OUTPUT_SIZE / 4, 16, + {0x00000002, 0x00000006, 0x0000000a, 0x00000000, 0x00000000, 0x00000007, 0x0000000b, 0x00000000, + 0x0000000e, 0x00000014, 0x00000000, 0x00000000, 0x0000000f, 0x00000016, 0x0000001e}}, + {SetMatrix, 0, 0, 0, 8, + {0x00000002, 0x00000006, 0x0000000a, 0x00000000, 0x00000000, 0x00000007, 0x0000000b}}, + {SetMatrixArray}, + {SetMatrixArray, 0, 1, 1, 8, + {0x00000002, 0x00000006, 0x0000000a, 0x00000000, 0x00000000, 0x00000007, 0x0000000b}}, + {SetMatrixArray, 0, 2, REGISTER_OUTPUT_SIZE / 16, 16, + {0x00000002, 0x00000006, 0x0000000a, 0x00000000, 0x00000000, 0x00000007, 0x0000000b, 0x00000000, + 0x00000014, 0x00000000, 0x00000000, 0x00000000, 0x00000016, 0x0000001e, 0x0000002c}}, + {SetMatrixTranspose, 0, 0, 0, 8, + {0x00000002, 0x00000000, 0x00000004, 0x00000000, 0x00000006, 0x00000007, 0x00000008}}, + {SetMatrixTransposeArray}, + {SetMatrixTransposeArray, 0, 1, 1, 8, + {0x00000002, 0x00000000, 0x00000004, 0x00000000, 0x00000006, 0x00000007, 0x00000008}}, + {SetMatrixTransposeArray, 0, 2, REGISTER_OUTPUT_SIZE / 16, 16, + {0x00000002, 0x00000000, 0x00000004, 0x00000000, 0x00000006, 0x00000007, 0x00000008, 0x00000000, + 0x00000014, 0x00000016, 0x00000018, 0x00000000, 0x00000000, 0x0000001e, 0x00000020}}, + {SetMatrixPointerArray}, + {SetMatrixPointerArray, 0, 1, 1, 8, + {0x00000002, 0x00000006, 0x0000000a, 0x00000000, 0x00000000, 0x00000007, 0x0000000b}}, + {SetMatrixPointerArray, 0, 2, REGISTER_OUTPUT_SIZE / 16, 16, + {0x00000002, 0x00000006, 0x0000000a, 0x00000000, 0x00000000, 0x00000007, 0x0000000b, 0x00000000, + 0x00000012, 0x0000001a, 0x00000024, 0x00000000, 0x00000014, 0x00000000, 0x00000000}}, + {SetMatrixTransposePointerArray}, + {SetMatrixTransposePointerArray, 0, 1, 1, 8, + {0x00000002, 0x00000000, 0x00000004, 0x00000000, 0x00000006, 0x00000007, 0x00000008}}, + {SetMatrixTransposePointerArray, 0, 2, REGISTER_OUTPUT_SIZE / 16, 16, + {0x00000002, 0x00000000, 0x00000004, 0x00000000, 0x00000006, 0x00000007, 0x00000008, 0x00000000, + 0x00000012, 0x00000014, 0x00000016, 0x00000000, 0x0000001a, 0x00000000, 0x0000001e}}, +}; + +static const struct registerset_constants registerset_constants_column_array_bool[] = +{ + {"cab", {"cab", D3DXRS_BOOL, 0, 12, D3DXPC_MATRIX_COLUMNS, D3DXPT_BOOL, 3, 2, 2, 0, 48, NULL}, 37}, + {"cab[0]", {"cab", D3DXRS_BOOL, 0, 6, D3DXPC_MATRIX_COLUMNS, D3DXPT_BOOL, 3, 2, 1, 0, 24, NULL}, 37}, + {"cab[1]", {"cab", D3DXRS_BOOL, 6, 6, D3DXPC_MATRIX_COLUMNS, D3DXPT_BOOL, 3, 2, 1, 0, 24, NULL}, 43}, +}; + +static const struct registerset_test registerset_test_column_array_bool[] = +{ + {SetInt}, + {SetBool}, + {SetFloat}, + {SetIntArray, 1, 0, 5}, + {SetIntArray, 1, 6, 11, 6, + {0x00000001, 0x00000001, 0x00000000, 0x00000001, 0x00000001, 0x00000001}}, + {SetIntArray, 1, 12, REGISTER_OUTPUT_SIZE, 12, + {0x00000001, 0x00000001, 0x00000000, 0x00000001, 0x00000001, 0x00000001, 0x00000001, 0x00000001, + 0x00000001, 0x00000001, 0x00000001, 0x00000001}}, + {SetBoolArray, 1, 0, 5}, + {SetBoolArray, 1, 6, 11, 6, + {0x00000002, 0x00000004, 0x00000000, 0x00000003, 0x00000005, 0x00000007}}, + {SetBoolArray, 1, 12, REGISTER_OUTPUT_SIZE, 12, + {0x00000002, 0x00000004, 0x00000000, 0x00000003, 0x00000005, 0x00000007, 0x00000008, 0x0000000a, + 0x0000000c, 0x00000009, 0x0000000b, 0x0000000d}}, + {SetFloatArray, 0, 0, 5}, + {SetFloatArray, 0, 6, 11, 6, + {0x00000001, 0x00000001, 0x00000001, 0x00000000, 0x00000001, 0x00000001}}, + {SetFloatArray, 0, 12, REGISTER_OUTPUT_SIZE, 12, + {0x00000001, 0x00000001, 0x00000001, 0x00000000, 0x00000001, 0x00000001, 0x00000001, 0x00000001, + 0x00000001, 0x00000001, 0x00000001, 0x00000001}}, + {SetValue, 1, 0, 23}, + {SetValue, 1, 24, 47, 6, + {0x00000002, 0x00000004, 0x00000000, 0x00000003, 0x00000005, 0x00000007}}, + {SetValue, 1, 48, REGISTER_OUTPUT_SIZE * 4, 12, + {0x00000002, 0x00000004, 0x00000000, 0x00000003, 0x00000005, 0x00000007, 0x00000008, 0x0000000a, + 0x0000000c, 0x00000009, 0x0000000b, 0x0000000d}}, + {SetVector}, + {SetVectorArray, 0, 0, 1}, + {SetVectorArray, 0, 2, 3, 6, + {0x00000001, 0x00000001, 0x00000001, 0x00000000, 0x00000001, 0x00000001}}, + {SetVectorArray, 0, 4, REGISTER_OUTPUT_SIZE / 4, 12, + {0x00000001, 0x00000001, 0x00000001, 0x00000000, 0x00000001, 0x00000001, 0x00000001, 0x00000001, + 0x00000000, 0x00000001, 0x00000001, 0x00000001}}, + {SetMatrix, 0, 0, 0, 6, + {0x00000001, 0x00000001, 0x00000001, 0x00000000, 0x00000001, 0x00000001}}, + {SetMatrixArray}, + {SetMatrixArray, 0, 1, 1, 6, + {0x00000001, 0x00000001, 0x00000001, 0x00000000, 0x00000001, 0x00000001}}, + {SetMatrixArray, 0, 2, REGISTER_OUTPUT_SIZE / 16, 12, + {0x00000001, 0x00000001, 0x00000001, 0x00000000, 0x00000001, 0x00000001, 0x00000001, 0x00000000, + 0x00000000, 0x00000001, 0x00000001, 0x00000001}}, + {SetMatrixTranspose, 0, 0, 0, 6, + {0x00000001, 0x00000000, 0x00000001, 0x00000001, 0x00000001, 0x00000001}}, + {SetMatrixTransposeArray}, + {SetMatrixTransposeArray, 0, 1, 1, 6, + {0x00000001, 0x00000000, 0x00000001, 0x00000001, 0x00000001, 0x00000001}}, + {SetMatrixTransposeArray, 0, 2, REGISTER_OUTPUT_SIZE / 16, 12, + {0x00000001, 0x00000000, 0x00000001, 0x00000001, 0x00000001, 0x00000001, 0x00000001, 0x00000001, + 0x00000001, 0x00000000, 0x00000001, 0x00000001}}, + {SetMatrixPointerArray}, + {SetMatrixPointerArray, 0, 1, 1, 6, + {0x00000001, 0x00000001, 0x00000001, 0x00000000, 0x00000001, 0x00000001}}, + {SetMatrixPointerArray, 0, 2, REGISTER_OUTPUT_SIZE / 16, 12, + {0x00000001, 0x00000001, 0x00000001, 0x00000000, 0x00000001, 0x00000001, 0x00000001, 0x00000001, + 0x00000001, 0x00000001, 0x00000000, 0x00000000}}, + {SetMatrixTransposePointerArray}, + {SetMatrixTransposePointerArray, 0, 1, 1, 6, + {0x00000001, 0x00000000, 0x00000001, 0x00000001, 0x00000001, 0x00000001}}, + {SetMatrixTransposePointerArray, 0, 2, REGISTER_OUTPUT_SIZE / 16, 12, + {0x00000001, 0x00000000, 0x00000001, 0x00000001, 0x00000001, 0x00000001, 0x00000001, 0x00000001, + 0x00000001, 0x00000001, 0x00000000, 0x00000001}}, +}; + +static const struct registerset_constants registerset_constants_column_array_int_float[] = +{ + {"canf", {"canf", D3DXRS_FLOAT4, 8, 4, D3DXPC_MATRIX_COLUMNS, D3DXPT_INT, 3, 2, 2, 0, 48, NULL}, 119}, + {"canf[0]", {"canf", D3DXRS_FLOAT4, 8, 2, D3DXPC_MATRIX_COLUMNS, D3DXPT_INT, 3, 2, 1, 0, 24, NULL}, 119}, + {"canf[1]", {"canf", D3DXRS_FLOAT4, 10, 2, D3DXPC_MATRIX_COLUMNS, D3DXPT_INT, 3, 2, 1, 0, 24, NULL}, 127}, +}; + +static const struct registerset_test registerset_test_column_array_int_float[] = +{ + {SetInt}, + {SetBool}, + {SetFloat}, + {SetIntArray, 1, 0, 5}, + {SetIntArray, 1, 6, 11, 8, + {0x40000000, 0x40800000, 0x00000000, 0x00000000, 0x40400000, 0x40a00000, 0x40e00000}}, + {SetIntArray, 1, 12, REGISTER_OUTPUT_SIZE, 16, + {0x40000000, 0x40800000, 0x00000000, 0x00000000, 0x40400000, 0x40a00000, 0x40e00000, 0x00000000, + 0x41000000, 0x41200000, 0x41400000, 0x00000000, 0x41100000, 0x41300000, 0x41500000}}, + {SetBoolArray, 1, 0, 5}, + {SetBoolArray, 1, 6, 11, 8, + {0x3f800000, 0x3f800000, 0x00000000, 0x00000000, 0x3f800000, 0x3f800000, 0x3f800000}}, + {SetBoolArray, 1, 12, REGISTER_OUTPUT_SIZE, 16, + {0x3f800000, 0x3f800000, 0x00000000, 0x00000000, 0x3f800000, 0x3f800000, 0x3f800000, 0x00000000, + 0x3f800000, 0x3f800000, 0x3f800000, 0x00000000, 0x3f800000, 0x3f800000, 0x3f800000}}, + {SetFloatArray, 0, 0, 5}, + {SetFloatArray, 0, 6, 11, 8, + {0x40000000, 0x40800000, 0x40c00000, 0x00000000, 0x00000000, 0x40a00000, 0x40e00000}}, + {SetFloatArray, 0, 12, REGISTER_OUTPUT_SIZE, 16, + {0x40000000, 0x40800000, 0x40c00000, 0x00000000, 0x00000000, 0x40a00000, 0x40e00000, 0x00000000, + 0x41000000, 0x41200000, 0x41400000, 0x00000000, 0x41100000, 0x41300000, 0x41500000}}, + {SetValue, 1, 0, 23}, + {SetValue, 1, 24, 47, 8, + {0x40000000, 0x40800000, 0x00000000, 0x00000000, 0x40400000, 0x40a00000, 0x40e00000}}, + {SetValue, 1, 48, REGISTER_OUTPUT_SIZE * 4, 16, + {0x40000000, 0x40800000, 0x00000000, 0x00000000, 0x40400000, 0x40a00000, 0x40e00000, 0x00000000, + 0x41000000, 0x41200000, 0x41400000, 0x00000000, 0x41100000, 0x41300000, 0x41500000}}, + {SetVector}, + {SetVectorArray, 0, 0, 1},/*16*/ + {SetVectorArray, 0, 2, 3, 8, + {0x40000000, 0x40c00000, 0x41200000, 0x00000000, 0x00000000, 0x40e00000, 0x41300000}}, + {SetVectorArray, 0, 4, REGISTER_OUTPUT_SIZE / 4, 16, + {0x40000000, 0x40c00000, 0x41200000, 0x00000000, 0x00000000, 0x40e00000, 0x41300000, 0x00000000, + 0x41600000, 0x41a00000, 0x00000000, 0x00000000, 0x41700000, 0x41b00000, 0x41f00000}}, + {SetMatrix, 0, 0, 0, 8, + {0x40000000, 0x40c00000, 0x41200000, 0x00000000, 0x00000000, 0x40e00000, 0x41300000}}, + {SetMatrixArray}, + {SetMatrixArray, 0, 1, 1, 8, + {0x40000000, 0x40c00000, 0x41200000, 0x00000000, 0x00000000, 0x40e00000, 0x41300000}}, + {SetMatrixArray, 0, 2, REGISTER_OUTPUT_SIZE / 16, 16, + {0x40000000, 0x40c00000, 0x41200000, 0x00000000, 0x00000000, 0x40e00000, 0x41300000, 0x00000000, + 0x41a00000, 0x00000000, 0x00000000, 0x00000000, 0x41b00000, 0x41f00000, 0x42300000}}, + {SetMatrixTranspose, 0, 0, 0, 8, + {0x40000000, 0x00000000, 0x40800000, 0x00000000, 0x40c00000, 0x40e00000, 0x41000000}}, + {SetMatrixTransposeArray}, + {SetMatrixTransposeArray, 0, 1, 1, 8, + {0x40000000, 0x00000000, 0x40800000, 0x00000000, 0x40c00000, 0x40e00000, 0x41000000}}, + {SetMatrixTransposeArray, 0, 2, REGISTER_OUTPUT_SIZE / 16, 16, + {0x40000000, 0x00000000, 0x40800000, 0x00000000, 0x40c00000, 0x40e00000, 0x41000000, 0x00000000, + 0x41a00000, 0x41b00000, 0x41c00000, 0x00000000, 0x00000000, 0x41f00000, 0x42000000}}, + {SetMatrixPointerArray}, + {SetMatrixPointerArray, 0, 1, 1, 8, + {0x40000000, 0x40c00000, 0x41200000, 0x00000000, 0x00000000, 0x40e00000, 0x41300000}}, + {SetMatrixPointerArray, 0, 2, REGISTER_OUTPUT_SIZE / 16, 16, + {0x40000000, 0x40c00000, 0x41200000, 0x00000000, 0x00000000, 0x40e00000, 0x41300000, 0x00000000, + 0x41900000, 0x41d00000, 0x42100000, 0x00000000, 0x41a00000, 0x00000000, 0x00000000}}, + {SetMatrixTransposePointerArray}, + {SetMatrixTransposePointerArray, 0, 1, 1, 8, + {0x40000000, 0x00000000, 0x40800000, 0x00000000, 0x40c00000, 0x40e00000, 0x41000000}}, + {SetMatrixTransposePointerArray, 0, 2, REGISTER_OUTPUT_SIZE / 16, 16, + {0x40000000, 0x00000000, 0x40800000, 0x00000000, 0x40c00000, 0x40e00000, 0x41000000, 0x00000000, + 0x41900000, 0x41a00000, 0x41b00000, 0x00000000, 0x41d00000, 0x00000000, 0x41f00000}}, +}; + +static const struct registerset_constants registerset_constants_column_array_bool_float[] = +{ + {"cabf", {"cabf", D3DXRS_FLOAT4, 4, 4, D3DXPC_MATRIX_COLUMNS, D3DXPT_BOOL, 3, 2, 2, 0, 48, NULL}, 55}, + {"cabf[0]", {"cabf", D3DXRS_FLOAT4, 4, 2, D3DXPC_MATRIX_COLUMNS, D3DXPT_BOOL, 3, 2, 1, 0, 24, NULL}, 55}, + {"cabf[1]", {"cabf", D3DXRS_FLOAT4, 6, 2, D3DXPC_MATRIX_COLUMNS, D3DXPT_BOOL, 3, 2, 1, 0, 24, NULL}, 63}, +}; + +static const struct registerset_test registerset_test_column_array_bool_float[] = +{ + {SetInt}, + {SetBool}, + {SetFloat}, + {SetIntArray, 1, 0, 5}, + {SetIntArray, 1, 6, 11, 8, + {0x3f800000, 0x3f800000, 0x00000000, 0x00000000, 0x3f800000, 0x3f800000, 0x3f800000}}, + {SetIntArray, 1, 12, REGISTER_OUTPUT_SIZE, 16, + {0x3f800000, 0x3f800000, 0x00000000, 0x00000000, 0x3f800000, 0x3f800000, 0x3f800000, 0x00000000, + 0x3f800000, 0x3f800000, 0x3f800000, 0x00000000, 0x3f800000, 0x3f800000, 0x3f800000}}, + {SetBoolArray, 1, 0, 5}, + {SetBoolArray, 1, 6, 11, 8, + {0x3f800000, 0x3f800000, 0x00000000, 0x00000000, 0x3f800000, 0x3f800000, 0x3f800000}}, + {SetBoolArray, 1, 12, REGISTER_OUTPUT_SIZE, 16, + {0x3f800000, 0x3f800000, 0x00000000, 0x00000000, 0x3f800000, 0x3f800000, 0x3f800000, 0x00000000, + 0x3f800000, 0x3f800000, 0x3f800000, 0x00000000, 0x3f800000, 0x3f800000, 0x3f800000}}, + {SetFloatArray, 0, 0, 5}, + {SetFloatArray, 0, 6, 11, 8, + {0x3f800000, 0x3f800000, 0x3f800000, 0x00000000, 0x00000000, 0x3f800000, 0x3f800000}}, + {SetFloatArray, 0, 12, REGISTER_OUTPUT_SIZE, 16, + {0x3f800000, 0x3f800000, 0x3f800000, 0x00000000, 0x00000000, 0x3f800000, 0x3f800000, 0x00000000, + 0x3f800000, 0x3f800000, 0x3f800000, 0x00000000, 0x3f800000, 0x3f800000, 0x3f800000}}, + {SetValue, 1, 0, 23}, + {SetValue, 1, 24, 47, 8, + {0x3f800000, 0x3f800000, 0x00000000, 0x00000000, 0x3f800000, 0x3f800000, 0x3f800000}}, + {SetValue, 1, 48, REGISTER_OUTPUT_SIZE * 4, 16, + {0x3f800000, 0x3f800000, 0x00000000, 0x00000000, 0x3f800000, 0x3f800000, 0x3f800000, 0x00000000, + 0x3f800000, 0x3f800000, 0x3f800000, 0x00000000, 0x3f800000, 0x3f800000, 0x3f800000}}, + {SetVector}, + {SetVectorArray, 0, 0, 1}, + {SetVectorArray, 0, 2, 3, 8, + {0x3f800000, 0x3f800000, 0x3f800000, 0x00000000, 0x00000000, 0x3f800000, 0x3f800000}}, + {SetVectorArray, 0, 4, REGISTER_OUTPUT_SIZE / 4, 16, + {0x3f800000, 0x3f800000, 0x3f800000, 0x00000000, 0x00000000, 0x3f800000, 0x3f800000, 0x00000000, + 0x3f800000, 0x3f800000, 0x00000000, 0x00000000, 0x3f800000, 0x3f800000, 0x3f800000}}, + {SetMatrix, 0, 0, 0, 8, + {0x3f800000, 0x3f800000, 0x3f800000, 0x00000000, 0x00000000, 0x3f800000, 0x3f800000}}, + {SetMatrixArray}, + {SetMatrixArray, 0, 1, 1, 8, + {0x3f800000, 0x3f800000, 0x3f800000, 0x00000000, 0x00000000, 0x3f800000, 0x3f800000}}, + {SetMatrixArray, 0, 2, REGISTER_OUTPUT_SIZE / 16, 16, + {0x3f800000, 0x3f800000, 0x3f800000, 0x00000000, 0x00000000, 0x3f800000, 0x3f800000, 0x00000000, + 0x3f800000, 0x00000000, 0x00000000, 0x00000000, 0x3f800000, 0x3f800000, 0x3f800000}}, + {SetMatrixTranspose, 0, 0, 0, 8, + {0x3f800000, 0x00000000, 0x3f800000, 0x00000000, 0x3f800000, 0x3f800000, 0x3f800000}}, + {SetMatrixTransposeArray}, + {SetMatrixTransposeArray, 0, 1, 1, 8, + {0x3f800000, 0x00000000, 0x3f800000, 0x00000000, 0x3f800000, 0x3f800000, 0x3f800000}}, + {SetMatrixTransposeArray, 0, 2, REGISTER_OUTPUT_SIZE / 16, 16, + {0x3f800000, 0x00000000, 0x3f800000, 0x00000000, 0x3f800000, 0x3f800000, 0x3f800000, 0x00000000, + 0x3f800000, 0x3f800000, 0x3f800000, 0x00000000, 0x00000000, 0x3f800000, 0x3f800000}}, + {SetMatrixPointerArray}, + {SetMatrixPointerArray, 0, 1, 1, 8, + {0x3f800000, 0x3f800000, 0x3f800000, 0x00000000, 0x00000000, 0x3f800000, 0x3f800000}}, + {SetMatrixPointerArray, 0, 2, REGISTER_OUTPUT_SIZE / 16, 16, + {0x3f800000, 0x3f800000, 0x3f800000, 0x00000000, 0x00000000, 0x3f800000, 0x3f800000, 0x00000000, + 0x3f800000, 0x3f800000, 0x3f800000, 0x00000000, 0x3f800000, 0x00000000, 0x00000000}}, + {SetMatrixTransposePointerArray}, + {SetMatrixTransposePointerArray, 0, 1, 1, 8, + {0x3f800000, 0x00000000, 0x3f800000, 0x00000000, 0x3f800000, 0x3f800000, 0x3f800000}}, + {SetMatrixTransposePointerArray, 0, 2, REGISTER_OUTPUT_SIZE / 16, 16, + {0x3f800000, 0x00000000, 0x3f800000, 0x00000000, 0x3f800000, 0x3f800000, 0x3f800000, 0x00000000, + 0x3f800000, 0x3f800000, 0x3f800000, 0x00000000, 0x3f800000, 0x00000000, 0x3f800000}}, +}; + +/* + * fxc.exe /Tvs_3_0 + */ +#if 0 +row_major bool3x2 rb = {1, 1, 0, 0, 1, 1}; +row_major int3x2 rn = {80, 81, 82, 83, 84, 85}; +row_major float3x2 rf = {95.1, 95.2, 95.3, 95.4, 95.5, 95.6}; +row_major bool3x2 rbf = {1, 1, 1, 1, 0, 1}; +row_major int3x2 rnf = {37, 13, 98, 54, 77, 36}; +float4 main(float4 pos : POSITION) : POSITION +{ + float4 tmp = 0; + int i; + if (rb._32) for (i = 0; i < rn._31; i++) tmp.x += pos.z * rf._31 * rbf._32; + else for (i = 0; i < rn._32; i++) tmp.y += pos.y * rf._32 * rnf._32; + return tmp; +} +#endif +static const DWORD registerset_blob_row[] = +{ +0xfffe0300, 0x0076fffe, 0x42415443, 0x0000001c, 0x000001a3, 0xfffe0300, 0x00000005, 0x0000001c, +0x00000100, 0x0000019c, 0x00000080, 0x00000000, 0x00000006, 0x00000084, 0x00000094, 0x000000ac, +0x00030002, 0x00000003, 0x00000084, 0x000000b0, 0x000000e0, 0x00000002, 0x00000003, 0x000000e4, +0x000000f4, 0x00000124, 0x00000001, 0x00000006, 0x00000128, 0x00000138, 0x00000168, 0x00060002, +0x00000003, 0x00000128, 0x0000016c, 0xab006272, 0x00010002, 0x00020003, 0x00000001, 0x00000000, +0xffffffff, 0xffffffff, 0x00000000, 0x00000000, 0xffffffff, 0xffffffff, 0x00666272, 0x3f800000, +0x3f800000, 0x00000000, 0x00000000, 0x3f800000, 0x3f800000, 0x00000000, 0x00000000, 0x00000000, +0x3f800000, 0x00000000, 0x00000000, 0xab006672, 0x00030002, 0x00020003, 0x00000001, 0x00000000, +0x42be3333, 0x42be6666, 0x00000000, 0x00000000, 0x42be999a, 0x42becccd, 0x00000000, 0x00000000, +0x42bf0000, 0x42bf3333, 0x00000000, 0x00000000, 0xab006e72, 0x00020002, 0x00020003, 0x00000001, +0x00000000, 0x00000050, 0x00000051, 0x00000001, 0x00000000, 0x00000052, 0x00000053, 0x00000001, +0x00000000, 0x00000054, 0x00000055, 0x00000001, 0x00000000, 0x00666e72, 0x42140000, 0x41500000, +0x00000000, 0x00000000, 0x42c40000, 0x42580000, 0x00000000, 0x00000000, 0x429a0000, 0x42100000, +0x00000000, 0x00000000, 0x335f7376, 0x4d00305f, 0x6f726369, 0x74666f73, 0x29522820, 0x534c4820, +0x6853204c, 0x72656461, 0x6d6f4320, 0x656c6970, 0x2e392072, 0x392e3932, 0x332e3235, 0x00313131, +0x05000051, 0xa00f0009, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x0200001f, 0x80000000, +0x900f0000, 0x0200001f, 0x80000000, 0xe00f0000, 0x01000028, 0xe0e40805, 0x03000005, 0x80010000, +0xa0000002, 0x90aa0000, 0x02000001, 0x80010001, 0xa0000009, 0x01000026, 0xf0e40004, 0x04000004, +0x80010001, 0x80000000, 0xa0550005, 0x80000001, 0x00000027, 0x02000001, 0x80020001, 0xa0000009, +0x0000002a, 0x03000005, 0x80010000, 0xa0550002, 0x90550000, 0x02000001, 0x80020001, 0xa0000009, +0x01000026, 0xf0e40005, 0x04000004, 0x80020001, 0x80000000, 0xa0550008, 0x80550001, 0x00000027, +0x02000001, 0x80010001, 0xa0000009, 0x0000002b, 0x02000001, 0xe0030000, 0x80e40001, 0x02000001, +0xe00c0000, 0xa0000009, 0x0000ffff, +}; + +static const struct registerset_constants registerset_constants_row_float[] = +{ + {"rf", {"rf", D3DXRS_FLOAT4, 0, 3, D3DXPC_MATRIX_ROWS, D3DXPT_FLOAT, 3, 2, 1, 0, 24, NULL}, 61}, +}; + +static const struct registerset_test registerset_test_row_float[] = +{ + {SetInt}, + {SetBool}, + {SetFloat}, + {SetIntArray, 1, 0, 5}, + {SetIntArray, 1, 6, REGISTER_OUTPUT_SIZE, 12, + {0x40000000, 0x40400000, 0x00000000, 0x00000000, 0x40800000, 0x40a00000, 0x00000000, 0x00000000, + 0x00000000, 0x40e00000}}, + {SetBoolArray, 1, 0, 5}, + {SetBoolArray, 1, 6, REGISTER_OUTPUT_SIZE, 12, + {0x3f800000, 0x3f800000, 0x00000000, 0x00000000, 0x3f800000, 0x3f800000, 0x00000000, 0x00000000, + 0x00000000, 0x3f800000}}, + {SetFloatArray, 0, 0, 5}, + {SetFloatArray, 0, 6, REGISTER_OUTPUT_SIZE, 12, + {0x40000123, 0x00000000, 0x00000000, 0x00000000, 0x40800123, 0x40a00123, 0x00000000, 0x00000000, + 0x40c00123, 0x40e00123}}, + {SetValue, 0, 0, 23}, + {SetValue, 0, 24, REGISTER_OUTPUT_SIZE * 4, 12, + {0x40000123, 0x00000000, 0x00000000, 0x00000000, 0x40800123, 0x40a00123, 0x00000000, 0x00000000, + 0x40c00123, 0x40e00123}}, + {SetVector}, + {SetVectorArray, 0, 0, 2}, + {SetVectorArray, 0, 3, REGISTER_OUTPUT_SIZE / 4, 12, + {0x40000123, 0x00000000, 0x00000000, 0x00000000, 0x40c00123, 0x40e00123, 0x00000000, 0x00000000, + 0x41200123, 0x41300123}}, + {SetMatrix, 0, 0, 0, 12, + {0x40000123, 0x00000000, 0x00000000, 0x00000000, 0x40c00123, 0x40e00123, 0x00000000, 0x00000000, + 0x41200123, 0x41300123}}, + {SetMatrixArray}, + {SetMatrixArray, 0, 1, REGISTER_OUTPUT_SIZE / 16, 12, + {0x40000123, 0x00000000, 0x00000000, 0x00000000, 0x40c00123, 0x40e00123, 0x00000000, 0x00000000, + 0x41200123, 0x41300123}}, + {SetMatrixTranspose, 0, 0, 0, 12, + {0x40000123, 0x40c00123, 0x00000000, 0x00000000, 0x00000000, 0x40e00123, 0x00000000, 0x00000000, + 0x40800123, 0x41000123}}, + {SetMatrixTransposeArray}, + {SetMatrixTransposeArray, 0, 1, REGISTER_OUTPUT_SIZE / 16, 12, + {0x40000123, 0x40c00123, 0x00000000, 0x00000000, 0x00000000, 0x40e00123, 0x00000000, 0x00000000, + 0x40800123, 0x41000123}}, + {SetMatrixPointerArray}, + {SetMatrixPointerArray, 0, 1, REGISTER_OUTPUT_SIZE / 16, 12, + {0x40000123, 0x00000000, 0x00000000, 0x00000000, 0x40c00123, 0x40e00123, 0x00000000, 0x00000000, + 0x41200123, 0x41300123}}, + {SetMatrixTransposePointerArray}, + {SetMatrixTransposePointerArray, 0, 1, REGISTER_OUTPUT_SIZE / 16, 12, + {0x40000123, 0x40c00123, 0x00000000, 0x00000000, 0x00000000, 0x40e00123, 0x00000000, 0x00000000, + 0x40800123, 0x41000123}}, +}; + +static const struct registerset_constants registerset_constants_row_int[] = +{ + {"rn", {"rn", D3DXRS_INT4, 0, 6, D3DXPC_MATRIX_ROWS, D3DXPT_INT, 3, 2, 1, 0, 24, NULL}, 78}, +}; + +static const struct registerset_test registerset_test_row_int[] = +{ + {SetInt}, + {SetBool}, + {SetFloat}, + {SetIntArray, 1, 0, 5}, + {SetIntArray, 1, 6, REGISTER_OUTPUT_SIZE, 12, + {0x00000002, 0x00000003, 0x00000001, 0x00000000, 0x00000004, 0x00000005, 0x00000001, 0x00000000, + 0x00000000, 0x00000007, 0x00000001}}, + {SetBoolArray, 1, 0, 5}, + {SetBoolArray, 1, 6, REGISTER_OUTPUT_SIZE, 12, + {0x00000001, 0x00000001, 0x00000001, 0x00000000, 0x00000001, 0x00000001, 0x00000001, 0x00000000, + 0x00000000, 0x00000001, 0x00000001}}, + {SetFloatArray, 0, 0, 5}, + {SetFloatArray, 0, 6, REGISTER_OUTPUT_SIZE, 12, + {0x00000002, 0x00000000, 0x00000001, 0x00000000, 0x00000004, 0x00000005, 0x00000001, 0x00000000, + 0x00000006, 0x00000007, 0x00000001}}, + {SetValue, 1, 0, 23}, + {SetValue, 1, 24, REGISTER_OUTPUT_SIZE * 4, 12, + {0x00000002, 0x00000003, 0x00000001, 0x00000000, 0x00000004, 0x00000005, 0x00000001, 0x00000000, + 0x00000000, 0x00000007, 0x00000001}}, + {SetVector}, + {SetVectorArray, 0, 0, 2}, + {SetVectorArray, 0, 3, REGISTER_OUTPUT_SIZE / 4, 12, + {0x00000002, 0x00000000, 0x00000001, 0x00000000, 0x00000006, 0x00000007, 0x00000001, 0x00000000, + 0x0000000a, 0x0000000b, 0x00000001}}, + {SetMatrix, 0, 0, 0, 12, + {0x00000002, 0x00000000, 0x00000001, 0x00000000, 0x00000006, 0x00000007, 0x00000001, 0x00000000, + 0x0000000a, 0x0000000b, 0x00000001}}, + {SetMatrixArray}, + {SetMatrixArray, 0, 1, REGISTER_OUTPUT_SIZE / 16, 12, + {0x00000002, 0x00000000, 0x00000001, 0x00000000, 0x00000006, 0x00000007, 0x00000001, 0x00000000, + 0x0000000a, 0x0000000b, 0x00000001}}, + {SetMatrixTranspose, 0, 0, 0, 12, + {0x00000002, 0x00000006, 0x00000001, 0x00000000, 0x00000000, 0x00000007, 0x00000001, 0x00000000, + 0x00000004, 0x00000008, 0x00000001}}, + {SetMatrixTransposeArray}, + {SetMatrixTransposeArray, 0, 1, REGISTER_OUTPUT_SIZE / 16, 12, + {0x00000002, 0x00000006, 0x00000001, 0x00000000, 0x00000000, 0x00000007, 0x00000001, 0x00000000, + 0x00000004, 0x00000008, 0x00000001}}, + {SetMatrixPointerArray}, + {SetMatrixPointerArray, 0, 1, REGISTER_OUTPUT_SIZE / 16, 12, + {0x00000002, 0x00000000, 0x00000001, 0x00000000, 0x00000006, 0x00000007, 0x00000001, 0x00000000, + 0x0000000a, 0x0000000b, 0x00000001}}, + {SetMatrixTransposePointerArray}, + {SetMatrixTransposePointerArray, 0, 1, REGISTER_OUTPUT_SIZE / 16, 12, + {0x00000002, 0x00000006, 0x00000001, 0x00000000, 0x00000000, 0x00000007, 0x00000001, 0x00000000, + 0x00000004, 0x00000008, 0x00000001}}, +}; + +static const struct registerset_constants registerset_constants_row_bool[] = +{ + {"rb", {"rb", D3DXRS_BOOL, 0, 6, D3DXPC_MATRIX_ROWS, D3DXPT_BOOL, 3, 2, 1, 0, 24, NULL}, 37}, +}; + +static const struct registerset_test registerset_test_row_bool[] = +{ + {SetInt}, + {SetBool}, + {SetFloat}, + {SetIntArray, 0, 0, 5,}, + {SetIntArray, 1, 6, REGISTER_OUTPUT_SIZE, 6, + {0x00000001, 0x00000001, 0x00000001, 0x00000001, 0x00000000, 0x00000001}}, + {SetBoolArray, 0, 0, 5}, + {SetBoolArray, 1, 6, REGISTER_OUTPUT_SIZE, 6, + {0x00000002, 0x00000003, 0x00000004, 0x00000005, 0x00000000, 0x00000007}}, + {SetFloatArray, 0, 0, 5}, + {SetFloatArray, 0, 6, REGISTER_OUTPUT_SIZE, 6, + {0x00000001, 0x00000000, 0x00000001, 0x00000001, 0x00000001, 0x00000001}}, + {SetValue, 0, 0, 23}, + {SetValue, 1, 24, REGISTER_OUTPUT_SIZE * 4, 6, + {0x00000002, 0x00000003, 0x00000004, 0x00000005, 0x00000000, 0x00000007}}, + {SetVector}, + {SetVectorArray, 0, 0, 2}, + {SetVectorArray, 0, 3, REGISTER_OUTPUT_SIZE / 4, 6, + {0x00000001, 0x00000000, 0x00000001, 0x00000001, 0x00000001, 0x00000001}}, + {SetMatrix, 0, 0, 0, 6, + {0x00000001, 0x00000000, 0x00000001, 0x00000001, 0x00000001, 0x00000001},}, + {SetMatrixArray}, + {SetMatrixArray, 0, 1, REGISTER_OUTPUT_SIZE / 16, 6, + {0x00000001, 0x00000000, 0x00000001, 0x00000001, 0x00000001, 0x00000001}}, + {SetMatrixTranspose, 0, 0, 0, 6, + {0x00000001, 0x00000001, 0x00000000, 0x00000001, 0x00000001, 0x00000001}}, + {SetMatrixTransposeArray}, + {SetMatrixTransposeArray, 0, 1, REGISTER_OUTPUT_SIZE / 16, 6, + {0x00000001, 0x00000001, 0x00000000, 0x00000001, 0x00000001, 0x00000001}}, + {SetMatrixPointerArray}, + {SetMatrixPointerArray, 0, 1, REGISTER_OUTPUT_SIZE / 16, 6, + {0x00000001, 0x00000000, 0x00000001, 0x00000001, 0x00000001, 0x00000001}}, + {SetMatrixTransposePointerArray}, + {SetMatrixTransposePointerArray, 0, 1, REGISTER_OUTPUT_SIZE / 16, 6, + {0x00000001, 0x00000001, 0x00000000, 0x00000001, 0x00000001, 0x00000001}}, +}; + +static const struct registerset_constants registerset_constants_row_int_float[] = +{ + {"rnf", {"rnf", D3DXRS_FLOAT4, 6, 3, D3DXPC_MATRIX_ROWS, D3DXPT_INT, 3, 2, 1, 0, 24, NULL}, 91}, +}; + +static const struct registerset_test registerset_test_row_int_float[] = +{ + {SetInt}, + {SetBool}, + {SetFloat}, + {SetIntArray, 1, 0, 5}, + {SetIntArray, 1, 6, REGISTER_OUTPUT_SIZE, 12, + {0x40000000, 0x40400000, 0x00000000, 0x00000000, 0x40800000, 0x40a00000, 0x00000000, 0x00000000, + 0x00000000, 0x40e00000}}, + {SetBoolArray, 1, 0, 5}, + {SetBoolArray, 1, 6, REGISTER_OUTPUT_SIZE, 12, + {0x3f800000, 0x3f800000, 0x00000000, 0x00000000, 0x3f800000, 0x3f800000, 0x00000000, 0x00000000, + 0x00000000, 0x3f800000}}, + {SetFloatArray, 0, 0, 5}, + {SetFloatArray, 0, 6, REGISTER_OUTPUT_SIZE, 12, + {0x40000000, 0x00000000, 0x00000000, 0x00000000, 0x40800000, 0x40a00000, 0x00000000, 0x00000000, + 0x40c00000, 0x40e00000}}, + {SetValue, 1, 0, 23}, + {SetValue, 1, 24, REGISTER_OUTPUT_SIZE * 4, 12, + {0x40000000, 0x40400000, 0x00000000, 0x00000000, 0x40800000, 0x40a00000, 0x00000000, 0x00000000, + 0x00000000, 0x40e00000}}, + {SetVector}, + {SetVectorArray, 0, 0, 2}, + {SetVectorArray, 0, 3, REGISTER_OUTPUT_SIZE / 4, 12, + {0x40000000, 0x00000000, 0x00000000, 0x00000000, 0x40c00000, 0x40e00000, 0x00000000, 0x00000000, + 0x41200000, 0x41300000}}, + {SetMatrix, 0, 0, 0, 12, + {0x40000000, 0x00000000, 0x00000000, 0x00000000, 0x40c00000, 0x40e00000, 0x00000000, 0x00000000, + 0x41200000, 0x41300000}}, + {SetMatrixArray}, + {SetMatrixArray, 0, 1, REGISTER_OUTPUT_SIZE / 16, 12, + {0x40000000, 0x00000000, 0x00000000, 0x00000000, 0x40c00000, 0x40e00000, 0x00000000, 0x00000000, + 0x41200000, 0x41300000}}, + {SetMatrixTranspose, 0, 0, 0, 12, + {0x40000000, 0x40c00000, 0x00000000, 0x00000000, 0x00000000, 0x40e00000, 0x00000000, 0x00000000, + 0x40800000, 0x41000000}}, + {SetMatrixTransposeArray}, + {SetMatrixTransposeArray, 0, 1, REGISTER_OUTPUT_SIZE / 16, 12, + {0x40000000, 0x40c00000, 0x00000000, 0x00000000, 0x00000000, 0x40e00000, 0x00000000, 0x00000000, + 0x40800000, 0x41000000}}, + {SetMatrixPointerArray}, + {SetMatrixPointerArray, 0, 1, REGISTER_OUTPUT_SIZE / 16, 12, + {0x40000000, 0x00000000, 0x00000000, 0x00000000, 0x40c00000, 0x40e00000, 0x00000000, 0x00000000, + 0x41200000, 0x41300000}}, + {SetMatrixTransposePointerArray}, + {SetMatrixTransposePointerArray, 0, 1, REGISTER_OUTPUT_SIZE / 16, 12, + {0x40000000, 0x40c00000, 0x00000000, 0x00000000, 0x00000000, 0x40e00000, 0x00000000, 0x00000000, + 0x40800000, 0x41000000}}, +}; + +static const struct registerset_constants registerset_constants_row_bool_float[] = +{ + {"rbf", {"rbf", D3DXRS_FLOAT4, 3, 3, D3DXPC_MATRIX_ROWS, D3DXPT_BOOL, 3, 2, 1, 0, 24, NULL}, 44}, +}; + +static const struct registerset_test registerset_test_row_bool_float[] = +{ + {SetInt}, + {SetBool}, + {SetFloat}, + {SetIntArray, 1, 0, 5}, + {SetIntArray, 1, 6, REGISTER_OUTPUT_SIZE, 12, + {0x3f800000, 0x3f800000, 0x00000000, 0x00000000, 0x3f800000, 0x3f800000, 0x00000000, 0x00000000, + 0x00000000, 0x3f800000}}, + {SetBoolArray, 1, 0, 5}, + {SetBoolArray, 1, 6, REGISTER_OUTPUT_SIZE, 12, + {0x3f800000, 0x3f800000, 0x00000000, 0x00000000, 0x3f800000, 0x3f800000, 0x00000000, 0x00000000, + 0x00000000, 0x3f800000}}, + {SetFloatArray, 0, 0, 5}, + {SetFloatArray, 0, 6, REGISTER_OUTPUT_SIZE, 12, + {0x3f800000, 0x00000000, 0x00000000, 0x00000000, 0x3f800000, 0x3f800000, 0x00000000, 0x00000000, + 0x3f800000, 0x3f800000}}, + {SetValue, 1, 0, 23}, + {SetValue, 1, 24, REGISTER_OUTPUT_SIZE * 4, 12, + {0x3f800000, 0x3f800000, 0x00000000, 0x00000000, 0x3f800000, 0x3f800000, 0x00000000, 0x00000000, + 0x00000000, 0x3f800000}}, + {SetVector}, + {SetVectorArray, 0, 0, 2}, + {SetVectorArray, 0, 3, REGISTER_OUTPUT_SIZE / 4, 12, + {0x3f800000, 0x00000000, 0x00000000, 0x00000000, 0x3f800000, 0x3f800000, 0x00000000, 0x00000000, + 0x3f800000, 0x3f800000}}, + {SetMatrix, 0, 0, 0, 12, + {0x3f800000, 0x00000000, 0x00000000, 0x00000000, 0x3f800000, 0x3f800000, 0x00000000, 0x00000000, + 0x3f800000, 0x3f800000}}, + {SetMatrixArray}, + {SetMatrixArray, 0, 1, REGISTER_OUTPUT_SIZE / 16, 12, + {0x3f800000, 0x00000000, 0x00000000, 0x00000000, 0x3f800000, 0x3f800000, 0x00000000, 0x00000000, + 0x3f800000, 0x3f800000}}, + {SetMatrixTranspose, 0, 0, 0, 12, + {0x3f800000, 0x3f800000, 0x00000000, 0x00000000, 0x00000000, 0x3f800000, 0x00000000, 0x00000000, + 0x3f800000, 0x3f800000}}, + {SetMatrixTransposeArray}, + {SetMatrixTransposeArray, 0, 1, REGISTER_OUTPUT_SIZE / 16, 12, + {0x3f800000, 0x3f800000, 0x00000000, 0x00000000, 0x00000000, 0x3f800000, 0x00000000, 0x00000000, + 0x3f800000, 0x3f800000}}, + {SetMatrixPointerArray}, + {SetMatrixPointerArray, 0, 1, REGISTER_OUTPUT_SIZE / 16, 12, + {0x3f800000, 0x00000000, 0x00000000, 0x00000000, 0x3f800000, 0x3f800000, 0x00000000, 0x00000000, + 0x3f800000, 0x3f800000}}, + {SetMatrixTransposePointerArray}, + {SetMatrixTransposePointerArray, 0, 1, REGISTER_OUTPUT_SIZE / 16, 12, + {0x3f800000, 0x3f800000, 0x00000000, 0x00000000, 0x00000000, 0x3f800000, 0x00000000, 0x00000000, + 0x3f800000, 0x3f800000}}, +}; + +/* + * fxc.exe /Tvs_3_0 + */ +#if 0 +row_major bool3x2 rab[2] = {1, 0, 0, 1, 0, 1, 0, 0, 1, 1, 0, 1}; +row_major int3x2 ran[2] = {4, 5, 6, 1, 8, 1, 5, 3, 9, 6, 7, 3}; +row_major float3x2 raf[2] = {1.5, 2.8, 3.3, 4.9, 5.9, 6.8, 7.9, 8.5, 9.4, 1.3, 1.2, 1.1}; +row_major bool3x2 rabf[2] = {1, 1, 1, 1, 0, 1, 1, 1, 0, 0, 0, 1}; +row_major int3x2 ranf[2] = {35, 40, 60, 80, 70, 56, 37, 13, 98, 54, 77, 36}; +float4 main(float4 pos : POSITION) : POSITION +{ + float4 tmp = 0; + int i; + if (rab[1]._32) for (i = 0; i < ran[1]._31; i++) tmp.x += pos.z * raf[1]._31 * rabf[1]._32; + else for (i = 0; i < ran[1]._32; i++) tmp.y += pos.y * raf[1]._32 * ranf[1]._32; + return tmp; +} +#endif +static const DWORD registerset_blob_row_array[] = +{ +0xfffe0300, 0x00b6fffe, 0x42415443, 0x0000001c, 0x000002a3, 0xfffe0300, 0x00000005, 0x0000001c, +0x00000100, 0x0000029c, 0x00000080, 0x00000000, 0x0000000c, 0x00000084, 0x00000094, 0x000000c4, +0x00060002, 0x00000006, 0x000000cc, 0x000000dc, 0x0000013c, 0x00000002, 0x00000006, 0x00000140, +0x00000150, 0x000001b0, 0x00000001, 0x0000000c, 0x000001b4, 0x000001c4, 0x00000224, 0x000c0002, +0x00000006, 0x0000022c, 0x0000023c, 0x00626172, 0x00010002, 0x00020003, 0x00000002, 0x00000000, +0xffffffff, 0x00000000, 0x00000000, 0xffffffff, 0x00000000, 0xffffffff, 0x00000000, 0x00000000, +0xffffffff, 0xffffffff, 0x00000000, 0xffffffff, 0x66626172, 0xababab00, 0x00010002, 0x00020003, +0x00000002, 0x00000000, 0x3f800000, 0x3f800000, 0x00000000, 0x00000000, 0x3f800000, 0x3f800000, +0x00000000, 0x00000000, 0x00000000, 0x3f800000, 0x00000000, 0x00000000, 0x3f800000, 0x3f800000, +0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x3f800000, +0x00000000, 0x00000000, 0x00666172, 0x00030002, 0x00020003, 0x00000002, 0x00000000, 0x3fc00000, +0x40333333, 0x00000000, 0x00000000, 0x40533333, 0x409ccccd, 0x00000000, 0x00000000, 0x40bccccd, +0x40d9999a, 0x00000000, 0x00000000, 0x40fccccd, 0x41080000, 0x00000000, 0x00000000, 0x41166666, +0x3fa66666, 0x00000000, 0x00000000, 0x3f99999a, 0x3f8ccccd, 0x00000000, 0x00000000, 0x006e6172, +0x00020002, 0x00020003, 0x00000002, 0x00000000, 0x00000004, 0x00000005, 0x00000001, 0x00000000, +0x00000006, 0x00000001, 0x00000001, 0x00000000, 0x00000008, 0x00000001, 0x00000001, 0x00000000, +0x00000005, 0x00000003, 0x00000001, 0x00000000, 0x00000009, 0x00000006, 0x00000001, 0x00000000, +0x00000007, 0x00000003, 0x00000001, 0x00000000, 0x666e6172, 0xababab00, 0x00020002, 0x00020003, +0x00000002, 0x00000000, 0x420c0000, 0x42200000, 0x00000000, 0x00000000, 0x42700000, 0x42a00000, +0x00000000, 0x00000000, 0x428c0000, 0x42600000, 0x00000000, 0x00000000, 0x42140000, 0x41500000, +0x00000000, 0x00000000, 0x42c40000, 0x42580000, 0x00000000, 0x00000000, 0x429a0000, 0x42100000, +0x00000000, 0x00000000, 0x335f7376, 0x4d00305f, 0x6f726369, 0x74666f73, 0x29522820, 0x534c4820, +0x6853204c, 0x72656461, 0x6d6f4320, 0x656c6970, 0x2e392072, 0x392e3932, 0x332e3235, 0x00313131, +0x05000051, 0xa00f0012, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x0200001f, 0x80000000, +0x900f0000, 0x0200001f, 0x80000000, 0xe00f0000, 0x01000028, 0xe0e4080b, 0x03000005, 0x80010000, +0xa0000005, 0x90aa0000, 0x02000001, 0x80010001, 0xa0000012, 0x01000026, 0xf0e4000a, 0x04000004, +0x80010001, 0x80000000, 0xa055000b, 0x80000001, 0x00000027, 0x02000001, 0x80020001, 0xa0000012, +0x0000002a, 0x03000005, 0x80010000, 0xa0550005, 0x90550000, 0x02000001, 0x80020001, 0xa0000012, +0x01000026, 0xf0e4000b, 0x04000004, 0x80020001, 0x80000000, 0xa0550011, 0x80550001, 0x00000027, +0x02000001, 0x80010001, 0xa0000012, 0x0000002b, 0x02000001, 0xe0030000, 0x80e40001, 0x02000001, +0xe00c0000, 0xa0000012, 0x0000ffff, +}; + +static const struct registerset_constants registerset_constants_row_array_float[] = +{ + {"raf", {"raf", D3DXRS_FLOAT4, 0, 6, D3DXPC_MATRIX_ROWS, D3DXPT_FLOAT, 3, 2, 2, 0, 48, NULL}, 84}, + {"raf[0]", {"raf", D3DXRS_FLOAT4, 0, 3, D3DXPC_MATRIX_ROWS, D3DXPT_FLOAT, 3, 2, 1, 0, 24, NULL}, 84}, + {"raf[1]", {"raf", D3DXRS_FLOAT4, 3, 3, D3DXPC_MATRIX_ROWS, D3DXPT_FLOAT, 3, 2, 1, 0, 24, NULL}, 96}, +}; + +static const struct registerset_test registerset_test_row_array_float[] = +{ + {SetInt}, + {SetBool}, + {SetFloat}, + {SetIntArray, 1, 0, 5}, + {SetIntArray, 1, 6, 11, 12, + {0x40000000, 0x40400000, 0x00000000, 0x00000000, 0x40800000, 0x40a00000, 0x00000000, 0x00000000, + 0x00000000, 0x40e00000}}, + {SetIntArray, 1, 12, REGISTER_OUTPUT_SIZE, 24, + {0x40000000, 0x40400000, 0x00000000, 0x00000000, 0x40800000, 0x40a00000, 0x00000000, 0x00000000, + 0x00000000, 0x40e00000, 0x00000000, 0x00000000, 0x41000000, 0x41100000, 0x00000000, 0x00000000, + 0x41200000, 0x41300000, 0x00000000, 0x00000000, 0x41400000, 0x41500000}}, + {SetBoolArray, 1, 0, 5}, + {SetBoolArray, 1, 6, 11, 12, + {0x3f800000, 0x3f800000, 0x00000000, 0x00000000, 0x3f800000, 0x3f800000, 0x00000000, 0x00000000, + 0x00000000, 0x3f800000}}, + {SetBoolArray, 1, 12, REGISTER_OUTPUT_SIZE, 24, + {0x3f800000, 0x3f800000, 0x00000000, 0x00000000, 0x3f800000, 0x3f800000, 0x00000000, 0x00000000, + 0x00000000, 0x3f800000, 0x00000000, 0x00000000, 0x3f800000, 0x3f800000, 0x00000000, 0x00000000, + 0x3f800000, 0x3f800000, 0x00000000, 0x00000000, 0x3f800000, 0x3f800000}}, + {SetFloatArray, 0, 0, 5}, + {SetFloatArray, 0, 6, 11, 12, + {0x40000123, 0x00000000, 0x00000000, 0x00000000, 0x40800123, 0x40a00123, 0x00000000, 0x00000000, + 0x40c00123, 0x40e00123}}, + {SetFloatArray, 0, 12, REGISTER_OUTPUT_SIZE, 24, + {0x40000123, 0x00000000, 0x00000000, 0x00000000, 0x40800123, 0x40a00123, 0x00000000, 0x00000000, + 0x40c00123, 0x40e00123, 0x00000000, 0x00000000, 0x41000123, 0x41100123, 0x00000000, 0x00000000, + 0x41200123, 0x41300123, 0x00000000, 0x00000000, 0x41400123, 0x41500123}}, + {SetValue, 0, 0, 23}, + {SetValue, 0, 24, 47, 12, + {0x40000123, 0x00000000, 0x00000000, 0x00000000, 0x40800123, 0x40a00123, 0x00000000, 0x00000000, + 0x40c00123, 0x40e00123}}, + {SetValue, 0, 48, REGISTER_OUTPUT_SIZE * 4, 24, + {0x40000123, 0x00000000, 0x00000000, 0x00000000, 0x40800123, 0x40a00123, 0x00000000, 0x00000000, + 0x40c00123, 0x40e00123, 0x00000000, 0x00000000, 0x41000123, 0x41100123, 0x00000000, 0x00000000, + 0x41200123, 0x41300123, 0x00000000, 0x00000000, 0x41400123, 0x41500123}}, + {SetVector}, + {SetVectorArray, 0, 0, 2}, + {SetVectorArray, 0, 3, 5, 12, + {0x40000123, 0x00000000, 0x00000000, 0x00000000, 0x40c00123, 0x40e00123, 0x00000000, 0x00000000, + 0x41200123, 0x41300123}}, + {SetVectorArray, 0, 6, REGISTER_OUTPUT_SIZE / 4, 24, + {0x40000123, 0x00000000, 0x00000000, 0x00000000, 0x40c00123, 0x40e00123, 0x00000000, 0x00000000, + 0x41200123, 0x41300123, 0x00000000, 0x00000000, 0x41600123, 0x41700123, 0x00000000, 0x00000000, + 0x41a00123, 0x41b00123, 0x00000000, 0x00000000, 0x00000000, 0x41f00123}}, + {SetMatrix, 0, 0, 0, 12, + {0x40000123, 0x00000000, 0x00000000, 0x00000000, 0x40c00123, 0x40e00123, 0x00000000, 0x00000000, + 0x41200123, 0x41300123}}, + {SetMatrixArray}, + {SetMatrixArray, 0, 1, 1, 12, + {0x40000123, 0x00000000, 0x00000000, 0x00000000, 0x40c00123, 0x40e00123, 0x00000000, 0x00000000, + 0x41200123, 0x41300123}}, + {SetMatrixArray, 0, 2, REGISTER_OUTPUT_SIZE / 16, 24, + {0x40000123, 0x00000000, 0x00000000, 0x00000000, 0x40c00123, 0x40e00123, 0x00000000, 0x00000000, + 0x41200123, 0x41300123, 0x00000000, 0x00000000, 0x41a00123, 0x41b00123, 0x00000000, 0x00000000, + 0x00000000, 0x41f00123, 0x00000000, 0x00000000, 0x00000000, 0x42300123}}, + {SetMatrixTranspose, 0, 0, 0, 12, + {0x40000123, 0x40c00123, 0x00000000, 0x00000000, 0x00000000, 0x40e00123, 0x00000000, 0x00000000, + 0x40800123, 0x41000123}}, + {SetMatrixTransposeArray}, + {SetMatrixTransposeArray, 0, 1, 1, 12, + {0x40000123, 0x40c00123, 0x00000000, 0x00000000, 0x00000000, 0x40e00123, 0x00000000, 0x00000000, + 0x40800123, 0x41000123}}, + {SetMatrixTransposeArray, 0, 2, REGISTER_OUTPUT_SIZE / 16, 24, + {0x40000123, 0x40c00123, 0x00000000, 0x00000000, 0x00000000, 0x40e00123, 0x00000000, 0x00000000, + 0x40800123, 0x41000123, 0x00000000, 0x00000000, 0x41a00123, 0x00000000, 0x00000000, 0x00000000, + 0x41b00123, 0x41f00123, 0x00000000, 0x00000000, 0x41c00123, 0x42000123}}, + {SetMatrixPointerArray}, + {SetMatrixPointerArray, 0, 1, 1, 12, + {0x40000123, 0x00000000, 0x00000000, 0x00000000, 0x40c00123, 0x40e00123, 0x00000000, 0x00000000, + 0x41200123, 0x41300123}}, + {SetMatrixPointerArray, 0, 2, REGISTER_OUTPUT_SIZE / 16, 24, + {0x40000123, 0x00000000, 0x00000000, 0x00000000, 0x40c00123, 0x40e00123, 0x00000000, 0x00000000, + 0x41200123, 0x41300123, 0x00000000, 0x00000000, 0x41900123, 0x41a00123, 0x00000000, 0x00000000, + 0x41d00123, 0x00000000, 0x00000000, 0x00000000, 0x42100123, 0x00000000}}, + {SetMatrixTransposePointerArray}, + {SetMatrixTransposePointerArray, 0, 1, 1, 12, + {0x40000123, 0x40c00123, 0x00000000, 0x00000000, 0x00000000, 0x40e00123, 0x00000000, 0x00000000, + 0x40800123, 0x41000123}}, + {SetMatrixTransposePointerArray, 0, 2, REGISTER_OUTPUT_SIZE / 16, 24, + {0x40000123, 0x40c00123, 0x00000000, 0x00000000, 0x00000000, 0x40e00123, 0x00000000, 0x00000000, + 0x40800123, 0x41000123, 0x00000000, 0x00000000, 0x41900123, 0x41d00123, 0x00000000, 0x00000000, + 0x41a00123, 0x00000000, 0x00000000, 0x00000000, 0x41b00123, 0x41f00123}}, +}; + +static const struct registerset_constants registerset_constants_row_array_int[] = +{ + {"ran", {"ran", D3DXRS_INT4, 0, 12, D3DXPC_MATRIX_ROWS, D3DXPT_INT, 3, 2, 2, 0, 48, NULL}, 113}, + {"ran[0]", {"ran", D3DXRS_INT4, 0, 3, D3DXPC_MATRIX_ROWS, D3DXPT_INT, 3, 2, 1, 0, 24, NULL}, 113}, + {"ran[1]", {"ran", D3DXRS_INT4, 3, 3, D3DXPC_MATRIX_ROWS, D3DXPT_INT, 3, 2, 1, 0, 24, NULL}, 125}, +}; + +static const struct registerset_test registerset_test_row_array_int[] = +{ + {SetInt}, + {SetBool}, + {SetFloat}, + {SetIntArray, 1, 0, 5}, + {SetIntArray, 1, 6, 11, 12, + {0x00000002, 0x00000003, 0x00000001, 0x00000000, 0x00000004, 0x00000005, 0x00000001, 0x00000000, + 0x00000000, 0x00000007, 0x00000001}}, + {SetIntArray, 1, 12, REGISTER_OUTPUT_SIZE, 24, + {0x00000002, 0x00000003, 0x00000001, 0x00000000, 0x00000004, 0x00000005, 0x00000001, 0x00000000, + 0x00000000, 0x00000007, 0x00000001, 0x00000000, 0x00000008, 0x00000009, 0x00000001, 0x00000000, + 0x0000000a, 0x0000000b, 0x00000001, 0x00000000, 0x0000000c, 0x0000000d, 0x00000001}}, + {SetBoolArray, 1, 0, 5}, + {SetBoolArray, 1, 6, 11, 12, + {0x00000001, 0x00000001, 0x00000001, 0x00000000, 0x00000001, 0x00000001, 0x00000001, 0x00000000, + 0x00000000, 0x00000001, 0x00000001}}, + {SetBoolArray, 1, 12, REGISTER_OUTPUT_SIZE, 24, + {0x00000001, 0x00000001, 0x00000001, 0x00000000, 0x00000001, 0x00000001, 0x00000001, 0x00000000, + 0x00000000, 0x00000001, 0x00000001, 0x00000000, 0x00000001, 0x00000001, 0x00000001, 0x00000000, + 0x00000001, 0x00000001, 0x00000001, 0x00000000, 0x00000001, 0x00000001, 0x00000001}}, + {SetFloatArray, 0, 0, 5}, + {SetFloatArray, 0, 6, 11, 12, + {0x00000002, 0x00000000, 0x00000001, 0x00000000, 0x00000004, 0x00000005, 0x00000001, 0x00000000, + 0x00000006, 0x00000007, 0x00000001}}, + {SetFloatArray, 0, 12, REGISTER_OUTPUT_SIZE, 24, + {0x00000002, 0x00000000, 0x00000001, 0x00000000, 0x00000004, 0x00000005, 0x00000001, 0x00000000, + 0x00000006, 0x00000007, 0x00000001, 0x00000000, 0x00000008, 0x00000009, 0x00000001, 0x00000000, + 0x0000000a, 0x0000000b, 0x00000001, 0x00000000, 0x0000000c, 0x0000000d, 0x00000001}}, + {SetValue, 1, 0, 23}, + {SetValue, 1, 24, 47, 12, + {0x00000002, 0x00000003, 0x00000001, 0x00000000, 0x00000004, 0x00000005, 0x00000001, 0x00000000, + 0x00000000, 0x00000007, 0x00000001}}, + {SetValue, 1, 48, REGISTER_OUTPUT_SIZE * 4, 24, + {0x00000002, 0x00000003, 0x00000001, 0x00000000, 0x00000004, 0x00000005, 0x00000001, 0x00000000, + 0x00000000, 0x00000007, 0x00000001, 0x00000000, 0x00000008, 0x00000009, 0x00000001, 0x00000000, + 0x0000000a, 0x0000000b, 0x00000001, 0x00000000, 0x0000000c, 0x0000000d, 0x00000001}}, + {SetVector}, + {SetVectorArray, 0, 0, 2}, + {SetVectorArray, 0, 3, 5, 12, + {0x00000002, 0x00000000, 0x00000001, 0x00000000, 0x00000006, 0x00000007, 0x00000001, 0x00000000, + 0x0000000a, 0x0000000b, 0x00000001}}, + {SetVectorArray, 0, 6, REGISTER_OUTPUT_SIZE / 4, 24, + {0x00000002, 0x00000000, 0x00000001, 0x00000000, 0x00000006, 0x00000007, 0x00000001, 0x00000000, + 0x0000000a, 0x0000000b, 0x00000001, 0x00000000, 0x0000000e, 0x0000000f, 0x00000001, 0x00000000, + 0x00000014, 0x00000016, 0x00000001, 0x00000000, 0x00000000, 0x0000001e, 0x00000001}}, + {SetMatrix, 0, 0, 0, 12, + {0x00000002, 0x00000000, 0x00000001, 0x00000000, 0x00000006, 0x00000007, 0x00000001, 0x00000000, + 0x0000000a, 0x0000000b, 0x00000001}}, + {SetMatrixArray}, + {SetMatrixArray, 0, 1, 1, 12, + {0x00000002, 0x00000000, 0x00000001, 0x00000000, 0x00000006, 0x00000007, 0x00000001, 0x00000000, + 0x0000000a, 0x0000000b, 0x00000001}}, + {SetMatrixArray, 0, 2, REGISTER_OUTPUT_SIZE / 16, 24, + {0x00000002, 0x00000000, 0x00000001, 0x00000000, 0x00000006, 0x00000007, 0x00000001, 0x00000000, + 0x0000000a, 0x0000000b, 0x00000001, 0x00000000, 0x00000014, 0x00000016, 0x00000001, 0x00000000, + 0x00000000, 0x0000001e, 0x00000001, 0x00000000, 0x00000000, 0x0000002c, 0x00000001}}, + {SetMatrixTranspose, 0, 0, 0, 12, + {0x00000002, 0x00000006, 0x00000001, 0x00000000, 0x00000000, 0x00000007, 0x00000001, 0x00000000, + 0x00000004, 0x00000008, 0x00000001}}, + {SetMatrixTransposeArray}, + {SetMatrixTransposeArray, 0, 1, 1, 12, + {0x00000002, 0x00000006, 0x00000001, 0x00000000, 0x00000000, 0x00000007, 0x00000001, 0x00000000, + 0x00000004, 0x00000008, 0x00000001}}, + {SetMatrixTransposeArray, 0, 2, REGISTER_OUTPUT_SIZE / 16, 24, + {0x00000002, 0x00000006, 0x00000001, 0x00000000, 0x00000000, 0x00000007, 0x00000001, 0x00000000, + 0x00000004, 0x00000008, 0x00000001, 0x00000000, 0x00000014, 0x00000000, 0x00000001, 0x00000000, + 0x00000016, 0x0000001e, 0x00000001, 0x00000000, 0x00000018, 0x00000020, 0x00000001}}, + {SetMatrixPointerArray}, + {SetMatrixPointerArray, 0, 1, 1, 12, + {0x00000002, 0x00000000, 0x00000001, 0x00000000, 0x00000006, 0x00000007, 0x00000001, 0x00000000, + 0x0000000a, 0x0000000b, 0x00000001}}, + {SetMatrixPointerArray, 0, 2, REGISTER_OUTPUT_SIZE / 16, 24, + {0x00000002, 0x00000000, 0x00000001, 0x00000000, 0x00000006, 0x00000007, 0x00000001, 0x00000000, + 0x0000000a, 0x0000000b, 0x00000001, 0x00000000, 0x00000012, 0x00000014, 0x00000001, 0x00000000, + 0x0000001a, 0x00000000, 0x00000001, 0x00000000, 0x00000024, 0x00000000, 0x00000001}}, + {SetMatrixTransposePointerArray}, + {SetMatrixTransposePointerArray, 0, 1, 1, 12, + {0x00000002, 0x00000006, 0x00000001, 0x00000000, 0x00000000, 0x00000007, 0x00000001, 0x00000000, + 0x00000004, 0x00000008, 0x00000001}}, + {SetMatrixTransposePointerArray, 0, 2, REGISTER_OUTPUT_SIZE / 16, 24, + {0x00000002, 0x00000006, 0x00000001, 0x00000000, 0x00000000, 0x00000007, 0x00000001, 0x00000000, + 0x00000004, 0x00000008, 0x00000001, 0x00000000, 0x00000012, 0x0000001a, 0x00000001, 0x00000000, + 0x00000014, 0x00000000, 0x00000001, 0x00000000, 0x00000016, 0x0000001e, 0x00000001}}, +}; + +static const struct registerset_constants registerset_constants_row_array_bool[] = +{ + {"rab", {"rab", D3DXRS_BOOL, 0, 12, D3DXPC_MATRIX_ROWS, D3DXPT_BOOL, 3, 2, 2, 0, 48, NULL}, 37}, + {"rab[0]", {"rab", D3DXRS_BOOL, 0, 6, D3DXPC_MATRIX_ROWS, D3DXPT_BOOL, 3, 2, 1, 0, 24, NULL}, 37}, + {"rab[1]", {"rab", D3DXRS_BOOL, 6, 6, D3DXPC_MATRIX_ROWS, D3DXPT_BOOL, 3, 2, 1, 0, 24, NULL}, 43}, +}; + +static const struct registerset_test registerset_test_row_array_bool[] = +{ + {SetInt}, + {SetBool}, + {SetFloat}, + {SetIntArray, 1, 0, 5,}, + {SetIntArray, 1, 6, 11, 6, + {0x00000001, 0x00000001, 0x00000001, 0x00000001, 0x00000000, 0x00000001}}, + {SetIntArray, 1, 12, REGISTER_OUTPUT_SIZE, 12, + {0x00000001, 0x00000001, 0x00000001, 0x00000001, 0x00000000, 0x00000001, 0x00000001, 0x00000001, + 0x00000001, 0x00000001, 0x00000001, 0x00000001}}, + {SetBoolArray, 1, 0, 5}, + {SetBoolArray, 1, 6, 11, 6, + {0x00000002, 0x00000003, 0x00000004, 0x00000005, 0x00000000, 0x00000007}}, + {SetBoolArray, 1, 12, REGISTER_OUTPUT_SIZE, 12, + {0x00000002, 0x00000003, 0x00000004, 0x00000005, 0x00000000, 0x00000007, 0x00000008, 0x00000009, + 0x0000000a, 0x0000000b, 0x0000000c, 0x0000000d}}, + {SetFloatArray, 0, 0, 5}, + {SetFloatArray, 0, 6, 11, 6, + {0x00000001, 0x00000000, 0x00000001, 0x00000001, 0x00000001, 0x00000001}}, + {SetFloatArray, 0, 12, REGISTER_OUTPUT_SIZE, 12, + {0x00000001, 0x00000000, 0x00000001, 0x00000001, 0x00000001, 0x00000001, 0x00000001, 0x00000001, + 0x00000001, 0x00000001, 0x00000001, 0x00000001}}, + {SetValue, 1, 0, 23}, + {SetValue, 1, 24, 47, 6, + {0x00000002, 0x00000003, 0x00000004, 0x00000005, 0x00000000, 0x00000007}}, + {SetValue, 1, 48, REGISTER_OUTPUT_SIZE * 4, 12, + {0x00000002, 0x00000003, 0x00000004, 0x00000005, 0x00000000, 0x00000007, 0x00000008, 0x00000009, + 0x0000000a, 0x0000000b, 0x0000000c, 0x0000000d}}, + {SetVector}, + {SetVectorArray, 0, 0, 2}, + {SetVectorArray, 0, 3, 5, 6, + {0x00000001, 0x00000000, 0x00000001, 0x00000001, 0x00000001, 0x00000001}}, + {SetVectorArray, 0, 6, REGISTER_OUTPUT_SIZE / 4, 12, + {0x00000001, 0x00000000, 0x00000001, 0x00000001, 0x00000001, 0x00000001, 0x00000001, 0x00000001, + 0x00000001, 0x00000001, 0x00000000, 0x00000001}}, + {SetMatrix, 0, 0, 0, 6, + {0x00000001, 0x00000000, 0x00000001, 0x00000001, 0x00000001, 0x00000001}}, + {SetMatrixArray}, + {SetMatrixArray, 0, 1, 1, 6, + {0x00000001, 0x00000000, 0x00000001, 0x00000001, 0x00000001, 0x00000001}}, + {SetMatrixArray, 0, 2, REGISTER_OUTPUT_SIZE / 16, 12, + {0x00000001, 0x00000000, 0x00000001, 0x00000001, 0x00000001, 0x00000001, 0x00000001, 0x00000001, + 0x00000000, 0x00000001, 0x00000000, 0x00000001}}, + {SetMatrixTranspose, 0, 0, 0, 6, + {0x00000001, 0x00000001, 0x00000000, 0x00000001, 0x00000001, 0x00000001}}, + {SetMatrixTransposeArray}, + {SetMatrixTransposeArray, 0, 1, 1, 6, + {0x00000001, 0x00000001, 0x00000000, 0x00000001, 0x00000001, 0x00000001}}, + {SetMatrixTransposeArray, 0, 2, REGISTER_OUTPUT_SIZE / 16, 12, + {0x00000001, 0x00000001, 0x00000000, 0x00000001, 0x00000001, 0x00000001, 0x00000001, 0x00000000, + 0x00000001, 0x00000001, 0x00000001, 0x00000001}}, + {SetMatrixPointerArray}, + {SetMatrixPointerArray, 0, 1, 1, 6, + {0x00000001, 0x00000000, 0x00000001, 0x00000001, 0x00000001, 0x00000001}}, + {SetMatrixPointerArray, 0, 2, REGISTER_OUTPUT_SIZE / 16, 12, + {0x00000001, 0x00000000, 0x00000001, 0x00000001, 0x00000001, 0x00000001, 0x00000001, 0x00000001, + 0x00000001, 0x00000000, 0x00000001, 0x00000000}}, + {SetMatrixTransposePointerArray}, + {SetMatrixTransposePointerArray, 0, 1, 1, 6, + {0x00000001, 0x00000001, 0x00000000, 0x00000001, 0x00000001, 0x00000001}}, + {SetMatrixTransposePointerArray, 0, 2, REGISTER_OUTPUT_SIZE / 16, 12, + {0x00000001, 0x00000001, 0x00000000, 0x00000001, 0x00000001, 0x00000001, 0x00000001, 0x00000001, + 0x00000001, 0x00000000, 0x00000001, 0x00000001}}, +}; + +static const struct registerset_constants registerset_constants_row_array_int_float[] = +{ + {"ranf", {"ranf", D3DXRS_FLOAT4, 12, 6, D3DXPC_MATRIX_ROWS, D3DXPT_INT, 3, 2, 2, 0, 48, NULL}, 143}, + {"ranf[0]", {"ranf", D3DXRS_FLOAT4, 12, 3, D3DXPC_MATRIX_ROWS, D3DXPT_INT, 3, 2, 1, 0, 24, NULL}, 143}, + {"ranf[1]", {"ranf", D3DXRS_FLOAT4, 15, 3, D3DXPC_MATRIX_ROWS, D3DXPT_INT, 3, 2, 1, 0, 24, NULL}, 155}, +}; + +static const struct registerset_test registerset_test_row_array_int_float[] = +{ + {SetInt}, + {SetBool}, + {SetFloat}, + {SetIntArray, 1, 0, 5}, + {SetIntArray, 1, 6, 11, 12, + {0x40000000, 0x40400000, 0x00000000, 0x00000000, 0x40800000, 0x40a00000, 0x00000000, 0x00000000, + 0x00000000, 0x40e00000,}}, + {SetIntArray, 1, 12, REGISTER_OUTPUT_SIZE, 24, + {0x40000000, 0x40400000, 0x00000000, 0x00000000, 0x40800000, 0x40a00000, 0x00000000, 0x00000000, + 0x00000000, 0x40e00000, 0x00000000, 0x00000000, 0x41000000, 0x41100000, 0x00000000, 0x00000000, + 0x41200000, 0x41300000, 0x00000000, 0x00000000, 0x41400000, 0x41500000}}, + {SetBoolArray, 1, 0, 5}, + {SetBoolArray, 1, 6, 11, 12, + {0x3f800000, 0x3f800000, 0x00000000, 0x00000000, 0x3f800000, 0x3f800000, 0x00000000, 0x00000000, + 0x00000000, 0x3f800000}}, + {SetBoolArray, 1, 12, REGISTER_OUTPUT_SIZE, 24, + {0x3f800000, 0x3f800000, 0x00000000, 0x00000000, 0x3f800000, 0x3f800000, 0x00000000, 0x00000000, + 0x00000000, 0x3f800000, 0x00000000, 0x00000000, 0x3f800000, 0x3f800000, 0x00000000, 0x00000000, + 0x3f800000, 0x3f800000, 0x00000000, 0x00000000, 0x3f800000, 0x3f800000}}, + {SetFloatArray, 0, 0, 5}, + {SetFloatArray, 0, 6, 11, 12, + {0x40000000, 0x00000000, 0x00000000, 0x00000000, 0x40800000, 0x40a00000, 0x00000000, 0x00000000, + 0x40c00000, 0x40e00000}}, + {SetFloatArray, 0, 12, REGISTER_OUTPUT_SIZE, 24, + {0x40000000, 0x00000000, 0x00000000, 0x00000000, 0x40800000, 0x40a00000, 0x00000000, 0x00000000, + 0x40c00000, 0x40e00000, 0x00000000, 0x00000000, 0x41000000, 0x41100000, 0x00000000, 0x00000000, + 0x41200000, 0x41300000, 0x00000000, 0x00000000, 0x41400000, 0x41500000}}, + {SetValue, 1, 0, 23}, + {SetValue, 1, 24, 47, 12, + {0x40000000, 0x40400000, 0x00000000, 0x00000000, 0x40800000, 0x40a00000, 0x00000000, 0x00000000, + 0x00000000, 0x40e00000}}, + {SetValue, 1, 48, REGISTER_OUTPUT_SIZE * 4, 24, + {0x40000000, 0x40400000, 0x00000000, 0x00000000, 0x40800000, 0x40a00000, 0x00000000, 0x00000000, + 0x00000000, 0x40e00000, 0x00000000, 0x00000000, 0x41000000, 0x41100000, 0x00000000, 0x00000000, + 0x41200000, 0x41300000, 0x00000000, 0x00000000, 0x41400000, 0x41500000}}, + {SetVector}, + {SetVectorArray, 0, 0, 2}, + {SetVectorArray, 0, 3, 5, 12, + {0x40000000, 0x00000000, 0x00000000, 0x00000000, 0x40c00000, 0x40e00000, 0x00000000, 0x00000000, + 0x41200000, 0x41300000}}, + {SetVectorArray, 0, 6, REGISTER_OUTPUT_SIZE / 4, 24, + {0x40000000, 0x00000000, 0x00000000, 0x00000000, 0x40c00000, 0x40e00000, 0x00000000, 0x00000000, + 0x41200000, 0x41300000, 0x00000000, 0x00000000, 0x41600000, 0x41700000, 0x00000000, 0x00000000, + 0x41a00000, 0x41b00000, 0x00000000, 0x00000000, 0x00000000, 0x41f00000}}, + {SetMatrix, 0, 0, 0, 12, + {0x40000000, 0x00000000, 0x00000000, 0x00000000, 0x40c00000, 0x40e00000, 0x00000000, 0x00000000, + 0x41200000, 0x41300000}}, + {SetMatrixArray}, + {SetMatrixArray, 0, 1, 1, 12, + {0x40000000, 0x00000000, 0x00000000, 0x00000000, 0x40c00000, 0x40e00000, 0x00000000, 0x00000000, + 0x41200000, 0x41300000}}, + {SetMatrixArray, 0, 2, REGISTER_OUTPUT_SIZE / 16, 24, + {0x40000000, 0x00000000, 0x00000000, 0x00000000, 0x40c00000, 0x40e00000, 0x00000000, 0x00000000, + 0x41200000, 0x41300000, 0x00000000, 0x00000000, 0x41a00000, 0x41b00000, 0x00000000, 0x00000000, + 0x00000000, 0x41f00000, 0x00000000, 0x00000000, 0x00000000, 0x42300000}}, + {SetMatrixTranspose, 0, 0, 0, 12, + {0x40000000, 0x40c00000, 0x00000000, 0x00000000, 0x00000000, 0x40e00000, 0x00000000, 0x00000000, + 0x40800000, 0x41000000}}, + {SetMatrixTransposeArray}, + {SetMatrixTransposeArray, 0, 1, 1, 12, + {0x40000000, 0x40c00000, 0x00000000, 0x00000000, 0x00000000, 0x40e00000, 0x00000000, 0x00000000, + 0x40800000, 0x41000000}}, + {SetMatrixTransposeArray, 0, 2, REGISTER_OUTPUT_SIZE / 16, 24, + {0x40000000, 0x40c00000, 0x00000000, 0x00000000, 0x00000000, 0x40e00000, 0x00000000, 0x00000000, + 0x40800000, 0x41000000, 0x00000000, 0x00000000, 0x41a00000, 0x00000000, 0x00000000, 0x00000000, + 0x41b00000, 0x41f00000, 0x00000000, 0x00000000, 0x41c00000, 0x42000000}}, + {SetMatrixPointerArray}, + {SetMatrixPointerArray, 0, 1, 1, 12, + {0x40000000, 0x00000000, 0x00000000, 0x00000000, 0x40c00000, 0x40e00000, 0x00000000, 0x00000000, + 0x41200000, 0x41300000}}, + {SetMatrixPointerArray, 0, 2, REGISTER_OUTPUT_SIZE / 16, 24, + {0x40000000, 0x00000000, 0x00000000, 0x00000000, 0x40c00000, 0x40e00000, 0x00000000, 0x00000000, + 0x41200000, 0x41300000, 0x00000000, 0x00000000, 0x41900000, 0x41a00000, 0x00000000, 0x00000000, + 0x41d00000, 0x00000000, 0x00000000, 0x00000000, 0x42100000, 0x00000000}}, + {SetMatrixTransposePointerArray}, + {SetMatrixTransposePointerArray, 0, 1, 1, 12, + {0x40000000, 0x40c00000, 0x00000000, 0x00000000, 0x00000000, 0x40e00000, 0x00000000, 0x00000000, + 0x40800000, 0x41000000}}, + {SetMatrixTransposePointerArray, 0, 2, REGISTER_OUTPUT_SIZE / 16, 24, + {0x40000000, 0x40c00000, 0x00000000, 0x00000000, 0x00000000, 0x40e00000, 0x00000000, 0x00000000, + 0x40800000, 0x41000000, 0x00000000, 0x00000000, 0x41900000, 0x41d00000, 0x00000000, 0x00000000, + 0x41a00000, 0x00000000, 0x00000000, 0x00000000, 0x41b00000, 0x41f00000}}, +}; + +static const struct registerset_constants registerset_constants_row_array_bool_float[] = +{ + {"rabf", {"rabf", D3DXRS_FLOAT4, 6, 6, D3DXPC_MATRIX_ROWS, D3DXPT_BOOL, 3, 2, 2, 0, 48, NULL}, 55}, + {"rabf[0]", {"rabf", D3DXRS_FLOAT4, 6, 3, D3DXPC_MATRIX_ROWS, D3DXPT_BOOL, 3, 2, 1, 0, 24, NULL}, 55}, + {"rabf[1]", {"rabf", D3DXRS_FLOAT4, 9, 3, D3DXPC_MATRIX_ROWS, D3DXPT_BOOL, 3, 2, 1, 0, 24, NULL}, 67}, +}; + +static const struct registerset_test registerset_test_row_array_bool_float[] = +{ + {SetInt}, + {SetBool}, + {SetFloat}, + {SetIntArray, 1, 0, 5}, + {SetIntArray, 1, 6, 11, 12, + {0x3f800000, 0x3f800000, 0x00000000, 0x00000000, 0x3f800000, 0x3f800000, 0x00000000, 0x00000000, + 0x00000000, 0x3f800000}}, + {SetIntArray, 1, 12, REGISTER_OUTPUT_SIZE, 24, + {0x3f800000, 0x3f800000, 0x00000000, 0x00000000, 0x3f800000, 0x3f800000, 0x00000000, 0x00000000, + 0x00000000, 0x3f800000, 0x00000000, 0x00000000, 0x3f800000, 0x3f800000, 0x00000000, 0x00000000, + 0x3f800000, 0x3f800000, 0x00000000, 0x00000000, 0x3f800000, 0x3f800000}}, + {SetBoolArray, 1, 0, 5}, + {SetBoolArray, 1, 6, 11, 12, + {0x3f800000, 0x3f800000, 0x00000000, 0x00000000, 0x3f800000, 0x3f800000, 0x00000000, 0x00000000, + 0x00000000, 0x3f800000}}, + {SetBoolArray, 1, 12, REGISTER_OUTPUT_SIZE, 24, + {0x3f800000, 0x3f800000, 0x00000000, 0x00000000, 0x3f800000, 0x3f800000, 0x00000000, 0x00000000, + 0x00000000, 0x3f800000, 0x00000000, 0x00000000, 0x3f800000, 0x3f800000, 0x00000000, 0x00000000, + 0x3f800000, 0x3f800000, 0x00000000, 0x00000000, 0x3f800000, 0x3f800000}}, + {SetFloatArray, 0, 0, 5}, + {SetFloatArray, 0, 6, 11, 12, + {0x3f800000, 0x00000000, 0x00000000, 0x00000000, 0x3f800000, 0x3f800000, 0x00000000, 0x00000000, + 0x3f800000, 0x3f800000}}, + {SetFloatArray, 0, 12, REGISTER_OUTPUT_SIZE, 24, + {0x3f800000, 0x00000000, 0x00000000, 0x00000000, 0x3f800000, 0x3f800000, 0x00000000, 0x00000000, + 0x3f800000, 0x3f800000, 0x00000000, 0x00000000, 0x3f800000, 0x3f800000, 0x00000000, 0x00000000, + 0x3f800000, 0x3f800000, 0x00000000, 0x00000000, 0x3f800000, 0x3f800000}}, + {SetValue, 1, 0, 23}, + {SetValue, 1, 24, 47, 12, + {0x3f800000, 0x3f800000, 0x00000000, 0x00000000, 0x3f800000, 0x3f800000, 0x00000000, 0x00000000, + 0x00000000, 0x3f800000}}, + {SetValue, 1, 48, REGISTER_OUTPUT_SIZE * 4, 24, + {0x3f800000, 0x3f800000, 0x00000000, 0x00000000, 0x3f800000, 0x3f800000, 0x00000000, 0x00000000, + 0x00000000, 0x3f800000, 0x00000000, 0x00000000, 0x3f800000, 0x3f800000, 0x00000000, 0x00000000, + 0x3f800000, 0x3f800000, 0x00000000, 0x00000000, 0x3f800000, 0x3f800000}}, + {SetVector}, + {SetVectorArray, 0, 0, 2}, + {SetVectorArray, 0, 3, 5, 12, + {0x3f800000, 0x00000000, 0x00000000, 0x00000000, 0x3f800000, 0x3f800000, 0x00000000, 0x00000000, + 0x3f800000, 0x3f800000}}, + {SetVectorArray, 0, 6, REGISTER_OUTPUT_SIZE / 4, 24, + {0x3f800000, 0x00000000, 0x00000000, 0x00000000, 0x3f800000, 0x3f800000, 0x00000000, 0x00000000, + 0x3f800000, 0x3f800000, 0x00000000, 0x00000000, 0x3f800000, 0x3f800000, 0x00000000, 0x00000000, + 0x3f800000, 0x3f800000, 0x00000000, 0x00000000, 0x00000000, 0x3f800000}}, + {SetMatrix, 0, 0, 0, 12, + {0x3f800000, 0x00000000, 0x00000000, 0x00000000, 0x3f800000, 0x3f800000, 0x00000000, 0x00000000, + 0x3f800000, 0x3f800000}}, + {SetMatrixArray}, + {SetMatrixArray, 0, 1, 1, 12, + {0x3f800000, 0x00000000, 0x00000000, 0x00000000, 0x3f800000, 0x3f800000, 0x00000000, 0x00000000, + 0x3f800000, 0x3f800000}}, + {SetMatrixArray, 0, 2, REGISTER_OUTPUT_SIZE / 16, 24, + {0x3f800000, 0x00000000, 0x00000000, 0x00000000, 0x3f800000, 0x3f800000, 0x00000000, 0x00000000, + 0x3f800000, 0x3f800000, 0x00000000, 0x00000000, 0x3f800000, 0x3f800000, 0x00000000, 0x00000000, + 0x00000000, 0x3f800000, 0x00000000, 0x00000000, 0x00000000, 0x3f800000}}, + {SetMatrixTranspose, 0, 0, 0, 12, + {0x3f800000, 0x3f800000, 0x00000000, 0x00000000, 0x00000000, 0x3f800000, 0x00000000, 0x00000000, + 0x3f800000, 0x3f800000}}, + {SetMatrixTransposeArray}, + {SetMatrixTransposeArray, 0, 1, 1, 12, + {0x3f800000, 0x3f800000, 0x00000000, 0x00000000, 0x00000000, 0x3f800000, 0x00000000, 0x00000000, + 0x3f800000, 0x3f800000}}, + {SetMatrixTransposeArray, 0, 2, REGISTER_OUTPUT_SIZE / 16, 24, + {0x3f800000, 0x3f800000, 0x00000000, 0x00000000, 0x00000000, 0x3f800000, 0x00000000, 0x00000000, + 0x3f800000, 0x3f800000, 0x00000000, 0x00000000, 0x3f800000, 0x00000000, 0x00000000, 0x00000000, + 0x3f800000, 0x3f800000, 0x00000000, 0x00000000, 0x3f800000, 0x3f800000}}, + {SetMatrixPointerArray}, + {SetMatrixPointerArray, 0, 1, 1, 12, + {0x3f800000, 0x00000000, 0x00000000, 0x00000000, 0x3f800000, 0x3f800000, 0x00000000, 0x00000000, + 0x3f800000, 0x3f800000}}, + {SetMatrixPointerArray, 0, 2, REGISTER_OUTPUT_SIZE / 16, 24, + {0x3f800000, 0x00000000, 0x00000000, 0x00000000, 0x3f800000, 0x3f800000, 0x00000000, 0x00000000, + 0x3f800000, 0x3f800000, 0x00000000, 0x00000000, 0x3f800000, 0x3f800000, 0x00000000, 0x00000000, + 0x3f800000, 0x00000000, 0x00000000, 0x00000000, 0x3f800000, 0x00000000}}, + {SetMatrixTransposePointerArray}, + {SetMatrixTransposePointerArray, 0, 1, 1, 12, + {0x3f800000, 0x3f800000, 0x00000000, 0x00000000, 0x00000000, 0x3f800000, 0x00000000, 0x00000000, + 0x3f800000, 0x3f800000}}, + {SetMatrixTransposePointerArray, 0, 2, REGISTER_OUTPUT_SIZE / 16, 24, + {0x3f800000, 0x3f800000, 0x00000000, 0x00000000, 0x00000000, 0x3f800000, 0x00000000, 0x00000000, + 0x3f800000, 0x3f800000, 0x00000000, 0x00000000, 0x3f800000, 0x3f800000, 0x00000000, 0x00000000, + 0x3f800000, 0x00000000, 0x00000000, 0x00000000, 0x3f800000, 0x3f800000}}, +}; + +/* + * fxc.exe /Tvs_3_0 + */ +#if 0 +struct {bool b; bool3 vb;} sb = {1, 1, 0, 1}; +struct {int n; int3 vn;} sn = {11, 12, 13, 14}; +struct {float f; float3 vf;} sf = {1.1f, 2.2f, 3.3f, 4.4f}; +struct {int nf; int3 vnf;} snf = {31, 32, 33, 34}; +struct {bool bf; bool3 vbf;} sbf = {1, 0, 0, 1}; +float4 main(float4 pos : POSITION) : POSITION +{ + float4 tmp = 0; + int i; + if (sb.vb.z) for (i = 0; i < sn.n; i++) tmp.x += pos.z * sf.vf.x * snf.vnf.z; + else for (i = 0; i < sn.vn.z; i++) tmp.y += pos.y * sf.vf.z * sbf.vbf.y; + return tmp; +} +#endif +static const DWORD registerset_blob_struct[] = +{ +0xfffe0300, 0x00a2fffe, 0x42415443, 0x0000001c, 0x00000253, 0xfffe0300, 0x00000005, 0x0000001c, +0x00000100, 0x0000024c, 0x00000080, 0x00000000, 0x00000004, 0x000000bc, 0x000000cc, 0x000000dc, +0x00040002, 0x00000002, 0x000000f8, 0x00000108, 0x00000128, 0x00000002, 0x00000002, 0x00000164, +0x00000174, 0x00000194, 0x00000001, 0x00000004, 0x000001d0, 0x000001e0, 0x00000200, 0x00020002, +0x00000002, 0x0000021c, 0x0000022c, 0x62006273, 0xababab00, 0x00010000, 0x00010001, 0x00000001, +0x00000000, 0xab006276, 0x00010001, 0x00030001, 0x00000001, 0x00000000, 0x00000083, 0x00000088, +0x00000098, 0x0000009c, 0x00000005, 0x00040001, 0x00020001, 0x000000ac, 0xffffffff, 0xffffffff, +0x00000000, 0xffffffff, 0x00666273, 0x76006662, 0xab006662, 0x000000e0, 0x00000088, 0x000000e3, +0x0000009c, 0x00000005, 0x00040001, 0x00020001, 0x000000e8, 0x3f800000, 0x00000000, 0x00000000, +0x00000000, 0x00000000, 0x00000000, 0x3f800000, 0x00000000, 0x66006673, 0xababab00, 0x00030000, +0x00010001, 0x00000001, 0x00000000, 0xab006676, 0x00030001, 0x00030001, 0x00000001, 0x00000000, +0x0000012b, 0x00000130, 0x00000140, 0x00000144, 0x00000005, 0x00040001, 0x00020001, 0x00000154, +0x3f8ccccd, 0x00000000, 0x00000000, 0x00000000, 0x400ccccd, 0x40533333, 0x408ccccd, 0x00000000, +0x6e006e73, 0xababab00, 0x00020000, 0x00010001, 0x00000001, 0x00000000, 0xab006e76, 0x00020001, +0x00030001, 0x00000001, 0x00000000, 0x00000197, 0x0000019c, 0x000001ac, 0x000001b0, 0x00000005, +0x00040001, 0x00020001, 0x000001c0, 0x0000000b, 0x00000000, 0x00000001, 0x00000000, 0x0000000c, +0x0000000d, 0x0000000e, 0x00000000, 0x00666e73, 0x7600666e, 0xab00666e, 0x00000204, 0x0000019c, +0x00000207, 0x000001b0, 0x00000005, 0x00040001, 0x00020001, 0x0000020c, 0x41f80000, 0x00000000, +0x00000000, 0x00000000, 0x42000000, 0x42040000, 0x42080000, 0x00000000, 0x335f7376, 0x4d00305f, +0x6f726369, 0x74666f73, 0x29522820, 0x534c4820, 0x6853204c, 0x72656461, 0x6d6f4320, 0x656c6970, +0x2e392072, 0x392e3932, 0x332e3235, 0x00313131, 0x05000051, 0xa00f0006, 0x00000000, 0x00000000, +0x00000000, 0x00000000, 0x0200001f, 0x80000000, 0x900f0000, 0x0200001f, 0x80000000, 0xe00f0000, +0x01000028, 0xe0e40803, 0x03000005, 0x80010000, 0xa0000001, 0x90aa0000, 0x02000001, 0x80010001, +0xa0000006, 0x01000026, 0xf0e40000, 0x04000004, 0x80010001, 0x80000000, 0xa0aa0003, 0x80000001, +0x00000027, 0x02000001, 0x80020001, 0xa0000006, 0x0000002a, 0x03000005, 0x80010000, 0xa0aa0001, +0x90550000, 0x02000001, 0x80020001, 0xa0000006, 0x01000026, 0xf0e40003, 0x04000004, 0x80020001, +0x80000000, 0xa0550005, 0x80550001, 0x00000027, 0x02000001, 0x80010001, 0xa0000006, 0x0000002b, +0x02000001, 0xe0030000, 0x80e40001, 0x02000001, 0xe00c0000, 0xa0000006, 0x0000ffff, +}; + +static const struct registerset_constants registerset_constants_struct_float[] = +{ + {"sf", {"sf", D3DXRS_FLOAT4, 0, 2, D3DXPC_STRUCT, D3DXPT_VOID, 1, 4, 1, 2, 16, NULL}, 93}, + {"sf.f", {"f", D3DXRS_FLOAT4, 0, 1, D3DXPC_SCALAR, D3DXPT_FLOAT, 1, 1, 1, 0, 4, NULL}, 93}, + {"sf.vf", {"vf", D3DXRS_FLOAT4, 1, 1, D3DXPC_VECTOR, D3DXPT_FLOAT, 1, 3, 1, 0, 12, NULL}, 97}, +}; + +static const struct registerset_test registerset_test_struct_float[] = +{ + {SetInt}, + {SetBool}, + {SetFloat}, + {SetIntArray, 1, 0, 3}, + {SetIntArray, 1, 4, REGISTER_OUTPUT_SIZE, 8, + {0x40000000, 0x00000000, 0x00000000, 0x00000000, 0x40400000, 0x40800000, 0x40a00000, 0x00000000}}, + {SetBoolArray, 1, 0, 3}, + {SetBoolArray, 1, 4, REGISTER_OUTPUT_SIZE, 8, + {0x3f800000, 0x00000000, 0x00000000, 0x00000000, 0x3f800000, 0x3f800000, 0x3f800000, 0x00000000}}, + {SetFloatArray, 0, 0, 3}, + {SetFloatArray, 0, 4, REGISTER_OUTPUT_SIZE, 8, + {0x40000123, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x40800123, 0x40a00123, 0x00000000}}, + {SetValue, 0, 0, 15}, + {SetValue, 0, 16, REGISTER_OUTPUT_SIZE * 4, 8, + {0x40000123, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x40800123, 0x40a00123, 0x00000000}}, + {SetVector, 0, 0, 0, 8, + {0x40000123, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x40800123, 0x40a00123, 0x00000000}}, + {SetVectorArray}, + {SetVectorArray, 0, 1, REGISTER_OUTPUT_SIZE / 4, 8, + {0x40000123, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x40800123, 0x40a00123, 0x00000000}}, + {SetMatrix, 0, 0, 0, 8, + {0x40000123, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x40800123, 0x40a00123, 0x00000000}}, + {SetMatrixArray}, + {SetMatrixArray, 0, 1, REGISTER_OUTPUT_SIZE / 16, 8, + {0x40000123, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x40800123, 0x40a00123, 0x00000000}}, + {SetMatrixTranspose, 0, 0, 0, 8, + {0x40000123, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000}}, + {SetMatrixTransposeArray}, + {SetMatrixTransposeArray, 0, 1, REGISTER_OUTPUT_SIZE / 16, 8, + {0x40000123, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000}}, + {SetMatrixPointerArray}, + {SetMatrixPointerArray, 0, 1, REGISTER_OUTPUT_SIZE / 16, 8, + {0x40000123, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000}}, + {SetMatrixTransposePointerArray}, + {SetMatrixTransposePointerArray, 0, 1, REGISTER_OUTPUT_SIZE / 16, 8, + {0x40000123, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000}}, +}; + +static const struct registerset_constants registerset_constants_struct_int[] = +{ + {"sn", {"sn", D3DXRS_INT4, 0, 4, D3DXPC_STRUCT, D3DXPT_VOID, 1, 4, 1, 2, 16, NULL}, 120}, + {"sn.n", {"n", D3DXRS_INT4, 0, 1, D3DXPC_SCALAR, D3DXPT_INT, 1, 1, 1, 0, 4, NULL}, 120}, + {"sn.vn", {"vn", D3DXRS_INT4, 1, 1, D3DXPC_VECTOR, D3DXPT_INT, 1, 3, 1, 0, 12, NULL}, 124}, +}; + +static const struct registerset_test registerset_test_struct_int[] = +{ + {SetInt}, + {SetBool}, + {SetFloat}, + {SetIntArray, 1, 0, 3}, + {SetIntArray, 1, 4, REGISTER_OUTPUT_SIZE, 8, + {0x00000002, 0x00000000, 0x00000001, 0x00000000, 0x00000003, 0x00000004, 0x00000005, 0x00000000}}, + {SetBoolArray, 1, 0, 3}, + {SetBoolArray, 1, 4, REGISTER_OUTPUT_SIZE, 8, + {0x00000001, 0x00000000, 0x00000001, 0x00000000, 0x00000001, 0x00000001, 0x00000001, 0x00000000}}, + {SetFloatArray, 0, 0, 3}, + {SetFloatArray, 0, 4, REGISTER_OUTPUT_SIZE, 8, + {0x00000002, 0x00000000, 0x00000001, 0x00000000, 0x00000000, 0x00000004, 0x00000005, 0x00000000}}, + {SetValue, 1, 0, 15}, + {SetValue, 1, 16, REGISTER_OUTPUT_SIZE * 4, 8, + {0x00000002, 0x00000000, 0x00000001, 0x00000000, 0x00000003, 0x00000004, 0x00000005, 0x00000000}}, + {SetVector, 0, 0, 0, 8, + {0x00000002, 0x00000000, 0x00000001, 0x00000000, 0x00000000, 0x00000004, 0x00000005, 0x00000000}}, + {SetVectorArray}, + {SetVectorArray, 0, 1, REGISTER_OUTPUT_SIZE / 4, 8, + {0x00000002, 0x00000000, 0x00000001, 0x00000000, 0x00000000, 0x00000004, 0x00000005, 0x00000000}}, + {SetMatrix, 0, 0, 0, 8, + {0x00000002, 0x00000000, 0x00000001, 0x00000000, 0x00000000, 0x00000004, 0x00000005, 0x00000000}}, + {SetMatrixArray}, + {SetMatrixArray, 0, 1, REGISTER_OUTPUT_SIZE / 16, 8, + {0x00000002, 0x00000000, 0x00000001, 0x00000000, 0x00000000, 0x00000004, 0x00000005, 0x00000000}}, + {SetMatrixTranspose, 0, 0, 0, 8, + {0x00000002, 0x00000000, 0x00000001, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000}}, + {SetMatrixTransposeArray}, + {SetMatrixTransposeArray, 0, 1, REGISTER_OUTPUT_SIZE / 16, 8, + {0x00000002, 0x00000000, 0x00000001, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000}}, + {SetMatrixPointerArray}, + {SetMatrixPointerArray, 0, 1, REGISTER_OUTPUT_SIZE / 16, 8, + {0x00000002, 0x00000000, 0x00000001, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000}}, + {SetMatrixTransposePointerArray}, + {SetMatrixTransposePointerArray, 0, 1, REGISTER_OUTPUT_SIZE / 16, 8, + {0x00000002, 0x00000000, 0x00000001, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000}}, +}; + +static const struct registerset_constants registerset_constants_struct_bool[] = +{ + {"sb", {"sb", D3DXRS_BOOL, 0, 4, D3DXPC_STRUCT, D3DXPT_VOID, 1, 4, 1, 2, 16, NULL}, 51}, + {"sb.b", {"b", D3DXRS_BOOL, 0, 1, D3DXPC_SCALAR, D3DXPT_BOOL, 1, 1, 1, 0, 4, NULL}, 51}, + {"sb.vb", {"vb", D3DXRS_BOOL, 1, 3, D3DXPC_VECTOR, D3DXPT_BOOL, 1, 3, 1, 0, 12, NULL}, 52}, +}; + +static const struct registerset_test registerset_test_struct_bool[] = +{ + {SetInt}, + {SetBool}, + {SetFloat}, + {SetIntArray, 1, 0, 3}, + {SetIntArray, 1, 4, REGISTER_OUTPUT_SIZE, 4, + {0x00000001, 0x00000001, 0x00000001, 0x00000001}}, + {SetBoolArray, 1, 0, 3}, + {SetBoolArray, 1, 4, REGISTER_OUTPUT_SIZE, 4, + {0x00000002, 0x00000003, 0x00000004, 0x00000005}}, + {SetFloatArray, 0, 0, 3}, + {SetFloatArray, 0, 4, REGISTER_OUTPUT_SIZE, 4, + {0x00000001, 0x00000000, 0x00000001, 0x00000001}}, + {SetValue, 1, 0, 15}, + {SetValue, 1, 16, REGISTER_OUTPUT_SIZE * 4, 4, + {0x00000002, 0x00000003, 0x00000004, 0x00000005}}, + {SetVector, 0, 0, 0, 4, + {0x00000001, 0x00000000, 0x00000001, 0x00000001}}, + {SetVectorArray}, + {SetVectorArray, 0, 1, REGISTER_OUTPUT_SIZE / 4, 4, + {0x00000001, 0x00000000, 0x00000001, 0x00000001}}, + {SetMatrix, 0, 0, 0, 4, + {0x00000001, 0x00000000, 0x00000001, 0x00000001}}, + {SetMatrixArray}, + {SetMatrixArray, 0, 1, REGISTER_OUTPUT_SIZE / 16, 4, + {0x00000001, 0x00000000, 0x00000001, 0x00000001}}, + {SetMatrixTranspose, 0, 0, 0, 4, + {0x00000001, 0x00000001, 0x00000001, 0x00000001}}, + {SetMatrixTransposeArray}, + {SetMatrixTransposeArray, 0, 1, REGISTER_OUTPUT_SIZE / 16, 4, + {0x00000001, 0x00000001, 0x00000001, 0x00000001}}, + {SetMatrixPointerArray}, + {SetMatrixPointerArray, 0, 1, REGISTER_OUTPUT_SIZE / 16, 4, + {0x00000001, 0x00000000, 0x00000001, 0x00000001}}, + {SetMatrixTransposePointerArray}, + {SetMatrixTransposePointerArray, 0, 1, REGISTER_OUTPUT_SIZE / 16, 4, + {0x00000001, 0x00000001, 0x00000001, 0x00000001}}, +}; + +static const struct registerset_constants registerset_constants_struct_int_float[] = +{ + {"snf", {"snf", D3DXRS_FLOAT4, 2, 2, D3DXPC_STRUCT, D3DXPT_VOID, 1, 4, 1, 2, 16, NULL}, 139}, + {"snf.nf", {"nf", D3DXRS_FLOAT4, 2, 1, D3DXPC_SCALAR, D3DXPT_INT, 1, 1, 1, 0, 4, NULL}, 139}, + {"snf.vnf", {"vnf", D3DXRS_FLOAT4, 3, 1, D3DXPC_VECTOR, D3DXPT_INT, 1, 3, 1, 0, 12, NULL}, 143}, +}; + +static const struct registerset_test registerset_test_struct_int_float[] = +{ + {SetInt}, + {SetBool}, + {SetFloat}, + {SetIntArray, 1, 0, 3}, + {SetIntArray, 1, 4, REGISTER_OUTPUT_SIZE, 8, + {0x40000000, 0x00000000, 0x00000000, 0x00000000, 0x40400000, 0x40800000, 0x40a00000, 0x00000000}}, + {SetBoolArray, 1, 0, 3}, + {SetBoolArray, 1, 4, REGISTER_OUTPUT_SIZE, 8, + {0x3f800000, 0x00000000, 0x00000000, 0x00000000, 0x3f800000, 0x3f800000, 0x3f800000, 0x00000000}}, + {SetFloatArray, 0, 0, 3}, + {SetFloatArray, 0, 4, REGISTER_OUTPUT_SIZE, 8, + {0x40000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x40800000, 0x40a00000, 0x00000000}}, + {SetValue, 1, 0, 15}, + {SetValue, 1, 16, REGISTER_OUTPUT_SIZE * 4, 8, + {0x40000000, 0x00000000, 0x00000000, 0x00000000, 0x40400000, 0x40800000, 0x40a00000, 0x00000000}}, + {SetVector, 0, 0, 0, 8, + {0x40000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x40800000, 0x40a00000, 0x00000000}}, + {SetVectorArray}, + {SetVectorArray, 0, 1, REGISTER_OUTPUT_SIZE / 4, 8, + {0x40000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x40800000, 0x40a00000, 0x00000000}}, + {SetMatrix, 0, 0, 0, 8, + {0x40000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x40800000, 0x40a00000, 0x00000000}}, + {SetMatrixArray}, + {SetMatrixArray, 0, 1, REGISTER_OUTPUT_SIZE / 16, 8, + {0x40000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x40800000, 0x40a00000, 0x00000000}}, + {SetMatrixTranspose, 0, 0, 0, 8, + {0x40000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000}}, + {SetMatrixTransposeArray}, + {SetMatrixTransposeArray, 0, 1, REGISTER_OUTPUT_SIZE / 16, 8, + {0x40000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000}}, + {SetMatrixPointerArray}, + {SetMatrixPointerArray, 0, 1, REGISTER_OUTPUT_SIZE / 16, 8, + {0x40000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000}}, + {SetMatrixTransposePointerArray}, + {SetMatrixTransposePointerArray, 0, 1, REGISTER_OUTPUT_SIZE / 16, 8, + {0x40000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000}}, +}; + +static const struct registerset_constants registerset_constants_struct_bool_float[] = +{ + {"sbf", {"sbf", D3DXRS_FLOAT4, 4, 2, D3DXPC_STRUCT, D3DXPT_VOID, 1, 4, 1, 2, 16, NULL}, 66}, + {"sbf.bf", {"bf", D3DXRS_FLOAT4, 4, 1, D3DXPC_SCALAR, D3DXPT_BOOL, 1, 1, 1, 0, 4, NULL}, 66}, + {"sbf.vbf", {"vbf", D3DXRS_FLOAT4, 5, 1, D3DXPC_VECTOR, D3DXPT_BOOL, 1, 3, 1, 0, 12, NULL}, 70}, +}; + +static const struct registerset_test registerset_test_struct_bool_float[] = +{ + {SetInt}, + {SetBool}, + {SetFloat}, + {SetIntArray, 1, 0, 3}, + {SetIntArray, 1, 4, REGISTER_OUTPUT_SIZE, 8, + {0x3f800000, 0x00000000, 0x00000000, 0x00000000, 0x3f800000, 0x3f800000, 0x3f800000, 0x00000000}}, + {SetBoolArray, 1, 0, 3}, + {SetBoolArray, 1, 4, REGISTER_OUTPUT_SIZE, 8, + {0x3f800000, 0x00000000, 0x00000000, 0x00000000, 0x3f800000, 0x3f800000, 0x3f800000, 0x00000000}}, + {SetFloatArray, 0, 0, 3}, + {SetFloatArray, 0, 4, REGISTER_OUTPUT_SIZE, 8, + {0x3f800000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x3f800000, 0x3f800000, 0x00000000}}, + {SetValue, 1, 0, 15}, + {SetValue, 1, 16, REGISTER_OUTPUT_SIZE * 4, 8, + {0x3f800000, 0x00000000, 0x00000000, 0x00000000, 0x3f800000, 0x3f800000, 0x3f800000, 0x00000000}}, + {SetVector, 0, 0, 0, 8, + {0x3f800000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x3f800000, 0x3f800000, 0x00000000}}, + {SetVectorArray}, + {SetVectorArray, 0, 1, REGISTER_OUTPUT_SIZE / 4, 8, + {0x3f800000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x3f800000, 0x3f800000, 0x00000000}}, + {SetMatrix, 0, 0, 0, 8, + {0x3f800000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x3f800000, 0x3f800000, 0x00000000}}, + {SetMatrixArray}, + {SetMatrixArray, 0, 1, REGISTER_OUTPUT_SIZE / 16, 8, + {0x3f800000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x3f800000, 0x3f800000, 0x00000000}}, + {SetMatrixTranspose, 0, 0, 0, 8, + {0x3f800000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000}}, + {SetMatrixTransposeArray}, + {SetMatrixTransposeArray, 0, 1, REGISTER_OUTPUT_SIZE / 16, 8, + {0x3f800000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000}}, + {SetMatrixPointerArray}, + {SetMatrixPointerArray, 0, 1, REGISTER_OUTPUT_SIZE / 16, 8, + {0x3f800000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000}}, + {SetMatrixTransposePointerArray}, + {SetMatrixTransposePointerArray, 0, 1, REGISTER_OUTPUT_SIZE / 16, 8, + {0x3f800000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000}}, +}; + +/* + * fxc.exe /Tvs_3_0 + */ +#if 0 +struct {bool b; bool3 vb;} sab[2] = {1, 1, 0, 1, 0, 1, 0, 1}; +struct {int n; int3 vn;} san[2] = {21, 22, 23, 24, 25, 26, 27, 28}; +struct {float f; float3 vf;} saf[2] = {1.1f, 2.1f, 3.1f, 4.1f, 5.1f, 6.1f, 7.1f, 8.1f}; +struct {int nf; int3 vnf;} sanf[2] = {41, 0, 43, 44, 41, 42, 43, 44}; +struct {bool bf; bool3 vbf;} sabf[2] = {1, 0, 0, 1, 1, 1, 0, 1}; +float4 main(float4 pos : POSITION) : POSITION +{ + float4 tmp = 0; + int i; + if (sab[1].vb.z) for (i = 0; i < san[1].n; i++) tmp.x += pos.z * saf[1].vf.x * sanf[1].vnf.z; + else for (i = 0; i < san[1].vn.z; i++) tmp.y += pos.y * saf[1].vf.z * sabf[1].vbf.y; + return tmp; +} +#endif +static const DWORD registerset_blob_struct_array[] = +{ +0xfffe0300, 0x00c6fffe, 0x42415443, 0x0000001c, 0x000002e3, 0xfffe0300, 0x00000005, 0x0000001c, +0x00000100, 0x000002dc, 0x00000080, 0x00000000, 0x00000008, 0x000000bc, 0x000000cc, 0x000000ec, +0x00080002, 0x00000004, 0x00000108, 0x00000118, 0x00000158, 0x00000002, 0x00000004, 0x00000194, +0x000001a4, 0x000001e4, 0x00000001, 0x00000008, 0x00000220, 0x00000230, 0x00000270, 0x00040002, +0x00000004, 0x0000028c, 0x0000029c, 0x00626173, 0xabab0062, 0x00010000, 0x00010001, 0x00000001, +0x00000000, 0xab006276, 0x00010001, 0x00030001, 0x00000001, 0x00000000, 0x00000084, 0x00000088, +0x00000098, 0x0000009c, 0x00000005, 0x00040001, 0x00020002, 0x000000ac, 0xffffffff, 0xffffffff, +0x00000000, 0xffffffff, 0x00000000, 0xffffffff, 0x00000000, 0xffffffff, 0x66626173, 0x00666200, +0x00666276, 0x000000f1, 0x00000088, 0x000000f4, 0x0000009c, 0x00000005, 0x00040001, 0x00020002, +0x000000f8, 0x3f800000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x3f800000, +0x00000000, 0x3f800000, 0x00000000, 0x00000000, 0x00000000, 0x3f800000, 0x00000000, 0x3f800000, +0x00000000, 0x00666173, 0xabab0066, 0x00030000, 0x00010001, 0x00000001, 0x00000000, 0xab006676, +0x00030001, 0x00030001, 0x00000001, 0x00000000, 0x0000015c, 0x00000160, 0x00000170, 0x00000174, +0x00000005, 0x00040001, 0x00020002, 0x00000184, 0x3f8ccccd, 0x00000000, 0x00000000, 0x00000000, +0x40066666, 0x40466666, 0x40833333, 0x00000000, 0x40a33333, 0x00000000, 0x00000000, 0x00000000, +0x40c33333, 0x40e33333, 0x4101999a, 0x00000000, 0x006e6173, 0xabab006e, 0x00020000, 0x00010001, +0x00000001, 0x00000000, 0xab006e76, 0x00020001, 0x00030001, 0x00000001, 0x00000000, 0x000001e8, +0x000001ec, 0x000001fc, 0x00000200, 0x00000005, 0x00040001, 0x00020002, 0x00000210, 0x00000015, +0x00000000, 0x00000001, 0x00000000, 0x00000016, 0x00000017, 0x00000018, 0x00000000, 0x00000019, +0x00000000, 0x00000001, 0x00000000, 0x0000001a, 0x0000001b, 0x0000001c, 0x00000000, 0x666e6173, +0x00666e00, 0x00666e76, 0x00000275, 0x000001ec, 0x00000278, 0x00000200, 0x00000005, 0x00040001, +0x00020002, 0x0000027c, 0x42240000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x422c0000, +0x42300000, 0x00000000, 0x42240000, 0x00000000, 0x00000000, 0x00000000, 0x42280000, 0x422c0000, +0x42300000, 0x00000000, 0x335f7376, 0x4d00305f, 0x6f726369, 0x74666f73, 0x29522820, 0x534c4820, +0x6853204c, 0x72656461, 0x6d6f4320, 0x656c6970, 0x2e392072, 0x392e3932, 0x332e3235, 0x00313131, +0x05000051, 0xa00f000c, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x0200001f, 0x80000000, +0x900f0000, 0x0200001f, 0x80000000, 0xe00f0000, 0x01000028, 0xe0e40807, 0x03000005, 0x80010000, +0xa0000003, 0x90aa0000, 0x02000001, 0x80010001, 0xa000000c, 0x01000026, 0xf0e40004, 0x04000004, +0x80010001, 0x80000000, 0xa0aa0007, 0x80000001, 0x00000027, 0x02000001, 0x80020001, 0xa000000c, +0x0000002a, 0x03000005, 0x80010000, 0xa0aa0003, 0x90550000, 0x02000001, 0x80020001, 0xa000000c, +0x01000026, 0xf0e40007, 0x04000004, 0x80020001, 0x80000000, 0xa055000b, 0x80550001, 0x00000027, +0x02000001, 0x80010001, 0xa000000c, 0x0000002b, 0x02000001, 0xe0030000, 0x80e40001, 0x02000001, +0xe00c0000, 0xa000000c, 0x0000ffff, +}; + +static const struct registerset_constants registerset_constants_struct_array_float[] = +{ + {"saf", {"saf", D3DXRS_FLOAT4, 0, 4, D3DXPC_STRUCT, D3DXPT_VOID, 1, 4, 2, 2, 32, NULL}, 105}, + {"saf[0]", {"saf", D3DXRS_FLOAT4, 0, 2, D3DXPC_STRUCT, D3DXPT_VOID, 1, 4, 1, 2, 16, NULL}, 105}, + {"saf[0].f", {"f", D3DXRS_FLOAT4, 0, 1, D3DXPC_SCALAR, D3DXPT_FLOAT, 1, 1, 1, 0, 4, NULL}, 105}, + {"saf[0].vf", {"vf", D3DXRS_FLOAT4, 1, 1, D3DXPC_VECTOR, D3DXPT_FLOAT, 1, 3, 1, 0, 12, NULL}, 109}, + {"saf[1]", {"saf", D3DXRS_FLOAT4, 2, 2, D3DXPC_STRUCT, D3DXPT_VOID, 1, 4, 1, 2, 16, NULL}, 113}, + {"saf[1].f", {"f", D3DXRS_FLOAT4, 2, 1, D3DXPC_SCALAR, D3DXPT_FLOAT, 1, 1, 1, 0, 4, NULL}, 113}, + {"saf[1].vf", {"vf", D3DXRS_FLOAT4, 3, 1, D3DXPC_VECTOR, D3DXPT_FLOAT, 1, 3, 1, 0, 12, NULL}, 117}, +}; + +static const struct registerset_test registerset_test_struct_array_float[] = +{ + {SetInt}, + {SetBool}, + {SetFloat}, + {SetIntArray, 1, 0, 3}, + {SetIntArray, 1, 4, 7, 8, + {0x40000000, 0x00000000, 0x00000000, 0x00000000, 0x40400000, 0x40800000, 0x40a00000, 0x00000000}}, + {SetIntArray, 1, 8, REGISTER_OUTPUT_SIZE, 8, + {0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x40e00000, 0x41000000, 0x41100000, 0x00000000}}, + {SetBoolArray, 1, 0, 3}, + {SetBoolArray, 1, 4, 7, 8, + {0x3f800000, 0x00000000, 0x00000000, 0x00000000, 0x3f800000, 0x3f800000, 0x3f800000, 0x00000000}}, + {SetBoolArray, 1, 8, REGISTER_OUTPUT_SIZE, 8, + {0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x3f800000, 0x3f800000, 0x3f800000, 0x00000000}}, + {SetFloatArray, 0, 0, 3}, + {SetFloatArray, 0, 4, 7, 8, + {0x40000123, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x40800123, 0x40a00123, 0x00000000}}, + {SetFloatArray, 0, 8, REGISTER_OUTPUT_SIZE, 8, + {0x40c00123, 0x00000000, 0x00000000, 0x00000000, 0x40e00123, 0x41000123, 0x41100123, 0x00000000}}, + {SetValue, 0, 0, 15}, + {SetValue, 0, 16, 31, 8, + {0x40000123, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x40800123, 0x40a00123, 0x00000000}}, + {SetValue, 0, 32, REGISTER_OUTPUT_SIZE * 4, 8, + {0x40c00123, 0x00000000, 0x00000000, 0x00000000, 0x40e00123, 0x41000123, 0x41100123, 0x00000000}}, + {SetVector, 0, 0, 0, 8, + {0x40000123, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x40800123, 0x40a00123, 0x00000000}}, + {SetVectorArray}, + {SetVectorArray, 0, 1, 1, 8, + {0x40000123, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x40800123, 0x40a00123, 0x00000000}}, + {SetVectorArray, 0, 2, REGISTER_OUTPUT_SIZE / 4, 8, + {0x40c00123, 0x00000000, 0x00000000, 0x00000000, 0x40e00123, 0x41000123, 0x41100123, 0x00000000}}, + {SetMatrix, 0, 0, 0, 8, + {0x40c00123, 0x00000000, 0x00000000, 0x00000000, 0x40e00123, 0x41000123, 0x41100123, 0x00000000}}, + {SetMatrixArray}, + {SetMatrixArray, 0, 1, REGISTER_OUTPUT_SIZE / 16, 8, + {0x40c00123, 0x00000000, 0x00000000, 0x00000000, 0x40e00123, 0x41000123, 0x41100123, 0x00000000}}, + {SetMatrixTranspose, 0, 0, 0, 8, + {0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000}}, + {SetMatrixTransposeArray}, + {SetMatrixTransposeArray, 0, 1, REGISTER_OUTPUT_SIZE / 16, 8, + {0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000}}, + {SetMatrixPointerArray}, + {SetMatrixPointerArray, 0, 1, REGISTER_OUTPUT_SIZE / 16, 8}, + {SetMatrixTransposePointerArray}, + {SetMatrixTransposePointerArray, 0, 1, REGISTER_OUTPUT_SIZE / 16, 8}, +}; + +static const struct registerset_constants registerset_constants_struct_array_int[] = +{ + {"san", {"san", D3DXRS_INT4, 0, 8, D3DXPC_STRUCT, D3DXPT_VOID, 1, 4, 2, 2, 32, NULL}, 140}, + {"san[0]", {"san", D3DXRS_INT4, 0, 2, D3DXPC_STRUCT, D3DXPT_VOID, 1, 4, 1, 2, 16, NULL}, 140}, + {"san[0].n", {"n", D3DXRS_INT4, 0, 1, D3DXPC_SCALAR, D3DXPT_INT, 1, 1, 1, 0, 4, NULL}, 140}, + {"san[0].vn", {"vn", D3DXRS_INT4, 1, 1, D3DXPC_VECTOR, D3DXPT_INT, 1, 3, 1, 0, 12, NULL}, 144}, + {"san[1]", {"san", D3DXRS_INT4, 2, 2, D3DXPC_STRUCT, D3DXPT_VOID, 1, 4, 1, 2, 16, NULL}, 148}, + {"san[1].n", {"n", D3DXRS_INT4, 2, 1, D3DXPC_SCALAR, D3DXPT_INT, 1, 1, 1, 0, 4, NULL}, 148}, + {"san[1].vn", {"vn", D3DXRS_INT4, 3, 1, D3DXPC_VECTOR, D3DXPT_INT, 1, 3, 1, 0, 12, NULL}, 152}, +}; + +static const struct registerset_test registerset_test_struct_array_int[] = +{ + {SetInt}, + {SetBool}, + {SetFloat}, + {SetIntArray, 1, 0, 3}, + {SetIntArray, 1, 4, 7, 8, + {0x00000002, 0x00000000, 0x00000001, 0x00000000, 0x00000003, 0x00000004, 0x00000005, 0x00000000}}, + {SetIntArray, 1, 8, REGISTER_OUTPUT_SIZE, 8, + {0x00000000, 0x00000000, 0x00000001, 0x00000000, 0x00000007, 0x00000008, 0x00000009, 0x00000000}}, + {SetBoolArray, 1, 0, 3}, + {SetBoolArray, 1, 4, 7, 8, + {0x00000001, 0x00000000, 0x00000001, 0x00000000, 0x00000001, 0x00000001, 0x00000001, 0x00000000}}, + {SetBoolArray, 1, 8, REGISTER_OUTPUT_SIZE, 8, + {0x00000000, 0x00000000, 0x00000001, 0x00000000, 0x00000001, 0x00000001, 0x00000001, 0x00000000}}, + {SetFloatArray, 0, 0, 3}, + {SetFloatArray, 0, 4, 7, 8, + {0x00000002, 0x00000000, 0x00000001, 0x00000000, 0x00000000, 0x00000004, 0x00000005, 0x00000000}}, + {SetFloatArray, 0, 8, REGISTER_OUTPUT_SIZE, 8, + {0x00000006, 0x00000000, 0x00000001, 0x00000000, 0x00000007, 0x00000008, 0x00000009, 0x00000000}}, + {SetValue, 1, 0, 15}, + {SetValue, 1, 16, 31, 8, + {0x00000002, 0x00000000, 0x00000001, 0x00000000, 0x00000003, 0x00000004, 0x00000005, 0x00000000}}, + {SetValue, 1, 32, REGISTER_OUTPUT_SIZE * 4, 8, + {0x00000000, 0x00000000, 0x00000001, 0x00000000, 0x00000007, 0x00000008, 0x00000009, 0x00000000}}, + {SetVector, 0, 0, 0, 8, + {0x00000002, 0x00000000, 0x00000001, 0x00000000, 0x00000000, 0x00000004, 0x00000005, 0x00000000}}, + {SetVectorArray}, + {SetVectorArray, 0, 1, 1, 8, + {0x00000002, 0x00000000, 0x00000001, 0x00000000, 0x00000000, 0x00000004, 0x00000005, 0x00000000}}, + {SetVectorArray, 0, 2, REGISTER_OUTPUT_SIZE / 4, 8, + {0x00000006, 0x00000000, 0x00000001, 0x00000000, 0x00000007, 0x00000008, 0x00000009, 0x00000000}}, + {SetMatrix, 0, 0, 0, 8, + {0x00000006, 0x00000000, 0x00000001, 0x00000000, 0x00000007, 0x00000008, 0x00000009, 0x00000000},}, + {SetMatrixArray}, + {SetMatrixArray, 0, 1, REGISTER_OUTPUT_SIZE / 16, 8, + {0x00000006, 0x00000000, 0x00000001, 0x00000000, 0x00000007, 0x00000008, 0x00000009, 0x00000000}}, + {SetMatrixTranspose, 0, 0, 0, 8, + {0x00000000, 0x00000000, 0x00000001, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000}}, + {SetMatrixTransposeArray}, + {SetMatrixTransposeArray, 0, 1, REGISTER_OUTPUT_SIZE / 16, 8, + {0x00000000, 0x00000000, 0x00000001, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000}}, + {SetMatrixPointerArray}, + {SetMatrixPointerArray, 0, 1, REGISTER_OUTPUT_SIZE / 16, 8, + {0x00000000, 0x00000000, 0x00000001, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000}}, + {SetMatrixTransposePointerArray}, + {SetMatrixTransposePointerArray, 0, 1, REGISTER_OUTPUT_SIZE / 16, 8, + {0x00000000, 0x00000000, 0x00000001, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000}}, +}; + +static const struct registerset_constants registerset_constants_struct_array_bool[] = +{ + {"sab", {"sab", D3DXRS_BOOL, 0, 8, D3DXPC_STRUCT, D3DXPT_VOID, 1, 4, 2, 2, 32, NULL}, 51}, + {"sab[0]", {"sab", D3DXRS_BOOL, 0, 4, D3DXPC_STRUCT, D3DXPT_VOID, 1, 4, 1, 2, 16, NULL}, 51}, + {"sab[0].b", {"b", D3DXRS_BOOL, 0, 1, D3DXPC_SCALAR, D3DXPT_BOOL, 1, 1, 1, 0, 4, NULL}, 51}, + {"sab[0].vb", {"vb", D3DXRS_BOOL, 1, 3, D3DXPC_VECTOR, D3DXPT_BOOL, 1, 3, 1, 0, 12, NULL}, 52}, + {"sab[1]", {"sab", D3DXRS_BOOL, 4, 4, D3DXPC_STRUCT, D3DXPT_VOID, 1, 4, 1, 2, 16, NULL}, 55}, + {"sab[1].b", {"b", D3DXRS_BOOL, 4, 1, D3DXPC_SCALAR, D3DXPT_BOOL, 1, 1, 1, 0, 4, NULL}, 55}, + {"sab[1].vb", {"vb", D3DXRS_BOOL, 5, 3, D3DXPC_VECTOR, D3DXPT_BOOL, 1, 3, 1, 0, 12, NULL}, 56}, +}; + +static const struct registerset_test registerset_test_struct_array_bool[] = +{ + {SetInt}, + {SetBool}, + {SetFloat}, + {SetIntArray, 1, 0, 3}, + {SetIntArray, 1, 4, 7, 4, + {0x00000001, 0x00000001, 0x00000001, 0x00000001}}, + {SetIntArray, 1, 8, REGISTER_OUTPUT_SIZE, 4, + {0x00000000, 0x00000001, 0x00000001, 0x00000001}}, + {SetBoolArray, 1, 0, 3}, + {SetBoolArray, 1, 4, 7, 4, + {0x00000002, 0x00000003, 0x00000004, 0x00000005}}, + {SetBoolArray, 1, 8, REGISTER_OUTPUT_SIZE, 4, + {0x00000000, 0x00000007, 0x00000008, 0x00000009}}, + {SetFloatArray, 0, 0, 3}, + {SetFloatArray, 0, 4, 7, 4, + {0x00000001, 0x00000000, 0x00000001, 0x00000001}}, + {SetFloatArray, 0, 8, REGISTER_OUTPUT_SIZE, 4, + {0x00000001, 0x00000001, 0x00000001, 0x00000001}}, + {SetValue, 1, 0, 15}, + {SetValue, 1, 16, 31, 4, + {0x00000002, 0x00000003, 0x00000004, 0x00000005}}, + {SetValue, 1, 32, REGISTER_OUTPUT_SIZE * 4, 4, + {0x00000000, 0x00000007, 0x00000008, 0x00000009}}, + {SetVector, 0, 0, 0, 4, + {0x00000001, 0x00000000, 0x00000001, 0x00000001}}, + {SetVectorArray}, + {SetVectorArray, 0, 1, 1, 4, + {0x00000001, 0x00000000, 0x00000001, 0x00000001}}, + {SetVectorArray, 0, 2, REGISTER_OUTPUT_SIZE / 4, 4, + {0x00000001, 0x00000001, 0x00000001, 0x00000001}}, + {SetMatrix, 0, 0, 0, 4, + {0x00000001, 0x00000001, 0x00000001, 0x00000001}}, + {SetMatrixArray}, + {SetMatrixArray, 0, 1, REGISTER_OUTPUT_SIZE / 16, 4, + {0x00000001, 0x00000001, 0x00000001, 0x00000001}}, + {SetMatrixTranspose, 0, 0, 0, 4, + {0x00000000, 0x00000001, 0x00000001, 0x00000001}}, + {SetMatrixTransposeArray}, + {SetMatrixTransposeArray, 0, 1, REGISTER_OUTPUT_SIZE / 16, 4, + {0x00000000, 0x00000001, 0x00000001, 0x00000001}}, + {SetMatrixPointerArray}, + {SetMatrixPointerArray, 0, 1, REGISTER_OUTPUT_SIZE / 16, 4, + {0x00000001, 0x00000001, 0x00000001, 0x00000001}}, + {SetMatrixTransposePointerArray}, + {SetMatrixTransposePointerArray, 0, 1, REGISTER_OUTPUT_SIZE / 16, 4, + {0x00000000, 0x00000001, 0x00000001, 0x00000001}}, +}; + +static const struct registerset_constants registerset_constants_struct_array_int_float[] = +{ + {"sanf", {"sanf", D3DXRS_FLOAT4, 4, 4, D3DXPC_STRUCT, D3DXPT_VOID, 1, 4, 2, 2, 32, NULL}, 167}, + {"sanf[0]", {"sanf", D3DXRS_FLOAT4, 4, 2, D3DXPC_STRUCT, D3DXPT_VOID, 1, 4, 1, 2, 16, NULL}, 167}, + {"sanf[0].nf", {"nf", D3DXRS_FLOAT4, 4, 1, D3DXPC_SCALAR, D3DXPT_INT, 1, 1, 1, 0, 4, NULL}, 167}, + {"sanf[0].vnf", {"vnf", D3DXRS_FLOAT4, 5, 1, D3DXPC_VECTOR, D3DXPT_INT, 1, 3, 1, 0, 12, NULL}, 171}, + {"sanf[1]", {"sanf", D3DXRS_FLOAT4, 6, 2, D3DXPC_STRUCT, D3DXPT_VOID, 1, 4, 1, 2, 16, NULL}, 175}, + {"sanf[1].nf", {"nf", D3DXRS_FLOAT4, 6, 1, D3DXPC_SCALAR, D3DXPT_INT, 1, 1, 1, 0, 4, NULL}, 175}, + {"sanf[1].vnf", {"vnf", D3DXRS_FLOAT4, 7, 1, D3DXPC_VECTOR, D3DXPT_INT, 1, 3, 1, 0, 12, NULL}, 179}, +}; + +static const struct registerset_test registerset_test_struct_array_int_float[] = +{ + {SetInt}, + {SetBool}, + {SetFloat}, + {SetIntArray, 1, 0, 3}, + {SetIntArray, 1, 4, 7, 8, + {0x40000000, 0x00000000, 0x00000000, 0x00000000, 0x40400000, 0x40800000, 0x40a00000, 0x00000000}}, + {SetIntArray, 1, 8, REGISTER_OUTPUT_SIZE, 8, + {0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x40e00000, 0x41000000, 0x41100000, 0x00000000}}, + {SetBoolArray, 1, 0, 3}, + {SetBoolArray, 1, 4, 7, 8, + {0x3f800000, 0x00000000, 0x00000000, 0x00000000, 0x3f800000, 0x3f800000, 0x3f800000, 0x00000000}}, + {SetBoolArray, 1, 8, REGISTER_OUTPUT_SIZE, 8, + {0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x3f800000, 0x3f800000, 0x3f800000, 0x00000000}}, + {SetFloatArray, 0, 0, 3}, + {SetFloatArray, 0, 4, 7, 8, + {0x40000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x40800000, 0x40a00000, 0x00000000}}, + {SetFloatArray, 0, 8, REGISTER_OUTPUT_SIZE, 8, + {0x40c00000, 0x00000000, 0x00000000, 0x00000000, 0x40e00000, 0x41000000, 0x41100000, 0x00000000}}, + {SetValue, 1, 0, 15}, + {SetValue, 1, 16, 31, 8, + {0x40000000, 0x00000000, 0x00000000, 0x00000000, 0x40400000, 0x40800000, 0x40a00000, 0x00000000}}, + {SetValue, 1, 32, REGISTER_OUTPUT_SIZE * 4, 8, + {0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x40e00000, 0x41000000, 0x41100000, 0x00000000}}, + {SetVector, 0, 0, 0, 8, + {0x40000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x40800000, 0x40a00000, 0x00000000}}, + {SetVectorArray}, + {SetVectorArray, 0, 1, 1, 8, + {0x40000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x40800000, 0x40a00000, 0x00000000}}, + {SetVectorArray, 0, 2, REGISTER_OUTPUT_SIZE / 4, 8, + {0x40c00000, 0x00000000, 0x00000000, 0x00000000, 0x40e00000, 0x41000000, 0x41100000, 0x00000000}}, + {SetMatrix, 0, 0, 0, 8, + {0x40c00000, 0x00000000, 0x00000000, 0x00000000, 0x40e00000, 0x41000000, 0x41100000, 0x00000000}}, + {SetMatrixArray}, + {SetMatrixArray, 0, 1, REGISTER_OUTPUT_SIZE / 16, 8, + {0x40c00000, 0x00000000, 0x00000000, 0x00000000, 0x40e00000, 0x41000000, 0x41100000, 0x00000000}}, + {SetMatrixTranspose, 0, 0, 0, 8, + {0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000}}, + {SetMatrixTransposeArray}, + {SetMatrixTransposeArray, 0, 1, REGISTER_OUTPUT_SIZE / 16, 8, + {0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000}}, + {SetMatrixPointerArray}, + {SetMatrixPointerArray, 0, 1, REGISTER_OUTPUT_SIZE / 16, 8}, + {SetMatrixTransposePointerArray}, + {SetMatrixTransposePointerArray, 0, 1, REGISTER_OUTPUT_SIZE / 16, 8}, +}; + +static const struct registerset_constants registerset_constants_struct_array_bool_float[] = +{ + {"sabf", {"sabf", D3DXRS_FLOAT4, 8, 4, D3DXPC_STRUCT, D3DXPT_VOID, 1, 4, 2, 2, 32, NULL}, 70}, + {"sabf[0]", {"sabf", D3DXRS_FLOAT4, 8, 2, D3DXPC_STRUCT, D3DXPT_VOID, 1, 4, 1, 2, 16, NULL}, 70}, + {"sabf[0].bf", {"bf", D3DXRS_FLOAT4, 8, 1, D3DXPC_SCALAR, D3DXPT_BOOL, 1, 1, 1, 0, 4, NULL}, 70}, + {"sabf[0].vbf", {"vbf", D3DXRS_FLOAT4, 9, 1, D3DXPC_VECTOR, D3DXPT_BOOL, 1, 3, 1, 0, 12, NULL}, 74}, + {"sabf[1]", {"sabf", D3DXRS_FLOAT4, 10, 2, D3DXPC_STRUCT, D3DXPT_VOID, 1, 4, 1, 2, 16, NULL}, 78}, + {"sabf[1].bf", {"bf", D3DXRS_FLOAT4, 10, 1, D3DXPC_SCALAR, D3DXPT_BOOL, 1, 1, 1, 0, 4, NULL}, 78}, + {"sabf[1].vbf", {"vbf", D3DXRS_FLOAT4, 11, 1, D3DXPC_VECTOR, D3DXPT_BOOL, 1, 3, 1, 0, 12, NULL}, 82}, +}; + +static const struct registerset_test registerset_test_struct_array_bool_float[] = +{ + {SetInt}, + {SetBool}, + {SetFloat}, + {SetIntArray, 1, 0, 3}, + {SetIntArray, 1, 4, 7, 8, + {0x3f800000, 0x00000000, 0x00000000, 0x00000000, 0x3f800000, 0x3f800000, 0x3f800000, 0x00000000}}, + {SetIntArray, 1, 8, REGISTER_OUTPUT_SIZE, 8, + {0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x3f800000, 0x3f800000, 0x3f800000, 0x00000000}}, + {SetBoolArray, 1, 0, 3}, + {SetBoolArray, 1, 4, 7, 8, + {0x3f800000, 0x00000000, 0x00000000, 0x00000000, 0x3f800000, 0x3f800000, 0x3f800000, 0x00000000}}, + {SetBoolArray, 1, 8, REGISTER_OUTPUT_SIZE, 8, + {0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x3f800000, 0x3f800000, 0x3f800000, 0x00000000}}, + {SetFloatArray, 0, 0, 3}, + {SetFloatArray, 0, 4, 7, 8, + {0x3f800000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x3f800000, 0x3f800000, 0x00000000}}, + {SetFloatArray, 0, 8, REGISTER_OUTPUT_SIZE, 8, + {0x3f800000, 0x00000000, 0x00000000, 0x00000000, 0x3f800000, 0x3f800000, 0x3f800000, 0x00000000}}, + {SetValue, 1, 0, 15}, + {SetValue, 1, 16, 31, 8, + {0x3f800000, 0x00000000, 0x00000000, 0x00000000, 0x3f800000, 0x3f800000, 0x3f800000, 0x00000000}}, + {SetValue, 1, 32, REGISTER_OUTPUT_SIZE * 4, 8, + {0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x3f800000, 0x3f800000, 0x3f800000, 0x00000000}}, + {SetVector, 0, 0, 0, 8, + {0x3f800000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x3f800000, 0x3f800000, 0x00000000}}, + {SetVectorArray}, + {SetVectorArray, 0, 1, 1, 8, + {0x3f800000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x3f800000, 0x3f800000, 0x00000000}}, + {SetVectorArray, 0, 2, REGISTER_OUTPUT_SIZE / 4, 8, + {0x3f800000, 0x00000000, 0x00000000, 0x00000000, 0x3f800000, 0x3f800000, 0x3f800000, 0x00000000}}, + {SetMatrix, 0, 0, 0, 8, + {0x3f800000, 0x00000000, 0x00000000, 0x00000000, 0x3f800000, 0x3f800000, 0x3f800000, 0x00000000}}, + {SetMatrixArray}, + {SetMatrixArray, 0, 1, REGISTER_OUTPUT_SIZE / 16, 8, + {0x3f800000, 0x00000000, 0x00000000, 0x00000000, 0x3f800000, 0x3f800000, 0x3f800000, 0x00000000}}, + {SetMatrixTranspose, 0, 0, 0, 8, + {0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000}}, + {SetMatrixTransposeArray}, + {SetMatrixTransposeArray, 0, 1, REGISTER_OUTPUT_SIZE / 16, 8, + {0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000}}, + {SetMatrixPointerArray}, + {SetMatrixPointerArray, 0, 1, REGISTER_OUTPUT_SIZE / 16, 8}, + {SetMatrixTransposePointerArray}, + {SetMatrixTransposePointerArray, 0, 1, REGISTER_OUTPUT_SIZE / 16, 8}, +}; + +/* + * fxc.exe /Tvs_3_0 + */ +#if 0 +struct {bool b; struct {bool b; bool3 vb;} s; bool b1;} ssb = {1, 1, 0, 1, 1, 0}; +struct {int n; struct {int n; int3 vn;} s; int n1;} ssn = {71, 72, 73, 74, 75, 76}; +struct {float f; struct {float f; float3 vf;} s; float f1;} ssf = {1.1f, 2.1f, 3.1f, 4.1f, 5.1f, 6.1f}; +struct {int nf; struct {int nf; int3 vnf;} s; int nf1;} ssnf = {41, 0, 43, 44, 41, 42}; +struct {bool bf; struct {bool bf; bool3 vbf;} s; bool bf1;} ssbf = {1, 0, 0, 1, 1, 0}; +float4 main(float4 pos : POSITION) : POSITION +{ + float4 tmp = 0; + int i; + if (ssb.b1) for (i = 0; i < ssn.n1; i++) tmp.x += pos.z * ssf.f1 * ssnf.nf1; + else for (i = 0; i < ssn.s.vn.z; i++) tmp.y += pos.y * ssf.s.vf.z * ssbf.bf1; + return tmp; +} +#endif +static const DWORD registerset_blob_struct_struct[] = +{ +0xfffe0300, 0x00fcfffe, 0x42415443, 0x0000001c, 0x000003bb, 0xfffe0300, 0x00000005, 0x0000001c, +0x00000100, 0x000003b4, 0x00000080, 0x00000000, 0x00000006, 0x000000ec, 0x000000fc, 0x00000114, +0x00080002, 0x00000004, 0x0000015c, 0x0000016c, 0x000001ac, 0x00000002, 0x00000004, 0x00000214, +0x00000224, 0x00000264, 0x00000001, 0x00000006, 0x000002cc, 0x000002dc, 0x0000031c, 0x00040002, +0x00000004, 0x00000364, 0x00000374, 0x00627373, 0xabab0062, 0x00010000, 0x00010001, 0x00000001, +0x00000000, 0x62760073, 0xababab00, 0x00010001, 0x00030001, 0x00000001, 0x00000000, 0x00000084, +0x00000088, 0x0000009a, 0x000000a0, 0x00000005, 0x00040001, 0x00020001, 0x000000b0, 0xab003162, +0x00000084, 0x00000088, 0x00000098, 0x000000c0, 0x000000d0, 0x00000088, 0x00000005, 0x00060001, +0x00030001, 0x000000d4, 0xffffffff, 0xffffffff, 0x00000000, 0xffffffff, 0xffffffff, 0x00000000, +0x66627373, 0x00666200, 0x00666276, 0x00000119, 0x00000088, 0x0000011c, 0x000000a0, 0x00000005, +0x00040001, 0x00020001, 0x00000120, 0x00316662, 0x00000119, 0x00000088, 0x00000098, 0x00000130, +0x00000140, 0x00000088, 0x00000005, 0x00060001, 0x00030001, 0x00000144, 0x3f800000, 0x00000000, +0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x3f800000, +0x3f800000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00667373, 0xabab0066, +0x00030000, 0x00010001, 0x00000001, 0x00000000, 0xab006676, 0x00030001, 0x00030001, 0x00000001, +0x00000000, 0x000001b0, 0x000001b4, 0x000001c4, 0x000001c8, 0x00000005, 0x00040001, 0x00020001, +0x000001d8, 0xab003166, 0x000001b0, 0x000001b4, 0x00000098, 0x000001e8, 0x000001f8, 0x000001b4, +0x00000005, 0x00060001, 0x00030001, 0x000001fc, 0x3f8ccccd, 0x00000000, 0x00000000, 0x00000000, +0x40066666, 0x00000000, 0x00000000, 0x00000000, 0x40466666, 0x40833333, 0x40a33333, 0x00000000, +0x40c33333, 0x00000000, 0x00000000, 0x00000000, 0x006e7373, 0xabab006e, 0x00020000, 0x00010001, +0x00000001, 0x00000000, 0xab006e76, 0x00020001, 0x00030001, 0x00000001, 0x00000000, 0x00000268, +0x0000026c, 0x0000027c, 0x00000280, 0x00000005, 0x00040001, 0x00020001, 0x00000290, 0xab00316e, +0x00000268, 0x0000026c, 0x00000098, 0x000002a0, 0x000002b0, 0x0000026c, 0x00000005, 0x00060001, +0x00030001, 0x000002b4, 0x00000047, 0x00000000, 0x00000001, 0x00000000, 0x00000048, 0x00000000, +0x00000001, 0x00000000, 0x00000049, 0x0000004a, 0x0000004b, 0x00000000, 0x0000004c, 0x00000000, +0x00000001, 0x00000000, 0x666e7373, 0x00666e00, 0x00666e76, 0x00000321, 0x0000026c, 0x00000324, +0x00000280, 0x00000005, 0x00040001, 0x00020001, 0x00000328, 0x0031666e, 0x00000321, 0x0000026c, +0x00000098, 0x00000338, 0x00000348, 0x0000026c, 0x00000005, 0x00060001, 0x00030001, 0x0000034c, +0x42240000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, +0x422c0000, 0x42300000, 0x42240000, 0x00000000, 0x42280000, 0x00000000, 0x00000000, 0x00000000, +0x335f7376, 0x4d00305f, 0x6f726369, 0x74666f73, 0x29522820, 0x534c4820, 0x6853204c, 0x72656461, +0x6d6f4320, 0x656c6970, 0x2e392072, 0x392e3932, 0x332e3235, 0x00313131, 0x05000051, 0xa00f000c, +0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x0200001f, 0x80000000, 0x900f0000, 0x0200001f, +0x80000000, 0xe00f0000, 0x01000028, 0xe0e40805, 0x03000005, 0x80010000, 0xa0000003, 0x90aa0000, +0x02000001, 0x80010001, 0xa000000c, 0x01000026, 0xf0e40005, 0x04000004, 0x80010001, 0x80000000, +0xa0000007, 0x80000001, 0x00000027, 0x02000001, 0x80020001, 0xa000000c, 0x0000002a, 0x03000005, +0x80010000, 0xa0aa0002, 0x90550000, 0x02000001, 0x80020001, 0xa000000c, 0x01000026, 0xf0e40004, +0x04000004, 0x80020001, 0x80000000, 0xa000000b, 0x80550001, 0x00000027, 0x02000001, 0x80010001, +0xa000000c, 0x0000002b, 0x02000001, 0xe0030000, 0x80e40001, 0x02000001, 0xe00c0000, 0xa000000c, +0x0000ffff, +}; + +static const struct registerset_constants registerset_constants_struct_struct_float[] = +{ + {"ssf", {"ssf", D3DXRS_FLOAT4, 0, 4, D3DXPC_STRUCT, D3DXPT_VOID, 1, 6, 1, 3, 24, NULL}, 137}, + {"ssf.f", {"f", D3DXRS_FLOAT4, 0, 1, D3DXPC_SCALAR, D3DXPT_FLOAT, 1, 1, 1, 0, 4, NULL}, 137}, + {"ssf.s", {"s", D3DXRS_FLOAT4, 1, 2, D3DXPC_STRUCT, D3DXPT_VOID, 1, 4, 1, 2, 16, NULL}, 141}, + {"ssf.s.f", {"f", D3DXRS_FLOAT4, 1, 1, D3DXPC_SCALAR, D3DXPT_FLOAT, 1, 1, 1, 0, 4, NULL}, 141}, + {"ssf.s.vf", {"vf", D3DXRS_FLOAT4, 2, 1, D3DXPC_VECTOR, D3DXPT_FLOAT, 1, 3, 1, 0, 12, NULL}, 145}, + {"ssf.f1", {"f1", D3DXRS_FLOAT4, 3, 1, D3DXPC_SCALAR, D3DXPT_FLOAT, 1, 1, 1, 0, 4, NULL}, 149}, +}; + +static const struct registerset_test registerset_test_struct_struct_float[] = +{ + {SetInt}, + {SetBool}, + {SetFloat}, + {SetIntArray, 1, 0, 5}, + {SetIntArray, 1, 6, REGISTER_OUTPUT_SIZE, 16, + {0x40000000, 0x00000000, 0x00000000, 0x00000000, 0x40400000, 0x00000000, 0x00000000, 0x00000000, + 0x40800000, 0x40a00000, 0x00000000, 0x00000000, 0x40e00000}}, + {SetBoolArray, 1, 0, 5}, + {SetBoolArray, 1, 6, REGISTER_OUTPUT_SIZE, 16, + {0x3f800000, 0x00000000, 0x00000000, 0x00000000, 0x3f800000, 0x00000000, 0x00000000, 0x00000000, + 0x3f800000, 0x3f800000, 0x00000000, 0x00000000, 0x3f800000}}, + {SetFloatArray, 0, 0, 5}, + {SetFloatArray, 0, 6, REGISTER_OUTPUT_SIZE, 16, + {0x40000123, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x40800123, 0x40a00123, 0x40c00123, 0x00000000, 0x40e00123}}, + {SetValue, 0, 0, 23}, + {SetValue, 0, 24, REGISTER_OUTPUT_SIZE * 4, 16, + {0x40000123, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x40800123, 0x40a00123, 0x40c00123, 0x00000000, 0x40e00123}}, + {SetVector}, + {SetVectorArray, 0, 0, 1}, + {SetVectorArray, 0, 2, REGISTER_OUTPUT_SIZE / 4, 16, + {0x40000123, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x40800123, 0x40a00123, 0x40c00123, 0x00000000, 0x40e00123}}, + {SetMatrix, 0, 0, 0, 16, + {0x40000123, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x40800123, 0x40a00123, 0x40c00123, 0x00000000, 0x40e00123}}, + {SetMatrixArray}, + {SetMatrixArray, 0, 1, REGISTER_OUTPUT_SIZE / 16, 16, + {0x40000123, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x40800123, 0x40a00123, 0x40c00123, 0x00000000, 0x40e00123}}, + {SetMatrixTranspose, 0, 0, 0, 16, {0x40000123}}, + {SetMatrixTransposeArray}, + {SetMatrixTransposeArray, 0, 1, REGISTER_OUTPUT_SIZE / 16, 16, {0x40000123}}, + {SetMatrixPointerArray}, + {SetMatrixPointerArray, 0, 1, REGISTER_OUTPUT_SIZE / 16, 16, {0x40000123}}, + {SetMatrixTransposePointerArray}, + {SetMatrixTransposePointerArray, 0, 1, REGISTER_OUTPUT_SIZE / 16, 16, {0x40000123}}, +}; + +static const struct registerset_constants registerset_constants_struct_struct_int[] = +{ + {"ssn", {"ssn", D3DXRS_INT4, 0, 6, D3DXPC_STRUCT, D3DXPT_VOID, 1, 6, 1, 3, 24, NULL}, 183}, + {"ssn.n", {"n", D3DXRS_INT4, 0, 1, D3DXPC_SCALAR, D3DXPT_INT, 1, 1, 1, 0, 4, NULL}, 183}, + {"ssn.s", {"s", D3DXRS_INT4, 1, 2, D3DXPC_STRUCT, D3DXPT_VOID, 1, 4, 1, 2, 16, NULL}, 187}, + {"ssn.s.n", {"n", D3DXRS_INT4, 1, 1, D3DXPC_SCALAR, D3DXPT_INT, 1, 1, 1, 0, 4, NULL}, 187}, + {"ssn.s.vn", {"vn", D3DXRS_INT4, 2, 1, D3DXPC_VECTOR, D3DXPT_INT, 1, 3, 1, 0, 12, NULL}, 191}, + {"ssn.n1", {"n1", D3DXRS_INT4, 3, 1, D3DXPC_SCALAR, D3DXPT_INT, 1, 1, 1, 0, 4, NULL}, 195}, +}; + +static const struct registerset_test registerset_test_struct_struct_int[] = +{ + {SetInt}, + {SetBool}, + {SetFloat}, + {SetIntArray, 1, 0, 5}, + {SetIntArray, 1, 6, REGISTER_OUTPUT_SIZE, 16, + {0x00000002, 0x00000000, 0x00000001, 0x00000000, 0x00000003, 0x00000000, 0x00000001, 0x00000000, + 0x00000004, 0x00000005, 0x00000000, 0x00000000, 0x00000007, 0x00000000, 0x00000001}}, + {SetBoolArray, 1, 0, 5}, + {SetBoolArray, 1, 6, REGISTER_OUTPUT_SIZE, 16, + {0x00000001, 0x00000000, 0x00000001, 0x00000000, 0x00000001, 0x00000000, 0x00000001, 0x00000000, + 0x00000001, 0x00000001, 0x00000000, 0x00000000, 0x00000001, 0x00000000, 0x00000001}}, + {SetFloatArray, 0, 0, 5}, + {SetFloatArray, 0, 6, REGISTER_OUTPUT_SIZE, 16, + {0x00000002, 0x00000000, 0x00000001, 0x00000000, 0x00000000, 0x00000000, 0x00000001, 0x00000000, + 0x00000004, 0x00000005, 0x00000006, 0x00000000, 0x00000007, 0x00000000, 0x00000001}}, + {SetValue, 1, 0, 23}, + {SetValue, 1, 24, REGISTER_OUTPUT_SIZE * 4, 16, + {0x00000002, 0x00000000, 0x00000001, 0x00000000, 0x00000003, 0x00000000, 0x00000001, 0x00000000, + 0x00000004, 0x00000005, 0x00000000, 0x00000000, 0x00000007, 0x00000000, 0x00000001}}, + {SetVector}, + {SetVectorArray, 0, 0, 1}, + {SetVectorArray, 0, 2, REGISTER_OUTPUT_SIZE / 4, 16, + {0x00000002, 0x00000000, 0x00000001, 0x00000000, 0x00000000, 0x00000000, 0x00000001, 0x00000000, + 0x00000004, 0x00000005, 0x00000006, 0x00000000, 0x00000007, 0x00000000, 0x00000001}}, + {SetMatrix, 0, 0, 0, 16, + {0x00000002, 0x00000000, 0x00000001, 0x00000000, 0x00000000, 0x00000000, 0x00000001, 0x00000000, + 0x00000004, 0x00000005, 0x00000006, 0x00000000, 0x00000007, 0x00000000, 0x00000001}}, + {SetMatrixArray}, + {SetMatrixArray, 0, 1, REGISTER_OUTPUT_SIZE / 16, 16, + {0x00000002, 0x00000000, 0x00000001, 0x00000000, 0x00000000, 0x00000000, 0x00000001, 0x00000000, + 0x00000004, 0x00000005, 0x00000006, 0x00000000, 0x00000007, 0x00000000, 0x00000001}}, + {SetMatrixTranspose, 0, 0, 0, 16, + {0x00000002, 0x00000000, 0x00000001, 0x00000000, 0x00000000, 0x00000000, 0x00000001, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000001}}, + {SetMatrixTransposeArray}, + {SetMatrixTransposeArray, 0, 1, REGISTER_OUTPUT_SIZE / 16, 16, + {0x00000002, 0x00000000, 0x00000001, 0x00000000, 0x00000000, 0x00000000, 0x00000001, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000001}}, + {SetMatrixPointerArray}, + {SetMatrixPointerArray, 0, 1, REGISTER_OUTPUT_SIZE / 16, 16, + {0x00000002, 0x00000000, 0x00000001, 0x00000000, 0x00000000, 0x00000000, 0x00000001, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000001}}, + {SetMatrixTransposePointerArray}, + {SetMatrixTransposePointerArray, 0, 1, REGISTER_OUTPUT_SIZE / 16, 16, + {0x00000002, 0x00000000, 0x00000001, 0x00000000, 0x00000000, 0x00000000, 0x00000001, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000001}}, +}; + +static const struct registerset_constants registerset_constants_struct_struct_bool[] = +{ + {"ssb", {"ssb", D3DXRS_BOOL, 0, 6, D3DXPC_STRUCT, D3DXPT_VOID, 1, 6, 1, 3, 24, NULL}, 63}, + {"ssb.b", {"b", D3DXRS_BOOL, 0, 1, D3DXPC_SCALAR, D3DXPT_BOOL, 1, 1, 1, 0, 4, NULL}, 63}, + {"ssb.s", {"s", D3DXRS_BOOL, 1, 4, D3DXPC_STRUCT, D3DXPT_VOID, 1, 4, 1, 2, 16, NULL}, 64}, + {"ssb.s.b", {"b", D3DXRS_BOOL, 1, 1, D3DXPC_SCALAR, D3DXPT_BOOL, 1, 1, 1, 0, 4, NULL}, 64}, + {"ssb.s.vb", {"vb", D3DXRS_BOOL, 2, 3, D3DXPC_VECTOR, D3DXPT_BOOL, 1, 3, 1, 0, 12, NULL}, 65}, + {"ssb.b1", {"b1", D3DXRS_BOOL, 5, 1, D3DXPC_SCALAR, D3DXPT_BOOL, 1, 1, 1, 0, 4, NULL}, 68}, +}; + +static const struct registerset_test registerset_test_struct_struct_bool[] = +{ + {SetInt}, + {SetBool}, + {SetFloat}, + {SetIntArray, 1, 0, 5}, + {SetIntArray, 1, 6, REGISTER_OUTPUT_SIZE, 6, + {0x00000001, 0x00000001, 0x00000001, 0x00000001, 0x00000000, 0x00000001}}, + {SetBoolArray, 1, 0, 5}, + {SetBoolArray, 1, 6, REGISTER_OUTPUT_SIZE, 6, + {0x00000002, 0x00000003, 0x00000004, 0x00000005, 0x00000000, 0x00000007}}, + {SetFloatArray, 0, 0, 5}, + {SetFloatArray, 0, 6, REGISTER_OUTPUT_SIZE, 6, + {0x00000001, 0x00000000, 0x00000001, 0x00000001, 0x00000001, 0x00000001}}, + {SetValue, 1, 0, 23}, + {SetValue, 1, 24, REGISTER_OUTPUT_SIZE * 4, 6, + {0x00000002, 0x00000003, 0x00000004, 0x00000005, 0x00000000, 0x00000007}}, + {SetVector}, + {SetVectorArray, 0, 0, 1}, + {SetVectorArray, 0, 2, REGISTER_OUTPUT_SIZE / 4, 6, + {0x00000001, 0x00000000, 0x00000001, 0x00000001, 0x00000001, 0x00000001}}, + {SetMatrix, 0, 0, 0, 6, + {0x00000001, 0x00000000, 0x00000001, 0x00000001, 0x00000001, 0x00000001}}, + {SetMatrixArray}, + {SetMatrixArray, 0, 1, REGISTER_OUTPUT_SIZE / 16, 6, + {0x00000001, 0x00000000, 0x00000001, 0x00000001, 0x00000001, 0x00000001}}, + {SetMatrixTranspose, 0, 0, 0, 6, + {0x00000001, 0x00000001, 0x00000001, 0x00000001, 0x00000000, 0x00000001}}, + {SetMatrixTransposeArray}, + {SetMatrixTransposeArray, 0, 1, REGISTER_OUTPUT_SIZE / 16, 6, + {0x00000001, 0x00000001, 0x00000001, 0x00000001, 0x00000000, 0x00000001}}, + {SetMatrixPointerArray}, + {SetMatrixPointerArray, 0, 1, REGISTER_OUTPUT_SIZE / 16, 6, + {0x00000001, 0x00000000, 0x00000001, 0x00000001, 0x00000001, 0x00000001}}, + {SetMatrixTransposePointerArray}, + {SetMatrixTransposePointerArray, 0, 1, REGISTER_OUTPUT_SIZE / 16, 6, + {0x00000001, 0x00000001, 0x00000001, 0x00000001, 0x00000000, 0x00000001}}, +}; + +static const struct registerset_constants registerset_constants_struct_struct_int_float[] = +{ + {"ssnf", {"ssnf", D3DXRS_FLOAT4, 4, 4, D3DXPC_STRUCT, D3DXPT_VOID, 1, 6, 1, 3, 24, NULL}, 221}, + {"ssnf.nf", {"nf", D3DXRS_FLOAT4, 4, 1, D3DXPC_SCALAR, D3DXPT_INT, 1, 1, 1, 0, 4, NULL}, 221}, + {"ssnf.s", {"s", D3DXRS_FLOAT4, 5, 2, D3DXPC_STRUCT, D3DXPT_VOID, 1, 4, 1, 2, 16, NULL}, 225}, + {"ssnf.s.nf", {"nf", D3DXRS_FLOAT4, 5, 1, D3DXPC_SCALAR, D3DXPT_INT, 1, 1, 1, 0, 4, NULL}, 225}, + {"ssnf.s.vnf", {"vnf", D3DXRS_FLOAT4, 6, 1, D3DXPC_VECTOR, D3DXPT_INT, 1, 3, 1, 0, 12, NULL}, 229}, + {"ssnf.nf1", {"nf1", D3DXRS_FLOAT4, 7, 1, D3DXPC_SCALAR, D3DXPT_INT, 1, 1, 1, 0, 4, NULL}, 233}, +}; + +static const struct registerset_test registerset_test_struct_struct_int_float[] = +{ + {SetInt}, + {SetBool}, + {SetFloat}, + {SetIntArray, 1, 0, 5}, + {SetIntArray, 1, 6, REGISTER_OUTPUT_SIZE, 16, + {0x40000000, 0x00000000, 0x00000000, 0x00000000, 0x40400000, 0x00000000, 0x00000000, 0x00000000, + 0x40800000, 0x40a00000, 0x00000000, 0x00000000, 0x40e00000}}, + {SetBoolArray, 1, 0, 5}, + {SetBoolArray, 1, 6, REGISTER_OUTPUT_SIZE, 16, + {0x3f800000, 0x00000000, 0x00000000, 0x00000000, 0x3f800000, 0x00000000, 0x00000000, 0x00000000, + 0x3f800000, 0x3f800000, 0x00000000, 0x00000000, 0x3f800000}}, + {SetFloatArray, 0, 0, 5}, + {SetFloatArray, 0, 6, REGISTER_OUTPUT_SIZE, 16, + {0x40000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x40800000, 0x40a00000, 0x40c00000, 0x00000000, 0x40e00000}}, + {SetValue, 1, 0, 23}, + {SetValue, 1, 24, REGISTER_OUTPUT_SIZE * 4, 16, + {0x40000000, 0x00000000, 0x00000000, 0x00000000, 0x40400000, 0x00000000, 0x00000000, 0x00000000, + 0x40800000, 0x40a00000, 0x00000000, 0x00000000, 0x40e00000}}, + {SetVector}, + {SetVectorArray, 0, 0, 1}, + {SetVectorArray, 0, 2, REGISTER_OUTPUT_SIZE / 4, 16, + {0x40000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x40800000, 0x40a00000, 0x40c00000, 0x00000000, 0x40e00000}}, + {SetMatrix, 0, 0, 0, 16, + {0x40000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x40800000, 0x40a00000, 0x40c00000, 0x00000000, 0x40e00000}}, + {SetMatrixArray}, + {SetMatrixArray, 0, 1, REGISTER_OUTPUT_SIZE / 16, 16, + {0x40000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x40800000, 0x40a00000, 0x40c00000, 0x00000000, 0x40e00000}}, + {SetMatrixTranspose, 0, 0, 0, 16, {0x40000000}}, + {SetMatrixTransposeArray}, + {SetMatrixTransposeArray, 0, 1, REGISTER_OUTPUT_SIZE / 16, 16, {0x40000000}}, + {SetMatrixPointerArray}, + {SetMatrixPointerArray, 0, 1, REGISTER_OUTPUT_SIZE / 16, 16, {0x40000000}}, + {SetMatrixTransposePointerArray}, + {SetMatrixTransposePointerArray, 0, 1, REGISTER_OUTPUT_SIZE / 16, 16, {0x40000000}}, +}; + +static const struct registerset_constants registerset_constants_struct_struct_bool_float[] = +{ + {"ssbf", {"ssbf", D3DXRS_FLOAT4, 8, 4, D3DXPC_STRUCT, D3DXPT_VOID, 1, 6, 1, 3, 24, NULL}, 91}, + {"ssbf.bf", {"bf", D3DXRS_FLOAT4, 8, 1, D3DXPC_SCALAR, D3DXPT_BOOL, 1, 1, 1, 0, 4, NULL}, 91}, + {"ssbf.s", {"s", D3DXRS_FLOAT4, 9, 2, D3DXPC_STRUCT, D3DXPT_VOID, 1, 4, 1, 2, 16, NULL}, 95}, + {"ssbf.s.bf", {"bf", D3DXRS_FLOAT4, 9, 1, D3DXPC_SCALAR, D3DXPT_BOOL, 1, 1, 1, 0, 4, NULL}, 95}, + {"ssbf.s.vbf", {"vbf", D3DXRS_FLOAT4, 10, 1, D3DXPC_VECTOR, D3DXPT_BOOL, 1, 3, 1, 0, 12, NULL}, 99}, + {"ssbf.bf1", {"bf1", D3DXRS_FLOAT4, 11, 1, D3DXPC_SCALAR, D3DXPT_BOOL, 1, 1, 1, 0, 4, NULL}, 103}, +}; + +static const struct registerset_test registerset_test_struct_struct_bool_float[] = +{ + {SetInt}, + {SetBool}, + {SetFloat}, + {SetIntArray, 1, 0, 5}, + {SetIntArray, 1, 6, REGISTER_OUTPUT_SIZE, 16, + {0x3f800000, 0x00000000, 0x00000000, 0x00000000, 0x3f800000, 0x00000000, 0x00000000, 0x00000000, + 0x3f800000, 0x3f800000, 0x00000000, 0x00000000, 0x3f800000}}, + {SetBoolArray, 1, 0, 5}, + {SetBoolArray, 1, 6, REGISTER_OUTPUT_SIZE, 16, + {0x3f800000, 0x00000000, 0x00000000, 0x00000000, 0x3f800000, 0x00000000, 0x00000000, 0x00000000, + 0x3f800000, 0x3f800000, 0x00000000, 0x00000000, 0x3f800000}}, + {SetFloatArray, 0, 0, 5}, + {SetFloatArray, 0, 6, REGISTER_OUTPUT_SIZE, 16, + {0x3f800000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x3f800000, 0x3f800000, 0x3f800000, 0x00000000, 0x3f800000}}, + {SetValue, 1, 0, 23}, + {SetValue, 1, 24, REGISTER_OUTPUT_SIZE * 4, 16, + {0x3f800000, 0x00000000, 0x00000000, 0x00000000, 0x3f800000, 0x00000000, 0x00000000, 0x00000000, + 0x3f800000, 0x3f800000, 0x00000000, 0x00000000, 0x3f800000}}, + {SetVector}, + {SetVectorArray, 0, 0, 1}, + {SetVectorArray, 0, 2, REGISTER_OUTPUT_SIZE / 4, 16, + {0x3f800000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x3f800000, 0x3f800000, 0x3f800000, 0x00000000, 0x3f800000}}, + {SetMatrix, 0, 0, 0, 16, + {0x3f800000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x3f800000, 0x3f800000, 0x3f800000, 0x00000000, 0x3f800000}}, + {SetMatrixArray}, + {SetMatrixArray, 0, 1, REGISTER_OUTPUT_SIZE / 16, 16, + {0x3f800000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x3f800000, 0x3f800000, 0x3f800000, 0x00000000, 0x3f800000}}, + {SetMatrixTranspose, 0, 0, 0, 16, {0x3f800000}}, + {SetMatrixTransposeArray}, + {SetMatrixTransposeArray, 0, 1, REGISTER_OUTPUT_SIZE / 16, 16, {0x3f800000}}, + {SetMatrixPointerArray}, + {SetMatrixPointerArray, 0, 1, REGISTER_OUTPUT_SIZE / 16, 16, {0x3f800000}}, + {SetMatrixTransposePointerArray}, + {SetMatrixTransposePointerArray, 0, 1, REGISTER_OUTPUT_SIZE / 16, 16, {0x3f800000}}, +}; + +/* + * fxc.exe /Tvs_3_0 + */ +#if 0 +row_major int3x2 ran[2] = {4, 5, 6, 1, 8, 1, 2, 3, 4, 7, 9, 1}; +float4 main(float4 pos : POSITION) : POSITION +{ + float4 tmp = 0; + int k; + for (k = 0; k < ran[1]._21; k++) + tmp.y += pos.y + tmp.x; + return tmp; +} +#endif +static const DWORD registerset_blob_special_int[] = +{ +0xfffe0300, 0x0038fffe, 0x42415443, 0x0000001c, 0x000000ab, 0xfffe0300, 0x00000001, 0x0000001c, +0x00000100, 0x000000a4, 0x00000030, 0x00000001, 0x00000009, 0x00000034, 0x00000044, 0x006e6172, +0x00020002, 0x00020003, 0x00000002, 0x00000000, 0x00000004, 0x00000005, 0x00000001, 0x00000000, +0x00000006, 0x00000001, 0x00000001, 0x00000000, 0x00000008, 0x00000001, 0x00000001, 0x00000000, +0x00000002, 0x00000003, 0x00000001, 0x00000000, 0x00000004, 0x00000007, 0x00000001, 0x00000000, +0x00000009, 0x00000001, 0x00000001, 0x00000000, 0x335f7376, 0x4d00305f, 0x6f726369, 0x74666f73, +0x29522820, 0x534c4820, 0x6853204c, 0x72656461, 0x6d6f4320, 0x656c6970, 0x2e392072, 0x392e3932, +0x332e3235, 0x00313131, 0x05000051, 0xa00f0000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, +0x0200001f, 0x80000000, 0x900f0000, 0x0200001f, 0x80000000, 0xe00f0000, 0x02000001, 0x80010000, +0xa0000000, 0x01000026, 0xf0e40008, 0x03000002, 0x80010000, 0x80000000, 0x90550000, 0x00000027, +0x02000001, 0xe0020000, 0x80000000, 0x02000001, 0xe00d0000, 0xa0000000, 0x0000ffff, +}; + +static const struct registerset_constants registerset_constants_special_int[] = +{ + {"ran", {"ran", D3DXRS_INT4, 0, 9, D3DXPC_MATRIX_ROWS, D3DXPT_INT, 3, 2, 2, 0, 48, NULL}, 17}, + {"ran[0]", {"ran", D3DXRS_INT4, 0, 3, D3DXPC_MATRIX_ROWS, D3DXPT_INT, 3, 2, 1, 0, 24, NULL}, 17}, + {"ran[1]", {"ran", D3DXRS_INT4, 3, 3, D3DXPC_MATRIX_ROWS, D3DXPT_INT, 3, 2, 1, 0, 24, NULL}, 29}, +}; + +/* + * fxc.exe /Tvs_3_0 + */ +#if 0 +float3 vaf[10]; +float4 main(float4 pos : POSITION) : POSITION +{ + float4 tmp = 0; + tmp.y += pos.y + vaf[8].x; + return tmp; +} +#endif +static const DWORD registerset_blob_bigvec[] = +{ +0xfffe0300, 0x0020fffe, 0x42415443, 0x0000001c, 0x0000004b, 0xfffe0300, 0x00000001, 0x0000001c, +0x00000100, 0x00000044, 0x00000030, 0x00000002, 0x00000009, 0x00000034, 0x00000000, 0x00666176, +0x00030001, 0x00030001, 0x0000000a, 0x00000000, 0x335f7376, 0x4d00305f, 0x6f726369, 0x74666f73, +0x29522820, 0x534c4820, 0x6853204c, 0x72656461, 0x6d6f4320, 0x656c6970, 0x2e392072, 0x392e3932, +0x332e3235, 0x00313131, 0x05000051, 0xa00f0009, 0x00000000, 0x00000000, 0x00000000, 0x00000000, +0x0200001f, 0x80000000, 0x900f0000, 0x0200001f, 0x80000000, 0xe00f0000, 0x03000002, 0xe0020000, +0xa0000008, 0x90550000, 0x02000001, 0xe00d0000, 0xa0000009, 0x0000ffff, +}; + +static const struct registerset_constants registerset_constants_bigvec_float[] = +{ + {"vaf", {"vaf", D3DXRS_FLOAT4, 0, 9, D3DXPC_VECTOR, D3DXPT_FLOAT, 1, 3, 10, 0, 120, NULL}, 0}, + {"vaf[0]", {"vaf", D3DXRS_FLOAT4, 0, 1, D3DXPC_VECTOR, D3DXPT_FLOAT, 1, 3, 1, 0, 12, NULL}, 0}, + {"vaf[1]", {"vaf", D3DXRS_FLOAT4, 1, 1, D3DXPC_VECTOR, D3DXPT_FLOAT, 1, 3, 1, 0, 12, NULL}, 0}, + {"vaf[2]", {"vaf", D3DXRS_FLOAT4, 2, 1, D3DXPC_VECTOR, D3DXPT_FLOAT, 1, 3, 1, 0, 12, NULL}, 0}, + {"vaf[3]", {"vaf", D3DXRS_FLOAT4, 3, 1, D3DXPC_VECTOR, D3DXPT_FLOAT, 1, 3, 1, 0, 12, NULL}, 0}, + {"vaf[4]", {"vaf", D3DXRS_FLOAT4, 4, 1, D3DXPC_VECTOR, D3DXPT_FLOAT, 1, 3, 1, 0, 12, NULL}, 0}, + {"vaf[5]", {"vaf", D3DXRS_FLOAT4, 5, 1, D3DXPC_VECTOR, D3DXPT_FLOAT, 1, 3, 1, 0, 12, NULL}, 0}, + {"vaf[6]", {"vaf", D3DXRS_FLOAT4, 6, 1, D3DXPC_VECTOR, D3DXPT_FLOAT, 1, 3, 1, 0, 12, NULL}, 0}, + {"vaf[7]", {"vaf", D3DXRS_FLOAT4, 7, 1, D3DXPC_VECTOR, D3DXPT_FLOAT, 1, 3, 1, 0, 12, NULL}, 0}, + {"vaf[8]", {"vaf", D3DXRS_FLOAT4, 8, 1, D3DXPC_VECTOR, D3DXPT_FLOAT, 1, 3, 1, 0, 12, NULL}, 0}, + {"vaf[9]", {"vaf", D3DXRS_FLOAT4, 9, 0, D3DXPC_VECTOR, D3DXPT_FLOAT, 1, 3, 1, 0, 12, NULL}, 0}, +}; + +static const struct registerset_test registerset_test_bigvec_float[] = +{ + {SetMatrix, 0, 0, 0, 16, + {0x40000123, 0x00000000, 0x40800123, 0x00000000, 0x40c00123, 0x40e00123, 0x41000123, 0x00000000, + 0x41200123, 0x41300123, 0x41400123, 0x00000000, 0x41600123, 0x41700123, 0x41800123}}, + {SetMatrixArray}, + {SetMatrixArray, 0, 1, 1, 16, + {0x40000123, 0x00000000, 0x40800123, 0x00000000, 0x40c00123, 0x40e00123, 0x41000123, 0x00000000, + 0x41200123, 0x41300123, 0x41400123, 0x00000000, 0x41600123, 0x41700123, 0x41800123}}, + {SetMatrixArray, 0, 2, 2, 32, + {0x40000123, 0x00000000, 0x40800123, 0x00000000, 0x40c00123, 0x40e00123, 0x41000123, 0x00000000, + 0x41200123, 0x41300123, 0x41400123, 0x00000000, 0x41600123, 0x41700123, 0x41800123, 0x00000000, + 0x41a00123, 0x41b00123, 0x41c00123, 0x00000000, 0x00000000, 0x41f00123, 0x42000123, 0x00000000, + 0x00000000, 0x42300123, 0x42400123, 0x00000000, 0x42600123, 0x42700123, 0x42800123}}, + {SetMatrixArray, 0, 3, REGISTER_OUTPUT_SIZE / 16, 36, + {0x40000123, 0x00000000, 0x40800123, 0x00000000, 0x40c00123, 0x40e00123, 0x41000123, 0x00000000, + 0x41200123, 0x41300123, 0x41400123, 0x00000000, 0x41600123, 0x41700123, 0x41800123, 0x00000000, + 0x41a00123, 0x41b00123, 0x41c00123, 0x00000000, 0x00000000, 0x41f00123, 0x42000123, 0x00000000, + 0x00000000, 0x42300123, 0x42400123, 0x00000000, 0x42600123, 0x42700123, 0x42800123, 0x00000000, + 0x43000123, 0x43100123, 0x43200123}}, + {SetMatrixTranspose, 0, 0, 0, 16, + {0x40000123, 0x40c00123, 0x41200123, 0x00000000, 0x00000000, 0x40e00123, 0x41300123, 0x00000000, + 0x40800123, 0x41000123, 0x41400123, 0x00000000, 0x40a00123, 0x41100123, 0x41500123}}, + {SetMatrixTransposeArray}, + {SetMatrixTransposeArray, 0, 1, 1, 16, + {0x40000123, 0x40c00123, 0x41200123, 0x00000000, 0x00000000, 0x40e00123, 0x41300123, 0x00000000, + 0x40800123, 0x41000123, 0x41400123, 0x00000000, 0x40a00123, 0x41100123, 0x41500123}}, + {SetMatrixTransposeArray, 0, 2, 2, 32, + {0x40000123, 0x40c00123, 0x41200123, 0x00000000, 0x00000000, 0x40e00123, 0x41300123, 0x00000000, + 0x40800123, 0x41000123, 0x41400123, 0x00000000, 0x40a00123, 0x41100123, 0x41500123, 0x00000000, + 0x41a00123, 0x00000000, 0x00000000, 0x00000000, 0x41b00123, 0x41f00123, 0x42300123, 0x00000000, + 0x41c00123, 0x42000123, 0x42400123, 0x00000000, 0x41d00123, 0x42100123, 0x42500123}}, + {SetMatrixTransposeArray, 0, 3, REGISTER_OUTPUT_SIZE / 16, 36, + {0x40000123, 0x40c00123, 0x41200123, 0x00000000, 0x00000000, 0x40e00123, 0x41300123, 0x00000000, + 0x40800123, 0x41000123, 0x41400123, 0x00000000, 0x40a00123, 0x41100123, 0x41500123, 0x00000000, + 0x41a00123, 0x00000000, 0x00000000, 0x00000000, 0x41b00123, 0x41f00123, 0x42300123, 0x00000000, + 0x41c00123, 0x42000123, 0x42400123, 0x00000000, 0x41d00123, 0x42100123, 0x42500123, 0x00000000, + 0x43000123, 0x43400123, 0x43800123}}, + {SetMatrixPointerArray}, + {SetMatrixPointerArray, 0, 1, 1, 16, + {0x40000123, 0x00000000, 0x40800123, 0x00000000, 0x40c00123, 0x40e00123, 0x41000123, 0x00000000, + 0x41200123, 0x41300123, 0x41400123, 0x00000000, 0x41600123, 0x41700123, 0x41800123}}, + {SetMatrixPointerArray, 0, 2, 2, 32, + {0x40000123, 0x00000000, 0x40800123, 0x00000000, 0x40c00123, 0x40e00123, 0x41000123, 0x00000000, + 0x41200123, 0x41300123, 0x41400123, 0x00000000, 0x41600123, 0x41700123, 0x41800123, 0x00000000, + 0x41900123, 0x41a00123, 0x41b00123, 0x00000000, 0x41d00123, 0x00000000, 0x41f00123, 0x00000000, + 0x42100123, 0x00000000, 0x42300123, 0x00000000, 0x42500123, 0x42600123, 0x42700123}}, + {SetMatrixPointerArray, 0, 3, REGISTER_OUTPUT_SIZE / 16, 36, + {0x40000123, 0x00000000, 0x40800123, 0x00000000, 0x40c00123, 0x40e00123, 0x41000123, 0x00000000, + 0x41200123, 0x41300123, 0x41400123, 0x00000000, 0x41600123, 0x41700123, 0x41800123, 0x00000000, + 0x41900123, 0x41a00123, 0x41b00123, 0x00000000, 0x41d00123, 0x00000000, 0x41f00123, 0x00000000, + 0x42100123, 0x00000000, 0x42300123, 0x00000000, 0x42500123, 0x42600123, 0x42700123, 0x00000000, + 0x42800123, 0x42900123, 0x43000123}}, + {SetMatrixTransposePointerArray}, + {SetMatrixTransposePointerArray, 0, 1, 1, 16, + {0x40000123, 0x40c00123, 0x41200123, 0x00000000, 0x00000000, 0x40e00123, 0x41300123, 0x00000000, + 0x40800123, 0x41000123, 0x41400123, 0x00000000, 0x40a00123, 0x41100123, 0x41500123}}, + {SetMatrixTransposePointerArray, 0, 2, 2, 32, + {0x40000123, 0x40c00123, 0x41200123, 0x00000000, 0x00000000, 0x40e00123, 0x41300123, 0x00000000, + 0x40800123, 0x41000123, 0x41400123, 0x00000000, 0x40a00123, 0x41100123, 0x41500123, 0x00000000, + 0x41900123, 0x41d00123, 0x42100123, 0x00000000, 0x41a00123, 0x00000000, 0x00000000, 0x00000000, + 0x41b00123, 0x41f00123, 0x42300123, 0x00000000, 0x41c00123, 0x42000123, 0x42400123}}, + {SetMatrixTransposePointerArray, 0, 3, REGISTER_OUTPUT_SIZE / 16, 36, + {0x40000123, 0x40c00123, 0x41200123, 0x00000000, 0x00000000, 0x40e00123, 0x41300123, 0x00000000, + 0x40800123, 0x41000123, 0x41400123, 0x00000000, 0x40a00123, 0x41100123, 0x41500123, 0x00000000, + 0x41900123, 0x41d00123, 0x42100123, 0x00000000, 0x41a00123, 0x00000000, 0x00000000, 0x00000000, + 0x41b00123, 0x41f00123, 0x42300123, 0x00000000, 0x41c00123, 0x42000123, 0x42400123, 0x00000000, + 0x42800123, 0x43200123, 0x43600123}}, +}; + +/* + * fxc.exe /Tvs_3_0 + */ +#if 0 +float4x4 cf = {1.1, 2.2, 3.3, 4.4, 5.5, 6.6, 7.7, 8.8, 9.9, 1.2, 1.3, 1.4, 1.5, 1.6, 1.7, 1.8}; +float f = 33.33; +float4 main(float4 pos : POSITION) : POSITION +{ + float4 tmp = 0; + tmp.y += cf._22; + tmp.z = f; + return tmp; +} +#endif +static const DWORD registerset_blob_matrix_column_clamp[] = +{ +0xfffe0300, 0x003efffe, 0x42415443, 0x0000001c, 0x000000c3, 0xfffe0300, 0x00000002, 0x0000001c, +0x00000100, 0x000000bc, 0x00000044, 0x00000002, 0x00000002, 0x00000048, 0x00000058, 0x00000098, +0x00020002, 0x00000001, 0x0000009c, 0x000000ac, 0xab006663, 0x00030003, 0x00040004, 0x00000001, +0x00000000, 0x3f8ccccd, 0x40b00000, 0x411e6666, 0x3fc00000, 0x400ccccd, 0x40d33333, 0x3f99999a, +0x3fcccccd, 0x40533333, 0x40f66666, 0x3fa66666, 0x3fd9999a, 0x408ccccd, 0x410ccccd, 0x3fb33333, +0x3fe66666, 0xabab0066, 0x00030000, 0x00010001, 0x00000001, 0x00000000, 0x420551ec, 0x00000000, +0x00000000, 0x00000000, 0x335f7376, 0x4d00305f, 0x6f726369, 0x74666f73, 0x29522820, 0x534c4820, +0x6853204c, 0x72656461, 0x6d6f4320, 0x656c6970, 0x2e392072, 0x392e3932, 0x332e3235, 0x00313131, +0x05000051, 0xa00f0003, 0x00000000, 0x3f800000, 0x00000000, 0x00000000, 0x0200001f, 0x80000000, +0xe00f0000, 0x02000001, 0x80020000, 0xa0550001, 0x03000005, 0xe00b0000, 0x80550000, 0xa0240003, +0x02000001, 0xe0040000, 0xa0000002, 0x0000ffff, +}; + +static const struct registerset_constants registerset_constants_matrix_column_clamp[] = +{ + {"cf", {"cf", D3DXRS_FLOAT4, 0, 2, D3DXPC_MATRIX_COLUMNS, D3DXPT_FLOAT, 4, 4, 1, 0, 64, NULL}, 0}, + {"f", {"f", D3DXRS_FLOAT4, 2, 1, D3DXPC_SCALAR, D3DXPT_FLOAT, 1, 1, 1, 0, 4, NULL}, 0}, +}; + +static const struct registerset_test registerset_test_matrix_column_clamp[] = +{ + {SetMatrix, 0, 0, 0, 8, + {0x40000123, 0x40c00123, 0x41200123, 0x41600123, 0x00000000, 0x40e00123, 0x41300123, 0x41700123}}, +}; + +static const struct +{ + const char *name; + const char *var; + UINT start; + D3DXREGISTER_SET regset; + const DWORD *blob; + const struct registerset_test *tests; + UINT test_count; + const struct registerset_constants *constants; + UINT constant_count; +} +registerset_data[] = +{ + /* scalar */ + {"float", "f", 0, D3DXRS_FLOAT4, registerset_blob_scalar, + registerset_test_scalar_float, ARRAY_SIZE(registerset_test_scalar_float), + registerset_constants_scalar_float, ARRAY_SIZE(registerset_constants_scalar_float)}, + {"int", "n", 0, D3DXRS_INT4, registerset_blob_scalar, + registerset_test_scalar_int, ARRAY_SIZE(registerset_test_scalar_int), + registerset_constants_scalar_int, ARRAY_SIZE(registerset_constants_scalar_int)}, + {"int float", "nf", 4, D3DXRS_FLOAT4, registerset_blob_scalar, + registerset_test_scalar_int_float, ARRAY_SIZE(registerset_test_scalar_int_float), + registerset_constants_scalar_int_float, ARRAY_SIZE(registerset_constants_scalar_int_float)}, + {"bool float", "bf", 8, D3DXRS_FLOAT4, registerset_blob_scalar, + registerset_test_scalar_bool_float, ARRAY_SIZE(registerset_test_scalar_bool_float), + registerset_constants_scalar_bool_float, ARRAY_SIZE(registerset_constants_scalar_bool_float)}, + {"bool", "b", 0, D3DXRS_BOOL, registerset_blob_scalar, + registerset_test_scalar_bool, ARRAY_SIZE(registerset_test_scalar_bool), + registerset_constants_scalar_bool, ARRAY_SIZE(registerset_constants_scalar_bool)}, + /* scalar array */ + {"float [2]", "af", 0, D3DXRS_FLOAT4, registerset_blob_scalar_array, + registerset_test_scalar_array_float, ARRAY_SIZE(registerset_test_scalar_array_float), + registerset_constants_scalar_array_float, ARRAY_SIZE(registerset_constants_scalar_array_float)}, + {"int [2]", "an", 0, D3DXRS_INT4, registerset_blob_scalar_array, + registerset_test_scalar_array_int, ARRAY_SIZE(registerset_test_scalar_array_int), + registerset_constants_scalar_array_int, ARRAY_SIZE(registerset_constants_scalar_array_int)}, + {"bool [2]", "ab", 0, D3DXRS_BOOL, registerset_blob_scalar_array, + registerset_test_scalar_array_bool, ARRAY_SIZE(registerset_test_scalar_array_bool), + registerset_constants_scalar_array_bool, ARRAY_SIZE(registerset_constants_scalar_array_bool)}, + {"int float [2]", "anf", 8, D3DXRS_FLOAT4, registerset_blob_scalar_array, + registerset_test_scalar_array_int_float, ARRAY_SIZE(registerset_test_scalar_array_int_float), + registerset_constants_scalar_array_int_float, ARRAY_SIZE(registerset_constants_scalar_array_int_float)}, + {"bool float [2]", "abf", 16, D3DXRS_FLOAT4, registerset_blob_scalar_array, + registerset_test_scalar_array_bool_float, ARRAY_SIZE(registerset_test_scalar_array_bool_float), + registerset_constants_scalar_array_bool_float, ARRAY_SIZE(registerset_constants_scalar_array_bool_float)}, + /* vector */ + {"float 3", "vf", 0, D3DXRS_FLOAT4, registerset_blob_vector, + registerset_test_vector_float, ARRAY_SIZE(registerset_test_vector_float), + registerset_constants_vector_float, ARRAY_SIZE(registerset_constants_vector_float)}, + {"int 3", "vn", 0, D3DXRS_INT4, registerset_blob_vector, + registerset_test_vector_int, ARRAY_SIZE(registerset_test_vector_int), + registerset_constants_vector_int, ARRAY_SIZE(registerset_constants_vector_int)}, + {"bool 3", "vb", 0, D3DXRS_BOOL, registerset_blob_vector, + registerset_test_vector_bool, ARRAY_SIZE(registerset_test_vector_bool), + registerset_constants_vector_bool, ARRAY_SIZE(registerset_constants_vector_bool)}, + {"bool float 3", "vbf", 8, D3DXRS_FLOAT4, registerset_blob_vector, + registerset_test_vector_bool_float, ARRAY_SIZE(registerset_test_vector_bool_float), + registerset_constants_vector_bool_float, ARRAY_SIZE(registerset_constants_vector_bool_float)}, + {"int float 3", "vnf", 4, D3DXRS_FLOAT4, registerset_blob_vector, + registerset_test_vector_int_float, ARRAY_SIZE(registerset_test_vector_int_float), + registerset_constants_vector_int_float, ARRAY_SIZE(registerset_constants_vector_int_float)}, + /* vector array */ + {"float 3 [2]", "vaf", 0, D3DXRS_FLOAT4, registerset_blob_vector_array, + registerset_test_vector_array_float, ARRAY_SIZE(registerset_test_vector_array_float), + registerset_constants_vector_array_float, ARRAY_SIZE(registerset_constants_vector_array_float)}, + {"int 3 [2]", "van", 0, D3DXRS_INT4, registerset_blob_vector_array, + registerset_test_vector_array_int, ARRAY_SIZE(registerset_test_vector_array_int), + registerset_constants_vector_array_int, ARRAY_SIZE(registerset_constants_vector_array_int)}, + {"bool 3 [2]", "vab", 0, D3DXRS_BOOL, registerset_blob_vector_array, + registerset_test_vector_array_bool, ARRAY_SIZE(registerset_test_vector_array_bool), + registerset_constants_vector_array_bool, ARRAY_SIZE(registerset_constants_vector_array_bool)}, + {"bool float 3 [2]", "vabf", 16, D3DXRS_FLOAT4, registerset_blob_vector_array, + registerset_test_vector_array_bool_float, ARRAY_SIZE(registerset_test_vector_array_bool_float), + registerset_constants_vector_array_bool_float, ARRAY_SIZE(registerset_constants_vector_array_bool_float)}, + {"int float 3 [2]", "vanf", 8, D3DXRS_FLOAT4, registerset_blob_vector_array, + registerset_test_vector_array_int_float, ARRAY_SIZE(registerset_test_vector_array_int_float), + registerset_constants_vector_array_int_float, ARRAY_SIZE(registerset_constants_vector_array_int_float)}, + /* matrix column */ + {"float c3x2", "cf", 0, D3DXRS_FLOAT4, registerset_blob_column, + registerset_test_column_float, ARRAY_SIZE(registerset_test_column_float), + registerset_constants_column_float, ARRAY_SIZE(registerset_constants_column_float)}, + {"int c3x2", "cn", 0, D3DXRS_INT4, registerset_blob_column, + registerset_test_column_int, ARRAY_SIZE(registerset_test_column_int), + registerset_constants_column_int, ARRAY_SIZE(registerset_constants_column_int)}, + {"bool c3x2", "cb", 0, D3DXRS_BOOL, registerset_blob_column, + registerset_test_column_bool, ARRAY_SIZE(registerset_test_column_bool), + registerset_constants_column_bool, ARRAY_SIZE(registerset_constants_column_bool)}, + {"bool float c3x2", "cbf", 8, D3DXRS_FLOAT4, registerset_blob_column, + registerset_test_column_bool_float, ARRAY_SIZE(registerset_test_column_bool_float), + registerset_constants_column_bool_float, ARRAY_SIZE(registerset_constants_column_bool_float)}, + {"int float c3x2", "cnf", 16, D3DXRS_FLOAT4, registerset_blob_column, + registerset_test_column_int_float, ARRAY_SIZE(registerset_test_column_int_float), + registerset_constants_column_int_float, ARRAY_SIZE(registerset_constants_column_int_float)}, + /* matrix column array */ + {"float c3x2 [2]", "caf", 0, D3DXRS_FLOAT4, registerset_blob_column_array, + registerset_test_column_array_float, ARRAY_SIZE(registerset_test_column_array_float), + registerset_constants_column_array_float, ARRAY_SIZE(registerset_constants_column_array_float)}, + {"int c3x2 [2]", "can", 0, D3DXRS_INT4, registerset_blob_column_array, + registerset_test_column_array_int, ARRAY_SIZE(registerset_test_column_array_int), + registerset_constants_column_array_int, ARRAY_SIZE(registerset_constants_column_array_int)}, + {"bool c3x2 [2]", "cab", 0, D3DXRS_BOOL, registerset_blob_column_array, + registerset_test_column_array_bool, ARRAY_SIZE(registerset_test_column_array_bool), + registerset_constants_column_array_bool, ARRAY_SIZE(registerset_constants_column_array_bool)}, + {"bool float c3x2 [2]", "cabf", 16, D3DXRS_FLOAT4, registerset_blob_column_array, + registerset_test_column_array_bool_float, ARRAY_SIZE(registerset_test_column_array_bool_float), + registerset_constants_column_array_bool_float, ARRAY_SIZE(registerset_constants_column_array_bool_float)}, + {"int float c3x2 [2]", "canf", 32, D3DXRS_FLOAT4, registerset_blob_column_array, + registerset_test_column_array_int_float, ARRAY_SIZE(registerset_test_column_array_int_float), + registerset_constants_column_array_int_float, ARRAY_SIZE(registerset_constants_column_array_int_float)}, + /* matrix row */ + {"float r3x2", "rf", 0, D3DXRS_FLOAT4, registerset_blob_row, + registerset_test_row_float, ARRAY_SIZE(registerset_test_row_float), + registerset_constants_row_float, ARRAY_SIZE(registerset_constants_row_float)}, + {"int r3x2", "rn", 0, D3DXRS_INT4, registerset_blob_row, + registerset_test_row_int, ARRAY_SIZE(registerset_test_row_int), + registerset_constants_row_int, ARRAY_SIZE(registerset_constants_row_int)}, + {"bool r3x2", "rb", 0, D3DXRS_BOOL, registerset_blob_row, + registerset_test_row_bool, ARRAY_SIZE(registerset_test_row_bool), + registerset_constants_row_bool, ARRAY_SIZE(registerset_constants_row_bool)}, + {"bool float r3x2", "rbf", 12, D3DXRS_FLOAT4, registerset_blob_row, + registerset_test_row_bool_float, ARRAY_SIZE(registerset_test_row_bool_float), + registerset_constants_row_bool_float, ARRAY_SIZE(registerset_constants_row_bool_float)}, + {"int float r3x2", "rnf", 24, D3DXRS_FLOAT4, registerset_blob_row, + registerset_test_row_int_float, ARRAY_SIZE(registerset_test_row_int_float), + registerset_constants_row_int_float, ARRAY_SIZE(registerset_constants_row_int_float)}, + /* matrix row array */ + {"float 3x2 [2]", "raf", 0, D3DXRS_FLOAT4, registerset_blob_row_array, + registerset_test_row_array_float, ARRAY_SIZE(registerset_test_row_array_float), + registerset_constants_row_array_float, ARRAY_SIZE(registerset_constants_row_array_float)}, + {"int 3x2 [2]", "ran", 0, D3DXRS_INT4, registerset_blob_row_array, + registerset_test_row_array_int, ARRAY_SIZE(registerset_test_row_array_int), + registerset_constants_row_array_int, ARRAY_SIZE(registerset_constants_row_array_int)}, + {"bool 3x2 [2]", "rab", 0, D3DXRS_BOOL, registerset_blob_row_array, + registerset_test_row_array_bool, ARRAY_SIZE(registerset_test_row_array_bool), + registerset_constants_row_array_bool, ARRAY_SIZE(registerset_constants_row_array_bool)}, + {"bool float 3x2 [2]", "rabf", 24, D3DXRS_FLOAT4, registerset_blob_row_array, + registerset_test_row_array_bool_float, ARRAY_SIZE(registerset_test_row_array_bool_float), + registerset_constants_row_array_bool_float, ARRAY_SIZE(registerset_constants_row_array_bool_float)}, + {"int float 3x2 [2]", "ranf", 48, D3DXRS_FLOAT4, registerset_blob_row_array, + registerset_test_row_array_int_float, ARRAY_SIZE(registerset_test_row_array_int_float), + registerset_constants_row_array_int_float, ARRAY_SIZE(registerset_constants_row_array_int_float)}, + /* struct */ + {"struct float", "sf", 0, D3DXRS_FLOAT4, registerset_blob_struct, + registerset_test_struct_float, ARRAY_SIZE(registerset_test_struct_float), + registerset_constants_struct_float, ARRAY_SIZE(registerset_constants_struct_float)}, + {"struct int", "sn", 0, D3DXRS_INT4, registerset_blob_struct, + registerset_test_struct_int, ARRAY_SIZE(registerset_test_struct_int), + registerset_constants_struct_int, ARRAY_SIZE(registerset_constants_struct_int)}, + {"struct bool", "sb", 0, D3DXRS_BOOL, registerset_blob_struct, + registerset_test_struct_bool, ARRAY_SIZE(registerset_test_struct_bool), + registerset_constants_struct_bool, ARRAY_SIZE(registerset_constants_struct_bool)}, + {"struct bool float", "sbf", 16, D3DXRS_FLOAT4, registerset_blob_struct, + registerset_test_struct_bool_float, ARRAY_SIZE(registerset_test_struct_bool_float), + registerset_constants_struct_bool_float, ARRAY_SIZE(registerset_constants_struct_bool_float)}, + {"struct int float", "snf", 8, D3DXRS_FLOAT4, registerset_blob_struct, + registerset_test_struct_int_float, ARRAY_SIZE(registerset_test_struct_int_float), + registerset_constants_struct_int_float, ARRAY_SIZE(registerset_constants_struct_int_float)}, + /* struct array */ + {"struct float [2]", "saf", 0, D3DXRS_FLOAT4, registerset_blob_struct_array, + registerset_test_struct_array_float, ARRAY_SIZE(registerset_test_struct_array_float), + registerset_constants_struct_array_float, ARRAY_SIZE(registerset_constants_struct_array_float)}, + {"struct int [2]", "san", 0, D3DXRS_INT4, registerset_blob_struct_array, + registerset_test_struct_array_int, ARRAY_SIZE(registerset_test_struct_array_int), + registerset_constants_struct_array_int, ARRAY_SIZE(registerset_constants_struct_array_int)}, + {"struct bool [2]", "sab", 0, D3DXRS_BOOL, registerset_blob_struct_array, + registerset_test_struct_array_bool, ARRAY_SIZE(registerset_test_struct_array_bool), + registerset_constants_struct_array_bool, ARRAY_SIZE(registerset_constants_struct_array_bool)}, + {"struct bool float [2]", "sabf", 32, D3DXRS_FLOAT4, registerset_blob_struct_array, + registerset_test_struct_array_bool_float, ARRAY_SIZE(registerset_test_struct_array_bool_float), + registerset_constants_struct_array_bool_float, ARRAY_SIZE(registerset_constants_struct_array_bool_float)}, + {"struct int float [2]", "sanf", 16, D3DXRS_FLOAT4, registerset_blob_struct_array, + registerset_test_struct_array_int_float, ARRAY_SIZE(registerset_test_struct_array_int_float), + registerset_constants_struct_array_int_float, ARRAY_SIZE(registerset_constants_struct_array_int_float)}, + /* struct struct */ + {"struct struct float", "ssf", 0, D3DXRS_FLOAT4, registerset_blob_struct_struct, + registerset_test_struct_struct_float, ARRAY_SIZE(registerset_test_struct_struct_float), + registerset_constants_struct_struct_float, ARRAY_SIZE(registerset_constants_struct_struct_float)}, + {"struct struct int", "ssn", 0, D3DXRS_INT4, registerset_blob_struct_struct, + registerset_test_struct_struct_int, ARRAY_SIZE(registerset_test_struct_struct_int), + registerset_constants_struct_struct_int, ARRAY_SIZE(registerset_constants_struct_struct_int)}, + {"struct struct bool", "ssb", 0, D3DXRS_BOOL, registerset_blob_struct_struct, + registerset_test_struct_struct_bool, ARRAY_SIZE(registerset_test_struct_struct_bool), + registerset_constants_struct_struct_bool, ARRAY_SIZE(registerset_constants_struct_struct_bool)}, + {"struct struct bool float", "ssbf", 32, D3DXRS_FLOAT4, registerset_blob_struct_struct, + registerset_test_struct_struct_bool_float, ARRAY_SIZE(registerset_test_struct_struct_bool_float), + registerset_constants_struct_struct_bool_float, ARRAY_SIZE(registerset_constants_struct_struct_bool_float)}, + {"struct struct int float", "ssnf", 16, D3DXRS_FLOAT4, registerset_blob_struct_struct, + registerset_test_struct_struct_int_float, ARRAY_SIZE(registerset_test_struct_struct_int_float), + registerset_constants_struct_struct_int_float, ARRAY_SIZE(registerset_constants_struct_struct_int_float)}, + /* special */ + {"int ran", "ran", 0, D3DXRS_INT4, registerset_blob_special_int, NULL, 0, + registerset_constants_special_int, ARRAY_SIZE(registerset_constants_special_int)}, + {"bigvec", "vaf", 0, D3DXRS_FLOAT4, registerset_blob_bigvec, + registerset_test_bigvec_float, ARRAY_SIZE(registerset_test_bigvec_float), + registerset_constants_bigvec_float, ARRAY_SIZE(registerset_constants_bigvec_float)}, + {"cf", "cf", 0, D3DXRS_FLOAT4, registerset_blob_matrix_column_clamp, + registerset_test_matrix_column_clamp, ARRAY_SIZE(registerset_test_matrix_column_clamp), + registerset_constants_matrix_column_clamp, ARRAY_SIZE(registerset_constants_matrix_column_clamp)}, +}; + +static void registerset_clear(IDirect3DDevice9 *device) +{ + DWORD zero[1024]; + HRESULT hr; + + memset(zero, 0xde, 4096); + + hr = IDirect3DDevice9_SetVertexShaderConstantF(device, 0, (FLOAT*)zero, 256); + ok(hr == D3D_OK, "Clear failed, got %08x, expected %08x\n", hr, D3D_OK); + + hr = IDirect3DDevice9_SetPixelShaderConstantF(device, 0, (FLOAT*)zero, 224); + ok(hr == D3D_OK, "Clear failed, got %08x, expected %08x\n", hr, D3D_OK); + + hr = IDirect3DDevice9_SetVertexShaderConstantB(device, 0, (BOOL*)zero, 16); + ok(hr == D3D_OK, "Clear failed, got %08x, expected %08x\n", hr, D3D_OK); + + hr = IDirect3DDevice9_SetPixelShaderConstantB(device, 0, (BOOL*)zero, 16); + ok(hr == D3D_OK, "Clear failed, got %08x, expected %08x\n", hr, D3D_OK); + + hr = IDirect3DDevice9_SetVertexShaderConstantI(device, 0, (INT*)zero, 16); + ok(hr == D3D_OK, "Clear failed, got %08x, expected %08x\n", hr, D3D_OK); + + hr = IDirect3DDevice9_SetPixelShaderConstantI(device, 0, (INT*)zero, 16); + ok(hr == D3D_OK, "Clear failed, got %08x, expected %08x\n", hr, D3D_OK); +} + +static UINT registerset_compare(IDirect3DDevice9 *device, BOOL is_vs, D3DXREGISTER_SET regset, + UINT start, UINT in_count, const DWORD *expected) +{ + DWORD ret[1024] = {0}; + HRESULT hr; + UINT count = 1024, i, err = 0; + + memset(ret, 0xde, 4096); + + /* get shader constants */ + switch (regset) + { + case D3DXRS_BOOL: + count = 16; + if (is_vs) hr = IDirect3DDevice9_GetVertexShaderConstantB(device, 0, (BOOL*)ret, 16); + else hr = IDirect3DDevice9_GetPixelShaderConstantB(device, 0, (BOOL*)ret, 16); + ok(hr == D3D_OK, "Get*ShaderConstantB failed, got %08x\n", hr); + break; + + case D3DXRS_INT4: + count = 256; + if (is_vs) hr = IDirect3DDevice9_GetVertexShaderConstantI(device, 0, (INT*)ret, 16); + else hr = IDirect3DDevice9_GetPixelShaderConstantI(device, 0, (INT*)ret, 16); + ok(hr == D3D_OK, "Get*ShaderConstantI failed, got %08x\n", hr); + break; + + case D3DXRS_FLOAT4: + if (is_vs) hr = IDirect3DDevice9_GetVertexShaderConstantF(device, 0, (FLOAT*)ret, 256); + else + { + count = 896; + hr = IDirect3DDevice9_GetPixelShaderConstantF(device, 0, (FLOAT*)ret, 224); + } + ok(hr == D3D_OK, "Get*ShaderConstantF failed, got %08x\n", hr); + break; + + default: + ok(0, "This should not happen!\n"); + break; + } + + /* compare shader constants */ + for (i = 0; i < count; ++i) + { + DWORD value = 0xdededede; + if (i >= start && i < start + in_count) value = expected[i - start]; + + ok(ret[i] == value, "Get*ShaderConstant failed, %u got 0x%x(%f) expected 0x%x(%f)\n", i, + ret[i], ((FLOAT *)ret)[i], value, *((FLOAT *)&value)); + if (ret[i] != value) err++; + } + + return err; +} + +static UINT registerset_compare_all(IDirect3DDevice9 *device, BOOL is_vs, D3DXREGISTER_SET regset, + UINT start, UINT in_count, const DWORD *expected) +{ + D3DXREGISTER_SET regsets[] = {D3DXRS_BOOL, D3DXRS_INT4, D3DXRS_FLOAT4}; + UINT err = 0, i; + + for (i = 0; i < ARRAY_SIZE(regsets); i++) + { + if (regset == regsets[i]) + err += registerset_compare(device, is_vs, regset, start, in_count, expected); + else + err += registerset_compare(device, is_vs, regsets[i], 0, 0, NULL); + + err += registerset_compare(device, !is_vs, regsets[i], 0, 0, NULL); + } + + return err; +} + +static HRESULT registerset_apply(ID3DXConstantTable *ctable, IDirect3DDevice9 *device, D3DXHANDLE constant, + UINT index, DWORD count, enum Type type) +{ + const DWORD *in = registerset_test_input[index]; + const D3DXMATRIX *inp[REGISTER_OUTPUT_SIZE / 16]; + unsigned int i; + + /* overlap, to see the difference between Array and PointerArray */ + for (i = 0; i < REGISTER_OUTPUT_SIZE / 16; i++) + { + inp[i] = (D3DXMATRIX *)&in[i * 15]; + } + + switch (type) + { + case SetInt: + return ID3DXConstantTable_SetInt(ctable, device, constant, *((INT *)in)); + case SetFloat: + return ID3DXConstantTable_SetFloat(ctable, device, constant, *((FLOAT *)in)); + case SetBool: + return ID3DXConstantTable_SetBool(ctable, device, constant, *((BOOL *)in)); + case SetIntArray: + return ID3DXConstantTable_SetIntArray(ctable, device, constant, (INT *)in, count); + case SetBoolArray: + return ID3DXConstantTable_SetBoolArray(ctable, device, constant, (BOOL *)in, count); + case SetFloatArray: + return ID3DXConstantTable_SetFloatArray(ctable, device, constant, (FLOAT *)in, count); + case SetMatrix: + return ID3DXConstantTable_SetMatrix(ctable, device, constant, (D3DXMATRIX *)in); + case SetMatrixTranspose: + return ID3DXConstantTable_SetMatrixTranspose(ctable, device, constant, (D3DXMATRIX *)in); + case SetMatrixArray: + return ID3DXConstantTable_SetMatrixArray(ctable, device, constant, (D3DXMATRIX *)in, count); + case SetMatrixTransposeArray: + return ID3DXConstantTable_SetMatrixTransposeArray(ctable, device, constant, (D3DXMATRIX *)in, count); + case SetVector: + return ID3DXConstantTable_SetVector(ctable, device, constant, (D3DXVECTOR4 *)in); + case SetVectorArray: + return ID3DXConstantTable_SetVectorArray(ctable, device, constant, (D3DXVECTOR4 *)in, count); + case SetValue: + return ID3DXConstantTable_SetValue(ctable, device, constant, in, count); + case SetMatrixPointerArray: + return ID3DXConstantTable_SetMatrixPointerArray(ctable, device, constant, inp, count); + case SetMatrixTransposePointerArray: + return ID3DXConstantTable_SetMatrixTransposePointerArray(ctable, device, constant, inp, count); + } + + ok(0, "This should not happen!\n"); + return D3D_OK; +} + +static void test_registerset(void) +{ + UINT k; + HWND wnd; + IDirect3D9 *d3d; + IDirect3DDevice9 *device; + D3DPRESENT_PARAMETERS d3dpp; + HRESULT hr; + ULONG count; + D3DCAPS9 caps; + + 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 = IDirect3DDevice9_GetDeviceCaps(device, &caps); + ok(SUCCEEDED(hr), "Failed to get device caps, hr %#x.\n", hr); + if (caps.VertexShaderVersion < D3DVS_VERSION(3, 0) + || caps.PixelShaderVersion < D3DPS_VERSION(3, 0)) + { + skip("Skipping: Test requires VS >= 3 and PS >= 3.\n"); + IDirect3DDevice9_Release(device); + IDirect3D9_Release(d3d); + DestroyWindow(wnd); + return; + } + + for (k = 0; k < ARRAY_SIZE(registerset_data); ++k) + { + const char *tablename = registerset_data[k].name; + const char *name = registerset_data[k].var; + ID3DXConstantTable *ctable; + D3DXCONSTANTTABLE_DESC tdesc; + D3DXHANDLE constant; + UINT i; + BOOL is_vs; + DWORD *ctab; + + hr = D3DXGetShaderConstantTable(registerset_data[k].blob, &ctable); + ok(hr == D3D_OK, "D3DXGetShaderConstantTable \"%s\" failed, got %08x, expected %08x\n", tablename, hr, D3D_OK); + + hr = ID3DXConstantTable_GetDesc(ctable, &tdesc); + ok(hr == D3D_OK, "GetDesc \"%s\" failed, got %08x, expected %08x\n", tablename, hr, D3D_OK); + + ctab = ID3DXConstantTable_GetBufferPointer(ctable); + ok(ctab[0] == registerset_data[k].blob[3], "ID3DXConstantTable_GetBufferPointer failed\n"); + + is_vs = (tdesc.Version & 0xFFFF0000) == 0xFFFE0000; + + for (i = 0; i < registerset_data[k].constant_count; ++i) + { + const char *fullname = registerset_data[k].constants[i].fullname; + const D3DXCONSTANT_DESC *expected_desc = ®isterset_data[k].constants[i].desc; + D3DXCONSTANT_DESC desc; + UINT nr = 0; + UINT ctaboffset = registerset_data[k].constants[i].ctaboffset; + + constant = ID3DXConstantTable_GetConstantByName(ctable, NULL, fullname); + ok(constant != NULL, "GetConstantByName \"%s\" failed\n", fullname); + + hr = ID3DXConstantTable_GetConstantDesc(ctable, constant, &desc, &nr); + ok(hr == D3D_OK, "GetConstantDesc \"%s\" failed, got %08x, expected %08x\n", fullname, hr, D3D_OK); + + ok(!strcmp(expected_desc->Name, desc.Name), "GetConstantDesc \"%s\" failed, got \"%s\", expected \"%s\"\n", + fullname, desc.Name, expected_desc->Name); + ok(expected_desc->RegisterSet == desc.RegisterSet, "GetConstantDesc \"%s\" failed, got %#x, expected %#x\n", + fullname, desc.RegisterSet, expected_desc->RegisterSet); + ok(expected_desc->RegisterIndex == desc.RegisterIndex, + "GetConstantDesc \"%s\" failed, got %u, expected %u\n", + fullname, desc.RegisterIndex, expected_desc->RegisterIndex); + ok(expected_desc->RegisterCount == desc.RegisterCount, + "GetConstantDesc \"%s\" failed, got %u, expected %u\n", + fullname, desc.RegisterCount, expected_desc->RegisterCount); + ok(expected_desc->Class == desc.Class, "GetConstantDesc \"%s\" failed, got %u, expected %u\n", + fullname, desc.Class, expected_desc->Class); + ok(expected_desc->Type == desc.Type, "GetConstantDesc \"%s\" failed, got %#x, expected %#x\n", + fullname, desc.Type, expected_desc->Type); + ok(expected_desc->Rows == desc.Rows, "GetConstantDesc \"%s\" failed, got %#x, expected %#x\n", + fullname, desc.Rows, expected_desc->Rows); + ok(expected_desc->Columns == desc.Columns, "GetConstantDesc \"%s\" failed, got %u, expected %u\n", + fullname, desc.Columns, expected_desc->Columns); + ok(expected_desc->Elements == desc.Elements, "GetConstantDesc \"%s\" failed, got %u, expected %u\n", + fullname, desc.Elements, expected_desc->Elements); + ok(expected_desc->StructMembers == desc.StructMembers, + "GetConstantDesc \"%s\" failed, got %u, expected %u\n", + fullname, desc.StructMembers, expected_desc->StructMembers); + ok(expected_desc->Bytes == desc.Bytes, "GetConstantDesc \"%s\" failed, got %u, expected %u\n", + fullname, desc.Bytes, expected_desc->Bytes); + if (ctaboffset) + { + ok(ctaboffset == (DWORD *)desc.DefaultValue - ctab, + "GetConstantDesc \"%s\" failed, got %u, expected %u\n", + fullname, (UINT)((DWORD *)desc.DefaultValue - ctab), ctaboffset); + } + } + + constant = ID3DXConstantTable_GetConstantByName(ctable, NULL, name); + ok(constant != NULL, "GetConstantByName \"%s\" \"%s\" failed\n", tablename, name); + + for (i = 0; i < registerset_data[k].test_count; ++i) + { + const struct registerset_test *test = ®isterset_data[k].tests[i]; + UINT ret; + + registerset_clear(device); + + hr = registerset_apply(ctable, device, constant, test->in_index, test->in_count_min, test->type); + ok(hr == D3D_OK, "Set* \"%s\" index %u, count %u failed, got %x, expected %x\n", tablename, i, + test->in_count_min, hr, D3D_OK); + + ret = registerset_compare_all(device, is_vs, registerset_data[k].regset, + registerset_data[k].start, test->out_count, test->out); + ok(ret == 0, "Get*ShaderConstant \"%s\" index %u, count %u failed\n", tablename, i, test->in_count_min); + + if (test->in_count_max > test->in_count_min) + { + registerset_clear(device); + + hr = registerset_apply(ctable, device, constant, test->in_index, test->in_count_max, test->type); + ok(hr == D3D_OK, "Set* \"%s\" index %u, count %u failed, got %x, expected %x\n", tablename, i, + test->in_count_max, hr, D3D_OK); + + ret = registerset_compare_all(device, is_vs, registerset_data[k].regset, + registerset_data[k].start, test->out_count, test->out); + ok(ret == 0, "Get*ShaderConstant \"%s\" index %u, count %u failed\n", tablename, i, test->in_count_max); + } + } + + count = ID3DXConstantTable_Release(ctable); + ok(count == 0, "Release \"%s\" failed, got %u, expected %u\n", tablename, count, 0); + } + + /* Release resources */ + count = IDirect3DDevice9_Release(device); + ok(count == 0, "The Direct3D device reference count was %u, should be 0\n", count); + + count = IDirect3D9_Release(d3d); + ok(count == 0, "The Direct3D object referenct count was %u, should be 0\n", count); + + if (wnd) DestroyWindow(wnd); +} + +/* + * For D3DXRS_INT4 (int_count, ints[]): + * Native seems to just set the following shader blob up to the register count, which in bad cases is up + * to 4 times larger than the actual correct value. This explanes where the "bogus" values for these cases + * come from. Somehow they forgot that the registers are INT4 and not INT. + */ +static const struct +{ + const char *name; + const DWORD *blob; + unsigned int float_count; + unsigned int int_count; + unsigned int bool_count; + const DWORD floats[1024]; + const DWORD ints[256]; + const DWORD bools[16]; +} +registerset_defaults_data[] = +{ + {"scalar", registerset_blob_scalar, 12, 4, 1, + {0x40a33333, 0x00000000, 0x00000000, 0x00000000, 0x41300000, 0x00000000, 0x00000000, 0x00000000, + 0x3f800000, 0x00000000, 0x00000000, 0x00000000}, + {0x00000008, 0x00000000, 0x00000001}, + {0xffffffff}}, + {"scalar array", registerset_blob_scalar_array, 24, 8, 2, + {0x40466666, 0x00000000, 0x00000000, 0x00000000, 0x404ccccd, 0x00000000, 0x00000000, 0x00000000, + 0x41600000, 0x00000000, 0x00000000, 0x00000000, 0x41700000, 0x00000000, 0x00000000, 0x00000000, + 0x3f800000, 0x00000000, 0x00000000, 0x00000000, 0x3f800000, 0x00000000, 0x00000000, 0x00000000}, + {0x00000020, 0x00000000, 0x00000001, 0x00000000, 0x00000021, 0x00000000, 0x00000001, 0x00000000}, + {0xffffffff, 0x00000000}}, + {"vector", registerset_blob_vector, 12, 12, 3, + {0x40a33333, 0x40a66666, 0x40a9999a, 0x00000000, 0x41300000, 0x42aa0000, 0x42780000, 0x00000000, + 0x3f800000, 0x3f800000, 0x3f800000, 0x00000000}, + {0x00000007, 0x00000008, 0x00000009, 0x00000000, 0x00666e76, 0x41300000, 0x42aa0000, 0x42780000, + 0x00000000, 0x335f7376, 0x4d00305f, 0x6f726369}, + {0xffffffff, 0x00000000, 0xffffffff}}, + {"vector array", registerset_blob_vector_array, 24, 24, 6, + {0x425c6666, 0x425ccccd, 0x425d3333, 0x00000000, 0x425d999a, 0x425e0000, 0x425e6666, 0x00000000, + 0x43020000, 0x430c0000, 0x43160000, 0x00000000, 0x43200000, 0x432a0000, 0x43340000, 0x00000000, + 0x3f800000, 0x3f800000, 0x3f800000, 0x00000000, 0x3f800000, 0x3f800000, 0x3f800000, 0x00000000}, + {0x00000046, 0x00000050, 0x0000005a, 0x00000000, 0x00000064, 0x0000006e, 0x00000078, 0x00000000, + 0x666e6176, 0xababab00, 0x00020001, 0x00030001, 0x00000002, 0x00000000, 0x43020000, 0x430c0000, + 0x43160000, 0x00000000, 0x43200000, 0x432a0000, 0x43340000, 0x00000000, 0x335f7376, 0x4d00305f}, + {0xffffffff, 0x00000000, 0xffffffff, 0xffffffff, 0x00000000, 0xffffffff}}, + {"column", registerset_blob_column, 24, 24, 6, + {0x4171999a, 0x4174cccd, 0x41780000, 0x00000000, 0x41733333, 0x41766666, 0x4179999a, 0x00000000, + 0x3f800000, 0x00000000, 0x00000000, 0x00000000, 0x3f800000, 0x3f800000, 0x3f800000, 0x00000000, + 0x41f00000, 0x42040000, 0x42080000, 0x00000000, 0x41f80000, 0x42000000, 0x42100000, 0x00000000}, + {0x00000004, 0x00000006, 0x00000008, 0x00000000, 0x00000005, 0x00000007, 0x00000009, 0x00000000, + 0x00666e63, 0x41f00000, 0x42040000, 0x42080000, 0x00000000, 0x41f80000, 0x42000000, 0x42100000, + 0x00000000, 0x335f7376, 0x4d00305f, 0x6f726369, 0x74666f73, 0x29522820, 0x534c4820, 0x6853204c}, + {0xffffffff, 0x00000000, 0xffffffff, 0xffffffff, 0x00000000, 0xffffffff}}, + {"column array", registerset_blob_column_array, 48, 48, 12, + {0x3f8ccccd, 0x40533333, 0x40b00000, 0x00000000, 0x400ccccd, 0x408ccccd, 0x40d33333, 0x00000000, + 0x40f66666, 0x411e6666, 0x3fa66666, 0x00000000, 0x410ccccd, 0x3f99999a, 0x3fb33333, 0x00000000, + 0x3f800000, 0x00000000, 0x00000000, 0x00000000, 0x3f800000, 0x3f800000, 0x3f800000, 0x00000000, + 0x3f800000, 0x00000000, 0x00000000, 0x00000000, 0x3f800000, 0x3f800000, 0x3f800000, 0x00000000, + 0x43960000, 0x43978000, 0x43980000, 0x00000000, 0x43968000, 0x43970000, 0x43990000, 0x00000000, + 0x43af0000, 0x44238000, 0x43a30000, 0x00000000, 0x43b68000, 0x44190000, 0x4479c000, 0x00000000}, + {0x0000000e, 0x00000010, 0x00000012, 0x00000000, 0x0000000f, 0x00000047, 0x00000013, 0x00000000, + 0x00000037, 0x00000060, 0x00000061, 0x00000000, 0x0000003f, 0x00000060, 0x0000000d, 0x00000000, + 0x666e6163, 0xababab00, 0x00020003, 0x00020003, 0x00000002, 0x00000000, 0x43960000, 0x43978000, + 0x43980000, 0x00000000, 0x43968000, 0x43970000, 0x43990000, 0x00000000, 0x43af0000, 0x44238000, + 0x43a30000, 0x00000000, 0x43b68000, 0x44190000, 0x4479c000, 0x00000000, 0x335f7376, 0x4d00305f, + 0x6f726369, 0x74666f73, 0x29522820, 0x534c4820, 0x6853204c, 0x72656461, 0x6d6f4320, 0x656c6970}, + {0xffffffff, 0x00000000, 0xffffffff, 0xffffffff, 0x00000000, 0xffffffff, 0xffffffff, 0x00000000, + 0xffffffff, 0xffffffff, 0x00000000, 0xffffffff}}, + {"row", registerset_blob_row, 36, 24, 6, + {0x42be3333, 0x42be6666, 0x00000000, 0x00000000, 0x42be999a, 0x42becccd, 0x00000000, 0x00000000, + 0x42bf0000, 0x42bf3333, 0x00000000, 0x00000000, 0x3f800000, 0x3f800000, 0x00000000, 0x00000000, + 0x3f800000, 0x3f800000, 0x00000000, 0x00000000, 0x00000000, 0x3f800000, 0x00000000, 0x00000000, + 0x42140000, 0x41500000, 0x00000000, 0x00000000, 0x42c40000, 0x42580000, 0x00000000, 0x00000000, + 0x429a0000, 0x42100000, 0x00000000, 0x00000000}, + {0x00000050, 0x00000051, 0x00000001, 0x00000000, 0x00000052, 0x00000053, 0x00000001, 0x00000000, + 0x00000054, 0x00000055, 0x00000001, 0x00000000, 0x00666e72, 0x42140000, 0x41500000, 0x00000000, + 0x00000000, 0x42c40000, 0x42580000, 0x00000000, 0x00000000, 0x429a0000, 0x42100000, 0x00000000}, + {0xffffffff, 0xffffffff, 0x00000000, 0x00000000, 0xffffffff, 0xffffffff}}, + {"row array", registerset_blob_row_array, 72, 48, 12, + {0x3fc00000, 0x40333333, 0x00000000, 0x00000000, 0x40533333, 0x409ccccd, 0x00000000, 0x00000000, + 0x40bccccd, 0x40d9999a, 0x00000000, 0x00000000, 0x40fccccd, 0x41080000, 0x00000000, 0x00000000, + 0x41166666, 0x3fa66666, 0x00000000, 0x00000000, 0x3f99999a, 0x3f8ccccd, 0x00000000, 0x00000000, + 0x3f800000, 0x3f800000, 0x00000000, 0x00000000, 0x3f800000, 0x3f800000, 0x00000000, 0x00000000, + 0x00000000, 0x3f800000, 0x00000000, 0x00000000, 0x3f800000, 0x3f800000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x3f800000, 0x00000000, 0x00000000, + 0x420c0000, 0x42200000, 0x00000000, 0x00000000, 0x42700000, 0x42a00000, 0x00000000, 0x00000000, + 0x428c0000, 0x42600000, 0x00000000, 0x00000000, 0x42140000, 0x41500000, 0x00000000, 0x00000000, + 0x42c40000, 0x42580000, 0x00000000, 0x00000000, 0x429a0000, 0x42100000, 0x00000000, 0x00000000}, + {0x00000004, 0x00000005, 0x00000001, 0x00000000, 0x00000006, 0x00000001, 0x00000001, 0x00000000, + 0x00000008, 0x00000001, 0x00000001, 0x00000000, 0x00000005, 0x00000003, 0x00000001, 0x00000000, + 0x00000009, 0x00000006, 0x00000001, 0x00000000, 0x00000007, 0x00000003, 0x00000001, 0x00000000, + 0x666e6172, 0xababab00, 0x00020002, 0x00020003, 0x00000002, 0x00000000, 0x420c0000, 0x42200000, + 0x00000000, 0x00000000, 0x42700000, 0x42a00000, 0x00000000, 0x00000000, 0x428c0000, 0x42600000, + 0x00000000, 0x00000000, 0x42140000, 0x41500000, 0x00000000, 0x00000000, 0x42c40000, 0x42580000}, + {0xffffffff, 0x00000000, 0x00000000, 0xffffffff, 0x00000000, 0xffffffff, 0x00000000, 0x00000000, + 0xffffffff, 0xffffffff, 0x00000000, 0xffffffff}}, + {"struct", registerset_blob_struct, 24, 16, 4, + {0x3f8ccccd, 0x00000000, 0x00000000, 0x00000000, 0x400ccccd, 0x40533333, 0x408ccccd, 0x00000000, + 0x41f80000, 0x00000000, 0x00000000, 0x00000000, 0x42000000, 0x42040000, 0x42080000, 0x00000000, + 0x3f800000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x3f800000, 0x00000000}, + {0x0000000b, 0x00000000, 0x00000001, 0x00000000, 0x0000000c, 0x0000000d, 0x0000000e, 0x00000000, + 0x00666e73, 0x7600666e, 0xab00666e, 0x00000204, 0x0000019c, 0x00000207, 0x000001b0, 0x00000005}, + {0xffffffff, 0xffffffff, 0x00000000, 0xffffffff}}, + {"struct array", registerset_blob_struct_array, 48, 32, 8, + {0x3f8ccccd, 0x00000000, 0x00000000, 0x00000000, 0x40066666, 0x40466666, 0x40833333, 0x00000000, + 0x40a33333, 0x00000000, 0x00000000, 0x00000000, 0x40c33333, 0x40e33333, 0x4101999a, 0x00000000, + 0x42240000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x422c0000, 0x42300000, 0x00000000, + 0x42240000, 0x00000000, 0x00000000, 0x00000000, 0x42280000, 0x422c0000, 0x42300000, 0x00000000, + 0x3f800000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x3f800000, 0x00000000, + 0x3f800000, 0x00000000, 0x00000000, 0x00000000, 0x3f800000, 0x00000000, 0x3f800000, 0x00000000}, + {0x00000015, 0x00000000, 0x00000001, 0x00000000, 0x00000016, 0x00000017, 0x00000018, 0x00000000, + 0x00000019, 0x00000000, 0x00000001, 0x00000000, 0x0000001a, 0x0000001b, 0x0000001c, 0x00000000, + 0x666e6173, 0x00666e00, 0x00666e76, 0x00000275, 0x000001ec, 0x00000278, 0x00000200, 0x00000005, + 0x00040001, 0x00020002, 0x0000027c, 0x42240000, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, + {0xffffffff, 0xffffffff, 0x00000000, 0xffffffff, 0x00000000, 0xffffffff, 0x00000000, 0xffffffff}}, + {"struct struct", registerset_blob_struct_struct, 48, 24, 6, + {0x3f8ccccd, 0x00000000, 0x00000000, 0x00000000, 0x40066666, 0x00000000, 0x00000000, 0x00000000, + 0x40466666, 0x40833333, 0x40a33333, 0x00000000, 0x40c33333, 0x00000000, 0x00000000, 0x00000000, + 0x42240000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x422c0000, 0x42300000, 0x42240000, 0x00000000, 0x42280000, 0x00000000, 0x00000000, 0x00000000, + 0x3f800000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x3f800000, 0x3f800000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, + {0x00000047, 0x00000000, 0x00000001, 0x00000000, 0x00000048, 0x00000000, 0x00000001, 0x00000000, + 0x00000049, 0x0000004a, 0x0000004b, 0x00000000, 0x0000004c, 0x00000000, 0x00000001, 0x00000000, + 0x666e7373, 0x00666e00, 0x00666e76, 0x00000321, 0x0000026c, 0x00000324, 0x00000280, 0x00000005}, + {0xffffffff, 0xffffffff, 0x00000000, 0xffffffff, 0xffffffff, 0x00000000}}, + {"int ran", registerset_blob_special_int, 0, 36, 0, + {0x00000000}, + {0x00000004, 0x00000005, 0x00000001, 0x00000000, 0x00000006, 0x00000001, 0x00000001, 0x00000000, + 0x00000008, 0x00000001, 0x00000001, 0x00000000, 0x00000002, 0x00000003, 0x00000001, 0x00000000, + 0x00000004, 0x00000007, 0x00000001, 0x00000000, 0x00000009, 0x00000001, 0x00000001, 0x00000000, + 0x335f7376, 0x4d00305f, 0x6f726369, 0x74666f73, 0x29522820, 0x534c4820, 0x6853204c, 0x72656461, + 0x6d6f4320, 0x656c6970, 0x2e392072, 0x392e3932}, + {0x00000000}}, + /* DefaultValue = NULL */ + {"big vector", registerset_blob_bigvec}, + {"matrix column clamp", registerset_blob_matrix_column_clamp, 12, 0, 0, + {0x3f8ccccd, 0x40b00000, 0x411e6666, 0x3fc00000, 0x400ccccd, 0x40d33333, 0x3f99999a, 0x3fcccccd, + 0x420551ec, 0x00000000, 0x00000000, 0x00000000}, + {0x00000000}, + {0x00000000}}, +}; + +static void test_registerset_defaults(void) +{ + UINT k; + HWND wnd; + IDirect3D9 *d3d; + IDirect3DDevice9 *device; + D3DPRESENT_PARAMETERS d3dpp; + HRESULT hr; + ULONG count; + D3DCAPS9 caps; + + 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 = IDirect3DDevice9_GetDeviceCaps(device, &caps); + ok(SUCCEEDED(hr), "Failed to get device caps, hr %#x.\n", hr); + if (caps.VertexShaderVersion < D3DVS_VERSION(3, 0) + || caps.PixelShaderVersion < D3DPS_VERSION(3, 0)) + { + skip("Skipping: Test requires VS >= 3 and PS >= 3.\n"); + IDirect3DDevice9_Release(device); + IDirect3D9_Release(d3d); + DestroyWindow(wnd); + return; + } + + for (k = 0; k < ARRAY_SIZE(registerset_defaults_data); ++k) + { + const char *tablename = registerset_defaults_data[k].name; + ID3DXConstantTable *ctable; + D3DXCONSTANTTABLE_DESC tdesc; + BOOL is_vs; + UINT ret; + + hr = D3DXGetShaderConstantTable(registerset_defaults_data[k].blob, &ctable); + ok(hr == D3D_OK, "D3DXGetShaderConstantTable \"%s\" failed, got %08x, expected %08x\n", tablename, hr, D3D_OK); + + hr = ID3DXConstantTable_GetDesc(ctable, &tdesc); + ok(hr == D3D_OK, "GetDesc \"%s\" failed, got %08x, expected %08x\n", tablename, hr, D3D_OK); + + is_vs = (tdesc.Version & 0xFFFF0000) == 0xFFFE0000; + + registerset_clear(device); + + hr = ID3DXConstantTable_SetDefaults(ctable, device); + ok(hr == D3D_OK, "SetDefaults \"%s\" failed, got %08x, expected %08x\n", tablename, hr, D3D_OK); + + ret = registerset_compare(device, is_vs, D3DXRS_FLOAT4, 0, registerset_defaults_data[k].float_count, + registerset_defaults_data[k].floats); + ok(ret == 0, "Get*ShaderConstantF \"%s\" failed\n", tablename); + + ret = registerset_compare(device, is_vs, D3DXRS_INT4, 0, registerset_defaults_data[k].int_count, + registerset_defaults_data[k].ints); + ok(ret == 0, "Get*ShaderConstantI \"%s\" failed\n", tablename); + + ret = registerset_compare(device, is_vs, D3DXRS_BOOL, 0, registerset_defaults_data[k].bool_count, + registerset_defaults_data[k].bools); + ok(ret == 0, "Get*ShaderConstantB \"%s\" failed\n", tablename); + + count = ID3DXConstantTable_Release(ctable); + ok(count == 0, "Release \"%s\" failed, got %u, expected %u\n", tablename, count, 0); + } + + /* Release resources */ + count = IDirect3DDevice9_Release(device); + ok(count == 0, "The Direct3D device reference count was %u, should be 0\n", count); + + count = IDirect3D9_Release(d3d); + ok(count == 0, "The Direct3D object referenct count was %u, should be 0\n", count); + + if (wnd) DestroyWindow(wnd); +} + +static void test_shader_semantics(void) +{ + static const DWORD invalid_1[] = + { + 0x00000200 + }, + invalid_2[] = + { + 0xfffe0400 + }, + invalid_3[] = + { + 0xfffe0000 + }, + vs_1_1[] = + { + 0xfffe0101, /* vs_1_1 */ + 0x0000001f, 0x80000000, 0x900f0000, /* dcl_position v0 */ + 0x0000001f, 0x80000003, 0x900f0001, /* dcl_normal v1 */ + 0x0000001f, 0x8001000a, 0x900f0002, /* dcl_color1 v2 */ + 0x0000001f, 0x80000005, 0x900f0003, /* dcl_texcoord0 v3 */ + 0x00000001, 0xc00f0000, 0x90e40000, /* mov oPos, v0 */ + 0x00000001, 0xd00f0001, 0x90e40002, /* mov oD1, v2 */ + 0x00000001, 0xe0070000, 0x90e40001, /* mov oT0.xyz, v1 */ + 0x00000001, 0xc00f0001, 0x90ff0002, /* mov oFog, v2.w */ + 0x00000001, 0xc00f0002, 0x90ff0001, /* mov oPts, v1.w */ + 0x0000ffff + }, + vs_2_0[] = + { + 0xfffe0200, /* vs_2_0 */ + 0x0200001f, 0x80000000, 0x900f0000, /* dcl_position v0 */ + 0x0200001f, 0x80000003, 0x900f0001, /* dcl_normal v1 */ + 0x0200001f, 0x8001000a, 0x900f0002, /* dcl_color1 v2 */ + 0x0200001f, 0x80000005, 0x900f0003, /* dcl_texcoord0 v3 */ + 0x02000001, 0xc00f0000, 0x90e40000, /* mov oPos, v0 */ + 0x02000001, 0xd00f0001, 0x90e40002, /* mov oD1, v2 */ + 0x02000001, 0xe0070000, 0x90e40003, /* mov oT0.xyz, v3 */ + 0x02000001, 0xc00f0001, 0x90ff0002, /* mov oFog, v2.w */ + 0x02000001, 0xc00f0002, 0x90ff0001, /* mov oPts, v1.w */ + 0x0000ffff + }, + vs_3_0[] = + { + 0xfffe0300, /* vs_3_0 */ + 0x0002fffe, 0x0200000f, 0x00000000, /* comment */ + 0x0200001f, 0x80000000, 0x900f0000, /* dcl_position v0 */ + 0x0200001f, 0x80000003, 0x900f0001, /* dcl_normal v1 */ + 0x0200001f, 0x8001000a, 0x900f0002, /* dcl_color1 v2 */ + 0x0200001f, 0x80000005, 0x900f0003, /* dcl_texcoord0 v3 */ + 0x0200001f, 0x80000000, 0xe00f0000, /* dcl_position o0 */ + 0x0200001f, 0x8001000a, 0xe00f0001, /* dcl_color1 o1 */ + 0x0200001f, 0x80000005, 0xe00f0002, /* dcl_texcoord0 o2 */ + 0x0200001f, 0x8000000b, 0xe00f0003, /* dcl_fog o3 */ + 0x0200001f, 0x80000004, 0xe00f0004, /* dcl_psize o4 */ + 0x02000001, 0xe00f0000, 0x90e40000, /* mov o0, v0 */ + 0x02000001, 0xe00f0001, 0x90e40002, /* mov o1, v2 */ + 0x02000001, 0xe0070002, 0x90e40003, /* mov o2.xyz, v3 */ + 0x02000001, 0xe00f0003, 0x90ff0002, /* mov o3, v2.w */ + 0x02000001, 0xe00f0004, 0x90ff0001, /* mov o4, v1.w */ + 0x0000ffff + }, + ps_1_1[] = + { + 0xffff0101, /* ps_1_1 */ + 0x00000042, 0xb00f0000, /* tex t0 */ + 0x00000002, 0x800f0000, 0x90e40000, 0xb0e40000, /* add r0, v0, t0 */ + 0x0000ffff + }, + ps_2_0[] = + { + 0xffff0200, /* ps_2_0 */ + 0x0200001f, 0x80000000, 0x900f0000, /* dcl v0 */ + 0x0200001f, 0x80000000, 0xb00f0000, /* dcl t0 */ + 0x02000001, 0x800f0800, 0x90e40000, /* mov oC0, v0 */ + 0x0000ffff + }, + ps_3_0[] = + { + 0xffff0300, /* ps_3_0 */ + 0x0200001f, 0x8001000a, 0x900f0000, /* dcl_color1 v0 */ + 0x0200001f, 0x80000003, 0x900f0001, /* dcl_normal v1 */ + 0x0200001f, 0x80000005, 0x900f0002, /* dcl_texcoord0 v2 */ + 0x0200001f, 0x8000000b, 0x900f0003, /* dcl_fog v3 */ + 0x0200001f, 0x80000000, 0x90031000, /* dcl vPos.xy */ + 0x0200001f, 0x80000000, 0x900f1001, /* dcl vFace */ + 0x05000051, 0xa00f0000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, /* def c0, 0.0, 0.0, 0.0, 0.0 */ + 0x02000001, 0x800f0000, 0x90e40000, /* mov r0, v0 */ + 0x03000002, 0x800f0800, 0x80e40000, 0x90e40003, /* add oC0, r0, v3 */ + 0x02000001, 0x800f0001, 0x90e40001, /* mov r1, v1 */ + 0x03000005, 0x800f0801, 0x80e40001, 0x90e40002, /* mul oC1, r1, v2 */ + 0x02000001, 0x800f0802, 0x90441000, /* mov oC2, vPos.xyxy */ + 0x04000058, 0x800f0803, 0x90e41001, 0x90e40000, 0xa0e40000, /* cmp oC3, vFace, v0, c0 */ + 0x02000001, 0x900f0800, 0x90ff0001, /* mov oDepth, v1.w */ + 0x0000ffff + }; + static const struct + { + const DWORD *shader; + D3DXSEMANTIC expected_input[MAXD3DDECLLENGTH]; + D3DXSEMANTIC expected_output[MAXD3DDECLLENGTH]; + } + tests[] = + { + {vs_1_1, {{0, 0}, {3, 0}, {10, 1}, {5, 0}, {~0, ~0}}, {{5, 0}, {10, 1}, {0, 0}, {11, 0}, {4, 0}, {~0, ~0}}}, + {vs_2_0, {{0, 0}, {3, 0}, {10, 1}, {5, 0}, {~0, ~0}}, {{5, 0}, {10, 1}, {0, 0}, {11, 0}, {4, 0}, {~0, ~0}}}, + {vs_3_0, {{0, 0}, {3, 0}, {10, 1}, {5, 0}, {~0, ~0}}, {{0, 0}, {10, 1}, {5, 0}, {11, 0}, {4, 0}, {~0, ~0}}}, + {ps_1_1, {{5, 0}, {10, 0}, {~0, ~0}}, {{10, 0}, {~0, ~0}}}, + {ps_2_0, {{10, 0}, {5, 0}, {~0, ~0}}, {{10, 0}, {~0, ~0}}}, + {ps_3_0, {{10, 1}, {3,0}, {5, 0}, {11, 0}, {~0, ~0}}, {{10, 0}, {10, 1}, {10, 2}, {10, 3}, {12, 0}, {~0, ~0}}}, + }; + D3DXSEMANTIC semantics[MAXD3DDECLLENGTH]; + unsigned int count, count2; + unsigned int i, j; + HRESULT hr; + + hr = D3DXGetShaderInputSemantics(invalid_1, NULL, NULL); + ok(hr == D3DXERR_INVALIDDATA, "Unexpected hr %#x.\n", hr); + hr = D3DXGetShaderInputSemantics(invalid_2, NULL, NULL); + ok(hr == D3D_OK, "Unexpected hr %#x.\n", hr); + hr = D3DXGetShaderInputSemantics(invalid_3, NULL, NULL); + ok(hr == D3D_OK, "Unexpected hr %#x.\n", hr); + + hr = D3DXGetShaderInputSemantics(vs_1_1, NULL, NULL); + ok(hr == D3D_OK, "Unexpected hr %#x.\n", hr); + hr = D3DXGetShaderInputSemantics(vs_1_1, semantics, NULL); + ok(hr == D3D_OK, "Unexpected hr %#x.\n", hr); + + for (i = 0; i < ARRAY_SIZE(tests); ++i) + { + const DWORD *shader = tests[i].shader; + + hr = D3DXGetShaderInputSemantics(shader, NULL, &count); + ok(hr == D3D_OK, "Unexpected hr %#x.\n", hr); + hr = D3DXGetShaderInputSemantics(shader, semantics, &count2); + ok(hr == D3D_OK, "Unexpected hr %#x.\n", hr); + ok(count == count2, "Semantics count %u differs from previous count %u.\n", count2, count); + for (j = 0; j < count; ++j) + { + ok(semantics[j].Usage == tests[i].expected_input[j].Usage + && semantics[j].UsageIndex == tests[i].expected_input[j].UsageIndex, + "Unexpected semantic %u, %u, test %u, idx %u.\n", + semantics[j].Usage, semantics[j].UsageIndex, i, j); + } + ok(tests[i].expected_input[j].Usage == ~0 && tests[i].expected_input[j].UsageIndex == ~0, + "Unexpected semantics count %u.\n", count); + hr = D3DXGetShaderOutputSemantics(shader, NULL, &count); + ok(hr == D3D_OK, "Unexpected hr %#x.\n", hr); + hr = D3DXGetShaderOutputSemantics(shader, semantics, &count2); + ok(hr == D3D_OK, "Unexpected hr %#x.\n", hr); + ok(count == count2, "Semantics count %u differs from previous count %u.\n", count2, count); + for (j = 0; j < count; ++j) + { + ok(semantics[j].Usage == tests[i].expected_output[j].Usage + && semantics[j].UsageIndex == tests[i].expected_output[j].UsageIndex, + "Unexpected semantic %u, %u, test %u, idx %u.\n", + semantics[j].Usage, semantics[j].UsageIndex, i, j); + } + ok(tests[i].expected_output[j].Usage == ~0 && tests[i].expected_output[j].UsageIndex == ~0, + "Unexpected semantics count %u.\n", count); + } +} + +START_TEST(shader) +{ + test_get_shader_size(); + test_get_shader_version(); + test_find_shader_comment(); + test_get_shader_constant_table_ex(); + test_constant_tables(); + test_setting_constants(); + test_get_sampler_index(); + test_get_shader_samplers(); + test_get_shader_constant_variables(); + test_registerset(); + test_registerset_defaults(); + test_shader_semantics(); +} diff --git a/modules/rostests/winetests/d3dx9_36/surface.c b/modules/rostests/winetests/d3dx9_36/surface.c new file mode 100644 index 00000000000..d3450722ef7 --- /dev/null +++ b/modules/rostests/winetests/d3dx9_36/surface.c @@ -0,0 +1,1465 @@ +/* + * Tests for the D3DX9 surface functions + * + * Copyright 2009 Tony Wasserka + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA + */ + +#define COBJMACROS +#include +#include "wine/test.h" +#include "d3dx9tex.h" +#include "resources.h" + +#define check_release(obj, exp) _check_release(__LINE__, obj, exp) +static inline void _check_release(unsigned int line, IUnknown *obj, int exp) +{ + int ref = IUnknown_Release(obj); + ok_(__FILE__, line)(ref == exp, "Invalid refcount. Expected %d, got %d\n", exp, ref); +} + +/* 1x1 bmp (1 bpp) */ +static const unsigned char bmp_1bpp[] = { +0x42,0x4d,0x42,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x3e,0x00,0x00,0x00,0x28,0x00, +0x00,0x00,0x01,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x01,0x00,0x01,0x00,0x00,0x00, +0x00,0x00,0x04,0x00,0x00,0x00,0x12,0x0b,0x00,0x00,0x12,0x0b,0x00,0x00,0x02,0x00, +0x00,0x00,0x02,0x00,0x00,0x00,0xf1,0xf2,0xf3,0x80,0xf4,0xf5,0xf6,0x81,0x00,0x00, +0x00,0x00 +}; + +/* 1x1 bmp (2 bpp) */ +static const unsigned char bmp_2bpp[] = { +0x42,0x4d,0x42,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x3e,0x00,0x00,0x00,0x28,0x00, +0x00,0x00,0x01,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x01,0x00,0x02,0x00,0x00,0x00, +0x00,0x00,0x04,0x00,0x00,0x00,0x12,0x0b,0x00,0x00,0x12,0x0b,0x00,0x00,0x02,0x00, +0x00,0x00,0x02,0x00,0x00,0x00,0xf1,0xf2,0xf3,0x80,0xf4,0xf5,0xf6,0x81,0x00,0x00, +0x00,0x00 +}; + +/* 1x1 bmp (4 bpp) */ +static const unsigned char bmp_4bpp[] = { +0x42,0x4d,0x42,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x3e,0x00,0x00,0x00,0x28,0x00, +0x00,0x00,0x01,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x01,0x00,0x04,0x00,0x00,0x00, +0x00,0x00,0x04,0x00,0x00,0x00,0x12,0x0b,0x00,0x00,0x12,0x0b,0x00,0x00,0x02,0x00, +0x00,0x00,0x02,0x00,0x00,0x00,0xf1,0xf2,0xf3,0x80,0xf4,0xf5,0xf6,0x81,0x00,0x00, +0x00,0x00 +}; + +/* 1x1 bmp (8 bpp) */ +static const unsigned char bmp_8bpp[] = { +0x42,0x4d,0x42,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x3e,0x00,0x00,0x00,0x28,0x00, +0x00,0x00,0x01,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x01,0x00,0x08,0x00,0x00,0x00, +0x00,0x00,0x04,0x00,0x00,0x00,0x12,0x0b,0x00,0x00,0x12,0x0b,0x00,0x00,0x02,0x00, +0x00,0x00,0x02,0x00,0x00,0x00,0xf1,0xf2,0xf3,0x80,0xf4,0xf5,0xf6,0x81,0x00,0x00, +0x00,0x00 +}; + +static const unsigned char png_grayscale[] = +{ + 0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a, 0x00, 0x00, 0x00, 0x0d, 0x49, + 0x48, 0x44, 0x52, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x08, 0x00, + 0x00, 0x00, 0x00, 0x3a, 0x7e, 0x9b, 0x55, 0x00, 0x00, 0x00, 0x0a, 0x49, 0x44, + 0x41, 0x54, 0x08, 0xd7, 0x63, 0xf8, 0x0f, 0x00, 0x01, 0x01, 0x01, 0x00, 0x1b, + 0xb6, 0xee, 0x56, 0x00, 0x00, 0x00, 0x00, 0x49, 0x45, 0x4e, 0x44, 0xae, 0x42, + 0x60, 0x82 +}; + +/* 2x2 A8R8G8B8 pixel data */ +static const unsigned char pixdata[] = { +0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff +}; + +/* invalid image file */ +static const unsigned char noimage[4] = { +0x11,0x22,0x33,0x44 +}; + +/* 2x2 24-bit dds, 2 mipmaps */ +static const unsigned char dds_24bit[] = { +0x44,0x44,0x53,0x20,0x7c,0x00,0x00,0x00,0x07,0x10,0x0a,0x00,0x02,0x00,0x00,0x00, +0x02,0x00,0x00,0x00,0x0c,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x20,0x00,0x00,0x00, +0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x18,0x00,0x00,0x00,0x00,0x00,0xff,0x00, +0x00,0xff,0x00,0x00,0xff,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x08,0x10,0x40,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff +}; + +/* 2x2 16-bit dds, no mipmaps */ +static const unsigned char dds_16bit[] = { +0x44,0x44,0x53,0x20,0x7c,0x00,0x00,0x00,0x07,0x10,0x08,0x00,0x02,0x00,0x00,0x00, +0x02,0x00,0x00,0x00,0x08,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x20,0x00,0x00,0x00, +0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x10,0x00,0x00,0x00,0x00,0x7c,0x00,0x00, +0xe0,0x03,0x00,0x00,0x1f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x10,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0xff,0x7f,0xff,0x7f,0xff,0x7f,0xff,0x7f +}; + +/* 4x4 cube map dds */ +static const unsigned char dds_cube_map[] = { +0x44,0x44,0x53,0x20,0x7c,0x00,0x00,0x00,0x07,0x10,0x08,0x00,0x04,0x00,0x00,0x00, +0x04,0x00,0x00,0x00,0x10,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x20,0x00,0x00,0x00, +0x04,0x00,0x00,0x00,0x44,0x58,0x54,0x35,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x08,0x10,0x00,0x00, +0x00,0xfe,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0xff,0xff,0x00,0x00,0x00,0x00,0x00,0x00,0xef,0x87,0x0f,0x78,0x05,0x05,0x50,0x50, +0xff,0xff,0x00,0x00,0x00,0x00,0x00,0x00,0xef,0x87,0x0f,0x78,0x05,0x05,0x50,0x50, +0xff,0xff,0x00,0x00,0x00,0x00,0x00,0x00,0xef,0x87,0x0f,0x78,0x05,0x05,0x50,0x50, +0xff,0xff,0x00,0x00,0x00,0x00,0x00,0x00,0xef,0x87,0x0f,0x78,0x05,0x05,0x50,0x50, +0xff,0xff,0x00,0x00,0x00,0x00,0x00,0x00,0xef,0x87,0x0f,0x78,0x05,0x05,0x50,0x50, +0xff,0xff,0x00,0x00,0x00,0x00,0x00,0x00,0xef,0x87,0x0f,0x78,0x05,0x05,0x50,0x50 +}; + +/* 4x4x2 volume map dds, 2 mipmaps */ +static const unsigned char dds_volume_map[] = { +0x44,0x44,0x53,0x20,0x7c,0x00,0x00,0x00,0x07,0x10,0x8a,0x00,0x04,0x00,0x00,0x00, +0x04,0x00,0x00,0x00,0x10,0x00,0x00,0x00,0x02,0x00,0x00,0x00,0x03,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x20,0x00,0x00,0x00, +0x04,0x00,0x00,0x00,0x44,0x58,0x54,0x33,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x08,0x10,0x40,0x00, +0x00,0x00,0x20,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xef,0x87,0x0f,0x78,0x05,0x05,0x50,0x50, +0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xef,0x87,0x0f,0x78,0x05,0x05,0x50,0x50, +0xff,0x00,0xff,0x00,0x00,0x00,0x00,0x00,0x2f,0x7e,0xcf,0x79,0x01,0x54,0x5c,0x5c, +0x0f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x10,0x84,0xef,0x7b,0xaa,0xab,0xab,0xab +}; + +static HRESULT create_file(const char *filename, const unsigned char *data, const unsigned int size) +{ + DWORD received; + HANDLE hfile; + + hfile = CreateFileA(filename, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, 0); + if(hfile == INVALID_HANDLE_VALUE) return HRESULT_FROM_WIN32(GetLastError()); + + if(WriteFile(hfile, data, size, &received, NULL)) + { + CloseHandle(hfile); + return D3D_OK; + } + + CloseHandle(hfile); + return D3DERR_INVALIDCALL; +} + +/* dds_header.flags */ +#define DDS_CAPS 0x00000001 +#define DDS_HEIGHT 0x00000002 +#define DDS_WIDTH 0x00000004 +#define DDS_PITCH 0x00000008 +#define DDS_PIXELFORMAT 0x00001000 +#define DDS_MIPMAPCOUNT 0x00020000 +#define DDS_LINEARSIZE 0x00080000 + +/* dds_header.caps */ +#define DDSCAPS_ALPHA 0x00000002 +#define DDS_CAPS_TEXTURE 0x00001000 + +/* dds_pixel_format.flags */ +#define DDS_PF_ALPHA 0x00000001 +#define DDS_PF_ALPHA_ONLY 0x00000002 +#define DDS_PF_FOURCC 0x00000004 +#define DDS_PF_RGB 0x00000040 +#define DDS_PF_LUMINANCE 0x00020000 +#define DDS_PF_BUMPDUDV 0x00080000 + +struct dds_pixel_format +{ + DWORD size; + DWORD flags; + DWORD fourcc; + DWORD bpp; + DWORD rmask; + DWORD gmask; + DWORD bmask; + DWORD amask; +}; + +struct dds_header +{ + DWORD size; + DWORD flags; + DWORD height; + DWORD width; + DWORD pitch_or_linear_size; + DWORD depth; + DWORD miplevels; + DWORD reserved[11]; + struct dds_pixel_format pixel_format; + DWORD caps; + DWORD caps2; + DWORD caps3; + DWORD caps4; + DWORD reserved2; +}; + +/* fills dds_header with reasonable default values */ +static void fill_dds_header(struct dds_header *header) +{ + memset(header, 0, sizeof(*header)); + + header->size = sizeof(*header); + header->flags = DDS_CAPS | DDS_WIDTH | DDS_HEIGHT | DDS_PIXELFORMAT; + header->height = 4; + header->width = 4; + header->pixel_format.size = sizeof(header->pixel_format); + /* X8R8G8B8 */ + header->pixel_format.flags = DDS_PF_RGB; + header->pixel_format.fourcc = 0; + header->pixel_format.bpp = 32; + header->pixel_format.rmask = 0xff0000; + header->pixel_format.gmask = 0x00ff00; + header->pixel_format.bmask = 0x0000ff; + header->pixel_format.amask = 0; + header->caps = DDS_CAPS_TEXTURE; +} + +#define check_dds_pixel_format(flags, fourcc, bpp, rmask, gmask, bmask, amask, format) \ + check_dds_pixel_format_(__LINE__, flags, fourcc, bpp, rmask, gmask, bmask, amask, format) +static void check_dds_pixel_format_(unsigned int line, + DWORD flags, DWORD fourcc, DWORD bpp, + DWORD rmask, DWORD gmask, DWORD bmask, DWORD amask, + D3DFORMAT expected_format) +{ + HRESULT hr; + D3DXIMAGE_INFO info; + struct + { + DWORD magic; + struct dds_header header; + BYTE data[256]; + } dds; + + dds.magic = MAKEFOURCC('D','D','S',' '); + fill_dds_header(&dds.header); + dds.header.pixel_format.flags = flags; + dds.header.pixel_format.fourcc = fourcc; + dds.header.pixel_format.bpp = bpp; + dds.header.pixel_format.rmask = rmask; + dds.header.pixel_format.gmask = gmask; + dds.header.pixel_format.bmask = bmask; + dds.header.pixel_format.amask = amask; + memset(dds.data, 0, sizeof(dds.data)); + + hr = D3DXGetImageInfoFromFileInMemory(&dds, sizeof(dds), &info); + ok_(__FILE__, line)(hr == D3D_OK, "D3DXGetImageInfoFromFileInMemory returned %#x for pixel format %#x, expected %#x\n", + hr, expected_format, D3D_OK); + if (SUCCEEDED(hr)) + { + ok_(__FILE__, line)(info.Format == expected_format, "D3DXGetImageInfoFromFileInMemory returned format %#x, expected %#x\n", + info.Format, expected_format); + } +} + +static void test_dds_header_handling(void) +{ + int i; + HRESULT hr; + D3DXIMAGE_INFO info; + struct + { + DWORD magic; + struct dds_header header; + BYTE data[4096 * 1024]; + } *dds; + + struct + { + struct dds_pixel_format pixel_format; + DWORD flags; + DWORD width; + DWORD height; + DWORD pitch; + DWORD miplevels; + DWORD pixel_data_size; + struct + { + HRESULT hr; + UINT miplevels; + } + expected; + } tests[] = { + /* pitch is ignored */ + { { 32, DDS_PF_RGB | DDS_PF_ALPHA, 0, 32, 0x00ff0000, 0x0000ff00, 0x000000ff, 0xff000000 }, 0, 4, 4, 0, 0, + 63 /* pixel data size */, { D3DXERR_INVALIDDATA, 0 } }, + { { 32, DDS_PF_RGB | DDS_PF_ALPHA, 0, 32, 0x00ff0000, 0x0000ff00, 0x000000ff, 0xff000000 }, DDS_PITCH, 4, 4, 0 /* pitch */, 0, + 64, { D3D_OK, 1 } }, + { { 32, DDS_PF_RGB | DDS_PF_ALPHA, 0, 32, 0x00ff0000, 0x0000ff00, 0x000000ff, 0xff000000 }, DDS_PITCH, 4, 4, 1 /* pitch */, 0, + 64, { D3D_OK, 1 } }, + { { 32, DDS_PF_RGB | DDS_PF_ALPHA, 0, 32, 0x00ff0000, 0x0000ff00, 0x000000ff, 0xff000000 }, DDS_PITCH, 4, 4, 2 /* pitch */, 0, + 64, { D3D_OK, 1 } }, + { { 32, DDS_PF_RGB | DDS_PF_ALPHA, 0, 32, 0x00ff0000, 0x0000ff00, 0x000000ff, 0xff000000 }, DDS_PITCH, 4, 4, 3 /* pitch */, 0, + 64, { D3D_OK, 1 } }, + { { 32, DDS_PF_RGB | DDS_PF_ALPHA, 0, 32, 0x00ff0000, 0x0000ff00, 0x000000ff, 0xff000000 }, DDS_PITCH, 4, 4, 4 /* pitch */, 0, + 64, { D3D_OK, 1 } }, + { { 32, DDS_PF_RGB | DDS_PF_ALPHA, 0, 32, 0x00ff0000, 0x0000ff00, 0x000000ff, 0xff000000 }, DDS_PITCH, 4, 4, 16 /* pitch */, 0, + 64, { D3D_OK, 1 } }, + { { 32, DDS_PF_RGB | DDS_PF_ALPHA, 0, 32, 0x00ff0000, 0x0000ff00, 0x000000ff, 0xff000000 }, DDS_PITCH, 4, 4, 1024 /* pitch */, 0, + 64, { D3D_OK, 1 } }, + { { 32, DDS_PF_RGB | DDS_PF_ALPHA, 0, 32, 0x00ff0000, 0x0000ff00, 0x000000ff, 0xff000000 }, DDS_PITCH, 4, 4, -1 /* pitch */, 0, + 64, { D3D_OK, 1 } }, + /* linear size is ignored */ + { { 32, DDS_PF_FOURCC, D3DFMT_DXT1, 0, 0, 0, 0, 0 }, 0, 4, 4, 0, 0, + 7 /* pixel data size */, { D3DXERR_INVALIDDATA, 1 } }, + { { 32, DDS_PF_FOURCC, D3DFMT_DXT1, 0, 0, 0, 0, 0 }, DDS_LINEARSIZE, 4, 4, 0 /* linear size */, 0, + 8, { D3D_OK, 1 } }, + { { 32, DDS_PF_FOURCC, D3DFMT_DXT1, 0, 0, 0, 0, 0 }, DDS_LINEARSIZE, 4, 4, 1 /* linear size */, 0, + 8, { D3D_OK, 1 } }, + { { 32, DDS_PF_FOURCC, D3DFMT_DXT1, 0, 0, 0, 0, 0 }, DDS_LINEARSIZE, 4, 4, 2 /* linear size */, 0, + 8, { D3D_OK, 1 } }, + { { 32, DDS_PF_FOURCC, D3DFMT_DXT1, 0, 0, 0, 0, 0 }, DDS_LINEARSIZE, 4, 4, 9 /* linear size */, 0, + 8, { D3D_OK, 1 } }, + { { 32, DDS_PF_FOURCC, D3DFMT_DXT1, 0, 0, 0, 0, 0 }, DDS_LINEARSIZE, 4, 4, 16 /* linear size */, 0, + 8, { D3D_OK, 1 } }, + { { 32, DDS_PF_FOURCC, D3DFMT_DXT1, 0, 0, 0, 0, 0 }, DDS_LINEARSIZE, 4, 4, -1 /* linear size */, 0, + 8, { D3D_OK, 1 } }, + /* integer overflows */ + { { 32, DDS_PF_RGB, 0, 32, 0xff0000, 0x00ff00, 0x0000ff, 0 }, 0, 0x80000000, 0x80000000 /* 0x80000000 * 0x80000000 * 4 = 0 */, 0, 0, + 64, { D3D_OK, 1 } }, + { { 32, DDS_PF_RGB, 0, 32, 0xff0000, 0x00ff00, 0x0000ff, 0 }, 0, 0x8000100, 0x800100 /* 0x8000100 * 0x800100 * 4 = 262144 */, 0, 0, + 64, { D3DXERR_INVALIDDATA, 0 } }, + { { 32, DDS_PF_RGB, 0, 32, 0xff0000, 0x00ff00, 0x0000ff, 0 }, 0, 0x80000001, 0x80000001 /* 0x80000001 * 0x80000001 * 4 = 4 */, 0, 0, + 4, { D3D_OK, 1 } }, + { { 32, DDS_PF_RGB, 0, 32, 0xff0000, 0x00ff00, 0x0000ff, 0 }, 0, 0x80000001, 0x80000001 /* 0x80000001 * 0x80000001 * 4 = 4 */, 0, 0, + 3 /* pixel data size */, { D3DXERR_INVALIDDATA, 0 } }, + /* file size is validated */ + { { 32, DDS_PF_RGB, 0, 24, 0xff0000, 0x00ff00, 0x0000ff, 0x000000 }, 0, 256, 64, 0, 0, 49151, { D3DXERR_INVALIDDATA, 0 } }, + { { 32, DDS_PF_RGB, 0, 24, 0xff0000, 0x00ff00, 0x0000ff, 0x000000 }, 0, 256, 64, 0, 0, 49152, { D3D_OK, 1 } }, + { { 32, DDS_PF_RGB, 0, 24, 0xff0000, 0x00ff00, 0x0000ff, 0x000000 }, DDS_MIPMAPCOUNT, 256, 64, 0, 4, 65279, { D3DXERR_INVALIDDATA, 0 } }, + { { 32, DDS_PF_RGB, 0, 24, 0xff0000, 0x00ff00, 0x0000ff, 0x000000 }, DDS_MIPMAPCOUNT, 256, 64, 0, 4, 65280, { D3D_OK, 4 } }, + { { 32, DDS_PF_RGB, 0, 24, 0xff0000, 0x00ff00, 0x0000ff, 0x000000 }, DDS_MIPMAPCOUNT, 256, 64, 0, 9, 65540, { D3DXERR_INVALIDDATA, 0 } }, + { { 32, DDS_PF_RGB, 0, 24, 0xff0000, 0x00ff00, 0x0000ff, 0x000000 }, DDS_MIPMAPCOUNT, 256, 64, 0, 9, 65541, { D3D_OK, 9 } }, + { { 32, DDS_PF_RGB, 0, 24, 0xff0000, 0x00ff00, 0x0000ff, 0x000000 }, 0, 256, 256, 0, 0, 196607, { D3DXERR_INVALIDDATA, 0 } }, + { { 32, DDS_PF_RGB, 0, 24, 0xff0000, 0x00ff00, 0x0000ff, 0x000000 }, 0, 256, 256, 0, 0, 196608, { D3D_OK, 1 } }, + { { 32, DDS_PF_RGB, 0, 24, 0xff0000, 0x00ff00, 0x0000ff, 0x000000 }, 0, 256, 256, 0, 0, 196609, { D3D_OK, 1 } }, + { { 32, DDS_PF_RGB, 0, 24, 0xff0000, 0x00ff00, 0x0000ff, 0x000000 }, DDS_MIPMAPCOUNT, 256, 256, 0, 1, 196607, { D3DXERR_INVALIDDATA, 0 } }, + { { 32, DDS_PF_RGB, 0, 24, 0xff0000, 0x00ff00, 0x0000ff, 0x000000 }, DDS_MIPMAPCOUNT, 256, 256, 0, 1, 196608, { D3D_OK, 1 } }, + { { 32, DDS_PF_RGB, 0, 24, 0xff0000, 0x00ff00, 0x0000ff, 0x000000 }, DDS_MIPMAPCOUNT, 256, 256, 0, 0, 196607, { D3DXERR_INVALIDDATA, 0 } }, + { { 32, DDS_PF_RGB, 0, 24, 0xff0000, 0x00ff00, 0x0000ff, 0x000000 }, DDS_MIPMAPCOUNT, 256, 256, 0, 0, 196608, { D3D_OK, 1 } }, + { { 32, DDS_PF_RGB, 0, 24, 0xff0000, 0x00ff00, 0x0000ff, 0x000000 }, DDS_MIPMAPCOUNT, 256, 256, 0, 0, 400000, { D3D_OK, 1 } }, + { { 32, DDS_PF_RGB, 0, 24, 0xff0000, 0x00ff00, 0x0000ff, 0x000000 }, DDS_MIPMAPCOUNT, 256, 256, 0, 9, 262142, { D3DXERR_INVALIDDATA, 0 } }, + { { 32, DDS_PF_RGB, 0, 24, 0xff0000, 0x00ff00, 0x0000ff, 0x000000 }, DDS_MIPMAPCOUNT, 256, 256, 0, 9, 262143, { D3D_OK, 9 } }, + { { 32, DDS_PF_RGB, 0, 24, 0xff0000, 0x00ff00, 0x0000ff, 0x000000 }, DDS_MIPMAPCOUNT, 256, 256, 0, 10, 262145, { D3DXERR_INVALIDDATA, 0 } }, + { { 32, DDS_PF_RGB, 0, 24, 0xff0000, 0x00ff00, 0x0000ff, 0x000000 }, DDS_MIPMAPCOUNT, 256, 256, 0, 10, 262146, { D3D_OK, 10 } }, + { { 32, DDS_PF_RGB, 0, 24, 0xff0000, 0x00ff00, 0x0000ff, 0x000000 }, DDS_MIPMAPCOUNT, 256, 256, 0, 20, 262175, { D3DXERR_INVALIDDATA, 0 } }, + { { 32, DDS_PF_RGB, 0, 24, 0xff0000, 0x00ff00, 0x0000ff, 0x000000 }, DDS_MIPMAPCOUNT, 256, 256, 0, 20, 262176, { D3D_OK, 20 } }, + { { 32, DDS_PF_FOURCC, D3DFMT_DXT1, 0, 0, 0, 0, 0 }, 0, 256, 256, 0, 0, 32767, { D3DXERR_INVALIDDATA, 0 } }, + { { 32, DDS_PF_FOURCC, D3DFMT_DXT1, 0, 0, 0, 0, 0 }, 0, 256, 256, 0, 0, 32768, { D3D_OK, 1 } }, + { { 32, DDS_PF_FOURCC, D3DFMT_DXT1, 0, 0, 0, 0, 0 }, DDS_MIPMAPCOUNT, 256, 256, 0, 0, 32767, { D3DXERR_INVALIDDATA, 0 } }, + { { 32, DDS_PF_FOURCC, D3DFMT_DXT1, 0, 0, 0, 0, 0 }, DDS_MIPMAPCOUNT, 256, 256, 0, 0, 32768, { D3D_OK, 1 } }, + { { 32, DDS_PF_FOURCC, D3DFMT_DXT1, 0, 0, 0, 0, 0 }, DDS_MIPMAPCOUNT, 256, 256, 0, 9, 43703, { D3DXERR_INVALIDDATA, 0 } }, + { { 32, DDS_PF_FOURCC, D3DFMT_DXT1, 0, 0, 0, 0, 0 }, DDS_MIPMAPCOUNT, 256, 256, 0, 9, 43704, { D3D_OK, 9 } }, + { { 32, DDS_PF_FOURCC, D3DFMT_DXT1, 0, 0, 0, 0, 0 }, DDS_MIPMAPCOUNT, 256, 256, 0, 20, 43791, { D3DXERR_INVALIDDATA, 0 } }, + { { 32, DDS_PF_FOURCC, D3DFMT_DXT1, 0, 0, 0, 0, 0 }, DDS_MIPMAPCOUNT, 256, 256, 0, 20, 43792, { D3D_OK, 20 } }, + { { 32, DDS_PF_FOURCC, D3DFMT_DXT4, 0, 0, 0, 0, 0 }, 0, 256, 256, 0, 0, 65535, { D3DXERR_INVALIDDATA, 0 } }, + { { 32, DDS_PF_FOURCC, D3DFMT_DXT4, 0, 0, 0, 0, 0 }, 0, 256, 256, 0, 0, 65536, { D3D_OK, 1 } }, + { { 32, DDS_PF_FOURCC, D3DFMT_DXT4, 0, 0, 0, 0, 0 }, DDS_MIPMAPCOUNT, 256, 256, 0, 0, 65535, { D3DXERR_INVALIDDATA, 0 } }, + { { 32, DDS_PF_FOURCC, D3DFMT_DXT4, 0, 0, 0, 0, 0 }, DDS_MIPMAPCOUNT, 256, 256, 0, 0, 65536, { D3D_OK, 1 } }, + { { 32, DDS_PF_FOURCC, D3DFMT_DXT4, 0, 0, 0, 0, 0 }, DDS_MIPMAPCOUNT, 256, 256, 0, 9, 87407, { D3DXERR_INVALIDDATA, 0 } }, + { { 32, DDS_PF_FOURCC, D3DFMT_DXT4, 0, 0, 0, 0, 0 }, DDS_MIPMAPCOUNT, 256, 256, 0, 9, 87408, { D3D_OK, 9 } }, + { { 32, DDS_PF_FOURCC, D3DFMT_DXT4, 0, 0, 0, 0, 0 }, DDS_MIPMAPCOUNT, 256, 256, 0, 20, 87583, { D3DXERR_INVALIDDATA, 0 } }, + { { 32, DDS_PF_FOURCC, D3DFMT_DXT4, 0, 0, 0, 0, 0 }, DDS_MIPMAPCOUNT, 256, 256, 0, 20, 87584, { D3D_OK, 20 } }, + { { 32, DDS_PF_FOURCC, D3DFMT_DXT4, 0, 0, 0, 0, 0 }, DDS_MIPMAPCOUNT, 256, 64, 0, 4, 21759, { D3DXERR_INVALIDDATA, 0 } }, + { { 32, DDS_PF_FOURCC, D3DFMT_DXT4, 0, 0, 0, 0, 0 }, DDS_MIPMAPCOUNT, 256, 64, 0, 4, 21760, { D3D_OK, 4 } }, + /* DDS_MIPMAPCOUNT is ignored */ + { { 32, DDS_PF_RGB, 0, 24, 0xff0000, 0x00ff00, 0x0000ff, 0x000000 }, 0, 256, 256, 0, 0, 262146, { D3D_OK, 1 } }, + { { 32, DDS_PF_RGB, 0, 24, 0xff0000, 0x00ff00, 0x0000ff, 0x000000 }, 0, 256, 256, 0, 2, 262146, { D3D_OK, 2 } }, + { { 32, DDS_PF_RGB, 0, 24, 0xff0000, 0x00ff00, 0x0000ff, 0x000000 }, 0, 256, 256, 0, 9, 262146, { D3D_OK, 9 } }, + { { 32, DDS_PF_RGB, 0, 24, 0xff0000, 0x00ff00, 0x0000ff, 0x000000 }, 0, 256, 256, 0, 10, 262146, { D3D_OK, 10 } }, + }; + + dds = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*dds)); + if (!dds) + { + skip("Failed to allocate memory.\n"); + return; + } + + for (i = 0; i < ARRAY_SIZE(tests); i++) + { + DWORD file_size = sizeof(dds->magic) + sizeof(dds->header) + tests[i].pixel_data_size; + assert(file_size <= sizeof(*dds)); + + dds->magic = MAKEFOURCC('D','D','S',' '); + fill_dds_header(&dds->header); + dds->header.flags |= tests[i].flags; + dds->header.width = tests[i].width; + dds->header.height = tests[i].height; + dds->header.pitch_or_linear_size = tests[i].pitch; + dds->header.miplevels = tests[i].miplevels; + dds->header.pixel_format = tests[i].pixel_format; + + hr = D3DXGetImageInfoFromFileInMemory(dds, file_size, &info); + ok(hr == tests[i].expected.hr, "%d: D3DXGetImageInfoFromFileInMemory returned %#x, expected %#x\n", + i, hr, tests[i].expected.hr); + if (SUCCEEDED(hr)) + { + ok(info.MipLevels == tests[i].expected.miplevels, "%d: Got MipLevels %u, expected %u\n", + i, info.MipLevels, tests[i].expected.miplevels); + } + } + + HeapFree(GetProcessHeap(), 0, dds); +} + +static void test_D3DXGetImageInfo(void) +{ + HRESULT hr; + D3DXIMAGE_INFO info; + BOOL testdummy_ok, testbitmap_ok; + + hr = create_file("testdummy.bmp", noimage, sizeof(noimage)); /* invalid image */ + testdummy_ok = SUCCEEDED(hr); + + hr = create_file("testbitmap.bmp", bmp_1bpp, sizeof(bmp_1bpp)); /* valid image */ + testbitmap_ok = SUCCEEDED(hr); + + /* D3DXGetImageInfoFromFile */ + if(testbitmap_ok) { + hr = D3DXGetImageInfoFromFileA("testbitmap.bmp", &info); + ok(hr == D3D_OK, "D3DXGetImageInfoFromFile returned %#x, expected %#x\n", hr, D3D_OK); + + hr = D3DXGetImageInfoFromFileA("testbitmap.bmp", NULL); /* valid image, second parameter is NULL */ + ok(hr == D3D_OK, "D3DXGetImageInfoFromFile returned %#x, expected %#x\n", hr, D3D_OK); + } else skip("Couldn't create \"testbitmap.bmp\"\n"); + + if(testdummy_ok) { + hr = D3DXGetImageInfoFromFileA("testdummy.bmp", NULL); /* invalid image, second parameter is NULL */ + ok(hr == D3D_OK, "D3DXGetImageInfoFromFile returned %#x, expected %#x\n", hr, D3D_OK); + + hr = D3DXGetImageInfoFromFileA("testdummy.bmp", &info); + ok(hr == D3DXERR_INVALIDDATA, "D3DXGetImageInfoFromFile returned %#x, expected %#x\n", hr, D3DXERR_INVALIDDATA); + } else skip("Couldn't create \"testdummy.bmp\"\n"); + + hr = D3DXGetImageInfoFromFileA("filedoesnotexist.bmp", &info); + ok(hr == D3DXERR_INVALIDDATA, "D3DXGetImageInfoFromFile returned %#x, expected %#x\n", hr, D3DXERR_INVALIDDATA); + + hr = D3DXGetImageInfoFromFileA("filedoesnotexist.bmp", NULL); + ok(hr == D3DXERR_INVALIDDATA, "D3DXGetImageInfoFromFile returned %#x, expected %#x\n", hr, D3DXERR_INVALIDDATA); + + hr = D3DXGetImageInfoFromFileA("", &info); + ok(hr == D3DXERR_INVALIDDATA, "D3DXGetImageInfoFromFile returned %#x, expected %#x\n", hr, D3DXERR_INVALIDDATA); + + hr = D3DXGetImageInfoFromFileA(NULL, &info); + ok(hr == D3DERR_INVALIDCALL, "D3DXGetImageInfoFromFile returned %#x, expected %#x\n", hr, D3DERR_INVALIDCALL); + + hr = D3DXGetImageInfoFromFileA(NULL, NULL); + ok(hr == D3DERR_INVALIDCALL, "D3DXGetImageInfoFromFile returned %#x, expected %#x\n", hr, D3DERR_INVALIDCALL); + + + /* D3DXGetImageInfoFromResource */ + hr = D3DXGetImageInfoFromResourceA(NULL, MAKEINTRESOURCEA(IDB_BITMAP_1x1), &info); /* RT_BITMAP */ + ok(hr == D3D_OK, "D3DXGetImageInfoFromResource returned %#x, expected %#x\n", hr, D3D_OK); + + hr = D3DXGetImageInfoFromResourceA(NULL, MAKEINTRESOURCEA(IDB_BITMAP_1x1), NULL); + ok(hr == D3D_OK, "D3DXGetImageInfoFromResource returned %#x, expected %#x\n", hr, D3D_OK); + + hr = D3DXGetImageInfoFromResourceA(NULL, MAKEINTRESOURCEA(IDD_BITMAPDATA_1x1), &info); /* RT_RCDATA */ + ok(hr == D3D_OK, "D3DXGetImageInfoFromResource returned %#x, expected %#x\n", hr, D3D_OK); + + hr = D3DXGetImageInfoFromResourceA(NULL, MAKEINTRESOURCEA(IDS_STRING), &info); + ok(hr == D3DXERR_INVALIDDATA, "D3DXGetImageInfoFromResource returned %#x, expected %#x\n", hr, D3DXERR_INVALIDDATA); + + hr = D3DXGetImageInfoFromResourceA(NULL, MAKEINTRESOURCEA(IDS_STRING), NULL); + ok(hr == D3DXERR_INVALIDDATA, "D3DXGetImageInfoFromResource returned %#x, expected %#x\n", hr, D3DXERR_INVALIDDATA); + + hr = D3DXGetImageInfoFromResourceA(NULL, "resourcedoesnotexist", &info); + ok(hr == D3DXERR_INVALIDDATA, "D3DXGetImageInfoFromResource returned %#x, expected %#x\n", hr, D3DXERR_INVALIDDATA); + + hr = D3DXGetImageInfoFromResourceA(NULL, "resourcedoesnotexist", NULL); + ok(hr == D3DXERR_INVALIDDATA, "D3DXGetImageInfoFromResource returned %#x, expected %#x\n", hr, D3DXERR_INVALIDDATA); + + hr = D3DXGetImageInfoFromResourceA(NULL, NULL, NULL); + ok(hr == D3DXERR_INVALIDDATA, "D3DXGetImageInfoFromResource returned %#x, expected %#x\n", hr, D3DXERR_INVALIDDATA); + + + /* D3DXGetImageInfoFromFileInMemory */ + hr = D3DXGetImageInfoFromFileInMemory(bmp_1bpp, sizeof(bmp_1bpp), &info); + ok(hr == D3D_OK, "D3DXGetImageInfoFromFileInMemory returned %#x, expected %#x\n", hr, D3D_OK); + + hr = D3DXGetImageInfoFromFileInMemory(bmp_1bpp, sizeof(bmp_1bpp)+5, &info); /* too large size */ + ok(hr == D3D_OK, "D3DXGetImageInfoFromFileInMemory returned %#x, expected %#x\n", hr, D3D_OK); + + hr = D3DXGetImageInfoFromFileInMemory(bmp_1bpp, sizeof(bmp_1bpp), NULL); + ok(hr == D3D_OK, "D3DXGetImageInfoFromFileInMemory returned %#x, expected %#x\n", hr, D3D_OK); + + hr = D3DXGetImageInfoFromFileInMemory(noimage, sizeof(noimage), NULL); + ok(hr == D3D_OK, "D3DXGetImageInfoFromResource returned %#x, expected %#x\n", hr, D3D_OK); + + hr = D3DXGetImageInfoFromFileInMemory(noimage, sizeof(noimage), &info); + ok(hr == D3DXERR_INVALIDDATA, "D3DXGetImageInfoFromFileInMemory returned %#x, expected %#x\n", hr, D3DXERR_INVALIDDATA); + + todo_wine { + hr = D3DXGetImageInfoFromFileInMemory(bmp_1bpp, sizeof(bmp_1bpp)-1, &info); + ok(hr == D3DXERR_INVALIDDATA, "D3DXGetImageInfoFromFileInMemory returned %#x, expected %#x\n", hr, D3DXERR_INVALIDDATA); + } + + hr = D3DXGetImageInfoFromFileInMemory(bmp_1bpp+1, sizeof(bmp_1bpp)-1, &info); + ok(hr == D3DXERR_INVALIDDATA, "D3DXGetImageInfoFromFileInMemory returned %#x, expected %#x\n", hr, D3DXERR_INVALIDDATA); + + hr = D3DXGetImageInfoFromFileInMemory(bmp_1bpp, 0, &info); + ok(hr == D3DERR_INVALIDCALL, "D3DXGetImageInfoFromFileInMemory returned %#x, expected %#x\n", hr, D3DERR_INVALIDCALL); + + hr = D3DXGetImageInfoFromFileInMemory(bmp_1bpp, 0, NULL); + ok(hr == D3DERR_INVALIDCALL, "D3DXGetImageInfoFromFileInMemory returned %#x, expected %#x\n", hr, D3DERR_INVALIDCALL); + + hr = D3DXGetImageInfoFromFileInMemory(noimage, 0, &info); + ok(hr == D3DERR_INVALIDCALL, "D3DXGetImageInfoFromFileInMemory returned %#x, expected %#x\n", hr, D3DERR_INVALIDCALL); + + hr = D3DXGetImageInfoFromFileInMemory(noimage, 0, NULL); + ok(hr == D3DERR_INVALIDCALL, "D3DXGetImageInfoFromFileInMemory returned %#x, expected %#x\n", hr, D3DERR_INVALIDCALL); + + hr = D3DXGetImageInfoFromFileInMemory(NULL, 0, &info); + ok(hr == D3DERR_INVALIDCALL, "D3DXGetImageInfoFromFileInMemory returned %#x, expected %#x\n", hr, D3DERR_INVALIDCALL); + + hr = D3DXGetImageInfoFromFileInMemory(NULL, 4, NULL); + ok(hr == D3DERR_INVALIDCALL, "D3DXGetImageInfoFromFileInMemory returned %#x, expected %#x\n", hr, D3DERR_INVALIDCALL); + + hr = D3DXGetImageInfoFromFileInMemory(NULL, 4, &info); + ok(hr == D3DERR_INVALIDCALL, "D3DXGetImageInfoFromFileInMemory returned %#x, expected %#x\n", hr, D3DERR_INVALIDCALL); + + hr = D3DXGetImageInfoFromFileInMemory(NULL, 0, NULL); + ok(hr == D3DERR_INVALIDCALL, "D3DXGetImageInfoFromFileInMemory returned %#x, expected %#x\n", hr, D3DERR_INVALIDCALL); + + /* test BMP support */ + hr = D3DXGetImageInfoFromFileInMemory(bmp_1bpp, sizeof(bmp_1bpp), &info); + ok(hr == D3D_OK, "D3DXGetImageInfoFromFileInMemory returned %#x, expected %#x\n", hr, D3D_OK); + ok(info.Depth == 1, "Got depth %u, expected 1\n", info.Depth); + ok(info.Format == D3DFMT_P8, "Got format %u, expected %u\n", info.Format, D3DFMT_P8); + hr = D3DXGetImageInfoFromFileInMemory(bmp_2bpp, sizeof(bmp_2bpp), &info); + ok(hr == D3DXERR_INVALIDDATA, "D3DXGetImageInfoFromFileInMemory returned %#x, expected %#x\n", hr, D3DXERR_INVALIDDATA); + hr = D3DXGetImageInfoFromFileInMemory(bmp_4bpp, sizeof(bmp_4bpp), &info); + ok(hr == D3D_OK, "D3DXGetImageInfoFromFileInMemory returned %#x, expected %#x\n", hr, D3D_OK); + ok(info.Depth == 1, "Got depth %u, expected 1\n", info.Depth); + ok(info.Format == D3DFMT_P8, "Got format %u, expected %u\n", info.Format, D3DFMT_P8); + hr = D3DXGetImageInfoFromFileInMemory(bmp_8bpp, sizeof(bmp_8bpp), &info); + ok(hr == D3D_OK, "D3DXGetImageInfoFromFileInMemory returned %#x, expected %#x\n", hr, D3D_OK); + ok(info.Depth == 1, "Got depth %u, expected 1\n", info.Depth); + ok(info.Format == D3DFMT_P8, "Got format %u, expected %u\n", info.Format, D3DFMT_P8); + + /* Grayscale PNG */ + hr = D3DXGetImageInfoFromFileInMemory(png_grayscale, sizeof(png_grayscale), &info); + ok(hr == D3D_OK, "D3DXGetImageInfoFromFileInMemory returned %#x, expected %#x\n", hr, D3D_OK); + ok(info.Depth == 1, "Got depth %u, expected 1\n", info.Depth); + ok(info.Format == D3DFMT_L8, "Got format %u, expected %u\n", info.Format, D3DFMT_L8); + + /* test DDS support */ + hr = D3DXGetImageInfoFromFileInMemory(dds_24bit, sizeof(dds_24bit), &info); + ok(hr == D3D_OK, "D3DXGetImageInfoFromFileInMemory returned %#x, expected %#x\n", hr, D3D_OK); + if (hr == D3D_OK) { + ok(info.Width == 2, "Got width %u, expected 2\n", info.Width); + ok(info.Height == 2, "Got height %u, expected 2\n", info.Height); + ok(info.Depth == 1, "Got depth %u, expected 1\n", info.Depth); + ok(info.MipLevels == 2, "Got miplevels %u, expected 2\n", info.MipLevels); + ok(info.Format == D3DFMT_R8G8B8, "Got format %#x, expected %#x\n", info.Format, D3DFMT_R8G8B8); + ok(info.ResourceType == D3DRTYPE_TEXTURE, "Got resource type %#x, expected %#x\n", info.ResourceType, D3DRTYPE_TEXTURE); + ok(info.ImageFileFormat == D3DXIFF_DDS, "Got image file format %#x, expected %#x\n", info.ImageFileFormat, D3DXIFF_DDS); + } else skip("Couldn't get image info from 24-bit DDS file in memory\n"); + + hr = D3DXGetImageInfoFromFileInMemory(dds_16bit, sizeof(dds_16bit), &info); + ok(hr == D3D_OK, "D3DXGetImageInfoFromFileInMemory returned %#x, expected %#x\n", hr, D3D_OK); + if (hr == D3D_OK) { + ok(info.Width == 2, "Got width %u, expected 2\n", info.Width); + ok(info.Height == 2, "Got height %u, expected 2\n", info.Height); + ok(info.Depth == 1, "Got depth %u, expected 1\n", info.Depth); + ok(info.MipLevels == 1, "Got miplevels %u, expected 1\n", info.MipLevels); + ok(info.Format == D3DFMT_X1R5G5B5, "Got format %#x, expected %#x\n", info.Format, D3DFMT_X1R5G5B5); + ok(info.ResourceType == D3DRTYPE_TEXTURE, "Got resource type %#x, expected %#x\n", info.ResourceType, D3DRTYPE_TEXTURE); + ok(info.ImageFileFormat == D3DXIFF_DDS, "Got image file format %#x, expected %#x\n", info.ImageFileFormat, D3DXIFF_DDS); + } else skip("Couldn't get image info from 16-bit DDS file in memory\n"); + + hr = D3DXGetImageInfoFromFileInMemory(dds_cube_map, sizeof(dds_cube_map), &info); + ok(hr == D3D_OK, "D3DXGetImageInfoFromFileInMemory returned %#x, expected %#x\n", hr, D3D_OK); + if (hr == D3D_OK) { + ok(info.Width == 4, "Got width %u, expected 4\n", info.Width); + ok(info.Height == 4, "Got height %u, expected 4\n", info.Height); + ok(info.Depth == 1, "Got depth %u, expected 1\n", info.Depth); + ok(info.MipLevels == 1, "Got miplevels %u, expected 1\n", info.MipLevels); + ok(info.Format == D3DFMT_DXT5, "Got format %#x, expected %#x\n", info.Format, D3DFMT_DXT5); + ok(info.ResourceType == D3DRTYPE_CUBETEXTURE, "Got resource type %#x, expected %#x\n", info.ResourceType, D3DRTYPE_CUBETEXTURE); + ok(info.ImageFileFormat == D3DXIFF_DDS, "Got image file format %#x, expected %#x\n", info.ImageFileFormat, D3DXIFF_DDS); + } else skip("Couldn't get image info from cube map in memory\n"); + + hr = D3DXGetImageInfoFromFileInMemory(dds_volume_map, sizeof(dds_volume_map), &info); + ok(hr == D3D_OK, "D3DXGetImageInfoFromFileInMemory returned %#x, expected %#x\n", hr, D3D_OK); + if (hr == D3D_OK) { + ok(info.Width == 4, "Got width %u, expected 4\n", info.Width); + ok(info.Height == 4, "Got height %u, expected 4\n", info.Height); + ok(info.Depth == 2, "Got depth %u, expected 2\n", info.Depth); + ok(info.MipLevels == 3, "Got miplevels %u, expected 3\n", info.MipLevels); + ok(info.Format == D3DFMT_DXT3, "Got format %#x, expected %#x\n", info.Format, D3DFMT_DXT3); + ok(info.ResourceType == D3DRTYPE_VOLUMETEXTURE, "Got resource type %#x, expected %#x\n", info.ResourceType, D3DRTYPE_VOLUMETEXTURE); + ok(info.ImageFileFormat == D3DXIFF_DDS, "Got image file format %#x, expected %#x\n", info.ImageFileFormat, D3DXIFF_DDS); + } else skip("Couldn't get image info from volume map in memory\n"); + + check_dds_pixel_format(DDS_PF_FOURCC, D3DFMT_DXT1, 0, 0, 0, 0, 0, D3DFMT_DXT1); + check_dds_pixel_format(DDS_PF_FOURCC, D3DFMT_DXT2, 0, 0, 0, 0, 0, D3DFMT_DXT2); + check_dds_pixel_format(DDS_PF_FOURCC, D3DFMT_DXT3, 0, 0, 0, 0, 0, D3DFMT_DXT3); + check_dds_pixel_format(DDS_PF_FOURCC, D3DFMT_DXT4, 0, 0, 0, 0, 0, D3DFMT_DXT4); + check_dds_pixel_format(DDS_PF_FOURCC, D3DFMT_DXT5, 0, 0, 0, 0, 0, D3DFMT_DXT5); + check_dds_pixel_format(DDS_PF_FOURCC, D3DFMT_R8G8_B8G8, 0, 0, 0, 0, 0, D3DFMT_R8G8_B8G8); + check_dds_pixel_format(DDS_PF_FOURCC, D3DFMT_G8R8_G8B8, 0, 0, 0, 0, 0, D3DFMT_G8R8_G8B8); + check_dds_pixel_format(DDS_PF_FOURCC, D3DFMT_UYVY, 0, 0, 0, 0, 0, D3DFMT_UYVY); + check_dds_pixel_format(DDS_PF_FOURCC, D3DFMT_YUY2, 0, 0, 0, 0, 0, D3DFMT_YUY2); + check_dds_pixel_format(DDS_PF_RGB, 0, 16, 0xf800, 0x07e0, 0x001f, 0, D3DFMT_R5G6B5); + check_dds_pixel_format(DDS_PF_RGB | DDS_PF_ALPHA, 0, 16, 0x7c00, 0x03e0, 0x001f, 0x8000, D3DFMT_A1R5G5B5); + check_dds_pixel_format(DDS_PF_RGB | DDS_PF_ALPHA, 0, 16, 0x0f00, 0x00f0, 0x000f, 0xf000, D3DFMT_A4R4G4B4); + check_dds_pixel_format(DDS_PF_RGB, 0, 8, 0xe0, 0x1c, 0x03, 0, D3DFMT_R3G3B2); + check_dds_pixel_format(DDS_PF_ALPHA_ONLY, 0, 8, 0, 0, 0, 0xff, D3DFMT_A8); + check_dds_pixel_format(DDS_PF_RGB | DDS_PF_ALPHA, 0, 16, 0x00e0, 0x001c, 0x0003, 0xff00, D3DFMT_A8R3G3B2); + check_dds_pixel_format(DDS_PF_RGB, 0, 16, 0xf00, 0x0f0, 0x00f, 0, D3DFMT_X4R4G4B4); + check_dds_pixel_format(DDS_PF_RGB | DDS_PF_ALPHA, 0, 32, 0x3ff00000, 0x000ffc00, 0x000003ff, 0xc0000000, D3DFMT_A2B10G10R10); + check_dds_pixel_format(DDS_PF_RGB | DDS_PF_ALPHA, 0, 32, 0x000003ff, 0x000ffc00, 0x3ff00000, 0xc0000000, D3DFMT_A2R10G10B10); + check_dds_pixel_format(DDS_PF_RGB | DDS_PF_ALPHA, 0, 32, 0x00ff0000, 0x0000ff00, 0x000000ff, 0xff000000, D3DFMT_A8R8G8B8); + check_dds_pixel_format(DDS_PF_RGB | DDS_PF_ALPHA, 0, 32, 0x000000ff, 0x0000ff00, 0x00ff0000, 0xff000000, D3DFMT_A8B8G8R8); + check_dds_pixel_format(DDS_PF_RGB, 0, 32, 0xff0000, 0x00ff00, 0x0000ff, 0, D3DFMT_X8R8G8B8); + check_dds_pixel_format(DDS_PF_RGB, 0, 32, 0x0000ff, 0x00ff00, 0xff0000, 0, D3DFMT_X8B8G8R8); + check_dds_pixel_format(DDS_PF_RGB, 0, 24, 0xff0000, 0x00ff00, 0x0000ff, 0, D3DFMT_R8G8B8); + check_dds_pixel_format(DDS_PF_RGB, 0, 32, 0x0000ffff, 0xffff0000, 0, 0, D3DFMT_G16R16); + check_dds_pixel_format(DDS_PF_LUMINANCE, 0, 8, 0xff, 0, 0, 0, D3DFMT_L8); + check_dds_pixel_format(DDS_PF_LUMINANCE, 0, 16, 0xffff, 0, 0, 0, D3DFMT_L16); + check_dds_pixel_format(DDS_PF_LUMINANCE | DDS_PF_ALPHA, 0, 16, 0x00ff, 0, 0, 0xff00, D3DFMT_A8L8); + check_dds_pixel_format(DDS_PF_LUMINANCE | DDS_PF_ALPHA, 0, 8, 0x0f, 0, 0, 0xf0, D3DFMT_A4L4); + check_dds_pixel_format(DDS_PF_BUMPDUDV, 0, 16, 0x00ff, 0xff00, 0, 0, D3DFMT_V8U8); + check_dds_pixel_format(DDS_PF_BUMPDUDV, 0, 32, 0x0000ffff, 0xffff0000, 0, 0, D3DFMT_V16U16); + + test_dds_header_handling(); + + hr = D3DXGetImageInfoFromFileInMemory(dds_16bit, sizeof(dds_16bit) - 1, &info); + ok(hr == D3DXERR_INVALIDDATA, "D3DXGetImageInfoFromFileInMemory returned %#x, expected %#x\n", hr, D3DXERR_INVALIDDATA); + + hr = D3DXGetImageInfoFromFileInMemory(dds_24bit, sizeof(dds_24bit) - 1, &info); + ok(hr == D3DXERR_INVALIDDATA, "D3DXGetImageInfoFromFileInMemory returned %#x, expected %#x\n", hr, D3DXERR_INVALIDDATA); + + hr = D3DXGetImageInfoFromFileInMemory(dds_cube_map, sizeof(dds_cube_map) - 1, &info); + ok(hr == D3DXERR_INVALIDDATA, "D3DXGetImageInfoFromFileInMemory returned %#x, expected %#x\n", hr, D3DXERR_INVALIDDATA); + + hr = D3DXGetImageInfoFromFileInMemory(dds_volume_map, sizeof(dds_volume_map) - 1, &info); + ok(hr == D3DXERR_INVALIDDATA, "D3DXGetImageInfoFromFileInMemory returned %#x, expected %#x\n", hr, D3DXERR_INVALIDDATA); + + + /* cleanup */ + if(testdummy_ok) DeleteFileA("testdummy.bmp"); + if(testbitmap_ok) DeleteFileA("testbitmap.bmp"); +} + +#define check_pixel_2bpp(lockrect, x, y, color) _check_pixel_2bpp(__LINE__, lockrect, x, y, color) +static inline void _check_pixel_2bpp(unsigned int line, const D3DLOCKED_RECT *lockrect, int x, int y, WORD expected_color) +{ + WORD color = ((WORD*)lockrect->pBits)[x + y * lockrect->Pitch / 2]; + ok_(__FILE__, line)(color == expected_color, "Got color 0x%04x, expected 0x%04x\n", color, expected_color); +} + +#define check_pixel_4bpp(lockrect, x, y, color) _check_pixel_4bpp(__LINE__, lockrect, x, y, color) +static inline void _check_pixel_4bpp(unsigned int line, const D3DLOCKED_RECT *lockrect, int x, int y, DWORD expected_color) +{ + DWORD color = ((DWORD*)lockrect->pBits)[x + y * lockrect->Pitch / 4]; + ok_(__FILE__, line)(color == expected_color, "Got color 0x%08x, expected 0x%08x\n", color, expected_color); +} + +static void test_D3DXLoadSurface(IDirect3DDevice9 *device) +{ + HRESULT hr; + BOOL testdummy_ok, testbitmap_ok; + IDirect3DTexture9 *tex; + IDirect3DSurface9 *surf, *newsurf; + RECT rect, destrect; + D3DLOCKED_RECT lockrect; + const WORD pixdata_a8r3g3b2[] = { 0x57df, 0x98fc, 0xacdd, 0xc891 }; + const WORD pixdata_a1r5g5b5[] = { 0x46b5, 0x99c8, 0x06a2, 0x9431 }; + const WORD pixdata_r5g6b5[] = { 0x9ef6, 0x658d, 0x0aee, 0x42ee }; + const WORD pixdata_a8l8[] = { 0xff00, 0x00ff, 0xff30, 0x7f7f }; + const DWORD pixdata_g16r16[] = { 0x07d23fbe, 0xdc7f44a4, 0xe4d8976b, 0x9a84fe89 }; + const DWORD pixdata_a8b8g8r8[] = { 0xc3394cf0, 0x235ae892, 0x09b197fd, 0x8dc32bf6 }; + const DWORD pixdata_a2r10g10b10[] = { 0x57395aff, 0x5b7668fd, 0xb0d856b5, 0xff2c61d6 }; + + hr = create_file("testdummy.bmp", noimage, sizeof(noimage)); /* invalid image */ + testdummy_ok = SUCCEEDED(hr); + + hr = create_file("testbitmap.bmp", bmp_1bpp, sizeof(bmp_1bpp)); /* valid image */ + testbitmap_ok = SUCCEEDED(hr); + + hr = IDirect3DDevice9_CreateOffscreenPlainSurface(device, 256, 256, D3DFMT_A8R8G8B8, D3DPOOL_DEFAULT, &surf, NULL); + if(FAILED(hr)) { + skip("Failed to create a surface (%#x)\n", hr); + if(testdummy_ok) DeleteFileA("testdummy.bmp"); + if(testbitmap_ok) DeleteFileA("testbitmap.bmp"); + return; + } + + /* D3DXLoadSurfaceFromFile */ + if(testbitmap_ok) { + hr = D3DXLoadSurfaceFromFileA(surf, NULL, NULL, "testbitmap.bmp", NULL, D3DX_DEFAULT, 0, NULL); + ok(hr == D3D_OK, "D3DXLoadSurfaceFromFile returned %#x, expected %#x\n", hr, D3D_OK); + + hr = D3DXLoadSurfaceFromFileA(NULL, NULL, NULL, "testbitmap.bmp", NULL, D3DX_DEFAULT, 0, NULL); + ok(hr == D3DERR_INVALIDCALL, "D3DXLoadSurfaceFromFile returned %#x, expected %#x\n", hr, D3DERR_INVALIDCALL); + } else skip("Couldn't create \"testbitmap.bmp\"\n"); + + if(testdummy_ok) { + hr = D3DXLoadSurfaceFromFileA(surf, NULL, NULL, "testdummy.bmp", NULL, D3DX_DEFAULT, 0, NULL); + ok(hr == D3DXERR_INVALIDDATA, "D3DXLoadSurfaceFromFile returned %#x, expected %#x\n", hr, D3DXERR_INVALIDDATA); + } else skip("Couldn't create \"testdummy.bmp\"\n"); + + hr = D3DXLoadSurfaceFromFileA(surf, NULL, NULL, NULL, NULL, D3DX_DEFAULT, 0, NULL); + ok(hr == D3DERR_INVALIDCALL, "D3DXLoadSurfaceFromFile returned %#x, expected %#x\n", hr, D3DERR_INVALIDCALL); + + hr = D3DXLoadSurfaceFromFileA(surf, NULL, NULL, "", NULL, D3DX_DEFAULT, 0, NULL); + ok(hr == D3DXERR_INVALIDDATA, "D3DXLoadSurfaceFromFile returned %#x, expected %#x\n", hr, D3DXERR_INVALIDDATA); + + + /* D3DXLoadSurfaceFromResource */ + hr = D3DXLoadSurfaceFromResourceA(surf, NULL, NULL, NULL, + MAKEINTRESOURCEA(IDB_BITMAP_1x1), NULL, D3DX_DEFAULT, 0, NULL); + ok(hr == D3D_OK, "D3DXLoadSurfaceFromResource returned %#x, expected %#x\n", hr, D3D_OK); + + hr = D3DXLoadSurfaceFromResourceA(surf, NULL, NULL, NULL, + MAKEINTRESOURCEA(IDD_BITMAPDATA_1x1), NULL, D3DX_DEFAULT, 0, NULL); + ok(hr == D3D_OK, "D3DXLoadSurfaceFromResource returned %#x, expected %#x\n", hr, D3D_OK); + + hr = D3DXLoadSurfaceFromResourceA(surf, NULL, NULL, NULL, NULL, NULL, D3DX_DEFAULT, 0, NULL); + ok(hr == D3DXERR_INVALIDDATA, "D3DXLoadSurfaceFromResource returned %#x, expected %#x\n", hr, D3DXERR_INVALIDDATA); + + hr = D3DXLoadSurfaceFromResourceA(NULL, NULL, NULL, NULL, + MAKEINTRESOURCEA(IDB_BITMAP_1x1), NULL, D3DX_DEFAULT, 0, NULL); + ok(hr == D3DERR_INVALIDCALL, "D3DXLoadSurfaceFromResource returned %#x, expected %#x\n", hr, D3DERR_INVALIDCALL); + + hr = D3DXLoadSurfaceFromResourceA(surf, NULL, NULL, NULL, + MAKEINTRESOURCEA(IDS_STRING), NULL, D3DX_DEFAULT, 0, NULL); + ok(hr == D3DXERR_INVALIDDATA, "D3DXLoadSurfaceFromResource returned %#x, expected %#x\n", hr, D3DXERR_INVALIDDATA); + + + /* D3DXLoadSurfaceFromFileInMemory */ + hr = D3DXLoadSurfaceFromFileInMemory(surf, NULL, NULL, bmp_1bpp, sizeof(bmp_1bpp), NULL, D3DX_DEFAULT, 0, NULL); + ok(hr == D3D_OK, "D3DXLoadSurfaceFromFileInMemory returned %#x, expected %#x\n", hr, D3D_OK); + + hr = D3DXLoadSurfaceFromFileInMemory(surf, NULL, NULL, noimage, sizeof(noimage), NULL, D3DX_DEFAULT, 0, NULL); + ok(hr == D3DXERR_INVALIDDATA, "D3DXLoadSurfaceFromFileInMemory returned %#x, expected %#x\n", hr, D3DXERR_INVALIDDATA); + + hr = D3DXLoadSurfaceFromFileInMemory(surf, NULL, NULL, bmp_1bpp, 0, NULL, D3DX_DEFAULT, 0, NULL); + ok(hr == D3DERR_INVALIDCALL, "D3DXLoadSurfaceFromFileInMemory returned %#x, expected %#x\n", hr, D3DERR_INVALIDCALL); + + hr = D3DXLoadSurfaceFromFileInMemory(NULL, NULL, NULL, bmp_1bpp, sizeof(bmp_1bpp), NULL, D3DX_DEFAULT, 0, NULL); + ok(hr == D3DERR_INVALIDCALL, "D3DXLoadSurfaceFromFileInMemory returned %#x, expected %#x\n", hr, D3DERR_INVALIDCALL); + + hr = D3DXLoadSurfaceFromFileInMemory(surf, NULL, NULL, NULL, 8, NULL, D3DX_DEFAULT, 0, NULL); + ok(hr == D3DERR_INVALIDCALL, "D3DXLoadSurfaceFromFileInMemory returned %#x, expected %#x\n", hr, D3DERR_INVALIDCALL); + + hr = D3DXLoadSurfaceFromFileInMemory(surf, NULL, NULL, NULL, 0, NULL, D3DX_DEFAULT, 0, NULL); + ok(hr == D3DERR_INVALIDCALL, "D3DXLoadSurfaceFromFileInMemory returned %#x, expected %#x\n", hr, D3DERR_INVALIDCALL); + + hr = D3DXLoadSurfaceFromFileInMemory(NULL, NULL, NULL, NULL, 0, NULL, D3DX_DEFAULT, 0, NULL); + ok(hr == D3DERR_INVALIDCALL, "D3DXLoadSurfaceFromFileInMemory returned %#x, expected %#x\n", hr, D3DERR_INVALIDCALL); + + + /* D3DXLoadSurfaceFromMemory */ + SetRect(&rect, 0, 0, 2, 2); + + hr = D3DXLoadSurfaceFromMemory(surf, NULL, NULL, pixdata, D3DFMT_A8R8G8B8, sizeof(pixdata), NULL, &rect, D3DX_FILTER_NONE, 0); + ok(hr == D3D_OK, "D3DXLoadSurfaceFromMemory returned %#x, expected %#x\n", hr, D3D_OK); + + hr = D3DXLoadSurfaceFromMemory(surf, NULL, NULL, pixdata, D3DFMT_A8R8G8B8, 0, NULL, &rect, D3DX_FILTER_NONE, 0); + ok(hr == D3D_OK, "D3DXLoadSurfaceFromMemory returned %#x, expected %#x\n", hr, D3D_OK); + + hr = D3DXLoadSurfaceFromMemory(surf, NULL, NULL, NULL, D3DFMT_A8R8G8B8, sizeof(pixdata), NULL, &rect, D3DX_DEFAULT, 0); + ok(hr == D3DERR_INVALIDCALL, "D3DXLoadSurfaceFromMemory returned %#x, expected %#x\n", hr, D3DERR_INVALIDCALL); + + hr = D3DXLoadSurfaceFromMemory(NULL, NULL, NULL, pixdata, D3DFMT_A8R8G8B8, sizeof(pixdata), NULL, &rect, D3DX_DEFAULT, 0); + ok(hr == D3DERR_INVALIDCALL, "D3DXLoadSurfaceFromMemory returned %#x, expected %#x\n", hr, D3DERR_INVALIDCALL); + + hr = D3DXLoadSurfaceFromMemory(surf, NULL, NULL, pixdata, D3DFMT_A8R8G8B8, sizeof(pixdata), NULL, NULL, D3DX_DEFAULT, 0); + ok(hr == D3DERR_INVALIDCALL, "D3DXLoadSurfaceFromMemory returned %#x, expected %#x\n", hr, D3DERR_INVALIDCALL); + + hr = D3DXLoadSurfaceFromMemory(surf, NULL, NULL, pixdata, D3DFMT_UNKNOWN, sizeof(pixdata), NULL, &rect, D3DX_DEFAULT, 0); + ok(hr == E_FAIL, "D3DXLoadSurfaceFromMemory returned %#x, expected %#x\n", hr, E_FAIL); + + SetRect(&destrect, -1, -1, 1, 1); /* destination rect is partially outside texture boundaries */ + hr = D3DXLoadSurfaceFromMemory(surf, NULL, &destrect, pixdata, D3DFMT_A8R8G8B8, sizeof(pixdata), NULL, &rect, D3DX_FILTER_NONE, 0); + ok(hr == D3DERR_INVALIDCALL, "D3DXLoadSurfaceFromMemory returned %#x, expected %#x\n", hr, D3DERR_INVALIDCALL); + + SetRect(&destrect, 255, 255, 257, 257); /* destination rect is partially outside texture boundaries */ + hr = D3DXLoadSurfaceFromMemory(surf, NULL, &destrect, pixdata, D3DFMT_A8R8G8B8, sizeof(pixdata), NULL, &rect, D3DX_FILTER_NONE, 0); + ok(hr == D3DERR_INVALIDCALL, "D3DXLoadSurfaceFromMemory returned %#x, expected %#x\n", hr, D3DERR_INVALIDCALL); + + SetRect(&destrect, 1, 1, 0, 0); /* left > right, top > bottom */ + hr = D3DXLoadSurfaceFromMemory(surf, NULL, &destrect, pixdata, D3DFMT_A8R8G8B8, sizeof(pixdata), NULL, &rect, D3DX_FILTER_NONE, 0); + ok(hr == D3DERR_INVALIDCALL, "D3DXLoadSurfaceFromMemory returned %#x, expected %#x\n", hr, D3DERR_INVALIDCALL); + + SetRect(&destrect, 1, 2, 1, 2); /* left = right, top = bottom */ + hr = D3DXLoadSurfaceFromMemory(surf, NULL, &destrect, pixdata, D3DFMT_A8R8G8B8, sizeof(pixdata), NULL, &rect, D3DX_FILTER_NONE, 0); + /* fails when debug version of d3d9 is used */ + ok(hr == D3D_OK || broken(hr == D3DERR_INVALIDCALL), "D3DXLoadSurfaceFromMemory returned %#x, expected %#x\n", hr, D3D_OK); + + SetRect(&destrect, 257, 257, 257, 257); /* left = right, top = bottom, but invalid values */ + hr = D3DXLoadSurfaceFromMemory(surf, NULL, &destrect, pixdata, D3DFMT_A8R8G8B8, sizeof(pixdata), NULL, &rect, D3DX_FILTER_NONE, 0); + ok(hr == D3DERR_INVALIDCALL, "D3DXLoadSurfaceFromMemory returned %#x, expected %#x\n", hr, D3DERR_INVALIDCALL); + + + /* D3DXLoadSurfaceFromSurface */ + hr = IDirect3DDevice9_CreateOffscreenPlainSurface(device, 256, 256, D3DFMT_A8R8G8B8, D3DPOOL_DEFAULT, &newsurf, NULL); + if(SUCCEEDED(hr)) { + hr = D3DXLoadSurfaceFromSurface(newsurf, NULL, NULL, surf, NULL, NULL, D3DX_DEFAULT, 0); + ok(hr == D3D_OK, "D3DXLoadSurfaceFromSurface returned %#x, expected %#x\n", hr, D3D_OK); + + hr = D3DXLoadSurfaceFromSurface(NULL, NULL, NULL, surf, NULL, NULL, D3DX_DEFAULT, 0); + ok(hr == D3DERR_INVALIDCALL, "D3DXLoadSurfaceFromSurface returned %#x, expected %#x\n", hr, D3DERR_INVALIDCALL); + + hr = D3DXLoadSurfaceFromSurface(newsurf, NULL, NULL, NULL, NULL, NULL, D3DX_DEFAULT, 0); + ok(hr == D3DERR_INVALIDCALL, "D3DXLoadSurfaceFromSurface returned %#x, expected %#x\n", hr, D3DERR_INVALIDCALL); + + check_release((IUnknown*)newsurf, 0); + } else skip("Failed to create a second surface\n"); + + hr = IDirect3DDevice9_CreateTexture(device, 256, 256, 0, 0, D3DFMT_A8R8G8B8, D3DPOOL_DEFAULT, &tex, NULL); + if (SUCCEEDED(hr)) + { + IDirect3DTexture9_GetSurfaceLevel(tex, 0, &newsurf); + + hr = D3DXLoadSurfaceFromSurface(newsurf, NULL, NULL, surf, NULL, NULL, D3DX_DEFAULT, 0); + ok(hr == D3D_OK, "D3DXLoadSurfaceFromSurface returned %#x, expected %#x\n", hr, D3D_OK); + + IDirect3DSurface9_Release(newsurf); + IDirect3DTexture9_Release(tex); + } else skip("Failed to create texture\n"); + + /* non-lockable render target */ + hr = IDirect3DDevice9_CreateRenderTarget(device, 256, 256, D3DFMT_A8R8G8B8, D3DMULTISAMPLE_NONE, 0, FALSE, &newsurf, NULL); + if (SUCCEEDED(hr)) { + hr = D3DXLoadSurfaceFromSurface(surf, NULL, NULL, newsurf, NULL, NULL, D3DX_FILTER_NONE, 0); + ok(hr == D3D_OK, "D3DXLoadSurfaceFromSurface returned %#x, expected %#x\n", hr, D3D_OK); + + IDirect3DSurface9_Release(newsurf); + } else skip("Failed to create render target surface\n"); + + /* non-lockable multisampled render target */ + hr = IDirect3DDevice9_CreateRenderTarget(device, 256, 256, D3DFMT_A8R8G8B8, D3DMULTISAMPLE_2_SAMPLES, 0, FALSE, &newsurf, NULL); + if (SUCCEEDED(hr)) { + hr = D3DXLoadSurfaceFromSurface(surf, NULL, NULL, newsurf, NULL, NULL, D3DX_FILTER_NONE, 0); + ok(hr == D3D_OK, "D3DXLoadSurfaceFromSurface returned %#x, expected %#x\n", hr, D3D_OK); + + IDirect3DSurface9_Release(newsurf); + } else skip("Failed to create multisampled render target.\n"); + + hr = IDirect3DDevice9_GetRenderTarget(device, 0, &newsurf); + ok(hr == D3D_OK, "IDirect3DDevice9_GetRenderTarget returned %#x, expected %#x.\n", hr, D3D_OK); + + hr = D3DXLoadSurfaceFromSurface(newsurf, NULL, NULL, surf, NULL, NULL, D3DX_FILTER_NONE, 0); + ok(hr == D3D_OK, "D3DXLoadSurfaceFromSurface returned %#x, expected %#x.\n", hr, D3D_OK); + hr = D3DXLoadSurfaceFromSurface(surf, NULL, NULL, newsurf, NULL, NULL, D3DX_FILTER_NONE, 0); + ok(hr == D3D_OK, "D3DXLoadSurfaceFromSurface returned %#x, expected %#x.\n", hr, D3D_OK); + hr = D3DXLoadSurfaceFromSurface(surf, NULL, NULL, newsurf, NULL, NULL, D3DX_FILTER_NONE, 0xff000000); + ok(hr == D3D_OK, "D3DXLoadSurfaceFromSurface returned %#x, expected %#x.\n", hr, D3D_OK); + hr = D3DXLoadSurfaceFromSurface(surf, NULL, NULL, newsurf, NULL, NULL, D3DX_FILTER_TRIANGLE | D3DX_FILTER_MIRROR, 0); + ok(hr == D3D_OK, "D3DXLoadSurfaceFromSurface returned %#x, expected %#x.\n", hr, D3D_OK); + hr = D3DXLoadSurfaceFromSurface(surf, NULL, NULL, newsurf, NULL, NULL, D3DX_FILTER_LINEAR, 0); + ok(hr == D3D_OK, "D3DXLoadSurfaceFromSurface returned %#x, expected %#x.\n", hr, D3D_OK); + + IDirect3DSurface9_Release(newsurf); + + check_release((IUnknown*)surf, 0); + + + /* test color conversion */ + /* A8R8G8B8 */ + hr = IDirect3DDevice9_CreateOffscreenPlainSurface(device, 2, 2, D3DFMT_A8R8G8B8, D3DPOOL_DEFAULT, &surf, NULL); + if(FAILED(hr)) skip("Failed to create a surface (%#x)\n", hr); + else { + PALETTEENTRY palette; + + hr = D3DXLoadSurfaceFromMemory(surf, NULL, NULL, pixdata_a8r3g3b2, D3DFMT_A8R3G3B2, 4, NULL, &rect, D3DX_FILTER_NONE, 0); + ok(hr == D3D_OK, "D3DXLoadSurfaceFromMemory returned %#x, expected %#x\n", hr, D3D_OK); + IDirect3DSurface9_LockRect(surf, &lockrect, NULL, D3DLOCK_READONLY); + check_pixel_4bpp(&lockrect, 0, 0, 0x57dbffff); + check_pixel_4bpp(&lockrect, 1, 0, 0x98ffff00); + check_pixel_4bpp(&lockrect, 0, 1, 0xacdbff55); + check_pixel_4bpp(&lockrect, 1, 1, 0xc8929255); + IDirect3DSurface9_UnlockRect(surf); + + hr = D3DXLoadSurfaceFromMemory(surf, NULL, NULL, pixdata_a1r5g5b5, D3DFMT_A1R5G5B5, 4, NULL, &rect, D3DX_FILTER_NONE, 0); + ok(hr == D3D_OK, "D3DXLoadSurfaceFromMemory returned %#x, expected %#x\n", hr, D3D_OK); + IDirect3DSurface9_LockRect(surf, &lockrect, NULL, D3DLOCK_READONLY); + check_pixel_4bpp(&lockrect, 0, 0, 0x008cadad); + check_pixel_4bpp(&lockrect, 1, 0, 0xff317342); + check_pixel_4bpp(&lockrect, 0, 1, 0x0008ad10); + check_pixel_4bpp(&lockrect, 1, 1, 0xff29088c); + IDirect3DSurface9_UnlockRect(surf); + + hr = D3DXLoadSurfaceFromMemory(surf, NULL, NULL, pixdata_r5g6b5, D3DFMT_R5G6B5, 4, NULL, &rect, D3DX_FILTER_NONE, 0); + ok(hr == D3D_OK, "D3DXLoadSurfaceFromMemory returned %#x, expected %#x\n", hr, D3D_OK); + IDirect3DSurface9_LockRect(surf, &lockrect, NULL, D3DLOCK_READONLY); + check_pixel_4bpp(&lockrect, 0, 0, 0xff9cdfb5); + check_pixel_4bpp(&lockrect, 1, 0, 0xff63b26b); + check_pixel_4bpp(&lockrect, 0, 1, 0xff085d73); + check_pixel_4bpp(&lockrect, 1, 1, 0xff425d73); + IDirect3DSurface9_UnlockRect(surf); + + hr = D3DXLoadSurfaceFromMemory(surf, NULL, NULL, pixdata_g16r16, D3DFMT_G16R16, 8, NULL, &rect, D3DX_FILTER_NONE, 0); + ok(hr == D3D_OK, "D3DXLoadSurfaceFromMemory returned %#x, expected %#x\n", hr, D3D_OK); + IDirect3DSurface9_LockRect(surf, &lockrect, NULL, D3DLOCK_READONLY); + todo_wine { + check_pixel_4bpp(&lockrect, 0, 0, 0xff3f08ff); + } + check_pixel_4bpp(&lockrect, 1, 0, 0xff44dcff); + check_pixel_4bpp(&lockrect, 0, 1, 0xff97e4ff); + check_pixel_4bpp(&lockrect, 1, 1, 0xfffe9aff); + IDirect3DSurface9_UnlockRect(surf); + + hr = D3DXLoadSurfaceFromMemory(surf, NULL, NULL, pixdata_a8b8g8r8, D3DFMT_A8B8G8R8, 8, NULL, &rect, D3DX_FILTER_NONE, 0); + ok(hr == D3D_OK, "D3DXLoadSurfaceFromMemory returned %#x, expected %#x\n", hr, D3D_OK); + IDirect3DSurface9_LockRect(surf, &lockrect, NULL, D3DLOCK_READONLY); + check_pixel_4bpp(&lockrect, 0, 0, 0xc3f04c39); + check_pixel_4bpp(&lockrect, 1, 0, 0x2392e85a); + check_pixel_4bpp(&lockrect, 0, 1, 0x09fd97b1); + check_pixel_4bpp(&lockrect, 1, 1, 0x8df62bc3); + IDirect3DSurface9_UnlockRect(surf); + + hr = D3DXLoadSurfaceFromMemory(surf, NULL, NULL, pixdata_a2r10g10b10, D3DFMT_A2R10G10B10, 8, NULL, &rect, D3DX_FILTER_NONE, 0); + ok(hr == D3D_OK, "D3DXLoadSurfaceFromMemory returned %#x, expected %#x\n", hr, D3D_OK); + IDirect3DSurface9_LockRect(surf, &lockrect, NULL, D3DLOCK_READONLY); + check_pixel_4bpp(&lockrect, 0, 0, 0x555c95bf); + check_pixel_4bpp(&lockrect, 1, 0, 0x556d663f); + check_pixel_4bpp(&lockrect, 0, 1, 0xaac385ad); + todo_wine { + check_pixel_4bpp(&lockrect, 1, 1, 0xfffcc575); + } + IDirect3DSurface9_UnlockRect(surf); + + hr = D3DXLoadSurfaceFromMemory(surf, NULL, NULL, pixdata_a8l8, + D3DFMT_A8L8, 4, NULL, &rect, D3DX_FILTER_NONE, 0); + ok(SUCCEEDED(hr), "Failed to load surface, hr %#x.\n", hr); + hr = IDirect3DSurface9_LockRect(surf, &lockrect, NULL, D3DLOCK_READONLY); + ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr); + check_pixel_4bpp(&lockrect, 0, 0, 0xff000000); + check_pixel_4bpp(&lockrect, 1, 0, 0x00ffffff); + check_pixel_4bpp(&lockrect, 0, 1, 0xff303030); + check_pixel_4bpp(&lockrect, 1, 1, 0x7f7f7f7f); + hr = IDirect3DSurface9_UnlockRect(surf); + ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr); + + /* Test D3DXLoadSurfaceFromMemory with indexed color image */ + if (0) + { + /* Crashes on Nvidia Win10. */ + palette.peRed = bmp_1bpp[56]; + palette.peGreen = bmp_1bpp[55]; + palette.peBlue = bmp_1bpp[54]; + palette.peFlags = bmp_1bpp[57]; /* peFlags is the alpha component in DX8 and higher */ + hr = D3DXLoadSurfaceFromMemory(surf, NULL, NULL, &bmp_1bpp[62], + D3DFMT_P8, 1, (const PALETTEENTRY *)&palette, &rect, D3DX_FILTER_NONE, 0); + ok(hr == D3D_OK, "D3DXLoadSurfaceFromFileInMemory returned %#x, expected %#x\n", hr, D3D_OK); + hr = IDirect3DSurface9_LockRect(surf, &lockrect, NULL, D3DLOCK_READONLY); + ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x\n", hr); + ok(*(DWORD*)lockrect.pBits == 0x80f3f2f1, "Pixel color mismatch: got %#x, expected 0x80f3f2f1\n", *(DWORD*)lockrect.pBits); + hr = IDirect3DSurface9_UnlockRect(surf); + ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x\n", hr); + } + + /* Test D3DXLoadSurfaceFromFileInMemory with indexed color image (alpha is not taken into account for bmp file) */ + hr = D3DXLoadSurfaceFromFileInMemory(surf, NULL, NULL, bmp_1bpp, sizeof(bmp_1bpp), NULL, D3DX_FILTER_NONE, 0, NULL); + ok(hr == D3D_OK, "D3DXLoadSurfaceFromFileInMemory returned %#x, expected %#x\n", hr, D3D_OK); + hr = IDirect3DSurface9_LockRect(surf, &lockrect, NULL, D3DLOCK_READONLY); + ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x\n", hr); + ok(*(DWORD*)lockrect.pBits == 0xfff3f2f1, "Pixel color mismatch: got %#x, expected 0xfff3f2f1\n", *(DWORD*)lockrect.pBits); + hr = IDirect3DSurface9_UnlockRect(surf); + ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x\n", hr); + + check_release((IUnknown*)surf, 0); + } + + /* A1R5G5B5 */ + hr = IDirect3DDevice9_CreateOffscreenPlainSurface(device, 2, 2, D3DFMT_A1R5G5B5, D3DPOOL_DEFAULT, &surf, NULL); + if(FAILED(hr)) skip("Failed to create a surface (%#x)\n", hr); + else { + hr = D3DXLoadSurfaceFromMemory(surf, NULL, NULL, pixdata_a8r3g3b2, D3DFMT_A8R3G3B2, 4, NULL, &rect, D3DX_FILTER_NONE, 0); + ok(hr == D3D_OK, "D3DXLoadSurfaceFromMemory returned %#x, expected %#x\n", hr, D3D_OK); + IDirect3DSurface9_LockRect(surf, &lockrect, NULL, D3DLOCK_READONLY); + check_pixel_2bpp(&lockrect, 0, 0, 0x6fff); + check_pixel_2bpp(&lockrect, 1, 0, 0xffe0); + check_pixel_2bpp(&lockrect, 0, 1, 0xefea); + check_pixel_2bpp(&lockrect, 1, 1, 0xca4a); + IDirect3DSurface9_UnlockRect(surf); + + hr = D3DXLoadSurfaceFromMemory(surf, NULL, NULL, pixdata_a1r5g5b5, D3DFMT_A1R5G5B5, 4, NULL, &rect, D3DX_FILTER_NONE, 0); + ok(hr == D3D_OK, "D3DXLoadSurfaceFromMemory returned %#x, expected %#x\n", hr, D3D_OK); + IDirect3DSurface9_LockRect(surf, &lockrect, NULL, D3DLOCK_READONLY); + check_pixel_2bpp(&lockrect, 0, 0, 0x46b5); + check_pixel_2bpp(&lockrect, 1, 0, 0x99c8); + check_pixel_2bpp(&lockrect, 0, 1, 0x06a2); + check_pixel_2bpp(&lockrect, 1, 1, 0x9431); + IDirect3DSurface9_UnlockRect(surf); + + hr = D3DXLoadSurfaceFromMemory(surf, NULL, NULL, pixdata_r5g6b5, D3DFMT_R5G6B5, 4, NULL, &rect, D3DX_FILTER_NONE, 0); + ok(hr == D3D_OK, "D3DXLoadSurfaceFromMemory returned %#x, expected %#x\n", hr, D3D_OK); + IDirect3DSurface9_LockRect(surf, &lockrect, NULL, D3DLOCK_READONLY); + check_pixel_2bpp(&lockrect, 0, 0, 0xcf76); + check_pixel_2bpp(&lockrect, 1, 0, 0xb2cd); + check_pixel_2bpp(&lockrect, 0, 1, 0x856e); + check_pixel_2bpp(&lockrect, 1, 1, 0xa16e); + IDirect3DSurface9_UnlockRect(surf); + + hr = D3DXLoadSurfaceFromMemory(surf, NULL, NULL, pixdata_g16r16, D3DFMT_G16R16, 8, NULL, &rect, D3DX_FILTER_NONE, 0); + ok(hr == D3D_OK, "D3DXLoadSurfaceFromMemory returned %#x, expected %#x\n", hr, D3D_OK); + IDirect3DSurface9_LockRect(surf, &lockrect, NULL, D3DLOCK_READONLY); + todo_wine { + check_pixel_2bpp(&lockrect, 0, 0, 0xa03f); + } + check_pixel_2bpp(&lockrect, 1, 0, 0xa37f); + check_pixel_2bpp(&lockrect, 0, 1, 0xcb9f); + check_pixel_2bpp(&lockrect, 1, 1, 0xfe7f); + IDirect3DSurface9_UnlockRect(surf); + + hr = D3DXLoadSurfaceFromMemory(surf, NULL, NULL, pixdata_a8b8g8r8, D3DFMT_A8B8G8R8, 8, NULL, &rect, D3DX_FILTER_NONE, 0); + ok(hr == D3D_OK, "D3DXLoadSurfaceFromMemory returned %#x, expected %#x\n", hr, D3D_OK); + IDirect3DSurface9_LockRect(surf, &lockrect, NULL, D3DLOCK_READONLY); + todo_wine { + check_pixel_2bpp(&lockrect, 0, 0, 0xf527); + check_pixel_2bpp(&lockrect, 1, 0, 0x4b8b); + } + check_pixel_2bpp(&lockrect, 0, 1, 0x7e56); + check_pixel_2bpp(&lockrect, 1, 1, 0xf8b8); + IDirect3DSurface9_UnlockRect(surf); + + hr = D3DXLoadSurfaceFromMemory(surf, NULL, NULL, pixdata_a2r10g10b10, D3DFMT_A2R10G10B10, 8, NULL, &rect, D3DX_FILTER_NONE, 0); + ok(hr == D3D_OK, "D3DXLoadSurfaceFromMemory returned %#x, expected %#x\n", hr, D3D_OK); + IDirect3DSurface9_LockRect(surf, &lockrect, NULL, D3DLOCK_READONLY); + check_pixel_2bpp(&lockrect, 0, 0, 0x2e57); + todo_wine { + check_pixel_2bpp(&lockrect, 1, 0, 0x3588); + } + check_pixel_2bpp(&lockrect, 0, 1, 0xe215); + check_pixel_2bpp(&lockrect, 1, 1, 0xff0e); + IDirect3DSurface9_UnlockRect(surf); + + hr = D3DXLoadSurfaceFromMemory(surf, NULL, NULL, pixdata_a8l8, + D3DFMT_A8L8, 4, NULL, &rect, D3DX_FILTER_NONE, 0); + ok(SUCCEEDED(hr), "Failed to load surface, hr %#x.\n", hr); + hr = IDirect3DSurface9_LockRect(surf, &lockrect, NULL, D3DLOCK_READONLY); + ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr); + check_pixel_2bpp(&lockrect, 0, 0, 0x8000); + check_pixel_2bpp(&lockrect, 1, 0, 0x7fff); + check_pixel_2bpp(&lockrect, 0, 1, 0x98c6); + check_pixel_2bpp(&lockrect, 1, 1, 0x3def); + hr = IDirect3DSurface9_UnlockRect(surf); + ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr); + + check_release((IUnknown*)surf, 0); + } + + /* A8L8 */ + hr = IDirect3DDevice9_CreateTexture(device, 2, 2, 1, 0, D3DFMT_A8L8, D3DPOOL_MANAGED, &tex, NULL); + if (FAILED(hr)) + skip("Failed to create A8L8 texture, hr %#x.\n", hr); + else + { + hr = IDirect3DTexture9_GetSurfaceLevel(tex, 0, &surf); + ok(SUCCEEDED(hr), "Failed to get the surface, hr %#x.\n", hr); + + hr = D3DXLoadSurfaceFromMemory(surf, NULL, NULL, pixdata_a8r3g3b2, + D3DFMT_A8R3G3B2, 4, NULL, &rect, D3DX_FILTER_NONE, 0); + ok(SUCCEEDED(hr), "Failed to load surface, hr %#x.\n", hr); + hr = IDirect3DSurface9_LockRect(surf, &lockrect, NULL, D3DLOCK_READONLY); + ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr); + check_pixel_2bpp(&lockrect, 0, 0, 0x57f7); + check_pixel_2bpp(&lockrect, 1, 0, 0x98ed); + check_pixel_2bpp(&lockrect, 0, 1, 0xaceb); + check_pixel_2bpp(&lockrect, 1, 1, 0xc88d); + hr = IDirect3DSurface9_UnlockRect(surf); + ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr); + + hr = D3DXLoadSurfaceFromMemory(surf, NULL, NULL, pixdata_a1r5g5b5, + D3DFMT_A1R5G5B5, 4, NULL, &rect, D3DX_FILTER_NONE, 0); + ok(hr == D3D_OK, "D3DXLoadSurfaceFromMemory returned %#x, expected %#x\n", hr, D3D_OK); + hr = IDirect3DSurface9_LockRect(surf, &lockrect, NULL, D3DLOCK_READONLY); + ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr); + check_pixel_2bpp(&lockrect, 0, 0, 0x00a6); + check_pixel_2bpp(&lockrect, 1, 0, 0xff62); + check_pixel_2bpp(&lockrect, 0, 1, 0x007f); + check_pixel_2bpp(&lockrect, 1, 1, 0xff19); + hr = IDirect3DSurface9_UnlockRect(surf); + ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr); + + hr = D3DXLoadSurfaceFromMemory(surf, NULL, NULL, pixdata_r5g6b5, + D3DFMT_R5G6B5, 4, NULL, &rect, D3DX_FILTER_NONE, 0); + ok(SUCCEEDED(hr), "Failed to load surface, hr %#x.\n", hr); + hr = IDirect3DSurface9_LockRect(surf, &lockrect, NULL, D3DLOCK_READONLY); + ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr); + check_pixel_2bpp(&lockrect, 0, 0, 0xffce); + check_pixel_2bpp(&lockrect, 1, 0, 0xff9c); + check_pixel_2bpp(&lockrect, 0, 1, 0xff4d); + check_pixel_2bpp(&lockrect, 1, 1, 0xff59); + hr = IDirect3DSurface9_UnlockRect(surf); + ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr); + + hr = D3DXLoadSurfaceFromMemory(surf, NULL, NULL, pixdata_g16r16, + D3DFMT_G16R16, 8, NULL, &rect, D3DX_FILTER_NONE, 0); + ok(SUCCEEDED(hr), "Failed to load surface, hr %#x.\n", hr); + hr = IDirect3DSurface9_LockRect(surf, &lockrect, NULL, D3DLOCK_READONLY); + ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr); + check_pixel_2bpp(&lockrect, 0, 0, 0xff25); + check_pixel_2bpp(&lockrect, 1, 0, 0xffbe); + check_pixel_2bpp(&lockrect, 0, 1, 0xffd6); + check_pixel_2bpp(&lockrect, 1, 1, 0xffb6); + hr = IDirect3DSurface9_UnlockRect(surf); + ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr); + + hr = D3DXLoadSurfaceFromMemory(surf, NULL, NULL, pixdata_a8b8g8r8, + D3DFMT_A8B8G8R8, 8, NULL, &rect, D3DX_FILTER_NONE, 0); + ok(SUCCEEDED(hr), "Failed to load surface, hr %#x.\n", hr); + hr = IDirect3DSurface9_LockRect(surf, &lockrect, NULL, D3DLOCK_READONLY); + ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr); + check_pixel_2bpp(&lockrect, 0, 0, 0xc36d); + check_pixel_2bpp(&lockrect, 1, 0, 0x23cb); + check_pixel_2bpp(&lockrect, 0, 1, 0x09af); + check_pixel_2bpp(&lockrect, 1, 1, 0x8d61); + hr = IDirect3DSurface9_UnlockRect(surf); + ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr); + + hr = D3DXLoadSurfaceFromMemory(surf, NULL, NULL, pixdata_a2r10g10b10, + D3DFMT_A2R10G10B10, 8, NULL, &rect, D3DX_FILTER_NONE, 0); + ok(SUCCEEDED(hr), "Failed to load surface, hr %#x.\n", hr); + hr = IDirect3DSurface9_LockRect(surf, &lockrect, NULL, D3DLOCK_READONLY); + ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr); + check_pixel_2bpp(&lockrect, 0, 0, 0x558c); + check_pixel_2bpp(&lockrect, 1, 0, 0x5565); + check_pixel_2bpp(&lockrect, 0, 1, 0xaa95); + check_pixel_2bpp(&lockrect, 1, 1, 0xffcb); + hr = IDirect3DSurface9_UnlockRect(surf); + ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr); + + hr = D3DXLoadSurfaceFromMemory(surf, NULL, NULL, pixdata_a8l8, + D3DFMT_A8L8, 4, NULL, &rect, D3DX_FILTER_NONE, 0); + ok(SUCCEEDED(hr), "Failed to load surface, hr %#x.\n", hr); + hr = IDirect3DSurface9_LockRect(surf, &lockrect, NULL, D3DLOCK_READONLY); + ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr); + check_pixel_2bpp(&lockrect, 0, 0, 0xff00); + check_pixel_2bpp(&lockrect, 1, 0, 0x00ff); + check_pixel_2bpp(&lockrect, 0, 1, 0xff30); + check_pixel_2bpp(&lockrect, 1, 1, 0x7f7f); + hr = IDirect3DSurface9_UnlockRect(surf); + ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr); + + check_release((IUnknown*)surf, 1); + check_release((IUnknown*)tex, 0); + } + + /* DXT1, DXT2, DXT3, DXT4, DXT5 */ + hr = IDirect3DDevice9_CreateOffscreenPlainSurface(device, 4, 4, D3DFMT_A8R8G8B8, D3DPOOL_SYSTEMMEM, &surf, NULL); + if (FAILED(hr)) + skip("Failed to create R8G8B8 surface, hr %#x.\n", hr); + else + { + hr = D3DXLoadSurfaceFromFileInMemory(surf, NULL, NULL, dds_24bit, sizeof(dds_24bit), NULL, D3DX_FILTER_NONE, 0, NULL); + ok(SUCCEEDED(hr), "Failed to load surface, hr %#x.\n", hr); + + hr = IDirect3DDevice9_CreateTexture(device, 4, 4, 1, 0, D3DFMT_DXT2, D3DPOOL_SYSTEMMEM, &tex, NULL); + if (FAILED(hr)) + skip("Failed to create DXT2 texture, hr %#x.\n", hr); + else + { + hr = IDirect3DTexture9_GetSurfaceLevel(tex, 0, &newsurf); + ok(SUCCEEDED(hr), "Failed to get the surface, hr %#x.\n", hr); + hr = D3DXLoadSurfaceFromSurface(newsurf, NULL, NULL, surf, NULL, NULL, D3DX_FILTER_NONE, 0); + todo_wine ok(SUCCEEDED(hr), "Failed to convert pixels to DXT2 format.\n"); + check_release((IUnknown*)newsurf, 1); + check_release((IUnknown*)tex, 0); + } + + hr = IDirect3DDevice9_CreateTexture(device, 4, 4, 1, 0, D3DFMT_DXT3, D3DPOOL_SYSTEMMEM, &tex, NULL); + if (FAILED(hr)) + skip("Failed to create DXT3 texture, hr %#x.\n", hr); + else + { + hr = IDirect3DTexture9_GetSurfaceLevel(tex, 0, &newsurf); + ok(SUCCEEDED(hr), "Failed to get the surface, hr %#x.\n", hr); + hr = D3DXLoadSurfaceFromSurface(newsurf, NULL, NULL, surf, NULL, NULL, D3DX_FILTER_NONE, 0); + todo_wine ok(SUCCEEDED(hr), "Failed to convert pixels to DXT3 format.\n"); + check_release((IUnknown*)newsurf, 1); + check_release((IUnknown*)tex, 0); + } + + hr = IDirect3DDevice9_CreateTexture(device, 4, 4, 1, 0, D3DFMT_DXT4, D3DPOOL_SYSTEMMEM, &tex, NULL); + if (FAILED(hr)) + skip("Failed to create DXT4 texture, hr %#x.\n", hr); + else + { + hr = IDirect3DTexture9_GetSurfaceLevel(tex, 0, &newsurf); + ok(SUCCEEDED(hr), "Failed to get the surface, hr %#x.\n", hr); + hr = D3DXLoadSurfaceFromSurface(newsurf, NULL, NULL, surf, NULL, NULL, D3DX_FILTER_NONE, 0); + todo_wine ok(SUCCEEDED(hr), "Failed to convert pixels to DXT4 format.\n"); + check_release((IUnknown*)newsurf, 1); + check_release((IUnknown*)tex, 0); + } + + hr = IDirect3DDevice9_CreateTexture(device, 4, 4, 1, 0, D3DFMT_DXT5, D3DPOOL_SYSTEMMEM, &tex, NULL); + if (FAILED(hr)) + skip("Failed to create DXT5 texture, hr %#x.\n", hr); + else + { + hr = IDirect3DTexture9_GetSurfaceLevel(tex, 0, &newsurf); + ok(SUCCEEDED(hr), "Failed to get the surface, hr %#x.\n", hr); + hr = D3DXLoadSurfaceFromSurface(newsurf, NULL, NULL, surf, NULL, NULL, D3DX_FILTER_NONE, 0); + todo_wine ok(SUCCEEDED(hr), "Failed to convert pixels to DXT5 format.\n"); + check_release((IUnknown*)newsurf, 1); + check_release((IUnknown*)tex, 0); + } + + hr = IDirect3DDevice9_CreateTexture(device, 4, 4, 1, 0, D3DFMT_DXT1, D3DPOOL_SYSTEMMEM, &tex, NULL); + if (FAILED(hr)) + skip("Failed to create DXT1 texture, hr %#x.\n", hr); + else + { + hr = IDirect3DTexture9_GetSurfaceLevel(tex, 0, &newsurf); + ok(SUCCEEDED(hr), "Failed to get the surface, hr %#x.\n", hr); + hr = D3DXLoadSurfaceFromSurface(newsurf, NULL, NULL, surf, NULL, NULL, D3DX_FILTER_NONE, 0); + todo_wine ok(SUCCEEDED(hr), "Failed to convert pixels to DXT1 format.\n"); + + hr = D3DXLoadSurfaceFromSurface(surf, NULL, NULL, newsurf, NULL, NULL, D3DX_FILTER_NONE, 0); + todo_wine ok(SUCCEEDED(hr), "Failed to convert pixels from DXT1 format.\n"); + + check_release((IUnknown*)newsurf, 1); + check_release((IUnknown*)tex, 0); + } + + check_release((IUnknown*)surf, 0); + } + + /* cleanup */ + if(testdummy_ok) DeleteFileA("testdummy.bmp"); + if(testbitmap_ok) DeleteFileA("testbitmap.bmp"); +} + +static void test_D3DXSaveSurfaceToFileInMemory(IDirect3DDevice9 *device) +{ + HRESULT hr; + RECT rect; + ID3DXBuffer *buffer; + IDirect3DSurface9 *surface; + struct + { + DWORD magic; + struct dds_header header; + BYTE *data; + } *dds; + + hr = IDirect3DDevice9_CreateOffscreenPlainSurface(device, 4, 4, D3DFMT_A8R8G8B8, D3DPOOL_SCRATCH, &surface, NULL); + if (FAILED(hr)) { + skip("Couldn't create surface\n"); + return; + } + + SetRectEmpty(&rect); + hr = D3DXSaveSurfaceToFileInMemory(&buffer, D3DXIFF_BMP, surface, NULL, &rect); + /* fails with the debug version of d3d9 */ + ok(hr == D3D_OK || broken(hr == D3DERR_INVALIDCALL), "D3DXSaveSurfaceToFileInMemory returned %#x, expected %#x\n", hr, D3D_OK); + if (SUCCEEDED(hr)) { + DWORD size = ID3DXBuffer_GetBufferSize(buffer); + ok(size > 0, "ID3DXBuffer_GetBufferSize returned %u, expected > 0\n", size); + ID3DXBuffer_Release(buffer); + } + + SetRectEmpty(&rect); + hr = D3DXSaveSurfaceToFileInMemory(&buffer, D3DXIFF_DDS, surface, NULL, &rect); + todo_wine ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr); + if (SUCCEEDED(hr)) + { + dds = ID3DXBuffer_GetBufferPointer(buffer); + + ok(dds->magic == MAKEFOURCC('D','D','S',' '), "Got unexpected DDS signature %#x.\n", dds->magic); + ok(dds->header.size == sizeof(dds->header), "Got unexpected DDS size %u.\n", dds->header.size); + ok(!dds->header.height, "Got unexpected height %u.\n", dds->header.height); + ok(!dds->header.width, "Got unexpected width %u.\n", dds->header.width); + ok(!dds->header.depth, "Got unexpected depth %u.\n", dds->header.depth); + ok(!dds->header.miplevels, "Got unexpected miplevels %u.\n", dds->header.miplevels); + ok(!dds->header.pitch_or_linear_size, "Got unexpected pitch_or_linear_size %u.\n", dds->header.pitch_or_linear_size); + ok(dds->header.caps == (DDS_CAPS_TEXTURE | DDSCAPS_ALPHA), "Got unexpected caps %#x.\n", dds->header.caps); + ok(dds->header.flags == (DDS_CAPS | DDS_HEIGHT | DDS_WIDTH | DDS_PIXELFORMAT), + "Got unexpected flags %#x.\n", dds->header.flags); + ID3DXBuffer_Release(buffer); + } + + hr = D3DXSaveSurfaceToFileInMemory(&buffer, D3DXIFF_DDS, surface, NULL, NULL); + ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr); + + dds = ID3DXBuffer_GetBufferPointer(buffer); + ok(dds->magic == MAKEFOURCC('D','D','S',' '), "Got unexpected DDS signature %#x.\n", dds->magic); + ok(dds->header.size == sizeof(dds->header), "Got unexpected DDS size %u.\n", dds->header.size); + ok(dds->header.height == 4, "Got unexpected height %u.\n", dds->header.height); + ok(dds->header.width == 4, "Got unexpected width %u.\n", dds->header.width); + ok(!dds->header.depth, "Got unexpected depth %u.\n", dds->header.depth); + ok(!dds->header.miplevels, "Got unexpected miplevels %u.\n", dds->header.miplevels); + ok(!dds->header.pitch_or_linear_size, "Got unexpected pitch_or_linear_size %u.\n", dds->header.pitch_or_linear_size); + todo_wine ok(dds->header.caps == (DDS_CAPS_TEXTURE | DDSCAPS_ALPHA), "Got unexpected caps %#x.\n", dds->header.caps); + ok(dds->header.flags == (DDS_CAPS | DDS_HEIGHT | DDS_WIDTH | DDS_PIXELFORMAT), + "Got unexpected flags %#x.\n", dds->header.flags); + ID3DXBuffer_Release(buffer); + + IDirect3DSurface9_Release(surface); +} + +static void test_D3DXSaveSurfaceToFile(IDirect3DDevice9 *device) +{ + HRESULT hr; + IDirect3DSurface9 *surface; + RECT rect; + D3DLOCKED_RECT lock_rect; + D3DXIMAGE_INFO image_info; + const BYTE pixels[] = { 0xff, 0x00, 0x00, 0x00, 0xff, 0x00, + 0x00, 0x00, 0xff, 0x00, 0x00, 0xff }; + DWORD pitch = sizeof(pixels) / 2; + + hr = IDirect3DDevice9_CreateOffscreenPlainSurface(device, 2, 2, D3DFMT_R8G8B8, D3DPOOL_SCRATCH, &surface, NULL); + if (FAILED(hr)) { + skip("Couldn't create surface\n"); + return; + } + + SetRect(&rect, 0, 0, 2, 2); + hr = D3DXLoadSurfaceFromMemory(surface, NULL, NULL, pixels, D3DFMT_R8G8B8, pitch, NULL, &rect, D3DX_FILTER_NONE, 0); + if (SUCCEEDED(hr)) { + hr = D3DXSaveSurfaceToFileA("saved_surface.bmp", D3DXIFF_BMP, surface, NULL, NULL); + ok(hr == D3D_OK, "D3DXSaveSurfaceToFileA returned %#x, expected %#x\n", hr, D3D_OK); + + hr = D3DXLoadSurfaceFromFileA(surface, NULL, NULL, "saved_surface.bmp", NULL, D3DX_FILTER_NONE, 0, &image_info); + ok(hr == D3D_OK, "Couldn't load saved surface %#x\n", hr); + if (FAILED(hr)) goto next_tests; + + ok(image_info.Width == 2, "Wrong width %u\n", image_info.Width); + ok(image_info.Height == 2, "Wrong height %u\n", image_info.Height); + ok(image_info.Format == D3DFMT_R8G8B8, "Wrong format %#x\n", image_info.Format); + ok(image_info.ImageFileFormat == D3DXIFF_BMP, "Wrong file format %u\n", image_info.ImageFileFormat); + + hr = IDirect3DSurface9_LockRect(surface, &lock_rect, NULL, D3DLOCK_READONLY); + ok(hr == D3D_OK, "Couldn't lock surface %#x\n", hr); + if (FAILED(hr)) goto next_tests; + + ok(!memcmp(lock_rect.pBits, pixels, pitch), "Pixel data mismatch in first row\n"); + ok(!memcmp((BYTE *)lock_rect.pBits + lock_rect.Pitch, pixels + pitch, pitch), "Pixel data mismatch in second row\n"); + + IDirect3DSurface9_UnlockRect(surface); + } else skip("Couldn't fill surface\n"); + +next_tests: + hr = D3DXSaveSurfaceToFileA(NULL, D3DXIFF_BMP, surface, NULL, NULL); + ok(hr == D3DERR_INVALIDCALL, "D3DXSaveSurfaceToFileA returned %#x, expected %#x\n", hr, D3DERR_INVALIDCALL); + + /* PPM and TGA are supported, even though MSDN claims they aren't */ + todo_wine { + hr = D3DXSaveSurfaceToFileA("saved_surface.ppm", D3DXIFF_PPM, surface, NULL, NULL); + ok(hr == D3D_OK, "D3DXSaveSurfaceToFileA returned %#x, expected %#x\n", hr, D3D_OK); + hr = D3DXSaveSurfaceToFileA("saved_surface.tga", D3DXIFF_TGA, surface, NULL, NULL); + ok(hr == D3D_OK, "D3DXSaveSurfaceToFileA returned %#x, expected %#x\n", hr, D3D_OK); + } + + hr = D3DXSaveSurfaceToFileA("saved_surface.dds", D3DXIFF_DDS, surface, NULL, NULL); + ok(hr == D3D_OK, "D3DXSaveSurfaceToFileA returned %#x, expected %#x\n", hr, D3D_OK); + if (SUCCEEDED(hr)) { + hr = D3DXLoadSurfaceFromFileA(surface, NULL, NULL, "saved_surface.dds", NULL, D3DX_FILTER_NONE, 0, &image_info); + ok(hr == D3D_OK, "Couldn't load saved surface %#x\n", hr); + + if (SUCCEEDED(hr)) { + ok(image_info.Width == 2, "Wrong width %u\n", image_info.Width); + ok(image_info.Format == D3DFMT_R8G8B8, "Wrong format %#x\n", image_info.Format); + ok(image_info.ImageFileFormat == D3DXIFF_DDS, "Wrong file format %u\n", image_info.ImageFileFormat); + + hr = IDirect3DSurface9_LockRect(surface, &lock_rect, NULL, D3DLOCK_READONLY); + ok(hr == D3D_OK, "Couldn't lock surface %#x\n", hr); + if (SUCCEEDED(hr)) { + ok(!memcmp(lock_rect.pBits, pixels, pitch), "Pixel data mismatch in first row\n"); + ok(!memcmp((BYTE *)lock_rect.pBits + lock_rect.Pitch, pixels + pitch, pitch), "Pixel data mismatch in second row\n"); + IDirect3DSurface9_UnlockRect(surface); + } + } + } else skip("Couldn't save surface\n"); + + hr = D3DXSaveSurfaceToFileA("saved_surface", D3DXIFF_PFM + 1, surface, NULL, NULL); + ok(hr == D3DERR_INVALIDCALL, "D3DXSaveSurfaceToFileA returned %#x, expected %#x\n", hr, D3DERR_INVALIDCALL); + + SetRect(&rect, 0, 0, 4, 4); + hr = D3DXSaveSurfaceToFileA("saved_surface.bmp", D3DXIFF_BMP, surface, NULL, &rect); + ok(hr == D3DERR_INVALIDCALL, "D3DXSaveSurfaceToFileA returned %#x, expected %#x\n", hr, D3DERR_INVALIDCALL); + SetRect(&rect, 2, 0, 1, 4); + hr = D3DXSaveSurfaceToFileA("saved_surface.bmp", D3DXIFF_BMP, surface, NULL, &rect); + ok(hr == D3DERR_INVALIDCALL, "D3DXSaveSurfaceToFileA returned %#x, expected %#x\n", hr, D3DERR_INVALIDCALL); + SetRect(&rect, 0, 2, 4, 1); + hr = D3DXSaveSurfaceToFileA("saved_surface.bmp", D3DXIFF_BMP, surface, NULL, &rect); + ok(hr == D3DERR_INVALIDCALL, "D3DXSaveSurfaceToFileA returned %#x, expected %#x\n", hr, D3DERR_INVALIDCALL); + SetRect(&rect, -1, -1, 2, 2); + hr = D3DXSaveSurfaceToFileA("saved_surface.bmp", D3DXIFF_BMP, surface, NULL, &rect); + ok(hr == D3DERR_INVALIDCALL, "D3DXSaveSurfaceToFileA returned %#x, expected %#x\n", hr, D3DERR_INVALIDCALL); + SetRectEmpty(&rect); + hr = D3DXSaveSurfaceToFileA("saved_surface.bmp", D3DXIFF_BMP, surface, NULL, &rect); + /* fails when debug version of d3d9 is used */ + ok(hr == D3D_OK || broken(hr == D3DERR_INVALIDCALL), "D3DXSaveSurfaceToFileA returned %#x, expected %#x\n", hr, D3D_OK); + + DeleteFileA("saved_surface.bmp"); + DeleteFileA("saved_surface.ppm"); + DeleteFileA("saved_surface.tga"); + DeleteFileA("saved_surface.dds"); + + IDirect3DSurface9_Release(surface); +} + +START_TEST(surface) +{ + HWND wnd; + IDirect3D9 *d3d; + IDirect3DDevice9 *device; + D3DPRESENT_PARAMETERS d3dpp; + HRESULT hr; + + if (!(wnd = CreateWindowA("static", "d3dx9_test", WS_OVERLAPPEDWINDOW, 0, 0, + 640, 480, NULL, NULL, NULL, NULL))) + { + skip("Couldn't create application window\n"); + return; + } + d3d = Direct3DCreate9(D3D_SDK_VERSION); + if (!d3d) { + 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_SOFTWARE_VERTEXPROCESSING, &d3dpp, &device); + if(FAILED(hr)) { + skip("Failed to create IDirect3DDevice9 object %#x\n", hr); + IDirect3D9_Release(d3d); + DestroyWindow(wnd); + return; + } + + test_D3DXGetImageInfo(); + test_D3DXLoadSurface(device); + test_D3DXSaveSurfaceToFileInMemory(device); + test_D3DXSaveSurfaceToFile(device); + + check_release((IUnknown*)device, 0); + check_release((IUnknown*)d3d, 0); + DestroyWindow(wnd); +} diff --git a/modules/rostests/winetests/d3dx9_36/testlist.c b/modules/rostests/winetests/d3dx9_36/testlist.c new file mode 100644 index 00000000000..9fc068c0da7 --- /dev/null +++ b/modules/rostests/winetests/d3dx9_36/testlist.c @@ -0,0 +1,32 @@ +/* Automatically generated by make depend; DO NOT EDIT!! */ + +#define STANDALONE +#include + +extern void func_asm(void); +extern void func_core(void); +extern void func_effect(void); +extern void func_line(void); +extern void func_math(void); +extern void func_mesh(void); +extern void func_shader(void); +extern void func_surface(void); +extern void func_texture(void); +extern void func_volume(void); +extern void func_xfile(void); + +const struct test winetest_testlist[] = +{ + { "asm", func_asm }, + { "core", func_core }, + { "effect", func_effect }, + { "line", func_line }, + { "math", func_math }, + { "mesh", func_mesh }, + { "shader", func_shader }, + { "surface", func_surface }, + { "texture", func_texture }, + { "volume", func_volume }, + { "xfile", func_xfile }, + { 0, 0 } +}; diff --git a/modules/rostests/winetests/d3dx9_36/texture.c b/modules/rostests/winetests/d3dx9_36/texture.c new file mode 100644 index 00000000000..79cddc73ab6 --- /dev/null +++ b/modules/rostests/winetests/d3dx9_36/texture.c @@ -0,0 +1,2264 @@ +/* + * Tests for the D3DX9 texture functions + * + * Copyright 2009 Tony Wasserka + * Copyright 2010 Owen Rudge for CodeWeavers + * Copyright 2010 Matteo Bruni for CodeWeavers + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA + */ + +#define COBJMACROS +#include "wine/test.h" +#include "d3dx9tex.h" +#include "resources.h" + +static int has_2d_dxt3, has_2d_dxt5, has_cube_dxt5, has_3d_dxt3; + +/* 2x2 16-bit dds, no mipmaps */ +static const unsigned char dds_16bit[] = { +0x44,0x44,0x53,0x20,0x7c,0x00,0x00,0x00,0x07,0x10,0x08,0x00,0x02,0x00,0x00,0x00, +0x02,0x00,0x00,0x00,0x08,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x20,0x00,0x00,0x00, +0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x10,0x00,0x00,0x00,0x00,0x7c,0x00,0x00, +0xe0,0x03,0x00,0x00,0x1f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x10,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0xff,0x7f,0xff,0x7f,0xff,0x7f,0xff,0x7f +}; + +/* 2x2 24-bit dds, 2 mipmaps */ +static const unsigned char dds_24bit[] = { +0x44,0x44,0x53,0x20,0x7c,0x00,0x00,0x00,0x07,0x10,0x0a,0x00,0x02,0x00,0x00,0x00, +0x02,0x00,0x00,0x00,0x0c,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x20,0x00,0x00,0x00, +0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x18,0x00,0x00,0x00,0x00,0x00,0xff,0x00, +0x00,0xff,0x00,0x00,0xff,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x08,0x10,0x40,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff +}; + +/* 4x4 cube map dds */ +static const unsigned char dds_cube_map[] = { +0x44,0x44,0x53,0x20,0x7c,0x00,0x00,0x00,0x07,0x10,0x08,0x00,0x04,0x00,0x00,0x00, +0x04,0x00,0x00,0x00,0x10,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x20,0x00,0x00,0x00, +0x04,0x00,0x00,0x00,0x44,0x58,0x54,0x35,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x08,0x10,0x00,0x00, +0x00,0xfe,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0xff,0xff,0x00,0x00,0x00,0x00,0x00,0x00,0xef,0x87,0x0f,0x78,0x05,0x05,0x50,0x50, +0xff,0xff,0x00,0x00,0x00,0x00,0x00,0x00,0xef,0x87,0x0f,0x78,0x05,0x05,0x50,0x51, +0xff,0xff,0x00,0x00,0x00,0x00,0x00,0x00,0xef,0x87,0x0f,0x78,0x05,0x05,0x50,0x52, +0xff,0xff,0x00,0x00,0x00,0x00,0x00,0x00,0xef,0x87,0x0f,0x78,0x05,0x05,0x50,0x53, +0xff,0xff,0x00,0x00,0x00,0x00,0x00,0x00,0xef,0x87,0x0f,0x78,0x05,0x05,0x50,0x54, +0xff,0xff,0x00,0x00,0x00,0x00,0x00,0x00,0xef,0x87,0x0f,0x78,0x05,0x05,0x50,0x55 +}; + +/* 4x4x2 volume map dds, 2 mipmaps */ +static const unsigned char dds_volume_map[] = { +0x44,0x44,0x53,0x20,0x7c,0x00,0x00,0x00,0x07,0x10,0x8a,0x00,0x04,0x00,0x00,0x00, +0x04,0x00,0x00,0x00,0x10,0x00,0x00,0x00,0x02,0x00,0x00,0x00,0x03,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x20,0x00,0x00,0x00, +0x04,0x00,0x00,0x00,0x44,0x58,0x54,0x33,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x08,0x10,0x40,0x00, +0x00,0x00,0x20,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xef,0x87,0x0f,0x78,0x05,0x05,0x50,0x50, +0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xef,0x87,0x0f,0x78,0x05,0x05,0x50,0x50, +0xff,0x00,0xff,0x00,0x00,0x00,0x00,0x00,0x2f,0x7e,0xcf,0x79,0x01,0x54,0x5c,0x5c, +0x0f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x10,0x84,0xef,0x7b,0xaa,0xab,0xab,0xab +}; + +static const unsigned char png_grayscale[] = +{ + 0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a, 0x00, 0x00, 0x00, 0x0d, 0x49, + 0x48, 0x44, 0x52, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x08, 0x00, + 0x00, 0x00, 0x00, 0x3a, 0x7e, 0x9b, 0x55, 0x00, 0x00, 0x00, 0x0a, 0x49, 0x44, + 0x41, 0x54, 0x08, 0xd7, 0x63, 0xf8, 0x0f, 0x00, 0x01, 0x01, 0x01, 0x00, 0x1b, + 0xb6, 0xee, 0x56, 0x00, 0x00, 0x00, 0x00, 0x49, 0x45, 0x4e, 0x44, 0xae, 0x42, + 0x60, 0x82 +}; + +#define ADMITTED_ERROR 0.0001f + +static inline float relative_error(float expected, float got) +{ + return expected == 0.0f ? fabs(expected - got) : fabs(1.0f - got / expected); +} + +#define expect_vec4(expected, got) expect_vec4_(__LINE__, expected, got) +static inline void expect_vec4_(unsigned int line, const D3DXVECTOR4 *expected, const D3DXVECTOR4 *got) +{ + ok_(__FILE__, line)(relative_error(expected->x, got->x) < ADMITTED_ERROR + && relative_error(expected->y, got->y) < ADMITTED_ERROR + && relative_error(expected->z, got->z) < ADMITTED_ERROR + && relative_error(expected->w, got->w) < ADMITTED_ERROR, + "Expected (%f, %f, %f, %f), got (%f, %f, %f, %f)\n", + expected->x, expected->y, expected->z, expected->w, + got->x, got->y, got->z, got->w); +} + +static BOOL compare_color(DWORD c1, DWORD c2, BYTE max_diff) +{ + if (abs((c1 & 0xff) - (c2 & 0xff)) > max_diff) + return FALSE; + c1 >>= 8; c2 >>= 8; + if (abs((c1 & 0xff) - (c2 & 0xff)) > max_diff) + return FALSE; + c1 >>= 8; c2 >>= 8; + if (abs((c1 & 0xff) - (c2 & 0xff)) > max_diff) + return FALSE; + c1 >>= 8; c2 >>= 8; + if (abs((c1 & 0xff) - (c2 & 0xff)) > max_diff) + return FALSE; + return TRUE; +} + +static BOOL is_autogenmipmap_supported(IDirect3DDevice9 *device, D3DRESOURCETYPE resource_type) +{ + HRESULT hr; + D3DCAPS9 caps; + IDirect3D9 *d3d9; + D3DDISPLAYMODE mode; + D3DDEVICE_CREATION_PARAMETERS params; + + IDirect3DDevice9_GetDeviceCaps(device, &caps); + IDirect3DDevice9_GetDirect3D(device, &d3d9); + IDirect3DDevice9_GetCreationParameters(device, ¶ms); + IDirect3DDevice9_GetDisplayMode(device, 0, &mode); + + if (!(caps.Caps2 & D3DCAPS2_CANAUTOGENMIPMAP)) + return FALSE; + + hr = IDirect3D9_CheckDeviceFormat(d3d9, params.AdapterOrdinal, params.DeviceType, + mode.Format, D3DUSAGE_AUTOGENMIPMAP, resource_type, D3DFMT_A8R8G8B8); + + IDirect3D9_Release(d3d9); + return hr == D3D_OK; +} + +static void test_D3DXCheckTextureRequirements(IDirect3DDevice9 *device) +{ + UINT width, height, mipmaps; + D3DFORMAT format, expected; + D3DCAPS9 caps; + HRESULT hr; + IDirect3D9 *d3d; + D3DDEVICE_CREATION_PARAMETERS params; + D3DDISPLAYMODE mode; + + IDirect3DDevice9_GetDeviceCaps(device, &caps); + + /* general tests */ + hr = D3DXCheckTextureRequirements(device, NULL, NULL, NULL, 0, NULL, D3DPOOL_DEFAULT); + ok(hr == D3D_OK, "D3DXCheckTextureRequirements returned %#x, expected %#x\n", hr, D3D_OK); + + hr = D3DXCheckTextureRequirements(device, NULL, NULL, NULL, D3DX_DEFAULT, NULL, D3DPOOL_DEFAULT); + ok(hr == D3D_OK, "D3DXCheckTextureRequirements returned %#x, expected %#x\n", hr, D3D_OK); + + hr = D3DXCheckTextureRequirements(NULL, NULL, NULL, NULL, D3DX_DEFAULT, NULL, D3DPOOL_DEFAULT); + ok(hr == D3DERR_INVALIDCALL, "D3DXCheckTextureRequirements returned %#x, expected %#x\n", hr, D3DERR_INVALIDCALL); + + /* width & height */ + width = height = D3DX_DEFAULT; + hr = D3DXCheckTextureRequirements(device, &width, &height, NULL, 0, NULL, D3DPOOL_DEFAULT); + ok(hr == D3D_OK, "D3DXCheckTextureRequirements returned %#x, expected %#x\n", hr, D3D_OK); + ok(width == 256, "Returned width %d, expected %d\n", width, 256); + ok(height == 256, "Returned height %d, expected %d\n", height, 256); + + width = D3DX_DEFAULT; + hr = D3DXCheckTextureRequirements(device, &width, NULL, NULL, 0, NULL, D3DPOOL_DEFAULT); + ok(hr == D3D_OK, "D3DXCheckTextureRequirements returned %#x, expected %#x\n", hr, D3D_OK); + ok(width == 256, "Returned width %d, expected %d\n", width, 256); + + if (caps.TextureCaps & D3DPTEXTURECAPS_POW2) + skip("Hardware only supports pow2 textures\n"); + else + { + width = 62; + hr = D3DXCheckTextureRequirements(device, &width, NULL, NULL, 0, NULL, D3DPOOL_DEFAULT); + ok(hr == D3D_OK, "D3DXCheckTextureRequirements returned %#x, expected %#x\n", hr, D3D_OK); + ok(width == 62, "Returned width %d, expected %d\n", width, 62); + + width = D3DX_DEFAULT; height = 63; + hr = D3DXCheckTextureRequirements(device, &width, &height, NULL, 0, NULL, D3DPOOL_DEFAULT); + ok(hr == D3D_OK, "D3DXCheckTextureRequirements returned %#x, expected %#x\n", hr, D3D_OK); + ok(width == height, "Returned width %d, expected %d\n", width, height); + ok(height == 63, "Returned height %d, expected %d\n", height, 63); + } + + width = D3DX_DEFAULT; height = 0; + hr = D3DXCheckTextureRequirements(device, &width, &height, NULL, 0, NULL, D3DPOOL_DEFAULT); + ok(hr == D3D_OK, "D3DXCheckTextureRequirements returned %#x, expected %#x\n", hr, D3D_OK); + ok(width == 1, "Returned width %d, expected %d\n", width, 1); + ok(height == 1, "Returned height %d, expected %d\n", height, 1); + + width = 0; height = 0; + hr = D3DXCheckTextureRequirements(device, &width, &height, NULL, 0, NULL, D3DPOOL_DEFAULT); + ok(hr == D3D_OK, "D3DXCheckTextureRequirements returned %#x, expected %#x\n", hr, D3D_OK); + ok(width == 1, "Returned width %d, expected %d\n", width, 1); + ok(height == 1, "Returned height %d, expected %d\n", height, 1); + + width = 0; + hr = D3DXCheckTextureRequirements(device, &width, NULL, NULL, 0, NULL, D3DPOOL_DEFAULT); + ok(hr == D3D_OK, "D3DXCheckTextureRequirements returned %#x, expected %#x\n", hr, D3D_OK); + ok(width == 1, "Returned width %d, expected %d\n", width, 1); + + width = 0xFFFFFFFE; + hr = D3DXCheckTextureRequirements(device, &width, NULL, NULL, 0, NULL, D3DPOOL_DEFAULT); + ok(hr == D3D_OK, "D3DXCheckTextureRequirements returned %#x, expected %#x\n", hr, D3D_OK); + ok(width == caps.MaxTextureWidth, "Returned width %d, expected %d\n", width, caps.MaxTextureWidth); + + width = caps.MaxTextureWidth-1; + hr = D3DXCheckTextureRequirements(device, &width, NULL, NULL, 0, NULL, D3DPOOL_DEFAULT); + ok(hr == D3D_OK, "D3DXCheckTextureRequirements returned %#x, expected %#x\n", hr, D3D_OK); + if (caps.TextureCaps & D3DPTEXTURECAPS_POW2) + ok(width == caps.MaxTextureWidth, "Returned width %d, expected %d\n", width, caps.MaxTextureWidth); + else + ok(width == caps.MaxTextureWidth-1, "Returned width %d, expected %d\n", width, caps.MaxTextureWidth-1); + + /* mipmaps */ + width = 64; height = 63; + mipmaps = 9; + hr = D3DXCheckTextureRequirements(device, &width, &height, &mipmaps, 0, NULL, D3DPOOL_DEFAULT); + ok(hr == D3D_OK, "D3DXCheckTextureRequirements returned %#x, expected %#x\n", hr, D3D_OK); + ok(mipmaps == 7, "Returned mipmaps %d, expected %d\n", mipmaps, 7); + + if (!(caps.TextureCaps & D3DPTEXTURECAPS_POW2)) + { + width = 284; height = 137; + mipmaps = 20; + hr = D3DXCheckTextureRequirements(device, &width, &height, &mipmaps, 0, NULL, D3DPOOL_DEFAULT); + ok(hr == D3D_OK, "D3DXCheckTextureRequirements returned %#x, expected %#x\n", hr, D3D_OK); + ok(mipmaps == 9, "Returned mipmaps %d, expected %d\n", mipmaps, 9); + + width = height = 63; + mipmaps = 9; + hr = D3DXCheckTextureRequirements(device, &width, &height, &mipmaps, 0, NULL, D3DPOOL_DEFAULT); + ok(hr == D3D_OK, "D3DXCheckTextureRequirements returned %#x, expected %#x\n", hr, D3D_OK); + ok(mipmaps == 6, "Returned mipmaps %d, expected %d\n", mipmaps, 6); + } + else + skip("Skipping some tests, npot2 textures unsupported\n"); + + mipmaps = 20; + hr = D3DXCheckTextureRequirements(device, NULL, NULL, &mipmaps, 0, NULL, D3DPOOL_DEFAULT); + ok(hr == D3D_OK, "D3DXCheckTextureRequirements returned %#x, expected %#x\n", hr, D3D_OK); + ok(mipmaps == 9, "Returned mipmaps %d, expected %d\n", mipmaps, 9); + + mipmaps = 0; + hr = D3DXCheckTextureRequirements(device, NULL, NULL, &mipmaps, 0, NULL, D3DPOOL_DEFAULT); + ok(hr == D3D_OK, "D3DXCheckTextureRequirements returned %#x, expected %#x\n", hr, D3D_OK); + ok(mipmaps == 9, "Returned mipmaps %d, expected %d\n", mipmaps, 9); + + /* mipmaps when D3DUSAGE_AUTOGENMIPMAP is set */ + if (is_autogenmipmap_supported(device, D3DRTYPE_TEXTURE)) + { + mipmaps = 0; + hr = D3DXCheckTextureRequirements(device, NULL, NULL, &mipmaps, D3DUSAGE_AUTOGENMIPMAP, NULL, D3DPOOL_DEFAULT); + ok(hr == D3D_OK, "D3DXCheckTextureRequirements returned %#x, expected %#x\n", hr, D3D_OK); + ok(mipmaps == 0, "Returned mipmaps %d, expected %d\n", mipmaps, 0); + mipmaps = 1; + hr = D3DXCheckTextureRequirements(device, NULL, NULL, &mipmaps, D3DUSAGE_AUTOGENMIPMAP, NULL, D3DPOOL_DEFAULT); + ok(hr == D3D_OK, "D3DXCheckTextureRequirements returned %#x, expected %#x\n", hr, D3D_OK); + ok(mipmaps == 1, "Returned mipmaps %d, expected %d\n", mipmaps, 1); + mipmaps = 2; + hr = D3DXCheckTextureRequirements(device, NULL, NULL, &mipmaps, D3DUSAGE_AUTOGENMIPMAP, NULL, D3DPOOL_DEFAULT); + ok(hr == D3D_OK, "D3DXCheckTextureRequirements returned %#x, expected %#x\n", hr, D3D_OK); + ok(mipmaps == 0, "Returned mipmaps %d, expected %d\n", mipmaps, 0); + mipmaps = 6; + hr = D3DXCheckTextureRequirements(device, NULL, NULL, &mipmaps, D3DUSAGE_AUTOGENMIPMAP, NULL, D3DPOOL_DEFAULT); + ok(hr == D3D_OK, "D3DXCheckTextureRequirements returned %#x, expected %#x\n", hr, D3D_OK); + ok(mipmaps == 0, "Returned mipmaps %d, expected %d\n", mipmaps, 0); + } + else + skip("No D3DUSAGE_AUTOGENMIPMAP support for textures\n"); + + /* usage */ + hr = D3DXCheckTextureRequirements(device, NULL, NULL, NULL, D3DUSAGE_WRITEONLY, NULL, D3DPOOL_DEFAULT); + ok(hr == D3DERR_INVALIDCALL, "D3DXCheckTextureRequirements succeeded, but should've failed.\n"); + hr = D3DXCheckTextureRequirements(device, NULL, NULL, NULL, D3DUSAGE_DONOTCLIP, NULL, D3DPOOL_DEFAULT); + ok(hr == D3DERR_INVALIDCALL, "D3DXCheckTextureRequirements succeeded, but should've failed.\n"); + hr = D3DXCheckTextureRequirements(device, NULL, NULL, NULL, D3DUSAGE_POINTS, NULL, D3DPOOL_DEFAULT); + ok(hr == D3DERR_INVALIDCALL, "D3DXCheckTextureRequirements succeeded, but should've failed.\n"); + hr = D3DXCheckTextureRequirements(device, NULL, NULL, NULL, D3DUSAGE_RTPATCHES, NULL, D3DPOOL_DEFAULT); + ok(hr == D3DERR_INVALIDCALL, "D3DXCheckTextureRequirements succeeded, but should've failed.\n"); + hr = D3DXCheckTextureRequirements(device, NULL, NULL, NULL, D3DUSAGE_NPATCHES, NULL, D3DPOOL_DEFAULT); + ok(hr == D3DERR_INVALIDCALL, "D3DXCheckTextureRequirements succeeded, but should've failed.\n"); + + /* format */ + hr = D3DXCheckTextureRequirements(device, NULL, NULL, NULL, 0, NULL, D3DPOOL_DEFAULT); + ok(hr == D3D_OK, "D3DXCheckTextureRequirements returned %#x, expected %#x\n", hr, D3D_OK); + + format = D3DFMT_UNKNOWN; + hr = D3DXCheckTextureRequirements(device, NULL, NULL, NULL, 0, &format, D3DPOOL_DEFAULT); + ok(hr == D3D_OK, "D3DXCheckTextureRequirements returned %#x, expected %#x\n", hr, D3D_OK); + ok(format == D3DFMT_A8R8G8B8, "Returned format %u, expected %u\n", format, D3DFMT_A8R8G8B8); + + format = D3DX_DEFAULT; + hr = D3DXCheckTextureRequirements(device, NULL, NULL, NULL, 0, &format, D3DPOOL_DEFAULT); + ok(hr == D3D_OK, "D3DXCheckTextureRequirements returned %#x, expected %#x\n", hr, D3D_OK); + ok(format == D3DFMT_A8R8G8B8, "Returned format %u, expected %u\n", format, D3DFMT_A8R8G8B8); + + format = D3DFMT_R8G8B8; + hr = D3DXCheckTextureRequirements(device, NULL, NULL, NULL, 0, &format, D3DPOOL_DEFAULT); + ok(hr == D3D_OK, "D3DXCheckTextureRequirements returned %#x, expected %#x\n", hr, D3D_OK); + ok(format == D3DFMT_X8R8G8B8, "Returned format %u, expected %u\n", format, D3DFMT_X8R8G8B8); + + IDirect3DDevice9_GetDirect3D(device, &d3d); + IDirect3DDevice9_GetCreationParameters(device, ¶ms); + IDirect3DDevice9_GetDisplayMode(device, 0, &mode); + + if (SUCCEEDED(IDirect3D9_CheckDeviceFormat(d3d, params.AdapterOrdinal, params.DeviceType, + mode.Format, 0, D3DRTYPE_TEXTURE, D3DFMT_R3G3B2))) + expected = D3DFMT_R3G3B2; + else if (SUCCEEDED(IDirect3D9_CheckDeviceFormat(d3d, params.AdapterOrdinal, params.DeviceType, + mode.Format, 0, D3DRTYPE_TEXTURE, D3DFMT_X4R4G4B4))) + expected = D3DFMT_X4R4G4B4; + else if (SUCCEEDED(IDirect3D9_CheckDeviceFormat(d3d, params.AdapterOrdinal, params.DeviceType, + mode.Format, 0, D3DRTYPE_TEXTURE, D3DFMT_X1R5G5B5))) + expected = D3DFMT_X1R5G5B5; + else + expected = D3DFMT_R5G6B5; + + format = D3DFMT_R3G3B2; + hr = D3DXCheckTextureRequirements(device, NULL, NULL, NULL, 0, &format, D3DPOOL_DEFAULT); + ok(hr == D3D_OK, "D3DXCheckTextureRequirements returned %#x, expected %#x\n", hr, D3D_OK); + ok(format == expected, "Returned format %u, expected %u\n", format, expected); + + if(SUCCEEDED(IDirect3D9_CheckDeviceFormat(d3d, params.AdapterOrdinal, params.DeviceType, + mode.Format, 0, D3DRTYPE_TEXTURE, D3DFMT_A8R3G3B2))) + expected = D3DFMT_A8R3G3B2; + else + expected = D3DFMT_A8R8G8B8; + + format = D3DFMT_A8R3G3B2; + hr = D3DXCheckTextureRequirements(device, NULL, NULL, NULL, 0, &format, D3DPOOL_DEFAULT); + ok(hr == D3D_OK, "D3DXCheckTextureRequirements returned %#x, expected %#x\n", hr, D3D_OK); + ok(format == expected, "Returned format %u, expected %u\n", format, expected); + + if(SUCCEEDED(IDirect3D9_CheckDeviceFormat(d3d, params.AdapterOrdinal, params.DeviceType, + mode.Format, 0, D3DRTYPE_TEXTURE, D3DFMT_P8))) + expected = D3DFMT_P8; + else + expected = D3DFMT_A8R8G8B8; + + format = D3DFMT_P8; + hr = D3DXCheckTextureRequirements(device, NULL, NULL, NULL, 0, &format, D3DPOOL_DEFAULT); + ok(hr == D3D_OK, "D3DXCheckTextureRequirements returned %#x, expected %#x\n", hr, D3D_OK); + ok(format == expected, "Returned format %u, expected %u\n", format, expected); + + if(SUCCEEDED(IDirect3D9_CheckDeviceFormat(d3d, params.AdapterOrdinal, params.DeviceType, + mode.Format, D3DUSAGE_RENDERTARGET, D3DRTYPE_TEXTURE, D3DFMT_L8))) + expected = D3DFMT_L8; + else + expected = D3DFMT_X8R8G8B8; + + format = D3DFMT_L8; + hr = D3DXCheckTextureRequirements(device, NULL, NULL, NULL, D3DUSAGE_RENDERTARGET, &format, D3DPOOL_DEFAULT); + ok(hr == D3D_OK, "D3DXCheckTextureRequirements returned %#x, expected %#x\n", hr, D3D_OK); + ok(format == expected, "Returned format %u, expected %u\n", format, expected); + + if(SUCCEEDED(IDirect3D9_CheckDeviceFormat(d3d, params.AdapterOrdinal, params.DeviceType, + mode.Format, D3DUSAGE_RENDERTARGET, D3DRTYPE_TEXTURE, D3DFMT_L16))) + expected = D3DFMT_L16; + else + expected = D3DFMT_A16B16G16R16; + + format = D3DFMT_L16; + hr = D3DXCheckTextureRequirements(device, NULL, NULL, NULL, D3DUSAGE_RENDERTARGET, &format, D3DPOOL_DEFAULT); + ok(hr == D3D_OK, "D3DXCheckTextureRequirements returned %#x, expected %#x\n", hr, D3D_OK); + ok(format == expected, "Returned format %u, expected %u\n", format, expected); + + /* Block-based texture formats and size < block size. */ + if (has_2d_dxt5) + { + format = D3DFMT_DXT5; + width = 2; height = 2; + mipmaps = 1; + hr = D3DXCheckTextureRequirements(device, &width, &height, &mipmaps, 0, &format, D3DPOOL_DEFAULT); + ok(hr == D3D_OK, "D3DXCheckTextureRequirements returned %#x, expected %#x\n", hr, D3D_OK); + ok(width == 4, "Returned width %d, expected %d\n", width, 4); + ok(height == 4, "Returned height %d, expected %d\n", height, 4); + ok(mipmaps == 1, "Returned mipmaps %d, expected %d\n", mipmaps, 1); + ok(format == D3DFMT_DXT5, "Returned format %u, expected %u\n", format, D3DFMT_DXT5); + } + else + { + skip("D3DFMT_DXT5 textures are not supported, skipping a test.\n"); + } + + IDirect3D9_Release(d3d); +} + +static void test_D3DXCheckCubeTextureRequirements(IDirect3DDevice9 *device) +{ + UINT size, mipmaps, expected; + D3DFORMAT format; + D3DCAPS9 caps; + HRESULT hr; + + IDirect3DDevice9_GetDeviceCaps(device, &caps); + + if (!(caps.TextureCaps & D3DPTEXTURECAPS_CUBEMAP)) + { + skip("No cube textures support\n"); + return; + } + + /* general tests */ + hr = D3DXCheckCubeTextureRequirements(device, NULL, NULL, 0, NULL, D3DPOOL_DEFAULT); + ok(hr == D3D_OK, "D3DXCheckCubeTextureRequirements returned %#x, expected %#x\n", hr, D3D_OK); + + hr = D3DXCheckCubeTextureRequirements(device, NULL, NULL, D3DX_DEFAULT, NULL, D3DPOOL_DEFAULT); + ok(hr == D3D_OK, "D3DXCheckCubeTextureRequirements returned %#x, expected %#x\n", hr, D3D_OK); + + hr = D3DXCheckCubeTextureRequirements(NULL, NULL, NULL, D3DX_DEFAULT, NULL, D3DPOOL_DEFAULT); + ok(hr == D3DERR_INVALIDCALL, "D3DXCheckCubeTextureRequirements returned %#x, expected %#x\n", hr, D3DERR_INVALIDCALL); + + /* size */ + size = D3DX_DEFAULT; + hr = D3DXCheckCubeTextureRequirements(device, &size, NULL, 0, NULL, D3DPOOL_DEFAULT); + ok(hr == D3D_OK, "D3DXCheckCubeTextureRequirements returned %#x, expected %#x\n", hr, D3D_OK); + ok(size == 256, "Returned size %d, expected %d\n", size, 256); + + /* mipmaps */ + size = 64; + mipmaps = 9; + hr = D3DXCheckCubeTextureRequirements(device, &size, &mipmaps, 0, NULL, D3DPOOL_DEFAULT); + ok(hr == D3D_OK, "D3DXCheckCubeTextureRequirements returned %#x, expected %#x\n", hr, D3D_OK); + ok(mipmaps == 7, "Returned mipmaps %d, expected %d\n", mipmaps, 7); + + size = 284; + mipmaps = 20; + expected = caps.TextureCaps & D3DPTEXTURECAPS_CUBEMAP_POW2 ? 10 : 9; + expected = caps.TextureCaps & D3DPTEXTURECAPS_MIPCUBEMAP ? expected : 1; + hr = D3DXCheckCubeTextureRequirements(device, &size, &mipmaps, 0, NULL, D3DPOOL_DEFAULT); + ok(hr == D3D_OK, "D3DXCheckCubeTextureRequirements returned %#x, expected %#x\n", hr, D3D_OK); + ok(mipmaps == expected, "Returned mipmaps %d, expected %d\n", mipmaps, expected); + + size = 63; + mipmaps = 9; + expected = caps.TextureCaps & D3DPTEXTURECAPS_CUBEMAP_POW2 ? 7 : 6; + expected = caps.TextureCaps & D3DPTEXTURECAPS_MIPCUBEMAP ? expected : 1; + hr = D3DXCheckCubeTextureRequirements(device, &size, &mipmaps, 0, NULL, D3DPOOL_DEFAULT); + ok(hr == D3D_OK, "D3DXCheckCubeTextureRequirements returned %#x, expected %#x\n", hr, D3D_OK); + ok(mipmaps == expected, "Returned mipmaps %d, expected %d\n", mipmaps, expected); + + mipmaps = 0; + hr = D3DXCheckCubeTextureRequirements(device, NULL, &mipmaps, 0, NULL, D3DPOOL_DEFAULT); + ok(hr == D3D_OK, "D3DXCheckCubeTextureRequirements returned %#x, expected %#x\n", hr, D3D_OK); + ok(mipmaps == 9, "Returned mipmaps %d, expected %d\n", mipmaps, 9); + + if (is_autogenmipmap_supported(device, D3DRTYPE_CUBETEXTURE)) + { + mipmaps = 3; + hr = D3DXCheckCubeTextureRequirements(device, NULL, &mipmaps, D3DUSAGE_AUTOGENMIPMAP, NULL, D3DPOOL_DEFAULT); + ok(hr == D3D_OK, "D3DXCheckCubeTextureRequirements returned %#x, expected %#x\n", hr, D3D_OK); + ok(mipmaps == 0, "Returned mipmaps %d, expected %d\n", mipmaps, 0); + } + else + skip("No D3DUSAGE_AUTOGENMIPMAP support for cube textures\n"); + + /* usage */ + hr = D3DXCheckCubeTextureRequirements(device, NULL, NULL, D3DUSAGE_WRITEONLY, NULL, D3DPOOL_DEFAULT); + ok(hr == D3DERR_INVALIDCALL, "D3DXCheckCubeTextureRequirements succeeded, but should've failed.\n"); + hr = D3DXCheckCubeTextureRequirements(device, NULL, NULL, D3DUSAGE_DONOTCLIP, NULL, D3DPOOL_DEFAULT); + ok(hr == D3DERR_INVALIDCALL, "D3DXCheckCubeTextureRequirements succeeded, but should've failed.\n"); + hr = D3DXCheckCubeTextureRequirements(device, NULL, NULL, D3DUSAGE_POINTS, NULL, D3DPOOL_DEFAULT); + ok(hr == D3DERR_INVALIDCALL, "D3DXCheckCubeTextureRequirements succeeded, but should've failed.\n"); + hr = D3DXCheckCubeTextureRequirements(device, NULL, NULL, D3DUSAGE_RTPATCHES, NULL, D3DPOOL_DEFAULT); + ok(hr == D3DERR_INVALIDCALL, "D3DXCheckCubeTextureRequirements succeeded, but should've failed.\n"); + hr = D3DXCheckCubeTextureRequirements(device, NULL, NULL, D3DUSAGE_NPATCHES, NULL, D3DPOOL_DEFAULT); + ok(hr == D3DERR_INVALIDCALL, "D3DXCheckCubeTextureRequirements succeeded, but should've failed.\n"); + + /* format */ + hr = D3DXCheckCubeTextureRequirements(device, NULL, NULL, 0, NULL, D3DPOOL_DEFAULT); + ok(hr == D3D_OK, "D3DXCheckCubeTextureRequirements returned %#x, expected %#x\n", hr, D3D_OK); + + format = D3DFMT_UNKNOWN; + hr = D3DXCheckCubeTextureRequirements(device, NULL, NULL, 0, &format, D3DPOOL_DEFAULT); + ok(hr == D3D_OK, "D3DXCheckCubeTextureRequirements returned %#x, expected %#x\n", hr, D3D_OK); + ok(format == D3DFMT_A8R8G8B8, "Returned format %u, expected %u\n", format, D3DFMT_A8R8G8B8); + + format = D3DX_DEFAULT; + hr = D3DXCheckCubeTextureRequirements(device, NULL, NULL, 0, &format, D3DPOOL_DEFAULT); + ok(hr == D3D_OK, "D3DXCheckCubeTextureRequirements returned %#x, expected %#x\n", hr, D3D_OK); + ok(format == D3DFMT_A8R8G8B8, "Returned format %u, expected %u\n", format, D3DFMT_A8R8G8B8); + + format = D3DFMT_R8G8B8; + hr = D3DXCheckCubeTextureRequirements(device, NULL, NULL, 0, &format, D3DPOOL_DEFAULT); + ok(hr == D3D_OK, "D3DXCheckCubeTextureRequirements returned %#x, expected %#x\n", hr, D3D_OK); + ok(format == D3DFMT_X8R8G8B8, "Returned format %u, expected %u\n", format, D3DFMT_X8R8G8B8); +} + +static void test_D3DXCheckVolumeTextureRequirements(IDirect3DDevice9 *device) +{ + UINT width, height, depth, mipmaps, expected; + D3DFORMAT format; + D3DCAPS9 caps; + HRESULT hr; + + IDirect3DDevice9_GetDeviceCaps(device, &caps); + + if (!(caps.TextureCaps & D3DPTEXTURECAPS_VOLUMEMAP) || (caps.MaxVolumeExtent < 256)) + { + skip("Limited or no volume textures support.\n"); + return; + } + + /* general tests */ + hr = D3DXCheckVolumeTextureRequirements(device, NULL, NULL, NULL, NULL, 0, NULL, D3DPOOL_DEFAULT); + ok(hr == D3D_OK, "D3DXCheckVolumeTextureRequirements returned %#x, expected %#x\n", hr, D3D_OK); + + hr = D3DXCheckVolumeTextureRequirements(device, NULL, NULL, NULL, NULL, D3DX_DEFAULT, NULL, D3DPOOL_DEFAULT); + ok(hr == D3D_OK, "D3DXCheckVolumeTextureRequirements returned %#x, expected %#x\n", hr, D3D_OK); + + hr = D3DXCheckVolumeTextureRequirements(NULL, NULL, NULL, NULL, NULL, D3DX_DEFAULT, NULL, D3DPOOL_DEFAULT); + ok(hr == D3DERR_INVALIDCALL, "D3DXCheckVolumeTextureRequirements returned %#x, expected %#x\n", hr, D3DERR_INVALIDCALL); + + /* width, height, depth */ + width = height = depth = D3DX_DEFAULT; + hr = D3DXCheckVolumeTextureRequirements(device, &width, &height, &depth, NULL, 0, NULL, D3DPOOL_DEFAULT); + ok(hr == D3D_OK, "D3DXCheckVolumeTextureRequirements returned %#x, expected %#x\n", hr, D3D_OK); + ok(width == 256, "Returned width %d, expected %d\n", width, 256); + ok(height == 256, "Returned height %d, expected %d\n", height, 256); + ok(depth == 1, "Returned depth %d, expected %d\n", depth, 1); + + width = D3DX_DEFAULT; + hr = D3DXCheckVolumeTextureRequirements(device, &width, NULL, NULL, NULL, 0, NULL, D3DPOOL_DEFAULT); + ok(hr == D3D_OK, "D3DXCheckVolumeTextureRequirements returned %#x, expected %#x\n", hr, D3D_OK); + ok(width == 256, "Returned width %d, expected %d\n", width, 256); + + width = D3DX_DEFAULT; height = 0; depth = 0; + hr = D3DXCheckVolumeTextureRequirements(device, &width, &height, &depth, NULL, 0, NULL, D3DPOOL_DEFAULT); + ok(hr == D3D_OK, "D3DXCheckVolumeTextureRequirements returned %#x, expected %#x\n", hr, D3D_OK); + ok(width == 1, "Returned width %d, expected %d\n", width, 1); + ok(height == 1, "Returned height %d, expected %d\n", height, 1); + ok(depth == 1, "Returned height %d, expected %d\n", depth, 1); + + width = 0; height = 0; depth = 0; + hr = D3DXCheckVolumeTextureRequirements(device, &width, &height, &depth, NULL, 0, NULL, D3DPOOL_DEFAULT); + ok(hr == D3D_OK, "D3DXCheckVolumeTextureRequirements returned %#x, expected %#x\n", hr, D3D_OK); + ok(width == 1, "Returned width %d, expected %d\n", width, 1); + ok(height == 1, "Returned height %d, expected %d\n", height, 1); + ok(depth == 1, "Returned height %d, expected %d\n", depth, 1); + + width = 0; + hr = D3DXCheckVolumeTextureRequirements(device, &width, NULL, NULL, NULL, 0, NULL, D3DPOOL_DEFAULT); + ok(hr == D3D_OK, "D3DXCheckVolumeTextureRequirements returned %#x, expected %#x\n", hr, D3D_OK); + ok(width == 1, "Returned width %d, expected %d\n", width, 1); + + width = 0xFFFFFFFE; + hr = D3DXCheckVolumeTextureRequirements(device, &width, NULL, NULL, NULL, 0, NULL, D3DPOOL_DEFAULT); + ok(hr == D3D_OK, "D3DXCheckVolumeTextureRequirements returned %#x, expected %#x\n", hr, D3D_OK); + ok(width == caps.MaxVolumeExtent, "Returned width %d, expected %d\n", width, caps.MaxVolumeExtent); + + /* format */ + hr = D3DXCheckVolumeTextureRequirements(device, NULL, NULL, NULL, NULL, 0, NULL, D3DPOOL_DEFAULT); + ok(hr == D3D_OK, "D3DXCheckVolumeTextureRequirements returned %#x, expected %#x\n", hr, D3D_OK); + + format = D3DFMT_UNKNOWN; + hr = D3DXCheckVolumeTextureRequirements(device, NULL, NULL, NULL, NULL, 0, &format, D3DPOOL_DEFAULT); + ok(hr == D3D_OK, "D3DXCheckVolumeTextureRequirements returned %#x, expected %#x\n", hr, D3D_OK); + ok(format == D3DFMT_A8R8G8B8, "Returned format %u, expected %u\n", format, D3DFMT_A8R8G8B8); + + format = D3DX_DEFAULT; + hr = D3DXCheckVolumeTextureRequirements(device, NULL, NULL, NULL, NULL, 0, &format, D3DPOOL_DEFAULT); + ok(hr == D3D_OK, "D3DXCheckVolumeTextureRequirements returned %#x, expected %#x\n", hr, D3D_OK); + ok(format == D3DFMT_A8R8G8B8, "Returned format %u, expected %u\n", format, D3DFMT_A8R8G8B8); + + format = D3DFMT_R8G8B8; + hr = D3DXCheckVolumeTextureRequirements(device, NULL, NULL, NULL, NULL, 0, &format, D3DPOOL_DEFAULT); + ok(hr == D3D_OK, "D3DXCheckVolumeTextureRequirements returned %#x, expected %#x\n", hr, D3D_OK); + ok(format == D3DFMT_X8R8G8B8, "Returned format %u, expected %u\n", format, D3DFMT_X8R8G8B8); + + format = D3DFMT_DXT3; + hr = D3DXCheckVolumeTextureRequirements(device, NULL, NULL, NULL, NULL, 0, &format, D3DPOOL_DEFAULT); + ok(hr == D3D_OK, "D3DXCheckVolumeTextureRequirements returned %#x, expected %#x\n", hr, D3D_OK); + if (has_3d_dxt3) + ok(format == D3DFMT_DXT3, "Returned format %u, expected %u\n", format, D3DFMT_DXT3); + else + todo_wine ok(format == D3DFMT_A8R8G8B8, "Returned format %u, expected %u\n", format, D3DFMT_A8R8G8B8); + + /* mipmaps */ + if (!(caps.TextureCaps & D3DPTEXTURECAPS_MIPVOLUMEMAP)) + { + skip("No volume textures mipmapping support\n"); + return; + } + + width = height = depth = 64; + mipmaps = 9; + hr = D3DXCheckVolumeTextureRequirements(device, &width, &height, &depth, &mipmaps, 0, NULL, D3DPOOL_DEFAULT); + ok(hr == D3D_OK, "D3DXCheckVolumeTextureRequirements returned %#x, expected %#x\n", hr, D3D_OK); + ok(mipmaps == 7, "Returned mipmaps %d, expected %d\n", mipmaps, 7); + + width = 284; + height = 143; + depth = 55; + mipmaps = 20; + expected = (caps.TextureCaps & D3DPTEXTURECAPS_VOLUMEMAP_POW2 && caps.MaxVolumeExtent >= 512) ? 10 : 9; + hr = D3DXCheckVolumeTextureRequirements(device, &width, &height, &depth, &mipmaps, 0, NULL, D3DPOOL_DEFAULT); + ok(hr == D3D_OK, "D3DXCheckVolumeTextureRequirements returned %#x, expected %#x\n", hr, D3D_OK); + ok(mipmaps == expected, "Returned mipmaps %d, expected %d\n", mipmaps, expected); + + mipmaps = 0; + hr = D3DXCheckVolumeTextureRequirements(device, NULL, NULL, NULL, &mipmaps, 0, NULL, D3DPOOL_DEFAULT); + ok(hr == D3D_OK, "D3DXCheckVolumeTextureRequirements returned %#x, expected %#x\n", hr, D3D_OK); + ok(mipmaps == 9, "Returned mipmaps %d, expected %d\n", mipmaps, 9); + + /* D3DUSAGE_AUTOGENMIPMAP is never supported for volume textures. */ + ok(!is_autogenmipmap_supported(device, D3DRTYPE_VOLUMETEXTURE), + "D3DUSAGE_AUTOGENMIPMAP is unexpectedly supported on volume textures.\n"); +} + +static void test_D3DXCreateTexture(IDirect3DDevice9 *device) +{ + IDirect3DTexture9 *texture; + D3DSURFACE_DESC desc; + D3DCAPS9 caps; + UINT mipmaps; + HRESULT hr; + + IDirect3DDevice9_GetDeviceCaps(device, &caps); + + hr = D3DXCreateTexture(NULL, 0, 0, 0, 0, D3DX_DEFAULT, D3DPOOL_DEFAULT, NULL); + ok(hr == D3DERR_INVALIDCALL, "D3DXCreateTexture returned %#x, expected %#x\n", hr, D3DERR_INVALIDCALL); + + /* width and height tests */ + + hr = D3DXCreateTexture(device, D3DX_DEFAULT, D3DX_DEFAULT, D3DX_DEFAULT, 0, 0, D3DPOOL_DEFAULT, &texture); + ok(hr == D3D_OK, "D3DXCreateTexture returned %#x, expected %#x\n", hr, D3D_OK); + + if (texture) + { + hr = IDirect3DTexture9_GetLevelDesc(texture, 0, &desc); + ok(hr == D3D_OK, "GetLevelDesc returned %#x, expected %#x\n", hr, D3D_OK); + ok(desc.Format == D3DFMT_A8R8G8B8, "Returned format %u, expected %u\n", desc.Format, D3DFMT_A8R8G8B8); + + ok(desc.Width == 256, "Returned width %d, expected %d\n", desc.Width, 256); + ok(desc.Height == 256, "Returned height %d, expected %d\n", desc.Height, 256); + + IDirect3DTexture9_Release(texture); + } + + + hr = D3DXCreateTexture(device, 0, 0, 0, 0, 0, D3DPOOL_DEFAULT, &texture); + ok(hr == D3D_OK, "D3DXCreateTexture returned %#x, expected %#x\n", hr, D3D_OK); + + if (texture) + { + hr = IDirect3DTexture9_GetLevelDesc(texture, 0, &desc); + ok(hr == D3D_OK, "GetLevelDesc returned %#x, expected %#x\n", hr, D3D_OK); + ok(desc.Format == D3DFMT_A8R8G8B8, "Returned format %u, expected %u\n", desc.Format, D3DFMT_A8R8G8B8); + + ok(desc.Width == 1, "Returned width %d, expected %d\n", desc.Width, 1); + ok(desc.Height == 1, "Returned height %d, expected %d\n", desc.Height, 1); + + IDirect3DTexture9_Release(texture); + } + + + if (caps.TextureCaps & D3DPTEXTURECAPS_POW2) + skip("Hardware only supports pow2 textures\n"); + else + { + hr = D3DXCreateTexture(device, D3DX_DEFAULT, 63, 0, 0, 0, D3DPOOL_DEFAULT, &texture); + ok((hr == D3D_OK) || + /* may not work with conditional NPOT */ + ((hr != D3D_OK) && (caps.TextureCaps & D3DPTEXTURECAPS_NONPOW2CONDITIONAL)), + "D3DXCreateTexture returned %#x, expected %#x\n", hr, D3D_OK); + + if (texture) + { + hr = IDirect3DTexture9_GetLevelDesc(texture, 0, &desc); + ok(hr == D3D_OK, "GetLevelDesc returned %#x, expected %#x\n", hr, D3D_OK); + ok(desc.Format == D3DFMT_A8R8G8B8, "Returned format %u, expected %u\n", desc.Format, D3DFMT_A8R8G8B8); + + /* Conditional NPOT may create a texture with different dimensions, so allow those + situations instead of returning a fail */ + + ok(desc.Width == 63 || + (caps.TextureCaps & D3DPTEXTURECAPS_NONPOW2CONDITIONAL), + "Returned width %d, expected %d\n", desc.Width, 63); + + ok(desc.Height == 63 || + (caps.TextureCaps & D3DPTEXTURECAPS_NONPOW2CONDITIONAL), + "Returned height %d, expected %d\n", desc.Height, 63); + + IDirect3DTexture9_Release(texture); + } + } + + /* mipmaps */ + + hr = D3DXCreateTexture(device, 64, 63, 9, 0, 0, D3DPOOL_DEFAULT, &texture); + ok(hr == D3D_OK, "D3DXCreateTexture returned %#x, expected %#x\n", hr, D3D_OK); + + if (texture) + { + mipmaps = IDirect3DTexture9_GetLevelCount(texture); + ok(mipmaps == 7, "Returned mipmaps %d, expected %d\n", mipmaps, 7); + + IDirect3DTexture9_Release(texture); + } + + + hr = D3DXCreateTexture(device, 284, 137, 9, 0, 0, D3DPOOL_DEFAULT, &texture); + ok(hr == D3D_OK, "D3DXCreateTexture returned %#x, expected %#x\n", hr, D3D_OK); + + if (texture) + { + mipmaps = IDirect3DTexture9_GetLevelCount(texture); + ok(mipmaps == 9, "Returned mipmaps %d, expected %d\n", mipmaps, 9); + + IDirect3DTexture9_Release(texture); + } + + + hr = D3DXCreateTexture(device, 0, 0, 20, 0, 0, D3DPOOL_DEFAULT, &texture); + ok(hr == D3D_OK, "D3DXCreateTexture returned %#x, expected %#x\n", hr, D3D_OK); + + if (texture) + { + mipmaps = IDirect3DTexture9_GetLevelCount(texture); + ok(mipmaps == 1, "Returned mipmaps %d, expected %d\n", mipmaps, 1); + + IDirect3DTexture9_Release(texture); + } + + + hr = D3DXCreateTexture(device, 64, 64, 1, 0, 0, D3DPOOL_DEFAULT, &texture); + ok(hr == D3D_OK, "D3DXCreateTexture returned %#x, expected %#x\n", hr, D3D_OK); + + if (texture) + { + mipmaps = IDirect3DTexture9_GetLevelCount(texture); + ok(mipmaps == 1, "Returned mipmaps %d, expected %d\n", mipmaps, 1); + + IDirect3DTexture9_Release(texture); + } + + /* usage */ + + hr = D3DXCreateTexture(device, 0, 0, 0, D3DUSAGE_WRITEONLY, 0, D3DPOOL_DEFAULT, &texture); + ok(hr == D3DERR_INVALIDCALL, "D3DXCreateTexture succeeded, but should have failed.\n"); + hr = D3DXCreateTexture(device, 0, 0, 0, D3DUSAGE_DONOTCLIP, 0, D3DPOOL_DEFAULT, &texture); + ok(hr == D3DERR_INVALIDCALL, "D3DXCreateTexture succeeded, but should have failed.\n"); + hr = D3DXCreateTexture(device, 0, 0, 0, D3DUSAGE_POINTS, 0, D3DPOOL_DEFAULT, &texture); + ok(hr == D3DERR_INVALIDCALL, "D3DXCreateTexture succeeded, but should have failed.\n"); + hr = D3DXCreateTexture(device, 0, 0, 0, D3DUSAGE_RTPATCHES, 0, D3DPOOL_DEFAULT, &texture); + ok(hr == D3DERR_INVALIDCALL, "D3DXCreateTexture succeeded, but should have failed.\n"); + hr = D3DXCreateTexture(device, 0, 0, 0, D3DUSAGE_NPATCHES, 0, D3DPOOL_DEFAULT, &texture); + ok(hr == D3DERR_INVALIDCALL, "D3DXCreateTexture succeeded, but should have failed.\n"); + + /* format */ + + hr = D3DXCreateTexture(device, 0, 0, 0, 0, D3DFMT_UNKNOWN, D3DPOOL_DEFAULT, &texture); + ok(hr == D3D_OK, "D3DXCreateTexture returned %#x, expected %#x\n", hr, D3D_OK); + + if (texture) + { + hr = IDirect3DTexture9_GetLevelDesc(texture, 0, &desc); + ok(hr == D3D_OK, "GetLevelDesc returned %#x, expected %#x\n", hr, D3D_OK); + ok(desc.Format == D3DFMT_A8R8G8B8, "Returned format %u, expected %u\n", desc.Format, D3DFMT_A8R8G8B8); + + IDirect3DTexture9_Release(texture); + } + + + hr = D3DXCreateTexture(device, 0, 0, 0, 0, 0, D3DPOOL_DEFAULT, &texture); + ok(hr == D3D_OK, "D3DXCreateTexture returned %#x, expected %#x\n", hr, D3D_OK); + + if (texture) + { + hr = IDirect3DTexture9_GetLevelDesc(texture, 0, &desc); + ok(hr == D3D_OK, "GetLevelDesc returned %#x, expected %#x\n", hr, D3D_OK); + ok(desc.Format == D3DFMT_A8R8G8B8, "Returned format %u, expected %u\n", desc.Format, D3DFMT_A8R8G8B8); + + IDirect3DTexture9_Release(texture); + } + + /* D3DXCreateTextureFromResource */ + hr = D3DXCreateTextureFromResourceA(device, NULL, MAKEINTRESOURCEA(IDB_BITMAP_1x1), &texture); + ok(hr == D3D_OK, "D3DXCreateTextureFromResource returned %#x, expected %#x\n", hr, D3D_OK); + if (SUCCEEDED(hr)) IDirect3DTexture9_Release(texture); + + hr = D3DXCreateTextureFromResourceA(device, NULL, MAKEINTRESOURCEA(IDD_BITMAPDATA_1x1), &texture); + ok(hr == D3D_OK, "D3DXCreateTextureFromResource returned %#x, expected %#x\n", hr, D3D_OK); + if (SUCCEEDED(hr)) IDirect3DTexture9_Release(texture); + + hr = D3DXCreateTextureFromResourceA(device, NULL, MAKEINTRESOURCEA(IDS_STRING), &texture); + ok(hr == D3DXERR_INVALIDDATA, "D3DXCreateTextureFromResource returned %#x, expected %#x\n", hr, D3DXERR_INVALIDDATA); + + hr = D3DXCreateTextureFromResourceA(NULL, NULL, MAKEINTRESOURCEA(IDD_BITMAPDATA_1x1), &texture); + ok(hr == D3DERR_INVALIDCALL, "D3DXCreateTextureFromResource returned %#x, expected %#x\n", hr, D3DERR_INVALIDCALL); + + hr = D3DXCreateTextureFromResourceA(device, NULL, NULL, &texture); + ok(hr == D3DXERR_INVALIDDATA, "D3DXCreateTextureFromResource returned %#x, expected %#x\n", hr, D3DXERR_INVALIDDATA); + + hr = D3DXCreateTextureFromResourceA(device, NULL, MAKEINTRESOURCEA(IDD_BITMAPDATA_1x1), NULL); + ok(hr == D3DERR_INVALIDCALL, "D3DXCreateTextureFromResource returned %#x, expected %#x\n", hr, D3DERR_INVALIDCALL); + + + /* D3DXCreateTextureFromResourceEx */ + hr = D3DXCreateTextureFromResourceExA(device, NULL, MAKEINTRESOURCEA(IDD_BITMAPDATA_1x1), D3DX_DEFAULT, D3DX_DEFAULT, D3DX_DEFAULT, 0, D3DFMT_UNKNOWN, D3DPOOL_MANAGED, D3DX_DEFAULT, D3DX_DEFAULT, 0, NULL, NULL, &texture); + ok(hr == D3D_OK, "D3DXCreateTextureFromResourceEx returned %#x, expected %#x\n", hr, D3D_OK); + if (SUCCEEDED(hr)) IDirect3DTexture9_Release(texture); + + hr = D3DXCreateTextureFromResourceExA(device, NULL, MAKEINTRESOURCEA(IDS_STRING), D3DX_DEFAULT, D3DX_DEFAULT, D3DX_DEFAULT, 0, D3DFMT_UNKNOWN, D3DPOOL_MANAGED, D3DX_DEFAULT, D3DX_DEFAULT, 0, NULL, NULL, &texture); + ok(hr == D3DXERR_INVALIDDATA, "D3DXCreateTextureFromResourceEx returned %#x, expected %#x\n", hr, D3DXERR_INVALIDDATA); + + hr = D3DXCreateTextureFromResourceExA(NULL, NULL, MAKEINTRESOURCEA(IDD_BITMAPDATA_1x1), D3DX_DEFAULT, D3DX_DEFAULT, D3DX_DEFAULT, 0, D3DFMT_UNKNOWN, D3DPOOL_MANAGED, D3DX_DEFAULT, D3DX_DEFAULT, 0, NULL, NULL, &texture); + ok(hr == D3DERR_INVALIDCALL, "D3DXCreateTextureFromResourceEx returned %#x, expected %#x\n", hr, D3DERR_INVALIDCALL); + + hr = D3DXCreateTextureFromResourceExA(device, NULL, NULL, D3DX_DEFAULT, D3DX_DEFAULT, D3DX_DEFAULT, 0, D3DFMT_UNKNOWN, D3DPOOL_MANAGED, D3DX_DEFAULT, D3DX_DEFAULT, 0, NULL, NULL, &texture); + ok(hr == D3DXERR_INVALIDDATA, "D3DXCreateTextureFromResourceEx returned %#x, expected %#x\n", hr, D3DXERR_INVALIDDATA); + + hr = D3DXCreateTextureFromResourceExA(device, NULL, MAKEINTRESOURCEA(IDD_BITMAPDATA_1x1), D3DX_DEFAULT, D3DX_DEFAULT, D3DX_DEFAULT, 0, D3DFMT_UNKNOWN, D3DPOOL_MANAGED, D3DX_DEFAULT, D3DX_DEFAULT, 0, NULL, NULL, NULL); + ok(hr == D3DERR_INVALIDCALL, "D3DXCreateTextureFromResourceEx returned %#x, expected %#x\n", hr, D3DERR_INVALIDCALL); +} + +static void test_D3DXFilterTexture(IDirect3DDevice9 *device) +{ + IDirect3DTexture9 *tex; + IDirect3DCubeTexture9 *cubetex; + IDirect3DVolumeTexture9 *voltex; + HRESULT hr; + + hr = IDirect3DDevice9_CreateTexture(device, 256, 256, 5, 0, D3DFMT_A8R8G8B8, D3DPOOL_MANAGED, &tex, NULL); + + if (SUCCEEDED(hr)) + { + hr = D3DXFilterTexture((IDirect3DBaseTexture9*) tex, NULL, D3DX_DEFAULT, D3DX_FILTER_NONE); + ok(hr == D3D_OK, "D3DXFilterTexture returned %#x, expected %#x\n", hr, D3D_OK); + + hr = D3DXFilterTexture((IDirect3DBaseTexture9*) tex, NULL, 0, D3DX_FILTER_NONE); + ok(hr == D3D_OK, "D3DXFilterTexture returned %#x, expected %#x\n", hr, D3D_OK); + + hr = D3DXFilterTexture((IDirect3DBaseTexture9*) tex, NULL, 0, D3DX_FILTER_BOX + 1); /* Invalid filter */ + ok(hr == D3DERR_INVALIDCALL, "D3DXFilterTexture returned %#x, expected %#x\n", hr, D3DERR_INVALIDCALL); + + hr = D3DXFilterTexture((IDirect3DBaseTexture9*) tex, NULL, 5, D3DX_FILTER_NONE); /* Invalid miplevel */ + ok(hr == D3DERR_INVALIDCALL, "D3DXFilterTexture returned %#x, expected %#x\n", hr, D3DERR_INVALIDCALL); + + IDirect3DTexture9_Release(tex); + } + else + skip("Failed to create texture\n"); + + hr = D3DXFilterTexture(NULL, NULL, 0, D3DX_FILTER_NONE); + ok(hr == D3DERR_INVALIDCALL, "D3DXFilterTexture returned %#x, expected %#x\n", hr, D3DERR_INVALIDCALL); + + /* Test different pools */ + hr = IDirect3DDevice9_CreateTexture(device, 256, 256, 0, 0, D3DFMT_A8R8G8B8, D3DPOOL_SYSTEMMEM, &tex, NULL); + + if (SUCCEEDED(hr)) + { + hr = D3DXFilterTexture((IDirect3DBaseTexture9*) tex, NULL, 0, D3DX_FILTER_NONE); + ok(hr == D3D_OK, "D3DXFilterTexture returned %#x, expected %#x\n", hr, D3D_OK); + IDirect3DTexture9_Release(tex); + } + else + skip("Failed to create texture\n"); + + hr = IDirect3DDevice9_CreateTexture(device, 256, 256, 0, 0, D3DFMT_A8R8G8B8, D3DPOOL_SCRATCH, &tex, NULL); + + if (SUCCEEDED(hr)) + { + hr = D3DXFilterTexture((IDirect3DBaseTexture9*) tex, NULL, 0, D3DX_FILTER_NONE); + ok(hr == D3D_OK, "D3DXFilterTexture returned %#x, expected %#x\n", hr, D3D_OK); + IDirect3DTexture9_Release(tex); + } + else + skip("Failed to create texture\n"); + + hr = IDirect3DDevice9_CreateTexture(device, 256, 256, 0, 0, D3DFMT_A8R8G8B8, D3DPOOL_DEFAULT, &tex, NULL); + if (SUCCEEDED(hr)) + { + hr = D3DXFilterTexture((IDirect3DBaseTexture9*) tex, NULL, 0, D3DX_FILTER_POINT); + ok(hr == D3D_OK, "D3DXFilterTexture returned %#x, expected %#x\n", hr, D3D_OK); + IDirect3DTexture9_Release(tex); + } + else + skip("Failed to create texture\n"); + + hr = IDirect3DDevice9_CreateTexture(device, 256, 256, 0, D3DUSAGE_DYNAMIC, D3DFMT_A8R8G8B8, D3DPOOL_DEFAULT, &tex, NULL); + if (SUCCEEDED(hr)) + { + hr = D3DXFilterTexture((IDirect3DBaseTexture9*) tex, NULL, 0, D3DX_FILTER_POINT); + ok(hr == D3D_OK, "D3DXFilterTexture returned %#x, expected %#x\n", hr, D3D_OK); + IDirect3DTexture9_Release(tex); + } + else + skip("Failed to create texture\n"); + + /* Cube texture test */ + hr = IDirect3DDevice9_CreateCubeTexture(device, 256, 5, 0, D3DFMT_A8R8G8B8, D3DPOOL_MANAGED, &cubetex, NULL); + + if (SUCCEEDED(hr)) + { + hr = D3DXFilterTexture((IDirect3DBaseTexture9*) cubetex, NULL, 0, D3DX_FILTER_NONE); + ok(hr == D3D_OK, "D3DXFilterTexture returned %#x, expected %#x\n", hr, D3D_OK); + + hr = D3DXFilterTexture((IDirect3DBaseTexture9*) cubetex, NULL, 0, D3DX_FILTER_BOX + 1); /* Invalid filter */ + ok(hr == D3DERR_INVALIDCALL, "D3DXFilterTexture returned %#x, expected %#x\n", hr, D3DERR_INVALIDCALL); + + hr = D3DXFilterTexture((IDirect3DBaseTexture9*) cubetex, NULL, 5, D3DX_FILTER_NONE); /* Invalid miplevel */ + ok(hr == D3DERR_INVALIDCALL, "D3DXFilterTexture returned %#x, expected %#x\n", hr, D3DERR_INVALIDCALL); + IDirect3DCubeTexture9_Release(cubetex); + } + else + skip("Failed to create texture\n"); + + /* Volume texture test */ + hr = IDirect3DDevice9_CreateVolumeTexture(device, 256, 256, 4, 0, 0, D3DFMT_A8R8G8B8, D3DPOOL_MANAGED, &voltex, NULL); + if (SUCCEEDED(hr)) + { + DWORD level_count = IDirect3DVolumeTexture9_GetLevelCount(voltex); + + hr = D3DXFilterTexture((IDirect3DBaseTexture9*) voltex, NULL, 0, D3DX_FILTER_NONE); + ok(hr == D3D_OK, "D3DXFilterTexture returned %#x, expected %#x\n", hr, D3D_OK); + + hr = D3DXFilterTexture((IDirect3DBaseTexture9*) voltex, NULL, 0, D3DX_DEFAULT); + ok(hr == D3D_OK, "D3DXFilterTexture returned %#x, expected %#x\n", hr, D3D_OK); + + hr = D3DXFilterTexture((IDirect3DBaseTexture9*) voltex, NULL, 0, D3DX_FILTER_BOX); + ok(hr == D3D_OK, "D3DXFilterTexture returned %#x, expected %#x\n", hr, D3D_OK); + + hr = D3DXFilterTexture((IDirect3DBaseTexture9*) voltex, NULL, level_count - 1, D3DX_DEFAULT); + ok(hr == D3D_OK, "D3DXFilterTexture returned %#x, expected %#x\n", hr, D3D_OK); + + hr = D3DXFilterTexture((IDirect3DBaseTexture9*) voltex, NULL, level_count, D3DX_DEFAULT); + ok(hr == D3DERR_INVALIDCALL, "D3DXFilterTexture returned %#x, expected %#x\n", hr, D3DERR_INVALIDCALL); + + IDirect3DVolumeTexture9_Release(voltex); + } + else + skip("Failed to create volume texture\n"); + + /* Test textures with D3DUSAGE_AUTOGENMIPMAP usage */ + if (!is_autogenmipmap_supported(device, D3DRTYPE_TEXTURE)) + { + skip("No D3DUSAGE_AUTOGENMIPMAP supported for textures\n"); + return; + } + + hr = IDirect3DDevice9_CreateTexture(device, 256, 256, 0, D3DUSAGE_DYNAMIC | D3DUSAGE_AUTOGENMIPMAP, D3DFMT_A8R8G8B8, D3DPOOL_DEFAULT, &tex, NULL); + if (SUCCEEDED(hr)) + { + hr = D3DXFilterTexture((IDirect3DBaseTexture9*) tex, NULL, 0, D3DX_FILTER_NONE); + ok(hr == D3D_OK, "D3dXFilteTexture returned %#x, expected %#x\n", hr, D3D_OK); + IDirect3DTexture9_Release(tex); + } + else + skip("Failed to create texture\n"); + + hr = IDirect3DDevice9_CreateTexture(device, 256, 256, 1, D3DUSAGE_DYNAMIC | D3DUSAGE_AUTOGENMIPMAP, D3DFMT_A8R8G8B8, D3DPOOL_DEFAULT, &tex, NULL); + if (SUCCEEDED(hr)) + { + hr = D3DXFilterTexture((IDirect3DBaseTexture9*) tex, NULL, 0, D3DX_FILTER_NONE); + ok(hr == D3D_OK, "D3dXFilteTexture returned %#x, expected %#x\n", hr, D3D_OK); + IDirect3DTexture9_Release(tex); + } + else + skip("Failed to create texture\n"); +} + +static BOOL color_match(const DWORD *value, const DWORD *expected) +{ + int i; + + for (i = 0; i < 4; i++) + { + DWORD diff = value[i] > expected[i] ? value[i] - expected[i] : expected[i] - value[i]; + if (diff > 1) return FALSE; + } + return TRUE; +} + +static void WINAPI fillfunc(D3DXVECTOR4 *value, const D3DXVECTOR2 *texcoord, + const D3DXVECTOR2 *texelsize, void *data) +{ + value->x = texcoord->x; + value->y = texcoord->y; + value->z = texelsize->x; + value->w = 1.0f; +} + +static void test_D3DXFillTexture(IDirect3DDevice9 *device) +{ + IDirect3DTexture9 *tex; + HRESULT hr; + D3DLOCKED_RECT lock_rect; + DWORD x, y, m; + DWORD v[4], e[4]; + DWORD value, expected, size, pitch; + + size = 4; + hr = IDirect3DDevice9_CreateTexture(device, size, size, 0, 0, D3DFMT_A8R8G8B8, + D3DPOOL_MANAGED, &tex, NULL); + + if (SUCCEEDED(hr)) + { + hr = D3DXFillTexture(tex, fillfunc, NULL); + ok(hr == D3D_OK, "D3DXFillTexture returned %#x, expected %#x\n", hr, D3D_OK); + + for (m = 0; m < 3; m++) + { + hr = IDirect3DTexture9_LockRect(tex, m, &lock_rect, NULL, D3DLOCK_READONLY); + ok(hr == D3D_OK, "Couldn't lock the texture, error %#x\n", hr); + if (SUCCEEDED(hr)) + { + pitch = lock_rect.Pitch / sizeof(DWORD); + for (y = 0; y < size; y++) + { + for (x = 0; x < size; x++) + { + value = ((DWORD *)lock_rect.pBits)[y * pitch + x]; + v[0] = (value >> 24) & 0xff; + v[1] = (value >> 16) & 0xff; + v[2] = (value >> 8) & 0xff; + v[3] = value & 0xff; + + e[0] = 0xff; + e[1] = (x + 0.5f) / size * 255.0f + 0.5f; + e[2] = (y + 0.5f) / size * 255.0f + 0.5f; + e[3] = 255.0f / size + 0.5f; + expected = e[0] << 24 | e[1] << 16 | e[2] << 8 | e[3]; + + ok(color_match(v, e), + "Texel at (%u, %u) doesn't match: %#x, expected %#x\n", + x, y, value, expected); + } + } + IDirect3DTexture9_UnlockRect(tex, m); + } + size >>= 1; + } + + IDirect3DTexture9_Release(tex); + } + else + skip("Failed to create texture\n"); + + hr = IDirect3DDevice9_CreateTexture(device, 4, 4, 1, 0, D3DFMT_A1R5G5B5, + D3DPOOL_MANAGED, &tex, NULL); + + if (SUCCEEDED(hr)) + { + hr = D3DXFillTexture(tex, fillfunc, NULL); + ok(hr == D3D_OK, "D3DXFillTexture returned %#x, expected %#x\n", hr, D3D_OK); + + hr = IDirect3DTexture9_LockRect(tex, 0, &lock_rect, NULL, D3DLOCK_READONLY); + ok(hr == D3D_OK, "Couldn't lock the texture, error %#x\n", hr); + if (SUCCEEDED(hr)) + { + pitch = lock_rect.Pitch / sizeof(WORD); + for (y = 0; y < 4; y++) + { + for (x = 0; x < 4; x++) + { + value = ((WORD *)lock_rect.pBits)[y * pitch + x]; + v[0] = value >> 15; + v[1] = value >> 10 & 0x1f; + v[2] = value >> 5 & 0x1f; + v[3] = value & 0x1f; + + e[0] = 1; + e[1] = (x + 0.5f) / 4.0f * 31.0f + 0.5f; + e[2] = (y + 0.5f) / 4.0f * 31.0f + 0.5f; + e[3] = 8; + expected = e[0] << 15 | e[1] << 10 | e[2] << 5 | e[3]; + + ok(color_match(v, e), + "Texel at (%u, %u) doesn't match: %#x, expected %#x\n", + x, y, value, expected); + } + } + IDirect3DTexture9_UnlockRect(tex, 0); + } + + IDirect3DTexture9_Release(tex); + } + else + skip("Failed to create texture\n"); + + /* test floating-point textures */ + hr = IDirect3DDevice9_CreateTexture(device, 4, 4, 1, 0, D3DFMT_A16B16G16R16F, + D3DPOOL_MANAGED, &tex, NULL); + + if (SUCCEEDED(hr)) + { + hr = D3DXFillTexture(tex, fillfunc, NULL); + ok(hr == D3D_OK, "D3DXFillTexture returned %#x, expected %#x\n", hr, D3D_OK); + + hr = IDirect3DTexture9_LockRect(tex, 0, &lock_rect, NULL, D3DLOCK_READONLY); + if (SUCCEEDED(hr)) + { + pitch = lock_rect.Pitch / sizeof(WORD); + for (y = 0; y < 4; y++) + { + WORD *ptr = (WORD *)lock_rect.pBits + y * pitch; + for (x = 0; x < 4; x++) + { + D3DXVECTOR4 got, expected; + + D3DXFloat16To32Array((FLOAT *)&got, (D3DXFLOAT16 *)ptr, 4); + ptr += 4; + + expected.x = (x + 0.5f) / 4.0f; + expected.y = (y + 0.5f) / 4.0f; + expected.z = 1.0f / 4.0f; + expected.w = 1.0f; + + expect_vec4(&expected, &got); + } + } + + IDirect3DTexture9_UnlockRect(tex, 0); + } + else + skip("Failed to lock texture\n"); + + IDirect3DTexture9_Release(tex); + } + else + skip("Failed to create D3DFMT_A16B16G16R16F texture\n"); + + hr = IDirect3DDevice9_CreateTexture(device, 4, 4, 1, 0, D3DFMT_A32B32G32R32F, + D3DPOOL_MANAGED, &tex, NULL); + + if (SUCCEEDED(hr)) + { + hr = D3DXFillTexture(tex, fillfunc, NULL); + ok(hr == D3D_OK, "D3DXFillTexture returned %#x, expected %#x\n", hr, D3D_OK); + + hr = IDirect3DTexture9_LockRect(tex, 0, &lock_rect, NULL, D3DLOCK_READONLY); + if (SUCCEEDED(hr)) + { + pitch = lock_rect.Pitch / sizeof(float); + for (y = 0; y < 4; y++) + { + float *ptr = (float *)lock_rect.pBits + y * pitch; + for (x = 0; x < 4; x++) + { + D3DXVECTOR4 got, expected; + + got.x = *ptr++; + got.y = *ptr++; + got.z = *ptr++; + got.w = *ptr++; + + expected.x = (x + 0.5f) / 4.0f; + expected.y = (y + 0.5f) / 4.0f; + expected.z = 1.0f / 4.0f; + expected.w = 1.0f; + + expect_vec4(&expected, &got); + } + } + + IDirect3DTexture9_UnlockRect(tex, 0); + } + else + skip("Failed to lock texture\n"); + + IDirect3DTexture9_Release(tex); + } + else + skip("Failed to create D3DFMT_A32B32G32R32F texture\n"); + + /* test a compressed texture */ + hr = IDirect3DDevice9_CreateTexture(device, 4, 4, 1, 0, D3DFMT_DXT1, + D3DPOOL_MANAGED, &tex, NULL); + + if (SUCCEEDED(hr)) + { + hr = D3DXFillTexture(tex, fillfunc, NULL); + todo_wine ok(hr == D3D_OK, "D3DXFillTexture returned %#x, expected %#x\n", hr, D3D_OK); + + IDirect3DTexture9_Release(tex); + } + else + skip("Failed to create D3DFMT_DXT1 texture\n"); +} + +static void WINAPI fillfunc_cube(D3DXVECTOR4 *value, const D3DXVECTOR3 *texcoord, + const D3DXVECTOR3 *texelsize, void *data) +{ + value->x = (texcoord->x + 1.0f) / 2.0f; + value->y = (texcoord->y + 1.0f) / 2.0f; + value->z = (texcoord->z + 1.0f) / 2.0f; + value->w = texelsize->x; +} + +enum cube_coord +{ + XCOORD = 0, + XCOORDINV = 1, + YCOORD = 2, + YCOORDINV = 3, + ZERO = 4, + ONE = 5 +}; + +static float get_cube_coord(enum cube_coord coord, unsigned int x, unsigned int y, unsigned int size) +{ + switch (coord) + { + case XCOORD: + return x + 0.5f; + case XCOORDINV: + return size - x - 0.5f; + case YCOORD: + return y + 0.5f; + case YCOORDINV: + return size - y - 0.5f; + case ZERO: + return 0.0f; + case ONE: + return size; + default: + trace("Unexpected coordinate value\n"); + return 0.0f; + } +} + +static void test_D3DXFillCubeTexture(IDirect3DDevice9 *device) +{ + IDirect3DCubeTexture9 *tex; + HRESULT hr; + D3DLOCKED_RECT lock_rect; + DWORD x, y, f, m; + DWORD v[4], e[4]; + DWORD value, expected, size, pitch; + enum cube_coord coordmap[6][3] = + { + {ONE, YCOORDINV, XCOORDINV}, + {ZERO, YCOORDINV, XCOORD}, + {XCOORD, ONE, YCOORD}, + {XCOORD, ZERO, YCOORDINV}, + {XCOORD, YCOORDINV, ONE}, + {XCOORDINV, YCOORDINV, ZERO} + }; + + size = 4; + hr = IDirect3DDevice9_CreateCubeTexture(device, size, 0, 0, D3DFMT_A8R8G8B8, + D3DPOOL_MANAGED, &tex, NULL); + + if (SUCCEEDED(hr)) + { + hr = D3DXFillCubeTexture(tex, fillfunc_cube, NULL); + ok(hr == D3D_OK, "D3DXFillCubeTexture returned %#x, expected %#x\n", hr, D3D_OK); + + for (m = 0; m < 3; m++) + { + for (f = 0; f < 6; f++) + { + hr = IDirect3DCubeTexture9_LockRect(tex, f, m, &lock_rect, NULL, D3DLOCK_READONLY); + ok(hr == D3D_OK, "Couldn't lock the texture, error %#x\n", hr); + if (SUCCEEDED(hr)) + { + pitch = lock_rect.Pitch / sizeof(DWORD); + for (y = 0; y < size; y++) + { + for (x = 0; x < size; x++) + { + value = ((DWORD *)lock_rect.pBits)[y * pitch + x]; + v[0] = (value >> 24) & 0xff; + v[1] = (value >> 16) & 0xff; + v[2] = (value >> 8) & 0xff; + v[3] = value & 0xff; + + e[0] = (f == 0) || (f == 1) ? + 0 : (BYTE)(255.0f / size * 2.0f + 0.5f); + e[1] = get_cube_coord(coordmap[f][0], x, y, size) / size * 255.0f + 0.5f; + e[2] = get_cube_coord(coordmap[f][1], x, y, size) / size * 255.0f + 0.5f; + e[3] = get_cube_coord(coordmap[f][2], x, y, size) / size * 255.0f + 0.5f; + expected = e[0] << 24 | e[1] << 16 | e[2] << 8 | e[3]; + + ok(color_match(v, e), + "Texel at face %u (%u, %u) doesn't match: %#x, expected %#x\n", + f, x, y, value, expected); + } + } + IDirect3DCubeTexture9_UnlockRect(tex, f, m); + } + } + size >>= 1; + } + + IDirect3DCubeTexture9_Release(tex); + } + else + skip("Failed to create texture\n"); + + hr = IDirect3DDevice9_CreateCubeTexture(device, 4, 1, 0, D3DFMT_A1R5G5B5, + D3DPOOL_MANAGED, &tex, NULL); + + if (SUCCEEDED(hr)) + { + hr = D3DXFillCubeTexture(tex, fillfunc_cube, NULL); + ok(hr == D3D_OK, "D3DXFillTexture returned %#x, expected %#x\n", hr, D3D_OK); + for (f = 0; f < 6; f++) + { + hr = IDirect3DCubeTexture9_LockRect(tex, f, 0, &lock_rect, NULL, D3DLOCK_READONLY); + ok(hr == D3D_OK, "Couldn't lock the texture, error %#x\n", hr); + if (SUCCEEDED(hr)) + { + pitch = lock_rect.Pitch / sizeof(WORD); + for (y = 0; y < 4; y++) + { + for (x = 0; x < 4; x++) + { + value = ((WORD *)lock_rect.pBits)[y * pitch + x]; + v[0] = value >> 15; + v[1] = value >> 10 & 0x1f; + v[2] = value >> 5 & 0x1f; + v[3] = value & 0x1f; + + e[0] = (f == 0) || (f == 1) ? + 0 : (BYTE)(1.0f / size * 2.0f + 0.5f); + e[1] = get_cube_coord(coordmap[f][0], x, y, 4) / 4 * 31.0f + 0.5f; + e[2] = get_cube_coord(coordmap[f][1], x, y, 4) / 4 * 31.0f + 0.5f; + e[3] = get_cube_coord(coordmap[f][2], x, y, 4) / 4 * 31.0f + 0.5f; + expected = e[0] << 15 | e[1] << 10 | e[2] << 5 | e[3]; + + ok(color_match(v, e), + "Texel at face %u (%u, %u) doesn't match: %#x, expected %#x\n", + f, x, y, value, expected); + } + } + IDirect3DCubeTexture9_UnlockRect(tex, f, 0); + } + } + + IDirect3DCubeTexture9_Release(tex); + } + else + skip("Failed to create texture\n"); +} + +static void WINAPI fillfunc_volume(D3DXVECTOR4 *value, const D3DXVECTOR3 *texcoord, + const D3DXVECTOR3 *texelsize, void *data) +{ + value->x = texcoord->x; + value->y = texcoord->y; + value->z = texcoord->z; + value->w = texelsize->x; +} + +static void test_D3DXFillVolumeTexture(IDirect3DDevice9 *device) +{ + IDirect3DVolumeTexture9 *tex; + HRESULT hr; + D3DLOCKED_BOX lock_box; + DWORD x, y, z, m; + DWORD v[4], e[4]; + DWORD value, expected, size, row_pitch, slice_pitch; + + size = 4; + hr = IDirect3DDevice9_CreateVolumeTexture(device, size, size, size, 0, 0, D3DFMT_A8R8G8B8, + D3DPOOL_MANAGED, &tex, NULL); + + if (SUCCEEDED(hr)) + { + hr = D3DXFillVolumeTexture(tex, fillfunc_volume, NULL); + ok(hr == D3D_OK, "D3DXFillVolumeTexture returned %#x, expected %#x\n", hr, D3D_OK); + + for (m = 0; m < 3; m++) + { + hr = IDirect3DVolumeTexture9_LockBox(tex, m, &lock_box, NULL, D3DLOCK_READONLY); + ok(hr == D3D_OK, "Couldn't lock the texture, error %#x\n", hr); + if (SUCCEEDED(hr)) + { + row_pitch = lock_box.RowPitch / sizeof(DWORD); + slice_pitch = lock_box.SlicePitch / sizeof(DWORD); + for (z = 0; z < size; z++) + { + for (y = 0; y < size; y++) + { + for (x = 0; x < size; x++) + { + value = ((DWORD *)lock_box.pBits)[z * slice_pitch + y * row_pitch + x]; + v[0] = (value >> 24) & 0xff; + v[1] = (value >> 16) & 0xff; + v[2] = (value >> 8) & 0xff; + v[3] = value & 0xff; + + e[0] = 255.0f / size + 0.5f; + e[1] = (x + 0.5f) / size * 255.0f + 0.5f; + e[2] = (y + 0.5f) / size * 255.0f + 0.5f; + e[3] = (z + 0.5f) / size * 255.0f + 0.5f; + expected = e[0] << 24 | e[1] << 16 | e[2] << 8 | e[3]; + + ok(color_match(v, e), + "Texel at (%u, %u, %u) doesn't match: %#x, expected %#x\n", + x, y, z, value, expected); + } + } + } + IDirect3DVolumeTexture9_UnlockBox(tex, m); + } + size >>= 1; + } + + IDirect3DVolumeTexture9_Release(tex); + } + else + skip("Failed to create texture\n"); + + hr = IDirect3DDevice9_CreateVolumeTexture(device, 4, 4, 4, 1, 0, D3DFMT_A1R5G5B5, + D3DPOOL_MANAGED, &tex, NULL); + + if (SUCCEEDED(hr)) + { + hr = D3DXFillVolumeTexture(tex, fillfunc_volume, NULL); + ok(hr == D3D_OK, "D3DXFillTexture returned %#x, expected %#x\n", hr, D3D_OK); + hr = IDirect3DVolumeTexture9_LockBox(tex, 0, &lock_box, NULL, D3DLOCK_READONLY); + ok(hr == D3D_OK, "Couldn't lock the texture, error %#x\n", hr); + if (SUCCEEDED(hr)) + { + row_pitch = lock_box.RowPitch / sizeof(WORD); + slice_pitch = lock_box.SlicePitch / sizeof(WORD); + for (z = 0; z < 4; z++) + { + for (y = 0; y < 4; y++) + { + for (x = 0; x < 4; x++) + { + value = ((WORD *)lock_box.pBits)[z * slice_pitch + y * row_pitch + x]; + v[0] = value >> 15; + v[1] = value >> 10 & 0x1f; + v[2] = value >> 5 & 0x1f; + v[3] = value & 0x1f; + + e[0] = 1; + e[1] = (x + 0.5f) / 4 * 31.0f + 0.5f; + e[2] = (y + 0.5f) / 4 * 31.0f + 0.5f; + e[3] = (z + 0.5f) / 4 * 31.0f + 0.5f; + expected = e[0] << 15 | e[1] << 10 | e[2] << 5 | e[3]; + + ok(color_match(v, e), + "Texel at (%u, %u, %u) doesn't match: %#x, expected %#x\n", + x, y, z, value, expected); + } + } + } + IDirect3DVolumeTexture9_UnlockBox(tex, 0); + } + + IDirect3DVolumeTexture9_Release(tex); + } + else + skip("Failed to create texture\n"); +} + +static void test_D3DXCreateTextureFromFileInMemory(IDirect3DDevice9 *device) +{ + HRESULT hr; + IDirect3DTexture9 *texture; + D3DRESOURCETYPE type; + D3DSURFACE_DESC desc; + D3DLOCKED_RECT lock_rect; + int i; + DWORD level_count; + + hr = D3DXCreateTextureFromFileInMemory(device, dds_16bit, sizeof(dds_16bit), &texture); + ok(hr == D3D_OK, "D3DXCreateTextureFromFileInMemory returned %#x, expected %#x\n", hr, D3D_OK); + if (SUCCEEDED(hr)) IDirect3DTexture9_Release(texture); + + hr = D3DXCreateTextureFromFileInMemory(device, dds_24bit, sizeof(dds_24bit), &texture); + ok(hr == D3D_OK, "D3DXCreateTextureFromFileInMemory returned %#x, expected %#x\n", hr, D3D_OK); + if (SUCCEEDED(hr)) IDirect3DTexture9_Release(texture); + + hr = D3DXCreateTextureFromFileInMemory(device, dds_24bit, sizeof(dds_24bit) - 1, &texture); + ok(hr == D3DXERR_INVALIDDATA, "D3DXCreateTextureFromFileInMemory returned %#x, expected %#x\n", hr, D3DXERR_INVALIDDATA); + + /* Check that D3DXCreateTextureFromFileInMemory accepts cube texture dds file (only first face texture is loaded) */ + hr = D3DXCreateTextureFromFileInMemory(device, dds_cube_map, sizeof(dds_cube_map), &texture); + todo_wine_if (!has_2d_dxt5) + ok(hr == D3D_OK, "D3DXCreateTextureFromFileInMemory returned %#x, expected %#x.\n", hr, D3D_OK); + if (SUCCEEDED(hr)) + { + type = IDirect3DTexture9_GetType(texture); + ok(type == D3DRTYPE_TEXTURE, "IDirect3DTexture9_GetType returned %u, expected %u\n", type, D3DRTYPE_TEXTURE); + hr = IDirect3DTexture9_GetLevelDesc(texture, 0, &desc); + ok(hr == D3D_OK, "IDirect3DTexture9_GetLevelDesc returned %#x, expected %#x\n", hr, D3D_OK); + ok(desc.Width == 4, "Width is %u, expected 4\n", desc.Width); + ok(desc.Height == 4, "Height is %u, expected 4\n", desc.Height); + hr = IDirect3DTexture9_LockRect(texture, 0, &lock_rect, NULL, D3DLOCK_READONLY); + ok(hr == D3D_OK, "IDirect3DTexture9_LockRect returned %#x, expected %#x\n", hr, D3D_OK); + if (SUCCEEDED(hr)) + { + for (i = 0; i < 16; i++) + ok(((BYTE *)lock_rect.pBits)[i] == dds_cube_map[128 + i], + "Byte at index %u is 0x%02x, expected 0x%02x.\n", + i, ((BYTE *)lock_rect.pBits)[i], dds_cube_map[128 + i]); + IDirect3DTexture9_UnlockRect(texture, 0); + } + IDirect3DTexture9_Release(texture); + + } + + /* Volume textures work too. */ + hr = D3DXCreateTextureFromFileInMemory(device, dds_volume_map, sizeof(dds_volume_map), &texture); + todo_wine_if (!has_2d_dxt3) + ok(hr == D3D_OK, "D3DXCreateTextureFromFileInMemory returned %#x, expected %#x.\n", hr, D3D_OK); + if (SUCCEEDED(hr)) + { + type = IDirect3DTexture9_GetType(texture); + ok(type == D3DRTYPE_TEXTURE, "IDirect3DTexture9_GetType returned %u, expected %u.\n", type, D3DRTYPE_TEXTURE); + level_count = IDirect3DBaseTexture9_GetLevelCount((IDirect3DBaseTexture9 *)texture); + todo_wine ok(level_count == 3, "Texture has %u mip levels, 3 expected.\n", level_count); + hr = IDirect3DTexture9_GetLevelDesc(texture, 0, &desc); + ok(hr == D3D_OK, "IDirect3DTexture9_GetLevelDesc returned %#x, expected %#x.\n", hr, D3D_OK); + ok(desc.Width == 4, "Width is %u, expected 4.\n", desc.Width); + ok(desc.Height == 4, "Height is %u, expected 4.\n", desc.Height); + + hr = IDirect3DTexture9_LockRect(texture, 0, &lock_rect, NULL, D3DLOCK_READONLY); + ok(hr == D3D_OK, "IDirect3DTexture9_LockRect returned %#x, expected %#x.\n", hr, D3D_OK); + if (SUCCEEDED(hr)) + { + for (i = 0; i < 16; ++i) + ok(((BYTE *)lock_rect.pBits)[i] == dds_volume_map[128 + i], + "Byte at index %u is 0x%02x, expected 0x%02x.\n", + i, ((BYTE *)lock_rect.pBits)[i], dds_volume_map[128 + i]); + IDirect3DTexture9_UnlockRect(texture, 0); + } + /* The lower texture levels are apparently generated by filtering the level 0 surface + * I.e. following levels from the file are ignored. */ + IDirect3DTexture9_Release(texture); + } +} + +static void test_D3DXCreateTextureFromFileInMemoryEx(IDirect3DDevice9 *device) +{ + HRESULT hr; + IDirect3DTexture9 *texture; + unsigned int miplevels; + IDirect3DSurface9 *surface; + D3DSURFACE_DESC desc; + + hr = D3DXCreateTextureFromFileInMemoryEx(device, dds_16bit, sizeof(dds_16bit), D3DX_DEFAULT, D3DX_DEFAULT, D3DX_DEFAULT, + 0, D3DFMT_UNKNOWN, D3DPOOL_DEFAULT, D3DX_DEFAULT, D3DX_DEFAULT, 0, NULL, NULL, &texture); + ok(hr == D3D_OK, "D3DXCreateTextureFromFileInMemoryEx returned %#x, expected %#x\n", hr, D3D_OK); + IDirect3DTexture9_Release(texture); + + hr = D3DXCreateTextureFromFileInMemoryEx(device, dds_16bit, sizeof(dds_16bit), D3DX_DEFAULT, D3DX_DEFAULT, D3DX_DEFAULT, + D3DUSAGE_DYNAMIC, D3DFMT_UNKNOWN, D3DPOOL_DEFAULT, D3DX_DEFAULT, D3DX_DEFAULT, 0, NULL, NULL, &texture); + ok(hr == D3D_OK, "D3DXCreateTextureFromFileInMemoryEx returned %#x, expected %#x\n", hr, D3D_OK); + IDirect3DTexture9_Release(texture); + + hr = D3DXCreateTextureFromFileInMemoryEx(device, dds_24bit, sizeof(dds_24bit), D3DX_DEFAULT, + D3DX_DEFAULT, D3DX_DEFAULT, D3DUSAGE_DYNAMIC, D3DFMT_UNKNOWN, D3DPOOL_DEFAULT, + D3DX_DEFAULT, D3DX_SKIP_DDS_MIP_LEVELS(1, D3DX_FILTER_POINT), 0, NULL, NULL, &texture); + ok(hr == D3D_OK, "D3DXCreateTextureFromFileInMemoryEx returned %#x, expected %#x\n", hr, D3D_OK); + miplevels = IDirect3DTexture9_GetLevelCount(texture); + ok(miplevels == 1, "Got miplevels %u, expected %u.\n", miplevels, 1); + IDirect3DTexture9_GetSurfaceLevel(texture, 0, &surface); + IDirect3DSurface9_GetDesc(surface, &desc); + ok(desc.Width == 1 && desc.Height == 1, + "Surface dimensions are %ux%u, expected 1x1.\n", desc.Width, desc.Height); + IDirect3DSurface9_Release(surface); + IDirect3DTexture9_Release(texture); + + if (!is_autogenmipmap_supported(device, D3DRTYPE_TEXTURE)) + { + skip("No D3DUSAGE_AUTOGENMIPMAP support for textures\n"); + return; + } + + hr = D3DXCreateTextureFromFileInMemoryEx(device, dds_16bit, sizeof(dds_16bit), D3DX_DEFAULT, D3DX_DEFAULT, D3DX_DEFAULT, + D3DUSAGE_DYNAMIC | D3DUSAGE_AUTOGENMIPMAP, D3DFMT_UNKNOWN, D3DPOOL_DEFAULT, D3DX_DEFAULT, D3DX_DEFAULT, 0, NULL, NULL, &texture); + ok(hr == D3D_OK, "D3DXCreateTextureFromFileInMemoryEx returned %#x, expected %#x\n", hr, D3D_OK); + IDirect3DTexture9_Release(texture); + + /* Checking for color key format overrides. */ + hr = D3DXCreateTextureFromFileInMemoryEx(device, dds_16bit, sizeof(dds_16bit), + D3DX_DEFAULT, D3DX_DEFAULT, D3DX_DEFAULT, 0, D3DFMT_UNKNOWN, D3DPOOL_DEFAULT, + D3DX_DEFAULT, D3DX_DEFAULT, 0, NULL, NULL, &texture); + ok(hr == D3D_OK, "D3DXCreateTextureFromFileInMemoryEx returned %#x, expected %#x.\n", hr, D3D_OK); + IDirect3DTexture9_GetSurfaceLevel(texture, 0, &surface); + IDirect3DSurface9_GetDesc(surface, &desc); + ok(desc.Format == D3DFMT_X1R5G5B5, "Returned format %u, expected %u.\n", desc.Format, D3DFMT_X1R5G5B5); + IDirect3DSurface9_Release(surface); + IDirect3DTexture9_Release(texture); + hr = D3DXCreateTextureFromFileInMemoryEx(device, dds_16bit, sizeof(dds_16bit), + D3DX_DEFAULT, D3DX_DEFAULT, D3DX_DEFAULT, 0, D3DFMT_UNKNOWN, D3DPOOL_DEFAULT, + D3DX_DEFAULT, D3DX_DEFAULT, 0xff000000, NULL, NULL, &texture); + ok(hr == D3D_OK, "D3DXCreateTextureFromFileInMemoryEx returned %#x, expected %#x.\n", hr, D3D_OK); + IDirect3DTexture9_GetSurfaceLevel(texture, 0, &surface); + IDirect3DSurface9_GetDesc(surface, &desc); + ok(desc.Format == D3DFMT_A1R5G5B5, "Returned format %u, expected %u.\n", desc.Format, D3DFMT_A1R5G5B5); + IDirect3DSurface9_Release(surface); + IDirect3DTexture9_Release(texture); + hr = D3DXCreateTextureFromFileInMemoryEx(device, dds_16bit, sizeof(dds_16bit), + D3DX_DEFAULT, D3DX_DEFAULT, D3DX_DEFAULT, 0, D3DFMT_X1R5G5B5, D3DPOOL_DEFAULT, + D3DX_DEFAULT, D3DX_DEFAULT, 0xff000000, NULL, NULL, &texture); + ok(hr == D3D_OK, "D3DXCreateTextureFromFileInMemoryEx returned %#x, expected %#x.\n", hr, D3D_OK); + IDirect3DTexture9_GetSurfaceLevel(texture, 0, &surface); + IDirect3DSurface9_GetDesc(surface, &desc); + ok(desc.Format == D3DFMT_X1R5G5B5, "Returned format %u, expected %u.\n", desc.Format, D3DFMT_X1R5G5B5); + IDirect3DSurface9_Release(surface); + IDirect3DTexture9_Release(texture); + + hr = D3DXCreateTextureFromFileInMemoryEx(device, dds_24bit, sizeof(dds_24bit), + D3DX_DEFAULT, D3DX_DEFAULT, D3DX_DEFAULT, 0, D3DFMT_UNKNOWN, D3DPOOL_DEFAULT, + D3DX_DEFAULT, D3DX_DEFAULT, 0, NULL, NULL, &texture); + ok(hr == D3D_OK, "D3DXCreateTextureFromFileInMemoryEx returned %#x, expected %#x.\n", hr, D3D_OK); + IDirect3DTexture9_GetSurfaceLevel(texture, 0, &surface); + IDirect3DSurface9_GetDesc(surface, &desc); + ok(desc.Format == D3DFMT_X8R8G8B8, "Returned format %u, expected %u.\n", desc.Format, D3DFMT_X8R8G8B8); + IDirect3DSurface9_Release(surface); + IDirect3DTexture9_Release(texture); + hr = D3DXCreateTextureFromFileInMemoryEx(device, dds_24bit, sizeof(dds_24bit), + D3DX_DEFAULT, D3DX_DEFAULT, D3DX_DEFAULT, 0, D3DFMT_UNKNOWN, D3DPOOL_DEFAULT, + D3DX_DEFAULT, D3DX_DEFAULT, 0xff000000, NULL, NULL, &texture); + ok(hr == D3D_OK, "D3DXCreateTextureFromFileInMemoryEx returned %#x, expected %#x.\n", hr, D3D_OK); + IDirect3DTexture9_GetSurfaceLevel(texture, 0, &surface); + IDirect3DSurface9_GetDesc(surface, &desc); + ok(desc.Format == D3DFMT_A8R8G8B8, "Returned format %u, expected %u.\n", desc.Format, D3DFMT_A8R8G8B8); + IDirect3DSurface9_Release(surface); + IDirect3DTexture9_Release(texture); + hr = D3DXCreateTextureFromFileInMemoryEx(device, dds_24bit, sizeof(dds_24bit), + D3DX_DEFAULT, D3DX_DEFAULT, D3DX_DEFAULT, 0, D3DFMT_X8R8G8B8, D3DPOOL_DEFAULT, + D3DX_DEFAULT, D3DX_DEFAULT, 0xff000000, NULL, NULL, &texture); + ok(hr == D3D_OK, "D3DXCreateTextureFromFileInMemoryEx returned %#x, expected %#x.\n", hr, D3D_OK); + IDirect3DTexture9_GetSurfaceLevel(texture, 0, &surface); + IDirect3DSurface9_GetDesc(surface, &desc); + ok(desc.Format == D3DFMT_X8R8G8B8, "Returned format %u, expected %u.\n", desc.Format, D3DFMT_X8R8G8B8); + IDirect3DSurface9_Release(surface); + IDirect3DTexture9_Release(texture); + + hr = D3DXCreateTextureFromFileInMemoryEx(device, png_grayscale, sizeof(png_grayscale), + D3DX_DEFAULT, D3DX_DEFAULT, D3DX_DEFAULT, 0, D3DFMT_UNKNOWN, D3DPOOL_DEFAULT, + D3DX_DEFAULT, D3DX_DEFAULT, 0, NULL, NULL, &texture); + ok(hr == D3D_OK, "D3DXCreateTextureFromFileInMemoryEx returned %#x, expected %#x.\n", hr, D3D_OK); + IDirect3DTexture9_GetSurfaceLevel(texture, 0, &surface); + IDirect3DSurface9_GetDesc(surface, &desc); + ok(desc.Format == D3DFMT_L8, "Returned format %u, expected %u.\n", desc.Format, D3DFMT_L8); + IDirect3DSurface9_Release(surface); + IDirect3DTexture9_Release(texture); + hr = D3DXCreateTextureFromFileInMemoryEx(device, png_grayscale, sizeof(png_grayscale), + D3DX_DEFAULT, D3DX_DEFAULT, D3DX_DEFAULT, 0, D3DFMT_UNKNOWN, D3DPOOL_DEFAULT, + D3DX_DEFAULT, D3DX_DEFAULT, 0xff000000, NULL, NULL, &texture); + ok(hr == D3D_OK, "D3DXCreateTextureFromFileInMemoryEx returned %#x, expected %#x.\n", hr, D3D_OK); + IDirect3DTexture9_GetSurfaceLevel(texture, 0, &surface); + IDirect3DSurface9_GetDesc(surface, &desc); + ok(desc.Format == D3DFMT_A8L8, "Returned format %u, expected %u.\n", desc.Format, D3DFMT_A8L8); + IDirect3DSurface9_Release(surface); + IDirect3DTexture9_Release(texture); + hr = D3DXCreateTextureFromFileInMemoryEx(device, png_grayscale, sizeof(png_grayscale), + D3DX_DEFAULT, D3DX_DEFAULT, D3DX_DEFAULT, 0, D3DFMT_L8, D3DPOOL_DEFAULT, + D3DX_DEFAULT, D3DX_DEFAULT, 0xff000000, NULL, NULL, &texture); + ok(hr == D3D_OK, "D3DXCreateTextureFromFileInMemoryEx returned %#x, expected %#x.\n", hr, D3D_OK); + IDirect3DTexture9_GetSurfaceLevel(texture, 0, &surface); + IDirect3DSurface9_GetDesc(surface, &desc); + ok(desc.Format == D3DFMT_L8, "Returned format %u, expected %u.\n", desc.Format, D3DFMT_L8); + IDirect3DSurface9_Release(surface); + IDirect3DTexture9_Release(texture); +} + +static void test_D3DXCreateCubeTextureFromFileInMemory(IDirect3DDevice9 *device) +{ + HRESULT hr; + ULONG ref; + DWORD levelcount; + IDirect3DCubeTexture9 *cube_texture; + D3DSURFACE_DESC surface_desc; + + hr = D3DXCreateCubeTextureFromFileInMemory(NULL, dds_cube_map, sizeof(dds_cube_map), &cube_texture); + ok(hr == D3DERR_INVALIDCALL, "D3DXCreateCubeTextureFromFileInMemory returned %#x, expected %#x\n", hr, D3DERR_INVALIDCALL); + + hr = D3DXCreateCubeTextureFromFileInMemory(device, NULL, sizeof(dds_cube_map), &cube_texture); + ok(hr == D3DERR_INVALIDCALL, "D3DXCreateCubeTextureFromFileInMemory returned %#x, expected %#x\n", hr, D3DERR_INVALIDCALL); + + hr = D3DXCreateCubeTextureFromFileInMemory(device, dds_cube_map, 0, &cube_texture); + ok(hr == D3DERR_INVALIDCALL, "D3DXCreateCubeTextureFromFileInMemory returned %#x, expected %#x\n", hr, D3DERR_INVALIDCALL); + + hr = D3DXCreateCubeTextureFromFileInMemory(device, dds_cube_map, sizeof(dds_cube_map), NULL); + ok(hr == D3DERR_INVALIDCALL, "D3DXCreateCubeTextureFromFileInMemory returned %#x, expected %#x\n", hr, D3DERR_INVALIDCALL); + + hr = D3DXCreateCubeTextureFromFileInMemory(device, dds_cube_map, sizeof(dds_cube_map), &cube_texture); + if (SUCCEEDED(hr)) + { + levelcount = IDirect3DCubeTexture9_GetLevelCount(cube_texture); + todo_wine ok(levelcount == 3, "GetLevelCount returned %u, expected 3\n", levelcount); + + hr = IDirect3DCubeTexture9_GetLevelDesc(cube_texture, 0, &surface_desc); + ok(hr == D3D_OK, "GetLevelDesc returned %#x, expected %#x\n", hr, D3D_OK); + ok(surface_desc.Width == 4, "Got width %u, expected 4\n", surface_desc.Width); + ok(surface_desc.Height == 4, "Got height %u, expected 4\n", surface_desc.Height); + + ref = IDirect3DCubeTexture9_Release(cube_texture); + ok(ref == 0, "Invalid reference count. Got %u, expected 0\n", ref); + } else skip("Couldn't create cube texture\n"); +} + +static void test_D3DXCreateCubeTextureFromFileInMemoryEx(IDirect3DDevice9 *device) +{ + HRESULT hr; + IDirect3DCubeTexture9 *cube_texture; + + if (!is_autogenmipmap_supported(device, D3DRTYPE_CUBETEXTURE)) + { + skip("No D3DUSAGE_AUTOGENMIPMAP support for cube textures\n"); + return; + } + + hr = D3DXCreateCubeTextureFromFileInMemoryEx(device, dds_cube_map, sizeof(dds_cube_map), D3DX_DEFAULT, D3DX_DEFAULT, + D3DUSAGE_DYNAMIC | D3DUSAGE_AUTOGENMIPMAP, D3DFMT_UNKNOWN, D3DPOOL_DEFAULT, D3DX_DEFAULT, D3DX_DEFAULT, 0, NULL, NULL, &cube_texture); + todo_wine_if (!has_cube_dxt5) + ok(hr == D3D_OK, "D3DXCreateCubeTextureFromFileInMemoryEx returned %#x, expected %#x.\n", hr, D3D_OK); + if (SUCCEEDED(hr)) IDirect3DCubeTexture9_Release(cube_texture); +} + +static void test_D3DXCreateVolumeTextureFromFileInMemory(IDirect3DDevice9 *device) +{ + HRESULT hr; + ULONG ref; + DWORD levelcount; + IDirect3DVolumeTexture9 *volume_texture; + D3DVOLUME_DESC volume_desc; + + hr = D3DXCreateVolumeTextureFromFileInMemory(NULL, dds_volume_map, sizeof(dds_volume_map), &volume_texture); + ok(hr == D3DERR_INVALIDCALL, "D3DXCreateVolumeTextureFromFileInMemory returned %#x, expected %#x\n", hr, D3DERR_INVALIDCALL); + + hr = D3DXCreateVolumeTextureFromFileInMemory(device, NULL, sizeof(dds_volume_map), &volume_texture); + ok(hr == D3DERR_INVALIDCALL, "D3DXCreateVolumeTextureFromFileInMemory returned %#x, expected %#x\n", hr, D3DERR_INVALIDCALL); + + hr = D3DXCreateVolumeTextureFromFileInMemory(device, dds_volume_map, 0, &volume_texture); + ok(hr == D3DERR_INVALIDCALL, "D3DXCreateVolumeTextureFromFileInMemory returned %#x, expected %#x\n", hr, D3DERR_INVALIDCALL); + + hr = D3DXCreateVolumeTextureFromFileInMemory(device, dds_volume_map, sizeof(dds_volume_map), NULL); + ok(hr == D3DERR_INVALIDCALL, "D3DXCreateVolumeTextureFromFileInMemory returned %#x, expected %#x\n", hr, D3DERR_INVALIDCALL); + + hr = D3DXCreateVolumeTextureFromFileInMemory(device, dds_volume_map, sizeof(dds_volume_map), &volume_texture); + todo_wine_if (!has_3d_dxt3) + ok(hr == D3D_OK, "D3DXCreateVolumeTextureFromFileInMemory returned %#x, expected %#x\n", hr, D3D_OK); + if (SUCCEEDED(hr)) + { + levelcount = IDirect3DVolumeTexture9_GetLevelCount(volume_texture); + ok(levelcount == 3, "GetLevelCount returned %u, expected 3\n", levelcount); + + hr = IDirect3DVolumeTexture9_GetLevelDesc(volume_texture, 0, &volume_desc); + ok(hr == D3D_OK, "GetLevelDesc returned %#x, expected %#x\n", hr, D3D_OK); + ok(volume_desc.Width == 4, "Got width %u, expected 4\n", volume_desc.Width); + ok(volume_desc.Height == 4, "Got height %u, expected 4\n", volume_desc.Height); + ok(volume_desc.Depth == 2, "Got depth %u, expected 2\n", volume_desc.Depth); + ok(volume_desc.Pool == D3DPOOL_MANAGED, "Got pool %u, expected D3DPOOL_MANAGED\n", volume_desc.Pool); + + hr = IDirect3DVolumeTexture9_GetLevelDesc(volume_texture, 1, &volume_desc); + ok(hr == D3D_OK, "GetLevelDesc returned %#x, expected %#x\n", hr, D3D_OK); + ok(volume_desc.Width == 2, "Got width %u, expected 2\n", volume_desc.Width); + ok(volume_desc.Height == 2, "Got height %u, expected 2\n", volume_desc.Height); + ok(volume_desc.Depth == 1, "Got depth %u, expected 1\n", volume_desc.Depth); + + ref = IDirect3DVolumeTexture9_Release(volume_texture); + ok(ref == 0, "Invalid reference count. Got %u, expected 0\n", ref); + } +} + +/* fills positive x face with red color */ +static void WINAPI fill_cube_positive_x(D3DXVECTOR4 *out, const D3DXVECTOR3 *tex_coord, const D3DXVECTOR3 *texel_size, void *data) +{ + memset(out, 0, sizeof(*out)); + if (tex_coord->x > 0 && fabs(tex_coord->x) > fabs(tex_coord->y) && fabs(tex_coord->x) > fabs(tex_coord->z)) + out->x = 1; +} + +static void test_D3DXSaveTextureToFileInMemory(IDirect3DDevice9 *device) +{ + HRESULT hr; + IDirect3DTexture9 *texture; + IDirect3DCubeTexture9 *cube_texture; + IDirect3DVolumeTexture9 *volume_texture; + ID3DXBuffer *buffer; + void *buffer_pointer; + DWORD buffer_size; + D3DXIMAGE_INFO info; + D3DXIMAGE_FILEFORMAT file_format; + + /* textures */ + hr = IDirect3DDevice9_CreateTexture(device, 256, 256, 0, 0, D3DFMT_X8R8G8B8, D3DPOOL_MANAGED, &texture, NULL); + if (FAILED(hr)) + { + skip("Failed to create texture\n"); + return; + } + + for (file_format = D3DXIFF_BMP; file_format <= D3DXIFF_JPG; file_format++) + { + hr = D3DXSaveTextureToFileInMemory(&buffer, file_format, (IDirect3DBaseTexture9 *)texture, NULL); + ok(hr == D3D_OK, "D3DXSaveTextureToFileInMemory returned %#x, expected %#x\n", hr, D3D_OK); + if (SUCCEEDED(hr)) + { + buffer_pointer = ID3DXBuffer_GetBufferPointer(buffer); + buffer_size = ID3DXBuffer_GetBufferSize(buffer); + hr = D3DXGetImageInfoFromFileInMemory(buffer_pointer, buffer_size, &info); + ok(hr == D3D_OK, "D3DXGetImageInfoFromFileInMemory returned %#x, expected %#x\n", hr, D3D_OK); + + ok(info.Width == 256, "Got width %u, expected %u\n", info.Width, 256); + ok(info.Height == 256, "Got height %u, expected %u\n", info.Height, 256); + ok(info.MipLevels == 1, "Got miplevels %u, expected %u\n", info.MipLevels, 1); + ok(info.ResourceType == D3DRTYPE_TEXTURE, "Got resource type %#x, expected %#x\n", info.ResourceType, D3DRTYPE_TEXTURE); + ok(info.ImageFileFormat == file_format, "Got file format %#x, expected %#x\n", info.ImageFileFormat, file_format); + ID3DXBuffer_Release(buffer); + } + } + + todo_wine { + hr = D3DXSaveTextureToFileInMemory(&buffer, D3DXIFF_DDS, (IDirect3DBaseTexture9 *)texture, NULL); + ok(hr == D3D_OK, "D3DXSaveTextureToFileInMemory returned %#x, expected %#x\n", hr, D3D_OK); + if (SUCCEEDED(hr)) + { + buffer_pointer = ID3DXBuffer_GetBufferPointer(buffer); + buffer_size = ID3DXBuffer_GetBufferSize(buffer); + hr = D3DXGetImageInfoFromFileInMemory(buffer_pointer, buffer_size, &info); + ok(hr == D3D_OK, "D3DXGetImageInfoFromFileInMemory returned %#x, expected %#x\n", hr, D3D_OK); + + ok(info.Width == 256, "Got width %u, expected %u\n", info.Width, 256); + ok(info.Height == 256, "Got height %u, expected %u\n", info.Height, 256); + ok(info.MipLevels == 9, "Got miplevels %u, expected %u\n", info.MipLevels, 9); + ok(info.ResourceType == D3DRTYPE_TEXTURE, "Got resource type %#x, expected %#x\n", info.ResourceType, D3DRTYPE_TEXTURE); + ok(info.ImageFileFormat == D3DXIFF_DDS, "Got file format %#x, expected %#x\n", info.ImageFileFormat, D3DXIFF_DDS); + ID3DXBuffer_Release(buffer); + } + } + + IDirect3DTexture9_Release(texture); + + /* cube textures */ + hr = IDirect3DDevice9_CreateCubeTexture(device, 256, 0, 0, D3DFMT_X8R8G8B8, D3DPOOL_MANAGED, &cube_texture, NULL); + if (FAILED(hr)) + { + skip("Failed to create cube texture\n"); + return; + } + + hr = D3DXFillCubeTexture(cube_texture, fill_cube_positive_x, NULL); + ok(hr == D3D_OK, "D3DXFillCubeTexture returned %#x, expected %#x\n", hr, D3D_OK); + + hr = D3DXSaveTextureToFileInMemory(&buffer, D3DXIFF_BMP, (IDirect3DBaseTexture9 *)cube_texture, NULL); + ok(hr == D3D_OK, "D3DXSaveTextureToFileInMemory returned %#x, expected %#x\n", hr, D3D_OK); + if (SUCCEEDED(hr)) + { + IDirect3DSurface9 *surface; + + buffer_pointer = ID3DXBuffer_GetBufferPointer(buffer); + buffer_size = ID3DXBuffer_GetBufferSize(buffer); + hr = D3DXGetImageInfoFromFileInMemory(buffer_pointer, buffer_size, &info); + ok(hr == D3D_OK, "D3DXGetImageInfoFromFileInMemory returned %#x, expected %#x\n", hr, D3D_OK); + + ok(info.Width == 256, "Got width %u, expected %u\n", info.Width, 256); + ok(info.Height == 256, "Got height %u, expected %u\n", info.Height, 256); + ok(info.MipLevels == 1, "Got miplevels %u, expected %u\n", info.MipLevels, 1); + ok(info.ResourceType == D3DRTYPE_TEXTURE, "Got resource type %#x, expected %#x\n", info.ResourceType, D3DRTYPE_TEXTURE); + ok(info.ImageFileFormat == D3DXIFF_BMP, "Got file format %#x, expected %#x\n", info.ImageFileFormat, D3DXIFF_BMP); + + /* positive x face is saved */ + hr = IDirect3DDevice9_CreateOffscreenPlainSurface(device, 256, 256, D3DFMT_X8R8G8B8, D3DPOOL_SYSTEMMEM, &surface, NULL); + if (SUCCEEDED(hr)) + { + D3DLOCKED_RECT locked_rect; + + hr = D3DXLoadSurfaceFromFileInMemory(surface, NULL, NULL, buffer_pointer, buffer_size, NULL, D3DX_FILTER_NONE, 0, NULL); + ok(hr == D3D_OK, "D3DXLoadSurfaceFromFileInMemory returned %#x, expected %#x\n", hr, D3D_OK); + + hr = IDirect3DSurface9_LockRect(surface, &locked_rect, NULL, D3DLOCK_READONLY); + if (SUCCEEDED(hr)) + { + DWORD *color = locked_rect.pBits; + ok(*color == 0x00ff0000, "Got color %#x, expected %#x\n", *color, 0x00ff0000); + IDirect3DSurface9_UnlockRect(surface); + } + + IDirect3DSurface9_Release(surface); + } else skip("Failed to create surface\n"); + + ID3DXBuffer_Release(buffer); + } + + todo_wine { + hr = D3DXSaveTextureToFileInMemory(&buffer, D3DXIFF_DDS, (IDirect3DBaseTexture9 *)cube_texture, NULL); + ok(hr == D3D_OK, "D3DXSaveTextureToFileInMemory returned %#x, expected %#x\n", hr, D3D_OK); + if (SUCCEEDED(hr)) + { + buffer_pointer = ID3DXBuffer_GetBufferPointer(buffer); + buffer_size = ID3DXBuffer_GetBufferSize(buffer); + hr = D3DXGetImageInfoFromFileInMemory(buffer_pointer, buffer_size, &info); + ok(hr == D3D_OK, "D3DXGetImageInfoFromFileInMemory returned %#x, expected %#x\n", hr, D3D_OK); + + ok(info.Width == 256, "Got width %u, expected %u\n", info.Width, 256); + ok(info.Height == 256, "Got height %u, expected %u\n", info.Height, 256); + ok(info.MipLevels == 9, "Got miplevels %u, expected %u\n", info.MipLevels, 9); + ok(info.ResourceType == D3DRTYPE_CUBETEXTURE, "Got resource type %#x, expected %#x\n", info.ResourceType, D3DRTYPE_CUBETEXTURE); + ok(info.ImageFileFormat == D3DXIFF_DDS, "Got file format %#x, expected %#x\n", info.ImageFileFormat, D3DXIFF_DDS); + ID3DXBuffer_Release(buffer); + } + } + + IDirect3DCubeTexture9_Release(cube_texture); + + /* volume textures */ + hr = IDirect3DDevice9_CreateVolumeTexture(device, 256, 256, 256, 0, 0, D3DFMT_X8R8G8B8, D3DPOOL_MANAGED, &volume_texture, NULL); + if (FAILED(hr)) + { + skip("Failed to create volume texture\n"); + return; + } + + todo_wine { + hr = D3DXSaveTextureToFileInMemory(&buffer, D3DXIFF_BMP, (IDirect3DBaseTexture9 *)volume_texture, NULL); + ok(hr == D3D_OK, "D3DXSaveTextureToFileInMemory returned %#x, expected %#x\n", hr, D3D_OK); + if (SUCCEEDED(hr)) + { + buffer_pointer = ID3DXBuffer_GetBufferPointer(buffer); + buffer_size = ID3DXBuffer_GetBufferSize(buffer); + hr = D3DXGetImageInfoFromFileInMemory(buffer_pointer, buffer_size, &info); + ok(hr == D3D_OK, "D3DXGetImageInfoFromFileInMemory returned %#x, expected %#x\n", hr, D3D_OK); + + ok(info.Width == 256, "Got width %u, expected %u\n", info.Width, 256); + ok(info.Height == 256, "Got height %u, expected %u\n", info.Height, 256); + ok(info.Depth == 1, "Got depth %u, expected %u\n", info.Depth, 1); + ok(info.MipLevels == 1, "Got miplevels %u, expected %u\n", info.MipLevels, 1); + ok(info.ResourceType == D3DRTYPE_TEXTURE, "Got resource type %#x, expected %#x\n", info.ResourceType, D3DRTYPE_TEXTURE); + ok(info.ImageFileFormat == D3DXIFF_BMP, "Got file format %#x, expected %#x\n", info.ImageFileFormat, D3DXIFF_BMP); + ID3DXBuffer_Release(buffer); + } + + hr = D3DXSaveTextureToFileInMemory(&buffer, D3DXIFF_DDS, (IDirect3DBaseTexture9 *)volume_texture, NULL); + ok(hr == D3D_OK, "D3DXSaveTextureToFileInMemory returned %#x, expected %#x\n", hr, D3D_OK); + if (SUCCEEDED(hr)) + { + buffer_pointer = ID3DXBuffer_GetBufferPointer(buffer); + buffer_size = ID3DXBuffer_GetBufferSize(buffer); + hr = D3DXGetImageInfoFromFileInMemory(buffer_pointer, buffer_size, &info); + ok(hr == D3D_OK, "D3DXGetImageInfoFromFileInMemory returned %#x, expected %#x\n", hr, D3D_OK); + + ok(info.Width == 256, "Got width %u, expected %u\n", info.Width, 256); + ok(info.Height == 256, "Got height %u, expected %u\n", info.Height, 256); + ok(info.Depth == 256, "Got depth %u, expected %u\n", info.Depth, 256); + ok(info.MipLevels == 9, "Got miplevels %u, expected %u\n", info.MipLevels, 9); + ok(info.ResourceType == D3DRTYPE_VOLUMETEXTURE, "Got resource type %#x, expected %#x\n", info.ResourceType, D3DRTYPE_VOLUMETEXTURE); + ok(info.ImageFileFormat == D3DXIFF_DDS, "Got file format %#x, expected %#x\n", info.ImageFileFormat, D3DXIFF_DDS); + ID3DXBuffer_Release(buffer); + } + } + + IDirect3DVolumeTexture9_Release(volume_texture); +} + +static void test_texture_shader(void) +{ + static const DWORD shader_zero[] = {0x0}; + static const DWORD shader_invalid[] = {0xeeee0100}; + static const DWORD shader_empty[] = {0xfffe0200, 0x0000ffff}; +#if 0 +float4 main(float3 pos : POSITION, float3 size : PSIZE) : COLOR +{ + return float4(pos, 1.0); +} +#endif + static const DWORD shader_code[] = + { + 0x54580100, 0x0015fffe, 0x42415443, 0x0000001c, 0x0000001f, 0x54580100, 0x00000000, 0x00000000, + 0x00000100, 0x0000001c, 0x4d007874, 0x6f726369, 0x74666f73, 0x29522820, 0x534c4820, 0x6853204c, + 0x72656461, 0x6d6f4320, 0x656c6970, 0x2e392072, 0x392e3932, 0x332e3235, 0x00313131, 0x000afffe, + 0x54494c43, 0x00000004, 0x00000000, 0x3ff00000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x0014fffe, 0x434c5846, 0x00000002, 0x10000003, 0x00000001, 0x00000000, + 0x00000003, 0x00000000, 0x00000000, 0x00000004, 0x00000000, 0x10000001, 0x00000001, 0x00000000, + 0x00000001, 0x00000000, 0x00000000, 0x00000004, 0x00000003, 0xf0f0f0f0, 0x0f0f0f0f, 0x0000ffff, + }; + IDirect3DVolumeTexture9 *volume_texture; + IDirect3DCubeTexture9 *cube_texture; + D3DPRESENT_PARAMETERS d3dpp; + IDirect3DTexture9 *texture; + IDirect3DDevice9 *device; + ID3DXTextureShader *tx; + unsigned int x, y, z; + ID3DXBuffer *buffer; + unsigned int *data; + D3DLOCKED_RECT lr; + D3DLOCKED_BOX lb; + IDirect3D9 *d3d; + D3DCAPS9 caps; + HRESULT hr; + HWND wnd; + + hr = D3DXCreateTextureShader(NULL, NULL); + ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr); + + hr = D3DXCreateTextureShader(NULL, &tx); + ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr); + + hr = D3DXCreateTextureShader(shader_invalid, &tx); + todo_wine ok(hr == D3DXERR_INVALIDDATA, "Got unexpected hr %#x.\n", hr); + + hr = D3DXCreateTextureShader(shader_zero, &tx); + todo_wine ok(hr == D3DXERR_INVALIDDATA, "Got unexpected hr %#x.\n", hr); + + hr = D3DXCreateTextureShader(shader_empty, &tx); + todo_wine ok(hr == D3DXERR_INVALIDDATA, "Got unexpected hr %#x.\n", hr); + + hr = D3DXCreateTextureShader(shader_code, &tx); + ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr); + + hr = tx->lpVtbl->GetFunction(tx, &buffer); + todo_wine ok(SUCCEEDED(hr), "Failed to get texture shader bytecode.\n"); + if (FAILED(hr)) + { + skip("Texture shaders not supported, skipping further tests.\n"); + IUnknown_Release(tx); + return; + } + ID3DXBuffer_Release(buffer); + + if (!(wnd = CreateWindowA("static", "d3dx9_test", WS_OVERLAPPEDWINDOW, 0, 0, + 640, 480, NULL, NULL, NULL, NULL))) + { + skip("Couldn't create application window.\n"); + IUnknown_Release(tx); + return; + } + d3d = Direct3DCreate9(D3D_SDK_VERSION); + if (!d3d) + { + skip("Couldn't create IDirect3D9 object.\n"); + DestroyWindow(wnd); + IUnknown_Release(tx); + return; + } + + ZeroMemory(&d3dpp, sizeof(d3dpp)); + d3dpp.Windowed = TRUE; + d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD; + hr = IDirect3D9_CreateDevice(d3d, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, wnd, + D3DCREATE_SOFTWARE_VERTEXPROCESSING, &d3dpp, &device); + if (FAILED(hr)) + { + skip("Failed to create IDirect3DDevice9 object, hr %#x.\n", hr); + IDirect3D9_Release(d3d); + DestroyWindow(wnd); + IUnknown_Release(tx); + return; + } + + IDirect3DDevice9_GetDeviceCaps(device, &caps); + + hr = IDirect3DDevice9_CreateTexture(device, 256, 256, 1, 0, D3DFMT_A8R8G8B8, D3DPOOL_SYSTEMMEM, + &texture, NULL); + ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr); + + hr = D3DXFillTextureTX(texture, tx); + ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr); + + hr = IDirect3DTexture9_LockRect(texture, 0, &lr, NULL, D3DLOCK_READONLY); + ok(SUCCEEDED(hr), "Locking texture failed, hr %#x.\n", hr); + data = lr.pBits; + for (y = 0; y < 256; ++y) + { + for (x = 0; x < 256; ++x) + { + unsigned int expected = 0xff000000 | x << 16 | y << 8; + /* The third position coordinate is apparently undefined for 2D textures. */ + unsigned int color = data[y * lr.Pitch / sizeof(*data) + x] & 0xffffff00; + + ok(compare_color(color, expected, 1), "Unexpected color %08x at (%u, %u).\n", color, x, y); + } + } + hr = IDirect3DTexture9_UnlockRect(texture, 0); + ok(SUCCEEDED(hr), "Unlocking texture failed, hr %#x.\n", hr); + + IDirect3DTexture9_Release(texture); + + if (!(caps.TextureCaps & D3DPTEXTURECAPS_CUBEMAP)) + { + skip("Cube textures not supported, skipping tests.\n"); + goto cleanup; + } + + hr = IDirect3DDevice9_CreateCubeTexture(device, 256, 1, 0, D3DFMT_A8R8G8B8, D3DPOOL_SYSTEMMEM, + &cube_texture, NULL); + ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr); + + hr = D3DXFillCubeTextureTX(cube_texture, tx); + ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr); + + for (z = 0; z < 6; ++z) + { + static const char * const mapping[6][3] = + { + {"-x", "-y", "1"}, + {"+x", "-y", "0"}, + {"+y", "1", "+x"}, + {"-y", "0", "+x"}, + {"1", "-y", "+x"}, + {"0", "-y", "-x"}, + }; + + hr = IDirect3DCubeTexture9_LockRect(cube_texture, z, 0, &lr, NULL, D3DLOCK_READONLY); + ok(SUCCEEDED(hr), "Locking texture failed, hr %#x.\n", hr); + data = lr.pBits; + for (y = 0; y < 256; ++y) + { + for (x = 0; x < 256; ++x) + { + unsigned int color = data[y * lr.Pitch / sizeof(*data) + x]; + unsigned int expected = 0xff000000; + unsigned int i; + + for (i = 0; i < 3; ++i) + { + int component; + + if (mapping[z][i][0] == '0') + component = 0; + else if (mapping[z][i][0] == '1') + component = 255; + else + component = mapping[z][i][1] == 'x' ? x * 2 - 255 : y * 2 - 255; + if (mapping[z][i][0] == '-') + component = -component; + expected |= max(component, 0) << i * 8; + } + ok(compare_color(color, expected, 1), "Unexpected color %08x at (%u, %u, %u).\n", + color, x, y, z); + } + } + hr = IDirect3DCubeTexture9_UnlockRect(cube_texture, z, 0); + ok(SUCCEEDED(hr), "Unlocking texture failed, hr %#x.\n", hr); + } + + IDirect3DCubeTexture9_Release(cube_texture); + + if (!(caps.TextureCaps & D3DPTEXTURECAPS_VOLUMEMAP) || caps.MaxVolumeExtent < 64) + { + skip("Volume textures not supported, skipping test.\n"); + goto cleanup; + } + hr = IDirect3DDevice9_CreateVolumeTexture(device, 64, 64, 64, 1, 0, D3DFMT_A8R8G8B8, + D3DPOOL_SYSTEMMEM, &volume_texture, NULL); + ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr); + + hr = D3DXFillVolumeTextureTX(volume_texture, tx); + ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr); + + hr = IDirect3DVolumeTexture9_LockBox(volume_texture, 0, &lb, NULL, D3DLOCK_READONLY); + ok(SUCCEEDED(hr), "Locking texture failed, hr %#x.\n", hr); + data = lb.pBits; + for (z = 0; z < 64; ++z) + { + for (y = 0; y < 64; ++y) + { + for (x = 0; x < 64; ++x) + { + unsigned int expected = 0xff000000 | ((x * 4 + 2) << 16) | ((y * 4 + 2) << 8) | (z * 4 + 2); + unsigned int color = data[z * lb.SlicePitch / sizeof(*data) + y * lb.RowPitch / sizeof(*data) + x]; + + ok(compare_color(color, expected, 1), "Unexpected color %08x at (%u, %u, %u).\n", + color, x, y, z); + } + } + } + hr = IDirect3DVolumeTexture9_UnlockBox(volume_texture, 0); + ok(SUCCEEDED(hr), "Unlocking texture failed, hr %#x.\n", hr); + + IDirect3DVolumeTexture9_Release(volume_texture); + + cleanup: + IDirect3DDevice9_Release(device); + IDirect3D9_Release(d3d); + DestroyWindow(wnd); + IUnknown_Release(tx); +} + +START_TEST(texture) +{ + HWND wnd; + IDirect3D9 *d3d; + IDirect3DDevice9 *device; + D3DPRESENT_PARAMETERS d3dpp; + HRESULT hr; + ULONG ref; + + if (!(wnd = CreateWindowA("static", "d3dx9_test", WS_OVERLAPPEDWINDOW, 0, 0, + 640, 480, NULL, NULL, NULL, NULL))) + { + skip("Couldn't create application window\n"); + return; + } + d3d = Direct3DCreate9(D3D_SDK_VERSION); + if (!d3d) { + 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_SOFTWARE_VERTEXPROCESSING, &d3dpp, &device); + if (FAILED(hr)) { + skip("Failed to create IDirect3DDevice9 object %#x\n", hr); + IDirect3D9_Release(d3d); + DestroyWindow(wnd); + return; + } + + /* Check whether DXTn textures are supported. */ + has_2d_dxt3 = SUCCEEDED(IDirect3D9_CheckDeviceFormat(d3d, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, + D3DFMT_X8R8G8B8, 0, D3DRTYPE_TEXTURE, D3DFMT_DXT3)); + hr = IDirect3D9_CheckDeviceFormat(d3d, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, + D3DFMT_X8R8G8B8, 0, D3DRTYPE_TEXTURE, D3DFMT_DXT5); + has_2d_dxt5 = SUCCEEDED(hr); + hr = IDirect3D9_CheckDeviceFormat(d3d, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, + D3DFMT_X8R8G8B8, 0, D3DRTYPE_CUBETEXTURE, D3DFMT_DXT5); + has_cube_dxt5 = SUCCEEDED(hr); + has_3d_dxt3 = SUCCEEDED(IDirect3D9_CheckDeviceFormat(d3d, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, + D3DFMT_X8R8G8B8, 0, D3DRTYPE_VOLUMETEXTURE, D3DFMT_DXT3)); + + test_D3DXCheckTextureRequirements(device); + test_D3DXCheckCubeTextureRequirements(device); + test_D3DXCheckVolumeTextureRequirements(device); + test_D3DXCreateTexture(device); + test_D3DXFilterTexture(device); + test_D3DXFillTexture(device); + test_D3DXFillCubeTexture(device); + test_D3DXFillVolumeTexture(device); + test_D3DXCreateTextureFromFileInMemory(device); + test_D3DXCreateTextureFromFileInMemoryEx(device); + test_D3DXCreateCubeTextureFromFileInMemory(device); + test_D3DXCreateCubeTextureFromFileInMemoryEx(device); + test_D3DXCreateVolumeTextureFromFileInMemory(device); + test_D3DXSaveTextureToFileInMemory(device); + + ref = IDirect3DDevice9_Release(device); + ok(!ref, "Device has %u references left.\n", ref); + + IDirect3D9_Release(d3d); + DestroyWindow(wnd); + + test_texture_shader(); +} diff --git a/modules/rostests/winetests/d3dx9_36/volume.c b/modules/rostests/winetests/d3dx9_36/volume.c new file mode 100644 index 00000000000..53260c15a67 --- /dev/null +++ b/modules/rostests/winetests/d3dx9_36/volume.c @@ -0,0 +1,306 @@ +/* + * Tests for the D3DX9 volume functions + * + * Copyright 2012 Józef Kucia + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA + */ + +#define COBJMACROS +#include "wine/test.h" +#include "d3dx9tex.h" + +/* 4x4x2 volume map dds, 2 mipmaps */ +static const unsigned char dds_volume_map[] = +{ + 0x44,0x44,0x53,0x20,0x7c,0x00,0x00,0x00,0x07,0x10,0x8a,0x00,0x04,0x00,0x00,0x00, + 0x04,0x00,0x00,0x00,0x10,0x00,0x00,0x00,0x02,0x00,0x00,0x00,0x03,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x20,0x00,0x00,0x00, + 0x04,0x00,0x00,0x00,0x44,0x58,0x54,0x33,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x08,0x10,0x40,0x00, + 0x00,0x00,0x20,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xef,0x87,0x0f,0x78,0x05,0x05,0x50,0x50, + 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xef,0x87,0x0f,0x78,0x05,0x05,0x50,0x50, + 0xff,0x00,0xff,0x00,0x00,0x00,0x00,0x00,0x2f,0x7e,0xcf,0x79,0x01,0x54,0x5c,0x5c, + 0x0f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x10,0x84,0xef,0x7b,0xaa,0xab,0xab,0xab +}; + +#define check_pixel_4bpp(box, x, y, z, color) _check_pixel_4bpp(__LINE__, box, x, y, z, color) +static inline void _check_pixel_4bpp(unsigned int line, const D3DLOCKED_BOX *box, int x, int y, int z, DWORD expected_color) +{ + DWORD color = ((DWORD *)box->pBits)[x + (y * box->RowPitch + z * box->SlicePitch) / 4]; + ok_(__FILE__, line)(color == expected_color, "Got color 0x%08x, expected 0x%08x\n", color, expected_color); +} + +static inline void set_box(D3DBOX *box, UINT left, UINT top, UINT right, UINT bottom, UINT front, UINT back) +{ + box->Left = left; + box->Top = top; + box->Right = right; + box->Bottom = bottom; + box->Front = front; + box->Back = back; +} + +static void test_D3DXLoadVolumeFromMemory(IDirect3DDevice9 *device) +{ + int i, x, y, z; + HRESULT hr; + D3DBOX src_box, dst_box; + D3DLOCKED_BOX locked_box; + IDirect3DVolume9 *volume; + IDirect3DVolumeTexture9 *volume_texture; + const DWORD pixels[] = { 0xc3394cf0, 0x235ae892, 0x09b197fd, 0x8dc32bf6, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0x00000000, 0x00000000, 0x00000000, 0xffffffff, + 0xffffffff, 0x00000000, 0xffffffff, 0x00000000 }; + + hr = IDirect3DDevice9_CreateVolumeTexture(device, 256, 256, 4, 1, D3DUSAGE_DYNAMIC, D3DFMT_A8R8G8B8, D3DPOOL_DEFAULT, + &volume_texture, NULL); + if (FAILED(hr)) + { + skip("Failed to create volume texture.\n"); + return; + } + + IDirect3DVolumeTexture9_GetVolumeLevel(volume_texture, 0, &volume); + + set_box(&src_box, 0, 0, 4, 1, 0, 4); + set_box(&dst_box, 0, 0, 4, 1, 0, 4); + + hr = D3DXLoadVolumeFromMemory(volume, NULL, &dst_box, pixels, D3DFMT_A8R8G8B8, 16, 16, NULL, &src_box, D3DX_DEFAULT, 0); + if (FAILED(hr)) + { + win_skip("D3DXLoadVolumeFromMemory failed with error %#x, skipping some tests.\n", hr); + return; + } + + IDirect3DVolume9_LockBox(volume, &locked_box, &dst_box, D3DLOCK_READONLY); + for (i = 0; i < 16; i++) check_pixel_4bpp(&locked_box, i % 4, 0, i / 4, pixels[i]); + IDirect3DVolume9_UnlockBox(volume); + + hr = D3DXLoadVolumeFromMemory(volume, NULL, &dst_box, pixels, D3DFMT_UNKNOWN, 16, 16, NULL, &src_box, D3DX_DEFAULT, 0); + ok(hr == E_FAIL, "D3DXLoadVolumeFromMemory returned %#x, expected %#x\n", hr, E_FAIL); + + hr = D3DXLoadVolumeFromMemory(volume, NULL, NULL, pixels, D3DFMT_A8R8G8B8, 16, 16, NULL, &src_box, D3DX_DEFAULT, 0); + ok(hr == D3D_OK, "D3DXLoadVolumeFromMemory returned %#x, expected %#x\n", hr, D3D_OK); + + hr = D3DXLoadVolumeFromMemory(volume, NULL, &dst_box, NULL, D3DFMT_A8R8G8B8, 16, 16, NULL, &src_box, D3DX_DEFAULT, 0); + ok(hr == D3DERR_INVALIDCALL, "D3DXLoadVolumeFromMemory returned %#x, expected %#x\n", hr, D3DERR_INVALIDCALL); + + hr = D3DXLoadVolumeFromMemory(volume, NULL, &dst_box, pixels, D3DFMT_A8R8G8B8, 16, 16, NULL, NULL, D3DX_DEFAULT, 0); + ok(hr == D3DERR_INVALIDCALL, "D3DXLoadVolumeFromMemory returned %#x, expected %#x\n", hr, D3DERR_INVALIDCALL); + + set_box(&src_box, 0, 0, 4, 4, 0, 1); + set_box(&dst_box, 0, 0, 4, 4, 0, 1); + hr = D3DXLoadVolumeFromMemory(volume, NULL, &dst_box, pixels, D3DFMT_A8R8G8B8, 16, sizeof(pixels), NULL, &src_box, D3DX_DEFAULT, 0); + ok(hr == D3D_OK, "D3DXLoadVolumeFromMemory returned %#x, expected %#x\n", hr, D3D_OK); + + IDirect3DVolume9_LockBox(volume, &locked_box, &dst_box, D3DLOCK_READONLY); + for (i = 0; i < 16; i++) check_pixel_4bpp(&locked_box, i % 4, i / 4, 0, pixels[i]); + IDirect3DVolume9_UnlockBox(volume); + + hr = D3DXLoadVolumeFromMemory(volume, NULL, NULL, pixels, D3DFMT_A8R8G8B8, 16, sizeof(pixels), NULL, &src_box, D3DX_FILTER_NONE, 0); + ok(hr == D3D_OK, "D3DXLoadVolumeFromMemory returned %#x, expected %#x\n", hr, D3D_OK); + + IDirect3DVolume9_LockBox(volume, &locked_box, NULL, D3DLOCK_READONLY); + for (i = 0; i < 16; i++) check_pixel_4bpp(&locked_box, i % 4, i / 4, 0, pixels[i]); + for (z = 0; z < 4; z++) + { + for (y = 0; y < 256; y++) + { + for (x = 0; x < 256; x++) + if (z != 0 || y >= 4 || x >= 4) check_pixel_4bpp(&locked_box, x, y, z, 0); + } + } + IDirect3DVolume9_UnlockBox(volume); + + set_box(&src_box, 0, 0, 2, 2, 1, 2); + set_box(&dst_box, 0, 0, 2, 2, 0, 1); + hr = D3DXLoadVolumeFromMemory(volume, NULL, &dst_box, pixels, D3DFMT_A8R8G8B8, 8, 16, NULL, &src_box, D3DX_DEFAULT, 0); + ok(hr == D3D_OK, "D3DXLoadVolumeFromMemory returned %#x, expected %#x\n", hr, D3D_OK); + + IDirect3DVolume9_LockBox(volume, &locked_box, &dst_box, D3DLOCK_READONLY); + for (i = 0; i < 4; i++) check_pixel_4bpp(&locked_box, i % 2, i / 2, 0, pixels[i + 4]); + IDirect3DVolume9_UnlockBox(volume); + + set_box(&src_box, 0, 0, 2, 2, 2, 3); + set_box(&dst_box, 0, 0, 2, 2, 1, 2); + hr = D3DXLoadVolumeFromMemory(volume, NULL, &dst_box, pixels, D3DFMT_A8R8G8B8, 8, 16, NULL, &src_box, D3DX_DEFAULT, 0); + ok(hr == D3D_OK, "D3DXLoadVolumeFromMemory returned %#x, expected %#x\n", hr, D3D_OK); + + IDirect3DVolume9_LockBox(volume, &locked_box, &dst_box, D3DLOCK_READONLY); + for (i = 0; i < 4; i++) check_pixel_4bpp(&locked_box, i % 2, i / 2, 0, pixels[i + 8]); + IDirect3DVolume9_UnlockBox(volume); + + set_box(&src_box, 0, 0, 4, 1, 0, 4); + + set_box(&dst_box, -1, -1, 3, 0, 0, 4); + hr = D3DXLoadVolumeFromMemory(volume, NULL, &dst_box, pixels, D3DFMT_A8R8G8B8, 16, 16, NULL, &src_box, D3DX_DEFAULT, 0); + ok(hr == D3DERR_INVALIDCALL, "D3DXLoadVolumeFromMemory returned %#x, expected %#x\n", hr, D3DERR_INVALIDCALL); + + set_box(&dst_box, 254, 254, 258, 255, 0, 4); + hr = D3DXLoadVolumeFromMemory(volume, NULL, &dst_box, pixels, D3DFMT_A8R8G8B8, 16, 16, NULL, &src_box, D3DX_DEFAULT, 0); + ok(hr == D3DERR_INVALIDCALL, "D3DXLoadVolumeFromMemory returned %#x, expected %#x\n", hr, D3DERR_INVALIDCALL); + + set_box(&dst_box, 4, 1, 0, 0, 0, 4); + hr = D3DXLoadVolumeFromMemory(volume, NULL, &dst_box, pixels, D3DFMT_A8R8G8B8, 16, 16, NULL, &src_box, D3DX_DEFAULT, 0); + ok(hr == D3DERR_INVALIDCALL, "D3DXLoadVolumeFromMemory returned %#x, expected %#x\n", hr, D3DERR_INVALIDCALL); + + set_box(&dst_box, 0, 0, 0, 0, 0, 0); + hr = D3DXLoadVolumeFromMemory(volume, NULL, &dst_box, pixels, D3DFMT_A8R8G8B8, 16, 16, NULL, &src_box, D3DX_DEFAULT, 0); + ok(hr == D3DERR_INVALIDCALL, "D3DXLoadVolumeFromMemory returned %#x, expected %#x\n", hr, D3DERR_INVALIDCALL); + + set_box(&dst_box, 0, 0, 0, 0, 0, 1); + hr = D3DXLoadVolumeFromMemory(volume, NULL, &dst_box, pixels, D3DFMT_A8R8G8B8, 16, 16, NULL, &src_box, D3DX_DEFAULT, 0); + ok(hr == D3DERR_INVALIDCALL, "D3DXLoadVolumeFromMemory returned %#x, expected %#x\n", hr, D3DERR_INVALIDCALL); + + set_box(&dst_box, 300, 300, 300, 300, 0, 0); + hr = D3DXLoadVolumeFromMemory(volume, NULL, &dst_box, pixels, D3DFMT_A8R8G8B8, 16, 16, NULL, &src_box, D3DX_DEFAULT, 0); + ok(hr == D3DERR_INVALIDCALL, "D3DXLoadVolumeFromMemory returned %#x, expected %#x\n", hr, D3DERR_INVALIDCALL); + + IDirect3DVolume9_Release(volume); + IDirect3DVolumeTexture9_Release(volume_texture); + + hr = IDirect3DDevice9_CreateVolumeTexture(device, 256, 256, 4, 1, 0, D3DFMT_A8R8G8B8, D3DPOOL_DEFAULT, &volume_texture, NULL); + if (FAILED(hr)) + { + skip("Failed to create volume texture\n"); + return; + } + + IDirect3DVolumeTexture9_GetVolumeLevel(volume_texture, 0, &volume); + + set_box(&src_box, 0, 0, 4, 1, 0, 4); + set_box(&dst_box, 0, 0, 4, 1, 0, 4); + hr = D3DXLoadVolumeFromMemory(volume, NULL, &dst_box, pixels, D3DFMT_A8R8G8B8, 16, 16, NULL, &src_box, D3DX_DEFAULT, 0); + ok(hr == D3DERR_INVALIDCALL, "D3DXLoadVolumeFromMemory returned %#x, expected %#x\n", hr, D3DERR_INVALIDCALL); + + IDirect3DVolume9_Release(volume); + IDirect3DVolumeTexture9_Release(volume_texture); + + hr = IDirect3DDevice9_CreateVolumeTexture(device, 8, 8, 1, 1, D3DUSAGE_DYNAMIC, D3DFMT_DXT1, D3DPOOL_DEFAULT, &volume_texture, NULL); + if (FAILED(hr)) + { + skip("Failed to create volume texture\n"); + return; + } + + IDirect3DVolumeTexture9_GetVolumeLevel(volume_texture, 0, &volume); + + set_box(&src_box, 1, 1, 7, 7, 0, 1); + set_box(&dst_box, 1, 1, 7, 7, 0, 1); + hr = D3DXLoadVolumeFromMemory(volume, NULL, &dst_box, pixels, D3DFMT_A8R8G8B8, 16, 32, NULL, &src_box, D3DX_DEFAULT, 0); + todo_wine ok(hr == D3D_OK, "D3DXLoadVolumeFromMemory returned %#x, expected %#x\n", hr, D3D_OK); + + IDirect3DVolume9_Release(volume); + IDirect3DVolumeTexture9_Release(volume_texture); +} + +static void test_D3DXLoadVolumeFromFileInMemory(IDirect3DDevice9 *device) +{ + HRESULT hr; + D3DBOX src_box; + IDirect3DVolume9 *volume; + IDirect3DVolumeTexture9 *volume_texture; + + hr = IDirect3DDevice9_CreateVolumeTexture(device, 4, 4, 2, 1, D3DUSAGE_DYNAMIC, D3DFMT_DXT3, D3DPOOL_DEFAULT, + &volume_texture, NULL); + if (FAILED(hr)) + { + skip("Failed to create volume texture\n"); + return; + } + + IDirect3DVolumeTexture9_GetVolumeLevel(volume_texture, 0, &volume); + + hr = D3DXLoadVolumeFromFileInMemory(volume, NULL, NULL, dds_volume_map, sizeof(dds_volume_map), NULL, D3DX_DEFAULT, 0, NULL); + ok(hr == D3D_OK, "D3DXLoadVolumeFromFileInMemory returned %#x, expected %#x\n", hr, D3D_OK); + + hr = D3DXLoadVolumeFromFileInMemory(volume, NULL, NULL, NULL, sizeof(dds_volume_map), NULL, D3DX_DEFAULT, 0, NULL); + ok(hr == D3DERR_INVALIDCALL, "D3DXLoadVolumeFromFileInMemory returned %#x, expected %#x\n", hr, D3DERR_INVALIDCALL); + + hr = D3DXLoadVolumeFromFileInMemory(volume, NULL, NULL, NULL, 0, NULL, D3DX_DEFAULT, 0, NULL); + ok(hr == D3DERR_INVALIDCALL, "D3DXLoadVolumeFromFileInMemory returned %#x, expected %#x\n", hr, D3DERR_INVALIDCALL); + + hr = D3DXLoadVolumeFromFileInMemory(volume, NULL, NULL, dds_volume_map, 0, NULL, D3DX_DEFAULT, 0, NULL); + ok(hr == D3DERR_INVALIDCALL, "D3DXLoadVolumeFromFileInMemory returned %#x, expected %#x\n", hr, D3DERR_INVALIDCALL); + + hr = D3DXLoadVolumeFromFileInMemory(NULL, NULL, NULL, dds_volume_map, sizeof(dds_volume_map), NULL, D3DX_DEFAULT, 0, NULL); + ok(hr == D3DERR_INVALIDCALL, "D3DXLoadVolumeFromFileInMemory returned %#x, expected %#x\n", hr, D3DERR_INVALIDCALL); + + set_box(&src_box, 0, 0, 4, 4, 0, 2); + hr = D3DXLoadVolumeFromFileInMemory(volume, NULL, NULL, dds_volume_map, sizeof(dds_volume_map), &src_box, D3DX_DEFAULT, 0, NULL); + ok(hr == D3D_OK, "D3DXLoadVolumeFromFileInMemory returned %#x, expected %#x\n", hr, D3D_OK); + + set_box(&src_box, 0, 0, 0, 0, 0, 0); + hr = D3DXLoadVolumeFromFileInMemory(volume, NULL, NULL, dds_volume_map, sizeof(dds_volume_map), &src_box, D3DX_DEFAULT, 0, NULL); + ok(hr == E_FAIL, "D3DXLoadVolumeFromFileInMemory returned %#x, expected %#x\n", hr, E_FAIL); + + set_box(&src_box, 0, 0, 5, 4, 0, 2); + hr = D3DXLoadVolumeFromFileInMemory(volume, NULL, NULL, dds_volume_map, sizeof(dds_volume_map), &src_box, D3DX_DEFAULT, 0, NULL); + ok(hr == D3DERR_INVALIDCALL, "D3DXLoadVolumeFromFileInMemory returned %#x, expected %#x\n", hr, D3DERR_INVALIDCALL); + + set_box(&src_box, 0, 0, 4, 4, 0, 3); + hr = D3DXLoadVolumeFromFileInMemory(volume, NULL, NULL, dds_volume_map, sizeof(dds_volume_map), &src_box, D3DX_DEFAULT, 0, NULL); + ok(hr == D3DERR_INVALIDCALL, "D3DXLoadVolumeFromFileInMemory returned %#x, expected %#x\n", hr, D3DERR_INVALIDCALL); + + IDirect3DVolume9_Release(volume); + IDirect3DVolumeTexture9_Release(volume_texture); +} + +START_TEST(volume) +{ + HWND wnd; + IDirect3D9 *d3d; + IDirect3DDevice9 *device; + D3DPRESENT_PARAMETERS d3dpp; + HRESULT hr; + + if (!(wnd = CreateWindowA("static", "d3dx9_test", WS_OVERLAPPEDWINDOW, 0, 0, + 640, 480, NULL, NULL, NULL, NULL))) + { + skip("Couldn't create application window\n"); + return; + } + d3d = Direct3DCreate9(D3D_SDK_VERSION); + if (!d3d) + { + 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_SOFTWARE_VERTEXPROCESSING, &d3dpp, &device); + if(FAILED(hr)) + { + skip("Failed to create IDirect3DDevice9 object %#x\n", hr); + IDirect3D9_Release(d3d); + DestroyWindow(wnd); + return; + } + + test_D3DXLoadVolumeFromMemory(device); + test_D3DXLoadVolumeFromFileInMemory(device); + + IDirect3DDevice9_Release(device); + IDirect3D9_Release(d3d); + DestroyWindow(wnd); +} diff --git a/modules/rostests/winetests/d3dx9_36/xfile.c b/modules/rostests/winetests/d3dx9_36/xfile.c new file mode 100644 index 00000000000..46b4ee26564 --- /dev/null +++ b/modules/rostests/winetests/d3dx9_36/xfile.c @@ -0,0 +1,389 @@ +/* + * Copyright 2012 Christian Costa + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA + */ + +#include + +#include "wine/test.h" +#include "d3dx9.h" +#include "d3dx9xof.h" + +static const char templates_bad_file_type1[] = +"xOf 0302txt 0064\n"; + +static const char templates_bad_file_version[] = +"xof 0102txt 0064\n"; + +static const char templates_bad_file_type2[] = +"xof 0302foo 0064\n"; + +static const char templates_bad_file_float_size[] = +"xof 0302txt 0050\n"; + +static const char templates_parse_error[] = +"xof 0302txt 0064" +"foobar;\n"; + +static const char templates[] = +"xof 0302txt 0064" +"template Header" +"{" +"<3D82AB43-62DA-11CF-AB39-0020AF71E433>" +"WORD major;" +"WORD minor;" +"DWORD flags;" +"}\n"; + +static char objects[] = +"xof 0302txt 0064\n" +"Header Object\n" +"{\n" +"1; 2; 3;\n" +"}\n"; + +static char object_noname[] = +"xof 0302txt 0064\n" +"Header\n" +"{\n" +"1; 2; 3;\n" +"}\n"; + +static char template_using_index_color_lower[] = +"xof 0302txt 0064\n" +"template MeshVertexColors\n" +"{\n" +"<1630B821-7842-11cf-8F52-0040333594A3>\n" +"DWORD nVertexColors;\n" +"array indexColor vertexColors[nVertexColors];\n" +"}\n"; + +static char template_using_index_color_upper[] = +"xof 0302txt 0064\n" +"template MeshVertexColors\n" +"{\n" +"<1630B821-7842-11cf-8F52-0040333594A3>\n" +"DWORD nVertexColors;\n" +"array IndexColor vertexColors[nVertexColors];\n" +"}\n"; + +static void test_templates(void) +{ + ID3DXFile *d3dxfile; + HRESULT ret; + + ret = D3DXFileCreate(NULL); + ok(ret == E_POINTER, "D3DXCreateFile returned %#x, expected %#x\n", ret, E_POINTER); + + ret = D3DXFileCreate(&d3dxfile); + ok(ret == S_OK, "D3DXCreateFile failed with %#x\n", ret); + + ret = d3dxfile->lpVtbl->RegisterTemplates(d3dxfile, templates_bad_file_type1, sizeof(templates_bad_file_type1) - 1); + ok(ret == D3DXFERR_BADFILETYPE, "RegisterTemplates returned %#x, expected %#x\n", ret, D3DXFERR_BADFILETYPE); + + ret = d3dxfile->lpVtbl->RegisterTemplates(d3dxfile, templates_bad_file_version, sizeof(templates_bad_file_version) - 1); + ok(ret == D3DXFERR_BADFILEVERSION, "RegisterTemplates returned %#x, expected %#x\n", ret, D3DXFERR_BADFILEVERSION); + + ret = d3dxfile->lpVtbl->RegisterTemplates(d3dxfile, templates_bad_file_type2, sizeof(templates_bad_file_type2) - 1); + ok(ret == D3DXFERR_BADFILETYPE, "RegisterTemplates returned %#x, expected %#x\n", ret, D3DXFERR_BADFILETYPE); + + ret = d3dxfile->lpVtbl->RegisterTemplates(d3dxfile, templates_bad_file_float_size, sizeof(templates_bad_file_float_size) - 1); + ok(ret == D3DXFERR_BADFILEFLOATSIZE, "RegisterTemplates returned %#x, expected %#x\n", ret, D3DXFERR_BADFILEFLOATSIZE); + + ret = d3dxfile->lpVtbl->RegisterTemplates(d3dxfile, templates_parse_error, sizeof(templates_parse_error) - 1); + ok(ret == D3DXFERR_PARSEERROR, "RegisterTemplates returned %#x, expected %#x\n", ret, D3DXFERR_PARSEERROR); + + ret = d3dxfile->lpVtbl->RegisterTemplates(d3dxfile, templates, sizeof(templates) - 1); + ok(ret == S_OK, "RegisterTemplates failed with %#x\n", ret); + + d3dxfile->lpVtbl->Release(d3dxfile); +} + +static void test_lock_unlock(void) +{ + ID3DXFile *d3dxfile; + D3DXF_FILELOADMEMORY memory; + ID3DXFileEnumObject *enum_object; + ID3DXFileData *data_object; + const void *data; + SIZE_T size; + HRESULT ret; + + ret = D3DXFileCreate(&d3dxfile); + ok(ret == S_OK, "D3DXCreateFile failed with %#x\n", ret); + + ret = d3dxfile->lpVtbl->RegisterTemplates(d3dxfile, templates, sizeof(templates) - 1); + ok(ret == S_OK, "RegisterTemplates failed with %#x\n", ret); + + memory.lpMemory = objects; + memory.dSize = sizeof(objects) - 1; + + ret = d3dxfile->lpVtbl->CreateEnumObject(d3dxfile, &memory, D3DXF_FILELOAD_FROMMEMORY, &enum_object); + ok(ret == S_OK, "CreateEnumObject failed with %#x\n", ret); + + ret = enum_object->lpVtbl->GetChild(enum_object, 0, &data_object); + ok(ret == S_OK, "GetChild failed with %#x\n", ret); + + ret = data_object->lpVtbl->Unlock(data_object); + ok(ret == S_OK, "Unlock failed with %#x\n", ret); + ret = data_object->lpVtbl->Lock(data_object, &size, &data); + ok(ret == S_OK, "Lock failed with %#x\n", ret); + ret = data_object->lpVtbl->Lock(data_object, &size, &data); + ok(ret == S_OK, "Lock failed with %#x\n", ret); + ret = data_object->lpVtbl->Unlock(data_object); + ok(ret == S_OK, "Unlock failed with %#x\n", ret); + ret = data_object->lpVtbl->Unlock(data_object); + ok(ret == S_OK, "Unlock failed with %#x\n", ret); + + data_object->lpVtbl->Release(data_object); + enum_object->lpVtbl->Release(enum_object); + d3dxfile->lpVtbl->Release(d3dxfile); +} + +static void test_getname(void) +{ + ID3DXFile *d3dxfile; + D3DXF_FILELOADMEMORY memory; + ID3DXFileEnumObject *enum_object; + ID3DXFileData *data_object; + SIZE_T length; + char name[100]; + HRESULT ret; + + ret = D3DXFileCreate(&d3dxfile); + ok(ret == S_OK, "D3DXCreateFile failed with %#x\n", ret); + + ret = d3dxfile->lpVtbl->RegisterTemplates(d3dxfile, templates, sizeof(templates) - 1); + ok(ret == S_OK, "RegisterTemplates failed with %#x\n", ret); + + /* Check object with name */ + memory.lpMemory = objects; + memory.dSize = sizeof(objects) - 1; + ret = d3dxfile->lpVtbl->CreateEnumObject(d3dxfile, &memory, D3DXF_FILELOAD_FROMMEMORY, &enum_object); + ok(ret == S_OK, "CreateEnumObject failed with %#x\n", ret); + ret = enum_object->lpVtbl->GetChild(enum_object, 0, &data_object); + ok(ret == S_OK, "GetChild failed with %#x\n", ret); + + ret = data_object->lpVtbl->GetName(data_object, NULL, NULL); + ok(ret == D3DXFERR_BADVALUE, "GetName returned %#x, expected %#x\n", ret, D3DXFERR_BADVALUE); + ret = data_object->lpVtbl->GetName(data_object, name, NULL); + ok(ret == D3DXFERR_BADVALUE, "GetName returned %#x, expected %#x\n", ret, D3DXFERR_BADVALUE); + ret = data_object->lpVtbl->GetName(data_object, NULL, &length); + ok(ret == S_OK, "GetName failed with %#x\n", ret); + ok(length == 7, "Returned length should be 7 instead of %ld\n", length); + length = sizeof(name); + ret = data_object->lpVtbl->GetName(data_object, name, &length); + ok(ret == S_OK, "GetName failed with %#x\n", ret); + ok(length == 7, "Returned length should be 7 instead of %ld\n", length); + ok(!strcmp(name, "Object"), "Returned string should be 'Object' instead of '%s'\n", name); + length = 3; + ret = data_object->lpVtbl->GetName(data_object, name, &length); + ok(ret== D3DXFERR_BADVALUE, "GetName returned %#x, expected %#x\n", ret, D3DXFERR_BADVALUE); + + data_object->lpVtbl->Release(data_object); + enum_object->lpVtbl->Release(enum_object); + + /* Check object without name */ + memory.lpMemory = object_noname; + memory.dSize = sizeof(object_noname) - 1; + ret = d3dxfile->lpVtbl->CreateEnumObject(d3dxfile, &memory, D3DXF_FILELOAD_FROMMEMORY, &enum_object); + ok(ret == S_OK, "CreateEnumObject failed with %#x\n", ret); + ret = enum_object->lpVtbl->GetChild(enum_object, 0, &data_object); + ok(ret == S_OK, "GetChild failed with %#x\n", ret); + + /* Contrary to d3dxof, d3dx9_36 returns an empty string with a null byte when no name is available. + * If the input size is 0, it returns a length of 1 without touching the buffer */ + ret = data_object->lpVtbl->GetName(data_object, NULL, &length); + ok(ret == S_OK, "GetName failed with %#x\n", ret); + ok(length == 1, "Returned length should be 1 instead of %ld\n", length); + length = 0; + name[0] = 0x7f; + ret = data_object->lpVtbl->GetName(data_object, name, &length); + ok(ret == S_OK, "GetName failed with %#x\n", ret); + ok(length == 1, "Returned length should be 1 instead of %ld\n", length); + ok(name[0] == 0x7f, "First character is %#x instead of 0x7f\n", name[0]); + length = sizeof(name); + name[0] = 0x7f; + ret = data_object->lpVtbl->GetName(data_object, name, &length); + ok(ret == S_OK, "GetName failed with %#x\n", ret); + ok(length == 1, "Returned length should be 1 instead of %ld\n", length); + ok(name[0] == 0, "First character is %#x instead of 0x00\n", name[0]); + + data_object->lpVtbl->Release(data_object); + enum_object->lpVtbl->Release(enum_object); + d3dxfile->lpVtbl->Release(d3dxfile); +} + +static void test_type_index_color(void) +{ + ID3DXFile *d3dxfile; + HRESULT ret; + + ret = D3DXFileCreate(&d3dxfile); + ok(ret == S_OK, "D3DXCreateFile failed with %#x\n", ret); + + /* Test that 'indexColor' can be used (same as IndexedColor in standard templates) and is case sensitive */ + ret = d3dxfile->lpVtbl->RegisterTemplates(d3dxfile, template_using_index_color_lower, sizeof(template_using_index_color_lower) - 1); + ok(ret == S_OK, "RegisterTemplates failed with %#x\n", ret); + ret = d3dxfile->lpVtbl->RegisterTemplates(d3dxfile, template_using_index_color_upper, sizeof(template_using_index_color_upper) - 1); + ok(ret == D3DXFERR_PARSEERROR, "RegisterTemplates returned %#x instead of %#x\n", ret, D3DXFERR_PARSEERROR); + + d3dxfile->lpVtbl->Release(d3dxfile); +} + +static void process_data(ID3DXFileData *xfile_data, int level) +{ + HRESULT ret; + char name[100]; + GUID clsid; + GUID clsid_type; + SIZE_T len = sizeof(name); + int i; + const BYTE *data; + SIZE_T size; + SIZE_T children; + + ret = xfile_data->lpVtbl->GetId(xfile_data, &clsid); + ok(ret == S_OK, "ID3DXFileData_GetId failed with %#x\n", ret); + ret = xfile_data->lpVtbl->GetName(xfile_data, name, &len); + ok(ret == S_OK, "ID3DXFileData_GetName failed with %#x\n", ret); + ret = xfile_data->lpVtbl->GetType(xfile_data, &clsid_type); + ok(ret == S_OK, "IDirectXFileData_GetType failed with %#x\n", ret); + ret = xfile_data->lpVtbl->Lock(xfile_data, &size, (const void**)&data); + ok(ret == S_OK, "IDirectXFileData_Lock failed with %#x\n", ret); + + for (i = 0; i < level; i++) + printf(" "); + + printf("Found object '%s' - %s - %s - %lu\n", + len ? name : "", wine_dbgstr_guid(&clsid), wine_dbgstr_guid(&clsid_type), size); + + if (size) + { + int j; + for (j = 0; j < size; j++) + { + if (j && !(j%16)) + printf("\n"); + printf("%02x ", data[j]); + } + printf("\n"); + } + + ret = xfile_data->lpVtbl->Unlock(xfile_data); + ok(ret == S_OK, "ID3DXFileData_Unlock failed with %#x\n", ret); + + ret = xfile_data->lpVtbl->GetChildren(xfile_data, &children); + ok(ret == S_OK, "ID3DXFileData_GetChildren failed with %#x\n", ret); + + level++; + + for (i = 0; i < children; i++) + { + ID3DXFileData *child; + int j; + + ret = xfile_data->lpVtbl->GetChild(xfile_data, i, &child); + ok(ret == S_OK, "ID3DXFileData_GetChild failed with %#x\n", ret); + for (j = 0; j < level; j++) + printf(" "); + if (child->lpVtbl->IsReference(child)) + printf("Found Data Reference (%d)\n", i + 1); + else + printf("Found Data (%d)\n", i + 1); + + process_data(child, level); + + child->lpVtbl->Release(child); + } +} + +/* Dump an X file 'objects.x' and its related templates file 'templates.x' if they are both presents + * Useful for debug by comparing outputs from native and builtin dlls */ +static void test_dump(void) +{ + HRESULT ret; + ULONG ref; + ID3DXFile *xfile = NULL; + ID3DXFileEnumObject *xfile_enum_object = NULL; + HANDLE file; + void *data; + DWORD size; + SIZE_T children; + int i; + + /* Dump data only if there is an object and a template */ + file = CreateFileA("objects.x", GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL); + if (file == INVALID_HANDLE_VALUE) + return; + CloseHandle(file); + + file = CreateFileA("templates.x", GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL); + if (file == INVALID_HANDLE_VALUE) + return; + + data = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, 10000); + + if (!ReadFile(file, data, 10000, &size, NULL)) + { + skip("Templates file is too big\n"); + goto exit; + } + + printf("Load templates file (%u bytes)\n", size); + + ret = D3DXFileCreate(&xfile); + ok(ret == S_OK, "D3DXCreateFile failed with %#x\n", ret); + + ret = xfile->lpVtbl->RegisterTemplates(xfile, data, size); + ok(ret == S_OK, "ID3DXFileImpl_RegisterTemplates failed with %#x\n", ret); + + ret = xfile->lpVtbl->CreateEnumObject(xfile, (void*)"objects.x", D3DXF_FILELOAD_FROMFILE, &xfile_enum_object); + ok(ret == S_OK, "ID3DXFile_CreateEnumObject failed with %#x\n", ret); + + ret = xfile_enum_object->lpVtbl->GetChildren(xfile_enum_object, &children); + ok(ret == S_OK, "ID3DXFileEnumObject_GetChildren failed with %#x\n", ret); + + for (i = 0; i < children; i++) + { + ID3DXFileData *child; + ret = xfile_enum_object->lpVtbl->GetChild(xfile_enum_object, i, &child); + ok(ret == S_OK, "ID3DXFileEnumObject_GetChild failed with %#x\n", ret); + printf("\n"); + process_data(child, 0); + child->lpVtbl->Release(child); + } + + ref = xfile_enum_object->lpVtbl->Release(xfile_enum_object); + ok(ref == 0, "Got refcount %u, expected 0\n", ref); + + ref = xfile->lpVtbl->Release(xfile); + ok(ref == 0, "Got refcount %u, expected 0\n", ref); + + +exit: + CloseHandle(file); + HeapFree(GetProcessHeap(), 0, data); +} + +START_TEST(xfile) +{ + test_templates(); + test_lock_unlock(); + test_getname(); + test_type_index_color(); + test_dump(); +}