tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

VertexAttribute.cpp (5660B)


      1 //
      2 // Copyright 2014 The ANGLE Project Authors. All rights reserved.
      3 // Use of this source code is governed by a BSD-style license that can be
      4 // found in the LICENSE file.
      5 //
      6 // Implementation of the state classes for mananging GLES 3.1 Vertex Array Objects.
      7 //
      8 
      9 #include "libANGLE/VertexAttribute.h"
     10 
     11 namespace gl
     12 {
     13 
     14 // [OpenGL ES 3.1] (November 3, 2016) Section 20 Page 361
     15 // Table 20.2: Vertex Array Object State
     16 VertexBinding::VertexBinding() : VertexBinding(0) {}
     17 
     18 VertexBinding::VertexBinding(GLuint boundAttribute) : mStride(16u), mDivisor(0), mOffset(0)
     19 {
     20    mBoundAttributesMask.set(boundAttribute);
     21 }
     22 
     23 VertexBinding::VertexBinding(VertexBinding &&binding)
     24 {
     25    *this = std::move(binding);
     26 }
     27 
     28 VertexBinding::~VertexBinding() {}
     29 
     30 VertexBinding &VertexBinding::operator=(VertexBinding &&binding)
     31 {
     32    if (this != &binding)
     33    {
     34        mStride              = binding.mStride;
     35        mDivisor             = binding.mDivisor;
     36        mOffset              = binding.mOffset;
     37        mBoundAttributesMask = binding.mBoundAttributesMask;
     38        std::swap(binding.mBuffer, mBuffer);
     39    }
     40    return *this;
     41 }
     42 
     43 void VertexBinding::onContainerBindingChanged(const Context *context, int incr) const
     44 {
     45    if (mBuffer.get())
     46        mBuffer->onNonTFBindingChanged(incr);
     47 }
     48 
     49 VertexAttribute::VertexAttribute(GLuint bindingIndex)
     50    : enabled(false),
     51      format(&angle::Format::Get(angle::FormatID::R32G32B32A32_FLOAT)),
     52      pointer(nullptr),
     53      relativeOffset(0),
     54      vertexAttribArrayStride(0),
     55      bindingIndex(bindingIndex),
     56      mCachedElementLimit(0)
     57 {}
     58 
     59 VertexAttribute::VertexAttribute(VertexAttribute &&attrib)
     60    : enabled(attrib.enabled),
     61      format(attrib.format),
     62      pointer(attrib.pointer),
     63      relativeOffset(attrib.relativeOffset),
     64      vertexAttribArrayStride(attrib.vertexAttribArrayStride),
     65      bindingIndex(attrib.bindingIndex),
     66      mCachedElementLimit(attrib.mCachedElementLimit)
     67 {}
     68 
     69 VertexAttribute &VertexAttribute::operator=(VertexAttribute &&attrib)
     70 {
     71    if (this != &attrib)
     72    {
     73        enabled                 = attrib.enabled;
     74        format                  = attrib.format;
     75        pointer                 = attrib.pointer;
     76        relativeOffset          = attrib.relativeOffset;
     77        vertexAttribArrayStride = attrib.vertexAttribArrayStride;
     78        bindingIndex            = attrib.bindingIndex;
     79        mCachedElementLimit     = attrib.mCachedElementLimit;
     80    }
     81    return *this;
     82 }
     83 
     84 void VertexAttribute::updateCachedElementLimit(const VertexBinding &binding)
     85 {
     86    Buffer *buffer = binding.getBuffer().get();
     87    if (!buffer)
     88    {
     89        mCachedElementLimit = 0;
     90        return;
     91    }
     92 
     93    angle::CheckedNumeric<GLint64> bufferSize(buffer->getSize());
     94    angle::CheckedNumeric<GLint64> bufferOffset(binding.getOffset());
     95    angle::CheckedNumeric<GLint64> attribOffset(relativeOffset);
     96    angle::CheckedNumeric<GLint64> attribSize(ComputeVertexAttributeTypeSize(*this));
     97 
     98    // (buffer.size - buffer.offset - attrib.relativeOffset - attrib.size) / binding.stride
     99    angle::CheckedNumeric<GLint64> elementLimit =
    100        (bufferSize - bufferOffset - attribOffset - attribSize);
    101 
    102    // Use the special integer overflow value if there was a math error.
    103    if (!elementLimit.IsValid())
    104    {
    105        static_assert(kIntegerOverflow < 0, "Unexpected value");
    106        mCachedElementLimit = kIntegerOverflow;
    107        return;
    108    }
    109 
    110    mCachedElementLimit = elementLimit.ValueOrDie();
    111    if (mCachedElementLimit < 0)
    112    {
    113        return;
    114    }
    115 
    116    if (binding.getStride() == 0)
    117    {
    118        // Special case for a zero stride. If we can fit one vertex we can fit infinite vertices.
    119        mCachedElementLimit = std::numeric_limits<GLint64>::max();
    120        return;
    121    }
    122 
    123    angle::CheckedNumeric<GLint64> bindingStride(binding.getStride());
    124    elementLimit /= bindingStride;
    125 
    126    if (binding.getDivisor() > 0)
    127    {
    128        // For instanced draws, the element count is floor(instanceCount - 1) / binding.divisor.
    129        angle::CheckedNumeric<GLint64> bindingDivisor(binding.getDivisor());
    130        elementLimit *= bindingDivisor;
    131 
    132        // We account for the floor() part rounding by adding a rounding constant.
    133        elementLimit += bindingDivisor - 1;
    134    }
    135 
    136    mCachedElementLimit = elementLimit.ValueOrDefault(kIntegerOverflow);
    137 }
    138 
    139 size_t ComputeVertexAttributeStride(const VertexAttribute &attrib, const VertexBinding &binding)
    140 {
    141    // In ES 3.1, VertexAttribPointer will store the type size in the binding stride.
    142    // Hence, rendering always uses the binding's stride.
    143    return attrib.enabled ? binding.getStride() : 16u;
    144 }
    145 
    146 // Warning: you should ensure binding really matches attrib.bindingIndex before using this function.
    147 GLintptr ComputeVertexAttributeOffset(const VertexAttribute &attrib, const VertexBinding &binding)
    148 {
    149    return attrib.relativeOffset + binding.getOffset();
    150 }
    151 
    152 size_t ComputeVertexBindingElementCount(GLuint divisor, size_t drawCount, size_t instanceCount)
    153 {
    154    // For instanced rendering, we draw "instanceDrawCount" sets of "vertexDrawCount" vertices.
    155    //
    156    // A vertex attribute with a positive divisor loads one instanced vertex for every set of
    157    // non-instanced vertices, and the instanced vertex index advances once every "mDivisor"
    158    // instances.
    159    if (instanceCount > 0 && divisor > 0)
    160    {
    161        // When instanceDrawCount is not a multiple attrib.divisor, the division must round up.
    162        // For instance, with 5 non-instanced vertices and a divisor equal to 3, we need 2 instanced
    163        // vertices.
    164        return (instanceCount + divisor - 1u) / divisor;
    165    }
    166 
    167    return drawCount;
    168 }
    169 
    170 }  // namespace gl