[Date Prev][Date Next] [Thread Prev][Thread Next] [Date Index] [Thread Index]

xserver-xorg-video-intel: Changes to 'upstream-experimental'



 NEWS                                  |   14 
 configure.ac                          |   29 -
 libobj/alloca.c                       |    4 
 man/intel.man                         |    4 
 src/backlight.c                       |   68 +-
 src/backlight.h                       |    2 
 src/i915_pciids.h                     |   53 +-
 src/intel_device.c                    |    6 
 src/intel_list.h                      |   31 +
 src/intel_module.c                    |   62 +-
 src/intel_options.c                   |    1 
 src/intel_options.h                   |    1 
 src/legacy/i810/i810_common.h         |    4 
 src/legacy/i810/i810_hwmc.c           |    2 
 src/legacy/i810/i810_reg.h            |    2 
 src/legacy/i810/xvmc/I810XvMC.c       |    6 
 src/render_program/exa_wm.g4i         |    2 
 src/render_program/exa_wm_yuv_rgb.g8a |    4 
 src/render_program/exa_wm_yuv_rgb.g8b |    2 
 src/sna/blt.c                         |  549 +++++------------------
 src/sna/brw/brw_eu_emit.c             |    2 
 src/sna/compiler.h                    |   14 
 src/sna/gen6_common.h                 |   17 
 src/sna/gen6_render.c                 |   75 ++-
 src/sna/gen7_render.c                 |   80 ++-
 src/sna/gen8_render.c                 |  120 +++--
 src/sna/kgem.c                        |  798 +++++++++++++++++++++++----------
 src/sna/kgem.h                        |   34 +
 src/sna/kgem_debug_gen4.c             |    2 
 src/sna/kgem_debug_gen5.c             |    2 
 src/sna/kgem_debug_gen6.c             |    2 
 src/sna/sna.h                         |   54 ++
 src/sna/sna_accel.c                   |  413 ++++++++++-------
 src/sna/sna_blt.c                     |  137 ++---
 src/sna/sna_display.c                 |  803 +++++++++++++++++++++++-----------
 src/sna/sna_dri2.c                    |  655 ++++++++++++++++-----------
 src/sna/sna_dri3.c                    |   13 
 src/sna/sna_driver.c                  |   30 -
 src/sna/sna_glyphs.c                  |   92 ++-
 src/sna/sna_io.c                      |   22 
 src/sna/sna_present.c                 |  144 ++++--
 src/sna/sna_render.c                  |   16 
 src/sna/sna_render.h                  |    9 
 src/sna/sna_tiling.c                  |    4 
 src/sna/sna_trapezoids_boxes.c        |    4 
 src/sna/sna_trapezoids_imprecise.c    |    4 
 src/sna/sna_trapezoids_mono.c         |   52 +-
 src/sna/sna_trapezoids_precise.c      |    4 
 src/sna/sna_video_sprite.c            |   18 
 src/uxa/intel_display.c               |   59 +-
 src/uxa/intel_driver.c                |   13 
 src/uxa/intel_memory.c                |    2 
 test/.gitignore                       |    4 
 test/Makefile.am                      |    4 
 test/dri2-speed.c                     |  342 ++++++++++++++
 test/dri2-test.c                      |   48 +-
 test/dri3-test.c                      |   62 ++
 test/dri3.c                           |   34 +
 test/present-speed.c                  |  615 ++++++++++++++++++++++++++
 test/present-test.c                   |  399 ++++++++++++++--
 test/render-glyphs.c                  |  441 ++++++++++++++++++
 test/render-trapezoid.c               |  125 +++++
 test/render-triangle.c                |  180 +++++++
 test/test.h                           |    9 
 test/test_image.c                     |   36 -
 tools/Makefile.am                     |    6 
 tools/backlight_helper.c              |    6 
 tools/dri3info.c                      |  212 ++++++++
 tools/virtual.c                       |  243 ++++++----
 69 files changed, 5333 insertions(+), 1973 deletions(-)

New commits:
commit b24e7581bd1e5a0215cb73ec87093ebf03c20278
Author: Chris Wilson <chris@chris-wilson.co.uk>
Date:   Wed Jun 17 17:55:04 2015 +0100

    backlight: Factor known names into preferred interfaces
    
    Since the /sys/device/backlight never turned up we face an issue with
    disambiguating the backlight on multi-GPU devices. Both intel_backlight
    and nv_backlight are presented are raw interfaces, and on modern systems
    the ACPI interface is defunct, so we need a way to distinguish them. So,
    we fallback to our priority table of known interfaces and rank them
    accordingly, first by class (platform, native, raw) and then by priority.
    
    Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>

diff --git a/src/backlight.c b/src/backlight.c
index c65e466..d020a7c 100644
--- a/src/backlight.c
+++ b/src/backlight.c
@@ -152,12 +152,9 @@ int backlight_open(struct backlight *b, char *iface)
 	return param.curval;
 }
 
-enum backlight_type backlight_exists(const char *iface)
+int backlight_exists(const char *iface)
 {
-	if (iface != NULL)
-		return BL_NONE;
-
-	return BL_PLATFORM;
+	return iface == NULL;
 }
 
 int backlight_on(struct backlight *b)
@@ -250,10 +247,10 @@ static const char *known_interfaces[] = {
 	"intel_backlight",
 };
 
