move parts to new common component to avoid circular dependency of zonecommon and objcommon

This commit is contained in:
Jan
2021-03-03 12:56:15 -08:00
parent d616738be4
commit 12461d27e7
38 changed files with 70 additions and 22 deletions

114
src/Common/Image/DdsTypes.h Normal file
View File

@ -0,0 +1,114 @@
#pragma once
#include <cstdint>
constexpr uint32_t MakeFourCc(const char ch0, const char ch1, const char ch2, const char ch3)
{
return static_cast<uint32_t>(ch0)
| static_cast<uint32_t>(ch1) << 8
| static_cast<uint32_t>(ch2) << 16
| static_cast<uint32_t>(ch3) << 24;
}
enum DDP_FLAGS
{
DDPF_ALPHAPIXELS = 0x1,
DDPF_ALPHA = 0x2,
DDPF_FOURCC = 0x4,
DDPF_RGB = 0x40,
DDPF_YUV = 0x200,
DDPF_LUMINANCE = 0x20000
};
enum DDS_HEADER_FLAGS
{
DDSD_CAPS = 0x1,
DDSD_HEIGHT = 0x2,
DDSD_WIDTH = 0x4,
DDSD_PITCH = 0x8,
DDSD_PIXELFORMAT = 0x1000,
DDSD_MIPMAPCOUNT = 0x20000,
DDSD_LINEARSIZE = 0x80000,
DDSD_DEPTH = 0x800000,
};
enum DDS_HEADER_CAPS
{
DDSCAPS_COMPLEX = 0x8,
DDSCAPS_TEXTURE = 0x1000,
DDSCAPS_MIPMAP = 0x400000,
};
enum DDS_HEADER_CAPS2
{
DDSCAPS2_CUBEMAP = 0x200,
DDSCAPS2_CUBEMAP_POSITIVEX = 0x400,
DDSCAPS2_CUBEMAP_NEGATIVEX = 0x800,
DDSCAPS2_CUBEMAP_POSITIVEY = 0x1000,
DDSCAPS2_CUBEMAP_NEGATIVEY = 0x2000,
DDSCAPS2_CUBEMAP_POSITIVEZ = 0x4000,
DDSCAPS2_CUBEMAP_NEGATIVEZ = 0x8000,
DDSCAPS2_VOLUME = 0x200000,
};
struct DDS_PIXELFORMAT
{
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 DDS_HEADER
{
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];
DDS_PIXELFORMAT ddspf;
uint32_t dwCaps;
uint32_t dwCaps2;
uint32_t dwCaps3;
uint32_t dwCaps4;
uint32_t dwReserved2;
};
enum D3D10_RESOURCE_DIMENSION
{
D3D10_RESOURCE_DIMENSION_UNKNOWN,
D3D10_RESOURCE_DIMENSION_BUFFER,
D3D10_RESOURCE_DIMENSION_TEXTURE1D,
D3D10_RESOURCE_DIMENSION_TEXTURE2D,
D3D10_RESOURCE_DIMENSION_TEXTURE3D
};
enum DDS_HEADER_DXT10_MISC
{
DDS_RESOURCE_MISC_TEXTURECUBE = 0x4
};
enum DDS_HEADER_DXT10_MISC2
{
DDS_ALPHA_MODE_UNKNOWN = 0x0,
DDS_ALPHA_MODE_STRAIGHT = 0x1,
DDS_ALPHA_MODE_PREMULTIPLIED = 0x2,
DDS_ALPHA_MODE_OPAQUE = 0x3,
DDS_ALPHA_MODE_CUSTOM = 0x4,
};
struct DDS_HEADER_DXT10
{
DXGI_FORMAT dxgiFormat;
D3D10_RESOURCE_DIMENSION resourceDimension;
uint32_t miscFlag;
uint32_t arraySize;
uint32_t miscFlags2;
};

View File

