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

Sat, 03 Jan 2015 20:18:00 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Sat, 03 Jan 2015 20:18:00 +0100
branch
TOR_BUG_3246
changeset 7
129ffea94266
permissions
-rw-r--r--

Conditionally enable double key logic according to:
private browsing mode or privacy.thirdparty.isolate preference and
implement in GetCookieStringCommon and FindCookie where it counts...
With some reservations of how to convince FindCookie users to test
condition and pass a nullptr when disabling double key logic.

     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 //
     8 // VertexBuffer9.cpp: Defines the D3D9 VertexBuffer implementation.
    10 #include "libGLESv2/renderer/VertexBuffer9.h"
    11 #include "libGLESv2/renderer/vertexconversion.h"
    12 #include "libGLESv2/renderer/BufferStorage.h"
    13 #include "libGLESv2/Context.h"
    14 #include "libGLESv2/renderer/Renderer9.h"
    16 #include "libGLESv2/Buffer.h"
    18 namespace rx
    19 {
    21 bool VertexBuffer9::mTranslationsInitialized = false;
    22 VertexBuffer9::FormatConverter VertexBuffer9::mFormatConverters[NUM_GL_VERTEX_ATTRIB_TYPES][2][4];
    24 VertexBuffer9::VertexBuffer9(rx::Renderer9 *const renderer) : mRenderer(renderer)
    25 {
    26     mVertexBuffer = NULL;
    27     mBufferSize = 0;
    28     mDynamicUsage = false;
    30     if (!mTranslationsInitialized)
    31     {
    32         initializeTranslations(renderer->getCapsDeclTypes());
    33         mTranslationsInitialized = true;
    34     }
    35 }
    37 VertexBuffer9::~VertexBuffer9()
    38 {
    39     if (mVertexBuffer)
    40     {
    41         mVertexBuffer->Release();
    42         mVertexBuffer = NULL;
    43     }
    44 }
    46 bool VertexBuffer9::initialize(unsigned int size, bool dynamicUsage)
    47 {
    48     if (mVertexBuffer)
    49     {
    50         mVertexBuffer->Release();
    51         mVertexBuffer = NULL;
    52     }
    54     updateSerial();
    56     if (size > 0)
    57     {
    58         DWORD flags = D3DUSAGE_WRITEONLY;
    59         if (dynamicUsage)
    60         {
    61             flags |= D3DUSAGE_DYNAMIC;
    62         }
    64         HRESULT result = mRenderer->createVertexBuffer(size, flags, &mVertexBuffer);
    66         if (FAILED(result))
    67         {
    68             ERR("Out of memory allocating a vertex buffer of size %lu.", size);
    69             return false;
    70         }
    71     }
    73     mBufferSize = size;
    74     mDynamicUsage = dynamicUsage;
    75     return true;
    76 }
    78 VertexBuffer9 *VertexBuffer9::makeVertexBuffer9(VertexBuffer *vertexBuffer)
    79 {
    80     ASSERT(HAS_DYNAMIC_TYPE(VertexBuffer9*, vertexBuffer));
    81     return static_cast<VertexBuffer9*>(vertexBuffer);
    82 }
    84 bool VertexBuffer9::storeVertexAttributes(const gl::VertexAttribute &attrib, GLint start, GLsizei count,
    85                                              GLsizei instances, unsigned int offset)
    86 {
    87     if (mVertexBuffer)
    88     {
    89         gl::Buffer *buffer = attrib.mBoundBuffer.get();
    91         int inputStride = attrib.stride();
    92         int elementSize = attrib.typeSize();
    93         const FormatConverter &converter = formatConverter(attrib);
    95         DWORD lockFlags = mDynamicUsage ? D3DLOCK_NOOVERWRITE : 0;
    97         void *mapPtr = NULL;
    99         unsigned int mapSize;
   100         if (!spaceRequired(attrib, count, instances, &mapSize))
   101         {
   102             return false;
   103         }
   105         HRESULT result = mVertexBuffer->Lock(offset, mapSize, &mapPtr, lockFlags);
   107         if (FAILED(result))
   108         {
   109             ERR("Lock failed with error 0x%08x", result);
   110             return false;
   111         }
   113         const char *input = NULL;
   114         if (buffer)
   115         {
   116             BufferStorage *storage = buffer->getStorage();
   117             input = static_cast<const char*>(storage->getData()) + static_cast<int>(attrib.mOffset);
   118         }
   119         else
   120         {
   121             input = static_cast<const char*>(attrib.mPointer);
   122         }
   124         if (instances == 0 || attrib.mDivisor == 0)
   125         {
   126             input += inputStride * start;
   127         }
   129         if (converter.identity && inputStride == elementSize)
   130         {
   131             memcpy(mapPtr, input, count * inputStride);
   132         }
   133         else
   134         {
   135             converter.convertArray(input, inputStride, count, mapPtr);
   136         }
   138         mVertexBuffer->Unlock();
   140         return true;
   141     }
   142     else
   143     {
   144         ERR("Vertex buffer not initialized.");
   145         return false;
   146     }
   147 }
   149 bool VertexBuffer9::storeRawData(const void* data, unsigned int size, unsigned int offset)
   150 {
   151     if (mVertexBuffer)
   152     {
   153         DWORD lockFlags = mDynamicUsage ? D3DLOCK_NOOVERWRITE : 0;
   155         void *mapPtr = NULL;
   156         HRESULT result = mVertexBuffer->Lock(offset, size, &mapPtr, lockFlags);
   158         if (FAILED(result))
   159         {
   160             ERR("Lock failed with error 0x%08x", result);
   161             return false;
   162         }
   164         memcpy(mapPtr, data, size);
   166         mVertexBuffer->Unlock();
   168         return true;
   169     }
   170     else
   171     {
   172         ERR("Vertex buffer not initialized.");
   173         return false;
   174     }
   175 }
   177 bool VertexBuffer9::getSpaceRequired(const gl::VertexAttribute &attrib, GLsizei count, GLsizei instances,
   178                                      unsigned int *outSpaceRequired) const
   179 {
   180     return spaceRequired(attrib, count, instances, outSpaceRequired);
   181 }
   183 bool VertexBuffer9::requiresConversion(const gl::VertexAttribute &attrib) const
   184 {
   185     return formatConverter(attrib).identity;
   186 }
   188 unsigned int VertexBuffer9::getVertexSize(const gl::VertexAttribute &attrib) const
   189 {
   190     unsigned int spaceRequired;
   191     return getSpaceRequired(attrib, 1, 0, &spaceRequired) ? spaceRequired : 0;
   192 }
   194 D3DDECLTYPE VertexBuffer9::getDeclType(const gl::VertexAttribute &attrib) const
   195 {
   196     return formatConverter(attrib).d3dDeclType;
   197 }
   199 unsigned int VertexBuffer9::getBufferSize() const
   200 {
   201     return mBufferSize;
   202 }
   204 bool VertexBuffer9::setBufferSize(unsigned int size)
   205 {
   206     if (size > mBufferSize)
   207     {
   208         return initialize(size, mDynamicUsage);
   209     }
   210     else
   211     {
   212         return true;
   213     }
   214 }
   216 bool VertexBuffer9::discard()
   217 {
   218     if (mVertexBuffer)
   219     {
   220         void *dummy;
   221         HRESULT result;
   223         result = mVertexBuffer->Lock(0, 1, &dummy, D3DLOCK_DISCARD);
   224         if (FAILED(result))
   225         {
   226             ERR("Discard lock failed with error 0x%08x", result);
   227             return false;
   228         }
   230         result = mVertexBuffer->Unlock();
   231         if (FAILED(result))
   232         {
   233             ERR("Discard unlock failed with error 0x%08x", result);
   234             return false;
   235         }
   237         return true;
   238     }
   239     else
   240     {
   241         ERR("Vertex buffer not initialized.");
   242         return false;
   243     }
   244 }
   246 IDirect3DVertexBuffer9 * VertexBuffer9::getBuffer() const
   247 {
   248     return mVertexBuffer;
   249 }
   251 // Mapping from OpenGL-ES vertex attrib type to D3D decl type:
   252 //
   253 // BYTE                 SHORT (Cast)
   254 // BYTE-norm            FLOAT (Normalize) (can't be exactly represented as SHORT-norm)
   255 // UNSIGNED_BYTE        UBYTE4 (Identity) or SHORT (Cast)
   256 // UNSIGNED_BYTE-norm   UBYTE4N (Identity) or FLOAT (Normalize)
   257 // SHORT                SHORT (Identity)
   258 // SHORT-norm           SHORT-norm (Identity) or FLOAT (Normalize)
   259 // UNSIGNED_SHORT       FLOAT (Cast)
   260 // UNSIGNED_SHORT-norm  USHORT-norm (Identity) or FLOAT (Normalize)
   261 // FIXED (not in WebGL) FLOAT (FixedToFloat)
   262 // FLOAT                FLOAT (Identity)
   264 // GLToCType maps from GL type (as GLenum) to the C typedef.
   265 template <GLenum GLType> struct GLToCType { };
   267 template <> struct GLToCType<GL_BYTE>           { typedef GLbyte type;      };
   268 template <> struct GLToCType<GL_UNSIGNED_BYTE>  { typedef GLubyte type;     };
   269 template <> struct GLToCType<GL_SHORT>          { typedef GLshort type;     };
   270 template <> struct GLToCType<GL_UNSIGNED_SHORT> { typedef GLushort type;    };
   271 template <> struct GLToCType<GL_FIXED>          { typedef GLuint type;      };
   272 template <> struct GLToCType<GL_FLOAT>          { typedef GLfloat type;     };
   274 // This differs from D3DDECLTYPE in that it is unsized. (Size expansion is applied last.)
   275 enum D3DVertexType
   276 {
   277     D3DVT_FLOAT,
   278     D3DVT_SHORT,
   279     D3DVT_SHORT_NORM,
   280     D3DVT_UBYTE,
   281     D3DVT_UBYTE_NORM,
   282     D3DVT_USHORT_NORM
   283 };
   285 // D3DToCType maps from D3D vertex type (as enum D3DVertexType) to the corresponding C type.
   286 template <unsigned int D3DType> struct D3DToCType { };
   288 template <> struct D3DToCType<D3DVT_FLOAT> { typedef float type; };
   289 template <> struct D3DToCType<D3DVT_SHORT> { typedef short type; };
   290 template <> struct D3DToCType<D3DVT_SHORT_NORM> { typedef short type; };
   291 template <> struct D3DToCType<D3DVT_UBYTE> { typedef unsigned char type; };
   292 template <> struct D3DToCType<D3DVT_UBYTE_NORM> { typedef unsigned char type; };
   293 template <> struct D3DToCType<D3DVT_USHORT_NORM> { typedef unsigned short type; };
   295 // Encode the type/size combinations that D3D permits. For each type/size it expands to a widener that will provide the appropriate final size.
   296 template <unsigned int type, int size> struct WidenRule { };
   298 template <int size> struct WidenRule<D3DVT_FLOAT, size>          : NoWiden<size> { };
   299 template <int size> struct WidenRule<D3DVT_SHORT, size>          : WidenToEven<size> { };
   300 template <int size> struct WidenRule<D3DVT_SHORT_NORM, size>     : WidenToEven<size> { };
   301 template <int size> struct WidenRule<D3DVT_UBYTE, size>          : WidenToFour<size> { };
   302 template <int size> struct WidenRule<D3DVT_UBYTE_NORM, size>     : WidenToFour<size> { };
   303 template <int size> struct WidenRule<D3DVT_USHORT_NORM, size>    : WidenToEven<size> { };
   305 // VertexTypeFlags encodes the D3DCAPS9::DeclType flag and vertex declaration flag for each D3D vertex type & size combination.
   306 template <unsigned int d3dtype, int size> struct VertexTypeFlags { };
   308 template <unsigned int _capflag, unsigned int _declflag>
   309 struct VertexTypeFlagsHelper
   310 {
   311     enum { capflag = _capflag };
   312     enum { declflag = _declflag };
   313 };
   315 template <> struct VertexTypeFlags<D3DVT_FLOAT, 1> : VertexTypeFlagsHelper<0, D3DDECLTYPE_FLOAT1> { };
   316 template <> struct VertexTypeFlags<D3DVT_FLOAT, 2> : VertexTypeFlagsHelper<0, D3DDECLTYPE_FLOAT2> { };
   317 template <> struct VertexTypeFlags<D3DVT_FLOAT, 3> : VertexTypeFlagsHelper<0, D3DDECLTYPE_FLOAT3> { };
   318 template <> struct VertexTypeFlags<D3DVT_FLOAT, 4> : VertexTypeFlagsHelper<0, D3DDECLTYPE_FLOAT4> { };
   319 template <> struct VertexTypeFlags<D3DVT_SHORT, 2> : VertexTypeFlagsHelper<0, D3DDECLTYPE_SHORT2> { };
   320 template <> struct VertexTypeFlags<D3DVT_SHORT, 4> : VertexTypeFlagsHelper<0, D3DDECLTYPE_SHORT4> { };
   321 template <> struct VertexTypeFlags<D3DVT_SHORT_NORM, 2> : VertexTypeFlagsHelper<D3DDTCAPS_SHORT2N, D3DDECLTYPE_SHORT2N> { };
   322 template <> struct VertexTypeFlags<D3DVT_SHORT_NORM, 4> : VertexTypeFlagsHelper<D3DDTCAPS_SHORT4N, D3DDECLTYPE_SHORT4N> { };
   323 template <> struct VertexTypeFlags<D3DVT_UBYTE, 4> : VertexTypeFlagsHelper<D3DDTCAPS_UBYTE4, D3DDECLTYPE_UBYTE4> { };
   324 template <> struct VertexTypeFlags<D3DVT_UBYTE_NORM, 4> : VertexTypeFlagsHelper<D3DDTCAPS_UBYTE4N, D3DDECLTYPE_UBYTE4N> { };
   325 template <> struct VertexTypeFlags<D3DVT_USHORT_NORM, 2> : VertexTypeFlagsHelper<D3DDTCAPS_USHORT2N, D3DDECLTYPE_USHORT2N> { };
   326 template <> struct VertexTypeFlags<D3DVT_USHORT_NORM, 4> : VertexTypeFlagsHelper<D3DDTCAPS_USHORT4N, D3DDECLTYPE_USHORT4N> { };
   329 // VertexTypeMapping maps GL type & normalized flag to preferred and fallback D3D vertex types (as D3DVertexType enums).
   330 template <GLenum GLtype, bool normalized> struct VertexTypeMapping { };
   332 template <D3DVertexType Preferred, D3DVertexType Fallback = Preferred>
   333 struct VertexTypeMappingBase
   334 {
   335     enum { preferred = Preferred };
   336     enum { fallback = Fallback };
   337 };
   339 template <> struct VertexTypeMapping<GL_BYTE, false>                        : VertexTypeMappingBase<D3DVT_SHORT> { };                       // Cast
   340 template <> struct VertexTypeMapping<GL_BYTE, true>                         : VertexTypeMappingBase<D3DVT_FLOAT> { };                       // Normalize
   341 template <> struct VertexTypeMapping<GL_UNSIGNED_BYTE, false>               : VertexTypeMappingBase<D3DVT_UBYTE, D3DVT_FLOAT> { };          // Identity, Cast
   342 template <> struct VertexTypeMapping<GL_UNSIGNED_BYTE, true>                : VertexTypeMappingBase<D3DVT_UBYTE_NORM, D3DVT_FLOAT> { };     // Identity, Normalize
   343 template <> struct VertexTypeMapping<GL_SHORT, false>                       : VertexTypeMappingBase<D3DVT_SHORT> { };                       // Identity
   344 template <> struct VertexTypeMapping<GL_SHORT, true>                        : VertexTypeMappingBase<D3DVT_SHORT_NORM, D3DVT_FLOAT> { };     // Cast, Normalize
   345 template <> struct VertexTypeMapping<GL_UNSIGNED_SHORT, false>              : VertexTypeMappingBase<D3DVT_FLOAT> { };                       // Cast
   346 template <> struct VertexTypeMapping<GL_UNSIGNED_SHORT, true>               : VertexTypeMappingBase<D3DVT_USHORT_NORM, D3DVT_FLOAT> { };    // Cast, Normalize
   347 template <bool normalized> struct VertexTypeMapping<GL_FIXED, normalized>   : VertexTypeMappingBase<D3DVT_FLOAT> { };                       // FixedToFloat
   348 template <bool normalized> struct VertexTypeMapping<GL_FLOAT, normalized>   : VertexTypeMappingBase<D3DVT_FLOAT> { };                       // Identity
   351 // Given a GL type & norm flag and a D3D type, ConversionRule provides the type conversion rule (Cast, Normalize, Identity, FixedToFloat).
   352 // The conversion rules themselves are defined in vertexconversion.h.
   354 // Almost all cases are covered by Cast (including those that are actually Identity since Cast<T,T> knows it's an identity mapping).
   355 template <GLenum fromType, bool normalized, unsigned int toType>
   356 struct ConversionRule : Cast<typename GLToCType<fromType>::type, typename D3DToCType<toType>::type> { };
   358 // All conversions from normalized types to float use the Normalize operator.
   359 template <GLenum fromType> struct ConversionRule<fromType, true, D3DVT_FLOAT> : Normalize<typename GLToCType<fromType>::type> { };
   361 // Use a full specialization for this so that it preferentially matches ahead of the generic normalize-to-float rules.
   362 template <> struct ConversionRule<GL_FIXED, true, D3DVT_FLOAT>  : FixedToFloat<GLint, 16> { };
   363 template <> struct ConversionRule<GL_FIXED, false, D3DVT_FLOAT> : FixedToFloat<GLint, 16> { };
   365 // A 2-stage construction is used for DefaultVertexValues because float must use SimpleDefaultValues (i.e. 0/1)
   366 // whether it is normalized or not.
   367 template <class T, bool normalized> struct DefaultVertexValuesStage2 { };
   369 template <class T> struct DefaultVertexValuesStage2<T, true>  : NormalizedDefaultValues<T> { };
   370 template <class T> struct DefaultVertexValuesStage2<T, false> : SimpleDefaultValues<T> { };
   372 // Work out the default value rule for a D3D type (expressed as the C type) and
   373 template <class T, bool normalized> struct DefaultVertexValues : DefaultVertexValuesStage2<T, normalized> { };
   374 template <bool normalized> struct DefaultVertexValues<float, normalized> : SimpleDefaultValues<float> { };
   376 // Policy rules for use with Converter, to choose whether to use the preferred or fallback conversion.
   377 // The fallback conversion produces an output that all D3D9 devices must support.
   378 template <class T> struct UsePreferred { enum { type = T::preferred }; };
   379 template <class T> struct UseFallback { enum { type = T::fallback }; };
   381 // Converter ties it all together. Given an OpenGL type/norm/size and choice of preferred/fallback conversion,
   382 // it provides all the members of the appropriate VertexDataConverter, the D3DCAPS9::DeclTypes flag in cap flag
   383 // and the D3DDECLTYPE member needed for the vertex declaration in declflag.
   384 template <GLenum fromType, bool normalized, int size, template <class T> class PreferenceRule>
   385 struct Converter
   386     : VertexDataConverter<typename GLToCType<fromType>::type,
   387                           WidenRule<PreferenceRule< VertexTypeMapping<fromType, normalized> >::type, size>,
   388                           ConversionRule<fromType,
   389                                          normalized,
   390                                          PreferenceRule< VertexTypeMapping<fromType, normalized> >::type>,
   391                           DefaultVertexValues<typename D3DToCType<PreferenceRule< VertexTypeMapping<fromType, normalized> >::type>::type, normalized > >
   392 {
   393 private:
   394     enum { d3dtype = PreferenceRule< VertexTypeMapping<fromType, normalized> >::type };
   395     enum { d3dsize = WidenRule<d3dtype, size>::finalWidth };
   397 public:
   398     enum { capflag = VertexTypeFlags<d3dtype, d3dsize>::capflag };
   399     enum { declflag = VertexTypeFlags<d3dtype, d3dsize>::declflag };
   400 };
   402 // Initialize a TranslationInfo
   403 #define TRANSLATION(type, norm, size, preferred)                                    \
   404     {                                                                               \
   405         Converter<type, norm, size, preferred>::identity,                           \
   406         Converter<type, norm, size, preferred>::finalSize,                          \
   407         Converter<type, norm, size, preferred>::convertArray,                       \
   408         static_cast<D3DDECLTYPE>(Converter<type, norm, size, preferred>::declflag)  \
   409     }
   411 #define TRANSLATION_FOR_TYPE_NORM_SIZE(type, norm, size)    \
   412     {                                                       \
   413         Converter<type, norm, size, UsePreferred>::capflag, \
   414         TRANSLATION(type, norm, size, UsePreferred),        \
   415         TRANSLATION(type, norm, size, UseFallback)          \
   416     }
   418 #define TRANSLATIONS_FOR_TYPE(type)                                                                                                                                                                         \
   419     {                                                                                                                                                                                                       \
   420         { TRANSLATION_FOR_TYPE_NORM_SIZE(type, false, 1), TRANSLATION_FOR_TYPE_NORM_SIZE(type, false, 2), TRANSLATION_FOR_TYPE_NORM_SIZE(type, false, 3), TRANSLATION_FOR_TYPE_NORM_SIZE(type, false, 4) }, \
   421         { TRANSLATION_FOR_TYPE_NORM_SIZE(type, true, 1), TRANSLATION_FOR_TYPE_NORM_SIZE(type, true, 2), TRANSLATION_FOR_TYPE_NORM_SIZE(type, true, 3), TRANSLATION_FOR_TYPE_NORM_SIZE(type, true, 4) },     \
   422     }
   424 #define TRANSLATIONS_FOR_TYPE_NO_NORM(type)                                                                                                                                                                 \
   425     {                                                                                                                                                                                                       \
   426         { TRANSLATION_FOR_TYPE_NORM_SIZE(type, false, 1), TRANSLATION_FOR_TYPE_NORM_SIZE(type, false, 2), TRANSLATION_FOR_TYPE_NORM_SIZE(type, false, 3), TRANSLATION_FOR_TYPE_NORM_SIZE(type, false, 4) }, \
   427         { TRANSLATION_FOR_TYPE_NORM_SIZE(type, false, 1), TRANSLATION_FOR_TYPE_NORM_SIZE(type, false, 2), TRANSLATION_FOR_TYPE_NORM_SIZE(type, false, 3), TRANSLATION_FOR_TYPE_NORM_SIZE(type, false, 4) }, \
   428     }
   430 const VertexBuffer9::TranslationDescription VertexBuffer9::mPossibleTranslations[NUM_GL_VERTEX_ATTRIB_TYPES][2][4] = // [GL types as enumerated by typeIndex()][normalized][size-1]
   431 {
   432     TRANSLATIONS_FOR_TYPE(GL_BYTE),
   433     TRANSLATIONS_FOR_TYPE(GL_UNSIGNED_BYTE),
   434     TRANSLATIONS_FOR_TYPE(GL_SHORT),
   435     TRANSLATIONS_FOR_TYPE(GL_UNSIGNED_SHORT),
   436     TRANSLATIONS_FOR_TYPE_NO_NORM(GL_FIXED),
   437     TRANSLATIONS_FOR_TYPE_NO_NORM(GL_FLOAT)
   438 };
   440 void VertexBuffer9::initializeTranslations(DWORD declTypes)
   441 {
   442     for (unsigned int i = 0; i < NUM_GL_VERTEX_ATTRIB_TYPES; i++)
   443     {
   444         for (unsigned int j = 0; j < 2; j++)
   445         {
   446             for (unsigned int k = 0; k < 4; k++)
   447             {
   448                 if (mPossibleTranslations[i][j][k].capsFlag == 0 || (declTypes & mPossibleTranslations[i][j][k].capsFlag) != 0)
   449                 {
   450                     mFormatConverters[i][j][k] = mPossibleTranslations[i][j][k].preferredConversion;
   451                 }
   452                 else
   453                 {
   454                     mFormatConverters[i][j][k] = mPossibleTranslations[i][j][k].fallbackConversion;
   455                 }
   456             }
   457         }
   458     }
   459 }
   461 unsigned int VertexBuffer9::typeIndex(GLenum type)
   462 {
   463     switch (type)
   464     {
   465       case GL_BYTE: return 0;
   466       case GL_UNSIGNED_BYTE: return 1;
   467       case GL_SHORT: return 2;
   468       case GL_UNSIGNED_SHORT: return 3;
   469       case GL_FIXED: return 4;
   470       case GL_FLOAT: return 5;
   472       default: UNREACHABLE(); return 5;
   473     }
   474 }
   476 const VertexBuffer9::FormatConverter &VertexBuffer9::formatConverter(const gl::VertexAttribute &attribute)
   477 {
   478     return mFormatConverters[typeIndex(attribute.mType)][attribute.mNormalized][attribute.mSize - 1];
   479 }
   481 bool VertexBuffer9::spaceRequired(const gl::VertexAttribute &attrib, std::size_t count, GLsizei instances,
   482                                   unsigned int *outSpaceRequired)
   483 {
   484     unsigned int elementSize = formatConverter(attrib).outputElementSize;
   486     if (instances == 0 || attrib.mDivisor == 0)
   487     {
   488         unsigned int elementCount = 0;
   489         if (instances == 0 || attrib.mDivisor == 0)
   490         {
   491             elementCount = count;
   492         }
   493         else
   494         {
   495             if (static_cast<unsigned int>(instances) < std::numeric_limits<unsigned int>::max() - (attrib.mDivisor - 1))
   496             {
   497                 // Round up
   498                 elementCount = (static_cast<unsigned int>(instances) + (attrib.mDivisor - 1)) / attrib.mDivisor;
   499             }
   500             else
   501             {
   502                 elementCount = static_cast<unsigned int>(instances) / attrib.mDivisor;
   503             }
   504         }
   506         if (elementSize <= std::numeric_limits<unsigned int>::max() / elementCount)
   507         {
   508             if (outSpaceRequired)
   509             {
   510                 *outSpaceRequired = elementSize * elementCount;
   511             }
   512             return true;
   513         }
   514         else
   515         {
   516             return false;
   517         }
   518     }
   519     else
   520     {
   521         const unsigned int elementSize = 4;
   522         if (outSpaceRequired)
   523         {
   524             *outSpaceRequired = elementSize * 4;
   525         }
   526         return true;
   527     }
   528 }
   530 }

mercurial