Allow multiple graphics devices.


git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1803 c046a42c-6fe2-441c-8c8c-71466251a162
diff --git a/cocoa.m b/cocoa.m
index 27773e9..2e2908f 100644
--- a/cocoa.m
+++ b/cocoa.m
@@ -365,8 +365,8 @@
     pool = [ [ NSAutoreleasePool alloc ] init ];
     distantPast = [ NSDate distantPast ];
     
-    if (is_active_console(vga_console)) 
-        vga_update_display();
+    vga_hw_update();
+
     do {
         event = [ NSApp nextEventMatchingMask:NSAnyEventMask untilDate:distantPast
                         inMode: NSDefaultRunLoopMode dequeue:YES ];
@@ -382,7 +382,7 @@
                                 /* emulate caps lock and num lock keydown and keyup */
                                 kbd_put_keycode(keycode);
                                 kbd_put_keycode(keycode | 0x80);
-                            } else if (is_active_console(vga_console)) {
+                            } else if (is_graphic_console()) {
                                 if (keycode & 0x80)
                                     kbd_put_keycode(0xe0);
                                 if (modifiers_state[keycode] == 0) {
@@ -429,15 +429,12 @@
                                 /* toggle Monitor */
                                 case 0x02 ... 0x0a: /* '1' to '9' keys */
                                     console_select(keycode - 0x02);
-                                    if (is_active_console(vga_console)) {
-                                        /* tell the vga console to redisplay itself */
-                                        vga_invalidate_display();
                                     break;
                                 }
                             }
                         } else {
                             /* handle standard key events */
-                            if (is_active_console(vga_console)) {
+                            if (is_graphic_console()) {
                                 if (keycode & 0x80) //check bit for e0 in front
                                     kbd_put_keycode(0xe0);
                                 kbd_put_keycode(keycode & 0x7f); //remove e0 bit in front
@@ -468,7 +465,7 @@
                 case NSKeyUp:
                     {
                         int keycode = cocoa_keycode_to_qemu([event keyCode]);   
-                        if (is_active_console(vga_console)) {
+                        if (is_graphic_console()) {
                             if (keycode & 0x80)
                                 kbd_put_keycode(0xe0);
                             kbd_put_keycode(keycode | 0x80); //add 128 to signal release of key
diff --git a/console.c b/console.c
index d1eb406..6f9dc1f 100644
--- a/console.c
+++ b/console.c
@@ -53,10 +53,17 @@
     TTY_STATE_CSI,
 };
 
-
+/* ??? This is mis-named.
+   It is used for both text and graphical consoles.  */
 struct TextConsole {
     int text_console; /* true if text console */
     DisplayState *ds;
+    /* Graphic console state.  */
+    vga_hw_update_ptr hw_update;
+    vga_hw_invalidate_ptr hw_invalidate;
+    vga_hw_screen_dump_ptr hw_screen_dump;
+    void *hw;
+
     int g_width, g_height;
     int width;
     int height;
@@ -82,6 +89,26 @@
 static TextConsole *consoles[MAX_CONSOLES];
 static int nb_consoles = 0;
 
+void vga_hw_update(void)
+{
+    if (active_console->hw_update)
+        active_console->hw_update(active_console->hw);
+}
+
+void vga_hw_invalidate(void)
+{
+    if (active_console->hw_invalidate)
+        active_console->hw_invalidate(active_console->hw);
+}
+
+void vga_hw_screen_dump(const char *filename)
+{
+    /* There is currently no was of specifying which screen we want to dump,
+       so always dump the dirst one.  */
+    if (consoles[0]->hw_screen_dump)
+        consoles[0]->hw_screen_dump(consoles[0]->hw, filename);
+}
+
 /* convert a RGBA color to a color index usable in graphic primitives */
 static unsigned int vga_get_color(DisplayState *ds, unsigned int rgba)
 {
@@ -782,8 +809,10 @@
                 s->g_width = s->ds->width;
                 s->g_height = s->ds->height;
                 text_console_resize(s);
-        }
+            }
             console_refresh(s);
+        } else {
+            vga_hw_invalidate();
         }
     }
 }
@@ -874,9 +903,10 @@
     }
 }
 
