mirror of
https://github.com/libretro/RetroArch.git
synced 2024-11-24 08:30:16 +00:00
video_lima: add font rendering by using the temp buffer
This commit is contained in:
parent
a338d99781
commit
4b05426bbe
177
gfx/lima_gfx.c
177
gfx/lima_gfx.c
@ -90,8 +90,13 @@ typedef struct limare_data {
|
||||
|
||||
limare_texture_t **textures;
|
||||
unsigned texture_slots;
|
||||
|
||||
limare_texture_t *cur_texture;
|
||||
limare_texture_t *cur_texture_rgui;
|
||||
|
||||
unsigned font_width;
|
||||
unsigned font_height;
|
||||
limare_texture_t *font_texture;
|
||||
} limare_data_t;
|
||||
|
||||
/* Header for simple vertex shader. */
|
||||
@ -143,6 +148,14 @@ static const char *fshader_rgui_main_src =
|
||||
" gl_FragColor = pixel * uColor;\n"
|
||||
"}\n";
|
||||
|
||||
static inline void put_pixel_rgba4444(uint16_t *p, unsigned r, unsigned g, unsigned b, unsigned a) {
|
||||
*p = (a >> 4) | ((b >> 4) << 4) | ((g >> 4) << 8) | ((r >> 4) << 12);
|
||||
}
|
||||
|
||||
static inline unsigned align4(unsigned i) {
|
||||
return (i + 3) & ~0x3;
|
||||
}
|
||||
|
||||
static float get_screen_aspect(limare_state_t *state) {
|
||||
unsigned w = 0, h = 0;
|
||||
|
||||
@ -278,6 +291,8 @@ static const void *make_contiguous(limare_data_t *pdata,
|
||||
RARCH_ERR("video_lima: failed to allocate buffer to make pixel data contiguous\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
pdata->buffer_size = full_pitch * height;
|
||||
}
|
||||
|
||||
for (i = 0; i < height; ++i) {
|
||||
@ -399,6 +414,24 @@ fail:
|
||||
return -1;
|
||||
}
|
||||
|
||||
static void put_glyph_rgba4444(limare_data_t *pdata, const uint8_t *src, uint8_t *f_rgb,
|
||||
unsigned g_width, unsigned g_height, unsigned g_pitch,
|
||||
unsigned dst_x, unsigned dst_y) {
|
||||
unsigned x, y;
|
||||
uint16_t *dst;
|
||||
unsigned r, g, b;
|
||||
|
||||
dst = (uint16_t*)pdata->buffer + dst_y * pdata->font_width + dst_x;
|
||||
|
||||
for (y = 0; y < g_height; ++y, src += g_pitch, dst += pdata->font_width) {
|
||||
for (x = 0; x < g_width; ++x) {
|
||||
const uint8_t blend = src[x];
|
||||
|
||||
if (blend != 0) put_pixel_rgba4444(&dst[x], f_rgb[0], f_rgb[1], f_rgb[2], blend);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
typedef struct lima_video {
|
||||
limare_data_t *lima;
|
||||
|
||||
@ -439,6 +472,91 @@ static void lima_gfx_free(void *data) {
|
||||
free(vid);
|
||||
}
|
||||
|
||||
static void lima_init_font(lima_video_t *vid, const char *font_path, unsigned font_size) {
|
||||
if (!g_settings.video.font_enable) return;
|
||||
|
||||
if (font_renderer_create_default(&vid->font_driver, &vid->font)) {
|
||||
int r = g_settings.video.msg_color_r * 255;
|
||||
int g = g_settings.video.msg_color_g * 255;
|
||||
int b = g_settings.video.msg_color_b * 255;
|
||||
|
||||
vid->font_rgb[0] = r < 0 ? 0 : (r > 255 ? 255 : r);
|
||||
vid->font_rgb[1] = g < 0 ? 0 : (g > 255 ? 255 : g);
|
||||
vid->font_rgb[2] = b < 0 ? 0 : (b > 255 ? 255 : b);
|
||||
} else {
|
||||
RARCH_LOG("video_lima: font init failed\n");
|
||||
}
|
||||
}
|
||||
|
||||
static void lima_render_msg(lima_video_t *vid, const char *msg) {
|
||||
struct font_output_list out;
|
||||
struct font_output *head;
|
||||
|
||||
unsigned req_size;
|
||||
limare_data_t *lima = vid->lima;
|
||||
|
||||
const int msg_base_x = g_settings.video.msg_pos_x * lima->font_width;
|
||||
const int msg_base_y = (1.0 - g_settings.video.msg_pos_y) * lima->font_height;
|
||||
|
||||
if (vid->font == NULL) return;
|
||||
|
||||
/* Font texture uses RGBA4444 pixel data (2 bytes per pixel). */
|
||||
req_size = lima->font_width * lima->font_height * 2;
|
||||
|
||||
if (lima->buffer_size < req_size) {
|
||||
free(lima->buffer);
|
||||
lima->buffer = NULL;
|
||||
|
||||
lima->buffer = malloc(req_size);
|
||||
if (lima->buffer == NULL) {
|
||||
RARCH_ERR("video_lima: failed to allocate buffer to render fonts\n");
|
||||
return;
|
||||
}
|
||||
|
||||
lima->buffer_size = req_size;
|
||||
}
|
||||
|
||||
memset(lima->buffer, 0, req_size);
|
||||
|
||||
vid->font_driver->render_msg(vid->font, msg, &out);
|
||||
|
||||
for (head = out.head; head; head = head->next) {
|
||||
int base_x = msg_base_x + head->off_x;
|
||||
int base_y = msg_base_y - head->off_y - head->height;
|
||||
|
||||
const int max_width = lima->font_width - base_x;
|
||||
const int max_height = lima->font_height - base_y;
|
||||
|
||||
int glyph_width = head->width;
|
||||
int glyph_height = head->height;
|
||||
|
||||
const uint8_t *src = head->output;
|
||||
|
||||
if (base_x < 0) {
|
||||
src -= base_x;
|
||||
glyph_width += base_x;
|
||||
base_x = 0;
|
||||
}
|
||||
|
||||
if (base_y < 0) {
|
||||
src -= base_y * (int)head->pitch;
|
||||
glyph_height += base_y;
|
||||
base_y = 0;
|
||||
}
|
||||
|
||||
if (max_width <= 0 || max_height <= 0) continue;
|
||||
|
||||
if (glyph_width > max_width) glyph_width = max_width;
|
||||
if (glyph_height > max_height) glyph_height = max_height;
|
||||
|
||||
put_glyph_rgba4444(lima, src, vid->font_rgb,
|
||||
glyph_width, glyph_height,
|
||||
head->pitch, base_x, base_y);
|
||||
}
|
||||
|
||||
vid->font_driver->free_output(vid->font, &out);
|
||||
}
|
||||
|
||||
static void *lima_gfx_init(const video_info_t *video, const input_driver_t **input, void **input_data) {
|
||||
lima_video_t *vid = NULL;
|
||||
limare_data_t *lima = NULL;
|
||||
@ -476,6 +594,9 @@ static void *lima_gfx_init(const video_info_t *video, const input_driver_t **inp
|
||||
|
||||
lima->screen_aspect = get_screen_aspect(lima->state);
|
||||
|
||||
lima->font_height = 480;
|
||||
lima->font_width = align4((unsigned)(lima->screen_aspect * (float)lima->font_height));
|
||||
|
||||
lima->upload_format = (vid->bytes_per_pixel == 4) ?
|
||||
LIMA_TEXEL_FORMAT_RGBA_8888 : LIMA_TEXEL_FORMAT_BGR_565;
|
||||
lima->upload_bpp = vid->bytes_per_pixel;
|
||||
@ -507,7 +628,7 @@ static void *lima_gfx_init(const video_info_t *video, const input_driver_t **inp
|
||||
|
||||
vid->lima = lima;
|
||||
|
||||
/*lima_init_font(vid, g_settings.video.font_path, g_settings.video.font_size);*/
|
||||
lima_init_font(vid, g_settings.video.font_path, g_settings.video.font_size);
|
||||
|
||||
return vid;
|
||||
|
||||
@ -575,15 +696,12 @@ static bool lima_gfx_frame(void *data, const void *frame,
|
||||
}
|
||||
}
|
||||
|
||||
/*if (msg) lima_render_msg(vid, vid->screen, msg, vid->screen->w, vid->screen->h);
|
||||
if (g_settings.fps_show) {
|
||||
char buffer[128], buffer_fps[128];
|
||||
|
||||
char buffer[128], buffer_fps[128];
|
||||
bool fps_draw = g_settings.fps_show;
|
||||
if (fps_draw)
|
||||
{
|
||||
gfx_get_fps(buffer, sizeof(buffer), fps_draw ? buffer_fps : NULL, sizeof(buffer_fps));
|
||||
msg_queue_push(g_extern.msg_queue, buffer_fps, 1, 1);
|
||||
}*/
|
||||
gfx_get_fps(buffer, sizeof(buffer), g_settings.fps_show ? buffer_fps : NULL, sizeof(buffer_fps));
|
||||
msg_queue_push(g_extern.msg_queue, buffer_fps, 1, 1);
|
||||
}
|
||||
|
||||
if (vid->aspect_changed) {
|
||||
apply_aspect(lima, g_extern.system.aspect_ratio);
|
||||
@ -605,6 +723,47 @@ static bool lima_gfx_frame(void *data, const void *frame,
|
||||
if (limare_draw_arrays(lima->state, GL_TRIANGLE_STRIP, 0, 4)) return false;
|
||||
}
|
||||
|
||||
/* Handle font rendering. */
|
||||
if (msg) {
|
||||
bool upload_font = true;
|
||||
|
||||
/* Both font_vertices and font_color are constant, but we can't make them *
|
||||
* const, since limare_attribute_pointer expects (non-const) void pointers. */
|
||||
static vec3f_t font_vertices[4] = {
|
||||
{-1.0f, -1.0f, 0.0f},
|
||||
{ 1.0f, -1.0f, 0.0f},
|
||||
{-1.0f, 1.0f, 0.0f},
|
||||
{ 1.0f, 1.0f, 0.0f}
|
||||
};
|
||||
static float font_color[4] = {1.0f, 1.0f, 1.0f, 1.0f};
|
||||
|
||||
lima_render_msg(vid, msg);
|
||||
|
||||
if (lima->font_texture == NULL) {
|
||||
lima->font_texture = add_texture(lima, lima->font_width, lima->font_height,
|
||||
lima->buffer, LIMA_TEXEL_FORMAT_RGBA_4444);
|
||||
upload_font = false;
|
||||
}
|
||||
|
||||
if (upload_font)
|
||||
limare_texture_mipmap_upload(lima->state, lima->font_texture->handle, 0, lima->buffer);
|
||||
|
||||
/* We re-use the RGBA16 RGUI program here. */
|
||||
limare_program_current(lima->state, lima->program_rgui_rgba16);
|
||||
|
||||
limare_attribute_pointer(lima->state, "in_vertex", LIMARE_ATTRIB_FLOAT,
|
||||
3, 0, 4, font_vertices);
|
||||
limare_attribute_pointer(lima->state, "in_coord", LIMARE_ATTRIB_FLOAT,
|
||||
2, 0, 4, lima->coords + vid->rgui_rotation * 4);
|
||||
|
||||
limare_texture_attach(lima->state, "in_texture", lima->font_texture->handle);
|
||||
limare_uniform_attach(lima->state, "uColor", 4, font_color);
|
||||
|
||||
limare_enable(lima->state, GL_BLEND);
|
||||
if (limare_draw_arrays(lima->state, GL_TRIANGLE_STRIP, 0, 4)) return false;
|
||||
limare_disable(lima->state, GL_BLEND);
|
||||
}
|
||||
|
||||
if (vid->rgui_active && lima->cur_texture_rgui != NULL) {
|
||||
float color[4] = {1.0f, 1.0f, 1.0f, vid->rgui_alpha};
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user