Files
NBEngine/engine/NBGraphics/src/Window.cpp
T

151 lines
3.9 KiB
C++

#include <NBGraphics/Window.hpp>
namespace nb {
using GLFWCodes = GLFWError::Codes;
const std::string GLFWError::type = "nb::GLFWError";
const ErrorCodeMap GLFWError::ErrorMessages = {
{GLFWCodes::UNDEFINED, "Error"},
{GLFWCodes::INIT_FAILED, "GLFW initialization failed"},
{GLFWCodes::GLFW_INTIALIZED, "GLFW has already been initialized"},
{GLFWCodes::GLAD_FAILED, "GLAD initialization failed"},
{GLFWCodes::NOT_MAIN, "Action can only be done on main thread"},
{GLFWCodes::WINDOW_FAILED, "Failed to initialize window"}
};
// class OGLWindow
std::atomic<bool> OGLWindow::_glfwInitialized = false;
thread_local GLFWwindow* OGLWindow::_currWindow = nullptr;
thread_local const GLFWwindow* OGLWindow::_currArena = nullptr;
std::atomic<unsigned int> OGLWindow::_count = 0;
bool OGLWindow::InitGLFW(const std::vector<GLFWHint>& hints) {
if (nb::MainTID != GetTID()) {
THROW(GLFWError(GLFWError::NOT_MAIN));
}
if (!IsGLFWInitialized()) {
for (const auto& hint : hints) {
glfwInitHint(hint[0], hint[1]);
}
if (glfwInit()) {
OGLWindow::_glfwInitialized.store(true, std::memory_order_release);
} else {
THROW(GLFWError(GLFWError::INIT_FAILED));
}
}
return IsGLFWInitialized();
}
bool OGLWindow::TerminateGLFW() {
if (nb::MainTID != GetTID()) {
THROW(GLFWError(GLFWError::NOT_MAIN));
}
if (IsGLFWInitialized()) {
glfwTerminate();
OGLWindow::_glfwInitialized.store(false, std::memory_order_release);
}
return !IsGLFWInitialized();
}
GLFWwindow* OGLWindow::MakeCurrent(const std::shared_ptr<OGLWindow>& window) {
auto tmp = _currWindow;
if (window) {
_currWindow = window->getWindowPtr();
_currArena = window->_arena;
} else {
_currWindow = nullptr;
_currArena = nullptr;
}
glfwMakeContextCurrent(_currWindow);
return tmp;
}
OGLWindow::OGLWindow(
unsigned int x,
unsigned int y,
const std::string&,
GLFWwindow* sharingContext
) {
CheckForMainThread();
InitGLFW();
_window_ptr = glfwCreateWindow(
x,
y,
_title.c_str(),
NULL,
sharingContext
);
if (_window_ptr == NULL) {
THROW(GLFWError(GLFWError::Codes::WINDOW_FAILED));
}
_arena = _window_ptr;
auto tmp = makeCurrent();
if (!gladLoadGLLoader((GLADloadproc)glfwGetProcAddress)) {
THROW(GLFWError(GLFWError::Codes::GLAD_FAILED));
}
glfwMakeContextCurrent(tmp);
OGLWindow::_count.fetch_add(1);
}
OGLWindow::~OGLWindow() {
CheckForMainThread();
if (_window_ptr) {
if (_window_ptr == _currWindow) {
_currWindow = nullptr;
_currArena = nullptr;
}
glfwDestroyWindow(_window_ptr);
_count.fetch_add(-1);
if (!_count.load()) {
TerminateGLFW();
}
}
}
void OGLWindow::detachWindow() {
_title = "";
_window_ptr = nullptr;
_arena = nullptr;
}
int OGLWindow::getWindowAttribute(int attr) const {
CheckForMainThread();
return glfwGetWindowAttrib(_window_ptr, attr);
}
std::array<int, 2> OGLWindow::getSize() const {
CheckForMainThread();
int x, y;
glfwGetWindowSize(_window_ptr, &x, &y);
return {x, y};
}
bool OGLWindow::shouldClose() const {
CheckForMainThread();
return glfwWindowShouldClose(_window_ptr);
}
void OGLWindow::shouldClose(bool val) {
CheckForMainThread();
glfwSetWindowShouldClose(_window_ptr, val);
}
GLFWwindow* OGLWindow::makeCurrent() const {
auto tmp = glfwGetCurrentContext();
glfwMakeContextCurrent(_window_ptr);
return tmp;
}
void OGLWindow::setSize(unsigned int x, unsigned int y) {
CheckForMainThread();
glfwSetWindowSize(_window_ptr, x, y);
}
void OGLWindow::setTitle(const std::string& name) {
CheckForMainThread();
_title = name;
glfwSetWindowTitle(_window_ptr, _title.c_str());
}
};