@ -0,0 +1,145 @@
/*
* Copyright 2016 Józef Kucia for CodeWeavers
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
*/
const unsigned int DXGI_FORMAT_DEFINED = 1;
typedef enum DXGI_FORMAT
{
DXGI_FORMAT_UNKNOWN = 0x00,
DXGI_FORMAT_R32G32B32A32_TYPELESS = 0x01,
DXGI_FORMAT_R32G32B32A32_FLOAT = 0x02,
DXGI_FORMAT_R32G32B32A32_UINT = 0x03,
DXGI_FORMAT_R32G32B32A32_SINT = 0x04,
DXGI_FORMAT_R32G32B32_TYPELESS = 0x05,
DXGI_FORMAT_R32G32B32_FLOAT = 0x06,
DXGI_FORMAT_R32G32B32_UINT = 0x07,
DXGI_FORMAT_R32G32B32_SINT = 0x08,
DXGI_FORMAT_R16G16B16A16_TYPELESS = 0x09,
DXGI_FORMAT_R16G16B16A16_FLOAT = 0x0a,
DXGI_FORMAT_R16G16B16A16_UNORM = 0x0b,
DXGI_FORMAT_R16G16B16A16_UINT = 0x0c,
DXGI_FORMAT_R16G16B16A16_SNORM = 0x0d,
DXGI_FORMAT_R16G16B16A16_SINT = 0x0e,
DXGI_FORMAT_R32G32_TYPELESS = 0x0f,
DXGI_FORMAT_R32G32_FLOAT = 0x10,
DXGI_FORMAT_R32G32_UINT = 0x11,
DXGI_FORMAT_R32G32_SINT = 0x12,
DXGI_FORMAT_R32G8X24_TYPELESS = 0x13,
DXGI_FORMAT_D32_FLOAT_S8X24_UINT = 0x14,
DXGI_FORMAT_R32_FLOAT_X8X24_TYPELESS = 0x15,
DXGI_FORMAT_X32_TYPELESS_G8X24_UINT = 0x16,
DXGI_FORMAT_R10G10B10A2_TYPELESS = 0x17,
DXGI_FORMAT_R10G10B10A2_UNORM = 0x18,
DXGI_FORMAT_R10G10B10A2_UINT = 0x19,
DXGI_FORMAT_R11G11B10_FLOAT = 0x1a,
DXGI_FORMAT_R8G8B8A8_TYPELESS = 0x1b,
DXGI_FORMAT_R8G8B8A8_UNORM = 0x1c,
DXGI_FORMAT_R8G8B8A8_UNORM_SRGB = 0x1d,
DXGI_FORMAT_R8G8B8A8_UINT = 0x1e,
DXGI_FORMAT_R8G8B8A8_SNORM = 0x1f,
DXGI_FORMAT_R8G8B8A8_SINT = 0x20,
DXGI_FORMAT_R16G16_TYPELESS = 0x21,
DXGI_FORMAT_R16G16_FLOAT = 0x22,
DXGI_FORMAT_R16G16_UNORM = 0x23,
DXGI_FORMAT_R16G16_UINT = 0x24,
DXGI_FORMAT_R16G16_SNORM = 0x25,
DXGI_FORMAT_R16G16_SINT = 0x26,
DXGI_FORMAT_R32_TYPELESS = 0x27,
DXGI_FORMAT_D32_FLOAT = 0x28,
DXGI_FORMAT_R32_FLOAT = 0x29,
DXGI_FORMAT_R32_UINT = 0x2a,
DXGI_FORMAT_R32_SINT = 0x2b,
DXGI_FORMAT_R24G8_TYPELESS = 0x2c,
DXGI_FORMAT_D24_UNORM_S8_UINT = 0x2d,
DXGI_FORMAT_R24_UNORM_X8_TYPELESS = 0x2e,
DXGI_FORMAT_X24_TYPELESS_G8_UINT = 0x2f,
DXGI_FORMAT_R8G8_TYPELESS = 0x30,
DXGI_FORMAT_R8G8_UNORM = 0x31,
DXGI_FORMAT_R8G8_UINT = 0x32,
DXGI_FORMAT_R8G8_SNORM = 0x33,
DXGI_FORMAT_R8G8_SINT = 0x34,
DXGI_FORMAT_R16_TYPELESS = 0x35,
DXGI_FORMAT_R16_FLOAT = 0x36,
DXGI_FORMAT_D16_UNORM = 0x37,
DXGI_FORMAT_R16_UNORM = 0x38,
DXGI_FORMAT_R16_UINT = 0x39,
DXGI_FORMAT_R16_SNORM = 0x3a,
DXGI_FORMAT_R16_SINT = 0x3b,
DXGI_FORMAT_R8_TYPELESS = 0x3c,
DXGI_FORMAT_R8_UNORM = 0x3d,
DXGI_FORMAT_R8_UINT = 0x3e,
DXGI_FORMAT_R8_SNORM = 0x3f,
DXGI_FORMAT_R8_SINT = 0x40,
DXGI_FORMAT_A8_UNORM = 0x41,
DXGI_FORMAT_R1_UNORM = 0x42,
DXGI_FORMAT_R9G9B9E5_SHAREDEXP = 0x43,
DXGI_FORMAT_R8G8_B8G8_UNORM = 0x44,
DXGI_FORMAT_G8R8_G8B8_UNORM = 0x45,
DXGI_FORMAT_BC1_TYPELESS = 0x46,
DXGI_FORMAT_BC1_UNORM = 0x47,
DXGI_FORMAT_BC1_UNORM_SRGB = 0x48,
DXGI_FORMAT_BC2_TYPELESS = 0x49,
DXGI_FORMAT_BC2_UNORM = 0x4a,
DXGI_FORMAT_BC2_UNORM_SRGB = 0x4b,
DXGI_FORMAT_BC3_TYPELESS = 0x4c,
DXGI_FORMAT_BC3_UNORM = 0x4d,
DXGI_FORMAT_BC3_UNORM_SRGB = 0x4e,
DXGI_FORMAT_BC4_TYPELESS = 0x4f,
DXGI_FORMAT_BC4_UNORM = 0x50,
DXGI_FORMAT_BC4_SNORM = 0x51,
DXGI_FORMAT_BC5_TYPELESS = 0x52,
DXGI_FORMAT_BC5_UNORM = 0x53,
DXGI_FORMAT_BC5_SNORM = 0x54,
DXGI_FORMAT_B5G6R5_UNORM = 0x55,
DXGI_FORMAT_B5G5R5A1_UNORM = 0x56,
DXGI_FORMAT_B8G8R8A8_UNORM = 0x57,
DXGI_FORMAT_B8G8R8X8_UNORM = 0x58,
DXGI_FORMAT_R10G10B10_XR_BIAS_A2_UNORM = 0x59,
DXGI_FORMAT_B8G8R8A8_TYPELESS = 0x5a,
DXGI_FORMAT_B8G8R8A8_UNORM_SRGB = 0x5b,
DXGI_FORMAT_B8G8R8X8_TYPELESS = 0x5c,
DXGI_FORMAT_B8G8R8X8_UNORM_SRGB = 0x5d,
DXGI_FORMAT_BC6H_TYPELESS = 0x5e,
DXGI_FORMAT_BC6H_UF16 = 0x5f,
DXGI_FORMAT_BC6H_SF16 = 0x60,
DXGI_FORMAT_BC7_TYPELESS = 0x61,
DXGI_FORMAT_BC7_UNORM = 0x62,
DXGI_FORMAT_BC7_UNORM_SRGB = 0x63,
DXGI_FORMAT_AYUV = 0x64,
DXGI_FORMAT_Y410 = 0x65,
DXGI_FORMAT_Y416 = 0x66,
DXGI_FORMAT_NV12 = 0x67,
DXGI_FORMAT_P010 = 0x68,
DXGI_FORMAT_P016 = 0x69,
DXGI_FORMAT_420_OPAQUE = 0x6a,
DXGI_FORMAT_YUY2 = 0x6b,
DXGI_FORMAT_Y210 = 0x6c,
DXGI_FORMAT_Y216 = 0x6d,
DXGI_FORMAT_NV11 = 0x6e,
DXGI_FORMAT_AI44 = 0x6f,
DXGI_FORMAT_IA44 = 0x70,
DXGI_FORMAT_P8 = 0x71,
DXGI_FORMAT_A8P8 = 0x72,
DXGI_FORMAT_B4G4R4A4_UNORM = 0x73,
DXGI_FORMAT_P208 = 0x82,
DXGI_FORMAT_V208 = 0x83,
DXGI_FORMAT_V408 = 0x84,
DXGI_FORMAT_FORCE_UINT = 0xffffffff,
} DXGI_FORMAT;

View File

