diff options
Diffstat (limited to 'ui')
| -rw-r--r-- | ui/console.c | 109 | ||||
| -rw-r--r-- | ui/gtk-egl.c | 40 | ||||
| -rw-r--r-- | ui/gtk-gl-area.c | 52 |
3 files changed, 89 insertions, 112 deletions
diff --git a/ui/console.c b/ui/console.c index eabbbc951c..29a3e3f0f5 100644 --- a/ui/console.c +++ b/ui/console.c @@ -27,10 +27,12 @@ #include "hw/qdev-core.h" #include "qapi/error.h" #include "qapi/qapi-commands-ui.h" +#include "qemu/fifo8.h" +#include "qemu/main-loop.h" #include "qemu/module.h" #include "qemu/option.h" #include "qemu/timer.h" -#include "chardev/char-fe.h" +#include "chardev/char.h" #include "trace.h" #include "exec/memory.h" #include "io/channel-file.h" @@ -62,57 +64,6 @@ enum TTYState { TTY_STATE_CSI, }; -typedef struct QEMUFIFO { - uint8_t *buf; - int buf_size; - int count, wptr, rptr; -} QEMUFIFO; - -static int qemu_fifo_write(QEMUFIFO *f, const uint8_t *buf, int len1) -{ - int l, len; - - l = f->buf_size - f->count; - if (len1 > l) - len1 = l; - len = len1; - while (len > 0) { - l = f->buf_size - f->wptr; - if (l > len) - l = len; - memcpy(f->buf + f->wptr, buf, l); - f->wptr += l; - if (f->wptr >= f->buf_size) - f->wptr = 0; - buf += l; - len -= l; - } - f->count += len1; - return len1; -} - -static int qemu_fifo_read(QEMUFIFO *f, uint8_t *buf, int len1) -{ - int l, len; - - if (len1 > f->count) - len1 = f->count; - len = len1; - while (len > 0) { - l = f->buf_size - f->rptr; - if (l > len) - l = len; - memcpy(buf, f->buf + f->rptr, l); - f->rptr += l; - if (f->rptr >= f->buf_size) - f->rptr = 0; - buf += l; - len -= l; - } - f->count -= len1; - return len1; -} - typedef enum { GRAPHIC_CONSOLE, TEXT_CONSOLE, @@ -165,9 +116,7 @@ struct QemuConsole { Chardev *chr; /* fifo for key pressed */ - QEMUFIFO out_fifo; - uint8_t out_fifo_buf[16]; - QEMUTimer *kbd_timer; + Fifo8 out_fifo; CoQueue dump_queue; QTAILQ_ENTRY(QemuConsole) next; @@ -1157,25 +1106,20 @@ static int vc_chr_write(Chardev *chr, const uint8_t *buf, int len) return len; } -static void kbd_send_chars(void *opaque) +static void kbd_send_chars(QemuConsole *s) { - QemuConsole *s = opaque; - int len; - uint8_t buf[16]; + uint32_t len, avail; len = qemu_chr_be_can_write(s->chr); - if (len > s->out_fifo.count) - len = s->out_fifo.count; - if (len > 0) { - if (len > sizeof(buf)) - len = sizeof(buf); - qemu_fifo_read(&s->out_fifo, buf, len); - qemu_chr_be_write(s->chr, buf, len); - } - /* characters are pending: we send them a bit later (XXX: - horrible, should change char device API) */ - if (s->out_fifo.count > 0) { - timer_mod(s->kbd_timer, qemu_clock_get_ms(QEMU_CLOCK_REALTIME) + 1); + avail = fifo8_num_used(&s->out_fifo); + while (len > 0 && avail > 0) { + const uint8_t *buf; + uint32_t size; + + buf = fifo8_pop_buf(&s->out_fifo, MIN(len, avail), &size); + qemu_chr_be_write(s->chr, (uint8_t *)buf, size); + len = qemu_chr_be_can_write(s->chr); + avail -= size; } } @@ -1183,8 +1127,8 @@ static void kbd_send_chars(void *opaque) void kbd_put_keysym_console(QemuConsole *s, int keysym) { uint8_t buf[16], *q; - CharBackend *be; int c; + uint32_t num_free; if (!s || (s->console_type == GRAPHIC_CONSOLE)) return; @@ -1226,11 +1170,9 @@ void kbd_put_keysym_console(QemuConsole *s, int keysym) if (s->echo) { vc_chr_write(s->chr, buf, q - buf); } - be = s->chr->be; - if (be && be->chr_read) { - qemu_fifo_write(&s->out_fifo, buf, q - buf); - kbd_send_chars(s); - } + num_free = fifo8_num_free(&s->out_fifo); + fifo8_push_all(&s->out_fifo, buf, MIN(num_free, q - buf)); + kbd_send_chars(s); break; } } @@ -2186,6 +2128,14 @@ int qemu_console_get_height(QemuConsole *con, int fallback) return con ? surface_height(con->surface) : fallback; } +static void vc_chr_accept_input(Chardev *chr) +{ + VCChardev *drv = VC_CHARDEV(chr); + QemuConsole *s = drv->console; + + kbd_send_chars(s); +} + static void vc_chr_set_echo(Chardev *chr, bool echo) { VCChardev *drv = VC_CHARDEV(chr); @@ -2233,9 +2183,7 @@ static void text_console_do_init(Chardev *chr, DisplayState *ds) int g_width = 80 * FONT_WIDTH; int g_height = 24 * FONT_HEIGHT; - s->out_fifo.buf = s->out_fifo_buf; - s->out_fifo.buf_size = sizeof(s->out_fifo_buf); - s->kbd_timer = timer_new_ms(QEMU_CLOCK_REALTIME, kbd_send_chars, s); + fifo8_create(&s->out_fifo, 16); s->ds = ds; s->y_displayed = 0; @@ -2485,6 +2433,7 @@ static void char_vc_class_init(ObjectClass *oc, void *data) cc->parse = qemu_chr_parse_vc; cc->open = vc_chr_open; cc->chr_write = vc_chr_write; + cc->chr_accept_input = vc_chr_accept_input; cc->chr_set_echo = vc_chr_set_echo; } diff --git a/ui/gtk-egl.c b/ui/gtk-egl.c index 72ce5e1f8f..e912b20075 100644 --- a/ui/gtk-egl.c +++ b/ui/gtk-egl.c @@ -63,6 +63,9 @@ void gd_egl_init(VirtualConsole *vc) void gd_egl_draw(VirtualConsole *vc) { GdkWindow *window; +#ifdef CONFIG_GBM + QemuDmaBuf *dmabuf = vc->gfx.guest_fb.dmabuf; +#endif int ww, wh; if (!vc->gfx.gls) { @@ -74,10 +77,31 @@ void gd_egl_draw(VirtualConsole *vc) wh = gdk_window_get_height(window); if (vc->gfx.scanout_mode) { +#ifdef CONFIG_GBM + if (dmabuf) { + if (!dmabuf->draw_submitted) { + return; + } else { + dmabuf->draw_submitted = false; + } + } +#endif gd_egl_scanout_flush(&vc->gfx.dcl, 0, 0, vc->gfx.w, vc->gfx.h); vc->gfx.scale_x = (double)ww / vc->gfx.w; vc->gfx.scale_y = (double)wh / vc->gfx.h; + + glFlush(); +#ifdef CONFIG_GBM + if (dmabuf) { + egl_dmabuf_create_fence(dmabuf); + if (dmabuf->fence_fd > 0) { + qemu_set_fd_handler(dmabuf->fence_fd, gd_hw_gl_flushed, NULL, vc); + return; + } + graphic_hw_gl_block(vc->gfx.dcl.con, false); + } +#endif } else { if (!vc->gfx.ds) { return; @@ -92,21 +116,10 @@ void gd_egl_draw(VirtualConsole *vc) vc->gfx.scale_x = (double)ww / surface_width(vc->gfx.ds); vc->gfx.scale_y = (double)wh / surface_height(vc->gfx.ds); - } - - glFlush(); -#ifdef CONFIG_GBM - if (vc->gfx.guest_fb.dmabuf) { - QemuDmaBuf *dmabuf = vc->gfx.guest_fb.dmabuf; - egl_dmabuf_create_fence(dmabuf); - if (dmabuf->fence_fd > 0) { - qemu_set_fd_handler(dmabuf->fence_fd, gd_hw_gl_flushed, NULL, vc); - return; - } - graphic_hw_gl_block(vc->gfx.dcl.con, false); + glFlush(); } -#endif + graphic_hw_gl_flushed(vc->gfx.dcl.con); } @@ -317,6 +330,7 @@ void gd_egl_flush(DisplayChangeListener *dcl, if (vc->gfx.guest_fb.dmabuf) { graphic_hw_gl_block(vc->gfx.dcl.con, true); + vc->gfx.guest_fb.dmabuf->draw_submitted = true; gtk_widget_queue_draw_area(area, x, y, w, h); return; } diff --git a/ui/gtk-gl-area.c b/ui/gtk-gl-area.c index b23523748e..461da7712f 100644 --- a/ui/gtk-gl-area.c +++ b/ui/gtk-gl-area.c @@ -38,6 +38,9 @@ static void gtk_gl_area_set_scanout_mode(VirtualConsole *vc, bool scanout) void gd_gl_area_draw(VirtualConsole *vc) { +#ifdef CONFIG_GBM + QemuDmaBuf *dmabuf = vc->gfx.guest_fb.dmabuf; +#endif int ww, wh, y1, y2; if (!vc->gfx.gls) { @@ -53,6 +56,16 @@ void gd_gl_area_draw(VirtualConsole *vc) return; } +#ifdef CONFIG_GBM + if (dmabuf) { + if (!dmabuf->draw_submitted) { + return; + } else { + dmabuf->draw_submitted = false; + } + } +#endif + glBindFramebuffer(GL_READ_FRAMEBUFFER, vc->gfx.guest_fb.framebuffer); /* GtkGLArea sets GL_DRAW_FRAMEBUFFER for us */ @@ -62,6 +75,22 @@ void gd_gl_area_draw(VirtualConsole *vc) glBlitFramebuffer(0, y1, vc->gfx.w, y2, 0, 0, ww, wh, GL_COLOR_BUFFER_BIT, GL_NEAREST); +#ifdef CONFIG_GBM + if (dmabuf) { + egl_dmabuf_create_sync(dmabuf); + } +#endif + glFlush(); +#ifdef CONFIG_GBM + if (dmabuf) { + egl_dmabuf_create_fence(dmabuf); + if (dmabuf->fence_fd > 0) { + qemu_set_fd_handler(dmabuf->fence_fd, gd_hw_gl_flushed, NULL, vc); + return; + } + graphic_hw_gl_block(vc->gfx.dcl.con, false); + } +#endif } else { if (!vc->gfx.ds) { return; @@ -72,25 +101,6 @@ void gd_gl_area_draw(VirtualConsole *vc) surface_gl_render_texture(vc->gfx.gls, vc->gfx.ds); } -#ifdef CONFIG_GBM - if (vc->gfx.guest_fb.dmabuf) { - egl_dmabuf_create_sync(vc->gfx.guest_fb.dmabuf); - } -#endif - - glFlush(); -#ifdef CONFIG_GBM - if (vc->gfx.guest_fb.dmabuf) { - QemuDmaBuf *dmabuf = vc->gfx.guest_fb.dmabuf; - - egl_dmabuf_create_fence(dmabuf); - if (dmabuf->fence_fd > 0) { - qemu_set_fd_handler(dmabuf->fence_fd, gd_hw_gl_flushed, NULL, vc); - return; - } - graphic_hw_gl_block(vc->gfx.dcl.con, false); - } -#endif graphic_hw_gl_flushed(vc->gfx.dcl.con); } @@ -112,6 +122,9 @@ void gd_gl_area_refresh(DisplayChangeListener *dcl) { VirtualConsole *vc = container_of(dcl, VirtualConsole, gfx.dcl); + vc->gfx.dcl.update_interval = gd_monitor_update_interval( + vc->window ? vc->window : vc->gfx.drawing_area); + if (!vc->gfx.gls) { if (!gtk_widget_get_realized(vc->gfx.drawing_area)) { return; @@ -234,6 +247,7 @@ void gd_gl_area_scanout_flush(DisplayChangeListener *dcl, if (vc->gfx.guest_fb.dmabuf) { graphic_hw_gl_block(vc->gfx.dcl.con, true); + vc->gfx.guest_fb.dmabuf->draw_submitted = true; } gtk_gl_area_queue_render(GTK_GL_AREA(vc->gfx.drawing_area)); } |