aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--al/buffer.cpp55
1 files changed, 46 insertions, 9 deletions
diff --git a/al/buffer.cpp b/al/buffer.cpp
index dbbf38ff..1f008c8e 100644
--- a/al/buffer.cpp
+++ b/al/buffer.cpp
@@ -1553,40 +1553,77 @@ FORCE_ALIGN ALboolean AL_APIENTRY EAXSetBufferMode(ALsizei n, const ALuint *buff
if(!context)
{
ERR(EAX_PREFIX "%s\n", "No current context.");
- return ALC_FALSE;
+ return AL_FALSE;
}
if(!eax_g_is_enabled)
{
context->setError(AL_INVALID_OPERATION, EAX_PREFIX "%s", "EAX not enabled.");
- return ALC_FALSE;
+ return AL_FALSE;
}
const auto storage = EaxStorageFromEnum(value);
if(!storage)
{
context->setError(AL_INVALID_ENUM, EAX_PREFIX "Unsupported X-RAM mode 0x%x", value);
- return ALC_FALSE;
+ return AL_FALSE;
}
if(n == 0)
- return ALC_TRUE;
+ return AL_TRUE;
if(n < 0)
{
context->setError(AL_INVALID_VALUE, EAX_PREFIX "Buffer count %d out of range", n);
- return ALC_FALSE;
+ return AL_FALSE;
}
if(!buffers)
{
context->setError(AL_INVALID_VALUE, EAX_PREFIX "%s", "Null AL buffers");
- return ALC_FALSE;
+ return AL_FALSE;
}
auto device = context->mALDevice.get();
std::lock_guard<std::mutex> device_lock{device->BufferLock};
+ /* Special-case setting a single buffer, to avoid extraneous allocations. */
+ if(n == 1)
+ {
+ const auto bufid = buffers[0];
+ if(bufid == AL_NONE)
+ return AL_TRUE;
+
+ const auto buffer = LookupBuffer(device, bufid);
+ if(!buffer) UNLIKELY
+ {
+ ERR(EAX_PREFIX "Invalid buffer ID %u.\n", bufid);
+ return AL_FALSE;
+ }
+
+ /* TODO: Is the store location allowed to change for in-use buffers, or
+ * only when not set/queued on a source?
+ */
+
+ if(*storage == EaxStorage::Hardware)
+ {
+ if(!buffer->eax_x_ram_is_hardware
+ && buffer->OriginalSize > device->eax_x_ram_free_size) UNLIKELY
+ {
+ context->setError(AL_OUT_OF_MEMORY,
+ EAX_PREFIX "Out of X-RAM memory (need: %u, avail: %u)", buffer->OriginalSize,
+ device->eax_x_ram_free_size);
+ return AL_FALSE;
+ }
+
+ eax_x_ram_apply(*device, *buffer);
+ }
+ else
+ eax_x_ram_clear(*device, *buffer);
+ buffer->eax_x_ram_mode = *storage;
+ return AL_TRUE;
+ }
+
/* Validate the buffers. */
std::unordered_set<ALbuffer*> buflist;
for(auto i = 0;i < n;++i)
@@ -1599,7 +1636,7 @@ FORCE_ALIGN ALboolean AL_APIENTRY EAXSetBufferMode(ALsizei n, const ALuint *buff
if(!buffer) UNLIKELY
{
ERR(EAX_PREFIX "Invalid buffer ID %u.\n", bufid);
- return ALC_FALSE;
+ return AL_FALSE;
}
/* TODO: Is the store location allowed to change for in-use buffers, or
@@ -1620,7 +1657,7 @@ FORCE_ALIGN ALboolean AL_APIENTRY EAXSetBufferMode(ALsizei n, const ALuint *buff
{
context->setError(AL_OUT_OF_MEMORY, EAX_PREFIX "Size overflow (%u + %zu)\n",
buffer->OriginalSize, total_needed);
- return ALC_FALSE;
+ return AL_FALSE;
}
total_needed += buffer->OriginalSize;
}
@@ -1630,7 +1667,7 @@ FORCE_ALIGN ALboolean AL_APIENTRY EAXSetBufferMode(ALsizei n, const ALuint *buff
context->setError(AL_OUT_OF_MEMORY,
EAX_PREFIX "Out of X-RAM memory (need: %zu, avail: %u)", total_needed,
device->eax_x_ram_free_size);
- return ALC_FALSE;
+ return AL_FALSE;
}
}