From 3b7810164f6d92d895a90a6f73f98e89fb88b0dd Mon Sep 17 00:00:00 2001 From: Zhigang Gong Date: Mon, 10 Feb 2014 11:06:24 +0800 Subject: [PATCH v2] Fallback to tex array or system memory when fail to allocate one big fbo. If the texture is very large, for example 8K*8K, it may fail to be allocated. If that is the case, we don't need to crash the xserver. We just need to fallback to a smaller block size or fallback to system memory. See the related bug at: https://bugs.freedesktop.org/show_bug.cgi?id=71190 Signed-off-by: Zhigang Gong --- src/glamor.c | 18 ++++++++++-------- src/glamor_fbo.c | 23 +++++++++++++++-------- 2 files changed, 25 insertions(+), 16 deletions(-) diff --git a/src/glamor.c b/src/glamor.c index 93d3c5e..4a2f5ad 100644 --- a/src/glamor.c +++ b/src/glamor.c @@ -134,7 +134,7 @@ glamor_create_pixmap(ScreenPtr screen, int w, int h, int depth, glamor_pixmap_private *pixmap_priv; glamor_screen_private *glamor_priv = glamor_get_screen_private(screen); - glamor_pixmap_fbo *fbo; + glamor_pixmap_fbo *fbo = NULL; int pitch; GLenum format; @@ -173,13 +173,13 @@ glamor_create_pixmap(ScreenPtr screen, int w, int h, int depth, if (type == GLAMOR_MEMORY_MAP || glamor_check_fbo_size(glamor_priv, w, h)) { pixmap_priv->type = type; fbo = glamor_create_fbo(glamor_priv, w, h, format, usage); - } - else { - DEBUGF("Create LARGE pixmap %p width %d height %d\n", pixmap, w, h); + } else { + int tile_size = glamor_priv->max_fbo_size; + DEBUGF("Create LARGE pixmap %p width %d height %d, tile size %d\n", pixmap, w, h, tile_size); pixmap_priv->type = GLAMOR_TEXTURE_LARGE; fbo = glamor_create_fbo_array(glamor_priv, w, h, format, usage, - glamor_priv->max_fbo_size, - glamor_priv->max_fbo_size, + tile_size, + tile_size, pixmap_priv); } @@ -589,7 +589,8 @@ glamor_dri3_fd_from_pixmap (ScreenPtr screen, { case GLAMOR_TEXTURE_DRM: case GLAMOR_TEXTURE_ONLY: - glamor_pixmap_ensure_fbo(pixmap, GL_RGBA, 0); + if (!glamor_pixmap_ensure_fbo(pixmap, GL_RGBA, 0)) + return -1; return glamor_egl_dri3_fd_name_from_tex(screen, pixmap, pixmap_priv->base.fbo->tex, @@ -615,7 +616,8 @@ glamor_dri3_name_from_pixmap (PixmapPtr pixmap) { case GLAMOR_TEXTURE_DRM: case GLAMOR_TEXTURE_ONLY: - glamor_pixmap_ensure_fbo(pixmap, GL_RGBA, 0); + if (!glamor_pixmap_ensure_fbo(pixmap, GL_RGBA, 0)) + return -1; return glamor_egl_dri3_fd_name_from_tex(pixmap->drawable.pScreen, pixmap, pixmap_priv->base.fbo->tex, diff --git a/src/glamor_fbo.c b/src/glamor_fbo.c index d1b087e..4cb2de9 100644 --- a/src/glamor_fbo.c +++ b/src/glamor_fbo.c @@ -169,16 +169,17 @@ glamor_pixmap_fbo_cache_put(glamor_pixmap_fbo *fbo) #endif } -static void +static int glamor_pixmap_ensure_fb(glamor_pixmap_fbo *fbo) { glamor_gl_dispatch *dispatch; - int status; + int status, err = 0; dispatch = glamor_get_dispatch(fbo->glamor_priv); if (fbo->fb == 0) dispatch->glGenFramebuffers(1, &fbo->fb); + assert(fbo->tex != 0); dispatch->glBindFramebuffer(GL_FRAMEBUFFER, fbo->fb); dispatch->glFramebufferTexture2D(GL_FRAMEBUFFER, @@ -211,11 +212,12 @@ glamor_pixmap_ensure_fb(glamor_pixmap_fbo *fbo) str = "unknown error"; break; } - - FatalError("destination is framebuffer incomplete: %s [%x]\n", - str, status); + LogMessage(X_WARNING, + "glamor: Failed to create fbo, %s\n", str); + err = -1; } glamor_put_dispatch(fbo->glamor_priv); + return err; } glamor_pixmap_fbo * @@ -244,8 +246,12 @@ glamor_create_fbo_from_tex(glamor_screen_private *glamor_priv, goto done; } - if (flag != GLAMOR_CREATE_FBO_NO_FBO) - glamor_pixmap_ensure_fb(fbo); + if (flag != GLAMOR_CREATE_FBO_NO_FBO) { + if (glamor_pixmap_ensure_fb(fbo) != 0) { + glamor_purge_fbo(fbo); + fbo = NULL; + } + } done: return fbo; @@ -570,7 +576,8 @@ glamor_pixmap_ensure_fbo(PixmapPtr pixmap, GLenum format, int flag) pixmap->drawable.height, format); if (flag != GLAMOR_CREATE_FBO_NO_FBO && pixmap_priv->base.fbo->fb == 0) - glamor_pixmap_ensure_fb(pixmap_priv->base.fbo); + if (glamor_pixmap_ensure_fb(pixmap_priv->base.fbo) != 0) + return FALSE; } return TRUE; -- 1.7.9.5