static bool get_tex2d_desc(const dds_hdr* dhdr, int* w, int* h, int* mips, base::pixelfmt* pixfmt) { if(dhdr->_magic != DDS_MAGIC) throw base::exception("Bad magic number in DDS file!"); const DDSURFACEDESC2 *hdr = &dhdr->_ddsd; const DDPIXELFORMAT &ddpf = hdr->ddpfPixelFormat; // fill other stuff in desc *w = hdr->dwWidth; *h = hdr->dwHeight; *mips = hdr->dwMipMapCount>1 ? hdr->dwMipMapCount : 1U; // find pixel format *pixfmt = base::PF_UNKNOWN; if( ddpf.dwFlags & DDPF_RGB ) { if( 32==ddpf.dwRGBBitCount ) { if( ISBITMASK(0x00ff0000,0x0000ff00,0x000000ff,0xff000000) ) *pixfmt = base::PF_BGRA8; if( ISBITMASK(0x000000ff,0x0000ff00,0x00ff0000,0xff000000) ) *pixfmt = base::PF_RGBA8; } } else if( ddpf.dwFlags & DDPF_FOURCC ) { if( MAKEFOURCC('D','X','T','1')==ddpf.dwFourCC ) *pixfmt = base::PF_DXT1; else if( MAKEFOURCC('D','X','T','3')==ddpf.dwFourCC ) *pixfmt = base::PF_DXT3; else if( MAKEFOURCC('D','X','T','5')==ddpf.dwFourCC ) *pixfmt = base::PF_DXT5; else if( MAKEFOURCC(114,0,0,0)==ddpf.dwFourCC ) *pixfmt = base::PF_R32F; else if( MAKEFOURCC(115,0,0,0)==ddpf.dwFourCC ) *pixfmt = base::PF_RG32F; else if( MAKEFOURCC(116,0,0,0)==ddpf.dwFourCC ) *pixfmt = base::PF_RGBA32F; else if( MAKEFOURCC('D','X','1','0')==ddpf.dwFourCC ) return false; } else if( ddpf.dwFlags & DDPF_LUMINANCE ) { if( ddpf.dwRGBBitCount==8 ) { *pixfmt = base::PF_R8; } } else return false; return true; }
//-------------------------------------------------------------------------- static VeRenderResource::Format GetDXGIFormat( const DDS_PIXELFORMAT& ddpf) noexcept { if (ddpf.m_u32Flags & DDS_RGB) { switch (ddpf.m_u32RGBBitCount) { case 32: if (ISBITMASK(0x000000ff, 0x0000ff00, 0x00ff0000, 0xff000000)) { return VeRenderResource::FORMAT_R8G8B8A8_UNORM; } if (ISBITMASK(0x00ff0000, 0x0000ff00, 0x000000ff, 0xff000000)) { return VeRenderResource::FORMAT_B8G8R8A8_UNORM; } if (ISBITMASK(0x00ff0000, 0x0000ff00, 0x000000ff, 0x00000000)) { return VeRenderResource::FORMAT_B8G8R8X8_UNORM; } if (ISBITMASK(0x3ff00000, 0x000ffc00, 0x000003ff, 0xc0000000)) { return VeRenderResource::FORMAT_R10G10B10A2_UNORM; } if (ISBITMASK(0x0000ffff, 0xffff0000, 0x00000000, 0x00000000)) { return VeRenderResource::FORMAT_R16G16_UNORM; } if (ISBITMASK(0xffffffff, 0x00000000, 0x00000000, 0x00000000)) { return VeRenderResource::FORMAT_R32_FLOAT; } break; case 24: break; case 16: if (ISBITMASK(0x7c00, 0x03e0, 0x001f, 0x8000)) { return VeRenderResource::FORMAT_B5G5R5A1_UNORM; } if (ISBITMASK(0xf800, 0x07e0, 0x001f, 0x0000)) { return VeRenderResource::FORMAT_B5G6R5_UNORM; } if (ISBITMASK(0x0f00, 0x00f0, 0x000f, 0xf000)) { return VeRenderResource::FORMAT_B4G4R4A4_UNORM; } break; } } else if (ddpf.m_u32Flags & DDS_LUMINANCE) { if (8 == ddpf.m_u32RGBBitCount) { if (ISBITMASK(0x000000ff, 0x00000000, 0x00000000, 0x00000000)) { return VeRenderResource::FORMAT_R8_UNORM; } } if (16 == ddpf.m_u32RGBBitCount) { if (ISBITMASK(0x0000ffff, 0x00000000, 0x00000000, 0x00000000)) { return VeRenderResource::FORMAT_R16_UNORM; } if (ISBITMASK(0x000000ff, 0x00000000, 0x00000000, 0x0000ff00)) { return VeRenderResource::FORMAT_R8G8_UNORM; } } } else if (ddpf.m_u32Flags & DDS_ALPHA) { if (8 == ddpf.m_u32RGBBitCount) { return VeRenderResource::FORMAT_A8_UNORM; } } else if (ddpf.m_u32Flags & DDS_FOURCC) { if (VE_FOURCC('D', 'X', 'T', '1') == ddpf.m_u32FourCC) { return VeRenderResource::FORMAT_BC1_UNORM; } if (VE_FOURCC('D', 'X', 'T', '3') == ddpf.m_u32FourCC) { return VeRenderResource::FORMAT_BC2_UNORM; } if (VE_FOURCC('D', 'X', 'T', '5') == ddpf.m_u32FourCC) { return VeRenderResource::FORMAT_BC3_UNORM; } if (VE_FOURCC('D', 'X', 'T', '2') == ddpf.m_u32FourCC) { return VeRenderResource::FORMAT_BC2_UNORM; } if (VE_FOURCC('D', 'X', 'T', '4') == ddpf.m_u32FourCC) { return VeRenderResource::FORMAT_BC3_UNORM; } if (VE_FOURCC('A', 'T', 'I', '1') == ddpf.m_u32FourCC) { return VeRenderResource::FORMAT_BC4_UNORM; } if (VE_FOURCC('B', 'C', '4', 'U') == ddpf.m_u32FourCC) { return VeRenderResource::FORMAT_BC4_UNORM; } if (VE_FOURCC('B', 'C', '4', 'S') == ddpf.m_u32FourCC) { return VeRenderResource::FORMAT_BC4_SNORM; } if (VE_FOURCC('A', 'T', 'I', '2') == ddpf.m_u32FourCC) { return VeRenderResource::FORMAT_BC5_UNORM; } if (VE_FOURCC('B', 'C', '5', 'U') == ddpf.m_u32FourCC) { return VeRenderResource::FORMAT_BC5_UNORM; } if (VE_FOURCC('B', 'C', '5', 'S') == ddpf.m_u32FourCC) { return VeRenderResource::FORMAT_BC5_SNORM; } if (VE_FOURCC('R', 'G', 'B', 'G') == ddpf.m_u32FourCC) { return VeRenderResource::FORMAT_R8G8_B8G8_UNORM; } if (VE_FOURCC('G', 'R', 'G', 'B') == ddpf.m_u32FourCC) { return VeRenderResource::FORMAT_G8R8_G8B8_UNORM; } if (VE_FOURCC('Y', 'U', 'Y', '2') == ddpf.m_u32FourCC) { return VeRenderResource::FORMAT_YUY2; } switch (ddpf.m_u32FourCC) { case 36: // D3DFMT_A16B16G16R16 return VeRenderResource::FORMAT_R16G16B16A16_UNORM; case 110: // D3DFMT_Q16W16V16U16 return VeRenderResource::FORMAT_R16G16B16A16_SNORM; case 111: // D3DFMT_R16F return VeRenderResource::FORMAT_R16_FLOAT; case 112: // D3DFMT_G16R16F return VeRenderResource::FORMAT_R16G16_FLOAT; case 113: // D3DFMT_A16B16G16R16F return VeRenderResource::FORMAT_R16G16B16A16_FLOAT; case 114: // D3DFMT_R32F return VeRenderResource::FORMAT_R32_FLOAT; case 115: // D3DFMT_G32R32F return VeRenderResource::FORMAT_R32G32_FLOAT; case 116: // D3DFMT_A32B32G32R32F return VeRenderResource::FORMAT_R32G32B32A32_FLOAT; } } return VeRenderResource::FORMAT_UNKNOWN; }
//-------------------------------------------------------------------------------------- DXGI_FORMAT GetDXGIFormat( const DDS_PIXELFORMAT& ddpf ) { if( ddpf.dwFlags & DDS_RGB ) { switch (ddpf.dwRGBBitCount) { case 32: // DXGI_FORMAT_B8G8R8A8_UNORM_SRGB & DXGI_FORMAT_B8G8R8X8_UNORM_SRGB should be // written using the DX10 extended header instead since these formats require // DXGI 1.1 // // This code will use the fallback to swizzle RGB to BGR in memory for standard // DDS files which works on 10 and 10.1 devices with WDDM 1.0 drivers if( ISBITMASK(0x000000ff,0x0000ff00,0x00ff0000,0xff000000) ) return DXGI_FORMAT_R8G8B8A8_UNORM; if( ISBITMASK(0x000000ff,0x0000ff00,0x00ff0000,0x00000000) ) return DXGI_FORMAT_R8G8B8A8_UNORM; if( ISBITMASK(0xffffffff,0x00000000,0x00000000,0x00000000) ) // Only 32-bit color channel format in D3D9 was R32F return DXGI_FORMAT_R32_FLOAT; break; case 24: // No 24bpp DXGI formats break; case 16: if( ISBITMASK(0x0000f800,0x000007e0,0x0000001f,0x00000000) ) return DXGI_FORMAT_B5G6R5_UNORM; if( ISBITMASK(0x00007c00,0x000003e0,0x0000001f,0x00008000) ) return DXGI_FORMAT_B5G5R5A1_UNORM; // No 4bpp DXGI formats break; } } else if( ddpf.dwFlags & DDS_LUMINANCE ) { if( 8 == ddpf.dwRGBBitCount ) { return DXGI_FORMAT_R8_UNORM; } if( 16 == ddpf.dwRGBBitCount ) { if( ISBITMASK(0x000000ff,0x00000000,0x00000000,0x0000ff00) ) return DXGI_FORMAT_R8G8_UNORM; } } else if( ddpf.dwFlags & DDS_ALPHA ) { if( 8 == ddpf.dwRGBBitCount ) { return DXGI_FORMAT_A8_UNORM; } } else if( ddpf.dwFlags & DDS_FOURCC ) { if( MAKEFOURCC( 'D', 'X', 'T', '1' ) == ddpf.dwFourCC ) return DXGI_FORMAT_BC1_UNORM; if( MAKEFOURCC( 'D', 'X', 'T', '2' ) == ddpf.dwFourCC ) return DXGI_FORMAT_BC1_UNORM; if( MAKEFOURCC( 'D', 'X', 'T', '3' ) == ddpf.dwFourCC ) return DXGI_FORMAT_BC2_UNORM; if( MAKEFOURCC( 'D', 'X', 'T', '4' ) == ddpf.dwFourCC ) return DXGI_FORMAT_BC2_UNORM; if( MAKEFOURCC( 'D', 'X', 'T', '5' ) == ddpf.dwFourCC ) return DXGI_FORMAT_BC3_UNORM_SRGB; // Check for D3DFORMAT enums being set here switch( ddpf.dwFourCC ) { case D3DFMT_R16F: return DXGI_FORMAT_R16_FLOAT; case D3DFMT_G16R16F: return DXGI_FORMAT_R16G16_FLOAT; case D3DFMT_A16B16G16R16F: return DXGI_FORMAT_R16G16B16A16_FLOAT; case D3DFMT_R32F: return DXGI_FORMAT_R32_FLOAT; case D3DFMT_G32R32F: return DXGI_FORMAT_R32G32_FLOAT; case D3DFMT_A32B32G32R32F: return DXGI_FORMAT_R32G32B32A32_FLOAT; } } return DXGI_FORMAT_UNKNOWN; }
static DXGI_FORMAT GetDXGIFormat(DDS_PIXELFORMAT ddpf) { if (ddpf.flags & DDS_RGB) { // Note that sRGB formats are written using the "DX10" extended header switch (ddpf.RGBBitCount) { case 32: if( ISBITMASK(0x000000ff, 0x0000ff00, 0x00ff0000, 0xff000000) ) return DXGI_FORMAT_R8G8B8A8_UNORM; if( ISBITMASK(0x00ff0000, 0x0000ff00, 0x000000ff, 0xff000000) ) return DXGI_FORMAT_B8G8R8A8_UNORM; if( ISBITMASK(0x00ff0000, 0x0000ff00, 0x000000ff, 0x00000000) ) return DXGI_FORMAT_B8G8R8X8_UNORM; // No DXGI format maps to ISBITMASK(0x000000ff, 0x0000ff00, 0x00ff0000, 0x00000000) aka D3DFMT_X8B8G8R8 // Note that many common DDS reader/writers (including D3DX) swap the // the RED/BLUE masks for 10:10:10:2 formats. We assumme // below that the 'backwards' header mask is being used since it is most // likely written by D3DX. The more robust solution is to use the 'DX10' // header extension and specify the DXGI_FORMAT_R10G10B10A2_UNORM format directly // For 'correct' writers, this should be 0x000003ff, 0x000ffc00, 0x3ff00000 for RGB data if( ISBITMASK(0x3ff00000, 0x000ffc00, 0x000003ff, 0xc0000000) ) return DXGI_FORMAT_R10G10B10A2_UNORM; // No DXGI format maps to ISBITMASK(0x000003ff, 0x000ffc00, 0x3ff00000, 0xc0000000) aka D3DFMT_A2R10G10B10 if( ISBITMASK(0x0000ffff, 0xffff0000, 0x00000000, 0x00000000) ) return DXGI_FORMAT_R16G16_UNORM; if( ISBITMASK(0xffffffff, 0x00000000, 0x00000000, 0x00000000) ) { // Only 32-bit color channel format in D3D9 was R32F return DXGI_FORMAT_R32_FLOAT; // D3DX writes this out as a FourCC of 114 } break; case 24: // No 24bpp DXGI formats aka D3DFMT_R8G8B8 break; case 16: if( ISBITMASK(0x7c00, 0x03e0, 0x001f, 0x8000) ) return DXGI_FORMAT_B5G5R5A1_UNORM; if( ISBITMASK(0xf800, 0x07e0, 0x001f, 0x0000) ) return DXGI_FORMAT_B5G6R5_UNORM; // No DXGI format maps to ISBITMASK(0x7c00, 0x03e0, 0x001f, 0x0000) aka D3DFMT_X1R5G5B5 if( ISBITMASK(0x0f00, 0x00f0, 0x000f, 0xf000) ) return DXGI_FORMAT_B4G4R4A4_UNORM; // No DXGI format maps to ISBITMASK(0x0f00, 0x00f0, 0x000f, 0x0000) aka D3DFMT_X4R4G4B4 // No 3:3:2, 3:3:2:8, or paletted DXGI formats aka D3DFMT_A8R3G3B2, D3DFMT_R3G3B2, D3DFMT_P8, D3DFMT_A8P8, etc. break; } } else if (ddpf.flags & DDS_LUMINANCE) { if (8 == ddpf.RGBBitCount) { if( ISBITMASK(0x000000ff, 0x00000000, 0x00000000, 0x00000000) ) return DXGI_FORMAT_R8_UNORM; // D3DX10/11 writes this out as DX10 extension // No DXGI format maps to ISBITMASK(0x0f, 0x00, 0x00, 0xf0) aka D3DFMT_A4L4 } if (16 == ddpf.RGBBitCount) { if( ISBITMASK(0x0000ffff, 0x00000000, 0x00000000, 0x00000000) ) return DXGI_FORMAT_R16_UNORM; // D3DX10/11 writes this out as DX10 extension if( ISBITMASK(0x000000ff, 0x00000000, 0x00000000, 0x0000ff00) ) return DXGI_FORMAT_R8G8_UNORM; // D3DX10/11 writes this out as DX10 extension } } else if (ddpf.flags & DDS_ALPHA) { if (8 == ddpf.RGBBitCount) { return DXGI_FORMAT_A8_UNORM; } } else if (ddpf.flags & DDS_FOURCC) { if( MAKEFOURCC('D', 'X', 'T', '1') == ddpf.fourCC ) return DXGI_FORMAT_BC1_UNORM; if( MAKEFOURCC('D', 'X', 'T', '3') == ddpf.fourCC ) return DXGI_FORMAT_BC2_UNORM; if( MAKEFOURCC('D', 'X', 'T', '5') == ddpf.fourCC ) return DXGI_FORMAT_BC3_UNORM; // While pre-mulitplied alpha isn't directly supported by the DXGI formats, // they are basically the same as these BC formats so they can be mapped if( MAKEFOURCC('D', 'X', 'T', '2') == ddpf.fourCC ) return DXGI_FORMAT_BC2_UNORM; if( MAKEFOURCC('D', 'X', 'T', '4') == ddpf.fourCC ) return DXGI_FORMAT_BC3_UNORM; if( MAKEFOURCC('A', 'T', 'I', '1') == ddpf.fourCC ) return DXGI_FORMAT_BC4_UNORM; if( MAKEFOURCC('B', 'C', '4', 'U') == ddpf.fourCC ) return DXGI_FORMAT_BC4_UNORM; if( MAKEFOURCC('B', 'C', '4', 'S') == ddpf.fourCC ) return DXGI_FORMAT_BC4_SNORM; if( MAKEFOURCC('A', 'T', 'I', '2') == ddpf.fourCC ) return DXGI_FORMAT_BC5_UNORM; if( MAKEFOURCC('B', 'C', '5', 'U') == ddpf.fourCC ) return DXGI_FORMAT_BC5_UNORM; if( MAKEFOURCC('B', 'C', '5', 'S') == ddpf.fourCC ) return DXGI_FORMAT_BC5_SNORM; // BC6H and BC7 are written using the "DX10" extended header if( MAKEFOURCC('R', 'G', 'B', 'G') == ddpf.fourCC ) return DXGI_FORMAT_R8G8_B8G8_UNORM; if( MAKEFOURCC('G', 'R', 'G', 'B') == ddpf.fourCC ) return DXGI_FORMAT_G8R8_G8B8_UNORM; // Check for D3DFORMAT enums being set here switch (ddpf.fourCC) { case 36: // D3DFMT_A16B16G16R16 return DXGI_FORMAT_R16G16B16A16_UNORM; case 110: // D3DFMT_Q16W16V16U16 return DXGI_FORMAT_R16G16B16A16_SNORM; case 111: // D3DFMT_R16F return DXGI_FORMAT_R16_FLOAT; case 112: // D3DFMT_G16R16F return DXGI_FORMAT_R16G16_FLOAT; case 113: // D3DFMT_A16B16G16R16F return DXGI_FORMAT_R16G16B16A16_FLOAT; case 114: // D3DFMT_R32F return DXGI_FORMAT_R32_FLOAT; case 115: // D3DFMT_G32R32F return DXGI_FORMAT_R32G32_FLOAT; case 116: // D3DFMT_A32B32G32R32F return DXGI_FORMAT_R32G32B32A32_FLOAT; } } return DXGI_FORMAT_UNKNOWN; }
//-------------------------------------------------------------------------------------- D3DFORMAT GetD3D9Format( const DDS_PIXELFORMAT& ddpf ) { if( ddpf.dwFlags & DDS_RGB ) { switch (ddpf.dwRGBBitCount) { case 32: if( ISBITMASK(0x00ff0000,0x0000ff00,0x000000ff,0xff000000) ) return D3DFMT_A8R8G8B8; if( ISBITMASK(0x00ff0000,0x0000ff00,0x000000ff,0x00000000) ) return D3DFMT_X8R8G8B8; if( ISBITMASK(0x000000ff,0x0000ff00,0x00ff0000,0xff000000) ) return D3DFMT_A8B8G8R8; if( ISBITMASK(0x000000ff,0x0000ff00,0x00ff0000,0x00000000) ) return D3DFMT_X8B8G8R8; if( ISBITMASK(0xffffffff,0x00000000,0x00000000,0x00000000) ) return D3DFMT_R32F; break; case 24: if( ISBITMASK(0x00ff0000,0x0000ff00,0x000000ff,0x00000000) ) return D3DFMT_R8G8B8; break; case 16: if( ISBITMASK(0x0000f800,0x000007e0,0x0000001f,0x00000000) ) return D3DFMT_R5G6B5; if( ISBITMASK(0x00007c00,0x000003e0,0x0000001f,0x00008000) ) return D3DFMT_A1R5G5B5; if( ISBITMASK(0x00000f00,0x000000f0,0x0000000f,0x0000f000) ) return D3DFMT_A4R4G4B4; break; } } else if( ddpf.dwFlags & DDS_LUMINANCE ) { if( 8 == ddpf.dwRGBBitCount ) { return D3DFMT_L8; } if( 16 == ddpf.dwRGBBitCount ) { if( ISBITMASK(0x000000ff,0x00000000,0x00000000,0x0000ff00) ) return D3DFMT_A8L8; } } else if( ddpf.dwFlags & DDS_ALPHA ) { if( 8 == ddpf.dwRGBBitCount ) { return D3DFMT_A8; } } else if( ddpf.dwFlags & DDS_FOURCC ) { if( MAKEFOURCC( 'D', 'X', 'T', '1' ) == ddpf.dwFourCC ) return D3DFMT_DXT1; if( MAKEFOURCC( 'D', 'X', 'T', '2' ) == ddpf.dwFourCC ) return D3DFMT_DXT2; if( MAKEFOURCC( 'D', 'X', 'T', '3' ) == ddpf.dwFourCC ) return D3DFMT_DXT3; if( MAKEFOURCC( 'D', 'X', 'T', '4' ) == ddpf.dwFourCC ) return D3DFMT_DXT4; if( MAKEFOURCC( 'D', 'X', 'T', '5' ) == ddpf.dwFourCC ) return D3DFMT_DXT5; // Check for D3DFORMAT enums being set here switch( ddpf.dwFourCC ) { case D3DFMT_R16F: case D3DFMT_G16R16F: case D3DFMT_A16B16G16R16F: case D3DFMT_R32F: case D3DFMT_G32R32F: case D3DFMT_A32B32G32R32F: return (D3DFORMAT)ddpf.dwFourCC; } } return D3DFMT_UNKNOWN; }