xf86-video-intel: 5 commits - src/intel_device.c src/sna/gen6_render.c src/sna/gen7_render.c src/sna/gen8_render.c src/sna/sna_composite.c src/sna/sna_dri2.c src/sna/sna_glyphs.c src/sna/sna_render.c src/sna/sna_render.h src/sna/sna_render_inline.h

Chris Wilson ickle at kemper.freedesktop.org
Tue Jun 24 02:56:53 PDT 2014


 src/intel_device.c          |  165 +++++++++++++++++++++++++++++++++++++++-----
 src/sna/gen6_render.c       |   48 ++----------
 src/sna/gen7_render.c       |   48 ++----------
 src/sna/gen8_render.c       |   48 ++----------
 src/sna/sna_composite.c     |   37 +++++++--
 src/sna/sna_dri2.c          |   11 ++
 src/sna/sna_glyphs.c        |   12 ++-
 src/sna/sna_render.c        |  152 ++++++++++++++++++++++++++++++++++++----
 src/sna/sna_render.h        |    6 +
 src/sna/sna_render_inline.h |   38 ++++++++++
 10 files changed, 404 insertions(+), 161 deletions(-)

New commits:
commit 92119ef0939897dd1850b417d04a2ba558aee8ca
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date:   Tue Jun 24 10:23:03 2014 +0100

    sna/glyphs: Clip damage to dst
    
    We only check if the hardware will automatically discard writes outside
    of the target pixmap, but we must manually clip the damage before adding
    it to our tracker.
    
    Reported-by: Jiri Slaby <jirislaby at gmail.com>
    Reported-by: Zdenek Kabelac <zkabelac at redhat.com>
    References: https://bugs.freedesktop.org/show_bug.cgi?id=70461#c58
    Signed-off-by: Chris Wilson <chris at chris-wilson.co.uk>

diff --git a/src/sna/sna_glyphs.c b/src/sna/sna_glyphs.c
index 96279e6..28cb58d 100644
--- a/src/sna/sna_glyphs.c
+++ b/src/sna/sna_glyphs.c
@@ -548,7 +548,15 @@ static inline bool clipped_glyphs(PicturePtr dst, int nlist, GlyphListPtr list,
 	if (dst->pCompositeClip->data == NULL &&
 	    region_matches_pixmap(dst->pCompositeClip,
 				  get_drawable_pixmap(dst->pDrawable))) {
-		DBG(("%s: no, region matches drawable\n", __FUNCTION__));
+		DBG(("%s: no, clip region (%d, %d), (%d, %d) matches drawable pixmap=%ld size=%dx%d\n",
+		     __FUNCTION__,
+		     dst->pCompositeClip->extents.x1,
+		     dst->pCompositeClip->extents.y1,
+		     dst->pCompositeClip->extents.x2,
+		     dst->pCompositeClip->extents.y2,
+		     get_drawable_pixmap(dst->pDrawable),
+		     get_drawable_pixmap(dst->pDrawable)->drawable.width,
+		     get_drawable_pixmap(dst->pDrawable)->drawable.height));
 		return false;
 	}
 
@@ -900,7 +908,7 @@ next_glyph_N:
 			     r.width, r.height));
 
 			tmp.blt(sna, &tmp, &r);
-			apply_damage(&tmp, &r);
+			apply_damage_clipped_to_dst(&tmp, &r, dst->pDrawable);
 
 next_glyph_0:
 			x += glyph->info.xOff;
commit b33be7fbac005eb222302ffbb533ded1cd700953
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date:   Tue Jun 24 10:17:47 2014 +0100

    sna: Trim composite region against dst clip extents
    
    Signed-off-by: Chris Wilson <chris at chris-wilson.co.uk>

