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

Signed-off-by: Gabriel Ravier <gabravier@gmail.com>
This commit is contained in:
Gabriel Ravier 2020-04-10 22:32:29 +02:00
parent b2679edf37
commit 7f7c3d8434
7 changed files with 161 additions and 42 deletions

View file

@ -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))

View file

@ -2,6 +2,7 @@
#include <stddef.h>
#include <stdio.h>
#include <string>
#include "SDL.h"
@ -66,7 +67,8 @@ BOOL AudioBackend_Init(void)
{
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,15 +87,16 @@ BOOL AudioBackend_Init(void)
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);
printf("Selected SDL2 audio driver: %s\n", SDL_GetCurrentAudioDriver());

View file

@ -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: \
@ -290,6 +292,26 @@ void Backend_ShowMessageBox(const char *title, const char *message)
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)
{
return (unsigned long)(glfwGetTime() * 1000.0);

View file

@ -1,6 +1,7 @@
#pragma once
#include "../WindowsWrapper.h"
#include "../Attributes.h"
enum
{
@ -96,5 +97,7 @@ void PlaybackBackend_EnableDragAndDrop(void);
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);

View file

@ -3,6 +3,7 @@
#include <stddef.h>
#include <stdlib.h>
#include <string.h>
#include <string>
#include "SDL.h"
@ -51,10 +52,19 @@ RenderBackend_Surface* RenderBackend_Init(const char *window_title, int screen_w
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);
if (!window_sdlsurface)
{
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
{
framebuffer.sdlsurface = SDL_CreateRGBSurfaceWithFormat(0, window_sdlsurface->w, window_sdlsurface->h, 0, SDL_PIXELFORMAT_RGB24);
if (framebuffer.sdlsurface != NULL)
@ -63,16 +73,17 @@ RenderBackend_Surface* RenderBackend_Init(const char *window_title, int screen_w
return &framebuffer;
}
else
{
Backend_ShowMessageBox("Fatal error (SDLSurface rendering backend)", "Could not create framebuffer surface");
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);
}
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_Deinit(void)
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 @@ void RenderBackend_Blit(RenderBackend_Surface *source_surface, const RECT *rect,
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 @@ void RenderBackend_ColourFill(RenderBackend_Surface *surface, const RECT *rect,
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 @@ RenderBackend_Glyph* RenderBackend_LoadGlyph(const unsigned char *pixels, unsign
if (glyph->sdlsurface == NULL)
{
Backend_PrintError("Couldn't create RBG surface: %s", SDL_GetError());
free(glyph);
return NULL;
}
@ -240,9 +259,11 @@ void RenderBackend_DrawGlyph(RenderBackend_Glyph *glyph, long x, long y)
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 @@ void RenderBackend_HandleWindowResize(unsigned int width, unsigned int height)
// 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());
}

View file

@ -4,6 +4,7 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <string>
#include "SDL.h"
@ -73,8 +74,11 @@ static void GlyphBatch_Draw(spritebatch_sprite_t *sprites, int count, int textur
// 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)
{
@ -83,7 +87,8 @@ static void GlyphBatch_Draw(spritebatch_sprite_t *sprites, int count, int textur
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,7 +109,11 @@ static SPRITEBATCH_U64 GlyphBatch_CreateTexture(void *pixels, int w, int h, void
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 @@ static void GlyphBatch_DestroyTexture(SPRITEBATCH_U64 texture_id, void *udata)
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 @@ RenderBackend_Surface* RenderBackend_Init(const char *window_title, int screen_w
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 @@ RenderBackend_Surface* RenderBackend_Init(const char *window_title, int screen_w
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,14 +189,16 @@ RenderBackend_Surface* RenderBackend_Init(const char *window_title, int screen_w
}
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);
}
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 @@ RenderBackend_Surface* RenderBackend_Init(const char *window_title, int screen_w
}
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;

View file

@ -4,6 +4,7 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <string>
#include "SDL.h"
@ -36,25 +37,30 @@ BOOL Backend_Init(void)
{
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 @@ void Backend_PostWindowCreation(void)
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 @@ void Backend_SetWindowIcon(const unsigned char *rgb_pixels, unsigned int width,
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 @@ void Backend_SetCursor(const unsigned char *rgb_pixels, unsigned int width, unsi
}
}
}
else
{
Backend_PrintError("Failed to allocate memory for cursor surface");
}
}
void PlaybackBackend_EnableDragAndDrop(void)
@ -283,8 +300,29 @@ void Backend_GetKeyboardState(BOOL *out_keyboard_state)
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)