From ba6dd8aa492d9d555d8b175bcf350e5db1821597 Mon Sep 17 00:00:00 2001 From: Zhigang Gong Date: Fri, 10 Jun 2011 18:32:15 +0800 Subject: [PATCH] glamor: Simplify fill acceleration for spans/polyfillrect by only clipping once. This commit was borrowed from uxa driver contributed by Eric. commit number is e0066e77e026b0dd0daa0c3765473c7d63aa6753. commit log paste as below: We were clipping each span against the bounds of the clip, throwing out the span early if it was all clipped, and then walked the clip box clipping against each of the cliprects. We would expect spans to typically be clipped against one box, and not thrown out, so we were not saving any work there. For multiple cliprects, we were adding work. Only for many spans clipped entirely out of a complicated clip region would it have saved work, and it clearly didn't save bugs as evidenced by the many fix attempts here. Signed-off-by: Zhigang Gong --- glamor/glamor_fillspans.c | 84 +++++++++++------------------ glamor/glamor_polyfillrect.c | 102 ++++++++++++++--------------------- 2 files changed, 73 insertions(+), 113 deletions(-) diff --git a/glamor/glamor_fillspans.c b/glamor/glamor_fillspans.c index a633b3066..c6976c376 100644 --- a/glamor/glamor_fillspans.c +++ b/glamor/glamor_fillspans.c @@ -38,68 +38,48 @@ glamor_fill_spans(DrawablePtr drawable, int *widths, int sorted) { - RegionPtr clip = gc->pCompositeClip; - BoxPtr extents, boxes; + DDXPointPtr ppt; int nbox; - int extentX1, extentX2, extentY1, extentY2; - int fullX1, fullX2, fullY1; - int partX1, partX2; + BoxPtr pbox; + int x1, x2, y; + int off_x, off_y; + RegionPtr pClip = fbGetCompositeClip(gc); + PixmapPtr pixmap = glamor_get_drawable_pixmap(drawable); + if (gc->fillStyle != FillSolid && gc->fillStyle != FillTiled) goto fail; - extents = REGION_EXTENTS(gc->pScreen, clip); - extentX1 = extents->x1; - extentY1 = extents->y1; - extentX2 = extents->x2; - extentY2 = extents->y2; - while (n--) { - fullX1 = points->x; - fullY1 = points->y; - fullX2 = fullX1 + *widths; - points++; - widths++; - if (fullY1 < extentY1 || extentY2 <= fullY1) - continue; + glamor_get_drawable_deltas(drawable, pixmap, &off_x, &off_y); + ppt = points; + while (n--) { + x1 = ppt->x; + y = ppt->y; + x2 = x1 + (int)*widths; + ppt++; + widths++; - if (fullX1 < extentX1) - fullX1 = extentX1; + nbox = REGION_NUM_RECTS(pClip); + pbox = REGION_RECTS(pClip); + while (nbox--) { + if (pbox->y1 > y || pbox->y2 <= y) + continue; - if (fullX2 > extentX2) - fullX2 = extentX2; + if (x1 < pbox->x1) + x1 = pbox->x1; - if (fullX1 >= fullX2) - continue; + if (x2 > pbox->x2) + x2 = pbox->x2; - nbox = REGION_NUM_RECTS (clip); - if (nbox == 1) { - glamor_fill(drawable, - gc, - fullX1, fullY1, fullX2-fullX1, 1); - } else { - boxes = REGION_RECTS(clip); - while(nbox--) - { - if (boxes->y1 <= fullY1 && fullY1 < boxes->y2) - { - partX1 = boxes->x1; - if (partX1 < fullX1) - partX1 = fullX1; - partX2 = boxes->x2; - if (partX2 > fullX2) - partX2 = fullX2; - if (partX2 > partX1) - { - glamor_fill(drawable, gc, - partX1, fullY1, - partX2 - partX1, 1); - } - } - boxes++; - } - } - } + if (x2 <= x1) + continue; + glamor_fill (drawable,gc, + x1 + off_x, y + off_y, + x2 - x1 , 1); + pbox++; + } + } return; fail: glamor_fallback("glamor_fillspans(): to %p (%c)\n", drawable, diff --git a/glamor/glamor_polyfillrect.c b/glamor/glamor_polyfillrect.c index 29e9db537..660dc4a5b 100644 --- a/glamor/glamor_polyfillrect.c +++ b/glamor/glamor_polyfillrect.c @@ -43,80 +43,60 @@ glamor_poly_fill_rect(DrawablePtr drawable, int nrect, xRectangle *prect) { - RegionPtr clip = fbGetCompositeClip(gc); - register BoxPtr box; - BoxPtr pextent; - int extentX1, extentX2, extentY1, extentY2; int fullX1, fullX2, fullY1, fullY2; - int partX1, partX2, partY1, partY2; int xorg, yorg; int n; + register BoxPtr pbox; + int off_x, off_y; + RegionPtr pClip = fbGetCompositeClip(gc); + PixmapPtr pixmap = glamor_get_drawable_pixmap(drawable); if (gc->fillStyle != FillSolid && gc->fillStyle != FillTiled) goto fail; xorg = drawable->x; yorg = drawable->y; + glamor_get_drawable_deltas(drawable, pixmap, &off_x, &off_y); - pextent = REGION_EXTENTS(gc->pScreen, clip); - extentX1 = pextent->x1; - extentY1 = pextent->y1; - extentX2 = pextent->x2; - extentY2 = pextent->y2; - while (nrect--) - { - fullX1 = prect->x + xorg; - fullY1 = prect->y + yorg; - fullX2 = fullX1 + (int)prect->width; - fullY2 = fullY1 + (int)prect->height; - prect++; + while (nrect--) { + fullX1 = prect->x + xorg; + fullY1 = prect->y + yorg; + fullX2 = fullX1 + (int)prect->width; + fullY2 = fullY1 + (int)prect->height; + prect++; - if (fullX1 < extentX1) - fullX1 = extentX1; + n = REGION_NUM_RECTS(pClip); + pbox = REGION_RECTS(pClip); + /* + * clip the rectangle to each box in the clip region + * this is logically equivalent to calling Intersect(), + * but rectangles may overlap each other here. + */ + while (n--) { + int x1 = fullX1; + int x2 = fullX2; + int y1 = fullY1; + int y2 = fullY2; - if (fullY1 < extentY1) - fullY1 = extentY1; + if (pbox->x1 > x1) + x1 = pbox->x1; + if (pbox->x2 < x2) + x2 = pbox->x2; + if (pbox->y1 > y1) + y1 = pbox->y1; + if (pbox->y2 < y2) + y2 = pbox->y2; + pbox++; - if (fullX2 > extentX2) - fullX2 = extentX2; - - if (fullY2 > extentY2) - fullY2 = extentY2; - - if ((fullX1 >= fullX2) || (fullY1 >= fullY2)) - continue; - n = REGION_NUM_RECTS(clip); - if (n == 1) { - glamor_fill(drawable, - gc, - fullX1, fullY1, fullX2-fullX1, fullY2-fullY1); - } else { - box = REGION_RECTS(clip); - /* clip the rectangle to each box in the clip region - * this is logically equivalent to calling Intersect() - */ - while (n--) { - partX1 = box->x1; - if (partX1 < fullX1) - partX1 = fullX1; - partY1 = box->y1; - if (partY1 < fullY1) - partY1 = fullY1; - partX2 = box->x2; - if (partX2 > fullX2) - partX2 = fullX2; - partY2 = box->y2; - if (partY2 > fullY2) - partY2 = fullY2; - - box++; - - if (partX1 < partX2 && partY1 < partY2) - glamor_fill(drawable, gc, - partX1, partY1, - partX2 - partX1, partY2 - partY1); - } - } + if (x1 >= x2 || y1 >= y2) + continue; + glamor_fill(drawable, + gc, + x1 + off_x, + y1 + off_y, + x2 - x1, + y2 - y1); + } } return;