diff --git a/dlls/d3drm/d3drm.c b/dlls/d3drm/d3drm.c index 260cc7d2173..31564364a53 100644 --- a/dlls/d3drm/d3drm.c +++ b/dlls/d3drm/d3drm.c @@ -407,9 +407,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, @@ -882,9 +898,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, @@ -1484,9 +1516,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, diff --git a/dlls/d3drm/d3drm_private.h b/dlls/d3drm/d3drm_private.h index 033fcffe982..cfef7885f47 100644 --- a/dlls/d3drm/d3drm_private.h +++ b/dlls/d3drm/d3drm_private.h @@ -51,6 +51,7 @@ struct d3drm_texture IDirect3DRMTexture3 IDirect3DRMTexture3_iface; IDirect3DRM *d3drm; D3DRMIMAGE *image; + IDirectDrawSurface *surface; }; struct d3drm_frame diff --git a/dlls/d3drm/tests/d3drm.c b/dlls/d3drm/tests/d3drm.c index 90820a2499a..411cd835f60 100644 --- a/dlls/d3drm/tests/d3drm.c +++ b/dlls/d3drm/tests/d3drm.c @@ -2342,8 +2342,10 @@ static void test_Texture(void) ok(ref4 == ref1, "expected ref4 == ref1, got ref1 = %u , ref4 = %u.\n", ref1, ref4); /* Created from image, GetSurface() does not work. */ + hr = IDirect3DRMTexture3_GetSurface(texture3, 0, NULL); + ok(hr == D3DRMERR_BADVALUE, "GetSurface() expected to fail, %#x\n", hr); + hr = IDirect3DRMTexture3_GetSurface(texture3, 0, &surface); -todo_wine ok(hr == D3DRMERR_NOTCREATEDFROMDDS, "GetSurface() expected to fail, %#x\n", hr); /* Test all failures together */ @@ -6599,66 +6601,52 @@ static void test_create_texture_from_surface(void) /* Test NULL params */ texture1 = (IDirect3DRMTexture *)0xdeadbeef; hr = IDirect3DRM_CreateTextureFromSurface(d3drm1, NULL, &texture1); -todo_wine { ok(hr == D3DRMERR_BADVALUE, "Expected hr == D3DRMERR_BADVALUE, got %#x.\n", hr); ok(!texture1, "Expected texture returned == NULL, got %p.\n", texture1); -} + hr = IDirect3DRM_CreateTextureFromSurface(d3drm1, NULL, NULL); -todo_wine ok(hr == D3DRMERR_BADVALUE, "Expected hr == D3DRMERR_BADVALUE, got %#x.\n", hr); texture2 = (IDirect3DRMTexture2 *)0xdeadbeef; hr = IDirect3DRM2_CreateTextureFromSurface(d3drm2, NULL, &texture2); -todo_wine { ok(hr == D3DRMERR_BADVALUE, "Expected hr == D3DRMERR_BADVALUE, got %#x.\n", hr); ok(!texture2, "Expected texture returned == NULL, got %p.\n", texture2); -} + hr = IDirect3DRM2_CreateTextureFromSurface(d3drm2, NULL, NULL); -todo_wine ok(hr == D3DRMERR_BADVALUE, "Expected hr == D3DRMERR_BADVALUE, got %#x.\n", hr); texture3 = (IDirect3DRMTexture3 *)0xdeadbeef; hr = IDirect3DRM3_CreateTextureFromSurface(d3drm3, NULL, &texture3); -todo_wine { ok(hr == D3DRMERR_BADVALUE, "Expected hr == D3DRMERR_BADVALUE, got %#x.\n", hr); ok(!texture3, "Expected texture returned == NULL, got %p.\n", texture3); -} + hr = IDirect3DRM3_CreateTextureFromSurface(d3drm3, NULL, NULL); -todo_wine ok(hr == D3DRMERR_BADVALUE, "Expected hr == D3DRMERR_BADVALUE, got %#x.\n", hr); ok(get_refcount((IUnknown *)surface) == 1, "Unexpected surface refcount.\n"); hr = IDirect3DRM_CreateTextureFromSurface(d3drm1, surface, &texture1); -todo_wine ok(SUCCEEDED(hr), "Failed to create texture, hr %#x.\n", hr); -if (SUCCEEDED(hr)) -{ + ok(get_refcount((IUnknown *)surface) == 2, "Unexpected surface refcount.\n"); image = IDirect3DRMTexture_GetImage(texture1); ok(image == NULL, "Unexpected image, %p.\n", image); hr = IDirect3DRMTexture_InitFromSurface(texture1, NULL); ok(hr == D3DRMERR_BADOBJECT, "Expected hr == D3DRMERR_BADOBJECT, got %#x.\n", hr); IDirect3DRMTexture_Release(texture1); -} + ok(get_refcount((IUnknown *)surface) == 1, "Unexpected surface refcount.\n"); hr = IDirect3DRM2_CreateTextureFromSurface(d3drm2, surface, &texture2); -todo_wine ok(SUCCEEDED(hr), "Failed to create texture, hr %#x.\n", hr); -if (SUCCEEDED(hr)) -{ ok(get_refcount((IUnknown *)surface) == 2, "Unexpected surface refcount.\n"); image = IDirect3DRMTexture2_GetImage(texture2); ok(image == NULL, "Unexpected image, %p.\n", image); hr = IDirect3DRMTexture2_InitFromSurface(texture2, NULL); ok(hr == D3DRMERR_BADOBJECT, "Expected hr == D3DRMERR_BADOBJECT, got %#x.\n", hr); IDirect3DRMTexture_Release(texture2); -} + ok(get_refcount((IUnknown *)surface) == 1, "Unexpected surface refcount.\n"); hr = IDirect3DRM3_CreateTextureFromSurface(d3drm3, surface, &texture3); -todo_wine ok(SUCCEEDED(hr), "Failed to create texture, hr %#x.\n", hr); -if (SUCCEEDED(hr)) -{ ok(get_refcount((IUnknown *)surface) == 2, "Unexpected surface refcount.\n"); image = IDirect3DRMTexture3_GetImage(texture3); ok(image == NULL, "Unexpected image, %p.\n", image); @@ -6711,9 +6699,8 @@ if (SUCCEEDED(hr)) ok(ref3 == get_refcount((IUnknown *)d3drm3), "Expected d3drm3 reference unchanged.\n"); /* Release leaked reference to d3drm1 */ IDirect3DRM_Release(d3drm1); - IDirect3DRMTexture3_Release(texture3); -} + IDirectDrawSurface_Release(surface2); IDirectDrawSurface_Release(surface); IDirect3DRM3_Release(d3drm3); diff --git a/dlls/d3drm/texture.c b/dlls/d3drm/texture.c index 5d621a05f83..3de22c64236 100644 --- a/dlls/d3drm/texture.c +++ b/dlls/d3drm/texture.c @@ -45,8 +45,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); } @@ -177,9 +179,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) @@ -477,9 +481,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) @@ -835,9 +841,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) @@ -974,7 +993,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; @@ -1001,9 +1020,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)