10bac285a78df6a6d7a6b68784748b92805420ffbNicolas Capens// Copyright 2016 The SwiftShader Authors. All Rights Reserved.
20bac285a78df6a6d7a6b68784748b92805420ffbNicolas Capens//
30bac285a78df6a6d7a6b68784748b92805420ffbNicolas Capens// Licensed under the Apache License, Version 2.0 (the "License");
40bac285a78df6a6d7a6b68784748b92805420ffbNicolas Capens// you may not use this file except in compliance with the License.
50bac285a78df6a6d7a6b68784748b92805420ffbNicolas Capens// You may obtain a copy of the License at
60bac285a78df6a6d7a6b68784748b92805420ffbNicolas Capens//
70bac285a78df6a6d7a6b68784748b92805420ffbNicolas Capens//    http://www.apache.org/licenses/LICENSE-2.0
80bac285a78df6a6d7a6b68784748b92805420ffbNicolas Capens//
90bac285a78df6a6d7a6b68784748b92805420ffbNicolas Capens// Unless required by applicable law or agreed to in writing, software
100bac285a78df6a6d7a6b68784748b92805420ffbNicolas Capens// distributed under the License is distributed on an "AS IS" BASIS,
110bac285a78df6a6d7a6b68784748b92805420ffbNicolas Capens// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
120bac285a78df6a6d7a6b68784748b92805420ffbNicolas Capens// See the License for the specific language governing permissions and
130bac285a78df6a6d7a6b68784748b92805420ffbNicolas Capens// limitations under the License.
140bac285a78df6a6d7a6b68784748b92805420ffbNicolas Capens
150bac285a78df6a6d7a6b68784748b92805420ffbNicolas Capens// VertexDataManager.h: Defines the VertexDataManager, a class that
160bac285a78df6a6d7a6b68784748b92805420ffbNicolas Capens// runs the Buffer translation process.
170bac285a78df6a6d7a6b68784748b92805420ffbNicolas Capens
180bac285a78df6a6d7a6b68784748b92805420ffbNicolas Capens#include "VertexDataManager.h"
190bac285a78df6a6d7a6b68784748b92805420ffbNicolas Capens
200bac285a78df6a6d7a6b68784748b92805420ffbNicolas Capens#include "Buffer.h"
210bac285a78df6a6d7a6b68784748b92805420ffbNicolas Capens#include "Program.h"
220bac285a78df6a6d7a6b68784748b92805420ffbNicolas Capens#include "IndexDataManager.h"
230bac285a78df6a6d7a6b68784748b92805420ffbNicolas Capens#include "common/debug.h"
240bac285a78df6a6d7a6b68784748b92805420ffbNicolas Capens
250bac285a78df6a6d7a6b68784748b92805420ffbNicolas Capensnamespace
260bac285a78df6a6d7a6b68784748b92805420ffbNicolas Capens{
270bac285a78df6a6d7a6b68784748b92805420ffbNicolas Capens	enum {INITIAL_STREAM_BUFFER_SIZE = 1024 * 1024};
280bac285a78df6a6d7a6b68784748b92805420ffbNicolas Capens}
290bac285a78df6a6d7a6b68784748b92805420ffbNicolas Capens
300bac285a78df6a6d7a6b68784748b92805420ffbNicolas Capensnamespace es2
310bac285a78df6a6d7a6b68784748b92805420ffbNicolas Capens{
320bac285a78df6a6d7a6b68784748b92805420ffbNicolas Capens
330bac285a78df6a6d7a6b68784748b92805420ffbNicolas CapensVertexDataManager::VertexDataManager(Context *context) : mContext(context)
340bac285a78df6a6d7a6b68784748b92805420ffbNicolas Capens{
350bac285a78df6a6d7a6b68784748b92805420ffbNicolas Capens	for(int i = 0; i < MAX_VERTEX_ATTRIBS; i++)
360bac285a78df6a6d7a6b68784748b92805420ffbNicolas Capens	{
370bac285a78df6a6d7a6b68784748b92805420ffbNicolas Capens		mDirtyCurrentValue[i] = true;
380bac285a78df6a6d7a6b68784748b92805420ffbNicolas Capens		mCurrentValueBuffer[i] = nullptr;
390bac285a78df6a6d7a6b68784748b92805420ffbNicolas Capens	}
400bac285a78df6a6d7a6b68784748b92805420ffbNicolas Capens
410bac285a78df6a6d7a6b68784748b92805420ffbNicolas Capens	mStreamingBuffer = new StreamingVertexBuffer(INITIAL_STREAM_BUFFER_SIZE);
420bac285a78df6a6d7a6b68784748b92805420ffbNicolas Capens
430bac285a78df6a6d7a6b68784748b92805420ffbNicolas Capens	if(!mStreamingBuffer)
440bac285a78df6a6d7a6b68784748b92805420ffbNicolas Capens	{
450bac285a78df6a6d7a6b68784748b92805420ffbNicolas Capens		ERR("Failed to allocate the streaming vertex buffer.");
460bac285a78df6a6d7a6b68784748b92805420ffbNicolas Capens	}
470bac285a78df6a6d7a6b68784748b92805420ffbNicolas Capens}
480bac285a78df6a6d7a6b68784748b92805420ffbNicolas Capens
490bac285a78df6a6d7a6b68784748b92805420ffbNicolas CapensVertexDataManager::~VertexDataManager()
500bac285a78df6a6d7a6b68784748b92805420ffbNicolas Capens{
510bac285a78df6a6d7a6b68784748b92805420ffbNicolas Capens	delete mStreamingBuffer;
520bac285a78df6a6d7a6b68784748b92805420ffbNicolas Capens
530bac285a78df6a6d7a6b68784748b92805420ffbNicolas Capens	for(int i = 0; i < MAX_VERTEX_ATTRIBS; i++)
540bac285a78df6a6d7a6b68784748b92805420ffbNicolas Capens	{
550bac285a78df6a6d7a6b68784748b92805420ffbNicolas Capens		delete mCurrentValueBuffer[i];
560bac285a78df6a6d7a6b68784748b92805420ffbNicolas Capens	}
570bac285a78df6a6d7a6b68784748b92805420ffbNicolas Capens}
580bac285a78df6a6d7a6b68784748b92805420ffbNicolas Capens
590bac285a78df6a6d7a6b68784748b92805420ffbNicolas Capensunsigned int VertexDataManager::writeAttributeData(StreamingVertexBuffer *vertexBuffer, GLint start, GLsizei count, const VertexAttribute &attribute)
600bac285a78df6a6d7a6b68784748b92805420ffbNicolas Capens{
610bac285a78df6a6d7a6b68784748b92805420ffbNicolas Capens	Buffer *buffer = attribute.mBoundBuffer;
620bac285a78df6a6d7a6b68784748b92805420ffbNicolas Capens
630bac285a78df6a6d7a6b68784748b92805420ffbNicolas Capens	int inputStride = attribute.stride();
640bac285a78df6a6d7a6b68784748b92805420ffbNicolas Capens	int elementSize = attribute.typeSize();
650bac285a78df6a6d7a6b68784748b92805420ffbNicolas Capens	unsigned int streamOffset = 0;
660bac285a78df6a6d7a6b68784748b92805420ffbNicolas Capens
670bac285a78df6a6d7a6b68784748b92805420ffbNicolas Capens	char *output = nullptr;
680bac285a78df6a6d7a6b68784748b92805420ffbNicolas Capens
690bac285a78df6a6d7a6b68784748b92805420ffbNicolas Capens	if(vertexBuffer)
700bac285a78df6a6d7a6b68784748b92805420ffbNicolas Capens	{
710bac285a78df6a6d7a6b68784748b92805420ffbNicolas Capens		output = (char*)vertexBuffer->map(attribute, attribute.typeSize() * count, &streamOffset);
720bac285a78df6a6d7a6b68784748b92805420ffbNicolas Capens	}
730bac285a78df6a6d7a6b68784748b92805420ffbNicolas Capens
740bac285a78df6a6d7a6b68784748b92805420ffbNicolas Capens	if(!output)
750bac285a78df6a6d7a6b68784748b92805420ffbNicolas Capens	{
760bac285a78df6a6d7a6b68784748b92805420ffbNicolas Capens		ERR("Failed to map vertex buffer.");
770bac285a78df6a6d7a6b68784748b92805420ffbNicolas Capens		return ~0u;
780bac285a78df6a6d7a6b68784748b92805420ffbNicolas Capens	}
790bac285a78df6a6d7a6b68784748b92805420ffbNicolas Capens
800bac285a78df6a6d7a6b68784748b92805420ffbNicolas Capens	const char *input = nullptr;
810bac285a78df6a6d7a6b68784748b92805420ffbNicolas Capens
820bac285a78df6a6d7a6b68784748b92805420ffbNicolas Capens	if(buffer)
830bac285a78df6a6d7a6b68784748b92805420ffbNicolas Capens	{
840bac285a78df6a6d7a6b68784748b92805420ffbNicolas Capens		input = static_cast<const char*>(buffer->data()) + attribute.mOffset;
850bac285a78df6a6d7a6b68784748b92805420ffbNicolas Capens	}
860bac285a78df6a6d7a6b68784748b92805420ffbNicolas Capens	else
870bac285a78df6a6d7a6b68784748b92805420ffbNicolas Capens	{
880bac285a78df6a6d7a6b68784748b92805420ffbNicolas Capens		input = static_cast<const char*>(attribute.mPointer);
890bac285a78df6a6d7a6b68784748b92805420ffbNicolas Capens	}
900bac285a78df6a6d7a6b68784748b92805420ffbNicolas Capens
910bac285a78df6a6d7a6b68784748b92805420ffbNicolas Capens	input += inputStride * start;
920bac285a78df6a6d7a6b68784748b92805420ffbNicolas Capens
930bac285a78df6a6d7a6b68784748b92805420ffbNicolas Capens	if(inputStride == elementSize)
940bac285a78df6a6d7a6b68784748b92805420ffbNicolas Capens	{
950bac285a78df6a6d7a6b68784748b92805420ffbNicolas Capens		memcpy(output, input, count * inputStride);
960bac285a78df6a6d7a6b68784748b92805420ffbNicolas Capens	}
970bac285a78df6a6d7a6b68784748b92805420ffbNicolas Capens	else
980bac285a78df6a6d7a6b68784748b92805420ffbNicolas Capens	{
990bac285a78df6a6d7a6b68784748b92805420ffbNicolas Capens		for(int i = 0; i < count; i++)
1000bac285a78df6a6d7a6b68784748b92805420ffbNicolas Capens		{
1010bac285a78df6a6d7a6b68784748b92805420ffbNicolas Capens			memcpy(output, input, elementSize);
1020bac285a78df6a6d7a6b68784748b92805420ffbNicolas Capens			output += elementSize;
1030bac285a78df6a6d7a6b68784748b92805420ffbNicolas Capens			input += inputStride;
1040bac285a78df6a6d7a6b68784748b92805420ffbNicolas Capens		}
1050bac285a78df6a6d7a6b68784748b92805420ffbNicolas Capens	}
1060bac285a78df6a6d7a6b68784748b92805420ffbNicolas Capens
1070bac285a78df6a6d7a6b68784748b92805420ffbNicolas Capens	vertexBuffer->unmap();
1080bac285a78df6a6d7a6b68784748b92805420ffbNicolas Capens
1090bac285a78df6a6d7a6b68784748b92805420ffbNicolas Capens	return streamOffset;
1100bac285a78df6a6d7a6b68784748b92805420ffbNicolas Capens}
1110bac285a78df6a6d7a6b68784748b92805420ffbNicolas Capens
1120bac285a78df6a6d7a6b68784748b92805420ffbNicolas CapensGLenum VertexDataManager::prepareVertexData(GLint start, GLsizei count, TranslatedAttribute *translated, GLsizei instanceId)
1130bac285a78df6a6d7a6b68784748b92805420ffbNicolas Capens{
1140bac285a78df6a6d7a6b68784748b92805420ffbNicolas Capens	if(!mStreamingBuffer)
1150bac285a78df6a6d7a6b68784748b92805420ffbNicolas Capens	{
1160bac285a78df6a6d7a6b68784748b92805420ffbNicolas Capens		return GL_OUT_OF_MEMORY;
1170bac285a78df6a6d7a6b68784748b92805420ffbNicolas Capens	}
1180bac285a78df6a6d7a6b68784748b92805420ffbNicolas Capens
1190bac285a78df6a6d7a6b68784748b92805420ffbNicolas Capens	const VertexAttributeArray &attribs = mContext->getVertexArrayAttributes();
1200bac285a78df6a6d7a6b68784748b92805420ffbNicolas Capens	const VertexAttributeArray &currentAttribs = mContext->getCurrentVertexAttributes();
1210bac285a78df6a6d7a6b68784748b92805420ffbNicolas Capens	Program *program = mContext->getCurrentProgram();
1220bac285a78df6a6d7a6b68784748b92805420ffbNicolas Capens
1230bac285a78df6a6d7a6b68784748b92805420ffbNicolas Capens	// Determine the required storage size per used buffer
1240bac285a78df6a6d7a6b68784748b92805420ffbNicolas Capens	for(int i = 0; i < MAX_VERTEX_ATTRIBS; i++)
1250bac285a78df6a6d7a6b68784748b92805420ffbNicolas Capens	{
1260bac285a78df6a6d7a6b68784748b92805420ffbNicolas Capens		const VertexAttribute &attrib = attribs[i].mArrayEnabled ? attribs[i] : currentAttribs[i];
1270bac285a78df6a6d7a6b68784748b92805420ffbNicolas Capens
1280bac285a78df6a6d7a6b68784748b92805420ffbNicolas Capens		if(program->getAttributeStream(i) != -1 && attrib.mArrayEnabled)
1290bac285a78df6a6d7a6b68784748b92805420ffbNicolas Capens		{
1300bac285a78df6a6d7a6b68784748b92805420ffbNicolas Capens			if(!attrib.mBoundBuffer)
1310bac285a78df6a6d7a6b68784748b92805420ffbNicolas Capens			{
1320bac285a78df6a6d7a6b68784748b92805420ffbNicolas Capens				const bool isInstanced = attrib.mDivisor > 0;
1330bac285a78df6a6d7a6b68784748b92805420ffbNicolas Capens				mStreamingBuffer->addRequiredSpace(attrib.typeSize() * (isInstanced ? 1 : count));
1340bac285a78df6a6d7a6b68784748b92805420ffbNicolas Capens			}
1350bac285a78df6a6d7a6b68784748b92805420ffbNicolas Capens		}
1360bac285a78df6a6d7a6b68784748b92805420ffbNicolas Capens	}
1370bac285a78df6a6d7a6b68784748b92805420ffbNicolas Capens
1380bac285a78df6a6d7a6b68784748b92805420ffbNicolas Capens	mStreamingBuffer->reserveRequiredSpace();
1390bac285a78df6a6d7a6b68784748b92805420ffbNicolas Capens
1400bac285a78df6a6d7a6b68784748b92805420ffbNicolas Capens	// Perform the vertex data translations
1410bac285a78df6a6d7a6b68784748b92805420ffbNicolas Capens	for(int i = 0; i < MAX_VERTEX_ATTRIBS; i++)
1420bac285a78df6a6d7a6b68784748b92805420ffbNicolas Capens	{
1430bac285a78df6a6d7a6b68784748b92805420ffbNicolas Capens		if(program->getAttributeStream(i) != -1)
1440bac285a78df6a6d7a6b68784748b92805420ffbNicolas Capens		{
1450bac285a78df6a6d7a6b68784748b92805420ffbNicolas Capens			const VertexAttribute &attrib = attribs[i].mArrayEnabled ? attribs[i] : currentAttribs[i];
1460bac285a78df6a6d7a6b68784748b92805420ffbNicolas Capens
1470bac285a78df6a6d7a6b68784748b92805420ffbNicolas Capens			if(attrib.mArrayEnabled)
1480bac285a78df6a6d7a6b68784748b92805420ffbNicolas Capens			{
1490bac285a78df6a6d7a6b68784748b92805420ffbNicolas Capens				const bool isInstanced = attrib.mDivisor > 0;
1500bac285a78df6a6d7a6b68784748b92805420ffbNicolas Capens
1510bac285a78df6a6d7a6b68784748b92805420ffbNicolas Capens				// Instanced vertices do not apply the 'start' offset
1520bac285a78df6a6d7a6b68784748b92805420ffbNicolas Capens				GLint firstVertexIndex = isInstanced ? instanceId / attrib.mDivisor : start;
1530bac285a78df6a6d7a6b68784748b92805420ffbNicolas Capens
1540bac285a78df6a6d7a6b68784748b92805420ffbNicolas Capens				Buffer *buffer = attrib.mBoundBuffer;
1550bac285a78df6a6d7a6b68784748b92805420ffbNicolas Capens
1562d4b7be6248d1f8ae9898f74174fa4393ae36435Nicolas Capens				if((!buffer && attrib.mPointer == nullptr) || (buffer && !buffer->data()))
1570bac285a78df6a6d7a6b68784748b92805420ffbNicolas Capens				{
1580bac285a78df6a6d7a6b68784748b92805420ffbNicolas Capens					// This is an application error that would normally result in a crash, but we catch it and return an error
1590bac285a78df6a6d7a6b68784748b92805420ffbNicolas Capens					ERR("An enabled vertex array has no buffer and no pointer.");
1600bac285a78df6a6d7a6b68784748b92805420ffbNicolas Capens					return GL_INVALID_OPERATION;
1610bac285a78df6a6d7a6b68784748b92805420ffbNicolas Capens				}
1620bac285a78df6a6d7a6b68784748b92805420ffbNicolas Capens
1630bac285a78df6a6d7a6b68784748b92805420ffbNicolas Capens				sw::Resource *staticBuffer = buffer ? buffer->getResource() : nullptr;
1640bac285a78df6a6d7a6b68784748b92805420ffbNicolas Capens
1650bac285a78df6a6d7a6b68784748b92805420ffbNicolas Capens				if(staticBuffer)
1660bac285a78df6a6d7a6b68784748b92805420ffbNicolas Capens				{
1670bac285a78df6a6d7a6b68784748b92805420ffbNicolas Capens					translated[i].vertexBuffer = staticBuffer;
168bffe803cd29475ca68ab1fea8a04276726fa83b7Alexis Hetu					translated[i].offset = firstVertexIndex * attrib.stride() + static_cast<int>(attrib.mOffset);
1690bac285a78df6a6d7a6b68784748b92805420ffbNicolas Capens					translated[i].stride = isInstanced ? 0 : attrib.stride();
1700bac285a78df6a6d7a6b68784748b92805420ffbNicolas Capens				}
1710bac285a78df6a6d7a6b68784748b92805420ffbNicolas Capens				else
1720bac285a78df6a6d7a6b68784748b92805420ffbNicolas Capens				{
1730bac285a78df6a6d7a6b68784748b92805420ffbNicolas Capens					unsigned int streamOffset = writeAttributeData(mStreamingBuffer, firstVertexIndex, isInstanced ? 1 : count, attrib);
1740bac285a78df6a6d7a6b68784748b92805420ffbNicolas Capens
1750bac285a78df6a6d7a6b68784748b92805420ffbNicolas Capens					if(streamOffset == ~0u)
1760bac285a78df6a6d7a6b68784748b92805420ffbNicolas Capens					{
1770bac285a78df6a6d7a6b68784748b92805420ffbNicolas Capens						return GL_OUT_OF_MEMORY;
1780bac285a78df6a6d7a6b68784748b92805420ffbNicolas Capens					}
1790bac285a78df6a6d7a6b68784748b92805420ffbNicolas Capens
1800bac285a78df6a6d7a6b68784748b92805420ffbNicolas Capens					translated[i].vertexBuffer = mStreamingBuffer->getResource();
1810bac285a78df6a6d7a6b68784748b92805420ffbNicolas Capens					translated[i].offset = streamOffset;
1820bac285a78df6a6d7a6b68784748b92805420ffbNicolas Capens					translated[i].stride = isInstanced ? 0 : attrib.typeSize();
1830bac285a78df6a6d7a6b68784748b92805420ffbNicolas Capens				}
1840bac285a78df6a6d7a6b68784748b92805420ffbNicolas Capens
1850bac285a78df6a6d7a6b68784748b92805420ffbNicolas Capens				switch(attrib.mType)
1860bac285a78df6a6d7a6b68784748b92805420ffbNicolas Capens				{
1870bac285a78df6a6d7a6b68784748b92805420ffbNicolas Capens				case GL_BYTE:           translated[i].type = sw::STREAMTYPE_SBYTE;  break;
1880bac285a78df6a6d7a6b68784748b92805420ffbNicolas Capens				case GL_UNSIGNED_BYTE:  translated[i].type = sw::STREAMTYPE_BYTE;   break;
1890bac285a78df6a6d7a6b68784748b92805420ffbNicolas Capens				case GL_SHORT:          translated[i].type = sw::STREAMTYPE_SHORT;  break;
1900bac285a78df6a6d7a6b68784748b92805420ffbNicolas Capens				case GL_UNSIGNED_SHORT: translated[i].type = sw::STREAMTYPE_USHORT; break;
1910bac285a78df6a6d7a6b68784748b92805420ffbNicolas Capens				case GL_INT:            translated[i].type = sw::STREAMTYPE_INT;    break;
1920bac285a78df6a6d7a6b68784748b92805420ffbNicolas Capens				case GL_UNSIGNED_INT:   translated[i].type = sw::STREAMTYPE_UINT;   break;
1930bac285a78df6a6d7a6b68784748b92805420ffbNicolas Capens				case GL_FIXED:          translated[i].type = sw::STREAMTYPE_FIXED;  break;
1940bac285a78df6a6d7a6b68784748b92805420ffbNicolas Capens				case GL_FLOAT:          translated[i].type = sw::STREAMTYPE_FLOAT;  break;
19570085ba50becdb3b19b84e54383725e5cfeab17cAlexis Hetu				case GL_HALF_FLOAT:     translated[i].type = sw::STREAMTYPE_HALF;   break;
19684d0e22331ea67a91156ddd57262adc1f0a38596Nicolas Capens				case GL_HALF_FLOAT_OES: translated[i].type = sw::STREAMTYPE_HALF;   break;
19770085ba50becdb3b19b84e54383725e5cfeab17cAlexis Hetu				case GL_INT_2_10_10_10_REV:          translated[i].type = sw::STREAMTYPE_2_10_10_10_INT;  break;
19870085ba50becdb3b19b84e54383725e5cfeab17cAlexis Hetu				case GL_UNSIGNED_INT_2_10_10_10_REV: translated[i].type = sw::STREAMTYPE_2_10_10_10_UINT; break;
1990bac285a78df6a6d7a6b68784748b92805420ffbNicolas Capens				default: UNREACHABLE(attrib.mType); translated[i].type = sw::STREAMTYPE_FLOAT;  break;
2000bac285a78df6a6d7a6b68784748b92805420ffbNicolas Capens				}
2010bac285a78df6a6d7a6b68784748b92805420ffbNicolas Capens
2020bac285a78df6a6d7a6b68784748b92805420ffbNicolas Capens				translated[i].count = attrib.mSize;
2030bac285a78df6a6d7a6b68784748b92805420ffbNicolas Capens				translated[i].normalized = attrib.mNormalized;
2040bac285a78df6a6d7a6b68784748b92805420ffbNicolas Capens			}
2050bac285a78df6a6d7a6b68784748b92805420ffbNicolas Capens			else
2060bac285a78df6a6d7a6b68784748b92805420ffbNicolas Capens			{
2070bac285a78df6a6d7a6b68784748b92805420ffbNicolas Capens				if(mDirtyCurrentValue[i])
2080bac285a78df6a6d7a6b68784748b92805420ffbNicolas Capens				{
2090bac285a78df6a6d7a6b68784748b92805420ffbNicolas Capens					delete mCurrentValueBuffer[i];
2100bac285a78df6a6d7a6b68784748b92805420ffbNicolas Capens					mCurrentValueBuffer[i] = new ConstantVertexBuffer(attrib.getCurrentValueBitsAsFloat(0), attrib.getCurrentValueBitsAsFloat(1), attrib.getCurrentValueBitsAsFloat(2), attrib.getCurrentValueBitsAsFloat(3));
2110bac285a78df6a6d7a6b68784748b92805420ffbNicolas Capens					mDirtyCurrentValue[i] = false;
2120bac285a78df6a6d7a6b68784748b92805420ffbNicolas Capens				}
2130bac285a78df6a6d7a6b68784748b92805420ffbNicolas Capens
2140bac285a78df6a6d7a6b68784748b92805420ffbNicolas Capens				translated[i].vertexBuffer = mCurrentValueBuffer[i]->getResource();
2150bac285a78df6a6d7a6b68784748b92805420ffbNicolas Capens
2166125b66df9208481b41d28c1f8b1b6576529d3c5Alexis Hetu				switch(attrib.currentValueType())
2176125b66df9208481b41d28c1f8b1b6576529d3c5Alexis Hetu				{
2186125b66df9208481b41d28c1f8b1b6576529d3c5Alexis Hetu				case GL_INT:
2196125b66df9208481b41d28c1f8b1b6576529d3c5Alexis Hetu					translated[i].type = sw::STREAMTYPE_INT;
2206125b66df9208481b41d28c1f8b1b6576529d3c5Alexis Hetu					break;
2216125b66df9208481b41d28c1f8b1b6576529d3c5Alexis Hetu				case GL_UNSIGNED_INT:
2226125b66df9208481b41d28c1f8b1b6576529d3c5Alexis Hetu					translated[i].type = sw::STREAMTYPE_UINT;
2236125b66df9208481b41d28c1f8b1b6576529d3c5Alexis Hetu					break;
2246125b66df9208481b41d28c1f8b1b6576529d3c5Alexis Hetu				default:
2256125b66df9208481b41d28c1f8b1b6576529d3c5Alexis Hetu					translated[i].type = sw::STREAMTYPE_FLOAT;
2266125b66df9208481b41d28c1f8b1b6576529d3c5Alexis Hetu					break;
2276125b66df9208481b41d28c1f8b1b6576529d3c5Alexis Hetu				}
2280bac285a78df6a6d7a6b68784748b92805420ffbNicolas Capens				translated[i].count = 4;
2290bac285a78df6a6d7a6b68784748b92805420ffbNicolas Capens				translated[i].stride = 0;
2300bac285a78df6a6d7a6b68784748b92805420ffbNicolas Capens				translated[i].offset = 0;
2316125b66df9208481b41d28c1f8b1b6576529d3c5Alexis Hetu				translated[i].normalized = false;
2320bac285a78df6a6d7a6b68784748b92805420ffbNicolas Capens			}
2330bac285a78df6a6d7a6b68784748b92805420ffbNicolas Capens		}
2340bac285a78df6a6d7a6b68784748b92805420ffbNicolas Capens	}
2350bac285a78df6a6d7a6b68784748b92805420ffbNicolas Capens
2360bac285a78df6a6d7a6b68784748b92805420ffbNicolas Capens	return GL_NO_ERROR;
2370bac285a78df6a6d7a6b68784748b92805420ffbNicolas Capens}
2380bac285a78df6a6d7a6b68784748b92805420ffbNicolas Capens
2390bac285a78df6a6d7a6b68784748b92805420ffbNicolas CapensVertexBuffer::VertexBuffer(unsigned int size) : mVertexBuffer(nullptr)
2400bac285a78df6a6d7a6b68784748b92805420ffbNicolas Capens{
2410bac285a78df6a6d7a6b68784748b92805420ffbNicolas Capens	if(size > 0)
2420bac285a78df6a6d7a6b68784748b92805420ffbNicolas Capens	{
2430bac285a78df6a6d7a6b68784748b92805420ffbNicolas Capens		mVertexBuffer = new sw::Resource(size + 1024);
2440bac285a78df6a6d7a6b68784748b92805420ffbNicolas Capens
2450bac285a78df6a6d7a6b68784748b92805420ffbNicolas Capens		if(!mVertexBuffer)
2460bac285a78df6a6d7a6b68784748b92805420ffbNicolas Capens		{
2470bac285a78df6a6d7a6b68784748b92805420ffbNicolas Capens			ERR("Out of memory allocating a vertex buffer of size %u.", size);
2480bac285a78df6a6d7a6b68784748b92805420ffbNicolas Capens		}
2490bac285a78df6a6d7a6b68784748b92805420ffbNicolas Capens	}
2500bac285a78df6a6d7a6b68784748b92805420ffbNicolas Capens}
2510bac285a78df6a6d7a6b68784748b92805420ffbNicolas Capens
2520bac285a78df6a6d7a6b68784748b92805420ffbNicolas CapensVertexBuffer::~VertexBuffer()
2530bac285a78df6a6d7a6b68784748b92805420ffbNicolas Capens{
2540bac285a78df6a6d7a6b68784748b92805420ffbNicolas Capens	if(mVertexBuffer)
2550bac285a78df6a6d7a6b68784748b92805420ffbNicolas Capens	{
2560bac285a78df6a6d7a6b68784748b92805420ffbNicolas Capens		mVertexBuffer->destruct();
2570bac285a78df6a6d7a6b68784748b92805420ffbNicolas Capens	}
2580bac285a78df6a6d7a6b68784748b92805420ffbNicolas Capens}
2590bac285a78df6a6d7a6b68784748b92805420ffbNicolas Capens
2600bac285a78df6a6d7a6b68784748b92805420ffbNicolas Capensvoid VertexBuffer::unmap()
2610bac285a78df6a6d7a6b68784748b92805420ffbNicolas Capens{
2620bac285a78df6a6d7a6b68784748b92805420ffbNicolas Capens	if(mVertexBuffer)
2630bac285a78df6a6d7a6b68784748b92805420ffbNicolas Capens	{
2640bac285a78df6a6d7a6b68784748b92805420ffbNicolas Capens		mVertexBuffer->unlock();
2650bac285a78df6a6d7a6b68784748b92805420ffbNicolas Capens	}
2660bac285a78df6a6d7a6b68784748b92805420ffbNicolas Capens}
2670bac285a78df6a6d7a6b68784748b92805420ffbNicolas Capens
2680bac285a78df6a6d7a6b68784748b92805420ffbNicolas Capenssw::Resource *VertexBuffer::getResource() const
2690bac285a78df6a6d7a6b68784748b92805420ffbNicolas Capens{
2700bac285a78df6a6d7a6b68784748b92805420ffbNicolas Capens	return mVertexBuffer;
2710bac285a78df6a6d7a6b68784748b92805420ffbNicolas Capens}
2720bac285a78df6a6d7a6b68784748b92805420ffbNicolas Capens
2730bac285a78df6a6d7a6b68784748b92805420ffbNicolas CapensConstantVertexBuffer::ConstantVertexBuffer(float x, float y, float z, float w) : VertexBuffer(4 * sizeof(float))
2740bac285a78df6a6d7a6b68784748b92805420ffbNicolas Capens{
2750bac285a78df6a6d7a6b68784748b92805420ffbNicolas Capens	if(mVertexBuffer)
2760bac285a78df6a6d7a6b68784748b92805420ffbNicolas Capens	{
2770bac285a78df6a6d7a6b68784748b92805420ffbNicolas Capens		float *vector = (float*)mVertexBuffer->lock(sw::PUBLIC);
2780bac285a78df6a6d7a6b68784748b92805420ffbNicolas Capens
2790bac285a78df6a6d7a6b68784748b92805420ffbNicolas Capens		vector[0] = x;
2800bac285a78df6a6d7a6b68784748b92805420ffbNicolas Capens		vector[1] = y;
2810bac285a78df6a6d7a6b68784748b92805420ffbNicolas Capens		vector[2] = z;
2820bac285a78df6a6d7a6b68784748b92805420ffbNicolas Capens		vector[3] = w;
2830bac285a78df6a6d7a6b68784748b92805420ffbNicolas Capens
2840bac285a78df6a6d7a6b68784748b92805420ffbNicolas Capens		mVertexBuffer->unlock();
2850bac285a78df6a6d7a6b68784748b92805420ffbNicolas Capens	}
2860bac285a78df6a6d7a6b68784748b92805420ffbNicolas Capens}
2870bac285a78df6a6d7a6b68784748b92805420ffbNicolas Capens
2880bac285a78df6a6d7a6b68784748b92805420ffbNicolas CapensConstantVertexBuffer::~ConstantVertexBuffer()
2890bac285a78df6a6d7a6b68784748b92805420ffbNicolas Capens{
2900bac285a78df6a6d7a6b68784748b92805420ffbNicolas Capens}
2910bac285a78df6a6d7a6b68784748b92805420ffbNicolas Capens
2920bac285a78df6a6d7a6b68784748b92805420ffbNicolas CapensStreamingVertexBuffer::StreamingVertexBuffer(unsigned int size) : VertexBuffer(size)
2930bac285a78df6a6d7a6b68784748b92805420ffbNicolas Capens{
2940bac285a78df6a6d7a6b68784748b92805420ffbNicolas Capens	mBufferSize = size;
2950bac285a78df6a6d7a6b68784748b92805420ffbNicolas Capens	mWritePosition = 0;
2960bac285a78df6a6d7a6b68784748b92805420ffbNicolas Capens	mRequiredSpace = 0;
2970bac285a78df6a6d7a6b68784748b92805420ffbNicolas Capens}
2980bac285a78df6a6d7a6b68784748b92805420ffbNicolas Capens
2990bac285a78df6a6d7a6b68784748b92805420ffbNicolas CapensStreamingVertexBuffer::~StreamingVertexBuffer()
3000bac285a78df6a6d7a6b68784748b92805420ffbNicolas Capens{
3010bac285a78df6a6d7a6b68784748b92805420ffbNicolas Capens}
3020bac285a78df6a6d7a6b68784748b92805420ffbNicolas Capens
3030bac285a78df6a6d7a6b68784748b92805420ffbNicolas Capensvoid StreamingVertexBuffer::addRequiredSpace(unsigned int requiredSpace)
3040bac285a78df6a6d7a6b68784748b92805420ffbNicolas Capens{
3050bac285a78df6a6d7a6b68784748b92805420ffbNicolas Capens	mRequiredSpace += requiredSpace;
3060bac285a78df6a6d7a6b68784748b92805420ffbNicolas Capens}
3070bac285a78df6a6d7a6b68784748b92805420ffbNicolas Capens
3080bac285a78df6a6d7a6b68784748b92805420ffbNicolas Capensvoid *StreamingVertexBuffer::map(const VertexAttribute &attribute, unsigned int requiredSpace, unsigned int *offset)
3090bac285a78df6a6d7a6b68784748b92805420ffbNicolas Capens{
3100bac285a78df6a6d7a6b68784748b92805420ffbNicolas Capens	void *mapPtr = nullptr;
3110bac285a78df6a6d7a6b68784748b92805420ffbNicolas Capens
3120bac285a78df6a6d7a6b68784748b92805420ffbNicolas Capens	if(mVertexBuffer)
3130bac285a78df6a6d7a6b68784748b92805420ffbNicolas Capens	{
3140bac285a78df6a6d7a6b68784748b92805420ffbNicolas Capens		// We can use a private lock because we never overwrite the content
3150bac285a78df6a6d7a6b68784748b92805420ffbNicolas Capens		mapPtr = (char*)mVertexBuffer->lock(sw::PRIVATE) + mWritePosition;
3160bac285a78df6a6d7a6b68784748b92805420ffbNicolas Capens
3170bac285a78df6a6d7a6b68784748b92805420ffbNicolas Capens		*offset = mWritePosition;
3180bac285a78df6a6d7a6b68784748b92805420ffbNicolas Capens		mWritePosition += requiredSpace;
3190bac285a78df6a6d7a6b68784748b92805420ffbNicolas Capens	}
3200bac285a78df6a6d7a6b68784748b92805420ffbNicolas Capens
3210bac285a78df6a6d7a6b68784748b92805420ffbNicolas Capens	return mapPtr;
3220bac285a78df6a6d7a6b68784748b92805420ffbNicolas Capens}
3230bac285a78df6a6d7a6b68784748b92805420ffbNicolas Capens
3240bac285a78df6a6d7a6b68784748b92805420ffbNicolas Capensvoid StreamingVertexBuffer::reserveRequiredSpace()
3250bac285a78df6a6d7a6b68784748b92805420ffbNicolas Capens{
3260bac285a78df6a6d7a6b68784748b92805420ffbNicolas Capens	if(mRequiredSpace > mBufferSize)
3270bac285a78df6a6d7a6b68784748b92805420ffbNicolas Capens	{
3280bac285a78df6a6d7a6b68784748b92805420ffbNicolas Capens		if(mVertexBuffer)
3290bac285a78df6a6d7a6b68784748b92805420ffbNicolas Capens		{
3300bac285a78df6a6d7a6b68784748b92805420ffbNicolas Capens			mVertexBuffer->destruct();
3310bac285a78df6a6d7a6b68784748b92805420ffbNicolas Capens			mVertexBuffer = 0;
3320bac285a78df6a6d7a6b68784748b92805420ffbNicolas Capens		}
3330bac285a78df6a6d7a6b68784748b92805420ffbNicolas Capens
3340bac285a78df6a6d7a6b68784748b92805420ffbNicolas Capens		mBufferSize = std::max(mRequiredSpace, 3 * mBufferSize / 2);   // 1.5 x mBufferSize is arbitrary and should be checked to see we don't have too many reallocations.
3350bac285a78df6a6d7a6b68784748b92805420ffbNicolas Capens
3360bac285a78df6a6d7a6b68784748b92805420ffbNicolas Capens		mVertexBuffer = new sw::Resource(mBufferSize);
3370bac285a78df6a6d7a6b68784748b92805420ffbNicolas Capens
3380bac285a78df6a6d7a6b68784748b92805420ffbNicolas Capens		if(!mVertexBuffer)
3390bac285a78df6a6d7a6b68784748b92805420ffbNicolas Capens		{
3400bac285a78df6a6d7a6b68784748b92805420ffbNicolas Capens			ERR("Out of memory allocating a vertex buffer of size %u.", mBufferSize);
3410bac285a78df6a6d7a6b68784748b92805420ffbNicolas Capens		}
3420bac285a78df6a6d7a6b68784748b92805420ffbNicolas Capens
3430bac285a78df6a6d7a6b68784748b92805420ffbNicolas Capens		mWritePosition = 0;
3440bac285a78df6a6d7a6b68784748b92805420ffbNicolas Capens	}
3450bac285a78df6a6d7a6b68784748b92805420ffbNicolas Capens	else if(mWritePosition + mRequiredSpace > mBufferSize)   // Recycle
3460bac285a78df6a6d7a6b68784748b92805420ffbNicolas Capens	{
3470bac285a78df6a6d7a6b68784748b92805420ffbNicolas Capens		if(mVertexBuffer)
3480bac285a78df6a6d7a6b68784748b92805420ffbNicolas Capens		{
3490bac285a78df6a6d7a6b68784748b92805420ffbNicolas Capens			mVertexBuffer->destruct();
3500bac285a78df6a6d7a6b68784748b92805420ffbNicolas Capens			mVertexBuffer = new sw::Resource(mBufferSize);
3510bac285a78df6a6d7a6b68784748b92805420ffbNicolas Capens		}
3520bac285a78df6a6d7a6b68784748b92805420ffbNicolas Capens
3530bac285a78df6a6d7a6b68784748b92805420ffbNicolas Capens		mWritePosition = 0;
3540bac285a78df6a6d7a6b68784748b92805420ffbNicolas Capens	}
3550bac285a78df6a6d7a6b68784748b92805420ffbNicolas Capens
3560bac285a78df6a6d7a6b68784748b92805420ffbNicolas Capens	mRequiredSpace = 0;
3570bac285a78df6a6d7a6b68784748b92805420ffbNicolas Capens}
3580bac285a78df6a6d7a6b68784748b92805420ffbNicolas Capens
3590bac285a78df6a6d7a6b68784748b92805420ffbNicolas Capens}
360