blob: acac7dc6820fa2c949ae53048a95a90361d87c4e [file] [log] [blame]
daniel@transgaming.com0f7aaf52010-03-11 19:41:38 +00001//
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
daniel@transgaming.combbf56f72010-04-20 18:52:13 +000010#include "libGLESv2/geometry/VertexDataManager.h"
daniel@transgaming.com0f7aaf52010-03-11 19:41:38 +000011
alokp@chromium.orgea0e1af2010-03-22 19:33:14 +000012#include "common/debug.h"
daniel@transgaming.com0f7aaf52010-03-11 19:41:38 +000013
daniel@transgaming.combbf56f72010-04-20 18:52:13 +000014#include "libGLESv2/Buffer.h"
15#include "libGLESv2/Program.h"
16
17#include "libGLESv2/geometry/backend.h"
18#include "libGLESv2/geometry/IndexDataManager.h"
daniel@transgaming.com0f7aaf52010-03-11 19:41:38 +000019
20namespace
21{
22 enum { INITIAL_STREAM_BUFFER_SIZE = 1024*1024 };
daniel@transgaming.comc828b142010-05-12 03:42:04 +000023 enum { MAX_CURRENT_VALUE_EXPANSION = 16 };
24 enum { CURRENT_VALUES_REQUIRED_SPACE = 4 * sizeof(float) * gl::MAX_VERTEX_ATTRIBS * MAX_CURRENT_VALUE_EXPANSION };
daniel@transgaming.com0f7aaf52010-03-11 19:41:38 +000025}
26
27namespace gl
28{
29
30VertexDataManager::VertexDataManager(Context *context, BufferBackEnd *backend)
daniel@transgaming.com97bffae2010-05-05 18:49:44 +000031 : mContext(context), mBackend(backend), mDirtyCurrentValues(true), mCurrentValueOffset(0)
daniel@transgaming.com0f7aaf52010-03-11 19:41:38 +000032{
33 mStreamBuffer = mBackend->createVertexBuffer(INITIAL_STREAM_BUFFER_SIZE);
34 try
35 {
daniel@transgaming.comc828b142010-05-12 03:42:04 +000036 mCurrentValueBuffer = mBackend->createVertexBufferForStrideZero(4 * sizeof(float) * MAX_VERTEX_ATTRIBS);
daniel@transgaming.com0f7aaf52010-03-11 19:41:38 +000037 }
38 catch (...)
39 {
40 delete mStreamBuffer;
41 throw;
42 }
43}
44
45VertexDataManager::~VertexDataManager()
46{
47 delete mStreamBuffer;
48 delete mCurrentValueBuffer;
49}
50
daniel@transgaming.com3e4c6002010-05-05 18:50:13 +000051std::bitset<MAX_VERTEX_ATTRIBS> VertexDataManager::getActiveAttribs() const
daniel@transgaming.com0f7aaf52010-03-11 19:41:38 +000052{
53 std::bitset<MAX_VERTEX_ATTRIBS> active;
54
daniel@transgaming.comb4ff1f82010-04-22 13:35:18 +000055 Program *program = mContext->getCurrentProgram();
daniel@transgaming.com0f7aaf52010-03-11 19:41:38 +000056
daniel@transgaming.comb4ff1f82010-04-22 13:35:18 +000057 for (int attributeIndex = 0; attributeIndex < MAX_VERTEX_ATTRIBS; attributeIndex++)
daniel@transgaming.com0f7aaf52010-03-11 19:41:38 +000058 {
daniel@transgaming.comb4ff1f82010-04-22 13:35:18 +000059 active[attributeIndex] = (program->getSemanticIndex(attributeIndex) != -1);
daniel@transgaming.com0f7aaf52010-03-11 19:41:38 +000060 }
61
62 return active;
63}
64
65GLenum VertexDataManager::preRenderValidate(GLint start, GLsizei count,
daniel@transgaming.com3e4c6002010-05-05 18:50:13 +000066 TranslatedAttribute *translated)
daniel@transgaming.com0f7aaf52010-03-11 19:41:38 +000067{
daniel@transgaming.com3e4c6002010-05-05 18:50:13 +000068 const AttributeState *attribs = mContext->getVertexAttribBlock();
69 const std::bitset<MAX_VERTEX_ATTRIBS> activeAttribs = getActiveAttribs();
daniel@transgaming.com0f7aaf52010-03-11 19:41:38 +000070
daniel@transgaming.com0f7aaf52010-03-11 19:41:38 +000071 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
daniel@transgaming.com0f7aaf52010-03-11 19:41:38 +000077 for (int i = 0; i < MAX_VERTEX_ATTRIBS; i++)
78 {
79 translated[i].enabled = activeAttribs[i];
80 }
81
daniel@transgaming.comc828b142010-05-12 03:42:04 +000082 bool usesCurrentValues = false;
daniel@transgaming.com0f7aaf52010-03-11 19:41:38 +000083
daniel@transgaming.comc828b142010-05-12 03:42:04 +000084 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.
daniel@transgaming.com9a0606c2010-05-12 03:42:00 +000094 // Process array attributes.
95
96 std::size_t requiredSpace = 0;
daniel@transgaming.com0f7aaf52010-03-11 19:41:38 +000097
98 for (int i = 0; i < MAX_VERTEX_ATTRIBS; i++)
99 {
100 if (activeAttribs[i] && attribs[i].mEnabled)
101 {
daniel@transgaming.com9a0606c2010-05-12 03:42:00 +0000102 requiredSpace += spaceRequired(attribs[i], count);
daniel@transgaming.com0f7aaf52010-03-11 19:41:38 +0000103 }
104 }
105
daniel@transgaming.comc828b142010-05-12 03:42:04 +0000106 if (usesCurrentValues)
107 {
108 requiredSpace += CURRENT_VALUES_REQUIRED_SPACE;
109 }
110
daniel@transgaming.com9a0606c2010-05-12 03:42:00 +0000111 if (requiredSpace > mStreamBuffer->size())
daniel@transgaming.com0f7aaf52010-03-11 19:41:38 +0000112 {
daniel@transgaming.com9a0606c2010-05-12 03:42:00 +0000113 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.
daniel@transgaming.com0f7aaf52010-03-11 19:41:38 +0000114
daniel@transgaming.com9a0606c2010-05-12 03:42:00 +0000115 TranslatedVertexBuffer *newStreamBuffer = mBackend->createVertexBuffer(newSize);
116
117 delete mStreamBuffer;
118 mStreamBuffer = newStreamBuffer;
119 }
120
121 mStreamBuffer->reserveSpace(requiredSpace);
122
123 for (size_t i = 0; i < MAX_VERTEX_ATTRIBS; i++)
124 {
125 if (activeAttribs[i] && attribs[i].mEnabled)
daniel@transgaming.com0f7aaf52010-03-11 19:41:38 +0000126 {
daniel@transgaming.com9a0606c2010-05-12 03:42:00 +0000127 FormatConverter formatConverter = mBackend->getFormatConverter(attribs[i].mType, attribs[i].mSize, attribs[i].mNormalized);
128
129 translated[i].type = attribs[i].mType;
130 translated[i].size = attribs[i].mSize;
131 translated[i].normalized = attribs[i].mNormalized;
132 translated[i].stride = formatConverter.outputVertexSize;
133 translated[i].buffer = mStreamBuffer;
134
135 void *output = mStreamBuffer->map(spaceRequired(attribs[i], count), &translated[i].offset);
136
137 const void *input;
138 if (attribs[i].mBoundBuffer)
daniel@transgaming.com0f7aaf52010-03-11 19:41:38 +0000139 {
daniel@transgaming.com9a0606c2010-05-12 03:42:00 +0000140 input = mContext->getBuffer(attribs[i].mBoundBuffer)->data();
141 input = static_cast<const char*>(input) + reinterpret_cast<size_t>(attribs[i].mPointer);
daniel@transgaming.com0f7aaf52010-03-11 19:41:38 +0000142 }
daniel@transgaming.com9a0606c2010-05-12 03:42:00 +0000143 else
daniel@transgaming.com0f7aaf52010-03-11 19:41:38 +0000144 {
daniel@transgaming.com9a0606c2010-05-12 03:42:00 +0000145 input = attribs[i].mPointer;
146 }
daniel@transgaming.com0f7aaf52010-03-11 19:41:38 +0000147
daniel@transgaming.com9a0606c2010-05-12 03:42:00 +0000148 size_t inputStride = interpretGlStride(attribs[i]);
daniel@transgaming.com0f7aaf52010-03-11 19:41:38 +0000149
daniel@transgaming.com9a0606c2010-05-12 03:42:00 +0000150 input = static_cast<const char*>(input) + inputStride * start;
daniel@transgaming.com0f7aaf52010-03-11 19:41:38 +0000151
daniel@transgaming.com9a0606c2010-05-12 03:42:00 +0000152 if (formatConverter.identity && inputStride == typeSize(attribs[i].mType) * attribs[i].mSize)
153 {
154 memcpy(output, input, count * inputStride);
155 }
156 else
157 {
daniel@transgaming.com3e4c6002010-05-05 18:50:13 +0000158 formatConverter.convertArray(input, inputStride, count, output);
daniel@transgaming.com0f7aaf52010-03-11 19:41:38 +0000159 }
daniel@transgaming.com9a0606c2010-05-12 03:42:00 +0000160
161 mStreamBuffer->unmap();
daniel@transgaming.com0f7aaf52010-03-11 19:41:38 +0000162 }
163 }
164
daniel@transgaming.comc828b142010-05-12 03:42:04 +0000165 if (usesCurrentValues)
daniel@transgaming.com0f7aaf52010-03-11 19:41:38 +0000166 {
daniel@transgaming.comc828b142010-05-12 03:42:04 +0000167 processNonArrayAttributes(attribs, activeAttribs, translated, count);
daniel@transgaming.com0f7aaf52010-03-11 19:41:38 +0000168 }
daniel@transgaming.com97bffae2010-05-05 18:49:44 +0000169
daniel@transgaming.comc828b142010-05-12 03:42:04 +0000170 return GL_NO_ERROR;
daniel@transgaming.com0f7aaf52010-03-11 19:41:38 +0000171}
172
173std::size_t VertexDataManager::typeSize(GLenum type) const
174{
175 switch (type)
176 {
177 case GL_BYTE: case GL_UNSIGNED_BYTE: return sizeof(GLbyte);
178 case GL_SHORT: case GL_UNSIGNED_SHORT: return sizeof(GLshort);
179 case GL_FIXED: return sizeof(GLfixed);
180 case GL_FLOAT: return sizeof(GLfloat);
daniel@transgaming.com9efa6f62010-03-16 06:23:20 +0000181 default: UNREACHABLE(); return sizeof(GLfloat);
daniel@transgaming.com0f7aaf52010-03-11 19:41:38 +0000182 }
183}
184
185std::size_t VertexDataManager::interpretGlStride(const AttributeState &attrib) const
186{
187 return attrib.mStride ? attrib.mStride : typeSize(attrib.mType) * attrib.mSize;
188}
189
190// Round up x (>=0) to the next multiple of multiple (>0).
191// 0 rounds up to 0.
192std::size_t VertexDataManager::roundUp(std::size_t x, std::size_t multiple) const
193{
194 ASSERT(x >= 0);
195 ASSERT(multiple > 0);
196
197 std::size_t remainder = x % multiple;
198 if (remainder != 0)
199 {
200 return x + multiple - remainder;
201 }
202 else
203 {
204 return x;
205 }
206}
207
208std::size_t VertexDataManager::spaceRequired(const AttributeState &attrib, std::size_t maxVertex) const
209{
210 std::size_t size = mBackend->getFormatConverter(attrib.mType, attrib.mSize, attrib.mNormalized).outputVertexSize;
211 size *= maxVertex;
212
213 return roundUp(size, 4 * sizeof(GLfloat));
214}
215
daniel@transgaming.comc828b142010-05-12 03:42:04 +0000216void VertexDataManager::processNonArrayAttributes(const AttributeState *attribs, const std::bitset<MAX_VERTEX_ATTRIBS> &activeAttribs, TranslatedAttribute *translated, std::size_t count)
daniel@transgaming.com0f7aaf52010-03-11 19:41:38 +0000217{
daniel@transgaming.comc828b142010-05-12 03:42:04 +0000218 if (count <= MAX_CURRENT_VALUE_EXPANSION)
daniel@transgaming.com0f7aaf52010-03-11 19:41:38 +0000219 {
daniel@transgaming.comc828b142010-05-12 03:42:04 +0000220 if (mDirtyCurrentValues || mCurrentValueLoadBuffer != mStreamBuffer)
daniel@transgaming.com0f7aaf52010-03-11 19:41:38 +0000221 {
daniel@transgaming.comc828b142010-05-12 03:42:04 +0000222 float *p = static_cast<float*>(mStreamBuffer->map(CURRENT_VALUES_REQUIRED_SPACE, &mCurrentValueOffset));
223
224 for (int i = 0; i < MAX_VERTEX_ATTRIBS; i++)
225 {
226 float *out = p + MAX_CURRENT_VALUE_EXPANSION * 4 * i;
227 for (unsigned int j = 0; j < MAX_CURRENT_VALUE_EXPANSION; j++)
228 {
229 *out++ = attribs[i].mCurrentValue[0];
230 *out++ = attribs[i].mCurrentValue[1];
231 *out++ = attribs[i].mCurrentValue[2];
232 *out++ = attribs[i].mCurrentValue[3];
233 }
234 }
235
236 mStreamBuffer->unmap();
237
238 mCurrentValueLoadBuffer = mStreamBuffer;
239 mCurrentValueSize = MAX_CURRENT_VALUE_EXPANSION;
240 mCurrentValueStride = 4 * sizeof(float);
241 }
242 }
243 else
244 {
245 if (mDirtyCurrentValues || mCurrentValueLoadBuffer != mCurrentValueBuffer)
246 {
247 std::size_t totalSize = 4 * sizeof(float) * MAX_VERTEX_ATTRIBS;
248
249 mCurrentValueBuffer->reserveSpace(totalSize);
250
251 float* p = static_cast<float*>(mCurrentValueBuffer->map(totalSize, &mCurrentValueOffset));
252
253 for (int i = 0; i < MAX_VERTEX_ATTRIBS; i++)
254 {
255 memcpy(&p[i*4], attribs[i].mCurrentValue, sizeof(attribs[i].mCurrentValue)); // FIXME: this should be doing a translation. This assumes that GL_FLOATx4 is supported.
256 }
257
258 mCurrentValueBuffer->unmap();
259
260 mCurrentValueLoadBuffer = mCurrentValueBuffer;
261 mCurrentValueSize = 1;
262 mCurrentValueStride = 0;
daniel@transgaming.com0f7aaf52010-03-11 19:41:38 +0000263 }
264 }
265
daniel@transgaming.comc828b142010-05-12 03:42:04 +0000266 for (std::size_t i = 0; i < MAX_VERTEX_ATTRIBS; i++)
daniel@transgaming.com0f7aaf52010-03-11 19:41:38 +0000267 {
daniel@transgaming.comc828b142010-05-12 03:42:04 +0000268 if (activeAttribs[i] && !attribs[i].mEnabled)
daniel@transgaming.com0f7aaf52010-03-11 19:41:38 +0000269 {
daniel@transgaming.comc828b142010-05-12 03:42:04 +0000270 translated[i].buffer = mCurrentValueLoadBuffer;
daniel@transgaming.com0f7aaf52010-03-11 19:41:38 +0000271
daniel@transgaming.comc828b142010-05-12 03:42:04 +0000272 translated[i].type = GL_FLOAT;
273 translated[i].size = 4;
274 translated[i].normalized = false;
275 translated[i].stride = mCurrentValueStride;
276 translated[i].offset = mCurrentValueOffset + 4 * sizeof(float) * i * mCurrentValueSize;
daniel@transgaming.com0f7aaf52010-03-11 19:41:38 +0000277 }
278 }
279}
280
281}