diff options
author | Chris Wilson <chris@chris-wilson.co.uk> | 2015-06-02 15:24:38 +0100 |
---|---|---|
committer | Chris Wilson <chris@chris-wilson.co.uk> | 2015-06-03 13:14:01 +0100 |
commit | 1525b0177862b1533232d6de923d40256a738845 (patch) | |
tree | e14050636853725251f888969fbae2b8bdc4124a | |
parent | d0ba02666d786f63a88f7c69b82246560521adc7 (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.c | 210 |
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)); |