summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorRay Smith <raymond.smith@arm.com>2013-03-13 10:08:36 +0000
committerRay Smith <raymond.smith@arm.com>2013-07-23 15:00:39 +0100
commitb4299f81bc02f7c8536aa5d49f47e5d73f517ce0 (patch)
treeda28d80960c6471c704aafc6375eb92f0422d2b2 /src
parent4d37be3492bb1d3af52b550fdb233f411b004d70 (diff)
Fallback to blitting when out of scanout memory
If DRM can't allocate a scanout buffer for a flippable window's back buffer, we now attempt to allocate a non-scanout buffer and blit the window rather than fail the DRI2 buffer allocation completely. Note that this fallback is only suitable for back buffers - if reallocating the front buffer (on res change etc.) failed, we can't fall back to a non-scanout buffer. Change-Id: I9614dde01e80fd3dc03a37afee1a38d00dd55348
Diffstat (limited to 'src')
-rw-r--r--src/armsoc_dri2.c14
-rw-r--r--src/armsoc_dumb.c1
-rw-r--r--src/armsoc_exa.c29
-rw-r--r--src/drmmode_display.c30
4 files changed, 60 insertions, 14 deletions
diff --git a/src/armsoc_dri2.c b/src/armsoc_dri2.c
index a2e71ca..ae8b05e 100644
--- a/src/armsoc_dri2.c
+++ b/src/armsoc_dri2.c
@@ -229,16 +229,16 @@ ARMSOCDRI2CreateBuffer(DrawablePtr pDraw, unsigned int attachment,
goto fail;
}
- /* Q: how to know across ARMSOC generations what formats the display
- * can support directly?
- * A: attempt to create a drm_framebuffer, and if that fails then the
- * hw must not support.. then fall back to blitting
- */
if (canflip(pDraw) && attachment != DRI2BufferFrontLeft) {
+ /* Create an fb around this buffer. This will fail and we will
+ * fall back to blitting if the display controller hardware
+ * cannot scan out this buffer (for example, if it doesn't
+ * support the format or there was insufficient scanout memory
+ * at buffer creation time). */
int ret = armsoc_bo_add_fb(bo);
if (ret) {
- /* to-bad, so-sad, we can't flip */
- WARNING_MSG("could not create fb: %d", ret);
+ WARNING_MSG(
+ "Falling back to blitting a flippable window");
}
}
diff --git a/src/armsoc_dumb.c b/src/armsoc_dumb.c
index d395b89..a1fd800 100644
--- a/src/armsoc_dumb.c
+++ b/src/armsoc_dumb.c
@@ -350,7 +350,6 @@ int armsoc_bo_add_fb(struct armsoc_bo *bo)
ret = drmModeAddFB(bo->dev->fd, bo->width, bo->height, bo->depth,
bo->bpp, bo->pitch, bo->handle, &bo->fb_id);
if (ret < 0) {
- xf86DrvMsg(-1, X_ERROR, "Could not add fb to bo %d\n", ret);
bo->fb_id = 0;
return ret;
}
diff --git a/src/armsoc_exa.c b/src/armsoc_exa.c
index 8aaa297..879c605 100644
--- a/src/armsoc_exa.c
+++ b/src/armsoc_exa.c
@@ -96,6 +96,21 @@ ARMSOCCreatePixmap2(ScreenPtr pScreen, int width, int height,
height,
depth,
bitsPerPixel, buf_type);
+
+ if ((!priv->bo) && ARMSOC_BO_SCANOUT == buf_type) {
+ /* Tried to create a scanout but failed. Attempt to
+ * fall back to non-scanout instead.
+ */
+ WARNING_MSG(
+ "Scanout buffer allocation failed, falling back to non-scanout");
+ buf_type = ARMSOC_BO_NON_SCANOUT;
+ priv->bo = armsoc_bo_new_with_dim(pARMSOC->dev,
+ width,
+ height,
+ depth,
+ bitsPerPixel, buf_type);
+ }
+
if (!priv->bo) {
ERROR_MSG("failed to allocate %dx%d bo, buf_type = %d",
width, height, buf_type);
@@ -204,6 +219,20 @@ ARMSOCModifyPixmapHeader(PixmapPtr pPixmap, int width, int height,
pPixmap->drawable.depth,
pPixmap->drawable.bitsPerPixel, buf_type);
+ if ((!priv->bo) && ARMSOC_BO_SCANOUT == buf_type) {
+ /* Tried to create a scanout but failed. Attempt to
+ * fall back to non-scanout instead.
+ */
+ WARNING_MSG(
+ "Scanout buffer allocation failed, falling back to non-scanout");
+ buf_type = ARMSOC_BO_NON_SCANOUT;
+ priv->bo = armsoc_bo_new_with_dim(pARMSOC->dev,
+ pPixmap->drawable.width,
+ pPixmap->drawable.height,
+ pPixmap->drawable.depth,
+ pPixmap->drawable.bitsPerPixel,
+ buf_type);
+ }
if (!priv->bo) {
ERROR_MSG("failed to allocate %dx%d bo, buf_type = %d",
pPixmap->drawable.width,
diff --git a/src/drmmode_display.c b/src/drmmode_display.c
index f805e29..ba6d439 100644
--- a/src/drmmode_display.c
+++ b/src/drmmode_display.c
@@ -200,8 +200,11 @@ drmmode_set_mode_major(xf86CrtcPtr crtc, DisplayModePtr mode,
pScrn->virtualX, pScrn->virtualY);
ret = armsoc_bo_add_fb(pARMSOC->scanout);
- if (ret)
+ if (ret) {
+ ERROR_MSG(
+ "Failed to add framebuffer to the scanout buffer");
return FALSE;
+ }
fb_id = armsoc_bo_get_fb(pARMSOC->scanout);
if (0 == fb_id)
@@ -1144,24 +1147,39 @@ drmmode_xf86crtc_resize(ScrnInfoPtr pScrn, int width, int height)
/* Resize the bo */
if (armsoc_bo_resize(pARMSOC->scanout, width, height)) {
armsoc_bo_clear(pARMSOC->scanout);
- armsoc_bo_add_fb(pARMSOC->scanout);
+ if (armsoc_bo_add_fb(pARMSOC->scanout))
+ ERROR_MSG(
+ "Failed to add framebuffer to the existing scanout buffer");
return FALSE;
}
+
/* Add new fb to the bo */
- if (armsoc_bo_clear(pARMSOC->scanout) ||
- armsoc_bo_add_fb(pARMSOC->scanout))
+ if (armsoc_bo_clear(pARMSOC->scanout))
+ return FALSE;
+
+ if (armsoc_bo_add_fb(pARMSOC->scanout)) {
+ ERROR_MSG(
+ "Failed to add framebuffer to the existing scanout buffer");
return FALSE;
+ }
pitch = armsoc_bo_pitch(pARMSOC->scanout);
} else {
DEBUG_MSG("allocated new scanout buffer okay");
pitch = armsoc_bo_pitch(new_scanout);
/* clear new BO and add FB */
- if (armsoc_bo_clear(new_scanout) ||
- armsoc_bo_add_fb(new_scanout)) {
+ if (armsoc_bo_clear(new_scanout)) {
+ armsoc_bo_unreference(new_scanout);
+ return FALSE;
+ }
+
+ if (armsoc_bo_add_fb(new_scanout)) {
+ ERROR_MSG(
+ "Failed to add framebuffer to the new scanout buffer");
armsoc_bo_unreference(new_scanout);
return FALSE;
}
+
/* Handle dma_buf fd that may be attached to old bo */
if (armsoc_bo_has_dmabuf(pARMSOC->scanout)) {
int res;