ref: 639039ce3ae8d1c9b2b09692bf9e682925e3a831
parent: fa8ab56e9359ff0db40bf89a52a972d1d19b26cd
author: Clownacy <Clownacy@users.noreply.github.com>
date: Sat Feb 1 11:40:23 EST 2020
Added Backend_PrepareToDrawGlyphs This is to reduce OpenGL context changes, and help pave the way for glyph-batching
--- a/src/Backends/Rendering.h
+++ b/src/Backends/Rendering.h
@@ -28,6 +28,7 @@
BOOL Backend_SupportsSubpixelGlyphs(void);
Backend_Glyph* Backend_LoadGlyph(const unsigned char *pixels, unsigned int width, unsigned int height, int pitch, FontPixelMode pixel_mode);
void Backend_UnloadGlyph(Backend_Glyph *glyph);
-void Backend_DrawGlyph(Backend_Surface *surface, Backend_Glyph *glyph, long x, long y, const unsigned char *colours);
+void Backend_PrepareToDrawGlyphs(Backend_Surface *destination_surface, const unsigned char *colour_channels);
+void Backend_DrawGlyph(Backend_Glyph *glyph, long x, long y);
void Backend_HandleRenderTargetLoss(void);
void Backend_HandleWindowResize(void);
--- a/src/Backends/Rendering/OpenGL3.cpp
+++ b/src/Backends/Rendering/OpenGL3.cpp
@@ -95,6 +95,9 @@
static Backend_Surface framebuffer;
+static unsigned char glyph_colour_channels[3];
+static Backend_Surface *glyph_destination_surface;
+
#ifdef USE_OPENGLES2
static const GLchar *vertex_shader_plain = " \
#version 100\n \
@@ -976,8 +979,18 @@
free(glyph);
}
-void Backend_DrawGlyph(Backend_Surface *surface, Backend_Glyph *glyph, long x, long y, const unsigned char *colours)
+void Backend_PrepareToDrawGlyphs(Backend_Surface *destination_surface, const unsigned char *colour_channels)
{
+ if (destination_surface == NULL)
+ return;
+
+ glyph_destination_surface = destination_surface;
+
+ memcpy(glyph_colour_channels, colour_channels, sizeof(glyph_colour_channels));
+}
+
+void Backend_DrawGlyph(Backend_Glyph *glyph, long x, long y)
+{
static Backend_Surface *last_surface;
static Backend_Glyph *last_glyph;
static unsigned char last_red;
@@ -984,36 +997,36 @@
static unsigned char last_green;
static unsigned char last_blue;
- if (glyph == NULL || surface == NULL)
+ if (glyph == NULL || glyph_destination_surface == NULL)
return;
const RenderMode render_mode = (glyph->pixel_mode == FONT_PIXEL_MODE_LCD ? MODE_DRAW_GLYPH_LCD : MODE_DRAW_GLYPH);
- if (last_render_mode != render_mode || last_surface != surface || last_glyph != glyph || last_red != colours[0] || last_green != colours[1] || last_blue != colours[2])
+ if (last_render_mode != render_mode || last_surface != glyph_destination_surface || last_glyph != glyph || last_red != glyph_colour_channels[0] || last_green != glyph_colour_channels[1] || last_blue != glyph_colour_channels[2])
{
FlushVertexBuffer();
last_render_mode = render_mode;
- last_surface = surface;
+ last_surface = glyph_destination_surface;
last_glyph = glyph;
- last_red = colours[0];
- last_green = colours[1];
- last_blue = colours[2];
+ last_red = glyph_colour_channels[0];
+ last_green = glyph_colour_channels[1];
+ last_blue = glyph_colour_channels[2];
if (glyph->pixel_mode == FONT_PIXEL_MODE_LCD)
{
glUseProgram(program_glyph_subpixel_part2);
- glUniform4f(program_glyph_subpixel_part2_uniform_colour, colours[0] / 255.0f, colours[1] / 255.0f, colours[2] / 255.0f, 1.0f);
+ glUniform4f(program_glyph_subpixel_part2_uniform_colour, glyph_colour_channels[0] / 255.0f, glyph_colour_channels[1] / 255.0f, glyph_colour_channels[2] / 255.0f, 1.0f);
}
else
{
glUseProgram(program_glyph_normal);
- glUniform4f(program_glyph_normal_uniform_colour, colours[0] / 255.0f, colours[1] / 255.0f, colours[2] / 255.0f, 1.0f);
+ glUniform4f(program_glyph_normal_uniform_colour, glyph_colour_channels[0] / 255.0f, glyph_colour_channels[1] / 255.0f, glyph_colour_channels[2] / 255.0f, 1.0f);
}
// Point our framebuffer to the destination texture
- glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, surface->texture_id, 0);
- glViewport(0, 0, surface->width, surface->height);
+ glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, glyph_destination_surface->texture_id, 0);
+ glViewport(0, 0, glyph_destination_surface->width, glyph_destination_surface->height);
glEnable(GL_BLEND);
@@ -1023,10 +1036,10 @@
glBindTexture(GL_TEXTURE_2D, glyph->texture_id);
}
- const GLfloat vertex_left = (x * (2.0f / surface->width)) - 1.0f;
- const GLfloat vertex_right = ((x + glyph->width) * (2.0f / surface->width)) - 1.0f;
- const GLfloat vertex_top = (y * (2.0f / surface->height)) - 1.0f;
- const GLfloat vertex_bottom = ((y + glyph->height) * (2.0f / surface->height)) - 1.0f;
+ const GLfloat vertex_left = (x * (2.0f / glyph_destination_surface->width)) - 1.0f;
+ const GLfloat vertex_right = ((x + glyph->width) * (2.0f / glyph_destination_surface->width)) - 1.0f;
+ const GLfloat vertex_top = (y * (2.0f / glyph_destination_surface->height)) - 1.0f;
+ const GLfloat vertex_bottom = ((y + glyph->height) * (2.0f / glyph_destination_surface->height)) - 1.0f;
VertexBufferSlot *vertex_buffer_slot = GetVertexBufferSlot();
--- a/src/Backends/Rendering/SDLSurface.cpp
+++ b/src/Backends/Rendering/SDLSurface.cpp
@@ -24,6 +24,9 @@
static Backend_Surface framebuffer;
+static unsigned char glyph_colour_channels[3];
+static SDL_Surface *glyph_destination_sdlsurface;
+
static void RectToSDLRect(const RECT *rect, SDL_Rect *sdl_rect)
{
sdl_rect->x = (int)rect->left;
@@ -243,11 +246,21 @@
free(glyph);
}
-void Backend_DrawGlyph(Backend_Surface *surface, Backend_Glyph *glyph, long x, long y, const unsigned char *colours)
+void Backend_PrepareToDrawGlyphs(Backend_Surface *destination_surface, const unsigned char *colour_channels)
{
- if (glyph == NULL || surface == NULL)
+ if (destination_surface == NULL)
return;
+ glyph_destination_sdlsurface = destination_surface->sdlsurface;
+
+ memcpy(glyph_colour_channels, colour_channels, sizeof(glyph_colour_channels));
+}
+
+void Backend_DrawGlyph(Backend_Glyph *glyph, long x, long y)
+{
+ if (glyph == NULL)
+ return;
+
SDL_Rect rect;
rect.x = x;
rect.y = y;
@@ -254,9 +267,9 @@
rect.w = glyph->sdlsurface->w;
rect.h = glyph->sdlsurface->h;
- SDL_SetSurfaceColorMod(glyph->sdlsurface, colours[0], colours[1], colours[2]);
+ SDL_SetSurfaceColorMod(glyph->sdlsurface, glyph_colour_channels[0], glyph_colour_channels[1], glyph_colour_channels[2]);
- SDL_BlitSurface(glyph->sdlsurface, NULL, surface->sdlsurface, &rect);
+ SDL_BlitSurface(glyph->sdlsurface, NULL, glyph_destination_sdlsurface, &rect);
}
void Backend_HandleRenderTargetLoss(void)
--- a/src/Backends/Rendering/SDLTexture.cpp
+++ b/src/Backends/Rendering/SDLTexture.cpp
@@ -42,6 +42,8 @@
static Backend_Surface *surface_list_head;
+static unsigned char glyph_colour_channels[3];
+
static void RectToSDLRect(const RECT *rect, SDL_Rect *sdl_rect)
{
sdl_rect->x = (int)rect->left;
@@ -376,20 +378,29 @@
free(glyph);
}
-void Backend_DrawGlyph(Backend_Surface *surface, Backend_Glyph *glyph, long x, long y, const unsigned char *colours)
+void Backend_PrepareToDrawGlyphs(Backend_Surface *destination_surface, const unsigned char *colour_channels)
{
+ if (destination_surface == NULL)
+ return;
+
+ SDL_SetRenderTarget(renderer, destination_surface->texture);
+
+ memcpy(glyph_colour_channels, colour_channels, sizeof(glyph_colour_channels));
+}
+
+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.
- if (glyph == NULL || surface == NULL)
+ 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, colours[0], colours[1], colours[2]);
+ SDL_SetTextureColorMod(glyph->texture, glyph_colour_channels[0], glyph_colour_channels[1], glyph_colour_channels[2]);
SDL_SetTextureBlendMode(glyph->texture, SDL_BLENDMODE_BLEND);
- SDL_SetRenderTarget(renderer, surface->texture);
SDL_RenderCopy(renderer, glyph->texture, NULL, &destination_rect);
}
--- a/src/Backends/Rendering/Software.cpp
+++ b/src/Backends/Rendering/Software.cpp
@@ -34,6 +34,9 @@
static SDL_Surface *framebuffer_sdlsurface;
static Backend_Surface framebuffer;
+static unsigned char glyph_colour_channels[3];
+static Backend_Surface *glyph_destination_surface;
+
Backend_Surface* Backend_Init(const char *title, int width, int height, BOOL fullscreen)
{
window = SDL_CreateWindow(title, SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, width, height, 0);
@@ -371,28 +374,38 @@
free(glyph);
}
-void Backend_DrawGlyph(Backend_Surface *surface, Backend_Glyph *glyph, long x, long y, const unsigned char *colours)
+void Backend_PrepareToDrawGlyphs(Backend_Surface *destination_surface, const unsigned char *colour_channels)
{
- if (glyph == NULL || surface == NULL)
+ if (destination_surface == NULL)
return;
+ glyph_destination_surface = destination_surface;
+
+ memcpy(glyph_colour_channels, colour_channels, sizeof(glyph_colour_channels));
+}
+
+void Backend_DrawGlyph(Backend_Glyph *glyph, long x, long y)
+{
+ if (glyph == NULL)
+ return;
+
switch (glyph->pixel_mode)
{
case FONT_PIXEL_MODE_LCD:
- for (unsigned int iy = MAX(-y, 0); y + iy < MIN(y + glyph->height, surface->height); ++iy)
+ for (unsigned int iy = MAX(-y, 0); y + iy < MIN(y + glyph->height, glyph_destination_surface->height); ++iy)
{
- for (unsigned int ix = MAX(-x, 0); x + ix < MIN(x + glyph->width, surface->width); ++ix)
+ for (unsigned int ix = MAX(-x, 0); x + ix < MIN(x + glyph->width, glyph_destination_surface->width); ++ix)
{
const float *font_pixel = (float*)glyph->pixels + (iy * glyph->width + ix) * 3;
if (font_pixel[0] || font_pixel[1] || font_pixel[2])
{
- unsigned char *bitmap_pixel = surface->pixels + (y + iy) * surface->pitch + (x + ix) * 3;
+ unsigned char *bitmap_pixel = glyph_destination_surface->pixels + (y + iy) * glyph_destination_surface->pitch + (x + ix) * 3;
for (unsigned int j = 0; j < 3; ++j)
{
const float alpha = font_pixel[j];
- bitmap_pixel[j] = (unsigned char)((colours[j] * alpha) + (bitmap_pixel[j] * (1.0f - alpha))); // Alpha blending
+ bitmap_pixel[j] = (unsigned char)((glyph_colour_channels[j] * alpha) + (bitmap_pixel[j] * (1.0f - alpha))); // Alpha blending
}
}
}
@@ -401,18 +414,18 @@
break;
case FONT_PIXEL_MODE_GRAY:
- for (unsigned int iy = MAX(-y, 0); y + iy < MIN(y + glyph->height, surface->height); ++iy)
+ for (unsigned int iy = MAX(-y, 0); y + iy < MIN(y + glyph->height, glyph_destination_surface->height); ++iy)
{
- for (unsigned int ix = MAX(-x, 0); x + ix < MIN(x + glyph->width, surface->width); ++ix)
+ for (unsigned int ix = MAX(-x, 0); x + ix < MIN(x + glyph->width, glyph_destination_surface->width); ++ix)
{
const float alpha = ((float*)glyph->pixels)[iy * glyph->width + ix];
if (alpha)
{
- unsigned char *bitmap_pixel = surface->pixels + (y + iy) * surface->pitch + (x + ix) * 3;
+ unsigned char *bitmap_pixel = glyph_destination_surface->pixels + (y + iy) * glyph_destination_surface->pitch + (x + ix) * 3;
for (unsigned int j = 0; j < 3; ++j)
- bitmap_pixel[j] = (unsigned char)((colours[j] * alpha) + (bitmap_pixel[j] * (1.0f - alpha))); // Alpha blending
+ bitmap_pixel[j] = (unsigned char)((glyph_colour_channels[j] * alpha) + (bitmap_pixel[j] * (1.0f - alpha))); // Alpha blending
}
}
}
@@ -420,16 +433,16 @@
break;
case FONT_PIXEL_MODE_MONO:
- for (unsigned int iy = MAX(-y, 0); y + iy < MIN(y + glyph->height, surface->height); ++iy)
+ for (unsigned int iy = MAX(-y, 0); y + iy < MIN(y + glyph->height, glyph_destination_surface->height); ++iy)
{
- for (unsigned int ix = MAX(-x, 0); x + ix < MIN(x + glyph->width, surface->width); ++ix)
+ for (unsigned int ix = MAX(-x, 0); x + ix < MIN(x + glyph->width, glyph_destination_surface->width); ++ix)
{
if (((unsigned char*)glyph->pixels)[iy * glyph->width + ix])
{
- unsigned char *bitmap_pixel = surface->pixels + (y + iy) * surface->pitch + (x + ix) * 3;
+ unsigned char *bitmap_pixel = glyph_destination_surface->pixels + (y + iy) * glyph_destination_surface->pitch + (x + ix) * 3;
for (unsigned int j = 0; j < 3; ++j)
- bitmap_pixel[j] = colours[j];
+ bitmap_pixel[j] = glyph_colour_channels[j];
}
}
}
--- a/src/Font.cpp
+++ b/src/Font.cpp
@@ -1114,8 +1114,10 @@
{
if (font_object != NULL)
{
- const unsigned char colours[3] = {(unsigned char)colour, (unsigned char)(colour >> 8), (unsigned char)(colour >> 16)};
+ const unsigned char colour_channels[3] = {(unsigned char)colour, (unsigned char)(colour >> 8), (unsigned char)(colour >> 16)};
+ Backend_PrepareToDrawGlyphs(surface, colour_channels);
+
unsigned int pen_x = 0;
const unsigned char *string_pointer = (unsigned char*)string;
@@ -1139,7 +1141,7 @@
const int letter_y = y + glyph->y;
if (glyph->backend != NULL)
- Backend_DrawGlyph(surface, glyph->backend, letter_x, letter_y, colours);
+ Backend_DrawGlyph(glyph->backend, letter_x, letter_y);
pen_x += glyph->x_advance;
}
--
⑨