[Glamor] [PATCH v2 2/2] glamor: Avoid 1bpp pixmap uploading fallback for both GL/GLES.

zhigang.gong at linux.intel.com zhigang.gong at linux.intel.com
Wed Mar 28 06:09:45 PDT 2012


From: Zhigang Gong <zhigang.gong at linux.intel.com>

This commit fixed three things:

1. As OpenGL desktop version do support GL_BITMAP for 1bpp
pixmap, we add it back and don't need to fallback.

2. Fixed the fbo's texture format handling, especially for GLES2.
For GLES2, for a given depth the texture format may be GL_RGBA or
GL_BGRA. And thus we can't set the format by using
gl_iformat_for_depth. Change the prototype of glamor_create_fbo
and let the caller to determine which internal format it wants.

3. GLES2 doesn't support 1BPP texture uploading. We
use pixman to convert a 1BPP texels to 8BPP texels and then
upload it to a GL_ALPHA texture to avoid fallback the whole
rendering.

Due to the change of No.2 we can set a different format to a
fbo which is for the uploading purpose. The pixmap's format is
1BPP, but the fbo could be GL_ALPHA.

Signed-off-by: Zhigang Gong <zhigang.gong at linux.intel.com>
---
 src/glamor.c        |   12 ++++-
 src/glamor_fbo.c    |   15 +++----
 src/glamor_pixmap.c |  111 +++++++++++++++++++++++++++++++++++++++++---------
 src/glamor_priv.h   |    4 +-
 src/glamor_utils.h  |   18 ++++----
 5 files changed, 117 insertions(+), 43 deletions(-)

diff --git a/src/glamor.c b/src/glamor.c
index 532b9ef..8fc3b05 100644
--- a/src/glamor.c
+++ b/src/glamor.c
@@ -84,6 +84,7 @@ glamor_set_pixmap_texture(PixmapPtr pixmap, unsigned int tex)
 	glamor_pixmap_private *pixmap_priv;
 	glamor_screen_private *glamor_priv;
 	glamor_pixmap_fbo *fbo;
+	GLenum format;
 
 	glamor_priv = glamor_get_screen_private(screen);
 	pixmap_priv = glamor_get_pixmap_private(pixmap);
@@ -93,9 +94,10 @@ glamor_set_pixmap_texture(PixmapPtr pixmap, unsigned int tex)
 		glamor_destroy_fbo(fbo);
 	}
 
