OSDN Git Service

47479fe3523151cd5db65d1e51f6815efcda0862
[android-x86/external-swiftshader.git] / src / Radiance / libRAD / VertexDataManager.cpp
1 // SwiftShader Software Renderer\r
2 //\r
3 // Copyright(c) 2005-2012 TransGaming Inc.\r
4 //\r
5 // All rights reserved. No part of this software may be copied, distributed, transmitted,\r
6 // transcribed, stored in a retrieval system, translated into any human or computer\r
7 // language by any means, or disclosed to third parties without the explicit written\r
8 // agreement of TransGaming Inc. Without such an agreement, no rights or licenses, express\r
9 // or implied, including but not limited to any patent rights, are granted to you.\r
10 //\r
11 \r
12 // VertexDataManager.h: Defines the VertexDataManager, a class that\r
13 // runs the Buffer translation process.\r
14 \r
15 #include "VertexDataManager.h"\r
16 \r
17 #include "Buffer.h"\r
18 #include "Program.h"\r
19 #include "IndexDataManager.h"\r
20 #include "common/debug.h"\r
21 \r
22 namespace\r
23 {\r
24     enum {INITIAL_STREAM_BUFFER_SIZE = 1024 * 1024};\r
25 }\r
26 \r
27 namespace rad\r
28 {\r
29 \r
30 VertexDataManager::VertexDataManager(Context *context) : mContext(context)\r
31 {\r
32     for(int i = 0; i < MAX_VERTEX_ATTRIBS; i++)\r
33     {\r
34         mDirtyCurrentValue[i] = true;\r
35         mCurrentValueBuffer[i] = NULL;\r
36     }\r
37 \r
38     mStreamingBuffer = new StreamingVertexBuffer(INITIAL_STREAM_BUFFER_SIZE);\r
39 \r
40     if(!mStreamingBuffer)\r
41     {\r
42         ERR("Failed to allocate the streaming vertex buffer.");\r
43     }\r
44 }\r
45 \r
46 VertexDataManager::~VertexDataManager()\r
47 {\r
48     delete mStreamingBuffer;\r
49 \r
50     for(int i = 0; i < MAX_VERTEX_ATTRIBS; i++)\r
51     {\r
52         delete mCurrentValueBuffer[i];\r
53     }\r
54 }\r
55 \r
56 unsigned int VertexDataManager::writeAttributeData(StreamingVertexBuffer *vertexBuffer, GLint start, GLsizei count, const VertexAttribute &attribute)\r
57 {\r
58     Buffer *buffer = attribute.mBoundBuffer.get();\r
59 \r
60     int inputStride = attribute.stride();\r
61     int elementSize = attribute.typeSize();\r
62     unsigned int streamOffset = 0;\r
63 \r
64     char *output = NULL;\r
65     \r
66     if(vertexBuffer)\r
67     {\r
68         output = (char*)vertexBuffer->map(attribute, attribute.typeSize() * count, &streamOffset);\r
69     }\r
70 \r
71     if(output == NULL)\r
72     {\r
73         ERR("Failed to map vertex buffer.");\r
74         return -1;\r
75     }\r
76 \r
77     const char *input = NULL;\r
78 \r
79     if(buffer)\r
80     {\r
81         int offset = attribute.mOffset;\r
82 \r
83         input = static_cast<const char*>(buffer->data()) + offset;\r
84     }\r
85     else\r
86     {\r
87         input = static_cast<const char*>(attribute.mPointer);\r
88     }\r
89 \r
90     input += inputStride * start;\r
91 \r
92     if(inputStride == elementSize)\r
93     {\r
94         memcpy(output, input, count * inputStride);\r
95     }\r
96     else\r
97     {\r
98                 for(int i = 0; i < count; i++)\r
99                 {\r
100                         memcpy(output, input, elementSize);\r
101                         output += elementSize;\r
102                         input += inputStride;\r
103                 }\r
104     }\r
105 \r
106     vertexBuffer->unmap();\r
107 \r
108     return streamOffset;\r
109 }\r
110 \r
111 GLenum VertexDataManager::prepareVertexData(GLint start, GLsizei count, TranslatedAttribute *translated)\r
112 {\r
113     if(!mStreamingBuffer)\r
114     {\r
115         return GL_OUT_OF_MEMORY;\r
116     }\r
117 \r
118     const VertexAttributeArray &attribs = mContext->getVertexAttributes();\r
119     Program *program = mContext->getCurrentProgram();\r
120 \r
121     // Determine the required storage size per used buffer\r
122     for(int i = 0; i < MAX_VERTEX_ATTRIBS; i++)\r
123     {\r
124         if(program->getAttributeStream(i) != -1 && attribs[i].mArrayEnabled)\r
125         {\r
126             if(!attribs[i].mBoundBuffer)\r
127             {\r
128                 mStreamingBuffer->addRequiredSpace(attribs[i].typeSize() * count);\r
129             }\r
130         }\r
131     }\r
132 \r
133     mStreamingBuffer->reserveRequiredSpace();\r
134     \r
135     // Perform the vertex data translations\r
136     for(int i = 0; i < MAX_VERTEX_ATTRIBS; i++)\r
137     {\r
138         if(program->getAttributeStream(i) != -1)\r
139         {\r
140             if(attribs[i].mArrayEnabled)\r
141             {\r
142                 Buffer *buffer = attribs[i].mBoundBuffer.get();\r
143 \r
144                 if(!buffer && attribs[i].mPointer == NULL)\r
145                 {\r
146                     // This is an application error that would normally result in a crash, but we catch it and return an error\r
147                     ERR("An enabled vertex array has no buffer and no pointer.");\r
148                     return GL_INVALID_OPERATION;\r
149                 }\r
150 \r
151                 sw::Resource *staticBuffer = buffer ? buffer->getResource() : NULL;\r
152 \r
153                 if(staticBuffer)\r
154                 {\r
155                                         translated[i].vertexBuffer = staticBuffer;\r
156                                         translated[i].offset = start * attribs[i].stride() + attribs[i].mOffset;\r
157                                         translated[i].stride = attribs[i].stride();\r
158                 }\r
159                 else\r
160                 {\r
161                     unsigned int streamOffset = writeAttributeData(mStreamingBuffer, start, count, attribs[i]);\r
162 \r
163                                         if(streamOffset == -1)\r
164                                         {\r
165                                                 return GL_OUT_OF_MEMORY;\r
166                                         }\r
167 \r
168                                         translated[i].vertexBuffer = mStreamingBuffer->getResource();\r
169                                         translated[i].offset = streamOffset;\r
170                                         translated[i].stride = attribs[i].typeSize();\r
171                 }\r
172 \r
173                                 switch(attribs[i].mType)\r
174                                 {\r
175                                 case GL_BYTE:           translated[i].type = sw::STREAMTYPE_SBYTE;  break;\r
176                                 case GL_UNSIGNED_BYTE:  translated[i].type = sw::STREAMTYPE_BYTE;   break;\r
177                                 case GL_SHORT:          translated[i].type = sw::STREAMTYPE_SHORT;  break;\r
178                                 case GL_UNSIGNED_SHORT: translated[i].type = sw::STREAMTYPE_USHORT; break;\r
179                                 case GL_FIXED:          translated[i].type = sw::STREAMTYPE_FIXED;  break;\r
180                                 case GL_FLOAT:          translated[i].type = sw::STREAMTYPE_FLOAT;  break;\r
181                                 default: UNREACHABLE(); translated[i].type = sw::STREAMTYPE_FLOAT;  break;\r
182                                 }\r
183 \r
184                                 translated[i].count = attribs[i].mSize;\r
185                                 translated[i].normalized = attribs[i].mNormalized;\r
186             }\r
187             else\r
188             {\r
189                 if(mDirtyCurrentValue[i])\r
190                 {\r
191                     delete mCurrentValueBuffer[i];\r
192                     mCurrentValueBuffer[i] = new ConstantVertexBuffer(attribs[i].mCurrentValue[0], attribs[i].mCurrentValue[1], attribs[i].mCurrentValue[2], attribs[i].mCurrentValue[3]);\r
193                     mDirtyCurrentValue[i] = false;\r
194                 }\r
195 \r
196                 translated[i].vertexBuffer = mCurrentValueBuffer[i]->getResource();\r
197 \r
198                 translated[i].type = sw::STREAMTYPE_FLOAT;\r
199                                 translated[i].count = 4;\r
200                 translated[i].stride = 0;\r
201                 translated[i].offset = 0;\r
202             }\r
203         }\r
204     }\r
205 \r
206     return GL_NO_ERROR;\r
207 }\r
208 \r
209 VertexBuffer::VertexBuffer(unsigned int size) : mVertexBuffer(NULL)\r
210 {\r
211     if(size > 0)\r
212     {\r
213         mVertexBuffer = new sw::Resource(size + 1024);\r
214         \r
215         if(!mVertexBuffer)\r
216         {\r
217             ERR("Out of memory allocating a vertex buffer of size %lu.", size);\r
218         }\r
219     }\r
220 }\r
221 \r
222 VertexBuffer::~VertexBuffer()\r
223 {\r
224     if(mVertexBuffer)\r
225     {\r
226         mVertexBuffer->destruct();\r
227     }\r
228 }\r
229 \r
230 void VertexBuffer::unmap()\r
231 {\r
232     if(mVertexBuffer)\r
233     {\r
234                 mVertexBuffer->unlock();\r
235     }\r
236 }\r
237 \r
238 sw::Resource *VertexBuffer::getResource() const\r
239 {\r
240     return mVertexBuffer;\r
241 }\r
242 \r
243 ConstantVertexBuffer::ConstantVertexBuffer(float x, float y, float z, float w) : VertexBuffer(4 * sizeof(float))\r
244 {\r
245     if(mVertexBuffer)\r
246     {\r
247                 float *vector = (float*)mVertexBuffer->lock(sw::PUBLIC);\r
248      \r
249         vector[0] = x;\r
250         vector[1] = y;\r
251         vector[2] = z;\r
252         vector[3] = w;\r
253 \r
254         mVertexBuffer->unlock();\r
255     }\r
256 }\r
257 \r
258 ConstantVertexBuffer::~ConstantVertexBuffer()\r
259 {\r
260 }\r
261 \r
262 StreamingVertexBuffer::StreamingVertexBuffer(unsigned int size) : VertexBuffer(size)\r
263 {\r
264     mBufferSize = size;\r
265     mWritePosition = 0;\r
266     mRequiredSpace = 0;\r
267 }\r
268 \r
269 StreamingVertexBuffer::~StreamingVertexBuffer()\r
270 {\r
271 }\r
272 \r
273 void StreamingVertexBuffer::addRequiredSpace(unsigned int requiredSpace)\r
274 {\r
275     mRequiredSpace += requiredSpace;\r
276 }\r
277 \r
278 void *StreamingVertexBuffer::map(const VertexAttribute &attribute, unsigned int requiredSpace, unsigned int *offset)\r
279 {\r
280     void *mapPtr = NULL;\r
281 \r
282     if(mVertexBuffer)\r
283     {\r
284                 mapPtr = (char*)mVertexBuffer->lock(sw::PUBLIC) + mWritePosition;\r
285         \r
286         if(!mapPtr)\r
287         {\r
288             ERR("Lock failed");\r
289             return NULL;\r
290         }\r
291 \r
292         *offset = mWritePosition;\r
293         mWritePosition += requiredSpace;\r
294     }\r
295 \r
296     return mapPtr;\r
297 }\r
298 \r
299 void StreamingVertexBuffer::reserveRequiredSpace()\r
300 {\r
301     if(mRequiredSpace > mBufferSize)\r
302     {\r
303         if(mVertexBuffer)\r
304         {\r
305             mVertexBuffer->destruct();\r
306             mVertexBuffer = 0;\r
307         }\r
308 \r
309         mBufferSize = std::max(mRequiredSpace, 3 * mBufferSize / 2);   // 1.5 x mBufferSize is arbitrary and should be checked to see we don't have too many reallocations.\r
310 \r
311                 mVertexBuffer = new sw::Resource(mBufferSize);\r
312     \r
313         if(!mVertexBuffer)\r
314         {\r
315             ERR("Out of memory allocating a vertex buffer of size %lu.", mBufferSize);\r
316         }\r
317 \r
318         mWritePosition = 0;\r
319     }\r
320     else if(mWritePosition + mRequiredSpace > mBufferSize)   // Recycle\r
321     {\r
322         if(mVertexBuffer)\r
323         {\r
324             mVertexBuffer->destruct();\r
325                         mVertexBuffer = new sw::Resource(mBufferSize);\r
326         }\r
327 \r
328         mWritePosition = 0;\r
329     }\r
330 \r
331     mRequiredSpace = 0;\r
332 }\r
333 \r
334 }\r