NzImage now handles mipmaps

Added NzRenderer::SetClearColor(const Color&)
Added describe comment for pixel formats
Fixed NzPixelFormat conversion for RGBA4 and RGB5A1 types
Fixed NzRenderer::Clear prototype
Renamed NzLock to NzLockGuard
ResourceLoader's loaders are now tested from newest to oldest
This commit is contained in:
Lynix 2012-05-30 18:10:17 +02:00
parent f39e2f7d36
commit b220e00c88
17 changed files with 591 additions and 221 deletions

View File

@ -40,10 +40,10 @@ class NzColor
static NzColor FromXYZ(float x, float y, float z);
static void ToCMY(const NzColor& color, float* cyan, float* magenta, float* yellow);
static void ToCMYK(const NzColor& color, float* cyan, float* magenta, float* yellow, float* black);
static void ToXYZ(const NzColor& color, NzVector3f* vec);
static void ToXYZ(const NzColor& color, float* x, float* y, float* z);
static void ToHSL(const NzColor& color, nzUInt8* hue, nzUInt8* saturation, nzUInt8* lightness);
static void ToHSV(const NzColor& color, nzUInt8* hue, nzUInt8* saturation, float* value);
static void ToXYZ(const NzColor& color, NzVector3f* vec);
static void ToXYZ(const NzColor& color, float* x, float* y, float* z);
nzUInt8 r, g, b, a;

View File

@ -4,21 +4,21 @@
#pragma once
#ifndef NAZARA_LOCK_HPP
#define NAZARA_LOCK_HPP
#ifndef NAZARA_LOCKGUARD_HPP
#define NAZARA_LOCKGUARD_HPP
#include <Nazara/Prerequesites.hpp>
class NzMutex;
class NAZARA_API NzLock
class NAZARA_API NzLockGuard
{
public:
NzLock(NzMutex& mutex);
~NzLock();
NzLockGuard(NzMutex& mutex);
~NzLockGuard();
private:
NzMutex& m_mutex;
};
#endif // NAZARA_LOCK_HPP
#endif // NAZARA_LOCKGUARD_HPP

View File

@ -24,10 +24,10 @@
(NAZARA_THREADSAFETY_STRING && defined(NAZARA_CLASS_STRING)) || \
(NAZARA_THREADSAFETY_STRINGSTREAM && defined(NAZARA_CLASS_STRINGSTREAM)))
#include <Nazara/Core/Lock.hpp>
#include <Nazara/Core/LockGuard.hpp>
#include <Nazara/Core/Mutex.hpp>
#define NazaraLock(mutex) NzLock lock_mutex(mutex);
#define NazaraLock(mutex) NzLockGuard lock_mutex(mutex);
#define NazaraMutex(name) NzMutex name;
#define NazaraMutexAttrib(name, attribute) attribute NzMutex name;
#define NazaraMutexLock(mutex) mutex.Lock();

View File

@ -44,6 +44,7 @@ enum nzRendererClear
nzRendererClear_Stencil = 0x04
};
class NzColor;
class NzIndexBuffer;
class NzRenderTarget;
class NzShader;
@ -57,7 +58,7 @@ class NAZARA_API NzRenderer
NzRenderer();
~NzRenderer();
void Clear(nzRendererClear flags);
void Clear(unsigned long flags = nzRendererClear_Color | nzRendererClear_Depth);
void DrawIndexedPrimitives(nzPrimitiveType primitive, unsigned int firstIndex, unsigned int indexCount);
void DrawPrimitives(nzPrimitiveType primitive, unsigned int firstVertex, unsigned int vertexCount);
@ -69,6 +70,7 @@ class NAZARA_API NzRenderer
bool HasCapability(nzRendererCap capability) const;
bool Initialize();
void SetClearColor(const NzColor& color);
void SetClearColor(nzUInt8 r, nzUInt8 g, nzUInt8 b, nzUInt8 a = 255);
void SetClearDepth(double depth);
void SetClearStencil(unsigned int value);

View File

