ref: eaf2de05b693ee726d5c0ac9a911ebdad5b85214
parent: 639039ce3ae8d1c9b2b09692bf9e682925e3a831
author: Clownacy <[email protected]>
date: Sat Feb 1 12:49:26 EST 2020
Add glyph-batching to the SDLTexture backend Hope it will be this easy for the OpenGL backend
--- a/src/Backends/Rendering.h
+++ b/src/Backends/Rendering.h
@@ -30,5 +30,6 @@
void Backend_UnloadGlyph(Backend_Glyph *glyph);
void Backend_PrepareToDrawGlyphs(Backend_Surface *destination_surface, const unsigned char *colour_channels);
void Backend_DrawGlyph(Backend_Glyph *glyph, long x, long y);
+void Backend_FlushGlyphs(void);
void Backend_HandleRenderTargetLoss(void);
void Backend_HandleWindowResize(void);
--- a/src/Backends/Rendering/OpenGL3.cpp
+++ b/src/Backends/Rendering/OpenGL3.cpp
@@ -1072,6 +1072,11 @@
vertex_buffer_slot->vertices[1][2].vertex_coordinate.y = vertex_bottom;
}
+void Backend_FlushGlyphs(void)
+{
+
+}
+
void Backend_HandleRenderTargetLoss(void)
{
// No problem for us
--- a/src/Backends/Rendering/SDLTexture.cpp
+++ b/src/Backends/Rendering/SDLTexture.cpp
@@ -8,6 +8,10 @@
#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 "../../Draw.h"
@@ -30,7 +34,7 @@
typedef struct Backend_Glyph
{
- SDL_Texture *texture;
+ unsigned char *pixels;
unsigned int width;
unsigned int height;
} Backend_Glyph;
@@ -44,6 +48,8 @@
static unsigned char glyph_colour_channels[3];
+static spritebatch_t glyph_batcher;
+
static void RectToSDLRect(const RECT *rect, SDL_Rect *sdl_rect)
{
sdl_rect->x = (int)rect->left;
@@ -58,6 +64,56 @@
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)
{
#ifndef NDEBUG
@@ -110,6 +166,14 @@
framebuffer.width = width;
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;
}
else
@@ -301,25 +365,16 @@
if (glyph == 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);
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)
{
case FONT_PIXEL_MODE_LCD:
@@ -360,9 +415,6 @@
break;
}
- SDL_UpdateTexture(glyph->texture, NULL, buffer, width * 4);
- free(buffer);
-
glyph->width = width;
glyph->height = height;
@@ -374,7 +426,7 @@
if (glyph == NULL)
return;
- SDL_DestroyTexture(glyph->texture);
+ free(glyph->pixels);
free(glyph);
}
@@ -390,18 +442,14 @@
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
- // with the colour key doesn't occur.
+ spritebatch_push(&glyph_batcher, (SPRITEBATCH_U64)glyph, glyph->width, glyph->height, x, y, 1.0f, 1.0f, 0.0f, 0.0f, 0);
+}
- if (glyph == NULL)
- return;
-
- SDL_Rect destination_rect = {(int)x, (int)y, (int)glyph->width, (int)glyph->height};
-
- // 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_FlushGlyphs(void)
+{
+ spritebatch_tick(&glyph_batcher);
+ spritebatch_defrag(&glyph_batcher);
+ spritebatch_flush(&glyph_batcher);
}
void Backend_HandleRenderTargetLoss(void)
--- a/src/Backends/Rendering/Software.cpp
+++ b/src/Backends/Rendering/Software.cpp
@@ -451,6 +451,11 @@
}
}
+void Backend_FlushGlyphs(void)
+{
+
+}
+
void Backend_HandleRenderTargetLoss(void)
{
// No problem for us
--- a/src/Font.cpp
+++ b/src/Font.cpp
@@ -1146,6 +1146,8 @@
pen_x += glyph->x_advance;
}
}
+
+ Backend_FlushGlyphs();
}
}