video_lima: add font rendering by using the temp buffer

This commit is contained in:
Tobias Jakobi 2014-01-25 21:15:36 +01:00
parent a338d99781
commit 4b05426bbe

View File

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