[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