aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorChris Robinson <[email protected]>2018-01-23 10:38:27 -0800
committerChris Robinson <[email protected]>2018-01-23 10:38:27 -0800
commit4f9a0460c4a0fc6df5dba8b98ee6ac4e3ed7d90a (patch)
treed1f6d2054b39f8be02bf29778da7fa94ad20aacf
parentad61392318d3054d1c3810a6cc0ac0924dddab6f (diff)
Add a flag for persistent mapping
And a function to "flush" a mapped buffer
-rw-r--r--OpenAL32/Include/alMain.h3
-rw-r--r--OpenAL32/alBuffer.c49
-rw-r--r--OpenAL32/alSource.c5
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);