xf86-video-intel: src/sna/kgem.c src/sna/kgem.h src/sna/sna_display.c

Chris Wilson ickle at kemper.freedesktop.org
Fri Apr 12 03:40:26 PDT 2013


 src/sna/kgem.c        |   88 +++++++++++++++++++++++++++++++++++++-------------
 src/sna/kgem.h        |    5 ++
 src/sna/sna_display.c |   23 +++++++------
 3 files changed, 84 insertions(+), 32 deletions(-)

New commits:
commit 9dae6f9f1f169c228929185a8bd94e82afe92574
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date:   Fri Apr 12 11:01:08 2013 +0100

    sna: Flush the scanout cache after resizing the display
    
    And ensure that any new scanout allocations make the requested size.
    
    Signed-off-by: Chris Wilson <chris at chris-wilson.co.uk>

diff --git a/src/sna/kgem.c b/src/sna/kgem.c
index 4b13cc0..a2bb688 100644
--- a/src/sna/kgem.c
+++ b/src/sna/kgem.c
@@ -1603,6 +1603,17 @@ inline static void kgem_bo_remove_from_active(struct kgem *kgem,
 	assert(list_is_empty(&bo->vma));
 }
 
+static void _kgem_bo_delete_buffer(struct kgem *kgem, struct kgem_bo *bo)
+{
+	struct kgem_buffer *io = (struct kgem_buffer *)bo->proxy;
+
+	DBG(("%s: size=%d, offset=%d, parent used=%d\n",
+	     __FUNCTION__, bo->size.bytes, bo->delta, io->used));
+
+	if (ALIGN(bo->delta + bo->size.bytes, UPLOAD_ALIGNMENT) == io->used)
+		io->used = bo->delta;
+}
+
 static void kgem_bo_clear_scanout(struct kgem *kgem, struct kgem_bo *bo)
 {
 	assert(bo->scanout);
@@ -1627,15 +1638,31 @@ static void kgem_bo_clear_scanout(struct kgem *kgem, struct kgem_bo *bo)
 		bo->reusable = false;
 }
 
-static void _kgem_bo_delete_buffer(struct kgem *kgem, struct kgem_bo *bo)
+static bool check_scanout_size(struct kgem *kgem,
+			       struct kgem_bo *bo,
+			       int width, int height)
 {
-	struct kgem_buffer *io = (struct kgem_buffer *)bo->proxy;
+	struct drm_mode_fb_cmd info;
 
-	DBG(("%s: size=%d, offset=%d, parent used=%d\n",
-	     __FUNCTION__, bo->size.bytes, bo->delta, io->used));
+	assert(bo->scanout);
 
-	if (ALIGN(bo->delta + bo->size.bytes, UPLOAD_ALIGNMENT) == io->used)
-		io->used = bo->delta;
+	VG_CLEAR(info);
+	info.fb_id = bo->delta;
+
+	if (drmIoctl(kgem->fd, DRM_IOCTL_MODE_GETFB, &info))
+		return false;
+
+	gem_close(kgem->fd, info.handle);
+
+	if (width != info.width || height != info.height) {
+		DBG(("%s: not using scanout %d (%dx%d), want (%dx%d)\n",
+		     __FUNCTION__,
+		     info.fb_id, info.width, info.height,
+		     width, height))
+		return false;
+	}
+
+	return true;
 }
 
 static void kgem_bo_move_to_scanout(struct kgem *kgem, struct kgem_bo *bo)
@@ -2771,6 +2798,31 @@ void kgem_purge_cache(struct kgem *kgem)
 	kgem->need_purge = false;
 }
 
+void kgem_clean_scanout_cache(struct kgem *kgem)
+{
+	while (!list_is_empty(&kgem->scanout)) {
+		struct kgem_bo *bo;
+
+		bo = list_first_entry(&kgem->scanout, struct kgem_bo, list);
+		if (__kgem_busy(kgem, bo->handle))
+			break;
+
+		list_del(&bo->list);
+		kgem_bo_clear_scanout(kgem, bo);
+		__kgem_bo_destroy(kgem, bo);
+	}
+}
+
+void kgem_clean_large_cache(struct kgem *kgem)
+{
+	while (!list_is_empty(&kgem->large_inactive)) {
+		kgem_bo_free(kgem,
+			     list_first_entry(&kgem->large_inactive,
+					      struct kgem_bo, list));
+
+	}
+}
+
 bool kgem_expire_cache(struct kgem *kgem)
 {
 	time_t now, expire;
@@ -2793,22 +2845,8 @@ bool kgem_expire_cache(struct kgem *kgem)
 		free(rq);
 	}
 
