ref: f079a14b581c3f73cd1dacc4069d194c2131cb3a
parent: 0b83da1fd996fc9b31ff16eaf394f4bfc3ceb1d9
author: Clownacy <Clownacy@users.noreply.github.com>
date: Mon Sep 7 22:40:27 EDT 2020
Update the SDLTexture renderer
--- a/src/Backends/Rendering/SDLTexture.cpp
+++ b/src/Backends/Rendering/SDLTexture.cpp
@@ -7,9 +7,6 @@
#include "SDL.h"
-#define SPRITEBATCH_IMPLEMENTATION
-#include "../../../external/cute_spritebatch.h"
-
#include "../../WindowsWrapper.h"
#include "../Misc.h"
@@ -27,12 +24,10 @@
struct RenderBackend_Surface *prev;
} RenderBackend_Surface;
-typedef struct RenderBackend_Glyph
+typedef struct RenderBackend_GlyphAtlas
{
- unsigned char *pixels;
- unsigned int width;
- unsigned int height;
-} RenderBackend_Glyph;
+ SDL_Texture *texture;
+} RenderBackend_GlyphAtlas;
SDL_Window *window;
@@ -42,10 +37,6 @@
static RenderBackend_Surface *surface_list_head;
-static unsigned char glyph_colour_channels[3];
-
-static spritebatch_t glyph_batcher;
-
static void RectToSDLRect(const RenderBackend_Rect *rect, SDL_Rect *sdl_rect)
{
sdl_rect->x = (int)rect->left;
@@ -60,67 +51,6 @@
sdl_rect->h = 0;
}
-// Blit the glyphs in the batch
-static void GlyphBatch_Draw(spritebatch_sprite_t *sprites, int count, int texture_w, int texture_h, void *udata)
-{
- (void)udata;
-
- SDL_Texture *texture_atlas = (SDL_Texture*)sprites[0].texture_id;
-
- // 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.
- 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;
-
- 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};
-
- if (SDL_RenderCopy(renderer, texture_atlas, &source_rect, &destination_rect) < 0)
- Backend_PrintError("Couldn't copy glyph texture portion to renderer: %s", SDL_GetError());
- }
-}
-
-// Upload the glyph's pixels
-static void GlyphBatch_GetPixels(SPRITEBATCH_U64 image_id, void *buffer, int bytes_to_fill, void *udata)
-{
- (void)udata;
-
- RenderBackend_Glyph *glyph = (RenderBackend_Glyph*)image_id;
-
- memcpy(buffer, glyph->pixels, bytes_to_fill);
-}
-
-// Create a texture atlas, and upload pixels to it
-static SPRITEBATCH_U64 GlyphBatch_CreateTexture(void *pixels, int w, int h, void *udata)
-{
- (void)udata;
-
- SDL_Texture *texture = SDL_CreateTexture(renderer, SDL_PIXELFORMAT_RGBA32, SDL_TEXTUREACCESS_STATIC, w, h);
-
- if (texture == NULL)
- 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;
-}
-
-// Destroy texture atlas
-static void GlyphBatch_DestroyTexture(SPRITEBATCH_U64 texture_id, void *udata)
-{
- (void)udata;
-
- SDL_DestroyTexture((SDL_Texture*)texture_id);
-}
-
RenderBackend_Surface* RenderBackend_Init(const char *window_title, int screen_width, int screen_height, bool fullscreen)
{
Backend_PrintInfo("Available SDL render drivers:");
@@ -163,27 +93,9 @@
framebuffer.width = screen_width;
framebuffer.height = screen_height;
- // Set-up glyph-batcher
- spritebatch_config_t config;
- spritebatch_set_default_config(&config);
- config.pixel_stride = 4;
- config.atlas_width_in_pixels = 256;
- config.atlas_height_in_pixels = 256;
- config.lonely_buffer_count_till_flush = 4; // Start making atlases immediately
- config.batch_callback = GlyphBatch_Draw;
- config.get_pixels_callback = GlyphBatch_GetPixels;
- config.generate_texture_callback = GlyphBatch_CreateTexture;
- config.delete_texture_callback = GlyphBatch_DestroyTexture;
- if (spritebatch_init(&glyph_batcher, &config, NULL) == 0)
- {
- Backend_PostWindowCreation();
+ Backend_PostWindowCreation();
- return &framebuffer;
- }
- else
- {
- Backend_ShowMessageBox("Fatal error (SDLTexture rendering backend)", "Failed to initialize spritebatch");
- }
+ return &framebuffer;
}
else
{
@@ -213,7 +125,6 @@
void RenderBackend_Deinit(void)
{
- spritebatch_term(&glyph_batcher);
SDL_DestroyTexture(framebuffer.texture);
SDL_DestroyRenderer(renderer);
SDL_DestroyWindow(window);
@@ -221,8 +132,6 @@
void RenderBackend_DrawScreen(void)
{
- spritebatch_tick(&glyph_batcher);
-
if (SDL_SetRenderTarget(renderer, NULL) < 0)
Backend_PrintError("Couldn't set default render target as the current rendering target: %s", SDL_GetError());
@@ -396,28 +305,46 @@
Backend_PrintError("Couldn't enable alpha blending for drawing operations: %s", SDL_GetError());
}
-RenderBackend_Glyph* RenderBackend_LoadGlyph(const unsigned char *pixels, unsigned int width, unsigned int height, int pitch)
+
+RenderBackend_GlyphAtlas* RenderBackend_CreateGlyphAtlas(size_t size)
{
- RenderBackend_Glyph *glyph = (RenderBackend_Glyph*)malloc(sizeof(RenderBackend_Glyph));
+ RenderBackend_GlyphAtlas *atlas = (RenderBackend_GlyphAtlas*)malloc(sizeof(RenderBackend_GlyphAtlas));
- if (glyph == NULL)
- return NULL;
+ if (atlas != NULL)
+ {
+ atlas->texture = SDL_CreateTexture(renderer, SDL_PIXELFORMAT_RGBA32, SDL_TEXTUREACCESS_STATIC, size, size);
- glyph->pixels = (unsigned char*)malloc(width * height * 4);
+ if (atlas->texture != NULL)
+ {
+ return atlas;
+ }
+ else
+ {
+ Backend_PrintError("Couldn't create texture for renderer: %s", SDL_GetError());
+ }
- if (glyph->pixels == NULL)
- {
- free(glyph);
- return NULL;
+ free(atlas);
}
- unsigned char *destination_pointer = glyph->pixels;
+ return NULL;
+}
- for (unsigned int y = 0; y < height; ++y)
+void RenderBackend_DestroyGlyphAtlas(RenderBackend_GlyphAtlas *atlas)
+{
+ SDL_DestroyTexture(atlas->texture);
+ free(atlas);
+}
+
+void RenderBackend_UploadGlyph(RenderBackend_GlyphAtlas *atlas, size_t x, size_t y, const unsigned char *pixels, size_t width, size_t height)
+{
+ unsigned char *buffer = (unsigned char*)malloc(width * height * 4);
+
+ if (buffer != NULL)
{
- const unsigned char *source_pointer = pixels + y * pitch;
+ unsigned char *destination_pointer = buffer;
+ const unsigned char *source_pointer = pixels;
- for (unsigned int x = 0; x < width; ++x)
+ for (size_t i = 0; i < width * height; ++i)
{
*destination_pointer++ = 0xFF;
*destination_pointer++ = 0xFF;
@@ -424,25 +351,24 @@
*destination_pointer++ = 0xFF;
*destination_pointer++ = *source_pointer++;
}
- }
- glyph->width = width;
- glyph->height = height;
+ SDL_Rect rect;
+ rect.x = x;
+ rect.y = y;
+ rect.w = width;
+ rect.h = height;
- return glyph;
-}
+ if (SDL_UpdateTexture(atlas->texture, &rect, buffer, width * 4) < 0)
+ Backend_PrintError("Couldn't update texture: %s", SDL_GetError());
-void RenderBackend_UnloadGlyph(RenderBackend_Glyph *glyph)
-{
- if (glyph == NULL)
- return;
-
- free(glyph->pixels);
- free(glyph);
+ free(buffer);
+ }
}
-void RenderBackend_PrepareToDrawGlyphs(RenderBackend_Surface *destination_surface, const unsigned char *colour_channels)
+void RenderBackend_PrepareToDrawGlyphs(RenderBackend_GlyphAtlas *atlas, RenderBackend_Surface *destination_surface, const unsigned char *colour_channels)
{
+ (void)atlas;
+
if (destination_surface == NULL)
return;
@@ -449,21 +375,37 @@
if (SDL_SetRenderTarget(renderer, destination_surface->texture) < 0)
Backend_PrintError("Couldn't set texture as current rendering target: %s", SDL_GetError());
- memcpy(glyph_colour_channels, colour_channels, sizeof(glyph_colour_channels));
+ // 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.
+ if (SDL_SetTextureColorMod(atlas->texture, colour_channels[0], colour_channels[1], colour_channels[2]) < 0)
+ Backend_PrintError("Couldn't set additional color value: %s", SDL_GetError());
+
+ if (SDL_SetTextureBlendMode(atlas->texture, SDL_BLENDMODE_BLEND) < 0)
+ Backend_PrintError("Couldn't set texture blend mode: %s", SDL_GetError());
+
}
-void RenderBackend_DrawGlyph(RenderBackend_Glyph *glyph, long x, long y)
+void RenderBackend_DrawGlyph(RenderBackend_GlyphAtlas *atlas, long x, long y, size_t glyph_x, size_t glyph_y, size_t glyph_width, size_t glyph_height)
{
- if (spritebatch_push(&glyph_batcher, (SPRITEBATCH_U64)glyph, glyph->width, glyph->height, x, y, 1.0f, 1.0f, 0.0f, 0.0f, 0) != 1)
- Backend_PrintError("Failed to push glyph to batcher");
+ SDL_Rect source_rect;
+ source_rect.x = glyph_x;
+ source_rect.y = glyph_y;
+ source_rect.w = glyph_width;
+ source_rect.h = glyph_height;
+
+ SDL_Rect destination_rect;
+ destination_rect.x = x;
+ destination_rect.y = y;
+ destination_rect.w = glyph_width;
+ destination_rect.h = glyph_height;
+
+ if (SDL_RenderCopy(renderer, atlas->texture, &source_rect, &destination_rect) < 0)
+ Backend_PrintError("Couldn't copy glyph texture portion to renderer: %s", SDL_GetError());
}
void RenderBackend_FlushGlyphs(void)
{
- if (spritebatch_defrag(&glyph_batcher) != 1)
- Backend_PrintError("Couldn't defrag textures");
-
- spritebatch_flush(&glyph_batcher);
+
}
void RenderBackend_HandleRenderTargetLoss(void)