From 1dca5d7b91ed6fced34f389453678407bc223e9c Mon Sep 17 00:00:00 2001 From: Zhigang Gong Date: Thu, 30 Jun 2011 16:04:59 +0800 Subject: [PATCH] glamor: Reduce source pixmap's size. If the dest pixmap is in texture memory, but source pixmap is not. Then we need to upload the source pixmap to texture memory. Previous version will upload the whole source pixmap. This commit preprocess the source pixmap, and reduce it to a smaller tempory pixmap only contains the required region. Signed-off-by: Zhigang Gong --- glamor/glamor_copyarea.c | 60 +++++++++++++++++++++++++++++++++++++--- glamor/glamor_utils.h | 38 +++++++++++++++++++++++++ 2 files changed, 94 insertions(+), 4 deletions(-) diff --git a/glamor/glamor_copyarea.c b/glamor/glamor_copyarea.c index cebce218b..2408e3aae 100644 --- a/glamor/glamor_copyarea.c +++ b/glamor/glamor_copyarea.c @@ -308,6 +308,23 @@ glamor_copy_n_to_n(DrawablePtr src, Pixel bitplane, void *closure) { + glamor_access_t dst_access; + PixmapPtr dst_pixmap, src_pixmap, temp_pixmap; + DrawablePtr temp_src = src; + glamor_pixmap_private *dst_pixmap_priv, *src_pixmap_priv; + BoxRec bound; + ScreenPtr screen; + int temp_dx = dx; + int temp_dy = dy; + dst_pixmap = glamor_get_drawable_pixmap(dst); + dst_pixmap_priv = glamor_get_pixmap_private(dst_pixmap); + screen = dst_pixmap->drawable.pScreen; + + if (!GLAMOR_PIXMAP_PRIV_HAS_FBO(dst_pixmap_priv)) { + glamor_fallback("dest pixmap %p has no fbo. \n", dst_pixmap); + goto fail; + } + if (glamor_copy_n_to_n_fbo_blit(src, dst, gc, box, nbox, dx, dy)) { goto done; return; @@ -318,17 +335,50 @@ glamor_copy_n_to_n(DrawablePtr src, return; } - if (glamor_copy_n_to_n_textured(src, dst, gc, box, nbox, dx, dy)) { - goto done; - return; + src_pixmap = glamor_get_drawable_pixmap(src); + src_pixmap_priv = glamor_get_pixmap_private(dst_pixmap); + + glamor_calculate_boxes_bound(&bound, box, nbox); + + if (!GLAMOR_PIXMAP_PRIV_HAS_FBO(src_pixmap_priv) + && ((bound.x2 - bound.x1) * (bound.y2 - bound.y1) + * 4 > src_pixmap->drawable.width * src_pixmap->drawable.height)) { + + temp_pixmap = (*screen->CreatePixmap)(screen, + bound.x2 - bound.x1, + bound.y2 - bound.y1, + src_pixmap->drawable.depth, + GLAMOR_CREATE_PIXMAP_CPU); + if (!temp_src) + goto fail; + glamor_transform_boxes(box, nbox, -bound.x1, -bound.y1); + fbCopyNtoN(src, temp_src, gc, box, nbox, + temp_dx + bound.x1, temp_dy + bound.y1, + reverse, upsidedown, bitplane, + closure); + glamor_transform_boxes(box, nbox, bound.x1, bound.y1); + temp_dx = -bound.x1; + temp_dy = -bound.y1; + temp_src = &temp_pixmap->drawable; } + if (glamor_copy_n_to_n_textured(temp_src, dst, gc, box, nbox, temp_dx, temp_dy)) { + goto done; + } + + fail: glamor_report_delayed_fallbacks(src->pScreen); glamor_report_delayed_fallbacks(dst->pScreen); glamor_fallback("from %p to %p (%c,%c)\n", src, dst, glamor_get_drawable_location(src), glamor_get_drawable_location(dst)); + + if (gc && gc->alu != GXcopy) + dst_access = GLAMOR_ACCESS_RW; + else + dst_access = GLAMOR_ACCESS_WO; + if (glamor_prepare_access(dst, GLAMOR_ACCESS_RW)) { if (dst == src || glamor_prepare_access(src, GLAMOR_ACCESS_RO)) { fbCopyNtoN(src, dst, gc, box, nbox, @@ -339,11 +389,13 @@ glamor_copy_n_to_n(DrawablePtr src, } glamor_finish_access(dst); } - return; done: glamor_clear_delayed_fallbacks(src->pScreen); glamor_clear_delayed_fallbacks(dst->pScreen); + if (temp_src != src) { + (*screen->DestroyPixmap)(temp_pixmap); + } } RegionPtr diff --git a/glamor/glamor_utils.h b/glamor/glamor_utils.h index b8b437eb8..2c6563232 100644 --- a/glamor/glamor_utils.h +++ b/glamor/glamor_utils.h @@ -121,4 +121,42 @@ } while(0) +inline static void +glamor_calculate_boxes_bound(BoxPtr bound, BoxPtr boxes, int nbox) +{ + int x_min, y_min; + int x_max, y_max; + int i; + x_min = y_min = MAXSHORT; + x_max = y_max = MINSHORT; + for(i = 0; i < nbox; i++) + { + if (x_min > boxes[i].x1) + x_min = boxes[i].x1; + if (y_min > boxes[i].y1) + x_min = boxes[i].y1; + + if (x_max < boxes[i].x2) + x_max = boxes[i].x2; + if (y_max > boxes[i].y2) + y_max = boxes[i].y2; + } + bound->x1 = x_min; + bound->y1 = y_min; + bound->x2 = x_max; + bound->y2 = y_max; +} + +inline static void +glamor_transform_boxes(BoxPtr boxes, int nbox, int dx, int dy) +{ + int i; + for (i = 0; i < nbox; i++) + { + boxes[i].x1 += dx; + boxes[i].y1 += dy; + boxes[i].x2 += dx; + boxes[i].y2 += dy; + } +} #endif