xf86-video-intel: 6 commits - src/intel_options.c src/intel_options.h src/sna/sna_display.c src/sna/sna_dri.c src/sna/sna_driver.c src/sna/sna.h src/sna/sna_threads.c

Chris Wilson ickle at kemper.freedesktop.org
Thu May 8 06:23:02 PDT 2014


 src/intel_options.c   |    1 
 src/intel_options.h   |    1 
 src/sna/sna.h         |    1 
 src/sna/sna_display.c |   41 +++++++--
 src/sna/sna_dri.c     |  221 ++++++++++++++++++++++++++++++++++++--------------
 src/sna/sna_driver.c  |    3 
 src/sna/sna_threads.c |   13 ++
 7 files changed, 212 insertions(+), 69 deletions(-)

New commits:
commit ad01e1c8700caeaf0288b72450646d7ebe7cce93
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date:   Thu May 8 13:02:15 2014 +0100

    sna: Fix another assignment inside an assert
    
    Another recent introduction, spotted by Rinat Ibragimov.
    
    Signed-off-by: Chris Wilson <chris at chris-wilson.co.uk>

diff --git a/src/sna/sna_display.c b/src/sna/sna_display.c
index 51b4db6..eda6c5b 100644
--- a/src/sna/sna_display.c
+++ b/src/sna/sna_display.c
@@ -3014,7 +3014,7 @@ static void sort_randr_outputs(struct sna *sna, ScreenPtr screen)
 	rrScrPriv(screen);
 	int i;
 
