//#define DEBUG_CONSOLE
#define DEFAULT_BACKSCROLL 512
#define MAX_CONSOLES 12
-#define DEFAULT_MONITOR_SIZE "800x600"
#define QEMU_RGBA(r, g, b, a) (((a) << 24) | ((r) << 16) | ((g) << 8) | (b))
#define QEMU_RGB(r, g, b) QEMU_RGBA(r, g, b, 0xff)
TextAttributes t_attrib; /* currently active text attributes */
TextCell *cells;
int text_x[2], text_y[2], cursor_invalidate;
+ int echo;
int update_x0;
int update_y0;
QEMUTimer *kbd_timer;
};
+static DisplayState *display_state;
static TextConsole *active_console;
static TextConsole *consoles[MAX_CONSOLES];
static int nb_consoles = 0;
void vga_hw_invalidate(void)
{
- if (active_console->hw_invalidate)
+ if (active_console && active_console->hw_invalidate)
active_console->hw_invalidate(active_console->hw);
}
active_console = consoles[0];
/* There is currently no way of specifying which screen we want to dump,
so always dump the first one. */
- if (consoles[0]->hw_screen_dump)
+ if (consoles[0] && consoles[0]->hw_screen_dump)
consoles[0]->hw_screen_dump(consoles[0]->hw, filename);
active_console = previous_active_console;
}
(((uint32_t)(__x) & (uint32_t)0x00ff0000UL) >> 8) | \
(((uint32_t)(__x) & (uint32_t)0xff000000UL) >> 24) ))
-#ifdef WORDS_BIGENDIAN
+#ifdef HOST_WORDS_BIGENDIAN
#define PAT(x) x
#else
#define PAT(x) cbswap_32(x)
TextCell *c = &s->cells[y1 * s->width + x];
c->ch = ' ';
c->t_attrib = s->t_attrib_default;
- c++;
update_xy(s, x, y);
}
if (index >= MAX_CONSOLES)
return;
- active_console->g_width = ds_get_width(active_console->ds);
- active_console->g_height = ds_get_height(active_console->ds);
+ if (active_console) {
+ active_console->g_width = ds_get_width(active_console->ds);
+ active_console->g_height = ds_get_height(active_console->ds);
+ }
s = consoles[index];
if (s) {
DisplayState *ds = s->ds;
active_console = s;
if (ds_get_bits_per_pixel(s->ds)) {
- ds->surface = qemu_resize_displaysurface(ds->surface, s->g_width,
- s->g_height, 32, 4 * s->g_width);
+ ds->surface = qemu_resize_displaysurface(ds, s->g_width, s->g_height);
} else {
s->ds->surface->width = s->width;
s->ds->surface->height = s->height;
/* characters are pending: we send them a bit later (XXX:
horrible, should change char device API) */
if (s->out_fifo.count > 0) {
- qemu_mod_timer(s->kbd_timer, qemu_get_clock(rt_clock) + 1);
+ qemu_mod_timer(s->kbd_timer, qemu_get_clock_ms(rt_clock) + 1);
}
}
*q++ = '\033';
*q++ = '[';
*q++ = keysym & 0xff;
+ } else if (s->echo && (keysym == '\r' || keysym == '\n')) {
+ console_puts(s->chr, (const uint8_t *) "\r", 1);
+ *q++ = '\n';
} else {
- *q++ = keysym;
+ *q++ = keysym;
+ }
+ if (s->echo) {
+ console_puts(s->chr, buf, q - buf);
}
if (s->chr->chr_read) {
qemu_fifo_write(&s->out_fifo, buf, q - buf);
if (nb_consoles >= MAX_CONSOLES)
return NULL;
s = qemu_mallocz(sizeof(TextConsole));
- if (!s) {
- return NULL;
- }
if (!active_console || ((active_console->console_type != GRAPHIC_CONSOLE) &&
(console_type == GRAPHIC_CONSOLE))) {
active_console = s;
return s;
}
+static DisplaySurface* defaultallocator_create_displaysurface(int width, int height)
+{
+ DisplaySurface *surface = (DisplaySurface*) qemu_mallocz(sizeof(DisplaySurface));
+
+ int linesize = width * 4;
+ qemu_alloc_display(surface, width, height, linesize,
+ qemu_default_pixelformat(32), 0);
+ return surface;
+}
+
+static DisplaySurface* defaultallocator_resize_displaysurface(DisplaySurface *surface,
+ int width, int height)
+{
+ int linesize = width * 4;
+ qemu_alloc_display(surface, width, height, linesize,
+ qemu_default_pixelformat(32), 0);
+ return surface;
+}
+
+void qemu_alloc_display(DisplaySurface *surface, int width, int height,
+ int linesize, PixelFormat pf, int newflags)
+{
+ void *data;
+ surface->width = width;
+ surface->height = height;
+ surface->linesize = linesize;
+ surface->pf = pf;
+ if (surface->flags & QEMU_ALLOCATED_FLAG) {
+ data = qemu_realloc(surface->data,
+ surface->linesize * surface->height);
+ } else {
+ data = qemu_malloc(surface->linesize * surface->height);
+ }
+ surface->data = (uint8_t *)data;
+ surface->flags = newflags | QEMU_ALLOCATED_FLAG;
+#ifdef HOST_WORDS_BIGENDIAN
+ surface->flags |= QEMU_BIG_ENDIAN_FLAG;
+#endif
+}
+
+DisplaySurface* qemu_create_displaysurface_from(int width, int height, int bpp,
+ int linesize, uint8_t *data)
+{
+ DisplaySurface *surface = (DisplaySurface*) qemu_mallocz(sizeof(DisplaySurface));
+
+ surface->width = width;
+ surface->height = height;
+ surface->linesize = linesize;
+ surface->pf = qemu_default_pixelformat(bpp);
+#ifdef HOST_WORDS_BIGENDIAN
+ surface->flags = QEMU_BIG_ENDIAN_FLAG;
+#endif
+ surface->data = data;
+
+ return surface;
+}
+
+static void defaultallocator_free_displaysurface(DisplaySurface *surface)
+{
+ if (surface == NULL)
+ return;
+ if (surface->flags & QEMU_ALLOCATED_FLAG)
+ qemu_free(surface->data);
+ qemu_free(surface);
+}
+
+static struct DisplayAllocator default_allocator = {
+ defaultallocator_create_displaysurface,
+ defaultallocator_resize_displaysurface,
+ defaultallocator_free_displaysurface
+};
+
+static void dumb_display_init(void)
+{
+ DisplayState *ds = qemu_mallocz(sizeof(DisplayState));
+ ds->allocator = &default_allocator;
+ ds->surface = qemu_create_displaysurface(ds, 640, 480);
+ register_displaystate(ds);
+}
+
+/***********************************************************/
+/* register display */
+
+void register_displaystate(DisplayState *ds)
+{
+ DisplayState **s;
+ s = &display_state;
+ while (*s != NULL)
+ s = &(*s)->next;
+ ds->next = NULL;
+ *s = ds;
+}
+
+DisplayState *get_displaystate(void)
+{
+ if (!display_state) {
+ dumb_display_init ();
+ }
+ return display_state;
+}
+
+DisplayAllocator *register_displayallocator(DisplayState *ds, DisplayAllocator *da)
+{
+ if(ds->allocator == &default_allocator) {
+ DisplaySurface *surf;
+ surf = da->create_displaysurface(ds_get_width(ds), ds_get_height(ds));
+ defaultallocator_free_displaysurface(ds->surface);
+ ds->surface = surf;
+ ds->allocator = da;
+ }
+ return ds->allocator;
+}
+
DisplayState *graphic_console_init(vga_hw_update_ptr update,
vga_hw_invalidate_ptr invalidate,
vga_hw_screen_dump_ptr screen_dump,
DisplayState *ds;
ds = (DisplayState *) qemu_mallocz(sizeof(DisplayState));
- if (ds == NULL)
- return NULL;
- ds->surface = qemu_create_displaysurface(640, 480, 32, 640 * 4);
+ ds->allocator = &default_allocator;
+ ds->surface = qemu_create_displaysurface(ds, 640, 480);
s = new_console(ds, GRAPHIC_CONSOLE);
if (s == NULL) {
- qemu_free_displaysurface(ds->surface);
+ qemu_free_displaysurface(ds);
qemu_free(ds);
return NULL;
}
static int n_text_consoles;
static CharDriverState *text_consoles[128];
-static char *text_console_strs[128];
-static void text_console_do_init(CharDriverState *chr, DisplayState *ds, const char *p)
+static void text_console_set_echo(CharDriverState *chr, bool echo)
+{
+ TextConsole *s = chr->opaque;
+
+ s->echo = echo;
+}
+
+static void text_console_do_init(CharDriverState *chr, DisplayState *ds)
{
TextConsole *s;
- unsigned width;
- unsigned height;
static int color_inited;
- s = new_console(ds, (p == 0) ? TEXT_CONSOLE : TEXT_CONSOLE_FIXED_SIZE);
- if (!s) {
- free(chr);
- return;
- }
- chr->opaque = s;
+ s = chr->opaque;
+
chr->chr_write = console_puts;
chr->chr_send_event = console_send_event;
- s->chr = chr;
s->out_fifo.buf = s->out_fifo_buf;
s->out_fifo.buf_size = sizeof(s->out_fifo_buf);
- s->kbd_timer = qemu_new_timer(rt_clock, kbd_send_chars, s);
+ s->kbd_timer = qemu_new_timer_ms(rt_clock, kbd_send_chars, s);
s->ds = ds;
if (!color_inited) {
s->total_height = DEFAULT_BACKSCROLL;
s->x = 0;
s->y = 0;
- width = ds_get_width(s->ds);
- height = ds_get_height(s->ds);
- if (p != 0) {
- width = strtoul(p, (char **)&p, 10);
- if (*p == 'C') {
- p++;
- width *= FONT_WIDTH;
- }
- if (*p == 'x') {
- p++;
- height = strtoul(p, (char **)&p, 10);
- if (*p == 'C') {
- p++;
- height *= FONT_HEIGHT;
- }
- }
+ if (s->console_type == TEXT_CONSOLE) {
+ s->g_width = ds_get_width(s->ds);
+ s->g_height = ds_get_height(s->ds);
}
- s->g_width = width;
- s->g_height = height;
s->hw_invalidate = text_console_invalidate;
s->hw_text_update = text_console_update;
s->t_attrib = s->t_attrib_default;
text_console_resize(s);
- qemu_chr_reset(chr);
+ if (chr->label) {
+ char msg[128];
+ int len;
+
+ s->t_attrib.bgcol = COLOR_BLUE;
+ len = snprintf(msg, sizeof(msg), "%s console\r\n", chr->label);
+ console_puts(chr, (uint8_t*)msg, len);
+ s->t_attrib = s->t_attrib_default;
+ }
+
+ qemu_chr_generic_open(chr);
if (chr->init)
chr->init(chr);
}
-CharDriverState *text_console_init(const char *p)
+CharDriverState *text_console_init(QemuOpts *opts)
{
CharDriverState *chr;
+ TextConsole *s;
+ unsigned width;
+ unsigned height;
chr = qemu_mallocz(sizeof(CharDriverState));
- if (!chr)
- return NULL;
if (n_text_consoles == 128) {
fprintf(stderr, "Too many text consoles\n");
exit(1);
}
text_consoles[n_text_consoles] = chr;
- text_console_strs[n_text_consoles] = p ? qemu_strdup(p) : NULL;
n_text_consoles++;
+ width = qemu_opt_get_number(opts, "width", 0);
+ if (width == 0)
+ width = qemu_opt_get_number(opts, "cols", 0) * FONT_WIDTH;
+
+ height = qemu_opt_get_number(opts, "height", 0);
+ if (height == 0)
+ height = qemu_opt_get_number(opts, "rows", 0) * FONT_HEIGHT;
+
+ if (width == 0 || height == 0) {
+ s = new_console(NULL, TEXT_CONSOLE);
+ } else {
+ s = new_console(NULL, TEXT_CONSOLE_FIXED_SIZE);
+ }
+
+ if (!s) {
+ free(chr);
+ return NULL;
+ }
+
+ s->chr = chr;
+ s->g_width = width;
+ s->g_height = height;
+ chr->opaque = s;
+ chr->chr_set_echo = text_console_set_echo;
return chr;
}
int i;
for (i = 0; i < n_text_consoles; i++) {
- text_console_do_init(text_consoles[i], ds, text_console_strs[i]);
- qemu_free(text_console_strs[i]);
+ text_console_do_init(text_consoles[i], ds);
}
n_text_consoles = 0;
void qemu_console_resize(DisplayState *ds, int width, int height)
{
TextConsole *s = get_graphic_console(ds);
+ if (!s) return;
+
s->g_width = width;
s->g_height = height;
if (is_graphic_console()) {
- ds->surface = qemu_resize_displaysurface(ds->surface, width, height, 32, 4 * width);
+ ds->surface = qemu_resize_displaysurface(ds, width, height);
dpy_resize(ds);
}
}
}
}
-static PixelFormat qemu_default_pixelformat(int bpp)
+PixelFormat qemu_different_endianness_pixelformat(int bpp)
{
PixelFormat pf;
pf.depth = bpp == 32 ? 24 : bpp;
switch (bpp) {
- case 8:
- pf.rmask = 0x000000E0;
- pf.gmask = 0x0000001C;
- pf.bmask = 0x00000003;
- pf.rmax = 7;
- pf.gmax = 7;
- pf.bmax = 3;
- pf.rshift = 5;
- pf.gshift = 2;
+ case 24:
+ pf.rmask = 0x000000FF;
+ pf.gmask = 0x0000FF00;
+ pf.bmask = 0x00FF0000;
+ pf.rmax = 255;
+ pf.gmax = 255;
+ pf.bmax = 255;
+ pf.rshift = 0;
+ pf.gshift = 8;
+ pf.bshift = 16;
+ pf.rbits = 8;
+ pf.gbits = 8;
+ pf.bbits = 8;
+ break;
+ case 32:
+ pf.rmask = 0x0000FF00;
+ pf.gmask = 0x00FF0000;
+ pf.bmask = 0xFF000000;
+ pf.amask = 0x00000000;
+ pf.amax = 255;
+ pf.rmax = 255;
+ pf.gmax = 255;
+ pf.bmax = 255;
+ pf.ashift = 0;
+ pf.rshift = 8;
+ pf.gshift = 16;
+ pf.bshift = 24;
+ pf.rbits = 8;
+ pf.gbits = 8;
+ pf.bbits = 8;
+ pf.abits = 8;
+ break;
+ default:
+ break;
+ }
+ return pf;
+}
+
+PixelFormat qemu_default_pixelformat(int bpp)
+{
+ PixelFormat pf;
+
+ memset(&pf, 0x00, sizeof(PixelFormat));
+
+ pf.bits_per_pixel = bpp;
+ pf.bytes_per_pixel = bpp / 8;
+ pf.depth = bpp == 32 ? 24 : bpp;
+
+ switch (bpp) {
+ case 15:
+ pf.bits_per_pixel = 16;
+ pf.bytes_per_pixel = 2;
+ pf.rmask = 0x00007c00;
+ pf.gmask = 0x000003E0;
+ pf.bmask = 0x0000001F;
+ pf.rmax = 31;
+ pf.gmax = 31;
+ pf.bmax = 31;
+ pf.rshift = 10;
+ pf.gshift = 5;
pf.bshift = 0;
+ pf.rbits = 5;
+ pf.gbits = 5;
+ pf.bbits = 5;
break;
case 16:
pf.rmask = 0x0000F800;
pf.rshift = 11;
pf.gshift = 5;
pf.bshift = 0;
+ pf.rbits = 5;
+ pf.gbits = 6;
+ pf.bbits = 5;
break;
case 24:
+ pf.rmask = 0x00FF0000;
+ pf.gmask = 0x0000FF00;
+ pf.bmask = 0x000000FF;
+ pf.rmax = 255;
+ pf.gmax = 255;
+ pf.bmax = 255;
+ pf.rshift = 16;
+ pf.gshift = 8;
+ pf.bshift = 0;
+ pf.rbits = 8;
+ pf.gbits = 8;
+ pf.bbits = 8;
case 32:
pf.rmask = 0x00FF0000;
pf.gmask = 0x0000FF00;
pf.bmask = 0x000000FF;
+ pf.amax = 255;
pf.rmax = 255;
pf.gmax = 255;
pf.bmax = 255;
+ pf.ashift = 24;
pf.rshift = 16;
pf.gshift = 8;
pf.bshift = 0;
+ pf.rbits = 8;
+ pf.gbits = 8;
+ pf.bbits = 8;
+ pf.abits = 8;
break;
default:
break;
}
return pf;
}
-
-DisplaySurface* qemu_create_displaysurface(int width, int height, int bpp, int linesize)
-{
- DisplaySurface *surface = (DisplaySurface*) qemu_mallocz(sizeof(DisplaySurface));
- if (surface == NULL) {
- fprintf(stderr, "qemu_create_displaysurface: malloc failed\n");
- exit(1);
- }
-
- surface->width = width;
- surface->height = height;
- surface->linesize = linesize;
- surface->pf = qemu_default_pixelformat(bpp);
-#ifdef WORDS_BIGENDIAN
- surface->flags = QEMU_ALLOCATED_FLAG | QEMU_BIG_ENDIAN_FLAG;
-#else
- surface->flags = QEMU_ALLOCATED_FLAG;
-#endif
- surface->data = (uint8_t*) qemu_mallocz(surface->linesize * surface->height);
- if (surface->data == NULL) {
- fprintf(stderr, "qemu_create_displaysurface: malloc failed\n");
- exit(1);
- }
-
- return surface;
-}
-
-DisplaySurface* qemu_resize_displaysurface(DisplaySurface *surface,
- int width, int height, int bpp, int linesize)
-{
- surface->width = width;
- surface->height = height;
- surface->linesize = linesize;
- surface->pf = qemu_default_pixelformat(bpp);
- if (surface->flags & QEMU_ALLOCATED_FLAG)
- surface->data = (uint8_t*) qemu_realloc(surface->data, surface->linesize * surface->height);
- else
- surface->data = (uint8_t*) qemu_malloc(surface->linesize * surface->height);
- if (surface->data == NULL) {
- fprintf(stderr, "qemu_resize_displaysurface: malloc failed\n");
- exit(1);
- }
-#ifdef WORDS_BIGENDIAN
- surface->flags = QEMU_ALLOCATED_FLAG | QEMU_BIG_ENDIAN_FLAG;
-#else
- surface->flags = QEMU_ALLOCATED_FLAG;
-#endif
-
- return surface;
-}
-
-DisplaySurface* qemu_create_displaysurface_from(int width, int height, int bpp,
- int linesize, uint8_t *data)
-{
- DisplaySurface *surface = (DisplaySurface*) qemu_mallocz(sizeof(DisplaySurface));
- if (surface == NULL) {
- fprintf(stderr, "qemu_create_displaysurface_from: malloc failed\n");
- exit(1);
- }
-
- surface->width = width;
- surface->height = height;
- surface->linesize = linesize;
- surface->pf = qemu_default_pixelformat(bpp);
-#ifdef WORDS_BIGENDIAN
- surface->flags = QEMU_BIG_ENDIAN_FLAG;
-#endif
- surface->data = data;
-
- return surface;
-}
-
-void qemu_free_displaysurface(DisplaySurface *surface)
-{
- if (surface == NULL)
- return;
- if (surface->flags & QEMU_ALLOCATED_FLAG)
- qemu_free(surface->data);
- qemu_free(surface);
-}