diff options
author | Chris Wilson <chris@chris-wilson.co.uk> | 2013-08-31 19:44:50 +0100 |
---|---|---|
committer | Chris Wilson <chris@chris-wilson.co.uk> | 2013-08-31 20:48:24 +0100 |
commit | 8ecb758697af42e8e68edee0d1945986470a9c04 (patch) | |
tree | 712c58bd6662dad6766fed7f6c1aa61e30135a2c | |
parent | 57904e8d3d1deef33dd5515f3179b4d60c912712 (diff) |
sna: Expand the array of fake outputs if the last is used
Always maintain one spare so that we can reconfigure for any number of
desired outputs on the fly.
Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
-rw-r--r-- | src/sna/sna.h | 4 | ||||
-rw-r--r-- | src/sna/sna_display.c | 2 | ||||
-rw-r--r-- | src/sna/sna_display_fake.c | 177 | ||||
-rw-r--r-- | tools/intel-virtual-output.man | 9 | ||||
-rw-r--r-- | tools/virtual.c | 45 |
5 files changed, 160 insertions, 77 deletions
diff --git a/src/sna/sna.h b/src/sna/sna.h index 298883c8..c47a8ab2 100644 --- a/src/sna/sna.h +++ b/src/sna/sna.h @@ -265,6 +265,10 @@ struct sna { DamagePtr shadow_damage; struct kgem_bo *shadow; int shadow_flip; + + unsigned num_real_crtc; + unsigned num_real_output; + unsigned num_fake; } mode; struct sna_dri { diff --git a/src/sna/sna_display.c b/src/sna/sna_display.c index aa445ae3..263bae95 100644 --- a/src/sna/sna_display.c +++ b/src/sna/sna_display.c @@ -3211,7 +3211,7 @@ bool sna_mode_pre_init(ScrnInfoPtr scrn, struct sna *sna) } if (!xf86GetOptValInteger(sna->Options, OPTION_VIRTUAL, &num_fake)) - num_fake = 0; + num_fake = 1; mode->kmode = drmModeGetResources(sna->kgem.fd); if (mode->kmode) { diff --git a/src/sna/sna_display_fake.c b/src/sna/sna_display_fake.c index 73fca7e6..3daa793c 100644 --- a/src/sna/sna_display_fake.c +++ b/src/sna/sna_display_fake.c @@ -31,6 +31,8 @@ #include "sna.h" +static bool add_fake_output(struct sna *sna, bool late); + static void sna_crtc_dpms(xf86CrtcPtr crtc, int mode) { @@ -102,21 +104,6 @@ static const xf86CrtcFuncsRec sna_crtc_funcs = { #endif }; -static bool -sna_crtc_fake(struct sna *sna) -{ - ScrnInfoPtr scrn = sna->scrn; - xf86CrtcPtr crtc; - - DBG(("%s\n", __FUNCTION__)); - - crtc = xf86CrtcCreate(scrn, &sna_crtc_funcs); - if (crtc == NULL) - return false; - - return true; -} - static void sna_output_create_resources(xf86OutputPtr output) { @@ -143,8 +130,14 @@ sna_output_dpms(xf86OutputPtr output, int dpms) static xf86OutputStatus sna_output_detect(xf86OutputPtr output) { - if (output->randr_output->numUserModes) + if (output->randr_output->numUserModes) { + xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(output->scrn); + + if (xf86_config->output[xf86_config->num_output-1] == output) + add_fake_output(to_sna(output->scrn), true); + return XF86OutputStatusConnected; + } return XF86OutputStatusDisconnected; } @@ -183,32 +176,6 @@ static const xf86OutputFuncsRec sna_output_funcs = { .destroy = sna_output_destroy }; -static bool -sna_output_fake(struct sna *sna, int n, int num_fake, int num_real_crtc, int num_real_output) -{ - ScrnInfoPtr scrn = sna->scrn; - xf86OutputPtr output; - unsigned mask; - char buf[80]; - - sprintf(buf, "VIRTUAL%d", n+1); - output = xf86OutputCreate(scrn, &sna_output_funcs, buf); - if (!output) - return false; - - output->mm_width = 0; - output->mm_height = 0; - - output->subpixel_order = SubPixelNone; - - mask = (1 << num_fake) - 1; - output->possible_crtcs = mask << num_real_crtc; - output->possible_clones = mask << num_real_output; - output->interlaceAllowed = FALSE; - - return true; -} - static Bool sna_mode_resize(ScrnInfoPtr scrn, int width, int height) { @@ -251,28 +218,126 @@ static const xf86CrtcConfigFuncsRec sna_mode_funcs = { sna_mode_resize }; -bool sna_mode_fake_init(struct sna *sna, int num_fake) +static bool add_fake_output(struct sna *sna, bool late) { - xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(sna->scrn); - int n, num_real_crtc, num_real_output; + ScrnInfoPtr scrn = sna->scrn; + xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(scrn); + xf86OutputPtr output; + xf86CrtcPtr crtc; + RROutputPtr clones[32]; + RRCrtcPtr crtcs[32]; + unsigned mask; + char buf[80]; + int i, j, len; - if (num_fake == 0) - return true; + if (sna->mode.num_fake >= 32) + return false; - num_real_crtc = xf86_config->num_crtc; - num_real_output = xf86_config->num_output; + DBG(("%s(late=%d, num_fake=%d)\n", __FUNCTION__, late, sna->mode.num_fake+1)); - if (num_real_crtc == 0) - xf86CrtcConfigInit(sna->scrn, &sna_mode_funcs); + crtc = xf86CrtcCreate(scrn, &sna_crtc_funcs); + if (crtc == NULL) + return false; - for (n = 0; n < num_fake; n++) { - if (!sna_crtc_fake(sna)) - return false; + len = sprintf(buf, "VIRTUAL%d", sna->mode.num_fake+1); + output = xf86OutputCreate(scrn, &sna_output_funcs, buf); + if (!output) { + xf86CrtcDestroy(crtc); + return false; + } + + output->mm_width = 0; + output->mm_height = 0; + output->interlaceAllowed = FALSE; + output->subpixel_order = SubPixelNone; + + if (late) { + ScreenPtr screen = xf86ScrnToScreen(scrn); - if (!sna_output_fake(sna, n, num_fake, - num_real_crtc, num_real_output)) + crtc->randr_crtc = RRCrtcCreate(screen, crtc); + output->randr_output = RROutputCreate(screen, buf, len, output); + if (crtc->randr_crtc == NULL || output->randr_output == NULL) { + xf86OutputDestroy(output); + xf86CrtcDestroy(crtc); return false; + } + + RRPostPendingProperties(output->randr_output); + + mask = (1 << ++sna->mode.num_fake) - 1; + for (i = j = 0; i < xf86_config->num_output; i++) { + output = xf86_config->output[i]; + if (output->driver_private) + continue; + + output->possible_crtcs = mask << sna->mode.num_real_crtc; + output->possible_clones = mask << sna->mode.num_real_output; + + clones[j++] = output->randr_output; + } + assert(j == sna->mode.num_fake); + + for (i = j = 0; i < xf86_config->num_crtc; i++) { + crtc = xf86_config->crtc[i]; + if (crtc->driver_private) + continue; + + crtcs[j++] = crtc->randr_crtc; + } + assert(j == sna->mode.num_fake); + + for (i = 0; i < xf86_config->num_output; i++) { + output = xf86_config->output[i]; + if (output->driver_private) + continue; + + if (!RROutputSetCrtcs(output->randr_output, crtcs, j) || + !RROutputSetClones(output->randr_output, clones, j)) + goto err; + } + } else { + mask = (1 << ++sna->mode.num_fake) - 1; + output->possible_crtcs = mask << sna->mode.num_real_crtc; + output->possible_clones = mask << sna->mode.num_real_output; } return true; + +err: + for (i = 0; i < xf86_config->num_output; i++) { + output = xf86_config->output[i]; + if (output->driver_private) + continue; + + xf86OutputDestroy(output); + } + + for (i = 0; i < xf86_config->num_crtc; i++) { + crtc = xf86_config->crtc[i]; + if (crtc->driver_private) + continue; + xf86CrtcDestroy(crtc); + } + sna->mode.num_fake = -1; + return false; +} + +bool sna_mode_fake_init(struct sna *sna, int num_fake) +{ + xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(sna->scrn); + bool ret; + + if (num_fake == 0) + return true; + + sna->mode.num_real_crtc = xf86_config->num_crtc; + sna->mode.num_real_output = xf86_config->num_output; + + if (sna->mode.num_real_crtc == 0) + xf86CrtcConfigInit(sna->scrn, &sna_mode_funcs); + + ret = true; + while (ret && num_fake--) + ret = add_fake_output(sna, false); + return ret; } diff --git a/tools/intel-virtual-output.man b/tools/intel-virtual-output.man index 7a2e6262..675238c1 100644 --- a/tools/intel-virtual-output.man +++ b/tools/intel-virtual-output.man @@ -5,19 +5,12 @@ intel-virtual-output \- Utility for connecting the Integrated Intel GPU to discrete outputs .SH SYNOPSIS .nf -.B "Section \*qDevice\*q" -.BI " Identifier \*q" devname \*q -.B " Driver \*qintel\*q" -.B " Option \*qVirtualHeads\*q" \*q<number>\*q -\ \ ... -.B EndSection -.B "" .B "intel-virtual-output [<remote display>] <output name>..." .fi .SH DESCRIPTION .B intel-virtual-output is a utility for Intel integrated graphics chipsets on hybrid systems. -The tool connects pre-allocated VirtualHeads to a remote output, allowing +The tool connects local VirtualHeads to a remote output, allowing the primary display to extend onto the remote outputs. .SH REPORTING BUGS diff --git a/tools/virtual.c b/tools/virtual.c index d3f71a67..00342c9e 100644 --- a/tools/virtual.c +++ b/tools/virtual.c @@ -383,6 +383,37 @@ err: return ret; } +static int claim_virtual(struct output *output) +{ + char buf[] = "ClaimVirtualHead"; + XRRScreenResources *res; + XRRModeInfo mode; + RRMode id; + + /* Set any mode on the VirtualHead to make the Xserver allocate another */ + assert(output->rr_output); + + memset(&mode, 0, sizeof(mode)); + mode.width = 1024; + mode.height = 768; + mode.name = buf; + mode.nameLength = sizeof(buf) - 1; + + id = XRRCreateMode(output->dpy, output->window, &mode); + XRRAddOutputMode(output->dpy, output->rr_output, id); + + /* Force a redetection for the ddx to spot the new outputs */ + res = XRRGetScreenResources(output->dpy, output->window); + if (res == NULL) + return ENOMEM; + + XRRFreeScreenResources(res); + XRRDeleteOutputMode(output->dpy, output->rr_output, id); + XRRDestroyMode(output->dpy, id); + + return 0; +} + static int get_current_config(struct output *output) { XRRScreenResources *res; @@ -1471,18 +1502,8 @@ int main(int argc, char **argv) sprintf(buf, "VIRTUAL%d", ctx.num_clones+1); ret = clone_output_init(&ctx.clones[ctx.num_clones], &ctx.clones[ctx.num_clones].src, &ctx.display[0], buf); - if (ret) { - while (++i < argc) - ctx.num_clones += strchr(argv[i], ':') == NULL; - fprintf(stderr, - "No preallocated VirtualHead found for argv[i].\n" - "Please increase the number of VirtualHeads in xorg.conf:\n" - " Section \"Device\"\n" - " Identifier \"<identifier>\"\n" - " Driver \"intel\"\n" - " Option \"VirtualHeads\" \"%d\"\n" - " ...\n" - " EndSection\n", ctx.num_clones+1); + if (ret || claim_virtual(&ctx.clones[ctx.num_clones].src)) { + fprintf(stderr, "Failed to find available VirtualHead for argv[i].\n"); return ret; } |