dsound: Add SndQueueMin to have less lock contention in mixer.

This commit is contained in:
Maarten Lankhorst 2007-07-30 16:12:29 +02:00 committed by Alexandre Julliard
parent 60f4db0345
commit 575f34e548
3 changed files with 23 additions and 7 deletions

View File

@ -55,6 +55,7 @@ WINE_DEFAULT_DEBUG_CHANNEL(dsound);
#define DS_HEL_BUFLEN 0x8000 /* HEL: The buffer length of the emulated buffer */
#define DS_SND_QUEUE_MAX 10 /* max number of fragments to prebuffer, each fragment is approximately 10 ms long */
#define DS_SND_QUEUE_MIN 6 /* If the minimum of prebuffered fragments go below this, forcibly take all locks to prevent underruns */
DirectSoundDevice* DSOUND_renderer[MAXWAVEDRIVERS];
GUID DSOUND_renderer_guids[MAXWAVEDRIVERS];
@ -90,6 +91,7 @@ HRESULT mmErr(UINT err)
int ds_emuldriver = 0;
int ds_hel_buflen = DS_HEL_BUFLEN;
int ds_snd_queue_max = DS_SND_QUEUE_MAX;
int ds_snd_queue_min = DS_SND_QUEUE_MIN;
int ds_hw_accel = DS_HW_ACCEL_FULL;
int ds_default_playback = 0;
int ds_default_capture = 0;
@ -152,6 +154,9 @@ void setup_dsound_options(void)
if (!get_config_key( hkey, appkey, "SndQueueMax", buffer, MAX_PATH ))
ds_snd_queue_max = atoi(buffer);
if (!get_config_key( hkey, appkey, "SndQueueMin", buffer, MAX_PATH ))
ds_snd_queue_min = atoi(buffer);
if (!get_config_key( hkey, appkey, "HardwareAcceleration", buffer, MAX_PATH )) {
if (strcmp(buffer, "Full") == 0)
ds_hw_accel = DS_HW_ACCEL_FULL;
@ -184,6 +189,8 @@ void setup_dsound_options(void)
WARN("ds_hel_buflen = %d (default=%d)\n",ds_hel_buflen ,DS_HEL_BUFLEN);
if (ds_snd_queue_max != DS_SND_QUEUE_MAX)
WARN("ds_snd_queue_max = %d (default=%d)\n",ds_snd_queue_max ,DS_SND_QUEUE_MAX);
if (ds_snd_queue_min != DS_SND_QUEUE_MIN)
WARN("ds_snd_queue_min = %d (default=%d)\n",ds_snd_queue_min ,DS_SND_QUEUE_MIN);
if (ds_hw_accel != DS_HW_ACCEL_FULL)
WARN("ds_hw_accel = %s (default=Full)\n",
ds_hw_accel==DS_HW_ACCEL_FULL ? "Full" :

View File

@ -32,6 +32,7 @@
extern int ds_emuldriver;
extern int ds_hel_buflen;
extern int ds_snd_queue_max;
extern int ds_snd_queue_min;
extern int ds_hw_accel;
extern int ds_default_playback;
extern int ds_default_capture;

View File

@ -667,10 +667,10 @@ static DWORD DSOUND_MixOne(IDirectSoundBufferImpl *dsb, DWORD writepos, DWORD mi
* For a DirectSoundDevice, go through all the currently playing buffers and
* mix them in to the device buffer.
*
* playpos = the current play position in the primary buffer
* writepos = the current safe-to-write position in the primary buffer
* mixlen = the maximum amount to mix into the primary buffer
* (beyond the current writepos)
* mustlock = Do we have to fight for lock because we otherwise risk an underrun?
* recover = true if the sound device may have been reset and the write
* position in the device buffer changed
* all_stopped = reports back if all buffers have stopped
@ -678,12 +678,12 @@ static DWORD DSOUND_MixOne(IDirectSoundBufferImpl *dsb, DWORD writepos, DWORD mi
* Returns: the length beyond the writepos that was mixed to.
*/
static DWORD DSOUND_MixToPrimary(const DirectSoundDevice *device, DWORD writepos,
DWORD mixlen, BOOL recover, BOOL *all_stopped)
static DWORD DSOUND_MixToPrimary(const DirectSoundDevice *device, DWORD writepos, DWORD mixlen, BOOL mustlock, BOOL recover, BOOL *all_stopped)
{
INT i, len;
DWORD minlen = 0;
IDirectSoundBufferImpl *dsb;
BOOL gotall = TRUE;
/* unless we find a running buffer, all have stopped */
*all_stopped = TRUE;
@ -696,8 +696,11 @@ static DWORD DSOUND_MixToPrimary(const DirectSoundDevice *device, DWORD writepos
if (dsb->buflen && dsb->state && !dsb->hwbuf) {
TRACE("Checking %p, mixlen=%d\n", dsb, mixlen);
RtlAcquireResourceShared(&dsb->lock, TRUE);
if (!RtlAcquireResourceShared(&dsb->lock, mustlock))
{
gotall = FALSE;
continue;
}
/* if buffer is stopping it is stopped now */
if (dsb->state == STATE_STOPPING) {
dsb->state = STATE_STOPPED;
@ -733,7 +736,7 @@ static DWORD DSOUND_MixToPrimary(const DirectSoundDevice *device, DWORD writepos
}
TRACE("Mixed at least %d from all buffers\n", minlen);
if (!gotall) return 0;
return minlen;
}
@ -816,6 +819,7 @@ static void DSOUND_PerformMix(DirectSoundDevice *device)
DWORD playpos, writepos, writelead, maxq, frag, prebuff_max, prebuff_left, size1, size2;
LPVOID buf1, buf2;
BOOL lock = (device->hwbuf && !(device->drvdesc.dwFlags & DSDDESC_DONTNEEDPRIMARYLOCK));
BOOL mustlock = FALSE;
int nfiller;
/* the sound of silence */
@ -890,11 +894,15 @@ static void DSOUND_PerformMix(DirectSoundDevice *device)
device->mixpos = writepos;
}
/* Do we risk an 'underrun' if we don't advance pointer? */
if (writelead/device->fraglen <= ds_snd_queue_min || recover)
mustlock = TRUE;
if (lock)
IDsDriverBuffer_Lock(device->hwbuf, &buf1, &size1, &buf2, &size2, writepos, maxq, 0);
/* do the mixing */
frag = DSOUND_MixToPrimary(device, writepos, maxq, recover, &all_stopped);
frag = DSOUND_MixToPrimary(device, writepos, maxq, mustlock, recover, &all_stopped);
/* update the mix position, taking wrap-around into acount */
device->mixpos = writepos + frag;