1bdf2d80f459d43f5a6df074431bacf41584f81b7shannon.woods@transgaming.com#include "precompiled.h"
2955377ebef0134a7258a8b690853bccb705e9ad3daniel@transgaming.com//
3955377ebef0134a7258a8b690853bccb705e9ad3daniel@transgaming.com// Copyright (c) 2002-2012 The ANGLE Project Authors. All rights reserved.
4955377ebef0134a7258a8b690853bccb705e9ad3daniel@transgaming.com// Use of this source code is governed by a BSD-style license that can be
5955377ebef0134a7258a8b690853bccb705e9ad3daniel@transgaming.com// found in the LICENSE file.
6955377ebef0134a7258a8b690853bccb705e9ad3daniel@transgaming.com//
7955377ebef0134a7258a8b690853bccb705e9ad3daniel@transgaming.com
8955377ebef0134a7258a8b690853bccb705e9ad3daniel@transgaming.com// IndexBuffer.cpp: Defines the abstract IndexBuffer class and IndexBufferInterface
9955377ebef0134a7258a8b690853bccb705e9ad3daniel@transgaming.com// class with derivations, classes that perform graphics API agnostic index buffer operations.
10955377ebef0134a7258a8b690853bccb705e9ad3daniel@transgaming.com
11955377ebef0134a7258a8b690853bccb705e9ad3daniel@transgaming.com#include "libGLESv2/renderer/IndexBuffer.h"
12486d9e9b6b4ed31f66d2624b8e822020fe40a1f7shannon.woods@transgaming.com#include "libGLESv2/renderer/Renderer.h"
13955377ebef0134a7258a8b690853bccb705e9ad3daniel@transgaming.com
14955377ebef0134a7258a8b690853bccb705e9ad3daniel@transgaming.comnamespace rx
15955377ebef0134a7258a8b690853bccb705e9ad3daniel@transgaming.com{
16955377ebef0134a7258a8b690853bccb705e9ad3daniel@transgaming.com
172befccdf021fe2962f6cfd6f0ffb541954390d78daniel@transgaming.comunsigned int IndexBuffer::mNextSerial = 1;
182befccdf021fe2962f6cfd6f0ffb541954390d78daniel@transgaming.com
192befccdf021fe2962f6cfd6f0ffb541954390d78daniel@transgaming.comIndexBuffer::IndexBuffer()
202befccdf021fe2962f6cfd6f0ffb541954390d78daniel@transgaming.com{
212befccdf021fe2962f6cfd6f0ffb541954390d78daniel@transgaming.com    updateSerial();
222befccdf021fe2962f6cfd6f0ffb541954390d78daniel@transgaming.com}
232befccdf021fe2962f6cfd6f0ffb541954390d78daniel@transgaming.com
242befccdf021fe2962f6cfd6f0ffb541954390d78daniel@transgaming.comIndexBuffer::~IndexBuffer()
252befccdf021fe2962f6cfd6f0ffb541954390d78daniel@transgaming.com{
262befccdf021fe2962f6cfd6f0ffb541954390d78daniel@transgaming.com}
272befccdf021fe2962f6cfd6f0ffb541954390d78daniel@transgaming.com
282befccdf021fe2962f6cfd6f0ffb541954390d78daniel@transgaming.comunsigned int IndexBuffer::getSerial() const
292befccdf021fe2962f6cfd6f0ffb541954390d78daniel@transgaming.com{
302befccdf021fe2962f6cfd6f0ffb541954390d78daniel@transgaming.com    return mSerial;
312befccdf021fe2962f6cfd6f0ffb541954390d78daniel@transgaming.com}
322befccdf021fe2962f6cfd6f0ffb541954390d78daniel@transgaming.com
332befccdf021fe2962f6cfd6f0ffb541954390d78daniel@transgaming.comvoid IndexBuffer::updateSerial()
342befccdf021fe2962f6cfd6f0ffb541954390d78daniel@transgaming.com{
352befccdf021fe2962f6cfd6f0ffb541954390d78daniel@transgaming.com    mSerial = mNextSerial++;
362befccdf021fe2962f6cfd6f0ffb541954390d78daniel@transgaming.com}
372befccdf021fe2962f6cfd6f0ffb541954390d78daniel@transgaming.com
382befccdf021fe2962f6cfd6f0ffb541954390d78daniel@transgaming.com
391e3a80411aa79afd2fbe1eeff66b28d2049a5814daniel@transgaming.comIndexBufferInterface::IndexBufferInterface(Renderer *renderer, bool dynamic) : mRenderer(renderer)
40955377ebef0134a7258a8b690853bccb705e9ad3daniel@transgaming.com{
411e3a80411aa79afd2fbe1eeff66b28d2049a5814daniel@transgaming.com    mIndexBuffer = renderer->createIndexBuffer();
42955377ebef0134a7258a8b690853bccb705e9ad3daniel@transgaming.com
431e3a80411aa79afd2fbe1eeff66b28d2049a5814daniel@transgaming.com    mDynamic = dynamic;
441e3a80411aa79afd2fbe1eeff66b28d2049a5814daniel@transgaming.com    mWritePosition = 0;
45955377ebef0134a7258a8b690853bccb705e9ad3daniel@transgaming.com}
46955377ebef0134a7258a8b690853bccb705e9ad3daniel@transgaming.com
4750cc725131415c0448592104ae2ad5f2079ebc1bdaniel@transgaming.comIndexBufferInterface::~IndexBufferInterface()
48955377ebef0134a7258a8b690853bccb705e9ad3daniel@transgaming.com{
49955377ebef0134a7258a8b690853bccb705e9ad3daniel@transgaming.com    if (mIndexBuffer)
50955377ebef0134a7258a8b690853bccb705e9ad3daniel@transgaming.com    {
511e3a80411aa79afd2fbe1eeff66b28d2049a5814daniel@transgaming.com        delete mIndexBuffer;
52955377ebef0134a7258a8b690853bccb705e9ad3daniel@transgaming.com    }
53955377ebef0134a7258a8b690853bccb705e9ad3daniel@transgaming.com}
54955377ebef0134a7258a8b690853bccb705e9ad3daniel@transgaming.com
551e3a80411aa79afd2fbe1eeff66b28d2049a5814daniel@transgaming.comGLenum IndexBufferInterface::getIndexType() const
56955377ebef0134a7258a8b690853bccb705e9ad3daniel@transgaming.com{
571e3a80411aa79afd2fbe1eeff66b28d2049a5814daniel@transgaming.com    return mIndexBuffer->getIndexType();
58955377ebef0134a7258a8b690853bccb705e9ad3daniel@transgaming.com}
59955377ebef0134a7258a8b690853bccb705e9ad3daniel@transgaming.com
601e3a80411aa79afd2fbe1eeff66b28d2049a5814daniel@transgaming.comunsigned int IndexBufferInterface::getBufferSize() const
61955377ebef0134a7258a8b690853bccb705e9ad3daniel@transgaming.com{
621e3a80411aa79afd2fbe1eeff66b28d2049a5814daniel@transgaming.com    return mIndexBuffer->getBufferSize();
63955377ebef0134a7258a8b690853bccb705e9ad3daniel@transgaming.com}
64955377ebef0134a7258a8b690853bccb705e9ad3daniel@transgaming.com
651e3a80411aa79afd2fbe1eeff66b28d2049a5814daniel@transgaming.comunsigned int IndexBufferInterface::getSerial() const
66955377ebef0134a7258a8b690853bccb705e9ad3daniel@transgaming.com{
671e3a80411aa79afd2fbe1eeff66b28d2049a5814daniel@transgaming.com    return mIndexBuffer->getSerial();
68955377ebef0134a7258a8b690853bccb705e9ad3daniel@transgaming.com}
69955377ebef0134a7258a8b690853bccb705e9ad3daniel@transgaming.com
70a36ead4a7d5641181ab994a13b7d5027c1b5bd07Geoff Langbool IndexBufferInterface::mapBuffer(unsigned int size, void** outMappedMemory, unsigned int *streamOffset)
71955377ebef0134a7258a8b690853bccb705e9ad3daniel@transgaming.com{
72a36ead4a7d5641181ab994a13b7d5027c1b5bd07Geoff Lang    // Protect against integer overflow
73a36ead4a7d5641181ab994a13b7d5027c1b5bd07Geoff Lang    if (mWritePosition + size < mWritePosition)
74a36ead4a7d5641181ab994a13b7d5027c1b5bd07Geoff Lang    {
75a36ead4a7d5641181ab994a13b7d5027c1b5bd07Geoff Lang        return false;
76a36ead4a7d5641181ab994a13b7d5027c1b5bd07Geoff Lang    }
77a36ead4a7d5641181ab994a13b7d5027c1b5bd07Geoff Lang
781e3a80411aa79afd2fbe1eeff66b28d2049a5814daniel@transgaming.com    if (!mIndexBuffer->mapBuffer(mWritePosition, size, outMappedMemory))
79955377ebef0134a7258a8b690853bccb705e9ad3daniel@transgaming.com    {
80a36ead4a7d5641181ab994a13b7d5027c1b5bd07Geoff Lang        if (outMappedMemory)
81a36ead4a7d5641181ab994a13b7d5027c1b5bd07Geoff Lang        {
82a36ead4a7d5641181ab994a13b7d5027c1b5bd07Geoff Lang            *outMappedMemory = NULL;
83a36ead4a7d5641181ab994a13b7d5027c1b5bd07Geoff Lang        }
84a36ead4a7d5641181ab994a13b7d5027c1b5bd07Geoff Lang        return false;
85955377ebef0134a7258a8b690853bccb705e9ad3daniel@transgaming.com    }
861e3a80411aa79afd2fbe1eeff66b28d2049a5814daniel@transgaming.com
87a36ead4a7d5641181ab994a13b7d5027c1b5bd07Geoff Lang    if (streamOffset)
88a36ead4a7d5641181ab994a13b7d5027c1b5bd07Geoff Lang    {
89a36ead4a7d5641181ab994a13b7d5027c1b5bd07Geoff Lang        *streamOffset = mWritePosition;
90a36ead4a7d5641181ab994a13b7d5027c1b5bd07Geoff Lang    }
911e3a80411aa79afd2fbe1eeff66b28d2049a5814daniel@transgaming.com
92a36ead4a7d5641181ab994a13b7d5027c1b5bd07Geoff Lang    mWritePosition += size;
93a36ead4a7d5641181ab994a13b7d5027c1b5bd07Geoff Lang    return true;
94955377ebef0134a7258a8b690853bccb705e9ad3daniel@transgaming.com}
95955377ebef0134a7258a8b690853bccb705e9ad3daniel@transgaming.com
961e3a80411aa79afd2fbe1eeff66b28d2049a5814daniel@transgaming.combool IndexBufferInterface::unmapBuffer()
97955377ebef0134a7258a8b690853bccb705e9ad3daniel@transgaming.com{
981e3a80411aa79afd2fbe1eeff66b28d2049a5814daniel@transgaming.com    return mIndexBuffer->unmapBuffer();
99955377ebef0134a7258a8b690853bccb705e9ad3daniel@transgaming.com}
100955377ebef0134a7258a8b690853bccb705e9ad3daniel@transgaming.com
1011e3a80411aa79afd2fbe1eeff66b28d2049a5814daniel@transgaming.comIndexBuffer * IndexBufferInterface::getIndexBuffer() const
102955377ebef0134a7258a8b690853bccb705e9ad3daniel@transgaming.com{
1031e3a80411aa79afd2fbe1eeff66b28d2049a5814daniel@transgaming.com    return mIndexBuffer;
104955377ebef0134a7258a8b690853bccb705e9ad3daniel@transgaming.com}
105955377ebef0134a7258a8b690853bccb705e9ad3daniel@transgaming.com
1061e3a80411aa79afd2fbe1eeff66b28d2049a5814daniel@transgaming.comunsigned int IndexBufferInterface::getWritePosition() const
107955377ebef0134a7258a8b690853bccb705e9ad3daniel@transgaming.com{
1081e3a80411aa79afd2fbe1eeff66b28d2049a5814daniel@transgaming.com    return mWritePosition;
1091e3a80411aa79afd2fbe1eeff66b28d2049a5814daniel@transgaming.com}
110955377ebef0134a7258a8b690853bccb705e9ad3daniel@transgaming.com
1111e3a80411aa79afd2fbe1eeff66b28d2049a5814daniel@transgaming.comvoid IndexBufferInterface::setWritePosition(unsigned int writePosition)
1121e3a80411aa79afd2fbe1eeff66b28d2049a5814daniel@transgaming.com{
1131e3a80411aa79afd2fbe1eeff66b28d2049a5814daniel@transgaming.com    mWritePosition = writePosition;
1141e3a80411aa79afd2fbe1eeff66b28d2049a5814daniel@transgaming.com}
115955377ebef0134a7258a8b690853bccb705e9ad3daniel@transgaming.com
1161e3a80411aa79afd2fbe1eeff66b28d2049a5814daniel@transgaming.combool IndexBufferInterface::discard()
1171e3a80411aa79afd2fbe1eeff66b28d2049a5814daniel@transgaming.com{
1181e3a80411aa79afd2fbe1eeff66b28d2049a5814daniel@transgaming.com    return mIndexBuffer->discard();
119955377ebef0134a7258a8b690853bccb705e9ad3daniel@transgaming.com}
120955377ebef0134a7258a8b690853bccb705e9ad3daniel@transgaming.com
1211e3a80411aa79afd2fbe1eeff66b28d2049a5814daniel@transgaming.combool IndexBufferInterface::setBufferSize(unsigned int bufferSize, GLenum indexType)
122955377ebef0134a7258a8b690853bccb705e9ad3daniel@transgaming.com{
1231e3a80411aa79afd2fbe1eeff66b28d2049a5814daniel@transgaming.com    if (mIndexBuffer->getBufferSize() == 0)
124955377ebef0134a7258a8b690853bccb705e9ad3daniel@transgaming.com    {
1251e3a80411aa79afd2fbe1eeff66b28d2049a5814daniel@transgaming.com        return mIndexBuffer->initialize(bufferSize, indexType, mDynamic);
126955377ebef0134a7258a8b690853bccb705e9ad3daniel@transgaming.com    }
1271e3a80411aa79afd2fbe1eeff66b28d2049a5814daniel@transgaming.com    else
128955377ebef0134a7258a8b690853bccb705e9ad3daniel@transgaming.com    {
1291e3a80411aa79afd2fbe1eeff66b28d2049a5814daniel@transgaming.com        return mIndexBuffer->setSize(bufferSize, indexType);
130955377ebef0134a7258a8b690853bccb705e9ad3daniel@transgaming.com    }
131955377ebef0134a7258a8b690853bccb705e9ad3daniel@transgaming.com}
132955377ebef0134a7258a8b690853bccb705e9ad3daniel@transgaming.com
1331e3a80411aa79afd2fbe1eeff66b28d2049a5814daniel@transgaming.comStreamingIndexBufferInterface::StreamingIndexBufferInterface(Renderer *renderer) : IndexBufferInterface(renderer, true)
134955377ebef0134a7258a8b690853bccb705e9ad3daniel@transgaming.com{
135955377ebef0134a7258a8b690853bccb705e9ad3daniel@transgaming.com}
136955377ebef0134a7258a8b690853bccb705e9ad3daniel@transgaming.com
1371e3a80411aa79afd2fbe1eeff66b28d2049a5814daniel@transgaming.comStreamingIndexBufferInterface::~StreamingIndexBufferInterface()
138955377ebef0134a7258a8b690853bccb705e9ad3daniel@transgaming.com{
139955377ebef0134a7258a8b690853bccb705e9ad3daniel@transgaming.com}
140955377ebef0134a7258a8b690853bccb705e9ad3daniel@transgaming.com
1411e3a80411aa79afd2fbe1eeff66b28d2049a5814daniel@transgaming.combool StreamingIndexBufferInterface::reserveBufferSpace(unsigned int size, GLenum indexType)
142955377ebef0134a7258a8b690853bccb705e9ad3daniel@transgaming.com{
1431e3a80411aa79afd2fbe1eeff66b28d2049a5814daniel@transgaming.com    bool result = true;
1441e3a80411aa79afd2fbe1eeff66b28d2049a5814daniel@transgaming.com    unsigned int curBufferSize = getBufferSize();
145d81cf64c467689b9f7126d0d0064d6387c0adc5dGeoff Lang    unsigned int writePos = getWritePosition();
1461e3a80411aa79afd2fbe1eeff66b28d2049a5814daniel@transgaming.com    if (size > curBufferSize)
147955377ebef0134a7258a8b690853bccb705e9ad3daniel@transgaming.com    {
1481e3a80411aa79afd2fbe1eeff66b28d2049a5814daniel@transgaming.com        result = setBufferSize(std::max(size, 2 * curBufferSize), indexType);
1491e3a80411aa79afd2fbe1eeff66b28d2049a5814daniel@transgaming.com        setWritePosition(0);
1501e3a80411aa79afd2fbe1eeff66b28d2049a5814daniel@transgaming.com    }
151d81cf64c467689b9f7126d0d0064d6387c0adc5dGeoff Lang    else if (writePos + size > curBufferSize || writePos + size < writePos)
1521e3a80411aa79afd2fbe1eeff66b28d2049a5814daniel@transgaming.com    {
1531e3a80411aa79afd2fbe1eeff66b28d2049a5814daniel@transgaming.com        if (!discard())
154955377ebef0134a7258a8b690853bccb705e9ad3daniel@transgaming.com        {
1551e3a80411aa79afd2fbe1eeff66b28d2049a5814daniel@transgaming.com            return false;
156955377ebef0134a7258a8b690853bccb705e9ad3daniel@transgaming.com        }
1571e3a80411aa79afd2fbe1eeff66b28d2049a5814daniel@transgaming.com        setWritePosition(0);
158955377ebef0134a7258a8b690853bccb705e9ad3daniel@transgaming.com    }
159955377ebef0134a7258a8b690853bccb705e9ad3daniel@transgaming.com
1601e3a80411aa79afd2fbe1eeff66b28d2049a5814daniel@transgaming.com    return result;
161955377ebef0134a7258a8b690853bccb705e9ad3daniel@transgaming.com}
162955377ebef0134a7258a8b690853bccb705e9ad3daniel@transgaming.com
1631e3a80411aa79afd2fbe1eeff66b28d2049a5814daniel@transgaming.com
1641e3a80411aa79afd2fbe1eeff66b28d2049a5814daniel@transgaming.comStaticIndexBufferInterface::StaticIndexBufferInterface(Renderer *renderer) : IndexBufferInterface(renderer, false)
165955377ebef0134a7258a8b690853bccb705e9ad3daniel@transgaming.com{
1661e3a80411aa79afd2fbe1eeff66b28d2049a5814daniel@transgaming.com}
167955377ebef0134a7258a8b690853bccb705e9ad3daniel@transgaming.com
1681e3a80411aa79afd2fbe1eeff66b28d2049a5814daniel@transgaming.comStaticIndexBufferInterface::~StaticIndexBufferInterface()
1691e3a80411aa79afd2fbe1eeff66b28d2049a5814daniel@transgaming.com{
1701e3a80411aa79afd2fbe1eeff66b28d2049a5814daniel@transgaming.com}
171955377ebef0134a7258a8b690853bccb705e9ad3daniel@transgaming.com
1721e3a80411aa79afd2fbe1eeff66b28d2049a5814daniel@transgaming.combool StaticIndexBufferInterface::reserveBufferSpace(unsigned int size, GLenum indexType)
1731e3a80411aa79afd2fbe1eeff66b28d2049a5814daniel@transgaming.com{
1741e3a80411aa79afd2fbe1eeff66b28d2049a5814daniel@transgaming.com    unsigned int curSize = getBufferSize();
1751e3a80411aa79afd2fbe1eeff66b28d2049a5814daniel@transgaming.com    if (curSize == 0)
1761e3a80411aa79afd2fbe1eeff66b28d2049a5814daniel@transgaming.com    {
1771e3a80411aa79afd2fbe1eeff66b28d2049a5814daniel@transgaming.com        return setBufferSize(size, indexType);
178955377ebef0134a7258a8b690853bccb705e9ad3daniel@transgaming.com    }
1791e3a80411aa79afd2fbe1eeff66b28d2049a5814daniel@transgaming.com    else if (curSize >= size && indexType == getIndexType())
180955377ebef0134a7258a8b690853bccb705e9ad3daniel@transgaming.com    {
1811e3a80411aa79afd2fbe1eeff66b28d2049a5814daniel@transgaming.com        return true;
1821e3a80411aa79afd2fbe1eeff66b28d2049a5814daniel@transgaming.com    }
1831e3a80411aa79afd2fbe1eeff66b28d2049a5814daniel@transgaming.com    else
1841e3a80411aa79afd2fbe1eeff66b28d2049a5814daniel@transgaming.com    {
1851e3a80411aa79afd2fbe1eeff66b28d2049a5814daniel@transgaming.com        ERR("Static index buffers can't be resized");
1861e3a80411aa79afd2fbe1eeff66b28d2049a5814daniel@transgaming.com        UNREACHABLE();
1871e3a80411aa79afd2fbe1eeff66b28d2049a5814daniel@transgaming.com        return false;
188955377ebef0134a7258a8b690853bccb705e9ad3daniel@transgaming.com    }
189955377ebef0134a7258a8b690853bccb705e9ad3daniel@transgaming.com}
190955377ebef0134a7258a8b690853bccb705e9ad3daniel@transgaming.com
191f23eb28c3ad98344e340b97dcad268a7ec362e8bGeoff LangIndexRangeCache *StaticIndexBufferInterface::getIndexRangeCache()
192955377ebef0134a7258a8b690853bccb705e9ad3daniel@transgaming.com{
193f23eb28c3ad98344e340b97dcad268a7ec362e8bGeoff Lang    return &mIndexRangeCache;
194955377ebef0134a7258a8b690853bccb705e9ad3daniel@transgaming.com}
195955377ebef0134a7258a8b690853bccb705e9ad3daniel@transgaming.com
196955377ebef0134a7258a8b690853bccb705e9ad3daniel@transgaming.com}
197