+	gl_iformat_for_depth(pixmap->drawable.depth, &format);
 	fbo = glamor_create_fbo_from_tex(glamor_priv, pixmap->drawable.width,
 					 pixmap->drawable.height,
-					 pixmap->drawable.depth, tex, 0);
+					 format, tex, 0);
 
 	if (fbo == NULL) {
 		ErrorF("XXX fail to create fbo.\n");
@@ -133,11 +135,14 @@ glamor_create_pixmap(ScreenPtr screen, int w, int h, int depth,
 	glamor_pixmap_fbo *fbo;
 	int pitch;
 	int flag;
+	GLenum format;
 
 	if (w > 32767 || h > 32767)
 		return NullPixmap;
 
-	if (usage == GLAMOR_CREATE_PIXMAP_CPU || (w == 0 && h == 0))
+	if (usage == GLAMOR_CREATE_PIXMAP_CPU
+	    || (w == 0 && h == 0)
+	    || !glamor_check_pixmap_fbo_depth(depth))
 		return fbCreatePixmap(screen, w, h, depth, usage);
 	else
 		pixmap = fbCreatePixmap(screen, 0, 0, depth, usage);
@@ -154,7 +159,8 @@ glamor_create_pixmap(ScreenPtr screen, int w, int h, int depth,
 	pixmap_priv->glamor_priv = glamor_priv;
 	pixmap_priv->type = type;
 
-	fbo = glamor_create_fbo(glamor_priv, w, h, depth, usage);
+	gl_iformat_for_depth(depth, &format);
+	fbo = glamor_create_fbo(glamor_priv, w, h, format, usage);
 
 	if (fbo == NULL) {
 		fbDestroyPixmap(pixmap);
diff --git a/src/glamor_fbo.c b/src/glamor_fbo.c
index d212bd4..4a7068f 100644
--- a/src/glamor_fbo.c
+++ b/src/glamor_fbo.c
@@ -170,17 +170,15 @@ glamor_pixmap_fbo_cache_put(glamor_pixmap_fbo *fbo)
 
 glamor_pixmap_fbo *
 glamor_create_fbo_from_tex(glamor_screen_private *glamor_priv,
-		  int w, int h, int depth, GLint tex, int flag)
+		  int w, int h, GLenum format, GLint tex, int flag)
 {
 	glamor_pixmap_fbo *fbo;
-	GLenum format;
 
 	fbo = calloc(1, sizeof(*fbo));
 	if (fbo == NULL)
 		return NULL;
 
 	xorg_list_init(&fbo->list);
-	gl_iformat_for_depth(depth, &format);
 
 	fbo->tex = tex;
 	fbo->width = w;
@@ -338,19 +336,18 @@ glamor_destroy_tex_obj(glamor_pixmap_fbo * tex_obj)
 
 glamor_pixmap_fbo *
 glamor_create_fbo(glamor_screen_private *glamor_priv,
-		  int w, int h, int depth, int flag)
+		  int w, int h,
+		  GLenum format,
+		  int flag)
 {
 	glamor_gl_dispatch *dispatch;
 	glamor_pixmap_fbo *fbo;
-	GLenum format;
 	GLint tex;
 	int cache_flag;
 
-	if (!glamor_check_fbo_size(glamor_priv, w, h)
-	    || !glamor_check_fbo_depth(depth))
+	if (!glamor_check_fbo_size(glamor_priv, w, h))
 		return NULL;
 
-	gl_iformat_for_depth(depth, &format);
 	if (flag == GLAMOR_CREATE_FBO_NO_FBO)
 		goto new_fbo;
 
@@ -374,7 +371,7 @@ new_fbo:
 	dispatch->glTexImage2D(GL_TEXTURE_2D, 0, format, w, h, 0, format,
 			       GL_UNSIGNED_BYTE, NULL);
 
-	fbo = glamor_create_fbo_from_tex(glamor_priv, w, h, depth, tex, flag);
+	fbo = glamor_create_fbo_from_tex(glamor_priv, w, h, format, tex, flag);
 	glamor_put_dispatch(glamor_priv);
 
 	return fbo;
diff --git a/src/glamor_pixmap.c b/src/glamor_pixmap.c
index 7f4a90b..808e527 100644
--- a/src/glamor_pixmap.c
+++ b/src/glamor_pixmap.c
@@ -211,10 +211,10 @@ glamor_set_alu(struct glamor_gl_dispatch *dispatch, unsigned char alu)
  * Upload pixmap to a specified texture.
  * This texture may not be the one attached to it.
  **/
-int in_restore = 0;
 static void
 __glamor_upload_pixmap_to_texture(PixmapPtr pixmap, GLenum format,
-				  GLenum type, GLuint tex, int sub)
+				  GLenum type, GLuint tex, int sub,
+				  void *bits)
 {
 	glamor_pixmap_private *pixmap_priv =
 	    glamor_get_pixmap_private(pixmap);
@@ -222,7 +222,6 @@ __glamor_upload_pixmap_to_texture(PixmapPtr pixmap, GLenum format,
 	    glamor_get_screen_private(pixmap->drawable.pScreen);
 	glamor_gl_dispatch *dispatch;
 	unsigned int stride, row_length;
-	void *texels;
 	GLenum iformat;
 
 	if (glamor_priv->gl_flavor == GLAMOR_GL_ES2)
@@ -247,32 +246,78 @@ __glamor_upload_pixmap_to_texture(PixmapPtr pixmap, GLenum format,
 		dispatch->glPixelStorei(GL_UNPACK_ALIGNMENT, 4);
 	}
 
-	if (pixmap_priv->fbo->pbo && pixmap_priv->fbo->pbo_valid) {
-		texels = NULL;
+	if (bits == NULL)
 		dispatch->glBindBuffer(GL_PIXEL_UNPACK_BUFFER,
 				       pixmap_priv->fbo->pbo);
-	} else
-		texels = pixmap->devPrivate.ptr;
 
 	if (sub)
 		dispatch->glTexSubImage2D(GL_TEXTURE_2D,
 				       0,0,0,
 				       pixmap->drawable.width,
 				       pixmap->drawable.height, format, type,
-				       texels);
+				       bits);
 	else
 		dispatch->glTexImage2D(GL_TEXTURE_2D,
 				       0,
 				       iformat,
 				       pixmap->drawable.width,
 				       pixmap->drawable.height, 0, format, type,
-				       texels);
+				       bits);
 
-	if (pixmap_priv->fbo->pbo && pixmap_priv->fbo->pbo_valid)
+	if (bits == NULL)
 		dispatch->glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0);
 	glamor_put_dispatch(glamor_priv);
 }
 
+/*
+ * The only possible format is GL_ALPHA currently.
+ * For the bpp larger than 8, they should be supported by uploaded directly.
+ * Only for 1bpp texture on GLES2, we need to convert it to PICT_a8.
+ * For the other possible unsupported color format which is less than 8bpp,
+ * we may also convert it to PICT_a8 here.
+ */
+
+static pixman_image_t *
+glamor_convert_pixmap_to_image(PixmapPtr pixmap, GLenum format, GLenum type)
+{
+	pixman_image_t *dst_image;
+	pixman_image_t *src_image;
+	PictFormatShort dst_format, src_format;
+
+	if (format == GL_ALPHA)
+		dst_format = PICT_a8;
+	else
+		return NULL;
+
+	src_format = format_for_pixmap(pixmap);
+
+	dst_image = pixman_image_create_bits(dst_format,
+					     pixmap->drawable.width,
+					     pixmap->drawable.height,
+					     NULL,
+					     0);
+	if (dst_image == NULL)
+		return NULL;
+
+	src_image = pixman_image_create_bits(src_format,
+					     pixmap->drawable.width,
+					     pixmap->drawable.height,
+					     pixmap->devPrivate.ptr,
+					     pixmap->devKind);
+	if (src_image == NULL) {
+		pixman_image_unref(src_image);
+		return NULL;
+	}
+
+	pixman_image_composite(PictOpSrc, src_image, NULL, dst_image,
+			       0, 0, 0, 0, 0, 0,
+			       pixmap->drawable.width,
+			       pixmap->drawable.height);
+
+	pixman_image_unref(src_image);
+
+	return dst_image;
+}
 
 /* 
  * Load texture from the pixmap's data pointer and then
@@ -305,6 +350,8 @@ _glamor_upload_pixmap_to_texture(PixmapPtr pixmap, GLenum format,
 	float dst_xscale, dst_yscale;
 	GLuint tex;
 	int need_flip;
+	void *bits;
+	pixman_image_t *image = NULL;
 
 	if (!pixmap_priv)
 		return;
@@ -317,12 +364,27 @@ _glamor_upload_pixmap_to_texture(PixmapPtr pixmap, GLenum format,
 			    pixmap->drawable.height,
 			    pixmap->drawable.depth);
 
+	if (pixmap_priv->fbo->pbo && pixmap_priv->fbo->pbo_valid)
+		bits = NULL;
+	else {
+		if (glamor_priv->gl_flavor == GLAMOR_GL_DESKTOP
+		    || pixmap->drawable.depth >= 8)
+			bits = pixmap->devPrivate.ptr;
+		else {
+			image = glamor_convert_pixmap_to_image(pixmap, format, type);
+			bits = pixman_image_get_data(image);
+		}
+	}
+
 	/* Try fast path firstly, upload the pixmap to the texture attached
 	 * to the fbo directly. */
-	if (no_alpha == 0 && no_revert == 1 && !need_flip) {
+	if (no_alpha == 0
+	    && no_revert == 1
+	    && !need_flip) {
 		__glamor_upload_pixmap_to_texture(pixmap, format, type,
-						  pixmap_priv->fbo->tex, 1);
-		return;
+						  pixmap_priv->fbo->tex, 1,
+						  bits);
+		goto clean_image;
 	}
 
 	if (need_flip)
@@ -352,7 +414,7 @@ _glamor_upload_pixmap_to_texture(PixmapPtr pixmap, GLenum format,
 	glamor_set_destination_pixmap_priv_nc(pixmap_priv);
 	dispatch->glGenTextures(1, &tex);
 
-	__glamor_upload_pixmap_to_texture(pixmap, format, type, tex, 0);
+	__glamor_upload_pixmap_to_texture(pixmap, format, type, tex, 0, bits);
 	dispatch->glActiveTexture(GL_TEXTURE0);
 	dispatch->glBindTexture(GL_TEXTURE_2D, tex);
 
@@ -382,6 +444,10 @@ _glamor_upload_pixmap_to_texture(PixmapPtr pixmap, GLenum format,
 	dispatch->glBindFramebuffer(GL_FRAMEBUFFER, 0);
 
 	glamor_put_dispatch(glamor_priv);
+
+clean_image:
+	if (image != NULL)
+		pixman_image_unref(image);
 }
 
 void
@@ -439,15 +505,17 @@ glamor_pixmap_ensure_fb(glamor_pixmap_fbo *fbo)
  * Two condtion need to setup a fbo for a pixmap
  * 1. !yInverted, we need to do flip if we are not yInverted.
  * 2. no_alpha != 0, we need to wire the alpha.
+ * Input parameter format is not internal texture format it's the format
+ * of texels data.
  * */
 static int
-glamor_pixmap_upload_prepare(PixmapPtr pixmap, int no_alpha, int no_revert)
+glamor_pixmap_upload_prepare(PixmapPtr pixmap, GLenum format, int no_alpha, int no_revert)
 {
 	int flag;
 	glamor_pixmap_private *pixmap_priv;
 	glamor_screen_private *glamor_priv;
-	GLenum format;
 	glamor_pixmap_fbo *fbo;
+	GLenum iformat;
 
 	pixmap_priv = glamor_get_pixmap_private(pixmap);
 	glamor_priv = glamor_get_screen_private(pixmap->drawable.pScreen);
@@ -464,9 +532,14 @@ glamor_pixmap_upload_prepare(PixmapPtr pixmap, int no_alpha, int no_revert)
 		flag = 0;
 	}
 
+	if (glamor_priv->gl_flavor == GLAMOR_GL_DESKTOP)
+		gl_iformat_for_depth(pixmap->drawable.depth, &iformat);
+	else
+		iformat = format;
+
 	fbo = glamor_create_fbo(glamor_priv, pixmap->drawable.width,
 				pixmap->drawable.height,
-				pixmap->drawable.depth,
+				iformat,
 				flag);
 	if (fbo == NULL) {
 		glamor_fallback
@@ -495,7 +568,7 @@ glamor_upload_pixmap_to_texture(PixmapPtr pixmap)
 				pixmap->drawable.depth);
 		return GLAMOR_UPLOAD_FAILED;
 	}
-	if (glamor_pixmap_upload_prepare(pixmap, no_alpha, no_revert))
+	if (glamor_pixmap_upload_prepare(pixmap, format, no_alpha, no_revert))
 		return GLAMOR_UPLOAD_FAILED;
 	_glamor_upload_pixmap_to_texture(pixmap, format, type, no_alpha,
 					 no_revert, 1);
@@ -534,10 +607,8 @@ glamor_restore_pixmap_to_texture(PixmapPtr pixmap)
 		assert(0);
 	}
 
