[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