blob: 301572382fcae462b19b61a8d3d4547a6ad981cb [file] [log] [blame]
daniel@transgaming.comf8b58a02010-03-26 04:08:45 +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/IndexDataManager.cpp: Defines the IndexDataManager, a class that
8// runs the Buffer translation process for index buffers.
9
daniel@transgaming.combbf56f72010-04-20 18:52:13 +000010#include "libGLESv2/geometry/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"
15#include "libGLESv2/geometry/backend.h"
daniel@transgaming.comf8b58a02010-03-26 04:08:45 +000016
17namespace
18{
daniel@transgaming.com3e4c6002010-05-05 18:50:13 +000019 enum { INITIAL_INDEX_BUFFER_SIZE = 4096 * sizeof(GLuint) };
daniel@transgaming.comf8b58a02010-03-26 04:08:45 +000020}
21
22namespace gl
23{
24
25IndexDataManager::IndexDataManager(Context *context, BufferBackEnd *backend)
daniel@transgaming.com3e4c6002010-05-05 18:50:13 +000026 : mContext(context), mBackend(backend), mIntIndicesSupported(backend->supportIntIndices())
daniel@transgaming.comf8b58a02010-03-26 04:08:45 +000027{
daniel@transgaming.com3e4c6002010-05-05 18:50:13 +000028 mStreamBufferShort = mBackend->createIndexBuffer(INITIAL_INDEX_BUFFER_SIZE, GL_UNSIGNED_SHORT);
29
30 if (mIntIndicesSupported)
31 {
32 mStreamBufferInt = mBackend->createIndexBuffer(INITIAL_INDEX_BUFFER_SIZE, GL_UNSIGNED_INT);
33 }
34 else
35 {
36 mStreamBufferInt = NULL;
37 }
daniel@transgaming.comf8b58a02010-03-26 04:08:45 +000038}
39
40IndexDataManager::~IndexDataManager()
41{
daniel@transgaming.com3e4c6002010-05-05 18:50:13 +000042 delete mStreamBufferShort;
43 delete mStreamBufferInt;
daniel@transgaming.comf8b58a02010-03-26 04:08:45 +000044}
45
46namespace
47{
48
daniel@transgaming.com3e4c6002010-05-05 18:50:13 +000049template <class InputIndexType, class OutputIndexType>
50void copyIndices(const InputIndexType *in, GLsizei count, OutputIndexType *out, GLuint *minIndex, GLuint *maxIndex)
daniel@transgaming.comf8b58a02010-03-26 04:08:45 +000051{
daniel@transgaming.com3e4c6002010-05-05 18:50:13 +000052 InputIndexType first = *in;
daniel@transgaming.combf2b52a2010-04-20 18:53:03 +000053 GLuint minIndexSoFar = first;
54 GLuint maxIndexSoFar = first;
daniel@transgaming.comf8b58a02010-03-26 04:08:45 +000055
56 for (GLsizei i = 0; i < count; i++)
57 {
58 if (minIndexSoFar > *in) minIndexSoFar = *in;
59 if (maxIndexSoFar < *in) maxIndexSoFar = *in;
60
61 *out++ = *in++;
62 }
63
daniel@transgaming.combf2b52a2010-04-20 18:53:03 +000064 // It might be a line loop, so copy the loop index.
65 *out = first;
66
daniel@transgaming.comf8b58a02010-03-26 04:08:45 +000067 *minIndex = minIndexSoFar;
68 *maxIndex = maxIndexSoFar;
69}
70
71}
72
73TranslatedIndexData IndexDataManager::preRenderValidate(GLenum mode, GLenum type, GLsizei count, Buffer *arrayElementBuffer, const void *indices)
74{
daniel@transgaming.com3e4c6002010-05-05 18:50:13 +000075 ASSERT(type == GL_UNSIGNED_SHORT || type == GL_UNSIGNED_BYTE || type == GL_UNSIGNED_INT);
daniel@transgaming.comf8b58a02010-03-26 04:08:45 +000076 ASSERT(count > 0);
77
78 TranslatedIndexData translated;
79
80 translated.count = count;
81
daniel@transgaming.combf2b52a2010-04-20 18:53:03 +000082 std::size_t requiredSpace = spaceRequired(type, count);
daniel@transgaming.comf8b58a02010-03-26 04:08:45 +000083
daniel@transgaming.com3e4c6002010-05-05 18:50:13 +000084 TranslatedIndexBuffer *streamIb = prepareIndexBuffer(type, requiredSpace);
daniel@transgaming.comf8b58a02010-03-26 04:08:45 +000085
86 size_t offset;
daniel@transgaming.com3e4c6002010-05-05 18:50:13 +000087 void *output = streamIb->map(requiredSpace, &offset);
daniel@transgaming.comf8b58a02010-03-26 04:08:45 +000088
daniel@transgaming.com3e4c6002010-05-05 18:50:13 +000089 translated.buffer = streamIb;
daniel@transgaming.comf8b58a02010-03-26 04:08:45 +000090 translated.offset = offset;
daniel@transgaming.com3e4c6002010-05-05 18:50:13 +000091 translated.indexSize = indexSize(type);
daniel@transgaming.comf8b58a02010-03-26 04:08:45 +000092
daniel@transgaming.com3e4c6002010-05-05 18:50:13 +000093 translated.indices = output;
daniel@transgaming.comf8b58a02010-03-26 04:08:45 +000094
95 if (arrayElementBuffer != NULL)
96 {
97 indices = static_cast<const GLubyte*>(arrayElementBuffer->data()) + reinterpret_cast<GLsizei>(indices);
98 }
99
daniel@transgaming.com3e4c6002010-05-05 18:50:13 +0000100 if (type == GL_UNSIGNED_BYTE)
daniel@transgaming.comf8b58a02010-03-26 04:08:45 +0000101 {
daniel@transgaming.com3e4c6002010-05-05 18:50:13 +0000102 const GLubyte *in = static_cast<const GLubyte*>(indices);
103 GLushort *out = static_cast<GLushort*>(output);
daniel@transgaming.comf8b58a02010-03-26 04:08:45 +0000104
105 copyIndices(in, count, out, &translated.minIndex, &translated.maxIndex);
106 }
daniel@transgaming.com3e4c6002010-05-05 18:50:13 +0000107 else if (type == GL_UNSIGNED_INT)
108 {
109 const GLuint *in = static_cast<const GLuint*>(indices);
110
111 if (mIntIndicesSupported)
112 {
113 GLuint *out = static_cast<GLuint*>(output);
114
115 copyIndices(in, count, out, &translated.minIndex, &translated.maxIndex);
116 }
117 else
118 {
119 // When 32-bit indices are unsupported, fake them by truncating to 16-bit.
120
121 GLushort *out = static_cast<GLushort*>(output);
122
123 copyIndices(in, count, out, &translated.minIndex, &translated.maxIndex);
124 }
125 }
daniel@transgaming.comf8b58a02010-03-26 04:08:45 +0000126 else
127 {
daniel@transgaming.com3e4c6002010-05-05 18:50:13 +0000128 const GLushort *in = static_cast<const GLushort*>(indices);
129 GLushort *out = static_cast<GLushort*>(output);
daniel@transgaming.comf8b58a02010-03-26 04:08:45 +0000130
131 copyIndices(in, count, out, &translated.minIndex, &translated.maxIndex);
132 }
133
daniel@transgaming.com3e4c6002010-05-05 18:50:13 +0000134 streamIb->unmap();
daniel@transgaming.comf8b58a02010-03-26 04:08:45 +0000135
136 return translated;
137}
138
daniel@transgaming.com3e4c6002010-05-05 18:50:13 +0000139std::size_t IndexDataManager::indexSize(GLenum type) const
daniel@transgaming.comf8b58a02010-03-26 04:08:45 +0000140{
daniel@transgaming.com3e4c6002010-05-05 18:50:13 +0000141 return (type == GL_UNSIGNED_INT && mIntIndicesSupported) ? sizeof(GLuint) : sizeof(GLushort);
142}
143
144std::size_t IndexDataManager::spaceRequired(GLenum type, GLsizei count) const
145{
146 return (count + 1) * indexSize(type); // +1 because we always leave an extra for line loops
147}
148
149TranslatedIndexBuffer *IndexDataManager::prepareIndexBuffer(GLenum type, std::size_t requiredSpace)
150{
151 bool use32 = (type == GL_UNSIGNED_INT && mIntIndicesSupported);
152
153 TranslatedIndexBuffer *streamIb = use32 ? mStreamBufferInt : mStreamBufferShort;
154
155 if (requiredSpace > streamIb->size())
156 {
157 std::size_t newSize = std::max(requiredSpace, 2 * streamIb->size());
158
159 TranslatedIndexBuffer *newStreamBuffer = mBackend->createIndexBuffer(newSize, use32 ? GL_UNSIGNED_INT : GL_UNSIGNED_SHORT);
160
161 delete streamIb;
162
163 streamIb = newStreamBuffer;
164
165 if (use32)
166 {
167 mStreamBufferInt = streamIb;
168 }
169 else
170 {
171 mStreamBufferShort = streamIb;
172 }
173 }
174
175 streamIb->reserveSpace(requiredSpace);
176
177 return streamIb;
daniel@transgaming.comf8b58a02010-03-26 04:08:45 +0000178}
179
180}