gfx/angle/src/libGLESv2/renderer/IndexDataManager.cpp

changeset 0
6474c204b198
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/gfx/angle/src/libGLESv2/renderer/IndexDataManager.cpp	Wed Dec 31 06:09:35 2014 +0100
     1.3 @@ -0,0 +1,333 @@
     1.4 +#include "precompiled.h"
     1.5 +//
     1.6 +// Copyright (c) 2002-2012 The ANGLE Project Authors. All rights reserved.
     1.7 +// Use of this source code is governed by a BSD-style license that can be
     1.8 +// found in the LICENSE file.
     1.9 +//
    1.10 +
    1.11 +// IndexDataManager.cpp: Defines the IndexDataManager, a class that
    1.12 +// runs the Buffer translation process for index buffers.
    1.13 +
    1.14 +#include "libGLESv2/renderer/IndexDataManager.h"
    1.15 +#include "libGLESv2/renderer/BufferStorage.h"
    1.16 +
    1.17 +#include "libGLESv2/Buffer.h"
    1.18 +#include "libGLESv2/main.h"
    1.19 +#include "libGLESv2/utilities.h"
    1.20 +#include "libGLESv2/renderer/IndexBuffer.h"
    1.21 +
    1.22 +namespace rx
    1.23 +{
    1.24 +
    1.25 +IndexDataManager::IndexDataManager(Renderer *renderer) : mRenderer(renderer)
    1.26 +{
    1.27 +    mStreamingBufferShort = new StreamingIndexBufferInterface(mRenderer);
    1.28 +    if (!mStreamingBufferShort->reserveBufferSpace(INITIAL_INDEX_BUFFER_SIZE, GL_UNSIGNED_SHORT))
    1.29 +    {
    1.30 +        delete mStreamingBufferShort;
    1.31 +        mStreamingBufferShort = NULL;
    1.32 +    }
    1.33 +
    1.34 +    mStreamingBufferInt = new StreamingIndexBufferInterface(mRenderer);
    1.35 +    if (!mStreamingBufferInt->reserveBufferSpace(INITIAL_INDEX_BUFFER_SIZE, GL_UNSIGNED_INT))
    1.36 +    {
    1.37 +        delete mStreamingBufferInt;
    1.38 +        mStreamingBufferInt = NULL;
    1.39 +    }
    1.40 +
    1.41 +    if (!mStreamingBufferShort)
    1.42 +    {
    1.43 +        // Make sure both buffers are deleted.
    1.44 +        delete mStreamingBufferInt;
    1.45 +        mStreamingBufferInt = NULL;
    1.46 +
    1.47 +        ERR("Failed to allocate the streaming index buffer(s).");
    1.48 +    }
    1.49 +
    1.50 +    mCountingBuffer = NULL;
    1.51 +}
    1.52 +
    1.53 +IndexDataManager::~IndexDataManager()
    1.54 +{
    1.55 +    delete mStreamingBufferShort;
    1.56 +    delete mStreamingBufferInt;
    1.57 +    delete mCountingBuffer;
    1.58 +}
    1.59 +
    1.60 +static void convertIndices(GLenum type, const void *input, GLsizei count, void *output)
    1.61 +{
    1.62 +    if (type == GL_UNSIGNED_BYTE)
    1.63 +    {
    1.64 +        const GLubyte *in = static_cast<const GLubyte*>(input);
    1.65 +        GLushort *out = static_cast<GLushort*>(output);
    1.66 +
    1.67 +        for (GLsizei i = 0; i < count; i++)
    1.68 +        {
    1.69 +            out[i] = in[i];
    1.70 +        }
    1.71 +    }
    1.72 +    else if (type == GL_UNSIGNED_INT)
    1.73 +    {
    1.74 +        memcpy(output, input, count * sizeof(GLuint));
    1.75 +    }
    1.76 +    else if (type == GL_UNSIGNED_SHORT)
    1.77 +    {
    1.78 +        memcpy(output, input, count * sizeof(GLushort));
    1.79 +    }
    1.80 +    else UNREACHABLE();
    1.81 +}
    1.82 +
    1.83 +template <class IndexType>
    1.84 +static void computeRange(const IndexType *indices, GLsizei count, GLuint *minIndex, GLuint *maxIndex)
    1.85 +{
    1.86 +    *minIndex = indices[0];
    1.87 +    *maxIndex = indices[0];
    1.88 +
    1.89 +    for (GLsizei i = 0; i < count; i++)
    1.90 +    {
    1.91 +        if (*minIndex > indices[i]) *minIndex = indices[i];
    1.92 +        if (*maxIndex < indices[i]) *maxIndex = indices[i];
    1.93 +    }
    1.94 +}
    1.95 +
    1.96 +static void computeRange(GLenum type, const GLvoid *indices, GLsizei count, GLuint *minIndex, GLuint *maxIndex)
    1.97 +{
    1.98 +    if (type == GL_UNSIGNED_BYTE)
    1.99 +    {
   1.100 +        computeRange(static_cast<const GLubyte*>(indices), count, minIndex, maxIndex);
   1.101 +    }
   1.102 +    else if (type == GL_UNSIGNED_INT)
   1.103 +    {
   1.104 +        computeRange(static_cast<const GLuint*>(indices), count, minIndex, maxIndex);
   1.105 +    }
   1.106 +    else if (type == GL_UNSIGNED_SHORT)
   1.107 +    {
   1.108 +        computeRange(static_cast<const GLushort*>(indices), count, minIndex, maxIndex);
   1.109 +    }
   1.110 +    else UNREACHABLE();
   1.111 +}
   1.112 +
   1.113 +GLenum IndexDataManager::prepareIndexData(GLenum type, GLsizei count, gl::Buffer *buffer, const GLvoid *indices, TranslatedIndexData *translated)
   1.114 +{
   1.115 +    if (!mStreamingBufferShort)
   1.116 +    {
   1.117 +        return GL_OUT_OF_MEMORY;
   1.118 +    }
   1.119 +
   1.120 +    GLenum destinationIndexType = (type == GL_UNSIGNED_INT) ? GL_UNSIGNED_INT : GL_UNSIGNED_SHORT;
   1.121 +    intptr_t offset = reinterpret_cast<intptr_t>(indices);
   1.122 +    bool alignedOffset = false;
   1.123 +
   1.124 +    BufferStorage *storage = NULL;
   1.125 +
   1.126 +    if (buffer != NULL)
   1.127 +    {
   1.128 +        storage = buffer->getStorage();
   1.129 +
   1.130 +        switch (type)
   1.131 +        {
   1.132 +          case GL_UNSIGNED_BYTE:  alignedOffset = (offset % sizeof(GLubyte) == 0);  break;
   1.133 +          case GL_UNSIGNED_SHORT: alignedOffset = (offset % sizeof(GLushort) == 0); break;
   1.134 +          case GL_UNSIGNED_INT:   alignedOffset = (offset % sizeof(GLuint) == 0);   break;
   1.135 +          default: UNREACHABLE(); alignedOffset = false;
   1.136 +        }
   1.137 +
   1.138 +        unsigned int typeSize = gl::ComputeTypeSize(type);
   1.139 +
   1.140 +        // check for integer overflows and underflows
   1.141 +        if (static_cast<unsigned int>(offset) > (std::numeric_limits<unsigned int>::max() / typeSize) ||
   1.142 +            static_cast<unsigned int>(count) > ((std::numeric_limits<unsigned int>::max() / typeSize) - offset))
   1.143 +        {
   1.144 +            return GL_OUT_OF_MEMORY;
   1.145 +        }
   1.146 +
   1.147 +        if (typeSize * static_cast<unsigned int>(count) + offset > storage->getSize())
   1.148 +        {
   1.149 +            return GL_INVALID_OPERATION;
   1.150 +        }
   1.151 +
   1.152 +        indices = static_cast<const GLubyte*>(storage->getData()) + offset;
   1.153 +    }
   1.154 +
   1.155 +    StreamingIndexBufferInterface *streamingBuffer = (type == GL_UNSIGNED_INT) ? mStreamingBufferInt : mStreamingBufferShort;
   1.156 +
   1.157 +    StaticIndexBufferInterface *staticBuffer = buffer ? buffer->getStaticIndexBuffer() : NULL;
   1.158 +    IndexBufferInterface *indexBuffer = streamingBuffer;
   1.159 +    bool directStorage = alignedOffset && storage && storage->supportsDirectBinding() &&
   1.160 +                         destinationIndexType == type;
   1.161 +    unsigned int streamOffset = 0;
   1.162 +
   1.163 +    if (directStorage)
   1.164 +    {
   1.165 +        indexBuffer = streamingBuffer;
   1.166 +        streamOffset = offset;
   1.167 +        storage->markBufferUsage();
   1.168 +
   1.169 +        if (!buffer->getIndexRangeCache()->findRange(type, offset, count, &translated->minIndex,
   1.170 +                                                     &translated->maxIndex, NULL))
   1.171 +        {
   1.172 +            computeRange(type, indices, count, &translated->minIndex, &translated->maxIndex);
   1.173 +            buffer->getIndexRangeCache()->addRange(type, offset, count, translated->minIndex,
   1.174 +                                                   translated->maxIndex, offset);
   1.175 +        }
   1.176 +    }
   1.177 +    else if (staticBuffer && staticBuffer->getBufferSize() != 0 && staticBuffer->getIndexType() == type && alignedOffset)
   1.178 +    {
   1.179 +        indexBuffer = staticBuffer;
   1.180 +        if (!staticBuffer->getIndexRangeCache()->findRange(type, offset, count, &translated->minIndex,
   1.181 +                                                           &translated->maxIndex, &streamOffset))
   1.182 +        {
   1.183 +            streamOffset = (offset / gl::ComputeTypeSize(type)) * gl::ComputeTypeSize(destinationIndexType);
   1.184 +            computeRange(type, indices, count, &translated->minIndex, &translated->maxIndex);
   1.185 +            staticBuffer->getIndexRangeCache()->addRange(type, offset, count, translated->minIndex,
   1.186 +                                                         translated->maxIndex, streamOffset);
   1.187 +        }
   1.188 +    }
   1.189 +    else
   1.190 +    {
   1.191 +        unsigned int convertCount = count;
   1.192 +
   1.193 +        if (staticBuffer)
   1.194 +        {
   1.195 +            if (staticBuffer->getBufferSize() == 0 && alignedOffset)
   1.196 +            {
   1.197 +                indexBuffer = staticBuffer;
   1.198 +                convertCount = storage->getSize() / gl::ComputeTypeSize(type);
   1.199 +            }
   1.200 +            else
   1.201 +            {
   1.202 +                buffer->invalidateStaticData();
   1.203 +                staticBuffer = NULL;
   1.204 +            }
   1.205 +        }
   1.206 +
   1.207 +        if (!indexBuffer)
   1.208 +        {
   1.209 +            ERR("No valid index buffer.");
   1.210 +            return GL_INVALID_OPERATION;
   1.211 +        }
   1.212 +
   1.213 +        unsigned int indexTypeSize = gl::ComputeTypeSize(destinationIndexType);
   1.214 +        if (convertCount > std::numeric_limits<unsigned int>::max() / indexTypeSize)
   1.215 +        {
   1.216 +            ERR("Reserving %u indicies of %u bytes each exceeds the maximum buffer size.", convertCount, indexTypeSize);
   1.217 +            return GL_OUT_OF_MEMORY;
   1.218 +        }
   1.219 +
   1.220 +        unsigned int bufferSizeRequired = convertCount * indexTypeSize;
   1.221 +        if (!indexBuffer->reserveBufferSpace(bufferSizeRequired, type))
   1.222 +        {
   1.223 +            ERR("Failed to reserve %u bytes in an index buffer.", bufferSizeRequired);
   1.224 +            return GL_OUT_OF_MEMORY;
   1.225 +        }
   1.226 +
   1.227 +        void* output = NULL;
   1.228 +        if (!indexBuffer->mapBuffer(bufferSizeRequired, &output, &streamOffset))
   1.229 +        {
   1.230 +            ERR("Failed to map index buffer.");
   1.231 +            return GL_OUT_OF_MEMORY;
   1.232 +        }
   1.233 +
   1.234 +        convertIndices(type, staticBuffer ? storage->getData() : indices, convertCount, output);
   1.235 +
   1.236 +        if (!indexBuffer->unmapBuffer())
   1.237 +        {
   1.238 +            ERR("Failed to unmap index buffer.");
   1.239 +            return GL_OUT_OF_MEMORY;
   1.240 +        }
   1.241 +
   1.242 +        computeRange(type, indices, count, &translated->minIndex, &translated->maxIndex);
   1.243 +
   1.244 +        if (staticBuffer)
   1.245 +        {
   1.246 +            streamOffset = (offset / gl::ComputeTypeSize(type)) * gl::ComputeTypeSize(destinationIndexType);
   1.247 +            staticBuffer->getIndexRangeCache()->addRange(type, offset, count, translated->minIndex,
   1.248 +                                                         translated->maxIndex, streamOffset);
   1.249 +        }
   1.250 +    }
   1.251 +
   1.252 +    translated->storage = directStorage ? storage : NULL;
   1.253 +    translated->indexBuffer = indexBuffer->getIndexBuffer();
   1.254 +    translated->serial = directStorage ? storage->getSerial() : indexBuffer->getSerial();
   1.255 +    translated->startIndex = streamOffset / gl::ComputeTypeSize(destinationIndexType);
   1.256 +    translated->startOffset = streamOffset;
   1.257 +
   1.258 +    if (buffer)
   1.259 +    {
   1.260 +        buffer->promoteStaticUsage(count * gl::ComputeTypeSize(type));
   1.261 +    }
   1.262 +
   1.263 +    return GL_NO_ERROR;
   1.264 +}
   1.265 +
   1.266 +StaticIndexBufferInterface *IndexDataManager::getCountingIndices(GLsizei count)
   1.267 +{
   1.268 +    if (count <= 65536)   // 16-bit indices
   1.269 +    {
   1.270 +        const unsigned int spaceNeeded = count * sizeof(unsigned short);
   1.271 +
   1.272 +        if (!mCountingBuffer || mCountingBuffer->getBufferSize() < spaceNeeded)
   1.273 +        {
   1.274 +            delete mCountingBuffer;
   1.275 +            mCountingBuffer = new StaticIndexBufferInterface(mRenderer);
   1.276 +            mCountingBuffer->reserveBufferSpace(spaceNeeded, GL_UNSIGNED_SHORT);
   1.277 +
   1.278 +            void* mappedMemory = NULL;
   1.279 +            if (!mCountingBuffer->mapBuffer(spaceNeeded, &mappedMemory, NULL))
   1.280 +            {
   1.281 +                ERR("Failed to map counting buffer.");
   1.282 +                return NULL;
   1.283 +            }
   1.284 +
   1.285 +            unsigned short *data = reinterpret_cast<unsigned short*>(mappedMemory);
   1.286 +            for(int i = 0; i < count; i++)
   1.287 +            {
   1.288 +                data[i] = i;
   1.289 +            }
   1.290 +
   1.291 +            if (!mCountingBuffer->unmapBuffer())
   1.292 +            {
   1.293 +                ERR("Failed to unmap counting buffer.");
   1.294 +                return NULL;
   1.295 +            }
   1.296 +        }
   1.297 +    }
   1.298 +    else if (mStreamingBufferInt)   // 32-bit indices supported
   1.299 +    {
   1.300 +        const unsigned int spaceNeeded = count * sizeof(unsigned int);
   1.301 +
   1.302 +        if (!mCountingBuffer || mCountingBuffer->getBufferSize() < spaceNeeded)
   1.303 +        {
   1.304 +            delete mCountingBuffer;
   1.305 +            mCountingBuffer = new StaticIndexBufferInterface(mRenderer);
   1.306 +            mCountingBuffer->reserveBufferSpace(spaceNeeded, GL_UNSIGNED_INT);
   1.307 +
   1.308 +            void* mappedMemory = NULL;
   1.309 +            if (!mCountingBuffer->mapBuffer(spaceNeeded, &mappedMemory, NULL))
   1.310 +            {
   1.311 +                ERR("Failed to map counting buffer.");
   1.312 +                return NULL;
   1.313 +            }
   1.314 +
   1.315 +            unsigned int *data = reinterpret_cast<unsigned int*>(mappedMemory);
   1.316 +            for(int i = 0; i < count; i++)
   1.317 +            {
   1.318 +                data[i] = i;
   1.319 +            }
   1.320 +
   1.321 +            if (!mCountingBuffer->unmapBuffer())
   1.322 +            {
   1.323 +                ERR("Failed to unmap counting buffer.");
   1.324 +                return NULL;
   1.325 +            }
   1.326 +        }
   1.327 +    }
   1.328 +    else
   1.329 +    {
   1.330 +        return NULL;
   1.331 +    }
   1.332 +
   1.333 +    return mCountingBuffer;
   1.334 +}
   1.335 +
   1.336 +}

mercurial