[PATCH] d3dx9_36: Beginning of constants parsing + tests (based on work from Luis Busquets) (try 3)

Christian Costa titan.costa at wanadoo.fr
Mon Apr 5 16:03:27 CDT 2010


--
Use UINT_PTR instead of UINT
---

 dlls/d3dx9_36/shader.c       |  137 +++++++++++++++++++++++++++++++++++++++---
 dlls/d3dx9_36/tests/shader.c |  105 ++++++++++++++++++++++++++++++++
 2 files changed, 233 insertions(+), 9 deletions(-)
-------------- next part --------------
diff --git a/dlls/d3dx9_36/shader.c b/dlls/d3dx9_36/shader.c
index 3aeaf78..bd061ea 100644
--- a/dlls/d3dx9_36/shader.c
+++ b/dlls/d3dx9_36/shader.c
@@ -650,6 +650,29 @@ HRESULT WINAPI D3DXCompileShader(LPCSTR pSrcData,
     return D3DERR_INVALIDCALL;
 }
 
+typedef struct ctab_constant ctab_constant;
+
+struct ctab_constant {
+    D3DXCONSTANT_DESC desc;
+    ctab_constant* members;
+};
+
+inline ctab_constant* get_constant(D3DXHANDLE ptr)
+{
+    if (!ptr) return NULL;
+    return (ctab_constant*)~((UINT_PTR)ptr);
+}
+
+inline D3DXHANDLE get_handle(ctab_constant* ptr)
+{
+    return (D3DXHANDLE)~((UINT_PTR)ptr);
+}
+
+inline BOOL isstring(D3DXHANDLE ptr)
+{
+    return !(((UINT_PTR)ptr) & (1 << (sizeof(UINT_PTR)*8-1)));
+}
+
 static const struct ID3DXConstantTableVtbl ID3DXConstantTable_Vtbl;
 
 typedef struct ID3DXConstantTableImpl {
@@ -658,6 +681,7 @@ typedef struct ID3DXConstantTableImpl {
     LPVOID ctab;
     DWORD size;
     D3DXCONSTANTTABLE_DESC desc;
+    ctab_constant* constants;
 } ID3DXConstantTableImpl;
 
 /*** IUnknown methods ***/
@@ -699,6 +723,7 @@ static ULONG WINAPI ID3DXConstantTableImpl_Release(ID3DXConstantTable* iface)
 
     if (!ref)
     {
+        HeapFree(GetProcessHeap(), 0, This->constants);
         HeapFree(GetProcessHeap(), 0, This->ctab);
         HeapFree(GetProcessHeap(), 0, This);
     }
@@ -744,10 +769,23 @@ static HRESULT WINAPI ID3DXConstantTableImpl_GetConstantDesc(ID3DXConstantTable*
                                                              D3DXCONSTANT_DESC *desc, UINT *count)
 {
     ID3DXConstantTableImpl *This = (ID3DXConstantTableImpl *)iface;
+    ctab_constant* constant_info;
 
-    FIXME("(%p)->(%p, %p, %p): stub\n", This, constant, desc, count);
+    TRACE("(%p)->(%p, %p, %p)\n", This, constant, desc, count);
 
-    return E_NOTIMPL;
+    if (!constant)
+        return D3DERR_INVALIDCALL;
+
+    constant_info = get_constant(isstring(constant) ? ID3DXConstantTable_GetConstantByName(iface, NULL, constant) : constant);
+    if (!constant_info)
+        return D3DERR_INVALIDCALL;
+
+    if (desc)
+        *desc = constant_info->desc;
+    if (count)
+        *count = 1;
+
+    return D3D_OK;
 }
 
 static UINT WINAPI ID3DXConstantTableImpl_GetSamplerIndex(LPD3DXCONSTANTTABLE iface, D3DXHANDLE constant)
@@ -763,17 +801,40 @@ static D3DXHANDLE WINAPI ID3DXConstantTableImpl_GetConstant(ID3DXConstantTable*
 {
     ID3DXConstantTableImpl *This = (ID3DXConstantTableImpl *)iface;
 
-    FIXME("(%p)->(%p, %d): stub\n", This, constant, index);
+    TRACE("(%p)->(%p, %d)\n", This, constant, index);
 
-    return NULL;
+    if (constant)
+    {
+        FIXME("Only top level constants supported\n");
+        return NULL;
+    }
+
+    if (index >= This->desc.Constants)
+        return NULL;
+
+    return get_handle(This->constants + index);
 }
 
 static D3DXHANDLE WINAPI ID3DXConstantTableImpl_GetConstantByName(ID3DXConstantTable* iface, D3DXHANDLE constant, LPCSTR name)
 {
     ID3DXConstantTableImpl *This = (ID3DXConstantTableImpl *)iface;
+    UINT i;
 
-    FIXME("(%p)->(%p, %s): stub\n", This, constant, name);
+    TRACE("(%p)->(%p, %s)\n", This, constant, name);
 
+    if (!name)
+        return NULL;
+
+    if (constant)
+    {
+        FIXME("Only top level constants supported\n");
+        return NULL;
+    }
+
+    for (i = 0; i < This->desc.Constants; i++)
+        if (!strcmp(This->constants[i].desc.Name, name))
+            return get_handle(This->constants + i);
+        
     return NULL;
 }
 
@@ -978,6 +1039,26 @@ static const struct ID3DXConstantTableVtbl ID3DXConstantTable_Vtbl =
     ID3DXConstantTableImpl_SetMatrixTransposePointerArray
 };
 
+HRESULT parse_ctab_constant_type(LPVOID ctab, LPD3DXSHADER_TYPEINFO type, ctab_constant* constant)
+{
+    constant->desc.Class = (D3DXPARAMETER_CLASS)type->Class;
+    constant->desc.Type = (D3DXPARAMETER_TYPE)type->Type;
+    constant->desc.Rows = type->Rows;
+    constant->desc.Columns = type->Columns;
+    constant->desc.StructMembers = type->StructMembers;
+ 
+    TRACE("class = %d, type = %d, rows = %d, columns = %d, struct_members = %d\n", constant->desc.Class, constant->desc.Type,
+          constant->desc.Rows, constant->desc.Columns, constant->desc.StructMembers);
+
+    if ((constant->desc.Class == D3DXPC_STRUCT) && constant->desc.StructMembers)
+    {
+        FIXME("Struct not supported yet\n");
+        return E_NOTIMPL;
+    }
+
+    return D3D_OK;
+}
+
 HRESULT WINAPI D3DXGetShaderConstantTableEx(CONST DWORD* byte_code,
                                             DWORD flags,
                                             LPD3DXCONSTANTTABLE* constant_table)
@@ -987,8 +1068,10 @@ HRESULT WINAPI D3DXGetShaderConstantTableEx(CONST DWORD* byte_code,
     LPCVOID data;
     UINT size;
     const D3DXSHADER_CONSTANTTABLE* ctab_header;
+    LPD3DXSHADER_CONSTANTINFO constant_info;
+    DWORD i;
 
-    FIXME("(%p, %x, %p): semi-stub\n", byte_code, flags, constant_table);
+    TRACE("(%p, %x, %p)\n", byte_code, flags, constant_table);
 
     if (!byte_code || !constant_table)
         return D3DERR_INVALIDCALL;
@@ -1008,24 +1091,59 @@ HRESULT WINAPI D3DXGetShaderConstantTableEx(CONST DWORD* byte_code,
     object->ref = 1;
 
     if (size < sizeof(D3DXSHADER_CONSTANTTABLE))
+    {
+        hr = D3DXERR_INVALIDDATA;
         goto error;
+    }
 
     object->ctab = HeapAlloc(GetProcessHeap(), 0, size);
     if (!object->ctab)
     {
-        HeapFree(GetProcessHeap(), 0, object);
         ERR("Out of memory\n");
-        return E_OUTOFMEMORY;
+        hr = E_OUTOFMEMORY;
+        goto error;
     }
     object->size = size;
     memcpy(object->ctab, data, object->size);
 
     ctab_header = (const D3DXSHADER_CONSTANTTABLE*)data;
     if (ctab_header->Size != sizeof(D3DXSHADER_CONSTANTTABLE))
+    {
+        hr = D3DXERR_INVALIDDATA;
         goto error;
+    }
     object->desc.Creator = ctab_header->Creator ? (LPCSTR)object->ctab + ctab_header->Creator : NULL;
     object->desc.Version = ctab_header->Version;
     object->desc.Constants = ctab_header->Constants;
+    if (object->desc.Creator)
+        TRACE("Creator = %s\n", object->desc.Creator);
+    TRACE("Version = %x\n", object->desc.Version);
+    TRACE("Constants = %d\n", ctab_header->Constants);
+    if (ctab_header->Target)
+        TRACE("Target = %s\n", (LPCSTR)object->ctab + ctab_header->Target);
+
+    object->constants = (ctab_constant*)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
+                                                      sizeof(ctab_constant)*object->desc.Constants);
+    if (!object->constants)
+    {
+         ERR("Out of memory\n");
+         hr = E_OUTOFMEMORY;
+         goto error;
+    }
+
+    constant_info = (LPD3DXSHADER_CONSTANTINFO)((LPCSTR)object->ctab + ctab_header->ConstantInfo);
+    for (i = 0; i < ctab_header->Constants; i++)
+    {
+        TRACE("name = %s\n", (LPCSTR)object->ctab + constant_info[i].Name);
+        object->constants[i].desc.Name = (LPCSTR)object->ctab + constant_info[i].Name;
+        object->constants[i].desc.RegisterSet = (D3DXREGISTER_SET)constant_info[i].RegisterSet;
+        object->constants[i].desc.RegisterIndex = constant_info[i].RegisterIndex;
+        object->constants[i].desc.RegisterCount = 0;
+        hr = parse_ctab_constant_type(object->ctab, (LPD3DXSHADER_TYPEINFO)((LPCSTR)object->ctab + constant_info[i].TypeInfo),
+             &object->constants[i]);
+        if (hr != D3D_OK)
+            goto error;
+    }
 
     *constant_table = (LPD3DXCONSTANTTABLE)object;
 
@@ -1033,10 +1151,11 @@ HRESULT WINAPI D3DXGetShaderConstantTableEx(CONST DWORD* byte_code,
 
 error:
 
+    HeapFree(GetProcessHeap(), 0, object->constants);
     HeapFree(GetProcessHeap(), 0, object->ctab);
     HeapFree(GetProcessHeap(), 0, object);
 
-    return D3DXERR_INVALIDDATA;
+    return hr;
 }
 
 HRESULT WINAPI D3DXGetShaderConstantTable(CONST DWORD* byte_code,
diff --git a/dlls/d3dx9_36/tests/shader.c b/dlls/d3dx9_36/tests/shader.c
index 6bf0de3..318ac92 100644
--- a/dlls/d3dx9_36/tests/shader.c
+++ b/dlls/d3dx9_36/tests/shader.c
@@ -55,6 +55,23 @@ static const DWORD shader_with_invalid_ctab[] = {
                 0x00000000, 0x00000000,
     0x0000ffff};                                                            /* END                          */
 
+static const DWORD shader_with_ctab_constants[] = {
+    0xfffe0300,                                                             /* vs_3_0                       */
+    0x002efffe, FCC_CTAB,                                                   /* CTAB comment                 */
+    0x0000001c, 0x000000a4, 0xfffe0300, 0x00000003, 0x0000001c, 0x20008100, /* Header                       */
+    0x0000009c,
+    0x00000058, 0x00070002, 0x00000001, 0x00000064, 0x00000000,             /* Constant 1 desc              */
+    0x00000074, 0x00000002, 0x00000004, 0x00000080, 0x00000000,             /* Constant 2 desc              */
+    0x00000090, 0x00040002, 0x00000003, 0x00000080, 0x00000000,             /* Constant 3 desc              */
+    0x736e6f43, 0x746e6174, 0xabab0031,                                     /* Constant 1 name string       */
+    0x00030001, 0x00040001, 0x00000001, 0x00000000,                         /* Constant 1 type desc         */
+    0x736e6f43, 0x746e6174, 0xabab0032,                                     /* Constant 2 name string       */
+    0x00030003, 0x00040004, 0x00000001, 0x00000000,                         /* Constant 2 & 3 type desc     */
+    0x736e6f43, 0x746e6174, 0xabab0033,                                     /* Constant 3 name string       */
+    0x335f7376, 0xab00305f,                                                 /* Target name string           */
+    0x656e6957, 0x6f727020, 0x7463656a, 0xababab00,                         /* Creator name string          */
+    0x0000ffff};                                                            /* END                          */
+
 static void test_get_shader_size(void)
 {
     UINT shader_size, expected;
@@ -156,6 +173,94 @@ static void test_get_shader_constant_table_ex(void)
 
         ID3DXConstantTable_Release(constant_table);
     }
+
+    hr = D3DXGetShaderConstantTableEx(shader_with_ctab_constants, 0, &constant_table);
+    ok(hr == D3D_OK, "Got result %x, expected 0 (D3D_OK)\n", hr);
+
+    if (hr == D3D_OK)
+    {
+        D3DXHANDLE constant;
+        D3DXCONSTANT_DESC constant_desc;
+        D3DXCONSTANT_DESC constant_desc_save;
+        UINT nb;
+
+        /* Test GetDesc */
+        hr = ID3DXConstantTable_GetDesc(constant_table, &desc);
+        ok(hr == D3D_OK, "Got result %x, expected 0 (D3D_OK)\n", hr);
+        ok(!strcmp(desc.Creator, "Wine project"), "Got result '%s', expected 'Wine project'\n", desc.Creator);
+        ok(desc.Version == D3DVS_VERSION(3, 0), "Got result %x, expected %x\n", desc.Version, D3DVS_VERSION(3, 0));
+        ok(desc.Constants == 3, "Got result %x, expected 3\n", desc.Constants);
+
+        /* Test GetConstant */
+        constant = ID3DXConstantTable_GetConstant(constant_table, NULL, 0);
+        ok(constant != NULL, "No constant found\n");
+        hr = ID3DXConstantTable_GetConstantDesc(constant_table, constant, &constant_desc, &nb);
+        ok(hr == D3D_OK, "Got result %x, expected 0 (D3D_OK)\n", hr);
+        ok(!strcmp(constant_desc.Name, "Constant1"), "Got result '%s', expected 'Constant1'\n",
+            constant_desc.Name);
+        ok(constant_desc.Class == D3DXPC_VECTOR, "Got result %x, expected %u (D3DXPC_VECTOR)\n",
+            constant_desc.Class, D3DXPC_VECTOR);
+        ok(constant_desc.Type == D3DXPT_FLOAT, "Got result %x, expected %u (D3DXPT_FLOAT)\n",
+            constant_desc.Type, D3DXPT_FLOAT);
+        ok(constant_desc.Rows == 1, "Got result %x, expected 1\n", constant_desc.Rows);
+        ok(constant_desc.Columns == 4, "Got result %x, expected 4\n", constant_desc.Columns);
+
+        constant = ID3DXConstantTable_GetConstant(constant_table, NULL, 1);
+        ok(constant != NULL, "No constant found\n");
+        hr = ID3DXConstantTable_GetConstantDesc(constant_table, constant, &constant_desc, &nb);
+        ok(hr == D3D_OK, "Got result %x, expected 0 (D3D_OK)\n", hr);
+        ok(!strcmp(constant_desc.Name, "Constant2"), "Got result '%s', expected 'Constant2'\n",
+            constant_desc.Name);
+        ok(constant_desc.Class == D3DXPC_MATRIX_COLUMNS, "Got result %x, expected %u (D3DXPC_MATRIX_COLUMNS)\n",
+            constant_desc.Class, D3DXPC_MATRIX_COLUMNS);
+        ok(constant_desc.Type == D3DXPT_FLOAT, "Got result %x, expected %u (D3DXPT_FLOAT)\n",
+            constant_desc.Type, D3DXPT_FLOAT);
+        ok(constant_desc.Rows == 4, "Got result %x, expected 1\n", constant_desc.Rows);
+        ok(constant_desc.Columns == 4, "Got result %x, expected 4\n", constant_desc.Columns);
+
+        constant = ID3DXConstantTable_GetConstant(constant_table, NULL, 2);
+        ok(constant != NULL, "No constant found\n");
+        hr = ID3DXConstantTable_GetConstantDesc(constant_table, constant, &constant_desc, &nb);
+        ok(hr == D3D_OK, "Got result %x, expected 0 (D3D_OK)\n", hr);
+        ok(!strcmp(constant_desc.Name, "Constant3"), "Got result '%s', expected 'Constant3'\n",
+            constant_desc.Name);
+        ok(constant_desc.Class == D3DXPC_MATRIX_COLUMNS, "Got result %x, expected %u (D3DXPC_MATRIX_COLUMNS)\n",
+            constant_desc.Class, D3DXPC_MATRIX_COLUMNS);
+        ok(constant_desc.Type == D3DXPT_FLOAT, "Got result %x, expected %u (D3DXPT_FLOAT)\n",
+            constant_desc.Type, D3DXPT_FLOAT);
+        ok(constant_desc.Rows == 4, "Got result %x, expected 1\n", constant_desc.Rows);
+        ok(constant_desc.Columns == 4, "Got result %x, expected 4\n", constant_desc.Columns);
+        constant_desc_save = constant_desc; /* For GetConstantDesc test */
+
+        constant = ID3DXConstantTable_GetConstant(constant_table, NULL, 3);
+        ok(constant == NULL, "Got result %p, expected NULL\n", constant);
+
+        /* Test GetConstantByName */
+        constant = ID3DXConstantTable_GetConstantByName(constant_table, NULL, "Constant unknown");
+        ok(constant == NULL, "Got result %p, expected NULL\n", constant);
+        constant = ID3DXConstantTable_GetConstantByName(constant_table, NULL, "Constant3");
+        ok(constant != NULL, "No constant found\n");
+        hr = ID3DXConstantTable_GetConstantDesc(constant_table, constant, &constant_desc, &nb);
+        ok(hr == D3D_OK, "Got result %x, expected 0 (D3D_OK)\n", hr);
+        ok(!memcmp(&constant_desc, &constant_desc_save, sizeof(D3DXCONSTANT_DESC)), "Got different constant data\n");
+
+        /* Test GetConstantDesc */
+        constant = ID3DXConstantTable_GetConstant(constant_table, NULL, 0);
+        ok(constant != NULL, "No constant found\n");
+        hr = ID3DXConstantTable_GetConstantDesc(constant_table, NULL, &constant_desc, &nb);
+        ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n", hr, D3DERR_INVALIDCALL);
+        hr = ID3DXConstantTable_GetConstantDesc(constant_table, constant, NULL, &nb);
+        ok(hr == D3D_OK, "Got result %x, expected 0 (D3D_OK)\n", hr);
+        hr = ID3DXConstantTable_GetConstantDesc(constant_table, constant, &constant_desc, NULL);
+        ok(hr == D3D_OK, "Got result %x, expected 0 (D3D_OK)\n", hr);
+        hr = ID3DXConstantTable_GetConstantDesc(constant_table, "Constant unknow", &constant_desc, &nb);
+        ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n", hr, D3DERR_INVALIDCALL);
+        hr = ID3DXConstantTable_GetConstantDesc(constant_table, "Constant3", &constant_desc, &nb);
+        ok(hr == D3D_OK, "Got result %x, expected 0 (D3D_OK)\n", hr);
+        ok(!memcmp(&constant_desc, &constant_desc_save, sizeof(D3DXCONSTANT_DESC)), "Got different constant data\n");
+
+        ID3DXConstantTable_Release(constant_table);
+    }
 }
 
 START_TEST(shader)


More information about the wine-patches mailing list