[3/3] d3dx9: D3DXPreprocessShader implementation with tests.

Matteo Bruni matteo.mystral at gmail.com
Thu Sep 9 12:23:27 CDT 2010


-------------- next part --------------
From ea736401edeba45a501f58656561775212f89352 Mon Sep 17 00:00:00 2001
From: Matteo Bruni <matteo.mystral at gmail.com>
Date: Thu, 9 Sep 2010 18:41:39 +0200
Subject: d3dx9: D3DXPreprocessShader implementation with tests.

---
 dlls/d3dx9_36/d3dx9_36.spec |   10 ++--
 dlls/d3dx9_36/shader.c      |  117 +++++++++++++++++++++++++++++++++++++-
 dlls/d3dx9_36/tests/asm.c   |  132 +++++++++++++++++++++++++++++++++++++++++++
 include/d3dx9shader.h       |   33 +++++++++++
 4 files changed, 286 insertions(+), 6 deletions(-)

diff --git a/dlls/d3dx9_36/d3dx9_36.spec b/dlls/d3dx9_36/d3dx9_36.spec
index 9c84dbf..0901b48 100644
--- a/dlls/d3dx9_36/d3dx9_36.spec
+++ b/dlls/d3dx9_36/d3dx9_36.spec
@@ -236,11 +236,11 @@
 @ stdcall D3DXPlaneNormalize(ptr ptr)
 @ stdcall D3DXPlaneTransform(ptr ptr ptr)
 @ stdcall D3DXPlaneTransformArray(ptr long ptr long ptr long)
-@ stub D3DXPreprocessShader
-@ stub D3DXPreprocessShaderFromFileA
-@ stub D3DXPreprocessShaderFromFileW
-@ stub D3DXPreprocessShaderFromResourceA
-@ stub D3DXPreprocessShaderFromResourceW
+@ stdcall D3DXPreprocessShader(ptr long ptr ptr ptr ptr)
+@ stdcall D3DXPreprocessShaderFromFileA(str ptr ptr ptr ptr)
+@ stdcall D3DXPreprocessShaderFromFileW(wstr ptr ptr ptr ptr)
+@ stdcall D3DXPreprocessShaderFromResourceA(long str ptr ptr ptr ptr)
+@ stdcall D3DXPreprocessShaderFromResourceW(long wstr ptr ptr ptr ptr)
 @ stdcall D3DXQuaternionBaryCentric(ptr ptr ptr ptr float float)
 @ stdcall D3DXQuaternionExp(ptr ptr)
 @ stdcall D3DXQuaternionInverse(ptr ptr)
diff --git a/dlls/d3dx9_36/shader.c b/dlls/d3dx9_36/shader.c
index a3648c2..7361e85 100644
--- a/dlls/d3dx9_36/shader.c
+++ b/dlls/d3dx9_36/shader.c
@@ -446,7 +446,7 @@ HRESULT WINAPI D3DXCompileShaderFromFileW(LPCWSTR filename,
     }
     WideCharToMultiByte(CP_ACP, 0, filename, -1, filename_a, filename_len, NULL, NULL);
 
-    hr = D3DCompile(buffer, len, filename_a, (D3D_SHADER_MACRO *)defines,
+    hr = D3DCompile(buffer, len, filename_a, (const D3D_SHADER_MACRO *)defines,
                     (ID3DInclude *)include, entrypoint, profile, flags, 0,
                     (ID3DBlob **)shader, (ID3DBlob **)error_messages);
 
@@ -505,6 +505,121 @@ HRESULT WINAPI D3DXCompileShaderFromResourceW(HMODULE module,
                              flags, shader, error_messages, constant_table);
 }
 
