[PATCH 6/7] d3drm: Implement IDirect3DRMViewport*::Init.

Aaryaman Vasishta jem456.vasishta at gmail.com
Fri Jun 24 16:49:32 CDT 2016


Signed-off-by: Aaryaman Vasishta <jem456.vasishta at gmail.com>
---
 dlls/d3drm/d3drm.c         |  16 +++-
 dlls/d3drm/d3drm_private.h |   2 +
 dlls/d3drm/tests/d3drm.c   | 179 +++++++++++++++++++++++++++++++++++++++++----
 dlls/d3drm/viewport.c      | 128 ++++++++++++++++++++++++++++++--
 4 files changed, 303 insertions(+), 22 deletions(-)

diff --git a/dlls/d3drm/d3drm.c b/dlls/d3drm/d3drm.c
index 7833d81..001ace4 100644
--- a/dlls/d3drm/d3drm.c
+++ b/dlls/d3drm/d3drm.c
@@ -64,6 +64,19 @@ static HRESULT d3drm_create_texture_object(void **object, IDirect3DRM *d3drm)
     return hr;
 }
 
+static HRESULT d3drm_create_viewport_object(void **object, IDirect3DRM *d3drm)
+{
+    struct d3drm_viewport *viewport;
+    HRESULT hr;
+
+    if (FAILED(hr = d3drm_viewport_create(&viewport, d3drm)))
+        return hr;
+
+    *object = &viewport->IDirect3DRMViewport_iface;
+
+    return hr;
+}
+
 struct d3drm
 {
     IDirect3DRM IDirect3DRM_iface;
@@ -1128,7 +1141,8 @@ static HRESULT WINAPI d3drm3_CreateObject(IDirect3DRM3 *iface,
     }
     object_table[] =
     {
-        { &CLSID_CDirect3DRMTexture, d3drm_create_texture_object },
+        { &CLSID_CDirect3DRMTexture,  d3drm_create_texture_object  },
+        { &CLSID_CDirect3DRMViewport, d3drm_create_viewport_object },
     };
     int num_entries = sizeof(object_table) / sizeof(*object_table);
 
diff --git a/dlls/d3drm/d3drm_private.h b/dlls/d3drm/d3drm_private.h
index 06cbdc1..8f15706 100644
--- a/dlls/d3drm/d3drm_private.h
+++ b/dlls/d3drm/d3drm_private.h
@@ -68,8 +68,10 @@ struct d3drm_frame
 struct d3drm_viewport
 {
     struct d3drm_object obj;
+    IDirect3DRMFrame *camera;
     IDirect3DRMViewport IDirect3DRMViewport_iface;
     IDirect3DRMViewport2 IDirect3DRMViewport2_iface;
+    IDirect3DViewport *d3d_viewport;
     IDirect3DRM *d3drm;
     D3DVALUE back;
     D3DVALUE front;
diff --git a/dlls/d3drm/tests/d3drm.c b/dlls/d3drm/tests/d3drm.c
index 4321bc9..3d7b389 100644
--- a/dlls/d3drm/tests/d3drm.c
+++ b/dlls/d3drm/tests/d3drm.c
@@ -1364,8 +1364,8 @@ static void test_object(void)
         { &CLSID_CDirect3DRMTexture,       &IID_IDirect3DRMTexture,      FALSE },
         { &CLSID_CDirect3DRMTexture,       &IID_IDirect3DRMTexture2,     FALSE },
         { &CLSID_CDirect3DRMTexture,       &IID_IDirect3DRMTexture3,     FALSE },
-        { &CLSID_CDirect3DRMViewport,      &IID_IDirect3DRMViewport,     TRUE  },
-        { &CLSID_CDirect3DRMViewport,      &IID_IDirect3DRMViewport2,    TRUE  },
+        { &CLSID_CDirect3DRMViewport,      &IID_IDirect3DRMViewport,     FALSE },
+        { &CLSID_CDirect3DRMViewport,      &IID_IDirect3DRMViewport2,    FALSE },
     };
     IDirect3DRM *d3drm1;
     IDirect3DRM2 *d3drm2;
@@ -1463,40 +1463,56 @@ static void test_object(void)
 
 static void test_Viewport(void)
 {
-    IDirectDrawClipper *pClipper;
+    IDirectDrawClipper *clipper;
     HRESULT hr;
-    IDirect3DRM *d3drm;
-    IDirect3DRMDevice *device;
+    IDirect3DRM *d3drm1;
+    IDirect3DRM2 *d3drm2;
+    IDirect3DRM3 *d3drm3;
+    IDirect3DRMDevice *device1;
+    IDirect3DRMDevice3 *device3;
     IDirect3DRMFrame *frame;
+    IDirect3DRMFrame3 *frame3;
     IDirect3DRMViewport *viewport;
     IDirect3DRMViewport2 *viewport2;
     IDirect3DRMObject *obj, *obj2;
     GUID driver;
     HWND window;
     RECT rc;
-    DWORD size, data;
+    DWORD size, data, ref1, ref2, ref3, ref4;
+    DWORD initial_ref1, initial_ref2, initial_ref3, device_ref, frame_ref, frame_ref2;
     CHAR cname[64] = {0};
 
     window = CreateWindowA("static", "d3drm_test", WS_OVERLAPPEDWINDOW, 0, 0, 300, 200, 0, 0, 0, 0);
     GetClientRect(window, &rc);
 
-    hr = Direct3DRMCreate(&d3drm);
+    hr = Direct3DRMCreate(&d3drm1);
     ok(hr == D3DRM_OK, "Cannot get IDirect3DRM interface (hr = %x)\n", hr);
+    hr = IDirect3DRM_QueryInterface(d3drm1, &IID_IDirect3DRM2, (void **)&d3drm2);
+    ok(SUCCEEDED(hr), "Cannot get IDirect3DRM2 interface (hr = %#x).\n", hr);
+    hr = IDirect3DRM_QueryInterface(d3drm1, &IID_IDirect3DRM3, (void **)&d3drm3);
+    ok(SUCCEEDED(hr), "Cannot get IDirect3DRM3 interface (hr = %#x).\n", hr);
+    initial_ref1 = get_refcount((IUnknown *)d3drm1);
+    initial_ref2 = get_refcount((IUnknown *)d3drm2);
+    initial_ref3 = get_refcount((IUnknown *)d3drm3);
 
-    hr = DirectDrawCreateClipper(0, &pClipper, NULL);
+    hr = DirectDrawCreateClipper(0, &clipper, NULL);
     ok(hr == DD_OK, "Cannot get IDirectDrawClipper interface (hr = %x)\n", hr);
 
-    hr = IDirectDrawClipper_SetHWnd(pClipper, 0, window);
+    hr = IDirectDrawClipper_SetHWnd(clipper, 0, window);
     ok(hr == DD_OK, "Cannot set HWnd to Clipper (hr = %x)\n", hr);
 
     memcpy(&driver, &IID_IDirect3DRGBDevice, sizeof(GUID));
-    hr = IDirect3DRM3_CreateDeviceFromClipper(d3drm, pClipper, &driver, rc.right, rc.bottom, &device);
+    hr = IDirect3DRM3_CreateDeviceFromClipper(d3drm3, clipper, &driver, rc.right, rc.bottom, &device3);
     ok(hr == D3DRM_OK, "Cannot get IDirect3DRMDevice interface (hr = %x)\n", hr);
+    hr = IDirect3DRMDevice3_QueryInterface(device3, &IID_IDirect3DRMDevice, (void **)&device1);
+    ok(SUCCEEDED(hr), "Cannot get IDirect3DRMDevice interface (hr = %#x).\n", hr);
 
-    hr = IDirect3DRM_CreateFrame(d3drm, NULL, &frame);
+    hr = IDirect3DRM_CreateFrame(d3drm1, NULL, &frame);
     ok(hr == D3DRM_OK, "Cannot get IDirect3DRMFrame interface (hr = %x)\n", hr);
+    hr = IDirect3DRM3_CreateFrame(d3drm3, NULL, &frame3);
+    ok(SUCCEEDED(hr), "Cannot get IDirect3DRMFrame3 interface (hr = %x).\n", hr);
 
-    hr = IDirect3DRM_CreateViewport(d3drm, device, frame, rc.left, rc.top, rc.right, rc.bottom, &viewport);
+    hr = IDirect3DRM_CreateViewport(d3drm1, device1, frame, rc.left, rc.top, rc.right, rc.bottom, &viewport);
     ok(hr == D3DRM_OK, "Cannot get IDirect3DRMViewport interface (hr = %x)\n", hr);
 
     hr = IDirect3DRMViewport_QueryInterface(viewport, &IID_IDirect3DRMObject, (void**)&obj);
@@ -1547,12 +1563,145 @@ static void test_Viewport(void)
     data = IDirect3DRMViewport2_GetAppData(viewport2);
     ok(data == 1, "got %x\n", data);
     IDirect3DRMViewport2_Release(viewport2);
+    IDirect3DRMViewport_Release(viewport);
+
+    /* IDirect3DRMViewport*::Init tests */
+    ref1 = get_refcount((IUnknown *)d3drm1);
+    ref2 = get_refcount((IUnknown *)d3drm2);
+    ref3 = get_refcount((IUnknown *)d3drm3);
+    hr = IDirect3DRM_CreateObject(d3drm1, &CLSID_CDirect3DRMViewport, NULL, &IID_IDirect3DRMViewport,
+            (void **)&viewport);
+    ok(SUCCEEDED(hr), "Cannot get IDirect3DRMViewport interface (hr = %#x).\n", hr);
+    ref4 = get_refcount((IUnknown *)d3drm1);
+    ok(ref4 == ref1, "Expected ref4 == ref1, got ref1 = %u, ref4 = %u.\n", ref1, ref4);
+    ref4 = get_refcount((IUnknown *)d3drm2);
+    ok(ref4 == ref2, "Expected ref4 == ref2, got ref2 = %u, ref4 = %u.\n", ref2, ref4);
+    ref4 = get_refcount((IUnknown *)d3drm3);
+    ok(ref4 == ref3, "Expected ref4 == ref3, got ref3 = %u, ref4 = %u.\n", ref3, ref4);
+
+    /* Test all failures together */
+    hr = IDirect3DRMViewport_Init(viewport, NULL, frame, rc.left, rc.top, rc.right, rc.bottom);
+    ok(hr == D3DRMERR_BADOBJECT, "Expected hr == D3DRMERR_BADOBJECT, got %#x.\n", hr);
+    hr = IDirect3DRMViewport_Init(viewport, device1, NULL, rc.left, rc.top, rc.right, rc.bottom);
+    ok(hr == D3DRMERR_BADOBJECT, "Expected hr == D3DRMERR_BADOBJECT, got %#x.\n", hr);
+    hr = IDirect3DRMViewport_Init(viewport, device1, frame, rc.left, rc.top, rc.right + 1, rc.bottom + 1);
+    ok(hr == D3DRMERR_BADOBJECT, "Expected hr == D3DRMERR_BADOBJECT, got %#x.\n", hr);
+    hr = IDirect3DRMViewport_Init(viewport, device1, frame, rc.left, rc.top, rc.right + 1, rc.bottom);
+    ok(hr == D3DRMERR_BADOBJECT, "Expected hr == D3DRMERR_BADOBJECT, got %#x.\n", hr);
+    hr = IDirect3DRMViewport_Init(viewport, device1, frame, rc.left, rc.top, rc.right + 1, rc.bottom + 1);
+    ok(hr == D3DRMERR_BADOBJECT, "Expected hr == D3DRMERR_BADOBJECT, got %#x.\n", hr);
+
+    device_ref = get_refcount((IUnknown *)device1);
+    frame_ref = get_refcount((IUnknown *)frame);
+    hr = IDirect3DRMViewport_Init(viewport, device1, frame, rc.left, rc.top, rc.right, rc.bottom);
+    ok(SUCCEEDED(hr), "Cannot initialize IDirect3DRMViewport interface (hr = %#x).\n", hr);
+    ref4 = get_refcount((IUnknown *)d3drm1);
+    ok(ref4 > ref1, "Expected ref4 > ref1, got ref1 = %u, ref4 = %u.\n", ref1, ref4);
+    ref4 = get_refcount((IUnknown *)d3drm2);
+    ok(ref4 == ref2, "Expected ref4 == ref2, got ref2 = %u, ref4 = %u.\n", ref2, ref4);
+    ref4 = get_refcount((IUnknown *)d3drm3);
+    ok(ref4 == ref3, "Expected ref4 == ref3, got ref3 = %u, ref4 = %u.\n", ref3, ref4);
+    ref4 = get_refcount((IUnknown *)device1);
+    ok(ref4 == device_ref, "Expected ref4 == device_ref, got device_ref = %u, ref4 = %u.\n", device_ref, ref4);
+    ref4 = get_refcount((IUnknown *)frame);
+    ok(ref4 > frame_ref, "Expected ref4 > frame_ref, got frame_ref = %u, ref4 = %u.\n", frame_ref, ref4);
+
+    hr = IDirect3DRMViewport_Init(viewport, device1, frame, rc.left, rc.top, rc.right, rc.bottom);
+    ok(hr == D3DRMERR_BADOBJECT, "Expected hr == D3DRMERR_BADOBJECT, got %#x.\n", hr);
+
+    IDirect3DRMViewport_Release(viewport);
+    ref4 = get_refcount((IUnknown *)d3drm1);
+    todo_wine ok(ref4 > ref1, "Expected ref4 > ref1, got ref1 = %u, ref4 = %u.\n", ref1, ref4);
+    ref4 = get_refcount((IUnknown *)d3drm2);
+    ok(ref4 == ref2, "Expected ref4 == ref2, got ref2 = %u, ref4 = %u.\n", ref2, ref4);
+    ref4 = get_refcount((IUnknown *)d3drm3);
+    ok(ref4 == ref3, "Expected ref4 == ref3, got ref3 = %u, ref4 = %u.\n", ref3, ref4);
+    ref4 = get_refcount((IUnknown *)device1);
+    ok(ref4 == device_ref, "Expected ref4 == device_ref, got device_ref = %u, ref4 = %u.\n", device_ref, ref4);
+    ref4 = get_refcount((IUnknown *)frame);
+    todo_wine ok(ref4 > frame_ref, "Expected ref4 > frame_ref, got frame_ref = %u, ref4 = %u.\n", frame_ref, ref4);
+
+    ref1 = get_refcount((IUnknown *)d3drm1);
+    ref2 = get_refcount((IUnknown *)d3drm2);
+    ref3 = get_refcount((IUnknown *)d3drm3);
+    hr = IDirect3DRM3_CreateObject(d3drm2, &CLSID_CDirect3DRMViewport, NULL, &IID_IDirect3DRMViewport2,
+            (void **)&viewport2);
+    ok(SUCCEEDED(hr), "Cannot get IDirect3DRMViewport2 interface (hr = %#x).\n", hr);
+    ref4 = get_refcount((IUnknown *)d3drm1);
+    ok(ref4 == ref1, "Expected ref4 == ref1, got ref1 = %u, ref4 = %u.\n", ref1, ref4);
+    ref4 = get_refcount((IUnknown *)d3drm2);
+    ok(ref4 == ref2, "Expected ref4 == ref2, got ref2 = %u, ref4 = %u.\n", ref2, ref4);
+    ref4 = get_refcount((IUnknown *)d3drm3);
+    ok(ref4 == ref3, "Expected ref4 == ref3, got ref3 = %u, ref4 = %u.\n", ref3, ref4);
+
+    hr = IDirect3DRMViewport2_Init(viewport2, NULL, frame3, rc.left, rc.top, rc.right, rc.bottom);
+    ok(hr == D3DRMERR_BADOBJECT, "Expected hr == D3DRMERR_BADOBJECT, got %#x.\n", hr);
+    hr = IDirect3DRMViewport2_Init(viewport2, device3, NULL, rc.left, rc.top, rc.right, rc.bottom);
+    ok(hr == D3DRMERR_BADOBJECT, "Expected hr == D3DRMERR_BADOBJECT, got %#x.\n", hr);
+    hr = IDirect3DRMViewport2_Init(viewport2, device3, frame3, rc.left, rc.top, rc.right + 1, rc.bottom + 1);
+    ok(hr == D3DRMERR_BADOBJECT, "Expected hr == D3DRMERR_BADOBJECT, got %#x.\n", hr);
+    hr = IDirect3DRMViewport2_Init(viewport2, device3, frame3, rc.left, rc.top, rc.right + 1, rc.bottom);
+    ok(hr == D3DRMERR_BADOBJECT, "Expected hr == D3DRMERR_BADOBJECT, got %#x.\n", hr);
+    hr = IDirect3DRMViewport2_Init(viewport2, device3, frame3, rc.left, rc.top, rc.right, rc.bottom + 1);
+    ok(hr == D3DRMERR_BADOBJECT, "Expected hr == D3DRMERR_BADOBJECT, got %#x.\n", hr);
+
+    device_ref = get_refcount((IUnknown *)device3);
+    frame_ref2 = get_refcount((IUnknown *)frame3);
+    hr = IDirect3DRMViewport2_Init(viewport2, device3, frame3, rc.left, rc.top, rc.right, rc.bottom);
+    ok(SUCCEEDED(hr), "Cannot initialize IDirect3DRMViewport2 interface (hr = %#x).\n", hr);
+    ref4 = get_refcount((IUnknown *)device3);
+    ok(ref4 == device_ref, "Expected ref4 == device_ref, got device_ref = %u, ref4 = %u.\n", device_ref, ref4);
+    ref4 = get_refcount((IUnknown *)frame3);
+    ok(ref4 > frame_ref2, "Expected ref4 > frame_ref2, got frame_ref2 = %u, ref4 = %u.\n", frame_ref2, ref4);
+
+    hr = IDirect3DRMViewport2_Init(viewport2, device3, frame3, rc.left, rc.top, rc.right, rc.bottom);
+    ok(hr == D3DRMERR_BADOBJECT, "Expected hr == D3DRMERR_BADOBJECT, got %#x.\n", hr);
+
+    IDirect3DRMViewport2_Release(viewport2);
+    ref4 = get_refcount((IUnknown *)d3drm1);
+    todo_wine ok(ref4 > ref1, "Expected ref4 > ref1, got ref1 = %u, ref4 = %u.\n", ref1, ref4);
+    ref4 = get_refcount((IUnknown *)d3drm2);
+    ok(ref4 == ref2, "Expected ref4 == ref2, got ref2 = %u, ref4 = %u.\n", ref2, ref4);
+    ref4 = get_refcount((IUnknown *)d3drm3);
+    ok(ref4 == ref3, "Expected ref4 == ref3, got ref3 = %u, ref4 = %u.\n", ref3, ref4);
+    ref4 = get_refcount((IUnknown *)device3);
+    ok(ref4 == device_ref, "Expected ref4 == device_ref, got device_ref = %u, ref4 = %u.\n", device_ref, ref4);
+    ref4 = get_refcount((IUnknown *)frame3);
+    todo_wine ok(ref4 > frame_ref2, "Expected ref4 > frame_ref2, got frame_ref2 = %u, ref4 = %u.\n", frame_ref2, ref4);
+
+    IDirect3DRMDevice3_Release(device3);
+    IDirect3DRMDevice_Release(device1);
+    ref4 = get_refcount((IUnknown *)d3drm1);
+    todo_wine ok(ref4 > initial_ref1, "Expected ref4 > initial_ref1, got initial_ref1 = %u, ref4 = %u.\n", initial_ref1, ref4);
+    ref4 = get_refcount((IUnknown *)d3drm2);
+    ok(ref4 == initial_ref2, "Expected ref4 == initial_ref2, got initial_ref2 = %u, ref4 = %u.\n", initial_ref2, ref4);
+    ref4 = get_refcount((IUnknown *)d3drm3);
+    ok(ref4 == initial_ref3, "Expected ref4 == initial_ref3, got initial_ref3 = %u, ref4 = %u.\n", initial_ref3, ref4);
+    ref4 = get_refcount((IUnknown *)frame);
+    ok(ref4 == frame_ref, "Expected ref4 == frame_ref, got frame_ref = %u, ref4 = %u.\n", frame_ref, ref4);
+    ref4 = get_refcount((IUnknown *)frame3);
+    ok(ref4 == frame_ref2, "Expected ref4 == frame_ref2, got frame_ref2 = %u, ref4 = %u.\n", frame_ref2, ref4);
+
+    IDirect3DRMFrame3_Release(frame3);
+    ref4 = get_refcount((IUnknown *)d3drm1);
+    todo_wine ok(ref4 > initial_ref1, "Expected ref4 > initial_ref1, got initial_ref1 = %u, ref4 = %u.\n", initial_ref1, ref4);
+    ref4 = get_refcount((IUnknown *)d3drm2);
+    ok(ref4 == initial_ref2, "Expected ref4 == initial_ref2, got initial_ref2 = %u, ref4 = %u.\n", initial_ref2, ref4);
+    ref4 = get_refcount((IUnknown *)d3drm3);
+    ok(ref4 == initial_ref3, "Expected ref4 == initial_ref3, got initial_ref3 = %u, ref4 = %u.\n", initial_ref3, ref4);
 
     IDirect3DRMFrame_Release(frame);
-    IDirect3DRMDevice_Release(device);
-    IDirectDrawClipper_Release(pClipper);
+    ref4 = get_refcount((IUnknown *)d3drm1);
+    ok(ref4 == initial_ref1, "Expected ref4 == initial_ref1, got initial_ref1 = %u, ref4 = %u.\n", initial_ref1, ref4);
+    ref4 = get_refcount((IUnknown *)d3drm2);
+    ok(ref4 == initial_ref2, "Expected ref4 == initial_ref2, got initial_ref2 = %u, ref4 = %u.\n", initial_ref2, ref4);
+    ref4 = get_refcount((IUnknown *)d3drm3);
+    ok(ref4 == initial_ref3, "Expected ref4 == initial_ref3, got initial_ref3 = %u, ref4 = %u.\n", initial_ref3, ref4);
+    IDirectDrawClipper_Release(clipper);
 
-    IDirect3DRM_Release(d3drm);
+    IDirect3DRM3_Release(d3drm3);
+    IDirect3DRM2_Release(d3drm2);
+    IDirect3DRM_Release(d3drm1);
     DestroyWindow(window);
 }
 
diff --git a/dlls/d3drm/viewport.c b/dlls/d3drm/viewport.c
index cb5f9b5..8b0c772 100644
--- a/dlls/d3drm/viewport.c
+++ b/dlls/d3drm/viewport.c
@@ -42,6 +42,13 @@ static inline struct d3drm_viewport *impl_from_IDirect3DRMViewport2(IDirect3DRMV
 static void d3drm_viewport_destroy(struct d3drm_viewport *viewport)
 {
     d3drm_object_cleanup((IDirect3DRMObject*)&viewport->IDirect3DRMViewport_iface, &viewport->obj);
+    TRACE("viewport %p releasing attached interfaces.\n", viewport);
+    if (viewport->d3d_viewport)
+    {
+        IDirect3DViewport_Release(viewport->d3d_viewport);
+        IDirect3DRMFrame_Release(viewport->camera);
+        IDirect3DRM_Release(viewport->d3drm);
+    }
     HeapFree(GetProcessHeap(), 0, viewport);
 }
 
@@ -270,19 +277,128 @@ static HRESULT WINAPI d3drm_viewport1_GetClassName(IDirect3DRMViewport *iface, D
 static HRESULT WINAPI d3drm_viewport2_Init(IDirect3DRMViewport2 *iface, IDirect3DRMDevice3 *device,
         IDirect3DRMFrame3 *camera, DWORD x, DWORD y, DWORD width, DWORD height)
 {
-    FIXME("iface %p, device %p, camera %p, x %u, y %u, width %u, height %u stub!\n",
+    struct d3drm_viewport *viewport = impl_from_IDirect3DRMViewport2(iface);
+    D3DVIEWPORT vp;
+    D3DVALUE scale;
+    IDirect3D *d3d1 = NULL;
+    D3DCOLOR color;
+    IDirect3DDevice *d3d_device = NULL;
+    IDirect3DMaterial *material = NULL;
+    D3DMATERIAL mat;
+    D3DMATERIALHANDLE hmat;
+    HRESULT hr = D3DRM_OK;
+
+    TRACE("iface %p, device %p, camera %p, x %u, y %u, width %u, height %u.\n",
             iface, device, camera, x, y, width, height);
 
-    return E_NOTIMPL;
+    if (!device || !camera
+            || width > IDirect3DRMDevice3_GetWidth(device)
+            || height > IDirect3DRMDevice3_GetHeight(device))
+    {
+        return D3DRMERR_BADOBJECT;
+    }
+
+    if (viewport->d3d_viewport)
+        return D3DRMERR_BADOBJECT;
+
+    IDirect3DRM_AddRef(viewport->d3drm);
+
+    if (FAILED(hr = IDirect3DRMDevice3_GetDirect3DDevice(device, &d3d_device)))
+        goto cleanup;
+
+    if (FAILED(hr = IDirect3DDevice_GetDirect3D(d3d_device, &d3d1)))
+        goto cleanup;
+
+    if (FAILED(hr = IDirect3D_CreateViewport(d3d1, &viewport->d3d_viewport, NULL)))
+        goto cleanup;
+
+    vp.dwSize = sizeof(vp);
+    vp.dwWidth = width;
+    vp.dwHeight = height;
+    vp.dwX = x;
+    vp.dwY = y;
+    scale = width > height ? (float)width / 2.0f : (float)height / 2.0f;
+    vp.dvScaleX = scale;
+    vp.dvScaleY = scale;
+    vp.dvMaxX = vp.dwWidth / (2.0f * vp.dvScaleX);
+    vp.dvMaxY = vp.dwHeight / (2.0f * vp.dvScaleY);
+    vp.dvMinZ = 0.0f;
+    vp.dvMaxZ = 1.0f;
+
+    if (FAILED(hr = IDirect3DViewport_SetViewport(viewport->d3d_viewport, &vp)))
+        goto cleanup;
+
+    if (FAILED(hr = IDirect3DDevice_AddViewport(d3d_device, viewport->d3d_viewport)))
+        goto cleanup;
+
+    if (FAILED(hr = IDirect3DRMFrame3_QueryInterface(camera, &IID_IDirect3DRMFrame, (void **)&viewport->camera)))
+        goto cleanup;
+
+    color = IDirect3DRMFrame3_GetSceneBackground(camera);
+    /* Create material (ambient/diffuse/emissive?), set material */
+    if (FAILED(hr = IDirect3D_CreateMaterial(d3d1, &material, NULL)))
+        goto cleanup;
+
+    memset(&mat, 0, sizeof(mat));
+    memcpy(&mat.diffuse, &color, sizeof(color));
+
+    if (FAILED(hr = IDirect3DMaterial_SetMaterial(material, &mat)))
+        goto cleanup;
+
+    if (FAILED(hr = IDirect3DMaterial_GetHandle(material, d3d_device, &hmat)))
+        goto cleanup;
+
+    hr = IDirect3DViewport_SetBackground(viewport->d3d_viewport, hmat);
+
+cleanup:
+
+    if (material)
+        IDirect3DMaterial_Release(material);
+    if (FAILED(hr))
+    {
+        if (viewport->d3d_viewport)
+        {
+            IDirect3DViewport_Release(viewport->d3d_viewport);
+            viewport->d3d_viewport = NULL;
+        }
+        if (viewport->camera)
+            IDirect3DRMFrame_Release(viewport->camera);
+        IDirect3DRM_Release(viewport->d3drm);
+    }
+    if (d3d_device)
+        IDirect3DDevice_Release(d3d_device);
+    if (d3d1)
+        IDirect3D_Release(d3d1);
+
+    return hr;
 }
 
 static HRESULT WINAPI d3drm_viewport1_Init(IDirect3DRMViewport *iface, IDirect3DRMDevice *device,
         IDirect3DRMFrame *camera, DWORD x, DWORD y, DWORD width, DWORD height)
 {
-    FIXME("iface %p, device %p, camera %p, x %u, y %u, width %u, height %u stub!\n",
-            iface, device, camera, x, y, width, height);
+    struct d3drm_viewport *viewport = impl_from_IDirect3DRMViewport(iface);
+    IDirect3DRMDevice3 *device3;
+    IDirect3DRMFrame3 *camera3;
+    HRESULT hr;
 
-    return E_NOTIMPL;
+    TRACE("iface %p, device %p, camera %p, x %u, y %u, width %u, height %u.\n",
+          iface, device, camera, x, y, width, height);
+
+    if (!device || !camera)
+        return D3DRMERR_BADOBJECT;
+
+    if (FAILED(hr = IDirect3DRMDevice_QueryInterface(device, &IID_IDirect3DRMDevice3, (void **)&device3)))
+        return hr;
+
+    if (FAILED(hr = IDirect3DRMFrame_QueryInterface(camera, &IID_IDirect3DRMFrame3, (void **)&camera3)))
+    {
+        IDirect3DRMDevice3_Release(device3);
+        return hr;
+    }
+    IDirect3DRMDevice_Release(device);
+    IDirect3DRMFrame_Release(camera);
+
+    return d3drm_viewport2_Init(&viewport->IDirect3DRMViewport2_iface, device3, camera3, x, y, width, height);
 }
 
 static HRESULT WINAPI d3drm_viewport2_Clear(IDirect3DRMViewport2 *iface, DWORD flags)
@@ -827,7 +943,7 @@ HRESULT d3drm_viewport_create(struct d3drm_viewport **viewport, IDirect3DRM *d3d
 {
     struct d3drm_viewport *object;
 
-    TRACE("viewport %p, d3drm %p.\n", viewport, d3drm);
+    TRACE("out %p, d3drm %p.\n", viewport, d3drm);
 
     if (!(object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*object))))
         return E_OUTOFMEMORY;
-- 
2.3.2 (Apple Git-55)




More information about the wine-patches mailing list