diff --git a/src/sna/sna_composite.c b/src/sna/sna_composite.c
index 490999f..f20d3c3 100644
--- a/src/sna/sna_composite.c
+++ b/src/sna/sna_composite.c
@@ -178,7 +178,7 @@ sna_compute_composite_region(RegionPtr region,
 
 	if (region->extents.x1 >= region->extents.x2 ||
 	    region->extents.y1 >= region->extents.y2)
-		return FALSE;
+		return false;
 
 	region->extents.x1 += dst->pDrawable->x;
 	region->extents.x2 += dst->pDrawable->x;
@@ -190,7 +190,7 @@ sna_compute_composite_region(RegionPtr region,
 
 	/* clip against dst */
 	if (!clip_to_dst(region, dst->pCompositeClip, 0, 0))
-		return FALSE;
+		return false;
 
 	DBG(("%s: clip against dst->pCompositeClip: (%d, %d), (%d, %d)\n",
 	     __FUNCTION__,
@@ -202,7 +202,7 @@ sna_compute_composite_region(RegionPtr region,
 				 -dst->alphaOrigin.x,
 				 -dst->alphaOrigin.y)) {
 			pixman_region_fini (region);
-			return FALSE;
+			return false;
 		}
 	}
 
@@ -214,7 +214,7 @@ sna_compute_composite_region(RegionPtr region,
 		}
 		if (!clip_to_src(region, src, dst_x - src_x, dst_y - src_y)) {
 			pixman_region_fini (region);
-			return FALSE;
+			return false;
 		}
 		DBG(("%s: clip against src (%dx%d clip=%d): (%d, %d), (%d, %d)\n",
 		       __FUNCTION__,
@@ -229,7 +229,7 @@ sna_compute_composite_region(RegionPtr region,
 					 dst_x - (src_x - src->alphaOrigin.x),
 					 dst_y - (src_y - src->alphaOrigin.y))) {
 				pixman_region_fini(region);
-				return FALSE;
+				return false;
 			}
 		}
 	}
@@ -242,14 +242,14 @@ sna_compute_composite_region(RegionPtr region,
 		}
 		if (!clip_to_src(region, mask, dst_x - mask_x, dst_y - mask_y)) {
 			pixman_region_fini(region);
-			return FALSE;
+			return false;
 		}
 		if (mask->alphaMap) {
 			if (!clip_to_src(region, mask->alphaMap,
 					 dst_x - (mask_x - mask->alphaOrigin.x),
 					 dst_y - (mask_y - mask->alphaOrigin.y))) {
 				pixman_region_fini(region);
-				return FALSE;
+				return false;
 			}
 		}
 
@@ -342,15 +342,32 @@ sna_compute_composite_extents(BoxPtr extents,
 	     extents->x1, extents->y1,
 	     extents->x2, extents->y2));
 
-	if (extents->x1 >= extents->x2 ||
-	    extents->y1 >= extents->y2)
-		return FALSE;
+	if (extents->x1 >= extents->x2 || extents->y1 >= extents->y2)
+		return false;
 
 	extents->x1 += dst->pDrawable->x;
 	extents->x2 += dst->pDrawable->x;
 	extents->y1 += dst->pDrawable->y;
 	extents->y2 += dst->pDrawable->y;
 
+	if (extents->x1 < dst->pCompositeClip->extents.x1)
+		extents->x1 = dst->pCompositeClip->extents.x1;
+	if (extents->x2 > dst->pCompositeClip->extents.x2)
+		extents->x2 = dst->pCompositeClip->extents.x2;
+
+	if (extents->y1 < dst->pCompositeClip->extents.y1)
+		extents->y1 = dst->pCompositeClip->extents.y1;
+	if (extents->y2 > dst->pCompositeClip->extents.y2)
+		extents->y2 = dst->pCompositeClip->extents.y2;
+
+	DBG(("%s: initial clip against dst->pCompositeClip: (%d, %d), (%d, %d)\n",
+	     __FUNCTION__,
+	     extents->x1, extents->y1,
+	     extents->x2, extents->y2));
+
+	if (extents->x1 >= extents->x2 || extents->y1 >= extents->y2)
+		return false;
+
 	dst_x += dst->pDrawable->x;
 	dst_y += dst->pDrawable->y;
 
commit f66e25def3431a900068cc1c23a6b1e8322ef046
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date:   Mon Jun 23 16:14:28 2014 +0100

    intel: Wait for the DRM device to load
    
    Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=80397
    Signed-off-by: Chris Wilson <chris at chris-wilson.co.uk>

diff --git a/src/intel_device.c b/src/intel_device.c
index d9d8df3..fcb179b 100644
--- a/src/intel_device.c
+++ b/src/intel_device.c
@@ -35,6 +35,7 @@
 #include <unistd.h>
 #include <fcntl.h>
 #include <stdlib.h>
+#include <dirent.h>
 #include <errno.h>
 
 #include <pciaccess.h>
@@ -162,32 +163,164 @@ static int __intel_check_device(int fd)
 	return ret;
 }
 
