Module: wine Branch: refs/heads/master Commit: 01273e7eb67a7bd918a246e0d76f36fd628f6a34 URL: http://source.winehq.org/git/?p=wine.git;a=commit;h=01273e7eb67a7bd918a246e0...
Author: Stefan Dösinger stefandoesinger@gmx.at Date: Sat Jun 17 15:47:52 2006 +0200
ddraw: Palette refcounting fixes + tests.
---
dlls/ddraw/ddraw.c | 21 +++++- dlls/ddraw/palette.c | 1 dlls/ddraw/surface.c | 4 + dlls/ddraw/tests/.gitignore | 1 dlls/ddraw/tests/Makefile.in | 3 + dlls/ddraw/tests/refcount.c | 147 ++++++++++++++++++++++++++++++++++++++++++ 6 files changed, 174 insertions(+), 3 deletions(-) create mode 100644 dlls/ddraw/tests/refcount.c
diff --git a/dlls/ddraw/ddraw.c b/dlls/ddraw/ddraw.c index cdf4d46..5fad1cd 100644 --- a/dlls/ddraw/ddraw.c +++ b/dlls/ddraw/ddraw.c @@ -2950,13 +2950,29 @@ IDirectDrawImpl_CreatePalette(IDirectDra HRESULT hr = DDERR_GENERIC; TRACE("(%p)->(%lx,%p,%p,%p)\n", This, Flags, ColorTable, Palette, pUnkOuter);
- if(pUnkOuter != NULL) return CLASS_E_NOAGGREGATION; /* unchecked */ + if(pUnkOuter != NULL) + { + WARN("pUnkOuter is %p, returning CLASS_E_NOAGGREGATION\n", pUnkOuter); + return CLASS_E_NOAGGREGATION; + } + + /* The refcount test shows that a cooplevel is required for this */ + if(!This->cooperative_level) + { + WARN("No cooperative level set, returning DDERR_NOCOOPERATIVELEVELSET\n"); + return DDERR_NOCOOPERATIVELEVELSET; + }
object = HeapAlloc(GetProcessHeap(), 0, sizeof(IDirectDrawPaletteImpl)); - if(!object) return E_OUTOFMEMORY; + if(!object) + { + ERR("Out of memory when allocating memory for a palette implementation\n"); + return E_OUTOFMEMORY; + }
ICOM_INIT_INTERFACE(object, IDirectDrawPalette, IDirectDrawPalette_Vtbl); object->ref = 1; + object->ddraw_owner = This;
hr = IWineD3DDevice_CreatePalette(This->wineD3DDevice, Flags, ColorTable, &object->wineD3DPalette, (IUnknown *) ICOM_INTERFACE(object, IDirectDrawPalette) ); if(hr != DD_OK) @@ -2965,6 +2981,7 @@ IDirectDrawImpl_CreatePalette(IDirectDra return hr; }
+ IDirectDraw7_AddRef(iface); *Palette = ICOM_INTERFACE(object, IDirectDrawPalette); return DD_OK; } diff --git a/dlls/ddraw/palette.c b/dlls/ddraw/palette.c index 66b8844..97a9ef4 100644 --- a/dlls/ddraw/palette.c +++ b/dlls/ddraw/palette.c @@ -104,6 +104,7 @@ IDirectDrawPaletteImpl_Release(IDirectDr if (ref == 0) { IWineD3DPalette_Release(This->wineD3DPalette); + IDirectDraw7_Release(ICOM_INTERFACE(This->ddraw_owner, IDirectDraw7)); HeapFree(GetProcessHeap(), 0, This); }
diff --git a/dlls/ddraw/surface.c b/dlls/ddraw/surface.c index 212b9b3..5590c80 100644 --- a/dlls/ddraw/surface.c +++ b/dlls/ddraw/surface.c @@ -360,6 +360,10 @@ IDirectDrawSurfaceImpl_Release(IDirectDr } }
+ /* The refcount test shows that the palette is detached when the surface is destroyed */ + IDirectDrawSurface7_SetPalette(ICOM_INTERFACE(This, IDirectDrawSurface7), + NULL); + /* Loop through all complex attached surfaces, * and destroy them */ diff --git a/dlls/ddraw/tests/.gitignore b/dlls/ddraw/tests/.gitignore index 7daa343..348040a 100644 --- a/dlls/ddraw/tests/.gitignore +++ b/dlls/ddraw/tests/.gitignore @@ -2,4 +2,5 @@ Makefile d3d.ok ddrawmodes.ok dsurface.ok +refcount.ok testlist.c diff --git a/dlls/ddraw/tests/Makefile.in b/dlls/ddraw/tests/Makefile.in index d6fc8b1..ec8488f 100644 --- a/dlls/ddraw/tests/Makefile.in +++ b/dlls/ddraw/tests/Makefile.in @@ -9,7 +9,8 @@ EXTRALIBS = -ldxguid CTESTS = \ d3d.c \ ddrawmodes.c \ - dsurface.c + dsurface.c \ + refcount.c
@MAKE_TEST_RULES@
diff --git a/dlls/ddraw/tests/refcount.c b/dlls/ddraw/tests/refcount.c new file mode 100644 index 0000000..466868e --- /dev/null +++ b/dlls/ddraw/tests/refcount.c @@ -0,0 +1,147 @@ +/* + * Some unit tests for ddraw reference counting + * + * Copyright (C) 2006 Stefan Dösinger + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA + */ +#define COBJMACROS + +#include <assert.h> +#include "wine/test.h" +#include "ddraw.h" +#include "d3d.h" +#include "unknwn.h" + +static HRESULT (WINAPI *pDirectDrawCreateEx)(LPGUID,LPVOID*,REFIID,LPUNKNOWN); + +static void init_function_pointers(void) +{ + HMODULE hmod = GetModuleHandleA("ddraw.dll"); + + if(hmod) + { + pDirectDrawCreateEx = (void*)GetProcAddress(hmod, "DirectDrawCreateEx"); + } +} + +unsigned long getRefcount(IUnknown *iface) +{ + IUnknown_AddRef(iface); + return IUnknown_Release(iface); +} + +static void test_ddraw(void) +{ + HRESULT hr; + unsigned long ref; + IDirectDraw7 *DDraw; + IDirectDrawPalette *palette; + IDirectDrawSurface7 *surface; + PALETTEENTRY Table[256]; + DDSURFACEDESC2 ddsd; + + hr = pDirectDrawCreateEx(NULL, (void **) &DDraw, &IID_IDirectDraw7, NULL); + ok(hr == DD_OK || hr==DDERR_NODIRECTDRAWSUPPORT, "DirectDrawCreateEx returned: %lx\n", hr); + if(!DDraw) + { + trace("Couldn't create DDraw interface, skipping tests\n"); + return; + } + + ref = getRefcount( (IUnknown *) DDraw); + ok(ref == 1, "Got refcount %ld, expected 1\n", ref); + + /* Fails without a cooplevel */ + hr = IDirectDraw7_CreatePalette(DDraw, DDPCAPS_ALLOW256 | DDPCAPS_8BIT, Table, &palette, NULL); + ok(hr == DDERR_NOCOOPERATIVELEVELSET, "CreatePalette returned %08lx\n", hr); + + /* This check is before the cooplevel check */ + hr = IDirectDraw7_CreatePalette(DDraw, DDPCAPS_ALLOW256 | DDPCAPS_8BIT, Table, &palette, (void *) 0xdeadbeef); + ok(hr == CLASS_E_NOAGGREGATION, "CreatePalette returned %08lx\n", hr); + + hr = IDirectDraw7_SetCooperativeLevel(DDraw, 0, DDSCL_NORMAL); + ok(hr == DD_OK, "SetCooperativeLevel failed with %08lx\n", hr); + + memset(&ddsd, 0, sizeof(ddsd)); + ddsd.dwSize = sizeof(ddsd); + ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT; + ddsd.dwWidth = 64; + ddsd.dwHeight = 64; + ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN; + ddsd.ddpfPixelFormat.dwSize = sizeof(ddsd.ddpfPixelFormat); + ddsd.ddpfPixelFormat.dwFlags = DDPF_PALETTEINDEXED8 | DDPF_RGB; + ddsd.ddpfPixelFormat.dwRGBBitCount = 8; + + hr = IDirectDraw7_CreateSurface(DDraw, &ddsd, &surface, NULL); + ok(hr == DD_OK, "CreateSurface failed with %08lx\n", hr); + + /* DDraw refcount increased by 1 */ + ref = getRefcount( (IUnknown *) DDraw); + ok(ref == 2, "Got refcount %ld, expected 2\n", ref); + + /* Surface refcount starts with 1 */ + ref = getRefcount( (IUnknown *) surface); + ok(ref == 1, "Got refcount %ld, expected 1\n", ref); + + hr = IDirectDraw7_CreatePalette(DDraw, DDPCAPS_ALLOW256 | DDPCAPS_8BIT, Table, &palette, NULL); + ok(hr == DD_OK, "CreatePalette returned %08lx\n", hr); + + /* DDraw refcount increased by 1 */ + ref = getRefcount( (IUnknown *) DDraw); + ok(ref == 3, "Got refcount %ld, expected 3\n", ref); + + /* Palette starts with 1 */ + ref = getRefcount( (IUnknown *) palette); + ok(ref == 1, "Got refcount %ld, expected 1\n", ref); + + /* Test attaching a palette to a surface */ + hr = IDirectDrawSurface7_SetPalette(surface, palette); + ok(hr == DD_OK, "IDirectDrawSurface_SetPalette failed with %08lx\n", hr); + + /* Palette refcount increased, surface stays the same */ + ref = getRefcount( (IUnknown *) palette); + ok(ref == 2, "Got refcount %ld, expected 2\n", ref); + ref = getRefcount( (IUnknown *) surface); + ok(ref == 1, "Got refcount %ld, expected 1\n", ref); + + IDirectDrawSurface7_Release(surface); + /* Incresed before - decrease now */ + ref = getRefcount( (IUnknown *) DDraw); + ok(ref == 2, "Got refcount %ld, expected 2\n", ref); + + /* Releasing the surface detaches the palette */ + ref = getRefcount( (IUnknown *) palette); + ok(ref == 1, "Got refcount %ld, expected 1\n", ref); + + IDirectDrawPalette_Release(palette); + + /* Incresed before - decrease now */ + ref = getRefcount( (IUnknown *) DDraw); + ok(ref == 1, "Got refcount %ld, expected 1\n", ref); + + IDirectDraw7_Release(DDraw); +} + +START_TEST(refcount) +{ + init_function_pointers(); + if(!pDirectDrawCreateEx) + { + trace("function DirectDrawCreateEx not available, skipping tests\n"); + return; + } + test_ddraw(); +}