shithub: cstory

Download patch

ref: 7f7c3d8434781ccef776de76242d9ab5cb1e31d4
parent: b2679edf37e9cccd2a17732f47f5f6561939e9e7
author: Gabriel Ravier <[email protected]>
date: Fri Apr 10 18:32:29 EDT 2020

Backends: Started adding a bunch of error handling stuff (error checking only done in SDL2 for now)

Signed-off-by: Gabriel Ravier <[email protected]>

--- a/src/Attributes.h
+++ b/src/Attributes.h
@@ -1,5 +1,15 @@
 #pragma once
 
+/// Include file for portable usage of __attribute__
+
+#ifdef __MINGW32__
+#define ATTRIBUTE_FORMAT_PRINTF(stringIndex, firstToCheck) __attribute__((format(__MINGW_PRINTF_FORMAT, stringIndex, firstToCheck)))
+#elif defined(__GNUC__)
+#define ATTRIBUTE_FORMAT_PRINTF(stringIndex, firstToCheck) __attribute__((format(printf, stringIndex, firstToCheck)))
+#else
+#define ATTRIBUTE_FORMAT_PRINTF(stringIndex, firstToCheck)
+#endif
+
 #ifdef __GNUC__
 
 #define ATTRIBUTE_HOT __attribute__((hot))
--- a/src/Backends/Audio/SDL2.cpp
+++ b/src/Backends/Audio/SDL2.cpp
@@ -2,6 +2,7 @@
 
 #include <stddef.h>
 #include <stdio.h>
+#include <string>
 
 #include "SDL.h"
 