-static int __intel_open_device(const struct pci_device *pci, const char *path)
+#ifdef __linux__
+static int __intel_open_device__major_minor(int _major, int _minor)
 {
-	int fd;
+	char path[256];
+	DIR *dir;
+	struct dirent *de;
+	int base, fd = -1;
 
-	if (path == NULL) {
-		char id[20];
-		int ret;
+	base = sprintf(path, "/dev/dri/");
 
-		if (pci == NULL)
-			return -1;
+	dir = opendir(path);
+	if (dir == NULL)
+		return -1;
+
+	while ((de = readdir(dir)) != NULL) {
+		struct stat st;
+
+		if (*de->d_name == '.')
+			continue;
 
-		snprintf(id, sizeof(id),
-			 "pci:%04x:%02x:%02x.%d",
-			 pci->domain, pci->bus, pci->dev, pci->func);
+		sprintf(path + base, "%s", de->d_name);
+		if (stat(path, &st) == 0 &&
+		    major(st.st_rdev) == _major &&
+		    minor(st.st_rdev) == _minor) {
+#ifdef O_CLOEXEC
+			fd = open(path, O_RDWR | O_NONBLOCK | O_CLOEXEC);
+#endif
+			if (fd == -1)
+				fd = fd_set_cloexec(open(path, O_RDWR | O_NONBLOCK));
+			break;
+		}
+	}
+
+	closedir(dir);
+
+	return fd;
+}
 
-		ret = drmCheckModesettingSupported(id);
-		if (ret) {
+static int __intel_open_device__pci(const struct pci_device *pci)
+{
+	struct stat st;
+	char path[256];
+	DIR *dir;
+	struct dirent *de;
+	int base;
+	int fd;
+
+	/* Look up the major:minor for the drm device through sysfs.
+	 * First we need to check that sysfs is available, then
+	 * check that we have loaded our driver. When we are happy
+	 * that our KMS module is loaded, we can then search for our
+	 * device node. We make the assumption that it uses the same
+	 * name, but after that we read the major:minor assigned to us
+	 * and search for a matching entry in /dev.
+	 */
+
+	base = sprintf(path,
+		       "/sys/bus/pci/devices/%04x:%02x:%02x.%d/",
+		       pci->domain, pci->bus, pci->dev, pci->func);
+	if (stat(path, &st))
+		return -1;
+
+	sprintf(path + base, "drm");
+	dir = opendir(path);
+	if (dir == NULL) {
+		int loop = 0;
+
+		sprintf(path + base, "driver");
+		if (stat(path, &st)) {
 			if (xf86LoadKernelModule("i915"))
-				ret = drmCheckModesettingSupported(id);
-			if (ret)
 				return -1;
-			/* Be nice to the user and load fbcon too */
 			(void)xf86LoadKernelModule("fbcon");
 		}
 
-		fd = fd_set_nonblock(drmOpen(NULL, id));
+		sprintf(path + base, "drm");
+		while ((dir = opendir(path)) == NULL && loop++ < 100)
+			usleep(20000);
+
+		ErrorF("intel: waited %d ms for i915.ko driver to load\n", loop * 20000 / 1000);
+
+		if (dir == NULL)
+			return -1;
+	}
+
+	fd = -1;
+	while ((de = readdir(dir)) != NULL) {
+		if (*de->d_name == '.')
+			continue;
+
+		if (strncmp(de->d_name, "card", 4) == 0) {
+			sprintf(path + base + 4, "/dev/dri/%s", de->d_name);
+#ifdef O_CLOEXEC
+			fd = open(path + base + 4, O_RDWR | O_NONBLOCK | O_CLOEXEC);
+#endif
+			if (fd == -1)
+				fd = fd_set_cloexec(open(path + base + 4, O_RDWR | O_NONBLOCK));
+			if (fd != -1)
+				break;
+
+			sprintf(path + base + 3, "/%s/dev", de->d_name);
+			fd = open(path, O_RDONLY);
+			if (fd == -1)
+				break;
+
+			base = read(fd, path, 256);
+			close(fd);
+
+			fd = -1;
+			if (base > 0) {
+				int major, minor;
+				path[base] = '\0';
+				if (sscanf(path, "%d:%d", &major, &minor) == 2)
+					fd = __intel_open_device__major_minor(major, minor);
+			}
+			break;
+		}
+	}
+	closedir(dir);
+
+	return fd;
+}
+#else
+static int __intel_open_device__pci(const struct pci_device *pci) { return -1; }
+#endif
+
+static int __intel_open_device__legacy(const struct pci_device *pci)
+{
+	char id[20];
+	int ret;
+
+	snprintf(id, sizeof(id),
+		 "pci:%04x:%02x:%02x.%d",
+		 pci->domain, pci->bus, pci->dev, pci->func);
+
+	ret = drmCheckModesettingSupported(id);
+	if (ret) {
+		if (xf86LoadKernelModule("i915"))
+			ret = drmCheckModesettingSupported(id);
+		if (ret)
+			return -1;
+		/* Be nice to the user and load fbcon too */
+		(void)xf86LoadKernelModule("fbcon");
+	}
+
+	return fd_set_nonblock(drmOpen(NULL, id));
+}
+
+static int __intel_open_device(const struct pci_device *pci, const char *path)
+{
+	int fd;
+
+	if (path == NULL) {
+		if (pci == NULL)
+			return -1;
+
+		fd = __intel_open_device__pci(pci);
+		if (fd == -1)
+			fd = __intel_open_device__legacy(pci);
 	} else {
 #ifdef O_CLOEXEC
 		fd = open(path, O_RDWR | O_NONBLOCK | O_CLOEXEC);
commit 1d74b2e07d125ad95b9db6c9c032e90faf2bfa60
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date:   Tue Jun 24 08:58:51 2014 +0100

    sna: Decompose self-copy into overlapping/non-overlapping regions
    
    We only need to stage the copy for the overlapping portion of the
    self-copy, for the rest we can do in a single pass.
    
    Signed-off-by: Chris Wilson <chris at chris-wilson.co.uk>

diff --git a/src/sna/gen6_render.c b/src/sna/gen6_render.c
index 6ef26c8..fe0426e 100644
--- a/src/sna/gen6_render.c
+++ b/src/sna/gen6_render.c
@@ -2655,40 +2655,6 @@ static inline bool prefer_blt_copy(struct sna *sna,
 	return prefer_blt_bo(sna, src_bo) || prefer_blt_bo(sna, dst_bo);
 }
 
-inline static void boxes_extents(const BoxRec *box, int n, BoxRec *extents)
-{
-	*extents = box[0];
-	while (--n) {
-		box++;
-
-		if (box->x1 < extents->x1)
-			extents->x1 = box->x1;
-		if (box->x2 > extents->x2)
-			extents->x2 = box->x2;
-
-		if (box->y1 < extents->y1)
-			extents->y1 = box->y1;
-		if (box->y2 > extents->y2)
-			extents->y2 = box->y2;
-	}
-}
-
-static inline bool
-overlaps(struct sna *sna,
-	 struct kgem_bo *src_bo, int16_t src_dx, int16_t src_dy,
-	 struct kgem_bo *dst_bo, int16_t dst_dx, int16_t dst_dy,
-	 const BoxRec *box, int n, BoxRec *extents)
-{
-	if (src_bo != dst_bo)
-		return false;
-
-	boxes_extents(box, n, extents);
-	return (extents->x2 + src_dx > extents->x1 + dst_dx &&
-		extents->x1 + src_dx < extents->x2 + dst_dx &&
-		extents->y2 + src_dy > extents->y1 + dst_dy &&
-		extents->y1 + src_dy < extents->y2 + dst_dy);
-}
-
 static bool
 gen6_render_copy_boxes(struct sna *sna, uint8_t alu,
 		       PixmapPtr src, struct kgem_bo *src_bo, int16_t src_dx, int16_t src_dy,
@@ -2704,7 +2670,7 @@ gen6_render_copy_boxes(struct sna *sna, uint8_t alu,
 	     overlaps(sna,
 		      src_bo, src_dx, src_dy,
 		      dst_bo, dst_dx, dst_dy,
-		      box, n, &extents)));
+		      box, n, flags, &extents)));
 
 	if (prefer_blt_copy(sna, src_bo, dst_bo, flags) &&
 	    sna_blt_compare_depth(&src->drawable, &dst->drawable) &&
@@ -2729,7 +2695,8 @@ fallback_blt:
 	if (overlaps(sna,
 		     src_bo, src_dx, src_dy,
 		     dst_bo, dst_dx, dst_dy,
-		     box, n, &extents)) {
+		     box, n, flags,
+		     &extents)) {
 		bool big = too_large(extents.x2-extents.x1, extents.y2-extents.y1);
 
 		if ((big || can_switch_to_blt(sna, dst_bo, flags)) &&
@@ -2743,9 +2710,14 @@ fallback_blt:
 		if (big)
 			goto fallback_blt;
 
+		assert(src_bo == dst_bo);
+		assert(src->drawable.depth == dst->drawable.depth);
+		assert(src->drawable.width == dst->drawable.width);
+		assert(src->drawable.height == dst->drawable.height);
 		return sna_render_copy_boxes__overlap(sna, alu,
-						      src, src_bo, src_dx, src_dy,
-						      dst, dst_bo, dst_dx, dst_dy,
+						      src, src_bo,
+						      src_dx, src_dy,
+						      dst_dx, dst_dy,
 						      box, n, &extents);
 	}
 
diff --git a/src/sna/gen7_render.c b/src/sna/gen7_render.c
index ce153e5..a588254 100644
--- a/src/sna/gen7_render.c
+++ b/src/sna/gen7_render.c
@@ -2891,40 +2891,6 @@ prefer_blt_copy(struct sna *sna,
 	return prefer_blt_bo(sna, src_bo) || prefer_blt_bo(sna, dst_bo);
 }
 
-inline static void boxes_extents(const BoxRec *box, int n, BoxRec *extents)
-{
-	*extents = box[0];
-	while (--n) {
-		box++;
-
-		if (box->x1 < extents->x1)
-			extents->x1 = box->x1;
-		if (box->x2 > extents->x2)
-			extents->x2 = box->x2;
-
-		if (box->y1 < extents->y1)
-			extents->y1 = box->y1;
-		if (box->y2 > extents->y2)
-			extents->y2 = box->y2;
-	}
-}
-
-static inline bool
-overlaps(struct sna *sna,
-	 struct kgem_bo *src_bo, int16_t src_dx, int16_t src_dy,
-	 struct kgem_bo *dst_bo, int16_t dst_dx, int16_t dst_dy,
-	 const BoxRec *box, int n, BoxRec *extents)
-{
-	if (src_bo != dst_bo)
-		return false;
-
-	boxes_extents(box, n, extents);
-	return (extents->x2 + src_dx > extents->x1 + dst_dx &&
-		extents->x1 + src_dx < extents->x2 + dst_dx &&
-		extents->y2 + src_dy > extents->y1 + dst_dy &&
-		extents->y1 + src_dy < extents->y2 + dst_dy);
-}
-
 static bool
 gen7_render_copy_boxes(struct sna *sna, uint8_t alu,
 		       PixmapPtr src, struct kgem_bo *src_bo, int16_t src_dx, int16_t src_dy,
@@ -2940,7 +2906,7 @@ gen7_render_copy_boxes(struct sna *sna, uint8_t alu,
 	     overlaps(sna,
 		      src_bo, src_dx, src_dy,
 		      dst_bo, dst_dx, dst_dy,
-		      box, n, &extents)));
+		      box, n, flags, &extents)));
 
 	if (prefer_blt_copy(sna, src_bo, dst_bo, flags) &&
 	    sna_blt_compare_depth(&src->drawable, &dst->drawable) &&
@@ -2966,7 +2932,8 @@ fallback_blt:
 	if (overlaps(sna,
 		     src_bo, src_dx, src_dy,
 		     dst_bo, dst_dx, dst_dy,
-		     box, n, &extents)) {
+		     box, n, flags,
+		     &extents)) {
 		bool big = too_large(extents.x2-extents.x1, extents.y2-extents.y1);
 
 		if ((big || can_switch_to_blt(sna, dst_bo, flags)) &&
@@ -2980,9 +2947,14 @@ fallback_blt:
 		if (big)
 			goto fallback_blt;
 
+		assert(src_bo == dst_bo);
+		assert(src->drawable.depth == dst->drawable.depth);
+		assert(src->drawable.width == dst->drawable.width);
+		assert(src->drawable.height == dst->drawable.height);
 		return sna_render_copy_boxes__overlap(sna, alu,
-						      src, src_bo, src_dx, src_dy,
-						      dst, dst_bo, dst_dx, dst_dy,
+						      src, src_bo,
+						      src_dx, src_dy,
+						      dst_dx, dst_dy,
 						      box, n, &extents);
 	}
 
diff --git a/src/sna/gen8_render.c b/src/sna/gen8_render.c
index 53bac81..365e8f6 100644
--- a/src/sna/gen8_render.c
+++ b/src/sna/gen8_render.c
@@ -2713,40 +2713,6 @@ prefer_blt_copy(struct sna *sna,
 	return prefer_blt_bo(sna, src_bo) || prefer_blt_bo(sna, dst_bo);
 }
 
-inline static void boxes_extents(const BoxRec *box, int n, BoxRec *extents)
-{
-	*extents = box[0];
-	while (--n) {
-		box++;
-
-		if (box->x1 < extents->x1)
-			extents->x1 = box->x1;
-		if (box->x2 > extents->x2)
-			extents->x2 = box->x2;
-
-		if (box->y1 < extents->y1)
-			extents->y1 = box->y1;
-		if (box->y2 > extents->y2)
-			extents->y2 = box->y2;
-	}
-}
-
-static inline bool
-overlaps(struct sna *sna,
-	 struct kgem_bo *src_bo, int16_t src_dx, int16_t src_dy,
-	 struct kgem_bo *dst_bo, int16_t dst_dx, int16_t dst_dy,
-	 const BoxRec *box, int n, BoxRec *extents)
-{
-	if (src_bo != dst_bo)
-		return false;
-
-	boxes_extents(box, n, extents);
-	return (extents->x2 + src_dx > extents->x1 + dst_dx &&
-		extents->x1 + src_dx < extents->x2 + dst_dx &&
-		extents->y2 + src_dy > extents->y1 + dst_dy &&
-		extents->y1 + src_dy < extents->y2 + dst_dy);
-}
-
 static bool
 gen8_render_copy_boxes(struct sna *sna, uint8_t alu,
 		       PixmapPtr src, struct kgem_bo *src_bo, int16_t src_dx, int16_t src_dy,
@@ -2762,7 +2728,7 @@ gen8_render_copy_boxes(struct sna *sna, uint8_t alu,
 	     overlaps(sna,
 		      src_bo, src_dx, src_dy,
 		      dst_bo, dst_dx, dst_dy,
-		      box, n, &extents)));
+		      box, n, flags, &extents)));
 
 	if (prefer_blt_copy(sna, src_bo, dst_bo, flags) &&
 	    sna_blt_compare_depth(&src->drawable, &dst->drawable) &&
@@ -2790,7 +2756,8 @@ fallback_blt:
 	if (overlaps(sna,
 		     src_bo, src_dx, src_dy,
 		     dst_bo, dst_dx, dst_dy,
-		     box, n, &extents)) {
+		     box, n, flags,
+		     &extents)) {
 		bool big = too_large(extents.x2-extents.x1, extents.y2-extents.y1);
 
 		if ((big || can_switch_to_blt(sna, dst_bo, flags)) &&
@@ -2804,9 +2771,14 @@ fallback_blt:
 		if (big)
 			goto fallback_blt;
 
+		assert(src_bo == dst_bo);
+		assert(src->drawable.depth == dst->drawable.depth);
+		assert(src->drawable.width == dst->drawable.width);
+		assert(src->drawable.height == dst->drawable.height);
 		return sna_render_copy_boxes__overlap(sna, alu,
-						      src, src_bo, src_dx, src_dy,
-						      dst, dst_bo, dst_dx, dst_dy,
+						      src, src_bo,
+						      src_dx, src_dy,
+						      dst_dx, dst_dy,
 						      box, n, &extents);
 	}
 
diff --git a/src/sna/sna_render.c b/src/sna/sna_render.c
index e8060b4..b455f42 100644
--- a/src/sna/sna_render.c
+++ b/src/sna/sna_render.c
@@ -2123,37 +2123,159 @@ sna_render_composite_redirect_done(struct sna *sna,
 	}
 }
 
