summaryrefslogtreecommitdiffstats
path: root/src/3rdparty/angle/src/libGLESv2/renderer/BufferStorage11.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/3rdparty/angle/src/libGLESv2/renderer/BufferStorage11.cpp')
-rw-r--r--src/3rdparty/angle/src/libGLESv2/renderer/BufferStorage11.cpp342
1 files changed, 342 insertions, 0 deletions
diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/BufferStorage11.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/BufferStorage11.cpp
new file mode 100644
index 0000000000..4c37bdbf60
--- /dev/null
+++ b/src/3rdparty/angle/src/libGLESv2/renderer/BufferStorage11.cpp
@@ -0,0 +1,342 @@
+#include "precompiled.h"
+//
+// Copyright (c) 2013 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// BufferStorage11.cpp Defines the BufferStorage11 class.
+
+#include "libGLESv2/renderer/BufferStorage11.h"
+#include "libGLESv2/main.h"
+#include "libGLESv2/renderer/Renderer11.h"
+
+namespace rx
+{
+
+BufferStorage11::BufferStorage11(Renderer11 *renderer)
+{
+ mRenderer = renderer;
+
+ mStagingBuffer = NULL;
+ mStagingBufferSize = 0;
+
+ mBuffer = NULL;
+ mBufferSize = 0;
+
+ mSize = 0;
+
+ mResolvedData = NULL;
+ mResolvedDataSize = 0;
+ mResolvedDataValid = false;
+
+ mReadUsageCount = 0;
+ mWriteUsageCount = 0;
+}
+
+BufferStorage11::~BufferStorage11()
+{
+ if (mStagingBuffer)
+ {
+ mStagingBuffer->Release();
+ mStagingBuffer = NULL;
+ }
+
+ if (mBuffer)
+ {
+ mBuffer->Release();
+ mBuffer = NULL;
+ }
+
+ if (mResolvedData)
+ {
+ free(mResolvedData);
+ mResolvedData = NULL;
+ }
+}
+
+BufferStorage11 *BufferStorage11::makeBufferStorage11(BufferStorage *bufferStorage)
+{
+ ASSERT(HAS_DYNAMIC_TYPE(BufferStorage11*, bufferStorage));
+ return static_cast<BufferStorage11*>(bufferStorage);
+}
+
+void *BufferStorage11::getData()
+{
+ if (!mResolvedDataValid)
+ {
+ ID3D11Device *device = mRenderer->getDevice();
+ ID3D11DeviceContext *context = mRenderer->getDeviceContext();
+ HRESULT result;
+
+ if (!mStagingBuffer || mStagingBufferSize < mBufferSize)
+ {
+ if (mStagingBuffer)
+ {
+ mStagingBuffer->Release();
+ mStagingBuffer = NULL;
+ mStagingBufferSize = 0;
+ }
+
+ D3D11_BUFFER_DESC bufferDesc;
+ bufferDesc.ByteWidth = mSize;
+ bufferDesc.Usage = D3D11_USAGE_STAGING;
+ bufferDesc.BindFlags = 0;
+ bufferDesc.CPUAccessFlags = D3D11_CPU_ACCESS_READ | D3D11_CPU_ACCESS_WRITE;
+ bufferDesc.MiscFlags = 0;
+ bufferDesc.StructureByteStride = 0;
+
+ result = device->CreateBuffer(&bufferDesc, NULL, &mStagingBuffer);
+ if (FAILED(result))
+ {
+ return gl::error(GL_OUT_OF_MEMORY, (void*)NULL);
+ }
+
+ mStagingBufferSize = bufferDesc.ByteWidth;
+ }
+
+ if (!mResolvedData || mResolvedDataSize < mBufferSize)
+ {
+ free(mResolvedData);
+ mResolvedData = malloc(mSize);
+ mResolvedDataSize = mSize;
+ }
+
+ D3D11_BOX srcBox;
+ srcBox.left = 0;
+ srcBox.right = mSize;
+ srcBox.top = 0;
+ srcBox.bottom = 1;
+ srcBox.front = 0;
+ srcBox.back = 1;
+
+ context->CopySubresourceRegion(mStagingBuffer, 0, 0, 0, 0, mBuffer, 0, &srcBox);
+
+ D3D11_MAPPED_SUBRESOURCE mappedResource;
+ result = context->Map(mStagingBuffer, 0, D3D11_MAP_READ, 0, &mappedResource);
+ if (FAILED(result))
+ {
+ return gl::error(GL_OUT_OF_MEMORY, (void*)NULL);
+ }
+
+ memcpy(mResolvedData, mappedResource.pData, mSize);
+
+ context->Unmap(mStagingBuffer, 0);
+
+ mResolvedDataValid = true;
+ }
+
+ mReadUsageCount = 0;
+
+ return mResolvedData;
+}
+
+void BufferStorage11::setData(const void* data, unsigned int size, unsigned int offset)
+{
+ ID3D11Device *device = mRenderer->getDevice();
+ ID3D11DeviceContext *context = mRenderer->getDeviceContext();
+ HRESULT result;
+
+ unsigned int requiredBufferSize = size + offset;
+ unsigned int requiredStagingSize = size;
+ bool directInitialization = offset == 0 && (!mBuffer || mBufferSize < size + offset);
+
+ if (!directInitialization)
+ {
+ if (!mStagingBuffer || mStagingBufferSize < requiredStagingSize)
+ {
+ if (mStagingBuffer)
+ {
+ mStagingBuffer->Release();
+ mStagingBuffer = NULL;
+ mStagingBufferSize = 0;
+ }
+
+ D3D11_BUFFER_DESC bufferDesc;
+ bufferDesc.ByteWidth = size;
+ bufferDesc.Usage = D3D11_USAGE_STAGING;
+ bufferDesc.BindFlags = 0;
+ bufferDesc.CPUAccessFlags = D3D11_CPU_ACCESS_READ | D3D11_CPU_ACCESS_WRITE;
+ bufferDesc.MiscFlags = 0;
+ bufferDesc.StructureByteStride = 0;
+
+ D3D11_SUBRESOURCE_DATA initialData;
+ initialData.pSysMem = data;
+ initialData.SysMemPitch = size;
+ initialData.SysMemSlicePitch = 0;
+
+ result = device->CreateBuffer(&bufferDesc, &initialData, &mStagingBuffer);
+ if (FAILED(result))
+ {
+ return gl::error(GL_OUT_OF_MEMORY);
+ }
+
+ mStagingBufferSize = size;
+ }
+ else
+ {
+ D3D11_MAPPED_SUBRESOURCE mappedResource;
+ result = context->Map(mStagingBuffer, 0, D3D11_MAP_WRITE, 0, &mappedResource);
+ if (FAILED(result))
+ {
+ return gl::error(GL_OUT_OF_MEMORY);
+ }
+
+ memcpy(mappedResource.pData, data, size);
+
+ context->Unmap(mStagingBuffer, 0);
+ }
+ }
+
+ if (!mBuffer || mBufferSize < size + offset)
+ {
+ D3D11_BUFFER_DESC bufferDesc;
+ bufferDesc.ByteWidth = requiredBufferSize;
+ bufferDesc.Usage = D3D11_USAGE_DEFAULT;
+ bufferDesc.BindFlags = D3D11_BIND_VERTEX_BUFFER | D3D11_BIND_INDEX_BUFFER;
+ bufferDesc.CPUAccessFlags = 0;
+ bufferDesc.MiscFlags = 0;
+ bufferDesc.StructureByteStride = 0;
+
+ if (directInitialization)
+ {
+ // Since the data will fill the entire buffer (being larger than the initial size and having
+ // no offset), the buffer can be initialized with the data so no staging buffer is required
+
+ // No longer need the old buffer
+ if (mBuffer)
+ {
+ mBuffer->Release();
+ mBuffer = NULL;
+ mBufferSize = 0;
+ }
+
+ D3D11_SUBRESOURCE_DATA initialData;
+ initialData.pSysMem = data;
+ initialData.SysMemPitch = size;
+ initialData.SysMemSlicePitch = 0;
+
+ result = device->CreateBuffer(&bufferDesc, &initialData, &mBuffer);
+ if (FAILED(result))
+ {
+ return gl::error(GL_OUT_OF_MEMORY);
+ }
+ }
+ else if (mBuffer && offset > 0)
+ {
+ // If offset is greater than zero and the buffer is non-null, need to preserve the data from
+ // the old buffer up to offset
+ ID3D11Buffer *newBuffer = NULL;
+
+ result = device->CreateBuffer(&bufferDesc, NULL, &newBuffer);
+ if (FAILED(result))
+ {
+ return gl::error(GL_OUT_OF_MEMORY);
+ }
+
+ D3D11_BOX srcBox;
+ srcBox.left = 0;
+ srcBox.right = std::min(offset, mBufferSize);
+ srcBox.top = 0;
+ srcBox.bottom = 1;
+ srcBox.front = 0;
+ srcBox.back = 1;
+
+ context->CopySubresourceRegion(newBuffer, 0, 0, 0, 0, mBuffer, 0, &srcBox);
+
+ mBuffer->Release();
+ mBuffer = newBuffer;
+ }
+ else
+ {
+ // Simple case, nothing needs to be copied from the old buffer to the new one, just create
+ // a new buffer
+
+ // No longer need the old buffer
+ if (mBuffer)
+ {
+ mBuffer->Release();
+ mBuffer = NULL;
+ mBufferSize = 0;
+ }
+
+ // Create a new buffer for data storage
+ result = device->CreateBuffer(&bufferDesc, NULL, &mBuffer);
+ if (FAILED(result))
+ {
+ return gl::error(GL_OUT_OF_MEMORY);
+ }
+ }
+
+ updateSerial();
+ mBufferSize = bufferDesc.ByteWidth;
+ }
+
+ if (!directInitialization)
+ {
+ ASSERT(mStagingBuffer && mStagingBufferSize >= requiredStagingSize);
+
+ // Data is already put into the staging buffer, copy it over to the data buffer
+ D3D11_BOX srcBox;
+ srcBox.left = 0;
+ srcBox.right = size;
+ srcBox.top = 0;
+ srcBox.bottom = 1;
+ srcBox.front = 0;
+ srcBox.back = 1;
+
+ context->CopySubresourceRegion(mBuffer, 0, offset, 0, 0, mStagingBuffer, 0, &srcBox);
+ }
+
+ mSize = std::max(mSize, offset + size);
+
+ mWriteUsageCount = 0;
+
+ mResolvedDataValid = false;
+}
+
+void BufferStorage11::clear()
+{
+ mResolvedDataValid = false;
+ mSize = 0;
+}
+
+unsigned int BufferStorage11::getSize() const
+{
+ return mSize;
+}
+
+bool BufferStorage11::supportsDirectBinding() const
+{
+ return true;
+}
+
+void BufferStorage11::markBufferUsage()
+{
+ mReadUsageCount++;
+ mWriteUsageCount++;
+
+ static const unsigned int usageLimit = 5;
+
+ if (mReadUsageCount > usageLimit && mResolvedData)
+ {
+ free(mResolvedData);
+ mResolvedData = NULL;
+ mResolvedDataSize = 0;
+ mResolvedDataValid = false;
+ }
+
+ if (mReadUsageCount > usageLimit && mWriteUsageCount > usageLimit && mStagingBuffer)
+ {
+ mStagingBuffer->Release();
+ mStagingBuffer = NULL;
+ mStagingBufferSize = 0;
+ }
+}
+
+ID3D11Buffer *BufferStorage11::getBuffer() const
+{
+ return mBuffer;
+}
+
+}