151 lines
3.9 KiB
C++
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());
|
|
}
|
|
|
|
}; |