OSDN Git Service

ui/console: drop have_gfx
[qmiga/qemu.git] / ui / console.c
1 /*
2  * QEMU graphical console
3  *
4  * Copyright (c) 2004 Fabrice Bellard
5  *
6  * Permission is hereby granted, free of charge, to any person obtaining a copy
7  * of this software and associated documentation files (the "Software"), to deal
8  * in the Software without restriction, including without limitation the rights
9  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10  * copies of the Software, and to permit persons to whom the Software is
11  * furnished to do so, subject to the following conditions:
12  *
13  * The above copyright notice and this permission notice shall be included in
14  * all copies or substantial portions of the Software.
15  *
16  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
19  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22  * THE SOFTWARE.
23  */
24
25 #include "qemu/osdep.h"
26 #include "ui/console.h"
27 #include "hw/qdev-core.h"
28 #include "qapi/error.h"
29 #include "qapi/qapi-commands-ui.h"
30 #include "qemu/coroutine.h"
31 #include "qemu/fifo8.h"
32 #include "qemu/error-report.h"
33 #include "qemu/main-loop.h"
34 #include "qemu/module.h"
35 #include "qemu/option.h"
36 #include "qemu/timer.h"
37 #include "chardev/char.h"
38 #include "trace.h"
39 #include "exec/memory.h"
40 #include "qom/object.h"
41
42 #define DEFAULT_BACKSCROLL 512
43 #define CONSOLE_CURSOR_PERIOD 500
44
45 typedef struct TextAttributes {
46     uint8_t fgcol:4;
47     uint8_t bgcol:4;
48     uint8_t bold:1;
49     uint8_t uline:1;
50     uint8_t blink:1;
51     uint8_t invers:1;
52     uint8_t unvisible:1;
53 } TextAttributes;
54
55 typedef struct TextCell {
56     uint8_t ch;
57     TextAttributes t_attrib;
58 } TextCell;
59
60 #define MAX_ESC_PARAMS 3
61
62 enum TTYState {
63     TTY_STATE_NORM,
64     TTY_STATE_ESC,
65     TTY_STATE_CSI,
66 };
67
68 typedef enum {
69     GRAPHIC_CONSOLE,
70     TEXT_CONSOLE,
71     TEXT_CONSOLE_FIXED_SIZE
72 } console_type_t;
73
74 struct QemuConsole {
75     Object parent;
76
77     int index;
78     console_type_t console_type;
79     DisplayState *ds;
80     DisplaySurface *surface;
81     DisplayScanout scanout;
82     int dcls;
83     DisplayGLCtx *gl;
84     int gl_block;
85     QEMUTimer *gl_unblock_timer;
86     int window_id;
87
88     /* Graphic console state.  */
89     Object *device;
90     uint32_t head;
91     QemuUIInfo ui_info;
92     QEMUTimer *ui_timer;
93     QEMUCursor *cursor;
94     int cursor_x, cursor_y, cursor_on;
95     const GraphicHwOps *hw_ops;
96     void *hw;
97
98     /* Text console state */
99     int width;
100     int height;
101     int total_height;
102     int backscroll_height;
103     int x, y;
104     int x_saved, y_saved;
105     int y_displayed;
106     int y_base;
107     TextAttributes t_attrib_default; /* default text attributes */
108     TextAttributes t_attrib; /* currently active text attributes */
109     TextCell *cells;
110     int text_x[2], text_y[2], cursor_invalidate;
111     int echo;
112
113     int update_x0;
114     int update_y0;
115     int update_x1;
116     int update_y1;
117
118     enum TTYState state;
119     int esc_params[MAX_ESC_PARAMS];
120     int nb_esc_params;
121
122     Chardev *chr;
123     /* fifo for key pressed */
124     Fifo8 out_fifo;
125     CoQueue dump_queue;
126
127     QTAILQ_ENTRY(QemuConsole) next;
128 };
129
130 struct DisplayState {
131     QEMUTimer *gui_timer;
132     uint64_t last_update;
133     uint64_t update_interval;
134     bool refreshing;
135
136     QLIST_HEAD(, DisplayChangeListener) listeners;
137 };
138
139 static DisplayState *display_state;
140 static QemuConsole *active_console;
141 static QTAILQ_HEAD(, QemuConsole) consoles =
142     QTAILQ_HEAD_INITIALIZER(consoles);
143 static bool cursor_visible_phase;
144 static QEMUTimer *cursor_timer;
145
146 static void text_console_do_init(Chardev *chr, DisplayState *ds);
147 static void dpy_refresh(DisplayState *s);
148 static DisplayState *get_alloc_displaystate(void);
149 static void text_console_update_cursor_timer(void);
150 static void text_console_update_cursor(void *opaque);
151 static bool displaychangelistener_has_dmabuf(DisplayChangeListener *dcl);
152 static bool console_compatible_with(QemuConsole *con,
153                                     DisplayChangeListener *dcl, Error **errp);
154
155 static void gui_update(void *opaque)
156 {
157     uint64_t interval = GUI_REFRESH_INTERVAL_IDLE;
158     uint64_t dcl_interval;
159     DisplayState *ds = opaque;
160     DisplayChangeListener *dcl;
161
162     ds->refreshing = true;
163     dpy_refresh(ds);
164     ds->refreshing = false;
165
166     QLIST_FOREACH(dcl, &ds->listeners, next) {
167         dcl_interval = dcl->update_interval ?
168             dcl->update_interval : GUI_REFRESH_INTERVAL_DEFAULT;
169         if (interval > dcl_interval) {
170             interval = dcl_interval;
171         }
172     }
173     if (ds->update_interval != interval) {
174         ds->update_interval = interval;
175         trace_console_refresh(interval);
176     }
177     ds->last_update = qemu_clock_get_ms(QEMU_CLOCK_REALTIME);
178     timer_mod(ds->gui_timer, ds->last_update + interval);
179 }
180
181 static void gui_setup_refresh(DisplayState *ds)
182 {
183     DisplayChangeListener *dcl;
184     bool need_timer = false;
185
186     QLIST_FOREACH(dcl, &ds->listeners, next) {
187         if (dcl->ops->dpy_refresh != NULL) {
188             need_timer = true;
189         }
190     }
191
192     if (need_timer && ds->gui_timer == NULL) {
193         ds->gui_timer = timer_new_ms(QEMU_CLOCK_REALTIME, gui_update, ds);
194         timer_mod(ds->gui_timer, qemu_clock_get_ms(QEMU_CLOCK_REALTIME));
195     }
196     if (!need_timer && ds->gui_timer != NULL) {
197         timer_free(ds->gui_timer);
198         ds->gui_timer = NULL;
199     }
200 }
201
202 void graphic_hw_update_done(QemuConsole *con)
203 {
204     if (con) {
205         qemu_co_enter_all(&con->dump_queue, NULL);
206     }
207 }
208
209 void graphic_hw_update(QemuConsole *con)
210 {
211     bool async = false;
212     con = con ? con : active_console;
213     if (!con) {
214         return;
215     }
216     if (con->hw_ops->gfx_update) {
217         con->hw_ops->gfx_update(con->hw);
218         async = con->hw_ops->gfx_update_async;
219     }
220     if (!async) {
221         graphic_hw_update_done(con);
222     }
223 }
224
225 static void graphic_hw_update_bh(void *con)
226 {
227     graphic_hw_update(con);
228 }
229
230 void qemu_console_co_wait_update(QemuConsole *con)
231 {
232     if (qemu_co_queue_empty(&con->dump_queue)) {
233         /* Defer the update, it will restart the pending coroutines */
234         aio_bh_schedule_oneshot(qemu_get_aio_context(),
235                                 graphic_hw_update_bh, con);
236     }
237     qemu_co_queue_wait(&con->dump_queue, NULL);
238
239 }
240
241 static void graphic_hw_gl_unblock_timer(void *opaque)
242 {
243     warn_report("console: no gl-unblock within one second");
244 }
245
246 void graphic_hw_gl_block(QemuConsole *con, bool block)
247 {
248     uint64_t timeout;
249     assert(con != NULL);
250
251     if (block) {
252         con->gl_block++;
253     } else {
254         con->gl_block--;
255     }
256     assert(con->gl_block >= 0);
257     if (!con->hw_ops->gl_block) {
258         return;
259     }
260     if ((block && con->gl_block != 1) || (!block && con->gl_block != 0)) {
261         return;
262     }
263     con->hw_ops->gl_block(con->hw, block);
264
265     if (block) {
266         timeout = qemu_clock_get_ms(QEMU_CLOCK_REALTIME);
267         timeout += 1000; /* one sec */
268         timer_mod(con->gl_unblock_timer, timeout);
269     } else {
270         timer_del(con->gl_unblock_timer);
271     }
272 }
273
274 int qemu_console_get_window_id(QemuConsole *con)
275 {
276     return con->window_id;
277 }
278
279 void qemu_console_set_window_id(QemuConsole *con, int window_id)
280 {
281     con->window_id = window_id;
282 }
283
284 void graphic_hw_invalidate(QemuConsole *con)
285 {
286     if (!con) {
287         con = active_console;
288     }
289     if (con && con->hw_ops->invalidate) {
290         con->hw_ops->invalidate(con->hw);
291     }
292 }
293
294 void graphic_hw_text_update(QemuConsole *con, console_ch_t *chardata)
295 {
296     if (!con) {
297         con = active_console;
298     }
299     if (con && con->hw_ops->text_update) {
300         con->hw_ops->text_update(con->hw, chardata);
301     }
302 }
303
304 static void vga_fill_rect(QemuConsole *con,
305                           int posx, int posy, int width, int height,
306                           pixman_color_t color)
307 {
308     DisplaySurface *surface = qemu_console_surface(con);
309     pixman_rectangle16_t rect = {
310         .x = posx, .y = posy, .width = width, .height = height
311     };
312
313     pixman_image_fill_rectangles(PIXMAN_OP_SRC, surface->image,
314                                  &color, 1, &rect);
315 }
316
317 /* copy from (xs, ys) to (xd, yd) a rectangle of size (w, h) */
318 static void vga_bitblt(QemuConsole *con,
319                        int xs, int ys, int xd, int yd, int w, int h)
320 {
321     DisplaySurface *surface = qemu_console_surface(con);
322
323     pixman_image_composite(PIXMAN_OP_SRC,
324                            surface->image, NULL, surface->image,
325                            xs, ys, 0, 0, xd, yd, w, h);
326 }
327
328 /***********************************************************/
329 /* basic char display */
330
331 #define FONT_HEIGHT 16
332 #define FONT_WIDTH 8
333
334 #include "vgafont.h"
335
336 #define QEMU_RGB(r, g, b)                                               \
337     { .red = r << 8, .green = g << 8, .blue = b << 8, .alpha = 0xffff }
338
339 static const pixman_color_t color_table_rgb[2][8] = {
340     {   /* dark */
341         [QEMU_COLOR_BLACK]   = QEMU_RGB(0x00, 0x00, 0x00),  /* black */
342         [QEMU_COLOR_BLUE]    = QEMU_RGB(0x00, 0x00, 0xaa),  /* blue */
343         [QEMU_COLOR_GREEN]   = QEMU_RGB(0x00, 0xaa, 0x00),  /* green */
344         [QEMU_COLOR_CYAN]    = QEMU_RGB(0x00, 0xaa, 0xaa),  /* cyan */
345         [QEMU_COLOR_RED]     = QEMU_RGB(0xaa, 0x00, 0x00),  /* red */
346         [QEMU_COLOR_MAGENTA] = QEMU_RGB(0xaa, 0x00, 0xaa),  /* magenta */
347         [QEMU_COLOR_YELLOW]  = QEMU_RGB(0xaa, 0xaa, 0x00),  /* yellow */
348         [QEMU_COLOR_WHITE]   = QEMU_RGB(0xaa, 0xaa, 0xaa),  /* white */
349     },
350     {   /* bright */
351         [QEMU_COLOR_BLACK]   = QEMU_RGB(0x00, 0x00, 0x00),  /* black */
352         [QEMU_COLOR_BLUE]    = QEMU_RGB(0x00, 0x00, 0xff),  /* blue */
353         [QEMU_COLOR_GREEN]   = QEMU_RGB(0x00, 0xff, 0x00),  /* green */
354         [QEMU_COLOR_CYAN]    = QEMU_RGB(0x00, 0xff, 0xff),  /* cyan */
355         [QEMU_COLOR_RED]     = QEMU_RGB(0xff, 0x00, 0x00),  /* red */
356         [QEMU_COLOR_MAGENTA] = QEMU_RGB(0xff, 0x00, 0xff),  /* magenta */
357         [QEMU_COLOR_YELLOW]  = QEMU_RGB(0xff, 0xff, 0x00),  /* yellow */
358         [QEMU_COLOR_WHITE]   = QEMU_RGB(0xff, 0xff, 0xff),  /* white */
359     }
360 };
361
362 static void vga_putcharxy(QemuConsole *s, int x, int y, int ch,
363                           TextAttributes *t_attrib)
364 {
365     static pixman_image_t *glyphs[256];
366     DisplaySurface *surface = qemu_console_surface(s);
367     pixman_color_t fgcol, bgcol;
368
369     if (t_attrib->invers) {
370         bgcol = color_table_rgb[t_attrib->bold][t_attrib->fgcol];
371         fgcol = color_table_rgb[t_attrib->bold][t_attrib->bgcol];
372     } else {
373         fgcol = color_table_rgb[t_attrib->bold][t_attrib->fgcol];
374         bgcol = color_table_rgb[t_attrib->bold][t_attrib->bgcol];
375     }
376
377     if (!glyphs[ch]) {
378         glyphs[ch] = qemu_pixman_glyph_from_vgafont(FONT_HEIGHT, vgafont16, ch);
379     }
380     qemu_pixman_glyph_render(glyphs[ch], surface->image,
381                              &fgcol, &bgcol, x, y, FONT_WIDTH, FONT_HEIGHT);
382 }
383
384 static void text_console_resize(QemuConsole *s)
385 {
386     TextCell *cells, *c, *c1;
387     int w1, x, y, last_width;
388
389     assert(s->scanout.kind == SCANOUT_SURFACE);
390
391     last_width = s->width;
392     s->width = surface_width(s->surface) / FONT_WIDTH;
393     s->height = surface_height(s->surface) / FONT_HEIGHT;
394
395     w1 = last_width;
396     if (s->width < w1)
397         w1 = s->width;
398
399     cells = g_new(TextCell, s->width * s->total_height + 1);
400     for(y = 0; y < s->total_height; y++) {
401         c = &cells[y * s->width];
402         if (w1 > 0) {
403             c1 = &s->cells[y * last_width];
404             for(x = 0; x < w1; x++) {
405                 *c++ = *c1++;
406             }
407         }
408         for(x = w1; x < s->width; x++) {
409             c->ch = ' ';
410             c->t_attrib = s->t_attrib_default;
411             c++;
412         }
413     }
414     g_free(s->cells);
415     s->cells = cells;
416 }
417
418 static inline void text_update_xy(QemuConsole *s, int x, int y)
419 {
420     s->text_x[0] = MIN(s->text_x[0], x);
421     s->text_x[1] = MAX(s->text_x[1], x);
422     s->text_y[0] = MIN(s->text_y[0], y);
423     s->text_y[1] = MAX(s->text_y[1], y);
424 }
425
426 static void invalidate_xy(QemuConsole *s, int x, int y)
427 {
428     if (!qemu_console_is_visible(s)) {
429         return;
430     }
431     if (s->update_x0 > x * FONT_WIDTH)
432         s->update_x0 = x * FONT_WIDTH;
433     if (s->update_y0 > y * FONT_HEIGHT)
434         s->update_y0 = y * FONT_HEIGHT;
435     if (s->update_x1 < (x + 1) * FONT_WIDTH)
436         s->update_x1 = (x + 1) * FONT_WIDTH;
437     if (s->update_y1 < (y + 1) * FONT_HEIGHT)
438         s->update_y1 = (y + 1) * FONT_HEIGHT;
439 }
440
441 static void update_xy(QemuConsole *s, int x, int y)
442 {
443     TextCell *c;
444     int y1, y2;
445
446     text_update_xy(s, x, y);
447
448     y1 = (s->y_base + y) % s->total_height;
449     y2 = y1 - s->y_displayed;
450     if (y2 < 0) {
451         y2 += s->total_height;
452     }
453     if (y2 < s->height) {
454         if (x >= s->width) {
455             x = s->width - 1;
456         }
457         c = &s->cells[y1 * s->width + x];
458         vga_putcharxy(s, x, y2, c->ch,
459                       &(c->t_attrib));
460         invalidate_xy(s, x, y2);
461     }
462 }
463
464 static void console_show_cursor(QemuConsole *s, int show)
465 {
466     TextCell *c;
467     int y, y1;
468     int x = s->x;
469
470     s->cursor_invalidate = 1;
471
472     if (x >= s->width) {
473         x = s->width - 1;
474     }
475     y1 = (s->y_base + s->y) % s->total_height;
476     y = y1 - s->y_displayed;
477     if (y < 0) {
478         y += s->total_height;
479     }
480     if (y < s->height) {
481         c = &s->cells[y1 * s->width + x];
482         if (show && cursor_visible_phase) {
483             TextAttributes t_attrib = s->t_attrib_default;
484             t_attrib.invers = !(t_attrib.invers); /* invert fg and bg */
485             vga_putcharxy(s, x, y, c->ch, &t_attrib);
486         } else {
487             vga_putcharxy(s, x, y, c->ch, &(c->t_attrib));
488         }
489         invalidate_xy(s, x, y);
490     }
491 }
492
493 static void console_refresh(QemuConsole *s)
494 {
495     DisplaySurface *surface = qemu_console_surface(s);
496     TextCell *c;
497     int x, y, y1;
498
499     s->text_x[0] = 0;
500     s->text_y[0] = 0;
501     s->text_x[1] = s->width - 1;
502     s->text_y[1] = s->height - 1;
503     s->cursor_invalidate = 1;
504
505     vga_fill_rect(s, 0, 0, surface_width(surface), surface_height(surface),
506                   color_table_rgb[0][QEMU_COLOR_BLACK]);
507     y1 = s->y_displayed;
508     for (y = 0; y < s->height; y++) {
509         c = s->cells + y1 * s->width;
510         for (x = 0; x < s->width; x++) {
511             vga_putcharxy(s, x, y, c->ch,
512                           &(c->t_attrib));
513             c++;
514         }
515         if (++y1 == s->total_height) {
516             y1 = 0;
517         }
518     }
519     console_show_cursor(s, 1);
520     dpy_gfx_update(s, 0, 0,
521                    surface_width(surface), surface_height(surface));
522 }
523
524 static void console_scroll(QemuConsole *s, int ydelta)
525 {
526     int i, y1;
527
528     if (ydelta > 0) {
529         for(i = 0; i < ydelta; i++) {
530             if (s->y_displayed == s->y_base)
531                 break;
532             if (++s->y_displayed == s->total_height)
533                 s->y_displayed = 0;
534         }
535     } else {
536         ydelta = -ydelta;
537         i = s->backscroll_height;
538         if (i > s->total_height - s->height)
539             i = s->total_height - s->height;
540         y1 = s->y_base - i;
541         if (y1 < 0)
542             y1 += s->total_height;
543         for(i = 0; i < ydelta; i++) {
544             if (s->y_displayed == y1)
545                 break;
546             if (--s->y_displayed < 0)
547                 s->y_displayed = s->total_height - 1;
548         }
549     }
550     console_refresh(s);
551 }
552
553 static void console_put_lf(QemuConsole *s)
554 {
555     TextCell *c;
556     int x, y1;
557
558     s->y++;
559     if (s->y >= s->height) {
560         s->y = s->height - 1;
561
562         if (s->y_displayed == s->y_base) {
563             if (++s->y_displayed == s->total_height)
564                 s->y_displayed = 0;
565         }
566         if (++s->y_base == s->total_height)
567             s->y_base = 0;
568         if (s->backscroll_height < s->total_height)
569             s->backscroll_height++;
570         y1 = (s->y_base + s->height - 1) % s->total_height;
571         c = &s->cells[y1 * s->width];
572         for(x = 0; x < s->width; x++) {
573             c->ch = ' ';
574             c->t_attrib = s->t_attrib_default;
575             c++;
576         }
577         if (s->y_displayed == s->y_base) {
578             s->text_x[0] = 0;
579             s->text_y[0] = 0;
580             s->text_x[1] = s->width - 1;
581             s->text_y[1] = s->height - 1;
582
583             vga_bitblt(s, 0, FONT_HEIGHT, 0, 0,
584                        s->width * FONT_WIDTH,
585                        (s->height - 1) * FONT_HEIGHT);
586             vga_fill_rect(s, 0, (s->height - 1) * FONT_HEIGHT,
587                           s->width * FONT_WIDTH, FONT_HEIGHT,
588                           color_table_rgb[0][s->t_attrib_default.bgcol]);
589             s->update_x0 = 0;
590             s->update_y0 = 0;
591             s->update_x1 = s->width * FONT_WIDTH;
592             s->update_y1 = s->height * FONT_HEIGHT;
593         }
594     }
595 }
596
597 /* Set console attributes depending on the current escape codes.
598  * NOTE: I know this code is not very efficient (checking every color for it
599  * self) but it is more readable and better maintainable.
600  */
601 static void console_handle_escape(QemuConsole *s)
602 {
603     int i;
604
605     for (i=0; i<s->nb_esc_params; i++) {
606         switch (s->esc_params[i]) {
607             case 0: /* reset all console attributes to default */
608                 s->t_attrib = s->t_attrib_default;
609                 break;
610             case 1:
611                 s->t_attrib.bold = 1;
612                 break;
613             case 4:
614                 s->t_attrib.uline = 1;
615                 break;
616             case 5:
617                 s->t_attrib.blink = 1;
618                 break;
619             case 7:
620                 s->t_attrib.invers = 1;
621                 break;
622             case 8:
623                 s->t_attrib.unvisible = 1;
624                 break;
625             case 22:
626                 s->t_attrib.bold = 0;
627                 break;
628             case 24:
629                 s->t_attrib.uline = 0;
630                 break;
631             case 25:
632                 s->t_attrib.blink = 0;
633                 break;
634             case 27:
635                 s->t_attrib.invers = 0;
636                 break;
637             case 28:
638                 s->t_attrib.unvisible = 0;
639                 break;
640             /* set foreground color */
641             case 30:
642                 s->t_attrib.fgcol = QEMU_COLOR_BLACK;
643                 break;
644             case 31:
645                 s->t_attrib.fgcol = QEMU_COLOR_RED;
646                 break;
647             case 32:
648                 s->t_attrib.fgcol = QEMU_COLOR_GREEN;
649                 break;
650             case 33:
651                 s->t_attrib.fgcol = QEMU_COLOR_YELLOW;
652                 break;
653             case 34:
654                 s->t_attrib.fgcol = QEMU_COLOR_BLUE;
655                 break;
656             case 35:
657                 s->t_attrib.fgcol = QEMU_COLOR_MAGENTA;
658                 break;
659             case 36:
660                 s->t_attrib.fgcol = QEMU_COLOR_CYAN;
661                 break;
662             case 37:
663                 s->t_attrib.fgcol = QEMU_COLOR_WHITE;
664                 break;
665             /* set background color */
666             case 40:
667                 s->t_attrib.bgcol = QEMU_COLOR_BLACK;
668                 break;
669             case 41:
670                 s->t_attrib.bgcol = QEMU_COLOR_RED;
671                 break;
672             case 42:
673                 s->t_attrib.bgcol = QEMU_COLOR_GREEN;
674                 break;
675             case 43:
676                 s->t_attrib.bgcol = QEMU_COLOR_YELLOW;
677                 break;
678             case 44:
679                 s->t_attrib.bgcol = QEMU_COLOR_BLUE;
680                 break;
681             case 45:
682                 s->t_attrib.bgcol = QEMU_COLOR_MAGENTA;
683                 break;
684             case 46:
685                 s->t_attrib.bgcol = QEMU_COLOR_CYAN;
686                 break;
687             case 47:
688                 s->t_attrib.bgcol = QEMU_COLOR_WHITE;
689                 break;
690         }
691     }
692 }
693
694 static void console_clear_xy(QemuConsole *s, int x, int y)
695 {
696     int y1 = (s->y_base + y) % s->total_height;
697     if (x >= s->width) {
698         x = s->width - 1;
699     }
700     TextCell *c = &s->cells[y1 * s->width + x];
701     c->ch = ' ';
702     c->t_attrib = s->t_attrib_default;
703     update_xy(s, x, y);
704 }
705
706 static void console_put_one(QemuConsole *s, int ch)
707 {
708     TextCell *c;
709     int y1;
710     if (s->x >= s->width) {
711         /* line wrap */
712         s->x = 0;
713         console_put_lf(s);
714     }
715     y1 = (s->y_base + s->y) % s->total_height;
716     c = &s->cells[y1 * s->width + s->x];
717     c->ch = ch;
718     c->t_attrib = s->t_attrib;
719     update_xy(s, s->x, s->y);
720     s->x++;
721 }
722
723 static void console_respond_str(QemuConsole *s, const char *buf)
724 {
725     while (*buf) {
726         console_put_one(s, *buf);
727         buf++;
728     }
729 }
730
731 /* set cursor, checking bounds */
732 static void set_cursor(QemuConsole *s, int x, int y)
733 {
734     if (x < 0) {
735         x = 0;
736     }
737     if (y < 0) {
738         y = 0;
739     }
740     if (y >= s->height) {
741         y = s->height - 1;
742     }
743     if (x >= s->width) {
744         x = s->width - 1;
745     }
746
747     s->x = x;
748     s->y = y;
749 }
750
751 static void console_putchar(QemuConsole *s, int ch)
752 {
753     int i;
754     int x, y;
755     char response[40];
756
757     switch(s->state) {
758     case TTY_STATE_NORM:
759         switch(ch) {
760         case '\r':  /* carriage return */
761             s->x = 0;
762             break;
763         case '\n':  /* newline */
764             console_put_lf(s);
765             break;
766         case '\b':  /* backspace */
767             if (s->x > 0)
768                 s->x--;
769             break;
770         case '\t':  /* tabspace */
771             if (s->x + (8 - (s->x % 8)) > s->width) {
772                 s->x = 0;
773                 console_put_lf(s);
774             } else {
775                 s->x = s->x + (8 - (s->x % 8));
776             }
777             break;
778         case '\a':  /* alert aka. bell */
779             /* TODO: has to be implemented */
780             break;
781         case 14:
782             /* SI (shift in), character set 0 (ignored) */
783             break;
784         case 15:
785             /* SO (shift out), character set 1 (ignored) */
786             break;
787         case 27:    /* esc (introducing an escape sequence) */
788             s->state = TTY_STATE_ESC;
789             break;
790         default:
791             console_put_one(s, ch);
792             break;
793         }
794         break;
795     case TTY_STATE_ESC: /* check if it is a terminal escape sequence */
796         if (ch == '[') {
797             for(i=0;i<MAX_ESC_PARAMS;i++)
798                 s->esc_params[i] = 0;
799             s->nb_esc_params = 0;
800             s->state = TTY_STATE_CSI;
801         } else {
802             s->state = TTY_STATE_NORM;
803         }
804         break;
805     case TTY_STATE_CSI: /* handle escape sequence parameters */
806         if (ch >= '0' && ch <= '9') {
807             if (s->nb_esc_params < MAX_ESC_PARAMS) {
808                 int *param = &s->esc_params[s->nb_esc_params];
809                 int digit = (ch - '0');
810
811                 *param = (*param <= (INT_MAX - digit) / 10) ?
812                          *param * 10 + digit : INT_MAX;
813             }
814         } else {
815             if (s->nb_esc_params < MAX_ESC_PARAMS)
816                 s->nb_esc_params++;
817             if (ch == ';' || ch == '?') {
818                 break;
819             }
820             trace_console_putchar_csi(s->esc_params[0], s->esc_params[1],
821                                       ch, s->nb_esc_params);
822             s->state = TTY_STATE_NORM;
823             switch(ch) {
824             case 'A':
825                 /* move cursor up */
826                 if (s->esc_params[0] == 0) {
827                     s->esc_params[0] = 1;
828                 }
829                 set_cursor(s, s->x, s->y - s->esc_params[0]);
830                 break;
831             case 'B':
832                 /* move cursor down */
833                 if (s->esc_params[0] == 0) {
834                     s->esc_params[0] = 1;
835                 }
836                 set_cursor(s, s->x, s->y + s->esc_params[0]);
837                 break;
838             case 'C':
839                 /* move cursor right */
840                 if (s->esc_params[0] == 0) {
841                     s->esc_params[0] = 1;
842                 }
843                 set_cursor(s, s->x + s->esc_params[0], s->y);
844                 break;
845             case 'D':
846                 /* move cursor left */
847                 if (s->esc_params[0] == 0) {
848                     s->esc_params[0] = 1;
849                 }
850                 set_cursor(s, s->x - s->esc_params[0], s->y);
851                 break;
852             case 'G':
853                 /* move cursor to column */
854                 set_cursor(s, s->esc_params[0] - 1, s->y);
855                 break;
856             case 'f':
857             case 'H':
858                 /* move cursor to row, column */
859                 set_cursor(s, s->esc_params[1] - 1, s->esc_params[0] - 1);
860                 break;
861             case 'J':
862                 switch (s->esc_params[0]) {
863                 case 0:
864                     /* clear to end of screen */
865                     for (y = s->y; y < s->height; y++) {
866                         for (x = 0; x < s->width; x++) {
867                             if (y == s->y && x < s->x) {
868                                 continue;
869                             }
870                             console_clear_xy(s, x, y);
871                         }
872                     }
873                     break;
874                 case 1:
875                     /* clear from beginning of screen */
876                     for (y = 0; y <= s->y; y++) {
877                         for (x = 0; x < s->width; x++) {
878                             if (y == s->y && x > s->x) {
879                                 break;
880                             }
881                             console_clear_xy(s, x, y);
882                         }
883                     }
884                     break;
885                 case 2:
886                     /* clear entire screen */
887                     for (y = 0; y <= s->height; y++) {
888                         for (x = 0; x < s->width; x++) {
889                             console_clear_xy(s, x, y);
890                         }
891                     }
892                     break;
893                 }
894                 break;
895             case 'K':
896                 switch (s->esc_params[0]) {
897                 case 0:
898                     /* clear to eol */
899                     for(x = s->x; x < s->width; x++) {
900                         console_clear_xy(s, x, s->y);
901                     }
902                     break;
903                 case 1:
904                     /* clear from beginning of line */
905                     for (x = 0; x <= s->x && x < s->width; x++) {
906                         console_clear_xy(s, x, s->y);
907                     }
908                     break;
909                 case 2:
910                     /* clear entire line */
911                     for(x = 0; x < s->width; x++) {
912                         console_clear_xy(s, x, s->y);
913                     }
914                     break;
915                 }
916                 break;
917             case 'm':
918                 console_handle_escape(s);
919                 break;
920             case 'n':
921                 switch (s->esc_params[0]) {
922                 case 5:
923                     /* report console status (always succeed)*/
924                     console_respond_str(s, "\033[0n");
925                     break;
926                 case 6:
927                     /* report cursor position */
928                     sprintf(response, "\033[%d;%dR",
929                            (s->y_base + s->y) % s->total_height + 1,
930                             s->x + 1);
931                     console_respond_str(s, response);
932                     break;
933                 }
934                 break;
935             case 's':
936                 /* save cursor position */
937                 s->x_saved = s->x;
938                 s->y_saved = s->y;
939                 break;
940             case 'u':
941                 /* restore cursor position */
942                 s->x = s->x_saved;
943                 s->y = s->y_saved;
944                 break;
945             default:
946                 trace_console_putchar_unhandled(ch);
947                 break;
948             }
949             break;
950         }
951     }
952 }
953
954 static void displaychangelistener_gfx_switch(DisplayChangeListener *dcl,
955                                              struct DisplaySurface *new_surface,
956                                              bool update)
957 {
958     if (dcl->ops->dpy_gfx_switch) {
959         dcl->ops->dpy_gfx_switch(dcl, new_surface);
960     }
961
962     if (update && dcl->ops->dpy_gfx_update) {
963         dcl->ops->dpy_gfx_update(dcl, 0, 0,
964                                  surface_width(new_surface),
965                                  surface_height(new_surface));
966     }
967 }
968
969 static void dpy_gfx_create_texture(QemuConsole *con, DisplaySurface *surface)
970 {
971     if (con->gl && con->gl->ops->dpy_gl_ctx_create_texture) {
972         con->gl->ops->dpy_gl_ctx_create_texture(con->gl, surface);
973     }
974 }
975
976 static void dpy_gfx_destroy_texture(QemuConsole *con, DisplaySurface *surface)
977 {
978     if (con->gl && con->gl->ops->dpy_gl_ctx_destroy_texture) {
979         con->gl->ops->dpy_gl_ctx_destroy_texture(con->gl, surface);
980     }
981 }
982
983 static void dpy_gfx_update_texture(QemuConsole *con, DisplaySurface *surface,
984                                    int x, int y, int w, int h)
985 {
986     if (con->gl && con->gl->ops->dpy_gl_ctx_update_texture) {
987         con->gl->ops->dpy_gl_ctx_update_texture(con->gl, surface, x, y, w, h);
988     }
989 }
990
991 static void displaychangelistener_display_console(DisplayChangeListener *dcl,
992                                                   QemuConsole *con,
993                                                   Error **errp)
994 {
995     static const char nodev[] =
996         "This VM has no graphic display device.";
997     static DisplaySurface *dummy;
998
999     if (!con || !console_compatible_with(con, dcl, errp)) {
1000         if (!dummy) {
1001             dummy = qemu_create_placeholder_surface(640, 480, nodev);
1002         }
1003         if (con) {
1004             dpy_gfx_create_texture(con, dummy);
1005         }
1006         displaychangelistener_gfx_switch(dcl, dummy, TRUE);
1007         return;
1008     }
1009
1010     dpy_gfx_create_texture(con, con->surface);
1011     displaychangelistener_gfx_switch(dcl, con->surface,
1012                                      con->scanout.kind == SCANOUT_SURFACE);
1013
1014     if (con->scanout.kind == SCANOUT_DMABUF &&
1015         displaychangelistener_has_dmabuf(dcl)) {
1016         dcl->ops->dpy_gl_scanout_dmabuf(dcl, con->scanout.dmabuf);
1017     } else if (con->scanout.kind == SCANOUT_TEXTURE &&
1018                dcl->ops->dpy_gl_scanout_texture) {
1019         dcl->ops->dpy_gl_scanout_texture(dcl,
1020                                          con->scanout.texture.backing_id,
1021                                          con->scanout.texture.backing_y_0_top,
1022                                          con->scanout.texture.backing_width,
1023                                          con->scanout.texture.backing_height,
1024                                          con->scanout.texture.x,
1025                                          con->scanout.texture.y,
1026                                          con->scanout.texture.width,
1027                                          con->scanout.texture.height,
1028                                          con->scanout.texture.d3d_tex2d);
1029     }
1030 }
1031
1032 void console_select(unsigned int index)
1033 {
1034     DisplayChangeListener *dcl;
1035     QemuConsole *s;
1036
1037     trace_console_select(index);
1038     s = qemu_console_lookup_by_index(index);
1039     if (s) {
1040         DisplayState *ds = s->ds;
1041
1042         active_console = s;
1043         QLIST_FOREACH (dcl, &ds->listeners, next) {
1044             if (dcl->con != NULL) {
1045                 continue;
1046             }
1047             displaychangelistener_display_console(dcl, s, NULL);
1048         }
1049         dpy_text_resize(s, s->width, s->height);
1050         text_console_update_cursor(NULL);
1051     }
1052 }
1053
1054 struct VCChardev {
1055     Chardev parent;
1056     QemuConsole *console;
1057 };
1058 typedef struct VCChardev VCChardev;
1059
1060 #define TYPE_CHARDEV_VC "chardev-vc"
1061 DECLARE_INSTANCE_CHECKER(VCChardev, VC_CHARDEV,
1062                          TYPE_CHARDEV_VC)
1063
1064 static int vc_chr_write(Chardev *chr, const uint8_t *buf, int len)
1065 {
1066     VCChardev *drv = VC_CHARDEV(chr);
1067     QemuConsole *s = drv->console;
1068     int i;
1069
1070     if (!s->ds) {
1071         return 0;
1072     }
1073
1074     s->update_x0 = s->width * FONT_WIDTH;
1075     s->update_y0 = s->height * FONT_HEIGHT;
1076     s->update_x1 = 0;
1077     s->update_y1 = 0;
1078     console_show_cursor(s, 0);
1079     for(i = 0; i < len; i++) {
1080         console_putchar(s, buf[i]);
1081     }
1082     console_show_cursor(s, 1);
1083     if (s->update_x0 < s->update_x1) {
1084         dpy_gfx_update(s, s->update_x0, s->update_y0,
1085                        s->update_x1 - s->update_x0,
1086                        s->update_y1 - s->update_y0);
1087     }
1088     return len;
1089 }
1090
1091 static void kbd_send_chars(QemuConsole *s)
1092 {
1093     uint32_t len, avail;
1094
1095     len = qemu_chr_be_can_write(s->chr);
1096     avail = fifo8_num_used(&s->out_fifo);
1097     while (len > 0 && avail > 0) {
1098         const uint8_t *buf;
1099         uint32_t size;
1100
1101         buf = fifo8_pop_buf(&s->out_fifo, MIN(len, avail), &size);
1102         qemu_chr_be_write(s->chr, buf, size);
1103         len = qemu_chr_be_can_write(s->chr);
1104         avail -= size;
1105     }
1106 }
1107
1108 /* called when an ascii key is pressed */
1109 void kbd_put_keysym_console(QemuConsole *s, int keysym)
1110 {
1111     uint8_t buf[16], *q;
1112     int c;
1113     uint32_t num_free;
1114
1115     if (!s || (s->console_type == GRAPHIC_CONSOLE))
1116         return;
1117
1118     switch(keysym) {
1119     case QEMU_KEY_CTRL_UP:
1120         console_scroll(s, -1);
1121         break;
1122     case QEMU_KEY_CTRL_DOWN:
1123         console_scroll(s, 1);
1124         break;
1125     case QEMU_KEY_CTRL_PAGEUP:
1126         console_scroll(s, -10);
1127         break;
1128     case QEMU_KEY_CTRL_PAGEDOWN:
1129         console_scroll(s, 10);
1130         break;
1131     default:
1132         /* convert the QEMU keysym to VT100 key string */
1133         q = buf;
1134         if (keysym >= 0xe100 && keysym <= 0xe11f) {
1135             *q++ = '\033';
1136             *q++ = '[';
1137             c = keysym - 0xe100;
1138             if (c >= 10)
1139                 *q++ = '0' + (c / 10);
1140             *q++ = '0' + (c % 10);
1141             *q++ = '~';
1142         } else if (keysym >= 0xe120 && keysym <= 0xe17f) {
1143             *q++ = '\033';
1144             *q++ = '[';
1145             *q++ = keysym & 0xff;
1146         } else if (s->echo && (keysym == '\r' || keysym == '\n')) {
1147             qemu_chr_write(s->chr, (uint8_t *)"\r", 1, true);
1148             *q++ = '\n';
1149         } else {
1150             *q++ = keysym;
1151         }
1152         if (s->echo) {
1153             qemu_chr_write(s->chr, buf, q - buf, true);
1154         }
1155         num_free = fifo8_num_free(&s->out_fifo);
1156         fifo8_push_all(&s->out_fifo, buf, MIN(num_free, q - buf));
1157         kbd_send_chars(s);
1158         break;
1159     }
1160 }
1161
1162 static const int qcode_to_keysym[Q_KEY_CODE__MAX] = {
1163     [Q_KEY_CODE_UP]     = QEMU_KEY_UP,
1164     [Q_KEY_CODE_DOWN]   = QEMU_KEY_DOWN,
1165     [Q_KEY_CODE_RIGHT]  = QEMU_KEY_RIGHT,
1166     [Q_KEY_CODE_LEFT]   = QEMU_KEY_LEFT,
1167     [Q_KEY_CODE_HOME]   = QEMU_KEY_HOME,
1168     [Q_KEY_CODE_END]    = QEMU_KEY_END,
1169     [Q_KEY_CODE_PGUP]   = QEMU_KEY_PAGEUP,
1170     [Q_KEY_CODE_PGDN]   = QEMU_KEY_PAGEDOWN,
1171     [Q_KEY_CODE_DELETE] = QEMU_KEY_DELETE,
1172     [Q_KEY_CODE_TAB]    = QEMU_KEY_TAB,
1173     [Q_KEY_CODE_BACKSPACE] = QEMU_KEY_BACKSPACE,
1174 };
1175
1176 static const int ctrl_qcode_to_keysym[Q_KEY_CODE__MAX] = {
1177     [Q_KEY_CODE_UP]     = QEMU_KEY_CTRL_UP,
1178     [Q_KEY_CODE_DOWN]   = QEMU_KEY_CTRL_DOWN,
1179     [Q_KEY_CODE_RIGHT]  = QEMU_KEY_CTRL_RIGHT,
1180     [Q_KEY_CODE_LEFT]   = QEMU_KEY_CTRL_LEFT,
1181     [Q_KEY_CODE_HOME]   = QEMU_KEY_CTRL_HOME,
1182     [Q_KEY_CODE_END]    = QEMU_KEY_CTRL_END,
1183     [Q_KEY_CODE_PGUP]   = QEMU_KEY_CTRL_PAGEUP,
1184     [Q_KEY_CODE_PGDN]   = QEMU_KEY_CTRL_PAGEDOWN,
1185 };
1186
1187 bool kbd_put_qcode_console(QemuConsole *s, int qcode, bool ctrl)
1188 {
1189     int keysym;
1190
1191     keysym = ctrl ? ctrl_qcode_to_keysym[qcode] : qcode_to_keysym[qcode];
1192     if (keysym == 0) {
1193         return false;
1194     }
1195     kbd_put_keysym_console(s, keysym);
1196     return true;
1197 }
1198
1199 void kbd_put_string_console(QemuConsole *s, const char *str, int len)
1200 {
1201     int i;
1202
1203     for (i = 0; i < len && str[i]; i++) {
1204         kbd_put_keysym_console(s, str[i]);
1205     }
1206 }
1207
1208 void kbd_put_keysym(int keysym)
1209 {
1210     kbd_put_keysym_console(active_console, keysym);
1211 }
1212
1213 static void text_console_invalidate(void *opaque)
1214 {
1215     QemuConsole *s = (QemuConsole *) opaque;
1216
1217     if (s->console_type == TEXT_CONSOLE) {
1218         text_console_resize(s);
1219     }
1220     console_refresh(s);
1221 }
1222
1223 static void text_console_update(void *opaque, console_ch_t *chardata)
1224 {
1225     QemuConsole *s = (QemuConsole *) opaque;
1226     int i, j, src;
1227
1228     if (s->text_x[0] <= s->text_x[1]) {
1229         src = (s->y_base + s->text_y[0]) * s->width;
1230         chardata += s->text_y[0] * s->width;
1231         for (i = s->text_y[0]; i <= s->text_y[1]; i ++)
1232             for (j = 0; j < s->width; j++, src++) {
1233                 console_write_ch(chardata ++,
1234                                  ATTR2CHTYPE(s->cells[src].ch,
1235                                              s->cells[src].t_attrib.fgcol,
1236                                              s->cells[src].t_attrib.bgcol,
1237                                              s->cells[src].t_attrib.bold));
1238             }
1239         dpy_text_update(s, s->text_x[0], s->text_y[0],
1240                         s->text_x[1] - s->text_x[0], i - s->text_y[0]);
1241         s->text_x[0] = s->width;
1242         s->text_y[0] = s->height;
1243         s->text_x[1] = 0;
1244         s->text_y[1] = 0;
1245     }
1246     if (s->cursor_invalidate) {
1247         dpy_text_cursor(s, s->x, s->y);
1248         s->cursor_invalidate = 0;
1249     }
1250 }
1251
1252 static QemuConsole *new_console(DisplayState *ds, console_type_t console_type,
1253                                 uint32_t head)
1254 {
1255     Object *obj;
1256     QemuConsole *s;
1257     int i;
1258
1259     obj = object_new(TYPE_QEMU_CONSOLE);
1260     s = QEMU_CONSOLE(obj);
1261     qemu_co_queue_init(&s->dump_queue);
1262     s->head = head;
1263     object_property_add_link(obj, "device", TYPE_DEVICE,
1264                              (Object **)&s->device,
1265                              object_property_allow_set_link,
1266                              OBJ_PROP_LINK_STRONG);
1267     object_property_add_uint32_ptr(obj, "head", &s->head,
1268                                    OBJ_PROP_FLAG_READ);
1269
1270     if (!active_console || ((active_console->console_type != GRAPHIC_CONSOLE) &&
1271         (console_type == GRAPHIC_CONSOLE))) {
1272         active_console = s;
1273     }
1274     s->ds = ds;
1275     s->console_type = console_type;
1276     s->window_id = -1;
1277
1278     if (QTAILQ_EMPTY(&consoles)) {
1279         s->index = 0;
1280         QTAILQ_INSERT_TAIL(&consoles, s, next);
1281     } else if (console_type != GRAPHIC_CONSOLE || phase_check(PHASE_MACHINE_READY)) {
1282         QemuConsole *last = QTAILQ_LAST(&consoles);
1283         s->index = last->index + 1;
1284         QTAILQ_INSERT_TAIL(&consoles, s, next);
1285     } else {
1286         /*
1287          * HACK: Put graphical consoles before text consoles.
1288          *
1289          * Only do that for coldplugged devices.  After initial device
1290          * initialization we will not renumber the consoles any more.
1291          */
1292         QemuConsole *c = QTAILQ_FIRST(&consoles);
1293
1294         while (QTAILQ_NEXT(c, next) != NULL &&
1295                c->console_type == GRAPHIC_CONSOLE) {
1296             c = QTAILQ_NEXT(c, next);
1297         }
1298         if (c->console_type == GRAPHIC_CONSOLE) {
1299             /* have no text consoles */
1300             s->index = c->index + 1;
1301             QTAILQ_INSERT_AFTER(&consoles, c, s, next);
1302         } else {
1303             s->index = c->index;
1304             QTAILQ_INSERT_BEFORE(c, s, next);
1305             /* renumber text consoles */
1306             for (i = s->index + 1; c != NULL; c = QTAILQ_NEXT(c, next), i++) {
1307                 c->index = i;
1308             }
1309         }
1310     }
1311     return s;
1312 }
1313
1314 #ifdef WIN32
1315 void qemu_displaysurface_win32_set_handle(DisplaySurface *surface,
1316                                           HANDLE h, uint32_t offset)
1317 {
1318     assert(!surface->handle);
1319
1320     surface->handle = h;
1321     surface->handle_offset = offset;
1322 }
1323
1324 static void
1325 win32_pixman_image_destroy(pixman_image_t *image, void *data)
1326 {
1327     DisplaySurface *surface = data;
1328
1329     if (!surface->handle) {
1330         return;
1331     }
1332
1333     assert(surface->handle_offset == 0);
1334
1335     qemu_win32_map_free(
1336         pixman_image_get_data(surface->image),
1337         surface->handle,
1338         &error_warn
1339     );
1340 }
1341 #endif
1342
1343 DisplaySurface *qemu_create_displaysurface(int width, int height)
1344 {
1345     DisplaySurface *surface;
1346     void *bits = NULL;
1347 #ifdef WIN32
1348     HANDLE handle = NULL;
1349 #endif
1350
1351     trace_displaysurface_create(width, height);
1352
1353 #ifdef WIN32
1354     bits = qemu_win32_map_alloc(width * height * 4, &handle, &error_abort);
1355 #endif
1356
1357     surface = qemu_create_displaysurface_from(
1358         width, height,
1359         PIXMAN_x8r8g8b8,
1360         width * 4, bits
1361     );
1362     surface->flags = QEMU_ALLOCATED_FLAG;
1363
1364 #ifdef WIN32
1365     qemu_displaysurface_win32_set_handle(surface, handle, 0);
1366 #endif
1367     return surface;
1368 }
1369
1370 DisplaySurface *qemu_create_displaysurface_from(int width, int height,
1371                                                 pixman_format_code_t format,
1372                                                 int linesize, uint8_t *data)
1373 {
1374     DisplaySurface *surface = g_new0(DisplaySurface, 1);
1375
1376     trace_displaysurface_create_from(surface, width, height, format);
1377     surface->format = format;
1378     surface->image = pixman_image_create_bits(surface->format,
1379                                               width, height,
1380                                               (void *)data, linesize);
1381     assert(surface->image != NULL);
1382 #ifdef WIN32
1383     pixman_image_set_destroy_function(surface->image,
1384                                       win32_pixman_image_destroy, surface);
1385 #endif
1386
1387     return surface;
1388 }
1389
1390 DisplaySurface *qemu_create_displaysurface_pixman(pixman_image_t *image)
1391 {
1392     DisplaySurface *surface = g_new0(DisplaySurface, 1);
1393
1394     trace_displaysurface_create_pixman(surface);
1395     surface->format = pixman_image_get_format(image);
1396     surface->image = pixman_image_ref(image);
1397
1398     return surface;
1399 }
1400
1401 DisplaySurface *qemu_create_placeholder_surface(int w, int h,
1402                                                 const char *msg)
1403 {
1404     DisplaySurface *surface = qemu_create_displaysurface(w, h);
1405     pixman_color_t bg = color_table_rgb[0][QEMU_COLOR_BLACK];
1406     pixman_color_t fg = color_table_rgb[0][QEMU_COLOR_WHITE];
1407     pixman_image_t *glyph;
1408     int len, x, y, i;
1409
1410     len = strlen(msg);
1411     x = (w / FONT_WIDTH  - len) / 2;
1412     y = (h / FONT_HEIGHT - 1)   / 2;
1413     for (i = 0; i < len; i++) {
1414         glyph = qemu_pixman_glyph_from_vgafont(FONT_HEIGHT, vgafont16, msg[i]);
1415         qemu_pixman_glyph_render(glyph, surface->image, &fg, &bg,
1416                                  x+i, y, FONT_WIDTH, FONT_HEIGHT);
1417         qemu_pixman_image_unref(glyph);
1418     }
1419     surface->flags |= QEMU_PLACEHOLDER_FLAG;
1420     return surface;
1421 }
1422
1423 void qemu_free_displaysurface(DisplaySurface *surface)
1424 {
1425     if (surface == NULL) {
1426         return;
1427     }
1428     trace_displaysurface_free(surface);
1429     qemu_pixman_image_unref(surface->image);
1430     g_free(surface);
1431 }
1432
1433 bool console_has_gl(QemuConsole *con)
1434 {
1435     return con->gl != NULL;
1436 }
1437
1438 static bool displaychangelistener_has_dmabuf(DisplayChangeListener *dcl)
1439 {
1440     if (dcl->ops->dpy_has_dmabuf) {
1441         return dcl->ops->dpy_has_dmabuf(dcl);
1442     }
1443
1444     if (dcl->ops->dpy_gl_scanout_dmabuf) {
1445         return true;
1446     }
1447
1448     return false;
1449 }
1450
1451 static bool console_compatible_with(QemuConsole *con,
1452                                     DisplayChangeListener *dcl, Error **errp)
1453 {
1454     int flags;
1455
1456     flags = con->hw_ops->get_flags ? con->hw_ops->get_flags(con->hw) : 0;
1457
1458     if (console_has_gl(con) &&
1459         !con->gl->ops->dpy_gl_ctx_is_compatible_dcl(con->gl, dcl)) {
1460         error_setg(errp, "Display %s is incompatible with the GL context",
1461                    dcl->ops->dpy_name);
1462         return false;
1463     }
1464
1465     if (flags & GRAPHIC_FLAGS_GL &&
1466         !console_has_gl(con)) {
1467         error_setg(errp, "The console requires a GL context.");
1468         return false;
1469
1470     }
1471
1472     if (flags & GRAPHIC_FLAGS_DMABUF &&
1473         !displaychangelistener_has_dmabuf(dcl)) {
1474         error_setg(errp, "The console requires display DMABUF support.");
1475         return false;
1476     }
1477
1478     return true;
1479 }
1480
1481 void console_handle_touch_event(QemuConsole *con,
1482                                 struct touch_slot touch_slots[INPUT_EVENT_SLOTS_MAX],
1483                                 uint64_t num_slot,
1484                                 int width, int height,
1485                                 double x, double y,
1486                                 InputMultiTouchType type,
1487                                 Error **errp)
1488 {
1489     struct touch_slot *slot;
1490     bool needs_sync = false;
1491     int update;
1492     int i;
1493
1494     if (num_slot >= INPUT_EVENT_SLOTS_MAX) {
1495         error_setg(errp,
1496                    "Unexpected touch slot number: % " PRId64" >= %d",
1497                    num_slot, INPUT_EVENT_SLOTS_MAX);
1498         return;
1499     }
1500
1501     slot = &touch_slots[num_slot];
1502     slot->x = x;
1503     slot->y = y;
1504
1505     if (type == INPUT_MULTI_TOUCH_TYPE_BEGIN) {
1506         slot->tracking_id = num_slot;
1507     }
1508
1509     for (i = 0; i < INPUT_EVENT_SLOTS_MAX; ++i) {
1510         if (i == num_slot) {
1511             update = type;
1512         } else {
1513             update = INPUT_MULTI_TOUCH_TYPE_UPDATE;
1514         }
1515
1516         slot = &touch_slots[i];
1517
1518         if (slot->tracking_id == -1) {
1519             continue;
1520         }
1521
1522         if (update == INPUT_MULTI_TOUCH_TYPE_END) {
1523             slot->tracking_id = -1;
1524             qemu_input_queue_mtt(con, update, i, slot->tracking_id);
1525             needs_sync = true;
1526         } else {
1527             qemu_input_queue_mtt(con, update, i, slot->tracking_id);
1528             qemu_input_queue_btn(con, INPUT_BUTTON_TOUCH, true);
1529             qemu_input_queue_mtt_abs(con,
1530                                     INPUT_AXIS_X, (int) slot->x,
1531                                     0, width,
1532                                     i, slot->tracking_id);
1533             qemu_input_queue_mtt_abs(con,
1534                                     INPUT_AXIS_Y, (int) slot->y,
1535                                     0, height,
1536                                     i, slot->tracking_id);
1537             needs_sync = true;
1538         }
1539     }
1540
1541     if (needs_sync) {
1542         qemu_input_event_sync();
1543     }
1544 }
1545
1546 void qemu_console_set_display_gl_ctx(QemuConsole *con, DisplayGLCtx *gl)
1547 {
1548     /* display has opengl support */
1549     assert(con);
1550     if (con->gl) {
1551         error_report("The console already has an OpenGL context.");
1552         exit(1);
1553     }
1554     con->gl = gl;
1555 }
1556
1557 void register_displaychangelistener(DisplayChangeListener *dcl)
1558 {
1559     QemuConsole *con;
1560
1561     assert(!dcl->ds);
1562
1563     trace_displaychangelistener_register(dcl, dcl->ops->dpy_name);
1564     dcl->ds = get_alloc_displaystate();
1565     QLIST_INSERT_HEAD(&dcl->ds->listeners, dcl, next);
1566     gui_setup_refresh(dcl->ds);
1567     if (dcl->con) {
1568         dcl->con->dcls++;
1569         con = dcl->con;
1570     } else {
1571         con = active_console;
1572     }
1573     displaychangelistener_display_console(dcl, con, dcl->con ? &error_fatal : NULL);
1574     if (con && con->cursor && dcl->ops->dpy_cursor_define) {
1575         dcl->ops->dpy_cursor_define(dcl, con->cursor);
1576     }
1577     if (con && dcl->ops->dpy_mouse_set) {
1578         dcl->ops->dpy_mouse_set(dcl, con->cursor_x, con->cursor_y, con->cursor_on);
1579     }
1580     text_console_update_cursor(NULL);
1581 }
1582
1583 void update_displaychangelistener(DisplayChangeListener *dcl,
1584                                   uint64_t interval)
1585 {
1586     DisplayState *ds = dcl->ds;
1587
1588     dcl->update_interval = interval;
1589     if (!ds->refreshing && ds->update_interval > interval) {
1590         timer_mod(ds->gui_timer, ds->last_update + interval);
1591     }
1592 }
1593
1594 void unregister_displaychangelistener(DisplayChangeListener *dcl)
1595 {
1596     DisplayState *ds = dcl->ds;
1597     trace_displaychangelistener_unregister(dcl, dcl->ops->dpy_name);
1598     if (dcl->con) {
1599         dcl->con->dcls--;
1600     }
1601     QLIST_REMOVE(dcl, next);
1602     dcl->ds = NULL;
1603     gui_setup_refresh(ds);
1604 }
1605
1606 static void dpy_set_ui_info_timer(void *opaque)
1607 {
1608     QemuConsole *con = opaque;
1609
1610     con->hw_ops->ui_info(con->hw, con->head, &con->ui_info);
1611 }
1612
1613 bool dpy_ui_info_supported(QemuConsole *con)
1614 {
1615     if (con == NULL) {
1616         con = active_console;
1617     }
1618
1619     return con->hw_ops->ui_info != NULL;
1620 }
1621
1622 const QemuUIInfo *dpy_get_ui_info(const QemuConsole *con)
1623 {
1624     if (con == NULL) {
1625         con = active_console;
1626     }
1627
1628     return &con->ui_info;
1629 }
1630
1631 int dpy_set_ui_info(QemuConsole *con, QemuUIInfo *info, bool delay)
1632 {
1633     if (con == NULL) {
1634         con = active_console;
1635     }
1636
1637     if (!dpy_ui_info_supported(con)) {
1638         return -1;
1639     }
1640     if (memcmp(&con->ui_info, info, sizeof(con->ui_info)) == 0) {
1641         /* nothing changed -- ignore */
1642         return 0;
1643     }
1644
1645     /*
1646      * Typically we get a flood of these as the user resizes the window.
1647      * Wait until the dust has settled (one second without updates), then
1648      * go notify the guest.
1649      */
1650     con->ui_info = *info;
1651     timer_mod(con->ui_timer,
1652               qemu_clock_get_ms(QEMU_CLOCK_REALTIME) + (delay ? 1000 : 0));
1653     return 0;
1654 }
1655
1656 void dpy_gfx_update(QemuConsole *con, int x, int y, int w, int h)
1657 {
1658     DisplayState *s = con->ds;
1659     DisplayChangeListener *dcl;
1660     int width = qemu_console_get_width(con, x + w);
1661     int height = qemu_console_get_height(con, y + h);
1662
1663     x = MAX(x, 0);
1664     y = MAX(y, 0);
1665     x = MIN(x, width);
1666     y = MIN(y, height);
1667     w = MIN(w, width - x);
1668     h = MIN(h, height - y);
1669
1670     if (!qemu_console_is_visible(con)) {
1671         return;
1672     }
1673     dpy_gfx_update_texture(con, con->surface, x, y, w, h);
1674     QLIST_FOREACH(dcl, &s->listeners, next) {
1675         if (con != (dcl->con ? dcl->con : active_console)) {
1676             continue;
1677         }
1678         if (dcl->ops->dpy_gfx_update) {
1679             dcl->ops->dpy_gfx_update(dcl, x, y, w, h);
1680         }
1681     }
1682 }
1683
1684 void dpy_gfx_update_full(QemuConsole *con)
1685 {
1686     int w = qemu_console_get_width(con, 0);
1687     int h = qemu_console_get_height(con, 0);
1688
1689     dpy_gfx_update(con, 0, 0, w, h);
1690 }
1691
1692 void dpy_gfx_replace_surface(QemuConsole *con,
1693                              DisplaySurface *surface)
1694 {
1695     static const char placeholder_msg[] = "Display output is not active.";
1696     DisplayState *s = con->ds;
1697     DisplaySurface *old_surface = con->surface;
1698     DisplaySurface *new_surface = surface;
1699     DisplayChangeListener *dcl;
1700     int width;
1701     int height;
1702
1703     if (!surface) {
1704         if (old_surface) {
1705             width = surface_width(old_surface);
1706             height = surface_height(old_surface);
1707         } else {
1708             width = 640;
1709             height = 480;
1710         }
1711
1712         new_surface = qemu_create_placeholder_surface(width, height, placeholder_msg);
1713     }
1714
1715     assert(old_surface != new_surface);
1716
1717     con->scanout.kind = SCANOUT_SURFACE;
1718     con->surface = new_surface;
1719     dpy_gfx_create_texture(con, new_surface);
1720     QLIST_FOREACH(dcl, &s->listeners, next) {
1721         if (con != (dcl->con ? dcl->con : active_console)) {
1722             continue;
1723         }
1724         displaychangelistener_gfx_switch(dcl, new_surface, surface ? FALSE : TRUE);
1725     }
1726     dpy_gfx_destroy_texture(con, old_surface);
1727     qemu_free_displaysurface(old_surface);
1728 }
1729
1730 bool dpy_gfx_check_format(QemuConsole *con,
1731                           pixman_format_code_t format)
1732 {
1733     DisplayChangeListener *dcl;
1734     DisplayState *s = con->ds;
1735
1736     QLIST_FOREACH(dcl, &s->listeners, next) {
1737         if (dcl->con && dcl->con != con) {
1738             /* dcl bound to another console -> skip */
1739             continue;
1740         }
1741         if (dcl->ops->dpy_gfx_check_format) {
1742             if (!dcl->ops->dpy_gfx_check_format(dcl, format)) {
1743                 return false;
1744             }
1745         } else {
1746             /* default is to allow native 32 bpp only */
1747             if (format != qemu_default_pixman_format(32, true)) {
1748                 return false;
1749             }
1750         }
1751     }
1752     return true;
1753 }
1754
1755 static void dpy_refresh(DisplayState *s)
1756 {
1757     DisplayChangeListener *dcl;
1758
1759     QLIST_FOREACH(dcl, &s->listeners, next) {
1760         if (dcl->ops->dpy_refresh) {
1761             dcl->ops->dpy_refresh(dcl);
1762         }
1763     }
1764 }
1765
1766 void dpy_text_cursor(QemuConsole *con, int x, int y)
1767 {
1768     DisplayState *s = con->ds;
1769     DisplayChangeListener *dcl;
1770
1771     if (!qemu_console_is_visible(con)) {
1772         return;
1773     }
1774     QLIST_FOREACH(dcl, &s->listeners, next) {
1775         if (con != (dcl->con ? dcl->con : active_console)) {
1776             continue;
1777         }
1778         if (dcl->ops->dpy_text_cursor) {
1779             dcl->ops->dpy_text_cursor(dcl, x, y);
1780         }
1781     }
1782 }
1783
1784 void dpy_text_update(QemuConsole *con, int x, int y, int w, int h)
1785 {
1786     DisplayState *s = con->ds;
1787     DisplayChangeListener *dcl;
1788
1789     if (!qemu_console_is_visible(con)) {
1790         return;
1791     }
1792     QLIST_FOREACH(dcl, &s->listeners, next) {
1793         if (con != (dcl->con ? dcl->con : active_console)) {
1794             continue;
1795         }
1796         if (dcl->ops->dpy_text_update) {
1797             dcl->ops->dpy_text_update(dcl, x, y, w, h);
1798         }
1799     }
1800 }
1801
1802 void dpy_text_resize(QemuConsole *con, int w, int h)
1803 {
1804     DisplayState *s = con->ds;
1805     DisplayChangeListener *dcl;
1806
1807     if (!qemu_console_is_visible(con)) {
1808         return;
1809     }
1810     QLIST_FOREACH(dcl, &s->listeners, next) {
1811         if (con != (dcl->con ? dcl->con : active_console)) {
1812             continue;
1813         }
1814         if (dcl->ops->dpy_text_resize) {
1815             dcl->ops->dpy_text_resize(dcl, w, h);
1816         }
1817     }
1818 }
1819
1820 void dpy_mouse_set(QemuConsole *con, int x, int y, int on)
1821 {
1822     DisplayState *s = con->ds;
1823     DisplayChangeListener *dcl;
1824
1825     con->cursor_x = x;
1826     con->cursor_y = y;
1827     con->cursor_on = on;
1828     if (!qemu_console_is_visible(con)) {
1829         return;
1830     }
1831     QLIST_FOREACH(dcl, &s->listeners, next) {
1832         if (con != (dcl->con ? dcl->con : active_console)) {
1833             continue;
1834         }
1835         if (dcl->ops->dpy_mouse_set) {
1836             dcl->ops->dpy_mouse_set(dcl, x, y, on);
1837         }
1838     }
1839 }
1840
1841 void dpy_cursor_define(QemuConsole *con, QEMUCursor *cursor)
1842 {
1843     DisplayState *s = con->ds;
1844     DisplayChangeListener *dcl;
1845
1846     cursor_unref(con->cursor);
1847     con->cursor = cursor_ref(cursor);
1848     if (!qemu_console_is_visible(con)) {
1849         return;
1850     }
1851     QLIST_FOREACH(dcl, &s->listeners, next) {
1852         if (con != (dcl->con ? dcl->con : active_console)) {
1853             continue;
1854         }
1855         if (dcl->ops->dpy_cursor_define) {
1856             dcl->ops->dpy_cursor_define(dcl, cursor);
1857         }
1858     }
1859 }
1860
1861 bool dpy_cursor_define_supported(QemuConsole *con)
1862 {
1863     DisplayState *s = con->ds;
1864     DisplayChangeListener *dcl;
1865
1866     QLIST_FOREACH(dcl, &s->listeners, next) {
1867         if (dcl->ops->dpy_cursor_define) {
1868             return true;
1869         }
1870     }
1871     return false;
1872 }
1873
1874 QEMUGLContext dpy_gl_ctx_create(QemuConsole *con,
1875                                 struct QEMUGLParams *qparams)
1876 {
1877     assert(con->gl);
1878     return con->gl->ops->dpy_gl_ctx_create(con->gl, qparams);
1879 }
1880
1881 void dpy_gl_ctx_destroy(QemuConsole *con, QEMUGLContext ctx)
1882 {
1883     assert(con->gl);
1884     con->gl->ops->dpy_gl_ctx_destroy(con->gl, ctx);
1885 }
1886
1887 int dpy_gl_ctx_make_current(QemuConsole *con, QEMUGLContext ctx)
1888 {
1889     assert(con->gl);
1890     return con->gl->ops->dpy_gl_ctx_make_current(con->gl, ctx);
1891 }
1892
1893 void dpy_gl_scanout_disable(QemuConsole *con)
1894 {
1895     DisplayState *s = con->ds;
1896     DisplayChangeListener *dcl;
1897
1898     if (con->scanout.kind != SCANOUT_SURFACE) {
1899         con->scanout.kind = SCANOUT_NONE;
1900     }
1901     QLIST_FOREACH(dcl, &s->listeners, next) {
1902         if (con != (dcl->con ? dcl->con : active_console)) {
1903             continue;
1904         }
1905         if (dcl->ops->dpy_gl_scanout_disable) {
1906             dcl->ops->dpy_gl_scanout_disable(dcl);
1907         }
1908     }
1909 }
1910
1911 void dpy_gl_scanout_texture(QemuConsole *con,
1912                             uint32_t backing_id,
1913                             bool backing_y_0_top,
1914                             uint32_t backing_width,
1915                             uint32_t backing_height,
1916                             uint32_t x, uint32_t y,
1917                             uint32_t width, uint32_t height,
1918                             void *d3d_tex2d)
1919 {
1920     DisplayState *s = con->ds;
1921     DisplayChangeListener *dcl;
1922
1923     con->scanout.kind = SCANOUT_TEXTURE;
1924     con->scanout.texture = (ScanoutTexture) {
1925         backing_id, backing_y_0_top, backing_width, backing_height,
1926         x, y, width, height, d3d_tex2d,
1927     };
1928     QLIST_FOREACH(dcl, &s->listeners, next) {
1929         if (con != (dcl->con ? dcl->con : active_console)) {
1930             continue;
1931         }
1932         if (dcl->ops->dpy_gl_scanout_texture) {
1933             dcl->ops->dpy_gl_scanout_texture(dcl, backing_id,
1934                                              backing_y_0_top,
1935                                              backing_width, backing_height,
1936                                              x, y, width, height,
1937                                              d3d_tex2d);
1938         }
1939     }
1940 }
1941
1942 void dpy_gl_scanout_dmabuf(QemuConsole *con,
1943                            QemuDmaBuf *dmabuf)
1944 {
1945     DisplayState *s = con->ds;
1946     DisplayChangeListener *dcl;
1947
1948     con->scanout.kind = SCANOUT_DMABUF;
1949     con->scanout.dmabuf = dmabuf;
1950     QLIST_FOREACH(dcl, &s->listeners, next) {
1951         if (con != (dcl->con ? dcl->con : active_console)) {
1952             continue;
1953         }
1954         if (dcl->ops->dpy_gl_scanout_dmabuf) {
1955             dcl->ops->dpy_gl_scanout_dmabuf(dcl, dmabuf);
1956         }
1957     }
1958 }
1959
1960 void dpy_gl_cursor_dmabuf(QemuConsole *con, QemuDmaBuf *dmabuf,
1961                           bool have_hot, uint32_t hot_x, uint32_t hot_y)
1962 {
1963     DisplayState *s = con->ds;
1964     DisplayChangeListener *dcl;
1965
1966     QLIST_FOREACH(dcl, &s->listeners, next) {
1967         if (con != (dcl->con ? dcl->con : active_console)) {
1968             continue;
1969         }
1970         if (dcl->ops->dpy_gl_cursor_dmabuf) {
1971             dcl->ops->dpy_gl_cursor_dmabuf(dcl, dmabuf,
1972                                            have_hot, hot_x, hot_y);
1973         }
1974     }
1975 }
1976
1977 void dpy_gl_cursor_position(QemuConsole *con,
1978                             uint32_t pos_x, uint32_t pos_y)
1979 {
1980     DisplayState *s = con->ds;
1981     DisplayChangeListener *dcl;
1982
1983     QLIST_FOREACH(dcl, &s->listeners, next) {
1984         if (con != (dcl->con ? dcl->con : active_console)) {
1985             continue;
1986         }
1987         if (dcl->ops->dpy_gl_cursor_position) {
1988             dcl->ops->dpy_gl_cursor_position(dcl, pos_x, pos_y);
1989         }
1990     }
1991 }
1992
1993 void dpy_gl_release_dmabuf(QemuConsole *con,
1994                           QemuDmaBuf *dmabuf)
1995 {
1996     DisplayState *s = con->ds;
1997     DisplayChangeListener *dcl;
1998
1999     QLIST_FOREACH(dcl, &s->listeners, next) {
2000         if (con != (dcl->con ? dcl->con : active_console)) {
2001             continue;
2002         }
2003         if (dcl->ops->dpy_gl_release_dmabuf) {
2004             dcl->ops->dpy_gl_release_dmabuf(dcl, dmabuf);
2005         }
2006     }
2007 }
2008
2009 void dpy_gl_update(QemuConsole *con,
2010                    uint32_t x, uint32_t y, uint32_t w, uint32_t h)
2011 {
2012     DisplayState *s = con->ds;
2013     DisplayChangeListener *dcl;
2014
2015     assert(con->gl);
2016
2017     graphic_hw_gl_block(con, true);
2018     QLIST_FOREACH(dcl, &s->listeners, next) {
2019         if (con != (dcl->con ? dcl->con : active_console)) {
2020             continue;
2021         }
2022         if (dcl->ops->dpy_gl_update) {
2023             dcl->ops->dpy_gl_update(dcl, x, y, w, h);
2024         }
2025     }
2026     graphic_hw_gl_block(con, false);
2027 }
2028
2029 /***********************************************************/
2030 /* register display */
2031
2032 /* console.c internal use only */
2033 static DisplayState *get_alloc_displaystate(void)
2034 {
2035     if (!display_state) {
2036         display_state = g_new0(DisplayState, 1);
2037         cursor_timer = timer_new_ms(QEMU_CLOCK_REALTIME,
2038                                     text_console_update_cursor, NULL);
2039     }
2040     return display_state;
2041 }
2042
2043 /*
2044  * Called by main(), after creating QemuConsoles
2045  * and before initializing ui (sdl/vnc/...).
2046  */
2047 DisplayState *init_displaystate(void)
2048 {
2049     gchar *name;
2050     QemuConsole *con;
2051
2052     get_alloc_displaystate();
2053     QTAILQ_FOREACH(con, &consoles, next) {
2054         if (con->console_type != GRAPHIC_CONSOLE &&
2055             con->ds == NULL) {
2056             text_console_do_init(con->chr, display_state);
2057         }
2058
2059         /* Hook up into the qom tree here (not in new_console()), once
2060          * all QemuConsoles are created and the order / numbering
2061          * doesn't change any more */
2062         name = g_strdup_printf("console[%d]", con->index);
2063         object_property_add_child(container_get(object_get_root(), "/backend"),
2064                                   name, OBJECT(con));
2065         g_free(name);
2066     }
2067
2068     return display_state;
2069 }
2070
2071 void graphic_console_set_hwops(QemuConsole *con,
2072                                const GraphicHwOps *hw_ops,
2073                                void *opaque)
2074 {
2075     con->hw_ops = hw_ops;
2076     con->hw = opaque;
2077 }
2078
2079 QemuConsole *graphic_console_init(DeviceState *dev, uint32_t head,
2080                                   const GraphicHwOps *hw_ops,
2081                                   void *opaque)
2082 {
2083     static const char noinit[] =
2084         "Guest has not initialized the display (yet).";
2085     int width = 640;
2086     int height = 480;
2087     QemuConsole *s;
2088     DisplayState *ds;
2089     DisplaySurface *surface;
2090
2091     ds = get_alloc_displaystate();
2092     s = qemu_console_lookup_unused();
2093     if (s) {
2094         trace_console_gfx_reuse(s->index);
2095         width = qemu_console_get_width(s, 0);
2096         height = qemu_console_get_height(s, 0);
2097     } else {
2098         trace_console_gfx_new();
2099         s = new_console(ds, GRAPHIC_CONSOLE, head);
2100         s->ui_timer = timer_new_ms(QEMU_CLOCK_REALTIME,
2101                                    dpy_set_ui_info_timer, s);
2102     }
2103     graphic_console_set_hwops(s, hw_ops, opaque);
2104     if (dev) {
2105         object_property_set_link(OBJECT(s), "device", OBJECT(dev),
2106                                  &error_abort);
2107     }
2108
2109     surface = qemu_create_placeholder_surface(width, height, noinit);
2110     dpy_gfx_replace_surface(s, surface);
2111     s->gl_unblock_timer = timer_new_ms(QEMU_CLOCK_REALTIME,
2112                                        graphic_hw_gl_unblock_timer, s);
2113     return s;
2114 }
2115
2116 static const GraphicHwOps unused_ops = {
2117     /* no callbacks */
2118 };
2119
2120 void graphic_console_close(QemuConsole *con)
2121 {
2122     static const char unplugged[] =
2123         "Guest display has been unplugged";
2124     DisplaySurface *surface;
2125     int width = qemu_console_get_width(con, 640);
2126     int height = qemu_console_get_height(con, 480);
2127
2128     trace_console_gfx_close(con->index);
2129     object_property_set_link(OBJECT(con), "device", NULL, &error_abort);
2130     graphic_console_set_hwops(con, &unused_ops, NULL);
2131
2132     if (con->gl) {
2133         dpy_gl_scanout_disable(con);
2134     }
2135     surface = qemu_create_placeholder_surface(width, height, unplugged);
2136     dpy_gfx_replace_surface(con, surface);
2137 }
2138
2139 QemuConsole *qemu_console_lookup_by_index(unsigned int index)
2140 {
2141     QemuConsole *con;
2142
2143     QTAILQ_FOREACH(con, &consoles, next) {
2144         if (con->index == index) {
2145             return con;
2146         }
2147     }
2148     return NULL;
2149 }
2150
2151 QemuConsole *qemu_console_lookup_by_device(DeviceState *dev, uint32_t head)
2152 {
2153     QemuConsole *con;
2154     Object *obj;
2155     uint32_t h;
2156
2157     QTAILQ_FOREACH(con, &consoles, next) {
2158         obj = object_property_get_link(OBJECT(con),
2159                                        "device", &error_abort);
2160         if (DEVICE(obj) != dev) {
2161             continue;
2162         }
2163         h = object_property_get_uint(OBJECT(con),
2164                                      "head", &error_abort);
2165         if (h != head) {
2166             continue;
2167         }
2168         return con;
2169     }
2170     return NULL;
2171 }
2172
2173 QemuConsole *qemu_console_lookup_by_device_name(const char *device_id,
2174                                                 uint32_t head, Error **errp)
2175 {
2176     DeviceState *dev;
2177     QemuConsole *con;
2178
2179     dev = qdev_find_recursive(sysbus_get_default(), device_id);
2180     if (dev == NULL) {
2181         error_set(errp, ERROR_CLASS_DEVICE_NOT_FOUND,
2182                   "Device '%s' not found", device_id);
2183         return NULL;
2184     }
2185
2186     con = qemu_console_lookup_by_device(dev, head);
2187     if (con == NULL) {
2188         error_setg(errp, "Device %s (head %d) is not bound to a QemuConsole",
2189                    device_id, head);
2190         return NULL;
2191     }
2192
2193     return con;
2194 }
2195
2196 QemuConsole *qemu_console_lookup_unused(void)
2197 {
2198     QemuConsole *con;
2199     Object *obj;
2200
2201     QTAILQ_FOREACH(con, &consoles, next) {
2202         if (con->hw_ops != &unused_ops) {
2203             continue;
2204         }
2205         obj = object_property_get_link(OBJECT(con),
2206                                        "device", &error_abort);
2207         if (obj != NULL) {
2208             continue;
2209         }
2210         return con;
2211     }
2212     return NULL;
2213 }
2214
2215 QEMUCursor *qemu_console_get_cursor(QemuConsole *con)
2216 {
2217     if (con == NULL) {
2218         con = active_console;
2219     }
2220     return con ? con->cursor : NULL;
2221 }
2222
2223 bool qemu_console_is_visible(QemuConsole *con)
2224 {
2225     return (con == active_console) || (con->dcls > 0);
2226 }
2227
2228 bool qemu_console_is_graphic(QemuConsole *con)
2229 {
2230     if (con == NULL) {
2231         con = active_console;
2232     }
2233     return con && (con->console_type == GRAPHIC_CONSOLE);
2234 }
2235
2236 bool qemu_console_is_fixedsize(QemuConsole *con)
2237 {
2238     if (con == NULL) {
2239         con = active_console;
2240     }
2241     return con && (con->console_type != TEXT_CONSOLE);
2242 }
2243
2244 bool qemu_console_is_gl_blocked(QemuConsole *con)
2245 {
2246     assert(con != NULL);
2247     return con->gl_block;
2248 }
2249
2250 bool qemu_console_is_multihead(DeviceState *dev)
2251 {
2252     QemuConsole *con;
2253     Object *obj;
2254     uint32_t f = 0xffffffff;
2255     uint32_t h;
2256
2257     QTAILQ_FOREACH(con, &consoles, next) {
2258         obj = object_property_get_link(OBJECT(con),
2259                                        "device", &error_abort);
2260         if (DEVICE(obj) != dev) {
2261             continue;
2262         }
2263
2264         h = object_property_get_uint(OBJECT(con),
2265                                      "head", &error_abort);
2266         if (f == 0xffffffff) {
2267             f = h;
2268         } else if (h != f) {
2269             return true;
2270         }
2271     }
2272     return false;
2273 }
2274
2275 char *qemu_console_get_label(QemuConsole *con)
2276 {
2277     if (con->console_type == GRAPHIC_CONSOLE) {
2278         if (con->device) {
2279             DeviceState *dev;
2280             bool multihead;
2281
2282             dev = DEVICE(con->device);
2283             multihead = qemu_console_is_multihead(dev);
2284             if (multihead) {
2285                 return g_strdup_printf("%s.%d", dev->id ?
2286                                        dev->id :
2287                                        object_get_typename(con->device),
2288                                        con->head);
2289             } else {
2290                 return g_strdup_printf("%s", dev->id ?
2291                                        dev->id :
2292                                        object_get_typename(con->device));
2293             }
2294         }
2295         return g_strdup("VGA");
2296     } else {
2297         if (con->chr && con->chr->label) {
2298             return g_strdup(con->chr->label);
2299         }
2300         return g_strdup_printf("vc%d", con->index);
2301     }
2302 }
2303
2304 int qemu_console_get_index(QemuConsole *con)
2305 {
2306     if (con == NULL) {
2307         con = active_console;
2308     }
2309     return con ? con->index : -1;
2310 }
2311
2312 uint32_t qemu_console_get_head(QemuConsole *con)
2313 {
2314     if (con == NULL) {
2315         con = active_console;
2316     }
2317     return con ? con->head : -1;
2318 }
2319
2320 int qemu_console_get_width(QemuConsole *con, int fallback)
2321 {
2322     if (con == NULL) {
2323         con = active_console;
2324     }
2325     if (con == NULL) {
2326         return fallback;
2327     }
2328     switch (con->scanout.kind) {
2329     case SCANOUT_DMABUF:
2330         return con->scanout.dmabuf->width;
2331     case SCANOUT_TEXTURE:
2332         return con->scanout.texture.width;
2333     case SCANOUT_SURFACE:
2334         return surface_width(con->surface);
2335     default:
2336         return fallback;
2337     }
2338 }
2339
2340 int qemu_console_get_height(QemuConsole *con, int fallback)
2341 {
2342     if (con == NULL) {
2343         con = active_console;
2344     }
2345     if (con == NULL) {
2346         return fallback;
2347     }
2348     switch (con->scanout.kind) {
2349     case SCANOUT_DMABUF:
2350         return con->scanout.dmabuf->height;
2351     case SCANOUT_TEXTURE:
2352         return con->scanout.texture.height;
2353     case SCANOUT_SURFACE:
2354         return surface_height(con->surface);
2355     default:
2356         return fallback;
2357     }
2358 }
2359
2360 static void vc_chr_accept_input(Chardev *chr)
2361 {
2362     VCChardev *drv = VC_CHARDEV(chr);
2363     QemuConsole *s = drv->console;
2364
2365     kbd_send_chars(s);
2366 }
2367
2368 static void vc_chr_set_echo(Chardev *chr, bool echo)
2369 {
2370     VCChardev *drv = VC_CHARDEV(chr);
2371     QemuConsole *s = drv->console;
2372
2373     s->echo = echo;
2374 }
2375
2376 static void text_console_update_cursor_timer(void)
2377 {
2378     timer_mod(cursor_timer, qemu_clock_get_ms(QEMU_CLOCK_REALTIME)
2379               + CONSOLE_CURSOR_PERIOD / 2);
2380 }
2381
2382 static void text_console_update_cursor(void *opaque)
2383 {
2384     QemuConsole *s;
2385     int count = 0;
2386
2387     cursor_visible_phase = !cursor_visible_phase;
2388
2389     QTAILQ_FOREACH(s, &consoles, next) {
2390         if (qemu_console_is_graphic(s) ||
2391             !qemu_console_is_visible(s)) {
2392             continue;
2393         }
2394         count++;
2395         graphic_hw_invalidate(s);
2396     }
2397
2398     if (count) {
2399         text_console_update_cursor_timer();
2400     }
2401 }
2402
2403 static const GraphicHwOps text_console_ops = {
2404     .invalidate  = text_console_invalidate,
2405     .text_update = text_console_update,
2406 };
2407
2408 static void text_console_do_init(Chardev *chr, DisplayState *ds)
2409 {
2410     VCChardev *drv = VC_CHARDEV(chr);
2411     QemuConsole *s = drv->console;
2412     int g_width = 80 * FONT_WIDTH;
2413     int g_height = 24 * FONT_HEIGHT;
2414
2415     fifo8_create(&s->out_fifo, 16);
2416     s->ds = ds;
2417
2418     s->y_displayed = 0;
2419     s->y_base = 0;
2420     s->total_height = DEFAULT_BACKSCROLL;
2421     s->x = 0;
2422     s->y = 0;
2423     if (s->scanout.kind != SCANOUT_SURFACE) {
2424         if (active_console && active_console->scanout.kind == SCANOUT_SURFACE) {
2425             g_width = qemu_console_get_width(active_console, g_width);
2426             g_height = qemu_console_get_height(active_console, g_height);
2427         }
2428         s->surface = qemu_create_displaysurface(g_width, g_height);
2429         s->scanout.kind = SCANOUT_SURFACE;
2430     }
2431
2432     s->hw_ops = &text_console_ops;
2433     s->hw = s;
2434
2435     /* Set text attribute defaults */
2436     s->t_attrib_default.bold = 0;
2437     s->t_attrib_default.uline = 0;
2438     s->t_attrib_default.blink = 0;
2439     s->t_attrib_default.invers = 0;
2440     s->t_attrib_default.unvisible = 0;
2441     s->t_attrib_default.fgcol = QEMU_COLOR_WHITE;
2442     s->t_attrib_default.bgcol = QEMU_COLOR_BLACK;
2443     /* set current text attributes to default */
2444     s->t_attrib = s->t_attrib_default;
2445     text_console_resize(s);
2446
2447     if (chr->label) {
2448         char *msg;
2449
2450         s->t_attrib.bgcol = QEMU_COLOR_BLUE;
2451         msg = g_strdup_printf("%s console\r\n", chr->label);
2452         qemu_chr_write(chr, (uint8_t *)msg, strlen(msg), true);
2453         g_free(msg);
2454         s->t_attrib = s->t_attrib_default;
2455     }
2456
2457     qemu_chr_be_event(chr, CHR_EVENT_OPENED);
2458 }
2459
2460 static void vc_chr_open(Chardev *chr,
2461                         ChardevBackend *backend,
2462                         bool *be_opened,
2463                         Error **errp)
2464 {
2465     ChardevVC *vc = backend->u.vc.data;
2466     VCChardev *drv = VC_CHARDEV(chr);
2467     QemuConsole *s;
2468     unsigned width = 0;
2469     unsigned height = 0;
2470
2471     if (vc->has_width) {
2472         width = vc->width;
2473     } else if (vc->has_cols) {
2474         width = vc->cols * FONT_WIDTH;
2475     }
2476
2477     if (vc->has_height) {
2478         height = vc->height;
2479     } else if (vc->has_rows) {
2480         height = vc->rows * FONT_HEIGHT;
2481     }
2482
2483     trace_console_txt_new(width, height);
2484     if (width == 0 || height == 0) {
2485         s = new_console(NULL, TEXT_CONSOLE, 0);
2486     } else {
2487         s = new_console(NULL, TEXT_CONSOLE_FIXED_SIZE, 0);
2488         s->scanout.kind = SCANOUT_SURFACE;
2489         s->surface = qemu_create_displaysurface(width, height);
2490     }
2491
2492     if (!s) {
2493         error_setg(errp, "cannot create text console");
2494         return;
2495     }
2496
2497     s->chr = chr;
2498     drv->console = s;
2499
2500     if (display_state) {
2501         text_console_do_init(chr, display_state);
2502     }
2503
2504     /* console/chardev init sometimes completes elsewhere in a 2nd
2505      * stage, so defer OPENED events until they are fully initialized
2506      */
2507     *be_opened = false;
2508 }
2509
2510 void qemu_console_resize(QemuConsole *s, int width, int height)
2511 {
2512     DisplaySurface *surface = qemu_console_surface(s);
2513
2514     assert(s->console_type == GRAPHIC_CONSOLE);
2515
2516     if ((s->scanout.kind != SCANOUT_SURFACE ||
2517          (surface && surface->flags & QEMU_ALLOCATED_FLAG)) &&
2518         qemu_console_get_width(s, -1) == width &&
2519         qemu_console_get_height(s, -1) == height) {
2520         return;
2521     }
2522
2523     surface = qemu_create_displaysurface(width, height);
2524     dpy_gfx_replace_surface(s, surface);
2525 }
2526
2527 DisplaySurface *qemu_console_surface(QemuConsole *console)
2528 {
2529     switch (console->scanout.kind) {
2530     case SCANOUT_SURFACE:
2531         return console->surface;
2532     default:
2533         return NULL;
2534     }
2535 }
2536
2537 PixelFormat qemu_default_pixelformat(int bpp)
2538 {
2539     pixman_format_code_t fmt = qemu_default_pixman_format(bpp, true);
2540     PixelFormat pf = qemu_pixelformat_from_pixman(fmt);
2541     return pf;
2542 }
2543
2544 static QemuDisplay *dpys[DISPLAY_TYPE__MAX];
2545
2546 void qemu_display_register(QemuDisplay *ui)
2547 {
2548     assert(ui->type < DISPLAY_TYPE__MAX);
2549     dpys[ui->type] = ui;
2550 }
2551
2552 bool qemu_display_find_default(DisplayOptions *opts)
2553 {
2554     static DisplayType prio[] = {
2555 #if defined(CONFIG_GTK)
2556         DISPLAY_TYPE_GTK,
2557 #endif
2558 #if defined(CONFIG_SDL)
2559         DISPLAY_TYPE_SDL,
2560 #endif
2561 #if defined(CONFIG_COCOA)
2562         DISPLAY_TYPE_COCOA
2563 #endif
2564     };
2565     int i;
2566
2567     for (i = 0; i < (int)ARRAY_SIZE(prio); i++) {
2568         if (dpys[prio[i]] == NULL) {
2569             Error *local_err = NULL;
2570             int rv = ui_module_load(DisplayType_str(prio[i]), &local_err);
2571             if (rv < 0) {
2572                 error_report_err(local_err);
2573             }
2574         }
2575         if (dpys[prio[i]] == NULL) {
2576             continue;
2577         }
2578         opts->type = prio[i];
2579         return true;
2580     }
2581     return false;
2582 }
2583
2584 void qemu_display_early_init(DisplayOptions *opts)
2585 {
2586     assert(opts->type < DISPLAY_TYPE__MAX);
2587     if (opts->type == DISPLAY_TYPE_NONE) {
2588         return;
2589     }
2590     if (dpys[opts->type] == NULL) {
2591         Error *local_err = NULL;
2592         int rv = ui_module_load(DisplayType_str(opts->type), &local_err);
2593         if (rv < 0) {
2594             error_report_err(local_err);
2595         }
2596     }
2597     if (dpys[opts->type] == NULL) {
2598         error_report("Display '%s' is not available.",
2599                      DisplayType_str(opts->type));
2600         exit(1);
2601     }
2602     if (dpys[opts->type]->early_init) {
2603         dpys[opts->type]->early_init(opts);
2604     }
2605 }
2606
2607 void qemu_display_init(DisplayState *ds, DisplayOptions *opts)
2608 {
2609     assert(opts->type < DISPLAY_TYPE__MAX);
2610     if (opts->type == DISPLAY_TYPE_NONE) {
2611         return;
2612     }
2613     assert(dpys[opts->type] != NULL);
2614     dpys[opts->type]->init(ds, opts);
2615 }
2616
2617 void qemu_display_help(void)
2618 {
2619     int idx;
2620
2621     printf("Available display backend types:\n");
2622     printf("none\n");
2623     for (idx = DISPLAY_TYPE_NONE; idx < DISPLAY_TYPE__MAX; idx++) {
2624         if (!dpys[idx]) {
2625             Error *local_err = NULL;
2626             int rv = ui_module_load(DisplayType_str(idx), &local_err);
2627             if (rv < 0) {
2628                 error_report_err(local_err);
2629             }
2630         }
2631         if (dpys[idx]) {
2632             printf("%s\n",  DisplayType_str(dpys[idx]->type));
2633         }
2634     }
2635 }
2636
2637 void qemu_chr_parse_vc(QemuOpts *opts, ChardevBackend *backend, Error **errp)
2638 {
2639     int val;
2640     ChardevVC *vc;
2641
2642     backend->type = CHARDEV_BACKEND_KIND_VC;
2643     vc = backend->u.vc.data = g_new0(ChardevVC, 1);
2644     qemu_chr_parse_common(opts, qapi_ChardevVC_base(vc));
2645
2646     val = qemu_opt_get_number(opts, "width", 0);
2647     if (val != 0) {
2648         vc->has_width = true;
2649         vc->width = val;
2650     }
2651
2652     val = qemu_opt_get_number(opts, "height", 0);
2653     if (val != 0) {
2654         vc->has_height = true;
2655         vc->height = val;
2656     }
2657
2658     val = qemu_opt_get_number(opts, "cols", 0);
2659     if (val != 0) {
2660         vc->has_cols = true;
2661         vc->cols = val;
2662     }
2663
2664     val = qemu_opt_get_number(opts, "rows", 0);
2665     if (val != 0) {
2666         vc->has_rows = true;
2667         vc->rows = val;
2668     }
2669 }
2670
2671 static const TypeInfo qemu_console_info = {
2672     .name = TYPE_QEMU_CONSOLE,
2673     .parent = TYPE_OBJECT,
2674     .instance_size = sizeof(QemuConsole),
2675     .class_size = sizeof(QemuConsoleClass),
2676 };
2677
2678 static void char_vc_class_init(ObjectClass *oc, void *data)
2679 {
2680     ChardevClass *cc = CHARDEV_CLASS(oc);
2681
2682     cc->parse = qemu_chr_parse_vc;
2683     cc->open = vc_chr_open;
2684     cc->chr_write = vc_chr_write;
2685     cc->chr_accept_input = vc_chr_accept_input;
2686     cc->chr_set_echo = vc_chr_set_echo;
2687 }
2688
2689 static const TypeInfo char_vc_type_info = {
2690     .name = TYPE_CHARDEV_VC,
2691     .parent = TYPE_CHARDEV,
2692     .instance_size = sizeof(VCChardev),
2693     .class_init = char_vc_class_init,
2694 };
2695
2696 void qemu_console_early_init(void)
2697 {
2698     /* set the default vc driver */
2699     if (!object_class_by_name(TYPE_CHARDEV_VC)) {
2700         type_register(&char_vc_type_info);
2701     }
2702 }
2703
2704 static void register_types(void)
2705 {
2706     type_register_static(&qemu_console_info);
2707 }
2708
2709 type_init(register_types);