summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChris Wilson <chris@chris-wilson.co.uk>2014-09-15 11:36:20 +0100
committerChris Wilson <chris@chris-wilson.co.uk>2014-09-15 11:41:38 +0100
commitd470f0f520f6bd160ae4acef2b4b3c86afd8dbbd (patch)
tree1a6d94cdc2bdc352a4bd512f3ae781008b62877a
parent435fe185e335a147f5edb803561509e1f0cb4e70 (diff)
sna: Last ditch attempt to make extra large batches fit
If we have unfortunate fragmentation, e.g. a cursor is pinned in the middle of an aperture, we can struggle to fit large objects, especially fenced objects on gen2/gen3. We do have one last trick up our sleeves that we can try: disable all of the outputs and cursors and try submitting the batch in as pristine an aperture as we can arrange. We can only hope that the subsequent restoration of the outputs is more conducive to future batches (and so not lead us into continual flicker). Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
-rw-r--r--src/sna/kgem.c25
-rw-r--r--src/sna/sna.h2
-rw-r--r--src/sna/sna_display.c46
3 files changed, 71 insertions, 2 deletions
diff --git a/src/sna/kgem.c b/src/sna/kgem.c
index 82ff619f..485ef8fb 100644
--- a/src/sna/kgem.c
+++ b/src/sna/kgem.c
@@ -3200,7 +3200,7 @@ static void dump_fence_regs(struct kgem *kgem)
static int do_execbuf(struct kgem *kgem, struct drm_i915_gem_execbuffer2 *execbuf)
{
- int ret;
+ int ret, err;
retry:
ret = do_ioctl(kgem->fd, DRM_IOCTL_I915_GEM_EXECBUFFER2, execbuf);
@@ -3216,7 +3216,28 @@ retry:
goto retry;
/* last gasp */
- return do_ioctl(kgem->fd, DRM_IOCTL_I915_GEM_EXECBUFFER2, execbuf);
+ ret = do_ioctl(kgem->fd, DRM_IOCTL_I915_GEM_EXECBUFFER2, execbuf);
+ if (ret == 0)
+ return 0;
+
+ xf86DrvMsg(kgem_get_screen_index(kgem), X_WARNING,
+ "Failed to submit rendering commands, trying again with outputs disabled.\n");
+
+ /* One last trick up our sleeve for when we run out of space.
+ * We turn everything off to free up our pinned framebuffers,
+ * sprites and cursors, and try one last time.
+ */
+ err = errno;
+ if (sna_mode_disable(container_of(kgem, struct sna, kgem))) {
+ kgem_cleanup_cache(kgem);
+ ret = do_ioctl(kgem->fd,
+ DRM_IOCTL_I915_GEM_EXECBUFFER2,
+ execbuf);
+ sna_mode_enable(container_of(kgem, struct sna, kgem));
+ }
+ errno = err;
+
+ return ret;
}
void _kgem_submit(struct kgem *kgem)
diff --git a/src/sna/sna.h b/src/sna/sna.h
index ad74870a..04ee35c9 100644
--- a/src/sna/sna.h
+++ b/src/sna/sna.h
@@ -426,6 +426,8 @@ bool sna_mode_wants_tear_free(struct sna *sna);
void sna_mode_adjust_frame(struct sna *sna, int x, int y);
extern void sna_mode_discover(struct sna *sna);
extern void sna_mode_check(struct sna *sna);
+extern bool sna_mode_disable(struct sna *sna);
+extern void sna_mode_enable(struct sna *sna);
extern void sna_mode_reset(struct sna *sna);
extern void sna_mode_wakeup(struct sna *sna);
extern void sna_mode_redisplay(struct sna *sna);
diff --git a/src/sna/sna_display.c b/src/sna/sna_display.c
index 54ebe786..2a98fb94 100644
--- a/src/sna/sna_display.c
+++ b/src/sna/sna_display.c
@@ -5785,6 +5785,52 @@ sna_mode_set_primary(struct sna *sna)
#endif
}
+bool
+sna_mode_disable(struct sna *sna)
+{
+ xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(sna->scrn);
+ int i;
+
+ if (sna->flags & SNA_IS_HOSTED)
+ return false;
+
+ if (!sna->scrn->vtSema)
+ return false;
+
+ sna_hide_cursors(sna->scrn);
+ for (i = 0; i < sna->mode.num_real_crtc; i++)
+ sna_crtc_disable(config->crtc[i]);
+
+ while (sna_mode_has_pending_events(sna))
+ sna_mode_wakeup(sna);
+
+ kgem_clean_scanout_cache(&sna->kgem);
+ return true;
+}
+
+void
+sna_mode_enable(struct sna *sna)
+{
+ xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(sna->scrn);
+ int i;
+
+ if (sna->flags & SNA_IS_HOSTED)
+ return;
+
+ if (!sna->scrn->vtSema)
+ return;
+
+ for (i = 0; i < sna->mode.num_real_crtc; i++) {
+ xf86CrtcPtr crtc = config->crtc[i];
+
+ assert(to_sna_crtc(crtc) != NULL);
+ if (!crtc->enabled)
+ continue;
+
+ __sna_crtc_set_mode(crtc);
+ }
+}
+
void
sna_mode_close(struct sna *sna)
{