@@ -66,7 +67,8 @@
 {
 	if (SDL_InitSubSystem(SDL_INIT_AUDIO) < 0)
 	{
-		Backend_ShowMessageBox("Fatal error (SDL2 audio backend)", "'SDL_InitSubSystem(SDL_INIT_AUDIO)' failed");
+		std::string errorMessage = std::string("'SDL_InitSubSystem(SDL_INIT_AUDIO)' failed : ") + SDL_GetError();
+		Backend_ShowMessageBox("Fatal error (SDL2 audio backend)", errorMessage.c_str());
 		return FALSE;
 	}
 
@@ -85,14 +87,15 @@
 
 	SDL_AudioSpec obtained_specification;
 	device_id = SDL_OpenAudioDevice(NULL, 0, &specification, &obtained_specification, SDL_AUDIO_ALLOW_FREQUENCY_CHANGE);
-	output_frequency = obtained_specification.freq;
-	Mixer_Init(obtained_specification.freq);
-
 	if (device_id == 0)
 	{
-		Backend_ShowMessageBox("Fatal error (SDL2 audio backend)", "'SDL_OpenAudioDevice' failed");
+		std::string error_message = std::string("'SDL_OpenAudioDevice' failed : ") + SDL_GetError();
+		Backend_ShowMessageBox("Fatal error (SDL2 audio backend)", error_message.c_str());
 		return FALSE;
 	}
+
+	output_frequency = obtained_specification.freq;
+	Mixer_Init(obtained_specification.freq);
 
 	SDL_PauseAudioDevice(device_id, 0);
 
--- a/src/Backends/GLFW3/Misc.cpp
+++ b/src/Backends/GLFW3/Misc.cpp
@@ -1,6 +1,7 @@
 #include "../Misc.h"
 
 #include <chrono>
+#include <stdarg.h>
 #include <stddef.h>
 #include <stdio.h>
 #include <stdlib.h>
@@ -17,6 +18,7 @@
 #include "../../Organya.h"
 #include "../../Profile.h"
 #include "../../Resource.h"
+#include "../../Attributes.h"
 
 #define DO_KEY(GLFW_KEY, BACKEND_KEY) \
 	case GLFW_KEY: \
@@ -288,6 +290,26 @@
 {
 	// GLFW3 doesn't have a message box
 	printf("ShowMessageBox - '%s' - '%s'\n", title, message);
+}
+
+ATTRIBUTE_FORMAT_PRINTF(1, 2) void Backend_PrintError(const char *format, ...)
+{
+	va_list argumentList;
+	va_start(argumentList, format);
+	fputs("ERROR: ", stderr);
+	vfprintf(stderr, format, argumentList);
+	fputc('\n', stderr);
+	va_end(argumentList);
+}
+
+ATTRIBUTE_FORMAT_PRINTF(1, 2) void Backend_PrintInfo(const char *format, ...)
+{
+	va_list argumentList;
+	va_start(argumentList, format);
+	fputs("INFO: ", stdout);
+	vprintf(format, argumentList);
+	putchar('\n');
+	va_end(argumentList);
 }
 
 unsigned long Backend_GetTicks(void)
--- a/src/Backends/Misc.h
+++ b/src/Backends/Misc.h
@@ -1,6 +1,7 @@
 #pragma once
 
 #include "../WindowsWrapper.h"
+#include "../Attributes.h"
 
 enum
 {
@@ -96,5 +97,7 @@
 BOOL Backend_SystemTask(void);
 void Backend_GetKeyboardState(BOOL *keyboard_state);
 void Backend_ShowMessageBox(const char *title, const char *message);
+ATTRIBUTE_FORMAT_PRINTF(1, 2) void Backend_PrintError(const char *format, ...);
+ATTRIBUTE_FORMAT_PRINTF(1, 2) void Backend_PrintInfo(const char *format, ...);
 unsigned long Backend_GetTicks(void);
 void Backend_Delay(unsigned int ticks);
--- a/src/Backends/Rendering/SDLSurface.cpp
+++ b/src/Backends/Rendering/SDLSurface.cpp
@@ -3,6 +3,7 @@
 #include <stddef.h>
 #include <stdlib.h>
 #include <string.h>
+#include <string>
 
 #include "SDL.h"
 
@@ -51,21 +52,30 @@
 	if (window != NULL)
 	{
 		if (fullscreen)
-			SDL_SetWindowFullscreen(window, SDL_WINDOW_FULLSCREEN);
+		{
+			if (SDL_SetWindowFullscreen(window, SDL_WINDOW_FULLSCREEN) < 0)
+				Backend_PrintError("Could not set window to fullscreen: %s", SDL_GetError());
+		}
 
 		window_sdlsurface = SDL_GetWindowSurface(window);
-
-		framebuffer.sdlsurface = SDL_CreateRGBSurfaceWithFormat(0, window_sdlsurface->w, window_sdlsurface->h, 0, SDL_PIXELFORMAT_RGB24);
-
-		if (framebuffer.sdlsurface != NULL)
+		if (!window_sdlsurface)
 		{
-			Backend_PostWindowCreation();
-
-			return &framebuffer;
+			std::string error_message = std::string("Could not get SDL surface of the window: ") + SDL_GetError();
+			Backend_ShowMessageBox("Fatal error (SDLSurface rendering backend)", error_message.c_str());
 		}
 		else
 		{
-			Backend_ShowMessageBox("Fatal error (SDLSurface rendering backend)", "Could not create framebuffer surface");
+			framebuffer.sdlsurface = SDL_CreateRGBSurfaceWithFormat(0, window_sdlsurface->w, window_sdlsurface->h, 0, SDL_PIXELFORMAT_RGB24);
+
+			if (framebuffer.sdlsurface != NULL)
+			{
+				Backend_PostWindowCreation();
+
+				return &framebuffer;
+			}
+
+			std::string error_message = std::string("Could not create framebuffer surface : ") + SDL_GetError();
+			Backend_ShowMessageBox("Fatal error (SDLSurface rendering backend)", error_message.c_str());
 		}
 
 		SDL_DestroyWindow(window);
@@ -72,7 +82,8 @@
 	}
 	else
 	{
-		Backend_ShowMessageBox("Fatal error (SDLSurface rendering backend)", "Could not create window");
+		std::string error_message = std::string("Could not create window : ") + SDL_GetError();
+		Backend_ShowMessageBox("Fatal error (SDLSurface rendering backend)", error_message.c_str());
 	}
 
 	return NULL;
@@ -86,8 +97,11 @@
 
 void RenderBackend_DrawScreen(void)
 {
-	SDL_BlitSurface(framebuffer.sdlsurface, NULL, window_sdlsurface, NULL);
-	SDL_UpdateWindowSurface(window);
+	if (SDL_BlitSurface(framebuffer.sdlsurface, NULL, window_sdlsurface, NULL) < 0)
+		Backend_PrintError("Couldn't blit framebuffer surface to window surface: %s", SDL_GetError());
+
+	if (SDL_UpdateWindowSurface(window) < 0)
+		Backend_PrintError("Couldn't put window surface on screen: %s", SDL_GetError());
 }
 
 RenderBackend_Surface* RenderBackend_CreateSurface(unsigned int width, unsigned int height)
@@ -162,9 +176,12 @@
 	destination_rect.w = source_rect.w;
 	destination_rect.h = source_rect.h;
 
-	SDL_SetColorKey(source_surface->sdlsurface, colour_key ? SDL_TRUE : SDL_FALSE, SDL_MapRGB(source_surface->sdlsurface->format, 0, 0, 0)); // Assumes the colour key will always be #000000 (black)
+	// Assumes the colour key will always be #000000 (black)
+	if (SDL_SetColorKey(source_surface->sdlsurface, colour_key ? SDL_TRUE : SDL_FALSE, SDL_MapRGB(source_surface->sdlsurface->format, 0, 0, 0)) < 0)
+		Backend_PrintError("Couldn't set color key of surface: %s", SDL_GetError());
 
-	SDL_BlitSurface(source_surface->sdlsurface, &source_rect, destination_surface->sdlsurface, &destination_rect);
+	if (SDL_BlitSurface(source_surface->sdlsurface, &source_rect, destination_surface->sdlsurface, &destination_rect) < 0)
+		Backend_PrintError("Couldn't blit surface: %s", SDL_GetError());
 }
 
 void RenderBackend_ColourFill(RenderBackend_Surface *surface, const RECT *rect, unsigned char red, unsigned char green, unsigned char blue)
@@ -175,7 +192,8 @@
 	SDL_Rect destination_rect;
 	RectToSDLRect(rect, &destination_rect);
 
-	SDL_FillRect(surface->sdlsurface, &destination_rect, SDL_MapRGB(surface->sdlsurface->format, red, green, blue));
+	if (SDL_FillRect(surface->sdlsurface, &destination_rect, SDL_MapRGB(surface->sdlsurface->format, red, green, blue)) < 0)
+		Backend_PrintError("Couldn't fill rectangle with color: %s", SDL_GetError());
 }
 
 RenderBackend_Glyph* RenderBackend_LoadGlyph(const unsigned char *pixels, unsigned int width, unsigned int height, int pitch)
