mirror of
https://github.com/libretro/RetroArch
synced 2025-04-16 08:43:10 +00:00
(GL) update font driver to support a dynamic atlas.
This commit is contained in:
parent
e3bfb617e4
commit
6f81a19f60
@ -51,15 +51,14 @@ typedef struct
|
|||||||
|
|
||||||
const font_renderer_driver_t *font_driver;
|
const font_renderer_driver_t *font_driver;
|
||||||
void *font_data;
|
void *font_data;
|
||||||
|
struct font_atlas *atlas;
|
||||||
|
|
||||||
video_font_raster_block_t *block;
|
video_font_raster_block_t *block;
|
||||||
} gl_raster_t;
|
} gl_raster_t;
|
||||||
|
|
||||||
static void gl_raster_font_free_font(void *data);
|
static void gl_raster_font_free_font(void *data);
|
||||||
|
|
||||||
static bool gl_raster_font_upload_atlas(gl_raster_t *font,
|
static bool gl_raster_font_upload_atlas(gl_raster_t *font)
|
||||||
const struct font_atlas *atlas,
|
|
||||||
unsigned width, unsigned height)
|
|
||||||
{
|
{
|
||||||
unsigned i, j;
|
unsigned i, j;
|
||||||
GLint gl_internal = GL_LUMINANCE_ALPHA;
|
GLint gl_internal = GL_LUMINANCE_ALPHA;
|
||||||
@ -97,30 +96,30 @@ static bool gl_raster_font_upload_atlas(gl_raster_t *font,
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
tmp = (uint8_t*)calloc(height, width * ncomponents);
|
tmp = (uint8_t*)calloc(font->tex_height, font->tex_width * ncomponents);
|
||||||
|
|
||||||
if (!tmp)
|
if (!tmp)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
for (i = 0; i < atlas->height; ++i)
|
for (i = 0; i < font->atlas->height; ++i)
|
||||||
{
|
{
|
||||||
const uint8_t *src = &atlas->buffer[i * atlas->width];
|
const uint8_t *src = &font->atlas->buffer[i * font->atlas->width];
|
||||||
uint8_t *dst = &tmp[i * width * ncomponents];
|
uint8_t *dst = &tmp[i * font->tex_width * ncomponents];
|
||||||
|
|
||||||
switch (ncomponents)
|
switch (ncomponents)
|
||||||
{
|
{
|
||||||
case 1:
|
case 1:
|
||||||
memcpy(dst, src, atlas->width);
|
memcpy(dst, src, font->atlas->width);
|
||||||
break;
|
break;
|
||||||
case 2:
|
case 2:
|
||||||
for (j = 0; j < atlas->width; ++j)
|
for (j = 0; j < font->atlas->width; ++j)
|
||||||
{
|
{
|
||||||
*dst++ = 0xff;
|
*dst++ = 0xff;
|
||||||
*dst++ = *src++;
|
*dst++ = *src++;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 4:
|
case 4:
|
||||||
for (j = 0; j < atlas->width; ++j)
|
for (j = 0; j < font->atlas->width; ++j)
|
||||||
{
|
{
|
||||||
*dst++ = 0xff;
|
*dst++ = 0xff;
|
||||||
*dst++ = 0xff;
|
*dst++ = 0xff;
|
||||||
@ -136,7 +135,7 @@ static bool gl_raster_font_upload_atlas(gl_raster_t *font,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
glTexImage2D(GL_TEXTURE_2D, 0, gl_internal, width, height,
|
glTexImage2D(GL_TEXTURE_2D, 0, gl_internal, font->tex_width, font->tex_height,
|
||||||
0, gl_format, GL_UNSIGNED_BYTE, tmp);
|
0, gl_format, GL_UNSIGNED_BYTE, tmp);
|
||||||
|
|
||||||
free(tmp);
|
free(tmp);
|
||||||
@ -174,14 +173,15 @@ static void *gl_raster_font_init_font(void *data,
|
|||||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
||||||
|
|
||||||
atlas = font->font_driver->get_atlas(font->font_data);
|
font->atlas = font->font_driver->get_atlas(font->font_data);
|
||||||
font->tex_width = next_pow2(atlas->width);
|
font->tex_width = next_pow2(font->atlas->width);
|
||||||
font->tex_height = next_pow2(atlas->height);
|
font->tex_height = next_pow2(font->atlas->height);
|
||||||
|
|
||||||
if (!gl_raster_font_upload_atlas(font, atlas,
|
if (!gl_raster_font_upload_atlas(font))
|
||||||
font->tex_width, font->tex_height))
|
|
||||||
goto error;
|
goto error;
|
||||||
|
|
||||||
|
font->atlas->dirty = false;
|
||||||
|
|
||||||
glBindTexture(GL_TEXTURE_2D, font->gl->texture[font->gl->tex_index]);
|
glBindTexture(GL_TEXTURE_2D, font->gl->texture[font->gl->tex_index]);
|
||||||
|
|
||||||
return font;
|
return font;
|
||||||
@ -212,12 +212,12 @@ static void gl_raster_font_free_font(void *data)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static int gl_get_message_width(void *data, const char *msg,
|
static int gl_get_message_width(void *data, const char *msg,
|
||||||
unsigned msg_len_full, float scale)
|
unsigned msg_len, float scale)
|
||||||
{
|
{
|
||||||
unsigned i;
|
unsigned i;
|
||||||
int delta_x = 0;
|
|
||||||
unsigned msg_len = MIN(msg_len_full, MAX_MSG_LEN_CHUNK);
|
|
||||||
gl_raster_t *font = (gl_raster_t*)data;
|
gl_raster_t *font = (gl_raster_t*)data;
|
||||||
|
const char* msg_end = msg + msg_len;
|
||||||
|
int delta_x = 0;
|
||||||
|
|
||||||
if (!font)
|
if (!font)
|
||||||
return 0;
|
return 0;
|
||||||
@ -228,17 +228,10 @@ static int gl_get_message_width(void *data, const char *msg,
|
|||||||
|| !font->font_data )
|
|| !font->font_data )
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
while (msg_len_full)
|
while (msg < msg_end)
|
||||||
{
|
|
||||||
for (i = 0; i < msg_len; i++)
|
|
||||||
{
|
{
|
||||||
const struct font_glyph *glyph = NULL;
|
const struct font_glyph *glyph = NULL;
|
||||||
const char *msg_tmp = &msg[i];
|
unsigned code = utf8_walk(&msg);
|
||||||
unsigned code = utf8_walk(&msg_tmp);
|
|
||||||
unsigned skip = msg_tmp - &msg[i];
|
|
||||||
|
|
||||||
if (skip > 1)
|
|
||||||
i += skip - 1;
|
|
||||||
|
|
||||||
glyph = font->font_driver->get_glyph(font->font_data, code);
|
glyph = font->font_driver->get_glyph(font->font_data, code);
|
||||||
|
|
||||||
@ -250,26 +243,27 @@ static int gl_get_message_width(void *data, const char *msg,
|
|||||||
delta_x += glyph->advance_x;
|
delta_x += glyph->advance_x;
|
||||||
}
|
}
|
||||||
|
|
||||||
msg_len_full -= msg_len;
|
|
||||||
msg += msg_len;
|
|
||||||
msg_len = MIN(msg_len_full, MAX_MSG_LEN_CHUNK);
|
|
||||||
}
|
|
||||||
|
|
||||||
return delta_x * scale;
|
return delta_x * scale;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void gl_raster_font_draw_vertices(gl_t *gl, const video_coords_t *coords)
|
static void gl_raster_font_draw_vertices(gl_raster_t *font, const video_coords_t *coords)
|
||||||
{
|
{
|
||||||
video_shader_ctx_mvp_t mvp;
|
video_shader_ctx_mvp_t mvp;
|
||||||
video_shader_ctx_coords_t coords_data;
|
video_shader_ctx_coords_t coords_data;
|
||||||
|
|
||||||
|
if (font->atlas->dirty)
|
||||||
|
{
|
||||||
|
gl_raster_font_upload_atlas(font);
|
||||||
|
font->atlas->dirty = false;
|
||||||
|
}
|
||||||
|
|
||||||
coords_data.handle_data = NULL;
|
coords_data.handle_data = NULL;
|
||||||
coords_data.data = coords;
|
coords_data.data = coords;
|
||||||
|
|
||||||
video_shader_driver_set_coords(&coords_data);
|
video_shader_driver_set_coords(&coords_data);
|
||||||
|
|
||||||
mvp.data = gl;
|
mvp.data = font->gl;
|
||||||
mvp.matrix = &gl->mvp_no_rot;
|
mvp.matrix = &font->gl->mvp_no_rot;
|
||||||
|
|
||||||
video_shader_driver_set_mvp(&mvp);
|
video_shader_driver_set_mvp(&mvp);
|
||||||
|
|
||||||
@ -277,25 +271,24 @@ static void gl_raster_font_draw_vertices(gl_t *gl, const video_coords_t *coords)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void gl_raster_font_render_line(
|
static void gl_raster_font_render_line(
|
||||||
gl_raster_t *font, const char *msg, unsigned msg_len_full,
|
gl_raster_t *font, const char *msg, unsigned msg_len,
|
||||||
GLfloat scale, const GLfloat color[4], GLfloat pos_x,
|
GLfloat scale, const GLfloat color[4], GLfloat pos_x,
|
||||||
GLfloat pos_y, unsigned text_align)
|
GLfloat pos_y, unsigned text_align)
|
||||||
{
|
{
|
||||||
int x, y, delta_x, delta_y;
|
int x, y, delta_x, delta_y;
|
||||||
float inv_tex_size_x, inv_tex_size_y, inv_win_width, inv_win_height;
|
float inv_tex_size_x, inv_tex_size_y, inv_win_width, inv_win_height;
|
||||||
unsigned i, msg_len;
|
unsigned i;
|
||||||
struct video_coords coords;
|
struct video_coords coords;
|
||||||
GLfloat font_tex_coords[2 * 6 * MAX_MSG_LEN_CHUNK];
|
GLfloat font_tex_coords[2 * 6 * MAX_MSG_LEN_CHUNK];
|
||||||
GLfloat font_vertex[2 * 6 * MAX_MSG_LEN_CHUNK];
|
GLfloat font_vertex[2 * 6 * MAX_MSG_LEN_CHUNK];
|
||||||
GLfloat font_color[4 * 6 * MAX_MSG_LEN_CHUNK];
|
GLfloat font_color[4 * 6 * MAX_MSG_LEN_CHUNK];
|
||||||
GLfloat font_lut_tex_coord[2 * 6 * MAX_MSG_LEN_CHUNK];
|
GLfloat font_lut_tex_coord[2 * 6 * MAX_MSG_LEN_CHUNK];
|
||||||
gl_t *gl = font ? font->gl : NULL;
|
gl_t *gl = font ? font->gl : NULL;
|
||||||
|
const char* msg_end = msg + msg_len;
|
||||||
|
|
||||||
if (!gl)
|
if (!gl)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
msg_len = MIN(msg_len_full, MAX_MSG_LEN_CHUNK);
|
|
||||||
|
|
||||||
x = roundf(pos_x * gl->vp.width);
|
x = roundf(pos_x * gl->vp.width);
|
||||||
y = roundf(pos_y * gl->vp.height);
|
y = roundf(pos_y * gl->vp.height);
|
||||||
delta_x = 0;
|
delta_x = 0;
|
||||||
@ -304,10 +297,10 @@ static void gl_raster_font_render_line(
|
|||||||
switch (text_align)
|
switch (text_align)
|
||||||
{
|
{
|
||||||
case TEXT_ALIGN_RIGHT:
|
case TEXT_ALIGN_RIGHT:
|
||||||
x -= gl_get_message_width(font, msg, msg_len_full, scale);
|
x -= gl_get_message_width(font, msg, msg_len, scale);
|
||||||
break;
|
break;
|
||||||
case TEXT_ALIGN_CENTER:
|
case TEXT_ALIGN_CENTER:
|
||||||
x -= gl_get_message_width(font, msg, msg_len_full, scale) / 2.0;
|
x -= gl_get_message_width(font, msg, msg_len, scale) / 2.0;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -316,23 +309,15 @@ static void gl_raster_font_render_line(
|
|||||||
inv_win_width = 1.0f / font->gl->vp.width;
|
inv_win_width = 1.0f / font->gl->vp.width;
|
||||||
inv_win_height = 1.0f / font->gl->vp.height;
|
inv_win_height = 1.0f / font->gl->vp.height;
|
||||||
|
|
||||||
while (msg_len_full)
|
|
||||||
|
while (msg < msg_end)
|
||||||
{
|
{
|
||||||
for (i = 0; i < msg_len; i++)
|
i = 0;
|
||||||
|
while ((i < MAX_MSG_LEN_CHUNK) && (msg < msg_end))
|
||||||
{
|
{
|
||||||
int off_x, off_y, tex_x, tex_y, width, height;
|
int off_x, off_y, tex_x, tex_y, width, height;
|
||||||
const struct font_glyph *glyph = NULL;
|
const struct font_glyph *glyph = NULL;
|
||||||
const char *msg_tmp = &msg[i];
|
unsigned code = utf8_walk(&msg);
|
||||||
unsigned code = utf8_walk(&msg_tmp);
|
|
||||||
unsigned skip = msg_tmp - &msg[i];
|
|
||||||
|
|
||||||
if (skip > 1)
|
|
||||||
{
|
|
||||||
i += skip - 1;
|
|
||||||
|
|
||||||
if (i >= msg_len)
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
glyph = font->font_driver->get_glyph(font->font_data, code);
|
glyph = font->font_driver->get_glyph(font->font_data, code);
|
||||||
|
|
||||||
@ -356,6 +341,8 @@ static void gl_raster_font_render_line(
|
|||||||
gl_raster_font_emit(4, 0, 0); /* Top-left */
|
gl_raster_font_emit(4, 0, 0); /* Top-left */
|
||||||
gl_raster_font_emit(5, 1, 1); /* Bottom-right */
|
gl_raster_font_emit(5, 1, 1); /* Bottom-right */
|
||||||
|
|
||||||
|
i++;
|
||||||
|
|
||||||
delta_x += glyph->advance_x;
|
delta_x += glyph->advance_x;
|
||||||
delta_y -= glyph->advance_y;
|
delta_y -= glyph->advance_y;
|
||||||
}
|
}
|
||||||
@ -363,17 +350,13 @@ static void gl_raster_font_render_line(
|
|||||||
coords.tex_coord = font_tex_coords;
|
coords.tex_coord = font_tex_coords;
|
||||||
coords.vertex = font_vertex;
|
coords.vertex = font_vertex;
|
||||||
coords.color = font_color;
|
coords.color = font_color;
|
||||||
coords.vertices = 6 * msg_len;
|
coords.vertices = i * 6;
|
||||||
coords.lut_tex_coord = font_lut_tex_coord;
|
coords.lut_tex_coord = font_lut_tex_coord;
|
||||||
|
|
||||||
if (font->block)
|
if (font->block)
|
||||||
video_coord_array_append(&font->block->carr, &coords, coords.vertices);
|
video_coord_array_append(&font->block->carr, &coords, coords.vertices);
|
||||||
else
|
else
|
||||||
gl_raster_font_draw_vertices(gl, &coords);
|
gl_raster_font_draw_vertices(font, &coords);
|
||||||
|
|
||||||
msg_len_full -= msg_len;
|
|
||||||
msg += msg_len;
|
|
||||||
msg_len = MIN(msg_len_full, MAX_MSG_LEN_CHUNK);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -568,7 +551,7 @@ static void gl_raster_font_flush_block(void *data)
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
gl_raster_font_setup_viewport(font, block->fullscreen);
|
gl_raster_font_setup_viewport(font, block->fullscreen);
|
||||||
gl_raster_font_draw_vertices(font->gl, (video_coords_t*)&block->carr.coords);
|
gl_raster_font_draw_vertices(font, (video_coords_t*)&block->carr.coords);
|
||||||
gl_raster_font_restore_viewport(font->gl, block->fullscreen);
|
gl_raster_font_restore_viewport(font->gl, block->fullscreen);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -34,7 +34,7 @@ typedef struct bm_renderer
|
|||||||
struct font_atlas atlas;
|
struct font_atlas atlas;
|
||||||
} bm_renderer_t;
|
} bm_renderer_t;
|
||||||
|
|
||||||
static const struct font_atlas *font_renderer_bmp_get_atlas(void *data)
|
static struct font_atlas *font_renderer_bmp_get_atlas(void *data)
|
||||||
{
|
{
|
||||||
bm_renderer_t *handle = (bm_renderer_t*)data;
|
bm_renderer_t *handle = (bm_renderer_t*)data;
|
||||||
if (!handle)
|
if (!handle)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user