[D3DRM] Sync with Wine Staging 2.16. CORE-13762
authorAmine Khaldi <amine.khaldi@reactos.org>
Sat, 16 Sep 2017 20:44:24 +0000 (20:44 +0000)
committerAmine Khaldi <amine.khaldi@reactos.org>
Sat, 16 Sep 2017 20:44:24 +0000 (20:44 +0000)
svn path=/trunk/; revision=75853

reactos/dll/directx/wine/d3drm/d3drm.c
reactos/dll/directx/wine/d3drm/d3drm_main.c
reactos/dll/directx/wine/d3drm/d3drm_private.h
reactos/dll/directx/wine/d3drm/device.c
reactos/dll/directx/wine/d3drm/face.c
reactos/dll/directx/wine/d3drm/frame.c
reactos/dll/directx/wine/d3drm/light.c
reactos/dll/directx/wine/d3drm/material.c
reactos/dll/directx/wine/d3drm/meshbuilder.c
reactos/dll/directx/wine/d3drm/texture.c
reactos/dll/directx/wine/d3drm/viewport.c

index d1656a9..8c46751 100644 (file)
@@ -79,6 +79,110 @@ static HRESULT d3drm_create_viewport_object(void **object, IDirect3DRM *d3drm)
     return hr;
 }
 
