Update To 11.40.268.0
[platform/framework/web/crosswalk.git] / src / third_party / angle / src / libGLESv2 / renderer / d3d / VertexDataManager.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 // VertexDataManager.h: Defines the VertexDataManager, a class that
8 // runs the Buffer translation process.
9
10 #include "libGLESv2/renderer/d3d/VertexDataManager.h"
11 #include "libGLESv2/renderer/d3d/BufferD3D.h"
12 #include "libGLESv2/renderer/d3d/VertexBuffer.h"
13 #include "libGLESv2/renderer/Renderer.h"
14 #include "libGLESv2/Buffer.h"
15 #include "libGLESv2/ProgramBinary.h"
16 #include "libGLESv2/VertexAttribute.h"
17 #include "libGLESv2/State.h"
18
19 namespace
20 {
21     enum { INITIAL_STREAM_BUFFER_SIZE = 1024*1024 };
22     // This has to be at least 4k or else it fails on ATI cards.
23     enum { CONSTANT_VERTEX_BUFFER_SIZE = 4096 };
24 }
25
26 namespace rx
27 {
28
29 static int ElementsInBuffer(const gl::VertexAttribute &attrib, unsigned int size)
30 {
31     // Size cannot be larger than a GLsizei
32     if (size > static_cast<unsigned int>(std::numeric_limits<int>::max()))
33     {
34         size = static_cast<unsigned int>(std::numeric_limits<int>::max());
35     }
36
37     GLsizei stride = ComputeVertexAttributeStride(attrib);
38     return (size - attrib.offset % stride + (stride - ComputeVertexAttributeTypeSize(attrib))) / stride;
39 }
40
41 static int StreamingBufferElementCount(const gl::VertexAttribute &attrib, int vertexDrawCount, int instanceDrawCount)
42 {
43     // For instanced rendering, we draw "instanceDrawCount" sets of "vertexDrawCount" vertices.
44     //
45     // A vertex attribute with a positive divisor loads one instanced vertex for every set of
46     // non-instanced vertices, and the instanced vertex index advances once every "mDivisor" instances.
47     if (instanceDrawCount > 0 && attrib.divisor > 0)
48     {
49         return instanceDrawCount / attrib.divisor;
50     }
51
52     return vertexDrawCount;
53 }
54
55 VertexDataManager::VertexDataManager(Renderer *renderer) : mRenderer(renderer)
56 {
57     for (int i = 0; i < gl::MAX_VERTEX_ATTRIBS; i++)
58     {
59         mCurrentValue[i].FloatValues[0] = std::numeric_limits<float>::quiet_NaN();
60         mCurrentValue[i].FloatValues[1] = std::numeric_limits<float>::quiet_NaN();
61         mCurrentValue[i].FloatValues[2] = std::numeric_limits<float>::quiet_NaN();
62         mCurrentValue[i].FloatValues[3] = std::numeric_limits<float>::quiet_NaN();
63         mCurrentValue[i].Type = GL_FLOAT;
64         mCurrentValueBuffer[i] = NULL;
65         mCurrentValueOffsets[i] = 0;
66     }
67
68     mStreamingBuffer = new StreamingVertexBufferInterface(renderer, INITIAL_STREAM_BUFFER_SIZE);
69
70     if (!mStreamingBuffer)
71     {
72         ERR("Failed to allocate the streaming vertex buffer.");
73     }
74 }
75
76 VertexDataManager::~VertexDataManager()
77 {
78     delete mStreamingBuffer;
79
80     for (int i = 0; i < gl::MAX_VERTEX_ATTRIBS; i++)
81     {
82         delete mCurrentValueBuffer[i];
83     }
84 }
85
86 gl::Error VertexDataManager::prepareVertexData(const gl::State &state, GLint start, GLsizei count,
87                                                TranslatedAttribute *translated, GLsizei instances)
88 {
89     if (!mStreamingBuffer)
90     {
91         return gl::Error(GL_OUT_OF_MEMORY, "Internal streaming vertex buffer is unexpectedly NULL.");
92     }
93
94     // Invalidate static buffers that don't contain matching attributes
95     for (int attributeIndex = 0; attributeIndex < gl::MAX_VERTEX_ATTRIBS; attributeIndex++)
96     {
97         translated[attributeIndex].active = (state.getCurrentProgramBinary()->getSemanticIndex(attributeIndex) != -1);
98         const gl::VertexAttribute &curAttrib = state.getVertexAttribState(attributeIndex);
99
100         if (translated[attributeIndex].active && curAttrib.enabled)
101         {
102             invalidateMatchingStaticData(curAttrib, state.getVertexAttribCurrentValue(attributeIndex));
103         }
104     }
105
106     // Reserve the required space in the buffers
107     for (int i = 0; i < gl::MAX_VERTEX_ATTRIBS; i++)
108     {
109         const gl::VertexAttribute &curAttrib = state.getVertexAttribState(i);
110         if (translated[i].active && curAttrib.enabled)
111         {
112             gl::Error error = reserveSpaceForAttrib(curAttrib, state.getVertexAttribCurrentValue(i), count, instances);
113             if (error.isError())
114             {
115                 return error;
116             }
117         }
118     }
119
120     // Perform the vertex data translations
121     for (int i = 0; i < gl::MAX_VERTEX_ATTRIBS; i++)
122     {
123         const gl::VertexAttribute &curAttrib = state.getVertexAttribState(i);
124         if (translated[i].active)
125         {
126             if (curAttrib.enabled)
127             {
128                 gl::Error error = storeAttribute(curAttrib, state.getVertexAttribCurrentValue(i),
129                                                  &translated[i], start, count, instances);
130
131                 if (error.isError())
132                 {
133                     return error;
134                 }
135             }
136             else
137             {
138                 if (!mCurrentValueBuffer[i])
139                 {
140                     mCurrentValueBuffer[i] = new StreamingVertexBufferInterface(mRenderer, CONSTANT_VERTEX_BUFFER_SIZE);
141                 }
142
143                 gl::Error error = storeCurrentValue(curAttrib, state.getVertexAttribCurrentValue(i), &translated[i],
144                                                     &mCurrentValue[i], &mCurrentValueOffsets[i],
145                                                     mCurrentValueBuffer[i]);
146                 if (error.isError())
147                 {
148                     return error;
149                 }
150             }
151         }
152     }
153
154     for (int i = 0; i < gl::MAX_VERTEX_ATTRIBS; i++)
155     {
156         const gl::VertexAttribute &curAttrib = state.getVertexAttribState(i);
157         if (translated[i].active && curAttrib.enabled)
158         {
159             gl::Buffer *buffer = curAttrib.buffer.get();
160
161             if (buffer)
162             {
163                 BufferD3D *bufferImpl = BufferD3D::makeBufferD3D(buffer->getImplementation());
164                 bufferImpl->promoteStaticUsage(count * ComputeVertexAttributeTypeSize(curAttrib));
165             }
166         }
167     }
168
169     return gl::Error(GL_NO_ERROR);
170 }
171
172 void VertexDataManager::invalidateMatchingStaticData(const gl::VertexAttribute &attrib,
173                                                      const gl::VertexAttribCurrentValueData &currentValue) const
174 {
175     gl::Buffer *buffer = attrib.buffer.get();
176
177     if (buffer)
178     {
179         BufferD3D *bufferImpl = BufferD3D::makeBufferD3D(buffer->getImplementation());
180         StaticVertexBufferInterface *staticBuffer = bufferImpl->getStaticVertexBuffer();
181
182         if (staticBuffer &&
183             staticBuffer->getBufferSize() > 0 &&
184             !staticBuffer->lookupAttribute(attrib, NULL) &&
185             !staticBuffer->directStoragePossible(attrib, currentValue))
186         {
187             bufferImpl->invalidateStaticData();
188         }
189     }
190 }
191
192 gl::Error VertexDataManager::reserveSpaceForAttrib(const gl::VertexAttribute &attrib,
193                                                    const gl::VertexAttribCurrentValueData &currentValue,
194                                                    GLsizei count,
195                                                    GLsizei instances) const
196 {
197     gl::Buffer *buffer = attrib.buffer.get();
198     BufferD3D *bufferImpl = buffer ? BufferD3D::makeBufferD3D(buffer->getImplementation()) : NULL;
199     StaticVertexBufferInterface *staticBuffer = bufferImpl ? bufferImpl->getStaticVertexBuffer() : NULL;
200     VertexBufferInterface *vertexBuffer = staticBuffer ? staticBuffer : static_cast<VertexBufferInterface*>(mStreamingBuffer);
201
202     if (!vertexBuffer->directStoragePossible(attrib, currentValue))
203     {
204         if (staticBuffer)
205         {
206             if (staticBuffer->getBufferSize() == 0)
207             {
208                 int totalCount = ElementsInBuffer(attrib, bufferImpl->getSize());
209                 gl::Error error = staticBuffer->reserveVertexSpace(attrib, totalCount, 0);
210                 if (error.isError())
211                 {
212                     return error;
213                 }
214             }
215         }
216         else
217         {
218             int totalCount = StreamingBufferElementCount(attrib, count, instances);
219             ASSERT(!bufferImpl || ElementsInBuffer(attrib, bufferImpl->getSize()) >= totalCount);
220
221             gl::Error error = mStreamingBuffer->reserveVertexSpace(attrib, totalCount, instances);
222             if (error.isError())
223             {
224                 return error;
225             }
226         }
227     }
228
229     return gl::Error(GL_NO_ERROR);
230 }
231
232 gl::Error VertexDataManager::storeAttribute(const gl::VertexAttribute &attrib,
233                                             const gl::VertexAttribCurrentValueData &currentValue,
234                                             TranslatedAttribute *translated,
235                                             GLint start,
236                                             GLsizei count,
237                                             GLsizei instances)
238 {
239     gl::Buffer *buffer = attrib.buffer.get();
240     ASSERT(buffer || attrib.pointer);
241
242     BufferD3D *storage = buffer ? BufferD3D::makeBufferD3D(buffer->getImplementation()) : NULL;
243     StaticVertexBufferInterface *staticBuffer = storage ? storage->getStaticVertexBuffer() : NULL;
244     VertexBufferInterface *vertexBuffer = staticBuffer ? staticBuffer : static_cast<VertexBufferInterface*>(mStreamingBuffer);
245     bool directStorage = vertexBuffer->directStoragePossible(attrib, currentValue);
246
247     unsigned int streamOffset = 0;
248     unsigned int outputElementSize = 0;
249
250     if (directStorage)
251     {
252         outputElementSize = ComputeVertexAttributeStride(attrib);
253         streamOffset = attrib.offset + outputElementSize * start;
254     }
255     else if (staticBuffer)
256     {
257         gl::Error error = staticBuffer->getVertexBuffer()->getSpaceRequired(attrib, 1, 0, &outputElementSize);
258         if (error.isError())
259         {
260             return error;
261         }
262
263         if (!staticBuffer->lookupAttribute(attrib, &streamOffset))
264         {
265             // Convert the entire buffer
266             int totalCount = ElementsInBuffer(attrib, storage->getSize());
267             int startIndex = attrib.offset / ComputeVertexAttributeStride(attrib);
268
269             gl::Error error = staticBuffer->storeVertexAttributes(attrib, currentValue, -startIndex, totalCount,
270                                                                   0, &streamOffset);
271             if (error.isError())
272             {
273                 return error;
274             }
275         }
276
277         unsigned int firstElementOffset = (attrib.offset / ComputeVertexAttributeStride(attrib)) * outputElementSize;
278         unsigned int startOffset = (instances == 0 || attrib.divisor == 0) ? start * outputElementSize : 0;
279         if (streamOffset + firstElementOffset + startOffset < streamOffset)
280         {
281             return gl::Error(GL_OUT_OF_MEMORY);
282         }
283
284         streamOffset += firstElementOffset + startOffset;
285     }
286     else
287     {
288         int totalCount = StreamingBufferElementCount(attrib, count, instances);
289         gl::Error error = mStreamingBuffer->getVertexBuffer()->getSpaceRequired(attrib, 1, 0, &outputElementSize);
290         if (error.isError())
291         {
292             return error;
293         }
294
295         error = mStreamingBuffer->storeVertexAttributes(attrib, currentValue, start, totalCount, instances, &streamOffset);
296         if (error.isError())
297         {
298             return error;
299         }
300     }
301
302     translated->storage = directStorage ? storage : NULL;
303     translated->vertexBuffer = vertexBuffer->getVertexBuffer();
304     translated->serial = directStorage ? storage->getSerial() : vertexBuffer->getSerial();
305     translated->divisor = attrib.divisor;
306
307     translated->attribute = &attrib;
308     translated->currentValueType = currentValue.Type;
309     translated->stride = outputElementSize;
310     translated->offset = streamOffset;
311
312     return gl::Error(GL_NO_ERROR);
313 }
314
315 gl::Error VertexDataManager::storeCurrentValue(const gl::VertexAttribute &attrib,
316                                                const gl::VertexAttribCurrentValueData &currentValue,
317                                                TranslatedAttribute *translated,
318                                                gl::VertexAttribCurrentValueData *cachedValue,
319                                                size_t *cachedOffset,
320                                                StreamingVertexBufferInterface *buffer)
321 {
322     if (*cachedValue != currentValue)
323     {
324         gl::Error error = buffer->reserveVertexSpace(attrib, 1, 0);
325         if (error.isError())
326         {
327             return error;
328         }
329
330         unsigned int streamOffset;
331         error = buffer->storeVertexAttributes(attrib, currentValue, 0, 1, 0, &streamOffset);
332         if (error.isError())
333         {
334             return error;
335         }
336
337         *cachedValue = currentValue;
338         *cachedOffset = streamOffset;
339     }
340
341     translated->storage = NULL;
342     translated->vertexBuffer = buffer->getVertexBuffer();
343     translated->serial = buffer->getSerial();
344     translated->divisor = 0;
345
346     translated->attribute = &attrib;
347     translated->currentValueType = currentValue.Type;
348     translated->stride = 0;
349     translated->offset = *cachedOffset;
350
351     return gl::Error(GL_NO_ERROR);
352 }
353
354 }