#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)
{
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;
}
}
-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));
*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)
{
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)
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)
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;
}
}
unsigned int v;
int y = 0, x = 0;
-
+
INTEL_DEBUG("Take a screenshot %s\n", filename);
-
+
intel_refresh(lds);
fd = fopen(filename, "w");
}
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);
}