-static enum backlight_type __backlight_type(const char *iface)
+static int __backlight_type(const char *iface)
 {
 	char buf[1024];
-	int fd, v;
+	int fd, v, i;
 
 	v = -1;
 	fd = __backlight_open(iface, "type", O_RDONLY);
@@ -267,39 +264,41 @@ static enum backlight_type __backlight_type(const char *iface)
 		buf[v] = '\0';
 
 		if (strcmp(buf, "raw") == 0)
-			v = BL_RAW;
+			v = BL_RAW << 8;
 		else if (strcmp(buf, "platform") == 0)
-			v = BL_PLATFORM;
+			v = BL_PLATFORM << 8;
 		else if (strcmp(buf, "firmware") == 0)
-			v = BL_FIRMWARE;
+			v = BL_FIRMWARE << 8;
 		else
-			v = BL_NAMED;
+			v = BL_NAMED << 8;
 	} else
-		v = BL_NAMED;
+		v = BL_NAMED << 8;
 
-	if (v == BL_NAMED) {
-		int i;
-		for (i = 0; i < ARRAY_SIZE(known_interfaces); i++) {
-			if (strcmp(iface, known_interfaces[i]) == 0)
-				break;
-		}
-		v += i;
+	for (i = 0; i < ARRAY_SIZE(known_interfaces); i++) {
+		if (strcmp(iface, known_interfaces[i]) == 0)
+			break;
 	}
+	v += i;
 
 	return v;
 }
 
-enum backlight_type backlight_exists(const char *iface)
+static int __backlight_exists(const char *iface)
 {
 	if (__backlight_read(iface, "brightness") < 0)
-		return BL_NONE;
+		return -1;
 
 	if (__backlight_read(iface, "max_brightness") <= 0)
-		return BL_NONE;
+		return -1;
 
 	return __backlight_type(iface);
 }
 
