diff --git a/gfx/drivers/gl.c b/gfx/drivers/gl.c index 426efad4de..fc99bf59f7 100644 --- a/gfx/drivers/gl.c +++ b/gfx/drivers/gl.c @@ -39,6 +39,7 @@ #endif #include "../gl_common.h" +#include "../font_gl_driver.h" #include "../video_viewport.h" #include "../video_pixel_converter.h" #include "../video_context_driver.h" diff --git a/gfx/drivers_font/gl_raster_font.c b/gfx/drivers_font/gl_raster_font.c index 6c96ef9cb7..53912fbec9 100644 --- a/gfx/drivers_font/gl_raster_font.c +++ b/gfx/drivers_font/gl_raster_font.c @@ -15,6 +15,7 @@ */ #include "../gl_common.h" +#include "../font_gl_driver.h" #include "../video_shader_driver.h" #define emit(c, vx, vy) do { \ @@ -38,6 +39,8 @@ typedef struct const font_renderer_driver_t *font_driver; void *font_data; + + gl_font_raster_block_t *block; } gl_raster_t; static void *gl_raster_font_init_font(void *gl_data, @@ -152,6 +155,14 @@ static int get_message_width(gl_raster_t *font, const char *msg) return delta_x; } +static void draw_vertices(gl_t *gl, const gl_coords_t *coords) +{ + gl->shader->set_coords(coords); + gl->shader->set_mvp(gl, &gl->mvp_no_rot); + + glDrawArrays(GL_TRIANGLES, 0, coords->vertices); +} + 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) { @@ -162,8 +173,7 @@ static void render_message(gl_raster_t *font, const char *msg, GLfloat scale, GLfloat font_vertex[2 * 6 * MAX_MSG_LEN_CHUNK]; GLfloat font_color[4 * 6 * MAX_MSG_LEN_CHUNK]; gl_t *gl = font->gl; - - glBindTexture(GL_TEXTURE_2D, font->tex); + struct gl_coords coords; msg_len_full = strlen(msg); msg_len = min(msg_len_full, MAX_MSG_LEN_CHUNK); @@ -183,14 +193,10 @@ static void render_message(gl_raster_t *font, const char *msg, GLfloat scale, while (msg_len_full) { - /* Rebind shaders so attrib cache gets reset. */ - if (gl->shader && gl->shader->use) - gl->shader->use(gl, GL_SHADER_STOCK_BLEND); - for (i = 0; i < msg_len; i++) { int off_x, off_y, tex_x, tex_y, width, height; - const struct font_glyph *glyph = + const struct font_glyph *glyph = font->font_driver->get_glyph(font->font_data, (uint8_t)msg[i]); if (!glyph) glyph = font->font_driver->get_glyph(font->font_data, '?'); /* Do something smarter here ... */ @@ -217,25 +223,45 @@ static void render_message(gl_raster_t *font, const char *msg, GLfloat scale, delta_y -= glyph->advance_y; } - gl->coords.tex_coord = font_tex_coords; - gl->coords.vertex = font_vertex; - gl->coords.color = font_color; - gl->coords.vertices = 6 * msg_len; - gl->shader->set_coords(&gl->coords); - gl->shader->set_mvp(gl, &gl->mvp_no_rot); - glDrawArrays(GL_TRIANGLES, 0, 6 * msg_len); + coords.tex_coord = font_tex_coords; + coords.vertex = font_vertex; + coords.color = font_color; + coords.vertices = 6 * msg_len; + coords.lut_tex_coord = gl->coords.lut_tex_coord; + + if (font->block) + gl_coord_array_add(&font->block->carr, &coords, coords.vertices); + else + draw_vertices(gl, &coords); msg_len_full -= msg_len; msg += msg_len; msg_len = min(msg_len_full, MAX_MSG_LEN_CHUNK); } +} - /* Post - Go back to old rendering path. */ - gl->coords.vertex = gl->vertex_ptr; - gl->coords.tex_coord = gl->tex_info.coord; - gl->coords.color = gl->white_color_ptr; - gl->coords.vertices = 4; +static void setup_viewport(gl_raster_t *font, bool full_screen) +{ + gl_t *gl = font->gl; + + 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); + + glBindTexture(GL_TEXTURE_2D, font->tex); + + if (gl->shader && gl->shader->use) + gl->shader->use(gl, GL_SHADER_STOCK_BLEND); +} + +static void restore_viewport(gl_t *gl) +{ 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_raster_font_render_msg(void *data, const char *msg, @@ -293,11 +319,10 @@ static void gl_raster_font_render_msg(void *data, const char *msg, drop_mod = 0.3f; } - 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); + if (font->block) + font->block->fullscreen = true; + else + setup_viewport(font, full_screen); if (drop_x || drop_y) { @@ -310,10 +335,11 @@ static void gl_raster_font_render_msg(void *data, const char *msg, x + scale * drop_x / gl->vp.width, y + scale * drop_y / gl->vp.height, align_right); } + render_message(font, msg, scale, color, x, y, align_right); - glDisable(GL_BLEND); - gl_set_viewport(gl, gl->win_width, gl->win_height, false, true); + if (!font->block) + restore_viewport(gl); } static const struct font_glyph *gl_raster_font_get_glyph( @@ -326,10 +352,37 @@ static const struct font_glyph *gl_raster_font_get_glyph( return font->font_driver->get_glyph((void*)font->font_driver, code); } +static void gl_flush_block(void *data) +{ + gl_raster_t *font = (gl_raster_t*)data; + gl_font_raster_block_t *block = font->block; + + if (block->carr.coords.vertices) + { + setup_viewport(font, block->fullscreen); + + draw_vertices(font->gl, (gl_coords_t*)&block->carr.coords); + + restore_viewport(font->gl); + } + + /* block->carr.coords.vertices = 0; */ +} + +static void gl_bind_block(void *data, gl_font_raster_block_t *block) +{ + gl_raster_t *font = (gl_raster_t*)data; + unsigned i = 0; + + font->block = block; +} + 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_bind_block, + gl_flush_block }; diff --git a/gfx/drivers_font/ps_libdbgfont.c b/gfx/drivers_font/ps_libdbgfont.c index 9fb73a95a5..76dd7078a7 100644 --- a/gfx/drivers_font/ps_libdbgfont.c +++ b/gfx/drivers_font/ps_libdbgfont.c @@ -16,6 +16,7 @@ #include "../font_renderer_driver.h" #include "../gl_common.h" +#include "../font_gl_driver.h" #if defined(SN_TARGET_PSP2) #include diff --git a/gfx/font_gl_driver.h b/gfx/font_gl_driver.h index c710dd2132..27bba314c2 100644 --- a/gfx/font_gl_driver.h +++ b/gfx/font_gl_driver.h @@ -18,10 +18,17 @@ #define __FONT_GL_DRIVER_H__ #include "../driver.h" +#include "gl_common.h" #include struct font_glyph; +/* XXX: please include gl_common.h before this file */ +typedef struct gl_raster_block { + bool fullscreen; + gl_coord_array_t carr; +} gl_font_raster_block_t; + typedef struct gl_font_renderer { void *(*init)(void *data, const char *font_path, float font_size); @@ -31,6 +38,8 @@ typedef struct gl_font_renderer const char *ident; const struct font_glyph *(*get_glyph)(void *data, uint32_t code); + void (*bind_block)(void *data, gl_font_raster_block_t *block); + void (*flush)(void *data); } gl_font_renderer_t; extern gl_font_renderer_t gl_raster_font; diff --git a/gfx/gl_common.c b/gfx/gl_common.c index 8a0ae3c111..76d12b9cc3 100644 --- a/gfx/gl_common.c +++ b/gfx/gl_common.c @@ -125,3 +125,80 @@ bool gl_load_luts(const struct video_shader *shader, glBindTexture(GL_TEXTURE_2D, 0); return true; } + +static INLINE bool realloc_checked(void **ptr, size_t size) +{ + void *nptr; + + if (*ptr) + nptr = realloc(*ptr, size); + else + nptr = malloc(size); + + if (nptr) + *ptr = nptr; + + return *ptr == nptr; +} + +bool gl_coord_array_add(gl_coord_array_t *ca, const gl_coords_t *coords, unsigned count) +{ + bool success = false; + count = min(count, coords->vertices); + + if (ca->coords.vertices + count >= ca->allocated) + { + unsigned alloc_size = next_pow2(ca->coords.vertices + count); + size_t base_size = sizeof(GLfloat) * alloc_size; + + bool vert_ok = realloc_checked((void**)&ca->coords.vertex, 2 * base_size); + bool color_ok = realloc_checked((void**)&ca->coords.color, 4 * base_size); + bool tex_ok = realloc_checked((void**)&ca->coords.tex_coord, 2 * base_size); + bool lut_ok = realloc_checked((void**)&ca->coords.lut_tex_coord, 2 * base_size); + + if (vert_ok && color_ok && tex_ok && lut_ok) + { + ca->allocated = alloc_size; + success = true; + } + } + else + success = true; + + if (success) + { + size_t base_size = coords->vertices * sizeof(GLfloat); + size_t offset = ca->coords.vertices; + + /* XXX: i wish we used interlaced arrays so we could call memcpy only once */ + memcpy(ca->coords.vertex + offset * 2, coords->vertex, base_size * 2); + memcpy(ca->coords.color + offset * 4, coords->color, base_size * 4); + memcpy(ca->coords.tex_coord + offset * 2, coords->tex_coord, base_size * 2); + memcpy(ca->coords.lut_tex_coord + offset * 2, coords->lut_tex_coord, base_size * 2); + + ca->coords.vertices += count; + } + else + RARCH_WARN("Allocation failed."); + + return success; +} + +void gl_coord_array_release(gl_coord_array_t *ca) +{ + if (!ca->allocated) + return; + + free(ca->coords.vertex); + free(ca->coords.color); + free(ca->coords.tex_coord); + free(ca->coords.lut_tex_coord); + + ca->coords.vertex = NULL; + ca->coords.color = NULL; + ca->coords.tex_coord = NULL; + ca->coords.lut_tex_coord = NULL; + + ca->coords.vertices = 0; + ca->allocated = 0; +} diff --git a/gfx/gl_common.h b/gfx/gl_common.h index 30ed555f62..acc0c488b7 100644 --- a/gfx/gl_common.h +++ b/gfx/gl_common.h @@ -21,7 +21,7 @@ #include "font_renderer_driver.h" #include #include -#include "font_gl_driver.h" +//#include "font_gl_driver.h" #include #include "video_shader_driver.h" #include @@ -231,14 +231,31 @@ struct gl_tex_info GLfloat coord[8]; }; -struct gl_coords +typedef struct gl_coords { const GLfloat *vertex; const GLfloat *color; const GLfloat *tex_coord; const GLfloat *lut_tex_coord; unsigned vertices; -}; +} gl_coords_t; + +typedef struct gl_mut_coords +{ + GLfloat *vertex; + GLfloat *color; + GLfloat *tex_coord; + GLfloat *lut_tex_coord; + unsigned vertices; +} gl_mut_coords_t; + +typedef struct gl_coord_array +{ + gl_mut_coords_t coords; + unsigned allocated; +} gl_coord_array_t; + +struct gl_font_renderer; typedef struct gl { @@ -318,7 +335,7 @@ typedef struct gl #endif /* Fonts */ - const gl_font_renderer_t *font_driver; + const struct gl_font_renderer *font_driver; void *font_handle; bool egl_images; @@ -422,4 +439,7 @@ static INLINE unsigned gl_wrap_type_to_enum(enum gfx_wrap_type type) return 0; } +bool gl_coord_array_add(gl_coord_array_t *ca, const gl_coords_t *coords, unsigned count); +void gl_coord_array_release(gl_coord_array_t *ca); + #endif diff --git a/menu/drivers/glui.c b/menu/drivers/glui.c index ae2852f804..04b10d4c2a 100644 --- a/menu/drivers/glui.c +++ b/menu/drivers/glui.c @@ -25,6 +25,7 @@ #include #include "../../gfx/gl_common.h" +#include "../../gfx/font_gl_driver.h" #include "../../gfx/video_texture.h" #include @@ -46,6 +47,8 @@ typedef struct glui_handle char path[PATH_MAX_LENGTH]; } bg; } textures; + + gl_font_raster_block_t raster_block; } glui_handle_t; static int glui_entry_iterate(unsigned action) @@ -53,10 +56,18 @@ static int glui_entry_iterate(unsigned action) const char *label = NULL; menu_file_list_cbs_t *cbs = NULL; menu_handle_t *menu = menu_driver_get_ptr(); + runloop_t *runloop = rarch_main_get_ptr(); - if (!menu) + if (!menu || !runloop) return -1; + if (action != MENU_ACTION_NOOP || menu->need_refresh || + runloop->frames.video.current.menu.label.is_updated || + runloop->frames.video.current.menu.animation.is_active) + { + runloop->frames.video.current.menu.framebuf.dirty = true; + } + cbs = (menu_file_list_cbs_t*)menu_list_get_actiondata_at_offset( menu->menu_list->selection_buf, menu->navigation.selection_ptr); @@ -72,7 +83,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; @@ -288,10 +299,6 @@ static void glui_render(void) menu->frame_buf.width = gl->win_width; menu->frame_buf.height = gl->win_height; - runloop->frames.video.current.menu.animation.is_active = false; - runloop->frames.video.current.menu.label.is_updated = false; - runloop->frames.video.current.menu.framebuf.dirty = false; - menu->mouse.ptr = (menu->mouse.y - glui->margin) / glui->line_height - 2 + menu->begin; @@ -326,6 +333,7 @@ static void glui_frame(void) settings_t *settings = config_get_ptr(); const uint32_t normal_color = FONT_COLOR_ARGB_TO_RGBA(settings->menu.entry_normal_color); const uint32_t hover_color = FONT_COLOR_ARGB_TO_RGBA(settings->menu.entry_hover_color); + const uint32_t title_color = FONT_COLOR_ARGB_TO_RGBA(settings->menu.title_color); runloop_t *runloop = rarch_main_get_ptr(); global_t *global = global_get_ptr(); @@ -349,12 +357,22 @@ static void glui_frame(void) glViewport(0, 0, gl->win_width, gl->win_height); + glui_render_background(settings, gl, glui, false); + + if (!menu_display_update_pending()) + goto draw_text; + + glui->raster_block.carr.coords.vertices = 0; + + runloop->frames.video.current.menu.animation.is_active = false; + runloop->frames.video.current.menu.label.is_updated = false; + runloop->frames.video.current.menu.framebuf.dirty = false; + end = (menu->begin + glui->term_height <= menu_list_get_size(menu->menu_list)) ? menu->begin + glui->term_height : menu_list_get_size(menu->menu_list); - glui_render_background(settings, gl, glui, false); menu_list_get_last_stack(menu->menu_list, &dir, &label, &menu_type); @@ -363,7 +381,7 @@ static void glui_frame(void) menu_animation_ticker_line(title_buf, glui->term_width - 3, runloop->frames.video.count / glui->margin, title, true); glui_blit_line(gl, glui->margin * 2, glui->margin + glui->line_height, - title_buf, FONT_COLOR_ARGB_TO_RGBA(settings->menu.title_color)); + title_buf, title_color); core_name = global->menu.info.library_name; if (!core_name) @@ -384,17 +402,16 @@ static void glui_frame(void) glui_blit_line(gl, glui->margin * 2, - glui->margin + glui->term_height * glui->line_height - + glui->line_height * 2, title_msg, FONT_COLOR_ARGB_TO_RGBA(settings->menu.title_color)); + glui->margin + glui->term_height * glui->line_height + + glui->line_height * 2, title_msg, 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); } @@ -404,40 +421,40 @@ static void glui_frame(void) for (i = menu->begin; i < end; i++, y += glui->line_height) { char message[PATH_MAX_LENGTH], type_str[PATH_MAX_LENGTH], - entry_title_buf[PATH_MAX_LENGTH], type_str_buf[PATH_MAX_LENGTH], - path_buf[PATH_MAX_LENGTH]; + entry_title_buf[PATH_MAX_LENGTH], type_str_buf[PATH_MAX_LENGTH], + path_buf[PATH_MAX_LENGTH]; const char *path = NULL, *entry_label = NULL; unsigned type = 0, w = 0; bool selected = false; menu_file_list_cbs_t *cbs = NULL; menu_list_get_at_offset(menu->menu_list->selection_buf, i, &path, - &entry_label, &type); + &entry_label, &type); cbs = (menu_file_list_cbs_t*) - menu_list_get_actiondata_at_offset(menu->menu_list->selection_buf, - i); + menu_list_get_actiondata_at_offset(menu->menu_list->selection_buf, + i); if (cbs && cbs->action_get_representation) cbs->action_get_representation(menu->menu_list->selection_buf, - &w, type, i, label, - type_str, sizeof(type_str), - entry_label, path, - path_buf, sizeof(path_buf)); + &w, type, i, label, + type_str, sizeof(type_str), + entry_label, path, + path_buf, sizeof(path_buf)); selected = (i == menu->navigation.selection_ptr); menu_animation_ticker_line(entry_title_buf, glui->term_width - (w + 1 + 2), - runloop->frames.video.count / glui->margin, path_buf, selected); - menu_animation_ticker_line(type_str_buf, w, - runloop->frames.video.count / glui->margin, type_str, selected); + runloop->frames.video.count / glui->margin, path_buf, selected); + menu_animation_ticker_line(type_str_buf, w, + runloop->frames.video.count / glui->margin, type_str, selected); strlcpy(message, entry_title_buf, sizeof(message)); 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 , - y, type_str_buf, selected ? hover_color : normal_color); + glui_blit_line(gl, gl->win_width - glui->glyph_width * w - glui->margin , + y, type_str_buf, selected ? hover_color : normal_color); } if (menu->keyboard.display) @@ -461,6 +478,10 @@ static void glui_frame(void) if (settings->menu.mouse.enable) glui_draw_cursor(gl, menu->mouse.x, menu->mouse.y); +draw_text: + if (gl->font_driver->flush) + gl->font_driver->flush(gl->font_handle); + gl_set_viewport(gl, gl->win_width, gl->win_height, false, true); } @@ -490,6 +511,9 @@ static void *glui_init(void) glui = (glui_handle_t*)menu->userdata; glui->textures.bg.id = 0; + if (gl->font_driver->bind_block) + gl->font_driver->bind_block(gl->font_handle, &glui->raster_block); + return menu; error: if (menu) @@ -499,7 +523,15 @@ error: static void glui_free(void *data) { + gl_t *gl = (gl_t*)video_driver_get_ptr(NULL); + menu_handle_t *menu = (menu_handle_t*)data; + glui_handle_t *glui = (glui_handle_t*)menu->userdata; + + gl_coord_array_release(&glui->raster_block.carr); + + if (gl->font_driver->bind_block) + gl->font_driver->bind_block(gl->font_handle, NULL); if (menu->alloc_font) free((uint8_t*)menu->font); @@ -555,6 +587,7 @@ static void glui_context_reset(void) glui_handle_t *glui = NULL; menu_handle_t *menu = menu_driver_get_ptr(); settings_t *settings = config_get_ptr(); + gl_t *gl = (gl_t*)video_driver_get_ptr(NULL); if (!menu) return; @@ -588,6 +621,9 @@ static void glui_context_reset(void) texture_image_free(&ti); } + + if (gl->font_driver->bind_block) + gl->font_driver->bind_block(gl->font_handle, &glui->raster_block); } static void glui_navigation_clear(bool pending_push) diff --git a/menu/drivers/xmb.c b/menu/drivers/xmb.c index d2ad33de4d..eb9f76926c 100644 --- a/menu/drivers/xmb.c +++ b/menu/drivers/xmb.c @@ -211,6 +211,8 @@ typedef struct xmb_handle xmb_node_t settings_node; bool prevent_populate; + + gl_font_raster_block_t raster_block; } xmb_handle_t; static const GLfloat rmb_vertex[] = { @@ -397,7 +399,7 @@ static void xmb_draw_text(gl_t *gl, xmb_handle_t *xmb, const char *str, float x, || y < -xmb->icon.size || y > gl->win_height + xmb->icon.size) return; - 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; @@ -1165,6 +1167,7 @@ static void xmb_draw_items(xmb_handle_t *xmb, gl_t *gl, xmb_draw_icon_end(gl, xmb); } + } static void xmb_draw_cursor(gl_t *gl, xmb_handle_t *xmb, float x, float y) @@ -1377,6 +1380,9 @@ static void xmb_frame(void) xmb_frame_messagebox(msg); } + if (gl->font_driver->flush) + gl->font_driver->flush(gl->font_handle); + if (settings->menu.mouse.enable) xmb_draw_cursor(gl, xmb, menu->mouse.x, menu->mouse.y); @@ -1482,6 +1488,9 @@ static void *xmb_init(void) if (global->core_info) menu->categories.size = global->core_info->count + 1; + if (gl->font_driver->bind_block) + gl->font_driver->bind_block(gl->font_handle, &xmb->raster_block); + return menu; error: @@ -1497,9 +1506,18 @@ error: static void xmb_free(void *data) { menu_handle_t *menu = (menu_handle_t*)data; + xmb_handle_t *xmb = NULL; + gl_t *gl = (gl_t*)video_driver_get_ptr(NULL); if (menu && menu->userdata) free(menu->userdata); + + xmb = (xmb_handle_t*)menu->userdata; + + gl_coord_array_release(&xmb->raster_block.carr); + + if (gl->font_driver->bind_block) + gl->font_driver->bind_block(gl->font_handle, NULL); } static bool xmb_font_init_first(const gl_font_renderer_t **font_driver, @@ -1767,6 +1785,9 @@ static void xmb_context_reset(void) else if (xmb->depth <= 1) node->alpha = xmb->categories.passive.alpha; } + + if (gl->font_driver->bind_block) + gl->font_driver->bind_block(gl->font_handle, &xmb->raster_block); } static void xmb_navigation_clear(bool pending_push)