-bool
-sna_render_copy_boxes__overlap(struct sna *sna, uint8_t alu,
-			       PixmapPtr src, struct kgem_bo *src_bo, int16_t src_dx, int16_t src_dy,
-			       PixmapPtr dst, struct kgem_bo *dst_bo, int16_t dst_dx, int16_t dst_dy,
-			       const BoxRec *box, int n, const BoxRec *extents)
+static bool
+copy_overlap(struct sna *sna, uint8_t alu,
+	     PixmapPtr pixmap, struct kgem_bo *bo,
+	     int16_t src_dx, int16_t src_dy,
+	     int16_t dst_dx, int16_t dst_dy,
+	     const BoxRec *box, int n, const BoxRec *extents)
 {
-	ScreenPtr screen = dst->drawable.pScreen;
-	struct kgem_bo *bo;
+	ScreenPtr screen = pixmap->drawable.pScreen;
+	struct kgem_bo *tmp_bo;
 	PixmapPtr tmp;
 	bool ret = false;
 
+	if (n == 0)
+		return true;
+
+	DBG(("%s: %d x %dx%d src=(%d, %d), dst=(%d, %d)\n",
+	     __FUNCTION__, n,
+	     extents->x2 - extents->x1,
+	     extents->y2 - extents->y1,
+	     src_dx, src_dy,
+	     dst_dx, dst_dy));
+
 	tmp = screen->CreatePixmap(screen,
 				   extents->x2 - extents->x1,
 				   extents->y2 - extents->y1,
-				   dst->drawable.depth,
+				   pixmap->drawable.depth,
 				   SNA_CREATE_SCRATCH);
 	if (tmp == NULL)
 		return false;
 
-	bo = __sna_pixmap_get_bo(tmp);
-	assert(bo);
+	tmp_bo = __sna_pixmap_get_bo(tmp);
+	assert(tmp_bo);
 
 	ret = (sna->render.copy_boxes(sna, GXcopy,
-				      src, src_bo, src_dx, src_dy,
-				      tmp, bo, -extents->x1, -extents->y1,
+				      pixmap, bo, src_dx, src_dy,
+				      tmp, tmp_bo, -extents->x1, -extents->y1,
 				      box, n , 0) &&
 	       sna->render.copy_boxes(sna, alu,
-				      tmp, bo, -extents->x1, -extents->y1,
-				      dst, dst_bo, dst_dx, dst_dy,
+				      tmp, tmp_bo, -extents->x1, -extents->y1,
+				      pixmap, bo, dst_dx, dst_dy,
 				      box, n , 0));
 
 	screen->DestroyPixmap(tmp);
 	return ret;
 }
