diff --git a/Makefile b/Makefile
index 67697bfd83..033fcbd993 100644
--- a/Makefile
+++ b/Makefile
@@ -105,7 +105,7 @@ ifeq ($(HAVE_SDL), 1)
LIBS += $(SDL_LIBS)
ifeq ($(HAVE_OPENGL), 1)
- OBJ += gfx/gl.o
+ OBJ += gfx/gl.o gfx/gl_font.o
ifeq ($(OSX),1)
LIBS += -framework OpenGL
else
diff --git a/Makefile.win b/Makefile.win
index ddb5eebae5..9782ef8a81 100644
--- a/Makefile.win
+++ b/Makefile.win
@@ -39,7 +39,7 @@ ifeq ($(TDM_GCC),)
endif
ifeq ($(HAVE_SDL), 1)
- OBJ += gfx/sdl_gfx.o gfx/gl.o gfx/context/sdl_ctx.o input/sdl_input.o audio/sdl_audio.o fifo_buffer.o
+ OBJ += gfx/sdl_gfx.o gfx/gl.o gfx/gl_font.o gfx/context/sdl_ctx.o input/sdl_input.o audio/sdl_audio.o fifo_buffer.o
LIBS += -lSDL
DEFINES += -ISDL -DHAVE_SDL
endif
diff --git a/gfx/gl.c b/gfx/gl.c
index 0d0e38c789..25fa0a660c 100644
--- a/gfx/gl.c
+++ b/gfx/gl.c
@@ -13,7 +13,6 @@
* If not, see .
*/
-
#include "../driver.h"
#include
@@ -28,6 +27,7 @@
#endif
#include "gl_common.h"
+#include "gl_font.h"
#include "gfx_common.h"
#include "gfx_context.h"
#include "../compat/strl.h"
@@ -138,72 +138,6 @@ static inline bool load_gl_proc(void)
static inline bool load_gl_proc(void) { return true; }
#endif
-#define MAX_SHADERS 16
-
-#if defined(HAVE_XML) || defined(HAVE_CG)
-#define TEXTURES 8
-#else
-#define TEXTURES 1
-#endif
-#define TEXTURES_MASK (TEXTURES - 1)
-
-typedef struct gl
-{
- bool vsync;
- GLuint texture[TEXTURES];
- unsigned tex_index; // For use with PREV.
- struct gl_tex_info prev_info[TEXTURES];
- GLuint tex_filter;
-
- void *empty_buf;
-
- unsigned frame_count;
-
-#ifdef HAVE_FBO
- // Render-to-texture, multipass shaders
- GLuint fbo[MAX_SHADERS];
- GLuint fbo_texture[MAX_SHADERS];
- struct gl_fbo_rect fbo_rect[MAX_SHADERS];
- struct gl_fbo_scale fbo_scale[MAX_SHADERS];
- bool render_to_tex;
- int fbo_pass;
- bool fbo_inited;
-#endif
-
- bool should_resize;
- bool quitting;
- bool fullscreen;
- bool keep_aspect;
- unsigned rotation;
-
- unsigned full_x, full_y;
-
- unsigned win_width;
- unsigned win_height;
- unsigned vp_width, vp_out_width;
- unsigned vp_height, vp_out_height;
- unsigned last_width[TEXTURES];
- unsigned last_height[TEXTURES];
- unsigned tex_w, tex_h;
- GLfloat tex_coords[8];
-
- GLenum texture_type; // XBGR1555 or ARGB
- GLenum texture_fmt;
- unsigned base_size; // 2 or 4
-
-#ifdef HAVE_FREETYPE
- font_renderer_t *font;
- GLuint font_tex;
- int font_tex_w, font_tex_h;
- void *font_tex_empty_buf;
- char font_last_msg[256];
- int font_last_width, font_last_height;
- GLfloat font_color[16];
- GLfloat font_color_dark[16];
-#endif
-
-} gl_t;
-
////////////////// Shaders
static bool gl_shader_init(void)
{
@@ -357,57 +291,6 @@ static void gl_shader_scale(unsigned index, struct gl_fbo_scale *scale)
#endif
///////////////////
-//////////////// Message rendering
-static inline void gl_init_font(gl_t *gl, const char *font_path, unsigned font_size)
-{
-#ifdef HAVE_FREETYPE
- if (!g_settings.video.font_enable)
- return;
-
- const char *path = font_path;
- if (!*path)
- path = font_renderer_get_default_font();
-
- if (path)
- {
- gl->font = font_renderer_new(path, font_size);
- if (gl->font)
- {
- glGenTextures(1, &gl->font_tex);
- glBindTexture(GL_TEXTURE_2D, gl->font_tex);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_BORDER);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_BORDER);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
- glBindTexture(GL_TEXTURE_2D, gl->texture[gl->tex_index]);
- }
- else
- RARCH_WARN("Couldn't init font renderer with font \"%s\"...\n", font_path);
- }
- else
- RARCH_LOG("Did not find default font.\n");
-
- for (unsigned i = 0; i < 4; i++)
- {
- gl->font_color[4 * i + 0] = g_settings.video.msg_color_r;
- gl->font_color[4 * i + 1] = g_settings.video.msg_color_g;
- gl->font_color[4 * i + 2] = g_settings.video.msg_color_b;
- gl->font_color[4 * i + 3] = 1.0;
- }
-
- for (unsigned i = 0; i < 4; i++)
- {
- for (unsigned j = 0; j < 3; j++)
- gl->font_color_dark[4 * i + j] = 0.3 * gl->font_color[4 * i + j];
- gl->font_color_dark[4 * i + 3] = 1.0;
- }
-
-#else
- (void)gl;
- (void)font_path;
- (void)font_size;
-#endif
-}
#ifdef HAVE_FBO
static void gl_compute_fbo_geometry(gl_t *gl, unsigned width, unsigned height,
@@ -544,34 +427,8 @@ static void gl_init_fbo(gl_t *gl, unsigned width, unsigned height)
}
#endif
-static inline void gl_deinit_font(gl_t *gl)
-{
-#ifdef HAVE_FREETYPE
- if (gl->font)
- {
- font_renderer_free(gl->font);
- glDeleteTextures(1, &gl->font_tex);
-
- if (gl->font_tex_empty_buf)
- free(gl->font_tex_empty_buf);
- }
-#else
- (void)gl;
-#endif
-}
////////////
-static inline unsigned get_alignment(unsigned pitch)
-{
- if (pitch & 1)
- return 1;
- if (pitch & 2)
- return 2;
- if (pitch & 4)
- return 4;
- return 8;
-}
-
static void set_projection(gl_t *gl, bool allow_rotate)
{
glMatrixMode(GL_PROJECTION);
@@ -636,209 +493,6 @@ static void gl_set_rotation(void *data, unsigned rotation)
set_projection(gl, true);
}
-#ifdef HAVE_FREETYPE
-
-// Somewhat overwhelming code just to render some damn fonts.
-// We aim to use NPOT textures for compatibility with old and shitty cards.
-// Also, we want to avoid reallocating a texture for each glyph (performance dips), so we
-// contruct the whole texture using one call, and copy straight to it with
-// glTexSubImage.
-
-struct font_rect
-{
- int x, y;
- int width, height;
- int pot_width, pot_height;
-};
-
-static void calculate_msg_geometry(const struct font_output *head, struct font_rect *rect)
-{
- int x_min = head->off_x;
- int x_max = head->off_x + head->width;
- int y_min = head->off_y;
- int y_max = head->off_y + head->height;
-
- while ((head = head->next))
- {
- int left = head->off_x;
- int right = head->off_x + head->width;
- int bottom = head->off_y;
- int top = head->off_y + head->height;
-
- if (left < x_min)
- x_min = left;
- if (right > x_max)
- x_max = right;
-
- if (bottom < y_min)
- y_min = bottom;
- if (top > y_max)
- y_max = top;
- }
-
- rect->x = x_min;
- rect->y = y_min;
- rect->width = x_max - x_min;
- rect->height = y_max - y_min;
-}
-
-static void adjust_power_of_two(gl_t *gl, struct font_rect *geom)
-{
- // Some systems really hate NPOT textures.
- geom->pot_width = next_pow2(geom->width);
- geom->pot_height = next_pow2(geom->height);
-
- if ((geom->pot_width > gl->font_tex_w) || (geom->pot_height > gl->font_tex_h))
- {
- gl->font_tex_empty_buf = realloc(gl->font_tex_empty_buf, geom->pot_width * geom->pot_height);
- memset(gl->font_tex_empty_buf, 0, geom->pot_width * geom->pot_height);
-
- glPixelStorei(GL_UNPACK_ALIGNMENT, 8);
- glPixelStorei(GL_UNPACK_ROW_LENGTH, geom->pot_width);
- glTexImage2D(GL_TEXTURE_2D, 0, GL_INTENSITY8, geom->pot_width, geom->pot_height,
- 0, GL_LUMINANCE, GL_UNSIGNED_BYTE, gl->font_tex_empty_buf);
-
- gl->font_tex_w = geom->pot_width;
- gl->font_tex_h = geom->pot_height;
- }
-}
-
-// Old style "blitting", so we can render all the fonts in one go.
-// TODO: Is it possible that fonts could overlap if we blit without alpha blending?
-static void blit_fonts(gl_t *gl, const struct font_output *head, const struct font_rect *geom)
-{
- // Clear out earlier fonts.
- glPixelStorei(GL_UNPACK_ALIGNMENT, 8);
- glPixelStorei(GL_UNPACK_ROW_LENGTH, gl->font_tex_w);
- glTexSubImage2D(GL_TEXTURE_2D,
- 0, 0, 0, gl->font_tex_w, gl->font_tex_h,
- GL_LUMINANCE, GL_UNSIGNED_BYTE, gl->font_tex_empty_buf);
-
- while (head)
- {
- // head has top-left oriented coords.
- int x = head->off_x - geom->x;
- int y = head->off_y - geom->y;
- y = gl->font_tex_h - head->height - y - 1;
-
- glPixelStorei(GL_UNPACK_ALIGNMENT, get_alignment(head->pitch));
- glPixelStorei(GL_UNPACK_ROW_LENGTH, head->pitch);
- glTexSubImage2D(GL_TEXTURE_2D,
- 0, x, y, head->width, head->height,
- GL_LUMINANCE, GL_UNSIGNED_BYTE, head->output);
-
- head = head->next;
- }
-}
-
-static void calculate_font_coords(gl_t *gl,
- GLfloat font_vertex[8], GLfloat font_vertex_dark[8], GLfloat font_tex_coords[8])
-{
- GLfloat scale_factor = g_settings.video.font_scale ?
- (GLfloat)gl->full_x / (GLfloat)gl->vp_width :
- 1.0f;
-
- GLfloat lx = g_settings.video.msg_pos_x;
- GLfloat hx = (GLfloat)gl->font_last_width / (gl->vp_width * scale_factor) + lx;
- GLfloat ly = g_settings.video.msg_pos_y;
- GLfloat hy = (GLfloat)gl->font_last_height / (gl->vp_height * scale_factor) + ly;
-
- font_vertex[0] = lx;
- font_vertex[1] = ly;
- font_vertex[2] = lx;
- font_vertex[3] = hy;
- font_vertex[4] = hx;
- font_vertex[5] = hy;
- font_vertex[6] = hx;
- font_vertex[7] = ly;
-
- GLfloat shift_x = 2.0f / gl->vp_width;
- GLfloat shift_y = 2.0f / gl->vp_height;
- for (unsigned i = 0; i < 4; i++)
- {
- font_vertex_dark[2 * i + 0] = font_vertex[2 * i + 0] - shift_x;
- font_vertex_dark[2 * i + 1] = font_vertex[2 * i + 1] - shift_y;
- }
-
- lx = 0.0f;
- hx = (GLfloat)gl->font_last_width / gl->font_tex_w;
- ly = 1.0f - (GLfloat)gl->font_last_height / gl->font_tex_h;
- hy = 1.0f;
-
- font_tex_coords[0] = lx;
- font_tex_coords[1] = hy;
- font_tex_coords[2] = lx;
- font_tex_coords[3] = ly;
- font_tex_coords[4] = hx;
- font_tex_coords[5] = ly;
- font_tex_coords[6] = hx;
- font_tex_coords[7] = hy;
-}
-
-static void gl_render_msg(gl_t *gl, const char *msg)
-{
- if (!gl->font)
- return;
-
- GLfloat font_vertex[8];
- GLfloat font_vertex_dark[8];
- GLfloat font_tex_coords[8];
-
- // Deactivate custom shaders. Enable the font texture.
- gl_shader_use(0);
- set_viewport(gl, gl->win_width, gl->win_height, false, false);
- glBindTexture(GL_TEXTURE_2D, gl->font_tex);
- glTexCoordPointer(2, GL_FLOAT, 0, font_tex_coords);
-
- // Need blending.
- // Using fixed function pipeline here since we cannot guarantee presence of shaders (would be kinda overkill anyways).
- glEnable(GL_BLEND);
-
- struct font_output_list out;
-
- // If we get the same message, there's obviously no need to render fonts again ...
- if (strcmp(gl->font_last_msg, msg) != 0)
- {
- font_renderer_msg(gl->font, msg, &out);
- struct font_output *head = out.head;
-
- struct font_rect geom;
- calculate_msg_geometry(head, &geom);
- adjust_power_of_two(gl, &geom);
- blit_fonts(gl, head, &geom);
-
- font_renderer_free_output(&out);
- strlcpy(gl->font_last_msg, msg, sizeof(gl->font_last_msg));
-
- gl->font_last_width = geom.width;
- gl->font_last_height = geom.height;
- }
- calculate_font_coords(gl, font_vertex, font_vertex_dark, font_tex_coords);
-
- glVertexPointer(2, GL_FLOAT, 0, font_vertex_dark);
- glColorPointer(4, GL_FLOAT, 0, gl->font_color_dark);
- glDrawArrays(GL_QUADS, 0, 4);
- glVertexPointer(2, GL_FLOAT, 0, font_vertex);
- glColorPointer(4, GL_FLOAT, 0, gl->font_color);
- glDrawArrays(GL_QUADS, 0, 4);
-
- // Go back to old rendering path.
- glTexCoordPointer(2, GL_FLOAT, 0, gl->tex_coords);
- glVertexPointer(2, GL_FLOAT, 0, vertexes_flipped);
- glColorPointer(4, GL_FLOAT, 0, white_color);
- glBindTexture(GL_TEXTURE_2D, gl->texture[gl->tex_index]);
-
- glDisable(GL_BLEND);
- set_projection(gl, true);
-}
-#else
-static void gl_render_msg(gl_t *gl, const char *msg)
-{
- (void)gl;
- (void)msg;
-}
-#endif
-
static inline void set_lut_texture_coords(const GLfloat *coords)
{
#if defined(HAVE_XML) || defined(HAVE_CG)
@@ -1117,6 +771,30 @@ static void gl_next_texture_index(gl_t *gl, const struct gl_tex_info *tex_info)
gl->tex_index = (gl->tex_index + 1) & TEXTURES_MASK;
}
+#ifdef HAVE_FREETYPE
+static inline void gl_render_msg_pre(gl_t *gl)
+{
+ gl_shader_use(0);
+ set_viewport(gl, gl->win_width, gl->win_height, false, false);
+ glEnable(GL_BLEND);
+}
+
+static inline void gl_render_msg_post(gl_t *gl)
+{
+ // Go back to old rendering path.
+ glTexCoordPointer(2, GL_FLOAT, 0, gl->tex_coords);
+ glVertexPointer(2, GL_FLOAT, 0, vertexes_flipped);
+ glColorPointer(4, GL_FLOAT, 0, white_color);
+ glBindTexture(GL_TEXTURE_2D, gl->texture[gl->tex_index]);
+
+ glDisable(GL_BLEND);
+ set_projection(gl, true);
+}
+#else
+#define gl_render_msg_pre(...)
+#define gl_render_msg_post(...)
+#endif
+
static bool gl_frame(void *data, const void *frame, unsigned width, unsigned height, unsigned pitch, const char *msg)
{
gl_t *gl = (gl_t*)data;
@@ -1176,7 +854,11 @@ static bool gl_frame(void *data, const void *frame, unsigned width, unsigned hei
gl_next_texture_index(gl, &tex_info);
if (msg)
+ {
+ gl_render_msg_pre(gl);
gl_render_msg(gl, msg);
+ gl_render_msg_post(gl);
+ }
gfx_ctx_update_window_title(false);
gfx_ctx_swap_buffers();
diff --git a/gfx/gl_common.h b/gfx/gl_common.h
index 369fcea228..c0b9512535 100644
--- a/gfx/gl_common.h
+++ b/gfx/gl_common.h
@@ -17,6 +17,7 @@
#define __GL_COMMON_H
#include "../general.h"
+#include "fonts.h"
#ifdef HAVE_CONFIG_H
#include "../config.h"
@@ -67,6 +68,17 @@ static inline bool gl_check_error(void)
return false;
}
+static inline unsigned get_alignment(unsigned pitch)
+{
+ if (pitch & 1)
+ return 1;
+ if (pitch & 2)
+ return 2;
+ if (pitch & 4)
+ return 4;
+ return 8;
+}
+
struct gl_fbo_rect
{
unsigned img_width;
@@ -103,6 +115,71 @@ struct gl_tex_info
GLfloat coord[8];
};
+#define MAX_SHADERS 16
+
+#if defined(HAVE_XML) || defined(HAVE_CG)
+#define TEXTURES 8
+#else
+#define TEXTURES 1
+#endif
+#define TEXTURES_MASK (TEXTURES - 1)
+
+typedef struct gl
+{
+ bool vsync;
+ GLuint texture[TEXTURES];
+ unsigned tex_index; // For use with PREV.
+ struct gl_tex_info prev_info[TEXTURES];
+ GLuint tex_filter;
+
+ void *empty_buf;
+
+ unsigned frame_count;
+
+#ifdef HAVE_FBO
+ // Render-to-texture, multipass shaders
+ GLuint fbo[MAX_SHADERS];
+ GLuint fbo_texture[MAX_SHADERS];
+ struct gl_fbo_rect fbo_rect[MAX_SHADERS];
+ struct gl_fbo_scale fbo_scale[MAX_SHADERS];
+ bool render_to_tex;
+ int fbo_pass;
+ bool fbo_inited;
+#endif
+
+ bool should_resize;
+ bool quitting;
+ bool fullscreen;
+ bool keep_aspect;
+ unsigned rotation;
+
+ unsigned full_x, full_y;
+
+ unsigned win_width;
+ unsigned win_height;
+ unsigned vp_width, vp_out_width;
+ unsigned vp_height, vp_out_height;
+ unsigned last_width[TEXTURES];
+ unsigned last_height[TEXTURES];
+ unsigned tex_w, tex_h;
+ GLfloat tex_coords[8];
+
+ GLenum texture_type; // XBGR1555 or ARGB
+ GLenum texture_fmt;
+ unsigned base_size; // 2 or 4
+
+#ifdef HAVE_FREETYPE
+ font_renderer_t *font;
+ GLuint font_tex;
+ int font_tex_w, font_tex_h;
+ void *font_tex_empty_buf;
+ char font_last_msg[256];
+ int font_last_width, font_last_height;
+ GLfloat font_color[16];
+ GLfloat font_color_dark[16];
+#endif
+} gl_t;
+
// Windows ... <_<
#if (defined(HAVE_XML) || defined(HAVE_CG)) && defined(_WIN32)
extern PFNGLCLIENTACTIVETEXTUREPROC pglClientActiveTexture;
diff --git a/gfx/gl_font.c b/gfx/gl_font.c
new file mode 100644
index 0000000000..1ce34d164d
--- /dev/null
+++ b/gfx/gl_font.c
@@ -0,0 +1,269 @@
+/* RetroArch - A frontend for libretro.
+ * Copyright (C) 2010-2012 - Hans-Kristian Arntzen
+ *
+ * RetroArch is free software: you can redistribute it and/or modify it under the terms
+ * of the GNU General Public License as published by the Free Software Found-
+ * ation, either version 3 of the License, or (at your option) any later version.
+ *
+ * RetroArch is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
+ * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+ * PURPOSE. See the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with RetroArch.
+ * If not, see .
+ */
+
+#include "gl_font.h"
+
+void gl_init_font(gl_t *gl, const char *font_path, unsigned font_size)
+{
+#ifdef HAVE_FREETYPE
+ if (!g_settings.video.font_enable)
+ return;
+
+ const char *path = font_path;
+ if (!*path)
+ path = font_renderer_get_default_font();
+
+ if (path)
+ {
+ gl->font = font_renderer_new(path, font_size);
+ if (gl->font)
+ {
+ glGenTextures(1, &gl->font_tex);
+ glBindTexture(GL_TEXTURE_2D, gl->font_tex);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_BORDER);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_BORDER);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
+ glBindTexture(GL_TEXTURE_2D, gl->texture[gl->tex_index]);
+ }
+ else
+ RARCH_WARN("Couldn't init font renderer with font \"%s\"...\n", font_path);
+ }
+ else
+ RARCH_LOG("Did not find default font.\n");
+
+ for (unsigned i = 0; i < 4; i++)
+ {
+ gl->font_color[4 * i + 0] = g_settings.video.msg_color_r;
+ gl->font_color[4 * i + 1] = g_settings.video.msg_color_g;
+ gl->font_color[4 * i + 2] = g_settings.video.msg_color_b;
+ gl->font_color[4 * i + 3] = 1.0;
+ }
+
+ for (unsigned i = 0; i < 4; i++)
+ {
+ for (unsigned j = 0; j < 3; j++)
+ gl->font_color_dark[4 * i + j] = 0.3 * gl->font_color[4 * i + j];
+ gl->font_color_dark[4 * i + 3] = 1.0;
+ }
+
+#else
+ (void)gl;
+ (void)font_path;
+ (void)font_size;
+#endif
+}
+
+void gl_deinit_font(gl_t *gl)
+{
+#ifdef HAVE_FREETYPE
+ if (gl->font)
+ {
+ font_renderer_free(gl->font);
+ glDeleteTextures(1, &gl->font_tex);
+
+ if (gl->font_tex_empty_buf)
+ free(gl->font_tex_empty_buf);
+ }
+#else
+ (void)gl;
+#endif
+}
+
+#ifdef HAVE_FREETYPE
+// Somewhat overwhelming code just to render some damn fonts.
+// We aim to use NPOT textures for compatibility with old and shitty cards.
+// Also, we want to avoid reallocating a texture for each glyph (performance dips), so we
+// contruct the whole texture using one call, and copy straight to it with
+// glTexSubImage.
+
+struct font_rect
+{
+ int x, y;
+ int width, height;
+ int pot_width, pot_height;
+};
+
+static void calculate_msg_geometry(const struct font_output *head, struct font_rect *rect)
+{
+ int x_min = head->off_x;
+ int x_max = head->off_x + head->width;
+ int y_min = head->off_y;
+ int y_max = head->off_y + head->height;
+
+ while ((head = head->next))
+ {
+ int left = head->off_x;
+ int right = head->off_x + head->width;
+ int bottom = head->off_y;
+ int top = head->off_y + head->height;
+
+ if (left < x_min)
+ x_min = left;
+ if (right > x_max)
+ x_max = right;
+
+ if (bottom < y_min)
+ y_min = bottom;
+ if (top > y_max)
+ y_max = top;
+ }
+
+ rect->x = x_min;
+ rect->y = y_min;
+ rect->width = x_max - x_min;
+ rect->height = y_max - y_min;
+}
+
+static void adjust_power_of_two(gl_t *gl, struct font_rect *geom)
+{
+ // Some systems really hate NPOT textures.
+ geom->pot_width = next_pow2(geom->width);
+ geom->pot_height = next_pow2(geom->height);
+
+ if ((geom->pot_width > gl->font_tex_w) || (geom->pot_height > gl->font_tex_h))
+ {
+ gl->font_tex_empty_buf = realloc(gl->font_tex_empty_buf, geom->pot_width * geom->pot_height);
+ memset(gl->font_tex_empty_buf, 0, geom->pot_width * geom->pot_height);
+
+ glPixelStorei(GL_UNPACK_ALIGNMENT, 8);
+ glPixelStorei(GL_UNPACK_ROW_LENGTH, geom->pot_width);
+ glTexImage2D(GL_TEXTURE_2D, 0, GL_INTENSITY8, geom->pot_width, geom->pot_height,
+ 0, GL_LUMINANCE, GL_UNSIGNED_BYTE, gl->font_tex_empty_buf);
+
+ gl->font_tex_w = geom->pot_width;
+ gl->font_tex_h = geom->pot_height;
+ }
+}
+
+// Old style "blitting", so we can render all the fonts in one go.
+// TODO: Is it possible that fonts could overlap if we blit without alpha blending?
+static void blit_fonts(gl_t *gl, const struct font_output *head, const struct font_rect *geom)
+{
+ // Clear out earlier fonts.
+ glPixelStorei(GL_UNPACK_ALIGNMENT, 8);
+ glPixelStorei(GL_UNPACK_ROW_LENGTH, gl->font_tex_w);
+ glTexSubImage2D(GL_TEXTURE_2D,
+ 0, 0, 0, gl->font_tex_w, gl->font_tex_h,
+ GL_LUMINANCE, GL_UNSIGNED_BYTE, gl->font_tex_empty_buf);
+
+ while (head)
+ {
+ // head has top-left oriented coords.
+ int x = head->off_x - geom->x;
+ int y = head->off_y - geom->y;
+ y = gl->font_tex_h - head->height - y - 1;
+
+ glPixelStorei(GL_UNPACK_ALIGNMENT, get_alignment(head->pitch));
+ glPixelStorei(GL_UNPACK_ROW_LENGTH, head->pitch);
+ glTexSubImage2D(GL_TEXTURE_2D,
+ 0, x, y, head->width, head->height,
+ GL_LUMINANCE, GL_UNSIGNED_BYTE, head->output);
+
+ head = head->next;
+ }
+}
+
+static void calculate_font_coords(gl_t *gl,
+ GLfloat font_vertex[8], GLfloat font_vertex_dark[8], GLfloat font_tex_coords[8])
+{
+ GLfloat scale_factor = g_settings.video.font_scale ?
+ (GLfloat)gl->full_x / (GLfloat)gl->vp_width :
+ 1.0f;
+
+ GLfloat lx = g_settings.video.msg_pos_x;
+ GLfloat hx = (GLfloat)gl->font_last_width / (gl->vp_width * scale_factor) + lx;
+ GLfloat ly = g_settings.video.msg_pos_y;
+ GLfloat hy = (GLfloat)gl->font_last_height / (gl->vp_height * scale_factor) + ly;
+
+ font_vertex[0] = lx;
+ font_vertex[1] = ly;
+ font_vertex[2] = lx;
+ font_vertex[3] = hy;
+ font_vertex[4] = hx;
+ font_vertex[5] = hy;
+ font_vertex[6] = hx;
+ font_vertex[7] = ly;
+
+ GLfloat shift_x = 2.0f / gl->vp_width;
+ GLfloat shift_y = 2.0f / gl->vp_height;
+ for (unsigned i = 0; i < 4; i++)
+ {
+ font_vertex_dark[2 * i + 0] = font_vertex[2 * i + 0] - shift_x;
+ font_vertex_dark[2 * i + 1] = font_vertex[2 * i + 1] - shift_y;
+ }
+
+ lx = 0.0f;
+ hx = (GLfloat)gl->font_last_width / gl->font_tex_w;
+ ly = 1.0f - (GLfloat)gl->font_last_height / gl->font_tex_h;
+ hy = 1.0f;
+
+ font_tex_coords[0] = lx;
+ font_tex_coords[1] = hy;
+ font_tex_coords[2] = lx;
+ font_tex_coords[3] = ly;
+ font_tex_coords[4] = hx;
+ font_tex_coords[5] = ly;
+ font_tex_coords[6] = hx;
+ font_tex_coords[7] = hy;
+}
+#endif
+
+void gl_render_msg(gl_t *gl, const char *msg)
+{
+#ifdef HAVE_FREETYPE
+ if (!gl->font)
+ return;
+
+ GLfloat font_vertex[8];
+ GLfloat font_vertex_dark[8];
+ GLfloat font_tex_coords[8];
+
+ glBindTexture(GL_TEXTURE_2D, gl->font_tex);
+ glTexCoordPointer(2, GL_FLOAT, 0, font_tex_coords);
+
+ struct font_output_list out;
+
+ // If we get the same message, there's obviously no need to render fonts again ...
+ if (strcmp(gl->font_last_msg, msg) != 0)
+ {
+ font_renderer_msg(gl->font, msg, &out);
+ struct font_output *head = out.head;
+
+ struct font_rect geom;
+ calculate_msg_geometry(head, &geom);
+ adjust_power_of_two(gl, &geom);
+ blit_fonts(gl, head, &geom);
+
+ font_renderer_free_output(&out);
+ strlcpy(gl->font_last_msg, msg, sizeof(gl->font_last_msg));
+
+ gl->font_last_width = geom.width;
+ gl->font_last_height = geom.height;
+ }
+ calculate_font_coords(gl, font_vertex, font_vertex_dark, font_tex_coords);
+
+ glVertexPointer(2, GL_FLOAT, 0, font_vertex_dark);
+ glColorPointer(4, GL_FLOAT, 0, gl->font_color_dark);
+ glDrawArrays(GL_QUADS, 0, 4);
+ glVertexPointer(2, GL_FLOAT, 0, font_vertex);
+ glColorPointer(4, GL_FLOAT, 0, gl->font_color);
+ glDrawArrays(GL_QUADS, 0, 4);
+#else
+ (void)gl;
+ (void)msg;
+#endif
+}
+
diff --git a/gfx/gl_font.h b/gfx/gl_font.h
new file mode 100644
index 0000000000..9c512ecd35
--- /dev/null
+++ b/gfx/gl_font.h
@@ -0,0 +1,27 @@
+/* RetroArch - A frontend for libretro.
+ * Copyright (C) 2010-2012 - Hans-Kristian Arntzen
+ *
+ * RetroArch is free software: you can redistribute it and/or modify it under the terms
+ * of the GNU General Public License as published by the Free Software Found-
+ * ation, either version 3 of the License, or (at your option) any later version.
+ *
+ * RetroArch is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
+ * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+ * PURPOSE. See the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with RetroArch.
+ * If not, see .
+ */
+
+#ifndef GL_FONT_H__
+#define GL_FONT_H__
+
+#include "gl_common.h"
+
+void gl_init_font(gl_t *gl, const char *font_path, unsigned font_size);
+void gl_deinit_font(gl_t *gl);
+
+void gl_render_msg(gl_t *gl, const char *msg);
+
+#endif
+