revamp the gfx+display systems a bit (#739)

* revamp gfx and display systems a bit

* Use some fancy c++ pointers instead of just raw pointers

* Tidy some things up.

* clang

* clang 2

* fixes

* fixesss

* error detection when making display
This commit is contained in:
ManDude
2021-08-10 00:16:39 +01:00
committed by GitHub
parent 95a07558a6
commit a850b5d5cb
12 changed files with 404 additions and 111 deletions
+112 -35
View File
@@ -4,51 +4,128 @@
*/
#include "display.h"
#include "gfx.h"
#include "common/log/log.h"
namespace Display {
/* ****************************** */
/* Internal functions */
/* ****************************** */
GLFWwindow* display = NULL;
namespace {
void InitDisplay(int width, int height, const char* title, GLFWwindow*& d) {
if (d) {
lg::warn("InitDisplay has already created a display window");
return;
}
// request OpenGL 3.0 (placeholder)
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 0);
d = glfwCreateWindow(width, height, title, NULL, NULL);
if (!d) {
lg::error("InitDisplay failed - Could not create display window");
return;
}
glfwMakeContextCurrent(d);
if (!gladLoadGL()) {
lg::error("GL init fail");
KillDisplay(d);
return;
}
// enable vsync by default
glfwSwapInterval(1);
lg::debug("init display #x{}", (uintptr_t)d);
bool renderer_is_correct(const GfxRendererModule* renderer, GfxPipeline pipeline) {
return renderer->pipeline == pipeline;
}
void KillDisplay(GLFWwindow*& d) {
lg::debug("kill display #x{}", (uintptr_t)d);
if (!d) {
lg::warn("KillDisplay called when no display was available");
void set_main_display(std::shared_ptr<GfxDisplay> display) {
if (Display::g_displays.size() > 0) {
Display::g_displays[0] = display;
} else {
Display::g_displays.push_back(display);
}
}
} // namespace
/* ****************************** */
/* GfxDisplay */
/* ****************************** */
GfxDisplay::GfxDisplay(GLFWwindow* a_window) {
set_renderer(GfxPipeline::OpenGL);
set_window(a_window);
}
GfxDisplay::~GfxDisplay() {
m_renderer->kill_display(this);
// window_generic_ptr = nullptr;
}
void GfxDisplay::set_renderer(GfxPipeline pipeline) {
if (is_active()) {
lg::error("Can't change display's renderer while window exists.");
return;
}
if (m_renderer != nullptr) {
lg::error("A display changed renderer unexpectedly.");
return;
}
glfwDestroyWindow(d);
d = NULL;
m_renderer = Gfx::GetRenderer(pipeline);
}
void GfxDisplay::set_window(GLFWwindow* window) {
if (!renderer_is_correct(m_renderer, GfxPipeline::OpenGL)) {
lg::error("Can't set OpenGL window when using {}", m_renderer->name);
return;
}
if (is_active()) {
lg::error("Already have a window. Close window first.");
return;
}
this->window_glfw = window;
}
void GfxDisplay::set_title(const char* title) {
if (!is_active()) {
lg::error("No window to set title `{}`.", title);
return;
}
m_title = title;
}
void GfxDisplay::render_graphics() {
m_renderer->render_display(this);
}
/* ****************************** */
/* DISPLAY */
/* ****************************** */
namespace Display {
std::vector<std::shared_ptr<GfxDisplay>> g_displays;
std::shared_ptr<GfxDisplay> GetMainDisplay() {
if (g_displays.size() == 0)
return NULL;
return g_displays.front()->is_active() ? g_displays.front() : NULL;
}
int InitMainDisplay(int width, int height, const char* title, GfxSettings& settings) {
if (GetMainDisplay() != NULL) {
lg::warn("InitMainDisplay called when main display already exists.");
return 1;
}
auto display = settings.renderer->make_main_display(width, height, title, settings);
if (display == NULL) {
lg::error("Failed to make main display.");
return 1;
}
set_main_display(display);
}
void KillDisplay(std::shared_ptr<GfxDisplay> display) {
// lg::debug("kill display #x{:x}", (uintptr_t)display);
if (!display->is_active()) {
lg::warn("display #x{:x} cant be killed because it is not active");
return;
}
if (GetMainDisplay() == display) {
// killing the main display, kill all children displays too!
for (int i = 1; i < g_displays.size(); ++i) {
KillDisplay(g_displays.at(i));
}
}
// find this display in the list and remove it from there
// if everything went right the smart pointer should delete the display.
auto this_disp = std::find(g_displays.begin(), g_displays.end(), display);
g_displays.erase(this_disp);
}
} // namespace Display