Skip to content

Commit 0d382fb

Browse files
walbourn_cpwalbourn_cp
walbourn_cp
authored and
walbourn_cp
committed
DirectXTex updated to read & write new miscFlags2 alpha mode metadata for DDS files
- Added helper to see if a texure's alpha channel is all opaque - Reads and writes DXT2 and DXT4 DDS files - Updated PremultiplyAlpha function to set miscFlags2 appropriately - Texconv updated for new feature, "-dx10" switch now allows write of miscFlags2 data
1 parent ee978ad commit 0d382fb

File tree

9 files changed

+340
-73
lines changed

9 files changed

+340
-73
lines changed

DirectXTex/DDS.h

Lines changed: 26 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -169,20 +169,33 @@ extern __declspec(selectany) const DDS_PIXELFORMAT DDSPF_DX10 =
169169
#define DDS_FLAGS_VOLUME 0x00200000 // DDSCAPS2_VOLUME
170170

171171
// Subset here matches D3D10_RESOURCE_DIMENSION and D3D11_RESOURCE_DIMENSION
172-
typedef enum DDS_RESOURCE_DIMENSION
172+
enum DDS_RESOURCE_DIMENSION
173173
{
174174
DDS_DIMENSION_TEXTURE1D = 2,
175175
DDS_DIMENSION_TEXTURE2D = 3,
176176
DDS_DIMENSION_TEXTURE3D = 4,
177-
} DDS_RESOURCE_DIMENSION;
177+
};
178178

179179
// Subset here matches D3D10_RESOURCE_MISC_FLAG and D3D11_RESOURCE_MISC_FLAG
180-
typedef enum DDS_RESOURCE_MISC_FLAG
180+
enum DDS_RESOURCE_MISC_FLAG
181+
{
182+
DDS_RESOURCE_MISC_TEXTURECUBE = 0x4L,
183+
};
184+
185+
enum DDS_MISC_FLAGS2
181186
{
182-
DDS_RESOURCE_MISC_TEXTURECUBE = 0x4L,
183-
} DDS_RESOURCE_MISC_FLAG;
187+
DDS_MISC_FLAGS2_ALPHA_MODE_MASK = 0x3L,
188+
};
184189

185-
typedef struct
190+
enum DDS_ALPHA_MODE
191+
{
192+
DDS_ALPHA_MODE_STRAIGHT = 0,
193+
DDS_ALPHA_MODE_PREMULTIPLIED = 1,
194+
DDS_ALPHA_MODE_4TH_CHANNEL = 2,
195+
DDS_ALPHA_MODE_OPAQUE = 3,
196+
};
197+
198+
struct DDS_HEADER
186199
{
187200
uint32_t dwSize;
188201
uint32_t dwFlags;
@@ -198,17 +211,20 @@ typedef struct
198211
uint32_t dwCaps3;
199212
uint32_t dwCaps4;
200213
uint32_t dwReserved2;
201-
} DDS_HEADER;
214+
};
202215

203-
typedef struct
216+
struct DDS_HEADER_DXT10
204217
{
205218
DXGI_FORMAT dxgiFormat;
206219
uint32_t resourceDimension;
207220
uint32_t miscFlag; // see DDS_RESOURCE_MISC_FLAG
208221
uint32_t arraySize;
209-
uint32_t reserved;
210-
} DDS_HEADER_DXT10;
222+
uint32_t miscFlags2; // see DDS_MISC_FLAGS2
223+
};
211224

212225
#pragma pack(pop)
213226

227+
static_assert( sizeof(DDS_HEADER) == 124, "DDS Header size mismatch" );
228+
static_assert( sizeof(DDS_HEADER_DXT10) == 20, "DDS DX10 Extended Header size mismatch");
229+
214230
}; // namespace

DirectXTex/DirectXTex.h

Lines changed: 28 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@
2727
#include <dxgiformat.h>
2828
#include <d3d11.h>
2929

30-
#define DIRECTX_TEX_VERSION 101
30+
#define DIRECTX_TEX_VERSION 102
3131

3232
#if defined(_MSC_VER) && (_MSC_VER<1610) && !defined(_In_reads_)
3333
#define _Analysis_assume_(exp)
@@ -99,6 +99,20 @@ namespace DirectX
9999
TEX_MISC_TEXTURECUBE = 0x4L,
100100
};
101101

