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