Upstream version 10.39.225.0
[platform/framework/web/crosswalk.git] / src / third_party / angle / src / libGLESv2 / renderer / d3d / d3d11 / Buffer11.cpp
index 48514db..43ce5ba 100644 (file)
@@ -1,4 +1,3 @@
-#include "precompiled.h"
 //
 // Copyright 2014 The ANGLE Project Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
@@ -8,9 +7,9 @@
 // Buffer11.cpp Defines the Buffer11 class.
 
 #include "libGLESv2/renderer/d3d/d3d11/Buffer11.h"
-#include "libGLESv2/main.h"
 #include "libGLESv2/renderer/d3d/d3d11/Renderer11.h"
 #include "libGLESv2/renderer/d3d/d3d11/formatutils11.h"
+#include "libGLESv2/main.h"
 
 namespace rx
 {
@@ -118,6 +117,8 @@ class Buffer11::NativeBuffer11 : public Buffer11::BufferStorage11
     virtual void *map(size_t offset, size_t length, GLbitfield access);
     virtual void unmap();
 
+    bool setData(D3D11_MAP mapMode, const uint8_t *data, size_t size, size_t offset);
+
   private:
     ID3D11Buffer *mNativeBuffer;
 
@@ -139,7 +140,7 @@ class Buffer11::PackStorage11 : public Buffer11::BufferStorage11
     virtual void *map(size_t offset, size_t length, GLbitfield access);
     virtual void unmap();
 
-    void packPixels(ID3D11Texture2D *srcTexure, UINT srcSubresource, const PackPixelsParams &params);
+    gl::Error packPixels(ID3D11Texture2D *srcTexure, UINT srcSubresource, const PackPixelsParams &params);
 
   private:
 
@@ -178,16 +179,20 @@ Buffer11 *Buffer11::makeBuffer11(BufferImpl *buffer)
     return static_cast<Buffer11*>(buffer);
 }
 
-void Buffer11::setData(const void* data, size_t size, GLenum usage)
+gl::Error Buffer11::setData(const void *data, size_t size, GLenum usage)
 {
-    mIndexRangeCache.clear();
-
-    setSubData(data, size, 0);
+    gl::Error error = setSubData(data, size, 0);
+    if (error.isError())
+    {
+        return error;
+    }
 
     if (usage == GL_STATIC_DRAW)
     {
         initializeStaticData();
     }
+
+    return error;
 }
 
 void *Buffer11::getData()
@@ -228,16 +233,23 @@ void *Buffer11::getData()
 
     mReadUsageCount = 0;
 
+    // Only happens if we initialized the buffer with no data (NULL)
+    if (mResolvedData.empty())
+    {
+        if (!mResolvedData.resize(mSize))
+        {
+            return gl::error(GL_OUT_OF_MEMORY, (void*)NULL);
+        }
+    }
+
+    ASSERT(mResolvedData.size() >= mSize);
+
     return mResolvedData.data();
 }
 
-void Buffer11::setSubData(const void* data, size_t size, size_t offset)
+gl::Error Buffer11::setSubData(const void *data, size_t size, size_t offset)
 {
     size_t requiredSize = size + offset;
-    mSize = std::max(mSize, requiredSize);
-
-    mIndexRangeCache.invalidateRange(offset, size);
-    invalidateStaticData();
 
     if (data && size > 0)
     {
@@ -245,8 +257,7 @@ void Buffer11::setSubData(const void* data, size_t size, size_t offset)
 
         if (!stagingBuffer)
         {
-            // Out-of-memory
-            return;
+            return gl::Error(GL_OUT_OF_MEMORY, "Failed to allocate internal staging buffer.");
         }
 
         // Explicitly resize the staging buffer, preserving data if the new data will not
@@ -256,81 +267,78 @@ void Buffer11::setSubData(const void* data, size_t size, size_t offset)
             bool preserveData = (offset > 0);
             if (!stagingBuffer->resize(requiredSize, preserveData))
             {
-                // Out-of-memory
-                return;
+                return gl::Error(GL_OUT_OF_MEMORY, "Failed to resize internal staging buffer.");
             }
         }
 
-        ID3D11DeviceContext *context = mRenderer->getDeviceContext();
-
-        D3D11_MAPPED_SUBRESOURCE mappedResource;
-        HRESULT result = context->Map(stagingBuffer->getNativeBuffer(), 0, D3D11_MAP_WRITE, 0, &mappedResource);
-        if (FAILED(result))
+        if (!stagingBuffer->setData(D3D11_MAP_WRITE, reinterpret_cast<const uint8_t *>(data), size, offset))
         {
-            return gl::error(GL_OUT_OF_MEMORY);
+            return gl::Error(GL_OUT_OF_MEMORY, "Failed to set data on internal staging buffer.");
         }
 
-        unsigned char *offsetBufferPointer = reinterpret_cast<unsigned char *>(mappedResource.pData) + offset;
-        memcpy(offsetBufferPointer, data, size);
-
-        context->Unmap(stagingBuffer->getNativeBuffer(), 0);
-
         stagingBuffer->setDataRevision(stagingBuffer->getDataRevision() + 1);
     }
