summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEric Anholt <eric@anholt.net>2015-11-09 09:36:35 -0800
committerEric Anholt <eric@anholt.net>2015-12-15 10:39:27 -0800
commit661bd478d3874ac4bb274ea0758003f07c2325e3 (patch)
treeba7a788019f5b4511b24ae314ed10251301db2a4
parente7040514b6b1f0fdbeaf25a09ba809301f3f3233 (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.c33
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(&region);
- 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;