diff --git a/dlls/d3drm/d3drm.c b/dlls/d3drm/d3drm.c index 61d0a25c7c9..83f7c056ab0 100644 --- a/dlls/d3drm/d3drm.c +++ b/dlls/d3drm/d3drm.c @@ -247,18 +247,31 @@ static HRESULT WINAPI d3drm1_CreateDevice(IDirect3DRM *iface, static HRESULT WINAPI d3drm1_CreateDeviceFromSurface(IDirect3DRM *iface, GUID *guid, IDirectDraw *ddraw, IDirectDrawSurface *backbuffer, IDirect3DRMDevice **device) { + struct d3drm *d3drm = impl_from_IDirect3DRM(iface); struct d3drm_device *object; HRESULT hr; - FIXME("iface %p, guid %s, ddraw %p, backbuffer %p, device %p partial stub.\n", + + TRACE("iface %p, guid %s, ddraw %p, backbuffer %p, device %p.\n", iface, debugstr_guid(guid), ddraw, backbuffer, device); + if (!device) + return D3DRMERR_BADVALUE; + *device = NULL; + + if (!backbuffer || !ddraw) + return D3DRMERR_BADDEVICE; + hr = d3drm_device_create(&object); if (FAILED(hr)) return hr; - *device = IDirect3DRMDevice_from_impl(object); + hr = d3drm_device_init(object, 1, &d3drm->IDirect3DRM_iface, ddraw, backbuffer, TRUE); + if (SUCCEEDED(hr)) + *device = IDirect3DRMDevice_from_impl(object); + else + d3drm_device_destroy(object); - return D3DRM_OK; + return hr; } static HRESULT WINAPI d3drm1_CreateDeviceFromD3D(IDirect3DRM *iface, @@ -316,7 +329,7 @@ static HRESULT WINAPI d3drm1_CreateDeviceFromClipper(IDirect3DRM *iface, return hr; } - hr = d3drm_device_init(object, 1, iface, ddraw, render_target); + hr = d3drm_device_init(object, 1, iface, ddraw, render_target, TRUE); IDirectDraw_Release(ddraw); IDirectDrawSurface_Release(render_target); if (FAILED(hr)) @@ -1144,7 +1157,7 @@ static HRESULT WINAPI d3drm3_CreateDeviceFromClipper(IDirect3DRM3 *iface, return hr; } - hr = d3drm_device_init(object, 3, &d3drm->IDirect3DRM_iface, ddraw, render_target); + hr = d3drm_device_init(object, 3, &d3drm->IDirect3DRM_iface, ddraw, render_target, TRUE); IDirectDraw_Release(ddraw); IDirectDrawSurface_Release(render_target); if (FAILED(hr)) diff --git a/dlls/d3drm/d3drm_private.h b/dlls/d3drm/d3drm_private.h index 00fa7a85bc4..9e2b3bd4d60 100644 --- a/dlls/d3drm/d3drm_private.h +++ b/dlls/d3drm/d3drm_private.h @@ -47,7 +47,8 @@ void d3drm_device_destroy(struct d3drm_device *device) 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; -HRESULT d3drm_device_init(struct d3drm_device *device, UINT version, IDirect3DRM *d3drm, IDirectDraw *ddraw, IDirectDrawSurface *surface) DECLSPEC_HIDDEN; +HRESULT d3drm_device_init(struct d3drm_device *device, UINT version, IDirect3DRM *d3drm, IDirectDraw *ddraw, IDirectDrawSurface *surface, + BOOL create_z_surface) DECLSPEC_HIDDEN; struct d3drm_file_header { diff --git a/dlls/d3drm/device.c b/dlls/d3drm/device.c index 4024ead565a..03caa36b411 100644 --- a/dlls/d3drm/device.c +++ b/dlls/d3drm/device.c @@ -159,8 +159,10 @@ HRESULT d3drm_device_create_surfaces_from_clipper(struct d3drm_device *object, I return D3DRM_OK; } -HRESULT d3drm_device_init(struct d3drm_device *device, UINT version, IDirect3DRM *d3drm, IDirectDraw *ddraw, IDirectDrawSurface *surface) +HRESULT d3drm_device_init(struct d3drm_device *device, UINT version, IDirect3DRM *d3drm, IDirectDraw *ddraw, IDirectDrawSurface *surface, + BOOL create_z_surface) { + DDSCAPS caps = { DDSCAPS_ZBUFFER }; IDirectDrawSurface *ds = NULL; IDirect3DDevice *device1 = NULL; IDirect3DDevice2 *device2 = NULL; @@ -180,21 +182,35 @@ HRESULT d3drm_device_init(struct d3drm_device *device, UINT version, IDirect3DRM if (FAILED(hr)) return hr; - memset(&surface_desc, 0, sizeof(surface_desc)); - surface_desc.dwSize = sizeof(surface_desc); - surface_desc.dwFlags = DDSD_CAPS | DDSD_ZBUFFERBITDEPTH | DDSD_WIDTH | DDSD_HEIGHT; - surface_desc.ddsCaps.dwCaps = DDSCAPS_ZBUFFER; - surface_desc.dwZBufferBitDepth = 16; - surface_desc.dwWidth = desc.dwWidth; - surface_desc.dwHeight = desc.dwHeight; - hr = IDirectDraw_CreateSurface(ddraw, &surface_desc, &ds, NULL); - if (FAILED(hr)) - return hr; + if (!(desc.ddsCaps.dwCaps & DDSCAPS_3DDEVICE)) + return DDERR_INVALIDCAPS; - hr = IDirectDrawSurface_AddAttachedSurface(surface, ds); - IDirectDrawSurface_Release(ds); - if (FAILED(hr)) - return hr; + hr = IDirectDrawSurface_GetAttachedSurface(surface, &caps, &ds); + if (SUCCEEDED(hr)) + { + create_z_surface = FALSE; + IDirectDrawSurface_Release(ds); + ds = NULL; + } + + if (create_z_surface) + { + memset(&surface_desc, 0, sizeof(surface_desc)); + surface_desc.dwSize = sizeof(surface_desc); + surface_desc.dwFlags = DDSD_CAPS | DDSD_ZBUFFERBITDEPTH | DDSD_WIDTH | DDSD_HEIGHT; + surface_desc.ddsCaps.dwCaps = DDSCAPS_ZBUFFER; + surface_desc.dwZBufferBitDepth = 16; + surface_desc.dwWidth = desc.dwWidth; + surface_desc.dwHeight = desc.dwHeight; + hr = IDirectDraw_CreateSurface(ddraw, &surface_desc, &ds, NULL); + if (FAILED(hr)) + return hr; + + hr = IDirectDrawSurface_AddAttachedSurface(surface, ds); + IDirectDrawSurface_Release(ds); + if (FAILED(hr)) + return hr; + } if (version == 1) hr = IDirectDrawSurface_QueryInterface(surface, &IID_IDirect3DRGBDevice, (void **)&device1); diff --git a/dlls/d3drm/tests/d3drm.c b/dlls/d3drm/tests/d3drm.c index 981590d06f5..5a33cf8eb6b 100644 --- a/dlls/d3drm/tests/d3drm.c +++ b/dlls/d3drm/tests/d3drm.c @@ -2481,7 +2481,7 @@ static void test_create_device_from_surface1(void) DDSURFACEDESC desc; IDirectDraw *ddraw = NULL; IDirect3DRM *d3drm1 = NULL; - IDirect3DRMDevice *device1 = NULL; + IDirect3DRMDevice *device1 = (IDirect3DRMDevice *)0xdeadbeef; IDirect3DDevice *d3ddevice1 = NULL; IDirectDrawSurface *surface = NULL, *ds = NULL, *d3drm_surface = NULL, *d3drm_ds = NULL; DWORD expected_flags; @@ -2517,21 +2517,28 @@ static void test_create_device_from_surface1(void) ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr); hr = IDirect3DRM_CreateDeviceFromSurface(d3drm1, &driver, ddraw, surface, &device1); - todo_wine ok(hr == DDERR_INVALIDCAPS, "Expected hr == DDERR_INVALIDCAPS, got %x.\n", hr); + ok(hr == DDERR_INVALIDCAPS, "Expected hr == DDERR_INVALIDCAPS, got %x.\n", hr); + ok(device1 == NULL, "Expected device returned == NULL, got %p.\n", device1); IDirectDrawSurface_Release(surface); - if (SUCCEEDED(hr)) - IDirect3DRMDevice_Release(device1); desc.ddsCaps.dwCaps |= DDSCAPS_3DDEVICE; hr = IDirectDraw_CreateSurface(ddraw, &desc, &surface, NULL); ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr); surface_ref1 = get_refcount((IUnknown *)surface); + + hr = IDirect3DRM_CreateDeviceFromSurface(d3drm1, &driver, ddraw, surface, NULL); + ok(hr == D3DRMERR_BADVALUE, "Expected hr == DDERR_BADVALUE, got %x.\n", hr); + hr = IDirect3DRM_CreateDeviceFromSurface(d3drm1, &driver, ddraw, NULL, &device1); + ok(hr == D3DRMERR_BADDEVICE, "Expected hr == DDERR_BADDEVICE, got %x.\n", hr); + hr = IDirect3DRM_CreateDeviceFromSurface(d3drm1, &driver, NULL, surface, &device1); + ok(hr == D3DRMERR_BADDEVICE, "Expected hr == DDERR_BADDEVICE, got %x.\n", hr); + hr = IDirect3DRM_CreateDeviceFromSurface(d3drm1, &driver, ddraw, surface, &device1); ok(SUCCEEDED(hr), "Cannot create IDirect3DRMDevice interface (hr = %x).\n", hr); ref2 = get_refcount((IUnknown *)d3drm1); - todo_wine ok(ref2 > ref1, "expected ref2 > ref1, got ref1 = %u , ref2 = %u.\n", ref1, ref2); + ok(ref2 > ref1, "expected ref2 > ref1, got ref1 = %u , ref2 = %u.\n", ref1, ref2); surface_ref2 = get_refcount((IUnknown *)surface); - todo_wine ok(surface_ref2 > surface_ref1, "Expected surface_ref2 > surface_ref1, got surface_ref1 = %u, surface_ref2 = %u.\n", surface_ref1, surface_ref2); + ok(surface_ref2 > surface_ref1, "Expected surface_ref2 > surface_ref1, got surface_ref1 = %u, surface_ref2 = %u.\n", surface_ref1, surface_ref2); /* Check if CreateDeviceFromSurface creates a primary surface */ hr = IDirectDraw_EnumSurfaces(ddraw, DDENUMSURFACES_ALL | DDENUMSURFACES_DOESEXIST, @@ -2540,9 +2547,7 @@ static void test_create_device_from_surface1(void) ok(d3drm_surface == NULL, "No primary surface should have enumerated (%p).\n", d3drm_surface); hr = IDirect3DRMDevice_GetDirect3DDevice(device1, &d3ddevice1); - todo_wine ok(hr == D3DRM_OK, "Cannot get IDirect3DDevice interface (hr = %x).\n", hr); - if (FAILED(hr)) - goto cleanup; + ok(hr == D3DRM_OK, "Cannot get IDirect3DDevice interface (hr = %x).\n", hr); hr = IDirect3DDevice_QueryInterface(d3ddevice1, &IID_IDirectDrawSurface, (void **)&d3drm_surface); ok(hr == DD_OK, "Cannot get surface to the render target (hr = %x).\n", hr); @@ -2579,7 +2584,6 @@ static void test_create_device_from_surface1(void) /*The render target still holds a reference to ds as the depth surface remains attached to it, so refcount will be 1*/ ref1 = IDirectDrawSurface_Release(ds); ok(ref1 == 1, "Expected ref1 == 1, got %u.\n", ref1); - ref1 = IDirectDrawSurface_Release(surface); ok(ref1 == 0, "Expected Render target refcount == 0, got %u.\n", ref1); @@ -2609,9 +2613,7 @@ static void test_create_device_from_surface1(void) ok(SUCCEEDED(hr), "Cannot create IDirect3DRMDevice interface (hr = %x).\n", hr); hr = IDirect3DRMDevice2_GetDirect3DDevice(device1, &d3ddevice1); - todo_wine ok(hr == D3DRM_OK, "Cannot get IDirect3DDevice interface (hr = %x).\n", hr); - if (FAILED(hr)) - goto cleanup; + ok(hr == D3DRM_OK, "Cannot get IDirect3DDevice interface (hr = %x).\n", hr); hr = IDirect3DDevice_QueryInterface(d3ddevice1, &IID_IDirectDrawSurface, (void **)&d3drm_surface); ok(hr == DD_OK, "Cannot get surface to the render target (hr = %x).\n", hr); @@ -2626,27 +2628,17 @@ static void test_create_device_from_surface1(void) IDirectDrawSurface_Release(d3drm_surface); IDirectDrawSurface_Release(ds); -cleanup: - if (d3ddevice1) - IDirect3DDevice_Release(d3ddevice1); + IDirect3DDevice_Release(d3ddevice1); IDirect3DRMDevice_Release(device1); hr = IDirectDrawSurface_GetAttachedSurface(surface, &caps, &ds); - todo_wine ok(hr == DD_OK, "Cannot get attached depth surface (hr = %x).\n", hr); - if (SUCCEEDED(hr)) - { - /*The render target still holds a reference to ds as the depth surface remains attached to it, so refcount will be 1*/ - ref1 = IDirectDrawSurface_Release(ds); - ok(ref1 == 1, "Expected ref1 == 1, got %u.\n", ref1); - } - if (surface) - { - ref1 = IDirectDrawSurface_Release(surface); - ok(ref1 == 0, "Expected Render target refcount == 0, got %u.\n", ref1); - } - if (d3drm1) - IDirect3DRM_Release(d3drm1); - if (ddraw) - IDirectDraw_Release(ddraw); + ok(hr == DD_OK, "Cannot get attached depth surface (hr = %x).\n", hr); + /*The render target still holds a reference to ds as the depth surface remains attached to it, so refcount will be 1*/ + ref1 = IDirectDrawSurface_Release(ds); + ok(ref1 == 1, "Expected ref1 == 1, got %u.\n", ref1); + ref1 = IDirectDrawSurface_Release(surface); + ok(ref1 == 0, "Expected Render target refcount == 0, got %u.\n", ref1); + IDirect3DRM_Release(d3drm1); + IDirectDraw_Release(ddraw); DestroyWindow(window); }