@@ -189,6 +207,7 @@
 
 	if (glyph->sdlsurface == NULL)
 	{
+		Backend_PrintError("Couldn't create RBG surface: %s", SDL_GetError());
 		free(glyph);
 		return NULL;
 	}
@@ -240,9 +259,11 @@
 	rect.w = glyph->sdlsurface->w;
 	rect.h = glyph->sdlsurface->h;
 
-	SDL_SetSurfaceColorMod(glyph->sdlsurface, glyph_colour_channels[0], glyph_colour_channels[1], glyph_colour_channels[2]);
+	if (SDL_SetSurfaceColorMod(glyph->sdlsurface, glyph_colour_channels[0], glyph_colour_channels[1], glyph_colour_channels[2]) < 0)
+		Backend_PrintError("Couldn't set color value: %s", SDL_GetError());
 
-	SDL_BlitSurface(glyph->sdlsurface, NULL, glyph_destination_sdlsurface, &rect);
+	if (SDL_BlitSurface(glyph->sdlsurface, NULL, glyph_destination_sdlsurface, &rect) < 0)
+		Backend_PrintError("Couldn't blit glyph indivual surface to final glyph surface: %s", SDL_GetError());
 }
 
 void RenderBackend_FlushGlyphs(void)
@@ -263,4 +284,7 @@
 	// https://wiki.libsdl.org/SDL_GetWindowSurface
 	// We need to fetch a new surface pointer
 	window_sdlsurface = SDL_GetWindowSurface(window);
+
+	if (!window_sdlsurface)
+		Backend_PrintError("Couldn't get SDL surface for window after resize: %s", SDL_GetError());
 }
--- a/src/Backends/Rendering/SDLTexture.cpp
+++ b/src/Backends/Rendering/SDLTexture.cpp
@@ -4,6 +4,7 @@
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
+#include <string>
 
 #include "SDL.h"
 
@@ -73,9 +74,12 @@
 
 	// The SDL_Texture side of things uses alpha, not a colour-key, so the bug where the font is blended
 	// with the colour key doesn't occur.
-	SDL_SetTextureColorMod(texture_atlas, glyph_colour_channels[0], glyph_colour_channels[1], glyph_colour_channels[2]);
-	SDL_SetTextureBlendMode(texture_atlas, SDL_BLENDMODE_BLEND);
+	if (SDL_SetTextureColorMod(texture_atlas, glyph_colour_channels[0], glyph_colour_channels[1], glyph_colour_channels[2]) < 0)
+		Backend_PrintError("Couldn't set additional color value: %s", SDL_GetError());
 