+
+    mSize = std::max(mSize, requiredSize);
+    invalidateStaticData();
+
+    return gl::Error(GL_NO_ERROR);
 }
 
-void Buffer11::copySubData(BufferImpl* source, GLintptr sourceOffset, GLintptr destOffset, GLsizeiptr size)
+gl::Error Buffer11::copySubData(BufferImpl* source, GLintptr sourceOffset, GLintptr destOffset, GLsizeiptr size)
 {
     Buffer11 *sourceBuffer = makeBuffer11(source);
-    if (sourceBuffer)
+    ASSERT(sourceBuffer != NULL);
+
+    BufferStorage11 *copyDest = getLatestBufferStorage();
+    if (!copyDest)
     {
-        BufferStorage11 *dest = getLatestBufferStorage();
-        if (!dest)
-        {
-            dest = getStagingBuffer();
-        }
+        copyDest = getStagingBuffer();
+    }
 
-        BufferStorage11 *source = sourceBuffer->getLatestBufferStorage();
-        if (source && dest)
-        {
-            // If copying to/from a pixel pack buffer, we must have a staging or
-            // pack buffer partner, because other native buffers can't be mapped
-            if (dest->getUsage() == BUFFER_USAGE_PIXEL_PACK && !source->isMappable())
-            {
-                source = sourceBuffer->getStagingBuffer();
-            }
-            else if (source->getUsage() == BUFFER_USAGE_PIXEL_PACK && !dest->isMappable())
-            {
-                dest = getStagingBuffer();
-            }
+    BufferStorage11 *copySource = sourceBuffer->getLatestBufferStorage();
 
-            // D3D11 does not allow overlapped copies until 11.1, and only if the
-            // device supports D3D11_FEATURE_DATA_D3D11_OPTIONS::CopyWithOverlap
-            // Get around this via a different source buffer
-            if (source == dest)
-            {
-                if (source->getUsage() == BUFFER_USAGE_STAGING)
-                {
-                    source = getBufferStorage(BUFFER_USAGE_VERTEX_OR_TRANSFORM_FEEDBACK);
-                }
-                else
-                {
-                    source = getStagingBuffer();
-                }
-            }
+    if (!copySource || !copyDest)
+    {
+        return gl::Error(GL_OUT_OF_MEMORY, "Failed to allocate internal staging buffer.");
+    }
 
-            dest->copyFromStorage(source, sourceOffset, size, destOffset);
-            dest->setDataRevision(dest->getDataRevision() + 1);
-        }
+    // If copying to/from a pixel pack buffer, we must have a staging or
+    // pack buffer partner, because other native buffers can't be mapped
+    if (copyDest->getUsage() == BUFFER_USAGE_PIXEL_PACK && !copySource->isMappable())
+    {
+        copySource = sourceBuffer->getStagingBuffer();
+    }
+    else if (copySource->getUsage() == BUFFER_USAGE_PIXEL_PACK && !copyDest->isMappable())
+    {
+        copyDest = getStagingBuffer();
+    }
 
-        mSize = std::max<size_t>(mSize, destOffset + size);
+    // D3D11 does not allow overlapped copies until 11.1, and only if the
+    // device supports D3D11_FEATURE_DATA_D3D11_OPTIONS::CopyWithOverlap
+    // Get around this via a different source buffer
+    if (copySource == copyDest)
+    {
+        if (copySource->getUsage() == BUFFER_USAGE_STAGING)
+        {
+            copySource = getBufferStorage(BUFFER_USAGE_VERTEX_OR_TRANSFORM_FEEDBACK);
+        }
+        else
+        {
+            copySource = getStagingBuffer();
+        }
     }
 
-    mIndexRangeCache.invalidateRange(destOffset, size);
+    copyDest->copyFromStorage(copySource, sourceOffset, size, destOffset);
+    copyDest->setDataRevision(copyDest->getDataRevision() + 1);
+
+    mSize = std::max<size_t>(mSize, destOffset + size);
     invalidateStaticData();
+
+    return gl::Error(GL_NO_ERROR);
 }
 
