Add glyph-batching to the SDLTexture backend

Hope it will be this easy for the OpenGL backend
This commit is contained in:
Clownacy 2020-02-01 17:49:26 +00:00
parent 639039ce3a
commit eaf2de05b6
5 changed files with 89 additions and 28 deletions

View file

@ -30,5 +30,6 @@ Backend_Glyph* Backend_LoadGlyph(const unsigned char *pixels, unsigned int width
void Backend_UnloadGlyph(Backend_Glyph *glyph); void Backend_UnloadGlyph(Backend_Glyph *glyph);
void Backend_PrepareToDrawGlyphs(Backend_Surface *destination_surface, const unsigned char *colour_channels); void Backend_PrepareToDrawGlyphs(Backend_Surface *destination_surface, const unsigned char *colour_channels);
void Backend_DrawGlyph(Backend_Glyph *glyph, long x, long y); void Backend_DrawGlyph(Backend_Glyph *glyph, long x, long y);
void Backend_FlushGlyphs(void);
void Backend_HandleRenderTargetLoss(void); void Backend_HandleRenderTargetLoss(void);
void Backend_HandleWindowResize(void); void Backend_HandleWindowResize(void);

View file

@ -1072,6 +1072,11 @@ void Backend_DrawGlyph(Backend_Glyph *glyph, long x, long y)
vertex_buffer_slot->vertices[1][2].vertex_coordinate.y = vertex_bottom; vertex_buffer_slot->vertices[1][2].vertex_coordinate.y = vertex_bottom;
} }
void Backend_FlushGlyphs(void)
{
}
void Backend_HandleRenderTargetLoss(void) void Backend_HandleRenderTargetLoss(void)
{ {
// No problem for us // No problem for us

View file

@ -8,6 +8,10 @@
#include "SDL.h" #include "SDL.h"
#define SPRITEBATCH_IMPLEMENTATION
#include <limits.h> // Needed by `cute_spritebatch.h` for `INT_MAX`
#include "cute_spritebatch.h"
#include "../../WindowsWrapper.h" #include "../../WindowsWrapper.h"
#include "../../Draw.h" #include "../../Draw.h"
@ -30,7 +34,7 @@ typedef struct Backend_Surface
typedef struct Backend_Glyph typedef struct Backend_Glyph
{ {
SDL_Texture *texture; unsigned char *pixels;
unsigned int width; unsigned int width;
unsigned int height; unsigned int height;
} Backend_Glyph; } Backend_Glyph;
@ -44,6 +48,8 @@ static Backend_Surface *surface_list_head;
static unsigned char glyph_colour_channels[3]; static unsigned char glyph_colour_channels[3];
static spritebatch_t glyph_batcher;
static void RectToSDLRect(const RECT *rect, SDL_Rect *sdl_rect) static void RectToSDLRect(const RECT *rect, SDL_Rect *sdl_rect)
{ {
sdl_rect->x = (int)rect->left; sdl_rect->x = (int)rect->left;
@ -58,6 +64,56 @@ static void RectToSDLRect(const RECT *rect, SDL_Rect *sdl_rect)
sdl_rect->h = 0; 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.
SDL_SetTextureColorMod(texture_atlas, glyph_colour_channels[0], glyph_colour_channels[1], glyph_colour_channels[2]);
SDL_SetTextureBlendMode(texture_atlas, SDL_BLENDMODE_BLEND);
for (int i = 0; i < count; ++i)
{
SDL_Rect destination_rect = {(int)sprites[i].x, (int)sprites[i].y, texture_w, texture_h};
SDL_RenderCopy(renderer, texture_atlas, NULL, &destination_rect);
}
}
// Upload the glyph's pixels
static void GlyphBatch_GetPixels(SPRITEBATCH_U64 image_id, void* buffer, int bytes_to_fill, void* udata)
{
(void)udata;
Backend_Glyph *glyph = (Backend_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);
SDL_UpdateTexture(texture, NULL, pixels, w * 4);
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);
}
Backend_Surface* Backend_Init(const char *title, int width, int height, BOOL fullscreen) Backend_Surface* Backend_Init(const char *title, int width, int height, BOOL fullscreen)
{ {
#ifndef NDEBUG #ifndef NDEBUG
@ -110,6 +166,14 @@ Backend_Surface* Backend_Init(const char *title, int width, int height, BOOL ful
framebuffer.width = width; framebuffer.width = width;
framebuffer.height = height; framebuffer.height = height;
spritebatch_config_t config;
spritebatch_set_default_config(&config);
config.batch_callback = GlyphBatch_Draw;
config.get_pixels_callback = GlyphBatch_GetPixels;
config.generate_texture_callback = GlyphBatch_CreateTexture;
config.delete_texture_callback = GlyphBatch_DestroyTexture;
spritebatch_init(&glyph_batcher, &config, NULL);
return &framebuffer; return &framebuffer;
} }
else else
@ -301,24 +365,15 @@ Backend_Glyph* Backend_LoadGlyph(const unsigned char *pixels, unsigned int width
if (glyph == NULL) if (glyph == NULL)
return NULL; return NULL;
glyph->texture = SDL_CreateTexture(renderer, SDL_PIXELFORMAT_RGBA32, SDL_TEXTUREACCESS_STATIC, width, height); glyph->pixels = (unsigned char*)malloc(width * height * 4);
if (glyph->texture == NULL) if (glyph->pixels == NULL)
{ {
free(glyph); free(glyph);
return NULL; return NULL;
} }
unsigned char *buffer = (unsigned char*)malloc(width * height * 4); unsigned char *destination_pointer = glyph->pixels;
if (buffer == NULL)
{
SDL_DestroyTexture(glyph->texture);
free(glyph);
return NULL;
}
unsigned char *destination_pointer = buffer;
switch (pixel_mode) switch (pixel_mode)
{ {
@ -360,9 +415,6 @@ Backend_Glyph* Backend_LoadGlyph(const unsigned char *pixels, unsigned int width
break; break;
} }
SDL_UpdateTexture(glyph->texture, NULL, buffer, width * 4);
free(buffer);
glyph->width = width; glyph->width = width;
glyph->height = height; glyph->height = height;
@ -374,7 +426,7 @@ void Backend_UnloadGlyph(Backend_Glyph *glyph)
if (glyph == NULL) if (glyph == NULL)
return; return;
SDL_DestroyTexture(glyph->texture); free(glyph->pixels);
free(glyph); free(glyph);
} }
@ -390,18 +442,14 @@ void Backend_PrepareToDrawGlyphs(Backend_Surface *destination_surface, const uns
void Backend_DrawGlyph(Backend_Glyph *glyph, long x, long y) void Backend_DrawGlyph(Backend_Glyph *glyph, long x, long y)
{ {
// The SDL_Texture side of things uses alpha, not a colour-key, so the bug where the font is blended spritebatch_push(&glyph_batcher, (SPRITEBATCH_U64)glyph, glyph->width, glyph->height, x, y, 1.0f, 1.0f, 0.0f, 0.0f, 0);
// with the colour key doesn't occur. }
if (glyph == NULL) void Backend_FlushGlyphs(void)
return; {
spritebatch_tick(&glyph_batcher);
SDL_Rect destination_rect = {(int)x, (int)y, (int)glyph->width, (int)glyph->height}; spritebatch_defrag(&glyph_batcher);
spritebatch_flush(&glyph_batcher);
// Blit the texture
SDL_SetTextureColorMod(glyph->texture, glyph_colour_channels[0], glyph_colour_channels[1], glyph_colour_channels[2]);
SDL_SetTextureBlendMode(glyph->texture, SDL_BLENDMODE_BLEND);
SDL_RenderCopy(renderer, glyph->texture, NULL, &destination_rect);
} }
void Backend_HandleRenderTargetLoss(void) void Backend_HandleRenderTargetLoss(void)

View file

@ -451,6 +451,11 @@ void Backend_DrawGlyph(Backend_Glyph *glyph, long x, long y)
} }
} }
void Backend_FlushGlyphs(void)
{
}
void Backend_HandleRenderTargetLoss(void) void Backend_HandleRenderTargetLoss(void)
{ {
// No problem for us // No problem for us

View file

@ -1146,6 +1146,8 @@ void DrawText(FontObject *font_object, Backend_Surface *surface, int x, int y, u
pen_x += glyph->x_advance; pen_x += glyph->x_advance;
} }
} }
Backend_FlushGlyphs();
} }
} }