-TextConsole *graphic_console_init(DisplayState *ds)
+static TextConsole *new_console(DisplayState *ds, int text)
 {
     TextConsole *s;
+    int i;
 
     if (nb_consoles >= MAX_CONSOLES)
         return NULL;
@@ -884,16 +914,44 @@
     if (!s) {
         return NULL;
     }
-    if (!active_console)
+    if (!active_console || (active_console->text_console && !text))
         active_console = s;
     s->ds = ds;
-    consoles[nb_consoles++] = s;
+    s->text_console = text;
+    if (text) {
+        consoles[nb_consoles++] = s;
+    } else {
+        /* HACK: Put graphical consoles before text consoles.  */
+        for (i = nb_consoles; i > 0; i--) {
+            if (!consoles[i - 1]->text_console)
+                break;
+            consoles[i] = consoles[i - 1];
+        }
+        consoles[i] = s;
+    }
     return s;
 }
 
-int is_active_console(TextConsole *s)
+TextConsole *graphic_console_init(DisplayState *ds, vga_hw_update_ptr update,
+                                  vga_hw_invalidate_ptr invalidate,
+                                  vga_hw_screen_dump_ptr screen_dump,
+                                  void *opaque)
 {
-    return s == active_console;
+    TextConsole *s;
+
+    s = new_console(ds, 0);
+    if (!s)
+      return NULL;
+    s->hw_update = update;
+    s->hw_invalidate = invalidate;
+    s->hw_screen_dump = screen_dump;
+    s->hw = opaque;
+    return s;
+}
+
+int is_graphic_console(void)
+{
+    return !active_console->text_console;
 }
 
 CharDriverState *text_console_init(DisplayState *ds)
@@ -906,12 +964,11 @@
     chr = qemu_mallocz(sizeof(CharDriverState));
     if (!chr)
         return NULL;
-    s = graphic_console_init(ds);
+    s = new_console(ds, 1);
     if (!s) {
         free(chr);
         return NULL;
     }
-    s->text_console = 1;
     chr->opaque = s;
     chr->chr_write = console_puts;
     chr->chr_add_read_handler = console_chr_add_read_handler;
diff --git a/hw/integratorcp.c b/hw/integratorcp.c
index db73efd..1bcd734 100644
--- a/hw/integratorcp.c
+++ b/hw/integratorcp.c
@@ -27,22 +27,6 @@
 {
 }
 
-static void *lcd;
-
-void vga_update_display(void)
-{
-    pl110_update_display(lcd);
-}
-
-void vga_screen_dump(const char *filename)
-{
-}
-
-void vga_invalidate_display(void)
-{
-    pl110_invalidate_display(lcd);
-}
-
 void DMA_run (void)
 {
 }
@@ -1210,7 +1194,7 @@
             exit (1);
         }
     }
-    lcd = pl110_init(ds, 0xc0000000, pic, 22);
+    pl110_init(ds, 0xc0000000, pic, 22, 0);
 
     /* Load the kernel.  */
     if (!kernel_filename) {
diff --git a/hw/pl110.c b/hw/pl110.c
index 2506dfd..839f103 100644
--- a/hw/pl110.c
+++ b/hw/pl110.c
@@ -89,7 +89,7 @@
   return (s->cr & PL110_CR_EN) && (s->cr & PL110_CR_PWR);
 }
 
-void pl110_update_display(void *opaque)
+static void pl110_update_display(void *opaque)
 {
     pl110_state *s = (pl110_state *)opaque;
     drawfn* fntable;
@@ -205,7 +205,7 @@
     dpy_update(s->ds, 0, first, s->cols, last - first + 1);
 }
 
-void pl110_invalidate_display(void * opaque)
+static void pl110_invalidate_display(void * opaque)
 {
     pl110_state *s = (pl110_state *)opaque;
     s->invalidate = 1;
@@ -378,7 +378,8 @@
    pl110_write
 };
 
