diff options
author | Eric Anholt <eric@anholt.net> | 2015-11-09 09:36:35 -0800 |
---|---|---|
committer | Eric Anholt <eric@anholt.net> | 2015-12-15 10:39:27 -0800 |
commit | 661bd478d3874ac4bb274ea0758003f07c2325e3 (patch) | |
tree | ba7a788019f5b4511b24ae314ed10251301db2a4 | |
parent | e7040514b6b1f0fdbeaf25a09ba809301f3f3233 (diff) |
glamor: Recover gracefully from prepare_access PBO allocation failure.raspbian-backport
We may be allocating big PBOs here, based on the size of the FBO, so
it's a fairly likely place for a driver to OOM. When it happens, just
fall back to the non-PBO transfer path.
Signed-off-by: Eric Anholt <eric@anholt.net>
-rw-r--r-- | glamor/glamor_prepare.c | 33 |
1 files changed, 24 insertions, 9 deletions
diff --git a/glamor/glamor_prepare.c b/glamor/glamor_prepare.c index 4d29bd9de..66eb87522 100644 --- a/glamor/glamor_prepare.c +++ b/glamor/glamor_prepare.c @@ -83,16 +83,33 @@ glamor_prep_pixmap_box(PixmapPtr pixmap, glamor_access_t access, BoxPtr box) RegionInit(&priv->prepare_region, box, 1); if (glamor_priv->has_rw_pbo) { + GLsizei size = pixmap->devKind * pixmap->drawable.height; + if (priv->pbo == 0) glGenBuffers(1, &priv->pbo); gl_usage = GL_STREAM_READ; glBindBuffer(GL_PIXEL_PACK_BUFFER, priv->pbo); - glBufferData(GL_PIXEL_PACK_BUFFER, - pixmap->devKind * pixmap->drawable.height, NULL, - gl_usage); - } else { + glamor_priv->suppress_gl_out_of_memory_logging = TRUE; + glBufferData(GL_PIXEL_PACK_BUFFER, size, NULL, gl_usage); + glamor_priv->suppress_gl_out_of_memory_logging = FALSE; + + if (glGetError() == GL_OUT_OF_MEMORY) { + if (!glamor_priv->logged_any_oom) { + LogMessageVerb(X_WARNING, 0, + "Failed to allocate %db PBO for fallback " + "rendering.\n", size); + LogMessageVerb(X_WARNING, 0, + "Expect reduced performance.\n"); + glamor_priv->logged_any_oom = true; + } + glDeleteBuffers(1, &priv->pbo); + priv->pbo = 0; + } + } + + if (!priv->pbo) { pixmap->devPrivate.ptr = malloc(pixmap->devKind * pixmap->drawable.height); if (!pixmap->devPrivate.ptr) @@ -106,7 +123,7 @@ glamor_prep_pixmap_box(PixmapPtr pixmap, glamor_access_t access, BoxPtr box) RegionUninit(®ion); - if (glamor_priv->has_rw_pbo) { + if (priv->pbo) { if (priv->map_access == GLAMOR_ACCESS_RW) gl_access = GL_READ_WRITE; else @@ -128,8 +145,6 @@ glamor_prep_pixmap_box(PixmapPtr pixmap, glamor_access_t access, BoxPtr box) static void glamor_fini_pixmap(PixmapPtr pixmap) { - ScreenPtr screen = pixmap->drawable.pScreen; - glamor_screen_private *glamor_priv = glamor_get_screen_private(screen); glamor_pixmap_private *priv = glamor_get_pixmap_private(pixmap); if (!GLAMOR_PIXMAP_PRIV_HAS_FBO(priv)) @@ -138,7 +153,7 @@ glamor_fini_pixmap(PixmapPtr pixmap) if (!priv->prepared) return; - if (glamor_priv->has_rw_pbo) { + if (priv->pbo) { glBindBuffer(GL_PIXEL_UNPACK_BUFFER, priv->pbo); glUnmapBuffer(GL_PIXEL_UNPACK_BUFFER); pixmap->devPrivate.ptr = NULL; @@ -153,7 +168,7 @@ glamor_fini_pixmap(PixmapPtr pixmap) RegionUninit(&priv->prepare_region); - if (glamor_priv->has_rw_pbo) { + if (priv->pbo) { glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0); glDeleteBuffers(1, &priv->pbo); priv->pbo = 0; |