diff --git a/build/scripts/module/renderer.lua b/build/scripts/module/renderer.lua index 872e48798..4945e717e 100644 --- a/build/scripts/module/renderer.lua +++ b/build/scripts/module/renderer.lua @@ -1,6 +1,5 @@ project "NazaraRenderer" -defines "NAZARA_RENDERER_OPENGL" links "gdi32" links "opengl32" links "winmm" diff --git a/include/Nazara/Core/String.hpp b/include/Nazara/Core/String.hpp index 0d85c4e9f..43d3d9680 100644 --- a/include/Nazara/Core/String.hpp +++ b/include/Nazara/Core/String.hpp @@ -9,8 +9,7 @@ #include #include -#include -#include +#include #include #include diff --git a/include/Nazara/Math/Cube.hpp b/include/Nazara/Math/Cube.hpp new file mode 100644 index 000000000..bbc98dae4 --- /dev/null +++ b/include/Nazara/Math/Cube.hpp @@ -0,0 +1,58 @@ +// Copyright (C) 2012 Jérôme Leclercq +// This file is part of the "Nazara Engine". +// For conditions of distribution and use, see copyright notice in Config.hpp + +#pragma once + +#ifndef NAZARA_CUBE_HPP +#define NAZARA_CUBE_HPP + +#include +#include + +template +class NzCube +{ + public: + NzCube(); + NzCube(T X, T Y, T Z, T Width, T Height, T Depth); + NzCube(T cube[6]); + template explicit NzCube(const NzCube& rect); + NzCube(const NzCube& rect) = default; + ~NzCube() = default; + + bool Contains(T X, T Y, T Z) const; + bool Contains(const NzVector3& point) const; + bool Contains(const NzCube& rect) const; + + void ExtendTo(const NzVector3& point); + void ExtendTo(const NzCube& rect); + + NzVector3 GetCenter() const; + + bool Intersect(const NzCube& rect) const; + bool Intersect(const NzCube& rect, NzCube& intersection) const; + + bool IsValid() const; + + NzString ToString() const; + + operator NzString() const; + + T& operator[](unsigned int i); + T operator[](unsigned int i) const; + + T x, y, z, width, height, depth; +}; + +template +std::ostream& operator<<(std::ostream& out, const NzCube& vec); + +typedef NzCube NzCubed; +typedef NzCube NzCubef; +typedef NzCube NzCubei; +typedef NzCube NzCubeui; + +#include + +#endif // NAZARA_CUBE_HPP diff --git a/include/Nazara/Math/Cube.inl b/include/Nazara/Math/Cube.inl new file mode 100644 index 000000000..f281dc824 --- /dev/null +++ b/include/Nazara/Math/Cube.inl @@ -0,0 +1,183 @@ +// Copyright (C) 2012 Jérôme Leclercq +// This file is part of the "Nazara Engine". +// For conditions of distribution and use, see copyright notice in Config.hpp + +#include +#include +#include + +template +NzCube::NzCube() +{ +} + +template +NzCube::NzCube(T X, T Y, T Z, T Width, T Height, T Depth) : +x(X), +y(Y), +z(Z), +width(Width), +height(Height), +depth(Depth) +{ +} + +template +NzCube::NzCube(T vec[6]) : +x(vec[0]), +y(vec[1]), +z(vec[2]), +width(vec[3]), +height(vec[4]), +depth(vec[5]) +{ +} + +template +template +NzCube::NzCube(const NzCube& rect) : +x(static_cast(rect.x)), +y(static_cast(rect.y)), +z(static_cast(rect.z)), +width(static_cast(rect.width)), +height(static_cast(rect.height)), +depth(static_cast(rect.depth)) +{ +} + +template +bool NzCube::Contains(T X, T Y, T Z) const +{ + return X >= x && X < x+width && + Y >= y && Y < y+height && + Z >= z && Z < z+depth; +} + +template +bool NzCube::Contains(const NzVector3& point) const +{ + return Contains(point.x, point.y, point.z); +} + +template +bool NzCube::Contains(const NzCube& rect) const +{ + return Contains(rect.x, rect.y, rect.z) && + Contains(rect.x + rect.width, rect.y + rect.height, rect.z + rect.depth); +} + +template +void NzCube::ExtendTo(const NzVector3& point) +{ + x = std::min(x, point.x); + y = std::min(y, point.y); + z = std::min(z, point.z); + width = std::max(x+width, point.x)-x; + height = std::max(y+height, point.x)-y; + depth = std::max(z+depth, point.x)-z; +} + +template +void NzCube::ExtendTo(const NzCube& rect) +{ + x = std::min(x, rect.x); + y = std::min(y, rect.y); + z = std::min(y, rect.z); + width = std::max(x+width, rect.x+rect.width)-x; + height = std::max(x+height, rect.y+rect.height)-y; + depth = std::max(x+depth, rect.z+rect.depth)-z; +} + +template +NzVector3 NzCube::GetCenter() const +{ + return NzVector3((x+width)/2, (y+height)/2, (z+depth)/2); +} + +template +bool NzCube::Intersect(const NzCube& rect) const +{ + NzCube intersection; // Optimisé par le compilateur + return Intersect(rect, intersection); +} + +template +bool NzCube::Intersect(const NzCube& rect, NzCube& intersection) const +{ + T left = std::max(x, rect.x); + T right = std::min(x+width, rect.x+rect.width); + T top = std::max(y, rect.y); + T bottom = std::min(y+height, rect.y+rect.height); + T up = std::max(z, rect.z); + T down = std::min(z+depth, rect.z+rect.depth); + + if (left < right && top < bottom && up < down) + { + intersection.x = left; + intersection.y = top; + intersection.z = up; + intersection.width = right-left; + intersection.height = bottom-top; + intersection.depth = down-up; + + return true; + } + else + return false; +} + +template +bool NzCube::IsValid() const +{ + return width > 0 && height > 0 && depth > 0; +} + +template +NzString NzCube::ToString() const +{ + NzStringStream ss; + + return ss << "Cube(" << x << ", " << y << ", " << z << ", " << width << ", " << height << ", " << depth << ')'; +} + +template +NzCube::operator NzString() const +{ + return ToString(); +} + +template +T& NzCube::operator[](unsigned int i) +{ + if (i >= 6) + { + NzStringStream ss; + ss << __FILE__ << ':' << __LINE__ << ": Index out of range (" << i << " >= 4)"; + + throw std::domain_error(ss.ToString()); + } + + return *(&x+i); +} + +template +T NzCube::operator[](unsigned int i) const +{ + if (i >= 6) + { + NzStringStream ss; + ss << __FILE__ << ':' << __LINE__ << ": Index out of range (" << i << " >= 4)"; + + throw std::domain_error(ss.ToString()); + } + + return *(&x+i); +} + +template +std::ostream& operator<<(std::ostream& out, const NzCube& rect) +{ + return out << rect.ToString(); +} + +#include diff --git a/include/Nazara/Math/Quaternion.hpp b/include/Nazara/Math/Quaternion.hpp index 4d98f8e34..a36a7c4e6 100644 --- a/include/Nazara/Math/Quaternion.hpp +++ b/include/Nazara/Math/Quaternion.hpp @@ -47,13 +47,11 @@ template class NzQuaternion //NzMatrix3 ToRotationMatrix() const; NzString ToString() const; - NzQuaternion operator+(const NzQuaternion& quat) const; NzQuaternion operator*(const NzQuaternion& quat) const; NzVector3 operator*(const NzVector3& vec) const; NzQuaternion operator*(T scale) const; NzQuaternion operator/(const NzQuaternion& quat) const; - NzQuaternion operator+=(const NzQuaternion& quat); NzQuaternion operator*=(const NzQuaternion& quat); NzQuaternion operator*=(T scale); NzQuaternion operator/=(const NzQuaternion& quat); diff --git a/include/Nazara/Math/Quaternion.inl b/include/Nazara/Math/Quaternion.inl index 09c7bd0c0..1017798df 100644 --- a/include/Nazara/Math/Quaternion.inl +++ b/include/Nazara/Math/Quaternion.inl @@ -76,17 +76,21 @@ double NzQuaternion::Magnitude() const template double NzQuaternion::Normalize() { - double length = Magnitude(); + T squaredLength = SquaredMagnitude(); - if (length != 0.0) + if (std::fabs(squaredLength) > 0.00001 && std::fabs(squaredLength - 1.0) > 0.00001) { + double length = std::sqrt(squaredLength); + w /= length; x /= length; y /= length; z /= length; - } - return length; + return length; + } + else + return std::sqrt(squaredLength); } template @@ -102,6 +106,8 @@ void NzQuaternion::Set(T W, T X, T Y, T Z) x = X; y = Y; z = Z; + + Normalize(); } template @@ -111,6 +117,8 @@ void NzQuaternion::Set(T quat[4]) x = quat[1]; y = quat[2]; z = quat[3]; + + Normalize(); } template @@ -195,35 +203,32 @@ NzString NzQuaternion::ToString() const return ss << "Quaternion(" << w << " | " << x << ", " << y << ", " << z << ')'; } -template -NzQuaternion NzQuaternion::operator+(const NzQuaternion& quat) const -{ - return NzQuaternion(w + quat.w, - x + quat.x, - y + quat.y, - z + quat.z); -} - template NzQuaternion NzQuaternion::operator*(const NzQuaternion& quat) const { - return NzQuaternion(w * quat.w - x * quat.x - y * quat.y - z * quat.z, - w * quat.x + x * quat.w + y * quat.z - z * quat.y, - w * quat.y + y * quat.w + z * quat.x - x * quat.z, - w * quat.z + z * quat.w + x * quat.y - y * quat.x); + NzQuaternion result(w * quat.w - x * quat.x - y * quat.y - z * quat.z, + w * quat.x + x * quat.w + y * quat.z - z * quat.y, + w * quat.y + y * quat.w + z * quat.x - x * quat.z, + w * quat.z + z * quat.w + x * quat.y - y * quat.x); + + result.Normalize(); + + return result; } template NzVector3 NzQuaternion::operator*(const NzVector3& vec) const { - NzVector3 uv, uuv; - NzVector3 qvec(x, y, z); - uv = qvec.CrossProduct(vec); - uuv = qvec.CrossProduct(uv); - uv *= 2.0 * w; - uuv *= 2.0; + NzVector3 normal(vec); + normal.Normalise(); + + NzQuaternion qvec(0.0, normal.x, normal.y, normal.z); + NzQuaternion result; + + result = operator*(qvec * GetConjugate()); + + return NzVector3(result.x, result.y, result.z); - return vec + uv + uuv; } template @@ -241,24 +246,12 @@ NzQuaternion NzQuaternion::operator/(const NzQuaternion& quat) const return GetConjugate(quat) * (*this); } -template -NzQuaternion NzQuaternion::operator+=(const NzQuaternion& quat) -{ - w += quat.w; - x += quat.x; - y += quat.y; - z += quat.z; - - return *this; -} - template NzQuaternion NzQuaternion::operator*=(const NzQuaternion& quat) { NzQuaternion q(*this); - operator=(q * quat); - return *this; + return operator=(q * quat); } template @@ -276,9 +269,8 @@ template NzQuaternion NzQuaternion::operator/=(const NzQuaternion& quat) { NzQuaternion q(*this); - operator=(q / quat); - return *this; + return operator=(q / quat); } template diff --git a/include/Nazara/Math/Rect.hpp b/include/Nazara/Math/Rect.hpp index b0ac31d52..4669c801d 100644 --- a/include/Nazara/Math/Rect.hpp +++ b/include/Nazara/Math/Rect.hpp @@ -28,6 +28,8 @@ class NzRect void ExtendTo(const NzVector2& point); void ExtendTo(const NzRect& rect); + NzVector2 GetCenter() const; + bool Intersect(const NzRect& rect) const; bool Intersect(const NzRect& rect, NzRect& intersection) const; diff --git a/include/Nazara/Math/Rect.inl b/include/Nazara/Math/Rect.inl index 964708361..97dab6292 100644 --- a/include/Nazara/Math/Rect.inl +++ b/include/Nazara/Math/Rect.inl @@ -65,7 +65,7 @@ void NzRect::ExtendTo(const NzVector2& point) x = std::min(x, point.x); y = std::min(y, point.y); width = std::max(x+width, point.x)-x; - height = std::max(x+width, point.x)-y; + height = std::max(y+height, point.y)-y; } template @@ -74,7 +74,13 @@ void NzRect::ExtendTo(const NzRect& rect) x = std::min(x, rect.x); y = std::min(y, rect.y); width = std::max(x+width, rect.x+rect.width)-x; - height = std::max(x+width, rect.x+rect.height)-y; + height = std::max(x+height, rect.y+rect.height)-y; +} + +template +NzVector2 NzRect::GetCenter() const +{ + return NzVector2((x+width)/2, (y+height)/2); } template @@ -97,7 +103,7 @@ bool NzRect::Intersect(const NzRect& rect, NzRect& intersection) const intersection.x = left; intersection.y = top; intersection.width = right-left; - intersection.height = top-bottom; + intersection.height = bottom-top; return true; } diff --git a/include/Nazara/Math/Vector2.hpp b/include/Nazara/Math/Vector2.hpp index e550890c4..bd2c54017 100644 --- a/include/Nazara/Math/Vector2.hpp +++ b/include/Nazara/Math/Vector2.hpp @@ -33,7 +33,8 @@ template class NzVector2 NzString ToString() const; - operator NzString() const; + operator T*(); + operator const T*() const; T& operator[](unsigned int i); T operator[](unsigned int i) const; diff --git a/include/Nazara/Math/Vector2.inl b/include/Nazara/Math/Vector2.inl index f01f14146..3026f860b 100644 --- a/include/Nazara/Math/Vector2.inl +++ b/include/Nazara/Math/Vector2.inl @@ -136,9 +136,15 @@ NzString NzVector2::ToString() const } template -NzVector2::operator NzString() const +NzVector2::operator T*() { - return ToString(); + return &x; +} + +template +NzVector2::operator const T*() const +{ + return &x; } template diff --git a/include/Nazara/Math/Vector3.hpp b/include/Nazara/Math/Vector3.hpp index b658960c3..bd0dc9b35 100644 --- a/include/Nazara/Math/Vector3.hpp +++ b/include/Nazara/Math/Vector3.hpp @@ -34,7 +34,8 @@ template class NzVector3 NzString ToString() const; - operator NzString() const; + operator T*(); + operator const T*() const; T& operator[](unsigned int i); T operator[](unsigned int i) const; diff --git a/include/Nazara/Math/Vector3.inl b/include/Nazara/Math/Vector3.inl index 91cec9fad..40e1cabb7 100644 --- a/include/Nazara/Math/Vector3.inl +++ b/include/Nazara/Math/Vector3.inl @@ -153,9 +153,15 @@ NzString NzVector3::ToString() const } template -NzVector3::operator NzString() const +NzVector3::operator T*() { - return ToString(); + return &x; +} + +template +NzVector3::operator const T*() const +{ + return &x; } template diff --git a/include/Nazara/Math/Vector4.hpp b/include/Nazara/Math/Vector4.hpp index 2f8d4860e..afd108acb 100644 --- a/include/Nazara/Math/Vector4.hpp +++ b/include/Nazara/Math/Vector4.hpp @@ -28,7 +28,8 @@ template class NzVector4 NzString ToString() const; - operator NzString() const; + operator T*(); + operator const T*() const; T& operator[](unsigned int i); T operator[](unsigned int i) const; diff --git a/include/Nazara/Math/Vector4.inl b/include/Nazara/Math/Vector4.inl index 9073d37b0..3ee1f4165 100644 --- a/include/Nazara/Math/Vector4.inl +++ b/include/Nazara/Math/Vector4.inl @@ -120,9 +120,15 @@ NzString NzVector4::ToString() const } template -NzVector4::operator NzString() const +NzVector4::operator T*() { - return ToString(); + return &x; +} + +template +NzVector4::operator const T*() const +{ + return &x; } template diff --git a/include/Nazara/Prerequesites.hpp b/include/Nazara/Prerequesites.hpp index 2a3fe5140..8acfc19f5 100644 --- a/include/Nazara/Prerequesites.hpp +++ b/include/Nazara/Prerequesites.hpp @@ -17,22 +17,27 @@ #include ///TODO: Rajouter des tests d'identification de compilateurs +// NAZARA_THREADLOCAL n'existe qu'en attendant le support complet de thread_local #if defined(_MSC_VER) #define NAZARA_COMPILER_MSVC #define NAZARA_DEPRECATED(txt) __declspec(deprecated(txt)) #define NAZARA_FUNCTION __FUNCSIG__ + #define NAZARA_THREADLOCAL __declspec(thread) #elif defined(__GNUC__) #define NAZARA_COMPILER_GCC #define NAZARA_DEPRECATED(txt) __attribute__((__deprecated__(txt))) #define NAZARA_FUNCTION __PRETTY_FUNCTION__ + #define NAZARA_THREADLOCAL __thread #elif defined(__BORLANDC__) #define NAZARA_COMPILER_BORDLAND #define NAZARA_DEPRECATED(txt) #define NAZARA_FUNCTION __FUNC__ + #define NAZARA_THREADLOCAL __declspec(thread) #else #define NAZARA_COMPILER_UNKNOWN #define NAZARA_DEPRECATED(txt) #define NAZARA_FUNCTION __func__ // __func__ est standard depuis le C++11 + #define NAZARA_THREADLOCAL thread_local #error This compiler is not fully supported #endif diff --git a/include/Nazara/Renderer/Buffer.hpp b/include/Nazara/Renderer/Buffer.hpp index 8176f1c61..c023ade1c 100644 --- a/include/Nazara/Renderer/Buffer.hpp +++ b/include/Nazara/Renderer/Buffer.hpp @@ -11,12 +11,12 @@ #include #include -enum nzBufferLock +enum nzBufferAccess { - nzBufferLock_DiscardAndWrite, - nzBufferLock_ReadOnly, - nzBufferLock_ReadWrite, - nzBufferLock_WriteOnly + nzBufferAccess_DiscardAndWrite, + nzBufferAccess_ReadOnly, + nzBufferAccess_ReadWrite, + nzBufferAccess_WriteOnly }; enum nzBufferStorage @@ -68,8 +68,8 @@ class NAZARA_API NzBuffer : public NzResource, NzNonCopyable bool IsHardware() const; - void* Lock(nzBufferLock lock, unsigned int offset = 0, unsigned int length = 0); - bool Unlock(); + void* Map(nzBufferAccess access, unsigned int offset = 0, unsigned int length = 0); + bool Unmap(); static bool IsSupported(nzBufferStorage storage); diff --git a/include/Nazara/Renderer/Context.hpp b/include/Nazara/Renderer/Context.hpp index 9c489c390..08da75937 100644 --- a/include/Nazara/Renderer/Context.hpp +++ b/include/Nazara/Renderer/Context.hpp @@ -30,11 +30,12 @@ class NAZARA_API NzContext bool SetActive(bool active); void SwapBuffers(); - static const NzContext* GetCurrent(); + static bool EnsureContext(); + static NzContext* GetCurrent(); static const NzContext* GetReference(); - static const NzContext* GetThreadContext(); - static bool InitializeReference(); - static void UninitializeReference(); + static NzContext* GetThreadContext(); + static bool Initialize(); + static void Uninitialize(); private: NzContextParameters m_parameters; diff --git a/include/Nazara/Renderer/IndexBuffer.hpp b/include/Nazara/Renderer/IndexBuffer.hpp index a7b4a9015..b3a50b1d0 100644 --- a/include/Nazara/Renderer/IndexBuffer.hpp +++ b/include/Nazara/Renderer/IndexBuffer.hpp @@ -30,8 +30,8 @@ class NAZARA_API NzIndexBuffer bool IsHardware() const; bool IsSequential() const; - void* Lock(nzBufferLock lock, unsigned int offset = 0, unsigned int length = 0); - bool Unlock(); + void* Map(nzBufferAccess access, unsigned int offset = 0, unsigned int length = 0); + bool Unmap(); private: NzBuffer* m_buffer; diff --git a/include/Nazara/Renderer/OpenGL.hpp b/include/Nazara/Renderer/OpenGL.hpp index 8b2761c84..0deb0b068 100644 --- a/include/Nazara/Renderer/OpenGL.hpp +++ b/include/Nazara/Renderer/OpenGL.hpp @@ -37,6 +37,7 @@ class NAZARA_API NzOpenGL DebugOutput, FP64, FrameBufferObject, + SeparateShaderObjects, Texture3D, TextureCompression_s3tc, TextureStorage, @@ -131,6 +132,17 @@ NAZARA_API extern PFNGLLINKPROGRAMPROC glLinkProgram; NAZARA_API extern PFNGLMAPBUFFERPROC glMapBuffer; NAZARA_API extern PFNGLMAPBUFFERRANGEPROC glMapBufferRange; NAZARA_API extern PFNGLPOLYGONMODEPROC glPolygonMode; +NAZARA_API extern PFNGLPROGRAMUNIFORM1DPROC glProgramUniform1d; +NAZARA_API extern PFNGLPROGRAMUNIFORM1FPROC glProgramUniform1f; +NAZARA_API extern PFNGLPROGRAMUNIFORM1IPROC glProgramUniform1i; +NAZARA_API extern PFNGLPROGRAMUNIFORM2DVPROC glProgramUniform2dv; +NAZARA_API extern PFNGLPROGRAMUNIFORM2FVPROC glProgramUniform2fv; +NAZARA_API extern PFNGLPROGRAMUNIFORM3DVPROC glProgramUniform3dv; +NAZARA_API extern PFNGLPROGRAMUNIFORM3FVPROC glProgramUniform3fv; +NAZARA_API extern PFNGLPROGRAMUNIFORM4DVPROC glProgramUniform4dv; +NAZARA_API extern PFNGLPROGRAMUNIFORM4FVPROC glProgramUniform4fv; +NAZARA_API extern PFNGLPROGRAMUNIFORMMATRIX4DVPROC glProgramUniformMatrix4dv; +NAZARA_API extern PFNGLPROGRAMUNIFORMMATRIX4FVPROC glProgramUniformMatrix4fv; NAZARA_API extern PFNGLREADPIXELSPROC glReadPixels; NAZARA_API extern PFNGLRENDERBUFFERSTORAGEPROC glRenderbufferStorage; NAZARA_API extern PFNGLSCISSORPROC glScissor; diff --git a/include/Nazara/Renderer/RenderTarget.hpp b/include/Nazara/Renderer/RenderTarget.hpp index 1b5ce9858..8a065a31c 100644 --- a/include/Nazara/Renderer/RenderTarget.hpp +++ b/include/Nazara/Renderer/RenderTarget.hpp @@ -21,15 +21,16 @@ class NAZARA_API NzRenderTarget NzRenderTarget() = default; virtual ~NzRenderTarget(); - virtual bool CanActivate() const = 0; - - virtual NzRenderTargetParameters GetRenderTargetParameters() const = 0; - - #ifdef NAZARA_RENDERER_OPENGL + #ifndef NAZARA_RENDERER_COMMON virtual bool HasContext() const = 0; #endif + virtual unsigned int GetHeight() const = 0; + virtual NzRenderTargetParameters GetParameters() const = 0; + virtual unsigned int GetWidth() const = 0; + bool IsActive() const; + virtual bool IsValid() const = 0; bool SetActive(bool active); diff --git a/include/Nazara/Renderer/RenderWindow.hpp b/include/Nazara/Renderer/RenderWindow.hpp index 2c43579ec..fabd16265 100644 --- a/include/Nazara/Renderer/RenderWindow.hpp +++ b/include/Nazara/Renderer/RenderWindow.hpp @@ -10,13 +10,10 @@ #define NAZARA_RENDERWINDOW_HPP #include -#include #include -#include - -#ifndef NAZARA_RENDERER_COMMON #include -#endif +#include +#include class NzContext; class NzImage; @@ -25,16 +22,12 @@ struct NzContextParameters; class NAZARA_API NzRenderWindow : public NzRenderTarget, public NzWindow { - friend class NzTexture; - public: NzRenderWindow(); NzRenderWindow(NzVideoMode mode, const NzString& title, nzUInt32 style = NzWindow::Default, const NzContextParameters& parameters = NzContextParameters()); NzRenderWindow(NzWindowHandle handle, const NzContextParameters& parameters = NzContextParameters()); virtual ~NzRenderWindow(); - bool CanActivate() const; - bool CopyToImage(NzImage* image); ///TODO: Const bool CopyToTexture(NzTexture* texture); ///TODO: Const @@ -45,14 +38,20 @@ class NAZARA_API NzRenderWindow : public NzRenderTarget, public NzWindow void EnableVerticalSync(bool enabled); - NzRenderTargetParameters GetRenderTargetParameters() const; - #ifndef NAZARA_RENDERER_COMMON NzContextParameters GetContextParameters() const; + #endif + unsigned int GetHeight() const; + NzRenderTargetParameters GetParameters() const; + unsigned int GetWidth() const; + + #ifndef NAZARA_RENDERER_COMMON bool HasContext() const; #endif + bool IsValid() const; + protected: bool Activate(); diff --git a/include/Nazara/Renderer/Renderer.hpp b/include/Nazara/Renderer/Renderer.hpp index aab95ab7c..6296f22f5 100644 --- a/include/Nazara/Renderer/Renderer.hpp +++ b/include/Nazara/Renderer/Renderer.hpp @@ -8,6 +8,7 @@ #define NAZARA_RENDERER_HPP #include +#include #include #include @@ -87,7 +88,6 @@ enum nzRendererComparison enum nzRendererParameter { - nzRendererParameter_AlphaTest, nzRendererParameter_Blend, nzRendererParameter_ColorWrite, nzRendererParameter_DepthTest, @@ -135,10 +135,12 @@ class NAZARA_API NzRenderer unsigned int GetMaxTextureUnits() const; NzShader* GetShader() const; NzRenderTarget* GetTarget() const; + NzRectui GetViewport() const; bool HasCapability(nzRendererCap capability) const; bool Initialize(); + void SetBlendFunc(nzBlendFunc src, nzBlendFunc dest); void SetClearColor(const NzColor& color); void SetClearColor(nzUInt8 r, nzUInt8 g, nzUInt8 b, nzUInt8 a = 255); void SetClearDepth(double depth); @@ -156,6 +158,7 @@ class NAZARA_API NzRenderer bool SetTarget(NzRenderTarget* target); bool SetVertexBuffer(const NzVertexBuffer* vertexBuffer); bool SetVertexDeclaration(const NzVertexDeclaration* vertexDeclaration); + void SetViewport(const NzRectui& viewport); void Uninitialize(); diff --git a/include/Nazara/Renderer/Shader.hpp b/include/Nazara/Renderer/Shader.hpp index 79d0402de..b060c9bde 100644 --- a/include/Nazara/Renderer/Shader.hpp +++ b/include/Nazara/Renderer/Shader.hpp @@ -11,6 +11,9 @@ #include #include #include +#include +#include +#include #include enum nzShaderLanguage @@ -66,6 +69,12 @@ class NAZARA_API NzShader : public NzResource, NzNonCopyable bool SendInteger(const NzString& name, int value); bool SendMatrix(const NzString& name, const NzMatrix4d& matrix); bool SendMatrix(const NzString& name, const NzMatrix4f& matrix); + bool SendVector(const NzString& name, const NzVector2d& vector); + bool SendVector(const NzString& name, const NzVector2f& vector); + bool SendVector(const NzString& name, const NzVector3d& vector); + bool SendVector(const NzString& name, const NzVector3f& vector); + bool SendVector(const NzString& name, const NzVector4d& vector); + bool SendVector(const NzString& name, const NzVector4f& vector); bool SendTexture(const NzString& name, NzTexture* texture); void Unlock(); diff --git a/include/Nazara/Renderer/Texture.hpp b/include/Nazara/Renderer/Texture.hpp index 01b69b115..98df54f38 100644 --- a/include/Nazara/Renderer/Texture.hpp +++ b/include/Nazara/Renderer/Texture.hpp @@ -39,7 +39,9 @@ class NAZARA_API NzTexture : public NzResource, NzNonCopyable explicit NzTexture(const NzImage& image); ~NzTexture(); - bool Bind(); + #ifndef NAZARA_RENDERER_COMMON + bool Bind() const; + #endif bool Create(nzImageType type, nzPixelFormat format, unsigned int width, unsigned int height, unsigned int depth = 1, nzUInt8 levelCount = 1, bool lock = false); void Destroy(); @@ -60,6 +62,7 @@ class NAZARA_API NzTexture : public NzResource, NzNonCopyable bool IsCompressed() const; bool IsCubemap() const; + bool IsTarget() const; bool IsValid() const; bool LoadFromFile(const NzString& filePath, const NzImageParams& params = NzImageParams()); @@ -76,10 +79,10 @@ class NAZARA_API NzTexture : public NzResource, NzNonCopyable bool Update(const NzImage& image, nzUInt8 level = 0); bool Update(const NzImage& image, const NzRectui& rect, unsigned int z = 0, nzUInt8 level = 0); - //bool Update(const NzImage& image, const NzCubeui& cube, nzUInt8 level = 0); + bool Update(const NzImage& image, const NzCubeui& cube, nzUInt8 level = 0); 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 Update(const nzUInt8* pixels, const NzCubeui& cube, nzUInt8 level = 0); bool UpdateFace(nzCubemapFace face, const NzImage& image, nzUInt8 level = 0); bool UpdateFace(nzCubemapFace face, const NzImage& image, const NzRectui& rect, nzUInt8 level = 0); bool UpdateFace(nzCubemapFace face, const nzUInt8* pixels, nzUInt8 level = 0); @@ -92,6 +95,8 @@ class NAZARA_API NzTexture : public NzResource, NzNonCopyable static bool IsTypeSupported(nzImageType type); private: + void SetTarget(bool isTarget); + NzTextureImpl* m_impl; }; diff --git a/include/Nazara/Renderer/VertexBuffer.hpp b/include/Nazara/Renderer/VertexBuffer.hpp index 721b32ee4..a4634d78a 100644 --- a/include/Nazara/Renderer/VertexBuffer.hpp +++ b/include/Nazara/Renderer/VertexBuffer.hpp @@ -29,8 +29,8 @@ class NAZARA_API NzVertexBuffer bool IsHardware() const; - void* Lock(nzBufferLock lock, unsigned int offset = 0, unsigned int length = 0); - bool Unlock(); + void* Map(nzBufferAccess access, unsigned int offset = 0, unsigned int length = 0); + bool Unmap(); private: NzBuffer* m_buffer; diff --git a/include/Nazara/Utility/Image.hpp b/include/Nazara/Utility/Image.hpp index 359cce0a9..296179ae5 100644 --- a/include/Nazara/Utility/Image.hpp +++ b/include/Nazara/Utility/Image.hpp @@ -10,6 +10,7 @@ #include #include #include +#include #include #include #include @@ -104,7 +105,7 @@ class NAZARA_API NzImage : public NzResource, public NzResourceLoader(src), static_cast(src) + GetBPP(srcFormat), static_cast(dst))) + if (!func(reinterpret_cast(src), reinterpret_cast(src) + GetBPP(srcFormat), reinterpret_cast(dst))) { NazaraError("Pixel format conversion from " + ToString(srcFormat) + " to " + ToString(dstFormat) + " failed"); return false; @@ -48,7 +48,7 @@ inline bool NzPixelFormat::Convert(nzPixelFormat srcFormat, nzPixelFormat dstFor { if (srcFormat == dstFormat) { - std::memcpy(dst, start, static_cast(end)-static_cast(start)); + std::memcpy(dst, start, reinterpret_cast(end)-reinterpret_cast(start)); return true; } @@ -59,7 +59,7 @@ inline bool NzPixelFormat::Convert(nzPixelFormat srcFormat, nzPixelFormat dstFor return false; } - if (!func(static_cast(start), static_cast(end), static_cast(dst))) + if (!func(reinterpret_cast(start), reinterpret_cast(end), reinterpret_cast(dst))) { NazaraError("Pixel format conversion from " + ToString(srcFormat) + " to " + ToString(dstFormat) + " failed"); return false; @@ -72,10 +72,6 @@ inline nzUInt8 NzPixelFormat::GetBPP(nzPixelFormat format) { switch (format) { - case nzPixelFormat_Count: - case nzPixelFormat_Undefined: - return 0; - case nzPixelFormat_BGR8: return 3; @@ -132,6 +128,11 @@ inline nzUInt8 NzPixelFormat::GetBPP(nzPixelFormat format) case nzPixelFormat_RGBA8: return 4; + + case nzPixelFormat_Count: + case nzPixelFormat_Undefined: + NazaraError("Invalid pixel format"); + return 0; } NazaraInternalError("Invalid pixel format"); @@ -152,9 +153,19 @@ inline bool NzPixelFormat::HasAlpha(nzPixelFormat format) case nzPixelFormat_RGBA8: return true; - default: + case nzPixelFormat_BGR8: + case nzPixelFormat_DXT1: + case nzPixelFormat_L8: + case nzPixelFormat_RGB8: return false; + + case nzPixelFormat_Count: + case nzPixelFormat_Undefined: + break; } + + NazaraError("Invalid pixel format"); + return false; } inline bool NzPixelFormat::IsCompressed(nzPixelFormat format) @@ -258,13 +269,13 @@ inline NzString NzPixelFormat::ToString(nzPixelFormat format) case nzPixelFormat_RGBA8: return "RGBA8"; - default: - NazaraInternalError("Invalid pixel format"); - case nzPixelFormat_Count: case nzPixelFormat_Undefined: - return "Invalid format"; + break; } + + NazaraError("Invalid pixel format"); + return "Invalid format"; } #include diff --git a/src/Nazara/Core/File.cpp b/src/Nazara/Core/File.cpp index d50cbae27..c7b21bab7 100644 --- a/src/Nazara/Core/File.cpp +++ b/src/Nazara/Core/File.cpp @@ -313,7 +313,7 @@ std::size_t NzFile::Read(void* buffer, std::size_t typeSize, unsigned int count) { unsigned int typeCount = byteRead/typeSize; for (unsigned int i = 0; i < typeCount; ++i) - NzByteSwap(static_cast(buffer) + i*typeSize, typeSize); + NzByteSwap(reinterpret_cast(buffer) + i*typeSize, typeSize); } return byteRead; diff --git a/src/Nazara/Core/MemoryStream.cpp b/src/Nazara/Core/MemoryStream.cpp index 17d223e6c..182d7f12e 100644 --- a/src/Nazara/Core/MemoryStream.cpp +++ b/src/Nazara/Core/MemoryStream.cpp @@ -8,7 +8,7 @@ #include NzMemoryStream::NzMemoryStream(const void* ptr, nzUInt64 size) : -m_ptr(static_cast(ptr)), +m_ptr(reinterpret_cast(ptr)), m_pos(0), m_size(size) { diff --git a/src/Nazara/Core/Win32/ThreadImpl.cpp b/src/Nazara/Core/Win32/ThreadImpl.cpp index e6a627e0b..6e8db44c6 100644 --- a/src/Nazara/Core/Win32/ThreadImpl.cpp +++ b/src/Nazara/Core/Win32/ThreadImpl.cpp @@ -67,7 +67,7 @@ void NzThreadImpl::Terminate() unsigned int _stdcall NzThreadImpl::ThreadProc(void* userdata) { - NzThread* owner = static_cast(userdata); + NzThread* owner = reinterpret_cast(userdata); NzFunctor* func = owner->m_func; HANDLE myHandle = owner->m_impl->m_thread; func->Run(); diff --git a/src/Nazara/Renderer/Buffer.cpp b/src/Nazara/Renderer/Buffer.cpp index 804d26eb0..335d13e7e 100644 --- a/src/Nazara/Renderer/Buffer.cpp +++ b/src/Nazara/Renderer/Buffer.cpp @@ -50,17 +50,17 @@ NzBuffer::~NzBuffer() bool NzBuffer::CopyContent(NzBuffer& buffer) { - void* ptr = buffer.Lock(nzBufferLock_ReadOnly); + void* ptr = buffer.Map(nzBufferAccess_ReadOnly); if (!ptr) { - NazaraError("Unable to lock source buffer"); + NazaraError("Failed to map source buffer"); return false; } bool r = Fill(ptr, 0, m_length); - if (!buffer.Unlock()) - NazaraWarning("Unable to unlock source buffer"); + if (!buffer.Unmap()) + NazaraWarning("Failed to unmap source buffer"); return r; } @@ -205,7 +205,7 @@ bool NzBuffer::IsHardware() const return m_storage == nzBufferStorage_Hardware; } -void* NzBuffer::Lock(nzBufferLock lock, unsigned int offset, unsigned int length) +void* NzBuffer::Map(nzBufferAccess access, unsigned int offset, unsigned int length) { #if NAZARA_RENDERER_SAFE if (!m_impl) @@ -221,10 +221,10 @@ void* NzBuffer::Lock(nzBufferLock lock, unsigned int offset, unsigned int length } #endif - return m_impl->Lock(lock, offset*m_typeSize, length*m_typeSize); + return m_impl->Map(access, offset*m_typeSize, length*m_typeSize); } -bool NzBuffer::Unlock() +bool NzBuffer::Unmap() { #if NAZARA_RENDERER_SAFE if (!m_impl) @@ -234,7 +234,7 @@ bool NzBuffer::Unlock() } #endif - return m_impl->Unlock(); + return m_impl->Unmap(); } bool NzBuffer::IsSupported(nzBufferStorage storage) diff --git a/src/Nazara/Renderer/BufferImpl.hpp b/src/Nazara/Renderer/BufferImpl.hpp index 74b8d835a..74795abe9 100644 --- a/src/Nazara/Renderer/BufferImpl.hpp +++ b/src/Nazara/Renderer/BufferImpl.hpp @@ -26,8 +26,8 @@ class NzBufferImpl virtual bool IsHardware() const = 0; - virtual void* Lock(nzBufferLock lock, unsigned int offset = 0, unsigned int size = 0) = 0; - virtual bool Unlock() = 0; + virtual void* Map(nzBufferAccess access, unsigned int offset = 0, unsigned int size = 0) = 0; + virtual bool Unmap() = 0; }; #endif // NAZARA_BUFFERIMPL_INCLUDED diff --git a/src/Nazara/Renderer/Context.cpp b/src/Nazara/Renderer/Context.cpp index dfd885ee3..520586671 100644 --- a/src/Nazara/Renderer/Context.cpp +++ b/src/Nazara/Renderer/Context.cpp @@ -8,6 +8,7 @@ #include #include #include +#include #if defined(NAZARA_PLATFORM_WINDOWS) #include @@ -21,9 +22,10 @@ namespace { - ///TODO: Thread-local - NzContext* currentContext = nullptr; - NzContext* threadContext = nullptr; + NAZARA_THREADLOCAL NzContext* currentContext = nullptr; + NAZARA_THREADLOCAL NzContext* threadContext = nullptr; + + std::vector contexts; void CALLBACK DebugCallback(unsigned int source, unsigned int type, unsigned int id, unsigned int severity, int length, const char* message, void* userParam) { @@ -269,7 +271,36 @@ void NzContext::SwapBuffers() m_impl->SwapBuffers(); } -const NzContext* NzContext::GetCurrent() +bool NzContext::EnsureContext() +{ + if (!currentContext) + { + if (!threadContext) + { + NzContext* context = new NzContext; + if (!context->Create()) + { + NazaraError("Failed to create context"); + delete context; + + return false; + } + + contexts.push_back(context); + + threadContext = context; + } + else if (!threadContext->SetActive(true)) + { + NazaraError("Failed to active thread context"); + return false; + } + } + + return true; +} + +NzContext* NzContext::GetCurrent() { return currentContext; } @@ -279,12 +310,14 @@ const NzContext* NzContext::GetReference() return s_reference; } -const NzContext* NzContext::GetThreadContext() +NzContext* NzContext::GetThreadContext() { + EnsureContext(); + return threadContext; } -bool NzContext::InitializeReference() +bool NzContext::Initialize() { NzContextParameters parameters; // parameters.compatibilityProfile = true; @@ -299,11 +332,21 @@ bool NzContext::InitializeReference() return false; } + // Le contexte de référence doit rester désactivé pour le partage + s_reference->SetActive(false); + + NzContextParameters::defaultShareContext = s_reference; + return true; } -void NzContext::UninitializeReference() +void NzContext::Uninitialize() { + for (NzContext* context : contexts) + delete context; + + contexts.clear(); // On supprime tous les contextes créés + delete s_reference; s_reference = nullptr; } diff --git a/src/Nazara/Renderer/GLSLShader.cpp b/src/Nazara/Renderer/GLSLShader.cpp index 4ddc12fad..7518a3643 100644 --- a/src/Nazara/Renderer/GLSLShader.cpp +++ b/src/Nazara/Renderer/GLSLShader.cpp @@ -6,6 +6,7 @@ #include #include #include +#include #include #include #include @@ -52,6 +53,14 @@ bool NzGLSLShader::Bind() } #endif + #ifdef NAZARA_DEBUG + if (NzContext::GetCurrent() == nullptr) + { + NazaraError("No active context"); + return false; + } + #endif + glUseProgram(m_program); for (auto it = m_textures.begin(); it != m_textures.end(); ++it) @@ -66,6 +75,8 @@ bool NzGLSLShader::Bind() bool NzGLSLShader::Compile() { + NzContext::EnsureContext(); + m_idCache.clear(); glLinkProgram(m_program); @@ -104,6 +115,8 @@ bool NzGLSLShader::Compile() bool NzGLSLShader::Create() { + NzContext::EnsureContext(); + m_program = glCreateProgram(); if (!m_program) { @@ -126,13 +139,13 @@ bool NzGLSLShader::Create() for (int i = 0; i < nzShaderType_Count; ++i) m_shaders[i] = 0; - m_textureFreeID = 0; - return true; } void NzGLSLShader::Destroy() { + NzContext::EnsureContext(); + for (GLuint shader : m_shaders) if (shader) glDeleteShader(shader); @@ -153,6 +166,8 @@ nzShaderLanguage NzGLSLShader::GetLanguage() const NzString NzGLSLShader::GetSourceCode(nzShaderType type) const { + NzContext::EnsureContext(); + NzString source; GLint length; @@ -172,6 +187,8 @@ GLint NzGLSLShader::GetUniformLocation(const NzString& name) const GLint id; if (it == m_idCache.end()) { + NzContext::EnsureContext(); + id = glGetUniformLocation(m_program, name.GetConstBuffer()); m_idCache[name] = id; } @@ -188,6 +205,8 @@ bool NzGLSLShader::IsLoaded(nzShaderType type) const bool NzGLSLShader::Load(nzShaderType type, const NzString& source) { + NzContext::EnsureContext(); + GLuint shader = glCreateShader(shaderType[type]); if (!shader) { @@ -244,6 +263,8 @@ bool NzGLSLShader::Lock() { if (lockedLevel++ == 0) { + NzContext::EnsureContext(); + GLint previous; glGetIntegerv(GL_CURRENT_PROGRAM, &previous); @@ -258,54 +279,168 @@ bool NzGLSLShader::Lock() bool NzGLSLShader::SendBoolean(const NzString& name, bool value) { - Lock(); - glUniform1i(GetUniformLocation(name), value); - Unlock(); + if (glProgramUniform1i) + glProgramUniform1i(m_program, GetUniformLocation(name), value); + else + { + Lock(); + glUniform1i(GetUniformLocation(name), value); + Unlock(); + } return true; } bool NzGLSLShader::SendDouble(const NzString& name, double value) { - Lock(); - glUniform1d(GetUniformLocation(name), value); - Unlock(); + if (glProgramUniform1d) + glProgramUniform1d(m_program, GetUniformLocation(name), value); + else + { + Lock(); + glUniform1d(GetUniformLocation(name), value); + Unlock(); + } return true; } bool NzGLSLShader::SendFloat(const NzString& name, float value) { - Lock(); - glUniform1f(GetUniformLocation(name), value); - Unlock(); + if (glProgramUniform1f) + glProgramUniform1f(m_program, GetUniformLocation(name), value); + else + { + Lock(); + glUniform1f(GetUniformLocation(name), value); + Unlock(); + } return true; } bool NzGLSLShader::SendInteger(const NzString& name, int value) { - Lock(); - glUniform1i(GetUniformLocation(name), value); - Unlock(); + if (glProgramUniform1i) + glProgramUniform1i(m_program, GetUniformLocation(name), value); + else + { + Lock(); + glUniform1i(GetUniformLocation(name), value); + Unlock(); + } return true; } bool NzGLSLShader::SendMatrix(const NzString& name, const NzMatrix4d& matrix) { - Lock(); - glUniformMatrix4dv(GetUniformLocation(name), 1, GL_FALSE, matrix); - Unlock(); + if (glProgramUniformMatrix4dv) + glProgramUniformMatrix4dv(m_program, GetUniformLocation(name), 1, GL_FALSE, matrix); + else + { + Lock(); + glUniformMatrix4dv(GetUniformLocation(name), 1, GL_FALSE, matrix); + Unlock(); + } return true; } bool NzGLSLShader::SendMatrix(const NzString& name, const NzMatrix4f& matrix) { - Lock(); - glUniformMatrix4fv(GetUniformLocation(name), 1, GL_FALSE, matrix); - Unlock(); + if (glProgramUniformMatrix4fv) + glProgramUniformMatrix4fv(m_program, GetUniformLocation(name), 1, GL_FALSE, matrix); + else + { + Lock(); + glUniformMatrix4fv(GetUniformLocation(name), 1, GL_FALSE, matrix); + Unlock(); + } + + return true; +} + +bool NzGLSLShader::SendVector(const NzString& name, const NzVector2d& vector) +{ + if (glProgramUniform2dv) + glProgramUniform2dv(m_program, GetUniformLocation(name), 1, vector); + else + { + Lock(); + glUniform2dv(GetUniformLocation(name), 1, vector); + Unlock(); + } + + return true; +} + +bool NzGLSLShader::SendVector(const NzString& name, const NzVector2f& vector) +{ + if (glProgramUniform2fv) + glProgramUniform2fv(m_program, GetUniformLocation(name), 1, vector); + else + { + Lock(); + glUniform2fv(GetUniformLocation(name), 1, vector); + Unlock(); + } + + return true; +} + +bool NzGLSLShader::SendVector(const NzString& name, const NzVector3d& vector) +{ + if (glProgramUniform3dv) + glProgramUniform3dv(m_program, GetUniformLocation(name), 1, vector); + else + { + Lock(); + glUniform3dv(GetUniformLocation(name), 1, vector); + Unlock(); + } + + return true; +} + +bool NzGLSLShader::SendVector(const NzString& name, const NzVector3f& vector) +{ + if (glProgramUniform3fv) + glProgramUniform3fv(m_program, GetUniformLocation(name), 1, vector); + else + { + Lock(); + glUniform3fv(GetUniformLocation(name), 1, vector); + Unlock(); + } + + return true; +} + +bool NzGLSLShader::SendVector(const NzString& name, const NzVector4d& vector) +{ + if (glProgramUniform4dv) + glProgramUniform4dv(m_program, GetUniformLocation(name), 1, vector); + else + { + Lock(); + glUniform4dv(GetUniformLocation(name), 1, vector); + Unlock(); + } + + return true; +} + +bool NzGLSLShader::SendVector(const NzString& name, const NzVector4f& vector) +{ + if (glProgramUniform4fv) + glProgramUniform4fv(m_program, GetUniformLocation(name), 1, vector); + else + { + Lock(); + glUniform4fv(GetUniformLocation(name), 1, vector); + Unlock(); + } return true; } @@ -356,25 +491,48 @@ bool NzGLSLShader::SendTexture(const NzString& name, NzTexture* texture) m_textures[location] = TextureSlot{unit, texture}; - Lock(); - glUniform1i(location, unit); - Unlock(); + if (glProgramUniform1i) + glProgramUniform1i(m_program, location, unit); + else + { + Lock(); + glUniform1i(location, unit); + Unlock(); + } return true; } void NzGLSLShader::Unbind() { + #ifdef NAZARA_DEBUG + if (NzContext::GetCurrent() == nullptr) + { + NazaraError("No active context"); + return; + } + #endif + glUseProgram(0); } void NzGLSLShader::Unlock() { + #ifdef NAZARA_DEBUG + if (NzContext::GetCurrent() == nullptr) + { + NazaraError("No active context"); + return; + } + #endif + + #if NAZARA_RENDERER_SAFE if (lockedLevel == 0) { NazaraWarning("Unlock called on non-locked texture"); return; } + #endif if (--lockedLevel == 0 && lockedPrevious != m_program) glUseProgram(lockedPrevious); diff --git a/src/Nazara/Renderer/GLSLShader.hpp b/src/Nazara/Renderer/GLSLShader.hpp index 2d0287652..658e6e67d 100644 --- a/src/Nazara/Renderer/GLSLShader.hpp +++ b/src/Nazara/Renderer/GLSLShader.hpp @@ -42,6 +42,12 @@ class NzGLSLShader : public NzShaderImpl bool SendInteger(const NzString& name, int value); bool SendMatrix(const NzString& name, const NzMatrix4d& matrix); bool SendMatrix(const NzString& name, const NzMatrix4f& matrix); + bool SendVector(const NzString& name, const NzVector2d& vector); + bool SendVector(const NzString& name, const NzVector2f& vector); + bool SendVector(const NzString& name, const NzVector3d& vector); + bool SendVector(const NzString& name, const NzVector3f& vector); + bool SendVector(const NzString& name, const NzVector4d& vector); + bool SendVector(const NzString& name, const NzVector4f& vector); bool SendTexture(const NzString& name, NzTexture* texture); void Unbind(); @@ -58,7 +64,6 @@ class NzGLSLShader : public NzShaderImpl std::map m_textures; GLuint m_program; GLuint m_shaders[nzShaderType_Count]; - nzUInt8 m_textureFreeID; NzShader* m_parent; NzString m_log; }; diff --git a/src/Nazara/Renderer/HardwareBuffer.cpp b/src/Nazara/Renderer/HardwareBuffer.cpp index d42db2593..c017967be 100644 --- a/src/Nazara/Renderer/HardwareBuffer.cpp +++ b/src/Nazara/Renderer/HardwareBuffer.cpp @@ -5,6 +5,7 @@ #include #include #include +#include #include #include #include @@ -12,17 +13,17 @@ namespace { GLenum bufferLock[] = { - GL_WRITE_ONLY, // nzBufferLock_DiscardAndWrite - GL_READ_ONLY, // nzBufferLock_ReadOnly - GL_READ_WRITE, // nzBufferLock_ReadWrite - GL_WRITE_ONLY // nzBufferLock_WriteOnly + GL_WRITE_ONLY, // nzBufferAccess_DiscardAndWrite + GL_READ_ONLY, // nzBufferAccess_ReadOnly + GL_READ_WRITE, // nzBufferAccess_ReadWrite + GL_WRITE_ONLY // nzBufferAccess_WriteOnly }; GLenum bufferLockRange[] = { - GL_MAP_INVALIDATE_BUFFER_BIT | GL_MAP_WRITE_BIT, // nzBufferLock_DiscardAndWrite - GL_MAP_READ_BIT, // nzBufferLock_ReadOnly - GL_MAP_READ_BIT | GL_MAP_WRITE_BIT, // nzBufferLock_ReadWrite - GL_MAP_WRITE_BIT // nzBufferLock_WriteOnly + GL_MAP_INVALIDATE_BUFFER_BIT | GL_MAP_WRITE_BIT, // nzBufferAccess_DiscardAndWrite + GL_MAP_READ_BIT, // nzBufferAccess_ReadOnly + GL_MAP_READ_BIT | GL_MAP_WRITE_BIT, // nzBufferAccess_ReadWrite + GL_MAP_WRITE_BIT // nzBufferAccess_WriteOnly }; GLenum bufferTarget[] = { @@ -43,13 +44,13 @@ namespace GL_STATIC_DRAW // nzBufferUsage_Static }; - typedef nzUInt8* (*LockRoutine)(nzBufferType type, nzBufferLock lock, unsigned int offset, unsigned int size); + typedef nzUInt8* (*LockRoutine)(nzBufferType type, nzBufferAccess access, unsigned int offset, unsigned int size); - nzUInt8* LockBuffer(nzBufferType type, nzBufferLock lock, unsigned int offset, unsigned int size) + nzUInt8* LockBuffer(nzBufferType type, nzBufferAccess access, unsigned int offset, unsigned int size) { NazaraUnused(size); - if (lock == nzBufferLock_DiscardAndWrite) + if (access == nzBufferAccess_DiscardAndWrite) { GLint size; glGetBufferParameteriv(bufferTargetBinding[type], GL_BUFFER_SIZE, &size); @@ -61,30 +62,30 @@ namespace glBufferData(bufferTargetBinding[type], size, nullptr, usage); } - void* ptr = glMapBuffer(bufferTarget[type], bufferLock[lock]); + void* ptr = glMapBuffer(bufferTarget[type], bufferLock[access]); if (ptr) return reinterpret_cast(ptr) + offset; else return nullptr; } - nzUInt8* LockBufferRange(nzBufferType type, nzBufferLock lock, unsigned int offset, unsigned int size) + nzUInt8* LockBufferRange(nzBufferType type, nzBufferAccess access, unsigned int offset, unsigned int size) { - return reinterpret_cast(glMapBufferRange(bufferTarget[type], offset, size, bufferLockRange[lock])); + return reinterpret_cast(glMapBufferRange(bufferTarget[type], offset, size, bufferLockRange[access])); } - nzUInt8* LockBufferFirstRun(nzBufferType type, nzBufferLock lock, unsigned int offset, unsigned int size); + nzUInt8* LockBufferFirstRun(nzBufferType type, nzBufferAccess access, unsigned int offset, unsigned int size); - LockRoutine lockBuffer = LockBufferFirstRun; + LockRoutine mapBuffer = LockBufferFirstRun; - nzUInt8* LockBufferFirstRun(nzBufferType type, nzBufferLock lock, unsigned int offset, unsigned int size) + nzUInt8* LockBufferFirstRun(nzBufferType type, nzBufferAccess access, unsigned int offset, unsigned int size) { if (glMapBufferRange) - lockBuffer = LockBufferRange; + mapBuffer = LockBufferRange; else - lockBuffer = LockBuffer; + mapBuffer = LockBuffer; - return lockBuffer(type, lock, offset, size); + return mapBuffer(type, access, offset, size); } } @@ -100,20 +101,24 @@ NzHardwareBuffer::~NzHardwareBuffer() void NzHardwareBuffer::Bind() { + #ifdef NAZARA_DEBUG + if (NzContext::GetCurrent() == nullptr) + { + NazaraError("No active context"); + return; + } + #endif + glBindBuffer(bufferTarget[m_type], m_buffer); } bool NzHardwareBuffer::Create(unsigned int size, nzBufferUsage usage) { + NzContext::EnsureContext(); + m_buffer = 0; glGenBuffers(1, &m_buffer); - if (!m_buffer) - { - NazaraError("Failed to create buffer"); - return false; - } - GLint previous; glGetIntegerv(bufferTargetBinding[m_type], &previous); @@ -129,11 +134,15 @@ bool NzHardwareBuffer::Create(unsigned int size, nzBufferUsage usage) void NzHardwareBuffer::Destroy() { + NzContext::EnsureContext(); + glDeleteBuffers(1, &m_buffer); } bool NzHardwareBuffer::Fill(const void* data, unsigned int offset, unsigned int size) { + NzContext::EnsureContext(); + GLuint previous; glGetIntegerv(bufferTargetBinding[m_type], reinterpret_cast(&previous)); @@ -152,10 +161,10 @@ bool NzHardwareBuffer::Fill(const void* data, unsigned int offset, unsigned int } else { - nzUInt8* ptr = lockBuffer(m_type, (size == m_parent->GetSize()) ? nzBufferLock_DiscardAndWrite : nzBufferLock_WriteOnly, offset, size); + nzUInt8* ptr = mapBuffer(m_type, (size == m_parent->GetSize()) ? nzBufferAccess_DiscardAndWrite : nzBufferAccess_WriteOnly, offset, size); if (!ptr) { - NazaraError("Failed to lock buffer"); + NazaraError("Failed to map buffer"); return false; } @@ -164,7 +173,7 @@ bool NzHardwareBuffer::Fill(const void* data, unsigned int offset, unsigned int if (glUnmapBuffer(bufferTarget[m_type]) != GL_TRUE) { // Une erreur rare est survenue, nous devons réinitialiser le buffer - NazaraError("Failed to unlock buffer, reinitialising content... (OpenGL error : 0x" + NzString::Number(glGetError(), 16) + ')'); + NazaraError("Failed to unmap buffer, reinitialising content... (OpenGL error : 0x" + NzString::Number(glGetError(), 16) + ')'); glBufferData(bufferTarget[m_type], m_parent->GetSize(), nullptr, bufferUsage[m_parent->GetStorage()]); @@ -189,8 +198,10 @@ bool NzHardwareBuffer::IsHardware() const return true; } -void* NzHardwareBuffer::Lock(nzBufferLock lock, unsigned int offset, unsigned int length) +void* NzHardwareBuffer::Map(nzBufferAccess access, unsigned int offset, unsigned int length) { + NzContext::EnsureContext(); + // Pour ne pas perturber le rendu, on interfère pas avec le binding déjà présent GLuint previous; glGetIntegerv(bufferTargetBinding[m_type], reinterpret_cast(&previous)); @@ -198,7 +209,7 @@ void* NzHardwareBuffer::Lock(nzBufferLock lock, unsigned int offset, unsigned in if (previous != m_buffer) glBindBuffer(bufferTarget[m_type], m_buffer); - void* ptr = lockBuffer(m_type, lock, offset, length); + void* ptr = mapBuffer(m_type, access, offset, length); // Inutile de rebinder s'il n'y avait aucun buffer (Optimise les opérrations chaînées) if (previous != m_buffer && previous != 0) @@ -207,8 +218,10 @@ void* NzHardwareBuffer::Lock(nzBufferLock lock, unsigned int offset, unsigned in return ptr; } -bool NzHardwareBuffer::Unlock() +bool NzHardwareBuffer::Unmap() { + NzContext::EnsureContext(); + GLuint previous; glGetIntegerv(bufferTargetBinding[m_type], reinterpret_cast(&previous)); @@ -218,7 +231,7 @@ bool NzHardwareBuffer::Unlock() if (glUnmapBuffer(bufferTarget[m_type]) != GL_TRUE) { // Une erreur rare est survenue, nous devons réinitialiser le buffer - NazaraError("Failed to unlock buffer, reinitialising content... (OpenGL error : 0x" + NzString::Number(glGetError(), 16) + ')'); + NazaraError("Failed to unmap buffer, reinitialising content... (OpenGL error : 0x" + NzString::Number(glGetError(), 16) + ')'); glBufferData(bufferTarget[m_type], m_parent->GetSize(), nullptr, bufferUsage[m_parent->GetStorage()]); diff --git a/src/Nazara/Renderer/HardwareBuffer.hpp b/src/Nazara/Renderer/HardwareBuffer.hpp index 044633634..f1652098e 100644 --- a/src/Nazara/Renderer/HardwareBuffer.hpp +++ b/src/Nazara/Renderer/HardwareBuffer.hpp @@ -28,8 +28,8 @@ class NzHardwareBuffer : public NzBufferImpl bool IsHardware() const; - void* Lock(nzBufferLock lock, unsigned int offset = 0, unsigned int length = 0); - bool Unlock(); + void* Map(nzBufferAccess access, unsigned int offset = 0, unsigned int length = 0); + bool Unmap(); private: GLuint m_buffer; diff --git a/src/Nazara/Renderer/IndexBuffer.cpp b/src/Nazara/Renderer/IndexBuffer.cpp index 7eb0a5c68..2e822d5d9 100644 --- a/src/Nazara/Renderer/IndexBuffer.cpp +++ b/src/Nazara/Renderer/IndexBuffer.cpp @@ -172,12 +172,12 @@ bool NzIndexBuffer::IsSequential() const return m_buffer == nullptr; } -void* NzIndexBuffer::Lock(nzBufferLock lock, unsigned int offset, unsigned int length) +void* NzIndexBuffer::Map(nzBufferAccess access, unsigned int offset, unsigned int length) { #if NAZARA_RENDERER_SAFE if (!m_buffer) { - NazaraError("Impossible to lock sequential index buffer"); + NazaraError("Impossible to map sequential index buffer"); return nullptr; } @@ -188,10 +188,10 @@ void* NzIndexBuffer::Lock(nzBufferLock lock, unsigned int offset, unsigned int l } #endif - return m_buffer->Lock(lock, m_startIndex+offset, (length) ? length : m_indexCount-offset); + return m_buffer->Map(access, m_startIndex+offset, (length) ? length : m_indexCount-offset); } -bool NzIndexBuffer::Unlock() +bool NzIndexBuffer::Unmap() { #if NAZARA_RENDERER_SAFE if (!m_buffer) @@ -201,5 +201,5 @@ bool NzIndexBuffer::Unlock() } #endif - return m_buffer->Unlock(); + return m_buffer->Unmap(); } diff --git a/src/Nazara/Renderer/OcclusionQuery.cpp b/src/Nazara/Renderer/OcclusionQuery.cpp index 5ce46f719..50901e190 100644 --- a/src/Nazara/Renderer/OcclusionQuery.cpp +++ b/src/Nazara/Renderer/OcclusionQuery.cpp @@ -6,6 +6,7 @@ #include #include #include +#include #include #include #include @@ -15,9 +16,13 @@ m_id(0) { #if NAZARA_RENDERER_SAFE if (IsSupported()) + { #endif + NzContext::EnsureContext(); + glGenQueries(1, reinterpret_cast(&m_id)); #if NAZARA_RENDERER_SAFE + } else { NazaraError("Occlusion queries not supported"); @@ -38,6 +43,8 @@ NzOcclusionQuery::~NzOcclusionQuery() { if (m_id) { + NzContext::EnsureContext(); + GLuint query = static_cast(m_id); glDeleteQueries(1, &query); } @@ -45,16 +52,34 @@ NzOcclusionQuery::~NzOcclusionQuery() void NzOcclusionQuery::Begin() { + #ifdef NAZARA_DEBUG + if (NzContext::GetCurrent() == nullptr) + { + NazaraError("No active context"); + return; + } + #endif + glBeginQuery(GL_SAMPLES_PASSED, m_id); } void NzOcclusionQuery::End() { + #ifdef NAZARA_DEBUG + if (NzContext::GetCurrent() == nullptr) + { + NazaraError("No active context"); + return; + } + #endif + glEndQuery(GL_SAMPLES_PASSED); } unsigned int NzOcclusionQuery::GetResult() const { + NzContext::EnsureContext(); + GLuint result; glGetQueryObjectuiv(m_id, GL_QUERY_RESULT, &result); @@ -63,6 +88,8 @@ unsigned int NzOcclusionQuery::GetResult() const bool NzOcclusionQuery::IsResultAvailable() const { + NzContext::EnsureContext(); + GLint available; glGetQueryObjectiv(m_id, GL_QUERY_RESULT_AVAILABLE, &available); diff --git a/src/Nazara/Renderer/OpenGL.cpp b/src/Nazara/Renderer/OpenGL.cpp index 502cc1066..401499ef6 100644 --- a/src/Nazara/Renderer/OpenGL.cpp +++ b/src/Nazara/Renderer/OpenGL.cpp @@ -116,7 +116,6 @@ bool NzOpenGL::Initialize() } // Le chargement des fonctions OpenGL nécessite un contexte OpenGL - // Le contexte de chargement ne peut pas être partagé car le contexte de référence n'existe pas encore NzContextParameters parameters; parameters.majorVersion = 2; parameters.minorVersion = 0; @@ -124,8 +123,8 @@ bool NzOpenGL::Initialize() /* Note: Même le contexte de chargement nécessite quelques fonctions de base pour correctement s'initialiser - Pour cette raison, sa création est faite en deux fois, la première sert à récupérer le strict minimum, - la seconde à créer le véritable contexte de chargement. + Pour cette raison, deux contextes sont créés, le premier sert à récupérer les fonctions permetttant + de créer le second avec les bons paramètres.s Non sérieusement si quelqu'un a une meilleure idée qu'il me le dise */ @@ -371,50 +370,50 @@ bool NzOpenGL::Initialize() } // FrameBufferObject - try + if (openGLversion >= 300 || IsSupported("GL_ARB_framebuffer_object")) { - glBindFramebuffer = reinterpret_cast(LoadEntry("glBindFramebuffer")); - glBindRenderbuffer = reinterpret_cast(LoadEntry("glBindRenderbuffer")); - glCheckFramebufferStatus = reinterpret_cast(LoadEntry("glCheckFramebufferStatus")); - glDeleteFramebuffers = reinterpret_cast(LoadEntry("glDeleteFramebuffers")); - glDeleteRenderbuffers = reinterpret_cast(LoadEntry("glDeleteRenderbuffers")); - glFramebufferRenderbuffer = reinterpret_cast(LoadEntry("glFramebufferRenderbuffer")); - glFramebufferTexture2D = reinterpret_cast(LoadEntry("glFramebufferTexture2D")); - glGenerateMipmap = reinterpret_cast(LoadEntry("glGenerateMipmap")); - glGenFramebuffers = reinterpret_cast(LoadEntry("glGenFramebuffers")); - glGenRenderbuffers = reinterpret_cast(LoadEntry("glGenRenderbuffers")); - glRenderbufferStorage = reinterpret_cast(LoadEntry("glRenderbufferStorage")); - - openGLextensions[NzOpenGL::FrameBufferObject] = true; - } - catch (const std::exception& e) - { - if (openGLversion >= 300) - NazaraWarning("Failed to load core FBOs (" + NzString(e.what()) + ")"); - - if (IsSupported("GL_EXT_framebuffer_object")) + try { - try - { - glBindFramebuffer = reinterpret_cast(LoadEntry("glBindFramebufferEXT")); - glBindRenderbuffer = reinterpret_cast(LoadEntry("glBindRenderbufferEXT")); - glCheckFramebufferStatus = reinterpret_cast(LoadEntry("glCheckFramebufferStatusEXT")); - glDeleteFramebuffers = reinterpret_cast(LoadEntry("glDeleteFramebuffersEXT")); - glDeleteRenderbuffers = reinterpret_cast(LoadEntry("glDeleteRenderbuffersEXT")); - glFramebufferRenderbuffer = reinterpret_cast(LoadEntry("glFramebufferRenderbufferEXT")); - glFramebufferTexture2D = reinterpret_cast(LoadEntry("glFramebufferTexture2DEXT")); - glGenerateMipmap = reinterpret_cast(LoadEntry("glGenerateMipmapEXT")); - glGenFramebuffers = reinterpret_cast(LoadEntry("glGenFramebuffersEXT")); - glGenRenderbuffers = reinterpret_cast(LoadEntry("glGenRenderbuffersEXT")); - glRenderbufferStorage = reinterpret_cast(LoadEntry("glRenderbufferStorageEXT")); + glBindFramebuffer = reinterpret_cast(LoadEntry("glBindFramebuffer")); + glBindRenderbuffer = reinterpret_cast(LoadEntry("glBindRenderbuffer")); + glCheckFramebufferStatus = reinterpret_cast(LoadEntry("glCheckFramebufferStatus")); + glDeleteFramebuffers = reinterpret_cast(LoadEntry("glDeleteFramebuffers")); + glDeleteRenderbuffers = reinterpret_cast(LoadEntry("glDeleteRenderbuffers")); + glFramebufferRenderbuffer = reinterpret_cast(LoadEntry("glFramebufferRenderbuffer")); + glFramebufferTexture2D = reinterpret_cast(LoadEntry("glFramebufferTexture2D")); + glGenerateMipmap = reinterpret_cast(LoadEntry("glGenerateMipmap")); + glGenFramebuffers = reinterpret_cast(LoadEntry("glGenFramebuffers")); + glGenRenderbuffers = reinterpret_cast(LoadEntry("glGenRenderbuffers")); + glRenderbufferStorage = reinterpret_cast(LoadEntry("glRenderbufferStorage")); - openGLextensions[NzOpenGL::FrameBufferObject] = true; - } - catch (const std::exception& e) - { - NazaraError("Failed to load EXT_framebuffer_object: " + NzString(e.what())); - } + openGLextensions[NzOpenGL::FrameBufferObject] = true; } + catch (const std::exception& e) + { + NazaraError("Failed to load ARB_framebuffer_object: (" + NzString(e.what()) + ")"); + } + } + + // SeparateShaderObjects + if (openGLversion >= 400 || IsSupported("GL_ARB_gpu_shader_fp64")) + { + glProgramUniform1f = reinterpret_cast(LoadEntry("glProgramUniform1f")); + glProgramUniform1i = reinterpret_cast(LoadEntry("glProgramUniform1i")); + glProgramUniform2fv = reinterpret_cast(LoadEntry("glProgramUniform2fv")); + glProgramUniform3fv = reinterpret_cast(LoadEntry("glProgramUniform3fv")); + glProgramUniform4fv = reinterpret_cast(LoadEntry("glProgramUniform4fv")); + glProgramUniformMatrix4fv = reinterpret_cast(LoadEntry("glProgramUniformMatrix4fv")); + + if (openGLextensions[NzOpenGL::FP64]) + { + glProgramUniform1d = reinterpret_cast(LoadEntry("glProgramUniform1d")); + glProgramUniform2dv = reinterpret_cast(LoadEntry("glProgramUniform2dv")); + glProgramUniform3dv = reinterpret_cast(LoadEntry("glProgramUniform3dv")); + glProgramUniform4dv = reinterpret_cast(LoadEntry("glProgramUniform4dv")); + glProgramUniformMatrix4dv = reinterpret_cast(LoadEntry("glProgramUniformMatrix4dv")); + } + + openGLextensions[NzOpenGL::SeparateShaderObjects] = true; } // Texture3D @@ -452,7 +451,7 @@ bool NzOpenGL::Initialize() // TextureCompression_s3tc openGLextensions[NzOpenGL::TextureCompression_s3tc] = IsSupported("GL_EXT_texture_compression_s3tc"); - // VertexArrayObject + // TextureStorage if (openGLversion >= 420 || IsSupported("GL_ARB_texture_storage")) { try @@ -489,16 +488,14 @@ bool NzOpenGL::Initialize() /****************************************Contexte de référence****************************************/ ///FIXME: Utiliser le contexte de chargement comme référence ? (Vérifier mode debug) - if (!NzContext::InitializeReference()) + if (!NzContext::Initialize()) { - NazaraError("Failed to initialize reference context"); + NazaraError("Failed to initialize contexts"); Uninitialize(); return false; } - NzContextParameters::defaultShareContext = NzContext::GetReference(); - return true; } @@ -514,7 +511,7 @@ bool NzOpenGL::IsSupported(const NzString& string) void NzOpenGL::Uninitialize() { - NzContext::UninitializeReference(); + NzContext::Uninitialize(); for (bool& ext : openGLextensions) ext = false; @@ -604,6 +601,17 @@ PFNGLLINKPROGRAMPROC glLinkProgram = nullptr; PFNGLMAPBUFFERPROC glMapBuffer = nullptr; PFNGLMAPBUFFERRANGEPROC glMapBufferRange = nullptr; PFNGLPOLYGONMODEPROC glPolygonMode = nullptr; +PFNGLPROGRAMUNIFORM1DPROC glProgramUniform1d = nullptr; +PFNGLPROGRAMUNIFORM1FPROC glProgramUniform1f = nullptr; +PFNGLPROGRAMUNIFORM1IPROC glProgramUniform1i = nullptr; +PFNGLPROGRAMUNIFORM2DVPROC glProgramUniform2dv = nullptr; +PFNGLPROGRAMUNIFORM2FVPROC glProgramUniform2fv = nullptr; +PFNGLPROGRAMUNIFORM3DVPROC glProgramUniform3dv = nullptr; +PFNGLPROGRAMUNIFORM3FVPROC glProgramUniform3fv = nullptr; +PFNGLPROGRAMUNIFORM4DVPROC glProgramUniform4dv = nullptr; +PFNGLPROGRAMUNIFORM4FVPROC glProgramUniform4fv = nullptr; +PFNGLPROGRAMUNIFORMMATRIX4DVPROC glProgramUniformMatrix4dv = nullptr; +PFNGLPROGRAMUNIFORMMATRIX4FVPROC glProgramUniformMatrix4fv = nullptr; PFNGLREADPIXELSPROC glReadPixels = nullptr; PFNGLRENDERBUFFERSTORAGEPROC glRenderbufferStorage = nullptr; PFNGLSCISSORPROC glScissor = nullptr; diff --git a/src/Nazara/Renderer/RenderTarget.cpp b/src/Nazara/Renderer/RenderTarget.cpp index 8ac1905a7..2954e61ca 100644 --- a/src/Nazara/Renderer/RenderTarget.cpp +++ b/src/Nazara/Renderer/RenderTarget.cpp @@ -25,5 +25,5 @@ bool NzRenderTarget::SetActive(bool active) void NzRenderTarget::Desactivate() { - // Seuls les target sans contextes (ex: RenderTexture) nécessitent une désactivation + // Seuls les target sans contextes (ex: NzRenderTexture) nécessitent une désactivation } diff --git a/src/Nazara/Renderer/RenderWindow.cpp b/src/Nazara/Renderer/RenderWindow.cpp index bc8c91db8..6891e3aba 100644 --- a/src/Nazara/Renderer/RenderWindow.cpp +++ b/src/Nazara/Renderer/RenderWindow.cpp @@ -5,9 +5,7 @@ #include #include #include -#include #include -#include #include #include #include @@ -49,11 +47,6 @@ NzRenderWindow::~NzRenderWindow() { } -bool NzRenderWindow::CanActivate() const -{ - return m_impl != nullptr && m_context != nullptr; -} - bool NzRenderWindow::CopyToImage(NzImage* image) { #if NAZARA_RENDERER_SAFE @@ -144,7 +137,7 @@ bool NzRenderWindow::Create(NzWindowHandle handle, const NzContextParameters& pa void NzRenderWindow::Display() { - if (m_context) + if (m_context && m_parameters.doubleBuffered) m_context->SwapBuffers(); } @@ -181,7 +174,23 @@ void NzRenderWindow::EnableVerticalSync(bool enabled) NazaraError("No context"); } -NzRenderTargetParameters NzRenderWindow::GetRenderTargetParameters() const +NzContextParameters NzRenderWindow::GetContextParameters() const +{ + if (m_context) + return m_context->GetParameters(); + else + { + NazaraError("Window not created/context not initialized"); + return NzContextParameters(); + } +} + +unsigned int NzRenderWindow::GetHeight() const +{ + return NzWindow::GetHeight(); +} + +NzRenderTargetParameters NzRenderWindow::GetParameters() const { if (m_context) { @@ -195,15 +204,9 @@ NzRenderTargetParameters NzRenderWindow::GetRenderTargetParameters() const } } -NzContextParameters NzRenderWindow::GetContextParameters() const +unsigned int NzRenderWindow::GetWidth() const { - if (m_context) - return m_context->GetParameters(); - else - { - NazaraError("Window not created/context not initialized"); - return NzContextParameters(); - } + return NzWindow::GetWidth(); } bool NzRenderWindow::HasContext() const @@ -211,9 +214,23 @@ bool NzRenderWindow::HasContext() const return true; } +bool NzRenderWindow::IsValid() const +{ + return m_impl != nullptr && m_context != nullptr; +} + bool NzRenderWindow::Activate() { - return m_context->SetActive(true); + if (m_context->SetActive(true)) + { + glDrawBuffer((m_parameters.doubleBuffered) ? GL_BACK : GL_FRONT); + return true; + } + else + { + NazaraError("Failed to activate window's context"); + return false; + } } void NzRenderWindow::OnClose() diff --git a/src/Nazara/Renderer/Renderer.cpp b/src/Nazara/Renderer/Renderer.cpp index 11e18926e..ce8e0ab53 100644 --- a/src/Nazara/Renderer/Renderer.cpp +++ b/src/Nazara/Renderer/Renderer.cpp @@ -23,17 +23,32 @@ namespace { const nzUInt8 attribIndex[] = { - 2, // nzElementUsage_Diffuse - 1, // nzElementUsage_Normal - 0, // nzElementUsage_Position - 3, // nzElementUsage_Tangent - 4 // nzElementUsage_TexCoord + 2, // nzElementUsage_Diffuse + 1, // nzElementUsage_Normal + 0, // nzElementUsage_Position + 3, // nzElementUsage_Tangent + 4 // nzElementUsage_TexCoord + }; + + + const GLenum blendFunc[] = + { + GL_DST_ALPHA, // nzBlendFunc_DestAlpha + GL_DST_COLOR, // nzBlendFunc_DestColor + GL_SRC_ALPHA, // nzBlendFunc_SrcAlpha + GL_SRC_COLOR, // nzBlendFunc_SrcColor + GL_ONE_MINUS_DST_ALPHA, // nzBlendFunc_InvDestAlpha + GL_ONE_MINUS_DST_COLOR, // nzBlendFunc_InvDestColor + GL_ONE_MINUS_SRC_ALPHA, // nzBlendFunc_InvSrcAlpha + GL_ONE_MINUS_SRC_COLOR, // nzBlendFunc_InvSrcColor + GL_ONE, // nzBlendFunc_One + GL_ZERO // nzBlendFunc_Zero }; const GLenum faceCullingMode[] = { - GL_BACK, // nzFaceCulling_Back - GL_FRONT, // nzFaceCulling_Front + GL_BACK, // nzFaceCulling_Back + GL_FRONT, // nzFaceCulling_Front GL_FRONT_AND_BACK // nzFaceCulling_FrontAndBack }; @@ -41,18 +56,18 @@ namespace { GL_POINT, // nzFaceFilling_Point GL_LINE, // nzFaceFilling_Line - GL_FILL // nzFaceFilling_Fill + GL_FILL // nzFaceFilling_Fill }; const GLenum openglPrimitive[] = { - GL_LINES, // nzPrimitiveType_LineList, - GL_LINE_STRIP, // nzPrimitiveType_LineStrip, - GL_POINTS, // nzPrimitiveType_PointList, - GL_TRIANGLES, // nzPrimitiveType_TriangleList, + GL_LINES, // nzPrimitiveType_LineList, + GL_LINE_STRIP, // nzPrimitiveType_LineStrip, + GL_POINTS, // nzPrimitiveType_PointList, + GL_TRIANGLES, // nzPrimitiveType_TriangleList, GL_TRIANGLE_STRIP, // nzPrimitiveType_TriangleStrip, - GL_TRIANGLE_FAN // nzPrimitiveType_TriangleFan + GL_TRIANGLE_FAN // nzPrimitiveType_TriangleFan }; const nzUInt8 openglSize[] = @@ -71,47 +86,47 @@ namespace const GLenum openglType[] = { GL_UNSIGNED_BYTE, // nzElementType_Color - GL_DOUBLE, // nzElementType_Double1 - GL_DOUBLE, // nzElementType_Double2 - GL_DOUBLE, // nzElementType_Double3 - GL_DOUBLE, // nzElementType_Double4 - GL_FLOAT, // nzElementType_Float1 - GL_FLOAT, // nzElementType_Float2 - GL_FLOAT, // nzElementType_Float3 - GL_FLOAT // nzElementType_Float4 + GL_DOUBLE, // nzElementType_Double1 + GL_DOUBLE, // nzElementType_Double2 + GL_DOUBLE, // nzElementType_Double3 + GL_DOUBLE, // nzElementType_Double4 + GL_FLOAT, // nzElementType_Float1 + GL_FLOAT, // nzElementType_Float2 + GL_FLOAT, // nzElementType_Float3 + GL_FLOAT // nzElementType_Float4 }; const GLenum rendererComparison[] = { - GL_ALWAYS, // nzRendererComparison_Always - GL_EQUAL, // nzRendererComparison_Equal - GL_GREATER, // nzRendererComparison_Greater - GL_GEQUAL, // nzRendererComparison_GreaterOrEqual - GL_LESS, // nzRendererComparison_Less - GL_LEQUAL, // nzRendererComparison_LessOrEqual - GL_NEVER // nzRendererComparison_Never + GL_ALWAYS, // nzRendererComparison_Always + GL_EQUAL, // nzRendererComparison_Equal + GL_GREATER, // nzRendererComparison_Greater + GL_GEQUAL, // nzRendererComparison_GreaterOrEqual + GL_LESS, // nzRendererComparison_Less + GL_LEQUAL, // nzRendererComparison_LessOrEqual + GL_NEVER // nzRendererComparison_Never }; const GLenum rendererParameter[] = { - GL_BLEND, // nzRendererParameter_Blend - GL_NONE, // nzRendererParameter_ColorWrite - GL_DEPTH_TEST, // nzRendererParameter_DepthTest - GL_NONE, // nzRendererParameter_DepthWrite - GL_CULL_FACE, // nzRendererParameter_FaceCulling - GL_STENCIL_TEST // nzRendererParameter_Stencil + GL_BLEND, // nzRendererParameter_Blend + GL_NONE, // nzRendererParameter_ColorWrite + GL_DEPTH_TEST, // nzRendererParameter_DepthTest + GL_NONE, // nzRendererParameter_DepthWrite + GL_CULL_FACE, // nzRendererParameter_FaceCulling + GL_STENCIL_TEST // nzRendererParameter_Stencil }; const GLenum stencilOperation[] = { - GL_DECR, // nzStencilOperation_Decrement + GL_DECR, // nzStencilOperation_Decrement GL_DECR_WRAP, // nzStencilOperation_DecrementToSaturation - GL_INCR, // nzStencilOperation_Increment + GL_INCR, // nzStencilOperation_Increment GL_INCR_WRAP, // nzStencilOperation_IncrementToSaturation - GL_INVERT, // nzStencilOperation_Invert - GL_KEEP, // nzStencilOperation_Keep - GL_REPLACE, // nzStencilOperation_Replace - GL_ZERO // nzStencilOperation_Zero + GL_INVERT, // nzStencilOperation_Invert + GL_KEEP, // nzStencilOperation_Keep + GL_REPLACE, // nzStencilOperation_Replace + GL_ZERO // nzStencilOperation_Zero }; } @@ -228,6 +243,14 @@ void NzRenderer::DrawPrimitives(nzPrimitiveType primitive, unsigned int firstVer void NzRenderer::Enable(nzRendererParameter parameter, bool enable) { + #ifdef NAZARA_DEBUG + if (NzContext::GetCurrent() == nullptr) + { + NazaraError("No active context"); + return; + } + #endif + switch (parameter) { case nzRendererParameter_ColorWrite: @@ -273,6 +296,22 @@ NzRenderTarget* NzRenderer::GetTarget() const return m_target; } +NzRectui NzRenderer::GetViewport() const +{ + #ifdef NAZARA_DEBUG + if (NzContext::GetCurrent() == nullptr) + { + NazaraError("No active context"); + return NzRectui(); + } + #endif + + GLint params[4]; + glGetIntegerv(GL_VIEWPORT, ¶ms[0]); + + return NzRectui(params[0], params[1], params[2], params[3]); +} + bool NzRenderer::HasCapability(nzRendererCap capability) const { return m_capabilities[capability]; @@ -297,6 +336,11 @@ bool NzRenderer::Initialize() if (NzOpenGL::Initialize()) { + NzContext::EnsureContext(); + + const NzContext* context = NzContext::GetReference(); + bool compatibility = context->GetParameters().compatibilityProfile; + m_vaoUpdated = false; m_indexBuffer = nullptr; m_shader = nullptr; @@ -318,7 +362,7 @@ bool NzRenderer::Initialize() m_capabilities[nzRendererCap_HardwareBuffer] = true; // Natif depuis OpenGL 1.5 m_capabilities[nzRendererCap_MultipleRenderTargets] = true; // Natif depuis OpenGL 2.0 m_capabilities[nzRendererCap_OcclusionQuery] = true; // Natif depuis OpenGL 1.5 - m_capabilities[nzRendererCap_SoftwareBuffer] = NzOpenGL::GetVersion() <= 300; // Déprécié en OpenGL 3 + m_capabilities[nzRendererCap_SoftwareBuffer] = compatibility || NzOpenGL::GetVersion() <= 300; // Déprécié en OpenGL 3 m_capabilities[nzRendererCap_Texture3D] = NzOpenGL::IsSupported(NzOpenGL::Texture3D); m_capabilities[nzRendererCap_TextureCubemap] = true; // Natif depuis OpenGL 1.3 m_capabilities[nzRendererCap_TextureMulti] = true; // Natif depuis OpenGL 1.3 @@ -336,14 +380,10 @@ bool NzRenderer::Initialize() if (m_capabilities[nzRendererCap_MultipleRenderTargets]) { - // Permettre de gérer plus de targets que de nombre de sorties dans le shader ne servirait à rien GLint maxDrawBuffers; glGetIntegerv(GL_MAX_DRAW_BUFFERS, &maxDrawBuffers); - GLint maxRenderTextureTargets; - glGetIntegerv(GL_MAX_COLOR_ATTACHMENTS, &maxRenderTextureTargets); - - m_maxRenderTarget = static_cast(std::min(maxDrawBuffers, maxRenderTextureTargets)); + m_maxRenderTarget = static_cast(maxDrawBuffers); } else m_maxRenderTarget = 1; @@ -366,6 +406,19 @@ bool NzRenderer::Initialize() return false; } +void NzRenderer::SetBlendFunc(nzBlendFunc src, nzBlendFunc dest) +{ + #ifdef NAZARA_DEBUG + if (NzContext::GetCurrent() == nullptr) + { + NazaraError("No active context"); + return; + } + #endif + + glBlendFunc(blendFunc[src], blendFunc[dest]); +} + void NzRenderer::SetClearColor(const NzColor& color) { #ifdef NAZARA_DEBUG @@ -462,10 +515,7 @@ bool NzRenderer::SetShader(NzShader* shader) return true; if (m_shader) - { m_shader->m_impl->Unbind(); - m_shader = nullptr; - } if (shader) { @@ -473,6 +523,8 @@ bool NzRenderer::SetShader(NzShader* shader) if (!shader->IsCompiled()) { NazaraError("Shader is not compiled"); + m_shader = nullptr; + return false; } #endif @@ -480,9 +532,13 @@ bool NzRenderer::SetShader(NzShader* shader) if (!shader->m_impl->Bind()) { NazaraError("Failed to bind shader"); + m_shader = nullptr; + return false; } } + else + m_shader = nullptr; m_shader = shader; @@ -548,19 +604,19 @@ bool NzRenderer::SetTarget(NzRenderTarget* target) if (target == m_target) return true; - #if NAZARA_RENDERER_SAFE - if (target && !target->CanActivate()) - { - NazaraError("Target cannot be activated"); - return false; - } - #endif - if (m_target && !m_target->HasContext()) m_target->Desactivate(); if (target) { + #if NAZARA_RENDERER_SAFE + if (!target->IsValid()) + { + NazaraError("Target not valid"); + return false; + } + #endif + if (target->Activate()) m_target = target; else @@ -599,6 +655,43 @@ bool NzRenderer::SetVertexDeclaration(const NzVertexDeclaration* vertexDeclarati return true; } +void NzRenderer::SetViewport(const NzRectui& viewport) +{ + #ifdef NAZARA_DEBUG + if (NzContext::GetCurrent() == nullptr) + { + NazaraError("No active context"); + return; + } + #endif + + unsigned int height = m_target->GetHeight(); + + #if NAZARA_RENDERER_SAFE + if (!m_target) + { + NazaraError("Renderer has no target"); + return; + } + + unsigned int width = m_target->GetWidth(); + if (viewport.x+viewport.width >= width) + { + NazaraError("Rectangle dimensions are out of bounds"); + return; + } + + if (viewport.y+viewport.height >= height) + { + NazaraError("Rectangle dimensions are out of bounds"); + return; + } + #endif + + glViewport(viewport.x, height-viewport.height-viewport.y, viewport.width, viewport.height); + glScissor(viewport.x, height-viewport.height-viewport.y, viewport.width, viewport.height); +} + void NzRenderer::Uninitialize() { #if NAZARA_RENDERER_SAFE @@ -609,6 +702,8 @@ void NzRenderer::Uninitialize() } #endif + NzContext::EnsureContext(); + s_initialized = false; // Libération des VAOs @@ -644,6 +739,14 @@ bool NzRenderer::IsInitialized() bool NzRenderer::EnsureStateUpdate() { + #ifdef NAZARA_DEBUG + if (NzContext::GetCurrent() == nullptr) + { + NazaraError("No active context"); + return false; + } + #endif + if (!m_stencilFuncUpdated) { glStencilFunc(rendererComparison[m_stencilCompare], m_stencilReference, m_stencilMask); diff --git a/src/Nazara/Renderer/Shader.cpp b/src/Nazara/Renderer/Shader.cpp index 6d642626b..f3e635089 100644 --- a/src/Nazara/Renderer/Shader.cpp +++ b/src/Nazara/Renderer/Shader.cpp @@ -253,11 +253,12 @@ bool NzShader::LoadFromFile(nzShaderType type, const NzString& filePath) return false; } - NzString source; unsigned int length = file.GetSize(); + + NzString source; source.Resize(length); - if (file.Read(&source[0], sizeof(char), length) != length*sizeof(char)) + if (file.Read(&source[0], length) != length) { NazaraError("Failed to read shader file"); return false; @@ -371,6 +372,102 @@ bool NzShader::SendMatrix(const NzString& name, const NzMatrix4f& matrix) return m_impl->SendMatrix(name, matrix); } +bool NzShader::SendVector(const NzString& name, const NzVector2d& vector) +{ + #if NAZARA_RENDERER_SAFE + if (!m_impl) + { + NazaraError("Shader not created"); + return false; + } + + if (!NazaraRenderer->HasCapability(nzRendererCap_FP64)) + { + NazaraError("FP64 is not supported"); + return false; + } + #endif + + return m_impl->SendVector(name, vector); +} + +bool NzShader::SendVector(const NzString& name, const NzVector2f& vector) +{ + #if NAZARA_RENDERER_SAFE + if (!m_impl) + { + NazaraError("Shader not created"); + return false; + } + #endif + + return m_impl->SendVector(name, vector); +} + +bool NzShader::SendVector(const NzString& name, const NzVector3d& vector) +{ + #if NAZARA_RENDERER_SAFE + if (!m_impl) + { + NazaraError("Shader not created"); + return false; + } + + if (!NazaraRenderer->HasCapability(nzRendererCap_FP64)) + { + NazaraError("FP64 is not supported"); + return false; + } + #endif + + return m_impl->SendVector(name, vector); +} + +bool NzShader::SendVector(const NzString& name, const NzVector3f& vector) +{ + #if NAZARA_RENDERER_SAFE + if (!m_impl) + { + NazaraError("Shader not created"); + return false; + } + #endif + + return m_impl->SendVector(name, vector); +} + +bool NzShader::SendVector(const NzString& name, const NzVector4d& vector) +{ + #if NAZARA_RENDERER_SAFE + if (!m_impl) + { + NazaraError("Shader not created"); + return false; + } + + if (!NazaraRenderer->HasCapability(nzRendererCap_FP64)) + { + NazaraError("FP64 is not supported"); + return false; + } + #endif + + return m_impl->SendVector(name, vector); +} + +bool NzShader::SendVector(const NzString& name, const NzVector4f& vector) +{ + #if NAZARA_RENDERER_SAFE + if (!m_impl) + { + NazaraError("Shader not created"); + return false; + } + #endif + + return m_impl->SendVector(name, vector); +} + bool NzShader::SendTexture(const NzString& name, NzTexture* texture) { #if NAZARA_RENDERER_SAFE diff --git a/src/Nazara/Renderer/ShaderImpl.hpp b/src/Nazara/Renderer/ShaderImpl.hpp index 330b9dccf..504f59853 100644 --- a/src/Nazara/Renderer/ShaderImpl.hpp +++ b/src/Nazara/Renderer/ShaderImpl.hpp @@ -45,6 +45,12 @@ class NzShaderImpl virtual bool SendInteger(const NzString& name, int value) = 0; virtual bool SendMatrix(const NzString& name, const NzMatrix4d& matrix) = 0; virtual bool SendMatrix(const NzString& name, const NzMatrix4f& matrix) = 0; + virtual bool SendVector(const NzString& name, const NzVector2d& vector) = 0; + virtual bool SendVector(const NzString& name, const NzVector2f& vector) = 0; + virtual bool SendVector(const NzString& name, const NzVector3d& vector) = 0; + virtual bool SendVector(const NzString& name, const NzVector3f& vector) = 0; + virtual bool SendVector(const NzString& name, const NzVector4d& vector) = 0; + virtual bool SendVector(const NzString& name, const NzVector4f& vector) = 0; virtual bool SendTexture(const NzString& name, NzTexture* texture) = 0; virtual void Unbind() = 0; diff --git a/src/Nazara/Renderer/SoftwareBuffer.cpp b/src/Nazara/Renderer/SoftwareBuffer.cpp index a234ac00c..c579a7e40 100644 --- a/src/Nazara/Renderer/SoftwareBuffer.cpp +++ b/src/Nazara/Renderer/SoftwareBuffer.cpp @@ -6,6 +6,7 @@ #include #include #include +#include #include #include #include @@ -30,6 +31,14 @@ NzSoftwareBuffer::~NzSoftwareBuffer() void NzSoftwareBuffer::Bind() { + #ifdef NAZARA_DEBUG + if (NzContext::GetCurrent() == nullptr) + { + NazaraError("No active context"); + return; + } + #endif + glBindBuffer(bufferTarget[m_type], 0); } @@ -48,7 +57,7 @@ bool NzSoftwareBuffer::Create(unsigned int size, nzBufferUsage usage) return false; } - m_locked = false; + m_mapped = false; return true; } @@ -61,9 +70,9 @@ void NzSoftwareBuffer::Destroy() bool NzSoftwareBuffer::Fill(const void* data, unsigned int offset, unsigned int size) { #if NAZARA_RENDERER_SAFE - if (m_locked) + if (m_mapped) { - NazaraError("Buffer already locked"); + NazaraError("Buffer already mapped"); return false; } #endif @@ -83,35 +92,35 @@ bool NzSoftwareBuffer::IsHardware() const return false; } -void* NzSoftwareBuffer::Lock(nzBufferLock lock, unsigned int offset, unsigned int size) +void* NzSoftwareBuffer::Map(nzBufferAccess access, unsigned int offset, unsigned int size) { - NazaraUnused(lock); + NazaraUnused(access); NazaraUnused(size); #if NAZARA_RENDERER_SAFE - if (m_locked) + if (m_mapped) { - NazaraError("Buffer already locked"); + NazaraError("Buffer already mapped"); return nullptr; } #endif - m_locked = true; + m_mapped = true; return &m_buffer[offset]; } -bool NzSoftwareBuffer::Unlock() +bool NzSoftwareBuffer::Unmap() { #if NAZARA_RENDERER_SAFE - if (!m_locked) + if (!m_mapped) { - NazaraError("Buffer not locked"); + NazaraError("Buffer not mapped"); return true; } #endif - m_locked = false; + m_mapped = false; return true; } diff --git a/src/Nazara/Renderer/SoftwareBuffer.hpp b/src/Nazara/Renderer/SoftwareBuffer.hpp index 865b7d6d2..704f8e65f 100644 --- a/src/Nazara/Renderer/SoftwareBuffer.hpp +++ b/src/Nazara/Renderer/SoftwareBuffer.hpp @@ -27,13 +27,13 @@ class NzSoftwareBuffer : public NzBufferImpl bool IsHardware() const; - void* Lock(nzBufferLock lock, unsigned int offset = 0, unsigned int length = 0); - bool Unlock(); + void* Map(nzBufferAccess access, unsigned int offset = 0, unsigned int length = 0); + bool Unmap(); private: nzBufferType m_type; nzUInt8* m_buffer; - bool m_locked; + bool m_mapped; }; #endif // NAZARA_SOFTWAREBUFFER_HPP diff --git a/src/Nazara/Renderer/Texture.cpp b/src/Nazara/Renderer/Texture.cpp index a69dca501..c5eb3e639 100644 --- a/src/Nazara/Renderer/Texture.cpp +++ b/src/Nazara/Renderer/Texture.cpp @@ -5,6 +5,7 @@ #include #include #include +#include #include #include #include @@ -14,8 +15,9 @@ struct NzTextureImpl { // GCC 4.7 !!!!!! NzTextureImpl() : + isTarget(false), mipmapping(false), - mipmapsUpdated(false) + mipmapsUpdated(true) { } @@ -23,6 +25,7 @@ struct NzTextureImpl nzImageType type; nzPixelFormat format; nzUInt8 levelCount; + bool isTarget; bool mipmapping; bool mipmapsUpdated; unsigned int depth; @@ -73,31 +76,31 @@ namespace format->dataFormat = GL_BGR; format->dataType = GL_UNSIGNED_BYTE; format->internalFormat = GL_RGB8; - break; + return true; case nzPixelFormat_BGRA8: format->dataFormat = GL_BGRA; format->dataType = GL_UNSIGNED_BYTE; format->internalFormat = GL_RGBA8; - break; + return true; case nzPixelFormat_DXT1: format->dataFormat = GL_RGB; format->dataType = GL_UNSIGNED_BYTE; format->internalFormat = GL_COMPRESSED_RGB_S3TC_DXT1_EXT; - break; + return true; case nzPixelFormat_DXT3: format->dataFormat = GL_RGBA; format->dataType = GL_UNSIGNED_BYTE; format->internalFormat = GL_COMPRESSED_RGBA_S3TC_DXT3_EXT; - break; + return true; case nzPixelFormat_DXT5: format->dataFormat = GL_RGBA; format->dataType = GL_UNSIGNED_BYTE; format->internalFormat = GL_COMPRESSED_RGBA_S3TC_DXT5_EXT; - break; + return true; case nzPixelFormat_L8: case nzPixelFormat_LA8: @@ -108,32 +111,35 @@ namespace format->dataFormat = GL_RGBA; format->dataType = GL_UNSIGNED_SHORT_5_5_5_1; format->internalFormat = GL_RGB5_A1; - break; + return true; case nzPixelFormat_RGB8: format->dataFormat = GL_RGB; format->dataType = GL_UNSIGNED_BYTE; format->internalFormat = GL_RGB8; - break; + return true; case nzPixelFormat_RGBA4: format->dataFormat = GL_RGBA; format->dataType = GL_UNSIGNED_SHORT_4_4_4_4; format->internalFormat = GL_RGBA4; - break; + return true; case nzPixelFormat_RGBA8: format->dataFormat = GL_RGBA; format->dataType = GL_UNSIGNED_BYTE; format->internalFormat = GL_RGBA8; - break; + return true; - default: - NazaraError("Pixel format not handled"); + case nzPixelFormat_Undefined: + case nzPixelFormat_Count: + NazaraInternalError("Invalid pixel format"); return false; } - return true; + NazaraError("Pixel format not handled"); + + return false; } bool CreateTexture(NzTextureImpl* impl, bool proxy) @@ -145,8 +151,6 @@ namespace return false; } - static const bool texStorageSupported = NzOpenGL::IsSupported(NzOpenGL::TextureStorage); - GLenum target; switch (impl->type) { @@ -154,15 +158,16 @@ namespace { target = (proxy) ? GL_TEXTURE_1D : GL_PROXY_TEXTURE_1D; - if (texStorageSupported) + /*if (glTexStorage1D) glTexStorage1D(target, impl->levelCount, openGLFormat.internalFormat, impl->width); - else + else*/ { unsigned int w = impl->width; for (nzUInt8 level = 0; level < impl->levelCount; ++level) { glTexImage1D(target, level, openGLFormat.internalFormat, w, 0, openGLFormat.dataFormat, openGLFormat.dataType, nullptr); - w = std::max(w/2, 1U); + if (w > 1U) + w >>= 1; } } break; @@ -172,17 +177,20 @@ namespace { target = (proxy) ? GL_TEXTURE_2D : GL_PROXY_TEXTURE_2D; - if (texStorageSupported) + /*if (glTexStorage2D) glTexStorage2D(target, impl->levelCount, openGLFormat.internalFormat, impl->width, impl->height); - else + else*/ { unsigned int w = impl->width; unsigned int h = impl->height; for (nzUInt8 level = 0; level < impl->levelCount; ++level) { glTexImage2D(target, level, openGLFormat.internalFormat, w, h, 0, openGLFormat.dataFormat, openGLFormat.dataType, nullptr); - w = std::max(w/2, 1U); - h = std::max(h/2, 1U); + if (w > 1U) + w >>= 1; + + if (h > 1U) + h >>= 1; } } break; @@ -192,9 +200,9 @@ namespace { target = (proxy) ? GL_TEXTURE_3D : GL_PROXY_TEXTURE_3D; - if (texStorageSupported) + /*if (glTexStorage3D) glTexStorage3D(target, impl->levelCount, openGLFormat.internalFormat, impl->width, impl->height, impl->depth); - else + else*/ { unsigned int w = impl->width; unsigned int h = impl->height; @@ -202,9 +210,14 @@ namespace for (nzUInt8 level = 0; level < impl->levelCount; ++level) { glTexImage3D(target, level, openGLFormat.internalFormat, w, h, d, 0, openGLFormat.dataFormat, openGLFormat.dataType, nullptr); - w = std::max(w/2, 1U); - h = std::max(h/2, 1U); - d = std::max(d/2, 1U); + if (w > 1U) + w >>= 1; + + if (h > 1U) + h >>= 1; + + if (d > 1U) + d >>= 1; } } break; @@ -214,9 +227,9 @@ namespace { target = (proxy) ? GL_TEXTURE_CUBE_MAP : GL_PROXY_TEXTURE_CUBE_MAP; - if (texStorageSupported) + /*if (glTexStorage2D) glTexStorage2D(target, impl->levelCount, openGLFormat.internalFormat, impl->width, impl->height); - else + else*/ { unsigned int size = impl->width; // Les cubemaps ont une longueur et largeur identique for (nzUInt8 level = 0; level < impl->levelCount; ++level) @@ -224,7 +237,8 @@ namespace for (GLenum face : cubemapFace) glTexImage2D(face, level, openGLFormat.internalFormat, size, size, 0, openGLFormat.dataFormat, openGLFormat.dataType, nullptr); - size = std::max(size/2, 1U); + if (size > 1U) + size >>= 1; } } break; @@ -253,6 +267,8 @@ namespace { if (lockedLevel[impl->type]++ == 0) { + NzContext::EnsureContext(); + GLint previous; glGetIntegerv(openglTargetBinding[impl->type], &previous); @@ -265,6 +281,14 @@ namespace void UnlockTexture(NzTextureImpl* impl) { + #ifdef NAZARA_DEBUG + if (NzContext::GetCurrent() == nullptr) + { + NazaraError("No active context"); + return; + } + #endif + #if NAZARA_RENDERER_SAFE if (lockedLevel[impl->type] == 0) { @@ -302,7 +326,7 @@ NzTexture::~NzTexture() Destroy(); } -bool NzTexture::Bind() +bool NzTexture::Bind() const { #if NAZARA_RENDERER_SAFE if (lockedLevel[m_impl->type] > 0) @@ -314,11 +338,25 @@ bool NzTexture::Bind() glBindTexture(openglTarget[m_impl->type], m_impl->id); + if (!m_impl->mipmapsUpdated) + { + glGenerateMipmap(openglTarget[m_impl->type]); + m_impl->mipmapsUpdated = true; + } + return true; } bool NzTexture::Create(nzImageType type, nzPixelFormat format, unsigned int width, unsigned int height, unsigned int depth, nzUInt8 levelCount, bool lock) { + #if NAZARA_RENDERER_SAFE + if (m_impl && m_impl->isTarget) + { + NazaraError("Texture is a target, it cannot be recreated"); + return false; + } + #endif + Destroy(); if (width == 0 || height == 0 || depth == 0) @@ -348,7 +386,7 @@ bool NzTexture::Create(nzImageType type, nzPixelFormat format, unsigned int widt case nzImageType_1D: if (height > 1) { - NazaraError("1D textures must be 1 height"); + NazaraError("One dimensional texture's height must be 1"); return false; } @@ -390,6 +428,8 @@ bool NzTexture::Create(nzImageType type, nzPixelFormat format, unsigned int widt } #endif + NzContext::EnsureContext(); + levelCount = std::min(levelCount, NzImage::GetMaxLevel(width, height, depth)); NzTextureImpl* impl = new NzTextureImpl; @@ -433,6 +473,12 @@ bool NzTexture::Create(nzImageType type, nzPixelFormat format, unsigned int widt SetMipmapRange(0, m_impl->levelCount); SetWrapMode(nzTextureWrap_Repeat); + if (m_impl->levelCount > 1U) + { + m_impl->mipmapping = true; + m_impl->mipmapsUpdated = false; + } + if (!lock) UnlockTexture(impl); @@ -443,6 +489,16 @@ void NzTexture::Destroy() { if (m_impl) { + #if NAZARA_RENDERER_SAFE + if (m_impl->isTarget) + { + NazaraError("Texture is a target, it cannot be destroyed"); + return; + } + #endif + + NzContext::EnsureContext(); + glDeleteTextures(1, &m_impl->id); delete m_impl; m_impl = nullptr; @@ -505,9 +561,14 @@ bool NzTexture::Download(NzImage* image) const ptr += faceSize; } - width = std::max(width >> 1, 1U); - height = std::max(height >> 1, 1U); - depth = std::max(depth >> 1, 1U); + if (width > 1) + width >>= 1; + + if (height > 1) + height >>= 1; + + if (depth > 1) + depth >>= 1; } UnlockTexture(m_impl); @@ -533,15 +594,22 @@ bool NzTexture::EnableMipmapping(bool enable) return false; } - LockTexture(m_impl); - if (!m_impl->mipmapping && enable) - glGenerateMipmap(openglTarget[m_impl->type]); + { + GLint tex; + glGetIntegerv(openglTargetBinding[m_impl->type], &tex); + + if (m_impl->id == static_cast(tex)) + { + glGenerateMipmap(openglTarget[m_impl->type]); + m_impl->mipmapsUpdated = true; + } + else + m_impl->mipmapsUpdated = false; + } m_impl->mipmapping = enable; - UnlockTexture(m_impl); - return true; } @@ -744,6 +812,19 @@ bool NzTexture::IsCubemap() const return m_impl->type == nzImageType_Cubemap; } +bool NzTexture::IsTarget() const +{ + #if NAZARA_RENDERER_SAFE + if (!IsValid()) + { + NazaraError("Texture must be valid"); + return false; + } + #endif + + return m_impl->isTarget; +} + bool NzTexture::IsValid() const { return m_impl != nullptr; @@ -1059,7 +1140,7 @@ bool NzTexture::Update(const NzImage& image, const NzRectui& rect, unsigned int return Update(image.GetConstPixels(level), rect, z, level); } -/* + bool NzTexture::Update(const NzImage& image, const NzCubeui& cube, nzUInt8 level) { #if NAZARA_RENDERER_SAFE @@ -1078,7 +1159,7 @@ bool NzTexture::Update(const NzImage& image, const NzCubeui& cube, nzUInt8 level return Update(image.GetConstPixels(level), cube, level); } -*/ + bool NzTexture::Update(const nzUInt8* pixels, nzUInt8 level) { #if NAZARA_RENDERER_SAFE @@ -1090,11 +1171,7 @@ bool NzTexture::Update(const nzUInt8* pixels, nzUInt8 level) #endif if (m_impl->type == nzImageType_3D) - { - NazaraInternalError("Not implemented yet, sorry"); - return false; - //return Update(pixels, NzCube(0, 0, 0, std::max(m_impl->width >> level, 1U), std::max(m_impl->height >> level, 1U), std::max(m_impl->depth >> level, 1U)), level); - } + return Update(pixels, NzCubeui(0, 0, 0, std::max(m_impl->width >> level, 1U), std::max(m_impl->height >> level, 1U), std::max(m_impl->depth >> level, 1U)), level); else return Update(pixels, NzRectui(0, 0, std::max(m_impl->width >> level, 1U), std::max(m_impl->height >> level, 1U)), 0, level); } @@ -1108,6 +1185,12 @@ bool NzTexture::Update(const nzUInt8* pixels, const NzRectui& rect, unsigned int return false; } + if (m_impl->isTarget) + { + NazaraError("Texture is a target, it cannot be updated"); + return false; + } + if (m_impl->type == nzImageType_Cubemap) { NazaraError("Update is not designed for cubemaps, use UpdateFace instead"); @@ -1190,8 +1273,8 @@ bool NzTexture::Update(const nzUInt8* pixels, const NzRectui& rect, unsigned int return true; } -/* -bool NzTexture::Update(const nzUInt8* pixels, const NzCubeui& cube, nzUInt8 level = 0) + +bool NzTexture::Update(const nzUInt8* pixels, const NzCubeui& cube, nzUInt8 level) { #if NAZARA_RENDERER_SAFE if (!IsValid()) @@ -1200,6 +1283,12 @@ bool NzTexture::Update(const nzUInt8* pixels, const NzCubeui& cube, nzUInt8 leve return false; } + if (m_impl->isTarget) + { + NazaraError("Texture is a target, it cannot be updated"); + return false; + } + if (m_impl->type == nzImageType_Cubemap) { NazaraError("Update is not designed for cubemaps, use UpdateFace instead"); @@ -1263,15 +1352,15 @@ bool NzTexture::Update(const nzUInt8* pixels, const NzCubeui& cube, nzUInt8 leve switch (m_impl->type) { case nzImageType_1D: - glTexSubImage1D(GL_TEXTURE_1D, level, cube.x, cube.width, format->dataFormat, format->dataType, mirrored); + glTexSubImage1D(GL_TEXTURE_1D, level, cube.x, cube.width, format.dataFormat, format.dataType, mirrored); break; case nzImageType_2D: - glTexSubImage1D(GL_TEXTURE_2D, level, cube.x, cube.y, cube.width, cube.height, format->dataFormat, format->dataType, mirrored); + glTexSubImage2D(GL_TEXTURE_2D, level, cube.x, cube.y, cube.width, cube.height, format.dataFormat, format.dataType, mirrored); break; case nzImageType_3D: - glTexSubImage1D(GL_TEXTURE_3D, level, cube.x, cube.y, cube.z, cube.width, cube.height, cube.depth, format->dataFormat, format->dataType, mirrored); + glTexSubImage3D(GL_TEXTURE_3D, level, cube.x, cube.y, cube.z, cube.width, cube.height, cube.depth, format.dataFormat, format.dataType, mirrored); break; default: @@ -1284,7 +1373,7 @@ bool NzTexture::Update(const nzUInt8* pixels, const NzCubeui& cube, nzUInt8 leve return true; } -*/ + bool NzTexture::UpdateFace(nzCubemapFace face, const NzImage& image, nzUInt8 level) { #if NAZARA_RENDERER_SAFE @@ -1345,6 +1434,12 @@ bool NzTexture::UpdateFace(nzCubemapFace face, const nzUInt8* pixels, const NzRe return false; } + if (m_impl->isTarget) + { + NazaraError("Texture is a target, it cannot be updated"); + return false; + } + if (m_impl->type != nzImageType_Cubemap) { NazaraError("UpdateFace is designed for cubemaps, use Update instead"); @@ -1433,14 +1528,6 @@ unsigned int NzTexture::GetValidSize(unsigned int size) bool NzTexture::IsFormatSupported(nzPixelFormat format) { - #if NAZARA_RENDERER_SAFE - if (!NzPixelFormat::IsValid(format)) - { - NazaraError("Invalid pixel format"); - return nzPixelFormat_Undefined; - } - #endif - switch (format) { // Formats de base @@ -1468,9 +1555,14 @@ bool NzTexture::IsFormatSupported(nzPixelFormat format) return supported; } - default: - return false; + case nzPixelFormat_Undefined: + case nzPixelFormat_Count: + break; } + + NazaraError("Invalid pixel format"); + + return false; } bool NzTexture::IsTypeSupported(nzImageType type) @@ -1487,3 +1579,16 @@ bool NzTexture::IsTypeSupported(nzImageType type) return false; } } + +void NzTexture::SetTarget(bool isTarget) +{ + #if NAZARA_RENDERER_SAFE + if (!IsValid()) + { + NazaraInternalError("Texture must be valid"); + return; + } + #endif + + m_impl->isTarget = isTarget; +} diff --git a/src/Nazara/Renderer/VertexBuffer.cpp b/src/Nazara/Renderer/VertexBuffer.cpp index 62bdac667..fed64316b 100644 --- a/src/Nazara/Renderer/VertexBuffer.cpp +++ b/src/Nazara/Renderer/VertexBuffer.cpp @@ -97,7 +97,7 @@ bool NzVertexBuffer::IsHardware() const return m_buffer->IsHardware(); } -void* NzVertexBuffer::Lock(nzBufferLock lock, unsigned int offset, unsigned int length) +void* NzVertexBuffer::Map(nzBufferAccess access, unsigned int offset, unsigned int length) { #if NAZARA_RENDERER_SAFE if (offset+length > m_vertexCount) @@ -107,10 +107,10 @@ void* NzVertexBuffer::Lock(nzBufferLock lock, unsigned int offset, unsigned int } #endif - return m_buffer->Lock(lock, m_startVertex+offset, (length) ? length : m_vertexCount-offset); + return m_buffer->Map(access, m_startVertex+offset, (length) ? length : m_vertexCount-offset); } -bool NzVertexBuffer::Unlock() +bool NzVertexBuffer::Unmap() { - return m_buffer->Unlock(); + return m_buffer->Unmap(); } diff --git a/src/Nazara/Utility/Image.cpp b/src/Nazara/Utility/Image.cpp index aeca004a7..d5a1f08b6 100644 --- a/src/Nazara/Utility/Image.cpp +++ b/src/Nazara/Utility/Image.cpp @@ -701,21 +701,72 @@ bool NzImage::Update(const nzUInt8* pixels, const NzRectui& rect, unsigned int z return false; } + if (level >= m_sharedImage->levelCount) + { + NazaraError("Level out of bounds (" + NzString::Number(level) + " >= " + NzString::Number(m_sharedImage->levelCount) + ')'); + return false; + } + #endif + + unsigned int width = std::max(m_sharedImage->width >> level, 1U); + unsigned int height = std::max(m_sharedImage->height >> level, 1U); + + #if NAZARA_UTILITY_SAFE if (!rect.IsValid()) { NazaraError("Invalid rectangle"); return false; } - if (rect.x+rect.width > std::max(m_sharedImage->width >> level, 1U) || rect.y+rect.height > std::max(m_sharedImage->height >> level, 1U)) + if (rect.x+rect.width > width || rect.y+rect.height > height) { NazaraError("Rectangle dimensions are out of bounds"); return false; } - if (z >= std::max(m_sharedImage->depth >> level, 1U)) + unsigned int depth = std::max(m_sharedImage->depth >> level, 1U); + if (z >= depth) { - NazaraError("Z value exceeds depth (" + NzString::Number(z) + " >= (" + NzString::Number(m_sharedImage->depth) + ')'); + NazaraError("Z value exceeds depth (" + NzString::Number(z) + " >= (" + NzString::Number(depth) + ')'); + return false; + } + #endif + + EnsureOwnership(); + + nzUInt8 bpp = NzPixelFormat::GetBPP(m_sharedImage->format); + nzUInt8* dstPixels = &m_sharedImage->pixels[level][(height*(width*z + rect.y) + rect.x) * bpp]; + unsigned int srcStride = rect.width * bpp; + unsigned int blockSize = width * bpp; + for (unsigned int i = 0; i < rect.height; ++i) + { + std::memcpy(dstPixels, pixels, blockSize); + pixels += srcStride; + dstPixels += blockSize; + } + + return true; +} + +bool NzImage::Update(const nzUInt8* pixels, const NzCubeui& cube, nzUInt8 level) +{ + ///FIXME: Vérifier que ça fonctionne correctement + #if NAZARA_UTILITY_SAFE + if (!IsValid()) + { + NazaraError("Image must be valid"); + return false; + } + + if (m_sharedImage->type == nzImageType_Cubemap) + { + NazaraError("Update is not designed for cubemaps, use UpdateFace instead"); + return false; + } + + if (!pixels) + { + NazaraError("Invalid pixel source"); return false; } @@ -726,17 +777,42 @@ bool NzImage::Update(const nzUInt8* pixels, const NzRectui& rect, unsigned int z } #endif + unsigned int width = std::max(m_sharedImage->width >> level, 1U); + unsigned int height = std::max(m_sharedImage->height >> level, 1U); + unsigned int depth = std::max(m_sharedImage->height >> level, 1U); + + #if NAZARA_UTILITY_SAFE + if (!cube.IsValid()) + { + NazaraError("Invalid cube"); + return false; + } + + if (cube.x+cube.width > width || cube.y+cube.height > height || cube.z+cube.depth > depth) + { + NazaraError("Cube dimensions are out of bounds"); + return false; + } + #endif + EnsureOwnership(); nzUInt8 bpp = NzPixelFormat::GetBPP(m_sharedImage->format); - nzUInt8* dstPixels = &m_sharedImage->pixels[level][(m_sharedImage->height*(m_sharedImage->width*z + rect.y) + rect.x) * bpp]; - unsigned int srcStride = rect.width * bpp; - unsigned int blockSize = m_sharedImage->width * bpp; - for (unsigned int i = 0; i < rect.height; ++i) + nzUInt8* dstPixels = &m_sharedImage->pixels[level][(height*(width*cube.z + cube.y) + cube.x) * bpp]; + unsigned int srcStride = cube.width * bpp; + unsigned int blockSize = width * bpp; + unsigned int faceSize = width * height * bpp; + for (unsigned int z = 0; z < cube.depth; ++z) { - std::memcpy(dstPixels, pixels, blockSize); - pixels += srcStride; - dstPixels += blockSize; + nzUInt8* facePixels = dstPixels; + for (unsigned int i = 0; i < cube.height; ++i) + { + std::memcpy(dstPixels, pixels, blockSize); + pixels += srcStride; + facePixels += blockSize; + } + + dstPixels += faceSize; } return true; diff --git a/src/Nazara/Utility/Loaders/STB.cpp b/src/Nazara/Utility/Loaders/STB.cpp index ff0e3fbea..1b6ed1c6b 100644 --- a/src/Nazara/Utility/Loaders/STB.cpp +++ b/src/Nazara/Utility/Loaders/STB.cpp @@ -21,19 +21,19 @@ namespace { int Read(void* userdata, char* data, int size) { - NzInputStream* stream = static_cast(userdata); + NzInputStream* stream = reinterpret_cast(userdata); return static_cast(stream->Read(data, size)); } void Skip(void* userdata, unsigned int size) { - NzInputStream* stream = static_cast(userdata); + NzInputStream* stream = reinterpret_cast(userdata); stream->Read(nullptr, size); } int Eof(void* userdata) { - NzInputStream* stream = static_cast(userdata); + NzInputStream* stream = reinterpret_cast(userdata); return stream->GetCursorPos() >= stream->GetSize(); } @@ -63,7 +63,8 @@ namespace { NazaraUnused(parameters); - static nzPixelFormat formats[4] = { + static const nzPixelFormat formats[4] = + { nzPixelFormat_L8, nzPixelFormat_LA8, nzPixelFormat_RGB8, @@ -134,7 +135,7 @@ namespace NazaraUnused(parameters); int width, height, bpp; - return stbi_info_from_memory(static_cast(data), size, &width, &height, &bpp); + return stbi_info_from_memory(reinterpret_cast(data), size, &width, &height, &bpp); } bool NzLoader_STB_IsStreamLoadingSupported(NzInputStream& stream, const NzImageParams& parameters) diff --git a/src/Nazara/Utility/PixelFormat.cpp b/src/Nazara/Utility/PixelFormat.cpp index 84685f296..1a189181e 100644 --- a/src/Nazara/Utility/PixelFormat.cpp +++ b/src/Nazara/Utility/PixelFormat.cpp @@ -1317,4 +1317,4 @@ void NzPixelFormat::Uninitialize() std::memset(s_convertFunctions, 0, nzPixelFormat_Count*nzPixelFormat_Count*sizeof(NzPixelFormat::ConvertFunction)); } -NzPixelFormat::ConvertFunction NzPixelFormat::s_convertFunctions[nzPixelFormat_Count][nzPixelFormat_Count] = {{0}}; +NzPixelFormat::ConvertFunction NzPixelFormat::s_convertFunctions[nzPixelFormat_Count][nzPixelFormat_Count] = {{0}}; ///FIXME: Fonctionne correctement ? diff --git a/src/Nazara/Utility/Win32/InputImpl.cpp b/src/Nazara/Utility/Win32/InputImpl.cpp index 3423b16c8..4d44710db 100644 --- a/src/Nazara/Utility/Win32/InputImpl.cpp +++ b/src/Nazara/Utility/Win32/InputImpl.cpp @@ -18,7 +18,7 @@ NzVector2i NzEventImpl::GetMousePosition() NzVector2i NzEventImpl::GetMousePosition(const NzWindow& relativeTo) { - HWND handle = static_cast(relativeTo.GetHandle()); + HWND handle = reinterpret_cast(relativeTo.GetHandle()); if (handle) { POINT pos; @@ -229,7 +229,7 @@ void NzEventImpl::SetMousePosition(int x, int y) void NzEventImpl::SetMousePosition(int x, int y, const NzWindow& relativeTo) { - HWND handle = static_cast(relativeTo.GetHandle()); + HWND handle = reinterpret_cast(relativeTo.GetHandle()); if (handle) { POINT pos = {x, y}; diff --git a/src/Nazara/Utility/Win32/WindowImpl.cpp b/src/Nazara/Utility/Win32/WindowImpl.cpp index 946045a5c..8ce9a18b7 100644 --- a/src/Nazara/Utility/Win32/WindowImpl.cpp +++ b/src/Nazara/Utility/Win32/WindowImpl.cpp @@ -166,7 +166,7 @@ bool NzWindowImpl::Create(NzWindowHandle handle) return false; } - m_handle = static_cast(handle); + m_handle = reinterpret_cast(handle); m_eventListener = false; m_ownsWindow = false; @@ -354,7 +354,7 @@ void NzWindowImpl::ShowMouseCursor(bool show) // http://msdn.microsoft.com/en-us/library/windows/desktop/ms648045(v=vs.85).aspx if (show) - m_cursor = static_cast(LoadImage(nullptr, MAKEINTRESOURCE(OCR_NORMAL), IMAGE_CURSOR, 0, 0, LR_SHARED)); + m_cursor = reinterpret_cast(LoadImage(nullptr, MAKEINTRESOURCE(OCR_NORMAL), IMAGE_CURSOR, 0, 0, LR_SHARED)); else m_cursor = nullptr;