OSDN Git Service

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