First commit
This commit is contained in:
196
src/Nazara/Renderer/Buffer.cpp
Normal file
196
src/Nazara/Renderer/Buffer.cpp
Normal file
@@ -0,0 +1,196 @@
|
||||
// Copyright (C) 2012 Jérôme Leclercq
|
||||
// This file is part of the "Nazara Engine".
|
||||
// For conditions of distribution and use, see copyright notice in Config.hpp
|
||||
|
||||
#include <Nazara/Renderer/OpenGL.hpp>
|
||||
#include <Nazara/Renderer/Buffer.hpp>
|
||||
#include <Nazara/Core/Error.hpp>
|
||||
#include <Nazara/Renderer/HardwareBuffer.hpp>
|
||||
#include <Nazara/Renderer/Renderer.hpp>
|
||||
#include <Nazara/Renderer/SoftwareBuffer.hpp>
|
||||
#include <stdexcept>
|
||||
#include <Nazara/Renderer/Debug.hpp>
|
||||
|
||||
NzBuffer::NzBuffer(nzBufferType type) :
|
||||
m_type(type),
|
||||
m_typeSize(0),
|
||||
m_impl(nullptr),
|
||||
m_length(0)
|
||||
{
|
||||
}
|
||||
|
||||
NzBuffer::NzBuffer(nzBufferType type, unsigned int length, nzUInt8 typeSize, nzBufferUsage usage) :
|
||||
m_type(type),
|
||||
m_impl(nullptr)
|
||||
{
|
||||
Create(length, typeSize, usage);
|
||||
|
||||
#if NAZARA_DEBUG
|
||||
if (!m_impl)
|
||||
{
|
||||
NazaraError("Failed to create buffer");
|
||||
throw std::runtime_error("Constructor failed");
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
NzBuffer::~NzBuffer()
|
||||
{
|
||||
Destroy();
|
||||
}
|
||||
|
||||
bool NzBuffer::CopyContent(NzBuffer& buffer)
|
||||
{
|
||||
void* ptr = buffer.Lock(nzBufferLock_ReadOnly);
|
||||
if (!ptr)
|
||||
{
|
||||
NazaraError("Unable to lock buffer");
|
||||
return false;
|
||||
}
|
||||
|
||||
bool r = Fill(ptr, 0, m_length);
|
||||
|
||||
if (!buffer.Unlock())
|
||||
NazaraWarning("Unable to unlock buffer");
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
bool NzBuffer::Create(unsigned int length, nzUInt8 typeSize, nzBufferUsage usage)
|
||||
{
|
||||
Destroy();
|
||||
|
||||
// On tente d'abord de faire un buffer hardware, si supporté
|
||||
if (NazaraRenderer->HasCapability(nzRendererCap_HardwareBuffer))
|
||||
{
|
||||
m_impl = new NzHardwareBuffer(this, m_type);
|
||||
if (!m_impl->Create(length, typeSize, usage))
|
||||
{
|
||||
NazaraWarning("Failed to create hardware buffer, trying to create software buffer...");
|
||||
|
||||
delete m_impl;
|
||||
m_impl = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
if (!m_impl)
|
||||
{
|
||||
m_impl = new NzSoftwareBuffer(this, m_type);
|
||||
if (!m_impl->Create(length, typeSize, usage))
|
||||
{
|
||||
NazaraError("Failed to create software buffer");
|
||||
delete m_impl;
|
||||
m_impl = nullptr;
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
m_length = length;
|
||||
m_typeSize = typeSize;
|
||||
m_usage = usage;
|
||||
|
||||
// Si on arrive ici c'est que tout s'est bien passé.
|
||||
return true;
|
||||
}
|
||||
|
||||
void NzBuffer::Destroy()
|
||||
{
|
||||
if (m_impl)
|
||||
{
|
||||
m_impl->Destroy();
|
||||
delete m_impl;
|
||||
m_impl = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
bool NzBuffer::Fill(const void* data, unsigned int offset, unsigned int length)
|
||||
{
|
||||
#if NAZARA_RENDERER_SAFE
|
||||
if (!m_impl)
|
||||
{
|
||||
NazaraError("Buffer not created");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (offset+length > m_length)
|
||||
{
|
||||
NazaraError("Exceeding buffer size");
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
|
||||
return m_impl->Fill(data, offset, length);
|
||||
}
|
||||
|
||||
unsigned int NzBuffer::GetLength() const
|
||||
{
|
||||
return m_length;
|
||||
}
|
||||
|
||||
unsigned int NzBuffer::GetSize() const
|
||||
{
|
||||
return m_length*m_typeSize;
|
||||
}
|
||||
|
||||
nzBufferStorage NzBuffer::GetStorage() const
|
||||
{
|
||||
return m_storage;
|
||||
}
|
||||
|
||||
nzBufferType NzBuffer::GetType() const
|
||||
{
|
||||
return m_type;
|
||||
}
|
||||
|
||||
nzUInt8 NzBuffer::GetTypeSize() const
|
||||
{
|
||||
return m_typeSize;
|
||||
}
|
||||
|
||||
nzBufferUsage NzBuffer::GetUsage() const
|
||||
{
|
||||
return m_usage;
|
||||
}
|
||||
|
||||
bool NzBuffer::IsHardware() const
|
||||
{
|
||||
return m_storage == nzBufferStorage_Hardware;
|
||||
}
|
||||
|
||||
void* NzBuffer::Lock(nzBufferLock lock, unsigned int offset, unsigned int length)
|
||||
{
|
||||
#if NAZARA_RENDERER_SAFE
|
||||
if (!m_impl)
|
||||
{
|
||||
NazaraError("Buffer not created");
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
if (offset+length > m_length)
|
||||
{
|
||||
NazaraError("Exceeding buffer size");
|
||||
return nullptr;
|
||||
}
|
||||
#endif
|
||||
|
||||
return m_impl->Lock(lock, offset, length);
|
||||
}
|
||||
|
||||
bool NzBuffer::Unlock()
|
||||
{
|
||||
#if NAZARA_RENDERER_SAFE
|
||||
if (!m_impl)
|
||||
{
|
||||
NazaraError("Buffer not created");
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
|
||||
return m_impl->Unlock();
|
||||
}
|
||||
|
||||
bool NzBuffer::IsHardwareSupported()
|
||||
{
|
||||
return NazaraRenderer->HasCapability(nzRendererCap_HardwareBuffer);
|
||||
}
|
||||
7
src/Nazara/Renderer/BufferImpl.cpp
Normal file
7
src/Nazara/Renderer/BufferImpl.cpp
Normal file
@@ -0,0 +1,7 @@
|
||||
// Copyright (C) 2012 Jérôme Leclercq
|
||||
// This file is part of the "Nazara Engine".
|
||||
// For conditions of distribution and use, see copyright notice in Config.hpp
|
||||
|
||||
#include <Nazara/Renderer/BufferImpl.hpp>
|
||||
|
||||
NzBufferImpl::~NzBufferImpl() = default;
|
||||
31
src/Nazara/Renderer/BufferImpl.hpp
Normal file
31
src/Nazara/Renderer/BufferImpl.hpp
Normal file
@@ -0,0 +1,31 @@
|
||||
// Copyright (C) 2012 Jérôme Leclercq
|
||||
// This file is part of the "Nazara Engine".
|
||||
// For conditions of distribution and use, see copyright notice in Config.hpp
|
||||
|
||||
#pragma once
|
||||
|
||||
#ifndef NAZARA_BUFFERIMPL_HPP
|
||||
#define NAZARA_BUFFERIMPL_HPP
|
||||
|
||||
#include <Nazara/Renderer/Buffer.hpp>
|
||||
|
||||
class NzBufferImpl
|
||||
{
|
||||
public:
|
||||
NzBufferImpl() = default;
|
||||
virtual ~NzBufferImpl();
|
||||
|
||||
virtual void Bind() = 0;
|
||||
|
||||
virtual bool Create(unsigned int length, nzUInt8 typeSize, nzBufferUsage usage = nzBufferUsage_Static) = 0;
|
||||
virtual void Destroy() = 0;
|
||||
|
||||
virtual bool Fill(const void* data, unsigned int offset, unsigned int length) = 0;
|
||||
|
||||
virtual bool IsHardware() const = 0;
|
||||
|
||||
virtual void* Lock(nzBufferLock lock, unsigned int offset = 0, unsigned int length = 0) = 0;
|
||||
virtual bool Unlock() = 0;
|
||||
};
|
||||
|
||||
#endif // NAZARA_BUFFERIMPL_INCLUDED
|
||||
167
src/Nazara/Renderer/Context.cpp
Normal file
167
src/Nazara/Renderer/Context.cpp
Normal file
@@ -0,0 +1,167 @@
|
||||
// Copyright (C) 2012 Jérôme Leclercq
|
||||
// This file is part of the "Nazara Engine".
|
||||
// For conditions of distribution and use, see copyright notice in Config.hpp
|
||||
|
||||
#include <Nazara/Renderer/OpenGL.hpp>
|
||||
#include <Nazara/Renderer/Context.hpp>
|
||||
#include <Nazara/Core/Error.hpp>
|
||||
#include <Nazara/Renderer/Config.hpp>
|
||||
|
||||
#if defined(NAZARA_PLATFORM_WINDOWS)
|
||||
#include <Nazara/Renderer/Win32/ContextImpl.hpp>
|
||||
#elif defined(NAZARA_PLATFORM_LINUX)
|
||||
#include <Nazara/Renderer/Linux/ContextImpl.hpp>
|
||||
#else
|
||||
#error Lack of implementation: Context
|
||||
#endif
|
||||
|
||||
#include <Nazara/Renderer/Debug.hpp>
|
||||
|
||||
namespace
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
NzContext::NzContext() :
|
||||
m_impl(nullptr)
|
||||
{
|
||||
}
|
||||
|
||||
NzContext::~NzContext()
|
||||
{
|
||||
if (m_impl)
|
||||
{
|
||||
if (m_impl->IsActive())
|
||||
NzContextImpl::Desactivate();
|
||||
|
||||
m_impl->Destroy();
|
||||
delete m_impl;
|
||||
}
|
||||
}
|
||||
|
||||
bool NzContext::Create(const NzContextParameters& parameters)
|
||||
{
|
||||
m_parameters = parameters;
|
||||
if (m_parameters.shared && !m_parameters.shareContext)
|
||||
m_parameters.shareContext = s_reference;
|
||||
|
||||
m_impl = new NzContextImpl;
|
||||
if (!m_impl->Create(m_parameters))
|
||||
{
|
||||
NazaraError("Failed to create context implementation");
|
||||
delete m_impl;
|
||||
m_impl = nullptr;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!m_impl->Activate())
|
||||
{
|
||||
NazaraError("Failed to activate context");
|
||||
|
||||
m_impl->Destroy();
|
||||
delete m_impl;
|
||||
m_impl = nullptr;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
if (m_parameters.antialiasingLevel > 0)
|
||||
glEnable(GL_MULTISAMPLE);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
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 m_impl->IsActive();
|
||||
}
|
||||
|
||||
bool NzContext::SetActive(bool active)
|
||||
{
|
||||
#ifdef NAZARA_RENDERER_SAFE
|
||||
if (!m_impl)
|
||||
{
|
||||
NazaraError("No context has been created");
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (active)
|
||||
{
|
||||
if (!m_impl->IsActive())
|
||||
return m_impl->Activate();
|
||||
}
|
||||
else if (m_impl->IsActive())
|
||||
return NzContextImpl::Desactivate();
|
||||
|
||||
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();
|
||||
}
|
||||
|
||||
const NzContext* NzContext::GetReference()
|
||||
{
|
||||
return s_reference;
|
||||
}
|
||||
|
||||
bool NzContext::InitializeReference()
|
||||
{
|
||||
NzContextParameters parameters;
|
||||
// parameters.compatibilityProfile = true;
|
||||
parameters.shared = false; // Difficile de partager le contexte de référence avec lui-même
|
||||
|
||||
s_reference = new NzContext;
|
||||
if (!s_reference->Create(parameters))
|
||||
{
|
||||
delete s_reference;
|
||||
s_reference = nullptr;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void NzContext::UninitializeReference()
|
||||
{
|
||||
delete s_reference;
|
||||
s_reference = nullptr;
|
||||
}
|
||||
|
||||
NzContext* NzContext::s_reference = nullptr;
|
||||
14
src/Nazara/Renderer/ContextParameters.cpp
Normal file
14
src/Nazara/Renderer/ContextParameters.cpp
Normal file
@@ -0,0 +1,14 @@
|
||||
// Copyright (C) 2012 Jérôme Leclercq
|
||||
// This file is part of the "Nazara Engine".
|
||||
// For conditions of distribution and use, see copyright notice in Config.hpp
|
||||
|
||||
#include <Nazara/Renderer/ContextParameters.hpp>
|
||||
#include <Nazara/Renderer/Debug.hpp>
|
||||
|
||||
nzUInt8 NzContextParameters::defaultMajorVersion; // Initialisé par NzOpenGL
|
||||
nzUInt8 NzContextParameters::defaultMinorVersion; // Initialisé par NzOpenGL
|
||||
const NzContext* NzContextParameters::defaultShareContext = nullptr;
|
||||
NzWindowHandle NzContextParameters::defaultWindow = 0;
|
||||
bool NzContextParameters::defaultCompatibilityProfile = false;
|
||||
bool NzContextParameters::defaultDoubleBuffered = false;
|
||||
bool NzContextParameters::defaultShared = true;
|
||||
29
src/Nazara/Renderer/Debug/Leaks.cpp
Normal file
29
src/Nazara/Renderer/Debug/Leaks.cpp
Normal file
@@ -0,0 +1,29 @@
|
||||
// Copyright (C) 2012 Jérôme Leclercq
|
||||
// This file is part of the "Nazara Engine".
|
||||
// For conditions of distribution and use, see copyright notice in Config.hpp
|
||||
|
||||
#include <Nazara/Renderer/Config.hpp>
|
||||
#if NAZARA_RENDERER_MEMORYLEAKTRACKER || defined(NAZARA_DEBUG)
|
||||
#include <Nazara/Core/Debug/MemoryLeakTracker.hpp>
|
||||
#include <new>
|
||||
|
||||
void* operator new(std::size_t size) throw(std::bad_alloc)
|
||||
{
|
||||
return NzMemoryManager::Allocate(size, false);
|
||||
}
|
||||
|
||||
void* operator new[](std::size_t size) throw(std::bad_alloc)
|
||||
{
|
||||
return NzMemoryManager::Allocate(size, true);
|
||||
}
|
||||
|
||||
void operator delete(void* pointer) throw()
|
||||
{
|
||||
NzMemoryManager::Free(pointer, false);
|
||||
}
|
||||
|
||||
void operator delete[](void* pointer) throw()
|
||||
{
|
||||
NzMemoryManager::Free(pointer, true);
|
||||
}
|
||||
#endif
|
||||
254
src/Nazara/Renderer/GLSLShader.cpp
Normal file
254
src/Nazara/Renderer/GLSLShader.cpp
Normal file
@@ -0,0 +1,254 @@
|
||||
// Copyright (C) 2012 Jérôme Leclercq
|
||||
// This file is part of the "Nazara Engine".
|
||||
// For conditions of distribution and use, see copyright notice in Config.hpp
|
||||
|
||||
#include <Nazara/Renderer/OpenGL.hpp>
|
||||
#include <Nazara/Renderer/GLSLShader.hpp>
|
||||
#include <Nazara/Core/Error.hpp>
|
||||
#include <Nazara/Core/String.hpp>
|
||||
#include <Nazara/Renderer/Debug.hpp>
|
||||
|
||||
namespace
|
||||
{
|
||||
GLenum shaderType[nzShaderType_Count] = {
|
||||
GL_FRAGMENT_SHADER, // nzShaderType_Fragment
|
||||
GL_GEOMETRY_SHADER, // nzShaderType_Geometry
|
||||
GL_VERTEX_SHADER // nzShaderType_Vertex
|
||||
};
|
||||
}
|
||||
|
||||
NzGLSLShader::NzGLSLShader(NzShader* parent) :
|
||||
m_parent(parent)
|
||||
{
|
||||
}
|
||||
|
||||
NzGLSLShader::~NzGLSLShader()
|
||||
{
|
||||
}
|
||||
|
||||
bool NzGLSLShader::Bind()
|
||||
{
|
||||
glUseProgram(m_program);
|
||||
|
||||
return true; ///FIXME: Comment détecter une erreur d'OpenGL sans ralentir le programme ?
|
||||
}
|
||||
|
||||
bool NzGLSLShader::Compile()
|
||||
{
|
||||
m_idCache.clear();
|
||||
|
||||
glLinkProgram(m_program);
|
||||
|
||||
GLint success;
|
||||
glGetProgramiv(m_program, GL_LINK_STATUS, &success);
|
||||
|
||||
if (success == GL_TRUE)
|
||||
{
|
||||
static NzString success("Linkage successful");
|
||||
m_log = success;
|
||||
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
// On remplit le log avec l'erreur de compilation
|
||||
GLint length = 0;
|
||||
glGetProgramiv(m_program, GL_INFO_LOG_LENGTH, &length);
|
||||
if (length > 1)
|
||||
{
|
||||
m_log.Reserve(length+19-1); // La taille retournée est celle du buffer (Avec caractère de fin)
|
||||
m_log.Prepend("Linkage error: ");
|
||||
m_log.Resize(length+19-1); // Extension du buffer d'écriture pour ajouter le log
|
||||
|
||||
glGetProgramInfoLog(m_program, length-1, nullptr, &m_log[19]);
|
||||
}
|
||||
else
|
||||
m_log = "Linkage failed but no info log found";
|
||||
|
||||
NazaraError(m_log);
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
bool NzGLSLShader::Create()
|
||||
{
|
||||
m_program = glCreateProgram();
|
||||
if (!m_program)
|
||||
{
|
||||
NazaraError("Failed to create program");
|
||||
return false;
|
||||
}
|
||||
|
||||
glBindAttribLocation(m_program, 0, "Position");
|
||||
glBindAttribLocation(m_program, 1, "Normal");
|
||||
//glBindAttribLocation(m_program, 2, "Diffuse");
|
||||
glBindAttribLocation(m_program, 3, "Tangent");
|
||||
|
||||
for (unsigned int i = 0; i < 8; ++i)
|
||||
{
|
||||
NzString uniformName = "TexCoord" + NzString::Number(i);
|
||||
glBindAttribLocation(m_program, 4+i, uniformName.GetConstBuffer());
|
||||
}
|
||||
|
||||
for (int i = 0; i < nzShaderType_Count; ++i)
|
||||
m_shaders[i] = 0;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void NzGLSLShader::Destroy()
|
||||
{
|
||||
for (GLuint shader : m_shaders)
|
||||
if (shader)
|
||||
glDeleteShader(shader);
|
||||
|
||||
if (m_program)
|
||||
glDeleteProgram(m_program);
|
||||
}
|
||||
|
||||
NzString NzGLSLShader::GetLog() const
|
||||
{
|
||||
return m_log;
|
||||
}
|
||||
|
||||
nzShaderLanguage NzGLSLShader::GetLanguage() const
|
||||
{
|
||||
return nzShaderLanguage_GLSL;
|
||||
}
|
||||
|
||||
NzString NzGLSLShader::GetSourceCode(nzShaderType type) const
|
||||
{
|
||||
NzString source;
|
||||
|
||||
GLint length;
|
||||
glGetShaderiv(m_shaders[type], GL_SHADER_SOURCE_LENGTH, &length);
|
||||
if (length > 1)
|
||||
{
|
||||
source.Resize(length-1); // La taille retournée est celle du buffer (Avec caractère de fin)
|
||||
glGetShaderSource(m_shaders[type], length, nullptr, &source[0]);
|
||||
}
|
||||
|
||||
return source;
|
||||
}
|
||||
|
||||
GLint NzGLSLShader::GetUniformLocation(const NzString& name) const
|
||||
{
|
||||
std::map<NzString, GLint>::const_iterator it = m_idCache.find(name);
|
||||
GLint id;
|
||||
if (it == m_idCache.end())
|
||||
{
|
||||
id = glGetUniformLocation(m_program, name.GetConstBuffer());
|
||||
m_idCache[name] = id;
|
||||
}
|
||||
else
|
||||
id = it->second;
|
||||
|
||||
return id;
|
||||
}
|
||||
|
||||
bool NzGLSLShader::IsLoaded(nzShaderType type) const
|
||||
{
|
||||
return m_shaders[type] != 0;
|
||||
}
|
||||
|
||||
bool NzGLSLShader::Load(nzShaderType type, const NzString& source)
|
||||
{
|
||||
GLuint shader = glCreateShader(shaderType[type]);
|
||||
if (!shader)
|
||||
{
|
||||
m_log = "Failed to create shader object";
|
||||
NazaraError(m_log);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
const char* tmp = source.GetConstBuffer();
|
||||
GLint length = source.GetSize();
|
||||
glShaderSource(shader, 1, &tmp, &length);
|
||||
|
||||
glCompileShader(shader);
|
||||
|
||||
GLint success;
|
||||
glGetShaderiv(shader, GL_COMPILE_STATUS, &success);
|
||||
|
||||
if (success == GL_TRUE)
|
||||
{
|
||||
glAttachShader(m_program, shader);
|
||||
m_shaders[type] = shader;
|
||||
|
||||
static NzString success("Compilation successful");
|
||||
m_log = success;
|
||||
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
// On remplit le log avec l'erreur de compilation
|
||||
length = 0;
|
||||
glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &length);
|
||||
if (length > 1)
|
||||
{
|
||||
m_log.Reserve(length+19-1); // La taille retournée est celle du buffer (Avec caractère de fin)
|
||||
m_log.Prepend("Compilation error: ");
|
||||
m_log.Resize(length+19-1); // Extension du buffer d'écriture pour ajouter le log
|
||||
|
||||
glGetShaderInfoLog(shader, length-1, nullptr, &m_log[19]);
|
||||
}
|
||||
else
|
||||
m_log = "Compilation failed but no info log found";
|
||||
|
||||
NazaraError(m_log);
|
||||
|
||||
glDeleteShader(shader);
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
bool NzGLSLShader::SendBoolean(const NzString& name, bool value)
|
||||
{
|
||||
glUniform1i(GetUniformLocation(name), value);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool NzGLSLShader::SendDouble(const NzString& name, double value)
|
||||
{
|
||||
glUniform1d(GetUniformLocation(name), value);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool NzGLSLShader::SendFloat(const NzString& name, float value)
|
||||
{
|
||||
glUniform1f(GetUniformLocation(name), value);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool NzGLSLShader::SendInteger(const NzString& name, int value)
|
||||
{
|
||||
glUniform1i(GetUniformLocation(name), value);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool NzGLSLShader::SendMatrix(const NzString& name, const NzMatrix4d& matrix)
|
||||
{
|
||||
glUniformMatrix4dv(GetUniformLocation(name), 1, GL_FALSE, matrix);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool NzGLSLShader::SendMatrix(const NzString& name, const NzMatrix4f& matrix)
|
||||
{
|
||||
glUniformMatrix4fv(GetUniformLocation(name), 1, GL_FALSE, matrix);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void NzGLSLShader::Unbind()
|
||||
{
|
||||
glUseProgram(0);
|
||||
}
|
||||
55
src/Nazara/Renderer/GLSLShader.hpp
Normal file
55
src/Nazara/Renderer/GLSLShader.hpp
Normal file
@@ -0,0 +1,55 @@
|
||||
// Copyright (C) 2012 Jérôme Leclercq
|
||||
// This file is part of the "Nazara Engine".
|
||||
// For conditions of distribution and use, see copyright notice in Config.hpp
|
||||
|
||||
#pragma once
|
||||
|
||||
#ifndef NAZARA_GLSLSHADER_HPP
|
||||
#define NAZARA_GLSLSHADER_HPP
|
||||
|
||||
#include <Nazara/Core/String.hpp>
|
||||
#include <Nazara/Renderer/OpenGL.hpp>
|
||||
#include <Nazara/Renderer/Shader.hpp>
|
||||
#include <Nazara/Renderer/ShaderImpl.hpp>
|
||||
#include <map>
|
||||
|
||||
class NzGLSLShader : public NzShaderImpl
|
||||
{
|
||||
public:
|
||||
NzGLSLShader(NzShader* parent);
|
||||
~NzGLSLShader();
|
||||
|
||||
bool Bind();
|
||||
|
||||
bool Compile();
|
||||
bool Create();
|
||||
|
||||
void Destroy();
|
||||
|
||||
NzString GetLog() const;
|
||||
nzShaderLanguage GetLanguage() const;
|
||||
NzString GetSourceCode(nzShaderType type) const;
|
||||
GLint GetUniformLocation(const NzString& name) const;
|
||||
|
||||
bool IsLoaded(nzShaderType type) const;
|
||||
|
||||
bool Load(nzShaderType type, const NzString& source);
|
||||
|
||||
bool SendBoolean(const NzString& name, bool value);
|
||||
bool SendDouble(const NzString& name, double value);
|
||||
bool SendFloat(const NzString& name, float value);
|
||||
bool SendInteger(const NzString& name, int value);
|
||||
bool SendMatrix(const NzString& name, const NzMatrix4d& matrix);
|
||||
bool SendMatrix(const NzString& name, const NzMatrix4f& matrix);
|
||||
|
||||
void Unbind();
|
||||
|
||||
private:
|
||||
mutable std::map<NzString, GLint> m_idCache;
|
||||
GLuint m_program;
|
||||
GLuint m_shaders[nzShaderType_Count];
|
||||
NzShader* m_parent;
|
||||
NzString m_log;
|
||||
};
|
||||
|
||||
#endif // NAZARA_GLSLSHADER_HPPs
|
||||
231
src/Nazara/Renderer/HardwareBuffer.cpp
Normal file
231
src/Nazara/Renderer/HardwareBuffer.cpp
Normal file
@@ -0,0 +1,231 @@
|
||||
// Copyright (C) 2012 Jérôme Leclercq
|
||||
// This file is part of the "Nazara Engine".
|
||||
// For conditions of distribution and use, see copyright notice in Config.hpp
|
||||
|
||||
#include <Nazara/Renderer/OpenGL.hpp>
|
||||
#include <Nazara/Renderer/HardwareBuffer.hpp>
|
||||
#include <Nazara/Core/Error.hpp>
|
||||
#include <cstring>
|
||||
#include <stdexcept>
|
||||
#include <Nazara/Renderer/Debug.hpp>
|
||||
|
||||
namespace
|
||||
{
|
||||
GLenum bufferLock[] = {
|
||||
GL_WRITE_ONLY, // nzBufferLock_DiscardAndWrite
|
||||
GL_READ_ONLY, // nzBufferLock_ReadOnly
|
||||
GL_READ_WRITE, // nzBufferLock_ReadWrite
|
||||
GL_WRITE_ONLY // nzBufferLock_WriteOnly
|
||||
};
|
||||
|
||||
GLenum bufferLockRange[] = {
|
||||
GL_MAP_INVALIDATE_BUFFER_BIT | GL_MAP_WRITE_BIT, // nzBufferLock_DiscardAndWrite
|
||||
GL_MAP_READ_BIT, // nzBufferLock_ReadOnly
|
||||
GL_MAP_READ_BIT | GL_MAP_WRITE_BIT, // nzBufferLock_ReadWrite
|
||||
GL_MAP_WRITE_BIT // nzBufferLock_WriteOnly
|
||||
};
|
||||
|
||||
GLenum bufferTarget[] = {
|
||||
GL_ELEMENT_ARRAY_BUFFER, // nzBufferType_Index,
|
||||
GL_ARRAY_BUFFER, // nzBufferType_Vertex
|
||||
};
|
||||
|
||||
GLenum bufferTargetBinding[] = {
|
||||
GL_ELEMENT_ARRAY_BUFFER_BINDING, // BufferType_Index,
|
||||
GL_ARRAY_BUFFER_BINDING, // BufferType_Vertex
|
||||
};
|
||||
|
||||
GLenum bufferUsage[] = {
|
||||
// J'ai choisi DYNAMIC_DRAW à la place de STREAM_DRAW car DYNAMIC semble plus adapté au profil "une mise à jour pour quelques rendus"
|
||||
// Ce qui est je pense le scénario qui arrivera le plus souvent (Prévoir une option pour permettre d'utiliser le STREAM_DRAW ?)
|
||||
// Source: http://www.opengl.org/discussion_boards/ubbthreads.php?ubb=showflat&Number=160839
|
||||
GL_DYNAMIC_DRAW, // nzBufferUsage_Dynamic
|
||||
GL_STATIC_DRAW // nzBufferUsage_Static
|
||||
};
|
||||
|
||||
typedef nzUInt8* (*LockRoutine)(nzBufferType type, nzBufferLock lock, unsigned int offset, unsigned int length);
|
||||
|
||||
nzUInt8* LockBuffer(nzBufferType type, nzBufferLock lock, unsigned int offset, unsigned int length)
|
||||
{
|
||||
NazaraUnused(length);
|
||||
|
||||
if (lock == nzBufferLock_DiscardAndWrite)
|
||||
{
|
||||
GLint size;
|
||||
glGetBufferParameteriv(bufferTargetBinding[type], GL_BUFFER_SIZE, &size);
|
||||
|
||||
GLint usage;
|
||||
glGetBufferParameteriv(bufferTargetBinding[type], GL_BUFFER_USAGE, &usage);
|
||||
|
||||
// On discard le buffer
|
||||
glBufferData(bufferTargetBinding[type], size, nullptr, usage);
|
||||
}
|
||||
|
||||
void* ptr = glMapBuffer(bufferTarget[type], bufferLock[lock]);
|
||||
if (ptr)
|
||||
return reinterpret_cast<nzUInt8*>(ptr) + offset;
|
||||
else
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
nzUInt8* LockBufferRange(nzBufferType type, nzBufferLock lock, unsigned int offset, unsigned int length)
|
||||
{
|
||||
return reinterpret_cast<nzUInt8*>(glMapBufferRange(bufferTarget[type], offset, length, bufferLockRange[lock]));
|
||||
}
|
||||
|
||||
nzUInt8* LockBufferFirstRun(nzBufferType type, nzBufferLock lock, unsigned int offset, unsigned int length)
|
||||
{
|
||||
if (glMapBufferRange)
|
||||
lockBuffer = LockBufferRange;
|
||||
else
|
||||
lockBuffer = LockBuffer;
|
||||
|
||||
return lockBuffer(type, lock, offset, length);
|
||||
}
|
||||
|
||||
LockRoutine lockBuffer = LockBufferFirstRun;
|
||||
}
|
||||
|
||||
NzHardwareBuffer::NzHardwareBuffer(NzBuffer* parent, nzBufferType type) :
|
||||
m_type(type),
|
||||
m_parent(parent)
|
||||
{
|
||||
}
|
||||
|
||||
NzHardwareBuffer::~NzHardwareBuffer()
|
||||
{
|
||||
}
|
||||
|
||||
void NzHardwareBuffer::Bind()
|
||||
{
|
||||
glBindBuffer(bufferTarget[m_type], m_buffer);
|
||||
}
|
||||
|
||||
bool NzHardwareBuffer::Create(unsigned int length, nzUInt8 typeSize, nzBufferUsage usage)
|
||||
{
|
||||
m_buffer = 0;
|
||||
glGenBuffers(1, &m_buffer);
|
||||
|
||||
if (!m_buffer)
|
||||
{
|
||||
NazaraError("Failed to create buffer");
|
||||
return false;
|
||||
}
|
||||
|
||||
GLint previous;
|
||||
glGetIntegerv(bufferTargetBinding[m_type], &previous);
|
||||
|
||||
glBindBuffer(bufferTarget[m_type], m_buffer);
|
||||
glBufferData(bufferTarget[m_type], length*typeSize, nullptr, bufferUsage[usage]);
|
||||
|
||||
// Pour ne pas perturber le rendu, on interfère pas avec le binding déjà présent
|
||||
if (previous != 0)
|
||||
glBindBuffer(bufferTarget[m_type], previous);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void NzHardwareBuffer::Destroy()
|
||||
{
|
||||
glDeleteBuffers(1, &m_buffer);
|
||||
}
|
||||
|
||||
bool NzHardwareBuffer::Fill(const void* data, unsigned int offset, unsigned int length)
|
||||
{
|
||||
GLuint previous;
|
||||
glGetIntegerv(bufferTargetBinding[m_type], reinterpret_cast<GLint*>(&previous));
|
||||
|
||||
if (previous != m_buffer)
|
||||
glBindBuffer(bufferTarget[m_type], m_buffer);
|
||||
|
||||
// Il semblerait que glBufferSubData soit plus performant que glMapBuffer(Range) en dessous d'un certain seuil
|
||||
if (length < 32*1024)
|
||||
{
|
||||
if (length == m_parent->GetLength())
|
||||
glBufferData(bufferTarget[m_type], m_parent->GetSize(), data, bufferUsage[m_parent->GetStorage()]);
|
||||
else
|
||||
{
|
||||
nzUInt8 typeSize = m_parent->GetTypeSize();
|
||||
glBufferSubData(bufferTarget[m_type], offset*typeSize, length*typeSize, data);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
nzUInt8* ptr = lockBuffer(m_type, (length == m_parent->GetLength()) ? nzBufferLock_DiscardAndWrite : nzBufferLock_WriteOnly, offset, length);
|
||||
if (ptr)
|
||||
{
|
||||
NazaraError("Failed to lock buffer");
|
||||
return false;
|
||||
}
|
||||
|
||||
std::memcpy(ptr, data, length*m_parent->GetTypeSize());
|
||||
|
||||
if (glUnmapBuffer(bufferTarget[m_type]) != GL_TRUE)
|
||||
{
|
||||
// Une erreur rare est survenue, nous devons réinitialiser le buffer
|
||||
NazaraError("Failed to unlock buffer, reinitialising content... (OpenGL error : 0x" + NzString::Number(glGetError(), 16) + ')');
|
||||
|
||||
glBufferData(bufferTarget[m_type], m_parent->GetSize(), nullptr, bufferUsage[m_parent->GetStorage()]);
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// Inutile de rebinder s'il n'y avait aucun buffer (Optimise les opérations chaînées)
|
||||
if (previous != m_buffer && previous != 0)
|
||||
glBindBuffer(bufferTarget[m_type], previous);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool NzHardwareBuffer::IsHardware() const
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
void* NzHardwareBuffer::Lock(nzBufferLock lock, unsigned int offset, unsigned int length)
|
||||
{
|
||||
// Pour ne pas perturber le rendu, on interfère pas avec le binding déjà présent
|
||||
GLuint previous;
|
||||
glGetIntegerv(bufferTargetBinding[m_type], reinterpret_cast<GLint*>(&previous));
|
||||
|
||||
if (previous != m_buffer)
|
||||
glBindBuffer(bufferTarget[m_type], m_buffer);
|
||||
|
||||
void* ptr = lockBuffer(m_type, lock, offset, length);
|
||||
|
||||
// Inutile de rebinder s'il n'y avait aucun buffer (Optimise les opérrations chaînées)
|
||||
if (previous != m_buffer && previous != 0)
|
||||
glBindBuffer(bufferTarget[m_type], previous);
|
||||
|
||||
return ptr;
|
||||
}
|
||||
|
||||
bool NzHardwareBuffer::Unlock()
|
||||
{
|
||||
GLuint previous;
|
||||
glGetIntegerv(bufferTargetBinding[m_type], reinterpret_cast<GLint*>(&previous));
|
||||
|
||||
if (previous != m_buffer)
|
||||
glBindBuffer(bufferTarget[m_type], m_buffer);
|
||||
|
||||
if (glUnmapBuffer(bufferTarget[m_type]) != GL_TRUE)
|
||||
{
|
||||
// Une erreur rare est survenue, nous devons réinitialiser le buffer
|
||||
NazaraError("Failed to unlock buffer, reinitialising content... (OpenGL error : 0x" + NzString::Number(glGetError(), 16) + ')');
|
||||
|
||||
glBufferData(bufferTarget[m_type], m_parent->GetSize(), nullptr, bufferUsage[m_parent->GetStorage()]);
|
||||
|
||||
// Inutile de rebinder s'il n'y avait aucun buffer (Optimise les opérrations chaînées)
|
||||
if (previous != m_buffer && previous != 0)
|
||||
glBindBuffer(bufferTarget[m_type], previous);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
// Inutile de rebinder s'il n'y avait aucun buffer (Optimise les opérrations chaînées)
|
||||
if (previous != m_buffer && previous != 0)
|
||||
glBindBuffer(bufferTarget[m_type], previous);
|
||||
|
||||
return true;
|
||||
}
|
||||
38
src/Nazara/Renderer/HardwareBuffer.hpp
Normal file
38
src/Nazara/Renderer/HardwareBuffer.hpp
Normal file
@@ -0,0 +1,38 @@
|
||||
// Copyright (C) 2012 Jérôme Leclercq
|
||||
// This file is part of the "Nazara Engine".
|
||||
// For conditions of distribution and use, see copyright notice in Config.hpp
|
||||
|
||||
#pragma once
|
||||
|
||||
#ifndef NAZARA_HARDWAREBUFFER_HPP
|
||||
#define NAZARA_HARDWAREBUFFER_HPP
|
||||
|
||||
#include <Nazara/Prerequesites.hpp>
|
||||
#include <Nazara/Renderer/BufferImpl.hpp>
|
||||
#include <Nazara/Renderer/OpenGL.hpp>
|
||||
|
||||
class NzHardwareBuffer : public NzBufferImpl
|
||||
{
|
||||
public:
|
||||
NzHardwareBuffer(NzBuffer* parent, nzBufferType type);
|
||||
~NzHardwareBuffer();
|
||||
|
||||
void Bind();
|
||||
|
||||
bool Create(unsigned int length, nzUInt8 typeSize, nzBufferUsage usage = nzBufferUsage_Static);
|
||||
void Destroy();
|
||||
|
||||
bool Fill(const void* data, unsigned int offset, unsigned int length);
|
||||
|
||||
bool IsHardware() const;
|
||||
|
||||
void* Lock(nzBufferLock lock, unsigned int offset = 0, unsigned int length = 0);
|
||||
bool Unlock();
|
||||
|
||||
private:
|
||||
GLuint m_buffer;
|
||||
nzBufferType m_type;
|
||||
NzBuffer* m_parent;
|
||||
};
|
||||
|
||||
#endif // NAZARA_HARDWAREBUFFER_HPP
|
||||
154
src/Nazara/Renderer/IndexBuffer.cpp
Normal file
154
src/Nazara/Renderer/IndexBuffer.cpp
Normal file
@@ -0,0 +1,154 @@
|
||||
// Copyright (C) 2012 Jérôme Leclercq
|
||||
// This file is part of the "Nazara Engine".
|
||||
// For conditions of distribution and use, see copyright notice in Config.hpp
|
||||
|
||||
#include <Nazara/Renderer/IndexBuffer.hpp>
|
||||
#include <Nazara/Core/Error.hpp>
|
||||
#include <Nazara/Renderer/Debug.hpp>
|
||||
|
||||
NzIndexBuffer::NzIndexBuffer(NzBuffer* buffer, unsigned int startIndex, unsigned int indexCount) :
|
||||
m_buffer(buffer),
|
||||
m_ownsBuffer(false),
|
||||
m_indexCount(indexCount),
|
||||
m_startIndex(startIndex)
|
||||
{
|
||||
if (m_buffer)
|
||||
m_buffer->AddResourceReference();
|
||||
}
|
||||
|
||||
NzIndexBuffer::NzIndexBuffer(unsigned int length, nzUInt8 indexSize, nzBufferUsage usage) :
|
||||
m_ownsBuffer(true),
|
||||
m_indexCount(length),
|
||||
m_startIndex(0)
|
||||
{
|
||||
m_buffer = new NzBuffer(nzBufferType_Index, length, indexSize, usage);
|
||||
m_buffer->AddResourceReference();
|
||||
m_buffer->SetPersistent(false);
|
||||
}
|
||||
|
||||
NzIndexBuffer::NzIndexBuffer(const NzIndexBuffer& indexBuffer) :
|
||||
m_buffer(indexBuffer.m_buffer),
|
||||
m_indexCount(indexBuffer.m_indexCount),
|
||||
m_startIndex(indexBuffer.m_startIndex)
|
||||
{
|
||||
if (m_buffer)
|
||||
{
|
||||
if (m_ownsBuffer)
|
||||
{
|
||||
m_buffer = new NzBuffer(nzBufferType_Index, indexBuffer.m_buffer->GetLength(), indexBuffer.m_buffer->GetSize(), indexBuffer.m_buffer->GetUsage());
|
||||
m_buffer->AddResourceReference();
|
||||
m_buffer->SetPersistent(false);
|
||||
m_buffer->CopyContent(*indexBuffer.m_buffer);
|
||||
}
|
||||
else
|
||||
{
|
||||
m_buffer = indexBuffer.m_buffer;
|
||||
m_buffer->AddResourceReference();
|
||||
}
|
||||
}
|
||||
else
|
||||
m_buffer = nullptr;
|
||||
}
|
||||
|
||||
NzIndexBuffer::~NzIndexBuffer()
|
||||
{
|
||||
if (m_buffer)
|
||||
m_buffer->RemoveResourceReference();
|
||||
}
|
||||
|
||||
bool NzIndexBuffer::Fill(const void* data, unsigned int offset, unsigned int length)
|
||||
{
|
||||
#if NAZARA_RENDERER_SAFE
|
||||
if (!m_buffer)
|
||||
{
|
||||
NazaraError("Impossible to fill sequential buffer");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (offset+length > m_indexCount)
|
||||
{
|
||||
NazaraError("Exceeding virtual buffer size");
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
|
||||
return m_buffer->Fill(data, m_startIndex+offset, length);
|
||||
}
|
||||
|
||||
NzBuffer* NzIndexBuffer::GetBuffer() const
|
||||
{
|
||||
return m_buffer;
|
||||
}
|
||||
|
||||
nzUInt8 NzIndexBuffer::GetIndexSize() const
|
||||
{
|
||||
#if NAZARA_RENDERER_SAFE
|
||||
if (!m_buffer)
|
||||
{
|
||||
NazaraError("Sequential index buffer: Buffer has no index size");
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
return m_buffer->GetTypeSize();
|
||||
}
|
||||
|
||||
unsigned int NzIndexBuffer::GetIndexCount() const
|
||||
{
|
||||
return m_indexCount;
|
||||
}
|
||||
|
||||
unsigned int NzIndexBuffer::GetStartIndex() const
|
||||
{
|
||||
return m_startIndex;
|
||||
}
|
||||
|
||||
bool NzIndexBuffer::IsHardware() const
|
||||
{
|
||||
#if NAZARA_RENDERER_SAFE
|
||||
if (!m_buffer)
|
||||
{
|
||||
NazaraError("Sequential index buffer is neither hardware or software");
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
|
||||
return m_buffer->IsHardware();
|
||||
}
|
||||
|
||||
bool NzIndexBuffer::IsSequential() const
|
||||
{
|
||||
return m_buffer == nullptr;
|
||||
}
|
||||
|
||||
void* NzIndexBuffer::Lock(nzBufferLock lock, unsigned int offset, unsigned int length)
|
||||
{
|
||||
#if NAZARA_RENDERER_SAFE
|
||||
if (!m_buffer)
|
||||
{
|
||||
NazaraError("Impossible to lock sequential index buffer");
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
if (offset+length > m_indexCount)
|
||||
{
|
||||
NazaraError("Exceeding virtual buffer size");
|
||||
return nullptr;
|
||||
}
|
||||
#endif
|
||||
|
||||
return m_buffer->Lock(lock, m_startIndex+offset, (length) ? length : m_indexCount-offset);
|
||||
}
|
||||
|
||||
bool NzIndexBuffer::Unlock()
|
||||
{
|
||||
#if NAZARA_RENDERER_SAFE
|
||||
if (!m_buffer)
|
||||
{
|
||||
NazaraError("Impossible to unlock sequential index buffer");
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
|
||||
return m_buffer->Unlock();
|
||||
}
|
||||
563
src/Nazara/Renderer/OpenGL.cpp
Normal file
563
src/Nazara/Renderer/OpenGL.cpp
Normal file
@@ -0,0 +1,563 @@
|
||||
#include <Nazara/Renderer/OpenGL.hpp>
|
||||
#include <Nazara/Core/Error.hpp>
|
||||
#include <Nazara/Renderer/Context.hpp>
|
||||
#include <set>
|
||||
#include <sstream>
|
||||
#include <stdexcept>
|
||||
#include <Nazara/Renderer/Debug.hpp>
|
||||
|
||||
namespace
|
||||
{
|
||||
#ifdef NAZARA_PLATFORM_WINDOWS
|
||||
HMODULE openGLlibrary;
|
||||
#endif
|
||||
|
||||
NzOpenGLFunc LoadEntry(const char* name, bool launchException = true)
|
||||
{
|
||||
#if defined(NAZARA_PLATFORM_WINDOWS)
|
||||
NzOpenGLFunc entry = reinterpret_cast<NzOpenGLFunc>(wglGetProcAddress(name));
|
||||
if (!entry) // wglGetProcAddress ne fonctionne pas sur les fonctions OpenGL <= 1.1
|
||||
entry = reinterpret_cast<NzOpenGLFunc>(GetProcAddress(openGLlibrary, name));
|
||||
#elif defined(NAZARA_PLATFORM_LINUX)
|
||||
NzOpenGLFunc entry = reinterpret_cast<NzOpenGLFunc>(glXGetProcAddress(name));
|
||||
#else
|
||||
#error OS not handled
|
||||
#endif
|
||||
|
||||
if (!entry && launchException)
|
||||
{
|
||||
std::ostringstream oss;
|
||||
oss << "failed to load \"" << name << '"';
|
||||
|
||||
throw std::runtime_error(oss.str());
|
||||
}
|
||||
|
||||
return entry;
|
||||
}
|
||||
|
||||
bool LoadLibrary()
|
||||
{
|
||||
#ifdef NAZARA_PLATFORM_WINDOWS
|
||||
openGLlibrary = ::LoadLibraryA("opengl32.dll");
|
||||
|
||||
return openGLlibrary != nullptr;
|
||||
#else
|
||||
return true;
|
||||
#endif
|
||||
}
|
||||
|
||||
void UnloadLibrary()
|
||||
{
|
||||
#ifdef NAZARA_PLATFORM_WINDOWS
|
||||
FreeLibrary(openGLlibrary);
|
||||
#endif
|
||||
}
|
||||
|
||||
std::set<NzString> openGLextensionSet;
|
||||
bool openGLextensions[NzOpenGL::Count] = {false};
|
||||
unsigned int openGLversion = 0;
|
||||
|
||||
bool LoadExtensionsString(const NzString& extensionString)
|
||||
{
|
||||
if (extensionString.IsEmpty())
|
||||
{
|
||||
NazaraError("Unable to get extension string");
|
||||
return false;
|
||||
}
|
||||
|
||||
// On peut sûrement faire plus rapide mais comme ça ne se fait qu'une fois et que NzString implémente le COW...
|
||||
std::vector<NzString> ext;
|
||||
extensionString.Split(ext);
|
||||
|
||||
for (std::vector<NzString>::iterator it = ext.begin(); it != ext.end(); ++it)
|
||||
openGLextensionSet.insert(*it);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool LoadExtensions3()
|
||||
{
|
||||
GLint extensionCount = 0;
|
||||
glGetIntegerv(GL_NUM_EXTENSIONS, &extensionCount);
|
||||
|
||||
if (extensionCount <= 0)
|
||||
{
|
||||
NazaraError("Unable to get extension count");
|
||||
return false;
|
||||
}
|
||||
|
||||
for (int i = 0; i < extensionCount; ++i)
|
||||
{
|
||||
NzString extension(reinterpret_cast<const char*>(glGetStringi(GL_EXTENSIONS, i)));
|
||||
if (extension.IsEmpty())
|
||||
{
|
||||
NazaraWarning("Unable to get extension #" + NzString::Number(i));
|
||||
continue;
|
||||
}
|
||||
|
||||
openGLextensionSet.insert(extension);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
unsigned int NzOpenGL::GetVersion()
|
||||
{
|
||||
return openGLversion;
|
||||
}
|
||||
|
||||
bool NzOpenGL::Initialize()
|
||||
{
|
||||
if (!LoadLibrary())
|
||||
{
|
||||
NazaraError("Failed to load OpenGL library");
|
||||
return false;
|
||||
}
|
||||
|
||||
// Le chargement des fonctions OpenGL nécessite un contexte OpenGL
|
||||
// Le contexte de chargement ne peut pas être partagé car le contexte de référence n'existe pas encore
|
||||
NzContextParameters parameters;
|
||||
parameters.majorVersion = 2;
|
||||
parameters.minorVersion = 0;
|
||||
parameters.shared = false;
|
||||
|
||||
NzContext loadContext;
|
||||
if (!loadContext.Create(parameters))
|
||||
{
|
||||
NazaraError("Failed to create load context");
|
||||
return false;
|
||||
}
|
||||
|
||||
/****************************************Noyau****************************************/
|
||||
|
||||
try
|
||||
{
|
||||
glActiveTexture = reinterpret_cast<PFNGLACTIVETEXTUREPROC>(LoadEntry("glActiveTexture"));
|
||||
glAttachShader = reinterpret_cast<PFNGLATTACHSHADERPROC>(LoadEntry("glAttachShader"));
|
||||
glBindAttribLocation = reinterpret_cast<PFNGLBINDATTRIBLOCATIONPROC>(LoadEntry("glBindAttribLocation"));
|
||||
glBindBuffer = reinterpret_cast<PFNGLBINDBUFFERPROC>(LoadEntry("glBindBuffer"));
|
||||
glBindTexture = reinterpret_cast<PFNGLBINDTEXTUREPROC>(LoadEntry("glBindTexture"));
|
||||
glBlendFunc = reinterpret_cast<PFNGLBLENDFUNCPROC>(LoadEntry("glBlendFunc"));
|
||||
glBufferData = reinterpret_cast<PFNGLBUFFERDATAPROC>(LoadEntry("glBufferData"));
|
||||
glBufferSubData = reinterpret_cast<PFNGLBUFFERSUBDATAPROC>(LoadEntry("glBufferSubData"));
|
||||
glClear = reinterpret_cast<PFNGLCLEARPROC>(LoadEntry("glClear"));
|
||||
glClearColor = reinterpret_cast<PFNGLCLEARCOLORPROC>(LoadEntry("glClearColor"));
|
||||
glClearDepth = reinterpret_cast<PFNGLCLEARDEPTHPROC>(LoadEntry("glClearDepth"));
|
||||
glClearStencil = reinterpret_cast<PFNGLCLEARSTENCILPROC>(LoadEntry("glClearStencil"));
|
||||
glCreateProgram = reinterpret_cast<PFNGLCREATEPROGRAMPROC>(LoadEntry("glCreateProgram"));
|
||||
glCreateShader = reinterpret_cast<PFNGLCREATESHADERPROC>(LoadEntry("glCreateShader"));
|
||||
glColorMask = reinterpret_cast<PFNGLCOLORMASKPROC>(LoadEntry("glColorMask"));
|
||||
glCullFace = reinterpret_cast<PFNGLCULLFACEPROC>(LoadEntry("glCullFace"));
|
||||
glCompileShader = reinterpret_cast<PFNGLCOMPILESHADERPROC>(LoadEntry("glCompileShader"));
|
||||
glDeleteBuffers = reinterpret_cast<PFNGLDELETEBUFFERSPROC>(LoadEntry("glDeleteBuffers"));
|
||||
glDeleteProgram = reinterpret_cast<PFNGLDELETEPROGRAMPROC>(LoadEntry("glDeleteProgram"));
|
||||
glDeleteShader = reinterpret_cast<PFNGLDELETESHADERPROC>(LoadEntry("glDeleteShader"));
|
||||
glDeleteTextures = reinterpret_cast<PFNGLDELETETEXTURESPROC>(LoadEntry("glDeleteTextures"));
|
||||
glDepthFunc = reinterpret_cast<PFNGLDEPTHFUNCPROC>(LoadEntry("glDepthFunc"));
|
||||
glDepthMask = reinterpret_cast<PFNGLDEPTHMASKPROC>(LoadEntry("glDepthMask"));
|
||||
glDisable = reinterpret_cast<PFNGLDISABLEPROC>(LoadEntry("glDisable"));
|
||||
glDisableVertexAttribArray = reinterpret_cast<PFNGLDISABLEVERTEXATTRIBARRAYPROC>(LoadEntry("glDisableVertexAttribArray"));
|
||||
glDrawArrays = reinterpret_cast<PFNGLDRAWARRAYSPROC>(LoadEntry("glDrawArrays"));
|
||||
glDrawBuffer = reinterpret_cast<PFNGLDRAWBUFFERPROC>(LoadEntry("glDrawBuffer"));
|
||||
glDrawBuffers = reinterpret_cast<PFNGLDRAWBUFFERSPROC>(LoadEntry("glDrawBuffers"));
|
||||
glDrawElements = reinterpret_cast<PFNGLDRAWELEMENTSPROC>(LoadEntry("glDrawElements"));
|
||||
glFlush = reinterpret_cast<PFNGLFLUSHPROC>(LoadEntry("glFlush"));
|
||||
glEnable = reinterpret_cast<PFNGLENABLEPROC>(LoadEntry("glEnable"));
|
||||
glEnableVertexAttribArray = reinterpret_cast<PFNGLENABLEVERTEXATTRIBARRAYPROC>(LoadEntry("glEnableVertexAttribArray"));
|
||||
glGenBuffers = reinterpret_cast<PFNGLGENBUFFERSPROC>(LoadEntry("glGenBuffers"));
|
||||
glGenTextures = reinterpret_cast<PFNGLGENTEXTURESPROC>(LoadEntry("glGenTextures"));
|
||||
glGetBufferParameteriv = reinterpret_cast<PFNGLGETBUFFERPARAMETERIVPROC>(LoadEntry("glGetBufferParameteriv"));
|
||||
glGetError = reinterpret_cast<PFNGLGETERRORPROC>(LoadEntry("glGetError"));
|
||||
glGetIntegerv = reinterpret_cast<PFNGLGETINTEGERVPROC>(LoadEntry("glGetIntegerv"));
|
||||
glGetProgramiv = reinterpret_cast<PFNGLGETPROGRAMIVPROC>(LoadEntry("glGetProgramiv"));
|
||||
glGetProgramInfoLog = reinterpret_cast<PFNGLGETPROGRAMINFOLOGPROC>(LoadEntry("glGetProgramInfoLog"));
|
||||
glGetShaderInfoLog = reinterpret_cast<PFNGLGETSHADERINFOLOGPROC>(LoadEntry("glGetShaderInfoLog"));
|
||||
glGetShaderiv = reinterpret_cast<PFNGLGETSHADERIVPROC>(LoadEntry("glGetShaderiv"));
|
||||
glGetShaderSource = reinterpret_cast<PFNGLGETSHADERSOURCEPROC>(LoadEntry("glGetShaderSource"));
|
||||
glGetString = reinterpret_cast<PFNGLGETSTRINGPROC>(LoadEntry("glGetString"));
|
||||
glGetTexImage = reinterpret_cast<PFNGLGETTEXIMAGEPROC>(LoadEntry("glGetTexImage"));
|
||||
glGetTexParameterfv = reinterpret_cast<PFNGLGETTEXPARAMETERFVPROC>(LoadEntry("glGetTexParameterfv"));
|
||||
glGetTexParameteriv = reinterpret_cast<PFNGLGETTEXPARAMETERIVPROC>(LoadEntry("glGetTexParameteriv"));
|
||||
glGetUniformLocation = reinterpret_cast<PFNGLGETUNIFORMLOCATIONPROC>(LoadEntry("glGetUniformLocation"));
|
||||
glLinkProgram = reinterpret_cast<PFNGLLINKPROGRAMPROC>(LoadEntry("glLinkProgram"));
|
||||
glMapBuffer = reinterpret_cast<PFNGLMAPBUFFERPROC>(LoadEntry("glMapBuffer"));
|
||||
glPolygonMode = reinterpret_cast<PFNGLPOLYGONMODEPROC>(LoadEntry("glPolygonMode"));
|
||||
glScissor = reinterpret_cast<PFNGLSCISSORPROC>(LoadEntry("glScissor"));
|
||||
glShaderSource = reinterpret_cast<PFNGLSHADERSOURCEPROC>(LoadEntry("glShaderSource"));
|
||||
glStencilFunc = reinterpret_cast<PFNGLSTENCILFUNCPROC>(LoadEntry("glStencilFunc"));
|
||||
glStencilOp = reinterpret_cast<PFNGLSTENCILOPPROC>(LoadEntry("glStencilOp"));
|
||||
glTexImage2D = reinterpret_cast<PFNGLTEXIMAGE2DPROC>(LoadEntry("glTexImage2D"));
|
||||
glTexParameterf = reinterpret_cast<PFNGLTEXPARAMETERFPROC>(LoadEntry("glTexParameterf"));
|
||||
glTexParameteri = reinterpret_cast<PFNGLTEXPARAMETERIPROC>(LoadEntry("glTexParameteri"));
|
||||
glTexSubImage2D = reinterpret_cast<PFNGLTEXSUBIMAGE2DPROC>(LoadEntry("glTexSubImage2D"));
|
||||
glUniform1f = reinterpret_cast<PFNGLUNIFORM1FPROC>(LoadEntry("glUniform1f"));
|
||||
glUniform1i = reinterpret_cast<PFNGLUNIFORM1IPROC>(LoadEntry("glUniform1i"));
|
||||
glUniform2fv = reinterpret_cast<PFNGLUNIFORM2FVPROC>(LoadEntry("glUniform2fv"));
|
||||
glUniform3fv = reinterpret_cast<PFNGLUNIFORM3FVPROC>(LoadEntry("glUniform3fv"));
|
||||
glUniform4fv = reinterpret_cast<PFNGLUNIFORM4FVPROC>(LoadEntry("glUniform4fv"));
|
||||
glUniformMatrix4fv = reinterpret_cast<PFNGLUNIFORMMATRIX4FVPROC>(LoadEntry("glUniformMatrix4fv"));
|
||||
glUnmapBuffer = reinterpret_cast<PFNGLUNMAPBUFFERPROC>(LoadEntry("glUnmapBuffer"));
|
||||
glUseProgram = reinterpret_cast<PFNGLUSEPROGRAMPROC>(LoadEntry("glUseProgram"));
|
||||
glVertexAttrib4f = reinterpret_cast<PFNGLVERTEXATTRIB4FPROC>(LoadEntry("glVertexAttrib4f"));
|
||||
glVertexAttribPointer = reinterpret_cast<PFNGLVERTEXATTRIBPOINTERPROC>(LoadEntry("glVertexAttribPointer"));
|
||||
glViewport = reinterpret_cast<PFNGLVIEWPORTPROC>(LoadEntry("glViewport"));
|
||||
}
|
||||
catch (const std::exception& e)
|
||||
{
|
||||
NazaraError("Unable to load OpenGL: " + NzString(e.what()));
|
||||
Uninitialize();
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
// Fonctions optionnelles
|
||||
glGetStringi = reinterpret_cast<PFNGLGETSTRINGIPROC>(LoadEntry("glGetStringi", false));
|
||||
glMapBufferRange = reinterpret_cast<PFNGLMAPBUFFERRANGEPROC>(LoadEntry("glMapBufferRange", false));
|
||||
|
||||
#if defined(NAZARA_PLATFORM_WINDOWS)
|
||||
wglCreateContextAttribs = reinterpret_cast<PFNWGLCREATECONTEXTATTRIBSARBPROC>(LoadEntry("wglCreateContextAttribsARB", false));
|
||||
wglChoosePixelFormat = reinterpret_cast<PFNWGLCHOOSEPIXELFORMATARBPROC>(LoadEntry("wglChoosePixelFormatARB", false));
|
||||
if (!wglChoosePixelFormat)
|
||||
wglChoosePixelFormat = reinterpret_cast<PFNWGLCHOOSEPIXELFORMATEXTPROC>(LoadEntry("wglChoosePixelFormatEXT", false));
|
||||
|
||||
wglGetExtensionsStringARB = reinterpret_cast<PFNWGLGETEXTENSIONSSTRINGARBPROC>(LoadEntry("wglGetExtensionsStringARB", false));
|
||||
wglGetExtensionsStringEXT = reinterpret_cast<PFNWGLGETEXTENSIONSSTRINGEXTPROC>(LoadEntry("wglGetExtensionsStringEXT", false));
|
||||
wglSwapInterval = reinterpret_cast<PFNWGLSWAPINTERVALEXTPROC>(LoadEntry("wglSwapIntervalEXT", false));
|
||||
#elif defined(NAZARA_PLATFORM_LINUX)
|
||||
glXCreateContextAttribs = reinterpret_cast<PFNGLXCREATECONTEXTATTRIBSARBPROC>(LoadEntry("glXCreateContextAttribsARB", false));
|
||||
glXSwapInterval = reinterpret_cast<PFNGLXSWAPINTERVALSGIPROC>(LoadEntry("glXSwapIntervalSGI", false));
|
||||
#endif
|
||||
|
||||
// Récupération de la version d'OpenGL
|
||||
// Ce code se base sur le fait que la carte graphique renverra un contexte de compatibilité avec la plus haute version supportée
|
||||
// Ce qui semble vrai au moins chez ATI/AMD et NVidia, mais si quelqu'un à une meilleure idée ...
|
||||
const GLubyte* version = glGetString(GL_VERSION);
|
||||
if (!version)
|
||||
{
|
||||
NazaraError("Unable to retrieve OpenGL version");
|
||||
Uninitialize();
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
unsigned int major = version[0] - '0';
|
||||
unsigned int minor = version[2] - '0';
|
||||
|
||||
if (major == 0 || major > 9)
|
||||
{
|
||||
NazaraError("Unable to retrieve OpenGL major version");
|
||||
Uninitialize();
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
if (minor > 9)
|
||||
{
|
||||
NazaraWarning("Unable to retrieve OpenGL minor version (using 0)");
|
||||
minor = 0;
|
||||
}
|
||||
|
||||
openGLversion = major*100 + minor*10;
|
||||
|
||||
/****************************************Extensions****************************************/
|
||||
|
||||
if (!glGetStringi || !LoadExtensions3())
|
||||
{
|
||||
if (openGLversion >= 300) // Dans le cas contraire c'est normal
|
||||
NazaraWarning("Failed to load OpenGL 3 extension system, switching to OpenGL 2 extension system...");
|
||||
|
||||
if (!LoadExtensionsString(reinterpret_cast<const char*>(glGetString(GL_EXTENSIONS))))
|
||||
NazaraWarning("Failed to load extension system");
|
||||
}
|
||||
|
||||
#ifdef NAZARA_PLATFORM_WINDOWS
|
||||
{
|
||||
bool loaded;
|
||||
if (wglGetExtensionsStringARB)
|
||||
loaded = LoadExtensionsString(reinterpret_cast<const char*>(wglGetExtensionsStringARB(wglGetCurrentDC())));
|
||||
else if (wglGetExtensionsStringEXT)
|
||||
loaded = LoadExtensionsString(reinterpret_cast<const char*>(wglGetExtensionsStringEXT()));
|
||||
else
|
||||
loaded = false;
|
||||
|
||||
if (!loaded)
|
||||
NazaraWarning("Failed to load windows' extension string");
|
||||
}
|
||||
#endif
|
||||
|
||||
// AnisotropicFilter
|
||||
openGLextensions[NzOpenGL::AnisotropicFilter] = IsSupported("GL_EXT_texture_filter_anisotropic");
|
||||
|
||||
// FP64
|
||||
if (openGLversion >= 400 || IsSupported("GL_ARB_gpu_shader_fp64"))
|
||||
{
|
||||
try
|
||||
{
|
||||
glUniform1d = reinterpret_cast<PFNGLUNIFORM1DPROC>(LoadEntry("glUniform1d"));
|
||||
glUniform2dv = reinterpret_cast<PFNGLUNIFORM2DVPROC>(LoadEntry("glUniform2dv"));
|
||||
glUniform3dv = reinterpret_cast<PFNGLUNIFORM3DVPROC>(LoadEntry("glUniform3dv"));
|
||||
glUniform4dv = reinterpret_cast<PFNGLUNIFORM4DVPROC>(LoadEntry("glUniform4dv"));
|
||||
|
||||
openGLextensions[NzOpenGL::FP64] = true;
|
||||
}
|
||||
catch (const std::exception& e)
|
||||
{
|
||||
NazaraError("Failed to load ARB_gpu_shader_fp64: " + NzString(e.what()));
|
||||
}
|
||||
}
|
||||
|
||||
// Framebuffer_Object
|
||||
try
|
||||
{
|
||||
glBindFramebuffer = reinterpret_cast<PFNGLBINDFRAMEBUFFERPROC>(LoadEntry("glBindFramebuffer"));
|
||||
glBindRenderbuffer = reinterpret_cast<PFNGLBINDRENDERBUFFERPROC>(LoadEntry("glBindRenderbuffer"));
|
||||
glCheckFramebufferStatus = reinterpret_cast<PFNGLCHECKFRAMEBUFFERSTATUSPROC>(LoadEntry("glCheckFramebufferStatus"));
|
||||
glDeleteFramebuffers = reinterpret_cast<PFNGLDELETEFRAMEBUFFERSPROC>(LoadEntry("glDeleteFramebuffers"));
|
||||
glDeleteRenderbuffers = reinterpret_cast<PFNGLDELETERENDERBUFFERSPROC>(LoadEntry("glDeleteRenderbuffers"));
|
||||
glFramebufferRenderbuffer = reinterpret_cast<PFNGLFRAMEBUFFERRENDERBUFFERPROC>(LoadEntry("glFramebufferRenderbuffer"));
|
||||
glFramebufferTexture2D = reinterpret_cast<PFNGLFRAMEBUFFERTEXTURE2DPROC>(LoadEntry("glFramebufferTexture2D"));
|
||||
glGenerateMipmap = reinterpret_cast<PFNGLGENERATEMIPMAPPROC>(LoadEntry("glGenerateMipmap"));
|
||||
glGenFramebuffers = reinterpret_cast<PFNGLGENFRAMEBUFFERSPROC>(LoadEntry("glGenFramebuffers"));
|
||||
glGenRenderbuffers = reinterpret_cast<PFNGLGENRENDERBUFFERSPROC>(LoadEntry("glGenRenderbuffers"));
|
||||
glRenderbufferStorage = reinterpret_cast<PFNGLRENDERBUFFERSTORAGEPROC>(LoadEntry("glRenderbufferStorage"));
|
||||
|
||||
openGLextensions[NzOpenGL::Framebuffer_Object] = true;
|
||||
}
|
||||
catch (const std::exception& e)
|
||||
{
|
||||
if (openGLversion >= 300)
|
||||
NazaraWarning("Failed to load core FBOs (" + NzString(e.what()) + ")");
|
||||
|
||||
if (IsSupported("GL_EXT_framebuffer_object"))
|
||||
{
|
||||
try
|
||||
{
|
||||
glBindFramebuffer = reinterpret_cast<PFNGLBINDFRAMEBUFFEREXTPROC>(LoadEntry("glBindFramebufferEXT"));
|
||||
glBindRenderbuffer = reinterpret_cast<PFNGLBINDRENDERBUFFEREXTPROC>(LoadEntry("glBindRenderbufferEXT"));
|
||||
glCheckFramebufferStatus = reinterpret_cast<PFNGLCHECKFRAMEBUFFERSTATUSEXTPROC>(LoadEntry("glCheckFramebufferStatusEXT"));
|
||||
glDeleteFramebuffers = reinterpret_cast<PFNGLDELETEFRAMEBUFFERSEXTPROC>(LoadEntry("glDeleteFramebuffersEXT"));
|
||||
glDeleteRenderbuffers = reinterpret_cast<PFNGLDELETERENDERBUFFERSEXTPROC>(LoadEntry("glDeleteRenderbuffersEXT"));
|
||||
glFramebufferRenderbuffer = reinterpret_cast<PFNGLFRAMEBUFFERRENDERBUFFEREXTPROC>(LoadEntry("glFramebufferRenderbufferEXT"));
|
||||
glFramebufferTexture2D = reinterpret_cast<PFNGLFRAMEBUFFERTEXTURE2DEXTPROC>(LoadEntry("glFramebufferTexture2DEXT"));
|
||||
glGenerateMipmap = reinterpret_cast<PFNGLGENERATEMIPMAPEXTPROC>(LoadEntry("glGenerateMipmapEXT"));
|
||||
glGenFramebuffers = reinterpret_cast<PFNGLGENFRAMEBUFFERSEXTPROC>(LoadEntry("glGenFramebuffersEXT"));
|
||||
glGenRenderbuffers = reinterpret_cast<PFNGLGENRENDERBUFFERSEXTPROC>(LoadEntry("glGenRenderbuffersEXT"));
|
||||
glRenderbufferStorage = reinterpret_cast<PFNGLRENDERBUFFERSTORAGEEXTPROC>(LoadEntry("glRenderbufferStorageEXT"));
|
||||
|
||||
openGLextensions[NzOpenGL::Framebuffer_Object] = true;
|
||||
}
|
||||
catch (const std::exception& e)
|
||||
{
|
||||
NazaraError("Failed to load EXT_framebuffer_object: " + NzString(e.what()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Occlusion_Query
|
||||
try
|
||||
{
|
||||
glBeginQuery = reinterpret_cast<PFNGLBEGINQUERYPROC>(LoadEntry("glBeginQuery"));
|
||||
glDeleteQueries = reinterpret_cast<PFNGLDELETEQUERIESPROC>(LoadEntry("glDeleteQueries"));
|
||||
glEndQuery = reinterpret_cast<PFNGLENDQUERYPROC>(LoadEntry("glEndQuery"));
|
||||
glGenQueries = reinterpret_cast<PFNGLGENQUERIESPROC>(LoadEntry("glGenQueries"));
|
||||
glGetQueryiv = reinterpret_cast<PFNGLGETQUERYIVPROC>(LoadEntry("glGetQueryiv"));
|
||||
glGetQueryObjectiv = reinterpret_cast<PFNGLGETQUERYOBJECTIVPROC>(LoadEntry("glGetQueryObjectiv"));
|
||||
glGetQueryObjectuiv = reinterpret_cast<PFNGLGETQUERYOBJECTUIVPROC>(LoadEntry("glGetQueryObjectuiv"));
|
||||
|
||||
openGLextensions[NzOpenGL::Occlusion_Query] = true;
|
||||
}
|
||||
catch (const std::exception& e)
|
||||
{
|
||||
if (openGLversion >= 150)
|
||||
NazaraWarning("Failed to load core Occlusion Queries (" + NzString(e.what()) + "), loading ARB_occlusion_query...");
|
||||
|
||||
if (IsSupported("GL_ARB_occlusion_query"))
|
||||
{
|
||||
try
|
||||
{
|
||||
glBeginQuery = reinterpret_cast<PFNGLBEGINQUERYARBPROC>(LoadEntry("glBeginQueryARB"));
|
||||
glDeleteQueries = reinterpret_cast<PFNGLDELETEQUERIESARBPROC>(LoadEntry("glDeleteQueriesARB"));
|
||||
glEndQuery = reinterpret_cast<PFNGLENDQUERYARBPROC>(LoadEntry("glEndQueryARB"));
|
||||
glGenQueries = reinterpret_cast<PFNGLGENQUERIESARBPROC>(LoadEntry("glGenQueriesARB"));
|
||||
glGetQueryiv = reinterpret_cast<PFNGLGETQUERYIVARBPROC>(LoadEntry("glGetQueryivARB"));
|
||||
glGetQueryObjectiv = reinterpret_cast<PFNGLGETQUERYOBJECTIVARBPROC>(LoadEntry("glGetQueryObjectivARB"));
|
||||
glGetQueryObjectuiv = reinterpret_cast<PFNGLGETQUERYOBJECTUIVARBPROC>(LoadEntry("glGetQueryObjectuivARB"));
|
||||
|
||||
openGLextensions[NzOpenGL::Occlusion_Query] = true;
|
||||
}
|
||||
catch (const std::exception& e)
|
||||
{
|
||||
NazaraError("Failed to load ARB_occlusion_query: " + NzString(e.what()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Texture3D
|
||||
if (IsSupported("GL_EXT_texture3D"))
|
||||
{
|
||||
try
|
||||
{
|
||||
glTexImage3D = reinterpret_cast<PFNGLTEXIMAGE3DEXTPROC>(LoadEntry("glTexImage3DEXT"));
|
||||
glTexSubImage3D = reinterpret_cast<PFNGLTEXSUBIMAGE3DEXTPROC>(LoadEntry("glTexSubImage3DEXT"));
|
||||
|
||||
openGLextensions[NzOpenGL::Texture3D] = true;
|
||||
}
|
||||
catch (const std::exception& e)
|
||||
{
|
||||
NazaraError("Failed to load EXT_texture3D: " + NzString(e.what()));
|
||||
}
|
||||
}
|
||||
|
||||
/****************************************Contextes****************************************/
|
||||
|
||||
/*
|
||||
NzContextParameters::defaultMajorVersion = openGLversion/100;
|
||||
NzContextParameters::defaultMinorVersion = (openGLversion%100)/10;
|
||||
*/
|
||||
|
||||
NzContextParameters::defaultMajorVersion = std::min(openGLversion/100, 2U);
|
||||
NzContextParameters::defaultMinorVersion = std::min((openGLversion%100)/10, 1U);
|
||||
|
||||
if (!NzContext::InitializeReference())
|
||||
{
|
||||
NazaraError("Failed to initialize reference context");
|
||||
Uninitialize();
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
NzContextParameters::defaultShareContext = NzContext::GetReference();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool NzOpenGL::IsSupported(Extension extension)
|
||||
{
|
||||
return openGLextensions[extension];
|
||||
}
|
||||
|
||||
bool NzOpenGL::IsSupported(const NzString& string)
|
||||
{
|
||||
return openGLextensionSet.find(string) != openGLextensionSet.end();
|
||||
}
|
||||
|
||||
void NzOpenGL::Uninitialize()
|
||||
{
|
||||
NzContext::UninitializeReference();
|
||||
|
||||
for (bool& ext : openGLextensions)
|
||||
ext = false;
|
||||
|
||||
openGLextensionSet.clear();
|
||||
openGLversion = 0;
|
||||
|
||||
UnloadLibrary();
|
||||
}
|
||||
|
||||
PFNGLACTIVETEXTUREPROC glActiveTexture = nullptr;
|
||||
PFNGLATTACHSHADERPROC glAttachShader = nullptr;
|
||||
PFNGLBEGINQUERYPROC glBeginQuery = nullptr;
|
||||
PFNGLBINDATTRIBLOCATIONPROC glBindAttribLocation = nullptr;
|
||||
PFNGLBINDBUFFERPROC glBindBuffer = nullptr;
|
||||
PFNGLBINDFRAMEBUFFERPROC glBindFramebuffer = nullptr;
|
||||
PFNGLBINDRENDERBUFFERPROC glBindRenderbuffer = nullptr;
|
||||
PFNGLBINDTEXTUREPROC glBindTexture = nullptr;
|
||||
PFNGLBLENDFUNCPROC glBlendFunc = nullptr;
|
||||
PFNGLBUFFERDATAPROC glBufferData = nullptr;
|
||||
PFNGLBUFFERSUBDATAPROC glBufferSubData = nullptr;
|
||||
PFNGLCLEARPROC glClear = nullptr;
|
||||
PFNGLCLEARCOLORPROC glClearColor = nullptr;
|
||||
PFNGLCLEARDEPTHPROC glClearDepth = nullptr;
|
||||
PFNGLCLEARSTENCILPROC glClearStencil = nullptr;
|
||||
PFNGLCREATEPROGRAMPROC glCreateProgram = nullptr;
|
||||
PFNGLCREATESHADERPROC glCreateShader = nullptr;
|
||||
PFNGLCHECKFRAMEBUFFERSTATUSPROC glCheckFramebufferStatus = nullptr;
|
||||
PFNGLCOLORMASKPROC glColorMask = nullptr;
|
||||
PFNGLCULLFACEPROC glCullFace = nullptr;
|
||||
PFNGLCOMPILESHADERPROC glCompileShader = nullptr;
|
||||
PFNGLDELETEBUFFERSPROC glDeleteBuffers = nullptr;
|
||||
PFNGLDELETEFRAMEBUFFERSPROC glDeleteFramebuffers = nullptr;
|
||||
PFNGLDELETEPROGRAMPROC glDeleteProgram = nullptr;
|
||||
PFNGLDELETEQUERIESPROC glDeleteQueries = nullptr;
|
||||
PFNGLDELETERENDERBUFFERSPROC glDeleteRenderbuffers = nullptr;
|
||||
PFNGLDELETESHADERPROC glDeleteShader = nullptr;
|
||||
PFNGLDELETETEXTURESPROC glDeleteTextures = nullptr;
|
||||
PFNGLDEPTHFUNCPROC glDepthFunc = nullptr;
|
||||
PFNGLDEPTHMASKPROC glDepthMask = nullptr;
|
||||
PFNGLDISABLEPROC glDisable = nullptr;
|
||||
PFNGLDISABLEVERTEXATTRIBARRAYPROC glDisableVertexAttribArray = nullptr;
|
||||
PFNGLDRAWARRAYSPROC glDrawArrays = nullptr;
|
||||
PFNGLDRAWBUFFERPROC glDrawBuffer = nullptr;
|
||||
PFNGLDRAWBUFFERSPROC glDrawBuffers = nullptr;
|
||||
PFNGLDRAWELEMENTSPROC glDrawElements = nullptr;
|
||||
PFNGLENDQUERYPROC glEndQuery = nullptr;
|
||||
PFNGLFLUSHPROC glFlush = nullptr;
|
||||
PFNGLFRAMEBUFFERRENDERBUFFERPROC glFramebufferRenderbuffer = nullptr;
|
||||
PFNGLFRAMEBUFFERTEXTURE2DPROC glFramebufferTexture2D = nullptr;
|
||||
PFNGLENABLEPROC glEnable = nullptr;
|
||||
PFNGLENABLEVERTEXATTRIBARRAYPROC glEnableVertexAttribArray = nullptr;
|
||||
PFNGLGENERATEMIPMAPPROC glGenerateMipmap = nullptr;
|
||||
PFNGLGENBUFFERSPROC glGenBuffers = nullptr;
|
||||
PFNGLGENFRAMEBUFFERSPROC glGenFramebuffers = nullptr;
|
||||
PFNGLGENRENDERBUFFERSPROC glGenRenderbuffers = nullptr;
|
||||
PFNGLGENQUERIESPROC glGenQueries = nullptr;
|
||||
PFNGLGENTEXTURESPROC glGenTextures = nullptr;
|
||||
PFNGLGETBUFFERPARAMETERIVPROC glGetBufferParameteriv = nullptr;
|
||||
PFNGLGETERRORPROC glGetError = nullptr;
|
||||
PFNGLGETINTEGERVPROC glGetIntegerv = nullptr;
|
||||
PFNGLGETPROGRAMIVPROC glGetProgramiv = nullptr;
|
||||
PFNGLGETPROGRAMINFOLOGPROC glGetProgramInfoLog = nullptr;
|
||||
PFNGLGETQUERYIVPROC glGetQueryiv = nullptr;
|
||||
PFNGLGETQUERYOBJECTIVPROC glGetQueryObjectiv = nullptr;
|
||||
PFNGLGETQUERYOBJECTUIVPROC glGetQueryObjectuiv = nullptr;
|
||||
PFNGLGETSHADERINFOLOGPROC glGetShaderInfoLog = nullptr;
|
||||
PFNGLGETSHADERIVPROC glGetShaderiv = nullptr;
|
||||
PFNGLGETSHADERSOURCEPROC glGetShaderSource = nullptr;
|
||||
PFNGLGETSTRINGPROC glGetString = nullptr;
|
||||
PFNGLGETSTRINGIPROC glGetStringi = nullptr;
|
||||
PFNGLGETTEXIMAGEPROC glGetTexImage = nullptr;
|
||||
PFNGLGETTEXPARAMETERFVPROC glGetTexParameterfv = nullptr;
|
||||
PFNGLGETTEXPARAMETERIVPROC glGetTexParameteriv = nullptr;
|
||||
PFNGLGETUNIFORMLOCATIONPROC glGetUniformLocation = nullptr;
|
||||
PFNGLLINKPROGRAMPROC glLinkProgram = nullptr;
|
||||
PFNGLMAPBUFFERPROC glMapBuffer = nullptr;
|
||||
PFNGLMAPBUFFERRANGEPROC glMapBufferRange = nullptr;
|
||||
PFNGLPOLYGONMODEPROC glPolygonMode = nullptr;
|
||||
PFNGLRENDERBUFFERSTORAGEPROC glRenderbufferStorage = nullptr;
|
||||
PFNGLSCISSORPROC glScissor = nullptr;
|
||||
PFNGLSHADERSOURCEPROC glShaderSource = nullptr;
|
||||
PFNGLSTENCILFUNCPROC glStencilFunc = nullptr;
|
||||
PFNGLSTENCILOPPROC glStencilOp = nullptr;
|
||||
PFNGLTEXIMAGE2DPROC glTexImage2D = nullptr;
|
||||
PFNGLTEXIMAGE3DEXTPROC glTexImage3D = nullptr;
|
||||
PFNGLTEXPARAMETERFPROC glTexParameterf = nullptr;
|
||||
PFNGLTEXPARAMETERIPROC glTexParameteri = nullptr;
|
||||
PFNGLTEXSUBIMAGE2DPROC glTexSubImage2D = nullptr;
|
||||
PFNGLTEXSUBIMAGE3DEXTPROC glTexSubImage3D = nullptr;
|
||||
PFNGLUNIFORM1DPROC glUniform1d = nullptr;
|
||||
PFNGLUNIFORM1FPROC glUniform1f = nullptr;
|
||||
PFNGLUNIFORM1IPROC glUniform1i = nullptr;
|
||||
PFNGLUNIFORM2DVPROC glUniform2dv = nullptr;
|
||||
PFNGLUNIFORM2FVPROC glUniform2fv = nullptr;
|
||||
PFNGLUNIFORM3DVPROC glUniform3dv = nullptr;
|
||||
PFNGLUNIFORM3FVPROC glUniform3fv = nullptr;
|
||||
PFNGLUNIFORM4DVPROC glUniform4dv = nullptr;
|
||||
PFNGLUNIFORM4FVPROC glUniform4fv = nullptr;
|
||||
PFNGLUNIFORMMATRIX4DVPROC glUniformMatrix4dv = nullptr;
|
||||
PFNGLUNIFORMMATRIX4FVPROC glUniformMatrix4fv = nullptr;
|
||||
PFNGLUNMAPBUFFERPROC glUnmapBuffer = nullptr;
|
||||
PFNGLUSEPROGRAMPROC glUseProgram = nullptr;
|
||||
PFNGLVERTEXATTRIB4FPROC glVertexAttrib4f = nullptr;
|
||||
PFNGLVERTEXATTRIBPOINTERPROC glVertexAttribPointer = nullptr;
|
||||
PFNGLVIEWPORTPROC glViewport = nullptr;
|
||||
#if defined(NAZARA_PLATFORM_WINDOWS)
|
||||
PFNWGLCHOOSEPIXELFORMATARBPROC wglChoosePixelFormat = nullptr;
|
||||
PFNWGLCREATECONTEXTATTRIBSARBPROC wglCreateContextAttribs = nullptr;
|
||||
PFNWGLGETEXTENSIONSSTRINGARBPROC wglGetExtensionsStringARB = nullptr;
|
||||
PFNWGLGETEXTENSIONSSTRINGEXTPROC wglGetExtensionsStringEXT = nullptr;
|
||||
PFNWGLSWAPINTERVALEXTPROC wglSwapInterval = nullptr;
|
||||
#elif defined(NAZARA_PLATFORM_LINUX)
|
||||
PFNGLXCREATECONTEXTATTRIBSARBPROC glXCreateContextAttribs = nullptr;
|
||||
PFNGLXSWAPINTERVALSGIPROC glXSwapInterval = nullptr;
|
||||
#endif
|
||||
29
src/Nazara/Renderer/RenderTarget.cpp
Normal file
29
src/Nazara/Renderer/RenderTarget.cpp
Normal file
@@ -0,0 +1,29 @@
|
||||
// Copyright (C) 2012 Jérôme Leclercq
|
||||
// This file is part of the "Nazara Engine".
|
||||
// For conditions of distribution and use, see copyright notice in Config.hpp
|
||||
|
||||
#include <Nazara/Renderer/RenderTarget.hpp>
|
||||
#include <Nazara/Renderer/Renderer.hpp>
|
||||
#include <Nazara/Renderer/Debug.hpp>
|
||||
|
||||
NzRenderTarget::~NzRenderTarget() = default;
|
||||
|
||||
bool NzRenderTarget::IsActive() const
|
||||
{
|
||||
return NazaraRenderer->GetTarget() == this;
|
||||
}
|
||||
|
||||
bool NzRenderTarget::SetActive(bool active)
|
||||
{
|
||||
if (active)
|
||||
return NazaraRenderer->SetTarget(this);
|
||||
else if (NazaraRenderer->GetTarget() == this)
|
||||
return NazaraRenderer->SetTarget(nullptr);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void NzRenderTarget::Desactivate()
|
||||
{
|
||||
// Seuls les target sans contextes (ex: RenderTexture) nécessitent une désactivation
|
||||
}
|
||||
156
src/Nazara/Renderer/RenderWindow.cpp
Normal file
156
src/Nazara/Renderer/RenderWindow.cpp
Normal file
@@ -0,0 +1,156 @@
|
||||
// Copyright (C) 2012 Jérôme Leclercq
|
||||
// This file is part of the "Nazara Engine".
|
||||
// For conditions of distribution and use, see copyright notice in Config.hpp
|
||||
|
||||
#include <Nazara/Renderer/OpenGL.hpp>
|
||||
#include <Nazara/Renderer/RenderWindow.hpp>
|
||||
#include <Nazara/Core/Error.hpp>
|
||||
#include <Nazara/Renderer/Context.hpp>
|
||||
#include <Nazara/Renderer/ContextParameters.hpp>
|
||||
#include <Nazara/Renderer/Debug.hpp>
|
||||
|
||||
namespace
|
||||
{
|
||||
NzContextParameters invalidContextParameters;
|
||||
NzRenderTargetParameters invalidRTParameters;
|
||||
}
|
||||
|
||||
NzRenderWindow::NzRenderWindow() :
|
||||
m_context(nullptr)
|
||||
{
|
||||
}
|
||||
|
||||
NzRenderWindow::NzRenderWindow(NzVideoMode mode, const NzString& title, nzUInt32 style, const NzContextParameters& parameters) :
|
||||
m_context(nullptr)
|
||||
{
|
||||
Create(mode, title, style, parameters);
|
||||
}
|
||||
|
||||
NzRenderWindow::NzRenderWindow(NzWindowHandle handle, const NzContextParameters& parameters) :
|
||||
m_context(nullptr)
|
||||
{
|
||||
Create(handle, parameters);
|
||||
}
|
||||
|
||||
NzRenderWindow::~NzRenderWindow()
|
||||
{
|
||||
}
|
||||
|
||||
bool NzRenderWindow::CanActivate() const
|
||||
{
|
||||
return m_impl != nullptr && m_context != nullptr;
|
||||
}
|
||||
|
||||
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_context)
|
||||
m_context->SwapBuffers();
|
||||
}
|
||||
|
||||
void NzRenderWindow::EnableVerticalSync(bool enabled)
|
||||
{
|
||||
if (m_context)
|
||||
{
|
||||
#if defined(NAZARA_PLATFORM_WINDOWS)
|
||||
if (!m_context->SetActive(true))
|
||||
{
|
||||
NazaraError("Unable to activate context");
|
||||
return;
|
||||
}
|
||||
|
||||
if (wglSwapInterval)
|
||||
wglSwapInterval(enabled ? 1 : 0);
|
||||
else
|
||||
#elif defined(NAZARA_PLATFORM_LINUX)
|
||||
if (!m_context->SetActive(true))
|
||||
{
|
||||
NazaraError("Unable to activate context");
|
||||
return;
|
||||
}
|
||||
|
||||
if (glXSwapInterval)
|
||||
glXSwapInterval(enabled ? 1 : 0);
|
||||
else
|
||||
#else
|
||||
#error Vertical Sync is not supported on this platform
|
||||
#endif
|
||||
NazaraError("Vertical Sync is not supported on this platform");
|
||||
}
|
||||
else
|
||||
NazaraError("No context");
|
||||
}
|
||||
|
||||
NzRenderTargetParameters NzRenderWindow::GetRenderTargetParameters() 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();
|
||||
}
|
||||
}
|
||||
|
||||
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()
|
||||
{
|
||||
return m_context->SetActive(true);
|
||||
}
|
||||
|
||||
void NzRenderWindow::OnClose()
|
||||
{
|
||||
delete m_context;
|
||||
}
|
||||
|
||||
bool NzRenderWindow::OnCreate()
|
||||
{
|
||||
m_parameters.doubleBuffered = true;
|
||||
m_parameters.window = GetHandle();
|
||||
m_context = new NzContext;
|
||||
if (!m_context->Create(m_parameters))
|
||||
{
|
||||
NazaraError("Failed not create context");
|
||||
delete m_context;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
EnableVerticalSync(false);
|
||||
|
||||
#if NAZARA_RENDERER_ACTIVATE_RENDERWINDOW_ON_CREATION
|
||||
if (!SetActive(true)) // Les fenêtres s'activent à la création
|
||||
NazaraWarning("Failed to activate window");
|
||||
#endif
|
||||
|
||||
return true;
|
||||
}
|
||||
248
src/Nazara/Renderer/Renderer.cpp
Normal file
248
src/Nazara/Renderer/Renderer.cpp
Normal file
@@ -0,0 +1,248 @@
|
||||
// Copyright (C) 2012 Jérôme Leclercq
|
||||
// This file is part of the "Nazara Engine".
|
||||
// For conditions of distribution and use, see copyright notice in Config.hpp
|
||||
|
||||
#include <Nazara/Renderer/OpenGL.hpp> // Pour éviter une redéfinition de WIN32_LEAN_AND_MEAN
|
||||
#include <Nazara/Renderer/Renderer.hpp>
|
||||
#include <Nazara/Core/Error.hpp>
|
||||
#include <Nazara/Renderer/BufferImpl.hpp>
|
||||
#include <Nazara/Renderer/ShaderImpl.hpp>
|
||||
#include <stdexcept>
|
||||
#include <Nazara/Renderer/Debug.hpp>
|
||||
|
||||
NzRenderer::NzRenderer() :
|
||||
m_indexBuffer(nullptr),
|
||||
m_target(nullptr),
|
||||
m_shader(nullptr)
|
||||
{
|
||||
#if NAZARA_RENDERER_SAFE
|
||||
if (s_instance)
|
||||
throw std::runtime_error("Renderer already instanced");
|
||||
#endif
|
||||
|
||||
s_instance = this;
|
||||
}
|
||||
|
||||
NzRenderer::~NzRenderer()
|
||||
{
|
||||
Uninitialize();
|
||||
|
||||
s_instance = nullptr;
|
||||
}
|
||||
|
||||
void NzRenderer::Clear(nzRendererClear flags)
|
||||
{
|
||||
#if NAZARA_DEBUG
|
||||
if (NzContext::GetCurrent() == nullptr)
|
||||
{
|
||||
NazaraError("No active context");
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (flags)
|
||||
{
|
||||
GLenum mask = 0;
|
||||
|
||||
if (flags & nzRendererClear_Color)
|
||||
mask |= GL_COLOR_BUFFER_BIT;
|
||||
|
||||
if (flags & nzRendererClear_Depth)
|
||||
mask |= GL_DEPTH_BUFFER_BIT;
|
||||
|
||||
if (flags & nzRendererClear_Stencil)
|
||||
mask |= GL_STENCIL_BUFFER_BIT;
|
||||
|
||||
glClear(mask);
|
||||
}
|
||||
}
|
||||
|
||||
NzShader* NzRenderer::GetShader() const
|
||||
{
|
||||
return m_shader;
|
||||
}
|
||||
|
||||
NzRenderTarget* NzRenderer::GetTarget() const
|
||||
{
|
||||
return m_target;
|
||||
}
|
||||
|
||||
bool NzRenderer::HasCapability(nzRendererCap capability) const
|
||||
{
|
||||
return m_capabilities[capability];
|
||||
}
|
||||
|
||||
bool NzRenderer::Initialize()
|
||||
{
|
||||
if (NzOpenGL::Initialize())
|
||||
{
|
||||
m_capabilities[nzRendererCap_AnisotropicFilter] = NzOpenGL::IsSupported(NzOpenGL::AnisotropicFilter);
|
||||
m_capabilities[nzRendererCap_FP64] = NzOpenGL::IsSupported(NzOpenGL::FP64);
|
||||
m_capabilities[nzRendererCap_HardwareBuffer] = true; // Natif depuis OpenGL 2.0
|
||||
m_capabilities[nzRendererCap_MultipleRenderTargets] = true; // Natif depuis OpenGL 2.0
|
||||
m_capabilities[nzRendererCap_Texture3D] = NzOpenGL::IsSupported(NzOpenGL::Texture3D);
|
||||
m_capabilities[nzRendererCap_TextureCubemap] = true; // Natif depuis OpenGL 1.3
|
||||
m_capabilities[nzRendererCap_TextureMulti] = true; // Natif depuis OpenGL 1.3
|
||||
m_capabilities[nzRendererCap_TextureNPOT] = true; // Natif depuis OpenGL 2.0
|
||||
|
||||
return true;
|
||||
}
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
void NzRenderer::SetClearColor(nzUInt8 r, nzUInt8 g, nzUInt8 b, nzUInt8 a)
|
||||
{
|
||||
#if NAZARA_DEBUG
|
||||
if (NzContext::GetCurrent() == nullptr)
|
||||
{
|
||||
NazaraError("No active context");
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
glClearColor(r/255.f, g/255.f, b/255.f, a/255.f);
|
||||
}
|
||||
|
||||
void NzRenderer::SetClearDepth(double depth)
|
||||
{
|
||||
#if NAZARA_DEBUG
|
||||
if (NzContext::GetCurrent() == nullptr)
|
||||
{
|
||||
NazaraError("No active context");
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
glClearDepth(depth);
|
||||
}
|
||||
|
||||
void NzRenderer::SetClearStencil(unsigned int value)
|
||||
{
|
||||
#if NAZARA_DEBUG
|
||||
if (NzContext::GetCurrent() == nullptr)
|
||||
{
|
||||
NazaraError("No active context");
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
glClearStencil(value);
|
||||
}
|
||||
|
||||
bool NzRenderer::SetIndexBuffer(const NzIndexBuffer* indexBuffer)
|
||||
{
|
||||
if (indexBuffer == m_indexBuffer)
|
||||
return true;
|
||||
|
||||
// OpenGL ne nécessite pas de débinder un index buffer pour ne pas l'utiliser
|
||||
if (indexBuffer)
|
||||
indexBuffer->GetBuffer()->m_impl->Bind();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool NzRenderer::SetShader(NzShader* shader)
|
||||
{
|
||||
if (shader == m_shader)
|
||||
return true;
|
||||
|
||||
if (shader)
|
||||
{
|
||||
#if NAZARA_RENDERER_SAFE
|
||||
if (!shader->IsCompiled())
|
||||
{
|
||||
NazaraError("Shader is not compiled");
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (!shader->m_impl->Bind())
|
||||
{
|
||||
NazaraError("Failed to bind shader");
|
||||
return false;
|
||||
}
|
||||
|
||||
m_shader = shader;
|
||||
}
|
||||
else if (m_shader)
|
||||
{
|
||||
m_shader->m_impl->Unbind();
|
||||
m_shader = nullptr;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool NzRenderer::SetTarget(NzRenderTarget* target)
|
||||
{
|
||||
if (target == m_target)
|
||||
return true;
|
||||
|
||||
#if NAZARA_RENDERER_SAFE
|
||||
if (target && !target->CanActivate())
|
||||
{
|
||||
NazaraError("Target cannot be activated");
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (m_target && !m_target->HasContext())
|
||||
m_target->Desactivate();
|
||||
|
||||
if (target)
|
||||
{
|
||||
if (target->Activate())
|
||||
m_target = target;
|
||||
else
|
||||
{
|
||||
NazaraError("Failed to activate target");
|
||||
m_target = nullptr;
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else
|
||||
m_target = nullptr;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool NzRenderer::SetVertexBuffer(const NzVertexBuffer* vertexBuffer)
|
||||
{
|
||||
if (m_vertexBuffer == vertexBuffer)
|
||||
return true;
|
||||
|
||||
m_vertexBuffer = vertexBuffer;
|
||||
m_vertexBufferUpdated = false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void NzRenderer::Uninitialize()
|
||||
{
|
||||
NzOpenGL::Uninitialize();
|
||||
}
|
||||
|
||||
#if NAZARA_RENDERER_SINGLETON
|
||||
void NzRenderer::Destroy()
|
||||
{
|
||||
delete s_instance;
|
||||
s_instance = nullptr;
|
||||
}
|
||||
#endif
|
||||
|
||||
NzRenderer* NzRenderer::Instance()
|
||||
{
|
||||
#if NAZARA_RENDERER_SINGLETON
|
||||
if (!s_instance)
|
||||
s_instance = new NzRenderer;
|
||||
#elif defined(NAZARA_DEBUG)
|
||||
if (!s_instance)
|
||||
NazaraError("Renderer not instanced");
|
||||
#endif
|
||||
|
||||
return s_instance;
|
||||
}
|
||||
|
||||
NzRenderer* NzRenderer::s_instance = nullptr;
|
||||
391
src/Nazara/Renderer/Shader.cpp
Normal file
391
src/Nazara/Renderer/Shader.cpp
Normal file
@@ -0,0 +1,391 @@
|
||||
// Copyright (C) 2012 Jérôme Leclercq
|
||||
// This file is part of the "Nazara Engine".
|
||||
// For conditions of distribution and use, see copyright notice in Config.hpp
|
||||
|
||||
#include <Nazara/Renderer/OpenGL.hpp>
|
||||
#include <Nazara/Renderer/Shader.hpp>
|
||||
#include <Nazara/Core/Error.hpp>
|
||||
#include <Nazara/Core/File.hpp>
|
||||
#include <Nazara/Core/String.hpp>
|
||||
#include <Nazara/Renderer/GLSLShader.hpp>
|
||||
#include <Nazara/Renderer/Renderer.hpp>
|
||||
#include <Nazara/Renderer/ShaderImpl.hpp>
|
||||
#include <stdexcept>
|
||||
#include <Nazara/Renderer/Debug.hpp>
|
||||
|
||||
NzShader::NzShader() :
|
||||
m_impl(nullptr),
|
||||
m_compiled(false)
|
||||
{
|
||||
}
|
||||
|
||||
NzShader::NzShader(nzShaderLanguage language) :
|
||||
m_impl(nullptr),
|
||||
m_compiled(false)
|
||||
{
|
||||
Create(language);
|
||||
|
||||
#if NAZARA_DEBUG
|
||||
if (!m_impl)
|
||||
{
|
||||
NazaraError("Failed to create shader");
|
||||
throw std::runtime_error("Constructor failed");
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
NzShader::~NzShader()
|
||||
{
|
||||
Destroy();
|
||||
}
|
||||
|
||||
bool NzShader::Create(nzShaderLanguage language)
|
||||
{
|
||||
Destroy();
|
||||
|
||||
switch (language)
|
||||
{
|
||||
case nzShaderLanguage_Cg:
|
||||
NazaraError("Cg support is not implemented yet");
|
||||
return false;
|
||||
|
||||
case nzShaderLanguage_GLSL:
|
||||
m_impl = new NzGLSLShader(this);
|
||||
break;
|
||||
|
||||
default:
|
||||
NazaraError("Shader language not handled (0x" + NzString::Number(language, 16) + ')');
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!m_impl->Create())
|
||||
{
|
||||
NazaraError("Failed to create shader");
|
||||
delete m_impl;
|
||||
m_impl = nullptr;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool NzShader::Compile()
|
||||
{
|
||||
#if NAZARA_RENDERER_SAFE
|
||||
if (!m_impl)
|
||||
{
|
||||
NazaraError("Shader not created");
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (m_impl->Compile())
|
||||
{
|
||||
m_compiled = true;
|
||||
return true;
|
||||
}
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
void NzShader::Destroy()
|
||||
{
|
||||
if (m_impl)
|
||||
{
|
||||
m_impl->Destroy();
|
||||
delete m_impl;
|
||||
m_impl = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
NzString NzShader::GetLog() const
|
||||
{
|
||||
#if NAZARA_RENDERER_SAFE
|
||||
if (!m_impl)
|
||||
{
|
||||
NzString error = "Shader not created";
|
||||
NazaraError(error);
|
||||
|
||||
return error;
|
||||
}
|
||||
#endif
|
||||
|
||||
return m_impl->GetLog();
|
||||
}
|
||||
|
||||
nzShaderLanguage NzShader::GetLanguage() const
|
||||
{
|
||||
#if NAZARA_RENDERER_SAFE
|
||||
if (!m_impl)
|
||||
{
|
||||
NzString error = "Shader not created";
|
||||
NazaraError(error);
|
||||
|
||||
return nzShaderLanguage_Unknown;
|
||||
}
|
||||
#endif
|
||||
|
||||
return m_impl->GetLanguage();
|
||||
}
|
||||
|
||||
NzString NzShader::GetSourceCode(nzShaderType type) const
|
||||
{
|
||||
#if NAZARA_RENDERER_SAFE
|
||||
if (!m_impl)
|
||||
{
|
||||
NzString error = "Shader not created";
|
||||
NazaraError(error);
|
||||
|
||||
return error;
|
||||
}
|
||||
|
||||
if (!IsTypeSupported(type))
|
||||
{
|
||||
NzString error = "Shader type not supported";
|
||||
NazaraError(error);
|
||||
|
||||
return error;
|
||||
}
|
||||
|
||||
if (!m_impl->IsLoaded(type))
|
||||
{
|
||||
NzString error = "Shader not loaded";
|
||||
NazaraError(error);
|
||||
|
||||
return error;
|
||||
}
|
||||
#endif
|
||||
|
||||
return m_impl->GetSourceCode(type);
|
||||
}
|
||||
|
||||
bool NzShader::IsCompiled() const
|
||||
{
|
||||
#if NAZARA_RENDERER_SAFE
|
||||
if (!m_impl)
|
||||
{
|
||||
NazaraError("Shader not created");
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
|
||||
return m_compiled;
|
||||
}
|
||||
|
||||
bool NzShader::IsLoaded(nzShaderType type) const
|
||||
{
|
||||
#if NAZARA_RENDERER_SAFE
|
||||
if (!m_impl)
|
||||
{
|
||||
NazaraError("Shader not created");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!IsTypeSupported(type))
|
||||
{
|
||||
NazaraError("Shader type not supported");
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
|
||||
return m_impl->IsLoaded(type);
|
||||
}
|
||||
|
||||
bool NzShader::Load(nzShaderType type, const NzString& source)
|
||||
{
|
||||
#if NAZARA_RENDERER_SAFE
|
||||
if (!m_impl)
|
||||
{
|
||||
NazaraError("Shader not created");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!IsTypeSupported(type))
|
||||
{
|
||||
NazaraError("Shader type not supported");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (source.IsEmpty())
|
||||
{
|
||||
NazaraError("Empty source code");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (m_impl->IsLoaded(type))
|
||||
{
|
||||
NazaraError("Shader already loaded");
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
|
||||
return m_impl->Load(type, source);
|
||||
}
|
||||
|
||||
bool NzShader::LoadFromFile(nzShaderType type, const NzString& filePath)
|
||||
{
|
||||
#if NAZARA_RENDERER_SAFE
|
||||
if (!m_impl)
|
||||
{
|
||||
NazaraError("Shader not created");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!IsTypeSupported(type))
|
||||
{
|
||||
NazaraError("Shader type not supported");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (m_impl->IsLoaded(type))
|
||||
{
|
||||
NazaraError("Shader already loaded");
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
|
||||
NzFile file(filePath);
|
||||
if (!file.Open(NzFile::ReadOnly | NzFile::Text))
|
||||
{
|
||||
NazaraError("Failed to open \"" + filePath + '"');
|
||||
return false;
|
||||
}
|
||||
|
||||
NzString source;
|
||||
unsigned int length = file.GetSize();
|
||||
source.Resize(length);
|
||||
|
||||
if (file.Read(&source[0], sizeof(char), length) != length*sizeof(char))
|
||||
{
|
||||
NazaraError("Failed to read shader file");
|
||||
return false;
|
||||
}
|
||||
|
||||
file.Close();
|
||||
|
||||
return m_impl->Load(type, source);
|
||||
}
|
||||
|
||||
bool NzShader::SendBoolean(const NzString& name, bool value)
|
||||
{
|
||||
#if NAZARA_RENDERER_SAFE
|
||||
if (!m_impl)
|
||||
{
|
||||
NazaraError("Shader not created");
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
|
||||
return m_impl->SendBoolean(name, value);
|
||||
}
|
||||
|
||||
bool NzShader::SendDouble(const NzString& name, double value)
|
||||
{
|
||||
#if NAZARA_RENDERER_SAFE
|
||||
if (!m_impl)
|
||||
{
|
||||
NazaraError("Shader not created");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!NazaraRenderer->HasCapability(nzRendererCap_FP64))
|
||||
{
|
||||
NazaraError("FP64 is not supported");
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
|
||||
return m_impl->SendDouble(name, value);
|
||||
}
|
||||
|
||||
bool NzShader::SendFloat(const NzString& name, float value)
|
||||
{
|
||||
#if NAZARA_RENDERER_SAFE
|
||||
if (!m_impl)
|
||||
{
|
||||
NazaraError("Shader not created");
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
|
||||
return m_impl->SendFloat(name, value);
|
||||
}
|
||||
|
||||
bool NzShader::SendInteger(const NzString& name, int value)
|
||||
{
|
||||
#if NAZARA_RENDERER_SAFE
|
||||
if (!m_impl)
|
||||
{
|
||||
NazaraError("Shader not created");
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
|
||||
return m_impl->SendInteger(name, value);
|
||||
}
|
||||
|
||||
bool NzShader::SendMatrix(const NzString& name, const NzMatrix4d& matrix)
|
||||
{
|
||||
#if NAZARA_RENDERER_SAFE
|
||||
if (!m_impl)
|
||||
{
|
||||
NazaraError("Shader not created");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!NazaraRenderer->HasCapability(nzRendererCap_FP64))
|
||||
{
|
||||
NazaraError("FP64 is not supported");
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
|
||||
return m_impl->SendMatrix(name, matrix);
|
||||
}
|
||||
|
||||
bool NzShader::SendMatrix(const NzString& name, const NzMatrix4f& matrix)
|
||||
{
|
||||
#if NAZARA_RENDERER_SAFE
|
||||
if (!m_impl)
|
||||
{
|
||||
NazaraError("Shader not created");
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
|
||||
return m_impl->SendMatrix(name, matrix);
|
||||
}
|
||||
|
||||
bool NzShader::IsLanguageSupported(nzShaderLanguage language)
|
||||
{
|
||||
switch (language)
|
||||
{
|
||||
case nzShaderLanguage_Cg:
|
||||
return false; // ??
|
||||
|
||||
case nzShaderLanguage_GLSL:
|
||||
return true;
|
||||
|
||||
default:
|
||||
NazaraError("Shader language not handled (0x" + NzString::Number(language, 16) + ')');
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
bool NzShader::IsTypeSupported(nzShaderType type)
|
||||
{
|
||||
switch (type)
|
||||
{
|
||||
case nzShaderType_Fragment:
|
||||
case nzShaderType_Vertex:
|
||||
return true;
|
||||
|
||||
case nzShaderType_Geometry:
|
||||
return false; // ??
|
||||
|
||||
default:
|
||||
NazaraError("Shader type not handled (0x" + NzString::Number(type, 16) + ')');
|
||||
return false;
|
||||
}
|
||||
}
|
||||
7
src/Nazara/Renderer/ShaderImpl.cpp
Normal file
7
src/Nazara/Renderer/ShaderImpl.cpp
Normal file
@@ -0,0 +1,7 @@
|
||||
// Copyright (C) 2012 Jérôme Leclercq
|
||||
// This file is part of the "Nazara Engine".
|
||||
// For conditions of distribution and use, see copyright notice in Config.hpp
|
||||
|
||||
#include <Nazara/Renderer/ShaderImpl.hpp>
|
||||
|
||||
NzShaderImpl::~NzShaderImpl() = default;
|
||||
43
src/Nazara/Renderer/ShaderImpl.hpp
Normal file
43
src/Nazara/Renderer/ShaderImpl.hpp
Normal file
@@ -0,0 +1,43 @@
|
||||
// Copyright (C) 2012 Jérôme Leclercq
|
||||
// This file is part of the "Nazara Engine".
|
||||
// For conditions of distribution and use, see copyright notice in Config.hpp
|
||||
|
||||
#pragma once
|
||||
|
||||
#ifndef NAZARA_SHADERIMPL_HPP
|
||||
#define NAZARA_SHADERIMPL_HPP
|
||||
|
||||
#include <Nazara/Renderer/Shader.hpp>
|
||||
|
||||
class NzShaderImpl
|
||||
{
|
||||
public:
|
||||
NzShaderImpl() = default;
|
||||
virtual ~NzShaderImpl();
|
||||
|
||||
virtual bool Bind() = 0;
|
||||
|
||||
virtual bool Compile() = 0;
|
||||
virtual bool Create() = 0;
|
||||
|
||||
virtual void Destroy() = 0;
|
||||
|
||||
virtual NzString GetLog() const = 0;
|
||||
virtual nzShaderLanguage GetLanguage() const = 0;
|
||||
virtual NzString GetSourceCode(nzShaderType type) const = 0;
|
||||
|
||||
virtual bool IsLoaded(nzShaderType type) const = 0;
|
||||
|
||||
virtual bool Load(nzShaderType type, const NzString& source) = 0;
|
||||
|
||||
virtual bool SendBoolean(const NzString& name, bool value) = 0;
|
||||
virtual bool SendDouble(const NzString& name, double value) = 0;
|
||||
virtual bool SendFloat(const NzString& name, float value) = 0;
|
||||
virtual bool SendInteger(const NzString& name, int value) = 0;
|
||||
virtual bool SendMatrix(const NzString& name, const NzMatrix4d& matrix) = 0;
|
||||
virtual bool SendMatrix(const NzString& name, const NzMatrix4f& matrix) = 0;
|
||||
|
||||
virtual void Unbind() = 0;
|
||||
};
|
||||
|
||||
#endif // NAZARA_SHADERIMPL_HPP
|
||||
113
src/Nazara/Renderer/SoftwareBuffer.cpp
Normal file
113
src/Nazara/Renderer/SoftwareBuffer.cpp
Normal file
@@ -0,0 +1,113 @@
|
||||
// Copyright (C) 2012 Jérôme Leclercq
|
||||
// This file is part of the "Nazara Engine".
|
||||
// For conditions of distribution and use, see copyright notice in Config.hpp
|
||||
|
||||
#include <Nazara/Renderer/OpenGL.hpp>
|
||||
#include <Nazara/Renderer/SoftwareBuffer.hpp>
|
||||
#include <Nazara/Core/Error.hpp>
|
||||
#include <cstring>
|
||||
#include <stdexcept>
|
||||
#include <Nazara/Renderer/Debug.hpp>
|
||||
|
||||
namespace
|
||||
{
|
||||
GLenum bufferTarget[] = {
|
||||
GL_ELEMENT_ARRAY_BUFFER, // nzBufferType_Index,
|
||||
GL_ARRAY_BUFFER, // nzBufferType_Vertex
|
||||
};
|
||||
}
|
||||
|
||||
NzSoftwareBuffer::NzSoftwareBuffer(NzBuffer* parent, nzBufferType type) :
|
||||
m_type(type)
|
||||
{
|
||||
NazaraUnused(parent);
|
||||
}
|
||||
|
||||
NzSoftwareBuffer::~NzSoftwareBuffer()
|
||||
{
|
||||
}
|
||||
|
||||
void NzSoftwareBuffer::Bind()
|
||||
{
|
||||
glBindBuffer(bufferTarget[m_type], 0);
|
||||
}
|
||||
|
||||
bool NzSoftwareBuffer::Create(unsigned int length, nzUInt8 typeSize, nzBufferUsage usage)
|
||||
{
|
||||
NazaraUnused(usage);
|
||||
|
||||
// Cette allocation est protégée car sa taille dépend directement de paramètres utilisateurs
|
||||
try
|
||||
{
|
||||
m_buffer = new nzUInt8[length*typeSize];
|
||||
}
|
||||
catch (const std::exception& e)
|
||||
{
|
||||
NazaraError("Failed to allocate software buffer (" + NzString(e.what()) + ')');
|
||||
return false;
|
||||
}
|
||||
|
||||
m_length = length;
|
||||
m_locked = false;
|
||||
m_typeSize = typeSize;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void NzSoftwareBuffer::Destroy()
|
||||
{
|
||||
delete[] m_buffer;
|
||||
}
|
||||
|
||||
bool NzSoftwareBuffer::Fill(const void* data, unsigned int offset, unsigned int length)
|
||||
{
|
||||
#if NAZARA_RENDERER_SAFE
|
||||
if (m_locked)
|
||||
{
|
||||
NazaraError("Buffer already locked");
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
|
||||
std::memcpy(&m_buffer[offset*m_typeSize], data, length*m_typeSize);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool NzSoftwareBuffer::IsHardware() const
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
void* NzSoftwareBuffer::Lock(nzBufferLock lock, unsigned int offset, unsigned int length)
|
||||
{
|
||||
NazaraUnused(length);
|
||||
NazaraUnused(lock);
|
||||
|
||||
#if NAZARA_RENDERER_SAFE
|
||||
if (m_locked)
|
||||
{
|
||||
NazaraError("Buffer already locked");
|
||||
return nullptr;
|
||||
}
|
||||
#endif
|
||||
|
||||
m_locked = true;
|
||||
|
||||
return &m_buffer[offset*m_typeSize];
|
||||
}
|
||||
|
||||
bool NzSoftwareBuffer::Unlock()
|
||||
{
|
||||
#if NAZARA_RENDERER_SAFE
|
||||
if (!m_locked)
|
||||
{
|
||||
NazaraError("Buffer not locked");
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
|
||||
m_locked = false;
|
||||
|
||||
return true;
|
||||
}
|
||||
39
src/Nazara/Renderer/SoftwareBuffer.hpp
Normal file
39
src/Nazara/Renderer/SoftwareBuffer.hpp
Normal file
@@ -0,0 +1,39 @@
|
||||
// Copyright (C) 2012 Jérôme Leclercq
|
||||
// This file is part of the "Nazara Engine".
|
||||
// For conditions of distribution and use, see copyright notice in Config.hpp
|
||||
|
||||
#pragma once
|
||||
|
||||
#ifndef NAZARA_SOFTWAREBUFFER_HPP
|
||||
#define NAZARA_SOFTWAREBUFFER_HPP
|
||||
|
||||
#include <Nazara/Prerequesites.hpp>
|
||||
#include <Nazara/Renderer/BufferImpl.hpp>
|
||||
|
||||
class NzSoftwareBuffer : public NzBufferImpl
|
||||
{
|
||||
public:
|
||||
NzSoftwareBuffer(NzBuffer* parent, nzBufferType type);
|
||||
~NzSoftwareBuffer();
|
||||
|
||||
void Bind();
|
||||
|
||||
bool Create(unsigned int length, nzUInt8 typeSize, nzBufferUsage usage = nzBufferUsage_Static);
|
||||
void Destroy();
|
||||
|
||||
bool Fill(const void* data, unsigned int offset, unsigned int length);
|
||||
|
||||
bool IsHardware() const;
|
||||
|
||||
void* Lock(nzBufferLock lock, unsigned int offset = 0, unsigned int length = 0);
|
||||
bool Unlock();
|
||||
|
||||
private:
|
||||
nzBufferType m_type;
|
||||
nzUInt8 m_typeSize;
|
||||
nzUInt8* m_buffer;
|
||||
bool m_locked;
|
||||
unsigned int m_length;
|
||||
};
|
||||
|
||||
#endif // NAZARA_SOFTWAREBUFFER_HPP
|
||||
106
src/Nazara/Renderer/VertexBuffer.cpp
Normal file
106
src/Nazara/Renderer/VertexBuffer.cpp
Normal file
@@ -0,0 +1,106 @@
|
||||
// Copyright (C) 2012 Jérôme Leclercq
|
||||
// This file is part of the "Nazara Engine".
|
||||
// For conditions of distribution and use, see copyright notice in Config.hpp
|
||||
|
||||
#include <Nazara/Renderer/VertexBuffer.hpp>
|
||||
#include <Nazara/Core/Error.hpp>
|
||||
#include <Nazara/Renderer/Debug.hpp>
|
||||
|
||||
NzVertexBuffer::NzVertexBuffer(NzBuffer* buffer, unsigned int startVertex, unsigned int vertexCount) :
|
||||
m_buffer(buffer),
|
||||
m_ownsBuffer(false),
|
||||
m_startVertex(startVertex),
|
||||
m_vertexCount(vertexCount)
|
||||
{
|
||||
m_buffer->AddResourceReference();
|
||||
}
|
||||
|
||||
NzVertexBuffer::NzVertexBuffer(unsigned int length, nzUInt8 typeSize, nzBufferUsage usage) :
|
||||
m_ownsBuffer(true),
|
||||
m_startVertex(0),
|
||||
m_vertexCount(length)
|
||||
{
|
||||
m_buffer = new NzBuffer(nzBufferType_Vertex, length, typeSize, usage);
|
||||
m_buffer->AddResourceReference();
|
||||
m_buffer->SetPersistent(false);
|
||||
}
|
||||
|
||||
NzVertexBuffer::NzVertexBuffer(const NzVertexBuffer& vertexBuffer) :
|
||||
m_ownsBuffer(vertexBuffer.m_ownsBuffer),
|
||||
m_startVertex(vertexBuffer.m_startVertex),
|
||||
m_vertexCount(vertexBuffer.m_vertexCount)
|
||||
{
|
||||
if (m_ownsBuffer)
|
||||
{
|
||||
m_buffer = new NzBuffer(nzBufferType_Vertex, vertexBuffer.m_buffer->GetLength(), vertexBuffer.m_buffer->GetSize(), vertexBuffer.m_buffer->GetUsage());
|
||||
m_buffer->AddResourceReference();
|
||||
m_buffer->SetPersistent(false);
|
||||
m_buffer->CopyContent(*vertexBuffer.m_buffer);
|
||||
}
|
||||
else
|
||||
{
|
||||
m_buffer = vertexBuffer.m_buffer;
|
||||
m_buffer->AddResourceReference();
|
||||
}
|
||||
}
|
||||
|
||||
NzVertexBuffer::~NzVertexBuffer()
|
||||
{
|
||||
m_buffer->RemoveResourceReference();
|
||||
}
|
||||
|
||||
bool NzVertexBuffer::Fill(const void* data, unsigned int offset, unsigned int length)
|
||||
{
|
||||
#if NAZARA_RENDERER_SAFE
|
||||
if (offset+length > m_vertexCount)
|
||||
{
|
||||
NazaraError("Exceeding virtual buffer size");
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
|
||||
return m_buffer->Fill(data, m_startVertex+offset, length);
|
||||
}
|
||||
|
||||
NzBuffer* NzVertexBuffer::GetBuffer() const
|
||||
{
|
||||
return m_buffer;
|
||||
}
|
||||
|
||||
unsigned int NzVertexBuffer::GetStartVertex() const
|
||||
{
|
||||
return m_startVertex;
|
||||
}
|
||||
|
||||
nzUInt8 NzVertexBuffer::GetTypeSize() const
|
||||
{
|
||||
return m_buffer->GetTypeSize();
|
||||
}
|
||||
|
||||
unsigned int NzVertexBuffer::GetVertexCount() const
|
||||
{
|
||||
return m_vertexCount;
|
||||
}
|
||||
|
||||
bool NzVertexBuffer::IsHardware() const
|
||||
{
|
||||
return m_buffer->IsHardware();
|
||||
}
|
||||
|
||||
void* NzVertexBuffer::Lock(nzBufferLock lock, unsigned int offset, unsigned int length)
|
||||
{
|
||||
#if NAZARA_RENDERER_SAFE
|
||||
if (offset+length > m_vertexCount)
|
||||
{
|
||||
NazaraError("Exceeding virtual buffer size");
|
||||
return nullptr;
|
||||
}
|
||||
#endif
|
||||
|
||||
return m_buffer->Lock(lock, m_startVertex+offset, (length) ? length : m_vertexCount-offset);
|
||||
}
|
||||
|
||||
bool NzVertexBuffer::Unlock()
|
||||
{
|
||||
return m_buffer->Unlock();
|
||||
}
|
||||
126
src/Nazara/Renderer/VertexDeclaration.cpp
Normal file
126
src/Nazara/Renderer/VertexDeclaration.cpp
Normal file
@@ -0,0 +1,126 @@
|
||||
// Copyright (C) 2012 Jérôme Leclercq
|
||||
// This file is part of the "Nazara Engine".
|
||||
// For conditions of distribution and use, see copyright notice in Config.hpp
|
||||
|
||||
#include <Nazara/Renderer/VertexDeclaration.hpp>
|
||||
#include <Nazara/Core/Error.hpp>
|
||||
#include <Nazara/Renderer/Renderer.hpp>
|
||||
#include <Nazara/Renderer/Debug.hpp>
|
||||
|
||||
namespace
|
||||
{
|
||||
const unsigned int size[] =
|
||||
{
|
||||
4, // nzElementType_Color
|
||||
8, // nzElementType_Double1
|
||||
16, // nzElementType_Double2
|
||||
24, // nzElementType_Double3
|
||||
32, // nzElementType_Double4
|
||||
4, // nzElementType_Float1
|
||||
8, // nzElementType_Float2
|
||||
12, // nzElementType_Float3
|
||||
16 // nzElementType_Float4
|
||||
};
|
||||
}
|
||||
|
||||
bool NzVertexDeclaration::Create(const NzVertexElement* elements, unsigned int elementCount)
|
||||
{
|
||||
for (unsigned int i = 0; i < elementCount; ++i)
|
||||
{
|
||||
unsigned int stream = elements[i].stream;
|
||||
|
||||
if (stream >= m_streams.size())
|
||||
m_streams.resize(stream+1);
|
||||
#if NAZARA_RENDERER_SAFE
|
||||
else // Seulement si le stream ne vient pas d'être créé (Autrement c'est inutile)
|
||||
{
|
||||
bool fp64 = NazaraRenderer->HasCapability(nzRendererCap_FP64);
|
||||
|
||||
for (unsigned int j = 0; j < i; ++j)
|
||||
{
|
||||
if (elements[j].stream == stream && elements[j].usage == elements[i].usage && elements[j].usageIndex == elements[i].usageIndex)
|
||||
{
|
||||
NazaraError("Element usage (" + NzString::Number(elements[j].usage, 16) + ") collision on stream " + NzString::Number(stream) + " with usage index " + NzString::Number(elements[j].usageIndex));
|
||||
return false;
|
||||
}
|
||||
else if (!fp64 && elements[j].type >= nzElementType_Double1 && elements[j].type <= nzElementType_Double4)
|
||||
{
|
||||
NazaraError("FP64 not supported");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
Element element;
|
||||
element.offset = elements[i].offset;
|
||||
element.type = elements[i].type;
|
||||
element.usage = elements[i].usage;
|
||||
element.usageIndex = elements[i].usageIndex;
|
||||
|
||||
m_streams[stream].elements.push_back(element);
|
||||
}
|
||||
|
||||
for (Stream& stream : m_streams)
|
||||
{
|
||||
stream.stride = 0;
|
||||
for (const Element& element : stream.elements)
|
||||
stream.stride += size[element.type];
|
||||
|
||||
#if NAZARA_RENDERER_FORCE_DECLARATION_STRIDE_MULTIPLE_OF_32
|
||||
stream.stride = ((static_cast<int>(stream.stride)-1)/32+1)*32;
|
||||
#endif
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
const NzVertexDeclaration::Element* NzVertexDeclaration::GetElement(unsigned int i, unsigned int stream) const
|
||||
{
|
||||
#if NAZARA_RENDERER_SAFE
|
||||
if (stream >= m_streams.size())
|
||||
{
|
||||
NazaraError("Stream out of range");
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
if (i >= m_streams[stream].elements.size())
|
||||
{
|
||||
NazaraError("Index out of range");
|
||||
return nullptr;
|
||||
}
|
||||
#endif
|
||||
|
||||
return &m_streams[stream].elements[i];
|
||||
}
|
||||
|
||||
unsigned int NzVertexDeclaration::GetElementCount(unsigned int stream) const
|
||||
{
|
||||
#if NAZARA_RENDERER_SAFE
|
||||
if (stream >= m_streams.size())
|
||||
{
|
||||
NazaraError("Stream out of range");
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
return m_streams[stream].elements.size();
|
||||
}
|
||||
|
||||
unsigned int NzVertexDeclaration::GetStreamCount() const
|
||||
{
|
||||
return m_streams.size();
|
||||
}
|
||||
|
||||
unsigned int NzVertexDeclaration::GetStride(unsigned int stream) const
|
||||
{
|
||||
#if NAZARA_RENDERER_SAFE
|
||||
if (stream >= m_streams.size())
|
||||
{
|
||||
NazaraError("Stream out of range");
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
return m_streams[stream].stride;
|
||||
}
|
||||
257
src/Nazara/Renderer/Win32/ContextImpl.cpp
Normal file
257
src/Nazara/Renderer/Win32/ContextImpl.cpp
Normal file
@@ -0,0 +1,257 @@
|
||||
// Copyright (C) 2012 Jérôme Leclercq
|
||||
// This file is part of the "Nazara Engine".
|
||||
// For conditions of distribution and use, see copyright notice in Config.hpp
|
||||
|
||||
// Code inspiré de NeHe (Lesson1) et de la SFML par Laurent Gomila
|
||||
|
||||
#include <Nazara/Renderer/OpenGL.hpp>
|
||||
#include <Nazara/Renderer/Win32/ContextImpl.hpp>
|
||||
#include <Nazara/Core/Error.hpp>
|
||||
#include <Nazara/Core/Lock.hpp>
|
||||
#include <Nazara/Core/Mutex.hpp>
|
||||
#include <Nazara/Renderer/Context.hpp>
|
||||
#include <cstring>
|
||||
#include <iostream>
|
||||
|
||||
NzContextImpl::NzContextImpl()
|
||||
{
|
||||
}
|
||||
|
||||
bool NzContextImpl::Activate()
|
||||
{
|
||||
return wglMakeCurrent(m_deviceContext, m_context);
|
||||
}
|
||||
|
||||
bool NzContextImpl::Create(NzContextParameters& parameters)
|
||||
{
|
||||
if (parameters.window)
|
||||
{
|
||||
m_window = static_cast<HWND>(parameters.window);
|
||||
m_ownsWindow = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_window = CreateWindowA("STATIC", nullptr, WS_DISABLED | WS_POPUP, 0, 0, 1, 1, nullptr, nullptr, GetModuleHandle(nullptr), nullptr);
|
||||
ShowWindow(m_window, SW_HIDE);
|
||||
m_ownsWindow = true;
|
||||
|
||||
if (!m_window)
|
||||
{
|
||||
NazaraError("Failed to create window");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
m_deviceContext = GetDC(m_window);
|
||||
if (!m_deviceContext)
|
||||
{
|
||||
NazaraError("Failed to get device context");
|
||||
Destroy();
|
||||
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);
|
||||
}
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
NazaraError("Failed to choose pixel format");
|
||||
Destroy();
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (!SetPixelFormat(m_deviceContext, pixelFormat, &descriptor))
|
||||
{
|
||||
NazaraError("Failed to set pixel format");
|
||||
Destroy();
|
||||
return false;
|
||||
}
|
||||
|
||||
// Arrivé ici, tout est créé, nous récupérons donc les paramètres actuels du 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;
|
||||
|
||||
std::cout << "Context version: " << (int) parameters.majorVersion << '.' << (int) parameters.minorVersion << std::endl;
|
||||
std::cout << "Active context: " << wglGetCurrentContext() << std::endl;
|
||||
|
||||
m_context = nullptr;
|
||||
if (wglCreateContextAttribs)
|
||||
{
|
||||
std::cout << "wglCreateContextAttribs" << std::endl;
|
||||
|
||||
/*int attributes[] = {
|
||||
WGL_CONTEXT_MAJOR_VERSION_ARB, parameters.majorVersion,
|
||||
WGL_CONTEXT_MINOR_VERSION_ARB, parameters.minorVersion,
|
||||
WGL_CONTEXT_FLAGS_ARB, (parameters.compatibilityProfile) ? 0 : WGL_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB,
|
||||
WGL_CONTEXT_PROFILE_MASK_ARB, (parameters.compatibilityProfile) ? WGL_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB : WGL_CONTEXT_CORE_PROFILE_BIT_ARB,
|
||||
0
|
||||
};*/
|
||||
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;
|
||||
if (parameters.compatibilityProfile)
|
||||
*attrib++ = WGL_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB;
|
||||
else
|
||||
{
|
||||
*attrib++ = WGL_CONTEXT_CORE_PROFILE_BIT_ARB;
|
||||
|
||||
*attrib++ = WGL_CONTEXT_FLAGS_ARB;
|
||||
*attrib++ = WGL_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB;
|
||||
}
|
||||
}
|
||||
|
||||
*attrib++ = 0;
|
||||
|
||||
m_context = wglCreateContextAttribs(m_deviceContext, shareContext, attributes);
|
||||
|
||||
if (m_context)
|
||||
std::cout << "Context created with success ! Pointer: " << m_context << std::endl;
|
||||
else
|
||||
std::cout << "wglCreateContextAttribs failed ! (glGetError(): " << glGetError() << ") " << std::endl;
|
||||
}
|
||||
|
||||
if (!m_context)
|
||||
{
|
||||
std::cout << "wglCreateContext" << std::endl;
|
||||
|
||||
m_context = wglCreateContext(m_deviceContext);
|
||||
if (m_context)
|
||||
std::cout << "Context created with success ! Pointer: " << m_context << std::endl;
|
||||
else
|
||||
std::cout << "wglCreateContext failed ! (glGetError(): " << glGetError() << ") " << std::endl;
|
||||
|
||||
if (shareContext)
|
||||
{
|
||||
std::cout << "Sharing context with context " << shareContext << std::endl;
|
||||
// wglShareLists n'est pas thread-safe (source: SFML)
|
||||
static NzMutex mutex;
|
||||
NzLock lock(mutex);
|
||||
|
||||
if (wglShareLists(shareContext, m_context))
|
||||
std::cout << "Success !" << std::endl;
|
||||
else
|
||||
{
|
||||
std::cout << "Failed !" << std::endl;
|
||||
NazaraWarning("Failed to share the context: " + NzGetLastSystemError());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!m_context)
|
||||
{
|
||||
NazaraError("Failed to create context");
|
||||
Destroy();
|
||||
return false;
|
||||
}
|
||||
|
||||
std::cout << std::endl;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void NzContextImpl::Destroy()
|
||||
{
|
||||
if (m_context)
|
||||
wglDeleteContext(m_context);
|
||||
|
||||
if (m_deviceContext)
|
||||
ReleaseDC(m_window, m_deviceContext);
|
||||
|
||||
if (m_ownsWindow)
|
||||
DestroyWindow(m_window);
|
||||
}
|
||||
|
||||
bool NzContextImpl::IsActive() const
|
||||
{
|
||||
return wglGetCurrentContext() == m_context;
|
||||
}
|
||||
|
||||
void NzContextImpl::SwapBuffers()
|
||||
{
|
||||
::SwapBuffers(m_deviceContext);
|
||||
}
|
||||
|
||||
bool NzContextImpl::Desactivate()
|
||||
{
|
||||
return wglMakeCurrent(nullptr, nullptr);
|
||||
}
|
||||
|
||||
33
src/Nazara/Renderer/Win32/ContextImpl.hpp
Normal file
33
src/Nazara/Renderer/Win32/ContextImpl.hpp
Normal file
@@ -0,0 +1,33 @@
|
||||
// Copyright (C) 2012 Jérôme Leclercq
|
||||
// This file is part of the "Nazara Engine".
|
||||
// For conditions of distribution and use, see copyright notice in Config.hpp
|
||||
|
||||
#pragma once
|
||||
|
||||
#ifndef NAZARA_CONTEXTIMPL_HPP
|
||||
#define NAZARA_CONTEXTIMPL_HPP
|
||||
|
||||
#include <Nazara/Renderer/ContextParameters.hpp>
|
||||
#include <windows.h>
|
||||
|
||||
class NzContextImpl
|
||||
{
|
||||
public:
|
||||
NzContextImpl();
|
||||
|
||||
bool Activate();
|
||||
bool Create(NzContextParameters& parameters);
|
||||
void Destroy();
|
||||
bool IsActive() const;
|
||||
void SwapBuffers();
|
||||
|
||||
static bool Desactivate();
|
||||
|
||||
private:
|
||||
HDC m_deviceContext;
|
||||
HGLRC m_context;
|
||||
HWND m_window;
|
||||
bool m_ownsWindow;
|
||||
};
|
||||
|
||||
#endif // NAZARA_CONTEXTIMPL_HPP
|
||||
Reference in New Issue
Block a user