blob: 8e5ea881b2d5a4b391bcca8d1848a232dcb108d3 [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{
42 GLuint minIndexSoFar = *in;
43 GLuint maxIndexSoFar = *in;
44
45 for (GLsizei i = 0; i < count; i++)
46 {
47 if (minIndexSoFar > *in) minIndexSoFar = *in;
48 if (maxIndexSoFar < *in) maxIndexSoFar = *in;
49
50 *out++ = *in++;
51 }
52
53 *minIndex = minIndexSoFar;
54 *maxIndex = maxIndexSoFar;
55}
56
57}
58
59TranslatedIndexData IndexDataManager::preRenderValidate(GLenum mode, GLenum type, GLsizei count, Buffer *arrayElementBuffer, const void *indices)
60{
61 ASSERT(type == GL_UNSIGNED_SHORT || type == GL_UNSIGNED_BYTE);
62 ASSERT(count > 0);
63
64 TranslatedIndexData translated;
65
66 translated.count = count;
67
68 std::size_t requiredSpace = spaceRequired(mode, type, count);
69
70 if (requiredSpace > mStreamBuffer->size())
71 {
72 std::size_t newSize = std::max(requiredSpace, 2 * mStreamBuffer->size());
73
74 TranslatedIndexBuffer *newStreamBuffer = mBackend->createIndexBuffer(newSize);
75
76 delete mStreamBuffer;
77 mStreamBuffer = newStreamBuffer;
78 }
79
80 mStreamBuffer->reserveSpace(requiredSpace);
81
82 size_t offset;
83 void *output = mStreamBuffer->map(requiredSpace, &offset);
84
85 translated.buffer = mStreamBuffer;
86 translated.offset = offset;
87
88 translated.indices = static_cast<const Index*>(output);
89
90 if (arrayElementBuffer != NULL)
91 {
92 indices = static_cast<const GLubyte*>(arrayElementBuffer->data()) + reinterpret_cast<GLsizei>(indices);
93 }
94
95 Index *out = static_cast<Index*>(output);
96
97 if (type == GL_UNSIGNED_SHORT)
98 {
99 const GLushort *in = static_cast<const GLushort*>(indices);
100
101 copyIndices(in, count, out, &translated.minIndex, &translated.maxIndex);
102 }
103 else
104 {
105 const GLubyte *in = static_cast<const GLubyte*>(indices);
106
107 copyIndices(in, count, out, &translated.minIndex, &translated.maxIndex);
108 }
109
110 mStreamBuffer->unmap();
111
112 return translated;
113}
114
115std::size_t IndexDataManager::spaceRequired(GLenum mode, GLenum type, GLsizei count)
116{
117 return count * sizeof(Index);
118}
119
120}