From f871d174a861e7c3d2b8f4d9a3f10c38a5120606 Mon Sep 17 00:00:00 2001 From: Zhigang Gong Date: Thu, 19 May 2011 11:40:38 +0800 Subject: [PATCH] glamor: Switch to software fb for too large pixmap. If pixmap's size exceeds the limitation of the MESA library, the rendering will fail. So we switch to software fb if it is the case. Add one new element for pixmap private structure to indicate whehter we are a software fb type or a opengl type. --- glamor/glamor.c | 26 +++++++++++++++++++------- glamor/glamor_priv.h | 18 ++++++++++++++++-- 2 files changed, 35 insertions(+), 9 deletions(-) diff --git a/glamor/glamor.c b/glamor/glamor.c index 66a694ec9..4594f145c 100644 --- a/glamor/glamor.c +++ b/glamor/glamor.c @@ -95,12 +95,24 @@ glamor_create_pixmap(ScreenPtr screen, int w, int h, int depth, PixmapPtr pixmap; GLenum format; GLuint tex; - + glamor_pixmap_private *pixmap_priv; + int type = GLAMOR_GL; if (w > 32767 || h > 32767) return NullPixmap; - pixmap = fbCreatePixmap (screen, 0, 0, depth, usage); + if (w > MAX_WIDTH || h > MAX_HEIGHT) { + /* MESA can only support upto MAX_WIDTH*MAX_HEIGHT fbo. + If we exceed such limitation, we have to use framebuffer.*/ + type = GLAMOR_FB; + pixmap = fbCreatePixmap (screen, w, h, depth, usage); + screen->ModifyPixmapHeader(pixmap, w, h, 0, 0, + (((w * pixmap->drawable.bitsPerPixel + + 7) / 8) + 3) & ~3, + NULL); + ErrorF("fallback to software fb for pixmap %p , %d x %d \n", pixmap, w, h); + } else + pixmap = fbCreatePixmap (screen, 0, 0, depth, usage); if (dixAllocatePrivates(&pixmap->devPrivates, PRIVATE_PIXMAP) != TRUE) { fbDestroyPixmap(pixmap); @@ -108,8 +120,12 @@ glamor_create_pixmap(ScreenPtr screen, int w, int h, int depth, return NullPixmap; } - if (w == 0 || h == 0) + if (w == 0 || h == 0 || type != GLAMOR_GL) return pixmap; + + pixmap_priv = glamor_get_pixmap_private(pixmap); + pixmap_priv->type = type; + /* We should probably take advantage of ARB_fbo's allowance of GL_ALPHA. * FBOs, which EXT_fbo forgot to do. */ @@ -122,7 +138,6 @@ glamor_create_pixmap(ScreenPtr screen, int w, int h, int depth, break; } - /* Create the texture used to store the pixmap's data. */ glGenTextures(1, &tex); glBindTexture(GL_TEXTURE_2D, tex); @@ -132,7 +147,6 @@ glamor_create_pixmap(ScreenPtr screen, int w, int h, int depth, format, GL_UNSIGNED_BYTE, NULL); glamor_set_pixmap_texture(pixmap, w, h, tex); - return pixmap; } @@ -141,7 +155,6 @@ glamor_destroy_pixmap(PixmapPtr pixmap) { if (pixmap->refcnt == 1) { glamor_pixmap_private *pixmap_priv = glamor_get_pixmap_private(pixmap); - glDeleteFramebuffersEXT(1, &pixmap_priv->fb); glDeleteTextures(1, &pixmap_priv->tex); } @@ -285,7 +298,6 @@ glamor_close_screen(int idx, ScreenPtr screen) #ifdef RENDER PictureScreenPtr ps = GetPictureScreenIfSet(screen); #endif - glamor_glyphs_fini(screen); screen->CloseScreen = glamor_priv->saved_close_screen; screen->CreateGC = glamor_priv->saved_create_gc; diff --git a/glamor/glamor_priv.h b/glamor/glamor_priv.h index b98907837..93837e0b7 100644 --- a/glamor/glamor_priv.h +++ b/glamor/glamor_priv.h @@ -39,6 +39,14 @@ #include "glyphstr.h" #endif +#ifndef MAX_WIDTH +#define MAX_WIDTH 4096 +#endif + +#ifndef MAX_HEIGHT +#define MAX_HEIGHT 4096 +#endif + typedef enum glamor_access { GLAMOR_ACCESS_RO, GLAMOR_ACCESS_RW, @@ -175,10 +183,16 @@ typedef struct glamor_screen_private { glamor_glyph_cache_t glyph_caches[GLAMOR_NUM_GLYPH_CACHES]; } glamor_screen_private; +enum glamor_pixmap_type { + GLAMOR_GL, + GLAMOR_FB +}; + typedef struct glamor_pixmap_private { GLuint tex; GLuint fb; GLuint pbo; + enum glamor_pixmap_type type; } glamor_pixmap_private; extern DevPrivateKey glamor_screen_private_key; @@ -250,8 +264,8 @@ glamor_report_delayed_fallbacks(ScreenPtr screen) glamor_screen_private *glamor_priv = glamor_get_screen_private(screen); if (glamor_priv->delayed_fallback_string) { - LogMessageVerb(X_INFO, 0, "fallback: %s", - glamor_priv->delayed_fallback_string); + // LogMessageVerb(X_INFO, 0, "fallback: %s", + // glamor_priv->delayed_fallback_string); glamor_clear_delayed_fallbacks(screen); } }