+int backlight_exists(const char *iface)
+{
+	return __backlight_exists(iface) != -1;
+}
+
 static int __backlight_init(struct backlight *b, char *iface, int fd)
 {
 	b->fd = fd_move_cloexec(fd_set_nonblock(fd));
@@ -405,7 +404,10 @@ __backlight_find(void)
 			continue;
 
 		/* Fallback to priority list of known iface for old kernels */
-		v = backlight_exists(de->d_name);
+		v = __backlight_exists(de->d_name);
+		if (v < 0)
+			continue;
+
 		if (v < best_type) {
 			char *copy = strdup(de->d_name);
 			if (copy) {
@@ -422,14 +424,17 @@ __backlight_find(void)
 
 int backlight_open(struct backlight *b, char *iface)
 {
-	int level;
+	int level, type;
 
 	if (iface == NULL)
 		iface = __backlight_find();
 	if (iface == NULL)
 		goto err;
 
-	b->type = __backlight_type(iface);
+	type = __backlight_type(iface);
+	if (type < 0)
+		goto err;
+	b->type = type >> 8;
 
 	b->max = __backlight_read(iface, "max_brightness");
 	if (b->max <= 0)
@@ -549,7 +554,10 @@ char *backlight_find_for_device(struct pci_device *pci)
 		if (*de->d_name == '.')
 			continue;
 
-		v = backlight_exists(de->d_name);
+		v = __backlight_exists(de->d_name);
+		if (v < 0)
+			continue;
+
 		if (v < best_type) {
 			char *copy = strdup(de->d_name);
 			if (copy) {
diff --git a/src/backlight.h b/src/backlight.h
index bb0e28b..ba17755 100644
--- a/src/backlight.h
+++ b/src/backlight.h
@@ -43,7 +43,7 @@ struct backlight {
 	int pid, fd;
 };
 
-enum backlight_type backlight_exists(const char *iface);
+int backlight_exists(const char *iface);
 
 void backlight_init(struct backlight *backlight);
 int backlight_open(struct backlight *backlight, char *iface);
diff --git a/src/sna/sna_display.c b/src/sna/sna_display.c
index efc5fc9..53eb9ca 100644
--- a/src/sna/sna_display.c
+++ b/src/sna/sna_display.c
@@ -767,7 +767,7 @@ has_user_backlight_override(xf86OutputPtr output)
 	if (*str == '\0')
 		return (char *)str;
 
-	if (backlight_exists(str) == BL_NONE) {
+	if (!backlight_exists(str)) {
 		xf86DrvMsg(output->scrn->scrnIndex, X_ERROR,
 			   "Unrecognised backlight control interface '%s'\n",
 			   str);
diff --git a/src/uxa/intel_display.c b/src/uxa/intel_display.c
index 0cdc8d2..8bf0184 100644
--- a/src/uxa/intel_display.c
+++ b/src/uxa/intel_display.c
@@ -192,7 +192,7 @@ intel_output_backlight_init(xf86OutputPtr output)
 
 	str = xf86GetOptValString(intel->Options, OPTION_BACKLIGHT);
 	if (str != NULL) {
-		if (backlight_exists(str) != BL_NONE) {
+		if (backlight_exists(str)) {
 			intel_output->backlight_active_level =
 				backlight_open(&intel_output->backlight,
 					       strdup(str));

commit f1f2e7202854c725293c63293de1552337c717b2
Author: Chris Wilson <chris@chris-wilson.co.uk>
Date:   Tue Jun 16 16:45:59 2015 +0100

    sna/dri2: Handle intermixing of exchanges and blits
    
    Since there were two paths performing similar tasks for swapping a
    windowed buffer, they would get easily confused and queue themselves in
    conflict with each other as they behaved slightly differently wrt to rapid
    swaps. Almagamate the two paths such that the behaviour is the same -
    with the complication being in tracking the spare active buffer.
    
    Fixes (some at least!) flickering from
    commit 72d208a7f2f0e8f2d93483e535154f34a8a26d81
    Author: Chris Wilson <chris@chris-wilson.co.uk>
    Date:   Thu Mar 5 12:26:15 2015 +0000
    
        sna/dri2: Perform swap elision on windows for swap-interval==0
    
    Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>

diff --git a/src/sna/sna_dri2.c b/src/sna/sna_dri2.c
index 6a0c80c..52a64f0 100644
--- a/src/sna/sna_dri2.c
+++ b/src/sna/sna_dri2.c
@@ -69,7 +69,12 @@ static inline struct kgem_bo *ref(struct kgem_bo *bo)
 
 struct sna_dri2_private {
 	PixmapPtr pixmap;
-	struct kgem_bo *bo, *copy;
+	struct kgem_bo *bo;
+	struct  copy {
+		struct kgem_bo *bo;
+		uint32_t name;
+		uint32_t flags;
+	} copy;
 	DRI2Buffer2Ptr proxy;
 	bool stale;
 	uint32_t size;
@@ -197,6 +202,44 @@ static struct dri2_window *dri2_window(WindowPtr win)
 	return ((void **)__get_private(win, sna_window_key))[1];
 }
 
+static void
+sna_dri2_cache_bo(struct sna *sna,
+		  DrawablePtr draw,
+		  DRI2BufferPtr buffer,
+		  struct kgem_bo *bo,
+		  uint32_t name,
+		  uint32_t flags)
+{
+	struct dri_bo *c;
+
+	if (draw == NULL)
+		goto err;
+
+	if (bo->refcnt > 1)
+		goto err;
+
+	if ((draw->height << 16 | draw->width) != get_private(buffer)->size)
+		goto err;
+
+	if (bo->scanout && front_pitch(draw) != bo->pitch)
+		goto err;
+
+	c = malloc(sizeof(*c));
+	if (!c)
+		goto err;
+
+	DBG(("%s: cacheing handle=%d (name=%d, flags=%d, active_scanout=%d)\n", __FUNCTION__, bo->handle, name, flags, bo->active_scanout));
+
+	c->bo = bo;
+	c->name = name;
+	c->flags = flags;
+	list_add(&c->link, &dri2_window((WindowPtr)draw)->cache);
+	return;
+
+err:
+	assert(bo->active_scanout == 0);
+	kgem_bo_destroy(&sna->kgem, bo);
+}
 
 static void
 sna_dri2_get_back(struct sna *sna,
@@ -282,7 +325,7 @@ sna_dri2_get_back(struct sna *sna,
 	}
 	assert(bo->active_scanout == 0);
 
-	if (reuse) {
+	if (reuse && get_private(back)->bo->refcnt == 1) {
 		bool found = false;
 
 		list_for_each_entry_reverse(c, &priv->cache, link) {
@@ -393,6 +436,7 @@ sna_dri2_reuse_buffer(DrawablePtr draw, DRI2BufferPtr buffer)
 	    draw->type != DRAWABLE_PIXMAP) {
 		DBG(("%s: replacing back buffer on window %ld\n", __FUNCTION__, draw->id));
 		sna_dri2_get_back(to_sna_from_drawable(draw), draw, buffer);
+
 		assert(get_private(buffer)->bo->refcnt);
 		assert(get_private(buffer)->bo->active_scanout == 0);
 		assert(kgem_bo_flink(&to_sna_from_drawable(draw)->kgem, get_private(buffer)->bo) == buffer->name);
@@ -743,7 +787,9 @@ err:
 	return NULL;
 }
 
-static void _sna_dri2_destroy_buffer(struct sna *sna, DRI2Buffer2Ptr buffer)
+static void _sna_dri2_destroy_buffer(struct sna *sna,
+				     DrawablePtr draw,
+				     DRI2Buffer2Ptr buffer)
 {
 	struct sna_dri2_private *private = get_private(buffer);
 
@@ -761,13 +807,16 @@ static void _sna_dri2_destroy_buffer(struct sna *sna, DRI2Buffer2Ptr buffer)
 
 	if (private->proxy) {
 		DBG(("%s: destroying proxy\n", __FUNCTION__));
-		_sna_dri2_destroy_buffer(sna, private->proxy);
+		_sna_dri2_destroy_buffer(sna, draw, private->proxy);
 		private->pixmap = NULL;
 	}
 
-	if (private->copy) {
-		private->copy->active_scanout--;
-		kgem_bo_destroy(&sna->kgem, private->copy);
+	if (private->copy.bo) {
+		private->copy.bo->active_scanout--;
+		sna_dri2_cache_bo(sna, draw, buffer,
+				  private->copy.bo,
+				  private->copy.name,
+				  private->copy.flags);
 	}
 
 	if (private->pixmap) {
@@ -807,7 +856,7 @@ static void _sna_dri2_destroy_buffer(struct sna *sna, DRI2Buffer2Ptr buffer)
 
 static void sna_dri2_destroy_buffer(DrawablePtr draw, DRI2Buffer2Ptr buffer)
 {
-	_sna_dri2_destroy_buffer(to_sna_from_drawable(draw), buffer);
+	_sna_dri2_destroy_buffer(to_sna_from_drawable(draw), draw, buffer);
 }
 
 static DRI2BufferPtr sna_dri2_reference_buffer(DRI2BufferPtr buffer)
@@ -1451,8 +1500,8 @@ sna_dri2_event_free(struct sna_dri2_event *info)
 	if (draw && draw->type == DRAWABLE_WINDOW)
 		sna_dri2_remove_event((WindowPtr)draw, info);
 
-	_sna_dri2_destroy_buffer(info->sna, info->front);
-	_sna_dri2_destroy_buffer(info->sna, info->back);
+	_sna_dri2_destroy_buffer(info->sna, draw, info->front);
+	_sna_dri2_destroy_buffer(info->sna, draw, info->back);
 
 	if (info->bo) {
 		DBG(("%s: releasing batch handle=%d\n", __FUNCTION__, info->bo->handle));
@@ -1581,7 +1630,7 @@ void sna_dri2_decouple_window(WindowPtr win)
 		struct sna *sna = to_sna_from_drawable(&win->drawable);
 		assert(priv->crtc);
 		sna_shadow_unset_crtc(sna, priv->crtc);
-		_sna_dri2_destroy_buffer(sna, priv->front);
+		_sna_dri2_destroy_buffer(sna, NULL, priv->front);
 		priv->front = NULL;
 	}
 }
@@ -1600,7 +1649,7 @@ void sna_dri2_destroy_window(WindowPtr win)
 		struct sna *sna = to_sna_from_drawable(&win->drawable);
 		assert(priv->crtc);
 		sna_shadow_unset_crtc(sna, priv->crtc);
-		_sna_dri2_destroy_buffer(sna, priv->front);
+		_sna_dri2_destroy_buffer(sna, NULL, priv->front);
 	}
 
 	if (priv->chain) {
@@ -1900,6 +1949,8 @@ can_xchg(struct sna *sna,
 		return false;
 	}
 
+	DBG(("%s: back size=%x, front size=%x\n",
+	     __FUNCTION__, get_private(back)->size, get_private(front)->size));
 	if (get_private(back)->size != get_private(front)->size) {
 		DBG(("%s: no, back buffer %dx%d does not match front buffer %dx%d\n",
 		     __FUNCTION__,
@@ -2052,7 +2103,6 @@ sna_dri2_xchg(DrawablePtr draw, DRI2BufferPtr front, DRI2BufferPtr back)
 
 	back_bo = get_private(back)->bo;
 	front_bo = get_private(front)->bo;
-	assert(front_bo != back_bo);
 
 	DBG(("%s: win=%ld, exchange front=%d/%d and back=%d/%d, pixmap=%ld %dx%d\n",
 	     __FUNCTION__, win->drawable.id,
@@ -2066,6 +2116,8 @@ sna_dri2_xchg(DrawablePtr draw, DRI2BufferPtr front, DRI2BufferPtr back)
 	     __FUNCTION__, back_bo->handle, back_bo->pitch, kgem_bo_size(back_bo), back_bo->refcnt, back_bo->active_scanout));
 	DBG(("%s: front_bo handle=%d, pitch=%d, size=%d, ref=%d, active_scanout?=%d\n",
 	     __FUNCTION__, front_bo->handle, front_bo->pitch, kgem_bo_size(front_bo), front_bo->refcnt, front_bo->active_scanout));
+
+	assert(front_bo != back_bo);
 	assert(front_bo->refcnt);
 	assert(back_bo->refcnt);
 
@@ -2219,7 +2271,7 @@ static void fake_swap_complete(struct sna *sna, ClientPtr client,
 static void chain_swap(struct sna_dri2_event *chain)
 {
 	union drm_wait_vblank vbl;
-	struct kgem_bo *tmp;
+	struct copy tmp;
 
 	if (chain->draw == NULL) {
 		sna_dri2_event_free(chain);
@@ -2261,9 +2313,22 @@ static void chain_swap(struct sna_dri2_event *chain)
 		 * exchange back again so that we are consistent with the
 		 * client once more.
 		 */
-		if (get_private(chain->back)->copy) {
-			tmp = get_private(chain->back)->bo;
-			get_private(chain->back)->bo = get_private(chain->back)->copy;
+		if (get_private(chain->back)->copy.bo) {
+			tmp.bo = get_private(chain->back)->copy.bo;
+			assert(tmp.bo->active_scanout);
+			DBG(("%s: removing active marker [%d] from handle=%d\n",
+			     __FUNCTION__,
+			     tmp.bo->active_scanout, tmp.bo->handle));
+			tmp.bo->active_scanout--;
+
+			tmp.bo = get_private(chain->back)->bo;
+			tmp.name = chain->back->name;
+			tmp.flags = chain->back->flags;
+
+			get_private(chain->back)->bo = get_private(chain->back)->copy.bo;
+			chain->back->name = get_private(chain->back)->copy.name;
+			chain->back->flags = get_private(chain->back)->copy.flags;
+			chain->back->pitch = get_private(chain->back)->copy.bo->pitch;
 		}
 
 		if (can_xchg(chain->sna, chain->draw, chain->front, chain->back)) {
@@ -2275,20 +2340,24 @@ static void chain_swap(struct sna_dri2_event *chain)
 			__sna_dri2_copy_event(chain, DRI2_BO);
 		}
 
-		if (get_private(chain->back)->copy) {
-			DBG(("%s: removing active marker [%d] from handle=%d\n",
-			     __FUNCTION__,
-			     get_private(chain->back)->copy->active_scanout,
-			     get_private(chain->back)->copy->handle));
-			assert(get_private(chain->back)->copy->active_scanout);
-			get_private(chain->back)->copy->active_scanout--;
+		if (get_private(chain->back)->copy.bo) {
+			if (get_private(chain->back)->copy.bo == get_private(chain->back)->bo) {
+				get_private(chain->back)->bo = tmp.bo;
+				chain->back->name = tmp.name;
+				chain->back->flags = tmp.flags;
+				chain->back->pitch = tmp.bo->pitch;
+
+				tmp.bo = get_private(chain->back)->copy.bo;
+			}
 
-			kgem_bo_destroy(&chain->sna->kgem,
-					get_private(chain->back)->copy);
-			get_private(chain->back)->copy = NULL;
+			kgem_bo_destroy(&chain->sna->kgem, tmp.bo);
 
-			get_private(chain->back)->bo = tmp;
+			get_private(chain->back)->copy.bo = ref(get_private(chain->back)->bo);
+			get_private(chain->back)->copy.name = chain->back->name;
+			get_private(chain->back)->copy.flags = chain->back->flags;
+			get_private(chain->back)->bo->active_scanout++;
 		}
+		assert(get_private(chain->back)->bo != get_private(chain->front)->bo);
 	case SWAP:
 		break;
 	default:
@@ -2498,9 +2567,14 @@ sna_dri2_immediate_blit(struct sna *sna,
 
 		DBG(("%s: no pending blit, starting chain\n", __FUNCTION__));
 
-		info->queued = true;
-		__sna_dri2_copy_event(info, sync | DRI2_BO);
+		if (can_xchg(chain->sna, chain->draw, chain->front, chain->back)) {
+			sna_dri2_xchg(chain->draw, chain->front, chain->back);
+		} else if (can_xchg_crtc(chain->sna, chain->draw, chain->front, chain->back, chain->crtc)) {
+			sna_dri2_xchg_crtc(chain->sna, chain->draw, chain->crtc, chain->front, chain->back);
+		} else
+			__sna_dri2_copy_event(info, sync | DRI2_BO);
 
+		info->queued = true;
 		VG_CLEAR(vbl);
 		vbl.request.type =
 			DRM_VBLANK_RELATIVE |
@@ -2516,21 +2590,30 @@ sna_dri2_immediate_blit(struct sna *sna,
 		return;
 	}
 
-	DBG(("%s: adding active marker [%d] to handle=%d, removing [%d] from handle=%d\n",
-	     __FUNCTION__,
-	     get_private(info->back)->bo->active_scanout,
-	     get_private(info->back)->bo->handle,
-	     get_private(info->back)->copy ? get_private(info->back)->copy->active_scanout : 0,
-	     get_private(info->back)->copy ? get_private(info->back)->copy->handle : 0));
-	assert(get_private(info->back)->bo->active_scanout == 0);
-	if (get_private(info->back)->copy) {
-		get_private(info->back)->copy->active_scanout--;
-		kgem_bo_destroy(&sna->kgem, get_private(info->back)->copy);
-	}
-	get_private(info->back)->copy = ref(get_private(info->back)->bo);
-	get_private(info->back)->bo->active_scanout++;
-
-	if (chain->chain != info && chain->chain->type == SWAP_THROTTLE) {
+	if (get_private(info->back)->copy.bo != get_private(info->back)->bo) {
+		DBG(("%s: adding active marker [%d] to handle=%d, removing [%d] from handle=%d\n",
+		     __FUNCTION__,
+		     get_private(info->back)->bo->active_scanout,
+		     get_private(info->back)->bo->handle,
+		     get_private(info->back)->copy.bo ? get_private(info->back)->copy.bo->active_scanout : 0,
+		     get_private(info->back)->copy.bo ? get_private(info->back)->copy.bo->handle : 0));
+		assert(get_private(info->back)->bo->active_scanout == 0);
+		if (get_private(info->back)->copy.bo) {
+			get_private(info->back)->copy.bo->active_scanout--;
+			sna_dri2_cache_bo(sna, info->draw, info->back,
+					  get_private(info->back)->copy.bo,
+					  get_private(info->back)->copy.name,
+					  get_private(info->back)->copy.flags);
+		}
+		get_private(info->back)->copy.bo = ref(get_private(info->back)->bo);
+		get_private(info->back)->copy.name = info->back->name;
+		get_private(info->back)->copy.flags = info->back->flags;
+		get_private(info->back)->bo->active_scanout++;
+	}
+
+	if (chain->type == SWAP_THROTTLE &&
+	    chain->chain != info &&
+	    chain->chain->type == SWAP_THROTTLE) {
 		struct sna_dri2_event *tmp = chain->chain;
 
 		assert(!tmp->queued);
@@ -2543,7 +2626,7 @@ sna_dri2_immediate_blit(struct sna *sna,
 		tmp->chain = NULL;
 
 		DBG(("%s: swap elision, unblocking client\n", __FUNCTION__));
-		frame_swap_complete(tmp, DRI2_BLIT_COMPLETE);
+		frame_swap_complete(tmp, DRI2_EXCHANGE_COMPLETE);
 
 		tmp->draw = NULL;
 		sna_dri2_event_free(tmp);
@@ -2841,7 +2924,7 @@ sna_dri2_schedule_flip(ClientPtr client, DrawablePtr draw, xf86CrtcPtr crtc,
 			assert(info->front == front);
 			assert(info->queued);
 			if (info->back != back) {
-				_sna_dri2_destroy_buffer(sna, info->back);
+				_sna_dri2_destroy_buffer(sna, draw, info->back);
 				info->back = sna_dri2_reference_buffer(back);
 			}
 			DBG(("%s: executing xchg of pending flip: flip_continue=%d, keepalive=%d\n", __FUNCTION__, info->flip_continue, info->keepalive));
@@ -2955,130 +3038,6 @@ queue:
 	return true;
 }
 
-static bool
-sna_dri2_schedule_xchg(ClientPtr client, DrawablePtr draw, xf86CrtcPtr crtc,
-		       DRI2BufferPtr front, DRI2BufferPtr back,
-		       bool immediate, CARD64 *target_msc, CARD64 current_msc,
-		       DRI2SwapEventPtr func, void *data)
-{
-	struct sna *sna = to_sna_from_drawable(draw);
-	bool sync, event;
-
-	if (!immediate)
-		return false;
-
-	sync = current_msc < *target_msc && xorg_can_triple_buffer();
-	event = dri2_chain(draw) == NULL;
-	DBG(("%s: synchronous?=%d, send-event?=%d\n", __FUNCTION__, sync, event));
-	if (!sync || event) {
-		DBG(("%s: performing immediate xchg on pipe %d\n",
-		     __FUNCTION__, sna_crtc_pipe(crtc)));
-		sna_dri2_xchg(draw, front, back);
-	}
-	if (sync) {
-		struct sna_dri2_event *info;
-
-		info = sna_dri2_add_event(sna, draw, client, crtc);
-		if (!info)
-			goto complete;
-
-		info->event_complete = func;
-		info->event_data = data;
-
-		info->front = sna_dri2_reference_buffer(front);
-		info->back = sna_dri2_reference_buffer(back);
-		info->type = SWAP_THROTTLE;
-
-		if (event) {
-			union drm_wait_vblank vbl;
-
-			VG_CLEAR(vbl);
-			vbl.request.type =
-				DRM_VBLANK_RELATIVE |
-				DRM_VBLANK_EVENT;
-			vbl.request.sequence = 1;
-			vbl.request.signal = (uintptr_t)info;
-
-			info->queued = true;
-			if (sna_wait_vblank(sna, &vbl, info->pipe)) {
-				DBG(("%s: vblank queue failed, unblocking client\n", __FUNCTION__));
-				sna_dri2_event_free(info);
-				goto complete;
-			}
-
-			swap_limit(draw, 2);
-		}
-	} else {
-complete:
-		fake_swap_complete(sna, client, draw, crtc, DRI2_EXCHANGE_COMPLETE, func, data);
-	}
-
-	*target_msc = current_msc + 1;
-	return true;
-}
-
-static bool
-sna_dri2_schedule_xchg_crtc(ClientPtr client, DrawablePtr draw, xf86CrtcPtr crtc,
-			    DRI2BufferPtr front, DRI2BufferPtr back,
-			    bool immediate, CARD64 *target_msc, CARD64 current_msc,
-			    DRI2SwapEventPtr func, void *data)
-{
-	struct sna *sna = to_sna_from_drawable(draw);
-	bool sync, event;
-
-	if (!immediate)
-		return false;
-
-	sync = current_msc < *target_msc && xorg_can_triple_buffer();
-	event = dri2_chain(draw) == NULL;
-	DBG(("%s: synchronous?=%d, send-event?=%d\n", __FUNCTION__, sync, event));
-	if (!sync || event) {
-		DBG(("%s: performing immediate xchg only on pipe %d\n",
-		     __FUNCTION__, sna_crtc_pipe(crtc)));
-		sna_dri2_xchg_crtc(sna, draw, crtc, front, back);
-	}
-	if (sync) {
-		struct sna_dri2_event *info;
-
-		info = sna_dri2_add_event(sna, draw, client, crtc);
-		if (!info)
-			goto complete;
-
-		info->event_complete = func;
-		info->event_data = data;
-
-		info->front = sna_dri2_reference_buffer(front);
-		info->back = sna_dri2_reference_buffer(back);
-		info->type = SWAP_THROTTLE;
-
-		if (event) {
-			union drm_wait_vblank vbl;
-
-			VG_CLEAR(vbl);
-			vbl.request.type =
-				DRM_VBLANK_RELATIVE |
-				DRM_VBLANK_EVENT;
-			vbl.request.sequence = 1;
-			vbl.request.signal = (uintptr_t)info;
-
-			info->queued = true;
-			if (sna_wait_vblank(sna, &vbl, info->pipe)) {
-				DBG(("%s: vblank queue failed, unblocking client\n", __FUNCTION__));
-				sna_dri2_event_free(info);
-				goto complete;
-			}
-
-			swap_limit(draw, 2);
-		}
-	} else {
-complete:
-		fake_swap_complete(sna, client, draw, crtc, DRI2_EXCHANGE_COMPLETE, func, data);
-	}
-
-	*target_msc = current_msc + 1;
-	return true;
-}
-
 static bool has_pending_events(struct sna *sna)
 {
 	struct pollfd pfd;
@@ -3144,6 +3103,7 @@ sna_dri2_schedule_swap(ClientPtr client, DrawablePtr draw, DRI2BufferPtr front,
 	assert(get_private(front)->refcnt);
 	assert(get_private(back)->refcnt);
 
+	assert(get_private(back)->bo != get_private(front)->bo);
 	assert(get_private(front)->bo->refcnt);
 	assert(get_private(back)->bo->refcnt);
 
@@ -3202,18 +3162,6 @@ sna_dri2_schedule_swap(ClientPtr client, DrawablePtr draw, DRI2BufferPtr front,
 				   target_msc, divisor, remainder,
 				   &current_msc);
 
-	if (can_xchg(sna, draw, front, back) &&
-	    sna_dri2_schedule_xchg(client, draw, crtc, front, back,
-				   immediate, target_msc, current_msc,
-				   func, data))
-		return TRUE;
-
-	if (can_xchg_crtc(sna, draw, front, back, crtc) &&
-	    sna_dri2_schedule_xchg_crtc(client, draw, crtc, front, back,
-					immediate, target_msc, current_msc,
-					func, data))
-		return TRUE;
-
 	if (can_flip(sna, draw, front, back, crtc) &&
 	    sna_dri2_schedule_flip(client, draw, crtc, front, back,
 				  immediate, target_msc, current_msc,

commit 7d9a74622e5a936e4860fcef8358619bf59adae8
Author: Chris Wilson <chris@chris-wilson.co.uk>
Date:   Mon Jun 15 14:16:34 2015 +0100

    sna: Be robust in handling DPMS failures
    
    If we fail to turn off an output via DPMS, disable the entire CRTC in
    order to blank the output and save the screeen/power.
    
    Reported-by: Lukas Hejtmanek  <xhejtman@fi.muni.cz>
    References: https://bugs.freedesktop.org/show_bug.cgi?id=90179
    Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>

diff --git a/src/sna/sna_display.c b/src/sna/sna_display.c
index f58eb8d..efc5fc9 100644
--- a/src/sna/sna_display.c
+++ b/src/sna/sna_display.c
@@ -213,7 +213,7 @@ struct sna_output {
 	int panel_vdisplay;
 
 	uint32_t dpms_id;
-	int dpms_mode;
+	uint8_t dpms_mode;
 	struct backlight backlight;
 	int backlight_active_level;
 
@@ -251,6 +251,7 @@ enum { /* XXX copied from hw/xfree86/modes/xf86Crtc.c */
 	OPTION_DEFAULT_MODES,
 };
 
+static void __sna_output_dpms(xf86OutputPtr output, int dpms, int fixup);
 static void sna_crtc_disable_cursor(struct sna *sna, struct sna_crtc *crtc);
 
 static bool is_zaphod(ScrnInfoPtr scrn)
@@ -936,7 +937,7 @@ sna_crtc_force_outputs_on(xf86CrtcPtr crtc)
 		if (output->crtc != crtc)
 			continue;
 
-		output->funcs->dpms(output, DPMSModeOn);
+		__sna_output_dpms(output, DPMSModeOn, false);
 	}
 
 #if XF86_CRTC_VERSION >= 3
@@ -966,7 +967,7 @@ sna_crtc_force_outputs_off(xf86CrtcPtr crtc)
 		if (output->crtc != crtc)
 			continue;
 
-		output->funcs->dpms(output, DPMSModeOff);
+		__sna_output_dpms(output, DPMSModeOff, false);
 	}
 }
 
@@ -1099,7 +1100,7 @@ sna_crtc_apply(xf86CrtcPtr crtc)
 		 * and we lose track of the user settings.
 		 */
 		if (output->crtc == NULL)
-			output->funcs->dpms(output, DPMSModeOff);
+			__sna_output_dpms(output, DPMSModeOff, false);
 
 		if (output->crtc != crtc)
 			continue;
@@ -3580,7 +3581,7 @@ sna_output_destroy(xf86OutputPtr output)
 }
 
 static void
-sna_output_dpms(xf86OutputPtr output, int dpms)
+__sna_output_dpms(xf86OutputPtr output, int dpms, int fixup)
 {
 	struct sna *sna = to_sna(output->scrn);
 	struct sna_output *sna_output = output->driver_private;
@@ -3607,8 +3608,9 @@ sna_output_dpms(xf86OutputPtr output, int dpms)
 	if (sna_output->backlight.iface && dpms != DPMSModeOn) {
 		if (old_dpms == DPMSModeOn) {
 			sna_output->backlight_active_level = sna_output_backlight_get(output);
-			DBG(("%s: saving current backlight %d\n",
-			     __FUNCTION__, sna_output->backlight_active_level));
+			DBG(("%s(%s:%d): saving current backlight %d\n",
+			     __FUNCTION__, output->name, sna_output->id,
+			     sna_output->backlight_active_level));
 		}
 		sna_output->dpms_mode = dpms;
 		sna_output_backlight_off(sna_output);
@@ -3618,18 +3620,31 @@ sna_output_dpms(xf86OutputPtr output, int dpms)
 	    drmModeConnectorSetProperty(sna->kgem.fd,
 					sna_output->id,
 					sna_output->dpms_id,
-					dpms))
-		dpms = old_dpms;
+					dpms)) {
+		DBG(("%s(%s:%d): failed to set DPMS to %d (fixup? %d)\n",
+		     __FUNCTION__, output->name, sna_output->id, dpms, fixup));
+		if (fixup) {
+			sna_crtc_disable(output->crtc, false);
+			return;
+		}
+	}
 
 	if (sna_output->backlight.iface && dpms == DPMSModeOn) {
-		DBG(("%s: restoring previous backlight %d\n",
-		     __FUNCTION__, sna_output->backlight_active_level));
+		DBG(("%s(%d:%d: restoring previous backlight %d\n",
+		     __FUNCTION__, output->name, sna_output->id,
+		     sna_output->backlight_active_level));
 		sna_output_backlight_on(sna_output);
 	}
 
 	sna_output->dpms_mode = dpms;
 }
 
+static void
+sna_output_dpms(xf86OutputPtr output, int dpms)
+{
+	__sna_output_dpms(output, dpms, true);
+}
+
 static bool
 sna_property_ignore(drmModePropertyPtr prop)
 {
@@ -4438,10 +4453,8 @@ reset:
 		sna_output->dpms_mode = sna_output->prop_values[i];
 		DBG(("%s: found 'DPMS' (idx=%d, id=%d), initial value=%d\n",
 		     __FUNCTION__, i, sna_output->dpms_id, sna_output->dpms_mode));
-	} else {
-		sna_output->dpms_id = -1;
+	} else
 		sna_output->dpms_mode = DPMSModeOff;
-	}
 
 	sna_output->possible_encoders = possible_encoders;
 	sna_output->attached_encoders = attached_encoders;

commit 670d05f438520bcef8e86a0e32016ae542c61cee
Author: Chris Wilson <chris@chris-wilson.co.uk>
Date:   Sat Jun 13 18:43:13 2015 +0100

    sna/dri2: Destroy the right bo
    
    Fixes copy'n'paste error in
    
    commit d46c793663d2b1b5ffb923500111b7affa8402b6
    Author: Chris Wilson <chris@chris-wilson.co.uk>
    Date:   Fri Jun 12 13:50:35 2015 +0100
    
        sna/dri2: Remove the active_scanout flag when deleting the event
    
    Reported-by: Andreas Reis <andreas.reis@gmail.com>
    Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=90968#c8
    Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>

diff --git a/src/sna/sna_dri2.c b/src/sna/sna_dri2.c
index 1041c52..6a0c80c 100644
--- a/src/sna/sna_dri2.c
+++ b/src/sna/sna_dri2.c
@@ -2525,8 +2525,7 @@ sna_dri2_immediate_blit(struct sna *sna,
 	assert(get_private(info->back)->bo->active_scanout == 0);
 	if (get_private(info->back)->copy) {
 		get_private(info->back)->copy->active_scanout--;
-		kgem_bo_destroy(&chain->sna->kgem,
-				get_private(chain->back)->copy);
+		kgem_bo_destroy(&sna->kgem, get_private(info->back)->copy);
 	}
 	get_private(info->back)->copy = ref(get_private(info->back)->bo);
 	get_private(info->back)->bo->active_scanout++;

commit ed7bcae0ab0af41bc51dbcb729e4af34e2ba5094
Author: Chris Wilson <chris@chris-wilson.co.uk>
Date:   Sat Jun 13 12:53:19 2015 +0100

    sna/dri2: SWAP_THROTTLE is also used for a delayed SWAP
    
    If there is already a pending operation on the drawable, the swap is
    queued. It is queued with SWAP_THROTTLE which classes with the
    vblank_mode=0 chaining, so the choice is to either review all other uses
    of SWAP_THROTTLE and duplicate the chain swap handling, or to choose when
    use to the alternate copy or back buffer. This patch opts for the
    latter.
    
    Fixes regression from
    commit dcb4d323ca19f86fbe0230378ac9035161a70f9e
    Author: Chris Wilson <chris@chris-wilson.co.uk>
    Date:   Thu Jun 11 13:54:49 2015 +0100
    
        sna/dri2: Mark the pending backbuffer copy as active
    
    Reported-by: Christoph Haag <haagch@frickel.club>
    Reported-by: Andreas Reis <andreas.reis@gmail.com>
    Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=90968
    Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>

diff --git a/src/sna/sna_dri2.c b/src/sna/sna_dri2.c
index 6cb346f..1041c52 100644
--- a/src/sna/sna_dri2.c
+++ b/src/sna/sna_dri2.c
@@ -2261,16 +2261,10 @@ static void chain_swap(struct sna_dri2_event *chain)
 		 * exchange back again so that we are consistent with the
 		 * client once more.
 		 */
-		assert(get_private(chain->back)->copy);
-		DBG(("%s: removing active marker [%d] from handle=%d\n",
-		     __FUNCTION__,
-		     get_private(chain->back)->copy->active_scanout,
-		     get_private(chain->back)->copy->handle));
-		assert(get_private(chain->back)->copy->active_scanout);
-		get_private(chain->back)->copy->active_scanout--;
-
-		tmp = get_private(chain->back)->bo;
-		 get_private(chain->back)->bo = get_private(chain->back)->copy;
+		if (get_private(chain->back)->copy) {
+			tmp = get_private(chain->back)->bo;
+			get_private(chain->back)->bo = get_private(chain->back)->copy;
+		}
 
 		if (can_xchg(chain->sna, chain->draw, chain->front, chain->back)) {
 			sna_dri2_xchg(chain->draw, chain->front, chain->back);
@@ -2280,10 +2274,21 @@ static void chain_swap(struct sna_dri2_event *chain)
 			assert(chain->queued);
 			__sna_dri2_copy_event(chain, DRI2_BO);
 		}
-		get_private(chain->back)->bo = tmp;
-		kgem_bo_destroy(&chain->sna->kgem,
-				get_private(chain->back)->copy);
-		get_private(chain->back)->copy = NULL;
+
+		if (get_private(chain->back)->copy) {
+			DBG(("%s: removing active marker [%d] from handle=%d\n",
+			     __FUNCTION__,
+			     get_private(chain->back)->copy->active_scanout,
+			     get_private(chain->back)->copy->handle));
+			assert(get_private(chain->back)->copy->active_scanout);
+			get_private(chain->back)->copy->active_scanout--;
+
+			kgem_bo_destroy(&chain->sna->kgem,


Reply to: