blob: 346477066c8f189e92a60a5bfa3a92becebef4c7 [file] [log] [blame]
daniel@transgaming.comf8b58a02010-03-26 04:08:45 +00001//
daniel@transgaming.comf6549452012-01-27 15:39:08 +00002// Copyright (c) 2002-2012 The ANGLE Project Authors. All rights reserved.
daniel@transgaming.comf8b58a02010-03-26 04:08:45 +00003// Use of this source code is governed by a BSD-style license that can be
4// found in the LICENSE file.
5//
6
daniel@transgaming.com8fd34bd2011-02-18 02:52:14 +00007// IndexDataManager.cpp: Defines the IndexDataManager, a class that
daniel@transgaming.comf8b58a02010-03-26 04:08:45 +00008// runs the Buffer translation process for index buffers.
9
daniel@transgaming.com50aadb02012-11-28 21:06:11 +000010#include "libGLESv2/renderer/IndexDataManager.h"
daniel@transgaming.comf8b58a02010-03-26 04:08:45 +000011
12#include "common/debug.h"
daniel@transgaming.combbf56f72010-04-20 18:52:13 +000013
14#include "libGLESv2/Buffer.h"
daniel@transgaming.com81655a72010-05-20 19:18:17 +000015#include "libGLESv2/mathutil.h"
daniel@transgaming.com37b141e2011-01-08 05:46:13 +000016#include "libGLESv2/main.h"
daniel@transgaming.comf8b58a02010-03-26 04:08:45 +000017
daniel@transgaming.com31240482012-11-28 21:06:41 +000018namespace rx
daniel@transgaming.comf8b58a02010-03-26 04:08:45 +000019{
jbauman@chromium.orgd8f3faa2011-09-02 01:10:47 +000020unsigned int IndexBuffer::mCurrentSerial = 1;
daniel@transgaming.comf8b58a02010-03-26 04:08:45 +000021
daniel@transgaming.com76d3e6e2012-10-31 19:55:33 +000022IndexDataManager::IndexDataManager(rx::Renderer9 *renderer) : mRenderer(renderer)
daniel@transgaming.comf8b58a02010-03-26 04:08:45 +000023{
daniel@transgaming.com6716a272012-10-31 18:31:39 +000024 mStreamingBufferShort = new StreamingIndexBuffer(mRenderer, INITIAL_INDEX_BUFFER_SIZE, D3DFMT_INDEX16);
daniel@transgaming.com81655a72010-05-20 19:18:17 +000025
daniel@transgaming.com408caa52012-10-31 18:47:01 +000026 if (renderer->get32BitIndexSupport())
daniel@transgaming.com3e4c6002010-05-05 18:50:13 +000027 {
daniel@transgaming.com6716a272012-10-31 18:31:39 +000028 mStreamingBufferInt = new StreamingIndexBuffer(mRenderer, INITIAL_INDEX_BUFFER_SIZE, D3DFMT_INDEX32);
daniel@transgaming.com72b9e182011-04-13 14:58:33 +000029
30 if (!mStreamingBufferInt)
31 {
32 // Don't leave it in a half-initialized state
33 delete mStreamingBufferShort;
34 mStreamingBufferShort = NULL;
35 }
daniel@transgaming.com3e4c6002010-05-05 18:50:13 +000036 }
37 else
38 {
daniel@transgaming.com83921382011-01-08 05:46:00 +000039 mStreamingBufferInt = NULL;
daniel@transgaming.com3e4c6002010-05-05 18:50:13 +000040 }
daniel@transgaming.com72b9e182011-04-13 14:58:33 +000041
42 if (!mStreamingBufferShort)
43 {
44 ERR("Failed to allocate the streaming index buffer(s).");
45 }
daniel@transgaming.comf6549452012-01-27 15:39:08 +000046
47 mCountingBuffer = NULL;
daniel@transgaming.comf8b58a02010-03-26 04:08:45 +000048}
49
50IndexDataManager::~IndexDataManager()
51{
daniel@transgaming.com83921382011-01-08 05:46:00 +000052 delete mStreamingBufferShort;
53 delete mStreamingBufferInt;
daniel@transgaming.comf6549452012-01-27 15:39:08 +000054 delete mCountingBuffer;
daniel@transgaming.comf8b58a02010-03-26 04:08:45 +000055}
56
daniel@transgaming.com83921382011-01-08 05:46:00 +000057void convertIndices(GLenum type, const void *input, GLsizei count, void *output)
daniel@transgaming.comf8b58a02010-03-26 04:08:45 +000058{
daniel@transgaming.com83921382011-01-08 05:46:00 +000059 if (type == GL_UNSIGNED_BYTE)
60 {
61 const GLubyte *in = static_cast<const GLubyte*>(input);
62 GLushort *out = static_cast<GLushort*>(output);
daniel@transgaming.comf8b58a02010-03-26 04:08:45 +000063
daniel@transgaming.com83921382011-01-08 05:46:00 +000064 for (GLsizei i = 0; i < count; i++)
65 {
66 out[i] = in[i];
67 }
68 }
69 else if (type == GL_UNSIGNED_INT)
70 {
71 memcpy(output, input, count * sizeof(GLuint));
72 }
73 else if (type == GL_UNSIGNED_SHORT)
74 {
75 memcpy(output, input, count * sizeof(GLushort));
76 }
77 else UNREACHABLE();
78}
79
80template <class IndexType>
81void computeRange(const IndexType *indices, GLsizei count, GLuint *minIndex, GLuint *maxIndex)
daniel@transgaming.comf8b58a02010-03-26 04:08:45 +000082{
daniel@transgaming.com83921382011-01-08 05:46:00 +000083 *minIndex = indices[0];
84 *maxIndex = indices[0];
daniel@transgaming.comf8b58a02010-03-26 04:08:45 +000085
86 for (GLsizei i = 0; i < count; i++)
87 {
daniel@transgaming.com83921382011-01-08 05:46:00 +000088 if (*minIndex > indices[i]) *minIndex = indices[i];
89 if (*maxIndex < indices[i]) *maxIndex = indices[i];
daniel@transgaming.comf8b58a02010-03-26 04:08:45 +000090 }
daniel@transgaming.comf8b58a02010-03-26 04:08:45 +000091}
92
daniel@transgaming.comd2820bf2012-01-27 15:38:48 +000093void computeRange(GLenum type, const GLvoid *indices, GLsizei count, GLuint *minIndex, GLuint *maxIndex)
daniel@transgaming.comf8b58a02010-03-26 04:08:45 +000094{
daniel@transgaming.com83921382011-01-08 05:46:00 +000095 if (type == GL_UNSIGNED_BYTE)
daniel@transgaming.com41d8dd82010-05-12 03:45:03 +000096 {
daniel@transgaming.com83921382011-01-08 05:46:00 +000097 computeRange(static_cast<const GLubyte*>(indices), count, minIndex, maxIndex);
98 }
99 else if (type == GL_UNSIGNED_INT)
100 {
101 computeRange(static_cast<const GLuint*>(indices), count, minIndex, maxIndex);
102 }
103 else if (type == GL_UNSIGNED_SHORT)
104 {
105 computeRange(static_cast<const GLushort*>(indices), count, minIndex, maxIndex);
106 }
107 else UNREACHABLE();
108}
daniel@transgaming.comf8b58a02010-03-26 04:08:45 +0000109
daniel@transgaming.com31240482012-11-28 21:06:41 +0000110GLenum IndexDataManager::prepareIndexData(GLenum type, GLsizei count, gl::Buffer *buffer, const GLvoid *indices, TranslatedIndexData *translated, IDirect3DIndexBuffer9 **d3dIndexBuffer, unsigned int *serial)
daniel@transgaming.com83921382011-01-08 05:46:00 +0000111{
daniel@transgaming.com72b9e182011-04-13 14:58:33 +0000112 if (!mStreamingBufferShort)
113 {
114 return GL_OUT_OF_MEMORY;
115 }
116
daniel@transgaming.com83921382011-01-08 05:46:00 +0000117 D3DFORMAT format = (type == GL_UNSIGNED_INT) ? D3DFMT_INDEX32 : D3DFMT_INDEX16;
118 intptr_t offset = reinterpret_cast<intptr_t>(indices);
119 bool alignedOffset = false;
120
121 if (buffer != NULL)
122 {
123 switch (type)
124 {
125 case GL_UNSIGNED_BYTE: alignedOffset = (offset % sizeof(GLubyte) == 0); break;
126 case GL_UNSIGNED_SHORT: alignedOffset = (offset % sizeof(GLushort) == 0); break;
127 case GL_UNSIGNED_INT: alignedOffset = (offset % sizeof(GLuint) == 0); break;
128 default: UNREACHABLE(); alignedOffset = false;
129 }
130
131 if (typeSize(type) * count + offset > static_cast<std::size_t>(buffer->size()))
daniel@transgaming.com41d8dd82010-05-12 03:45:03 +0000132 {
133 return GL_INVALID_OPERATION;
134 }
135
daniel@transgaming.com83921382011-01-08 05:46:00 +0000136 indices = static_cast<const GLubyte*>(buffer->data()) + offset;
daniel@transgaming.com41d8dd82010-05-12 03:45:03 +0000137 }
138
daniel@transgaming.com83921382011-01-08 05:46:00 +0000139 StreamingIndexBuffer *streamingBuffer = (type == GL_UNSIGNED_INT) ? mStreamingBufferInt : mStreamingBufferShort;
daniel@transgaming.comf8b58a02010-03-26 04:08:45 +0000140
daniel@transgaming.com78624ca2011-04-22 04:17:57 +0000141 StaticIndexBuffer *staticBuffer = buffer ? buffer->getStaticIndexBuffer() : NULL;
daniel@transgaming.com83921382011-01-08 05:46:00 +0000142 IndexBuffer *indexBuffer = streamingBuffer;
143 UINT streamOffset = 0;
daniel@transgaming.comf8b58a02010-03-26 04:08:45 +0000144
daniel@transgaming.com83921382011-01-08 05:46:00 +0000145 if (staticBuffer && staticBuffer->lookupType(type) && alignedOffset)
apatrick@chromium.orgf99fbb72010-11-16 01:57:05 +0000146 {
daniel@transgaming.com83921382011-01-08 05:46:00 +0000147 indexBuffer = staticBuffer;
148 streamOffset = staticBuffer->lookupRange(offset, count, &translated->minIndex, &translated->maxIndex);
daniel@transgaming.comf8b58a02010-03-26 04:08:45 +0000149
daniel@transgaming.com83921382011-01-08 05:46:00 +0000150 if (streamOffset == -1)
daniel@transgaming.com3e4c6002010-05-05 18:50:13 +0000151 {
daniel@transgaming.com83921382011-01-08 05:46:00 +0000152 streamOffset = (offset / typeSize(type)) * indexSize(format);
153 computeRange(type, indices, count, &translated->minIndex, &translated->maxIndex);
154 staticBuffer->addRange(offset, count, translated->minIndex, translated->maxIndex, streamOffset);
daniel@transgaming.com3e4c6002010-05-05 18:50:13 +0000155 }
156 }
daniel@transgaming.comf8b58a02010-03-26 04:08:45 +0000157 else
158 {
daniel@transgaming.com83921382011-01-08 05:46:00 +0000159 int convertCount = count;
daniel@transgaming.comf8b58a02010-03-26 04:08:45 +0000160
daniel@transgaming.com83921382011-01-08 05:46:00 +0000161 if (staticBuffer)
162 {
163 if (staticBuffer->size() == 0 && alignedOffset)
164 {
165 indexBuffer = staticBuffer;
166 convertCount = buffer->size() / typeSize(type);
167 }
168 else
169 {
170 buffer->invalidateStaticData();
171 staticBuffer = NULL;
172 }
173 }
174
daniel@transgaming.com5ee2ad02011-01-08 05:46:20 +0000175 void *output = NULL;
daniel@transgaming.com50aadb02012-11-28 21:06:11 +0000176
daniel@transgaming.com5ee2ad02011-01-08 05:46:20 +0000177 if (indexBuffer)
178 {
179 indexBuffer->reserveSpace(convertCount * indexSize(format), type);
180 output = indexBuffer->map(indexSize(format) * convertCount, &streamOffset);
181 }
daniel@transgaming.com50aadb02012-11-28 21:06:11 +0000182
daniel@transgaming.com83921382011-01-08 05:46:00 +0000183 if (output == NULL)
184 {
185 ERR("Failed to map index buffer.");
186 return GL_OUT_OF_MEMORY;
187 }
188
189 convertIndices(type, staticBuffer ? buffer->data() : indices, convertCount, output);
190 indexBuffer->unmap();
191
192 computeRange(type, indices, count, &translated->minIndex, &translated->maxIndex);
193
194 if (staticBuffer)
195 {
196 streamOffset = (offset / typeSize(type)) * indexSize(format);
197 staticBuffer->addRange(offset, count, translated->minIndex, translated->maxIndex, streamOffset);
198 }
daniel@transgaming.comf8b58a02010-03-26 04:08:45 +0000199 }
200
daniel@transgaming.com91207b72012-11-28 20:56:43 +0000201 *d3dIndexBuffer = indexBuffer->getBuffer();
202 *serial = indexBuffer->getSerial();
daniel@transgaming.com83921382011-01-08 05:46:00 +0000203 translated->startIndex = streamOffset / indexSize(format);
daniel@transgaming.comf8b58a02010-03-26 04:08:45 +0000204
daniel@transgaming.com78624ca2011-04-22 04:17:57 +0000205 if (buffer)
206 {
207 buffer->promoteStaticUsage(count * typeSize(type));
208 }
209
daniel@transgaming.com41d8dd82010-05-12 03:45:03 +0000210 return GL_NO_ERROR;
daniel@transgaming.comf8b58a02010-03-26 04:08:45 +0000211}
212
daniel@transgaming.com83921382011-01-08 05:46:00 +0000213std::size_t IndexDataManager::indexSize(D3DFORMAT format) const
daniel@transgaming.comf8b58a02010-03-26 04:08:45 +0000214{
daniel@transgaming.com83921382011-01-08 05:46:00 +0000215 return (format == D3DFMT_INDEX32) ? sizeof(unsigned int) : sizeof(unsigned short);
daniel@transgaming.com3e4c6002010-05-05 18:50:13 +0000216}
217
daniel@transgaming.com41d8dd82010-05-12 03:45:03 +0000218std::size_t IndexDataManager::typeSize(GLenum type) const
219{
220 switch (type)
221 {
daniel@transgaming.com83921382011-01-08 05:46:00 +0000222 case GL_UNSIGNED_INT: return sizeof(GLuint);
daniel@transgaming.com41d8dd82010-05-12 03:45:03 +0000223 case GL_UNSIGNED_SHORT: return sizeof(GLushort);
daniel@transgaming.com83921382011-01-08 05:46:00 +0000224 case GL_UNSIGNED_BYTE: return sizeof(GLubyte);
225 default: UNREACHABLE(); return sizeof(GLushort);
daniel@transgaming.com41d8dd82010-05-12 03:45:03 +0000226 }
227}
228
daniel@transgaming.comf6549452012-01-27 15:39:08 +0000229StaticIndexBuffer *IndexDataManager::getCountingIndices(GLsizei count)
230{
daniel@transgaming.com0f328a72012-03-05 15:07:50 +0000231 if (count <= 65536) // 16-bit indices
daniel@transgaming.comf6549452012-01-27 15:39:08 +0000232 {
233 const unsigned int spaceNeeded = count * sizeof(unsigned short);
234
235 if (!mCountingBuffer || mCountingBuffer->size() < spaceNeeded)
236 {
237 delete mCountingBuffer;
daniel@transgaming.com6716a272012-10-31 18:31:39 +0000238 mCountingBuffer = new StaticIndexBuffer(mRenderer);
daniel@transgaming.comf6549452012-01-27 15:39:08 +0000239 mCountingBuffer->reserveSpace(spaceNeeded, GL_UNSIGNED_SHORT);
240
241 UINT offset;
242 unsigned short *data = static_cast<unsigned short*>(mCountingBuffer->map(spaceNeeded, &offset));
daniel@transgaming.com50aadb02012-11-28 21:06:11 +0000243
daniel@transgaming.comf6549452012-01-27 15:39:08 +0000244 if (data)
245 {
246 for(int i = 0; i < count; i++)
247 {
248 data[i] = i;
249 }
250
251 mCountingBuffer->unmap();
252 }
253 }
254 }
255 else if (mStreamingBufferInt) // 32-bit indices supported
256 {
257 const unsigned int spaceNeeded = count * sizeof(unsigned int);
258
259 if (!mCountingBuffer || mCountingBuffer->size() < spaceNeeded)
260 {
261 delete mCountingBuffer;
daniel@transgaming.com6716a272012-10-31 18:31:39 +0000262 mCountingBuffer = new StaticIndexBuffer(mRenderer);
daniel@transgaming.comf6549452012-01-27 15:39:08 +0000263 mCountingBuffer->reserveSpace(spaceNeeded, GL_UNSIGNED_INT);
264
265 UINT offset;
266 unsigned int *data = static_cast<unsigned int*>(mCountingBuffer->map(spaceNeeded, &offset));
daniel@transgaming.com50aadb02012-11-28 21:06:11 +0000267
daniel@transgaming.comf6549452012-01-27 15:39:08 +0000268 if (data)
269 {
270 for(int i = 0; i < count; i++)
271 {
272 data[i] = i;
273 }
daniel@transgaming.com50aadb02012-11-28 21:06:11 +0000274
daniel@transgaming.comf6549452012-01-27 15:39:08 +0000275 mCountingBuffer->unmap();
276 }
277 }
278 }
279 else return NULL;
daniel@transgaming.com50aadb02012-11-28 21:06:11 +0000280
daniel@transgaming.comf6549452012-01-27 15:39:08 +0000281 return mCountingBuffer;
282}
283
daniel@transgaming.com76d3e6e2012-10-31 19:55:33 +0000284IndexBuffer::IndexBuffer(rx::Renderer9 *renderer, UINT size, D3DFORMAT format) : mRenderer(renderer), mBufferSize(size), mIndexBuffer(NULL)
daniel@transgaming.com3e4c6002010-05-05 18:50:13 +0000285{
daniel@transgaming.com83921382011-01-08 05:46:00 +0000286 if (size > 0)
287 {
daniel@transgaming.com621ce052012-10-31 17:52:29 +0000288 // D3D9_REPLACE
daniel@transgaming.com113f0eb2012-10-31 18:46:58 +0000289 HRESULT result = mRenderer->createIndexBuffer(size, D3DUSAGE_DYNAMIC | D3DUSAGE_WRITEONLY, format, &mIndexBuffer);
jbauman@chromium.orgd8f3faa2011-09-02 01:10:47 +0000290 mSerial = issueSerial();
daniel@transgaming.com83921382011-01-08 05:46:00 +0000291
292 if (FAILED(result))
293 {
294 ERR("Out of memory allocating an index buffer of size %lu.", size);
295 }
296 }
daniel@transgaming.com3e4c6002010-05-05 18:50:13 +0000297}
298
daniel@transgaming.com83921382011-01-08 05:46:00 +0000299IndexBuffer::~IndexBuffer()
daniel@transgaming.com3e4c6002010-05-05 18:50:13 +0000300{
daniel@transgaming.com83921382011-01-08 05:46:00 +0000301 if (mIndexBuffer)
daniel@transgaming.com3e4c6002010-05-05 18:50:13 +0000302 {
daniel@transgaming.com83921382011-01-08 05:46:00 +0000303 mIndexBuffer->Release();
daniel@transgaming.com3e4c6002010-05-05 18:50:13 +0000304 }
daniel@transgaming.comf8b58a02010-03-26 04:08:45 +0000305}
306
daniel@transgaming.com83921382011-01-08 05:46:00 +0000307IDirect3DIndexBuffer9 *IndexBuffer::getBuffer() const
daniel@transgaming.com81655a72010-05-20 19:18:17 +0000308{
daniel@transgaming.com83921382011-01-08 05:46:00 +0000309 return mIndexBuffer;
310}
daniel@transgaming.com81655a72010-05-20 19:18:17 +0000311
jbauman@chromium.orgd8f3faa2011-09-02 01:10:47 +0000312unsigned int IndexBuffer::getSerial() const
313{
314 return mSerial;
315}
316
317unsigned int IndexBuffer::issueSerial()
318{
319 return mCurrentSerial++;
320}
321
daniel@transgaming.com83921382011-01-08 05:46:00 +0000322void IndexBuffer::unmap()
323{
324 if (mIndexBuffer)
daniel@transgaming.com81655a72010-05-20 19:18:17 +0000325 {
daniel@transgaming.com83921382011-01-08 05:46:00 +0000326 mIndexBuffer->Unlock();
daniel@transgaming.com81655a72010-05-20 19:18:17 +0000327 }
daniel@transgaming.com83921382011-01-08 05:46:00 +0000328}
329
daniel@transgaming.com76d3e6e2012-10-31 19:55:33 +0000330StreamingIndexBuffer::StreamingIndexBuffer(rx::Renderer9 *renderer, UINT initialSize, D3DFORMAT format) : IndexBuffer(renderer, initialSize, format)
daniel@transgaming.com83921382011-01-08 05:46:00 +0000331{
332 mWritePosition = 0;
333}
334
335StreamingIndexBuffer::~StreamingIndexBuffer()
336{
337}
338
339void *StreamingIndexBuffer::map(UINT requiredSpace, UINT *offset)
340{
341 void *mapPtr = NULL;
342
343 if (mIndexBuffer)
daniel@transgaming.com81655a72010-05-20 19:18:17 +0000344 {
daniel@transgaming.com83921382011-01-08 05:46:00 +0000345 HRESULT result = mIndexBuffer->Lock(mWritePosition, requiredSpace, &mapPtr, D3DLOCK_NOOVERWRITE);
daniel@transgaming.com50aadb02012-11-28 21:06:11 +0000346
daniel@transgaming.com83921382011-01-08 05:46:00 +0000347 if (FAILED(result))
apatrick@chromium.orgf99fbb72010-11-16 01:57:05 +0000348 {
daniel@transgaming.com83921382011-01-08 05:46:00 +0000349 ERR(" Lock failed with error 0x%08x", result);
350 return NULL;
apatrick@chromium.orgf99fbb72010-11-16 01:57:05 +0000351 }
daniel@transgaming.com81655a72010-05-20 19:18:17 +0000352
daniel@transgaming.com83921382011-01-08 05:46:00 +0000353 *offset = mWritePosition;
354 mWritePosition += requiredSpace;
daniel@transgaming.com81655a72010-05-20 19:18:17 +0000355 }
356
daniel@transgaming.com83921382011-01-08 05:46:00 +0000357 return mapPtr;
358}
daniel@transgaming.com81655a72010-05-20 19:18:17 +0000359
daniel@transgaming.com83921382011-01-08 05:46:00 +0000360void StreamingIndexBuffer::reserveSpace(UINT requiredSpace, GLenum type)
361{
362 if (requiredSpace > mBufferSize)
363 {
364 if (mIndexBuffer)
365 {
366 mIndexBuffer->Release();
367 mIndexBuffer = NULL;
368 }
369
370 mBufferSize = std::max(requiredSpace, 2 * mBufferSize);
371
daniel@transgaming.com621ce052012-10-31 17:52:29 +0000372 // D3D9_REPLACE
daniel@transgaming.com113f0eb2012-10-31 18:46:58 +0000373 HRESULT result = mRenderer->createIndexBuffer(mBufferSize, D3DUSAGE_DYNAMIC | D3DUSAGE_WRITEONLY, type == GL_UNSIGNED_INT ? D3DFMT_INDEX32 : D3DFMT_INDEX16, &mIndexBuffer);
jbauman@chromium.orgd8f3faa2011-09-02 01:10:47 +0000374 mSerial = issueSerial();
daniel@transgaming.com50aadb02012-11-28 21:06:11 +0000375
daniel@transgaming.com83921382011-01-08 05:46:00 +0000376 if (FAILED(result))
377 {
378 ERR("Out of memory allocating a vertex buffer of size %lu.", mBufferSize);
379 }
380
381 mWritePosition = 0;
382 }
383 else if (mWritePosition + requiredSpace > mBufferSize) // Recycle
384 {
385 void *dummy;
386 mIndexBuffer->Lock(0, 1, &dummy, D3DLOCK_DISCARD);
387 mIndexBuffer->Unlock();
388
389 mWritePosition = 0;
390 }
391}
392
daniel@transgaming.com76d3e6e2012-10-31 19:55:33 +0000393StaticIndexBuffer::StaticIndexBuffer(rx::Renderer9 *renderer) : IndexBuffer(renderer, 0, D3DFMT_UNKNOWN)
daniel@transgaming.com83921382011-01-08 05:46:00 +0000394{
395 mCacheType = GL_NONE;
396}
397
398StaticIndexBuffer::~StaticIndexBuffer()
399{
400}
401
402void *StaticIndexBuffer::map(UINT requiredSpace, UINT *offset)
403{
404 void *mapPtr = NULL;
405
406 if (mIndexBuffer)
407 {
408 HRESULT result = mIndexBuffer->Lock(0, requiredSpace, &mapPtr, 0);
daniel@transgaming.com50aadb02012-11-28 21:06:11 +0000409
daniel@transgaming.com83921382011-01-08 05:46:00 +0000410 if (FAILED(result))
411 {
412 ERR(" Lock failed with error 0x%08x", result);
413 return NULL;
414 }
415
416 *offset = 0;
417 }
418
419 return mapPtr;
420}
421
422void StaticIndexBuffer::reserveSpace(UINT requiredSpace, GLenum type)
423{
424 if (!mIndexBuffer && mBufferSize == 0)
425 {
daniel@transgaming.com621ce052012-10-31 17:52:29 +0000426 // D3D9_REPLACE
daniel@transgaming.com113f0eb2012-10-31 18:46:58 +0000427 HRESULT result = mRenderer->createIndexBuffer(requiredSpace, D3DUSAGE_WRITEONLY, type == GL_UNSIGNED_INT ? D3DFMT_INDEX32 : D3DFMT_INDEX16, &mIndexBuffer);
jbauman@chromium.orgd8f3faa2011-09-02 01:10:47 +0000428 mSerial = issueSerial();
daniel@transgaming.com50aadb02012-11-28 21:06:11 +0000429
daniel@transgaming.com83921382011-01-08 05:46:00 +0000430 if (FAILED(result))
431 {
432 ERR("Out of memory allocating a vertex buffer of size %lu.", mBufferSize);
433 }
434
435 mBufferSize = requiredSpace;
436 mCacheType = type;
437 }
438 else if (mIndexBuffer && mBufferSize >= requiredSpace && mCacheType == type)
439 {
440 // Already allocated
441 }
442 else UNREACHABLE(); // Static index buffers can't be resized
443}
444
445bool StaticIndexBuffer::lookupType(GLenum type)
446{
447 return mCacheType == type;
448}
449
450UINT StaticIndexBuffer::lookupRange(intptr_t offset, GLsizei count, UINT *minIndex, UINT *maxIndex)
451{
jbauman@chromium.org43cbe742011-09-01 22:09:40 +0000452 IndexRange range = {offset, count};
daniel@transgaming.com83921382011-01-08 05:46:00 +0000453
jbauman@chromium.org43cbe742011-09-01 22:09:40 +0000454 std::map<IndexRange, IndexResult>::iterator res = mCache.find(range);
daniel@transgaming.com50aadb02012-11-28 21:06:11 +0000455
jbauman@chromium.org43cbe742011-09-01 22:09:40 +0000456 if (res == mCache.end())
457 {
458 return -1;
daniel@transgaming.com83921382011-01-08 05:46:00 +0000459 }
460
jbauman@chromium.org43cbe742011-09-01 22:09:40 +0000461 *minIndex = res->second.minIndex;
462 *maxIndex = res->second.maxIndex;
463 return res->second.streamOffset;
daniel@transgaming.com83921382011-01-08 05:46:00 +0000464}
465
466void StaticIndexBuffer::addRange(intptr_t offset, GLsizei count, UINT minIndex, UINT maxIndex, UINT streamOffset)
467{
jbauman@chromium.org43cbe742011-09-01 22:09:40 +0000468 IndexRange indexRange = {offset, count};
469 IndexResult indexResult = {minIndex, maxIndex, streamOffset};
470 mCache[indexRange] = indexResult;
daniel@transgaming.com81655a72010-05-20 19:18:17 +0000471}
472
daniel@transgaming.comf8b58a02010-03-26 04:08:45 +0000473}