+	if (SDL_SetTextureBlendMode(texture_atlas, SDL_BLENDMODE_BLEND) < 0)
+		Backend_PrintError("Couldn't set texture blend mode: %s", SDL_GetError());
+
 	for (int i = 0; i < count; ++i)
 	{
 		RenderBackend_Glyph *glyph = (RenderBackend_Glyph*)sprites[i].image_id;
@@ -83,7 +87,8 @@
 		SDL_Rect source_rect = {(int)(texture_w * sprites[i].minx), (int)(texture_h * sprites[i].maxy), (int)glyph->width, (int)glyph->height};
 		SDL_Rect destination_rect = {(int)sprites[i].x, (int)sprites[i].y, (int)glyph->width, (int)glyph->height};
 
-		SDL_RenderCopy(renderer, texture_atlas, &source_rect, &destination_rect);
+		if (SDL_RenderCopy(renderer, texture_atlas, &source_rect, &destination_rect) < 0)
+			Backend_PrintError("Couldn't copy glyph texture portion to renderer: %s", SDL_GetError());
 	}
 }
 
@@ -104,8 +109,12 @@
 
 	SDL_Texture *texture = SDL_CreateTexture(renderer, SDL_PIXELFORMAT_RGBA32, SDL_TEXTUREACCESS_STATIC, w, h);
 
-	SDL_UpdateTexture(texture, NULL, pixels, w * 4);
+	if (!texture)
+		Backend_PrintError("Couldn't create texture for renderer: %s", SDL_GetError());
 
+	if (SDL_UpdateTexture(texture, NULL, pixels, w * 4) < 0)
+		Backend_PrintError("Couldn't update texture : %s", SDL_GetError());
+
 	return (SPRITEBATCH_U64)texture;
 }
 
@@ -119,13 +128,15 @@
 
 RenderBackend_Surface* RenderBackend_Init(const char *window_title, int screen_width, int screen_height, BOOL fullscreen)
 {
-	puts("Available SDL2 render drivers:");
+	Backend_PrintInfo("Available SDL2 render drivers:");
 
 	for (int i = 0; i < SDL_GetNumRenderDrivers(); ++i)
 	{
 		SDL_RendererInfo info;
-		SDL_GetRenderDriverInfo(i, &info);
-		puts(info.name);
+		if (SDL_GetRenderDriverInfo(i, &info) < 0)
+			Backend_PrintError("Couldn't get render driver information : %s", SDL_GetError());
+		else
+			Backend_PrintInfo("%s", info.name);
 	}
 
 	window = SDL_CreateWindow(window_title, SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, screen_width, screen_height, 0);
@@ -133,7 +144,10 @@
 	if (window != NULL)
 	{
 		if (fullscreen)
-			SDL_SetWindowFullscreen(window, SDL_WINDOW_FULLSCREEN);
+		{
+			if (SDL_SetWindowFullscreen(window, SDL_WINDOW_FULLSCREEN) < 0)
+				Backend_PrintError("Couldn't set window to fullscreen: %s", SDL_GetError());
+		}
 
 	#if SDL_VERSION_ATLEAST(2,0,10)
 		SDL_SetHint(SDL_HINT_RENDER_BATCHING, "1");	// We never interfere with the renderer, so don't let SDL implicitly disable batching
@@ -144,8 +158,10 @@
 		if (renderer != NULL)
 		{
 			SDL_RendererInfo info;
-			SDL_GetRendererInfo(renderer, &info);
-			printf("Selected SDL2 render driver: %s\n", info.name);
+			if (SDL_GetRendererInfo(renderer, &info) < 0)
+				Backend_PrintError("Couldn't get selected render driver information : %s", SDL_GetError());
+			else
+				Backend_PrintInfo("Selected SDL2 render driver: %s", info.name);
 
 			framebuffer.texture = SDL_CreateTexture(renderer, SDL_PIXELFORMAT_RGBA32, SDL_TEXTUREACCESS_TARGET, screen_width, screen_height);
 
@@ -173,7 +189,8 @@
 			}
 			else
 			{
-				Backend_ShowMessageBox("Fatal error (SDLTexture rendering backend)", "Could not create framebuffer");
+				std::string error_message = std::string("Could not create framebuffer: ") + SDL_GetError();
+				Backend_ShowMessageBox("Fatal error (SDLTexture rendering backend)", error_message.c_str());
 			}
 
 			SDL_DestroyRenderer(renderer);
@@ -180,7 +197,8 @@
 		}
 		else
 		{
-			Backend_ShowMessageBox("Fatal error (SDLTexture rendering backend)", "Could not create renderer");
+			std::string error_message = std::string("Could not create renderer: ") + SDL_GetError();
+			Backend_ShowMessageBox("Fatal error (SDLTexture rendering backend)", error_message.c_str());
 		}
 
 
@@ -188,7 +206,8 @@
 	}
 	else
 	{
-		Backend_ShowMessageBox("Fatal error (SDLTexture rendering backend)", "Could not create window");
+		std::string error_message = std::string("Could not create window: ") + SDL_GetError();
+		Backend_ShowMessageBox("Fatal error (SDLTexture rendering backend)", error_message.c_str());
 	}
 
 	return NULL;
