@@ -46,6 +46,9 @@ namespace
46
46
CONV_FLAGS_L8 = 0x40000 , // Source is a 8 luminance format
47
47
CONV_FLAGS_L16 = 0x80000 , // Source is a 16 luminance format
48
48
CONV_FLAGS_A8L8 = 0x100000 , // Source is a 8:8 luminance format
49
+ CONV_FLAGS_L6V5U5 = 0x200000 , // Source is a 6:5:5 bumpluminance format
50
+ CONV_FLAGS_L8U8V8 = 0x400000 , // Source is a X:8:8:8 bumpluminance format
51
+ CONV_FLAGS_WUV10 = 0x800000 , // Source is a 2:10:10:10 bump format
49
52
};
50
53
51
54
struct LegacyDDS
@@ -141,7 +144,7 @@ namespace
141
144
142
145
{ DXGI_FORMAT_R8G8B8A8_UNORM, CONV_FLAGS_EXPAND
143
146
| CONV_FLAGS_PAL8
144
- | CONV_FLAGS_A8P8, { sizeof (DDS_PIXELFORMAT), DDS_PAL8A, 0 , 16 , 0 , 0 , 0 , 0 } }, // D3DFMT_A8P8
147
+ | CONV_FLAGS_A8P8, { sizeof (DDS_PIXELFORMAT), DDS_PAL8A, 0 , 16 , 0 , 0 , 0 , 0xff00 } }, // D3DFMT_A8P8
145
148
{ DXGI_FORMAT_R8G8B8A8_UNORM, CONV_FLAGS_EXPAND
146
149
| CONV_FLAGS_PAL8, { sizeof (DDS_PIXELFORMAT), DDS_PAL8, 0 , 8 , 0 , 0 , 0 , 0 } }, // D3DFMT_P8
147
150
@@ -157,6 +160,11 @@ namespace
157
160
{ DXGI_FORMAT_R8G8_SNORM, CONV_FLAGS_NONE, DDSPF_V8U8 }, // D3DFMT_V8U8
158
161
{ DXGI_FORMAT_R8G8B8A8_SNORM, CONV_FLAGS_NONE, DDSPF_Q8W8V8U8 }, // D3DFMT_Q8W8V8U8
159
162
{ DXGI_FORMAT_R16G16_SNORM, CONV_FLAGS_NONE, DDSPF_V16U16 }, // D3DFMT_V16U16
163
+
164
+ { DXGI_FORMAT_R8G8B8A8_UNORM, CONV_FLAGS_L6V5U5
165
+ | CONV_FLAGS_EXPAND, DDSPF_L6V5U5 }, // D3DFMT_L6V5U5
166
+ { DXGI_FORMAT_R8G8B8A8_UNORM, CONV_FLAGS_L8U8V8, DDSPF_X8L8V8U8 }, // D3DFMT_X8L8V8U8
167
+ { DXGI_FORMAT_R10G10B10A2_UNORM, CONV_FLAGS_WUV10, DDSPF_A2W10V10U10 }, // D3DFMT_A2W10V10U10
160
168
};
161
169
162
170
// Note that many common DDS reader/writers (including D3DX) swap the
@@ -166,15 +174,14 @@ namespace
166
174
// header extension and specify the DXGI_FORMAT_R10G10B10A2_UNORM format directly
167
175
168
176
// We do not support the following legacy Direct3D 9 formats:
169
- // BumpDuDv D3DFMT_A2W10V10U10
170
- // BumpLuminance D3DFMT_L6V5U5, D3DFMT_X8L8V8U8
171
- // FourCC 117 D3DFMT_CxV8U8
172
- // ZBuffer D3DFMT_D16_LOCKABLE
177
+ // D3DFMT_D16_LOCKABLE (DDPF_ZBUFFER: 0x00000400)
173
178
// FourCC 82 D3DFMT_D32F_LOCKABLE
179
+ // FourCC 117 D3DFMT_CxV8U8
174
180
175
181
// We do not support the following known FourCC codes:
176
182
// FourCC CTX1 (Xbox 360 only)
177
183
// FourCC EAR, EARG, ET2, ET2A (Ericsson Texture Compression)
184
+ // FourCC MET1 (a.k.a. D3DFMT_MULTI2_ARGB8; rarely supported by any hardware)
178
185
179
186
DXGI_FORMAT GetDXGIFormat (const DDS_HEADER& hdr, const DDS_PIXELFORMAT& ddpf,
180
187
DDS_FLAGS flags,
@@ -215,66 +222,70 @@ namespace
215
222
if (ddpf.fourCC == entry->ddpf .fourCC )
216
223
break ;
217
224
}
218
- else if (ddpfFlags == entry->ddpf .flags )
225
+ else if (( ddpfFlags == entry->ddpf .flags ) && (ddpf. RGBBitCount == entry-> ddpf . RGBBitCount ) )
219
226
{
220
227
if (entry->ddpf .flags & DDS_PAL8)
221
228
{
222
- if (ddpf. RGBBitCount == entry-> ddpf . RGBBitCount )
223
- break ;
229
+ // PAL8 / PAL8A
230
+ break ;
224
231
}
225
232
else if (entry->ddpf .flags & DDS_ALPHA)
226
233
{
227
- if (ddpf.RGBBitCount == entry->ddpf .RGBBitCount
228
- && ddpf.ABitMask == entry->ddpf .ABitMask )
234
+ if (ddpf.ABitMask == entry->ddpf .ABitMask )
229
235
break ;
230
236
}
231
237
else if (entry->ddpf .flags & DDS_LUMINANCE)
232
238
{
233
239
if (entry->ddpf .flags & DDS_ALPHAPIXELS)
234
240
{
235
241
// LUMINANCEA
236
- if (ddpf.RGBBitCount == entry->ddpf .RGBBitCount
237
- && ddpf.RBitMask == entry->ddpf .RBitMask
242
+ if (ddpf.RBitMask == entry->ddpf .RBitMask
238
243
&& ddpf.ABitMask == entry->ddpf .ABitMask )
239
244
break ;
240
245
}
241
246
else
242
247
{
243
248
// LUMINANCE
244
- if (ddpf.RGBBitCount == entry->ddpf .RGBBitCount
245
- && ddpf.RBitMask == entry->ddpf .RBitMask )
249
+ if (ddpf.RBitMask == entry->ddpf .RBitMask )
246
250
break ;
247
251
}
248
252
}
249
253
else if (entry->ddpf .flags & DDS_BUMPDUDV)
250
- {
251
- if (ddpf.RGBBitCount == entry->ddpf .RGBBitCount
252
- && ddpf.RBitMask == entry->ddpf .RBitMask
253
- && ddpf.GBitMask == entry->ddpf .GBitMask
254
- && ddpf.BBitMask == entry->ddpf .BBitMask
255
- && ddpf.ABitMask == entry->ddpf .ABitMask )
256
- break ;
257
- }
258
- else if (ddpf.RGBBitCount == entry->ddpf .RGBBitCount )
259
254
{
260
255
if (entry->ddpf .flags & DDS_ALPHAPIXELS)
261
256
{
262
- // RGBA
257
+ // BUMPDUDVA
263
258
if (ddpf.RBitMask == entry->ddpf .RBitMask
264
- && ddpf.GBitMask == entry->ddpf .GBitMask
265
- && ddpf.BBitMask == entry->ddpf .BBitMask
266
259
&& ddpf.ABitMask == entry->ddpf .ABitMask )
260
+ {
261
+ flags &= ~DDS_FLAGS_NO_R10B10G10A2_FIXUP;
267
262
break ;
263
+ }
268
264
}
269
265
else
270
266
{
271
- // RGB
272
- if (ddpf.RBitMask == entry->ddpf .RBitMask
273
- && ddpf.GBitMask == entry->ddpf .GBitMask
274
- && ddpf.BBitMask == entry->ddpf .BBitMask )
267
+ // BUMPDUDV
268
+ if (ddpf.RBitMask == entry->ddpf .RBitMask )
275
269
break ;
276
270
}
277
271
}
272
+ else if (entry->ddpf .flags & DDS_ALPHAPIXELS)
273
+ {
274
+ // RGBA
275
+ if (ddpf.RBitMask == entry->ddpf .RBitMask
276
+ && ddpf.GBitMask == entry->ddpf .GBitMask
277
+ && ddpf.BBitMask == entry->ddpf .BBitMask
278
+ && ddpf.ABitMask == entry->ddpf .ABitMask )
279
+ break ;
280
+ }
281
+ else
282
+ {
283
+ // RGB
284
+ if (ddpf.RBitMask == entry->ddpf .RBitMask
285
+ && ddpf.GBitMask == entry->ddpf .GBitMask
286
+ && ddpf.BBitMask == entry->ddpf .BBitMask )
287
+ break ;
288
+ }
278
289
}
279
290
}
280
291
}
@@ -996,7 +1007,10 @@ namespace
996
1007
TEXP_LEGACY_B4G4R4A4,
997
1008
TEXP_LEGACY_L8,
998
1009
TEXP_LEGACY_L16,
999
- TEXP_LEGACY_A8L8
1010
+ TEXP_LEGACY_A8L8,
1011
+ TEXP_LEGACY_L6V5U5,
1012
+ TEXP_LEGACY_X8L8V8U8,
1013
+ TEXP_LEGACY_A2W10V10U10
1000
1014
};
1001
1015
1002
1016
constexpr TEXP_LEGACY_FORMAT FindLegacyFormat (uint32_t flags) noexcept
@@ -1023,6 +1037,12 @@ namespace
1023
1037
lformat = TEXP_LEGACY_L16;
1024
1038
else if (flags & CONV_FLAGS_A8L8)
1025
1039
lformat = TEXP_LEGACY_A8L8;
1040
+ else if (flags & CONV_FLAGS_L6V5U5)
1041
+ lformat = TEXP_LEGACY_L6V5U5;
1042
+ else if (flags & CONV_FLAGS_L8U8V8)
1043
+ lformat = TEXP_LEGACY_X8L8V8U8;
1044
+ else if (flags & CONV_FLAGS_WUV10)
1045
+ lformat = TEXP_LEGACY_A2W10V10U10;
1026
1046
1027
1047
return lformat;
1028
1048
}
@@ -1328,11 +1348,120 @@ namespace
1328
1348
}
1329
1349
return false ;
1330
1350
1351
+ case TEXP_LEGACY_L6V5U5:
1352
+ if (outFormat != DXGI_FORMAT_R8G8B8A8_UNORM)
1353
+ return false ;
1354
+
1355
+ // D3DFMT_L6V5U5 -> DXGI_FORMAT_R8G8B8A8_UNORM (LUVA)
1356
+ if (inSize >= 2 && outSize >= 4 )
1357
+ {
1358
+ const uint16_t * __restrict sPtr = static_cast <const uint16_t *>(pSource);
1359
+ uint32_t * __restrict dPtr = static_cast <uint32_t *>(pDestination);
1360
+
1361
+ for (size_t ocount = 0 , icount = 0 ; ((icount < (inSize - 1 )) && (ocount < (outSize - 3 ))); icount += 2 , ocount += 4 )
1362
+ {
1363
+ const uint16_t t = *(sPtr ++);
1364
+
1365
+ // Converts unsigned 6-bit/signed 5-bit/signed 5-bit bump luminance to 8:8:8:8 unsigned
1366
+ uint32_t t1 = ((t & 0xFC00 ) >> 8 ) | ((t & 0xC000 ) >> 14 );
1367
+
1368
+ constexpr int m = 1U << 4 ;
1369
+ int8_t v = ((((t >> 5 ) & 0x1f ) ^ m) - m) + 16 ;
1370
+ int8_t u = (((t & 0x1f ) ^ m) - m) + 16 ;
1371
+
1372
+ uint32_t t2 = u << 3 | u >> 2 ;
1373
+ uint32_t t3 = v << 3 | v >> 2 ;
1374
+
1375
+ *(dPtr++) = t1 | (t2 << 8 ) | (t3 << 16 ) | 0xff000000 ;
1376
+ }
1377
+ return true ;
1378
+ }
1379
+ return false ;
1380
+
1331
1381
default :
1332
1382
return false ;
1333
1383
}
1334
1384
}
1335
1385
1386
+ _Success_ (return )
1387
+ bool LegacyConvertScanline(
1388
+ _Out_writes_bytes_ (outSize) void* pDestination,
1389
+ size_t outSize,
1390
+ _In_ DXGI_FORMAT outFormat,
1391
+ _In_reads_bytes_(inSize) const void* pSource,
1392
+ size_t inSize,
1393
+ _In_ TEXP_LEGACY_FORMAT inFormat,
1394
+ uint32_t tflags) noexcept
1395
+ {
1396
+ assert (pDestination && outSize > 0 );
1397
+ assert (pSource && inSize > 0 );
1398
+
1399
+ switch (inFormat)
1400
+ {
1401
+ case TEXP_LEGACY_X8L8V8U8:
1402
+ if (outFormat != DXGI_FORMAT_R8G8B8A8_UNORM)
1403
+ return false ;
1404
+
1405
+ // D3DFMT_X8L8V8U8 -> DXGI_FORMAT_R8G8B8A8_UNORM (LUVA)
1406
+ if (inSize >= 4 && outSize >= 4 )
1407
+ {
1408
+ auto sPtr = static_cast <const uint32_t *>(pSource);
1409
+ auto dPtr = static_cast <uint32_t *>(pDestination);
1410
+
1411
+ for (size_t ocount = 0 , icount = 0 ; ((icount < (inSize - 3 )) && (ocount < (outSize - 3 ))); icount += 4 , ocount += 4 )
1412
+ {
1413
+ const uint32_t t = *(sPtr ++);
1414
+
1415
+ // Converts 8-bit unsigned / 8-bit signed / 8-bit signed to 8:8:8:8 unsigned
1416
+ uint32_t t1 = (t >> 16 ) & 0xff ;
1417
+ constexpr int m = 1U << 7 ;
1418
+ uint32_t v = ((((t >> 8 ) & 0xff ) ^ m) - m) + 128 ;
1419
+ uint32_t u = (((t & 0xff ) ^ m) - m) + 128 ;
1420
+
1421
+ uint32_t t2 = u << 8 ;
1422
+ uint32_t t3 = v << 16 ;
1423
+
1424
+ *(dPtr++) = t1 | t2 | t3 | 0xff000000 ;
1425
+ }
1426
+ return true ;
1427
+ }
1428
+ return false ;
1429
+
1430
+ case TEXP_LEGACY_A2W10V10U10:
1431
+ if (outFormat != DXGI_FORMAT_R10G10B10A2_UNORM)
1432
+ return false ;
1433
+
1434
+ // D3DFMT_A2W10V10U10 -> DXGI_FORMAT_R10G10B10A2_UNORM (UVWA)
1435
+ if (inSize >= 4 && outSize >= 4 )
1436
+ {
1437
+ auto sPtr = static_cast <const uint32_t *>(pSource);
1438
+ auto dPtr = static_cast <uint32_t *>(pDestination);
1439
+
1440
+ for (size_t ocount = 0 , icount = 0 ; ((icount < (inSize - 3 )) && (ocount < (outSize - 3 ))); icount += 4 , ocount += 4 )
1441
+ {
1442
+ const uint32_t t = *(sPtr ++);
1443
+
1444
+ // Converts 2-bit unsigned / 10-bit signed / 10-bit signed / 10-bit signed to 2:10:10:10 unsigned
1445
+ constexpr int m = 1U << 9 ;
1446
+ uint32_t w = ((((t >> 20 ) & 0x3ff ) ^ m) - m) + 512 ;
1447
+ uint32_t v = ((((t >> 10 ) & 0x3ff ) ^ m) - m) + 512 ;
1448
+ uint32_t u = (((t & 0x3ff ) ^ m) - m) + 512 ;
1449
+
1450
+ uint32_t t1 = u;
1451
+ uint32_t t2 = v << 10 ;
1452
+ uint32_t t3 = w << 20 ;
1453
+ uint32_t ta = (tflags & TEXP_SCANLINE_SETALPHA) ? 0xC0000000 : (t & 0xC0000000 );
1454
+
1455
+ *(dPtr++) = t1 | t2 | t3 | ta;
1456
+ }
1457
+ return true ;
1458
+ }
1459
+ return false ;
1460
+
1461
+ default :
1462
+ return false ;
1463
+ }
1464
+ }
1336
1465
1337
1466
// -------------------------------------------------------------------------------------
1338
1467
// Converts or copies image data from pPixels into scratch image data
@@ -1356,7 +1485,7 @@ namespace
1356
1485
{
1357
1486
if (convFlags & CONV_FLAGS_888)
1358
1487
cpFlags |= CP_FLAGS_24BPP;
1359
- else if (convFlags & (CONV_FLAGS_565 | CONV_FLAGS_5551 | CONV_FLAGS_4444 | CONV_FLAGS_8332 | CONV_FLAGS_A8P8 | CONV_FLAGS_L16 | CONV_FLAGS_A8L8))
1488
+ else if (convFlags & (CONV_FLAGS_565 | CONV_FLAGS_5551 | CONV_FLAGS_4444 | CONV_FLAGS_8332 | CONV_FLAGS_A8P8 | CONV_FLAGS_L16 | CONV_FLAGS_A8L8 | CONV_FLAGS_L6V5U5 ))
1360
1489
cpFlags |= CP_FLAGS_16BPP;
1361
1490
else if (convFlags & (CONV_FLAGS_44 | CONV_FLAGS_332 | CONV_FLAGS_PAL8 | CONV_FLAGS_L8))
1362
1491
cpFlags |= CP_FLAGS_8BPP;
@@ -1502,13 +1631,18 @@ namespace
1502
1631
}
1503
1632
else if (convFlags & CONV_FLAGS_SWIZZLE)
1504
1633
{
1505
- SwizzleScanline (pDest, dpitch, pSrc, spitch,
1506
- metadata.format , tflags);
1634
+ SwizzleScanline (pDest, dpitch, pSrc, spitch, metadata.format , tflags);
1635
+ }
1636
+ else if (convFlags & (CONV_FLAGS_L8U8V8 | CONV_FLAGS_WUV10))
1637
+ {
1638
+ const TEXP_LEGACY_FORMAT lformat = FindLegacyFormat (convFlags);
1639
+ if (!LegacyConvertScanline (pDest, dpitch, metadata.format ,
1640
+ pSrc, spitch, lformat, tflags))
1641
+ return E_FAIL;
1507
1642
}
1508
1643
else
1509
1644
{
1510
- CopyScanline (pDest, dpitch, pSrc, spitch,
1511
- metadata.format , tflags);
1645
+ CopyScanline (pDest, dpitch, pSrc, spitch, metadata.format , tflags);
1512
1646
}
1513
1647
1514
1648
pSrc += spitch;
@@ -1605,6 +1739,13 @@ namespace
1605
1739
{
1606
1740
SwizzleScanline (pDest, dpitch, pSrc, spitch, metadata.format , tflags);
1607
1741
}
1742
+ else if (convFlags & (CONV_FLAGS_L8U8V8 | CONV_FLAGS_WUV10))
1743
+ {
1744
+ const TEXP_LEGACY_FORMAT lformat = FindLegacyFormat (convFlags);
1745
+ if (!LegacyConvertScanline (pDest, dpitch, metadata.format ,
1746
+ pSrc, spitch, lformat, tflags))
1747
+ return E_FAIL;
1748
+ }
1608
1749
else
1609
1750
{
1610
1751
CopyScanline (pDest, dpitch, pSrc, spitch, metadata.format , tflags);
@@ -1662,6 +1803,14 @@ namespace
1662
1803
{
1663
1804
SwizzleScanline (pPixels, rowPitch, pPixels, rowPitch, metadata.format , tflags);
1664
1805
}
1806
+ else if (convFlags & (CONV_FLAGS_L8U8V8 | CONV_FLAGS_WUV10))
1807
+ {
1808
+ const TEXP_LEGACY_FORMAT lformat = FindLegacyFormat (convFlags);
1809
+ if (!LegacyConvertScanline (pPixels, rowPitch, metadata.format , pPixels, rowPitch, lformat, tflags))
1810
+ {
1811
+ return E_UNEXPECTED;
1812
+ }
1813
+ }
1665
1814
else
1666
1815
{
1667
1816
CopyScanline (pPixels, rowPitch, pPixels, rowPitch, metadata.format , tflags);
@@ -2133,7 +2282,7 @@ HRESULT DirectX::LoadFromDDSFileEx(
2133
2282
}
2134
2283
#endif
2135
2284
2136
- if (convFlags & (CONV_FLAGS_SWIZZLE | CONV_FLAGS_NOALPHA))
2285
+ if (convFlags & (CONV_FLAGS_SWIZZLE | CONV_FLAGS_NOALPHA | CONV_FLAGS_L8U8V8 | CONV_FLAGS_WUV10 ))
2137
2286
{
2138
2287
// Swizzle/copy image in place
2139
2288
hr = CopyImageInPlace (convFlags, image);
0 commit comments