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/Context.h"
     14 
     15 namespace rx
     16 {
     17 
     18 unsigned int VertexBuffer::mNextSerial = 1;
     19 
     20 VertexBuffer::VertexBuffer()
     21 {
     22     updateSerial();
     23 }
     24 
     25 VertexBuffer::~VertexBuffer()
     26 {
     27 }
     28 
     29 void VertexBuffer::updateSerial()
     30 {
     31     mSerial = mNextSerial++;
     32 }
     33 
     34 unsigned int VertexBuffer::getSerial() const
     35 {
     36     return mSerial;
     37 }
     38 
     39 VertexBufferInterface::VertexBufferInterface(rx::Renderer *renderer, bool dynamic) : mRenderer(renderer)
     40 {
     41     mDynamic = dynamic;
     42     mWritePosition = 0;
     43     mReservedSpace = 0;
     44 
     45     mVertexBuffer = renderer->createVertexBuffer();
     46 }
     47 
     48 VertexBufferInterface::~VertexBufferInterface()
     49 {
     50     delete mVertexBuffer;
     51 }
     52 
     53 unsigned int VertexBufferInterface::getSerial() const
     54 {
     55     return mVertexBuffer->getSerial();
     56 }
     57 
     58 unsigned int VertexBufferInterface::getBufferSize() const
     59 {
     60     return mVertexBuffer->getBufferSize();
     61 }
     62 
     63 bool VertexBufferInterface::setBufferSize(unsigned int size)
     64 {
     65     if (mVertexBuffer->getBufferSize() == 0)
     66     {
     67         return mVertexBuffer->initialize(size, mDynamic);
     68     }
     69     else
     70     {
     71         return mVertexBuffer->setBufferSize(size);
     72     }
     73 }
     74 
     75 unsigned int VertexBufferInterface::getWritePosition() const
     76 {
     77     return mWritePosition;
     78 }
     79 
     80 void VertexBufferInterface::setWritePosition(unsigned int writePosition)
     81 {
     82     mWritePosition = writePosition;
     83 }
     84 
     85 bool VertexBufferInterface::discard()
     86 {
     87     return mVertexBuffer->discard();
     88 }
     89 
     90 bool VertexBufferInterface::storeVertexAttributes(const gl::VertexAttribute &attrib,  GLint start, GLsizei count, GLsizei instances,
     91                                                   unsigned int *outStreamOffset)
     92 {
     93     unsigned int spaceRequired;
     94     if (!mVertexBuffer->getSpaceRequired(attrib, count, instances, &spaceRequired))
     95     {
     96         return false;
     97     }
     98 
     99     if (mWritePosition + spaceRequired < mWritePosition)
    100     {
    101         return false;
    102     }
    103 
    104     if (!reserveSpace(mReservedSpace))
    105     {
    106         return false;
    107     }
    108     mReservedSpace = 0;
    109 
    110     if (!mVertexBuffer->storeVertexAttributes(attrib, start, count, instances, mWritePosition))
    111     {
    112         return false;
    113     }
    114 
    115     if (outStreamOffset)
    116     {
    117         *outStreamOffset = mWritePosition;
    118     }
    119 
    120     mWritePosition += spaceRequired;
    121 
    122     return true;
    123 }
    124 
    125 bool VertexBufferInterface::storeRawData(const void* data, unsigned int size, unsigned int *outStreamOffset)
    126 {
    127     if (mWritePosition + size < mWritePosition)
    128     {
    129         return false;
    130     }
    131 
    132     if (!reserveSpace(mReservedSpace))
    133     {
    134         return false;
    135     }
    136     mReservedSpace = 0;
    137 
    138     if (!mVertexBuffer->storeRawData(data, size, mWritePosition))
    139     {
    140         return false;
    141     }
    142 
    143     if (outStreamOffset)
    144     {
    145         *outStreamOffset = mWritePosition;
    146     }
    147 
    148     mWritePosition += size;
    149 
    150     return true;
    151 }
    152 
    153 bool VertexBufferInterface::reserveVertexSpace(const gl::VertexAttribute &attribute, GLsizei count, GLsizei instances)
    154 {
    155     unsigned int requiredSpace;
    156     if (!mVertexBuffer->getSpaceRequired(attribute, count, instances, &requiredSpace))
    157     {
    158         return false;
    159     }
    160 
    161     // Protect against integer overflow
    162     if (mReservedSpace + requiredSpace < mReservedSpace)
    163     {
    164          return false;
    165     }
    166 
    167     mReservedSpace += requiredSpace;
    168     return true;
    169 }
    170 
    171 bool VertexBufferInterface::reserveRawDataSpace(unsigned int size)
    172 {
    173     // Protect against integer overflow
    174     if (mReservedSpace + size < mReservedSpace)
    175     {
    176          return false;
    177     }
    178 
    179     mReservedSpace += size;
    180     return true;
    181 }
    182 
    183 VertexBuffer* VertexBufferInterface::getVertexBuffer() const
    184 {
    185     return mVertexBuffer;
    186 }
    187 
    188 
    189 StreamingVertexBufferInterface::StreamingVertexBufferInterface(rx::Renderer *renderer, std::size_t initialSize) : VertexBufferInterface(renderer, true)
    190 {
    191     setBufferSize(initialSize);
    192 }
    193 
    194 StreamingVertexBufferInterface::~StreamingVertexBufferInterface()
    195 {
    196 }
    197 
    198 bool StreamingVertexBufferInterface::reserveSpace(unsigned int size)
    199 {
    200     bool result = true;
    201     unsigned int curBufferSize = getBufferSize();
    202     if (size > curBufferSize)
    203     {
    204         result = setBufferSize(std::max(size, 3 * curBufferSize / 2));
    205         setWritePosition(0);
    206     }
    207     else if (getWritePosition() + size > curBufferSize)
    208     {
    209         if (!discard())
    210         {
    211             return false;
    212         }
    213         setWritePosition(0);
    214     }
    215 
    216     return result;
    217 }
    218 
    219 StaticVertexBufferInterface::StaticVertexBufferInterface(rx::Renderer *renderer) : VertexBufferInterface(renderer, false)
    220 {
    221 }
    222 
    223 StaticVertexBufferInterface::~StaticVertexBufferInterface()
    224 {
    225 }
    226 
    227 bool StaticVertexBufferInterface::lookupAttribute(const gl::VertexAttribute &attribute, unsigned int *outStreamOffset)
    228 {
    229     for (unsigned int element = 0; element < mCache.size(); element++)
    230     {
    231         if (mCache[element].type == attribute.mType &&
    232             mCache[element].size == attribute.mSize &&
    233             mCache[element].stride == attribute.stride() &&
    234             mCache[element].normalized == attribute.mNormalized)
    235         {
    236             if (mCache[element].attributeOffset == attribute.mOffset % attribute.stride())
    237             {
    238                 if (outStreamOffset)
    239                 {
    240                     *outStreamOffset = mCache[element].streamOffset;
    241                 }
    242                 return true;
    243             }
    244         }
    245     }
    246 
    247     return false;
    248 }
    249 
    250 bool StaticVertexBufferInterface::reserveSpace(unsigned int size)
    251 {
    252     unsigned int curSize = getBufferSize();
    253     if (curSize == 0)
    254     {
    255         setBufferSize(size);
    256         return true;
    257     }
    258     else if (curSize >= size)
    259     {
    260         return true;
    261     }
    262     else
    263     {
    264         UNREACHABLE();   // Static vertex buffers can't be resized
    265         return false;
    266     }
    267 }
    268 
    269 bool StaticVertexBufferInterface::storeVertexAttributes(const gl::VertexAttribute &attrib, GLint start, GLsizei count, GLsizei instances,
    270                                                         unsigned int *outStreamOffset)
    271 {
    272     unsigned int streamOffset;
    273     if (VertexBufferInterface::storeVertexAttributes(attrib, start, count, instances, &streamOffset))
    274     {
    275         int attributeOffset = attrib.mOffset % attrib.stride();
    276         VertexElement element = { attrib.mType, attrib.mSize, attrib.stride(), attrib.mNormalized, attributeOffset, streamOffset };
    277         mCache.push_back(element);
    278 
    279         if (outStreamOffset)
    280         {
    281             *outStreamOffset = streamOffset;
    282         }
    283 
    284         return true;
    285     }
    286     else
    287     {
    288         return false;
    289     }
    290 }
    291 
    292 }
    293