Move ANGLE to Sources/ThirdParty
[WebKit.git] / Sources / ThirdParty / ANGLE / src / libGLESv2 / geometry / VertexDataManager.cpp
1 //
2 // Copyright (c) 2002-2010 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 // geometry/VertexDataManager.h: Defines the VertexDataManager, a class that
8 // runs the Buffer translation process.
9
10 #include "libGLESv2/geometry/VertexDataManager.h"
11
12 #include <limits>
13
14 #include "common/debug.h"
15
16 #include "libGLESv2/Buffer.h"
17 #include "libGLESv2/Program.h"
18
19 #include "libGLESv2/geometry/backend.h"
20 #include "libGLESv2/geometry/IndexDataManager.h"
21
22 namespace
23 {
24     enum { INITIAL_STREAM_BUFFER_SIZE = 1024*1024 };
25 }
26
27 namespace gl
28 {
29
30 VertexDataManager::VertexDataManager(Context *context, BufferBackEnd *backend)
31     : mContext(context), mBackend(backend), mDirtyCurrentValues(true), mCurrentValueOffset(0)
32 {
33     mStreamBuffer = mBackend->createVertexBuffer(INITIAL_STREAM_BUFFER_SIZE);
34     try
35     {
36         mCurrentValueBuffer = mBackend->createVertexBufferForStrideZero(4 * sizeof(float) * MAX_VERTEX_ATTRIBS);
37     }
38     catch (...)
39     {
40         delete mStreamBuffer;
41         throw;
42     }
43 }
44
45 VertexDataManager::~VertexDataManager()
46 {
47     delete mStreamBuffer;
48     delete mCurrentValueBuffer;
49 }
50
51 std::bitset<MAX_VERTEX_ATTRIBS> VertexDataManager::getActiveAttribs() const
52 {
53     std::bitset<MAX_VERTEX_ATTRIBS> active;
54
55     Program *program = mContext->getCurrentProgram();
56
57     for (int attributeIndex = 0; attributeIndex < MAX_VERTEX_ATTRIBS; attributeIndex++)
58     {
59         active[attributeIndex] = (program->getSemanticIndex(attributeIndex) != -1);
60     }
61
62     return active;
63 }
64
65 GLenum VertexDataManager::preRenderValidate(GLint start, GLsizei count,
66                                             TranslatedAttribute *translated)
67 {
68     const AttributeState *attribs = mContext->getVertexAttribBlock();
69     const std::bitset<MAX_VERTEX_ATTRIBS> activeAttribs = getActiveAttribs();
70
71     for (int i = 0; i < MAX_VERTEX_ATTRIBS; i++)
72     {
73         if (!activeAttribs[i] && attribs[i].mEnabled && attribs[i].mBoundBuffer != 0 && !mContext->getBuffer(attribs[i].mBoundBuffer))
74             return GL_INVALID_OPERATION;
75     }
76
77     for (int i = 0; i < MAX_VERTEX_ATTRIBS; i++)
78     {
79         translated[i].enabled = activeAttribs[i];
80     }
81
82     bool usesCurrentValues = false;
83
84     for (int i = 0; i < MAX_VERTEX_ATTRIBS; i++)
85     {
86         if (activeAttribs[i] && !attribs[i].mEnabled)
87         {
88             usesCurrentValues = true;
89             break;
90         }
91     }
92
93     // Handle the identity-mapped attributes.
94     // Process array attributes.
95
96     std::size_t requiredSpace = 0;
97
98     for (int i = 0; i < MAX_VERTEX_ATTRIBS; i++)
99     {
100         if (activeAttribs[i] && attribs[i].mEnabled)
101         {
102             requiredSpace += spaceRequired(attribs[i], count);
103         }
104     }
105
106     if (requiredSpace > mStreamBuffer->size())
107     {
108         std::size_t newSize = std::max(requiredSpace, 3 * mStreamBuffer->size() / 2); // 1.5 x mStreamBuffer->size() is arbitrary and should be checked to see we don't have too many reallocations.
109
110         TranslatedVertexBuffer *newStreamBuffer = mBackend->createVertexBuffer(newSize);
111
112         delete mStreamBuffer;
113         mStreamBuffer = newStreamBuffer;
114     }
115
116     mStreamBuffer->reserveSpace(requiredSpace);
117
118     for (size_t i = 0; i < MAX_VERTEX_ATTRIBS; i++)
119     {
120         if (activeAttribs[i] && attribs[i].mEnabled)
121         {
122             FormatConverter formatConverter = mBackend->getFormatConverter(attribs[i].mType, attribs[i].mSize, attribs[i].mNormalized);
123
124             translated[i].nonArray = false;
125             translated[i].type = attribs[i].mType;
126             translated[i].size = attribs[i].mSize;
127             translated[i].normalized = attribs[i].mNormalized;
128             translated[i].stride = formatConverter.outputVertexSize;
129             translated[i].buffer = mStreamBuffer;
130
131             size_t inputStride = interpretGlStride(attribs[i]);
132             size_t elementSize = typeSize(attribs[i].mType) * attribs[i].mSize;
133
134             void *output = mStreamBuffer->map(spaceRequired(attribs[i], count), &translated[i].offset);
135
136             const void *input;
137             if (attribs[i].mBoundBuffer)
138             {
139                 Buffer *buffer = mContext->getBuffer(attribs[i].mBoundBuffer);
140
141                 size_t offset = reinterpret_cast<size_t>(attribs[i].mPointer);
142
143                 // Before we calculate the required size below, make sure it can be computed without integer overflow.
144                 if (std::numeric_limits<std::size_t>::max() - start < static_cast<std::size_t>(count)
145                     || std::numeric_limits<std::size_t>::max() / inputStride < static_cast<std::size_t>(start + count - 1) // it's a prerequisite that count >= 1, so start+count-1 >= 0.
146                     || std::numeric_limits<std::size_t>::max() - offset < inputStride * (start + count - 1)
147                     || std::numeric_limits<std::size_t>::max() - elementSize < offset + inputStride * (start + count - 1) + elementSize)
148                 {
149                     mStreamBuffer->unmap();
150                     return GL_INVALID_OPERATION;
151                 }
152
153                 if (offset + inputStride * (start + count - 1) + elementSize > buffer->size())
154                 {
155                     mStreamBuffer->unmap();
156                     return GL_INVALID_OPERATION;
157                 }
158
159                 input = static_cast<const char*>(buffer->data()) + offset;
160             }
161             else
162             {
163                 input = attribs[i].mPointer;
164             }
165
166             input = static_cast<const char*>(input) + inputStride * start;
167
168             if (formatConverter.identity && inputStride == elementSize)
169             {
170                 memcpy(output, input, count * inputStride);
171             }
172             else
173             {
174                 formatConverter.convertArray(input, inputStride, count, output);
175             }
176
177             mStreamBuffer->unmap();
178         }
179     }
180
181     if (usesCurrentValues)
182     {
183         processNonArrayAttributes(attribs, activeAttribs, translated, count);
184     }
185
186     return GL_NO_ERROR;
187 }
188
189 std::size_t VertexDataManager::typeSize(GLenum type) const
190 {
191     switch (type)
192     {
193       case GL_BYTE: case GL_UNSIGNED_BYTE: return sizeof(GLbyte);
194       case GL_SHORT: case GL_UNSIGNED_SHORT: return sizeof(GLshort);
195       case GL_FIXED: return sizeof(GLfixed);
196       case GL_FLOAT: return sizeof(GLfloat);
197       default: UNREACHABLE(); return sizeof(GLfloat);
198     }
199 }
200
201 std::size_t VertexDataManager::interpretGlStride(const AttributeState &attrib) const
202 {
203     return attrib.mStride ? attrib.mStride : typeSize(attrib.mType) * attrib.mSize;
204 }
205
206 // Round up x (>=0) to the next multiple of multiple (>0).
207 // 0 rounds up to 0.
208 std::size_t VertexDataManager::roundUp(std::size_t x, std::size_t multiple) const
209 {
210     ASSERT(x >= 0);
211     ASSERT(multiple > 0);
212
213     std::size_t remainder = x % multiple;
214     if (remainder != 0)
215     {
216         return x + multiple - remainder;
217     }
218     else
219     {
220         return x;
221     }
222 }
223
224 std::size_t VertexDataManager::spaceRequired(const AttributeState &attrib, std::size_t maxVertex) const
225 {
226     std::size_t size = mBackend->getFormatConverter(attrib.mType, attrib.mSize, attrib.mNormalized).outputVertexSize;
227     size *= maxVertex;
228
229     return roundUp(size, 4 * sizeof(GLfloat));
230 }
231
232 void VertexDataManager::processNonArrayAttributes(const AttributeState *attribs, const std::bitset<MAX_VERTEX_ATTRIBS> &activeAttribs, TranslatedAttribute *translated, std::size_t count)
233 {
234     if (mDirtyCurrentValues)
235     {
236         std::size_t totalSize = 4 * sizeof(float) * MAX_VERTEX_ATTRIBS;
237
238         mCurrentValueBuffer->reserveSpace(totalSize);
239
240         float* currentValues = static_cast<float*>(mCurrentValueBuffer->map(totalSize, &mCurrentValueOffset));
241
242         for (int i = 0; i < MAX_VERTEX_ATTRIBS; i++)
243         {
244             // This assumes that the GL_FLOATx4 is supported by the back-end. (For D3D9, it is a mandatory format.)
245             currentValues[i*4+0] = attribs[i].mCurrentValue[0];
246             currentValues[i*4+1] = attribs[i].mCurrentValue[1];
247             currentValues[i*4+2] = attribs[i].mCurrentValue[2];
248             currentValues[i*4+3] = attribs[i].mCurrentValue[3];
249         }
250
251         mCurrentValueBuffer->unmap();
252     }
253
254     for (std::size_t i = 0; i < MAX_VERTEX_ATTRIBS; i++)
255     {
256         if (activeAttribs[i] && !attribs[i].mEnabled)
257         {
258             translated[i].nonArray = true;
259
260             translated[i].buffer = mCurrentValueBuffer;
261
262             translated[i].type = GL_FLOAT;
263             translated[i].size = 4;
264             translated[i].normalized = false;
265             translated[i].stride = 0;
266             translated[i].offset = mCurrentValueOffset + 4 * sizeof(float) * i;
267         }
268     }
269 }
270
271 }