Utility/Image: Clean memory managing
Former-commit-id: 15312493a66ea26266029a45cc3aa22cc83386eb
This commit is contained in:
parent
4f04795ef6
commit
310dcf40b1
|
|
@ -121,11 +121,12 @@ class NAZARA_API NzImage : public NzAbstractImage, public NzRefCounted, public N
|
||||||
|
|
||||||
struct SharedImage
|
struct SharedImage
|
||||||
{
|
{
|
||||||
SharedImage(unsigned short RefCount, nzImageType Type, nzPixelFormat Format, nzUInt8 LevelCount = 1, nzUInt8** Pixels = nullptr, unsigned int Width = 1, unsigned int Height = 1, unsigned int Depth = 1) :
|
using PixelContainer = std::vector<std::unique_ptr<nzUInt8[]>>;
|
||||||
|
|
||||||
|
SharedImage(unsigned short RefCount, nzImageType Type, nzPixelFormat Format, PixelContainer&& Levels, unsigned int Width, unsigned int Height, unsigned int Depth) :
|
||||||
type(Type),
|
type(Type),
|
||||||
format(Format),
|
format(Format),
|
||||||
levelCount(LevelCount),
|
levels(std::move(Levels)),
|
||||||
pixels(Pixels),
|
|
||||||
depth(Depth),
|
depth(Depth),
|
||||||
height(Height),
|
height(Height),
|
||||||
width(Width),
|
width(Width),
|
||||||
|
|
@ -135,8 +136,7 @@ class NAZARA_API NzImage : public NzAbstractImage, public NzRefCounted, public N
|
||||||
|
|
||||||
nzImageType type;
|
nzImageType type;
|
||||||
nzPixelFormat format;
|
nzPixelFormat format;
|
||||||
nzUInt8 levelCount;
|
PixelContainer levels;
|
||||||
nzUInt8** pixels;
|
|
||||||
unsigned int depth;
|
unsigned int depth;
|
||||||
unsigned int height;
|
unsigned int height;
|
||||||
unsigned int width;
|
unsigned int width;
|
||||||
|
|
|
||||||
|
|
@ -13,7 +13,7 @@
|
||||||
#include <Nazara/Utility/Debug.hpp>
|
#include <Nazara/Utility/Debug.hpp>
|
||||||
|
|
||||||
///TODO: Rajouter des warnings (Formats compressés avec les méthodes Copy/Update, tests taille dans Copy)
|
///TODO: Rajouter des warnings (Formats compressés avec les méthodes Copy/Update, tests taille dans Copy)
|
||||||
///TODO: Rendre les méthodes exception-safe (Virer toute cette merde de calcul de pointeurs, faire usage du RAII)
|
///TODO: Rendre les méthodes exception-safe (faire usage du RAII)
|
||||||
///FIXME: Gérer correctement les formats utilisant moins d'un octet par pixel
|
///FIXME: Gérer correctement les formats utilisant moins d'un octet par pixel
|
||||||
|
|
||||||
namespace
|
namespace
|
||||||
|
|
@ -70,7 +70,7 @@ NzImage::~NzImage()
|
||||||
Destroy();
|
Destroy();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool NzImage::Convert(nzPixelFormat format)
|
bool NzImage::Convert(nzPixelFormat newFormat)
|
||||||
{
|
{
|
||||||
#if NAZARA_UTILITY_SAFE
|
#if NAZARA_UTILITY_SAFE
|
||||||
if (m_sharedImage == &emptyImage)
|
if (m_sharedImage == &emptyImage)
|
||||||
|
|
@ -79,23 +79,23 @@ bool NzImage::Convert(nzPixelFormat format)
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!NzPixelFormat::IsValid(format))
|
if (!NzPixelFormat::IsValid(newFormat))
|
||||||
{
|
{
|
||||||
NazaraError("Invalid pixel format");
|
NazaraError("Invalid pixel format");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!NzPixelFormat::IsConversionSupported(m_sharedImage->format, format))
|
if (!NzPixelFormat::IsConversionSupported(m_sharedImage->format, newFormat))
|
||||||
{
|
{
|
||||||
NazaraError("Conversion from " + NzPixelFormat::ToString(m_sharedImage->format) + " to " + NzPixelFormat::ToString(format) + " is not supported");
|
NazaraError("Conversion from " + NzPixelFormat::ToString(m_sharedImage->format) + " to " + NzPixelFormat::ToString(newFormat) + " is not supported");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (format == m_sharedImage->format)
|
if (m_sharedImage->format == newFormat)
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
nzUInt8** levels = new nzUInt8*[m_sharedImage->levelCount];
|
SharedImage::PixelContainer levels(m_sharedImage->levels.size());
|
||||||
|
|
||||||
unsigned int width = m_sharedImage->width;
|
unsigned int width = m_sharedImage->width;
|
||||||
unsigned int height = m_sharedImage->height;
|
unsigned int height = m_sharedImage->height;
|
||||||
|
|
@ -103,37 +103,28 @@ bool NzImage::Convert(nzPixelFormat format)
|
||||||
// Les images 3D et cubemaps sont stockés de la même façon
|
// Les images 3D et cubemaps sont stockés de la même façon
|
||||||
unsigned int depth = (m_sharedImage->type == nzImageType_Cubemap) ? 6 : m_sharedImage->depth;
|
unsigned int depth = (m_sharedImage->type == nzImageType_Cubemap) ? 6 : m_sharedImage->depth;
|
||||||
|
|
||||||
for (unsigned int i = 0; i < m_sharedImage->levelCount; ++i)
|
for (unsigned int i = 0; i < levels.size(); ++i)
|
||||||
{
|
{
|
||||||
unsigned int pixelsPerFace = width * height;
|
unsigned int pixelsPerFace = width * height;
|
||||||
nzUInt8* face = new nzUInt8[pixelsPerFace*depth*NzPixelFormat::GetBytesPerPixel(format)];
|
levels[i].reset(new nzUInt8[pixelsPerFace * depth * NzPixelFormat::GetBytesPerPixel(newFormat)]);
|
||||||
nzUInt8* ptr = face;
|
|
||||||
nzUInt8* pixels = m_sharedImage->pixels[i];
|
nzUInt8* dst = levels[i].get();
|
||||||
|
nzUInt8* src = m_sharedImage->levels[i].get();
|
||||||
unsigned int srcStride = pixelsPerFace * NzPixelFormat::GetBytesPerPixel(m_sharedImage->format);
|
unsigned int srcStride = pixelsPerFace * NzPixelFormat::GetBytesPerPixel(m_sharedImage->format);
|
||||||
unsigned int dstStride = pixelsPerFace * NzPixelFormat::GetBytesPerPixel(format);
|
unsigned int dstStride = pixelsPerFace * NzPixelFormat::GetBytesPerPixel(newFormat);
|
||||||
|
|
||||||
for (unsigned int d = 0; d < depth; ++d)
|
for (unsigned int d = 0; d < depth; ++d)
|
||||||
{
|
{
|
||||||
if (!NzPixelFormat::Convert(m_sharedImage->format, format, pixels, &pixels[srcStride], ptr))
|
if (!NzPixelFormat::Convert(m_sharedImage->format, newFormat, src, &src[srcStride], dst))
|
||||||
{
|
{
|
||||||
NazaraError("Failed to convert image");
|
NazaraError("Failed to convert image");
|
||||||
|
|
||||||
// Nettoyage de la mémoire
|
|
||||||
delete[] face; // Permet une optimisation de boucle (GCC)
|
|
||||||
for (unsigned int j = 0; j < i; ++j)
|
|
||||||
delete[] levels[j];
|
|
||||||
|
|
||||||
delete[] levels;
|
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
pixels += srcStride;
|
src += srcStride;
|
||||||
ptr += dstStride;
|
dst += dstStride;
|
||||||
}
|
}
|
||||||
|
|
||||||
levels[i] = face;
|
|
||||||
|
|
||||||
if (width > 1)
|
if (width > 1)
|
||||||
width >>= 1;
|
width >>= 1;
|
||||||
|
|
||||||
|
|
@ -144,7 +135,7 @@ bool NzImage::Convert(nzPixelFormat format)
|
||||||
depth >>= 1;
|
depth >>= 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
SharedImage* newImage = new SharedImage(1, m_sharedImage->type, format, m_sharedImage->levelCount, levels, m_sharedImage->width, m_sharedImage->height, m_sharedImage->depth);
|
SharedImage* newImage = new SharedImage(1, m_sharedImage->type, newFormat, std::move(levels), m_sharedImage->width, m_sharedImage->height, m_sharedImage->depth);
|
||||||
|
|
||||||
ReleaseImage();
|
ReleaseImage();
|
||||||
m_sharedImage = newImage;
|
m_sharedImage = newImage;
|
||||||
|
|
@ -184,7 +175,7 @@ void NzImage::Copy(const NzImage& source, const NzBoxui& srcBox, const NzVector3
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
nzUInt8 bpp = NzPixelFormat::GetBytesPerPixel(m_sharedImage->format);
|
nzUInt8 bpp = NzPixelFormat::GetBytesPerPixel(m_sharedImage->format);
|
||||||
nzUInt8* dstPtr = GetPixelPtr(m_sharedImage->pixels[0], bpp, dstPos.x, dstPos.y, dstPos.z, m_sharedImage->width, m_sharedImage->height);
|
nzUInt8* dstPtr = GetPixelPtr(m_sharedImage->levels[0].get(), bpp, dstPos.x, dstPos.y, dstPos.z, m_sharedImage->width, m_sharedImage->height);
|
||||||
|
|
||||||
Copy(dstPtr, srcPtr, bpp, srcBox.width, srcBox.height, srcBox.depth, m_sharedImage->width, m_sharedImage->height, source.GetWidth(), source.GetHeight());
|
Copy(dstPtr, srcPtr, bpp, srcBox.width, srcBox.height, srcBox.depth, m_sharedImage->width, m_sharedImage->height, source.GetWidth(), source.GetHeight());
|
||||||
}
|
}
|
||||||
|
|
@ -269,7 +260,7 @@ bool NzImage::Create(nzImageType type, nzPixelFormat format, unsigned int width,
|
||||||
|
|
||||||
levelCount = std::min(levelCount, GetMaxLevel(type, width, height, depth));
|
levelCount = std::min(levelCount, GetMaxLevel(type, width, height, depth));
|
||||||
|
|
||||||
nzUInt8** levels = new nzUInt8*[levelCount];
|
SharedImage::PixelContainer levels(levelCount);
|
||||||
|
|
||||||
unsigned int w = width;
|
unsigned int w = width;
|
||||||
unsigned int h = height;
|
unsigned int h = height;
|
||||||
|
|
@ -280,7 +271,7 @@ bool NzImage::Create(nzImageType type, nzPixelFormat format, unsigned int width,
|
||||||
// Cette allocation est protégée car sa taille dépend directement de paramètres utilisateurs
|
// Cette allocation est protégée car sa taille dépend directement de paramètres utilisateurs
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
levels[i] = new nzUInt8[w * h * d * NzPixelFormat::GetBytesPerPixel(format)];
|
levels[i].reset(new nzUInt8[w * h * d * NzPixelFormat::GetBytesPerPixel(format)]);
|
||||||
|
|
||||||
if (w > 1)
|
if (w > 1)
|
||||||
w >>= 1;
|
w >>= 1;
|
||||||
|
|
@ -294,19 +285,11 @@ bool NzImage::Create(nzImageType type, nzPixelFormat format, unsigned int width,
|
||||||
catch (const std::exception& e)
|
catch (const std::exception& e)
|
||||||
{
|
{
|
||||||
NazaraError("Failed to allocate image's level " + NzString::Number(i) + " (" + NzString(e.what()) + ')');
|
NazaraError("Failed to allocate image's level " + NzString::Number(i) + " (" + NzString(e.what()) + ')');
|
||||||
|
|
||||||
// Nettoyage
|
|
||||||
delete[] levels[i]; // Permet une optimisation de boucle (GCC)
|
|
||||||
for (unsigned int j = 0; j < i; ++j)
|
|
||||||
delete[] levels[j];
|
|
||||||
|
|
||||||
delete[] levels;
|
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
m_sharedImage = new SharedImage(1, type, format, levelCount, levels, width, height, depth);
|
m_sharedImage = new SharedImage(1, type, format, std::move(levels), width, height, depth);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
@ -322,6 +305,8 @@ void NzImage::Destroy()
|
||||||
|
|
||||||
bool NzImage::Fill(const NzColor& color)
|
bool NzImage::Fill(const NzColor& color)
|
||||||
{
|
{
|
||||||
|
///FIXME: Pourquoi cette méthode alloue une nouvelle image plutôt que de remplir l'existante ?
|
||||||
|
|
||||||
#if NAZARA_UTILITY_SAFE
|
#if NAZARA_UTILITY_SAFE
|
||||||
if (m_sharedImage == &emptyImage)
|
if (m_sharedImage == &emptyImage)
|
||||||
{
|
{
|
||||||
|
|
@ -344,7 +329,7 @@ bool NzImage::Fill(const NzColor& color)
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
nzUInt8** levels = new nzUInt8*[m_sharedImage->levelCount];
|
SharedImage::PixelContainer levels(m_sharedImage->levels.size());
|
||||||
|
|
||||||
unsigned int width = m_sharedImage->width;
|
unsigned int width = m_sharedImage->width;
|
||||||
unsigned int height = m_sharedImage->height;
|
unsigned int height = m_sharedImage->height;
|
||||||
|
|
@ -352,11 +337,12 @@ bool NzImage::Fill(const NzColor& color)
|
||||||
// Les images 3D et cubemaps sont stockés de la même façon
|
// Les images 3D et cubemaps sont stockés de la même façon
|
||||||
unsigned int depth = (m_sharedImage->type == nzImageType_Cubemap) ? 6 : m_sharedImage->depth;
|
unsigned int depth = (m_sharedImage->type == nzImageType_Cubemap) ? 6 : m_sharedImage->depth;
|
||||||
|
|
||||||
for (unsigned int i = 0; i < m_sharedImage->levelCount; ++i)
|
for (unsigned int i = 0; i < levels.size(); ++i)
|
||||||
{
|
{
|
||||||
unsigned int size = width*height*depth*bpp;
|
unsigned int size = width*height*depth*bpp;
|
||||||
nzUInt8* face = new nzUInt8[size];
|
levels[i].reset(new nzUInt8[size]);
|
||||||
nzUInt8* ptr = face;
|
|
||||||
|
nzUInt8* ptr = levels[i].get();
|
||||||
nzUInt8* end = &ptr[size];
|
nzUInt8* end = &ptr[size];
|
||||||
|
|
||||||
while (ptr < end)
|
while (ptr < end)
|
||||||
|
|
@ -365,8 +351,6 @@ bool NzImage::Fill(const NzColor& color)
|
||||||
ptr += bpp;
|
ptr += bpp;
|
||||||
}
|
}
|
||||||
|
|
||||||
levels[i] = face;
|
|
||||||
|
|
||||||
if (width > 1U)
|
if (width > 1U)
|
||||||
width >>= 1;
|
width >>= 1;
|
||||||
|
|
||||||
|
|
@ -377,7 +361,7 @@ bool NzImage::Fill(const NzColor& color)
|
||||||
depth >>= 1;
|
depth >>= 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
SharedImage* newImage = new SharedImage(1, m_sharedImage->type, m_sharedImage->format, m_sharedImage->levelCount, levels, m_sharedImage->width, m_sharedImage->height, m_sharedImage->depth);
|
SharedImage* newImage = new SharedImage(1, m_sharedImage->type, m_sharedImage->format, std::move(levels), m_sharedImage->width, m_sharedImage->height, m_sharedImage->depth);
|
||||||
|
|
||||||
ReleaseImage();
|
ReleaseImage();
|
||||||
m_sharedImage = newImage;
|
m_sharedImage = newImage;
|
||||||
|
|
@ -418,7 +402,7 @@ bool NzImage::Fill(const NzColor& color, const NzBoxui& box)
|
||||||
}
|
}
|
||||||
|
|
||||||
///FIXME: L'algorithme a du mal avec un bpp non multiple de 2
|
///FIXME: L'algorithme a du mal avec un bpp non multiple de 2
|
||||||
nzUInt8* dstPixels = GetPixelPtr(m_sharedImage->pixels[0], bpp, box.x, box.y, box.z, m_sharedImage->width, m_sharedImage->height);
|
nzUInt8* dstPixels = GetPixelPtr(m_sharedImage->levels[0].get(), bpp, box.x, box.y, box.z, m_sharedImage->width, m_sharedImage->height);
|
||||||
unsigned int srcStride = box.width * bpp;
|
unsigned int srcStride = box.width * bpp;
|
||||||
unsigned int dstStride = m_sharedImage->width * bpp;
|
unsigned int dstStride = m_sharedImage->width * bpp;
|
||||||
unsigned int faceSize = dstStride * m_sharedImage->height;
|
unsigned int faceSize = dstStride * m_sharedImage->height;
|
||||||
|
|
@ -484,7 +468,7 @@ bool NzImage::Fill(const NzColor& color, const NzRectui& rect, unsigned int z)
|
||||||
}
|
}
|
||||||
|
|
||||||
///FIXME: L'algorithme a du mal avec un bpp non multiple de 2
|
///FIXME: L'algorithme a du mal avec un bpp non multiple de 2
|
||||||
nzUInt8* dstPixels = GetPixelPtr(m_sharedImage->pixels[0], bpp, rect.x, rect.y, z, m_sharedImage->width, m_sharedImage->height);
|
nzUInt8* dstPixels = GetPixelPtr(m_sharedImage->levels[0].get(), bpp, rect.x, rect.y, z, m_sharedImage->width, m_sharedImage->height);
|
||||||
unsigned int srcStride = rect.width * bpp;
|
unsigned int srcStride = rect.width * bpp;
|
||||||
unsigned int dstStride = m_sharedImage->width * bpp;
|
unsigned int dstStride = m_sharedImage->width * bpp;
|
||||||
for (unsigned int y = 0; y < rect.height; ++y)
|
for (unsigned int y = 0; y < rect.height; ++y)
|
||||||
|
|
@ -518,9 +502,10 @@ bool NzImage::FlipHorizontally()
|
||||||
unsigned int width = m_sharedImage->width;
|
unsigned int width = m_sharedImage->width;
|
||||||
unsigned int height = m_sharedImage->height;
|
unsigned int height = m_sharedImage->height;
|
||||||
unsigned int depth = (m_sharedImage->type == nzImageType_Cubemap) ? 6 : m_sharedImage->depth;
|
unsigned int depth = (m_sharedImage->type == nzImageType_Cubemap) ? 6 : m_sharedImage->depth;
|
||||||
for (unsigned int level = 0; level < m_sharedImage->levelCount; ++level)
|
for (unsigned int level = 0; level < m_sharedImage->levels.size(); ++level)
|
||||||
{
|
{
|
||||||
if (!NzPixelFormat::Flip(nzPixelFlipping_Horizontally, m_sharedImage->format, width, height, depth, m_sharedImage->pixels[level], m_sharedImage->pixels[level]))
|
nzUInt8* ptr = m_sharedImage->levels[level].get();
|
||||||
|
if (!NzPixelFormat::Flip(nzPixelFlipping_Horizontally, m_sharedImage->format, width, height, depth, ptr, ptr))
|
||||||
{
|
{
|
||||||
NazaraError("Failed to flip image");
|
NazaraError("Failed to flip image");
|
||||||
return false;
|
return false;
|
||||||
|
|
@ -560,9 +545,10 @@ bool NzImage::FlipVertically()
|
||||||
unsigned int width = m_sharedImage->width;
|
unsigned int width = m_sharedImage->width;
|
||||||
unsigned int height = m_sharedImage->height;
|
unsigned int height = m_sharedImage->height;
|
||||||
unsigned int depth = (m_sharedImage->type == nzImageType_Cubemap) ? 6 : m_sharedImage->depth;
|
unsigned int depth = (m_sharedImage->type == nzImageType_Cubemap) ? 6 : m_sharedImage->depth;
|
||||||
for (unsigned int level = 0; level < m_sharedImage->levelCount; ++level)
|
for (unsigned int level = 0; level < m_sharedImage->levels.size(); ++level)
|
||||||
{
|
{
|
||||||
if (!NzPixelFormat::Flip(nzPixelFlipping_Vertically, m_sharedImage->format, width, height, depth, m_sharedImage->pixels[level], m_sharedImage->pixels[level]))
|
nzUInt8* ptr = m_sharedImage->levels[level].get();
|
||||||
|
if (!NzPixelFormat::Flip(nzPixelFlipping_Vertically, m_sharedImage->format, width, height, depth, ptr, ptr))
|
||||||
{
|
{
|
||||||
NazaraError("Failed to flip image");
|
NazaraError("Failed to flip image");
|
||||||
return false;
|
return false;
|
||||||
|
|
@ -590,9 +576,9 @@ const nzUInt8* NzImage::GetConstPixels(unsigned int x, unsigned int y, unsigned
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (level >= m_sharedImage->levelCount)
|
if (level >= m_sharedImage->levels.size())
|
||||||
{
|
{
|
||||||
NazaraError("Level out of bounds (" + NzString::Number(level) + " >= " + NzString::Number(m_sharedImage->levelCount) + ')');
|
NazaraError("Level out of bounds (" + NzString::Number(level) + " >= " + NzString::Number(m_sharedImage->levels.size()) + ')');
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
@ -622,15 +608,15 @@ const nzUInt8* NzImage::GetConstPixels(unsigned int x, unsigned int y, unsigned
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
return GetPixelPtr(m_sharedImage->pixels[level], NzPixelFormat::GetBytesPerPixel(m_sharedImage->format), x, y, z, width, height);
|
return GetPixelPtr(m_sharedImage->levels[level].get(), NzPixelFormat::GetBytesPerPixel(m_sharedImage->format), x, y, z, width, height);
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned int NzImage::GetDepth(nzUInt8 level) const
|
unsigned int NzImage::GetDepth(nzUInt8 level) const
|
||||||
{
|
{
|
||||||
#if NAZARA_UTILITY_SAFE
|
#if NAZARA_UTILITY_SAFE
|
||||||
if (level >= m_sharedImage->levelCount)
|
if (level >= m_sharedImage->levels.size())
|
||||||
{
|
{
|
||||||
NazaraError("Level out of bounds (" + NzString::Number(level) + " >= " + NzString::Number(m_sharedImage->levelCount) + ')');
|
NazaraError("Level out of bounds (" + NzString::Number(level) + " >= " + NzString::Number(m_sharedImage->levels.size()) + ')');
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
@ -646,9 +632,9 @@ nzPixelFormat NzImage::GetFormat() const
|
||||||
unsigned int NzImage::GetHeight(nzUInt8 level) const
|
unsigned int NzImage::GetHeight(nzUInt8 level) const
|
||||||
{
|
{
|
||||||
#if NAZARA_UTILITY_SAFE
|
#if NAZARA_UTILITY_SAFE
|
||||||
if (level >= m_sharedImage->levelCount)
|
if (level >= m_sharedImage->levels.size())
|
||||||
{
|
{
|
||||||
NazaraError("Level out of bounds (" + NzString::Number(level) + " >= " + NzString::Number(m_sharedImage->levelCount) + ')');
|
NazaraError("Level out of bounds (" + NzString::Number(level) + " >= " + NzString::Number(m_sharedImage->levels.size()) + ')');
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
@ -658,7 +644,7 @@ unsigned int NzImage::GetHeight(nzUInt8 level) const
|
||||||
|
|
||||||
nzUInt8 NzImage::GetLevelCount() const
|
nzUInt8 NzImage::GetLevelCount() const
|
||||||
{
|
{
|
||||||
return m_sharedImage->levelCount;
|
return m_sharedImage->levels.size();
|
||||||
}
|
}
|
||||||
|
|
||||||
nzUInt8 NzImage::GetMaxLevel() const
|
nzUInt8 NzImage::GetMaxLevel() const
|
||||||
|
|
@ -673,7 +659,7 @@ unsigned int NzImage::GetMemoryUsage() const
|
||||||
unsigned int depth = m_sharedImage->depth;
|
unsigned int depth = m_sharedImage->depth;
|
||||||
|
|
||||||
unsigned int size = 0;
|
unsigned int size = 0;
|
||||||
for (unsigned int i = 0; i < m_sharedImage->levelCount; ++i)
|
for (unsigned int i = 0; i < m_sharedImage->levels.size(); ++i)
|
||||||
{
|
{
|
||||||
size += width * height * depth;
|
size += width * height * depth;
|
||||||
|
|
||||||
|
|
@ -695,14 +681,6 @@ unsigned int NzImage::GetMemoryUsage() const
|
||||||
|
|
||||||
unsigned int NzImage::GetMemoryUsage(nzUInt8 level) const
|
unsigned int NzImage::GetMemoryUsage(nzUInt8 level) const
|
||||||
{
|
{
|
||||||
#if NAZARA_UTILITY_SAFE
|
|
||||||
if (level >= m_sharedImage->levelCount)
|
|
||||||
{
|
|
||||||
NazaraError("Level out of bounds (" + NzString::Number(level) + " >= " + NzString::Number(m_sharedImage->levelCount) + ')');
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
return (GetLevelSize(m_sharedImage->width, level)) *
|
return (GetLevelSize(m_sharedImage->width, level)) *
|
||||||
(GetLevelSize(m_sharedImage->height, level)) *
|
(GetLevelSize(m_sharedImage->height, level)) *
|
||||||
((m_sharedImage->type == nzImageType_Cubemap) ? 6 : GetLevelSize(m_sharedImage->depth, level)) *
|
((m_sharedImage->type == nzImageType_Cubemap) ? 6 : GetLevelSize(m_sharedImage->depth, level)) *
|
||||||
|
|
@ -744,7 +722,7 @@ NzColor NzImage::GetPixelColor(unsigned int x, unsigned int y, unsigned int z) c
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
const nzUInt8* pixel = GetPixelPtr(m_sharedImage->pixels[0], NzPixelFormat::GetBytesPerPixel(m_sharedImage->format), x, y, z, m_sharedImage->width, m_sharedImage->height);
|
const nzUInt8* pixel = GetPixelPtr(m_sharedImage->levels[0].get(), NzPixelFormat::GetBytesPerPixel(m_sharedImage->format), x, y, z, m_sharedImage->width, m_sharedImage->height);
|
||||||
|
|
||||||
NzColor color;
|
NzColor color;
|
||||||
if (!NzPixelFormat::Convert(m_sharedImage->format, nzPixelFormat_RGBA8, pixel, &color.r))
|
if (!NzPixelFormat::Convert(m_sharedImage->format, nzPixelFormat_RGBA8, pixel, &color.r))
|
||||||
|
|
@ -762,9 +740,9 @@ nzUInt8* NzImage::GetPixels(unsigned int x, unsigned int y, unsigned int z, nzUI
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (level >= m_sharedImage->levelCount)
|
if (level >= m_sharedImage->levels.size())
|
||||||
{
|
{
|
||||||
NazaraError("Level out of bounds (" + NzString::Number(level) + " >= " + NzString::Number(m_sharedImage->levelCount) + ')');
|
NazaraError("Level out of bounds (" + NzString::Number(level) + " >= " + NzString::Number(m_sharedImage->levels.size()) + ')');
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
@ -793,24 +771,24 @@ nzUInt8* NzImage::GetPixels(unsigned int x, unsigned int y, unsigned int z, nzUI
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (level >= m_sharedImage->levelCount)
|
if (level >= m_sharedImage->levels.size())
|
||||||
{
|
{
|
||||||
NazaraError("Level out of bounds (" + NzString::Number(level) + " >= " + NzString::Number(m_sharedImage->levelCount) + ')');
|
NazaraError("Level out of bounds (" + NzString::Number(level) + " >= " + NzString::Number(m_sharedImage->levels.size()) + ')');
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
EnsureOwnership();
|
EnsureOwnership();
|
||||||
|
|
||||||
return GetPixelPtr(m_sharedImage->pixels[level], NzPixelFormat::GetBytesPerPixel(m_sharedImage->format), x, y, z, width, height);
|
return GetPixelPtr(m_sharedImage->levels[level].get(), NzPixelFormat::GetBytesPerPixel(m_sharedImage->format), x, y, z, width, height);
|
||||||
}
|
}
|
||||||
|
|
||||||
NzVector3ui NzImage::GetSize(nzUInt8 level) const
|
NzVector3ui NzImage::GetSize(nzUInt8 level) const
|
||||||
{
|
{
|
||||||
#if NAZARA_UTILITY_SAFE
|
#if NAZARA_UTILITY_SAFE
|
||||||
if (level >= m_sharedImage->levelCount)
|
if (level >= m_sharedImage->levels.size())
|
||||||
{
|
{
|
||||||
NazaraError("Level out of bounds (" + NzString::Number(level) + " >= " + NzString::Number(m_sharedImage->levelCount) + ')');
|
NazaraError("Level out of bounds (" + NzString::Number(level) + " >= " + NzString::Number(m_sharedImage->levels.size()) + ')');
|
||||||
return NzVector3ui::Zero();
|
return NzVector3ui::Zero();
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
@ -826,9 +804,9 @@ nzImageType NzImage::GetType() const
|
||||||
unsigned int NzImage::GetWidth(nzUInt8 level) const
|
unsigned int NzImage::GetWidth(nzUInt8 level) const
|
||||||
{
|
{
|
||||||
#if NAZARA_UTILITY_SAFE
|
#if NAZARA_UTILITY_SAFE
|
||||||
if (level >= m_sharedImage->levelCount)
|
if (level >= m_sharedImage->levels.size())
|
||||||
{
|
{
|
||||||
NazaraError("Level out of bounds (" + NzString::Number(level) + " >= " + NzString::Number(m_sharedImage->levelCount) + ')');
|
NazaraError("Level out of bounds (" + NzString::Number(level) + " >= " + NzString::Number(m_sharedImage->levels.size()) + ')');
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
@ -1104,29 +1082,17 @@ void NzImage::SetLevelCount(nzUInt8 levelCount)
|
||||||
|
|
||||||
levelCount = std::min(levelCount, GetMaxLevel());
|
levelCount = std::min(levelCount, GetMaxLevel());
|
||||||
|
|
||||||
if (m_sharedImage->levelCount == levelCount)
|
if (m_sharedImage->levels.size() == levelCount)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
EnsureOwnership();
|
EnsureOwnership();
|
||||||
|
|
||||||
nzUInt8 oldLevelCount = m_sharedImage->levelCount;
|
nzUInt8 oldLevelCount = m_sharedImage->levels.size();
|
||||||
nzUInt8 maxLevelCount = std::max(levelCount, oldLevelCount);
|
nzUInt8 maxLevelCount = std::max(levelCount, oldLevelCount);
|
||||||
m_sharedImage->levelCount = levelCount; // Pour faire fonctionner GetMemoryUsage
|
|
||||||
|
|
||||||
nzUInt8** pixels = new nzUInt8*[levelCount];
|
m_sharedImage->levels.resize(levelCount);
|
||||||
for (unsigned int i = 0; i < maxLevelCount; ++i)
|
for (nzUInt8 i = oldLevelCount; i < maxLevelCount; ++i)
|
||||||
{
|
m_sharedImage->levels[i].reset(new nzUInt8[GetMemoryUsage(i)]);
|
||||||
if (i < oldLevelCount)
|
|
||||||
pixels[i] = m_sharedImage->pixels[i];
|
|
||||||
else if (i < levelCount)
|
|
||||||
pixels[i] = new nzUInt8[GetMemoryUsage(i)];
|
|
||||||
else
|
|
||||||
delete[] m_sharedImage->pixels[i];
|
|
||||||
}
|
|
||||||
|
|
||||||
delete[] m_sharedImage->pixels;
|
|
||||||
|
|
||||||
m_sharedImage->pixels = pixels;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool NzImage::SetPixelColor(const NzColor& color, unsigned int x, unsigned int y, unsigned int z)
|
bool NzImage::SetPixelColor(const NzColor& color, unsigned int x, unsigned int y, unsigned int z)
|
||||||
|
|
@ -1164,7 +1130,7 @@ bool NzImage::SetPixelColor(const NzColor& color, unsigned int x, unsigned int y
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
nzUInt8* pixel = GetPixelPtr(m_sharedImage->pixels[0], NzPixelFormat::GetBytesPerPixel(m_sharedImage->format), x, y, z, m_sharedImage->width, m_sharedImage->height);
|
nzUInt8* pixel = GetPixelPtr(m_sharedImage->levels[0].get(), NzPixelFormat::GetBytesPerPixel(m_sharedImage->format), x, y, z, m_sharedImage->width, m_sharedImage->height);
|
||||||
|
|
||||||
if (!NzPixelFormat::Convert(nzPixelFormat_RGBA8, m_sharedImage->format, &color.r, pixel))
|
if (!NzPixelFormat::Convert(nzPixelFormat_RGBA8, m_sharedImage->format, &color.r, pixel))
|
||||||
{
|
{
|
||||||
|
|
@ -1190,16 +1156,16 @@ bool NzImage::Update(const nzUInt8* pixels, unsigned int srcWidth, unsigned int
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (level >= m_sharedImage->levelCount)
|
if (level >= m_sharedImage->levels.size())
|
||||||
{
|
{
|
||||||
NazaraError("Level out of bounds (" + NzString::Number(level) + " >= " + NzString::Number(m_sharedImage->levelCount) + ')');
|
NazaraError("Level out of bounds (" + NzString::Number(level) + " >= " + NzString::Number(m_sharedImage->levels.size()) + ')');
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
EnsureOwnership();
|
EnsureOwnership();
|
||||||
|
|
||||||
Copy(m_sharedImage->pixels[level], pixels, NzPixelFormat::GetBytesPerPixel(m_sharedImage->format),
|
Copy(m_sharedImage->levels[level].get(), pixels, NzPixelFormat::GetBytesPerPixel(m_sharedImage->format),
|
||||||
GetLevelSize(m_sharedImage->width, level),
|
GetLevelSize(m_sharedImage->width, level),
|
||||||
GetLevelSize(m_sharedImage->height, level),
|
GetLevelSize(m_sharedImage->height, level),
|
||||||
GetLevelSize(m_sharedImage->depth, level),
|
GetLevelSize(m_sharedImage->depth, level),
|
||||||
|
|
@ -1224,9 +1190,9 @@ bool NzImage::Update(const nzUInt8* pixels, const NzBoxui& box, unsigned int src
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (level >= m_sharedImage->levelCount)
|
if (level >= m_sharedImage->levels.size())
|
||||||
{
|
{
|
||||||
NazaraError("Level out of bounds (" + NzString::Number(level) + " >= " + NzString::Number(m_sharedImage->levelCount) + ')');
|
NazaraError("Level out of bounds (" + NzString::Number(level) + " >= " + NzString::Number(m_sharedImage->levels.size()) + ')');
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
@ -1253,7 +1219,7 @@ bool NzImage::Update(const nzUInt8* pixels, const NzBoxui& box, unsigned int src
|
||||||
EnsureOwnership();
|
EnsureOwnership();
|
||||||
|
|
||||||
nzUInt8 bpp = NzPixelFormat::GetBytesPerPixel(m_sharedImage->format);
|
nzUInt8 bpp = NzPixelFormat::GetBytesPerPixel(m_sharedImage->format);
|
||||||
nzUInt8* dstPixels = GetPixelPtr(m_sharedImage->pixels[level], bpp, box.x, box.y, box.z, width, height);
|
nzUInt8* dstPixels = GetPixelPtr(m_sharedImage->levels[level].get(), bpp, box.x, box.y, box.z, width, height);
|
||||||
|
|
||||||
Copy(dstPixels, pixels, bpp,
|
Copy(dstPixels, pixels, bpp,
|
||||||
box.width, box.height, box.depth,
|
box.width, box.height, box.depth,
|
||||||
|
|
@ -1357,17 +1323,16 @@ void NzImage::EnsureOwnership()
|
||||||
|
|
||||||
if (m_sharedImage->refCount > 1)
|
if (m_sharedImage->refCount > 1)
|
||||||
{
|
{
|
||||||
m_sharedImage->refCount--;
|
SharedImage::PixelContainer levels(m_sharedImage->levels.size());
|
||||||
|
for (unsigned int i = 0; i < levels.size(); ++i)
|
||||||
nzUInt8** pixels = new nzUInt8*[m_sharedImage->levelCount];
|
|
||||||
for (unsigned int i = 0; i < m_sharedImage->levelCount; ++i)
|
|
||||||
{
|
{
|
||||||
unsigned int size = GetMemoryUsage(i);
|
unsigned int size = GetMemoryUsage(i);
|
||||||
pixels[i] = new nzUInt8[size];
|
levels[i].reset(new nzUInt8[size]);
|
||||||
std::memcpy(pixels[i], m_sharedImage->pixels[i], size);
|
std::memcpy(levels[i].get(), m_sharedImage->levels[i].get(), size);
|
||||||
}
|
}
|
||||||
|
|
||||||
m_sharedImage = new SharedImage(1, m_sharedImage->type, m_sharedImage->format, m_sharedImage->levelCount, pixels, m_sharedImage->width, m_sharedImage->height, m_sharedImage->depth);
|
m_sharedImage->refCount--;
|
||||||
|
m_sharedImage = new SharedImage(1, m_sharedImage->type, m_sharedImage->format, std::move(levels), m_sharedImage->width, m_sharedImage->height, m_sharedImage->depth);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1377,13 +1342,7 @@ void NzImage::ReleaseImage()
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (--m_sharedImage->refCount == 0)
|
if (--m_sharedImage->refCount == 0)
|
||||||
{
|
|
||||||
for (unsigned int i = 0; i < m_sharedImage->levelCount; ++i)
|
|
||||||
delete[] m_sharedImage->pixels[i];
|
|
||||||
|
|
||||||
delete[] m_sharedImage->pixels;
|
|
||||||
delete m_sharedImage;
|
delete m_sharedImage;
|
||||||
}
|
|
||||||
|
|
||||||
m_sharedImage = &emptyImage;
|
m_sharedImage = &emptyImage;
|
||||||
}
|
}
|
||||||
|
|
@ -1411,7 +1370,7 @@ void NzImage::Uninitialize()
|
||||||
NzImageLibrary::Uninitialize();
|
NzImageLibrary::Uninitialize();
|
||||||
}
|
}
|
||||||
|
|
||||||
NzImage::SharedImage NzImage::emptyImage(0, nzImageType_2D, nzPixelFormat_Undefined, 1, nullptr, 0, 0, 0);
|
NzImage::SharedImage NzImage::emptyImage(0, nzImageType_2D, nzPixelFormat_Undefined, NzImage::SharedImage::PixelContainer(), 0, 0, 0);
|
||||||
NzImageLibrary::LibraryMap NzImage::s_library;
|
NzImageLibrary::LibraryMap NzImage::s_library;
|
||||||
NzImageLoader::LoaderList NzImage::s_loaders;
|
NzImageLoader::LoaderList NzImage::s_loaders;
|
||||||
NzImageManager::ManagerMap NzImage::s_managerMap;
|
NzImageManager::ManagerMap NzImage::s_managerMap;
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue