Merge branch 'master' of /home/nchip/public_html/qemu into garage-push
[qemu] / console.c
index 6f0f1af..52e3e57 100644 (file)
--- a/console.c
+++ b/console.c
@@ -28,7 +28,6 @@
 //#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)
@@ -139,6 +138,11 @@ struct TextConsole {
     TextCell *cells;
     int text_x[2], text_y[2], cursor_invalidate;
 
+    int update_x0;
+    int update_y0;
+    int update_x1;
+    int update_y1;
+
     enum TTYState state;
     int esc_params[MAX_ESC_PARAMS];
     int nb_esc_params;
@@ -537,6 +541,18 @@ static inline void text_update_xy(TextConsole *s, int x, int y)
     s->text_y[1] = MAX(s->text_y[1], y);
 }
 
+static void invalidate_xy(TextConsole *s, int x, int y)
+{
+    if (s->update_x0 > x * FONT_WIDTH)
+        s->update_x0 = x * FONT_WIDTH;
+    if (s->update_y0 > y * FONT_HEIGHT)
+        s->update_y0 = y * FONT_HEIGHT;
+    if (s->update_x1 < (x + 1) * FONT_WIDTH)
+        s->update_x1 = (x + 1) * FONT_WIDTH;
+    if (s->update_y1 < (y + 1) * FONT_HEIGHT)
+        s->update_y1 = (y + 1) * FONT_HEIGHT;
+}
+
 static void update_xy(TextConsole *s, int x, int y)
 {
     TextCell *c;
@@ -556,8 +572,7 @@ static void update_xy(TextConsole *s, int x, int y)
             c = &s->cells[y1 * s->width + x];
             vga_putcharxy(s->ds, x, y2, c->ch,
                           &(c->t_attrib));
-            dpy_update(s->ds, x * FONT_WIDTH, y2 * FONT_HEIGHT,
-                       FONT_WIDTH, FONT_HEIGHT);
+            invalidate_xy(s, x, y2);
         }
     }
 }
@@ -591,8 +606,7 @@ static void console_show_cursor(TextConsole *s, int show)
             } else {
                 vga_putcharxy(s->ds, x, y, c->ch, &(c->t_attrib));
             }
-            dpy_update(s->ds, x * FONT_WIDTH, y * FONT_HEIGHT,
-                       FONT_WIDTH, FONT_HEIGHT);
+            invalidate_xy(s, x, y);
         }
     }
 }
@@ -626,8 +640,8 @@ static void console_refresh(TextConsole *s)
         if (++y1 == s->total_height)
             y1 = 0;
     }
-    dpy_update(s->ds, 0, 0, ds_get_width(s->ds), ds_get_height(s->ds));
     console_show_cursor(s, 1);
+    dpy_update(s->ds, 0, 0, ds_get_width(s->ds), ds_get_height(s->ds));
 }
 
 static void console_scroll(int ydelta)
@@ -703,8 +717,10 @@ static void console_put_lf(TextConsole *s)
             vga_fill_rect(s->ds, 0, (s->height - 1) * FONT_HEIGHT,
                           s->width * FONT_WIDTH, FONT_HEIGHT,
                           color_table[0][s->t_attrib_default.bgcol]);
-            dpy_update(s->ds, 0, 0,
-                       s->width * FONT_WIDTH, s->height * FONT_HEIGHT);
+            s->update_x0 = 0;
+            s->update_y0 = 0;
+            s->update_x1 = s->width * FONT_WIDTH;
+            s->update_y1 = s->height * FONT_HEIGHT;
         }
     }
 }
@@ -1050,8 +1066,12 @@ void console_select(unsigned int index)
     if (s) {
         DisplayState *ds = s->ds;
         active_console = s;
-        ds->surface = qemu_resize_displaysurface(ds->surface, s->g_width,
-                                                s->g_height, 32, 4 * s->g_width);
+        if (ds_get_bits_per_pixel(s->ds)) {
+            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;
+        }
         dpy_resize(s->ds);
         vga_hw_invalidate();
     }
@@ -1062,11 +1082,20 @@ static int console_puts(CharDriverState *chr, const uint8_t *buf, int len)
     TextConsole *s = chr->opaque;
     int i;
 
+    s->update_x0 = s->width * FONT_WIDTH;
+    s->update_y0 = s->height * FONT_HEIGHT;
+    s->update_x1 = 0;
+    s->update_y1 = 0;
     console_show_cursor(s, 0);
     for(i = 0; i < len; i++) {
         console_putchar(s, buf[i]);
     }
     console_show_cursor(s, 1);
