mirror of
https://github.com/X11Libre/xf86-video-intel.git
synced 2026-03-24 01:24:12 +00:00
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:
216
tools/virtual.c
216
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,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));
|
||||
|
||||
Reference in New Issue
Block a user