xf86-video-intel: 3 commits - man/intel.man src/intel_options.c src/intel_options.h src/sna/sna_display.c src/sna/sna_display_fake.c src/sna/sna_dri.c src/sna/sna.h

Chris Wilson ickle at kemper.freedesktop.org
Fri Aug 30 01:00:23 PDT 2013


 man/intel.man              |   12 ++++++++
 src/intel_options.c        |    1 
 src/intel_options.h        |    1 
 src/sna/sna.h              |    6 ++--
 src/sna/sna_display.c      |   62 +++++++++++++++++++++++++++++++++------------
 src/sna/sna_display_fake.c |   40 +++++++++++++++++++++++------
 src/sna/sna_dri.c          |   24 ++++++++++-------
 7 files changed, 110 insertions(+), 36 deletions(-)

New commits:
commit 6d99249c580cfb062a05ce1da446410741eb1223
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date:   Fri Aug 30 03:03:58 2013 +0100

    sna: Protect against unattached pixmaps when peeking inside for a GPU bo
    
    Prevent a NULL dereference for the small system pixmaps. Introduced with
    
    commit f22d7f68b8b1bd5caf5ae831fca63eb1e6957520
    Author: Chris Wilson <chris at chris-wilson.co.uk>
    Date:   Wed Aug 28 14:24:33 2013 +0100
    
        sna/gen6+: Improve ring stickyness for BLT composite ops
    
    Reported-by: Sami Farin <hvtaifwkbgefbaei at gmail.com>
    Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=68728
    Signed-off-by: Chris Wilson <chris at chris-wilson.co.uk>

diff --git a/src/sna/sna.h b/src/sna/sna.h
index 5b26ebf..298883c 100644
--- a/src/sna/sna.h
+++ b/src/sna/sna.h
@@ -176,6 +176,7 @@ static inline PixmapPtr get_window_pixmap(WindowPtr window)
 
 static inline PixmapPtr get_drawable_pixmap(DrawablePtr drawable)
 {
+	assert(drawable);
 	if (drawable->type == DRAWABLE_PIXMAP)
 		return (PixmapPtr)drawable;
 	else
@@ -619,7 +620,8 @@ static inline struct kgem_bo *__sna_pixmap_get_bo(PixmapPtr pixmap)
 
 static inline struct kgem_bo *__sna_drawable_peek_bo(DrawablePtr d)
 {
-	return sna_pixmap(get_drawable_pixmap(d))->gpu_bo;
+	struct sna_pixmap *priv = sna_pixmap(get_drawable_pixmap(d));
+	return priv ? priv->gpu_bo : NULL;
 }
 
 static inline struct kgem_bo *sna_pixmap_pin(PixmapPtr pixmap, unsigned flags)
commit 314cfd7353c8c1acd961fdfc8eadbc0d55fa0f01
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date:   Thu Aug 29 21:30:28 2013 +0100

    sna/dri: Correct the target_msc for immediate double-buffering
    
    We also need to correctly offset the current_msc for the normal
    pageflip, so rearrange the code flow so that we only do the calculation
    of target_msc once.
    
    Signed-off-by: Chris Wilson <chris at chris-wilson.co.uk>

diff --git a/src/sna/sna_dri.c b/src/sna/sna_dri.c
index 1eec740..44c2749 100644
--- a/src/sna/sna_dri.c
+++ b/src/sna/sna_dri.c
@@ -1044,6 +1044,11 @@ sna_dri_page_flip(struct sna *sna, struct sna_dri_frame_event *info)
 	if (!info->count)
 		return false;
 
+	DBG(("%s: mark handle=%d as scanout, swap front (handle=%d, name=%d) and back (handle=%d, name=%d)\n",
+	     __FUNCTION__, bo->handle,
+	     get_private(info->front)->bo->handle, info->front->name,
+	     get_private(info->back)->bo->handle, info->back->name));
+
 	info->scanout[1] = info->scanout[0];
 	info->scanout[0].bo = ref(bo);
 	info->scanout[0].name = info->back->name;
@@ -1589,8 +1594,8 @@ static void sna_dri_flip_event(struct sna *sna,
 	/* We assume our flips arrive in order, so we don't check the frame */
 	switch (flip->type) {
 	case DRI2_FLIP:
-		DBG(("%s: flip complete (drawable gone? %d)\n",
-		     __FUNCTION__, flip->draw == NULL));
+		DBG(("%s: flip complete (drawable gone? %d), msc=%d\n",
+		     __FUNCTION__, flip->draw == NULL, flip->fe_frame));
 		if (flip->draw)
 			DRI2SwapComplete(flip->client, flip->draw,
 					 flip->fe_frame,
@@ -1784,17 +1789,15 @@ sna_dri_schedule_flip(ClientPtr client, DrawablePtr draw,
 			     __FUNCTION__));
 			info->type = DRI2_FLIP;
 			sna->dri.flip_pending = info;
-			*target_msc = current_msc + 1;
-			return true;
-		}
-
-		if (!sna_dri_page_flip(sna, info)) {
-			sna_dri_frame_event_info_free(sna, draw, info);
-			return false;
+		} else {
+			if (!sna_dri_page_flip(sna, info)) {
+				sna_dri_frame_event_info_free(sna, draw, info);
+				return false;
+			}
 		}
 
+		current_msc++;
 		if (info->type != DRI2_FLIP) {
-			current_msc++;
 new_back:
 			sna_dri_flip_get_back(sna, info);
 			DRI2SwapComplete(client, draw, 0, 0, 0,
@@ -1802,6 +1805,7 @@ new_back:
 					 func, data);
 		}
 out:
+		DBG(("%s: target_msc=%lu\n", __FUNCTION__, (unsigned long)current_msc));
 		*target_msc = current_msc;
 		return true;
 	}
commit 68d139388a2a037347fa5c838391e67e006793ee
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date:   Thu Aug 29 23:00:05 2013 +0100

    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 at chris-wilson.co.uk>

diff --git a/man/intel.man b/man/intel.man
index 9e19687..0a26511 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 b81bde6..153cc62 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 112983d..095660c 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 337ebc8..5b26ebf 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 da3475f..aa445ae 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 6231eb5..afd5588 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;
 }


More information about the xorg-commit mailing list