-void *pl110_init(DisplayState *ds, uint32_t base, void *pic, int irq)
+void *pl110_init(DisplayState *ds, uint32_t base, void *pic, int irq,
+                 int versatile)
 {
     pl110_state *s;
     int iomemtype;
@@ -386,11 +387,13 @@
     s = (pl110_state *)qemu_mallocz(sizeof(pl110_state));
     iomemtype = cpu_register_io_memory(0, pl110_readfn,
                                        pl110_writefn, s);
-    cpu_register_physical_memory(base, 0x007fffff, iomemtype);
+    cpu_register_physical_memory(base, 0x00000fff, iomemtype);
     s->base = base;
     s->ds = ds;
     s->pic = pic;
     s->irq = irq;
+    graphic_console_init(ds, pl110_update_display, pl110_invalidate_display,
+                         NULL, s);
     /* ??? Save/restore.  */
     return s;
 }
diff --git a/hw/sun4m.c b/hw/sun4m.c
index b41ee25..435ac02 100644
--- a/hw/sun4m.c
+++ b/hw/sun4m.c
@@ -187,23 +187,6 @@
     slavio_pic_set_irq_cpu(slavio_intctl, irq, level, cpu);
 }
 
-static void *tcx;
-
-void vga_update_display()
-{
-    tcx_update_display(tcx);
-}
-
-void vga_invalidate_display()
-{
-    tcx_invalidate_display(tcx);
-}
-
-void vga_screen_dump(const char *filename)
-{
-    tcx_screen_dump(tcx, filename);
-}
-
 static void *iommu;
 
 uint32_t iommu_translate(uint32_t addr)
@@ -256,7 +239,7 @@
         slavio_intctl_set_cpu(slavio_intctl, i, envs[i]);
     }
 
