Home | History | Annotate | Download | only in renderer
      1 #include "precompiled.h"
      2 //
      3 // Copyright (c) 2002-2012 The ANGLE Project Authors. All rights reserved.
      4 // Use of this source code is governed by a BSD-style license that can be
      5 // found in the LICENSE file.
      6 //
      7 
      8 // VertexBuffer.cpp: Defines the abstract VertexBuffer class and VertexBufferInterface
      9 // class with derivations, classes that perform graphics API agnostic vertex buffer operations.
     10 
     11 #include "libGLESv2/renderer/VertexBuffer.h"
     12 #include "libGLESv2/renderer/Renderer.h"
     13 #include "libGLESv2/VertexAttribute.h"
     14 #include "libGLESv2/renderer/BufferStorage.h"
     15 #include "common/mathutil.h"
     16 
     17 namespace rx
     18 {
     19 
     20 unsigned int VertexBuffer::mNextSerial = 1;
     21 
     22 VertexBuffer::VertexBuffer()
     23 {
     24     updateSerial();
     25 }
     26 
     27 VertexBuffer::~VertexBuffer()
     28 {
     29 }
     30 
     31 void VertexBuffer::updateSerial()
     32 {
     33     mSerial = mNextSerial++;
     34 }
     35 
     36 unsigned int VertexBuffer::getSerial() const
     37 {
     38     return mSerial;
     39 }
     40 
     41 VertexBufferInterface::VertexBufferInterface(rx::Renderer *renderer, bool dynamic) : mRenderer(renderer)
     42 {
     43     mDynamic = dynamic;
     44     mWritePosition = 0;
     45     mReservedSpace = 0;
     46 
     47     mVertexBuffer = renderer->createVertexBuffer();
     48 }
     49 
     50 VertexBufferInterface::~VertexBufferInterface()
     51 {
     52     delete mVertexBuffer;
     53 }
     54 
     55 unsigned int VertexBufferInterface::getSerial() const
     56 {
     57     return mVertexBuffer->getSerial();
     58 }
     59 
     60 unsigned int VertexBufferInterface::getBufferSize() const
     61 {
     62     return mVertexBuffer->getBufferSize();
     63 }
     64 
     65 bool VertexBufferInterface::setBufferSize(unsigned int size)
     66 {
     67     if (mVertexBuffer->getBufferSize() == 0)
     68     {
     69         return mVertexBuffer->initialize(size, mDynamic);
     70     }
     71     else
     72     {
     73         return mVertexBuffer->setBufferSize(size);
     74     }
     75 }
     76 
     77 unsigned int VertexBufferInterface::getWritePosition() const
     78 {
     79     return mWritePosition;
     80 }
     81 
     82 void VertexBufferInterface::setWritePosition(unsigned int writePosition)
     83 {
     84     mWritePosition = writePosition;
     85 }
     86 
     87 bool VertexBufferInterface::discard()
     88 {
     89     return mVertexBuffer->discard();
     90 }
     91 
     92 bool VertexBufferInterface::storeVertexAttributes(const gl::VertexAttribute &attrib, const gl::VertexAttribCurrentValueData &currentValue,
     93                                                   GLint start, GLsizei count, GLsizei instances, unsigned int *outStreamOffset)
     94 {
     95     unsigned int spaceRequired;
     96     if (!mVertexBuffer->getSpaceRequired(attrib, count, instances, &spaceRequired))
     97     {
     98         return false;
     99     }
    100 
    101     if (mWritePosition + spaceRequired < mWritePosition)
    102     {
    103         return false;
    104     }
    105 
    106     if (!reserveSpace(mReservedSpace))
    107     {
    108         return false;
    109     }
    110     mReservedSpace = 0;
    111 
    112     if (!mVertexBuffer->storeVertexAttributes(attrib, currentValue, start, count, instances, mWritePosition))
    113     {
    114         return false;
    115     }
    116 
    117     if (outStreamOffset)
    118     {
    119         *outStreamOffset = mWritePosition;
    120     }
    121 
    122     mWritePosition += spaceRequired;
    123 
    124     // Align to 16-byte boundary
    125     mWritePosition = rx::roundUp(mWritePosition, 16u);
    126 
    127     return true;
    128 }
    129 
    130 bool VertexBufferInterface::reserveVertexSpace(const gl::VertexAttribute &attribute, GLsizei count, GLsizei instances)
    131 {
    132     unsigned int requiredSpace;
    133     if (!mVertexBuffer->getSpaceRequired(attribute, count, instances, &requiredSpace))
    134     {
    135         return false;
    136     }
    137 
    138     // Protect against integer overflow
    139     if (mReservedSpace + requiredSpace < mReservedSpace)
    140     {
    141          return false;
    142     }
    143 
    144     mReservedSpace += requiredSpace;
    145 
    146     // Align to 16-byte boundary
    147     mReservedSpace = rx::roundUp(mReservedSpace, 16u);
    148 
    149     return true;
    150 }
    151 
    152 VertexBuffer* VertexBufferInterface::getVertexBuffer() const
    153 {
    154     return mVertexBuffer;
    155 }
    156 
    157 bool VertexBufferInterface::directStoragePossible(const gl::VertexAttribute &attrib,
    158                                                   const gl::VertexAttribCurrentValueData &currentValue) const
    159 {
    160     gl::Buffer *buffer = attrib.mBoundBuffer.get();
    161     BufferStorage *storage = buffer ? buffer->getStorage() : NULL;
    162 
    163     if (!storage || !storage->supportsDirectBinding())
    164     {
    165         return false;
    166     }
    167 
    168     // Alignment restrictions: In D3D, vertex data must be aligned to
    169     //  the format stride, or to a 4-byte boundary, whichever is smaller.
    170     //  (Undocumented, and experimentally confirmed)
    171     size_t alignment = 4;
    172     bool requiresConversion = false;
    173 
    174     if (attrib.mType != GL_FLOAT)
    175     {
    176         gl::VertexFormat vertexFormat(attrib, currentValue.Type);
    177 
    178         unsigned int outputElementSize;
    179         getVertexBuffer()->getSpaceRequired(attrib, 1, 0, &outputElementSize);
    180         alignment = std::min<size_t>(outputElementSize, 4);
    181 
    182         requiresConversion = (mRenderer->getVertexConversionType(vertexFormat) & VERTEX_CONVERT_CPU) != 0;
    183     }
    184 
    185     bool isAligned = (static_cast<size_t>(attrib.stride()) % alignment == 0) &&
    186                      (static_cast<size_t>(attrib.mOffset) % alignment == 0);
    187 
    188     return !requiresConversion && isAligned;
    189 }
    190 
    191 StreamingVertexBufferInterface::StreamingVertexBufferInterface(rx::Renderer *renderer, std::size_t initialSize) : VertexBufferInterface(renderer, true)
    192 {
    193     setBufferSize(initialSize);
    194 }
    195 
    196 StreamingVertexBufferInterface::~StreamingVertexBufferInterface()
    197 {
    198 }
    199 
    200 bool StreamingVertexBufferInterface::reserveSpace(unsigned int size)
    201 {
    202     bool result = true;
    203     unsigned int curBufferSize = getBufferSize();
    204     if (size > curBufferSize)
    205     {
    206         result = setBufferSize(std::max(size, 3 * curBufferSize / 2));
    207         setWritePosition(0);
    208     }
    209     else if (getWritePosition() + size > curBufferSize)
    210     {
    211         if (!discard())
    212         {
    213             return false;
    214         }
    215         setWritePosition(0);
    216     }
    217 
    218     return result;
    219 }
    220 
    221 StaticVertexBufferInterface::StaticVertexBufferInterface(rx::Renderer *renderer) : VertexBufferInterface(renderer, false)
    222 {
    223 }
    224 
    225 StaticVertexBufferInterface::~StaticVertexBufferInterface()
    226 {
    227 }
    228 
    229 bool StaticVertexBufferInterface::lookupAttribute(const gl::VertexAttribute &attribute, unsigned int *outStreamOffset)
    230 {
    231     for (unsigned int element = 0; element < mCache.size(); element++)
    232     {
    233         if (mCache[element].type == attribute.mType &&
    234             mCache[element].size == attribute.mSize &&
    235             mCache[element].stride == attribute.stride() &&
    236             mCache[element].normalized == attribute.mNormalized &&
    237             mCache[element].pureInteger == attribute.mPureInteger)
    238         {
    239             if (mCache[element].attributeOffset == attribute.mOffset % attribute.stride())
    240             {
    241                 if (outStreamOffset)
    242                 {
    243                     *outStreamOffset = mCache[element].streamOffset;
    244                 }
    245                 return true;
    246             }
    247         }
    248     }
    249 
    250     return false;
    251 }
    252 
    253 bool StaticVertexBufferInterface::reserveSpace(unsigned int size)
    254 {
    255     unsigned int curSize = getBufferSize();
    256     if (curSize == 0)
    257     {
    258         setBufferSize(size);
    259         return true;
    260     }
    261     else if (curSize >= size)
    262     {
    263         return true;
    264     }
    265     else
    266     {
    267         UNREACHABLE();   // Static vertex buffers can't be resized
    268         return false;
    269     }
    270 }
    271 
    272 bool StaticVertexBufferInterface::storeVertexAttributes(const gl::VertexAttribute &attrib, const gl::VertexAttribCurrentValueData &currentValue,
    273                                                        GLint start, GLsizei count, GLsizei instances, unsigned int *outStreamOffset)
    274 {
    275     unsigned int streamOffset;
    276     if (VertexBufferInterface::storeVertexAttributes(attrib, currentValue, start, count, instances, &streamOffset))
    277     {
    278         int attributeOffset = attrib.mOffset % attrib.stride();
    279         VertexElement element = { attrib.mType, attrib.mSize, attrib.stride(), attrib.mNormalized, attrib.mPureInteger, attributeOffset, streamOffset };
    280         mCache.push_back(element);
    281 
    282         if (outStreamOffset)
    283         {
    284             *outStreamOffset = streamOffset;
    285         }
    286 
    287         return true;
    288     }
    289     else
    290     {
    291         return false;
    292     }
    293 }
    294 
    295 }
    296