+    if (ds_get_bits_per_pixel(s->ds) && s->update_x0 < s->update_x1) {
+        dpy_update(s->ds, s->update_x0, s->update_y0,
+                   s->update_x1 - s->update_x0,
+                   s->update_y1 - s->update_y0);
+    }
     return len;
 }
 
@@ -1160,6 +1189,11 @@ void kbd_put_keysym(int keysym)
 static void text_console_invalidate(void *opaque)
 {
     TextConsole *s = (TextConsole *) opaque;
+    if (!ds_get_bits_per_pixel(s->ds) && s->console_type == TEXT_CONSOLE) {
+        s->g_width = ds_get_width(s->ds);
+        s->g_height = ds_get_height(s->ds);
+        text_console_resize(s);
+    }
     console_refresh(s);
 }
 
@@ -1210,9 +1244,6 @@ static TextConsole *new_console(DisplayState *ds, console_type_t console_type)
     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;
@@ -1244,13 +1275,12 @@ DisplayState *graphic_console_init(vga_hw_update_ptr update,
     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;
     }
@@ -1296,7 +1326,7 @@ static void text_console_do_init(CharDriverState *chr, DisplayState *ds, const c
     unsigned height;
     static int color_inited;
 
-    s = new_console(ds, (p == 0) ? TEXT_CONSOLE : TEXT_CONSOLE_FIXED_SIZE);
+    s = new_console(ds, (p == NULL) ? TEXT_CONSOLE : TEXT_CONSOLE_FIXED_SIZE);
     if (!s) {
         free(chr);
         return;
@@ -1322,7 +1352,7 @@ static void text_console_do_init(CharDriverState *chr, DisplayState *ds, const c
     s->y = 0;
     width = ds_get_width(s->ds);
     height = ds_get_height(s->ds);
-    if (p != 0) {
+    if (p != NULL) {
         width = strtoul(p, (char **)&p, 10);
         if (*p == 'C') {
             p++;
@@ -1366,8 +1396,6 @@ CharDriverState *text_console_init(const char *p)
     CharDriverState *chr;
 
     chr = qemu_mallocz(sizeof(CharDriverState));
-    if (!chr)
-        return NULL;
 
     if (n_text_consoles == 128) {
         fprintf(stderr, "Too many text consoles\n");
@@ -1395,10 +1423,12 @@ void text_consoles_set_display(DisplayState *ds)
 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);
     }
 }
@@ -1411,7 +1441,7 @@ void qemu_console_copy(DisplayState *ds, int src_x, int src_y,
     }
 }
 
-static PixelFormat qemu_default_pixelformat(int bpp)
+PixelFormat qemu_different_endianness_pixelformat(int bpp)
 {
     PixelFormat pf;
 
@@ -1422,17 +1452,55 @@ static PixelFormat qemu_default_pixelformat(int bpp)
     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;
-            pf.bshift = 0;
+        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 16:
             pf.rmask = 0x0000F800;
             pf.gmask = 0x000007E0;
@@ -1443,18 +1511,39 @@ static PixelFormat qemu_default_pixelformat(int bpp)
             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;
@@ -1462,47 +1551,35 @@ static PixelFormat qemu_default_pixelformat(int bpp)
     return pf;
 }
 
-DisplaySurface* qemu_create_displaysurface(int width, int height, int bpp, int linesize)
+DisplaySurface* defaultallocator_create_displaysurface(int width, int height)
 {
     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);
+    surface->linesize = width * 4;
+    surface->pf = qemu_default_pixelformat(32);
 #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)
+DisplaySurface* defaultallocator_resize_displaysurface(DisplaySurface *surface,
+                                          int width, int height)
 {
     surface->width = width;
     surface->height = height;
-    surface->linesize = linesize;
-    surface->pf = qemu_default_pixelformat(bpp);
+    surface->linesize = width * 4;
+    surface->pf = qemu_default_pixelformat(32);
     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
@@ -1516,10 +1593,6 @@ 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;
@@ -1533,7 +1606,7 @@ DisplaySurface* qemu_create_displaysurface_from(int width, int height, int bpp,
     return surface;
 }
 
-void qemu_free_displaysurface(DisplaySurface *surface)
+void defaultallocator_free_displaysurface(DisplaySurface *surface)
 {
     if (surface == NULL)
         return;