Signed-off-by: Matteo Bruni mbruni@codeweavers.com --- For bug 43863 (Rollcage Redux).
dlls/d3dx9_36/d3dx9_private.h | 8 ++++++++ dlls/d3dx9_36/effect.c | 37 ++++++++++++++++++++++++++++++------- dlls/d3dx9_36/shader.c | 38 +++++++++++++++++--------------------- 3 files changed, 55 insertions(+), 28 deletions(-)
diff --git a/dlls/d3dx9_36/d3dx9_private.h b/dlls/d3dx9_36/d3dx9_private.h index 2044b2af448..6cc1126c80f 100644 --- a/dlls/d3dx9_36/d3dx9_private.h +++ b/dlls/d3dx9_36/d3dx9_private.h @@ -69,6 +69,14 @@ struct pixel_format_desc { void (*to_rgba)(const struct vec4 *src, struct vec4 *dst, const PALETTEENTRY *palette); };
+struct d3dx_include_from_file +{ + ID3DXInclude ID3DXInclude_iface; +}; + +extern CRITICAL_SECTION from_file_mutex DECLSPEC_HIDDEN; +extern const struct ID3DXIncludeVtbl d3dx_include_from_file_vtbl DECLSPEC_HIDDEN; + static inline BOOL is_conversion_from_supported(const struct pixel_format_desc *format) { if (format->type == FORMAT_ARGB || format->type == FORMAT_ARGBF16 diff --git a/dlls/d3dx9_36/effect.c b/dlls/d3dx9_36/effect.c index 33e0fc4cdae..7675f17e403 100644 --- a/dlls/d3dx9_36/effect.c +++ b/dlls/d3dx9_36/effect.c @@ -6664,8 +6664,10 @@ static HRESULT d3dx9_base_effect_init(struct d3dx9_base_effect *base, #endif unsigned int i, j;
- TRACE("base %p, data %p, data_size %lu, effect %p, pool %p, skip_constants %s.\n", - base, data, data_size, effect, pool, debugstr_a(skip_constants_string)); + TRACE("base %p, data %p, data_size %lu, defines %p, include %p, eflags %#x, errors %p, " + "effect %p, pool %p, skip_constants %s.\n", + base, data, data_size, defines, include, eflags, errors, effect, pool, + debugstr_a(skip_constants_string));
base->effect = effect; base->pool = pool; @@ -7041,9 +7043,11 @@ HRESULT WINAPI D3DXCreateEffectFromFileExW(struct IDirect3DDevice9 *device, cons const D3DXMACRO *defines, struct ID3DXInclude *include, const char *skipconstants, DWORD flags, struct ID3DXEffectPool *pool, struct ID3DXEffect **effect, struct ID3DXBuffer **compilationerrors) { - void *buffer; + struct d3dx_include_from_file include_from_file; + const void *buffer; + unsigned int size; + char *filename_a; HRESULT ret; - DWORD size;
TRACE("device %p, srcfile %s, defines %p, include %p, skipconstants %s, " "flags %#x, pool %p, effect %p, compilationerrors %p.\n", @@ -7053,14 +7057,33 @@ HRESULT WINAPI D3DXCreateEffectFromFileExW(struct IDirect3DDevice9 *device, cons if (!device || !srcfile) return D3DERR_INVALIDCALL;
- ret = map_view_of_file(srcfile, &buffer, &size); + if (!include) + { + include_from_file.ID3DXInclude_iface.lpVtbl = &d3dx_include_from_file_vtbl; + include = &include_from_file.ID3DXInclude_iface; + }
+ size = WideCharToMultiByte(CP_ACP, 0, srcfile, -1, NULL, 0, NULL, NULL); + filename_a = heap_alloc(size); + if (!filename_a) + return E_OUTOFMEMORY; + WideCharToMultiByte(CP_ACP, 0, srcfile, -1, filename_a, size, NULL, NULL); + + EnterCriticalSection(&from_file_mutex); + ret = ID3DXInclude_Open(include, D3DXINC_LOCAL, filename_a, NULL, &buffer, &size); if (FAILED(ret)) + { + LeaveCriticalSection(&from_file_mutex); + heap_free(filename_a); return D3DXERR_INVALIDDATA; + }
- ret = D3DXCreateEffectEx(device, buffer, size, defines, include, skipconstants, flags, pool, effect, compilationerrors); - UnmapViewOfFile(buffer); + ret = D3DXCreateEffectEx(device, buffer, size, defines, include, skipconstants, flags, pool, + effect, compilationerrors);
+ ID3DXInclude_Close(include, buffer); + LeaveCriticalSection(&from_file_mutex); + heap_free(filename_a); return ret; }
diff --git a/dlls/d3dx9_36/shader.c b/dlls/d3dx9_36/shader.c index f3724947601..acbbf0718ad 100644 --- a/dlls/d3dx9_36/shader.c +++ b/dlls/d3dx9_36/shader.c @@ -214,7 +214,6 @@ HRESULT WINAPI D3DXAssembleShader(const char *data, UINT data_len, const D3DXMAC
static const void *main_file_data;
-static CRITICAL_SECTION from_file_mutex; static CRITICAL_SECTION_DEBUG from_file_mutex_debug = { 0, 0, &from_file_mutex, @@ -224,14 +223,14 @@ static CRITICAL_SECTION_DEBUG from_file_mutex_debug = }, 0, 0, {(DWORD_PTR)(__FILE__ ": from_file_mutex")} }; -static CRITICAL_SECTION from_file_mutex = {&from_file_mutex_debug, -1, 0, 0, 0, 0}; +CRITICAL_SECTION from_file_mutex = {&from_file_mutex_debug, -1, 0, 0, 0, 0};
/* D3DXInclude private implementation, used to implement * D3DXAssembleShaderFromFile() from D3DXAssembleShader(). */ /* To be able to correctly resolve include search paths we have to store the * pathname of each include file. We store the pathname pointer right before * the file data. */ -static HRESULT WINAPI d3dincludefromfile_open(ID3DXInclude *iface, D3DXINCLUDE_TYPE include_type, +static HRESULT WINAPI d3dx_include_from_file_open(ID3DXInclude *iface, D3DXINCLUDE_TYPE include_type, const char *filename, const void *parent_data, const void **data, UINT *bytes) { const char *p, *parent_name = ""; @@ -250,7 +249,7 @@ static HRESULT WINAPI d3dincludefromfile_open(ID3DXInclude *iface, D3DXINCLUDE_T parent_name = *((const char **)main_file_data - 1); }
- TRACE("Looking up for include file %s, parent %s\n", debugstr_a(filename), debugstr_a(parent_name)); + TRACE("Looking up include file %s, parent %s.\n", debugstr_a(filename), debugstr_a(parent_name));
if ((p = strrchr(parent_name, '\'))) ++p; @@ -301,7 +300,7 @@ error: return HRESULT_FROM_WIN32(GetLastError()); }
-static HRESULT WINAPI d3dincludefromfile_close(ID3DXInclude *iface, const void *data) +static HRESULT WINAPI d3dx_include_from_file_close(ID3DXInclude *iface, const void *data) { HeapFree(GetProcessHeap(), 0, *((char **)data - 1)); HeapFree(GetProcessHeap(), 0, (char **)data - 1); @@ -310,13 +309,10 @@ static HRESULT WINAPI d3dincludefromfile_close(ID3DXInclude *iface, const void * return S_OK; }
-static const struct ID3DXIncludeVtbl D3DXInclude_Vtbl = { - d3dincludefromfile_open, - d3dincludefromfile_close -}; - -struct D3DXIncludeImpl { - ID3DXInclude ID3DXInclude_iface; +const struct ID3DXIncludeVtbl d3dx_include_from_file_vtbl = +{ + d3dx_include_from_file_open, + d3dx_include_from_file_close };
HRESULT WINAPI D3DXAssembleShaderFromFileA(const char *filename, const D3DXMACRO *defines, @@ -348,7 +344,7 @@ HRESULT WINAPI D3DXAssembleShaderFromFileW(const WCHAR *filename, const D3DXMACR const void *buffer; DWORD len; HRESULT hr; - struct D3DXIncludeImpl includefromfile; + struct d3dx_include_from_file include_from_file; char *filename_a;
TRACE("filename %s, defines %p, include %p, flags %#x, shader %p, error_messages %p.\n", @@ -356,8 +352,8 @@ HRESULT WINAPI D3DXAssembleShaderFromFileW(const WCHAR *filename, const D3DXMACR
if(!include) { - includefromfile.ID3DXInclude_iface.lpVtbl = &D3DXInclude_Vtbl; - include = &includefromfile.ID3DXInclude_iface; + include_from_file.ID3DXInclude_iface.lpVtbl = &d3dx_include_from_file_vtbl; + include = &include_from_file.ID3DXInclude_iface; }
len = WideCharToMultiByte(CP_ACP, 0, filename, -1, NULL, 0, NULL, NULL); @@ -481,7 +477,7 @@ HRESULT WINAPI D3DXCompileShaderFromFileW(const WCHAR *filename, const D3DXMACRO const void *buffer; DWORD len, filename_len; HRESULT hr; - struct D3DXIncludeImpl includefromfile; + struct d3dx_include_from_file include_from_file; char *filename_a;
TRACE("filename %s, defines %p, include %p, entrypoint %s, profile %s, " @@ -491,8 +487,8 @@ HRESULT WINAPI D3DXCompileShaderFromFileW(const WCHAR *filename, const D3DXMACRO
if (!include) { - includefromfile.ID3DXInclude_iface.lpVtbl = &D3DXInclude_Vtbl; - include = &includefromfile.ID3DXInclude_iface; + include_from_file.ID3DXInclude_iface.lpVtbl = &d3dx_include_from_file_vtbl; + include = &include_from_file.ID3DXInclude_iface; }
filename_len = WideCharToMultiByte(CP_ACP, 0, filename, -1, NULL, 0, NULL, NULL); @@ -606,7 +602,7 @@ HRESULT WINAPI D3DXPreprocessShaderFromFileW(const WCHAR *filename, const D3DXMA const void *buffer; DWORD len; HRESULT hr; - struct D3DXIncludeImpl includefromfile; + struct d3dx_include_from_file include_from_file; char *filename_a;
TRACE("filename %s, defines %p, include %p, shader %p, error_messages %p.\n", @@ -614,8 +610,8 @@ HRESULT WINAPI D3DXPreprocessShaderFromFileW(const WCHAR *filename, const D3DXMA
if (!include) { - includefromfile.ID3DXInclude_iface.lpVtbl = &D3DXInclude_Vtbl; - include = &includefromfile.ID3DXInclude_iface; + include_from_file.ID3DXInclude_iface.lpVtbl = &d3dx_include_from_file_vtbl; + include = &include_from_file.ID3DXInclude_iface; }
len = WideCharToMultiByte(CP_ACP, 0, filename, -1, NULL, 0, NULL, NULL);
Signed-off-by: Matteo Bruni mbruni@codeweavers.com --- It turns out that preprocessing of "ASCII" effects is pretty broken on native. In theory we should replicate the same brokenness in Wine but 1. I don't quite understand how exactly it's broken like and 2. the current implementation works well enough for the case at hand.
dlls/d3dx9_36/tests/effect.c | 348 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 348 insertions(+)
diff --git a/dlls/d3dx9_36/tests/effect.c b/dlls/d3dx9_36/tests/effect.c index bcaf377f9dc..acc5ded6fd7 100644 --- a/dlls/d3dx9_36/tests/effect.c +++ b/dlls/d3dx9_36/tests/effect.c @@ -189,6 +189,63 @@ static IDirect3DDevice9 *create_device(HWND *window) 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" @@ -7485,6 +7542,296 @@ static void test_refcount(void) 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, sizeof(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); +} + START_TEST(effect) { IDirect3DDevice9 *device; @@ -7522,4 +7869,5 @@ START_TEST(effect) test_effect_null_shader(); test_effect_clone(); test_refcount(); + test_create_effect_from_file(); }
Signed-off-by: Matteo Bruni mbruni@codeweavers.com --- For bug 34101 / 43863.
dlls/d3dx9_36/effect.c | 40 ++++++++++++++++++++++++++++++++++++---- 1 file changed, 36 insertions(+), 4 deletions(-)
diff --git a/dlls/d3dx9_36/effect.c b/dlls/d3dx9_36/effect.c index 7675f17e403..1e91a7b82b9 100644 --- a/dlls/d3dx9_36/effect.c +++ b/dlls/d3dx9_36/effect.c @@ -4038,13 +4038,45 @@ done: return ret; }
-static HRESULT WINAPI ID3DXEffectImpl_FindNextValidTechnique(ID3DXEffect* iface, D3DXHANDLE technique, D3DXHANDLE* next_technique) +static HRESULT WINAPI ID3DXEffectImpl_FindNextValidTechnique(ID3DXEffect *iface, + D3DXHANDLE technique, D3DXHANDLE *next_technique) { - struct ID3DXEffectImpl *This = impl_from_ID3DXEffect(iface); + struct ID3DXEffectImpl *effect = impl_from_ID3DXEffect(iface); + struct d3dx9_base_effect *base = &effect->base_effect; + struct d3dx_technique *prev_tech, *tech; + unsigned int i;
- FIXME("(%p)->(%p, %p): stub\n", This, technique, next_technique); + TRACE("iface %p, technique %p, next_technique %p.\n", iface, technique, next_technique);
- return E_NOTIMPL; + if (technique) + { + if (!(prev_tech = get_valid_technique(base, technique))) + return D3DERR_INVALIDCALL; + + for (i = 0; i < base->technique_count; ++i) + { + tech = &base->techniques[i]; + if (tech == prev_tech) + break; + } + } + else + { + i = 0; + } + + for (++i; i < base->technique_count; ++i) + { + tech = &base->techniques[i]; + if (SUCCEEDED(ID3DXEffectImpl_ValidateTechnique(iface, get_technique_handle(tech)))) + { + *next_technique = get_technique_handle(tech); + return D3D_OK; + } + } + + *next_technique = get_technique_handle(&base->techniques[0]); + return S_FALSE; }
static BOOL walk_parameter_dep(struct d3dx_parameter *param, walk_parameter_dep_func param_func,
Signed-off-by: Matteo Bruni mbruni@codeweavers.com --- dlls/d3dx9_36/tests/effect.c | 88 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 88 insertions(+)
diff --git a/dlls/d3dx9_36/tests/effect.c b/dlls/d3dx9_36/tests/effect.c index acc5ded6fd7..0ae02315f4d 100644 --- a/dlls/d3dx9_36/tests/effect.c +++ b/dlls/d3dx9_36/tests/effect.c @@ -7832,6 +7832,93 @@ static void test_create_effect_from_file(void) DestroyWindow(window); }
+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_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; @@ -7870,4 +7957,5 @@ START_TEST(effect) test_effect_clone(); test_refcount(); test_create_effect_from_file(); + test_effect_find_next_valid_technique(); }
Signed-off-by: Matteo Bruni mbruni@codeweavers.com --- Sharing the implementation with ID3DXEffect makes no sense. Instead of incorrectly claiming to partially implement it, make it a complete stub. Doing that even avoids a crash inside D3DXCreateEffectCompiler() when a "working" d3dcompiler_43.dll is around (specifically, it previously called d3dx9_base_effect_init() and then crashed in d3dx9_create_object() because base->effect was NULL).
This improves Battlefield 2142 (bug 39652), although (unsurprisingly) it's not enough to make the game work.
dlls/d3dx9_36/effect.c | 365 ++++++++++++++----------------------------- dlls/d3dx9_36/tests/effect.c | 2 +- 2 files changed, 117 insertions(+), 250 deletions(-)
diff --git a/dlls/d3dx9_36/effect.c b/dlls/d3dx9_36/effect.c index 1e91a7b82b9..404a36d0b54 100644 --- a/dlls/d3dx9_36/effect.c +++ b/dlls/d3dx9_36/effect.c @@ -207,8 +207,6 @@ struct ID3DXEffectCompilerImpl { ID3DXEffectCompiler ID3DXEffectCompiler_iface; LONG ref; - - struct d3dx9_base_effect base_effect; };
static struct d3dx_parameter *get_annotation_by_name(struct d3dx9_base_effect *base, @@ -736,13 +734,6 @@ static void free_effect(struct ID3DXEffectImpl *effect) IDirect3DDevice9_Release(effect->device); }
-static void free_effect_compiler(struct ID3DXEffectCompilerImpl *compiler) -{ - TRACE("Free effect compiler %p\n", compiler); - - d3dx9_base_effect_cleanup(&compiler->base_effect); -} - static void get_vector(struct d3dx_parameter *param, D3DXVECTOR4 *vector) { UINT i; @@ -4661,7 +4652,6 @@ static ULONG WINAPI ID3DXEffectCompilerImpl_Release(ID3DXEffectCompiler *iface)
if (!ref) { - free_effect_compiler(This); HeapFree(GetProcessHeap(), 0, This); }
@@ -4671,547 +4661,435 @@ static ULONG WINAPI ID3DXEffectCompilerImpl_Release(ID3DXEffectCompiler *iface) /*** ID3DXBaseEffect methods ***/ static HRESULT WINAPI ID3DXEffectCompilerImpl_GetDesc(ID3DXEffectCompiler *iface, D3DXEFFECT_DESC *desc) { - struct ID3DXEffectCompilerImpl *compiler = impl_from_ID3DXEffectCompiler(iface); + FIXME("iface %p, desc %p stub!\n", iface, desc);
- TRACE("iface %p, desc %p.\n", iface, desc); - - return d3dx9_base_effect_get_desc(&compiler->base_effect, desc); + return E_NOTIMPL; }
static HRESULT WINAPI ID3DXEffectCompilerImpl_GetParameterDesc(ID3DXEffectCompiler *iface, D3DXHANDLE parameter, D3DXPARAMETER_DESC *desc) { - struct ID3DXEffectCompilerImpl *compiler = impl_from_ID3DXEffectCompiler(iface); + FIXME("iface %p, parameter %p, desc %p stub!\n", iface, parameter, desc);
- TRACE("iface %p, parameter %p, desc %p.\n", iface, parameter, desc); - - return d3dx9_base_effect_get_parameter_desc(&compiler->base_effect, parameter, desc); + return E_NOTIMPL; }
static HRESULT WINAPI ID3DXEffectCompilerImpl_GetTechniqueDesc(ID3DXEffectCompiler *iface, D3DXHANDLE technique, D3DXTECHNIQUE_DESC *desc) { - struct ID3DXEffectCompilerImpl *compiler = impl_from_ID3DXEffectCompiler(iface); + FIXME("iface %p, technique %p, desc %p stub!\n", iface, technique, desc);
- TRACE("iface %p, technique %p, desc %p.\n", iface, technique, desc); - - return d3dx9_base_effect_get_technique_desc(&compiler->base_effect, technique, desc); + return E_NOTIMPL; }
static HRESULT WINAPI ID3DXEffectCompilerImpl_GetPassDesc(ID3DXEffectCompiler *iface, D3DXHANDLE pass, D3DXPASS_DESC *desc) { - struct ID3DXEffectCompilerImpl *compiler = impl_from_ID3DXEffectCompiler(iface); + FIXME("iface %p, pass %p, desc %p stub!\n", iface, pass, desc);
- TRACE("iface %p, pass %p, desc %p.\n", iface, pass, desc); - - return d3dx9_base_effect_get_pass_desc(&compiler->base_effect, pass, desc); + return E_NOTIMPL; }
static HRESULT WINAPI ID3DXEffectCompilerImpl_GetFunctionDesc(ID3DXEffectCompiler *iface, D3DXHANDLE shader, D3DXFUNCTION_DESC *desc) { - struct ID3DXEffectCompilerImpl *compiler = impl_from_ID3DXEffectCompiler(iface); + FIXME("iface %p, shader %p, desc %p stub!\n", iface, shader, desc);
- TRACE("iface %p, shader %p, desc %p.\n", iface, shader, desc); - - return d3dx9_base_effect_get_function_desc(&compiler->base_effect, shader, desc); + return E_NOTIMPL; }
static D3DXHANDLE WINAPI ID3DXEffectCompilerImpl_GetParameter(ID3DXEffectCompiler *iface, D3DXHANDLE parameter, UINT index) { - struct ID3DXEffectCompilerImpl *compiler = impl_from_ID3DXEffectCompiler(iface); - - TRACE("iface %p, parameter %p, index %u.\n", iface, parameter, index); + FIXME("iface %p, parameter %p, index %u stub!\n", iface, parameter, index);
- return d3dx9_base_effect_get_parameter(&compiler->base_effect, parameter, index); + return NULL; }
static D3DXHANDLE WINAPI ID3DXEffectCompilerImpl_GetParameterByName(ID3DXEffectCompiler *iface, D3DXHANDLE parameter, const char *name) { - struct ID3DXEffectCompilerImpl *compiler = impl_from_ID3DXEffectCompiler(iface); - - TRACE("iface %p, parameter %p, name %s.\n", iface, parameter, debugstr_a(name)); + FIXME("iface %p, parameter %p, name %s stub!\n", iface, parameter, debugstr_a(name));
- return d3dx9_base_effect_get_parameter_by_name(&compiler->base_effect, parameter, name); + return NULL; }
static D3DXHANDLE WINAPI ID3DXEffectCompilerImpl_GetParameterBySemantic(ID3DXEffectCompiler *iface, D3DXHANDLE parameter, const char *semantic) { - struct ID3DXEffectCompilerImpl *compiler = impl_from_ID3DXEffectCompiler(iface); - - TRACE("iface %p, parameter %p, semantic %s.\n", iface, parameter, debugstr_a(semantic)); + FIXME("iface %p, parameter %p, semantic %s stub!\n", iface, parameter, debugstr_a(semantic));
- return d3dx9_base_effect_get_parameter_by_semantic(&compiler->base_effect, parameter, semantic); + return NULL; }
static D3DXHANDLE WINAPI ID3DXEffectCompilerImpl_GetParameterElement(ID3DXEffectCompiler *iface, D3DXHANDLE parameter, UINT index) { - struct ID3DXEffectCompilerImpl *compiler = impl_from_ID3DXEffectCompiler(iface); - - TRACE("iface %p, parameter %p, index %u.\n", iface, parameter, index); + FIXME("iface %p, parameter %p, index %u stub!\n", iface, parameter, index);
- return d3dx9_base_effect_get_parameter_element(&compiler->base_effect, parameter, index); + return NULL; }
static D3DXHANDLE WINAPI ID3DXEffectCompilerImpl_GetTechnique(ID3DXEffectCompiler *iface, UINT index) { - struct ID3DXEffectCompilerImpl *compiler = impl_from_ID3DXEffectCompiler(iface); - - TRACE("iface %p, index %u.\n", iface, index); + FIXME("iface %p, index %u stub!\n", iface, index);
- return d3dx9_base_effect_get_technique(&compiler->base_effect, index); + return NULL; }
static D3DXHANDLE WINAPI ID3DXEffectCompilerImpl_GetTechniqueByName(ID3DXEffectCompiler *iface, const char *name) { - struct ID3DXEffectCompilerImpl *compiler = impl_from_ID3DXEffectCompiler(iface); - - TRACE("iface %p, name %s.\n", iface, debugstr_a(name)); + FIXME("iface %p, name %s stub!\n", iface, debugstr_a(name));
- return d3dx9_base_effect_get_technique_by_name(&compiler->base_effect, name); + return NULL; }
static D3DXHANDLE WINAPI ID3DXEffectCompilerImpl_GetPass(ID3DXEffectCompiler *iface, D3DXHANDLE technique, UINT index) { - struct ID3DXEffectCompilerImpl *compiler = impl_from_ID3DXEffectCompiler(iface); - - TRACE("iface %p, technique %p, index %u.\n", iface, technique, index); + FIXME("iface %p, technique %p, index %u stub!\n", iface, technique, index);
- return d3dx9_base_effect_get_pass(&compiler->base_effect, technique, index); + return NULL; }
static D3DXHANDLE WINAPI ID3DXEffectCompilerImpl_GetPassByName(ID3DXEffectCompiler *iface, D3DXHANDLE technique, const char *name) { - struct ID3DXEffectCompilerImpl *compiler = impl_from_ID3DXEffectCompiler(iface); - - TRACE("iface %p, technique %p, name %s.\n", iface, technique, debugstr_a(name)); + FIXME("iface %p, technique %p, name %s stub!\n", iface, technique, debugstr_a(name));
- return d3dx9_base_effect_get_pass_by_name(&compiler->base_effect, technique, name); + return NULL; }
static D3DXHANDLE WINAPI ID3DXEffectCompilerImpl_GetFunction(ID3DXEffectCompiler *iface, UINT index) { - struct ID3DXEffectCompilerImpl *compiler = impl_from_ID3DXEffectCompiler(iface); + FIXME("iface %p, index %u stub!\n", iface, index);
- TRACE("iface %p, index %u.\n", iface, index); - - return d3dx9_base_effect_get_function(&compiler->base_effect, index); + return NULL; }
static D3DXHANDLE WINAPI ID3DXEffectCompilerImpl_GetFunctionByName(ID3DXEffectCompiler *iface, const char *name) { - struct ID3DXEffectCompilerImpl *compiler = impl_from_ID3DXEffectCompiler(iface); - - TRACE("iface %p, name %s.\n", iface, debugstr_a(name)); + FIXME("iface %p, name %s stub!\n", iface, debugstr_a(name));
- return d3dx9_base_effect_get_function_by_name(&compiler->base_effect, name); + return NULL; }
static D3DXHANDLE WINAPI ID3DXEffectCompilerImpl_GetAnnotation(ID3DXEffectCompiler *iface, D3DXHANDLE object, UINT index) { - struct ID3DXEffectCompilerImpl *compiler = impl_from_ID3DXEffectCompiler(iface); - - TRACE("iface %p, object %p, index %u.\n", iface, object, index); + FIXME("iface %p, object %p, index %u stub!\n", iface, object, index);
- return d3dx9_base_effect_get_annotation(&compiler->base_effect, object, index); + return NULL; }
static D3DXHANDLE WINAPI ID3DXEffectCompilerImpl_GetAnnotationByName(ID3DXEffectCompiler *iface, D3DXHANDLE object, const char *name) { - struct ID3DXEffectCompilerImpl *compiler = impl_from_ID3DXEffectCompiler(iface); - - TRACE("iface %p, object %p, name %s.\n", iface, object, debugstr_a(name)); + FIXME("iface %p, object %p, name %s stub!\n", iface, object, debugstr_a(name));
- return d3dx9_base_effect_get_annotation_by_name(&compiler->base_effect, object, name); + return NULL; }
static HRESULT WINAPI ID3DXEffectCompilerImpl_SetValue(ID3DXEffectCompiler *iface, D3DXHANDLE parameter, const void *data, UINT bytes) { - struct ID3DXEffectCompilerImpl *compiler = impl_from_ID3DXEffectCompiler(iface); + FIXME("iface %p, parameter %p, data %p, bytes %u stub!\n", iface, parameter, data, bytes);
- TRACE("iface %p, parameter %p, data %p, bytes %u.\n", iface, parameter, data, bytes); - - return d3dx9_base_effect_set_value(&compiler->base_effect, parameter, data, bytes); + return E_NOTIMPL; }
static HRESULT WINAPI ID3DXEffectCompilerImpl_GetValue(ID3DXEffectCompiler *iface, D3DXHANDLE parameter, void *data, UINT bytes) { - struct ID3DXEffectCompilerImpl *compiler = impl_from_ID3DXEffectCompiler(iface); - - TRACE("iface %p, parameter %p, data %p, bytes %u.\n", iface, parameter, data, bytes); + FIXME("iface %p, parameter %p, data %p, bytes %u stub!\n", iface, parameter, data, bytes);
- return d3dx9_base_effect_get_value(&compiler->base_effect, parameter, data, bytes); + return E_NOTIMPL; }
static HRESULT WINAPI ID3DXEffectCompilerImpl_SetBool(ID3DXEffectCompiler *iface, D3DXHANDLE parameter, BOOL b) { - struct ID3DXEffectCompilerImpl *compiler = impl_from_ID3DXEffectCompiler(iface); + FIXME("iface %p, parameter %p, b %#x stub!\n", iface, parameter, b);
- TRACE("iface %p, parameter %p, b %#x.\n", iface, parameter, b); - - return d3dx9_base_effect_set_bool(&compiler->base_effect, parameter, b); + return E_NOTIMPL; }
static HRESULT WINAPI ID3DXEffectCompilerImpl_GetBool(ID3DXEffectCompiler *iface, D3DXHANDLE parameter, BOOL *b) { - struct ID3DXEffectCompilerImpl *compiler = impl_from_ID3DXEffectCompiler(iface); + FIXME("iface %p, parameter %p, b %p stub!\n", iface, parameter, b);
- TRACE("iface %p, parameter %p, b %p.\n", iface, parameter, b); - - return d3dx9_base_effect_get_bool(&compiler->base_effect, parameter, b); + return E_NOTIMPL; }
static HRESULT WINAPI ID3DXEffectCompilerImpl_SetBoolArray(ID3DXEffectCompiler *iface, D3DXHANDLE parameter, const BOOL *b, UINT count) { - struct ID3DXEffectCompilerImpl *compiler = impl_from_ID3DXEffectCompiler(iface); + FIXME("iface %p, parameter %p, b %p, count %u stub!\n", iface, parameter, b, count);
- TRACE("iface %p, parameter %p, b %p, count %u.\n", iface, parameter, b, count); - - return d3dx9_base_effect_set_bool_array(&compiler->base_effect, parameter, b, count); + return E_NOTIMPL; }
static HRESULT WINAPI ID3DXEffectCompilerImpl_GetBoolArray(ID3DXEffectCompiler *iface, D3DXHANDLE parameter, BOOL *b, UINT count) { - struct ID3DXEffectCompilerImpl *compiler = impl_from_ID3DXEffectCompiler(iface); + FIXME("iface %p, parameter %p, b %p, count %u stub!\n", iface, parameter, b, count);
- TRACE("iface %p, parameter %p, b %p, count %u.\n", iface, parameter, b, count); - - return d3dx9_base_effect_get_bool_array(&compiler->base_effect, parameter, b, count); + return E_NOTIMPL; }
static HRESULT WINAPI ID3DXEffectCompilerImpl_SetInt(ID3DXEffectCompiler *iface, D3DXHANDLE parameter, INT n) { - struct ID3DXEffectCompilerImpl *compiler = impl_from_ID3DXEffectCompiler(iface); + FIXME("iface %p, parameter %p, n %d stub!\n", iface, parameter, n);
- TRACE("iface %p, parameter %p, n %d.\n", iface, parameter, n); - - return d3dx9_base_effect_set_int(&compiler->base_effect, parameter, n); + return E_NOTIMPL; }
static HRESULT WINAPI ID3DXEffectCompilerImpl_GetInt(ID3DXEffectCompiler *iface, D3DXHANDLE parameter, INT *n) { - struct ID3DXEffectCompilerImpl *compiler = impl_from_ID3DXEffectCompiler(iface); - - TRACE("iface %p, parameter %p, n %p.\n", iface, parameter, n); + FIXME("iface %p, parameter %p, n %p stub!\n", iface, parameter, n);
- return d3dx9_base_effect_get_int(&compiler->base_effect, parameter, n); + return E_NOTIMPL; }
static HRESULT WINAPI ID3DXEffectCompilerImpl_SetIntArray(ID3DXEffectCompiler *iface, D3DXHANDLE parameter, const INT *n, UINT count) { - struct ID3DXEffectCompilerImpl *compiler = impl_from_ID3DXEffectCompiler(iface); - - TRACE("iface %p, parameter %p, n %p, count %u.\n", iface, parameter, n, count); + FIXME("iface %p, parameter %p, n %p, count %u stub!\n", iface, parameter, n, count);
- return d3dx9_base_effect_set_int_array(&compiler->base_effect, parameter, n, count); + return E_NOTIMPL; }
static HRESULT WINAPI ID3DXEffectCompilerImpl_GetIntArray(ID3DXEffectCompiler *iface, D3DXHANDLE parameter, INT *n, UINT count) { - struct ID3DXEffectCompilerImpl *compiler = impl_from_ID3DXEffectCompiler(iface); - - TRACE("iface %p, parameter %p, n %p, count %u.\n", iface, parameter, n, count); + FIXME("iface %p, parameter %p, n %p, count %u stub!\n", iface, parameter, n, count);
- return d3dx9_base_effect_get_int_array(&compiler->base_effect, parameter, n, count); + return E_NOTIMPL; }
static HRESULT WINAPI ID3DXEffectCompilerImpl_SetFloat(ID3DXEffectCompiler *iface, D3DXHANDLE parameter, float f) { - struct ID3DXEffectCompilerImpl *compiler = impl_from_ID3DXEffectCompiler(iface); - - TRACE("iface %p, parameter %p, f %.8e.\n", iface, parameter, f); + FIXME("iface %p, parameter %p, f %.8e stub!\n", iface, parameter, f);
- return d3dx9_base_effect_set_float(&compiler->base_effect, parameter, f); + return E_NOTIMPL; }
static HRESULT WINAPI ID3DXEffectCompilerImpl_GetFloat(ID3DXEffectCompiler *iface, D3DXHANDLE parameter, float *f) { - struct ID3DXEffectCompilerImpl *compiler = impl_from_ID3DXEffectCompiler(iface); - - TRACE("iface %p, parameter %p, f %p.\n", iface, parameter, f); + FIXME("iface %p, parameter %p, f %p stub!\n", iface, parameter, f);
- return d3dx9_base_effect_get_float(&compiler->base_effect, parameter, f); + return E_NOTIMPL; }
static HRESULT WINAPI ID3DXEffectCompilerImpl_SetFloatArray(ID3DXEffectCompiler *iface, D3DXHANDLE parameter, const float *f, UINT count) { - struct ID3DXEffectCompilerImpl *compiler = impl_from_ID3DXEffectCompiler(iface); - - TRACE("iface %p, parameter %p, f %p, count %u.\n", iface, parameter, f, count); + FIXME("iface %p, parameter %p, f %p, count %u stub!\n", iface, parameter, f, count);
- return d3dx9_base_effect_set_float_array(&compiler->base_effect, parameter, f, count); + return E_NOTIMPL; }
static HRESULT WINAPI ID3DXEffectCompilerImpl_GetFloatArray(ID3DXEffectCompiler *iface, D3DXHANDLE parameter, float *f, UINT count) { - struct ID3DXEffectCompilerImpl *compiler = impl_from_ID3DXEffectCompiler(iface); - - TRACE("iface %p, parameter %p, f %p, count %u.\n", iface, parameter, f, count); + FIXME("iface %p, parameter %p, f %p, count %u stub!\n", iface, parameter, f, count);
- return d3dx9_base_effect_get_float_array(&compiler->base_effect, parameter, f, count); + return E_NOTIMPL; }
static HRESULT WINAPI ID3DXEffectCompilerImpl_SetVector(ID3DXEffectCompiler *iface, D3DXHANDLE parameter, const D3DXVECTOR4 *vector) { - struct ID3DXEffectCompilerImpl *compiler = impl_from_ID3DXEffectCompiler(iface); - - TRACE("iface %p, parameter %p, vector %p.\n", iface, parameter, vector); + FIXME("iface %p, parameter %p, vector %p stub!\n", iface, parameter, vector);
- return d3dx9_base_effect_set_vector(&compiler->base_effect, parameter, vector); + return E_NOTIMPL; }
static HRESULT WINAPI ID3DXEffectCompilerImpl_GetVector(ID3DXEffectCompiler *iface, D3DXHANDLE parameter, D3DXVECTOR4 *vector) { - struct ID3DXEffectCompilerImpl *compiler = impl_from_ID3DXEffectCompiler(iface); + FIXME("iface %p, parameter %p, vector %p stub!\n", iface, parameter, vector);
- TRACE("iface %p, parameter %p, vector %p.\n", iface, parameter, vector); - - return d3dx9_base_effect_get_vector(&compiler->base_effect, parameter, vector); + return E_NOTIMPL; }
static HRESULT WINAPI ID3DXEffectCompilerImpl_SetVectorArray(ID3DXEffectCompiler *iface, D3DXHANDLE parameter, const D3DXVECTOR4 *vector, UINT count) { - struct ID3DXEffectCompilerImpl *compiler = impl_from_ID3DXEffectCompiler(iface); - - TRACE("iface %p, parameter %p, vector %p, count %u.\n", iface, parameter, vector, count); + FIXME("iface %p, parameter %p, vector %p, count %u stub!\n", iface, parameter, vector, count);
- return d3dx9_base_effect_set_vector_array(&compiler->base_effect, parameter, vector, count); + return E_NOTIMPL; }
static HRESULT WINAPI ID3DXEffectCompilerImpl_GetVectorArray(ID3DXEffectCompiler *iface, D3DXHANDLE parameter, D3DXVECTOR4 *vector, UINT count) { - struct ID3DXEffectCompilerImpl *compiler = impl_from_ID3DXEffectCompiler(iface); + FIXME("iface %p, parameter %p, vector %p, count %u stub!\n", iface, parameter, vector, count);
- TRACE("iface %p, parameter %p, vector %p, count %u.\n", iface, parameter, vector, count); - - return d3dx9_base_effect_get_vector_array(&compiler->base_effect, parameter, vector, count); + return E_NOTIMPL; }
static HRESULT WINAPI ID3DXEffectCompilerImpl_SetMatrix(ID3DXEffectCompiler *iface, D3DXHANDLE parameter, const D3DXMATRIX *matrix) { - struct ID3DXEffectCompilerImpl *compiler = impl_from_ID3DXEffectCompiler(iface); + FIXME("iface %p, parameter %p, matrix %p stub!\n", iface, parameter, matrix);
- TRACE("iface %p, parameter %p, matrix %p.\n", iface, parameter, matrix); - - return d3dx9_base_effect_set_matrix(&compiler->base_effect, parameter, matrix); + return E_NOTIMPL; }
static HRESULT WINAPI ID3DXEffectCompilerImpl_GetMatrix(ID3DXEffectCompiler *iface, D3DXHANDLE parameter, D3DXMATRIX *matrix) { - struct ID3DXEffectCompilerImpl *compiler = impl_from_ID3DXEffectCompiler(iface); + FIXME("iface %p, parameter %p, matrix %p stub!\n", iface, parameter, matrix);
- TRACE("iface %p, parameter %p, matrix %p.\n", iface, parameter, matrix); - - return d3dx9_base_effect_get_matrix(&compiler->base_effect, parameter, matrix); + return E_NOTIMPL; }
static HRESULT WINAPI ID3DXEffectCompilerImpl_SetMatrixArray(ID3DXEffectCompiler *iface, D3DXHANDLE parameter, const D3DXMATRIX *matrix, UINT count) { - struct ID3DXEffectCompilerImpl *compiler = impl_from_ID3DXEffectCompiler(iface); + FIXME("iface %p, parameter %p, matrix %p, count %u stub!\n", iface, parameter, matrix, count);
- TRACE("iface %p, parameter %p, matrix %p, count %u.\n", iface, parameter, matrix, count); - - return d3dx9_base_effect_set_matrix_array(&compiler->base_effect, parameter, matrix, count); + return E_NOTIMPL; }
static HRESULT WINAPI ID3DXEffectCompilerImpl_GetMatrixArray(ID3DXEffectCompiler *iface, D3DXHANDLE parameter, D3DXMATRIX *matrix, UINT count) { - struct ID3DXEffectCompilerImpl *compiler = impl_from_ID3DXEffectCompiler(iface); + FIXME("iface %p, parameter %p, matrix %p, count %u stub!\n", iface, parameter, matrix, count);
- TRACE("iface %p, parameter %p, matrix %p, count %u.\n", iface, parameter, matrix, count); - - return d3dx9_base_effect_get_matrix_array(&compiler->base_effect, parameter, matrix, count); + return E_NOTIMPL; }
static HRESULT WINAPI ID3DXEffectCompilerImpl_SetMatrixPointerArray(ID3DXEffectCompiler *iface, D3DXHANDLE parameter, const D3DXMATRIX **matrix, UINT count) { - struct ID3DXEffectCompilerImpl *compiler = impl_from_ID3DXEffectCompiler(iface); + FIXME("iface %p, parameter %p, matrix %p, count %u stub!\n", iface, parameter, matrix, count);
- TRACE("iface %p, parameter %p, matrix %p, count %u.\n", iface, parameter, matrix, count); - - return d3dx9_base_effect_set_matrix_pointer_array(&compiler->base_effect, parameter, matrix, count); + return E_NOTIMPL; }
static HRESULT WINAPI ID3DXEffectCompilerImpl_GetMatrixPointerArray(ID3DXEffectCompiler *iface, D3DXHANDLE parameter, D3DXMATRIX **matrix, UINT count) { - struct ID3DXEffectCompilerImpl *compiler = impl_from_ID3DXEffectCompiler(iface); + FIXME("iface %p, parameter %p, matrix %p, count %u stub!\n", iface, parameter, matrix, count);
- TRACE("iface %p, parameter %p, matrix %p, count %u.\n", iface, parameter, matrix, count); - - return d3dx9_base_effect_get_matrix_pointer_array(&compiler->base_effect, parameter, matrix, count); + return E_NOTIMPL; }
static HRESULT WINAPI ID3DXEffectCompilerImpl_SetMatrixTranspose(ID3DXEffectCompiler *iface, D3DXHANDLE parameter, const D3DXMATRIX *matrix) { - struct ID3DXEffectCompilerImpl *compiler = impl_from_ID3DXEffectCompiler(iface); + FIXME("iface %p, parameter %p, matrix %p stub!\n", iface, parameter, matrix);
- TRACE("iface %p, parameter %p, matrix %p.\n", iface, parameter, matrix); - - return d3dx9_base_effect_set_matrix_transpose(&compiler->base_effect, parameter, matrix); + return E_NOTIMPL; }
static HRESULT WINAPI ID3DXEffectCompilerImpl_GetMatrixTranspose(ID3DXEffectCompiler *iface, D3DXHANDLE parameter, D3DXMATRIX *matrix) { - struct ID3DXEffectCompilerImpl *compiler = impl_from_ID3DXEffectCompiler(iface); + FIXME("iface %p, parameter %p, matrix %p stub!\n", iface, parameter, matrix);
- TRACE("iface %p, parameter %p, matrix %p.\n", iface, parameter, matrix); - - return d3dx9_base_effect_get_matrix_transpose(&compiler->base_effect, parameter, matrix); + return E_NOTIMPL; }
static HRESULT WINAPI ID3DXEffectCompilerImpl_SetMatrixTransposeArray(ID3DXEffectCompiler *iface, D3DXHANDLE parameter, const D3DXMATRIX *matrix, UINT count) { - struct ID3DXEffectCompilerImpl *compiler = impl_from_ID3DXEffectCompiler(iface); - - TRACE("iface %p, parameter %p, matrix %p, count %u.\n", iface, parameter, matrix, count); + FIXME("iface %p, parameter %p, matrix %p, count %u stub!\n", iface, parameter, matrix, count);
- return d3dx9_base_effect_set_matrix_transpose_array(&compiler->base_effect, parameter, matrix, count); + return E_NOTIMPL; }
static HRESULT WINAPI ID3DXEffectCompilerImpl_GetMatrixTransposeArray(ID3DXEffectCompiler *iface, D3DXHANDLE parameter, D3DXMATRIX *matrix, UINT count) { - struct ID3DXEffectCompilerImpl *compiler = impl_from_ID3DXEffectCompiler(iface); - - TRACE("iface %p, parameter %p, matrix %p, count %u.\n", iface, parameter, matrix, count); + FIXME("iface %p, parameter %p, matrix %p, count %u stub!\n", iface, parameter, matrix, count);
- return d3dx9_base_effect_get_matrix_transpose_array(&compiler->base_effect, parameter, matrix, count); + return E_NOTIMPL; }
static HRESULT WINAPI ID3DXEffectCompilerImpl_SetMatrixTransposePointerArray(ID3DXEffectCompiler *iface, D3DXHANDLE parameter, const D3DXMATRIX **matrix, UINT count) { - struct ID3DXEffectCompilerImpl *compiler = impl_from_ID3DXEffectCompiler(iface); - - TRACE("iface %p, parameter %p, matrix %p, count %u.\n", iface, parameter, matrix, count); + FIXME("iface %p, parameter %p, matrix %p, count %u stub!\n", iface, parameter, matrix, count);
- return d3dx9_base_effect_set_matrix_transpose_pointer_array(&compiler->base_effect, parameter, matrix, count); + return E_NOTIMPL; }
static HRESULT WINAPI ID3DXEffectCompilerImpl_GetMatrixTransposePointerArray(ID3DXEffectCompiler *iface, D3DXHANDLE parameter, D3DXMATRIX **matrix, UINT count) { - struct ID3DXEffectCompilerImpl *compiler = impl_from_ID3DXEffectCompiler(iface); - - TRACE("iface %p, parameter %p, matrix %p, count %u.\n", iface, parameter, matrix, count); + FIXME("iface %p, parameter %p, matrix %p, count %u stub!\n", iface, parameter, matrix, count);
- return d3dx9_base_effect_get_matrix_transpose_pointer_array(&compiler->base_effect, parameter, matrix, count); + return E_NOTIMPL; }
static HRESULT WINAPI ID3DXEffectCompilerImpl_SetString(ID3DXEffectCompiler *iface, D3DXHANDLE parameter, const char *string) { - struct ID3DXEffectCompilerImpl *compiler = impl_from_ID3DXEffectCompiler(iface); - - TRACE("iface %p, parameter %p, string %s.\n", iface, parameter, debugstr_a(string)); + FIXME("iface %p, parameter %p, string %s stub!\n", iface, parameter, debugstr_a(string));
- return d3dx9_base_effect_set_string(&compiler->base_effect, parameter, string); + return E_NOTIMPL; }
static HRESULT WINAPI ID3DXEffectCompilerImpl_GetString(ID3DXEffectCompiler *iface, D3DXHANDLE parameter, const char **string) { - struct ID3DXEffectCompilerImpl *compiler = impl_from_ID3DXEffectCompiler(iface); - - TRACE("iface %p, parameter %p, string %p.\n", iface, parameter, string); + FIXME("iface %p, parameter %p, string %p stub!\n", iface, parameter, string);
- return d3dx9_base_effect_get_string(&compiler->base_effect, parameter, string); + return E_NOTIMPL; }
static HRESULT WINAPI ID3DXEffectCompilerImpl_SetTexture(struct ID3DXEffectCompiler *iface, D3DXHANDLE parameter, struct IDirect3DBaseTexture9 *texture) { - struct ID3DXEffectCompilerImpl *compiler = impl_from_ID3DXEffectCompiler(iface); - - TRACE("iface %p, parameter %p, texture %p.\n", iface, parameter, texture); + FIXME("iface %p, parameter %p, texture %p stub!\n", iface, parameter, texture);
- return d3dx9_base_effect_set_texture(&compiler->base_effect, parameter, texture); + return E_NOTIMPL; }
static HRESULT WINAPI ID3DXEffectCompilerImpl_GetTexture(struct ID3DXEffectCompiler *iface, D3DXHANDLE parameter, struct IDirect3DBaseTexture9 **texture) { - struct ID3DXEffectCompilerImpl *compiler = impl_from_ID3DXEffectCompiler(iface); - - TRACE("iface %p, parameter %p, texture %p.\n", iface, parameter, texture); + FIXME("iface %p, parameter %p, texture %p stub!\n", iface, parameter, texture);
- return d3dx9_base_effect_get_texture(&compiler->base_effect, parameter, texture); + return E_NOTIMPL; }
static HRESULT WINAPI ID3DXEffectCompilerImpl_GetPixelShader(ID3DXEffectCompiler *iface, D3DXHANDLE parameter, struct IDirect3DPixelShader9 **shader) { - struct ID3DXEffectCompilerImpl *compiler = impl_from_ID3DXEffectCompiler(iface); + FIXME("iface %p, parameter %p, shader %p stub!\n", iface, parameter, shader);
- TRACE("iface %p, parameter %p, shader %p.\n", iface, parameter, shader); - - return d3dx9_base_effect_get_pixel_shader(&compiler->base_effect, parameter, shader); + return E_NOTIMPL; }
static HRESULT WINAPI ID3DXEffectCompilerImpl_GetVertexShader(struct ID3DXEffectCompiler *iface, D3DXHANDLE parameter, struct IDirect3DVertexShader9 **shader) { - struct ID3DXEffectCompilerImpl *compiler = impl_from_ID3DXEffectCompiler(iface); - - TRACE("iface %p, parameter %p, shader %p.\n", iface, parameter, shader); + FIXME("iface %p, parameter %p, shader %p stub!\n", iface, parameter, shader);
- return d3dx9_base_effect_get_vertex_shader(&compiler->base_effect, parameter, shader); + return E_NOTIMPL; }
static HRESULT WINAPI ID3DXEffectCompilerImpl_SetArrayRange(ID3DXEffectCompiler *iface, D3DXHANDLE parameter, UINT start, UINT end) { - struct ID3DXEffectCompilerImpl *compiler = impl_from_ID3DXEffectCompiler(iface); + FIXME("iface %p, parameter %p, start %u, end %u stub!\n", iface, parameter, start, end);
- TRACE("iface %p, parameter %p, start %u, end %u.\n", iface, parameter, start, end); - - return d3dx9_base_effect_set_array_range(&compiler->base_effect, parameter, start, end); + return E_NOTIMPL; }
/*** ID3DXEffectCompiler methods ***/ static HRESULT WINAPI ID3DXEffectCompilerImpl_SetLiteral(ID3DXEffectCompiler *iface, D3DXHANDLE parameter, BOOL literal) { - struct ID3DXEffectCompilerImpl *This = impl_from_ID3DXEffectCompiler(iface); - - FIXME("iface %p, parameter %p, literal %u\n", This, parameter, literal); + FIXME("iface %p, parameter %p, literal %#x stub!\n", iface, parameter, literal);
return E_NOTIMPL; }
static HRESULT WINAPI ID3DXEffectCompilerImpl_GetLiteral(ID3DXEffectCompiler *iface, D3DXHANDLE parameter, BOOL *literal) { - struct ID3DXEffectCompilerImpl *This = impl_from_ID3DXEffectCompiler(iface); - - FIXME("iface %p, parameter %p, literal %p\n", This, parameter, literal); + FIXME("iface %p, parameter %p, literal %p stub!\n", iface, parameter, literal);
return E_NOTIMPL; } @@ -5219,9 +5097,7 @@ static HRESULT WINAPI ID3DXEffectCompilerImpl_GetLiteral(ID3DXEffectCompiler *if static HRESULT WINAPI ID3DXEffectCompilerImpl_CompileEffect(ID3DXEffectCompiler *iface, DWORD flags, ID3DXBuffer **effect, ID3DXBuffer **error_msgs) { - struct ID3DXEffectCompilerImpl *This = impl_from_ID3DXEffectCompiler(iface); - - FIXME("iface %p, flags %#x, effect %p, error_msgs %p stub\n", This, flags, effect, error_msgs); + FIXME("iface %p, flags %#x, effect %p, error_msgs %p stub!\n", iface, flags, effect, error_msgs);
return E_NOTIMPL; } @@ -5230,10 +5106,8 @@ static HRESULT WINAPI ID3DXEffectCompilerImpl_CompileShader(ID3DXEffectCompiler const char *target, DWORD flags, ID3DXBuffer **shader, ID3DXBuffer **error_msgs, ID3DXConstantTable **constant_table) { - struct ID3DXEffectCompilerImpl *This = impl_from_ID3DXEffectCompiler(iface); - - FIXME("iface %p, function %p, target %p, flags %#x, shader %p, error_msgs %p, constant_table %p stub\n", - This, function, target, flags, shader, error_msgs, constant_table); + FIXME("iface %p, function %p, target %s, flags %#x, shader %p, error_msgs %p, constant_table %p stub!\n", + iface, function, debugstr_a(target), flags, shader, error_msgs, constant_table);
return E_NOTIMPL; } @@ -6921,20 +6795,13 @@ static HRESULT d3dx9_effect_compiler_init(struct ID3DXEffectCompilerImpl *compil const char *data, SIZE_T data_size, const D3D_SHADER_MACRO *defines, ID3DInclude *include, UINT eflags, ID3DBlob **error_messages) { - HRESULT hr; - - TRACE("effect %p, data %p, data_size %lu\n", compiler, data, data_size); + TRACE("compiler %p, data %p, data_size %lu, defines %p, include %p, eflags %#x, error_messages %p.\n", + compiler, data, data_size, defines, include, eflags, error_messages);
compiler->ID3DXEffectCompiler_iface.lpVtbl = &ID3DXEffectCompiler_Vtbl; compiler->ref = 1;
- if (FAILED(hr = d3dx9_base_effect_init(&compiler->base_effect, data, data_size, defines, - include, eflags, error_messages, NULL, NULL, NULL))) - { - FIXME("Failed to parse effect, hr %#x.\n", hr); - free_effect_compiler(compiler); - return hr; - } + FIXME("ID3DXEffectCompiler implementation is only a stub.\n");
return D3D_OK; } diff --git a/dlls/d3dx9_36/tests/effect.c b/dlls/d3dx9_36/tests/effect.c index 0ae02315f4d..9693939a76b 100644 --- a/dlls/d3dx9_36/tests/effect.c +++ b/dlls/d3dx9_36/tests/effect.c @@ -388,7 +388,7 @@ static void test_create_effect_compiler(void) 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); - todo_wine ok(hr == D3D_OK, "Got result %x, expected %x (D3D_OK)\n", hr, D3D_OK); + ok(hr == D3D_OK, "Got result %x, expected %x (D3D_OK)\n", hr, D3D_OK); if (FAILED(hr)) { skip("D3DXCreateEffectCompiler failed, skipping test.\n");
Signed-off-by: Matteo Bruni mbruni@codeweavers.com --- v2: Fix extents check.
dlls/d3d8/device.c | 21 ++++++++++++++++++++- 1 file changed, 20 insertions(+), 1 deletion(-)
diff --git a/dlls/d3d8/device.c b/dlls/d3d8/device.c index 4fcad71451e..3a676b0fd4c 100644 --- a/dlls/d3d8/device.c +++ b/dlls/d3d8/device.c @@ -1638,10 +1638,30 @@ static HRESULT WINAPI d3d8_device_MultiplyTransform(IDirect3DDevice8 *iface, static HRESULT WINAPI d3d8_device_SetViewport(IDirect3DDevice8 *iface, const D3DVIEWPORT8 *viewport) { struct d3d8_device *device = impl_from_IDirect3DDevice8(iface); + struct wined3d_sub_resource_desc rt_desc; + struct wined3d_rendertarget_view *rtv; + struct d3d8_surface *surface; struct wined3d_viewport vp;
TRACE("iface %p, viewport %p.\n", iface, viewport);
+ wined3d_mutex_lock(); + if (!(rtv = wined3d_device_get_rendertarget_view(device->wined3d_device, 0))) + { + wined3d_mutex_unlock(); + return D3DERR_NOTFOUND; + } + surface = wined3d_rendertarget_view_get_sub_resource_parent(rtv); + wined3d_texture_get_sub_resource_desc(surface->wined3d_texture, surface->sub_resource_idx, &rt_desc); + + if (viewport->X > rt_desc.width || viewport->Width > rt_desc.width - viewport->X + || viewport->Y > rt_desc.height || viewport->Height > rt_desc.height - viewport->Y) + { + WARN("Invalid viewport, returning D3DERR_INVALIDCALL.\n"); + wined3d_mutex_unlock(); + return D3DERR_INVALIDCALL; + } + vp.x = viewport->X; vp.y = viewport->Y; vp.width = viewport->Width; @@ -1649,7 +1669,6 @@ static HRESULT WINAPI d3d8_device_SetViewport(IDirect3DDevice8 *iface, const D3D vp.min_z = viewport->MinZ; vp.max_z = viewport->MaxZ;
- wined3d_mutex_lock(); wined3d_device_set_viewport(device->wined3d_device, &vp); wined3d_mutex_unlock();
Signed-off-by: Henri Verbeet hverbeet@codeweavers.com
Signed-off-by: Matteo Bruni mbruni@codeweavers.com --- v2: Minor cleanups, add a couple additional RT sizes.
dlls/d3d8/tests/visual.c | 156 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 156 insertions(+)
diff --git a/dlls/d3d8/tests/visual.c b/dlls/d3d8/tests/visual.c index b64f08c8a15..c2a4abfc049 100644 --- a/dlls/d3d8/tests/visual.c +++ b/dlls/d3d8/tests/visual.c @@ -196,6 +196,45 @@ static D3DCOLOR get_surface_color(IDirect3DSurface8 *surface, UINT x, UINT y) return color; }
+static void check_rect(struct surface_readback *rb, RECT r, const char *message) +{ + LONG x_coords[2][2] = + { + {r.left - 1, r.left + 1}, + {r.right + 1, r.right - 1}, + }; + LONG y_coords[2][2] = + { + {r.top - 1, r.top + 1}, + {r.bottom + 1, r.bottom - 1} + }; + unsigned int i, j, x_side, y_side; + DWORD color; + LONG x, y; + + for (i = 0; i < 2; ++i) + { + for (j = 0; j < 2; ++j) + { + for (x_side = 0; x_side < 2; ++x_side) + { + for (y_side = 0; y_side < 2; ++y_side) + { + DWORD expected = (x_side == 1 && y_side == 1) ? 0xffffffff : 0xff000000; + + x = x_coords[i][x_side]; + y = y_coords[j][y_side]; + if (x < 0 || x >= 640 || y < 0 || y >= 480) + continue; + color = get_readback_color(rb, x, y); + ok(color == expected, "%s: Pixel (%d, %d) has color %08x, expected %08x.\n", + message, x, y, color, expected); + } + } + } + } +} + static IDirect3DDevice8 *create_device(IDirect3D8 *d3d, HWND device_window, HWND focus_window, BOOL windowed) { D3DPRESENT_PARAMETERS present_parameters = {0}; @@ -10132,6 +10171,122 @@ done: DestroyWindow(window); }
+static void test_viewport(void) +{ + static const struct + { + D3DVIEWPORT8 vp; + RECT expected_rect; + const char *message; + } + tests[] = + { + {{ 0, 0, 640, 480}, { 0, 120, 479, 359}, "Viewport (0, 0) - (640, 480)"}, + {{ 0, 0, 320, 240}, { 0, 60, 239, 179}, "Viewport (0, 0) - (320, 240)"}, + {{ 0, 0, 1280, 960}, { 0, 240, 639, 479}, "Viewport (0, 0) - (1280, 960)"}, + {{ 0, 0, 2000, 1600}, {-10, -10, -10, -10}, "Viewport (0, 0) - (2000, 1600)"}, + {{100, 100, 640, 480}, {100, 220, 579, 459}, "Viewport (100, 100) - (640, 480)"}, + {{ 0, 0, 8192, 8192}, {-10, -10, -10, -10}, "Viewport (0, 0) - (8192, 8192)"}, + }; + static const struct vec3 quad[] = + { + {-1.5f, -0.5f, 0.1f}, + {-1.5f, 0.5f, 0.1f}, + { 0.5f, -0.5f, 0.1f}, + { 0.5f, 0.5f, 0.1f}, + }; + static const struct vec2 rt_sizes[] = + { + {640, 480}, {1280, 960}, {320, 240}, {800, 600}, + }; + struct surface_readback rb; + IDirect3DDevice8 *device; + IDirect3DSurface8 *rt; + unsigned int i, j; + IDirect3D8 *d3d; + ULONG refcount; + HWND window; + HRESULT hr; + + window = create_window(); + d3d = Direct3DCreate8(D3D_SDK_VERSION); + ok(!!d3d, "Failed to create a D3D object.\n"); + if (!(device = create_device(d3d, window, window, TRUE))) + { + skip("Failed to create a D3D device, skipping tests.\n"); + goto done; + } + + hr = IDirect3DDevice8_SetRenderState(device, D3DRS_ZENABLE, D3DZB_FALSE); + ok(SUCCEEDED(hr), "Failed to disable depth test, hr %#x.\n", hr); + hr = IDirect3DDevice8_SetRenderState(device, D3DRS_LIGHTING, FALSE); + ok(SUCCEEDED(hr), "Failed to disable lighting, hr %#x.\n", hr); + + hr = IDirect3DDevice8_SetVertexShader(device, D3DFVF_XYZ); + ok(SUCCEEDED(hr), "Failed to set FVF, hr %#x.\n", hr); + + /* This crashes on Windows. */ + /* hr = IDirect3DDevice8_SetViewport(device, NULL); */ + + for (i = 0; i < sizeof(rt_sizes) / sizeof(rt_sizes[0]); ++i) + { + if (i) + { + hr = IDirect3DDevice8_CreateRenderTarget(device, rt_sizes[i].x, rt_sizes[i].y, + D3DFMT_A8R8G8B8, D3DMULTISAMPLE_NONE, TRUE, &rt); + ok(SUCCEEDED(hr), "Failed to create render target, hr %#x (i %u).\n", hr, i); + hr = IDirect3DDevice8_SetRenderTarget(device, rt, NULL); + ok(SUCCEEDED(hr), "Failed to set render target, hr %#x (i %u).\n", hr, i); + } + else + { + hr = IDirect3DDevice8_GetBackBuffer(device, 0, D3DBACKBUFFER_TYPE_MONO, &rt); + ok(SUCCEEDED(hr), "Failed to get backbuffer, hr %#x.\n", hr); + } + + for (j = 0; j < sizeof(tests) / sizeof(tests[0]); ++j) + { + hr = IDirect3DDevice8_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xff000000, 1.0f, 0); + ok(SUCCEEDED(hr), "Failed to clear, hr %#x (i %u, j %u).\n", hr, i, j); + + hr = IDirect3DDevice8_SetViewport(device, &tests[j].vp); + if (tests[j].vp.X + tests[j].vp.Width > rt_sizes[i].x + || tests[j].vp.Y + tests[j].vp.Height > rt_sizes[i].y) + { + ok(hr == D3DERR_INVALIDCALL, + "Setting the viewport returned unexpected hr %#x (i %u, j %u).\n", hr, i, j); + continue; + } + else + { + ok(SUCCEEDED(hr), "Failed to set the viewport, hr %#x (i %u, j %u).\n", hr, i, j); + } + + hr = IDirect3DDevice8_BeginScene(device); + ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x (i %u, j %u).\n", hr, i, j); + hr = IDirect3DDevice8_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad, sizeof(quad[0])); + ok(SUCCEEDED(hr), "Got unexpected hr %#x (i %u, j %u).\n", hr, i, j); + hr = IDirect3DDevice8_EndScene(device); + ok(SUCCEEDED(hr), "Failed to end scene, hr %#x (i %u, j %u).\n", hr, i, j); + + get_rt_readback(rt, &rb); + check_rect(&rb, tests[j].expected_rect, tests[j].message); + release_surface_readback(&rb); + } + + IDirect3DSurface8_Release(rt); + } + + hr = IDirect3DDevice8_Present(device, NULL, NULL, NULL, NULL); + ok(SUCCEEDED(hr), "Failed to present, hr %#x.\n", hr); + + refcount = IDirect3DDevice8_Release(device); + ok(!refcount, "Device has %u references left.\n", refcount); +done: + IDirect3D8_Release(d3d); + DestroyWindow(window); +} + START_TEST(visual) { D3DADAPTER_IDENTIFIER8 identifier; @@ -10204,4 +10359,5 @@ START_TEST(visual) test_backbuffer_resize(); test_drawindexedprimitiveup(); test_map_synchronisation(); + test_viewport(); }
Signed-off-by: Henri Verbeet hverbeet@codeweavers.com
Signed-off-by: Matteo Bruni mbruni@codeweavers.com --- v2: Fix extents check.
dlls/ddraw/device.c | 21 ++++++++++++++++++++- 1 file changed, 20 insertions(+), 1 deletion(-)
diff --git a/dlls/ddraw/device.c b/dlls/ddraw/device.c index 75e000aa096..38fcc00e6b6 100644 --- a/dlls/ddraw/device.c +++ b/dlls/ddraw/device.c @@ -5315,6 +5315,9 @@ static HRESULT WINAPI d3d_device7_Clear_FPUPreserve(IDirect3DDevice7 *iface, DWO static HRESULT d3d_device7_SetViewport(IDirect3DDevice7 *iface, D3DVIEWPORT7 *viewport) { struct d3d_device *device = impl_from_IDirect3DDevice7(iface); + struct wined3d_sub_resource_desc rt_desc; + struct wined3d_rendertarget_view *rtv; + struct ddraw_surface *surface; struct wined3d_viewport vp;
TRACE("iface %p, viewport %p.\n", iface, viewport); @@ -5322,6 +5325,23 @@ static HRESULT d3d_device7_SetViewport(IDirect3DDevice7 *iface, D3DVIEWPORT7 *vi if (!viewport) return DDERR_INVALIDPARAMS;
+ wined3d_mutex_lock(); + if (!(rtv = wined3d_device_get_rendertarget_view(device->wined3d_device, 0))) + { + wined3d_mutex_unlock(); + return DDERR_INVALIDCAPS; + } + surface = wined3d_rendertarget_view_get_sub_resource_parent(rtv); + wined3d_texture_get_sub_resource_desc(surface->wined3d_texture, surface->sub_resource_idx, &rt_desc); + + if (viewport->dwX > rt_desc.width || viewport->dwWidth > rt_desc.width - viewport->dwX + || viewport->dwY > rt_desc.height || viewport->dwHeight > rt_desc.height - viewport->dwY) + { + WARN("Invalid viewport, returning E_INVALIDARG.\n"); + wined3d_mutex_unlock(); + return E_INVALIDARG; + } + vp.x = viewport->dwX; vp.y = viewport->dwY; vp.width = viewport->dwWidth; @@ -5329,7 +5349,6 @@ static HRESULT d3d_device7_SetViewport(IDirect3DDevice7 *iface, D3DVIEWPORT7 *vi vp.min_z = viewport->dvMinZ; vp.max_z = viewport->dvMaxZ;
- wined3d_mutex_lock(); wined3d_device_set_viewport(device->wined3d_device, &vp); wined3d_mutex_unlock();
Signed-off-by: Matteo Bruni mbruni@codeweavers.com --- Generally the viewport is explicitly set again immediately after the SetRenderTarget() so you wouldn't notice the difference. The ddraw7 test_viewport() does a Clear() before that though and, without this patch, it crashes in surface_cpu_blt_colour_fill() when switching from the 1280x960 to the 320x240 RT.
I guess another option is to fix this in wined3d (instead OR in addition to this).
dlls/ddraw/device.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/dlls/ddraw/device.c b/dlls/ddraw/device.c index 38fcc00e6b6..6858a1bb645 100644 --- a/dlls/ddraw/device.c +++ b/dlls/ddraw/device.c @@ -1818,7 +1818,7 @@ static HRESULT d3d_device_set_render_target(struct d3d_device *device, }
if (FAILED(hr = wined3d_device_set_rendertarget_view(device->wined3d_device, - 0, ddraw_surface_get_rendertarget_view(target), FALSE))) + 0, ddraw_surface_get_rendertarget_view(target), TRUE))) return hr;
IUnknown_AddRef(rt_iface);
On 22 March 2018 at 21:43, Matteo Bruni mbruni@codeweavers.com wrote:
Signed-off-by: Matteo Bruni mbruni@codeweavers.com
Generally the viewport is explicitly set again immediately after the SetRenderTarget() so you wouldn't notice the difference. The ddraw7 test_viewport() does a Clear() before that though and, without this patch, it crashes in surface_cpu_blt_colour_fill() when switching from the 1280x960 to the 320x240 RT.
I guess another option is to fix this in wined3d (instead OR in addition to this).
dlls/ddraw/device.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
This causes test failures here:
../../../../../src/wine-git/tools/runtest -q -P wine -T ../../.. -M ddraw.dll -p ddraw_test.exe.so d3d && touch d3d.ok d3d.c:2554: Test failed: vp.dwX is 0, expected 10 d3d.c:2555: Test failed: vp.dwY is 0, expected 10 d3d.c:2556: Test failed: vp.dwWidth is 64, expected 246 d3d.c:2557: Test failed: vp.dwHeight is 64, expected 246 d3d.c:2558: Test failed: vp.dvMinZ is 0.000000, expected 0.25 d3d.c:2559: Test failed: vp.dvMaxZ is 1.000000, expected 0.75 d3d.c:2582: Test failed: vp.dwWidth is 256, expected 64 d3d.c:2583: Test failed: vp.dwHeight is 256, expected 64 d3d.c:2595: Test failed: vp.dwWidth is 256, expected 64 d3d.c:2596: Test failed: vp.dwHeight is 256, expected 64 Makefile:193: recipe for target 'd3d.ok' failed make: *** [d3d.ok] Error 10
Signed-off-by: Matteo Bruni mbruni@codeweavers.com --- v2: Properly attach a depth buffer to the offscreen surfaces, some minor cleanups, add a couple more RT sizes (actually 320x240 after 1280x960 crashed without the d3d_device_set_render_target() fix).
dlls/ddraw/tests/ddraw7.c | 177 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 177 insertions(+)
diff --git a/dlls/ddraw/tests/ddraw7.c b/dlls/ddraw/tests/ddraw7.c index 3f433a6765b..ccac01c5f89 100644 --- a/dlls/ddraw/tests/ddraw7.c +++ b/dlls/ddraw/tests/ddraw7.c @@ -280,6 +280,45 @@ static D3DCOLOR get_surface_color(IDirectDrawSurface7 *surface, UINT x, UINT y) return color; }
+static void check_rect(IDirectDrawSurface7 *surface, RECT r, const char *message) +{ + LONG x_coords[2][2] = + { + {r.left - 1, r.left + 1}, + {r.right + 1, r.right - 1}, + }; + LONG y_coords[2][2] = + { + {r.top - 1, r.top + 1}, + {r.bottom + 1, r.bottom - 1} + }; + unsigned int i, j, x_side, y_side; + DWORD color; + LONG x, y; + + for (i = 0; i < 2; ++i) + { + for (j = 0; j < 2; ++j) + { + for (x_side = 0; x_side < 2; ++x_side) + { + for (y_side = 0; y_side < 2; ++y_side) + { + DWORD expected = (x_side == 1 && y_side == 1) ? 0x00ffffff : 0x00000000; + + x = x_coords[i][x_side]; + y = y_coords[j][y_side]; + if (x < 0 || x >= 640 || y < 0 || y >= 480) + continue; + color = get_surface_color(surface, x, y); + ok(color == expected, "%s: Pixel (%d, %d) has color %08x, expected %08x.\n", + message, x, y, color, expected); + } + } + } + } +} + static HRESULT CALLBACK enum_z_fmt(DDPIXELFORMAT *format, void *ctx) { DDPIXELFORMAT *z_fmt = ctx; @@ -14095,6 +14134,143 @@ static void test_enum_surfaces(void) IDirectDraw7_Release(ddraw); }
+static void test_viewport(void) +{ + static struct + { + D3DVIEWPORT7 vp; + RECT expected_rect; + const char *message; + } + tests[] = + { + {{ 0, 0, 640, 480}, { 0, 120, 479, 359}, "Viewport (0, 0) - (640, 480)"}, + {{ 0, 0, 320, 240}, { 0, 60, 239, 179}, "Viewport (0, 0) - (320, 240)"}, + {{ 0, 0, 1280, 960}, { 0, 240, 639, 479}, "Viewport (0, 0) - (1280, 960)"}, + {{ 0, 0, 2000, 1600}, {-10, -10, -10, -10}, "Viewport (0, 0) - (2000, 1600)"}, + {{100, 100, 640, 480}, {100, 220, 579, 459}, "Viewport (100, 100) - (640, 480)"}, + {{ 0, 0, 8192, 8192}, {-10, -10, -10, -10}, "Viewport (0, 0) - (8192, 8192)"}, + }; + static struct vec3 quad[] = + { + {-1.5f, -0.5f, 0.1f}, + {-1.5f, 0.5f, 0.1f}, + { 0.5f, -0.5f, 0.1f}, + { 0.5f, 0.5f, 0.1f}, + }; + static const struct vec2 rt_sizes[] = + { + {640, 480}, {1280, 960}, {320, 240}, {800, 600}, + }; + IDirectDrawSurface7 *rt, *ds; + DDSURFACEDESC2 surface_desc; + IDirect3DDevice7 *device; + IDirectDraw7 *ddraw; + DDPIXELFORMAT z_fmt; + unsigned int i, j; + IDirect3D7 *d3d; + ULONG refcount; + HWND window; + HRESULT hr; + + window = CreateWindowA("static", "d3d7_test", WS_OVERLAPPEDWINDOW, + 0, 0, 640, 480, 0, 0, 0, 0); + if (!(device = create_device(window, DDSCL_NORMAL))) + { + skip("Failed to create a 3D device, skipping test.\n"); + DestroyWindow(window); + return; + } + + hr = IDirect3DDevice7_GetDirect3D(device, &d3d); + ok(SUCCEEDED(hr), "Failed to get Direct3D7 interface, hr %#x.\n", hr); + hr = IDirect3D7_QueryInterface(d3d, &IID_IDirectDraw7, (void **)&ddraw); + ok(SUCCEEDED(hr), "Failed to get ddraw interface, hr %#x.\n", hr); + IDirect3D7_Release(d3d); + + hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_ZENABLE, D3DZB_FALSE); + ok(SUCCEEDED(hr), "Failed to disable depth test, hr %#x.\n", hr); + hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_LIGHTING, FALSE); + ok(SUCCEEDED(hr), "Failed to disable lighting, hr %#x.\n", hr); + + hr = IDirect3DDevice7_SetViewport(device, NULL); + ok(hr == E_INVALIDARG, "Setting NULL viewport data returned unexpected hr %#x.\n", hr); + + ds = get_depth_stencil(device); + memset(&surface_desc, 0, sizeof(surface_desc)); + surface_desc.dwSize = sizeof(surface_desc); + hr = IDirectDrawSurface7_GetSurfaceDesc(ds, &surface_desc); + z_fmt = U4(surface_desc).ddpfPixelFormat; + + for (i = 0; i < sizeof(rt_sizes) / sizeof(rt_sizes[0]); ++i) + { + if (i) + { + memset(&surface_desc, 0, sizeof(surface_desc)); + surface_desc.dwSize = sizeof(surface_desc); + surface_desc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT; + surface_desc.dwWidth = rt_sizes[i].x; + surface_desc.dwHeight = rt_sizes[i].y; + surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | DDSCAPS_3DDEVICE; + hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &rt, NULL); + ok(SUCCEEDED(hr), "Failed to create render target, hr %#x (i %u).\n", hr, i); + + surface_desc.dwFlags = DDSD_CAPS | DDSD_PIXELFORMAT | DDSD_WIDTH | DDSD_HEIGHT; + surface_desc.ddsCaps.dwCaps = DDSCAPS_ZBUFFER; + U4(surface_desc).ddpfPixelFormat = z_fmt; + hr = IDirectDraw7_CreateSurface(ddraw, &surface_desc, &ds, NULL); + ok(SUCCEEDED(hr), "Failed to create depth buffer, hr %#x (i %u).\n", hr, i); + hr = IDirectDrawSurface7_AddAttachedSurface(rt, ds); + ok(SUCCEEDED(hr), "Failed to attach depth buffer, hr %#x (i %u).\n", hr, i); + + hr = IDirect3DDevice7_SetRenderTarget(device, rt, 0); + ok(SUCCEEDED(hr), "Failed to set render target, hr %#x (i %u).\n", hr, i); + } + else + { + hr = IDirect3DDevice7_GetRenderTarget(device, &rt); + ok(SUCCEEDED(hr), "Failed to get render target, hr %#x.\n", hr); + } + + for (j = 0; j < sizeof(tests) / sizeof(tests[0]); ++j) + { + hr = IDirect3DDevice7_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xff000000, 1.0f, 0); + ok(SUCCEEDED(hr), "Failed to clear, hr %#x (i %u, j %u).\n", hr, i, j); + + hr = IDirect3DDevice7_SetViewport(device, &tests[j].vp); + if (tests[j].vp.dwX + tests[j].vp.dwWidth > rt_sizes[i].x + || tests[j].vp.dwY + tests[j].vp.dwHeight > rt_sizes[i].y) + { + ok(hr == E_INVALIDARG, "Setting the viewport returned unexpected hr %#x (i %u, j %u).\n", hr, i, j); + continue; + } + else + { + ok(SUCCEEDED(hr), "Failed to set the viewport, hr %#x (i %u, j %u).\n", hr, i, j); + } + + hr = IDirect3DDevice7_BeginScene(device); + ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x (i %u, j %u).\n", hr, i, j); + hr = IDirect3DDevice7_DrawPrimitive(device, D3DPT_TRIANGLESTRIP, D3DFVF_XYZ, quad, 4, 0); + ok(SUCCEEDED(hr), "Got unexpected hr %#x (i %u, j %u).\n", hr, i, j); + hr = IDirect3DDevice7_EndScene(device); + ok(SUCCEEDED(hr), "Failed to end scene, hr %#x (i %u, j %u).\n", hr, i, j); + + check_rect(rt, tests[j].expected_rect, tests[j].message); + } + + hr = IDirectDrawSurface7_DeleteAttachedSurface(rt, 0, ds); + ok(SUCCEEDED(hr), "Failed to detach surface, hr %#x (i %u).\n", hr, i); + IDirectDrawSurface7_Release(ds); + + IDirectDrawSurface7_Release(rt); + } + + refcount = IDirect3DDevice7_Release(device); + ok(!refcount, "Device has %u references left.\n", refcount); + DestroyWindow(window); +} + START_TEST(ddraw7) { DDDEVICEIDENTIFIER2 identifier; @@ -14229,4 +14405,5 @@ START_TEST(ddraw7) test_depth_readback(); test_clear(); test_enum_surfaces(); + test_viewport(); }