+bool
+sna_render_copy_boxes__overlap(struct sna *sna, uint8_t alu,
+			       PixmapPtr pixmap, struct kgem_bo *bo,
+			       int16_t src_dx, int16_t src_dy,
+			       int16_t dst_dx, int16_t dst_dy,
+			       const BoxRec *box, int n, const BoxRec *extents)
+{
+	bool ret = false;
+	RegionRec overlap, non_overlap;
+	pixman_region16_t region;
+	pixman_box16_t stack_boxes[64], *boxes = stack_boxes;
+	int num_boxes, i;
+
+	DBG(("%s: pixmap=%ld, handle=%d, %d x [(%d, %d), (%d, %d)], dst=(%d, %d), src=(%d, %d)\n",
+	     __FUNCTION__, pixmap->drawable.serialNumber, bo->handle,
+	     n, extents->x1, extents->y1, extents->x2, extents->y2,
+	     src_dx, src_dy, dst_dx, dst_dy));
+
+	if ((dst_dx - src_dx < 4 && src_dx - dst_dx < 4) &&
+	    (dst_dy - src_dy < 4 && src_dy - dst_dy < 4))
+		return copy_overlap(sna, alu, pixmap, bo,
+				    src_dx, src_dy,
+				    dst_dx, dst_dy,
+				    box, n, extents);
+
+	if (n > ARRAY_SIZE(stack_boxes)) {
+		boxes = malloc(sizeof(pixman_box16_t) * n);
+		if (boxes == NULL)
+			return copy_overlap(sna, alu, pixmap, bo,
+					    src_dx, src_dy,
+					    dst_dx, dst_dy,
+					    box, n, extents);
+	}
+
+	region.extents.x1 = extents->x1 + dst_dx;
+	region.extents.x2 = extents->x2 + dst_dx;
+	region.extents.y1 = extents->y1 + dst_dy;
+	region.extents.y2 = extents->x2 + dst_dy;
+
+	for (i = num_boxes = 0; i < n; i++) {
+		boxes[num_boxes].x1 = box[i].x1 + dst_dx;
+		if (boxes[num_boxes].x1 < region.extents.x1)
+			boxes[num_boxes].x1 = region.extents.x1;
+
+		boxes[num_boxes].y1 = box[i].y1 + dst_dy;
+		if (boxes[num_boxes].y1 < region.extents.y1)
+			boxes[num_boxes].y1 = region.extents.y1;
+
+		boxes[num_boxes].x2 = box[i].x2 + dst_dy;
+		if (boxes[num_boxes].x2 > region.extents.x2)
+			boxes[num_boxes].x2 = region.extents.x2;
+
+		boxes[num_boxes].y2 = box[i].y2 + dst_dy;
+		if (boxes[num_boxes].y2 > region.extents.y2)
+			boxes[num_boxes].y2 = region.extents.y2;
+
+		if (boxes[num_boxes].x2 > boxes[num_boxes].x1 &&
+		    boxes[num_boxes].y2 > boxes[num_boxes].y1)
+			num_boxes++;
+	}
+
+	if (num_boxes == 0) {
+		ret = true;
+		goto cleanup_boxes;
+	}
+
+	if (!pixman_region_init_rects(&region, boxes, num_boxes))
+		goto cleanup_boxes;
+
+	overlap.extents.x1 = extents->x1 + src_dx;
+	overlap.extents.x2 = extents->x2 + src_dx;
+	overlap.extents.y1 = extents->y1 + src_dy;
+	overlap.extents.y2 = extents->x2 + src_dy;
+	overlap.data = NULL;
+
+	RegionIntersect(&overlap, &overlap, &region);
+	DBG(("%s: overlapping extents: (%d, %d), (%d, %d) x %d\n",
+	     __FUNCTION__,
+	     overlap.extents.x1, overlap.extents.y1,
+	     overlap.extents.x2, overlap.extents.y2,
+	     region_num_rects(&overlap)));
+
+	RegionNull(&non_overlap);
+	RegionSubtract(&non_overlap, &region, &overlap);
+	DBG(("%s: non-overlapping extents: (%d, %d), (%d, %d) x %d\n",
+	     __FUNCTION__,
+	     non_overlap.extents.x1, non_overlap.extents.y1,
+	     non_overlap.extents.x2, non_overlap.extents.y2,
+	     region_num_rects(&non_overlap)));
+
+	n = region_num_rects(&non_overlap);
+	box = region_rects(&non_overlap);
+	if (n && !sna->render.copy_boxes(sna, alu,
+					 pixmap, bo, -dst_dx + src_dx, -dst_dy + src_dy,
+					 pixmap, bo, 0, 0,
+					 box, n , COPY_NO_OVERLAP))
+		goto cleanup_boxes;
+
+	n = region_num_rects(&overlap);
+	box = region_rects(&overlap);
+	ret = copy_overlap(sna, alu, pixmap, bo,
+			   -dst_dx + src_dx, -dst_dy + src_dy,
+			   0, 0,
+			   box, n, &overlap.extents);
+
+cleanup_boxes:
+	if (boxes != stack_boxes)
+		free(boxes);
+
+	return ret;
+}
diff --git a/src/sna/sna_render.h b/src/sna/sna_render.h
index 52bb44e..0637ceb 100644
--- a/src/sna/sna_render.h
+++ b/src/sna/sna_render.h
@@ -285,6 +285,7 @@ struct sna_render {
 			   const BoxRec *box, int n, unsigned flags);
 #define COPY_LAST 0x1
 #define COPY_SYNC 0x2
