Audio: Implement support for ALC_EXT_thread_local_context
This commit is contained in:
parent
3e1b61070c
commit
3fb1096d07
|
|
@ -27,6 +27,7 @@ namespace Nz
|
|||
enum class OpenALExtension
|
||||
{
|
||||
SourceLatency,
|
||||
ThreadLocalContext,
|
||||
|
||||
Max = SourceLatency
|
||||
};
|
||||
|
|
@ -82,6 +83,8 @@ namespace Nz
|
|||
OpenALDevice& operator=(const OpenALDevice&) = delete;
|
||||
OpenALDevice& operator=(OpenALDevice&&) = delete;
|
||||
|
||||
static const OpenALDevice* GetCurrentDevice();
|
||||
|
||||
// We give each device its own set of function pointer, even though regular OpenAL extensions are always the same (for a set library).
|
||||
// This makes it easier to wrap them (for error handling), and extension pointers are device-local anyway.
|
||||
#define NAZARA_AUDIO_AL_ALC_FUNCTION(name) decltype(&::name) name;
|
||||
|
|
|
|||
|
|
@ -28,6 +28,18 @@
|
|||
#define NAZARA_AUDIO_AL_EXT_END()
|
||||
#endif
|
||||
|
||||
#ifndef NAZARA_AUDIO_ALC_EXT_FUNCTION
|
||||
#define NAZARA_AUDIO_ALC_EXT_FUNCTION(func) NAZARA_AUDIO_AL_EXT_FUNCTION(func)
|
||||
#endif
|
||||
|
||||
#ifndef NAZARA_AUDIO_ALC_EXT_BEGIN
|
||||
#define NAZARA_AUDIO_ALC_EXT_BEGIN(ext) NAZARA_AUDIO_AL_EXT_BEGIN(ext)
|
||||
#endif
|
||||
|
||||
#ifndef NAZARA_AUDIO_ALC_EXT_END
|
||||
#define NAZARA_AUDIO_ALC_EXT_END() NAZARA_AUDIO_AL_EXT_END()
|
||||
#endif
|
||||
|
||||
NAZARA_AUDIO_AL_FUNCTION(alBuffer3f)
|
||||
NAZARA_AUDIO_AL_FUNCTION(alBuffer3i)
|
||||
NAZARA_AUDIO_AL_FUNCTION(alBufferData)
|
||||
|
|
@ -102,7 +114,7 @@ NAZARA_AUDIO_AL_FUNCTION(alSourceStopv)
|
|||
NAZARA_AUDIO_AL_FUNCTION(alSourceUnqueueBuffers)
|
||||
NAZARA_AUDIO_AL_FUNCTION(alSpeedOfSound)
|
||||
|
||||
#ifndef NAZARA_PLATFORM_WEB
|
||||
#ifdef AL_SOFT_source_latency
|
||||
NAZARA_AUDIO_AL_EXT_BEGIN(AL_SOFT_source_latency)
|
||||
NAZARA_AUDIO_AL_EXT_FUNCTION(alGetSource3dSOFT)
|
||||
NAZARA_AUDIO_AL_EXT_FUNCTION(alGetSource3i64SOFT)
|
||||
|
|
@ -140,9 +152,19 @@ NAZARA_AUDIO_ALC_FUNCTION(alcOpenDevice)
|
|||
NAZARA_AUDIO_ALC_FUNCTION(alcProcessContext)
|
||||
NAZARA_AUDIO_ALC_FUNCTION(alcSuspendContext)
|
||||
|
||||
#ifdef ALC_EXT_thread_local_context
|
||||
NAZARA_AUDIO_ALC_EXT_BEGIN(ALC_EXT_thread_local_context)
|
||||
NAZARA_AUDIO_ALC_EXT_FUNCTION(alcGetThreadContext)
|
||||
NAZARA_AUDIO_ALC_EXT_FUNCTION(alcSetThreadContext)
|
||||
NAZARA_AUDIO_ALC_EXT_END()
|
||||
#endif
|
||||
|
||||
#undef NAZARA_AUDIO_AL_FUNCTION
|
||||
#undef NAZARA_AUDIO_AL_ALC_FUNCTION
|
||||
#undef NAZARA_AUDIO_AL_EXT_FUNCTION
|
||||
#undef NAZARA_AUDIO_ALC_FUNCTION
|
||||
#undef NAZARA_AUDIO_AL_EXT_BEGIN
|
||||
#undef NAZARA_AUDIO_AL_EXT_END
|
||||
#undef NAZARA_AUDIO_ALC_EXT_FUNCTION
|
||||
#undef NAZARA_AUDIO_ALC_EXT_BEGIN
|
||||
#undef NAZARA_AUDIO_ALC_EXT_END
|
||||
#undef NAZARA_AUDIO_ALC_FUNCTION
|
||||
|
|
|
|||
|
|
@ -23,7 +23,9 @@ namespace Nz
|
|||
#include <Nazara/Audio/OpenALFunctions.hpp>
|
||||
};
|
||||
|
||||
thread_local const OpenALDevice* s_currentALDevice;
|
||||
// Regular OpenAL contexts are process-wide, but ALC_EXT_thread_local_context allows thread-local contexts
|
||||
const OpenALDevice* s_currentGlobalALDevice;
|
||||
thread_local const OpenALDevice* s_currentThreadALDevice;
|
||||
|
||||
template<typename FuncType, std::size_t FuncIndex, typename>
|
||||
struct ALWrapper;
|
||||
|
|
@ -35,7 +37,7 @@ namespace Nz
|
|||
{
|
||||
return [](Args... args) -> Ret
|
||||
{
|
||||
const OpenALDevice* device = s_currentALDevice; //< pay TLS cost once
|
||||
const OpenALDevice* device = OpenALDevice::GetCurrentDevice();
|
||||
assert(device);
|
||||
|
||||
FuncType funcPtr = reinterpret_cast<FuncType>(device->GetFunctionByIndex(FuncIndex));
|
||||
|
|
@ -121,7 +123,7 @@ namespace Nz
|
|||
if (m_library.alcMakeContextCurrent(m_context) != AL_TRUE)
|
||||
throw std::runtime_error("failed to activate OpenAL context");
|
||||
|
||||
s_currentALDevice = this;
|
||||
s_currentGlobalALDevice = this;
|
||||
|
||||
SymbolLoader loader(*this);
|
||||
#ifdef NAZARA_DEBUG
|
||||
|
|
@ -131,6 +133,7 @@ namespace Nz
|
|||
#define NAZARA_AUDIO_AL_FUNCTION(name) loader.Load<decltype(&::name), UnderlyingCast(FunctionIndex:: name), false>(name, #name, library.name);
|
||||
#define NAZARA_AUDIO_ALC_FUNCTION(name) loader.Load<decltype(&::name), UnderlyingCast(FunctionIndex:: name), true>(name, #name, library.name);
|
||||
#define NAZARA_AUDIO_AL_EXT_FUNCTION(name) loader.Load<decltype(&::name), UnderlyingCast(FunctionIndex:: name), false>(name, #name, nullptr);
|
||||
#define NAZARA_AUDIO_ALC_EXT_FUNCTION(name) loader.Load<decltype(&::name), UnderlyingCast(FunctionIndex:: name), true>(name, #name, nullptr);
|
||||
#include <Nazara/Audio/OpenALFunctions.hpp>
|
||||
|
||||
m_renderer = reinterpret_cast<const char*>(alGetString(AL_RENDERER));
|
||||
|
|
@ -157,6 +160,9 @@ namespace Nz
|
|||
if (library.alIsExtensionPresent("AL_SOFT_source_latency"))
|
||||
m_extensionStatus[OpenALExtension::SourceLatency] = true;
|
||||
|
||||
if (library.alIsExtensionPresent("ALC_EXT_thread_local_context"))
|
||||
m_extensionStatus[OpenALExtension::ThreadLocalContext] = true;
|
||||
|
||||
SetListenerDirection(Vector3f::Forward());
|
||||
}
|
||||
|
||||
|
|
@ -164,20 +170,23 @@ namespace Nz
|
|||
{
|
||||
NAZARA_USE_ANONYMOUS_NAMESPACE
|
||||
|
||||
MakeContextCurrent();
|
||||
|
||||
// alcMakeContextCurrent resets the thread context
|
||||
alcMakeContextCurrent(m_context);
|
||||
alcDestroyContext(m_context);
|
||||
alcCloseDevice(m_device);
|
||||
|
||||
if (s_currentALDevice == this)
|
||||
s_currentALDevice = nullptr;
|
||||
if (s_currentThreadALDevice)
|
||||
s_currentThreadALDevice = nullptr;
|
||||
|
||||
if (s_currentGlobalALDevice == this)
|
||||
s_currentGlobalALDevice = nullptr;
|
||||
}
|
||||
|
||||
bool OpenALDevice::ClearErrorFlag() const
|
||||
{
|
||||
NAZARA_USE_ANONYMOUS_NAMESPACE
|
||||
|
||||
assert(s_currentALDevice == this);
|
||||
assert(GetCurrentDevice() == this);
|
||||
alGetError();
|
||||
|
||||
return true;
|
||||
|
|
@ -322,10 +331,27 @@ namespace Nz
|
|||
{
|
||||
NAZARA_USE_ANONYMOUS_NAMESPACE
|
||||
|
||||
if (s_currentALDevice != this)
|
||||
if (alcSetThreadContext)
|
||||
{
|
||||
m_library.alcMakeContextCurrent(m_context);
|
||||
s_currentALDevice = this;
|
||||
if (s_currentThreadALDevice != this)
|
||||
{
|
||||
alcSetThreadContext(m_context);
|
||||
s_currentThreadALDevice = this;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (s_currentGlobalALDevice != this)
|
||||
{
|
||||
/*
|
||||
From EXT_thread_local_context:
|
||||
alcMakeContextCurrent changes the current process-wide context and set the current thread-local context to NULL.
|
||||
This has the side effect of changing the current thread-local context, so that the new current process-wide context will be used.
|
||||
*/
|
||||
alcMakeContextCurrent(m_context);
|
||||
s_currentGlobalALDevice = this;
|
||||
s_currentThreadALDevice = nullptr;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -358,7 +384,7 @@ namespace Nz
|
|||
{
|
||||
NAZARA_USE_ANONYMOUS_NAMESPACE
|
||||
|
||||
assert(s_currentALDevice == this);
|
||||
assert(GetCurrentDevice() == this);
|
||||
|
||||
bool hasAnyError = false;
|
||||
if (ALuint lastError = alGetError(); lastError != AL_NO_ERROR)
|
||||
|
|
@ -485,4 +511,13 @@ namespace Nz
|
|||
|
||||
alSpeedOfSound(speed);
|
||||
}
|
||||
|
||||
const OpenALDevice* OpenALDevice::GetCurrentDevice()
|
||||
{
|
||||
const OpenALDevice* device = s_currentThreadALDevice;
|
||||
if (device)
|
||||
return device;
|
||||
|
||||
return s_currentGlobalALDevice;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue