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>
This commit is contained in:
Chris Wilson
2015-06-02 15:24:38 +01:00
parent d0ba02666d
commit 1525b01778

View File

@@ -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,63 +2773,66 @@ 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));
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;
}
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;
}
clone->active = ctx->active;
ctx->active = clone;
}
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, "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;
}
/* 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;
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));