Merge branch 'NDK-Refactor' into NDK
Conflicts: examples/HardwareInfo/main.cpp include/Nazara/Renderer/Enums.hpp include/Nazara/Renderer/GpuQuery.hpp include/Nazara/Renderer/OpenGL.hpp include/Nazara/Renderer/RenderBuffer.hpp include/Nazara/Renderer/RenderTexture.hpp include/Nazara/Renderer/Texture.hpp src/Nazara/Graphics/AbstractRenderTechnique.cpp src/Nazara/Graphics/DeferredRenderTechnique.cpp src/Nazara/Graphics/Material.cpp src/Nazara/Graphics/SkyboxBackground.cpp src/Nazara/Renderer/GpuQuery.cpp src/Nazara/Renderer/OpenGL.cpp src/Nazara/Renderer/RenderBuffer.cpp src/Nazara/Renderer/RenderTexture.cpp src/Nazara/Renderer/Renderer.cpp src/Nazara/Renderer/Shader.cpp src/Nazara/Renderer/ShaderStage.cpp src/Nazara/Renderer/Texture.cpp Former-commit-id: 2f1c7e9f9766f59ab83d9405856a1898ac4ab48f
This commit is contained in:
@@ -23,351 +23,354 @@
|
||||
|
||||
#include <Nazara/Renderer/Debug.hpp>
|
||||
|
||||
namespace
|
||||
namespace Nz
|
||||
{
|
||||
thread_local const NzContext* s_currentContext = nullptr;
|
||||
thread_local const NzContext* s_threadContext = nullptr;
|
||||
|
||||
void CALLBACK DebugCallback(unsigned int source, unsigned int type, unsigned int id, unsigned int severity, int length, const char* message, const void* userParam)
|
||||
namespace
|
||||
{
|
||||
NazaraUnused(length);
|
||||
thread_local const Context* s_currentContext = nullptr;
|
||||
thread_local const Context* s_threadContext = nullptr;
|
||||
|
||||
NzStringStream ss;
|
||||
ss << "OpenGL debug message (ID: 0x" << NzString::Number(id, 16) << "):\n";
|
||||
ss << "Sent by context: " << userParam;
|
||||
ss << "\n-Source: ";
|
||||
switch (source)
|
||||
void CALLBACK DebugCallback(unsigned int source, unsigned int type, unsigned int id, unsigned int severity, int length, const char* message, const void* userParam)
|
||||
{
|
||||
case GL_DEBUG_SOURCE_API:
|
||||
ss << "OpenGL API";
|
||||
break;
|
||||
NazaraUnused(length);
|
||||
|
||||
case GL_DEBUG_SOURCE_WINDOW_SYSTEM:
|
||||
ss << "Operating system";
|
||||
break;
|
||||
|
||||
case GL_DEBUG_SOURCE_SHADER_COMPILER:
|
||||
ss << "Shader compiler";
|
||||
break;
|
||||
|
||||
case GL_DEBUG_SOURCE_THIRD_PARTY:
|
||||
ss << "Third party";
|
||||
break;
|
||||
|
||||
case GL_DEBUG_SOURCE_APPLICATION:
|
||||
ss << "Application";
|
||||
break;
|
||||
|
||||
case GL_DEBUG_SOURCE_OTHER:
|
||||
ss << "Other";
|
||||
break;
|
||||
|
||||
default:
|
||||
// Peut être rajouté par une extension
|
||||
ss << "Unknown";
|
||||
break;
|
||||
}
|
||||
ss << '\n';
|
||||
|
||||
ss << "-Type: ";
|
||||
switch (type)
|
||||
{
|
||||
case GL_DEBUG_TYPE_ERROR:
|
||||
ss << "Error";
|
||||
break;
|
||||
|
||||
case GL_DEBUG_TYPE_DEPRECATED_BEHAVIOR:
|
||||
ss << "Deprecated behavior";
|
||||
break;
|
||||
|
||||
case GL_DEBUG_TYPE_UNDEFINED_BEHAVIOR:
|
||||
ss << "Undefined behavior";
|
||||
break;
|
||||
|
||||
case GL_DEBUG_TYPE_PORTABILITY:
|
||||
ss << "Portability";
|
||||
break;
|
||||
|
||||
case GL_DEBUG_TYPE_PERFORMANCE:
|
||||
ss << "Performance";
|
||||
break;
|
||||
|
||||
case GL_DEBUG_TYPE_OTHER:
|
||||
ss << "Other";
|
||||
break;
|
||||
|
||||
default:
|
||||
// Peut être rajouté par une extension
|
||||
ss << "Unknown";
|
||||
break;
|
||||
}
|
||||
ss << '\n';
|
||||
|
||||
ss << "-Severity: ";
|
||||
switch (severity)
|
||||
{
|
||||
case GL_DEBUG_SEVERITY_HIGH:
|
||||
ss << "High";
|
||||
break;
|
||||
|
||||
case GL_DEBUG_SEVERITY_MEDIUM:
|
||||
ss << "Medium";
|
||||
break;
|
||||
|
||||
case GL_DEBUG_SEVERITY_LOW:
|
||||
ss << "Low";
|
||||
break;
|
||||
|
||||
default:
|
||||
// Peut être rajouté par une extension
|
||||
ss << "Unknown";
|
||||
break;
|
||||
}
|
||||
ss << '\n';
|
||||
|
||||
ss << "Message: " << message << '\n';
|
||||
|
||||
NazaraNotice(ss);
|
||||
}
|
||||
}
|
||||
|
||||
NzContext::~NzContext()
|
||||
{
|
||||
OnContextRelease(this);
|
||||
|
||||
Destroy();
|
||||
}
|
||||
|
||||
bool NzContext::Create(const NzContextParameters& parameters)
|
||||
{
|
||||
Destroy();
|
||||
|
||||
m_parameters = parameters;
|
||||
if (m_parameters.shared && !m_parameters.shareContext)
|
||||
m_parameters.shareContext = s_reference.get();
|
||||
|
||||
std::unique_ptr<NzContextImpl> impl(new NzContextImpl);
|
||||
if (!impl->Create(m_parameters))
|
||||
{
|
||||
NazaraError("Failed to create context implementation");
|
||||
return false;
|
||||
}
|
||||
|
||||
m_impl = impl.release();
|
||||
|
||||
NzCallOnExit onExit([this] () { Destroy(); });
|
||||
|
||||
if (!SetActive(true))
|
||||
{
|
||||
NazaraError("Failed to activate context");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (m_parameters.antialiasingLevel > 0)
|
||||
glEnable(GL_MULTISAMPLE);
|
||||
|
||||
if (m_parameters.debugMode && NzOpenGL::IsSupported(nzOpenGLExtension_DebugOutput))
|
||||
{
|
||||
glDebugMessageCallback(&DebugCallback, this);
|
||||
|
||||
#ifdef NAZARA_DEBUG
|
||||
glEnable(GL_DEBUG_OUTPUT_SYNCHRONOUS);
|
||||
#endif
|
||||
}
|
||||
|
||||
onExit.Reset();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void NzContext::Destroy()
|
||||
{
|
||||
if (m_impl)
|
||||
{
|
||||
OnContextDestroy(this);
|
||||
|
||||
NzOpenGL::OnContextDestruction(this);
|
||||
SetActive(false);
|
||||
|
||||
m_impl->Destroy();
|
||||
delete m_impl;
|
||||
m_impl = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
void NzContext::EnableVerticalSync(bool enabled)
|
||||
{
|
||||
#ifdef NAZARA_RENDERER_SAFE
|
||||
if (!m_impl)
|
||||
{
|
||||
NazaraError("No context has been created");
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
m_impl->EnableVerticalSync(enabled);
|
||||
}
|
||||
|
||||
const NzContextParameters& NzContext::GetParameters() const
|
||||
{
|
||||
#ifdef NAZARA_RENDERER_SAFE
|
||||
if (!m_impl)
|
||||
NazaraError("No context has been created");
|
||||
#endif
|
||||
|
||||
return m_parameters;
|
||||
}
|
||||
|
||||
bool NzContext::IsActive() const
|
||||
{
|
||||
#ifdef NAZARA_RENDERER_SAFE
|
||||
if (!m_impl)
|
||||
{
|
||||
NazaraError("No context has been created");
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
|
||||
return s_currentContext == this;
|
||||
}
|
||||
|
||||
bool NzContext::SetActive(bool active) const
|
||||
{
|
||||
#ifdef NAZARA_RENDERER_SAFE
|
||||
if (!m_impl)
|
||||
{
|
||||
NazaraError("No context has been created");
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
|
||||
// Si le contexte est déjà activé/désactivé
|
||||
if ((s_currentContext == this) == active)
|
||||
return true;
|
||||
|
||||
if (active)
|
||||
{
|
||||
if (!m_impl->Activate())
|
||||
return false;
|
||||
|
||||
s_currentContext = this;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!NzContextImpl::Desactivate())
|
||||
return false;
|
||||
|
||||
s_currentContext = nullptr;
|
||||
}
|
||||
|
||||
NzOpenGL::OnContextChanged(s_currentContext);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void NzContext::SwapBuffers()
|
||||
{
|
||||
#ifdef NAZARA_RENDERER_SAFE
|
||||
if (!m_impl)
|
||||
{
|
||||
NazaraError("No context has been created");
|
||||
return;
|
||||
}
|
||||
|
||||
if (!m_parameters.doubleBuffered)
|
||||
{
|
||||
NazaraError("Context is not double buffered");
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
m_impl->SwapBuffers();
|
||||
}
|
||||
|
||||
bool NzContext::EnsureContext()
|
||||
{
|
||||
if (!s_currentContext)
|
||||
{
|
||||
if (!s_threadContext)
|
||||
{
|
||||
std::unique_ptr<NzContext> context(new NzContext);
|
||||
if (!context->Create())
|
||||
StringStream ss;
|
||||
ss << "OpenGL debug message (ID: 0x" << String::Number(id, 16) << "):\n";
|
||||
ss << "Sent by context: " << userParam;
|
||||
ss << "\n-Source: ";
|
||||
switch (source)
|
||||
{
|
||||
NazaraError("Failed to create context");
|
||||
case GL_DEBUG_SOURCE_API:
|
||||
ss << "OpenGL API";
|
||||
break;
|
||||
|
||||
case GL_DEBUG_SOURCE_WINDOW_SYSTEM:
|
||||
ss << "Operating system";
|
||||
break;
|
||||
|
||||
case GL_DEBUG_SOURCE_SHADER_COMPILER:
|
||||
ss << "Shader compiler";
|
||||
break;
|
||||
|
||||
case GL_DEBUG_SOURCE_THIRD_PARTY:
|
||||
ss << "Third party";
|
||||
break;
|
||||
|
||||
case GL_DEBUG_SOURCE_APPLICATION:
|
||||
ss << "Application";
|
||||
break;
|
||||
|
||||
case GL_DEBUG_SOURCE_OTHER:
|
||||
ss << "Other";
|
||||
break;
|
||||
|
||||
default:
|
||||
// Peut être rajouté par une extension
|
||||
ss << "Unknown";
|
||||
break;
|
||||
}
|
||||
ss << '\n';
|
||||
|
||||
ss << "-Type: ";
|
||||
switch (type)
|
||||
{
|
||||
case GL_DEBUG_TYPE_ERROR:
|
||||
ss << "Error";
|
||||
break;
|
||||
|
||||
case GL_DEBUG_TYPE_DEPRECATED_BEHAVIOR:
|
||||
ss << "Deprecated behavior";
|
||||
break;
|
||||
|
||||
case GL_DEBUG_TYPE_UNDEFINED_BEHAVIOR:
|
||||
ss << "Undefined behavior";
|
||||
break;
|
||||
|
||||
case GL_DEBUG_TYPE_PORTABILITY:
|
||||
ss << "Portability";
|
||||
break;
|
||||
|
||||
case GL_DEBUG_TYPE_PERFORMANCE:
|
||||
ss << "Performance";
|
||||
break;
|
||||
|
||||
case GL_DEBUG_TYPE_OTHER:
|
||||
ss << "Other";
|
||||
break;
|
||||
|
||||
default:
|
||||
// Peut être rajouté par une extension
|
||||
ss << "Unknown";
|
||||
break;
|
||||
}
|
||||
ss << '\n';
|
||||
|
||||
ss << "-Severity: ";
|
||||
switch (severity)
|
||||
{
|
||||
case GL_DEBUG_SEVERITY_HIGH:
|
||||
ss << "High";
|
||||
break;
|
||||
|
||||
case GL_DEBUG_SEVERITY_MEDIUM:
|
||||
ss << "Medium";
|
||||
break;
|
||||
|
||||
case GL_DEBUG_SEVERITY_LOW:
|
||||
ss << "Low";
|
||||
break;
|
||||
|
||||
default:
|
||||
// Peut être rajouté par une extension
|
||||
ss << "Unknown";
|
||||
break;
|
||||
}
|
||||
ss << '\n';
|
||||
|
||||
ss << "Message: " << message << '\n';
|
||||
|
||||
NazaraNotice(ss);
|
||||
}
|
||||
}
|
||||
|
||||
Context::~Context()
|
||||
{
|
||||
OnContextRelease(this);
|
||||
|
||||
Destroy();
|
||||
}
|
||||
|
||||
bool Context::Create(const ContextParameters& parameters)
|
||||
{
|
||||
Destroy();
|
||||
|
||||
m_parameters = parameters;
|
||||
if (m_parameters.shared && !m_parameters.shareContext)
|
||||
m_parameters.shareContext = s_reference.get();
|
||||
|
||||
std::unique_ptr<ContextImpl> impl(new ContextImpl);
|
||||
if (!impl->Create(m_parameters))
|
||||
{
|
||||
NazaraError("Failed to create context implementation");
|
||||
return false;
|
||||
}
|
||||
|
||||
m_impl = impl.release();
|
||||
|
||||
CallOnExit onExit([this] () { Destroy(); });
|
||||
|
||||
if (!SetActive(true))
|
||||
{
|
||||
NazaraError("Failed to activate context");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (m_parameters.antialiasingLevel > 0)
|
||||
glEnable(GL_MULTISAMPLE);
|
||||
|
||||
if (m_parameters.debugMode && OpenGL::IsSupported(OpenGLExtension_DebugOutput))
|
||||
{
|
||||
glDebugMessageCallback(&DebugCallback, this);
|
||||
|
||||
#ifdef NAZARA_DEBUG
|
||||
glEnable(GL_DEBUG_OUTPUT_SYNCHRONOUS);
|
||||
#endif
|
||||
}
|
||||
|
||||
onExit.Reset();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void Context::Destroy()
|
||||
{
|
||||
if (m_impl)
|
||||
{
|
||||
OnContextDestroy(this);
|
||||
|
||||
OpenGL::OnContextDestruction(this);
|
||||
SetActive(false);
|
||||
|
||||
m_impl->Destroy();
|
||||
delete m_impl;
|
||||
m_impl = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
void Context::EnableVerticalSync(bool enabled)
|
||||
{
|
||||
#ifdef NAZARA_RENDERER_SAFE
|
||||
if (!m_impl)
|
||||
{
|
||||
NazaraError("No context has been created");
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
m_impl->EnableVerticalSync(enabled);
|
||||
}
|
||||
|
||||
const ContextParameters& Context::GetParameters() const
|
||||
{
|
||||
#ifdef NAZARA_RENDERER_SAFE
|
||||
if (!m_impl)
|
||||
NazaraError("No context has been created");
|
||||
#endif
|
||||
|
||||
return m_parameters;
|
||||
}
|
||||
|
||||
bool Context::IsActive() const
|
||||
{
|
||||
#ifdef NAZARA_RENDERER_SAFE
|
||||
if (!m_impl)
|
||||
{
|
||||
NazaraError("No context has been created");
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
|
||||
return s_currentContext == this;
|
||||
}
|
||||
|
||||
bool Context::SetActive(bool active) const
|
||||
{
|
||||
#ifdef NAZARA_RENDERER_SAFE
|
||||
if (!m_impl)
|
||||
{
|
||||
NazaraError("No context has been created");
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
|
||||
// Si le contexte est déjà activé/désactivé
|
||||
if ((s_currentContext == this) == active)
|
||||
return true;
|
||||
|
||||
if (active)
|
||||
{
|
||||
if (!m_impl->Activate())
|
||||
return false;
|
||||
|
||||
s_currentContext = this;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!ContextImpl::Desactivate())
|
||||
return false;
|
||||
|
||||
s_currentContext = nullptr;
|
||||
}
|
||||
|
||||
OpenGL::OnContextChanged(s_currentContext);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void Context::SwapBuffers()
|
||||
{
|
||||
#ifdef NAZARA_RENDERER_SAFE
|
||||
if (!m_impl)
|
||||
{
|
||||
NazaraError("No context has been created");
|
||||
return;
|
||||
}
|
||||
|
||||
if (!m_parameters.doubleBuffered)
|
||||
{
|
||||
NazaraError("Context is not double buffered");
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
m_impl->SwapBuffers();
|
||||
}
|
||||
|
||||
bool Context::EnsureContext()
|
||||
{
|
||||
if (!s_currentContext)
|
||||
{
|
||||
if (!s_threadContext)
|
||||
{
|
||||
std::unique_ptr<Context> context(new Context);
|
||||
if (!context->Create())
|
||||
{
|
||||
NazaraError("Failed to create context");
|
||||
return false;
|
||||
}
|
||||
|
||||
s_threadContext = context.get();
|
||||
|
||||
s_contexts.emplace_back(std::move(context));
|
||||
}
|
||||
|
||||
s_threadContext = context.get();
|
||||
|
||||
s_contexts.emplace_back(std::move(context));
|
||||
if (!s_threadContext->SetActive(true))
|
||||
{
|
||||
NazaraError("Failed to active thread context");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (!s_threadContext->SetActive(true))
|
||||
return true;
|
||||
}
|
||||
|
||||
const Context* Context::GetCurrent()
|
||||
{
|
||||
return s_currentContext;
|
||||
}
|
||||
|
||||
const Context* Context::GetReference()
|
||||
{
|
||||
return s_reference.get();
|
||||
}
|
||||
|
||||
const Context* Context::GetThreadContext()
|
||||
{
|
||||
EnsureContext();
|
||||
|
||||
return s_threadContext;
|
||||
}
|
||||
|
||||
bool Context::Initialize()
|
||||
{
|
||||
if (!ContextLibrary::Initialize())
|
||||
{
|
||||
NazaraError("Failed to active thread context");
|
||||
NazaraError("Failed to initialise library");
|
||||
return false;
|
||||
}
|
||||
|
||||
ContextParameters parameters;
|
||||
parameters.shared = false; // Difficile de partager le contexte de référence avec lui-même
|
||||
|
||||
std::unique_ptr<Context> reference(new Context);
|
||||
if (!reference->Create(parameters))
|
||||
{
|
||||
NazaraError("Failed to create reference context");
|
||||
return false;
|
||||
}
|
||||
|
||||
// Le contexte de référence doit rester désactivé pour le partage
|
||||
if (!reference->SetActive(false))
|
||||
{
|
||||
NazaraError("Failed to desactive reference context");
|
||||
return false;
|
||||
}
|
||||
|
||||
s_reference = std::move(reference);
|
||||
|
||||
// Le contexte de référence est partagé par défaut avec les autres contextes
|
||||
ContextParameters::defaultShareContext = s_reference.get();
|
||||
return true;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
const NzContext* NzContext::GetCurrent()
|
||||
{
|
||||
return s_currentContext;
|
||||
}
|
||||
|
||||
const NzContext* NzContext::GetReference()
|
||||
{
|
||||
return s_reference.get();
|
||||
}
|
||||
|
||||
const NzContext* NzContext::GetThreadContext()
|
||||
{
|
||||
EnsureContext();
|
||||
|
||||
return s_threadContext;
|
||||
}
|
||||
|
||||
bool NzContext::Initialize()
|
||||
{
|
||||
if (!NzContextLibrary::Initialize())
|
||||
void Context::Uninitialize()
|
||||
{
|
||||
NazaraError("Failed to initialise library");
|
||||
return false;
|
||||
ContextLibrary::Uninitialize();
|
||||
s_contexts.clear(); // On supprime tous les contextes créés
|
||||
s_reference.reset();
|
||||
}
|
||||
|
||||
NzContextParameters parameters;
|
||||
parameters.shared = false; // Difficile de partager le contexte de référence avec lui-même
|
||||
|
||||
std::unique_ptr<NzContext> reference(new NzContext);
|
||||
if (!reference->Create(parameters))
|
||||
{
|
||||
NazaraError("Failed to create reference context");
|
||||
return false;
|
||||
}
|
||||
|
||||
// Le contexte de référence doit rester désactivé pour le partage
|
||||
if (!reference->SetActive(false))
|
||||
{
|
||||
NazaraError("Failed to desactive reference context");
|
||||
return false;
|
||||
}
|
||||
|
||||
s_reference = std::move(reference);
|
||||
|
||||
// Le contexte de référence est partagé par défaut avec les autres contextes
|
||||
NzContextParameters::defaultShareContext = s_reference.get();
|
||||
return true;
|
||||
std::unique_ptr<Context> Context::s_reference;
|
||||
std::vector<std::unique_ptr<Context>> Context::s_contexts;
|
||||
ContextLibrary::LibraryMap Context::s_library;
|
||||
}
|
||||
|
||||
void NzContext::Uninitialize()
|
||||
{
|
||||
NzContextLibrary::Uninitialize();
|
||||
s_contexts.clear(); // On supprime tous les contextes créés
|
||||
s_reference.reset();
|
||||
}
|
||||
|
||||
std::unique_ptr<NzContext> NzContext::s_reference;
|
||||
std::vector<std::unique_ptr<NzContext>> NzContext::s_contexts;
|
||||
NzContextLibrary::LibraryMap NzContext::s_library;
|
||||
|
||||
@@ -6,27 +6,30 @@
|
||||
#include <Nazara/Renderer/Config.hpp>
|
||||
#include <Nazara/Renderer/Debug.hpp>
|
||||
|
||||
// Version majeure d'OpenGL, initialisé par NzOpenGL::Initialize()
|
||||
nzUInt8 NzContextParameters::defaultMajorVersion;
|
||||
namespace Nz
|
||||
{
|
||||
// Version majeure d'OpenGL, initialisé par OpenGL::Initialize()
|
||||
UInt8 ContextParameters::defaultMajorVersion;
|
||||
|
||||
// Version majeure d'OpenGL, initialisé par NzOpenGL::Initialize()
|
||||
nzUInt8 NzContextParameters::defaultMinorVersion;
|
||||
// Version majeure d'OpenGL, initialisé par OpenGL::Initialize()
|
||||
UInt8 ContextParameters::defaultMinorVersion;
|
||||
|
||||
// Contexte de partage par défaut, initialisé par NzOpenGL::Initialize()
|
||||
const NzContext* NzContextParameters::defaultShareContext = nullptr;
|
||||
// Contexte de partage par défaut, initialisé par OpenGL::Initialize()
|
||||
const Context* ContextParameters::defaultShareContext = nullptr;
|
||||
|
||||
// Si possible, garder la compatibilité avec les fonctionnalités dépréciées
|
||||
bool NzContextParameters::defaultCompatibilityProfile = false;
|
||||
// Si possible, garder la compatibilité avec les fonctionnalités dépréciées
|
||||
bool ContextParameters::defaultCompatibilityProfile = false;
|
||||
|
||||
// Mode debug d'OpenGL par défaut
|
||||
#if NAZARA_RENDERER_OPENGL_DEBUG || defined(NAZARA_DEBUG)
|
||||
bool NzContextParameters::defaultDebugMode = true;
|
||||
#else
|
||||
bool NzContextParameters::defaultDebugMode = false;
|
||||
#endif
|
||||
// Mode debug d'OpenGL par défaut
|
||||
#if NAZARA_RENDERER_OPENGL_DEBUG || defined(NAZARA_DEBUG)
|
||||
bool ContextParameters::defaultDebugMode = true;
|
||||
#else
|
||||
bool ContextParameters::defaultDebugMode = false;
|
||||
#endif
|
||||
|
||||
// Active le double-buffering sur les contextes
|
||||
bool NzContextParameters::defaultDoubleBuffered = false;
|
||||
// Active le double-buffering sur les contextes
|
||||
bool ContextParameters::defaultDoubleBuffered = false;
|
||||
|
||||
// Active le partage des ressources entre contextes (Via le defaultShareContext)
|
||||
bool NzContextParameters::defaultShared = true;
|
||||
// Active le partage des ressources entre contextes (Via le defaultShareContext)
|
||||
bool ContextParameters::defaultShared = true;
|
||||
}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -11,108 +11,112 @@
|
||||
#include <stdexcept>
|
||||
#include <Nazara/Renderer/Debug.hpp>
|
||||
|
||||
NzGpuQuery::NzGpuQuery()
|
||||
namespace Nz
|
||||
{
|
||||
NzContext::EnsureContext();
|
||||
|
||||
m_id = 0;
|
||||
glGenQueries(1, reinterpret_cast<GLuint*>(&m_id));
|
||||
|
||||
#ifdef NAZARA_DEBUG
|
||||
if (!m_id)
|
||||
GpuQuery::GpuQuery() :
|
||||
m_id(0)
|
||||
{
|
||||
NazaraError("Failed to create occlusion query");
|
||||
throw std::runtime_error("Constructor failed");
|
||||
}
|
||||
#endif
|
||||
}
|
||||
Context::EnsureContext();
|
||||
|
||||
NzGpuQuery::~NzGpuQuery()
|
||||
{
|
||||
if (m_id)
|
||||
{
|
||||
NzContext::EnsureContext();
|
||||
m_id = 0;
|
||||
glGenQueries(1, reinterpret_cast<GLuint*>(&m_id));
|
||||
|
||||
GLuint query = static_cast<GLuint>(m_id);
|
||||
glDeleteQueries(1, &query);
|
||||
}
|
||||
}
|
||||
|
||||
void NzGpuQuery::Begin(nzGpuQueryMode mode)
|
||||
{
|
||||
#ifdef NAZARA_DEBUG
|
||||
if (NzContext::GetCurrent() == nullptr)
|
||||
{
|
||||
NazaraError("No active context");
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if NAZARA_RENDERER_SAFE
|
||||
if (!IsModeSupported(mode))
|
||||
{
|
||||
NazaraError("Mode (0x" + NzString::Number(mode, 16) + ") not supported");
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
m_mode = mode;
|
||||
glBeginQuery(NzOpenGL::QueryMode[mode], m_id);
|
||||
}
|
||||
|
||||
void NzGpuQuery::End()
|
||||
{
|
||||
#ifdef NAZARA_DEBUG
|
||||
if (NzContext::GetCurrent() == nullptr)
|
||||
{
|
||||
NazaraError("No active context");
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
glEndQuery(NzOpenGL::QueryMode[m_mode]);
|
||||
}
|
||||
|
||||
unsigned int NzGpuQuery::GetResult() const
|
||||
{
|
||||
NzContext::EnsureContext();
|
||||
|
||||
GLuint result;
|
||||
glGetQueryObjectuiv(m_id, GL_QUERY_RESULT, &result);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
bool NzGpuQuery::IsResultAvailable() const
|
||||
{
|
||||
NzContext::EnsureContext();
|
||||
|
||||
GLint available;
|
||||
glGetQueryObjectiv(m_id, GL_QUERY_RESULT_AVAILABLE, &available);
|
||||
|
||||
return available == GL_TRUE;
|
||||
}
|
||||
|
||||
unsigned int NzGpuQuery::GetOpenGLID() const
|
||||
{
|
||||
return m_id;
|
||||
}
|
||||
|
||||
bool NzGpuQuery::IsModeSupported(nzGpuQueryMode mode)
|
||||
{
|
||||
switch (mode)
|
||||
{
|
||||
case nzGpuQueryMode_AnySamplesPassedConservative:
|
||||
return NzOpenGL::GetVersion() >= 430;
|
||||
|
||||
case nzGpuQueryMode_AnySamplesPassed:
|
||||
case nzGpuQueryMode_PrimitiveGenerated:
|
||||
case nzGpuQueryMode_SamplesPassed:
|
||||
case nzGpuQueryMode_TimeElapsed:
|
||||
case nzGpuQueryMode_TransformFeedbackPrimitivesWritten:
|
||||
return true;
|
||||
#ifdef NAZARA_DEBUG
|
||||
if (!m_id)
|
||||
{
|
||||
NazaraError("Failed to create occlusion query");
|
||||
throw std::runtime_error("Constructor failed");
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
NazaraError("Gpu Query mode not handled (0x" + NzString::Number(mode, 16) + ')');
|
||||
return false;
|
||||
GpuQuery::~GpuQuery()
|
||||
{
|
||||
if (m_id)
|
||||
{
|
||||
Context::EnsureContext();
|
||||
|
||||
GLuint query = static_cast<GLuint>(m_id);
|
||||
glDeleteQueries(1, &query);
|
||||
}
|
||||
}
|
||||
|
||||
void GpuQuery::Begin(GpuQueryMode mode)
|
||||
{
|
||||
#ifdef NAZARA_DEBUG
|
||||
if (Context::GetCurrent() == nullptr)
|
||||
{
|
||||
NazaraError("No active context");
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if NAZARA_RENDERER_SAFE
|
||||
if (!IsModeSupported(mode))
|
||||
{
|
||||
NazaraError("Mode (0x" + String::Number(mode, 16) + ") not supported");
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
m_mode = mode;
|
||||
glBeginQuery(OpenGL::QueryMode[mode], m_id);
|
||||
}
|
||||
|
||||
void GpuQuery::End()
|
||||
{
|
||||
#ifdef NAZARA_DEBUG
|
||||
if (Context::GetCurrent() == nullptr)
|
||||
{
|
||||
NazaraError("No active context");
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
glEndQuery(OpenGL::QueryMode[m_mode]);
|
||||
}
|
||||
|
||||
unsigned int GpuQuery::GetResult() const
|
||||
{
|
||||
Context::EnsureContext();
|
||||
|
||||
GLuint result;
|
||||
glGetQueryObjectuiv(m_id, GL_QUERY_RESULT, &result);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
bool GpuQuery::IsResultAvailable() const
|
||||
{
|
||||
Context::EnsureContext();
|
||||
|
||||
GLint available;
|
||||
glGetQueryObjectiv(m_id, GL_QUERY_RESULT_AVAILABLE, &available);
|
||||
|
||||
return available == GL_TRUE;
|
||||
}
|
||||
|
||||
unsigned int GpuQuery::GetOpenGLID() const
|
||||
{
|
||||
return m_id;
|
||||
}
|
||||
|
||||
bool GpuQuery::IsModeSupported(GpuQueryMode mode)
|
||||
{
|
||||
switch (mode)
|
||||
{
|
||||
case GpuQueryMode_AnySamplesPassedConservative:
|
||||
return OpenGL::GetVersion() >= 430;
|
||||
|
||||
case GpuQueryMode_AnySamplesPassed:
|
||||
case GpuQueryMode_PrimitiveGenerated:
|
||||
case GpuQueryMode_SamplesPassed:
|
||||
case GpuQueryMode_TimeElapsed:
|
||||
case GpuQueryMode_TransformFeedbackPrimitivesWritten:
|
||||
return true;
|
||||
}
|
||||
|
||||
NazaraError("Gpu Query mode not handled (0x" + String::Number(mode, 16) + ')');
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -11,124 +11,127 @@
|
||||
#include <stdexcept>
|
||||
#include <Nazara/Renderer/Debug.hpp>
|
||||
|
||||
NzHardwareBuffer::NzHardwareBuffer(NzBuffer* parent, nzBufferType type) :
|
||||
m_type(type),
|
||||
m_parent(parent)
|
||||
namespace Nz
|
||||
{
|
||||
}
|
||||
|
||||
NzHardwareBuffer::~NzHardwareBuffer() = default;
|
||||
|
||||
bool NzHardwareBuffer::Create(unsigned int size, nzBufferUsage usage)
|
||||
{
|
||||
NzContext::EnsureContext();
|
||||
|
||||
m_buffer = 0;
|
||||
glGenBuffers(1, &m_buffer);
|
||||
|
||||
NzOpenGL::BindBuffer(m_type, m_buffer);
|
||||
|
||||
glBufferData(NzOpenGL::BufferTarget[m_type], size, nullptr, NzOpenGL::BufferUsage[usage]);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void NzHardwareBuffer::Destroy()
|
||||
{
|
||||
NzContext::EnsureContext();
|
||||
|
||||
NzOpenGL::DeleteBuffer(m_type, m_buffer);
|
||||
}
|
||||
|
||||
bool NzHardwareBuffer::Fill(const void* data, unsigned int offset, unsigned int size, bool forceDiscard)
|
||||
{
|
||||
NzContext::EnsureContext();
|
||||
|
||||
unsigned int totalSize = m_parent->GetSize();
|
||||
|
||||
if (!forceDiscard)
|
||||
forceDiscard = (size == totalSize);
|
||||
|
||||
NzOpenGL::BindBuffer(m_type, m_buffer);
|
||||
|
||||
// Il semblerait que glBuffer(Sub)Data soit plus performant que glMapBuffer(Range) en dessous d'un certain seuil
|
||||
// http://www.stevestreeting.com/2007/03/17/glmapbuffer-vs-glbuffersubdata-the-return/
|
||||
if (size < 32*1024)
|
||||
HardwareBuffer::HardwareBuffer(Buffer* parent, BufferType type) :
|
||||
m_type(type),
|
||||
m_parent(parent)
|
||||
{
|
||||
// http://www.opengl.org/wiki/Buffer_Object_Streaming
|
||||
if (forceDiscard)
|
||||
glBufferData(NzOpenGL::BufferTarget[m_type], totalSize, nullptr, NzOpenGL::BufferUsage[m_parent->GetUsage()]); // Discard
|
||||
|
||||
glBufferSubData(NzOpenGL::BufferTarget[m_type], offset, size, data);
|
||||
}
|
||||
else
|
||||
|
||||
HardwareBuffer::~HardwareBuffer() = default;
|
||||
|
||||
bool HardwareBuffer::Create(unsigned int size, BufferUsage usage)
|
||||
{
|
||||
void* ptr = Map((forceDiscard) ? nzBufferAccess_DiscardAndWrite : nzBufferAccess_WriteOnly, offset, size);
|
||||
if (!ptr)
|
||||
Context::EnsureContext();
|
||||
|
||||
m_buffer = 0;
|
||||
glGenBuffers(1, &m_buffer);
|
||||
|
||||
OpenGL::BindBuffer(m_type, m_buffer);
|
||||
|
||||
glBufferData(OpenGL::BufferTarget[m_type], size, nullptr, OpenGL::BufferUsage[usage]);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void HardwareBuffer::Destroy()
|
||||
{
|
||||
Context::EnsureContext();
|
||||
|
||||
OpenGL::DeleteBuffer(m_type, m_buffer);
|
||||
}
|
||||
|
||||
bool HardwareBuffer::Fill(const void* data, unsigned int offset, unsigned int size, bool forceDiscard)
|
||||
{
|
||||
Context::EnsureContext();
|
||||
|
||||
unsigned int totalSize = m_parent->GetSize();
|
||||
|
||||
if (!forceDiscard)
|
||||
forceDiscard = (size == totalSize);
|
||||
|
||||
OpenGL::BindBuffer(m_type, m_buffer);
|
||||
|
||||
// Il semblerait que glBuffer(Sub)Data soit plus performant que glMapBuffer(Range) en dessous d'un certain seuil
|
||||
// http://www.stevestreeting.com/2007/03/17/glmapbuffer-vs-glbuffersubdata-the-return/
|
||||
if (size < 32*1024)
|
||||
{
|
||||
NazaraError("Failed to map buffer");
|
||||
// http://www.opengl.org/wiki/Buffer_Object_Streaming
|
||||
if (forceDiscard)
|
||||
glBufferData(OpenGL::BufferTarget[m_type], totalSize, nullptr, OpenGL::BufferUsage[m_parent->GetUsage()]); // Discard
|
||||
|
||||
glBufferSubData(OpenGL::BufferTarget[m_type], offset, size, data);
|
||||
}
|
||||
else
|
||||
{
|
||||
void* ptr = Map((forceDiscard) ? BufferAccess_DiscardAndWrite : BufferAccess_WriteOnly, offset, size);
|
||||
if (!ptr)
|
||||
{
|
||||
NazaraError("Failed to map buffer");
|
||||
return false;
|
||||
}
|
||||
|
||||
std::memcpy(ptr, data, size);
|
||||
|
||||
Unmap();
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool HardwareBuffer::IsHardware() const
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
void* HardwareBuffer::Map(BufferAccess access, unsigned int offset, unsigned int size)
|
||||
{
|
||||
Context::EnsureContext();
|
||||
|
||||
OpenGL::BindBuffer(m_type, m_buffer);
|
||||
|
||||
if (glMapBufferRange)
|
||||
return glMapBufferRange(OpenGL::BufferTarget[m_type], offset, size, OpenGL::BufferLockRange[access]);
|
||||
else
|
||||
{
|
||||
// http://www.opengl.org/wiki/Buffer_Object_Streaming
|
||||
if (access == BufferAccess_DiscardAndWrite)
|
||||
glBufferData(OpenGL::BufferTarget[m_type], m_parent->GetSize(), nullptr, OpenGL::BufferUsage[m_parent->GetUsage()]); // Discard
|
||||
|
||||
UInt8* ptr = static_cast<UInt8*>(glMapBuffer(OpenGL::BufferTarget[m_type], OpenGL::BufferLock[access]));
|
||||
if (ptr)
|
||||
ptr += offset;
|
||||
|
||||
return ptr;
|
||||
}
|
||||
}
|
||||
|
||||
bool HardwareBuffer::Unmap()
|
||||
{
|
||||
Context::EnsureContext();
|
||||
|
||||
OpenGL::BindBuffer(m_type, m_buffer);
|
||||
|
||||
if (glUnmapBuffer(OpenGL::BufferTarget[m_type]) != GL_TRUE)
|
||||
{
|
||||
glBufferData(OpenGL::BufferTarget[m_type], m_parent->GetSize(), nullptr, OpenGL::BufferUsage[m_parent->GetUsage()]);
|
||||
|
||||
// Une erreur rare est survenue, nous devons réinitialiser le buffer
|
||||
NazaraError("Failed to unmap buffer, reinitialising content... (OpenGL error : 0x" + String::Number(glGetError(), 16) + ')');
|
||||
return false;
|
||||
}
|
||||
|
||||
std::memcpy(ptr, data, size);
|
||||
|
||||
Unmap();
|
||||
return true;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool NzHardwareBuffer::IsHardware() const
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
void* NzHardwareBuffer::Map(nzBufferAccess access, unsigned int offset, unsigned int size)
|
||||
{
|
||||
NzContext::EnsureContext();
|
||||
|
||||
NzOpenGL::BindBuffer(m_type, m_buffer);
|
||||
|
||||
if (glMapBufferRange)
|
||||
return glMapBufferRange(NzOpenGL::BufferTarget[m_type], offset, size, NzOpenGL::BufferLockRange[access]);
|
||||
else
|
||||
void HardwareBuffer::Bind() const
|
||||
{
|
||||
// http://www.opengl.org/wiki/Buffer_Object_Streaming
|
||||
if (access == nzBufferAccess_DiscardAndWrite)
|
||||
glBufferData(NzOpenGL::BufferTarget[m_type], m_parent->GetSize(), nullptr, NzOpenGL::BufferUsage[m_parent->GetUsage()]); // Discard
|
||||
|
||||
nzUInt8* ptr = static_cast<nzUInt8*>(glMapBuffer(NzOpenGL::BufferTarget[m_type], NzOpenGL::BufferLock[access]));
|
||||
if (ptr)
|
||||
ptr += offset;
|
||||
|
||||
return ptr;
|
||||
OpenGL::BindBuffer(m_type, m_buffer);
|
||||
}
|
||||
}
|
||||
|
||||
bool NzHardwareBuffer::Unmap()
|
||||
{
|
||||
NzContext::EnsureContext();
|
||||
|
||||
NzOpenGL::BindBuffer(m_type, m_buffer);
|
||||
|
||||
if (glUnmapBuffer(NzOpenGL::BufferTarget[m_type]) != GL_TRUE)
|
||||
unsigned int HardwareBuffer::GetOpenGLID() const
|
||||
{
|
||||
glBufferData(NzOpenGL::BufferTarget[m_type], m_parent->GetSize(), nullptr, NzOpenGL::BufferUsage[m_parent->GetUsage()]);
|
||||
|
||||
// Une erreur rare est survenue, nous devons réinitialiser le buffer
|
||||
NazaraError("Failed to unmap buffer, reinitialising content... (OpenGL error : 0x" + NzString::Number(glGetError(), 16) + ')');
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
return m_buffer;
|
||||
}
|
||||
|
||||
void NzHardwareBuffer::Bind() const
|
||||
{
|
||||
NzOpenGL::BindBuffer(m_type, m_buffer);
|
||||
}
|
||||
|
||||
unsigned int NzHardwareBuffer::GetOpenGLID() const
|
||||
{
|
||||
return m_buffer;
|
||||
}
|
||||
|
||||
@@ -11,30 +11,33 @@
|
||||
#include <Nazara/Renderer/OpenGL.hpp>
|
||||
#include <Nazara/Utility/AbstractBuffer.hpp>
|
||||
|
||||
class NzHardwareBuffer : public NzAbstractBuffer
|
||||
namespace Nz
|
||||
{
|
||||
public:
|
||||
NzHardwareBuffer(NzBuffer* parent, nzBufferType type);
|
||||
~NzHardwareBuffer();
|
||||
class HardwareBuffer : public AbstractBuffer
|
||||
{
|
||||
public:
|
||||
HardwareBuffer(Buffer* parent, BufferType type);
|
||||
~HardwareBuffer();
|
||||
|
||||
bool Create(unsigned int size, nzBufferUsage usage = nzBufferUsage_Static);
|
||||
void Destroy();
|
||||
bool Create(unsigned int size, BufferUsage usage = BufferUsage_Static);
|
||||
void Destroy();
|
||||
|
||||
bool Fill(const void* data, unsigned int offset, unsigned int size, bool forceDiscard);
|
||||
bool Fill(const void* data, unsigned int offset, unsigned int size, bool forceDiscard);
|
||||
|
||||
bool IsHardware() const;
|
||||
bool IsHardware() const;
|
||||
|
||||
void* Map(nzBufferAccess access, unsigned int offset = 0, unsigned int size = 0);
|
||||
bool Unmap();
|
||||
void* Map(BufferAccess access, unsigned int offset = 0, unsigned int size = 0);
|
||||
bool Unmap();
|
||||
|
||||
// Fonctions OpenGL
|
||||
void Bind() const;
|
||||
unsigned int GetOpenGLID() const;
|
||||
// Fonctions OpenGL
|
||||
void Bind() const;
|
||||
unsigned int GetOpenGLID() const;
|
||||
|
||||
private:
|
||||
GLuint m_buffer;
|
||||
nzBufferType m_type;
|
||||
NzBuffer* m_parent;
|
||||
};
|
||||
private:
|
||||
GLuint m_buffer;
|
||||
BufferType m_type;
|
||||
Buffer* m_parent;
|
||||
};
|
||||
}
|
||||
|
||||
#endif // NAZARA_HARDWAREBUFFER_HPP
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -9,122 +9,125 @@
|
||||
#include <Nazara/Utility/PixelFormat.hpp>
|
||||
#include <Nazara/Renderer/Debug.hpp>
|
||||
|
||||
NzRenderBuffer::NzRenderBuffer() :
|
||||
m_id(0)
|
||||
namespace Nz
|
||||
{
|
||||
}
|
||||
|
||||
NzRenderBuffer::~NzRenderBuffer()
|
||||
{
|
||||
OnRenderBufferRelease(this);
|
||||
|
||||
Destroy();
|
||||
}
|
||||
|
||||
bool NzRenderBuffer::Create(nzPixelFormat format, unsigned int width, unsigned int height)
|
||||
{
|
||||
Destroy();
|
||||
|
||||
#if NAZARA_RENDERER_SAFE
|
||||
if (width == 0 || height == 0)
|
||||
RenderBuffer::RenderBuffer() :
|
||||
m_id(0)
|
||||
{
|
||||
NazaraError("Invalid size");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!NzPixelFormat::IsValid(format))
|
||||
RenderBuffer::~RenderBuffer()
|
||||
{
|
||||
NazaraError("Invalid pixel format");
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
OnRenderBufferRelease(this);
|
||||
|
||||
NzOpenGL::Format openglFormat;
|
||||
if (!NzOpenGL::TranslateFormat(format, &openglFormat, NzOpenGL::FormatType_RenderBuffer))
|
||||
{
|
||||
NazaraError("Failed to translate pixel format \"" + NzPixelFormat::ToString(format) + "\" into OpenGL format");
|
||||
return false;
|
||||
Destroy();
|
||||
}
|
||||
|
||||
GLuint renderBuffer = 0;
|
||||
|
||||
glGenRenderbuffers(1, &renderBuffer);
|
||||
if (!renderBuffer)
|
||||
bool RenderBuffer::Create(PixelFormatType format, unsigned int width, unsigned int height)
|
||||
{
|
||||
NazaraError("Failed to create renderbuffer");
|
||||
return false;
|
||||
Destroy();
|
||||
|
||||
#if NAZARA_RENDERER_SAFE
|
||||
if (width == 0 || height == 0)
|
||||
{
|
||||
NazaraError("Invalid size");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!PixelFormat::IsValid(format))
|
||||
{
|
||||
NazaraError("Invalid pixel format");
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
|
||||
OpenGL::Format openglFormat;
|
||||
if (!OpenGL::TranslateFormat(format, &openglFormat, OpenGL::FormatType_RenderBuffer))
|
||||
{
|
||||
NazaraError("Failed to translate pixel format \"" + PixelFormat::ToString(format) + "\" into OpenGL format");
|
||||
return false;
|
||||
}
|
||||
|
||||
GLuint renderBuffer = 0;
|
||||
|
||||
glGenRenderbuffers(1, &renderBuffer);
|
||||
if (!renderBuffer)
|
||||
{
|
||||
NazaraError("Failed to create renderbuffer");
|
||||
return false;
|
||||
}
|
||||
|
||||
GLint previous;
|
||||
glGetIntegerv(GL_RENDERBUFFER_BINDING, &previous);
|
||||
|
||||
glBindRenderbuffer(GL_RENDERBUFFER, renderBuffer);
|
||||
glRenderbufferStorage(GL_RENDERBUFFER, openglFormat.internalFormat, width, height);
|
||||
|
||||
if (previous != 0)
|
||||
glBindRenderbuffer(GL_RENDERBUFFER, previous);
|
||||
|
||||
m_pixelFormat = format;
|
||||
m_height = height;
|
||||
m_id = renderBuffer;
|
||||
m_width = width;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
GLint previous;
|
||||
glGetIntegerv(GL_RENDERBUFFER_BINDING, &previous);
|
||||
|
||||
glBindRenderbuffer(GL_RENDERBUFFER, renderBuffer);
|
||||
glRenderbufferStorage(GL_RENDERBUFFER, openglFormat.internalFormat, width, height);
|
||||
|
||||
if (previous != 0)
|
||||
glBindRenderbuffer(GL_RENDERBUFFER, previous);
|
||||
|
||||
m_pixelFormat = format;
|
||||
m_height = height;
|
||||
m_id = renderBuffer;
|
||||
m_width = width;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void NzRenderBuffer::Destroy()
|
||||
{
|
||||
if (m_id)
|
||||
void RenderBuffer::Destroy()
|
||||
{
|
||||
OnRenderBufferDestroy(this);
|
||||
if (m_id)
|
||||
{
|
||||
OnRenderBufferDestroy(this);
|
||||
|
||||
NzContext::EnsureContext();
|
||||
Context::EnsureContext();
|
||||
|
||||
GLuint renderBuffer = m_id;
|
||||
glDeleteRenderbuffers(1, &renderBuffer); // Les Renderbuffers sont partagés entre les contextes: Ne posera pas de problème
|
||||
m_id = 0;
|
||||
}
|
||||
}
|
||||
|
||||
unsigned int NzRenderBuffer::GetHeight() const
|
||||
{
|
||||
return m_height;
|
||||
}
|
||||
|
||||
nzPixelFormat NzRenderBuffer::GetFormat() const
|
||||
{
|
||||
return m_pixelFormat;
|
||||
}
|
||||
|
||||
unsigned int NzRenderBuffer::GetWidth() const
|
||||
{
|
||||
return m_width;
|
||||
}
|
||||
|
||||
unsigned int NzRenderBuffer::GetOpenGLID() const
|
||||
{
|
||||
return m_id;
|
||||
}
|
||||
|
||||
bool NzRenderBuffer::IsValid() const
|
||||
{
|
||||
return m_id != 0;
|
||||
}
|
||||
|
||||
bool NzRenderBuffer::Initialize()
|
||||
{
|
||||
if (!NzRenderBufferLibrary::Initialize())
|
||||
{
|
||||
NazaraError("Failed to initialise library");
|
||||
return false;
|
||||
GLuint renderBuffer = m_id;
|
||||
glDeleteRenderbuffers(1, &renderBuffer); // Les Renderbuffers sont partagés entre les contextes: Ne posera pas de problème
|
||||
m_id = 0;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
unsigned int RenderBuffer::GetHeight() const
|
||||
{
|
||||
return m_height;
|
||||
}
|
||||
|
||||
void NzRenderBuffer::Uninitialize()
|
||||
{
|
||||
NzRenderBufferLibrary::Uninitialize();
|
||||
}
|
||||
PixelFormatType RenderBuffer::GetFormat() const
|
||||
{
|
||||
return m_pixelFormat;
|
||||
}
|
||||
|
||||
NzRenderBufferLibrary::LibraryMap NzRenderBuffer::s_library;
|
||||
unsigned int RenderBuffer::GetWidth() const
|
||||
{
|
||||
return m_width;
|
||||
}
|
||||
|
||||
unsigned int RenderBuffer::GetOpenGLID() const
|
||||
{
|
||||
return m_id;
|
||||
}
|
||||
|
||||
bool RenderBuffer::IsValid() const
|
||||
{
|
||||
return m_id != 0;
|
||||
}
|
||||
|
||||
bool RenderBuffer::Initialize()
|
||||
{
|
||||
if (!RenderBufferLibrary::Initialize())
|
||||
{
|
||||
NazaraError("Failed to initialise library");
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void RenderBuffer::Uninitialize()
|
||||
{
|
||||
RenderBufferLibrary::Uninitialize();
|
||||
}
|
||||
|
||||
RenderBufferLibrary::LibraryMap RenderBuffer::s_library;
|
||||
}
|
||||
|
||||
@@ -6,27 +6,30 @@
|
||||
#include <Nazara/Renderer/Renderer.hpp>
|
||||
#include <Nazara/Renderer/Debug.hpp>
|
||||
|
||||
NzRenderTarget::~NzRenderTarget()
|
||||
namespace Nz
|
||||
{
|
||||
OnRenderTargetRelease(this);
|
||||
}
|
||||
RenderTarget::~RenderTarget()
|
||||
{
|
||||
OnRenderTargetRelease(this);
|
||||
}
|
||||
|
||||
bool NzRenderTarget::IsActive() const
|
||||
{
|
||||
return NzRenderer::GetTarget() == this;
|
||||
}
|
||||
bool RenderTarget::IsActive() const
|
||||
{
|
||||
return Renderer::GetTarget() == this;
|
||||
}
|
||||
|
||||
bool NzRenderTarget::SetActive(bool active)
|
||||
{
|
||||
if (active)
|
||||
return NzRenderer::SetTarget(this);
|
||||
else if (NzRenderer::GetTarget() == this)
|
||||
return NzRenderer::SetTarget(nullptr);
|
||||
bool RenderTarget::SetActive(bool active)
|
||||
{
|
||||
if (active)
|
||||
return Renderer::SetTarget(this);
|
||||
else if (Renderer::GetTarget() == this)
|
||||
return Renderer::SetTarget(nullptr);
|
||||
|
||||
return true;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void NzRenderTarget::Desactivate() const
|
||||
{
|
||||
// Seuls les target sans contextes (ex: NzRenderTexture) nécessitent une désactivation
|
||||
void RenderTarget::Desactivate() const
|
||||
{
|
||||
// Seuls les target sans contextes (ex: RenderTexture) nécessitent une désactivation
|
||||
}
|
||||
}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -13,277 +13,279 @@
|
||||
#include <stdexcept>
|
||||
#include <Nazara/Renderer/Debug.hpp>
|
||||
|
||||
NzRenderWindow::NzRenderWindow(NzVideoMode mode, const NzString& title, nzUInt32 style, const NzContextParameters& parameters) :
|
||||
NzRenderTarget(), NzWindow()
|
||||
namespace Nz
|
||||
{
|
||||
NzErrorFlags flags(nzErrorFlag_ThrowException, true);
|
||||
Create(mode, title, style, parameters);
|
||||
}
|
||||
|
||||
NzRenderWindow::NzRenderWindow(NzWindowHandle handle, const NzContextParameters& parameters) :
|
||||
NzRenderTarget(), NzWindow()
|
||||
{
|
||||
NzErrorFlags flags(nzErrorFlag_ThrowException, true);
|
||||
Create(handle, parameters);
|
||||
}
|
||||
|
||||
NzRenderWindow::~NzRenderWindow()
|
||||
{
|
||||
// Nécessaire si NzWindow::Destroy est appelé par son destructeur
|
||||
OnWindowDestroy();
|
||||
}
|
||||
|
||||
bool NzRenderWindow::CopyToImage(NzAbstractImage* image, const NzVector3ui& dstPos) const
|
||||
{
|
||||
#if NAZARA_RENDERER_SAFE
|
||||
if (!m_context)
|
||||
RenderWindow::RenderWindow(VideoMode mode, const String& title, UInt32 style, const ContextParameters& parameters) :
|
||||
RenderTarget(), Window()
|
||||
{
|
||||
NazaraError("Window has not been created");
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
|
||||
return CopyToImage(image, NzRectui(NzVector2ui(0U), GetSize()), dstPos);
|
||||
}
|
||||
|
||||
bool NzRenderWindow::CopyToImage(NzAbstractImage* image, const NzRectui& rect, const NzVector3ui& dstPos) const
|
||||
{
|
||||
#if NAZARA_RENDERER_SAFE
|
||||
if (!m_context)
|
||||
{
|
||||
NazaraError("Window has not been created");
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
|
||||
NzVector2ui windowSize = GetSize();
|
||||
|
||||
#if NAZARA_RENDERER_SAFE
|
||||
if (!image)
|
||||
{
|
||||
NazaraError("Image must be valid");
|
||||
return false;
|
||||
ErrorFlags flags(ErrorFlag_ThrowException, true);
|
||||
Create(mode, title, style, parameters);
|
||||
}
|
||||
|
||||
if (image->GetFormat() != nzPixelFormat_RGBA8)
|
||||
RenderWindow::RenderWindow(WindowHandle handle, const ContextParameters& parameters) :
|
||||
RenderTarget(), Window()
|
||||
{
|
||||
// Pour plus de facilité, évidemment on peut faire sauter cette règle avec un peu de gestion
|
||||
NazaraError("Image must be RGBA8-formatted");
|
||||
return false;
|
||||
ErrorFlags flags(ErrorFlag_ThrowException, true);
|
||||
Create(handle, parameters);
|
||||
}
|
||||
|
||||
if (rect.x + rect.width > windowSize.x || rect.y + rect.height > windowSize.y)
|
||||
RenderWindow::~RenderWindow()
|
||||
{
|
||||
NazaraError("Rectangle dimensions are out of window's bounds");
|
||||
return false;
|
||||
// Nécessaire si Window::Destroy est appelé par son destructeur
|
||||
OnWindowDestroy();
|
||||
}
|
||||
|
||||
NzVector3ui imageSize = image->GetSize();
|
||||
if (dstPos.x + rect.width > imageSize.x || dstPos.y + rect.height > imageSize.y || dstPos.z > imageSize.z)
|
||||
bool RenderWindow::CopyToImage(AbstractImage* image, const Vector3ui& dstPos) const
|
||||
{
|
||||
NazaraError("Cube dimensions are out of image's bounds");
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
|
||||
const NzContext* currentContext = NzContext::GetCurrent();
|
||||
if (m_context != currentContext)
|
||||
{
|
||||
if (!m_context->SetActive(true))
|
||||
#if NAZARA_RENDERER_SAFE
|
||||
if (!m_context)
|
||||
{
|
||||
NazaraError("Failed to activate context");
|
||||
NazaraError("Window has not been created");
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
|
||||
return CopyToImage(image, Rectui(Vector2ui(0U), GetSize()), dstPos);
|
||||
}
|
||||
|
||||
bool RenderWindow::CopyToImage(AbstractImage* image, const Rectui& rect, const Vector3ui& dstPos) const
|
||||
{
|
||||
#if NAZARA_RENDERER_SAFE
|
||||
if (!m_context)
|
||||
{
|
||||
NazaraError("Window has not been created");
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
|
||||
Vector2ui windowSize = GetSize();
|
||||
|
||||
#if NAZARA_RENDERER_SAFE
|
||||
if (!image)
|
||||
{
|
||||
NazaraError("Image must be valid");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (image->GetFormat() != PixelFormatType_RGBA8)
|
||||
{
|
||||
// Pour plus de facilité, évidemment on peut faire sauter cette règle avec un peu de gestion
|
||||
NazaraError("Image must be RGBA8-formatted");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (rect.x + rect.width > windowSize.x || rect.y + rect.height > windowSize.y)
|
||||
{
|
||||
NazaraError("Rectangle dimensions are out of window's bounds");
|
||||
return false;
|
||||
}
|
||||
|
||||
Vector3ui imageSize = image->GetSize();
|
||||
if (dstPos.x + rect.width > imageSize.x || dstPos.y + rect.height > imageSize.y || dstPos.z > imageSize.z)
|
||||
{
|
||||
NazaraError("Cube dimensions are out of image's bounds");
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
|
||||
const Context* currentContext = Context::GetCurrent();
|
||||
if (m_context != currentContext)
|
||||
{
|
||||
if (!m_context->SetActive(true))
|
||||
{
|
||||
NazaraError("Failed to activate context");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
///TODO: Fast-path pour les images en cas de copie du buffer entier
|
||||
|
||||
m_buffer.resize(rect.width*rect.height*4);
|
||||
glReadPixels(rect.x, windowSize.y - rect.height - rect.y, rect.width, rect.height, GL_RGBA, GL_UNSIGNED_BYTE, m_buffer.data());
|
||||
|
||||
// Les pixels sont retournés, nous devons envoyer les pixels par rangée
|
||||
for (unsigned int i = 0; i < rect.height; ++i)
|
||||
image->Update(&m_buffer[rect.width*4*i], Boxui(dstPos.x, rect.height - i - 1, dstPos.z, rect.width, 1, 1), rect.width);
|
||||
|
||||
if (m_context != currentContext)
|
||||
{
|
||||
if (currentContext)
|
||||
{
|
||||
if (!currentContext->SetActive(true))
|
||||
NazaraWarning("Failed to reset old context");
|
||||
}
|
||||
else
|
||||
m_context->SetActive(false);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool RenderWindow::Create(VideoMode mode, const String& title, UInt32 style, const ContextParameters& parameters)
|
||||
{
|
||||
m_parameters = parameters;
|
||||
return Window::Create(mode, title, style);
|
||||
}
|
||||
|
||||
bool RenderWindow::Create(WindowHandle handle, const ContextParameters& parameters)
|
||||
{
|
||||
m_parameters = parameters;
|
||||
return Window::Create(handle);
|
||||
}
|
||||
|
||||
void RenderWindow::Display()
|
||||
{
|
||||
if (m_framerateLimit > 0)
|
||||
{
|
||||
int remainingTime = 1000/static_cast<int>(m_framerateLimit) - static_cast<int>(m_clock.GetMilliseconds());
|
||||
if (remainingTime > 0)
|
||||
Thread::Sleep(remainingTime);
|
||||
|
||||
m_clock.Restart();
|
||||
}
|
||||
|
||||
if (m_context && m_parameters.doubleBuffered)
|
||||
m_context->SwapBuffers();
|
||||
}
|
||||
|
||||
void RenderWindow::EnableVerticalSync(bool enabled)
|
||||
{
|
||||
if (m_context)
|
||||
{
|
||||
if (!m_context->SetActive(true))
|
||||
{
|
||||
NazaraError("Failed to activate context");
|
||||
return;
|
||||
}
|
||||
|
||||
m_context->EnableVerticalSync(enabled);
|
||||
}
|
||||
else
|
||||
NazaraError("No context");
|
||||
}
|
||||
|
||||
unsigned int RenderWindow::GetHeight() const
|
||||
{
|
||||
return Window::GetHeight();
|
||||
}
|
||||
|
||||
RenderTargetParameters RenderWindow::GetParameters() const
|
||||
{
|
||||
if (m_context)
|
||||
{
|
||||
const ContextParameters& parameters = m_context->GetParameters();
|
||||
return RenderTargetParameters(parameters.antialiasingLevel, parameters.depthBits, parameters.stencilBits);
|
||||
}
|
||||
else
|
||||
{
|
||||
NazaraError("Window not created/context not initialized");
|
||||
return RenderTargetParameters();
|
||||
}
|
||||
}
|
||||
|
||||
unsigned int RenderWindow::GetWidth() const
|
||||
{
|
||||
return Window::GetWidth();
|
||||
}
|
||||
|
||||
bool RenderWindow::IsRenderable() const
|
||||
{
|
||||
return m_impl != nullptr; // Si m_impl est valide, alors m_context l'est aussi
|
||||
}
|
||||
|
||||
bool RenderWindow::IsValid() const
|
||||
{
|
||||
return m_impl != nullptr;
|
||||
}
|
||||
|
||||
void RenderWindow::SetFramerateLimit(unsigned int limit)
|
||||
{
|
||||
m_framerateLimit = limit;
|
||||
}
|
||||
|
||||
ContextParameters RenderWindow::GetContextParameters() const
|
||||
{
|
||||
if (m_context)
|
||||
return m_context->GetParameters();
|
||||
else
|
||||
{
|
||||
NazaraError("Window not created/context not initialized");
|
||||
return ContextParameters();
|
||||
}
|
||||
}
|
||||
|
||||
bool RenderWindow::HasContext() const
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
bool RenderWindow::Activate() const
|
||||
{
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
///TODO: Fast-path pour les images en cas de copie du buffer entier
|
||||
|
||||
m_buffer.resize(rect.width*rect.height*4);
|
||||
glReadPixels(rect.x, windowSize.y - rect.height - rect.y, rect.width, rect.height, GL_RGBA, GL_UNSIGNED_BYTE, m_buffer.data());
|
||||
|
||||
// Les pixels sont retournés, nous devons envoyer les pixels par rangée
|
||||
for (unsigned int i = 0; i < rect.height; ++i)
|
||||
image->Update(&m_buffer[rect.width*4*i], NzBoxui(dstPos.x, rect.height - i - 1, dstPos.z, rect.width, 1, 1), rect.width);
|
||||
|
||||
if (m_context != currentContext)
|
||||
void RenderWindow::EnsureTargetUpdated() const
|
||||
{
|
||||
if (currentContext)
|
||||
{
|
||||
if (!currentContext->SetActive(true))
|
||||
NazaraWarning("Failed to reset old context");
|
||||
}
|
||||
else
|
||||
m_context->SetActive(false);
|
||||
// Rien à faire
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool NzRenderWindow::Create(NzVideoMode mode, const NzString& title, nzUInt32 style, const NzContextParameters& parameters)
|
||||
{
|
||||
m_parameters = parameters;
|
||||
return NzWindow::Create(mode, title, style);
|
||||
}
|
||||
|
||||
bool NzRenderWindow::Create(NzWindowHandle handle, const NzContextParameters& parameters)
|
||||
{
|
||||
m_parameters = parameters;
|
||||
return NzWindow::Create(handle);
|
||||
}
|
||||
|
||||
void NzRenderWindow::Display()
|
||||
{
|
||||
if (m_framerateLimit > 0)
|
||||
bool RenderWindow::OnWindowCreated()
|
||||
{
|
||||
int remainingTime = 1000/static_cast<int>(m_framerateLimit) - static_cast<int>(m_clock.GetMilliseconds());
|
||||
if (remainingTime > 0)
|
||||
NzThread::Sleep(remainingTime);
|
||||
m_parameters.doubleBuffered = true;
|
||||
m_parameters.window = GetHandle();
|
||||
|
||||
std::unique_ptr<Context> context(new Context);
|
||||
if (!context->Create(m_parameters))
|
||||
{
|
||||
NazaraError("Failed to create context");
|
||||
return false;
|
||||
}
|
||||
|
||||
m_context = context.release();
|
||||
|
||||
if (!SetActive(true)) // Les fenêtres s'activent à la création
|
||||
NazaraWarning("Failed to activate window");
|
||||
|
||||
EnableVerticalSync(false);
|
||||
|
||||
Vector2ui size = GetSize();
|
||||
|
||||
// Le scissorBox/viewport (à la création) est de la taille de la fenêtre
|
||||
// https://www.opengl.org/sdk/docs/man/xhtml/glGet.xml
|
||||
OpenGL::SetScissorBox(Recti(0, 0, size.x, size.y));
|
||||
OpenGL::SetViewport(Recti(0, 0, size.x, size.y));
|
||||
|
||||
OnRenderTargetParametersChange(this);
|
||||
OnRenderTargetSizeChange(this);
|
||||
|
||||
m_clock.Restart();
|
||||
}
|
||||
|
||||
if (m_context && m_parameters.doubleBuffered)
|
||||
m_context->SwapBuffers();
|
||||
}
|
||||
|
||||
void NzRenderWindow::EnableVerticalSync(bool enabled)
|
||||
{
|
||||
if (m_context)
|
||||
{
|
||||
if (!m_context->SetActive(true))
|
||||
{
|
||||
NazaraError("Failed to activate context");
|
||||
return;
|
||||
}
|
||||
|
||||
m_context->EnableVerticalSync(enabled);
|
||||
}
|
||||
else
|
||||
NazaraError("No context");
|
||||
}
|
||||
|
||||
unsigned int NzRenderWindow::GetHeight() const
|
||||
{
|
||||
return NzWindow::GetHeight();
|
||||
}
|
||||
|
||||
NzRenderTargetParameters NzRenderWindow::GetParameters() const
|
||||
{
|
||||
if (m_context)
|
||||
{
|
||||
const NzContextParameters& parameters = m_context->GetParameters();
|
||||
return NzRenderTargetParameters(parameters.antialiasingLevel, parameters.depthBits, parameters.stencilBits);
|
||||
}
|
||||
else
|
||||
{
|
||||
NazaraError("Window not created/context not initialized");
|
||||
return NzRenderTargetParameters();
|
||||
}
|
||||
}
|
||||
|
||||
unsigned int NzRenderWindow::GetWidth() const
|
||||
{
|
||||
return NzWindow::GetWidth();
|
||||
}
|
||||
|
||||
bool NzRenderWindow::IsRenderable() const
|
||||
{
|
||||
return m_impl != nullptr; // Si m_impl est valide, alors m_context l'est aussi
|
||||
}
|
||||
|
||||
bool NzRenderWindow::IsValid() const
|
||||
{
|
||||
return m_impl != nullptr;
|
||||
}
|
||||
|
||||
void NzRenderWindow::SetFramerateLimit(unsigned int limit)
|
||||
{
|
||||
m_framerateLimit = limit;
|
||||
}
|
||||
|
||||
NzContextParameters NzRenderWindow::GetContextParameters() const
|
||||
{
|
||||
if (m_context)
|
||||
return m_context->GetParameters();
|
||||
else
|
||||
{
|
||||
NazaraError("Window not created/context not initialized");
|
||||
return NzContextParameters();
|
||||
}
|
||||
}
|
||||
|
||||
bool NzRenderWindow::HasContext() const
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
bool NzRenderWindow::Activate() const
|
||||
{
|
||||
if (m_context->SetActive(true))
|
||||
{
|
||||
glDrawBuffer((m_parameters.doubleBuffered) ? GL_BACK : GL_FRONT);
|
||||
return true;
|
||||
}
|
||||
else
|
||||
|
||||
void RenderWindow::OnWindowDestroy()
|
||||
{
|
||||
NazaraError("Failed to activate window's context");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
if (m_context)
|
||||
{
|
||||
if (IsActive())
|
||||
Renderer::SetTarget(nullptr);
|
||||
|
||||
void NzRenderWindow::EnsureTargetUpdated() const
|
||||
{
|
||||
// Rien à faire
|
||||
}
|
||||
|
||||
bool NzRenderWindow::OnWindowCreated()
|
||||
{
|
||||
m_parameters.doubleBuffered = true;
|
||||
m_parameters.window = GetHandle();
|
||||
|
||||
std::unique_ptr<NzContext> context(new NzContext);
|
||||
if (!context->Create(m_parameters))
|
||||
{
|
||||
NazaraError("Failed to create context");
|
||||
return false;
|
||||
delete m_context;
|
||||
m_context = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
m_context = context.release();
|
||||
|
||||
if (!SetActive(true)) // Les fenêtres s'activent à la création
|
||||
NazaraWarning("Failed to activate window");
|
||||
|
||||
EnableVerticalSync(false);
|
||||
|
||||
NzVector2ui size = GetSize();
|
||||
|
||||
// Le scissorBox/viewport (à la création) est de la taille de la fenêtre
|
||||
// https://www.opengl.org/sdk/docs/man/xhtml/glGet.xml
|
||||
NzOpenGL::SetScissorBox(NzRecti(0, 0, size.x, size.y));
|
||||
NzOpenGL::SetViewport(NzRecti(0, 0, size.x, size.y));
|
||||
|
||||
OnRenderTargetParametersChange(this);
|
||||
OnRenderTargetSizeChange(this);
|
||||
|
||||
m_clock.Restart();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void NzRenderWindow::OnWindowDestroy()
|
||||
{
|
||||
if (m_context)
|
||||
void RenderWindow::OnWindowResized()
|
||||
{
|
||||
if (IsActive())
|
||||
NzRenderer::SetTarget(nullptr);
|
||||
|
||||
delete m_context;
|
||||
m_context = nullptr;
|
||||
OnRenderTargetSizeChange(this);
|
||||
}
|
||||
}
|
||||
|
||||
void NzRenderWindow::OnWindowResized()
|
||||
{
|
||||
OnRenderTargetSizeChange(this);
|
||||
}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -7,225 +7,228 @@
|
||||
#include <Nazara/Renderer/OpenGL.hpp>
|
||||
#include <Nazara/Renderer/Debug.hpp>
|
||||
|
||||
NzShaderStage::NzShaderStage() :
|
||||
m_compiled(false),
|
||||
m_id(0)
|
||||
namespace Nz
|
||||
{
|
||||
}
|
||||
|
||||
NzShaderStage::NzShaderStage(nzShaderStage stage) :
|
||||
NzShaderStage()
|
||||
{
|
||||
Create(stage);
|
||||
}
|
||||
|
||||
NzShaderStage::NzShaderStage(NzShaderStage&& stage) :
|
||||
m_stage(stage.m_stage),
|
||||
m_compiled(stage.m_compiled),
|
||||
m_id(stage.m_id)
|
||||
{
|
||||
stage.m_id = 0;
|
||||
}
|
||||
|
||||
NzShaderStage::~NzShaderStage()
|
||||
{
|
||||
Destroy();
|
||||
}
|
||||
|
||||
bool NzShaderStage::Compile()
|
||||
{
|
||||
#if NAZARA_RENDERER_SAFE
|
||||
if (!m_id)
|
||||
ShaderStage::ShaderStage() :
|
||||
m_compiled(false),
|
||||
m_id(0)
|
||||
{
|
||||
NazaraError("Shader stage is not initialized");
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
|
||||
glCompileShader(m_id);
|
||||
|
||||
GLint success;
|
||||
glGetShaderiv(m_id, GL_COMPILE_STATUS, &success);
|
||||
|
||||
m_compiled = (success == GL_TRUE);
|
||||
if (m_compiled)
|
||||
return true;
|
||||
else
|
||||
{
|
||||
NazaraError("Failed to compile shader stage: " + GetLog());
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
bool NzShaderStage::Create(nzShaderStage stage)
|
||||
{
|
||||
Destroy();
|
||||
|
||||
m_id = glCreateShader(NzOpenGL::ShaderStage[stage]);
|
||||
m_stage = stage;
|
||||
|
||||
return (m_id != 0);
|
||||
}
|
||||
|
||||
void NzShaderStage::Destroy()
|
||||
{
|
||||
m_compiled = false;
|
||||
if (m_id)
|
||||
{
|
||||
glDeleteShader(m_id);
|
||||
m_id = 0;
|
||||
}
|
||||
}
|
||||
|
||||
NzString NzShaderStage::GetLog() const
|
||||
{
|
||||
#if NAZARA_RENDERER_SAFE
|
||||
if (!m_id)
|
||||
{
|
||||
NazaraError("Shader stage is not initialized");
|
||||
return NzString();
|
||||
}
|
||||
#endif
|
||||
|
||||
NzString log;
|
||||
|
||||
GLint length = 0;
|
||||
glGetShaderiv(m_id, GL_INFO_LOG_LENGTH, &length);
|
||||
if (length > 1) // Le caractère de fin faisant partie du compte
|
||||
{
|
||||
log.Set(length - 1, '\0'); // La taille retournée est celle du buffer (Avec caractère de fin)
|
||||
glGetShaderInfoLog(m_id, length, nullptr, &log[0]);
|
||||
}
|
||||
else
|
||||
log = "No log.";
|
||||
|
||||
return log;
|
||||
}
|
||||
|
||||
NzString NzShaderStage::GetSource() const
|
||||
{
|
||||
#if NAZARA_RENDERER_SAFE
|
||||
if (!m_id)
|
||||
{
|
||||
NazaraError("Shader stage is not initialized");
|
||||
return NzString();
|
||||
}
|
||||
#endif
|
||||
|
||||
NzString source;
|
||||
|
||||
GLint length = 0;
|
||||
glGetShaderiv(m_id, GL_SHADER_SOURCE_LENGTH, &length);
|
||||
if (length > 1) // Le caractère de fin compte
|
||||
{
|
||||
source.Set(length - 1, '\0'); // La taille retournée est celle du buffer (Avec caractère de fin)
|
||||
glGetShaderSource(m_id, length, nullptr, &source[0]);
|
||||
}
|
||||
|
||||
return source;
|
||||
}
|
||||
|
||||
bool NzShaderStage::IsCompiled() const
|
||||
{
|
||||
return m_compiled;
|
||||
}
|
||||
|
||||
bool NzShaderStage::IsValid() const
|
||||
{
|
||||
return m_id != 0;
|
||||
}
|
||||
|
||||
void NzShaderStage::SetSource(const char* source, unsigned int length)
|
||||
{
|
||||
#if NAZARA_RENDERER_SAFE
|
||||
if (!m_id)
|
||||
ShaderStage::ShaderStage(ShaderStageType stage) :
|
||||
ShaderStage()
|
||||
{
|
||||
NazaraError("Shader stage is not initialized");
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
glShaderSource(m_id, 1, &source, reinterpret_cast<const GLint*>(&length));
|
||||
}
|
||||
|
||||
void NzShaderStage::SetSource(const NzString& source)
|
||||
{
|
||||
#if NAZARA_RENDERER_SAFE
|
||||
if (!m_id)
|
||||
{
|
||||
NazaraError("Shader stage is not initialized");
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
const char* tmp = source.GetConstBuffer();
|
||||
GLint length = source.GetSize();
|
||||
glShaderSource(m_id, 1, &tmp, &length);
|
||||
}
|
||||
|
||||
bool NzShaderStage::SetSourceFromFile(const NzString& filePath)
|
||||
{
|
||||
#if NAZARA_RENDERER_SAFE
|
||||
if (!m_id)
|
||||
{
|
||||
NazaraError("Shader stage is not initialized");
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
|
||||
NzFile file(filePath);
|
||||
if (!file.Open(nzOpenMode_ReadOnly | nzOpenMode_Text))
|
||||
{
|
||||
NazaraError("Failed to open \"" + filePath + '"');
|
||||
return false;
|
||||
Create(stage);
|
||||
}
|
||||
|
||||
unsigned int length = static_cast<unsigned int>(file.GetSize());
|
||||
|
||||
NzString source(length, '\0');
|
||||
|
||||
if (file.Read(&source[0], length) != length)
|
||||
ShaderStage::ShaderStage(ShaderStage&& stage) :
|
||||
m_stage(stage.m_stage),
|
||||
m_compiled(stage.m_compiled),
|
||||
m_id(stage.m_id)
|
||||
{
|
||||
NazaraError("Failed to read program file");
|
||||
return false;
|
||||
stage.m_id = 0;
|
||||
}
|
||||
|
||||
file.Close();
|
||||
|
||||
SetSource(source);
|
||||
return true;
|
||||
}
|
||||
|
||||
NzShaderStage& NzShaderStage::operator=(NzShaderStage&& shader)
|
||||
{
|
||||
Destroy();
|
||||
|
||||
m_compiled = shader.m_compiled;
|
||||
m_id = shader.m_id;
|
||||
m_stage = shader.m_stage;
|
||||
|
||||
shader.m_id = 0;
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
// Fonctions OpenGL
|
||||
unsigned int NzShaderStage::GetOpenGLID() const
|
||||
{
|
||||
return m_id;
|
||||
}
|
||||
|
||||
bool NzShaderStage::IsSupported(nzShaderStage stage)
|
||||
{
|
||||
switch (stage)
|
||||
ShaderStage::~ShaderStage()
|
||||
{
|
||||
case nzShaderStage_Fragment:
|
||||
case nzShaderStage_Geometry:
|
||||
case nzShaderStage_Vertex:
|
||||
return true;
|
||||
Destroy();
|
||||
}
|
||||
|
||||
default:
|
||||
NazaraError("Shader stage not handled (0x" + NzString::Number(stage, 16) + ')');
|
||||
bool ShaderStage::Compile()
|
||||
{
|
||||
#if NAZARA_RENDERER_SAFE
|
||||
if (!m_id)
|
||||
{
|
||||
NazaraError("Shader stage is not initialized");
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
|
||||
glCompileShader(m_id);
|
||||
|
||||
GLint success;
|
||||
glGetShaderiv(m_id, GL_COMPILE_STATUS, &success);
|
||||
|
||||
m_compiled = (success == GL_TRUE);
|
||||
if (m_compiled)
|
||||
return true;
|
||||
else
|
||||
{
|
||||
NazaraError("Failed to compile shader stage: " + GetLog());
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
bool ShaderStage::Create(ShaderStageType stage)
|
||||
{
|
||||
Destroy();
|
||||
|
||||
m_id = glCreateShader(OpenGL::ShaderStage[stage]);
|
||||
m_stage = stage;
|
||||
|
||||
return (m_id != 0);
|
||||
}
|
||||
|
||||
void ShaderStage::Destroy()
|
||||
{
|
||||
m_compiled = false;
|
||||
if (m_id)
|
||||
{
|
||||
glDeleteShader(m_id);
|
||||
m_id = 0;
|
||||
}
|
||||
}
|
||||
|
||||
String ShaderStage::GetLog() const
|
||||
{
|
||||
#if NAZARA_RENDERER_SAFE
|
||||
if (!m_id)
|
||||
{
|
||||
NazaraError("Shader stage is not initialized");
|
||||
return String();
|
||||
}
|
||||
#endif
|
||||
|
||||
String log;
|
||||
|
||||
GLint length = 0;
|
||||
glGetShaderiv(m_id, GL_INFO_LOG_LENGTH, &length);
|
||||
if (length > 1) // Le caractère de fin faisant partie du compte
|
||||
{
|
||||
log.Set(length - 1, '\0'); // La taille retournée est celle du buffer (Avec caractère de fin)
|
||||
glGetShaderInfoLog(m_id, length, nullptr, &log[0]);
|
||||
}
|
||||
else
|
||||
log = "No log.";
|
||||
|
||||
return log;
|
||||
}
|
||||
|
||||
String ShaderStage::GetSource() const
|
||||
{
|
||||
#if NAZARA_RENDERER_SAFE
|
||||
if (!m_id)
|
||||
{
|
||||
NazaraError("Shader stage is not initialized");
|
||||
return String();
|
||||
}
|
||||
#endif
|
||||
|
||||
String source;
|
||||
|
||||
GLint length = 0;
|
||||
glGetShaderiv(m_id, GL_SHADER_SOURCE_LENGTH, &length);
|
||||
if (length > 1) // Le caractère de fin compte
|
||||
{
|
||||
source.Set(length - 1, '\0'); // La taille retournée est celle du buffer (Avec caractère de fin)
|
||||
glGetShaderSource(m_id, length, nullptr, &source[0]);
|
||||
}
|
||||
|
||||
return source;
|
||||
}
|
||||
|
||||
bool ShaderStage::IsCompiled() const
|
||||
{
|
||||
return m_compiled;
|
||||
}
|
||||
|
||||
bool ShaderStage::IsValid() const
|
||||
{
|
||||
return m_id != 0;
|
||||
}
|
||||
|
||||
void ShaderStage::SetSource(const char* source, unsigned int length)
|
||||
{
|
||||
#if NAZARA_RENDERER_SAFE
|
||||
if (!m_id)
|
||||
{
|
||||
NazaraError("Shader stage is not initialized");
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
glShaderSource(m_id, 1, &source, reinterpret_cast<const GLint*>(&length));
|
||||
}
|
||||
|
||||
void ShaderStage::SetSource(const String& source)
|
||||
{
|
||||
#if NAZARA_RENDERER_SAFE
|
||||
if (!m_id)
|
||||
{
|
||||
NazaraError("Shader stage is not initialized");
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
const char* tmp = source.GetConstBuffer();
|
||||
GLint length = source.GetSize();
|
||||
glShaderSource(m_id, 1, &tmp, &length);
|
||||
}
|
||||
|
||||
bool ShaderStage::SetSourceFromFile(const String& filePath)
|
||||
{
|
||||
#if NAZARA_RENDERER_SAFE
|
||||
if (!m_id)
|
||||
{
|
||||
NazaraError("Shader stage is not initialized");
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
|
||||
File file(filePath);
|
||||
if (!file.Open(OpenMode_ReadOnly | OpenMode_Text))
|
||||
{
|
||||
NazaraError("Failed to open \"" + filePath + '"');
|
||||
return false;
|
||||
}
|
||||
|
||||
unsigned int length = static_cast<unsigned int>(file.GetSize());
|
||||
|
||||
String source(length, '\0');
|
||||
|
||||
if (file.Read(&source[0], length) != length)
|
||||
{
|
||||
NazaraError("Failed to read program file");
|
||||
return false;
|
||||
}
|
||||
|
||||
file.Close();
|
||||
|
||||
SetSource(source);
|
||||
return true;
|
||||
}
|
||||
|
||||
ShaderStage& ShaderStage::operator=(ShaderStage&& shader)
|
||||
{
|
||||
Destroy();
|
||||
|
||||
m_compiled = shader.m_compiled;
|
||||
m_id = shader.m_id;
|
||||
m_stage = shader.m_stage;
|
||||
|
||||
shader.m_id = 0;
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
// Fonctions OpenGL
|
||||
unsigned int ShaderStage::GetOpenGLID() const
|
||||
{
|
||||
return m_id;
|
||||
}
|
||||
|
||||
bool ShaderStage::IsSupported(ShaderStageType stage)
|
||||
{
|
||||
switch (stage)
|
||||
{
|
||||
case ShaderStageType_Fragment:
|
||||
case ShaderStageType_Geometry:
|
||||
case ShaderStageType_Vertex:
|
||||
return true;
|
||||
|
||||
default:
|
||||
NazaraError("Shader stage not handled (0x" + String::Number(stage, 16) + ')');
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -12,379 +12,382 @@
|
||||
#include <unordered_map>
|
||||
#include <Nazara/Renderer/Debug.hpp>
|
||||
|
||||
namespace
|
||||
namespace Nz
|
||||
{
|
||||
std::unordered_map<nzUInt32, GLuint> s_samplers;
|
||||
nzUInt8 s_maxAnisotropyLevel;
|
||||
bool s_useAnisotropicFilter;
|
||||
}
|
||||
|
||||
NzTextureSampler::NzTextureSampler() :
|
||||
m_filterMode(nzSamplerFilter_Default),
|
||||
m_wrapMode(nzSamplerWrap_Default),
|
||||
m_anisotropicLevel(0),
|
||||
m_mipmaps(true),
|
||||
m_samplerId(0)
|
||||
{
|
||||
}
|
||||
|
||||
nzUInt8 NzTextureSampler::GetAnisotropicLevel() const
|
||||
{
|
||||
return m_anisotropicLevel;
|
||||
}
|
||||
|
||||
nzSamplerFilter NzTextureSampler::GetFilterMode() const
|
||||
{
|
||||
return m_filterMode;
|
||||
}
|
||||
|
||||
nzSamplerWrap NzTextureSampler::GetWrapMode() const
|
||||
{
|
||||
return m_wrapMode;
|
||||
}
|
||||
|
||||
void NzTextureSampler::SetAnisotropyLevel(nzUInt8 anisotropyLevel)
|
||||
{
|
||||
#ifdef NAZARA_DEBUG
|
||||
if (!NzRenderer::IsInitialized())
|
||||
namespace
|
||||
{
|
||||
NazaraError("Renderer module must be initialized");
|
||||
return;
|
||||
std::unordered_map<UInt32, GLuint> s_samplers;
|
||||
UInt8 s_maxAnisotropyLevel;
|
||||
bool s_useAnisotropicFilter;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (m_anisotropicLevel != anisotropyLevel)
|
||||
TextureSampler::TextureSampler() :
|
||||
m_filterMode(SamplerFilter_Default),
|
||||
m_wrapMode(SamplerWrap_Default),
|
||||
m_anisotropicLevel(0),
|
||||
m_mipmaps(true),
|
||||
m_samplerId(0)
|
||||
{
|
||||
}
|
||||
|
||||
UInt8 TextureSampler::GetAnisotropicLevel() const
|
||||
{
|
||||
return m_anisotropicLevel;
|
||||
}
|
||||
|
||||
SamplerFilter TextureSampler::GetFilterMode() const
|
||||
{
|
||||
return m_filterMode;
|
||||
}
|
||||
|
||||
SamplerWrap TextureSampler::GetWrapMode() const
|
||||
{
|
||||
return m_wrapMode;
|
||||
}
|
||||
|
||||
void TextureSampler::SetAnisotropyLevel(UInt8 anisotropyLevel)
|
||||
{
|
||||
#ifdef NAZARA_DEBUG
|
||||
if (!Renderer::IsInitialized())
|
||||
{
|
||||
NazaraError("Renderer module must be initialized");
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (m_anisotropicLevel != anisotropyLevel)
|
||||
{
|
||||
if (anisotropyLevel > s_maxAnisotropyLevel)
|
||||
{
|
||||
NazaraWarning("Anisotropy level is over maximum anisotropy level (" + String::Number(anisotropyLevel) + " > " + String::Number(s_maxAnisotropyLevel) + ')');
|
||||
anisotropyLevel = s_maxAnisotropyLevel;
|
||||
}
|
||||
|
||||
m_anisotropicLevel = anisotropyLevel;
|
||||
m_samplerId = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void TextureSampler::SetFilterMode(SamplerFilter filterMode)
|
||||
{
|
||||
if (m_filterMode != filterMode)
|
||||
{
|
||||
m_filterMode = filterMode;
|
||||
m_samplerId = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void TextureSampler::SetWrapMode(SamplerWrap wrapMode)
|
||||
{
|
||||
if (m_wrapMode != wrapMode)
|
||||
{
|
||||
m_wrapMode = wrapMode;
|
||||
m_samplerId = 0;
|
||||
}
|
||||
}
|
||||
|
||||
UInt8 TextureSampler::GetDefaultAnisotropicLevel()
|
||||
{
|
||||
return s_defaultAnisotropyLevel;
|
||||
}
|
||||
|
||||
SamplerFilter TextureSampler::GetDefaultFilterMode()
|
||||
{
|
||||
return s_defaultFilterMode;
|
||||
}
|
||||
|
||||
SamplerWrap TextureSampler::GetDefaultWrapMode()
|
||||
{
|
||||
return s_defaultWrapMode;
|
||||
}
|
||||
|
||||
void TextureSampler::SetDefaultAnisotropyLevel(UInt8 anisotropyLevel)
|
||||
{
|
||||
#if NAZARA_RENDERER_SAFE
|
||||
if (anisotropyLevel == 0)
|
||||
{
|
||||
NazaraError("Default anisotropy level mode cannot be set to default value (0)");
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef NAZARA_DEBUG
|
||||
if (!Renderer::IsInitialized())
|
||||
{
|
||||
NazaraError("Renderer module must be initialized");
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (anisotropyLevel > s_maxAnisotropyLevel)
|
||||
{
|
||||
NazaraWarning("Anisotropy level is over maximum anisotropy level (" + NzString::Number(anisotropyLevel) + " > " + NzString::Number(s_maxAnisotropyLevel) + ')');
|
||||
NazaraWarning("Anisotropy level is over maximum anisotropy level (" + String::Number(anisotropyLevel) + " > " + String::Number(s_maxAnisotropyLevel));
|
||||
anisotropyLevel = s_maxAnisotropyLevel;
|
||||
}
|
||||
|
||||
m_anisotropicLevel = anisotropyLevel;
|
||||
m_samplerId = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void NzTextureSampler::SetFilterMode(nzSamplerFilter filterMode)
|
||||
{
|
||||
if (m_filterMode != filterMode)
|
||||
{
|
||||
m_filterMode = filterMode;
|
||||
m_samplerId = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void NzTextureSampler::SetWrapMode(nzSamplerWrap wrapMode)
|
||||
{
|
||||
if (m_wrapMode != wrapMode)
|
||||
{
|
||||
m_wrapMode = wrapMode;
|
||||
m_samplerId = 0;
|
||||
}
|
||||
}
|
||||
|
||||
nzUInt8 NzTextureSampler::GetDefaultAnisotropicLevel()
|
||||
{
|
||||
return s_defaultAnisotropyLevel;
|
||||
}
|
||||
|
||||
nzSamplerFilter NzTextureSampler::GetDefaultFilterMode()
|
||||
{
|
||||
return s_defaultFilterMode;
|
||||
}
|
||||
|
||||
nzSamplerWrap NzTextureSampler::GetDefaultWrapMode()
|
||||
{
|
||||
return s_defaultWrapMode;
|
||||
}
|
||||
|
||||
void NzTextureSampler::SetDefaultAnisotropyLevel(nzUInt8 anisotropyLevel)
|
||||
{
|
||||
#if NAZARA_RENDERER_SAFE
|
||||
if (anisotropyLevel == 0)
|
||||
{
|
||||
NazaraError("Default anisotropy level mode cannot be set to default value (0)");
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef NAZARA_DEBUG
|
||||
if (!NzRenderer::IsInitialized())
|
||||
{
|
||||
NazaraError("Renderer module must be initialized");
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (anisotropyLevel > s_maxAnisotropyLevel)
|
||||
{
|
||||
NazaraWarning("Anisotropy level is over maximum anisotropy level (" + NzString::Number(anisotropyLevel) + " > " + NzString::Number(s_maxAnisotropyLevel));
|
||||
anisotropyLevel = s_maxAnisotropyLevel;
|
||||
}
|
||||
|
||||
s_defaultAnisotropyLevel = anisotropyLevel;
|
||||
|
||||
if (s_useAnisotropicFilter)
|
||||
{
|
||||
for (const std::pair<nzUInt32, GLuint>& pair : s_samplers)
|
||||
{
|
||||
if (((pair.first >> 5) & 0xFF) == 0)
|
||||
glSamplerParameterf(pair.second, GL_TEXTURE_MAX_ANISOTROPY_EXT, static_cast<float>(anisotropyLevel));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void NzTextureSampler::SetDefaultFilterMode(nzSamplerFilter filterMode)
|
||||
{
|
||||
#if NAZARA_RENDERER_SAFE
|
||||
if (filterMode == nzSamplerFilter_Default)
|
||||
{
|
||||
NazaraError("Default filter mode cannot be set to default enum value (nzSamplerFilter_Default)");
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
s_defaultFilterMode = filterMode;
|
||||
|
||||
for (const std::pair<nzUInt32, GLuint>& pair : s_samplers)
|
||||
{
|
||||
if (((pair.first >> 1) & 0x3) == nzSamplerFilter_Default)
|
||||
{
|
||||
bool mipmaps = pair.first & 0x1;
|
||||
switch (filterMode)
|
||||
{
|
||||
case nzSamplerFilter_Bilinear:
|
||||
if (mipmaps)
|
||||
glSamplerParameteri(pair.second, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_NEAREST);
|
||||
else
|
||||
glSamplerParameteri(pair.second, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
||||
|
||||
glSamplerParameteri(pair.second, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||
break;
|
||||
|
||||
case nzSamplerFilter_Nearest:
|
||||
if (mipmaps)
|
||||
glSamplerParameteri(pair.second, GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_NEAREST);
|
||||
else
|
||||
glSamplerParameteri(pair.second, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
|
||||
|
||||
glSamplerParameteri(pair.second, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
|
||||
break;
|
||||
|
||||
case nzSamplerFilter_Trilinear:
|
||||
if (mipmaps)
|
||||
glSamplerParameteri(pair.second, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
|
||||
else
|
||||
glSamplerParameteri(pair.second, GL_TEXTURE_MIN_FILTER, GL_LINEAR); // Filtrage bilinéaire
|
||||
|
||||
glSamplerParameteri(pair.second, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||
break;
|
||||
|
||||
default:
|
||||
NazaraError("Texture filter not handled (0x" + NzString::Number(filterMode, 16) + ')');
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void NzTextureSampler::SetDefaultWrapMode(nzSamplerWrap wrapMode)
|
||||
{
|
||||
#if NAZARA_RENDERER_SAFE
|
||||
if (wrapMode == nzSamplerWrap_Default)
|
||||
{
|
||||
NazaraError("Default wrap mode cannot be set to default enum value (nzSamplerWrap_Default)");
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
s_defaultWrapMode = wrapMode;
|
||||
|
||||
GLenum wrapEnum = NzOpenGL::SamplerWrapMode[wrapMode];
|
||||
for (const std::pair<nzUInt32, GLuint>& pair : s_samplers)
|
||||
{
|
||||
if (((pair.first >> 3) & 0x3) == nzSamplerWrap_Default)
|
||||
{
|
||||
glSamplerParameteri(pair.second, GL_TEXTURE_WRAP_R, wrapEnum);
|
||||
glSamplerParameteri(pair.second, GL_TEXTURE_WRAP_T, wrapEnum);
|
||||
glSamplerParameteri(pair.second, GL_TEXTURE_WRAP_S, wrapEnum);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void NzTextureSampler::Apply(const NzTexture* texture) const
|
||||
{
|
||||
nzImageType type = texture->GetType();
|
||||
GLenum target = NzOpenGL::TextureTarget[type];
|
||||
|
||||
NzOpenGL::BindTexture(type, texture->GetOpenGLID());
|
||||
|
||||
if (s_useAnisotropicFilter)
|
||||
{
|
||||
nzUInt8 anisotropyLevel = (m_anisotropicLevel == 0) ? s_defaultAnisotropyLevel : m_anisotropicLevel;
|
||||
glTexParameterf(target, GL_TEXTURE_MAX_ANISOTROPY_EXT, static_cast<float>(anisotropyLevel));
|
||||
}
|
||||
|
||||
nzSamplerFilter filterMode = (m_filterMode == nzSamplerFilter_Default) ? s_defaultFilterMode : m_filterMode;
|
||||
switch (filterMode)
|
||||
{
|
||||
case nzSamplerFilter_Bilinear:
|
||||
if (m_mipmaps)
|
||||
glTexParameteri(target, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_NEAREST);
|
||||
else
|
||||
glTexParameteri(target, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
||||
|
||||
glTexParameteri(target, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||
break;
|
||||
|
||||
case nzSamplerFilter_Nearest:
|
||||
if (m_mipmaps)
|
||||
glTexParameteri(target, GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_NEAREST);
|
||||
else
|
||||
glTexParameteri(target, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
|
||||
|
||||
glTexParameteri(target, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
|
||||
break;
|
||||
|
||||
case nzSamplerFilter_Trilinear:
|
||||
if (m_mipmaps)
|
||||
glTexParameteri(target, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
|
||||
else
|
||||
glTexParameteri(target, GL_TEXTURE_MIN_FILTER, GL_LINEAR); // Filtrage bilinéaire
|
||||
|
||||
glTexParameteri(target, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||
break;
|
||||
|
||||
default:
|
||||
NazaraError("Texture filter not handled (0x" + NzString::Number(filterMode, 16) + ')');
|
||||
break;
|
||||
}
|
||||
|
||||
GLenum wrapMode = NzOpenGL::SamplerWrapMode[(m_wrapMode == nzSamplerWrap_Default) ? s_defaultWrapMode : m_wrapMode];
|
||||
switch (type)
|
||||
{
|
||||
// Notez l'absence de "break" ici
|
||||
case nzImageType_3D:
|
||||
glTexParameteri(target, GL_TEXTURE_WRAP_R, wrapMode);
|
||||
case nzImageType_2D:
|
||||
case nzImageType_2D_Array:
|
||||
case nzImageType_Cubemap:
|
||||
glTexParameteri(target, GL_TEXTURE_WRAP_T, wrapMode);
|
||||
case nzImageType_1D:
|
||||
case nzImageType_1D_Array:
|
||||
glTexParameteri(target, GL_TEXTURE_WRAP_S, wrapMode);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void NzTextureSampler::Bind(unsigned int unit) const
|
||||
{
|
||||
static_assert(nzSamplerFilter_Max < 0x4, "Maximum sampler filter mode takes more than 2 bits");
|
||||
static_assert(nzSamplerWrap_Max < 0x4, "Maximum sampler wrap mode takes more than 2 bits");
|
||||
|
||||
if (!m_samplerId)
|
||||
UpdateSamplerId();
|
||||
|
||||
NzOpenGL::BindSampler(unit, m_samplerId);
|
||||
}
|
||||
|
||||
unsigned int NzTextureSampler::GetOpenGLID() const
|
||||
{
|
||||
if (!m_samplerId)
|
||||
UpdateSamplerId();
|
||||
|
||||
return m_samplerId;
|
||||
}
|
||||
|
||||
void NzTextureSampler::UpdateSamplerId() const
|
||||
{
|
||||
nzUInt32 key = (((m_mipmaps) ? 1 : 0) << 0) | // 1 bit
|
||||
(m_filterMode << 1) | // 2 bits
|
||||
(m_wrapMode << 3) | // 2 bits
|
||||
(m_anisotropicLevel << 5); // 8 bits
|
||||
|
||||
auto it = s_samplers.find(key);
|
||||
if (it == s_samplers.end())
|
||||
{
|
||||
GLuint sampler;
|
||||
glGenSamplers(1, &sampler);
|
||||
s_defaultAnisotropyLevel = anisotropyLevel;
|
||||
|
||||
if (s_useAnisotropicFilter)
|
||||
{
|
||||
nzUInt8 anisotropyLevel = (m_anisotropicLevel == 0) ? s_defaultAnisotropyLevel : m_anisotropicLevel;
|
||||
glSamplerParameterf(sampler, GL_TEXTURE_MAX_ANISOTROPY_EXT, static_cast<float>(anisotropyLevel));
|
||||
for (const std::pair<UInt32, GLuint>& pair : s_samplers)
|
||||
{
|
||||
if (((pair.first >> 5) & 0xFF) == 0)
|
||||
glSamplerParameterf(pair.second, GL_TEXTURE_MAX_ANISOTROPY_EXT, static_cast<float>(anisotropyLevel));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void TextureSampler::SetDefaultFilterMode(SamplerFilter filterMode)
|
||||
{
|
||||
#if NAZARA_RENDERER_SAFE
|
||||
if (filterMode == SamplerFilter_Default)
|
||||
{
|
||||
NazaraError("Default filter mode cannot be set to default enum value (SamplerFilter_Default)");
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
s_defaultFilterMode = filterMode;
|
||||
|
||||
for (const std::pair<UInt32, GLuint>& pair : s_samplers)
|
||||
{
|
||||
if (((pair.first >> 1) & 0x3) == SamplerFilter_Default)
|
||||
{
|
||||
bool mipmaps = pair.first & 0x1;
|
||||
switch (filterMode)
|
||||
{
|
||||
case SamplerFilter_Bilinear:
|
||||
if (mipmaps)
|
||||
glSamplerParameteri(pair.second, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_NEAREST);
|
||||
else
|
||||
glSamplerParameteri(pair.second, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
||||
|
||||
glSamplerParameteri(pair.second, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||
break;
|
||||
|
||||
case SamplerFilter_Nearest:
|
||||
if (mipmaps)
|
||||
glSamplerParameteri(pair.second, GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_NEAREST);
|
||||
else
|
||||
glSamplerParameteri(pair.second, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
|
||||
|
||||
glSamplerParameteri(pair.second, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
|
||||
break;
|
||||
|
||||
case SamplerFilter_Trilinear:
|
||||
if (mipmaps)
|
||||
glSamplerParameteri(pair.second, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
|
||||
else
|
||||
glSamplerParameteri(pair.second, GL_TEXTURE_MIN_FILTER, GL_LINEAR); // Filtrage bilinéaire
|
||||
|
||||
glSamplerParameteri(pair.second, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||
break;
|
||||
|
||||
default:
|
||||
NazaraError("Texture filter not handled (0x" + String::Number(filterMode, 16) + ')');
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void TextureSampler::SetDefaultWrapMode(SamplerWrap wrapMode)
|
||||
{
|
||||
#if NAZARA_RENDERER_SAFE
|
||||
if (wrapMode == SamplerWrap_Default)
|
||||
{
|
||||
NazaraError("Default wrap mode cannot be set to default enum value (SamplerWrap_Default)");
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
s_defaultWrapMode = wrapMode;
|
||||
|
||||
GLenum wrapEnum = OpenGL::SamplerWrapMode[wrapMode];
|
||||
for (const std::pair<UInt32, GLuint>& pair : s_samplers)
|
||||
{
|
||||
if (((pair.first >> 3) & 0x3) == SamplerWrap_Default)
|
||||
{
|
||||
glSamplerParameteri(pair.second, GL_TEXTURE_WRAP_R, wrapEnum);
|
||||
glSamplerParameteri(pair.second, GL_TEXTURE_WRAP_T, wrapEnum);
|
||||
glSamplerParameteri(pair.second, GL_TEXTURE_WRAP_S, wrapEnum);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void TextureSampler::Apply(const Texture* texture) const
|
||||
{
|
||||
ImageType type = texture->GetType();
|
||||
GLenum target = OpenGL::TextureTarget[type];
|
||||
|
||||
OpenGL::BindTexture(type, texture->GetOpenGLID());
|
||||
|
||||
if (s_useAnisotropicFilter)
|
||||
{
|
||||
UInt8 anisotropyLevel = (m_anisotropicLevel == 0) ? s_defaultAnisotropyLevel : m_anisotropicLevel;
|
||||
glTexParameterf(target, GL_TEXTURE_MAX_ANISOTROPY_EXT, static_cast<float>(anisotropyLevel));
|
||||
}
|
||||
|
||||
nzSamplerFilter filterMode = (m_filterMode == nzSamplerFilter_Default) ? s_defaultFilterMode : m_filterMode;
|
||||
SamplerFilter filterMode = (m_filterMode == SamplerFilter_Default) ? s_defaultFilterMode : m_filterMode;
|
||||
switch (filterMode)
|
||||
{
|
||||
case nzSamplerFilter_Bilinear:
|
||||
glSamplerParameteri(sampler, GL_TEXTURE_MIN_FILTER, (m_mipmaps) ? GL_LINEAR_MIPMAP_NEAREST : GL_LINEAR);
|
||||
glSamplerParameteri(sampler, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||
case SamplerFilter_Bilinear:
|
||||
if (m_mipmaps)
|
||||
glTexParameteri(target, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_NEAREST);
|
||||
else
|
||||
glTexParameteri(target, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
||||
|
||||
glTexParameteri(target, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||
break;
|
||||
|
||||
case nzSamplerFilter_Nearest:
|
||||
glSamplerParameteri(sampler, GL_TEXTURE_MIN_FILTER, (m_mipmaps) ? GL_NEAREST_MIPMAP_NEAREST : GL_NEAREST);
|
||||
glSamplerParameteri(sampler, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
|
||||
case SamplerFilter_Nearest:
|
||||
if (m_mipmaps)
|
||||
glTexParameteri(target, GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_NEAREST);
|
||||
else
|
||||
glTexParameteri(target, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
|
||||
|
||||
glTexParameteri(target, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
|
||||
break;
|
||||
|
||||
case nzSamplerFilter_Trilinear:
|
||||
// Équivalent au filtrage bilinéaire si les mipmaps sont absentes
|
||||
glSamplerParameteri(sampler, GL_TEXTURE_MIN_FILTER, (m_mipmaps) ? GL_LINEAR_MIPMAP_LINEAR : GL_LINEAR);
|
||||
glSamplerParameteri(sampler, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||
case SamplerFilter_Trilinear:
|
||||
if (m_mipmaps)
|
||||
glTexParameteri(target, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
|
||||
else
|
||||
glTexParameteri(target, GL_TEXTURE_MIN_FILTER, GL_LINEAR); // Filtrage bilinéaire
|
||||
|
||||
glTexParameteri(target, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||
break;
|
||||
|
||||
default:
|
||||
NazaraError("Texture filter not handled (0x" + NzString::Number(filterMode, 16) + ')');
|
||||
NazaraError("Texture filter not handled (0x" + String::Number(filterMode, 16) + ')');
|
||||
break;
|
||||
}
|
||||
|
||||
GLenum wrapMode = NzOpenGL::SamplerWrapMode[(m_wrapMode == nzSamplerWrap_Default) ? s_defaultWrapMode : m_wrapMode];
|
||||
glSamplerParameteri(sampler, GL_TEXTURE_WRAP_R, wrapMode);
|
||||
glSamplerParameteri(sampler, GL_TEXTURE_WRAP_T, wrapMode);
|
||||
glSamplerParameteri(sampler, GL_TEXTURE_WRAP_S, wrapMode);
|
||||
|
||||
s_samplers[key] = sampler;
|
||||
m_samplerId = sampler;
|
||||
GLenum wrapMode = OpenGL::SamplerWrapMode[(m_wrapMode == SamplerWrap_Default) ? s_defaultWrapMode : m_wrapMode];
|
||||
switch (type)
|
||||
{
|
||||
// Notez l'absence de "break" ici
|
||||
case ImageType_3D:
|
||||
glTexParameteri(target, GL_TEXTURE_WRAP_R, wrapMode);
|
||||
case ImageType_2D:
|
||||
case ImageType_2D_Array:
|
||||
case ImageType_Cubemap:
|
||||
glTexParameteri(target, GL_TEXTURE_WRAP_T, wrapMode);
|
||||
case ImageType_1D:
|
||||
case ImageType_1D_Array:
|
||||
glTexParameteri(target, GL_TEXTURE_WRAP_S, wrapMode);
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
m_samplerId = it->second;
|
||||
}
|
||||
|
||||
bool NzTextureSampler::UseMipmaps(bool mipmaps)
|
||||
{
|
||||
if (m_mipmaps != mipmaps)
|
||||
void TextureSampler::Bind(unsigned int unit) const
|
||||
{
|
||||
m_mipmaps = mipmaps;
|
||||
m_samplerId = 0;
|
||||
static_assert(SamplerFilter_Max < 0x4, "Maximum sampler filter mode takes more than 2 bits");
|
||||
static_assert(SamplerWrap_Max < 0x4, "Maximum sampler wrap mode takes more than 2 bits");
|
||||
|
||||
return true; // Renvoie true si la valeur a été changée (Donc s'il faut réappliquer le sampler)
|
||||
if (!m_samplerId)
|
||||
UpdateSamplerId();
|
||||
|
||||
OpenGL::BindSampler(unit, m_samplerId);
|
||||
}
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
bool NzTextureSampler::Initialize()
|
||||
{
|
||||
s_maxAnisotropyLevel = NzRenderer::GetMaxAnisotropyLevel();
|
||||
s_useAnisotropicFilter = NzOpenGL::IsSupported(nzOpenGLExtension_AnisotropicFilter);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void NzTextureSampler::Uninitialize()
|
||||
{
|
||||
if (!s_samplers.empty())
|
||||
unsigned int TextureSampler::GetOpenGLID() const
|
||||
{
|
||||
NzContext::EnsureContext();
|
||||
for (const std::pair<nzUInt32, GLuint>& pair : s_samplers)
|
||||
NzOpenGL::DeleteSampler(pair.second);
|
||||
if (!m_samplerId)
|
||||
UpdateSamplerId();
|
||||
|
||||
s_samplers.clear();
|
||||
return m_samplerId;
|
||||
}
|
||||
}
|
||||
|
||||
nzUInt8 NzTextureSampler::s_defaultAnisotropyLevel = 1;
|
||||
nzSamplerFilter NzTextureSampler::s_defaultFilterMode = nzSamplerFilter_Trilinear;
|
||||
nzSamplerWrap NzTextureSampler::s_defaultWrapMode = nzSamplerWrap_Repeat;
|
||||
void TextureSampler::UpdateSamplerId() const
|
||||
{
|
||||
UInt32 key = (((m_mipmaps) ? 1 : 0) << 0) | // 1 bit
|
||||
(m_filterMode << 1) | // 2 bits
|
||||
(m_wrapMode << 3) | // 2 bits
|
||||
(m_anisotropicLevel << 5); // 8 bits
|
||||
|
||||
auto it = s_samplers.find(key);
|
||||
if (it == s_samplers.end())
|
||||
{
|
||||
GLuint sampler;
|
||||
glGenSamplers(1, &sampler);
|
||||
|
||||
if (s_useAnisotropicFilter)
|
||||
{
|
||||
UInt8 anisotropyLevel = (m_anisotropicLevel == 0) ? s_defaultAnisotropyLevel : m_anisotropicLevel;
|
||||
glSamplerParameterf(sampler, GL_TEXTURE_MAX_ANISOTROPY_EXT, static_cast<float>(anisotropyLevel));
|
||||
}
|
||||
|
||||
SamplerFilter filterMode = (m_filterMode == SamplerFilter_Default) ? s_defaultFilterMode : m_filterMode;
|
||||
switch (filterMode)
|
||||
{
|
||||
case SamplerFilter_Bilinear:
|
||||
glSamplerParameteri(sampler, GL_TEXTURE_MIN_FILTER, (m_mipmaps) ? GL_LINEAR_MIPMAP_NEAREST : GL_LINEAR);
|
||||
glSamplerParameteri(sampler, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||
break;
|
||||
|
||||
case SamplerFilter_Nearest:
|
||||
glSamplerParameteri(sampler, GL_TEXTURE_MIN_FILTER, (m_mipmaps) ? GL_NEAREST_MIPMAP_NEAREST : GL_NEAREST);
|
||||
glSamplerParameteri(sampler, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
|
||||
break;
|
||||
|
||||
case SamplerFilter_Trilinear:
|
||||
// Équivalent au filtrage bilinéaire si les mipmaps sont absentes
|
||||
glSamplerParameteri(sampler, GL_TEXTURE_MIN_FILTER, (m_mipmaps) ? GL_LINEAR_MIPMAP_LINEAR : GL_LINEAR);
|
||||
glSamplerParameteri(sampler, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||
break;
|
||||
|
||||
default:
|
||||
NazaraError("Texture filter not handled (0x" + String::Number(filterMode, 16) + ')');
|
||||
break;
|
||||
}
|
||||
|
||||
GLenum wrapMode = OpenGL::SamplerWrapMode[(m_wrapMode == SamplerWrap_Default) ? s_defaultWrapMode : m_wrapMode];
|
||||
glSamplerParameteri(sampler, GL_TEXTURE_WRAP_R, wrapMode);
|
||||
glSamplerParameteri(sampler, GL_TEXTURE_WRAP_T, wrapMode);
|
||||
glSamplerParameteri(sampler, GL_TEXTURE_WRAP_S, wrapMode);
|
||||
|
||||
s_samplers[key] = sampler;
|
||||
m_samplerId = sampler;
|
||||
}
|
||||
else
|
||||
m_samplerId = it->second;
|
||||
}
|
||||
|
||||
bool TextureSampler::UseMipmaps(bool mipmaps)
|
||||
{
|
||||
if (m_mipmaps != mipmaps)
|
||||
{
|
||||
m_mipmaps = mipmaps;
|
||||
m_samplerId = 0;
|
||||
|
||||
return true; // Renvoie true si la valeur a été changée (Donc s'il faut réappliquer le sampler)
|
||||
}
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
bool TextureSampler::Initialize()
|
||||
{
|
||||
s_maxAnisotropyLevel = Renderer::GetMaxAnisotropyLevel();
|
||||
s_useAnisotropicFilter = OpenGL::IsSupported(OpenGLExtension_AnisotropicFilter);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void TextureSampler::Uninitialize()
|
||||
{
|
||||
if (!s_samplers.empty())
|
||||
{
|
||||
Context::EnsureContext();
|
||||
for (const std::pair<UInt32, GLuint>& pair : s_samplers)
|
||||
OpenGL::DeleteSampler(pair.second);
|
||||
|
||||
s_samplers.clear();
|
||||
}
|
||||
}
|
||||
|
||||
UInt8 TextureSampler::s_defaultAnisotropyLevel = 1;
|
||||
SamplerFilter TextureSampler::s_defaultFilterMode = SamplerFilter_Trilinear;
|
||||
SamplerWrap TextureSampler::s_defaultWrapMode = SamplerWrap_Repeat;
|
||||
}
|
||||
|
||||
@@ -5,25 +5,28 @@
|
||||
#include <Nazara/Renderer/UberShader.hpp>
|
||||
#include <Nazara/Renderer/Debug.hpp>
|
||||
|
||||
NzUberShader::~NzUberShader()
|
||||
namespace Nz
|
||||
{
|
||||
OnUberShaderRelease(this);
|
||||
}
|
||||
|
||||
bool NzUberShader::Initialize()
|
||||
{
|
||||
if (!NzUberShaderLibrary::Initialize())
|
||||
UberShader::~UberShader()
|
||||
{
|
||||
NazaraError("Failed to initialise library");
|
||||
return false;
|
||||
OnUberShaderRelease(this);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
bool UberShader::Initialize()
|
||||
{
|
||||
if (!UberShaderLibrary::Initialize())
|
||||
{
|
||||
NazaraError("Failed to initialise library");
|
||||
return false;
|
||||
}
|
||||
|
||||
void NzUberShader::Uninitialize()
|
||||
{
|
||||
NzUberShaderLibrary::Uninitialize();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
NzUberShaderLibrary::LibraryMap NzUberShader::s_library;
|
||||
void UberShader::Uninitialize()
|
||||
{
|
||||
UberShaderLibrary::Uninitialize();
|
||||
}
|
||||
|
||||
UberShaderLibrary::LibraryMap UberShader::s_library;
|
||||
}
|
||||
|
||||
@@ -6,14 +6,17 @@
|
||||
#include <algorithm>
|
||||
#include <Nazara/Renderer/Debug.hpp>
|
||||
|
||||
NzUberShaderInstance::NzUberShaderInstance(const NzShader* shader) :
|
||||
m_shader(shader)
|
||||
namespace Nz
|
||||
{
|
||||
}
|
||||
UberShaderInstance::UberShaderInstance(const Shader* shader) :
|
||||
m_shader(shader)
|
||||
{
|
||||
}
|
||||
|
||||
NzUberShaderInstance::~NzUberShaderInstance() = default;
|
||||
UberShaderInstance::~UberShaderInstance() = default;
|
||||
|
||||
const NzShader* NzUberShaderInstance::GetShader() const
|
||||
{
|
||||
return m_shader;
|
||||
const Shader* UberShaderInstance::GetShader() const
|
||||
{
|
||||
return m_shader;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,16 +6,19 @@
|
||||
#include <Nazara/Renderer/Renderer.hpp>
|
||||
#include <Nazara/Renderer/Debug.hpp>
|
||||
|
||||
NzUberShaderInstancePreprocessor::NzUberShaderInstancePreprocessor(const NzShader* shader) :
|
||||
NzUberShaderInstance(shader)
|
||||
namespace Nz
|
||||
{
|
||||
}
|
||||
|
||||
NzUberShaderInstancePreprocessor::~NzUberShaderInstancePreprocessor() = default;
|
||||
|
||||
bool NzUberShaderInstancePreprocessor::Activate() const
|
||||
{
|
||||
NzRenderer::SetShader(m_shader);
|
||||
|
||||
return true;
|
||||
UberShaderInstancePreprocessor::UberShaderInstancePreprocessor(const Shader* shader) :
|
||||
UberShaderInstance(shader)
|
||||
{
|
||||
}
|
||||
|
||||
UberShaderInstancePreprocessor::~UberShaderInstancePreprocessor() = default;
|
||||
|
||||
bool UberShaderInstancePreprocessor::Activate() const
|
||||
{
|
||||
Renderer::SetShader(m_shader);
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -10,175 +10,178 @@
|
||||
#include <memory>
|
||||
#include <Nazara/Renderer/Debug.hpp>
|
||||
|
||||
NzUberShaderPreprocessor::~NzUberShaderPreprocessor()
|
||||
namespace Nz
|
||||
{
|
||||
OnUberShaderPreprocessorRelease(this);
|
||||
}
|
||||
|
||||
NzUberShaderInstance* NzUberShaderPreprocessor::Get(const NzParameterList& parameters) const
|
||||
{
|
||||
// Première étape, transformer les paramètres en un flag
|
||||
nzUInt32 flags = 0;
|
||||
for (auto it = m_flags.begin(); it != m_flags.end(); ++it)
|
||||
UberShaderPreprocessor::~UberShaderPreprocessor()
|
||||
{
|
||||
if (parameters.HasParameter(it->first))
|
||||
{
|
||||
bool value;
|
||||
if (parameters.GetBooleanParameter(it->first, &value) && value)
|
||||
flags |= it->second;
|
||||
}
|
||||
OnUberShaderPreprocessorRelease(this);
|
||||
}
|
||||
|
||||
// Le shader fait-il partie du cache ?
|
||||
auto shaderIt = m_cache.find(flags);
|
||||
|
||||
// Si non, il nous faut le construire
|
||||
if (shaderIt == m_cache.end())
|
||||
UberShaderInstance* UberShaderPreprocessor::Get(const ParameterList& parameters) const
|
||||
{
|
||||
try
|
||||
// Première étape, transformer les paramètres en un flag
|
||||
UInt32 flags = 0;
|
||||
for (auto it = m_flags.begin(); it != m_flags.end(); ++it)
|
||||
{
|
||||
// Une exception sera lancée à la moindre erreur et celle-ci ne sera pas enregistrée dans le log (car traitée dans le bloc catch)
|
||||
NzErrorFlags errFlags(nzErrorFlag_Silent | nzErrorFlag_ThrowException, true);
|
||||
|
||||
NzShaderRef shader = NzShader::New();
|
||||
shader->Create();
|
||||
|
||||
for (unsigned int i = 0; i <= nzShaderStage_Max; ++i)
|
||||
if (parameters.HasParameter(it->first))
|
||||
{
|
||||
const Shader& shaderStage = m_shaders[i];
|
||||
|
||||
// Le shader stage est-il activé dans cette version du shader ?
|
||||
if (shaderStage.present && (flags & shaderStage.requiredFlags) == shaderStage.requiredFlags)
|
||||
{
|
||||
nzUInt32 stageFlags = 0;
|
||||
for (auto it = shaderStage.flags.begin(); it != shaderStage.flags.end(); ++it)
|
||||
{
|
||||
if (parameters.HasParameter(it->first))
|
||||
{
|
||||
bool value;
|
||||
if (parameters.GetBooleanParameter(it->first, &value) && value)
|
||||
stageFlags |= it->second;
|
||||
}
|
||||
}
|
||||
|
||||
auto stageIt = shaderStage.cache.find(stageFlags);
|
||||
if (stageIt == shaderStage.cache.end())
|
||||
{
|
||||
NzShaderStage stage;
|
||||
stage.Create(static_cast<nzShaderStage>(i));
|
||||
|
||||
unsigned int glslVersion = NzOpenGL::GetGLSLVersion();
|
||||
|
||||
NzStringStream code;
|
||||
code << "#version " << glslVersion << "\n\n";
|
||||
|
||||
code << "#define GLSL_VERSION " << glslVersion << "\n\n";
|
||||
|
||||
code << "#define EARLY_FRAGMENT_TEST " << (glslVersion >= 420 || NzOpenGL::IsSupported(nzOpenGLExtension_Shader_ImageLoadStore)) << "\n\n";
|
||||
|
||||
for (auto it = shaderStage.flags.begin(); it != shaderStage.flags.end(); ++it)
|
||||
code << "#define " << it->first << ' ' << ((stageFlags & it->second) ? '1' : '0') << '\n';
|
||||
|
||||
code << "\n#line 1\n"; // Pour que les éventuelles erreurs du shader se réfèrent à la bonne ligne
|
||||
code << shaderStage.source;
|
||||
|
||||
stage.SetSource(code);
|
||||
stage.Compile();
|
||||
|
||||
stageIt = shaderStage.cache.emplace(flags, std::move(stage)).first;
|
||||
}
|
||||
|
||||
shader->AttachStage(static_cast<nzShaderStage>(i), stageIt->second);
|
||||
}
|
||||
bool value;
|
||||
if (parameters.GetBooleanParameter(it->first, &value) && value)
|
||||
flags |= it->second;
|
||||
}
|
||||
|
||||
shader->Link();
|
||||
|
||||
// On construit l'instant
|
||||
shaderIt = m_cache.emplace(flags, shader.Get()).first;
|
||||
}
|
||||
catch (const std::exception&)
|
||||
|
||||
// Le shader fait-il partie du cache ?
|
||||
auto shaderIt = m_cache.find(flags);
|
||||
|
||||
// Si non, il nous faut le construire
|
||||
if (shaderIt == m_cache.end())
|
||||
{
|
||||
NzErrorFlags errFlags(nzErrorFlag_ThrowExceptionDisabled);
|
||||
try
|
||||
{
|
||||
// Une exception sera lancée à la moindre erreur et celle-ci ne sera pas enregistrée dans le log (car traitée dans le bloc catch)
|
||||
ErrorFlags errFlags(ErrorFlag_Silent | ErrorFlag_ThrowException, true);
|
||||
|
||||
NazaraError("Failed to build UberShader instance: " + NzError::GetLastError());
|
||||
throw;
|
||||
ShaderRef shader = Shader::New();
|
||||
shader->Create();
|
||||
|
||||
for (unsigned int i = 0; i <= ShaderStageType_Max; ++i)
|
||||
{
|
||||
const CachedShader& shaderStage = m_shaders[i];
|
||||
|
||||
// Le shader stage est-il activé dans cette version du shader ?
|
||||
if (shaderStage.present && (flags & shaderStage.requiredFlags) == shaderStage.requiredFlags)
|
||||
{
|
||||
UInt32 stageFlags = 0;
|
||||
for (auto it = shaderStage.flags.begin(); it != shaderStage.flags.end(); ++it)
|
||||
{
|
||||
if (parameters.HasParameter(it->first))
|
||||
{
|
||||
bool value;
|
||||
if (parameters.GetBooleanParameter(it->first, &value) && value)
|
||||
stageFlags |= it->second;
|
||||
}
|
||||
}
|
||||
|
||||
auto stageIt = shaderStage.cache.find(stageFlags);
|
||||
if (stageIt == shaderStage.cache.end())
|
||||
{
|
||||
ShaderStage stage;
|
||||
stage.Create(static_cast<ShaderStageType>(i));
|
||||
|
||||
unsigned int glslVersion = OpenGL::GetGLSLVersion();
|
||||
|
||||
StringStream code;
|
||||
code << "#version " << glslVersion << "\n\n";
|
||||
|
||||
code << "#define GLSL_VERSION " << glslVersion << "\n\n";
|
||||
|
||||
code << "#define EARLY_FRAGMENT_TEST " << (glslVersion >= 420 || OpenGL::IsSupported(OpenGLExtension_Shader_ImageLoadStore)) << "\n\n";
|
||||
|
||||
for (auto it = shaderStage.flags.begin(); it != shaderStage.flags.end(); ++it)
|
||||
code << "#define " << it->first << ' ' << ((stageFlags & it->second) ? '1' : '0') << '\n';
|
||||
|
||||
code << "\n#line 1\n"; // Pour que les éventuelles erreurs du shader se réfèrent à la bonne ligne
|
||||
code << shaderStage.source;
|
||||
|
||||
stage.SetSource(code);
|
||||
stage.Compile();
|
||||
|
||||
stageIt = shaderStage.cache.emplace(flags, std::move(stage)).first;
|
||||
}
|
||||
|
||||
shader->AttachStage(static_cast<ShaderStageType>(i), stageIt->second);
|
||||
}
|
||||
}
|
||||
|
||||
shader->Link();
|
||||
|
||||
// On construit l'instant
|
||||
shaderIt = m_cache.emplace(flags, shader.Get()).first;
|
||||
}
|
||||
catch (const std::exception&)
|
||||
{
|
||||
ErrorFlags errFlags(ErrorFlag_ThrowExceptionDisabled);
|
||||
|
||||
NazaraError("Failed to build UberShader instance: " + Error::GetLastError());
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
return &shaderIt->second;
|
||||
}
|
||||
|
||||
return &shaderIt->second;
|
||||
}
|
||||
|
||||
void NzUberShaderPreprocessor::SetShader(nzShaderStage stage, const NzString& source, const NzString& shaderFlags, const NzString& requiredFlags)
|
||||
{
|
||||
Shader& shader = m_shaders[stage];
|
||||
shader.present = true;
|
||||
shader.source = source;
|
||||
|
||||
// On extrait les flags de la chaîne
|
||||
std::vector<NzString> flags;
|
||||
shaderFlags.Split(flags, ' ');
|
||||
|
||||
for (NzString& flag : flags)
|
||||
void UberShaderPreprocessor::SetShader(ShaderStageType stage, const String& source, const String& shaderFlags, const String& requiredFlags)
|
||||
{
|
||||
auto it = m_flags.find(flag);
|
||||
if (it == m_flags.end())
|
||||
m_flags[flag] = 1U << m_flags.size();
|
||||
CachedShader& shader = m_shaders[stage];
|
||||
shader.present = true;
|
||||
shader.source = source;
|
||||
|
||||
auto it2 = shader.flags.find(flag);
|
||||
if (it2 == shader.flags.end())
|
||||
shader.flags[flag] = 1U << shader.flags.size();
|
||||
}
|
||||
// On extrait les flags de la chaîne
|
||||
std::vector<String> flags;
|
||||
shaderFlags.Split(flags, ' ');
|
||||
|
||||
// On construit les flags requis pour l'activation du shader
|
||||
shader.requiredFlags = 0;
|
||||
|
||||
flags.clear();
|
||||
requiredFlags.Split(flags, ' ');
|
||||
|
||||
for (NzString& flag : flags)
|
||||
{
|
||||
nzUInt32 flagVal;
|
||||
|
||||
auto it = m_flags.find(flag);
|
||||
if (it == m_flags.end())
|
||||
for (String& flag : flags)
|
||||
{
|
||||
flagVal = 1U << m_flags.size();
|
||||
m_flags[flag] = flagVal;
|
||||
auto it = m_flags.find(flag);
|
||||
if (it == m_flags.end())
|
||||
m_flags[flag] = 1U << m_flags.size();
|
||||
|
||||
auto it2 = shader.flags.find(flag);
|
||||
if (it2 == shader.flags.end())
|
||||
shader.flags[flag] = 1U << shader.flags.size();
|
||||
}
|
||||
else
|
||||
flagVal = it->second;
|
||||
|
||||
shader.requiredFlags |= flagVal;
|
||||
// On construit les flags requis pour l'activation du shader
|
||||
shader.requiredFlags = 0;
|
||||
|
||||
flags.clear();
|
||||
requiredFlags.Split(flags, ' ');
|
||||
|
||||
for (String& flag : flags)
|
||||
{
|
||||
UInt32 flagVal;
|
||||
|
||||
auto it = m_flags.find(flag);
|
||||
if (it == m_flags.end())
|
||||
{
|
||||
flagVal = 1U << m_flags.size();
|
||||
m_flags[flag] = flagVal;
|
||||
}
|
||||
else
|
||||
flagVal = it->second;
|
||||
|
||||
shader.requiredFlags |= flagVal;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool NzUberShaderPreprocessor::SetShaderFromFile(nzShaderStage stage, const NzString& filePath, const NzString& shaderFlags, const NzString& requiredFlags)
|
||||
{
|
||||
NzFile file(filePath);
|
||||
if (!file.Open(nzOpenMode_ReadOnly | nzOpenMode_Text))
|
||||
bool UberShaderPreprocessor::SetShaderFromFile(ShaderStageType stage, const String& filePath, const String& shaderFlags, const String& requiredFlags)
|
||||
{
|
||||
NazaraError("Failed to open \"" + filePath + '"');
|
||||
return false;
|
||||
File file(filePath);
|
||||
if (!file.Open(OpenMode_ReadOnly | OpenMode_Text))
|
||||
{
|
||||
NazaraError("Failed to open \"" + filePath + '"');
|
||||
return false;
|
||||
}
|
||||
|
||||
unsigned int length = static_cast<unsigned int>(file.GetSize());
|
||||
|
||||
String source(length, '\0');
|
||||
|
||||
if (file.Read(&source[0], length) != length)
|
||||
{
|
||||
NazaraError("Failed to read program file");
|
||||
return false;
|
||||
}
|
||||
|
||||
file.Close();
|
||||
|
||||
SetShader(stage, source, shaderFlags, requiredFlags);
|
||||
return true;
|
||||
}
|
||||
|
||||
unsigned int length = static_cast<unsigned int>(file.GetSize());
|
||||
|
||||
NzString source(length, '\0');
|
||||
|
||||
if (file.Read(&source[0], length) != length)
|
||||
bool UberShaderPreprocessor::IsSupported()
|
||||
{
|
||||
NazaraError("Failed to read program file");
|
||||
return false;
|
||||
return true; // Forcément supporté
|
||||
}
|
||||
|
||||
file.Close();
|
||||
|
||||
SetShader(stage, source, shaderFlags, requiredFlags);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool NzUberShaderPreprocessor::IsSupported()
|
||||
{
|
||||
return true; // Forcément supporté
|
||||
}
|
||||
|
||||
@@ -14,232 +14,235 @@
|
||||
#include <cstring>
|
||||
#include <Nazara/Renderer/Debug.hpp>
|
||||
|
||||
NzContextImpl::NzContextImpl()
|
||||
namespace Nz
|
||||
{
|
||||
}
|
||||
|
||||
bool NzContextImpl::Activate()
|
||||
{
|
||||
return wglMakeCurrent(m_deviceContext, m_context) == TRUE;
|
||||
}
|
||||
|
||||
bool NzContextImpl::Create(NzContextParameters& parameters)
|
||||
{
|
||||
if (parameters.window)
|
||||
ContextImpl::ContextImpl()
|
||||
{
|
||||
m_window = static_cast<HWND>(parameters.window);
|
||||
m_ownsWindow = false;
|
||||
}
|
||||
else
|
||||
|
||||
bool ContextImpl::Activate()
|
||||
{
|
||||
m_window = CreateWindowA("STATIC", nullptr, WS_DISABLED | WS_POPUP, 0, 0, 1, 1, nullptr, nullptr, GetModuleHandle(nullptr), nullptr);
|
||||
if (!m_window)
|
||||
return wglMakeCurrent(m_deviceContext, m_context) == TRUE;
|
||||
}
|
||||
|
||||
bool ContextImpl::Create(ContextParameters& parameters)
|
||||
{
|
||||
if (parameters.window)
|
||||
{
|
||||
NazaraError("Failed to create window");
|
||||
return false;
|
||||
}
|
||||
|
||||
ShowWindow(m_window, SW_HIDE);
|
||||
m_ownsWindow = true;
|
||||
}
|
||||
|
||||
// En cas d'exception, la ressource sera quand même libérée
|
||||
NzCallOnExit onExit([this] ()
|
||||
{
|
||||
Destroy();
|
||||
});
|
||||
|
||||
m_deviceContext = GetDC(m_window);
|
||||
if (!m_deviceContext)
|
||||
{
|
||||
NazaraError("Failed to get device context");
|
||||
return false;
|
||||
}
|
||||
|
||||
int pixelFormat = 0;
|
||||
if (parameters.antialiasingLevel > 0)
|
||||
{
|
||||
if (wglChoosePixelFormat)
|
||||
{
|
||||
bool valid;
|
||||
UINT numFormats;
|
||||
|
||||
int attributes[] = {
|
||||
WGL_DRAW_TO_WINDOW_ARB, GL_TRUE,
|
||||
WGL_SUPPORT_OPENGL_ARB, GL_TRUE,
|
||||
WGL_ACCELERATION_ARB, WGL_FULL_ACCELERATION_ARB,
|
||||
WGL_COLOR_BITS_ARB, (parameters.bitsPerPixel == 32) ? 24 : parameters.bitsPerPixel,
|
||||
WGL_ALPHA_BITS_ARB, (parameters.bitsPerPixel == 32) ? 8 : 0,
|
||||
WGL_DEPTH_BITS_ARB, parameters.depthBits,
|
||||
WGL_STENCIL_BITS_ARB, parameters.stencilBits,
|
||||
WGL_DOUBLE_BUFFER_ARB, (parameters.doubleBuffered) ? GL_TRUE : GL_FALSE,
|
||||
WGL_SAMPLE_BUFFERS_ARB, GL_TRUE,
|
||||
WGL_SAMPLES_ARB, parameters.antialiasingLevel,
|
||||
0, 0
|
||||
};
|
||||
|
||||
do
|
||||
{
|
||||
valid = (wglChoosePixelFormat(m_deviceContext, attributes, nullptr, 1, &pixelFormat, &numFormats) == TRUE);
|
||||
}
|
||||
while ((!valid || numFormats == 0) && --attributes[19] > 0);
|
||||
|
||||
if (!valid)
|
||||
{
|
||||
NazaraWarning("Could not find a format matching requirements, disabling antialiasing...");
|
||||
pixelFormat = 0;
|
||||
}
|
||||
|
||||
parameters.antialiasingLevel = attributes[19];
|
||||
m_window = static_cast<HWND>(parameters.window);
|
||||
m_ownsWindow = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
NazaraWarning("Antialiasing is not supported");
|
||||
parameters.antialiasingLevel = 0;
|
||||
m_window = CreateWindowA("STATIC", nullptr, WS_DISABLED | WS_POPUP, 0, 0, 1, 1, nullptr, nullptr, GetModuleHandle(nullptr), nullptr);
|
||||
if (!m_window)
|
||||
{
|
||||
NazaraError("Failed to create window");
|
||||
return false;
|
||||
}
|
||||
|
||||
ShowWindow(m_window, SW_HIDE);
|
||||
m_ownsWindow = true;
|
||||
}
|
||||
}
|
||||
|
||||
PIXELFORMATDESCRIPTOR descriptor;
|
||||
ZeroMemory(&descriptor, sizeof(PIXELFORMATDESCRIPTOR));
|
||||
descriptor.nSize = sizeof(PIXELFORMATDESCRIPTOR);
|
||||
descriptor.nVersion = 1;
|
||||
|
||||
if (pixelFormat == 0)
|
||||
{
|
||||
descriptor.cColorBits = parameters.bitsPerPixel;
|
||||
descriptor.cDepthBits = parameters.depthBits;
|
||||
descriptor.cStencilBits = parameters.stencilBits;
|
||||
descriptor.dwFlags = PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL;
|
||||
descriptor.iPixelType = PFD_TYPE_RGBA;
|
||||
|
||||
if (parameters.bitsPerPixel == 32)
|
||||
descriptor.cAlphaBits = 8;
|
||||
|
||||
if (parameters.doubleBuffered)
|
||||
descriptor.dwFlags |= PFD_DOUBLEBUFFER;
|
||||
|
||||
pixelFormat = ChoosePixelFormat(m_deviceContext, &descriptor);
|
||||
if (pixelFormat == 0)
|
||||
// En cas d'exception, la ressource sera quand même libérée
|
||||
CallOnExit onExit([this] ()
|
||||
{
|
||||
NazaraError("Failed to choose pixel format");
|
||||
Destroy();
|
||||
});
|
||||
|
||||
m_deviceContext = GetDC(m_window);
|
||||
if (!m_deviceContext)
|
||||
{
|
||||
NazaraError("Failed to get device context");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (!SetPixelFormat(m_deviceContext, pixelFormat, &descriptor))
|
||||
{
|
||||
NazaraError("Failed to set pixel format");
|
||||
return false;
|
||||
}
|
||||
|
||||
// Arrivé ici, le format de pixel est choisi, nous récupérons donc les paramètres réels du futur contexte
|
||||
if (DescribePixelFormat(m_deviceContext, pixelFormat, sizeof(PIXELFORMATDESCRIPTOR), &descriptor) != 0)
|
||||
{
|
||||
parameters.bitsPerPixel = descriptor.cColorBits + descriptor.cAlphaBits;
|
||||
parameters.depthBits = descriptor.cDepthBits;
|
||||
parameters.stencilBits = descriptor.cDepthBits;
|
||||
}
|
||||
else
|
||||
NazaraWarning("Failed to get context's parameters");
|
||||
|
||||
HGLRC shareContext = (parameters.shared) ? static_cast<NzContextImpl*>(parameters.shareContext->m_impl)->m_context : nullptr;
|
||||
|
||||
m_context = nullptr;
|
||||
if (wglCreateContextAttribs)
|
||||
{
|
||||
int attributes[4*2+1];
|
||||
int* attrib = attributes;
|
||||
|
||||
*attrib++ = WGL_CONTEXT_MAJOR_VERSION_ARB;
|
||||
*attrib++ = parameters.majorVersion;
|
||||
|
||||
*attrib++ = WGL_CONTEXT_MINOR_VERSION_ARB;
|
||||
*attrib++ = parameters.minorVersion;
|
||||
|
||||
if (parameters.majorVersion >= 3)
|
||||
int pixelFormat = 0;
|
||||
if (parameters.antialiasingLevel > 0)
|
||||
{
|
||||
*attrib++ = WGL_CONTEXT_PROFILE_MASK_ARB;
|
||||
*attrib++ = (parameters.compatibilityProfile) ? WGL_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB : WGL_CONTEXT_CORE_PROFILE_BIT_ARB;
|
||||
if (wglChoosePixelFormat)
|
||||
{
|
||||
bool valid;
|
||||
UINT numFormats;
|
||||
|
||||
// Les contextes forward-compatible ne sont plus utilisés pour cette raison :
|
||||
// http://www.opengl.org/discussion_boards/showthread.php/175052-Forward-compatible-vs-Core-profile
|
||||
int attributes[] = {
|
||||
WGL_DRAW_TO_WINDOW_ARB, GL_TRUE,
|
||||
WGL_SUPPORT_OPENGL_ARB, GL_TRUE,
|
||||
WGL_ACCELERATION_ARB, WGL_FULL_ACCELERATION_ARB,
|
||||
WGL_COLOR_BITS_ARB, (parameters.bitsPerPixel == 32) ? 24 : parameters.bitsPerPixel,
|
||||
WGL_ALPHA_BITS_ARB, (parameters.bitsPerPixel == 32) ? 8 : 0,
|
||||
WGL_DEPTH_BITS_ARB, parameters.depthBits,
|
||||
WGL_STENCIL_BITS_ARB, parameters.stencilBits,
|
||||
WGL_DOUBLE_BUFFER_ARB, (parameters.doubleBuffered) ? GL_TRUE : GL_FALSE,
|
||||
WGL_SAMPLE_BUFFERS_ARB, GL_TRUE,
|
||||
WGL_SAMPLES_ARB, parameters.antialiasingLevel,
|
||||
0, 0
|
||||
};
|
||||
|
||||
do
|
||||
{
|
||||
valid = (wglChoosePixelFormat(m_deviceContext, attributes, nullptr, 1, &pixelFormat, &numFormats) == TRUE);
|
||||
}
|
||||
while ((!valid || numFormats == 0) && --attributes[19] > 0);
|
||||
|
||||
if (!valid)
|
||||
{
|
||||
NazaraWarning("Could not find a format matching requirements, disabling antialiasing...");
|
||||
pixelFormat = 0;
|
||||
}
|
||||
|
||||
parameters.antialiasingLevel = attributes[19];
|
||||
}
|
||||
else
|
||||
{
|
||||
NazaraWarning("Antialiasing is not supported");
|
||||
parameters.antialiasingLevel = 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (parameters.debugMode)
|
||||
PIXELFORMATDESCRIPTOR descriptor;
|
||||
ZeroMemory(&descriptor, sizeof(PIXELFORMATDESCRIPTOR));
|
||||
descriptor.nSize = sizeof(PIXELFORMATDESCRIPTOR);
|
||||
descriptor.nVersion = 1;
|
||||
|
||||
if (pixelFormat == 0)
|
||||
{
|
||||
*attrib++ = WGL_CONTEXT_FLAGS_ARB;
|
||||
*attrib++ = WGL_CONTEXT_DEBUG_BIT_ARB;
|
||||
descriptor.cColorBits = parameters.bitsPerPixel;
|
||||
descriptor.cDepthBits = parameters.depthBits;
|
||||
descriptor.cStencilBits = parameters.stencilBits;
|
||||
descriptor.dwFlags = PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL;
|
||||
descriptor.iPixelType = PFD_TYPE_RGBA;
|
||||
|
||||
if (parameters.bitsPerPixel == 32)
|
||||
descriptor.cAlphaBits = 8;
|
||||
|
||||
if (parameters.doubleBuffered)
|
||||
descriptor.dwFlags |= PFD_DOUBLEBUFFER;
|
||||
|
||||
pixelFormat = ChoosePixelFormat(m_deviceContext, &descriptor);
|
||||
if (pixelFormat == 0)
|
||||
{
|
||||
NazaraError("Failed to choose pixel format");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
*attrib++ = 0;
|
||||
|
||||
m_context = wglCreateContextAttribs(m_deviceContext, shareContext, attributes);
|
||||
}
|
||||
|
||||
if (!m_context)
|
||||
{
|
||||
m_context = wglCreateContext(m_deviceContext);
|
||||
|
||||
if (shareContext)
|
||||
if (!SetPixelFormat(m_deviceContext, pixelFormat, &descriptor))
|
||||
{
|
||||
// wglShareLists n'est pas thread-safe (source: SFML)
|
||||
static NzMutex mutex;
|
||||
NzLockGuard lock(mutex);
|
||||
|
||||
if (!wglShareLists(shareContext, m_context))
|
||||
NazaraWarning("Failed to share the context: " + NzError::GetLastSystemError());
|
||||
NazaraError("Failed to set pixel format");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (!m_context)
|
||||
{
|
||||
NazaraError("Failed to create context");
|
||||
return false;
|
||||
}
|
||||
// Arrivé ici, le format de pixel est choisi, nous récupérons donc les paramètres réels du futur contexte
|
||||
if (DescribePixelFormat(m_deviceContext, pixelFormat, sizeof(PIXELFORMATDESCRIPTOR), &descriptor) != 0)
|
||||
{
|
||||
parameters.bitsPerPixel = descriptor.cColorBits + descriptor.cAlphaBits;
|
||||
parameters.depthBits = descriptor.cDepthBits;
|
||||
parameters.stencilBits = descriptor.cDepthBits;
|
||||
}
|
||||
else
|
||||
NazaraWarning("Failed to get context's parameters");
|
||||
|
||||
onExit.Reset();
|
||||
HGLRC shareContext = (parameters.shared) ? static_cast<ContextImpl*>(parameters.shareContext->m_impl)->m_context : nullptr;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void NzContextImpl::Destroy()
|
||||
{
|
||||
if (m_context)
|
||||
{
|
||||
if (wglGetCurrentContext() == m_context)
|
||||
wglMakeCurrent(nullptr, nullptr);
|
||||
|
||||
wglDeleteContext(m_context);
|
||||
m_context = nullptr;
|
||||
if (wglCreateContextAttribs)
|
||||
{
|
||||
int attributes[4*2+1];
|
||||
int* attrib = attributes;
|
||||
|
||||
*attrib++ = WGL_CONTEXT_MAJOR_VERSION_ARB;
|
||||
*attrib++ = parameters.majorVersion;
|
||||
|
||||
*attrib++ = WGL_CONTEXT_MINOR_VERSION_ARB;
|
||||
*attrib++ = parameters.minorVersion;
|
||||
|
||||
if (parameters.majorVersion >= 3)
|
||||
{
|
||||
*attrib++ = WGL_CONTEXT_PROFILE_MASK_ARB;
|
||||
*attrib++ = (parameters.compatibilityProfile) ? WGL_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB : WGL_CONTEXT_CORE_PROFILE_BIT_ARB;
|
||||
|
||||
// Les contextes forward-compatible ne sont plus utilisés pour cette raison :
|
||||
// http://www.opengl.org/discussion_boards/showthread.php/175052-Forward-compatible-vs-Core-profile
|
||||
}
|
||||
|
||||
if (parameters.debugMode)
|
||||
{
|
||||
*attrib++ = WGL_CONTEXT_FLAGS_ARB;
|
||||
*attrib++ = WGL_CONTEXT_DEBUG_BIT_ARB;
|
||||
}
|
||||
|
||||
*attrib++ = 0;
|
||||
|
||||
m_context = wglCreateContextAttribs(m_deviceContext, shareContext, attributes);
|
||||
}
|
||||
|
||||
if (!m_context)
|
||||
{
|
||||
m_context = wglCreateContext(m_deviceContext);
|
||||
|
||||
if (shareContext)
|
||||
{
|
||||
// wglShareLists n'est pas thread-safe (source: SFML)
|
||||
static Mutex mutex;
|
||||
LockGuard lock(mutex);
|
||||
|
||||
if (!wglShareLists(shareContext, m_context))
|
||||
NazaraWarning("Failed to share the context: " + Error::GetLastSystemError());
|
||||
}
|
||||
}
|
||||
|
||||
if (!m_context)
|
||||
{
|
||||
NazaraError("Failed to create context");
|
||||
return false;
|
||||
}
|
||||
|
||||
onExit.Reset();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
if (m_deviceContext)
|
||||
void ContextImpl::Destroy()
|
||||
{
|
||||
ReleaseDC(m_window, m_deviceContext);
|
||||
m_deviceContext = nullptr;
|
||||
if (m_context)
|
||||
{
|
||||
if (wglGetCurrentContext() == m_context)
|
||||
wglMakeCurrent(nullptr, nullptr);
|
||||
|
||||
wglDeleteContext(m_context);
|
||||
m_context = nullptr;
|
||||
}
|
||||
|
||||
if (m_deviceContext)
|
||||
{
|
||||
ReleaseDC(m_window, m_deviceContext);
|
||||
m_deviceContext = nullptr;
|
||||
}
|
||||
|
||||
if (m_ownsWindow)
|
||||
{
|
||||
DestroyWindow(m_window);
|
||||
m_window = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
if (m_ownsWindow)
|
||||
void ContextImpl::EnableVerticalSync(bool enabled)
|
||||
{
|
||||
DestroyWindow(m_window);
|
||||
m_window = nullptr;
|
||||
if (wglSwapInterval)
|
||||
wglSwapInterval(enabled ? 1 : 0);
|
||||
else
|
||||
NazaraError("Vertical sync not supported");
|
||||
}
|
||||
|
||||
void ContextImpl::SwapBuffers()
|
||||
{
|
||||
::SwapBuffers(m_deviceContext);
|
||||
}
|
||||
|
||||
bool ContextImpl::Desactivate()
|
||||
{
|
||||
return wglMakeCurrent(nullptr, nullptr) == TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
void NzContextImpl::EnableVerticalSync(bool enabled)
|
||||
{
|
||||
if (wglSwapInterval)
|
||||
wglSwapInterval(enabled ? 1 : 0);
|
||||
else
|
||||
NazaraError("Vertical sync not supported");
|
||||
}
|
||||
|
||||
void NzContextImpl::SwapBuffers()
|
||||
{
|
||||
::SwapBuffers(m_deviceContext);
|
||||
}
|
||||
|
||||
bool NzContextImpl::Desactivate()
|
||||
{
|
||||
return wglMakeCurrent(nullptr, nullptr) == TRUE;
|
||||
}
|
||||
|
||||
@@ -11,28 +11,31 @@
|
||||
#include <Nazara/Renderer/ContextParameters.hpp>
|
||||
#include <windows.h>
|
||||
|
||||
class NzContextImpl
|
||||
namespace Nz
|
||||
{
|
||||
public:
|
||||
NzContextImpl();
|
||||
class ContextImpl
|
||||
{
|
||||
public:
|
||||
ContextImpl();
|
||||
|
||||
bool Activate();
|
||||
bool Activate();
|
||||
|
||||
bool Create(NzContextParameters& parameters);
|
||||
bool Create(ContextParameters& parameters);
|
||||
|
||||
void Destroy();
|
||||
void Destroy();
|
||||
|
||||
void EnableVerticalSync(bool enabled);
|
||||
void EnableVerticalSync(bool enabled);
|
||||
|
||||
void SwapBuffers();
|
||||
void SwapBuffers();
|
||||
|
||||
static bool Desactivate();
|
||||
static bool Desactivate();
|
||||
|
||||
private:
|
||||
HDC m_deviceContext;
|
||||
HGLRC m_context;
|
||||
HWND m_window;
|
||||
bool m_ownsWindow;
|
||||
};
|
||||
private:
|
||||
HDC m_deviceContext;
|
||||
HGLRC m_context;
|
||||
HWND m_window;
|
||||
bool m_ownsWindow;
|
||||
};
|
||||
}
|
||||
|
||||
#endif // NAZARA_CONTEXTIMPL_HPP
|
||||
|
||||
Reference in New Issue
Block a user