@ -0,0 +1,171 @@
#include "ImageFormat.h"
ImageFormat::ImageFormat(const ImageFormatId id, const DXGI_FORMAT dxgiFormat)
{
m_id = id;
m_dxgi_format = dxgiFormat;
}
ImageFormatId ImageFormat::GetId() const
{
return m_id;
}
DXGI_FORMAT ImageFormat::GetDxgiFormat() const
{
return m_dxgi_format;
}
ImageFormatUnsigned::ImageFormatUnsigned(const ImageFormatId id, const DXGI_FORMAT dxgiFormat,
const unsigned bitsPerPixel, const unsigned rOffset, const unsigned rSize,
const unsigned gOffset, const unsigned gSize, const unsigned bOffset,
const unsigned bSize, const unsigned aOffset, const unsigned aSize)
: ImageFormat(id, dxgiFormat),
m_bits_per_pixel(bitsPerPixel),
m_r_offset(rOffset),
m_r_size(rSize),
m_g_offset(gOffset),
m_g_size(gSize),
m_b_offset(bOffset),
m_b_size(bSize),
m_a_offset(aOffset),
m_a_size(aSize)
{
}
ImageFormatType ImageFormatUnsigned::GetType() const
{
return ImageFormatType::UNSIGNED;
}
size_t ImageFormatUnsigned::GetPitch(const unsigned mipLevel, const unsigned width) const
{
unsigned mipWidth = width >> mipLevel;
if (mipWidth == 0)
mipWidth = 1;
return mipWidth * m_bits_per_pixel / 8;
}
size_t ImageFormatUnsigned::GetSizeOfMipLevel(const unsigned mipLevel, const unsigned width, const unsigned height,
const unsigned depth) const
{
unsigned mipWidth = width >> mipLevel;
unsigned mipHeight = height >> mipLevel;
unsigned mipDepth = depth >> mipLevel;
if (mipWidth == 0)
mipWidth = 1;
if (mipHeight == 0)
mipHeight = 1;
if (mipDepth == 0)
mipDepth = 1;
return mipWidth * mipHeight * mipDepth * m_bits_per_pixel / 8;
}
ImageFormatBlockCompressed::ImageFormatBlockCompressed(const ImageFormatId id, const DXGI_FORMAT dxgiFormat,
const unsigned blockSize, const unsigned bitsPerBlock)
: ImageFormat(id, dxgiFormat),
m_block_size(blockSize),
m_bits_per_block(bitsPerBlock)
{
}
ImageFormatType ImageFormatBlockCompressed::GetType() const
{
return ImageFormatType::BLOCK_COMPRESSED;
}
size_t ImageFormatBlockCompressed::GetPitch(const unsigned mipLevel, const unsigned width) const
{
unsigned mipWidth = width >> mipLevel;
if (mipWidth == 0)
mipWidth = 1;
const unsigned blockCount = (mipWidth + m_block_size - 1) / m_block_size;
return blockCount * m_bits_per_block / 8;
}
size_t ImageFormatBlockCompressed::GetSizeOfMipLevel(const unsigned mipLevel, const unsigned width,
const unsigned height, const unsigned depth) const
{
unsigned mipWidth = width >> mipLevel;
unsigned mipHeight = height >> mipLevel;
unsigned mipDepth = depth >> mipLevel;
if (mipWidth == 0)
mipWidth = 1;
if (mipHeight == 0)
mipHeight = 1;
if (mipDepth == 0)
mipDepth = 1;
const unsigned blockCount = ((mipWidth + m_block_size - 1) / m_block_size)
* ((mipHeight + m_block_size - 1) / m_block_size)
* mipDepth;
return blockCount * m_bits_per_block / 8;
}
bool ImageFormatUnsigned::HasR() const
{
return m_r_size > 0;
}
bool ImageFormatUnsigned::HasG() const
{
return m_g_size > 0;
}
bool ImageFormatUnsigned::HasB() const
{
return m_b_size > 0;
}
bool ImageFormatUnsigned::HasA() const
{
return m_a_size > 0;
}
const ImageFormatUnsigned ImageFormat::FORMAT_R8_G8_B8(ImageFormatId::R8_G8_B8, DXGI_FORMAT_UNKNOWN,
24, 0, 8, 8, 8, 16, 8, 0, 0);
const ImageFormatUnsigned ImageFormat::FORMAT_B8_G8_R8_X8(ImageFormatId::B8_G8_R8_X8, DXGI_FORMAT_B8G8R8X8_UNORM,
32, 16, 8, 8, 8, 0, 8, 0, 0);
const ImageFormatUnsigned ImageFormat::FORMAT_R8_G8_B8_A8(ImageFormatId::R8_G8_B8_A8, DXGI_FORMAT_R8G8B8A8_UNORM,
32, 0, 8, 8, 8, 16, 8, 24, 8);
const ImageFormatUnsigned ImageFormat::FORMAT_B8_G8_R8_A8(ImageFormatId::B8_G8_R8_A8, DXGI_FORMAT_B8G8R8A8_UNORM,
32, 16, 8, 8, 8, 0, 8, 24, 8);
const ImageFormatUnsigned ImageFormat::FORMAT_A8(ImageFormatId::A8, DXGI_FORMAT_A8_UNORM,
8, 0, 0, 0, 0, 0, 0, 0, 8);
const ImageFormatUnsigned ImageFormat::FORMAT_R16_G16_B16_A16_FLOAT(ImageFormatId::R16_G16_B16_A16_FLOAT,
DXGI_FORMAT_R16G16B16A16_FLOAT,
128, 0, 0, 0, 0, 0, 0, 0, 8);
const ImageFormatUnsigned ImageFormat::FORMAT_R8(ImageFormatId::R8, DXGI_FORMAT_R8_UNORM,
8, 0, 8, 0, 0, 0, 0, 0, 0);
const ImageFormatUnsigned ImageFormat::FORMAT_R8_A8(ImageFormatId::R8_A8, DXGI_FORMAT_UNKNOWN,
16, 0, 8, 0, 0, 0, 0, 8, 8);
const ImageFormatBlockCompressed ImageFormat::FORMAT_BC1(ImageFormatId::BC1, DXGI_FORMAT_BC1_UNORM, 4, 64);
const ImageFormatBlockCompressed ImageFormat::FORMAT_BC2(ImageFormatId::BC2, DXGI_FORMAT_BC2_UNORM, 4, 128);
const ImageFormatBlockCompressed ImageFormat::FORMAT_BC3(ImageFormatId::BC3, DXGI_FORMAT_BC3_UNORM, 4, 128);
const ImageFormatBlockCompressed ImageFormat::FORMAT_BC4(ImageFormatId::BC4, DXGI_FORMAT_BC4_UNORM, 4, 64);
const ImageFormatBlockCompressed ImageFormat::FORMAT_BC5(ImageFormatId::BC5, DXGI_FORMAT_BC5_UNORM, 4, 128);
const ImageFormat* const ImageFormat::ALL_FORMATS[static_cast<unsigned>(ImageFormatId::MAX)]
{
&FORMAT_R8_G8_B8,
&FORMAT_B8_G8_R8_X8,
&FORMAT_R8_G8_B8_A8,
&FORMAT_B8_G8_R8_A8,
&FORMAT_A8,
&FORMAT_R16_G16_B16_A16_FLOAT,
&FORMAT_R8,
&FORMAT_R8_A8,
&FORMAT_BC1,
&FORMAT_BC2,
&FORMAT_BC3,
&FORMAT_BC4,
&FORMAT_BC5,
};

