Home | History | Annotate | Download | only in libGLES_CM
      1 // Copyright 2016 The SwiftShader Authors. All Rights Reserved.
      2 //
      3 // Licensed under the Apache License, Version 2.0 (the "License");
      4 // you may not use this file except in compliance with the License.
      5 // You may obtain a copy of the License at
      6 //
      7 //    http://www.apache.org/licenses/LICENSE-2.0
      8 //
      9 // Unless required by applicable law or agreed to in writing, software
     10 // distributed under the License is distributed on an "AS IS" BASIS,
     11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     12 // See the License for the specific language governing permissions and
     13 // limitations under the License.
     14 
     15 // VertexDataManager.h: Defines the VertexDataManager, a class that
     16 // runs the Buffer translation process.
     17 
     18 #include "VertexDataManager.h"
     19 
     20 #include "Buffer.h"
     21 #include "IndexDataManager.h"
     22 #include "common/debug.h"
     23 
     24 #include <algorithm>
     25 
     26 namespace
     27 {
     28 	enum {INITIAL_STREAM_BUFFER_SIZE = 1024 * 1024};
     29 }
     30 
     31 namespace es1
     32 {
     33 
     34 VertexDataManager::VertexDataManager(Context *context) : mContext(context)
     35 {
     36 	for(int i = 0; i < MAX_VERTEX_ATTRIBS; i++)
     37 	{
     38 		mDirtyCurrentValue[i] = true;
     39 		mCurrentValueBuffer[i] = nullptr;
     40 	}
     41 
     42 	mStreamingBuffer = new StreamingVertexBuffer(INITIAL_STREAM_BUFFER_SIZE);
     43 
     44 	if(!mStreamingBuffer)
     45 	{
     46 		ERR("Failed to allocate the streaming vertex buffer.");
     47 	}
     48 }
     49 
     50 VertexDataManager::~VertexDataManager()
     51 {
     52 	delete mStreamingBuffer;
     53 
     54 	for(int i = 0; i < MAX_VERTEX_ATTRIBS; i++)
     55 	{
     56 		delete mCurrentValueBuffer[i];
     57 	}
     58 }
     59 
     60 unsigned int VertexDataManager::writeAttributeData(StreamingVertexBuffer *vertexBuffer, GLint start, GLsizei count, const VertexAttribute &attribute)
     61 {
     62 	Buffer *buffer = attribute.mBoundBuffer;
     63 
     64 	int inputStride = attribute.stride();
     65 	int elementSize = attribute.typeSize();
     66 	unsigned int streamOffset = 0;
     67 
     68 	char *output = nullptr;
     69 
     70 	if(vertexBuffer)
     71 	{
     72 		output = (char*)vertexBuffer->map(attribute, attribute.typeSize() * count, &streamOffset);
     73 	}
     74 
     75 	if(!output)
     76 	{
     77 		ERR("Failed to map vertex buffer.");
     78 		return ~0u;
     79 	}
     80 
     81 	const char *input = nullptr;
     82 
     83 	if(buffer)
     84 	{
     85 		int offset = attribute.mOffset;
     86 
     87 		input = static_cast<const char*>(buffer->data()) + offset;
     88 	}
     89 	else
     90 	{
     91 		input = static_cast<const char*>(attribute.mPointer);
     92 	}
     93 
     94 	input += inputStride * start;
     95 
     96 	if(inputStride == elementSize)
     97 	{
     98 		memcpy(output, input, count * inputStride);
     99 	}
    100 	else
    101 	{
    102 		for(int i = 0; i < count; i++)
    103 		{
    104 			memcpy(output, input, elementSize);
    105 			output += elementSize;
    106 			input += inputStride;
    107 		}
    108 	}
    109 
    110 	vertexBuffer->unmap();
    111 
    112 	return streamOffset;
    113 }
    114 
    115 GLenum VertexDataManager::prepareVertexData(GLint start, GLsizei count, TranslatedAttribute *translated)
    116 {
    117 	if(!mStreamingBuffer)
    118 	{
    119 		return GL_OUT_OF_MEMORY;
    120 	}
    121 
    122 	const VertexAttributeArray &attribs = mContext->getVertexAttributes();
    123 
    124 	// Determine the required storage size per used buffer
    125 	for(int i = 0; i < MAX_VERTEX_ATTRIBS; i++)
    126 	{
    127 		if(attribs[i].mArrayEnabled)
    128 		{
    129 			if(!attribs[i].mBoundBuffer)
    130 			{
    131 				mStreamingBuffer->addRequiredSpace(attribs[i].typeSize() * count);
    132 			}
    133 		}
    134 	}
    135 
    136 	mStreamingBuffer->reserveRequiredSpace();
    137 
    138 	// Perform the vertex data translations
    139 	for(int i = 0; i < MAX_VERTEX_ATTRIBS; i++)
    140 	{
    141 		if(attribs[i].mArrayEnabled)
    142 		{
    143 			Buffer *buffer = attribs[i].mBoundBuffer;
    144 
    145 			if(!buffer && attribs[i].mPointer == nullptr)
    146 			{
    147 				// This is an application error that would normally result in a crash, but we catch it and return an error
    148 				ERR("An enabled vertex array has no buffer and no pointer.");
    149 				return GL_INVALID_OPERATION;
    150 			}
    151 
    152 			sw::Resource *staticBuffer = buffer ? buffer->getResource() : nullptr;
    153 
    154 			if(staticBuffer)
    155 			{
    156 				translated[i].vertexBuffer = staticBuffer;
    157 				translated[i].offset = start * attribs[i].stride() + attribs[i].mOffset;
    158 				translated[i].stride = attribs[i].stride();
    159 			}
    160 			else
    161 			{
    162 				unsigned int streamOffset = writeAttributeData(mStreamingBuffer, start, count, attribs[i]);
    163 
    164 				if(streamOffset == ~0u)
    165 				{
    166 					return GL_OUT_OF_MEMORY;
    167 				}
    168 
    169 				translated[i].vertexBuffer = mStreamingBuffer->getResource();
    170 				translated[i].offset = streamOffset;
    171 				translated[i].stride = attribs[i].typeSize();
    172 			}
    173 
    174 			switch(attribs[i].mType)
    175 			{
    176 			case GL_BYTE:           translated[i].type = sw::STREAMTYPE_SBYTE;  break;
    177 			case GL_UNSIGNED_BYTE:  translated[i].type = sw::STREAMTYPE_BYTE;   break;
    178 			case GL_SHORT:          translated[i].type = sw::STREAMTYPE_SHORT;  break;
    179 			case GL_UNSIGNED_SHORT: translated[i].type = sw::STREAMTYPE_USHORT; break;
    180 			case GL_INT:            translated[i].type = sw::STREAMTYPE_INT;    break;
    181 			case GL_UNSIGNED_INT:   translated[i].type = sw::STREAMTYPE_UINT;   break;
    182 			case GL_FIXED:          translated[i].type = sw::STREAMTYPE_FIXED;  break;
    183 			case GL_FLOAT:          translated[i].type = sw::STREAMTYPE_FLOAT;  break;
    184 			default: UNREACHABLE(attribs[i].mType); translated[i].type = sw::STREAMTYPE_FLOAT;  break;
    185 			}
    186 
    187 			translated[i].count = attribs[i].mSize;
    188 			translated[i].normalized = attribs[i].mNormalized;
    189 		}
    190 		else
    191 		{
    192 			if(mDirtyCurrentValue[i])
    193 			{
    194 				delete mCurrentValueBuffer[i];
    195 				mCurrentValueBuffer[i] = new ConstantVertexBuffer(attribs[i].mCurrentValue[0], attribs[i].mCurrentValue[1], attribs[i].mCurrentValue[2], attribs[i].mCurrentValue[3]);
    196 				mDirtyCurrentValue[i] = false;
    197 			}
    198 
    199 			translated[i].vertexBuffer = mCurrentValueBuffer[i]->getResource();
    200 
    201 			translated[i].type = sw::STREAMTYPE_FLOAT;
    202 			translated[i].count = 4;
    203 			translated[i].stride = 0;
    204 			translated[i].offset = 0;
    205 		}
    206 	}
    207 
    208 	return GL_NO_ERROR;
    209 }
    210 
    211 VertexBuffer::VertexBuffer(unsigned int size) : mVertexBuffer(nullptr)
    212 {
    213 	if(size > 0)
    214 	{
    215 		mVertexBuffer = new sw::Resource(size + 1024);
    216 
    217 		if(!mVertexBuffer)
    218 		{
    219 			ERR("Out of memory allocating a vertex buffer of size %u.", size);
    220 		}
    221 	}
    222 }
    223 
    224 VertexBuffer::~VertexBuffer()
    225 {
    226 	if(mVertexBuffer)
    227 	{
    228 		mVertexBuffer->destruct();
    229 	}
    230 }
    231 
    232 void VertexBuffer::unmap()
    233 {
    234 	if(mVertexBuffer)
    235 	{
    236 		mVertexBuffer->unlock();
    237 	}
    238 }
    239 
    240 sw::Resource *VertexBuffer::getResource() const
    241 {
    242 	return mVertexBuffer;
    243 }
    244 
    245 ConstantVertexBuffer::ConstantVertexBuffer(float x, float y, float z, float w) : VertexBuffer(4 * sizeof(float))
    246 {
    247 	if(mVertexBuffer)
    248 	{
    249 		float *vector = (float*)mVertexBuffer->lock(sw::PUBLIC);
    250 
    251 		vector[0] = x;
    252 		vector[1] = y;
    253 		vector[2] = z;
    254 		vector[3] = w;
    255 
    256 		mVertexBuffer->unlock();
    257 	}
    258 }
    259 
    260 ConstantVertexBuffer::~ConstantVertexBuffer()
    261 {
    262 }
    263 
    264 StreamingVertexBuffer::StreamingVertexBuffer(unsigned int size) : VertexBuffer(size)
    265 {
    266 	mBufferSize = size;
    267 	mWritePosition = 0;
    268 	mRequiredSpace = 0;
    269 }
    270 
    271 StreamingVertexBuffer::~StreamingVertexBuffer()
    272 {
    273 }
    274 
    275 void StreamingVertexBuffer::addRequiredSpace(unsigned int requiredSpace)
    276 {
    277 	mRequiredSpace += requiredSpace;
    278 }
    279 
    280 void *StreamingVertexBuffer::map(const VertexAttribute &attribute, unsigned int requiredSpace, unsigned int *offset)
    281 {
    282 	void *mapPtr = nullptr;
    283 
    284 	if(mVertexBuffer)
    285 	{
    286 		// We can use a private lock because we never overwrite the content
    287 		mapPtr = (char*)mVertexBuffer->lock(sw::PRIVATE) + mWritePosition;
    288 
    289 		*offset = mWritePosition;
    290 		mWritePosition += requiredSpace;
    291 	}
    292 
    293 	return mapPtr;
    294 }
    295 
    296 void StreamingVertexBuffer::reserveRequiredSpace()
    297 {
    298 	if(mRequiredSpace > mBufferSize)
    299 	{
    300 		if(mVertexBuffer)
    301 		{
    302 			mVertexBuffer->destruct();
    303 			mVertexBuffer = 0;
    304 		}
    305 
    306 		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.
    307 
    308 		mVertexBuffer = new sw::Resource(mBufferSize);
    309 
    310 		if(!mVertexBuffer)
    311 		{
    312 			ERR("Out of memory allocating a vertex buffer of size %u.", mBufferSize);
    313 		}
    314 
    315 		mWritePosition = 0;
    316 	}
    317 	else if(mWritePosition + mRequiredSpace > mBufferSize)   // Recycle
    318 	{
    319 		if(mVertexBuffer)
    320 		{
    321 			mVertexBuffer->destruct();
    322 			mVertexBuffer = new sw::Resource(mBufferSize);
    323 		}
    324 
    325 		mWritePosition = 0;
    326 	}
    327 
    328 	mRequiredSpace = 0;
    329 }
    330 
    331 }
    332