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