From b220e00c887203cf997c389cdad5315c370e1997 Mon Sep 17 00:00:00 2001 From: Lynix Date: Wed, 30 May 2012 18:10:17 +0200 Subject: [PATCH] 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 --- include/Nazara/Core/Color.hpp | 4 +- .../Nazara/Core/{Lock.hpp => LockGuard.hpp} | 12 +- include/Nazara/Core/ThreadSafety.hpp | 4 +- include/Nazara/Renderer/Renderer.hpp | 4 +- include/Nazara/Utility/Image.hpp | 37 +- include/Nazara/Utility/PixelFormat.hpp | 27 +- include/Nazara/Utility/PixelFormat.inl | 32 +- include/Nazara/Utility/ResourceLoader.inl | 13 +- src/Nazara/Core/{Lock.cpp => LockGuard.cpp} | 6 +- src/Nazara/Renderer/GLSLShader.cpp | 2 +- src/Nazara/Renderer/RenderWindow.cpp | 1 + src/Nazara/Renderer/Renderer.cpp | 16 +- src/Nazara/Renderer/Win32/ContextImpl.cpp | 4 +- src/Nazara/Utility/Image.cpp | 334 +++++++++++++----- src/Nazara/Utility/Loaders/STB.cpp | 1 + src/Nazara/Utility/PixelFormat.cpp | 307 ++++++++++++---- src/Nazara/Utility/Window.cpp | 8 +- 17 files changed, 591 insertions(+), 221 deletions(-) rename include/Nazara/Core/{Lock.hpp => LockGuard.hpp} (62%) rename src/Nazara/Core/{Lock.cpp => LockGuard.cpp} (72%) diff --git a/include/Nazara/Core/Color.hpp b/include/Nazara/Core/Color.hpp index be4143c7f..7a3b59f42 100644 --- a/include/Nazara/Core/Color.hpp +++ b/include/Nazara/Core/Color.hpp @@ -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; diff --git a/include/Nazara/Core/Lock.hpp b/include/Nazara/Core/LockGuard.hpp similarity index 62% rename from include/Nazara/Core/Lock.hpp rename to include/Nazara/Core/LockGuard.hpp index 62e3707a2..c9397bc2d 100644 --- a/include/Nazara/Core/Lock.hpp +++ b/include/Nazara/Core/LockGuard.hpp @@ -4,21 +4,21 @@ #pragma once -#ifndef NAZARA_LOCK_HPP -#define NAZARA_LOCK_HPP +#ifndef NAZARA_LOCKGUARD_HPP +#define NAZARA_LOCKGUARD_HPP #include 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 diff --git a/include/Nazara/Core/ThreadSafety.hpp b/include/Nazara/Core/ThreadSafety.hpp index 53b7e05cf..dcbc4a515 100644 --- a/include/Nazara/Core/ThreadSafety.hpp +++ b/include/Nazara/Core/ThreadSafety.hpp @@ -24,10 +24,10 @@ (NAZARA_THREADSAFETY_STRING && defined(NAZARA_CLASS_STRING)) || \ (NAZARA_THREADSAFETY_STRINGSTREAM && defined(NAZARA_CLASS_STRINGSTREAM))) - #include + #include #include - #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(); diff --git a/include/Nazara/Renderer/Renderer.hpp b/include/Nazara/Renderer/Renderer.hpp index f2aa3d76c..6b509ece0 100644 --- a/include/Nazara/Renderer/Renderer.hpp +++ b/include/Nazara/Renderer/Renderer.hpp @@ -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); diff --git a/include/Nazara/Utility/Image.hpp b/include/Nazara/Utility/Image.hpp index c77ad76d3..aafbb72c1 100644 --- a/include/Nazara/Utility/Image.hpp +++ b/include/Nazara/Utility/Image.hpp @@ -50,9 +50,7 @@ struct NzImageParams } }; -///TODO: Animations ? ///TODO: Filtres -///TODO: Mipmaps class NAZARA_API NzImage : public NzResource, public NzResourceLoader { @@ -70,20 +68,23 @@ class NAZARA_API NzImage : public NzResource, public NzResourceLoader(src), static_cast(src) + GetBPP(srcFormat), static_cast(dst)); + if (!func(static_cast(src), static_cast(src) + GetBPP(srcFormat), static_cast(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(start), static_cast(end), static_cast(dst)); + if (!func(static_cast(start), static_cast(end), static_cast(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"; diff --git a/include/Nazara/Utility/ResourceLoader.inl b/include/Nazara/Utility/ResourceLoader.inl index dc1e60e01..ccc3cae0e 100644 --- a/include/Nazara/Utility/ResourceLoader.inl +++ b/include/Nazara/Utility/ResourceLoader.inl @@ -35,14 +35,20 @@ bool NzResourceLoader::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::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::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::UnregisterResourceFileLoader(const NzSt } } } - //s_fileLoaders.erase(std::make_pair(ext, loadFile)); } template diff --git a/src/Nazara/Core/Lock.cpp b/src/Nazara/Core/LockGuard.cpp similarity index 72% rename from src/Nazara/Core/Lock.cpp rename to src/Nazara/Core/LockGuard.cpp index a48fe13a5..34f04fd16 100644 --- a/src/Nazara/Core/Lock.cpp +++ b/src/Nazara/Core/LockGuard.cpp @@ -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 +#include #include #include -NzLock::NzLock(NzMutex& mutex) : +NzLockGuard::NzLockGuard(NzMutex& mutex) : m_mutex(mutex) { m_mutex.Lock(); } -NzLock::~NzLock() +NzLockGuard::~NzLockGuard() { m_mutex.Unlock(); } diff --git a/src/Nazara/Renderer/GLSLShader.cpp b/src/Nazara/Renderer/GLSLShader.cpp index 624c33fc9..eda9240e8 100644 --- a/src/Nazara/Renderer/GLSLShader.cpp +++ b/src/Nazara/Renderer/GLSLShader.cpp @@ -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; diff --git a/src/Nazara/Renderer/RenderWindow.cpp b/src/Nazara/Renderer/RenderWindow.cpp index 5d3bf24f2..38be6c833 100644 --- a/src/Nazara/Renderer/RenderWindow.cpp +++ b/src/Nazara/Renderer/RenderWindow.cpp @@ -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)) { diff --git a/src/Nazara/Renderer/Renderer.cpp b/src/Nazara/Renderer/Renderer.cpp index 9d5f660d5..6daae067c 100644 --- a/src/Nazara/Renderer/Renderer.cpp +++ b/src/Nazara/Renderer/Renderer.cpp @@ -4,6 +4,7 @@ #include // Pour éviter une redéfinition de WIN32_LEAN_AND_MEAN #include +#include #include #include #include @@ -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 diff --git a/src/Nazara/Renderer/Win32/ContextImpl.cpp b/src/Nazara/Renderer/Win32/ContextImpl.cpp index 071545de5..c9abbac2c 100644 --- a/src/Nazara/Renderer/Win32/ContextImpl.cpp +++ b/src/Nazara/Renderer/Win32/ContextImpl.cpp @@ -7,7 +7,7 @@ #include #include #include -#include +#include #include #include #include @@ -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()); diff --git a/src/Nazara/Utility/Image.cpp b/src/Nazara/Utility/Image.cpp index 2ede746b5..e23d24cbd 100644 --- a/src/Nazara/Utility/Image.cpp +++ b/src/Nazara/Utility/Image.cpp @@ -6,6 +6,7 @@ #include #include #include +#include #include 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::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); diff --git a/src/Nazara/Utility/Loaders/STB.cpp b/src/Nazara/Utility/Loaders/STB.cpp index d4910e6ef..e6b42ba6f 100644 --- a/src/Nazara/Utility/Loaders/STB.cpp +++ b/src/Nazara/Utility/Loaders/STB.cpp @@ -120,6 +120,7 @@ namespace } resource->Update(ptr); + stbi_image_free(ptr); if (stbiFormat == STBI_default && parameters.loadFormat != nzPixelFormat_Undefined) diff --git a/src/Nazara/Utility/PixelFormat.cpp b/src/Nazara/Utility/PixelFormat.cpp index 9723b970d..84685f296 100644 --- a/src/Nazara/Utility/PixelFormat.cpp +++ b/src/Nazara/Utility/PixelFormat.cpp @@ -8,15 +8,23 @@ #include #include -///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(const nzUInt8* start, const nzUInt8* end, nzUInt8* dst) { + nzUInt16* ptr = reinterpret_cast(dst); while (start < end) { - *dst++ = ((c8to4(start[2])) << 4) | c8to4(start[1]); - *dst++ = ((c8to4(start[0])) << 4) | 0x0F; + *ptr = (static_cast(c8to4(start[2])) << 12) | + (static_cast(c8to4(start[1])) << 8) | + (static_cast(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(dst); while (start < end) { - *ptr++ = (static_cast(c8to5(start[2])) << 11) | - (static_cast(c8to5(start[1])) << 6) | - (static_cast(c8to5(start[0])) << 1) | - 0x1; + *ptr = (static_cast(c8to5(start[2])) << 11) | + (static_cast(c8to5(start[1])) << 6) | + (static_cast(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(const nzUInt8* start, const nzUInt8* end, nzUInt8* dst) { + nzUInt16* ptr = reinterpret_cast(dst); while (start < end) { - *dst++ = (c8to4(start[2]) << 4) | c8to4(start[1]); - *dst++ = (c8to4(start[0]) << 4) | c8to4(start[3]); + *ptr = (static_cast(c8to4(start[2])) << 12) | + (static_cast(c8to4(start[1])) << 8) | + (static_cast(c8to4(start[0])) << 4) | + (static_cast(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(dst); while (start < end) { - *ptr++ = (static_cast(c8to5(start[2])) << 11) | - (static_cast(c8to5(start[1])) << 6) | - (static_cast(c8to5(start[0])) << 1) | - ((start[3] == 0xFF) ? 1 : 0); + *ptr = (static_cast(c8to5(start[2])) << 11) | + (static_cast(c8to5(start[1])) << 6) | + (static_cast(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(const nzUInt8* start, const nzUInt8* end, nzUInt8* dst) { + nzUInt16* ptr = reinterpret_cast(dst); while (start < end) { - nzUInt8 l = c8to4(start[0]); + nzUInt16 l = static_cast(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(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(const nzUInt8* start, const nzUInt8* end, nzUInt8* dst) { + nzUInt16* ptr = reinterpret_cast(dst); while (start < end) { - nzUInt8 l = c8to4(start[0]); + nzUInt16 l = static_cast(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(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(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(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(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(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(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(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(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(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(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(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(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(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(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(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(const nzUInt8* start, const nzUInt8* end, nzUInt8* dst) { + nzUInt16* ptr = reinterpret_cast(dst); while (start < end) { nzUInt16 pixel = *reinterpret_cast(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(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(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(const nzUInt8* start, const nzUInt8* end, nzUInt8* dst) { + nzUInt16* ptr = reinterpret_cast(dst); while (start < end) { - *dst++ = (c8to4(start[0]) << 4) | c8to4(start[1]); - *dst++ = (c8to4(start[2]) << 4) | 0x0F; + *ptr = (static_cast(c8to4(start[0])) << 12) | + (static_cast(c8to4(start[1])) << 8) | + (static_cast(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(dst); while (start < end) { - *ptr++ = (static_cast(c8to5(start[0])) << 11) | - (static_cast(c8to5(start[1])) << 6) | - (static_cast(c8to5(start[2])) << 1) | - 0x1; + *ptr = (static_cast(c8to5(start[0])) << 11) | + (static_cast(c8to5(start[1])) << 6) | + (static_cast(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(const nzUInt8* start, const nzUInt8* end, nzUInt8* dst) { + nzUInt16* ptr = reinterpret_cast(dst); while (start < end) { - *dst++ = (c8to4(start[0]) << 4) | c8to4(start[1]); - *dst++ = (c8to4(start[2]) << 4) | c8to4(start[3]); + *ptr = (static_cast(c8to4(start[0])) << 12) | + (static_cast(c8to4(start[1])) << 8) | + (static_cast(c8to4(start[2])) << 4) | + (static_cast(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(dst); while (start < end) { - *ptr++ = (static_cast(c8to5(start[0])) << 11) | - (static_cast(c8to5(start[1])) << 6) | - (static_cast(c8to5(start[2])) << 1) | - ((start[3] == 0xFF) ? 1 : 0); + *ptr = (static_cast(c8to5(start[0])) << 11) | + (static_cast(c8to5(start[1])) << 6) | + (static_cast(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(); /**********************************DXT1***********************************/ - ///TODO + ///TODO: Décompresseur DXT1 /* RegisterConverter(); RegisterConverter(); @@ -999,7 +1162,7 @@ bool NzPixelFormat::Initialize() */ /**********************************DXT3***********************************/ - ///TODO + ///TODO: Décompresseur DXT3 /* RegisterConverter(); RegisterConverter(); @@ -1022,7 +1185,7 @@ bool NzPixelFormat::Initialize() */ /**********************************DXT5***********************************/ - ///TODO + ///TODO: Décompresseur DXT5 /* RegisterConverter(); RegisterConverter(); @@ -1091,7 +1254,6 @@ bool NzPixelFormat::Initialize() RegisterConverter(); RegisterConverter(); RegisterConverter();*/ - RegisterConverter(); RegisterConverter(); RegisterConverter(); RegisterConverter(); @@ -1110,7 +1272,6 @@ bool NzPixelFormat::Initialize() RegisterConverter(); RegisterConverter();*/ RegisterConverter(); - RegisterConverter(); RegisterConverter(); RegisterConverter(); diff --git a/src/Nazara/Utility/Window.cpp b/src/Nazara/Utility/Window.cpp index b8425bd7e..dbe29b835 100644 --- a/src/Nazara/Utility/Window.cpp +++ b/src/Nazara/Utility/Window.cpp @@ -4,7 +4,7 @@ #include #include -#include +#include #include #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()) {