blob: e50ca6bb3735c45f64ef475508295221bd3a57ce [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{
19 enum { INITIAL_INDEX_BUFFER_SIZE = sizeof(gl::Index) * 8192 };
20}
21
22namespace gl
23{
24
25IndexDataManager::IndexDataManager(Context *context, BufferBackEnd *backend)
26 : mContext(context), mBackend(backend)
27{
28 mStreamBuffer = mBackend->createIndexBuffer(INITIAL_INDEX_BUFFER_SIZE);
29}
30
31IndexDataManager::~IndexDataManager()
32{
33 delete mStreamBuffer;
34}
35
36namespace
37{
38
39template <class InputIndexType>
40void copyIndices(const InputIndexType *in, GLsizei count, Index *out, GLuint *minIndex, GLuint *maxIndex)
41{
daniel@transgaming.combf2b52a2010-04-20 18:53:03 +000042 Index first = *in;
43 GLuint minIndexSoFar = first;
44 GLuint maxIndexSoFar = first;
daniel@transgaming.comf8b58a02010-03-26 04:08:45 +000045
46 for (GLsizei i = 0; i < count; i++)
47 {
48 if (minIndexSoFar > *in) minIndexSoFar = *in;
49 if (maxIndexSoFar < *in) maxIndexSoFar = *in;
50
51 *out++ = *in++;
52 }
53
daniel@transgaming.combf2b52a2010-04-20 18:53:03 +000054 // It might be a line loop, so copy the loop index.
55 *out = first;
56
daniel@transgaming.comf8b58a02010-03-26 04:08:45 +000057 *minIndex = minIndexSoFar;
58 *maxIndex = maxIndexSoFar;
59}
60
61}
62
63TranslatedIndexData IndexDataManager::preRenderValidate(GLenum mode, GLenum type, GLsizei count, Buffer *arrayElementBuffer, const void *indices)
64{
65 ASSERT(type == GL_UNSIGNED_SHORT || type == GL_UNSIGNED_BYTE);
66 ASSERT(count > 0);
67
68 TranslatedIndexData translated;
69
70 translated.count = count;
71
daniel@transgaming.combf2b52a2010-04-20 18:53:03 +000072 std::size_t requiredSpace = spaceRequired(type, count);
daniel@transgaming.comf8b58a02010-03-26 04:08:45 +000073
74 if (requiredSpace > mStreamBuffer->size())
75 {
76 std::size_t newSize = std::max(requiredSpace, 2 * mStreamBuffer->size());
77
78 TranslatedIndexBuffer *newStreamBuffer = mBackend->createIndexBuffer(newSize);
79
80 delete mStreamBuffer;
81 mStreamBuffer = newStreamBuffer;
82 }
83
84 mStreamBuffer->reserveSpace(requiredSpace);
85
86 size_t offset;
87 void *output = mStreamBuffer->map(requiredSpace, &offset);
88
89 translated.buffer = mStreamBuffer;
90 translated.offset = offset;
91
92 translated.indices = static_cast<const Index*>(output);
93
94 if (arrayElementBuffer != NULL)
95 {
96 indices = static_cast<const GLubyte*>(arrayElementBuffer->data()) + reinterpret_cast<GLsizei>(indices);
97 }
98
99 Index *out = static_cast<Index*>(output);
100
101 if (type == GL_UNSIGNED_SHORT)
102 {
103 const GLushort *in = static_cast<const GLushort*>(indices);
104
105 copyIndices(in, count, out, &translated.minIndex, &translated.maxIndex);
106 }
107 else
108 {
109 const GLubyte *in = static_cast<const GLubyte*>(indices);
110
111 copyIndices(in, count, out, &translated.minIndex, &translated.maxIndex);
112 }
113
114 mStreamBuffer->unmap();
115
116 return translated;
117}
118
daniel@transgaming.combf2b52a2010-04-20 18:53:03 +0000119std::size_t IndexDataManager::spaceRequired(GLenum type, GLsizei count)
daniel@transgaming.comf8b58a02010-03-26 04:08:45 +0000120{
daniel@transgaming.combf2b52a2010-04-20 18:53:03 +0000121 return (count + 1) * sizeof(Index); // +1 because we always leave an extra for line loops
daniel@transgaming.comf8b58a02010-03-26 04:08:45 +0000122}
123
124}