xf86-video-intel: 2 commits - tools/virtual.c

Chris Wilson ickle at kemper.freedesktop.org
Mon Sep 2 13:24:57 PDT 2013


 tools/virtual.c |  278 ++++++++++++++++++++++++++++++++++----------------------
 1 file changed, 172 insertions(+), 106 deletions(-)

New commits:
commit 5fed6e24996eb0fcfeec19341ce4103e7e7eb2d8
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date:   Mon Sep 2 21:19:24 2013 +0100

    intel-virtual-output: Perform pixel type conversion from XfixesCursorImage
    
    For whatever reason, Xfixes uses "unsigned long" in its protocol
    definition for the cursor pixels.
    
    Signed-off-by: Chris Wilson <chris at chris-wilson.co.uk>

diff --git a/tools/virtual.c b/tools/virtual.c
index 120d9e8..27d80e8 100644
--- a/tools/virtual.c
+++ b/tools/virtual.c
@@ -88,6 +88,8 @@ struct display {
 	Cursor invisible_cursor;
 	Cursor visible_cursor;
 
+	XcursorImage cursor_image;
+	int cursor_serial;
 	int cursor_x;
 	int cursor_y;
 	int cursor_moved;
@@ -1001,26 +1003,47 @@ static Cursor display_load_invisible_cursor(struct display *display)
 	return XCreatePixmapCursor(display->dpy, bitmap, bitmap, &black, &black, 0, 0);
 }
 
-static void display_load_visible_cursor(struct display *display, XFixesCursorImage *cur)
+static Cursor display_get_visible_cursor(struct display *display)
 {
-	XcursorImage image;
+	if (display->cursor_serial != display->cursor_image.size) {
+		DBG(("%s updating cursor\n", DisplayString(display->dpy)));
+
+		if (display->visible_cursor)
+			XFreeCursor(display->dpy, display->visible_cursor);
 
-	memset(&image, 0, sizeof(image));
-	image.width = cur->width;
-	image.height = cur->height;
-	image.size = image.width;
-	if (image.height > image.size)
-		image.size = image.height;
-	image.xhot = cur->xhot;
-	image.yhot = cur->yhot;
-	image.pixels = (void *)cur->pixels;
+		display->visible_cursor = XcursorImageLoadCursor(display->dpy, &display->cursor_image);
+		display->cursor_serial = display->cursor_image.size;
+	}
+
+	return display->visible_cursor;
+}
+
+static void display_load_visible_cursor(struct display *display, XFixesCursorImage *cur)
+{
+	unsigned long *src; /* XXX deep sigh */
+	XcursorPixel *dst;
+	unsigned n;
+
+	if (cur->width != display->cursor_image.width ||
+	    cur->height != display->cursor_image.height)
+		display->cursor_image.pixels = realloc(display->cursor_image.pixels,
+						       4 * cur->width * cur->height);
+	if (display->cursor_image.pixels == NULL)
+		return;
 
-	if (display->visible_cursor)
-		XFreeCursor(display->dpy, display->visible_cursor);
+	display->cursor_image.width  = cur->width;
+	display->cursor_image.height = cur->height;
+	display->cursor_image.xhot = cur->xhot;
+	display->cursor_image.yhot = cur->yhot;
+	display->cursor_image.size++;
 
-	DBG(("%s updating cursor\n", DisplayString(display->dpy)));
-	display->visible_cursor = XcursorImageLoadCursor(display->dpy, &image);
+	n = cur->width*cur->height;
+	src = cur->pixels;
+	dst = display->cursor_image.pixels;
+	while (n--)
+		*dst++ = *src++;
 
+	DBG(("%s marking cursor changed\n", DisplayString(display->dpy)));
 	display->cursor_moved++;
 	display->cursor_visible += display->cursor != display->invisible_cursor;
 }
@@ -1058,7 +1081,7 @@ static void display_flush_cursor(struct display *display)
 
 	cursor = None;
 	if (display->cursor_visible)
