2007-11-13 18:02:18 -08:00
|
|
|
/**
|
|
|
|
* OpenAL cross platform audio library
|
|
|
|
* Copyright (C) 1999-2000 by authors.
|
|
|
|
* This library is free software; you can redistribute it and/or
|
|
|
|
* modify it under the terms of the GNU Library General Public
|
|
|
|
* License as published by the Free Software Foundation; either
|
|
|
|
* version 2 of the License, or (at your option) any later version.
|
|
|
|
*
|
|
|
|
* This library is distributed in the hope that it will be useful,
|
|
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
|
|
* Library General Public License for more details.
|
|
|
|
*
|
|
|
|
* You should have received a copy of the GNU Library General Public
|
|
|
|
* License along with this library; if not, write to the
|
2014-08-18 14:11:03 +02:00
|
|
|
* Free Software Foundation, Inc.,
|
|
|
|
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
2007-11-13 18:02:18 -08:00
|
|
|
* Or go to http://www.gnu.org/copyleft/lgpl.html
|
|
|
|
*/
|
|
|
|
|
2008-01-16 14:09:04 -08:00
|
|
|
#include "config.h"
|
|
|
|
|
2007-11-13 18:02:18 -08:00
|
|
|
#include <stdlib.h>
|
|
|
|
#include "alMain.h"
|
|
|
|
#include "AL/alc.h"
|
2013-11-28 01:53:05 -08:00
|
|
|
#include "AL/al.h"
|
2009-08-16 00:54:08 -07:00
|
|
|
#include "AL/alext.h"
|
2007-11-13 18:02:18 -08:00
|
|
|
#include "alError.h"
|
2016-05-11 18:40:17 -07:00
|
|
|
#include "alListener.h"
|
2008-11-25 18:56:10 -08:00
|
|
|
#include "alSource.h"
|
2011-08-22 17:13:03 -07:00
|
|
|
#include "alAuxEffectSlot.h"
|
2013-12-17 23:03:34 -08:00
|
|
|
|
2014-11-01 15:55:18 -07:00
|
|
|
#include "backends/base.h"
|
2012-09-14 03:10:12 -07:00
|
|
|
|
2007-11-13 18:02:18 -08:00
|
|
|
|
|
|
|
static const ALchar alVendor[] = "OpenAL Community";
|
2008-10-25 15:48:17 -07:00
|
|
|
static const ALchar alVersion[] = "1.1 ALSOFT "ALSOFT_VERSION;
|
2007-12-14 08:50:54 -08:00
|
|
|
static const ALchar alRenderer[] = "OpenAL Soft";
|
2007-11-13 18:02:18 -08:00
|
|
|
|
|
|
|
// Error Messages
|
|
|
|
static const ALchar alNoError[] = "No Error";
|
|
|
|
static const ALchar alErrInvalidName[] = "Invalid Name";
|
|
|
|
static const ALchar alErrInvalidEnum[] = "Invalid Enum";
|
|
|
|
static const ALchar alErrInvalidValue[] = "Invalid Value";
|
|
|
|
static const ALchar alErrInvalidOp[] = "Invalid Operation";
|
|
|
|
static const ALchar alErrOutOfMemory[] = "Out of Memory";
|
|
|
|
|
2010-03-19 14:34:18 -07:00
|
|
|
AL_API ALvoid AL_APIENTRY alEnable(ALenum capability)
|
2007-11-13 18:02:18 -08:00
|
|
|
{
|
2013-10-07 08:50:17 -07:00
|
|
|
ALCcontext *context;
|
2007-11-13 18:02:18 -08:00
|
|
|
|
2013-10-07 08:50:17 -07:00
|
|
|
context = GetContextRef();
|
|
|
|
if(!context) return;
|
2007-11-13 18:02:18 -08:00
|
|
|
|
2016-05-13 20:21:20 -07:00
|
|
|
WriteLock(&context->PropLock);
|
2013-10-07 08:50:17 -07:00
|
|
|
switch(capability)
|
2007-11-13 18:02:18 -08:00
|
|
|
{
|
2013-10-07 08:50:17 -07:00
|
|
|
case AL_SOURCE_DISTANCE_MODEL:
|
|
|
|
context->SourceDistanceModel = AL_TRUE;
|
|
|
|
break;
|
2009-11-27 20:05:21 -08:00
|
|
|
|
2013-10-07 08:50:17 -07:00
|
|
|
default:
|
|
|
|
SET_ERROR_AND_GOTO(context, AL_INVALID_ENUM, done);
|
2007-11-13 18:02:18 -08:00
|
|
|
}
|
Provide asynchronous property updates for sources
This necessitates a change in how source updates are handled. Rather than just
being able to update sources when a dependent object state is changed (e.g. a
listener gain change), now all source updates must be proactively provided.
Consequently, apps that do not utilize any deferring (AL_SOFT_defer_updates or
alcSuspendContext/alcProcessContext) may utilize more CPU since it'll be
filling out more update containers for the mixer thread to use.
The upside is that there's less blocking between the app's calling thread and
the mixer thread, particularly for vectors and other multi-value properties
(filters and sends). Deferring behavior when used is also improved, since
updates that shouldn't be applied yet are simply not provided. And when they
are provided, the mixer doesn't have to ignore them, meaning the actual
deferring of a context doesn't have to synchrnously force an update -- the
process call will send any pending updates, which the mixer will apply even if
another deferral occurs before the mixer runs, because it'll still be there
waiting on the next mixer invocation.
There is one slight bug introduced by this commit. When a listener change is
made, or changes to multiple sources while updates are being deferred, it is
possible for the mixer to run while the sources are prepping their updates,
causing some of the source updates to be seen before the other. This will be
fixed in short order.
2016-05-14 23:43:40 -07:00
|
|
|
if(!ATOMIC_LOAD(&context->DeferUpdates, almemory_order_acquire))
|
2016-08-23 19:17:17 -07:00
|
|
|
UpdateListenerProps(context);
|
2009-08-16 15:09:36 -07:00
|
|
|
|
2013-10-07 08:50:17 -07:00
|
|
|
done:
|
2016-05-13 20:21:20 -07:00
|
|
|
WriteUnlock(&context->PropLock);
|
2013-10-07 08:50:17 -07:00
|
|
|
ALCcontext_DecRef(context);
|
2007-11-13 18:02:18 -08:00
|
|
|
}
|
|
|
|
|
2010-03-19 14:34:18 -07:00
|
|
|
AL_API ALvoid AL_APIENTRY alDisable(ALenum capability)
|
2007-11-13 18:02:18 -08:00
|
|
|
{
|
2013-10-07 08:50:17 -07:00
|
|
|
ALCcontext *context;
|
2007-11-13 18:02:18 -08:00
|
|
|
|
2013-10-07 08:50:17 -07:00
|
|
|
context = GetContextRef();
|
|
|
|
if(!context) return;
|
2007-11-13 18:02:18 -08:00
|
|
|
|
2016-05-13 20:21:20 -07:00
|
|
|
WriteLock(&context->PropLock);
|
2013-10-07 08:50:17 -07:00
|
|
|
switch(capability)
|
2007-11-13 18:02:18 -08:00
|
|
|
{
|
2013-10-07 08:50:17 -07:00
|
|
|
case AL_SOURCE_DISTANCE_MODEL:
|
|
|
|
context->SourceDistanceModel = AL_FALSE;
|
|
|
|
break;
|
2009-11-27 20:05:21 -08:00
|
|
|
|
2013-10-07 08:50:17 -07:00
|
|
|
default:
|
|
|
|
SET_ERROR_AND_GOTO(context, AL_INVALID_ENUM, done);
|
2007-11-13 18:02:18 -08:00
|
|
|
}
|
Provide asynchronous property updates for sources
This necessitates a change in how source updates are handled. Rather than just
being able to update sources when a dependent object state is changed (e.g. a
listener gain change), now all source updates must be proactively provided.
Consequently, apps that do not utilize any deferring (AL_SOFT_defer_updates or
alcSuspendContext/alcProcessContext) may utilize more CPU since it'll be
filling out more update containers for the mixer thread to use.
The upside is that there's less blocking between the app's calling thread and
the mixer thread, particularly for vectors and other multi-value properties
(filters and sends). Deferring behavior when used is also improved, since
updates that shouldn't be applied yet are simply not provided. And when they
are provided, the mixer doesn't have to ignore them, meaning the actual
deferring of a context doesn't have to synchrnously force an update -- the
process call will send any pending updates, which the mixer will apply even if
another deferral occurs before the mixer runs, because it'll still be there
waiting on the next mixer invocation.
There is one slight bug introduced by this commit. When a listener change is
made, or changes to multiple sources while updates are being deferred, it is
possible for the mixer to run while the sources are prepping their updates,
causing some of the source updates to be seen before the other. This will be
fixed in short order.
2016-05-14 23:43:40 -07:00
|
|
|
if(!ATOMIC_LOAD(&context->DeferUpdates, almemory_order_acquire))
|
2016-08-23 19:17:17 -07:00
|
|
|
UpdateListenerProps(context);
|
2009-08-16 15:09:36 -07:00
|
|
|
|
2013-10-07 08:50:17 -07:00
|
|
|
done:
|
2016-05-13 20:21:20 -07:00
|
|
|
WriteUnlock(&context->PropLock);
|
2013-10-07 08:50:17 -07:00
|
|
|
ALCcontext_DecRef(context);
|
2007-11-13 18:02:18 -08:00
|
|
|
}
|
|
|
|
|
2010-03-19 14:34:18 -07:00
|
|
|
AL_API ALboolean AL_APIENTRY alIsEnabled(ALenum capability)
|
2007-11-13 18:02:18 -08:00
|
|
|
{
|
2013-10-07 08:50:17 -07:00
|
|
|
ALCcontext *context;
|
2007-11-13 18:02:18 -08:00
|
|
|
ALboolean value=AL_FALSE;
|
|
|
|
|
2013-10-07 08:50:17 -07:00
|
|
|
context = GetContextRef();
|
|
|
|
if(!context) return AL_FALSE;
|
2007-11-13 18:02:18 -08:00
|
|
|
|
2013-10-07 08:50:17 -07:00
|
|
|
switch(capability)
|
2007-11-13 18:02:18 -08:00
|
|
|
{
|
2013-10-07 08:50:17 -07:00
|
|
|
case AL_SOURCE_DISTANCE_MODEL:
|
|
|
|
value = context->SourceDistanceModel;
|
|
|
|
break;
|
2009-11-27 20:05:21 -08:00
|
|
|
|
2013-10-07 08:50:17 -07:00
|
|
|
default:
|
|
|
|
SET_ERROR_AND_GOTO(context, AL_INVALID_ENUM, done);
|
2007-11-13 18:02:18 -08:00
|
|
|
}
|
|
|
|
|
2013-10-07 08:50:17 -07:00
|
|
|
done:
|
|
|
|
ALCcontext_DecRef(context);
|
2009-08-16 15:09:36 -07:00
|
|
|
|
2007-11-13 18:02:18 -08:00
|
|
|
return value;
|
|
|
|
}
|
|
|
|
|
2010-03-19 14:34:18 -07:00
|
|
|
AL_API ALboolean AL_APIENTRY alGetBoolean(ALenum pname)
|
2007-11-13 18:02:18 -08:00
|
|
|
{
|
2013-10-07 08:50:17 -07:00
|
|
|
ALCcontext *context;
|
2007-11-13 18:02:18 -08:00
|
|
|
ALboolean value=AL_FALSE;
|
|
|
|
|
2013-10-07 08:50:17 -07:00
|
|
|
context = GetContextRef();
|
|
|
|
if(!context) return AL_FALSE;
|
2007-11-13 18:02:18 -08:00
|
|
|
|
2013-10-07 08:50:17 -07:00
|
|
|
switch(pname)
|
2009-08-16 15:09:36 -07:00
|
|
|
{
|
2013-10-07 08:50:17 -07:00
|
|
|
case AL_DOPPLER_FACTOR:
|
|
|
|
if(context->DopplerFactor != 0.0f)
|
|
|
|
value = AL_TRUE;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case AL_DOPPLER_VELOCITY:
|
|
|
|
if(context->DopplerVelocity != 0.0f)
|
|
|
|
value = AL_TRUE;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case AL_DISTANCE_MODEL:
|
|
|
|
if(context->DistanceModel == AL_INVERSE_DISTANCE_CLAMPED)
|
|
|
|
value = AL_TRUE;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case AL_SPEED_OF_SOUND:
|
|
|
|
if(context->SpeedOfSound != 0.0f)
|
|
|
|
value = AL_TRUE;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case AL_DEFERRED_UPDATES_SOFT:
|
Provide asynchronous property updates for sources
This necessitates a change in how source updates are handled. Rather than just
being able to update sources when a dependent object state is changed (e.g. a
listener gain change), now all source updates must be proactively provided.
Consequently, apps that do not utilize any deferring (AL_SOFT_defer_updates or
alcSuspendContext/alcProcessContext) may utilize more CPU since it'll be
filling out more update containers for the mixer thread to use.
The upside is that there's less blocking between the app's calling thread and
the mixer thread, particularly for vectors and other multi-value properties
(filters and sends). Deferring behavior when used is also improved, since
updates that shouldn't be applied yet are simply not provided. And when they
are provided, the mixer doesn't have to ignore them, meaning the actual
deferring of a context doesn't have to synchrnously force an update -- the
process call will send any pending updates, which the mixer will apply even if
another deferral occurs before the mixer runs, because it'll still be there
waiting on the next mixer invocation.
There is one slight bug introduced by this commit. When a listener change is
made, or changes to multiple sources while updates are being deferred, it is
possible for the mixer to run while the sources are prepping their updates,
causing some of the source updates to be seen before the other. This will be
fixed in short order.
2016-05-14 23:43:40 -07:00
|
|
|
value = ATOMIC_LOAD(&context->DeferUpdates, almemory_order_acquire);
|
2013-10-07 08:50:17 -07:00
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
|
|
|
SET_ERROR_AND_GOTO(context, AL_INVALID_ENUM, done);
|
2007-11-13 18:02:18 -08:00
|
|
|
}
|
|
|
|
|
2013-10-07 08:50:17 -07:00
|
|
|
done:
|
|
|
|
ALCcontext_DecRef(context);
|
2009-08-16 15:09:36 -07:00
|
|
|
|
2007-11-13 18:02:18 -08:00
|
|
|
return value;
|
|
|
|
}
|
|
|
|
|
2010-03-19 14:34:18 -07:00
|
|
|
AL_API ALdouble AL_APIENTRY alGetDouble(ALenum pname)
|
2007-11-13 18:02:18 -08:00
|
|
|
{
|
2013-10-07 08:50:17 -07:00
|
|
|
ALCcontext *context;
|
2007-11-13 18:02:18 -08:00
|
|
|
ALdouble value = 0.0;
|
|
|
|
|
2013-10-07 08:50:17 -07:00
|
|
|
context = GetContextRef();
|
|
|
|
if(!context) return 0.0;
|
2009-08-16 15:09:36 -07:00
|
|
|
|
2013-10-07 08:50:17 -07:00
|
|
|
switch(pname)
|
2007-11-13 18:02:18 -08:00
|
|
|
{
|
2013-10-07 08:50:17 -07:00
|
|
|
case AL_DOPPLER_FACTOR:
|
|
|
|
value = (ALdouble)context->DopplerFactor;
|
|
|
|
break;
|
2007-11-13 18:02:18 -08:00
|
|
|
|
2013-10-07 08:50:17 -07:00
|
|
|
case AL_DOPPLER_VELOCITY:
|
|
|
|
value = (ALdouble)context->DopplerVelocity;
|
|
|
|
break;
|
2007-11-13 18:02:18 -08:00
|
|
|
|
2013-10-07 08:50:17 -07:00
|
|
|
case AL_DISTANCE_MODEL:
|
|
|
|
value = (ALdouble)context->DistanceModel;
|
|
|
|
break;
|
2007-11-13 18:02:18 -08:00
|
|
|
|
2013-10-07 08:50:17 -07:00
|
|
|
case AL_SPEED_OF_SOUND:
|
|
|
|
value = (ALdouble)context->SpeedOfSound;
|
|
|
|
break;
|
2007-11-13 18:02:18 -08:00
|
|
|
|
2013-10-07 08:50:17 -07:00
|
|
|
case AL_DEFERRED_UPDATES_SOFT:
|
Provide asynchronous property updates for sources
This necessitates a change in how source updates are handled. Rather than just
being able to update sources when a dependent object state is changed (e.g. a
listener gain change), now all source updates must be proactively provided.
Consequently, apps that do not utilize any deferring (AL_SOFT_defer_updates or
alcSuspendContext/alcProcessContext) may utilize more CPU since it'll be
filling out more update containers for the mixer thread to use.
The upside is that there's less blocking between the app's calling thread and
the mixer thread, particularly for vectors and other multi-value properties
(filters and sends). Deferring behavior when used is also improved, since
updates that shouldn't be applied yet are simply not provided. And when they
are provided, the mixer doesn't have to ignore them, meaning the actual
deferring of a context doesn't have to synchrnously force an update -- the
process call will send any pending updates, which the mixer will apply even if
another deferral occurs before the mixer runs, because it'll still be there
waiting on the next mixer invocation.
There is one slight bug introduced by this commit. When a listener change is
made, or changes to multiple sources while updates are being deferred, it is
possible for the mixer to run while the sources are prepping their updates,
causing some of the source updates to be seen before the other. This will be
fixed in short order.
2016-05-14 23:43:40 -07:00
|
|
|
value = (ALdouble)ATOMIC_LOAD(&context->DeferUpdates, almemory_order_acquire);
|
2013-10-07 08:50:17 -07:00
|
|
|
break;
|
2011-07-16 16:59:20 -07:00
|
|
|
|
2013-10-07 08:50:17 -07:00
|
|
|
default:
|
|
|
|
SET_ERROR_AND_GOTO(context, AL_INVALID_ENUM, done);
|
2009-08-16 15:09:36 -07:00
|
|
|
}
|
|
|
|
|
2013-10-07 08:50:17 -07:00
|
|
|
done:
|
|
|
|
ALCcontext_DecRef(context);
|
2009-08-16 15:09:36 -07:00
|
|
|
|
|
|
|
return value;
|
|
|
|
}
|
|
|
|
|
2010-03-19 14:34:18 -07:00
|
|
|
AL_API ALfloat AL_APIENTRY alGetFloat(ALenum pname)
|
2009-08-16 15:09:36 -07:00
|
|
|
{
|
2013-10-07 08:50:17 -07:00
|
|
|
ALCcontext *context;
|
2009-08-16 15:09:36 -07:00
|
|
|
ALfloat value = 0.0f;
|
|
|
|
|
2013-10-07 08:50:17 -07:00
|
|
|
context = GetContextRef();
|
|
|
|
if(!context) return 0.0f;
|
2009-08-16 15:09:36 -07:00
|
|
|
|
2013-10-07 08:50:17 -07:00
|
|
|
switch(pname)
|
2009-08-16 15:09:36 -07:00
|
|
|
{
|
2013-10-07 08:50:17 -07:00
|
|
|
case AL_DOPPLER_FACTOR:
|
|
|
|
value = context->DopplerFactor;
|
|
|
|
break;
|
2009-08-16 15:09:36 -07:00
|
|
|
|
2013-10-07 08:50:17 -07:00
|
|
|
case AL_DOPPLER_VELOCITY:
|
|
|
|
value = context->DopplerVelocity;
|
|
|
|
break;
|
2009-08-16 15:09:36 -07:00
|
|
|
|
2013-10-07 08:50:17 -07:00
|
|
|
case AL_DISTANCE_MODEL:
|
|
|
|
value = (ALfloat)context->DistanceModel;
|
|
|
|
break;
|
2009-08-16 15:09:36 -07:00
|
|
|
|
2013-10-07 08:50:17 -07:00
|
|
|
case AL_SPEED_OF_SOUND:
|
|
|
|
value = context->SpeedOfSound;
|
|
|
|
break;
|
2007-11-13 18:02:18 -08:00
|
|
|
|
2013-10-07 08:50:17 -07:00
|
|
|
case AL_DEFERRED_UPDATES_SOFT:
|
Provide asynchronous property updates for sources
This necessitates a change in how source updates are handled. Rather than just
being able to update sources when a dependent object state is changed (e.g. a
listener gain change), now all source updates must be proactively provided.
Consequently, apps that do not utilize any deferring (AL_SOFT_defer_updates or
alcSuspendContext/alcProcessContext) may utilize more CPU since it'll be
filling out more update containers for the mixer thread to use.
The upside is that there's less blocking between the app's calling thread and
the mixer thread, particularly for vectors and other multi-value properties
(filters and sends). Deferring behavior when used is also improved, since
updates that shouldn't be applied yet are simply not provided. And when they
are provided, the mixer doesn't have to ignore them, meaning the actual
deferring of a context doesn't have to synchrnously force an update -- the
process call will send any pending updates, which the mixer will apply even if
another deferral occurs before the mixer runs, because it'll still be there
waiting on the next mixer invocation.
There is one slight bug introduced by this commit. When a listener change is
made, or changes to multiple sources while updates are being deferred, it is
possible for the mixer to run while the sources are prepping their updates,
causing some of the source updates to be seen before the other. This will be
fixed in short order.
2016-05-14 23:43:40 -07:00
|
|
|
value = (ALfloat)ATOMIC_LOAD(&context->DeferUpdates, almemory_order_acquire);
|
2013-10-07 08:50:17 -07:00
|
|
|
break;
|
2011-07-16 16:59:20 -07:00
|
|
|
|
2013-10-07 08:50:17 -07:00
|
|
|
default:
|
|
|
|
SET_ERROR_AND_GOTO(context, AL_INVALID_ENUM, done);
|
2007-11-13 18:02:18 -08:00
|
|
|
}
|
2009-08-16 15:09:36 -07:00
|
|
|
|
2013-10-07 08:50:17 -07:00
|
|
|
done:
|
|
|
|
ALCcontext_DecRef(context);
|
2009-08-16 15:09:36 -07:00
|
|
|
|
|
|
|
return value;
|
|
|
|
}
|
|
|
|
|
2010-03-19 14:34:18 -07:00
|
|
|
AL_API ALint AL_APIENTRY alGetInteger(ALenum pname)
|
2009-08-16 15:09:36 -07:00
|
|
|
{
|
2013-10-07 08:50:17 -07:00
|
|
|
ALCcontext *context;
|
2009-08-16 15:09:36 -07:00
|
|
|
ALint value = 0;
|
|
|
|
|
2013-10-07 08:50:17 -07:00
|
|
|
context = GetContextRef();
|
|
|
|
if(!context) return 0;
|
2009-08-16 15:09:36 -07:00
|
|
|
|
2013-10-07 08:50:17 -07:00
|
|
|
switch(pname)
|
2007-11-13 18:02:18 -08:00
|
|
|
{
|
2013-10-07 08:50:17 -07:00
|
|
|
case AL_DOPPLER_FACTOR:
|
|
|
|
value = (ALint)context->DopplerFactor;
|
|
|
|
break;
|
2009-08-16 15:09:36 -07:00
|
|
|
|
2013-10-07 08:50:17 -07:00
|
|
|
case AL_DOPPLER_VELOCITY:
|
|
|
|
value = (ALint)context->DopplerVelocity;
|
|
|
|
break;
|
2009-08-16 15:09:36 -07:00
|
|
|
|
2013-10-07 08:50:17 -07:00
|
|
|
case AL_DISTANCE_MODEL:
|
|
|
|
value = (ALint)context->DistanceModel;
|
|
|
|
break;
|
2009-08-16 15:09:36 -07:00
|
|
|
|
2013-10-07 08:50:17 -07:00
|
|
|
case AL_SPEED_OF_SOUND:
|
|
|
|
value = (ALint)context->SpeedOfSound;
|
|
|
|
break;
|
2009-08-16 15:09:36 -07:00
|
|
|
|
2013-10-07 08:50:17 -07:00
|
|
|
case AL_DEFERRED_UPDATES_SOFT:
|
Provide asynchronous property updates for sources
This necessitates a change in how source updates are handled. Rather than just
being able to update sources when a dependent object state is changed (e.g. a
listener gain change), now all source updates must be proactively provided.
Consequently, apps that do not utilize any deferring (AL_SOFT_defer_updates or
alcSuspendContext/alcProcessContext) may utilize more CPU since it'll be
filling out more update containers for the mixer thread to use.
The upside is that there's less blocking between the app's calling thread and
the mixer thread, particularly for vectors and other multi-value properties
(filters and sends). Deferring behavior when used is also improved, since
updates that shouldn't be applied yet are simply not provided. And when they
are provided, the mixer doesn't have to ignore them, meaning the actual
deferring of a context doesn't have to synchrnously force an update -- the
process call will send any pending updates, which the mixer will apply even if
another deferral occurs before the mixer runs, because it'll still be there
waiting on the next mixer invocation.
There is one slight bug introduced by this commit. When a listener change is
made, or changes to multiple sources while updates are being deferred, it is
possible for the mixer to run while the sources are prepping their updates,
causing some of the source updates to be seen before the other. This will be
fixed in short order.
2016-05-14 23:43:40 -07:00
|
|
|
value = (ALint)ATOMIC_LOAD(&context->DeferUpdates, almemory_order_acquire);
|
2013-10-07 08:50:17 -07:00
|
|
|
break;
|
2011-07-16 16:59:20 -07:00
|
|
|
|
2013-10-07 08:50:17 -07:00
|
|
|
default:
|
|
|
|
SET_ERROR_AND_GOTO(context, AL_INVALID_ENUM, done);
|
2007-11-13 18:02:18 -08:00
|
|
|
}
|
|
|
|
|
2013-10-07 08:50:17 -07:00
|
|
|
done:
|
|
|
|
ALCcontext_DecRef(context);
|
2009-08-16 15:09:36 -07:00
|
|
|
|
2007-11-13 18:02:18 -08:00
|
|
|
return value;
|
|
|
|
}
|
|
|
|
|
2013-11-28 01:53:05 -08:00
|
|
|
AL_API ALint64SOFT AL_APIENTRY alGetInteger64SOFT(ALenum pname)
|
|
|
|
{
|
|
|
|
ALCcontext *context;
|
|
|
|
ALint64SOFT value = 0;
|
|
|
|
|
|
|
|
context = GetContextRef();
|
|
|
|
if(!context) return 0;
|
|
|
|
|
|
|
|
switch(pname)
|
|
|
|
{
|
|
|
|
case AL_DOPPLER_FACTOR:
|
|
|
|
value = (ALint64SOFT)context->DopplerFactor;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case AL_DOPPLER_VELOCITY:
|
|
|
|
value = (ALint64SOFT)context->DopplerVelocity;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case AL_DISTANCE_MODEL:
|
|
|
|
value = (ALint64SOFT)context->DistanceModel;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case AL_SPEED_OF_SOUND:
|
|
|
|
value = (ALint64SOFT)context->SpeedOfSound;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case AL_DEFERRED_UPDATES_SOFT:
|
Provide asynchronous property updates for sources
This necessitates a change in how source updates are handled. Rather than just
being able to update sources when a dependent object state is changed (e.g. a
listener gain change), now all source updates must be proactively provided.
Consequently, apps that do not utilize any deferring (AL_SOFT_defer_updates or
alcSuspendContext/alcProcessContext) may utilize more CPU since it'll be
filling out more update containers for the mixer thread to use.
The upside is that there's less blocking between the app's calling thread and
the mixer thread, particularly for vectors and other multi-value properties
(filters and sends). Deferring behavior when used is also improved, since
updates that shouldn't be applied yet are simply not provided. And when they
are provided, the mixer doesn't have to ignore them, meaning the actual
deferring of a context doesn't have to synchrnously force an update -- the
process call will send any pending updates, which the mixer will apply even if
another deferral occurs before the mixer runs, because it'll still be there
waiting on the next mixer invocation.
There is one slight bug introduced by this commit. When a listener change is
made, or changes to multiple sources while updates are being deferred, it is
possible for the mixer to run while the sources are prepping their updates,
causing some of the source updates to be seen before the other. This will be
fixed in short order.
2016-05-14 23:43:40 -07:00
|
|
|
value = (ALint64SOFT)ATOMIC_LOAD(&context->DeferUpdates, almemory_order_acquire);
|
2013-11-28 01:53:05 -08:00
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
|
|
|
SET_ERROR_AND_GOTO(context, AL_INVALID_ENUM, done);
|
|
|
|
}
|
|
|
|
|
|
|
|
done:
|
|
|
|
ALCcontext_DecRef(context);
|
|
|
|
|
|
|
|
return value;
|
|
|
|
}
|
|
|
|
|
2012-04-24 02:51:57 -07:00
|
|
|
AL_API ALvoid AL_APIENTRY alGetBooleanv(ALenum pname, ALboolean *values)
|
2007-11-13 18:02:18 -08:00
|
|
|
{
|
2013-10-07 08:50:17 -07:00
|
|
|
ALCcontext *context;
|
2007-11-13 18:02:18 -08:00
|
|
|
|
2012-04-24 02:51:57 -07:00
|
|
|
if(values)
|
2007-11-13 18:02:18 -08:00
|
|
|
{
|
2009-08-16 15:09:36 -07:00
|
|
|
switch(pname)
|
2007-11-13 18:02:18 -08:00
|
|
|
{
|
|
|
|
case AL_DOPPLER_FACTOR:
|
|
|
|
case AL_DOPPLER_VELOCITY:
|
|
|
|
case AL_DISTANCE_MODEL:
|
|
|
|
case AL_SPEED_OF_SOUND:
|
2011-07-16 16:59:20 -07:00
|
|
|
case AL_DEFERRED_UPDATES_SOFT:
|
2012-04-24 02:51:57 -07:00
|
|
|
values[0] = alGetBoolean(pname);
|
2011-07-11 00:51:18 -07:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-10-07 08:50:17 -07:00
|
|
|
context = GetContextRef();
|
|
|
|
if(!context) return;
|
2007-11-13 18:02:18 -08:00
|
|
|
|
2013-10-07 08:50:17 -07:00
|
|
|
if(!(values))
|
|
|
|
SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done);
|
|
|
|
switch(pname)
|
2011-07-11 00:51:18 -07:00
|
|
|
{
|
2013-10-07 08:50:17 -07:00
|
|
|
default:
|
|
|
|
SET_ERROR_AND_GOTO(context, AL_INVALID_ENUM, done);
|
2007-11-13 18:02:18 -08:00
|
|
|
}
|
|
|
|
|
2013-10-07 08:50:17 -07:00
|
|
|
done:
|
|
|
|
ALCcontext_DecRef(context);
|
2007-11-13 18:02:18 -08:00
|
|
|
}
|
|
|
|
|
2012-04-24 02:51:57 -07:00
|
|
|
AL_API ALvoid AL_APIENTRY alGetDoublev(ALenum pname, ALdouble *values)
|
2007-11-13 18:02:18 -08:00
|
|
|
{
|
2013-10-07 08:50:17 -07:00
|
|
|
ALCcontext *context;
|
2007-11-13 18:02:18 -08:00
|
|
|
|
2012-04-24 02:51:57 -07:00
|
|
|
if(values)
|
2007-11-13 18:02:18 -08:00
|
|
|
{
|
2009-08-16 15:09:36 -07:00
|
|
|
switch(pname)
|
2007-11-13 18:02:18 -08:00
|
|
|
{
|
|
|
|
case AL_DOPPLER_FACTOR:
|
|
|
|
case AL_DOPPLER_VELOCITY:
|
|
|
|
case AL_DISTANCE_MODEL:
|
|
|
|
case AL_SPEED_OF_SOUND:
|
2011-07-16 16:59:20 -07:00
|
|
|
case AL_DEFERRED_UPDATES_SOFT:
|
2012-04-24 02:51:57 -07:00
|
|
|
values[0] = alGetDouble(pname);
|
2011-07-11 00:51:18 -07:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-10-07 08:50:17 -07:00
|
|
|
context = GetContextRef();
|
|
|
|
if(!context) return;
|
2009-08-16 00:54:08 -07:00
|
|
|
|
2013-10-07 08:50:17 -07:00
|
|
|
if(!(values))
|
|
|
|
SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done);
|
|
|
|
switch(pname)
|
2011-07-11 00:51:18 -07:00
|
|
|
{
|
2013-10-07 08:50:17 -07:00
|
|
|
default:
|
|
|
|
SET_ERROR_AND_GOTO(context, AL_INVALID_ENUM, done);
|
2007-11-13 18:02:18 -08:00
|
|
|
}
|
|
|
|
|
2013-10-07 08:50:17 -07:00
|
|
|
done:
|
|
|
|
ALCcontext_DecRef(context);
|
2007-11-13 18:02:18 -08:00
|
|
|
}
|
|
|
|
|
2012-04-24 02:51:57 -07:00
|
|
|
AL_API ALvoid AL_APIENTRY alGetFloatv(ALenum pname, ALfloat *values)
|
2007-11-13 18:02:18 -08:00
|
|
|
{
|
2013-10-07 08:50:17 -07:00
|
|
|
ALCcontext *context;
|
2007-11-13 18:02:18 -08:00
|
|
|
|
2012-04-24 02:51:57 -07:00
|
|
|
if(values)
|
2007-11-13 18:02:18 -08:00
|
|
|
{
|
2009-08-16 15:09:36 -07:00
|
|
|
switch(pname)
|
2007-11-13 18:02:18 -08:00
|
|
|
{
|
2009-08-16 15:09:36 -07:00
|
|
|
case AL_DOPPLER_FACTOR:
|
|
|
|
case AL_DOPPLER_VELOCITY:
|
|
|
|
case AL_DISTANCE_MODEL:
|
|
|
|
case AL_SPEED_OF_SOUND:
|
2011-07-16 16:59:20 -07:00
|
|
|
case AL_DEFERRED_UPDATES_SOFT:
|
2012-04-24 02:51:57 -07:00
|
|
|
values[0] = alGetFloat(pname);
|
2011-07-11 00:51:18 -07:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-10-07 08:50:17 -07:00
|
|
|
context = GetContextRef();
|
|
|
|
if(!context) return;
|
2007-11-13 18:02:18 -08:00
|
|
|
|
2013-10-07 08:50:17 -07:00
|
|
|
if(!(values))
|
|
|
|
SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done);
|
|
|
|
switch(pname)
|
2011-07-11 00:51:18 -07:00
|
|
|
{
|
2013-10-07 08:50:17 -07:00
|
|
|
default:
|
|
|
|
SET_ERROR_AND_GOTO(context, AL_INVALID_ENUM, done);
|
2007-11-13 18:02:18 -08:00
|
|
|
}
|
|
|
|
|
2013-10-07 08:50:17 -07:00
|
|
|
done:
|
|
|
|
ALCcontext_DecRef(context);
|
2007-11-13 18:02:18 -08:00
|
|
|
}
|
|
|
|
|
2012-04-24 02:51:57 -07:00
|
|
|
AL_API ALvoid AL_APIENTRY alGetIntegerv(ALenum pname, ALint *values)
|
2007-11-13 18:02:18 -08:00
|
|
|
{
|
2013-10-07 08:50:17 -07:00
|
|
|
ALCcontext *context;
|
2007-11-13 18:02:18 -08:00
|
|
|
|
2012-04-24 02:51:57 -07:00
|
|
|
if(values)
|
2007-11-13 18:02:18 -08:00
|
|
|
{
|
2009-08-16 15:09:36 -07:00
|
|
|
switch(pname)
|
2007-11-13 18:02:18 -08:00
|
|
|
{
|
2009-08-16 15:09:36 -07:00
|
|
|
case AL_DOPPLER_FACTOR:
|
|
|
|
case AL_DOPPLER_VELOCITY:
|
|
|
|
case AL_DISTANCE_MODEL:
|
|
|
|
case AL_SPEED_OF_SOUND:
|
2011-07-16 16:59:20 -07:00
|
|
|
case AL_DEFERRED_UPDATES_SOFT:
|
2012-04-24 02:51:57 -07:00
|
|
|
values[0] = alGetInteger(pname);
|
2011-07-11 00:51:18 -07:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-10-07 08:50:17 -07:00
|
|
|
context = GetContextRef();
|
|
|
|
if(!context) return;
|
2007-11-13 18:02:18 -08:00
|
|
|
|
2013-10-07 08:50:17 -07:00
|
|
|
switch(pname)
|
2011-07-11 00:51:18 -07:00
|
|
|
{
|
2013-10-07 08:50:17 -07:00
|
|
|
default:
|
|
|
|
SET_ERROR_AND_GOTO(context, AL_INVALID_ENUM, done);
|
2007-11-13 18:02:18 -08:00
|
|
|
}
|
|
|
|
|
2013-10-07 08:50:17 -07:00
|
|
|
done:
|
|
|
|
ALCcontext_DecRef(context);
|
2007-11-13 18:02:18 -08:00
|
|
|
}
|
|
|
|
|
2013-11-28 01:53:05 -08:00
|
|
|
AL_API void AL_APIENTRY alGetInteger64vSOFT(ALenum pname, ALint64SOFT *values)
|
|
|
|
{
|
|
|
|
ALCcontext *context;
|
|
|
|
|
|
|
|
if(values)
|
|
|
|
{
|
|
|
|
switch(pname)
|
|
|
|
{
|
|
|
|
case AL_DOPPLER_FACTOR:
|
|
|
|
case AL_DOPPLER_VELOCITY:
|
|
|
|
case AL_DISTANCE_MODEL:
|
|
|
|
case AL_SPEED_OF_SOUND:
|
|
|
|
case AL_DEFERRED_UPDATES_SOFT:
|
|
|
|
values[0] = alGetInteger64SOFT(pname);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
context = GetContextRef();
|
|
|
|
if(!context) return;
|
|
|
|
|
|
|
|
switch(pname)
|
|
|
|
{
|
|
|
|
default:
|
|
|
|
SET_ERROR_AND_GOTO(context, AL_INVALID_ENUM, done);
|
|
|
|
}
|
|
|
|
|
|
|
|
done:
|
|
|
|
ALCcontext_DecRef(context);
|
|
|
|
}
|
|
|
|
|
2010-03-19 14:34:18 -07:00
|
|
|
AL_API const ALchar* AL_APIENTRY alGetString(ALenum pname)
|
2007-11-13 18:02:18 -08:00
|
|
|
{
|
2013-03-24 13:55:41 -07:00
|
|
|
const ALchar *value = NULL;
|
2013-10-07 08:50:17 -07:00
|
|
|
ALCcontext *context;
|
2007-11-13 18:02:18 -08:00
|
|
|
|
2013-10-07 08:50:17 -07:00
|
|
|
context = GetContextRef();
|
|
|
|
if(!context) return NULL;
|
2007-11-13 18:02:18 -08:00
|
|
|
|
2013-10-07 08:50:17 -07:00
|
|
|
switch(pname)
|
2012-04-24 02:51:57 -07:00
|
|
|
{
|
2013-10-07 08:50:17 -07:00
|
|
|
case AL_VENDOR:
|
|
|
|
value = alVendor;
|
|
|
|
break;
|
2012-04-24 02:51:57 -07:00
|
|
|
|
2013-10-07 08:50:17 -07:00
|
|
|
case AL_VERSION:
|
|
|
|
value = alVersion;
|
|
|
|
break;
|
2012-04-24 02:51:57 -07:00
|
|
|
|
2013-10-07 08:50:17 -07:00
|
|
|
case AL_RENDERER:
|
|
|
|
value = alRenderer;
|
|
|
|
break;
|
2012-04-24 02:51:57 -07:00
|
|
|
|
2013-10-07 08:50:17 -07:00
|
|
|
case AL_EXTENSIONS:
|
|
|
|
value = context->ExtensionList;
|
|
|
|
break;
|
2012-04-24 02:51:57 -07:00
|
|
|
|
2013-10-07 08:50:17 -07:00
|
|
|
case AL_NO_ERROR:
|
|
|
|
value = alNoError;
|
|
|
|
break;
|
2012-04-24 02:51:57 -07:00
|
|
|
|
2013-10-07 08:50:17 -07:00
|
|
|
case AL_INVALID_NAME:
|
|
|
|
value = alErrInvalidName;
|
|
|
|
break;
|
2012-04-24 02:51:57 -07:00
|
|
|
|
2013-10-07 08:50:17 -07:00
|
|
|
case AL_INVALID_ENUM:
|
|
|
|
value = alErrInvalidEnum;
|
|
|
|
break;
|
2012-04-24 02:51:57 -07:00
|
|
|
|
2013-10-07 08:50:17 -07:00
|
|
|
case AL_INVALID_VALUE:
|
|
|
|
value = alErrInvalidValue;
|
|
|
|
break;
|
2012-04-24 02:51:57 -07:00
|
|
|
|
2013-10-07 08:50:17 -07:00
|
|
|
case AL_INVALID_OPERATION:
|
|
|
|
value = alErrInvalidOp;
|
|
|
|
break;
|
2012-04-24 02:51:57 -07:00
|
|
|
|
2013-10-07 08:50:17 -07:00
|
|
|
case AL_OUT_OF_MEMORY:
|
|
|
|
value = alErrOutOfMemory;
|
|
|
|
break;
|
2012-04-24 02:51:57 -07:00
|
|
|
|
2013-10-07 08:50:17 -07:00
|
|
|
default:
|
|
|
|
SET_ERROR_AND_GOTO(context, AL_INVALID_ENUM, done);
|
2012-04-24 02:51:57 -07:00
|
|
|
}
|
2007-11-13 18:02:18 -08:00
|
|
|
|
2013-10-07 08:50:17 -07:00
|
|
|
done:
|
|
|
|
ALCcontext_DecRef(context);
|
2007-11-13 18:02:18 -08:00
|
|
|
|
|
|
|
return value;
|
|
|
|
}
|
|
|
|
|
2010-03-19 14:34:18 -07:00
|
|
|
AL_API ALvoid AL_APIENTRY alDopplerFactor(ALfloat value)
|
2007-11-13 18:02:18 -08:00
|
|
|
{
|
2013-10-07 08:50:17 -07:00
|
|
|
ALCcontext *context;
|
2007-11-13 18:02:18 -08:00
|
|
|
|
2013-10-07 08:50:17 -07:00
|
|
|
context = GetContextRef();
|
|
|
|
if(!context) return;
|
2007-11-13 18:02:18 -08:00
|
|
|
|
2013-10-07 08:50:17 -07:00
|
|
|
if(!(value >= 0.0f && isfinite(value)))
|
|
|
|
SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done);
|
2012-04-24 02:51:57 -07:00
|
|
|
|
2016-05-11 18:40:17 -07:00
|
|
|
WriteLock(&context->PropLock);
|
2013-10-07 08:50:17 -07:00
|
|
|
context->DopplerFactor = value;
|
Provide asynchronous property updates for sources
This necessitates a change in how source updates are handled. Rather than just
being able to update sources when a dependent object state is changed (e.g. a
listener gain change), now all source updates must be proactively provided.
Consequently, apps that do not utilize any deferring (AL_SOFT_defer_updates or
alcSuspendContext/alcProcessContext) may utilize more CPU since it'll be
filling out more update containers for the mixer thread to use.
The upside is that there's less blocking between the app's calling thread and
the mixer thread, particularly for vectors and other multi-value properties
(filters and sends). Deferring behavior when used is also improved, since
updates that shouldn't be applied yet are simply not provided. And when they
are provided, the mixer doesn't have to ignore them, meaning the actual
deferring of a context doesn't have to synchrnously force an update -- the
process call will send any pending updates, which the mixer will apply even if
another deferral occurs before the mixer runs, because it'll still be there
waiting on the next mixer invocation.
There is one slight bug introduced by this commit. When a listener change is
made, or changes to multiple sources while updates are being deferred, it is
possible for the mixer to run while the sources are prepping their updates,
causing some of the source updates to be seen before the other. This will be
fixed in short order.
2016-05-14 23:43:40 -07:00
|
|
|
if(!ATOMIC_LOAD(&context->DeferUpdates, almemory_order_acquire))
|
|
|
|
UpdateListenerProps(context);
|
2016-05-11 18:40:17 -07:00
|
|
|
WriteUnlock(&context->PropLock);
|
2007-11-13 18:02:18 -08:00
|
|
|
|
2013-10-07 08:50:17 -07:00
|
|
|
done:
|
|
|
|
ALCcontext_DecRef(context);
|
2007-11-13 18:02:18 -08:00
|
|
|
}
|
|
|
|
|
2010-03-19 14:34:18 -07:00
|
|
|
AL_API ALvoid AL_APIENTRY alDopplerVelocity(ALfloat value)
|
2007-11-13 18:02:18 -08:00
|
|
|
{
|
2013-10-07 08:50:17 -07:00
|
|
|
ALCcontext *context;
|
2007-11-13 18:02:18 -08:00
|
|
|
|
2013-10-07 08:50:17 -07:00
|
|
|
context = GetContextRef();
|
|
|
|
if(!context) return;
|
2007-11-13 18:02:18 -08:00
|
|
|
|
2013-10-07 08:50:17 -07:00
|
|
|
if(!(value >= 0.0f && isfinite(value)))
|
|
|
|
SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done);
|
2012-04-24 02:51:57 -07:00
|
|
|
|
2016-05-11 18:40:17 -07:00
|
|
|
WriteLock(&context->PropLock);
|
2013-10-07 08:50:17 -07:00
|
|
|
context->DopplerVelocity = value;
|
Provide asynchronous property updates for sources
This necessitates a change in how source updates are handled. Rather than just
being able to update sources when a dependent object state is changed (e.g. a
listener gain change), now all source updates must be proactively provided.
Consequently, apps that do not utilize any deferring (AL_SOFT_defer_updates or
alcSuspendContext/alcProcessContext) may utilize more CPU since it'll be
filling out more update containers for the mixer thread to use.
The upside is that there's less blocking between the app's calling thread and
the mixer thread, particularly for vectors and other multi-value properties
(filters and sends). Deferring behavior when used is also improved, since
updates that shouldn't be applied yet are simply not provided. And when they
are provided, the mixer doesn't have to ignore them, meaning the actual
deferring of a context doesn't have to synchrnously force an update -- the
process call will send any pending updates, which the mixer will apply even if
another deferral occurs before the mixer runs, because it'll still be there
waiting on the next mixer invocation.
There is one slight bug introduced by this commit. When a listener change is
made, or changes to multiple sources while updates are being deferred, it is
possible for the mixer to run while the sources are prepping their updates,
causing some of the source updates to be seen before the other. This will be
fixed in short order.
2016-05-14 23:43:40 -07:00
|
|
|
if(!ATOMIC_LOAD(&context->DeferUpdates, almemory_order_acquire))
|
|
|
|
UpdateListenerProps(context);
|
2016-05-11 18:40:17 -07:00
|
|
|
WriteUnlock(&context->PropLock);
|
2007-11-13 18:02:18 -08:00
|
|
|
|
2013-10-07 08:50:17 -07:00
|
|
|
done:
|
|
|
|
ALCcontext_DecRef(context);
|
2007-11-13 18:02:18 -08:00
|
|
|
}
|
|
|
|
|
2012-04-19 22:50:11 -07:00
|
|
|
AL_API ALvoid AL_APIENTRY alSpeedOfSound(ALfloat value)
|
2007-11-13 18:02:18 -08:00
|
|
|
{
|
2013-10-07 08:50:17 -07:00
|
|
|
ALCcontext *context;
|
2007-11-13 18:02:18 -08:00
|
|
|
|
2013-10-07 08:50:17 -07:00
|
|
|
context = GetContextRef();
|
|
|
|
if(!context) return;
|
2007-11-13 18:02:18 -08:00
|
|
|
|
2013-10-07 08:50:17 -07:00
|
|
|
if(!(value > 0.0f && isfinite(value)))
|
|
|
|
SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done);
|
2012-04-24 02:51:57 -07:00
|
|
|
|
2016-05-11 18:40:17 -07:00
|
|
|
WriteLock(&context->PropLock);
|
2013-10-07 08:50:17 -07:00
|
|
|
context->SpeedOfSound = value;
|
Provide asynchronous property updates for sources
This necessitates a change in how source updates are handled. Rather than just
being able to update sources when a dependent object state is changed (e.g. a
listener gain change), now all source updates must be proactively provided.
Consequently, apps that do not utilize any deferring (AL_SOFT_defer_updates or
alcSuspendContext/alcProcessContext) may utilize more CPU since it'll be
filling out more update containers for the mixer thread to use.
The upside is that there's less blocking between the app's calling thread and
the mixer thread, particularly for vectors and other multi-value properties
(filters and sends). Deferring behavior when used is also improved, since
updates that shouldn't be applied yet are simply not provided. And when they
are provided, the mixer doesn't have to ignore them, meaning the actual
deferring of a context doesn't have to synchrnously force an update -- the
process call will send any pending updates, which the mixer will apply even if
another deferral occurs before the mixer runs, because it'll still be there
waiting on the next mixer invocation.
There is one slight bug introduced by this commit. When a listener change is
made, or changes to multiple sources while updates are being deferred, it is
possible for the mixer to run while the sources are prepping their updates,
causing some of the source updates to be seen before the other. This will be
fixed in short order.
2016-05-14 23:43:40 -07:00
|
|
|
if(!ATOMIC_LOAD(&context->DeferUpdates, almemory_order_acquire))
|
|
|
|
UpdateListenerProps(context);
|
2016-05-11 18:40:17 -07:00
|
|
|
WriteUnlock(&context->PropLock);
|
2007-11-13 18:02:18 -08:00
|
|
|
|
2013-10-07 08:50:17 -07:00
|
|
|
done:
|
|
|
|
ALCcontext_DecRef(context);
|
2007-11-13 18:02:18 -08:00
|
|
|
}
|
|
|
|
|
2010-03-19 14:34:18 -07:00
|
|
|
AL_API ALvoid AL_APIENTRY alDistanceModel(ALenum value)
|
2007-11-13 18:02:18 -08:00
|
|
|
{
|
2013-10-07 08:50:17 -07:00
|
|
|
ALCcontext *context;
|
2007-11-13 18:02:18 -08:00
|
|
|
|
2013-10-07 08:50:17 -07:00
|
|
|
context = GetContextRef();
|
|
|
|
if(!context) return;
|
2009-08-16 15:09:36 -07:00
|
|
|
|
2013-10-07 08:50:17 -07:00
|
|
|
if(!(value == AL_INVERSE_DISTANCE || value == AL_INVERSE_DISTANCE_CLAMPED ||
|
|
|
|
value == AL_LINEAR_DISTANCE || value == AL_LINEAR_DISTANCE_CLAMPED ||
|
|
|
|
value == AL_EXPONENT_DISTANCE || value == AL_EXPONENT_DISTANCE_CLAMPED ||
|
|
|
|
value == AL_NONE))
|
|
|
|
SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done);
|
|
|
|
|
2016-05-11 18:40:17 -07:00
|
|
|
WriteLock(&context->PropLock);
|
2013-10-07 08:50:17 -07:00
|
|
|
context->DistanceModel = value;
|
|
|
|
if(!context->SourceDistanceModel)
|
Provide asynchronous property updates for sources
This necessitates a change in how source updates are handled. Rather than just
being able to update sources when a dependent object state is changed (e.g. a
listener gain change), now all source updates must be proactively provided.
Consequently, apps that do not utilize any deferring (AL_SOFT_defer_updates or
alcSuspendContext/alcProcessContext) may utilize more CPU since it'll be
filling out more update containers for the mixer thread to use.
The upside is that there's less blocking between the app's calling thread and
the mixer thread, particularly for vectors and other multi-value properties
(filters and sends). Deferring behavior when used is also improved, since
updates that shouldn't be applied yet are simply not provided. And when they
are provided, the mixer doesn't have to ignore them, meaning the actual
deferring of a context doesn't have to synchrnously force an update -- the
process call will send any pending updates, which the mixer will apply even if
another deferral occurs before the mixer runs, because it'll still be there
waiting on the next mixer invocation.
There is one slight bug introduced by this commit. When a listener change is
made, or changes to multiple sources while updates are being deferred, it is
possible for the mixer to run while the sources are prepping their updates,
causing some of the source updates to be seen before the other. This will be
fixed in short order.
2016-05-14 23:43:40 -07:00
|
|
|
{
|
|
|
|
if(!ATOMIC_LOAD(&context->DeferUpdates, almemory_order_acquire))
|
2016-08-23 19:17:17 -07:00
|
|
|
UpdateListenerProps(context);
|
Provide asynchronous property updates for sources
This necessitates a change in how source updates are handled. Rather than just
being able to update sources when a dependent object state is changed (e.g. a
listener gain change), now all source updates must be proactively provided.
Consequently, apps that do not utilize any deferring (AL_SOFT_defer_updates or
alcSuspendContext/alcProcessContext) may utilize more CPU since it'll be
filling out more update containers for the mixer thread to use.
The upside is that there's less blocking between the app's calling thread and
the mixer thread, particularly for vectors and other multi-value properties
(filters and sends). Deferring behavior when used is also improved, since
updates that shouldn't be applied yet are simply not provided. And when they
are provided, the mixer doesn't have to ignore them, meaning the actual
deferring of a context doesn't have to synchrnously force an update -- the
process call will send any pending updates, which the mixer will apply even if
another deferral occurs before the mixer runs, because it'll still be there
waiting on the next mixer invocation.
There is one slight bug introduced by this commit. When a listener change is
made, or changes to multiple sources while updates are being deferred, it is
possible for the mixer to run while the sources are prepping their updates,
causing some of the source updates to be seen before the other. This will be
fixed in short order.
2016-05-14 23:43:40 -07:00
|
|
|
}
|
2016-05-11 18:40:17 -07:00
|
|
|
WriteUnlock(&context->PropLock);
|
2007-11-13 18:02:18 -08:00
|
|
|
|
2013-10-07 08:50:17 -07:00
|
|
|
done:
|
|
|
|
ALCcontext_DecRef(context);
|
2007-11-13 18:02:18 -08:00
|
|
|
}
|
2011-07-16 16:59:20 -07:00
|
|
|
|
|
|
|
|
|
|
|
AL_API ALvoid AL_APIENTRY alDeferUpdatesSOFT(void)
|
|
|
|
{
|
2013-10-07 08:50:17 -07:00
|
|
|
ALCcontext *context;
|
2011-07-16 16:59:20 -07:00
|
|
|
|
2013-10-07 08:50:17 -07:00
|
|
|
context = GetContextRef();
|
|
|
|
if(!context) return;
|
2011-07-16 16:59:20 -07:00
|
|
|
|
2014-10-12 09:03:08 -07:00
|
|
|
ALCcontext_DeferUpdates(context);
|
2011-07-16 16:59:20 -07:00
|
|
|
|
2013-10-07 08:50:17 -07:00
|
|
|
ALCcontext_DecRef(context);
|
2011-07-16 16:59:20 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
AL_API ALvoid AL_APIENTRY alProcessUpdatesSOFT(void)
|
|
|
|
{
|
2013-10-07 08:50:17 -07:00
|
|
|
ALCcontext *context;
|
2011-07-16 16:59:20 -07:00
|
|
|
|
2013-10-07 08:50:17 -07:00
|
|
|
context = GetContextRef();
|
|
|
|
if(!context) return;
|
2011-07-16 16:59:20 -07:00
|
|
|
|
2014-10-12 09:03:08 -07:00
|
|
|
ALCcontext_ProcessUpdates(context);
|
2011-07-16 16:59:20 -07:00
|
|
|
|
2013-10-07 08:50:17 -07:00
|
|
|
ALCcontext_DecRef(context);
|
2011-07-16 16:59:20 -07:00
|
|
|
}
|