+HRESULT WINAPI D3DXPreprocessShader(LPCSTR data,
+                                    UINT data_len,
+                                    CONST D3DXMACRO* defines,
+                                    LPD3DXINCLUDE include,
+                                    LPD3DXBUFFER* shader,
+                                    LPD3DXBUFFER* error_messages)
+{
+    TRACE("Forward to D3DPreprocess\n");
+    return D3DPreprocess(data, data_len, NULL,
+                         (const D3D_SHADER_MACRO *)defines, (ID3DInclude *)include,
+                         (ID3DBlob **)shader, (ID3DBlob **)error_messages);
+}
+
+HRESULT WINAPI D3DXPreprocessShaderFromFileA(LPCSTR filename,
+                                             CONST D3DXMACRO* defines,
+                                             LPD3DXINCLUDE include,
+                                             LPD3DXBUFFER* shader,
+                                             LPD3DXBUFFER* error_messages)
+{
+    WCHAR *filename_w = NULL;
+    DWORD len;
+    HRESULT ret;
+
+    if (!filename) return D3DXERR_INVALIDDATA;
+
+    len = MultiByteToWideChar(CP_ACP, 0, filename, -1, NULL, 0);
+    filename_w = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
+    if (!filename_w) return E_OUTOFMEMORY;
+    MultiByteToWideChar(CP_ACP, 0, filename, -1, filename_w, len);
+
+    ret = D3DXPreprocessShaderFromFileW(filename_w, defines, include, shader, error_messages);
+
+    HeapFree(GetProcessHeap(), 0, filename_w);
+    return ret;
+}
+
+HRESULT WINAPI D3DXPreprocessShaderFromFileW(LPCWSTR filename,
+                                             CONST D3DXMACRO* defines,
+                                             LPD3DXINCLUDE include,
+                                             LPD3DXBUFFER* shader,
+                                             LPD3DXBUFFER* error_messages)
+{
+    void *buffer;
+    DWORD len, filename_len;
+    HRESULT hr;
+    struct D3DXIncludeImpl includefromfile;
+    char *filename_a;
+
+    if (FAILED(map_view_of_file(filename, &buffer, &len)))
+        return D3DXERR_INVALIDDATA;
+
+    if (!include)
+    {
+        includefromfile.lpVtbl = &D3DXInclude_Vtbl;
+        include = (LPD3DXINCLUDE)&includefromfile;
+    }
+
+    filename_len = WideCharToMultiByte(CP_ACP, 0, filename, -1, NULL, 0, NULL, NULL);
+    filename_a = HeapAlloc(GetProcessHeap(), 0, filename_len * sizeof(char));
+    if (!filename_a)
+    {
+        UnmapViewOfFile(buffer);
+        return E_OUTOFMEMORY;
+    }
+    WideCharToMultiByte(CP_ACP, 0, filename, -1, filename_a, filename_len, NULL, NULL);
+
+    hr = D3DPreprocess(buffer, len, NULL,
+                       (const D3D_SHADER_MACRO *)defines,
+                       (ID3DInclude *) include,
+                       (ID3DBlob **)shader, (ID3DBlob **)error_messages);
+
+    HeapFree(GetProcessHeap(), 0, filename_a);
+    UnmapViewOfFile(buffer);
+    return hr;
+}
+
+HRESULT WINAPI D3DXPreprocessShaderFromResourceA(HMODULE module,
+                                                 LPCSTR resource,
+                                                 CONST D3DXMACRO* defines,
+                                                 LPD3DXINCLUDE include,
+                                                 LPD3DXBUFFER* shader,
+                                                 LPD3DXBUFFER* error_messages)
+{
+    HRSRC res;
+    const char *buffer;
+    DWORD len;
+
+    if (!(res = FindResourceA(module, resource, (LPCSTR)RT_RCDATA)))
+        return D3DXERR_INVALIDDATA;
+    if (FAILED(load_resource_into_memory(module, res, (LPVOID *)&buffer, &len)))
+        return D3DXERR_INVALIDDATA;
+    return D3DXPreprocessShader(buffer, len, defines, include,
+                                shader, error_messages);
+}
+
+HRESULT WINAPI D3DXPreprocessShaderFromResourceW(HMODULE module,
+                                                 LPCWSTR resource,
+                                                 CONST D3DXMACRO* defines,
+                                                 LPD3DXINCLUDE include,
+                                                 LPD3DXBUFFER* shader,
+                                                 LPD3DXBUFFER* error_messages)
+{
+    HRSRC res;
+    const char *buffer;
+    DWORD len;
+
+    if (!(res = FindResourceW(module, resource, (const WCHAR *)RT_RCDATA)))
+        return D3DXERR_INVALIDDATA;
+    if (FAILED(load_resource_into_memory(module, res, (void **)&buffer, &len)))
+        return D3DXERR_INVALIDDATA;
+    return D3DXPreprocessShader(buffer, len, defines, include,
+                                shader, error_messages);
+
+}
+
 static const struct ID3DXConstantTableVtbl ID3DXConstantTable_Vtbl;
 
 typedef struct ID3DXConstantTableImpl {
diff --git a/dlls/d3dx9_36/tests/asm.c b/dlls/d3dx9_36/tests/asm.c
index 4d319ed..f6a0cb2 100644
--- a/dlls/d3dx9_36/tests/asm.c
+++ b/dlls/d3dx9_36/tests/asm.c
@@ -325,7 +325,139 @@ static void assembleshader_test(void) {
     }
 }
 
