Remove the individual source queue and buffer locks
They're inherently protected by the mutex for their respective lists. Should those mutexes be replaced by rwlocks the individual locks should also be reinstated, but they're unlikely to be unless a lot of contention starts happening in the read-only case.
This commit is contained in:
parent
6a4a88f8f5
commit
28fa82378b
@ -102,8 +102,6 @@ typedef struct ALbuffer {
|
|||||||
/* Number of times buffer was attached to a source (deletion can only occur when 0) */
|
/* Number of times buffer was attached to a source (deletion can only occur when 0) */
|
||||||
RefCount ref;
|
RefCount ref;
|
||||||
|
|
||||||
RWLock lock;
|
|
||||||
|
|
||||||
/* Self ID */
|
/* Self ID */
|
||||||
ALuint id;
|
ALuint id;
|
||||||
} ALbuffer;
|
} ALbuffer;
|
||||||
|
@ -95,7 +95,6 @@ typedef struct ALsource {
|
|||||||
ATOMIC(ALenum) state;
|
ATOMIC(ALenum) state;
|
||||||
|
|
||||||
/** Source Buffer Queue head. */
|
/** Source Buffer Queue head. */
|
||||||
RWLock queue_lock;
|
|
||||||
ALbufferlistitem *queue;
|
ALbufferlistitem *queue;
|
||||||
|
|
||||||
ATOMIC_FLAG PropsClean;
|
ATOMIC_FLAG PropsClean;
|
||||||
|
@ -192,11 +192,7 @@ AL_API void AL_APIENTRY alBufferStorageSOFT(ALuint buffer, ALenum format, const
|
|||||||
else if(UNLIKELY(DecomposeUserFormat(format, &srcchannels, &srctype) == AL_FALSE))
|
else if(UNLIKELY(DecomposeUserFormat(format, &srcchannels, &srctype) == AL_FALSE))
|
||||||
alSetError(context, AL_INVALID_ENUM, "Invalid format 0x%04x", format);
|
alSetError(context, AL_INVALID_ENUM, "Invalid format 0x%04x", format);
|
||||||
else
|
else
|
||||||
{
|
|
||||||
WriteLock(&albuf->lock);
|
|
||||||
LoadData(context, albuf, freq, size, srcchannels, srctype, data, flags);
|
LoadData(context, albuf, freq, size, srcchannels, srctype, data, flags);
|
||||||
WriteUnlock(&albuf->lock);
|
|
||||||
}
|
|
||||||
|
|
||||||
UnlockBufferList(device);
|
UnlockBufferList(device);
|
||||||
ALCcontext_DecRef(context);
|
ALCcontext_DecRef(context);
|
||||||
@ -223,9 +219,7 @@ AL_API void* AL_APIENTRY alMapBufferSOFT(ALuint buffer, ALsizei offset, ALsizei
|
|||||||
buffer);
|
buffer);
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
ALbitfieldSOFT unavailable;
|
ALbitfieldSOFT unavailable = (albuf->Access^access) & access;
|
||||||
WriteLock(&albuf->lock);
|
|
||||||
unavailable = (albuf->Access^access) & access;
|
|
||||||
if(UNLIKELY(ReadRef(&albuf->ref) != 0 && !(access&AL_MAP_PERSISTENT_BIT_SOFT)))
|
if(UNLIKELY(ReadRef(&albuf->ref) != 0 && !(access&AL_MAP_PERSISTENT_BIT_SOFT)))
|
||||||
alSetError(context, AL_INVALID_OPERATION,
|
alSetError(context, AL_INVALID_OPERATION,
|
||||||
"Mapping in-use buffer %u without persistent mapping", buffer);
|
"Mapping in-use buffer %u without persistent mapping", buffer);
|
||||||
@ -251,8 +245,6 @@ AL_API void* AL_APIENTRY alMapBufferSOFT(ALuint buffer, ALsizei offset, ALsizei
|
|||||||
albuf->MappedOffset = offset;
|
albuf->MappedOffset = offset;
|
||||||
albuf->MappedSize = length;
|
albuf->MappedSize = length;
|
||||||
}
|
}
|
||||||
|
|
||||||
WriteUnlock(&albuf->lock);
|
|
||||||
}
|
}
|
||||||
UnlockBufferList(device);
|
UnlockBufferList(device);
|
||||||
|
|
||||||
@ -273,18 +265,13 @@ AL_API void AL_APIENTRY alUnmapBufferSOFT(ALuint buffer)
|
|||||||
LockBufferList(device);
|
LockBufferList(device);
|
||||||
if((albuf=LookupBuffer(device, buffer)) == NULL)
|
if((albuf=LookupBuffer(device, buffer)) == NULL)
|
||||||
alSetError(context, AL_INVALID_NAME, "Invalid buffer ID %u", buffer);
|
alSetError(context, AL_INVALID_NAME, "Invalid buffer ID %u", buffer);
|
||||||
|
else if(albuf->MappedAccess == 0)
|
||||||
|
alSetError(context, AL_INVALID_OPERATION, "Unmapping unmapped buffer %u", buffer);
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
WriteLock(&albuf->lock);
|
albuf->MappedAccess = 0;
|
||||||
if(albuf->MappedAccess == 0)
|
albuf->MappedOffset = 0;
|
||||||
alSetError(context, AL_INVALID_OPERATION, "Unmapping unmapped buffer %u", buffer);
|
albuf->MappedSize = 0;
|
||||||
else
|
|
||||||
{
|
|
||||||
albuf->MappedAccess = 0;
|
|
||||||
albuf->MappedOffset = 0;
|
|
||||||
albuf->MappedSize = 0;
|
|
||||||
}
|
|
||||||
WriteUnlock(&albuf->lock);
|
|
||||||
}
|
}
|
||||||
UnlockBufferList(device);
|
UnlockBufferList(device);
|
||||||
|
|
||||||
@ -304,27 +291,22 @@ AL_API void AL_APIENTRY alFlushMappedBufferSOFT(ALuint buffer, ALsizei offset, A
|
|||||||
LockBufferList(device);
|
LockBufferList(device);
|
||||||
if(UNLIKELY((albuf=LookupBuffer(device, buffer)) == NULL))
|
if(UNLIKELY((albuf=LookupBuffer(device, buffer)) == NULL))
|
||||||
alSetError(context, AL_INVALID_NAME, "Invalid buffer ID %u", buffer);
|
alSetError(context, AL_INVALID_NAME, "Invalid buffer ID %u", buffer);
|
||||||
|
else if(UNLIKELY(!(albuf->MappedAccess&AL_MAP_WRITE_BIT_SOFT)))
|
||||||
|
alSetError(context, AL_INVALID_OPERATION,
|
||||||
|
"Flushing buffer %u while not mapped for writing", buffer);
|
||||||
|
else if(UNLIKELY(offset < albuf->MappedOffset ||
|
||||||
|
offset >= albuf->MappedOffset+albuf->MappedSize ||
|
||||||
|
length <= 0 || length > albuf->MappedOffset+albuf->MappedSize-offset))
|
||||||
|
alSetError(context, AL_INVALID_VALUE, "Flushing invalid range %d+%d on buffer %u",
|
||||||
|
offset, length, buffer);
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
WriteLock(&albuf->lock);
|
/* FIXME: Need to use some method of double-buffering for the mixer and
|
||||||
if(UNLIKELY(!(albuf->MappedAccess&AL_MAP_WRITE_BIT_SOFT)))
|
* app to hold separate memory, which can be safely transfered
|
||||||
alSetError(context, AL_INVALID_OPERATION,
|
* asynchronously. Currently we just say the app shouldn't write where
|
||||||
"Flushing buffer %u while not mapped for writing", buffer);
|
* OpenAL's reading, and hope for the best...
|
||||||
else if(UNLIKELY(offset < albuf->MappedOffset ||
|
*/
|
||||||
offset >= albuf->MappedOffset+albuf->MappedSize ||
|
ATOMIC_THREAD_FENCE(almemory_order_seq_cst);
|
||||||
length <= 0 || length > albuf->MappedOffset+albuf->MappedSize-offset))
|
|
||||||
alSetError(context, AL_INVALID_VALUE, "Flushing invalid range %d+%d on buffer %u",
|
|
||||||
offset, length, buffer);
|
|
||||||
else
|
|
||||||
{
|
|
||||||
/* FIXME: Need to use some method of double-buffering for the mixer
|
|
||||||
* and app to hold separate memory, which can be safely transfered
|
|
||||||
* asynchronously. Currently we just say the app shouldn't write
|
|
||||||
* where OpenAL's reading, and hope for the best...
|
|
||||||
*/
|
|
||||||
ATOMIC_THREAD_FENCE(almemory_order_seq_cst);
|
|
||||||
}
|
|
||||||
WriteUnlock(&albuf->lock);
|
|
||||||
}
|
}
|
||||||
UnlockBufferList(device);
|
UnlockBufferList(device);
|
||||||
|
|
||||||
@ -356,7 +338,6 @@ AL_API ALvoid AL_APIENTRY alBufferSubDataSOFT(ALuint buffer, ALenum format, cons
|
|||||||
ALsizei num_chans;
|
ALsizei num_chans;
|
||||||
void *dst;
|
void *dst;
|
||||||
|
|
||||||
WriteLock(&albuf->lock);
|
|
||||||
unpack_align = ATOMIC_LOAD_SEQ(&albuf->UnpackAlign);
|
unpack_align = ATOMIC_LOAD_SEQ(&albuf->UnpackAlign);
|
||||||
align = SanitizeAlignment(srctype, unpack_align);
|
align = SanitizeAlignment(srctype, unpack_align);
|
||||||
if(UNLIKELY(align < 1))
|
if(UNLIKELY(align < 1))
|
||||||
@ -412,8 +393,6 @@ AL_API ALvoid AL_APIENTRY alBufferSubDataSOFT(ALuint buffer, ALenum format, cons
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
WriteUnlock(&albuf->lock);
|
|
||||||
}
|
}
|
||||||
UnlockBufferList(device);
|
UnlockBufferList(device);
|
||||||
|
|
||||||
@ -638,7 +617,6 @@ AL_API void AL_APIENTRY alBufferiv(ALuint buffer, ALenum param, const ALint *val
|
|||||||
else switch(param)
|
else switch(param)
|
||||||
{
|
{
|
||||||
case AL_LOOP_POINTS_SOFT:
|
case AL_LOOP_POINTS_SOFT:
|
||||||
WriteLock(&albuf->lock);
|
|
||||||
if(UNLIKELY(ReadRef(&albuf->ref) != 0))
|
if(UNLIKELY(ReadRef(&albuf->ref) != 0))
|
||||||
alSetError(context, AL_INVALID_OPERATION, "Modifying in-use buffer %u's loop points",
|
alSetError(context, AL_INVALID_OPERATION, "Modifying in-use buffer %u's loop points",
|
||||||
buffer);
|
buffer);
|
||||||
@ -650,7 +628,6 @@ AL_API void AL_APIENTRY alBufferiv(ALuint buffer, ALenum param, const ALint *val
|
|||||||
albuf->LoopStart = values[0];
|
albuf->LoopStart = values[0];
|
||||||
albuf->LoopEnd = values[1];
|
albuf->LoopEnd = values[1];
|
||||||
}
|
}
|
||||||
WriteUnlock(&albuf->lock);
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
@ -776,10 +753,8 @@ AL_API ALvoid AL_APIENTRY alGetBufferi(ALuint buffer, ALenum param, ALint *value
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case AL_SIZE:
|
case AL_SIZE:
|
||||||
ReadLock(&albuf->lock);
|
|
||||||
*value = albuf->SampleLen * FrameSizeFromFmt(albuf->FmtChannels,
|
*value = albuf->SampleLen * FrameSizeFromFmt(albuf->FmtChannels,
|
||||||
albuf->FmtType);
|
albuf->FmtType);
|
||||||
ReadUnlock(&albuf->lock);
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case AL_UNPACK_BLOCK_ALIGNMENT_SOFT:
|
case AL_UNPACK_BLOCK_ALIGNMENT_SOFT:
|
||||||
@ -857,10 +832,8 @@ AL_API void AL_APIENTRY alGetBufferiv(ALuint buffer, ALenum param, ALint *values
|
|||||||
else switch(param)
|
else switch(param)
|
||||||
{
|
{
|
||||||
case AL_LOOP_POINTS_SOFT:
|
case AL_LOOP_POINTS_SOFT:
|
||||||
ReadLock(&albuf->lock);
|
|
||||||
values[0] = albuf->LoopStart;
|
values[0] = albuf->LoopStart;
|
||||||
values[1] = albuf->LoopEnd;
|
values[1] = albuf->LoopEnd;
|
||||||
ReadUnlock(&albuf->lock);
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
@ -1279,7 +1252,6 @@ static ALbuffer *AllocBuffer(ALCcontext *context)
|
|||||||
}
|
}
|
||||||
|
|
||||||
memset(buffer, 0, sizeof(*buffer));
|
memset(buffer, 0, sizeof(*buffer));
|
||||||
RWLockInit(&buffer->lock);
|
|
||||||
|
|
||||||
/* Add 1 to avoid buffer ID 0. */
|
/* Add 1 to avoid buffer ID 0. */
|
||||||
buffer->id = ((lidx<<6) | slidx) + 1;
|
buffer->id = ((lidx<<6) | slidx) + 1;
|
||||||
|
@ -651,14 +651,11 @@ static ALboolean SetSourcefv(ALsource *Source, ALCcontext *Context, SourceProp p
|
|||||||
voice = GetSourceVoice(Source, Context);
|
voice = GetSourceVoice(Source, Context);
|
||||||
if(voice)
|
if(voice)
|
||||||
{
|
{
|
||||||
WriteLock(&Source->queue_lock);
|
|
||||||
if(ApplyOffset(Source, voice) == AL_FALSE)
|
if(ApplyOffset(Source, voice) == AL_FALSE)
|
||||||
{
|
{
|
||||||
WriteUnlock(&Source->queue_lock);
|
|
||||||
ALCdevice_Unlock(Context->Device);
|
ALCdevice_Unlock(Context->Device);
|
||||||
SETERR_RETURN(Context, AL_INVALID_VALUE, AL_FALSE, "Invalid offset");
|
SETERR_RETURN(Context, AL_INVALID_VALUE, AL_FALSE, "Invalid offset");
|
||||||
}
|
}
|
||||||
WriteUnlock(&Source->queue_lock);
|
|
||||||
}
|
}
|
||||||
ALCdevice_Unlock(Context->Device);
|
ALCdevice_Unlock(Context->Device);
|
||||||
}
|
}
|
||||||
@ -784,7 +781,6 @@ static ALboolean SetSourceiv(ALsource *Source, ALCcontext *Context, SourceProp p
|
|||||||
case AL_LOOPING:
|
case AL_LOOPING:
|
||||||
CHECKVAL(*values == AL_FALSE || *values == AL_TRUE);
|
CHECKVAL(*values == AL_FALSE || *values == AL_TRUE);
|
||||||
|
|
||||||
WriteLock(&Source->queue_lock);
|
|
||||||
Source->Looping = (ALboolean)*values;
|
Source->Looping = (ALboolean)*values;
|
||||||
if(IsPlayingOrPaused(Source))
|
if(IsPlayingOrPaused(Source))
|
||||||
{
|
{
|
||||||
@ -804,7 +800,6 @@ static ALboolean SetSourceiv(ALsource *Source, ALCcontext *Context, SourceProp p
|
|||||||
althrd_yield();
|
althrd_yield();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
WriteUnlock(&Source->queue_lock);
|
|
||||||
return AL_TRUE;
|
return AL_TRUE;
|
||||||
|
|
||||||
case AL_BUFFER:
|
case AL_BUFFER:
|
||||||
@ -816,11 +811,9 @@ static ALboolean SetSourceiv(ALsource *Source, ALCcontext *Context, SourceProp p
|
|||||||
*values);
|
*values);
|
||||||
}
|
}
|
||||||
|
|
||||||
WriteLock(&Source->queue_lock);
|
|
||||||
if(buffer && buffer->MappedAccess != 0 &&
|
if(buffer && buffer->MappedAccess != 0 &&
|
||||||
!(buffer->MappedAccess&AL_MAP_PERSISTENT_BIT_SOFT))
|
!(buffer->MappedAccess&AL_MAP_PERSISTENT_BIT_SOFT))
|
||||||
{
|
{
|
||||||
WriteUnlock(&Source->queue_lock);
|
|
||||||
UnlockBufferList(device);
|
UnlockBufferList(device);
|
||||||
SETERR_RETURN(Context, AL_INVALID_OPERATION, AL_FALSE,
|
SETERR_RETURN(Context, AL_INVALID_OPERATION, AL_FALSE,
|
||||||
"Setting non-persistently mapped buffer %u", buffer->id);
|
"Setting non-persistently mapped buffer %u", buffer->id);
|
||||||
@ -830,7 +823,6 @@ static ALboolean SetSourceiv(ALsource *Source, ALCcontext *Context, SourceProp p
|
|||||||
ALenum state = GetSourceState(Source, GetSourceVoice(Source, Context));
|
ALenum state = GetSourceState(Source, GetSourceVoice(Source, Context));
|
||||||
if(state == AL_PLAYING || state == AL_PAUSED)
|
if(state == AL_PLAYING || state == AL_PAUSED)
|
||||||
{
|
{
|
||||||
WriteUnlock(&Source->queue_lock);
|
|
||||||
UnlockBufferList(device);
|
UnlockBufferList(device);
|
||||||
SETERR_RETURN(Context, AL_INVALID_OPERATION, AL_FALSE,
|
SETERR_RETURN(Context, AL_INVALID_OPERATION, AL_FALSE,
|
||||||
"Setting buffer on playing or paused source %u", Source->id);
|
"Setting buffer on playing or paused source %u", Source->id);
|
||||||
@ -858,7 +850,6 @@ static ALboolean SetSourceiv(ALsource *Source, ALCcontext *Context, SourceProp p
|
|||||||
Source->SourceType = AL_UNDETERMINED;
|
Source->SourceType = AL_UNDETERMINED;
|
||||||
Source->queue = NULL;
|
Source->queue = NULL;
|
||||||
}
|
}
|
||||||
WriteUnlock(&Source->queue_lock);
|
|
||||||
UnlockBufferList(device);
|
UnlockBufferList(device);
|
||||||
|
|
||||||
/* Delete all elements in the previous queue */
|
/* Delete all elements in the previous queue */
|
||||||
@ -893,15 +884,12 @@ static ALboolean SetSourceiv(ALsource *Source, ALCcontext *Context, SourceProp p
|
|||||||
voice = GetSourceVoice(Source, Context);
|
voice = GetSourceVoice(Source, Context);
|
||||||
if(voice)
|
if(voice)
|
||||||
{
|
{
|
||||||
WriteLock(&Source->queue_lock);
|
|
||||||
if(ApplyOffset(Source, voice) == AL_FALSE)
|
if(ApplyOffset(Source, voice) == AL_FALSE)
|
||||||
{
|
{
|
||||||
WriteUnlock(&Source->queue_lock);
|
|
||||||
ALCdevice_Unlock(Context->Device);
|
ALCdevice_Unlock(Context->Device);
|
||||||
SETERR_RETURN(Context, AL_INVALID_VALUE, AL_FALSE,
|
SETERR_RETURN(Context, AL_INVALID_VALUE, AL_FALSE,
|
||||||
"Invalid source offset");
|
"Invalid source offset");
|
||||||
}
|
}
|
||||||
WriteUnlock(&Source->queue_lock);
|
|
||||||
}
|
}
|
||||||
ALCdevice_Unlock(Context->Device);
|
ALCdevice_Unlock(Context->Device);
|
||||||
}
|
}
|
||||||
@ -1298,7 +1286,6 @@ static ALboolean GetSourcedv(ALsource *Source, ALCcontext *Context, SourceProp p
|
|||||||
return AL_TRUE;
|
return AL_TRUE;
|
||||||
|
|
||||||
case AL_SEC_LENGTH_SOFT:
|
case AL_SEC_LENGTH_SOFT:
|
||||||
ReadLock(&Source->queue_lock);
|
|
||||||
if(!(BufferList=Source->queue))
|
if(!(BufferList=Source->queue))
|
||||||
*values = 0;
|
*values = 0;
|
||||||
else
|
else
|
||||||
@ -1322,7 +1309,6 @@ static ALboolean GetSourcedv(ALsource *Source, ALCcontext *Context, SourceProp p
|
|||||||
} while(BufferList != NULL);
|
} while(BufferList != NULL);
|
||||||
*values = (ALdouble)length / (ALdouble)freq;
|
*values = (ALdouble)length / (ALdouble)freq;
|
||||||
}
|
}
|
||||||
ReadUnlock(&Source->queue_lock);
|
|
||||||
return AL_TRUE;
|
return AL_TRUE;
|
||||||
|
|
||||||
case AL_SOURCE_RADIUS:
|
case AL_SOURCE_RADIUS:
|
||||||
@ -1436,11 +1422,9 @@ static ALboolean GetSourceiv(ALsource *Source, ALCcontext *Context, SourceProp p
|
|||||||
return AL_TRUE;
|
return AL_TRUE;
|
||||||
|
|
||||||
case AL_BUFFER:
|
case AL_BUFFER:
|
||||||
ReadLock(&Source->queue_lock);
|
|
||||||
BufferList = (Source->SourceType == AL_STATIC) ? Source->queue : NULL;
|
BufferList = (Source->SourceType == AL_STATIC) ? Source->queue : NULL;
|
||||||
*values = (BufferList && BufferList->num_buffers >= 1 && BufferList->buffers[0]) ?
|
*values = (BufferList && BufferList->num_buffers >= 1 && BufferList->buffers[0]) ?
|
||||||
BufferList->buffers[0]->id : 0;
|
BufferList->buffers[0]->id : 0;
|
||||||
ReadUnlock(&Source->queue_lock);
|
|
||||||
return AL_TRUE;
|
return AL_TRUE;
|
||||||
|
|
||||||
case AL_SOURCE_STATE:
|
case AL_SOURCE_STATE:
|
||||||
@ -1448,7 +1432,6 @@ static ALboolean GetSourceiv(ALsource *Source, ALCcontext *Context, SourceProp p
|
|||||||
return AL_TRUE;
|
return AL_TRUE;
|
||||||
|
|
||||||
case AL_BYTE_LENGTH_SOFT:
|
case AL_BYTE_LENGTH_SOFT:
|
||||||
ReadLock(&Source->queue_lock);
|
|
||||||
if(!(BufferList=Source->queue))
|
if(!(BufferList=Source->queue))
|
||||||
*values = 0;
|
*values = 0;
|
||||||
else
|
else
|
||||||
@ -1491,11 +1474,9 @@ static ALboolean GetSourceiv(ALsource *Source, ALCcontext *Context, SourceProp p
|
|||||||
} while(BufferList != NULL);
|
} while(BufferList != NULL);
|
||||||
*values = length;
|
*values = length;
|
||||||
}
|
}
|
||||||
ReadUnlock(&Source->queue_lock);
|
|
||||||
return AL_TRUE;
|
return AL_TRUE;
|
||||||
|
|
||||||
case AL_SAMPLE_LENGTH_SOFT:
|
case AL_SAMPLE_LENGTH_SOFT:
|
||||||
ReadLock(&Source->queue_lock);
|
|
||||||
if(!(BufferList=Source->queue))
|
if(!(BufferList=Source->queue))
|
||||||
*values = 0;
|
*values = 0;
|
||||||
else
|
else
|
||||||
@ -1514,11 +1495,9 @@ static ALboolean GetSourceiv(ALsource *Source, ALCcontext *Context, SourceProp p
|
|||||||
} while(BufferList != NULL);
|
} while(BufferList != NULL);
|
||||||
*values = length;
|
*values = length;
|
||||||
}
|
}
|
||||||
ReadUnlock(&Source->queue_lock);
|
|
||||||
return AL_TRUE;
|
return AL_TRUE;
|
||||||
|
|
||||||
case AL_BUFFERS_QUEUED:
|
case AL_BUFFERS_QUEUED:
|
||||||
ReadLock(&Source->queue_lock);
|
|
||||||
if(!(BufferList=Source->queue))
|
if(!(BufferList=Source->queue))
|
||||||
*values = 0;
|
*values = 0;
|
||||||
else
|
else
|
||||||
@ -1530,11 +1509,9 @@ static ALboolean GetSourceiv(ALsource *Source, ALCcontext *Context, SourceProp p
|
|||||||
} while(BufferList != NULL);
|
} while(BufferList != NULL);
|
||||||
*values = count;
|
*values = count;
|
||||||
}
|
}
|
||||||
ReadUnlock(&Source->queue_lock);
|
|
||||||
return AL_TRUE;
|
return AL_TRUE;
|
||||||
|
|
||||||
case AL_BUFFERS_PROCESSED:
|
case AL_BUFFERS_PROCESSED:
|
||||||
ReadLock(&Source->queue_lock);
|
|
||||||
if(Source->Looping || Source->SourceType != AL_STREAMING)
|
if(Source->Looping || Source->SourceType != AL_STREAMING)
|
||||||
{
|
{
|
||||||
/* Buffers on a looping source are in a perpetual state of
|
/* Buffers on a looping source are in a perpetual state of
|
||||||
@ -1561,7 +1538,6 @@ static ALboolean GetSourceiv(ALsource *Source, ALCcontext *Context, SourceProp p
|
|||||||
}
|
}
|
||||||
*values = played;
|
*values = played;
|
||||||
}
|
}
|
||||||
ReadUnlock(&Source->queue_lock);
|
|
||||||
return AL_TRUE;
|
return AL_TRUE;
|
||||||
|
|
||||||
case AL_SOURCE_TYPE:
|
case AL_SOURCE_TYPE:
|
||||||
@ -2571,7 +2547,6 @@ AL_API ALvoid AL_APIENTRY alSourcePlayv(ALsizei n, const ALuint *sources)
|
|||||||
ALsizei s;
|
ALsizei s;
|
||||||
|
|
||||||
source = LookupSource(context, sources[i]);
|
source = LookupSource(context, sources[i]);
|
||||||
WriteLock(&source->queue_lock);
|
|
||||||
/* Check that there is a queue containing at least one valid, non zero
|
/* Check that there is a queue containing at least one valid, non zero
|
||||||
* length Buffer.
|
* length Buffer.
|
||||||
*/
|
*/
|
||||||
@ -2598,7 +2573,7 @@ AL_API ALvoid AL_APIENTRY alSourcePlayv(ALsizei n, const ALuint *sources)
|
|||||||
ATOMIC_STORE(&source->state, AL_STOPPED, almemory_order_relaxed);
|
ATOMIC_STORE(&source->state, AL_STOPPED, almemory_order_relaxed);
|
||||||
source->OffsetType = AL_NONE;
|
source->OffsetType = AL_NONE;
|
||||||
source->Offset = 0.0;
|
source->Offset = 0.0;
|
||||||
goto finish_play;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
voice = GetSourceVoice(source, context);
|
voice = GetSourceVoice(source, context);
|
||||||
@ -2610,14 +2585,14 @@ AL_API ALvoid AL_APIENTRY alSourcePlayv(ALsizei n, const ALuint *sources)
|
|||||||
ATOMIC_STORE(&voice->current_buffer, BufferList, almemory_order_relaxed);
|
ATOMIC_STORE(&voice->current_buffer, BufferList, almemory_order_relaxed);
|
||||||
ATOMIC_STORE(&voice->position, 0, almemory_order_relaxed);
|
ATOMIC_STORE(&voice->position, 0, almemory_order_relaxed);
|
||||||
ATOMIC_STORE(&voice->position_fraction, 0, almemory_order_release);
|
ATOMIC_STORE(&voice->position_fraction, 0, almemory_order_release);
|
||||||
goto finish_play;
|
continue;
|
||||||
|
|
||||||
case AL_PAUSED:
|
case AL_PAUSED:
|
||||||
assert(voice != NULL);
|
assert(voice != NULL);
|
||||||
/* A source that's paused simply resumes. */
|
/* A source that's paused simply resumes. */
|
||||||
ATOMIC_STORE(&voice->Playing, true, almemory_order_release);
|
ATOMIC_STORE(&voice->Playing, true, almemory_order_release);
|
||||||
ATOMIC_STORE(&source->state, AL_PLAYING, almemory_order_release);
|
ATOMIC_STORE(&source->state, AL_PLAYING, almemory_order_release);
|
||||||
goto finish_play;
|
continue;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
@ -2693,8 +2668,6 @@ AL_API ALvoid AL_APIENTRY alSourcePlayv(ALsizei n, const ALuint *sources)
|
|||||||
ATOMIC_STORE(&voice->Playing, true, almemory_order_release);
|
ATOMIC_STORE(&voice->Playing, true, almemory_order_release);
|
||||||
ATOMIC_STORE(&source->state, AL_PLAYING, almemory_order_release);
|
ATOMIC_STORE(&source->state, AL_PLAYING, almemory_order_release);
|
||||||
source->VoiceIdx = vidx;
|
source->VoiceIdx = vidx;
|
||||||
finish_play:
|
|
||||||
WriteUnlock(&source->queue_lock);
|
|
||||||
}
|
}
|
||||||
ALCdevice_Unlock(device);
|
ALCdevice_Unlock(device);
|
||||||
|
|
||||||
@ -2732,7 +2705,6 @@ AL_API ALvoid AL_APIENTRY alSourcePausev(ALsizei n, const ALuint *sources)
|
|||||||
for(i = 0;i < n;i++)
|
for(i = 0;i < n;i++)
|
||||||
{
|
{
|
||||||
source = LookupSource(context, sources[i]);
|
source = LookupSource(context, sources[i]);
|
||||||
WriteLock(&source->queue_lock);
|
|
||||||
if((voice=GetSourceVoice(source, context)) != NULL)
|
if((voice=GetSourceVoice(source, context)) != NULL)
|
||||||
{
|
{
|
||||||
ATOMIC_STORE(&voice->Playing, false, almemory_order_release);
|
ATOMIC_STORE(&voice->Playing, false, almemory_order_release);
|
||||||
@ -2741,7 +2713,6 @@ AL_API ALvoid AL_APIENTRY alSourcePausev(ALsizei n, const ALuint *sources)
|
|||||||
}
|
}
|
||||||
if(GetSourceState(source, voice) == AL_PLAYING)
|
if(GetSourceState(source, voice) == AL_PLAYING)
|
||||||
ATOMIC_STORE(&source->state, AL_PAUSED, almemory_order_release);
|
ATOMIC_STORE(&source->state, AL_PAUSED, almemory_order_release);
|
||||||
WriteUnlock(&source->queue_lock);
|
|
||||||
}
|
}
|
||||||
ALCdevice_Unlock(device);
|
ALCdevice_Unlock(device);
|
||||||
|
|
||||||
@ -2779,7 +2750,6 @@ AL_API ALvoid AL_APIENTRY alSourceStopv(ALsizei n, const ALuint *sources)
|
|||||||
for(i = 0;i < n;i++)
|
for(i = 0;i < n;i++)
|
||||||
{
|
{
|
||||||
source = LookupSource(context, sources[i]);
|
source = LookupSource(context, sources[i]);
|
||||||
WriteLock(&source->queue_lock);
|
|
||||||
if((voice=GetSourceVoice(source, context)) != NULL)
|
if((voice=GetSourceVoice(source, context)) != NULL)
|
||||||
{
|
{
|
||||||
ATOMIC_STORE(&voice->Source, NULL, almemory_order_relaxed);
|
ATOMIC_STORE(&voice->Source, NULL, almemory_order_relaxed);
|
||||||
@ -2791,7 +2761,6 @@ AL_API ALvoid AL_APIENTRY alSourceStopv(ALsizei n, const ALuint *sources)
|
|||||||
ATOMIC_STORE(&source->state, AL_STOPPED, almemory_order_relaxed);
|
ATOMIC_STORE(&source->state, AL_STOPPED, almemory_order_relaxed);
|
||||||
source->OffsetType = AL_NONE;
|
source->OffsetType = AL_NONE;
|
||||||
source->Offset = 0.0;
|
source->Offset = 0.0;
|
||||||
WriteUnlock(&source->queue_lock);
|
|
||||||
}
|
}
|
||||||
ALCdevice_Unlock(device);
|
ALCdevice_Unlock(device);
|
||||||
|
|
||||||
@ -2829,7 +2798,6 @@ AL_API ALvoid AL_APIENTRY alSourceRewindv(ALsizei n, const ALuint *sources)
|
|||||||
for(i = 0;i < n;i++)
|
for(i = 0;i < n;i++)
|
||||||
{
|
{
|
||||||
source = LookupSource(context, sources[i]);
|
source = LookupSource(context, sources[i]);
|
||||||
WriteLock(&source->queue_lock);
|
|
||||||
if((voice=GetSourceVoice(source, context)) != NULL)
|
if((voice=GetSourceVoice(source, context)) != NULL)
|
||||||
{
|
{
|
||||||
ATOMIC_STORE(&voice->Source, NULL, almemory_order_relaxed);
|
ATOMIC_STORE(&voice->Source, NULL, almemory_order_relaxed);
|
||||||
@ -2841,7 +2809,6 @@ AL_API ALvoid AL_APIENTRY alSourceRewindv(ALsizei n, const ALuint *sources)
|
|||||||
ATOMIC_STORE(&source->state, AL_INITIAL, almemory_order_relaxed);
|
ATOMIC_STORE(&source->state, AL_INITIAL, almemory_order_relaxed);
|
||||||
source->OffsetType = AL_NONE;
|
source->OffsetType = AL_NONE;
|
||||||
source->Offset = 0.0;
|
source->Offset = 0.0;
|
||||||
WriteUnlock(&source->queue_lock);
|
|
||||||
}
|
}
|
||||||
ALCdevice_Unlock(device);
|
ALCdevice_Unlock(device);
|
||||||
|
|
||||||
@ -2875,10 +2842,8 @@ AL_API ALvoid AL_APIENTRY alSourceQueueBuffers(ALuint src, ALsizei nb, const ALu
|
|||||||
if((source=LookupSource(context, src)) == NULL)
|
if((source=LookupSource(context, src)) == NULL)
|
||||||
SETERR_GOTO(context, AL_INVALID_NAME, done, "Invalid source ID %u", src);
|
SETERR_GOTO(context, AL_INVALID_NAME, done, "Invalid source ID %u", src);
|
||||||
|
|
||||||
WriteLock(&source->queue_lock);
|
|
||||||
if(source->SourceType == AL_STATIC)
|
if(source->SourceType == AL_STATIC)
|
||||||
{
|
{
|
||||||
WriteUnlock(&source->queue_lock);
|
|
||||||
/* Can't queue on a Static Source */
|
/* Can't queue on a Static Source */
|
||||||
SETERR_GOTO(context, AL_INVALID_OPERATION, done, "Queueing onto static source %u", src);
|
SETERR_GOTO(context, AL_INVALID_OPERATION, done, "Queueing onto static source %u", src);
|
||||||
}
|
}
|
||||||
@ -2903,11 +2868,8 @@ AL_API ALvoid AL_APIENTRY alSourceQueueBuffers(ALuint src, ALsizei nb, const ALu
|
|||||||
{
|
{
|
||||||
ALbuffer *buffer = NULL;
|
ALbuffer *buffer = NULL;
|
||||||
if(buffers[i] && (buffer=LookupBuffer(device, buffers[i])) == NULL)
|
if(buffers[i] && (buffer=LookupBuffer(device, buffers[i])) == NULL)
|
||||||
{
|
|
||||||
WriteUnlock(&source->queue_lock);
|
|
||||||
SETERR_GOTO(context, AL_INVALID_NAME, buffer_error, "Queueing invalid buffer ID %u",
|
SETERR_GOTO(context, AL_INVALID_NAME, buffer_error, "Queueing invalid buffer ID %u",
|
||||||
buffers[i]);
|
buffers[i]);
|
||||||
}
|
|
||||||
|
|
||||||
if(!BufferListStart)
|
if(!BufferListStart)
|
||||||
{
|
{
|
||||||
@ -2927,18 +2889,11 @@ AL_API ALvoid AL_APIENTRY alSourceQueueBuffers(ALuint src, ALsizei nb, const ALu
|
|||||||
BufferList->buffers[0] = buffer;
|
BufferList->buffers[0] = buffer;
|
||||||
if(!buffer) continue;
|
if(!buffer) continue;
|
||||||
|
|
||||||
/* Hold a read lock on each buffer being queued while checking all
|
|
||||||
* provided buffers. This is done so other threads don't see an extra
|
|
||||||
* reference on some buffers if this operation ends up failing. */
|
|
||||||
ReadLock(&buffer->lock);
|
|
||||||
IncrementRef(&buffer->ref);
|
IncrementRef(&buffer->ref);
|
||||||
|
|
||||||
if(buffer->MappedAccess != 0 && !(buffer->MappedAccess&AL_MAP_PERSISTENT_BIT_SOFT))
|
if(buffer->MappedAccess != 0 && !(buffer->MappedAccess&AL_MAP_PERSISTENT_BIT_SOFT))
|
||||||
{
|
|
||||||
WriteUnlock(&source->queue_lock);
|
|
||||||
SETERR_GOTO(context, AL_INVALID_OPERATION, buffer_error,
|
SETERR_GOTO(context, AL_INVALID_OPERATION, buffer_error,
|
||||||
"Queueing non-persistently mapped buffer %u", buffer->id);
|
"Queueing non-persistently mapped buffer %u", buffer->id);
|
||||||
}
|
|
||||||
|
|
||||||
if(BufferFmt == NULL)
|
if(BufferFmt == NULL)
|
||||||
BufferFmt = buffer;
|
BufferFmt = buffer;
|
||||||
@ -2946,7 +2901,6 @@ AL_API ALvoid AL_APIENTRY alSourceQueueBuffers(ALuint src, ALsizei nb, const ALu
|
|||||||
BufferFmt->FmtChannels != buffer->FmtChannels ||
|
BufferFmt->FmtChannels != buffer->FmtChannels ||
|
||||||
BufferFmt->OriginalType != buffer->OriginalType)
|
BufferFmt->OriginalType != buffer->OriginalType)
|
||||||
{
|
{
|
||||||
WriteUnlock(&source->queue_lock);
|
|
||||||
alSetError(context, AL_INVALID_OPERATION, "Queueing buffer with mismatched format");
|
alSetError(context, AL_INVALID_OPERATION, "Queueing buffer with mismatched format");
|
||||||
|
|
||||||
buffer_error:
|
buffer_error:
|
||||||
@ -2959,10 +2913,7 @@ AL_API ALvoid AL_APIENTRY alSourceQueueBuffers(ALuint src, ALsizei nb, const ALu
|
|||||||
for(i = 0;i < BufferListStart->num_buffers;i++)
|
for(i = 0;i < BufferListStart->num_buffers;i++)
|
||||||
{
|
{
|
||||||
if((buffer=BufferListStart->buffers[i]) != NULL)
|
if((buffer=BufferListStart->buffers[i]) != NULL)
|
||||||
{
|
|
||||||
DecrementRef(&buffer->ref);
|
DecrementRef(&buffer->ref);
|
||||||
ReadUnlock(&buffer->lock);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
al_free(BufferListStart);
|
al_free(BufferListStart);
|
||||||
BufferListStart = next;
|
BufferListStart = next;
|
||||||
@ -2971,17 +2922,7 @@ AL_API ALvoid AL_APIENTRY alSourceQueueBuffers(ALuint src, ALsizei nb, const ALu
|
|||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
/* All buffers good, unlock them now. */
|
/* All buffers good. */
|
||||||
BufferList = BufferListStart;
|
|
||||||
while(BufferList != NULL)
|
|
||||||
{
|
|
||||||
for(i = 0;i < BufferList->num_buffers;i++)
|
|
||||||
{
|
|
||||||
ALbuffer *buffer = BufferList->buffers[i];
|
|
||||||
if(buffer) ReadUnlock(&buffer->lock);
|
|
||||||
}
|
|
||||||
BufferList = ATOMIC_LOAD(&BufferList->next, almemory_order_relaxed);
|
|
||||||
}
|
|
||||||
UnlockBufferList(device);
|
UnlockBufferList(device);
|
||||||
|
|
||||||
/* Source is now streaming */
|
/* Source is now streaming */
|
||||||
@ -2996,7 +2937,6 @@ AL_API ALvoid AL_APIENTRY alSourceQueueBuffers(ALuint src, ALsizei nb, const ALu
|
|||||||
BufferList = next;
|
BufferList = next;
|
||||||
ATOMIC_STORE(&BufferList->next, BufferListStart, almemory_order_release);
|
ATOMIC_STORE(&BufferList->next, BufferListStart, almemory_order_release);
|
||||||
}
|
}
|
||||||
WriteUnlock(&source->queue_lock);
|
|
||||||
|
|
||||||
done:
|
done:
|
||||||
UnlockSourceList(context);
|
UnlockSourceList(context);
|
||||||
@ -3025,18 +2965,11 @@ AL_API ALvoid AL_APIENTRY alSourceUnqueueBuffers(ALuint src, ALsizei nb, ALuint
|
|||||||
/* Nothing to unqueue. */
|
/* Nothing to unqueue. */
|
||||||
if(nb == 0) goto done;
|
if(nb == 0) goto done;
|
||||||
|
|
||||||
WriteLock(&source->queue_lock);
|
|
||||||
if(source->Looping)
|
if(source->Looping)
|
||||||
{
|
|
||||||
WriteUnlock(&source->queue_lock);
|
|
||||||
SETERR_GOTO(context, AL_INVALID_VALUE, done, "Unqueueing from looping source %u", src);
|
SETERR_GOTO(context, AL_INVALID_VALUE, done, "Unqueueing from looping source %u", src);
|
||||||
}
|
|
||||||
if(source->SourceType != AL_STREAMING)
|
if(source->SourceType != AL_STREAMING)
|
||||||
{
|
|
||||||
WriteUnlock(&source->queue_lock);
|
|
||||||
SETERR_GOTO(context, AL_INVALID_VALUE, done, "Unqueueing from a non-streaming source %u",
|
SETERR_GOTO(context, AL_INVALID_VALUE, done, "Unqueueing from a non-streaming source %u",
|
||||||
src);
|
src);
|
||||||
}
|
|
||||||
|
|
||||||
/* Find the new buffer queue head */
|
/* Find the new buffer queue head */
|
||||||
OldTail = source->queue;
|
OldTail = source->queue;
|
||||||
@ -3055,15 +2988,11 @@ AL_API ALvoid AL_APIENTRY alSourceUnqueueBuffers(ALuint src, ALsizei nb, ALuint
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if(i != nb)
|
if(i != nb)
|
||||||
{
|
|
||||||
WriteUnlock(&source->queue_lock);
|
|
||||||
SETERR_GOTO(context, AL_INVALID_VALUE, done, "Unqueueing pending buffers");
|
SETERR_GOTO(context, AL_INVALID_VALUE, done, "Unqueueing pending buffers");
|
||||||
}
|
|
||||||
|
|
||||||
/* Swap it, and cut the new head from the old. */
|
/* Swap it, and cut the new head from the old. */
|
||||||
OldHead = source->queue;
|
OldHead = source->queue;
|
||||||
source->queue = ATOMIC_EXCHANGE_PTR(&OldTail->next, NULL, almemory_order_acq_rel);
|
source->queue = ATOMIC_EXCHANGE_PTR(&OldTail->next, NULL, almemory_order_acq_rel);
|
||||||
WriteUnlock(&source->queue_lock);
|
|
||||||
|
|
||||||
while(OldHead != NULL)
|
while(OldHead != NULL)
|
||||||
{
|
{
|
||||||
@ -3092,8 +3021,6 @@ static void InitSourceParams(ALsource *Source, ALsizei num_sends)
|
|||||||
{
|
{
|
||||||
ALsizei i;
|
ALsizei i;
|
||||||
|
|
||||||
RWLockInit(&Source->queue_lock);
|
|
||||||
|
|
||||||
Source->InnerAngle = 360.0f;
|
Source->InnerAngle = 360.0f;
|
||||||
Source->OuterAngle = 360.0f;
|
Source->OuterAngle = 360.0f;
|
||||||
Source->Pitch = 1.0f;
|
Source->Pitch = 1.0f;
|
||||||
@ -3319,7 +3246,6 @@ static ALint64 GetSourceSampleOffset(ALsource *Source, ALCcontext *context, ALui
|
|||||||
ALuint refcount;
|
ALuint refcount;
|
||||||
ALvoice *voice;
|
ALvoice *voice;
|
||||||
|
|
||||||
ReadLock(&Source->queue_lock);
|
|
||||||
do {
|
do {
|
||||||
Current = NULL;
|
Current = NULL;
|
||||||
readPos = 0;
|
readPos = 0;
|
||||||
@ -3359,7 +3285,6 @@ static ALint64 GetSourceSampleOffset(ALsource *Source, ALCcontext *context, ALui
|
|||||||
readPos = minu64(readPos, U64(0x7fffffffffffffff));
|
readPos = minu64(readPos, U64(0x7fffffffffffffff));
|
||||||
}
|
}
|
||||||
|
|
||||||
ReadUnlock(&Source->queue_lock);
|
|
||||||
return (ALint64)readPos;
|
return (ALint64)readPos;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -3377,7 +3302,6 @@ static ALdouble GetSourceSecOffset(ALsource *Source, ALCcontext *context, ALuint
|
|||||||
ALdouble offset;
|
ALdouble offset;
|
||||||
ALvoice *voice;
|
ALvoice *voice;
|
||||||
|
|
||||||
ReadLock(&Source->queue_lock);
|
|
||||||
do {
|
do {
|
||||||
Current = NULL;
|
Current = NULL;
|
||||||
readPos = 0;
|
readPos = 0;
|
||||||
@ -3435,7 +3359,6 @@ static ALdouble GetSourceSecOffset(ALsource *Source, ALCcontext *context, ALuint
|
|||||||
(ALdouble)BufferFmt->Frequency;
|
(ALdouble)BufferFmt->Frequency;
|
||||||
}
|
}
|
||||||
|
|
||||||
ReadUnlock(&Source->queue_lock);
|
|
||||||
return offset;
|
return offset;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -3455,7 +3378,6 @@ static ALdouble GetSourceOffset(ALsource *Source, ALenum name, ALCcontext *conte
|
|||||||
ALdouble offset;
|
ALdouble offset;
|
||||||
ALvoice *voice;
|
ALvoice *voice;
|
||||||
|
|
||||||
ReadLock(&Source->queue_lock);
|
|
||||||
do {
|
do {
|
||||||
Current = NULL;
|
Current = NULL;
|
||||||
readPos = readPosFrac = 0;
|
readPos = readPosFrac = 0;
|
||||||
@ -3552,7 +3474,6 @@ static ALdouble GetSourceOffset(ALsource *Source, ALenum name, ALCcontext *conte
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ReadUnlock(&Source->queue_lock);
|
|
||||||
return offset;
|
return offset;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user