View File

@ -0,0 +1,109 @@
#pragma once
#include <cstdint>
#include <cstddef>
#include "DxgiFormat.h"
enum class ImageFormatId
{
UNKNOWN = -1,
R8_G8_B8,
B8_G8_R8_X8,
R8_G8_B8_A8,
B8_G8_R8_A8,
A8,
R16_G16_B16_A16_FLOAT,
R8,
R8_A8,
BC1,
BC2,
BC3,
BC4,
BC5,
MAX
};
enum class ImageFormatType
{
UNKNOWN,
UNSIGNED,
BLOCK_COMPRESSED
};
class ImageFormatUnsigned;
class ImageFormatBlockCompressed;
class ImageFormat
{
ImageFormatId m_id;
DXGI_FORMAT m_dxgi_format;
protected:
ImageFormat(ImageFormatId id, DXGI_FORMAT dxgiFormat);
public:
virtual ~ImageFormat() = default;
ImageFormatId GetId() const;
DXGI_FORMAT GetDxgiFormat() const;
virtual ImageFormatType GetType() const = 0;
virtual size_t GetPitch(unsigned mipLevel, unsigned width) const = 0;
virtual size_t GetSizeOfMipLevel(unsigned mipLevel, unsigned width, unsigned height, unsigned depth) const = 0;
static const ImageFormatUnsigned FORMAT_R8_G8_B8;
static const ImageFormatUnsigned FORMAT_B8_G8_R8_X8;
static const ImageFormatUnsigned FORMAT_R8_G8_B8_A8;
static const ImageFormatUnsigned FORMAT_B8_G8_R8_A8;
static const ImageFormatUnsigned FORMAT_A8;
static const ImageFormatUnsigned FORMAT_R16_G16_B16_A16_FLOAT; //TODO: Float not unsigned
static const ImageFormatUnsigned FORMAT_R8;
static const ImageFormatUnsigned FORMAT_R8_A8;
static const ImageFormatBlockCompressed FORMAT_BC1;
static const ImageFormatBlockCompressed FORMAT_BC2;
static const ImageFormatBlockCompressed FORMAT_BC3;
static const ImageFormatBlockCompressed FORMAT_BC4;
static const ImageFormatBlockCompressed FORMAT_BC5;
static const ImageFormat* const ALL_FORMATS[static_cast<unsigned>(ImageFormatId::MAX)];
};
class ImageFormatUnsigned final : public ImageFormat
{
public:
unsigned m_bits_per_pixel;
unsigned m_r_offset;
unsigned m_r_size;
unsigned m_g_offset;
unsigned m_g_size;
unsigned m_b_offset;
unsigned m_b_size;
unsigned m_a_offset;
unsigned m_a_size;
ImageFormatUnsigned(ImageFormatId id, DXGI_FORMAT dxgiFormat, unsigned bitsPerPixel, unsigned rOffset,
unsigned rSize, unsigned gOffset, unsigned gSize, unsigned bOffset, unsigned bSize,
unsigned aOffset, unsigned aSize);
ImageFormatType GetType() const override;
size_t GetPitch(unsigned mipLevel, unsigned width) const override;
size_t GetSizeOfMipLevel(unsigned mipLevel, unsigned width, unsigned height, unsigned depth) const override;
bool HasR() const;
bool HasG() const;
bool HasB() const;
bool HasA() const;
};
class ImageFormatBlockCompressed final : public ImageFormat
{
public:
unsigned m_block_size;
unsigned m_bits_per_block;
ImageFormatBlockCompressed(ImageFormatId id, DXGI_FORMAT dxgiFormat, unsigned blockSize, unsigned bitsPerBlock);
ImageFormatType GetType() const override;
size_t GetPitch(unsigned mipLevel, unsigned width) const override;
size_t GetSizeOfMipLevel(unsigned mipLevel, unsigned width, unsigned height, unsigned depth) const override;
};

145
src/Common/Image/IwiTypes.h Normal file
View File

