1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24#include "qemu-common.h"
25#include "console.h"
26#include "qemu-timer.h"
27
28
29#define DEFAULT_BACKSCROLL 512
30#define MAX_CONSOLES 12
31
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)
34
35typedef 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;
44
45typedef struct TextCell {
46 uint8_t ch;
47 TextAttributes t_attrib;
48} TextCell;
49
50#define MAX_ESC_PARAMS 3
51
52enum TTYState {
53 TTY_STATE_NORM,
54 TTY_STATE_ESC,
55 TTY_STATE_CSI,
56};
57
58typedef struct QEMUFIFO {
59 uint8_t *buf;
60 int buf_size;
61 int count, wptr, rptr;
62} QEMUFIFO;
63
64static int qemu_fifo_write(QEMUFIFO *f, const uint8_t *buf, int len1)
65{
66 int l, len;
67
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;
82 }
83 f->count += len1;
84 return len1;
85}
86
87static int qemu_fifo_read(QEMUFIFO *f, uint8_t *buf, int len1)
88{
89 int l, len;
90
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;
104 }
105 f->count -= len1;
106 return len1;
107}
108
109typedef enum {
110 GRAPHIC_CONSOLE,
111 TEXT_CONSOLE,
112 TEXT_CONSOLE_FIXED_SIZE
113} console_type_t;
114
115
116
117struct TextConsole {
118 console_type_t console_type;
119 DisplayState *ds;
120
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;
126
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;
137 TextAttributes t_attrib;
138 TextCell *cells;
139 int text_x[2], text_y[2], cursor_invalidate;
140
141 int update_x0;
142 int update_y0;
143 int update_x1;
144 int update_y1;
145
146 enum TTYState state;
147 int esc_params[MAX_ESC_PARAMS];
148 int nb_esc_params;
149
150 CharDriverState *chr;
151
152 QEMUFIFO out_fifo;
153 uint8_t out_fifo_buf[16];
154 QEMUTimer *kbd_timer;
155};
156
157static TextConsole *active_console;
158static TextConsole *consoles[MAX_CONSOLES];
159static int nb_consoles = 0;
160
161void vga_hw_update(void)
162{
163 if (active_console && active_console->hw_update)
164 active_console->hw_update(active_console->hw);
165}
166
167void vga_hw_invalidate(void)
168{
169 if (active_console->hw_invalidate)
170 active_console->hw_invalidate(active_console->hw);
171}
172
173void vga_hw_screen_dump(const char *filename)
174{
175 TextConsole *previous_active_console;
176
177 previous_active_console = active_console;
178 active_console = consoles[0];
179
180
181 if (consoles[0]->hw_screen_dump)
182 consoles[0]->hw_screen_dump(consoles[0]->hw, filename);
183 active_console = previous_active_console;
184}
185
186void vga_hw_text_update(console_ch_t *chardata)
187{
188 if (active_console && active_console->hw_text_update)
189 active_console->hw_text_update(active_console->hw, chardata);
190}
191
192
193static unsigned int vga_get_color(DisplayState *ds, unsigned int rgba)
194{
195 unsigned int r, g, b, color;
196
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;
224 }
225 return color;
226}
227
228static void vga_fill_rect (DisplayState *ds,
229 int posx, int posy, int width, int height, uint32_t color)
230{
231 uint8_t *d, *d1;
232 int x, y, bpp;
233
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++;
244 }
245 break;
246 case 2:
247 for (x = 0; x < width; x++) {
248 *((uint16_t *)d) = color;
249 d += 2;
250 }
251 break;
252 case 4:
253 for (x = 0; x < width; x++) {
254 *((uint32_t *)d) = color;
255 d += 4;
256 }
257 break;
258 }
259 d1 += ds_get_linesize(ds);
260 }
261}
262
263
264static void vga_bitblt(DisplayState *ds, int xs, int ys, int xd, int yd, int w, int h)
265{
266 const uint8_t *s;
267 uint8_t *d;
268 int wb, y, bpp;
269
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);
281 }
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);
291 }
292 }
293}
294
295
296
297
298#define FONT_HEIGHT 16
299#define FONT_WIDTH 8
300
301#include "vgafont.h"
302
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) ))
309
310#ifdef WORDS_BIGENDIAN
311#define PAT(x) x
312#else
313#define PAT(x) cbswap_32(x)
314#endif
315
316static 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),
333};
334
335static const uint32_t dmask4[4] = {
336 PAT(0x00000000),
337 PAT(0x0000ffff),
338 PAT(0xffff0000),
339 PAT(0xffffffff),
340};
341
342static uint32_t color_table[2][8];
343
344enum 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
353};
354
355static const uint32_t color_table_rgb[2][8] = {
356 {
357 QEMU_RGB(0x00, 0x00, 0x00),
358 QEMU_RGB(0xaa, 0x00, 0x00),
359 QEMU_RGB(0x00, 0xaa, 0x00),
360 QEMU_RGB(0xaa, 0xaa, 0x00),
361 QEMU_RGB(0x00, 0x00, 0xaa),
362 QEMU_RGB(0xaa, 0x00, 0xaa),
363 QEMU_RGB(0x00, 0xaa, 0xaa),
364 QEMU_RGB(0xaa, 0xaa, 0xaa),
365 },
366 {
367 QEMU_RGB(0x00, 0x00, 0x00),
368 QEMU_RGB(0xff, 0x00, 0x00),
369 QEMU_RGB(0x00, 0xff, 0x00),
370 QEMU_RGB(0xff, 0xff, 0x00),
371 QEMU_RGB(0x00, 0x00, 0xff),
372 QEMU_RGB(0xff, 0x00, 0xff),
373 QEMU_RGB(0x00, 0xff, 0xff),
374 QEMU_RGB(0xff, 0xff, 0xff),
375 }
376};
377
378static inline unsigned int col_expand(DisplayState *ds, unsigned int col)
379{
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;
391 }
392
393 return col;
394}
395#ifdef DEBUG_CONSOLE
396static void console_print_text_attributes(TextAttributes *t_attrib, char ch)
397{
398 if (t_attrib->bold) {
399 printf("b");
400 } else {
401 printf(" ");
402 }
403 if (t_attrib->uline) {
404 printf("u");
405 } else {
406 printf(" ");
407 }
408 if (t_attrib->blink) {
409 printf("l");
410 } else {
411 printf(" ");
412 }
413 if (t_attrib->invers) {
414 printf("i");
415 } else {
416 printf(" ");
417 }
418 if (t_attrib->unvisible) {
419 printf("n");
420 } else {
421 printf(" ");
422 }
423
424 printf(" fg: %d bg: %d ch:'%2X' '%c'\n", t_attrib->fgcol, t_attrib->bgcol, ch, ch);
425}
426#endif
427
428static void vga_putcharxy(DisplayState *ds, int x, int y, int ch,
429 TextAttributes *t_attrib)
430{
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;
436
437#ifdef DEBUG_CONSOLE
438 printf("x: %2i y: %2i", x, y);
439 console_print_text_attributes(t_attrib, ch);
440#endif
441
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];
448 }
449
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;
463 }
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;
467 }
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;
476 }
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;
482 }
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;
489 }
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;
499 }
500 break;
501 }
502}
503
504static void text_console_resize(TextConsole *s)
505{
506 TextCell *cells, *c, *c1;
507 int w1, x, y, last_width;
508
509 last_width = s->width;
510 s->width = s->g_width / FONT_WIDTH;
511 s->height = s->g_height / FONT_HEIGHT;
512
513 w1 = last_width;
514 if (s->width < w1)
515 w1 = s->width;
516
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++;
524 }
525 }
526 for(x = w1; x < s->width; x++) {
527 c->ch = ' ';
528 c->t_attrib = s->t_attrib_default;
529 c++;
530 }
531 }
532 qemu_free(s->cells);
533 s->cells = cells;
534}
535
536static inline void text_update_xy(TextConsole *s, int x, int y)
537{
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);
542}
543
544static void invalidate_xy(TextConsole *s, int x, int y)
545{
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;
554}
555
556static void update_xy(TextConsole *s, int x, int y)
557{
558 TextCell *c;
559 int y1, y2;
560
561 if (s == active_console) {
562 if (!ds_get_bits_per_pixel(s->ds)) {
563 text_update_xy(s, x, y);
564 return;
565 }
566
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);
576 }
577 }
578}
579
580static void console_show_cursor(TextConsole *s, int show)
581{
582 TextCell *c;
583 int y, y1;
584
585 if (s == active_console) {
586 int x = s->x;
587
588 if (!ds_get_bits_per_pixel(s->ds)) {
589 s->cursor_invalidate = 1;
590 return;
591 }
592
593 if (x >= s->width) {
594 x = s->width - 1;
595 }
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);
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));
608 }
609 invalidate_xy(s, x, y);
610 }
611 }
612}
613
614static void console_refresh(TextConsole *s)
615{
616 TextCell *c;
617 int x, y, y1;
618
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;
628 }
629
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++;
639 }
640 if (++y1 == s->total_height)
641 y1 = 0;
642 }
643 console_show_cursor(s, 1);
644 dpy_update(s->ds, 0, 0, ds_get_width(s->ds), ds_get_height(s->ds));
645}
646
647static void console_scroll(int ydelta)
648{
649 TextConsole *s;
650 int i, y1;
651
652 s = active_console;
653 if (!s || (s->console_type == GRAPHIC_CONSOLE))
654 return;
655
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;
662 }
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;
676 }
677 }
678 console_refresh(s);
679}
680
681static void console_put_lf(TextConsole *s)
682{
683 TextCell *c;
684 int x, y1;
685
686 s->y++;
687 if (s->y >= s->height) {
688 s->y = s->height - 1;
689
690 if (s->y_displayed == s->y_base) {
691 if (++s->y_displayed == s->total_height)
692 s->y_displayed = 0;
693 }
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++;
704 }
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;
712 }
713
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;
724 }
725 }
726}
727
728
729
730
731
732static void console_handle_escape(TextConsole *s)
733{
734 int i;
735
736 for (i=0; i<s->nb_esc_params; i++) {
737 switch (s->esc_params[i]) {
738 case 0:
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
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
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;
821 }
822 }
823}
824
825static void console_clear_xy(TextConsole *s, int x, int y)
826{
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);
833}
834
835static void console_putchar(TextConsole *s, int ch)
836{
837 TextCell *c;
838 int y1, i;
839 int x, y;
840
841 switch(s->state) {
842 case TTY_STATE_NORM:
843 switch(ch) {
844 case '\r':
845 s->x = 0;
846 break;
847 case '\n':
848 console_put_lf(s);
849 break;
850 case '\b':
851 if (s->x > 0)
852 s->x--;
853 break;
854 case '\t':
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));
860 }
861 break;
862 case '\a':
863
864 break;
865 case 14:
866
867 break;
868 case 15:
869
870 break;
871 case 27:
872 s->state = TTY_STATE_ESC;
873 break;
874 default:
875 if (s->x >= s->width) {
876
877 s->x = 0;
878 console_put_lf(s);
879 }
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;
887 }
888 break;
889 case TTY_STATE_ESC:
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;
897 }
898 break;
899 case TTY_STATE_CSI:
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';
904 }
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
917 if (s->esc_params[0] == 0) {
918 s->esc_params[0] = 1;
919 }
920 s->y -= s->esc_params[0];
921 if (s->y < 0) {
922 s->y = 0;
923 }
924 break;
925 case 'B':
926
927 if (s->esc_params[0] == 0) {
928 s->esc_params[0] = 1;
929 }
930 s->y += s->esc_params[0];
931 if (s->y >= s->height) {
932 s->y = s->height - 1;
933 }
934 break;
935 case 'C':
936
937 if (s->esc_params[0] == 0) {
938 s->esc_params[0] = 1;
939 }
940 s->x += s->esc_params[0];
941 if (s->x >= s->width) {
942 s->x = s->width - 1;
943 }
944 break;
945 case 'D':
946
947 if (s->esc_params[0] == 0) {
948 s->esc_params[0] = 1;
949 }
950 s->x -= s->esc_params[0];
951 if (s->x < 0) {
952 s->x = 0;
953 }
954 break;
955 case 'G':
956
957 s->x = s->esc_params[0] - 1;
958 if (s->x < 0) {
959 s->x = 0;
960 }
961 break;
962 case 'f':
963 case 'H':
964
965 s->x = s->esc_params[1] - 1;
966 if (s->x < 0) {
967 s->x = 0;
968 }
969 s->y = s->esc_params[0] - 1;
970 if (s->y < 0) {
971 s->y = 0;
972 }
973 break;
974 case 'J':
975 switch (s->esc_params[0]) {
976 case 0:
977
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;
982 }
983 console_clear_xy(s, x, y);
984 }
985 }
986 break;
987 case 1:
988
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;
993 }
994 console_clear_xy(s, x, y);
995 }
996 }
997 break;
998 case 2:
999
1000 for (y = 0; y <= s->height; y++) {
1001 for (x = 0; x < s->width; x++) {
1002 console_clear_xy(s, x, y);
1003 }
1004 }
1005 break;
1006 }
1007 case 'K':
1008 switch (s->esc_params[0]) {
1009 case 0:
1010
1011 for(x = s->x; x < s->width; x++) {
1012 console_clear_xy(s, x, s->y);
1013 }
1014 break;
1015 case 1:
1016
1017 for (x = 0; x <= s->x; x++) {
1018 console_clear_xy(s, x, s->y);
1019 }
1020 break;
1021 case 2:
1022
1023 for(x = 0; x < s->width; x++) {
1024 console_clear_xy(s, x, s->y);
1025 }
1026 break;
1027 }
1028 break;
1029 case 'm':
1030 console_handle_escape(s);
1031 break;
1032 case 'n':
1033
1034
1035 break;
1036 case 's':
1037
1038 s->x_saved = s->x;
1039 s->y_saved = s->y;
1040 break;
1041 case 'u':
1042
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;
1051 }
1052 break;
1053 }
1054 }
1055}
1056
1057void console_select(unsigned int index)
1058{
1059 TextConsole *s;
1060
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;
1074 }
1075 dpy_resize(s->ds);
1076 vga_hw_invalidate();
1077 }
1078}
1079
1080static int console_puts(CharDriverState *chr, const uint8_t *buf, int len)
1081{
1082 TextConsole *s = chr->opaque;
1083 int i;
1084
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]);
1092 }
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);
1098 }
1099 return len;
1100}
1101
1102static void console_send_event(CharDriverState *chr, int event)
1103{
1104 TextConsole *s = chr->opaque;
1105 int i;
1106
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;
1112 }
1113 }
1114 }
1115}
1116
1117static void kbd_send_chars(void *opaque)
1118{
1119 TextConsole *s = opaque;
1120 int len;
1121 uint8_t buf[16];
1122
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);
1131 }
1132
1133
1134 if (s->out_fifo.count > 0) {
1135 qemu_mod_timer(s->kbd_timer, qemu_get_clock(rt_clock) + 1);
1136 }
1137}
1138
1139
1140void kbd_put_keysym(int keysym)
1141{
1142 TextConsole *s;
1143 uint8_t buf[16], *q;
1144 int c;
1145
1146 s = active_console;
1147 if (!s || (s->console_type == GRAPHIC_CONSOLE))
1148 return;
1149
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
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;
1180 }
1181 if (s->chr->chr_read) {
1182 qemu_fifo_write(&s->out_fifo, buf, q - buf);
1183 kbd_send_chars(s);
1184 }
1185 break;
1186 }
1187}
1188
1189static void text_console_invalidate(void *opaque)
1190{
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);
1196 }
1197 console_refresh(s);
1198}
1199
1200static void text_console_update(void *opaque, console_ch_t *chardata)
1201{
1202 TextConsole *s = (TextConsole *) opaque;
1203 int i, j, src;
1204
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;
1220 }
1221 if (s->cursor_invalidate) {
1222 dpy_cursor(s->ds, s->x, s->y);
1223 s->cursor_invalidate = 0;
1224 }
1225}
1226
1227static TextConsole *get_graphic_console(DisplayState *ds)
1228{
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;
1235 }
1236 return NULL;
1237}
1238
1239static TextConsole *new_console(DisplayState *ds, console_type_t console_type)
1240{
1241 TextConsole *s;
1242 int i;
1243
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;
1250 }
1251 s->ds = ds;
1252 s->console_type = console_type;
1253 if (console_type != GRAPHIC_CONSOLE) {
1254 consoles[nb_consoles++] = s;
1255 } else {
1256
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];
1261 }
1262 consoles[i] = s;
1263 nb_consoles++;
1264 }
1265 return s;
1266}
1267
1268DisplayState *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)
1273{
1274 TextConsole *s;
1275 DisplayState *ds;
1276
1277 ds = (DisplayState *) qemu_mallocz(sizeof(DisplayState));
1278 ds->allocator = &default_allocator;
1279 ds->surface = qemu_create_displaysurface(ds, 640, 480);
1280
1281 s = new_console(ds, GRAPHIC_CONSOLE);
1282 if (s == NULL) {
1283 qemu_free_displaysurface(ds);
1284 qemu_free(ds);
1285 return NULL;
1286 }
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;
1292
1293 register_displaystate(ds);
1294 return ds;
1295}
1296
1297int is_graphic_console(void)
1298{
1299 return active_console && active_console->console_type == GRAPHIC_CONSOLE;
1300}
1301
1302int is_fixedsize_console(void)
1303{
1304 return active_console && active_console->console_type != TEXT_CONSOLE;
1305}
1306
1307void console_color_init(DisplayState *ds)
1308{
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]));
1314 }
1315 }
1316}
1317
1318static int n_text_consoles;
1319static CharDriverState *text_consoles[128];
1320static char *text_console_strs[128];
1321
1322static void text_console_do_init(CharDriverState *chr, DisplayState *ds, const char *p)
1323{
1324 TextConsole *s;
1325 unsigned width;
1326 unsigned height;
1327 static int color_inited;
1328
1329 s = new_console(ds, (p == NULL) ? TEXT_CONSOLE : TEXT_CONSOLE_FIXED_SIZE);
1330 if (!s) {
1331 free(chr);
1332 return;
1333 }
1334 chr->opaque = s;
1335 chr->chr_write = console_puts;
1336 chr->chr_send_event = console_send_event;
1337
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;
1343
1344 if (!color_inited) {
1345 color_inited = 1;
1346 console_color_init(s->ds);
1347 }
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;
1360 }
1361 if (*p == 'x') {
1362 p++;
1363 height = strtoul(p, (char **)&p, 10);
1364 if (*p == 'C') {
1365 p++;
1366 height *= FONT_HEIGHT;
1367 }
1368 }
1369 }
1370 s->g_width = width;
1371 s->g_height = height;
1372
1373 s->hw_invalidate = text_console_invalidate;
1374 s->hw_text_update = text_console_update;
1375 s->hw = s;
1376
1377
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
1386 s->t_attrib = s->t_attrib_default;
1387 text_console_resize(s);
1388
1389 qemu_chr_reset(chr);
1390 if (chr->init)
1391 chr->init(chr);
1392}
1393
1394CharDriverState *text_console_init(const char *p)
1395{
1396 CharDriverState *chr;
1397
1398 chr = qemu_mallocz(sizeof(CharDriverState));
1399
1400 if (n_text_consoles == 128) {
1401 fprintf(stderr, "Too many text consoles\n");
1402 exit(1);
1403 }
1404 text_consoles[n_text_consoles] = chr;
1405 text_console_strs[n_text_consoles] = p ? qemu_strdup(p) : NULL;
1406 n_text_consoles++;
1407
1408 return chr;
1409}
1410
1411void text_consoles_set_display(DisplayState *ds)
1412{
1413 int i;
1414
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]);
1418 }
1419
1420 n_text_consoles = 0;
1421}
1422
1423void qemu_console_resize(DisplayState *ds, int width, int height)
1424{
1425 TextConsole *s = get_graphic_console(ds);
1426 if (!s) return;
1427
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);
1433 }
1434}
1435
1436void qemu_console_copy(DisplayState *ds, int src_x, int src_y,
1437 int dst_x, int dst_y, int w, int h)
1438{
1439 if (is_graphic_console()) {
1440 dpy_copy(ds, src_x, src_y, dst_x, dst_y, w, h);
1441 }
1442}
1443
1444PixelFormat qemu_different_endianness_pixelformat(int bpp)
1445{
1446 PixelFormat pf;
1447
1448 memset(&pf, 0x00, sizeof(PixelFormat));
1449
1450 pf.bits_per_pixel = bpp;
1451 pf.bytes_per_pixel = bpp / 8;
1452 pf.depth = bpp == 32 ? 24 : bpp;
1453
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;
1489 }
1490 return pf;
1491}
1492
1493PixelFormat qemu_default_pixelformat(int bpp)
1494{
1495 PixelFormat pf;
1496
1497 memset(&pf, 0x00, sizeof(PixelFormat));
1498
1499 pf.bits_per_pixel = bpp;
1500 pf.bytes_per_pixel = bpp / 8;
1501 pf.depth = bpp == 32 ? 24 : bpp;
1502
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;
1550 }
1551 return pf;
1552}
1553
1554DisplaySurface* defaultallocator_create_displaysurface(int width, int height)
1555{
1556 DisplaySurface *surface = (DisplaySurface*) qemu_mallocz(sizeof(DisplaySurface));
1557
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);
1568
1569 return surface;
1570}
1571
1572DisplaySurface* defaultallocator_resize_displaysurface(DisplaySurface *surface,
1573 int width, int height)
1574{
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
1588
1589 return surface;
1590}
1591
1592DisplaySurface* qemu_create_displaysurface_from(int width, int height, int bpp,
1593 int linesize, uint8_t *data)
1594{
1595 DisplaySurface *surface = (DisplaySurface*) qemu_mallocz(sizeof(DisplaySurface));
1596
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;
1605
1606 return surface;
1607}
1608
1609void defaultallocator_free_displaysurface(DisplaySurface *surface)
1610{
1611 if (surface == NULL)
1612 return;
1613 if (surface->flags & QEMU_ALLOCATED_FLAG)
1614 qemu_free(surface->data);
1615 qemu_free(surface);
1616}
1617