From 1f06027403aef46e13fe093ef854605cd7647ba5 Mon Sep 17 00:00:00 2001 From: Clownacy Date: Thu, 9 Apr 2020 19:29:45 +0100 Subject: [PATCH] Added GLFW3 support for the software renderer A few things need cleaning-up --- CMakeLists.txt | 8 ++ src/Backends/GLFW3/Window-Software.cpp | 151 +++++++++++++++++++++++++ src/Backends/GLFW3/Window.h | 1 - src/Backends/Rendering/Software.cpp | 61 ++-------- src/Backends/SDL2/Window-Software.cpp | 74 ++++++++++++ src/Backends/Window-Software.h | 10 ++ 6 files changed, 253 insertions(+), 52 deletions(-) create mode 100644 src/Backends/GLFW3/Window-Software.cpp create mode 100644 src/Backends/SDL2/Window-Software.cpp create mode 100644 src/Backends/Window-Software.h diff --git a/CMakeLists.txt b/CMakeLists.txt index 38651405..35cb44e1 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -355,10 +355,13 @@ elseif(BACKEND_PLATFORM MATCHES "SDL2" AND BACKEND_RENDERER MATCHES "OpenGLES2") elseif(BACKEND_PLATFORM MATCHES "SDL2" AND BACKEND_RENDERER MATCHES "SDLTexture") elseif(BACKEND_PLATFORM MATCHES "SDL2" AND BACKEND_RENDERER MATCHES "SDLSurface") elseif(BACKEND_PLATFORM MATCHES "SDL2" AND BACKEND_RENDERER MATCHES "Software") + target_sources(CSE2 PRIVATE "src/Backends/SDL2/Window-Software.cpp") elseif(BACKEND_PLATFORM MATCHES "GLFW3" AND BACKEND_RENDERER MATCHES "OpenGL3") target_sources(CSE2 PRIVATE "src/Backends/GLFW3/Window-OpenGL3.cpp") elseif(BACKEND_PLATFORM MATCHES "GLFW3" AND BACKEND_RENDERER MATCHES "OpenGLES2") target_sources(CSE2 PRIVATE "src/Backends/GLFW3/Window-OpenGLES2.cpp") +elseif(BACKEND_PLATFORM MATCHES "GLFW3" AND BACKEND_RENDERER MATCHES "Software") + target_sources(CSE2 PRIVATE "src/Backends/GLFW3/Window-Software.cpp") else() message(FATAL_ERROR "Invalid BACKEND_PLATFORM/BACKEND_RENDERER combination") endif() @@ -564,6 +567,11 @@ if(BACKEND_RENDERER MATCHES "OpenGLES2") target_link_libraries(CSE2 PRIVATE ${OPENGLES2_LIBRARIES}) endif() +if(BACKEND_PLATFORM MATCHES "GLFW3" AND BACKEND_RENDERER MATCHES "Software") + find_package(OpenGL REQUIRED) + target_link_libraries(CSE2 PRIVATE OpenGL::GL) +endif() + ####################### # Resource conversion # diff --git a/src/Backends/GLFW3/Window-Software.cpp b/src/Backends/GLFW3/Window-Software.cpp new file mode 100644 index 00000000..091175e5 --- /dev/null +++ b/src/Backends/GLFW3/Window-Software.cpp @@ -0,0 +1,151 @@ +#include "../Window-Software.h" +#include "Window.h" + +#include +#include + +#if defined(__APPLE__) + #include +#else + #include +#endif +#include + +#include "../../WindowsWrapper.h" + +#include "../Misc.h" + +GLFWwindow *window; + +static unsigned char *framebuffer; +static int framebuffer_width; +static int framebuffer_height; + +static float framebuffer_x_ratio; +static float framebuffer_y_ratio; + +static GLuint screen_texture_id; + +unsigned char* WindowBackend_Software_CreateWindow(const char *window_title, int screen_width, int screen_height, BOOL fullscreen, size_t *pitch) +{ + glfwWindowHint(GLFW_CLIENT_API, GLFW_OPENGL_API); + glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 1); + glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 0); + + framebuffer_width = screen_width; + framebuffer_height = screen_height; + + GLFWmonitor *monitor = NULL; + + if (fullscreen) + { + monitor = glfwGetPrimaryMonitor(); + + if (monitor != NULL) + { + const GLFWvidmode *mode = glfwGetVideoMode(monitor); + + screen_width = mode->width; + screen_height = mode->height; + } + } + + window = glfwCreateWindow(screen_width, screen_height, window_title, monitor, NULL); + + if (window != NULL) + { + glfwMakeContextCurrent(window); + + glClearColor(0.0f, 0.0f, 0.0f, 1.0f); + + glEnable(GL_TEXTURE_2D); + + // Create screen texture + glGenTextures(1, &screen_texture_id); + glBindTexture(GL_TEXTURE_2D, screen_texture_id); + + int framebuffer_texture_width = 1; + while (framebuffer_texture_width < framebuffer_width) + framebuffer_texture_width <<= 1; + + int framebuffer_texture_height = 1; + while (framebuffer_texture_height < framebuffer_height) + framebuffer_texture_height <<= 1; + + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, framebuffer_texture_width, framebuffer_texture_height, 0, GL_RGB, GL_UNSIGNED_BYTE, NULL); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + + framebuffer_x_ratio = (float)framebuffer_width / framebuffer_texture_width; + framebuffer_y_ratio = (float)framebuffer_height / framebuffer_texture_height; + + framebuffer = (unsigned char*)malloc(framebuffer_width * framebuffer_height * 3); + + *pitch = framebuffer_width * 3; + + Backend_PostWindowCreation(); + + return framebuffer; + } + else + { + Backend_ShowMessageBox("Fatal error (OpenGL rendering backend)", "Could not create window"); + } + + return NULL; +} + +void WindowBackend_Software_DestroyWindow(void) +{ + free(framebuffer); + glDeleteTextures(1, &screen_texture_id); + glfwDestroyWindow(window); +} + +void WindowBackend_Software_Display(void) +{ + glClear(GL_COLOR_BUFFER_BIT); + + glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, framebuffer_width, framebuffer_height, GL_RGB, GL_UNSIGNED_BYTE, framebuffer); + + glBegin(GL_TRIANGLE_STRIP); + glTexCoord2f(0.0f, framebuffer_y_ratio); + glVertex2f(-1.0f, -1.0f); + glTexCoord2f(framebuffer_x_ratio, framebuffer_y_ratio); + glVertex2f(1.0f, -1.0f); + glTexCoord2f(0.0f, 0.0f); + glVertex2f(-1.0f, 1.0f); + glTexCoord2f(framebuffer_x_ratio, 0.0f); + glVertex2f(1.0f, 1.0f); + glEnd(); + + glfwSwapBuffers(window); +} + +void WindowBackend_Software_HandleWindowResize(unsigned int width, unsigned int height) +{ + // Do some viewport trickery, to fit the framebuffer in the center of the screen + GLint viewport_x; + GLint viewport_y; + GLsizei viewport_width; + GLsizei viewport_height; + + if (width > height) + { + viewport_y = 0; + viewport_height = height; + + viewport_width = framebuffer_width * ((float)height / (float)framebuffer_height); + viewport_x = (width - viewport_width) / 2; + } + else + { + viewport_x = 0; + viewport_width = width; + + viewport_height = framebuffer_height * ((float)width / (float)framebuffer_width); + viewport_y = (height - viewport_height) / 2; + } + + glViewport(viewport_x, viewport_y, viewport_width, viewport_height); +} diff --git a/src/Backends/GLFW3/Window.h b/src/Backends/GLFW3/Window.h index 5087e303..ae1ed082 100644 --- a/src/Backends/GLFW3/Window.h +++ b/src/Backends/GLFW3/Window.h @@ -2,6 +2,5 @@ #define GLFW_INCLUDE_NONE #include -#undef GLFW_INCLUDE_NONE extern GLFWwindow *window; diff --git a/src/Backends/Rendering/Software.cpp b/src/Backends/Rendering/Software.cpp index e548faf1..4cc01a17 100644 --- a/src/Backends/Rendering/Software.cpp +++ b/src/Backends/Rendering/Software.cpp @@ -4,12 +4,10 @@ #include #include -#include "SDL.h" - #include "../../WindowsWrapper.h" #include "../Misc.h" -#include "../SDL2/Window.h" +#include "../Window-Software.h" #include "../../Attributes.h" #define MIN(a, b) ((a) < (b) ? (a) : (b)) @@ -30,64 +28,30 @@ typedef struct RenderBackend_Glyph unsigned int height; } RenderBackend_Glyph; -static SDL_Surface *window_sdlsurface; -static SDL_Surface *framebuffer_sdlsurface; static RenderBackend_Surface framebuffer; static unsigned char glyph_colour_channels[3]; static RenderBackend_Surface *glyph_destination_surface; -SDL_Window *window; - RenderBackend_Surface* RenderBackend_Init(const char *window_title, int screen_width, int screen_height, BOOL fullscreen) { - window = SDL_CreateWindow(window_title, SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, screen_width, screen_height, 0); + size_t pitch; + framebuffer.pixels = WindowBackend_Software_CreateWindow(window_title, screen_width, screen_height, fullscreen, &pitch); + framebuffer.width = screen_width; + framebuffer.height = screen_height; + framebuffer.pitch = pitch; - if (window != NULL) - { - if (fullscreen) - SDL_SetWindowFullscreen(window, SDL_WINDOW_FULLSCREEN); - - window_sdlsurface = SDL_GetWindowSurface(window); - - framebuffer_sdlsurface = SDL_CreateRGBSurfaceWithFormat(0, window_sdlsurface->w, window_sdlsurface->h, 0, SDL_PIXELFORMAT_RGB24); - - if (framebuffer_sdlsurface != NULL) - { - framebuffer.pixels = (unsigned char*)framebuffer_sdlsurface->pixels; - framebuffer.width = framebuffer_sdlsurface->w; - framebuffer.height = framebuffer_sdlsurface->h; - framebuffer.pitch = framebuffer_sdlsurface->pitch; - - Backend_PostWindowCreation(); - - return &framebuffer; - } - else - { - Backend_ShowMessageBox("Fatal error (software rendering backend)", "Could not create framebuffer surface"); - } - - SDL_DestroyWindow(window); - } - else - { - Backend_ShowMessageBox("Fatal error (software rendering backend)", "Could not create window"); - } - - return NULL; + return &framebuffer; } void RenderBackend_Deinit(void) { - SDL_FreeSurface(framebuffer_sdlsurface); - SDL_DestroyWindow(window); + WindowBackend_Software_DestroyWindow(); } void RenderBackend_DrawScreen(void) { - SDL_BlitSurface(framebuffer_sdlsurface, NULL, window_sdlsurface, NULL); - SDL_UpdateWindowSurface(window); + WindowBackend_Software_Display(); } RenderBackend_Surface* RenderBackend_CreateSurface(unsigned int width, unsigned int height) @@ -372,10 +336,5 @@ void RenderBackend_HandleRenderTargetLoss(void) void RenderBackend_HandleWindowResize(unsigned int width, unsigned int height) { - (void)width; - (void)height; - - // https://wiki.libsdl.org/SDL_GetWindowSurface - // We need to fetch a new surface pointer - window_sdlsurface = SDL_GetWindowSurface(window); + WindowBackend_Software_HandleWindowResize(width, height); } diff --git a/src/Backends/SDL2/Window-Software.cpp b/src/Backends/SDL2/Window-Software.cpp new file mode 100644 index 00000000..97ba3a4b --- /dev/null +++ b/src/Backends/SDL2/Window-Software.cpp @@ -0,0 +1,74 @@ +#include "../Window-Software.h" +#include "Window.h" + +#include +#include + +#include "SDL.h" + +#include "../../WindowsWrapper.h" + +#include "../Misc.h" + +SDL_Window *window; + +static SDL_Surface *window_sdlsurface; +static SDL_Surface *framebuffer_sdlsurface; + +unsigned char* WindowBackend_Software_CreateWindow(const char *window_title, int screen_width, int screen_height, BOOL fullscreen, size_t *pitch) +{ + window = SDL_CreateWindow(window_title, SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, screen_width, screen_height, 0); + + if (window != NULL) + { + if (fullscreen) + SDL_SetWindowFullscreen(window, SDL_WINDOW_FULLSCREEN); + + window_sdlsurface = SDL_GetWindowSurface(window); + + framebuffer_sdlsurface = SDL_CreateRGBSurfaceWithFormat(0, window_sdlsurface->w, window_sdlsurface->h, 0, SDL_PIXELFORMAT_RGB24); + + if (framebuffer_sdlsurface != NULL) + { + *pitch = framebuffer_sdlsurface->pitch; + + Backend_PostWindowCreation(); + + return (unsigned char*)framebuffer_sdlsurface->pixels; + } + else + { + Backend_ShowMessageBox("Fatal error (software rendering backend)", "Could not create framebuffer surface"); + } + + SDL_DestroyWindow(window); + } + else + { + Backend_ShowMessageBox("Fatal error (software rendering backend)", "Could not create window"); + } + + return NULL; +} + +void WindowBackend_Software_DestroyWindow(void) +{ + SDL_FreeSurface(framebuffer_sdlsurface); + SDL_DestroyWindow(window); +} + +void WindowBackend_Software_Display(void) +{ + SDL_BlitSurface(framebuffer_sdlsurface, NULL, window_sdlsurface, NULL); + SDL_UpdateWindowSurface(window); +} + +void WindowBackend_Software_HandleWindowResize(unsigned int width, unsigned int height) +{ + (void)width; + (void)height; + + // https://wiki.libsdl.org/SDL_GetWindowSurface + // We need to fetch a new surface pointer + window_sdlsurface = SDL_GetWindowSurface(window); +} diff --git a/src/Backends/Window-Software.h b/src/Backends/Window-Software.h new file mode 100644 index 00000000..8f525c2e --- /dev/null +++ b/src/Backends/Window-Software.h @@ -0,0 +1,10 @@ +#pragma once + +#include + +#include "../WindowsWrapper.h" + +unsigned char* WindowBackend_Software_CreateWindow(const char *window_title, int screen_width, int screen_height, BOOL fullscreen, size_t *pitch); +void WindowBackend_Software_DestroyWindow(void); +void WindowBackend_Software_Display(void); +void WindowBackend_Software_HandleWindowResize(unsigned int width, unsigned int height);