@ -50,9 +50,7 @@ struct NzImageParams
}
};
///TODO: Animations ?
///TODO: Filtres
///TODO: Mipmaps
class NAZARA_API NzImage : public NzResource, public NzResourceLoader<NzImage, NzImageParams>
{
@ -70,20 +68,23 @@ class NAZARA_API NzImage : public NzResource, public NzResourceLoader<NzImage, N
bool Copy(const NzImage& source, const NzRectui& srcRect, const NzVector2ui& dstPos);
bool CopyToFace(nzCubemapFace face, const NzImage& source, const NzRectui& srcRect, const NzVector2ui& dstPos);
bool Create(nzImageType type, nzPixelFormat format, unsigned int width, unsigned int height = 1, unsigned int depth = 1);
bool Create(nzImageType type, nzPixelFormat format, unsigned int width, unsigned int height, unsigned int depth = 1, nzUInt8 levelCount = 1);
void Destroy();
nzUInt8 GetBPP() const;
const nzUInt8* GetConstPixels() const;
unsigned int GetDepth() const;
const nzUInt8* GetConstPixels(nzUInt8 level = 0) const;
unsigned int GetDepth(nzUInt8 level = 0) const;
nzPixelFormat GetFormat() const;
unsigned int GetHeight() const;
unsigned int GetHeight(nzUInt8 level = 0) const;
nzUInt8 GetLevelCount() const;
nzUInt8 GetMaxLevel() const;
NzColor GetPixel(unsigned int x, unsigned int y = 0, unsigned int z = 0) const;
NzColor GetPixelFace(nzCubemapFace face, unsigned int x, unsigned int y) const;
nzUInt8* GetPixels();
nzUInt8* GetPixels(nzUInt8 level = 0);
unsigned int GetSize() const;
unsigned int GetSize(nzUInt8 level) const;
nzImageType GetType() const;
unsigned int GetWidth() const;
unsigned int GetWidth(nzUInt8 level = 0) const;
bool IsCompressed() const;
bool IsCubemap() const;
@ -93,18 +94,20 @@ class NAZARA_API NzImage : public NzResource, public NzResourceLoader<NzImage, N
bool LoadFromMemory(const void* data, std::size_t size, const NzImageParams& params = NzImageParams());
bool LoadFromStream(NzInputStream& stream, const NzImageParams& params = NzImageParams());
bool SetLevelCount(nzUInt8 levelCount);
bool SetPixel(const NzColor& color, unsigned int x, unsigned int y = 0, unsigned int z = 0);
bool SetPixelFace(const NzColor& color, nzCubemapFace face, unsigned int x, unsigned int y);
bool SetPixelFace(nzCubemapFace face, const NzColor& color, unsigned int x, unsigned int y);
bool Update(const nzUInt8* pixels);
bool Update(const nzUInt8* pixels, const NzRectui& rect, unsigned int z = 0);
//bool Update(const nzUInt8* pixels, const NzCubeui& cube);
bool UpdateFace(nzCubemapFace face, const nzUInt8* pixels);
bool UpdateFace(nzCubemapFace face, const nzUInt8* pixels, const NzRectui& rect);
bool Update(const nzUInt8* pixels, nzUInt8 level = 0);
bool Update(const nzUInt8* pixels, const NzRectui& rect, unsigned int z = 0, nzUInt8 level = 0);
//bool Update(const nzUInt8* pixels, const NzCubeui& cube, nzUInt8 level = 0);
bool UpdateFace(nzCubemapFace face, const nzUInt8* pixels, nzUInt8 level = 0);
bool UpdateFace(nzCubemapFace face, const nzUInt8* pixels, const NzRectui& rect, nzUInt8 level = 0);
NzImage& operator=(const NzImage& image);
NzImage& operator=(NzImage&& image);
static nzUInt8 GetMaxLevel(unsigned int width, unsigned int height, unsigned int depth = 1);
static void RegisterFileLoader(const NzString& extensions, LoadFileFunction loadFile);
static void RegisterMemoryLoader(IsMemoryLoadingSupportedFunction isLoadingSupported, LoadMemoryFunction loadMemory);
static void RegisterStreamLoader(IsStreamLoadingSupportedFunction isLoadingSupported, LoadStreamFunction loadStream);
@ -119,9 +122,10 @@ class NAZARA_API NzImage : public NzResource, public NzResourceLoader<NzImage, N
{
}
SharedImage(unsigned short RefCount, nzImageType Type, nzPixelFormat Format, nzUInt8* Pixels, unsigned int Width, unsigned int Height = 1, unsigned int Depth = 1) :
SharedImage(unsigned short RefCount, nzImageType Type, nzPixelFormat Format, nzInt8 LevelCount = 1, nzUInt8** Pixels = nullptr, unsigned int Width = 1, unsigned int Height = 1, unsigned int Depth = 1) :
type(Type),
format(Format),
levelCount(LevelCount),
pixels(Pixels),
depth(Depth),
height(Height),
@ -132,7 +136,8 @@ class NAZARA_API NzImage : public NzResource, public NzResourceLoader<NzImage, N
nzImageType type;
nzPixelFormat format;
nzUInt8* pixels;
nzUInt8 levelCount;
nzUInt8** pixels;
unsigned int depth;
unsigned int height;
unsigned int width;

View File

@ -14,29 +14,27 @@ enum nzPixelFormat
{
nzPixelFormat_Undefined,
nzPixelFormat_BGR8,
nzPixelFormat_BGRA8,
nzPixelFormat_BGR8, // 3*nzUInt8
nzPixelFormat_BGRA8, // 4*nzUInt8
nzPixelFormat_DXT1,
nzPixelFormat_DXT3,
nzPixelFormat_DXT5,
nzPixelFormat_L8,
nzPixelFormat_LA8,
nzPixelFormat_L8, // 1*nzUInt8
nzPixelFormat_LA8, // 2*nzUInt8
/*
nzPixelFormat_RGB16F,
nzPixelFormat_RGB16I,
nzPixelFormat_RGB16I, // 4*nzUInt16
nzPixelFormat_RGB32F,
nzPixelFormat_RGB32I,
*/
nzPixelFormat_RGB32I, // 4*nzUInt32
nzPixelFormat_RGBA16F,
nzPixelFormat_RGBA16I,
/*
nzPixelFormat_RGBA16I, // 4*nzUInt16
nzPixelFormat_RGBA32F,
nzPixelFormat_RGBA32I,
nzPixelFormat_RGBA32I, // 4*nzUInt32
*/
nzPixelFormat_RGBA4,
nzPixelFormat_RGB5A1,
nzPixelFormat_RGB8,
nzPixelFormat_RGBA8,
nzPixelFormat_RGBA4, // 1*nzUInt16
nzPixelFormat_RGB5A1, // 1*nzUInt16
nzPixelFormat_RGB8, // 3*nzUInt8
nzPixelFormat_RGBA8, // 4*nzUInt8
nzPixelFormat_Count
};
@ -56,6 +54,7 @@ class NzPixelFormat
static nzUInt8 GetBPP(nzPixelFormat format);
static bool IsCompressed(nzPixelFormat format);
static bool IsConversionSupported(nzPixelFormat srcFormat, nzPixelFormat dstFormat);
static bool IsValid(nzPixelFormat format);
static void SetConvertFunction(nzPixelFormat srcFormat, nzPixelFormat dstFormat, ConvertFunction);

View File

@ -31,11 +31,15 @@ inline bool NzPixelFormat::Convert(nzPixelFormat srcFormat, nzPixelFormat dstFor
ConvertFunction func = s_convertFunctions[srcFormat][dstFormat];
if (!func)
{
NazaraError("Pixel format conversion from " + ToString(srcFormat) + " to " + ToString(dstFormat) + " not supported");
NazaraError("Pixel format conversion from " + ToString(srcFormat) + " to " + ToString(dstFormat) + " is not supported");
return false;
}
func(static_cast<const nzUInt8*>(src), static_cast<const nzUInt8*>(src) + GetBPP(srcFormat), static_cast<nzUInt8*>(dst));
if (!func(static_cast<const nzUInt8*>(src), static_cast<const nzUInt8*>(src) + GetBPP(srcFormat), static_cast<nzUInt8*>(dst)))
{
NazaraError("Pixel format conversion from " + ToString(srcFormat) + " to " + ToString(dstFormat) + " failed");
return false;
}
return true;
}
@ -51,11 +55,15 @@ inline bool NzPixelFormat::Convert(nzPixelFormat srcFormat, nzPixelFormat dstFor
ConvertFunction func = s_convertFunctions[srcFormat][dstFormat];
if (!func)
{
NazaraError("Pixel format conversion from " + ToString(srcFormat) + " to " + ToString(dstFormat) + " not supported");
NazaraError("Pixel format conversion from " + ToString(srcFormat) + " to " + ToString(dstFormat) + " is not supported");
return false;
}
func(static_cast<const nzUInt8*>(start), static_cast<const nzUInt8*>(end), static_cast<nzUInt8*>(dst));
if (!func(static_cast<const nzUInt8*>(start), static_cast<const nzUInt8*>(end), static_cast<nzUInt8*>(dst)))
{
NazaraError("Pixel format conversion from " + ToString(srcFormat) + " to " + ToString(dstFormat) + " failed");
return false;
}
return true;
}
@ -100,13 +108,13 @@ inline nzUInt8 NzPixelFormat::GetBPP(nzPixelFormat format)
case nzPixelFormat_RGB32I:
return 12;
*/
case nzPixelFormat_RGBA16F:
return 8;
case nzPixelFormat_RGBA16I:
return 8;
/*
case nzPixelFormat_RGBA32F:
return 16;
@ -145,6 +153,14 @@ inline bool NzPixelFormat::IsCompressed(nzPixelFormat format)
}
}
inline bool NzPixelFormat::IsConversionSupported(nzPixelFormat srcFormat, nzPixelFormat dstFormat)
{
if (srcFormat == dstFormat)
return true;
return s_convertFunctions[srcFormat][dstFormat] != nullptr;
}
inline bool NzPixelFormat::IsValid(nzPixelFormat format)
{
switch (format)
@ -199,13 +215,13 @@ inline NzString NzPixelFormat::ToString(nzPixelFormat format)
case nzPixelFormat_RGB32I:
return "RGB32I";
*/
case nzPixelFormat_RGBA16F:
return "RGBA16F";
case nzPixelFormat_RGBA16I:
return "RGBA16I";
/*
case nzPixelFormat_RGBA32F:
return "RGBA32F";

View File

@ -35,14 +35,20 @@ bool NzResourceLoader<Type, Parameters>::LoadResourceFromFile(Type* resource, co
return false;
}
for (auto it = range.first; it != range.second; ++it)
// range.second est un itérateur vers l'élément après le dernier élémént du range
auto it = range.second;
do
{
it--;
// Chargement de la ressource
if (it->second(resource, filePath, parameters))
return true;
NazaraWarning("Loader failed");
}
while (it != range.first);
NazaraError("Failed to load file: all loaders failed");
@ -66,7 +72,7 @@ bool NzResourceLoader<Type, Parameters>::LoadResourceFromMemory(Type* resource,
}
#endif
for (auto loader = s_memoryLoaders.begin(); loader != s_memoryLoaders.end(); ++loader)
for (auto loader = s_memoryLoaders.rbegin(); loader != s_memoryLoaders.rend(); ++loader)
{
// Le loader supporte-t-il les données ?
if (!loader->first(data, size, parameters))
@ -101,7 +107,7 @@ bool NzResourceLoader<Type, Parameters>::LoadResourceFromStream(Type* resource,
#endif
nzUInt64 streamPos = stream.GetCursorPos();
for (auto loader = s_streamLoaders.begin(); loader != s_streamLoaders.end(); ++loader)
for (auto loader = s_streamLoaders.rbegin(); loader != s_streamLoaders.rend(); ++loader)
{
stream.SetCursorPos(streamPos);
@ -164,7 +170,6 @@ void NzResourceLoader<Type, Parameters>::UnregisterResourceFileLoader(const NzSt
}
}
}
//s_fileLoaders.erase(std::make_pair(ext, loadFile));
}
template<typename Type, typename Parameters>

View File

@ -2,17 +2,17 @@
// This file is part of the "Nazara Engine".
// For conditions of distribution and use, see copyright notice in Config.hpp
#include <Nazara/Core/Lock.hpp>
#include <Nazara/Core/LockGuard.hpp>
#include <Nazara/Core/Mutex.hpp>
#include <Nazara/Core/Debug.hpp>
NzLock::NzLock(NzMutex& mutex) :
NzLockGuard::NzLockGuard(NzMutex& mutex) :
m_mutex(mutex)
{
m_mutex.Lock();
}
NzLock::~NzLock()
NzLockGuard::~NzLockGuard()
{
m_mutex.Unlock();
}

View File

@ -123,7 +123,7 @@ bool NzGLSLShader::Create()
glBindAttribLocation(m_program, attribIndex[nzElementUsage_Diffuse], "Diffuse");
glBindAttribLocation(m_program, attribIndex[nzElementUsage_Tangent], "Tangent");
NzString uniformName = "TexCoord0";
NzString uniformName = "TexCoordi";
for (unsigned int i = 0; i < 8; ++i)
{
uniformName[8] = '0'+i;

View File

@ -137,6 +137,7 @@ bool NzRenderWindow::OnCreate()
{
m_parameters.doubleBuffered = true;
m_parameters.window = GetHandle();
m_context = new NzContext;
if (!m_context->Create(m_parameters))
{

View File

@ -4,6 +4,7 @@
#include <Nazara/Renderer/OpenGL.hpp> // Pour éviter une redéfinition de WIN32_LEAN_AND_MEAN
#include <Nazara/Renderer/Renderer.hpp>
#include <Nazara/Core/Color.hpp>
#include <Nazara/Core/Error.hpp>
#include <Nazara/Renderer/BufferImpl.hpp>
#include <Nazara/Renderer/Config.hpp>
@ -53,7 +54,7 @@ NzRenderer::~NzRenderer()
s_instance = nullptr;
}
void NzRenderer::Clear(nzRendererClear flags)
void NzRenderer::Clear(unsigned long flags)
{
#ifdef NAZARA_DEBUG
if (NzContext::GetCurrent() == nullptr)
@ -205,6 +206,19 @@ bool NzRenderer::Initialize()
return false;
}
void NzRenderer::SetClearColor(const NzColor& color)
{
#ifdef NAZARA_DEBUG
if (NzContext::GetCurrent() == nullptr)
{
NazaraError("No active context");
return;
}
#endif
glClearColor(color.r/255.f, color.g/255.f, color.b/255.f, color.a/255.f);
}
void NzRenderer::SetClearColor(nzUInt8 r, nzUInt8 g, nzUInt8 b, nzUInt8 a)
{
#ifdef NAZARA_DEBUG

View File

@ -7,7 +7,7 @@
#include <Nazara/Renderer/OpenGL.hpp>
#include <Nazara/Renderer/Win32/ContextImpl.hpp>
#include <Nazara/Core/Error.hpp>
#include <Nazara/Core/Lock.hpp>
#include <Nazara/Core/LockGuard.hpp>
#include <Nazara/Core/Mutex.hpp>
#include <Nazara/Renderer/Context.hpp>
#include <cstring>
@ -180,7 +180,7 @@ bool NzContextImpl::Create(NzContextParameters& parameters)
{
// wglShareLists n'est pas thread-safe (source: SFML)
static NzMutex mutex;
NzLock lock(mutex);
NzLockGuard lock(mutex);
if (!wglShareLists(shareContext, m_context))
NazaraWarning("Failed to share the context: " + NzGetLastSystemError());

View File

@ -6,6 +6,7 @@
#include <Nazara/Core/Error.hpp>
#include <Nazara/Utility/Config.hpp>
#include <Nazara/Utility/ResourceLoader.hpp>
#include <cmath>
#include <Nazara/Utility/Debug.hpp>
NzImage::NzImage() :
@ -50,36 +51,63 @@ bool NzImage::Convert(nzPixelFormat format)
NazaraError("Invalid pixel format");
return false;
}
if (!NzPixelFormat::IsConversionSupported(m_sharedImage->format, format))
{
NazaraError("Conversion from " + NzPixelFormat::ToString(m_sharedImage->format) + " to " + NzPixelFormat::ToString(format) + " is not supported");
return false;
}
#endif
if (format == m_sharedImage->format)
return true;
nzUInt8** levels = new nzUInt8*[m_sharedImage->levelCount];
unsigned int width = m_sharedImage->width;
unsigned int height = m_sharedImage->height;
// 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 pixelsPerFace = m_sharedImage->width*m_sharedImage->height;
nzUInt8* buffer = new nzUInt8[pixelsPerFace*depth*NzPixelFormat::GetBPP(format)];
nzUInt8* ptr = buffer;
nzUInt8* pixels = m_sharedImage->pixels;
unsigned int srcStride = pixelsPerFace * NzPixelFormat::GetBPP(m_sharedImage->format);
unsigned int dstStride = pixelsPerFace * NzPixelFormat::GetBPP(format);
for (unsigned int i = 0; i < depth; ++i)
for (unsigned int i = 0; i < m_sharedImage->levelCount; ++i)
{
if (!NzPixelFormat::Convert(m_sharedImage->format, format, pixels, &pixels[srcStride], ptr))
{
NazaraError("Failed to convert image");
delete[] buffer;
unsigned int pixelsPerFace = width*height;
nzUInt8* ptr = new nzUInt8[pixelsPerFace*depth*NzPixelFormat::GetBPP(format)];
nzUInt8* pixels = m_sharedImage->pixels[i];
unsigned int srcStride = pixelsPerFace * NzPixelFormat::GetBPP(m_sharedImage->format);
unsigned int dstStride = pixelsPerFace * NzPixelFormat::GetBPP(format);
return false;
levels[i] = ptr;
for (unsigned int d = 0; d < depth; ++d)
{
if (!NzPixelFormat::Convert(m_sharedImage->format, format, pixels, &pixels[srcStride], ptr))
{
NazaraError("Failed to convert image");
for (unsigned int j = 0; j <= i; ++j)
delete[] levels[j];
delete[] levels;
return false;
}
pixels += srcStride;
ptr += dstStride;
}
pixels += srcStride;
ptr += dstStride;
if (width > 1)
width /= 2;
if (height > 1)
height /= 2;
if (depth > 1 && m_sharedImage->type != nzImageType_Cubemap)
depth /= 2;
}
SharedImage* newImage = new SharedImage(1, m_sharedImage->type, format, buffer, m_sharedImage->width, m_sharedImage->height, m_sharedImage->depth);
SharedImage* newImage = new SharedImage(1, m_sharedImage->type, format, m_sharedImage->levelCount, levels, m_sharedImage->width, m_sharedImage->height, m_sharedImage->depth);
ReleaseImage();
m_sharedImage = newImage;
@ -103,7 +131,8 @@ bool NzImage::Copy(const NzImage& source, const NzRectui& srcRect, const NzVecto
}
#endif
return Update(&source.GetConstPixels()[(srcRect.x + srcRect.y * source.GetHeight()) * source.GetBPP()], NzRectui(dstPos.x, dstPos.y, srcRect.width, srcRect.height));
return Update(&source.GetConstPixels()[(srcRect.x + srcRect.y * source.GetHeight()) * source.GetBPP()],
NzRectui(dstPos.x, dstPos.y, srcRect.width, srcRect.height));
}
bool NzImage::CopyToFace(nzCubemapFace face, const NzImage& source, const NzRectui& srcRect, const NzVector2ui& dstPos)
@ -122,10 +151,12 @@ bool NzImage::CopyToFace(nzCubemapFace face, const NzImage& source, const NzRect
}
#endif
return UpdateFace(face, &source.GetConstPixels()[(srcRect.x + srcRect.y * source.GetHeight()) * source.GetBPP()], NzRectui(dstPos.x, dstPos.y, srcRect.width, srcRect.height));
return UpdateFace(face,
&source.GetConstPixels()[(srcRect.x + srcRect.y * source.GetHeight()) * source.GetBPP()],
NzRectui(dstPos.x, dstPos.y, srcRect.width, srcRect.height));
}
bool NzImage::Create(nzImageType type, nzPixelFormat format, unsigned int width, unsigned int height, unsigned int depth)
bool NzImage::Create(nzImageType type, nzPixelFormat format, unsigned int width, unsigned int height, unsigned int depth, nzUInt8 levelCount)
{
ReleaseImage();
@ -135,13 +166,7 @@ bool NzImage::Create(nzImageType type, nzPixelFormat format, unsigned int width,
NazaraError("Invalid pixel format");
return false;
}
#endif
unsigned int size = width*height*depth*NzPixelFormat::GetBPP(format);
if (size == 0)
return true;
#if NAZARA_UTILITY_SAFE
switch (type)
{
case nzImageType_1D:
@ -178,31 +203,53 @@ bool NzImage::Create(nzImageType type, nzPixelFormat format, unsigned int width,
NazaraError("Cubemaps must have square dimensions");
return false;
}
size *= 6; // Les cubemaps ont six faces
break;
default:
break;
}
#else
if (type == nzImageType_Cubemap)
size *= 6; // Les cubemaps ont six faces
#endif
// Cette allocation est protégée car sa taille dépend directement de paramètres utilisateurs
nzUInt8* buffer;
try
if (width == 0 || height == 0 || depth == 0)
return true;
levelCount = std::min(levelCount, GetMaxLevel(width, height, depth));
nzUInt8** levels = new nzUInt8*[levelCount];
unsigned int w = width;
unsigned int h = height;
unsigned int d = (type == nzImageType_Cubemap) ? 6 : depth;
for (unsigned int i = 0; i < levelCount; ++i)
{
buffer = new nzUInt8[size];
}
catch (const std::exception& e)
{
NazaraError("Failed to allocate image buffer (" + NzString(e.what()) + ')');
return false;
// Cette allocation est protégée car sa taille dépend directement de paramètres utilisateurs
try
{
levels[i] = new nzUInt8[w * h * d * NzPixelFormat::GetBPP(format)];
if (w > 1)
w /= 2;
if (h > 1)
h /= 2;
if (d > 1 && type != nzImageType_Cubemap)
d /= 2;
}
catch (const std::exception& e)
{
NazaraError("Failed to allocate image's level " + NzString::Number(i) + " (" + NzString(e.what()) + ')');
for (unsigned int j = 0; j <= i; ++j)
delete[] levels[j];
delete[] levels;
return false;
}
}
m_sharedImage = new SharedImage(1, type, format, buffer, width, height, depth);
m_sharedImage = new SharedImage(1, type, format, levelCount, levels, width, height, depth);
return true;
}
@ -217,14 +264,14 @@ nzUInt8 NzImage::GetBPP() const
return NzPixelFormat::GetBPP(m_sharedImage->format);
}
const nzUInt8* NzImage::GetConstPixels() const
const nzUInt8* NzImage::GetConstPixels(nzUInt8 level) const
{
return m_sharedImage->pixels;
return m_sharedImage->pixels[level];
}
unsigned int NzImage::GetDepth() const
unsigned int NzImage::GetDepth(nzUInt8 level) const
{
return m_sharedImage->depth;
return m_sharedImage->depth/(1 << level);
}
nzPixelFormat NzImage::GetFormat() const
@ -232,9 +279,19 @@ nzPixelFormat NzImage::GetFormat() const
return m_sharedImage->format;
}
unsigned int NzImage::GetHeight() const
unsigned int NzImage::GetHeight(nzUInt8 level) const
{
return m_sharedImage->height;
return m_sharedImage->height/(1 << level);
}
nzUInt8 NzImage::GetLevelCount() const
{
return m_sharedImage->levelCount;
}
nzUInt8 NzImage::GetMaxLevel() const
{
return GetMaxLevel(m_sharedImage->width, m_sharedImage->height, m_sharedImage->depth);
}
NzColor NzImage::GetPixel(unsigned int x, unsigned int y, unsigned int z) const
@ -277,10 +334,9 @@ NzColor NzImage::GetPixel(unsigned int x, unsigned int y, unsigned int z) const
}
#endif
const nzUInt8* pixel = &m_sharedImage->pixels[0][(m_sharedImage->height*(m_sharedImage->width*z+y) + x) * NzPixelFormat::GetBPP(m_sharedImage->format)];
NzColor color;
const nzUInt8* pixel = &m_sharedImage->pixels[(m_sharedImage->height*(m_sharedImage->width*z+y) + x) * NzPixelFormat::GetBPP(m_sharedImage->format)];
if (!NzPixelFormat::Convert(m_sharedImage->format, nzPixelFormat_RGBA8, pixel, &color.r))
NazaraError("Failed to convert image's format to RGBA8");
@ -321,26 +377,55 @@ NzColor NzImage::GetPixelFace(nzCubemapFace face, unsigned int x, unsigned int y
}
#endif
const nzUInt8* pixel = &m_sharedImage->pixels[0][(m_sharedImage->height*(m_sharedImage->width*(face-nzCubemapFace_PositiveX)+y) + x) * NzPixelFormat::GetBPP(m_sharedImage->format)];
NzColor color;
const nzUInt8* pixel = &m_sharedImage->pixels[(m_sharedImage->height*(m_sharedImage->width*(face-nzCubemapFace_PositiveX)+y) + x) * NzPixelFormat::GetBPP(m_sharedImage->format)];
if (!NzPixelFormat::Convert(m_sharedImage->format, nzPixelFormat_RGBA8, pixel, &color.r))
NazaraError("Failed to convert image's format to RGBA8");
return color;
}
nzUInt8* NzImage::GetPixels()
nzUInt8* NzImage::GetPixels(nzUInt8 level)
{
EnsureOwnership();
return m_sharedImage->pixels;
return m_sharedImage->pixels[level];
}
unsigned int NzImage::GetSize() const
{
return m_sharedImage->width * m_sharedImage->height * ((m_sharedImage->type == nzImageType_Cubemap) ? 6 : m_sharedImage->depth) * NzPixelFormat::GetBPP(m_sharedImage->format);
unsigned int width = m_sharedImage->width;
unsigned int height = m_sharedImage->height;
unsigned int depth = m_sharedImage->depth;
unsigned int size = 0;
for (unsigned int i = 0; i < m_sharedImage->levelCount; ++i)
{
size += width * height * depth;
if (width > 1)
width /= 2;
if (height > 1)
height /= 2;
if (depth > 1)
depth /= 2;
}
if (m_sharedImage->type == nzImageType_Cubemap)
size *= 6;
return size * NzPixelFormat::GetBPP(m_sharedImage->format);
}
unsigned int NzImage::GetSize(nzUInt8 level) const
{
return (std::max(m_sharedImage->width/(1 << level), 1)) *
(std::max(m_sharedImage->height/(1 << level), 1)) *
((m_sharedImage->type == nzImageType_Cubemap) ? 6 : std::min(m_sharedImage->depth/(1 << level), 1)) *
NzPixelFormat::GetBPP(m_sharedImage->format);
}
nzImageType NzImage::GetType() const
@ -348,9 +433,9 @@ nzImageType NzImage::GetType() const
return m_sharedImage->type;
}
unsigned int NzImage::GetWidth() const
unsigned int NzImage::GetWidth(nzUInt8 level) const
{
return m_sharedImage->width;
return m_sharedImage->width/(1 << level);
}
bool NzImage::IsCompressed() const
@ -383,6 +468,50 @@ bool NzImage::LoadFromStream(NzInputStream& stream, const NzImageParams& params)
return NzResourceLoader<NzImage, NzImageParams>::LoadResourceFromStream(this, stream, params);
}
bool NzImage::SetLevelCount(nzUInt8 levelCount)
{
#if NAZARA_UTILITY_SAFE
if (!IsValid())
{
NazaraError("Image must be valid");
return false;
}
if (levelCount == 0)
{
NazaraError("Level count must be positive");
return false;
}
#endif
levelCount = std::min(levelCount, GetMaxLevel(m_sharedImage->width, m_sharedImage->height, m_sharedImage->depth));
if (m_sharedImage->levelCount == levelCount)
return true;
EnsureOwnership();
nzUInt8** pixels = new nzUInt8*[levelCount];
for (unsigned int i = 0; i < levelCount; ++i)
{
if (i < m_sharedImage->levelCount)
pixels[i] = m_sharedImage->pixels[i];
else
{
unsigned int size = GetSize(i);
pixels[i] = new nzUInt8[size];
std::memcpy(pixels[i], m_sharedImage->pixels[i], size);
}
}
delete[] m_sharedImage->pixels;
m_sharedImage->levelCount = levelCount;
m_sharedImage->pixels = pixels;
return true;
}
bool NzImage::SetPixel(const NzColor& color, unsigned int x, unsigned int y, unsigned int z)
{
#if NAZARA_UTILITY_SAFE
@ -423,7 +552,7 @@ bool NzImage::SetPixel(const NzColor& color, unsigned int x, unsigned int y, uns
}
#endif
nzUInt8* pixel = &m_sharedImage->pixels[(m_sharedImage->height*(m_sharedImage->width*z+y) + x) * NzPixelFormat::GetBPP(m_sharedImage->format)];
nzUInt8* pixel = &m_sharedImage->pixels[0][(m_sharedImage->height*(m_sharedImage->width*z+y) + x) * NzPixelFormat::GetBPP(m_sharedImage->format)];
if (!NzPixelFormat::Convert(nzPixelFormat_RGBA8, m_sharedImage->format, &color.r, pixel))
{
@ -434,7 +563,7 @@ bool NzImage::SetPixel(const NzColor& color, unsigned int x, unsigned int y, uns
return true;
}
bool NzImage::SetPixelFace(const NzColor& color, nzCubemapFace face, unsigned int x, unsigned int y)
bool NzImage::SetPixelFace(nzCubemapFace face, const NzColor& color, unsigned int x, unsigned int y)
{
#if NAZARA_UTILITY_SAFE
if (!IsValid())
@ -468,7 +597,7 @@ bool NzImage::SetPixelFace(const NzColor& color, nzCubemapFace face, unsigned in
}
#endif
nzUInt8* pixel = &m_sharedImage->pixels[(m_sharedImage->height*(m_sharedImage->width*(face-nzCubemapFace_PositiveX)+y) + x) * NzPixelFormat::GetBPP(m_sharedImage->format)];
nzUInt8* pixel = &m_sharedImage->pixels[0][(m_sharedImage->height*(m_sharedImage->width*(face-nzCubemapFace_PositiveX)+y) + x) * NzPixelFormat::GetBPP(m_sharedImage->format)];
if (!NzPixelFormat::Convert(nzPixelFormat_RGBA8, m_sharedImage->format, &color.r, pixel))
{
@ -479,7 +608,7 @@ bool NzImage::SetPixelFace(const NzColor& color, nzCubemapFace face, unsigned in
return true;
}
bool NzImage::Update(const nzUInt8* pixels)
bool NzImage::Update(const nzUInt8* pixels, nzUInt8 level)
{
#if NAZARA_UTILITY_SAFE
if (!IsValid())
@ -499,16 +628,22 @@ bool NzImage::Update(const nzUInt8* pixels)
NazaraError("Invalid pixel source");
return false;
}
if (level >= m_sharedImage->levelCount)
{
NazaraError("Level out of bounds (" + NzString::Number(level) + " >= " + NzString::Number(m_sharedImage->levelCount) + ')');
return false;
}
#endif
EnsureOwnership();
std::memcpy(m_sharedImage->pixels, pixels, GetSize());
std::memcpy(m_sharedImage->pixels[level], pixels, GetSize(level));
return true;
}
bool NzImage::Update(const nzUInt8* pixels, const NzRectui& rect, unsigned int z)
bool NzImage::Update(const nzUInt8* pixels, const NzRectui& rect, unsigned int z, nzUInt8 level)
{
#if NAZARA_UTILITY_SAFE
if (!IsValid())
@ -535,13 +670,19 @@ bool NzImage::Update(const nzUInt8* pixels, const NzRectui& rect, unsigned int z
return false;
}
if (rect.x+rect.width > m_sharedImage->width || rect.y+rect.height > m_sharedImage->height)
if (level >= m_sharedImage->levelCount)
{
NazaraError("Level out of bounds (" + NzString::Number(level) + " >= " + NzString::Number(m_sharedImage->levelCount) + ')');
return false;
}
if (rect.x+rect.width > (m_sharedImage->width << level) || rect.y+rect.height > (m_sharedImage->height) << level)
{
NazaraError("Rectangle dimensions are out of bounds");
return false;
}
if (z >= m_sharedImage->depth)
if (z >= (m_sharedImage->depth << level))
{
NazaraError("Z value exceeds depth (" + NzString::Number(z) + " >= (" + NzString::Number(m_sharedImage->depth) + ')');
return false;
@ -552,22 +693,20 @@ bool NzImage::Update(const nzUInt8* pixels, const NzRectui& rect, unsigned int z
nzUInt8 bpp = NzPixelFormat::GetBPP(m_sharedImage->format);
nzUInt8* dstPixels = &m_sharedImage->pixels[(m_sharedImage->height*(m_sharedImage->width*z + rect.y) + rect.x) * NzPixelFormat::GetBPP(m_sharedImage->format)];
nzUInt8* dstPixels = &m_sharedImage->pixels[level][(m_sharedImage->height*(m_sharedImage->width*z + rect.y) + rect.x) * NzPixelFormat::GetBPP(m_sharedImage->format)];
unsigned int srcStride = rect.width * bpp;
unsigned int dstStride = m_sharedImage->width * bpp;
unsigned int blockSize = m_sharedImage->width * bpp;
for (unsigned int i = 0; i < rect.height; ++i)
{
std::memcpy(dstPixels, pixels, blockSize);
pixels += srcStride;
dstPixels += dstStride;
dstPixels += blockSize;
}
return true;
}
bool NzImage::UpdateFace(nzCubemapFace face, const nzUInt8* pixels)
bool NzImage::UpdateFace(nzCubemapFace face, const nzUInt8* pixels, nzUInt8 level)
{
#if NAZARA_UTILITY_SAFE
if (!IsValid())
@ -587,17 +726,23 @@ bool NzImage::UpdateFace(nzCubemapFace face, const nzUInt8* pixels)
NazaraError("Invalid pixel source");
return false;
}
if (level >= m_sharedImage->levelCount)
{
NazaraError("Level out of bounds (" + NzString::Number(level) + " >= " + NzString::Number(m_sharedImage->levelCount) + ')');
return false;
}
#endif
EnsureOwnership();
unsigned int size = GetSize();
std::memcpy(&m_sharedImage->pixels[size*(face-nzCubemapFace_PositiveX)], pixels, size);
unsigned int size = GetSize(level);
std::memcpy(&m_sharedImage->pixels[level][size*(face-nzCubemapFace_PositiveX)], pixels, size);
return true;
}
bool NzImage::UpdateFace(nzCubemapFace face, const nzUInt8* pixels, const NzRectui& rect)
bool NzImage::UpdateFace(nzCubemapFace face, const nzUInt8* pixels, const NzRectui& rect, nzUInt8 level)
{
#if NAZARA_UTILITY_SAFE
if (!IsValid())
@ -624,7 +769,13 @@ bool NzImage::UpdateFace(nzCubemapFace face, const nzUInt8* pixels, const NzRect
return false;
}
if (rect.x+rect.width > m_sharedImage->width || rect.y+rect.height > m_sharedImage->height)
if (level >= m_sharedImage->levelCount)
{
NazaraError("Level out of bounds (" + NzString::Number(level) + " >= " + NzString::Number(m_sharedImage->levelCount) + ')');
return false;
}
if (rect.x+rect.width > (m_sharedImage->width << level) || rect.y+rect.height > (m_sharedImage->height) << level)
{
NazaraError("Rectangle dimensions are out of bounds");
return false;
@ -635,16 +786,14 @@ bool NzImage::UpdateFace(nzCubemapFace face, const nzUInt8* pixels, const NzRect
nzUInt8 bpp = NzPixelFormat::GetBPP(m_sharedImage->format);
nzUInt8* dstPixels = &m_sharedImage->pixels[(m_sharedImage->height*(m_sharedImage->width*(face-nzCubemapFace_PositiveX) + rect.y) + rect.x) * NzPixelFormat::GetBPP(m_sharedImage->format)];
nzUInt8* dstPixels = &m_sharedImage->pixels[level][(m_sharedImage->height*(m_sharedImage->width*(face-nzCubemapFace_PositiveX) + rect.y) + rect.x) * NzPixelFormat::GetBPP(m_sharedImage->format)];
unsigned int srcStride = rect.width * bpp;
unsigned int dstStride = m_sharedImage->width * bpp;
unsigned int blockSize = m_sharedImage->width * bpp;
for (unsigned int i = 0; i < rect.height; ++i)
{
std::memcpy(dstPixels, pixels, blockSize);
pixels += srcStride;
dstPixels += dstStride;
dstPixels += blockSize;
}
return true;
@ -672,6 +821,17 @@ NzImage& NzImage::operator=(NzImage&& image)
return *this;
}
nzUInt8 NzImage::GetMaxLevel(unsigned int width, unsigned int height, unsigned int depth)
{
static const float l2 = std::log(2);
unsigned int widthLevel = std::log(width)/l2;
unsigned int heightLevel = std::log(height)/l2;
unsigned int depthLevel = std::log(depth)/l2;
return std::max(std::max(widthLevel, heightLevel), depthLevel);
}
void NzImage::RegisterFileLoader(const NzString& extensions, LoadFileFunction loadFile)
{
return RegisterResourceFileLoader(extensions, loadFile);
@ -712,12 +872,15 @@ void NzImage::EnsureOwnership()
{
m_sharedImage->refCount--;
unsigned int size = GetSize();
nzUInt8** pixels = new nzUInt8*[m_sharedImage->levelCount];
for (unsigned int i = 0; i < m_sharedImage->levelCount; ++i)
{
unsigned int size = GetSize(i);
pixels[i] = new nzUInt8[size];
std::memcpy(pixels[i], &m_sharedImage->pixels[i], size);
}
nzUInt8* pixels = new nzUInt8[size];
std::memcpy(pixels, m_sharedImage->pixels, size);
m_sharedImage = new SharedImage(1, m_sharedImage->type, m_sharedImage->format, pixels, m_sharedImage->width, m_sharedImage->height, m_sharedImage->depth);
m_sharedImage = new SharedImage(1, m_sharedImage->type, m_sharedImage->format, m_sharedImage->levelCount, pixels, m_sharedImage->width, m_sharedImage->height, m_sharedImage->depth);
}
}
@ -732,6 +895,9 @@ void NzImage::ReleaseImage()
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;
}
@ -739,4 +905,4 @@ void NzImage::ReleaseImage()
m_sharedImage = &emptyImage;
}
NzImage::SharedImage NzImage::emptyImage(0, nzImageType_2D, nzPixelFormat_Undefined, nullptr, 0, 0, 0);
NzImage::SharedImage NzImage::emptyImage(0, nzImageType_2D, nzPixelFormat_Undefined, 0, nullptr, 0, 0, 0);

View File

@ -120,6 +120,7 @@ namespace
}
resource->Update(ptr);
stbi_image_free(ptr);
if (stbiFormat == STBI_default && parameters.loadFormat != nzPixelFormat_Undefined)

View File

@ -8,15 +8,23 @@
#include <Nazara/Core/Error.hpp>
#include <Nazara/Utility/Debug.hpp>
///FIXME: Endianness (nzUInt16)
namespace
{
inline nzUInt8 c4to5(nzUInt8 c)
{
return c * (31.f/15.f);
}
inline nzUInt8 c4to8(nzUInt8 c)
{
return c * (255/15);
}
inline nzUInt8 c5to4(nzUInt8 c)
{
return c * (15.f/31.f);
}
inline nzUInt8 c5to8(nzUInt8 c)
{
return c * (255.f/31.f);
@ -90,11 +98,19 @@ namespace
template<>
nzUInt8* ConvertPixels<nzPixelFormat_BGR8, nzPixelFormat_RGBA4>(const nzUInt8* start, const nzUInt8* end, nzUInt8* dst)
{
nzUInt16* ptr = reinterpret_cast<nzUInt16*>(dst);
while (start < end)
{
*dst++ = ((c8to4(start[2])) << 4) | c8to4(start[1]);
*dst++ = ((c8to4(start[0])) << 4) | 0x0F;
*ptr = (static_cast<nzUInt16>(c8to4(start[2])) << 12) |
(static_cast<nzUInt16>(c8to4(start[1])) << 8) |
(static_cast<nzUInt16>(c8to4(start[0])) << 4) |
0x0F;
#ifdef NAZARA_BIG_ENDIAN
NzByteSwap(ptr, sizeof(nzUInt16));
#endif
ptr++;
start += 3;
}
@ -107,11 +123,16 @@ namespace
nzUInt16* ptr = reinterpret_cast<nzUInt16*>(dst);
while (start < end)
{
*ptr++ = (static_cast<nzUInt16>(c8to5(start[2])) << 11) |
(static_cast<nzUInt16>(c8to5(start[1])) << 6) |
(static_cast<nzUInt16>(c8to5(start[0])) << 1) |
0x1;
*ptr = (static_cast<nzUInt16>(c8to5(start[2])) << 11) |
(static_cast<nzUInt16>(c8to5(start[1])) << 6) |
(static_cast<nzUInt16>(c8to5(start[0])) << 1) |
0x1;
#ifdef NAZARA_BIG_ENDIAN
NzByteSwap(ptr, sizeof(nzUInt16));
#endif
ptr++;
start += 3;
}
@ -195,11 +216,19 @@ namespace
template<>
nzUInt8* ConvertPixels<nzPixelFormat_BGRA8, nzPixelFormat_RGBA4>(const nzUInt8* start, const nzUInt8* end, nzUInt8* dst)
{
nzUInt16* ptr = reinterpret_cast<nzUInt16*>(dst);
while (start < end)
{
*dst++ = (c8to4(start[2]) << 4) | c8to4(start[1]);
*dst++ = (c8to4(start[0]) << 4) | c8to4(start[3]);
*ptr = (static_cast<nzUInt16>(c8to4(start[2])) << 12) |
(static_cast<nzUInt16>(c8to4(start[1])) << 8) |
(static_cast<nzUInt16>(c8to4(start[0])) << 4) |
(static_cast<nzUInt16>(c8to4(start[3])) << 0);
#ifdef NAZARA_BIG_ENDIAN
NzByteSwap(ptr, sizeof(nzUInt16));
#endif
ptr++;
start += 4;
}
@ -212,11 +241,16 @@ namespace
nzUInt16* ptr = reinterpret_cast<nzUInt16*>(dst);
while (start < end)
{
*ptr++ = (static_cast<nzUInt16>(c8to5(start[2])) << 11) |
(static_cast<nzUInt16>(c8to5(start[1])) << 6) |
(static_cast<nzUInt16>(c8to5(start[0])) << 1) |
((start[3] == 0xFF) ? 1 : 0);
*ptr = (static_cast<nzUInt16>(c8to5(start[2])) << 11) |
(static_cast<nzUInt16>(c8to5(start[1])) << 6) |
(static_cast<nzUInt16>(c8to5(start[0])) << 1) |
((start[3] == 0xFF) ? 1 : 0);
#ifdef NAZARA_BIG_ENDIAN
NzByteSwap(ptr, sizeof(nzUInt16));
#endif
ptr++;
start += 4;
}
@ -303,13 +337,21 @@ namespace
template<>
nzUInt8* ConvertPixels<nzPixelFormat_L8, nzPixelFormat_RGBA4>(const nzUInt8* start, const nzUInt8* end, nzUInt8* dst)
{
nzUInt16* ptr = reinterpret_cast<nzUInt16*>(dst);
while (start < end)
{
nzUInt8 l = c8to4(start[0]);
nzUInt16 l = static_cast<nzUInt16>(c8to4(start[0]));
*dst++ = (l << 4) | l;
*dst++ = (l << 4) | 0x0F;
*ptr = (l << 12) |
(l << 8) |
(l << 4) |
0x0F;
#ifdef NAZARA_BIG_ENDIAN
NzByteSwap(ptr, sizeof(nzUInt16));
#endif
ptr++;
start += 1;
}
@ -324,11 +366,16 @@ namespace
{
nzUInt16 l = static_cast<nzUInt16>(c8to5(start[0]));
*ptr++ = (l << 11) |
(l << 6) |
(l << 1) |
1;
*ptr = (l << 11) |
(l << 6) |
(l << 1) |
1;
#ifdef NAZARA_BIG_ENDIAN
NzByteSwap(ptr, sizeof(nzUInt16));
#endif
ptr++;
start += 1;
}
@ -414,13 +461,18 @@ namespace
template<>
nzUInt8* ConvertPixels<nzPixelFormat_LA8, nzPixelFormat_RGBA4>(const nzUInt8* start, const nzUInt8* end, nzUInt8* dst)
{
nzUInt16* ptr = reinterpret_cast<nzUInt16*>(dst);
while (start < end)
{
nzUInt8 l = c8to4(start[0]);
nzUInt16 l = static_cast<nzUInt16>(c8to4(start[0]));
*dst++ = (l << 4) | l;
*dst++ = (l << 4) | c8to4(start[1]);
*ptr = (l << 12) | (l << 8) | (l << 4) | c8to4(start[1]);
#ifdef NAZARA_BIG_ENDIAN
NzByteSwap(ptr, sizeof(nzUInt16));
#endif
ptr++;
start += 2;
}
@ -435,8 +487,13 @@ namespace
{
nzUInt16 l = static_cast<nzUInt16>(c8to5(start[0]));
*ptr++ = (l << 11) | (l << 6) | (l << 1) | ((start[1] == 0xFF) ? 1 : 0);
*ptr = (l << 11) | (l << 6) | (l << 1) | ((start[1] == 0xFF) ? 1 : 0);
#ifdef NAZARA_BIG_ENDIAN
NzByteSwap(ptr, sizeof(nzUInt16));
#endif
ptr++;
start += 2;
}
@ -480,9 +537,15 @@ namespace
{
while (start < end)
{
*dst++ = c4to8((start[1] & 0xF0) >> 4);
*dst++ = c4to8((start[0] & 0x0F) >> 0);
*dst++ = c4to8((start[0] & 0xF0) >> 4);
nzUInt16 pixel = *reinterpret_cast<const nzUInt16*>(start);
#ifdef NAZARA_BIG_ENDIAN
NzByteSwap(&pixel, sizeof(nzUInt16));
#endif
*dst++ = c4to8((pixel & 0x00F0) >> 4);
*dst++ = c4to8((pixel & 0x0F00) >> 8);
*dst++ = c4to8((pixel & 0xF000) >> 12);
start += 2;
}
@ -495,10 +558,16 @@ namespace
{
while (start < end)
{
*dst++ = c4to8((start[1] & 0xF0) >> 4);
*dst++ = c4to8((start[0] & 0x0F) >> 0);
*dst++ = c4to8((start[0] & 0xF0) >> 4);
*dst++ = c4to8((start[1] & 0x0F) >> 0);
nzUInt16 pixel = *reinterpret_cast<const nzUInt16*>(start);
#ifdef NAZARA_BIG_ENDIAN
NzByteSwap(&pixel, sizeof(nzUInt16));
#endif
*dst++ = c4to8((pixel & 0x00F0) >> 4);
*dst++ = c4to8((pixel & 0x0F00) >> 8);
*dst++ = c4to8((pixel & 0xF000) >> 12);
*dst++ = c4to8((pixel & 0x000F) >> 0);
start += 2;
}
@ -511,9 +580,15 @@ namespace
{
while (start < end)
{
nzUInt8 r = c4to8((start[0] & 0xF0) >> 4);
nzUInt8 g = c4to8((start[0] & 0x0F) >> 0);
nzUInt8 b = c4to8((start[1] & 0xF0) >> 4);
nzUInt16 pixel = *reinterpret_cast<const nzUInt16*>(start);
#ifdef NAZARA_BIG_ENDIAN
NzByteSwap(&pixel, sizeof(nzUInt16));
#endif
nzUInt16 r = c4to8((pixel & 0xF000) >> 12);
nzUInt16 g = c4to8((pixel & 0x0F00) >> 8);
nzUInt16 b = c4to8((pixel & 0x00F0) >> 4);
*dst++ = static_cast<nzUInt8>(r * 0.3 + g * 0.59 + b * 0.11);
@ -528,12 +603,18 @@ namespace
{
while (start < end)
{
nzUInt8 r = c4to8((start[0] & 0xF0) >> 4);
nzUInt8 g = c4to8((start[0] & 0x0F) >> 0);
nzUInt8 b = c4to8((start[1] & 0xF0) >> 4);
nzUInt16 pixel = *reinterpret_cast<const nzUInt16*>(start);
#ifdef NAZARA_BIG_ENDIAN
NzByteSwap(&pixel, sizeof(nzUInt16));
#endif
nzUInt16 r = c4to8((pixel & 0xF000) >> 12);
nzUInt16 g = c4to8((pixel & 0x0F00) >> 8);
nzUInt16 b = c4to8((pixel & 0x00F0) >> 4);
*dst++ = static_cast<nzUInt8>(r * 0.3 + g * 0.59 + b * 0.11);
*dst++ = c4to8(start[1] & 0x0F);
*dst++ = c4to8(pixel & 0x000F);
start += 2;
}
@ -547,13 +628,24 @@ namespace
nzUInt16* ptr = reinterpret_cast<nzUInt16*>(dst);
while (start < end)
{
nzUInt16 r = (start[0] & 0xF0) >> 4;
nzUInt16 g = (start[0] & 0x0F) >> 0;
nzUInt16 b = (start[1] & 0xF0) >> 4;
nzUInt8 a = (start[1] & 0x0F) >> 0;
nzUInt16 pixel = *reinterpret_cast<const nzUInt16*>(start);
*ptr++ = (r << 11) | (g << 6) | (b << 1) | ((a == 0xFF) ? 1 : 0);
#ifdef NAZARA_BIG_ENDIAN
NzByteSwap(&pixel, sizeof(nzUInt16));
#endif
nzUInt16 r = c4to5((pixel & 0xF000) >> 12);
nzUInt16 g = c4to5((pixel & 0x0F00) >> 8);
nzUInt16 b = c4to5((pixel & 0x00F0) >> 4);
nzUInt16 a = c4to5((pixel & 0x000F) >> 0);
*ptr = (r << 11) | (g << 6) | (b << 1) | ((a == 0xFF) ? 1 : 0);
#ifdef NAZARA_BIG_ENDIAN
NzByteSwap(ptr, sizeof(nzUInt16));
#endif
ptr++;
start += 2;
}
@ -565,9 +657,15 @@ namespace
{
while (start < end)
{
*dst++ = c4to8((start[0] & 0xF0) >> 4);
*dst++ = c4to8((start[0] & 0x0F) >> 0);
*dst++ = c4to8((start[1] & 0xF0) >> 4);
nzUInt16 pixel = *reinterpret_cast<const nzUInt16*>(start);
#ifdef NAZARA_BIG_ENDIAN
NzByteSwap(&pixel, sizeof(nzUInt16));
#endif
*dst++ = c4to8((pixel & 0xF000) >> 12);
*dst++ = c4to8((pixel & 0x0F00) >> 8);
*dst++ = c4to8((pixel & 0x00F0) >> 4);
start += 2;
}
@ -580,10 +678,16 @@ namespace
{
while (start < end)
{
*dst++ = c4to8((start[0] & 0xF0) >> 4);
*dst++ = c4to8((start[0] & 0x0F) >> 0);
*dst++ = c4to8((start[1] & 0xF0) >> 4);
*dst++ = c4to8((start[1] & 0x0F) >> 0);
nzUInt16 pixel = *reinterpret_cast<const nzUInt16*>(start);
#ifdef NAZARA_BIG_ENDIAN
NzByteSwap(&pixel, sizeof(nzUInt16));
#endif
*dst++ = c4to8((pixel & 0xF000) >> 12);
*dst++ = c4to8((pixel & 0x0F00) >> 8);
*dst++ = c4to8((pixel & 0x00F0) >> 4);
*dst++ = c4to8((pixel & 0x000F) >> 0);
start += 2;
}
@ -599,6 +703,10 @@ namespace
{
nzUInt16 pixel = *reinterpret_cast<const nzUInt16*>(start);
#ifdef NAZARA_BIG_ENDIAN
NzByteSwap(&pixel, sizeof(nzUInt16));
#endif
*dst++ = c5to8((pixel & 0x003E) >> 1);
*dst++ = c5to8((pixel & 0x07C0) >> 6);
*dst++ = c5to8((pixel & 0xF800) >> 11);
@ -616,6 +724,10 @@ namespace
{
nzUInt16 pixel = *reinterpret_cast<const nzUInt16*>(start);
#ifdef NAZARA_BIG_ENDIAN
NzByteSwap(&pixel, sizeof(nzUInt16));
#endif
*dst++ = c5to8((pixel & 0x003E) >> 1);
*dst++ = c5to8((pixel & 0x07C0) >> 6);
*dst++ = c5to8((pixel & 0xF800) >> 11);
@ -634,6 +746,10 @@ namespace
{
nzUInt16 pixel = *reinterpret_cast<const nzUInt16*>(start);
#ifdef NAZARA_BIG_ENDIAN
NzByteSwap(&pixel, sizeof(nzUInt16));
#endif
nzUInt8 r = c5to8((pixel & 0xF800) >> 11);
nzUInt8 g = c5to8((pixel & 0x07C0) >> 6);
nzUInt8 b = c5to8((pixel & 0x003E) >> 1);
@ -653,6 +769,10 @@ namespace
{
nzUInt16 pixel = *reinterpret_cast<const nzUInt16*>(start);
#ifdef NAZARA_BIG_ENDIAN
NzByteSwap(&pixel, sizeof(nzUInt16));
#endif
nzUInt8 r = c5to8((pixel & 0xF800) >> 11);
nzUInt8 g = c5to8((pixel & 0x07C0) >> 6);
nzUInt8 b = c5to8((pixel & 0x003E) >> 1);
@ -669,17 +789,26 @@ namespace
template<>
nzUInt8* ConvertPixels<nzPixelFormat_RGB5A1, nzPixelFormat_RGBA4>(const nzUInt8* start, const nzUInt8* end, nzUInt8* dst)
{
nzUInt16* ptr = reinterpret_cast<nzUInt16*>(dst);
while (start < end)
{
nzUInt16 pixel = *reinterpret_cast<const nzUInt16*>(start);
nzUInt8 r = c5to8((pixel & 0xF800) >> 11);
nzUInt8 g = c5to8((pixel & 0x07C0) >> 6);
nzUInt8 b = c5to8((pixel & 0x003E) >> 1);
#ifdef NAZARA_BIG_ENDIAN
NzByteSwap(&pixel, sizeof(nzUInt16));
#endif
*dst++ = (c8to4(r) << 4) | c8to4(g);
*dst++ = (c8to4(b) << 4) | ((pixel & 0x1)*0x0F);
nzUInt8 r = c5to4((pixel & 0xF800) >> 11);
nzUInt8 g = c5to4((pixel & 0x07C0) >> 6);
nzUInt8 b = c5to4((pixel & 0x003E) >> 1);
*ptr = (r << 12) | (g << 8) | (b << 4) | ((pixel & 0x1)*0x0F);
#ifdef NAZARA_BIG_ENDIAN
NzByteSwap(ptr, sizeof(nzUInt16));
#endif
ptr++;
start += 2;
}
@ -693,6 +822,10 @@ namespace
{
nzUInt16 pixel = *reinterpret_cast<const nzUInt16*>(start);
#ifdef NAZARA_BIG_ENDIAN
NzByteSwap(&pixel, sizeof(nzUInt16));
#endif
*dst++ = c5to8((pixel & 0xF800) >> 11);
*dst++ = c5to8((pixel & 0x07C0) >> 6);
*dst++ = c5to8((pixel & 0x003E) >> 1);
@ -710,6 +843,10 @@ namespace
{
nzUInt16 pixel = *reinterpret_cast<const nzUInt16*>(start);
#ifdef NAZARA_BIG_ENDIAN
NzByteSwap(&pixel, sizeof(nzUInt16));
#endif
*dst++ = c5to8((pixel & 0xF800) >> 11);
*dst++ = c5to8((pixel & 0x07C0) >> 6);
*dst++ = c5to8((pixel & 0x003E) >> 1);
@ -783,11 +920,19 @@ namespace
template<>
nzUInt8* ConvertPixels<nzPixelFormat_RGB8, nzPixelFormat_RGBA4>(const nzUInt8* start, const nzUInt8* end, nzUInt8* dst)
{
nzUInt16* ptr = reinterpret_cast<nzUInt16*>(dst);
while (start < end)
{
*dst++ = (c8to4(start[0]) << 4) | c8to4(start[1]);
*dst++ = (c8to4(start[2]) << 4) | 0x0F;
*ptr = (static_cast<nzUInt16>(c8to4(start[0])) << 12) |
(static_cast<nzUInt16>(c8to4(start[1])) << 8) |
(static_cast<nzUInt16>(c8to4(start[2])) << 4) |
0x0F;
#ifdef NAZARA_BIG_ENDIAN
NzByteSwap(ptr, sizeof(nzUInt16));
#endif
ptr++;
start += 3;
}
@ -800,11 +945,16 @@ namespace
nzUInt16* ptr = reinterpret_cast<nzUInt16*>(dst);
while (start < end)
{
*ptr++ = (static_cast<nzUInt16>(c8to5(start[0])) << 11) |
(static_cast<nzUInt16>(c8to5(start[1])) << 6) |
(static_cast<nzUInt16>(c8to5(start[2])) << 1) |
0x1;
*ptr = (static_cast<nzUInt16>(c8to5(start[0])) << 11) |
(static_cast<nzUInt16>(c8to5(start[1])) << 6) |
(static_cast<nzUInt16>(c8to5(start[2])) << 1) |
0x1;
#ifdef NAZARA_BIG_ENDIAN
NzByteSwap(ptr, sizeof(nzUInt16));
#endif
ptr++;
start += 3;
}
@ -889,11 +1039,19 @@ namespace
template<>
nzUInt8* ConvertPixels<nzPixelFormat_RGBA8, nzPixelFormat_RGBA4>(const nzUInt8* start, const nzUInt8* end, nzUInt8* dst)
{
nzUInt16* ptr = reinterpret_cast<nzUInt16*>(dst);
while (start < end)
{
*dst++ = (c8to4(start[0]) << 4) | c8to4(start[1]);
*dst++ = (c8to4(start[2]) << 4) | c8to4(start[3]);
*ptr = (static_cast<nzUInt16>(c8to4(start[0])) << 12) |
(static_cast<nzUInt16>(c8to4(start[1])) << 8) |
(static_cast<nzUInt16>(c8to4(start[2])) << 4) |
(static_cast<nzUInt16>(c8to4(start[3])) << 0);
#ifdef NAZARA_BIG_ENDIAN
NzByteSwap(ptr, sizeof(nzUInt16));
#endif
ptr++;
start += 4;
}
@ -906,11 +1064,16 @@ namespace
nzUInt16* ptr = reinterpret_cast<nzUInt16*>(dst);
while (start < end)
{
*ptr++ = (static_cast<nzUInt16>(c8to5(start[0])) << 11) |
(static_cast<nzUInt16>(c8to5(start[1])) << 6) |
(static_cast<nzUInt16>(c8to5(start[2])) << 1) |
((start[3] == 0xFF) ? 1 : 0);
*ptr = (static_cast<nzUInt16>(c8to5(start[0])) << 11) |
(static_cast<nzUInt16>(c8to5(start[1])) << 6) |
(static_cast<nzUInt16>(c8to5(start[2])) << 1) |
((start[3] == 0xFF) ? 1 : 0);
#ifdef NAZARA_BIG_ENDIAN
NzByteSwap(ptr, sizeof(nzUInt16));
#endif
ptr++;
start += 4;
}
@ -976,7 +1139,7 @@ bool NzPixelFormat::Initialize()
RegisterConverter<nzPixelFormat_BGRA8, nzPixelFormat_RGBA8>();
/**********************************DXT1***********************************/
///TODO
///TODO: Décompresseur DXT1
/*
RegisterConverter<nzPixelFormat_DXT1, nzPixelFormat_BGR8>();
RegisterConverter<nzPixelFormat_DXT1, nzPixelFormat_BGRA8>();
@ -999,7 +1162,7 @@ bool NzPixelFormat::Initialize()
*/
/**********************************DXT3***********************************/
///TODO
///TODO: Décompresseur DXT3
/*
RegisterConverter<nzPixelFormat_DXT3, nzPixelFormat_BGR8>();
RegisterConverter<nzPixelFormat_DXT3, nzPixelFormat_BGRA8>();
@ -1022,7 +1185,7 @@ bool NzPixelFormat::Initialize()
*/
/**********************************DXT5***********************************/
///TODO
///TODO: Décompresseur DXT5
/*
RegisterConverter<nzPixelFormat_DXT5, nzPixelFormat_BGR8>();
RegisterConverter<nzPixelFormat_DXT5, nzPixelFormat_BGRA8>();
@ -1091,7 +1254,6 @@ bool NzPixelFormat::Initialize()
RegisterConverter<nzPixelFormat_RGBA4, nzPixelFormat_RGBA16I>();
RegisterConverter<nzPixelFormat_RGBA4, nzPixelFormat_RGBA32F>();
RegisterConverter<nzPixelFormat_RGBA4, nzPixelFormat_RGBA32I>();*/
RegisterConverter<nzPixelFormat_RGBA4, nzPixelFormat_RGBA4>();
RegisterConverter<nzPixelFormat_RGBA4, nzPixelFormat_RGB5A1>();
RegisterConverter<nzPixelFormat_RGBA4, nzPixelFormat_RGB8>();
RegisterConverter<nzPixelFormat_RGBA4, nzPixelFormat_RGBA8>();
@ -1110,7 +1272,6 @@ bool NzPixelFormat::Initialize()
RegisterConverter<nzPixelFormat_RGB5A1, nzPixelFormat_RGBA32F>();
RegisterConverter<nzPixelFormat_RGB5A1, nzPixelFormat_RGBA32I>();*/
RegisterConverter<nzPixelFormat_RGB5A1, nzPixelFormat_RGBA4>();
RegisterConverter<nzPixelFormat_RGB5A1, nzPixelFormat_RGB5A1>();
RegisterConverter<nzPixelFormat_RGB5A1, nzPixelFormat_RGB8>();
RegisterConverter<nzPixelFormat_RGB5A1, nzPixelFormat_RGBA8>();

View File

@ -4,7 +4,7 @@
#include <Nazara/Utility/Window.hpp>
#include <Nazara/Core/Error.hpp>
#include <Nazara/Core/Lock.hpp>
#include <Nazara/Core/LockGuard.hpp>
#include <stdexcept>
#if defined(NAZARA_PLATFORM_WINDOWS)
@ -281,7 +281,7 @@ bool NzWindow::PollEvent(NzEvent* event)
return false;
#if NAZARA_UTILITY_THREADED_WINDOW
NzLock lock(m_eventMutex);
NzLockGuard lock(m_eventMutex);
#else
m_impl->ProcessEvents(false);
#endif
@ -308,7 +308,7 @@ void NzWindow::SetEventListener(bool listener)
m_impl->SetEventListener(listener);
if (!listener)
{
NzLock lock(m_eventMutex);
NzLockGuard lock(m_eventMutex);
while (!m_events.empty())
m_events.pop();
}
@ -408,7 +408,7 @@ bool NzWindow::WaitEvent(NzEvent* event)
return false;
#if NAZARA_UTILITY_THREADED_WINDOW
NzLock lock(m_eventMutex);
NzLockGuard lock(m_eventMutex);
if (m_events.empty())
{