aboutsummaryrefslogtreecommitdiffstats
path: root/OpenAL32/alBuffer.c
diff options
context:
space:
mode:
Diffstat (limited to 'OpenAL32/alBuffer.c')
-rw-r--r--OpenAL32/alBuffer.c211
1 files changed, 130 insertions, 81 deletions
diff --git a/OpenAL32/alBuffer.c b/OpenAL32/alBuffer.c
index 985fa6eb..1464ef74 100644
--- a/OpenAL32/alBuffer.c
+++ b/OpenAL32/alBuffer.c
@@ -36,12 +36,13 @@
#include "sample_cvt.h"
-extern inline void LockBuffersRead(ALCdevice *device);
-extern inline void UnlockBuffersRead(ALCdevice *device);
-extern inline ALbuffer *LookupBuffer(ALCdevice *device, ALuint id);
+extern inline void LockBufferList(ALCdevice *device);
+extern inline void UnlockBufferList(ALCdevice *device);
extern inline ALsizei FrameSizeFromUserFmt(enum UserFmtChannels chans, enum UserFmtType type);
extern inline ALsizei FrameSizeFromFmt(enum FmtChannels chans, enum FmtType type);
+static ALbuffer *AllocBuffer(ALCcontext *context);
+static void FreeBuffer(ALCdevice *device, ALbuffer *buffer);
static const ALchar *NameFromUserFmtType(enum UserFmtType type);
static void LoadData(ALCcontext *context, ALbuffer *buffer, ALuint freq, ALsizei size,
enum UserFmtChannels SrcChannels, enum UserFmtType SrcType,
@@ -49,13 +50,19 @@ static void LoadData(ALCcontext *context, ALbuffer *buffer, ALuint freq, ALsizei
static ALboolean DecomposeUserFormat(ALenum format, enum UserFmtChannels *chans, enum UserFmtType *type);
static ALsizei SanitizeAlignment(enum UserFmtType type, ALsizei align);
-static inline void LockBuffersWrite(ALCdevice *device)
-{ LockUIntMapWrite(&device->BufferMap); }
-static inline void UnlockBuffersWrite(ALCdevice *device)
-{ UnlockUIntMapWrite(&device->BufferMap); }
-
-static inline ALbuffer *RemoveBuffer(ALCdevice *device, ALuint id)
-{ return (ALbuffer*)RemoveUIntMapKeyNoLock(&device->BufferMap, id); }
+static inline ALbuffer *LookupBuffer(ALCdevice *device, ALuint id)
+{
+ BufferSubList *sublist;
+ ALuint lidx = (id-1) >> 6;
+ ALsizei slidx = (id-1) & 0x3f;
+
+ if(UNLIKELY(lidx >= VECTOR_SIZE(device->BufferList)))
+ return NULL;
+ sublist = &VECTOR_ELEM(device->BufferList, lidx);
+ if(UNLIKELY(sublist->FreeMask & (U64(1)<<slidx)))
+ return NULL;
+ return sublist->Buffers + slidx;
+}
#define INVALID_STORAGE_MASK ~(AL_MAP_READ_BIT_SOFT | AL_MAP_WRITE_BIT_SOFT | AL_PRESERVE_DATA_BIT_SOFT | AL_MAP_PERSISTENT_BIT_SOFT)
@@ -75,7 +82,7 @@ AL_API ALvoid AL_APIENTRY alGenBuffers(ALsizei n, ALuint *buffers)
alSetError(context, AL_INVALID_VALUE, "Generating %d buffers", n);
else for(cur = 0;cur < n;cur++)
{
- ALbuffer *buffer = NewBuffer(context);
+ ALbuffer *buffer = AllocBuffer(context);
if(!buffer)
{
alDeleteBuffers(cur, buffers);
@@ -100,7 +107,7 @@ AL_API ALvoid AL_APIENTRY alDeleteBuffers(ALsizei n, const ALuint *buffers)
device = context->Device;
- LockBuffersWrite(device);
+ LockBufferList(device);
if(UNLIKELY(n < 0))
{
alSetError(context, AL_INVALID_VALUE, "Deleting %d buffers", n);
@@ -127,11 +134,11 @@ AL_API ALvoid AL_APIENTRY alDeleteBuffers(ALsizei n, const ALuint *buffers)
for(i = 0;i < n;i++)
{
if((ALBuf=LookupBuffer(device, buffers[i])) != NULL)
- DeleteBuffer(device, ALBuf);
+ FreeBuffer(device, ALBuf);
}
done:
- UnlockBuffersWrite(device);
+ UnlockBufferList(device);
ALCcontext_DecRef(context);
}
@@ -143,10 +150,10 @@ AL_API ALboolean AL_APIENTRY alIsBuffer(ALuint buffer)
context = GetContextRef();
if(!context) return AL_FALSE;
- LockBuffersRead(context->Device);
+ LockBufferList(context->Device);
ret = ((!buffer || LookupBuffer(context->Device, buffer)) ?
AL_TRUE : AL_FALSE);
- UnlockBuffersRead(context->Device);
+ UnlockBufferList(context->Device);
ALCcontext_DecRef(context);
@@ -169,7 +176,7 @@ AL_API void AL_APIENTRY alBufferStorageSOFT(ALuint buffer, ALenum format, const
if(!context) return;
device = context->Device;
- LockBuffersRead(device);
+ LockBufferList(device);
if(UNLIKELY((albuf=LookupBuffer(device, buffer)) == NULL))
alSetError(context, AL_INVALID_NAME, "Invalid buffer ID %u", buffer);
else if(UNLIKELY(size < 0))
@@ -191,7 +198,7 @@ AL_API void AL_APIENTRY alBufferStorageSOFT(ALuint buffer, ALenum format, const
WriteUnlock(&albuf->lock);
}
- UnlockBuffersRead(device);
+ UnlockBufferList(device);
ALCcontext_DecRef(context);
}
@@ -206,7 +213,7 @@ AL_API void* AL_APIENTRY alMapBufferSOFT(ALuint buffer, ALsizei offset, ALsizei
if(!context) return retval;
device = context->Device;
- LockBuffersRead(device);
+ LockBufferList(device);
if(UNLIKELY((albuf=LookupBuffer(device, buffer)) == NULL))
alSetError(context, AL_INVALID_NAME, "Invalid buffer ID %u", buffer);
else if(UNLIKELY((access&INVALID_MAP_FLAGS) != 0))
@@ -247,7 +254,7 @@ AL_API void* AL_APIENTRY alMapBufferSOFT(ALuint buffer, ALsizei offset, ALsizei
WriteUnlock(&albuf->lock);
}
- UnlockBuffersRead(device);
+ UnlockBufferList(device);
ALCcontext_DecRef(context);
return retval;
@@ -263,7 +270,7 @@ AL_API void AL_APIENTRY alUnmapBufferSOFT(ALuint buffer)
if(!context) return;
device = context->Device;
- LockBuffersRead(device);
+ LockBufferList(device);
if((albuf=LookupBuffer(device, buffer)) == NULL)
alSetError(context, AL_INVALID_NAME, "Invalid buffer ID %u", buffer);
else
@@ -279,7 +286,7 @@ AL_API void AL_APIENTRY alUnmapBufferSOFT(ALuint buffer)
}
WriteUnlock(&albuf->lock);
}
- UnlockBuffersRead(device);
+ UnlockBufferList(device);
ALCcontext_DecRef(context);
}
@@ -294,7 +301,7 @@ AL_API void AL_APIENTRY alFlushMappedBufferSOFT(ALuint buffer, ALsizei offset, A
if(!context) return;
device = context->Device;
- LockBuffersRead(device);
+ LockBufferList(device);
if(UNLIKELY((albuf=LookupBuffer(device, buffer)) == NULL))
alSetError(context, AL_INVALID_NAME, "Invalid buffer ID %u", buffer);
else
@@ -319,7 +326,7 @@ AL_API void AL_APIENTRY alFlushMappedBufferSOFT(ALuint buffer, ALsizei offset, A
}
WriteUnlock(&albuf->lock);
}
- UnlockBuffersRead(device);
+ UnlockBufferList(device);
ALCcontext_DecRef(context);
}
@@ -336,7 +343,7 @@ AL_API ALvoid AL_APIENTRY alBufferSubDataSOFT(ALuint buffer, ALenum format, cons
if(!context) return;
device = context->Device;
- LockBuffersRead(device);
+ LockBufferList(device);
if(UNLIKELY((albuf=LookupBuffer(device, buffer)) == NULL))
alSetError(context, AL_INVALID_NAME, "Invalid buffer ID %u", buffer);
else if(UNLIKELY(DecomposeUserFormat(format, &srcchannels, &srctype) == AL_FALSE))
@@ -408,7 +415,7 @@ AL_API ALvoid AL_APIENTRY alBufferSubDataSOFT(ALuint buffer, ALenum format, cons
WriteUnlock(&albuf->lock);
}
- UnlockBuffersRead(device);
+ UnlockBufferList(device);
ALCcontext_DecRef(context);
}
@@ -479,7 +486,7 @@ AL_API void AL_APIENTRY alBufferf(ALuint buffer, ALenum param, ALfloat UNUSED(va
if(!context) return;
device = context->Device;
- LockBuffersRead(device);
+ LockBufferList(device);
if(UNLIKELY(LookupBuffer(device, buffer) == NULL))
alSetError(context, AL_INVALID_NAME, "Invalid buffer ID %u", buffer);
else switch(param)
@@ -487,7 +494,7 @@ AL_API void AL_APIENTRY alBufferf(ALuint buffer, ALenum param, ALfloat UNUSED(va
default:
alSetError(context, AL_INVALID_ENUM, "Invalid buffer float property 0x%04x", param);
}
- UnlockBuffersRead(device);
+ UnlockBufferList(device);
ALCcontext_DecRef(context);
}
@@ -502,7 +509,7 @@ AL_API void AL_APIENTRY alBuffer3f(ALuint buffer, ALenum param, ALfloat UNUSED(v
if(!context) return;
device = context->Device;
- LockBuffersRead(device);
+ LockBufferList(device);
if(UNLIKELY(LookupBuffer(device, buffer) == NULL))
alSetError(context, AL_INVALID_NAME, "Invalid buffer ID %u", buffer);
else switch(param)
@@ -510,7 +517,7 @@ AL_API void AL_APIENTRY alBuffer3f(ALuint buffer, ALenum param, ALfloat UNUSED(v
default:
alSetError(context, AL_INVALID_ENUM, "Invalid buffer 3-float property 0x%04x", param);
}
- UnlockBuffersRead(device);
+ UnlockBufferList(device);
ALCcontext_DecRef(context);
}
@@ -525,7 +532,7 @@ AL_API void AL_APIENTRY alBufferfv(ALuint buffer, ALenum param, const ALfloat *v
if(!context) return;
device = context->Device;
- LockBuffersRead(device);
+ LockBufferList(device);
if(UNLIKELY(LookupBuffer(device, buffer) == NULL))
alSetError(context, AL_INVALID_NAME, "Invalid buffer ID %u", buffer);
else if(UNLIKELY(!values))
@@ -535,7 +542,7 @@ AL_API void AL_APIENTRY alBufferfv(ALuint buffer, ALenum param, const ALfloat *v
default:
alSetError(context, AL_INVALID_ENUM, "Invalid buffer float-vector property 0x%04x", param);
}
- UnlockBuffersRead(device);
+ UnlockBufferList(device);
ALCcontext_DecRef(context);
}
@@ -551,7 +558,7 @@ AL_API void AL_APIENTRY alBufferi(ALuint buffer, ALenum param, ALint value)
if(!context) return;
device = context->Device;
- LockBuffersRead(device);
+ LockBufferList(device);
if(UNLIKELY((albuf=LookupBuffer(device, buffer)) == NULL))
alSetError(context, AL_INVALID_NAME, "Invalid buffer ID %u", buffer);
else switch(param)
@@ -573,7 +580,7 @@ AL_API void AL_APIENTRY alBufferi(ALuint buffer, ALenum param, ALint value)
default:
alSetError(context, AL_INVALID_ENUM, "Invalid buffer integer property 0x%04x", param);
}
- UnlockBuffersRead(device);
+ UnlockBufferList(device);
ALCcontext_DecRef(context);
}
@@ -588,7 +595,7 @@ AL_API void AL_APIENTRY alBuffer3i(ALuint buffer, ALenum param, ALint UNUSED(val
if(!context) return;
device = context->Device;
- LockBuffersRead(device);
+ LockBufferList(device);
if(UNLIKELY(LookupBuffer(device, buffer) == NULL))
alSetError(context, AL_INVALID_NAME, "Invalid buffer ID %u", buffer);
else switch(param)
@@ -596,7 +603,7 @@ AL_API void AL_APIENTRY alBuffer3i(ALuint buffer, ALenum param, ALint UNUSED(val
default:
alSetError(context, AL_INVALID_ENUM, "Invalid buffer 3-integer property 0x%04x", param);
}
- UnlockBuffersRead(device);
+ UnlockBufferList(device);
ALCcontext_DecRef(context);
}
@@ -623,7 +630,7 @@ AL_API void AL_APIENTRY alBufferiv(ALuint buffer, ALenum param, const ALint *val
if(!context) return;
device = context->Device;
- LockBuffersRead(device);
+ LockBufferList(device);
if(UNLIKELY((albuf=LookupBuffer(device, buffer)) == NULL))
alSetError(context, AL_INVALID_NAME, "Invalid buffer ID %u", buffer);
else if(UNLIKELY(!values))
@@ -650,7 +657,7 @@ AL_API void AL_APIENTRY alBufferiv(ALuint buffer, ALenum param, const ALint *val
alSetError(context, AL_INVALID_ENUM, "Invalid buffer integer-vector property 0x%04x",
param);
}
- UnlockBuffersRead(device);
+ UnlockBufferList(device);
ALCcontext_DecRef(context);
}
@@ -666,7 +673,7 @@ AL_API ALvoid AL_APIENTRY alGetBufferf(ALuint buffer, ALenum param, ALfloat *val
if(!context) return;
device = context->Device;
- LockBuffersRead(device);
+ LockBufferList(device);
if(UNLIKELY((albuf=LookupBuffer(device, buffer)) == NULL))
alSetError(context, AL_INVALID_NAME, "Invalid buffer ID %u", buffer);
else if(UNLIKELY(!value))
@@ -676,7 +683,7 @@ AL_API ALvoid AL_APIENTRY alGetBufferf(ALuint buffer, ALenum param, ALfloat *val
default:
alSetError(context, AL_INVALID_ENUM, "Invalid buffer float property 0x%04x", param);
}
- UnlockBuffersRead(device);
+ UnlockBufferList(device);
ALCcontext_DecRef(context);
}
@@ -691,7 +698,7 @@ AL_API void AL_APIENTRY alGetBuffer3f(ALuint buffer, ALenum param, ALfloat *valu
if(!context) return;
device = context->Device;
- LockBuffersRead(device);
+ LockBufferList(device);
if(UNLIKELY(LookupBuffer(device, buffer) == NULL))
alSetError(context, AL_INVALID_NAME, "Invalid buffer ID %u", buffer);
else if(UNLIKELY(!value1 || !value2 || !value3))
@@ -701,7 +708,7 @@ AL_API void AL_APIENTRY alGetBuffer3f(ALuint buffer, ALenum param, ALfloat *valu
default:
alSetError(context, AL_INVALID_ENUM, "Invalid buffer 3-float property 0x%04x", param);
}
- UnlockBuffersRead(device);
+ UnlockBufferList(device);
ALCcontext_DecRef(context);
}
@@ -723,7 +730,7 @@ AL_API void AL_APIENTRY alGetBufferfv(ALuint buffer, ALenum param, ALfloat *valu
if(!context) return;
device = context->Device;
- LockBuffersRead(device);
+ LockBufferList(device);
if(UNLIKELY(LookupBuffer(device, buffer) == NULL))
alSetError(context, AL_INVALID_NAME, "Invalid buffer ID %u", buffer);
else if(UNLIKELY(!values))
@@ -733,7 +740,7 @@ AL_API void AL_APIENTRY alGetBufferfv(ALuint buffer, ALenum param, ALfloat *valu
default:
alSetError(context, AL_INVALID_ENUM, "Invalid buffer float-vector property 0x%04x", param);
}
- UnlockBuffersRead(device);
+ UnlockBufferList(device);
ALCcontext_DecRef(context);
}
@@ -749,7 +756,7 @@ AL_API ALvoid AL_APIENTRY alGetBufferi(ALuint buffer, ALenum param, ALint *value
if(!context) return;
device = context->Device;
- LockBuffersRead(device);
+ LockBufferList(device);
if(UNLIKELY((albuf=LookupBuffer(device, buffer)) == NULL))
alSetError(context, AL_INVALID_NAME, "Invalid buffer ID %u", buffer);
else if(UNLIKELY(!value))
@@ -786,7 +793,7 @@ AL_API ALvoid AL_APIENTRY alGetBufferi(ALuint buffer, ALenum param, ALint *value
default:
alSetError(context, AL_INVALID_ENUM, "Invalid buffer integer property 0x%04x", param);
}
- UnlockBuffersRead(device);
+ UnlockBufferList(device);
ALCcontext_DecRef(context);
}
@@ -801,7 +808,7 @@ AL_API void AL_APIENTRY alGetBuffer3i(ALuint buffer, ALenum param, ALint *value1
if(!context) return;
device = context->Device;
- LockBuffersRead(device);
+ LockBufferList(device);
if(UNLIKELY(LookupBuffer(device, buffer) == NULL))
alSetError(context, AL_INVALID_NAME, "Invalid buffer ID %u", buffer);
else if(UNLIKELY(!value1 || !value2 || !value3))
@@ -811,7 +818,7 @@ AL_API void AL_APIENTRY alGetBuffer3i(ALuint buffer, ALenum param, ALint *value1
default:
alSetError(context, AL_INVALID_ENUM, "Invalid buffer 3-integer property 0x%04x", param);
}
- UnlockBuffersRead(device);
+ UnlockBufferList(device);
ALCcontext_DecRef(context);
}
@@ -842,7 +849,7 @@ AL_API void AL_APIENTRY alGetBufferiv(ALuint buffer, ALenum param, ALint *values
if(!context) return;
device = context->Device;
- LockBuffersRead(device);
+ LockBufferList(device);
if(UNLIKELY((albuf=LookupBuffer(device, buffer)) == NULL))
alSetError(context, AL_INVALID_NAME, "Invalid buffer ID %u", buffer);
else if(UNLIKELY(!values))
@@ -860,7 +867,7 @@ AL_API void AL_APIENTRY alGetBufferiv(ALuint buffer, ALenum param, ALint *values
alSetError(context, AL_INVALID_ENUM, "Invalid buffer integer-vector property 0x%04x",
param);
}
- UnlockBuffersRead(device);
+ UnlockBufferList(device);
ALCcontext_DecRef(context);
}
@@ -1221,43 +1228,76 @@ static ALsizei SanitizeAlignment(enum UserFmtType type, ALsizei align)
}
-ALbuffer *NewBuffer(ALCcontext *context)
+static ALbuffer *AllocBuffer(ALCcontext *context)
{
ALCdevice *device = context->Device;
- ALbuffer *buffer;
- ALenum err;
+ BufferSubList *sublist, *subend;
+ ALbuffer *buffer = NULL;
+ ALsizei lidx = 0;
+ ALsizei slidx;
+
+ almtx_lock(&device->BufferLock);
+ sublist = VECTOR_BEGIN(device->BufferList);
+ subend = VECTOR_END(device->BufferList);
+ for(;sublist != subend;++sublist)
+ {
+ if(sublist->FreeMask)
+ {
+ slidx = CTZ64(sublist->FreeMask);
+ buffer = sublist->Buffers + slidx;
+ break;
+ }
+ ++lidx;
+ }
+ if(UNLIKELY(!buffer))
+ {
+ const BufferSubList empty_sublist = { 0, NULL };
+ lidx = VECTOR_SIZE(device->BufferList);
+ /* Don't allocate so many list entries that the 32-bit ID could
+ * overflow...
+ */
+ if(UNLIKELY(lidx >= 1<<25))
+ {
+ almtx_unlock(&device->BufferLock);
+ return NULL;
+ }
+ VECTOR_PUSH_BACK(device->BufferList, empty_sublist);
+ sublist = &VECTOR_BACK(device->BufferList);
+ sublist->FreeMask = ~U64(0);
+ sublist->Buffers = al_calloc(16, sizeof(ALbuffer)*64);
+ if(UNLIKELY(!sublist->Buffers))
+ {
+ VECTOR_POP_BACK(device->BufferList);
+ almtx_unlock(&device->BufferLock);
+ return NULL;
+ }
+
+ slidx = 0;
+ buffer = sublist->Buffers + slidx;
+ }
- buffer = al_calloc(16, sizeof(ALbuffer));
- if(!buffer)
- SETERR_RETURN(context, AL_OUT_OF_MEMORY, NULL, "Failed to allocate buffer object");
+ memset(buffer, 0, sizeof(*buffer));
RWLockInit(&buffer->lock);
- buffer->Access = 0;
- buffer->MappedAccess = 0;
- err = NewThunkEntry(&buffer->id);
- if(err == AL_NO_ERROR)
- err = InsertUIntMapEntry(&device->BufferMap, buffer->id, buffer);
- if(err != AL_NO_ERROR)
- {
- FreeThunkEntry(buffer->id);
- memset(buffer, 0, sizeof(ALbuffer));
- al_free(buffer);
+ /* Add 1 to avoid buffer ID 0. */
+ buffer->id = ((lidx<<6) | slidx) + 1;
- SETERR_RETURN(context, err, NULL, "Failed to set buffer ID");
- }
+ sublist->FreeMask &= ~(U64(1)<<slidx);
+ almtx_unlock(&device->BufferLock);
return buffer;
}
-void DeleteBuffer(ALCdevice *device, ALbuffer *buffer)
+static void FreeBuffer(ALCdevice *device, ALbuffer *buffer)
{
- RemoveBuffer(device, buffer->id);
- FreeThunkEntry(buffer->id);
+ ALuint id = buffer->id - 1;
+ ALsizei lidx = id >> 6;
+ ALsizei slidx = id & 0x3f;
al_free(buffer->data);
-
memset(buffer, 0, sizeof(*buffer));
- al_free(buffer);
+
+ VECTOR_ELEM(device->BufferList, lidx).FreeMask |= U64(1) << slidx;
}
@@ -1268,16 +1308,25 @@ void DeleteBuffer(ALCdevice *device, ALbuffer *buffer)
*/
ALvoid ReleaseALBuffers(ALCdevice *device)
{
- ALsizei i;
- for(i = 0;i < device->BufferMap.size;i++)
+ BufferSubList *sublist = VECTOR_BEGIN(device->BufferList);
+ BufferSubList *subend = VECTOR_END(device->BufferList);
+ size_t leftover = 0;
+ for(;sublist != subend;++sublist)
{
- ALbuffer *temp = device->BufferMap.values[i];
- device->BufferMap.values[i] = NULL;
+ ALuint64 usemask = ~sublist->FreeMask;
+ while(usemask)
+ {
+ ALsizei idx = CTZ64(usemask);
+ ALbuffer *buffer = sublist->Buffers + idx;
- al_free(temp->data);
+ al_free(buffer->data);
+ memset(buffer, 0, sizeof(*buffer));
+ ++leftover;
- FreeThunkEntry(temp->id);
- memset(temp, 0, sizeof(ALbuffer));
- al_free(temp);
+ usemask &= ~(U64(1) << idx);
+ }
+ sublist->FreeMask = ~usemask;
}
+ if(leftover > 0)
+ WARN("(%p) Deleted "SZFMT" Buffer%s\n", device, leftover, (leftover==1)?"":"s");
}