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 +}