@ -0,0 +1,145 @@
#pragma once
#include <cstdint>
struct IwiVersion
{
char tag[3];
char version;
};
// IW4
namespace iwi8
{
struct IwiHeader
{
uint32_t flags;
int8_t format;
int8_t unused;
uint16_t dimensions[3];
uint32_t fileSizeForPicmip[4];
};
enum class IwiFormat
{
IMG_FORMAT_INVALID = 0x0,
IMG_FORMAT_BITMAP_RGBA = 0x1,
IMG_FORMAT_BITMAP_RGB = 0x2,
IMG_FORMAT_BITMAP_LUMINANCE_ALPHA = 0x3,
IMG_FORMAT_BITMAP_LUMINANCE = 0x4,
IMG_FORMAT_BITMAP_ALPHA = 0x5,
IMG_FORMAT_WAVELET_RGBA = 0x6,
IMG_FORMAT_WAVELET_RGB = 0x7,
IMG_FORMAT_WAVELET_LUMINANCE_ALPHA = 0x8,
IMG_FORMAT_WAVELET_LUMINANCE = 0x9,
IMG_FORMAT_WAVELET_ALPHA = 0xA,
IMG_FORMAT_DXT1 = 0xB,
IMG_FORMAT_DXT3 = 0xC,
IMG_FORMAT_DXT5 = 0xD,
IMG_FORMAT_DXN = 0xE,
IMG_FORMAT_DXT3A_AS_LUMINANCE = 0xF,
IMG_FORMAT_DXT5A_AS_LUMINANCE = 0x10,
IMG_FORMAT_DXT3A_AS_ALPHA = 0x11,
IMG_FORMAT_DXT5A_AS_ALPHA = 0x12,
IMG_FORMAT_DXT1_AS_LUMINANCE_ALPHA = 0x13,
IMG_FORMAT_DXN_AS_LUMINANCE_ALPHA = 0x14,
IMG_FORMAT_DXT1_AS_LUMINANCE = 0x15,
IMG_FORMAT_DXT1_AS_ALPHA = 0x16,
IMG_FORMAT_COUNT
};
enum IwiFlags
{
IMG_FLAG_NOPICMIP = 1 << 0,
IMG_FLAG_NOMIPMAPS = 1 << 1,
IMG_FLAG_STREAMING = 1 << 2,
IMG_FLAG_LEGACY_NORMALS = 1 << 3,
IMG_FLAG_CLAMP_U = 1 << 4,
IMG_FLAG_CLAMP_V = 1 << 5,
IMG_FLAG_ALPHA_WEIGHTED_COLORS = 1 << 6,
IMG_FLAG_DXTC_APPROX_WEIGHTS = 1 << 7,
IMG_FLAG_GAMMA_NONE = 0,
IMG_FLAG_GAMMA_SRGB = 1 << 8,
IMG_FLAG_GAMMA_PWL = 1 << 9,
IMG_FLAG_GAMMA_2 = IMG_FLAG_GAMMA_SRGB | IMG_FLAG_GAMMA_PWL,
IMG_FLAG_MAPTYPE_2D = 0,
IMG_FLAG_MAPTYPE_CUBE = 1 << 16,
IMG_FLAG_MAPTYPE_3D = 1 << 17,
IMG_FLAG_MAPTYPE_1D = IMG_FLAG_MAPTYPE_CUBE | IMG_FLAG_MAPTYPE_3D,
IMG_FLAG_MAPTYPE_MASK = IMG_FLAG_MAPTYPE_2D | IMG_FLAG_MAPTYPE_CUBE | IMG_FLAG_MAPTYPE_3D | IMG_FLAG_MAPTYPE_1D,
IMG_FLAG_NORMALMAP = 1 << 18,
IMG_FLAG_INTENSITY_TO_ALPHA = 1 << 19,
IMG_FLAG_DYNAMIC = 1 << 24,
IMG_FLAG_RENDER_TARGET = 1 << 25,
IMG_FLAG_SYSTEMMEM = 1 << 26
};
}
// T5
namespace iwi13
{
struct IwiHeader
{
int8_t format;
int8_t flags;
uint16_t dimensions[3];
float gamma;
uint32_t fileSizeForPicmip[8];
};
}
// T6
namespace iwi27
{
struct IwiHeader
{
int8_t format;
int8_t flags;
uint16_t dimensions[3];
float gamma;
int8_t maxGlossForMip[16];
uint32_t fileSizeForPicmip[8];
};
enum class IwiFormat
{
IMG_FORMAT_INVALID = 0x0,
IMG_FORMAT_BITMAP_RGBA = 0x1,
IMG_FORMAT_BITMAP_RGB = 0x2,
IMG_FORMAT_BITMAP_LUMINANCE_ALPHA = 0x3,
IMG_FORMAT_BITMAP_LUMINANCE = 0x4,
IMG_FORMAT_BITMAP_ALPHA = 0x5,
IMG_FORMAT_WAVELET_RGBA = 0x6,
IMG_FORMAT_WAVELET_RGB = 0x7,
IMG_FORMAT_WAVELET_LUMINANCE_ALPHA = 0x8,
IMG_FORMAT_WAVELET_LUMINANCE = 0x9,
IMG_FORMAT_WAVELET_ALPHA = 0xA,
IMG_FORMAT_DXT1 = 0xB,
IMG_FORMAT_DXT3 = 0xC,
IMG_FORMAT_DXT5 = 0xD,
IMG_FORMAT_DXN = 0xE,
IMG_FORMAT_BITMAP_RGB565 = 0xF,
IMG_FORMAT_BITMAP_RGB5A3 = 0x10,
IMG_FORMAT_BITMAP_C8 = 0x11,
IMG_FORMAT_BITMAP_RGBA8 = 0x12,
IMG_FORMAT_A16B16G16R16F = 0x13,
IMG_FORMAT_COUNT,
};
enum IwiFlags
{
IMG_FLAG_NOPICMIP = 1 << 0,
IMG_FLAG_NOMIPMAPS = 1 << 1,
IMG_FLAG_CUBEMAP = 1 << 2,
IMG_FLAG_VOLMAP = 1 << 3,
IMG_FLAG_STREAMING = 1 << 4,
IMG_FLAG_CLAMP_U = 1 << 6,
IMG_FLAG_CLAMP_V = 1 << 7,
IMG_FLAG_FORCE_SYSTEM = 1 << 8,
IMG_FLAG_DYNAMIC = 1 << 16,
IMG_FLAG_RENDER_TARGET = 1 << 17,
IMG_FLAG_MULTISAMPLE = 1 << 18,
};
}

View File

