Home | History | Annotate | Download | only in d3d9
      1 #include "precompiled.h"
      2 //
      3 // Copyright (c) 2013 The ANGLE Project Authors. All rights reserved.
      4 // Use of this source code is governed by a BSD-style license that can be
      5 // found in the LICENSE file.
      6 //
      7 
      8 // formatutils9.cpp: Queries for GL image formats and their translations to D3D9
      9 // formats.
     10 
     11 #include "libGLESv2/renderer/d3d9/formatutils9.h"
     12 #include "libGLESv2/renderer/d3d9/Renderer9.h"
     13 #include "libGLESv2/renderer/generatemip.h"
     14 #include "libGLESv2/renderer/loadimage.h"
     15 #include "libGLESv2/renderer/copyimage.h"
     16 #include "libGLESv2/renderer/vertexconversion.h"
     17 
     18 namespace rx
     19 {
     20 
     21 // Each GL internal format corresponds to one D3D format and data loading function.
     22 // Due to not all formats being available all the time, some of the function/format types are wrapped
     23 // in templates that perform format support queries on a Renderer9 object which is supplied
     24 // when requesting the function or format.
     25 
     26 typedef bool ((Renderer9::*Renderer9FormatCheckFunction)(void) const);
     27 typedef LoadImageFunction (*RendererCheckLoadFunction)(const Renderer9 *renderer);
     28 
     29 template <Renderer9FormatCheckFunction pred, LoadImageFunction prefered, LoadImageFunction fallback>
     30 LoadImageFunction RendererCheckLoad(const Renderer9 *renderer)
     31 {
     32     return ((renderer->*pred)()) ? prefered : fallback;
     33 }
     34 
     35 template <LoadImageFunction loadFunc>
     36 LoadImageFunction SimpleLoad(const Renderer9 *renderer)
     37 {
     38     return loadFunc;
     39 }
     40 
     41 LoadImageFunction UnreachableLoad(const Renderer9 *renderer)
     42 {
     43     UNREACHABLE();
     44     return NULL;
     45 }
     46 
     47 typedef bool (*FallbackPredicateFunction)(void);
     48 
     49 template <FallbackPredicateFunction pred, LoadImageFunction prefered, LoadImageFunction fallback>
     50 LoadImageFunction FallbackLoadFunction(const Renderer9 *renderer)
     51 {
     52     return pred() ? prefered : fallback;
     53 }
     54 
     55 typedef D3DFORMAT (*FormatQueryFunction)(const rx::Renderer9 *renderer);
     56 
     57 template <Renderer9FormatCheckFunction pred, D3DFORMAT prefered, D3DFORMAT fallback>
     58 D3DFORMAT CheckFormatSupport(const rx::Renderer9 *renderer)
     59 {
     60     return (renderer->*pred)() ? prefered : fallback;
     61 }
     62 
     63 template <D3DFORMAT format>
     64 D3DFORMAT D3D9Format(const rx::Renderer9 *renderer)
     65 {
     66     return format;
     67 }
     68 
     69 struct D3D9FormatInfo
     70 {
     71     FormatQueryFunction mTexFormat;
     72     FormatQueryFunction mRenderFormat;
     73     RendererCheckLoadFunction mLoadFunction;
     74 
     75     D3D9FormatInfo()
     76         : mTexFormat(NULL), mRenderFormat(NULL), mLoadFunction(NULL)
     77     { }
     78 
     79     D3D9FormatInfo(FormatQueryFunction textureFormat, FormatQueryFunction renderFormat, RendererCheckLoadFunction loadFunc)
     80         : mTexFormat(textureFormat), mRenderFormat(renderFormat), mLoadFunction(loadFunc)
     81     { }
     82 };
     83 
     84 const D3DFORMAT D3DFMT_INTZ = ((D3DFORMAT)(MAKEFOURCC('I','N','T','Z')));
     85 const D3DFORMAT D3DFMT_NULL = ((D3DFORMAT)(MAKEFOURCC('N','U','L','L')));
     86 
     87 typedef std::pair<GLenum, D3D9FormatInfo> D3D9FormatPair;
     88 typedef std::map<GLenum, D3D9FormatInfo> D3D9FormatMap;
     89 
     90 static D3D9FormatMap BuildD3D9FormatMap()
     91 {
     92     D3D9FormatMap map;
     93 
     94     //                       | Internal format                                   | Texture format                  | Render format                    | Load function                                   |
     95     map.insert(D3D9FormatPair(GL_NONE,                             D3D9FormatInfo(D3D9Format<D3DFMT_NULL>,          D3D9Format<D3DFMT_NULL>,           UnreachableLoad                                  )));
     96 
     97     map.insert(D3D9FormatPair(GL_DEPTH_COMPONENT16,                D3D9FormatInfo(D3D9Format<D3DFMT_INTZ>,          D3D9Format<D3DFMT_D24S8>,          UnreachableLoad                                  )));
     98     map.insert(D3D9FormatPair(GL_DEPTH_COMPONENT32_OES,            D3D9FormatInfo(D3D9Format<D3DFMT_INTZ>,          D3D9Format<D3DFMT_D32>,            UnreachableLoad                                  )));
     99     map.insert(D3D9FormatPair(GL_DEPTH24_STENCIL8_OES,             D3D9FormatInfo(D3D9Format<D3DFMT_INTZ>,          D3D9Format<D3DFMT_D24S8>,          UnreachableLoad                                  )));
    100     map.insert(D3D9FormatPair(GL_STENCIL_INDEX8,                   D3D9FormatInfo(D3D9Format<D3DFMT_UNKNOWN>,       D3D9Format<D3DFMT_D24S8>,          UnreachableLoad                                  ))); // TODO: What's the texture format?
    101 
    102     map.insert(D3D9FormatPair(GL_RGBA32F_EXT,                      D3D9FormatInfo(D3D9Format<D3DFMT_A32B32G32R32F>, D3D9Format<D3DFMT_A32B32G32R32F>,  SimpleLoad<loadToNative<GLfloat, 4> >            )));
    103     map.insert(D3D9FormatPair(GL_RGB32F_EXT,                       D3D9FormatInfo(D3D9Format<D3DFMT_A32B32G32R32F>, D3D9Format<D3DFMT_A32B32G32R32F>,  SimpleLoad<loadToNative3To4<GLfloat, gl::Float32One> >)));
    104     map.insert(D3D9FormatPair(GL_RG32F_EXT,                        D3D9FormatInfo(D3D9Format<D3DFMT_G32R32F>,       D3D9Format<D3DFMT_G32R32F>,        SimpleLoad<loadToNative<GLfloat, 2> >            )));
    105     map.insert(D3D9FormatPair(GL_R32F_EXT,                         D3D9FormatInfo(D3D9Format<D3DFMT_R32F>,          D3D9Format<D3DFMT_R32F>,           SimpleLoad<loadToNative<GLfloat, 1> >            )));
    106     map.insert(D3D9FormatPair(GL_ALPHA32F_EXT,                     D3D9FormatInfo(D3D9Format<D3DFMT_A32B32G32R32F>, D3D9Format<D3DFMT_UNKNOWN>,        SimpleLoad<loadAlphaFloatDataToRGBA>             )));
    107     map.insert(D3D9FormatPair(GL_LUMINANCE32F_EXT,                 D3D9FormatInfo(D3D9Format<D3DFMT_A32B32G32R32F>, D3D9Format<D3DFMT_UNKNOWN>,        SimpleLoad<loadLuminanceFloatDataToRGBA>         )));
    108     map.insert(D3D9FormatPair(GL_LUMINANCE_ALPHA32F_EXT,           D3D9FormatInfo(D3D9Format<D3DFMT_A32B32G32R32F>, D3D9Format<D3DFMT_UNKNOWN>,        SimpleLoad<loadLuminanceAlphaFloatDataToRGBA>    )));
    109 
    110     map.insert(D3D9FormatPair(GL_RGBA16F_EXT,                      D3D9FormatInfo(D3D9Format<D3DFMT_A16B16G16R16F>, D3D9Format<D3DFMT_A16B16G16R16F>,  SimpleLoad<loadToNative<GLhalf, 4> >             )));
    111     map.insert(D3D9FormatPair(GL_RGB16F_EXT,                       D3D9FormatInfo(D3D9Format<D3DFMT_A16B16G16R16F>, D3D9Format<D3DFMT_A16B16G16R16F>,  SimpleLoad<loadToNative3To4<GLhalf, gl::Float16One> >)));
    112     map.insert(D3D9FormatPair(GL_RG16F_EXT,                        D3D9FormatInfo(D3D9Format<D3DFMT_G16R16F>,       D3D9Format<D3DFMT_G16R16F>,        SimpleLoad<loadToNative<GLhalf, 2> >             )));
    113     map.insert(D3D9FormatPair(GL_R16F_EXT,                         D3D9FormatInfo(D3D9Format<D3DFMT_R16F>,          D3D9Format<D3DFMT_R16F>,           SimpleLoad<loadToNative<GLhalf, 1> >             )));
    114     map.insert(D3D9FormatPair(GL_ALPHA16F_EXT,                     D3D9FormatInfo(D3D9Format<D3DFMT_A16B16G16R16F>, D3D9Format<D3DFMT_UNKNOWN>,        SimpleLoad<loadAlphaHalfFloatDataToRGBA>         )));
    115     map.insert(D3D9FormatPair(GL_LUMINANCE16F_EXT,                 D3D9FormatInfo(D3D9Format<D3DFMT_A16B16G16R16F>, D3D9Format<D3DFMT_UNKNOWN>,        SimpleLoad<loadLuminanceHalfFloatDataToRGBA>     )));
    116     map.insert(D3D9FormatPair(GL_LUMINANCE_ALPHA16F_EXT,           D3D9FormatInfo(D3D9Format<D3DFMT_A16B16G16R16F>, D3D9Format<D3DFMT_UNKNOWN>,        SimpleLoad<loadLuminanceAlphaHalfFloatDataToRGBA>)));
    117 
    118     map.insert(D3D9FormatPair(GL_ALPHA8_EXT,                       D3D9FormatInfo(D3D9Format<D3DFMT_A8R8G8B8>,      D3D9Format<D3DFMT_A8R8G8B8>,       FallbackLoadFunction<gl::supportsSSE2, loadAlphaDataToBGRASSE2, loadAlphaDataToBGRA>)));
    119 
    120     map.insert(D3D9FormatPair(GL_RGB8_OES,                         D3D9FormatInfo(D3D9Format<D3DFMT_X8R8G8B8>,      D3D9Format<D3DFMT_X8R8G8B8>,       SimpleLoad<loadRGBUByteDataToBGRX>                )));
    121     map.insert(D3D9FormatPair(GL_RGB565,                           D3D9FormatInfo(CheckFormatSupport<&Renderer9::getRGB565TextureSupport, D3DFMT_R5G6B5, D3DFMT_X8R8G8B8>, CheckFormatSupport<&Renderer9::getRGB565TextureSupport, D3DFMT_R5G6B5, D3DFMT_X8R8G8B8>, RendererCheckLoad<&Renderer9::getRGB565TextureSupport, loadToNative<GLushort, 1>, loadRGB565DataToBGRA>)));
    122     map.insert(D3D9FormatPair(GL_RGBA8_OES,                        D3D9FormatInfo(D3D9Format<D3DFMT_A8R8G8B8>,      D3D9Format<D3DFMT_A8R8G8B8>,       FallbackLoadFunction<gl::supportsSSE2, loadRGBAUByteDataToBGRASSE2, loadRGBAUByteDataToBGRA>)));
    123     map.insert(D3D9FormatPair(GL_RGBA4,                            D3D9FormatInfo(D3D9Format<D3DFMT_A8R8G8B8>,      D3D9Format<D3DFMT_A8R8G8B8>,       SimpleLoad<loadRGBA4444DataToBGRA>                )));
    124     map.insert(D3D9FormatPair(GL_RGB5_A1,                          D3D9FormatInfo(D3D9Format<D3DFMT_A8R8G8B8>,      D3D9Format<D3DFMT_A8R8G8B8>,       SimpleLoad<loadRGBA5551DataToBGRA>                )));
    125     map.insert(D3D9FormatPair(GL_R8_EXT,                           D3D9FormatInfo(D3D9Format<D3DFMT_X8R8G8B8>,      D3D9Format<D3DFMT_X8R8G8B8>,       SimpleLoad<loadRUByteDataToBGRX>                  )));
    126     map.insert(D3D9FormatPair(GL_RG8_EXT,                          D3D9FormatInfo(D3D9Format<D3DFMT_X8R8G8B8>,      D3D9Format<D3DFMT_X8R8G8B8>,       SimpleLoad<loadRGUByteDataToBGRX>                 )));
    127 
    128     map.insert(D3D9FormatPair(GL_BGRA8_EXT,                        D3D9FormatInfo(D3D9Format<D3DFMT_A8R8G8B8>,      D3D9Format<D3DFMT_A8R8G8B8>,       SimpleLoad<loadToNative<GLubyte, 4> >             )));
    129     map.insert(D3D9FormatPair(GL_BGRA4_ANGLEX,                     D3D9FormatInfo(D3D9Format<D3DFMT_A8R8G8B8>,      D3D9Format<D3DFMT_A8R8G8B8>,       SimpleLoad<loadRGBA4444DataToRGBA>                )));
    130     map.insert(D3D9FormatPair(GL_BGR5_A1_ANGLEX,                   D3D9FormatInfo(D3D9Format<D3DFMT_A8R8G8B8>,      D3D9Format<D3DFMT_A8R8G8B8>,       SimpleLoad<loadRGBA5551DataToRGBA>                )));
    131 
    132     map.insert(D3D9FormatPair(GL_COMPRESSED_RGB_S3TC_DXT1_EXT,     D3D9FormatInfo(D3D9Format<D3DFMT_DXT1>,          D3D9Format<D3DFMT_UNKNOWN>,        SimpleLoad<loadCompressedBlockDataToNative<4, 4,  8> >)));
    133     map.insert(D3D9FormatPair(GL_COMPRESSED_RGBA_S3TC_DXT1_EXT,    D3D9FormatInfo(D3D9Format<D3DFMT_DXT1>,          D3D9Format<D3DFMT_UNKNOWN>,        SimpleLoad<loadCompressedBlockDataToNative<4, 4,  8> >)));
    134     map.insert(D3D9FormatPair(GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE,  D3D9FormatInfo(D3D9Format<D3DFMT_DXT3>,          D3D9Format<D3DFMT_UNKNOWN>,        SimpleLoad<loadCompressedBlockDataToNative<4, 4, 16> >)));
    135     map.insert(D3D9FormatPair(GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE,  D3D9FormatInfo(D3D9Format<D3DFMT_DXT5>,          D3D9Format<D3DFMT_UNKNOWN>,        SimpleLoad<loadCompressedBlockDataToNative<4, 4, 16> >)));
    136 
    137     // These formats require checking if the renderer supports D3DFMT_L8 or D3DFMT_A8L8 and
    138     // then changing the format and loading function appropriately.
    139     map.insert(D3D9FormatPair(GL_LUMINANCE8_EXT,                   D3D9FormatInfo(CheckFormatSupport<&Renderer9::getLuminanceTextureSupport, D3DFMT_L8, D3DFMT_A8R8G8B8>,        D3D9Format<D3DFMT_UNKNOWN>,  RendererCheckLoad<&Renderer9::getLuminanceTextureSupport, loadToNative<GLubyte, 1>, loadLuminanceDataToBGRA>)));
    140     map.insert(D3D9FormatPair(GL_LUMINANCE8_ALPHA8_EXT,            D3D9FormatInfo(CheckFormatSupport<&Renderer9::getLuminanceAlphaTextureSupport, D3DFMT_A8L8, D3DFMT_A8R8G8B8>, D3D9Format<D3DFMT_UNKNOWN>,  RendererCheckLoad<&Renderer9::getLuminanceTextureSupport, loadToNative<GLubyte, 2>, loadLuminanceAlphaDataToBGRA>)));
    141 
    142     return map;
    143 }
    144 
    145 static bool GetD3D9FormatInfo(GLenum internalFormat, D3D9FormatInfo *outFormatInfo)
    146 {
    147     static const D3D9FormatMap formatMap = BuildD3D9FormatMap();
    148     D3D9FormatMap::const_iterator iter = formatMap.find(internalFormat);
    149     if (iter != formatMap.end())
    150     {
    151         if (outFormatInfo)
    152         {
    153             *outFormatInfo = iter->second;
    154         }
    155         return true;
    156     }
    157     else
    158     {
    159         return false;
    160     }
    161 }
    162 
    163 // A map to determine the pixel size and mip generation function of a given D3D format
    164 struct D3DFormatInfo
    165 {
    166     GLuint mPixelBits;
    167     GLuint mBlockWidth;
    168     GLuint mBlockHeight;
    169     GLenum mInternalFormat;
    170 
    171     MipGenerationFunction mMipGenerationFunction;
    172     ColorReadFunction mColorReadFunction;
    173 
    174     D3DFormatInfo()
    175         : mPixelBits(0), mBlockWidth(0), mBlockHeight(0), mInternalFormat(GL_NONE), mMipGenerationFunction(NULL),
    176           mColorReadFunction(NULL)
    177     { }
    178 
    179     D3DFormatInfo(GLuint pixelBits, GLuint blockWidth, GLuint blockHeight, GLenum internalFormat,
    180                   MipGenerationFunction mipFunc, ColorReadFunction readFunc)
    181         : mPixelBits(pixelBits), mBlockWidth(blockWidth), mBlockHeight(blockHeight), mInternalFormat(internalFormat),
    182           mMipGenerationFunction(mipFunc), mColorReadFunction(readFunc)
    183     { }
    184 };
    185 
    186 typedef std::pair<D3DFORMAT, D3DFormatInfo> D3D9FormatInfoPair;
    187 typedef std::map<D3DFORMAT, D3DFormatInfo> D3D9FormatInfoMap;
    188 
    189 static D3D9FormatInfoMap BuildD3D9FormatInfoMap()
    190 {
    191     D3D9FormatInfoMap map;
    192 
    193     //                           | D3DFORMAT           |             | S  |W |H | Internal format                   | Mip generation function   | Color read function             |
    194     map.insert(D3D9FormatInfoPair(D3DFMT_NULL,          D3DFormatInfo(  0, 0, 0, GL_NONE,                            NULL,                       NULL                             )));
    195     map.insert(D3D9FormatInfoPair(D3DFMT_UNKNOWN,       D3DFormatInfo(  0, 0, 0, GL_NONE,                            NULL,                       NULL                             )));
    196 
    197     map.insert(D3D9FormatInfoPair(D3DFMT_L8,            D3DFormatInfo(  8, 1, 1, GL_LUMINANCE8_EXT,                  GenerateMip<L8>,            ReadColor<L8, GLfloat>           )));
    198     map.insert(D3D9FormatInfoPair(D3DFMT_A8,            D3DFormatInfo(  8, 1, 1, GL_ALPHA8_EXT,                      GenerateMip<A8>,            ReadColor<A8, GLfloat>           )));
    199     map.insert(D3D9FormatInfoPair(D3DFMT_A8L8,          D3DFormatInfo( 16, 1, 1, GL_LUMINANCE8_ALPHA8_EXT,           GenerateMip<A8L8>,          ReadColor<A8L8, GLfloat>         )));
    200     map.insert(D3D9FormatInfoPair(D3DFMT_A4R4G4B4,      D3DFormatInfo( 16, 1, 1, GL_BGRA4_ANGLEX,                    GenerateMip<B4G4R4A4>,      ReadColor<B4G4R4A4, GLfloat>     )));
    201     map.insert(D3D9FormatInfoPair(D3DFMT_A1R5G5B5,      D3DFormatInfo( 16, 1, 1, GL_BGR5_A1_ANGLEX,                  GenerateMip<B5G5R5A1>,      ReadColor<B5G5R5A1, GLfloat>     )));
    202     map.insert(D3D9FormatInfoPair(D3DFMT_R5G6B5,        D3DFormatInfo( 16, 1, 1, GL_RGB565,                          GenerateMip<R5G6B5>,        ReadColor<R5G6B5, GLfloat>       )));
    203     map.insert(D3D9FormatInfoPair(D3DFMT_X8R8G8B8,      D3DFormatInfo( 32, 1, 1, GL_BGRA8_EXT,                       GenerateMip<B8G8R8X8>,      ReadColor<B8G8R8X8, GLfloat>     )));
    204     map.insert(D3D9FormatInfoPair(D3DFMT_A8R8G8B8,      D3DFormatInfo( 32, 1, 1, GL_BGRA8_EXT,                       GenerateMip<B8G8R8A8>,      ReadColor<B8G8R8A8, GLfloat>     )));
    205     map.insert(D3D9FormatInfoPair(D3DFMT_R16F,          D3DFormatInfo( 16, 1, 1, GL_R16F_EXT,                        GenerateMip<R16F>,          ReadColor<R16F, GLfloat>         )));
    206     map.insert(D3D9FormatInfoPair(D3DFMT_G16R16F,       D3DFormatInfo( 32, 1, 1, GL_RG16F_EXT,                       GenerateMip<R16G16F>,       ReadColor<R16G16F, GLfloat>      )));
    207     map.insert(D3D9FormatInfoPair(D3DFMT_A16B16G16R16F, D3DFormatInfo( 64, 1, 1, GL_RGBA16F_EXT,                     GenerateMip<R16G16B16A16F>, ReadColor<R16G16B16A16F, GLfloat>)));
    208     map.insert(D3D9FormatInfoPair(D3DFMT_R32F,          D3DFormatInfo( 32, 1, 1, GL_R32F_EXT,                        GenerateMip<R32F>,          ReadColor<R32F, GLfloat>         )));
    209     map.insert(D3D9FormatInfoPair(D3DFMT_G32R32F,       D3DFormatInfo( 64, 1, 1, GL_RG32F_EXT,                       GenerateMip<R32G32F>,       ReadColor<R32G32F, GLfloat>      )));
    210     map.insert(D3D9FormatInfoPair(D3DFMT_A32B32G32R32F, D3DFormatInfo(128, 1, 1, GL_RGBA32F_EXT,                     GenerateMip<R32G32B32A32F>, ReadColor<R32G32B32A32F, GLfloat>)));
    211 
    212     map.insert(D3D9FormatInfoPair(D3DFMT_D16,           D3DFormatInfo( 16, 1, 1, GL_DEPTH_COMPONENT16,               NULL,                       NULL                             )));
    213     map.insert(D3D9FormatInfoPair(D3DFMT_D24S8,         D3DFormatInfo( 32, 1, 1, GL_DEPTH24_STENCIL8_OES,            NULL,                       NULL                             )));
    214     map.insert(D3D9FormatInfoPair(D3DFMT_D24X8,         D3DFormatInfo( 32, 1, 1, GL_DEPTH_COMPONENT16,               NULL,                       NULL                             )));
    215     map.insert(D3D9FormatInfoPair(D3DFMT_D32,           D3DFormatInfo( 32, 1, 1, GL_DEPTH_COMPONENT32_OES,           NULL,                       NULL                             )));
    216 
    217     map.insert(D3D9FormatInfoPair(D3DFMT_INTZ,          D3DFormatInfo( 32, 1, 1, GL_DEPTH24_STENCIL8_OES,            NULL,                       NULL                             )));
    218 
    219     map.insert(D3D9FormatInfoPair(D3DFMT_DXT1,          D3DFormatInfo( 64, 4, 4, GL_COMPRESSED_RGBA_S3TC_DXT1_EXT,   NULL,                       NULL                             )));
    220     map.insert(D3D9FormatInfoPair(D3DFMT_DXT3,          D3DFormatInfo(128, 4, 4, GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE, NULL,                       NULL                             )));
    221     map.insert(D3D9FormatInfoPair(D3DFMT_DXT5,          D3DFormatInfo(128, 4, 4, GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE, NULL,                       NULL                             )));
    222 
    223     return map;
    224 }
    225 
    226 static const D3D9FormatInfoMap &GetD3D9FormatInfoMap()
    227 {
    228     static const D3D9FormatInfoMap infoMap = BuildD3D9FormatInfoMap();
    229     return infoMap;
    230 }
    231 
    232 static bool GetD3D9FormatInfo(D3DFORMAT format, D3DFormatInfo *outFormatInfo)
    233 {
    234     const D3D9FormatInfoMap &infoMap = GetD3D9FormatInfoMap();
    235     D3D9FormatInfoMap::const_iterator iter = infoMap.find(format);
    236     if (iter != infoMap.end())
    237     {
    238         if (outFormatInfo)
    239         {
    240             *outFormatInfo = iter->second;
    241         }
    242         return true;
    243     }
    244     else
    245     {
    246         return false;
    247     }
    248 }
    249 static d3d9::D3DFormatSet BuildAllD3DFormatSet()
    250 {
    251     d3d9::D3DFormatSet set;
    252 
    253     const D3D9FormatInfoMap &infoMap = GetD3D9FormatInfoMap();
    254     for (D3D9FormatInfoMap::const_iterator i = infoMap.begin(); i != infoMap.end(); ++i)
    255     {
    256         set.insert(i->first);
    257     }
    258 
    259     return set;
    260 }
    261 
    262 struct D3D9FastCopyFormat
    263 {
    264     D3DFORMAT mSourceFormat;
    265     GLenum mDestFormat;
    266     GLenum mDestType;
    267 
    268     D3D9FastCopyFormat(D3DFORMAT sourceFormat, GLenum destFormat, GLenum destType)
    269         : mSourceFormat(sourceFormat), mDestFormat(destFormat), mDestType(destType)
    270     { }
    271 
    272     bool operator<(const D3D9FastCopyFormat& other) const
    273     {
    274         return memcmp(this, &other, sizeof(D3D9FastCopyFormat)) < 0;
    275     }
    276 };
    277 
    278 typedef std::map<D3D9FastCopyFormat, ColorCopyFunction> D3D9FastCopyMap;
    279 typedef std::pair<D3D9FastCopyFormat, ColorCopyFunction> D3D9FastCopyPair;
    280 
    281 static D3D9FastCopyMap BuildFastCopyMap()
    282 {
    283     D3D9FastCopyMap map;
    284 
    285     map.insert(D3D9FastCopyPair(D3D9FastCopyFormat(D3DFMT_A8R8G8B8, GL_RGBA, GL_UNSIGNED_BYTE), CopyBGRAUByteToRGBAUByte));
    286 
    287     return map;
    288 }
    289 
    290 typedef std::pair<GLint, InitializeTextureDataFunction> InternalFormatInitialzerPair;
    291 typedef std::map<GLint, InitializeTextureDataFunction> InternalFormatInitialzerMap;
    292 
    293 static InternalFormatInitialzerMap BuildInternalFormatInitialzerMap()
    294 {
    295     InternalFormatInitialzerMap map;
    296 
    297     map.insert(InternalFormatInitialzerPair(GL_RGB16F,  initialize4ComponentData<GLhalf,   0x0000,     0x0000,     0x0000,     gl::Float16One>));
    298     map.insert(InternalFormatInitialzerPair(GL_RGB32F,  initialize4ComponentData<GLfloat,  0x00000000, 0x00000000, 0x00000000, gl::Float32One>));
    299 
    300     return map;
    301 }
    302 
    303 static const InternalFormatInitialzerMap &GetInternalFormatInitialzerMap()
    304 {
    305     static const InternalFormatInitialzerMap map = BuildInternalFormatInitialzerMap();
    306     return map;
    307 }
    308 
    309 namespace d3d9
    310 {
    311 
    312 MipGenerationFunction GetMipGenerationFunction(D3DFORMAT format)
    313 {
    314     D3DFormatInfo d3dFormatInfo;
    315     if (GetD3D9FormatInfo(format, &d3dFormatInfo))
    316     {
    317         return d3dFormatInfo.mMipGenerationFunction;
    318     }
    319     else
    320     {
    321         UNREACHABLE();
    322         return NULL;
    323     }
    324 }
    325 
    326 LoadImageFunction GetImageLoadFunction(GLenum internalFormat, const Renderer9 *renderer)
    327 {
    328     if (!renderer)
    329     {
    330         return NULL;
    331     }
    332 
    333     ASSERT(renderer->getCurrentClientVersion() == 2);
    334 
    335     D3D9FormatInfo d3d9FormatInfo;
    336     if (GetD3D9FormatInfo(internalFormat, &d3d9FormatInfo))
    337     {
    338         return d3d9FormatInfo.mLoadFunction(renderer);
    339     }
    340     else
    341     {
    342         UNREACHABLE();
    343         return NULL;
    344     }
    345 }
    346 
    347 GLuint GetFormatPixelBytes(D3DFORMAT format)
    348 {
    349     D3DFormatInfo d3dFormatInfo;
    350     if (GetD3D9FormatInfo(format, &d3dFormatInfo))
    351     {
    352         return d3dFormatInfo.mPixelBits / 8;
    353     }
    354     else
    355     {
    356         UNREACHABLE();
    357         return 0;
    358     }
    359 }
    360 
    361 GLuint GetBlockWidth(D3DFORMAT format)
    362 {
    363     D3DFormatInfo d3dFormatInfo;
    364     if (GetD3D9FormatInfo(format, &d3dFormatInfo))
    365     {
    366         return d3dFormatInfo.mBlockWidth;
    367     }
    368     else
    369     {
    370         UNREACHABLE();
    371         return 0;
    372     }
    373 }
    374 
    375 GLuint GetBlockHeight(D3DFORMAT format)
    376 {
    377     D3DFormatInfo d3dFormatInfo;
    378     if (GetD3D9FormatInfo(format, &d3dFormatInfo))
    379     {
    380         return d3dFormatInfo.mBlockHeight;
    381     }
    382     else
    383     {
    384         UNREACHABLE();
    385         return 0;
    386     }
    387 }
    388 
    389 GLuint GetBlockSize(D3DFORMAT format, GLuint width, GLuint height)
    390 {
    391     D3DFormatInfo d3dFormatInfo;
    392     if (GetD3D9FormatInfo(format, &d3dFormatInfo))
    393     {
    394         GLuint numBlocksWide = (width + d3dFormatInfo.mBlockWidth - 1) / d3dFormatInfo.mBlockWidth;
    395         GLuint numBlocksHight = (height + d3dFormatInfo.mBlockHeight - 1) / d3dFormatInfo.mBlockHeight;
    396 
    397         return (d3dFormatInfo.mPixelBits * numBlocksWide * numBlocksHight) / 8;
    398     }
    399     else
    400     {
    401         UNREACHABLE();
    402         return 0;
    403     }
    404 }
    405 
    406 void MakeValidSize(bool isImage, D3DFORMAT format, GLsizei *requestWidth, GLsizei *requestHeight, int *levelOffset)
    407 {
    408     D3DFormatInfo d3dFormatInfo;
    409     if (GetD3D9FormatInfo(format, &d3dFormatInfo))
    410     {
    411         int upsampleCount = 0;
    412 
    413         GLsizei blockWidth = d3dFormatInfo.mBlockWidth;
    414         GLsizei blockHeight = d3dFormatInfo.mBlockHeight;
    415 
    416         // Don't expand the size of full textures that are at least (blockWidth x blockHeight) already.
    417         if (isImage || *requestWidth < blockWidth || *requestHeight < blockHeight)
    418         {
    419             while (*requestWidth % blockWidth != 0 || *requestHeight % blockHeight != 0)
    420             {
    421                 *requestWidth <<= 1;
    422                 *requestHeight <<= 1;
    423                 upsampleCount++;
    424             }
    425         }
    426         *levelOffset = upsampleCount;
    427     }
    428 }
    429 
    430 const D3DFormatSet &GetAllUsedD3DFormats()
    431 {
    432     static const D3DFormatSet formatSet = BuildAllD3DFormatSet();
    433     return formatSet;
    434 }
    435 
    436 ColorReadFunction GetColorReadFunction(D3DFORMAT format)
    437 {
    438     D3DFormatInfo d3dFormatInfo;
    439     if (GetD3D9FormatInfo(format, &d3dFormatInfo))
    440     {
    441         return d3dFormatInfo.mColorReadFunction;
    442     }
    443     else
    444     {
    445         UNREACHABLE();
    446         return NULL;
    447     }
    448 }
    449 
    450 ColorCopyFunction GetFastCopyFunction(D3DFORMAT sourceFormat, GLenum destFormat, GLenum destType, GLuint clientVersion)
    451 {
    452     static const D3D9FastCopyMap fastCopyMap = BuildFastCopyMap();
    453     D3D9FastCopyMap::const_iterator iter = fastCopyMap.find(D3D9FastCopyFormat(sourceFormat, destFormat, destType));
    454     return (iter != fastCopyMap.end()) ? iter->second : NULL;
    455 }
    456 
    457 GLenum GetDeclTypeComponentType(D3DDECLTYPE declType)
    458 {
    459     switch (declType)
    460     {
    461       case D3DDECLTYPE_FLOAT1:   return GL_FLOAT;
    462       case D3DDECLTYPE_FLOAT2:   return GL_FLOAT;
    463       case D3DDECLTYPE_FLOAT3:   return GL_FLOAT;
    464       case D3DDECLTYPE_FLOAT4:   return GL_FLOAT;
    465       case D3DDECLTYPE_UBYTE4:   return GL_UNSIGNED_INT;
    466       case D3DDECLTYPE_SHORT2:   return GL_INT;
    467       case D3DDECLTYPE_SHORT4:   return GL_INT;
    468       case D3DDECLTYPE_UBYTE4N:  return GL_UNSIGNED_NORMALIZED;
    469       case D3DDECLTYPE_SHORT4N:  return GL_SIGNED_NORMALIZED;
    470       case D3DDECLTYPE_USHORT4N: return GL_UNSIGNED_NORMALIZED;
    471       case D3DDECLTYPE_SHORT2N:  return GL_SIGNED_NORMALIZED;
    472       case D3DDECLTYPE_USHORT2N: return GL_UNSIGNED_NORMALIZED;
    473       default: UNREACHABLE();    return GL_NONE;
    474     }
    475 }
    476 
    477 // Attribute format conversion
    478 enum { NUM_GL_VERTEX_ATTRIB_TYPES = 6 };
    479 
    480 struct FormatConverter
    481 {
    482     bool identity;
    483     std::size_t outputElementSize;
    484     void (*convertArray)(const void *in, std::size_t stride, std::size_t n, void *out);
    485     D3DDECLTYPE d3dDeclType;
    486 };
    487 
    488 struct TranslationDescription
    489 {
    490     DWORD capsFlag;
    491     FormatConverter preferredConversion;
    492     FormatConverter fallbackConversion;
    493 };
    494 
    495 static unsigned int typeIndex(GLenum type);
    496 static const FormatConverter &formatConverter(const gl::VertexAttribute &attribute);
    497 
    498 bool mTranslationsInitialized = false;
    499 FormatConverter mFormatConverters[NUM_GL_VERTEX_ATTRIB_TYPES][2][4];
    500 
    501 // Mapping from OpenGL-ES vertex attrib type to D3D decl type:
    502 //
    503 // BYTE                 SHORT (Cast)
    504 // BYTE-norm            FLOAT (Normalize) (can't be exactly represented as SHORT-norm)
    505 // UNSIGNED_BYTE        UBYTE4 (Identity) or SHORT (Cast)
    506 // UNSIGNED_BYTE-norm   UBYTE4N (Identity) or FLOAT (Normalize)
    507 // SHORT                SHORT (Identity)
    508 // SHORT-norm           SHORT-norm (Identity) or FLOAT (Normalize)
    509 // UNSIGNED_SHORT       FLOAT (Cast)
    510 // UNSIGNED_SHORT-norm  USHORT-norm (Identity) or FLOAT (Normalize)
    511 // FIXED (not in WebGL) FLOAT (FixedToFloat)
    512 // FLOAT                FLOAT (Identity)
    513 
    514 // GLToCType maps from GL type (as GLenum) to the C typedef.
    515 template <GLenum GLType> struct GLToCType { };
    516 
    517 template <> struct GLToCType<GL_BYTE>           { typedef GLbyte type;      };
    518 template <> struct GLToCType<GL_UNSIGNED_BYTE>  { typedef GLubyte type;     };
    519 template <> struct GLToCType<GL_SHORT>          { typedef GLshort type;     };
    520 template <> struct GLToCType<GL_UNSIGNED_SHORT> { typedef GLushort type;    };
    521 template <> struct GLToCType<GL_FIXED>          { typedef GLuint type;      };
    522 template <> struct GLToCType<GL_FLOAT>          { typedef GLfloat type;     };
    523 
    524 // This differs from D3DDECLTYPE in that it is unsized. (Size expansion is applied last.)
    525 enum D3DVertexType
    526 {
    527     D3DVT_FLOAT,
    528     D3DVT_SHORT,
    529     D3DVT_SHORT_NORM,
    530     D3DVT_UBYTE,
    531     D3DVT_UBYTE_NORM,
    532     D3DVT_USHORT_NORM
    533 };
    534 
    535 // D3DToCType maps from D3D vertex type (as enum D3DVertexType) to the corresponding C type.
    536 template <unsigned int D3DType> struct D3DToCType { };
    537 
    538 template <> struct D3DToCType<D3DVT_FLOAT> { typedef float type; };
    539 template <> struct D3DToCType<D3DVT_SHORT> { typedef short type; };
    540 template <> struct D3DToCType<D3DVT_SHORT_NORM> { typedef short type; };
    541 template <> struct D3DToCType<D3DVT_UBYTE> { typedef unsigned char type; };
    542 template <> struct D3DToCType<D3DVT_UBYTE_NORM> { typedef unsigned char type; };
    543 template <> struct D3DToCType<D3DVT_USHORT_NORM> { typedef unsigned short type; };
    544 
    545 // Encode the type/size combinations that D3D permits. For each type/size it expands to a widener that will provide the appropriate final size.
    546 template <unsigned int type, int size> struct WidenRule { };
    547 
    548 template <int size> struct WidenRule<D3DVT_FLOAT, size>          : NoWiden<size> { };
    549 template <int size> struct WidenRule<D3DVT_SHORT, size>          : WidenToEven<size> { };
    550 template <int size> struct WidenRule<D3DVT_SHORT_NORM, size>     : WidenToEven<size> { };
    551 template <int size> struct WidenRule<D3DVT_UBYTE, size>          : WidenToFour<size> { };
    552 template <int size> struct WidenRule<D3DVT_UBYTE_NORM, size>     : WidenToFour<size> { };
    553 template <int size> struct WidenRule<D3DVT_USHORT_NORM, size>    : WidenToEven<size> { };
    554 
    555 // VertexTypeFlags encodes the D3DCAPS9::DeclType flag and vertex declaration flag for each D3D vertex type & size combination.
    556 template <unsigned int d3dtype, int size> struct VertexTypeFlags { };
    557 
    558 template <unsigned int _capflag, unsigned int _declflag>
    559 struct VertexTypeFlagsHelper
    560 {
    561     enum { capflag = _capflag };
    562     enum { declflag = _declflag };
    563 };
    564 
    565 template <> struct VertexTypeFlags<D3DVT_FLOAT, 1> : VertexTypeFlagsHelper<0, D3DDECLTYPE_FLOAT1> { };
    566 template <> struct VertexTypeFlags<D3DVT_FLOAT, 2> : VertexTypeFlagsHelper<0, D3DDECLTYPE_FLOAT2> { };
    567 template <> struct VertexTypeFlags<D3DVT_FLOAT, 3> : VertexTypeFlagsHelper<0, D3DDECLTYPE_FLOAT3> { };
    568 template <> struct VertexTypeFlags<D3DVT_FLOAT, 4> : VertexTypeFlagsHelper<0, D3DDECLTYPE_FLOAT4> { };
    569 template <> struct VertexTypeFlags<D3DVT_SHORT, 2> : VertexTypeFlagsHelper<0, D3DDECLTYPE_SHORT2> { };
    570 template <> struct VertexTypeFlags<D3DVT_SHORT, 4> : VertexTypeFlagsHelper<0, D3DDECLTYPE_SHORT4> { };
    571 template <> struct VertexTypeFlags<D3DVT_SHORT_NORM, 2> : VertexTypeFlagsHelper<D3DDTCAPS_SHORT2N, D3DDECLTYPE_SHORT2N> { };
    572 template <> struct VertexTypeFlags<D3DVT_SHORT_NORM, 4> : VertexTypeFlagsHelper<D3DDTCAPS_SHORT4N, D3DDECLTYPE_SHORT4N> { };
    573 template <> struct VertexTypeFlags<D3DVT_UBYTE, 4> : VertexTypeFlagsHelper<D3DDTCAPS_UBYTE4, D3DDECLTYPE_UBYTE4> { };
    574 template <> struct VertexTypeFlags<D3DVT_UBYTE_NORM, 4> : VertexTypeFlagsHelper<D3DDTCAPS_UBYTE4N, D3DDECLTYPE_UBYTE4N> { };
    575 template <> struct VertexTypeFlags<D3DVT_USHORT_NORM, 2> : VertexTypeFlagsHelper<D3DDTCAPS_USHORT2N, D3DDECLTYPE_USHORT2N> { };
    576 template <> struct VertexTypeFlags<D3DVT_USHORT_NORM, 4> : VertexTypeFlagsHelper<D3DDTCAPS_USHORT4N, D3DDECLTYPE_USHORT4N> { };
    577 
    578 
    579 // VertexTypeMapping maps GL type & normalized flag to preferred and fallback D3D vertex types (as D3DVertexType enums).
    580 template <GLenum GLtype, bool normalized> struct VertexTypeMapping { };
    581 
    582 template <D3DVertexType Preferred, D3DVertexType Fallback = Preferred>
    583 struct VertexTypeMappingBase
    584 {
    585     enum { preferred = Preferred };
    586     enum { fallback = Fallback };
    587 };
    588 
    589 template <> struct VertexTypeMapping<GL_BYTE, false>                        : VertexTypeMappingBase<D3DVT_SHORT> { };                       // Cast
    590 template <> struct VertexTypeMapping<GL_BYTE, true>                         : VertexTypeMappingBase<D3DVT_FLOAT> { };                       // Normalize
    591 template <> struct VertexTypeMapping<GL_UNSIGNED_BYTE, false>               : VertexTypeMappingBase<D3DVT_UBYTE, D3DVT_FLOAT> { };          // Identity, Cast
    592 template <> struct VertexTypeMapping<GL_UNSIGNED_BYTE, true>                : VertexTypeMappingBase<D3DVT_UBYTE_NORM, D3DVT_FLOAT> { };     // Identity, Normalize
    593 template <> struct VertexTypeMapping<GL_SHORT, false>                       : VertexTypeMappingBase<D3DVT_SHORT> { };                       // Identity
    594 template <> struct VertexTypeMapping<GL_SHORT, true>                        : VertexTypeMappingBase<D3DVT_SHORT_NORM, D3DVT_FLOAT> { };     // Cast, Normalize
    595 template <> struct VertexTypeMapping<GL_UNSIGNED_SHORT, false>              : VertexTypeMappingBase<D3DVT_FLOAT> { };                       // Cast
    596 template <> struct VertexTypeMapping<GL_UNSIGNED_SHORT, true>               : VertexTypeMappingBase<D3DVT_USHORT_NORM, D3DVT_FLOAT> { };    // Cast, Normalize
    597 template <bool normalized> struct VertexTypeMapping<GL_FIXED, normalized>   : VertexTypeMappingBase<D3DVT_FLOAT> { };                       // FixedToFloat
    598 template <bool normalized> struct VertexTypeMapping<GL_FLOAT, normalized>   : VertexTypeMappingBase<D3DVT_FLOAT> { };                       // Identity
    599 
    600 
    601 // Given a GL type & norm flag and a D3D type, ConversionRule provides the type conversion rule (Cast, Normalize, Identity, FixedToFloat).
    602 // The conversion rules themselves are defined in vertexconversion.h.
    603 
    604 // Almost all cases are covered by Cast (including those that are actually Identity since Cast<T,T> knows it's an identity mapping).
    605 template <GLenum fromType, bool normalized, unsigned int toType>
    606 struct ConversionRule : Cast<typename GLToCType<fromType>::type, typename D3DToCType<toType>::type> { };
    607 
    608 // All conversions from normalized types to float use the Normalize operator.
    609 template <GLenum fromType> struct ConversionRule<fromType, true, D3DVT_FLOAT> : Normalize<typename GLToCType<fromType>::type> { };
    610 
    611 // Use a full specialization for this so that it preferentially matches ahead of the generic normalize-to-float rules.
    612 template <> struct ConversionRule<GL_FIXED, true, D3DVT_FLOAT>  : FixedToFloat<GLint, 16> { };
    613 template <> struct ConversionRule<GL_FIXED, false, D3DVT_FLOAT> : FixedToFloat<GLint, 16> { };
    614 
    615 // A 2-stage construction is used for DefaultVertexValues because float must use SimpleDefaultValues (i.e. 0/1)
    616 // whether it is normalized or not.
    617 template <class T, bool normalized> struct DefaultVertexValuesStage2 { };
    618 
    619 template <class T> struct DefaultVertexValuesStage2<T, true>  : NormalizedDefaultValues<T> { };
    620 template <class T> struct DefaultVertexValuesStage2<T, false> : SimpleDefaultValues<T> { };
    621 
    622 // Work out the default value rule for a D3D type (expressed as the C type) and
    623 template <class T, bool normalized> struct DefaultVertexValues : DefaultVertexValuesStage2<T, normalized> { };
    624 template <bool normalized> struct DefaultVertexValues<float, normalized> : SimpleDefaultValues<float> { };
    625 
    626 // Policy rules for use with Converter, to choose whether to use the preferred or fallback conversion.
    627 // The fallback conversion produces an output that all D3D9 devices must support.
    628 template <class T> struct UsePreferred { enum { type = T::preferred }; };
    629 template <class T> struct UseFallback { enum { type = T::fallback }; };
    630 
    631 // Converter ties it all together. Given an OpenGL type/norm/size and choice of preferred/fallback conversion,
    632 // it provides all the members of the appropriate VertexDataConverter, the D3DCAPS9::DeclTypes flag in cap flag
    633 // and the D3DDECLTYPE member needed for the vertex declaration in declflag.
    634 template <GLenum fromType, bool normalized, int size, template <class T> class PreferenceRule>
    635 struct Converter
    636     : VertexDataConverter<typename GLToCType<fromType>::type,
    637                           WidenRule<PreferenceRule< VertexTypeMapping<fromType, normalized> >::type, size>,
    638                           ConversionRule<fromType,
    639                                          normalized,
    640                                          PreferenceRule< VertexTypeMapping<fromType, normalized> >::type>,
    641                           DefaultVertexValues<typename D3DToCType<PreferenceRule< VertexTypeMapping<fromType, normalized> >::type>::type, normalized > >
    642 {
    643 private:
    644     enum { d3dtype = PreferenceRule< VertexTypeMapping<fromType, normalized> >::type };
    645     enum { d3dsize = WidenRule<d3dtype, size>::finalWidth };
    646 
    647 public:
    648     enum { capflag = VertexTypeFlags<d3dtype, d3dsize>::capflag };
    649     enum { declflag = VertexTypeFlags<d3dtype, d3dsize>::declflag };
    650 };
    651 
    652 // Initialize a TranslationInfo
    653 #define TRANSLATION(type, norm, size, preferred)                                    \
    654     {                                                                               \
    655         Converter<type, norm, size, preferred>::identity,                           \
    656         Converter<type, norm, size, preferred>::finalSize,                          \
    657         Converter<type, norm, size, preferred>::convertArray,                       \
    658         static_cast<D3DDECLTYPE>(Converter<type, norm, size, preferred>::declflag)  \
    659     }
    660 
    661 #define TRANSLATION_FOR_TYPE_NORM_SIZE(type, norm, size)    \
    662     {                                                       \
    663         Converter<type, norm, size, UsePreferred>::capflag, \
    664         TRANSLATION(type, norm, size, UsePreferred),        \
    665         TRANSLATION(type, norm, size, UseFallback)          \
    666     }
    667 
    668 #define TRANSLATIONS_FOR_TYPE(type)                                                                                                                                                                         \
    669     {                                                                                                                                                                                                       \
    670         { 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) }, \
    671         { 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) },     \
    672     }
    673 
    674 #define TRANSLATIONS_FOR_TYPE_NO_NORM(type)                                                                                                                                                                 \
    675     {                                                                                                                                                                                                       \
    676         { 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) }, \
    677         { 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) }, \
    678     }
    679 
    680 const TranslationDescription mPossibleTranslations[NUM_GL_VERTEX_ATTRIB_TYPES][2][4] = // [GL types as enumerated by typeIndex()][normalized][size-1]
    681 {
    682     TRANSLATIONS_FOR_TYPE(GL_BYTE),
    683     TRANSLATIONS_FOR_TYPE(GL_UNSIGNED_BYTE),
    684     TRANSLATIONS_FOR_TYPE(GL_SHORT),
    685     TRANSLATIONS_FOR_TYPE(GL_UNSIGNED_SHORT),
    686     TRANSLATIONS_FOR_TYPE_NO_NORM(GL_FIXED),
    687     TRANSLATIONS_FOR_TYPE_NO_NORM(GL_FLOAT)
    688 };
    689 
    690 void InitializeVertexTranslations(const rx::Renderer9 *renderer)
    691 {
    692     DWORD declTypes = renderer->getCapsDeclTypes();
    693 
    694     for (unsigned int i = 0; i < NUM_GL_VERTEX_ATTRIB_TYPES; i++)
    695     {
    696         for (unsigned int j = 0; j < 2; j++)
    697         {
    698             for (unsigned int k = 0; k < 4; k++)
    699             {
    700                 if (mPossibleTranslations[i][j][k].capsFlag == 0 || (declTypes & mPossibleTranslations[i][j][k].capsFlag) != 0)
    701                 {
    702                     mFormatConverters[i][j][k] = mPossibleTranslations[i][j][k].preferredConversion;
    703                 }
    704                 else
    705                 {
    706                     mFormatConverters[i][j][k] = mPossibleTranslations[i][j][k].fallbackConversion;
    707                 }
    708             }
    709         }
    710     }
    711 }
    712 
    713 unsigned int typeIndex(GLenum type)
    714 {
    715     switch (type)
    716     {
    717       case GL_BYTE: return 0;
    718       case GL_UNSIGNED_BYTE: return 1;
    719       case GL_SHORT: return 2;
    720       case GL_UNSIGNED_SHORT: return 3;
    721       case GL_FIXED: return 4;
    722       case GL_FLOAT: return 5;
    723 
    724       default: UNREACHABLE(); return 5;
    725     }
    726 }
    727 
    728 const FormatConverter &formatConverter(const gl::VertexFormat &vertexFormat)
    729 {
    730     // Pure integer attributes only supported in ES3.0
    731     ASSERT(!vertexFormat.mPureInteger);
    732     return mFormatConverters[typeIndex(vertexFormat.mType)][vertexFormat.mNormalized][vertexFormat.mComponents - 1];
    733 }
    734 
    735 VertexCopyFunction GetVertexCopyFunction(const gl::VertexFormat &vertexFormat)
    736 {
    737     return formatConverter(vertexFormat).convertArray;
    738 }
    739 
    740 size_t GetVertexElementSize(const gl::VertexFormat &vertexFormat)
    741 {
    742     return formatConverter(vertexFormat).outputElementSize;
    743 }
    744 
    745 VertexConversionType GetVertexConversionType(const gl::VertexFormat &vertexFormat)
    746 {
    747     return (formatConverter(vertexFormat).identity ? VERTEX_CONVERT_NONE : VERTEX_CONVERT_CPU);
    748 }
    749 
    750 D3DDECLTYPE GetNativeVertexFormat(const gl::VertexFormat &vertexFormat)
    751 {
    752     return formatConverter(vertexFormat).d3dDeclType;
    753 }
    754 
    755 }
    756 
    757 namespace gl_d3d9
    758 {
    759 
    760 D3DFORMAT GetTextureFormat(GLenum internalFormat, const Renderer9 *renderer)
    761 {
    762     if (!renderer)
    763     {
    764         UNREACHABLE();
    765         return D3DFMT_UNKNOWN;
    766     }
    767 
    768     ASSERT(renderer->getCurrentClientVersion() == 2);
    769 
    770     D3D9FormatInfo d3d9FormatInfo;
    771     if (GetD3D9FormatInfo(internalFormat, &d3d9FormatInfo))
    772     {
    773         return d3d9FormatInfo.mTexFormat(renderer);
    774     }
    775     else
    776     {
    777         UNREACHABLE();
    778         return D3DFMT_UNKNOWN;
    779     }
    780 }
    781 
    782 D3DFORMAT GetRenderFormat(GLenum internalFormat, const Renderer9 *renderer)
    783 {
    784     if (!renderer)
    785     {
    786         UNREACHABLE();
    787         return D3DFMT_UNKNOWN;
    788     }
    789 
    790     ASSERT(renderer->getCurrentClientVersion() == 2);
    791 
    792     D3D9FormatInfo d3d9FormatInfo;
    793     if (GetD3D9FormatInfo(internalFormat, &d3d9FormatInfo))
    794     {
    795         return d3d9FormatInfo.mRenderFormat(renderer);
    796     }
    797     else
    798     {
    799         UNREACHABLE();
    800         return D3DFMT_UNKNOWN;
    801     }
    802 }
    803 
    804 D3DMULTISAMPLE_TYPE GetMultisampleType(GLsizei samples)
    805 {
    806     return (samples > 1) ? static_cast<D3DMULTISAMPLE_TYPE>(samples) : D3DMULTISAMPLE_NONE;
    807 }
    808 
    809 bool RequiresTextureDataInitialization(GLint internalFormat)
    810 {
    811     const InternalFormatInitialzerMap &map = GetInternalFormatInitialzerMap();
    812     return map.find(internalFormat) != map.end();
    813 }
    814 
    815 InitializeTextureDataFunction GetTextureDataInitializationFunction(GLint internalFormat)
    816 {
    817     const InternalFormatInitialzerMap &map = GetInternalFormatInitialzerMap();
    818     InternalFormatInitialzerMap::const_iterator iter = map.find(internalFormat);
    819     if (iter != map.end())
    820     {
    821         return iter->second;
    822     }
    823     else
    824     {
    825         UNREACHABLE();
    826         return NULL;
    827     }
    828 }
    829 
    830 }
    831 
    832 namespace d3d9_gl
    833 {
    834 
    835 GLenum GetInternalFormat(D3DFORMAT format)
    836 {
    837     static const D3D9FormatInfoMap infoMap = BuildD3D9FormatInfoMap();
    838     D3D9FormatInfoMap::const_iterator iter = infoMap.find(format);
    839     if (iter != infoMap.end())
    840     {
    841         return iter->second.mInternalFormat;
    842     }
    843     else
    844     {
    845         UNREACHABLE();
    846         return GL_NONE;
    847     }
    848 }
    849 
    850 GLsizei GetSamplesCount(D3DMULTISAMPLE_TYPE type)
    851 {
    852     return (type != D3DMULTISAMPLE_NONMASKABLE) ? type : 0;
    853 }
    854 
    855 bool IsFormatChannelEquivalent(D3DFORMAT d3dformat, GLenum format, GLuint clientVersion)
    856 {
    857     GLenum internalFormat = d3d9_gl::GetInternalFormat(d3dformat);
    858     GLenum convertedFormat = gl::GetFormat(internalFormat, clientVersion);
    859     return convertedFormat == format;
    860 }
    861 
    862 }
    863 
    864 }
    865