[v2 PATCH 1/2] d3drm: Initial support for storing animation keys

Nikolay Sivov nsivov at codeweavers.com
Wed Jul 5 04:02:06 CDT 2017


Signed-off-by: Nikolay Sivov <nsivov at codeweavers.com>
---

v2: changed the way helper are structured; now using bsearch()

 dlls/d3drm/d3drm_private.h |  23 ++++++
 dlls/d3drm/frame.c         | 190 ++++++++++++++++++++++++++++++++++++++++++++-
 dlls/d3drm/meshbuilder.c   |   2 +-
 dlls/d3drm/tests/d3drm.c   |  11 +--
 4 files changed, 214 insertions(+), 12 deletions(-)

diff --git a/dlls/d3drm/d3drm_private.h b/dlls/d3drm/d3drm_private.h
index 1ce29e592e..067c0e6ffe 100644
--- a/dlls/d3drm/d3drm_private.h
+++ b/dlls/d3drm/d3drm_private.h
@@ -208,6 +208,24 @@ struct d3drm_material
     struct color_rgb ambient;
 };
 
+struct d3drm_animation_key
+{
+    D3DVALUE time;
+    union
+    {
+        D3DVECTOR position;
+        D3DVECTOR scale;
+        D3DRMQUATERNION rotate;
+    } u;
+};
+
+struct d3drm_animation_keys
+{
+    struct d3drm_animation_key *keys;
+    SIZE_T count;
+    SIZE_T size;
+};
+
 struct d3drm_animation
 {
     struct d3drm_object obj;
@@ -217,6 +235,9 @@ struct d3drm_animation
     IDirect3DRM *d3drm;
     IDirect3DRMFrame3 *frame;
     D3DRMANIMATIONOPTIONS options;
+    struct d3drm_animation_keys position;
+    struct d3drm_animation_keys scale;
+    struct d3drm_animation_keys rotate;
 };
 
 struct d3drm_wrap
@@ -282,4 +303,6 @@ static inline void d3drm_set_color(D3DCOLOR *color, float r, float g, float b, f
             d3drm_color_component(b), d3drm_color_component(a));
 }
 
+BOOL d3drm_array_reserve(void **elements, SIZE_T *capacity, SIZE_T element_count, SIZE_T element_size) DECLSPEC_HIDDEN;
+
 #endif /* __D3DRM_PRIVATE_INCLUDED__ */
diff --git a/dlls/d3drm/frame.c b/dlls/d3drm/frame.c
index f6b0a1fe14..57ea078b6e 100644
--- a/dlls/d3drm/frame.c
+++ b/dlls/d3drm/frame.c
@@ -3095,6 +3095,9 @@ static ULONG WINAPI d3drm_animation2_Release(IDirect3DRMAnimation2 *iface)
     {
         d3drm_object_cleanup((IDirect3DRMObject *)&animation->IDirect3DRMAnimation_iface, &animation->obj);
         IDirect3DRM_Release(animation->d3drm);
+        HeapFree(GetProcessHeap(), 0, animation->position.keys);
+        HeapFree(GetProcessHeap(), 0, animation->scale.keys);
+        HeapFree(GetProcessHeap(), 0, animation->rotate.keys);
         HeapFree(GetProcessHeap(), 0, animation);
     }
 
@@ -3288,11 +3291,139 @@ static HRESULT WINAPI d3drm_animation1_SetOptions(IDirect3DRMAnimation *iface, D
     return d3drm_animation2_SetOptions(&animation->IDirect3DRMAnimation2_iface, options);
 }
 
