1955377ebef0134a7258a8b690853bccb705e9ad3daniel@transgaming.com//
2955377ebef0134a7258a8b690853bccb705e9ad3daniel@transgaming.com// Copyright (c) 2002-2012 The ANGLE Project Authors. All rights reserved.
3955377ebef0134a7258a8b690853bccb705e9ad3daniel@transgaming.com// Use of this source code is governed by a BSD-style license that can be
4955377ebef0134a7258a8b690853bccb705e9ad3daniel@transgaming.com// found in the LICENSE file.
5955377ebef0134a7258a8b690853bccb705e9ad3daniel@transgaming.com//
6955377ebef0134a7258a8b690853bccb705e9ad3daniel@transgaming.com
7955377ebef0134a7258a8b690853bccb705e9ad3daniel@transgaming.com// IndexBuffer.cpp: Defines the abstract IndexBuffer class and IndexBufferInterface
8955377ebef0134a7258a8b690853bccb705e9ad3daniel@transgaming.com// class with derivations, classes that perform graphics API agnostic index buffer operations.
9955377ebef0134a7258a8b690853bccb705e9ad3daniel@transgaming.com
10c7a4104957aa1f6fa36e4e9cf65d36b699eb05bdBrandon Jones#include "libGLESv2/renderer/d3d/IndexBuffer.h"
11486d9e9b6b4ed31f66d2624b8e822020fe40a1f7shannon.woods@transgaming.com#include "libGLESv2/renderer/Renderer.h"
12955377ebef0134a7258a8b690853bccb705e9ad3daniel@transgaming.com
13955377ebef0134a7258a8b690853bccb705e9ad3daniel@transgaming.comnamespace rx
14955377ebef0134a7258a8b690853bccb705e9ad3daniel@transgaming.com{
15955377ebef0134a7258a8b690853bccb705e9ad3daniel@transgaming.com
162befccdf021fe2962f6cfd6f0ffb541954390d78daniel@transgaming.comunsigned int IndexBuffer::mNextSerial = 1;
172befccdf021fe2962f6cfd6f0ffb541954390d78daniel@transgaming.com
182befccdf021fe2962f6cfd6f0ffb541954390d78daniel@transgaming.comIndexBuffer::IndexBuffer()
192befccdf021fe2962f6cfd6f0ffb541954390d78daniel@transgaming.com{
202befccdf021fe2962f6cfd6f0ffb541954390d78daniel@transgaming.com    updateSerial();
212befccdf021fe2962f6cfd6f0ffb541954390d78daniel@transgaming.com}
222befccdf021fe2962f6cfd6f0ffb541954390d78daniel@transgaming.com
232befccdf021fe2962f6cfd6f0ffb541954390d78daniel@transgaming.comIndexBuffer::~IndexBuffer()
242befccdf021fe2962f6cfd6f0ffb541954390d78daniel@transgaming.com{
252befccdf021fe2962f6cfd6f0ffb541954390d78daniel@transgaming.com}
262befccdf021fe2962f6cfd6f0ffb541954390d78daniel@transgaming.com
272befccdf021fe2962f6cfd6f0ffb541954390d78daniel@transgaming.comunsigned int IndexBuffer::getSerial() const
282befccdf021fe2962f6cfd6f0ffb541954390d78daniel@transgaming.com{
292befccdf021fe2962f6cfd6f0ffb541954390d78daniel@transgaming.com    return mSerial;
302befccdf021fe2962f6cfd6f0ffb541954390d78daniel@transgaming.com}
312befccdf021fe2962f6cfd6f0ffb541954390d78daniel@transgaming.com
322befccdf021fe2962f6cfd6f0ffb541954390d78daniel@transgaming.comvoid IndexBuffer::updateSerial()
332befccdf021fe2962f6cfd6f0ffb541954390d78daniel@transgaming.com{
342befccdf021fe2962f6cfd6f0ffb541954390d78daniel@transgaming.com    mSerial = mNextSerial++;
352befccdf021fe2962f6cfd6f0ffb541954390d78daniel@transgaming.com}
362befccdf021fe2962f6cfd6f0ffb541954390d78daniel@transgaming.com
372befccdf021fe2962f6cfd6f0ffb541954390d78daniel@transgaming.com
381e3a80411aa79afd2fbe1eeff66b28d2049a5814daniel@transgaming.comIndexBufferInterface::IndexBufferInterface(Renderer *renderer, bool dynamic) : mRenderer(renderer)
39955377ebef0134a7258a8b690853bccb705e9ad3daniel@transgaming.com{
401e3a80411aa79afd2fbe1eeff66b28d2049a5814daniel@transgaming.com    mIndexBuffer = renderer->createIndexBuffer();
41955377ebef0134a7258a8b690853bccb705e9ad3daniel@transgaming.com
421e3a80411aa79afd2fbe1eeff66b28d2049a5814daniel@transgaming.com    mDynamic = dynamic;
431e3a80411aa79afd2fbe1eeff66b28d2049a5814daniel@transgaming.com    mWritePosition = 0;
44955377ebef0134a7258a8b690853bccb705e9ad3daniel@transgaming.com}
45955377ebef0134a7258a8b690853bccb705e9ad3daniel@transgaming.com
4650cc725131415c0448592104ae2ad5f2079ebc1bdaniel@transgaming.comIndexBufferInterface::~IndexBufferInterface()
47955377ebef0134a7258a8b690853bccb705e9ad3daniel@transgaming.com{
48955377ebef0134a7258a8b690853bccb705e9ad3daniel@transgaming.com    if (mIndexBuffer)
49955377ebef0134a7258a8b690853bccb705e9ad3daniel@transgaming.com    {
501e3a80411aa79afd2fbe1eeff66b28d2049a5814daniel@transgaming.com        delete mIndexBuffer;
51955377ebef0134a7258a8b690853bccb705e9ad3daniel@transgaming.com    }
52955377ebef0134a7258a8b690853bccb705e9ad3daniel@transgaming.com}
53955377ebef0134a7258a8b690853bccb705e9ad3daniel@transgaming.com
541e3a80411aa79afd2fbe1eeff66b28d2049a5814daniel@transgaming.comGLenum IndexBufferInterface::getIndexType() const
55955377ebef0134a7258a8b690853bccb705e9ad3daniel@transgaming.com{
561e3a80411aa79afd2fbe1eeff66b28d2049a5814daniel@transgaming.com    return mIndexBuffer->getIndexType();
57955377ebef0134a7258a8b690853bccb705e9ad3daniel@transgaming.com}
58955377ebef0134a7258a8b690853bccb705e9ad3daniel@transgaming.com
591e3a80411aa79afd2fbe1eeff66b28d2049a5814daniel@transgaming.comunsigned int IndexBufferInterface::getBufferSize() const
60955377ebef0134a7258a8b690853bccb705e9ad3daniel@transgaming.com{
611e3a80411aa79afd2fbe1eeff66b28d2049a5814daniel@transgaming.com    return mIndexBuffer->getBufferSize();
62955377ebef0134a7258a8b690853bccb705e9ad3daniel@transgaming.com}
63955377ebef0134a7258a8b690853bccb705e9ad3daniel@transgaming.com
641e3a80411aa79afd2fbe1eeff66b28d2049a5814daniel@transgaming.comunsigned int IndexBufferInterface::getSerial() const
65955377ebef0134a7258a8b690853bccb705e9ad3daniel@transgaming.com{
661e3a80411aa79afd2fbe1eeff66b28d2049a5814daniel@transgaming.com    return mIndexBuffer->getSerial();
67955377ebef0134a7258a8b690853bccb705e9ad3daniel@transgaming.com}
68955377ebef0134a7258a8b690853bccb705e9ad3daniel@transgaming.com
69c9e69b1941522095a3878d9e1501511ab4722139Geoff Langgl::Error IndexBufferInterface::mapBuffer(unsigned int size, void** outMappedMemory, unsigned int *streamOffset)
70955377ebef0134a7258a8b690853bccb705e9ad3daniel@transgaming.com{
71a36ead4a7d5641181ab994a13b7d5027c1b5bd07Geoff Lang    // Protect against integer overflow
72a36ead4a7d5641181ab994a13b7d5027c1b5bd07Geoff Lang    if (mWritePosition + size < mWritePosition)
73a36ead4a7d5641181ab994a13b7d5027c1b5bd07Geoff Lang    {
74c9e69b1941522095a3878d9e1501511ab4722139Geoff Lang        return gl::Error(GL_OUT_OF_MEMORY, "Mapping of internal index buffer would cause an integer overflow.");
75a36ead4a7d5641181ab994a13b7d5027c1b5bd07Geoff Lang    }
76a36ead4a7d5641181ab994a13b7d5027c1b5bd07Geoff Lang
77c9e69b1941522095a3878d9e1501511ab4722139Geoff Lang    gl::Error error = mIndexBuffer->mapBuffer(mWritePosition, size, outMappedMemory);
78c9e69b1941522095a3878d9e1501511ab4722139Geoff Lang    if (error.isError())
79955377ebef0134a7258a8b690853bccb705e9ad3daniel@transgaming.com    {
80a36ead4a7d5641181ab994a13b7d5027c1b5bd07Geoff Lang        if (outMappedMemory)
81a36ead4a7d5641181ab994a13b7d5027c1b5bd07Geoff Lang        {
82a36ead4a7d5641181ab994a13b7d5027c1b5bd07Geoff Lang            *outMappedMemory = NULL;
83a36ead4a7d5641181ab994a13b7d5027c1b5bd07Geoff Lang        }
84c9e69b1941522095a3878d9e1501511ab4722139Geoff Lang        return error;
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;
93c9e69b1941522095a3878d9e1501511ab4722139Geoff Lang    return gl::Error(GL_NO_ERROR);
94955377ebef0134a7258a8b690853bccb705e9ad3daniel@transgaming.com}
95955377ebef0134a7258a8b690853bccb705e9ad3daniel@transgaming.com
96c9e69b1941522095a3878d9e1501511ab4722139Geoff Langgl::Error 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
116c9e69b1941522095a3878d9e1501511ab4722139Geoff Langgl::Error IndexBufferInterface::discard()
1171e3a80411aa79afd2fbe1eeff66b28d2049a5814daniel@transgaming.com{
1181e3a80411aa79afd2fbe1eeff66b28d2049a5814daniel@transgaming.com    return mIndexBuffer->discard();
119955377ebef0134a7258a8b690853bccb705e9ad3daniel@transgaming.com}
120955377ebef0134a7258a8b690853bccb705e9ad3daniel@transgaming.com
121c9e69b1941522095a3878d9e1501511ab4722139Geoff Langgl::Error 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
141c9e69b1941522095a3878d9e1501511ab4722139Geoff Langgl::Error StreamingIndexBufferInterface::reserveBufferSpace(unsigned int size, GLenum indexType)
142955377ebef0134a7258a8b690853bccb705e9ad3daniel@transgaming.com{
1431e3a80411aa79afd2fbe1eeff66b28d2049a5814daniel@transgaming.com    unsigned int curBufferSize = getBufferSize();
144d81cf64c467689b9f7126d0d0064d6387c0adc5dGeoff Lang    unsigned int writePos = getWritePosition();
1451e3a80411aa79afd2fbe1eeff66b28d2049a5814daniel@transgaming.com    if (size > curBufferSize)
146955377ebef0134a7258a8b690853bccb705e9ad3daniel@transgaming.com    {
147c9e69b1941522095a3878d9e1501511ab4722139Geoff Lang        gl::Error error = setBufferSize(std::max(size, 2 * curBufferSize), indexType);
148c9e69b1941522095a3878d9e1501511ab4722139Geoff Lang        if (error.isError())
149c9e69b1941522095a3878d9e1501511ab4722139Geoff Lang        {
150c9e69b1941522095a3878d9e1501511ab4722139Geoff Lang            return error;
151c9e69b1941522095a3878d9e1501511ab4722139Geoff Lang        }
1521e3a80411aa79afd2fbe1eeff66b28d2049a5814daniel@transgaming.com        setWritePosition(0);
1531e3a80411aa79afd2fbe1eeff66b28d2049a5814daniel@transgaming.com    }
154d81cf64c467689b9f7126d0d0064d6387c0adc5dGeoff Lang    else if (writePos + size > curBufferSize || writePos + size < writePos)
1551e3a80411aa79afd2fbe1eeff66b28d2049a5814daniel@transgaming.com    {
156c9e69b1941522095a3878d9e1501511ab4722139Geoff Lang        gl::Error error = discard();
157c9e69b1941522095a3878d9e1501511ab4722139Geoff Lang        if (error.isError())
158955377ebef0134a7258a8b690853bccb705e9ad3daniel@transgaming.com        {
159c9e69b1941522095a3878d9e1501511ab4722139Geoff Lang            return error;
160955377ebef0134a7258a8b690853bccb705e9ad3daniel@transgaming.com        }
1611e3a80411aa79afd2fbe1eeff66b28d2049a5814daniel@transgaming.com        setWritePosition(0);
162955377ebef0134a7258a8b690853bccb705e9ad3daniel@transgaming.com    }
163955377ebef0134a7258a8b690853bccb705e9ad3daniel@transgaming.com
164c9e69b1941522095a3878d9e1501511ab4722139Geoff Lang    return gl::Error(GL_NO_ERROR);
165955377ebef0134a7258a8b690853bccb705e9ad3daniel@transgaming.com}
166955377ebef0134a7258a8b690853bccb705e9ad3daniel@transgaming.com
1671e3a80411aa79afd2fbe1eeff66b28d2049a5814daniel@transgaming.com
1681e3a80411aa79afd2fbe1eeff66b28d2049a5814daniel@transgaming.comStaticIndexBufferInterface::StaticIndexBufferInterface(Renderer *renderer) : IndexBufferInterface(renderer, false)
169955377ebef0134a7258a8b690853bccb705e9ad3daniel@transgaming.com{
1701e3a80411aa79afd2fbe1eeff66b28d2049a5814daniel@transgaming.com}
171955377ebef0134a7258a8b690853bccb705e9ad3daniel@transgaming.com
1721e3a80411aa79afd2fbe1eeff66b28d2049a5814daniel@transgaming.comStaticIndexBufferInterface::~StaticIndexBufferInterface()
1731e3a80411aa79afd2fbe1eeff66b28d2049a5814daniel@transgaming.com{
1741e3a80411aa79afd2fbe1eeff66b28d2049a5814daniel@transgaming.com}
175955377ebef0134a7258a8b690853bccb705e9ad3daniel@transgaming.com
176c9e69b1941522095a3878d9e1501511ab4722139Geoff Langgl::Error StaticIndexBufferInterface::reserveBufferSpace(unsigned int size, GLenum indexType)
1771e3a80411aa79afd2fbe1eeff66b28d2049a5814daniel@transgaming.com{
1781e3a80411aa79afd2fbe1eeff66b28d2049a5814daniel@transgaming.com    unsigned int curSize = getBufferSize();
1791e3a80411aa79afd2fbe1eeff66b28d2049a5814daniel@transgaming.com    if (curSize == 0)
1801e3a80411aa79afd2fbe1eeff66b28d2049a5814daniel@transgaming.com    {
1811e3a80411aa79afd2fbe1eeff66b28d2049a5814daniel@transgaming.com        return setBufferSize(size, indexType);
182955377ebef0134a7258a8b690853bccb705e9ad3daniel@transgaming.com    }
1831e3a80411aa79afd2fbe1eeff66b28d2049a5814daniel@transgaming.com    else if (curSize >= size && indexType == getIndexType())
184955377ebef0134a7258a8b690853bccb705e9ad3daniel@transgaming.com    {
185c9e69b1941522095a3878d9e1501511ab4722139Geoff Lang        return gl::Error(GL_NO_ERROR);
1861e3a80411aa79afd2fbe1eeff66b28d2049a5814daniel@transgaming.com    }
1871e3a80411aa79afd2fbe1eeff66b28d2049a5814daniel@transgaming.com    else
1881e3a80411aa79afd2fbe1eeff66b28d2049a5814daniel@transgaming.com    {
1891e3a80411aa79afd2fbe1eeff66b28d2049a5814daniel@transgaming.com        UNREACHABLE();
190c9e69b1941522095a3878d9e1501511ab4722139Geoff Lang        return gl::Error(GL_INVALID_OPERATION, "Internal static index buffers can't be resized");
191955377ebef0134a7258a8b690853bccb705e9ad3daniel@transgaming.com    }
192955377ebef0134a7258a8b690853bccb705e9ad3daniel@transgaming.com}
193955377ebef0134a7258a8b690853bccb705e9ad3daniel@transgaming.com
194f23eb28c3ad98344e340b97dcad268a7ec362e8bGeoff LangIndexRangeCache *StaticIndexBufferInterface::getIndexRangeCache()
195955377ebef0134a7258a8b690853bccb705e9ad3daniel@transgaming.com{
196f23eb28c3ad98344e340b97dcad268a7ec362e8bGeoff Lang    return &mIndexRangeCache;
197955377ebef0134a7258a8b690853bccb705e9ad3daniel@transgaming.com}
198955377ebef0134a7258a8b690853bccb705e9ad3daniel@transgaming.com
199955377ebef0134a7258a8b690853bccb705e9ad3daniel@transgaming.com}
200