From 8f0302c5194ed3ac4fe77a50d10c03cf79b1acc7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Higor=20Eur=C3=ADpedes?= Date: Tue, 24 Mar 2015 16:43:53 -0300 Subject: [PATCH] (gl_font_renderer_t) Implement basic text block rendering --- gfx/drivers_font/gl_raster_font.c | 148 +++++++++++++++++++++++++++++- gfx/font_gl_driver.h | 2 + menu/drivers/glui.c | 15 ++- 3 files changed, 156 insertions(+), 9 deletions(-) diff --git a/gfx/drivers_font/gl_raster_font.c b/gfx/drivers_font/gl_raster_font.c index 2293eb1c9f..432e2491aa 100644 --- a/gfx/drivers_font/gl_raster_font.c +++ b/gfx/drivers_font/gl_raster_font.c @@ -30,6 +30,14 @@ #define MAX_MSG_LEN_CHUNK 64 +typedef struct gl_raster_block { + bool active; + bool reuse; + bool fullscreen; + unsigned allocated; + struct gl_coords coords; +} gl_raster_block_t; + typedef struct { gl_t *gl; @@ -38,6 +46,8 @@ typedef struct const font_renderer_driver_t *font_driver; void *font_data; + + gl_raster_block_t block; } gl_raster_t; static void *gl_raster_font_init_font(void *gl_data, @@ -156,9 +166,81 @@ static void draw_vertices(gl_t *gl, const struct gl_coords *coords) { gl->shader->set_coords(coords); gl->shader->set_mvp(gl, &gl->mvp_no_rot); + glDrawArrays(GL_TRIANGLES, 0, coords->vertices); } +static bool realloc_checked(void **ptr, size_t size) +{ + void *nptr; + + if (size == 0) + { + if (*ptr) + free(*ptr); + *ptr = NULL; + return true; + } + + if (*ptr == NULL) + nptr = malloc(size); + else + nptr = realloc(*ptr, size); + + if (nptr) + *ptr = nptr; + + return nptr != NULL; +} + +static bool resize_block(gl_raster_t *font, unsigned new_size) +{ + gl_raster_block_t *block = &font->block; + bool success = false; + + if (!font->block.allocated || new_size > font->block.allocated - 1) + { + unsigned actual_new_size = next_pow2(new_size); + + bool vsucceeded = realloc_checked((void**)&block->coords.vertex, sizeof(GLfloat) * 2 * actual_new_size); + bool csuccceeded = realloc_checked((void**)&block->coords.color, sizeof(GLfloat) * 4 * actual_new_size); + bool tsuccceeded = realloc_checked((void**)&block->coords.tex_coord, sizeof(GLfloat) * 2 * actual_new_size); + bool lsuccceeded = realloc_checked((void**)&block->coords.lut_tex_coord, sizeof(GLfloat) * 2 * actual_new_size); + + if (vsucceeded && csuccceeded && tsuccceeded && lsuccceeded) + { + font->block.allocated = actual_new_size; + block->coords.vertices = new_size; + success = true; + } + } + else + { + block->coords.vertices = new_size; + success = true; + } + + return success; +} + +static bool append_vertices(gl_raster_t *font, const struct gl_coords *coords) +{ + gl_raster_block_t *block = &font->block; + unsigned old_size = block->coords.vertices; + if (resize_block(font, block->coords.vertices + coords->vertices)) + { + const size_t base_size = coords->vertices * sizeof(GLfloat); + memcpy((void*)(block->coords.vertex+old_size*2), coords->vertex, base_size * 2); + memcpy((void*)(block->coords.color+old_size*4), coords->color, base_size * 4); + memcpy((void*)(block->coords.tex_coord+old_size*2), coords->tex_coord, base_size * 2); + memcpy((void*)(block->coords.lut_tex_coord+old_size*2), coords->lut_tex_coord, base_size * 2); + } + else + RARCH_WARN("Allocation failed."); + + return true; +} + static void render_message(gl_raster_t *font, const char *msg, GLfloat scale, const GLfloat color[4], GLfloat pos_x, GLfloat pos_y, bool align_right) { @@ -225,7 +307,10 @@ static void render_message(gl_raster_t *font, const char *msg, GLfloat scale, coords.vertices = 6 * msg_len; coords.lut_tex_coord = gl->coords.lut_tex_coord; - draw_vertices(gl, &coords); + if (font->block.active) + append_vertices(font, &coords); + else + draw_vertices(gl, &coords); msg_len_full -= msg_len; msg += msg_len; @@ -312,7 +397,10 @@ static void gl_raster_font_render_msg(void *data, const char *msg, drop_mod = 0.3f; } - setup_viewport(font, full_screen); + if (font->block.active) + font->block.fullscreen = true; + else + setup_viewport(font, full_screen); if (drop_x || drop_y) { @@ -328,7 +416,8 @@ static void gl_raster_font_render_msg(void *data, const char *msg, render_message(font, msg, scale, color, x, y, align_right); - restore_viewport(gl); + if (!font->block.active) + restore_viewport(gl); } static const struct font_glyph *gl_raster_font_get_glyph( @@ -341,10 +430,61 @@ static const struct font_glyph *gl_raster_font_get_glyph( return font->font_driver->get_glyph((void*)font->font_driver, code); } +static void gl_end_block(void *data) +{ + gl_raster_t *font = (gl_raster_t*)data; + gl_raster_block_t *block = &font->block; + gl_t *gl = font->gl; + + if (block->coords.vertices) + { + setup_viewport(font, block->fullscreen); + + draw_vertices(gl, &block->coords); + + restore_viewport(gl); + } + + if (block->reuse && block->coords.vertices) + block->coords.vertices = 0; + else + { + block->active = false; + block->allocated = 0; + resize_block(font, 0); + memset(&block->coords, 0, sizeof(block->coords)); + } +} + +static void gl_begin_block(void *data) +{ + gl_raster_t *font = (gl_raster_t*)data; + gl_raster_block_t *block = &font->block; + unsigned i = 0; + + if (block->active) + { + block->reuse = true; + gl_end_block(data); + } + + block->reuse = false; + block->active = true; + block->coords.vertices = 0; + + if (!block->allocated) + { + block->coords.color = block->coords.tex_coord = NULL; + block->coords.vertex = block->coords.lut_tex_coord = NULL; + } +} + gl_font_renderer_t gl_raster_font = { gl_raster_font_init_font, gl_raster_font_free_font, gl_raster_font_render_msg, "GL raster", - gl_raster_font_get_glyph + gl_raster_font_get_glyph, + gl_begin_block, + gl_end_block }; diff --git a/gfx/font_gl_driver.h b/gfx/font_gl_driver.h index c710dd2132..42611a7363 100644 --- a/gfx/font_gl_driver.h +++ b/gfx/font_gl_driver.h @@ -31,6 +31,8 @@ typedef struct gl_font_renderer const char *ident; const struct font_glyph *(*get_glyph)(void *data, uint32_t code); + void (*begin_block)(void *data); + void (*end_block)(void *data); } gl_font_renderer_t; extern gl_font_renderer_t gl_raster_font; diff --git a/menu/drivers/glui.c b/menu/drivers/glui.c index ae2852f804..2b850dbd52 100644 --- a/menu/drivers/glui.c +++ b/menu/drivers/glui.c @@ -72,7 +72,7 @@ static void glui_blit_line(gl_t *gl, float x, float y, const char *message, uint { struct font_params params = {0}; - gl_set_viewport(gl, gl->win_width, gl->win_height, false, false); + /* gl_set_viewport(gl, gl->win_width, gl->win_height, false, false); */ params.x = x / gl->win_width; params.y = 1.0f - y / gl->win_height; @@ -356,6 +356,9 @@ static void glui_frame(void) glui_render_background(settings, gl, glui, false); + if (gl->font_driver->begin_block) + gl->font_driver->begin_block(gl->font_handle); + menu_list_get_last_stack(menu->menu_list, &dir, &label, &menu_type); get_title(label, dir, menu_type, title, sizeof(title)); @@ -384,17 +387,16 @@ static void glui_frame(void) glui_blit_line(gl, glui->margin * 2, - glui->margin + glui->term_height * glui->line_height + glui->margin + glui->term_height * glui->line_height + glui->line_height * 2, title_msg, FONT_COLOR_ARGB_TO_RGBA(settings->menu.title_color)); } - if (settings->menu.timedate_enable) { disp_timedate_set_label(timedate, sizeof(timedate), 0); glui_blit_line(gl, glui->margin * 14, - glui->margin + glui->term_height * glui->line_height + glui->margin + glui->term_height * glui->line_height + glui->line_height * 2, timedate, hover_color); } @@ -436,7 +438,7 @@ static void glui_frame(void) glui_blit_line(gl, x, y, message, selected ? hover_color : normal_color); - glui_blit_line(gl, gl->win_width - glui->glyph_width * w - glui->margin , + glui_blit_line(gl, gl->win_width - glui->glyph_width * w - glui->margin , y, type_str_buf, selected ? hover_color : normal_color); } @@ -458,6 +460,9 @@ static void glui_frame(void) glui->box_message[0] = '\0'; } + if (gl->font_driver->end_block) + gl->font_driver->end_block(gl->font_handle); + if (settings->menu.mouse.enable) glui_draw_cursor(gl, menu->mouse.x, menu->mouse.y);