+struct d3drm_animation_compare_key
+{
+    D3DVALUE time;
+    struct d3drm_animation_key *cursor;
+};
+
+static int d3drm_animation_compare_keys(const void *a, const void *b)
+{
+    struct d3drm_animation_compare_key *key0 = (void *)a;
+    struct d3drm_animation_key *key1 = (void *)b;
+    float diff = key0->time - key1->time;
+
+    key0->cursor = key1;
+    return diff == 0.0f ? 0 : (diff > 0.0f ? 1 : -1);
+}
+
+static struct d3drm_animation_key *d3drm_animation_lookup_key(struct d3drm_animation_keys *keys,
+        DWORD start_index, D3DVALUE time)
+{
+    struct d3drm_animation_compare_key key0;
+
+    key0.time = time;
+    key0.cursor = NULL;
+    bsearch(&key0, &keys->keys[start_index], keys->count - start_index, sizeof(*keys->keys),
+            d3drm_animation_compare_keys);
+
+    return key0.cursor;
+}
+
+static DWORD d3drm_animation_get_index_min(struct d3drm_animation_keys *keys, D3DVALUE time)
+{
+    struct d3drm_animation_key *key;
+
+    key = d3drm_animation_lookup_key(keys, 0, time);
+    while (key > keys->keys && key[-1].time == time)
+        key--;
+
+    return key - keys->keys;
+}
+
+static DWORD d3drm_animation_get_index_max(struct d3drm_animation_keys *keys, DWORD start_index, D3DVALUE time)
+{
+    struct d3drm_animation_key *key;
+
+    key = d3drm_animation_lookup_key(keys, start_index, time);
+    while (key < &keys->keys[keys->count - 1] && key[1].time == time)
+        key++;
+
+    return key - keys->keys;
+}
+
+static DWORD d3drm_animation_get_insert_position(struct d3drm_animation_keys *keys, D3DVALUE time)
+{
+    if (keys->count == 0)
+        return 0;
+
+    if (time < keys->keys[0].time)
+        return 0;
+
+    if (time >= keys->keys[keys->count - 1].time)
+        return keys->count;
+
+    return d3drm_animation_get_index_max(keys, 0, time);
+}
+
+static const struct d3drm_animation_key *d3drm_animation_get_range(struct d3drm_animation_keys *keys,
+        D3DVALUE time_min, D3DVALUE time_max, DWORD *count)
+{
+    DWORD min, max;
+
+    if (keys->count == 0)
+        return NULL;
+
+    if (time_min > keys->keys[keys->count - 1].time || time_max < keys->keys[0].time)
+        return NULL;
+
+    min = d3drm_animation_get_index_min(keys, time_min);
+    max = d3drm_animation_get_index_max(keys, min, time_max);
+
+    *count = max - min + 1;
+
+    return &keys->keys[min];
+}
+
 static HRESULT WINAPI d3drm_animation2_AddKey(IDirect3DRMAnimation2 *iface, D3DRMANIMATIONKEY *key)
 {
-    FIXME("iface %p, key %p.\n", iface, key);
+    struct d3drm_animation *animation = impl_from_IDirect3DRMAnimation2(iface);
+    struct d3drm_animation_keys *keys;
+    DWORD index;
 
-    return E_NOTIMPL;
+    TRACE("iface %p, key %p.\n", iface, key);
+
+    if (!key || key->dwSize != sizeof(*key))
+        return E_INVALIDARG;
+
+    switch (key->dwKeyType)
+    {
+    case D3DRMANIMATION_POSITIONKEY:
+        keys = &animation->position;
+        break;
+    case D3DRMANIMATION_SCALEKEY:
+        keys = &animation->scale;
+        break;
+    case D3DRMANIMATION_ROTATEKEY:
+        keys = &animation->rotate;
+        break;
+    default:
+        return E_INVALIDARG;
+    }
+
+    index = d3drm_animation_get_insert_position(keys, key->dvTime);
+
+    if (!d3drm_array_reserve((void **)&keys->keys, &keys->size, keys->count + 1, sizeof(*keys->keys)))
+        return E_OUTOFMEMORY;
+
+    if (index < keys->count)
+        memmove(keys->keys + index + 1, keys->keys + index, sizeof(*keys->keys) * (keys->count - index));
+    keys->keys[index].time = key->dvTime;
+    switch (key->dwKeyType)
+    {
+    case D3DRMANIMATION_POSITIONKEY:
+        keys->keys[index].u.position = key->u.dvPositionKey;
+        break;
+    case D3DRMANIMATION_SCALEKEY:
+        keys->keys[index].u.scale = key->u.dvScaleKey;
+        break;
+    case D3DRMANIMATION_ROTATEKEY:
+        keys->keys[index].u.rotate = key->u.dqRotateKey;
+        break;
+    }
+    keys->count++;
+
+    return D3DRM_OK;
 }
 
 static HRESULT WINAPI d3drm_animation2_AddRotateKey(IDirect3DRMAnimation2 *iface, D3DVALUE time, D3DRMQUATERNION *q)