-	assert(pScrPriv->numOutputs = config->num_output);
+	assert(pScrPriv->numOutputs == config->num_output);
 	for (i = 0; i < config->num_output; i++) {
 		assert(config->output[i]->randr_output);
 		pScrPriv->outputs[i] = config->output[i]->randr_output;
commit e78a00c5da922024ac64270fae0797d98d1d6e57
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date:   Thu May 8 06:45:43 2014 +0100

    sna: Add an xorg.conf option for removing unused outputs
    
    Clients are not yet ready for outputs that disappear at runtime, often
    unexpectedly dieing with asynchronous BadOutput errors. A simple
    workaround is to not remove any output just yet - but allow users to opt
    in via xorg.conf, i.e.
    
    Section "Device"
      Option "DeleteUnusedDP12Displays" "true"
    EndSection
    
    The name chosen is to be consistent with the nvidia driver, which did
    MST first and encountered all of these issues first, and has also been
    adopted for -modesetting. If this is combined with persistent output
    naming (i.e. based on DisplayPort branch topology), the number of
    outputs presented to the user should be static.
    
    Instead of removing the outputs, we have to mark them detached instead
    to avoid throwing errors from the kernel.
    
    Based on the patch for -modesetting by Dave Airlie.
    Signed-off-by: Chris Wilson <chris at chris-wilson.co.uk>

diff --git a/src/intel_options.c b/src/intel_options.c
index 02a4ae1..51d5462 100644
--- a/src/intel_options.c
+++ b/src/intel_options.c
@@ -20,6 +20,7 @@ const OptionInfoRec intel_options[] = {
 	{OPTION_PREFER_OVERLAY, "XvPreferOverlay", OPTV_BOOLEAN, {0}, 0},
 	{OPTION_HOTPLUG,	"HotPlug",	OPTV_BOOLEAN,	{0},	1},
 	{OPTION_REPROBE,	"ReprobeOutputs", OPTV_BOOLEAN,	{0},	0},
+	{OPTION_DELETE_DP12,	"DeleteUnusedDP12Displays", OPTV_BOOLEAN,	{0},	0},
 #ifdef INTEL_XVMC
 	{OPTION_XVMC,		"XvMC",		OPTV_BOOLEAN,	{0},	1},
 #endif
diff --git a/src/intel_options.h b/src/intel_options.h
index 77f0c45..6873a6d 100644
--- a/src/intel_options.h
+++ b/src/intel_options.h
@@ -27,6 +27,7 @@ enum intel_options {
 	OPTION_PREFER_OVERLAY,
 	OPTION_HOTPLUG,
 	OPTION_REPROBE,
+	OPTION_DELETE_DP12,
 #if defined(XvMCExtension) && defined(ENABLE_XVMC)
 	OPTION_XVMC,
 #define INTEL_XVMC 1
diff --git a/src/sna/sna.h b/src/sna/sna.h
index 75a0e36..3a45924 100644
--- a/src/sna/sna.h
+++ b/src/sna/sna.h
@@ -244,6 +244,7 @@ struct sna {
 #define SNA_IS_HOSTED		0x80
 #define SNA_PERFORMANCE		0x100
 #define SNA_POWERSAVE		0x200
+#define SNA_REMOVE_OUTPUTS	0x400
 #define SNA_REDISCOVER		0x40000000
 #define SNA_REPROBE		0x80000000
 
diff --git a/src/sna/sna_display.c b/src/sna/sna_display.c
index af71f11..51b4db6 100644
--- a/src/sna/sna_display.c
+++ b/src/sna/sna_display.c
@@ -172,6 +172,8 @@ static inline struct sna_output *to_sna_output(xf86OutputPtr output)
 
 static inline int to_connector_id(xf86OutputPtr output)
 {
+	assert(to_sna_output(output));
+	assert(to_sna_output(output)->id);
 	return to_sna_output(output)->id;
 }
 
@@ -1904,7 +1906,10 @@ sna_output_detect(xf86OutputPtr output)
 	struct sna_output *sna_output = output->driver_private;
 	union compat_mode_get_connector compat_conn;
 
-	DBG(("%s(%s)\n", __FUNCTION__, output->name));
+	DBG(("%s(%s:%d)\n", __FUNCTION__, output->name, sna_output->id));
+
+	if (!sna_output->id)
+		return XF86OutputStatusDisconnected;
 
 	VG_CLEAR(compat_conn);
 	compat_conn.conn.connector_id = sna_output->id;
@@ -2134,7 +2139,8 @@ sna_output_get_modes(xf86OutputPtr output)
 	DisplayModePtr Modes = NULL, Mode, current = NULL;
 	int i;
 
-	DBG(("%s(%s)\n", __FUNCTION__, output->name));
+	DBG(("%s(%s:%d)\n", __FUNCTION__, output->name, sna_output->id));
+	assert(sna_output->id);
 
 	sna_output_attach_edid(output);
 
@@ -2245,7 +2251,7 @@ sna_output_dpms_backlight(xf86OutputPtr output, int oldmode, int mode)
 	if (!sna_output->backlight.iface)
 		return;
 
-	DBG(("%s(%s) -- %d -> %d\n", __FUNCTION__, output->name, oldmode, mode));
+	DBG(("%s(%s:%d) -- %d -> %d\n", __FUNCTION__, output->name, sna_output->id, oldmode, mode));
 
 	if (mode == DPMSModeOn) {
 		/* If we're going from off->on we may need to turn on the backlight. */
@@ -2266,11 +2272,14 @@ sna_output_dpms(xf86OutputPtr output, int dpms)
 	struct sna *sna = to_sna(output->scrn);
 	struct sna_output *sna_output = output->driver_private;
 
-	DBG(("%s(%s): dpms=%d (current: %d), active? %d\n",
-	     __FUNCTION__, output->name,
+	DBG(("%s(%s:%d): dpms=%d (current: %d), active? %d\n",
+	     __FUNCTION__, output->name, sna_output->id,
 	     dpms, sna_output->dpms_mode,
 	     output->crtc != NULL));
 
+	if (!sna_output->id)
+		return;
+
 	if (sna_output->dpms_mode == dpms)
 		return;
 
@@ -2465,6 +2474,9 @@ sna_output_set_property(xf86OutputPtr output, Atom property,
 		return TRUE;
 	}
 
+	if (!sna_output->id)
+		return TRUE;
+
 	for (i = 0; i < sna_output->num_props; i++) {
 		struct sna_property *p = &sna_output->props[i];
 
@@ -2725,8 +2737,13 @@ sna_mode_compute_possible_outputs(struct sna *sna)
 
 		assert(sna_output);
 
-		output->possible_clones = sna_output->possible_encoders;
-		encoder_mask[i] = sna_output->attached_encoders;
+		if (sna_output->id) {
+			output->possible_clones = sna_output->possible_encoders;
+			encoder_mask[i] = sna_output->attached_encoders;
+		} else {
+			output->possible_clones = 0;
+			encoder_mask[i] = 0;
+		}
 	}
 
 	/* Convert from encoder numbering to output numbering */
@@ -3045,7 +3062,12 @@ void sna_mode_discover(struct sna *sna)
 	for (i = 0; i < sna->mode.num_real_output; i++) {
 		xf86OutputPtr output = config->output[i];
 		if (to_sna_output(output)->serial != serial) {
-			sna_output_del(output); i--;
+			if (sna->flags & SNA_REMOVE_OUTPUTS) {
+				sna_output_del(output); i--;
+			} else {
+				to_sna_output(output)->id = 0;
+				output->crtc = NULL;
+			}
 			changed = true;
 		}
 	}
diff --git a/src/sna/sna_driver.c b/src/sna/sna_driver.c
index f1a30dc..58e5cbc 100644
--- a/src/sna/sna_driver.c
+++ b/src/sna/sna_driver.c
@@ -564,6 +564,9 @@ static Bool sna_pre_init(ScrnInfoPtr scrn, int flags)
 	if (xf86ReturnOptValBool(sna->Options, OPTION_TILING_FB, FALSE))
 		sna->tiling &= ~SNA_TILING_FB;
 
+	if (xf86ReturnOptValBool(sna->Options, OPTION_DELETE_DP12, FALSE))
+		sna->flags |= SNA_REMOVE_OUTPUTS;
+
 	if (!xf86ReturnOptValBool(sna->Options, OPTION_SWAPBUFFERS_WAIT, TRUE))
 		sna->flags |= SNA_NO_WAIT;
 	DBG(("%s: swapbuffer wait? %s\n", __FUNCTION__, sna->flags & SNA_NO_WAIT ? "disabled" : "enabled"));
commit a93157587a82c699e7df76fb482c49569f0686b9
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date:   Wed May 7 21:20:56 2014 +0100

    sna: Tidy thread handling under valgrind
    
    If valgrind is running, keep it simple and avoid using unknown
    instructions (causing valgrind to die with SIGILL).
    
    Signed-off-by: Chris Wilson <chris at chris-wilson.co.uk>

diff --git a/src/sna/sna_threads.c b/src/sna/sna_threads.c
index 1310972..f263d24 100644
--- a/src/sna/sna_threads.c
+++ b/src/sna/sna_threads.c
@@ -35,6 +35,13 @@
 #include <pthread.h>
 #include <signal.h>
 
+#ifdef HAVE_VALGRIND
+#include <valgrind.h>
+static inline bool valgrind_active(void) { return RUNNING_ON_VALGRIND; }
+#else
+static inline bool valgrind_active(void) { return false; }
+#endif
+
 static int max_threads = -1;
 
 static struct thread {
@@ -131,6 +138,9 @@ void sna_threads_init(void)
 	if (max_threads != -1)
 		return;
 
+	if (valgrind_active())
+		goto bail;
+
 	max_threads = num_cores();
 	if (max_threads == 0)
 		max_threads = sysconf(_SC_NPROCESSORS_ONLN) / 2;
@@ -182,6 +192,9 @@ void sna_threads_trap(int sig)
 	pthread_t t = pthread_self();
 	int n;
 
+	if (max_threads == 0)
+		return;
+
 	if (t == threads[0].thread)
 		return;
 
commit efd9e9c3eeb83b9e5725fa642066925d608c059d
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date:   Wed May 7 21:19:57 2014 +0100

    sna/dri: Use move-area-to-gpu to handle clipped regions more efficiently
    
    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 f30770f..9b882a7 100644
--- a/src/sna/sna_dri.c
+++ b/src/sna/sna_dri.c
@@ -747,14 +747,10 @@ __sna_dri_copy_region(struct sna *sna, DrawablePtr draw, RegionPtr region,
 		unsigned int flags;
 
 		flags = MOVE_WRITE | __MOVE_FORCE;
-		if (clip.data ||
-		    clip.extents.x1 > 0 ||
-		    clip.extents.x2 < pixmap->drawable.width ||
-		    clip.extents.y1 > 0 ||
-		    clip.extents.y2 < pixmap->drawable.height)
+		if (clip.data)
 			flags |= MOVE_READ;
 
-		priv = sna_pixmap_move_to_gpu(pixmap, flags);
+		priv = sna_pixmap_move_area_to_gpu(pixmap, &clip.extents, flags);
 		if (priv) {
 			damage(pixmap, priv, region);
 			dst_bo = priv->gpu_bo;
commit 1385ca9eeb26b0b82b623da619a65036830ccceb
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date:   Wed May 7 21:19:32 2014 +0100

    sna: Initialize value read through ioctl to please valgrind
    
    Signed-off-by: Chris Wilson <chris at chris-wilson.co.uk>

diff --git a/src/sna/sna_display.c b/src/sna/sna_display.c
index df80f1e..af71f11 100644
--- a/src/sna/sna_display.c
+++ b/src/sna/sna_display.c
@@ -3890,6 +3890,7 @@ sna_cursor_pre_init(struct sna *sna)
 
 	sna->cursor.max_size = 64;
 
+	cap.value = 0;
 	cap.name = DRM_CAP_CURSOR_WIDTH;
 	if (drmIoctl(sna->kgem.fd, LOCAL_IOCTL_GET_CAP, &cap) == 0)
 		sna->cursor.max_size = cap.value;
commit 7d516589ba9d0325e57e08d41becff64f81e2d00
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date:   Wed May 7 17:49:15 2014 +0100

    sna/dri: Implement TripleBuffering using DRI2SwapLimit
    
    An addition to DRI2 that was overlooked at the time, was the support
    added for having multiple outstanding swap requests in the core. The
    importance of this is that we can then send the SwapComplete reply after
    the pageflip is completed and not before as we currently do to fake
    triple buffering - in clear violation of OML_sync_control.
    
    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 89d707a..f30770f 100644
--- a/src/sna/sna_dri.c
+++ b/src/sna/sna_dri.c
@@ -55,6 +55,17 @@ USE OR OTHER DEALINGS IN THE SOFTWARE.
 #error DRI2 version supported by the Xserver is too old
 #endif
 
+#if DRI2INFOREC_VERSION < 6
+#define XORG_CAN_TRIPLE_BUFFER 0
+#else
+#define XORG_CAN_TRIPLE_BUFFER 1
+static Bool
+sna_dri_swap_limit_validate(DrawablePtr draw, int swap_limit)
+{
+	return swap_limit >= 1;
+}
+#endif
+
 #if DRI2INFOREC_VERSION < 10
 #undef USE_ASYNC_SWAP
 #define USE_ASYNC_SWAP 0
@@ -969,6 +980,7 @@ sna_dri_window_set_chain(WindowPtr win,
 {
 	DBG(("%s: head now %p\n", __FUNCTION__, chain));
 	assert(win->drawable.type == DRAWABLE_WINDOW);
+	assert(sna_dri_window_get_chain(win) != chain);
 	((void **)__get_private(win, sna_window_key))[1] = chain;
 }
 
@@ -1121,6 +1133,11 @@ sna_dri_page_flip(struct sna *sna, struct sna_dri_frame_event *info)
 	get_private(info->back)->bo = tmp.bo;
 
 	sna->dri.flip_pending = info;
+
+#if XORG_CAN_TRIPLE_BUFFER
+	DRI2SwapLimit(info->draw, 1 + (info->type == DRI2_FLIP_THROTTLE));
+#endif
+
 	return true;
 }
 
@@ -1304,48 +1321,53 @@ static void chain_swap(struct sna *sna,
 	DBG(("%s: chaining type=%d\n", __FUNCTION__, chain->type));
 	switch (chain->type) {
 	case DRI2_SWAP_THROTTLE:
-		break;
-	default:
-		return;
-	}
-
-	DBG(("%s: emitting chained vsync'ed blit\n", __FUNCTION__));
-
-	if (sna->mode.shadow_flip && !sna->mode.shadow_damage) {
-		/* recursed from wait_for_shadow(), simply requeue */
-		DBG(("%s -- recursed from wait_for_shadow(), requeuing\n", __FUNCTION__));
-		chain->type = DRI2_SWAP;
+		DBG(("%s: emitting chained vsync'ed blit\n", __FUNCTION__));
+		if (sna->mode.shadow_flip && !sna->mode.shadow_damage) {
+			/* recursed from wait_for_shadow(), simply requeue */
+			DBG(("%s -- recursed from wait_for_shadow(), requeuing\n", __FUNCTION__));
+			chain->type = DRI2_SWAP;
 
-		VG_CLEAR(vbl);
-		vbl.request.type =
-			DRM_VBLANK_RELATIVE |
-			DRM_VBLANK_EVENT;
-		vbl.request.sequence = 1;
-		vbl.request.signal = (unsigned long)chain;
+			VG_CLEAR(vbl);
+			vbl.request.type =
+				DRM_VBLANK_RELATIVE |
+				DRM_VBLANK_EVENT;
+			vbl.request.sequence = 1;
+			vbl.request.signal = (unsigned long)chain;
 
-		if (!sna_wait_vblank(sna, &vbl, chain->pipe))
-			return;
+			if (!sna_wait_vblank(sna, &vbl, chain->pipe))
+				return;
 
-		DBG(("%s -- requeue failed, errno=%d\n", __FUNCTION__, errno));
-	} else {
-		chain->bo = __sna_dri_copy_region(sna, draw, NULL,
-						  chain->back, chain->front, true);
+			DBG(("%s -- requeue failed, errno=%d\n", __FUNCTION__, errno));
+		} else {
+			chain->bo = __sna_dri_copy_region(sna, draw, NULL,
+							  chain->back, chain->front, true);
+		}
+	case DRI2_SWAP:
+		break;
+	default:
+		return;
 	}
 
-	DRI2SwapComplete(chain->client, draw,
-			 frame, tv_sec, tv_usec,
-			 DRI2_BLIT_COMPLETE,
-			 chain->client ? chain->event_complete : NULL, chain->event_data);
-
 	VG_CLEAR(vbl);
 	vbl.request.type =
 		DRM_VBLANK_RELATIVE |
-		DRM_VBLANK_NEXTONMISS |
 		DRM_VBLANK_EVENT;
-	vbl.request.sequence = 0;
+	vbl.request.sequence = 1;
 	vbl.request.signal = (unsigned long)chain;
-	if (sna_wait_vblank(sna, &vbl, chain->pipe))
+	if (sna_wait_vblank(sna, &vbl, chain->pipe)) {
+		DRI2SwapComplete(chain->client, draw,
+				 frame, tv_sec, tv_usec,
+				 DRI2_BLIT_COMPLETE,
+				 chain->client ? chain->event_complete : NULL, chain->event_data);
 		sna_dri_frame_event_info_free(sna, draw, chain);
+	} else {
+#if !XORG_CAN_TRIPLE_BUFFER
+		DRI2SwapComplete(chain->client, draw,
+				 frame, tv_sec, tv_usec,
+				 DRI2_BLIT_COMPLETE,
+				 chain->client ? chain->event_complete : NULL, chain->event_data);
+#endif
+	}
 }
 
 static bool sna_dri_blit_complete(struct sna *sna,
@@ -1432,6 +1454,18 @@ void sna_dri_vblank_handler(struct sna *sna, struct drm_event_vblank *event)
 		DBG(("%s: %d complete, frame=%d tv=%d.%06d\n",
 		     __FUNCTION__, info->type,
 		     event->sequence, event->tv_sec, event->tv_usec));
+
+#if XORG_CAN_TRIPLE_BUFFER
+		if (!sna_dri_blit_complete(sna, info))
+			return;
+
+		DRI2SwapComplete(info->client,
+				 draw, event->sequence,
+				 event->tv_sec, event->tv_usec,
+				 DRI2_BLIT_COMPLETE,
+				 info->client ? info->event_complete : NULL,
+				 info->event_data);
+#endif
 		break;
 
 	case DRI2_WAITMSC:
@@ -1448,6 +1482,7 @@ void sna_dri_vblank_handler(struct sna *sna, struct drm_event_vblank *event)
 	}
 
 	if (info->chain) {
+		assert(info->chain != info);
 		sna_dri_remove_frame_event((WindowPtr)draw, info);
 		chain_swap(sna, draw,
 			   event->sequence, event->tv_sec, event->tv_usec,
@@ -1475,10 +1510,7 @@ sna_dri_immediate_blit(struct sna *sna,
 	     event));
 
 	if (sync) {
-		info->type = DRI2_SWAP_THROTTLE;
 		if (sna_dri_window_get_chain((WindowPtr)draw) == info) {
-			drmVBlank vbl;
-
 			DBG(("%s: no pending blit, starting chain\n",
 			     __FUNCTION__));
 
@@ -1487,24 +1519,59 @@ sna_dri_immediate_blit(struct sna *sna,
 							 info->front,
 							 true);
 			if (event) {
-				DRI2SwapComplete(info->client, draw, 0, 0, 0,
-						 DRI2_BLIT_COMPLETE,
-						 info->event_complete,
-						 info->event_data);
+				drmVBlank vbl;
+
+				info->type = DRI2_SWAP_THROTTLE;
 
 				VG_CLEAR(vbl);
 				vbl.request.type =
 					DRM_VBLANK_RELATIVE |
-					DRM_VBLANK_NEXTONMISS |
 					DRM_VBLANK_EVENT;
-				vbl.request.sequence = 0;
+				vbl.request.sequence = 1;
 				vbl.request.signal = (unsigned long)info;
 				ret = !sna_wait_vblank(sna, &vbl, info->pipe);
+#if XORG_CAN_TRIPLE_BUFFER
+				if (ret)
+					DRI2SwapLimit(draw, 2);
+#endif
+				if (!XORG_CAN_TRIPLE_BUFFER || !ret)
+					DRI2SwapComplete(info->client, draw, 0, 0, 0,
+							 DRI2_BLIT_COMPLETE,
+							 info->event_complete,
+							 info->event_data);
 			}
 		} else {
 			DBG(("%s: pending blit, chained\n", __FUNCTION__));
 			ret = true;
 		}
+#if XORG_CAN_TRIPLE_BUFFER
+	} else if (event) {
+		if (sna_dri_window_get_chain((WindowPtr)draw) == info) {
+			drmVBlank vbl;
+
+			info->type = DRI2_SWAP_THROTTLE;
+			info->bo = __sna_dri_copy_region(sna, draw, NULL,
+							 info->back, info->front, false);
+
+			VG_CLEAR(vbl);
+			vbl.request.type =
+				DRM_VBLANK_RELATIVE |
+				DRM_VBLANK_EVENT;
+			vbl.request.sequence = 1;
+			vbl.request.signal = (unsigned long)info;
+			ret = !sna_wait_vblank(sna, &vbl, info->pipe);
+			if (ret)
+				DRI2SwapLimit(draw, 2);
+			else
+				DRI2SwapComplete(info->client, draw, 0, 0, 0,
+						 DRI2_BLIT_COMPLETE,
+						 info->event_complete,
+						 info->event_data);
+		} else {
+			DBG(("%s: pending blit, chained\n", __FUNCTION__));
+			ret = true;
+		}
+#endif
 	} else {
 		DBG(("%s: immediate blit\n", __FUNCTION__));
 		info->bo = __sna_dri_copy_region(sna, draw, NULL,
@@ -1618,11 +1685,13 @@ sna_dri_flip_continue(struct sna *sna, struct sna_dri_frame_event *info)
 			return false;
 
 		sna_dri_flip_get_back(sna, info);
+#if !XORG_CAN_TRIPLE_BUFFER
 		DRI2SwapComplete(info->client, info->draw,
 				 0, 0, 0,
 				 DRI2_FLIP_COMPLETE,
 				 info->client ? info->event_complete : NULL,
 				 info->event_data);
+#endif
 	}
 
 	info->mode = 0;
@@ -1653,6 +1722,23 @@ static void chain_flip(struct sna *sna)
 		chain->bo = __sna_dri_copy_region(sna, chain->draw, NULL,
 						  chain->back, chain->front,
 						  true);
+#if XORG_CAN_TRIPLE_BUFFER
+		{
+			drmVBlank vbl;
+
+			VG_CLEAR(vbl);
+
+			chain->type = DRI2_SWAP_WAIT;
+			vbl.request.type =
+				DRM_VBLANK_RELATIVE |
+				DRM_VBLANK_EVENT;
+			vbl.request.sequence = 1;
+			vbl.request.signal = (unsigned long)chain;
+
+			if (!sna_wait_vblank(sna, &vbl, chain->pipe))
+				return;
+		}
+#endif
 		DRI2SwapComplete(chain->client, chain->draw, 0, 0, 0,
 				 DRI2_BLIT_COMPLETE, chain->client ? chain->event_complete : NULL, chain->event_data);
 		sna_dri_frame_event_info_free(sna, chain->draw, chain);
@@ -1729,6 +1815,16 @@ static void sna_dri_flip_event(struct sna *sna,
 		break;
 
 	case DRI2_FLIP_THROTTLE:
+#if XORG_CAN_TRIPLE_BUFFER
+		if (flip->draw)
+			DRI2SwapComplete(flip->client, flip->draw,
+					 flip->fe_frame,
+					 flip->fe_tv_sec,
+					 flip->fe_tv_usec,
+					 DRI2_FLIP_COMPLETE,
+					 flip->client ? flip->event_complete : NULL,
+					 flip->event_data);
+#endif
 		if (sna->dri.flip_pending) {
 			sna_dri_frame_event_info_free(sna, flip->draw, flip);
 			chain_flip(sna);
@@ -1804,29 +1900,32 @@ get_current_msc_for_target(struct sna *sna, CARD64 target_msc, int pipe)
 	return ret;
 }
 
+#if !XORG_CAN_TRIPLE_BUFFER && XORG_VERSION_CURRENT >= XORG_VERSION_NUMERIC(1,12,99,901,0)
 static Bool find(pointer value, XID id, pointer cdata)
 {
 	return TRUE;
 }
+#endif
 
 static int use_triple_buffer(struct sna *sna, ClientPtr client)
 {
-	struct sna_client *priv;
-
 	if ((sna->flags & SNA_TRIPLE_BUFFER) == 0)
 		return DRI2_FLIP;
 
+#if XORG_CAN_TRIPLE_BUFFER
+	return DRI2_FLIP_THROTTLE;
+#elif XORG_VERSION_CURRENT >= XORG_VERSION_NUMERIC(1,12,99,901,0)
 	/* Hack: Disable triple buffering for compositors */
+	{
+		struct sna_client *priv = sna_client(client);
+		if (priv->is_compositor == 0)
+			priv->is_compositor =
+				LookupClientResourceComplex(client,
+							    CompositeClientWindowType+1,
+							    find, NULL) ? DRI2_FLIP : DRI2_FLIP_THROTTLE;
 
-#if XORG_VERSION_CURRENT >= XORG_VERSION_NUMERIC(1,12,99,901,0)
-	priv = sna_client(client);
-	if (priv->is_compositor == 0)
-		priv->is_compositor =
-			LookupClientResourceComplex(client,
-						    CompositeClientWindowType+1,
-						    find, NULL) ? DRI2_FLIP : DRI2_FLIP_THROTTLE;
-
-	return priv->is_compositor;
+		return priv->is_compositor;
+	}
 #else
 	return DRI2_FLIP_THROTTLE;
 #endif
@@ -1919,9 +2018,11 @@ sna_dri_schedule_flip(ClientPtr client, DrawablePtr draw,
 		if (info->type != DRI2_FLIP) {
 new_back:
 			sna_dri_flip_get_back(sna, info);
+#if !XORG_CAN_TRIPLE_BUFFER
 			DRI2SwapComplete(client, draw, 0, 0, 0,
 					 DRI2_EXCHANGE_COMPLETE,
 					 func, data);
+#endif
 		}
 out:
 		DBG(("%s: target_msc=%lu\n", __FUNCTION__, (unsigned long)current_msc));
@@ -2010,6 +2111,10 @@ out:
 		return false;
 	}
 
+#if XORG_CAN_TRIPLE_BUFFER
+	DRI2SwapLimit(draw, 1);
+#endif
+
 	return true;
 }
 
@@ -2345,10 +2450,10 @@ sna_dri_schedule_wait_msc(ClientPtr client, DrawablePtr draw, CARD64 target_msc,
 			vbl.request.sequence += divisor;
 	}
 
+	DBG(("%s: waiting until MSC=%llu\n", __FUNCTION__, (long long)vbl.request.sequence));
 	if (sna_wait_vblank(sna, &vbl, pipe))
 		goto out_free_info;
 
-	DBG(("%s: waiting until MSC=%llu\n", __FUNCTION__, (long long)vbl.request.sequence));
 	DRI2BlockClient(client, draw);
 	return TRUE;
 
@@ -2506,9 +2611,9 @@ bool sna_dri_open(struct sna *sna, ScreenPtr screen)
 	driverNames[1] = info.driverName;
 #endif
 
-#if DRI2INFOREC_VERSION >= 6
+#if XORG_CAN_TRIPLE_BUFFER
 	info.version = 6;
-	info.SwapLimitValidate = NULL;
+	info.SwapLimitValidate = sna_dri_swap_limit_validate;
 	info.ReuseBufferNotify = NULL;
 #endif
 


More information about the xorg-commit mailing list