formatutils9.cpp (27413B)
1 // 2 // Copyright 2013 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 7 // formatutils9.cpp: Queries for GL image formats and their translations to D3D9 8 // formats. 9 10 #include "libANGLE/renderer/d3d/d3d9/formatutils9.h" 11 12 #include "image_util/copyimage.h" 13 #include "image_util/generatemip.h" 14 #include "image_util/loadimage.h" 15 16 #include "anglebase/no_destructor.h" 17 #include "libANGLE/renderer/d3d/d3d9/Renderer9.h" 18 #include "libANGLE/renderer/d3d/d3d9/vertexconversion.h" 19 20 using namespace angle; 21 22 namespace rx 23 { 24 25 namespace d3d9 26 { 27 28 constexpr D3DFORMAT D3DFMT_INTZ = ((D3DFORMAT)(MAKEFOURCC('I', 'N', 'T', 'Z'))); 29 constexpr D3DFORMAT D3DFMT_NULL = ((D3DFORMAT)(MAKEFOURCC('N', 'U', 'L', 'L'))); 30 31 // A map to determine the pixel size and mip generation function of a given D3D format 32 typedef std::map<D3DFORMAT, D3DFormat> D3D9FormatInfoMap; 33 34 typedef std::pair<GLint, InitializeTextureDataFunction> InternalFormatInitialzerPair; 35 typedef std::map<GLint, InitializeTextureDataFunction> InternalFormatInitialzerMap; 36 37 static InternalFormatInitialzerMap BuildInternalFormatInitialzerMap() 38 { 39 using namespace angle; // For image initialization functions 40 41 InternalFormatInitialzerMap map; 42 43 map.insert(InternalFormatInitialzerPair( 44 GL_RGB16F, Initialize4ComponentData<GLhalf, 0x0000, 0x0000, 0x0000, gl::Float16One>)); 45 map.insert(InternalFormatInitialzerPair( 46 GL_RGB32F, 47 Initialize4ComponentData<GLfloat, 0x00000000, 0x00000000, 0x00000000, gl::Float32One>)); 48 49 return map; 50 } 51 52 static void UnreachableLoad(size_t width, 53 size_t height, 54 size_t depth, 55 const uint8_t *input, 56 size_t inputRowPitch, 57 size_t inputDepthPitch, 58 uint8_t *output, 59 size_t outputRowPitch, 60 size_t outputDepthPitch) 61 { 62 UNREACHABLE(); 63 } 64 65 typedef std::pair<GLenum, TextureFormat> D3D9FormatPair; 66 typedef std::map<GLenum, TextureFormat> D3D9FormatMap; 67 68 TextureFormat::TextureFormat() 69 : texFormat(D3DFMT_UNKNOWN), 70 renderFormat(D3DFMT_UNKNOWN), 71 dataInitializerFunction(nullptr), 72 loadFunction(UnreachableLoad) 73 {} 74 75 static inline void InsertD3D9FormatInfo(D3D9FormatMap *map, 76 GLenum internalFormat, 77 D3DFORMAT texFormat, 78 D3DFORMAT renderFormat, 79 LoadImageFunction loadFunction) 80 { 81 TextureFormat info; 82 info.texFormat = texFormat; 83 info.renderFormat = renderFormat; 84 85 static const angle::base::NoDestructor<InternalFormatInitialzerMap> dataInitializationMap( 86 BuildInternalFormatInitialzerMap()); 87 InternalFormatInitialzerMap::const_iterator dataInitIter = 88 dataInitializationMap->find(internalFormat); 89 info.dataInitializerFunction = 90 (dataInitIter != dataInitializationMap->end()) ? dataInitIter->second : nullptr; 91 92 info.loadFunction = loadFunction; 93 94 map->insert(std::make_pair(internalFormat, info)); 95 } 96 97 static D3D9FormatMap BuildD3D9FormatMap() 98 { 99 using namespace angle; // For image loading functions 100 101 D3D9FormatMap map; 102 103 // clang-format off 104 // | Internal format | Texture format | Render format | Load function | 105 InsertD3D9FormatInfo(&map, GL_NONE, D3DFMT_NULL, D3DFMT_NULL, UnreachableLoad ); 106 107 // We choose to downsample the GL_DEPTH_COMPONENT32_OES format to a 24-bit format because D3DFMT_D32 is not widely 108 // supported. We're allowed to do this because: 109 // - The ES spec 2.0.25 sec 3.7.1 states that we're allowed to store texture formats with internal format 110 // resolutions of our own choosing. 111 // - OES_depth_texture states that downsampling of the depth formats is allowed. 112 // - ANGLE_depth_texture does not state minimum required resolutions of the depth texture formats it 113 // introduces. 114 // In ES3 however, there are minimum resolutions for the texture formats and this would not be allowed. 115 116 InsertD3D9FormatInfo(&map, GL_DEPTH_COMPONENT16, D3DFMT_INTZ, D3DFMT_D24S8, UnreachableLoad ); 117 InsertD3D9FormatInfo(&map, GL_DEPTH_COMPONENT32_OES, D3DFMT_INTZ, D3DFMT_D24X8, UnreachableLoad ); 118 InsertD3D9FormatInfo(&map, GL_DEPTH24_STENCIL8_OES, D3DFMT_INTZ, D3DFMT_D24S8, UnreachableLoad ); 119 InsertD3D9FormatInfo(&map, GL_STENCIL_INDEX8, D3DFMT_UNKNOWN, D3DFMT_D24S8, UnreachableLoad ); // TODO: What's the texture format? 120 121 InsertD3D9FormatInfo(&map, GL_RGBA32F_EXT, D3DFMT_A32B32G32R32F, D3DFMT_A32B32G32R32F, LoadToNative<GLfloat, 4> ); 122 InsertD3D9FormatInfo(&map, GL_RGB32F_EXT, D3DFMT_A32B32G32R32F, D3DFMT_A32B32G32R32F, LoadToNative3To4<GLfloat, gl::Float32One>); 123 InsertD3D9FormatInfo(&map, GL_RG32F_EXT, D3DFMT_G32R32F, D3DFMT_G32R32F, LoadToNative<GLfloat, 2> ); 124 InsertD3D9FormatInfo(&map, GL_R32F_EXT, D3DFMT_R32F, D3DFMT_R32F, LoadToNative<GLfloat, 1> ); 125 InsertD3D9FormatInfo(&map, GL_ALPHA32F_EXT, D3DFMT_A32B32G32R32F, D3DFMT_UNKNOWN, LoadA32FToRGBA32F ); 126 InsertD3D9FormatInfo(&map, GL_LUMINANCE32F_EXT, D3DFMT_A32B32G32R32F, D3DFMT_UNKNOWN, LoadL32FToRGBA32F ); 127 InsertD3D9FormatInfo(&map, GL_LUMINANCE_ALPHA32F_EXT, D3DFMT_A32B32G32R32F, D3DFMT_UNKNOWN, LoadLA32FToRGBA32F ); 128 129 InsertD3D9FormatInfo(&map, GL_RGBA16F_EXT, D3DFMT_A16B16G16R16F, D3DFMT_A16B16G16R16F, LoadToNative<GLhalf, 4> ); 130 InsertD3D9FormatInfo(&map, GL_RGB16F_EXT, D3DFMT_A16B16G16R16F, D3DFMT_A16B16G16R16F, LoadToNative3To4<GLhalf, gl::Float16One> ); 131 InsertD3D9FormatInfo(&map, GL_RG16F_EXT, D3DFMT_G16R16F, D3DFMT_G16R16F, LoadToNative<GLhalf, 2> ); 132 InsertD3D9FormatInfo(&map, GL_R16F_EXT, D3DFMT_R16F, D3DFMT_R16F, LoadToNative<GLhalf, 1> ); 133 InsertD3D9FormatInfo(&map, GL_ALPHA16F_EXT, D3DFMT_A16B16G16R16F, D3DFMT_UNKNOWN, LoadA16FToRGBA16F ); 134 InsertD3D9FormatInfo(&map, GL_LUMINANCE16F_EXT, D3DFMT_A16B16G16R16F, D3DFMT_UNKNOWN, LoadL16FToRGBA16F ); 135 InsertD3D9FormatInfo(&map, GL_LUMINANCE_ALPHA16F_EXT, D3DFMT_A16B16G16R16F, D3DFMT_UNKNOWN, LoadLA16FToRGBA16F ); 136 137 InsertD3D9FormatInfo(&map, GL_ALPHA8_EXT, D3DFMT_A8R8G8B8, D3DFMT_A8R8G8B8, LoadA8ToBGRA8 ); 138 139 InsertD3D9FormatInfo(&map, GL_RGB8_OES, D3DFMT_X8R8G8B8, D3DFMT_X8R8G8B8, LoadRGB8ToBGRX8 ); 140 InsertD3D9FormatInfo(&map, GL_RGB565, D3DFMT_X8R8G8B8, D3DFMT_X8R8G8B8, LoadR5G6B5ToBGRA8 ); 141 InsertD3D9FormatInfo(&map, GL_RGBA8_OES, D3DFMT_A8R8G8B8, D3DFMT_A8R8G8B8, LoadRGBA8ToBGRA8 ); 142 InsertD3D9FormatInfo(&map, GL_RGBA4, D3DFMT_A8R8G8B8, D3DFMT_A8R8G8B8, LoadRGBA4ToBGRA8 ); 143 InsertD3D9FormatInfo(&map, GL_RGB5_A1, D3DFMT_A8R8G8B8, D3DFMT_A8R8G8B8, LoadRGB5A1ToBGRA8 ); 144 InsertD3D9FormatInfo(&map, GL_R8_EXT, D3DFMT_X8R8G8B8, D3DFMT_X8R8G8B8, LoadR8ToBGRX8 ); 145 InsertD3D9FormatInfo(&map, GL_RG8_EXT, D3DFMT_X8R8G8B8, D3DFMT_X8R8G8B8, LoadRG8ToBGRX8 ); 146 147 InsertD3D9FormatInfo(&map, GL_SRGB8, D3DFMT_X8R8G8B8, D3DFMT_UNKNOWN, LoadRGB8ToBGRX8 ); 148 InsertD3D9FormatInfo(&map, GL_SRGB8_ALPHA8_EXT, D3DFMT_A8R8G8B8, D3DFMT_A8R8G8B8, LoadRGBA8ToBGRA8 ); 149 150 InsertD3D9FormatInfo(&map, GL_BGRA8_EXT, D3DFMT_A8R8G8B8, D3DFMT_A8R8G8B8, LoadToNative<GLubyte, 4> ); 151 InsertD3D9FormatInfo(&map, GL_BGRA4_ANGLEX, D3DFMT_A8R8G8B8, D3DFMT_A8R8G8B8, LoadBGRA4ToBGRA8 ); 152 InsertD3D9FormatInfo(&map, GL_BGR5_A1_ANGLEX, D3DFMT_A8R8G8B8, D3DFMT_A8R8G8B8, LoadBGR5A1ToBGRA8 ); 153 154 InsertD3D9FormatInfo(&map, GL_COMPRESSED_RGB_S3TC_DXT1_EXT, D3DFMT_DXT1, D3DFMT_UNKNOWN, LoadCompressedToNative<4, 4, 1, 8> ); 155 InsertD3D9FormatInfo(&map, GL_COMPRESSED_RGBA_S3TC_DXT1_EXT, D3DFMT_DXT1, D3DFMT_UNKNOWN, LoadCompressedToNative<4, 4, 1, 8> ); 156 InsertD3D9FormatInfo(&map, GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE, D3DFMT_DXT3, D3DFMT_UNKNOWN, LoadCompressedToNative<4, 4, 1, 16> ); 157 InsertD3D9FormatInfo(&map, GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE, D3DFMT_DXT5, D3DFMT_UNKNOWN, LoadCompressedToNative<4, 4, 1, 16> ); 158 159 InsertD3D9FormatInfo(&map, GL_COMPRESSED_SRGB_S3TC_DXT1_EXT, D3DFMT_DXT1, D3DFMT_UNKNOWN, LoadCompressedToNative<4, 4, 1, 8> ); 160 InsertD3D9FormatInfo(&map, GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT, D3DFMT_DXT1, D3DFMT_UNKNOWN, LoadCompressedToNative<4, 4, 1, 8> ); 161 InsertD3D9FormatInfo(&map, GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT, D3DFMT_DXT3, D3DFMT_UNKNOWN, LoadCompressedToNative<4, 4, 1, 16> ); 162 InsertD3D9FormatInfo(&map, GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT, D3DFMT_DXT5, D3DFMT_UNKNOWN, LoadCompressedToNative<4, 4, 1, 16> ); 163 164 // These formats require checking if the renderer supports D3DFMT_L8 or D3DFMT_A8L8 and 165 // then changing the format and loading function appropriately. 166 InsertD3D9FormatInfo(&map, GL_LUMINANCE8_EXT, D3DFMT_L8, D3DFMT_UNKNOWN, LoadToNative<GLubyte, 1> ); 167 InsertD3D9FormatInfo(&map, GL_LUMINANCE8_ALPHA8_EXT, D3DFMT_A8L8, D3DFMT_UNKNOWN, LoadToNative<GLubyte, 2> ); 168 // clang-format on 169 170 return map; 171 } 172 173 const TextureFormat &GetTextureFormatInfo(GLenum internalFormat) 174 { 175 static const angle::base::NoDestructor<D3D9FormatMap> formatMap(BuildD3D9FormatMap()); 176 D3D9FormatMap::const_iterator iter = formatMap->find(internalFormat); 177 if (iter != formatMap->end()) 178 { 179 return iter->second; 180 } 181 else 182 { 183 static const TextureFormat defaultInfo; 184 return defaultInfo; 185 } 186 } 187 188 static GLenum GetDeclTypeComponentType(D3DDECLTYPE declType) 189 { 190 switch (declType) 191 { 192 case D3DDECLTYPE_FLOAT1: 193 return GL_FLOAT; 194 case D3DDECLTYPE_FLOAT2: 195 return GL_FLOAT; 196 case D3DDECLTYPE_FLOAT3: 197 return GL_FLOAT; 198 case D3DDECLTYPE_FLOAT4: 199 return GL_FLOAT; 200 case D3DDECLTYPE_UBYTE4: 201 return GL_UNSIGNED_INT; 202 case D3DDECLTYPE_SHORT2: 203 return GL_INT; 204 case D3DDECLTYPE_SHORT4: 205 return GL_INT; 206 case D3DDECLTYPE_UBYTE4N: 207 return GL_UNSIGNED_NORMALIZED; 208 case D3DDECLTYPE_SHORT4N: 209 return GL_SIGNED_NORMALIZED; 210 case D3DDECLTYPE_USHORT4N: 211 return GL_UNSIGNED_NORMALIZED; 212 case D3DDECLTYPE_SHORT2N: 213 return GL_SIGNED_NORMALIZED; 214 case D3DDECLTYPE_USHORT2N: 215 return GL_UNSIGNED_NORMALIZED; 216 default: 217 UNREACHABLE(); 218 return GL_NONE; 219 } 220 } 221 222 // Attribute format conversion 223 enum 224 { 225 NUM_GL_VERTEX_ATTRIB_TYPES = 6 226 }; 227 228 struct TranslationDescription 229 { 230 DWORD capsFlag; 231 VertexFormat preferredConversion; 232 VertexFormat fallbackConversion; 233 }; 234 235 // Mapping from OpenGL-ES vertex attrib type to D3D decl type: 236 // 237 // BYTE SHORT (Cast) 238 // BYTE-norm FLOAT (Normalize) (can't be exactly represented as SHORT-norm) 239 // UNSIGNED_BYTE UBYTE4 (Identity) or SHORT (Cast) 240 // UNSIGNED_BYTE-norm UBYTE4N (Identity) or FLOAT (Normalize) 241 // SHORT SHORT (Identity) 242 // SHORT-norm SHORT-norm (Identity) or FLOAT (Normalize) 243 // UNSIGNED_SHORT FLOAT (Cast) 244 // UNSIGNED_SHORT-norm USHORT-norm (Identity) or FLOAT (Normalize) 245 // FIXED (not in WebGL) FLOAT (FixedToFloat) 246 // FLOAT FLOAT (Identity) 247 248 // GLToCType maps from GL type (as GLenum) to the C typedef. 249 template <GLenum GLType> 250 struct GLToCType 251 {}; 252 253 template <> 254 struct GLToCType<GL_BYTE> 255 { 256 typedef GLbyte type; 257 }; 258 template <> 259 struct GLToCType<GL_UNSIGNED_BYTE> 260 { 261 typedef GLubyte type; 262 }; 263 template <> 264 struct GLToCType<GL_SHORT> 265 { 266 typedef GLshort type; 267 }; 268 template <> 269 struct GLToCType<GL_UNSIGNED_SHORT> 270 { 271 typedef GLushort type; 272 }; 273 template <> 274 struct GLToCType<GL_FIXED> 275 { 276 typedef GLuint type; 277 }; 278 template <> 279 struct GLToCType<GL_FLOAT> 280 { 281 typedef GLfloat type; 282 }; 283 284 // This differs from D3DDECLTYPE in that it is unsized. (Size expansion is applied last.) 285 enum D3DVertexType 286 { 287 D3DVT_FLOAT, 288 D3DVT_SHORT, 289 D3DVT_SHORT_NORM, 290 D3DVT_UBYTE, 291 D3DVT_UBYTE_NORM, 292 D3DVT_USHORT_NORM 293 }; 294 295 // D3DToCType maps from D3D vertex type (as enum D3DVertexType) to the corresponding C type. 296 template <unsigned int D3DType> 297 struct D3DToCType 298 {}; 299 300 template <> 301 struct D3DToCType<D3DVT_FLOAT> 302 { 303 typedef float type; 304 }; 305 template <> 306 struct D3DToCType<D3DVT_SHORT> 307 { 308 typedef short type; 309 }; 310 template <> 311 struct D3DToCType<D3DVT_SHORT_NORM> 312 { 313 typedef short type; 314 }; 315 template <> 316 struct D3DToCType<D3DVT_UBYTE> 317 { 318 typedef unsigned char type; 319 }; 320 template <> 321 struct D3DToCType<D3DVT_UBYTE_NORM> 322 { 323 typedef unsigned char type; 324 }; 325 template <> 326 struct D3DToCType<D3DVT_USHORT_NORM> 327 { 328 typedef unsigned short type; 329 }; 330 331 // Encode the type/size combinations that D3D permits. For each type/size it expands to a widener 332 // that will provide the appropriate final size. 333 template <unsigned int type, int size> 334 struct WidenRule 335 {}; 336 337 template <int size> 338 struct WidenRule<D3DVT_FLOAT, size> : NoWiden<size> 339 {}; 340 template <int size> 341 struct WidenRule<D3DVT_SHORT, size> : WidenToEven<size> 342 {}; 343 template <int size> 344 struct WidenRule<D3DVT_SHORT_NORM, size> : WidenToEven<size> 345 {}; 346 template <int size> 347 struct WidenRule<D3DVT_UBYTE, size> : WidenToFour<size> 348 {}; 349 template <int size> 350 struct WidenRule<D3DVT_UBYTE_NORM, size> : WidenToFour<size> 351 {}; 352 template <int size> 353 struct WidenRule<D3DVT_USHORT_NORM, size> : WidenToEven<size> 354 {}; 355 356 // VertexTypeFlags encodes the D3DCAPS9::DeclType flag and vertex declaration flag for each D3D 357 // vertex type & size combination. 358 template <unsigned int d3dtype, int size> 359 struct VertexTypeFlags 360 {}; 361 362 template <unsigned int _capflag, unsigned int _declflag> 363 struct VertexTypeFlagsHelper 364 { 365 enum 366 { 367 capflag = _capflag 368 }; 369 enum 370 { 371 declflag = _declflag 372 }; 373 }; 374 375 template <> 376 struct VertexTypeFlags<D3DVT_FLOAT, 1> : VertexTypeFlagsHelper<0, D3DDECLTYPE_FLOAT1> 377 {}; 378 template <> 379 struct VertexTypeFlags<D3DVT_FLOAT, 2> : VertexTypeFlagsHelper<0, D3DDECLTYPE_FLOAT2> 380 {}; 381 template <> 382 struct VertexTypeFlags<D3DVT_FLOAT, 3> : VertexTypeFlagsHelper<0, D3DDECLTYPE_FLOAT3> 383 {}; 384 template <> 385 struct VertexTypeFlags<D3DVT_FLOAT, 4> : VertexTypeFlagsHelper<0, D3DDECLTYPE_FLOAT4> 386 {}; 387 template <> 388 struct VertexTypeFlags<D3DVT_SHORT, 2> : VertexTypeFlagsHelper<0, D3DDECLTYPE_SHORT2> 389 {}; 390 template <> 391 struct VertexTypeFlags<D3DVT_SHORT, 4> : VertexTypeFlagsHelper<0, D3DDECLTYPE_SHORT4> 392 {}; 393 template <> 394 struct VertexTypeFlags<D3DVT_SHORT_NORM, 2> 395 : VertexTypeFlagsHelper<D3DDTCAPS_SHORT2N, D3DDECLTYPE_SHORT2N> 396 {}; 397 template <> 398 struct VertexTypeFlags<D3DVT_SHORT_NORM, 4> 399 : VertexTypeFlagsHelper<D3DDTCAPS_SHORT4N, D3DDECLTYPE_SHORT4N> 400 {}; 401 template <> 402 struct VertexTypeFlags<D3DVT_UBYTE, 4> : VertexTypeFlagsHelper<D3DDTCAPS_UBYTE4, D3DDECLTYPE_UBYTE4> 403 {}; 404 template <> 405 struct VertexTypeFlags<D3DVT_UBYTE_NORM, 4> 406 : VertexTypeFlagsHelper<D3DDTCAPS_UBYTE4N, D3DDECLTYPE_UBYTE4N> 407 {}; 408 template <> 409 struct VertexTypeFlags<D3DVT_USHORT_NORM, 2> 410 : VertexTypeFlagsHelper<D3DDTCAPS_USHORT2N, D3DDECLTYPE_USHORT2N> 411 {}; 412 template <> 413 struct VertexTypeFlags<D3DVT_USHORT_NORM, 4> 414 : VertexTypeFlagsHelper<D3DDTCAPS_USHORT4N, D3DDECLTYPE_USHORT4N> 415 {}; 416 417 // VertexTypeMapping maps GL type & normalized flag to preferred and fallback D3D vertex types (as 418 // D3DVertexType enums). 419 template <GLenum GLtype, bool normalized> 420 struct VertexTypeMapping 421 {}; 422 423 template <D3DVertexType Preferred, D3DVertexType Fallback = Preferred> 424 struct VertexTypeMappingBase 425 { 426 enum 427 { 428 preferred = Preferred 429 }; 430 enum 431 { 432 fallback = Fallback 433 }; 434 }; 435 436 template <> 437 struct VertexTypeMapping<GL_BYTE, false> : VertexTypeMappingBase<D3DVT_SHORT> 438 {}; // Cast 439 template <> 440 struct VertexTypeMapping<GL_BYTE, true> : VertexTypeMappingBase<D3DVT_FLOAT> 441 {}; // Normalize 442 template <> 443 struct VertexTypeMapping<GL_UNSIGNED_BYTE, false> : VertexTypeMappingBase<D3DVT_UBYTE, D3DVT_FLOAT> 444 {}; // Identity, Cast 445 template <> 446 struct VertexTypeMapping<GL_UNSIGNED_BYTE, true> 447 : VertexTypeMappingBase<D3DVT_UBYTE_NORM, D3DVT_FLOAT> 448 {}; // Identity, Normalize 449 template <> 450 struct VertexTypeMapping<GL_SHORT, false> : VertexTypeMappingBase<D3DVT_SHORT> 451 {}; // Identity 452 template <> 453 struct VertexTypeMapping<GL_SHORT, true> : VertexTypeMappingBase<D3DVT_SHORT_NORM, D3DVT_FLOAT> 454 {}; // Cast, Normalize 455 template <> 456 struct VertexTypeMapping<GL_UNSIGNED_SHORT, false> : VertexTypeMappingBase<D3DVT_FLOAT> 457 {}; // Cast 458 template <> 459 struct VertexTypeMapping<GL_UNSIGNED_SHORT, true> 460 : VertexTypeMappingBase<D3DVT_USHORT_NORM, D3DVT_FLOAT> 461 {}; // Cast, Normalize 462 template <bool normalized> 463 struct VertexTypeMapping<GL_FIXED, normalized> : VertexTypeMappingBase<D3DVT_FLOAT> 464 {}; // FixedToFloat 465 template <bool normalized> 466 struct VertexTypeMapping<GL_FLOAT, normalized> : VertexTypeMappingBase<D3DVT_FLOAT> 467 {}; // Identity 468 469 // Given a GL type & norm flag and a D3D type, ConversionRule provides the type conversion rule 470 // (Cast, Normalize, Identity, FixedToFloat). The conversion rules themselves are defined in 471 // vertexconversion.h. 472 473 // Almost all cases are covered by Cast (including those that are actually Identity since Cast<T,T> 474 // knows it's an identity mapping). 475 template <GLenum fromType, bool normalized, unsigned int toType> 476 struct ConversionRule : Cast<typename GLToCType<fromType>::type, typename D3DToCType<toType>::type> 477 {}; 478 479 // All conversions from normalized types to float use the Normalize operator. 480 template <GLenum fromType> 481 struct ConversionRule<fromType, true, D3DVT_FLOAT> : Normalize<typename GLToCType<fromType>::type> 482 {}; 483 484 // Use a full specialization for this so that it preferentially matches ahead of the generic 485 // normalize-to-float rules. 486 template <> 487 struct ConversionRule<GL_FIXED, true, D3DVT_FLOAT> : FixedToFloat<GLint, 16> 488 {}; 489 template <> 490 struct ConversionRule<GL_FIXED, false, D3DVT_FLOAT> : FixedToFloat<GLint, 16> 491 {}; 492 493 // A 2-stage construction is used for DefaultVertexValues because float must use SimpleDefaultValues 494 // (i.e. 0/1) whether it is normalized or not. 495 template <class T, bool normalized> 496 struct DefaultVertexValuesStage2 497 {}; 498 499 template <class T> 500 struct DefaultVertexValuesStage2<T, true> : NormalizedDefaultValues<T> 501 {}; 502 template <class T> 503 struct DefaultVertexValuesStage2<T, false> : SimpleDefaultValues<T> 504 {}; 505 506 // Work out the default value rule for a D3D type (expressed as the C type) and 507 template <class T, bool normalized> 508 struct DefaultVertexValues : DefaultVertexValuesStage2<T, normalized> 509 {}; 510 template <bool normalized> 511 struct DefaultVertexValues<float, normalized> : SimpleDefaultValues<float> 512 {}; 513 514 // Policy rules for use with Converter, to choose whether to use the preferred or fallback 515 // conversion. The fallback conversion produces an output that all D3D9 devices must support. 516 template <class T> 517 struct UsePreferred 518 { 519 enum 520 { 521 type = T::preferred 522 }; 523 }; 524 template <class T> 525 struct UseFallback 526 { 527 enum 528 { 529 type = T::fallback 530 }; 531 }; 532 533 // Converter ties it all together. Given an OpenGL type/norm/size and choice of preferred/fallback 534 // conversion, it provides all the members of the appropriate VertexDataConverter, the 535 // D3DCAPS9::DeclTypes flag in cap flag and the D3DDECLTYPE member needed for the vertex declaration 536 // in declflag. 537 template <GLenum fromType, bool normalized, int size, template <class T> class PreferenceRule> 538 struct Converter 539 : VertexDataConverter< 540 typename GLToCType<fromType>::type, 541 WidenRule<PreferenceRule<VertexTypeMapping<fromType, normalized>>::type, size>, 542 ConversionRule<fromType, 543 normalized, 544 PreferenceRule<VertexTypeMapping<fromType, normalized>>::type>, 545 DefaultVertexValues<typename D3DToCType<PreferenceRule< 546 VertexTypeMapping<fromType, normalized>>::type>::type, 547 normalized>> 548 { 549 private: 550 enum 551 { 552 d3dtype = PreferenceRule<VertexTypeMapping<fromType, normalized>>::type 553 }; 554 enum 555 { 556 d3dsize = WidenRule<d3dtype, size>::finalWidth 557 }; 558 559 public: 560 enum 561 { 562 capflag = VertexTypeFlags<d3dtype, d3dsize>::capflag 563 }; 564 enum 565 { 566 declflag = VertexTypeFlags<d3dtype, d3dsize>::declflag 567 }; 568 }; 569 570 VertexFormat::VertexFormat() 571 : conversionType(VERTEX_CONVERT_NONE), 572 outputElementSize(0), 573 copyFunction(nullptr), 574 nativeFormat(D3DDECLTYPE_UNUSED), 575 componentType(GL_NONE) 576 {} 577 578 // Initialize a TranslationInfo 579 VertexFormat CreateVertexFormatInfo(bool identity, 580 size_t elementSize, 581 VertexCopyFunction copyFunc, 582 D3DDECLTYPE nativeFormat) 583 { 584 VertexFormat formatInfo; 585 formatInfo.conversionType = identity ? VERTEX_CONVERT_NONE : VERTEX_CONVERT_CPU; 586 formatInfo.outputElementSize = elementSize; 587 formatInfo.copyFunction = copyFunc; 588 formatInfo.nativeFormat = nativeFormat; 589 formatInfo.componentType = GetDeclTypeComponentType(nativeFormat); 590 return formatInfo; 591 } 592 593 #define TRANSLATION(type, norm, size, preferred) \ 594 CreateVertexFormatInfo( \ 595 Converter<type, norm, size, preferred>::identity, \ 596 Converter<type, norm, size, preferred>::finalSize, \ 597 Converter<type, norm, size, preferred>::convertArray, \ 598 static_cast<D3DDECLTYPE>(Converter<type, norm, size, preferred>::declflag)) 599 600 #define TRANSLATION_FOR_TYPE_NORM_SIZE(type, norm, size) \ 601 { \ 602 Converter<type, norm, size, UsePreferred>::capflag, \ 603 TRANSLATION(type, norm, size, UsePreferred), \ 604 TRANSLATION(type, norm, size, UseFallback) \ 605 } 606 607 #define TRANSLATIONS_FOR_TYPE(type) \ 608 { \ 609 {TRANSLATION_FOR_TYPE_NORM_SIZE(type, false, 1), \ 610 TRANSLATION_FOR_TYPE_NORM_SIZE(type, false, 2), \ 611 TRANSLATION_FOR_TYPE_NORM_SIZE(type, false, 3), \ 612 TRANSLATION_FOR_TYPE_NORM_SIZE(type, false, 4)}, \ 613 {TRANSLATION_FOR_TYPE_NORM_SIZE(type, true, 1), \ 614 TRANSLATION_FOR_TYPE_NORM_SIZE(type, true, 2), \ 615 TRANSLATION_FOR_TYPE_NORM_SIZE(type, true, 3), \ 616 TRANSLATION_FOR_TYPE_NORM_SIZE(type, true, 4)}, \ 617 } 618 619 #define TRANSLATIONS_FOR_TYPE_NO_NORM(type) \ 620 { \ 621 {TRANSLATION_FOR_TYPE_NORM_SIZE(type, false, 1), \ 622 TRANSLATION_FOR_TYPE_NORM_SIZE(type, false, 2), \ 623 TRANSLATION_FOR_TYPE_NORM_SIZE(type, false, 3), \ 624 TRANSLATION_FOR_TYPE_NORM_SIZE(type, false, 4)}, \ 625 {TRANSLATION_FOR_TYPE_NORM_SIZE(type, false, 1), \ 626 TRANSLATION_FOR_TYPE_NORM_SIZE(type, false, 2), \ 627 TRANSLATION_FOR_TYPE_NORM_SIZE(type, false, 3), \ 628 TRANSLATION_FOR_TYPE_NORM_SIZE(type, false, 4)}, \ 629 } 630 631 static inline unsigned int ComputeTypeIndex(GLenum type) 632 { 633 switch (type) 634 { 635 case GL_BYTE: 636 return 0; 637 case GL_UNSIGNED_BYTE: 638 return 1; 639 case GL_SHORT: 640 return 2; 641 case GL_UNSIGNED_SHORT: 642 return 3; 643 case GL_FIXED: 644 return 4; 645 case GL_FLOAT: 646 return 5; 647 648 default: 649 UNREACHABLE(); 650 return 5; 651 } 652 } 653 654 const VertexFormat &GetVertexFormatInfo(DWORD supportedDeclTypes, angle::FormatID vertexFormatID) 655 { 656 static DWORD initializedDeclTypes = 0; 657 static VertexFormat formatConverters[NUM_GL_VERTEX_ATTRIB_TYPES][2][4]; 658 if (initializedDeclTypes != supportedDeclTypes) 659 { 660 const TranslationDescription 661 translations[NUM_GL_VERTEX_ATTRIB_TYPES][2] 662 [4] = // [GL types as enumerated by typeIndex()][normalized][size-1] 663 {TRANSLATIONS_FOR_TYPE(GL_BYTE), TRANSLATIONS_FOR_TYPE(GL_UNSIGNED_BYTE), 664 TRANSLATIONS_FOR_TYPE(GL_SHORT), TRANSLATIONS_FOR_TYPE(GL_UNSIGNED_SHORT), 665 TRANSLATIONS_FOR_TYPE_NO_NORM(GL_FIXED), TRANSLATIONS_FOR_TYPE_NO_NORM(GL_FLOAT)}; 666 for (unsigned int i = 0; i < NUM_GL_VERTEX_ATTRIB_TYPES; i++) 667 { 668 for (unsigned int j = 0; j < 2; j++) 669 { 670 for (unsigned int k = 0; k < 4; k++) 671 { 672 if (translations[i][j][k].capsFlag == 0 || 673 (supportedDeclTypes & translations[i][j][k].capsFlag) != 0) 674 { 675 formatConverters[i][j][k] = translations[i][j][k].preferredConversion; 676 } 677 else 678 { 679 formatConverters[i][j][k] = translations[i][j][k].fallbackConversion; 680 } 681 } 682 } 683 } 684 initializedDeclTypes = supportedDeclTypes; 685 } 686 687 const gl::VertexFormat &vertexFormat = gl::GetVertexFormatFromID(vertexFormatID); 688 689 // Pure integer attributes only supported in ES3.0 690 ASSERT(!vertexFormat.pureInteger); 691 return formatConverters[ComputeTypeIndex(vertexFormat.type)][vertexFormat.normalized] 692 [vertexFormat.components - 1]; 693 } 694 } // namespace d3d9 695 } // namespace rx