diff options
Diffstat (limited to 'libs/preview_dds_native/src')
| -rw-r--r-- | libs/preview_dds_native/src/CMakeLists.txt | 17 | ||||
| -rw-r--r-- | libs/preview_dds_native/src/ddsfile.cpp | 132 | ||||
| -rw-r--r-- | libs/preview_dds_native/src/ddsfile.h | 47 | ||||
| -rw-r--r-- | libs/preview_dds_native/src/ddsformat.cpp | 619 | ||||
| -rw-r--r-- | libs/preview_dds_native/src/ddsformat.h | 200 | ||||
| -rw-r--r-- | libs/preview_dds_native/src/ddspreview.cpp | 126 | ||||
| -rw-r--r-- | libs/preview_dds_native/src/ddspreview.h | 44 | ||||
| -rw-r--r-- | libs/preview_dds_native/src/ddswidget.cpp | 252 | ||||
| -rw-r--r-- | libs/preview_dds_native/src/ddswidget.h | 36 |
9 files changed, 0 insertions, 1473 deletions
diff --git a/libs/preview_dds_native/src/CMakeLists.txt b/libs/preview_dds_native/src/CMakeLists.txt deleted file mode 100644 index c920d49..0000000 --- a/libs/preview_dds_native/src/CMakeLists.txt +++ /dev/null @@ -1,17 +0,0 @@ -cmake_minimum_required(VERSION 3.16) - -find_package(Qt6 REQUIRED COMPONENTS OpenGL OpenGLWidgets) - -file(GLOB preview_dds_native_SOURCES CONFIGURE_DEPENDS - ${CMAKE_CURRENT_SOURCE_DIR}/*.cpp - ${CMAKE_CURRENT_SOURCE_DIR}/*.h -) - -add_library(preview_dds_native SHARED ${preview_dds_native_SOURCES}) -mo2_configure_plugin(preview_dds_native NO_SOURCES WARNINGS OFF) -target_link_libraries(preview_dds_native PRIVATE - mo2::uibase - Qt6::OpenGL - Qt6::OpenGLWidgets -) -mo2_install_plugin(preview_dds_native) diff --git a/libs/preview_dds_native/src/ddsfile.cpp b/libs/preview_dds_native/src/ddsfile.cpp deleted file mode 100644 index 91dc627..0000000 --- a/libs/preview_dds_native/src/ddsfile.cpp +++ /dev/null @@ -1,132 +0,0 @@ -#include "ddsfile.h" - -#include <QFile> - -#include <algorithm> -#include <cstring> - -bool DDSFile::loadFromFile(const QString& path) -{ - QFile file(path); - if (!file.open(QIODevice::ReadOnly)) { - return false; - } - return parse(file.readAll()); -} - -bool DDSFile::loadFromData(const QByteArray& data) -{ - return parse(data); -} - -bool DDSFile::parse(const QByteArray& data) -{ - const char* ptr = data.constData(); - int offset = 0; - int size = data.size(); - - // Magic number - if (size < 4) - return false; - uint32_t magic; - std::memcpy(&magic, ptr + offset, 4); - offset += 4; - if (magic != DDS_MAGIC) - return false; - - // DDS header - if (size - offset < static_cast<int>(sizeof(DDSHeader))) - return false; - DDSHeader header; - std::memcpy(&header, ptr + offset, sizeof(DDSHeader)); - offset += sizeof(DDSHeader); - - if (header.dwSize != 124) - return false; - - // DXT10 extended header - DDSHeaderDXT10 dxt10{}; - bool hasDXT10 = false; - if ((header.ddspf.dwFlags & DDPF_FOURCC) && - header.ddspf.dwFourCC == makeFourCC('D', 'X', '1', '0')) { - if (size - offset < static_cast<int>(sizeof(DDSHeaderDXT10))) - return false; - std::memcpy(&dxt10, ptr + offset, sizeof(DDSHeaderDXT10)); - offset += sizeof(DDSHeaderDXT10); - hasDXT10 = true; - } - - m_width = header.dwWidth; - m_height = header.dwHeight; - - // Determine GL format - m_glFormat = getGLFormat(header.ddspf, hasDXT10 ? &dxt10 : nullptr); - if (!m_glFormat.valid) { - return false; - } - - // Determine DXGI format for size calculations - if (hasDXT10) { - m_dxgiFormat = dxt10.dxgiFormat; - } else if (header.ddspf.dwFlags & DDPF_FOURCC) { - m_dxgiFormat = fourCCToDXGI(header.ddspf.dwFourCC); - } else { - m_dxgiFormat = DXGIFormat::UNKNOWN; - } - - // Description - m_description = formatDescription(header.ddspf, hasDXT10 ? &dxt10 : nullptr); - m_description += - QString(" | %1x%2").arg(m_width).arg(m_height); - - // Cubemap detection - m_cubemap = false; - int layers = 1; - if (header.dwCaps2 & DDSCAPS2_CUBEMAP) { - m_cubemap = true; - layers = 0; - if (header.dwCaps2 & DDSCAPS2_CUBEMAP_POSITIVEX) layers++; - if (header.dwCaps2 & DDSCAPS2_CUBEMAP_NEGATIVEX) layers++; - if (header.dwCaps2 & DDSCAPS2_CUBEMAP_POSITIVEY) layers++; - if (header.dwCaps2 & DDSCAPS2_CUBEMAP_NEGATIVEY) layers++; - if (header.dwCaps2 & DDSCAPS2_CUBEMAP_POSITIVEZ) layers++; - if (header.dwCaps2 & DDSCAPS2_CUBEMAP_NEGATIVEZ) layers++; - m_description += " | Cubemap"; - } else { - m_description += " | 2D"; - } - - // Mipmap count - int mipCount = 1; - if (header.dwFlags & DDSD_MIPMAPCOUNT) { - mipCount = std::max(1u, header.dwMipMapCount); - } - if (mipCount > 1) { - m_description += QString(" | %1 mips").arg(mipCount); - } - - // Read pixel data for each face and mip level - m_faces.resize(layers); - for (int face = 0; face < layers; ++face) { - m_faces[face].mips.resize(mipCount); - uint32_t w = m_width; - uint32_t h = m_height; - for (int mip = 0; mip < mipCount; ++mip) { - uint32_t dataSize = mipDataSize(m_dxgiFormat, header.ddspf, w, h); - if (offset + static_cast<int>(dataSize) > size) { - // Truncated file, keep what we have - m_faces[face].mips.resize(mip); - break; - } - m_faces[face].mips[mip].width = w; - m_faces[face].mips[mip].height = h; - m_faces[face].mips[mip].data = - QByteArray(ptr + offset, static_cast<int>(dataSize)); - offset += dataSize; - w = std::max(1u, w / 2); - h = std::max(1u, h / 2); - } - } - - return !m_faces.isEmpty() && !m_faces[0].mips.isEmpty(); -} diff --git a/libs/preview_dds_native/src/ddsfile.h b/libs/preview_dds_native/src/ddsfile.h deleted file mode 100644 index 4242c61..0000000 --- a/libs/preview_dds_native/src/ddsfile.h +++ /dev/null @@ -1,47 +0,0 @@ -#ifndef DDSFILE_H -#define DDSFILE_H - -#include "ddsformat.h" - -#include <QByteArray> -#include <QString> -#include <QVector> - -struct DDSMipLevel { - uint32_t width; - uint32_t height; - QByteArray data; -}; - -struct DDSFace { - QVector<DDSMipLevel> mips; -}; - -class DDSFile -{ -public: - bool loadFromFile(const QString& path); - bool loadFromData(const QByteArray& data); - - uint32_t width() const { return m_width; } - uint32_t height() const { return m_height; } - bool isCubemap() const { return m_cubemap; } - int faceCount() const { return m_faces.size(); } - int mipCount() const { return m_faces.isEmpty() ? 0 : m_faces[0].mips.size(); } - const DDSFace& face(int i) const { return m_faces[i]; } - const GLFormatInfo& glFormat() const { return m_glFormat; } - QString description() const { return m_description; } - -private: - bool parse(const QByteArray& data); - - uint32_t m_width = 0; - uint32_t m_height = 0; - bool m_cubemap = false; - GLFormatInfo m_glFormat; - DXGIFormat m_dxgiFormat = DXGIFormat::UNKNOWN; - QString m_description; - QVector<DDSFace> m_faces; -}; - -#endif // DDSFILE_H diff --git a/libs/preview_dds_native/src/ddsformat.cpp b/libs/preview_dds_native/src/ddsformat.cpp deleted file mode 100644 index b56db91..0000000 --- a/libs/preview_dds_native/src/ddsformat.cpp +++ /dev/null @@ -1,619 +0,0 @@ -#include "ddsformat.h" - -#include <QOpenGLFunctions> -#include <QString> - -#include <algorithm> -#include <cstring> - -// GL compressed format constants not always in headers -#ifndef GL_COMPRESSED_RGB_S3TC_DXT1_EXT -#define GL_COMPRESSED_RGB_S3TC_DXT1_EXT 0x83F0 -#endif -#ifndef GL_COMPRESSED_RGBA_S3TC_DXT1_EXT -#define GL_COMPRESSED_RGBA_S3TC_DXT1_EXT 0x83F1 -#endif -#ifndef GL_COMPRESSED_RGBA_S3TC_DXT3_EXT -#define GL_COMPRESSED_RGBA_S3TC_DXT3_EXT 0x83F2 -#endif -#ifndef GL_COMPRESSED_RGBA_S3TC_DXT5_EXT -#define GL_COMPRESSED_RGBA_S3TC_DXT5_EXT 0x83F3 -#endif -#ifndef GL_COMPRESSED_RED_RGTC1 -#define GL_COMPRESSED_RED_RGTC1 0x8DBB -#endif -#ifndef GL_COMPRESSED_SIGNED_RED_RGTC1 -#define GL_COMPRESSED_SIGNED_RED_RGTC1 0x8DBC -#endif -#ifndef GL_COMPRESSED_RG_RGTC2 -#define GL_COMPRESSED_RG_RGTC2 0x8DBD -#endif -#ifndef GL_COMPRESSED_SIGNED_RG_RGTC2 -#define GL_COMPRESSED_SIGNED_RG_RGTC2 0x8DBE -#endif -#ifndef GL_COMPRESSED_RGB_BPTC_UNSIGNED_FLOAT -#define GL_COMPRESSED_RGB_BPTC_UNSIGNED_FLOAT 0x8E8F -#endif -#ifndef GL_COMPRESSED_RGB_BPTC_SIGNED_FLOAT -#define GL_COMPRESSED_RGB_BPTC_SIGNED_FLOAT 0x8E8E -#endif -#ifndef GL_COMPRESSED_RGBA_BPTC_UNORM -#define GL_COMPRESSED_RGBA_BPTC_UNORM 0x8E8C -#endif -#ifndef GL_COMPRESSED_SRGB_ALPHA_BPTC_UNORM -#define GL_COMPRESSED_SRGB_ALPHA_BPTC_UNORM 0x8E8D -#endif -#ifndef GL_COMPRESSED_SRGB_S3TC_DXT1_EXT -#define GL_COMPRESSED_SRGB_S3TC_DXT1_EXT 0x8C4C -#endif -#ifndef GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT -#define GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT 0x8C4D -#endif -#ifndef GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT -#define GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT 0x8C4E -#endif -#ifndef GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT -#define GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT 0x8C4F -#endif - -static GLFormatInfo dxgiToGL(DXGIFormat fmt) -{ - GLFormatInfo info; - info.valid = true; - - switch (fmt) { - // BC1 (DXT1) - case DXGIFormat::BC1_UNORM: - info.compressed = true; - info.internalFormat = GL_COMPRESSED_RGBA_S3TC_DXT1_EXT; - break; - case DXGIFormat::BC1_UNORM_SRGB: - info.compressed = true; - info.internalFormat = GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT; - break; - // BC2 (DXT3) - case DXGIFormat::BC2_UNORM: - info.compressed = true; - info.internalFormat = GL_COMPRESSED_RGBA_S3TC_DXT3_EXT; - break; - case DXGIFormat::BC2_UNORM_SRGB: - info.compressed = true; - info.internalFormat = GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT; - break; - // BC3 (DXT5) - case DXGIFormat::BC3_UNORM: - info.compressed = true; - info.internalFormat = GL_COMPRESSED_RGBA_S3TC_DXT5_EXT; - break; - case DXGIFormat::BC3_UNORM_SRGB: - info.compressed = true; - info.internalFormat = GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT; - break; - // BC4 - case DXGIFormat::BC4_UNORM: - info.compressed = true; - info.internalFormat = GL_COMPRESSED_RED_RGTC1; - break; - case DXGIFormat::BC4_SNORM: - info.compressed = true; - info.internalFormat = GL_COMPRESSED_SIGNED_RED_RGTC1; - break; - // BC5 - case DXGIFormat::BC5_UNORM: - info.compressed = true; - info.internalFormat = GL_COMPRESSED_RG_RGTC2; - break; - case DXGIFormat::BC5_SNORM: - info.compressed = true; - info.internalFormat = GL_COMPRESSED_SIGNED_RG_RGTC2; - break; - // BC6H - case DXGIFormat::BC6H_UF16: - info.compressed = true; - info.internalFormat = GL_COMPRESSED_RGB_BPTC_UNSIGNED_FLOAT; - break; - case DXGIFormat::BC6H_SF16: - info.compressed = true; - info.internalFormat = GL_COMPRESSED_RGB_BPTC_SIGNED_FLOAT; - break; - // BC7 - case DXGIFormat::BC7_UNORM: - info.compressed = true; - info.internalFormat = GL_COMPRESSED_RGBA_BPTC_UNORM; - break; - case DXGIFormat::BC7_UNORM_SRGB: - info.compressed = true; - info.internalFormat = GL_COMPRESSED_SRGB_ALPHA_BPTC_UNORM; - break; - - // Uncompressed RGBA - case DXGIFormat::R8G8B8A8_UNORM: - case DXGIFormat::R8G8B8A8_UNORM_SRGB: - info.internalFormat = GL_RGBA8; - info.format = GL_RGBA; - info.type = GL_UNSIGNED_BYTE; - break; - case DXGIFormat::R8G8B8A8_UINT: - info.internalFormat = GL_RGBA8UI; - info.format = GL_RGBA_INTEGER; - info.type = GL_UNSIGNED_BYTE; - info.sampler = SamplerType::UInt; - break; - case DXGIFormat::R8G8B8A8_SNORM: - info.internalFormat = GL_RGBA8_SNORM; - info.format = GL_RGBA; - info.type = GL_BYTE; - break; - case DXGIFormat::R8G8B8A8_SINT: - info.internalFormat = GL_RGBA8I; - info.format = GL_RGBA_INTEGER; - info.type = GL_BYTE; - info.sampler = SamplerType::SInt; - break; - - // BGRA - case DXGIFormat::B8G8R8A8_UNORM: - case DXGIFormat::B8G8R8A8_UNORM_SRGB: - info.internalFormat = GL_RGBA8; - info.format = GL_BGRA; - info.type = GL_UNSIGNED_BYTE; - break; - case DXGIFormat::B8G8R8X8_UNORM: - case DXGIFormat::B8G8R8X8_UNORM_SRGB: - info.internalFormat = GL_RGBA8; - info.format = GL_BGRA; - info.type = GL_UNSIGNED_BYTE; - break; - - // 16-bit float - case DXGIFormat::R16G16B16A16_FLOAT: - info.internalFormat = GL_RGBA16F; - info.format = GL_RGBA; - info.type = GL_HALF_FLOAT; - break; - case DXGIFormat::R16G16B16A16_UNORM: - info.internalFormat = GL_RGBA16; - info.format = GL_RGBA; - info.type = GL_UNSIGNED_SHORT; - break; - case DXGIFormat::R16G16B16A16_UINT: - info.internalFormat = GL_RGBA16UI; - info.format = GL_RGBA_INTEGER; - info.type = GL_UNSIGNED_SHORT; - info.sampler = SamplerType::UInt; - break; - case DXGIFormat::R16G16B16A16_SNORM: - info.internalFormat = GL_RGBA16_SNORM; - info.format = GL_RGBA; - info.type = GL_SHORT; - break; - case DXGIFormat::R16G16B16A16_SINT: - info.internalFormat = GL_RGBA16I; - info.format = GL_RGBA_INTEGER; - info.type = GL_SHORT; - info.sampler = SamplerType::SInt; - break; - - // 32-bit float - case DXGIFormat::R32G32B32A32_FLOAT: - info.internalFormat = GL_RGBA32F; - info.format = GL_RGBA; - info.type = GL_FLOAT; - break; - case DXGIFormat::R32G32B32_FLOAT: - info.internalFormat = GL_RGB32F; - info.format = GL_RGB; - info.type = GL_FLOAT; - break; - - // RG formats - case DXGIFormat::R8G8_UNORM: - info.internalFormat = GL_RG8; - info.format = GL_RG; - info.type = GL_UNSIGNED_BYTE; - break; - case DXGIFormat::R16G16_FLOAT: - info.internalFormat = GL_RG16F; - info.format = GL_RG; - info.type = GL_HALF_FLOAT; - break; - case DXGIFormat::R16G16_UNORM: - info.internalFormat = GL_RG16; - info.format = GL_RG; - info.type = GL_UNSIGNED_SHORT; - break; - case DXGIFormat::R32G32_FLOAT: - info.internalFormat = GL_RG32F; - info.format = GL_RG; - info.type = GL_FLOAT; - break; - - // R formats - case DXGIFormat::R8_UNORM: - info.internalFormat = GL_R8; - info.format = GL_RED; - info.type = GL_UNSIGNED_BYTE; - break; - case DXGIFormat::R16_FLOAT: - info.internalFormat = GL_R16F; - info.format = GL_RED; - info.type = GL_HALF_FLOAT; - break; - case DXGIFormat::R16_UNORM: - info.internalFormat = GL_R16; - info.format = GL_RED; - info.type = GL_UNSIGNED_SHORT; - break; - case DXGIFormat::R32_FLOAT: - info.internalFormat = GL_R32F; - info.format = GL_RED; - info.type = GL_FLOAT; - break; - case DXGIFormat::A8_UNORM: - info.internalFormat = GL_R8; - info.format = GL_RED; - info.type = GL_UNSIGNED_BYTE; - break; - - // Packed formats - case DXGIFormat::R10G10B10A2_UNORM: - info.internalFormat = GL_RGB10_A2; - info.format = GL_RGBA; - info.type = GL_UNSIGNED_INT_2_10_10_10_REV; - break; - case DXGIFormat::R11G11B10_FLOAT: - info.internalFormat = GL_R11F_G11F_B10F; - info.format = GL_RGB; - info.type = GL_UNSIGNED_INT_10F_11F_11F_REV; - break; - case DXGIFormat::B5G6R5_UNORM: - info.internalFormat = GL_RGB565; - info.format = GL_RGB; - info.type = GL_UNSIGNED_SHORT_5_6_5; - break; - case DXGIFormat::B5G5R5A1_UNORM: - info.internalFormat = GL_RGB5_A1; - info.format = GL_BGRA; - info.type = GL_UNSIGNED_SHORT_1_5_5_5_REV; - break; - case DXGIFormat::B4G4R4A4_UNORM: - info.internalFormat = GL_RGBA4; - info.format = GL_BGRA; - info.type = GL_UNSIGNED_SHORT_4_4_4_4_REV; - break; - - default: - info.valid = false; - break; - } - - return info; -} - -DXGIFormat fourCCToDXGI(uint32_t fourCC) -{ - if (fourCC == makeFourCC('D', 'X', 'T', '1')) - return DXGIFormat::BC1_UNORM; - if (fourCC == makeFourCC('D', 'X', 'T', '3')) - return DXGIFormat::BC2_UNORM; - if (fourCC == makeFourCC('D', 'X', 'T', '5')) - return DXGIFormat::BC3_UNORM; - if (fourCC == makeFourCC('B', 'C', '4', 'U') || - fourCC == makeFourCC('A', 'T', 'I', '1')) - return DXGIFormat::BC4_UNORM; - if (fourCC == makeFourCC('B', 'C', '4', 'S')) - return DXGIFormat::BC4_SNORM; - if (fourCC == makeFourCC('A', 'T', 'I', '2') || - fourCC == makeFourCC('B', 'C', '5', 'U')) - return DXGIFormat::BC5_UNORM; - if (fourCC == makeFourCC('B', 'C', '5', 'S')) - return DXGIFormat::BC5_SNORM; - - // Numeric FourCC codes for float/half-float formats - switch (fourCC) { - case 36: - return DXGIFormat::R16G16B16A16_UNORM; - case 110: - return DXGIFormat::R16G16B16A16_SNORM; - case 111: - return DXGIFormat::R16_FLOAT; - case 112: - return DXGIFormat::R16G16_FLOAT; - case 113: - return DXGIFormat::R16G16B16A16_FLOAT; - case 114: - return DXGIFormat::R32_FLOAT; - case 115: - return DXGIFormat::R32G32_FLOAT; - case 116: - return DXGIFormat::R32G32B32A32_FLOAT; - default: - return DXGIFormat::UNKNOWN; - } -} - -// Helper: count trailing zeros / bit shift for a mask -static int maskShift(uint32_t mask) -{ - if (mask == 0) - return 0; - int shift = 0; - while ((mask & 1) == 0) { - mask >>= 1; - ++shift; - } - return shift; -} - -static int maskBits(uint32_t mask) -{ - int count = 0; - while (mask) { - count += mask & 1; - mask >>= 1; - } - return count; -} - -// Build a converter for arbitrary bitmask pixel formats -static GLFormatInfo buildBitmaskFormat(const DDSPixelFormat& pf) -{ - GLFormatInfo info; - info.valid = true; - - int rShift = maskShift(pf.dwRBitMask); - int gShift = maskShift(pf.dwGBitMask); - int bShift = maskShift(pf.dwBBitMask); - int aShift = maskShift(pf.dwABitMask); - int rBits = maskBits(pf.dwRBitMask); - int gBits = maskBits(pf.dwGBitMask); - int bBits = maskBits(pf.dwBBitMask); - int aBits = maskBits(pf.dwABitMask); - int bpp = pf.dwRGBBitCount; - - // Try to match common uncompressed formats directly - if (bpp == 32 && pf.dwRBitMask == 0x000000FF && pf.dwGBitMask == 0x0000FF00 && - pf.dwBBitMask == 0x00FF0000 && - (pf.dwABitMask == 0xFF000000 || pf.dwABitMask == 0)) { - info.internalFormat = GL_RGBA8; - info.format = GL_RGBA; - info.type = GL_UNSIGNED_BYTE; - return info; - } - if (bpp == 32 && pf.dwRBitMask == 0x00FF0000 && pf.dwGBitMask == 0x0000FF00 && - pf.dwBBitMask == 0x000000FF) { - info.internalFormat = GL_RGBA8; - info.format = GL_BGRA; - info.type = GL_UNSIGNED_BYTE; - return info; - } - - // Generic converter: extract channels and pack into RGBA8 - uint32_t rMask = pf.dwRBitMask; - uint32_t gMask = pf.dwGBitMask; - uint32_t bMask = pf.dwBBitMask; - uint32_t aMask = pf.dwABitMask; - bool hasAlpha = (pf.dwFlags & DDPF_ALPHAPIXELS) && aMask != 0; - int bytesPerPixel = bpp / 8; - - info.internalFormat = GL_RGBA8; - info.format = GL_RGBA; - info.type = GL_UNSIGNED_BYTE; - info.converter = [=](const QByteArray& data, int w, int h) -> QByteArray { - QByteArray result(w * h * 4, '\0'); - const uint8_t* src = reinterpret_cast<const uint8_t*>(data.constData()); - uint8_t* dst = reinterpret_cast<uint8_t*>(result.data()); - - for (int i = 0; i < w * h; ++i) { - uint32_t pixel = 0; - std::memcpy(&pixel, src + i * bytesPerPixel, - std::min(bytesPerPixel, 4)); - - int r = rBits > 0 ? ((pixel & rMask) >> rShift) * 255 / ((1 << rBits) - 1) : 0; - int g = gBits > 0 ? ((pixel & gMask) >> gShift) * 255 / ((1 << gBits) - 1) : 0; - int b = bBits > 0 ? ((pixel & bMask) >> bShift) * 255 / ((1 << bBits) - 1) : 0; - int a = hasAlpha && aBits > 0 - ? ((pixel & aMask) >> aShift) * 255 / ((1 << aBits) - 1) - : 255; - - dst[i * 4 + 0] = static_cast<uint8_t>(r); - dst[i * 4 + 1] = static_cast<uint8_t>(g); - dst[i * 4 + 2] = static_cast<uint8_t>(b); - dst[i * 4 + 3] = static_cast<uint8_t>(a); - } - return result; - }; - - return info; -} - -GLFormatInfo getGLFormat(const DDSPixelFormat& pf, const DDSHeaderDXT10* dxt10) -{ - // DX10 extended header takes priority - if (dxt10) { - return dxgiToGL(dxt10->dxgiFormat); - } - - // FourCC compressed or float formats - if (pf.dwFlags & DDPF_FOURCC) { - DXGIFormat dxgi = fourCCToDXGI(pf.dwFourCC); - if (dxgi != DXGIFormat::UNKNOWN) { - return dxgiToGL(dxgi); - } - GLFormatInfo info; - info.valid = false; - return info; - } - - // Uncompressed with bitmasks - if (pf.dwFlags & (DDPF_RGB | DDPF_LUMINANCE | DDPF_YUV | DDPF_ALPHA)) { - return buildBitmaskFormat(pf); - } - - GLFormatInfo info; - info.valid = false; - return info; -} - -static bool isBlockCompressed(DXGIFormat fmt) -{ - switch (fmt) { - case DXGIFormat::BC1_UNORM: - case DXGIFormat::BC1_UNORM_SRGB: - case DXGIFormat::BC2_UNORM: - case DXGIFormat::BC2_UNORM_SRGB: - case DXGIFormat::BC3_UNORM: - case DXGIFormat::BC3_UNORM_SRGB: - case DXGIFormat::BC4_UNORM: - case DXGIFormat::BC4_SNORM: - case DXGIFormat::BC5_UNORM: - case DXGIFormat::BC5_SNORM: - case DXGIFormat::BC6H_UF16: - case DXGIFormat::BC6H_SF16: - case DXGIFormat::BC7_UNORM: - case DXGIFormat::BC7_UNORM_SRGB: - return true; - default: - return false; - } -} - -static int blockSize(DXGIFormat fmt) -{ - switch (fmt) { - case DXGIFormat::BC1_UNORM: - case DXGIFormat::BC1_UNORM_SRGB: - case DXGIFormat::BC4_UNORM: - case DXGIFormat::BC4_SNORM: - return 8; - default: - return 16; - } -} - -uint32_t mipDataSize(DXGIFormat fmt, const DDSPixelFormat& pf, - uint32_t width, uint32_t height) -{ - if (isBlockCompressed(fmt)) { - uint32_t blocksW = std::max(1u, (width + 3) / 4); - uint32_t blocksH = std::max(1u, (height + 3) / 4); - return blocksW * blocksH * blockSize(fmt); - } - - // Uncompressed: use bits per pixel - uint32_t bpp = pf.dwRGBBitCount; - if (bpp == 0) { - // Estimate from DXGI format for non-bitmask formats - switch (fmt) { - case DXGIFormat::R32G32B32A32_FLOAT: - bpp = 128; - break; - case DXGIFormat::R32G32B32_FLOAT: - bpp = 96; - break; - case DXGIFormat::R16G16B16A16_FLOAT: - case DXGIFormat::R16G16B16A16_UNORM: - case DXGIFormat::R16G16B16A16_SNORM: - case DXGIFormat::R32G32_FLOAT: - bpp = 64; - break; - case DXGIFormat::R8G8B8A8_UNORM: - case DXGIFormat::R8G8B8A8_UNORM_SRGB: - case DXGIFormat::B8G8R8A8_UNORM: - case DXGIFormat::B8G8R8X8_UNORM: - case DXGIFormat::R16G16_FLOAT: - case DXGIFormat::R16G16_UNORM: - case DXGIFormat::R32_FLOAT: - case DXGIFormat::R10G10B10A2_UNORM: - case DXGIFormat::R11G11B10_FLOAT: - bpp = 32; - break; - case DXGIFormat::R8G8_UNORM: - case DXGIFormat::R16_FLOAT: - case DXGIFormat::R16_UNORM: - case DXGIFormat::B5G6R5_UNORM: - case DXGIFormat::B5G5R5A1_UNORM: - case DXGIFormat::B4G4R4A4_UNORM: - bpp = 16; - break; - case DXGIFormat::R8_UNORM: - case DXGIFormat::A8_UNORM: - bpp = 8; - break; - default: - bpp = 32; - break; - } - } - return width * height * bpp / 8; -} - -static const char* dxgiFormatName(DXGIFormat fmt) -{ - switch (fmt) { - case DXGIFormat::BC1_UNORM: - return "BC1_UNORM (DXT1)"; - case DXGIFormat::BC1_UNORM_SRGB: - return "BC1_UNORM_SRGB"; - case DXGIFormat::BC2_UNORM: - return "BC2_UNORM (DXT3)"; - case DXGIFormat::BC2_UNORM_SRGB: - return "BC2_UNORM_SRGB"; - case DXGIFormat::BC3_UNORM: - return "BC3_UNORM (DXT5)"; - case DXGIFormat::BC3_UNORM_SRGB: - return "BC3_UNORM_SRGB"; - case DXGIFormat::BC4_UNORM: - return "BC4_UNORM"; - case DXGIFormat::BC4_SNORM: - return "BC4_SNORM"; - case DXGIFormat::BC5_UNORM: - return "BC5_UNORM"; - case DXGIFormat::BC5_SNORM: - return "BC5_SNORM"; - case DXGIFormat::BC6H_UF16: - return "BC6H_UF16"; - case DXGIFormat::BC6H_SF16: - return "BC6H_SF16"; - case DXGIFormat::BC7_UNORM: - return "BC7_UNORM"; - case DXGIFormat::BC7_UNORM_SRGB: - return "BC7_UNORM_SRGB"; - case DXGIFormat::R8G8B8A8_UNORM: - return "R8G8B8A8_UNORM"; - case DXGIFormat::R8G8B8A8_UNORM_SRGB: - return "R8G8B8A8_UNORM_SRGB"; - case DXGIFormat::B8G8R8A8_UNORM: - return "B8G8R8A8_UNORM"; - case DXGIFormat::R16G16B16A16_FLOAT: - return "R16G16B16A16_FLOAT"; - case DXGIFormat::R32G32B32A32_FLOAT: - return "R32G32B32A32_FLOAT"; - default: - return "Unknown"; - } -} - -QString formatDescription(const DDSPixelFormat& pf, const DDSHeaderDXT10* dxt10) -{ - if (dxt10) { - return QString("DXGI: %1").arg(dxgiFormatName(dxt10->dxgiFormat)); - } - - if (pf.dwFlags & DDPF_FOURCC) { - char cc[5] = {0}; - std::memcpy(cc, &pf.dwFourCC, 4); - DXGIFormat dxgi = fourCCToDXGI(pf.dwFourCC); - if (dxgi != DXGIFormat::UNKNOWN) { - return QString("FourCC: %1 (%2)").arg(cc).arg(dxgiFormatName(dxgi)); - } - return QString("FourCC: %1").arg(cc); - } - - return QString("%1-bit R:0x%2 G:0x%3 B:0x%4 A:0x%5") - .arg(pf.dwRGBBitCount) - .arg(pf.dwRBitMask, 0, 16) - .arg(pf.dwGBitMask, 0, 16) - .arg(pf.dwBBitMask, 0, 16) - .arg(pf.dwABitMask, 0, 16); -} diff --git a/libs/preview_dds_native/src/ddsformat.h b/libs/preview_dds_native/src/ddsformat.h deleted file mode 100644 index 22d3565..0000000 --- a/libs/preview_dds_native/src/ddsformat.h +++ /dev/null @@ -1,200 +0,0 @@ -#ifndef DDSFORMAT_H -#define DDSFORMAT_H - -#include <cstdint> -#include <functional> -#include <vector> - -#include <QByteArray> - -// DDS file magic number -constexpr uint32_t DDS_MAGIC = 0x20534444; // "DDS " - -// DDS_PIXELFORMAT flags -constexpr uint32_t DDPF_ALPHAPIXELS = 0x1; -constexpr uint32_t DDPF_ALPHA = 0x2; -constexpr uint32_t DDPF_FOURCC = 0x4; -constexpr uint32_t DDPF_RGB = 0x40; -constexpr uint32_t DDPF_YUV = 0x200; -constexpr uint32_t DDPF_LUMINANCE = 0x20000; - -// DDS_HEADER flags -constexpr uint32_t DDSD_CAPS = 0x1; -constexpr uint32_t DDSD_HEIGHT = 0x2; -constexpr uint32_t DDSD_WIDTH = 0x4; -constexpr uint32_t DDSD_PITCH = 0x8; -constexpr uint32_t DDSD_PIXELFORMAT = 0x1000; -constexpr uint32_t DDSD_MIPMAPCOUNT = 0x20000; -constexpr uint32_t DDSD_LINEARSIZE = 0x80000; -constexpr uint32_t DDSD_DEPTH = 0x800000; - -// DDS_HEADER caps2 -constexpr uint32_t DDSCAPS2_CUBEMAP = 0x200; -constexpr uint32_t DDSCAPS2_CUBEMAP_POSITIVEX = 0x400; -constexpr uint32_t DDSCAPS2_CUBEMAP_NEGATIVEX = 0x800; -constexpr uint32_t DDSCAPS2_CUBEMAP_POSITIVEY = 0x1000; -constexpr uint32_t DDSCAPS2_CUBEMAP_NEGATIVEY = 0x2000; -constexpr uint32_t DDSCAPS2_CUBEMAP_POSITIVEZ = 0x4000; -constexpr uint32_t DDSCAPS2_CUBEMAP_NEGATIVEZ = 0x8000; -constexpr uint32_t DDSCAPS2_VOLUME = 0x200000; - -constexpr uint32_t DDSCAPS2_CUBEMAP_ALLFACES = - DDSCAPS2_CUBEMAP_POSITIVEX | DDSCAPS2_CUBEMAP_NEGATIVEX | - DDSCAPS2_CUBEMAP_POSITIVEY | DDSCAPS2_CUBEMAP_NEGATIVEY | - DDSCAPS2_CUBEMAP_POSITIVEZ | DDSCAPS2_CUBEMAP_NEGATIVEZ; - -// DXGI formats (subset covering common DDS textures) -enum class DXGIFormat : uint32_t { - UNKNOWN = 0, - R32G32B32A32_FLOAT = 2, - R32G32B32A32_UINT = 3, - R32G32B32A32_SINT = 4, - R32G32B32_FLOAT = 6, - R32G32B32_UINT = 7, - R32G32B32_SINT = 8, - R16G16B16A16_FLOAT = 10, - R16G16B16A16_UNORM = 11, - R16G16B16A16_UINT = 12, - R16G16B16A16_SNORM = 13, - R16G16B16A16_SINT = 14, - R32G32_FLOAT = 16, - R32G32_UINT = 17, - R32G32_SINT = 18, - R10G10B10A2_UNORM = 24, - R10G10B10A2_UINT = 25, - R11G11B10_FLOAT = 26, - R8G8B8A8_UNORM = 28, - R8G8B8A8_UNORM_SRGB = 29, - R8G8B8A8_UINT = 30, - R8G8B8A8_SNORM = 31, - R8G8B8A8_SINT = 32, - R16G16_FLOAT = 34, - R16G16_UNORM = 35, - R16G16_UINT = 36, - R16G16_SNORM = 37, - R16G16_SINT = 38, - R32_FLOAT = 41, - R32_UINT = 42, - R32_SINT = 43, - R8G8_UNORM = 49, - R8G8_UINT = 50, - R8G8_SNORM = 51, - R8G8_SINT = 52, - R16_FLOAT = 54, - R16_UNORM = 56, - R16_UINT = 57, - R16_SNORM = 58, - R16_SINT = 59, - R8_UNORM = 61, - R8_UINT = 62, - R8_SNORM = 63, - R8_SINT = 64, - A8_UNORM = 65, - BC1_UNORM = 71, - BC1_UNORM_SRGB = 72, - BC2_UNORM = 74, - BC2_UNORM_SRGB = 75, - BC3_UNORM = 77, - BC3_UNORM_SRGB = 78, - BC4_UNORM = 80, - BC4_SNORM = 81, - BC5_UNORM = 83, - BC5_SNORM = 84, - B5G6R5_UNORM = 85, - B5G5R5A1_UNORM = 86, - B8G8R8A8_UNORM = 87, - B8G8R8X8_UNORM = 88, - B8G8R8A8_UNORM_SRGB = 91, - B8G8R8X8_UNORM_SRGB = 93, - BC6H_UF16 = 95, - BC6H_SF16 = 96, - BC7_UNORM = 98, - BC7_UNORM_SRGB = 99, - B4G4R4A4_UNORM = 115, -}; - -// D3D10 resource dimension -enum class D3D10ResourceDimension : uint32_t { - Unknown = 0, - Buffer = 1, - Texture1D = 2, - Texture2D = 3, - Texture3D = 4, -}; - -#pragma pack(push, 1) - -struct DDSPixelFormat { - uint32_t dwSize; - uint32_t dwFlags; - uint32_t dwFourCC; - uint32_t dwRGBBitCount; - uint32_t dwRBitMask; - uint32_t dwGBitMask; - uint32_t dwBBitMask; - uint32_t dwABitMask; -}; - -struct DDSHeader { - uint32_t dwSize; - uint32_t dwFlags; - uint32_t dwHeight; - uint32_t dwWidth; - uint32_t dwPitchOrLinearSize; - uint32_t dwDepth; - uint32_t dwMipMapCount; - uint32_t dwReserved1[11]; - DDSPixelFormat ddspf; - uint32_t dwCaps; - uint32_t dwCaps2; - uint32_t dwCaps3; - uint32_t dwCaps4; - uint32_t dwReserved2; -}; - -struct DDSHeaderDXT10 { - DXGIFormat dxgiFormat; - D3D10ResourceDimension resourceDimension; - uint32_t miscFlag; - uint32_t arraySize; - uint32_t miscFlags2; -}; - -#pragma pack(pop) - -// Sampler type for shader selection -enum class SamplerType { Float, UInt, SInt }; - -// OpenGL format info -struct GLFormatInfo { - bool valid = false; - bool compressed = false; - uint32_t internalFormat = 0; - uint32_t format = 0; // only for uncompressed - uint32_t type = 0; // only for uncompressed - SamplerType sampler = SamplerType::Float; - // Optional converter for non-standard bitmask formats - std::function<QByteArray(const QByteArray&, int, int)> converter; -}; - -// Inline helper: make a FourCC from 4 chars -constexpr uint32_t makeFourCC(char a, char b, char c, char d) -{ - return static_cast<uint32_t>(a) | (static_cast<uint32_t>(b) << 8) | - (static_cast<uint32_t>(c) << 16) | (static_cast<uint32_t>(d) << 24); -} - -// Convert a FourCC code to DXGI format -DXGIFormat fourCCToDXGI(uint32_t fourCC); - -// Resolve the OpenGL format from a DDS pixel format + optional DXT10 header -GLFormatInfo getGLFormat(const DDSPixelFormat& pf, const DDSHeaderDXT10* dxt10); - -// Calculate mip level data size in bytes -uint32_t mipDataSize(DXGIFormat fmt, const DDSPixelFormat& pf, - uint32_t width, uint32_t height); - -// Get a human-readable format description -QString formatDescription(const DDSPixelFormat& pf, const DDSHeaderDXT10* dxt10); - -#endif // DDSFORMAT_H diff --git a/libs/preview_dds_native/src/ddspreview.cpp b/libs/preview_dds_native/src/ddspreview.cpp deleted file mode 100644 index 2bb95be..0000000 --- a/libs/preview_dds_native/src/ddspreview.cpp +++ /dev/null @@ -1,126 +0,0 @@ -#include "ddspreview.h" -#include "ddsfile.h" -#include "ddswidget.h" - -#include <QLabel> -#include <QVBoxLayout> -#include <QWidget> - -using namespace MOBase; - -DDSPreview::DDSPreview() {} - -bool DDSPreview::init(IOrganizer* moInfo) -{ - m_organizer = moInfo; - return true; -} - -QString DDSPreview::name() const -{ - return "DDS Preview (Native)"; -} - -QString DDSPreview::localizedName() const -{ - return tr("DDS Preview (Native)"); -} - -QString DDSPreview::author() const -{ - return "AnyOldName3"; -} - -QString DDSPreview::description() const -{ - return tr("Displays DDS texture files using OpenGL."); -} - -VersionInfo DDSPreview::version() const -{ - return VersionInfo(1, 0, 0, VersionInfo::RELEASE_FINAL); -} - -QList<PluginSetting> DDSPreview::settings() const -{ - return {}; -} - -std::set<QString> DDSPreview::supportedExtensions() const -{ - return {"dds"}; -} - -bool DDSPreview::supportsArchives() const -{ - return true; -} - -QWidget* DDSPreview::genFilePreview(const QString& fileName, - const QSize& maxSize) const -{ - DDSFile dds; - if (!dds.loadFromFile(fileName)) { - QLabel* label = new QLabel(tr("Failed to load DDS file.")); - label->setAlignment(Qt::AlignCenter); - return label; - } - return buildPreview(dds, maxSize); -} - -QWidget* DDSPreview::genDataPreview(const QByteArray& fileData, - const QString& fileName, - const QSize& maxSize) const -{ - DDSFile dds; - if (!dds.loadFromData(fileData)) { - QLabel* label = new QLabel(tr("Failed to load DDS data.")); - label->setAlignment(Qt::AlignCenter); - return label; - } - return buildPreview(dds, maxSize); -} - -QWidget* DDSPreview::buildPreview(DDSFile& dds, const QSize& maxSize) const -{ - QWidget* container = new QWidget(); - QVBoxLayout* layout = new QVBoxLayout(container); - - // Description label - QLabel* descLabel = new QLabel(dds.description()); - descLabel->setAlignment(Qt::AlignCenter); - layout->addWidget(descLabel); - - // OpenGL preview widget — we need to keep the DDSFile alive, so store - // it in the container. We use a shared_ptr stored as a property. - auto* ddsPtr = new DDSFile(std::move(dds)); - DDSWidget* widget = new DDSWidget(*ddsPtr, container); - - // Clean up DDSFile when container is destroyed - QObject::connect(container, &QObject::destroyed, [ddsPtr]() { - delete ddsPtr; - }); - - // Size the widget proportionally - int previewW = maxSize.width(); - int previewH = maxSize.height() - 30; // leave room for label - if (ddsPtr->width() > 0 && ddsPtr->height() > 0) { - float texAspect = - static_cast<float>(ddsPtr->width()) / ddsPtr->height(); - float availAspect = - static_cast<float>(previewW) / std::max(1, previewH); - if (texAspect > availAspect) { - previewH = static_cast<int>(previewW / texAspect); - } else { - previewW = static_cast<int>(previewH * texAspect); - } - } - widget->setMinimumSize(std::min(previewW, static_cast<int>(ddsPtr->width())), - std::min(previewH, static_cast<int>(ddsPtr->height()))); - widget->setMaximumSize(previewW, previewH); - - layout->addWidget(widget); - container->setLayout(layout); - - return container; -} diff --git a/libs/preview_dds_native/src/ddspreview.h b/libs/preview_dds_native/src/ddspreview.h deleted file mode 100644 index 36f2bec..0000000 --- a/libs/preview_dds_native/src/ddspreview.h +++ /dev/null @@ -1,44 +0,0 @@ -#ifndef DDSPREVIEW_H -#define DDSPREVIEW_H - -#include <set> - -#include <QString> - -#include <uibase/iplugin.h> -#include <uibase/ipluginpreview.h> - -class DDSPreview : public MOBase::IPluginPreview -{ - Q_OBJECT - Q_INTERFACES(MOBase::IPlugin MOBase::IPluginPreview) - Q_PLUGIN_METADATA(IID "org.tannin.DDSPreviewNative") - -public: - DDSPreview(); - -public: // IPlugin - bool init(MOBase::IOrganizer* moInfo) override; - QString name() const override; - QString localizedName() const override; - QString author() const override; - QString description() const override; - MOBase::VersionInfo version() const override; - QList<MOBase::PluginSetting> settings() const override; - -public: // IPluginPreview - std::set<QString> supportedExtensions() const override; - QWidget* genFilePreview(const QString& fileName, - const QSize& maxSize) const override; - bool supportsArchives() const override; - QWidget* genDataPreview(const QByteArray& fileData, - const QString& fileName, - const QSize& maxSize) const override; - -private: - QWidget* buildPreview(class DDSFile& dds, const QSize& maxSize) const; - - MOBase::IOrganizer* m_organizer = nullptr; -}; - -#endif // DDSPREVIEW_H diff --git a/libs/preview_dds_native/src/ddswidget.cpp b/libs/preview_dds_native/src/ddswidget.cpp deleted file mode 100644 index 43eb586..0000000 --- a/libs/preview_dds_native/src/ddswidget.cpp +++ /dev/null @@ -1,252 +0,0 @@ -#include "ddswidget.h" - -#include <QDebug> - -#include <algorithm> -#include <cstring> - -// Vertex data: position (x,y) + texcoord (u,v) -static const float quadVertices[] = { - // pos // tex - -1.0f, -1.0f, 0.0f, 1.0f, - 1.0f, -1.0f, 1.0f, 1.0f, - -1.0f, 1.0f, 0.0f, 0.0f, - 1.0f, 1.0f, 1.0f, 0.0f, -}; - -static const char* vertexShaderSrc = R"( -#version 330 core -layout(location = 0) in vec2 aPos; -layout(location = 1) in vec2 aTexCoord; -out vec2 vTexCoord; -uniform float uAspect; -uniform float uWidgetAspect; -void main() { - vec2 pos = aPos; - float ratio = uAspect / uWidgetAspect; - if (ratio > 1.0) - pos.y *= 1.0 / ratio; - else - pos.x *= ratio; - gl_Position = vec4(pos, 0.0, 1.0); - vTexCoord = aTexCoord; -} -)"; - -static const char* fragmentShaderSrc = R"( -#version 330 core -in vec2 vTexCoord; -out vec4 fragColor; -uniform sampler2D uTexture; -void main() { - vec4 texel = texture(uTexture, vTexCoord); - // Checkerboard for transparency - vec2 checker = floor(vTexCoord * 16.0); - float c = mod(checker.x + checker.y, 2.0); - vec3 bg = mix(vec3(0.6), vec3(0.4), c); - fragColor = vec4(mix(bg, texel.rgb, texel.a), 1.0); -} -)"; - -static const char* cubemapFragSrc = R"( -#version 330 core -in vec2 vTexCoord; -out vec4 fragColor; -uniform samplerCube uTexture; -void main() { - // Spherical projection for cubemap preview - float theta = vTexCoord.x * 6.28318530718; - float phi = vTexCoord.y * 3.14159265359; - vec3 dir = vec3(sin(phi) * cos(theta), cos(phi), sin(phi) * sin(theta)); - vec4 texel = texture(uTexture, dir); - vec2 checker = floor(vTexCoord * 16.0); - float c = mod(checker.x + checker.y, 2.0); - vec3 bg = mix(vec3(0.6), vec3(0.4), c); - fragColor = vec4(mix(bg, texel.rgb, texel.a), 1.0); -} -)"; - -DDSWidget::DDSWidget(const DDSFile& dds, QWidget* parent) - : QOpenGLWidget(parent), m_dds(dds), m_vbo(QOpenGLBuffer::VertexBuffer) -{ - if (dds.height() > 0) { - m_aspectRatio = - static_cast<float>(dds.width()) / static_cast<float>(dds.height()); - } -} - -DDSWidget::~DDSWidget() -{ - makeCurrent(); - delete m_texture; - delete m_shader; - m_vbo.destroy(); - doneCurrent(); -} - -void DDSWidget::initializeGL() -{ - initializeOpenGLFunctions(); - - glClearColor(0.2f, 0.2f, 0.2f, 1.0f); - - // VBO - m_vbo.create(); - m_vbo.bind(); - m_vbo.allocate(quadVertices, sizeof(quadVertices)); - - setupShaders(); - uploadTexture(); -} - -void DDSWidget::setupShaders() -{ - m_shader = new QOpenGLShaderProgram(this); - m_shader->addShaderFromSourceCode(QOpenGLShader::Vertex, vertexShaderSrc); - - if (m_dds.isCubemap()) { - m_shader->addShaderFromSourceCode(QOpenGLShader::Fragment, cubemapFragSrc); - } else { - m_shader->addShaderFromSourceCode(QOpenGLShader::Fragment, fragmentShaderSrc); - } - - m_shader->link(); -} - -void DDSWidget::uploadTexture() -{ - if (m_dds.faceCount() == 0 || m_dds.mipCount() == 0) - return; - - const auto& fmt = m_dds.glFormat(); - - if (m_dds.isCubemap()) { - m_texture = new QOpenGLTexture(QOpenGLTexture::TargetCubeMap); - } else { - m_texture = new QOpenGLTexture(QOpenGLTexture::Target2D); - } - - m_texture->setAutoMipMapGenerationEnabled(false); - m_texture->setMipLevels(m_dds.mipCount()); - - if (m_dds.isCubemap()) { - m_texture->setSize(m_dds.width(), m_dds.height()); - // Set format for allocation - if (fmt.compressed) { - m_texture->setFormat( - static_cast<QOpenGLTexture::TextureFormat>(fmt.internalFormat)); - } else { - m_texture->setFormat( - static_cast<QOpenGLTexture::TextureFormat>(fmt.internalFormat)); - } - m_texture->allocateStorage(); - - static const QOpenGLTexture::CubeMapFace cubeMapFaces[] = { - QOpenGLTexture::CubeMapPositiveX, QOpenGLTexture::CubeMapNegativeX, - QOpenGLTexture::CubeMapPositiveY, QOpenGLTexture::CubeMapNegativeY, - QOpenGLTexture::CubeMapPositiveZ, QOpenGLTexture::CubeMapNegativeZ, - }; - - int numFaces = std::min(m_dds.faceCount(), 6); - for (int f = 0; f < numFaces; ++f) { - const auto& face = m_dds.face(f); - for (int m = 0; m < face.mips.size(); ++m) { - const auto& mip = face.mips[m]; - QByteArray pixelData = mip.data; - if (fmt.converter) { - pixelData = fmt.converter(mip.data, mip.width, mip.height); - } - if (fmt.compressed) { - m_texture->setCompressedData( - m, 0, cubeMapFaces[f], - pixelData.size(), - pixelData.constData()); - } else { - m_texture->setData( - m, 0, cubeMapFaces[f], - static_cast<QOpenGLTexture::PixelFormat>(fmt.format), - static_cast<QOpenGLTexture::PixelType>(fmt.type), - pixelData.constData()); - } - } - } - } else { - m_texture->setSize(m_dds.width(), m_dds.height()); - if (fmt.compressed) { - m_texture->setFormat( - static_cast<QOpenGLTexture::TextureFormat>(fmt.internalFormat)); - } else { - m_texture->setFormat( - static_cast<QOpenGLTexture::TextureFormat>(fmt.internalFormat)); - } - m_texture->allocateStorage(); - - const auto& face = m_dds.face(0); - for (int m = 0; m < face.mips.size(); ++m) { - const auto& mip = face.mips[m]; - QByteArray pixelData = mip.data; - if (fmt.converter) { - pixelData = fmt.converter(mip.data, mip.width, mip.height); - } - if (fmt.compressed) { - m_texture->setCompressedData( - m, 0, - pixelData.size(), - pixelData.constData()); - } else { - m_texture->setData( - m, 0, - static_cast<QOpenGLTexture::PixelFormat>(fmt.format), - static_cast<QOpenGLTexture::PixelType>(fmt.type), - pixelData.constData()); - } - } - } - - m_texture->setWrapMode(QOpenGLTexture::ClampToEdge); - if (fmt.sampler != SamplerType::Float) { - m_texture->setMinMagFilters(QOpenGLTexture::Nearest, - QOpenGLTexture::Nearest); - } else { - m_texture->setMinMagFilters(QOpenGLTexture::LinearMipMapLinear, - QOpenGLTexture::Linear); - } -} - -void DDSWidget::resizeGL(int w, int h) -{ - glViewport(0, 0, w, h); -} - -void DDSWidget::paintGL() -{ - glClear(GL_COLOR_BUFFER_BIT); - - if (!m_texture || !m_shader) - return; - - m_shader->bind(); - m_texture->bind(); - - float widgetAspect = width() > 0 && height() > 0 - ? static_cast<float>(width()) / height() - : 1.0f; - m_shader->setUniformValue("uAspect", m_aspectRatio); - m_shader->setUniformValue("uWidgetAspect", widgetAspect); - m_shader->setUniformValue("uTexture", 0); - - m_vbo.bind(); - m_shader->enableAttributeArray(0); - m_shader->enableAttributeArray(1); - m_shader->setAttributeBuffer(0, GL_FLOAT, 0, 2, 4 * sizeof(float)); - m_shader->setAttributeBuffer(1, GL_FLOAT, 2 * sizeof(float), 2, - 4 * sizeof(float)); - - glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); - - m_shader->disableAttributeArray(0); - m_shader->disableAttributeArray(1); - m_vbo.release(); - m_texture->release(); - m_shader->release(); -} diff --git a/libs/preview_dds_native/src/ddswidget.h b/libs/preview_dds_native/src/ddswidget.h deleted file mode 100644 index 968e253..0000000 --- a/libs/preview_dds_native/src/ddswidget.h +++ /dev/null @@ -1,36 +0,0 @@ -#ifndef DDSWIDGET_H -#define DDSWIDGET_H - -#include "ddsfile.h" - -#include <QOpenGLBuffer> -#include <QOpenGLFunctions> -#include <QOpenGLShaderProgram> -#include <QOpenGLTexture> -#include <QOpenGLWidget> - -class DDSWidget : public QOpenGLWidget, protected QOpenGLFunctions -{ - Q_OBJECT - -public: - explicit DDSWidget(const DDSFile& dds, QWidget* parent = nullptr); - ~DDSWidget() override; - -protected: - void initializeGL() override; - void resizeGL(int w, int h) override; - void paintGL() override; - -private: - void uploadTexture(); - void setupShaders(); - - const DDSFile& m_dds; - QOpenGLTexture* m_texture = nullptr; - QOpenGLShaderProgram* m_shader = nullptr; - QOpenGLBuffer m_vbo; - float m_aspectRatio = 1.0f; -}; - -#endif // DDSWIDGET_H |
