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