-		cursor = display->visible_cursor;
+		cursor = display_get_visible_cursor(display);
 	if (cursor == None)
 		cursor = display->invisible_cursor;
 	if (cursor != display->cursor) {
commit b955622cc25ab12305a572901a8ed0f23896dab3
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date:   Mon Sep 2 20:45:12 2013 +0100

    intel-virtual-ouptput: Filter and rate-limit cursor events
    
    Make sure we are not responding to cursor motion on other screens, by
    checking for our root window.
    
    Signed-off-by: Chris Wilson <chris at chris-wilson.co.uk>

diff --git a/tools/virtual.c b/tools/virtual.c
index 1beccac..120d9e8 100644
--- a/tools/virtual.c
+++ b/tools/virtual.c
@@ -64,6 +64,7 @@
 struct display {
 	Display *dpy;
 	struct clone *clone;
+	struct context *ctx;
 
 	int damage_event, damage_error;
 	int xfixes_event, xfixes_error;
@@ -144,11 +145,18 @@ struct context {
 	int ndisplay;
 	int nfd;
 
+	int timer_active;
+
 	Atom singleton;
 	char command[1024];
 	int command_continuation;
 };
 
+static inline int is_power_of_2(unsigned long n)
+{
+	return n && ((n & (n - 1)) == 0);
+}
+
 static int xlib_vendor_is_xorg(Display *dpy)
 {
 	const char *const vendor = ServerVendor(dpy);
@@ -249,6 +257,100 @@ can_use_shm(Display *dpy,
 	return has_shm;
 }
 
+static int timerfd(int hz)
+{
+	struct itimerspec it;
+	int fd;
+
+	fd = timerfd_create(CLOCK_MONOTONIC_COARSE, TFD_NONBLOCK);
+	if (fd < 0)
+		fd = timerfd_create(CLOCK_MONOTONIC, TFD_NONBLOCK);
+	if (fd < 0)
+		return -ETIME;
+
+	it.it_interval.tv_sec = 0;
+	it.it_interval.tv_nsec = 1000000000 / hz;
+	it.it_value = it.it_interval;
+	if (timerfd_settime(fd, 0, &it, NULL) < 0) {
+		close(fd);
+		return -ETIME;
+	}
+
+	return fd;
+}
+
+static int context_init(struct context *ctx)
+{
+	struct pollfd *pfd;
+
+	memset(ctx, 0, sizeof(*ctx));
+
+	ctx->pfd = malloc(2*sizeof(struct pollfd));
+	if (ctx->pfd == NULL)
+		return -ENOMEM;
+
+	ctx->clones = malloc(sizeof(struct clone));
+	if (ctx->clones == NULL)
+		return -ENOMEM;
+
+	ctx->display = malloc(sizeof(struct display));
+	if (ctx->display == NULL)
+		return -ENOMEM;
+
+	pfd = memset(&ctx->pfd[ctx->nfd++], 0, sizeof(struct pollfd));
+	pfd->fd = timerfd(60);
+	if (pfd->fd < 0)
+		return pfd->fd;
+	pfd->events = POLLIN;
+
+	return 0;
+}
+
+static void context_enable_timer(struct context *ctx)
+{
+	uint64_t count;
+
+	DBG(("%s timer active? %d\n", __func__, ctx->timer_active));
+
+	if (ctx->timer_active)
+		return;
+
+	read(ctx->timer, &count, sizeof(count));
+	ctx->timer_active = 1;
+}
+
+static int add_fd(struct context *ctx, int fd)
+{
+	struct pollfd *pfd;
+
+	if (fd < 0)
+		return fd;
+
+	if (is_power_of_2(ctx->nfd)) {
+		ctx->pfd = realloc(ctx->pfd, 2*ctx->nfd*sizeof(struct pollfd));
+		if (ctx->pfd == NULL)
+			return -ENOMEM;
+	}
+
+	pfd = memset(&ctx->pfd[ctx->nfd++], 0, sizeof(struct pollfd));
+	pfd->fd = fd;
+	pfd->events = POLLIN;
+	return 0;
+}
+
+
+static void display_mark_flush(struct display *display)
+{
+	DBG(("%s mark flush (flush=%d)\n",
+	     DisplayString(display->dpy), display->flush));
+
+	if (display->flush)
+		return;
+
+	context_enable_timer(display->ctx);
+	display->flush = 1;
+}
+
 static int mode_equal(const XRRModeInfo *a, const XRRModeInfo *b)
 {
 	return (a->width == b->width &&
@@ -660,7 +762,7 @@ static int clone_init_xfer(struct clone *clone)
 	clone->damaged.y1 = clone->src.y;
 	clone->damaged.y2 = clone->src.y + clone->height;
 
-	clone->dst.display->flush = 1;
+	display_mark_flush(clone->dst.display);
 	return 0;
 }
 
@@ -925,6 +1027,8 @@ static void display_load_visible_cursor(struct display *display, XFixesCursorIma
 
 static void display_cursor_move(struct display *display, int x, int y, int visible)
 {
+	DBG(("%s cursor moved (visible=%d, (%d, %d))\n",
+	     DisplayString(display->dpy), visible, x, y));
 	display->cursor_moved++;
 	display->cursor_visible += visible;
 	if (visible) {
@@ -950,7 +1054,7 @@ static void display_flush_cursor(struct display *display)
 	}
 
 	XWarpPointer(display->dpy, None, display->root, 0, 0, 0, 0, x, y);
-	display->flush = 1;
+	display_mark_flush(display);
 
 	cursor = None;
 	if (display->cursor_visible)
@@ -1132,7 +1236,7 @@ static void put_dst(struct clone *c, const XRectangle *clip)
 		c->dst.serial = 0;
 	}
 
-	c->dst.display->flush = 1;
+	display_mark_flush(c->dst.display);
 }
 
 static int clone_paint(struct clone *c)
@@ -1204,10 +1308,17 @@ static void record_callback(XPointer closure, XRecordInterceptData *data)
 	struct context *ctx = (struct context *)closure;
 	int n;
 
+	DBG(("%s\n", __func__));
+
 	if (data->category == XRecordFromServer) {
 		const xEvent *e = (const xEvent *)data->data;
 
-		if (e->u.u.type == MotionNotify) {
+		DBG(("%s -- from server, event type %d, root %ld (ours? %d)\n",
+		     __func__, e->u.u.type, (long)e->u.keyButtonPointer.root,
+		     ctx->display->root == e->u.keyButtonPointer.root));
+
+		if (e->u.u.type == MotionNotify &&
+		    e->u.keyButtonPointer.root == ctx->display->root) {
 			for (n = 0; n < ctx->nclone; n++)
 				clone_move_cursor(&ctx->clones[n],
 						  e->u.keyButtonPointer.rootX,
@@ -1447,11 +1558,6 @@ static int clone_init_depth(struct clone *clone)
 	return 0;
 }
 
-static inline int is_power_of_2(unsigned long n)
-{
-	return n && ((n & (n - 1)) == 0);
-}
-
 static int add_display(struct context *ctx, Display *dpy)
 {
 	struct display *display;
@@ -1479,6 +1585,7 @@ static int add_display(struct context *ctx, Display *dpy)
 	display = memset(&ctx->display[ctx->ndisplay++], 0, sizeof(struct display));
 
 	display->dpy = dpy;
+	display->ctx = ctx;
 
 	display->root = DefaultRootWindow(dpy);
 	display->depth = DefaultDepth(dpy, DefaultScreen(dpy));
@@ -1580,74 +1687,6 @@ static int display_init_damage(struct display *display)
 	return 0;
 }
 
-static int timerfd(int hz)
-{
-	struct itimerspec it;
-	int fd;
-
-	fd = timerfd_create(CLOCK_MONOTONIC_COARSE, TFD_NONBLOCK);
-	if (fd < 0)
-		fd = timerfd_create(CLOCK_MONOTONIC, TFD_NONBLOCK);
-	if (fd < 0)
-		return -ETIME;
-
-	it.it_interval.tv_sec = 0;
-	it.it_interval.tv_nsec = 1000000000 / hz;
-	it.it_value = it.it_interval;
-	if (timerfd_settime(fd, 0, &it, NULL) < 0) {
-		close(fd);
-		return -ETIME;
-	}
-
-	return fd;
-}
-
-static int context_init(struct context *ctx)
-{
-	struct pollfd *pfd;
-
-	memset(ctx, 0, sizeof(*ctx));
-
-	ctx->pfd = malloc(2*sizeof(struct pollfd));
-	if (ctx->pfd == NULL)
-		return -ENOMEM;
-
-	ctx->clones = malloc(sizeof(struct clone));
-	if (ctx->clones == NULL)
-		return -ENOMEM;
-
-	ctx->display = malloc(sizeof(struct display));
-	if (ctx->display == NULL)
-		return -ENOMEM;
-
-	pfd = memset(&ctx->pfd[ctx->nfd++], 0, sizeof(struct pollfd));
-	pfd->fd = timerfd(60);
-	if (pfd->fd < 0)
-		return pfd->fd;
-	pfd->events = POLLIN;
-
-	return 0;
-}
-
-static int add_fd(struct context *ctx, int fd)
-{
-	struct pollfd *pfd;
-
-	if (fd < 0)
-		return fd;
-
-	if (is_power_of_2(ctx->nfd)) {
-		ctx->pfd = realloc(ctx->pfd, 2*ctx->nfd*sizeof(struct pollfd));
-		if (ctx->pfd == NULL)
-			return -ENOMEM;
-	}
-
-	pfd = memset(&ctx->pfd[ctx->nfd++], 0, sizeof(struct pollfd));
-	pfd->fd = fd;
-	pfd->events = POLLIN;
-	return 0;
-}
-
 static void display_init_randr_hpd(struct display *display)
 {
 	int major, minor;
@@ -2148,7 +2187,7 @@ static void display_flush_send(struct display *display)
 
 	XSendEvent(display->dpy, display->root, False, 0, (XEvent *)&e);
 	display->send = 0;
-	display->flush = 1;
+	display_mark_flush(display);
 }
 
 static void display_flush(struct display *display)
@@ -2203,7 +2242,6 @@ int main(int argc, char **argv)
 	struct context ctx;
 	const char *src_name = NULL;
 	uint64_t count;
-	int enable_timer = 0;
 	int daemonize = 1, bumblebee = 0, all = 0, singleton = 1;
 	int i, ret, open, fail;
 
@@ -2346,8 +2384,8 @@ int main(int argc, char **argv)
 		XEvent e;
 		int reconfigure = 0;
 
-		DBG(("polling - enable timer? %d, nfd=%d\n", enable_timer, ctx.nfd));
-		ret = poll(ctx.pfd + !enable_timer, ctx.nfd - !enable_timer, -1);
+		DBG(("polling - enable timer? %d, nfd=%d\n", ctx.timer_active, ctx.nfd));
+		ret = poll(ctx.pfd + !ctx.timer_active, ctx.nfd - !ctx.timer_active, -1);
 		if (ret <= 0)
 			break;
 
@@ -2368,12 +2406,14 @@ int main(int argc, char **argv)
 					     de->area.x, de->area.y, de->area.width, de->area.height));
 					for (i = 0; i < ctx.nclone; i++)
 						clone_damage(&ctx.clones[i], &de->area);
-					if (!enable_timer)
-						enable_timer = read(ctx.timer, &count, sizeof(count)) > 0;
+					context_enable_timer(&ctx);
 					damaged++;
 				} else if (e.type == ctx.display->xfixes_event + XFixesCursorNotify) {
 					XFixesCursorImage *cur;
 
+					DBG(("%s cursor changed\n",
+					     DisplayString(ctx.display->dpy)));
+
 					cur = XFixesGetCursorImage(ctx.display->dpy);
 					if (cur == NULL)
 						continue;
@@ -2386,8 +2426,7 @@ int main(int argc, char **argv)
 					DBG(("%s screen changed (reconfigure pending? %d)\n",
 					     DisplayString(ctx.display->dpy), reconfigure));
 					reconfigure = 1;
-					if (!enable_timer)
-						enable_timer = read(ctx.timer, &count, sizeof(count)) > 0;
+					context_enable_timer(&ctx);
 				} else if (e.type == PropertyNotify) {
 					XPropertyEvent *pe = (XPropertyEvent *)&e;
 					if (pe->atom == ctx.singleton) {
@@ -2397,6 +2436,9 @@ int main(int argc, char **argv)
 				} else if (e.type == ClientMessage) {
 					XClientMessageEvent *cme;
 
+					DBG(("%s client message\n",
+					     DisplayString(ctx.display->dpy)));
+
 					cme = (XClientMessageEvent *)&e;
 					if (cme->message_type != ctx.singleton)
 						continue;
@@ -2447,17 +2489,18 @@ int main(int argc, char **argv)
 		for (i = 0; i < ctx.nclone; i++)
 			clone_update(&ctx.clones[i]);
 
-		if (enable_timer && read(ctx.timer, &count, sizeof(count)) > 0 && count > 0) {
+		if (ctx.timer_active && read(ctx.timer, &count, sizeof(count)) > 0 && count > 0) {
+			DBG(("%s timer expired (count=%ld)\n", DisplayString(ctx.display->dpy), (long)count));
 			ret = 0;
 			for (i = 0; i < ctx.nclone; i++)
 				ret |= clone_paint(&ctx.clones[i]);
-			enable_timer = ret != 0;
+			ctx.timer_active = ret != 0;
+
+			for (i = 0; i < ctx.ndisplay; i++)
+				display_flush(&ctx.display[i]);
 		}
 
 		XPending(ctx.record);
-
-		for (i = 0; i < ctx.ndisplay; i++)
-			display_flush(&ctx.display[i]);
 	}
 
 	return EINVAL;


More information about the xorg-commit mailing list