summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChris Wilson <chris@chris-wilson.co.uk>2015-06-02 15:24:38 +0100
committerChris Wilson <chris@chris-wilson.co.uk>2015-06-03 13:14:01 +0100
commit1525b0177862b1533232d6de923d40256a738845 (patch)
treee14050636853725251f888969fbae2b8bdc4124a
parentd0ba02666d786f63a88f7c69b82246560521adc7 (diff)
intel-virtual-output: Fix cloning fixed mode outputs
When using a fixed mode, e.g. a Display without RandR support like Xnest, we have to remember to hook up the connection during recofiguration of VIRTUAL outputs. Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
-rw-r--r--tools/virtual.c210
1 files changed, 131 insertions, 79 deletions
diff --git a/tools/virtual.c b/tools/virtual.c
index f5cba1a0..ffda54af 100644
--- a/tools/virtual.c
+++ b/tools/virtual.c
@@ -145,6 +145,7 @@ struct output {
XRenderPictFormat *use_render;
int x, y;
+ int width, height;
XRRModeInfo mode;
Rotation rotation;
};
@@ -250,6 +251,10 @@ can_use_shm(Display *dpy,
XExtCodes *codes;
int major, minor, has_shm, has_pixmap;
+ *shm_event = 0;
+ *shm_opcode = 0;
+ *shm_pixmap = 0;
+
if (!XShmQueryExtension(dpy))
return 0;
@@ -824,6 +829,10 @@ static int clone_update_modes__fixed(struct clone *clone)
RRMode id;
int i, j, ret = ENOENT;
+ DBG(X11, ("%s-%s cloning modes fixed %dx%d\n",
+ DisplayString(clone->dst.dpy), clone->dst.name,
+ clone->dst.width, clone->dst.height));
+
assert(clone->src.rr_output);
res = _XRRGetScreenResourcesCurrent(clone->src.dpy, clone->src.window);
@@ -852,8 +861,8 @@ static int clone_update_modes__fixed(struct clone *clone)
/* Create matching mode for the real output on the virtual */
memset(&mode, 0, sizeof(mode));
- mode.width = clone->width;
- mode.height = clone->height;
+ mode.width = clone->dst.width;
+ mode.height = clone->dst.height;
mode.nameLength = sprintf(mode_name, "FAKE-%dx%d", mode.width, mode.height);
mode.name = mode_name;
@@ -1097,20 +1106,20 @@ static int clone_init_xfer(struct clone *clone)
width = 0;
height = 0;
} else if (clone->dri3.xid) {
- width = clone->dst.display->width;
- height = clone->dst.display->height;
+ width = clone->dst.width;
+ height = clone->dst.height;
} else {
width = mode_width(&clone->src.mode, clone->src.rotation);
height = mode_height(&clone->src.mode, clone->src.rotation);
}
+ DBG(DRAW, ("%s-%s create xfer, %dx%d (currently %dx%d)\n",
+ DisplayString(clone->dst.dpy), clone->dst.name,
+ width, height, clone->width, clone->height));
+
if (width == clone->width && height == clone->height)
return 0;
- DBG(DRAW, ("%s-%s create xfer, %dx%d\n",
- DisplayString(clone->dst.dpy), clone->dst.name,
- width, height));
-
if (clone->shm.shmaddr) {
if (clone->src.use_shm)
XShmDetach(clone->src.dpy, &clone->src.shm);
@@ -1340,8 +1349,19 @@ static int context_update(struct context *ctx)
struct clone *clone;
int x1, x2, y1, y2;
- if (display->rr_active == 0)
+ if (display->rr_active == 0) {
+ for (clone = display->clone; clone; clone = clone->next) {
+ struct output *output = &clone->src;
+ if (output->mode.id) {
+ clone->dst.mode.id = -1;
+ clone->dst.rr_crtc = -1;
+ } else {
+ clone->dst.mode.id = 0;
+ clone->dst.rr_crtc = 0;
+ }
+ }
continue;
+ }
x1 = y1 = INT_MAX;
x2 = y2 = INT_MIN;
@@ -1795,6 +1815,8 @@ static void get_src(struct clone *c, const XRectangle *clip)
c->image.obdata = (char *)&c->src.shm;
if (c->src.use_render) {
+ DBG(DRAW, ("%s-%s get_src via XRender\n",
+ DisplayString(c->dst.dpy), c->dst.name));
XRenderComposite(c->src.dpy, PictOpSrc,
c->src.win_picture, 0, c->src.pix_picture,
clip->x, clip->y,
@@ -1815,16 +1837,22 @@ static void get_src(struct clone *c, const XRectangle *clip)
&c->image, 0, 0);
}
} else if (c->src.pixmap) {
+ DBG(DRAW, ("%s-%s get_src XCopyArea (SHM/DRI3)\n",
+ DisplayString(c->dst.dpy), c->dst.name));
XCopyArea(c->src.dpy, c->src.window, c->src.pixmap, c->src.gc,
clip->x, clip->y,
clip->width, clip->height,
0, 0);
XSync(c->src.dpy, False);
} else if (c->src.use_shm) {
+ DBG(DRAW, ("%s-%s get_src XShmGetImage\n",
+ DisplayString(c->dst.dpy), c->dst.name));
ximage_prepare(&c->image, clip->width, clip->height);
XShmGetImage(c->src.dpy, c->src.window, &c->image,
clip->x, clip->y, AllPlanes);
} else {
+ DBG(DRAW, ("%s-%s get_src XGetSubImage (slow)\n",
+ DisplayString(c->dst.dpy), c->dst.name));
ximage_prepare(&c->image, c->width, c->height);
XGetSubImage(c->src.dpy, c->src.window,
clip->x, clip->y, clip->width, clip->height,
@@ -1903,6 +1931,9 @@ static int clone_paint(struct clone *c)
{
XRectangle clip;
+ if (c->width == 0 || c->height == 0)
+ return 0;
+
DBG(DRAW, ("%s-%s paint clone, damaged (%d, %d), (%d, %d) [(%d, %d), (%d, %d)]\n",
DisplayString(c->dst.dpy), c->dst.name,
c->damaged.x1, c->damaged.y1,
@@ -1977,6 +2008,10 @@ static int clone_paint(struct clone *c)
clip.height = c->damaged.y2 - c->damaged.y1;
get_src(c, &clip);
+ DBG(DRAW, ("%s-%s target offset %dx%d\n",
+ DisplayString(c->dst.dpy), c->dst.name,
+ c->dst.x - c->src.x, c->dst.y - c->src.y));
+
clip.x += c->dst.x - c->src.x;
clip.y += c->dst.y - c->src.y;
put_dst(c, &clip);
@@ -2285,6 +2320,8 @@ static int clone_init_depth(struct clone *clone)
if (ret)
return ret;
+ clone->depth = depth;
+
DBG(X11, ("%s-%s using depth %d, requires xrender for src? %d, for dst? %d\n",
DisplayString(clone->dst.dpy), clone->dst.name,
clone->depth,
@@ -2625,6 +2662,11 @@ static int last_display_add_clones__randr(struct context *ctx)
return ret;
}
+ clone->dst.x = 0;
+ clone->dst.y = 0;
+ clone->dst.width = display->width;
+ clone->dst.height = display->height;
+
ret = clone_update_modes__randr(clone);
if (ret) {
fprintf(stderr, "Failed to clone output \"%s\" from display \"%s\"\n",
@@ -2701,8 +2743,8 @@ static int last_display_add_clones__xinerama(struct context *ctx)
}
/* Replace the modes on the local VIRTUAL output with the remote Screen */
- clone->width = xi[n].width;
- clone->height = xi[n].height;
+ clone->dst.width = xi[n].width;
+ clone->dst.height = xi[n].height;
clone->dst.x = xi[n].x_org;
clone->dst.y = xi[n].y_org;
clone->dst.rr_crtc = -1;
@@ -2731,64 +2773,67 @@ static int last_display_add_clones__display(struct context *ctx)
Display *dpy = display->dpy;
struct clone *clone;
Screen *scr;
+ int count, s;
char buf[80];
int ret;
RROutput id;
+ count = ScreenCount(dpy);
+ DBG(X11, ("%s(%s) - %d screens\n", __func__, DisplayString(dpy), count));
+ for (s = 0; s < count; s++) {
+ clone = add_clone(ctx);
+ if (clone == NULL)
+ return -ENOMEM;
- DBG(X11, ("%s(%s)\n", __func__, DisplayString(dpy)));
- clone = add_clone(ctx);
- if (clone == NULL)
- return -ENOMEM;
+ clone->depth = 24;
+ clone->next = display->clone;
+ display->clone = clone;
- clone->depth = 24;
- clone->next = display->clone;
- display->clone = clone;
+ id = claim_virtual(ctx->display, buf, ctx->nclone);
+ if (id == 0) {
+ fprintf(stderr, "Failed to find available VirtualHead \"%s\" for on display \"%s\"\n",
+ buf, DisplayString(dpy));
+ }
+ ret = clone_output_init(clone, &clone->src, ctx->display, buf, id);
+ if (ret) {
+ fprintf(stderr, "Failed to add display \"%s\"\n",
+ DisplayString(ctx->display->dpy));
+ return ret;
+ }
- id = claim_virtual(ctx->display, buf, ctx->nclone);
- if (id == 0) {
- fprintf(stderr, "Failed to find available VirtualHead \"%s\" for on display \"%s\"\n",
- buf, DisplayString(dpy));
- }
- ret = clone_output_init(clone, &clone->src, ctx->display, buf, id);
- if (ret) {
- fprintf(stderr, "Failed to add display \"%s\"\n",
- DisplayString(ctx->display->dpy));
- return ret;
- }
+ sprintf(buf, "SCREEN%d", s);
+ ret = clone_output_init(clone, &clone->dst, display, buf, 0);
+ if (ret) {
+ fprintf(stderr, "Failed to add display \"%s\"\n",
+ DisplayString(dpy));
+ return ret;
+ }
- sprintf(buf, "WHOLE");
- ret = clone_output_init(clone, &clone->dst, display, buf, 0);
- if (ret) {
- fprintf(stderr, "Failed to add display \"%s\"\n",
- DisplayString(dpy));
- return ret;
- }
+ ret = clone_init_depth(clone);
+ if (ret) {
+ fprintf(stderr, "Failed to negotiate image format for display \"%s\"\n",
+ DisplayString(dpy));
+ return ret;
+ }
- ret = clone_init_depth(clone);
- if (ret) {
- fprintf(stderr, "Failed to negotiate image format for display \"%s\"\n",
- DisplayString(dpy));
- return ret;
- }
+ /* Replace the modes on the local VIRTUAL output with the remote Screen */
+ scr = ScreenOfDisplay(dpy, s);
+ clone->dst.width = scr->width;
+ clone->dst.height = scr->height;
+ clone->dst.x = 0;
+ clone->dst.y = 0;
+ clone->dst.rr_crtc = -1;
+ ret = clone_update_modes__fixed(clone);
+ if (ret) {
+ fprintf(stderr, "Failed to clone display \"%s\"\n",
+ DisplayString(dpy));
+ return ret;
+ }
- /* Replace the modes on the local VIRTUAL output with the remote Screen */
- scr = ScreenOfDisplay(dpy, DefaultScreen(dpy));
- clone->width = scr->width;
- clone->height = scr->height;
- clone->dst.x = 0;
- clone->dst.y = 0;
- clone->dst.rr_crtc = -1;
- ret = clone_update_modes__fixed(clone);
- if (ret) {
- fprintf(stderr, "Failed to clone display \"%s\"\n",
- DisplayString(dpy));
- return ret;
+ clone->active = ctx->active;
+ ctx->active = clone;
}
- clone->active = ctx->active;
- ctx->active = clone;
-
return 0;
}
@@ -3201,6 +3246,33 @@ static void context_cleanup(struct context *ctx)
XCloseDisplay(dpy);
}
+static void update_cursor_image(struct context *ctx)
+{
+ XFixesCursorImage *cur;
+ int i;
+
+ DBG(CURSOR, ("%s cursor changed\n",
+ DisplayString(ctx->display->dpy)));
+
+ cur = XFixesGetCursorImage(ctx->display->dpy);
+ if (cur == NULL)
+ return;
+
+ display_load_visible_cursor(&ctx->display[0], cur);
+ for (i = 1; i < ctx->ndisplay; i++) {
+ struct display *display = &ctx->display[i];
+
+ DBG(CURSOR, ("%s marking cursor changed\n", DisplayString(display->dpy)));
+ display->cursor_moved++;
+ if (display->cursor != display->invisible_cursor) {
+ display->cursor_visible++;
+ context_enable_timer(display->ctx);
+ }
+ }
+
+ XFree(cur);
+}
+
static int done;
static void signal_handler(int sig)
@@ -3382,6 +3454,7 @@ int main(int argc, char **argv)
signal(SIGTERM, signal_handler);
ctx.command_continuation = 0;
+ update_cursor_image(&ctx);
while (!done) {
XEvent e;
int reconfigure = 0;
@@ -3414,28 +3487,7 @@ int main(int argc, char **argv)
if (ctx.active)
context_enable_timer(&ctx);
} else if (e.type == ctx.display->xfixes_event + XFixesCursorNotify) {
- XFixesCursorImage *cur;
-
- DBG(CURSOR, ("%s cursor changed\n",
- DisplayString(ctx.display->dpy)));
-
- cur = XFixesGetCursorImage(ctx.display->dpy);
- if (cur == NULL)
- continue;
-
- display_load_visible_cursor(&ctx.display[0], cur);
- for (i = 1; i < ctx.ndisplay; i++) {
- struct display *display = &ctx.display[i];
-
- DBG(CURSOR, ("%s marking cursor changed\n", DisplayString(display->dpy)));
- display->cursor_moved++;
- if (display->cursor != display->invisible_cursor) {
- display->cursor_visible++;
- context_enable_timer(display->ctx);
- }
- }
-
- XFree(cur);
+ update_cursor_image(&ctx);
} else if (e.type == ctx.display->rr_event + RRScreenChangeNotify) {
DBG(XRR, ("%s screen changed (reconfigure pending? %d)\n",
DisplayString(ctx.display->dpy), reconfigure));