diff options
author | Chris Robinson <[email protected]> | 2018-01-23 10:38:27 -0800 |
---|---|---|
committer | Chris Robinson <[email protected]> | 2018-01-23 10:38:27 -0800 |
commit | 4f9a0460c4a0fc6df5dba8b98ee6ac4e3ed7d90a (patch) | |
tree | d1f6d2054b39f8be02bf29778da7fa94ad20aacf | |
parent | ad61392318d3054d1c3810a6cc0ac0924dddab6f (diff) |
Add a flag for persistent mapping
And a function to "flush" a mapped buffer
-rw-r--r-- | OpenAL32/Include/alMain.h | 3 | ||||
-rw-r--r-- | OpenAL32/alBuffer.c | 49 | ||||
-rw-r--r-- | OpenAL32/alSource.c | 5 |
3 files changed, 49 insertions, 8 deletions
diff --git a/OpenAL32/Include/alMain.h b/OpenAL32/Include/alMain.h index 6c30776b..d986adde 100644 --- a/OpenAL32/Include/alMain.h +++ b/OpenAL32/Include/alMain.h @@ -53,11 +53,14 @@ typedef unsigned int ALbitfieldSOFT; #define AL_MAP_READ_BIT_SOFT 0x01000000 #define AL_MAP_WRITE_BIT_SOFT 0x02000000 #define AL_PRESERVE_DATA_BIT_SOFT 0x04000000 +#define AL_MAP_PERSISTENT_BIT_SOFT 0x08000000 typedef void* (AL_APIENTRY*LPALMAPBUFFERSOFT)(ALuint buffer, ALsizei offset, ALsizei length, ALbitfieldSOFT access); typedef void (AL_APIENTRY*LPALUNMAPBUFFERSOFT)(ALuint buffer); +typedef void (AL_APIENTRY*LPALFLUSHMAPPEDBUFFERSOFT)(ALuint buffer, ALsizei offset, ALsizei length); #ifdef AL_ALEXT_PROTOTYPES AL_API void* AL_APIENTRY alMapBufferSOFT(ALuint buffer, ALsizei offset, ALsizei length, ALbitfieldSOFT access); AL_API void AL_APIENTRY alUnmapBufferSOFT(ALuint buffer); +AL_API void AL_APIENTRY alFlushMappedBufferSOFT(ALuint buffer, ALsizei offset, ALsizei length); #endif #endif diff --git a/OpenAL32/alBuffer.c b/OpenAL32/alBuffer.c index 9e4249ec..b2302933 100644 --- a/OpenAL32/alBuffer.c +++ b/OpenAL32/alBuffer.c @@ -51,9 +51,9 @@ static ALsizei SanitizeAlignment(enum UserFmtType type, ALsizei align); #define FORMAT_MASK 0x00ffffff -#define CONSTRUCT_FLAGS (AL_MAP_READ_BIT_SOFT | AL_MAP_WRITE_BIT_SOFT | AL_PRESERVE_DATA_BIT_SOFT) +#define CONSTRUCT_FLAGS (AL_MAP_READ_BIT_SOFT | AL_MAP_WRITE_BIT_SOFT | AL_PRESERVE_DATA_BIT_SOFT | AL_MAP_PERSISTENT_BIT_SOFT) #define INVALID_FORMAT_MASK ~(FORMAT_MASK | CONSTRUCT_FLAGS) -#define MAP_ACCESS_FLAGS (AL_MAP_READ_BIT_SOFT | AL_MAP_WRITE_BIT_SOFT) +#define MAP_ACCESS_FLAGS (AL_MAP_READ_BIT_SOFT | AL_MAP_WRITE_BIT_SOFT | AL_MAP_PERSISTENT_BIT_SOFT) AL_API ALvoid AL_APIENTRY alGenBuffers(ALsizei n, ALuint *buffers) @@ -232,18 +232,18 @@ AL_API void* AL_APIENTRY alMapBufferSOFT(ALuint buffer, ALsizei offset, ALsizei WriteLock(&albuf->lock); if(((access&AL_MAP_READ_BIT_SOFT) && !(albuf->Access&AL_MAP_READ_BIT_SOFT)) || - ((access&AL_MAP_WRITE_BIT_SOFT) && !(albuf->Access&AL_MAP_WRITE_BIT_SOFT))) + ((access&AL_MAP_WRITE_BIT_SOFT) && !(albuf->Access&AL_MAP_WRITE_BIT_SOFT)) || + ((access&AL_MAP_PERSISTENT_BIT_SOFT) && !(albuf->Access&AL_MAP_PERSISTENT_BIT_SOFT))) SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, unlock_done); if(offset < 0 || offset >= albuf->OriginalSize || length <= 0 || length > albuf->OriginalSize - offset) SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, unlock_done); - if(ReadRef(&albuf->ref) != 0 || albuf->MappedAccess != 0) + if(albuf->MappedAccess != 0 || + (!(access&AL_MAP_PERSISTENT_BIT_SOFT) && ReadRef(&albuf->ref) != 0)) SET_ERROR_AND_GOTO(context, AL_INVALID_OPERATION, unlock_done); retval = (ALbyte*)albuf->data + offset; albuf->MappedAccess = access; - if((access&AL_MAP_WRITE_BIT_SOFT) && !(access&AL_MAP_READ_BIT_SOFT)) - memset(retval, 0x55, length); unlock_done: WriteUnlock(&albuf->lock); @@ -281,6 +281,43 @@ done: ALCcontext_DecRef(context); } +AL_API void AL_APIENTRY alFlushMappedBufferSOFT(ALuint buffer, ALsizei offset, ALsizei length) +{ + ALCdevice *device; + ALCcontext *context; + ALbuffer *albuf; + + context = GetContextRef(); + if(!context) return; + + device = context->Device; + LockBuffersRead(device); + if((albuf=LookupBuffer(device, buffer)) == NULL) + SET_ERROR_AND_GOTO(context, AL_INVALID_NAME, done); + + WriteLock(&albuf->lock); + if(albuf->MappedAccess == 0 || !(albuf->MappedAccess&AL_MAP_WRITE_BIT_SOFT)) + alSetError(context, AL_INVALID_OPERATION); + /* TODO: Should check mapped range. */ + else if(offset < 0 || offset >= albuf->OriginalSize || + length <= 0 || length > albuf->OriginalSize - offset) + alSetError(context, AL_INVALID_VALUE); + else + { + /* FIXME: Need to use some method of double-buffering for the mixer and + * app to hold separate memory, which can be safely transfered + * asynchronously. Currently we just say the app shouldn't write where + * OpenAL's reading, and hope for the best... + */ + ATOMIC_THREAD_FENCE(almemory_order_seq_cst); + } + WriteUnlock(&albuf->lock); + +done: + UnlockBuffersRead(device); + ALCcontext_DecRef(context); +} + AL_API ALvoid AL_APIENTRY alBufferSubDataSOFT(ALuint buffer, ALenum format, const ALvoid *data, ALsizei offset, ALsizei length) { enum UserFmtChannels srcchannels = UserFmtMono; diff --git a/OpenAL32/alSource.c b/OpenAL32/alSource.c index 24f48895..8b3cb305 100644 --- a/OpenAL32/alSource.c +++ b/OpenAL32/alSource.c @@ -760,7 +760,8 @@ static ALboolean SetSourceiv(ALsource *Source, ALCcontext *Context, SourceProp p } WriteLock(&Source->queue_lock); - if(buffer && buffer->MappedAccess != 0) + if(buffer && buffer->MappedAccess != 0 && + !(buffer->MappedAccess&AL_MAP_PERSISTENT_BIT_SOFT)) { WriteUnlock(&Source->queue_lock); UnlockBuffersRead(device); @@ -2888,7 +2889,7 @@ AL_API ALvoid AL_APIENTRY alSourceQueueBuffers(ALuint src, ALsizei nb, const ALu ReadLock(&buffer->lock); IncrementRef(&buffer->ref); - if(buffer->MappedAccess != 0) + if(buffer->MappedAccess != 0 && !(buffer->MappedAccess&AL_MAP_PERSISTENT_BIT_SOFT)) { WriteUnlock(&source->queue_lock); SET_ERROR_AND_GOTO(context, AL_INVALID_OPERATION, buffer_error); |