shithub: cstory

Download patch

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;
 			}
--