Commit 0a812957 authored by Stefan Dösinger's avatar Stefan Dösinger Committed by Alexandre Julliard

ddraw: Split up the ddraw refcount.

parent d6900948
......@@ -131,7 +131,13 @@ IDirectDrawImpl_QueryInterface(IDirectDraw7 *iface,
TRACE("(%p) Returning IDirectDraw interface at %p\n", This, *obj);
}
/* Direct3D */
/* Direct3D
* The refcount unit test revealed that an IDirect3D7 interface can only be queried
* from a DirectDraw object that was created as an IDirectDraw7 interface. No idea
* who had this idea and why. The older interfaces can query and IDirect3D version
* because they are all created as IDirectDraw(1). This isn't really crucial behavior,
* and messy to implement with the common creation function, so it has been left out here.
*/
else if ( IsEqualGUID( &IID_IDirect3D , refiid ) ||
IsEqualGUID( &IID_IDirect3D2 , refiid ) ||
IsEqualGUID( &IID_IDirect3D3 , refiid ) ||
......@@ -197,17 +203,30 @@ IDirectDrawImpl_QueryInterface(IDirectDraw7 *iface,
/*****************************************************************************
* IDirectDraw7::AddRef
*
* Increases the interfaces refcount. Used for version 1, 2, 4 and 7
* Increases the interfaces refcount, basically
*
* DDraw refcounting is a bit tricky. The different DirectDraw interface
* versions have individual refcounts, but the IDirect3D interfaces do not.
* All interfaces are from one object, that means calling QueryInterface on an
* IDirectDraw7 interface for an IDirectDraw4 interface does not create a new
* IDirectDrawImpl object.
*
* That means all AddRef and Release implementations of IDirectDrawX work
* with their own counter, and IDirect3DX::AddRef thunk to IDirectDraw (1),
* except of IDirect3D7 which thunks to IDirectDraw7
*
* Returns: The new refcount
*
*****************************************************************************/
static ULONG WINAPI
IDirectDrawImpl_AddRef(IDirectDraw7 *iface)
{
ICOM_THIS_FROM(IDirectDrawImpl, IDirectDraw7, iface);
ULONG ref = InterlockedIncrement(&This->ref);
ULONG ref = InterlockedIncrement(&This->ref7);
TRACE("(%p) : incrementing from %lu.\n", This, ref -1);
TRACE("(%p) : incrementing IDirectDraw7 refcount from %lu.\n", This, ref -1);
if(ref == 1) InterlockedIncrement(&This->numIfaces);
return ref;
}
......@@ -215,8 +234,8 @@ IDirectDrawImpl_AddRef(IDirectDraw7 *iface)
/*****************************************************************************
* IDirectDrawImpl_Destroy
*
* Destroys a ddraw object. This is to share code between normal Release
* and the dll unload cleanup code
* Destroys a ddraw object if all refcounts are 0. This is to share code
* between the IDirectDrawX::Release functions
*
* Params:
* This: DirectDraw object to destroy
......@@ -225,45 +244,49 @@ IDirectDrawImpl_AddRef(IDirectDraw7 *iface)
void
IDirectDrawImpl_Destroy(IDirectDrawImpl *This)
{
IDirectDrawImpl *prev;
IDirectDrawImpl *prev;
TRACE("(%p)\n", This);
/* Clear the cooplevel to restore window and display mode */
IDirectDraw7_SetCooperativeLevel(ICOM_INTERFACE(This, IDirectDraw7),
NULL,
DDSCL_NORMAL);
/* Destroy the device window if we created one */
if(This->devicewindow != 0)
{
TRACE(" (%p) Destroying the device window %p\n", This, This->devicewindow);
DestroyWindow(This->devicewindow);
This->devicewindow = 0;
}
/* Destroy the device window if we created one */
if(This->devicewindow != 0)
{
TRACE(" (%p) Destroying the device window %p\n", This, This->devicewindow);
DestroyWindow(This->devicewindow);
This->devicewindow = 0;
}
/* Unregister the window class */
UnregisterClassA(This->classname, 0);
/* Unregister the window class */
UnregisterClassA(This->classname, 0);
/* Unchain it from the ddraw list */
if(ddraw_list == This)
{
ddraw_list = This->next;
/* No need to search for a predecessor here */
}
else
{
for(prev = ddraw_list; prev; prev = prev->next)
if(prev->next == This) break;
/* Unchain it from the ddraw list */
if(ddraw_list == This)
{
ddraw_list = This->next;
/* No need to search for a predecessor here */
}
else
{
for(prev = ddraw_list; prev; prev = prev->next)
if(prev->next == This) break;
if(prev)
prev->next = This->next;
else
ERR("Didn't find the previous ddraw element in the list\n");
}
if(prev)
prev->next = This->next;
else
ERR("Didn't find the previous ddraw element in the list\n");
}
/* Release the attached WineD3D stuff */
IWineD3DDevice_Release(This->wineD3DDevice);
IWineD3D_Release(This->wineD3D);
/* Release the attached WineD3D stuff */
IWineD3DDevice_Release(This->wineD3DDevice);
IWineD3D_Release(This->wineD3D);
/* Now free the object */
HeapFree(GetProcessHeap(), 0, This);
/* Now free the object */
HeapFree(GetProcessHeap(), 0, This);
}
/*****************************************************************************
* IDirectDraw7::Release
*
......@@ -275,21 +298,14 @@ static ULONG WINAPI
IDirectDrawImpl_Release(IDirectDraw7 *iface)
{
ICOM_THIS_FROM(IDirectDrawImpl, IDirectDraw7, iface);
ULONG ref = InterlockedDecrement(&This->ref);
ULONG ref = InterlockedDecrement(&This->ref7);
TRACE("(%p)->() decrementing from %lu.\n", This, ref +1);
TRACE("(%p)->() decrementing IDirectDraw7 refcount from %lu.\n", This, ref +1);
if (ref == 0)
if(ref == 0)
{
/* No need to restore the display mode - it's done by SetCooperativeLevel */
IDirectDraw7_SetCooperativeLevel(ICOM_INTERFACE(This, IDirectDraw7),
NULL,
DDSCL_NORMAL);
/* This is for the dll cleanup code in DllMain() */
if(!This->DoNotDestroy)
IDirectDrawImpl_Destroy(This);
ULONG ifacecount = InterlockedDecrement(&This->numIfaces);
if(ifacecount == 0) IDirectDrawImpl_Destroy(This);
}
return ref;
......@@ -2337,6 +2353,7 @@ IDirectDrawImpl_CreateSurface(IDirectDraw7 *iface,
/* Addref the ddraw interface to keep an reference for each surface */
IDirectDraw7_AddRef(iface);
object->ifaceToRelease = (IUnknown *) iface;
/* If the implementation is OpenGL and there's no d3ddevice, attach a d3ddevice
* But attach the d3ddevice only if the currently created surface was
......
......@@ -90,7 +90,8 @@ struct IDirectDrawImpl
ICOM_VFIELD_MULTI(IDirect3D2);
ICOM_VFIELD_MULTI(IDirect3D);
LONG ref;
/* See comment in IDirectDraw::AddRef */
LONG ref7, ref4, ref2, ref1, numIfaces;
/* WineD3D linkage */
IWineD3D *wineD3D;
......@@ -143,7 +144,6 @@ struct IDirectDrawImpl
/* For the dll unload cleanup code */
IDirectDrawImpl *next;
BOOL DoNotDestroy;
LONG surfaces;
};
......@@ -202,6 +202,7 @@ struct IDirectDrawSurfaceImpl
ICOM_VFIELD_MULTI(IDirect3DTexture);
LONG ref;
IUnknown *ifaceToRelease;
int version;
......
......@@ -17,15 +17,32 @@
*/
#include "config.h"
#include "wine/port.h"
#include <assert.h>
#include <stdarg.h>
#include <string.h>
#include <stdlib.h>
#define COBJMACROS
#define NONAMELESSUNION
#include "windef.h"
#include "winbase.h"
#include "winnls.h"
#include "winerror.h"
#include "wingdi.h"
#include "wine/exception.h"
#include "excpt.h"
#include "ddraw.h"
#include "d3d.h"
#include "ddraw_private.h"
#include "ddcomimpl.h"
#include "wine/debug.h"
WINE_DEFAULT_DEBUG_CHANNEL(ddraw_thunk);
WINE_DECLARE_DEBUG_CHANNEL(ddraw);
static HRESULT WINAPI
IDirectDrawImpl_QueryInterface(LPDIRECTDRAW This, REFIID iid, LPVOID *ppObj)
......@@ -56,51 +73,93 @@ IDirectDraw4Impl_QueryInterface(LPDIRECTDRAW4 This, REFIID iid, LPVOID *ppObj)
}
static ULONG WINAPI
IDirectDrawImpl_AddRef(LPDIRECTDRAW This)
IDirectDrawImpl_AddRef(LPDIRECTDRAW iface)
{
return IDirectDraw7_AddRef(COM_INTERFACE_CAST(IDirectDrawImpl,
IDirectDraw, IDirectDraw7,
This));
ICOM_THIS_FROM(IDirectDrawImpl, IDirectDraw, iface);
ULONG ref = InterlockedIncrement(&This->ref1);
TRACE("(%p) : incrementing IDirectDraw refcount from %lu.\n", This, ref -1);
if(ref == 1) InterlockedIncrement(&This->numIfaces);
return ref;
}
static ULONG WINAPI
IDirectDraw2Impl_AddRef(LPDIRECTDRAW2 This)
IDirectDraw2Impl_AddRef(LPDIRECTDRAW2 iface)
{
return IDirectDraw7_AddRef(COM_INTERFACE_CAST(IDirectDrawImpl,
IDirectDraw2, IDirectDraw7,
This));
ICOM_THIS_FROM(IDirectDrawImpl, IDirectDraw2, iface);
ULONG ref = InterlockedIncrement(&This->ref2);
TRACE("(%p) : incrementing IDirectDraw2 refcount from %lu.\n", This, ref -1);
if(ref == 1) InterlockedIncrement(&This->numIfaces);
return ref;
}
static ULONG WINAPI
IDirectDraw4Impl_AddRef(LPDIRECTDRAW4 This)
IDirectDraw4Impl_AddRef(LPDIRECTDRAW4 iface)
{
return IDirectDraw7_AddRef(COM_INTERFACE_CAST(IDirectDrawImpl,
IDirectDraw4, IDirectDraw7,
This));
ICOM_THIS_FROM(IDirectDrawImpl, IDirectDraw4, iface);
ULONG ref = InterlockedIncrement(&This->ref4);
TRACE("(%p) : incrementing IDirectDraw4 refcount from %lu.\n", This, ref -1);
if(ref == 1) InterlockedIncrement(&This->numIfaces);
return ref;
}
static ULONG WINAPI
IDirectDrawImpl_Release(LPDIRECTDRAW This)
IDirectDrawImpl_Release(LPDIRECTDRAW iface)
{
return IDirectDraw7_Release(COM_INTERFACE_CAST(IDirectDrawImpl,
IDirectDraw, IDirectDraw7,
This));
ICOM_THIS_FROM(IDirectDrawImpl, IDirectDraw, iface);
ULONG ref = InterlockedDecrement(&This->ref1);
TRACE_(ddraw)("(%p)->() decrementing IDirectDraw refcount from %lu.\n", This, ref +1);
if(ref == 0)
{
ULONG ifacecount = InterlockedDecrement(&This->numIfaces);
if(ifacecount == 0) IDirectDrawImpl_Destroy(This);
}
return ref;
}
static ULONG WINAPI
IDirectDraw2Impl_Release(LPDIRECTDRAW2 This)
IDirectDraw2Impl_Release(LPDIRECTDRAW2 iface)
{
return IDirectDraw7_Release(COM_INTERFACE_CAST(IDirectDrawImpl,
IDirectDraw2, IDirectDraw7,
This));
ICOM_THIS_FROM(IDirectDrawImpl, IDirectDraw2, iface);
ULONG ref = InterlockedDecrement(&This->ref2);
TRACE_(ddraw)("(%p)->() decrementing IDirectDraw2 refcount from %lu.\n", This, ref +1);
if(ref == 0)
{
ULONG ifacecount = InterlockedDecrement(&This->numIfaces);
if(ifacecount == 0) IDirectDrawImpl_Destroy(This);
}
return ref;
}
static ULONG WINAPI
IDirectDraw4Impl_Release(LPDIRECTDRAW4 This)
IDirectDraw4Impl_Release(LPDIRECTDRAW4 iface)
{
return IDirectDraw7_Release(COM_INTERFACE_CAST(IDirectDrawImpl,
IDirectDraw4, IDirectDraw7,
This));
ICOM_THIS_FROM(IDirectDrawImpl, IDirectDraw4, iface);
ULONG ref = InterlockedDecrement(&This->ref4);
TRACE_(ddraw)("(%p)->() decrementing IDirectDraw4 refcount from %lu.\n", This, ref +1);
if(ref == 0)
{
ULONG ifacecount = InterlockedDecrement(&This->numIfaces);
if(ifacecount == 0) IDirectDrawImpl_Destroy(This);
}
return ref;
}
static HRESULT WINAPI
......@@ -169,11 +228,20 @@ IDirectDrawImpl_CreatePalette(LPDIRECTDRAW This, DWORD dwFlags,
LPDIRECTDRAWPALETTE *ppPalette,
IUnknown *pUnkOuter)
{
return IDirectDraw7_CreatePalette(COM_INTERFACE_CAST(IDirectDrawImpl,
HRESULT hr;
hr = IDirectDraw7_CreatePalette(COM_INTERFACE_CAST(IDirectDrawImpl,
IDirectDraw,
IDirectDraw7,
This),
dwFlags, pEntries, ppPalette, pUnkOuter);
if(SUCCEEDED(hr) && *ppPalette)
{
IDirectDraw7_Release(COM_INTERFACE_CAST(IDirectDrawImpl,
IDirectDraw,
IDirectDraw7,
This));
}
return hr;
}
static HRESULT WINAPI
......@@ -182,11 +250,19 @@ IDirectDraw2Impl_CreatePalette(LPDIRECTDRAW2 This, DWORD dwFlags,
LPDIRECTDRAWPALETTE *ppPalette,
IUnknown *pUnkOuter)
{
HRESULT hr;
return IDirectDraw7_CreatePalette(COM_INTERFACE_CAST(IDirectDrawImpl,
IDirectDraw2,
IDirectDraw7,
This),
dwFlags, pEntries, ppPalette, pUnkOuter);
if(SUCCEEDED(hr) && *ppPalette)
{
IDirectDraw7_Release(COM_INTERFACE_CAST(IDirectDrawImpl,
IDirectDraw,
IDirectDraw7,
This));
}
}
static HRESULT WINAPI
......@@ -195,11 +271,19 @@ IDirectDraw4Impl_CreatePalette(LPDIRECTDRAW4 This, DWORD dwFlags,
LPDIRECTDRAWPALETTE *ppPalette,
IUnknown *pUnkOuter)
{
HRESULT hr;
return IDirectDraw7_CreatePalette(COM_INTERFACE_CAST(IDirectDrawImpl,
IDirectDraw4,
IDirectDraw7,
This),
dwFlags, pEntries, ppPalette, pUnkOuter);
if(SUCCEEDED(hr) && *ppPalette)
{
IDirectDraw7_Release(COM_INTERFACE_CAST(IDirectDrawImpl,
IDirectDraw,
IDirectDraw7,
This));
}
}
static HRESULT WINAPI
......@@ -226,9 +310,15 @@ IDirectDrawImpl_CreateSurface(LPDIRECTDRAW This, LPDDSURFACEDESC pSDesc,
pSurface7);
impl = ICOM_OBJECT(IDirectDrawSurfaceImpl, IDirectDrawSurface7, pSurface7);
if(impl)
if(SUCCEEDED(hr) && impl)
{
impl->version = 1;
IDirectDraw7_Release(COM_INTERFACE_CAST(IDirectDrawImpl,
IDirectDraw,
IDirectDraw7,
This));
IDirectDraw_AddRef(This);
impl->ifaceToRelease = (IUnknown *) This;
}
return hr;
......@@ -256,9 +346,15 @@ IDirectDraw2Impl_CreateSurface(LPDIRECTDRAW2 This, LPDDSURFACEDESC pSDesc,
pSurface7);
impl = ICOM_OBJECT(IDirectDrawSurfaceImpl, IDirectDrawSurface7, pSurface7);
if(impl)
if(SUCCEEDED(hr) && impl)
{
impl->version = 2;
IDirectDraw7_Release(COM_INTERFACE_CAST(IDirectDrawImpl,
IDirectDraw2,
IDirectDraw7,
This));
IDirectDraw2_AddRef(This);
impl->ifaceToRelease = (IUnknown *) This;
}
return hr;
......@@ -280,9 +376,15 @@ IDirectDraw4Impl_CreateSurface(LPDIRECTDRAW4 This, LPDDSURFACEDESC2 pSDesc,
(LPDIRECTDRAWSURFACE7 *)ppSurface,
pUnkOuter);
impl = ICOM_OBJECT(IDirectDrawSurfaceImpl, IDirectDrawSurface7, *ppSurface);
if(impl)
if(SUCCEEDED(hr) && impl)
{
impl->version = 4;
IDirectDraw7_Release(COM_INTERFACE_CAST(IDirectDrawImpl,
IDirectDraw4,
IDirectDraw7,
This));
IDirectDraw4_AddRef(This);
impl->ifaceToRelease = (IUnknown *) This;
}
return hr;
}
......
......@@ -43,10 +43,9 @@
WINE_DEFAULT_DEBUG_CHANNEL(d3d7);
/*****************************************************************************
* IUnknown Methods. Common for Version 1, 2, 3 and 7
* IDirect3D7::QueryInterface
*
* These are thunks which relay to IDirectDraw. See ddraw.c for
* details
* QueryInterface implementation with thunks to IDirectDraw7
*
*****************************************************************************/
static HRESULT WINAPI
......@@ -101,11 +100,30 @@ Thunk_IDirect3DImpl_1_QueryInterface(IDirect3D *iface,
obj);
}
/*****************************************************************************
* IDirect3D7::AddRef
*
* DirectDraw refcounting is a bit odd. Every version of the ddraw interface
* has its own refcount, but IDirect3D 1/2/3 refcounts are linked to
* IDirectDraw, and IDirect3D7 is linked to IDirectDraw7
*
* IDirect3D7 -> IDirectDraw7
* IDirect3D3 -> IDirectDraw
* IDirect3D2 -> IDirectDraw
* IDirect3D -> IDirectDraw
*
* So every AddRef implementation thunks to a different interface, and the
* IDirectDrawX::AddRef implementations have different counters...
*
* Returns
* The new refcount
*
*****************************************************************************/
static ULONG WINAPI
Thunk_IDirect3DImpl_7_AddRef(IDirect3D7 *iface)
{
ICOM_THIS_FROM(IDirectDrawImpl, IDirect3D7, iface);
TRACE("(%p) : Thunking to IDirectDraw7\n", This);
TRACE("(%p) : Thunking to IDirectDraw7.\n", This);
return IDirectDraw7_AddRef(ICOM_INTERFACE(This, IDirectDraw7));
}
......@@ -114,34 +132,42 @@ static ULONG WINAPI
Thunk_IDirect3DImpl_3_AddRef(IDirect3D3 *iface)
{
ICOM_THIS_FROM(IDirectDrawImpl, IDirect3D3, iface);
TRACE("(%p) : Thunking to IDirectDraw7\n", This);
TRACE("(%p) : Thunking to IDirectDraw.\n", This);
return IDirectDraw7_AddRef(ICOM_INTERFACE(This, IDirectDraw7));
return IDirectDraw_AddRef(ICOM_INTERFACE(This, IDirectDraw));
}
static ULONG WINAPI
Thunk_IDirect3DImpl_2_AddRef(IDirect3D2 *iface)
{
ICOM_THIS_FROM(IDirectDrawImpl, IDirect3D2, iface);
TRACE("(%p) : Thunking to IDirectDraw7\n", This);
TRACE("(%p) : Thunking to IDirectDraw.\n", This);
return IDirectDraw7_AddRef(ICOM_INTERFACE(This, IDirectDraw7));
return IDirectDraw_AddRef(ICOM_INTERFACE(This, IDirectDraw));
}
static ULONG WINAPI
Thunk_IDirect3DImpl_1_AddRef(IDirect3D *iface)
{
ICOM_THIS_FROM(IDirectDrawImpl, IDirect3D, iface);
TRACE("(%p) : Thunking to IDirectDraw7\n", This);
TRACE("(%p) : Thunking to IDirectDraw.\n", This);
return IDirectDraw7_AddRef(ICOM_INTERFACE(This, IDirectDraw7));
return IDirectDraw_AddRef(ICOM_INTERFACE(This, IDirectDraw));
}
/*****************************************************************************
* IDirect3D7::Release
*
* Same story as IDirect3D7::AddRef
*
* Returns: The new refcount
*
*****************************************************************************/
static ULONG WINAPI
Thunk_IDirect3DImpl_7_Release(IDirect3D7 *iface)
{
ICOM_THIS_FROM(IDirectDrawImpl, IDirect3D7, iface);
TRACE("(%p) : Thunking to IDirectDraw7", This);
TRACE("(%p) : Thunking to IDirectDraw7.\n", This);
return IDirectDraw7_Release(ICOM_INTERFACE(This, IDirectDraw7));
}
......@@ -150,27 +176,27 @@ static ULONG WINAPI
Thunk_IDirect3DImpl_3_Release(IDirect3D3 *iface)
{
ICOM_THIS_FROM(IDirectDrawImpl, IDirect3D3, iface);
TRACE("(%p) : Thunking to IDirectDraw7", This);
TRACE("(%p) : Thunking to IDirectDraw.\n", This);
return IDirectDraw7_Release(ICOM_INTERFACE(This, IDirectDraw7));
return IDirectDraw_Release(ICOM_INTERFACE(This, IDirectDraw));
}
static ULONG WINAPI
Thunk_IDirect3DImpl_2_Release(IDirect3D2 *iface)
{
ICOM_THIS_FROM(IDirectDrawImpl, IDirect3D2, iface);
TRACE("(%p) : Thunking to IDirectDraw7", This);
TRACE("(%p) : Thunking to IDirectDraw.\n", This);
return IDirectDraw7_Release(ICOM_INTERFACE(This, IDirectDraw7));
return IDirectDraw_Release(ICOM_INTERFACE(This, IDirectDraw));
}
static ULONG WINAPI
Thunk_IDirect3DImpl_1_Release(IDirect3D *iface)
{
ICOM_THIS_FROM(IDirectDrawImpl, IDirect3D, iface);
TRACE("(%p) : Thunking to IDirectDraw7", This);
TRACE("(%p) : Thunking to IDirectDraw.\n", This);
return IDirectDraw7_Release(ICOM_INTERFACE(This, IDirectDraw7));
return IDirectDraw_Release(ICOM_INTERFACE(This, IDirectDraw));
}
/*****************************************************************************
......
......@@ -135,7 +135,6 @@ DDRAW_Create(GUID *guid,
ICOM_INIT_INTERFACE(This, IDirect3D2, IDirect3D2_Vtbl);
ICOM_INIT_INTERFACE(This, IDirect3D3, IDirect3D3_Vtbl);
ICOM_INIT_INTERFACE(This, IDirect3D7, IDirect3D7_Vtbl);
This->ref = 1;
/* See comments in IDirectDrawImpl_CreateNewSurface for a description
* of this member.
......@@ -285,9 +284,10 @@ DDRAW_Create(GUID *guid,
This->next = ddraw_list;
ddraw_list = This;
/* Call QueryInterface to get the pointer to the requested interface */
/* Call QueryInterface to get the pointer to the requested interface. This also initializes
* The required refcount
*/
hr = IDirectDraw7_QueryInterface( ICOM_INTERFACE(This, IDirectDraw7), iid, DD);
IDirectDraw7_Release( ICOM_INTERFACE(This, IDirectDraw7) );
if(SUCCEEDED(hr)) return DD_OK;
err_out:
......@@ -843,9 +843,13 @@ DllMain(HINSTANCE hInstDLL,
DDSURFACEDESC2 desc;
int i;
WARN("DDraw %p has a refcount of %ld\n", ddraw, ddraw->ref);
WARN("DDraw %p has a refcount of %ld\n", ddraw, ddraw->ref7 + ddraw->ref4 + ddraw->ref2 + ddraw->ref1);
ddraw->DoNotDestroy = TRUE; /* Avoid to destroy the object too early */
/* Add references to each interface to avoid freeing them unexpectadely */
IDirectDraw_AddRef(ICOM_INTERFACE(ddraw, IDirectDraw));
IDirectDraw2_AddRef(ICOM_INTERFACE(ddraw, IDirectDraw2));
IDirectDraw4_AddRef(ICOM_INTERFACE(ddraw, IDirectDraw4));
IDirectDraw7_AddRef(ICOM_INTERFACE(ddraw, IDirectDraw7));
/* Does a D3D device exist? Destroy it
* TODO: Destroy all Vertex buffers, Lights, Materials
......@@ -877,12 +881,13 @@ DllMain(HINSTANCE hInstDLL,
if(ddraw->surfaces > 0)
ERR("DDraw %p still has %ld surfaces attached\n", ddraw, ddraw->surfaces);
/* Restore the cooperative level */
IDirectDraw7_SetCooperativeLevel(ICOM_INTERFACE(ddraw, IDirectDraw7),
NULL,
DDSCL_NORMAL);
ddraw->DoNotDestroy = FALSE;
IDirectDrawImpl_Destroy(ddraw);
/* Release all hanging references to destroy the objects. This
* restores the screen mode too
*/
while(IDirectDraw_Release(ICOM_INTERFACE(ddraw, IDirectDraw)));
while(IDirectDraw2_Release(ICOM_INTERFACE(ddraw, IDirectDraw2)));
while(IDirectDraw4_Release(ICOM_INTERFACE(ddraw, IDirectDraw4)));
while(IDirectDraw7_Release(ICOM_INTERFACE(ddraw, IDirectDraw7)));
}
}
}
......
......@@ -291,6 +291,7 @@ IDirectDrawSurfaceImpl_Release(IDirectDrawSurface7 *iface)
IDirectDrawSurfaceImpl *surf;
IDirectDrawImpl *ddraw;
IUnknown *ifaceToRelease = This->ifaceToRelease;
/* Destroy all complex attached surfaces
* Therefore, start with the first surface,
......@@ -385,7 +386,7 @@ IDirectDrawSurfaceImpl_Release(IDirectDrawSurface7 *iface)
IDirectDrawSurfaceImpl_Destroy(This);
/* Reduce the ddraw refcount */
IDirectDraw7_Release(ICOM_INTERFACE(ddraw, IDirectDraw7));
IUnknown_Release(ifaceToRelease);
}
return ref;
......@@ -1627,13 +1628,32 @@ IDirectDrawSurfaceImpl_GetDDInterface(IDirectDrawSurface7 *iface,
{
ICOM_THIS_FROM(IDirectDrawSurfaceImpl, IDirectDrawSurface7, iface);
TRACE("(%p)->(%p)\n",This,DD);
/* It is not quite correct to use the same lpVtable for the different
* IDirectDrawSurface versions because the GetDDInterface return different interfaces
*/
FIXME("(%p)->(%p)\n",This,DD);
if(!DD)
return DDERR_INVALIDPARAMS;
*((IDirectDraw7 **) DD) = ICOM_INTERFACE(This->ddraw, IDirectDraw7);
IDirectDraw7_AddRef( (IDirectDraw7 *) *DD);
switch(This->version)
{
case 7:
*((IDirectDraw7 **) DD) = ICOM_INTERFACE(This->ddraw, IDirectDraw7);
IDirectDraw7_AddRef(*(IDirectDraw7 **) DD);
break;
case 4:
*((IDirectDraw4 **) DD) = ICOM_INTERFACE(This->ddraw, IDirectDraw4);
IDirectDraw4_AddRef(*(IDirectDraw4 **) DD);
case 2:
case 1:
*((IDirectDraw **) DD) = ICOM_INTERFACE(This->ddraw, IDirectDraw);
IDirectDraw_AddRef( *(IDirectDraw **) DD);
break;
}
return DD_OK;
}
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment