Module: wine Branch: master Commit: c5055fb3eb59b951898d7408fae0d9461313e397 URL: http://source.winehq.org/git/wine.git/?a=commit;h=c5055fb3eb59b951898d7408fa...
Author: Stefan Dösinger stefan@codeweavers.com Date: Tue Oct 9 14:42:06 2007 +0200
ddraw: Cope with Init3D failures.
---
dlls/ddraw/ddraw.c | 29 ++++++++++++++++++++++++----- dlls/ddraw/ddraw_private.h | 1 + dlls/ddraw/surface.c | 2 +- 3 files changed, 26 insertions(+), 6 deletions(-)
diff --git a/dlls/ddraw/ddraw.c b/dlls/ddraw/ddraw.c index 7c6bf5f..508832b 100644 --- a/dlls/ddraw/ddraw.c +++ b/dlls/ddraw/ddraw.c @@ -2519,10 +2519,6 @@ IDirectDrawImpl_CreateSurface(IDirectDraw7 *iface, return hr; }
- /* 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 * a primary surface (2D app in 3D mode) or a 3DDEVICE surface (3D app) @@ -2555,10 +2551,32 @@ IDirectDrawImpl_CreateSurface(IDirectDraw7 *iface, hr = IDirectDrawImpl_AttachD3DDevice(This, target); if(hr != D3D_OK) { + IDirectDrawSurfaceImpl *release_surf; ERR("IDirectDrawImpl_AttachD3DDevice failed, hr = %x\n", hr); + *Surf = NULL; + + /* The before created surface structures are in an incomplete state here. + * WineD3D holds the reference on the IParents, and it released them on the failure + * already. So the regular release method implementation would fail on the attempt + * to destroy either the IParents or the swapchain. So free the surface here. + * The surface structure here is a list, not a tree, because onscreen targets + * cannot be cube textures + */ + while(object) + { + release_surf = object; + object = object->complex_array[0]; + IDirectDrawSurfaceImpl_Destroy(release_surf); + } + LeaveCriticalSection(&ddraw_cs); + return hr; } }
+ /* Addref the ddraw interface to keep an reference for each surface */ + IDirectDraw7_AddRef(iface); + object->ifaceToRelease = (IUnknown *) iface; + /* Create a WineD3DTexture if a texture was requested */ if(desc2.ddsCaps.dwCaps & DDSCAPS_TEXTURE) { @@ -3077,7 +3095,8 @@ IDirectDrawImpl_AttachD3DDevice(IDirectDrawImpl *This, D3D7CB_CreateAdditionalSwapChain); if(FAILED(hr)) { - This->wineD3DDevice = NULL; + This->d3d_target = NULL; + This->d3d_initialized = FALSE; return hr; }
diff --git a/dlls/ddraw/ddraw_private.h b/dlls/ddraw/ddraw_private.h index 2f35643..9b78edf 100644 --- a/dlls/ddraw/ddraw_private.h +++ b/dlls/ddraw/ddraw_private.h @@ -273,6 +273,7 @@ const IDirect3DTexture2Vtbl IDirect3DTexture2_Vtbl; const IDirect3DTextureVtbl IDirect3DTexture1_Vtbl;
HRESULT WINAPI IDirectDrawSurfaceImpl_AddAttachedSurface(IDirectDrawSurfaceImpl *This, IDirectDrawSurfaceImpl *Surf); +void IDirectDrawSurfaceImpl_Destroy(IDirectDrawSurfaceImpl *This);
/* Get the number of bytes per pixel for a given surface */ #define PFGET_BPP(pf) (pf.dwFlags&DDPF_PALETTEINDEXED8?1:((pf.dwRGBBitCount+7)/8)) diff --git a/dlls/ddraw/surface.c b/dlls/ddraw/surface.c index a5a0b21..646ea1a 100644 --- a/dlls/ddraw/surface.c +++ b/dlls/ddraw/surface.c @@ -178,7 +178,7 @@ IDirectDrawSurfaceImpl_AddRef(IDirectDrawSurface7 *iface) * This: Surface to free * *****************************************************************************/ -static void IDirectDrawSurfaceImpl_Destroy(IDirectDrawSurfaceImpl *This) +void IDirectDrawSurfaceImpl_Destroy(IDirectDrawSurfaceImpl *This) { TRACE("(%p)\n", This);