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)