d3dx9: Parse effect pass and technique.
authorRico Schüller <kgbricola@web.de>
Tue, 12 Apr 2011 19:25:06 +0000 (21:25 +0200)
committerAlexandre Julliard <julliard@winehq.org>
Wed, 13 Apr 2011 12:13:53 +0000 (14:13 +0200)
dlls/d3dx9_36/effect.c

index ba02c56af22d275edc360bb050148596bda1330f..66b5a40ec2946eacdf43bcd2d68d7880d372082f 100644 (file)
@@ -51,6 +51,29 @@ struct d3dx_parameter
     D3DXHANDLE *member_handles;
 };
 
+struct d3dx_pass
+{
+    struct ID3DXBaseEffectImpl *base;
+
+    char *name;
+    UINT state_count;
+    UINT annotation_count;
+
+    D3DXHANDLE *annotation_handles;
+};
+
+struct d3dx_technique
+{
+    struct ID3DXBaseEffectImpl *base;
+
+    char *name;
+    UINT pass_count;
+    UINT annotation_count;
+
+    D3DXHANDLE *annotation_handles;
+    D3DXHANDLE *pass_handles;
+};
+
 struct ID3DXBaseEffectImpl
 {
     ID3DXBaseEffect ID3DXBaseEffect_iface;
@@ -62,6 +85,7 @@ struct ID3DXBaseEffectImpl
     UINT technique_count;
 
     D3DXHANDLE *parameter_handles;
+    D3DXHANDLE *technique_handles;
 };
 
 struct ID3DXEffectImpl
@@ -107,11 +131,31 @@ static inline struct d3dx_parameter *get_parameter_struct(D3DXHANDLE handle)
     return (struct d3dx_parameter *) handle;
 }
 
+static inline struct d3dx_pass *get_pass_struct(D3DXHANDLE handle)
+{
+    return (struct d3dx_pass *) handle;
+}
+
+static inline struct d3dx_technique *get_technique_struct(D3DXHANDLE handle)
+{
+    return (struct d3dx_technique *) handle;
+}
+
 static inline D3DXHANDLE get_parameter_handle(struct d3dx_parameter *parameter)
 {
     return (D3DXHANDLE) parameter;
 }
 
+static inline D3DXHANDLE get_technique_handle(struct d3dx_technique *technique)
+{
+    return (D3DXHANDLE) technique;
+}
+
+static inline D3DXHANDLE get_pass_handle(struct d3dx_pass *pass)
+{
+    return (D3DXHANDLE) pass;
+}
+
 static void free_parameter(D3DXHANDLE handle, BOOL element, BOOL child)
 {
     unsigned int i;
@@ -162,6 +206,65 @@ static void free_parameter(D3DXHANDLE handle, BOOL element, BOOL child)
     HeapFree(GetProcessHeap(), 0, param);
 }
 
+static void free_pass(D3DXHANDLE handle)
+{
+    unsigned int i;
+    struct d3dx_pass *pass = get_pass_struct(handle);
+
+    TRACE("Free pass %p\n", pass);
+
+    if (!pass)
+    {
+        return;
+    }
+
+    if (pass->annotation_handles)
+    {
+        for (i = 0; i < pass->annotation_count; ++i)
+        {
+            free_parameter(pass->annotation_handles[i], FALSE, FALSE);
+        }
+        HeapFree(GetProcessHeap(), 0, pass->annotation_handles);
+    }
+
+    HeapFree(GetProcessHeap(), 0, pass->name);
+    HeapFree(GetProcessHeap(), 0, pass);
+}
+
+static void free_technique(D3DXHANDLE handle)
+{
+    unsigned int i;
+    struct d3dx_technique *technique = get_technique_struct(handle);
+
+    TRACE("Free technique %p\n", technique);
+
+    if (!technique)
+    {
+        return;
+    }
+
+    if (technique->annotation_handles)
+    {
+        for (i = 0; i < technique->annotation_count; ++i)
+        {
+            free_parameter(technique->annotation_handles[i], FALSE, FALSE);
+        }
+        HeapFree(GetProcessHeap(), 0, technique->annotation_handles);
+    }
+
+    if (technique->pass_handles)
+    {
+        for (i = 0; i < technique->pass_count; ++i)
+        {
+            free_pass(technique->pass_handles[i]);
+        }
+        HeapFree(GetProcessHeap(), 0, technique->pass_handles);
+    }
+
+    HeapFree(GetProcessHeap(), 0, technique->name);
+    HeapFree(GetProcessHeap(), 0, technique);
+}
+
 static void free_base_effect(struct ID3DXBaseEffectImpl *base)
 {
     unsigned int i;
@@ -176,6 +279,15 @@ static void free_base_effect(struct ID3DXBaseEffectImpl *base)
         }
         HeapFree(GetProcessHeap(), 0, base->parameter_handles);
     }
