Module: wine Branch: master Commit: 1b3376982d3019b09080bb55a1ec7531242b3f6e URL: http://source.winehq.org/git/wine.git/?a=commit;h=1b3376982d3019b09080bb55a1...
Author: Matteo Bruni matteo.mystral@gmail.com Date: Wed Jul 28 17:32:42 2010 +0200
d3dx9: Implement D3DXAssembleShaderFromFile.
---
dlls/d3dx9_36/shader.c | 98 +++++++++++++++++++++++++++++++++++++++++++-- dlls/d3dx9_36/tests/asm.c | 79 +++++++++++++++++++++++++----------- 2 files changed, 148 insertions(+), 29 deletions(-)
diff --git a/dlls/d3dx9_36/shader.c b/dlls/d3dx9_36/shader.c index ba23f07..f5ba7aa 100644 --- a/dlls/d3dx9_36/shader.c +++ b/dlls/d3dx9_36/shader.c @@ -309,8 +309,8 @@ static char *wpp_lookup_mem(const char *filename, const char *parent_name, }
path = malloc(strlen(filename) + 1); - if(!path) return NULL; - memcpy(path, filename, strlen(filename) + 1); + if(path) + memcpy(path, filename, strlen(filename) + 1); return path; }
@@ -636,6 +636,79 @@ cleanup: return hr; }
+/* 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, + LPCSTR filename, LPCVOID parent_data, + LPCVOID *data, UINT *bytes) { + const char *p, *parent_name = ""; + char *pathname = NULL; + char **buffer = NULL; + HANDLE file; + UINT size; + + if(parent_data != NULL) + parent_name = *((const char **)parent_data - 1); + + TRACE("Looking up for include file %s, parent %s\n", debugstr_a(filename), debugstr_a(parent_name)); + + if ((p = strrchr(parent_name, '\')) || (p = strrchr(parent_name, '/'))) p++; + else p = parent_name; + pathname = HeapAlloc(GetProcessHeap(), 0, (p - parent_name) + strlen(filename) + 1); + if(!pathname) + return HRESULT_FROM_WIN32(GetLastError()); + + memcpy(pathname, parent_name, p - parent_name); + strcpy(pathname + (p - parent_name), filename); + + file = CreateFileA(pathname, GENERIC_READ, FILE_SHARE_READ, 0, OPEN_EXISTING, 0, 0); + if(file == INVALID_HANDLE_VALUE) + goto error; + + TRACE("Include file found at pathname = %s\n", debugstr_a(pathname)); + + size = GetFileSize(file, NULL); + if(size == INVALID_FILE_SIZE) + goto error; + + buffer = HeapAlloc(GetProcessHeap(), 0, size + sizeof(char *)); + if(!buffer) + goto error; + *buffer = pathname; + if(!ReadFile(file, buffer + 1, size, bytes, NULL)) + goto error; + + *data = buffer + 1; + + CloseHandle(file); + return S_OK; + +error: + CloseHandle(file); + HeapFree(GetProcessHeap(), 0, pathname); + HeapFree(GetProcessHeap(), 0, buffer); + return HRESULT_FROM_WIN32(GetLastError()); +} + +static HRESULT WINAPI d3dincludefromfile_close(ID3DXInclude *iface, LPCVOID data) { + HeapFree(GetProcessHeap(), 0, *((char **)data - 1)); + HeapFree(GetProcessHeap(), 0, (char **)data - 1); + return S_OK; +} + +static const struct ID3DXIncludeVtbl D3DXInclude_Vtbl = { + d3dincludefromfile_open, + d3dincludefromfile_close +}; + +struct D3DXIncludeImpl { + const ID3DXIncludeVtbl *lpVtbl; +}; + HRESULT WINAPI D3DXAssembleShaderFromFileA(LPCSTR filename, CONST D3DXMACRO* defines, LPD3DXINCLUDE include, @@ -667,8 +740,25 @@ HRESULT WINAPI D3DXAssembleShaderFromFileW(LPCWSTR filename, LPD3DXBUFFER* shader, LPD3DXBUFFER* error_messages) { - FIXME("(%s, %p, %p, %x, %p, %p): stub\n", debugstr_w(filename), defines, include, flags, shader, error_messages); - return D3DERR_INVALIDCALL; + void *buffer; + DWORD len; + HRESULT hr; + struct D3DXIncludeImpl includefromfile; + + if(FAILED(map_view_of_file(filename, &buffer, &len))) + return D3DXERR_INVALIDDATA; + + if(!include) + { + includefromfile.lpVtbl = &D3DXInclude_Vtbl; + include = (LPD3DXINCLUDE)&includefromfile; + } + + hr = D3DXAssembleShader(buffer, len, defines, include, flags, + shader, error_messages); + + UnmapViewOfFile(buffer); + return hr; }
HRESULT WINAPI D3DXAssembleShaderFromResourceA(HMODULE module, diff --git a/dlls/d3dx9_36/tests/asm.c b/dlls/d3dx9_36/tests/asm.c index 388e74e..9c8d2e0 100644 --- a/dlls/d3dx9_36/tests/asm.c +++ b/dlls/d3dx9_36/tests/asm.c @@ -1561,6 +1561,19 @@ static void assembleshader_test(void) { "#include "incl2.vsh"\n" "mov REGISTER, v0\n" }; + const char testshader3[] = { + "#include "include/incl3.vsh"\n" + "mov REGISTER, v0\n" + }; + const char testincl3[] = { + "#include "incl4.vsh"\n" + }; + const char testincl4_ok[] = { + "vs.1.1\n" + }; + const char testincl4_wrong[] = { + "#error "wrong include"\n" + }; HRESULT hr; LPD3DXBUFFER shader, messages; D3DXMACRO defines[] = { @@ -1575,7 +1588,7 @@ static void assembleshader_test(void) { } }; struct D3DXIncludeImpl include; - HRESULT shader_vsh_res, incl_vsh_res; + HRESULT shader_vsh_res;
/* pDefines test */ shader = NULL; @@ -1649,25 +1662,22 @@ static void assembleshader_test(void) { } if(shader) ID3DXBuffer_Release(shader);
- todo_wine { - shader_vsh_res = create_file("shader.vsh", testshader, sizeof(testshader)); if(SUCCEEDED(shader_vsh_res)) { - incl_vsh_res = create_file("incl.vsh", testincl, sizeof(testincl)); - if(SUCCEEDED(incl_vsh_res)) { - /* D3DXAssembleShaderFromFile + #include test */ - shader = NULL; - messages = NULL; - hr = D3DXAssembleShaderFromFileA("shader.vsh", - 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); - } else skip("Couldn't create "incl.vsh"\n"); + create_file("incl.vsh", testincl, sizeof(testincl)); + + /* D3DXAssembleShaderFromFile + #include test */ + shader = NULL; + messages = NULL; + hr = D3DXAssembleShaderFromFileA("shader.vsh", + 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; @@ -1681,9 +1691,27 @@ static void assembleshader_test(void) { ID3DXBuffer_Release(messages); } if(shader) ID3DXBuffer_Release(shader); - } else skip("Couldn't create "shader.vsh"\n");
- } /* todo_wine */ + create_file("shader3.vsh", testshader3, sizeof(testshader3)); + create_file("incl4.vsh", testincl4_wrong, sizeof(testincl4_wrong)); + if(CreateDirectoryA("include", NULL)) { + create_file("include/incl3.vsh", testincl3, sizeof(testincl3)); + create_file("include/incl4.vsh", testincl4_ok, sizeof(testincl4_ok)); + + /* path search #include test */ + shader = NULL; + messages = NULL; + hr = D3DXAssembleShaderFromFileA("shader3.vsh", 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"); + } else skip("Couldn't create "shader.vsh"\n");
/* NULL shader tests */ shader = NULL; @@ -1698,8 +1726,6 @@ static void assembleshader_test(void) { } if(shader) ID3DXBuffer_Release(shader);
- todo_wine { - shader = NULL; messages = NULL; hr = D3DXAssembleShaderFromFileA("nonexistent.vsh", @@ -1714,8 +1740,6 @@ static void assembleshader_test(void) { } if(shader) ID3DXBuffer_Release(shader);
- } /* end of todo_wine */ - /* D3DXAssembleShaderFromResource test */ shader = NULL; messages = NULL; @@ -1745,7 +1769,12 @@ static void assembleshader_test(void) { /* cleanup */ if(SUCCEEDED(shader_vsh_res)) { DeleteFileA("shader.vsh"); - if(SUCCEEDED(incl_vsh_res)) DeleteFileA("incl.vsh"); + DeleteFileA("incl.vsh"); + DeleteFileA("shader3.vsh"); + DeleteFileA("incl4.vsh"); + DeleteFileA("include/incl3.vsh"); + DeleteFileA("include/incl4.vsh"); + RemoveDirectoryA("include"); } }