-GLvoid *Buffer11::map(size_t offset, size_t length, GLbitfield access)
+gl::Error Buffer11::map(size_t offset, size_t length, GLbitfield access, GLvoid **mapPtr)
 {
     ASSERT(!mMappedStorage);
 
@@ -351,26 +359,31 @@ GLvoid *Buffer11::map(size_t offset, size_t length, GLbitfield access)
 
     if (!mMappedStorage)
     {
-        // Out-of-memory
-        return NULL;
+        return gl::Error(GL_OUT_OF_MEMORY, "Failed to allocate mappable internal buffer.");
     }
 
     if ((access & GL_MAP_WRITE_BIT) > 0)
     {
-        mIndexRangeCache.invalidateRange(offset, length);
-
         // Update the data revision immediately, since the data might be changed at any time
         mMappedStorage->setDataRevision(mMappedStorage->getDataRevision() + 1);
     }
 
-    return mMappedStorage->map(offset, length, access);
+    void *mappedBuffer = mMappedStorage->map(offset, length, access);
+    if (!mappedBuffer)
+    {
+        return gl::Error(GL_OUT_OF_MEMORY, "Failed to map internal buffer.");
+    }
+
+    *mapPtr = mappedBuffer;
+    return gl::Error(GL_NO_ERROR);
 }
 
-void Buffer11::unmap()
+gl::Error Buffer11::unmap()
 {
     ASSERT(mMappedStorage);
     mMappedStorage->unmap();
     mMappedStorage = NULL;
+    return gl::Error(GL_NO_ERROR);
 }
 
 void Buffer11::markTransformFeedbackUsage()
@@ -382,7 +395,6 @@ void Buffer11::markTransformFeedbackUsage()
         transformFeedbackStorage->setDataRevision(transformFeedbackStorage->getDataRevision() + 1);
     }
 
-    mIndexRangeCache.clear();
     invalidateStaticData();
 }
 
@@ -469,7 +481,7 @@ ID3D11ShaderResourceView *Buffer11::getSRV(DXGI_FORMAT srvFormat)
     return bufferSRV;
 }
 
-void Buffer11::packPixels(ID3D11Texture2D *srcTexture, UINT srcSubresource, const PackPixelsParams &params)
+gl::Error Buffer11::packPixels(ID3D11Texture2D *srcTexture, UINT srcSubresource, const PackPixelsParams &params)
 {
     PackStorage11 *packStorage = getPackStorage();
 
@@ -477,11 +489,15 @@ void Buffer11::packPixels(ID3D11Texture2D *srcTexture, UINT srcSubresource, cons
 
     if (packStorage)
     {
-        packStorage->packPixels(srcTexture, srcSubresource, params);
+        gl::Error error = packStorage->packPixels(srcTexture, srcSubresource, params);
+        if (error.isError())
+        {
+            return error;
+        }
         packStorage->setDataRevision(latestStorage ? latestStorage->getDataRevision() + 1 : 1);
     }
 
-    mIndexRangeCache.clear();
+    return gl::Error(GL_NO_ERROR);
 }
 
 Buffer11::BufferStorage11 *Buffer11::getBufferStorage(BufferUsage usage)
@@ -592,6 +608,14 @@ Buffer11::PackStorage11 *Buffer11::getPackStorage()
     return static_cast<PackStorage11*>(packStorage);
 }
 
