From 9c6fd931a63fb8a5300014265e4f1cacc746857a Mon Sep 17 00:00:00 2001 From: Zhigang Gong Date: Fri, 20 Jan 2012 09:59:44 +0800 Subject: [PATCH] glamor-fbo-pool: Enable to reuse different size fbo/texture. Fixup three special cases, one is in tile and the other is in composite. Both cases are due to repeat texture issue. Maybe we can refine the shader to recalculate texture coords to support partial texture's repeating. The third is when upload a memory pixmap to texture, as now the texture may not have the exact size as the pixmap, we should not use the full rect coords. Signed-off-by: Zhigang Gong --- glamor/glamor.c | 2 +- glamor/glamor_fbo.c | 4 +- glamor/glamor_pixmap.c | 105 ++++++++++++++++++++++++++++++++++------- glamor/glamor_priv.h | 4 ++ glamor/glamor_render.c | 34 ++++++++++++- glamor/glamor_tile.c | 11 +++++ 6 files changed, 140 insertions(+), 20 deletions(-) diff --git a/glamor/glamor.c b/glamor/glamor.c index 9b9d82304..6e843f437 100644 --- a/glamor/glamor.c +++ b/glamor/glamor.c @@ -164,7 +164,7 @@ glamor_create_pixmap(ScreenPtr screen, int w, int h, int depth, if (w == 0 || h == 0) return pixmap; - fbo = glamor_create_fbo(glamor_priv, w, h, depth, 0); + fbo = glamor_create_fbo(glamor_priv, w, h, depth, usage); if (fbo == NULL) { fbDestroyPixmap(pixmap); diff --git a/glamor/glamor_fbo.c b/glamor/glamor_fbo.c index 97ba33c1c..9b6a05ef0 100644 --- a/glamor/glamor_fbo.c +++ b/glamor/glamor_fbo.c @@ -90,7 +90,7 @@ glamor_pixmap_fbo_cache_get(glamor_screen_private *glamor_priv, [cache_hbucket(h)]; if (flag != GLAMOR_CACHE_EXACT_SIZE) { list_for_each_entry(fbo_entry, cache, list) { - if (fbo_entry->width == w && fbo_entry->height == h) { + if (fbo_entry->width >= w && fbo_entry->height >= h) { DEBUGF("Request w %d h %d \n", w, h); DEBUGF("got cache entry %p w %d h %d fbo %d tex %d\n", @@ -263,7 +263,7 @@ glamor_create_fbo(glamor_screen_private *glamor_priv, gl_iformat_for_depth(depth, &format); fbo = glamor_pixmap_fbo_cache_get(glamor_priv, w, h, - format, GLAMOR_CACHE_EXACT_SIZE); + format, cache_flag); if (fbo) return fbo; diff --git a/glamor/glamor_pixmap.c b/glamor/glamor_pixmap.c index f001962e7..2020e2145 100644 --- a/glamor/glamor_pixmap.c +++ b/glamor/glamor_pixmap.c @@ -216,7 +216,7 @@ glamor_set_alu(struct glamor_gl_dispatch *dispatch, unsigned char alu) int in_restore = 0; static void __glamor_upload_pixmap_to_texture(PixmapPtr pixmap, GLenum format, - GLenum type, GLuint tex) + GLenum type, GLuint tex, int sub) { glamor_pixmap_private *pixmap_priv = glamor_get_pixmap_private(pixmap); @@ -255,12 +255,19 @@ __glamor_upload_pixmap_to_texture(PixmapPtr pixmap, GLenum format, } else texels = pixmap->devPrivate.ptr; - dispatch->glTexImage2D(GL_TEXTURE_2D, - 0, - iformat, - pixmap->drawable.width, - pixmap->drawable.height, 0, format, type, - texels); + if (sub) + dispatch->glTexSubImage2D(GL_TEXTURE_2D, + 0,0,0, + pixmap->drawable.width, + pixmap->drawable.height, format, type, + texels); + else + dispatch->glTexImage2D(GL_TEXTURE_2D, + 0, + iformat, + pixmap->drawable.width, + pixmap->drawable.height, 0, format, type, + texels); } @@ -280,11 +287,7 @@ _glamor_upload_pixmap_to_texture(PixmapPtr pixmap, GLenum format, glamor_screen_private *glamor_priv = glamor_get_screen_private(pixmap->drawable.pScreen); glamor_gl_dispatch *dispatch = &glamor_priv->dispatch; - static float vertices[8] = { -1, -1, - 1, -1, - 1, 1, - -1, 1 - }; + static float vertices[8]; static float texcoords[8] = { 0, 1, 1, 1, 1, 0, @@ -296,7 +299,7 @@ _glamor_upload_pixmap_to_texture(PixmapPtr pixmap, GLenum format, 0, 1 }; float *ptexcoords; - + float dst_xscale, dst_yscale; GLuint tex; int need_flip; @@ -315,16 +318,23 @@ _glamor_upload_pixmap_to_texture(PixmapPtr pixmap, GLenum format, * to the fbo directly. */ if (no_alpha == 0 && no_revert == 1 && !need_flip) { __glamor_upload_pixmap_to_texture(pixmap, format, type, - pixmap_priv->fbo->tex); + pixmap_priv->fbo->tex, 1); return; } - if (need_flip) ptexcoords = texcoords; else ptexcoords = texcoords_inv; + pixmap_priv_get_scale(pixmap_priv, &dst_xscale, &dst_yscale); + glamor_set_normalize_vcoords(dst_xscale, + dst_yscale, + 0, 0, + pixmap->drawable.width, pixmap->drawable.height, + glamor_priv->yInverted, + vertices); + /* Slow path, we need to flip y or wire alpha to 1. */ dispatch->glVertexAttribPointer(GLAMOR_VERTEX_POS, 2, GL_FLOAT, GL_FALSE, 2 * sizeof(float), @@ -338,7 +348,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); + __glamor_upload_pixmap_to_texture(pixmap, format, type, tex, 0); dispatch->glActiveTexture(GL_TEXTURE0); dispatch->glBindTexture(GL_TEXTURE_2D, tex); @@ -791,3 +801,66 @@ glamor_download_pixmap_to_cpu(PixmapPtr pixmap, glamor_access_t access) return TRUE; } + +/* fixup a fbo to the exact size as the pixmap. */ +Bool +glamor_fixup_pixmap_priv(ScreenPtr screen, glamor_pixmap_private *pixmap_priv) +{ + glamor_screen_private *glamor_priv; + glamor_pixmap_fbo *old_fbo; + glamor_pixmap_fbo *new_fbo = NULL; + PixmapPtr scratch = NULL; + glamor_pixmap_private *scratch_priv; + DrawablePtr drawable; + GCPtr gc = NULL; + int ret = FALSE; + + drawable = &pixmap_priv->container->drawable; + + if (pixmap_priv->container->drawable.width == pixmap_priv->fbo->width + && pixmap_priv->container->drawable.height == pixmap_priv->fbo->height) + return TRUE; + + old_fbo = pixmap_priv->fbo; + glamor_priv = pixmap_priv->glamor_priv; + + if (!old_fbo) + return FALSE; + + gc = GetScratchGC(drawable->depth, screen); + if (!gc) + goto fail; + + scratch = glamor_create_pixmap(screen, drawable->width, drawable->height, + drawable->depth, + GLAMOR_CREATE_PIXMAP_FIXUP); + + scratch_priv = glamor_get_pixmap_private(scratch); + + if (!scratch_priv || !scratch_priv->fbo) + goto fail; + + ValidateGC(&scratch->drawable, gc); + glamor_copy_area(drawable, + &scratch->drawable, + gc, 0, 0, + drawable->width, drawable->height, + 0, 0); + old_fbo = glamor_pixmap_detach_fbo(pixmap_priv); + new_fbo = glamor_pixmap_detach_fbo(scratch_priv); + glamor_pixmap_attach_fbo(pixmap_priv->container, new_fbo); + glamor_pixmap_attach_fbo(scratch, old_fbo); + + DEBUGF("old %dx%d type %d\n", + drawable->width, drawable->height, pixmap_priv->type); + DEBUGF("copy tex %d %dx%d to tex %d %dx%d \n", + old_fbo->tex, old_fbo->width, old_fbo->height, new_fbo->tex, new_fbo->width, new_fbo->height); + ret = TRUE; +fail: + if (gc) + FreeScratchGC(gc); + if (scratch) + glamor_destroy_pixmap(scratch); + + return ret; +} diff --git a/glamor/glamor_priv.h b/glamor/glamor_priv.h index 31f9c93ca..66e47c662 100644 --- a/glamor/glamor_priv.h +++ b/glamor/glamor_priv.h @@ -594,6 +594,10 @@ void glamor_destroy_picture(PicturePtr picture); enum glamor_pixmap_status glamor_upload_picture_to_texture(PicturePtr picture); +/* fixup a fbo to the exact size as the pixmap. */ +Bool +glamor_fixup_pixmap_priv(ScreenPtr screen, glamor_pixmap_private *pixmap_priv); + void glamor_picture_format_fixup(PicturePtr picture, glamor_pixmap_private * pixmap_priv); diff --git a/glamor/glamor_render.c b/glamor/glamor_render.c index 19ed22e55..03f7e3207 100644 --- a/glamor/glamor_render.c +++ b/glamor/glamor_render.c @@ -342,7 +342,6 @@ glamor_fini_composite_shaders(ScreenPtr screen) dispatch->glDeleteBuffers(1, &glamor_priv->vbo); dispatch->glDeleteBuffers(1, &glamor_priv->ebo); - for(i = 0; i < SHADER_SOURCE_COUNT; i++) for(j = 0; j < SHADER_MASK_COUNT; j++) for(k = 0; k < SHADER_IN_COUNT; k++) @@ -408,6 +407,33 @@ glamor_set_composite_op(ScreenPtr screen, return TRUE; } +static void +glamor_composite_texture_fixup(ScreenPtr screen, + PicturePtr picture, + glamor_pixmap_private * pixmap_priv) +{ + glamor_screen_private *glamor_priv = + glamor_get_screen_private(screen); + glamor_gl_dispatch *dispatch = &glamor_priv->dispatch; + Bool has_repeat; + int width, height; + + if (picture->repeatType == RepeatNone) + has_repeat = FALSE; + else + has_repeat = TRUE; + + if (has_repeat + && ( (pixmap_priv->container->drawable.width != pixmap_priv->fbo->width) + || (pixmap_priv->container->drawable.height != pixmap_priv->fbo->height))) { + /* Currently, we can't support repeat on partial texture, now redirect it + * to an exact size fbo. */ + DEBUGF("prepare to fixup texture \n"); + if (!glamor_fixup_pixmap_priv(screen, pixmap_priv)) + ErrorF("Failed to fixup a unmatch size of repeat picture. \n"); + } +} + static void glamor_set_composite_texture(ScreenPtr screen, int unit, PicturePtr picture, @@ -979,6 +1005,12 @@ glamor_composite_with_shader(CARD8 op, } } #endif + + if (key.source != SHADER_SOURCE_SOLID) + glamor_composite_texture_fixup(screen, source, source_pixmap_priv); + if (key.mask != SHADER_MASK_NONE && key.mask != SHADER_MASK_SOLID) + glamor_composite_texture_fixup(screen, mask, mask_pixmap_priv); + glamor_set_destination_pixmap_priv_nc(dest_pixmap_priv); glamor_validate_pixmap(dest_pixmap); if (!glamor_set_composite_op(screen, op, dest, mask)) { diff --git a/glamor/glamor_tile.c b/glamor/glamor_tile.c index 7e0e6acb3..4ff4fa15f 100644 --- a/glamor/glamor_tile.c +++ b/glamor/glamor_tile.c @@ -127,8 +127,10 @@ glamor_tile(PixmapPtr pixmap, PixmapPtr tile, if (((tile_x != 0) && (tile_x + width > tile->drawable.width)) || ((tile_y != 0) && (tile_y + height > tile->drawable.height))) { + /* XXX We can recreate a new pixmap here to avoid partial tiling. */ goto fail; } + if (glamor_priv->tile_prog == 0) { glamor_fallback("Tiling unsupported\n"); goto fail; @@ -148,6 +150,15 @@ glamor_tile(PixmapPtr pixmap, PixmapPtr tile, glamor_fallback("unsupported planemask %lx\n", planemask); goto fail; } + + if (src_pixmap_priv->fbo->width != tile->drawable.width + || src_pixmap_priv->fbo->height != tile->drawable.height) { + if (!glamor_fixup_pixmap_priv(screen, src_pixmap_priv)) { + glamor_fallback("Failed to create a fixup pixmap for partial tiling. \n"); + goto fail; + } + } + if (alu != GXcopy) { glamor_set_destination_pixmap_priv_nc(src_pixmap_priv); glamor_validate_pixmap(tile);