Make font rendering more robust.

Dynamically sized buffers, etc.
This commit is contained in:
Themaister 2014-06-08 12:37:32 +02:00
parent 614b866f57
commit d129ff3d13
5 changed files with 68 additions and 48 deletions

View File

@ -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

View File

@ -19,7 +19,7 @@
#include <string.h>
#ifdef HAVE_CONFIG_H
#include "config.h"
#include "../config.h"
#endif
#ifndef HAVE_STRCASESTR

View File

@ -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 = {

View File

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

View File

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