@ -0,0 +1,363 @@
#include "Texture.h"
#include <algorithm>
#include <cassert>
#include <cstring>
// ==============================================
// ================= Texture ====================
// ==============================================
Texture::Texture(const ImageFormat* format, const bool mipMaps)
{
m_format = format;
m_has_mip_maps = mipMaps;
m_data = nullptr;
}
Texture::Texture(Texture&& other) noexcept
{
m_format = other.m_format;
m_has_mip_maps = other.m_has_mip_maps;
m_data = other.m_data;
other.m_data = nullptr;
}
Texture& Texture::operator=(Texture&& other) noexcept
{
m_format = other.m_format;
m_has_mip_maps = other.m_has_mip_maps;
m_data = other.m_data;
other.m_data = nullptr;
return *this;
}
Texture::~Texture()
{
delete[] m_data;
m_data = nullptr;
}
const ImageFormat* Texture::GetFormat() const
{
return m_format;
}
void Texture::Allocate()
{
size_t storageRequirement = 0;
const int mipLevelCount = m_has_mip_maps ? GetMipMapCount() : 1;
for (int currentMipLevel = 0; currentMipLevel < mipLevelCount; currentMipLevel++)
{
storageRequirement += GetSizeOfMipLevel(currentMipLevel) * GetFaceCount();
}
if (storageRequirement > 0)
{
m_data = new uint8_t[storageRequirement];
memset(m_data, 0, storageRequirement);
}
}
bool Texture::Empty() const
{
return m_data == nullptr;
}
bool Texture::HasMipMaps() const
{
return m_has_mip_maps;
}
uint8_t* Texture::GetBufferForMipLevel(const int mipLevel)
{
return GetBufferForMipLevel(mipLevel, 0);
}
// ==============================================
// ================ Texture2D ===================
// ==============================================
Texture2D::Texture2D(const ImageFormat* format, const unsigned width, const unsigned height)
: Texture2D(format, width, height, false)
{
}
Texture2D::Texture2D(const ImageFormat* format, const unsigned width, const unsigned height, const bool mipMaps)
: Texture(format, mipMaps)
{
m_width = width;
m_height = height;
}
Texture2D::Texture2D(Texture2D&& other) noexcept
: Texture(std::move(other)),
m_width(other.m_width),
m_height(other.m_height)
{
}
Texture2D::~Texture2D() = default;
Texture2D& Texture2D::operator=(Texture2D&& other) noexcept
{
if (this == &other)
return *this;
Texture::operator=(std::move(other));
m_width = other.m_width;
m_height = other.m_height;
return *this;
}
TextureType Texture2D::GetTextureType() const
{
return TextureType::T_2D;
}
unsigned Texture2D::GetWidth() const
{
return m_width;
}
unsigned Texture2D::GetHeight() const
{
return m_height;
}
unsigned Texture2D::GetDepth() const
{
return 1;
}
int Texture2D::GetFaceCount() const
{
return 1;
}
size_t Texture2D::GetSizeOfMipLevel(const int mipLevel) const
{
return m_format->GetSizeOfMipLevel(mipLevel, m_width, m_height, 1);
}
int Texture2D::GetMipMapCount() const
{
unsigned maxDimension = std::max(m_width, m_height);
int mipMapCount = 0;
while (maxDimension != 0)
{
maxDimension >>= 1;
mipMapCount++;
}
return mipMapCount;
}
uint8_t* Texture2D::GetBufferForMipLevel(const int mipLevel, const int face)
{
assert(mipLevel >= 0);
assert(mipLevel < (m_has_mip_maps ? GetMipMapCount() : 1));
assert(face == 0);
assert(m_data);
if (mipLevel < 0 || mipLevel >= (m_has_mip_maps ? GetMipMapCount() : 1))
return nullptr;
if (face != 0)
return nullptr;
if (!m_data)
return nullptr;
size_t bufferOffset = 0;
for (int previousMipLevel = 0; previousMipLevel < mipLevel; previousMipLevel++)
{
bufferOffset += GetSizeOfMipLevel(previousMipLevel);
}
return &m_data[bufferOffset];
}
// ==============================================
// =============== TextureCube ==================
// ==============================================
const int TextureCube::FACE_COUNT = 6;
TextureCube::TextureCube(const ImageFormat* format, const unsigned width, const unsigned height)
: Texture2D(format, width, height)
{
}
TextureCube::TextureCube(const ImageFormat* format, const unsigned width, const unsigned height, const bool mipMaps)
: Texture2D(format, width, height, mipMaps)
{
}
TextureCube::TextureCube(TextureCube&& other) noexcept
: Texture2D(std::move(other))
{
}
TextureCube::~TextureCube() = default;
TextureCube& TextureCube::operator=(TextureCube&& other) noexcept
{
if (this == &other)
return *this;
Texture2D::operator=(std::move(other));
return *this;
}
TextureType TextureCube::GetTextureType() const
{
return TextureType::T_CUBE;
}
int TextureCube::GetFaceCount() const
{
return FACE_COUNT;
}
uint8_t* TextureCube::GetBufferForMipLevel(const int mipLevel, const int face)
{
assert(mipLevel >= 0);
assert(mipLevel < (m_has_mip_maps ? GetMipMapCount() : 1));
assert(face >= 0);
assert(face < FACE_COUNT);
assert(m_data);
if (mipLevel < 0 || mipLevel >= (m_has_mip_maps ? GetMipMapCount() : 1))
return nullptr;
if (face < 0 || face >= FACE_COUNT)
return nullptr;
if (!m_data)
return nullptr;
size_t bufferOffset = 0;
for (int previousMipLevel = 0; previousMipLevel < mipLevel; previousMipLevel++)
{
bufferOffset += GetSizeOfMipLevel(previousMipLevel) * FACE_COUNT;
}
return &m_data[bufferOffset + GetSizeOfMipLevel(mipLevel) * face];
}
// ==============================================
// ================ Texture3D ===================
// ==============================================
Texture3D::Texture3D(const ImageFormat* format, const unsigned width, const unsigned height, const unsigned depth)
: Texture3D(format, width, height, depth, false)
{
}
Texture3D::Texture3D(const ImageFormat* format, const unsigned width, const unsigned height, const unsigned depth,
const bool mipMaps)
: Texture(format, mipMaps)
{
m_width = width;
m_height = height;
m_depth = depth;
}
Texture3D::Texture3D(Texture3D&& other) noexcept
: Texture(std::move(other)),
m_width(other.m_width),
m_height(other.m_height),
m_depth(other.m_depth)
{
}
Texture3D::~Texture3D() = default;
Texture3D& Texture3D::operator=(Texture3D&& other) noexcept
{
if (this == &other)
return *this;
Texture::operator=(std::move(other));
m_width = other.m_width;
m_height = other.m_height;
m_depth = other.m_depth;
return *this;
}
TextureType Texture3D::GetTextureType() const
{
return TextureType::T_3D;
}
unsigned Texture3D::GetWidth() const
{
return m_width;
}
unsigned Texture3D::GetHeight() const
{
return m_height;
}
unsigned Texture3D::GetDepth() const
{
return m_depth;
}
int Texture3D::GetFaceCount() const
{
return 1;
}
size_t Texture3D::GetSizeOfMipLevel(const int mipLevel) const
{
return m_format->GetSizeOfMipLevel(mipLevel, m_width, m_height, m_depth);
}
int Texture3D::GetMipMapCount() const
{
unsigned maxDimension = std::max(std::max(m_width, m_height), m_depth);
int mipMapCount = 0;
while (maxDimension != 0)
{
maxDimension >>= 1;
mipMapCount++;
}
return mipMapCount;
}
uint8_t* Texture3D::GetBufferForMipLevel(const int mipLevel, const int face)
{
assert(mipLevel >= 0);
assert(mipLevel < (m_has_mip_maps ? GetMipMapCount() : 1));
assert(face == 0);
assert(m_data);
if (mipLevel < 0 || mipLevel >= (m_has_mip_maps ? GetMipMapCount() : 1))
return nullptr;
if (face != 0)
return nullptr;
if (!m_data)
return nullptr;
size_t bufferOffset = 0;
for (int previousMipLevel = 0; previousMipLevel < mipLevel; previousMipLevel++)
{
bufferOffset += GetSizeOfMipLevel(previousMipLevel);
}
return &m_data[bufferOffset];
}