+static HRESULT d3drm_create_face_object(void **object, IDirect3DRM *d3drm)
+{
+    struct d3drm_face *face;
+    HRESULT hr;
+
+    if (FAILED(hr = d3drm_face_create(&face)))
+        return hr;
+
+    *object = &face->IDirect3DRMFace_iface;
+
+    return hr;
+}
+
+static HRESULT d3drm_create_mesh_builder_object(void **object, IDirect3DRM *d3drm)
+{
+    struct d3drm_mesh_builder *mesh_builder;
+    HRESULT hr;
+
+    if (FAILED(hr = d3drm_mesh_builder_create(&mesh_builder, d3drm)))
+        return hr;
+
+    *object = &mesh_builder->IDirect3DRMMeshBuilder2_iface;
+
+    return hr;
+}
+
+static HRESULT d3drm_create_frame_object(void **object, IDirect3DRM *d3drm)
+{
+    struct d3drm_frame *frame;
+    HRESULT hr;
+
+    if (FAILED(hr = d3drm_frame_create(&frame, NULL, d3drm)))
+        return hr;
+
+    *object = &frame->IDirect3DRMFrame_iface;
+
+    return hr;
+}
+
+static HRESULT d3drm_create_light_object(void **object, IDirect3DRM *d3drm)
+{
+    struct d3drm_light *light;
+    HRESULT hr;
+
+    if (FAILED(hr = d3drm_light_create(&light, d3drm)))
+        return hr;
+
+    *object = &light->IDirect3DRMLight_iface;
+
+    return hr;
+}
+
+static HRESULT d3drm_create_material_object(void **object, IDirect3DRM *d3drm)
+{
+    struct d3drm_material *material;
+    HRESULT hr;
+
+    if (FAILED(hr = d3drm_material_create(&material, d3drm)))
+        return hr;
+
+    *object = &material->IDirect3DRMMaterial2_iface;
+
+    return hr;
+}
+
+static HRESULT d3drm_create_mesh_object(void **object, IDirect3DRM *d3drm)
+{
+    struct d3drm_mesh *mesh;
+    HRESULT hr;
+
+    if (FAILED(hr = d3drm_mesh_create(&mesh, d3drm)))
+        return hr;
+
+    *object = &mesh->IDirect3DRMMesh_iface;
+
+    return hr;
+}
+
+static HRESULT d3drm_create_animation_object(void **object, IDirect3DRM *d3drm)
+{
+    struct d3drm_animation *animation;
+    HRESULT hr;
+
+    if (FAILED(hr = d3drm_animation_create(&animation, d3drm)))
+        return hr;
+
+    *object = &animation->IDirect3DRMAnimation_iface;
+
+    return hr;
+}
+
+static HRESULT d3drm_create_wrap_object(void **object, IDirect3DRM *d3drm)
+{
+    struct d3drm_wrap *wrap;
+    HRESULT hr;
+
+    if (FAILED(hr = d3drm_wrap_create(&wrap, d3drm)))
+        return hr;
+
+    *object = &wrap->IDirect3DRMWrap_iface;
+
+    return hr;
+}
+
 struct d3drm
 {
     IDirect3DRM IDirect3DRM_iface;
@@ -202,23 +306,44 @@ static HRESULT WINAPI d3drm1_CreateMesh(IDirect3DRM *iface, IDirect3DRMMesh **me
 
 static HRESULT WINAPI d3drm1_CreateMeshBuilder(IDirect3DRM *iface, IDirect3DRMMeshBuilder **mesh_builder)
 {
+    struct d3drm *d3drm = impl_from_IDirect3DRM(iface);
+
     TRACE("iface %p, mesh_builder %p.\n", iface, mesh_builder);
 
-    return Direct3DRMMeshBuilder_create(&IID_IDirect3DRMMeshBuilder, (IUnknown **)mesh_builder);
+    return IDirect3DRM2_CreateMeshBuilder(&d3drm->IDirect3DRM2_iface, (IDirect3DRMMeshBuilder2 **)mesh_builder);
 }
 
 static HRESULT WINAPI d3drm1_CreateFace(IDirect3DRM *iface, IDirect3DRMFace **face)
 {
+    struct d3drm_face *object;
+    HRESULT hr;
+
     TRACE("iface %p, face %p.\n", iface, face);
 
-    return Direct3DRMFace_create(&IID_IDirect3DRMFace, (IUnknown **)face);
+    if (FAILED(hr = d3drm_face_create(&object)))
+        return hr;
+
+    *face = &object->IDirect3DRMFace_iface;
+
+    return S_OK;
 }
 
 static HRESULT WINAPI d3drm1_CreateAnimation(IDirect3DRM *iface, IDirect3DRMAnimation **animation)
 {
-    FIXME("iface %p, animation %p stub!\n", iface, animation);
+    struct d3drm_animation *object;
+    HRESULT hr;
 
-    return E_NOTIMPL;
+    TRACE("iface %p, animation %p.\n", iface, animation);
+
+    if (!animation)
+        return D3DRMERR_BADVALUE;
+
+    if (FAILED(hr = d3drm_animation_create(&object, iface)))
+        return hr;
+
+    *animation = &object->IDirect3DRMAnimation_iface;
+
+    return S_OK;
 }
 
 static HRESULT WINAPI d3drm1_CreateAnimationSet(IDirect3DRM *iface, IDirect3DRMAnimationSet **set)
@@ -402,9 +527,25 @@ static HRESULT WINAPI d3drm1_CreateDeviceFromClipper(IDirect3DRM *iface,
 static HRESULT WINAPI d3drm1_CreateTextureFromSurface(IDirect3DRM *iface,
         IDirectDrawSurface *surface, IDirect3DRMTexture **texture)
 {
-    FIXME("iface %p, surface %p, texture %p stub!\n", iface, surface, texture);
+    struct d3drm *d3drm = impl_from_IDirect3DRM(iface);
+    IDirect3DRMTexture3 *texture3;
+    HRESULT hr;
 
-    return E_NOTIMPL;
+    TRACE("iface %p, surface %p, texture %p.\n", iface, surface, texture);
+
+    if (!texture)
+        return D3DRMERR_BADVALUE;
+
+    if (FAILED(hr = IDirect3DRM3_CreateTextureFromSurface(&d3drm->IDirect3DRM3_iface, surface, &texture3)))
+    {
+        *texture = NULL;
+        return hr;
+    }
+
+    hr = IDirect3DRMTexture3_QueryInterface(texture3, &IID_IDirect3DRMTexture, (void **)texture);
+    IDirect3DRMTexture3_Release(texture3);
+
+    return hr;
 }
 
 static HRESULT WINAPI d3drm1_CreateShadow(IDirect3DRM *iface, IDirect3DRMVisual *visual,
@@ -460,11 +601,22 @@ static HRESULT WINAPI d3drm1_CreateWrap(IDirect3DRM *iface, D3DRMWRAPTYPE type,
         D3DVALUE ux, D3DVALUE uy, D3DVALUE uz, D3DVALUE ou, D3DVALUE ov, D3DVALUE su, D3DVALUE sv,
         IDirect3DRMWrap **wrap)
 {
+    struct d3drm_wrap *object;
+    HRESULT hr;
+
     FIXME("iface %p, type %#x, frame %p, ox %.8e, oy %.8e, oz %.8e, dx %.8e, dy %.8e, dz %.8e, "
-            "ux %.8e, uy %.8e, uz %.8e, ou %.8e, ov %.8e, su %.8e, sv %.8e, wrap %p stub!\n",
+            "ux %.8e, uy %.8e, uz %.8e, ou %.8e, ov %.8e, su %.8e, sv %.8e, wrap %p, semi-stub.\n",
             iface, type, frame, ox, oy, oz, dx, dy, dz, ux, uy, uz, ou, ov, su, sv, wrap);
 
-    return E_NOTIMPL;
+    if (!wrap)
+        return D3DRMERR_BADVALUE;
+
+    if (FAILED(hr = d3drm_wrap_create(&object, iface)))
+        return hr;
+
+    *wrap = &object->IDirect3DRMWrap_iface;
+
+    return S_OK;
 }
 
 static HRESULT WINAPI d3drm1_CreateUserVisual(IDirect3DRM *iface,
@@ -706,23 +858,36 @@ static HRESULT WINAPI d3drm2_CreateMesh(IDirect3DRM2 *iface, IDirect3DRMMesh **m
 
 static HRESULT WINAPI d3drm2_CreateMeshBuilder(IDirect3DRM2 *iface, IDirect3DRMMeshBuilder2 **mesh_builder)
 {
+    struct d3drm *d3drm = impl_from_IDirect3DRM2(iface);
+    struct d3drm_mesh_builder *object;
+    HRESULT hr;
+
     TRACE("iface %p, mesh_builder %p.\n", iface, mesh_builder);
 
-    return Direct3DRMMeshBuilder_create(&IID_IDirect3DRMMeshBuilder2, (IUnknown **)mesh_builder);
+    if (FAILED(hr = d3drm_mesh_builder_create(&object, &d3drm->IDirect3DRM_iface)))
+        return hr;
+
+    *mesh_builder = &object->IDirect3DRMMeshBuilder2_iface;
+
+    return S_OK;
 }
 
 static HRESULT WINAPI d3drm2_CreateFace(IDirect3DRM2 *iface, IDirect3DRMFace **face)
 {
+    struct d3drm *d3drm = impl_from_IDirect3DRM2(iface);
+
     TRACE("iface %p, face %p.\n", iface, face);
 
-    return Direct3DRMFace_create(&IID_IDirect3DRMFace, (IUnknown **)face);
+    return IDirect3DRM_CreateFace(&d3drm->IDirect3DRM_iface, face);
 }
 
 static HRESULT WINAPI d3drm2_CreateAnimation(IDirect3DRM2 *iface, IDirect3DRMAnimation **animation)
 {
-    FIXME("iface %p, animation %p stub!\n", iface, animation);
+    struct d3drm *d3drm = impl_from_IDirect3DRM2(iface);
 
-    return E_NOTIMPL;
+    TRACE("iface %p, animation %p.\n", iface, animation);
+
+    return IDirect3DRM_CreateAnimation(&d3drm->IDirect3DRM_iface, animation);
 }
 
 static HRESULT WINAPI d3drm2_CreateAnimationSet(IDirect3DRM2 *iface, IDirect3DRMAnimationSet **set)
@@ -877,9 +1042,25 @@ static HRESULT WINAPI d3drm2_CreateDeviceFromClipper(IDirect3DRM2 *iface,
 static HRESULT WINAPI d3drm2_CreateTextureFromSurface(IDirect3DRM2 *iface,
         IDirectDrawSurface *surface, IDirect3DRMTexture2 **texture)
 {
-    FIXME("iface %p, surface %p, texture %p stub!\n", iface, surface, texture);
+    struct d3drm *d3drm = impl_from_IDirect3DRM2(iface);
+    IDirect3DRMTexture3 *texture3;
+    HRESULT hr;
 
-    return E_NOTIMPL;
+    TRACE("iface %p, surface %p, texture %p.\n", iface, surface, texture);
+
+    if (!texture)
+        return D3DRMERR_BADVALUE;
+
+    if (FAILED(hr = IDirect3DRM3_CreateTextureFromSurface(&d3drm->IDirect3DRM3_iface, surface, &texture3)))
+    {
+        *texture = NULL;
+        return hr;
+    }
+
+    hr = IDirect3DRMTexture3_QueryInterface(texture3, &IID_IDirect3DRMTexture, (void **)texture);
+    IDirect3DRMTexture3_Release(texture3);
+
+    return hr;
 }
 
 static HRESULT WINAPI d3drm2_CreateShadow(IDirect3DRM2 *iface, IDirect3DRMVisual *visual,
@@ -935,11 +1116,14 @@ static HRESULT WINAPI d3drm2_CreateWrap(IDirect3DRM2 *iface, D3DRMWRAPTYPE type,
         D3DVALUE ux, D3DVALUE uy, D3DVALUE uz, D3DVALUE ou, D3DVALUE ov, D3DVALUE su, D3DVALUE sv,
         IDirect3DRMWrap **wrap)
 {
-    FIXME("iface %p, type %#x, frame %p, ox %.8e, oy %.8e, oz %.8e, dx %.8e, dy %.8e, dz %.8e, "
-            "ux %.8e, uy %.8e, uz %.8e, ou %.8e, ov %.8e, su %.8e, sv %.8e, wrap %p stub!\n",
+    struct d3drm *d3drm = impl_from_IDirect3DRM2(iface);
+
+    TRACE("iface %p, type %#x, frame %p, ox %.8e, oy %.8e, oz %.8e, dx %.8e, dy %.8e, dz %.8e, "
+            "ux %.8e, uy %.8e, uz %.8e, ou %.8e, ov %.8e, su %.8e, sv %.8e, wrap %p.\n",
             iface, type, frame, ox, oy, oz, dx, dy, dz, ux, uy, uz, ou, ov, su, sv, wrap);
 
-    return E_NOTIMPL;
+    return IDirect3DRM_CreateWrap(&d3drm->IDirect3DRM_iface, type, frame, ox, oy, oz, dx, dy, dz, ux, uy, uz,
+            ou, ov, su, sv, wrap);
 }
 
 static HRESULT WINAPI d3drm2_CreateUserVisual(IDirect3DRM2 *iface,
@@ -1171,6 +1355,14 @@ static HRESULT WINAPI d3drm3_CreateObject(IDirect3DRM3 *iface,
         {&CLSID_CDirect3DRMTexture, d3drm_create_texture_object},
         {&CLSID_CDirect3DRMDevice, d3drm_create_device_object},
         {&CLSID_CDirect3DRMViewport, d3drm_create_viewport_object},
+        {&CLSID_CDirect3DRMFace, d3drm_create_face_object},
+        {&CLSID_CDirect3DRMMeshBuilder, d3drm_create_mesh_builder_object},
+        {&CLSID_CDirect3DRMFrame, d3drm_create_frame_object},
+        {&CLSID_CDirect3DRMLight, d3drm_create_light_object},
+        {&CLSID_CDirect3DRMMaterial, d3drm_create_material_object},
+        {&CLSID_CDirect3DRMMesh, d3drm_create_mesh_object},
+        {&CLSID_CDirect3DRMAnimation, d3drm_create_animation_object},
+        {&CLSID_CDirect3DRMWrap, d3drm_create_wrap_object},
     };
 
     TRACE("iface %p, clsid %s, outer %p, iid %s, out %p.\n",
@@ -1237,30 +1429,67 @@ static HRESULT WINAPI d3drm3_CreateFrame(IDirect3DRM3 *iface,
 
 static HRESULT WINAPI d3drm3_CreateMesh(IDirect3DRM3 *iface, IDirect3DRMMesh **mesh)
 {
+    struct d3drm *d3drm = impl_from_IDirect3DRM3(iface);
+    struct d3drm_mesh *object;
+    HRESULT hr;
+
     TRACE("iface %p, mesh %p.\n", iface, mesh);
 
-    return Direct3DRMMesh_create(mesh);
+    if (FAILED(hr = d3drm_mesh_create(&object, &d3drm->IDirect3DRM_iface)))
+        return hr;
+
+    *mesh = &object->IDirect3DRMMesh_iface;
+
+    return S_OK;
 }
 
 static HRESULT WINAPI d3drm3_CreateMeshBuilder(IDirect3DRM3 *iface, IDirect3DRMMeshBuilder3 **mesh_builder)
 {
+    struct d3drm *d3drm = impl_from_IDirect3DRM3(iface);
+    struct d3drm_mesh_builder *object;
+    HRESULT hr;
+
     TRACE("iface %p, mesh_builder %p.\n", iface, mesh_builder);
 
-    return Direct3DRMMeshBuilder_create(&IID_IDirect3DRMMeshBuilder3, (IUnknown **)mesh_builder);
+    if (FAILED(hr = d3drm_mesh_builder_create(&object, &d3drm->IDirect3DRM_iface)))
+        return hr;
+
+    *mesh_builder = &object->IDirect3DRMMeshBuilder3_iface;
+
+    return S_OK;
 }
 
 static HRESULT WINAPI d3drm3_CreateFace(IDirect3DRM3 *iface, IDirect3DRMFace2 **face)
 {
+    struct d3drm *d3drm = impl_from_IDirect3DRM3(iface);
+    IDirect3DRMFace *face1;
+    HRESULT hr;
+
     TRACE("iface %p, face %p.\n", iface, face);
 
-    return Direct3DRMFace_create(&IID_IDirect3DRMFace2, (IUnknown **)face);
+    if (FAILED(hr = IDirect3DRM_CreateFace(&d3drm->IDirect3DRM_iface, &face1)))
+        return hr;
+
+    hr = IDirect3DRMFace_QueryInterface(face1, &IID_IDirect3DRMFace2, (void **)face);
+    IDirect3DRMFace_Release(face1);
+
+    return hr;
 }
 
 static HRESULT WINAPI d3drm3_CreateAnimation(IDirect3DRM3 *iface, IDirect3DRMAnimation2 **animation)
 {
-    FIXME("iface %p, animation %p stub!\n", iface, animation);
+    struct d3drm *d3drm = impl_from_IDirect3DRM3(iface);
+    struct d3drm_animation *object;
+    HRESULT hr;
 
-    return E_NOTIMPL;
+    TRACE("iface %p, animation %p.\n", iface, animation);
+
+    if (FAILED(hr = d3drm_animation_create(&object, &d3drm->IDirect3DRM_iface)))
+        return hr;
+
+    *animation = &object->IDirect3DRMAnimation2_iface;
+
+    return hr;
 }
 
 static HRESULT WINAPI d3drm3_CreateAnimationSet(IDirect3DRM3 *iface, IDirect3DRMAnimationSet2 **set)
@@ -1300,45 +1529,57 @@ static HRESULT WINAPI d3drm3_CreateTexture(IDirect3DRM3 *iface,
 static HRESULT WINAPI d3drm3_CreateLight(IDirect3DRM3 *iface,
         D3DRMLIGHTTYPE type, D3DCOLOR color, IDirect3DRMLight **light)
 {
+    struct d3drm *d3drm = impl_from_IDirect3DRM3(iface);
+    struct d3drm_light *object;
     HRESULT hr;
 
     FIXME("iface %p, type %#x, color 0x%08x, light %p partial stub!\n", iface, type, color, light);
 
-    if (SUCCEEDED(hr = Direct3DRMLight_create((IUnknown **)light)))
+    if (SUCCEEDED(hr = d3drm_light_create(&object, &d3drm->IDirect3DRM_iface)))
     {
-        IDirect3DRMLight_SetType(*light, type);
-        IDirect3DRMLight_SetColor(*light, color);
+        IDirect3DRMLight_SetType(&object->IDirect3DRMLight_iface, type);
+        IDirect3DRMLight_SetColor(&object->IDirect3DRMLight_iface, color);
     }
 
+    *light = &object->IDirect3DRMLight_iface;
+
     return hr;
 }
 
 static HRESULT WINAPI d3drm3_CreateLightRGB(IDirect3DRM3 *iface, D3DRMLIGHTTYPE type,
         D3DVALUE red, D3DVALUE green, D3DVALUE blue, IDirect3DRMLight **light)
 {
+    struct d3drm *d3drm = impl_from_IDirect3DRM3(iface);
+    struct d3drm_light *object;
     HRESULT hr;
 
     FIXME("iface %p, type %#x, red %.8e, green %.8e, blue %.8e, light %p partial stub!\n",
             iface, type, red, green, blue, light);
 
-    if (SUCCEEDED(hr = Direct3DRMLight_create((IUnknown **)light)))
+    if (SUCCEEDED(hr = d3drm_light_create(&object, &d3drm->IDirect3DRM_iface)))
     {
-        IDirect3DRMLight_SetType(*light, type);
-        IDirect3DRMLight_SetColorRGB(*light, red, green, blue);
+        IDirect3DRMLight_SetType(&object->IDirect3DRMLight_iface, type);
+        IDirect3DRMLight_SetColorRGB(&object->IDirect3DRMLight_iface, red, green, blue);
     }
 
+    *light = &object->IDirect3DRMLight_iface;
+
     return hr;
 }
 
 static HRESULT WINAPI d3drm3_CreateMaterial(IDirect3DRM3 *iface,
         D3DVALUE power, IDirect3DRMMaterial2 **material)
 {
+    struct d3drm *d3drm = impl_from_IDirect3DRM3(iface);
+    struct d3drm_material *object;
     HRESULT hr;
 
     TRACE("iface %p, power %.8e, material %p.\n", iface, power, material);
 
-    if (SUCCEEDED(hr = Direct3DRMMaterial_create(material)))
-        IDirect3DRMMaterial2_SetPower(*material, power);
+    if (SUCCEEDED(hr = d3drm_material_create(&object, &d3drm->IDirect3DRM_iface)))
+        IDirect3DRMMaterial2_SetPower(&object->IDirect3DRMMaterial2_iface, power);
+
+    *material = &object->IDirect3DRMMaterial2_iface;
 
     return hr;
 }
@@ -1479,9 +1720,28 @@ static HRESULT WINAPI d3drm3_CreateShadow(IDirect3DRM3 *iface, IUnknown *object,
 static HRESULT WINAPI d3drm3_CreateTextureFromSurface(IDirect3DRM3 *iface,
         IDirectDrawSurface *surface, IDirect3DRMTexture3 **texture)
 {
-    FIXME("iface %p, surface %p, texture %p stub!\n", iface, surface, texture);
+    struct d3drm *d3drm = impl_from_IDirect3DRM3(iface);
+    struct d3drm_texture *object;
+    HRESULT hr;
 
-    return E_NOTIMPL;
+    TRACE("iface %p, surface %p, texture %p.\n", iface, surface, texture);
+
+    if (!texture)
+        return D3DRMERR_BADVALUE;
+
+    if (FAILED(hr = d3drm_texture_create(&object, &d3drm->IDirect3DRM_iface)))
+        return hr;
+
+    *texture = &object->IDirect3DRMTexture3_iface;
+
+    if (FAILED(IDirect3DRMTexture3_InitFromSurface(*texture, surface)))
+    {
+        IDirect3DRMTexture3_Release(*texture);
+        *texture = NULL;
+        return D3DRMERR_BADVALUE;
+    }
+
+    return D3DRM_OK;
 }
 
 static HRESULT WINAPI d3drm3_CreateViewport(IDirect3DRM3 *iface, IDirect3DRMDevice3 *device,
@@ -1519,11 +1779,23 @@ static HRESULT WINAPI d3drm3_CreateWrap(IDirect3DRM3 *iface, D3DRMWRAPTYPE type,
         D3DVALUE ux, D3DVALUE uy, D3DVALUE uz, D3DVALUE ou, D3DVALUE ov, D3DVALUE su, D3DVALUE sv,
         IDirect3DRMWrap **wrap)
 {
+    struct d3drm *d3drm = impl_from_IDirect3DRM3(iface);
+    struct d3drm_wrap *object;
+    HRESULT hr;
+
     FIXME("iface %p, type %#x, frame %p, ox %.8e, oy %.8e, oz %.8e, dx %.8e, dy %.8e, dz %.8e, "
-            "ux %.8e, uy %.8e, uz %.8e, ou %.8e, ov %.8e, su %.8e, sv %.8e, wrap %p stub!\n",
+            "ux %.8e, uy %.8e, uz %.8e, ou %.8e, ov %.8e, su %.8e, sv %.8e, wrap %p, semi-stub.\n",
             iface, type, frame, ox, oy, oz, dx, dy, dz, ux, uy, uz, ou, ov, su, sv, wrap);
 
-    return E_NOTIMPL;
+    if (!wrap)
+        return D3DRMERR_BADVALUE;
+
+    if (FAILED(hr = d3drm_wrap_create(&object, &d3drm->IDirect3DRM_iface)))
+        return hr;
+
+    *wrap = &object->IDirect3DRMWrap_iface;
+
+    return S_OK;
 }
 
 static HRESULT WINAPI d3drm3_CreateUserVisual(IDirect3DRM3 *iface,
index 57ab529..5071671 100644 (file)
@@ -35,11 +35,13 @@ BOOL WINAPI DllMain(HINSTANCE inst, DWORD reason, void *reserved)
     return TRUE;
 }
 
-void d3drm_object_init(struct d3drm_object *object)
+void d3drm_object_init(struct d3drm_object *object, const char *classname)
 {
     object->ref = 1;
     object->appdata = 0;
     list_init(&object->destroy_callbacks);
+    object->classname = classname;
+    object->name = NULL;
 }
 
 struct destroy_callback
@@ -87,6 +89,67 @@ HRESULT d3drm_object_delete_destroy_callback(struct d3drm_object *object, D3DRMO
     return D3DRM_OK;
 }
 
+HRESULT d3drm_object_get_class_name(struct d3drm_object *object, DWORD *size, char *name)
+{
+    DWORD req_size;
+
+    if (!size)
+        return E_INVALIDARG;
+
+    req_size = strlen(object->classname) + 1;
+    if (name && *size < req_size)
+        return E_INVALIDARG;
+
+    *size = req_size;
+
+    if (name)
+        memcpy(name, object->classname, req_size);
+
+    return D3DRM_OK;
+}
+
+HRESULT d3drm_object_get_name(struct d3drm_object *object, DWORD *size, char *name)
+{
+    DWORD req_size;
+
+    if (!size)
+        return E_INVALIDARG;
+
+    req_size = object->name ? strlen(object->name) + 1 : 0;
+    if (name && *size < req_size)
+        return E_INVALIDARG;
+
+    if (name)
+    {
+        if (object->name)
+            memcpy(name, object->name, req_size);
+        else if (*size)
+            *name = 0;
+    }
+
+    *size = req_size;
+
+    return D3DRM_OK;
+}
+
+HRESULT d3drm_object_set_name(struct d3drm_object *object, const char *name)
+{
+    DWORD req_size;
+
+    HeapFree(GetProcessHeap(), 0, object->name);
+    object->name = NULL;
+
+    if (name)
+    {
+        req_size = strlen(name) + 1;
+        if (!(object->name = HeapAlloc(GetProcessHeap(), 0, req_size)))
+            return E_OUTOFMEMORY;
+        memcpy(object->name, name, req_size);
+    }
+
+    return D3DRM_OK;
+}
+
 void d3drm_object_cleanup(IDirect3DRMObject *iface, struct d3drm_object *object)
 {
     struct destroy_callback *callback, *callback2;
@@ -97,4 +160,7 @@ void d3drm_object_cleanup(IDirect3DRMObject *iface, struct d3drm_object *object)
         list_remove(&callback->entry);
         HeapFree(GetProcessHeap(), 0, callback);
     }
+
+    HeapFree(GetProcessHeap(), 0, object->name);
+    object->name = NULL;
 }
index 255ff7f..f6391a9 100644 (file)
@@ -53,6 +53,8 @@ struct d3drm_object
     LONG ref;
     DWORD appdata;
     struct list destroy_callbacks;
+    const char *classname;
+    char *name;
 };
 
 struct d3drm_texture
@@ -63,27 +65,30 @@ struct d3drm_texture
     IDirect3DRMTexture3 IDirect3DRMTexture3_iface;
     IDirect3DRM *d3drm;
     D3DRMIMAGE *image;
+    IDirectDrawSurface *surface;
 };
 
 struct d3drm_frame
 {
+    struct d3drm_object obj;
     IDirect3DRMFrame IDirect3DRMFrame_iface;
     IDirect3DRMFrame2 IDirect3DRMFrame2_iface;
     IDirect3DRMFrame3 IDirect3DRMFrame3_iface;
     IDirect3DRM *d3drm;
     LONG ref;
     struct d3drm_frame *parent;
-    ULONG nb_children;
-    ULONG children_capacity;
+    SIZE_T nb_children;
+    SIZE_T children_size;
     IDirect3DRMFrame3 **children;
-    ULONG nb_visuals;
-    ULONG visuals_capacity;
+    SIZE_T nb_visuals;
+    SIZE_T visuals_size;
     IDirect3DRMVisual **visuals;
-    ULONG nb_lights;
-    ULONG lights_capacity;
+    SIZE_T nb_lights;
+    SIZE_T lights_size;
     IDirect3DRMLight **lights;
     D3DRMMATRIX4D transform;
     D3DCOLOR scenebackground;
+    DWORD traversal_options;
 };
 
 struct d3drm_viewport
@@ -121,6 +126,139 @@ struct d3drm_device
     DWORD width;
 };
 
+struct d3drm_face
+{
+    struct d3drm_object obj;
+    IDirect3DRMFace IDirect3DRMFace_iface;
+    IDirect3DRMFace2 IDirect3DRMFace2_iface;
+    LONG ref;
+    D3DCOLOR color;
+};
+
+struct d3drm_mesh_builder
+{
+    struct d3drm_object obj;
+    IDirect3DRMMeshBuilder2 IDirect3DRMMeshBuilder2_iface;
+    IDirect3DRMMeshBuilder3 IDirect3DRMMeshBuilder3_iface;
+    LONG ref;
+    IDirect3DRM *d3drm;
+    SIZE_T nb_vertices;
+    SIZE_T vertices_size;
+    D3DVECTOR *vertices;
+    SIZE_T nb_normals;
+    SIZE_T normals_size;
+    D3DVECTOR *normals;
+    DWORD nb_faces;
+    DWORD face_data_size;
+    void *pFaceData;
+    DWORD nb_coords2d;
+    struct coords_2d *pCoords2d;
+    D3DCOLOR color;
+    IDirect3DRMMaterial2 *material;
+    IDirect3DRMTexture3 *texture;
+    DWORD nb_materials;
+    struct mesh_material *materials;
+    DWORD *material_indices;
+};
+
+struct mesh_group
+{
+    unsigned nb_vertices;
+    D3DRMVERTEX* vertices;
+    unsigned nb_faces;
+    unsigned vertex_per_face;
+    DWORD face_data_size;
+    unsigned* face_data;
+    D3DCOLOR color;
+    IDirect3DRMMaterial2* material;
+    IDirect3DRMTexture3* texture;
+};
+
+struct d3drm_mesh
+{
+    struct d3drm_object obj;
+    IDirect3DRMMesh IDirect3DRMMesh_iface;
+    LONG ref;
+    IDirect3DRM *d3drm;
+    SIZE_T nb_groups;
+    SIZE_T groups_size;
+    struct mesh_group *groups;
+};
+
+struct d3drm_light
+{
+    struct d3drm_object obj;
+    IDirect3DRMLight IDirect3DRMLight_iface;
+    LONG ref;
+    IDirect3DRM *d3drm;
+    D3DRMLIGHTTYPE type;
+    D3DCOLOR color;
+    D3DVALUE range;
+    D3DVALUE cattenuation;
+    D3DVALUE lattenuation;
+    D3DVALUE qattenuation;
+    D3DVALUE umbra;
+    D3DVALUE penumbra;
+};
+
+struct color_rgb
+{
+    D3DVALUE r;
+    D3DVALUE g;
+    D3DVALUE b;
+};
+
+struct d3drm_material
+{
+    struct d3drm_object obj;
+    IDirect3DRMMaterial2 IDirect3DRMMaterial2_iface;
+    LONG ref;
+    IDirect3DRM *d3drm;
+    struct color_rgb emissive;
+    struct color_rgb specular;
+    D3DVALUE power;
+    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;
+    IDirect3DRMAnimation2 IDirect3DRMAnimation2_iface;
+    IDirect3DRMAnimation IDirect3DRMAnimation_iface;
+    LONG ref;
+    IDirect3DRM *d3drm;
+    IDirect3DRMFrame3 *frame;
+    D3DRMANIMATIONOPTIONS options;
+    struct d3drm_animation_keys position;
+    struct d3drm_animation_keys scale;
+    struct d3drm_animation_keys rotate;
+};
+
+struct d3drm_wrap
+{
+    struct d3drm_object obj;
+    IDirect3DRMWrap IDirect3DRMWrap_iface;
+    LONG ref;
+};
+
 HRESULT d3drm_device_create(struct d3drm_device **device, IDirect3DRM *d3drm) DECLSPEC_HIDDEN;
 HRESULT d3drm_device_create_surfaces_from_clipper(struct d3drm_device *object, IDirectDraw *ddraw,
         IDirectDrawClipper *clipper, int width, int height, IDirectDrawSurface **surface) DECLSPEC_HIDDEN;
@@ -128,9 +266,12 @@ void d3drm_device_destroy(struct d3drm_device *device) DECLSPEC_HIDDEN;
 HRESULT d3drm_device_init(struct d3drm_device *device, UINT version, IDirectDraw *ddraw,
         IDirectDrawSurface *surface, BOOL create_z_surface) DECLSPEC_HIDDEN;
 
-void d3drm_object_init(struct d3drm_object *object) DECLSPEC_HIDDEN;
+void d3drm_object_init(struct d3drm_object *object, const char *classname) DECLSPEC_HIDDEN;
 HRESULT d3drm_object_add_destroy_callback(struct d3drm_object *object, D3DRMOBJECTCALLBACK cb, void *ctx) DECLSPEC_HIDDEN;
 HRESULT d3drm_object_delete_destroy_callback(struct d3drm_object *object, D3DRMOBJECTCALLBACK cb, void *ctx) DECLSPEC_HIDDEN;
+HRESULT d3drm_object_get_class_name(struct d3drm_object *object, DWORD *size, char *name) DECLSPEC_HIDDEN;
+HRESULT d3drm_object_get_name(struct d3drm_object *object, DWORD *size, char *name) DECLSPEC_HIDDEN;
+HRESULT d3drm_object_set_name(struct d3drm_object *object, const char *name) DECLSPEC_HIDDEN;
 void d3drm_object_cleanup(IDirect3DRMObject *iface, struct d3drm_object *object) DECLSPEC_HIDDEN;
 
 struct d3drm_frame *unsafe_impl_from_IDirect3DRMFrame(IDirect3DRMFrame *iface) DECLSPEC_HIDDEN;
@@ -138,12 +279,14 @@ struct d3drm_device *unsafe_impl_from_IDirect3DRMDevice3(IDirect3DRMDevice3 *ifa
 
 HRESULT d3drm_texture_create(struct d3drm_texture **texture, IDirect3DRM *d3drm) DECLSPEC_HIDDEN;
 HRESULT d3drm_frame_create(struct d3drm_frame **frame, IUnknown *parent_frame, IDirect3DRM *d3drm) DECLSPEC_HIDDEN;
+HRESULT d3drm_face_create(struct d3drm_face **face) DECLSPEC_HIDDEN;
 HRESULT d3drm_viewport_create(struct d3drm_viewport **viewport, IDirect3DRM *d3drm) DECLSPEC_HIDDEN;
-HRESULT Direct3DRMFace_create(REFIID riid, IUnknown** ret_iface) DECLSPEC_HIDDEN;
-HRESULT Direct3DRMLight_create(IUnknown** ppObj) DECLSPEC_HIDDEN;
-HRESULT Direct3DRMMesh_create(IDirect3DRMMesh** obj) DECLSPEC_HIDDEN;
-HRESULT Direct3DRMMeshBuilder_create(REFIID riid, IUnknown** ppObj) DECLSPEC_HIDDEN;
-HRESULT Direct3DRMMaterial_create(IDirect3DRMMaterial2** ret_iface) DECLSPEC_HIDDEN;
+HRESULT d3drm_mesh_builder_create(struct d3drm_mesh_builder **mesh_builder, IDirect3DRM *d3drm) DECLSPEC_HIDDEN;
+HRESULT d3drm_light_create(struct d3drm_light **light, IDirect3DRM *d3drm) DECLSPEC_HIDDEN;
+HRESULT d3drm_material_create(struct d3drm_material **material, IDirect3DRM *d3drm) DECLSPEC_HIDDEN;
+HRESULT d3drm_mesh_create(struct d3drm_mesh **mesh, IDirect3DRM *d3drm) DECLSPEC_HIDDEN;
+HRESULT d3drm_animation_create(struct d3drm_animation **animation, IDirect3DRM *d3drm) DECLSPEC_HIDDEN;
+HRESULT d3drm_wrap_create(struct d3drm_wrap **wrap, IDirect3DRM *d3drm) DECLSPEC_HIDDEN;
 
 HRESULT load_mesh_data(IDirect3DRMMeshBuilder3 *iface, IDirectXFileData *data,
                        D3DRMLOADTEXTURECALLBACK load_texture_proc, void *arg) DECLSPEC_HIDDEN;
@@ -172,4 +315,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__ */
index 03884ab..865e372 100644 (file)
@@ -449,9 +449,13 @@ static HRESULT WINAPI d3drm_device1_DeleteDestroyCallback(IDirect3DRMDevice *ifa
 
 static HRESULT WINAPI d3drm_device3_SetAppData(IDirect3DRMDevice3 *iface, DWORD data)
 {
-    FIXME("iface %p, data %#x stub!\n", iface, data);
+    struct d3drm_device *device = impl_from_IDirect3DRMDevice3(iface);
 
-    return E_NOTIMPL;
+    TRACE("iface %p, data %#x.\n", iface, data);
+
+    device->obj.appdata = data;
+
+    return D3DRM_OK;
 }
 
 static HRESULT WINAPI d3drm_device2_SetAppData(IDirect3DRMDevice2 *iface, DWORD data)
@@ -474,9 +478,11 @@ static HRESULT WINAPI d3drm_device1_SetAppData(IDirect3DRMDevice *iface, DWORD d
 
 static DWORD WINAPI d3drm_device3_GetAppData(IDirect3DRMDevice3 *iface)
 {
-    FIXME("iface %p stub!\n", iface);
+    struct d3drm_device *device = impl_from_IDirect3DRMDevice3(iface);
+
+    TRACE("iface %p.\n", iface);
 
-    return 0;
+    return device->obj.appdata;
 }
 
 static DWORD WINAPI d3drm_device2_GetAppData(IDirect3DRMDevice2 *iface)
@@ -499,9 +505,11 @@ static DWORD WINAPI d3drm_device1_GetAppData(IDirect3DRMDevice *iface)
 
 static HRESULT WINAPI d3drm_device3_SetName(IDirect3DRMDevice3 *iface, const char *name)
 {
-    FIXME("iface %p, name %s stub!\n", iface, debugstr_a(name));
+    struct d3drm_device *device = impl_from_IDirect3DRMDevice3(iface);
 
-    return E_NOTIMPL;
+    TRACE("iface %p, name %s.\n", iface, debugstr_a(name));
+
+    return d3drm_object_set_name(&device->obj, name);
 }
 
 static HRESULT WINAPI d3drm_device2_SetName(IDirect3DRMDevice2 *iface, const char *name)
@@ -524,9 +532,11 @@ static HRESULT WINAPI d3drm_device1_SetName(IDirect3DRMDevice *iface, const char
 
 static HRESULT WINAPI d3drm_device3_GetName(IDirect3DRMDevice3 *iface, DWORD *size, char *name)
 {
-    FIXME("iface %p, size %p, name %p stub!\n", iface, size, name);
+    struct d3drm_device *device = impl_from_IDirect3DRMDevice3(iface);
 
-    return E_NOTIMPL;
+    TRACE("iface %p, size %p, name %p.\n", iface, size, name);
+
+    return d3drm_object_get_name(&device->obj, size, name);
 }
 
 static HRESULT WINAPI d3drm_device2_GetName(IDirect3DRMDevice2 *iface, DWORD *size, char *name)
@@ -549,15 +559,11 @@ static HRESULT WINAPI d3drm_device1_GetName(IDirect3DRMDevice *iface, DWORD *siz
 
 static HRESULT WINAPI d3drm_device3_GetClassName(IDirect3DRMDevice3 *iface, DWORD *size, char *name)
 {
-    TRACE("iface %p, size %p, name %p.\n", iface, size, name);
-
-    if (!size || *size < strlen("Device") || !name)
-        return E_INVALIDARG;
+    struct d3drm_device *device = impl_from_IDirect3DRMDevice3(iface);
 
-    strcpy(name, "Device");
-    *size = sizeof("Device");
+    TRACE("iface %p, size %p, name %p.\n", iface, size, name);
 
-    return D3DRM_OK;
+    return d3drm_object_get_class_name(&device->obj, size, name);
 }
 
 static HRESULT WINAPI d3drm_device2_GetClassName(IDirect3DRMDevice2 *iface, DWORD *size, char *name)
@@ -1625,6 +1631,7 @@ struct d3drm_device *unsafe_impl_from_IDirect3DRMDevice3(IDirect3DRMDevice3 *ifa
 
 HRESULT d3drm_device_create(struct d3drm_device **device, IDirect3DRM *d3drm)
 {
+    static const char classname[] = "Device";
     struct d3drm_device *object;
 
     TRACE("device %p, d3drm %p.\n", device, d3drm);
@@ -1637,7 +1644,7 @@ HRESULT d3drm_device_create(struct d3drm_device **device, IDirect3DRM *d3drm)
     object->IDirect3DRMDevice3_iface.lpVtbl = &d3drm_device3_vtbl;
     object->IDirect3DRMWinDevice_iface.lpVtbl = &d3drm_device_win_vtbl;
     object->d3drm = d3drm;
-    d3drm_object_init(&object->obj);
+    d3drm_object_init(&object->obj, classname);
 
     *device = object;
 
index 746cfe8..ff492d0 100644 (file)
 
 #include "d3drm_private.h"
 
-struct d3drm_face
-{
-    IDirect3DRMFace IDirect3DRMFace_iface;
-    IDirect3DRMFace2 IDirect3DRMFace2_iface;
-    LONG ref;
-};
-
 static inline struct d3drm_face *impl_from_IDirect3DRMFace(IDirect3DRMFace *iface)
 {
     return CONTAINING_RECORD(iface, struct d3drm_face, IDirect3DRMFace_iface);
@@ -43,8 +36,8 @@ static HRESULT WINAPI d3drm_face1_QueryInterface(IDirect3DRMFace *iface, REFIID
 
     TRACE("iface %p, riid %s, out %p.\n", iface, debugstr_guid(riid), out);
 
-
     if (IsEqualGUID(riid, &IID_IDirect3DRMFace)
+            || IsEqualGUID(riid, &IID_IDirect3DRMObject)
             || IsEqualGUID(riid, &IID_IUnknown))
     {
         *out = &face->IDirect3DRMFace_iface;
@@ -82,7 +75,10 @@ static ULONG WINAPI d3drm_face1_Release(IDirect3DRMFace *iface)
     TRACE("%p decreasing refcount to %u.\n", iface, refcount);
 
     if (!refcount)
+    {
+        d3drm_object_cleanup((IDirect3DRMObject *)iface, &face->obj);
         HeapFree(GetProcessHeap(), 0, face);
+    }
 
     return refcount;
 }
@@ -98,45 +94,95 @@ static HRESULT WINAPI d3drm_face1_Clone(IDirect3DRMFace *iface,
 static HRESULT WINAPI d3drm_face1_AddDestroyCallback(IDirect3DRMFace *iface,
         D3DRMOBJECTCALLBACK cb, void *ctx)
 {
-    FIXME("iface %p, cb %p, ctx %p stub!\n", iface, cb, ctx);
+    struct d3drm_face *face = impl_from_IDirect3DRMFace(iface);
 
-    return E_NOTIMPL;
+    TRACE("iface %p, cb %p, ctx %p.\n", iface, cb, ctx);
+
+    return IDirect3DRMFace2_AddDestroyCallback(&face->IDirect3DRMFace2_iface, cb, ctx);
 }
 
 static HRESULT WINAPI d3drm_face1_DeleteDestroyCallback(IDirect3DRMFace *iface,
         D3DRMOBJECTCALLBACK cb, void *ctx)
 {
-    FIXME("iface %p, cb %p, ctx %p stub!\n", iface, cb, ctx);
+    struct d3drm_face *face = impl_from_IDirect3DRMFace(iface);
 
-    return E_NOTIMPL;
+    TRACE("iface %p, cb %p, ctx %p.\n", iface, cb, ctx);
+
+    return IDirect3DRMFace2_DeleteDestroyCallback(&face->IDirect3DRMFace2_iface, cb, ctx);
+}
+
+static HRESULT WINAPI d3drm_face2_SetAppData(IDirect3DRMFace2 *iface, DWORD data)
+{
+    struct d3drm_face *face = impl_from_IDirect3DRMFace2(iface);
+
+    TRACE("iface %p, data %#x.\n", iface, data);
+
+    face->obj.appdata = data;
+
+    return D3DRM_OK;
 }
 
 static HRESULT WINAPI d3drm_face1_SetAppData(IDirect3DRMFace *iface, DWORD data)
 {
-    FIXME("iface %p, data %#x stub!\n", iface, data);
+    struct d3drm_face *face = impl_from_IDirect3DRMFace(iface);
 
-    return E_NOTIMPL;
+    TRACE("iface %p, data %#x.\n", iface, data);
+
+    return d3drm_face2_SetAppData(&face->IDirect3DRMFace2_iface, data);
+}
+
+static DWORD WINAPI d3drm_face2_GetAppData(IDirect3DRMFace2 *iface)
+{
+    struct d3drm_face *face = impl_from_IDirect3DRMFace2(iface);
+
+    TRACE("iface %p.\n", iface);
+
+    return face->obj.appdata;
 }
 
 static DWORD WINAPI d3drm_face1_GetAppData(IDirect3DRMFace *iface)
 {
-    FIXME("iface %p stub!\n", iface);
+    struct d3drm_face *face = impl_from_IDirect3DRMFace(iface);
 
-    return 0;
+    TRACE("iface %p.\n", iface);
+
+    return d3drm_face2_GetAppData(&face->IDirect3DRMFace2_iface);
+}
+
+static HRESULT WINAPI d3drm_face2_SetName(IDirect3DRMFace2 *iface, const char *name)
+{
+    struct d3drm_face *face = impl_from_IDirect3DRMFace2(iface);
+
+    TRACE("iface %p, name %s.\n", iface, debugstr_a(name));
+
+    return d3drm_object_set_name(&face->obj, name);
 }
 
 static HRESULT WINAPI d3drm_face1_SetName(IDirect3DRMFace *iface, const char *name)
 {
-    FIXME("iface %p, name %s stub!\n", iface, debugstr_a(name));
+    struct d3drm_face *face = impl_from_IDirect3DRMFace(iface);
 
-    return E_NOTIMPL;
+    TRACE("iface %p, name %s.\n", iface, debugstr_a(name));
+
+    return d3drm_face2_SetName(&face->IDirect3DRMFace2_iface, name);
+}
+
+static HRESULT WINAPI d3drm_face2_GetName(IDirect3DRMFace2 *iface, DWORD *size, char *name)
+{
+    struct d3drm_face *face = impl_from_IDirect3DRMFace2(iface);
+
+    TRACE("iface %p, size %p, name %p.\n", iface, size, name);
+
+    return d3drm_object_get_name(&face->obj, size, name);
 }
 
 static HRESULT WINAPI d3drm_face1_GetName(IDirect3DRMFace *iface, DWORD *size, char *name)
 {
-    FIXME("iface %p, size %p, name %p stub!\n", iface, size, name);
+    struct d3drm_face *face = impl_from_IDirect3DRMFace(iface);
 
-    return E_NOTIMPL;
+    TRACE("iface %p, size %p, name %p.\n", iface, size, name);
+
+    return d3drm_face2_GetName(&face->IDirect3DRMFace2_iface, size, name);
 }
 
 static HRESULT WINAPI d3drm_face1_GetClassName(IDirect3DRMFace *iface, DWORD *size, char *name)
@@ -163,19 +209,45 @@ static HRESULT WINAPI d3drm_face1_AddVertexAndNormalIndexed(IDirect3DRMFace *ifa
     return E_NOTIMPL;
 }
 
+static HRESULT WINAPI d3drm_face2_SetColorRGB(IDirect3DRMFace2 *iface, D3DVALUE red, D3DVALUE green, D3DVALUE blue)
+{
+    struct d3drm_face *face = impl_from_IDirect3DRMFace2(iface);
+
+    TRACE("iface %p, red %.8e, green %.8e, blue %.8e.\n", iface, red, green, blue);
+
+    d3drm_set_color(&face->color, red, green, blue, 1.0f);
+
+    return D3DRM_OK;
+}
+
 static HRESULT WINAPI d3drm_face1_SetColorRGB(IDirect3DRMFace *iface,
-        D3DVALUE r, D3DVALUE g, D3DVALUE b)
+        D3DVALUE red, D3DVALUE green, D3DVALUE blue)
 {
-    FIXME("iface %p, r %.8e, g %.8e, b %.8e stub!\n", iface, r, g, b);
+    struct d3drm_face *face = impl_from_IDirect3DRMFace(iface);
 
-    return E_NOTIMPL;
+    TRACE("iface %p, red %.8e, green %.8e, blue %.8e.\n", iface, red, green, blue);
+
+    return d3drm_face2_SetColorRGB(&face->IDirect3DRMFace2_iface, red, green, blue);
+}
+
+static HRESULT WINAPI d3drm_face2_SetColor(IDirect3DRMFace2 *iface, D3DCOLOR color)
+{
+    struct d3drm_face *face = impl_from_IDirect3DRMFace2(iface);
+
+    TRACE("iface %p, color 0x%08x.\n", iface, color);
+
+    face->color = color;
+
+    return D3DRM_OK;
 }
 
 static HRESULT WINAPI d3drm_face1_SetColor(IDirect3DRMFace *iface, D3DCOLOR color)
 {
-    FIXME("iface %p, color 0x%08x stub!\n", iface, color);
+    struct d3drm_face *face = impl_from_IDirect3DRMFace(iface);
 
-    return E_NOTIMPL;
+    TRACE("iface %p, color 0x%08x.\n", iface, color);
+
+    return d3drm_face2_SetColor(&face->IDirect3DRMFace2_iface, color);
 }
 
 static HRESULT WINAPI d3drm_face1_SetTexture(IDirect3DRMFace *iface, IDirect3DRMTexture *texture)
@@ -281,11 +353,22 @@ static int WINAPI d3drm_face1_GetTextureCoordinateIndex(IDirect3DRMFace *iface,
     return 0;
 }
 
+static D3DCOLOR WINAPI d3drm_face2_GetColor(IDirect3DRMFace2 *iface)
+{
+    struct d3drm_face *face = impl_from_IDirect3DRMFace2(iface);
+
+    TRACE("iface %p.\n", iface);
+
+    return face->color;
+}
+
 static D3DCOLOR WINAPI d3drm_face1_GetColor(IDirect3DRMFace *iface)
 {
-    FIXME("iface %p stub!\n", iface);
+    struct d3drm_face *face = impl_from_IDirect3DRMFace(iface);
 
-    return 0;
+    TRACE("iface %p.\n", iface);
+
+    return d3drm_face2_GetColor(&face->IDirect3DRMFace2_iface);
 }
 
 static const struct IDirect3DRMFaceVtbl d3drm_face1_vtbl =
@@ -354,58 +437,30 @@ static HRESULT WINAPI d3drm_face2_Clone(IDirect3DRMFace2 *iface,
 static HRESULT WINAPI d3drm_face2_AddDestroyCallback(IDirect3DRMFace2 *iface,
         D3DRMOBJECTCALLBACK cb, void *ctx)
 {
-    FIXME("iface %p, cb %p, ctx %p stub!\n", iface, cb, ctx);
+    struct d3drm_face *face = impl_from_IDirect3DRMFace2(iface);
 
-    return E_NOTIMPL;
+    TRACE("iface %p, cb %p, ctx %p.\n", iface, cb, ctx);
+
+    return d3drm_object_add_destroy_callback(&face->obj, cb, ctx);
 }
 
 static HRESULT WINAPI d3drm_face2_DeleteDestroyCallback(IDirect3DRMFace2 *iface,
         D3DRMOBJECTCALLBACK cb, void *ctx)
 {
-    FIXME("iface %p, cb %p, ctx %p stub!\n", iface, cb, ctx);
-
-    return E_NOTIMPL;
-}
-
-static HRESULT WINAPI d3drm_face2_SetAppData(IDirect3DRMFace2 *iface, DWORD data)
-{
-    FIXME("iface %p, data %#x stub!\n", iface, data);
-
-    return E_NOTIMPL;
-}
-
-static DWORD WINAPI d3drm_face2_GetAppData(IDirect3DRMFace2 *iface)
-{
-    FIXME("iface %p stub!\n", iface);
-
-    return 0;
-}
-
-static HRESULT WINAPI d3drm_face2_SetName(IDirect3DRMFace2 *iface, const char *name)
-{
-    FIXME("iface %p, name %s stub!\n", iface, debugstr_a(name));
-
-    return E_NOTIMPL;
-}
+    struct d3drm_face *face = impl_from_IDirect3DRMFace2(iface);
 
-static HRESULT WINAPI d3drm_face2_GetName(IDirect3DRMFace2 *iface, DWORD *size, char *name)
-{
-    FIXME("iface %p, size %p, name %p stub!\n", iface, size, name);
+    TRACE("iface %p, cb %p, ctx %p.\n", iface, cb, ctx);
 
-    return E_NOTIMPL;
+    return d3drm_object_delete_destroy_callback(&face->obj, cb, ctx);
 }
 
 static HRESULT WINAPI d3drm_face2_GetClassName(IDirect3DRMFace2 *iface, DWORD *size, char *name)
 {
-    TRACE("iface %p, size %p, name %p.\n", iface, size, name);
-
-    if (!size || *size < strlen("Face") || !name)
-        return E_INVALIDARG;
+    struct d3drm_face *face = impl_from_IDirect3DRMFace2(iface);
 
-    strcpy(name, "Face");
-    *size = sizeof("Face");
+    TRACE("iface %p, size %p, name %p.\n", iface, size, name);
 
-    return D3DRM_OK;
+    return d3drm_object_get_class_name(&face->obj, size, name);
 }
 
 static HRESULT WINAPI d3drm_face2_AddVertex(IDirect3DRMFace2 *iface, D3DVALUE x, D3DVALUE y, D3DVALUE z)
@@ -423,20 +478,6 @@ static HRESULT WINAPI d3drm_face2_AddVertexAndNormalIndexed(IDirect3DRMFace2 *if
     return E_NOTIMPL;
 }
 
-static HRESULT WINAPI d3drm_face2_SetColorRGB(IDirect3DRMFace2 *iface, D3DVALUE r, D3DVALUE g, D3DVALUE b)
-{
-    FIXME("iface %p, r %.8e, g %.8e, b %.8e stub!\n", iface, r, g, b);
-
-    return E_NOTIMPL;
-}
-
-static HRESULT WINAPI d3drm_face2_SetColor(IDirect3DRMFace2 *iface, D3DCOLOR color)
-{
-    FIXME("iface %p, color 0x%08x stub!\n", iface, color);
-
-    return E_NOTIMPL;
-}
-
 static HRESULT WINAPI d3drm_face2_SetTexture(IDirect3DRMFace2 *iface, IDirect3DRMTexture3 *texture)
 {
     FIXME("iface %p, texture %p stub!\n", iface, texture);
@@ -540,13 +581,6 @@ static int WINAPI d3drm_face2_GetTextureCoordinateIndex(IDirect3DRMFace2 *iface,
     return 0;
 }
 
-static D3DCOLOR WINAPI d3drm_face2_GetColor(IDirect3DRMFace2 *iface)
-{
-    FIXME("iface %p stub!\n", iface);
-
-    return 0;
-}
-
 static const struct IDirect3DRMFace2Vtbl d3drm_face2_vtbl =
 {
     d3drm_face2_QueryInterface,
@@ -581,11 +615,12 @@ static const struct IDirect3DRMFace2Vtbl d3drm_face2_vtbl =
     d3drm_face2_GetColor,
 };
 
-HRESULT Direct3DRMFace_create(REFIID riid, IUnknown **out)
+HRESULT d3drm_face_create(struct d3drm_face **face)
 {
+    static const char classname[] = "Face";
     struct d3drm_face *object;
 
-    TRACE("riid %s, out %p.\n", debugstr_guid(riid), out);
+    TRACE("face %p.\n", face);
 
     if (!(object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*object))))
         return E_OUTOFMEMORY;
@@ -594,10 +629,9 @@ HRESULT Direct3DRMFace_create(REFIID riid, IUnknown **out)
     object->IDirect3DRMFace2_iface.lpVtbl = &d3drm_face2_vtbl;
     object->ref = 1;
 
-    if (IsEqualGUID(riid, &IID_IDirect3DRMFace2))
-        *out = (IUnknown*)&object->IDirect3DRMFace2_iface;
-    else
-        *out = (IUnknown*)&object->IDirect3DRMFace_iface;
+    d3drm_object_init(&object->obj, classname);
+
+    *face = object;
 
     return S_OK;
 }
index 11684e0..1f1fcdb 100644 (file)
@@ -84,6 +84,16 @@ static inline struct d3drm_light_array *impl_from_IDirect3DRMLightArray(IDirect3
     return CONTAINING_RECORD(iface, struct d3drm_light_array, IDirect3DRMLightArray_iface);
 }
 
+static inline struct d3drm_animation *impl_from_IDirect3DRMAnimation(IDirect3DRMAnimation *iface)
+{
+    return CONTAINING_RECORD(iface, struct d3drm_animation, IDirect3DRMAnimation_iface);
+}
+
+static inline struct d3drm_animation *impl_from_IDirect3DRMAnimation2(IDirect3DRMAnimation2 *iface)
+{
+    return CONTAINING_RECORD(iface, struct d3drm_animation, IDirect3DRMAnimation2_iface);
+}
+
 static HRESULT WINAPI d3drm_frame_array_QueryInterface(IDirect3DRMFrameArray *iface, REFIID riid, void **out)
 {
     TRACE("iface %p, riid %s, out %p.\n", iface, debugstr_guid(riid), out);
@@ -528,6 +538,7 @@ static ULONG WINAPI d3drm_frame3_Release(IDirect3DRMFrame3 *iface)
 
     if (!refcount)
     {
+        d3drm_object_cleanup((IDirect3DRMObject *)&frame->IDirect3DRMFrame_iface, &frame->obj);
         for (i = 0; i < frame->nb_children; ++i)
         {
             IDirect3DRMFrame3_Release(frame->children[i]);
@@ -543,6 +554,7 @@ static ULONG WINAPI d3drm_frame3_Release(IDirect3DRMFrame3 *iface)
             IDirect3DRMLight_Release(frame->lights[i]);
         }
         HeapFree(GetProcessHeap(), 0, frame->lights);
+        IDirect3DRM_Release(frame->d3drm);
         HeapFree(GetProcessHeap(), 0, frame);
     }
 
@@ -594,146 +606,180 @@ static HRESULT WINAPI d3drm_frame1_Clone(IDirect3DRMFrame *iface,
 static HRESULT WINAPI d3drm_frame3_AddDestroyCallback(IDirect3DRMFrame3 *iface,
         D3DRMOBJECTCALLBACK cb, void *ctx)
 {
-    FIXME("iface %p, cb %p, ctx %p stub!\n", iface, cb, ctx);
+    struct d3drm_frame *frame = impl_from_IDirect3DRMFrame3(iface);
 
-    return E_NOTIMPL;
+    TRACE("iface %p, cb %p, ctx %p.\n", iface, cb, ctx);
+
+    return d3drm_object_add_destroy_callback(&frame->obj, cb, ctx);
 }
 
 static HRESULT WINAPI d3drm_frame2_AddDestroyCallback(IDirect3DRMFrame2 *iface,
         D3DRMOBJECTCALLBACK cb, void *ctx)
 {
-    FIXME("iface %p, cb %p, ctx %p stub!\n", iface, cb, ctx);
+    struct d3drm_frame *frame = impl_from_IDirect3DRMFrame2(iface);
 
-    return E_NOTIMPL;
+    TRACE("iface %p, cb %p, ctx %p.\n", iface, cb, ctx);
+
+    return IDirect3DRMFrame3_AddDestroyCallback(&frame->IDirect3DRMFrame3_iface, cb, ctx);
 }
 
 static HRESULT WINAPI d3drm_frame1_AddDestroyCallback(IDirect3DRMFrame *iface,
         D3DRMOBJECTCALLBACK cb, void *ctx)
 {
-    FIXME("iface %p, cb %p, ctx %p stub!\n", iface, cb, ctx);
+    struct d3drm_frame *frame = impl_from_IDirect3DRMFrame(iface);
 
-    return E_NOTIMPL;
+    TRACE("iface %p, cb %p, ctx %p.\n", iface, cb, ctx);
+
+    return IDirect3DRMFrame3_AddDestroyCallback(&frame->IDirect3DRMFrame3_iface, cb, ctx);
 }
 
 static HRESULT WINAPI d3drm_frame3_DeleteDestroyCallback(IDirect3DRMFrame3 *iface,
         D3DRMOBJECTCALLBACK cb, void *ctx)
 {
-    FIXME("iface %p, cb %p, ctx %p stub!\n", iface, cb, ctx);
+    struct d3drm_frame *frame = impl_from_IDirect3DRMFrame3(iface);
 
-    return E_NOTIMPL;
+    TRACE("iface %p, cb %p, ctx %p.\n", iface, cb, ctx);
+
+    return d3drm_object_delete_destroy_callback(&frame->obj, cb, ctx);
 }
 
 static HRESULT WINAPI d3drm_frame2_DeleteDestroyCallback(IDirect3DRMFrame2 *iface,
         D3DRMOBJECTCALLBACK cb, void *ctx)
 {
-    FIXME("iface %p, cb %p, ctx %p stub!\n", iface, cb, ctx);
+    struct d3drm_frame *frame = impl_from_IDirect3DRMFrame2(iface);
 
-    return E_NOTIMPL;
+    TRACE("iface %p, cb %p, ctx %p.\n", iface, cb, ctx);
+
+    return IDirect3DRMFrame3_DeleteDestroyCallback(&frame->IDirect3DRMFrame3_iface, cb, ctx);
 }
 
 static HRESULT WINAPI d3drm_frame1_DeleteDestroyCallback(IDirect3DRMFrame *iface,
         D3DRMOBJECTCALLBACK cb, void *ctx)
 {
-    FIXME("iface %p, cb %p, ctx %p stub!\n", iface, cb, ctx);
+    struct d3drm_frame *frame = impl_from_IDirect3DRMFrame(iface);
 
-    return E_NOTIMPL;
+    TRACE("iface %p, cb %p, ctx %p.\n", iface, cb, ctx);
+
+    return IDirect3DRMFrame3_DeleteDestroyCallback(&frame->IDirect3DRMFrame3_iface, cb, ctx);
 }
 
 static HRESULT WINAPI d3drm_frame3_SetAppData(IDirect3DRMFrame3 *iface, DWORD data)
 {
-    FIXME("iface %p, data %#x stub!\n", iface, data);
+    struct d3drm_frame *frame = impl_from_IDirect3DRMFrame3(iface);
 
-    return E_NOTIMPL;
+    TRACE("iface %p, data %#x.\n", iface, data);
+
+    frame->obj.appdata = data;
+
+    return D3DRM_OK;
 }
 
 static HRESULT WINAPI d3drm_frame2_SetAppData(IDirect3DRMFrame2 *iface, DWORD data)
 {
-    FIXME("iface %p, data %#x stub!\n", iface, data);
+    struct d3drm_frame *frame = impl_from_IDirect3DRMFrame2(iface);
 
-    return E_NOTIMPL;
+    TRACE("iface %p, data %#x.\n", iface, data);
+
+    return d3drm_frame3_SetAppData(&frame->IDirect3DRMFrame3_iface, data);
 }
 
 static HRESULT WINAPI d3drm_frame1_SetAppData(IDirect3DRMFrame *iface, DWORD data)
 {
-    FIXME("iface %p, data %#x stub!\n", iface, data);
+    struct d3drm_frame *frame = impl_from_IDirect3DRMFrame(iface);
 
-    return E_NOTIMPL;
+    TRACE("iface %p, data %#x.\n", iface, data);
+
+    return d3drm_frame3_SetAppData(&frame->IDirect3DRMFrame3_iface, data);
 }
 
 static DWORD WINAPI d3drm_frame3_GetAppData(IDirect3DRMFrame3 *iface)
 {
-    FIXME("iface %p stub!\n", iface);
+    struct d3drm_frame *frame = impl_from_IDirect3DRMFrame3(iface);
 
-    return 0;
+    TRACE("iface %p.\n", iface);
+
+    return frame->obj.appdata;
 }
 
 static DWORD WINAPI d3drm_frame2_GetAppData(IDirect3DRMFrame2 *iface)
 {
-    FIXME("iface %p stub!\n", iface);
+    struct d3drm_frame *frame = impl_from_IDirect3DRMFrame2(iface);
 
-    return 0;
+    TRACE("iface %p.\n", iface);
+
+    return d3drm_frame3_GetAppData(&frame->IDirect3DRMFrame3_iface);
 }
 
 static DWORD WINAPI d3drm_frame1_GetAppData(IDirect3DRMFrame *iface)
 {
-    FIXME("iface %p stub!\n", iface);
+    struct d3drm_frame *frame = impl_from_IDirect3DRMFrame(iface);
 
-    return 0;
+    TRACE("iface %p.\n", iface);
+
+    return d3drm_frame3_GetAppData(&frame->IDirect3DRMFrame3_iface);
 }
 
 static HRESULT WINAPI d3drm_frame3_SetName(IDirect3DRMFrame3 *iface, const char *name)
 {
-    FIXME("iface %p, name %s stub!\n", iface, debugstr_a(name));
+    struct d3drm_frame *frame = impl_from_IDirect3DRMFrame3(iface);
 
-    return E_NOTIMPL;
+    TRACE("iface %p, name %s.\n", iface, debugstr_a(name));
+
+    return d3drm_object_set_name(&frame->obj, name);
 }
 
 static HRESULT WINAPI d3drm_frame2_SetName(IDirect3DRMFrame2 *iface, const char *name)
 {
-    FIXME("iface %p, name %s stub!\n", iface, debugstr_a(name));
+    struct d3drm_frame *frame = impl_from_IDirect3DRMFrame2(iface);
 
-    return E_NOTIMPL;
+    TRACE("iface %p, name %s.\n", iface, debugstr_a(name));
+
+    return d3drm_frame3_SetName(&frame->IDirect3DRMFrame3_iface, name);
 }
 
 static HRESULT WINAPI d3drm_frame1_SetName(IDirect3DRMFrame *iface, const char *name)
 {
-    FIXME("iface %p, name %s stub!\n", iface, debugstr_a(name));
+    struct d3drm_frame *frame = impl_from_IDirect3DRMFrame(iface);
 
-    return E_NOTIMPL;
+    TRACE("iface %p, name %s.\n", iface, debugstr_a(name));
+
+    return d3drm_frame3_SetName(&frame->IDirect3DRMFrame3_iface, name);
 }
 
 static HRESULT WINAPI d3drm_frame3_GetName(IDirect3DRMFrame3 *iface, DWORD *size, char *name)
 {
-    FIXME("iface %p, size %p, name %p stub!\n", iface, size, name);
+    struct d3drm_frame *frame = impl_from_IDirect3DRMFrame3(iface);
 
-    return E_NOTIMPL;
+    TRACE("iface %p, size %p, name %p.\n", iface, size, name);
+
+    return d3drm_object_get_name(&frame->obj, size, name);
 }
 
 static HRESULT WINAPI d3drm_frame2_GetName(IDirect3DRMFrame2 *iface, DWORD *size, char *name)
 {
-    FIXME("iface %p, size %p, name %p stub!\n", iface, size, name);
+    struct d3drm_frame *frame = impl_from_IDirect3DRMFrame2(iface);
 
-    return E_NOTIMPL;
+    TRACE("iface %p, size %p, name %p.\n", iface, size, name);
+
+    return d3drm_frame3_GetName(&frame->IDirect3DRMFrame3_iface, size, name);
 }
 
 static HRESULT WINAPI d3drm_frame1_GetName(IDirect3DRMFrame *iface, DWORD *size, char *name)
 {
-    FIXME("iface %p, size %p, name %p stub!\n", iface, size, name);
+    struct d3drm_frame *frame = impl_from_IDirect3DRMFrame(iface);
 
-    return E_NOTIMPL;
+    TRACE("iface %p, size %p, name %p.\n", iface, size, name);
+
+    return d3drm_frame3_GetName(&frame->IDirect3DRMFrame3_iface, size, name);
 }
 
 static HRESULT WINAPI d3drm_frame3_GetClassName(IDirect3DRMFrame3 *iface, DWORD *size, char *name)
 {
-    TRACE("iface %p, size %p, name %p.\n", iface, size, name);
-
-    if (!size || *size < strlen("Frame") || !name)
-        return E_INVALIDARG;
+    struct d3drm_frame *frame = impl_from_IDirect3DRMFrame3(iface);
 
-    strcpy(name, "Frame");
-    *size = sizeof("Frame");
+    TRACE("iface %p, size %p, name %p.\n", iface, size, name);
 
-    return D3DRM_OK;
+    return d3drm_object_get_class_name(&frame->obj, size, name);
 }
 
 static HRESULT WINAPI d3drm_frame2_GetClassName(IDirect3DRMFrame2 *iface, DWORD *size, char *name)
@@ -756,7 +802,7 @@ static HRESULT WINAPI d3drm_frame1_GetClassName(IDirect3DRMFrame *iface, DWORD *
 
 static HRESULT WINAPI d3drm_frame3_AddChild(IDirect3DRMFrame3 *iface, IDirect3DRMFrame3 *child)
 {
-    struct d3drm_frame *This = impl_from_IDirect3DRMFrame3(iface);
+    struct d3drm_frame *frame = impl_from_IDirect3DRMFrame3(iface);
     struct d3drm_frame *child_obj = unsafe_impl_from_IDirect3DRMFrame3(child);
 
     TRACE("iface %p, child %p.\n", iface, child);
@@ -780,32 +826,13 @@ static HRESULT WINAPI d3drm_frame3_AddChild(IDirect3DRMFrame3 *iface, IDirect3DR
         }
     }
 
-    if ((This->nb_children + 1) > This->children_capacity)
-    {
-        ULONG new_capacity;
-        IDirect3DRMFrame3** children;
-
-        if (!This->children_capacity)
-        {
-            new_capacity = 16;
-            children = HeapAlloc(GetProcessHeap(), 0, new_capacity * sizeof(IDirect3DRMFrame3*));
-        }
-        else
-        {
-            new_capacity = This->children_capacity * 2;
-            children = HeapReAlloc(GetProcessHeap(), 0, This->children, new_capacity * sizeof(IDirect3DRMFrame3*));
-        }
-
-        if (!children)
-            return E_OUTOFMEMORY;
-
-        This->children_capacity = new_capacity;
-        This->children = children;
-    }
+    if (!d3drm_array_reserve((void **)&frame->children, &frame->children_size,
+            frame->nb_children + 1, sizeof(*frame->children)))
+        return E_OUTOFMEMORY;
 
-    This->children[This->nb_children++] = child;
+    frame->children[frame->nb_children++] = child;
     IDirect3DRMFrame3_AddRef(child);
-    child_obj->parent = This;
+    child_obj->parent = frame;
 
     return D3DRM_OK;
 }
@@ -843,9 +870,8 @@ static HRESULT WINAPI d3drm_frame1_AddChild(IDirect3DRMFrame *iface, IDirect3DRM
 
 static HRESULT WINAPI d3drm_frame3_AddLight(IDirect3DRMFrame3 *iface, IDirect3DRMLight *light)
 {
-    struct d3drm_frame *This = impl_from_IDirect3DRMFrame3(iface);
+    struct d3drm_frame *frame = impl_from_IDirect3DRMFrame3(iface);
     ULONG i;
-    IDirect3DRMLight** lights;
 
     TRACE("iface %p, light %p.\n", iface, light);
 
@@ -853,33 +879,15 @@ static HRESULT WINAPI d3drm_frame3_AddLight(IDirect3DRMFrame3 *iface, IDirect3DR
         return D3DRMERR_BADOBJECT;
 
     /* Check if already existing and return gracefully without increasing ref count */
-    for (i = 0; i < This->nb_lights; i++)
-        if (This->lights[i] == light)
+    for (i = 0; i < frame->nb_lights; i++)
+        if (frame->lights[i] == light)
             return D3DRM_OK;
 
-    if ((This->nb_lights + 1) > This->lights_capacity)
-    {
-        ULONG new_capacity;
-
-        if (!This->lights_capacity)
-        {
-            new_capacity = 16;
-            lights = HeapAlloc(GetProcessHeap(), 0, new_capacity * sizeof(IDirect3DRMLight*));
-        }
-        else
-        {
-            new_capacity = This->lights_capacity * 2;
-            lights = HeapReAlloc(GetProcessHeap(), 0, This->lights, new_capacity * sizeof(IDirect3DRMLight*));
-        }
-
-        if (!lights)
-            return E_OUTOFMEMORY;
-
-        This->lights_capacity = new_capacity;
-        This->lights = lights;
-    }
+    if (!d3drm_array_reserve((void **)&frame->lights, &frame->lights_size,
+            frame->nb_lights + 1, sizeof(*frame->lights)))
+        return E_OUTOFMEMORY;
 
-    This->lights[This->nb_lights++] = light;
+    frame->lights[frame->nb_lights++] = light;
     IDirect3DRMLight_AddRef(light);
 
     return D3DRM_OK;
@@ -1051,9 +1059,8 @@ static HRESULT WINAPI d3drm_frame1_AddRotation(IDirect3DRMFrame *iface,
 
 static HRESULT WINAPI d3drm_frame3_AddVisual(IDirect3DRMFrame3 *iface, IUnknown *visual)
 {
-    struct d3drm_frame *This = impl_from_IDirect3DRMFrame3(iface);
+    struct d3drm_frame *frame = impl_from_IDirect3DRMFrame3(iface);
     ULONG i;
-    IDirect3DRMVisual** visuals;
 
     TRACE("iface %p, visual %p.\n", iface, visual);
 
@@ -1061,33 +1068,15 @@ static HRESULT WINAPI d3drm_frame3_AddVisual(IDirect3DRMFrame3 *iface, IUnknown
         return D3DRMERR_BADOBJECT;
 
     /* Check if already existing and return gracefully without increasing ref count */
-    for (i = 0; i < This->nb_visuals; i++)
-        if (This->visuals[i] == (IDirect3DRMVisual *)visual)
+    for (i = 0; i < frame->nb_visuals; i++)
+        if (frame->visuals[i] == (IDirect3DRMVisual *)visual)
             return D3DRM_OK;
 
-    if ((This->nb_visuals + 1) > This->visuals_capacity)
-    {
-        ULONG new_capacity;
-
-        if (!This->visuals_capacity)
-        {
-            new_capacity = 16;
-            visuals = HeapAlloc(GetProcessHeap(), 0, new_capacity * sizeof(IDirect3DRMVisual*));
-        }
-        else
-        {
-            new_capacity = This->visuals_capacity * 2;
-            visuals = HeapReAlloc(GetProcessHeap(), 0, This->visuals, new_capacity * sizeof(IDirect3DRMVisual*));
-        }
-
-        if (!visuals)
-            return E_OUTOFMEMORY;
-
-        This->visuals_capacity = new_capacity;
-        This->visuals = visuals;
-    }
+    if (!d3drm_array_reserve((void **)&frame->visuals, &frame->visuals_size,
+            frame->nb_visuals + 1, sizeof(*frame->visuals)))
+        return E_OUTOFMEMORY;
 
-    This->visuals[This->nb_visuals++] = (IDirect3DRMVisual *)visual;
+    frame->visuals[frame->nb_visuals++] = (IDirect3DRMVisual *)visual;
     IDirect3DRMVisual_AddRef(visual);
 
     return D3DRM_OK;
@@ -2615,18 +2604,33 @@ static HRESULT WINAPI d3drm_frame3_InverseTransformVectors(IDirect3DRMFrame3 *if
     return E_NOTIMPL;
 }
 
-static HRESULT WINAPI d3drm_frame3_SetTraversalOptions(IDirect3DRMFrame3 *iface, DWORD flags)
+static HRESULT WINAPI d3drm_frame3_SetTraversalOptions(IDirect3DRMFrame3 *iface, DWORD options)
 {
-    FIXME("iface %p, flags %#x stub!\n", iface, flags);
+    static const DWORD supported_options = D3DRMFRAME_RENDERENABLE | D3DRMFRAME_PICKENABLE;
+    struct d3drm_frame *frame = impl_from_IDirect3DRMFrame3(iface);
 
-    return E_NOTIMPL;
+    TRACE("iface %p, options %#x.\n", iface, options);
+
+    if (options & ~supported_options)
+        return D3DRMERR_BADVALUE;
+
+    frame->traversal_options = options;
+
+    return D3DRM_OK;
 }
 
-static HRESULT WINAPI d3drm_frame3_GetTraversalOptions(IDirect3DRMFrame3 *iface, DWORD *flags)
+static HRESULT WINAPI d3drm_frame3_GetTraversalOptions(IDirect3DRMFrame3 *iface, DWORD *options)
 {
-    FIXME("iface %p, flags %p stub!\n", iface, flags);
+    struct d3drm_frame *frame = impl_from_IDirect3DRMFrame3(iface);
 
-    return E_NOTIMPL;
+    TRACE("iface %p, options %p.\n", iface, options);
+
+    if (!options)
+        return D3DRMERR_BADVALUE;
+
+    *options = frame->traversal_options;
+
+    return D3DRM_OK;
 }
 
 static HRESULT WINAPI d3drm_frame3_SetSceneFogMethod(IDirect3DRMFrame3 *iface, DWORD flags)
@@ -2925,6 +2929,7 @@ struct d3drm_frame *unsafe_impl_from_IDirect3DRMFrame(IDirect3DRMFrame *iface)
 
 HRESULT d3drm_frame_create(struct d3drm_frame **frame, IUnknown *parent_frame, IDirect3DRM *d3drm)
 {
+    static const char classname[] = "Frame";
     struct d3drm_frame *object;
     HRESULT hr = D3DRM_OK;
 
@@ -2939,6 +2944,9 @@ HRESULT d3drm_frame_create(struct d3drm_frame **frame, IUnknown *parent_frame, I
     object->d3drm = d3drm;
     object->ref = 1;
     d3drm_set_color(&object->scenebackground, 0.0f, 0.0f, 0.0f, 1.0f);
+    object->traversal_options = D3DRMFRAME_RENDERENABLE | D3DRMFRAME_PICKENABLE;
+
+    d3drm_object_init(&object->obj, classname);
 
     memcpy(object->transform, identity, sizeof(D3DRMMATRIX4D));
 
@@ -2955,7 +2963,744 @@ HRESULT d3drm_frame_create(struct d3drm_frame **frame, IUnknown *parent_frame, I
         IDirect3DRMFrame3_AddChild(p, &object->IDirect3DRMFrame3_iface);
     }
 
+    IDirect3DRM_AddRef(object->d3drm);
+
     *frame = object;
 
     return hr;
 }
+
+static HRESULT WINAPI d3drm_animation2_QueryInterface(IDirect3DRMAnimation2 *iface, REFIID riid, void **out)
+{
+    struct d3drm_animation *animation = impl_from_IDirect3DRMAnimation2(iface);
+
+    TRACE("iface %p, riid %s, out %p.\n", iface, debugstr_guid(riid), out);
+
+    if (IsEqualGUID(riid, &IID_IDirect3DRMAnimation)
+            || IsEqualGUID(riid, &IID_IDirect3DRMObject)
+            || IsEqualGUID(riid, &IID_IUnknown))
+    {
+        *out = &animation->IDirect3DRMAnimation_iface;
+    }
+    else if (IsEqualGUID(riid, &IID_IDirect3DRMAnimation2))
+    {
+        *out = &animation->IDirect3DRMAnimation2_iface;
+    }
+    else
+    {
+        *out = NULL;
+        WARN("%s not implemented, returning CLASS_E_CLASSNOTAVAILABLE.\n", debugstr_guid(riid));
+        return CLASS_E_CLASSNOTAVAILABLE;
+    }
+
+    IUnknown_AddRef((IUnknown *)*out);
+    return S_OK;
+}
+
+static HRESULT WINAPI d3drm_animation1_QueryInterface(IDirect3DRMAnimation *iface, REFIID riid, void **out)
+{
+    struct d3drm_animation *animation = impl_from_IDirect3DRMAnimation(iface);
+
+    TRACE("iface %p, riid %s, out %p.\n", iface, debugstr_guid(riid), out);
+
+    return IDirect3DRMAnimation2_QueryInterface(&animation->IDirect3DRMAnimation2_iface, riid, out);
+}
+
+static ULONG WINAPI d3drm_animation2_AddRef(IDirect3DRMAnimation2 *iface)
+{
+    struct d3drm_animation *animation = impl_from_IDirect3DRMAnimation2(iface);
+    ULONG refcount = InterlockedIncrement(&animation->ref);
+
+    TRACE("%p increasing refcount to %u.\n", iface, refcount);
+
+    return refcount;
+}
+
+static ULONG WINAPI d3drm_animation1_AddRef(IDirect3DRMAnimation *iface)
+{
+    struct d3drm_animation *animation = impl_from_IDirect3DRMAnimation(iface);
+    return IDirect3DRMAnimation2_AddRef(&animation->IDirect3DRMAnimation2_iface);
+}
+
+static ULONG WINAPI d3drm_animation2_Release(IDirect3DRMAnimation2 *iface)
+{
+    struct d3drm_animation *animation = impl_from_IDirect3DRMAnimation2(iface);
+    ULONG refcount = InterlockedDecrement(&animation->ref);
+
+    TRACE("%p decreasing refcount to %u.\n", iface, refcount);
+
+    if (!refcount)
+    {
+        d3drm_object_cleanup((IDirect3DRMObject *)&animation->IDirect3DRMAnimation_iface, &animation->obj);
+        IDirect3DRM_Release(animation->d3drm);
+        HeapFree(GetProcessHeap(), 0, animation->rotate.keys);
+        HeapFree(GetProcessHeap(), 0, animation->scale.keys);
+        HeapFree(GetProcessHeap(), 0, animation->position.keys);
+        HeapFree(GetProcessHeap(), 0, animation);
+    }
+
+    return refcount;
+}
+
+static ULONG WINAPI d3drm_animation1_Release(IDirect3DRMAnimation *iface)
+{
+    struct d3drm_animation *animation = impl_from_IDirect3DRMAnimation(iface);
+
+    return IDirect3DRMAnimation2_Release(&animation->IDirect3DRMAnimation2_iface);
+}
+
+static HRESULT WINAPI d3drm_animation2_Clone(IDirect3DRMAnimation2 *iface, IUnknown *outer, REFIID iid, void **out)
+{
+    FIXME("iface %p, outer %p, iid %s, out %p stub!\n", iface, outer, debugstr_guid(iid), out);
+
+    return E_NOTIMPL;
+}
+
+static HRESULT WINAPI d3drm_animation1_Clone(IDirect3DRMAnimation *iface, IUnknown *outer, REFIID iid, void **out)
+{
+    FIXME("iface %p, outer %p, iid %s, out %p stub!\n", iface, outer, debugstr_guid(iid), out);
+
+    return E_NOTIMPL;
+}
+
+static HRESULT WINAPI d3drm_animation2_AddDestroyCallback(IDirect3DRMAnimation2 *iface,
+        D3DRMOBJECTCALLBACK cb, void *ctx)
+{
+    struct d3drm_animation *animation = impl_from_IDirect3DRMAnimation2(iface);
+
+    TRACE("iface %p, cb %p, ctx %p.\n", iface, cb, ctx);
+
+    return d3drm_object_add_destroy_callback(&animation->obj, cb, ctx);
+}
+
+static HRESULT WINAPI d3drm_animation1_AddDestroyCallback(IDirect3DRMAnimation *iface,
+        D3DRMOBJECTCALLBACK cb, void *ctx)
+{
+    struct d3drm_animation *animation = impl_from_IDirect3DRMAnimation(iface);
+
+    TRACE("iface %p, cb %p, ctx %p.\n", iface, cb, ctx);
+
+    return IDirect3DRMAnimation2_AddDestroyCallback(&animation->IDirect3DRMAnimation2_iface, cb, ctx);
+}
+
+static HRESULT WINAPI d3drm_animation2_DeleteDestroyCallback(IDirect3DRMAnimation2 *iface,
+        D3DRMOBJECTCALLBACK cb, void *ctx)
+{
+    struct d3drm_animation *animation = impl_from_IDirect3DRMAnimation2(iface);
+
+    TRACE("iface %p, cb %p, ctx %p.\n", iface, cb, ctx);
+
+    return d3drm_object_delete_destroy_callback(&animation->obj, cb, ctx);
+}
+
+static HRESULT WINAPI d3drm_animation1_DeleteDestroyCallback(IDirect3DRMAnimation *iface,
+        D3DRMOBJECTCALLBACK cb, void *ctx)
+{
+    struct d3drm_animation *animation = impl_from_IDirect3DRMAnimation(iface);
+
+    TRACE("iface %p, cb %p, ctx %p.\n", iface, cb, ctx);
+
+    return IDirect3DRMAnimation2_DeleteDestroyCallback(&animation->IDirect3DRMAnimation2_iface, cb, ctx);
+}
+
+static HRESULT WINAPI d3drm_animation2_SetAppData(IDirect3DRMAnimation2 *iface, DWORD data)
+{
+    struct d3drm_animation *animation = impl_from_IDirect3DRMAnimation2(iface);
+
+    TRACE("iface %p, data %#x.\n", iface, data);
+
+    animation->obj.appdata = data;
+
+    return D3DRM_OK;
+}
+
+static HRESULT WINAPI d3drm_animation1_SetAppData(IDirect3DRMAnimation *iface, DWORD data)
+{
+    struct d3drm_animation *animation = impl_from_IDirect3DRMAnimation(iface);
+
+    TRACE("iface %p, data %#x.\n", iface, data);
+
+    return d3drm_animation2_SetAppData(&animation->IDirect3DRMAnimation2_iface, data);
+}
+
+static DWORD WINAPI d3drm_animation2_GetAppData(IDirect3DRMAnimation2 *iface)
+{
+    struct d3drm_animation *animation = impl_from_IDirect3DRMAnimation2(iface);
+
+    TRACE("iface %p.\n", iface);
+
+    return animation->obj.appdata;
+}
+
+static DWORD WINAPI d3drm_animation1_GetAppData(IDirect3DRMAnimation *iface)
+{
+    struct d3drm_animation *animation = impl_from_IDirect3DRMAnimation(iface);
+
+    TRACE("iface %p.\n", iface);
+
+    return d3drm_animation2_GetAppData(&animation->IDirect3DRMAnimation2_iface);
+}
+
+static HRESULT WINAPI d3drm_animation2_SetName(IDirect3DRMAnimation2 *iface, const char *name)
+{
+    struct d3drm_animation *animation = impl_from_IDirect3DRMAnimation2(iface);
+
+    TRACE("iface %p, name %s.\n", iface, debugstr_a(name));
+
+    return d3drm_object_set_name(&animation->obj, name);
+}
+
+static HRESULT WINAPI d3drm_animation1_SetName(IDirect3DRMAnimation *iface, const char *name)
+{
+    struct d3drm_animation *animation = impl_from_IDirect3DRMAnimation(iface);
+
+    TRACE("iface %p, name %s.\n", iface, debugstr_a(name));
+
+    return d3drm_animation2_SetName(&animation->IDirect3DRMAnimation2_iface, name);
+}
+
+static HRESULT WINAPI d3drm_animation2_GetName(IDirect3DRMAnimation2 *iface, DWORD *size, char *name)
+{
+    struct d3drm_animation *animation = impl_from_IDirect3DRMAnimation2(iface);
+
+    TRACE("iface %p, size %p, name %p.\n", iface, size, name);
+
+    return d3drm_object_get_name(&animation->obj, size, name);
+}
+
+static HRESULT WINAPI d3drm_animation1_GetName(IDirect3DRMAnimation *iface, DWORD *size, char *name)
+{
+    struct d3drm_animation *animation = impl_from_IDirect3DRMAnimation(iface);
+
+    TRACE("iface %p, size %p, name %p.\n", iface, size, name);
+
+    return d3drm_animation2_GetName(&animation->IDirect3DRMAnimation2_iface, size, name);
+}
+
+static HRESULT WINAPI d3drm_animation2_GetClassName(IDirect3DRMAnimation2 *iface, DWORD *size, char *name)
+{
+    struct d3drm_animation *animation = impl_from_IDirect3DRMAnimation2(iface);
+
+    TRACE("iface %p, size %p, name %p.\n", iface, size, name);
+
+    return d3drm_object_get_class_name(&animation->obj, size, name);
+}
+
+static HRESULT WINAPI d3drm_animation1_GetClassName(IDirect3DRMAnimation *iface, DWORD *size, char *name)
+{
+    struct d3drm_animation *animation = impl_from_IDirect3DRMAnimation(iface);
+
+    TRACE("iface %p, size %p, name %p.\n", iface, size, name);
+
+    return d3drm_animation2_GetClassName(&animation->IDirect3DRMAnimation2_iface, size, name);
+}
+
+static HRESULT WINAPI d3drm_animation2_SetOptions(IDirect3DRMAnimation2 *iface, D3DRMANIMATIONOPTIONS options)
+{
+    struct d3drm_animation *animation = impl_from_IDirect3DRMAnimation2(iface);
+    static const DWORD supported_options = D3DRMANIMATION_OPEN | D3DRMANIMATION_CLOSED | D3DRMANIMATION_LINEARPOSITION
+        | D3DRMANIMATION_SPLINEPOSITION | D3DRMANIMATION_SCALEANDROTATION | D3DRMANIMATION_POSITION;
+
+    TRACE("iface %p, options %#x.\n", iface, options);
+
+    if (!(options & supported_options))
+        return D3DRMERR_BADVALUE;
+
+    if ((options & (D3DRMANIMATION_OPEN | D3DRMANIMATION_CLOSED)) == (D3DRMANIMATION_OPEN | D3DRMANIMATION_CLOSED) ||
+            (options & (D3DRMANIMATION_LINEARPOSITION | D3DRMANIMATION_SPLINEPOSITION)) ==
+            (D3DRMANIMATION_LINEARPOSITION | D3DRMANIMATION_SPLINEPOSITION) ||
+            (options & (D3DRMANIMATION_SCALEANDROTATION | D3DRMANIMATION_POSITION)) ==
+            (D3DRMANIMATION_SCALEANDROTATION | D3DRMANIMATION_POSITION))
+    {
+        return D3DRMERR_BADVALUE;
+    }
+
+    animation->options = options;
+
+    return D3DRM_OK;
+}
+
+static HRESULT WINAPI d3drm_animation1_SetOptions(IDirect3DRMAnimation *iface, D3DRMANIMATIONOPTIONS options)
+{
+    struct d3drm_animation *animation = impl_from_IDirect3DRMAnimation(iface);
+
+    TRACE("iface %p, %#x.\n", iface, options);
+
+    return d3drm_animation2_SetOptions(&animation->IDirect3DRMAnimation2_iface, options);
+}
+
+static SIZE_T d3drm_animation_lookup_key(const struct d3drm_animation_key *keys,
+        SIZE_T count, D3DVALUE time)
+{
+    SIZE_T start = 0, cur = 0, end = count;
+
+    while (start < end)
+    {
+        cur = start + (end - start) / 2;
+
+        if (time == keys[cur].time)
+            return cur;
+
+        if (time < keys[cur].time)
+            end = cur;
+        else
+            start = cur + 1;
+    }
+
+    return cur;
+}
+
+static SIZE_T d3drm_animation_get_index_min(const struct d3drm_animation_key *keys, SIZE_T count, D3DVALUE time)
+{
+    SIZE_T i;
+
+    i = d3drm_animation_lookup_key(keys, count, time);
+    while (i > 0 && keys[i - 1].time == time)
+        --i;
+
+    return i;
+}
+
+static SIZE_T d3drm_animation_get_index_max(const struct d3drm_animation_key *keys, SIZE_T count, D3DVALUE time)
+{
+    SIZE_T i;
+
+    i = d3drm_animation_lookup_key(keys, count, time);
+    while (i < count - 1 && keys[i + 1].time == time)
+        ++i;
+
+    return i;
+}
+
+static SIZE_T d3drm_animation_get_insert_position(const struct d3drm_animation_keys *keys, D3DVALUE time)
+{
+    if (!keys->count || 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->keys, keys->count, time);
+}
+
+static const struct d3drm_animation_key *d3drm_animation_get_range(const struct d3drm_animation_keys *keys,
+        D3DVALUE time_min, D3DVALUE time_max, SIZE_T *count)
+{
+    SIZE_T min;
+
+    if (!keys->count || time_max < keys->keys[0].time
+            || time_min > keys->keys[keys->count - 1].time)
+        return NULL;
+
+    min = d3drm_animation_get_index_min(keys->keys, keys->count, time_min);
+    if (count)
+        *count = d3drm_animation_get_index_max(&keys->keys[min], keys->count - min, time_max) - min + 1;
+
+    return &keys->keys[min];
+}
+
+static HRESULT WINAPI d3drm_animation2_AddKey(IDirect3DRMAnimation2 *iface, D3DRMANIMATIONKEY *key)
+{
+    struct d3drm_animation *animation = impl_from_IDirect3DRMAnimation2(iface);
+    struct d3drm_animation_keys *keys;
+    SIZE_T index;
+
+    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)
+{
+    D3DRMANIMATIONKEY key;
+
+    TRACE("iface %p, time %.8e, q %p.\n", iface, time, q);
+
+    key.dwSize = sizeof(key);
+    key.dwKeyType = D3DRMANIMATION_ROTATEKEY;
+    key.dvTime = time;
+    key.dwID = 0;
+    key.u.dqRotateKey = *q;
+
+    return d3drm_animation2_AddKey(iface, &key);
+}
+
+static HRESULT WINAPI d3drm_animation1_AddRotateKey(IDirect3DRMAnimation *iface, D3DVALUE time, D3DRMQUATERNION *q)
+{
+    struct d3drm_animation *animation = impl_from_IDirect3DRMAnimation(iface);
+
+    TRACE("iface %p, time %.8e, q %p.\n", iface, time, q);
+
+    return d3drm_animation2_AddRotateKey(&animation->IDirect3DRMAnimation2_iface, time, q);
+}
+
+static HRESULT WINAPI d3drm_animation2_AddPositionKey(IDirect3DRMAnimation2 *iface, D3DVALUE time,
+        D3DVALUE x, D3DVALUE y, D3DVALUE z)
+{
+    D3DRMANIMATIONKEY key;
+
+    TRACE("iface %p, time %.8e, x %.8e, y %.8e, z %.8e.\n", iface, time, x, y, z);
+
+    key.dwSize = sizeof(key);
+    key.dwKeyType = D3DRMANIMATION_POSITIONKEY;
+    key.dvTime = time;
+    key.dwID = 0;
+    key.u.dvPositionKey.u1.x = x;
+    key.u.dvPositionKey.u2.y = y;
+    key.u.dvPositionKey.u3.z = z;
+
+    return d3drm_animation2_AddKey(iface, &key);
+}
+
+static HRESULT WINAPI d3drm_animation1_AddPositionKey(IDirect3DRMAnimation *iface, D3DVALUE time,
+        D3DVALUE x, D3DVALUE y, D3DVALUE z)
+{
+    struct d3drm_animation *animation = impl_from_IDirect3DRMAnimation(iface);
+
+    TRACE("iface %p, time %.8e, x %.8e, y %.8e, z %.8e.\n", iface, time, x, y, z);
+
+    return d3drm_animation2_AddPositionKey(&animation->IDirect3DRMAnimation2_iface, time, x, y, z);
+}
+
+static HRESULT WINAPI d3drm_animation2_AddScaleKey(IDirect3DRMAnimation2 *iface, D3DVALUE time,
+        D3DVALUE x, D3DVALUE y, D3DVALUE z)
+{
+    D3DRMANIMATIONKEY key;
+
+    TRACE("iface %p, time %.8e, x %.8e, y %.8e, z %.8e.\n", iface, time, x, y, z);
+
+    key.dwSize = sizeof(key);
+    key.dwKeyType = D3DRMANIMATION_SCALEKEY;
+    key.dvTime = time;
+    key.dwID = 0;
+    key.u.dvScaleKey.u1.x = x;
+    key.u.dvScaleKey.u2.y = y;
+    key.u.dvScaleKey.u3.z = z;
+
+    return d3drm_animation2_AddKey(iface, &key);
+}
+
+static HRESULT WINAPI d3drm_animation1_AddScaleKey(IDirect3DRMAnimation *iface, D3DVALUE time,
+        D3DVALUE x, D3DVALUE y, D3DVALUE z)
+{
+    struct d3drm_animation *animation = impl_from_IDirect3DRMAnimation(iface);
+
+    TRACE("iface %p, time %.8e, x %.8e, y %.8e, z %.8e.\n", iface, time, x, y, z);
+
+    return d3drm_animation2_AddScaleKey(&animation->IDirect3DRMAnimation2_iface, time, x, y, z);
+}
+
+static void d3drm_animation_delete_key(struct d3drm_animation_keys *keys, const struct d3drm_animation_key *key)
+{
+    SIZE_T index = key - keys->keys;
+
+    if (index < keys->count - 1)
+        memmove(&keys->keys[index], &keys->keys[index + 1], sizeof(*keys->keys) * (keys->count - index - 1));
+    --keys->count;
+}
+
+static HRESULT WINAPI d3drm_animation2_DeleteKey(IDirect3DRMAnimation2 *iface, D3DVALUE time)
+{
+    struct d3drm_animation *animation = impl_from_IDirect3DRMAnimation2(iface);
+    const struct d3drm_animation_key *key;
+
+    TRACE("iface %p, time %.8e.\n", iface, time);
+
+    if ((key = d3drm_animation_get_range(&animation->rotate, time, time, NULL)))
+        d3drm_animation_delete_key(&animation->rotate, key);
+
+    if ((key = d3drm_animation_get_range(&animation->position, time, time, NULL)))
+        d3drm_animation_delete_key(&animation->position, key);
+
+    if ((key = d3drm_animation_get_range(&animation->scale, time, time, NULL)))
+        d3drm_animation_delete_key(&animation->scale, key);
+
+    return D3DRM_OK;
+}
+
+static HRESULT WINAPI d3drm_animation1_DeleteKey(IDirect3DRMAnimation *iface, D3DVALUE time)
+{
+    struct d3drm_animation *animation = impl_from_IDirect3DRMAnimation(iface);
+
+    TRACE("iface %p, time %.8e.\n", iface, time);
+
+    return d3drm_animation2_DeleteKey(&animation->IDirect3DRMAnimation2_iface, time);
+}
+
+static HRESULT WINAPI d3drm_animation1_SetFrame(IDirect3DRMAnimation *iface, IDirect3DRMFrame *frame)
+{
+    struct d3drm_animation *animation = impl_from_IDirect3DRMAnimation(iface);
+    HRESULT hr = D3DRM_OK;
+
+    TRACE("iface %p, frame %p.\n", iface, frame);
+
+    if (frame)
+    {
+        hr = IDirect3DRMFrame_QueryInterface(frame, &IID_IDirect3DRMFrame3, (void **)&animation->frame);
+        if (SUCCEEDED(hr))
+            IDirect3DRMFrame3_Release(animation->frame);
+    }
+    else
+        animation->frame = NULL;
+
+    return hr;
+}
+
+static HRESULT WINAPI d3drm_animation1_SetTime(IDirect3DRMAnimation *iface, D3DVALUE time)
+{
+    FIXME("iface %p, time %.8e.\n", iface, time);
+
+    return E_NOTIMPL;
+}
+
+static D3DRMANIMATIONOPTIONS WINAPI d3drm_animation2_GetOptions(IDirect3DRMAnimation2 *iface)
+{
+    struct d3drm_animation *animation = impl_from_IDirect3DRMAnimation2(iface);
+
+    TRACE("iface %p.\n", iface);
+
+    return animation->options;
+}
+
+static D3DRMANIMATIONOPTIONS WINAPI d3drm_animation1_GetOptions(IDirect3DRMAnimation *iface)
+{
+    struct d3drm_animation *animation = impl_from_IDirect3DRMAnimation(iface);
+
+    TRACE("iface %p.\n", iface);
+
+    return d3drm_animation2_GetOptions(&animation->IDirect3DRMAnimation2_iface);
+}
+
+static HRESULT WINAPI d3drm_animation2_SetFrame(IDirect3DRMAnimation2 *iface, IDirect3DRMFrame3 *frame)
+{
+    struct d3drm_animation *animation = impl_from_IDirect3DRMAnimation2(iface);
+
+    TRACE("iface %p, frame %p.\n", iface, frame);
+
+    animation->frame = frame;
+
+    return D3DRM_OK;
+}
+
+static HRESULT WINAPI d3drm_animation2_SetTime(IDirect3DRMAnimation2 *iface, D3DVALUE time)
+{
+    FIXME("iface %p, time %.8e.\n", iface, time);
+
+    return E_NOTIMPL;
+}
+
+static HRESULT WINAPI d3drm_animation2_GetFrame(IDirect3DRMAnimation2 *iface, IDirect3DRMFrame3 **frame)
+{
+    struct d3drm_animation *animation = impl_from_IDirect3DRMAnimation2(iface);
+
+    TRACE("iface %p, frame %p.\n", iface, frame);
+
+    if (!frame)
+        return D3DRMERR_BADVALUE;
+
+    *frame = animation->frame;
+    if (*frame)
+        IDirect3DRMFrame3_AddRef(*frame);
+
+    return D3DRM_OK;
+}
+
+static HRESULT WINAPI d3drm_animation2_DeleteKeyByID(IDirect3DRMAnimation2 *iface, DWORD id)
+{
+    FIXME("iface %p, id %#x.\n", iface, id);
+
+    return E_NOTIMPL;
+}
+
+static HRESULT WINAPI d3drm_animation2_ModifyKey(IDirect3DRMAnimation2 *iface, D3DRMANIMATIONKEY *key)
+{
+    FIXME("iface %p, key %p.\n", iface, key);
+
+    return E_NOTIMPL;
+}
+
+static HRESULT WINAPI d3drm_animation2_GetKeys(IDirect3DRMAnimation2 *iface, D3DVALUE time_min, D3DVALUE time_max,
+        DWORD *key_count, D3DRMANIMATIONKEY *keys)
+{
+    struct d3drm_animation *animation = impl_from_IDirect3DRMAnimation2(iface);
+    const struct d3drm_animation_key *key;
+    SIZE_T count, i;
+
+    TRACE("iface %p, time min %.8e, time max %.8e, 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)))
+    {
+        if (keys)
+        {
+            for (i = 0; i < count; ++i)
+            {
+                keys[i].dwSize = sizeof(*keys);
+                keys[i].dwKeyType = D3DRMANIMATION_ROTATEKEY;
+                keys[i].dvTime = key[i].time;
+                keys[i].dwID = 0; /* FIXME */
+                keys[i].u.dqRotateKey = key[i].u.rotate;
+            }
+            keys += count;
+        }
+        *key_count += count;
+    }
+
+    if ((key = d3drm_animation_get_range(&animation->position, time_min, time_max, &count)))
+    {
+        if (keys)
+        {
+            for (i = 0; i < count; ++i)
+            {
+                keys[i].dwSize = sizeof(*keys);
+                keys[i].dwKeyType = D3DRMANIMATION_POSITIONKEY;
+                keys[i].dvTime = key[i].time;
+                keys[i].dwID = 0; /* FIXME */
+                keys[i].u.dvPositionKey = key[i].u.position;
+            }
+            keys += count;
+        }
+        *key_count += count;
+    }
+
+    if ((key = d3drm_animation_get_range(&animation->scale, time_min, time_max, &count)))
+    {
+        if (keys)
+        {
+            for (i = 0; keys && i < count; ++i)
+            {
+                keys[i].dwSize = sizeof(*keys);
+                keys[i].dwKeyType = D3DRMANIMATION_SCALEKEY;
+                keys[i].dvTime = key[i].time;
+                keys[i].dwID = 0; /* FIXME */
+                keys[i].u.dvScaleKey = key[i].u.scale;
+            }
+            keys += count;
+        }
+        *key_count += count;
+    }
+
+    return *key_count ? D3DRM_OK : D3DRMERR_NOSUCHKEY;
+}
+
+static const struct IDirect3DRMAnimationVtbl d3drm_animation1_vtbl =
+{
+    d3drm_animation1_QueryInterface,
+    d3drm_animation1_AddRef,
+    d3drm_animation1_Release,
+    d3drm_animation1_Clone,
+    d3drm_animation1_AddDestroyCallback,
+    d3drm_animation1_DeleteDestroyCallback,
+    d3drm_animation1_SetAppData,
+    d3drm_animation1_GetAppData,
+    d3drm_animation1_SetName,
+    d3drm_animation1_GetName,
+    d3drm_animation1_GetClassName,
+    d3drm_animation1_SetOptions,
+    d3drm_animation1_AddRotateKey,
+    d3drm_animation1_AddPositionKey,
+    d3drm_animation1_AddScaleKey,
+    d3drm_animation1_DeleteKey,
+    d3drm_animation1_SetFrame,
+    d3drm_animation1_SetTime,
+    d3drm_animation1_GetOptions,
+};
+
+static const struct IDirect3DRMAnimation2Vtbl d3drm_animation2_vtbl =
+{
+    d3drm_animation2_QueryInterface,
+    d3drm_animation2_AddRef,
+    d3drm_animation2_Release,
+    d3drm_animation2_Clone,
+    d3drm_animation2_AddDestroyCallback,
+    d3drm_animation2_DeleteDestroyCallback,
+    d3drm_animation2_SetAppData,
+    d3drm_animation2_GetAppData,
+    d3drm_animation2_SetName,
+    d3drm_animation2_GetName,
+    d3drm_animation2_GetClassName,
+    d3drm_animation2_SetOptions,
+    d3drm_animation2_AddRotateKey,
+    d3drm_animation2_AddPositionKey,
+    d3drm_animation2_AddScaleKey,
+    d3drm_animation2_DeleteKey,
+    d3drm_animation2_SetFrame,
+    d3drm_animation2_SetTime,
+    d3drm_animation2_GetOptions,
+    d3drm_animation2_GetFrame,
+    d3drm_animation2_DeleteKeyByID,
+    d3drm_animation2_AddKey,
+    d3drm_animation2_ModifyKey,
+    d3drm_animation2_GetKeys,
+};
+
+HRESULT d3drm_animation_create(struct d3drm_animation **animation, IDirect3DRM *d3drm)
+{
+    static const char classname[] = "Animation";
+    struct d3drm_animation *object;
+    HRESULT hr = D3DRM_OK;
+
+    TRACE("animation %p, d3drm %p.\n", animation, d3drm);
+
+    if (!(object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*object))))
+        return E_OUTOFMEMORY;
+
+    object->IDirect3DRMAnimation_iface.lpVtbl = &d3drm_animation1_vtbl;
+    object->IDirect3DRMAnimation2_iface.lpVtbl = &d3drm_animation2_vtbl;
+    object->d3drm = d3drm;
+    object->ref = 1;
+    object->options = D3DRMANIMATION_CLOSED | D3DRMANIMATION_LINEARPOSITION;
+
+    d3drm_object_init(&object->obj, classname);
+
+    IDirect3DRM_AddRef(object->d3drm);
+
+    *animation = object;
+
+    return hr;
+}
index 8fc508e..b266956 100644 (file)
 
 #include "d3drm_private.h"
 
-struct d3drm_light
-{
-    IDirect3DRMLight IDirect3DRMLight_iface;
-    LONG ref;
-    D3DRMLIGHTTYPE type;
-    D3DCOLOR color;
-    D3DVALUE range;
-    D3DVALUE cattenuation;
-    D3DVALUE lattenuation;
-    D3DVALUE qattenuation;
-    D3DVALUE umbra;
-    D3DVALUE penumbra;
-};
-
 static inline struct d3drm_light *impl_from_IDirect3DRMLight(IDirect3DRMLight *iface)
 {
     return CONTAINING_RECORD(iface, struct d3drm_light, IDirect3DRMLight_iface);
@@ -44,6 +30,7 @@ static HRESULT WINAPI d3drm_light_QueryInterface(IDirect3DRMLight *iface, REFIID
     TRACE("iface %p, riid %s, out %p.\n", iface, debugstr_guid(riid), out);
 
     if (IsEqualGUID(riid, &IID_IDirect3DRMLight)
+            || IsEqualGUID(riid, &IID_IDirect3DRMObject)
             || IsEqualGUID(riid, &IID_IUnknown))
     {
         IDirect3DRMLight_AddRef(iface);
@@ -75,7 +62,11 @@ static ULONG WINAPI d3drm_light_Release(IDirect3DRMLight *iface)
     TRACE("%p decreasing refcount to %u.\n", iface, refcount);
 
     if (!refcount)
+    {
+        d3drm_object_cleanup((IDirect3DRMObject *)iface, &light->obj);
+        IDirect3DRM_Release(light->d3drm);
         HeapFree(GetProcessHeap(), 0, light);
+    }
 
     return refcount;
 }
@@ -91,58 +82,68 @@ static HRESULT WINAPI d3drm_light_Clone(IDirect3DRMLight *iface,
 static HRESULT WINAPI d3drm_light_AddDestroyCallback(IDirect3DRMLight *iface,
         D3DRMOBJECTCALLBACK cb, void *ctx)
 {
-    FIXME("iface %p, cb %p, ctx %p stub!\n", iface, cb, ctx);
+    struct d3drm_light *light = impl_from_IDirect3DRMLight(iface);
 
-    return E_NOTIMPL;
+    TRACE("iface %p, cb %p, ctx %p.\n", iface, cb, ctx);
+
+    return d3drm_object_add_destroy_callback(&light->obj, cb, ctx);
 }
 
 static HRESULT WINAPI d3drm_light_DeleteDestroyCallback(IDirect3DRMLight *iface,
         D3DRMOBJECTCALLBACK cb, void *ctx)
 {
-    FIXME("iface %p, cb %p, ctx %p stub!\n", iface, cb, ctx);
+    struct d3drm_light *light = impl_from_IDirect3DRMLight(iface);
 
-    return E_NOTIMPL;
+    TRACE("iface %p, cb %p, ctx %p.\n", iface, cb, ctx);
+
+    return d3drm_object_delete_destroy_callback(&light->obj, cb, ctx);
 }
 
 static HRESULT WINAPI d3drm_light_SetAppData(IDirect3DRMLight *iface, DWORD data)
 {
-    FIXME("iface %p, data %#x stub!\n", iface, data);
+    struct d3drm_light *light = impl_from_IDirect3DRMLight(iface);
 
-    return E_NOTIMPL;
+    TRACE("iface %p, data %#x.\n", iface, data);
+
+    light->obj.appdata = data;
+
+    return D3DRM_OK;
 }
 
 static DWORD WINAPI d3drm_light_GetAppData(IDirect3DRMLight *iface)
 {
-    FIXME("iface %p stub!\n", iface);
+    struct d3drm_light *light = impl_from_IDirect3DRMLight(iface);
 
-    return 0;
+    TRACE("iface %p.\n", iface);
+
+    return light->obj.appdata;
 }
 
 static HRESULT WINAPI d3drm_light_SetName(IDirect3DRMLight *iface, const char *name)
 {
-    FIXME("iface %p, name %s stub!\n", iface, debugstr_a(name));
+    struct d3drm_light *light = impl_from_IDirect3DRMLight(iface);
 
-    return E_NOTIMPL;
+    TRACE("iface %p, name %s.\n", iface, debugstr_a(name));
+
+    return d3drm_object_set_name(&light->obj, name);
 }
 
 static HRESULT WINAPI d3drm_light_GetName(IDirect3DRMLight *iface, DWORD *size, char *name)
 {
-    FIXME("iface %p, size %p, name %p stub!\n", iface, size, name);
+    struct d3drm_light *light = impl_from_IDirect3DRMLight(iface);
 
-    return E_NOTIMPL;
+    TRACE("iface %p, size %p, name %p.\n", iface, size, name);
+
+    return d3drm_object_get_name(&light->obj, size, name);
 }
 
 static HRESULT WINAPI d3drm_light_GetClassName(IDirect3DRMLight *iface, DWORD *size, char *name)
 {
-    TRACE("iface %p, size %p, name %p.\n", iface, size, name);
-
-    if (!size || *size < strlen("Light") || !name)
-        return E_INVALIDARG;
+    struct d3drm_light *light = impl_from_IDirect3DRMLight(iface);
 
-    strcpy(name, "Light");
-    *size = sizeof("Light");
+    TRACE("iface %p, size %p, name %p.\n", iface, size, name);
 
-    return D3DRM_OK;
+    return d3drm_object_get_class_name(&light->obj, size, name);
 }
 
 static HRESULT WINAPI d3drm_light_SetType(IDirect3DRMLight *iface, D3DRMLIGHTTYPE type)
@@ -365,19 +366,24 @@ static const struct IDirect3DRMLightVtbl d3drm_light_vtbl =
     d3drm_light_GetEnableFrame,
 };
 
-HRESULT Direct3DRMLight_create(IUnknown **out)
+HRESULT d3drm_light_create(struct d3drm_light **light, IDirect3DRM *d3drm)
 {
+    static const char classname[] = "Light";
     struct d3drm_light *object;
 
-    TRACE("out %p.\n", out);
+    TRACE("light %p.\n", light);
 
     if (!(object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*object))))
         return E_OUTOFMEMORY;
 
     object->IDirect3DRMLight_iface.lpVtbl = &d3drm_light_vtbl;
     object->ref = 1;
+    object->d3drm = d3drm;
+    IDirect3DRM_AddRef(object->d3drm);
+
+    d3drm_object_init(&object->obj, classname);
 
-    *out = (IUnknown *)&object->IDirect3DRMLight_iface;
+    *light = object;
 
     return S_OK;
 }
index 4e6fa27..4b56148 100644 (file)
 
 #include "d3drm_private.h"
 
-struct color_rgb
-{
-    D3DVALUE r;
-    D3DVALUE g;
-    D3DVALUE b;
-};
-
-struct d3drm_material
-{
-    IDirect3DRMMaterial2 IDirect3DRMMaterial2_iface;
-    LONG ref;
-    struct color_rgb emissive;
-    struct color_rgb specular;
-    D3DVALUE power;
-    struct color_rgb ambient;
-};
-
 static inline struct d3drm_material *impl_from_IDirect3DRMMaterial2(IDirect3DRMMaterial2 *iface)
 {
     return CONTAINING_RECORD(iface, struct d3drm_material, IDirect3DRMMaterial2_iface);
@@ -48,6 +31,7 @@ static HRESULT WINAPI d3drm_material_QueryInterface(IDirect3DRMMaterial2 *iface,
 
     if (IsEqualGUID(riid, &IID_IDirect3DRMMaterial2)
             || IsEqualGUID(riid, &IID_IDirect3DRMMaterial)
+            || IsEqualGUID(riid, &IID_IDirect3DRMObject)
             || IsEqualGUID(riid, &IID_IUnknown))
     {
         IDirect3DRMMaterial2_AddRef(iface);
@@ -79,7 +63,11 @@ static ULONG WINAPI d3drm_material_Release(IDirect3DRMMaterial2 *iface)
     TRACE("%p decreasing refcount to %u.\n", iface, refcount);
 
     if (!refcount)
+    {
+        d3drm_object_cleanup((IDirect3DRMObject *)iface, &material->obj);
+        IDirect3DRM_Release(material->d3drm);
         HeapFree(GetProcessHeap(), 0, material);
+    }
 
     return refcount;
 }
@@ -95,58 +83,68 @@ static HRESULT WINAPI d3drm_material_Clone(IDirect3DRMMaterial2 *iface,
 static HRESULT WINAPI d3drm_material_AddDestroyCallback(IDirect3DRMMaterial2 *iface,
         D3DRMOBJECTCALLBACK cb, void *ctx)
 {
-    FIXME("iface %p, cb %p, ctx %p stub!\n", iface, cb, ctx);
+    struct d3drm_material *material = impl_from_IDirect3DRMMaterial2(iface);
 
-    return E_NOTIMPL;
+    TRACE("iface %p, cb %p, ctx %p.\n", iface, cb, ctx);
+
+    return d3drm_object_add_destroy_callback(&material->obj, cb, ctx);
 }
 
 static HRESULT WINAPI d3drm_material_DeleteDestroyCallback(IDirect3DRMMaterial2 *iface,
         D3DRMOBJECTCALLBACK cb, void *ctx)
 {
-    FIXME("iface %p, cb %p, ctx %p stub!\n", iface, cb, ctx);
+    struct d3drm_material *material = impl_from_IDirect3DRMMaterial2(iface);
 
-    return E_NOTIMPL;
+    TRACE("iface %p, cb %p, ctx %p.\n", iface, cb, ctx);
+
+    return d3drm_object_delete_destroy_callback(&material->obj, cb, ctx);
 }
 
 static HRESULT WINAPI d3drm_material_SetAppData(IDirect3DRMMaterial2 *iface, DWORD data)
 {
-    FIXME("iface %p, data %#x stub!\n", iface, data);
+    struct d3drm_material *material = impl_from_IDirect3DRMMaterial2(iface);
 
-    return E_NOTIMPL;
+    TRACE("iface %p, data %#x.\n", iface, data);
+
+    material->obj.appdata = data;
+
+    return D3DRM_OK;
 }
 
 static DWORD WINAPI d3drm_material_GetAppData(IDirect3DRMMaterial2 *iface)
 {
-    FIXME("iface %p stub!\n", iface);
+    struct d3drm_material *material = impl_from_IDirect3DRMMaterial2(iface);
 
-    return 0;
+    TRACE("iface %p.\n", iface);
+
+    return material->obj.appdata;
 }
 
 static HRESULT WINAPI d3drm_material_SetName(IDirect3DRMMaterial2 *iface, const char *name)
 {
-    FIXME("iface %p, name %s stub!\n", iface, debugstr_a(name));
+    struct d3drm_material *material = impl_from_IDirect3DRMMaterial2(iface);
 
-    return E_NOTIMPL;
+    TRACE("iface %p, name %s.\n", iface, debugstr_a(name));
+
+    return d3drm_object_set_name(&material->obj, name);
 }
 
 static HRESULT WINAPI d3drm_material_GetName(IDirect3DRMMaterial2 *iface, DWORD *size, char *name)
 {
-    FIXME("iface %p, size %p, name %p stub!\n", iface, size, name);
+    struct d3drm_material *material = impl_from_IDirect3DRMMaterial2(iface);
 
-    return E_NOTIMPL;
+    TRACE("iface %p, size %p, name %p.\n", iface, size, name);
+
+    return d3drm_object_get_name(&material->obj, size, name);
 }
 
 static HRESULT WINAPI d3drm_material_GetClassName(IDirect3DRMMaterial2 *iface, DWORD *size, char *name)
 {
-    TRACE("iface %p, size %p, name %p.\n", iface, size, name);
-
-    if (!size || *size < strlen("Material") || !name)
-        return E_INVALIDARG;
+    struct d3drm_material *material = impl_from_IDirect3DRMMaterial2(iface);
 
-    strcpy(name, "Material");
-    *size = sizeof("Material");
+    TRACE("iface %p, size %p, name %p.\n", iface, size, name);
 
-    return D3DRM_OK;
+    return d3drm_object_get_class_name(&material->obj, size, name);
 }
 
 static HRESULT WINAPI d3drm_material_SetPower(IDirect3DRMMaterial2 *iface, D3DVALUE power)
@@ -276,23 +274,28 @@ static const struct IDirect3DRMMaterial2Vtbl d3drm_material_vtbl =
     d3drm_material_SetAmbient,
 };
 
-HRESULT Direct3DRMMaterial_create(IDirect3DRMMaterial2 **out)
+HRESULT d3drm_material_create(struct d3drm_material **material, IDirect3DRM *d3drm)
 {
+    static const char classname[] = "Material";
     struct d3drm_material *object;
 
-    TRACE("out %p.\n", out);
+    TRACE("material %p, d3drm %p.\n", material, d3drm);
 
     if (!(object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*object))))
         return E_OUTOFMEMORY;
 
     object->IDirect3DRMMaterial2_iface.lpVtbl = &d3drm_material_vtbl;
     object->ref = 1;
+    object->d3drm = d3drm;
+    IDirect3DRM_AddRef(object->d3drm);
 
     object->specular.r = 1.0f;
     object->specular.g = 1.0f;
     object->specular.b = 1.0f;
 
-    *out = &object->IDirect3DRMMaterial2_iface;
+    d3drm_object_init(&object->obj, classname);
+
+    *material = object;
 
     return S_OK;
 }
index e546061..962d8f6 100644 (file)
 
 #include "d3drm_private.h"
 
-struct mesh_group
-{
-    unsigned nb_vertices;
-    D3DRMVERTEX* vertices;
-    unsigned nb_faces;
-    unsigned vertex_per_face;
-    DWORD face_data_size;
-    unsigned* face_data;
-    D3DCOLOR color;
-    IDirect3DRMMaterial2* material;
-    IDirect3DRMTexture3* texture;
-};
-
-struct d3drm_mesh
-{
-    IDirect3DRMMesh IDirect3DRMMesh_iface;
-    LONG ref;
-    DWORD groups_capacity;
-    DWORD nb_groups;
-    struct mesh_group *groups;
-};
-
 struct coords_2d
 {
     D3DVALUE u;
@@ -56,29 +34,6 @@ struct mesh_material
     IDirect3DRMTexture3 *texture;
 };
 
-struct d3drm_mesh_builder
-{
-    IDirect3DRMMeshBuilder2 IDirect3DRMMeshBuilder2_iface;
-    IDirect3DRMMeshBuilder3 IDirect3DRMMeshBuilder3_iface;
-    LONG ref;
-    char* name;
-    DWORD nb_vertices;
-    D3DVECTOR* pVertices;
-    DWORD nb_normals;
-    D3DVECTOR* pNormals;
-    DWORD nb_faces;
-    DWORD face_data_size;
-    void *pFaceData;
-    DWORD nb_coords2d;
-    struct coords_2d *pCoords2d;
-    D3DCOLOR color;
-    IDirect3DRMMaterial2 *material;
-    IDirect3DRMTexture3 *texture;
-    DWORD nb_materials;
-    struct mesh_material *materials;
-    DWORD *material_indices;
-};
-
 char templates[] = {
 "xof 0302txt 0064"
 "template Header"
@@ -300,6 +255,38 @@ char templates[] = {
 "}"
 };
 
+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;
+
+    if (element_count <= *capacity)
+        return TRUE;
+
+    max_capacity = ~(SIZE_T)0 / element_size;
+    if (max_capacity < element_count)
+        return FALSE;
+
+    new_capacity = max(*capacity, 4);
+    while (new_capacity < element_count && new_capacity <= max_capacity / 2)
+        new_capacity *= 2;
+
+    if (new_capacity < element_count)
+        new_capacity = max_capacity;
+
+    if (*elements)
+        new_elements = HeapReAlloc(GetProcessHeap(), 0, *elements, new_capacity * element_size);
+    else
+        new_elements = HeapAlloc(GetProcessHeap(), 0, new_capacity * element_size);
+
+    if (!new_elements)
+        return FALSE;
+
+    *elements = new_elements;
+    *capacity = new_capacity;
+    return TRUE;
+}
+
 static inline struct d3drm_mesh *impl_from_IDirect3DRMMesh(IDirect3DRMMesh *iface)
 {
     return CONTAINING_RECORD(iface, struct d3drm_mesh, IDirect3DRMMesh_iface);
@@ -315,18 +302,24 @@ static inline struct d3drm_mesh_builder *impl_from_IDirect3DRMMeshBuilder3(IDire
     return CONTAINING_RECORD(iface, struct d3drm_mesh_builder, IDirect3DRMMeshBuilder3_iface);
 }
 
+static inline struct d3drm_wrap *impl_from_IDirect3DRMWrap(IDirect3DRMWrap *iface)
+{
+    return CONTAINING_RECORD(iface, struct d3drm_wrap, IDirect3DRMWrap_iface);
+}
+
 static void clean_mesh_builder_data(struct d3drm_mesh_builder *mesh_builder)
 {
     DWORD i;
 
-    HeapFree(GetProcessHeap(), 0, mesh_builder->name);
-    mesh_builder->name = NULL;
-    HeapFree(GetProcessHeap(), 0, mesh_builder->pVertices);
-    mesh_builder->pVertices = NULL;
+    IDirect3DRMMeshBuilder3_SetName(&mesh_builder->IDirect3DRMMeshBuilder3_iface, NULL);
+    HeapFree(GetProcessHeap(), 0, mesh_builder->vertices);
+    mesh_builder->vertices = NULL;
     mesh_builder->nb_vertices = 0;
-    HeapFree(GetProcessHeap(), 0, mesh_builder->pNormals);
-    mesh_builder->pNormals = NULL;
+    mesh_builder->vertices_size = 0;
+    HeapFree(GetProcessHeap(), 0, mesh_builder->normals);
+    mesh_builder->normals = NULL;
     mesh_builder->nb_normals = 0;
+    mesh_builder->normals_size = 0;
     HeapFree(GetProcessHeap(), 0, mesh_builder->pFaceData);
     mesh_builder->pFaceData = NULL;
     mesh_builder->face_data_size = 0;
@@ -356,6 +349,8 @@ static HRESULT WINAPI d3drm_mesh_builder2_QueryInterface(IDirect3DRMMeshBuilder2
 
     if (IsEqualGUID(riid, &IID_IDirect3DRMMeshBuilder2)
             || IsEqualGUID(riid, &IID_IDirect3DRMMeshBuilder)
+            || IsEqualGUID(riid, &IID_IDirect3DRMVisual)
+            || IsEqualGUID(riid, &IID_IDirect3DRMObject)
             || IsEqualGUID(riid, &IID_IUnknown))
     {
         *out = &mesh_builder->IDirect3DRMMeshBuilder2_iface;
@@ -394,11 +389,13 @@ static ULONG WINAPI d3drm_mesh_builder2_Release(IDirect3DRMMeshBuilder2 *iface)
 
     if (!refcount)
     {
+        d3drm_object_cleanup((IDirect3DRMObject *)iface, &mesh_builder->obj);
         clean_mesh_builder_data(mesh_builder);
         if (mesh_builder->material)
             IDirect3DRMMaterial2_Release(mesh_builder->material);
         if (mesh_builder->texture)
             IDirect3DRMTexture3_Release(mesh_builder->texture);
+        IDirect3DRM_Release(mesh_builder->d3drm);
         HeapFree(GetProcessHeap(), 0, mesh_builder);
     }
 
@@ -416,31 +413,59 @@ static HRESULT WINAPI d3drm_mesh_builder2_Clone(IDirect3DRMMeshBuilder2 *iface,
 static HRESULT WINAPI d3drm_mesh_builder2_AddDestroyCallback(IDirect3DRMMeshBuilder2 *iface,
         D3DRMOBJECTCALLBACK cb, void *ctx)
 {
-    FIXME("iface %p, cb %p, ctx %p stub!\n", iface, cb, ctx);
+    struct d3drm_mesh_builder *mesh_builder = impl_from_IDirect3DRMMeshBuilder2(iface);
 
-    return E_NOTIMPL;
+    TRACE("iface %p, cb %p, ctx %p.\n", iface, cb, ctx);
+
+    return IDirect3DRMMeshBuilder3_AddDestroyCallback(&mesh_builder->IDirect3DRMMeshBuilder3_iface, cb, ctx);
 }
 
 static HRESULT WINAPI d3drm_mesh_builder2_DeleteDestroyCallback(IDirect3DRMMeshBuilder2 *iface,
         D3DRMOBJECTCALLBACK cb, void *ctx)
 {
-    FIXME("iface %p, cb %p, ctx %p stub!\n", iface, cb, ctx);
+    struct d3drm_mesh_builder *mesh_builder = impl_from_IDirect3DRMMeshBuilder2(iface);
 
-    return E_NOTIMPL;
+    TRACE("iface %p, cb %p, ctx %p.\n", iface, cb, ctx);
+
+    return IDirect3DRMMeshBuilder3_DeleteDestroyCallback(&mesh_builder->IDirect3DRMMeshBuilder3_iface, cb, ctx);
+}
+
+static HRESULT WINAPI d3drm_mesh_builder3_SetAppData(IDirect3DRMMeshBuilder3 *iface, DWORD data)
+{
+    struct d3drm_mesh_builder *mesh_builder = impl_from_IDirect3DRMMeshBuilder3(iface);
+
+    TRACE("iface %p, data %#x.\n", iface, data);
+
+    mesh_builder->obj.appdata = data;
+
+    return D3DRM_OK;
 }
 
 static HRESULT WINAPI d3drm_mesh_builder2_SetAppData(IDirect3DRMMeshBuilder2 *iface, DWORD data)
 {
-    FIXME("iface %p, data %#x stub!\n", iface, data);
+    struct d3drm_mesh_builder *mesh_builder = impl_from_IDirect3DRMMeshBuilder2(iface);
 
-    return E_NOTIMPL;
+    TRACE("iface %p, data %#x.\n", iface, data);
+
+    return d3drm_mesh_builder3_SetAppData(&mesh_builder->IDirect3DRMMeshBuilder3_iface, data);
+}
+
+static DWORD WINAPI d3drm_mesh_builder3_GetAppData(IDirect3DRMMeshBuilder3 *iface)
+{
+    struct d3drm_mesh_builder *mesh_builder = impl_from_IDirect3DRMMeshBuilder3(iface);
+
+    TRACE("iface %p.\n", iface);
+
+    return mesh_builder->obj.appdata;
 }
 
 static DWORD WINAPI d3drm_mesh_builder2_GetAppData(IDirect3DRMMeshBuilder2 *iface)
 {
-    FIXME("iface %p stub!\n", iface);
+    struct d3drm_mesh_builder *mesh_builder = impl_from_IDirect3DRMMeshBuilder2(iface);
 
-    return 0;
+    TRACE("iface %p.\n", iface);
+
+    return d3drm_mesh_builder3_GetAppData(&mesh_builder->IDirect3DRMMeshBuilder3_iface);
 }
 
 static HRESULT WINAPI d3drm_mesh_builder2_SetName(IDirect3DRMMeshBuilder2 *iface, const char *name)
@@ -726,14 +751,14 @@ static HRESULT WINAPI d3drm_mesh_builder2_GetVertices(IDirect3DRMMeshBuilder2 *i
     if (vertex_count)
         *vertex_count = mesh_builder->nb_vertices;
     if (vertices && mesh_builder->nb_vertices)
-        memcpy(vertices, mesh_builder->pVertices, mesh_builder->nb_vertices * sizeof(*vertices));
+        memcpy(vertices, mesh_builder->vertices, mesh_builder->nb_vertices * sizeof(*vertices));
 
     if (normals && (!normal_count || (*normal_count < mesh_builder->nb_normals)))
         return D3DRMERR_BADVALUE;
     if (normal_count)
         *normal_count = mesh_builder->nb_normals;
     if (normals && mesh_builder->nb_normals)
-        memcpy(normals, mesh_builder->pNormals, mesh_builder->nb_normals * sizeof(*normals));
+        memcpy(normals, mesh_builder->normals, mesh_builder->nb_normals * sizeof(*normals));
 
     if (face_data && (!face_data_size || (*face_data_size < mesh_builder->face_data_size)))
         return D3DRMERR_BADVALUE;
@@ -759,24 +784,36 @@ static HRESULT WINAPI d3drm_mesh_builder2_GetTextureCoordinates(IDirect3DRMMeshB
 static int WINAPI d3drm_mesh_builder2_AddVertex(IDirect3DRMMeshBuilder2 *iface,
         D3DVALUE x, D3DVALUE y, D3DVALUE z)
 {
-    FIXME("iface %p, x %.8e, y %.8e, z %.8e stub!\n", iface, x, y, z);
+    struct d3drm_mesh_builder *mesh_builder = impl_from_IDirect3DRMMeshBuilder2(iface);
 
-    return 0;
+    TRACE("iface %p, x %.8e, y %.8e, z %.8e.\n", iface, x, y, z);
+
+    return IDirect3DRMMeshBuilder3_AddVertex(&mesh_builder->IDirect3DRMMeshBuilder3_iface, x, y, z);
 }
 
 static int WINAPI d3drm_mesh_builder2_AddNormal(IDirect3DRMMeshBuilder2 *iface,
         D3DVALUE x, D3DVALUE y, D3DVALUE z)
 {
-    FIXME("iface %p, x %.8e, y %.8e, z %.8e stub!\n", iface, x, y, z);
+    struct d3drm_mesh_builder *mesh_builder = impl_from_IDirect3DRMMeshBuilder2(iface);
 
-    return 0;
+    TRACE("iface %p, x %.8e, y %.8e, z %.8e.\n", iface, x, y, z);
+
+    return IDirect3DRMMeshBuilder3_AddNormal(&mesh_builder->IDirect3DRMMeshBuilder3_iface, x, y, z);
 }
 
 static HRESULT WINAPI d3drm_mesh_builder2_CreateFace(IDirect3DRMMeshBuilder2 *iface, IDirect3DRMFace **face)
 {
+    struct d3drm_face *object;
+    HRESULT hr;
+
     TRACE("iface %p, face %p.\n", iface, face);
 
-    return Direct3DRMFace_create(&IID_IDirect3DRMFace, (IUnknown **)face);
+    if (FAILED(hr = d3drm_face_create(&object)))
+        return hr;
+
+    *face = &object->IDirect3DRMFace_iface;
+
+    return S_OK;
 }
 
 static D3DRMRENDERQUALITY WINAPI d3drm_mesh_builder2_GetQuality(IDirect3DRMMeshBuilder2 *iface)
@@ -936,50 +973,30 @@ static HRESULT WINAPI d3drm_mesh_builder3_Clone(IDirect3DRMMeshBuilder3 *iface,
 static HRESULT WINAPI d3drm_mesh_builder3_AddDestroyCallback(IDirect3DRMMeshBuilder3 *iface,
         D3DRMOBJECTCALLBACK cb, void *ctx)
 {
-    FIXME("iface %p, cb %p, ctx %p stub!\n", iface, cb, ctx);
+    struct d3drm_mesh_builder *mesh_builder = impl_from_IDirect3DRMMeshBuilder3(iface);
 
-    return E_NOTIMPL;
+    TRACE("iface %p, cb %p, ctx %p.\n", iface, cb, ctx);
+
+    return d3drm_object_add_destroy_callback(&mesh_builder->obj, cb, ctx);
 }
 
 static HRESULT WINAPI d3drm_mesh_builder3_DeleteDestroyCallback(IDirect3DRMMeshBuilder3 *iface,
         D3DRMOBJECTCALLBACK cb, void *ctx)
 {
-    FIXME("iface %p, cb %p, ctx %p stub!\n", iface, cb, ctx);
-
-    return E_NOTIMPL;
-}
-
-static HRESULT WINAPI d3drm_mesh_builder3_SetAppData(IDirect3DRMMeshBuilder3 *iface, DWORD data)
-{
-    FIXME("iface %p, data %#x stub!\n", iface, data);
-
-    return E_NOTIMPL;
-}
+    struct d3drm_mesh_builder *mesh_builder = impl_from_IDirect3DRMMeshBuilder3(iface);
 
-static DWORD WINAPI d3drm_mesh_builder3_GetAppData(IDirect3DRMMeshBuilder3 *iface)
-{
-    FIXME("iface %p stub!\n", iface);
+    TRACE("iface %p, cb %p, ctx %p.\n", iface, cb, ctx);
 
-    return 0;
+    return d3drm_object_delete_destroy_callback(&mesh_builder->obj, cb, ctx);
 }
 
 static HRESULT WINAPI d3drm_mesh_builder3_SetName(IDirect3DRMMeshBuilder3 *iface, const char *name)
 {
     struct d3drm_mesh_builder *mesh_builder = impl_from_IDirect3DRMMeshBuilder3(iface);
-    char *string = NULL;
 
     TRACE("iface %p, name %s.\n", iface, debugstr_a(name));
 
-    if (name)
-    {
-        string = HeapAlloc(GetProcessHeap(), 0, strlen(name) + 1);
-        if (!string) return E_OUTOFMEMORY;
-        strcpy(string, name);
-    }
-    HeapFree(GetProcessHeap(), 0, mesh_builder->name);
-    mesh_builder->name = string;
-
-    return D3DRM_OK;
+    return d3drm_object_set_name(&mesh_builder->obj, name);
 }
 
 static HRESULT WINAPI d3drm_mesh_builder3_GetName(IDirect3DRMMeshBuilder3 *iface,
@@ -989,42 +1006,23 @@ static HRESULT WINAPI d3drm_mesh_builder3_GetName(IDirect3DRMMeshBuilder3 *iface
 
     TRACE("iface %p, size %p, name %p.\n", iface, size, name);
 
-    if (!size)
-        return E_POINTER;
-
-    if (!mesh_builder->name)
-    {
-        *size = 0;
-        return D3DRM_OK;
-    }
-
-    if (*size < (strlen(mesh_builder->name) + 1))
-        return E_INVALIDARG;
-
-    strcpy(name, mesh_builder->name);
-    *size = strlen(mesh_builder->name) + 1;
-
-    return D3DRM_OK;
+    return d3drm_object_get_name(&mesh_builder->obj, size, name);
 }
 
 static HRESULT WINAPI d3drm_mesh_builder3_GetClassName(IDirect3DRMMeshBuilder3 *iface,
         DWORD *size, char *name)
 {
-    TRACE("iface %p, size %p, name %p.\n", iface, size, name);
-
-    if (!size || *size < strlen("Builder") || !name)
-        return E_INVALIDARG;
+    struct d3drm_mesh_builder *meshbuilder = impl_from_IDirect3DRMMeshBuilder3(iface);
 
-    strcpy(name, "Builder");
-    *size = sizeof("Builder");
+    TRACE("iface %p, size %p, name %p.\n", iface, size, name);
 
-    return D3DRM_OK;
+    return d3drm_object_get_class_name(&meshbuilder->obj, size, name);
 }
 
 HRESULT load_mesh_data(IDirect3DRMMeshBuilder3 *iface, IDirectXFileData *pData,
         D3DRMLOADTEXTURECALLBACK load_texture_proc, void *arg)
 {
-    struct d3drm_mesh_builder *This = impl_from_IDirect3DRMMeshBuilder3(iface);
+    struct d3drm_mesh_builder *mesh_builder = impl_from_IDirect3DRMMeshBuilder3(iface);
     IDirectXFileData *pData2 = NULL;
     const GUID* guid;
     DWORD size;
@@ -1040,45 +1038,54 @@ HRESULT load_mesh_data(IDirect3DRMMeshBuilder3 *iface, IDirectXFileData *pData,
     DWORD faces_data_size = 0;
     DWORD i;
 
-    TRACE("(%p)->(%p)\n", This, pData);
+    TRACE("(%p)->(%p)\n", mesh_builder, pData);
 
     hr = IDirectXFileData_GetName(pData, NULL, &size);
     if (hr != DXFILE_OK)
         return hr;
     if (size)
     {
-        This->name = HeapAlloc(GetProcessHeap(), 0, size);
-        if (!This->name)
+        char *name = HeapAlloc(GetProcessHeap(), 0, size);
+        if (!name)
             return E_OUTOFMEMORY;
 
-        hr = IDirectXFileData_GetName(pData, This->name, &size);
+        if (SUCCEEDED(hr = IDirectXFileData_GetName(pData, name, &size)))
+            IDirect3DRMMeshBuilder3_SetName(iface, name);
+        HeapFree(GetProcessHeap(), 0, name);
         if (hr != DXFILE_OK)
             return hr;
     }
 
-    TRACE("Mesh name is %s\n", debugstr_a(This->name));
+    TRACE("Mesh name is %s\n", debugstr_a(mesh_builder->obj.name));
 
-    This->nb_normals = 0;
+    mesh_builder->nb_normals = 0;
 
     hr = IDirectXFileData_GetData(pData, NULL, &size, (void**)&ptr);
     if (hr != DXFILE_OK)
         goto end;
 
-    This->nb_vertices = *(DWORD*)ptr;
-    This->nb_faces = *(DWORD*)(ptr + sizeof(DWORD) + This->nb_vertices * sizeof(D3DVECTOR));
-    faces_vertex_idx_size = size - sizeof(DWORD) - This->nb_vertices * sizeof(D3DVECTOR) - sizeof(DWORD);
+    mesh_builder->nb_vertices = *(DWORD*)ptr;
+    mesh_builder->nb_faces = *(DWORD*)(ptr + sizeof(DWORD) + mesh_builder->nb_vertices * sizeof(D3DVECTOR));
+    faces_vertex_idx_size = size - sizeof(DWORD) - mesh_builder->nb_vertices * sizeof(D3DVECTOR) - sizeof(DWORD);
 
-    TRACE("Mesh: nb_vertices = %d, nb_faces = %d, faces_vertex_idx_size = %d\n", This->nb_vertices, This->nb_faces, faces_vertex_idx_size);
+    TRACE("Mesh: nb_vertices = %lu, nb_faces = %d, faces_vertex_idx_size = %d\n", mesh_builder->nb_vertices,
+            mesh_builder->nb_faces, faces_vertex_idx_size);
 
-    This->pVertices = HeapAlloc(GetProcessHeap(), 0, This->nb_vertices * sizeof(D3DVECTOR));
-    memcpy(This->pVertices, ptr + sizeof(DWORD), This->nb_vertices * sizeof(D3DVECTOR));
+    if (!d3drm_array_reserve((void **)&mesh_builder->vertices, &mesh_builder->vertices_size, mesh_builder->nb_vertices,
+           sizeof(*mesh_builder->vertices)))
+    {
+        hr = E_OUTOFMEMORY;
+        goto end;
+    }
+    memcpy(mesh_builder->vertices, ptr + sizeof(DWORD), mesh_builder->nb_vertices * sizeof(D3DVECTOR));
 
     faces_vertex_idx_ptr = faces_vertex_idx_data = HeapAlloc(GetProcessHeap(), 0, faces_vertex_idx_size);
-    memcpy(faces_vertex_idx_data, ptr + sizeof(DWORD) + This->nb_vertices * sizeof(D3DVECTOR) + sizeof(DWORD), faces_vertex_idx_size);
+    memcpy(faces_vertex_idx_data, ptr + sizeof(DWORD) + mesh_builder->nb_vertices * sizeof(D3DVECTOR) + sizeof(DWORD),
+            faces_vertex_idx_size);
 
     /* Each vertex index will have its normal index counterpart so just allocate twice the size */
-    This->pFaceData = HeapAlloc(GetProcessHeap(), 0, faces_vertex_idx_size * 2);
-    faces_data_ptr = (DWORD*)This->pFaceData;
+    mesh_builder->pFaceData = HeapAlloc(GetProcessHeap(), 0, faces_vertex_idx_size * 2);
+    faces_data_ptr = (DWORD*)mesh_builder->pFaceData;
 
     while (1)
     {
@@ -1113,19 +1120,24 @@ HRESULT load_mesh_data(IDirect3DRMMeshBuilder3 *iface, IDirectXFileData *pData,
             if (hr != DXFILE_OK)
                 goto end;
 
-            This->nb_normals = *(DWORD*)ptr;
-            nb_faces_normals = *(DWORD*)(ptr + sizeof(DWORD) + This->nb_normals * sizeof(D3DVECTOR));
+            mesh_builder->nb_normals = *(DWORD*)ptr;
+            nb_faces_normals = *(DWORD*)(ptr + sizeof(DWORD) + mesh_builder->nb_normals * sizeof(D3DVECTOR));
 
-            TRACE("MeshNormals: nb_normals = %d, nb_faces_normals = %d\n", This->nb_normals, nb_faces_normals);
-            if (nb_faces_normals != This->nb_faces)
-                WARN("nb_face_normals (%d) != nb_faces (%d)\n", nb_faces_normals, This->nb_normals);
+            TRACE("MeshNormals: nb_normals = %lu, nb_faces_normals = %d\n", mesh_builder->nb_normals, nb_faces_normals);
+            if (nb_faces_normals != mesh_builder->nb_faces)
+                WARN("nb_face_normals (%d) != nb_faces (%d)\n", nb_faces_normals, mesh_builder->nb_faces);
 
-            This->pNormals = HeapAlloc(GetProcessHeap(), 0, This->nb_normals * sizeof(D3DVECTOR));
-            memcpy(This->pNormals, ptr + sizeof(DWORD), This->nb_normals * sizeof(D3DVECTOR));
+            if (!d3drm_array_reserve((void **)&mesh_builder->normals, &mesh_builder->normals_size,
+                    mesh_builder->nb_normals, sizeof(*mesh_builder->normals)))
+            {
+                hr = E_OUTOFMEMORY;
+                goto end;
+            }
+            memcpy(mesh_builder->normals, ptr + sizeof(DWORD), mesh_builder->nb_normals * sizeof(D3DVECTOR));
 
-            faces_normal_idx_size = size - (2 * sizeof(DWORD) + This->nb_normals * sizeof(D3DVECTOR));
+            faces_normal_idx_size = size - (2 * sizeof(DWORD) + mesh_builder->nb_normals * sizeof(D3DVECTOR));
             faces_normal_idx_ptr = faces_normal_idx_data = HeapAlloc(GetProcessHeap(), 0, faces_normal_idx_size);
-            memcpy(faces_normal_idx_data, ptr + sizeof(DWORD) + This->nb_normals * sizeof(D3DVECTOR) + sizeof(DWORD), faces_normal_idx_size);
+            memcpy(faces_normal_idx_data, ptr + sizeof(DWORD) + mesh_builder->nb_normals * sizeof(D3DVECTOR) + sizeof(DWORD), faces_normal_idx_size);
         }
         else if (IsEqualGUID(guid, &TID_D3DRMMeshTextureCoords))
         {
@@ -1133,13 +1145,12 @@ HRESULT load_mesh_data(IDirect3DRMMeshBuilder3 *iface, IDirectXFileData *pData,
             if (hr != DXFILE_OK)
                 goto end;
 
-            This->nb_coords2d = *(DWORD*)ptr;
+            mesh_builder->nb_coords2d = *(DWORD*)ptr;
 
-            TRACE("MeshTextureCoords: nb_coords2d = %d\n", This->nb_coords2d);
-
-            This->pCoords2d = HeapAlloc(GetProcessHeap(), 0, This->nb_coords2d * sizeof(*This->pCoords2d));
-            memcpy(This->pCoords2d, ptr + sizeof(DWORD), This->nb_coords2d * sizeof(*This->pCoords2d));
+            TRACE("MeshTextureCoords: nb_coords2d = %d\n", mesh_builder->nb_coords2d);
 
+            mesh_builder->pCoords2d = HeapAlloc(GetProcessHeap(), 0, mesh_builder->nb_coords2d * sizeof(*mesh_builder->pCoords2d));
+            memcpy(mesh_builder->pCoords2d, ptr + sizeof(DWORD), mesh_builder->nb_coords2d * sizeof(*mesh_builder->pCoords2d));
         }
         else if (IsEqualGUID(guid, &TID_D3DRMMeshMaterialList))
         {
@@ -1166,24 +1177,25 @@ HRESULT load_mesh_data(IDirect3DRMMeshBuilder3 *iface, IDirectXFileData *pData,
             if (size != data_size)
                 WARN("Returned size %u does not match expected one %u\n", size, data_size);
 
-            This->material_indices = HeapAlloc(GetProcessHeap(), 0, sizeof(*This->material_indices) * nb_face_indices);
-            if (!This->material_indices)
+            mesh_builder->material_indices = HeapAlloc(GetProcessHeap(), 0, sizeof(*mesh_builder->material_indices) * nb_face_indices);
+            if (!mesh_builder->material_indices)
                 goto end;
-            memcpy(This->material_indices, ptr + 2 * sizeof(DWORD), sizeof(*This->material_indices) * nb_face_indices),
+            memcpy(mesh_builder->material_indices, ptr + 2 * sizeof(DWORD), sizeof(*mesh_builder->material_indices) * nb_face_indices),
 
-            This->materials = HeapAlloc(GetProcessHeap(), 0, sizeof(*This->materials) * nb_materials);
-            if (!This->materials)
+            mesh_builder->materials = HeapAlloc(GetProcessHeap(), 0, sizeof(*mesh_builder->materials) * nb_materials);
+            if (!mesh_builder->materials)
             {
-                HeapFree(GetProcessHeap(), 0, This->material_indices);
+                HeapFree(GetProcessHeap(), 0, mesh_builder->material_indices);
                 goto end;
             }
-            This->nb_materials = nb_materials;
+            mesh_builder->nb_materials = nb_materials;
 
             while (SUCCEEDED(hr = IDirectXFileData_GetNextObject(pData2, &child)) && (i < nb_materials))
             {
                 IDirectXFileData *data;
                 IDirectXFileDataReference *reference;
                 IDirectXFileObject *material_child;
+                struct d3drm_material *object;
 
                 hr = IDirectXFileObject_QueryInterface(child, &IID_IDirectXFileData, (void **)&data);
                 if (FAILED(hr))
@@ -1203,12 +1215,13 @@ HRESULT load_mesh_data(IDirect3DRMMeshBuilder3 *iface, IDirectXFileData *pData,
                     IDirectXFileObject_Release(child);
                 }
 
-                hr = Direct3DRMMaterial_create(&This->materials[i].material);
+                hr = d3drm_material_create(&object, mesh_builder->d3drm);
                 if (FAILED(hr))
                 {
                     IDirectXFileData_Release(data);
                     goto end;
                 }
+                mesh_builder->materials[i].material = &object->IDirect3DRMMaterial2_iface;
 
                 hr = IDirectXFileData_GetData(data, NULL, &size, (void**)&ptr);
                 if (hr != DXFILE_OK)
@@ -1222,14 +1235,14 @@ HRESULT load_mesh_data(IDirect3DRMMeshBuilder3 *iface, IDirectXFileData *pData,
 
                 values = (float*)ptr;
 
-                d3drm_set_color(&This->materials[i].color, values[0], values[1], values[2], values[3]);
+                d3drm_set_color(&mesh_builder->materials[i].color, values[0], values[1], values[2], values[3]);
 
-                IDirect3DRMMaterial2_SetAmbient(This->materials[i].material, values[0], values [1], values[2]); /* Alpha ignored */
-                IDirect3DRMMaterial2_SetPower(This->materials[i].material, values[4]);
-                IDirect3DRMMaterial2_SetSpecular(This->materials[i].material, values[5], values[6], values[7]);
-                IDirect3DRMMaterial2_SetEmissive(This->materials[i].material, values[8], values[9], values[10]);
+                IDirect3DRMMaterial2_SetAmbient(mesh_builder->materials[i].material, values[0], values [1], values[2]); /* Alpha ignored */
+                IDirect3DRMMaterial2_SetPower(mesh_builder->materials[i].material, values[4]);
+                IDirect3DRMMaterial2_SetSpecular(mesh_builder->materials[i].material, values[5], values[6], values[7]);
+                IDirect3DRMMaterial2_SetEmissive(mesh_builder->materials[i].material, values[8], values[9], values[10]);
 
-                This->materials[i].texture = NULL;
+                mesh_builder->materials[i].texture = NULL;
 
                 hr = IDirectXFileData_GetNextObject(data, &material_child);
                 if (hr == S_OK)
@@ -1273,7 +1286,8 @@ HRESULT load_mesh_data(IDirect3DRMMeshBuilder3 *iface, IDirectXFileData *pData,
                             hr = load_texture_proc(*filename, arg, &texture);
                             if (SUCCEEDED(hr))
                             {
-                                hr = IDirect3DTexture_QueryInterface(texture, &IID_IDirect3DRMTexture3, (void**)&This->materials[i].texture);
+                                hr = IDirect3DTexture_QueryInterface(texture, &IID_IDirect3DRMTexture3,
+                                        (void **)&mesh_builder->materials[i].texture);
                                 IDirect3DTexture_Release(texture);
                             }
                         }
@@ -1291,7 +1305,7 @@ HRESULT load_mesh_data(IDirect3DRMMeshBuilder3 *iface, IDirectXFileData *pData,
                                     IDirectXFileData_Release(data);
                                     goto end;
                                 }
-                                This->materials[i].texture = &texture_object->IDirect3DRMTexture3_iface;
+                                mesh_builder->materials[i].texture = &texture_object->IDirect3DRMTexture3_iface;
                             }
                         }
                     }
@@ -1326,15 +1340,16 @@ HRESULT load_mesh_data(IDirect3DRMMeshBuilder3 *iface, IDirectXFileData *pData,
         pData2 = NULL;
     }
 
-    if (!This->nb_normals)
+    if (!mesh_builder->nb_normals)
     {
         /* Allocate normals, one per vertex */
-        This->pNormals = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, This->nb_vertices * sizeof(D3DVECTOR));
-        if (!This->pNormals)
+        if (!d3drm_array_reserve((void **)&mesh_builder->normals, &mesh_builder->normals_size,
+                mesh_builder->nb_vertices, sizeof(*mesh_builder->normals)))
             goto end;
+        memset(mesh_builder->normals, 0, mesh_builder->nb_vertices * sizeof(*mesh_builder->normals));
     }
 
-    for (i = 0; i < This->nb_faces; i++)
+    for (i = 0; i < mesh_builder->nb_faces; i++)
     {
         DWORD j;
         DWORD nb_face_indexes;
@@ -1351,18 +1366,18 @@ HRESULT load_mesh_data(IDirect3DRMMeshBuilder3 *iface, IDirectXFileData *pData,
         if (faces_vertex_idx_size < (nb_face_indexes * sizeof(DWORD)))
             WARN("Not enough data to read all indices of face %d\n", i);
 
-        if (!This->nb_normals)
+        if (!mesh_builder->nb_normals)
         {
             /* Compute face normal */
             if (nb_face_indexes > 2
-                    && faces_vertex_idx_ptr[0] < This->nb_vertices
-                    && faces_vertex_idx_ptr[1] < This->nb_vertices
-                    && faces_vertex_idx_ptr[2] < This->nb_vertices)
+                    && faces_vertex_idx_ptr[0] < mesh_builder->nb_vertices
+                    && faces_vertex_idx_ptr[1] < mesh_builder->nb_vertices
+                    && faces_vertex_idx_ptr[2] < mesh_builder->nb_vertices)
             {
                 D3DVECTOR a, b;
 
-                D3DRMVectorSubtract(&a, &This->pVertices[faces_vertex_idx_ptr[2]], &This->pVertices[faces_vertex_idx_ptr[1]]);
-                D3DRMVectorSubtract(&b, &This->pVertices[faces_vertex_idx_ptr[0]], &This->pVertices[faces_vertex_idx_ptr[1]]);
+                D3DRMVectorSubtract(&a, &mesh_builder->vertices[faces_vertex_idx_ptr[2]], &mesh_builder->vertices[faces_vertex_idx_ptr[1]]);
+                D3DRMVectorSubtract(&b, &mesh_builder->vertices[faces_vertex_idx_ptr[0]], &mesh_builder->vertices[faces_vertex_idx_ptr[1]]);
                 D3DRMVectorCrossProduct(&face_normal, &a, &b);
                 D3DRMVectorNormalize(&face_normal);
             }
@@ -1379,7 +1394,7 @@ HRESULT load_mesh_data(IDirect3DRMMeshBuilder3 *iface, IDirectXFileData *pData,
             /* Copy vertex index */
             *(faces_data_ptr + faces_data_size++) = *faces_vertex_idx_ptr;
             /* Copy normal index */
-            if (This->nb_normals)
+            if (mesh_builder->nb_normals)
             {
                 /* Read from x file */
                 *(faces_data_ptr + faces_data_size++) = *(faces_normal_idx_ptr++);
@@ -1387,14 +1402,15 @@ HRESULT load_mesh_data(IDirect3DRMMeshBuilder3 *iface, IDirectXFileData *pData,
             else
             {
                 DWORD vertex_idx = *faces_vertex_idx_ptr;
-                if (vertex_idx >= This->nb_vertices)
+                if (vertex_idx >= mesh_builder->nb_vertices)
                 {
-                    WARN("Found vertex index %u but only %u vertices available => use index 0\n", vertex_idx, This->nb_vertices);
+                    WARN("Found vertex index %u but only %lu vertices available => use index 0\n", vertex_idx,
+                            mesh_builder->nb_vertices);
                     vertex_idx = 0;
                 }
                 *(faces_data_ptr + faces_data_size++) = vertex_idx;
                 /* Add face normal to vertex normal */
-                D3DRMVectorAdd(&This->pNormals[vertex_idx], &This->pNormals[vertex_idx], &face_normal);
+                D3DRMVectorAdd(&mesh_builder->normals[vertex_idx], &mesh_builder->normals[vertex_idx], &face_normal);
             }
             faces_vertex_idx_ptr++;
         }
@@ -1405,27 +1421,27 @@ HRESULT load_mesh_data(IDirect3DRMMeshBuilder3 *iface, IDirectXFileData *pData,
     *(faces_data_ptr + faces_data_size++) = 0;
 
     /* Set size (in number of DWORD) of all faces data */
-    This->face_data_size = faces_data_size;
+    mesh_builder->face_data_size = faces_data_size;
 
-    if (!This->nb_normals)
+    if (!mesh_builder->nb_normals)
     {
         /* Normalize all normals */
-        for (i = 0; i < This->nb_vertices; i++)
+        for (i = 0; i < mesh_builder->nb_vertices; i++)
         {
-            D3DRMVectorNormalize(&This->pNormals[i]);
+            D3DRMVectorNormalize(&mesh_builder->normals[i]);
         }
-        This->nb_normals = This->nb_vertices;
+        mesh_builder->nb_normals = mesh_builder->nb_vertices;
     }
 
     /* If there is no texture coordinates, generate default texture coordinates (0.0f, 0.0f) for each vertex */
-    if (!This->pCoords2d)
+    if (!mesh_builder->pCoords2d)
     {
-        This->nb_coords2d = This->nb_vertices;
-        This->pCoords2d = HeapAlloc(GetProcessHeap(), 0, This->nb_coords2d * sizeof(*This->pCoords2d));
-        for (i = 0; i < This->nb_coords2d; i++)
+        mesh_builder->nb_coords2d = mesh_builder->nb_vertices;
+        mesh_builder->pCoords2d = HeapAlloc(GetProcessHeap(), 0, mesh_builder->nb_coords2d * sizeof(*mesh_builder->pCoords2d));
+        for (i = 0; i < mesh_builder->nb_coords2d; i++)
         {
-            This->pCoords2d[i].u = 0.0f;
-            This->pCoords2d[i].v = 0.0f;
+            mesh_builder->pCoords2d[i].u = 0.0f;
+            mesh_builder->pCoords2d[i].v = 0.0f;
         }
     }
 
@@ -1577,9 +1593,9 @@ static HRESULT WINAPI d3drm_mesh_builder3_Scale(IDirect3DRMMeshBuilder3 *iface,
 
     for (i = 0; i < mesh_builder->nb_vertices; ++i)
     {
-        mesh_builder->pVertices[i].u1.x *= sx;
-        mesh_builder->pVertices[i].u2.y *= sy;
-        mesh_builder->pVertices[i].u3.z *= sz;
+        mesh_builder->vertices[i].u1.x *= sx;
+        mesh_builder->vertices[i].u2.y *= sy;
+        mesh_builder->vertices[i].u3.z *= sz;
     }
 
     /* Normals are not affected by Scale */
@@ -1839,24 +1855,52 @@ static HRESULT WINAPI d3drm_mesh_builder3_GetTextureCoordinates(IDirect3DRMMeshB
 static int WINAPI d3drm_mesh_builder3_AddVertex(IDirect3DRMMeshBuilder3 *iface,
         D3DVALUE x, D3DVALUE y, D3DVALUE z)
 {
-    FIXME("iface %p, x %.8e, y %.8e, z %.8e stub!\n", iface, x, y, z);
+    struct d3drm_mesh_builder *mesh_builder = impl_from_IDirect3DRMMeshBuilder3(iface);
 
-    return 0;
+    TRACE("iface %p, x %.8e, y %.8e, z %.8e.\n", iface, x, y, z);
+
+    if (!d3drm_array_reserve((void **)&mesh_builder->vertices, &mesh_builder->vertices_size,
+            mesh_builder->nb_vertices + 1, sizeof(*mesh_builder->vertices)))
+        return 0;
+
+    mesh_builder->vertices[mesh_builder->nb_vertices].u1.x = x;
+    mesh_builder->vertices[mesh_builder->nb_vertices].u2.y = y;
+    mesh_builder->vertices[mesh_builder->nb_vertices].u3.z = z;
+
+    return mesh_builder->nb_vertices++;
 }
 
 static int WINAPI d3drm_mesh_builder3_AddNormal(IDirect3DRMMeshBuilder3 *iface,
         D3DVALUE x, D3DVALUE y, D3DVALUE z)
 {
-    FIXME("iface %p, x %.8e, y %.8e, z %.8e stub!\n", iface, x, y, z);
+    struct d3drm_mesh_builder *mesh_builder = impl_from_IDirect3DRMMeshBuilder3(iface);
 
-    return 0;
+    TRACE("iface %p, x %.8e, y %.8e, z %.8e.\n", iface, x, y, z);
+
+    if (!d3drm_array_reserve((void **)&mesh_builder->normals, &mesh_builder->normals_size,
+            mesh_builder->nb_normals + 1, sizeof(*mesh_builder->normals)))
+        return 0;
+
+    mesh_builder->normals[mesh_builder->nb_normals].u1.x = x;
+    mesh_builder->normals[mesh_builder->nb_normals].u2.y = y;
+    mesh_builder->normals[mesh_builder->nb_normals].u3.z = z;
+
+    return mesh_builder->nb_normals++;
 }
 
 static HRESULT WINAPI d3drm_mesh_builder3_CreateFace(IDirect3DRMMeshBuilder3 *iface, IDirect3DRMFace2 **face)
 {
+    struct d3drm_face *object;
+    HRESULT hr;
+
     TRACE("iface %p, face %p.\n", iface, face);
 
-    return Direct3DRMFace_create(&IID_IDirect3DRMFace2, (IUnknown **)face);
+    if (FAILED(hr = d3drm_face_create(&object)))
+        return hr;
+
+    *face = &object->IDirect3DRMFace2_iface;
+
+    return S_OK;
 }
 
 static D3DRMRENDERQUALITY WINAPI d3drm_mesh_builder3_GetQuality(IDirect3DRMMeshBuilder3 *iface)
@@ -1901,7 +1945,7 @@ static D3DCOLOR WINAPI d3drm_mesh_builder3_GetVertexColor(IDirect3DRMMeshBuilder
 
 static HRESULT WINAPI d3drm_mesh_builder3_CreateMesh(IDirect3DRMMeshBuilder3 *iface, IDirect3DRMMesh **mesh)
 {
-    struct d3drm_mesh_builder *This = impl_from_IDirect3DRMMeshBuilder3(iface);
+    struct d3drm_mesh_builder *mesh_builder = impl_from_IDirect3DRMMeshBuilder3(iface);
     HRESULT hr;
     D3DRMGROUPINDEX group;
 
@@ -1910,47 +1954,47 @@ static HRESULT WINAPI d3drm_mesh_builder3_CreateMesh(IDirect3DRMMeshBuilder3 *if
     if (!mesh)
         return E_POINTER;
 
-    hr = Direct3DRMMesh_create(mesh);
+    hr = IDirect3DRM_CreateMesh(mesh_builder->d3drm, mesh);
     if (FAILED(hr))
         return hr;
 
     /* If there is mesh data, create a group and put data inside */
-    if (This->nb_vertices)
+    if (mesh_builder->nb_vertices)
     {
         DWORD i, j;
         int k;
         D3DRMVERTEX* vertices;
 
-        vertices = HeapAlloc(GetProcessHeap(), 0, This->nb_vertices * sizeof(D3DRMVERTEX));
+        vertices = HeapAlloc(GetProcessHeap(), 0, mesh_builder->nb_vertices * sizeof(D3DRMVERTEX));
         if (!vertices)
         {
             IDirect3DRMMesh_Release(*mesh);
             return E_OUTOFMEMORY;
         }
-        for (i = 0; i < This->nb_vertices; i++)
-            vertices[i].position = This->pVertices[i];
-        hr = IDirect3DRMMesh_SetVertices(*mesh, 0, 0, This->nb_vertices, vertices);
+        for (i = 0; i < mesh_builder->nb_vertices; i++)
+            vertices[i].position = mesh_builder->vertices[i];
+        hr = IDirect3DRMMesh_SetVertices(*mesh, 0, 0, mesh_builder->nb_vertices, vertices);
         HeapFree(GetProcessHeap(), 0, vertices);
 
         /* Groups are in reverse order compared to materials list in X file */
-        for (k = This->nb_materials - 1; k >= 0; k--)
+        for (k = mesh_builder->nb_materials - 1; k >= 0; k--)
         {
             unsigned* face_data;
             unsigned* out_ptr;
-            DWORD* in_ptr = This->pFaceData;
+            DWORD* in_ptr = mesh_builder->pFaceData;
             ULONG vertex_per_face = 0;
             BOOL* used_vertices;
             unsigned nb_vertices = 0;
             unsigned nb_faces = 0;
 
-            used_vertices = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, This->face_data_size * sizeof(*used_vertices));
+            used_vertices = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, mesh_builder->face_data_size * sizeof(*used_vertices));
             if (!used_vertices)
             {
                 IDirect3DRMMesh_Release(*mesh);
                 return E_OUTOFMEMORY;
             }
 
-            face_data = HeapAlloc(GetProcessHeap(), 0, This->face_data_size * sizeof(*face_data));
+            face_data = HeapAlloc(GetProcessHeap(), 0, mesh_builder->face_data_size * sizeof(*face_data));
             if (!face_data)
             {
                 HeapFree(GetProcessHeap(), 0, used_vertices);
@@ -1960,10 +2004,10 @@ static HRESULT WINAPI d3drm_mesh_builder3_CreateMesh(IDirect3DRMMeshBuilder3 *if
             out_ptr = face_data;
 
             /* If all faces have the same number of vertex, set vertex_per_face */
-            for (i = 0; i < This->nb_faces; i++)
+            for (i = 0; i < mesh_builder->nb_faces; i++)
             {
                 /* Process only faces belonging to the group */
-                if (This->material_indices[i] == k)
+                if (mesh_builder->material_indices[i] == k)
                 {
                     if (vertex_per_face && (vertex_per_face != *in_ptr))
                         break;
@@ -1971,17 +2015,17 @@ static HRESULT WINAPI d3drm_mesh_builder3_CreateMesh(IDirect3DRMMeshBuilder3 *if
                 }
                 in_ptr += 1 + *in_ptr * 2;
             }
-            if (i != This->nb_faces)
+            if (i != mesh_builder->nb_faces)
                 vertex_per_face = 0;
 
             /* Put only vertex indices */
-            in_ptr = This->pFaceData;
-            for (i = 0; i < This->nb_faces; i++)
+            in_ptr = mesh_builder->pFaceData;
+            for (i = 0; i < mesh_builder->nb_faces; i++)
             {
                 DWORD nb_indices = *in_ptr++;
 
                 /* Skip faces not belonging to the group */
-                if (This->material_indices[i] != k)
+                if (mesh_builder->material_indices[i] != k)
                 {
                     in_ptr += 2 * nb_indices;
                     continue;
@@ -2002,7 +2046,7 @@ static HRESULT WINAPI d3drm_mesh_builder3_CreateMesh(IDirect3DRMMeshBuilder3 *if
                 nb_faces++;
             }
 
-            for (i = 0; i < This->nb_vertices; i++)
+            for (i = 0; i < mesh_builder->nb_vertices; i++)
                 if (used_vertices[i])
                     nb_vertices++;
 
@@ -2010,15 +2054,15 @@ static HRESULT WINAPI d3drm_mesh_builder3_CreateMesh(IDirect3DRMMeshBuilder3 *if
             HeapFree(GetProcessHeap(), 0, used_vertices);
             HeapFree(GetProcessHeap(), 0, face_data);
             if (SUCCEEDED(hr))
-                hr = IDirect3DRMMesh_SetGroupColor(*mesh, group, This->materials[k].color);
+                hr = IDirect3DRMMesh_SetGroupColor(*mesh, group, mesh_builder->materials[k].color);
             if (SUCCEEDED(hr))
                 hr = IDirect3DRMMesh_SetGroupMaterial(*mesh, group,
-                        (IDirect3DRMMaterial *)This->materials[k].material);
-            if (SUCCEEDED(hr) && This->materials[k].texture)
+                        (IDirect3DRMMaterial *)mesh_builder->materials[k].material);
+            if (SUCCEEDED(hr) && mesh_builder->materials[k].texture)
             {
                 IDirect3DRMTexture *texture;
 
-                IDirect3DRMTexture3_QueryInterface(This->materials[k].texture,
+                IDirect3DRMTexture3_QueryInterface(mesh_builder->materials[k].texture,
                         &IID_IDirect3DRMTexture, (void **)&texture);
                 hr = IDirect3DRMMesh_SetGroupTexture(*mesh, group, texture);
                 IDirect3DRMTexture_Release(texture);
@@ -2177,7 +2221,7 @@ static HRESULT WINAPI d3drm_mesh_builder3_GetVertices(IDirect3DRMMeshBuilder3 *i
     if (vertex_count)
         *vertex_count = count;
     if (vertices && mesh_builder->nb_vertices)
-        memcpy(vertices, mesh_builder->pVertices + start_idx, count * sizeof(*vertices));
+        memcpy(vertices, mesh_builder->vertices + start_idx, count * sizeof(*vertices));
 
     return D3DRM_OK;
 }
@@ -2203,7 +2247,7 @@ static HRESULT WINAPI d3drm_mesh_builder3_GetNormals(IDirect3DRMMeshBuilder3 *if
     if (normal_count)
         *normal_count = count;
     if (normals && mesh_builder->nb_normals)
-        memcpy(normals, mesh_builder->pNormals + start_idx, count * sizeof(*normals));
+        memcpy(normals, &mesh_builder->normals[start_idx], count * sizeof(*normals));
 
     return D3DRM_OK;
 }
@@ -2291,11 +2335,12 @@ static const struct IDirect3DRMMeshBuilder3Vtbl d3drm_mesh_builder3_vtbl =
     d3drm_mesh_builder3_GetNormalCount,
 };
 
-HRESULT Direct3DRMMeshBuilder_create(REFIID riid, IUnknown **out)
+HRESULT d3drm_mesh_builder_create(struct d3drm_mesh_builder **mesh_builder, IDirect3DRM *d3drm)
 {
+    static const char classname[] = "Builder";
     struct d3drm_mesh_builder *object;
 
-    TRACE("riid %s, out %p.\n", debugstr_guid(riid), out);
+    TRACE("mesh_builder %p.\n", mesh_builder);
 
     if (!(object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*object))))
         return E_OUTOFMEMORY;
@@ -2303,11 +2348,12 @@ HRESULT Direct3DRMMeshBuilder_create(REFIID riid, IUnknown **out)
     object->IDirect3DRMMeshBuilder2_iface.lpVtbl = &d3drm_mesh_builder2_vtbl;
     object->IDirect3DRMMeshBuilder3_iface.lpVtbl = &d3drm_mesh_builder3_vtbl;
     object->ref = 1;
+    object->d3drm = d3drm;
+    IDirect3DRM_AddRef(object->d3drm);
 
-    if (IsEqualGUID(riid, &IID_IDirect3DRMMeshBuilder3))
-        *out = (IUnknown *)&object->IDirect3DRMMeshBuilder3_iface;
-    else
-        *out = (IUnknown *)&object->IDirect3DRMMeshBuilder2_iface;
+    d3drm_object_init(&object->obj, classname);
+
+    *mesh_builder = object;
 
     return S_OK;
 }
@@ -2317,6 +2363,8 @@ static HRESULT WINAPI d3drm_mesh_QueryInterface(IDirect3DRMMesh *iface, REFIID r
     TRACE("iface %p, riid %s, out %p.\n", iface, debugstr_guid(riid), out);
 
     if (IsEqualGUID(riid, &IID_IDirect3DRMMesh)
+            || IsEqualGUID(riid, &IID_IDirect3DRMVisual)
+            || IsEqualGUID(riid, &IID_IDirect3DRMObject)
             || IsEqualGUID(riid, &IID_IUnknown))
     {
         IDirect3DRMMesh_AddRef(iface);
@@ -2351,6 +2399,8 @@ static ULONG WINAPI d3drm_mesh_Release(IDirect3DRMMesh *iface)
     {
         DWORD i;
 
+        d3drm_object_cleanup((IDirect3DRMObject *)iface, &mesh->obj);
+        IDirect3DRM_Release(mesh->d3drm);
         for (i = 0; i < mesh->nb_groups; ++i)
         {
             HeapFree(GetProcessHeap(), 0, mesh->groups[i].vertices);
@@ -2378,58 +2428,68 @@ static HRESULT WINAPI d3drm_mesh_Clone(IDirect3DRMMesh *iface,
 static HRESULT WINAPI d3drm_mesh_AddDestroyCallback(IDirect3DRMMesh *iface,
         D3DRMOBJECTCALLBACK cb, void *ctx)
 {
-    FIXME("iface %p, cb %p, ctx %p stub!\n", iface, cb, ctx);
+    struct d3drm_mesh *mesh = impl_from_IDirect3DRMMesh(iface);
 
-    return E_NOTIMPL;
+    TRACE("iface %p, cb %p, ctx %p.\n", iface, cb, ctx);
+
+    return d3drm_object_add_destroy_callback(&mesh->obj, cb, ctx);
 }
 
 static HRESULT WINAPI d3drm_mesh_DeleteDestroyCallback(IDirect3DRMMesh *iface,
         D3DRMOBJECTCALLBACK cb, void *ctx)
 {
-    FIXME("iface %p, cb %p, ctx %p stub!\n", iface, cb, ctx);
+    struct d3drm_mesh *mesh = impl_from_IDirect3DRMMesh(iface);
 
-    return E_NOTIMPL;
+    TRACE("iface %p, cb %p, ctx %p.\n", iface, cb, ctx);
+
+    return d3drm_object_delete_destroy_callback(&mesh->obj, cb, ctx);
 }
 
 static HRESULT WINAPI d3drm_mesh_SetAppData(IDirect3DRMMesh *iface, DWORD data)
 {
-    FIXME("iface %p, data %#x stub!\n", iface, data);
+    struct d3drm_mesh *mesh = impl_from_IDirect3DRMMesh(iface);
 
-    return E_NOTIMPL;
+    TRACE("iface %p, data %#x.\n", iface, data);
+
+    mesh->obj.appdata = data;
+
+    return D3DRM_OK;
 }
 
 static DWORD WINAPI d3drm_mesh_GetAppData(IDirect3DRMMesh *iface)
 {
-    FIXME("iface %p stub!\n", iface);
+    struct d3drm_mesh *mesh = impl_from_IDirect3DRMMesh(iface);
 
-    return 0;
+    TRACE("iface %p.\n", iface);
+
+    return mesh->obj.appdata;
 }
 
 static HRESULT WINAPI d3drm_mesh_SetName(IDirect3DRMMesh *iface, const char *name)
 {
-    FIXME("iface %p, name %s stub!\n", iface, debugstr_a(name));
+    struct d3drm_mesh *mesh = impl_from_IDirect3DRMMesh(iface);
 
-    return E_NOTIMPL;
+    TRACE("iface %p, name %s.\n", iface, debugstr_a(name));
+
+    return d3drm_object_set_name(&mesh->obj, name);
 }
 
 static HRESULT WINAPI d3drm_mesh_GetName(IDirect3DRMMesh *iface, DWORD *size, char *name)
 {
-    FIXME("iface %p, size %p, name %p stub!\n", iface, size, name);
+    struct d3drm_mesh *mesh = impl_from_IDirect3DRMMesh(iface);
 
-    return E_NOTIMPL;
+    TRACE("iface %p, size %p, name %p.\n", iface, size, name);
+
+    return d3drm_object_get_name(&mesh->obj, size, name);
 }
 
 static HRESULT WINAPI d3drm_mesh_GetClassName(IDirect3DRMMesh *iface, DWORD *size, char *name)
 {
-    TRACE("iface %p, size %p, name %p.\n", iface, size, name);
-
-    if (!size || *size < strlen("Mesh") || !name)
-        return E_INVALIDARG;
+    struct d3drm_mesh *mesh = impl_from_IDirect3DRMMesh(iface);
 
-    strcpy(name, "Mesh");
-    *size = sizeof("Mesh");
+    TRACE("iface %p, size %p, name %p.\n", iface, size, name);
 
-    return D3DRM_OK;
+    return d3drm_object_get_class_name(&mesh->obj, size, name);
 }
 
 static HRESULT WINAPI d3drm_mesh_Scale(IDirect3DRMMesh *iface,
@@ -2467,28 +2527,8 @@ static HRESULT WINAPI d3drm_mesh_AddGroup(IDirect3DRMMesh *iface, unsigned verte
     if (!face_data || !id)
         return E_POINTER;
 
-    if ((mesh->nb_groups + 1) > mesh->groups_capacity)
-    {
-        struct mesh_group *groups;
-        ULONG new_capacity;
-
-        if (!mesh->groups_capacity)
-        {
-            new_capacity = 16;
-            groups = HeapAlloc(GetProcessHeap(), 0, new_capacity * sizeof(*groups));
-        }
-        else
-        {
-            new_capacity = mesh->groups_capacity * 2;
-            groups = HeapReAlloc(GetProcessHeap(), 0, mesh->groups, new_capacity * sizeof(*groups));
-        }
-
-        if (!groups)
-            return E_OUTOFMEMORY;
-
-        mesh->groups_capacity = new_capacity;
-        mesh->groups = groups;
-    }
+    if (!d3drm_array_reserve((void **)&mesh->groups, &mesh->groups_size, mesh->nb_groups + 1, sizeof(*mesh->groups)))
+        return E_OUTOFMEMORY;
 
     group = mesh->groups + mesh->nb_groups;
 
@@ -2797,19 +2837,208 @@ static const struct IDirect3DRMMeshVtbl d3drm_mesh_vtbl =
     d3drm_mesh_GetGroupTexture,
 };
 
-HRESULT Direct3DRMMesh_create(IDirect3DRMMesh **mesh)
+HRESULT d3drm_mesh_create(struct d3drm_mesh **mesh, IDirect3DRM *d3drm)
 {
+    static const char classname[] = "Mesh";
     struct d3drm_mesh *object;
 
-    TRACE("mesh %p.\n", mesh);
+    TRACE("mesh %p, d3drm %p.\n", mesh, d3drm);
 
     if (!(object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*object))))
         return E_OUTOFMEMORY;
 
     object->IDirect3DRMMesh_iface.lpVtbl = &d3drm_mesh_vtbl;
     object->ref = 1;
+    object->d3drm = d3drm;
+    IDirect3DRM_AddRef(object->d3drm);
+
+    d3drm_object_init(&object->obj, classname);
+
+    *mesh = object;
+
+    return S_OK;
+}
+
+static HRESULT WINAPI d3drm_wrap_QueryInterface(IDirect3DRMWrap *iface, REFIID riid, void **out)
+{
+    TRACE("iface %p, riid %s, out %p.\n", iface, debugstr_guid(riid), out);
+
+    if (IsEqualGUID(riid, &IID_IDirect3DRMWrap)
+            || IsEqualGUID(riid, &IID_IDirect3DRMObject)
+            || IsEqualGUID(riid, &IID_IUnknown))
+    {
+        IDirect3DRMWrap_AddRef(iface);
+        *out = iface;
+        return S_OK;
+    }
+
+    WARN("%s not implemented.\n", debugstr_guid(riid));
+
+    *out = NULL;
+    return CLASS_E_CLASSNOTAVAILABLE;
+}
+
+static ULONG WINAPI d3drm_wrap_AddRef(IDirect3DRMWrap *iface)
+{
+    struct d3drm_wrap *wrap = impl_from_IDirect3DRMWrap(iface);
+    ULONG refcount = InterlockedIncrement(&wrap->ref);
+
+    TRACE("%p increasing refcount to %u.\n", iface, refcount);
+
+    return refcount;
+}
+
+static ULONG WINAPI d3drm_wrap_Release(IDirect3DRMWrap *iface)
+{
+    struct d3drm_wrap *wrap = impl_from_IDirect3DRMWrap(iface);
+    ULONG refcount = InterlockedDecrement(&wrap->ref);
+
+    TRACE("%p decreasing refcount to %u.\n", iface, refcount);
+
+    if (!refcount)
+    {
+        d3drm_object_cleanup((IDirect3DRMObject *)iface, &wrap->obj);
+        HeapFree(GetProcessHeap(), 0, wrap);
+    }
+
+    return refcount;
+}
+
+static HRESULT WINAPI d3drm_wrap_Clone(IDirect3DRMWrap *iface,
+        IUnknown *outer, REFIID iid, void **out)
+{
+    FIXME("iface %p, outer %p, iid %s, out %p stub!\n", iface, outer, debugstr_guid(iid), out);
+
+    return E_NOTIMPL;
+}
+
+static HRESULT WINAPI d3drm_wrap_AddDestroyCallback(IDirect3DRMWrap *iface,
+        D3DRMOBJECTCALLBACK cb, void *ctx)
+{
+    struct d3drm_wrap *wrap = impl_from_IDirect3DRMWrap(iface);
+
+    TRACE("iface %p, cb %p, ctx %p.\n", iface, cb, ctx);
+
+    return d3drm_object_add_destroy_callback(&wrap->obj, cb, ctx);
+}
+
+static HRESULT WINAPI d3drm_wrap_DeleteDestroyCallback(IDirect3DRMWrap *iface,
+        D3DRMOBJECTCALLBACK cb, void *ctx)
+{
+    struct d3drm_wrap *wrap = impl_from_IDirect3DRMWrap(iface);
+
+    TRACE("iface %p, cb %p, ctx %p.\n", iface, cb, ctx);
+
+    return d3drm_object_delete_destroy_callback(&wrap->obj, cb, ctx);
+}
+
+static HRESULT WINAPI d3drm_wrap_SetAppData(IDirect3DRMWrap *iface, DWORD data)
+{
+    struct d3drm_wrap *wrap = impl_from_IDirect3DRMWrap(iface);
+
+    TRACE("iface %p, data %#x.\n", iface, data);
+
+    wrap->obj.appdata = data;
+
+    return D3DRM_OK;
+}
+
+static DWORD WINAPI d3drm_wrap_GetAppData(IDirect3DRMWrap *iface)
+{
+    struct d3drm_wrap *wrap = impl_from_IDirect3DRMWrap(iface);
+
+    TRACE("iface %p.\n", iface);
+
+    return wrap->obj.appdata;
+}
+
+static HRESULT WINAPI d3drm_wrap_SetName(IDirect3DRMWrap *iface, const char *name)
+{
+    struct d3drm_wrap *wrap = impl_from_IDirect3DRMWrap(iface);
+
+    TRACE("iface %p, name %s.\n", iface, debugstr_a(name));
+
+    return d3drm_object_set_name(&wrap->obj, name);
+}
+
+static HRESULT WINAPI d3drm_wrap_GetName(IDirect3DRMWrap *iface, DWORD *size, char *name)
+{
+    struct d3drm_wrap *wrap = impl_from_IDirect3DRMWrap(iface);
+
+    TRACE("iface %p, size %p, name %p.\n", iface, size, name);
+
+    return d3drm_object_get_name(&wrap->obj, size, name);
+}
+
+static HRESULT WINAPI d3drm_wrap_GetClassName(IDirect3DRMWrap *iface, DWORD *size, char *name)
+{
+    struct d3drm_wrap *wrap = impl_from_IDirect3DRMWrap(iface);
+
+    TRACE("iface %p, size %p, name %p.\n", iface, size, name);
+
+    return d3drm_object_get_class_name(&wrap->obj, size, name);
+}
+
+static HRESULT WINAPI d3drm_wrap_Init(IDirect3DRMWrap *iface, D3DRMWRAPTYPE type, IDirect3DRMFrame *reference,
+       D3DVALUE ox, D3DVALUE oy, D3DVALUE oz, D3DVALUE dx, D3DVALUE dy, D3DVALUE dz, D3DVALUE ux,
+       D3DVALUE uy, D3DVALUE uz, D3DVALUE ou, D3DVALUE ov, D3DVALUE su, D3DVALUE sv)
+{
+    FIXME("iface %p, type %d, reference frame %p, ox %.8e, oy %.8e, oz %.8e, dx %.8e, dy %.8e, dz %.8e, ux %.8e, "
+            "uy %.8e, uz %.8e, ou %.8e, ov %.8e, su %.8e, sv %.8e.\n", iface, type, reference, ox, oy, oz, dx, dy, dz,
+            ux, uy, uz, ou, ov, su, sv);
+
+    return E_NOTIMPL;
+}
+
+static HRESULT WINAPI d3drm_wrap_Apply(IDirect3DRMWrap *iface, IDirect3DRMObject *object)
+{
+    FIXME("iface %p, object %p.\n", iface, object);
+
+    return E_NOTIMPL;
+}
+
+static HRESULT WINAPI d3drm_wrap_ApplyRelative(IDirect3DRMWrap *iface, IDirect3DRMFrame *frame,
+       IDirect3DRMObject *object)
+{
+    FIXME("iface %p, frame %p, object %p.\n", iface, frame, object);
+
+    return E_NOTIMPL;
+}
+
+static const struct IDirect3DRMWrapVtbl d3drm_wrap_vtbl =
+{
+    d3drm_wrap_QueryInterface,
+    d3drm_wrap_AddRef,
+    d3drm_wrap_Release,
+    d3drm_wrap_Clone,
+    d3drm_wrap_AddDestroyCallback,
+    d3drm_wrap_DeleteDestroyCallback,
+    d3drm_wrap_SetAppData,
+    d3drm_wrap_GetAppData,
+    d3drm_wrap_SetName,
+    d3drm_wrap_GetName,
+    d3drm_wrap_GetClassName,
+    d3drm_wrap_Init,
+    d3drm_wrap_Apply,
+    d3drm_wrap_ApplyRelative,
+};
+
+HRESULT d3drm_wrap_create(struct d3drm_wrap **wrap, IDirect3DRM *d3drm)
+{
+    static const char classname[] = "";
+    struct d3drm_wrap *object;
+
+    TRACE("wrap %p, d3drm %p.\n", wrap, d3drm);
+
+    if (!(object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*object))))
+        return E_OUTOFMEMORY;
+
+    object->IDirect3DRMWrap_iface.lpVtbl = &d3drm_wrap_vtbl;
+    object->ref = 1;
+
+    d3drm_object_init(&object->obj, classname);
 
-    *mesh = &object->IDirect3DRMMesh_iface;
+    *wrap = object;
 
     return S_OK;
 }
index 27c6944..8631320 100644 (file)
@@ -40,8 +40,10 @@ static void d3drm_texture_destroy(struct d3drm_texture *texture)
     TRACE("texture %p is being destroyed.\n", texture);
 
     d3drm_object_cleanup((IDirect3DRMObject*)&texture->IDirect3DRMTexture_iface, &texture->obj);
-    if (texture->image)
+    if (texture->image || texture->surface)
         IDirect3DRM_Release(texture->d3drm);
+    if (texture->surface)
+        IDirectDrawSurface_Release(texture->surface);
     HeapFree(GetProcessHeap(), 0, texture);
 }
 
@@ -172,9 +174,11 @@ static HRESULT WINAPI d3drm_texture1_InitFromFile(IDirect3DRMTexture *iface, con
 static HRESULT WINAPI d3drm_texture1_InitFromSurface(IDirect3DRMTexture *iface,
         IDirectDrawSurface *surface)
 {
-    FIXME("iface %p, surface %p stub!\n", iface, surface);
+    struct d3drm_texture *texture = impl_from_IDirect3DRMTexture(iface);
 
-    return E_NOTIMPL;
+    TRACE("iface %p, surface %p.\n", iface, surface);
+
+    return IDirect3DRMTexture3_InitFromSurface(&texture->IDirect3DRMTexture3_iface, surface);
 }
 
 static HRESULT WINAPI d3drm_texture1_InitFromResource(IDirect3DRMTexture *iface, HRSRC resource)
@@ -472,9 +476,11 @@ static HRESULT WINAPI d3drm_texture2_InitFromFile(IDirect3DRMTexture2 *iface, co
 static HRESULT WINAPI d3drm_texture2_InitFromSurface(IDirect3DRMTexture2 *iface,
         IDirectDrawSurface *surface)
 {
-    FIXME("iface %p, surface %p stub!\n", iface, surface);
+    struct d3drm_texture *texture = impl_from_IDirect3DRMTexture2(iface);
 
-    return E_NOTIMPL;
+    TRACE("iface %p, surface %p.\n", iface, surface);
+
+    return IDirect3DRMTexture3_InitFromSurface(&texture->IDirect3DRMTexture3_iface, surface);
 }
 
 static HRESULT WINAPI d3drm_texture2_InitFromResource(IDirect3DRMTexture2 *iface, HRSRC resource)
@@ -795,29 +801,29 @@ static DWORD WINAPI d3drm_texture3_GetAppData(IDirect3DRMTexture3 *iface)
 
 static HRESULT WINAPI d3drm_texture3_SetName(IDirect3DRMTexture3 *iface, const char *name)
 {
-    FIXME("iface %p, name %s stub!\n", iface, debugstr_a(name));
+    struct d3drm_texture *texture = impl_from_IDirect3DRMTexture3(iface);
 
-    return E_NOTIMPL;
+    TRACE("iface %p, name %s.\n", iface, debugstr_a(name));
+
+    return d3drm_object_set_name(&texture->obj, name);
 }
 
 static HRESULT WINAPI d3drm_texture3_GetName(IDirect3DRMTexture3 *iface, DWORD *size, char *name)
 {
-    FIXME("iface %p, size %p, name %p stub!\n", iface, size, name);
+    struct d3drm_texture *texture = impl_from_IDirect3DRMTexture3(iface);
 
-    return E_NOTIMPL;
+    TRACE("iface %p, size %p, name %p.\n", iface, size, name);
+
+    return d3drm_object_get_name(&texture->obj, size, name);
 }
 
 static HRESULT WINAPI d3drm_texture3_GetClassName(IDirect3DRMTexture3 *iface, DWORD *size, char *name)
 {
-    TRACE("iface %p, size %p, name %p.\n", iface, size, name);
-
-    if (!size || *size < sizeof("Texture") || !name)
-        return E_INVALIDARG;
+    struct d3drm_texture *texture = impl_from_IDirect3DRMTexture3(iface);
 
-    strcpy(name, "Texture");
-    *size = sizeof("Texture");
+    TRACE("iface %p, size %p, name %p.\n", iface, size, name);
 
-    return D3DRM_OK;
+    return d3drm_object_get_class_name(&texture->obj, size, name);
 }
 
 static HRESULT WINAPI d3drm_texture3_InitFromFile(IDirect3DRMTexture3 *iface, const char *filename)
@@ -830,9 +836,22 @@ static HRESULT WINAPI d3drm_texture3_InitFromFile(IDirect3DRMTexture3 *iface, co
 static HRESULT WINAPI d3drm_texture3_InitFromSurface(IDirect3DRMTexture3 *iface,
         IDirectDrawSurface *surface)
 {
-    FIXME("iface %p, surface %p stub!\n", iface, surface);
+    struct d3drm_texture *texture = impl_from_IDirect3DRMTexture3(iface);
 
-    return E_NOTIMPL;
+    TRACE("iface %p, surface %p.\n", iface, surface);
+
+    if (!surface)
+        return D3DRMERR_BADOBJECT;
+
+    /* d3drm intentionally leaks a reference to IDirect3DRM here if texture has already been initialized. */
+    IDirect3DRM_AddRef(texture->d3drm);
+
+    if (texture->image || texture->surface)
+        return D3DRMERR_BADOBJECT;
+
+    texture->surface = surface;
+    IDirectDrawSurface_AddRef(texture->surface);
+    return D3DRM_OK;
 }
 
 static HRESULT WINAPI d3drm_texture3_InitFromResource(IDirect3DRMTexture3 *iface, HRSRC resource)
@@ -969,7 +988,7 @@ static HRESULT WINAPI d3drm_texture3_InitFromImage(IDirect3DRMTexture3 *iface, D
     /* d3drm intentionally leaks a reference to IDirect3DRM here if texture has already been initialized. */
     IDirect3DRM_AddRef(texture->d3drm);
 
-    if (texture->image)
+    if (texture->image || texture->surface)
         return D3DRMERR_BADOBJECT;
 
     texture->image = image;
@@ -996,9 +1015,23 @@ static HRESULT WINAPI d3drm_texture3_GenerateMIPMap(IDirect3DRMTexture3 *iface,
 static HRESULT WINAPI d3drm_texture3_GetSurface(IDirect3DRMTexture3 *iface,
         DWORD flags, IDirectDrawSurface **surface)
 {
-    FIXME("iface %p, flags %#x, surface %p stub!\n", iface, flags, surface);
+    struct d3drm_texture *texture = impl_from_IDirect3DRMTexture3(iface);
 
-    return E_NOTIMPL;
+    TRACE("iface %p, flags %#x, surface %p.\n", iface, flags, surface);
+
+    if (flags)
+        FIXME("unexpected flags %#x.\n", flags);
+
+    if (!surface)
+        return D3DRMERR_BADVALUE;
+
+    if (texture->image)
+        return D3DRMERR_NOTCREATEDFROMDDS;
+
+    *surface = texture->surface;
+    IDirectDrawSurface_AddRef(*surface);
+
+    return D3DRM_OK;
 }
 
 static HRESULT WINAPI d3drm_texture3_SetCacheOptions(IDirect3DRMTexture3 *iface, LONG importance, DWORD flags)
@@ -1076,6 +1109,7 @@ static const struct IDirect3DRMTexture3Vtbl d3drm_texture3_vtbl =
 
 HRESULT d3drm_texture_create(struct d3drm_texture **texture, IDirect3DRM *d3drm)
 {
+    static const char classname[] = "Texture";
     struct d3drm_texture *object;
 
     TRACE("texture %p.\n", texture);
@@ -1088,7 +1122,7 @@ HRESULT d3drm_texture_create(struct d3drm_texture **texture, IDirect3DRM *d3drm)
     object->IDirect3DRMTexture3_iface.lpVtbl = &d3drm_texture3_vtbl;
     object->d3drm = d3drm;
 
-    d3drm_object_init(&object->obj);
+    d3drm_object_init(&object->obj, classname);
 
     *texture = object;
 
index 8a0a080..247e077 100644 (file)
@@ -245,43 +245,47 @@ static DWORD WINAPI d3drm_viewport1_GetAppData(IDirect3DRMViewport *iface)
 
 static HRESULT WINAPI d3drm_viewport2_SetName(IDirect3DRMViewport2 *iface, const char *name)
 {
-    FIXME("iface %p, name %s stub!\n", iface, debugstr_a(name));
+    struct d3drm_viewport *viewport = impl_from_IDirect3DRMViewport2(iface);
 
-    return E_NOTIMPL;
+    TRACE("iface %p, name %s.\n", iface, debugstr_a(name));
+
+    return d3drm_object_set_name(&viewport->obj, name);
 }
 
 static HRESULT WINAPI d3drm_viewport1_SetName(IDirect3DRMViewport *iface, const char *name)
 {
-    FIXME("iface %p, name %s stub!\n", iface, debugstr_a(name));
+    struct d3drm_viewport *viewport = impl_from_IDirect3DRMViewport(iface);
 
-    return E_NOTIMPL;
+    TRACE("iface %p, name %s.\n", iface, debugstr_a(name));
+
+    return d3drm_viewport2_SetName(&viewport->IDirect3DRMViewport2_iface, name);
 }
 
 static HRESULT WINAPI d3drm_viewport2_GetName(IDirect3DRMViewport2 *iface, DWORD *size, char *name)
 {
-    FIXME("iface %p, size %p, name %p stub!\n", iface, size, name);
+    struct d3drm_viewport *viewport = impl_from_IDirect3DRMViewport2(iface);
 
-    return E_NOTIMPL;
+    TRACE("iface %p, size %p, name %p.\n", iface, size, name);
+
+    return d3drm_object_get_name(&viewport->obj, size, name);
 }
 
 static HRESULT WINAPI d3drm_viewport1_GetName(IDirect3DRMViewport *iface, DWORD *size, char *name)
 {
-    FIXME("iface %p, size %p, name %p stub!\n", iface, size, name);
+    struct d3drm_viewport *viewport = impl_from_IDirect3DRMViewport(iface);
 
-    return E_NOTIMPL;
+    TRACE("iface %p, size %p, name %p.\n", iface, size, name);
+
+    return d3drm_viewport2_GetName(&viewport->IDirect3DRMViewport2_iface, size, name);
 }
 
 static HRESULT WINAPI d3drm_viewport2_GetClassName(IDirect3DRMViewport2 *iface, DWORD *size, char *name)
 {
-    TRACE("iface %p, size %p, name %p.\n", iface, size, name);
-
-    if (!size || *size < strlen("Viewport") || !name)
-        return E_INVALIDARG;
+    struct d3drm_viewport *viewport = impl_from_IDirect3DRMViewport2(iface);
 
-    strcpy(name, "Viewport");
-    *size = sizeof("Viewport");
+    TRACE("iface %p, size %p, name %p.\n", iface, size, name);
 
-    return D3DRM_OK;
+    return d3drm_object_get_class_name(&viewport->obj, size, name);
 }
 
 static HRESULT WINAPI d3drm_viewport1_GetClassName(IDirect3DRMViewport *iface, DWORD *size, char *name)
@@ -1008,6 +1012,7 @@ static const struct IDirect3DRMViewportVtbl d3drm_viewport1_vtbl =
 
 HRESULT d3drm_viewport_create(struct d3drm_viewport **viewport, IDirect3DRM *d3drm)
 {
+    static const char classname[] = "Viewport";
     struct d3drm_viewport *object;
 
     TRACE("viewport %p, d3drm %p.\n", viewport, d3drm);
@@ -1018,7 +1023,7 @@ HRESULT d3drm_viewport_create(struct d3drm_viewport **viewport, IDirect3DRM *d3d
     object->IDirect3DRMViewport_iface.lpVtbl = &d3drm_viewport1_vtbl;
     object->IDirect3DRMViewport2_iface.lpVtbl = &d3drm_viewport2_vtbl;
     object->d3drm = d3drm;
-    d3drm_object_init(&object->obj);
+    d3drm_object_init(&object->obj, classname);
 
     *viewport = object;