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