Name ALC_EXT_direct_context AL_EXT_direct_context Contributors Chris Robinson Contact Chris Robinson (chris.kcat 'at' gmail.com) Status Complete. Dependencies This extension is for OpenAL 1.1. This extension interacts with every extension adding an AL function that uses the current context. Overview This extension adds functions to use the AL via an explicitly-passed context, rather than the globally set current context that standard AL functions utilize. The OpenAL API is purposely designed to resemble OpenGL. Among the design decisions was to utilize a "current context" that AL functions implicitly access. While this makes sense when making something similar to OpenGL, it presents some problems. For one, OpenGL benefited from the current context being thread-local, and disallowed the same context being current on multiple threads at once, along with being more strict about not allowing a context to be deleted when it's current. This allowed for efficient lookup as most systems will hold a pointer to thread-local storage in a CPU register, where the current GL context can be retrieved by offsetting the register value, while also being assured a given GL call won't have its context messed with by another thread during execution. The current context of one thread can't be changed or accessed by another thread. In contrast, OpenAL defined its current context as global state. This means whenever an AL function needs to access and use the current context, there needs to be protection from other threads having adverse effects on the current context (in regard to both changing which context is current, and making state changes that would affect what the initial call was trying to do). This largely negates the benefits an implicit context model provides. Additionally, having AL functions act on an implied current context inherits other problems that OpenGL has when driving multiple outputs. As a thread can only have one context current at a time, it requires swapping the current context when managing different targets, adding potentially significant overhead. For OpenAL, this issue is even worse since the context is global, requiring multi-threaded synchronization if two or more separate threads are trying to use different contexts, which may not be possible with more modular components that are unaware of each other using OpenAL. Given these issues, many apps can benefit from contexts being explicitly passed to AL functions. Since OpenAL already needs to work safely in multi-threaded scenarios, there's little benefit to having to set a context as current for future AL calls to implicitly use, compared to simply passing in which context to use when calling AL functions. The purpose of this extension is to provide such functions. Issues Q: Does this only affect standard functions? A: No. Although not listed individually, this extension affects all other extensions that provides functions that implicitly use the current context. It would be impractical to list every extension this interacts with, in part because not all affected extensions may be known, and also because future extensions that haven't been made yet will also be affected. For example, if an implmentation supports both this extension and ALC_EXT_EFX, it must also provide direct context versions of EFX functions. For naming, functions without a vendor suffix will have Direct appended to the end of the name (e.g. alGenFilters -> alGenFiltersDirect), while functions with a vendor suffix have will have Direct inserted just before the suffix (e.g. alGetPointervEXT -> alGetPointervDirectEXT). In both cases, the function is given an extra ALCcontext* parameter as the first parameter, which is the context used in place of the current context the original function would use. Everything else about the function prototype (other parameters, its return type, the calling convention, etc) is the same as the original function. Q: For scenarios involving a router DLL, as an extension these functions will come from the driver implementing them. Creative's router DLL, however, wraps the ALCcontext handle from the driver with its own that it gives to the app, which won't be recognized when that's given to the driver's direct context functions. Can this work when using Creative's router DLL? A: With a bit of work, yes. This isn't necessary on non-Windows systems (that don't use an OpenAL router), on Windows setups that use an implementation directly without an OpenAL router, or when using alternative OpenAL routers (like OpenAL Soft's) that don't wrap the ALCcontext handles. In such cases where an affected router is or may be used, the idea is to "bootstrap" the desired device by opening it normally, retrieving the device driver's OpenAL functions, then closing and reopening the desired device using the driver functions directly. This isn't too disimilar from how OpenGL is used on Windows, as Microsoft's driver doesn't recognize functions from later OpenGL versions and requires using the device driver's OpenGL functions directly. Creative's router has an additional wrinkle in that, when getting functions, it will always return its own version of functions that it knows of, regardless of any device or context being used. To work around the issue, this extension adds an alcGetProcAddress2 function that, for all intents and purposes, is just an alias for the standard alcGetProcAdress function, but isn't recognized by Creative's router to ensure it's from the desired driver. That in turn will allow getting the ALC functions from the driver to open a new ALCdevice with to create a new ALCcontext from, which will be recognized by the driver's direct context functions. In essense: // Get alcGetProcAddress2 from the driver of the desired device // (a check for ALC_EXT_direct_context excluded for brevity). ALCdevice *dummy = alcOpenDevice(...); LPALCGETPROCADDRESS2 alcGetProcAddress2 = alcGetProcAddress(device, "alcGetProcAddress2"); alcCloseDevice(dummy); // Load all desired functions directly from the device driver. LPALCOPENDEVICE palcOpenDevice = alcGetProcAddress2(NULL, "alcOpenDevice"); LPALCCREATECONTEXT palcCreateContext = alcGetProcAddress2(NULL, "alcCreateContext"); ... LPALGENBUFFERSDIRECT palGenBuffersDirect = alcGetProcAddress2(NULL, "alGenBuffersDirect"); LPALDELETEBUFFERSDIRECT palDeleteBuffersDirect = alcGetProcAddress2(NULL, "alDeleteBuffersDirect"); ... // Reopen the desired device, using the device driver functions // directly and bypassing the router. ALCdevice *device = palcOpenDevice(...); ALCcontext *context = palcCreateContext(device, NULL); ... palGenBuffersDirect(context, ...); New Types None New Procedures and Functions ALCvoid* ALC_APIENTRY alcGetProcAddress2(ALCdevice *device, const ALCchar *funcName); void AL_APIENTRY alEnableDirect(ALCcontext *context, ALenum capability); void AL_APIENTRY alDisableDirect(ALCcontext *context, ALenum capability); ALboolean AL_APIENTRY alIsEnabledDirect(ALCcontext *context, ALenum capability); void AL_APIENTRY alDopplerFactorDirect(ALCcontext *context, ALfloat value); void AL_APIENTRY alSpeedOfSoundDirect(ALCcontext *context, ALfloat value); void AL_APIENTRY alDistanceModelDirect(ALCcontext *context, ALenum distanceModel); const ALchar* AL_APIENTRY alGetStringDirect(ALCcontext *context, ALenum param); void AL_APIENTRY alGetBooleanvDirect(ALCcontext *context, ALenum param, ALboolean *values); void AL_APIENTRY alGetIntegervDirect(ALCcontext *context, ALenum param, ALint *values); void AL_APIENTRY alGetFloatvDirect(ALCcontext *context, ALenum param, ALfloat *values); void AL_APIENTRY alGetDoublevDirect(ALCcontext *context, ALenum param, ALdouble *values); ALboolean AL_APIENTRY alGetBooleanDirect(ALCcontext *context, ALenum param); ALint AL_APIENTRY alGetIntegerDirect(ALCcontext *context, ALenum param); ALfloat AL_APIENTRY alGetFloatDirect(ALCcontext *context, ALenum param); ALdouble AL_APIENTRY alGetDoubleDirect(ALCcontext *context, ALenum param); ALenum AL_APIENTRY alGetErrorDirect(ALCcontext *context); ALboolean AL_APIENTRY alIsExtensionPresentDirect(ALCcontext *context, const ALchar *extname); void* AL_APIENTRY alGetProcAddressDirect(ALCcontext *context, const ALchar *fname); ALenum AL_APIENTRY alGetEnumValueDirect(ALCcontext *context, const ALchar *ename); void AL_APIENTRY alListenerfDirect(ALCcontext *context, ALenum param, ALfloat value); void AL_APIENTRY alListener3fDirect(ALCcontext *context, ALenum param, ALfloat value1, ALfloat value2, ALfloat value3); void AL_APIENTRY alListenerfvDirect(ALCcontext *context, ALenum param, const ALfloat *values); void AL_APIENTRY alListeneriDirect(ALCcontext *context, ALenum param, ALint value); void AL_APIENTRY alListener3iDirect(ALCcontext *context, ALenum param, ALint value1, ALint value2, ALint value3); void AL_APIENTRY alListenerivDirect(ALCcontext *context, ALenum param, const ALint *values); void AL_APIENTRY alGetListenerfDirect(ALCcontext *context, ALenum param, ALfloat *value); void AL_APIENTRY alGetListener3fDirect(ALCcontext *context, ALenum param, ALfloat *value1, ALfloat *value2, ALfloat *value3); void AL_APIENTRY alGetListenerfvDirect(ALCcontext *context, ALenum param, ALfloat *values); void AL_APIENTRY alGetListeneriDirect(ALCcontext *context, ALenum param, ALint *value); void AL_APIENTRY alGetListener3iDirect(ALCcontext *context, ALenum param, ALint *value1, ALint *value2, ALint *value3); void AL_APIENTRY alGetListenerivDirect(ALCcontext *context, ALenum param, ALint *values); void AL_APIENTRY alGenSourcesDirect(ALCcontext *context, ALsizei n, ALuint *sources); void AL_APIENTRY alDeleteSourcesDirect(ALCcontext *context, ALsizei n, const ALuint *sources); ALboolean AL_APIENTRY alIsSourceDirect(ALCcontext *context, ALuint source); void AL_APIENTRY alSourcefDirect(ALCcontext *context, ALuint source, ALenum param, ALfloat value); void AL_APIENTRY alSource3fDirect(ALCcontext *context, ALuint source, ALenum param, ALfloat value1, ALfloat value2, ALfloat value3); void AL_APIENTRY alSourcefvDirect(ALCcontext *context, ALuint source, ALenum param, const ALfloat *values); void AL_APIENTRY alSourceiDirect(ALCcontext *context, ALuint source, ALenum param, ALint value); void AL_APIENTRY alSource3iDirect(ALCcontext *context, ALuint source, ALenum param, ALint value1, ALint value2, ALint value3); void AL_APIENTRY alSourceivDirect(ALCcontext *context, ALuint source, ALenum param, const ALint *values); void AL_APIENTRY alGetSourcefDirect(ALCcontext *context, ALuint source, ALenum param, ALfloat *value); void AL_APIENTRY alGetSource3fDirect(ALCcontext *context, ALuint source, ALenum param, ALfloat *value1, ALfloat *value2, ALfloat *value3); void AL_APIENTRY alGetSourcefvDirect(ALCcontext *context, ALuint source, ALenum param, ALfloat *values); void AL_APIENTRY alGetSourceiDirect(ALCcontext *context, ALuint source, ALenum param, ALint *value); void AL_APIENTRY alGetSource3iDirect(ALCcontext *context, ALuint source, ALenum param, ALint *value1, ALint *value2, ALint *value3); void AL_APIENTRY alGetSourceivDirect(ALCcontext *context, ALuint source, ALenum param, ALint *values); void AL_APIENTRY alSourcePlayDirect(ALCcontext *context, ALuint source); void AL_APIENTRY alSourceStopDirect(ALCcontext *context, ALuint source); void AL_APIENTRY alSourceRewindDirect(ALCcontext *context, ALuint source); void AL_APIENTRY alSourcePauseDirect(ALCcontext *context, ALuint source); void AL_APIENTRY alSourcePlayvDirect(ALCcontext *context, ALsizei n, const ALuint *sources); void AL_APIENTRY alSourceStopvDirect(ALCcontext *context, ALsizei n, const ALuint *sources); void AL_APIENTRY alSourceRewindvDirect(ALCcontext *context, ALsizei n, const ALuint *sources); void AL_APIENTRY alSourcePausevDirect(ALCcontext *context, ALsizei n, const ALuint *sources); void AL_APIENTRY alSourceQueueBuffersDirect(ALCcontext *context, ALuint source, ALsizei nb, const ALuint *buffers); void AL_APIENTRY alSourceUnqueueBuffersDirect(ALCcontext *context, ALuint source, ALsizei nb, ALuint *buffers); void AL_APIENTRY alGenBuffersDirect(ALCcontext *context, ALsizei n, ALuint *buffers); void AL_APIENTRY alDeleteBuffersDirect(ALCcontext *context, ALsizei n, const ALuint *buffers); ALboolean AL_APIENTRY alIsBufferDirect(ALCcontext *context, ALuint buffer); void AL_APIENTRY alBufferDataDirect(ALCcontext *context, ALuint buffer, ALenum format, const ALvoid *data, ALsizei size, ALsizei samplerate); void AL_APIENTRY alBufferfDirect(ALCcontext *context, ALuint buffer, ALenum param, ALfloat value); void AL_APIENTRY alBuffer3fDirect(ALCcontext *context, ALuint buffer, ALenum param, ALfloat value1, ALfloat value2, ALfloat value3); void AL_APIENTRY alBufferfvDirect(ALCcontext *context, ALuint buffer, ALenum param, const ALfloat *values); void AL_APIENTRY alBufferiDirect(ALCcontext *context, ALuint buffer, ALenum param, ALint value); void AL_APIENTRY alBuffer3iDirect(ALCcontext *context, ALuint buffer, ALenum param, ALint value1, ALint value2, ALint value3); void AL_APIENTRY alBufferivDirect(ALCcontext *context, ALuint buffer, ALenum param, const ALint *values); void AL_APIENTRY alGetBufferfDirect(ALCcontext *context, ALuint buffer, ALenum param, ALfloat *value); void AL_APIENTRY alGetBuffer3fDirect(ALCcontext *context, ALuint buffer, ALenum param, ALfloat *value1, ALfloat *value2, ALfloat *value3); void AL_APIENTRY alGetBufferfvDirect(ALCcontext *context, ALuint buffer, ALenum param, ALfloat *values); void AL_APIENTRY alGetBufferiDirect(ALCcontext *context, ALuint buffer, ALenum param, ALint *value); void AL_APIENTRY alGetBuffer3iDirect(ALCcontext *context, ALuint buffer, ALenum param, ALint *value1, ALint *value2, ALint *value3); void AL_APIENTRY alGetBufferivDirect(ALCcontext *context, ALuint buffer, ALenum param, ALint *values); New Tokens None. Additions to Specification Direct Context Functions As an alternative to functions that access the currently set global context, AL functions are provided that take an explicit context parameter as the context to access instead. These functions include void alEnableDirect(ALCcontext *context, ALenum capability); void alDisableDirect(ALCcontext *context, ALenum capability); ALboolean alIsEnabledDirect(ALCcontext *context, ALenum capability); void alDopplerFactorDirect(ALCcontext *context, ALfloat value); void alSpeedOfSoundDirect(ALCcontext *context, ALfloat value); void alDistanceModelDirect(ALCcontext *context, ALenum distanceModel); const ALchar* alGetStringDirect(ALCcontext *context, ALenum param); void alGetBooleanvDirect(ALCcontext *context, ALenum param, ALboolean *values); void alGetIntegervDirect(ALCcontext *context, ALenum param, ALint *values); void alGetFloatvDirect(ALCcontext *context, ALenum param, ALfloat *values); void alGetDoublevDirect(ALCcontext *context, ALenum param, ALdouble *values); ALboolean alGetBooleanDirect(ALCcontext *context, ALenum param); ALint alGetIntegerDirect(ALCcontext *context, ALenum param); ALfloat alGetFloatDirect(ALCcontext *context, ALenum param); ALdouble alGetDoubleDirect(ALCcontext *context, ALenum param); ALenum alGetErrorDirect(ALCcontext *context); ALboolean alIsExtensionPresentDirect(ALCcontext *context, const ALchar *extname); void* alGetProcAddressDirect(ALCcontext *context, const ALchar *fname); ALenum alGetEnumValueDirect(ALCcontext *context, const ALchar *ename); void alListenerfDirect(ALCcontext *context, ALenum param, ALfloat value); void alListener3fDirect(ALCcontext *context, ALenum param, ALfloat value1, ALfloat value2, ALfloat value3); void alListenerfvDirect(ALCcontext *context, ALenum param, const ALfloat *values); void alListeneriDirect(ALCcontext *context, ALenum param, ALint value); void alListener3iDirect(ALCcontext *context, ALenum param, ALint value1, ALint value2, ALint value3); void alListenerivDirect(ALCcontext *context, ALenum param, const ALint *values); void alGetListenerfDirect(ALCcontext *context, ALenum param, ALfloat *value); void alGetListener3fDirect(ALCcontext *context, ALenum param, ALfloat *value1, ALfloat *value2, ALfloat *value3); void alGetListenerfvDirect(ALCcontext *context, ALenum param, ALfloat *values); void alGetListeneriDirect(ALCcontext *context, ALenum param, ALint *value); void alGetListener3iDirect(ALCcontext *context, ALenum param, ALint *value1, ALint *value2, ALint *value3); void alGetListenerivDirect(ALCcontext *context, ALenum param, ALint *values); void alGenSourcesDirect(ALCcontext *context, ALsizei n, ALuint *sources); void alDeleteSourcesDirect(ALCcontext *context, ALsizei n, const ALuint *sources); ALboolean alIsSourceDirect(ALCcontext *context, ALuint source); void alSourcefDirect(ALCcontext *context, ALuint source, ALenum param, ALfloat value); void alSource3fDirect(ALCcontext *context, ALuint source, ALenum param, ALfloat value1, ALfloat value2, ALfloat value3); void alSourcefvDirect(ALCcontext *context, ALuint source, ALenum param, const ALfloat *values); void alSourceiDirect(ALCcontext *context, ALuint source, ALenum param, ALint value); void alSource3iDirect(ALCcontext *context, ALuint source, ALenum param, ALint value1, ALint value2, ALint value3); void alSourceivDirect(ALCcontext *context, ALuint source, ALenum param, const ALint *values); void alGetSourcefDirect(ALCcontext *context, ALuint source, ALenum param, ALfloat *value); void alGetSource3fDirect(ALCcontext *context, ALuint source, ALenum param, ALfloat *value1, ALfloat *value2, ALfloat *value3); void alGetSourcefvDirect(ALCcontext *context, ALuint source, ALenum param, ALfloat *values); void alGetSourceiDirect(ALCcontext *context, ALuint source, ALenum param, ALint *value); void alGetSource3iDirect(ALCcontext *context, ALuint source, ALenum param, ALint *value1, ALint *value2, ALint *value3); void alGetSourceivDirect(ALCcontext *context, ALuint source, ALenum param, ALint *values); void alSourcePlayDirect(ALCcontext *context, ALuint source); void alSourceStopDirect(ALCcontext *context, ALuint source); void alSourceRewindDirect(ALCcontext *context, ALuint source); void alSourcePauseDirect(ALCcontext *context, ALuint source); void alSourcePlayvDirect(ALCcontext *context, ALsizei n, const ALuint *sources); void alSourceStopvDirect(ALCcontext *context, ALsizei n, const ALuint *sources); void alSourceRewindvDirect(ALCcontext *context, ALsizei n, const ALuint *sources); void alSourcePausevDirect(ALCcontext *context, ALsizei n, const ALuint *sources); void alSourceQueueBuffersDirect(ALCcontext *context, ALuint source, ALsizei nb, const ALuint *buffers); void alSourceUnqueueBuffersDirect(ALCcontext *context, ALuint source, ALsizei nb, ALuint *buffers); void alGenBuffersDirect(ALCcontext *context, ALsizei n, ALuint *buffers); void alDeleteBuffersDirect(ALCcontext *context, ALsizei n, const ALuint *buffers); ALboolean alIsBufferDirect(ALCcontext *context, ALuint buffer); void alBufferDataDirect(ALCcontext *context, ALuint buffer, ALenum format, const ALvoid *data, ALsizei size, ALsizei samplerate); void alBufferfDirect(ALCcontext *context, ALuint buffer, ALenum param, ALfloat value); void alBuffer3fDirect(ALCcontext *context, ALuint buffer, ALenum param, ALfloat value1, ALfloat value2, ALfloat value3); void alBufferfvDirect(ALCcontext *context, ALuint buffer, ALenum param, const ALfloat *values); void alBufferiDirect(ALCcontext *context, ALuint buffer, ALenum param, ALint value); void alBuffer3iDirect(ALCcontext *context, ALuint buffer, ALenum param, ALint value1, ALint value2, ALint value3); void alBufferivDirect(ALCcontext *context, ALuint buffer, ALenum param, const ALint *values); void alGetBufferfDirect(ALCcontext *context, ALuint buffer, ALenum param, ALfloat *value); void alGetBuffer3fDirect(ALCcontext *context, ALuint buffer, ALenum param, ALfloat *value1, ALfloat *value2, ALfloat *value3); void alGetBufferfvDirect(ALCcontext *context, ALuint buffer, ALenum param, ALfloat *values); void alGetBufferiDirect(ALCcontext *context, ALuint buffer, ALenum param, ALint *value); void alGetBuffer3iDirect(ALCcontext *context, ALuint buffer, ALenum param, ALint *value1, ALint *value2, ALint *value3); void alGetBufferivDirect(ALCcontext *context, ALuint buffer, ALenum param, ALint *values); These functions behave exactly the same as the variant using the current context, except that it accesses the context provided as the first parameter instead of the current context, which goes ignored. Passing an invalid ALCcontext pointer is undefined behavior; it is expected that a debug build of the given AL runtime can do full validation, while a release build can opt to forgo validation, or only do a simple NULL check, depending on the desired performance target. In any case, providing an invalid context pointer is considered a severe error. In addition to the direct context functions above that are variants of the standard functions, other extensions supported by a given implementation that have functions that use the current context also get direct context variants. A non-exhaustive list from known extensions is given below. From ALC_EXT_EFX: void alGenEffectsDirect(ALCcontext *context, ALsizei n, ALuint *effects); void alDeleteEffectsDirect(ALCcontext *context, ALsizei n, const ALuint *effects); ALboolean alIsEffectDirect(ALCcontext *context, ALuint effect); void alEffectiDirect(ALCcontext *context, ALuint effect, ALenum param, ALint iValue); void alEffectivDirect(ALCcontext *context, ALuint effect, ALenum param, const ALint *piValues); void alEffectfDirect(ALCcontext *context, ALuint effect, ALenum param, ALfloat flValue); void alEffectfvDirect(ALCcontext *context, ALuint effect, ALenum param, const ALfloat *pflValues); void alGetEffectiDirect(ALCcontext *context, ALuint effect, ALenum param, ALint *piValue); void alGetEffectivDirect(ALCcontext *context, ALuint effect, ALenum param, ALint *piValues); void alGetEffectfDirect(ALCcontext *context, ALuint effect, ALenum param, ALfloat *pflValue); void alGetEffectfvDirect(ALCcontext *context, ALuint effect, ALenum param, ALfloat *pflValues); void alGenFiltersDirect(ALCcontext *context, ALsizei n, ALuint *filters); void alDeleteFiltersDirect(ALCcontext *context, ALsizei n, const ALuint *filters); ALboolean alIsFilterDirect(ALCcontext *context, ALuint filter); void alFilteriDirect(ALCcontext *context, ALuint filter, ALenum param, ALint iValue); void alFilterivDirect(ALCcontext *context, ALuint filter, ALenum param, const ALint *piValues); void alFilterfDirect(ALCcontext *context, ALuint filter, ALenum param, ALfloat flValue); void alFilterfvDirect(ALCcontext *context, ALuint filter, ALenum param, const ALfloat *pflValues); void alGetFilteriDirect(ALCcontext *context, ALuint filter, ALenum param, ALint *piValue); void alGetFilterivDirect(ALCcontext *context, ALuint filter, ALenum param, ALint *piValues); void alGetFilterfDirect(ALCcontext *context, ALuint filter, ALenum param, ALfloat *pflValue); void alGetFilterfvDirect(ALCcontext *context, ALuint filter, ALenum param, ALfloat *pflValues); void alGenAuxiliaryEffectSlotsDirect(ALCcontext *context, ALsizei n, ALuint *effectslots); void alDeleteAuxiliaryEffectSlotsDirect(ALCcontext *context, ALsizei n, const ALuint *effectslots); ALboolean alIsAuxiliaryEffectSlotDirect(ALCcontext *context, ALuint effectslot); void alAuxiliaryEffectSlotiDirect(ALCcontext *context, ALuint effectslot, ALenum param, ALint iValue); void alAuxiliaryEffectSlotivDirect(ALCcontext *context, ALuint effectslot, ALenum param, const ALint *piValues); void alAuxiliaryEffectSlotfDirect(ALCcontext *context, ALuint effectslot, ALenum param, ALfloat flValue); void alAuxiliaryEffectSlotfvDirect(ALCcontext *context, ALuint effectslot, ALenum param, const ALfloat *pflValues); void alGetAuxiliaryEffectSlotiDirect(ALCcontext *context, ALuint effectslot, ALenum param, ALint *piValue); void alGetAuxiliaryEffectSlotivDirect(ALCcontext *context, ALuint effectslot, ALenum param, ALint *piValues); void alGetAuxiliaryEffectSlotfDirect(ALCcontext *context, ALuint effectslot, ALenum param, ALfloat *pflValue); void alGetAuxiliaryEffectSlotfvDirect(ALCcontext *context, ALuint effectslot, ALenum param, ALfloat *pflValues); From AL_EXT_BUFFER_DATA_STATIC: void alBufferDataStaticDirect(ALCcontext *context, ALuint buffer, ALenum format, ALvoid *data, ALsizei size, ALsizei freq); From AL_EXT_debug: void alDebugMessageCallbackDirectEXT(ALCcontext *context, ALDEBUGPROCEXT callback, void *userParam); void alDebugMessageInsertDirectEXT(ALCcontext *context, ALenum source, ALenum type, ALuint id, ALenum severity, ALsizei length, const ALchar *message); void alDebugMessageControlDirectEXT(ALCcontext *context, ALenum source, ALenum type, ALenum severity, ALsizei count, const ALuint *ids, ALboolean enable); void alPushDebugGroupDirectEXT(ALCcontext *context, ALenum source, ALuint id, ALsizei length, const ALchar *message); void alPopDebugGroupDirectEXT(ALCcontext *context); ALuint alGetDebugMessageLogDirectEXT(ALCcontext *context, ALuint count, ALsizei logBufSize, ALenum *sources, ALenum *types, ALuint *ids, ALenum *severities, ALsizei *lengths, ALchar *logBuf); void alObjectLabelDirectEXT(ALCcontext *context, ALenum identifier, ALuint name, ALsizei length, const ALchar *label); void alGetObjectLabelDirectEXT(ALCcontext *context, ALenum identifier, ALuint name, ALsizei bufSize, ALsizei *length, ALchar *label); void* alGetPointerDirectEXT(ALCcontext *context, ALenum pname); void alGetPointervDirectEXT(ALCcontext *context, ALenum pname, void **values); From AL_EXT_FOLDBACK: void alRequestFoldbackStartDirect(ALCcontext *context, ALenum mode, ALsizei count, ALsizei length, ALfloat *mem, LPALFOLDBACKCALLBACK callback); void alRequestFoldbackStopDirect(ALCcontext *context); From AL_SOFT_buffer_sub_data: void alBufferSubDataDirectSOFT(ALCcontext *context, ALuint buffer, ALenum format, const ALvoid *data, ALsizei offset, ALsizei length); From AL_SOFT_source_latency: void alSourcedDirectSOFT(ALCcontext *context, ALuint source, ALenum param, ALdouble value); void alSource3dDirectSOFT(ALCcontext *context, ALuint source, ALenum param, ALdouble value1, ALdouble value2, ALdouble value3); void alSourcedvDirectSOFT(ALCcontext *context, ALuint source, ALenum param, const ALdouble *values); void alGetSourcedDirectSOFT(ALCcontext *context, ALuint source, ALenum param, ALdouble *value); void alGetSource3dDirectSOFT(ALCcontext *context, ALuint source, ALenum param, ALdouble *value1, ALdouble *value2, ALdouble *value3); void alGetSourcedvDirectSOFT(ALCcontext *context, ALuint source, ALenum param, ALdouble *values); void alSourcei64DirectSOFT(ALCcontext *context, ALuint source, ALenum param, ALint64SOFT value); void alSource3i64DirectSOFT(ALCcontext *context, ALuint source, ALenum param, ALint64SOFT value1, ALint64SOFT value2, ALint64SOFT value3); void alSourcei64vDirectSOFT(ALCcontext *context, ALuint source, ALenum param, const ALint64SOFT *values); void alGetSourcei64DirectSOFT(ALCcontext *context, ALuint source, ALenum param, ALint64SOFT *value); void alGetSource3i64DirectSOFT(ALCcontext *context, ALuint source, ALenum param, ALint64SOFT *value1, ALint64SOFT *value2, ALint64SOFT *value3); void alGetSourcei64vDirectSOFT(ALCcontext *context, ALuint source, ALenum param, ALint64SOFT *values); From AL_SOFT_deferred_updates: void alDeferUpdatesDirectSOFT(ALCcontext *context); void alProcessUpdatesDirectSOFT(ALCcontext *context); From AL_SOFT_source_resampler: const ALchar* alGetStringiDirectSOFT(ALCcontext *context, ALenum pname, ALsizei index); From AL_SOFT_events: void alEventControlDirectSOFT(ALCcontext *context, ALsizei count, const ALenum *types, ALboolean enable); void alEventCallbackDirectSOFT(ALCcontext *context, ALEVENTPROCSOFT callback, void *userParam); void* alGetPointerDirectSOFT(ALCcontext *context, ALenum pname); void alGetPointervDirectSOFT(ALCcontext *context, ALenum pname, void **values); From AL_SOFT_callback_buffer: void alBufferCallbackDirectSOFT(ALCcontext *context, ALuint buffer, ALenum format, ALsizei freq, ALBUFFERCALLBACKTYPESOFT callback, ALvoid *userptr); void alGetBufferPtrDirectSOFT(ALCcontext *context, ALuint buffer, ALenum param, ALvoid **ptr); void alGetBuffer3PtrDirectSOFT(ALCcontext *context, ALuint buffer, ALenum param, ALvoid **ptr0, ALvoid **ptr1, ALvoid **ptr2); void alGetBufferPtrvDirectSOFT(ALCcontext *context, ALuint buffer, ALenum param, ALvoid **ptr); From AL_SOFT_source_start_delay: void alSourcePlayAtTimeDirectSOFT(ALCcontext *context, ALuint source, ALint64SOFT start_time); void alSourcePlayAtTimevDirectSOFT(ALCcontext *context, ALsizei n, const ALuint *sources, ALint64SOFT start_time); From EAX: ALenum EAXSetDirect(ALCcontext *context, const GUID *property_set_id, ALuint property_id, ALuint source_id, ALvoid *value, ALuint value_size); ALenum EAXGetDirect(ALCcontext *context, const GUID *property_set_id, ALuint property_id, ALuint source_id, ALvoid *value, ALuint value_size); From EAX-RAM: ALboolean EAXSetBufferModeDirect(ALCcontext *context, ALsizei n, const ALuint *buffers, ALint value); ALenum EAXGetBufferModeDirect(ALCcontext *context, ALuint buffer, ALint *pReserved); Obviously, an implementation will not support functions relating to extensions it doesn't support. Errors