Write the file into xenstore at /local/domain/domid/screenshot.
"done" is written when the screenshot is ready.
The screenshot is a binary ppm file.
void vga_hw_update(void);
void vga_hw_invalidate(void);
void vga_hw_screen_dump(const char *filename);
+void vga_take_screenshot(const char *filename, DisplayState *ds);
int is_graphic_console(void);
CharDriverState *text_console_init(DisplayState *ds, const char *p);
/* intel.c */
void intel_display_init(DisplayState *ds, const char *arg);
void intel_focus(int focus);
+void intel_take_screenshot(const char *filename);
#endif
struct dom0_driver_xs_info info;
dom0_driver_read_xs_info(&info, DOM0_MOUSE);
- if (dom0_driver_xs_read_dom0("natif") != info.domid)
+ if (!vga_passthrough &&
+ dom0_driver_xs_read_dom0("natif") != info.domid)
intel_focus(!grab);
}
}
if (info.state == 1 && blank == 2)
{
sleep(1);
- intel_focus(info.domid == domid);
+ if (!vga_passthrough)
+ intel_focus(info.domid == domid);
}
}
}
s->ds = saved_ds;
}
+
+void vga_take_screenshot(const char *filename, DisplayState *ds)
+{
+ ppm_save(filename, ds->data, ds->width, ds->height, ds->linesize);
+}
#define TileW 128
#define TileH 8
-#define TilePitch 16
-#define REG_DR_DSPASURF 0x7019C
-#define REG_DR_DSPACNTR 0x70180
+#define REG_DR_DSPASURF 0x7019C
+#define REG_DR_DSPACNTR 0x70180
+#define REG_DR_DSPASTRIDE 0x70188
+
+extern int vga_passthrough;
static int display = 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 inline unsigned int intel_get_reg(unsigned int reg)
return (y * ds->width + x) * 4;
}
-static inline void intel_blit_tile(DisplayState *ds, int x, int y)
+static inline 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));
{
to = toffset + solid_line[i] * TileW * 4;
o = offset + solid_line[i] * ds->width * 4;
- memcpy(&buff[to], &ds->data[o], TileW * 4);
+ copy(&buff[to], &ds->data[o], TileW * 4);
}
toffset = to = intel_get_tiled_offset(x, y);
o = offset + dashed_line[i] * ds->width * 4 + 16 * 4;
for (j = 0; j < 4 ; j++)
{
- memcpy(&buff[to], &ds->data[o], 16 * 4);
+ copy(&buff[to], &ds->data[o], 16 * 4);
to += 16 * 4;
o -= 16 * 4;
- memcpy(&buff[to], &ds->data[o], 16 * 4);
+ copy(&buff[to], &ds->data[o], 16 * 4);
to += 16 * 4;
o += 48 * 4;
}
for (i = yt; i < ht; i++)
for (j = xt; j < wt; j++)
- if (j >= 0 && j < 10 && i >= 0 && i < 100 &&
+ if (j >= 0 && j < (TileX / TileW) && i >= 0 && i < (TileY / TileH) &&
(i * TileH) < ds->height && (j * TileW) < ds->width)
- intel_blit_tile(ds, j, i);
+ intel_blit_tile(ds, 0, j, i);
}
static void intel_update(DisplayState *ds, int x, int y, int w, int h)
static void intel_refresh(DisplayState *ds)
{
+ if (intel_get_reg(REG_DR_DSPASTRIDE) == 0x1000)
+ {
+ TilePitch = 8;
+ TileX = 1024;
+ TileY = 768;
+ }
+ else
+ {
+ TilePitch = 16;
+ TileX = 1280;
+ TileY = 800;
+ }
+
vga_hw_update();
}
tab = solid_line;
while (arg && *arg)
{
- tab[0] = strtol(arg, next, 10);
+ tab[0] = strtol(arg, &next, 10);
tab[1] = -1;
INTEL_DEBUG("solid/dashed line %d\n", *tab);
if (!next || !*next)
INTEL_DEBUG("unknow separator %c for intel arguement\n", *next);
exit (2);
}
+ arg = next + 1;
}
}
+void intel_take_screenshot(const char *filename)
+{
+ int i,j = 0;
+ FILE *fd;
+ struct DisplayState ds;
+ uint8_t *d;
+ uint32_t p;
+
+ INTEL_DEBUG("Take a screenshot %s\n", filename);
+
+ intel_refresh(&ds);
+
+ fd = fopen(filename, "w");
+ fprintf(fd, "P6\n%d %d\n%d\n", TileX, TileY, 255);
+ INTEL_DEBUG("screenshot %d,%d\n", TileX, TileY);
+
+ 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);
+
+ for (j = 0; j < TileY / TileH; j++)
+ for (i = 0; i < TileX / TileW; i++)
+ intel_blit_tile(&ds, 1, i, j);
+
+ d = ds.data;
+ for (j = 0; j < TileY; j++)
+ for (i = 0; i < TileX; i++)
+ {
+ p = *(uint32_t *)d;
+ fputc((p >> 16) & 0xff, fd);
+ fputc((p >> 8) & 0xff, fd);
+ fputc((p) & 0xff, fd);
+ d += 4;
+ }
+ fclose(fd);
+}
+
void intel_display_init(DisplayState *ds, const char *arg)
{
+ INTEL_DEBUG("\n");
+
+ xenstore_watch_screenshot_node();
+
intel_parse_arg(arg);
intel_init_mapping();
INTEL_DEBUG("Frambuffer is at 0x%x\n", intel_get_reg(REG_DR_DSPASURF));
ds->shared_buf = 0;
- ds->data = NULL;
ds->width = 640;
ds->height = 400;
ds->linesize = 640 * 4;
ds->depth = 32;
+ ds->data = malloc(ds->height * ds->linesize);
lds = ds;
ds->dpy_update = intel_update;
#endif
/* xenstore.c */
-typedef void (*xenstore_callback) (const char *token);
-void xenstore_watch_callback(const char *token, xenstore_callback fptr);
+typedef void (*xenstore_callback) (const char *token, void *opaque);
+int xenstore_watch_screenshot_node(DisplayState *ds);
+void xenstore_watch_callback(const char *token, xenstore_callback fptr, void *opaque);
void xenstore_parse_domain_config(int domid);
int xenstore_fd(void);
void xenstore_process_event(void *opaque);
{ "localtime", 0, QEMU_OPTION_localtime },
{ "std-vga", 0, QEMU_OPTION_std_vga },
{ "videoram", HAS_ARG, QEMU_OPTION_videoram },
- { "intel", 0, QEMU_OPTION_intel },
+ { "intel", HAS_ARG, QEMU_OPTION_intel },
{ "echr", HAS_ARG, QEMU_OPTION_echr },
{ "monitor", HAS_ARG, QEMU_OPTION_monitor },
{ "domain-name", 1, QEMU_OPTION_domainname },
/* terminal init */
memset(&display_state, 0, sizeof(display_state));
+ xenstore_watch_screenshot_node(&display_state);
+
#ifdef CONFIG_STUBDOM
if (xenfb_pv_display_init(ds) == 0) {
} else
char *xenstore_read_dom0_driver(const char *key);
int xenstore_write_dom0_driver(const char *key, int val);
-char *xenstore_dom_read(int domid, char *key, unsigned long *len);
+char *xenstore_dom_read(int domid, char *key, unsigned int *len);
int xenstore_dom_write(int domid, char *key, char *value);
int *xenstore_get_domids(int *len);
#include "pc.h"
#include "qemu-timer.h"
#include "qemu-xen.h"
+#include "console.h"
+
+extern int vga_passthrough;
struct xs_handle *xsh = NULL;
static char *media_filename[MAX_DRIVES+1];
{
char *token;
xenstore_callback cb;
+ void *opaque;
};
static struct xenstore_watch_cb_t *xenstore_watch_callbacks = NULL;
-void xenstore_watch_callback(const char *token, xenstore_callback fptr)
+void xenstore_watch_callback(const char *token, xenstore_callback fptr, void *opaque)
{
int i = 0;
(i + 2) * sizeof (struct xenstore_watch_cb_t));
xenstore_watch_callbacks[i].token = strdup(token);
xenstore_watch_callbacks[i].cb = fptr;
+ xenstore_watch_callbacks[i].opaque = opaque;
xenstore_watch_callbacks[i + 1].token = NULL;
}
if (!vec)
return;
- for (i = 0; xenstore_watch_callbacks[i].token; i++)
+ for (i = 0; xenstore_watch_callbacks && xenstore_watch_callbacks[i].token; i++)
if (!strcmp(vec[XS_WATCH_TOKEN], xenstore_watch_callbacks[i].token))
- xenstore_watch_callbacks[i].cb(vec[XS_WATCH_TOKEN]);
+ xenstore_watch_callbacks[i].cb(vec[XS_WATCH_TOKEN],
+ xenstore_watch_callbacks[i].opaque);
if (!strcmp(vec[XS_WATCH_TOKEN], "logdirty")) {
xenstore_process_logdirty_event();
return ret;
}
-char *xenstore_dom_read(int domid, char *key, unsigned long *len)
+char *xenstore_dom_read(int domid, char *key, unsigned int *len)
{
char *buf = NULL, *path = NULL, *value = NULL;
free(buf);
free(path);
}
+
+void xenstore_screenshot(const char *token, void *opaque)
+{
+ char *filename;
+ unsigned int len;
+ DisplayState *ds = (DisplayState *)opaque;
+
+ filename = xenstore_dom_read(domid, "screenshot", &len);
+ if (!filename)
+ return;
+
+ if (!strcmp(filename, "done"))
+ {
+ free(filename);
+ return;
+ }
+
+ fprintf(stderr, "screenshot %s\n", filename);
+
+ if (vga_passthrough)
+ intel_take_screenshot(filename);
+ else
+ vga_take_screenshot(filename, ds);
+
+ free(filename);
+ xenstore_dom_write(domid, "screenshot", "done");
+}
+
+int xenstore_watch_screenshot_node(DisplayState *ds)
+{
+ char *path;
+ char *buf = NULL;
+ int ret = 0;
+
+ path = xs_get_domain_path(xsh, domid);
+ if (!path) {
+ fprintf(logfile, "xs_get_domain_path() failed.\n");
+ goto out;
+ }
+ if (pasprintf(&buf, "%s/screenshot", path) == -1) {
+ fprintf(logfile, "pasprintf failed to get path.\n");
+ goto out;
+ }
+ xenstore_watch_callback("screenshot", xenstore_screenshot, ds);
+ fprintf(stderr, "screenshot watch node %s\n", buf);
+ ret = xs_watch(xsh, buf, "screenshot");
+ out:
+ free(buf);
+ free(path);
+ return ret;
+}