-	in_restore = 1;
 	_glamor_upload_pixmap_to_texture(pixmap, format, type, no_alpha,
 					 no_revert, 1);
-	in_restore = 0;
 }
 
 /* 
diff --git a/src/glamor_priv.h b/src/glamor_priv.h
index ad68737..227c407 100644
--- a/src/glamor_priv.h
+++ b/src/glamor_priv.h
@@ -395,9 +395,9 @@ Bool glamor_destroy_pixmap(PixmapPtr pixmap);
 glamor_pixmap_fbo* glamor_pixmap_detach_fbo(glamor_pixmap_private *pixmap_priv);
 void glamor_pixmap_attach_fbo(PixmapPtr pixmap, glamor_pixmap_fbo *fbo);
 glamor_pixmap_fbo * glamor_create_fbo_from_tex(glamor_screen_private *glamor_priv,
-					       int w, int h, int depth, GLint tex, int flag);
+					       int w, int h, GLenum format, GLint tex, int flag);
 glamor_pixmap_fbo * glamor_create_fbo(glamor_screen_private *glamor_priv,
-				      int w, int h, int depth, int flag);
+				      int w, int h, GLenum format, int flag);
 void glamor_destroy_fbo(glamor_pixmap_fbo *fbo);
 void glamor_purge_fbo(glamor_pixmap_fbo *fbo);
 
diff --git a/src/glamor_utils.h b/src/glamor_utils.h
index 75ebc7e..252f34c 100644
--- a/src/glamor_utils.h
+++ b/src/glamor_utils.h
@@ -194,13 +194,14 @@ glamor_transform_boxes(BoxPtr boxes, int nbox, int dx, int dy)
                                                     && (_w_) < _glamor_->max_fbo_size  \
                                                     && (_h_) < _glamor_->max_fbo_size)
 
-#define glamor_check_fbo_depth(_depth_) (			\
-                                         _depth_ == 8		\
-	                                 || _depth_ == 15	\
-                                         || _depth_ == 16	\
-                                         || _depth_ == 24	\
-                                         || _depth_ == 30	\
-                                         || _depth_ == 32)
+/* For 1bpp pixmap, we don't store it as texture. */
+#define glamor_check_pixmap_fbo_depth(_depth_) (			\
+						_depth_ == 8		\
+						|| _depth_ == 15	\
+						|| _depth_ == 16	\
+						|| _depth_ == 24	\
+						|| _depth_ == 30	\
+						|| _depth_ == 32)
 
 
 #define GLAMOR_PIXMAP_PRIV_IS_PICTURE(pixmap_priv) (pixmap_priv && pixmap_priv->is_picture == 1)
@@ -464,6 +465,7 @@ glamor_get_tex_format_type_from_pictformat(PictFormatShort format,
 		*no_revert = TRUE;
 		break;
 
+	case PICT_a1:
 	case PICT_a8:
 		*tex_format = GL_ALPHA;
 		*tex_type = GL_UNSIGNED_BYTE;
@@ -498,7 +500,6 @@ glamor_get_tex_format_type_from_pictformat(PictFormatShort format,
 
 #endif
 
-
 static inline int
 glamor_get_tex_format_type_from_pixmap(PixmapPtr pixmap,
 				       GLenum * format,
@@ -520,7 +521,6 @@ glamor_get_tex_format_type_from_pixmap(PixmapPtr pixmap,
 							  no_revert);
 }
 
-
 /* borrowed from uxa */
 static inline Bool
 glamor_get_rgba_from_pixel(CARD32 pixel,
-- 
1.7.4.4



More information about the Glamor mailing list