Upstream version 9.37.197.0
[platform/framework/web/crosswalk.git] / src / third_party / angle / src / libGLESv2 / renderer / d3d9 / formatutils9.cpp
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 }