Fix warning on WIN32
[qemu-kvm/fedora.git] / console.c
blob52e3e57b8897995dd4c840dd1cd37d19891b36e1
1 /*
2 * QEMU graphical console
4 * Copyright (c) 2004 Fabrice Bellard
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:
13 * The above copyright notice and this permission notice shall be included in
14 * all copies or substantial portions of the Software.
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.
24 #include "qemu-common.h"
25 #include "console.h"
26 #include "qemu-timer.h"
28 //#define DEBUG_CONSOLE
29 #define DEFAULT_BACKSCROLL 512
30 #define MAX_CONSOLES 12
32 #define QEMU_RGBA(r, g, b, a) (((a) << 24) | ((r) << 16) | ((g) << 8) | (b))
33 #define QEMU_RGB(r, g, b) QEMU_RGBA(r, g, b, 0xff)
35 typedef struct TextAttributes {
36 uint8_t fgcol:4;
37 uint8_t bgcol:4;
38 uint8_t bold:1;
39 uint8_t uline:1;
40 uint8_t blink:1;
41 uint8_t invers:1;
42 uint8_t unvisible:1;
43 } TextAttributes;
45 typedef struct TextCell {
46 uint8_t ch;
47 TextAttributes t_attrib;
48 } TextCell;
50 #define MAX_ESC_PARAMS 3
52 enum TTYState {
53 TTY_STATE_NORM,
54 TTY_STATE_ESC,
55 TTY_STATE_CSI,
58 typedef struct QEMUFIFO {
59 uint8_t *buf;
60 int buf_size;
61 int count, wptr, rptr;
62 } QEMUFIFO;
64 static int qemu_fifo_write(QEMUFIFO *f, const uint8_t *buf, int len1)
66 int l, len;
68 l = f->buf_size - f->count;
69 if (len1 > l)
70 len1 = l;
71 len = len1;
72 while (len > 0) {
73 l = f->buf_size - f->wptr;
74 if (l > len)
75 l = len;
76 memcpy(f->buf + f->wptr, buf, l);
77 f->wptr += l;
78 if (f->wptr >= f->buf_size)
79 f->wptr = 0;
80 buf += l;
81 len -= l;
83 f->count += len1;
84 return len1;
87 static int qemu_fifo_read(QEMUFIFO *f, uint8_t *buf, int len1)
89 int l, len;
91 if (len1 > f->count)
92 len1 = f->count;
93 len = len1;
94 while (len > 0) {
95 l = f->buf_size - f->rptr;
96 if (l > len)
97 l = len;
98 memcpy(buf, f->buf + f->rptr, l);
99 f->rptr += l;
100 if (f->rptr >= f->buf_size)
101 f->rptr = 0;
102 buf += l;
103 len -= l;
105 f->count -= len1;
106 return len1;
109 typedef enum {
110 GRAPHIC_CONSOLE,
111 TEXT_CONSOLE,
112 TEXT_CONSOLE_FIXED_SIZE
113 } console_type_t;
115 /* ??? This is mis-named.
116 It is used for both text and graphical consoles. */
117 struct TextConsole {
118 console_type_t console_type;
119 DisplayState *ds;
120 /* Graphic console state. */
121 vga_hw_update_ptr hw_update;
122 vga_hw_invalidate_ptr hw_invalidate;
123 vga_hw_screen_dump_ptr hw_screen_dump;
124 vga_hw_text_update_ptr hw_text_update;
125 void *hw;
127 int g_width, g_height;
128 int width;
129 int height;
130 int total_height;
131 int backscroll_height;
132 int x, y;
133 int x_saved, y_saved;
134 int y_displayed;
135 int y_base;
136 TextAttributes t_attrib_default; /* default text attributes */
137 TextAttributes t_attrib; /* currently active text attributes */
138 TextCell *cells;
139 int text_x[2], text_y[2], cursor_invalidate;
141 int update_x0;
142 int update_y0;
143 int update_x1;
144 int update_y1;
146 enum TTYState state;
147 int esc_params[MAX_ESC_PARAMS];
148 int nb_esc_params;
150 CharDriverState *chr;
151 /* fifo for key pressed */
152 QEMUFIFO out_fifo;
153 uint8_t out_fifo_buf[16];
154 QEMUTimer *kbd_timer;
157 static TextConsole *active_console;
158 static TextConsole *consoles[MAX_CONSOLES];
159 static int nb_consoles = 0;
161 void vga_hw_update(void)
163 if (active_console && active_console->hw_update)
164 active_console->hw_update(active_console->hw);
167 void vga_hw_invalidate(void)
169 if (active_console->hw_invalidate)
170 active_console->hw_invalidate(active_console->hw);
173 void vga_hw_screen_dump(const char *filename)
175 TextConsole *previous_active_console;
177 previous_active_console = active_console;
178 active_console = consoles[0];
179 /* There is currently no way of specifying which screen we want to dump,
180 so always dump the first one. */
181 if (consoles[0]->hw_screen_dump)
182 consoles[0]->hw_screen_dump(consoles[0]->hw, filename);
183 active_console = previous_active_console;
186 void vga_hw_text_update(console_ch_t *chardata)
188 if (active_console && active_console->hw_text_update)
189 active_console->hw_text_update(active_console->hw, chardata);
192 /* convert a RGBA color to a color index usable in graphic primitives */
193 static unsigned int vga_get_color(DisplayState *ds, unsigned int rgba)
195 unsigned int r, g, b, color;
197 switch(ds_get_bits_per_pixel(ds)) {
198 #if 0
199 case 8:
200 r = (rgba >> 16) & 0xff;
201 g = (rgba >> 8) & 0xff;
202 b = (rgba) & 0xff;
203 color = (rgb_to_index[r] * 6 * 6) +
204 (rgb_to_index[g] * 6) +
205 (rgb_to_index[b]);
206 break;
207 #endif
208 case 15:
209 r = (rgba >> 16) & 0xff;
210 g = (rgba >> 8) & 0xff;
211 b = (rgba) & 0xff;
212 color = ((r >> 3) << 10) | ((g >> 3) << 5) | (b >> 3);
213 break;
214 case 16:
215 r = (rgba >> 16) & 0xff;
216 g = (rgba >> 8) & 0xff;
217 b = (rgba) & 0xff;
218 color = ((r >> 3) << 11) | ((g >> 2) << 5) | (b >> 3);
219 break;
220 case 32:
221 default:
222 color = rgba;
223 break;
225 return color;
228 static void vga_fill_rect (DisplayState *ds,
229 int posx, int posy, int width, int height, uint32_t color)
231 uint8_t *d, *d1;
232 int x, y, bpp;
234 bpp = (ds_get_bits_per_pixel(ds) + 7) >> 3;
235 d1 = ds_get_data(ds) +
236 ds_get_linesize(ds) * posy + bpp * posx;
237 for (y = 0; y < height; y++) {
238 d = d1;
239 switch(bpp) {
240 case 1:
241 for (x = 0; x < width; x++) {
242 *((uint8_t *)d) = color;
243 d++;
245 break;
246 case 2:
247 for (x = 0; x < width; x++) {
248 *((uint16_t *)d) = color;
249 d += 2;
251 break;
252 case 4:
253 for (x = 0; x < width; x++) {
254 *((uint32_t *)d) = color;
255 d += 4;
257 break;
259 d1 += ds_get_linesize(ds);
263 /* copy from (xs, ys) to (xd, yd) a rectangle of size (w, h) */
264 static void vga_bitblt(DisplayState *ds, int xs, int ys, int xd, int yd, int w, int h)
266 const uint8_t *s;
267 uint8_t *d;
268 int wb, y, bpp;
270 bpp = (ds_get_bits_per_pixel(ds) + 7) >> 3;
271 wb = w * bpp;
272 if (yd <= ys) {
273 s = ds_get_data(ds) +
274 ds_get_linesize(ds) * ys + bpp * xs;
275 d = ds_get_data(ds) +
276 ds_get_linesize(ds) * yd + bpp * xd;
277 for (y = 0; y < h; y++) {
278 memmove(d, s, wb);
279 d += ds_get_linesize(ds);
280 s += ds_get_linesize(ds);
282 } else {
283 s = ds_get_data(ds) +
284 ds_get_linesize(ds) * (ys + h - 1) + bpp * xs;
285 d = ds_get_data(ds) +
286 ds_get_linesize(ds) * (yd + h - 1) + bpp * xd;
287 for (y = 0; y < h; y++) {
288 memmove(d, s, wb);
289 d -= ds_get_linesize(ds);
290 s -= ds_get_linesize(ds);
295 /***********************************************************/
296 /* basic char display */
298 #define FONT_HEIGHT 16
299 #define FONT_WIDTH 8
301 #include "vgafont.h"
303 #define cbswap_32(__x) \
304 ((uint32_t)( \
305 (((uint32_t)(__x) & (uint32_t)0x000000ffUL) << 24) | \
306 (((uint32_t)(__x) & (uint32_t)0x0000ff00UL) << 8) | \
307 (((uint32_t)(__x) & (uint32_t)0x00ff0000UL) >> 8) | \
308 (((uint32_t)(__x) & (uint32_t)0xff000000UL) >> 24) ))
310 #ifdef WORDS_BIGENDIAN
311 #define PAT(x) x
312 #else
313 #define PAT(x) cbswap_32(x)
314 #endif
316 static const uint32_t dmask16[16] = {
317 PAT(0x00000000),
318 PAT(0x000000ff),
319 PAT(0x0000ff00),
320 PAT(0x0000ffff),
321 PAT(0x00ff0000),
322 PAT(0x00ff00ff),
323 PAT(0x00ffff00),
324 PAT(0x00ffffff),
325 PAT(0xff000000),
326 PAT(0xff0000ff),
327 PAT(0xff00ff00),
328 PAT(0xff00ffff),
329 PAT(0xffff0000),
330 PAT(0xffff00ff),
331 PAT(0xffffff00),
332 PAT(0xffffffff),
335 static const uint32_t dmask4[4] = {
336 PAT(0x00000000),
337 PAT(0x0000ffff),
338 PAT(0xffff0000),
339 PAT(0xffffffff),
342 static uint32_t color_table[2][8];
344 enum color_names {
345 COLOR_BLACK = 0,
346 COLOR_RED = 1,
347 COLOR_GREEN = 2,
348 COLOR_YELLOW = 3,
349 COLOR_BLUE = 4,
350 COLOR_MAGENTA = 5,
351 COLOR_CYAN = 6,
352 COLOR_WHITE = 7
355 static const uint32_t color_table_rgb[2][8] = {
356 { /* dark */
357 QEMU_RGB(0x00, 0x00, 0x00), /* black */
358 QEMU_RGB(0xaa, 0x00, 0x00), /* red */
359 QEMU_RGB(0x00, 0xaa, 0x00), /* green */
360 QEMU_RGB(0xaa, 0xaa, 0x00), /* yellow */
361 QEMU_RGB(0x00, 0x00, 0xaa), /* blue */
362 QEMU_RGB(0xaa, 0x00, 0xaa), /* magenta */
363 QEMU_RGB(0x00, 0xaa, 0xaa), /* cyan */
364 QEMU_RGB(0xaa, 0xaa, 0xaa), /* white */
366 { /* bright */
367 QEMU_RGB(0x00, 0x00, 0x00), /* black */
368 QEMU_RGB(0xff, 0x00, 0x00), /* red */
369 QEMU_RGB(0x00, 0xff, 0x00), /* green */
370 QEMU_RGB(0xff, 0xff, 0x00), /* yellow */
371 QEMU_RGB(0x00, 0x00, 0xff), /* blue */
372 QEMU_RGB(0xff, 0x00, 0xff), /* magenta */
373 QEMU_RGB(0x00, 0xff, 0xff), /* cyan */
374 QEMU_RGB(0xff, 0xff, 0xff), /* white */
378 static inline unsigned int col_expand(DisplayState *ds, unsigned int col)
380 switch(ds_get_bits_per_pixel(ds)) {
381 case 8:
382 col |= col << 8;
383 col |= col << 16;
384 break;
385 case 15:
386 case 16:
387 col |= col << 16;
388 break;
389 default:
390 break;
393 return col;
395 #ifdef DEBUG_CONSOLE
396 static void console_print_text_attributes(TextAttributes *t_attrib, char ch)
398 if (t_attrib->bold) {
399 printf("b");
400 } else {
401 printf(" ");
403 if (t_attrib->uline) {
404 printf("u");
405 } else {
406 printf(" ");
408 if (t_attrib->blink) {
409 printf("l");
410 } else {
411 printf(" ");
413 if (t_attrib->invers) {
414 printf("i");
415 } else {
416 printf(" ");
418 if (t_attrib->unvisible) {
419 printf("n");
420 } else {
421 printf(" ");
424 printf(" fg: %d bg: %d ch:'%2X' '%c'\n", t_attrib->fgcol, t_attrib->bgcol, ch, ch);
426 #endif
428 static void vga_putcharxy(DisplayState *ds, int x, int y, int ch,
429 TextAttributes *t_attrib)
431 uint8_t *d;
432 const uint8_t *font_ptr;
433 unsigned int font_data, linesize, xorcol, bpp;
434 int i;
435 unsigned int fgcol, bgcol;
437 #ifdef DEBUG_CONSOLE
438 printf("x: %2i y: %2i", x, y);
439 console_print_text_attributes(t_attrib, ch);
440 #endif
442 if (t_attrib->invers) {
443 bgcol = color_table[t_attrib->bold][t_attrib->fgcol];
444 fgcol = color_table[t_attrib->bold][t_attrib->bgcol];
445 } else {
446 fgcol = color_table[t_attrib->bold][t_attrib->fgcol];
447 bgcol = color_table[t_attrib->bold][t_attrib->bgcol];
450 bpp = (ds_get_bits_per_pixel(ds) + 7) >> 3;
451 d = ds_get_data(ds) +
452 ds_get_linesize(ds) * y * FONT_HEIGHT + bpp * x * FONT_WIDTH;
453 linesize = ds_get_linesize(ds);
454 font_ptr = vgafont16 + FONT_HEIGHT * ch;
455 xorcol = bgcol ^ fgcol;
456 switch(ds_get_bits_per_pixel(ds)) {
457 case 8:
458 for(i = 0; i < FONT_HEIGHT; i++) {
459 font_data = *font_ptr++;
460 if (t_attrib->uline
461 && ((i == FONT_HEIGHT - 2) || (i == FONT_HEIGHT - 3))) {
462 font_data = 0xFFFF;
464 ((uint32_t *)d)[0] = (dmask16[(font_data >> 4)] & xorcol) ^ bgcol;
465 ((uint32_t *)d)[1] = (dmask16[(font_data >> 0) & 0xf] & xorcol) ^ bgcol;
466 d += linesize;
468 break;
469 case 16:
470 case 15:
471 for(i = 0; i < FONT_HEIGHT; i++) {
472 font_data = *font_ptr++;
473 if (t_attrib->uline
474 && ((i == FONT_HEIGHT - 2) || (i == FONT_HEIGHT - 3))) {
475 font_data = 0xFFFF;
477 ((uint32_t *)d)[0] = (dmask4[(font_data >> 6)] & xorcol) ^ bgcol;
478 ((uint32_t *)d)[1] = (dmask4[(font_data >> 4) & 3] & xorcol) ^ bgcol;
479 ((uint32_t *)d)[2] = (dmask4[(font_data >> 2) & 3] & xorcol) ^ bgcol;
480 ((uint32_t *)d)[3] = (dmask4[(font_data >> 0) & 3] & xorcol) ^ bgcol;
481 d += linesize;
483 break;
484 case 32:
485 for(i = 0; i < FONT_HEIGHT; i++) {
486 font_data = *font_ptr++;
487 if (t_attrib->uline && ((i == FONT_HEIGHT - 2) || (i == FONT_HEIGHT - 3))) {
488 font_data = 0xFFFF;
490 ((uint32_t *)d)[0] = (-((font_data >> 7)) & xorcol) ^ bgcol;
491 ((uint32_t *)d)[1] = (-((font_data >> 6) & 1) & xorcol) ^ bgcol;
492 ((uint32_t *)d)[2] = (-((font_data >> 5) & 1) & xorcol) ^ bgcol;
493 ((uint32_t *)d)[3] = (-((font_data >> 4) & 1) & xorcol) ^ bgcol;
494 ((uint32_t *)d)[4] = (-((font_data >> 3) & 1) & xorcol) ^ bgcol;
495 ((uint32_t *)d)[5] = (-((font_data >> 2) & 1) & xorcol) ^ bgcol;
496 ((uint32_t *)d)[6] = (-((font_data >> 1) & 1) & xorcol) ^ bgcol;
497 ((uint32_t *)d)[7] = (-((font_data >> 0) & 1) & xorcol) ^ bgcol;
498 d += linesize;
500 break;
504 static void text_console_resize(TextConsole *s)
506 TextCell *cells, *c, *c1;
507 int w1, x, y, last_width;
509 last_width = s->width;
510 s->width = s->g_width / FONT_WIDTH;
511 s->height = s->g_height / FONT_HEIGHT;
513 w1 = last_width;
514 if (s->width < w1)
515 w1 = s->width;
517 cells = qemu_malloc(s->width * s->total_height * sizeof(TextCell));
518 for(y = 0; y < s->total_height; y++) {
519 c = &cells[y * s->width];
520 if (w1 > 0) {
521 c1 = &s->cells[y * last_width];
522 for(x = 0; x < w1; x++) {
523 *c++ = *c1++;
526 for(x = w1; x < s->width; x++) {
527 c->ch = ' ';
528 c->t_attrib = s->t_attrib_default;
529 c++;
532 qemu_free(s->cells);
533 s->cells = cells;
536 static inline void text_update_xy(TextConsole *s, int x, int y)
538 s->text_x[0] = MIN(s->text_x[0], x);
539 s->text_x[1] = MAX(s->text_x[1], x);
540 s->text_y[0] = MIN(s->text_y[0], y);
541 s->text_y[1] = MAX(s->text_y[1], y);
544 static void invalidate_xy(TextConsole *s, int x, int y)
546 if (s->update_x0 > x * FONT_WIDTH)
547 s->update_x0 = x * FONT_WIDTH;
548 if (s->update_y0 > y * FONT_HEIGHT)
549 s->update_y0 = y * FONT_HEIGHT;
550 if (s->update_x1 < (x + 1) * FONT_WIDTH)
551 s->update_x1 = (x + 1) * FONT_WIDTH;
552 if (s->update_y1 < (y + 1) * FONT_HEIGHT)
553 s->update_y1 = (y + 1) * FONT_HEIGHT;
556 static void update_xy(TextConsole *s, int x, int y)
558 TextCell *c;
559 int y1, y2;
561 if (s == active_console) {
562 if (!ds_get_bits_per_pixel(s->ds)) {
563 text_update_xy(s, x, y);
564 return;
567 y1 = (s->y_base + y) % s->total_height;
568 y2 = y1 - s->y_displayed;
569 if (y2 < 0)
570 y2 += s->total_height;
571 if (y2 < s->height) {
572 c = &s->cells[y1 * s->width + x];
573 vga_putcharxy(s->ds, x, y2, c->ch,
574 &(c->t_attrib));
575 invalidate_xy(s, x, y2);
580 static void console_show_cursor(TextConsole *s, int show)
582 TextCell *c;
583 int y, y1;
585 if (s == active_console) {
586 int x = s->x;
588 if (!ds_get_bits_per_pixel(s->ds)) {
589 s->cursor_invalidate = 1;
590 return;
593 if (x >= s->width) {
594 x = s->width - 1;
596 y1 = (s->y_base + s->y) % s->total_height;
597 y = y1 - s->y_displayed;
598 if (y < 0)
599 y += s->total_height;
600 if (y < s->height) {
601 c = &s->cells[y1 * s->width + x];
602 if (show) {
603 TextAttributes t_attrib = s->t_attrib_default;
604 t_attrib.invers = !(t_attrib.invers); /* invert fg and bg */
605 vga_putcharxy(s->ds, x, y, c->ch, &t_attrib);
606 } else {
607 vga_putcharxy(s->ds, x, y, c->ch, &(c->t_attrib));
609 invalidate_xy(s, x, y);
614 static void console_refresh(TextConsole *s)
616 TextCell *c;
617 int x, y, y1;
619 if (s != active_console)
620 return;
621 if (!ds_get_bits_per_pixel(s->ds)) {
622 s->text_x[0] = 0;
623 s->text_y[0] = 0;
624 s->text_x[1] = s->width - 1;
625 s->text_y[1] = s->height - 1;
626 s->cursor_invalidate = 1;
627 return;
630 vga_fill_rect(s->ds, 0, 0, ds_get_width(s->ds), ds_get_height(s->ds),
631 color_table[0][COLOR_BLACK]);
632 y1 = s->y_displayed;
633 for(y = 0; y < s->height; y++) {
634 c = s->cells + y1 * s->width;
635 for(x = 0; x < s->width; x++) {
636 vga_putcharxy(s->ds, x, y, c->ch,
637 &(c->t_attrib));
638 c++;
640 if (++y1 == s->total_height)
641 y1 = 0;
643 console_show_cursor(s, 1);
644 dpy_update(s->ds, 0, 0, ds_get_width(s->ds), ds_get_height(s->ds));
647 static void console_scroll(int ydelta)
649 TextConsole *s;
650 int i, y1;
652 s = active_console;
653 if (!s || (s->console_type == GRAPHIC_CONSOLE))
654 return;
656 if (ydelta > 0) {
657 for(i = 0; i < ydelta; i++) {
658 if (s->y_displayed == s->y_base)
659 break;
660 if (++s->y_displayed == s->total_height)
661 s->y_displayed = 0;
663 } else {
664 ydelta = -ydelta;
665 i = s->backscroll_height;
666 if (i > s->total_height - s->height)
667 i = s->total_height - s->height;
668 y1 = s->y_base - i;
669 if (y1 < 0)
670 y1 += s->total_height;
671 for(i = 0; i < ydelta; i++) {
672 if (s->y_displayed == y1)
673 break;
674 if (--s->y_displayed < 0)
675 s->y_displayed = s->total_height - 1;
678 console_refresh(s);
681 static void console_put_lf(TextConsole *s)
683 TextCell *c;
684 int x, y1;
686 s->y++;
687 if (s->y >= s->height) {
688 s->y = s->height - 1;
690 if (s->y_displayed == s->y_base) {
691 if (++s->y_displayed == s->total_height)
692 s->y_displayed = 0;
694 if (++s->y_base == s->total_height)
695 s->y_base = 0;
696 if (s->backscroll_height < s->total_height)
697 s->backscroll_height++;
698 y1 = (s->y_base + s->height - 1) % s->total_height;
699 c = &s->cells[y1 * s->width];
700 for(x = 0; x < s->width; x++) {
701 c->ch = ' ';
702 c->t_attrib = s->t_attrib_default;
703 c++;
705 if (s == active_console && s->y_displayed == s->y_base) {
706 if (!ds_get_bits_per_pixel(s->ds)) {
707 s->text_x[0] = 0;
708 s->text_y[0] = 0;
709 s->text_x[1] = s->width - 1;
710 s->text_y[1] = s->height - 1;
711 return;
714 vga_bitblt(s->ds, 0, FONT_HEIGHT, 0, 0,
715 s->width * FONT_WIDTH,
716 (s->height - 1) * FONT_HEIGHT);
717 vga_fill_rect(s->ds, 0, (s->height - 1) * FONT_HEIGHT,
718 s->width * FONT_WIDTH, FONT_HEIGHT,
719 color_table[0][s->t_attrib_default.bgcol]);
720 s->update_x0 = 0;
721 s->update_y0 = 0;
722 s->update_x1 = s->width * FONT_WIDTH;
723 s->update_y1 = s->height * FONT_HEIGHT;
728 /* Set console attributes depending on the current escape codes.
729 * NOTE: I know this code is not very efficient (checking every color for it
730 * self) but it is more readable and better maintainable.
732 static void console_handle_escape(TextConsole *s)
734 int i;
736 for (i=0; i<s->nb_esc_params; i++) {
737 switch (s->esc_params[i]) {
738 case 0: /* reset all console attributes to default */
739 s->t_attrib = s->t_attrib_default;
740 break;
741 case 1:
742 s->t_attrib.bold = 1;
743 break;
744 case 4:
745 s->t_attrib.uline = 1;
746 break;
747 case 5:
748 s->t_attrib.blink = 1;
749 break;
750 case 7:
751 s->t_attrib.invers = 1;
752 break;
753 case 8:
754 s->t_attrib.unvisible = 1;
755 break;
756 case 22:
757 s->t_attrib.bold = 0;
758 break;
759 case 24:
760 s->t_attrib.uline = 0;
761 break;
762 case 25:
763 s->t_attrib.blink = 0;
764 break;
765 case 27:
766 s->t_attrib.invers = 0;
767 break;
768 case 28:
769 s->t_attrib.unvisible = 0;
770 break;
771 /* set foreground color */
772 case 30:
773 s->t_attrib.fgcol=COLOR_BLACK;
774 break;
775 case 31:
776 s->t_attrib.fgcol=COLOR_RED;
777 break;
778 case 32:
779 s->t_attrib.fgcol=COLOR_GREEN;
780 break;
781 case 33:
782 s->t_attrib.fgcol=COLOR_YELLOW;
783 break;
784 case 34:
785 s->t_attrib.fgcol=COLOR_BLUE;
786 break;
787 case 35:
788 s->t_attrib.fgcol=COLOR_MAGENTA;
789 break;
790 case 36:
791 s->t_attrib.fgcol=COLOR_CYAN;
792 break;
793 case 37:
794 s->t_attrib.fgcol=COLOR_WHITE;
795 break;
796 /* set background color */
797 case 40:
798 s->t_attrib.bgcol=COLOR_BLACK;
799 break;
800 case 41:
801 s->t_attrib.bgcol=COLOR_RED;
802 break;
803 case 42:
804 s->t_attrib.bgcol=COLOR_GREEN;
805 break;
806 case 43:
807 s->t_attrib.bgcol=COLOR_YELLOW;
808 break;
809 case 44:
810 s->t_attrib.bgcol=COLOR_BLUE;
811 break;
812 case 45:
813 s->t_attrib.bgcol=COLOR_MAGENTA;
814 break;
815 case 46:
816 s->t_attrib.bgcol=COLOR_CYAN;
817 break;
818 case 47:
819 s->t_attrib.bgcol=COLOR_WHITE;
820 break;
825 static void console_clear_xy(TextConsole *s, int x, int y)
827 int y1 = (s->y_base + y) % s->total_height;
828 TextCell *c = &s->cells[y1 * s->width + x];
829 c->ch = ' ';
830 c->t_attrib = s->t_attrib_default;
831 c++;
832 update_xy(s, x, y);
835 static void console_putchar(TextConsole *s, int ch)
837 TextCell *c;
838 int y1, i;
839 int x, y;
841 switch(s->state) {
842 case TTY_STATE_NORM:
843 switch(ch) {
844 case '\r': /* carriage return */
845 s->x = 0;
846 break;
847 case '\n': /* newline */
848 console_put_lf(s);
849 break;
850 case '\b': /* backspace */
851 if (s->x > 0)
852 s->x--;
853 break;
854 case '\t': /* tabspace */
855 if (s->x + (8 - (s->x % 8)) > s->width) {
856 s->x = 0;
857 console_put_lf(s);
858 } else {
859 s->x = s->x + (8 - (s->x % 8));
861 break;
862 case '\a': /* alert aka. bell */
863 /* TODO: has to be implemented */
864 break;
865 case 14:
866 /* SI (shift in), character set 0 (ignored) */
867 break;
868 case 15:
869 /* SO (shift out), character set 1 (ignored) */
870 break;
871 case 27: /* esc (introducing an escape sequence) */
872 s->state = TTY_STATE_ESC;
873 break;
874 default:
875 if (s->x >= s->width) {
876 /* line wrap */
877 s->x = 0;
878 console_put_lf(s);
880 y1 = (s->y_base + s->y) % s->total_height;
881 c = &s->cells[y1 * s->width + s->x];
882 c->ch = ch;
883 c->t_attrib = s->t_attrib;
884 update_xy(s, s->x, s->y);
885 s->x++;
886 break;
888 break;
889 case TTY_STATE_ESC: /* check if it is a terminal escape sequence */
890 if (ch == '[') {
891 for(i=0;i<MAX_ESC_PARAMS;i++)
892 s->esc_params[i] = 0;
893 s->nb_esc_params = 0;
894 s->state = TTY_STATE_CSI;
895 } else {
896 s->state = TTY_STATE_NORM;
898 break;
899 case TTY_STATE_CSI: /* handle escape sequence parameters */
900 if (ch >= '0' && ch <= '9') {
901 if (s->nb_esc_params < MAX_ESC_PARAMS) {
902 s->esc_params[s->nb_esc_params] =
903 s->esc_params[s->nb_esc_params] * 10 + ch - '0';
905 } else {
906 s->nb_esc_params++;
907 if (ch == ';')
908 break;
909 #ifdef DEBUG_CONSOLE
910 fprintf(stderr, "escape sequence CSI%d;%d%c, %d parameters\n",
911 s->esc_params[0], s->esc_params[1], ch, s->nb_esc_params);
912 #endif
913 s->state = TTY_STATE_NORM;
914 switch(ch) {
915 case 'A':
916 /* move cursor up */
917 if (s->esc_params[0] == 0) {
918 s->esc_params[0] = 1;
920 s->y -= s->esc_params[0];
921 if (s->y < 0) {
922 s->y = 0;
924 break;
925 case 'B':
926 /* move cursor down */
927 if (s->esc_params[0] == 0) {
928 s->esc_params[0] = 1;
930 s->y += s->esc_params[0];
931 if (s->y >= s->height) {
932 s->y = s->height - 1;
934 break;
935 case 'C':
936 /* move cursor right */
937 if (s->esc_params[0] == 0) {
938 s->esc_params[0] = 1;
940 s->x += s->esc_params[0];
941 if (s->x >= s->width) {
942 s->x = s->width - 1;
944 break;
945 case 'D':
946 /* move cursor left */
947 if (s->esc_params[0] == 0) {
948 s->esc_params[0] = 1;
950 s->x -= s->esc_params[0];
951 if (s->x < 0) {
952 s->x = 0;
954 break;
955 case 'G':
956 /* move cursor to column */
957 s->x = s->esc_params[0] - 1;
958 if (s->x < 0) {
959 s->x = 0;
961 break;
962 case 'f':
963 case 'H':
964 /* move cursor to row, column */
965 s->x = s->esc_params[1] - 1;
966 if (s->x < 0) {
967 s->x = 0;
969 s->y = s->esc_params[0] - 1;
970 if (s->y < 0) {
971 s->y = 0;
973 break;
974 case 'J':
975 switch (s->esc_params[0]) {
976 case 0:
977 /* clear to end of screen */
978 for (y = s->y; y < s->height; y++) {
979 for (x = 0; x < s->width; x++) {
980 if (y == s->y && x < s->x) {
981 continue;
983 console_clear_xy(s, x, y);
986 break;
987 case 1:
988 /* clear from beginning of screen */
989 for (y = 0; y <= s->y; y++) {
990 for (x = 0; x < s->width; x++) {
991 if (y == s->y && x > s->x) {
992 break;
994 console_clear_xy(s, x, y);
997 break;
998 case 2:
999 /* clear entire screen */
1000 for (y = 0; y <= s->height; y++) {
1001 for (x = 0; x < s->width; x++) {
1002 console_clear_xy(s, x, y);
1005 break;
1007 case 'K':
1008 switch (s->esc_params[0]) {
1009 case 0:
1010 /* clear to eol */
1011 for(x = s->x; x < s->width; x++) {
1012 console_clear_xy(s, x, s->y);
1014 break;
1015 case 1:
1016 /* clear from beginning of line */
1017 for (x = 0; x <= s->x; x++) {
1018 console_clear_xy(s, x, s->y);
1020 break;
1021 case 2:
1022 /* clear entire line */
1023 for(x = 0; x < s->width; x++) {
1024 console_clear_xy(s, x, s->y);
1026 break;
1028 break;
1029 case 'm':
1030 console_handle_escape(s);
1031 break;
1032 case 'n':
1033 /* report cursor position */
1034 /* TODO: send ESC[row;colR */
1035 break;
1036 case 's':
1037 /* save cursor position */
1038 s->x_saved = s->x;
1039 s->y_saved = s->y;
1040 break;
1041 case 'u':
1042 /* restore cursor position */
1043 s->x = s->x_saved;
1044 s->y = s->y_saved;
1045 break;
1046 default:
1047 #ifdef DEBUG_CONSOLE
1048 fprintf(stderr, "unhandled escape character '%c'\n", ch);
1049 #endif
1050 break;
1052 break;
1057 void console_select(unsigned int index)
1059 TextConsole *s;
1061 if (index >= MAX_CONSOLES)
1062 return;
1063 active_console->g_width = ds_get_width(active_console->ds);
1064 active_console->g_height = ds_get_height(active_console->ds);
1065 s = consoles[index];
1066 if (s) {
1067 DisplayState *ds = s->ds;
1068 active_console = s;
1069 if (ds_get_bits_per_pixel(s->ds)) {
1070 ds->surface = qemu_resize_displaysurface(ds, s->g_width, s->g_height);
1071 } else {
1072 s->ds->surface->width = s->width;
1073 s->ds->surface->height = s->height;
1075 dpy_resize(s->ds);
1076 vga_hw_invalidate();
1080 static int console_puts(CharDriverState *chr, const uint8_t *buf, int len)
1082 TextConsole *s = chr->opaque;
1083 int i;
1085 s->update_x0 = s->width * FONT_WIDTH;
1086 s->update_y0 = s->height * FONT_HEIGHT;
1087 s->update_x1 = 0;
1088 s->update_y1 = 0;
1089 console_show_cursor(s, 0);
1090 for(i = 0; i < len; i++) {
1091 console_putchar(s, buf[i]);
1093 console_show_cursor(s, 1);
1094 if (ds_get_bits_per_pixel(s->ds) && s->update_x0 < s->update_x1) {
1095 dpy_update(s->ds, s->update_x0, s->update_y0,
1096 s->update_x1 - s->update_x0,
1097 s->update_y1 - s->update_y0);
1099 return len;
1102 static void console_send_event(CharDriverState *chr, int event)
1104 TextConsole *s = chr->opaque;
1105 int i;
1107 if (event == CHR_EVENT_FOCUS) {
1108 for(i = 0; i < nb_consoles; i++) {
1109 if (consoles[i] == s) {
1110 console_select(i);
1111 break;
1117 static void kbd_send_chars(void *opaque)
1119 TextConsole *s = opaque;
1120 int len;
1121 uint8_t buf[16];
1123 len = qemu_chr_can_read(s->chr);
1124 if (len > s->out_fifo.count)
1125 len = s->out_fifo.count;
1126 if (len > 0) {
1127 if (len > sizeof(buf))
1128 len = sizeof(buf);
1129 qemu_fifo_read(&s->out_fifo, buf, len);
1130 qemu_chr_read(s->chr, buf, len);
1132 /* characters are pending: we send them a bit later (XXX:
1133 horrible, should change char device API) */
1134 if (s->out_fifo.count > 0) {
1135 qemu_mod_timer(s->kbd_timer, qemu_get_clock(rt_clock) + 1);
1139 /* called when an ascii key is pressed */
1140 void kbd_put_keysym(int keysym)
1142 TextConsole *s;
1143 uint8_t buf[16], *q;
1144 int c;
1146 s = active_console;
1147 if (!s || (s->console_type == GRAPHIC_CONSOLE))
1148 return;
1150 switch(keysym) {
1151 case QEMU_KEY_CTRL_UP:
1152 console_scroll(-1);
1153 break;
1154 case QEMU_KEY_CTRL_DOWN:
1155 console_scroll(1);
1156 break;
1157 case QEMU_KEY_CTRL_PAGEUP:
1158 console_scroll(-10);
1159 break;
1160 case QEMU_KEY_CTRL_PAGEDOWN:
1161 console_scroll(10);
1162 break;
1163 default:
1164 /* convert the QEMU keysym to VT100 key string */
1165 q = buf;
1166 if (keysym >= 0xe100 && keysym <= 0xe11f) {
1167 *q++ = '\033';
1168 *q++ = '[';
1169 c = keysym - 0xe100;
1170 if (c >= 10)
1171 *q++ = '0' + (c / 10);
1172 *q++ = '0' + (c % 10);
1173 *q++ = '~';
1174 } else if (keysym >= 0xe120 && keysym <= 0xe17f) {
1175 *q++ = '\033';
1176 *q++ = '[';
1177 *q++ = keysym & 0xff;
1178 } else {
1179 *q++ = keysym;
1181 if (s->chr->chr_read) {
1182 qemu_fifo_write(&s->out_fifo, buf, q - buf);
1183 kbd_send_chars(s);
1185 break;
1189 static void text_console_invalidate(void *opaque)
1191 TextConsole *s = (TextConsole *) opaque;
1192 if (!ds_get_bits_per_pixel(s->ds) && s->console_type == TEXT_CONSOLE) {
1193 s->g_width = ds_get_width(s->ds);
1194 s->g_height = ds_get_height(s->ds);
1195 text_console_resize(s);
1197 console_refresh(s);
1200 static void text_console_update(void *opaque, console_ch_t *chardata)
1202 TextConsole *s = (TextConsole *) opaque;
1203 int i, j, src;
1205 if (s->text_x[0] <= s->text_x[1]) {
1206 src = (s->y_base + s->text_y[0]) * s->width;
1207 chardata += s->text_y[0] * s->width;
1208 for (i = s->text_y[0]; i <= s->text_y[1]; i ++)
1209 for (j = 0; j < s->width; j ++, src ++)
1210 console_write_ch(chardata ++, s->cells[src].ch |
1211 (s->cells[src].t_attrib.fgcol << 12) |
1212 (s->cells[src].t_attrib.bgcol << 8) |
1213 (s->cells[src].t_attrib.bold << 21));
1214 dpy_update(s->ds, s->text_x[0], s->text_y[0],
1215 s->text_x[1] - s->text_x[0], i - s->text_y[0]);
1216 s->text_x[0] = s->width;
1217 s->text_y[0] = s->height;
1218 s->text_x[1] = 0;
1219 s->text_y[1] = 0;
1221 if (s->cursor_invalidate) {
1222 dpy_cursor(s->ds, s->x, s->y);
1223 s->cursor_invalidate = 0;
1227 static TextConsole *get_graphic_console(DisplayState *ds)
1229 int i;
1230 TextConsole *s;
1231 for (i = 0; i < nb_consoles; i++) {
1232 s = consoles[i];
1233 if (s->console_type == GRAPHIC_CONSOLE && s->ds == ds)
1234 return s;
1236 return NULL;
1239 static TextConsole *new_console(DisplayState *ds, console_type_t console_type)
1241 TextConsole *s;
1242 int i;
1244 if (nb_consoles >= MAX_CONSOLES)
1245 return NULL;
1246 s = qemu_mallocz(sizeof(TextConsole));
1247 if (!active_console || ((active_console->console_type != GRAPHIC_CONSOLE) &&
1248 (console_type == GRAPHIC_CONSOLE))) {
1249 active_console = s;
1251 s->ds = ds;
1252 s->console_type = console_type;
1253 if (console_type != GRAPHIC_CONSOLE) {
1254 consoles[nb_consoles++] = s;
1255 } else {
1256 /* HACK: Put graphical consoles before text consoles. */
1257 for (i = nb_consoles; i > 0; i--) {
1258 if (consoles[i - 1]->console_type == GRAPHIC_CONSOLE)
1259 break;
1260 consoles[i] = consoles[i - 1];
1262 consoles[i] = s;
1263 nb_consoles++;
1265 return s;
1268 DisplayState *graphic_console_init(vga_hw_update_ptr update,
1269 vga_hw_invalidate_ptr invalidate,
1270 vga_hw_screen_dump_ptr screen_dump,
1271 vga_hw_text_update_ptr text_update,
1272 void *opaque)
1274 TextConsole *s;
1275 DisplayState *ds;
1277 ds = (DisplayState *) qemu_mallocz(sizeof(DisplayState));
1278 ds->allocator = &default_allocator;
1279 ds->surface = qemu_create_displaysurface(ds, 640, 480);
1281 s = new_console(ds, GRAPHIC_CONSOLE);
1282 if (s == NULL) {
1283 qemu_free_displaysurface(ds);
1284 qemu_free(ds);
1285 return NULL;
1287 s->hw_update = update;
1288 s->hw_invalidate = invalidate;
1289 s->hw_screen_dump = screen_dump;
1290 s->hw_text_update = text_update;
1291 s->hw = opaque;
1293 register_displaystate(ds);
1294 return ds;
1297 int is_graphic_console(void)
1299 return active_console && active_console->console_type == GRAPHIC_CONSOLE;
1302 int is_fixedsize_console(void)
1304 return active_console && active_console->console_type != TEXT_CONSOLE;
1307 void console_color_init(DisplayState *ds)
1309 int i, j;
1310 for (j = 0; j < 2; j++) {
1311 for (i = 0; i < 8; i++) {
1312 color_table[j][i] = col_expand(ds,
1313 vga_get_color(ds, color_table_rgb[j][i]));
1318 static int n_text_consoles;
1319 static CharDriverState *text_consoles[128];
1320 static char *text_console_strs[128];
1322 static void text_console_do_init(CharDriverState *chr, DisplayState *ds, const char *p)
1324 TextConsole *s;
1325 unsigned width;
1326 unsigned height;
1327 static int color_inited;
1329 s = new_console(ds, (p == NULL) ? TEXT_CONSOLE : TEXT_CONSOLE_FIXED_SIZE);
1330 if (!s) {
1331 free(chr);
1332 return;
1334 chr->opaque = s;
1335 chr->chr_write = console_puts;
1336 chr->chr_send_event = console_send_event;
1338 s->chr = chr;
1339 s->out_fifo.buf = s->out_fifo_buf;
1340 s->out_fifo.buf_size = sizeof(s->out_fifo_buf);
1341 s->kbd_timer = qemu_new_timer(rt_clock, kbd_send_chars, s);
1342 s->ds = ds;
1344 if (!color_inited) {
1345 color_inited = 1;
1346 console_color_init(s->ds);
1348 s->y_displayed = 0;
1349 s->y_base = 0;
1350 s->total_height = DEFAULT_BACKSCROLL;
1351 s->x = 0;
1352 s->y = 0;
1353 width = ds_get_width(s->ds);
1354 height = ds_get_height(s->ds);
1355 if (p != NULL) {
1356 width = strtoul(p, (char **)&p, 10);
1357 if (*p == 'C') {
1358 p++;
1359 width *= FONT_WIDTH;
1361 if (*p == 'x') {
1362 p++;
1363 height = strtoul(p, (char **)&p, 10);
1364 if (*p == 'C') {
1365 p++;
1366 height *= FONT_HEIGHT;
1370 s->g_width = width;
1371 s->g_height = height;
1373 s->hw_invalidate = text_console_invalidate;
1374 s->hw_text_update = text_console_update;
1375 s->hw = s;
1377 /* Set text attribute defaults */
1378 s->t_attrib_default.bold = 0;
1379 s->t_attrib_default.uline = 0;
1380 s->t_attrib_default.blink = 0;
1381 s->t_attrib_default.invers = 0;
1382 s->t_attrib_default.unvisible = 0;
1383 s->t_attrib_default.fgcol = COLOR_WHITE;
1384 s->t_attrib_default.bgcol = COLOR_BLACK;
1385 /* set current text attributes to default */
1386 s->t_attrib = s->t_attrib_default;
1387 text_console_resize(s);
1389 qemu_chr_reset(chr);
1390 if (chr->init)
1391 chr->init(chr);
1394 CharDriverState *text_console_init(const char *p)
1396 CharDriverState *chr;
1398 chr = qemu_mallocz(sizeof(CharDriverState));
1400 if (n_text_consoles == 128) {
1401 fprintf(stderr, "Too many text consoles\n");
1402 exit(1);
1404 text_consoles[n_text_consoles] = chr;
1405 text_console_strs[n_text_consoles] = p ? qemu_strdup(p) : NULL;
1406 n_text_consoles++;
1408 return chr;
1411 void text_consoles_set_display(DisplayState *ds)
1413 int i;
1415 for (i = 0; i < n_text_consoles; i++) {
1416 text_console_do_init(text_consoles[i], ds, text_console_strs[i]);
1417 qemu_free(text_console_strs[i]);
1420 n_text_consoles = 0;
1423 void qemu_console_resize(DisplayState *ds, int width, int height)
1425 TextConsole *s = get_graphic_console(ds);
1426 if (!s) return;
1428 s->g_width = width;
1429 s->g_height = height;
1430 if (is_graphic_console()) {
1431 ds->surface = qemu_resize_displaysurface(ds, width, height);
1432 dpy_resize(ds);
1436 void qemu_console_copy(DisplayState *ds, int src_x, int src_y,
1437 int dst_x, int dst_y, int w, int h)
1439 if (is_graphic_console()) {
1440 dpy_copy(ds, src_x, src_y, dst_x, dst_y, w, h);
1444 PixelFormat qemu_different_endianness_pixelformat(int bpp)
1446 PixelFormat pf;
1448 memset(&pf, 0x00, sizeof(PixelFormat));
1450 pf.bits_per_pixel = bpp;
1451 pf.bytes_per_pixel = bpp / 8;
1452 pf.depth = bpp == 32 ? 24 : bpp;
1454 switch (bpp) {
1455 case 24:
1456 pf.rmask = 0x000000FF;
1457 pf.gmask = 0x0000FF00;
1458 pf.bmask = 0x00FF0000;
1459 pf.rmax = 255;
1460 pf.gmax = 255;
1461 pf.bmax = 255;
1462 pf.rshift = 0;
1463 pf.gshift = 8;
1464 pf.bshift = 16;
1465 pf.rbits = 8;
1466 pf.gbits = 8;
1467 pf.bbits = 8;
1468 break;
1469 case 32:
1470 pf.rmask = 0x0000FF00;
1471 pf.gmask = 0x00FF0000;
1472 pf.bmask = 0xFF000000;
1473 pf.amask = 0x00000000;
1474 pf.amax = 255;
1475 pf.rmax = 255;
1476 pf.gmax = 255;
1477 pf.bmax = 255;
1478 pf.ashift = 0;
1479 pf.rshift = 8;
1480 pf.gshift = 16;
1481 pf.bshift = 24;
1482 pf.rbits = 8;
1483 pf.gbits = 8;
1484 pf.bbits = 8;
1485 pf.abits = 8;
1486 break;
1487 default:
1488 break;
1490 return pf;
1493 PixelFormat qemu_default_pixelformat(int bpp)
1495 PixelFormat pf;
1497 memset(&pf, 0x00, sizeof(PixelFormat));
1499 pf.bits_per_pixel = bpp;
1500 pf.bytes_per_pixel = bpp / 8;
1501 pf.depth = bpp == 32 ? 24 : bpp;
1503 switch (bpp) {
1504 case 16:
1505 pf.rmask = 0x0000F800;
1506 pf.gmask = 0x000007E0;
1507 pf.bmask = 0x0000001F;
1508 pf.rmax = 31;
1509 pf.gmax = 63;
1510 pf.bmax = 31;
1511 pf.rshift = 11;
1512 pf.gshift = 5;
1513 pf.bshift = 0;
1514 pf.rbits = 5;
1515 pf.gbits = 6;
1516 pf.bbits = 5;
1517 break;
1518 case 24:
1519 pf.rmask = 0x00FF0000;
1520 pf.gmask = 0x0000FF00;
1521 pf.bmask = 0x000000FF;
1522 pf.rmax = 255;
1523 pf.gmax = 255;
1524 pf.bmax = 255;
1525 pf.rshift = 16;
1526 pf.gshift = 8;
1527 pf.bshift = 0;
1528 pf.rbits = 8;
1529 pf.gbits = 8;
1530 pf.bbits = 8;
1531 case 32:
1532 pf.rmask = 0x00FF0000;
1533 pf.gmask = 0x0000FF00;
1534 pf.bmask = 0x000000FF;
1535 pf.amax = 255;
1536 pf.rmax = 255;
1537 pf.gmax = 255;
1538 pf.bmax = 255;
1539 pf.ashift = 24;
1540 pf.rshift = 16;
1541 pf.gshift = 8;
1542 pf.bshift = 0;
1543 pf.rbits = 8;
1544 pf.gbits = 8;
1545 pf.bbits = 8;
1546 pf.abits = 8;
1547 break;
1548 default:
1549 break;
1551 return pf;
1554 DisplaySurface* defaultallocator_create_displaysurface(int width, int height)
1556 DisplaySurface *surface = (DisplaySurface*) qemu_mallocz(sizeof(DisplaySurface));
1558 surface->width = width;
1559 surface->height = height;
1560 surface->linesize = width * 4;
1561 surface->pf = qemu_default_pixelformat(32);
1562 #ifdef WORDS_BIGENDIAN
1563 surface->flags = QEMU_ALLOCATED_FLAG | QEMU_BIG_ENDIAN_FLAG;
1564 #else
1565 surface->flags = QEMU_ALLOCATED_FLAG;
1566 #endif
1567 surface->data = (uint8_t*) qemu_mallocz(surface->linesize * surface->height);
1569 return surface;
1572 DisplaySurface* defaultallocator_resize_displaysurface(DisplaySurface *surface,
1573 int width, int height)
1575 surface->width = width;
1576 surface->height = height;
1577 surface->linesize = width * 4;
1578 surface->pf = qemu_default_pixelformat(32);
1579 if (surface->flags & QEMU_ALLOCATED_FLAG)
1580 surface->data = (uint8_t*) qemu_realloc(surface->data, surface->linesize * surface->height);
1581 else
1582 surface->data = (uint8_t*) qemu_malloc(surface->linesize * surface->height);
1583 #ifdef WORDS_BIGENDIAN
1584 surface->flags = QEMU_ALLOCATED_FLAG | QEMU_BIG_ENDIAN_FLAG;
1585 #else
1586 surface->flags = QEMU_ALLOCATED_FLAG;
1587 #endif
1589 return surface;
1592 DisplaySurface* qemu_create_displaysurface_from(int width, int height, int bpp,
1593 int linesize, uint8_t *data)
1595 DisplaySurface *surface = (DisplaySurface*) qemu_mallocz(sizeof(DisplaySurface));
1597 surface->width = width;
1598 surface->height = height;
1599 surface->linesize = linesize;
1600 surface->pf = qemu_default_pixelformat(bpp);
1601 #ifdef WORDS_BIGENDIAN
1602 surface->flags = QEMU_BIG_ENDIAN_FLAG;
1603 #endif
1604 surface->data = data;
1606 return surface;
1609 void defaultallocator_free_displaysurface(DisplaySurface *surface)
1611 if (surface == NULL)
1612 return;
1613 if (surface->flags & QEMU_ALLOCATED_FLAG)
1614 qemu_free(surface->data);
1615 qemu_free(surface);