diff options
Diffstat (limited to 'src/runtimerender/resourcemanager/Qt3DSRenderLoadedTextureDDS.cpp')
-rw-r--r-- | src/runtimerender/resourcemanager/Qt3DSRenderLoadedTextureDDS.cpp | 695 |
1 files changed, 695 insertions, 0 deletions
diff --git a/src/runtimerender/resourcemanager/Qt3DSRenderLoadedTextureDDS.cpp b/src/runtimerender/resourcemanager/Qt3DSRenderLoadedTextureDDS.cpp new file mode 100644 index 0000000..19d41d1 --- /dev/null +++ b/src/runtimerender/resourcemanager/Qt3DSRenderLoadedTextureDDS.cpp @@ -0,0 +1,695 @@ +/**************************************************************************** +** +** Copyright (C) 2008-2016 NVIDIA Corporation. +** Copyright (C) 2017 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of Qt 3D Studio. +** +** $QT_BEGIN_LICENSE:GPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 or (at your option) any later version +** approved by the KDE Free Qt Foundation. The licenses are as published by +** the Free Software Foundation and appearing in the file LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "Qt3DSRenderLoadedTextureDDS.h" +#include "Qt3DSRenderLoadedTextureFreeImageCompat.h" + +using namespace qt3ds::render; + +namespace qt3ds { +namespace render { + + static int s_exception_string; + + //================================================================================ + // DXT data-layout structure definitions. + typedef struct + { + QT3DSU16 col0; // 16-bit 565 interpolant endpoints + QT3DSU16 col1; + QT3DSU8 row[4]; // 4x4 * 2bpp color-index == 4 bytes. + } DXTColBlock; + + typedef struct + { + QT3DSU16 row[4]; // 4x4 * 4bpp alpha == 8 bytes. (pure 4-bit alpha values) + } DXT3AlphaBlock; + + typedef struct + { + QT3DSU8 alpha0; // 8-bit alpha interpolant endpoints + QT3DSU8 alpha1; + QT3DSU8 row[6]; // 4x4 * 3bpp alpha-index == 48bits == 6 bytes. + } DXT5AlphaBlock; + + typedef struct + { + QT3DSU8 red; + QT3DSU8 green; + QT3DSU8 blue; + QT3DSU8 alpha; + } Color8888; + +//================================================================================ +// Various DDS file defines + +#define DDSD_CAPS 0x00000001l +#define DDSD_HEIGHT 0x00000002l +#define DDSD_WIDTH 0x00000004l +#define DDSD_PIXELFORMAT 0x00001000l +#define DDS_ALPHAPIXELS 0x00000001l +#define DDS_FOURCC 0x00000004l +#define DDS_PITCH 0x00000008l +#define DDS_COMPLEX 0x00000008l +#define DDS_RGB 0x00000040l +#define DDS_TEXTURE 0x00001000l +#define DDS_MIPMAPCOUNT 0x00020000l +#define DDS_LINEARSIZE 0x00080000l +#define DDS_VOLUME 0x00200000l +#define DDS_MIPMAP 0x00400000l +#define DDS_DEPTH 0x00800000l + +#define DDS_CUBEMAP 0x00000200L +#define DDS_CUBEMAP_POSITIVEX 0x00000400L +#define DDS_CUBEMAP_NEGATIVEX 0x00000800L +#define DDS_CUBEMAP_POSITIVEY 0x00001000L +#define DDS_CUBEMAP_NEGATIVEY 0x00002000L +#define DDS_CUBEMAP_POSITIVEZ 0x00004000L +#define DDS_CUBEMAP_NEGATIVEZ 0x00008000L + +#define FOURCC_DXT1 0x31545844 //(MAKEFOURCC('D','X','T','1')) +#define FOURCC_DXT3 0x33545844 //(MAKEFOURCC('D','X','T','3')) +#define FOURCC_DXT5 0x35545844 //(MAKEFOURCC('D','X','T','5')) + +#define DDS_MAGIC_FLIPPED 0x0F7166ED + + //================================================================================ + // DDS file format structures. + typedef struct _DDS_PIXELFORMAT + { + QT3DSU32 dwSize; + QT3DSU32 dwFlags; + QT3DSU32 dwFourCC; + QT3DSU32 dwRGBBitCount; + QT3DSU32 dwRBitMask; + QT3DSU32 dwGBitMask; + QT3DSU32 dwBBitMask; + QT3DSU32 dwABitMask; + } DDS_PIXELFORMAT; + + typedef struct _DDS_HEADER + { + QT3DSU32 dwSize; + QT3DSU32 dwFlags; + QT3DSU32 dwHeight; + QT3DSU32 dwWidth; + QT3DSU32 dwPitchOrLinearSize; + QT3DSU32 dwDepth; + QT3DSU32 dwMipMapCount; + QT3DSU32 dwReserved1[11]; + DDS_PIXELFORMAT ddspf; + QT3DSU32 dwCaps1; + QT3DSU32 dwCaps2; + QT3DSU32 dwReserved2[3]; + } DDS_HEADER; + + //================================================================================ + // helper functions + //================================================================================ + + // helper macros. + static inline void NvSwapChar(QT3DSU8 &a, QT3DSU8 &b) + { + QT3DSU8 tmp; + tmp = a; + a = b; + b = tmp; + } + + static inline void NvSwapShort(QT3DSU16 &a, QT3DSU16 &b) + { + QT3DSU16 tmp; + tmp = a; + a = b; + b = tmp; + } + + //================================================================================ + //================================================================================ + static void flip_blocks_dxtc1(DXTColBlock *line, QT3DSI32 numBlocks) + { + DXTColBlock *curblock = line; + QT3DSI32 i; + + for (i = 0; i < numBlocks; i++) { + NvSwapChar(curblock->row[0], curblock->row[3]); + NvSwapChar(curblock->row[1], curblock->row[2]); + curblock++; + } + } + + //================================================================================ + //================================================================================ + static void flip_blocks_dxtc3(DXTColBlock *line, QT3DSI32 numBlocks) + { + DXTColBlock *curblock = line; + DXT3AlphaBlock *alphablock; + QT3DSI32 i; + + for (i = 0; i < numBlocks; i++) { + alphablock = (DXT3AlphaBlock *)curblock; + + NvSwapShort(alphablock->row[0], alphablock->row[3]); + NvSwapShort(alphablock->row[1], alphablock->row[2]); + curblock++; + + NvSwapChar(curblock->row[0], curblock->row[3]); + NvSwapChar(curblock->row[1], curblock->row[2]); + curblock++; + } + } + + static void flip_dxt5_alpha(DXT5AlphaBlock *block) + { + QT3DSI8 gBits[4][4]; + + const QT3DSU32 mask = 0x00000007; // bits = 00 00 01 11 + QT3DSU32 bits = 0; + memcpy(&bits, &block->row[0], sizeof(QT3DSI8) * 3); + + gBits[0][0] = (QT3DSI8)(bits & mask); + bits >>= 3; + gBits[0][1] = (QT3DSI8)(bits & mask); + bits >>= 3; + gBits[0][2] = (QT3DSI8)(bits & mask); + bits >>= 3; + gBits[0][3] = (QT3DSI8)(bits & mask); + bits >>= 3; + gBits[1][0] = (QT3DSI8)(bits & mask); + bits >>= 3; + gBits[1][1] = (QT3DSI8)(bits & mask); + bits >>= 3; + gBits[1][2] = (QT3DSI8)(bits & mask); + bits >>= 3; + gBits[1][3] = (QT3DSI8)(bits & mask); + + bits = 0; + memcpy(&bits, &block->row[3], sizeof(QT3DSI8) * 3); + + gBits[2][0] = (QT3DSI8)(bits & mask); + bits >>= 3; + gBits[2][1] = (QT3DSI8)(bits & mask); + bits >>= 3; + gBits[2][2] = (QT3DSI8)(bits & mask); + bits >>= 3; + gBits[2][3] = (QT3DSI8)(bits & mask); + bits >>= 3; + gBits[3][0] = (QT3DSI8)(bits & mask); + bits >>= 3; + gBits[3][1] = (QT3DSI8)(bits & mask); + bits >>= 3; + gBits[3][2] = (QT3DSI8)(bits & mask); + bits >>= 3; + gBits[3][3] = (QT3DSI8)(bits & mask); + + bits = (gBits[3][0] << 0) | (gBits[3][1] << 3) | (gBits[3][2] << 6) | (gBits[3][3] << 9) + | (gBits[2][0] << 12) | (gBits[2][1] << 15) | (gBits[2][2] << 18) | (gBits[2][3] << 21); + memcpy(&block->row[0], &bits, 3); + + bits = (gBits[1][0] << 0) | (gBits[1][1] << 3) | (gBits[1][2] << 6) | (gBits[1][3] << 9) + | (gBits[0][0] << 12) | (gBits[0][1] << 15) | (gBits[0][2] << 18) | (gBits[0][3] << 21); + memcpy(&block->row[3], &bits, 3); + } + + static void flip_blocks_dxtc5(DXTColBlock *line, QT3DSI32 numBlocks) + { + DXTColBlock *curblock = line; + DXT5AlphaBlock *alphablock; + QT3DSI32 i; + + for (i = 0; i < numBlocks; i++) { + alphablock = (DXT5AlphaBlock *)curblock; + + flip_dxt5_alpha(alphablock); + curblock++; + + NvSwapChar(curblock->row[0], curblock->row[3]); + NvSwapChar(curblock->row[1], curblock->row[2]); + curblock++; + } + } + + static void flip_data_vertical(FreeImageIO *io, QT3DSI8 *image, QT3DSI32 width, QT3DSI32 height, + Qt3DSDDSImage *info) + { + if (info->compressed) { + QT3DSI32 linesize, j; + DXTColBlock *top; + DXTColBlock *bottom; + QT3DSI8 *tmp; + void (*flipblocks)(DXTColBlock *, QT3DSI32) = NULL; + QT3DSI32 xblocks = width / 4; + QT3DSI32 yblocks = height / 4; + QT3DSI32 blocksize; + + switch (info->format) { + case qt3ds::render::NVRenderTextureFormats::RGBA_DXT1: + blocksize = 8; + flipblocks = &flip_blocks_dxtc1; + break; + case qt3ds::render::NVRenderTextureFormats::RGBA_DXT3: + blocksize = 16; + flipblocks = &flip_blocks_dxtc3; + break; + case qt3ds::render::NVRenderTextureFormats::RGBA_DXT5: + blocksize = 16; + flipblocks = &flip_blocks_dxtc5; + break; + default: + return; + } + + linesize = xblocks * blocksize; + tmp = (QT3DSI8 *)QT3DS_ALLOC(io->m_Allocator, linesize, "flip_data_vertical compressed"); + + for (j = 0; j < (yblocks >> 1); j++) { + top = (DXTColBlock *)(void *)(image + j * linesize); + bottom = (DXTColBlock *)(void *)(image + (((yblocks - j) - 1) * linesize)); + + (*flipblocks)(top, xblocks); + (*flipblocks)(bottom, xblocks); + + memcpy(tmp, bottom, linesize); + memcpy(bottom, top, linesize); + memcpy(top, tmp, linesize); + } + + // Catch the middle row of blocks if there is one + // The loop above will skip the middle row + if (yblocks & 0x01) { + DXTColBlock *middle = (DXTColBlock *)(void *)(image + (yblocks >> 1) * linesize); + (*flipblocks)(middle, xblocks); + } + + QT3DS_FREE(io->m_Allocator, tmp); + } else { + QT3DSI32 linesize = width * info->bytesPerPixel; + QT3DSI32 j; + QT3DSI8 *top; + QT3DSI8 *bottom; + QT3DSI8 *tmp; + + // much simpler - just compute the line length and swap each row + tmp = (QT3DSI8 *)QT3DS_ALLOC(io->m_Allocator, linesize, "flip_data_vertical"); + ; + + for (j = 0; j < (height >> 1); j++) { + top = (QT3DSI8 *)(image + j * linesize); + bottom = (QT3DSI8 *)(image + (((height - j) - 1) * linesize)); + + memcpy(tmp, bottom, linesize); + memcpy(bottom, top, linesize); + memcpy(top, tmp, linesize); + } + + QT3DS_FREE(io->m_Allocator, tmp); + } + } + + static QT3DSI32 size_image(QT3DSI32 width, QT3DSI32 height, const Qt3DSDDSImage *image) + { + if (image->compressed) { + return ((width + 3) / 4) * ((height + 3) / 4) + * (image->format == qt3ds::render::NVRenderTextureFormats::RGBA_DXT1 ? 8 : 16); + } else { + return width * height * image->bytesPerPixel; + } + } + + static QT3DSI32 total_image_data_size(Qt3DSDDSImage *image) + { + QT3DSI32 i, j, index = 0, size = 0, w, h; + QT3DSI32 cubeCount = image->cubemap ? 6 : 1; + + for (j = 0; j < cubeCount; j++) { + w = image->width; + h = image->height; + + for (i = 0; i < image->numMipmaps; i++) // account for base plus each mip + { + image->size[index] = size_image(w, h, image); + image->mipwidth[index] = w; + image->mipheight[index] = h; + size += image->size[index]; + if (w != 1) { + w >>= 1; + } + if (h != 1) { + h >>= 1; + } + + index++; + } + } + + return (size); + } + + void *Qt3DSDDSAllocDataBlock(FreeImageIO *io, Qt3DSDDSImage *image) + { + if (image) { + QT3DSI32 i; + QT3DSI32 size = total_image_data_size(image); + image->dataBlock = + QT3DS_ALLOC(io->m_Allocator, size, + "Qt3DSDDSAllocDataBlock"); // no need to calloc, as we fill every bit... + if (image->dataBlock == NULL) { + return NULL; + } + + image->data[0] = image->dataBlock; + + QT3DSI32 planes = image->numMipmaps * (image->cubemap ? 6 : 1); + + for (i = 1; i < planes; i++) // account for base plus each mip + { + image->data[i] = + (void *)(((size_t)(image->data[i - 1])) + (size_t)image->size[i - 1]); + } + + return (image->dataBlock); // in case caller wants to sanity check... + } + return (NULL); + } + + static FIBITMAP *DoLoadDDS(FreeImageIO *io, IInStream &inStream, QT3DSI32 flipVertical) + { + FIBITMAP *dib = NULL; + DDS_HEADER ddsh; + QT3DSI8 filecode[4]; + Qt3DSDDSImage *image = NULL; + bool needsBGRASwap = false; + ; + bool isAllreadyFlipped = false; + + try { + // check file code + inStream.Read(filecode, 4); + if (memcmp(filecode, "DDS ", 4)) { + throw "Invalid DDS file"; + } + + image = (Qt3DSDDSImage *)QT3DS_ALLOC(io->m_Allocator, sizeof(Qt3DSDDSImage), "DoLoadDDS"); + if (image == NULL) { + throw "Qt3DSDDSImage allocation failed"; + } + memset(image, 0, sizeof(Qt3DSDDSImage)); + + // read in DDS header + inStream.Read(&ddsh, 1); + + // check if image is a cubempap + if (ddsh.dwCaps2 & DDS_CUBEMAP) { + const QT3DSI32 allFaces = DDS_CUBEMAP_POSITIVEX | DDS_CUBEMAP_POSITIVEY + | DDS_CUBEMAP_POSITIVEZ | DDS_CUBEMAP_NEGATIVEX | DDS_CUBEMAP_NEGATIVEY + | DDS_CUBEMAP_NEGATIVEZ; + + if ((ddsh.dwCaps2 & allFaces) != allFaces) { + throw "Not all cubemap faces defined - not supported"; + } + + image->cubemap = 1; + } else { + image->cubemap = 0; + } + + // check if image is a volume texture + if ((ddsh.dwCaps2 & DDS_VOLUME) && (ddsh.dwDepth > 0)) { + throw "Volume textures not supported"; + } + + // allocated the memory for the structure we return + dib = QT3DS_NEW(io->m_Allocator, SLoadedTexture)(io->m_Allocator); + if (dib == NULL) { + throw "DIB allocation failed"; + } + + // figure out what the image format is + if (ddsh.ddspf.dwFlags & DDS_FOURCC) { + switch (ddsh.ddspf.dwFourCC) { + case FOURCC_DXT1: + image->format = qt3ds::render::NVRenderTextureFormats::RGBA_DXT1; + image->components = 3; + image->compressed = 1; + image->alpha = 0; // Ugh - for backwards compatibility + dib->format = qt3ds::render::NVRenderTextureFormats::RGB_DXT1; + break; + case FOURCC_DXT3: + image->format = qt3ds::render::NVRenderTextureFormats::RGBA_DXT3; + image->components = 4; + image->compressed = 1; + image->alpha = 1; + dib->format = qt3ds::render::NVRenderTextureFormats::RGBA_DXT3; + break; + case FOURCC_DXT5: + image->format = qt3ds::render::NVRenderTextureFormats::RGBA_DXT5; + image->components = 4; + image->compressed = 1; + image->alpha = 1; + dib->format = qt3ds::render::NVRenderTextureFormats::RGBA_DXT5; + break; + default: + throw "Unsupported FOURCC code"; + } + } else { + // Check for a supported pixel format + if ((ddsh.ddspf.dwRGBBitCount == 32) && (ddsh.ddspf.dwRBitMask == 0x000000FF) + && (ddsh.ddspf.dwGBitMask == 0x0000FF00) + && (ddsh.ddspf.dwBBitMask == 0x00FF0000) + && (ddsh.ddspf.dwABitMask == 0xFF000000)) { + // We support D3D's A8B8G8R8, which is actually RGBA in linear + // memory, equivalent to GL's RGBA + image->format = qt3ds::render::NVRenderTextureFormats::RGBA8; + image->components = 4; + image->componentFormat = qt3ds::render::NVRenderComponentTypes::QT3DSU8; + image->bytesPerPixel = 4; + image->alpha = 1; + image->compressed = 0; + dib->format = qt3ds::render::NVRenderTextureFormats::RGBA8; + } else if ((ddsh.ddspf.dwRGBBitCount == 32) && (ddsh.ddspf.dwRBitMask == 0x00FF0000) + && (ddsh.ddspf.dwGBitMask == 0x0000FF00) + && (ddsh.ddspf.dwBBitMask == 0x000000FF) + && (ddsh.ddspf.dwABitMask == 0xFF000000)) { + // We support D3D's A8R8G8B8, which is actually BGRA in linear + // memory, need to be + image->format = qt3ds::render::NVRenderTextureFormats::RGBA8; + image->components = 4; + image->componentFormat = qt3ds::render::NVRenderComponentTypes::QT3DSU8; + image->bytesPerPixel = 4; + image->alpha = 1; + image->compressed = 0; + needsBGRASwap = true; + dib->format = qt3ds::render::NVRenderTextureFormats::RGBA8; + } else if ((ddsh.ddspf.dwRGBBitCount == 16) && (ddsh.ddspf.dwRBitMask == 0x0000F800) + && (ddsh.ddspf.dwGBitMask == 0x000007E0) + && (ddsh.ddspf.dwBBitMask == 0x0000001F) + && (ddsh.ddspf.dwABitMask == 0x00000000)) { + // We support D3D's R5G6B5, which is actually RGB in linear + // memory. It is equivalent to GL's GL_UNSIGNED_SHORT_5_6_5 + image->format = qt3ds::render::NVRenderTextureFormats::RGB8; + image->components = 3; + image->alpha = 0; + image->componentFormat = qt3ds::render::NVRenderComponentTypes::QT3DSU16; + image->bytesPerPixel = 2; + image->compressed = 0; + dib->format = qt3ds::render::NVRenderTextureFormats::RGB8; + } else if ((ddsh.ddspf.dwRGBBitCount == 8) && (ddsh.ddspf.dwRBitMask == 0x00000000) + && (ddsh.ddspf.dwGBitMask == 0x00000000) + && (ddsh.ddspf.dwBBitMask == 0x00000000) + && (ddsh.ddspf.dwABitMask == 0x000000FF)) { + // We support D3D's A8 + image->format = qt3ds::render::NVRenderTextureFormats::Alpha8; + image->components = 1; + image->alpha = 1; + image->componentFormat = qt3ds::render::NVRenderComponentTypes::QT3DSU8; + image->bytesPerPixel = 1; + image->compressed = 0; + dib->format = qt3ds::render::NVRenderTextureFormats::Alpha8; + } else if ((ddsh.ddspf.dwRGBBitCount == 8) && (ddsh.ddspf.dwRBitMask == 0x000000FF) + && (ddsh.ddspf.dwGBitMask == 0x00000000) + && (ddsh.ddspf.dwBBitMask == 0x00000000) + && (ddsh.ddspf.dwABitMask == 0x00000000)) { + // We support D3D's L8 (flagged as 8 bits of red only) + image->format = qt3ds::render::NVRenderTextureFormats::Luminance8; + image->components = 1; + image->alpha = 0; + image->componentFormat = qt3ds::render::NVRenderComponentTypes::QT3DSU8; + image->bytesPerPixel = 1; + image->compressed = 0; + dib->format = qt3ds::render::NVRenderTextureFormats::Luminance8; + } else if ((ddsh.ddspf.dwRGBBitCount == 16) && (ddsh.ddspf.dwRBitMask == 0x000000FF) + && (ddsh.ddspf.dwGBitMask == 0x00000000) + && (ddsh.ddspf.dwBBitMask == 0x00000000) + && (ddsh.ddspf.dwABitMask == 0x0000FF00)) { + // We support D3D's A8L8 (flagged as 8 bits of red and 8 bits of alpha) + image->format = qt3ds::render::NVRenderTextureFormats::LuminanceAlpha8; + image->components = 2; + image->alpha = 1; + image->componentFormat = qt3ds::render::NVRenderComponentTypes::QT3DSU8; + image->bytesPerPixel = 2; + image->compressed = 0; + dib->format = qt3ds::render::NVRenderTextureFormats::LuminanceAlpha8; + } else { + throw "not a DXTC or supported RGB(A) format image"; + } + } + + // detect flagging to indicate this texture was stored in a y-inverted fashion + if (!(ddsh.dwFlags & DDS_LINEARSIZE)) { + if (ddsh.dwPitchOrLinearSize == DDS_MAGIC_FLIPPED) { + isAllreadyFlipped = true; + } + } + + flipVertical = (isAllreadyFlipped != (flipVertical ? true : false)) ? 1 : 0; + + // store primary surface width/height/numMipmaps + image->width = ddsh.dwWidth; + image->height = ddsh.dwHeight; + image->numMipmaps = ddsh.dwFlags & DDS_MIPMAPCOUNT ? ddsh.dwMipMapCount : 1; + + if (image->numMipmaps > QT3DS_DDS_MAX_MIPMAPS) { + throw "Too many mipmaps: max 16"; + } + + // allocate the meta datablock for all mip storage. + Qt3DSDDSAllocDataBlock(io, image); + if (image->dataBlock == NULL) { + throw "Failed to allocate memory for image data storage"; + } + + dib->width = image->width; + dib->height = image->height; + dib->dds = image; + + QT3DSI32 faces = image->cubemap ? 6 : 1; + + QT3DSI32 index = 0; + for (QT3DSI32 j = 0; j < faces; j++) { + // load all surfaces for the image + QT3DSI32 width = image->width; + QT3DSI32 height = image->height; + + for (QT3DSI32 i = 0; i < image->numMipmaps; i++) { + // Get the size, read in the data. + inStream.Read( + NVDataRef<QT3DSU8>((QT3DSU8 *)image->data[index], (QT3DSU32)image->size[index])); + + // Flip in Y for OpenGL if needed + if (flipVertical) + flip_data_vertical(io, (QT3DSI8 *)image->data[index], width, height, image); + + // shrink to next power of 2 + width >>= 1; + height >>= 1; + + if (!width) + width = 1; + + if (!height) + height = 1; + + // make sure DXT isn't <4 on a side... + if (image->compressed) { + if (width < 4) + width = 4; + if (height < 4) + height = 4; + } + + index++; + } + } + + if (needsBGRASwap) { + QT3DSI32 index = 0; + QT3DSI32 k; + + for (k = 0; k < faces; k++) { + QT3DSI32 width = image->width; + QT3DSI32 height = image->height; + + for (QT3DSI32 i = 0; i < image->numMipmaps; i++) { + QT3DSI8 *data = (QT3DSI8 *)(image->data[index]); + QT3DSI32 pixels = width * height; + QT3DSI32 j; + + for (j = 0; j < pixels; j++) { + QT3DSI8 temp = data[0]; + data[0] = data[2]; + data[2] = temp; + + data += 4; + } + + // shrink to next power of 2 + width >>= 1; + height >>= 1; + + if (!width) + width = 1; + + if (!height) + height = 1; + + index++; + } + } + } + } catch (const char *message) { + if (image) { + if (image->dataBlock) + QT3DS_FREE(io->m_Allocator, image->dataBlock); + + QT3DS_FREE(io->m_Allocator, image); + } + if (dib) { + FreeImage_Unload(dib); + } + if (message) { + FreeImage_OutputMessageProc(s_exception_string, message, io); + } + } + + return dib; + } + + SLoadedTexture *SLoadedTexture::LoadDDS(IInStream &inStream, QT3DSI32 flipVertical, + NVFoundationBase &inFnd, + qt3ds::render::NVRenderContextType renderContextType) + { + Q_UNUSED(renderContextType) + FreeImageIO theIO(inFnd.getAllocator(), inFnd); + SLoadedTexture *retval = DoLoadDDS(&theIO, inStream, flipVertical); + + return retval; + } +} +} |