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