-	while (!list_is_empty(&kgem->large_inactive)) {
-		kgem_bo_free(kgem,
-			     list_first_entry(&kgem->large_inactive,
-					      struct kgem_bo, list));
-
-	}
-
-	while (!list_is_empty(&kgem->scanout)) {
-		bo = list_first_entry(&kgem->scanout, struct kgem_bo, list);
-		if (__kgem_busy(kgem, bo->handle))
-			break;
-
-		list_del(&bo->list);
-		kgem_bo_clear_scanout(kgem, bo);
-		__kgem_bo_destroy(kgem, bo);
-	}
+	kgem_clean_large_cache(kgem);
+	kgem_clean_scanout_cache(kgem);
 
 	expire = 0;
 	list_for_each_entry(bo, &kgem->snoop, list) {
@@ -2962,6 +3000,9 @@ void kgem_cleanup_cache(struct kgem *kgem)
 						     struct kgem_bo, list));
 	}
 
+	kgem_clean_large_cache(kgem);
+	kgem_clean_scanout_cache(kgem);
+
 	while (!list_is_empty(&kgem->snoop))
 		kgem_bo_free(kgem,
 			     list_last_entry(&kgem->snoop,
@@ -3576,6 +3617,9 @@ struct kgem_bo *kgem_create_2d(struct kgem *kgem,
 			if (size > num_pages(bo) || num_pages(bo) > 2*size)
 				continue;
 
+			if (!check_scanout_size(kgem, bo, width, height))
+				continue;
+
 			if (bo->tiling != tiling ||
 			    (tiling != I915_TILING_NONE && bo->pitch != pitch)) {
 				if (!gem_set_tiling(kgem->fd, bo->handle,
diff --git a/src/sna/kgem.h b/src/sna/kgem.h
index e486292..3086f17 100644
--- a/src/sna/kgem.h
+++ b/src/sna/kgem.h
@@ -194,10 +194,10 @@ struct kgem {
 	void (*retire)(struct kgem *kgem);
 	void (*expire)(struct kgem *kgem);
 
+	uint16_t reloc__self[256];
 	uint32_t batch[64*1024-8] page_aligned;
 	struct drm_i915_gem_exec_object2 exec[256] page_aligned;
 	struct drm_i915_gem_relocation_entry reloc[4096] page_aligned;
-	uint16_t reloc__self[256];
 
 #ifdef DEBUG_MEMORY
 	struct {
@@ -682,6 +682,9 @@ bool kgem_expire_cache(struct kgem *kgem);
 void kgem_purge_cache(struct kgem *kgem);
 void kgem_cleanup_cache(struct kgem *kgem);
 
+void kgem_clean_scanout_cache(struct kgem *kgem);
+void kgem_clean_large_cache(struct kgem *kgem);
+
 #if HAS_DEBUG_FULL
 void __kgem_batch_debug(struct kgem *kgem, uint32_t nbatch);
 #else
diff --git a/src/sna/sna_display.c b/src/sna/sna_display.c
index 0d32086..ba9bf79 100644
--- a/src/sna/sna_display.c
+++ b/src/sna/sna_display.c
@@ -103,6 +103,14 @@ static inline struct sna_crtc *to_sna_crtc(xf86CrtcPtr crtc)
 	return crtc->driver_private;
 }
 
+static bool sna_mode_has_pending_events(struct sna *sna)
+{
+	struct pollfd pfd;
+	pfd.fd = sna->kgem.fd;
+	pfd.events = POLLIN;
+	return poll(&pfd, 1, 0) == 1;
+}
+
 #define BACKLIGHT_CLASS "/sys/class/backlight"
 
 /* Enough for 10 digits of backlight + '\n' + '\0' */
@@ -2601,6 +2609,11 @@ sna_mode_resize(ScrnInfoPtr scrn, int width, int height)
 
 	screen->DestroyPixmap(old_front);
 
+	while (sna_mode_has_pending_events(sna))
+		sna_mode_wakeup(sna);
+
+	kgem_clean_scanout_cache(&sna->kgem);
+
 	return TRUE;
 }
 
@@ -2743,14 +2756,6 @@ bool sna_mode_pre_init(ScrnInfoPtr scrn, struct sna *sna)
 	return true;
 }
 
-static Bool sna_mode_has_pending_events(struct sna *sna)
-{
-	struct pollfd pfd;
-	pfd.fd = sna->kgem.fd;
-	pfd.events = POLLIN;
-	return poll(&pfd, 1, 0) == 1;
-}
-
 void
 sna_mode_close(struct sna *sna)
 {
@@ -2761,7 +2766,7 @@ sna_mode_close(struct sna *sna)
 	 * check that the fd is readable before attempting to read the next
 	 * event from drm.
 	 */
-	if (sna_mode_has_pending_events(sna))
+	while (sna_mode_has_pending_events(sna))
 		sna_mode_wakeup(sna);
 
 	for (i = 0; i < xf86_config->num_crtc; i++)


More information about the xorg-commit mailing list