+
+    if (base->technique_handles)
+    {
+        for (i = 0; i < base->technique_count; ++i)
+        {
+            free_technique(base->technique_handles[i]);
+        }
+        HeapFree(GetProcessHeap(), 0, base->technique_handles);
+    }
 }
 
 static void free_effect(struct ID3DXEffectImpl *effect)
@@ -2842,10 +2954,220 @@ err_out:
     return hr;
 }
 
+static HRESULT d3dx9_parse_effect_pass(struct d3dx_pass *pass, const char *data, const char **ptr)
+{
+    DWORD offset;
+    HRESULT hr;
+    unsigned int i;
+    D3DXHANDLE *annotation_handles = NULL;
+    char *name = NULL;
+
+    read_dword(ptr, &offset);
+    TRACE("Pass name offset: %#x\n", offset);
+    hr = d3dx9_parse_name(&name, data + offset);
+    if (hr != D3D_OK)
+    {
+        WARN("Failed to parse name\n");
+        goto err_out;
+    }
+
+    read_dword(ptr, &pass->annotation_count);
+    TRACE("Annotation count: %u\n", pass->annotation_count);
+
+    read_dword(ptr, &pass->state_count);
+    TRACE("State count: %u\n", pass->state_count);
+
+    if (pass->annotation_count)
+    {
+        annotation_handles = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*annotation_handles) * pass->annotation_count);
+        if (!annotation_handles)
+        {
+            ERR("Out of memory\n");
+            hr = E_OUTOFMEMORY;
+            goto err_out;
+        }
+
+        for (i = 0; i < pass->annotation_count; ++i)
+        {
+            struct d3dx_parameter *annotation;
+
+            annotation = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*annotation));
+            if (!annotation)
+            {
+                ERR("Out of memory\n");
+                hr = E_OUTOFMEMORY;
+                goto err_out;
+            }
+
+            annotation_handles[i] = get_parameter_handle(annotation);
+            annotation->base = pass->base;
+
+            hr = d3dx9_parse_effect_annotation(annotation, data, ptr);
+            if (hr != D3D_OK)
+            {
+                WARN("Failed to parse annotations\n");
+                goto err_out;
+            }
+        }
+    }
+
+    if (pass->state_count)
+    {
+        for (i = 0; i < pass->state_count; ++i)
+        {
+            skip_dword_unknown(ptr, 4);
+        }
+    }
+
+    pass->name = name;
+    pass->annotation_handles = annotation_handles;
+
+    return D3D_OK;
+
+err_out:
+
+    if (annotation_handles)
+    {
+        for (i = 0; i < pass->annotation_count; ++i)
+        {
+            free_parameter(annotation_handles[i], FALSE, FALSE);
+        }
+        HeapFree(GetProcessHeap(), 0, annotation_handles);
+    }
+
+    HeapFree(GetProcessHeap(), 0, name);
+
+    return hr;
+}
+
+static HRESULT d3dx9_parse_effect_technique(struct d3dx_technique *technique, const char *data, const char **ptr)
+{
+    DWORD offset;
+    HRESULT hr;
+    unsigned int i;
+    D3DXHANDLE *annotation_handles = NULL;
+    D3DXHANDLE *pass_handles = NULL;
+    char *name = NULL;
+
+    read_dword(ptr, &offset);
+    TRACE("Technique name offset: %#x\n", offset);
+    hr = d3dx9_parse_name(&name, data + offset);
+    if (hr != D3D_OK)
+    {
+        WARN("Failed to parse name\n");
+        goto err_out;
+    }
+
+    read_dword(ptr, &technique->annotation_count);
+    TRACE("Annotation count: %u\n", technique->annotation_count);
+
+    read_dword(ptr, &technique->pass_count);
+    TRACE("Pass count: %u\n", technique->pass_count);
+
+    if (technique->annotation_count)
+    {
+        annotation_handles = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*annotation_handles) * technique->annotation_count);
+        if (!annotation_handles)
+        {
+            ERR("Out of memory\n");
+            hr = E_OUTOFMEMORY;
+            goto err_out;
+        }
+
+        for (i = 0; i < technique->annotation_count; ++i)
+        {
+            struct d3dx_parameter *annotation;
+
+            annotation = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*annotation));
+            if (!annotation)
+            {
+                ERR("Out of memory\n");
+                hr = E_OUTOFMEMORY;
+                goto err_out;
+            }
+
+            annotation_handles[i] = get_parameter_handle(annotation);
+            annotation->base = technique->base;
+
+            hr = d3dx9_parse_effect_annotation(annotation, data, ptr);
+            if (hr != D3D_OK)
+            {
+                WARN("Failed to parse annotations\n");
+                goto err_out;
+            }
+        }
+    }
+
+    if (technique->pass_count)
+    {
+        pass_handles = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*pass_handles) * technique->pass_count);
+        if (!pass_handles)
+        {
+            ERR("Out of memory\n");
+            hr = E_OUTOFMEMORY;
+            goto err_out;
+        }
+
+        for (i = 0; i < technique->pass_count; ++i)
+        {
+            struct d3dx_pass *pass;
+
+            pass = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*pass));
+            if (!pass)
+            {
+                ERR("Out of memory\n");
+                hr = E_OUTOFMEMORY;
+                goto err_out;
+            }
+
+            pass_handles[i] = get_pass_handle(pass);
+            pass->base = technique->base;
+
+            hr = d3dx9_parse_effect_pass(pass, data, ptr);
+            if (hr != D3D_OK)
+            {
+                WARN("Failed to parse passes\n");
+                goto err_out;
+            }
+        }
+    }
+
+    technique->name = name;
+    technique->pass_handles = pass_handles;
+    technique->annotation_handles = annotation_handles;
+
+    return D3D_OK;
+
+err_out:
+
+    if (pass_handles)
+    {
+        for (i = 0; i < technique->pass_count; ++i)
+        {
+            free_pass(pass_handles[i]);
+        }
+        HeapFree(GetProcessHeap(), 0, pass_handles);
+    }
+
+    if (annotation_handles)
+    {
+        for (i = 0; i < technique->annotation_count; ++i)
+        {
+            free_parameter(annotation_handles[i], FALSE, FALSE);
+        }
+        HeapFree(GetProcessHeap(), 0, annotation_handles);
+    }
+
+    HeapFree(GetProcessHeap(), 0, name);
+
+    return hr;
+}
+
 static HRESULT d3dx9_parse_effect(struct ID3DXBaseEffectImpl *base, const char *data, UINT data_size, DWORD start)
 {
     const char *ptr = data + start;
     D3DXHANDLE *parameter_handles = NULL;
+    D3DXHANDLE *technique_handles = NULL;
     HRESULT hr;
     unsigned int i;
 
@@ -2891,14 +3213,56 @@ static HRESULT d3dx9_parse_effect(struct ID3DXBaseEffectImpl *base, const char *
         }
     }
 
