From 5517fa16bdce40f066e3271691226ee6c47e39c2 Mon Sep 17 00:00:00 2001 From: David Herrmann Date: Wed, 1 Aug 2012 15:41:22 +0200 Subject: [PATCH] Use new text renderer This fixes the console and terminal layer to use the new text renderer instead of the old one. Signed-off-by: David Herrmann --- Makefile.am | 3 +- configure.ac | 2 +- src/console.c | 34 +++-------- src/console.h | 4 +- src/main.c | 14 ++++- src/terminal.c | 159 ++++++++++++++++++++++++++++++++++--------------- 6 files changed, 136 insertions(+), 80 deletions(-) diff --git a/Makefile.am b/Makefile.am index f5ce8db..4926535 100644 --- a/Makefile.am +++ b/Makefile.am @@ -118,8 +118,9 @@ libkmscon_core_la_SOURCES = \ src/pty.c src/pty.h \ src/gl.h \ src/gl_math.c \ - src/font_pango.c \ src/text.h \ + src/text.c \ + src/text_bblit.c \ src/text_font.c \ src/text_font_8x16.c \ src/text_font_pango.c diff --git a/configure.ac b/configure.ac index af71388..c6c2aca 100644 --- a/configure.ac +++ b/configure.ac @@ -76,7 +76,7 @@ PKG_CHECK_MODULES([GLES2], [glesv2], PKG_CHECK_MODULES([XKBCOMMON], [xkbcommon], [have_xkbcommon=yes], [have_xkbcommon=no]) -PKG_CHECK_MODULES([PANGO], [pango pangocairo cairo], +PKG_CHECK_MODULES([PANGO], [pango pangoft2], [have_pango=yes], [have_pango=no]) PKG_CHECK_MODULES([FREETYPE2], [freetype2], diff --git a/src/console.c b/src/console.c index 85276d5..c98152b 100644 --- a/src/console.c +++ b/src/console.c @@ -37,8 +37,8 @@ #include #include "console.h" #include "font.h" -#include "gl.h" #include "log.h" +#include "text.h" #include "unicode.h" #define LOG_SUBSYSTEM "console" @@ -729,17 +729,16 @@ void kmscon_console_reset_all_tabstops(struct kmscon_console *con) con->tab_ruler[i] = false; } -void kmscon_console_draw(struct kmscon_console *con, struct font_screen *fscr) +void kmscon_console_draw(struct kmscon_console *con, struct kmscon_text *txt) { unsigned int cur_x, cur_y; unsigned int i, j, k; struct line *iter, *line = NULL; struct cell *cell; - float m[16]; - bool cursor_done = false, draw_bg; struct font_char_attr attr; + bool cursor_done = false; - if (!con || !fscr) + if (!con || !txt) return; cur_x = con->cursor_x; @@ -749,7 +748,7 @@ void kmscon_console_draw(struct kmscon_console *con, struct font_screen *fscr) if (con->cursor_y >= con->size_y) cur_y = con->size_y - 1; - font_screen_draw_start(fscr); + kmscon_text_prepare(txt); iter = con->sb_pos; k = 0; @@ -780,22 +779,7 @@ void kmscon_console_draw(struct kmscon_console *con, struct font_screen *fscr) if (con->flags & KMSCON_CONSOLE_INVERSE) attr.inverse = !attr.inverse; - /* draw bg only if it differs from real bg */ - if (attr.inverse && - attr.fr == con->bg_r && - attr.fg == con->bg_g && - attr.fb == con->bg_b) - draw_bg = false; - else if (!attr.inverse && - attr.br == con->bg_r && - attr.bg == con->bg_g && - attr.bb == con->bg_b) - draw_bg = false; - else - draw_bg = true; - - font_screen_draw_char(fscr, cell->ch, &attr, - j, i, 1, 1, draw_bg); + kmscon_text_draw(txt, cell->ch, j, i, &attr); } if (k == cur_y + 1 && !cursor_done) { @@ -803,14 +787,12 @@ void kmscon_console_draw(struct kmscon_console *con, struct font_screen *fscr) if (!(con->flags & KMSCON_CONSOLE_HIDE_CURSOR)) { if (!(con->flags & KMSCON_CONSOLE_INVERSE)) attr.inverse = !attr.inverse; - font_screen_draw_char(fscr, 0, &attr, - cur_x, i, 1, 1, true); + kmscon_text_draw(txt, 0, cur_x, i, &attr); } } } - gl_m4_identity(m); - font_screen_draw_perform(fscr, m); + kmscon_text_render(txt); } void kmscon_console_write(struct kmscon_console *con, kmscon_symbol_t ch, diff --git a/src/console.h b/src/console.h index 0f95a64..e54dc3c 100644 --- a/src/console.h +++ b/src/console.h @@ -37,7 +37,7 @@ #include #include #include "font.h" -#include "gl.h" +#include "text.h" #include "unicode.h" struct kmscon_console; @@ -78,7 +78,7 @@ void kmscon_console_set_tabstop(struct kmscon_console *con); void kmscon_console_reset_tabstop(struct kmscon_console *con); void kmscon_console_reset_all_tabstops(struct kmscon_console *con); -void kmscon_console_draw(struct kmscon_console *con, struct font_screen *fscr); +void kmscon_console_draw(struct kmscon_console *con, struct kmscon_text *txt); void kmscon_console_write(struct kmscon_console *con, kmscon_symbol_t ch, const struct font_char_attr *attr); diff --git a/src/main.c b/src/main.c index 02e9d1f..9ac6691 100644 --- a/src/main.c +++ b/src/main.c @@ -33,6 +33,7 @@ #include "eloop.h" #include "log.h" #include "static_misc.h" +#include "text.h" #include "ui.h" #include "uterm.h" #include "vt.h" @@ -333,10 +334,14 @@ int main(int argc, char **argv) if (ret) goto err_out; + kmscon_font_8x16_load(); + kmscon_font_pango_load(); + kmscon_text_bblit_load(); + memset(&app, 0, sizeof(app)); ret = setup_app(&app); if (ret) - goto err_out; + goto err_unload; if (conf_global.switchvt) { /* TODO: implement automatic VT switching */ @@ -361,11 +366,18 @@ int main(int argc, char **argv) } destroy_app(&app); + kmscon_text_bblit_unload(); + kmscon_font_pango_unload(); + kmscon_font_8x16_unload(); conf_free(); log_info("exiting"); return EXIT_SUCCESS; +err_unload: + kmscon_text_bblit_unload(); + kmscon_font_pango_unload(); + kmscon_font_8x16_unload(); err_out: conf_free(); log_err("cannot initialize kmscon, errno %d: %s", ret, strerror(-ret)); diff --git a/src/terminal.c b/src/terminal.c index a06fd17..5202316 100644 --- a/src/terminal.c +++ b/src/terminal.c @@ -39,7 +39,9 @@ #include "gl.h" #include "log.h" #include "pty.h" +#include "static_misc.h" #include "terminal.h" +#include "text.h" #include "unicode.h" #include "uterm.h" #include "vte.h" @@ -47,12 +49,11 @@ #define LOG_SUBSYSTEM "terminal" struct screen { - struct screen *next; - struct screen *prev; + struct kmscon_dlist list; struct uterm_display *disp; struct uterm_screen *screen; - struct font_buffer *buf; - struct font_screen *fscr; + struct kmscon_font *font; + struct kmscon_text *txt; }; struct kmscon_terminal { @@ -63,9 +64,9 @@ struct kmscon_terminal { struct gl_shader *shader; bool opened; - struct screen *screens; - unsigned int max_width; - unsigned int max_height; + struct kmscon_dlist screens; + unsigned int min_cols; + unsigned int min_rows; bool redraw; struct kmscon_console *console; @@ -79,18 +80,19 @@ struct kmscon_terminal { static void draw_all(struct ev_eloop *eloop, void *unused, void *data) { struct kmscon_terminal *term = data; - struct screen *iter; struct uterm_screen *screen; int ret; unsigned int cflags; + struct kmscon_dlist *iter; + struct screen *ent; ev_eloop_unregister_idle_cb(term->eloop, draw_all, term); term->redraw = false; cflags = kmscon_console_get_flags(term->console); - iter = term->screens; - for (; iter; iter = iter->next) { - screen = iter->screen; + kmscon_dlist_for_each(iter, &term->screens) { + ent = kmscon_dlist_entry(iter, struct screen, list); + screen = ent->screen; ret = uterm_screen_use(screen); if (!ret) { @@ -101,7 +103,7 @@ static void draw_all(struct ev_eloop *eloop, void *unused, void *data) gl_clear_color(0.0, 0.0, 0.0, 1.0); gl_clear(); } - kmscon_console_draw(term->console, iter->fscr); + kmscon_console_draw(term->console, ent->txt); uterm_screen_swap(screen); } } @@ -120,15 +122,53 @@ static void schedule_redraw(struct kmscon_terminal *term) term->redraw = true; } +/* + * Resize terminal + * We support multiple monitors per terminal. As some software-rendering + * backends to not support scaling, we always use the smalles cols/rows that are + * provided so wider displays will have black margins. + * This can be extended to support scaling but that would mean we need to check + * whether the text-renderer backend supports that, first (TODO). + * + * If @force is true, then the console/pty are notified even though the size did + * not changed. If @notify is false, then console/pty are not notified even + * though the size might have changed. force = true and notify = false doesn't + * make any sense, though. + */ +static void terminal_resize(struct kmscon_terminal *term, + unsigned int cols, unsigned int rows, + bool force, bool notify) +{ + bool resize = false; + + if (!term->min_cols || (cols > 0 && cols < term->min_cols)) { + term->min_cols = cols; + resize = true; + } + if (!term->min_rows || (rows > 0 && rows < term->min_rows)) { + term->min_rows = rows; + resize = true; + } + + if (!notify || (!resize && !force)) + return; + + /* shrinking always succeeds */ + kmscon_console_resize(term->console, term->min_cols, term->min_rows); + kmscon_pty_resize(term->pty, term->min_cols, term->min_rows); +} + static int add_display(struct kmscon_terminal *term, struct uterm_display *disp) { + struct kmscon_dlist *iter; struct screen *scr; int ret; - unsigned int width, height; - struct screen *iter; + unsigned int cols, rows; + const struct kmscon_font_attr attr = { "", 0, 20, false, false, 0, 0 }; - for (iter = term->screens; iter; iter = iter->next) { - if (iter->disp == disp) + kmscon_dlist_for_each(iter, &term->screens) { + scr = kmscon_dlist_entry(iter, struct screen, list); + if (scr->disp == disp) return 0; } @@ -146,34 +186,35 @@ static int add_display(struct kmscon_terminal *term, struct uterm_display *disp) goto err_free; } - width = uterm_screen_width(scr->screen); - height = uterm_screen_height(scr->screen); - - ret = font_buffer_new(&scr->buf, width, height); + ret = kmscon_font_find(&scr->font, &attr, NULL); if (ret) { - log_error("cannot create buffer for display %p", scr->disp); + log_error("cannot create font"); goto err_screen; } - ret = font_screen_new_fixed(&scr->fscr, scr->buf, FONT_ATTR(NULL, 12, 0), - 80, 24, scr->screen, term->shader); + ret = kmscon_text_new(&scr->txt, NULL); if (ret) { - log_error("cannot create font for display %p", scr->disp); - goto err_buf; + log_error("cannot create text-renderer"); + goto err_font; } - scr->next = term->screens; - if (scr->next) - scr->next->prev = scr; - term->screens = scr; + kmscon_text_set_bgcolor(scr->txt, 0, 0, 0); + kmscon_text_set_font(scr->txt, scr->font); + kmscon_text_set_screen(scr->txt, scr->screen); + + cols = kmscon_text_get_cols(scr->txt); + rows = kmscon_text_get_rows(scr->txt); + terminal_resize(term, cols, rows, false, true); + + kmscon_dlist_link(&term->screens, &scr->list); log_debug("added display %p to terminal %p", disp, term); schedule_redraw(term); uterm_display_ref(scr->disp); return 0; -err_buf: - font_buffer_free(scr->buf); +err_font: + kmscon_font_unref(scr->font); err_screen: uterm_screen_unref(scr->screen); err_free: @@ -181,49 +222,68 @@ err_free: return ret; } -static void free_screen(struct screen *scr) +static void free_screen(struct kmscon_terminal *term, struct screen *scr, + bool update) { + struct kmscon_dlist *iter; + struct screen *ent; + log_debug("destroying terminal screen %p", scr); - font_screen_free(scr->fscr); - font_buffer_free(scr->buf); + kmscon_dlist_unlink(&scr->list); + kmscon_text_unref(scr->txt); + kmscon_font_unref(scr->font); uterm_screen_unref(scr->screen); uterm_display_unref(scr->disp); free(scr); + + if (!update) + return; + + term->min_cols = 0; + term->min_rows = 0; + kmscon_dlist_for_each(iter, &term->screens) { + ent = kmscon_dlist_entry(iter, struct screen, list); + terminal_resize(term, + kmscon_text_get_cols(ent->txt), + kmscon_text_get_rows(ent->txt), + false, false); + } + + terminal_resize(term, 0, 0, true, true); } static void rm_display(struct kmscon_terminal *term, struct uterm_display *disp) { + struct kmscon_dlist *iter; struct screen *scr; - for (scr = term->screens; scr; scr = scr->next) { - if (scr->disp == disp) { - if (scr->prev) - scr->prev->next = scr->next; - if (scr->next) - scr->next->prev = scr->prev; - if (term->screens == scr) - term->screens = scr->next; + kmscon_dlist_for_each(iter, &term->screens) { + scr = kmscon_dlist_entry(iter, struct screen, list); + if (scr->disp == disp) break; - } } - if (!scr) + if (iter == &term->screens) return; log_debug("removed display %p from terminal %p", disp, term); - free_screen(scr); - if (!term->screens && term->cb) + free_screen(term, scr, true); + if (kmscon_dlist_empty(&term->screens) && term->cb) term->cb(term, KMSCON_TERMINAL_NO_DISPLAY, term->data); } static void rm_all_screens(struct kmscon_terminal *term) { + struct kmscon_dlist *iter; struct screen *scr; - while ((scr = term->screens)) { - term->screens = scr->next; - free_screen(scr); + while ((iter = term->screens.next) != &term->screens) { + scr = kmscon_dlist_entry(iter, struct screen, list); + free_screen(term, scr, false); } + + term->min_cols = 0; + term->min_rows = 0; } static void pty_input(struct kmscon_pty *pty, const char *u8, size_t len, @@ -280,6 +340,7 @@ int kmscon_terminal_new(struct kmscon_terminal **out, term->eloop = loop; term->video = video; term->input = input; + kmscon_dlist_init(&term->screens); ret = kmscon_console_new(&term->console); if (ret)