diff options
author | Paul Lemire <paul.lemire@kdab.com> | 2016-05-19 17:15:51 +0200 |
---|---|---|
committer | Paul Lemire <paul.lemire@kdab.com> | 2016-05-20 12:16:34 +0000 |
commit | 2fc9cba25793170faa81c10c531c7d2ec1b3a382 (patch) | |
tree | 9deaa20c6db4a5e24875df88ecaab75770557c88 /src | |
parent | a2999182a07a94ee6124de8e970596002e5e9078 (diff) |
QTexture: cleanup
Load compressed files in QFromSourceTextureGenerator
and remove related code from QTextureImageData. Unify
loading code paths for texture generator and image.
Change-Id: Iebeb67bf1e542f55af06880b1d725c2de70b8ccb
Reviewed-by: Sean Harmer <sean.harmer@kdab.com>
Diffstat (limited to 'src')
-rw-r--r-- | src/render/jobs/loadtexturedatajob.cpp | 2 | ||||
-rw-r--r-- | src/render/texture/qtexture.cpp | 676 | ||||
-rw-r--r-- | src/render/texture/qtexture_p.h | 6 | ||||
-rw-r--r-- | src/render/texture/qtextureimage.cpp | 20 | ||||
-rw-r--r-- | src/render/texture/qtextureimage_p.h | 41 | ||||
-rw-r--r-- | src/render/texture/qtextureimagedata.cpp | 645 | ||||
-rw-r--r-- | src/render/texture/qtextureimagedata.h | 30 | ||||
-rw-r--r-- | src/render/texture/qtextureimagedata_p.h | 3 | ||||
-rw-r--r-- | src/render/texture/texture.cpp | 3 |
9 files changed, 756 insertions, 670 deletions
diff --git a/src/render/jobs/loadtexturedatajob.cpp b/src/render/jobs/loadtexturedatajob.cpp index 65bcd70bc..d8243f1d0 100644 --- a/src/render/jobs/loadtexturedatajob.cpp +++ b/src/render/jobs/loadtexturedatajob.cpp @@ -103,11 +103,9 @@ void createTextureFromGenerator(TextureDataManager *textureDataManager, qWarning() << "When a texture provides a generator, it's target is expected to be TargetAutomatic"; texture->setTarget(static_cast<QAbstractTexture::Target>(generatedData->target())); - texture->setSize(generatedData->width(), generatedData->height(), generatedData->depth()); texture->setLayers(generatedData->layers()); texture->setFormat(generatedData->format()); - texture->setFormat(static_cast<QAbstractTexture::TextureFormat>(generatedData->format())); // Note: These texture data handles aren't associated with a QTextureImageDataGenerator // and will therefore be destroyed when the Texture element is destroyed or cleaned up diff --git a/src/render/texture/qtexture.cpp b/src/render/texture/qtexture.cpp index c2f243f57..9ffb10a88 100644 --- a/src/render/texture/qtexture.cpp +++ b/src/render/texture/qtexture.cpp @@ -43,11 +43,637 @@ #include "qtexturedata.h" #include "qtexture.h" #include "qtexture_p.h" +#include <QFileInfo> +#include <qendian.h> QT_BEGIN_NAMESPACE namespace Qt3DRender { +namespace { + +struct DdsPixelFormat +{ + quint32 size; + quint32 flags; + quint32 fourCC; + quint32 rgbBitCount; + quint32 redMask; + quint32 greenMask; + quint32 blueMask; + quint32 alphaMask; +}; + +struct DdsHeader +{ + char magic[4]; + quint32 size; + quint32 flags; + quint32 height; + quint32 width; + quint32 pitchOrLinearSize; + quint32 depth; + quint32 mipmapCount; + quint32 reserved[11]; + DdsPixelFormat pixelFormat; + quint32 caps; + quint32 caps2; + quint32 caps3; + quint32 caps4; + quint32 reserved2; +}; + +struct DdsDX10Header +{ + quint32 format; + quint32 dimension; + quint32 miscFlag; + quint32 arraySize; + quint32 miscFlags2; +}; + +enum DdsFlags +{ + MipmapCountFlag = 0x20000, +}; + +enum PixelFormatFlag +{ + AlphaFlag = 0x1, + FourCCFlag = 0x4, + RGBFlag = 0x40, + RGBAFlag = RGBFlag | AlphaFlag, + YUVFlag = 0x200, + LuminanceFlag = 0x20000 +}; + +enum Caps2Flags +{ + CubemapFlag = 0x200, + CubemapPositiveXFlag = 0x400, + CubemapNegativeXFlag = 0x800, + CubemapPositiveYFlag = 0x1000, + CubemapNegativeYFlag = 0x2000, + CubemapPositiveZFlag = 0x4000, + CubemapNegativeZFlag = 0x8000, + AllCubemapFaceFlags = CubemapPositiveXFlag | + CubemapNegativeXFlag | + CubemapPositiveYFlag | + CubemapNegativeYFlag | + CubemapPositiveZFlag | + CubemapNegativeZFlag, + VolumeFlag = 0x200000 +}; + +enum DXGIFormat +{ + DXGI_FORMAT_UNKNOWN = 0, + DXGI_FORMAT_R32G32B32A32_TYPELESS = 1, + DXGI_FORMAT_R32G32B32A32_FLOAT = 2, + DXGI_FORMAT_R32G32B32A32_UINT = 3, + DXGI_FORMAT_R32G32B32A32_SINT = 4, + DXGI_FORMAT_R32G32B32_TYPELESS = 5, + DXGI_FORMAT_R32G32B32_FLOAT = 6, + DXGI_FORMAT_R32G32B32_UINT = 7, + DXGI_FORMAT_R32G32B32_SINT = 8, + DXGI_FORMAT_R16G16B16A16_TYPELESS = 9, + DXGI_FORMAT_R16G16B16A16_FLOAT = 10, + DXGI_FORMAT_R16G16B16A16_UNORM = 11, + DXGI_FORMAT_R16G16B16A16_UINT = 12, + DXGI_FORMAT_R16G16B16A16_SNORM = 13, + DXGI_FORMAT_R16G16B16A16_SINT = 14, + DXGI_FORMAT_R32G32_TYPELESS = 15, + DXGI_FORMAT_R32G32_FLOAT = 16, + DXGI_FORMAT_R32G32_UINT = 17, + DXGI_FORMAT_R32G32_SINT = 18, + DXGI_FORMAT_R32G8X24_TYPELESS = 19, + DXGI_FORMAT_D32_FLOAT_S8X24_UINT = 20, + DXGI_FORMAT_R32_FLOAT_X8X24_TYPELESS = 21, + DXGI_FORMAT_X32_TYPELESS_G8X24_UINT = 22, + DXGI_FORMAT_R10G10B10A2_TYPELESS = 23, + DXGI_FORMAT_R10G10B10A2_UNORM = 24, + DXGI_FORMAT_R10G10B10A2_UINT = 25, + DXGI_FORMAT_R11G11B10_FLOAT = 26, + DXGI_FORMAT_R8G8B8A8_TYPELESS = 27, + DXGI_FORMAT_R8G8B8A8_UNORM = 28, + DXGI_FORMAT_R8G8B8A8_UNORM_SRGB = 29, + DXGI_FORMAT_R8G8B8A8_UINT = 30, + DXGI_FORMAT_R8G8B8A8_SNORM = 31, + DXGI_FORMAT_R8G8B8A8_SINT = 32, + DXGI_FORMAT_R16G16_TYPELESS = 33, + DXGI_FORMAT_R16G16_FLOAT = 34, + DXGI_FORMAT_R16G16_UNORM = 35, + DXGI_FORMAT_R16G16_UINT = 36, + DXGI_FORMAT_R16G16_SNORM = 37, + DXGI_FORMAT_R16G16_SINT = 38, + DXGI_FORMAT_R32_TYPELESS = 39, + DXGI_FORMAT_D32_FLOAT = 40, + DXGI_FORMAT_R32_FLOAT = 41, + DXGI_FORMAT_R32_UINT = 42, + DXGI_FORMAT_R32_SINT = 43, + DXGI_FORMAT_R24G8_TYPELESS = 44, + DXGI_FORMAT_D24_UNORM_S8_UINT = 45, + DXGI_FORMAT_R24_UNORM_X8_TYPELESS = 46, + DXGI_FORMAT_X24_TYPELESS_G8_UINT = 47, + DXGI_FORMAT_R8G8_TYPELESS = 48, + DXGI_FORMAT_R8G8_UNORM = 49, + DXGI_FORMAT_R8G8_UINT = 50, + DXGI_FORMAT_R8G8_SNORM = 51, + DXGI_FORMAT_R8G8_SINT = 52, + DXGI_FORMAT_R16_TYPELESS = 53, + DXGI_FORMAT_R16_FLOAT = 54, + DXGI_FORMAT_D16_UNORM = 55, + DXGI_FORMAT_R16_UNORM = 56, + DXGI_FORMAT_R16_UINT = 57, + DXGI_FORMAT_R16_SNORM = 58, + DXGI_FORMAT_R16_SINT = 59, + DXGI_FORMAT_R8_TYPELESS = 60, + DXGI_FORMAT_R8_UNORM = 61, + DXGI_FORMAT_R8_UINT = 62, + DXGI_FORMAT_R8_SNORM = 63, + DXGI_FORMAT_R8_SINT = 64, + DXGI_FORMAT_A8_UNORM = 65, + DXGI_FORMAT_R1_UNORM = 66, + DXGI_FORMAT_R9G9B9E5_SHAREDEXP = 67, + DXGI_FORMAT_R8G8_B8G8_UNORM = 68, + DXGI_FORMAT_G8R8_G8B8_UNORM = 69, + DXGI_FORMAT_BC1_TYPELESS = 70, + DXGI_FORMAT_BC1_UNORM = 71, + DXGI_FORMAT_BC1_UNORM_SRGB = 72, + DXGI_FORMAT_BC2_TYPELESS = 73, + DXGI_FORMAT_BC2_UNORM = 74, + DXGI_FORMAT_BC2_UNORM_SRGB = 75, + DXGI_FORMAT_BC3_TYPELESS = 76, + DXGI_FORMAT_BC3_UNORM = 77, + DXGI_FORMAT_BC3_UNORM_SRGB = 78, + DXGI_FORMAT_BC4_TYPELESS = 79, + DXGI_FORMAT_BC4_UNORM = 80, + DXGI_FORMAT_BC4_SNORM = 81, + DXGI_FORMAT_BC5_TYPELESS = 82, + DXGI_FORMAT_BC5_UNORM = 83, + DXGI_FORMAT_BC5_SNORM = 84, + DXGI_FORMAT_B5G6R5_UNORM = 85, + DXGI_FORMAT_B5G5R5A1_UNORM = 86, + DXGI_FORMAT_B8G8R8A8_UNORM = 87, + DXGI_FORMAT_B8G8R8X8_UNORM = 88, + DXGI_FORMAT_R10G10B10_XR_BIAS_A2_UNORM = 89, + DXGI_FORMAT_B8G8R8A8_TYPELESS = 90, + DXGI_FORMAT_B8G8R8A8_UNORM_SRGB = 91, + DXGI_FORMAT_B8G8R8X8_TYPELESS = 92, + DXGI_FORMAT_B8G8R8X8_UNORM_SRGB = 93, + DXGI_FORMAT_BC6H_TYPELESS = 94, + DXGI_FORMAT_BC6H_UF16 = 95, + DXGI_FORMAT_BC6H_SF16 = 96, + DXGI_FORMAT_BC7_TYPELESS = 97, + DXGI_FORMAT_BC7_UNORM = 98, + DXGI_FORMAT_BC7_UNORM_SRGB = 99, + DXGI_FORMAT_AYUV = 100, + DXGI_FORMAT_Y410 = 101, + DXGI_FORMAT_Y416 = 102, + DXGI_FORMAT_NV12 = 103, + DXGI_FORMAT_P010 = 104, + DXGI_FORMAT_P016 = 105, + DXGI_FORMAT_420_OPAQUE = 106, + DXGI_FORMAT_YUY2 = 107, + DXGI_FORMAT_Y210 = 108, + DXGI_FORMAT_Y216 = 109, + DXGI_FORMAT_NV11 = 110, + DXGI_FORMAT_AI44 = 111, + DXGI_FORMAT_IA44 = 112, + DXGI_FORMAT_P8 = 113, + DXGI_FORMAT_A8P8 = 114, + DXGI_FORMAT_B4G4R4A4_UNORM = 115, + DXGI_FORMAT_P208 = 130, + DXGI_FORMAT_V208 = 131, + DXGI_FORMAT_V408 = 132, +}; + +template <int a, int b, int c, int d> +struct DdsFourCC +{ + static const quint32 value = a | (b << 8) | (c << 16) | (d << 24); +}; + +struct FormatInfo +{ + QOpenGLTexture::PixelFormat pixelFormat; + QOpenGLTexture::TextureFormat textureFormat; + QOpenGLTexture::PixelType pixelType; + int components; + bool compressed; +}; + +const struct RGBAFormat +{ + quint32 redMask; + quint32 greenMask; + quint32 blueMask; + quint32 alphaMask; + FormatInfo formatInfo; + +} rgbaFormats[] = { + // unorm formats +{ 0x000000ff, 0x0000ff00, 0x00ff0000, 0xff000000, { QOpenGLTexture::RGBA, QOpenGLTexture::RGBA8_UNorm, QOpenGLTexture::UInt8, 4, false } }, +{ 0x00ff0000, 0x0000ff00, 0x000000ff, 0xff000000, { QOpenGLTexture::BGRA, QOpenGLTexture::RGBA8_UNorm, QOpenGLTexture::UInt8, 4, false } }, +{ 0x000000ff, 0x0000ff00, 0x00ff0000, 0x00000000, { QOpenGLTexture::RGBA, QOpenGLTexture::RGBA8_UNorm, QOpenGLTexture::UInt8, 4, false } }, +{ 0x00ff0000, 0x0000ff00, 0x000000ff, 0x00000000, { QOpenGLTexture::BGRA, QOpenGLTexture::RGBA8_UNorm, QOpenGLTexture::UInt8, 4, false } }, +{ 0x000000ff, 0x0000ff00, 0x00ff0000, 0x00000000, { QOpenGLTexture::RGB, QOpenGLTexture::RGB8_UNorm, QOpenGLTexture::UInt8, 3, false } }, +{ 0x00ff0000, 0x0000ff00, 0x000000ff, 0x00000000, { QOpenGLTexture::BGR, QOpenGLTexture::RGB8_UNorm, QOpenGLTexture::UInt8, 3, false } }, + +// packed formats +{ 0x0000f800, 0x000007e0, 0x0000001f, 0x00000000, { QOpenGLTexture::RGB, QOpenGLTexture::R5G6B5, QOpenGLTexture::UInt16_R5G6B5, 2, false } }, +{ 0x00007c00, 0x000003e0, 0x0000001f, 0x00008000, { QOpenGLTexture::RGBA, QOpenGLTexture::RGB5A1, QOpenGLTexture::UInt16_RGB5A1, 2, false } }, +{ 0x00000f00, 0x000000f0, 0x0000000f, 0x0000f000, { QOpenGLTexture::RGBA, QOpenGLTexture::RGBA4, QOpenGLTexture::UInt16_RGBA4, 2, false } }, +{ 0x000000e0, 0x0000001c, 0x00000003, 0x00000000, { QOpenGLTexture::RGB, QOpenGLTexture::RG3B2, QOpenGLTexture::UInt8_RG3B2, 1, false } }, +{ 0x3ff00000, 0x000ffc00, 0x000003ff, 0xc0000000, { QOpenGLTexture::RGBA, QOpenGLTexture::RGB10A2, QOpenGLTexture::UInt32_RGB10A2, 4, false } }, + +// luminance alpha +{ 0x000000ff, 0x000000ff, 0x000000ff, 0x00000000, { QOpenGLTexture::Red, QOpenGLTexture::R8_UNorm, QOpenGLTexture::UInt8, 1, false } }, +{ 0x000000ff, 0x00000000, 0x00000000, 0x00000000, { QOpenGLTexture::Red, QOpenGLTexture::R8_UNorm, QOpenGLTexture::UInt8, 1, false } }, +{ 0x000000ff, 0x000000ff, 0x000000ff, 0x0000ff00, { QOpenGLTexture::RG, QOpenGLTexture::RG8_UNorm, QOpenGLTexture::UInt8, 2, false } }, +{ 0x000000ff, 0x00000000, 0x00000000, 0x0000ff00, { QOpenGLTexture::RG, QOpenGLTexture::RG8_UNorm, QOpenGLTexture::UInt8, 2, false } }, +}; + +const struct FourCCFormat +{ + quint32 fourCC; + FormatInfo formatInfo; +} fourCCFormats[] = { +{ DdsFourCC<'D','X','T','1'>::value, { QOpenGLTexture::NoSourceFormat, QOpenGLTexture::RGBA_DXT1, QOpenGLTexture::NoPixelType, 8, true } }, +{ DdsFourCC<'D','X','T','3'>::value, { QOpenGLTexture::NoSourceFormat, QOpenGLTexture::RGBA_DXT3, QOpenGLTexture::NoPixelType, 16, true } }, +{ DdsFourCC<'D','X','T','5'>::value, { QOpenGLTexture::NoSourceFormat, QOpenGLTexture::RGBA_DXT5, QOpenGLTexture::NoPixelType, 16, true } }, +{ DdsFourCC<'A','T','I','1'>::value, { QOpenGLTexture::NoSourceFormat, QOpenGLTexture::R_ATI1N_UNorm, QOpenGLTexture::NoPixelType, 8, true } }, +{ DdsFourCC<'A','T','I','2'>::value, { QOpenGLTexture::NoSourceFormat, QOpenGLTexture::RG_ATI2N_UNorm, QOpenGLTexture::NoPixelType, 16, true } }, +}; + +const struct DX10Format +{ + DXGIFormat dxgiFormat; + FormatInfo formatInfo; +} dx10Formats[] = { + // unorm formats +{ DXGI_FORMAT_R8_UNORM, { QOpenGLTexture::Red, QOpenGLTexture::R8_UNorm, QOpenGLTexture::UInt8, 1, false } }, +{ DXGI_FORMAT_R8G8_UNORM, { QOpenGLTexture::RG, QOpenGLTexture::RG8_UNorm, QOpenGLTexture::UInt8, 2, false } }, +{ DXGI_FORMAT_R8G8B8A8_UNORM, { QOpenGLTexture::RGBA, QOpenGLTexture::RGBA8_UNorm, QOpenGLTexture::UInt8, 4, false } }, + +{ DXGI_FORMAT_R16_UNORM, { QOpenGLTexture::Red, QOpenGLTexture::R16_UNorm, QOpenGLTexture::UInt16, 2, false } }, +{ DXGI_FORMAT_R16G16_UNORM, { QOpenGLTexture::RG, QOpenGLTexture::RG16_UNorm, QOpenGLTexture::UInt16, 4, false } }, +{ DXGI_FORMAT_R16G16B16A16_UNORM, { QOpenGLTexture::RGBA, QOpenGLTexture::RGBA16_UNorm, QOpenGLTexture::UInt16, 8, false } }, + +// snorm formats +{ DXGI_FORMAT_R8_SNORM, { QOpenGLTexture::Red, QOpenGLTexture::R8_SNorm, QOpenGLTexture::Int8, 1, false } }, +{ DXGI_FORMAT_R8G8_SNORM, { QOpenGLTexture::RG, QOpenGLTexture::RG8_SNorm, QOpenGLTexture::Int8, 2, false } }, +{ DXGI_FORMAT_R8G8B8A8_SNORM, { QOpenGLTexture::RGBA, QOpenGLTexture::RGBA8_SNorm, QOpenGLTexture::Int8, 4, false } }, + +{ DXGI_FORMAT_R16_SNORM, { QOpenGLTexture::Red, QOpenGLTexture::R16_SNorm, QOpenGLTexture::Int16, 2, false } }, +{ DXGI_FORMAT_R16G16_SNORM, { QOpenGLTexture::RG, QOpenGLTexture::RG16_SNorm, QOpenGLTexture::Int16, 4, false } }, +{ DXGI_FORMAT_R16G16B16A16_SNORM, { QOpenGLTexture::RGBA, QOpenGLTexture::RGBA16_SNorm, QOpenGLTexture::Int16, 8, false } }, + +// unsigned integer formats +{ DXGI_FORMAT_R8_UINT, { QOpenGLTexture::Red_Integer, QOpenGLTexture::R8U, QOpenGLTexture::UInt8, 1, false } }, +{ DXGI_FORMAT_R8G8_UINT, { QOpenGLTexture::RG_Integer, QOpenGLTexture::RG8U, QOpenGLTexture::UInt8, 2, false } }, +{ DXGI_FORMAT_R8G8B8A8_UINT, { QOpenGLTexture::RGBA_Integer, QOpenGLTexture::RGBA8U, QOpenGLTexture::UInt8, 4, false } }, + +{ DXGI_FORMAT_R16_UINT, { QOpenGLTexture::Red_Integer, QOpenGLTexture::R16U, QOpenGLTexture::UInt16, 2, false } }, +{ DXGI_FORMAT_R16G16_UINT, { QOpenGLTexture::RG_Integer, QOpenGLTexture::RG16U, QOpenGLTexture::UInt16, 4, false } }, +{ DXGI_FORMAT_R16G16B16A16_UINT, { QOpenGLTexture::RGBA_Integer, QOpenGLTexture::RGBA16U, QOpenGLTexture::UInt16, 8, false } }, + +{ DXGI_FORMAT_R32_UINT, { QOpenGLTexture::Red_Integer, QOpenGLTexture::R32U, QOpenGLTexture::UInt32, 4, false } }, +{ DXGI_FORMAT_R32G32_UINT, { QOpenGLTexture::RG_Integer, QOpenGLTexture::RG32U, QOpenGLTexture::UInt32, 8, false } }, +{ DXGI_FORMAT_R32G32B32_UINT, { QOpenGLTexture::RGB_Integer, QOpenGLTexture::RGB32U, QOpenGLTexture::UInt32, 12, false } }, +{ DXGI_FORMAT_R32G32B32A32_UINT, { QOpenGLTexture::RGBA_Integer, QOpenGLTexture::RGBA32U, QOpenGLTexture::UInt32, 16, false } }, + +// signed integer formats +{ DXGI_FORMAT_R8_SINT, { QOpenGLTexture::Red_Integer, QOpenGLTexture::R8I, QOpenGLTexture::Int8, 1, false } }, +{ DXGI_FORMAT_R8G8_SINT, { QOpenGLTexture::RG_Integer, QOpenGLTexture::RG8I, QOpenGLTexture::Int8, 2, false } }, +{ DXGI_FORMAT_R8G8B8A8_SINT, { QOpenGLTexture::RGBA_Integer, QOpenGLTexture::RGBA8I, QOpenGLTexture::Int8, 4, false } }, + +{ DXGI_FORMAT_R16_SINT, { QOpenGLTexture::Red_Integer, QOpenGLTexture::R16I, QOpenGLTexture::Int16, 2, false } }, +{ DXGI_FORMAT_R16G16_SINT, { QOpenGLTexture::RG_Integer, QOpenGLTexture::RG16I, QOpenGLTexture::Int16, 4, false } }, +{ DXGI_FORMAT_R16G16B16A16_SINT, { QOpenGLTexture::RGBA_Integer, QOpenGLTexture::RGBA16I, QOpenGLTexture::Int16, 8, false } }, + +{ DXGI_FORMAT_R32_SINT, { QOpenGLTexture::Red_Integer, QOpenGLTexture::R32I, QOpenGLTexture::Int32, 4, false } }, +{ DXGI_FORMAT_R32G32_SINT, { QOpenGLTexture::RG_Integer, QOpenGLTexture::RG32I, QOpenGLTexture::Int32, 8, false } }, +{ DXGI_FORMAT_R32G32B32_SINT, { QOpenGLTexture::RGB_Integer, QOpenGLTexture::RGB32I, QOpenGLTexture::Int32, 12, false } }, +{ DXGI_FORMAT_R32G32B32A32_SINT, { QOpenGLTexture::RGBA_Integer, QOpenGLTexture::RGBA32I, QOpenGLTexture::Int32, 16, false } }, + +// floating formats +{ DXGI_FORMAT_R16_FLOAT, { QOpenGLTexture::Red, QOpenGLTexture::R16F, QOpenGLTexture::Float16, 2, false } }, +{ DXGI_FORMAT_R16G16_FLOAT, { QOpenGLTexture::RG, QOpenGLTexture::RG16F, QOpenGLTexture::Float16, 4, false } }, +{ DXGI_FORMAT_R16G16B16A16_FLOAT, { QOpenGLTexture::RGBA, QOpenGLTexture::RGBA16F, QOpenGLTexture::Float16, 8, false } }, + +{ DXGI_FORMAT_R32_FLOAT, { QOpenGLTexture::Red, QOpenGLTexture::R32F, QOpenGLTexture::Float32, 4, false } }, +{ DXGI_FORMAT_R32G32_FLOAT, { QOpenGLTexture::RG, QOpenGLTexture::RG32F, QOpenGLTexture::Float32, 8, false } }, +{ DXGI_FORMAT_R32G32B32_FLOAT, { QOpenGLTexture::RGB, QOpenGLTexture::RGB32F, QOpenGLTexture::Float32, 12, false } }, +{ DXGI_FORMAT_R32G32B32A32_FLOAT, { QOpenGLTexture::RGBA, QOpenGLTexture::RGBA32F, QOpenGLTexture::Float32, 16, false } }, + +// sRGB formats +{ DXGI_FORMAT_B8G8R8X8_UNORM_SRGB, { QOpenGLTexture::RGB, QOpenGLTexture::SRGB8, QOpenGLTexture::UInt8, 4, false } }, +{ DXGI_FORMAT_R8G8B8A8_UNORM_SRGB, { QOpenGLTexture::RGBA, QOpenGLTexture::SRGB8_Alpha8, QOpenGLTexture::UInt8, 4, false } }, + +// packed formats +// { DXGI_FORMAT_R10G10B10A2_UNORM, { QOpenGLTexture::RGB10A2_UNORM, QOpenGLTexture::RGBA, QOpenGLTexture::UInt32_RGB10A2, 4, false } }, +{ DXGI_FORMAT_R10G10B10A2_UINT, { QOpenGLTexture::RGBA_Integer, QOpenGLTexture::RGB10A2, QOpenGLTexture::UInt32_RGB10A2, 4, false } }, +{ DXGI_FORMAT_R9G9B9E5_SHAREDEXP, { QOpenGLTexture::RGB, QOpenGLTexture::RGB9E5, QOpenGLTexture::UInt32_RGB9_E5, 4, false } }, +{ DXGI_FORMAT_R11G11B10_FLOAT, { QOpenGLTexture::RGB, QOpenGLTexture::RG11B10F, QOpenGLTexture::UInt32_RG11B10F, 4, false } }, +{ DXGI_FORMAT_B5G6R5_UNORM, { QOpenGLTexture::RGB, QOpenGLTexture::R5G6B5, QOpenGLTexture::UInt16_R5G6B5, 2, false } }, +{ DXGI_FORMAT_B5G5R5A1_UNORM, { QOpenGLTexture::RGBA, QOpenGLTexture::RGB5A1, QOpenGLTexture::UInt16_RGB5A1, 2, false } }, +{ DXGI_FORMAT_B4G4R4A4_UNORM, { QOpenGLTexture::RGBA, QOpenGLTexture::RGBA4, QOpenGLTexture::UInt16_RGBA4, 2, false } }, + +// swizzle formats +{ DXGI_FORMAT_B8G8R8X8_UNORM, { QOpenGLTexture::BGRA, QOpenGLTexture::RGB8_UNorm, QOpenGLTexture::UInt8, 4, false } }, +{ DXGI_FORMAT_B8G8R8A8_UNORM, { QOpenGLTexture::BGRA, QOpenGLTexture::RGBA8_UNorm, QOpenGLTexture::UInt8, 4, false } }, +{ DXGI_FORMAT_B8G8R8X8_UNORM_SRGB, { QOpenGLTexture::BGRA, QOpenGLTexture::SRGB8, QOpenGLTexture::UInt8, 4, false } }, +{ DXGI_FORMAT_B8G8R8A8_UNORM_SRGB, { QOpenGLTexture::BGRA, QOpenGLTexture::SRGB8_Alpha8, QOpenGLTexture::UInt8, 4, false } }, + +// luminance alpha formats +{ DXGI_FORMAT_R8_UNORM, { QOpenGLTexture::Red, QOpenGLTexture::R8_UNorm, QOpenGLTexture::UInt8, 1, false } }, +{ DXGI_FORMAT_R8G8_UNORM, { QOpenGLTexture::RG, QOpenGLTexture::RG8_UNorm, QOpenGLTexture::UInt8, 2, false } }, +{ DXGI_FORMAT_R16_UNORM, { QOpenGLTexture::Red, QOpenGLTexture::R16_UNorm, QOpenGLTexture::UInt16, 2, false } }, +{ DXGI_FORMAT_R16_UNORM, { QOpenGLTexture::RG, QOpenGLTexture::RG16_UNorm, QOpenGLTexture::UInt16, 4, false } }, + +// depth formats +{ DXGI_FORMAT_D16_UNORM, { QOpenGLTexture::Depth, QOpenGLTexture::D16, QOpenGLTexture::NoPixelType, 2, false } }, +{ DXGI_FORMAT_D24_UNORM_S8_UINT, { QOpenGLTexture::DepthStencil, QOpenGLTexture::D24S8, QOpenGLTexture::NoPixelType, 4, false } }, +{ DXGI_FORMAT_D32_FLOAT, { QOpenGLTexture::Depth, QOpenGLTexture::D32F, QOpenGLTexture::NoPixelType, 4, false } }, +{ DXGI_FORMAT_D32_FLOAT_S8X24_UINT, { QOpenGLTexture::DepthStencil, QOpenGLTexture::D32FS8X24, QOpenGLTexture::NoPixelType, 8, false } }, + +// compressed formats +{ DXGI_FORMAT_BC1_UNORM, { QOpenGLTexture::NoSourceFormat, QOpenGLTexture::RGBA_DXT1, QOpenGLTexture::NoPixelType, 8, true } }, +{ DXGI_FORMAT_BC2_UNORM, { QOpenGLTexture::NoSourceFormat, QOpenGLTexture::RGBA_DXT3, QOpenGLTexture::NoPixelType, 16, true } }, +{ DXGI_FORMAT_BC3_UNORM, { QOpenGLTexture::NoSourceFormat, QOpenGLTexture::RGBA_DXT5, QOpenGLTexture::NoPixelType, 16, true } }, +{ DXGI_FORMAT_BC4_UNORM, { QOpenGLTexture::NoSourceFormat, QOpenGLTexture::R_ATI1N_UNorm, QOpenGLTexture::NoPixelType, 8, true } }, +{ DXGI_FORMAT_BC4_SNORM, { QOpenGLTexture::NoSourceFormat, QOpenGLTexture::R_ATI1N_SNorm, QOpenGLTexture::NoPixelType, 8, true } }, +{ DXGI_FORMAT_BC5_UNORM, { QOpenGLTexture::NoSourceFormat, QOpenGLTexture::RG_ATI2N_UNorm, QOpenGLTexture::NoPixelType, 16, true } }, +{ DXGI_FORMAT_BC5_SNORM, { QOpenGLTexture::NoSourceFormat, QOpenGLTexture::RG_ATI2N_SNorm, QOpenGLTexture::NoPixelType, 16, true } }, +{ DXGI_FORMAT_BC6H_UF16, { QOpenGLTexture::NoSourceFormat, QOpenGLTexture::RGB_BP_UNSIGNED_FLOAT, QOpenGLTexture::NoPixelType, 16, true } }, +{ DXGI_FORMAT_BC6H_SF16, { QOpenGLTexture::NoSourceFormat, QOpenGLTexture::RGB_BP_SIGNED_FLOAT, QOpenGLTexture::NoPixelType, 16, true } }, +{ DXGI_FORMAT_BC7_UNORM, { QOpenGLTexture::NoSourceFormat, QOpenGLTexture::RGB_BP_UNorm, QOpenGLTexture::NoPixelType, 16, true } }, + +// compressed sRGB formats +{ DXGI_FORMAT_BC1_UNORM_SRGB, { QOpenGLTexture::NoSourceFormat, QOpenGLTexture::SRGB_DXT1, QOpenGLTexture::NoPixelType, 8, true } }, +{ DXGI_FORMAT_BC1_UNORM_SRGB, { QOpenGLTexture::NoSourceFormat, QOpenGLTexture::SRGB_Alpha_DXT1, QOpenGLTexture::NoPixelType, 8, true } }, +{ DXGI_FORMAT_BC2_UNORM_SRGB, { QOpenGLTexture::NoSourceFormat, QOpenGLTexture::SRGB_Alpha_DXT3, QOpenGLTexture::NoPixelType, 16, true } }, +{ DXGI_FORMAT_BC3_UNORM_SRGB, { QOpenGLTexture::NoSourceFormat, QOpenGLTexture::SRGB_Alpha_DXT5, QOpenGLTexture::NoPixelType, 16, true } }, +{ DXGI_FORMAT_BC7_UNORM_SRGB, { QOpenGLTexture::NoSourceFormat, QOpenGLTexture::SRGB_BP_UNorm, QOpenGLTexture::NoPixelType, 16, true } }, +}; + +int bitCount(quint32 n) +{ + int r = 0; + + for (; n; n >>= 1) + r += (n & 1); + + return r; +} + +enum CompressedFormatExtension { + None = 0, + DDS, + PKM +}; + +CompressedFormatExtension texturedCompressedFormat(const QString &source) +{ + const QString suffix = QFileInfo(source).suffix(); + if (suffix == QStringLiteral("pkm")) + return PKM; + if (suffix == QStringLiteral("dds")) + return DDS; + return None; +} + +QTextureImageDataPtr setPkmFile(const QString &source) +{ + QTextureImageDataPtr imageData; + QFile f(source); + if (!f.open(QIODevice::ReadOnly)) { + qWarning() << "Failed to open" << source; + return imageData; + } + + // ETC1 in PKM, as generated by f.ex. Android's etc1tool + static const char pkmMagic[] = { 'P', 'K', 'M', ' ', '1', '0' }; + const int pkmHeaderSize = 6 + 2 + 4 * 2; + const QByteArray header = f.read(pkmHeaderSize); + if (header.size() >= pkmHeaderSize && !qstrncmp(header.constData(), pkmMagic, 6)) { + imageData = QTextureImageDataPtr::create(); + imageData->setTarget(QOpenGLTexture::Target2D); + imageData->setFormat(QOpenGLTexture::RGB8_ETC1); // may get changed to RGB8_ETC2 later on + // get the extended (multiple of 4) width and height + imageData->setWidth(qFromBigEndian(*(reinterpret_cast<const quint16 *>(header.constData() + 6 + 2)))); + imageData->setHeight(qFromBigEndian(*(reinterpret_cast<const quint16 *>(header.constData() + 6 + 2 + 2)))); + imageData->setDepth(1); + const QByteArray data = f.readAll(); + if (data.size() < (imageData->width() / 4) * (imageData->height() / 4) * 8) + qWarning() << "Unexpected end of ETC1 data in" << source; + const bool isCompressed = true; + const int blockSize = 8; + imageData->setPixelFormat(QOpenGLTexture::RGBA); + imageData->setPixelType(QOpenGLTexture::UInt8); + imageData->setData(data, blockSize, isCompressed); + } + return imageData; +} + +QTextureImageDataPtr setDdsFile(const QString &source) +{ + QTextureImageDataPtr imageData; + QFile f(source); + if (!f.open(QIODevice::ReadOnly)) { + qWarning() << "Failed to open" << source; + return imageData; + } + + DdsHeader header; + if ((f.read(reinterpret_cast<char *>(&header), sizeof header) != sizeof header) + || (qstrncmp(header.magic, "DDS ", 4) != 0)) + return imageData; + + int layers = 1; + const quint32 pixelFlags = qFromLittleEndian(header.pixelFormat.flags); + const quint32 fourCC = qFromLittleEndian(header.pixelFormat.fourCC); + const FormatInfo *formatInfo = nullptr; + + if ((pixelFlags & FourCCFlag) == FourCCFlag) { + if (fourCC == DdsFourCC<'D', 'X', '1', '0'>::value) { + // DX10 texture + DdsDX10Header dx10Header; + if (f.read(reinterpret_cast<char *>(&dx10Header), sizeof dx10Header) != sizeof dx10Header) + return imageData; + + layers = qFromLittleEndian(dx10Header.arraySize); + DXGIFormat format = static_cast<DXGIFormat>(qFromLittleEndian(dx10Header.format)); + + for (auto i = 0U; i < sizeof(dx10Formats) / sizeof(*dx10Formats); ++i) { + if (dx10Formats[i].dxgiFormat == format) { + formatInfo = &dx10Formats[i].formatInfo; + break; + } + } + } else { + // compressed, FourCC texture + for (auto i = 0U; i < sizeof(fourCCFormats) / sizeof(*fourCCFormats); ++i) { + if (fourCCFormats[i].fourCC == fourCC) { + formatInfo = &fourCCFormats[i].formatInfo; + break; + } + } + } + } else { + // uncompressed texture + const quint32 rgbBitCount = qFromLittleEndian(header.pixelFormat.rgbBitCount); + const quint32 redMask = qFromLittleEndian(header.pixelFormat.redMask); + const quint32 greenMask = qFromLittleEndian(header.pixelFormat.greenMask); + const quint32 blueMask = qFromLittleEndian(header.pixelFormat.blueMask); + const quint32 alphaMask = qFromLittleEndian(header.pixelFormat.alphaMask); + + for (unsigned i = 0; i < sizeof rgbaFormats/sizeof *rgbaFormats; i++) { + const RGBAFormat *info = &rgbaFormats[i]; + + if (info->formatInfo.components * 8u == rgbBitCount && + info->redMask == redMask && info->greenMask == greenMask && + info->blueMask == blueMask && info->alphaMask == alphaMask) { + formatInfo = &info->formatInfo; + break; + } + } + } + + if (formatInfo == nullptr) { + qWarning() << "Unrecognized pixel format in" << source; + return imageData; + } + + // target + // XXX should worry about Target1D? + QOpenGLTexture::Target target; + const int width = qFromLittleEndian(header.width); + const int height = qFromLittleEndian(header.height); + const quint32 caps2Flags = qFromLittleEndian(header.caps2); + const int blockSize = formatInfo->components; + const bool isCompressed = formatInfo->compressed; + const int mipLevelCount = ((qFromLittleEndian(header.flags) & MipmapCountFlag) == MipmapCountFlag) ? qFromLittleEndian(header.mipmapCount) : 1; + int depth; + int faces; + + if ((caps2Flags & VolumeFlag) == VolumeFlag) { + target = QOpenGLTexture::Target3D; + depth = qFromLittleEndian(header.depth); + faces = 1; + } else if ((caps2Flags & CubemapFlag) == CubemapFlag) { + target = layers > 1 ? QOpenGLTexture::TargetCubeMapArray : QOpenGLTexture::TargetCubeMap; + depth = 1; + faces = bitCount(caps2Flags & AllCubemapFaceFlags); + } else { + target = layers > 1 ? QOpenGLTexture::Target2DArray : QOpenGLTexture::Target2D; + depth = 1; + faces = 1; + } + + int layerSize = 0; + int tmpSize = 0; + + auto computeMipMapLevelSize = [&] (int level) { + const int w = qMax(width >> level, 1); + const int h = qMax(height >> level, 1); + const int d = qMax(depth >> level, 1); + + if (isCompressed) + return ((w + 3) / 4) * ((h + 3) / 4) * blockSize * d; + else + return w * h * blockSize * d; + }; + + for (auto i = 0; i < mipLevelCount; ++i) + tmpSize += computeMipMapLevelSize(i); + + layerSize = faces * tmpSize; + + // data + const QByteArray data = f.readAll(); + if (data.size() != layers * layerSize) { + qWarning() << "Unexpected data size (got " << data.size() << ", expecting" << layers * layerSize << ")"; + return imageData; + } + imageData = QTextureImageDataPtr::create(); + imageData->setData(data,blockSize, isCompressed); + + // target + imageData->setTarget(target); + + // mip levels + imageData->setMipLevels(mipLevelCount); + + // texture format + imageData->setFormat(formatInfo->textureFormat); + imageData->setPixelType(formatInfo->pixelType); + imageData->setPixelFormat(formatInfo->pixelFormat); + + // dimensions + imageData->setLayers(layers); + imageData->setDepth(depth); + imageData->setWidth(width); + imageData->setHeight(height); + imageData->setFaces(faces); + + return imageData; +} + +} // anonynous + +QTextureImageDataPtr TextureLoadingHelper::loadTextureData(const QUrl &url, bool allow3D) +{ + QTextureImageDataPtr textureData; + if (url.isLocalFile() || url.scheme() == QLatin1String("qrc")) { + const QString source = Qt3DRender::QUrlHelper::urlToLocalFileOrQrc(url); + const CompressedFormatExtension formatExtension = texturedCompressedFormat(source); + switch (formatExtension) { + case DDS: + textureData = setDdsFile(source); + break; + case PKM: + textureData = setPkmFile(source); + break; + default: + QImage img; + if (img.load(source)) { + textureData = QTextureImageDataPtr::create(); + textureData->setImage(img); + } + break; + } + + if (!allow3D && (textureData->layers() > 1 || textureData->depth() > 1)) + qWarning() << "Texture data has a 3rd dimension which wasn't expected"; + } + return textureData; +} + +QTextureDataPtr QTextureFromSourceGenerator::operator ()() +{ + QTextureDataPtr generatedData = QTextureDataPtr::create(); + m_status = QAbstractTexture::Loading; + + const QTextureImageDataPtr textureData = TextureLoadingHelper::loadTextureData(m_url, true); + + if (textureData && textureData->data().length() > 0) { + generatedData->setTarget(static_cast<QAbstractTexture::Target>(textureData->target())); + generatedData->setFormat(static_cast<QAbstractTexture::TextureFormat>(textureData->format())); + generatedData->setWidth(textureData->width()); + generatedData->setHeight(textureData->height()); + generatedData->setDepth(textureData->depth()); + generatedData->setLayers(textureData->layers()); + generatedData->addImageData(textureData); + // TO DO: Check that we aren't forgetting to set something here + m_status = QAbstractTexture::Ready; + } else { + m_status = QAbstractTexture::Error; + } + return generatedData; +} + QTextureLoaderPrivate::QTextureLoaderPrivate() : QAbstractTexturePrivate() { @@ -304,64 +930,14 @@ bool QTextureFromSourceGenerator::operator ==(const QTextureGenerator &other) co { const QTextureFromSourceGenerator *otherFunctor = functor_cast<QTextureFromSourceGenerator>(&other); return (otherFunctor != Q_NULLPTR && otherFunctor->m_url == m_url); - } - QTextureFromSourceGenerator::QTextureFromSourceGenerator(const QUrl &url) : QTextureGenerator() , m_url(url) { } -// Note: Maybe this should return a struct containing information such as -// the format, number of layers .... -// This would also give more flexibility for the future -QTextureDataPtr QTextureFromSourceGenerator::operator ()() -{ - QTextureDataPtr generatedData = QTextureDataPtr::create(); - // TO DO: Make it handle more formats and formats with nested images - - m_status = QAbstractTexture::Loading; - - if (m_url.isLocalFile() || m_url.scheme() == QStringLiteral("qrc")) { - QString source = Qt3DRender::QUrlHelper::urlToLocalFileOrQrc(m_url); - QVector<QTextureImageDataPtr> images; - QTextureImageDataPtr dataPtr = QTextureImageDataPtr::create(); - // TO DO: Ideally a setter shouldn't return a value - // Separate that into isCompressedFile and setCompressedFile - // Set compressed fill the QTextImageData if possible, - // returns false if it failed or is not a compressed format - - // TO DO: Make separateSetCompressed from the loading of a compressed file - // Make such loader set the property formats, targets and sizes in the generatedData - - if (!dataPtr->setCompressedFile(source)) { - // Try to load using QImage - QImage img; - if (img.load(source)) - dataPtr->setImage(img); - generatedData->setTarget(QAbstractTexture::Target2D); - generatedData->setWidth(img.width()); - generatedData->setHeight(img.height()); - generatedData->setDepth(1); - } - - if (dataPtr->data().length() > 0) { - m_status = QAbstractTexture::Ready; - generatedData->addImageData(dataPtr); - images.push_back(dataPtr); - } else { - m_status = QAbstractTexture::Error; - qWarning() << "Failed to load image : " << source; - } - } else { - m_status = QAbstractTexture::Error; - qWarning() << "implement loading from remote URLs"; - } - return generatedData; -} - } // namespace Qt3DRender QT_END_NAMESPACE diff --git a/src/render/texture/qtexture_p.h b/src/render/texture/qtexture_p.h index 7f295bbbe..d80e048f7 100644 --- a/src/render/texture/qtexture_p.h +++ b/src/render/texture/qtexture_p.h @@ -81,6 +81,12 @@ private: QAbstractTexture::Status m_status; }; +class Q_AUTOTEST_EXPORT TextureLoadingHelper +{ +public: + static QTextureImageDataPtr loadTextureData(const QUrl &source, bool allow3D); +}; + } // namespace Qt3DRender QT_END_NAMESPACE diff --git a/src/render/texture/qtextureimage.cpp b/src/render/texture/qtextureimage.cpp index 717a80100..67bef5efb 100644 --- a/src/render/texture/qtextureimage.cpp +++ b/src/render/texture/qtextureimage.cpp @@ -39,6 +39,7 @@ #include "qtextureimage.h" #include "qtextureimage_p.h" +#include "qtexture_p.h" #include "qabstracttextureimage_p.h" #include <Qt3DCore/qpropertyupdatedchange.h> @@ -149,6 +150,25 @@ void QTextureImage::sceneChangeEvent(const Qt3DCore::QSceneChangePtr &change) setStatus(static_cast<QTextureImage::Status>(e->value().toInt())); } +QImageTextureDataFunctor::QImageTextureDataFunctor(const QUrl &url) + : QTextureImageDataGenerator() + , m_url(url) +{} + +QTextureImageDataPtr QImageTextureDataFunctor::operator ()() +{ + // We assume that a texture image is going to contain a single image data + // For compressed dds or ktx textures a warning should be issued if + // there are layers or 3D textures + return TextureLoadingHelper::loadTextureData(m_url, false); +} + +bool QImageTextureDataFunctor::operator ==(const QTextureImageDataGenerator &other) const +{ + const QImageTextureDataFunctor *otherFunctor = functor_cast<QImageTextureDataFunctor>(&other); + return (otherFunctor != Q_NULLPTR && otherFunctor->m_url == m_url); +} + } // namespace Qt3DRender QT_END_NAMESPACE diff --git a/src/render/texture/qtextureimage_p.h b/src/render/texture/qtextureimage_p.h index 30bc44628..ed1ae2ced 100644 --- a/src/render/texture/qtextureimage_p.h +++ b/src/render/texture/qtextureimage_p.h @@ -78,44 +78,11 @@ public: class QImageTextureDataFunctor : public QTextureImageDataGenerator { public: - QImageTextureDataFunctor(const QUrl &url) - : QTextureImageDataGenerator() - , m_url(url) - {} - + QImageTextureDataFunctor(const QUrl &url); // Will be executed from within a QAspectJob - QTextureImageDataPtr operator ()() Q_DECL_FINAL - { - QTextureImageDataPtr dataPtr; - if (m_url.isLocalFile() || m_url.scheme() == QLatin1String("qrc")) { - QString source = Qt3DRender::QUrlHelper::urlToLocalFileOrQrc(m_url); - dataPtr.reset(new QTextureImageData()); - if (dataPtr->setCompressedFile(source)) - return dataPtr; - QImage img; - if (img.load(source)) { - dataPtr->setImage(img); - return dataPtr; - } - dataPtr.reset(); - qWarning() << "Failed to load image : " << source; - } else if (!m_url.isEmpty()) { - qWarning() << "implement loading from remote URLs"; - } - return dataPtr; - } - - bool operator ==(const QTextureImageDataGenerator &other) const Q_DECL_FINAL - { - const QImageTextureDataFunctor *otherFunctor = functor_cast<QImageTextureDataFunctor>(&other); - return (otherFunctor != Q_NULLPTR && otherFunctor->m_url == m_url); - } - - QTextureImage::Status status() const - { - return m_status; - } - + QTextureImageDataPtr operator ()() Q_DECL_FINAL; + bool operator ==(const QTextureImageDataGenerator &other) const Q_DECL_FINAL; + inline QTextureImage::Status status() const { return m_status; } QT3D_FUNCTOR(QImageTextureDataFunctor) private: diff --git a/src/render/texture/qtextureimagedata.cpp b/src/render/texture/qtextureimagedata.cpp index 80e6f5575..ee080ee9f 100644 --- a/src/render/texture/qtextureimagedata.cpp +++ b/src/render/texture/qtextureimagedata.cpp @@ -41,370 +41,11 @@ #include <QDebug> #include <QFileInfo> #include <QFile> -#include <qendian.h> QT_BEGIN_NAMESPACE namespace Qt3DRender { -namespace { - -struct DdsPixelFormat { - quint32 size; - quint32 flags; - quint32 fourCC; - quint32 rgbBitCount; - quint32 redMask; - quint32 greenMask; - quint32 blueMask; - quint32 alphaMask; -}; - -struct DdsHeader { - char magic[4]; - quint32 size; - quint32 flags; - quint32 height; - quint32 width; - quint32 pitchOrLinearSize; - quint32 depth; - quint32 mipmapCount; - quint32 reserved[11]; - DdsPixelFormat pixelFormat; - quint32 caps; - quint32 caps2; - quint32 caps3; - quint32 caps4; - quint32 reserved2; -}; - -struct DdsDX10Header { - quint32 format; - quint32 dimension; - quint32 miscFlag; - quint32 arraySize; - quint32 miscFlags2; -}; - -enum DdsFlags { - MipmapCountFlag = 0x20000, -}; - -enum PixelFormatFlag { - AlphaFlag = 0x1, - FourCCFlag = 0x4, - RGBFlag = 0x40, - RGBAFlag = RGBFlag | AlphaFlag, - YUVFlag = 0x200, - LuminanceFlag = 0x20000 -}; - -enum Caps2Flags { - CubemapFlag = 0x200, - CubemapPositiveXFlag = 0x400, - CubemapNegativeXFlag = 0x800, - CubemapPositiveYFlag = 0x1000, - CubemapNegativeYFlag = 0x2000, - CubemapPositiveZFlag = 0x4000, - CubemapNegativeZFlag = 0x8000, - AllCubemapFaceFlags = CubemapPositiveXFlag | - CubemapNegativeXFlag | - CubemapPositiveYFlag | - CubemapNegativeYFlag | - CubemapPositiveZFlag | - CubemapNegativeZFlag, - VolumeFlag = 0x200000 -}; - -enum DXGIFormat { - DXGI_FORMAT_UNKNOWN = 0, - DXGI_FORMAT_R32G32B32A32_TYPELESS = 1, - DXGI_FORMAT_R32G32B32A32_FLOAT = 2, - DXGI_FORMAT_R32G32B32A32_UINT = 3, - DXGI_FORMAT_R32G32B32A32_SINT = 4, - DXGI_FORMAT_R32G32B32_TYPELESS = 5, - DXGI_FORMAT_R32G32B32_FLOAT = 6, - DXGI_FORMAT_R32G32B32_UINT = 7, - DXGI_FORMAT_R32G32B32_SINT = 8, - DXGI_FORMAT_R16G16B16A16_TYPELESS = 9, - DXGI_FORMAT_R16G16B16A16_FLOAT = 10, - DXGI_FORMAT_R16G16B16A16_UNORM = 11, - DXGI_FORMAT_R16G16B16A16_UINT = 12, - DXGI_FORMAT_R16G16B16A16_SNORM = 13, - DXGI_FORMAT_R16G16B16A16_SINT = 14, - DXGI_FORMAT_R32G32_TYPELESS = 15, - DXGI_FORMAT_R32G32_FLOAT = 16, - DXGI_FORMAT_R32G32_UINT = 17, - DXGI_FORMAT_R32G32_SINT = 18, - DXGI_FORMAT_R32G8X24_TYPELESS = 19, - DXGI_FORMAT_D32_FLOAT_S8X24_UINT = 20, - DXGI_FORMAT_R32_FLOAT_X8X24_TYPELESS = 21, - DXGI_FORMAT_X32_TYPELESS_G8X24_UINT = 22, - DXGI_FORMAT_R10G10B10A2_TYPELESS = 23, - DXGI_FORMAT_R10G10B10A2_UNORM = 24, - DXGI_FORMAT_R10G10B10A2_UINT = 25, - DXGI_FORMAT_R11G11B10_FLOAT = 26, - DXGI_FORMAT_R8G8B8A8_TYPELESS = 27, - DXGI_FORMAT_R8G8B8A8_UNORM = 28, - DXGI_FORMAT_R8G8B8A8_UNORM_SRGB = 29, - DXGI_FORMAT_R8G8B8A8_UINT = 30, - DXGI_FORMAT_R8G8B8A8_SNORM = 31, - DXGI_FORMAT_R8G8B8A8_SINT = 32, - DXGI_FORMAT_R16G16_TYPELESS = 33, - DXGI_FORMAT_R16G16_FLOAT = 34, - DXGI_FORMAT_R16G16_UNORM = 35, - DXGI_FORMAT_R16G16_UINT = 36, - DXGI_FORMAT_R16G16_SNORM = 37, - DXGI_FORMAT_R16G16_SINT = 38, - DXGI_FORMAT_R32_TYPELESS = 39, - DXGI_FORMAT_D32_FLOAT = 40, - DXGI_FORMAT_R32_FLOAT = 41, - DXGI_FORMAT_R32_UINT = 42, - DXGI_FORMAT_R32_SINT = 43, - DXGI_FORMAT_R24G8_TYPELESS = 44, - DXGI_FORMAT_D24_UNORM_S8_UINT = 45, - DXGI_FORMAT_R24_UNORM_X8_TYPELESS = 46, - DXGI_FORMAT_X24_TYPELESS_G8_UINT = 47, - DXGI_FORMAT_R8G8_TYPELESS = 48, - DXGI_FORMAT_R8G8_UNORM = 49, - DXGI_FORMAT_R8G8_UINT = 50, - DXGI_FORMAT_R8G8_SNORM = 51, - DXGI_FORMAT_R8G8_SINT = 52, - DXGI_FORMAT_R16_TYPELESS = 53, - DXGI_FORMAT_R16_FLOAT = 54, - DXGI_FORMAT_D16_UNORM = 55, - DXGI_FORMAT_R16_UNORM = 56, - DXGI_FORMAT_R16_UINT = 57, - DXGI_FORMAT_R16_SNORM = 58, - DXGI_FORMAT_R16_SINT = 59, - DXGI_FORMAT_R8_TYPELESS = 60, - DXGI_FORMAT_R8_UNORM = 61, - DXGI_FORMAT_R8_UINT = 62, - DXGI_FORMAT_R8_SNORM = 63, - DXGI_FORMAT_R8_SINT = 64, - DXGI_FORMAT_A8_UNORM = 65, - DXGI_FORMAT_R1_UNORM = 66, - DXGI_FORMAT_R9G9B9E5_SHAREDEXP = 67, - DXGI_FORMAT_R8G8_B8G8_UNORM = 68, - DXGI_FORMAT_G8R8_G8B8_UNORM = 69, - DXGI_FORMAT_BC1_TYPELESS = 70, - DXGI_FORMAT_BC1_UNORM = 71, - DXGI_FORMAT_BC1_UNORM_SRGB = 72, - DXGI_FORMAT_BC2_TYPELESS = 73, - DXGI_FORMAT_BC2_UNORM = 74, - DXGI_FORMAT_BC2_UNORM_SRGB = 75, - DXGI_FORMAT_BC3_TYPELESS = 76, - DXGI_FORMAT_BC3_UNORM = 77, - DXGI_FORMAT_BC3_UNORM_SRGB = 78, - DXGI_FORMAT_BC4_TYPELESS = 79, - DXGI_FORMAT_BC4_UNORM = 80, - DXGI_FORMAT_BC4_SNORM = 81, - DXGI_FORMAT_BC5_TYPELESS = 82, - DXGI_FORMAT_BC5_UNORM = 83, - DXGI_FORMAT_BC5_SNORM = 84, - DXGI_FORMAT_B5G6R5_UNORM = 85, - DXGI_FORMAT_B5G5R5A1_UNORM = 86, - DXGI_FORMAT_B8G8R8A8_UNORM = 87, - DXGI_FORMAT_B8G8R8X8_UNORM = 88, - DXGI_FORMAT_R10G10B10_XR_BIAS_A2_UNORM = 89, - DXGI_FORMAT_B8G8R8A8_TYPELESS = 90, - DXGI_FORMAT_B8G8R8A8_UNORM_SRGB = 91, - DXGI_FORMAT_B8G8R8X8_TYPELESS = 92, - DXGI_FORMAT_B8G8R8X8_UNORM_SRGB = 93, - DXGI_FORMAT_BC6H_TYPELESS = 94, - DXGI_FORMAT_BC6H_UF16 = 95, - DXGI_FORMAT_BC6H_SF16 = 96, - DXGI_FORMAT_BC7_TYPELESS = 97, - DXGI_FORMAT_BC7_UNORM = 98, - DXGI_FORMAT_BC7_UNORM_SRGB = 99, - DXGI_FORMAT_AYUV = 100, - DXGI_FORMAT_Y410 = 101, - DXGI_FORMAT_Y416 = 102, - DXGI_FORMAT_NV12 = 103, - DXGI_FORMAT_P010 = 104, - DXGI_FORMAT_P016 = 105, - DXGI_FORMAT_420_OPAQUE = 106, - DXGI_FORMAT_YUY2 = 107, - DXGI_FORMAT_Y210 = 108, - DXGI_FORMAT_Y216 = 109, - DXGI_FORMAT_NV11 = 110, - DXGI_FORMAT_AI44 = 111, - DXGI_FORMAT_IA44 = 112, - DXGI_FORMAT_P8 = 113, - DXGI_FORMAT_A8P8 = 114, - DXGI_FORMAT_B4G4R4A4_UNORM = 115, - DXGI_FORMAT_P208 = 130, - DXGI_FORMAT_V208 = 131, - DXGI_FORMAT_V408 = 132, -}; - -template <int a, int b, int c, int d> -struct DdsFourCC -{ - static const quint32 value = a | (b << 8) | (c << 16) | (d << 24); -}; - -struct FormatInfo { - QOpenGLTexture::PixelFormat pixelFormat; - QOpenGLTexture::TextureFormat textureFormat; - QOpenGLTexture::PixelType pixelType; - int components; - bool compressed; -}; - -const struct RGBAFormat { - quint32 redMask; - quint32 greenMask; - quint32 blueMask; - quint32 alphaMask; - FormatInfo formatInfo; -} rgbaFormats[] = { - // unorm formats - { 0x000000ff, 0x0000ff00, 0x00ff0000, 0xff000000, { QOpenGLTexture::RGBA, QOpenGLTexture::RGBA8_UNorm, QOpenGLTexture::UInt8, 4, false } }, - { 0x00ff0000, 0x0000ff00, 0x000000ff, 0xff000000, { QOpenGLTexture::BGRA, QOpenGLTexture::RGBA8_UNorm, QOpenGLTexture::UInt8, 4, false } }, - { 0x000000ff, 0x0000ff00, 0x00ff0000, 0x00000000, { QOpenGLTexture::RGBA, QOpenGLTexture::RGBA8_UNorm, QOpenGLTexture::UInt8, 4, false } }, - { 0x00ff0000, 0x0000ff00, 0x000000ff, 0x00000000, { QOpenGLTexture::BGRA, QOpenGLTexture::RGBA8_UNorm, QOpenGLTexture::UInt8, 4, false } }, - { 0x000000ff, 0x0000ff00, 0x00ff0000, 0x00000000, { QOpenGLTexture::RGB, QOpenGLTexture::RGB8_UNorm, QOpenGLTexture::UInt8, 3, false } }, - { 0x00ff0000, 0x0000ff00, 0x000000ff, 0x00000000, { QOpenGLTexture::BGR, QOpenGLTexture::RGB8_UNorm, QOpenGLTexture::UInt8, 3, false } }, - - // packed formats - { 0x0000f800, 0x000007e0, 0x0000001f, 0x00000000, { QOpenGLTexture::RGB, QOpenGLTexture::R5G6B5, QOpenGLTexture::UInt16_R5G6B5, 2, false } }, - { 0x00007c00, 0x000003e0, 0x0000001f, 0x00008000, { QOpenGLTexture::RGBA, QOpenGLTexture::RGB5A1, QOpenGLTexture::UInt16_RGB5A1, 2, false } }, - { 0x00000f00, 0x000000f0, 0x0000000f, 0x0000f000, { QOpenGLTexture::RGBA, QOpenGLTexture::RGBA4, QOpenGLTexture::UInt16_RGBA4, 2, false } }, - { 0x000000e0, 0x0000001c, 0x00000003, 0x00000000, { QOpenGLTexture::RGB, QOpenGLTexture::RG3B2, QOpenGLTexture::UInt8_RG3B2, 1, false } }, - { 0x3ff00000, 0x000ffc00, 0x000003ff, 0xc0000000, { QOpenGLTexture::RGBA, QOpenGLTexture::RGB10A2, QOpenGLTexture::UInt32_RGB10A2, 4, false } }, - - // luminance alpha - { 0x000000ff, 0x000000ff, 0x000000ff, 0x00000000, { QOpenGLTexture::Red, QOpenGLTexture::R8_UNorm, QOpenGLTexture::UInt8, 1, false } }, - { 0x000000ff, 0x00000000, 0x00000000, 0x00000000, { QOpenGLTexture::Red, QOpenGLTexture::R8_UNorm, QOpenGLTexture::UInt8, 1, false } }, - { 0x000000ff, 0x000000ff, 0x000000ff, 0x0000ff00, { QOpenGLTexture::RG, QOpenGLTexture::RG8_UNorm, QOpenGLTexture::UInt8, 2, false } }, - { 0x000000ff, 0x00000000, 0x00000000, 0x0000ff00, { QOpenGLTexture::RG, QOpenGLTexture::RG8_UNorm, QOpenGLTexture::UInt8, 2, false } }, -}; - -const struct FourCCFormat { - quint32 fourCC; - FormatInfo formatInfo; -} fourCCFormats[] = { - { DdsFourCC<'D','X','T','1'>::value, { QOpenGLTexture::NoSourceFormat, QOpenGLTexture::RGBA_DXT1, QOpenGLTexture::NoPixelType, 8, true } }, - { DdsFourCC<'D','X','T','3'>::value, { QOpenGLTexture::NoSourceFormat, QOpenGLTexture::RGBA_DXT3, QOpenGLTexture::NoPixelType, 16, true } }, - { DdsFourCC<'D','X','T','5'>::value, { QOpenGLTexture::NoSourceFormat, QOpenGLTexture::RGBA_DXT5, QOpenGLTexture::NoPixelType, 16, true } }, - { DdsFourCC<'A','T','I','1'>::value, { QOpenGLTexture::NoSourceFormat, QOpenGLTexture::R_ATI1N_UNorm, QOpenGLTexture::NoPixelType, 8, true } }, - { DdsFourCC<'A','T','I','2'>::value, { QOpenGLTexture::NoSourceFormat, QOpenGLTexture::RG_ATI2N_UNorm, QOpenGLTexture::NoPixelType, 16, true } }, -}; - -const struct DX10Format { - DXGIFormat dxgiFormat; - FormatInfo formatInfo; -} dx10Formats[] = { - // unorm formats - { DXGI_FORMAT_R8_UNORM, { QOpenGLTexture::Red, QOpenGLTexture::R8_UNorm, QOpenGLTexture::UInt8, 1, false } }, - { DXGI_FORMAT_R8G8_UNORM, { QOpenGLTexture::RG, QOpenGLTexture::RG8_UNorm, QOpenGLTexture::UInt8, 2, false } }, - { DXGI_FORMAT_R8G8B8A8_UNORM, { QOpenGLTexture::RGBA, QOpenGLTexture::RGBA8_UNorm, QOpenGLTexture::UInt8, 4, false } }, - - { DXGI_FORMAT_R16_UNORM, { QOpenGLTexture::Red, QOpenGLTexture::R16_UNorm, QOpenGLTexture::UInt16, 2, false } }, - { DXGI_FORMAT_R16G16_UNORM, { QOpenGLTexture::RG, QOpenGLTexture::RG16_UNorm, QOpenGLTexture::UInt16, 4, false } }, - { DXGI_FORMAT_R16G16B16A16_UNORM, { QOpenGLTexture::RGBA, QOpenGLTexture::RGBA16_UNorm, QOpenGLTexture::UInt16, 8, false } }, - - // snorm formats - { DXGI_FORMAT_R8_SNORM, { QOpenGLTexture::Red, QOpenGLTexture::R8_SNorm, QOpenGLTexture::Int8, 1, false } }, - { DXGI_FORMAT_R8G8_SNORM, { QOpenGLTexture::RG, QOpenGLTexture::RG8_SNorm, QOpenGLTexture::Int8, 2, false } }, - { DXGI_FORMAT_R8G8B8A8_SNORM, { QOpenGLTexture::RGBA, QOpenGLTexture::RGBA8_SNorm, QOpenGLTexture::Int8, 4, false } }, - - { DXGI_FORMAT_R16_SNORM, { QOpenGLTexture::Red, QOpenGLTexture::R16_SNorm, QOpenGLTexture::Int16, 2, false } }, - { DXGI_FORMAT_R16G16_SNORM, { QOpenGLTexture::RG, QOpenGLTexture::RG16_SNorm, QOpenGLTexture::Int16, 4, false } }, - { DXGI_FORMAT_R16G16B16A16_SNORM, { QOpenGLTexture::RGBA, QOpenGLTexture::RGBA16_SNorm, QOpenGLTexture::Int16, 8, false } }, - - // unsigned integer formats - { DXGI_FORMAT_R8_UINT, { QOpenGLTexture::Red_Integer, QOpenGLTexture::R8U, QOpenGLTexture::UInt8, 1, false } }, - { DXGI_FORMAT_R8G8_UINT, { QOpenGLTexture::RG_Integer, QOpenGLTexture::RG8U, QOpenGLTexture::UInt8, 2, false } }, - { DXGI_FORMAT_R8G8B8A8_UINT, { QOpenGLTexture::RGBA_Integer, QOpenGLTexture::RGBA8U, QOpenGLTexture::UInt8, 4, false } }, - - { DXGI_FORMAT_R16_UINT, { QOpenGLTexture::Red_Integer, QOpenGLTexture::R16U, QOpenGLTexture::UInt16, 2, false } }, - { DXGI_FORMAT_R16G16_UINT, { QOpenGLTexture::RG_Integer, QOpenGLTexture::RG16U, QOpenGLTexture::UInt16, 4, false } }, - { DXGI_FORMAT_R16G16B16A16_UINT, { QOpenGLTexture::RGBA_Integer, QOpenGLTexture::RGBA16U, QOpenGLTexture::UInt16, 8, false } }, - - { DXGI_FORMAT_R32_UINT, { QOpenGLTexture::Red_Integer, QOpenGLTexture::R32U, QOpenGLTexture::UInt32, 4, false } }, - { DXGI_FORMAT_R32G32_UINT, { QOpenGLTexture::RG_Integer, QOpenGLTexture::RG32U, QOpenGLTexture::UInt32, 8, false } }, - { DXGI_FORMAT_R32G32B32_UINT, { QOpenGLTexture::RGB_Integer, QOpenGLTexture::RGB32U, QOpenGLTexture::UInt32, 12, false } }, - { DXGI_FORMAT_R32G32B32A32_UINT, { QOpenGLTexture::RGBA_Integer, QOpenGLTexture::RGBA32U, QOpenGLTexture::UInt32, 16, false } }, - - // signed integer formats - { DXGI_FORMAT_R8_SINT, { QOpenGLTexture::Red_Integer, QOpenGLTexture::R8I, QOpenGLTexture::Int8, 1, false } }, - { DXGI_FORMAT_R8G8_SINT, { QOpenGLTexture::RG_Integer, QOpenGLTexture::RG8I, QOpenGLTexture::Int8, 2, false } }, - { DXGI_FORMAT_R8G8B8A8_SINT, { QOpenGLTexture::RGBA_Integer, QOpenGLTexture::RGBA8I, QOpenGLTexture::Int8, 4, false } }, - - { DXGI_FORMAT_R16_SINT, { QOpenGLTexture::Red_Integer, QOpenGLTexture::R16I, QOpenGLTexture::Int16, 2, false } }, - { DXGI_FORMAT_R16G16_SINT, { QOpenGLTexture::RG_Integer, QOpenGLTexture::RG16I, QOpenGLTexture::Int16, 4, false } }, - { DXGI_FORMAT_R16G16B16A16_SINT, { QOpenGLTexture::RGBA_Integer, QOpenGLTexture::RGBA16I, QOpenGLTexture::Int16, 8, false } }, - - { DXGI_FORMAT_R32_SINT, { QOpenGLTexture::Red_Integer, QOpenGLTexture::R32I, QOpenGLTexture::Int32, 4, false } }, - { DXGI_FORMAT_R32G32_SINT, { QOpenGLTexture::RG_Integer, QOpenGLTexture::RG32I, QOpenGLTexture::Int32, 8, false } }, - { DXGI_FORMAT_R32G32B32_SINT, { QOpenGLTexture::RGB_Integer, QOpenGLTexture::RGB32I, QOpenGLTexture::Int32, 12, false } }, - { DXGI_FORMAT_R32G32B32A32_SINT, { QOpenGLTexture::RGBA_Integer, QOpenGLTexture::RGBA32I, QOpenGLTexture::Int32, 16, false } }, - - // floating formats - { DXGI_FORMAT_R16_FLOAT, { QOpenGLTexture::Red, QOpenGLTexture::R16F, QOpenGLTexture::Float16, 2, false } }, - { DXGI_FORMAT_R16G16_FLOAT, { QOpenGLTexture::RG, QOpenGLTexture::RG16F, QOpenGLTexture::Float16, 4, false } }, - { DXGI_FORMAT_R16G16B16A16_FLOAT, { QOpenGLTexture::RGBA, QOpenGLTexture::RGBA16F, QOpenGLTexture::Float16, 8, false } }, - - { DXGI_FORMAT_R32_FLOAT, { QOpenGLTexture::Red, QOpenGLTexture::R32F, QOpenGLTexture::Float32, 4, false } }, - { DXGI_FORMAT_R32G32_FLOAT, { QOpenGLTexture::RG, QOpenGLTexture::RG32F, QOpenGLTexture::Float32, 8, false } }, - { DXGI_FORMAT_R32G32B32_FLOAT, { QOpenGLTexture::RGB, QOpenGLTexture::RGB32F, QOpenGLTexture::Float32, 12, false } }, - { DXGI_FORMAT_R32G32B32A32_FLOAT, { QOpenGLTexture::RGBA, QOpenGLTexture::RGBA32F, QOpenGLTexture::Float32, 16, false } }, - - // sRGB formats - { DXGI_FORMAT_B8G8R8X8_UNORM_SRGB, { QOpenGLTexture::RGB, QOpenGLTexture::SRGB8, QOpenGLTexture::UInt8, 4, false } }, - { DXGI_FORMAT_R8G8B8A8_UNORM_SRGB, { QOpenGLTexture::RGBA, QOpenGLTexture::SRGB8_Alpha8, QOpenGLTexture::UInt8, 4, false } }, - - // packed formats - // { DXGI_FORMAT_R10G10B10A2_UNORM, { QOpenGLTexture::RGB10A2_UNORM, QOpenGLTexture::RGBA, QOpenGLTexture::UInt32_RGB10A2, 4, false } }, - { DXGI_FORMAT_R10G10B10A2_UINT, { QOpenGLTexture::RGBA_Integer, QOpenGLTexture::RGB10A2, QOpenGLTexture::UInt32_RGB10A2, 4, false } }, - { DXGI_FORMAT_R9G9B9E5_SHAREDEXP, { QOpenGLTexture::RGB, QOpenGLTexture::RGB9E5, QOpenGLTexture::UInt32_RGB9_E5, 4, false } }, - { DXGI_FORMAT_R11G11B10_FLOAT, { QOpenGLTexture::RGB, QOpenGLTexture::RG11B10F, QOpenGLTexture::UInt32_RG11B10F, 4, false } }, - { DXGI_FORMAT_B5G6R5_UNORM, { QOpenGLTexture::RGB, QOpenGLTexture::R5G6B5, QOpenGLTexture::UInt16_R5G6B5, 2, false } }, - { DXGI_FORMAT_B5G5R5A1_UNORM, { QOpenGLTexture::RGBA, QOpenGLTexture::RGB5A1, QOpenGLTexture::UInt16_RGB5A1, 2, false } }, - { DXGI_FORMAT_B4G4R4A4_UNORM, { QOpenGLTexture::RGBA, QOpenGLTexture::RGBA4, QOpenGLTexture::UInt16_RGBA4, 2, false } }, - - // swizzle formats - { DXGI_FORMAT_B8G8R8X8_UNORM, { QOpenGLTexture::BGRA, QOpenGLTexture::RGB8_UNorm, QOpenGLTexture::UInt8, 4, false } }, - { DXGI_FORMAT_B8G8R8A8_UNORM, { QOpenGLTexture::BGRA, QOpenGLTexture::RGBA8_UNorm, QOpenGLTexture::UInt8, 4, false } }, - { DXGI_FORMAT_B8G8R8X8_UNORM_SRGB, { QOpenGLTexture::BGRA, QOpenGLTexture::SRGB8, QOpenGLTexture::UInt8, 4, false } }, - { DXGI_FORMAT_B8G8R8A8_UNORM_SRGB, { QOpenGLTexture::BGRA, QOpenGLTexture::SRGB8_Alpha8, QOpenGLTexture::UInt8, 4, false } }, - - // luminance alpha formats - { DXGI_FORMAT_R8_UNORM, { QOpenGLTexture::Red, QOpenGLTexture::R8_UNorm, QOpenGLTexture::UInt8, 1, false } }, - { DXGI_FORMAT_R8G8_UNORM, { QOpenGLTexture::RG, QOpenGLTexture::RG8_UNorm, QOpenGLTexture::UInt8, 2, false } }, - { DXGI_FORMAT_R16_UNORM, { QOpenGLTexture::Red, QOpenGLTexture::R16_UNorm, QOpenGLTexture::UInt16, 2, false } }, - { DXGI_FORMAT_R16_UNORM, { QOpenGLTexture::RG, QOpenGLTexture::RG16_UNorm, QOpenGLTexture::UInt16, 4, false } }, - - // depth formats - { DXGI_FORMAT_D16_UNORM, { QOpenGLTexture::Depth, QOpenGLTexture::D16, QOpenGLTexture::NoPixelType, 2, false } }, - { DXGI_FORMAT_D24_UNORM_S8_UINT, { QOpenGLTexture::DepthStencil, QOpenGLTexture::D24S8, QOpenGLTexture::NoPixelType, 4, false } }, - { DXGI_FORMAT_D32_FLOAT, { QOpenGLTexture::Depth, QOpenGLTexture::D32F, QOpenGLTexture::NoPixelType, 4, false } }, - { DXGI_FORMAT_D32_FLOAT_S8X24_UINT, { QOpenGLTexture::DepthStencil, QOpenGLTexture::D32FS8X24, QOpenGLTexture::NoPixelType, 8, false } }, - - // compressed formats - { DXGI_FORMAT_BC1_UNORM, { QOpenGLTexture::NoSourceFormat, QOpenGLTexture::RGBA_DXT1, QOpenGLTexture::NoPixelType, 8, true } }, - { DXGI_FORMAT_BC2_UNORM, { QOpenGLTexture::NoSourceFormat, QOpenGLTexture::RGBA_DXT3, QOpenGLTexture::NoPixelType, 16, true } }, - { DXGI_FORMAT_BC3_UNORM, { QOpenGLTexture::NoSourceFormat, QOpenGLTexture::RGBA_DXT5, QOpenGLTexture::NoPixelType, 16, true } }, - { DXGI_FORMAT_BC4_UNORM, { QOpenGLTexture::NoSourceFormat, QOpenGLTexture::R_ATI1N_UNorm, QOpenGLTexture::NoPixelType, 8, true } }, - { DXGI_FORMAT_BC4_SNORM, { QOpenGLTexture::NoSourceFormat, QOpenGLTexture::R_ATI1N_SNorm, QOpenGLTexture::NoPixelType, 8, true } }, - { DXGI_FORMAT_BC5_UNORM, { QOpenGLTexture::NoSourceFormat, QOpenGLTexture::RG_ATI2N_UNorm, QOpenGLTexture::NoPixelType, 16, true } }, - { DXGI_FORMAT_BC5_SNORM, { QOpenGLTexture::NoSourceFormat, QOpenGLTexture::RG_ATI2N_SNorm, QOpenGLTexture::NoPixelType, 16, true } }, - { DXGI_FORMAT_BC6H_UF16, { QOpenGLTexture::NoSourceFormat, QOpenGLTexture::RGB_BP_UNSIGNED_FLOAT, QOpenGLTexture::NoPixelType, 16, true } }, - { DXGI_FORMAT_BC6H_SF16, { QOpenGLTexture::NoSourceFormat, QOpenGLTexture::RGB_BP_SIGNED_FLOAT, QOpenGLTexture::NoPixelType, 16, true } }, - { DXGI_FORMAT_BC7_UNORM, { QOpenGLTexture::NoSourceFormat, QOpenGLTexture::RGB_BP_UNorm, QOpenGLTexture::NoPixelType, 16, true } }, - - // compressed sRGB formats - { DXGI_FORMAT_BC1_UNORM_SRGB, { QOpenGLTexture::NoSourceFormat, QOpenGLTexture::SRGB_DXT1, QOpenGLTexture::NoPixelType, 8, true } }, - { DXGI_FORMAT_BC1_UNORM_SRGB, { QOpenGLTexture::NoSourceFormat, QOpenGLTexture::SRGB_Alpha_DXT1, QOpenGLTexture::NoPixelType, 8, true } }, - { DXGI_FORMAT_BC2_UNORM_SRGB, { QOpenGLTexture::NoSourceFormat, QOpenGLTexture::SRGB_Alpha_DXT3, QOpenGLTexture::NoPixelType, 16, true } }, - { DXGI_FORMAT_BC3_UNORM_SRGB, { QOpenGLTexture::NoSourceFormat, QOpenGLTexture::SRGB_Alpha_DXT5, QOpenGLTexture::NoPixelType, 16, true } }, - { DXGI_FORMAT_BC7_UNORM_SRGB, { QOpenGLTexture::NoSourceFormat, QOpenGLTexture::SRGB_BP_UNorm, QOpenGLTexture::NoPixelType, 16, true } }, -}; - -} // namespace - QTextureImageDataPrivate::QTextureImageDataPrivate() : m_width(-1) , m_height(-1) @@ -425,10 +66,12 @@ QByteArray QTextureImageDataPrivate::data(int layer, int face, int mipmapLevel) { if (layer < 0 || layer >= m_layers || face < 0 || face >= m_faces || - mipmapLevel < 0 || mipmapLevel >= m_mipLevels) + mipmapLevel < 0 || mipmapLevel >= m_mipLevels) { + qWarning() << Q_FUNC_INFO << "Requesting texture data for invalid layer, face or mipMapLevel"; return QByteArray(); + } - int offset = layer*layerSize() + face*faceSize(); + int offset = layer * layerSize() + face * faceSize(); for (int i = 0; i < mipmapLevel; i++) offset += mipmapLevelSize(i); @@ -436,204 +79,18 @@ QByteArray QTextureImageDataPrivate::data(int layer, int face, int mipmapLevel) return QByteArray::fromRawData(m_data.constData() + offset, mipmapLevelSize(mipmapLevel)); } -void QTextureImageDataPrivate::setData(const QByteArray &data, QOpenGLTexture::PixelFormat fmt, - QOpenGLTexture::PixelType ptype) +void QTextureImageDataPrivate::setData(const QByteArray &data, + int blockSize, + bool isCompressed) { - m_isCompressed = false; + m_isCompressed = isCompressed; m_data = data; - m_layers = 1; - m_faces = 1; - m_mipLevels = 1; - m_target = QOpenGLTexture::Target2D; - m_pixelFormat = fmt; - m_pixelType = ptype; -} - -bool QTextureImageDataPrivate::setCompressedFile(const QString &source) -{ - QString suffix = QFileInfo(source).suffix(); - - if (suffix == QLatin1String("pkm")) - return setPkmFile(source); - else if (suffix == QLatin1String("dds")) - return setDdsFile(source); - else - return false; -} - -bool QTextureImageDataPrivate::setPkmFile(const QString &source) -{ - QFile f(source); - if (!f.open(QIODevice::ReadOnly)) { - qWarning() << "Failed to open" << source; - return false; - } - - // ETC1 in PKM, as generated by f.ex. Android's etc1tool - static const char pkmMagic[] = { 'P', 'K', 'M', ' ', '1', '0' }; - const int pkmHeaderSize = 6 + 2 + 4 * 2; - QByteArray header = f.read(pkmHeaderSize); - if (header.size() >= pkmHeaderSize && !qstrncmp(header.constData(), pkmMagic, 6)) { - m_format = QOpenGLTexture::RGB8_ETC1; // may get changed to RGB8_ETC2 later on - // get the extended (multiple of 4) width and height - m_width = qFromBigEndian(*(reinterpret_cast<const quint16 *>(header.constData() + 6 + 2))); - m_height = qFromBigEndian(*(reinterpret_cast<const quint16 *>(header.constData() + 6 + 2 + 2))); - m_depth = 1; - QByteArray data = f.readAll(); - if (data.size() < (m_width / 4) * (m_height / 4) * 8) - qWarning() << "Unexpected end of ETC1 data in" << source; - setData(data, QOpenGLTexture::RGBA, QOpenGLTexture::UInt8); - m_blockSize = 8; - m_isCompressed = true; - return true; - } - - return false; -} - -static int bitCount(quint32 n) -{ - int r = 0; - - for (; n; n >>= 1) - r += (n & 1); - - return r; -} - -bool QTextureImageDataPrivate::setDdsFile(const QString &source) -{ - QFile f(source); - if (!f.open(QIODevice::ReadOnly)) { - qWarning() << "Failed to open" << source; - return false; - } - - DdsHeader header; - if (f.read(reinterpret_cast<char *>(&header), sizeof header) != sizeof header) - return false; - - if (qstrncmp(header.magic, "DDS ", 4) != 0) - return false; - - // dimensions - - m_width = qFromLittleEndian(header.width); - m_height = qFromLittleEndian(header.height); - - // mip levels - - if ((qFromLittleEndian(header.flags) & MipmapCountFlag) == MipmapCountFlag) - m_mipLevels = qFromLittleEndian(header.mipmapCount); - else - m_mipLevels = 1; - - // texture format - - m_layers = 1; - - const quint32 pixelFlags = qFromLittleEndian(header.pixelFormat.flags); - const quint32 fourCC = qFromLittleEndian(header.pixelFormat.fourCC); - - const FormatInfo *formatInfo = nullptr; - - if ((pixelFlags & FourCCFlag) == FourCCFlag) { - if (fourCC == DdsFourCC<'D', 'X', '1', '0'>::value) { - // DX10 texture - - DdsDX10Header dx10Header; - if (f.read(reinterpret_cast<char *>(&dx10Header), sizeof dx10Header) != sizeof dx10Header) - return false; - - m_layers = qFromLittleEndian(dx10Header.arraySize); - - DXGIFormat format = static_cast<DXGIFormat>(qFromLittleEndian(dx10Header.format)); - - for (unsigned i = 0; i < sizeof dx10Formats/sizeof *dx10Formats; i++) { - if (dx10Formats[i].dxgiFormat == format) { - formatInfo = &dx10Formats[i].formatInfo; - break; - } - } - } else { - // compressed, FourCC texture - - for (unsigned i = 0; i < sizeof fourCCFormats/sizeof *fourCCFormats; i++) { - if (fourCCFormats[i].fourCC == fourCC) { - formatInfo = &fourCCFormats[i].formatInfo; - break; - } - } - } - } else { - // uncompressed texture - - m_pixelFormat = QOpenGLTexture::NoSourceFormat; - - const quint32 rgbBitCount = qFromLittleEndian(header.pixelFormat.rgbBitCount); - const quint32 redMask = qFromLittleEndian(header.pixelFormat.redMask); - const quint32 greenMask = qFromLittleEndian(header.pixelFormat.greenMask); - const quint32 blueMask = qFromLittleEndian(header.pixelFormat.blueMask); - const quint32 alphaMask = qFromLittleEndian(header.pixelFormat.alphaMask); - - for (unsigned i = 0; i < sizeof rgbaFormats/sizeof *rgbaFormats; i++) { - const RGBAFormat *info = &rgbaFormats[i]; - - if (info->formatInfo.components*8u == rgbBitCount && - info->redMask == redMask && info->greenMask == greenMask && - info->blueMask == blueMask && info->alphaMask == alphaMask) { - formatInfo = &info->formatInfo; - break; - } - } - } - - if (formatInfo == nullptr) { - qWarning() << "Unrecognized pixel format in" << source; - return false; - } - - m_pixelFormat = formatInfo->pixelFormat; - m_format = formatInfo->textureFormat; - m_pixelType = formatInfo->pixelType; - m_blockSize = formatInfo->components; - m_isCompressed = formatInfo->compressed; - - // target - - // XXX should worry about Target1D? - - const quint32 caps2Flags = qFromLittleEndian(header.caps2); - - if ((caps2Flags & VolumeFlag) == VolumeFlag) { - m_target = QOpenGLTexture::Target3D; - m_depth = qFromLittleEndian(header.depth); - m_faces = 1; - } else if ((caps2Flags & CubemapFlag) == CubemapFlag) { - m_target = m_layers > 1 ? QOpenGLTexture::TargetCubeMapArray : QOpenGLTexture::TargetCubeMap; - m_depth = 1; - m_faces = bitCount(caps2Flags & AllCubemapFaceFlags); - } else { - m_target = m_layers > 1 ? QOpenGLTexture::Target2DArray : QOpenGLTexture::Target2D; - m_depth = 1; - m_faces = 1; - } - - // data - - m_data = f.readAll(); - - if (m_data.size() != m_layers*layerSize()) { - qWarning() << "Unexpected data size (got " << m_data.size() << ", expecting" << m_layers*layerSize() << ")"; - return false; - } - - return true; + m_blockSize = blockSize; } int QTextureImageDataPrivate::layerSize() const { - return m_faces*faceSize(); + return m_faces * faceSize(); } int QTextureImageDataPrivate::faceSize() const @@ -738,6 +195,42 @@ int QTextureImageData::faces() const Q_DECL_NOTHROW return d->m_faces;; } +void QTextureImageData::setWidth(int width) Q_DECL_NOTHROW +{ + Q_D(QTextureImageData); + d->m_width = width; +} + +void QTextureImageData::setHeight(int height) Q_DECL_NOTHROW +{ + Q_D(QTextureImageData); + d->m_height = height; +} + +void QTextureImageData::setDepth(int depth) Q_DECL_NOTHROW +{ + Q_D(QTextureImageData); + d->m_depth = depth; +} + +void QTextureImageData::setLayers(int layers) Q_DECL_NOTHROW +{ + Q_D(QTextureImageData); + d->m_layers = layers; +} + +void QTextureImageData::setMipLevels(int mipLevels) Q_DECL_NOTHROW +{ + Q_D(QTextureImageData); + d->m_mipLevels = mipLevels; +} + +void QTextureImageData::setFaces(int faces) Q_DECL_NOTHROW +{ + Q_D(QTextureImageData); + d->m_faces = faces; +} + QOpenGLTexture::Target QTextureImageData::target() const Q_DECL_NOTHROW { Q_D(const QTextureImageData); @@ -750,33 +243,55 @@ QOpenGLTexture::TextureFormat QTextureImageData::format() const Q_DECL_NOTHROW return d->m_format; } +void QTextureImageData::setTarget(QOpenGLTexture::Target target) Q_DECL_NOTHROW +{ + Q_D(QTextureImageData); + d->m_target = target; +} + +void QTextureImageData::setFormat(QOpenGLTexture::TextureFormat format) Q_DECL_NOTHROW +{ + Q_D(QTextureImageData); + d->m_format = format; +} + +void QTextureImageData::setPixelFormat(QOpenGLTexture::PixelFormat pixelFormat) Q_DECL_NOTHROW +{ + Q_D(QTextureImageData); + d->m_pixelFormat = pixelFormat; +} + +void QTextureImageData::setPixelType(QOpenGLTexture::PixelType pixelType) Q_DECL_NOTHROW +{ + Q_D(QTextureImageData); + d->m_pixelType = pixelType; +} + void QTextureImageData::setImage(const QImage &image) { Q_D(QTextureImageData); d->m_width = image.width(); d->m_height = image.height(); d->m_depth = 1; - + d->m_faces = 1; + d->m_layers = 1; + d->m_mipLevels = 1; QImage glImage = image.convertToFormat(QImage::Format_RGBA8888); Q_ASSERT_X(glImage.bytesPerLine() == (glImage.width() * glImage.depth() + 7) / 8, "QTextureImageData::setImage", "glImage is not packed"); // QTBUG-48330 + d->m_blockSize = 4; QByteArray imageBytes((const char*) glImage.constBits(), glImage.byteCount()); - setData(imageBytes, QOpenGLTexture::RGBA, QOpenGLTexture::UInt8); + setData(imageBytes, d->m_blockSize, false); d->m_format = QOpenGLTexture::RGBA8_UNorm; - d->m_blockSize = 4; -} - -void QTextureImageData::setData(const QByteArray &data, QOpenGLTexture::PixelFormat fmt, - QOpenGLTexture::PixelType ptype) -{ - Q_D(QTextureImageData); - d->setData(data, fmt, ptype); + d->m_pixelFormat = QOpenGLTexture::RGBA; + d->m_pixelType = QOpenGLTexture::UInt8; + d->m_target = QOpenGLTexture::Target2D; } -bool QTextureImageData::setCompressedFile(const QString &source) +void QTextureImageData::setData(const QByteArray &data, int blockSize, bool isCompressed) { Q_D(QTextureImageData); - return d->setCompressedFile(source); + d->setData(data, blockSize, isCompressed); } QByteArray QTextureImageData::data(int layer, int face, int mipmapLevel) const diff --git a/src/render/texture/qtextureimagedata.h b/src/render/texture/qtextureimagedata.h index c1cc40593..6d66f2390 100644 --- a/src/render/texture/qtextureimagedata.h +++ b/src/render/texture/qtextureimagedata.h @@ -71,24 +71,32 @@ public: int mipLevels() const Q_DECL_NOTHROW; int faces() const Q_DECL_NOTHROW; - QOpenGLTexture::Target target() const Q_DECL_NOTHROW; - - QOpenGLTexture::TextureFormat format() const Q_DECL_NOTHROW; + void setWidth(int width) Q_DECL_NOTHROW; + void setHeight(int height) Q_DECL_NOTHROW; + void setDepth(int depth) Q_DECL_NOTHROW; - void setImage(const QImage &); + void setLayers(int layers) Q_DECL_NOTHROW; + void setMipLevels(int mipLevels) Q_DECL_NOTHROW; + void setFaces(int faces) Q_DECL_NOTHROW; - void setData(const QByteArray &data, - QOpenGLTexture::PixelFormat fmt, - QOpenGLTexture::PixelType ptype); + QOpenGLTexture::Target target() const Q_DECL_NOTHROW; + QOpenGLTexture::TextureFormat format() const Q_DECL_NOTHROW; - bool setCompressedFile(const QString &source); + QOpenGLTexture::PixelFormat pixelFormat() const Q_DECL_NOTHROW; + QOpenGLTexture::PixelType pixelType() const Q_DECL_NOTHROW; - QByteArray data(int layer = 0, int face = 0, int mipmapLevel = 0) const; + void setTarget(QOpenGLTexture::Target target) Q_DECL_NOTHROW; + void setFormat(QOpenGLTexture::TextureFormat format) Q_DECL_NOTHROW; - QOpenGLTexture::PixelFormat pixelFormat() const Q_DECL_NOTHROW; + void setPixelFormat(QOpenGLTexture::PixelFormat pixelFormat) Q_DECL_NOTHROW; + void setPixelType(QOpenGLTexture::PixelType pixelType) Q_DECL_NOTHROW; - QOpenGLTexture::PixelType pixelType() const Q_DECL_NOTHROW; + void setImage(const QImage &); + void setData(const QByteArray &data, + int blockSize, + bool isCompressed = false); + QByteArray data(int layer = 0, int face = 0, int mipmapLevel = 0) const; protected: QTextureImageData(QTextureImageDataPrivate &dd); diff --git a/src/render/texture/qtextureimagedata_p.h b/src/render/texture/qtextureimagedata_p.h index 6d46ae1b7..4426ba27b 100644 --- a/src/render/texture/qtextureimagedata_p.h +++ b/src/render/texture/qtextureimagedata_p.h @@ -62,8 +62,7 @@ class QTextureImageDataPrivate public: QTextureImageDataPrivate(); - void setData(const QByteArray &data, QOpenGLTexture::PixelFormat fmt, - QOpenGLTexture::PixelType ptype); + void setData(const QByteArray &data, int blockSize, bool isCompressed); bool setCompressedFile(const QString &source); diff --git a/src/render/texture/texture.cpp b/src/render/texture/texture.cpp index f0aef843e..387a00b3b 100644 --- a/src/render/texture/texture.cpp +++ b/src/render/texture/texture.cpp @@ -269,9 +269,6 @@ QOpenGLTexture *Texture::buildGLTexture() QOpenGLTexture* glTex = new QOpenGLTexture(static_cast<QOpenGLTexture::Target>(m_target)); - if (m_format == QAbstractTexture::Automatic) - qWarning() << Q_FUNC_INFO << "something went wrong, format shouldn't be automatic at this point"; - // m_format may not be ES2 compatible. Now it's time to convert it, if necessary. QAbstractTexture::TextureFormat format = m_format; if (ctx->isOpenGLES() && ctx->format().majorVersion() < 3) { |