-    /* todo: Parse techniques */
+    if (base->technique_count)
+    {
+        technique_handles = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*technique_handles) * base->technique_count);
+        if (!technique_handles)
+        {
+            ERR("Out of memory\n");
+            hr = E_OUTOFMEMORY;
+            goto err_out;
+        }
+
+        for (i = 0; i < base->technique_count; ++i)
+        {
+            struct d3dx_technique *technique;
 
+            technique = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*technique));
+            if (!technique)
+            {
+                ERR("Out of memory\n");
+                hr = E_OUTOFMEMORY;
+                goto err_out;
+            }
+
+            technique_handles[i] = get_technique_handle(technique);
+            technique->base = base;
+
+            hr = d3dx9_parse_effect_technique(technique, data, &ptr);
+            if (hr != D3D_OK)
+            {
+                WARN("Failed to parse technique\n");
+                goto err_out;
+            }
+        }
+    }
+
+    base->technique_handles = technique_handles;
     base->parameter_handles = parameter_handles;
 
     return D3D_OK;
 
 err_out:
 
+    if (technique_handles)
+    {
+        for (i = 0; i < base->technique_count; ++i)
+        {
+            free_technique(technique_handles[i]);
+        }
+        HeapFree(GetProcessHeap(), 0, technique_handles);
+    }
+
     if (parameter_handles)
     {
         for (i = 0; i < base->parameter_count; ++i)