+static void d3dxpreprocess_test(void) {
+    const char testincl[] = {
+        "#define REGISTER r0\n"
+        "vs.1.1\n"
+    };
+    const char testshader[] = {
+        "#include \"incl.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[] = {
+        "#define REGISTER r0\n"
+        "vs.1.1\n"
+    };
+    const char testincl4_wrong[] = {
+        "#error \"wrong include\"\n"
+    };
+    HRESULT hr;
+    LPD3DXBUFFER shader, messages;
+    HRESULT shader_vsh_res;
+    struct D3DXIncludeImpl include = {&D3DXInclude_Vtbl};
+
+    shader_vsh_res = create_file("shader.vsh", testshader, sizeof(testshader) - 1);
+    if(SUCCEEDED(shader_vsh_res)) {
+        create_file("incl.vsh", testincl, sizeof(testincl) - 1);
+        create_file("shader3.vsh", testshader3, sizeof(testshader3) - 1);
+        create_file("incl4.vsh", testincl4_wrong, sizeof(testincl4_wrong) - 1);
+        if(CreateDirectoryA("include", NULL)) {
+            create_file("include/incl3.vsh", testincl3, sizeof(testincl3) - 1);
+            create_file("include/incl4.vsh", testincl4_ok, sizeof(testincl4_ok) - 1);
+
+            /* path search #include test */
+            shader = NULL;
+            messages = NULL;
+            hr = D3DXPreprocessShaderFromFileA("shader3.vsh", NULL, NULL,
+                                               &shader, &messages);
+            ok(hr == D3D_OK, "D3DXPreprocessShaderFromFile path search test failed with error 0x%x - %d\n", hr, hr & 0x0000FFFF);
+            if(messages) {
+                trace("D3DXPreprocessShaderFromFile path search messages:\n%s", (char *)ID3DXBuffer_GetBufferPointer(messages));
+                ID3DXBuffer_Release(messages);
+            }
+            if(shader) ID3DXBuffer_Release(shader);
+        } else skip("Couldn't create \"include\" directory\n");
+
+        /* D3DXPreprocessShaderFromFile + #include test */
+        shader = NULL;
+        messages = NULL;
+        hr = D3DXPreprocessShaderFromFileA("shader.vsh",
+                                           NULL, NULL,
+                                           &shader, &messages);
+        ok(hr == D3D_OK, "D3DXPreprocessShaderFromFile test failed with error 0x%x - %d\n", hr, hr & 0x0000FFFF);
+        if(messages) {
+            trace("D3DXPreprocessShader messages:\n%s", (char *)ID3DXBuffer_GetBufferPointer(messages));
+            ID3DXBuffer_Release(messages);
+        }
+        if(shader) ID3DXBuffer_Release(shader);
+
+        /* D3DXPreprocessShaderFromFile + pInclude test */
+        shader = NULL;
+        messages = NULL;
+        hr = D3DXPreprocessShaderFromFileA("shader.vsh",
+                                           NULL, (LPD3DXINCLUDE)&include,
+                                           &shader, &messages);
+        ok(hr == D3D_OK, "D3DXPreprocessShaderFromFile + pInclude test failed with error 0x%x - %d\n", hr, hr & 0x0000FFFF);
+        if(messages) {
+            trace("D3DXPreprocessShader messages:\n%s", (char *)ID3DXBuffer_GetBufferPointer(messages));
+            ID3DXBuffer_Release(messages);
+        }
+        if(shader) ID3DXBuffer_Release(shader);
+    } else skip("Couldn't create \"shader.vsh\"\n");
+
+    /* NULL shader tests */
+    shader = NULL;
+    messages = NULL;
+    hr = D3DXPreprocessShaderFromFileA("nonexistent.vsh",
+                                       NULL, NULL,
+                                       &shader, &messages);
+    ok(hr == D3DXERR_INVALIDDATA || hr == E_FAIL, /* I get this on WinXP */
+        "D3DXPreprocessShaderFromFile nonexistent file test failed with error 0x%x - %d\n",
+        hr, hr & 0x0000FFFF);
+    if(messages) {
+        trace("D3DXPreprocessShaderFromFile messages:\n%s", (char *)ID3DXBuffer_GetBufferPointer(messages));
+        ID3DXBuffer_Release(messages);
+    }
+    if(shader) ID3DXBuffer_Release(shader);
+
+    /* D3DXPreprocessShaderFromResource test */
+    shader = NULL;
+    messages = NULL;
+    hr = D3DXPreprocessShaderFromResourceA(NULL, MAKEINTRESOURCEA(IDB_ASMSHADER),
+                                           NULL, NULL,
+                                           &shader, &messages);
+    ok(hr == D3D_OK, "D3DXPreprocessShaderFromResource test failed with error 0x%x - %d\n", hr, hr & 0x0000FFFF);
+    if(messages) {
+        trace("D3DXPreprocessShaderFromResource messages:\n%s", (char *)ID3DXBuffer_GetBufferPointer(messages));
+        ID3DXBuffer_Release(messages);
+    }
+    if(shader) ID3DXBuffer_Release(shader);
+
+    /* D3DXPreprocessShaderFromResource with missing shader resource test */
+    shader = NULL;
+    messages = NULL;
+    hr = D3DXPreprocessShaderFromResourceA(NULL, "notexisting",
+                                           NULL, NULL,
+                                           &shader, &messages);
+    ok(hr == D3DXERR_INVALIDDATA, "D3DXPreprocessShaderFromResource NULL shader test failed with error 0x%x - %d\n", hr, hr & 0x0000FFFF);
+    if(messages) {
+        trace("D3DXPreprocessShaderFromResource messages:\n%s", (char *)ID3DXBuffer_GetBufferPointer(messages));
+        ID3DXBuffer_Release(messages);
+    }
+    if(shader) ID3DXBuffer_Release(shader);
+
+    /* cleanup */
+    if(SUCCEEDED(shader_vsh_res)) {
+        DeleteFileA("shader.vsh");
+        DeleteFileA("incl.vsh");
+        DeleteFileA("shader3.vsh");
+        DeleteFileA("incl4.vsh");
+        DeleteFileA("include/incl3.vsh");
+        DeleteFileA("include/incl4.vsh");
+        RemoveDirectoryA("include");
+    }
+}
+
 START_TEST(asm)
 {
     assembleshader_test();
+
+    d3dxpreprocess_test();
 }
