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 <[email protected]> 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 <[email protected]> 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 <[email protected]> +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 <[email protected]> +(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 + -- To UNSUBSCRIBE, email to [email protected] with a subject of "unsubscribe". Trouble? Contact [email protected] Archive: http://lists.debian.org/[email protected]

