[2/2] d3dx9: Implement D3DXAssembleShaderFromFile. [try 2]
Matteo Bruni
matteo.mystral at gmail.com
Wed Jul 28 11:01:28 CDT 2010
Try 2: don't cast away const.
-------------- next part --------------
From 01c7c50542fdedcd415f4300d5cfe5f3d258fccb Mon Sep 17 00:00:00 2001
From: Matteo Bruni <matteo.mystral at gmail.com>
Date: Wed, 28 Jul 2010 17:32:42 +0200
Subject: 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 4d06bbf..06afaf4 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");
}
}
--
1.7.1
More information about the wine-patches
mailing list