aboutsummaryrefslogtreecommitdiffstats
path: root/OpenAL32
diff options
context:
space:
mode:
Diffstat (limited to 'OpenAL32')
-rw-r--r--OpenAL32/Include/alFilter.h16
-rw-r--r--OpenAL32/Include/alMain.h10
-rw-r--r--OpenAL32/alFilter.c194
-rw-r--r--OpenAL32/alSource.c26
4 files changed, 164 insertions, 82 deletions
diff --git a/OpenAL32/Include/alFilter.h b/OpenAL32/Include/alFilter.h
index c1932e2e..e28b7b2b 100644
--- a/OpenAL32/Include/alFilter.h
+++ b/OpenAL32/Include/alFilter.h
@@ -163,21 +163,7 @@ typedef struct ALfilter {
ALuint id;
} ALfilter;
-inline void LockFiltersRead(ALCdevice *device)
-{ LockUIntMapRead(&device->FilterMap); }
-inline void UnlockFiltersRead(ALCdevice *device)
-{ UnlockUIntMapRead(&device->FilterMap); }
-inline void LockFiltersWrite(ALCdevice *device)
-{ LockUIntMapWrite(&device->FilterMap); }
-inline void UnlockFiltersWrite(ALCdevice *device)
-{ UnlockUIntMapWrite(&device->FilterMap); }
-
-inline struct ALfilter *LookupFilter(ALCdevice *device, ALuint id)
-{ return (struct ALfilter*)LookupUIntMapKeyNoLock(&device->FilterMap, id); }
-inline struct ALfilter *RemoveFilter(ALCdevice *device, ALuint id)
-{ return (struct ALfilter*)RemoveUIntMapKeyNoLock(&device->FilterMap, id); }
-
-ALvoid ReleaseALFilters(ALCdevice *device);
+void ReleaseALFilters(ALCdevice *device);
#ifdef __cplusplus
}
diff --git a/OpenAL32/Include/alMain.h b/OpenAL32/Include/alMain.h
index 8908d93f..d21ec3b0 100644
--- a/OpenAL32/Include/alMain.h
+++ b/OpenAL32/Include/alMain.h
@@ -166,6 +166,7 @@ struct Compressor;
struct ALCbackend;
struct ALbuffer;
struct ALeffect;
+struct ALfilter;
struct ALsource;
struct ALcontextProps;
struct ALlistenerProps;
@@ -388,6 +389,12 @@ typedef struct EffectSubList {
} EffectSubList;
TYPEDEF_VECTOR(EffectSubList, vector_EffectSubList)
+typedef struct FilterSubList {
+ ALuint64 FreeMask;
+ struct ALfilter *Filters; /* 64 */
+} FilterSubList;
+TYPEDEF_VECTOR(FilterSubList, vector_FilterSubList)
+
typedef struct SourceSubList {
ALuint64 FreeMask;
struct ALsource *Sources; /* 64 */
@@ -496,7 +503,8 @@ struct ALCdevice_struct
almtx_t EffectLock;
// Map of Filters for this device
- UIntMap FilterMap;
+ vector_FilterSubList FilterList;
+ almtx_t FilterLock;
/* HRTF state and info */
struct DirectHrtfState *Hrtf;
diff --git a/OpenAL32/alFilter.c b/OpenAL32/alFilter.c
index 34f2f271..de8e3a8c 100644
--- a/OpenAL32/alFilter.c
+++ b/OpenAL32/alFilter.c
@@ -29,27 +29,40 @@
#include "alError.h"
-extern inline void LockFiltersRead(ALCdevice *device);
-extern inline void UnlockFiltersRead(ALCdevice *device);
-extern inline void LockFiltersWrite(ALCdevice *device);
-extern inline void UnlockFiltersWrite(ALCdevice *device);
-extern inline struct ALfilter *LookupFilter(ALCdevice *device, ALuint id);
-extern inline struct ALfilter *RemoveFilter(ALCdevice *device, ALuint id);
extern inline void ALfilterState_clear(ALfilterState *filter);
extern inline void ALfilterState_copyParams(ALfilterState *restrict dst, const ALfilterState *restrict src);
extern inline void ALfilterState_processPassthru(ALfilterState *filter, const ALfloat *restrict src, ALsizei numsamples);
extern inline ALfloat calc_rcpQ_from_slope(ALfloat gain, ALfloat slope);
extern inline ALfloat calc_rcpQ_from_bandwidth(ALfloat f0norm, ALfloat bandwidth);
+static ALfilter *AllocFilter(ALCcontext *context);
+static void FreeFilter(ALCdevice *device, ALfilter *filter);
static void InitFilterParams(ALfilter *filter, ALenum type);
+static inline void LockFilterList(ALCdevice *device)
+{ almtx_lock(&device->FilterLock); }
+static inline void UnlockFilterList(ALCdevice *device)
+{ almtx_unlock(&device->FilterLock); }
+
+static inline ALfilter *LookupFilter(ALCdevice *device, ALuint id)
+{
+ FilterSubList *sublist;
+ ALuint lidx = (id-1) >> 6;
+ ALsizei slidx = (id-1) & 0x3f;
+
+ if(UNLIKELY(lidx >= VECTOR_SIZE(device->FilterList)))
+ return NULL;
+ sublist = &VECTOR_ELEM(device->FilterList, lidx);
+ if(UNLIKELY(sublist->FreeMask & (U64(1)<<slidx)))
+ return NULL;
+ return sublist->Filters + slidx;
+}
+
AL_API ALvoid AL_APIENTRY alGenFilters(ALsizei n, ALuint *filters)
{
- ALCdevice *device;
ALCcontext *context;
ALsizei cur = 0;
- ALenum err;
context = GetContextRef();
if(!context) return;
@@ -57,28 +70,13 @@ AL_API ALvoid AL_APIENTRY alGenFilters(ALsizei n, ALuint *filters)
if(!(n >= 0))
SETERR_GOTO(context, AL_INVALID_VALUE, done, "Generating %d filters", n);
- device = context->Device;
for(cur = 0;cur < n;cur++)
{
- ALfilter *filter = al_calloc(16, sizeof(ALfilter));
+ ALfilter *filter = AllocFilter(context);
if(!filter)
{
alDeleteFilters(cur, filters);
- SETERR_GOTO(context, AL_OUT_OF_MEMORY, done, "Failed to allocate filter object");
- }
- InitFilterParams(filter, AL_FILTER_NULL);
-
- err = NewThunkEntry(&filter->id);
- if(err == AL_NO_ERROR)
- err = InsertUIntMapEntry(&device->FilterMap, filter->id, filter);
- if(err != AL_NO_ERROR)
- {
- FreeThunkEntry(filter->id);
- memset(filter, 0, sizeof(ALfilter));
- al_free(filter);
-
- alDeleteFilters(cur, filters);
- SETERR_GOTO(context, err, done, "Failed ot set filter ID");
+ break;
}
filters[cur] = filter->id;
@@ -99,7 +97,7 @@ AL_API ALvoid AL_APIENTRY alDeleteFilters(ALsizei n, const ALuint *filters)
if(!context) return;
device = context->Device;
- LockFiltersWrite(device);
+ LockFilterList(device);
if(!(n >= 0))
SETERR_GOTO(context, AL_INVALID_VALUE, done, "Deleting %d filters", n);
for(i = 0;i < n;i++)
@@ -109,16 +107,12 @@ AL_API ALvoid AL_APIENTRY alDeleteFilters(ALsizei n, const ALuint *filters)
}
for(i = 0;i < n;i++)
{
- if((filter=RemoveFilter(device, filters[i])) == NULL)
- continue;
- FreeThunkEntry(filter->id);
-
- memset(filter, 0, sizeof(*filter));
- al_free(filter);
+ if((filter=LookupFilter(device, filters[i])) != NULL)
+ FreeFilter(device, filter);
}
done:
- UnlockFiltersWrite(device);
+ UnlockFilterList(device);
ALCcontext_DecRef(context);
}
@@ -130,10 +124,10 @@ AL_API ALboolean AL_APIENTRY alIsFilter(ALuint filter)
Context = GetContextRef();
if(!Context) return AL_FALSE;
- LockFiltersRead(Context->Device);
+ LockFilterList(Context->Device);
result = ((!filter || LookupFilter(Context->Device, filter)) ?
AL_TRUE : AL_FALSE);
- UnlockFiltersRead(Context->Device);
+ UnlockFilterList(Context->Device);
ALCcontext_DecRef(Context);
@@ -150,7 +144,7 @@ AL_API ALvoid AL_APIENTRY alFilteri(ALuint filter, ALenum param, ALint value)
if(!Context) return;
Device = Context->Device;
- LockFiltersWrite(Device);
+ LockFilterList(Device);
if((ALFilter=LookupFilter(Device, filter)) == NULL)
alSetError(Context, AL_INVALID_NAME, "Invalid filter ID %u", filter);
else
@@ -169,7 +163,7 @@ AL_API ALvoid AL_APIENTRY alFilteri(ALuint filter, ALenum param, ALint value)
V(ALFilter,setParami)(Context, param, value);
}
}
- UnlockFiltersWrite(Device);
+ UnlockFilterList(Device);
ALCcontext_DecRef(Context);
}
@@ -191,7 +185,7 @@ AL_API ALvoid AL_APIENTRY alFilteriv(ALuint filter, ALenum param, const ALint *v
if(!Context) return;
Device = Context->Device;
- LockFiltersWrite(Device);
+ LockFilterList(Device);
if((ALFilter=LookupFilter(Device, filter)) == NULL)
alSetError(Context, AL_INVALID_NAME, "Invalid filter ID %u", filter);
else
@@ -199,7 +193,7 @@ AL_API ALvoid AL_APIENTRY alFilteriv(ALuint filter, ALenum param, const ALint *v
/* Call the appropriate handler */
V(ALFilter,setParamiv)(Context, param, values);
}
- UnlockFiltersWrite(Device);
+ UnlockFilterList(Device);
ALCcontext_DecRef(Context);
}
@@ -214,7 +208,7 @@ AL_API ALvoid AL_APIENTRY alFilterf(ALuint filter, ALenum param, ALfloat value)
if(!Context) return;
Device = Context->Device;
- LockFiltersWrite(Device);
+ LockFilterList(Device);
if((ALFilter=LookupFilter(Device, filter)) == NULL)
alSetError(Context, AL_INVALID_NAME, "Invalid filter ID %u", filter);
else
@@ -222,7 +216,7 @@ AL_API ALvoid AL_APIENTRY alFilterf(ALuint filter, ALenum param, ALfloat value)
/* Call the appropriate handler */
V(ALFilter,setParamf)(Context, param, value);
}
- UnlockFiltersWrite(Device);
+ UnlockFilterList(Device);
ALCcontext_DecRef(Context);
}
@@ -237,7 +231,7 @@ AL_API ALvoid AL_APIENTRY alFilterfv(ALuint filter, ALenum param, const ALfloat
if(!Context) return;
Device = Context->Device;
- LockFiltersWrite(Device);
+ LockFilterList(Device);
if((ALFilter=LookupFilter(Device, filter)) == NULL)
alSetError(Context, AL_INVALID_NAME, "Invalid filter ID %u", filter);
else
@@ -245,7 +239,7 @@ AL_API ALvoid AL_APIENTRY alFilterfv(ALuint filter, ALenum param, const ALfloat
/* Call the appropriate handler */
V(ALFilter,setParamfv)(Context, param, values);
}
- UnlockFiltersWrite(Device);
+ UnlockFilterList(Device);
ALCcontext_DecRef(Context);
}
@@ -260,7 +254,7 @@ AL_API ALvoid AL_APIENTRY alGetFilteri(ALuint filter, ALenum param, ALint *value
if(!Context) return;
Device = Context->Device;
- LockFiltersRead(Device);
+ LockFilterList(Device);
if((ALFilter=LookupFilter(Device, filter)) == NULL)
alSetError(Context, AL_INVALID_NAME, "Invalid filter ID %u", filter);
else
@@ -273,7 +267,7 @@ AL_API ALvoid AL_APIENTRY alGetFilteri(ALuint filter, ALenum param, ALint *value
V(ALFilter,getParami)(Context, param, value);
}
}
- UnlockFiltersRead(Device);
+ UnlockFilterList(Device);
ALCcontext_DecRef(Context);
}
@@ -295,7 +289,7 @@ AL_API ALvoid AL_APIENTRY alGetFilteriv(ALuint filter, ALenum param, ALint *valu
if(!Context) return;
Device = Context->Device;
- LockFiltersRead(Device);
+ LockFilterList(Device);
if((ALFilter=LookupFilter(Device, filter)) == NULL)
alSetError(Context, AL_INVALID_NAME, "Invalid filter ID %u", filter);
else
@@ -303,7 +297,7 @@ AL_API ALvoid AL_APIENTRY alGetFilteriv(ALuint filter, ALenum param, ALint *valu
/* Call the appropriate handler */
V(ALFilter,getParamiv)(Context, param, values);
}
- UnlockFiltersRead(Device);
+ UnlockFilterList(Device);
ALCcontext_DecRef(Context);
}
@@ -318,7 +312,7 @@ AL_API ALvoid AL_APIENTRY alGetFilterf(ALuint filter, ALenum param, ALfloat *val
if(!Context) return;
Device = Context->Device;
- LockFiltersRead(Device);
+ LockFilterList(Device);
if((ALFilter=LookupFilter(Device, filter)) == NULL)
alSetError(Context, AL_INVALID_NAME, "Invalid filter ID %u", filter);
else
@@ -326,7 +320,7 @@ AL_API ALvoid AL_APIENTRY alGetFilterf(ALuint filter, ALenum param, ALfloat *val
/* Call the appropriate handler */
V(ALFilter,getParamf)(Context, param, value);
}
- UnlockFiltersRead(Device);
+ UnlockFilterList(Device);
ALCcontext_DecRef(Context);
}
@@ -341,7 +335,7 @@ AL_API ALvoid AL_APIENTRY alGetFilterfv(ALuint filter, ALenum param, ALfloat *va
if(!Context) return;
Device = Context->Device;
- LockFiltersRead(Device);
+ LockFilterList(Device);
if((ALFilter=LookupFilter(Device, filter)) == NULL)
alSetError(Context, AL_INVALID_NAME, "Invalid filter ID %u", filter);
else
@@ -349,7 +343,7 @@ AL_API ALvoid AL_APIENTRY alGetFilterfv(ALuint filter, ALenum param, ALfloat *va
/* Call the appropriate handler */
V(ALFilter,getParamfv)(Context, param, values);
}
- UnlockFiltersRead(Device);
+ UnlockFilterList(Device);
ALCcontext_DecRef(Context);
}
@@ -625,19 +619,99 @@ static void ALnullfilter_getParamfv(ALfilter *UNUSED(filter), ALCcontext *contex
DEFINE_ALFILTER_VTABLE(ALnullfilter);
-ALvoid ReleaseALFilters(ALCdevice *device)
+static ALfilter *AllocFilter(ALCcontext *context)
{
- ALsizei i;
- for(i = 0;i < device->FilterMap.size;i++)
+ ALCdevice *device = context->Device;
+ FilterSubList *sublist, *subend;
+ ALfilter *filter = NULL;
+ ALsizei lidx = 0;
+ ALsizei slidx;
+
+ almtx_lock(&device->FilterLock);
+ sublist = VECTOR_BEGIN(device->FilterList);
+ subend = VECTOR_END(device->FilterList);
+ for(;sublist != subend;++sublist)
+ {
+ if(sublist->FreeMask)
+ {
+ slidx = CTZ64(sublist->FreeMask);
+ filter = sublist->Filters + slidx;
+ break;
+ }
+ ++lidx;
+ }
+ if(UNLIKELY(!filter))
{
- ALfilter *temp = device->FilterMap.values[i];
- device->FilterMap.values[i] = NULL;
+ const FilterSubList empty_sublist = { 0, NULL };
+ /* Don't allocate so many list entries that the 32-bit ID could
+ * overflow...
+ */
+ if(UNLIKELY(VECTOR_SIZE(device->FilterList) >= 1<<25))
+ {
+ almtx_unlock(&device->FilterLock);
+ return NULL;
+ }
+ lidx = (ALsizei)VECTOR_SIZE(device->FilterList);
+ VECTOR_PUSH_BACK(device->FilterList, empty_sublist);
+ sublist = &VECTOR_BACK(device->FilterList);
+ sublist->FreeMask = ~U64(0);
+ sublist->Filters = al_calloc(16, sizeof(ALfilter)*64);
+ if(UNLIKELY(!sublist->Filters))
+ {
+ VECTOR_POP_BACK(device->FilterList);
+ almtx_unlock(&device->FilterLock);
+ return NULL;
+ }
+
+ slidx = 0;
+ filter = sublist->Filters + slidx;
+ }
+
+ memset(filter, 0, sizeof(*filter));
+ InitFilterParams(filter, AL_FILTER_NULL);
+
+ /* Add 1 to avoid filter ID 0. */
+ filter->id = ((lidx<<6) | slidx) + 1;
+
+ sublist->FreeMask &= ~(U64(1)<<slidx);
+ almtx_unlock(&device->FilterLock);
+
+ return filter;
+}
+
+static void FreeFilter(ALCdevice *device, ALfilter *filter)
+{
+ ALuint id = filter->id - 1;
+ ALsizei lidx = id >> 6;
+ ALsizei slidx = id & 0x3f;
+
+ memset(filter, 0, sizeof(*filter));
+
+ VECTOR_ELEM(device->FilterList, lidx).FreeMask |= U64(1) << slidx;
+}
+
+void ReleaseALFilters(ALCdevice *device)
+{
+ FilterSubList *sublist = VECTOR_BEGIN(device->FilterList);
+ FilterSubList *subend = VECTOR_END(device->FilterList);
+ size_t leftover = 0;
+ for(;sublist != subend;++sublist)
+ {
+ ALuint64 usemask = ~sublist->FreeMask;
+ while(usemask)
+ {
+ ALsizei idx = CTZ64(usemask);
+ ALfilter *filter = sublist->Filters + idx;
- // Release filter structure
- FreeThunkEntry(temp->id);
- memset(temp, 0, sizeof(ALfilter));
- al_free(temp);
+ memset(filter, 0, sizeof(*filter));
+ ++leftover;
+
+ usemask &= ~(U64(1) << idx);
+ }
+ sublist->FreeMask = ~usemask;
}
+ if(leftover > 0)
+ WARN("(%p) Deleted "SZFMT" Filter%s\n", device, leftover, (leftover==1)?"":"s");
}
diff --git a/OpenAL32/alSource.c b/OpenAL32/alSource.c
index 58026aeb..01555b69 100644
--- a/OpenAL32/alSource.c
+++ b/OpenAL32/alSource.c
@@ -84,6 +84,20 @@ static inline ALbuffer *LookupBuffer(ALCdevice *device, ALuint id)
return sublist->Buffers + slidx;
}
+static inline ALfilter *LookupFilter(ALCdevice *device, ALuint id)
+{
+ FilterSubList *sublist;
+ ALuint lidx = (id-1) >> 6;
+ ALsizei slidx = (id-1) & 0x3f;
+
+ if(UNLIKELY(lidx >= VECTOR_SIZE(device->FilterList)))
+ return NULL;
+ sublist = &VECTOR_ELEM(device->FilterList, lidx);
+ if(UNLIKELY(sublist->FreeMask & (U64(1)<<slidx)))
+ return NULL;
+ return sublist->Filters + slidx;
+}
+
static inline ALeffectslot *LookupEffectSlot(ALCcontext *context, ALuint id)
{
id--;
@@ -894,10 +908,10 @@ static ALboolean SetSourceiv(ALsource *Source, ALCcontext *Context, SourceProp p
return AL_TRUE;
case AL_DIRECT_FILTER:
- LockFiltersRead(device);
+ almtx_lock(&device->FilterLock);
if(!(*values == 0 || (filter=LookupFilter(device, *values)) != NULL))
{
- UnlockFiltersRead(device);
+ almtx_unlock(&device->FilterLock);
SETERR_RETURN(Context, AL_INVALID_VALUE, AL_FALSE, "Invalid filter ID %u",
*values);
}
@@ -918,7 +932,7 @@ static ALboolean SetSourceiv(ALsource *Source, ALCcontext *Context, SourceProp p
Source->Direct.GainLF = filter->GainLF;
Source->Direct.LFReference = filter->LFReference;
}
- UnlockFiltersRead(device);
+ almtx_unlock(&device->FilterLock);
DO_UPDATEPROPS();
return AL_TRUE;
@@ -992,10 +1006,10 @@ static ALboolean SetSourceiv(ALsource *Source, ALCcontext *Context, SourceProp p
almtx_unlock(&Context->EffectSlotLock);
SETERR_RETURN(Context, AL_INVALID_VALUE, AL_FALSE, "Invalid send %u", values[1]);
}
- LockFiltersRead(device);
+ almtx_lock(&device->FilterLock);
if(!(values[2] == 0 || (filter=LookupFilter(device, values[2])) != NULL))
{
- UnlockFiltersRead(device);
+ almtx_unlock(&device->FilterLock);
almtx_unlock(&Context->EffectSlotLock);
SETERR_RETURN(Context, AL_INVALID_VALUE, AL_FALSE, "Invalid filter ID %u",
values[2]);
@@ -1018,7 +1032,7 @@ static ALboolean SetSourceiv(ALsource *Source, ALCcontext *Context, SourceProp p
Source->Send[values[1]].GainLF = filter->GainLF;
Source->Send[values[1]].LFReference = filter->LFReference;
}
- UnlockFiltersRead(device);
+ almtx_unlock(&device->FilterLock);
if(slot != Source->Send[values[1]].Slot && IsPlayingOrPaused(Source))
{