diff --git a/dlls/d3drm/d3drm.c b/dlls/d3drm/d3drm.c index 9e8630e966f..18ce95eb6c0 100644 --- a/dlls/d3drm/d3drm.c +++ b/dlls/d3drm/d3drm.c @@ -77,6 +77,19 @@ static HRESULT d3drm_create_device_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; @@ -1121,6 +1134,7 @@ 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}, }; TRACE("iface %p, clsid %s, outer %p, iid %s, out %p.\n", diff --git a/dlls/d3drm/d3drm_private.h b/dlls/d3drm/d3drm_private.h index 9bf7dff3399..9fc70002445 100644 --- a/dlls/d3drm/d3drm_private.h +++ b/dlls/d3drm/d3drm_private.h @@ -72,8 +72,11 @@ struct d3drm_frame struct d3drm_viewport { struct d3drm_object obj; + IDirect3DRMFrame *camera; IDirect3DRMViewport IDirect3DRMViewport_iface; IDirect3DRMViewport2 IDirect3DRMViewport2_iface; + IDirect3DViewport *d3d_viewport; + IDirect3DMaterial *material; IDirect3DRM *d3drm; D3DVALUE back; D3DVALUE front; @@ -112,6 +115,8 @@ HRESULT d3drm_object_add_destroy_callback(struct d3drm_object *object, D3DRMOBJE HRESULT d3drm_object_delete_destroy_callback(struct d3drm_object *object, D3DRMOBJECTCALLBACK cb, void *ctx) 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; + 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_viewport_create(struct d3drm_viewport **viewport, IDirect3DRM *d3drm) DECLSPEC_HIDDEN; diff --git a/dlls/d3drm/frame.c b/dlls/d3drm/frame.c index e58dd0514c0..2ff0241d76f 100644 --- a/dlls/d3drm/frame.c +++ b/dlls/d3drm/frame.c @@ -79,8 +79,6 @@ static inline struct d3drm_frame *impl_from_IDirect3DRMFrame3(IDirect3DRMFrame3 static inline struct d3drm_frame *unsafe_impl_from_IDirect3DRMFrame3(IDirect3DRMFrame3 *iface); -static inline struct d3drm_frame *unsafe_impl_from_IDirect3DRMFrame(IDirect3DRMFrame *iface); - static inline struct d3drm_frame_array *impl_from_IDirect3DRMFrameArray(IDirect3DRMFrameArray *iface) { return CONTAINING_RECORD(iface, struct d3drm_frame_array, IDirect3DRMFrameArray_iface); @@ -2897,7 +2895,7 @@ static inline struct d3drm_frame *unsafe_impl_from_IDirect3DRMFrame3(IDirect3DRM return impl_from_IDirect3DRMFrame3(iface); } -static inline struct d3drm_frame *unsafe_impl_from_IDirect3DRMFrame(IDirect3DRMFrame *iface) +struct d3drm_frame *unsafe_impl_from_IDirect3DRMFrame(IDirect3DRMFrame *iface) { if (!iface) return NULL; diff --git a/dlls/d3drm/tests/d3drm.c b/dlls/d3drm/tests/d3drm.c index db9a774f92d..e56639f9bdd 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,147 @@ 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, 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 6986a16b488..99b221795fc 100644 --- a/dlls/d3drm/viewport.c +++ b/dlls/d3drm/viewport.c @@ -41,9 +41,18 @@ static inline struct d3drm_viewport *impl_from_IDirect3DRMViewport2(IDirect3DRMV static void d3drm_viewport_destroy(struct d3drm_viewport *viewport) { - TRACE("viewport %p.\n", viewport); + TRACE("viewport %p releasing attached interfaces.\n", viewport); d3drm_object_cleanup((IDirect3DRMObject *)&viewport->IDirect3DRMViewport_iface, &viewport->obj); + + if (viewport->d3d_viewport) + { + IDirect3DViewport_Release(viewport->d3d_viewport); + IDirect3DMaterial_Release(viewport->material); + IDirect3DRMFrame_Release(viewport->camera); + IDirect3DRM_Release(viewport->d3drm); + } + HeapFree(GetProcessHeap(), 0, viewport); } @@ -270,19 +279,129 @@ 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)); + mat.dwSize = sizeof(mat); + mat.diffuse.r = RGBA_GETRED(color) / 255.0f; + mat.diffuse.g = RGBA_GETGREEN(color) / 255.0f; + mat.diffuse.b = RGBA_GETBLUE(color) / 255.0f; + mat.diffuse.a = RGBA_GETALPHA(color) / 255.0f; + + 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); + viewport->material = material; + +cleanup: + + if (FAILED(hr)) + { + if (viewport->d3d_viewport) + { + IDirect3DViewport_Release(viewport->d3d_viewport); + viewport->d3d_viewport = NULL; + } + if (viewport->camera) + IDirect3DRMFrame_Release(viewport->camera); + if (material) + IDirect3DMaterial_Release(material); + 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); + struct d3drm_frame *frame = unsafe_impl_from_IDirect3DRMFrame(camera); + IDirect3DRMDevice3 *device3; + 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 || !frame) + return D3DRMERR_BADOBJECT; + + if (FAILED(hr = IDirect3DRMDevice_QueryInterface(device, &IID_IDirect3DRMDevice3, (void **)&device3))) + return hr; + + hr = d3drm_viewport2_Init(&viewport->IDirect3DRMViewport2_iface, device3, &frame->IDirect3DRMFrame3_iface, + x, y, width, height); + IDirect3DRMDevice3_Release(device3); + + return hr; } static HRESULT WINAPI d3drm_viewport2_Clear(IDirect3DRMViewport2 *iface, DWORD flags)