From: Misha Koshelev Subject: d3dx9_36: Stub ID3DXRenderToSurface, with tests (try 2) Message-Id: Date: Mon, 28 Feb 2011 17:13:52 -0600 Makes the The Last Dance proceed further, fixes bug #24899. Sent per suggestion in http://www.winehq.org/pipermail/wine-devel/2011-February/088914.html Corrected per comments in http://www.winehq.org/pipermail/wine-devel/2011-February/089074.html Misha --- dlls/d3dx9_36/core.c | 149 +++++++++++++++++++++++++++++++++++++++++++ dlls/d3dx9_36/d3dx9_36.spec | 2 +- dlls/d3dx9_36/tests/core.c | 87 +++++++++++++++++++++++++ 3 files changed, 237 insertions(+), 1 deletions(-) diff --git a/dlls/d3dx9_36/core.c b/dlls/d3dx9_36/core.c index 6990fbd..9fadaa7 100644 --- a/dlls/d3dx9_36/core.c +++ b/dlls/d3dx9_36/core.c @@ -130,3 +130,152 @@ HRESULT WINAPI D3DXCreateBuffer(DWORD NumBytes, LPD3DXBUFFER* ppBuffer) *ppBuffer = &object->ID3DXBuffer_iface; return D3D_OK; } + +typedef struct ID3DXRenderToSurfaceImpl +{ + ID3DXRenderToSurface ID3DXRenderToSurface_iface; + LONG ref; + + D3DXRTS_DESC desc; + LPDIRECT3DDEVICE9 device; +} ID3DXRenderToSurfaceImpl; + +static inline ID3DXRenderToSurfaceImpl *impl_from_ID3DXRenderToSurface(ID3DXRenderToSurface *iface) +{ + return CONTAINING_RECORD(iface, ID3DXRenderToSurfaceImpl, ID3DXRenderToSurface_iface); +} + +static HRESULT WINAPI ID3DXRenderToSurfaceImpl_QueryInterface(ID3DXRenderToSurface *iface, REFIID riid, void **ppobj) +{ + if (IsEqualGUID(riid, &IID_IUnknown) + || IsEqualGUID(riid, &IID_ID3DXRenderToSurface)) + { + IUnknown_AddRef(iface); + *ppobj = iface; + return S_OK; + } + + WARN("(%p)->(%s,%p), not found\n", iface, debugstr_guid(riid), ppobj); + *ppobj = NULL; + return E_NOINTERFACE; +} + +static ULONG WINAPI ID3DXRenderToSurfaceImpl_AddRef(ID3DXRenderToSurface *iface) +{ + ID3DXRenderToSurfaceImpl *This = impl_from_ID3DXRenderToSurface(iface); + ULONG ref = InterlockedIncrement(&This->ref); + + TRACE("(%p): AddRef from %d\n", This, ref - 1); + + return ref; +} + +static ULONG WINAPI ID3DXRenderToSurfaceImpl_Release(ID3DXRenderToSurface *iface) +{ + ID3DXRenderToSurfaceImpl *This = impl_from_ID3DXRenderToSurface(iface); + ULONG ref = InterlockedDecrement(&This->ref); + + TRACE("(%p): ReleaseRef to %d\n", This, ref); + + if (ref == 0) + { + HeapFree(GetProcessHeap(), 0, This); + } + return ref; +} + +static HRESULT WINAPI ID3DXRenderToSurfaceImpl_BeginScene(ID3DXRenderToSurface *iface, LPDIRECT3DSURFACE9 surface, const D3DVIEWPORT9 *viewport) +{ + FIXME("(%p)->(%p, %p): stub\n", iface, surface, viewport); + + return E_NOTIMPL; +} + +static HRESULT WINAPI ID3DXRenderToSurfaceImpl_EndScene(ID3DXRenderToSurface *iface, DWORD mipfilter) +{ + FIXME("(%p)->(%u): stub\n", iface, mipfilter); + + return E_NOTIMPL; +} + +static HRESULT WINAPI ID3DXRenderToSurfaceImpl_GetDesc(ID3DXRenderToSurface *iface, D3DXRTS_DESC *parameters) +{ + ID3DXRenderToSurfaceImpl *This = impl_from_ID3DXRenderToSurface(iface); + + TRACE("(%p)->(%p)\n", This, parameters); + + if (parameters == NULL) return D3DERR_INVALIDCALL; + *parameters = This->desc; + + return D3D_OK; +} + +static HRESULT WINAPI ID3DXRenderToSurfaceImpl_GetDevice(ID3DXRenderToSurface *iface, LPDIRECT3DDEVICE9 *device) +{ + ID3DXRenderToSurfaceImpl *This = impl_from_ID3DXRenderToSurface(iface); + + TRACE("(%p)->(%p)\n", This, device); + + if (device == NULL) return D3DERR_INVALIDCALL; + *device = This->device; + IDirect3DDevice9_AddRef(This->device); + + return D3D_OK; +} + +static HRESULT WINAPI ID3DXRenderToSurfaceImpl_OnLostDevice(ID3DXRenderToSurface *iface) +{ + FIXME("(%p): stub\n", iface); + + return E_NOTIMPL; +} + +static HRESULT WINAPI ID3DXRenderToSurfaceImpl_OnResetDevice(ID3DXRenderToSurface *iface) +{ + FIXME("(%p): stub\n", iface); + + return E_NOTIMPL; +} + +const ID3DXRenderToSurfaceVtbl D3DXRenderToSurface_Vtbl = +{ + ID3DXRenderToSurfaceImpl_QueryInterface, + ID3DXRenderToSurfaceImpl_AddRef, + ID3DXRenderToSurfaceImpl_Release, + ID3DXRenderToSurfaceImpl_GetDevice, + ID3DXRenderToSurfaceImpl_GetDesc, + ID3DXRenderToSurfaceImpl_BeginScene, + ID3DXRenderToSurfaceImpl_EndScene, + ID3DXRenderToSurfaceImpl_OnLostDevice, + ID3DXRenderToSurfaceImpl_OnResetDevice +}; + +HRESULT WINAPI D3DXCreateRenderToSurface(LPDIRECT3DDEVICE9 device, UINT width, UINT height, D3DFORMAT format, + BOOL stencil, D3DFORMAT stencil_format, LPD3DXRENDERTOSURFACE *rts) +{ + ID3DXRenderToSurfaceImpl *object; + + TRACE("(%p, %u, %u, %u, %u, %u, %p)\n", device, width, height, format, stencil, stencil_format, rts); + + if (device == NULL || rts == NULL) + { + return D3DERR_INVALIDCALL; + } + + object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(ID3DXRenderToSurfaceImpl)); + if (object == NULL) + { + return E_OUTOFMEMORY; + } + object->ID3DXRenderToSurface_iface.lpVtbl = &D3DXRenderToSurface_Vtbl; + object->ref = 1; + object->device = device; + object->desc.Width = width; + object->desc.Height = height; + object->desc.Format = format; + object->desc.DepthStencil = stencil; + object->desc.DepthStencilFormat = stencil_format; + + *rts = &object->ID3DXRenderToSurface_iface; + return D3D_OK; +} diff --git a/dlls/d3dx9_36/d3dx9_36.spec b/dlls/d3dx9_36/d3dx9_36.spec index f91f962..c4f3dc6 100644 --- a/dlls/d3dx9_36/d3dx9_36.spec +++ b/dlls/d3dx9_36/d3dx9_36.spec @@ -82,7 +82,7 @@ @ stub D3DXCreatePRTCompBuffer @ stub D3DXCreatePRTEngine @ stub D3DXCreateRenderToEnvMap -@ stub D3DXCreateRenderToSurface +@ stdcall D3DXCreateRenderToSurface(ptr long long long long long ptr) @ stub D3DXCreateSPMesh @ stub D3DXCreateSkinInfo @ stub D3DXCreateSkinInfoFromBlendedMesh diff --git a/dlls/d3dx9_36/tests/core.c b/dlls/d3dx9_36/tests/core.c index b1379ef..69087a2 100644 --- a/dlls/d3dx9_36/tests/core.c +++ b/dlls/d3dx9_36/tests/core.c @@ -417,6 +417,92 @@ static void test_ID3DXFont(IDirect3DDevice9 *device) } else skip("Failed to create a ID3DXFont object\n"); } +static inline BOOL test_create_render_to_surface(LPDIRECT3DDEVICE9 device, UINT width, UINT height, D3DFORMAT format, + BOOL stencil, D3DFORMAT stencil_format, LPD3DXRENDERTOSURFACE *rts, + HRESULT expected, BOOL release_on_success, unsigned int line) +{ + HRESULT hr; + + hr = D3DXCreateRenderToSurface(device, width, height, format, stencil, stencil_format, rts); + ok(hr == expected, "Line %u, got result %x, expected %x\n", line, hr, expected); + + if (SUCCEEDED(hr) && *rts && release_on_success) + { + ID3DXRenderToSurface_Release(*rts); + } + + return SUCCEEDED(hr); +} + +static void test_D3DXCreateRenderToSurface(IDirect3DDevice9 *device) +{ + D3DXRTS_DESC desc = { 200, 200, D3DFMT_UNKNOWN, FALSE, D3DFMT_UNKNOWN }; + ID3DXRenderToSurface *rts; + HRESULT hr; + IDirect3DDevice9 *test_device; + D3DXRTS_DESC test_desc; + + test_create_render_to_surface(NULL, desc.Width, desc.Height, desc.Format, desc.DepthStencil, + desc.DepthStencilFormat, &rts, D3DERR_INVALIDCALL, TRUE, __LINE__); + test_create_render_to_surface(device, -1, desc.Height, desc.Format, desc.DepthStencil, + desc.DepthStencilFormat, &rts, D3D_OK, TRUE, __LINE__); + test_create_render_to_surface(device, 0, desc.Height, desc.Format, desc.DepthStencil, + desc.DepthStencilFormat, &rts, D3D_OK, TRUE, __LINE__); + test_create_render_to_surface(device, desc.Width, -1, desc.Format, desc.DepthStencil, + desc.DepthStencilFormat, &rts, D3D_OK, TRUE, __LINE__); + test_create_render_to_surface(device, desc.Width, 0, desc.Format, desc.DepthStencil, + desc.DepthStencilFormat, &rts, D3D_OK, TRUE, __LINE__); + test_create_render_to_surface(device, desc.Width, desc.Height, -1, desc.DepthStencil, + desc.DepthStencilFormat, &rts, D3D_OK, TRUE, __LINE__); + test_create_render_to_surface(device, desc.Width, desc.Height, desc.Format, -1, desc.DepthStencilFormat, + &rts, D3D_OK, TRUE, __LINE__); + test_create_render_to_surface(device, desc.Width, desc.Height, desc.Format, desc.DepthStencil, -1, &rts, + D3D_OK, TRUE, __LINE__); + test_create_render_to_surface(device, desc.Width, desc.Height, desc.Format, desc.DepthStencil, + desc.DepthStencilFormat, NULL, D3DERR_INVALIDCALL, TRUE, __LINE__); + + if (!test_create_render_to_surface(device, desc.Width, desc.Height, desc.Format, desc.DepthStencil, + desc.DepthStencilFormat, &rts, D3D_OK, FALSE, __LINE__)) + { + skip("D3DXCreateRenderToSurface failed, skipping\n"); + } + else + { + /* device */ + hr = ID3DXRenderToSurface_GetDevice(rts, NULL); + ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n", hr, D3DERR_INVALIDCALL); + + hr = ID3DXRenderToSurface_GetDevice(rts, &test_device); + ok(hr == D3D_OK, "Got result %x, expected %x (D3D_OK)\n", hr, D3D_OK); + ok(test_device == device, "Got result %p, expected %p\n", test_device, device); + + if (hr == D3D_OK) + { + IDirect3DDevice9_Release(device); + } + + /* description */ + hr = ID3DXRenderToSurface_GetDesc(rts, NULL); + ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3DERR_INVALIDCALL)\n", hr, D3DERR_INVALIDCALL); + + hr = ID3DXRenderToSurface_GetDesc(rts, &test_desc); + ok(hr == D3D_OK, "Got result %x, expected 0 (D3D_OK)\n", hr); + + if (hr == D3D_OK) + { + ok(test_desc.Width == desc.Width, "Returned width %d, expected %d\n", test_desc.Width, desc.Width); + ok(test_desc.Height == desc.Height, "Returned height %d, expected %d\n", test_desc.Height, desc.Height); + ok(test_desc.Format == desc.Format, "Returned format %d, expected %d\n", test_desc.Format, desc.Format); + ok(test_desc.DepthStencil == desc.DepthStencil, "Returned depth stencil %d, expected %d\n", + test_desc.DepthStencil, desc.DepthStencil); + ok(test_desc.DepthStencilFormat == desc.DepthStencilFormat, "Returned depth stencil format %d, expected %d\n", + test_desc.DepthStencilFormat, desc.DepthStencilFormat); + } + + ID3DXRenderToSurface_Release(rts); + } +} + START_TEST(core) { HWND wnd; @@ -450,6 +536,7 @@ START_TEST(core) test_ID3DXSprite(device); test_ID3DXFont(device); + test_D3DXCreateRenderToSurface(device); check_release((IUnknown*)device, 0); check_release((IUnknown*)d3d, 0);