[PATCH 4/5] d3dx9_36: Added support for structures and arrays to constant tables

Travis Athougies iammisc at gmail.com
Tue Jul 5 16:45:03 CDT 2011


---
 dlls/d3dx9_36/shader.c |  120 ++++++++++++++++++++++++++++++++++++++++++++---
 1 files changed, 112 insertions(+), 8 deletions(-)

diff --git a/dlls/d3dx9_36/shader.c b/dlls/d3dx9_36/shader.c
index b3b7bbc..4ee5c6e 100644
--- a/dlls/d3dx9_36/shader.c
+++ b/dlls/d3dx9_36/shader.c
@@ -769,6 +769,19 @@ static DWORD calc_constant_size(D3DXCONSTANT_DESC *desc)
     return 4 * desc->Elements * desc->Rows * desc->Columns;
 }
 
+static HRESULT calc_offset_of_element_constant(D3DXCONSTANT_DESC *desc, UINT element, UINT *offset)
+{
+    UINT element_size = desc->RegisterCount / desc->Elements;
+
+    if (element < desc->Elements)
+    {
+        *offset = element_size * element;
+        return D3D_OK;
+    }
+    else
+        return D3DXERR_INVALIDDATA;
+}
+
 static HRESULT WINAPI ID3DXConstantTableImpl_GetDesc(ID3DXConstantTable* iface, D3DXCONSTANTTABLE_DESC *desc)
 {
     ID3DXConstantTableImpl *This = impl_from_ID3DXConstantTable(iface);
@@ -857,28 +870,119 @@ static D3DXHANDLE WINAPI ID3DXConstantTableImpl_GetConstant(ID3DXConstantTable*
 static D3DXHANDLE WINAPI ID3DXConstantTableImpl_GetConstantByName(ID3DXConstantTable* iface, D3DXHANDLE constant, LPCSTR name)
 {
     ID3DXConstantTableImpl *This = impl_from_ID3DXConstantTable(iface);
-    UINT i;
+    UINT i, constant_count;
+    char *saveptr = NULL, *copied_name, *token, *membername, *index;
+    ctab_constant *constants, *cur_constant = NULL;
+    DWORD register_offset = 0, array_divisor = 1;
+    D3DXCONSTANT_DESC desc;
+    HRESULT hr;
 
     TRACE("(%p)->(%p, %s)\n", This, constant, name);
 
     if (!name)
         return NULL;
 
+    for (i = 0; i < This->handle_count; i++)
+        if (!strcmp(This->handles[i].full_name, name))
+            return (D3DXHANDLE)(DWORD_PTR)(i + 1);
+
     if (constant)
     {
         FIXME("Only top level constants supported\n");
         return NULL;
     }
+    else
+    {
+        constants = This->constants;
+        constant_count = This->desc.Constants;
+    }
 
-    for (i = 0; i < This->handle_count; i++)
-        if (!strcmp(This->handles[i].full_name, name))
-            return (D3DXHANDLE)(DWORD_PTR)(i + 1);
+    copied_name = strdup(name);
 
-    for (i = 0; i < This->desc.Constants; i++)
-        if (!strcmp(This->constants[i].desc.Name, name))
-            return (D3DXHANDLE)(DWORD_PTR)new_handle(This, &This->constants[i]);
+    for(token = strtok_r(copied_name, ".", &saveptr); token; token = strtok_r(NULL, ".", &saveptr))
+    {
+        if (!constants || !constant_count) {
+            free(copied_name);
+            return NULL;
+        }
 
-    return NULL;
+        membername = token;
+
+        index = strchr(token, '[');
+        if (index) {
+            *index = '\0';
+            index++;
+        }
+
+        for (i = 0; i < constant_count; i++)
+            if (!strcmp(constants[i].desc.Name, membername))
+            {
+                cur_constant = &constants[i];
+                constants = cur_constant->members;
+                break;
+            }
+
+        if (i == constant_count)
+        {
+            TRACE("Couldn't find constant %s: quit at %s\n", name, membername);
+            free(copied_name);
+            return NULL;
+        }
+
+        if (index)
+        {
+            /* We need to calculate an offset to add to the RegisterIndex of the associated D3DXCONSTANT_DESC */
+            /* Also, we need to calculate a value which we can use to calculate the number of registers in array elements */
+            char *endptr;
+            UINT index_i = strtoul(index, &endptr, 10), offset;
+
+            if (endptr == index || *endptr != ']' || *(endptr + 1) != '\0')
+            {
+                TRACE("Invalid index specified: %s in %s\n", index, name);
+                free(copied_name);
+                return NULL;
+            }
+
+            hr = calc_offset_of_element_constant(&cur_constant->desc, index_i, &offset);
+            if (FAILED(hr))
+            {
+                WARN("Could not calculate offset of element %d of %s in %s\n", index_i, membername, name);
+                free(copied_name);
+                return NULL;
+            }
+
+            register_offset += offset;
+            array_divisor = cur_constant->desc.Elements;
+        }
+        else
+            array_divisor = 1;
+    }
+
+    if (cur_constant)
+    {
+        WORD handle;
+
+        /* Copy over the base descriptor and make adjustments for indexing */
+        desc = cur_constant->desc;
+        desc.RegisterIndex += register_offset;
+        desc.RegisterCount /= array_divisor;
+        desc.Elements /= array_divisor;
+        desc.Bytes = calc_constant_size(&desc);
+
+        TRACE("Found constant: name = %s(%s), set = %d, index = %d, count = %d, class = %d, type = %d, rows = %d, "
+                "columns = %d, elements = %d, members = %d\n", membername, name, desc.RegisterSet, desc.RegisterIndex,
+                desc.RegisterCount, desc.Class, desc.Type, desc.Rows, desc.Columns, desc.Elements, desc.StructMembers);
+
+        handle = new_handle_with_desc_and_name(This, &desc, membername, name);
+
+        free(copied_name);
+        return (D3DXHANDLE)(DWORD_PTR)handle;
+    }
+    else
+    {
+        free(copied_name);
+        return NULL;
+    }
 }
 
 static D3DXHANDLE WINAPI ID3DXConstantTableImpl_GetConstantElement(ID3DXConstantTable* iface, D3DXHANDLE constant, UINT index)
-- 
1.6.4.4




More information about the wine-patches mailing list