Utility: Rework PixelFormat (WIP)

Former-commit-id: 1ab609e753783d9767ba23fd4cab9390453bf729
This commit is contained in:
Lynix
2016-05-17 14:23:45 +02:00
parent c31f70af55
commit 1ebe1a8091
9 changed files with 306 additions and 561 deletions

View File

@@ -2,13 +2,151 @@
// This file is part of the "Nazara Engine - Utility module"
// For conditions of distribution and use, see copyright notice in Config.hpp
#include <Nazara/Utility/PixelFormat.hpp>
#include <Nazara/Core/Error.hpp>
#include <algorithm>
#include <array>
#include <cstring>
#include <Nazara/Utility/Debug.hpp>
namespace Nz
{
inline PixelFormatInfo::PixelFormatInfo() :
bitsPerPixel(0),
content(PixelFormatContent_Undefined)
{
}
inline PixelFormatInfo::PixelFormatInfo(PixelFormatContent formatContent, UInt8 bpp, PixelFormatSubType subType) :
bitsPerPixel(bpp),
content(formatContent),
redType(subType),
greenType(subType),
blueType(subType),
alphaType(subType)
{
}
inline PixelFormatInfo::PixelFormatInfo(const String& formatName, PixelFormatContent formatContent, UInt8 bpp, PixelFormatSubType subType) :
bitsPerPixel(bpp),
content(formatContent),
redType(subType),
greenType(subType),
blueType(subType),
alphaType(subType),
name(formatName)
{
}
inline PixelFormatInfo::PixelFormatInfo(const String& formatName, PixelFormatContent formatContent, Bitset<> rMask, Bitset<> gMask, Bitset<> bMask, Bitset<> aMask, PixelFormatSubType subType) :
redMask(rMask),
greenMask(gMask),
blueMask(bMask),
alphaMask(aMask),
content(formatContent),
redType(subType),
greenType(subType),
blueType(subType),
alphaType(subType),
name(formatName)
{
RecomputeBitsPerPixel();
}
inline PixelFormatInfo::PixelFormatInfo(const String& formatName, PixelFormatContent formatContent, PixelFormatSubType rType, Bitset<> rMask, PixelFormatSubType gType, Bitset<> gMask, PixelFormatSubType bType, Bitset<> bMask, PixelFormatSubType aType, Bitset<> aMask, UInt8 bpp) :
redMask(rMask),
greenMask(gMask),
blueMask(bMask),
alphaMask(aMask),
content(formatContent),
redType(rType),
greenType(gType),
blueType(bType),
alphaType(aType),
name(formatName)
{
if (bpp == 0)
RecomputeBitsPerPixel();
}
inline void PixelFormatInfo::Clear()
{
bitsPerPixel = 0;
alphaMask.Clear();
blueMask.Clear();
greenMask.Clear();
redMask.Clear();
name.Clear();
}
inline bool PixelFormatInfo::IsCompressed() const
{
return redType == PixelFormatSubType_Compressed ||
greenType == PixelFormatSubType_Compressed ||
blueType == PixelFormatSubType_Compressed ||
alphaType == PixelFormatSubType_Compressed;
}
inline bool PixelFormatInfo::IsValid() const
{
return bitsPerPixel != 0;
}
inline void PixelFormatInfo::RecomputeBitsPerPixel()
{
Bitset<> counter;
counter |= redMask;
counter |= greenMask;
counter |= blueMask;
counter |= alphaMask;
bitsPerPixel = counter.Count();
}
inline bool PixelFormatInfo::Validate() const
{
if (!IsValid())
return false;
if (content <= PixelFormatContent_Undefined || content > PixelFormatContent_Max)
return false;
std::array<const Nz::Bitset<>*, 4> masks = {&redMask, &greenMask, &blueMask, &alphaMask};
std::array<PixelFormatSubType, 4> types = {redType, greenType, blueType, alphaType};
for (unsigned int i = 0; i < 4; ++i)
{
unsigned int usedBits = masks[i]->Count();
if (usedBits == 0)
continue;
if (usedBits > bitsPerPixel)
return false;
switch (types[i])
{
case PixelFormatSubType_Half:
if (usedBits != 16)
return false;
break;
case PixelFormatSubType_Float:
if (usedBits != 32)
return false;
break;
default:
break;
}
}
return true;
}
inline std::size_t PixelFormat::ComputeSize(PixelFormatType format, unsigned int width, unsigned int height, unsigned int depth)
{
if (IsCompressed(format))
@@ -54,13 +192,13 @@ namespace Nz
ConvertFunction func = s_convertFunctions[srcFormat][dstFormat];
if (!func)
{
NazaraError("Pixel format conversion from " + ToString(srcFormat) + " to " + ToString(dstFormat) + " is not supported");
NazaraError("Pixel format conversion from " + GetName(srcFormat) + " to " + GetName(dstFormat) + " is not supported");
return false;
}
if (!func(reinterpret_cast<const UInt8*>(src), reinterpret_cast<const UInt8*>(src) + GetBytesPerPixel(srcFormat), reinterpret_cast<UInt8*>(dst)))
{
NazaraError("Pixel format conversion from " + ToString(srcFormat) + " to " + ToString(dstFormat) + " failed");
NazaraError("Pixel format conversion from " + GetName(srcFormat) + " to " + GetName(dstFormat) + " failed");
return false;
}
@@ -78,13 +216,13 @@ namespace Nz
ConvertFunction func = s_convertFunctions[srcFormat][dstFormat];
if (!func)
{
NazaraError("Pixel format conversion from " + ToString(srcFormat) + " to " + ToString(dstFormat) + " is not supported");
NazaraError("Pixel format conversion from " + GetName(srcFormat) + " to " + GetName(dstFormat) + " is not supported");
return false;
}
if (!func(reinterpret_cast<const UInt8*>(start), reinterpret_cast<const UInt8*>(end), reinterpret_cast<UInt8*>(dst)))
{
NazaraError("Pixel format conversion from " + ToString(srcFormat) + " to " + ToString(dstFormat) + " failed");
NazaraError("Pixel format conversion from " + GetName(srcFormat) + " to " + GetName(dstFormat) + " failed");
return false;
}
@@ -189,126 +327,7 @@ namespace Nz
inline UInt8 PixelFormat::GetBitsPerPixel(PixelFormatType format)
{
switch (format)
{
case PixelFormatType_A8:
return 8;
case PixelFormatType_BGR8:
return 24;
case PixelFormatType_BGRA8:
return 32;
case PixelFormatType_DXT1:
return 8;
case PixelFormatType_DXT3:
return 16;
case PixelFormatType_DXT5:
return 16;
case PixelFormatType_L8:
return 8;
case PixelFormatType_LA8:
return 16;
case PixelFormatType_R8:
case PixelFormatType_R8I:
case PixelFormatType_R8UI:
return 8;
case PixelFormatType_R16:
case PixelFormatType_R16F:
case PixelFormatType_R16I:
case PixelFormatType_R16UI:
return 16;
case PixelFormatType_R32F:
case PixelFormatType_R32I:
case PixelFormatType_R32UI:
return 32;
case PixelFormatType_RG8:
case PixelFormatType_RG8I:
case PixelFormatType_RG8UI:
return 16;
case PixelFormatType_RG16:
case PixelFormatType_RG16F:
case PixelFormatType_RG16I:
case PixelFormatType_RG16UI:
return 32;
case PixelFormatType_RG32F:
case PixelFormatType_RG32I:
case PixelFormatType_RG32UI:
return 64;
case PixelFormatType_RGB16F:
case PixelFormatType_RGB16I:
case PixelFormatType_RGB16UI:
return 48;
case PixelFormatType_RGB32F:
case PixelFormatType_RGB32I:
case PixelFormatType_RGB32UI:
return 96;
case PixelFormatType_RGBA16F:
case PixelFormatType_RGBA16I:
case PixelFormatType_RGBA16UI:
return 64;
case PixelFormatType_RGBA32F:
case PixelFormatType_RGBA32I:
case PixelFormatType_RGBA32UI:
return 128;
case PixelFormatType_RGBA4:
return 16;
case PixelFormatType_RGB5A1:
return 16;
case PixelFormatType_RGB8:
return 24;
case PixelFormatType_RGBA8:
return 32;
case PixelFormatType_Depth16:
return 16;
case PixelFormatType_Depth24:
return 24;
case PixelFormatType_Depth24Stencil8:
return 32;
case PixelFormatType_Depth32:
return 32;
case PixelFormatType_Stencil1:
return 1;
case PixelFormatType_Stencil4:
return 2;
case PixelFormatType_Stencil8:
return 8;
case PixelFormatType_Stencil16:
return 16;
case PixelFormatType_Undefined:
break;
}
NazaraError("Invalid pixel format");
return 0;
return s_pixelFormatInfos[format].bitsPerPixel;
}
inline UInt8 PixelFormat::GetBytesPerPixel(PixelFormatType format)
@@ -316,212 +335,29 @@ namespace Nz
return GetBitsPerPixel(format)/8;
}
inline PixelFormatTypeType PixelFormat::GetType(PixelFormatType format)
inline PixelFormatContent PixelFormat::GetContent(PixelFormatType format)
{
switch (format)
{
case PixelFormatType_A8:
case PixelFormatType_BGR8:
case PixelFormatType_BGRA8:
case PixelFormatType_DXT1:
case PixelFormatType_DXT3:
case PixelFormatType_DXT5:
case PixelFormatType_L8:
case PixelFormatType_LA8:
case PixelFormatType_R8:
case PixelFormatType_R8I:
case PixelFormatType_R8UI:
case PixelFormatType_R16:
case PixelFormatType_R16F:
case PixelFormatType_R16I:
case PixelFormatType_R16UI:
case PixelFormatType_R32F:
case PixelFormatType_R32I:
case PixelFormatType_R32UI:
case PixelFormatType_RG8:
case PixelFormatType_RG8I:
case PixelFormatType_RG8UI:
case PixelFormatType_RG16:
case PixelFormatType_RG16F:
case PixelFormatType_RG16I:
case PixelFormatType_RG16UI:
case PixelFormatType_RG32F:
case PixelFormatType_RG32I:
case PixelFormatType_RG32UI:
case PixelFormatType_RGB5A1:
case PixelFormatType_RGB8:
case PixelFormatType_RGB16F:
case PixelFormatType_RGB16I:
case PixelFormatType_RGB16UI:
case PixelFormatType_RGB32F:
case PixelFormatType_RGB32I:
case PixelFormatType_RGB32UI:
case PixelFormatType_RGBA4:
case PixelFormatType_RGBA8:
case PixelFormatType_RGBA16F:
case PixelFormatType_RGBA16I:
case PixelFormatType_RGBA16UI:
case PixelFormatType_RGBA32F:
case PixelFormatType_RGBA32I:
case PixelFormatType_RGBA32UI:
return PixelFormatTypeType_Color;
return s_pixelFormatInfos[format].content;
}
case PixelFormatType_Depth16:
case PixelFormatType_Depth24:
case PixelFormatType_Depth32:
return PixelFormatTypeType_Depth;
inline const PixelFormatInfo& PixelFormat::GetInfo(PixelFormatType format)
{
return s_pixelFormatInfos[format];
}
case PixelFormatType_Depth24Stencil8:
return PixelFormatTypeType_DepthStencil;
case PixelFormatType_Stencil1:
case PixelFormatType_Stencil4:
case PixelFormatType_Stencil8:
case PixelFormatType_Stencil16:
return PixelFormatTypeType_Stencil;
case PixelFormatType_Undefined:
break;
}
NazaraError("Invalid pixel format");
return PixelFormatTypeType_Undefined;
inline const String& PixelFormat::GetName(PixelFormatType format)
{
return s_pixelFormatInfos[format].name;
}
inline bool PixelFormat::HasAlpha(PixelFormatType format)
{
switch (format)
{
case PixelFormatType_A8:
case PixelFormatType_BGRA8:
case PixelFormatType_DXT3:
case PixelFormatType_DXT5:
case PixelFormatType_LA8:
case PixelFormatType_RGB5A1:
case PixelFormatType_RGBA16F:
case PixelFormatType_RGBA16I:
case PixelFormatType_RGBA16UI:
case PixelFormatType_RGBA32F:
case PixelFormatType_RGBA32I:
case PixelFormatType_RGBA32UI:
case PixelFormatType_RGBA4:
case PixelFormatType_RGBA8:
return true;
case PixelFormatType_BGR8:
case PixelFormatType_DXT1:
case PixelFormatType_L8:
case PixelFormatType_R8:
case PixelFormatType_R8I:
case PixelFormatType_R8UI:
case PixelFormatType_R16:
case PixelFormatType_R16F:
case PixelFormatType_R16I:
case PixelFormatType_R16UI:
case PixelFormatType_R32F:
case PixelFormatType_R32I:
case PixelFormatType_R32UI:
case PixelFormatType_RG8:
case PixelFormatType_RG8I:
case PixelFormatType_RG8UI:
case PixelFormatType_RG16:
case PixelFormatType_RG16F:
case PixelFormatType_RG16I:
case PixelFormatType_RG16UI:
case PixelFormatType_RG32F:
case PixelFormatType_RG32I:
case PixelFormatType_RG32UI:
case PixelFormatType_RGB8:
case PixelFormatType_RGB16F:
case PixelFormatType_RGB16I:
case PixelFormatType_RGB16UI:
case PixelFormatType_RGB32F:
case PixelFormatType_RGB32I:
case PixelFormatType_RGB32UI:
case PixelFormatType_Depth16:
case PixelFormatType_Depth24:
case PixelFormatType_Depth24Stencil8:
case PixelFormatType_Depth32:
case PixelFormatType_Stencil1:
case PixelFormatType_Stencil4:
case PixelFormatType_Stencil8:
case PixelFormatType_Stencil16:
return false;
case PixelFormatType_Undefined:
break;
}
NazaraError("Invalid pixel format");
return false;
return s_pixelFormatInfos[format].alphaMask.TestAny();
}
inline bool PixelFormat::IsCompressed(PixelFormatType format)
{
switch (format)
{
case PixelFormatType_DXT1:
case PixelFormatType_DXT3:
case PixelFormatType_DXT5:
return true;
case PixelFormatType_A8:
case PixelFormatType_BGR8:
case PixelFormatType_BGRA8:
case PixelFormatType_L8:
case PixelFormatType_LA8:
case PixelFormatType_R8:
case PixelFormatType_R8I:
case PixelFormatType_R8UI:
case PixelFormatType_R16:
case PixelFormatType_R16F:
case PixelFormatType_R16I:
case PixelFormatType_R16UI:
case PixelFormatType_R32F:
case PixelFormatType_R32I:
case PixelFormatType_R32UI:
case PixelFormatType_RG8:
case PixelFormatType_RG8I:
case PixelFormatType_RG8UI:
case PixelFormatType_RG16:
case PixelFormatType_RG16F:
case PixelFormatType_RG16I:
case PixelFormatType_RG16UI:
case PixelFormatType_RG32F:
case PixelFormatType_RG32I:
case PixelFormatType_RG32UI:
case PixelFormatType_RGB5A1:
case PixelFormatType_RGB8:
case PixelFormatType_RGB16F:
case PixelFormatType_RGB16I:
case PixelFormatType_RGB16UI:
case PixelFormatType_RGB32F:
case PixelFormatType_RGB32I:
case PixelFormatType_RGB32UI:
case PixelFormatType_RGBA4:
case PixelFormatType_RGBA8:
case PixelFormatType_RGBA16F:
case PixelFormatType_RGBA16I:
case PixelFormatType_RGBA16UI:
case PixelFormatType_RGBA32F:
case PixelFormatType_RGBA32I:
case PixelFormatType_RGBA32UI:
case PixelFormatType_Depth16:
case PixelFormatType_Depth24:
case PixelFormatType_Depth24Stencil8:
case PixelFormatType_Depth32:
case PixelFormatType_Stencil1:
case PixelFormatType_Stencil4:
case PixelFormatType_Stencil8:
case PixelFormatType_Stencil16:
return false;
case PixelFormatType_Undefined:
break;
}
NazaraError("Invalid pixel format");
return false;
return s_pixelFormatInfos[format].IsCompressed();
}
inline bool PixelFormat::IsConversionSupported(PixelFormatType srcFormat, PixelFormatType dstFormat)
@@ -546,174 +382,6 @@ namespace Nz
{
s_flipFunctions[flipping][format] = func;
}
inline String PixelFormat::ToString(PixelFormatType format)
{
switch (format)
{
case PixelFormatType_A8:
return "A8";
case PixelFormatType_BGR8:
return "BGR8";
case PixelFormatType_BGRA8:
return "BGRA8";
case PixelFormatType_DXT1:
return "DXT1";
case PixelFormatType_DXT3:
return "DXT3";
case PixelFormatType_DXT5:
return "DXT5";
case PixelFormatType_L8:
return "L8";
case PixelFormatType_LA8:
return "LA8";
case PixelFormatType_R8:
return "R8";
case PixelFormatType_R8I:
return "R8I";
case PixelFormatType_R8UI:
return "R8UI";
case PixelFormatType_R16:
return "R16";
case PixelFormatType_R16F:
return "R16F";
case PixelFormatType_R16I:
return "R16I";
case PixelFormatType_R16UI:
return "R16UI";
case PixelFormatType_R32F:
return "R32F";
case PixelFormatType_R32I:
return "R32I";
case PixelFormatType_R32UI:
return "R32UI";
case PixelFormatType_RG8:
return "RG8";
case PixelFormatType_RG8I:
return "RG8I";
case PixelFormatType_RG8UI:
return "RG8UI";
case PixelFormatType_RG16:
return "RG16";
case PixelFormatType_RG16F:
return "RG16F";
case PixelFormatType_RG16I:
return "RG16I";
case PixelFormatType_RG16UI:
return "RG16UI";
case PixelFormatType_RG32F:
return "RG32F";
case PixelFormatType_RG32I:
return "RG32I";
case PixelFormatType_RG32UI:
return "RG32UI";
case PixelFormatType_RGB5A1:
return "RGB5A1";
case PixelFormatType_RGB8:
return "RGB8";
case PixelFormatType_RGB16F:
return "RGB16F";
case PixelFormatType_RGB16I:
return "RGB16I";
case PixelFormatType_RGB16UI:
return "RGB16UI";
case PixelFormatType_RGB32F:
return "RGB32F";
case PixelFormatType_RGB32I:
return "RGB32I";
case PixelFormatType_RGB32UI:
return "RGB32UI";
case PixelFormatType_RGBA4:
return "RGBA4";
case PixelFormatType_RGBA8:
return "RGBA8";
case PixelFormatType_RGBA16F:
return "RGBA16F";
case PixelFormatType_RGBA16I:
return "RGBA16I";
case PixelFormatType_RGBA16UI:
return "RGBA16UI";
case PixelFormatType_RGBA32F:
return "RGBA32F";
case PixelFormatType_RGBA32I:
return "RGBA32I";
case PixelFormatType_RGBA32UI:
return "RGBA32UI";
case PixelFormatType_Depth16:
return "Depth16";
case PixelFormatType_Depth24:
return "Depth24";
case PixelFormatType_Depth24Stencil8:
return "Depth24Stencil8";
case PixelFormatType_Depth32:
return "Depth32";
case PixelFormatType_Stencil1:
return "Stencil1";
case PixelFormatType_Stencil4:
return "Stencil4";
case PixelFormatType_Stencil8:
return "Stencil8";
case PixelFormatType_Stencil16:
return "Stencil16";
case PixelFormatType_Undefined:
return "Undefined";
}
NazaraError("Invalid pixel format");
return "Invalid format";
}
}
#include <Nazara/Utility/DebugOff.hpp>