+#define COPY_NO_OVERLAP 0x4
 
 	bool (*copy)(struct sna *sna, uint8_t alu,
 		     PixmapPtr src, struct kgem_bo *src_bo,
@@ -814,8 +815,9 @@ sna_render_composite_redirect_done(struct sna *sna,
 
 bool
 sna_render_copy_boxes__overlap(struct sna *sna, uint8_t alu,
-			       PixmapPtr src, struct kgem_bo *src_bo, int16_t src_dx, int16_t src_dy,
-			       PixmapPtr dst, struct kgem_bo *dst_bo, int16_t dst_dx, int16_t dst_dy,
+			       PixmapPtr pixmap, struct kgem_bo *bo,
+			       int16_t src_dx, int16_t src_dy,
+			       int16_t dst_dx, int16_t dst_dy,
 			       const BoxRec *box, int n, const BoxRec *extents);
 
 bool
diff --git a/src/sna/sna_render_inline.h b/src/sna/sna_render_inline.h
index 3750117..d51730e 100644
--- a/src/sna/sna_render_inline.h
+++ b/src/sna/sna_render_inline.h
@@ -319,5 +319,43 @@ untransformed(PicturePtr p)
 	return !p->transform || pixman_transform_is_int_translate(p->transform);
 }
 
+inline static void
+boxes_extents(const BoxRec *box, int n, BoxRec *extents)
+{
+	*extents = box[0];
+	while (--n) {
+		box++;
+
+		if (box->x1 < extents->x1)
+			extents->x1 = box->x1;
+		if (box->x2 > extents->x2)
+			extents->x2 = box->x2;
+
+		if (box->y1 < extents->y1)
+			extents->y1 = box->y1;
+		if (box->y2 > extents->y2)
+			extents->y2 = box->y2;
+	}
+}
+
+inline static bool
+overlaps(struct sna *sna,
+	 struct kgem_bo *src_bo, int16_t src_dx, int16_t src_dy,
+	 struct kgem_bo *dst_bo, int16_t dst_dx, int16_t dst_dy,
+	 const BoxRec *box, int n, unsigned flags,
+	 BoxRec *extents)
+{
+	if (src_bo != dst_bo)
+		return false;
+
+	if (flags & COPY_NO_OVERLAP)
+		return false;
+
+	boxes_extents(box, n, extents);
+	return (extents->x2 + src_dx > extents->x1 + dst_dx &&
+		extents->x1 + src_dx < extents->x2 + dst_dx &&
+		extents->y2 + src_dy > extents->y1 + dst_dy &&
+		extents->y1 + src_dy < extents->y2 + dst_dy);
+}
 
 #endif /* SNA_RENDER_INLINE_H */
commit 6e2cee27c379278b0321fd1db34ed80c439115a7
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date:   Tue Jun 24 07:34:46 2014 +0100

    sna/dri2: Add a dash more asserts
    
    References: https://bugs.freedesktop.org/attachment.cgi?id=101618
    Signed-off-by: Chris Wilson <chris at chris-wilson.co.uk>

diff --git a/src/sna/sna_dri2.c b/src/sna/sna_dri2.c
index 686fd60..4220f8f 100644
--- a/src/sna/sna_dri2.c
+++ b/src/sna/sna_dri2.c
@@ -1313,15 +1313,19 @@ void sna_dri2_destroy_window(WindowPtr win)
 
 		info = priv->chain;
 		info->draw = NULL;
+		info->client = NULL;
 
 		chain = info->chain;
 		info->chain = NULL;
 
 		assert(info->queued);
 		while ((info = chain)) {
+			info->draw = NULL;
+			info->client = NULL;
+
 			chain = info->chain;
 			info->chain = NULL;
-			info->draw = NULL;
+
 			if (!info->queued)
 				sna_dri2_event_free(sna, NULL, info);
 		}
@@ -1787,6 +1791,8 @@ static void frame_swap_complete(struct sna *sna,
 	if (frame->draw == NULL)
 		return;
 
+	assert(frame->client);
+
 	swap = sna_crtc_last_swap(frame->crtc);
 	DBG(("%s: draw=%ld, pipe=%d, frame=%lld [msc=%lld], tv=%d.%06d\n",
 	     __FUNCTION__, (long)frame->draw, frame->pipe,
@@ -2146,6 +2152,7 @@ static void chain_flip(struct sna *sna)
 	}
 
 	assert(chain == dri2_chain(chain->draw));
+	assert(!chain->queued);
 	chain->queued = true;
 
 	if (can_flip(sna, chain->draw, chain->front, chain->back, chain->crtc) &&
@@ -2153,7 +2160,6 @@ static void chain_flip(struct sna *sna)
 		DBG(("%s: performing chained flip\n", __FUNCTION__));
 	} else {
 		DBG(("%s: emitting chained vsync'ed blit\n", __FUNCTION__));
-		assert(chain->queued);
 		chain->bo = __sna_dri2_copy_region(sna, chain->draw, NULL,
 						  chain->back, chain->front,
 						  true);
@@ -2185,6 +2191,7 @@ static void sna_dri2_flip_event(struct sna *sna,
 				struct sna_dri2_event *flip)
 {
 	DBG(("%s(pipe=%d, event=%d)\n", __FUNCTION__, flip->pipe, flip->type));
+	assert(flip->queued);
 
 	if (sna->dri2.flip_pending == flip)
 		sna->dri2.flip_pending = NULL;
diff --git a/src/sna/sna_render.c b/src/sna/sna_render.c
index 3b8a54a..e8060b4 100644
--- a/src/sna/sna_render.c
+++ b/src/sna/sna_render.c
@@ -1348,10 +1348,10 @@ sna_render_picture_convolve(struct sna *sna,
 		DBG(("%s: pixmap allocation failed\n", __FUNCTION__));
 		return -1;
 	}
-	assert(__sna_pixmap_get_bo(tmp));
 
 	tmp = NULL;
 	bo = __sna_pixmap_get_bo(pixmap);
+	assert(bo);
 	if (sna->render.clear(sna, pixmap, bo))
 		tmp = CreatePicture(0, &pixmap->drawable,
 				PictureMatchFormat(screen, depth, channel->pict_format),


More information about the xorg-commit mailing list