@@ -3484,9 +3615,60 @@ static HRESULT WINAPI d3drm_animation2_ModifyKey(IDirect3DRMAnimation2 *iface, D
 static HRESULT WINAPI d3drm_animation2_GetKeys(IDirect3DRMAnimation2 *iface, D3DVALUE time_min, D3DVALUE time_max,
         DWORD *key_count, D3DRMANIMATIONKEY *keys)
 {
-    FIXME("iface %p, time min %.e, time max %.e, count %p, keys %p.\n", iface, time_min, time_max, key_count, keys);
+    struct d3drm_animation *animation = impl_from_IDirect3DRMAnimation2(iface);
+    const struct d3drm_animation_key *key;
+    DWORD count;
 
-    return E_NOTIMPL;
+    TRACE("iface %p, time min %.e, time max %.e, key_count %p, keys %p.\n", iface, time_min, time_max, key_count, keys);
+
+    if (!key_count)
+        return D3DRMERR_BADVALUE;
+
+    *key_count = 0;
+
+    if ((key = d3drm_animation_get_range(&animation->rotate, time_min, time_max, &count)))
+    {
+        *key_count += count;
+
+        for (; count && keys; count--, keys++, key++)
+        {
+            keys->dwSize = sizeof(*keys);
+            keys->dwKeyType = D3DRMANIMATION_ROTATEKEY;
+            keys->dvTime = key->time;
+            keys->dwID = 0; /* FIXME */
+            keys->u.dqRotateKey = key->u.rotate;
+        }
+    }
+
+    if ((key = d3drm_animation_get_range(&animation->position, time_min, time_max, &count)))
+    {
+        *key_count += count;
+
+        for (; count && keys; count--, keys++, key++)
+        {
+            keys->dwSize = sizeof(*keys);
+            keys->dwKeyType = D3DRMANIMATION_POSITIONKEY;
+            keys->dvTime = key->time;
+            keys->dwID = 0; /* FIXME */
+            keys->u.dvPositionKey = key->u.position;
+        }
+    }
+
+    if ((key = d3drm_animation_get_range(&animation->scale, time_min, time_max, &count)))
+    {
+        *key_count += count;
+
+        for (; count && keys; count--, keys++, key++)
+        {
+            keys->dwSize = sizeof(*keys);
+            keys->dwKeyType = D3DRMANIMATION_SCALEKEY;
+            keys->dvTime = key->time;
+            keys->dwID = 0; /* FIXME */
+            keys->u.dvScaleKey = key->u.scale;
+        }
+    }
+
+    return *key_count ? D3DRM_OK : D3DRMERR_NOSUCHKEY;
 }
 
 static const struct IDirect3DRMAnimationVtbl d3drm_animation1_vtbl =
diff --git a/dlls/d3drm/meshbuilder.c b/dlls/d3drm/meshbuilder.c
index e8e7f7e0f2..bb37678785 100644
--- a/dlls/d3drm/meshbuilder.c
+++ b/dlls/d3drm/meshbuilder.c
@@ -260,7 +260,7 @@ char templates[] = {
 "}"
 };
 
-static BOOL d3drm_array_reserve(void **elements, SIZE_T *capacity, SIZE_T element_count, SIZE_T element_size)
+BOOL d3drm_array_reserve(void **elements, SIZE_T *capacity, SIZE_T element_count, SIZE_T element_size)
 {
     SIZE_T new_capacity, max_capacity;
     void *new_elements;
diff --git a/dlls/d3drm/tests/d3drm.c b/dlls/d3drm/tests/d3drm.c
index 5fea2f0459..f19558e248 100644
--- a/dlls/d3drm/tests/d3drm.c
+++ b/dlls/d3drm/tests/d3drm.c
@@ -6885,11 +6885,8 @@ static void test_animation(void)
 
     /* Key management. */
     hr = IDirect3DRMAnimation_AddPositionKey(animation, 0.0f, 1.0f, 0.0f, 0.0f);
-todo_wine
     ok(SUCCEEDED(hr), "Failed to add position key, hr %#x.\n", hr);
 
-if (hr == S_OK)
-{
     hr = IDirect3DRMAnimation_AddScaleKey(animation, 0.0f, 1.0f, 2.0f, 1.0f);
     ok(SUCCEEDED(hr), "Failed to add scale key, hr %#x.\n", hr);
 
@@ -6940,6 +6937,8 @@ if (hr == S_OK)
     {
         ok(keys[i].dwSize == sizeof(*keys), "%u: unexpected dwSize value %u.\n", i, keys[i].dwSize);
 
+    todo_wine
+    {
         switch (keys[i].dwKeyType)
         {
         case D3DRMANIMATION_ROTATEKEY:
@@ -6955,6 +6954,7 @@ if (hr == S_OK)
             ok(0, "%u: unknown key type %d.\n", i, keys[i].dwKeyType);
         }
     }
+    }
 
     /* No keys in this range. */
     count = 10;
@@ -6970,17 +6970,14 @@ if (hr == S_OK)
     count = 10;
     hr = IDirect3DRMAnimation2_GetKeys(animation2, 0.0f, 0.0f, &count, NULL);
     ok(SUCCEEDED(hr), "Failed to get animation keys, hr %#x.\n", hr);
-    ok(hr == S_OK, "Failed to get animation keys, hr %#x.\n", hr);
     ok(count == 4, "Unexpected key count %u.\n", count);
 
     hr = IDirect3DRMAnimation2_GetKeys(animation2, 0.0f, 100.0f, NULL, NULL);
     ok(hr == D3DRMERR_BADVALUE, "Unexpected hr %#x.\n", hr);
 
     /* Time is 0-based. */
-    count = 123;
     hr = IDirect3DRMAnimation2_GetKeys(animation2, -100.0f, -50.0f, NULL, NULL);
     ok(hr == D3DRMERR_BADVALUE, "Unexpected hr %#x.\n", hr);
-    ok(count == 123, "Unexpected key count %u.\n", count);
 
     count = 10;
     hr = IDirect3DRMAnimation2_GetKeys(animation2, -100.0f, -50.0f, &count, NULL);
@@ -7018,7 +7015,7 @@ if (hr == S_OK)
     key.dwKeyType = D3DRMANIMATION_POSITIONKEY;
     hr = IDirect3DRMAnimation2_AddKey(animation2, &key);
     ok(SUCCEEDED(hr), "Failed to add key, hr %#x.\n", hr);
-}
+
     IDirect3DRMAnimation2_Release(animation2);
     IDirect3DRMAnimation_Release(animation);
 
-- 
2.13.2




More information about the wine-patches mailing list