From d129ff3d13500034fab48a309534617f8c341c1b Mon Sep 17 00:00:00 2001 From: Themaister Date: Sun, 8 Jun 2014 12:37:32 +0200 Subject: [PATCH] Make font rendering more robust. Dynamically sized buffers, etc. --- Makefile | 2 +- compat/strcasestr.h | 2 +- gfx/fonts/gl_raster_font.c | 50 +++++++++++++++------------------ gfx/gl.c | 5 ++++ gfx/shader_glsl.c | 57 +++++++++++++++++++++++++------------- 5 files changed, 68 insertions(+), 48 deletions(-) diff --git a/Makefile b/Makefile index 15aca03439..bd79e47a3e 100644 --- a/Makefile +++ b/Makefile @@ -394,7 +394,7 @@ else ifneq ($(findstring icc,$(CC)),) CFLAGS += -std=c99 -D_GNU_SOURCE else - CFLAGS += -std=gnu99 + CFLAGS += -std=gnu99 -D_GNU_SOURCE endif endif endif diff --git a/compat/strcasestr.h b/compat/strcasestr.h index 572c6d9d96..0d98af48b6 100644 --- a/compat/strcasestr.h +++ b/compat/strcasestr.h @@ -19,7 +19,7 @@ #include #ifdef HAVE_CONFIG_H -#include "config.h" +#include "../config.h" #endif #ifndef HAVE_STRCASESTR diff --git a/gfx/fonts/gl_raster_font.c b/gfx/fonts/gl_raster_font.c index 1fa511b51a..b0f1a0c283 100644 --- a/gfx/fonts/gl_raster_font.c +++ b/gfx/fonts/gl_raster_font.c @@ -98,39 +98,28 @@ void gl_free_font(void *data) #define emit(c, vx, vy) do { \ font_vertex[ 2 * (6 * i + c) + 0] = (x + (delta_x + off_x + vx * width) * scale) * inv_win_width; \ font_vertex[ 2 * (6 * i + c) + 1] = (y + (delta_y - off_y - vy * height) * scale) * inv_win_height; \ - font_vertex_dark[2 * (6 * i + c) + 0] = (x + (delta_x + off_x - 2 + vx * width) * scale) * inv_win_width; \ - font_vertex_dark[2 * (6 * i + c) + 1] = (y + (delta_y - off_y - 2 - vy * height) * scale) * inv_win_height; \ font_tex_coords[ 2 * (6 * i + c) + 0] = (tex_x + vx * width) * inv_tex_size_x; \ font_tex_coords[ 2 * (6 * i + c) + 1] = (tex_y + vy * height) * inv_tex_size_y; \ - font_color_dark[ 4 * (6 * i + c) + 0] = 0.3f * color[0]; \ - font_color_dark[ 4 * (6 * i + c) + 1] = 0.3f * color[1]; \ - font_color_dark[ 4 * (6 * i + c) + 2] = 0.3f * color[2]; \ - font_color_dark[ 4 * (6 * i + c) + 3] = color[3]; \ font_color[ 4 * (6 * i + c) + 0] = color[0]; \ font_color[ 4 * (6 * i + c) + 1] = color[1]; \ font_color[ 4 * (6 * i + c) + 2] = color[2]; \ font_color[ 4 * (6 * i + c) + 3] = color[3]; \ } while(0) -static void render_message(gl_raster_t *font, const char *msg, GLfloat scale, const GLfloat color[4], GLfloat pos_x, GLfloat pos_y, bool full_screen) +static void render_message(gl_raster_t *font, const char *msg, GLfloat scale, const GLfloat color[4], GLfloat pos_x, GLfloat pos_y) { unsigned i; gl_t *gl = font->gl; + // Rebind shaders so attrib cache gets reset. if (gl->shader && gl->shader->use) gl->shader->use(gl, GL_SHADER_STOCK_BLEND); - - gl_set_viewport(gl, gl->win_width, gl->win_height, full_screen, false); - - glEnable(GL_BLEND); glBindTexture(GL_TEXTURE_2D, font->tex); -#define MAX_MSG_LEN_CHUNK 32 +#define MAX_MSG_LEN_CHUNK 64 GLfloat font_tex_coords[2 * 6 * MAX_MSG_LEN_CHUNK]; GLfloat font_vertex[2 * 6 * MAX_MSG_LEN_CHUNK]; - GLfloat font_vertex_dark[2 * 6 * MAX_MSG_LEN_CHUNK]; GLfloat font_color[4 * 6 * MAX_MSG_LEN_CHUNK]; - GLfloat font_color_dark[4 * 6 * MAX_MSG_LEN_CHUNK]; unsigned msg_len_full = strlen(msg); unsigned msg_len = min(msg_len_full, MAX_MSG_LEN_CHUNK); @@ -175,14 +164,6 @@ static void render_message(gl_raster_t *font, const char *msg, GLfloat scale, co delta_y -= gly->advance_y; } - // TODO: Make drop shadows parameterized? - gl->coords.tex_coord = font_tex_coords; - gl->coords.vertex = font_vertex_dark; - gl->coords.color = font_color_dark; - gl->coords.vertices = 6 * msg_len; - gl_shader_set_coords(gl, &gl->coords, &gl->mvp_no_rot); - glDrawArrays(GL_TRIANGLES, 0, 6 * msg_len); - gl->coords.tex_coord = font_tex_coords; gl->coords.vertex = font_vertex; gl->coords.color = font_color; @@ -201,21 +182,20 @@ static void render_message(gl_raster_t *font, const char *msg, GLfloat scale, co gl->coords.color = gl->white_color_ptr; gl->coords.vertices = 4; glBindTexture(GL_TEXTURE_2D, gl->texture[gl->tex_index]); - - glDisable(GL_BLEND); - gl_set_viewport(gl, gl->win_width, gl->win_height, false, true); } static void gl_render_msg(void *data, const char *msg, const struct font_params *params) { GLfloat x, y, scale; - GLfloat color[4]; + GLfloat color[4], color_dark[4]; bool full_screen; gl_raster_t *font = (gl_raster_t*)data; if (!font) return; + gl_t *gl = font->gl; + if (params) { x = params->x; @@ -245,7 +225,23 @@ static void gl_render_msg(void *data, const char *msg, const struct font_params color[3] = 1.0f; } - render_message(font, msg, scale, color, x, y, full_screen); + color_dark[0] = color[0] * 0.3f; + color_dark[1] = color[1] * 0.3f; + color_dark[2] = color[2] * 0.3f; + color_dark[3] = color[3]; + + gl_set_viewport(gl, gl->win_width, gl->win_height, full_screen, false); + glEnable(GL_BLEND); + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + glBlendEquation(GL_FUNC_ADD); + + // TODO: Make drop shadows parameterized? + render_message(font, msg, scale, color_dark, + x - scale * 2.0f / gl->vp.width, y - scale * 2.0f / gl->vp.height); + render_message(font, msg, scale, color, x, y); + + glDisable(GL_BLEND); + gl_set_viewport(gl, gl->win_width, gl->win_height, false, true); } const gl_font_renderer_t gl_raster_font = { diff --git a/gfx/gl.c b/gfx/gl.c index b2dca76c92..6440d192ab 100644 --- a/gfx/gl.c +++ b/gfx/gl.c @@ -1037,6 +1037,7 @@ static void gl_frame_fbo(void *data, const struct gl_tex_info *tex_info) gl->vp.width, gl->vp.height, g_extern.frame_count, tex_info, gl->prev_info, fbo_tex_info, fbo_tex_info_cnt); + gl->coords.vertices = 4; gl_shader_set_coords(gl, &gl->coords, &gl->mvp); glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); } @@ -1086,6 +1087,7 @@ static void gl_frame_fbo(void *data, const struct gl_tex_info *tex_info) gl->coords.vertex = gl->vertex_ptr; + gl->coords.vertices = 4; gl_shader_set_coords(gl, &gl->coords, &gl->mvp); glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); @@ -1474,6 +1476,7 @@ static inline void gl_draw_texture(void *data) if (gl->shader) gl->shader->use(gl, GL_SHADER_STOCK_BLEND); + gl->coords.vertices = 4; gl_shader_set_coords(gl, &gl->coords, &gl->mvp_no_rot); glEnable(GL_BLEND); @@ -1612,6 +1615,7 @@ static bool gl_frame(void *data, const void *frame, unsigned width, unsigned hei g_extern.frame_count, &tex_info, gl->prev_info, NULL, 0); + gl->coords.vertices = 4; gl_shader_set_coords(gl, &gl->coords, &gl->mvp); glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); @@ -2796,6 +2800,7 @@ static void gl_render_overlay(void *data) gl->coords.vertex = gl->overlay[i].vertex_coord; gl->coords.tex_coord = gl->overlay[i].tex_coord; gl->coords.color = white_color_mod; + gl->coords.vertices = 4; gl_shader_set_coords(gl, &gl->coords, &gl->mvp_no_rot); glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); } diff --git a/gfx/shader_glsl.c b/gfx/shader_glsl.c index 124d60c052..3a2bf9ebd1 100644 --- a/gfx/shader_glsl.c +++ b/gfx/shader_glsl.c @@ -64,11 +64,11 @@ static char glsl_alias_define[1024]; struct cache_vbo { GLuint vbo_primary; - GLfloat buffer_primary[128]; + GLfloat *buffer_primary; size_t size_primary; GLuint vbo_secondary; - GLfloat buffer_secondary[128]; + GLfloat *buffer_secondary; size_t size_secondary; }; static struct cache_vbo glsl_vbo[GFX_MAX_SHADERS]; @@ -467,18 +467,24 @@ static void gl_glsl_reset_attrib(void) gl_attrib_index = 0; } -static void gl_glsl_set_vbo(GLfloat *buffer, size_t *buffer_elems, const GLfloat *data, size_t elems) +static void gl_glsl_set_vbo(GLfloat **buffer, size_t *buffer_elems, const GLfloat *data, size_t elems) { - if (elems != *buffer_elems || memcmp(data, buffer, elems * sizeof(GLfloat))) + if (elems != *buffer_elems || memcmp(data, *buffer, elems * sizeof(GLfloat))) { - //RARCH_LOG("[GL]: VBO updated with %u elems.\n", (unsigned)elems); - memcpy(buffer, data, elems * sizeof(GLfloat)); + if (elems > *buffer_elems) + { + GLfloat *new_buffer = (GLfloat*)realloc(*buffer, elems * sizeof(GLfloat)); + rarch_assert(new_buffer); + *buffer = new_buffer; + } + + memcpy(*buffer, data, elems * sizeof(GLfloat)); glBufferData(GL_ARRAY_BUFFER, elems * sizeof(GLfloat), data, GL_STATIC_DRAW); *buffer_elems = elems; } } -static void gl_glsl_set_attribs(GLuint vbo, GLfloat *buffer, size_t *buffer_elems, +static void gl_glsl_set_attribs(GLuint vbo, GLfloat **buffer, size_t *buffer_elems, const GLfloat *data, size_t elems, const struct glsl_attrib *attrs, size_t num_attrs) { size_t i; @@ -639,6 +645,9 @@ static void gl_glsl_deinit(void) glDeleteBuffers(1, &glsl_vbo[i].vbo_primary); if (glsl_vbo[i].vbo_secondary) glDeleteBuffers(1, &glsl_vbo[i].vbo_secondary); + + free(glsl_vbo[i].buffer_primary); + free(glsl_vbo[i].buffer_secondary); } memset(&glsl_vbo, 0, sizeof(glsl_vbo)); } @@ -843,7 +852,7 @@ static void gl_glsl_set_params(void *data, unsigned width, unsigned height, if (!glsl_enable || (gl_program[active_index] == 0)) return; - GLfloat buffer[128]; + GLfloat buffer[512]; unsigned i; size_t size = 0; struct glsl_attrib attribs[32]; @@ -986,7 +995,7 @@ static void gl_glsl_set_params(void *data, unsigned width, unsigned height, if (size) { gl_glsl_set_attribs(glsl_vbo[active_index].vbo_secondary, - glsl_vbo[active_index].buffer_secondary, + &glsl_vbo[active_index].buffer_secondary, &glsl_vbo[active_index].size_secondary, buffer, size, attribs, attribs_size); } @@ -1035,7 +1044,15 @@ static bool gl_glsl_set_coords(const struct gl_coords *coords) if (!glsl_enable || !glsl_shader->modern) return false; - GLfloat buffer[128]; + // Avoid hitting malloc on every single regular quad draw. + GLfloat short_buffer[4 * (2 + 2 + 4 + 2)]; + GLfloat *buffer = short_buffer; + if (coords->vertices > 4) + buffer = (GLfloat*)calloc(coords->vertices * (2 + 2 + 4 + 2), sizeof(*buffer)); + + if (!buffer) + return false; + size_t size = 0; struct glsl_attrib attribs[4]; @@ -1051,8 +1068,8 @@ static bool gl_glsl_set_coords(const struct gl_coords *coords) attribs_size++; attr++; - memcpy(buffer + size, coords->tex_coord, 8 * sizeof(GLfloat)); - size += 8; + memcpy(buffer + size, coords->tex_coord, 2 * coords->vertices * sizeof(GLfloat)); + size += 2 * coords->vertices; } if (uni->vertex_coord >= 0) @@ -1063,8 +1080,8 @@ static bool gl_glsl_set_coords(const struct gl_coords *coords) attribs_size++; attr++; - memcpy(buffer + size, coords->vertex, 8 * sizeof(GLfloat)); - size += 8; + memcpy(buffer + size, coords->vertex, 2 * coords->vertices * sizeof(GLfloat)); + size += 2 * coords->vertices; } if (uni->color >= 0) @@ -1075,8 +1092,8 @@ static bool gl_glsl_set_coords(const struct gl_coords *coords) attribs_size++; attr++; - memcpy(buffer + size, coords->color, 16 * sizeof(GLfloat)); - size += 16; + memcpy(buffer + size, coords->color, 4 * coords->vertices * sizeof(GLfloat)); + size += 4 * coords->vertices; } if (uni->lut_tex_coord >= 0) @@ -1087,19 +1104,21 @@ static bool gl_glsl_set_coords(const struct gl_coords *coords) attribs_size++; attr++; - memcpy(buffer + size, coords->lut_tex_coord, 8 * sizeof(GLfloat)); - size += 8; + memcpy(buffer + size, coords->lut_tex_coord, 2 * coords->vertices * sizeof(GLfloat)); + size += 2 * coords->vertices; } if (size) { gl_glsl_set_attribs(glsl_vbo[active_index].vbo_primary, - glsl_vbo[active_index].buffer_primary, + &glsl_vbo[active_index].buffer_primary, &glsl_vbo[active_index].size_primary, buffer, size, attribs, attribs_size); } + if (buffer != short_buffer) + free(buffer); return true; }