Upstream version 10.39.225.0
[platform/framework/web/crosswalk.git] / src / third_party / angle / src / libGLESv2 / renderer / d3d / d3d9 / VertexBuffer9.cpp
1 //
2 // Copyright (c) 2002-2012 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 // VertexBuffer9.cpp: Defines the D3D9 VertexBuffer implementation.
8
9 #include "libGLESv2/renderer/d3d/d3d9/VertexBuffer9.h"
10 #include "libGLESv2/renderer/d3d/d3d9/Renderer9.h"
11 #include "libGLESv2/renderer/d3d/d3d9/formatutils9.h"
12 #include "libGLESv2/renderer/vertexconversion.h"
13 #include "libGLESv2/renderer/BufferImpl.h"
14 #include "libGLESv2/VertexAttribute.h"
15 #include "libGLESv2/Buffer.h"
16
17 namespace rx
18 {
19
20 VertexBuffer9::VertexBuffer9(rx::Renderer9 *renderer) : mRenderer(renderer)
21 {
22     mVertexBuffer = NULL;
23     mBufferSize = 0;
24     mDynamicUsage = false;
25 }
26
27 VertexBuffer9::~VertexBuffer9()
28 {
29     SafeRelease(mVertexBuffer);
30 }
31
32 gl::Error VertexBuffer9::initialize(unsigned int size, bool dynamicUsage)
33 {
34     SafeRelease(mVertexBuffer);
35
36     updateSerial();
37
38     if (size > 0)
39     {
40         DWORD flags = D3DUSAGE_WRITEONLY;
41         if (dynamicUsage)
42         {
43             flags |= D3DUSAGE_DYNAMIC;
44         }
45
46         HRESULT result = mRenderer->createVertexBuffer(size, flags, &mVertexBuffer);
47
48         if (FAILED(result))
49         {
50             return gl::Error(GL_OUT_OF_MEMORY, "Failed to allocate internal vertex buffer of size, %lu.", size);
51         }
52     }
53
54     mBufferSize = size;
55     mDynamicUsage = dynamicUsage;
56     return gl::Error(GL_NO_ERROR);
57 }
58
59 VertexBuffer9 *VertexBuffer9::makeVertexBuffer9(VertexBuffer *vertexBuffer)
60 {
61     ASSERT(HAS_DYNAMIC_TYPE(VertexBuffer9*, vertexBuffer));
62     return static_cast<VertexBuffer9*>(vertexBuffer);
63 }
64
65 gl::Error VertexBuffer9::storeVertexAttributes(const gl::VertexAttribute &attrib, const gl::VertexAttribCurrentValueData &currentValue,
66                                                GLint start, GLsizei count, GLsizei instances, unsigned int offset)
67 {
68     if (!mVertexBuffer)
69     {
70         return gl::Error(GL_OUT_OF_MEMORY, "Internal vertex buffer is not initialized.");
71     }
72
73     gl::Buffer *buffer = attrib.buffer.get();
74
75     int inputStride = gl::ComputeVertexAttributeStride(attrib);
76     int elementSize = gl::ComputeVertexAttributeTypeSize(attrib);
77
78     DWORD lockFlags = mDynamicUsage ? D3DLOCK_NOOVERWRITE : 0;
79
80     uint8_t *mapPtr = NULL;
81
82     unsigned int mapSize;
83     gl::Error error = spaceRequired(attrib, count, instances, &mapSize);
84     if (error.isError())
85     {
86         return error;
87     }
88
89     HRESULT result = mVertexBuffer->Lock(offset, mapSize, reinterpret_cast<void**>(&mapPtr), lockFlags);
90     if (FAILED(result))
91     {
92         return gl::Error(GL_OUT_OF_MEMORY, "Failed to lock internal vertex buffer, HRESULT: 0x%08x.", result);
93     }
94
95     const uint8_t *input = NULL;
96     if (attrib.enabled)
97     {
98         if (buffer)
99         {
100             BufferImpl *storage = buffer->getImplementation();
101             input = static_cast<const uint8_t*>(storage->getData()) + static_cast<int>(attrib.offset);
102         }
103         else
104         {
105             input = static_cast<const uint8_t*>(attrib.pointer);
106         }
107     }
108     else
109     {
110         input = reinterpret_cast<const uint8_t*>(currentValue.FloatValues);
111     }
112
113     if (instances == 0 || attrib.divisor == 0)
114     {
115         input += inputStride * start;
116     }
117
118     gl::VertexFormat vertexFormat(attrib, currentValue.Type);
119     const d3d9::VertexFormat &d3dVertexInfo = d3d9::GetVertexFormatInfo(mRenderer->getCapsDeclTypes(), vertexFormat);
120     bool needsConversion = (d3dVertexInfo.conversionType & VERTEX_CONVERT_CPU) > 0;
121
122     if (!needsConversion && inputStride == elementSize)
123     {
124         size_t copySize = static_cast<size_t>(count) * static_cast<size_t>(inputStride);
125         memcpy(mapPtr, input, copySize);
126     }
127     else
128     {
129         d3dVertexInfo.copyFunction(input, inputStride, count, mapPtr);
130     }
131
132     mVertexBuffer->Unlock();
133
134     return gl::Error(GL_NO_ERROR);
135 }
136
137 gl::Error VertexBuffer9::getSpaceRequired(const gl::VertexAttribute &attrib, GLsizei count, GLsizei instances,
138                                           unsigned int *outSpaceRequired) const
139 {
140     return spaceRequired(attrib, count, instances, outSpaceRequired);
141 }
142
143 unsigned int VertexBuffer9::getBufferSize() const
144 {
145     return mBufferSize;
146 }
147
148 gl::Error VertexBuffer9::setBufferSize(unsigned int size)
149 {
150     if (size > mBufferSize)
151     {
152         return initialize(size, mDynamicUsage);
153     }
154     else
155     {
156         return gl::Error(GL_NO_ERROR);
157     }
158 }
159
160 gl::Error VertexBuffer9::discard()
161 {
162     if (!mVertexBuffer)
163     {
164         return gl::Error(GL_OUT_OF_MEMORY, "Internal vertex buffer is not initialized.");
165     }
166
167     void *dummy;
168     HRESULT result;
169
170     result = mVertexBuffer->Lock(0, 1, &dummy, D3DLOCK_DISCARD);
171     if (FAILED(result))
172     {
173         return gl::Error(GL_OUT_OF_MEMORY, "Failed to lock internal buffer for discarding, HRESULT: 0x%08x", result);
174     }
175
176     result = mVertexBuffer->Unlock();
177     if (FAILED(result))
178     {
179         return gl::Error(GL_OUT_OF_MEMORY, "Failed to unlock internal buffer for discarding, HRESULT: 0x%08x", result);
180     }
181
182     return gl::Error(GL_NO_ERROR);
183 }
184
185 IDirect3DVertexBuffer9 * VertexBuffer9::getBuffer() const
186 {
187     return mVertexBuffer;
188 }
189
190 gl::Error VertexBuffer9::spaceRequired(const gl::VertexAttribute &attrib, std::size_t count, GLsizei instances,
191                                        unsigned int *outSpaceRequired) const
192 {
193     gl::VertexFormat vertexFormat(attrib, GL_FLOAT);
194     const d3d9::VertexFormat &d3d9VertexInfo = d3d9::GetVertexFormatInfo(mRenderer->getCapsDeclTypes(), vertexFormat);
195
196     if (attrib.enabled)
197     {
198         unsigned int elementCount = 0;
199         if (instances == 0 || attrib.divisor == 0)
200         {
201             elementCount = count;
202         }
203         else
204         {
205             // Round up to divisor, if possible
206             elementCount = rx::UnsignedCeilDivide(static_cast<unsigned int>(instances), attrib.divisor);
207         }
208
209         if (d3d9VertexInfo.outputElementSize <= std::numeric_limits<unsigned int>::max() / elementCount)
210         {
211             if (outSpaceRequired)
212             {
213                 *outSpaceRequired = d3d9VertexInfo.outputElementSize * elementCount;
214             }
215             return gl::Error(GL_NO_ERROR);
216         }
217         else
218         {
219             return gl::Error(GL_OUT_OF_MEMORY, "New vertex buffer size would result in an overflow.");
220         }
221     }
222     else
223     {
224         const unsigned int elementSize = 4;
225         if (outSpaceRequired)
226         {
227             *outSpaceRequired = elementSize * 4;
228         }
229         return gl::Error(GL_NO_ERROR);
230     }
231 }
232
233 }