+bool Buffer11::supportsDirectBinding() const
+{
+    // Do not support direct buffers for dynamic data. The streaming buffer
+    // offers better performance for data which changes every frame.
+    // Check for absence of static buffer interfaces to detect dynamic data.
+    return (mStaticVertexBuffer && mStaticIndexBuffer);
+}
+
 Buffer11::BufferStorage11::BufferStorage11(Renderer11 *renderer, BufferUsage usage)
     : mRenderer(renderer),
       mUsage(usage),
@@ -747,7 +771,7 @@ void Buffer11::NativeBuffer11::fillBufferDesc(D3D11_BUFFER_DESC* bufferDesc, Ren
         // Constant buffers must be of a limited size, and aligned to 16 byte boundaries
         // For our purposes we ignore any buffer data past the maximum constant buffer size
         bufferDesc->ByteWidth = roundUp(bufferDesc->ByteWidth, 16u);
-        bufferDesc->ByteWidth = std::min(bufferDesc->ByteWidth, renderer->getMaxUniformBufferSize());
+        bufferDesc->ByteWidth = std::min<UINT>(bufferDesc->ByteWidth, renderer->getRendererCaps().maxUniformBlockSize);
         break;
 
     default:
@@ -771,6 +795,25 @@ void *Buffer11::NativeBuffer11::map(size_t offset, size_t length, GLbitfield acc
     return static_cast<GLubyte*>(mappedResource.pData) + offset;
 }
 
+bool Buffer11::NativeBuffer11::setData(D3D11_MAP mapMode, const uint8_t *data, size_t size, size_t offset)
+{
+    ID3D11DeviceContext *context = mRenderer->getDeviceContext();
+
+    D3D11_MAPPED_SUBRESOURCE mappedResource;
+    HRESULT result = context->Map(mNativeBuffer, 0, mapMode, 0, &mappedResource);
+    if (FAILED(result))
+    {
+        return gl::error(GL_OUT_OF_MEMORY, false);
+    }
+
+    uint8_t *offsetBufferPointer = reinterpret_cast<uint8_t *>(mappedResource.pData) + offset;
+    memcpy(offsetBufferPointer, data, size);
+
+    context->Unmap(mNativeBuffer, 0);
+
+    return true;
+}
+
 void Buffer11::NativeBuffer11::unmap()
 {
     ASSERT(mUsage == BUFFER_USAGE_STAGING);
@@ -835,7 +878,7 @@ void Buffer11::PackStorage11::unmap()
     // No-op
 }
 
-void Buffer11::PackStorage11::packPixels(ID3D11Texture2D *srcTexure, UINT srcSubresource, const PackPixelsParams &params)
+gl::Error Buffer11::PackStorage11::packPixels(ID3D11Texture2D *srcTexure, UINT srcSubresource, const PackPixelsParams &params)
 {
     flushQueuedPackCommand();
     mQueuedPackCommand = new PackPixelsParams(params);
@@ -877,7 +920,11 @@ void Buffer11::PackStorage11::packPixels(ID3D11Texture2D *srcTexure, UINT srcSub
         stagingDesc.MiscFlags = 0;
 
         hr = device->CreateTexture2D(&stagingDesc, NULL, &mStagingTexture);
-        ASSERT(SUCCEEDED(hr));
+        if (FAILED(hr))
+        {
+            ASSERT(hr == E_OUTOFMEMORY);
+            return gl::Error(GL_OUT_OF_MEMORY, "Failed to allocate internal staging texture.");
+        }
     }
 
     // ReadPixels from multisampled FBOs isn't supported in current GL
@@ -894,6 +941,8 @@ void Buffer11::PackStorage11::packPixels(ID3D11Texture2D *srcTexure, UINT srcSub
 
     // Asynchronous copy
     immediateContext->CopySubresourceRegion(mStagingTexture, 0, 0, 0, 0, srcTexure, srcSubresource, &srcBox);
+
+    return gl::Error(GL_NO_ERROR);
 }
 
 void Buffer11::PackStorage11::flushQueuedPackCommand()