Update To 11.40.268.0
[platform/framework/web/crosswalk.git] / src / third_party / angle / src / libGLESv2 / renderer / d3d / d3d11 / VertexBuffer11.cpp
1 //
2 // Copyright (c) 2013 The ANGLE Project Authors. All rights reserved.
3 // Use of this source code is governed by a BSD-style license that can be
4 // found in the LICENSE file.
5 //
6
7 // VertexBuffer11.cpp: Defines the D3D11 VertexBuffer implementation.
8
9 #include "libGLESv2/renderer/d3d/d3d11/VertexBuffer11.h"
10 #include "libGLESv2/renderer/d3d/d3d11/Buffer11.h"
11 #include "libGLESv2/renderer/d3d/d3d11/Renderer11.h"
12 #include "libGLESv2/renderer/d3d/d3d11/formatutils11.h"
13 #include "libGLESv2/Buffer.h"
14 #include "libGLESv2/VertexAttribute.h"
15
16 namespace rx
17 {
18
19 VertexBuffer11::VertexBuffer11(rx::Renderer11 *const renderer) : mRenderer(renderer)
20 {
21     mBuffer = NULL;
22     mBufferSize = 0;
23     mDynamicUsage = false;
24 }
25
26 VertexBuffer11::~VertexBuffer11()
27 {
28     SafeRelease(mBuffer);
29 }
30
31 gl::Error VertexBuffer11::initialize(unsigned int size, bool dynamicUsage)
32 {
33     SafeRelease(mBuffer);
34
35     updateSerial();
36
37     if (size > 0)
38     {
39         ID3D11Device* dxDevice = mRenderer->getDevice();
40
41         D3D11_BUFFER_DESC bufferDesc;
42         bufferDesc.ByteWidth = size;
43         bufferDesc.Usage = D3D11_USAGE_DYNAMIC;
44         bufferDesc.BindFlags = D3D11_BIND_VERTEX_BUFFER;
45         bufferDesc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE;
46         bufferDesc.MiscFlags = 0;
47         bufferDesc.StructureByteStride = 0;
48
49         HRESULT result = dxDevice->CreateBuffer(&bufferDesc, NULL, &mBuffer);
50         if (FAILED(result))
51         {
52             return gl::Error(GL_OUT_OF_MEMORY, "Failed to allocate internal vertex buffer of size, %lu.", size);
53         }
54     }
55
56     mBufferSize = size;
57     mDynamicUsage = dynamicUsage;
58
59     return gl::Error(GL_NO_ERROR);
60 }
61
62 VertexBuffer11 *VertexBuffer11::makeVertexBuffer11(VertexBuffer *vetexBuffer)
63 {
64     ASSERT(HAS_DYNAMIC_TYPE(VertexBuffer11*, vetexBuffer));
65     return static_cast<VertexBuffer11*>(vetexBuffer);
66 }
67
68 gl::Error VertexBuffer11::storeVertexAttributes(const gl::VertexAttribute &attrib, const gl::VertexAttribCurrentValueData &currentValue,
69                                                 GLint start, GLsizei count, GLsizei instances, unsigned int offset)
70 {
71     if (!mBuffer)
72     {
73         return gl::Error(GL_OUT_OF_MEMORY, "Internal vertex buffer is not initialized.");
74     }
75
76     gl::Buffer *buffer = attrib.buffer.get();
77     int inputStride = ComputeVertexAttributeStride(attrib);
78     ID3D11DeviceContext *dxContext = mRenderer->getDeviceContext();
79
80     D3D11_MAPPED_SUBRESOURCE mappedResource;
81     HRESULT result = dxContext->Map(mBuffer, 0, D3D11_MAP_WRITE_NO_OVERWRITE, 0, &mappedResource);
82     if (FAILED(result))
83     {
84         return gl::Error(GL_OUT_OF_MEMORY, "Failed to map internal vertex buffer, HRESULT: 0x%08x.", result);
85     }
86
87     uint8_t *output = reinterpret_cast<uint8_t*>(mappedResource.pData) + offset;
88
89     const uint8_t *input = NULL;
90     if (attrib.enabled)
91     {
92         if (buffer)
93         {
94             BufferD3D *storage = BufferD3D::makeFromBuffer(buffer);
95             gl::Error error = storage->getData(&input);
96             if (error.isError())
97             {
98                 return error;
99             }
100             input += static_cast<int>(attrib.offset);
101         }
102         else
103         {
104             input = static_cast<const uint8_t*>(attrib.pointer);
105         }
106     }
107     else
108     {
109         input = reinterpret_cast<const uint8_t*>(currentValue.FloatValues);
110     }
111
112     if (instances == 0 || attrib.divisor == 0)
113     {
114         input += inputStride * start;
115     }
116
117     gl::VertexFormat vertexFormat(attrib, currentValue.Type);
118     const d3d11::VertexFormat &vertexFormatInfo = d3d11::GetVertexFormatInfo(vertexFormat);
119     ASSERT(vertexFormatInfo.copyFunction != NULL);
120     vertexFormatInfo.copyFunction(input, inputStride, count, output);
121
122     dxContext->Unmap(mBuffer, 0);
123
124     return gl::Error(GL_NO_ERROR);
125 }
126
127 gl::Error VertexBuffer11::getSpaceRequired(const gl::VertexAttribute &attrib, GLsizei count,
128                                            GLsizei instances, unsigned int *outSpaceRequired) const
129 {
130     unsigned int elementCount = 0;
131     if (attrib.enabled)
132     {
133         if (instances == 0 || attrib.divisor == 0)
134         {
135             elementCount = count;
136         }
137         else
138         {
139             // Round up to divisor, if possible
140             elementCount = rx::UnsignedCeilDivide(static_cast<unsigned int>(instances), attrib.divisor);
141         }
142
143         gl::VertexFormat vertexFormat(attrib);
144         const d3d11::VertexFormat &vertexFormatInfo = d3d11::GetVertexFormatInfo(vertexFormat);
145         const d3d11::DXGIFormat &dxgiFormatInfo = d3d11::GetDXGIFormatInfo(vertexFormatInfo.nativeFormat);
146         unsigned int elementSize = dxgiFormatInfo.pixelBytes;
147         if (elementSize <= std::numeric_limits<unsigned int>::max() / elementCount)
148         {
149             if (outSpaceRequired)
150             {
151                 *outSpaceRequired = elementSize * elementCount;
152             }
153             return gl::Error(GL_NO_ERROR);
154         }
155         else
156         {
157             return gl::Error(GL_OUT_OF_MEMORY, "New vertex buffer size would result in an overflow.");
158         }
159     }
160     else
161     {
162         const unsigned int elementSize = 4;
163         if (outSpaceRequired)
164         {
165             *outSpaceRequired = elementSize * 4;
166         }
167         return gl::Error(GL_NO_ERROR);
168     }
169 }
170
171 unsigned int VertexBuffer11::getBufferSize() const
172 {
173     return mBufferSize;
174 }
175
176 gl::Error VertexBuffer11::setBufferSize(unsigned int size)
177 {
178     if (size > mBufferSize)
179     {
180         return initialize(size, mDynamicUsage);
181     }
182     else
183     {
184         return gl::Error(GL_NO_ERROR);
185     }
186 }
187
188 gl::Error VertexBuffer11::discard()
189 {
190     if (!mBuffer)
191     {
192         return gl::Error(GL_OUT_OF_MEMORY, "Internal vertex buffer is not initialized.");
193     }
194
195     ID3D11DeviceContext *dxContext = mRenderer->getDeviceContext();
196
197     D3D11_MAPPED_SUBRESOURCE mappedResource;
198     HRESULT result = dxContext->Map(mBuffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &mappedResource);
199     if (FAILED(result))
200     {
201         return gl::Error(GL_OUT_OF_MEMORY, "Failed to map internal buffer for discarding, HRESULT: 0x%08x", result);
202     }
203
204     dxContext->Unmap(mBuffer, 0);
205
206     return gl::Error(GL_NO_ERROR);
207 }
208
209 ID3D11Buffer *VertexBuffer11::getBuffer() const
210 {
211     return mBuffer;
212 }
213
214 }