102+
enum TEX_MISC_FLAG2
103+
{
104+
TEX_MISC2_ALPHA_MODE_MASK = 0x3L,
105+
};
106+
107+
enum TEX_ALPHA_MODE
108+
// Matches DDS_ALPHA_MODE, encoded in MISC_FLAGS2
109+
{
110+
TEX_ALPHA_MODE_STRAIGHT = 0,
111+
TEX_ALPHA_MODE_PREMULTIPLIED = 1,
112+
TEX_ALPHA_MODE_4TH_CHANNEL = 2,
113+
TEX_ALPHA_MODE_OPAQUE = 3,
114+
};
115+
102116
struct TexMetadata
103117
{
104118
size_t width;
@@ -107,11 +121,19 @@ namespace DirectX
107121
size_t arraySize; // For cubemap, this is a multiple of 6
108122
size_t mipLevels;
109123
uint32_t miscFlags;
124+
uint32_t miscFlags2;
110125
DXGI_FORMAT format;
111126
TEX_DIMENSION dimension;
112127

113128
size_t ComputeIndex( _In_ size_t mip, _In_ size_t item, _In_ size_t slice ) const;
114129
// Returns size_t(-1) to indicate an out-of-range error
130+
131+
bool IsCubemap() const { return (miscFlags & TEX_MISC_TEXTURECUBE) != 0; }
132+
// Helpers for miscFlags
133+
134+
bool IsPMAlpha() const { return ((miscFlags2 & TEX_MISC2_ALPHA_MODE_MASK) == TEX_ALPHA_MODE_PREMULTIPLIED) != 0; }
135+
void SetAlphaMode( TEX_ALPHA_MODE mode ) { miscFlags2 = (miscFlags2 & ~TEX_MISC2_ALPHA_MODE_MASK) | static_cast<uint32_t>(mode); }
136+
// Helpers for miscFlags2
115137
};
116138

117139
enum DDS_FLAGS
@@ -135,6 +157,9 @@ namespace DirectX
135157

136158
DDS_FLAGS_FORCE_DX10_EXT = 0x10000,
137159
// Always use the 'DX10' header extension for DDS writer (i.e. don't try to write DX9 compatible DDS files)
160+
161+
DDS_FLAGS_FORCE_DX10_EXT_MISC2 = 0x20000,
162+
// DDS_FLAGS_FORCE_DX10_EXT including miscFlags2 information (result may not be compatible with D3DX10 or D3DX11)
138163
};
139164

140165
enum WIC_FLAGS
@@ -227,6 +252,8 @@ namespace DirectX
227252
uint8_t* GetPixels() const { return _memory; }
228253
size_t GetPixelsSize() const { return _size; }
229254

255+
bool IsAlphaAllOpaque() const;
256+
230257
private:
231258
size_t _nimages;
232259
size_t _size;

DirectXTex/DirectXTex.inl

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -189,6 +189,9 @@ inline bool HasAlpha( DXGI_FORMAT fmt )
189189
case DXGI_FORMAT_R8G8B8A8_SNORM:
190190
case DXGI_FORMAT_R8G8B8A8_SINT:
191191
case DXGI_FORMAT_A8_UNORM:
192+
case DXGI_FORMAT_BC1_TYPELESS:
193+
case DXGI_FORMAT_BC1_UNORM:
194+
case DXGI_FORMAT_BC1_UNORM_SRGB:
192195
case DXGI_FORMAT_BC2_TYPELESS:
193196
case DXGI_FORMAT_BC2_UNORM:
194197
case DXGI_FORMAT_BC2_UNORM_SRGB:

DirectXTex/DirectXTexCompress.cpp

Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -426,6 +426,85 @@ static HRESULT _DecompressBC( _In_ const Image& cImage, _In_ const Image& result
426426
}
427427

428428

429+
//-------------------------------------------------------------------------------------
430+
bool _IsAlphaAllOpaqueBC( _In_ const Image& cImage )
431+
{
432+
if ( !cImage.pixels )
433+
return false;
434+
435+
// Image must be a multiple of 4 (degenerate cases of 1x1, 1x2, 2x1, and 2x2 are allowed)
436+
size_t width = cImage.width;
437+
if ( (width % 4) != 0 )
438+
{
439+
if ( width != 1 && width != 2 )
440+
return false;
441+
}
442+
443+
size_t height = cImage.height;
444+
if ( (height % 4) != 0 )
445+
{
446+
if ( height != 1 && height != 2 )
447+
return false;
448+
}
449+
450+
// Promote "typeless" BC formats
451+
DXGI_FORMAT cformat;
452+
switch( cImage.format )
453+
{
454+
case DXGI_FORMAT_BC1_TYPELESS: cformat = DXGI_FORMAT_BC1_UNORM; break;
455+
case DXGI_FORMAT_BC2_TYPELESS: cformat = DXGI_FORMAT_BC2_UNORM; break;
456+
case DXGI_FORMAT_BC3_TYPELESS: cformat = DXGI_FORMAT_BC3_UNORM; break;
457+
case DXGI_FORMAT_BC7_TYPELESS: cformat = DXGI_FORMAT_BC7_UNORM; break;
458+
default: cformat = cImage.format; break;
459+
}
460+
461+
// Determine BC format decoder
462+
BC_DECODE pfDecode;
463+
size_t sbpp;
464+
switch(cformat)
465+
{
466+
case DXGI_FORMAT_BC1_UNORM:
467+
case DXGI_FORMAT_BC1_UNORM_SRGB: pfDecode = D3DXDecodeBC1; sbpp = 8; break;
468+
case DXGI_FORMAT_BC2_UNORM:
469+
case DXGI_FORMAT_BC2_UNORM_SRGB: pfDecode = D3DXDecodeBC2; sbpp = 16; break;
470+
case DXGI_FORMAT_BC3_UNORM:
471+
case DXGI_FORMAT_BC3_UNORM_SRGB: pfDecode = D3DXDecodeBC3; sbpp = 16; break;
472+
case DXGI_FORMAT_BC7_UNORM:
473+
case DXGI_FORMAT_BC7_UNORM_SRGB: pfDecode = D3DXDecodeBC7; sbpp = 16; break;
474+
default:
475+
// BC4, BC5, and BC6 don't have alpha channels
476+
return false;
477+
}
478+
479+
// Scan blocks for non-opaque alpha
480+
static const XMVECTORF32 threshold = { 0.99f, 0.99f, 0.99f, 0.99f };
481+
482+
XMVECTOR temp[16];
483+
const uint8_t *pPixels = cImage.pixels;
484+
for( size_t h=0; h < cImage.height; h += 4 )
485+
{
486+
const uint8_t *ptr = pPixels;
487+
for( size_t count = 0; count < cImage.rowPitch; count += sbpp )
488+
{
489+
pfDecode( temp, ptr );
490+
491+
for( size_t j = 0; j < 16; ++j )
492+
{
493+
XMVECTOR alpha = XMVectorSplatW( temp[j] );
494+
if ( XMVector4Less( alpha, threshold ) )
495+
return false;
496+
}
497+
498+
ptr += sbpp;
499+
}
500+
501+
pPixels += cImage.rowPitch;
502+
}
503+
504+
return true;
505+
}
506+
507+
429508
//=====================================================================================
430509
// Entry-points
431510
//=====================================================================================

