diff options
author | Chris Wilson <chris@chris-wilson.co.uk> | 2013-08-29 23:00:05 +0100 |
---|---|---|
committer | Chris Wilson <chris@chris-wilson.co.uk> | 2013-08-30 08:57:25 +0100 |
commit | 68d139388a2a037347fa5c838391e67e006793ee (patch) | |
tree | fcac6d4c98fd88b1c9bd24483972da6a95cbd739 | |
parent | 92a43caab96e7f49c541fb999b75925914d9981a (diff) |
sna: Allow user specification of number of VirtualHeads
Previously, we instantiated a fake output in case we had a machine with
no output. (For certain server-class products.) The Bumblee project were
also doing something very similar in order to fake an extended desktop
on the Intel igfx and copy portions onto a discrete GPU. (The preferred
method for doing this upstream is through the use of PRIME). As the code
is very similar, we can support both use-cases simultaneously.
This adds the option:
Section "Device"
Driver "intel"
Option "VirtualHeads" "<count>"
EndSection
to allow the user to specify an additional set of fake outputs, which
can then be controlled using xrandr.
Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
-rw-r--r-- | man/intel.man | 12 | ||||
-rw-r--r-- | src/intel_options.c | 1 | ||||
-rw-r--r-- | src/intel_options.h | 1 | ||||
-rw-r--r-- | src/sna/sna.h | 2 | ||||
-rw-r--r-- | src/sna/sna_display.c | 62 | ||||
-rw-r--r-- | src/sna/sna_display_fake.c | 40 |
6 files changed, 93 insertions, 25 deletions
diff --git a/man/intel.man b/man/intel.man index 9e19687b..0a265114 100644 --- a/man/intel.man +++ b/man/intel.man @@ -261,6 +261,18 @@ applications when monitors are connected or disconnected. .IP Default: enabled. .TP +.BI "Option \*qVirtualheads\*q \*q" integer \*q +This option controls specifies the number of fake outputs to create in +addition to the normal outputs detected on your hardware. These outputs +cannot be assigned to the regular displays attached to the GPU, but do +otherwise act as any other xrandr output and share a portion of the +regular framebuffer. One use case for these extra heads is for extending +your desktop onto a discrete GPU using the Bumblebee project. However, +the recommendation here is to use PRIME instead to create a single +Xserver that can addresses and coordinate between multiple GPUs. +.IP +Default: 0 +.TP .BI "Option \*qZaphodHeads\*q \*q" string \*q .IP Specify the randr output(s) to use with zaphod mode for a particular driver diff --git a/src/intel_options.c b/src/intel_options.c index b81bde6e..153cc629 100644 --- a/src/intel_options.c +++ b/src/intel_options.c @@ -23,6 +23,7 @@ const OptionInfoRec intel_options[] = { #endif #ifdef USE_SNA {OPTION_ZAPHOD, "ZaphodHeads", OPTV_STRING, {0}, 0}, + {OPTION_VIRTUAL, "VirtualHeads", OPTV_INTEGER, {0}, 0}, {OPTION_TEAR_FREE, "TearFree", OPTV_BOOLEAN, {0}, 0}, {OPTION_CRTC_PIXMAPS, "PerCrtcPixmaps", OPTV_BOOLEAN, {0}, 0}, #endif diff --git a/src/intel_options.h b/src/intel_options.h index 112983d5..095660c3 100644 --- a/src/intel_options.h +++ b/src/intel_options.h @@ -30,6 +30,7 @@ enum intel_options { #endif #ifdef USE_SNA OPTION_ZAPHOD, + OPTION_VIRTUAL, OPTION_TEAR_FREE, OPTION_CRTC_PIXMAPS, #endif diff --git a/src/sna/sna.h b/src/sna/sna.h index 337ebc89..5b26ebfd 100644 --- a/src/sna/sna.h +++ b/src/sna/sna.h @@ -330,7 +330,7 @@ struct sna { }; bool sna_mode_pre_init(ScrnInfoPtr scrn, struct sna *sna); -bool sna_mode_fake_init(struct sna *sna); +bool sna_mode_fake_init(struct sna *sna, int num_fake); void sna_mode_adjust_frame(struct sna *sna, int x, int y); extern void sna_mode_update(struct sna *sna); extern void sna_mode_wakeup(struct sna *sna); diff --git a/src/sna/sna_display.c b/src/sna/sna_display.c index da3475ff..aa445ae3 100644 --- a/src/sna/sna_display.c +++ b/src/sna/sna_display.c @@ -2758,8 +2758,15 @@ sna_mode_resize(ScrnInfoPtr scrn, int width, int height) "resizing framebuffer to %dx%d\n", width, height); - for (i = 0; i < xf86_config->num_crtc; i++) - sna_crtc_disable_shadow(sna, to_sna_crtc(xf86_config->crtc[i])); + for (i = 0; i < xf86_config->num_crtc; i++) { + struct sna_crtc *crtc; + + crtc = to_sna_crtc(xf86_config->crtc[i]); + if (crtc == NULL) + continue; + + sna_crtc_disable_shadow(sna, crtc); + } assert(sna->mode.shadow_active == 0); assert(sna->mode.shadow_damage == NULL); assert(sna->mode.shadow == NULL); @@ -2778,7 +2785,7 @@ sna_mode_resize(ScrnInfoPtr scrn, int width, int height) for (i = 0; i < xf86_config->num_crtc; i++) { xf86CrtcPtr crtc = xf86_config->crtc[i]; - if (!crtc->enabled) + if (!crtc->enabled || to_sna_crtc(crtc) == NULL) continue; if (!sna_crtc_set_mode_major(crtc, @@ -2818,8 +2825,8 @@ static int do_page_flip(struct sna *sna, struct kgem_bo *bo, struct drm_mode_crtc_page_flip arg; DBG(("%s: crtc %d active? %d\n", - __FUNCTION__, i, crtc->bo != NULL)); - if (crtc->bo == NULL) + __FUNCTION__, i, crtc && crtc->bo)); + if (crtc == NULL || crtc->bo == NULL) continue; arg.crtc_id = crtc->id; @@ -3019,6 +3026,9 @@ static bool sna_probe_initial_configuration(struct sna *sna) struct drm_mode_crtc mode; uint16_t *gamma; + if (sna_crtc == NULL) + continue; + crtc->enabled = FALSE; crtc->desiredMode.status = MODE_NOMODE; @@ -3088,6 +3098,9 @@ static bool sna_probe_initial_configuration(struct sna *sna) xf86OutputPtr output = config->output[i]; uint32_t crtc_id; + if (to_sna_output(output) == NULL) + continue; + crtc_id = (uintptr_t)output->crtc; output->crtc = NULL; @@ -3189,6 +3202,7 @@ sna_crtc_config_notify(ScreenPtr screen) bool sna_mode_pre_init(ScrnInfoPtr scrn, struct sna *sna) { struct sna_mode *mode = &sna->mode; + int num_fake = 0; int i; if (sna->flags & SNA_IS_HOSTED) { @@ -3196,6 +3210,9 @@ bool sna_mode_pre_init(ScrnInfoPtr scrn, struct sna *sna) return true; } + if (!xf86GetOptValInteger(sna->Options, OPTION_VIRTUAL, &num_fake)) + num_fake = 0; + mode->kmode = drmModeGetResources(sna->kgem.fd); if (mode->kmode) { xf86CrtcConfigInit(scrn, &sna_mode_funcs); @@ -3211,17 +3228,20 @@ bool sna_mode_pre_init(ScrnInfoPtr scrn, struct sna *sna) if (!xf86IsEntityShared(scrn->entityList[0])) sna_mode_compute_possible_clones(scrn); - - sna_setup_provider(scrn); } else { - if (!sna_mode_fake_init(sna)) - return false; + if (num_fake == 0) + num_fake = 1; } set_size_range(sna); + if (!sna_mode_fake_init(sna, num_fake)) + return false; + if (!sna_probe_initial_configuration(sna)) xf86InitialConfiguration(scrn, TRUE); + + sna_setup_provider(scrn); return scrn->modes != NULL; } @@ -3241,8 +3261,15 @@ sna_mode_close(struct sna *sna) if (sna->flags & SNA_IS_HOSTED) return; - for (i = 0; i < xf86_config->num_crtc; i++) - sna_crtc_disable_shadow(sna, to_sna_crtc(xf86_config->crtc[i])); + for (i = 0; i < xf86_config->num_crtc; i++) { + struct sna_crtc *crtc; + + crtc = to_sna_crtc(xf86_config->crtc[i]); + if (crtc == NULL) + continue; + + sna_crtc_disable_shadow(sna, crtc); + } } void @@ -3567,7 +3594,8 @@ sna_wait_for_scanline(struct sna *sna, int y1, y2, pipe; bool ret; - assert(crtc); + assert(crtc != NULL); + assert(to_sna_crtc(crtc) != NULL); assert(to_sna_crtc(crtc)->bo != NULL); assert(pixmap == sna->front); @@ -3930,7 +3958,7 @@ void sna_mode_redisplay(struct sna *sna) struct sna_crtc *sna_crtc = to_sna_crtc(crtc); RegionRec damage; - if (!sna_crtc->shadow) + if (sna_crtc == NULL || !sna_crtc->shadow) continue; assert(crtc->enabled); @@ -3953,7 +3981,9 @@ void sna_mode_redisplay(struct sna *sna) struct sna_crtc *sna_crtc = to_sna_crtc(crtc); RegionRec damage; - if (!sna_crtc->shadow || sna_crtc->bo == sna->mode.shadow) + if (sna_crtc == NULL || + !sna_crtc->shadow || + sna_crtc->bo == sna->mode.shadow) continue; assert(crtc->enabled); @@ -3987,8 +4017,8 @@ void sna_mode_redisplay(struct sna *sna) struct drm_mode_crtc_page_flip arg; DBG(("%s: crtc %d [%d, pipe=%d] active? %d\n", - __FUNCTION__, i, crtc->id, crtc->pipe, crtc->bo != NULL)); - if (crtc->bo != old) + __FUNCTION__, i, crtc->id, crtc->pipe, crtc && crtc->bo)); + if (crtc == NULL || crtc->bo != old) continue; assert(config->crtc[i]->enabled); diff --git a/src/sna/sna_display_fake.c b/src/sna/sna_display_fake.c index 6231eb52..afd5588f 100644 --- a/src/sna/sna_display_fake.c +++ b/src/sna/sna_display_fake.c @@ -143,7 +143,7 @@ sna_output_dpms(xf86OutputPtr output, int dpms) static xf86OutputStatus sna_output_detect(xf86OutputPtr output) { - return XF86OutputStatusDisconnected; + return XF86OutputStatusUnknown; } static Bool @@ -178,12 +178,15 @@ static const xf86OutputFuncsRec sna_output_funcs = { }; static bool -sna_output_fake(struct sna *sna) +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]; - output = xf86OutputCreate(scrn, &sna_output_funcs, "FAKE"); + sprintf(buf, "VIRTUAL%d", n+1); + output = xf86OutputCreate(scrn, &sna_output_funcs, buf); if (!output) return false; @@ -192,8 +195,9 @@ sna_output_fake(struct sna *sna) output->subpixel_order = SubPixelNone; - output->possible_crtcs = 1; - output->possible_clones = 0; + mask = (1 << num_fake) - 1; + output->possible_crtcs = mask << num_real_crtc; + output->possible_clones = mask << num_real_output; output->interlaceAllowed = FALSE; return true; @@ -241,8 +245,28 @@ static const xf86CrtcConfigFuncsRec sna_mode_funcs = { sna_mode_resize }; -bool sna_mode_fake_init(struct sna *sna) +bool sna_mode_fake_init(struct sna *sna, int num_fake) { - xf86CrtcConfigInit(sna->scrn, &sna_mode_funcs); - return sna_crtc_fake(sna) && sna_output_fake(sna); + xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(sna->scrn); + int n, num_real_crtc, num_real_output; + + if (num_fake == 0) + return true; + + num_real_crtc = xf86_config->num_crtc; + num_real_output = xf86_config->num_output; + + if (num_real_crtc == 0) + xf86CrtcConfigInit(sna->scrn, &sna_mode_funcs); + + for (n = 0; n < num_fake; n++) { + if (!sna_crtc_fake(sna)) + return false; + + if (!sna_output_fake(sna, n, num_fake, + num_real_crtc, num_real_output)) + return false; + } + + return true; } |