diff options
author | Michel Dänzer <michel@tungstengraphics.com> | 2007-04-29 23:47:08 +0200 |
---|---|---|
committer | Michel Dänzer <michel@tungstengraphics.com> | 2007-04-29 23:47:08 +0200 |
commit | 0c8905ebc91cf654facef84ee52231a358deec5c (patch) | |
tree | b925c5f819f269fe37ba7a23cf19c399b7609fcc | |
parent | 567f18a09bfb05f448be40c7ebe0f210f955601c (diff) |
EXA: PolyFillRect improvements.
* Convert rects to region and use it for damage tracking.
* When possible, defer to exaFillRegion{Solid,Tiled} using converted region.
* Always migrate for fallbacks.
* Move damage tracking out of ExaCheckPolyFillRect.
-rw-r--r-- | exa/exa_accel.c | 81 | ||||
-rw-r--r-- | exa/exa_unaccel.c | 31 |
2 files changed, 68 insertions, 44 deletions
diff --git a/exa/exa_accel.c b/exa/exa_accel.c index 95084fc37..721882b4c 100644 --- a/exa/exa_accel.c +++ b/exa/exa_accel.c @@ -618,6 +618,9 @@ exaPolySegment (DrawablePtr pDrawable, GCPtr pGC, int nseg, DEALLOCATE_LOCAL(prect); } +static Bool exaFillRegionSolid (DrawablePtr pDrawable, RegionPtr pRegion, + Pixel pixel, CARD32 planemask, CARD32 alu); + static void exaPolyFillRect(DrawablePtr pDrawable, GCPtr pGC, @@ -626,7 +629,7 @@ exaPolyFillRect(DrawablePtr pDrawable, { ExaScreenPriv (pDrawable->pScreen); RegionPtr pClip = fbGetCompositeClip(pGC); - PixmapPtr pPixmap; + PixmapPtr pPixmap = exaGetDrawablePixmap(pDrawable); register BoxPtr pbox; BoxPtr pextent; int extentX1, extentX2, extentY1, extentY2; @@ -635,39 +638,80 @@ exaPolyFillRect(DrawablePtr pDrawable, int xoff, yoff; int xorg, yorg; int n; - ExaMigrationRec pixmaps[1]; + ExaMigrationRec pixmaps[2]; + RegionPtr pReg = RECTS_TO_REGION(pScreen, nrect, prect, CT_UNSORTED); + RegionPtr pDamageReg = DamageRegion(ExaGetPixmapPriv(pPixmap)->pDamage); + + /* Compute intersection of rects and clip region */ + REGION_TRANSLATE(pScreen, pReg, pDrawable->x, pDrawable->y); + REGION_INTERSECT(pScreen, pReg, pClip, pReg); + + if (!REGION_NUM_RECTS(pReg)) { + REGION_DESTROY(pScreen, pReg); + return; + } pixmaps[0].as_dst = TRUE; pixmaps[0].as_src = FALSE; - pixmaps[0].pPix = pPixmap = exaGetDrawablePixmap (pDrawable); + pixmaps[0].pPix = pPixmap; + exaGetDrawableDeltas(pDrawable, pPixmap, &xoff, &yoff); + if (pExaScr->swappedOut || - pGC->fillStyle != FillSolid || pPixmap->drawable.width > pExaScr->info->maxX || pPixmap->drawable.height > pExaScr->info->maxY) { - exaDoMigration (pixmaps, 1, FALSE); - ExaCheckPolyFillRect (pDrawable, pGC, nrect, prect); - while (nrect-- >= 0) { - exaDrawableDirty(pDrawable, - pDrawable->x + prect->x, - pDrawable->y + prect->y, - pDrawable->x + prect->x + prect->width, - pDrawable->y + prect->y + prect->height); - prect++; + goto fallback; + } + + /* For ROPs where overlaps don't matter, convert rectangles to region and + * call exaFillRegion{Solid,Tiled}. + */ + if ((pGC->fillStyle == FillSolid || pGC->fillStyle == FillTiled) && + (pGC->alu == GXcopy || pGC->alu == GXclear || pGC->alu == GXnoop || + pGC->alu == GXcopyInverted || pGC->alu == GXset)) { + if (((pGC->fillStyle == FillSolid || pGC->tileIsPixel) && + exaFillRegionSolid(pDrawable, pReg, pGC->fillStyle == FillSolid ? + pGC->fgPixel : pGC->tile.pixel, pGC->planemask, + pGC->alu)) || + (pGC->fillStyle == FillTiled && !pGC->tileIsPixel && + exaFillRegionTiled(pDrawable, pReg, pGC->tile.pixmap, &pGC->patOrg, + pGC->planemask, pGC->alu))) { + goto damage; } - return; - } else { - exaDoMigration (pixmaps, 1, TRUE); } - if (!(pPixmap = exaGetOffscreenPixmap (pDrawable, &xoff, &yoff)) || + if (pGC->fillStyle != FillSolid && + !(pGC->tileIsPixel && pGC->fillStyle == FillTiled)) + { + goto fallback; + } + + exaDoMigration (pixmaps, 1, TRUE); + + if (!exaPixmapIsOffscreen (pPixmap) || !(*pExaScr->info->PrepareSolid) (pPixmap, pGC->alu, pGC->planemask, pGC->fgPixel)) { +fallback: + if (pGC->fillStyle == FillTiled && !pGC->tileIsPixel) { + pixmaps[1].as_dst = FALSE; + pixmaps[1].as_src = TRUE; + pixmaps[1].pPix = pGC->tile.pixmap; + exaDoMigration (pixmaps, 2, FALSE); + } else { + exaDoMigration (pixmaps, 1, FALSE); + } + ExaCheckPolyFillRect (pDrawable, pGC, nrect, prect); + +damage: + REGION_TRANSLATE(pScreen, pReg, xoff, yoff); + REGION_UNION(pScreen, pDamageReg, pReg, pDamageReg); + REGION_DESTROY(pScreen, pReg); + return; } @@ -715,7 +759,8 @@ exaPolyFillRect(DrawablePtr pDrawable, pbox = REGION_RECTS(pClip); /* * clip the rectangle to each box in the clip region - * this is logically equivalent to calling Intersect() + * this is logically equivalent to calling Intersect(), + * but rectangles may overlap each other here. */ while(n--) { diff --git a/exa/exa_unaccel.c b/exa/exa_unaccel.c index 7713a08c9..a7f939845 100644 --- a/exa/exa_unaccel.c +++ b/exa/exa_unaccel.c @@ -201,32 +201,11 @@ ExaCheckPolyFillRect (DrawablePtr pDrawable, GCPtr pGC, { EXA_FALLBACK(("to %p (%c)\n", pDrawable, exaDrawableLocation(pDrawable))); - if (nrect) { - int x1 = max(prect->x, 0), y1 = max(prect->y, 0); - int x2 = min(prect->x + prect->width, pDrawable->width); - int y2 = min(prect->y + prect->height, pDrawable->height); - - exaPrepareAccess (pDrawable, EXA_PREPARE_DEST); - exaPrepareAccessGC (pGC); - fbPolyFillRect (pDrawable, pGC, nrect, prect); - exaFinishAccessGC (pGC); - exaFinishAccess (pDrawable, EXA_PREPARE_DEST); - - /* Only track bounding box of damage, as this path can degenerate to - * zillions of damage boxes - */ - while (--nrect) - { - prect++; - x1 = min(x1, prect->x); - x2 = max(x2, prect->x + prect->width); - y1 = min(y1, prect->y); - y2 = max(y2, prect->y + prect->height); - } - - exaDrawableDirty (pDrawable, pDrawable->x + x1, pDrawable->y + y1, - pDrawable->x + x2, pDrawable->y + y2); - } + exaPrepareAccess (pDrawable, EXA_PREPARE_DEST); + exaPrepareAccessGC (pGC); + fbPolyFillRect (pDrawable, pGC, nrect, prect); + exaFinishAccessGC (pGC); + exaFinishAccess (pDrawable, EXA_PREPARE_DEST); } void |