DirectXTex/DirectXTexD3D11.cpp

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -236,7 +236,7 @@ bool IsSupportedTexture( ID3D11Device* pDevice, const TexMetadata& metadata )
236236
break;
237237

238238
case TEX_DIMENSION_TEXTURE2D:
239-
if ( metadata.miscFlags & TEX_MISC_TEXTURECUBE )
239+
if ( metadata.IsCubemap() )
240240
{
241241
if ( !(formatSupport & D3D11_FORMAT_SUPPORT_TEXTURECUBE) )
242242
return false;
@@ -505,7 +505,7 @@ HRESULT CreateTextureEx( ID3D11Device* pDevice, const Image* srcImages, size_t n
505505
desc.Usage = usage;
506506
desc.BindFlags = bindFlags;
507507
desc.CPUAccessFlags = cpuAccessFlags;
508-
if (metadata.miscFlags & TEX_MISC_TEXTURECUBE)
508+
if ( metadata.IsCubemap() )
509509
desc.MiscFlags = miscFlags | D3D11_RESOURCE_MISC_TEXTURECUBE;
510510
else
511511
desc.MiscFlags = miscFlags & ~D3D11_RESOURCE_MISC_TEXTURECUBE;
@@ -589,7 +589,7 @@ HRESULT CreateShaderResourceViewEx( ID3D11Device* pDevice, const Image* srcImage
589589
break;
590590

591591
case TEX_DIMENSION_TEXTURE2D:
592-
if ( metadata.miscFlags & TEX_MISC_TEXTURECUBE )
592+
if ( metadata.IsCubemap() )
593593
{
594594
if (metadata.arraySize > 6)
595595
{
@@ -685,6 +685,7 @@ HRESULT CaptureTexture( ID3D11Device* pDevice, ID3D11DeviceContext* pContext, ID
685685
mdata.arraySize = desc.ArraySize;
686686
mdata.mipLevels = desc.MipLevels;
687687
mdata.miscFlags = 0;
688+
mdata.miscFlags2 = 0;
688689
mdata.format = desc.Format;
689690
mdata.dimension = TEX_DIMENSION_TEXTURE1D;
690691

@@ -786,6 +787,7 @@ HRESULT CaptureTexture( ID3D11Device* pDevice, ID3D11DeviceContext* pContext, ID
786787
mdata.arraySize = desc.ArraySize;
787788
mdata.mipLevels = desc.MipLevels;
788789
mdata.miscFlags = (desc.MiscFlags & D3D11_RESOURCE_MISC_TEXTURECUBE) ? TEX_MISC_TEXTURECUBE : 0;
790+
mdata.miscFlags2 = 0;
789791
mdata.format = desc.Format;
790792
mdata.dimension = TEX_DIMENSION_TEXTURE2D;
791793

@@ -830,6 +832,7 @@ HRESULT CaptureTexture( ID3D11Device* pDevice, ID3D11DeviceContext* pContext, ID
830832
mdata.arraySize = 1;
831833
mdata.mipLevels = desc.MipLevels;
832834
mdata.miscFlags = 0;
835+
mdata.miscFlags2 = 0;
833836
mdata.format = desc.Format;
834837
mdata.dimension = TEX_DIMENSION_TEXTURE3D;
835838

0 commit comments

Comments
 (0)