summaryrefslogtreecommitdiff
path: root/src/sna/sna_display_fake.c
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 /src/sna/sna_display_fake.c
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>
Diffstat (limited to 'src/sna/sna_display_fake.c')
-rw-r--r--src/sna/sna_display_fake.c177
1 files changed, 121 insertions, 56 deletions
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;
}