diff options
-rw-r--r-- | OpenAL32/Include/alBuffer.h | 3 | ||||
-rw-r--r-- | OpenAL32/Include/alMain.h | 12 | ||||
-rw-r--r-- | OpenAL32/alBuffer.c | 121 | ||||
-rw-r--r-- | OpenAL32/alSource.c | 13 |
4 files changed, 137 insertions, 12 deletions
diff --git a/OpenAL32/Include/alBuffer.h b/OpenAL32/Include/alBuffer.h index 852a8782..60a047c9 100644 --- a/OpenAL32/Include/alBuffer.h +++ b/OpenAL32/Include/alBuffer.h @@ -76,6 +76,7 @@ typedef struct ALbuffer { ALsizei Frequency; ALenum Format; + ALbitfieldSOFT Access; ALsizei SampleLen; enum FmtChannels FmtChannels; @@ -93,6 +94,8 @@ typedef struct ALbuffer { ATOMIC(ALsizei) UnpackAlign; ATOMIC(ALsizei) PackAlign; + ALbitfieldSOFT MappedAccess; + /* Number of times buffer was attached to a source (deletion can only occur when 0) */ RefCount ref; diff --git a/OpenAL32/Include/alMain.h b/OpenAL32/Include/alMain.h index 50c9decf..dbb4f14b 100644 --- a/OpenAL32/Include/alMain.h +++ b/OpenAL32/Include/alMain.h @@ -47,6 +47,18 @@ #define ALC_N3D_SOFT 0xfff7 #endif +#ifndef AL_SOFT_map_buffer +typedef unsigned int ALbitfieldSOFT; +#define AL_MAP_READ_BIT_SOFT 0x01000000 +#define AL_MAP_WRITE_BIT_SOFT 0x02000000 +typedef void* (AL_APIENTRY*LPALMAPBUFFERSOFT)(ALuint buffer, ALsizei offset, ALsizei length, ALbitfieldSOFT access); +typedef void* (AL_APIENTRY*LPALUNMAPBUFFERSOFT)(ALuint buffer); +#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); +#endif +#endif + #if defined(_WIN64) #define SZFMT "%I64u" diff --git a/OpenAL32/alBuffer.c b/OpenAL32/alBuffer.c index ac755688..1c9b2650 100644 --- a/OpenAL32/alBuffer.c +++ b/OpenAL32/alBuffer.c @@ -45,7 +45,7 @@ extern inline struct ALbuffer *RemoveBuffer(ALCdevice *device, ALuint id); extern inline ALsizei FrameSizeFromUserFmt(enum UserFmtChannels chans, enum UserFmtType type); extern inline ALsizei FrameSizeFromFmt(enum FmtChannels chans, enum FmtType type); -static ALenum LoadData(ALbuffer *buffer, ALuint freq, ALenum NewFormat, ALsizei frames, enum UserFmtChannels SrcChannels, enum UserFmtType SrcType, const ALvoid *data, ALsizei align, ALboolean storesrc); +static ALenum LoadData(ALbuffer *buffer, ALuint freq, ALenum NewFormat, ALsizei frames, enum UserFmtChannels SrcChannels, enum UserFmtType SrcType, const ALvoid *data, ALsizei align, ALbitfieldSOFT access, ALboolean storesrc); static ALboolean IsValidType(ALenum type); static ALboolean IsValidChannels(ALenum channels); static ALboolean DecomposeUserFormat(ALenum format, enum UserFmtChannels *chans, enum UserFmtType *type); @@ -53,6 +53,11 @@ static ALboolean DecomposeFormat(ALenum format, enum FmtChannels *chans, enum Fm static ALsizei SanitizeAlignment(enum UserFmtType type, ALsizei align); +#define FORMAT_MASK 0x00ffffff +#define ACCESS_FLAGS (AL_MAP_READ_BIT_SOFT | AL_MAP_WRITE_BIT_SOFT) +#define INVALID_FLAG_MASK ~(FORMAT_MASK | ACCESS_FLAGS) + + AL_API ALvoid AL_APIENTRY alGenBuffers(ALsizei n, ALuint *buffers) { ALCcontext *context; @@ -157,9 +162,9 @@ AL_API ALvoid AL_APIENTRY alBufferData(ALuint buffer, ALenum format, const ALvoi LockBuffersRead(device); if((albuf=LookupBuffer(device, buffer)) == NULL) SET_ERROR_AND_GOTO(context, AL_INVALID_NAME, done); - if(!(size >= 0 && freq > 0)) + if(!(size >= 0 && freq > 0) || (format&INVALID_FLAG_MASK) != 0) SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done); - if(DecomposeUserFormat(format, &srcchannels, &srctype) == AL_FALSE) + if(DecomposeUserFormat(format&FORMAT_MASK, &srcchannels, &srctype) == AL_FALSE) SET_ERROR_AND_GOTO(context, AL_INVALID_ENUM, done); align = SanitizeAlignment(srctype, ATOMIC_LOAD_SEQ(&albuf->UnpackAlign)); @@ -178,8 +183,9 @@ AL_API ALvoid AL_APIENTRY alBufferData(ALuint buffer, ALenum format, const ALvoi if((size%framesize) != 0) SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done); - err = LoadData(albuf, freq, format, size/framesize*align, - srcchannels, srctype, data, align, AL_TRUE); + err = LoadData(albuf, freq, format&FORMAT_MASK, size/framesize*align, + srcchannels, srctype, data, align, format&ACCESS_FLAGS, + AL_TRUE); if(err != AL_NO_ERROR) SET_ERROR_AND_GOTO(context, err, done); break; @@ -204,7 +210,8 @@ AL_API ALvoid AL_APIENTRY alBufferData(ALuint buffer, ALenum format, const ALvoi case UserFmtBFormat3D: newformat = AL_FORMAT_BFORMAT3D_FLOAT32; break; } err = LoadData(albuf, freq, newformat, size/framesize*align, - srcchannels, srctype, data, align, AL_TRUE); + srcchannels, srctype, data, align, format&ACCESS_FLAGS, + AL_TRUE); if(err != AL_NO_ERROR) SET_ERROR_AND_GOTO(context, err, done); break; @@ -228,7 +235,8 @@ AL_API ALvoid AL_APIENTRY alBufferData(ALuint buffer, ALenum format, const ALvoi case UserFmtBFormat3D: newformat = AL_FORMAT_BFORMAT3D_16; break; } err = LoadData(albuf, freq, newformat, size/framesize*align, - srcchannels, srctype, data, align, AL_TRUE); + srcchannels, srctype, data, align, format&ACCESS_FLAGS, + AL_TRUE); if(err != AL_NO_ERROR) SET_ERROR_AND_GOTO(context, err, done); break; @@ -252,7 +260,8 @@ AL_API ALvoid AL_APIENTRY alBufferData(ALuint buffer, ALenum format, const ALvoi case UserFmtBFormat3D: newformat = AL_FORMAT_BFORMAT3D_16; break; } err = LoadData(albuf, freq, newformat, size/framesize*align, - srcchannels, srctype, data, align, AL_TRUE); + srcchannels, srctype, data, align, format&ACCESS_FLAGS, + AL_TRUE); if(err != AL_NO_ERROR) SET_ERROR_AND_GOTO(context, err, done); break; @@ -263,6 +272,80 @@ done: ALCcontext_DecRef(context); } +AL_API void* AL_APIENTRY alMapBufferSOFT(ALuint buffer, ALsizei offset, ALsizei length, ALbitfieldSOFT access) +{ + void *retval = NULL; + ALCdevice *device; + ALCcontext *context; + ALbuffer *albuf; + + context = GetContextRef(); + if(!context) return retval; + + device = context->Device; + LockBuffersRead(device); + if((albuf=LookupBuffer(device, buffer)) == NULL) + SET_ERROR_AND_GOTO(context, AL_INVALID_NAME, done); + if(!access || (access&~(AL_MAP_READ_BIT_SOFT|AL_MAP_WRITE_BIT_SOFT)) != 0) + SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done); + 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))) + { + WriteUnlock(&albuf->lock); + SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done); + } + if(offset < 0 || offset >= albuf->OriginalSize || + length <= 0 || length > albuf->OriginalSize - offset) + { + WriteUnlock(&albuf->lock); + SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done); + } + if(ReadRef(&albuf->ref) != 0 || albuf->MappedAccess != 0) + { + WriteUnlock(&albuf->lock); + SET_ERROR_AND_GOTO(context, AL_INVALID_OPERATION, 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); + WriteUnlock(&albuf->lock); + +done: + UnlockBuffersRead(device); + ALCcontext_DecRef(context); + + return retval; +} + +AL_API void AL_APIENTRY alUnmapBufferSOFT(ALuint buffer) +{ + 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) + alSetError(context, AL_INVALID_OPERATION); + else + albuf->MappedAccess = 0; + 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; @@ -304,6 +387,11 @@ AL_API ALvoid AL_APIENTRY alBufferSubDataSOFT(ALuint buffer, ALenum format, cons WriteUnlock(&albuf->lock); SET_ERROR_AND_GOTO(context, AL_INVALID_ENUM, done); } + if(albuf->MappedAccess != 0) + { + WriteUnlock(&albuf->lock); + SET_ERROR_AND_GOTO(context, AL_INVALID_OPERATION, done); + } if(albuf->OriginalType == UserFmtIMA4) { @@ -362,7 +450,7 @@ AL_API void AL_APIENTRY alBufferSamplesSOFT(ALuint buffer, LockBuffersRead(device); if((albuf=LookupBuffer(device, buffer)) == NULL) SET_ERROR_AND_GOTO(context, AL_INVALID_NAME, done); - if(!(samples >= 0 && samplerate != 0)) + if(!(samples >= 0 && samplerate != 0) || (internalformat&~FORMAT_MASK) != 0) SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done); if(IsValidType(type) == AL_FALSE || IsValidChannels(channels) == AL_FALSE) SET_ERROR_AND_GOTO(context, AL_INVALID_ENUM, done); @@ -374,7 +462,7 @@ AL_API void AL_APIENTRY alBufferSamplesSOFT(ALuint buffer, SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done); err = LoadData(albuf, samplerate, internalformat, samples, - channels, type, data, align, AL_FALSE); + channels, type, data, align, 0, AL_FALSE); if(err != AL_NO_ERROR) SET_ERROR_AND_GOTO(context, err, done); @@ -956,7 +1044,7 @@ done: * Currently, the new format must have the same channel configuration as the * original format. */ -static ALenum LoadData(ALbuffer *ALBuf, ALuint freq, ALenum NewFormat, ALsizei frames, enum UserFmtChannels SrcChannels, enum UserFmtType SrcType, const ALvoid *data, ALsizei align, ALboolean storesrc) +static ALenum LoadData(ALbuffer *ALBuf, ALuint freq, ALenum NewFormat, ALsizei frames, enum UserFmtChannels SrcChannels, enum UserFmtType SrcType, const ALvoid *data, ALsizei align, ALbitfieldSOFT access, ALboolean storesrc) { enum FmtChannels DstChannels = FmtMono; enum FmtType DstType = FmtUByte; @@ -968,6 +1056,12 @@ static ALenum LoadData(ALbuffer *ALBuf, ALuint freq, ALenum NewFormat, ALsizei f if((long)SrcChannels != (long)DstChannels) return AL_INVALID_ENUM; + if(access != 0) + { + if(!storesrc || (long)SrcType != (long)DstType) + return AL_INVALID_VALUE; + } + NewChannels = ChannelsFromFmt(DstChannels); NewBytes = BytesFromFmt(DstType); @@ -978,7 +1072,7 @@ static ALenum LoadData(ALbuffer *ALBuf, ALuint freq, ALenum NewFormat, ALsizei f return AL_OUT_OF_MEMORY; WriteLock(&ALBuf->lock); - if(ReadRef(&ALBuf->ref) != 0) + if(ReadRef(&ALBuf->ref) != 0 || ALBuf->MappedAccess != 0) { WriteUnlock(&ALBuf->lock); return AL_INVALID_OPERATION; @@ -1041,6 +1135,7 @@ static ALenum LoadData(ALbuffer *ALBuf, ALuint freq, ALenum NewFormat, ALsizei f ALBuf->FmtChannels = DstChannels; ALBuf->FmtType = DstType; ALBuf->Format = NewFormat; + ALBuf->Access = access; ALBuf->SampleLen = frames; ALBuf->LoopStart = 0; @@ -1346,6 +1441,8 @@ ALbuffer *NewBuffer(ALCcontext *context) if(!buffer) SET_ERROR_AND_RETURN_VALUE(context, AL_OUT_OF_MEMORY, NULL); RWLockInit(&buffer->lock); + buffer->Access = 0; + buffer->MappedAccess = 0; err = NewThunkEntry(&buffer->id); if(err == AL_NO_ERROR) diff --git a/OpenAL32/alSource.c b/OpenAL32/alSource.c index 83233b3f..5f21b991 100644 --- a/OpenAL32/alSource.c +++ b/OpenAL32/alSource.c @@ -760,6 +760,13 @@ static ALboolean SetSourceiv(ALsource *Source, ALCcontext *Context, SourceProp p } WriteLock(&Source->queue_lock); + if(buffer && buffer->MappedAccess != 0) + { + WriteUnlock(&Source->queue_lock); + UnlockBuffersRead(device); + SET_ERROR_AND_RETURN_VALUE(Context, AL_INVALID_OPERATION, AL_FALSE); + } + else { ALenum state = GetSourceState(Source, GetSourceVoice(Source, Context)); if(state == AL_PLAYING || state == AL_PAUSED) @@ -2881,6 +2888,12 @@ AL_API ALvoid AL_APIENTRY alSourceQueueBuffers(ALuint src, ALsizei nb, const ALu ReadLock(&buffer->lock); IncrementRef(&buffer->ref); + if(buffer->MappedAccess != 0) + { + WriteUnlock(&source->queue_lock); + SET_ERROR_AND_GOTO(context, AL_INVALID_OPERATION, buffer_error); + } + if(BufferFmt == NULL) BufferFmt = buffer; else if(BufferFmt->Frequency != buffer->Frequency || |