summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChris Wilson <chris@chris-wilson.co.uk>2013-08-31 19:44:50 +0100
committerChris Wilson <chris@chris-wilson.co.uk>2013-08-31 20:48:24 +0100
commit8ecb758697af42e8e68edee0d1945986470a9c04 (patch)
tree712c58bd6662dad6766fed7f6c1aa61e30135a2c
parent57904e8d3d1deef33dd5515f3179b4d60c912712 (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.h4
-rw-r--r--src/sna/sna_display.c2
-rw-r--r--src/sna/sna_display_fake.c177
-rw-r--r--tools/intel-virtual-output.man9
-rw-r--r--tools/virtual.c45
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;
}