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

changeset 0
6474c204b198
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/gfx/angle/src/libGLESv2/renderer/VertexBuffer9.cpp	Wed Dec 31 06:09:35 2014 +0100
     1.3 @@ -0,0 +1,530 @@
     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 +// VertexBuffer9.cpp: Defines the D3D9 VertexBuffer implementation.
    1.12 +
    1.13 +#include "libGLESv2/renderer/VertexBuffer9.h"
    1.14 +#include "libGLESv2/renderer/vertexconversion.h"
    1.15 +#include "libGLESv2/renderer/BufferStorage.h"
    1.16 +#include "libGLESv2/Context.h"
    1.17 +#include "libGLESv2/renderer/Renderer9.h"
    1.18 +
    1.19 +#include "libGLESv2/Buffer.h"
    1.20 +
    1.21 +namespace rx
    1.22 +{
    1.23 +
    1.24 +bool VertexBuffer9::mTranslationsInitialized = false;
    1.25 +VertexBuffer9::FormatConverter VertexBuffer9::mFormatConverters[NUM_GL_VERTEX_ATTRIB_TYPES][2][4];
    1.26 +
    1.27 +VertexBuffer9::VertexBuffer9(rx::Renderer9 *const renderer) : mRenderer(renderer)
    1.28 +{
    1.29 +    mVertexBuffer = NULL;
    1.30 +    mBufferSize = 0;
    1.31 +    mDynamicUsage = false;
    1.32 +
    1.33 +    if (!mTranslationsInitialized)
    1.34 +    {
    1.35 +        initializeTranslations(renderer->getCapsDeclTypes());
    1.36 +        mTranslationsInitialized = true;
    1.37 +    }
    1.38 +}
    1.39 +
    1.40 +VertexBuffer9::~VertexBuffer9()
    1.41 +{
    1.42 +    if (mVertexBuffer)
    1.43 +    {
    1.44 +        mVertexBuffer->Release();
    1.45 +        mVertexBuffer = NULL;
    1.46 +    }
    1.47 +}
    1.48 +
    1.49 +bool VertexBuffer9::initialize(unsigned int size, bool dynamicUsage)
    1.50 +{
    1.51 +    if (mVertexBuffer)
    1.52 +    {
    1.53 +        mVertexBuffer->Release();
    1.54 +        mVertexBuffer = NULL;
    1.55 +    }
    1.56 +
    1.57 +    updateSerial();
    1.58 +
    1.59 +    if (size > 0)
    1.60 +    {
    1.61 +        DWORD flags = D3DUSAGE_WRITEONLY;
    1.62 +        if (dynamicUsage)
    1.63 +        {
    1.64 +            flags |= D3DUSAGE_DYNAMIC;
    1.65 +        }
    1.66 +
    1.67 +        HRESULT result = mRenderer->createVertexBuffer(size, flags, &mVertexBuffer);
    1.68 +
    1.69 +        if (FAILED(result))
    1.70 +        {
    1.71 +            ERR("Out of memory allocating a vertex buffer of size %lu.", size);
    1.72 +            return false;
    1.73 +        }
    1.74 +    }
    1.75 +
    1.76 +    mBufferSize = size;
    1.77 +    mDynamicUsage = dynamicUsage;
    1.78 +    return true;
    1.79 +}
    1.80 +
    1.81 +VertexBuffer9 *VertexBuffer9::makeVertexBuffer9(VertexBuffer *vertexBuffer)
    1.82 +{
    1.83 +    ASSERT(HAS_DYNAMIC_TYPE(VertexBuffer9*, vertexBuffer));
    1.84 +    return static_cast<VertexBuffer9*>(vertexBuffer);
    1.85 +}
    1.86 +
    1.87 +bool VertexBuffer9::storeVertexAttributes(const gl::VertexAttribute &attrib, GLint start, GLsizei count,
    1.88 +                                             GLsizei instances, unsigned int offset)
    1.89 +{
    1.90 +    if (mVertexBuffer)
    1.91 +    {
    1.92 +        gl::Buffer *buffer = attrib.mBoundBuffer.get();
    1.93 +
    1.94 +        int inputStride = attrib.stride();
    1.95 +        int elementSize = attrib.typeSize();
    1.96 +        const FormatConverter &converter = formatConverter(attrib);
    1.97 +
    1.98 +        DWORD lockFlags = mDynamicUsage ? D3DLOCK_NOOVERWRITE : 0;
    1.99 +
   1.100 +        void *mapPtr = NULL;
   1.101 +
   1.102 +        unsigned int mapSize;
   1.103 +        if (!spaceRequired(attrib, count, instances, &mapSize))
   1.104 +        {
   1.105 +            return false;
   1.106 +        }
   1.107 +
   1.108 +        HRESULT result = mVertexBuffer->Lock(offset, mapSize, &mapPtr, lockFlags);
   1.109 +
   1.110 +        if (FAILED(result))
   1.111 +        {
   1.112 +            ERR("Lock failed with error 0x%08x", result);
   1.113 +            return false;
   1.114 +        }
   1.115 +
   1.116 +        const char *input = NULL;
   1.117 +        if (buffer)
   1.118 +        {
   1.119 +            BufferStorage *storage = buffer->getStorage();
   1.120 +            input = static_cast<const char*>(storage->getData()) + static_cast<int>(attrib.mOffset);
   1.121 +        }
   1.122 +        else
   1.123 +        {
   1.124 +            input = static_cast<const char*>(attrib.mPointer);
   1.125 +        }
   1.126 +
   1.127 +        if (instances == 0 || attrib.mDivisor == 0)
   1.128 +        {
   1.129 +            input += inputStride * start;
   1.130 +        }
   1.131 +
   1.132 +        if (converter.identity && inputStride == elementSize)
   1.133 +        {
   1.134 +            memcpy(mapPtr, input, count * inputStride);
   1.135 +        }
   1.136 +        else
   1.137 +        {
   1.138 +            converter.convertArray(input, inputStride, count, mapPtr);
   1.139 +        }
   1.140 +
   1.141 +        mVertexBuffer->Unlock();
   1.142 +
   1.143 +        return true;
   1.144 +    }
   1.145 +    else
   1.146 +    {
   1.147 +        ERR("Vertex buffer not initialized.");
   1.148 +        return false;
   1.149 +    }
   1.150 +}
   1.151 +
   1.152 +bool VertexBuffer9::storeRawData(const void* data, unsigned int size, unsigned int offset)
   1.153 +{
   1.154 +    if (mVertexBuffer)
   1.155 +    {
   1.156 +        DWORD lockFlags = mDynamicUsage ? D3DLOCK_NOOVERWRITE : 0;
   1.157 +
   1.158 +        void *mapPtr = NULL;
   1.159 +        HRESULT result = mVertexBuffer->Lock(offset, size, &mapPtr, lockFlags);
   1.160 +
   1.161 +        if (FAILED(result))
   1.162 +        {
   1.163 +            ERR("Lock failed with error 0x%08x", result);
   1.164 +            return false;
   1.165 +        }
   1.166 +
   1.167 +        memcpy(mapPtr, data, size);
   1.168 +
   1.169 +        mVertexBuffer->Unlock();
   1.170 +
   1.171 +        return true;
   1.172 +    }
   1.173 +    else
   1.174 +    {
   1.175 +        ERR("Vertex buffer not initialized.");
   1.176 +        return false;
   1.177 +    }
   1.178 +}
   1.179 +
   1.180 +bool VertexBuffer9::getSpaceRequired(const gl::VertexAttribute &attrib, GLsizei count, GLsizei instances,
   1.181 +                                     unsigned int *outSpaceRequired) const
   1.182 +{
   1.183 +    return spaceRequired(attrib, count, instances, outSpaceRequired);
   1.184 +}
   1.185 +
   1.186 +bool VertexBuffer9::requiresConversion(const gl::VertexAttribute &attrib) const
   1.187 +{
   1.188 +    return formatConverter(attrib).identity;
   1.189 +}
   1.190 +
   1.191 +unsigned int VertexBuffer9::getVertexSize(const gl::VertexAttribute &attrib) const
   1.192 +{
   1.193 +    unsigned int spaceRequired;
   1.194 +    return getSpaceRequired(attrib, 1, 0, &spaceRequired) ? spaceRequired : 0;
   1.195 +}
   1.196 +
   1.197 +D3DDECLTYPE VertexBuffer9::getDeclType(const gl::VertexAttribute &attrib) const
   1.198 +{
   1.199 +    return formatConverter(attrib).d3dDeclType;
   1.200 +}
   1.201 +
   1.202 +unsigned int VertexBuffer9::getBufferSize() const
   1.203 +{
   1.204 +    return mBufferSize;
   1.205 +}
   1.206 +
   1.207 +bool VertexBuffer9::setBufferSize(unsigned int size)
   1.208 +{
   1.209 +    if (size > mBufferSize)
   1.210 +    {
   1.211 +        return initialize(size, mDynamicUsage);
   1.212 +    }
   1.213 +    else
   1.214 +    {
   1.215 +        return true;
   1.216 +    }
   1.217 +}
   1.218 +
   1.219 +bool VertexBuffer9::discard()
   1.220 +{
   1.221 +    if (mVertexBuffer)
   1.222 +    {
   1.223 +        void *dummy;
   1.224 +        HRESULT result;
   1.225 +
   1.226 +        result = mVertexBuffer->Lock(0, 1, &dummy, D3DLOCK_DISCARD);
   1.227 +        if (FAILED(result))
   1.228 +        {
   1.229 +            ERR("Discard lock failed with error 0x%08x", result);
   1.230 +            return false;
   1.231 +        }
   1.232 +
   1.233 +        result = mVertexBuffer->Unlock();
   1.234 +        if (FAILED(result))
   1.235 +        {
   1.236 +            ERR("Discard unlock failed with error 0x%08x", result);
   1.237 +            return false;
   1.238 +        }
   1.239 +
   1.240 +        return true;
   1.241 +    }
   1.242 +    else
   1.243 +    {
   1.244 +        ERR("Vertex buffer not initialized.");
   1.245 +        return false;
   1.246 +    }
   1.247 +}
   1.248 +
   1.249 +IDirect3DVertexBuffer9 * VertexBuffer9::getBuffer() const
   1.250 +{
   1.251 +    return mVertexBuffer;
   1.252 +}
   1.253 +
   1.254 +// Mapping from OpenGL-ES vertex attrib type to D3D decl type:
   1.255 +//
   1.256 +// BYTE                 SHORT (Cast)
   1.257 +// BYTE-norm            FLOAT (Normalize) (can't be exactly represented as SHORT-norm)
   1.258 +// UNSIGNED_BYTE        UBYTE4 (Identity) or SHORT (Cast)
   1.259 +// UNSIGNED_BYTE-norm   UBYTE4N (Identity) or FLOAT (Normalize)
   1.260 +// SHORT                SHORT (Identity)
   1.261 +// SHORT-norm           SHORT-norm (Identity) or FLOAT (Normalize)
   1.262 +// UNSIGNED_SHORT       FLOAT (Cast)
   1.263 +// UNSIGNED_SHORT-norm  USHORT-norm (Identity) or FLOAT (Normalize)
   1.264 +// FIXED (not in WebGL) FLOAT (FixedToFloat)
   1.265 +// FLOAT                FLOAT (Identity)
   1.266 +
   1.267 +// GLToCType maps from GL type (as GLenum) to the C typedef.
   1.268 +template <GLenum GLType> struct GLToCType { };
   1.269 +
   1.270 +template <> struct GLToCType<GL_BYTE>           { typedef GLbyte type;      };
   1.271 +template <> struct GLToCType<GL_UNSIGNED_BYTE>  { typedef GLubyte type;     };
   1.272 +template <> struct GLToCType<GL_SHORT>          { typedef GLshort type;     };
   1.273 +template <> struct GLToCType<GL_UNSIGNED_SHORT> { typedef GLushort type;    };
   1.274 +template <> struct GLToCType<GL_FIXED>          { typedef GLuint type;      };
   1.275 +template <> struct GLToCType<GL_FLOAT>          { typedef GLfloat type;     };
   1.276 +
   1.277 +// This differs from D3DDECLTYPE in that it is unsized. (Size expansion is applied last.)
   1.278 +enum D3DVertexType
   1.279 +{
   1.280 +    D3DVT_FLOAT,
   1.281 +    D3DVT_SHORT,
   1.282 +    D3DVT_SHORT_NORM,
   1.283 +    D3DVT_UBYTE,
   1.284 +    D3DVT_UBYTE_NORM,
   1.285 +    D3DVT_USHORT_NORM
   1.286 +};
   1.287 +
   1.288 +// D3DToCType maps from D3D vertex type (as enum D3DVertexType) to the corresponding C type.
   1.289 +template <unsigned int D3DType> struct D3DToCType { };
   1.290 +
   1.291 +template <> struct D3DToCType<D3DVT_FLOAT> { typedef float type; };
   1.292 +template <> struct D3DToCType<D3DVT_SHORT> { typedef short type; };
   1.293 +template <> struct D3DToCType<D3DVT_SHORT_NORM> { typedef short type; };
   1.294 +template <> struct D3DToCType<D3DVT_UBYTE> { typedef unsigned char type; };
   1.295 +template <> struct D3DToCType<D3DVT_UBYTE_NORM> { typedef unsigned char type; };
   1.296 +template <> struct D3DToCType<D3DVT_USHORT_NORM> { typedef unsigned short type; };
   1.297 +
   1.298 +// Encode the type/size combinations that D3D permits. For each type/size it expands to a widener that will provide the appropriate final size.
   1.299 +template <unsigned int type, int size> struct WidenRule { };
   1.300 +
   1.301 +template <int size> struct WidenRule<D3DVT_FLOAT, size>          : NoWiden<size> { };
   1.302 +template <int size> struct WidenRule<D3DVT_SHORT, size>          : WidenToEven<size> { };
   1.303 +template <int size> struct WidenRule<D3DVT_SHORT_NORM, size>     : WidenToEven<size> { };
   1.304 +template <int size> struct WidenRule<D3DVT_UBYTE, size>          : WidenToFour<size> { };
   1.305 +template <int size> struct WidenRule<D3DVT_UBYTE_NORM, size>     : WidenToFour<size> { };
   1.306 +template <int size> struct WidenRule<D3DVT_USHORT_NORM, size>    : WidenToEven<size> { };
   1.307 +
   1.308 +// VertexTypeFlags encodes the D3DCAPS9::DeclType flag and vertex declaration flag for each D3D vertex type & size combination.
   1.309 +template <unsigned int d3dtype, int size> struct VertexTypeFlags { };
   1.310 +
   1.311 +template <unsigned int _capflag, unsigned int _declflag>
   1.312 +struct VertexTypeFlagsHelper
   1.313 +{
   1.314 +    enum { capflag = _capflag };
   1.315 +    enum { declflag = _declflag };
   1.316 +};
   1.317 +
   1.318 +template <> struct VertexTypeFlags<D3DVT_FLOAT, 1> : VertexTypeFlagsHelper<0, D3DDECLTYPE_FLOAT1> { };
   1.319 +template <> struct VertexTypeFlags<D3DVT_FLOAT, 2> : VertexTypeFlagsHelper<0, D3DDECLTYPE_FLOAT2> { };
   1.320 +template <> struct VertexTypeFlags<D3DVT_FLOAT, 3> : VertexTypeFlagsHelper<0, D3DDECLTYPE_FLOAT3> { };
   1.321 +template <> struct VertexTypeFlags<D3DVT_FLOAT, 4> : VertexTypeFlagsHelper<0, D3DDECLTYPE_FLOAT4> { };
   1.322 +template <> struct VertexTypeFlags<D3DVT_SHORT, 2> : VertexTypeFlagsHelper<0, D3DDECLTYPE_SHORT2> { };
   1.323 +template <> struct VertexTypeFlags<D3DVT_SHORT, 4> : VertexTypeFlagsHelper<0, D3DDECLTYPE_SHORT4> { };
   1.324 +template <> struct VertexTypeFlags<D3DVT_SHORT_NORM, 2> : VertexTypeFlagsHelper<D3DDTCAPS_SHORT2N, D3DDECLTYPE_SHORT2N> { };
   1.325 +template <> struct VertexTypeFlags<D3DVT_SHORT_NORM, 4> : VertexTypeFlagsHelper<D3DDTCAPS_SHORT4N, D3DDECLTYPE_SHORT4N> { };
   1.326 +template <> struct VertexTypeFlags<D3DVT_UBYTE, 4> : VertexTypeFlagsHelper<D3DDTCAPS_UBYTE4, D3DDECLTYPE_UBYTE4> { };
   1.327 +template <> struct VertexTypeFlags<D3DVT_UBYTE_NORM, 4> : VertexTypeFlagsHelper<D3DDTCAPS_UBYTE4N, D3DDECLTYPE_UBYTE4N> { };
   1.328 +template <> struct VertexTypeFlags<D3DVT_USHORT_NORM, 2> : VertexTypeFlagsHelper<D3DDTCAPS_USHORT2N, D3DDECLTYPE_USHORT2N> { };
   1.329 +template <> struct VertexTypeFlags<D3DVT_USHORT_NORM, 4> : VertexTypeFlagsHelper<D3DDTCAPS_USHORT4N, D3DDECLTYPE_USHORT4N> { };
   1.330 +
   1.331 +
   1.332 +// VertexTypeMapping maps GL type & normalized flag to preferred and fallback D3D vertex types (as D3DVertexType enums).
   1.333 +template <GLenum GLtype, bool normalized> struct VertexTypeMapping { };
   1.334 +
   1.335 +template <D3DVertexType Preferred, D3DVertexType Fallback = Preferred>
   1.336 +struct VertexTypeMappingBase
   1.337 +{
   1.338 +    enum { preferred = Preferred };
   1.339 +    enum { fallback = Fallback };
   1.340 +};
   1.341 +
   1.342 +template <> struct VertexTypeMapping<GL_BYTE, false>                        : VertexTypeMappingBase<D3DVT_SHORT> { };                       // Cast
   1.343 +template <> struct VertexTypeMapping<GL_BYTE, true>                         : VertexTypeMappingBase<D3DVT_FLOAT> { };                       // Normalize
   1.344 +template <> struct VertexTypeMapping<GL_UNSIGNED_BYTE, false>               : VertexTypeMappingBase<D3DVT_UBYTE, D3DVT_FLOAT> { };          // Identity, Cast
   1.345 +template <> struct VertexTypeMapping<GL_UNSIGNED_BYTE, true>                : VertexTypeMappingBase<D3DVT_UBYTE_NORM, D3DVT_FLOAT> { };     // Identity, Normalize
   1.346 +template <> struct VertexTypeMapping<GL_SHORT, false>                       : VertexTypeMappingBase<D3DVT_SHORT> { };                       // Identity
   1.347 +template <> struct VertexTypeMapping<GL_SHORT, true>                        : VertexTypeMappingBase<D3DVT_SHORT_NORM, D3DVT_FLOAT> { };     // Cast, Normalize
   1.348 +template <> struct VertexTypeMapping<GL_UNSIGNED_SHORT, false>              : VertexTypeMappingBase<D3DVT_FLOAT> { };                       // Cast
   1.349 +template <> struct VertexTypeMapping<GL_UNSIGNED_SHORT, true>               : VertexTypeMappingBase<D3DVT_USHORT_NORM, D3DVT_FLOAT> { };    // Cast, Normalize
   1.350 +template <bool normalized> struct VertexTypeMapping<GL_FIXED, normalized>   : VertexTypeMappingBase<D3DVT_FLOAT> { };                       // FixedToFloat
   1.351 +template <bool normalized> struct VertexTypeMapping<GL_FLOAT, normalized>   : VertexTypeMappingBase<D3DVT_FLOAT> { };                       // Identity
   1.352 +
   1.353 +
   1.354 +// Given a GL type & norm flag and a D3D type, ConversionRule provides the type conversion rule (Cast, Normalize, Identity, FixedToFloat).
   1.355 +// The conversion rules themselves are defined in vertexconversion.h.
   1.356 +
   1.357 +// Almost all cases are covered by Cast (including those that are actually Identity since Cast<T,T> knows it's an identity mapping).
   1.358 +template <GLenum fromType, bool normalized, unsigned int toType>
   1.359 +struct ConversionRule : Cast<typename GLToCType<fromType>::type, typename D3DToCType<toType>::type> { };
   1.360 +
   1.361 +// All conversions from normalized types to float use the Normalize operator.
   1.362 +template <GLenum fromType> struct ConversionRule<fromType, true, D3DVT_FLOAT> : Normalize<typename GLToCType<fromType>::type> { };
   1.363 +
   1.364 +// Use a full specialization for this so that it preferentially matches ahead of the generic normalize-to-float rules.
   1.365 +template <> struct ConversionRule<GL_FIXED, true, D3DVT_FLOAT>  : FixedToFloat<GLint, 16> { };
   1.366 +template <> struct ConversionRule<GL_FIXED, false, D3DVT_FLOAT> : FixedToFloat<GLint, 16> { };
   1.367 +
   1.368 +// A 2-stage construction is used for DefaultVertexValues because float must use SimpleDefaultValues (i.e. 0/1)
   1.369 +// whether it is normalized or not.
   1.370 +template <class T, bool normalized> struct DefaultVertexValuesStage2 { };
   1.371 +
   1.372 +template <class T> struct DefaultVertexValuesStage2<T, true>  : NormalizedDefaultValues<T> { };
   1.373 +template <class T> struct DefaultVertexValuesStage2<T, false> : SimpleDefaultValues<T> { };
   1.374 +
   1.375 +// Work out the default value rule for a D3D type (expressed as the C type) and
   1.376 +template <class T, bool normalized> struct DefaultVertexValues : DefaultVertexValuesStage2<T, normalized> { };
   1.377 +template <bool normalized> struct DefaultVertexValues<float, normalized> : SimpleDefaultValues<float> { };
   1.378 +
   1.379 +// Policy rules for use with Converter, to choose whether to use the preferred or fallback conversion.
   1.380 +// The fallback conversion produces an output that all D3D9 devices must support.
   1.381 +template <class T> struct UsePreferred { enum { type = T::preferred }; };
   1.382 +template <class T> struct UseFallback { enum { type = T::fallback }; };
   1.383 +
   1.384 +// Converter ties it all together. Given an OpenGL type/norm/size and choice of preferred/fallback conversion,
   1.385 +// it provides all the members of the appropriate VertexDataConverter, the D3DCAPS9::DeclTypes flag in cap flag
   1.386 +// and the D3DDECLTYPE member needed for the vertex declaration in declflag.
   1.387 +template <GLenum fromType, bool normalized, int size, template <class T> class PreferenceRule>
   1.388 +struct Converter
   1.389 +    : VertexDataConverter<typename GLToCType<fromType>::type,
   1.390 +                          WidenRule<PreferenceRule< VertexTypeMapping<fromType, normalized> >::type, size>,
   1.391 +                          ConversionRule<fromType,
   1.392 +                                         normalized,
   1.393 +                                         PreferenceRule< VertexTypeMapping<fromType, normalized> >::type>,
   1.394 +                          DefaultVertexValues<typename D3DToCType<PreferenceRule< VertexTypeMapping<fromType, normalized> >::type>::type, normalized > >
   1.395 +{
   1.396 +private:
   1.397 +    enum { d3dtype = PreferenceRule< VertexTypeMapping<fromType, normalized> >::type };
   1.398 +    enum { d3dsize = WidenRule<d3dtype, size>::finalWidth };
   1.399 +
   1.400 +public:
   1.401 +    enum { capflag = VertexTypeFlags<d3dtype, d3dsize>::capflag };
   1.402 +    enum { declflag = VertexTypeFlags<d3dtype, d3dsize>::declflag };
   1.403 +};
   1.404 +
   1.405 +// Initialize a TranslationInfo
   1.406 +#define TRANSLATION(type, norm, size, preferred)                                    \
   1.407 +    {                                                                               \
   1.408 +        Converter<type, norm, size, preferred>::identity,                           \
   1.409 +        Converter<type, norm, size, preferred>::finalSize,                          \
   1.410 +        Converter<type, norm, size, preferred>::convertArray,                       \
   1.411 +        static_cast<D3DDECLTYPE>(Converter<type, norm, size, preferred>::declflag)  \
   1.412 +    }
   1.413 +
   1.414 +#define TRANSLATION_FOR_TYPE_NORM_SIZE(type, norm, size)    \
   1.415 +    {                                                       \
   1.416 +        Converter<type, norm, size, UsePreferred>::capflag, \
   1.417 +        TRANSLATION(type, norm, size, UsePreferred),        \
   1.418 +        TRANSLATION(type, norm, size, UseFallback)          \
   1.419 +    }
   1.420 +
   1.421 +#define TRANSLATIONS_FOR_TYPE(type)                                                                                                                                                                         \
   1.422 +    {                                                                                                                                                                                                       \
   1.423 +        { 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) }, \
   1.424 +        { 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) },     \
   1.425 +    }
   1.426 +
   1.427 +#define TRANSLATIONS_FOR_TYPE_NO_NORM(type)                                                                                                                                                                 \
   1.428 +    {                                                                                                                                                                                                       \
   1.429 +        { 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) }, \
   1.430 +        { 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) }, \
   1.431 +    }
   1.432 +
   1.433 +const VertexBuffer9::TranslationDescription VertexBuffer9::mPossibleTranslations[NUM_GL_VERTEX_ATTRIB_TYPES][2][4] = // [GL types as enumerated by typeIndex()][normalized][size-1]
   1.434 +{
   1.435 +    TRANSLATIONS_FOR_TYPE(GL_BYTE),
   1.436 +    TRANSLATIONS_FOR_TYPE(GL_UNSIGNED_BYTE),
   1.437 +    TRANSLATIONS_FOR_TYPE(GL_SHORT),
   1.438 +    TRANSLATIONS_FOR_TYPE(GL_UNSIGNED_SHORT),
   1.439 +    TRANSLATIONS_FOR_TYPE_NO_NORM(GL_FIXED),
   1.440 +    TRANSLATIONS_FOR_TYPE_NO_NORM(GL_FLOAT)
   1.441 +};
   1.442 +
   1.443 +void VertexBuffer9::initializeTranslations(DWORD declTypes)
   1.444 +{
   1.445 +    for (unsigned int i = 0; i < NUM_GL_VERTEX_ATTRIB_TYPES; i++)
   1.446 +    {
   1.447 +        for (unsigned int j = 0; j < 2; j++)
   1.448 +        {
   1.449 +            for (unsigned int k = 0; k < 4; k++)
   1.450 +            {
   1.451 +                if (mPossibleTranslations[i][j][k].capsFlag == 0 || (declTypes & mPossibleTranslations[i][j][k].capsFlag) != 0)
   1.452 +                {
   1.453 +                    mFormatConverters[i][j][k] = mPossibleTranslations[i][j][k].preferredConversion;
   1.454 +                }
   1.455 +                else
   1.456 +                {
   1.457 +                    mFormatConverters[i][j][k] = mPossibleTranslations[i][j][k].fallbackConversion;
   1.458 +                }
   1.459 +            }
   1.460 +        }
   1.461 +    }
   1.462 +}
   1.463 +
   1.464 +unsigned int VertexBuffer9::typeIndex(GLenum type)
   1.465 +{
   1.466 +    switch (type)
   1.467 +    {
   1.468 +      case GL_BYTE: return 0;
   1.469 +      case GL_UNSIGNED_BYTE: return 1;
   1.470 +      case GL_SHORT: return 2;
   1.471 +      case GL_UNSIGNED_SHORT: return 3;
   1.472 +      case GL_FIXED: return 4;
   1.473 +      case GL_FLOAT: return 5;
   1.474 +
   1.475 +      default: UNREACHABLE(); return 5;
   1.476 +    }
   1.477 +}
   1.478 +
   1.479 +const VertexBuffer9::FormatConverter &VertexBuffer9::formatConverter(const gl::VertexAttribute &attribute)
   1.480 +{
   1.481 +    return mFormatConverters[typeIndex(attribute.mType)][attribute.mNormalized][attribute.mSize - 1];
   1.482 +}
   1.483 +
   1.484 +bool VertexBuffer9::spaceRequired(const gl::VertexAttribute &attrib, std::size_t count, GLsizei instances,
   1.485 +                                  unsigned int *outSpaceRequired)
   1.486 +{
   1.487 +    unsigned int elementSize = formatConverter(attrib).outputElementSize;
   1.488 +
   1.489 +    if (instances == 0 || attrib.mDivisor == 0)
   1.490 +    {
   1.491 +        unsigned int elementCount = 0;
   1.492 +        if (instances == 0 || attrib.mDivisor == 0)
   1.493 +        {
   1.494 +            elementCount = count;
   1.495 +        }
   1.496 +        else
   1.497 +        {
   1.498 +            if (static_cast<unsigned int>(instances) < std::numeric_limits<unsigned int>::max() - (attrib.mDivisor - 1))
   1.499 +            {
   1.500 +                // Round up
   1.501 +                elementCount = (static_cast<unsigned int>(instances) + (attrib.mDivisor - 1)) / attrib.mDivisor;
   1.502 +            }
   1.503 +            else
   1.504 +            {
   1.505 +                elementCount = static_cast<unsigned int>(instances) / attrib.mDivisor;
   1.506 +            }
   1.507 +        }
   1.508 +
   1.509 +        if (elementSize <= std::numeric_limits<unsigned int>::max() / elementCount)
   1.510 +        {
   1.511 +            if (outSpaceRequired)
   1.512 +            {
   1.513 +                *outSpaceRequired = elementSize * elementCount;
   1.514 +            }
   1.515 +            return true;
   1.516 +        }
   1.517 +        else
   1.518 +        {
   1.519 +            return false;
   1.520 +        }
   1.521 +    }
   1.522 +    else
   1.523 +    {
   1.524 +        const unsigned int elementSize = 4;
   1.525 +        if (outSpaceRequired)
   1.526 +        {
   1.527 +            *outSpaceRequired = elementSize * 4;
   1.528 +        }
   1.529 +        return true;
   1.530 +    }
   1.531 +}
   1.532 +
   1.533 +}

mercurial