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.
This commit is contained in:
Zhigang Gong 2011-05-19 11:40:38 +08:00
parent 74ca45e7d0
commit f871d174a8
2 changed files with 35 additions and 9 deletions

View File

@ -95,11 +95,23 @@ glamor_create_pixmap(ScreenPtr screen, int w, int h, int depth,
PixmapPtr pixmap; PixmapPtr pixmap;
GLenum format; GLenum format;
GLuint tex; GLuint tex;
glamor_pixmap_private *pixmap_priv;
int type = GLAMOR_GL;
if (w > 32767 || h > 32767) if (w > 32767 || h > 32767)
return NullPixmap; return NullPixmap;
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); pixmap = fbCreatePixmap (screen, 0, 0, depth, usage);
if (dixAllocatePrivates(&pixmap->devPrivates, PRIVATE_PIXMAP) != TRUE) { if (dixAllocatePrivates(&pixmap->devPrivates, PRIVATE_PIXMAP) != TRUE) {
@ -108,8 +120,12 @@ glamor_create_pixmap(ScreenPtr screen, int w, int h, int depth,
return NullPixmap; return NullPixmap;
} }
if (w == 0 || h == 0) if (w == 0 || h == 0 || type != GLAMOR_GL)
return pixmap; 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. /* We should probably take advantage of ARB_fbo's allowance of GL_ALPHA.
* FBOs, which EXT_fbo forgot to do. * FBOs, which EXT_fbo forgot to do.
*/ */
@ -122,7 +138,6 @@ glamor_create_pixmap(ScreenPtr screen, int w, int h, int depth,
break; break;
} }
/* Create the texture used to store the pixmap's data. */ /* Create the texture used to store the pixmap's data. */
glGenTextures(1, &tex); glGenTextures(1, &tex);
glBindTexture(GL_TEXTURE_2D, 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); format, GL_UNSIGNED_BYTE, NULL);
glamor_set_pixmap_texture(pixmap, w, h, tex); glamor_set_pixmap_texture(pixmap, w, h, tex);
return pixmap; return pixmap;
} }
@ -141,7 +155,6 @@ glamor_destroy_pixmap(PixmapPtr pixmap)
{ {
if (pixmap->refcnt == 1) { if (pixmap->refcnt == 1) {
glamor_pixmap_private *pixmap_priv = glamor_get_pixmap_private(pixmap); glamor_pixmap_private *pixmap_priv = glamor_get_pixmap_private(pixmap);
glDeleteFramebuffersEXT(1, &pixmap_priv->fb); glDeleteFramebuffersEXT(1, &pixmap_priv->fb);
glDeleteTextures(1, &pixmap_priv->tex); glDeleteTextures(1, &pixmap_priv->tex);
} }
@ -285,7 +298,6 @@ glamor_close_screen(int idx, ScreenPtr screen)
#ifdef RENDER #ifdef RENDER
PictureScreenPtr ps = GetPictureScreenIfSet(screen); PictureScreenPtr ps = GetPictureScreenIfSet(screen);
#endif #endif
glamor_glyphs_fini(screen); glamor_glyphs_fini(screen);
screen->CloseScreen = glamor_priv->saved_close_screen; screen->CloseScreen = glamor_priv->saved_close_screen;
screen->CreateGC = glamor_priv->saved_create_gc; screen->CreateGC = glamor_priv->saved_create_gc;

View File

@ -39,6 +39,14 @@
#include "glyphstr.h" #include "glyphstr.h"
#endif #endif
#ifndef MAX_WIDTH
#define MAX_WIDTH 4096
#endif
#ifndef MAX_HEIGHT
#define MAX_HEIGHT 4096
#endif
typedef enum glamor_access { typedef enum glamor_access {
GLAMOR_ACCESS_RO, GLAMOR_ACCESS_RO,
GLAMOR_ACCESS_RW, GLAMOR_ACCESS_RW,
@ -175,10 +183,16 @@ typedef struct glamor_screen_private {
glamor_glyph_cache_t glyph_caches[GLAMOR_NUM_GLYPH_CACHES]; glamor_glyph_cache_t glyph_caches[GLAMOR_NUM_GLYPH_CACHES];
} glamor_screen_private; } glamor_screen_private;
enum glamor_pixmap_type {
GLAMOR_GL,
GLAMOR_FB
};
typedef struct glamor_pixmap_private { typedef struct glamor_pixmap_private {
GLuint tex; GLuint tex;
GLuint fb; GLuint fb;
GLuint pbo; GLuint pbo;
enum glamor_pixmap_type type;
} glamor_pixmap_private; } glamor_pixmap_private;
extern DevPrivateKey glamor_screen_private_key; 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); glamor_screen_private *glamor_priv = glamor_get_screen_private(screen);
if (glamor_priv->delayed_fallback_string) { if (glamor_priv->delayed_fallback_string) {
LogMessageVerb(X_INFO, 0, "fallback: %s", // LogMessageVerb(X_INFO, 0, "fallback: %s",
glamor_priv->delayed_fallback_string); // glamor_priv->delayed_fallback_string);
glamor_clear_delayed_fallbacks(screen); glamor_clear_delayed_fallbacks(screen);
} }
} }