[PATCH 09/10] d3dx9: Implement recording parameters to parameter block.

Paul Gofman gofmanp at gmail.com
Thu Nov 7 15:17:43 CST 2019


Signed-off-by: Paul Gofman <gofmanp at gmail.com>
---
 dlls/d3dx9_36/effect.c       | 111 +++++++++++++++++++++++++++++++++++
 dlls/d3dx9_36/tests/effect.c |   6 +-
 2 files changed, 114 insertions(+), 3 deletions(-)

diff --git a/dlls/d3dx9_36/effect.c b/dlls/d3dx9_36/effect.c
index 4739b0cc0e..7a7fc336e1 100644
--- a/dlls/d3dx9_36/effect.c
+++ b/dlls/d3dx9_36/effect.c
@@ -36,6 +36,7 @@ static const char parameter_block_magic_string[4] = {'@', '!', '#', '\xFE'};
 #define PARAMETER_FLAG_SHARED 1
 
 #define INITIAL_POOL_SIZE 16
+#define INITIAL_PARAM_BLOCK_SIZE 1024
 
 WINE_DEFAULT_DEBUG_CHANNEL(d3dx);
 
@@ -153,6 +154,15 @@ struct d3dx_parameter_block
 {
     char magic_string[ARRAY_SIZE(parameter_block_magic_string)];
     struct list entry;
+    size_t buffer_size;
+    size_t current_size;
+    BYTE *buffer;
+};
+
+struct d3dx_recorded_parameter
+{
+    struct d3dx_parameter *param;
+    unsigned int bytes;
 };
 
 struct d3dx_effect
@@ -706,11 +716,27 @@ static void free_technique(struct d3dx_technique *technique)
     technique->name = NULL;
 }
 
+static unsigned int get_recorded_parameter_size(const struct d3dx_recorded_parameter *record)
+{
+    return sizeof(*record) + record->bytes;
+}
+
 static void free_parameter_block(struct d3dx_parameter_block *block)
 {
+    struct d3dx_recorded_parameter *record;
+
     if (!block)
         return;
 
+    record = (struct d3dx_recorded_parameter *)block->buffer;
+    while ((BYTE *)record < block->buffer + block->current_size)
+    {
+        free_parameter_object_data(record->param, record + 1, record->bytes);
+        record = (struct d3dx_recorded_parameter *)((BYTE *)record + get_recorded_parameter_size(record));
+    }
+    assert((BYTE *)record == block->buffer + block->current_size);
+
+    heap_free(block->buffer);
     heap_free(block);
 }
 
@@ -1293,6 +1319,46 @@ static ULONG64 next_effect_update_version(struct d3dx_effect *effect)
     return next_update_version(get_version_counter_ptr(effect));
 }
 