diff --git a/include/d3dx9shader.h b/include/d3dx9shader.h
index 357ace2..b5380a3 100644
--- a/include/d3dx9shader.h
+++ b/include/d3dx9shader.h
@@ -349,6 +349,39 @@ HRESULT WINAPI D3DXCompileShaderFromResourceW(HMODULE module,
                                               LPD3DXCONSTANTTABLE* constant_table);
 #define D3DXCompileShaderFromResource WINELIB_NAME_AW(D3DXCompileShaderFromResource)
 
+HRESULT WINAPI D3DXPreprocessShader(LPCSTR data,
+                                    UINT data_len,
+                                    CONST D3DXMACRO* defines,
+                                    LPD3DXINCLUDE include,
+                                    LPD3DXBUFFER* shader,
+                                    LPD3DXBUFFER* error_messages);
+
+HRESULT WINAPI D3DXPreprocessShaderFromFileA(LPCSTR filename,
+                                             CONST D3DXMACRO* defines,
+                                             LPD3DXINCLUDE include,
+                                             LPD3DXBUFFER* shader,
+                                             LPD3DXBUFFER* error_messages);
+HRESULT WINAPI D3DXPreprocessShaderFromFileW(LPCWSTR filename,
+                                             CONST D3DXMACRO* defines,
+                                             LPD3DXINCLUDE include,
+                                             LPD3DXBUFFER* shader,
+                                             LPD3DXBUFFER* error_messages);
+#define D3DXPreprocessShaderFromFile WINELIB_NAME_AW(D3DXPreprocessShaderFromFile)
+
+HRESULT WINAPI D3DXPreprocessShaderFromResourceA(HMODULE module,
+                                                 LPCSTR resource,
+                                                 CONST D3DXMACRO* defines,
+                                                 LPD3DXINCLUDE include,
+                                                 LPD3DXBUFFER* shader,
+                                                 LPD3DXBUFFER* error_messages);
+HRESULT WINAPI D3DXPreprocessShaderFromResourceW(HMODULE module,
+                                                 LPCWSTR resource,
+                                                 CONST D3DXMACRO* defines,
+                                                 LPD3DXINCLUDE include,
+                                                 LPD3DXBUFFER* shader,
+                                                 LPD3DXBUFFER* error_messages);
+#define D3DXPreprocessShaderFromResource WINELIB_NAME_AW(D3DXPreprocessShaderFromResource)
+
 HRESULT WINAPI D3DXGetShaderConstantTableEx(CONST DWORD* byte_code,
                                             DWORD flags,
                                             LPD3DXCONSTANTTABLE* constant_table);
-- 
1.7.2.2


More information about the wine-patches mailing list