126
src/Common/Image/Texture.h Normal file
View File

@ -0,0 +1,126 @@
#pragma once
#include "ImageFormat.h"
#include <cstdint>
enum class TextureType
{
T_2D,
T_CUBE,
T_3D
};
class Texture
{
protected:
const ImageFormat* m_format;
bool m_has_mip_maps;
uint8_t* m_data;
Texture(const ImageFormat* format, bool mipMaps);
Texture(Texture&& other) noexcept;
Texture& operator=(Texture&& other) noexcept;
public:
Texture(const Texture& other) = delete;
virtual ~Texture();
Texture& operator=(const Texture& other) = delete;
virtual TextureType GetTextureType() const = 0;
const ImageFormat* GetFormat() const;
virtual unsigned GetWidth() const = 0;
virtual unsigned GetHeight() const = 0;
virtual unsigned GetDepth() const = 0;
virtual int GetFaceCount() const = 0;
void Allocate();
bool Empty() const;
virtual size_t GetSizeOfMipLevel(int mipLevel) const = 0;
virtual uint8_t* GetBufferForMipLevel(int mipLevel, int face) = 0;
uint8_t* GetBufferForMipLevel(int mipLevel);
bool HasMipMaps() const;
virtual int GetMipMapCount() const = 0;
};
class Texture2D : public Texture
{
protected:
unsigned m_width;
unsigned m_height;
public:
Texture2D(const ImageFormat* format, unsigned width, unsigned height);
Texture2D(const ImageFormat* format, unsigned width, unsigned height, bool mipMaps);
Texture2D(const Texture2D& other) = delete;
Texture2D(Texture2D&& other) noexcept;
~Texture2D() override;
Texture2D& operator=(const Texture2D& other) = delete;
Texture2D& operator=(Texture2D&& other) noexcept;
TextureType GetTextureType() const override;
unsigned GetWidth() const override;
unsigned GetHeight() const override;
unsigned GetDepth() const override;
int GetFaceCount() const override;
size_t GetSizeOfMipLevel(int mipLevel) const override;
uint8_t* GetBufferForMipLevel(int mipLevel, int face) override;
int GetMipMapCount() const override;
};
class TextureCube final : public Texture2D
{
static const int FACE_COUNT;
public:
TextureCube(const ImageFormat* format, unsigned width, unsigned height);
TextureCube(const ImageFormat* format, unsigned width, unsigned height, bool mipMaps);
TextureCube(const TextureCube& other) = delete;
TextureCube(TextureCube&& other) noexcept;
~TextureCube() override;
TextureCube& operator=(const TextureCube& other) = delete;
TextureCube& operator=(TextureCube&& other) noexcept;
TextureType GetTextureType() const override;
int GetFaceCount() const override;
uint8_t* GetBufferForMipLevel(int mipLevel, int face) override;
};
class Texture3D final : public Texture
{
unsigned m_width;
unsigned m_height;
unsigned m_depth;
public:
Texture3D(const ImageFormat* format, unsigned width, unsigned height, unsigned depth);
Texture3D(const ImageFormat* format, unsigned width, unsigned height, unsigned depth, bool mipMaps);
Texture3D(const Texture3D& other) = delete;
Texture3D(Texture3D&& other) noexcept;
~Texture3D() override;
Texture3D& operator=(const Texture3D& other) = delete;
Texture3D& operator=(Texture3D&& other) noexcept;
TextureType GetTextureType() const override;
unsigned GetWidth() const override;
unsigned GetHeight() const override;
unsigned GetDepth() const override;
int GetFaceCount() const override;
size_t GetSizeOfMipLevel(int mipLevel) const override;
uint8_t* GetBufferForMipLevel(int mipLevel, int face) override;
int GetMipMapCount() const override;
};

View File

