OSDN Git Service

Implement a Radiance prototype.
[android-x86/external-swiftshader.git] / src / Radiance / libRAD / IndexDataManager.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 // IndexDataManager.cpp: Defines the IndexDataManager, a class that\r
13 // runs the Buffer translation process for index buffers.\r
14 \r
15 #include "IndexDataManager.h"\r
16 \r
17 #include "Buffer.h"\r
18 #include "common/debug.h"\r
19 \r
20 #include <string.h>\r
21 #include <algorithm>\r
22 \r
23 namespace\r
24 {\r
25     enum { INITIAL_INDEX_BUFFER_SIZE = 4096 * sizeof(GLuint) };\r
26 }\r
27 \r
28 namespace es2\r
29 {\r
30 \r
31 IndexDataManager::IndexDataManager()\r
32 {\r
33     mStreamingBuffer = new StreamingIndexBuffer(INITIAL_INDEX_BUFFER_SIZE);\r
34 \r
35     if(!mStreamingBuffer)\r
36     {\r
37         ERR("Failed to allocate the streaming index buffer.");\r
38     }\r
39 }\r
40 \r
41 IndexDataManager::~IndexDataManager()\r
42 {\r
43     delete mStreamingBuffer;\r
44 }\r
45 \r
46 void copyIndices(GLenum type, const void *input, GLsizei count, void *output)\r
47 {\r
48     if(type == GL_UNSIGNED_BYTE)\r
49     {\r
50         memcpy(output, input, count * sizeof(GLubyte));\r
51     }\r
52     else if(type == GL_UNSIGNED_INT)\r
53     {\r
54         memcpy(output, input, count * sizeof(GLuint));\r
55     }\r
56     else if(type == GL_UNSIGNED_SHORT)\r
57     {\r
58         memcpy(output, input, count * sizeof(GLushort));\r
59     }\r
60     else UNREACHABLE();\r
61 }\r
62 \r
63 template<class IndexType>\r
64 void computeRange(const IndexType *indices, GLsizei count, GLuint *minIndex, GLuint *maxIndex)\r
65 {\r
66     *minIndex = indices[0];\r
67     *maxIndex = indices[0];\r
68 \r
69     for(GLsizei i = 0; i < count; i++)\r
70     {\r
71         if(*minIndex > indices[i]) *minIndex = indices[i];\r
72         if(*maxIndex < indices[i]) *maxIndex = indices[i];\r
73     }\r
74 }\r
75 \r
76 void computeRange(GLenum type, const void *indices, GLsizei count, GLuint *minIndex, GLuint *maxIndex)\r
77 {\r
78     if(type == GL_UNSIGNED_BYTE)\r
79     {\r
80         computeRange(static_cast<const GLubyte*>(indices), count, minIndex, maxIndex);\r
81     }\r
82     else if(type == GL_UNSIGNED_INT)\r
83     {\r
84         computeRange(static_cast<const GLuint*>(indices), count, minIndex, maxIndex);\r
85     }\r
86     else if(type == GL_UNSIGNED_SHORT)\r
87     {\r
88         computeRange(static_cast<const GLushort*>(indices), count, minIndex, maxIndex);\r
89     }\r
90     else UNREACHABLE();\r
91 }\r
92 \r
93 GLenum IndexDataManager::prepareIndexData(GLenum type, GLsizei count, Buffer *buffer, const void *indices, TranslatedIndexData *translated)\r
94 {\r
95     if(!mStreamingBuffer)\r
96     {\r
97         return GL_OUT_OF_MEMORY;\r
98     }\r
99 \r
100     intptr_t offset = reinterpret_cast<intptr_t>(indices);\r
101     bool alignedOffset = false;\r
102 \r
103     if(buffer != NULL)\r
104     {\r
105         switch(type)\r
106         {\r
107           case GL_UNSIGNED_BYTE:  alignedOffset = (offset % sizeof(GLubyte) == 0);  break;\r
108           case GL_UNSIGNED_SHORT: alignedOffset = (offset % sizeof(GLushort) == 0); break;\r
109           case GL_UNSIGNED_INT:   alignedOffset = (offset % sizeof(GLuint) == 0);   break;\r
110           default: UNREACHABLE(); alignedOffset = false;\r
111         }\r
112 \r
113         if(typeSize(type) * count + offset > static_cast<std::size_t>(buffer->size()))\r
114         {\r
115             return GL_INVALID_OPERATION;\r
116         }\r
117 \r
118         indices = static_cast<const GLubyte*>(buffer->data()) + offset;\r
119     }\r
120 \r
121     StreamingIndexBuffer *streamingBuffer = mStreamingBuffer;\r
122 \r
123         sw::Resource *staticBuffer = buffer ? buffer->getResource() : NULL;\r
124 \r
125     if(staticBuffer)\r
126     {\r
127         computeRange(type, indices, count, &translated->minIndex, &translated->maxIndex);\r
128 \r
129                 translated->indexBuffer = staticBuffer;\r
130                 translated->indexOffset = offset;\r
131     }\r
132     else\r
133     {\r
134                 unsigned int streamOffset = 0;\r
135         int convertCount = count;\r
136 \r
137         streamingBuffer->reserveSpace(convertCount * typeSize(type), type);\r
138         void *output = streamingBuffer->map(typeSize(type) * convertCount, &streamOffset);\r
139         \r
140         if(output == NULL)\r
141         {\r
142             ERR("Failed to map index buffer.");\r
143             return GL_OUT_OF_MEMORY;\r
144         }\r
145 \r
146         copyIndices(type, staticBuffer ? buffer->data() : indices, convertCount, output);\r
147         streamingBuffer->unmap();\r
148 \r
149         computeRange(type, indices, count, &translated->minIndex, &translated->maxIndex);\r
150 \r
151                 translated->indexBuffer = streamingBuffer->getResource();\r
152                 translated->indexOffset = streamOffset;\r
153     }\r
154 \r
155     return GL_NO_ERROR;\r
156 }\r
157 \r
158 std::size_t IndexDataManager::typeSize(GLenum type)\r
159 {\r
160     switch(type)\r
161     {\r
162     case GL_UNSIGNED_INT:   return sizeof(GLuint);\r
163     case GL_UNSIGNED_SHORT: return sizeof(GLushort);\r
164     case GL_UNSIGNED_BYTE:  return sizeof(GLubyte);\r
165     default: UNREACHABLE(); return sizeof(GLushort);\r
166     }\r
167 }\r
168 \r
169 StreamingIndexBuffer::StreamingIndexBuffer(unsigned int initialSize) : mBufferSize(initialSize), mIndexBuffer(NULL)\r
170 {\r
171         if(initialSize > 0)\r
172     {\r
173                 mIndexBuffer = new sw::Resource(initialSize + 16);\r
174 \r
175         if(!mIndexBuffer)\r
176         {\r
177             ERR("Out of memory allocating an index buffer of size %lu.", initialSize);\r
178         }\r
179     }\r
180 \r
181     mWritePosition = 0;\r
182 }\r
183 \r
184 StreamingIndexBuffer::~StreamingIndexBuffer()\r
185 {\r
186         if(mIndexBuffer)\r
187     {\r
188         mIndexBuffer->destruct();\r
189     }\r
190 }\r
191 \r
192 void *StreamingIndexBuffer::map(unsigned int requiredSpace, unsigned int *offset)\r
193 {\r
194     void *mapPtr = NULL;\r
195 \r
196     if(mIndexBuffer)\r
197     {\r
198         mapPtr = (char*)mIndexBuffer->lock(sw::PUBLIC) + mWritePosition;\r
199      \r
200         if(!mapPtr)\r
201         {\r
202             ERR(" Lock failed");\r
203             return NULL;\r
204         }\r
205 \r
206         *offset = mWritePosition;\r
207         mWritePosition += requiredSpace;\r
208     }\r
209 \r
210     return mapPtr;\r
211 }\r
212 \r
213 void StreamingIndexBuffer::unmap()\r
214 {\r
215     if(mIndexBuffer)\r
216     {\r
217         mIndexBuffer->unlock();\r
218     }\r
219 }\r
220 \r
221 void StreamingIndexBuffer::reserveSpace(unsigned int requiredSpace, GLenum type)\r
222 {\r
223     if(requiredSpace > mBufferSize)\r
224     {\r
225         if(mIndexBuffer)\r
226         {\r
227             mIndexBuffer->destruct();\r
228             mIndexBuffer = 0;\r
229         }\r
230 \r
231         mBufferSize = std::max(requiredSpace, 2 * mBufferSize);\r
232 \r
233                 mIndexBuffer = new sw::Resource(mBufferSize + 16);\r
234     \r
235         if(!mIndexBuffer)\r
236         {\r
237             ERR("Out of memory allocating an index buffer of size %lu.", mBufferSize);\r
238         }\r
239 \r
240         mWritePosition = 0;\r
241     }\r
242     else if(mWritePosition + requiredSpace > mBufferSize)   // Recycle\r
243     {\r
244                 if(mIndexBuffer)\r
245                 {\r
246                         mIndexBuffer->destruct();\r
247                         mIndexBuffer = new sw::Resource(mBufferSize + 16);\r
248                 }\r
249 \r
250         mWritePosition = 0;\r
251     }\r
252 }\r
253 \r
254 sw::Resource *StreamingIndexBuffer::getResource() const\r
255 {\r
256     return mIndexBuffer;\r
257 }\r
258 \r
259 }\r