--- a/src/Backends/SDL2/Misc.cpp
+++ b/src/Backends/SDL2/Misc.cpp
@@ -4,6 +4,7 @@
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
+#include <string>
 
 #include "SDL.h"
 
@@ -36,25 +37,30 @@
 	{
 		if (SDL_InitSubSystem(SDL_INIT_VIDEO) == 0)
 		{
-			puts("Available SDL2 video drivers:");
+			Backend_PrintInfo("Available SDL2 video drivers:");
 
 			for (int i = 0; i < SDL_GetNumVideoDrivers(); ++i)
-				puts(SDL_GetVideoDriver(i));
+				Backend_PrintInfo("%s", SDL_GetVideoDriver(i));
 
 			const char *driver = SDL_GetCurrentVideoDriver();
 
 			if (driver != NULL)
-				printf("Selected SDL2 video driver: %s\n", driver);
+				Backend_PrintInfo("Selected SDL2 video driver: %s", driver);
+			else
+				Backend_PrintError("No SDL2 video driver initialized !");
 
 			return TRUE;
 		}
 
-		Backend_ShowMessageBox("Fatal error", "Could not initialise SDL2 video subsystem");
+		std::string error_message = std::string("Could not initialise SDL2 video subsystem: ") + SDL_GetError();
+		Backend_ShowMessageBox("Fatal error", error_message.c_str());
 
 		SDL_Quit();
+		return FALSE;
 	}
 
-	Backend_ShowMessageBox("Fatal error", "Could not initialise SDL2");
+	std::string error_message = std::string("Could not initialise SDL2: ") + SDL_GetError();
+	Backend_ShowMessageBox("Fatal error", error_message.c_str());
 
 	return FALSE;
 }
@@ -80,6 +86,9 @@
 BOOL Backend_GetBasePath(char *string_buffer)
 {
 	char *base_path = SDL_GetBasePath();
+	if (!base_path)
+		return FALSE;
+
 	// Trim the trailing '/'
 	size_t base_path_length = strlen(base_path);
 	base_path[base_path_length - 1] = '\0';
@@ -103,6 +112,10 @@
 		SDL_SetWindowIcon(window, surface);
 		SDL_FreeSurface(surface);
 	}
+	else
+	{
+		Backend_PrintError("Couldn't create RGB surface for window icon: %s", SDL_GetError());
+	}
 }
 
 void Backend_SetCursor(const unsigned char *rgb_pixels, unsigned int width, unsigned int height)
@@ -126,6 +139,10 @@
 			}
 		}
 	}
+	else
+	{
+		Backend_PrintError("Failed to allocate memory for cursor surface");
+	}
 }
 
 void PlaybackBackend_EnableDragAndDrop(void)
@@ -283,8 +300,29 @@
 
 void Backend_ShowMessageBox(const char *title, const char *message)
 {
-	printf("ShowMessageBox - '%s' - '%s'\n", title, message);
-	SDL_ShowSimpleMessageBox(SDL_MESSAGEBOX_ERROR, title, message, window);
+	fprintf(stderr, "ShowMessageBox - '%s' - '%s'\n", title, message);
+	if (SDL_ShowSimpleMessageBox(SDL_MESSAGEBOX_ERROR, title, message, window) != 0)
+		Backend_PrintError("Was also unable to display a message box containing the error: %s", SDL_GetError());
+}
+
+ATTRIBUTE_FORMAT_PRINTF(1, 2) void Backend_PrintError(const char *format, ...)
+{
+	va_list argumentList;
+	va_start(argumentList, format);
+	fputs("ERROR: ", stderr);
+	vfprintf(stderr, format, argumentList);
+	fputc('\n', stderr);
+	va_end(argumentList);
+}
+
+ATTRIBUTE_FORMAT_PRINTF(1, 2) void Backend_PrintInfo(const char *format, ...)
+{
+	va_list argumentList;
+	va_start(argumentList, format);
+	fputs("INFO: ", stdout);
+	vprintf(format, argumentList);
+	putchar('\n');
+	va_end(argumentList);
 }
 
 unsigned long Backend_GetTicks(void)