Module: wine Branch: master Commit: f0be44c82dca8760c787576e1bdf76383bac3ee7 URL: http://source.winehq.org/git/wine.git/?a=commit;h=f0be44c82dca8760c787576e1b...
Author: Andrew Eikum aeikum@codeweavers.com Date: Wed May 9 08:48:56 2012 -0500
dsound: Don't destroy primary buffer until device is released.
---
dlls/dsound/buffer.c | 44 ++++++++++++++++++++++++++--------------- dlls/dsound/dsound.c | 5 ---- dlls/dsound/dsound_private.h | 1 + dlls/dsound/primary.c | 33 +++++++++++++++++++++++------- dlls/dsound/sound3d.c | 9 ++++--- dlls/dsound/tests/dsound.c | 9 ++++++++ 6 files changed, 68 insertions(+), 33 deletions(-)
diff --git a/dlls/dsound/buffer.c b/dlls/dsound/buffer.c index 5f9e455..08f4ba7 100644 --- a/dlls/dsound/buffer.c +++ b/dlls/dsound/buffer.c @@ -327,16 +327,22 @@ static ULONG WINAPI IDirectSoundBufferImpl_AddRef(IDirectSoundBuffer8 *iface) static ULONG WINAPI IDirectSoundBufferImpl_Release(IDirectSoundBuffer8 *iface) { IDirectSoundBufferImpl *This = impl_from_IDirectSoundBuffer8(iface); - ULONG ref = InterlockedDecrement(&This->ref); - - TRACE("(%p) ref was %d\n", This, ref + 1); + ULONG ref; + + if (is_primary_buffer(This)){ + ref = capped_refcount_dec(&This->ref); + if(!ref) + capped_refcount_dec(&This->numIfaces); + TRACE("(%p) ref is now: %d\n", This, ref); + return ref; + }
- if (!ref && !InterlockedDecrement(&This->numIfaces)) { - if (is_primary_buffer(This)) - primarybuffer_destroy(This); - else + ref = InterlockedDecrement(&This->ref); + if (!ref && !InterlockedDecrement(&This->numIfaces)) secondarybuffer_destroy(This); - } + + TRACE("(%p) ref is now %d\n", This, ref); + return ref; }
@@ -1077,16 +1083,22 @@ static ULONG WINAPI IKsPropertySetImpl_AddRef(IKsPropertySet *iface) static ULONG WINAPI IKsPropertySetImpl_Release(IKsPropertySet *iface) { IDirectSoundBufferImpl *This = impl_from_IKsPropertySet(iface); - ULONG ref = InterlockedDecrement(&This->refiks); + ULONG ref; + + if (is_primary_buffer(This)){ + ref = capped_refcount_dec(&This->refiks); + if(!ref) + capped_refcount_dec(&This->numIfaces); + TRACE("(%p) ref is now: %d\n", This, ref); + return ref; + }
- TRACE("(%p) ref was %d\n", This, ref + 1); + ref = InterlockedDecrement(&This->refiks); + if (!ref && !InterlockedDecrement(&This->numIfaces)) + secondarybuffer_destroy(This); + + TRACE("(%p) ref is now %d\n", This, ref);
- if (!ref && !InterlockedDecrement(&This->numIfaces)) { - if (is_primary_buffer(This)) - primarybuffer_destroy(This); - else - secondarybuffer_destroy(This); - } return ref; }
diff --git a/dlls/dsound/dsound.c b/dlls/dsound/dsound.c index 91184c9..2429042 100644 --- a/dlls/dsound/dsound.c +++ b/dlls/dsound/dsound.c @@ -1255,11 +1255,6 @@ ULONG DirectSoundDevice_Release(DirectSoundDevice * device) secondarybuffer_destroy(device->buffers[i]); }
- if (device->primary) { - WARN("primary buffer not released\n"); - IDirectSoundBuffer8_Release((LPDIRECTSOUNDBUFFER8)device->primary); - } - hr = DSOUND_PrimaryDestroy(device); if (hr != DS_OK) WARN("DSOUND_PrimaryDestroy failed\n"); diff --git a/dlls/dsound/dsound_private.h b/dlls/dsound/dsound_private.h index 8c6f60b..bed6959 100644 --- a/dlls/dsound/dsound_private.h +++ b/dlls/dsound/dsound_private.h @@ -288,6 +288,7 @@ HRESULT primarybuffer_create(DirectSoundDevice *device, IDirectSoundBufferImpl * const DSBUFFERDESC *dsbd) DECLSPEC_HIDDEN; void primarybuffer_destroy(IDirectSoundBufferImpl *This) DECLSPEC_HIDDEN; HRESULT primarybuffer_SetFormat(DirectSoundDevice *device, LPCWAVEFORMATEX wfex) DECLSPEC_HIDDEN; +LONG capped_refcount_dec(LONG *ref) DECLSPEC_HIDDEN;
/* duplex.c */
diff --git a/dlls/dsound/primary.c b/dlls/dsound/primary.c index c39da8a..b5a09f8 100644 --- a/dlls/dsound/primary.c +++ b/dlls/dsound/primary.c @@ -258,6 +258,13 @@ HRESULT DSOUND_PrimaryDestroy(DirectSoundDevice *device) EnterCriticalSection(&(device->mixlock));
DSOUND_PrimaryClose(device); + + if(device->primary && (device->primary->ref || device->primary->numIfaces)) + WARN("Destroying primary buffer while references held (%u %u)\n", device->primary->ref, device->primary->numIfaces); + + HeapFree(GetProcessHeap(), 0, device->primary); + device->primary = NULL; + HeapFree(GetProcessHeap(),0,device->pwfx); device->pwfx=NULL;
@@ -756,21 +763,31 @@ static ULONG WINAPI PrimaryBufferImpl_AddRef(IDirectSoundBuffer *iface) return ref; }
-void primarybuffer_destroy(IDirectSoundBufferImpl *This) +/* Decreases *out by 1 to no less than 0. + * Returns the new value of *out. */ +LONG capped_refcount_dec(LONG *out) { - This->device->primary = NULL; - HeapFree(GetProcessHeap(), 0, This); - TRACE("(%p) released\n", This); + LONG ref, oldref; + do { + ref = *out; + if(!ref) + return 0; + oldref = InterlockedCompareExchange(out, ref - 1, ref); + } while(oldref != ref); + return ref - 1; }
static ULONG WINAPI PrimaryBufferImpl_Release(IDirectSoundBuffer *iface) { IDirectSoundBufferImpl *This = impl_from_IDirectSoundBuffer(iface); - DWORD ref = InterlockedDecrement(&(This->ref)); - TRACE("(%p) ref was %d\n", This, ref + 1); + ULONG ref; + + ref = capped_refcount_dec(&This->ref); + if(!ref) + capped_refcount_dec(&This->numIfaces); + + TRACE("(%p) primary ref is now %d\n", This, ref);
- if (!ref && !InterlockedDecrement(&This->numIfaces)) - primarybuffer_destroy(This); return ref; }
diff --git a/dlls/dsound/sound3d.c b/dlls/dsound/sound3d.c index c57aa2e..604d19b 100644 --- a/dlls/dsound/sound3d.c +++ b/dlls/dsound/sound3d.c @@ -699,12 +699,13 @@ static ULONG WINAPI IDirectSound3DListenerImpl_AddRef(IDirectSound3DListener *if static ULONG WINAPI IDirectSound3DListenerImpl_Release(IDirectSound3DListener *iface) { IDirectSoundBufferImpl *This = impl_from_IDirectSound3DListener(iface); - ULONG ref = InterlockedDecrement(&This->ref3D); + ULONG ref;
- TRACE("(%p) ref was %d\n", This, ref + 1); + ref = capped_refcount_dec(&This->ref3D); + if(!ref) + capped_refcount_dec(&This->numIfaces);
- if (!ref && !InterlockedDecrement(&This->numIfaces)) - primarybuffer_destroy(This); + TRACE("(%p) ref is now %d\n", This, ref);
return ref; } diff --git a/dlls/dsound/tests/dsound.c b/dlls/dsound/tests/dsound.c index c68a5de..4c46f67 100644 --- a/dlls/dsound/tests/dsound.c +++ b/dlls/dsound/tests/dsound.c @@ -493,6 +493,15 @@ static HRESULT test_primary(LPGUID lpGuid) !(dscaps.dwFlags & DSCAPS_EMULDRIVER),5.0,0,0,0,0,FALSE,0);
ref=IDirectSoundBuffer_Release(primary); + ok(ref==0,"IDirectSoundBuffer_Release() primary has %d references\n",ref); + + ref=IDirectSoundBuffer_AddRef(primary); + ok(ref==1,"IDirectSoundBuffer_AddRef() primary has %d references\n",ref); + + ref=IDirectSoundBuffer_Release(primary); + ok(ref==0,"IDirectSoundBuffer_Release() primary has %d references\n",ref); + + ref=IDirectSoundBuffer_Release(primary); ok(ref==0,"IDirectSoundBuffer_Release() primary has %d references, " "should have 0\n",ref); }