xserver-xorg-video-intel: Changes to 'ubuntu'
debian/changelog | 11
debian/patches/series | 1
debian/patches/sna-flush-scanout-cache-after-resizing.patch | 228 ++++++++++++
3 files changed, 240 insertions(+)
New commits:
commit 30fce9c04afb32c5d060d7040d8e28d7de12228b
Author: Bryce Harrington <bryce@canonical.com>
Date: Fri Apr 19 21:27:20 2013 -0700
Add sna-flush-scanout-cache-after-resizing.patch
diff --git a/debian/changelog b/debian/changelog
index 6c2e6f1..be1fca2 100644
--- a/debian/changelog
+++ b/debian/changelog
@@ -1,3 +1,14 @@
+xserver-xorg-video-intel (2:2.21.6-0ubuntu4) raring-proposed; urgency=low
+
+ [Chris Arges]
+ * Add sna-flush-scanout-cache-after-resizing.patch: Flush the scanout
+ cache after resizing the display. Fixes a problem that occurs
+ e.g. when unplugging an external display, suspend/resume, etc. by
+ ensuring the scanout cache is properly sized.
+ (LP: #1157678)
+
+ -- Bryce Harrington <bryce@ubuntu.com> Fri, 19 Apr 2013 11:12:14 -0700
+
xserver-xorg-video-intel (2:2.21.6-0ubuntu3) raring-proposed; urgency=low
* rules: Drop --enable-valgrind for now (causes FTBS).
diff --git a/debian/patches/series b/debian/patches/series
index 23ed8a4..df7cb15 100644
--- a/debian/patches/series
+++ b/debian/patches/series
@@ -1 +1,2 @@
0002-Update-manpage-for-new-accelmethod-option.patch
+sna-flush-scanout-cache-after-resizing.patch
diff --git a/debian/patches/sna-flush-scanout-cache-after-resizing.patch b/debian/patches/sna-flush-scanout-cache-after-resizing.patch
new file mode 100644
index 0000000..bb4928f
--- /dev/null
+++ b/debian/patches/sna-flush-scanout-cache-after-resizing.patch
@@ -0,0 +1,228 @@
+From e083fbdc3f2025f4ccc199070e2488afc5afb2a7 Mon Sep 17 00:00:00 2001
+From: Chris Wilson <chris@chris-wilson.co.uk>
+Date: Fri, 12 Apr 2013 11:01:08 +0100
+Subject: [PATCH] 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@chris-wilson.co.uk>
+(cherry picked from commit 9dae6f9f1f169c228929185a8bd94e82afe92574)
+
+Conflicts:
+
+ src/sna/kgem.h
+---
+ src/sna/kgem.c | 88 ++++++++++++++++++++++++++++++++++++-------------
+ src/sna/kgem.h | 3 ++
+ src/sna/sna_display.c | 23 ++++++++-----
+ 3 files changed, 83 insertions(+), 31 deletions(-)
+
+diff --git a/src/sna/kgem.c b/src/sna/kgem.c
+index 4136ce9..cb2dea7 100644
+--- a/src/sna/kgem.c
++++ b/src/sna/kgem.c
+@@ -1601,6 +1601,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);
+@@ -1625,15 +1636,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)
+@@ -2769,6 +2796,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;
+@@ -2791,22 +2843,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) {
+@@ -2960,6 +2998,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,
+@@ -3571,6 +3612,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 f2b1c98..8f24d8b 100644
+--- a/src/sna/kgem.h
++++ b/src/sna/kgem.h
+@@ -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++)
+--
+1.7.9.5
+
Reply to: