From: Jean Guyader Date: Tue, 9 Dec 2008 01:38:15 +0000 (+0000) Subject: - Direct mapping of the emulated framebuffer on the intel if both card option X-Git-Url: http://xenbits.xensource.com/gitweb?a=commitdiff_plain;h=2903900da717f843857b0aed22270ca2237bcb35;p=xenclient%2Fioemu.git - Direct mapping of the emulated framebuffer on the intel if both card option are compatible. - Force the intel graphic card to linear mode when we do a fullscreen switching. --- diff --git a/console.h b/console.h index a0887d19..9322c65b 100644 --- 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 diff --git a/hw/vga.c b/hw/vga.c index 152a7a63..371362b2 100644 --- 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 b77aa423..2ec6a243 100644 --- a/intel.c +++ b/intel.c @@ -1,5 +1,6 @@ #include #include +#include #include #include #include @@ -24,26 +25,29 @@ #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); }