@ -0,0 +1,229 @@
#include "TextureConverter.h"
#include <cassert>
constexpr uint64_t TextureConverter::Mask1(const unsigned length)
{
if (length >= sizeof(uint64_t) * 8)
return UINT64_MAX;
return UINT64_MAX >> (sizeof(uint64_t) * 8 - length);
}
void TextureConverter::SetPixelFunctions(const unsigned inBitCount, const unsigned outBitCount)
{
switch (inBitCount)
{
case 16:
m_read_pixel_func = [](const void* offset, unsigned bitCount)
{
return static_cast<uint64_t>(*static_cast<const uint16_t*>(offset));
};
break;
case 32:
m_read_pixel_func = [](const void* offset, unsigned bitCount)
{
return static_cast<uint64_t>(*static_cast<const uint32_t*>(offset));
};
break;
case 64:
m_read_pixel_func = [](const void* offset, unsigned bitCount)
{
return *static_cast<const uint64_t*>(offset);
};
break;
default:
if (inBitCount <= 64)
{
m_read_pixel_func = [](const void* offset, const unsigned bitCount)
{
uint64_t result = 0;
for (auto pixelOffset = 0u; pixelOffset < bitCount; pixelOffset += 8)
{
result |= (static_cast<uint64_t>(*(static_cast<const uint8_t*>(offset) + (pixelOffset / 8))) <<
pixelOffset);
}
return result;
};
}
else
{
assert(false);
m_read_pixel_func = [](const void* offset, unsigned bitCount)
{
return 0ull;
};
}
break;
}
switch (outBitCount)
{
case 16:
m_write_pixel_func = [](void* offset, const uint64_t pixel, unsigned bitCount)
{
*static_cast<uint16_t*>(offset) = static_cast<uint16_t>(pixel);
};
break;
case 32:
m_write_pixel_func = [](void* offset, const uint64_t pixel, unsigned bitCount)
{
*static_cast<uint32_t*>(offset) = static_cast<uint32_t>(pixel);
};
break;
case 64:
m_write_pixel_func = [](void* offset, const uint64_t pixel, unsigned bitCount)
{
*static_cast<uint64_t*>(offset) = pixel;
};
break;
default:
if (inBitCount <= 64)
{
m_write_pixel_func = [](void* offset, const uint64_t pixel, const unsigned bitCount)
{
for (auto pixelOffset = 0u; pixelOffset < bitCount; pixelOffset += 8)
{
*(static_cast<uint8_t*>(offset) + (pixelOffset / 8)) = static_cast<uint8_t>(pixel >> pixelOffset);
}
};
}
else
{
assert(false);
m_write_pixel_func = [](void* offset, uint64_t pixel, unsigned bitCount)
{
};
}
break;
}
}
TextureConverter::TextureConverter(Texture* inputTexture, const ImageFormat* targetFormat)
: m_input_texture(inputTexture),
m_output_texture(nullptr),
m_input_format(inputTexture->GetFormat()),
m_output_format(targetFormat)
{
}
void TextureConverter::CreateOutputTexture()
{
switch (m_input_texture->GetTextureType())
{
case TextureType::T_2D:
m_output_texture = new Texture2D(m_output_format, m_input_texture->GetWidth(), m_input_texture->GetHeight(),
m_input_texture->HasMipMaps());
break;
case TextureType::T_CUBE:
m_output_texture = new TextureCube(m_output_format, m_input_texture->GetWidth(), m_input_texture->GetHeight(),
m_input_texture->HasMipMaps());
break;
case TextureType::T_3D:
m_output_texture = new Texture3D(m_output_format, m_input_texture->GetWidth(), m_input_texture->GetHeight(),
m_input_texture->GetDepth(), m_input_texture->HasMipMaps());
break;
default:
assert(false);
break;
}
m_output_texture->Allocate();
}
void TextureConverter::ReorderUnsignedToUnsigned() const
{
const auto* inputFormat = dynamic_cast<const ImageFormatUnsigned*>(m_input_format);
const auto* outputFormat = dynamic_cast<const ImageFormatUnsigned*>(m_output_format);
const auto mipCount = m_input_texture->HasMipMaps() ? m_input_texture->GetMipMapCount() : 1;
const auto rInputMask = inputFormat->HasR() ? Mask1(inputFormat->m_r_size) << inputFormat->m_r_offset : 0;
const auto gInputMask = inputFormat->HasG() ? Mask1(inputFormat->m_g_size) << inputFormat->m_g_offset : 0;
const auto bInputMask = inputFormat->HasB() ? Mask1(inputFormat->m_b_size) << inputFormat->m_b_offset : 0;
const auto aInputMask = inputFormat->HasA() ? Mask1(inputFormat->m_a_size) << inputFormat->m_a_offset : 0;
const bool rConvert = rInputMask != 0 && outputFormat->m_r_size > 0;
const bool gConvert = gInputMask != 0 && outputFormat->m_g_size > 0;
const bool bConvert = bInputMask != 0 && outputFormat->m_b_size > 0;
const bool aConvert = aInputMask != 0 && outputFormat->m_a_size > 0;
for (auto mipLevel = 0; mipLevel < mipCount; mipLevel++)
{
const auto mipLevelSize = m_input_texture->GetSizeOfMipLevel(mipLevel) * m_input_texture->GetFaceCount();
const auto* inputBuffer = m_input_texture->GetBufferForMipLevel(mipLevel);
auto* outputBuffer = m_output_texture->GetBufferForMipLevel(mipLevel);
const auto inputBytePerPixel = inputFormat->m_bits_per_pixel / 8;
const auto outputBytePerPixel = outputFormat->m_bits_per_pixel / 8;
auto outputOffset = 0u;
for (auto inputOffset = 0u; inputOffset < mipLevelSize; inputOffset += inputBytePerPixel, outputOffset +=
outputBytePerPixel)
{
uint64_t outPixel = 0;
const auto inPixel = m_read_pixel_func(&inputBuffer[inputOffset], inputFormat->m_bits_per_pixel);
if (rConvert)
outPixel |= (inPixel & rInputMask) >> inputFormat->m_r_offset << outputFormat->m_r_offset;
if (gConvert)
outPixel |= (inPixel & gInputMask) >> inputFormat->m_g_offset << outputFormat->m_g_offset;
if (bConvert)
outPixel |= (inPixel & bInputMask) >> inputFormat->m_b_offset << outputFormat->m_b_offset;
if (aConvert)
outPixel |= (inPixel & aInputMask) >> inputFormat->m_a_offset << outputFormat->m_a_offset;
m_write_pixel_func(&outputBuffer[outputOffset], outPixel, outputFormat->m_bits_per_pixel);
}
}
}
void TextureConverter::ConvertUnsignedToUnsigned()
{
const auto* inputFormat = dynamic_cast<const ImageFormatUnsigned*>(m_input_format);
const auto* outputFormat = dynamic_cast<const ImageFormatUnsigned*>(m_output_format);
assert(inputFormat->m_bits_per_pixel <= 64);
assert(outputFormat->m_bits_per_pixel <= 64);
SetPixelFunctions(inputFormat->m_bits_per_pixel, outputFormat->m_bits_per_pixel);
if (inputFormat->m_r_size == outputFormat->m_r_size
&& inputFormat->m_g_size == outputFormat->m_g_size
&& inputFormat->m_b_size == outputFormat->m_b_size
&& inputFormat->m_a_size == outputFormat->m_a_size)
{
ReorderUnsignedToUnsigned();
}
else
{
// Unsupported as of now
assert(false);
}
}
Texture* TextureConverter::Convert()
{
CreateOutputTexture();
if (m_input_format->GetType() == ImageFormatType::UNSIGNED
&& m_output_format->GetType() == ImageFormatType::UNSIGNED)
{
ConvertUnsignedToUnsigned();
}
else
{
// Unsupported as of now
assert(false);
}
return m_output_texture;
}

View File

@ -0,0 +1,30 @@
#pragma once
#include <functional>
#include "Texture.h"
class TextureConverter
{
Texture* m_input_texture;
Texture* m_output_texture;
const ImageFormat* m_input_format;
const ImageFormat* m_output_format;
std::function<uint64_t(const void* offset, unsigned bitCount)> m_read_pixel_func;
std::function<void(void* offset, uint64_t pixel, unsigned bitCount)> m_write_pixel_func;
static constexpr uint64_t Mask1(unsigned length);
void SetPixelFunctions(unsigned inBitCount, unsigned outBitCount);
void CreateOutputTexture();
void ReorderUnsignedToUnsigned() const;
void ConvertUnsignedToUnsigned();
public:
TextureConverter(Texture* inputTexture, const ImageFormat* targetFormat);
Texture* Convert();
};