shithub: cstory

Download patch

ref: 1f06027403aef46e13fe093ef854605cd7647ba5
parent: 0582fa93d142a8929030c61c6f52c8837a6ca8a6
author: Clownacy <[email protected]>
date: Thu Apr 9 15:29:45 EDT 2020

Added GLFW3 support for the software renderer

A few things need cleaning-up

--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -355,10 +355,13 @@
 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()
@@ -562,6 +565,11 @@
 	find_package(OpenGLES2 REQUIRED)
 	target_include_directories(CSE2 PRIVATE ${OPENGLES2_INCLUDE_DIR})
 	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()
 
 
--- /dev/null
+++ b/src/Backends/GLFW3/Window-Software.cpp
@@ -1,0 +1,151 @@
+#include "../Window-Software.h"
+#include "Window.h"
+
+#include <stddef.h>
+#include <stdlib.h>
+
+#if defined(__APPLE__)
+ #include <OpenGL/gl.h>
+#else
+ #include <GL/gl.h>
+#endif
+#include <GLFW/glfw3.h>
+
+#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);
+}
--- a/src/Backends/GLFW3/Window.h
+++ b/src/Backends/GLFW3/Window.h
@@ -2,6 +2,5 @@
 
 #define GLFW_INCLUDE_NONE
 #include <GLFW/glfw3.h>
-#undef GLFW_INCLUDE_NONE
 
 extern GLFWwindow *window;
--- a/src/Backends/Rendering/Software.cpp
+++ b/src/Backends/Rendering/Software.cpp
@@ -4,12 +4,10 @@
 #include <stdlib.h>
 #include <string.h>
 
-#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 @@
 	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_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);
 }
--- /dev/null
+++ b/src/Backends/SDL2/Window-Software.cpp
@@ -1,0 +1,74 @@
+#include "../Window-Software.h"
+#include "Window.h"
+
+#include <stddef.h>
+#include <stdlib.h>
+
+#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);
+}
--- /dev/null
+++ b/src/Backends/Window-Software.h
@@ -1,0 +1,10 @@
+#pragma once
+
+#include <stddef.h>
+
+#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);