-    tcx = tcx_init(ds, PHYS_JJ_TCX_FB, phys_ram_base + ram_size, ram_size, vram_size, graphic_width, graphic_height);
+    tcx_init(ds, PHYS_JJ_TCX_FB, phys_ram_base + ram_size, ram_size, vram_size, graphic_width, graphic_height);
     if (nd_table[0].vlan) {
         if (nd_table[0].model == NULL
             || strcmp(nd_table[0].model, "lance") == 0) {
diff --git a/hw/tcx.c b/hw/tcx.c
index c0fddf3..a3a2114 100644
--- a/hw/tcx.c
+++ b/hw/tcx.c
@@ -37,6 +37,8 @@
     uint8_t dac_index, dac_state;
 } TCXState;
 
+static void tcx_screen_dump(void *opaque, const char *filename);
+
 static void tcx_draw_line32(TCXState *s1, uint8_t *d, 
 			    const uint8_t *s, int width)
 {
@@ -81,7 +83,7 @@
 
 /* Fixed line length 1024 allows us to do nice tricks not possible on
    VGA... */
-void tcx_update_display(void *opaque)
+static void tcx_update_display(void *opaque)
 {
     TCXState *ts = opaque;
     uint32_t page;
@@ -158,7 +160,7 @@
     }
 }
 
-void tcx_invalidate_display(void *opaque)
+static void tcx_invalidate_display(void *opaque)
 {
     TCXState *s = opaque;
     int i;
@@ -269,15 +271,15 @@
     tcx_dac_writel,
 };
 
-void *tcx_init(DisplayState *ds, uint32_t addr, uint8_t *vram_base,
-	       unsigned long vram_offset, int vram_size, int width, int height)
+void tcx_init(DisplayState *ds, uint32_t addr, uint8_t *vram_base,
+	      unsigned long vram_offset, int vram_size, int width, int height)
 {
     TCXState *s;
     int io_memory;
 
     s = qemu_mallocz(sizeof(TCXState));
     if (!s)
-        return NULL;
+        return;
     s->ds = ds;
     s->addr = addr;
     s->vram = vram_base;
@@ -289,14 +291,15 @@
     io_memory = cpu_register_io_memory(0, tcx_dac_read, tcx_dac_write, s);
     cpu_register_physical_memory(addr + 0x200000, TCX_DAC_NREGS, io_memory);
 
+    graphic_console_init(s->ds, tcx_update_display, tcx_invalidate_display,
+                         tcx_screen_dump, s);
     register_savevm("tcx", addr, 1, tcx_save, tcx_load, s);
     qemu_register_reset(tcx_reset, s);
     tcx_reset(s);
     dpy_resize(s->ds, width, height);
-    return s;
 }
 
-void tcx_screen_dump(void *opaque, const char *filename)
+static void tcx_screen_dump(void *opaque, const char *filename)
 {
     TCXState *s = opaque;
     FILE *f;
diff --git a/hw/vga.c b/hw/vga.c
index 49e5b21..a712790 100644
--- a/hw/vga.c
+++ b/hw/vga.c
@@ -146,6 +146,8 @@
 VGAState *vga_state;
 int vga_io_memory;
 
+static void vga_screen_dump(void *opaque, const char *filename);
+
 static uint32_t vga_ioport_read(void *opaque, uint32_t addr)
 {
     VGAState *s = opaque;
@@ -1482,9 +1484,9 @@
 #define GMODE_GRAPH    1
 #define GMODE_BLANK 2 
 
-void vga_update_display(void)
+static void vga_update_display(void *opaque)
 {
-    VGAState *s = vga_state;
+    VGAState *s = (VGAState *)opaque;
     int full_update, graphic_mode;
 
     if (s->ds->depth == 0) {
@@ -1532,9 +1534,9 @@
 }
 
 /* force a full display refresh */
-void vga_invalidate_display(void)
+static void vga_invalidate_display(void *opaque)
 {
-    VGAState *s = vga_state;
+    VGAState *s = (VGAState *)opaque;
     
     s->last_width = -1;
     s->last_height = -1;
@@ -1698,6 +1700,8 @@
     s->get_bpp = vga_get_bpp;
     s->get_offsets = vga_get_offsets;
     s->get_resolution = vga_get_resolution;
+    graphic_console_init(s->ds, vga_update_display, vga_invalidate_display,
+                         vga_screen_dump, s);
     /* XXX: currently needed for display */
     vga_state = s;
 }
@@ -1854,13 +1858,13 @@
 
 /* save the vga display in a PPM image even if no display is
    available */
-void vga_screen_dump(const char *filename)
+static void vga_screen_dump(void *opaque, const char *filename)
 {
-    VGAState *s = vga_state;
+    VGAState *s = (VGAState *)opaque;
     DisplayState *saved_ds, ds1, *ds = &ds1;
     
     /* XXX: this is a little hackish */
-    vga_invalidate_display();
+    vga_invalidate_display(s);
     saved_ds = s->ds;
 
     memset(ds, 0, sizeof(DisplayState));
@@ -1871,7 +1875,7 @@
 
     s->ds = ds;
     s->graphic_mode = -1;
-    vga_update_display();
+    vga_update_display(s);
     
     if (ds->data) {
         ppm_save(filename, ds->data, vga_save_w, vga_save_h, 
diff --git a/monitor.c b/monitor.c
index 6b98cf1..3078b1d 100644
--- a/monitor.c
+++ b/monitor.c
@@ -356,7 +356,7 @@
 
 static void do_screen_dump(const char *filename)
 {
-    vga_screen_dump(filename);
+    vga_hw_screen_dump(filename);
 }
 
 static void do_log(const char *items)
diff --git a/sdl.c b/sdl.c
index d53f3e9..b8c82fd 100644
--- a/sdl.c
+++ b/sdl.c
@@ -314,8 +314,8 @@
         if (!gui_saved_grab)
             sdl_grab_end();
     }
-    vga_invalidate_display();
-    vga_update_display();
+    vga_hw_invalidate();
+    vga_hw_update();
 }
 
 static void sdl_refresh(DisplayState *ds)
@@ -328,8 +328,7 @@
         sdl_update_caption();
     }
 
-    if (is_active_console(vga_console)) 
-        vga_update_display();
+    vga_hw_update();
 
     while (SDL_PollEvent(ev)) {
         switch (ev->type) {
@@ -352,10 +351,7 @@
                         break;
                     case 0x02 ... 0x0a: /* '1' to '9' keys */ 
                         console_select(keycode - 0x02);
-                        if (is_active_console(vga_console)) {
-                            /* tell the vga console to redisplay itself */
-                            vga_invalidate_display();
-                        } else {
+                        if (!is_graphic_console()) {
                             /* display grab if going to a text console */
                             if (gui_grab)
                                 sdl_grab_end();
@@ -365,7 +361,7 @@
                     default:
                         break;
                     }
-                } else if (!is_active_console(vga_console)) {
+                } else if (!is_graphic_console()) {
                     int keysym;
                     keysym = 0;
                     if (ev->key.keysym.mod & (KMOD_LCTRL | KMOD_RCTRL)) {
@@ -420,7 +416,7 @@
                     }
                 }
             }
-            if (is_active_console(vga_console)) 
+            if (is_graphic_console()) 
                 sdl_process_key(&ev->key);
             break;
         case SDL_QUIT:
diff --git a/vl.c b/vl.c
index 3a99cbd..ed59988 100644
--- a/vl.c
+++ b/vl.c
@@ -137,7 +137,6 @@
 #endif
 int graphic_depth = 15;
 int full_screen = 0;
-TextConsole *vga_console;
 CharDriverState *serial_hds[MAX_SERIAL_PORTS];
 CharDriverState *parallel_hds[MAX_PARALLEL_PORTS];
 #ifdef TARGET_I386
@@ -2994,7 +2993,7 @@
 
 static void dumb_refresh(DisplayState *ds)
 {
-    vga_update_display();
+    vga_hw_update();
 }
 
 void dumb_display_init(DisplayState *ds)
@@ -5123,8 +5122,6 @@
 #endif
     }
 
-    vga_console = graphic_console_init(ds);
-    
     monitor_hd = qemu_chr_open(monitor_device);
     if (!monitor_hd) {
         fprintf(stderr, "qemu: could not open monitor device '%s'\n", monitor_device);
diff --git a/vl.h b/vl.h
index ada0788..0c6f013 100644
--- a/vl.h
+++ b/vl.h
@@ -254,10 +254,19 @@
 typedef struct DisplayState DisplayState;
 typedef struct TextConsole TextConsole;
 
-extern TextConsole *vga_console;
+typedef void (*vga_hw_update_ptr)(void *);
+typedef void (*vga_hw_invalidate_ptr)(void *);
+typedef void (*vga_hw_screen_dump_ptr)(void *, const char *);
 
-TextConsole *graphic_console_init(DisplayState *ds);
-int is_active_console(TextConsole *s);
+TextConsole *graphic_console_init(DisplayState *ds, vga_hw_update_ptr update,
+                                  vga_hw_invalidate_ptr invalidate,
+                                  vga_hw_screen_dump_ptr screen_dump,
+                                  void *opaque);
+void vga_hw_update(void);
+void vga_hw_invalidate(void);
+void vga_hw_screen_dump(const char *filename);
+
+int is_graphic_console(void);
 CharDriverState *text_console_init(DisplayState *ds);
 void console_select(unsigned int index);
 
@@ -673,9 +682,6 @@
 int vga_initialize(PCIBus *bus, DisplayState *ds, uint8_t *vga_ram_base, 
                    unsigned long vga_ram_offset, int vga_ram_size,
                    unsigned long vga_bios_offset, int vga_bios_size);
-void vga_update_display(void);
-void vga_invalidate_display(void);
-void vga_screen_dump(const char *filename);
 
 /* cirrus_vga.c */
 void pci_cirrus_vga_init(PCIBus *bus, DisplayState *ds, uint8_t *vga_ram_base, 
@@ -844,11 +850,8 @@
 void lance_init(NICInfo *nd, int irq, uint32_t leaddr, uint32_t ledaddr);
 
 /* tcx.c */
-void *tcx_init(DisplayState *ds, uint32_t addr, uint8_t *vram_base,
+void tcx_init(DisplayState *ds, uint32_t addr, uint8_t *vram_base,
 	       unsigned long vram_offset, int vram_size, int width, int height);
-void tcx_update_display(void *opaque);
-void tcx_invalidate_display(void *opaque);
-void tcx_screen_dump(void *opaque, const char *filename);
 
 /* slavio_intctl.c */
 void *slavio_intctl_init();
@@ -976,9 +979,7 @@
 void smc91c111_init(NICInfo *, uint32_t, void *, int);
 
 /* pl110.c */
-void *pl110_init(DisplayState *ds, uint32_t base, void *pic, int irq);
-void pl110_update_display(void *opaque);
-void pl110_invalidate_display(void *opaque);
+void *pl110_init(DisplayState *ds, uint32_t base, void *pic, int irq, int);
 
 #endif /* defined(QEMU_TOOL) */