]> xenbits.xensource.com Git - xenclient/ioemu.git/commitdiff
- Direct mapping of the emulated framebuffer on the intel if both card option
authorJean Guyader <jean.guyader@eu.citrix.com>
Tue, 9 Dec 2008 01:38:15 +0000 (01:38 +0000)
committerJean Guyader <jean.guyader@eu.citrix.com>
Tue, 9 Dec 2008 01:38:15 +0000 (01:38 +0000)
are compatible.
 - Force the intel graphic card to linear mode when we do a fullscreen
switching.

console.h
hw/vga.c
intel.c

index a0887d1955fa97b8aad8031d532a7dfaf4ecdd41..9322c65b54150976d12decf8d284e790a8436685 100644 (file)
--- a/console.h
+++ b/console.h
@@ -173,6 +173,10 @@ void dom0_driver_init(const char *position);
 /* intel.c */
 void intel_display_init(DisplayState *ds);
 void intel_focus(int focus);
+int intel_getfocus(void);
 void intel_take_screenshot(const char *filename);
+extern uint32_t guest_framebuffer;
+void unset_vga_acc(void);
+void set_vga_acc(void);
 
 #endif
index 152a7a630f4254e06129cb53ad0924672675eb7b..371362b2c7a69bcf0862324ada92c152d2badf3d 100644 (file)
--- a/hw/vga.c
+++ b/hw/vga.c
@@ -154,9 +154,20 @@ static const uint32_t dmask4[4] = {
 static uint32_t expand4[256];
 static uint16_t expand2[256];
 static uint8_t expand4to8[16];
+static VGAState *vga_state;
 
 static void vga_screen_dump(void *opaque, const char *filename);
 
+void unset_vga_acc(void)
+{
+    set_vram_mapping(vga_state, vga_state->stolen_vram_addr, vga_state->stolen_vram_addr + video_ram_size);
+}
+
+void set_vga_acc(void)
+{
+    set_vram_mapping(vga_state, vga_state->lfb_addr, vga_state->lfb_end);
+}
+
 static uint32_t vga_ioport_read(void *opaque, uint32_t addr)
 {
     VGAState *s = opaque;
@@ -472,7 +483,7 @@ static void vbe_ioport_write_data(void *opaque, uint32_t addr, uint32_t val)
                 !(s->vbe_regs[VBE_DISPI_INDEX_ENABLE] & VBE_DISPI_ENABLED)) {
                 int h, shift_control;
                 static int firsttime=0;
-                
+
                 if(s->map_addr != s->lfb_addr || s->map_end != s->lfb_end) {
                     set_vram_mapping(s, s->lfb_addr, s->lfb_end);
                     s->map_addr = s->lfb_addr;
@@ -1445,6 +1456,7 @@ static void vga_draw_graphic(VGAState *s, int full_update)
     ds_depth = s->ds->depth;
     depth = s->get_bpp(s);
     if (s->ds->dpy_resize_shared) {
+        guest_framebuffer = s->lfb_addr + (s->start_addr * 4);
         if (s->line_offset != s->last_line_offset ||
             disp_width != s->last_width ||
             height != s->last_height ||
@@ -1468,6 +1480,9 @@ static void vga_draw_graphic(VGAState *s, int full_update)
         s->last_height = height;
         full_update = 1;
     }
+    /* XXX this works only if intel.c is the frontend */
+    if (s->ds->shared_buf)
+        return;
 
     s->rgb_to_pixel =
         rgb_to_pixel_dup_table[get_depth_index(s->ds)];
@@ -1936,7 +1951,7 @@ static int vga_load(QEMUFile *f, void *opaque, int version_id)
             if (s->stolen_vram_addr || s->map_addr) {
                 xen_vga_vram_map(s->map_addr ? s->map_addr : s->stolen_vram_addr, 0);
             } else {
-                qemu_get_buffer(f, s->vram_ptr, s->vram_size); 
+                qemu_get_buffer(f, s->vram_ptr, s->vram_size);
                 xen_vga_populate_vram(s->lfb_addr);
             }
         }
@@ -2261,6 +2276,7 @@ void vga_common_init(VGAState *s, DisplayState *ds, uint8_t *vga_ram_base,
                          vga_screen_dump, NULL, s);
 
     vga_bios_init(s);
+    vga_state = s;
 }
 
 /* used by both ISA and PCI */
diff --git a/intel.c b/intel.c
index b77aa4236a3a0a33a1ce34da39b9f12b6460aabe..2ec6a243425abcd369b34f69efcb438266279398 100644 (file)
--- a/intel.c
+++ b/intel.c
@@ -1,5 +1,6 @@
 #include <stdio.h>
 #include <stdlib.h>
+#include <stdint.h>
 #include <sys/mman.h>
 #include <sys/types.h>
 #include <sys/stat.h>
 #define REG_DR_PIPEACONF       0x70008
 
 extern int                      vga_passthrough;
+uint32_t                        guest_framebuffer;
 
 static int                      display = 0;
 
 static int                      mmio_fd = -1;
 static int                      mem_fd = -1;
-static unsigned char            *intel_mem = NULL;
-static unsigned char            *intel_mmio = NULL;
+static uint8_t                  *intel_mem = NULL;
+static uint8_t                  *intel_mmio = NULL;
 static int                      intel_force_full_update = 0;
 static int                      intel_have_focus;
-static int                      solid_line[8];
-static int                      dashed_line[8];
 static int                      TilePitch = 16;
 static int                      TileX = 1280;
 static int                      TileY = 1024;
 static DisplayState             *lds = NULL;
-static unsigned char *old_data = NULL;
+static uint8_t                  *old_data = NULL;
+static uint32_t                 intel_fb_base, intel_mmio_base;
+static uint32_t                 map_s, map_d, map_size;
+static int                      refresh;
 
 static void set_data_mappings(void);
-static void unset_data_mappings(void);
+static void unset_data_mappings(int mapping);
 static void set_data_pointer(void);
+static void intel_resize(DisplayState *ds, int w, int h);
 
 static inline unsigned int intel_get_reg(unsigned int reg)
 {
@@ -75,74 +79,6 @@ static inline unsigned int intel_get_offset(DisplayState *ds, int x, int y)
     return (y * ds->width + x) * 4;
 }
 
-static void intel_blit_tile(DisplayState *ds, int read, int x, int y)
-{
-    typedef void (*copy_fptr) (uint8_t *, uint8_t *, int);
-    void        copy_read(uint8_t *tbuff, uint8_t *buff, int size)
-    {
-        memcpy(buff, tbuff, size);
-    }
-    void        copy_write(uint8_t *tbuff, uint8_t *buff, int size)
-    {
-        memcpy(tbuff, buff, size);
-    }
-    unsigned int        toffset, offset, to, o;
-    unsigned char       *buff;
-    int                 i, j;
-    copy_fptr           copy = NULL;
-
-    if (read)
-        copy = copy_read;
-    else
-        copy = copy_write;
-
-    buff = (unsigned char *)(intel_mem + intel_get_reg(REG_DR_DSPASURF));
-
-    /* Copy the solid lines */
-    toffset = intel_get_tiled_offset(x, y);
-    offset = intel_get_offset(ds, x * TileW, y * TileH);
-    for (i = 0; solid_line[i] != -1; i++)
-    {
-        to = toffset + solid_line[i] * TileW * 4;
-        o = offset + solid_line[i] * ds->width * 4;
-        copy(&buff[to], &ds->data[o], TileW * 4);
-    }
-
-    toffset = to = intel_get_tiled_offset(x, y);
-    offset = o = intel_get_offset(ds, x * TileW, y * TileH);
-    for (i = 0; dashed_line[i] != -1; i++)
-    {
-        to = toffset + dashed_line[i] * TileW * 4;
-        o = offset + dashed_line[i] * ds->width * 4 + 16 * 4;
-        for (j = 0; j < 4 ; j++)
-        {
-            copy(&buff[to], &ds->data[o], 16 * 4);
-            to += 16 * 4;
-            o -= 16 * 4;
-            copy(&buff[to], &ds->data[o], 16 * 4);
-            to += 16 * 4;
-            o += 48 * 4;
-        }
-    }
-}
-
-static void intel_update_tiled(DisplayState *ds, int x, int y, int w, int h)
-{
-    int i,j;
-    int xt, yt, wt, ht;
-
-    xt = x / TileW - 1;
-    yt = y / TileH - 1;
-    wt = w / TileW + xt + 3;
-    ht = h / TileH + yt + 3;
-
-    for (i = yt; i < ht; i++)
-        for (j = xt; j < wt; j++)
-            if (j >= 0 && j < (TileX / TileW) && i >= 0 && i < (TileY / TileH) &&
-                (i * TileH) < ds->height && (j * TileW) < ds->width)
-                intel_blit_tile(ds, 0, j, i);
-}
-
 static void intel_update_linear(DisplayState *ds, int x, int y, int w, int h)
 {
     int i, bpp = lds->depth / 8;
@@ -158,14 +94,14 @@ static void intel_update_linear(DisplayState *ds, int x, int y, int w, int h)
     }
 }
 
-static void intel_force_linear(void)
+static void intel_force_linear(int linesize)
 {
     unsigned int *dspacntr = (unsigned int *)(intel_mmio + REG_DR_DSPACNTR);
     unsigned int *pipeaconf = (unsigned int *)(intel_mmio + REG_DR_PIPEACONF);
     unsigned int *dspasurf = (unsigned int *)(intel_mmio + REG_DR_DSPASURF);
     unsigned int *dspastride = (unsigned int *)(intel_mmio + REG_DR_DSPASTRIDE);
     unsigned int surf, pipea;
-   
+
 
     INTEL_DEBUG("DSPASURF CTRL: 0x%x\n", intel_get_reg(REG_DR_DSPACNTR));
 
@@ -180,35 +116,152 @@ static void intel_force_linear(void)
     *dspasurf = 0x00000000;
     *pipeaconf |= pipea;
 
-    sleep(1);
-    memset(intel_mem + surf, 0, (*dspastride) * TileY);
+    usleep(20000);
 
     *pipeaconf &= ~(0x3 << 18);
     /* Enable surface linear mode */
     *dspacntr &= ~(1 << 10);
+    if (linesize) *dspastride = linesize;
     *dspasurf = surf;
     *dspacntr |= (1 << 31);
     *pipeaconf |= pipea;
+
+    usleep(20000);
 }
 
 static void intel_update(DisplayState *ds, int x, int y, int w, int h)
 {
-    if (intel_have_focus) {
-        if (!old_data)
-            intel_update_linear(ds, x, y, w, h);
+    if (intel_have_focus && !old_data && !map_size)
+        intel_update_linear(ds, x, y, w, h);
+}
+
+static void set_fb_mapping(void)
+{
+    int rc;
+    unsigned long nr_pfn;
+
+    unset_vga_acc();
+    fprintf(stderr, "set_fb_mapping: %x %x\n", (intel_fb_base + intel_get_reg(REG_DR_DSPASURF)), guest_framebuffer);
+    nr_pfn = (lds->linesize * lds->height) >> TARGET_PAGE_BITS;
+
+    rc = xc_domain_memory_mapping(xc_handle,
+            domid,
+            (guest_framebuffer >> TARGET_PAGE_BITS),
+            ((intel_fb_base + intel_get_reg(REG_DR_DSPASURF)) >> TARGET_PAGE_BITS),
+            nr_pfn,
+            DPCI_ADD_MAPPING);
+    if (rc) {
+        fprintf(stderr, "xc_domain_memory_mapping failed %d\n", rc);
+        return;
+    }
+    map_s = ((intel_fb_base + intel_get_reg(REG_DR_DSPASURF)) >> TARGET_PAGE_BITS);
+    map_d = (guest_framebuffer >> TARGET_PAGE_BITS);
+    map_size = nr_pfn;
+}
+
+static void unset_fb_mapping(void)
+{
+    int rc;
+
+    fprintf(stderr, "unset_fb_mapping: %x %x\n", map_d, map_s);
+
+    rc = xc_domain_memory_mapping(xc_handle,
+            domid,
+            map_d,
+            map_s,
+            map_size,
+            DPCI_REMOVE_MAPPING);
+    if (rc) {
+        fprintf(stderr, "xc_domain_memory_mapping failed %d\n", rc);
+        return;
+    }
+
+    set_vga_acc();
+    map_s = 0;
+    map_d = 0;
+    map_size = 0;
+}
+
+static void intel_setdata(DisplayState *ds, void *pixels)
+{
+    ds->data = pixels;
+    if (map_size)
+        unset_fb_mapping();
+    set_fb_mapping();
+}
+
+static void intel_resize_shared(DisplayState *ds, int w, int h, int depth, int linesize, void *pixels)
+{
+    if (!intel_have_focus) {
+        intel_resize(ds, w, h);
+        return;
+    }
+    if (depth == 32 && w == TileX && h == TileY)
+        ds->shared_buf = 1;
+    else
+        ds->shared_buf = 0;
+    if (ds->shared_buf) {
+        INTEL_DEBUG("intel_resize_shared: enable shared buffer, linesize %d\n", linesize);
+        ds->width = w;
+        ds->height = h;
+        ds->depth = 32;
+        ds->linesize = linesize;
+        /* adjust linesize */
+        intel_force_linear(linesize);
+        set_data_mappings();
+        if (refresh) {
+            memcpy(ds->data, pixels, ds->linesize * ds->height);
+            refresh = 0;
+        }
+        intel_setdata(ds, pixels);
+    } else {
+        intel_resize(ds, w, h);
     }
 }
 
 static void intel_resize(DisplayState *ds, int w, int h)
 {
+    int old_linesize = ds->linesize;
+    INTEL_DEBUG("intel_resize: no shared buffer, linesize=%d\n", ds->linesize);
     ds->width = w;
     ds->height = h;
     ds->depth = 32;
     ds->linesize = intel_get_pitch();
-    if (!old_data)
-        ds->data = realloc(ds->data, h * ds->linesize);
-    else
+    if (map_size) {
+        unset_fb_mapping();
+        unset_data_mappings(1);
+    }
+    if (intel_have_focus && !is_linear()) {
+        intel_force_linear(0);
+    }
+    ds->shared_buf = 0;
+    if (intel_have_focus && !old_data && w * h <= TileX * TileY)
+        set_data_mappings();
+    else if (intel_have_focus && old_data && w * h > TileX * TileY)
+        unset_data_mappings(0);
+    if (!old_data) {
+        qemu_free(ds->data);
+        ds->data = qemu_mallocz(h * ds->linesize);
+    } else {
+        INTEL_DEBUG("intel_resize: set_data_pointer\n");
         set_data_pointer();
+    }
+    if (intel_have_focus)
+        memset((unsigned char *)(intel_mem + intel_get_reg(REG_DR_DSPASURF)), 0x0, TileX * TileY);
+    if (refresh) {
+        if (old_data) {
+            unsigned char *s, *d;
+            int i;
+            s = old_data;
+            d = ds->data;
+            for (i = 0; i < ds->height; i++) {
+                memcpy(d, s, ds->width * 4);
+                s += old_linesize;
+                d += ds->linesize;
+            }
+        }
+        refresh = 0;
+    }
 }
 
 static void intel_refresh(DisplayState *ds)
@@ -220,7 +273,6 @@ static void intel_init_mapping(void)
 {
     struct pci_access   *pci_bus;
     struct pci_dev      *pci_dev;
-    uint32_t            intel_fb_base, intel_mmio_base;
 
     mmio_fd = open("/dev/mem", O_RDWR);
     if (mmio_fd == -1)
@@ -273,16 +325,42 @@ static void set_data_pointer(void)
 
 static void set_data_mappings(void)
 {
-    old_data = lds->data;
+    INTEL_DEBUG("set_data_mappings\n");
+    if (!old_data)
+        old_data = lds->data;
     set_data_pointer();
-    memcpy(lds->data, old_data, lds->linesize * lds->height);
 }
 
-static void unset_data_mappings(void)
+static void unset_data_mappings(int mapping)
+{
+    if (!old_data)
+        return;
+    if (mapping) {
+        uint8_t * buffer_pointer = lds->data;
+        lds->data = old_data;
+        old_data = NULL;
+        lds->data = realloc(lds->data, lds->linesize * lds->height);
+        memcpy(lds->data,
+                (unsigned char *)(intel_mem + intel_get_reg(REG_DR_DSPASURF)),
+                lds->linesize * lds->height);
+        memcpy(buffer_pointer,
+                lds->data,
+                lds->linesize * lds->height);
+    } else {
+        uint8_t * buffer_pointer = lds->data;
+        lds->data = old_data;
+        old_data = NULL;
+        lds->data = realloc(lds->data, lds->linesize * lds->height);
+        memcpy(lds->data,
+                buffer_pointer,
+                lds->linesize * lds->height);
+    }
+    INTEL_DEBUG("unset_data_mappings %d: success\n", mapping);
+}
+
+int intel_getfocus(void)
 {
-    lds->data = old_data;
-    old_data = NULL;
-    lds->data = realloc(lds->data, lds->linesize * lds->height);
+    return intel_have_focus;
 }
 
 void intel_focus(int focus)
@@ -290,49 +368,36 @@ void intel_focus(int focus)
     if (intel_have_focus == focus)
         return;
 
+    INTEL_DEBUG("intel_focus %d\n", focus);
+    intel_have_focus = focus;
     if (focus) {
         if (!is_linear()) {
             if (intel_get_reg(REG_DR_DSPASTRIDE) == 0x1000) {
                 TilePitch = 8;
                 TileX = 1024;
                 TileY = 768;
+                INTEL_DEBUG("Resolution 1024x768\n");
             } else {
                 TilePitch = 16;
                 TileX = 1280;
                 TileY = 800;
+                INTEL_DEBUG("Resolution 1280x800\n");
             }
-            intel_force_linear();
         }
-        set_data_mappings();
-    } else if (old_data) {
-        unset_data_mappings();
-    }
-    intel_have_focus = focus;
-}
-
-static void intel_parse_arg(const char *arg)
-{
-    int         *tab = NULL;
-    char        *next = NULL;
-    
-    tab = solid_line;
-    while (arg && *arg)
-    {
-        tab[0] = strtol(arg, &next, 10);
-        tab[1] = -1;
-        INTEL_DEBUG("solid/dashed line %d\n", *tab);
-        if (!next || !*next)
-            return;
-        if (*next == ',')
-            tab++;
-        else if (*next == '|')
-            tab = dashed_line;
-        else
-        {
-            INTEL_DEBUG("unknow separator %c for intel arguement\n", *next);
-            exit (2);
+        refresh = 1;
+        lds->dpy_resize_shared = intel_resize_shared;
+        lds->dpy_setdata = intel_setdata;
+        vga_hw_invalidate();
+    } else {
+        if (map_size) {
+            unset_fb_mapping();
+            unset_data_mappings(1);
+        } else if (old_data) {
+            unset_data_mappings(0);
         }
-        arg = next + 1;
+        lds->dpy_resize_shared = NULL;
+        lds->dpy_setdata = NULL;
+        lds->shared_buf = 0;
     }
 }
 
@@ -343,9 +408,9 @@ void intel_take_screenshot(const char *filename)
     unsigned int v;
     int y = 0, x = 0;
 
-    
+
     INTEL_DEBUG("Take a screenshot %s\n", filename);
-    
+
     intel_refresh(lds);
 
     fd = fopen(filename, "w");
@@ -366,30 +431,6 @@ void intel_take_screenshot(const char *filename)
             }
             d1 += lds->linesize;
         }
-    } else {
-        struct DisplayState ds;
-        ds.width = TileX;
-        ds.height = TileY;
-        ds.linesize = 4 * ds.width;
-        ds.depth = 32;
-        ds.data = malloc(ds.height * ds.linesize);
-        memset(ds.data, 0, ds.height * ds.linesize);
-
-        fprintf(fd, "P6\n%d %d\n%d\n", TileX, TileY, 255);
-        for (y = 0; y < TileY / TileH; y++)
-            for (x = 0; x < TileX / TileW; x++)
-                intel_blit_tile(&ds, 1, x, y);
-
-        d1 = ds.data;
-        for (y = 0; y < TileY; y++)
-            for (x = 0; x < TileX; x++)
-            {
-                v = *(uint32_t *)d1;
-                fputc((v >> 16) & 0xff, fd);
-                fputc((v >> 8) & 0xff, fd);
-                fputc((v) & 0xff, fd);
-                d1 += 4;
-            }
     }
     fclose(fd);
 }