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#define DEFAULT_MONITOR_SIZE "800x600"
32
33#define QEMU_RGBA(r, g, b, a) (((a) << 24) | ((r) << 16) | ((g) << 8) | (b))
34#define QEMU_RGB(r, g, b) QEMU_RGBA(r, g, b, 0xff)
35
36typedef struct TextAttributes {
37 uint8_t fgcol:4;
38 uint8_t bgcol:4;
39 uint8_t bold:1;
40 uint8_t uline:1;
41 uint8_t blink:1;
42 uint8_t invers:1;
43 uint8_t unvisible:1;
44} TextAttributes;
45
46typedef struct TextCell {
47 uint8_t ch;
48 TextAttributes t_attrib;
49} TextCell;
50
51#define MAX_ESC_PARAMS 3
52
53enum TTYState {
54 TTY_STATE_NORM,
55 TTY_STATE_ESC,
56 TTY_STATE_CSI,
57};
58
59typedef struct QEMUFIFO {
60 uint8_t *buf;
61 int buf_size;
62 int count, wptr, rptr;
63} QEMUFIFO;
64
65static int qemu_fifo_write(QEMUFIFO *f, const uint8_t *buf, int len1)
66{
67 int l, len;
68
69 l = f->buf_size - f->count;
70 if (len1 > l)
71 len1 = l;
72 len = len1;
73 while (len > 0) {
74 l = f->buf_size - f->wptr;
75 if (l > len)
76 l = len;
77 memcpy(f->buf + f->wptr, buf, l);
78 f->wptr += l;
79 if (f->wptr >= f->buf_size)
80 f->wptr = 0;
81 buf += l;
82 len -= l;
83 }
84 f->count += len1;
85 return len1;
86}
87
88static int qemu_fifo_read(QEMUFIFO *f, uint8_t *buf, int len1)
89{
90 int l, len;
91
92 if (len1 > f->count)
93 len1 = f->count;
94 len = len1;
95 while (len > 0) {
96 l = f->buf_size - f->rptr;
97 if (l > len)
98 l = len;
99 memcpy(buf, f->buf + f->rptr, l);
100 f->rptr += l;
101 if (f->rptr >= f->buf_size)
102 f->rptr = 0;
103 buf += l;
104 len -= l;
105 }
106 f->count -= len1;
107 return len1;
108}
109
110typedef enum {
111 GRAPHIC_CONSOLE,
112 TEXT_CONSOLE,
113 TEXT_CONSOLE_FIXED_SIZE
114} console_type_t;
115
116
117
118struct TextConsole {
119 console_type_t console_type;
120 DisplayState *ds;
121
122 vga_hw_update_ptr hw_update;
123 vga_hw_invalidate_ptr hw_invalidate;
124 vga_hw_screen_dump_ptr hw_screen_dump;
125 vga_hw_text_update_ptr hw_text_update;
126 void *hw;
127
128 int g_width, g_height;
129 int width;
130 int height;
131 int total_height;
132 int backscroll_height;
133 int x, y;
134 int x_saved, y_saved;
135 int y_displayed;
136 int y_base;
137 TextAttributes t_attrib_default;
138 TextAttributes t_attrib;
139 TextCell *cells;
140 int text_x[2], text_y[2], cursor_invalidate;
141
142 int update_x0;
143 int update_y0;
144 int update_x1;
145 int update_y1;
146
147 enum TTYState state;
148 int esc_params[MAX_ESC_PARAMS];
149 int nb_esc_params;
150
151 CharDriverState *chr;
152
153 QEMUFIFO out_fifo;
154 uint8_t out_fifo_buf[16];
155 QEMUTimer *kbd_timer;
156};
157
158static TextConsole *active_console;
159static TextConsole *consoles[MAX_CONSOLES];
160static int nb_consoles = 0;
161
162void vga_hw_update(void)
163{
164 if (active_console && active_console->hw_update)
165 active_console->hw_update(active_console->hw);
166}
167
168void vga_hw_invalidate(void)
169{
170 if (active_console->hw_invalidate)
171 active_console->hw_invalidate(active_console->hw);
172}
173
174void vga_hw_screen_dump(const char *filename)
175{
176 TextConsole *previous_active_console;
177
178 previous_active_console = active_console;
179 active_console = consoles[0];
180
181
182 if (consoles[0]->hw_screen_dump)
183 consoles[0]->hw_screen_dump(consoles[0]->hw, filename);
184 active_console = previous_active_console;
185}
186
187void vga_hw_text_update(console_ch_t *chardata)
188{
189 if (active_console && active_console->hw_text_update)
190 active_console->hw_text_update(active_console->hw, chardata);
191}
192
193
194static unsigned int vga_get_color(DisplayState *ds, unsigned int rgba)
195{
196 unsigned int r, g, b, color;
197
198 switch(ds_get_bits_per_pixel(ds)) {
199#if 0
200 case 8:
201 r = (rgba >> 16) & 0xff;
202 g = (rgba >> 8) & 0xff;
203 b = (rgba) & 0xff;
204 color = (rgb_to_index[r] * 6 * 6) +
205 (rgb_to_index[g] * 6) +
206 (rgb_to_index[b]);
207 break;
208#endif
209 case 15:
210 r = (rgba >> 16) & 0xff;
211 g = (rgba >> 8) & 0xff;
212 b = (rgba) & 0xff;
213 color = ((r >> 3) << 10) | ((g >> 3) << 5) | (b >> 3);
214 break;
215 case 16:
216 r = (rgba >> 16) & 0xff;
217 g = (rgba >> 8) & 0xff;
218 b = (rgba) & 0xff;
219 color = ((r >> 3) << 11) | ((g >> 2) << 5) | (b >> 3);
220 break;
221 case 32:
222 default:
223 color = rgba;
224 break;
225 }
226 return color;
227}
228
229static void vga_fill_rect (DisplayState *ds,
230 int posx, int posy, int width, int height, uint32_t color)
231{
232 uint8_t *d, *d1;
233 int x, y, bpp;
234
235 bpp = (ds_get_bits_per_pixel(ds) + 7) >> 3;
236 d1 = ds_get_data(ds) +
237 ds_get_linesize(ds) * posy + bpp * posx;
238 for (y = 0; y < height; y++) {
239 d = d1;
240 switch(bpp) {
241 case 1:
242 for (x = 0; x < width; x++) {
243 *((uint8_t *)d) = color;
244 d++;
245 }
246 break;
247 case 2:
248 for (x = 0; x < width; x++) {
249 *((uint16_t *)d) = color;
250 d += 2;
251 }
252 break;
253 case 4:
254 for (x = 0; x < width; x++) {
255 *((uint32_t *)d) = color;
256 d += 4;
257 }
258 break;
259 }
260 d1 += ds_get_linesize(ds);
261 }
262}
263
264
265static void vga_bitblt(DisplayState *ds, int xs, int ys, int xd, int yd, int w, int h)
266{
267 const uint8_t *s;
268 uint8_t *d;
269 int wb, y, bpp;
270
271 bpp = (ds_get_bits_per_pixel(ds) + 7) >> 3;
272 wb = w * bpp;
273 if (yd <= ys) {
274 s = ds_get_data(ds) +
275 ds_get_linesize(ds) * ys + bpp * xs;
276 d = ds_get_data(ds) +
277 ds_get_linesize(ds) * yd + bpp * xd;
278 for (y = 0; y < h; y++) {
279 memmove(d, s, wb);
280 d += ds_get_linesize(ds);
281 s += ds_get_linesize(ds);
282 }
283 } else {
284 s = ds_get_data(ds) +
285 ds_get_linesize(ds) * (ys + h - 1) + bpp * xs;
286 d = ds_get_data(ds) +
287 ds_get_linesize(ds) * (yd + h - 1) + bpp * xd;
288 for (y = 0; y < h; y++) {
289 memmove(d, s, wb);
290 d -= ds_get_linesize(ds);
291 s -= ds_get_linesize(ds);
292 }
293 }
294}
295
296
297
298
299#define FONT_HEIGHT 16
300#define FONT_WIDTH 8
301
302#include "vgafont.h"
303
304#define cbswap_32(__x) \
305((uint32_t)( \
306 (((uint32_t)(__x) & (uint32_t)0x000000ffUL) << 24) | \
307 (((uint32_t)(__x) & (uint32_t)0x0000ff00UL) << 8) | \
308 (((uint32_t)(__x) & (uint32_t)0x00ff0000UL) >> 8) | \
309 (((uint32_t)(__x) & (uint32_t)0xff000000UL) >> 24) ))
310
311#ifdef WORDS_BIGENDIAN
312#define PAT(x) x
313#else
314#define PAT(x) cbswap_32(x)
315#endif
316
317static const uint32_t dmask16[16] = {
318 PAT(0x00000000),
319 PAT(0x000000ff),
320 PAT(0x0000ff00),
321 PAT(0x0000ffff),
322 PAT(0x00ff0000),
323 PAT(0x00ff00ff),
324 PAT(0x00ffff00),
325 PAT(0x00ffffff),
326 PAT(0xff000000),
327 PAT(0xff0000ff),
328 PAT(0xff00ff00),
329 PAT(0xff00ffff),
330 PAT(0xffff0000),
331 PAT(0xffff00ff),
332 PAT(0xffffff00),
333 PAT(0xffffffff),
334};
335
336static const uint32_t dmask4[4] = {
337 PAT(0x00000000),
338 PAT(0x0000ffff),
339 PAT(0xffff0000),
340 PAT(0xffffffff),
341};
342
343static uint32_t color_table[2][8];
344
345enum color_names {
346 COLOR_BLACK = 0,
347 COLOR_RED = 1,
348 COLOR_GREEN = 2,
349 COLOR_YELLOW = 3,
350 COLOR_BLUE = 4,
351 COLOR_MAGENTA = 5,
352 COLOR_CYAN = 6,
353 COLOR_WHITE = 7
354};
355
356static const uint32_t color_table_rgb[2][8] = {
357 {
358 QEMU_RGB(0x00, 0x00, 0x00),
359 QEMU_RGB(0xaa, 0x00, 0x00),
360 QEMU_RGB(0x00, 0xaa, 0x00),
361 QEMU_RGB(0xaa, 0xaa, 0x00),
362 QEMU_RGB(0x00, 0x00, 0xaa),
363 QEMU_RGB(0xaa, 0x00, 0xaa),
364 QEMU_RGB(0x00, 0xaa, 0xaa),
365 QEMU_RGB(0xaa, 0xaa, 0xaa),
366 },
367 {
368 QEMU_RGB(0x00, 0x00, 0x00),
369 QEMU_RGB(0xff, 0x00, 0x00),
370 QEMU_RGB(0x00, 0xff, 0x00),
371 QEMU_RGB(0xff, 0xff, 0x00),
372 QEMU_RGB(0x00, 0x00, 0xff),
373 QEMU_RGB(0xff, 0x00, 0xff),
374 QEMU_RGB(0x00, 0xff, 0xff),
375 QEMU_RGB(0xff, 0xff, 0xff),
376 }
377};
378
379static inline unsigned int col_expand(DisplayState *ds, unsigned int col)
380{
381 switch(ds_get_bits_per_pixel(ds)) {
382 case 8:
383 col |= col << 8;
384 col |= col << 16;
385 break;
386 case 15:
387 case 16:
388 col |= col << 16;
389 break;
390 default:
391 break;
392 }
393
394 return col;
395}
396#ifdef DEBUG_CONSOLE
397static void console_print_text_attributes(TextAttributes *t_attrib, char ch)
398{
399 if (t_attrib->bold) {
400 printf("b");
401 } else {
402 printf(" ");
403 }
404 if (t_attrib->uline) {
405 printf("u");
406 } else {
407 printf(" ");
408 }
409 if (t_attrib->blink) {
410 printf("l");
411 } else {
412 printf(" ");
413 }
414 if (t_attrib->invers) {
415 printf("i");
416 } else {
417 printf(" ");
418 }
419 if (t_attrib->unvisible) {
420 printf("n");
421 } else {
422 printf(" ");
423 }
424
425 printf(" fg: %d bg: %d ch:'%2X' '%c'\n", t_attrib->fgcol, t_attrib->bgcol, ch, ch);
426}
427#endif
428
429static void vga_putcharxy(DisplayState *ds, int x, int y, int ch,
430 TextAttributes *t_attrib)
431{
432 uint8_t *d;
433 const uint8_t *font_ptr;
434 unsigned int font_data, linesize, xorcol, bpp;
435 int i;
436 unsigned int fgcol, bgcol;
437
438#ifdef DEBUG_CONSOLE
439 printf("x: %2i y: %2i", x, y);
440 console_print_text_attributes(t_attrib, ch);
441#endif
442
443 if (t_attrib->invers) {
444 bgcol = color_table[t_attrib->bold][t_attrib->fgcol];
445 fgcol = color_table[t_attrib->bold][t_attrib->bgcol];
446 } else {
447 fgcol = color_table[t_attrib->bold][t_attrib->fgcol];
448 bgcol = color_table[t_attrib->bold][t_attrib->bgcol];
449 }
450
451 bpp = (ds_get_bits_per_pixel(ds) + 7) >> 3;
452 d = ds_get_data(ds) +
453 ds_get_linesize(ds) * y * FONT_HEIGHT + bpp * x * FONT_WIDTH;
454 linesize = ds_get_linesize(ds);
455 font_ptr = vgafont16 + FONT_HEIGHT * ch;
456 xorcol = bgcol ^ fgcol;
457 switch(ds_get_bits_per_pixel(ds)) {
458 case 8:
459 for(i = 0; i < FONT_HEIGHT; i++) {
460 font_data = *font_ptr++;
461 if (t_attrib->uline
462 && ((i == FONT_HEIGHT - 2) || (i == FONT_HEIGHT - 3))) {
463 font_data = 0xFFFF;
464 }
465 ((uint32_t *)d)[0] = (dmask16[(font_data >> 4)] & xorcol) ^ bgcol;
466 ((uint32_t *)d)[1] = (dmask16[(font_data >> 0) & 0xf] & xorcol) ^ bgcol;
467 d += linesize;
468 }
469 break;
470 case 16:
471 case 15:
472 for(i = 0; i < FONT_HEIGHT; i++) {
473 font_data = *font_ptr++;
474 if (t_attrib->uline
475 && ((i == FONT_HEIGHT - 2) || (i == FONT_HEIGHT - 3))) {
476 font_data = 0xFFFF;
477 }
478 ((uint32_t *)d)[0] = (dmask4[(font_data >> 6)] & xorcol) ^ bgcol;
479 ((uint32_t *)d)[1] = (dmask4[(font_data >> 4) & 3] & xorcol) ^ bgcol;
480 ((uint32_t *)d)[2] = (dmask4[(font_data >> 2) & 3] & xorcol) ^ bgcol;
481 ((uint32_t *)d)[3] = (dmask4[(font_data >> 0) & 3] & xorcol) ^ bgcol;
482 d += linesize;
483 }
484 break;
485 case 32:
486 for(i = 0; i < FONT_HEIGHT; i++) {
487 font_data = *font_ptr++;
488 if (t_attrib->uline && ((i == FONT_HEIGHT - 2) || (i == FONT_HEIGHT - 3))) {
489 font_data = 0xFFFF;
490 }
491 ((uint32_t *)d)[0] = (-((font_data >> 7)) & xorcol) ^ bgcol;
492 ((uint32_t *)d)[1] = (-((font_data >> 6) & 1) & xorcol) ^ bgcol;
493 ((uint32_t *)d)[2] = (-((font_data >> 5) & 1) & xorcol) ^ bgcol;
494 ((uint32_t *)d)[3] = (-((font_data >> 4) & 1) & xorcol) ^ bgcol;
495 ((uint32_t *)d)[4] = (-((font_data >> 3) & 1) & xorcol) ^ bgcol;
496 ((uint32_t *)d)[5] = (-((font_data >> 2) & 1) & xorcol) ^ bgcol;
497 ((uint32_t *)d)[6] = (-((font_data >> 1) & 1) & xorcol) ^ bgcol;
498 ((uint32_t *)d)[7] = (-((font_data >> 0) & 1) & xorcol) ^ bgcol;
499 d += linesize;
500 }
501 break;
502 }
503}
504
505static void text_console_resize(TextConsole *s)
506{
507 TextCell *cells, *c, *c1;
508 int w1, x, y, last_width;
509
510 last_width = s->width;
511 s->width = s->g_width / FONT_WIDTH;
512 s->height = s->g_height / FONT_HEIGHT;
513
514 w1 = last_width;
515 if (s->width < w1)
516 w1 = s->width;
517
518 cells = qemu_malloc(s->width * s->total_height * sizeof(TextCell));
519 for(y = 0; y < s->total_height; y++) {
520 c = &cells[y * s->width];
521 if (w1 > 0) {
522 c1 = &s->cells[y * last_width];
523 for(x = 0; x < w1; x++) {
524 *c++ = *c1++;
525 }
526 }
527 for(x = w1; x < s->width; x++) {
528 c->ch = ' ';
529 c->t_attrib = s->t_attrib_default;
530 c++;
531 }
532 }
533 qemu_free(s->cells);
534 s->cells = cells;
535}
536
537static inline void text_update_xy(TextConsole *s, int x, int y)
538{
539 s->text_x[0] = MIN(s->text_x[0], x);
540 s->text_x[1] = MAX(s->text_x[1], x);
541 s->text_y[0] = MIN(s->text_y[0], y);
542 s->text_y[1] = MAX(s->text_y[1], y);
543}
544
545static void invalidate_xy(TextConsole *s, int x, int y)
546{
547 if (s->update_x0 > x * FONT_WIDTH)
548 s->update_x0 = x * FONT_WIDTH;
549 if (s->update_y0 > y * FONT_HEIGHT)
550 s->update_y0 = y * FONT_HEIGHT;
551 if (s->update_x1 < (x + 1) * FONT_WIDTH)
552 s->update_x1 = (x + 1) * FONT_WIDTH;
553 if (s->update_y1 < (y + 1) * FONT_HEIGHT)
554 s->update_y1 = (y + 1) * FONT_HEIGHT;
555}
556
557static void update_xy(TextConsole *s, int x, int y)
558{
559 TextCell *c;
560 int y1, y2;
561
562 if (s == active_console) {
563 if (!ds_get_bits_per_pixel(s->ds)) {
564 text_update_xy(s, x, y);
565 return;
566 }
567
568 y1 = (s->y_base + y) % s->total_height;
569 y2 = y1 - s->y_displayed;
570 if (y2 < 0)
571 y2 += s->total_height;
572 if (y2 < s->height) {
573 c = &s->cells[y1 * s->width + x];
574 vga_putcharxy(s->ds, x, y2, c->ch,
575 &(c->t_attrib));
576 invalidate_xy(s, x, y2);
577 }
578 }
579}
580
581static void console_show_cursor(TextConsole *s, int show)
582{
583 TextCell *c;
584 int y, y1;
585
586 if (s == active_console) {
587 int x = s->x;
588
589 if (!ds_get_bits_per_pixel(s->ds)) {
590 s->cursor_invalidate = 1;
591 return;
592 }
593
594 if (x >= s->width) {
595 x = s->width - 1;
596 }
597 y1 = (s->y_base + s->y) % s->total_height;
598 y = y1 - s->y_displayed;
599 if (y < 0)
600 y += s->total_height;
601 if (y < s->height) {
602 c = &s->cells[y1 * s->width + x];
603 if (show) {
604 TextAttributes t_attrib = s->t_attrib_default;
605 t_attrib.invers = !(t_attrib.invers);
606 vga_putcharxy(s->ds, x, y, c->ch, &t_attrib);
607 } else {
608 vga_putcharxy(s->ds, x, y, c->ch, &(c->t_attrib));
609 }
610 invalidate_xy(s, x, y);
611 }
612 }
613}
614
615static void console_refresh(TextConsole *s)
616{
617 TextCell *c;
618 int x, y, y1;
619
620 if (s != active_console)
621 return;
622 if (!ds_get_bits_per_pixel(s->ds)) {
623 s->text_x[0] = 0;
624 s->text_y[0] = 0;
625 s->text_x[1] = s->width - 1;
626 s->text_y[1] = s->height - 1;
627 s->cursor_invalidate = 1;
628 return;
629 }
630
631 vga_fill_rect(s->ds, 0, 0, ds_get_width(s->ds), ds_get_height(s->ds),
632 color_table[0][COLOR_BLACK]);
633 y1 = s->y_displayed;
634 for(y = 0; y < s->height; y++) {
635 c = s->cells + y1 * s->width;
636 for(x = 0; x < s->width; x++) {
637 vga_putcharxy(s->ds, x, y, c->ch,
638 &(c->t_attrib));
639 c++;
640 }
641 if (++y1 == s->total_height)
642 y1 = 0;
643 }
644 console_show_cursor(s, 1);
645 dpy_update(s->ds, 0, 0, ds_get_width(s->ds), ds_get_height(s->ds));
646}
647
648static void console_scroll(int ydelta)
649{
650 TextConsole *s;
651 int i, y1;
652
653 s = active_console;
654 if (!s || (s->console_type == GRAPHIC_CONSOLE))
655 return;
656
657 if (ydelta > 0) {
658 for(i = 0; i < ydelta; i++) {
659 if (s->y_displayed == s->y_base)
660 break;
661 if (++s->y_displayed == s->total_height)
662 s->y_displayed = 0;
663 }
664 } else {
665 ydelta = -ydelta;
666 i = s->backscroll_height;
667 if (i > s->total_height - s->height)
668 i = s->total_height - s->height;
669 y1 = s->y_base - i;
670 if (y1 < 0)
671 y1 += s->total_height;
672 for(i = 0; i < ydelta; i++) {
673 if (s->y_displayed == y1)
674 break;
675 if (--s->y_displayed < 0)
676 s->y_displayed = s->total_height - 1;
677 }
678 }
679 console_refresh(s);
680}
681
682static void console_put_lf(TextConsole *s)
683{
684 TextCell *c;
685 int x, y1;
686
687 s->y++;
688 if (s->y >= s->height) {
689 s->y = s->height - 1;
690
691 if (s->y_displayed == s->y_base) {
692 if (++s->y_displayed == s->total_height)
693 s->y_displayed = 0;
694 }
695 if (++s->y_base == s->total_height)
696 s->y_base = 0;
697 if (s->backscroll_height < s->total_height)
698 s->backscroll_height++;
699 y1 = (s->y_base + s->height - 1) % s->total_height;
700 c = &s->cells[y1 * s->width];
701 for(x = 0; x < s->width; x++) {
702 c->ch = ' ';
703 c->t_attrib = s->t_attrib_default;
704 c++;
705 }
706 if (s == active_console && s->y_displayed == s->y_base) {
707 if (!ds_get_bits_per_pixel(s->ds)) {
708 s->text_x[0] = 0;
709 s->text_y[0] = 0;
710 s->text_x[1] = s->width - 1;
711 s->text_y[1] = s->height - 1;
712 return;
713 }
714
715 vga_bitblt(s->ds, 0, FONT_HEIGHT, 0, 0,
716 s->width * FONT_WIDTH,
717 (s->height - 1) * FONT_HEIGHT);
718 vga_fill_rect(s->ds, 0, (s->height - 1) * FONT_HEIGHT,
719 s->width * FONT_WIDTH, FONT_HEIGHT,
720 color_table[0][s->t_attrib_default.bgcol]);
721 s->update_x0 = 0;
722 s->update_y0 = 0;
723 s->update_x1 = s->width * FONT_WIDTH;
724 s->update_y1 = s->height * FONT_HEIGHT;
725 }
726 }
727}
728
729
730
731
732
733static void console_handle_escape(TextConsole *s)
734{
735 int i;
736
737 for (i=0; i<s->nb_esc_params; i++) {
738 switch (s->esc_params[i]) {
739 case 0:
740 s->t_attrib = s->t_attrib_default;
741 break;
742 case 1:
743 s->t_attrib.bold = 1;
744 break;
745 case 4:
746 s->t_attrib.uline = 1;
747 break;
748 case 5:
749 s->t_attrib.blink = 1;
750 break;
751 case 7:
752 s->t_attrib.invers = 1;
753 break;
754 case 8:
755 s->t_attrib.unvisible = 1;
756 break;
757 case 22:
758 s->t_attrib.bold = 0;
759 break;
760 case 24:
761 s->t_attrib.uline = 0;
762 break;
763 case 25:
764 s->t_attrib.blink = 0;
765 break;
766 case 27:
767 s->t_attrib.invers = 0;
768 break;
769 case 28:
770 s->t_attrib.unvisible = 0;
771 break;
772
773 case 30:
774 s->t_attrib.fgcol=COLOR_BLACK;
775 break;
776 case 31:
777 s->t_attrib.fgcol=COLOR_RED;
778 break;
779 case 32:
780 s->t_attrib.fgcol=COLOR_GREEN;
781 break;
782 case 33:
783 s->t_attrib.fgcol=COLOR_YELLOW;
784 break;
785 case 34:
786 s->t_attrib.fgcol=COLOR_BLUE;
787 break;
788 case 35:
789 s->t_attrib.fgcol=COLOR_MAGENTA;
790 break;
791 case 36:
792 s->t_attrib.fgcol=COLOR_CYAN;
793 break;
794 case 37:
795 s->t_attrib.fgcol=COLOR_WHITE;
796 break;
797
798 case 40:
799 s->t_attrib.bgcol=COLOR_BLACK;
800 break;
801 case 41:
802 s->t_attrib.bgcol=COLOR_RED;
803 break;
804 case 42:
805 s->t_attrib.bgcol=COLOR_GREEN;
806 break;
807 case 43:
808 s->t_attrib.bgcol=COLOR_YELLOW;
809 break;
810 case 44:
811 s->t_attrib.bgcol=COLOR_BLUE;
812 break;
813 case 45:
814 s->t_attrib.bgcol=COLOR_MAGENTA;
815 break;
816 case 46:
817 s->t_attrib.bgcol=COLOR_CYAN;
818 break;
819 case 47:
820 s->t_attrib.bgcol=COLOR_WHITE;
821 break;
822 }
823 }
824}
825
826static void console_clear_xy(TextConsole *s, int x, int y)
827{
828 int y1 = (s->y_base + y) % s->total_height;
829 TextCell *c = &s->cells[y1 * s->width + x];
830 c->ch = ' ';
831 c->t_attrib = s->t_attrib_default;
832 c++;
833 update_xy(s, x, y);
834}
835
836static void console_putchar(TextConsole *s, int ch)
837{
838 TextCell *c;
839 int y1, i;
840 int x, y;
841
842 switch(s->state) {
843 case TTY_STATE_NORM:
844 switch(ch) {
845 case '\r':
846 s->x = 0;
847 break;
848 case '\n':
849 console_put_lf(s);
850 break;
851 case '\b':
852 if (s->x > 0)
853 s->x--;
854 break;
855 case '\t':
856 if (s->x + (8 - (s->x % 8)) > s->width) {
857 s->x = 0;
858 console_put_lf(s);
859 } else {
860 s->x = s->x + (8 - (s->x % 8));
861 }
862 break;
863 case '\a':
864
865 break;
866 case 14:
867
868 break;
869 case 15:
870
871 break;
872 case 27:
873 s->state = TTY_STATE_ESC;
874 break;
875 default:
876 if (s->x >= s->width) {
877
878 s->x = 0;
879 console_put_lf(s);
880 }
881 y1 = (s->y_base + s->y) % s->total_height;
882 c = &s->cells[y1 * s->width + s->x];
883 c->ch = ch;
884 c->t_attrib = s->t_attrib;
885 update_xy(s, s->x, s->y);
886 s->x++;
887 break;
888 }
889 break;
890 case TTY_STATE_ESC:
891 if (ch == '[') {
892 for(i=0;i<MAX_ESC_PARAMS;i++)
893 s->esc_params[i] = 0;
894 s->nb_esc_params = 0;
895 s->state = TTY_STATE_CSI;
896 } else {
897 s->state = TTY_STATE_NORM;
898 }
899 break;
900 case TTY_STATE_CSI:
901 if (ch >= '0' && ch <= '9') {
902 if (s->nb_esc_params < MAX_ESC_PARAMS) {
903 s->esc_params[s->nb_esc_params] =
904 s->esc_params[s->nb_esc_params] * 10 + ch - '0';
905 }
906 } else {
907 s->nb_esc_params++;
908 if (ch == ';')
909 break;
910#ifdef DEBUG_CONSOLE
911 fprintf(stderr, "escape sequence CSI%d;%d%c, %d parameters\n",
912 s->esc_params[0], s->esc_params[1], ch, s->nb_esc_params);
913#endif
914 s->state = TTY_STATE_NORM;
915 switch(ch) {
916 case 'A':
917
918 if (s->esc_params[0] == 0) {
919 s->esc_params[0] = 1;
920 }
921 s->y -= s->esc_params[0];
922 if (s->y < 0) {
923 s->y = 0;
924 }
925 break;
926 case 'B':
927
928 if (s->esc_params[0] == 0) {
929 s->esc_params[0] = 1;
930 }
931 s->y += s->esc_params[0];
932 if (s->y >= s->height) {
933 s->y = s->height - 1;
934 }
935 break;
936 case 'C':
937
938 if (s->esc_params[0] == 0) {
939 s->esc_params[0] = 1;
940 }
941 s->x += s->esc_params[0];
942 if (s->x >= s->width) {
943 s->x = s->width - 1;
944 }
945 break;
946 case 'D':
947
948 if (s->esc_params[0] == 0) {
949 s->esc_params[0] = 1;
950 }
951 s->x -= s->esc_params[0];
952 if (s->x < 0) {
953 s->x = 0;
954 }
955 break;
956 case 'G':
957
958 s->x = s->esc_params[0] - 1;
959 if (s->x < 0) {
960 s->x = 0;
961 }
962 break;
963 case 'f':
964 case 'H':
965
966 s->x = s->esc_params[1] - 1;
967 if (s->x < 0) {
968 s->x = 0;
969 }
970 s->y = s->esc_params[0] - 1;
971 if (s->y < 0) {
972 s->y = 0;
973 }
974 break;
975 case 'J':
976 switch (s->esc_params[0]) {
977 case 0:
978
979 for (y = s->y; y < s->height; y++) {
980 for (x = 0; x < s->width; x++) {
981 if (y == s->y && x < s->x) {
982 continue;
983 }
984 console_clear_xy(s, x, y);
985 }
986 }
987 break;
988 case 1:
989
990 for (y = 0; y <= s->y; y++) {
991 for (x = 0; x < s->width; x++) {
992 if (y == s->y && x > s->x) {
993 break;
994 }
995 console_clear_xy(s, x, y);
996 }
997 }
998 break;
999 case 2:
1000
1001 for (y = 0; y <= s->height; y++) {
1002 for (x = 0; x < s->width; x++) {
1003 console_clear_xy(s, x, y);
1004 }
1005 }
1006 break;
1007 }
1008 case 'K':
1009 switch (s->esc_params[0]) {
1010 case 0:
1011
1012 for(x = s->x; x < s->width; x++) {
1013 console_clear_xy(s, x, s->y);
1014 }
1015 break;
1016 case 1:
1017
1018 for (x = 0; x <= s->x; x++) {
1019 console_clear_xy(s, x, s->y);
1020 }
1021 break;
1022 case 2:
1023
1024 for(x = 0; x < s->width; x++) {
1025 console_clear_xy(s, x, s->y);
1026 }
1027 break;
1028 }
1029 break;
1030 case 'm':
1031 console_handle_escape(s);
1032 break;
1033 case 'n':
1034
1035
1036 break;
1037 case 's':
1038
1039 s->x_saved = s->x;
1040 s->y_saved = s->y;
1041 break;
1042 case 'u':
1043
1044 s->x = s->x_saved;
1045 s->y = s->y_saved;
1046 break;
1047 default:
1048#ifdef DEBUG_CONSOLE
1049 fprintf(stderr, "unhandled escape character '%c'\n", ch);
1050#endif
1051 break;
1052 }
1053 break;
1054 }
1055 }
1056}
1057
1058void console_select(unsigned int index)
1059{
1060 TextConsole *s;
1061
1062 if (index >= MAX_CONSOLES)
1063 return;
1064 active_console->g_width = ds_get_width(active_console->ds);
1065 active_console->g_height = ds_get_height(active_console->ds);
1066 s = consoles[index];
1067 if (s) {
1068 DisplayState *ds = s->ds;
1069 active_console = s;
1070 if (ds_get_bits_per_pixel(s->ds)) {
1071 ds->surface = qemu_resize_displaysurface(ds->surface, s->g_width,
1072 s->g_height, 32, 4 * s->g_width);
1073 } else {
1074 s->ds->surface->width = s->width;
1075 s->ds->surface->height = s->height;
1076 }
1077 dpy_resize(s->ds);
1078 vga_hw_invalidate();
1079 }
1080}
1081
1082static int console_puts(CharDriverState *chr, const uint8_t *buf, int len)
1083{
1084 TextConsole *s = chr->opaque;
1085 int i;
1086
1087 s->update_x0 = s->width * FONT_WIDTH;
1088 s->update_y0 = s->height * FONT_HEIGHT;
1089 s->update_x1 = 0;
1090 s->update_y1 = 0;
1091 console_show_cursor(s, 0);
1092 for(i = 0; i < len; i++) {
1093 console_putchar(s, buf[i]);
1094 }
1095 console_show_cursor(s, 1);
1096 if (ds_get_bits_per_pixel(s->ds) && s->update_x0 < s->update_x1) {
1097 dpy_update(s->ds, s->update_x0, s->update_y0,
1098 s->update_x1 - s->update_x0,
1099 s->update_y1 - s->update_y0);
1100 }
1101 return len;
1102}
1103
1104static void console_send_event(CharDriverState *chr, int event)
1105{
1106 TextConsole *s = chr->opaque;
1107 int i;
1108
1109 if (event == CHR_EVENT_FOCUS) {
1110 for(i = 0; i < nb_consoles; i++) {
1111 if (consoles[i] == s) {
1112 console_select(i);
1113 break;
1114 }
1115 }
1116 }
1117}
1118
1119static void kbd_send_chars(void *opaque)
1120{
1121 TextConsole *s = opaque;
1122 int len;
1123 uint8_t buf[16];
1124
1125 len = qemu_chr_can_read(s->chr);
1126 if (len > s->out_fifo.count)
1127 len = s->out_fifo.count;
1128 if (len > 0) {
1129 if (len > sizeof(buf))
1130 len = sizeof(buf);
1131 qemu_fifo_read(&s->out_fifo, buf, len);
1132 qemu_chr_read(s->chr, buf, len);
1133 }
1134
1135
1136 if (s->out_fifo.count > 0) {
1137 qemu_mod_timer(s->kbd_timer, qemu_get_clock(rt_clock) + 1);
1138 }
1139}
1140
1141
1142void kbd_put_keysym(int keysym)
1143{
1144 TextConsole *s;
1145 uint8_t buf[16], *q;
1146 int c;
1147
1148 s = active_console;
1149 if (!s || (s->console_type == GRAPHIC_CONSOLE))
1150 return;
1151
1152 switch(keysym) {
1153 case QEMU_KEY_CTRL_UP:
1154 console_scroll(-1);
1155 break;
1156 case QEMU_KEY_CTRL_DOWN:
1157 console_scroll(1);
1158 break;
1159 case QEMU_KEY_CTRL_PAGEUP:
1160 console_scroll(-10);
1161 break;
1162 case QEMU_KEY_CTRL_PAGEDOWN:
1163 console_scroll(10);
1164 break;
1165 default:
1166
1167 q = buf;
1168 if (keysym >= 0xe100 && keysym <= 0xe11f) {
1169 *q++ = '\033';
1170 *q++ = '[';
1171 c = keysym - 0xe100;
1172 if (c >= 10)
1173 *q++ = '0' + (c / 10);
1174 *q++ = '0' + (c % 10);
1175 *q++ = '~';
1176 } else if (keysym >= 0xe120 && keysym <= 0xe17f) {
1177 *q++ = '\033';
1178 *q++ = '[';
1179 *q++ = keysym & 0xff;
1180 } else {
1181 *q++ = keysym;
1182 }
1183 if (s->chr->chr_read) {
1184 qemu_fifo_write(&s->out_fifo, buf, q - buf);
1185 kbd_send_chars(s);
1186 }
1187 break;
1188 }
1189}
1190
1191static void text_console_invalidate(void *opaque)
1192{
1193 TextConsole *s = (TextConsole *) opaque;
1194 if (!ds_get_bits_per_pixel(s->ds) && s->console_type == TEXT_CONSOLE) {
1195 s->g_width = ds_get_width(s->ds);
1196 s->g_height = ds_get_height(s->ds);
1197 text_console_resize(s);
1198 }
1199 console_refresh(s);
1200}
1201
1202static void text_console_update(void *opaque, console_ch_t *chardata)
1203{
1204 TextConsole *s = (TextConsole *) opaque;
1205 int i, j, src;
1206
1207 if (s->text_x[0] <= s->text_x[1]) {
1208 src = (s->y_base + s->text_y[0]) * s->width;
1209 chardata += s->text_y[0] * s->width;
1210 for (i = s->text_y[0]; i <= s->text_y[1]; i ++)
1211 for (j = 0; j < s->width; j ++, src ++)
1212 console_write_ch(chardata ++, s->cells[src].ch |
1213 (s->cells[src].t_attrib.fgcol << 12) |
1214 (s->cells[src].t_attrib.bgcol << 8) |
1215 (s->cells[src].t_attrib.bold << 21));
1216 dpy_update(s->ds, s->text_x[0], s->text_y[0],
1217 s->text_x[1] - s->text_x[0], i - s->text_y[0]);
1218 s->text_x[0] = s->width;
1219 s->text_y[0] = s->height;
1220 s->text_x[1] = 0;
1221 s->text_y[1] = 0;
1222 }
1223 if (s->cursor_invalidate) {
1224 dpy_cursor(s->ds, s->x, s->y);
1225 s->cursor_invalidate = 0;
1226 }
1227}
1228
1229static TextConsole *get_graphic_console(DisplayState *ds)
1230{
1231 int i;
1232 TextConsole *s;
1233 for (i = 0; i < nb_consoles; i++) {
1234 s = consoles[i];
1235 if (s->console_type == GRAPHIC_CONSOLE && s->ds == ds)
1236 return s;
1237 }
1238 return NULL;
1239}
1240
1241static TextConsole *new_console(DisplayState *ds, console_type_t console_type)
1242{
1243 TextConsole *s;
1244 int i;
1245
1246 if (nb_consoles >= MAX_CONSOLES)
1247 return NULL;
1248 s = qemu_mallocz(sizeof(TextConsole));
1249 if (!active_console || ((active_console->console_type != GRAPHIC_CONSOLE) &&
1250 (console_type == GRAPHIC_CONSOLE))) {
1251 active_console = s;
1252 }
1253 s->ds = ds;
1254 s->console_type = console_type;
1255 if (console_type != GRAPHIC_CONSOLE) {
1256 consoles[nb_consoles++] = s;
1257 } else {
1258
1259 for (i = nb_consoles; i > 0; i--) {
1260 if (consoles[i - 1]->console_type == GRAPHIC_CONSOLE)
1261 break;
1262 consoles[i] = consoles[i - 1];
1263 }
1264 consoles[i] = s;
1265 nb_consoles++;
1266 }
1267 return s;
1268}
1269
1270DisplayState *graphic_console_init(vga_hw_update_ptr update,
1271 vga_hw_invalidate_ptr invalidate,
1272 vga_hw_screen_dump_ptr screen_dump,
1273 vga_hw_text_update_ptr text_update,
1274 void *opaque)
1275{
1276 TextConsole *s;
1277 DisplayState *ds;
1278
1279 ds = (DisplayState *) qemu_mallocz(sizeof(DisplayState));
1280 ds->surface = qemu_create_displaysurface(640, 480, 32, 640 * 4);
1281
1282 s = new_console(ds, GRAPHIC_CONSOLE);
1283 if (s == NULL) {
1284 qemu_free_displaysurface(ds->surface);
1285 qemu_free(ds);
1286 return NULL;
1287 }
1288 s->hw_update = update;
1289 s->hw_invalidate = invalidate;
1290 s->hw_screen_dump = screen_dump;
1291 s->hw_text_update = text_update;
1292 s->hw = opaque;
1293
1294 register_displaystate(ds);
1295 return ds;
1296}
1297
1298int is_graphic_console(void)
1299{
1300 return active_console && active_console->console_type == GRAPHIC_CONSOLE;
1301}
1302
1303int is_fixedsize_console(void)
1304{
1305 return active_console && active_console->console_type != TEXT_CONSOLE;
1306}
1307
1308void console_color_init(DisplayState *ds)
1309{
1310 int i, j;
1311 for (j = 0; j < 2; j++) {
1312 for (i = 0; i < 8; i++) {
1313 color_table[j][i] = col_expand(ds,
1314 vga_get_color(ds, color_table_rgb[j][i]));
1315 }
1316 }
1317}
1318
1319static int n_text_consoles;
1320static CharDriverState *text_consoles[128];
1321static char *text_console_strs[128];
1322
1323static void text_console_do_init(CharDriverState *chr, DisplayState *ds, const char *p)
1324{
1325 TextConsole *s;
1326 unsigned width;
1327 unsigned height;
1328 static int color_inited;
1329
1330 s = new_console(ds, (p == 0) ? TEXT_CONSOLE : TEXT_CONSOLE_FIXED_SIZE);
1331 if (!s) {
1332 free(chr);
1333 return;
1334 }
1335 chr->opaque = s;
1336 chr->chr_write = console_puts;
1337 chr->chr_send_event = console_send_event;
1338
1339 s->chr = chr;
1340 s->out_fifo.buf = s->out_fifo_buf;
1341 s->out_fifo.buf_size = sizeof(s->out_fifo_buf);
1342 s->kbd_timer = qemu_new_timer(rt_clock, kbd_send_chars, s);
1343 s->ds = ds;
1344
1345 if (!color_inited) {
1346 color_inited = 1;
1347 console_color_init(s->ds);
1348 }
1349 s->y_displayed = 0;
1350 s->y_base = 0;
1351 s->total_height = DEFAULT_BACKSCROLL;
1352 s->x = 0;
1353 s->y = 0;
1354 width = ds_get_width(s->ds);
1355 height = ds_get_height(s->ds);
1356 if (p != 0) {
1357 width = strtoul(p, (char **)&p, 10);
1358 if (*p == 'C') {
1359 p++;
1360 width *= FONT_WIDTH;
1361 }
1362 if (*p == 'x') {
1363 p++;
1364 height = strtoul(p, (char **)&p, 10);
1365 if (*p == 'C') {
1366 p++;
1367 height *= FONT_HEIGHT;
1368 }
1369 }
1370 }
1371 s->g_width = width;
1372 s->g_height = height;
1373
1374 s->hw_invalidate = text_console_invalidate;
1375 s->hw_text_update = text_console_update;
1376 s->hw = s;
1377
1378
1379 s->t_attrib_default.bold = 0;
1380 s->t_attrib_default.uline = 0;
1381 s->t_attrib_default.blink = 0;
1382 s->t_attrib_default.invers = 0;
1383 s->t_attrib_default.unvisible = 0;
1384 s->t_attrib_default.fgcol = COLOR_WHITE;
1385 s->t_attrib_default.bgcol = COLOR_BLACK;
1386
1387 s->t_attrib = s->t_attrib_default;
1388 text_console_resize(s);
1389
1390 qemu_chr_reset(chr);
1391 if (chr->init)
1392 chr->init(chr);
1393}
1394
1395CharDriverState *text_console_init(const char *p)
1396{
1397 CharDriverState *chr;
1398
1399 chr = qemu_mallocz(sizeof(CharDriverState));
1400
1401 if (n_text_consoles == 128) {
1402 fprintf(stderr, "Too many text consoles\n");
1403 exit(1);
1404 }
1405 text_consoles[n_text_consoles] = chr;
1406 text_console_strs[n_text_consoles] = p ? qemu_strdup(p) : NULL;
1407 n_text_consoles++;
1408
1409 return chr;
1410}
1411
1412void text_consoles_set_display(DisplayState *ds)
1413{
1414 int i;
1415
1416 for (i = 0; i < n_text_consoles; i++) {
1417 text_console_do_init(text_consoles[i], ds, text_console_strs[i]);
1418 qemu_free(text_console_strs[i]);
1419 }
1420
1421 n_text_consoles = 0;
1422}
1423
1424void qemu_console_resize(DisplayState *ds, int width, int height)
1425{
1426 TextConsole *s = get_graphic_console(ds);
1427 if (!s) return;
1428
1429 s->g_width = width;
1430 s->g_height = height;
1431 if (is_graphic_console()) {
1432 ds->surface = qemu_resize_displaysurface(ds->surface, width, height, 32, 4 * width);
1433 dpy_resize(ds);
1434 }
1435}
1436
1437void qemu_console_copy(DisplayState *ds, int src_x, int src_y,
1438 int dst_x, int dst_y, int w, int h)
1439{
1440 if (is_graphic_console()) {
1441 dpy_copy(ds, src_x, src_y, dst_x, dst_y, w, h);
1442 }
1443}
1444
1445PixelFormat qemu_different_endianness_pixelformat(int bpp)
1446{
1447 PixelFormat pf;
1448
1449 memset(&pf, 0x00, sizeof(PixelFormat));
1450
1451 pf.bits_per_pixel = bpp;
1452 pf.bytes_per_pixel = bpp / 8;
1453 pf.depth = bpp == 32 ? 24 : bpp;
1454
1455 switch (bpp) {
1456 case 24:
1457 pf.rmask = 0x000000FF;
1458 pf.gmask = 0x0000FF00;
1459 pf.bmask = 0x00FF0000;
1460 pf.rmax = 255;
1461 pf.gmax = 255;
1462 pf.bmax = 255;
1463 pf.rshift = 0;
1464 pf.gshift = 8;
1465 pf.bshift = 16;
1466 pf.rbits = 8;
1467 pf.gbits = 8;
1468 pf.bbits = 8;
1469 break;
1470 case 32:
1471 pf.rmask = 0x0000FF00;
1472 pf.gmask = 0x00FF0000;
1473 pf.bmask = 0xFF000000;
1474 pf.amask = 0x00000000;
1475 pf.amax = 255;
1476 pf.rmax = 255;
1477 pf.gmax = 255;
1478 pf.bmax = 255;
1479 pf.ashift = 0;
1480 pf.rshift = 8;
1481 pf.gshift = 16;
1482 pf.bshift = 24;
1483 pf.rbits = 8;
1484 pf.gbits = 8;
1485 pf.bbits = 8;
1486 pf.abits = 8;
1487 break;
1488 default:
1489 break;
1490 }
1491 return pf;
1492}
1493
1494PixelFormat qemu_default_pixelformat(int bpp)
1495{
1496 PixelFormat pf;
1497
1498 memset(&pf, 0x00, sizeof(PixelFormat));
1499
1500 pf.bits_per_pixel = bpp;
1501 pf.bytes_per_pixel = bpp / 8;
1502 pf.depth = bpp == 32 ? 24 : bpp;
1503
1504 switch (bpp) {
1505 case 16:
1506 pf.rmask = 0x0000F800;
1507 pf.gmask = 0x000007E0;
1508 pf.bmask = 0x0000001F;
1509 pf.rmax = 31;
1510 pf.gmax = 63;
1511 pf.bmax = 31;
1512 pf.rshift = 11;
1513 pf.gshift = 5;
1514 pf.bshift = 0;
1515 pf.rbits = 5;
1516 pf.gbits = 6;
1517 pf.bbits = 5;
1518 break;
1519 case 24:
1520 pf.rmask = 0x00FF0000;
1521 pf.gmask = 0x0000FF00;
1522 pf.bmask = 0x000000FF;
1523 pf.rmax = 255;
1524 pf.gmax = 255;
1525 pf.bmax = 255;
1526 pf.rshift = 16;
1527 pf.gshift = 8;
1528 pf.bshift = 0;
1529 pf.rbits = 8;
1530 pf.gbits = 8;
1531 pf.bbits = 8;
1532 case 32:
1533 pf.rmask = 0x00FF0000;
1534 pf.gmask = 0x0000FF00;
1535 pf.bmask = 0x000000FF;
1536 pf.amax = 255;
1537 pf.rmax = 255;
1538 pf.gmax = 255;
1539 pf.bmax = 255;
1540 pf.ashift = 24;
1541 pf.rshift = 16;
1542 pf.gshift = 8;
1543 pf.bshift = 0;
1544 pf.rbits = 8;
1545 pf.gbits = 8;
1546 pf.bbits = 8;
1547 pf.abits = 8;
1548 break;
1549 default:
1550 break;
1551 }
1552 return pf;
1553}
1554
1555DisplaySurface* qemu_create_displaysurface(int width, int height, int bpp, int linesize)
1556{
1557 DisplaySurface *surface = (DisplaySurface*) qemu_mallocz(sizeof(DisplaySurface));
1558
1559 surface->width = width;
1560 surface->height = height;
1561 surface->linesize = linesize;
1562 surface->pf = qemu_default_pixelformat(bpp);
1563#ifdef WORDS_BIGENDIAN
1564 surface->flags = QEMU_ALLOCATED_FLAG | QEMU_BIG_ENDIAN_FLAG;
1565#else
1566 surface->flags = QEMU_ALLOCATED_FLAG;
1567#endif
1568 surface->data = (uint8_t*) qemu_mallocz(surface->linesize * surface->height);
1569
1570 return surface;
1571}
1572
1573DisplaySurface* qemu_resize_displaysurface(DisplaySurface *surface,
1574 int width, int height, int bpp, int linesize)
1575{
1576 surface->width = width;
1577 surface->height = height;
1578 surface->linesize = linesize;
1579 surface->pf = qemu_default_pixelformat(bpp);
1580 if (surface->flags & QEMU_ALLOCATED_FLAG)
1581 surface->data = (uint8_t*) qemu_realloc(surface->data, surface->linesize * surface->height);
1582 else
1583 surface->data = (uint8_t*) qemu_malloc(surface->linesize * surface->height);
1584#ifdef WORDS_BIGENDIAN
1585 surface->flags = QEMU_ALLOCATED_FLAG | QEMU_BIG_ENDIAN_FLAG;
1586#else
1587 surface->flags = QEMU_ALLOCATED_FLAG;
1588#endif
1589
1590 return surface;
1591}
1592
1593DisplaySurface* qemu_create_displaysurface_from(int width, int height, int bpp,
1594 int linesize, uint8_t *data)
1595{
1596 DisplaySurface *surface = (DisplaySurface*) qemu_mallocz(sizeof(DisplaySurface));
1597
1598 surface->width = width;
1599 surface->height = height;
1600 surface->linesize = linesize;
1601 surface->pf = qemu_default_pixelformat(bpp);
1602#ifdef WORDS_BIGENDIAN
1603 surface->flags = QEMU_BIG_ENDIAN_FLAG;
1604#endif
1605 surface->data = data;
1606
1607 return surface;
1608}
1609
1610void qemu_free_displaysurface(DisplaySurface *surface)
1611{
1612 if (surface == NULL)
1613 return;
1614 if (surface->flags & QEMU_ALLOCATED_FLAG)
1615 qemu_free(surface->data);
1616 qemu_free(surface);
1617}
1618