+static void record_parameter(struct d3dx_effect *effect, struct d3dx_parameter *param, const void *data,
+        unsigned int bytes)
+{
+    struct d3dx_parameter_block *block = effect->current_parameter_block;
+    struct d3dx_recorded_parameter new_record, *record;
+    unsigned int new_size, alloc_size;
+
+    if (!block)
+        return;
+
+    assert(bytes <= param->bytes);
+
+    new_record.param = param;
+    new_record.bytes = bytes;
+    new_size = block->current_size + get_recorded_parameter_size(&new_record);
+
+    if (new_size > block->buffer_size)
+    {
+        BYTE *new_alloc;
+
+        alloc_size = max(block->buffer_size * 2, max(new_size, INITIAL_PARAM_BLOCK_SIZE));
+        if (block->buffer_size)
+            new_alloc = heap_realloc(block->buffer, alloc_size);
+        else
+            new_alloc = heap_alloc(alloc_size);
+
+        if (!new_alloc)
+        {
+            ERR("Out of memory.\n");
+            return;
+        }
+        block->buffer_size = alloc_size;
+        block->buffer = new_alloc;
+    }
+    record = (struct d3dx_recorded_parameter *)(block->buffer + block->current_size);
+    *record = new_record;
+    get_value(param, record + 1, data, bytes);
+    block->current_size = new_size;
+}
+
 static void set_dirty(struct d3dx_parameter *param)
 {
     struct d3dx_shared_data *shared_data;
@@ -2411,6 +2477,7 @@ static HRESULT WINAPI d3dx_effect_SetValue(ID3DXEffect *iface, D3DXHANDLE parame
     if (data && param->bytes <= bytes)
     {
         set_dirty(param);
+        record_parameter(effect, param, data, param->bytes);
         return set_value(param, data, bytes);
     }
 
@@ -2460,6 +2527,7 @@ static HRESULT WINAPI d3dx_effect_SetBool(ID3DXEffect *iface, D3DXHANDLE paramet
     if (param && !param->element_count && param->rows == 1 && param->columns == 1)
     {
         set_number(param->data, param->type, &b, D3DXPT_BOOL);
+        record_parameter(effect, param, NULL, sizeof(int));
         set_dirty(param);
         return D3D_OK;
     }
@@ -2511,6 +2579,7 @@ static HRESULT WINAPI d3dx_effect_SetBoolArray(ID3DXEffect *iface, D3DXHANDLE pa
                     /* don't crop the input, use D3DXPT_INT instead of D3DXPT_BOOL */
                     set_number((DWORD *)param->data + i, param->type, &b[i], D3DXPT_INT);
                 }
+                record_parameter(effect, param, NULL, count * sizeof(int));
                 set_dirty(param);
                 return D3D_OK;
 
@@ -2571,6 +2640,7 @@ static HRESULT WINAPI d3dx_effect_SetInt(ID3DXEffect *iface, D3DXHANDLE paramete
             set_number(&value, param->type, &n, D3DXPT_INT);
             if (value != *(DWORD *)param->data)
                 set_dirty(param);
+            record_parameter(effect, param, &value, sizeof(int));
             *(DWORD *)param->data = value;
             return D3D_OK;
         }
@@ -2587,6 +2657,7 @@ static HRESULT WINAPI d3dx_effect_SetInt(ID3DXEffect *iface, D3DXHANDLE paramete
             ((float *)param->data)[2] = (n & 0xff) * INT_FLOAT_MULTI_INVERSE;
             if (param->rows * param->columns > 3)
                 ((float *)param->data)[3] = ((n & 0xff000000) >> 24) * INT_FLOAT_MULTI_INVERSE;
+            record_parameter(effect, param, NULL, 4 * sizeof(float));
             set_dirty(param);
             return D3D_OK;
         }
@@ -2655,6 +2726,7 @@ static HRESULT WINAPI d3dx_effect_SetIntArray(ID3DXEffect *iface, D3DXHANDLE par
             case D3DXPC_MATRIX_ROWS:
                 for (i = 0; i < size; ++i)
                     set_number((DWORD *)param->data + i, param->type, &n[i], D3DXPT_INT);
+                record_parameter(effect, param, NULL, size * sizeof(int));
                 set_dirty(param);
                 return D3D_OK;
 
@@ -2712,6 +2784,7 @@ static HRESULT WINAPI d3dx_effect_SetFloat(ID3DXEffect *iface, D3DXHANDLE parame
         if (value != *(DWORD *)param->data)
             set_dirty(param);
         *(DWORD *)param->data = value;
+        record_parameter(effect, param, NULL, sizeof(float));
         return D3D_OK;
     }
 
@@ -2760,6 +2833,7 @@ static HRESULT WINAPI d3dx_effect_SetFloatArray(ID3DXEffect *iface, D3DXHANDLE p
             case D3DXPC_MATRIX_ROWS:
                 for (i = 0; i < size; ++i)
                     set_number((DWORD *)param->data + i, param->type, &f[i], D3DXPT_FLOAT);
+                record_parameter(effect, param, NULL, size * sizeof(float));
                 set_dirty(param);
                 return D3D_OK;
 
@@ -2829,15 +2903,18 @@ static HRESULT WINAPI d3dx_effect_SetVector(ID3DXEffect *iface, D3DXHANDLE param
                     tmp += ((DWORD)(max(min(vector->w, 1.0f), 0.0f) * INT_FLOAT_MULTI)) << 24;
 
                     *(int *)param->data = tmp;
+                    record_parameter(effect, param, NULL, sizeof(int));
                     return D3D_OK;
                 }
                 if (param->type == D3DXPT_FLOAT)
                 {
                     memcpy(param->data, vector, param->columns * sizeof(float));
+                    record_parameter(effect, param, NULL, param->columns * sizeof(float));
                     return D3D_OK;
                 }
 
                 set_vector(param, vector);
+                record_parameter(effect, param, NULL, param->columns * sizeof(float));
                 return D3D_OK;
 
             case D3DXPC_MATRIX_ROWS:
@@ -2920,16 +2997,23 @@ static HRESULT WINAPI d3dx_effect_SetVectorArray(ID3DXEffect *iface, D3DXHANDLE
                 if (param->type == D3DXPT_FLOAT)
                 {
                     if (param->columns == 4)
+                    {
                         memcpy(param->data, vector, count * 4 * sizeof(float));
+                        record_parameter(effect, param, NULL, count * 4 * sizeof(float));
+                    }
                     else
+                    {
                         for (i = 0; i < count; ++i)
                             memcpy((float *)param->data + param->columns * i, vector + i,
                                     param->columns * sizeof(float));
+                        record_parameter(effect, param, NULL, count * param->columns * sizeof(float));
+                    }
                     return D3D_OK;
                 }
 
                 for (i = 0; i < count; ++i)
                     set_vector(&param->members[i], &vector[i]);
+                record_parameter(effect, param, NULL, count * param->columns * sizeof(float));
                 return D3D_OK;
 
             case D3DXPC_SCALAR:
@@ -3005,6 +3089,7 @@ static HRESULT WINAPI d3dx_effect_SetMatrix(ID3DXEffect *iface, D3DXHANDLE param
         {
             case D3DXPC_MATRIX_ROWS:
                 set_matrix(param, matrix);
+                record_parameter(effect, param, NULL, param->rows * param->columns * sizeof(float));
                 set_dirty(param);
                 return D3D_OK;
 
@@ -3078,7 +3163,11 @@ static HRESULT WINAPI d3dx_effect_SetMatrixArray(ID3DXEffect *iface, D3DXHANDLE
             case D3DXPC_MATRIX_ROWS:
                 set_dirty(param);
                 for (i = 0; i < count; ++i)
+                {
                     set_matrix(&param->members[i], &matrix[i]);
+                    record_parameter(effect, &param->members[i], NULL, param->members[i].rows
+                            * param->members[i].columns * sizeof(float));
+                }
                 return D3D_OK;
 
             case D3DXPC_SCALAR:
@@ -3156,7 +3245,11 @@ static HRESULT WINAPI d3dx_effect_SetMatrixPointerArray(ID3DXEffect *iface, D3DX
             case D3DXPC_MATRIX_ROWS:
                 set_dirty(param);
                 for (i = 0; i < count; ++i)
+                {
                     set_matrix(&param->members[i], matrix[i]);
+                    record_parameter(effect, &param->members[i], NULL, param->members[i].rows
+                            * param->members[i].columns * sizeof(float));
+                }
                 return D3D_OK;
 
             case D3DXPC_SCALAR:
@@ -3232,6 +3325,7 @@ static HRESULT WINAPI d3dx_effect_SetMatrixTranspose(ID3DXEffect *iface, D3DXHAN
             case D3DXPC_MATRIX_ROWS:
                 set_dirty(param);
                 set_matrix_transpose(param, matrix);
+                record_parameter(effect, param, NULL, param->rows * param->columns * sizeof(float));
                 return D3D_OK;
 
             case D3DXPC_SCALAR:
@@ -3308,7 +3402,11 @@ static HRESULT WINAPI d3dx_effect_SetMatrixTransposeArray(ID3DXEffect *iface, D3
             case D3DXPC_MATRIX_ROWS:
                 set_dirty(param);
                 for (i = 0; i < count; ++i)
+                {
                     set_matrix_transpose(&param->members[i], &matrix[i]);
+                    record_parameter(effect, &param->members[i], NULL, param->members[i].rows
+                            * param->members[i].columns * sizeof(float));
+                }
                 return D3D_OK;
 
             case D3DXPC_SCALAR:
@@ -3386,7 +3484,11 @@ static HRESULT WINAPI d3dx_effect_SetMatrixTransposePointerArray(ID3DXEffect *if
             case D3DXPC_MATRIX_ROWS:
                 set_dirty(param);
                 for (i = 0; i < count; ++i)
+                {
                     set_matrix_transpose(&param->members[i], matrix[i]);
+                    record_parameter(effect, &param->members[i], NULL, param->members[i].rows
+                            * param->members[i].columns * sizeof(float));
+                }
                 return D3D_OK;
 
             case D3DXPC_SCALAR:
@@ -3455,6 +3557,10 @@ static HRESULT WINAPI d3dx_effect_SetString(ID3DXEffect *iface, D3DXHANDLE param
     if (param && param->type == D3DXPT_STRING)
     {
         set_dirty(param);
+
+        if (effect->current_parameter_block)
+            FIXME("Recording string parameters not supported.\n");
+
         return set_string(param->data, string);
     }
 
@@ -3507,6 +3613,7 @@ static HRESULT WINAPI d3dx_effect_SetTexture(ID3DXEffect *iface, D3DXHANDLE para
 
         *(IDirect3DBaseTexture9 **)param->data = texture;
         set_dirty(param);
+        record_parameter(effect, param, NULL, sizeof(void *));
 
         return D3D_OK;
     }
@@ -4148,6 +4255,10 @@ static D3DXHANDLE WINAPI d3dx_effect_EndParameterBlock(ID3DXEffect *iface)
         return NULL;
     }
     ret = effect->current_parameter_block;
+
+    ret->buffer = heap_realloc(ret->buffer, ret->current_size);
+    ret->buffer_size = ret->current_size;
+
     effect->current_parameter_block = NULL;
     list_add_tail(&effect->parameter_block_list, &ret->entry);
     return (D3DXHANDLE)ret;
diff --git a/dlls/d3dx9_36/tests/effect.c b/dlls/d3dx9_36/tests/effect.c
index 1732a77541..d24e04a753 100644
--- a/dlls/d3dx9_36/tests/effect.c
+++ b/dlls/d3dx9_36/tests/effect.c
@@ -8134,21 +8134,21 @@ static void test_effect_parameter_block(void)
      * Maybe native d3dx is using some copy on write strategy. */
     IDirect3DTexture9_AddRef(texture);
     refcount = IDirect3DTexture9_Release(texture);
-    ok(refcount == 2, "Got unexpected refcount %u.\n", refcount);
+    todo_wine ok(refcount == 2, "Got unexpected refcount %u.\n", refcount);
 
     block = effect->lpVtbl->EndParameterBlock(effect);
     ok(!!block, "Got unexpected block %p.\n", block);
 
     IDirect3DTexture9_AddRef(texture);
     refcount = IDirect3DTexture9_Release(texture);
-    ok(refcount == 2, "Got unexpected refcount %u.\n", refcount);
+    todo_wine ok(refcount == 2, "Got unexpected refcount %u.\n", refcount);
 
     hr = effect->lpVtbl->SetTexture(effect, "tex1", NULL);
     ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
 
     IDirect3DTexture9_AddRef(texture);
     refcount = IDirect3DTexture9_Release(texture);
-    todo_wine ok(refcount == 2, "Got unexpected refcount %u.\n", refcount);
+    ok(refcount == 2, "Got unexpected refcount %u.\n", refcount);
 
     hr = effect->lpVtbl->SetFloat(effect, "arr2[0]", 0.0f);
     ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
-- 
2.23.0




More information about the wine-devel mailing list