diff --git a/exa/exa.c b/exa/exa.c index e9f42df..8e22b89 100644 --- a/exa/exa.c +++ b/exa/exa.c @@ -126,7 +126,7 @@ exaGetDrawablePixmap(DrawablePtr pDrawable) * the backing drawable. These coordinates are nonzero only for redirected * windows. */ -static void +void exaGetDrawableDeltas (DrawablePtr pDrawable, PixmapPtr pPixmap, int *xp, int *yp) { @@ -172,29 +172,6 @@ exaPixmapDirty (PixmapPtr pPix, int x1, int y1, int x2, int y2) REGION_UNINIT(pScreen, ®ion); } -/** - * exaDrawableDirty() marks a pixmap backing a drawable as dirty, allowing for - * optimizations in pixmap migration when no changes have occurred. - */ -void -exaDrawableDirty (DrawablePtr pDrawable, int x1, int y1, int x2, int y2) -{ - PixmapPtr pPix = exaGetDrawablePixmap(pDrawable); - int xoff, yoff; - - x1 = max(x1, pDrawable->x); - y1 = max(y1, pDrawable->y); - x2 = min(x2, pDrawable->x + pDrawable->width); - y2 = min(y2, pDrawable->y + pDrawable->height); - - if (x1 >= x2 || y1 >= y2) - return; - - exaGetDrawableDeltas(pDrawable, pPix, &xoff, &yoff); - - exaPixmapDirty(pPix, x1 + xoff, y1 + yoff, x2 + xoff, y2 + yoff); -} - static Bool exaDestroyPixmap (PixmapPtr pPixmap) { @@ -322,6 +299,9 @@ exaPixmapIsOffscreen(PixmapPtr p) if (p->devPrivate.ptr == NULL) return TRUE; + if (pExaScr->info->PixmapIsOffscreen) + return pExaScr->info->PixmapIsOffscreen(p); + return ((unsigned long) ((CARD8 *) p->devPrivate.ptr - (CARD8 *) pExaScr->info->memoryBase) < pExaScr->info->memorySize); @@ -589,6 +569,45 @@ exaDriverInit (ScreenPtr pScreen, PictureScreenPtr ps; #endif + if (!pScreenInfo) + return FALSE; + + if (!pScreenInfo->memoryBase) { + LogMessage(X_ERROR, "EXA(%d): ExaDriverRec::memoryBase must be " + "non-zero\n", pScreen->myNum); + return FALSE; + } + + if (!pScreenInfo->memorySize) { + LogMessage(X_ERROR, "EXA(%d): ExaDriverRec::memorySize must be " + "non-zero\n", pScreen->myNum); + return FALSE; + } + + if (pScreenInfo->offScreenBase > pScreenInfo->memorySize) { + LogMessage(X_ERROR, "EXA(%d): ExaDriverRec::offScreenBase must be <= " + "ExaDriverRec::memorySize\n", pScreen->myNum); + return FALSE; + } + + if (!pScreenInfo->PrepareSolid) { + LogMessage(X_ERROR, "EXA(%d): ExaDriverRec::PrepareSolid must be " + "non-NULL\n", pScreen->myNum); + return FALSE; + } + + if (!pScreenInfo->PrepareCopy) { + LogMessage(X_ERROR, "EXA(%d): ExaDriverRec::PrepareCopy must be " + "non-NULL\n", pScreen->myNum); + return FALSE; + } + + if (!pScreenInfo->WaitMarker) { + LogMessage(X_ERROR, "EXA(%d): ExaDriverRec::WaitMarker must be " + "non-NULL\n", pScreen->myNum); + return FALSE; + } + if (pScreenInfo->exa_major != EXA_VERSION_MAJOR || pScreenInfo->exa_minor > EXA_VERSION_MINOR) { @@ -668,10 +687,6 @@ exaDriverInit (ScreenPtr pScreen, } #endif -#ifdef COMPOSITE - miDisableCompositeWrapper(pScreen); -#endif - #ifdef MITSHM /* Re-register with the MI funcs, which don't allow shared pixmaps. * Shared pixmaps are almost always a performance loss for us, but this diff --git a/exa/exa.h b/exa/exa.h index bf723f7..9ea5933 100644 --- a/exa/exa.h +++ b/exa/exa.h @@ -39,7 +39,7 @@ #include "fb.h" #define EXA_VERSION_MAJOR 2 -#define EXA_VERSION_MINOR 1 +#define EXA_VERSION_MINOR 2 #define EXA_VERSION_RELEASE 0 typedef struct _ExaOffscreenArea ExaOffscreenArea; @@ -229,7 +229,7 @@ typedef struct _ExaDriver { * @{ */ /** - * PrepareCopy() sets up the driver for doing a copy within offscreen + * PrepareCopy() sets up the driver for doing a copy within video * memory. * * @param pSrcPixmap source pixmap @@ -636,6 +636,23 @@ typedef struct _ExaDriver { */ void (*FinishAccess)(PixmapPtr pPix, int index); + /** + * PixmapIsOffscreen() is an optional driver replacement to + * exaPixmapIsOffscreen(). Set to NULL if you want the standard behaviour + * of exaPixmapIsOffscreen(). + * + * @param pPix the pixmap + * @return TRUE if the given drawable is in framebuffer memory. + * + * exaPixmapIsOffscreen() is used to determine if a pixmap is in offscreen + * memory, meaning that acceleration could probably be done to it, and that it + * will need to be wrapped by PrepareAccess()/FinishAccess() when accessing it + * with the CPU. + * + * + */ + Bool (*PixmapIsOffscreen)(PixmapPtr pPix); + /** @name PrepareAccess() and FinishAccess() indices * @{ */ @@ -704,6 +721,9 @@ exaOffscreenAlloc(ScreenPtr pScreen, int size, int align, ExaOffscreenArea * exaOffscreenFree(ScreenPtr pScreen, ExaOffscreenArea *area); +void +ExaOffscreenMarkUsed (PixmapPtr pPixmap); + unsigned long exaGetPixmapOffset(PixmapPtr pPix); diff --git a/exa/exa_accel.c b/exa/exa_accel.c index e633d80..cc383cc 100644 --- a/exa/exa_accel.c +++ b/exa/exa_accel.c @@ -74,6 +74,7 @@ exaFillSpans(DrawablePtr pDrawable, GCPtr pGC, int n, pGC->planemask, pGC->fgPixel)) { + exaDoMigration (pixmaps, 1, FALSE); ExaCheckFillSpans (pDrawable, pGC, n, ppt, pwidth, fSorted); return; } @@ -109,8 +110,6 @@ exaFillSpans(DrawablePtr pDrawable, GCPtr pGC, int n, (*pExaScr->info->Solid) (pPixmap, fullX1 + off_x, fullY1 + off_y, fullX2 + off_x, fullY1 + 1 + off_y); - exaPixmapDirty (pPixmap, fullX1 + off_x, fullY1 + off_y, - fullX2 + off_x, fullY1 + 1 + off_y); } else { @@ -129,8 +128,6 @@ exaFillSpans(DrawablePtr pDrawable, GCPtr pGC, int n, (*pExaScr->info->Solid) (pPixmap, partX1 + off_x, fullY1 + off_y, partX2 + off_x, fullY1 + 1 + off_y); - exaPixmapDirty (pPixmap, partX1 + off_x, fullY1 + off_y, - partX2 + off_x, fullY1 + 1 + off_y); } } pbox++; @@ -154,8 +151,9 @@ exaPutImage (DrawablePtr pDrawable, GCPtr pGC, int depth, int x, int y, int xoff, yoff; int src_stride, bpp = pDrawable->bitsPerPixel; - if (pExaScr->swappedOut || pExaScr->info->UploadToScreen == NULL) - goto migrate_and_fallback; + pixmaps[0].as_dst = TRUE; + pixmaps[0].as_src = FALSE; + pixmaps[0].pPix = exaGetDrawablePixmap (pDrawable); /* Don't bother with under 8bpp, XYPixmaps. */ if (format != ZPixmap || bpp < 8) @@ -165,10 +163,14 @@ exaPutImage (DrawablePtr pDrawable, GCPtr pGC, int depth, int x, int y, if (!EXA_PM_IS_SOLID(pDrawable, pGC->planemask) || pGC->alu != GXcopy) goto migrate_and_fallback; - pixmaps[0].as_dst = TRUE; - pixmaps[0].as_src = FALSE; - pixmaps[0].pPix = exaGetDrawablePixmap (pDrawable); + if (pExaScr->swappedOut) + goto fallback; + exaDoMigration (pixmaps, 1, TRUE); + + if (pExaScr->info->UploadToScreen == NULL) + goto fallback; + pPix = exaGetOffscreenPixmap (pDrawable, &xoff, &yoff); if (pPix == NULL) @@ -221,25 +223,23 @@ exaPutImage (DrawablePtr pDrawable, GCPtr pGC, int depth, int x, int y, fbBltStip((FbStip *)bits + (y1 - y) * (src_stride / sizeof(FbStip)), src_stride / sizeof(FbStip), - (x1 - x) * bpp, - dst + (y1 + yoff) * dst_stride, + (x1 - x) * dstBpp, + dst + (y1 + dstYoff) * dst_stride, dst_stride, - (x1 + xoff) * bpp, - (x2 - x1) * bpp, + (x1 + dstXoff) * dstBpp, + (x2 - x1) * dstBpp, y2 - y1, - GXcopy, FB_ALLONES, bpp); + GXcopy, FB_ALLONES, dstBpp); exaFinishAccess(pDrawable, EXA_PREPARE_DEST); } + exaPixmapDirty(pPix, x1 + xoff, y1 + yoff, x2 + xoff, y2 + yoff); } return; migrate_and_fallback: - pixmaps[0].as_dst = TRUE; - pixmaps[0].as_src = FALSE; - pixmaps[0].pPix = exaGetDrawablePixmap (pDrawable); exaDoMigration (pixmaps, 1, FALSE); fallback: @@ -387,6 +387,7 @@ exaCopyNtoN (DrawablePtr pSrcDrawable, int src_off_x, src_off_y; int dst_off_x, dst_off_y; ExaMigrationRec pixmaps[2]; + Bool fallback = FALSE; pixmaps[0].as_dst = TRUE; pixmaps[0].as_src = FALSE; @@ -404,62 +405,64 @@ exaCopyNtoN (DrawablePtr pSrcDrawable, pDstPixmap->drawable.width > pExaScr->info->maxX || pDstPixmap->drawable.height > pExaScr->info->maxY) { - exaDoMigration (pixmaps, 2, FALSE); - goto fallback; + fallback = TRUE; } else { exaDoMigration (pixmaps, 2, TRUE); } /* Mixed directions must be handled specially if the card is lame */ - if (pExaScr->info->flags & EXA_TWO_BITBLT_DIRECTIONS && + if (!fallback && (pExaScr->info->flags & EXA_TWO_BITBLT_DIRECTIONS) && reverse != upsidedown) { - if (!exaCopyNtoNTwoDir(pSrcDrawable, pDstDrawable, pGC, pbox, nbox, + if (exaCopyNtoNTwoDir(pSrcDrawable, pDstDrawable, pGC, pbox, nbox, dx, dy)) - goto fallback; - return; + return; + fallback = TRUE; + } + + pSrcPixmap = exaGetDrawablePixmap (pSrcDrawable); + pDstPixmap = exaGetDrawablePixmap (pDstDrawable); + + exaGetDrawableDeltas (pSrcDrawable, pSrcPixmap, &src_off_x, &src_off_y); + exaGetDrawableDeltas (pDstDrawable, pDstPixmap, &dst_off_x, &dst_off_y); + + if (fallback || !exaPixmapIsOffscreen(pSrcPixmap) || + !exaPixmapIsOffscreen(pDstPixmap) || + !(*pExaScr->info->PrepareCopy) (pSrcPixmap, pDstPixmap, reverse ? -1 : 1, + upsidedown ? -1 : 1, + pGC ? pGC->alu : GXcopy, + pGC ? pGC->planemask : FB_ALLONES)) { + fallback = TRUE; + EXA_FALLBACK(("from %p to %p (%c,%c)\n", pSrcDrawable, pDstDrawable, + exaDrawableLocation(pSrcDrawable), + exaDrawableLocation(pDstDrawable))); + exaDoMigration (pixmaps, 2, FALSE); + exaPrepareAccess (pDstDrawable, EXA_PREPARE_DEST); + exaPrepareAccess (pSrcDrawable, EXA_PREPARE_SRC); + fbCopyNtoN (pSrcDrawable, pDstDrawable, pGC, + pbox, nbox, dx, dy, reverse, upsidedown, + bitplane, closure); + exaFinishAccess (pSrcDrawable, EXA_PREPARE_SRC); + exaFinishAccess (pDstDrawable, EXA_PREPARE_DEST); } - if ((pSrcPixmap = exaGetOffscreenPixmap (pSrcDrawable, &src_off_x, &src_off_y)) && - (pDstPixmap = exaGetOffscreenPixmap (pDstDrawable, &dst_off_x, &dst_off_y)) && - (*pExaScr->info->PrepareCopy) (pSrcPixmap, pDstPixmap, - reverse ? -1 : 1, upsidedown ? -1 : 1, - pGC ? pGC->alu : GXcopy, - pGC ? pGC->planemask : FB_ALLONES)) + while (nbox--) { - while (nbox--) - { + if (!fallback) (*pExaScr->info->Copy) (pDstPixmap, pbox->x1 + dx + src_off_x, pbox->y1 + dy + src_off_y, pbox->x1 + dst_off_x, pbox->y1 + dst_off_y, - pbox->x2 - pbox->x1, - pbox->y2 - pbox->y1); - exaPixmapDirty (pDstPixmap, - pbox->x1 + dst_off_x, pbox->y1 + dst_off_y, - pbox->x2 + dst_off_x, pbox->y2 + dst_off_y); - pbox++; - } - (*pExaScr->info->DoneCopy) (pDstPixmap); - exaMarkSync(pDstDrawable->pScreen); - return; - } - -fallback: - EXA_FALLBACK(("from %p to %p (%c,%c)\n", pSrcDrawable, pDstDrawable, - exaDrawableLocation(pSrcDrawable), - exaDrawableLocation(pDstDrawable))); - exaPrepareAccess (pDstDrawable, EXA_PREPARE_DEST); - exaPrepareAccess (pSrcDrawable, EXA_PREPARE_SRC); - fbCopyNtoN (pSrcDrawable, pDstDrawable, pGC, - pbox, nbox, dx, dy, reverse, upsidedown, - bitplane, closure); - exaFinishAccess (pSrcDrawable, EXA_PREPARE_SRC); - exaFinishAccess (pDstDrawable, EXA_PREPARE_DEST); - while (nbox--) - { - exaDrawableDirty (pDstDrawable, pbox->x1, pbox->y1, pbox->x2, pbox->y2); + pbox->x2 - pbox->x1, pbox->y2 - pbox->y1); + exaPixmapDirty (pDstPixmap, pbox->x1 + dst_off_x, pbox->y1 + dst_off_y, + pbox->x2 + dst_off_x, pbox->y2 + dst_off_y); pbox++; } + + if (fallback) + return; + + (*pExaScr->info->DoneCopy) (pDstPixmap); + exaMarkSync (pDstDrawable->pScreen); } RegionPtr @@ -618,6 +621,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 +632,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,40 +641,73 @@ 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); + + /* 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)) { + goto out; + } 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 out; } - 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); - return; + goto out; } xorg = pDrawable->x; @@ -707,15 +746,14 @@ exaPolyFillRect(DrawablePtr pDrawable, (*pExaScr->info->Solid) (pPixmap, fullX1 + xoff, fullY1 + yoff, fullX2 + xoff, fullY2 + yoff); - exaPixmapDirty (pPixmap, fullX1 + xoff, fullY1 + yoff, - fullX2 + xoff, fullY2 + yoff); } else { 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--) { @@ -738,14 +776,15 @@ exaPolyFillRect(DrawablePtr pDrawable, (*pExaScr->info->Solid) (pPixmap, partX1 + xoff, partY1 + yoff, partX2 + xoff, partY2 + yoff); - exaPixmapDirty (pPixmap, partX1 + xoff, partY1 + yoff, - partX2 + xoff, partY2 + yoff); } } } } (*pExaScr->info->DoneSolid) (pPixmap); exaMarkSync(pDrawable->pScreen); + +out: + REGION_DESTROY(pScreen, pReg); } static void @@ -775,20 +814,19 @@ exaSolidBoxClipped (DrawablePtr pDrawable, pPixmap->drawable.width > pExaScr->info->maxX || pPixmap->drawable.height > pExaScr->info->maxY) { - exaDoMigration (pixmaps, 1, FALSE); - goto fallback; + fallback = TRUE; } else { exaDoMigration (pixmaps, 1, TRUE); } - pPixmap = exaGetOffscreenPixmap (pDrawable, &xoff, &yoff); + exaGetDrawableDeltas (pDrawable, pPixmap, &xoff, &yoff); - if (!pPixmap || + if (fallback || !exaPixmapIsOffscreen(pPixmap) || !(*pExaScr->info->PrepareSolid) (pPixmap, GXcopy, pm, fg)) { -fallback: EXA_FALLBACK(("to %p (%c)\n", pDrawable, exaDrawableLocation(pDrawable))); + exaDoMigration (pixmaps, 1, FALSE); fallback = TRUE; exaPrepareAccess (pDrawable, EXA_PREPARE_DEST); fg = fbReplicatePixel (fg, pDrawable->bitsPerPixel); @@ -827,10 +865,10 @@ fallback: (*pExaScr->info->Solid) (pPixmap, partX1 + xoff, partY1 + yoff, partX2 + xoff, partY2 + yoff); - exaPixmapDirty (pPixmap, partX1 + xoff, partY1 + yoff, - partX2 + xoff, partY2 + yoff); - } else - exaDrawableDirty (pDrawable, partX1, partY1, partX2, partY2); + } + + exaPixmapDirty (pPixmap, partX1 + xoff, partY1 + yoff, partX2 + xoff, + partY2 + yoff); } if (fallback) @@ -870,12 +908,36 @@ exaImageGlyphBlt (DrawablePtr pDrawable, int dstBpp; int dstXoff, dstYoff; FbBits depthMask; + PixmapPtr pPixmap = exaGetDrawablePixmap(pDrawable); + ExaMigrationRec pixmaps[1]; + int xBack, widthBack, yBack, heightBack; + + for (ppci = ppciInit, n = nglyph, widthBack = 0; n; n--) + widthBack += (*ppci++)->metrics.characterWidth; + + xBack = x; + if (widthBack < 0) + { + xBack += widthBack; + widthBack = -widthBack; + } + yBack = y - FONTASCENT(pGC->font); + heightBack = FONTASCENT(pGC->font) + FONTDESCENT(pGC->font); + + if (xBack >= pDrawable->width || yBack >= pDrawable->height || + (xBack + widthBack) <= 0 || (yBack + heightBack) <= 0) + return; + + pixmaps[0].as_dst = TRUE; + pixmaps[0].as_src = TRUE; + pixmaps[0].pPix = pPixmap; depthMask = FbFullMask(pDrawable->depth); if ((pGC->planemask & depthMask) != depthMask) { + exaDoMigration(pixmaps, 1, FALSE); ExaCheckImageGlyphBlt(pDrawable, pGC, x, y, nglyph, ppciInit, pglyphBase); - return; + goto damage; } glyph = NULL; switch (pDrawable->bitsPerPixel) { @@ -887,6 +949,8 @@ exaImageGlyphBlt (DrawablePtr pDrawable, x += pDrawable->x; y += pDrawable->y; + xBack += pDrawable->x; + yBack += pDrawable->y; if (TERMINALFONT (pGC->font) && !glyph) { @@ -894,23 +958,6 @@ exaImageGlyphBlt (DrawablePtr pDrawable, } else { - int xBack, widthBack; - int yBack, heightBack; - - ppci = ppciInit; - n = nglyph; - widthBack = 0; - while (n--) - widthBack += (*ppci++)->metrics.characterWidth; - - xBack = x; - if (widthBack < 0) - { - xBack += widthBack; - widthBack = -widthBack; - } - yBack = y - FONTASCENT(pGC->font); - heightBack = FONTASCENT(pGC->font) + FONTDESCENT(pGC->font); exaSolidBoxClipped (pDrawable, fbGetCompositeClip(pGC), pGC->planemask, @@ -923,74 +970,50 @@ exaImageGlyphBlt (DrawablePtr pDrawable, } EXA_FALLBACK(("to %p (%c)\n", pDrawable, exaDrawableLocation(pDrawable))); + exaDoMigration(pixmaps, 1, FALSE); exaPrepareAccess (pDrawable, EXA_PREPARE_DEST); exaPrepareAccessGC (pGC); fbGetDrawable (pDrawable, dst, dstStride, dstBpp, dstXoff, dstYoff); - ppci = ppciInit; - while (nglyph--) + for (ppci = ppciInit; nglyph; nglyph--, x += pci->metrics.characterWidth) { pci = *ppci++; - pglyph = FONTGLYPHBITS(pglyphBase, pci); gWidth = GLYPHWIDTHPIXELS(pci); gHeight = GLYPHHEIGHTPIXELS(pci); - if (gWidth && gHeight) + gx = x + pci->metrics.leftSideBearing; + gy = y - pci->metrics.ascent; + + if (!gWidth || !gHeight || (gx + gWidth) <= xBack || + (gy + gHeight) <= yBack || gx >= (xBack + widthBack) || + gy >= (yBack + heightBack)) + continue; + + pglyph = FONTGLYPHBITS(pglyphBase, pci); + + if (glyph && gWidth <= sizeof (FbStip) * 8 && + fbGlyphIn (fbGetCompositeClip(pGC), gx, gy, gWidth, gHeight)) { - gx = x + pci->metrics.leftSideBearing; - gy = y - pci->metrics.ascent; - if (glyph && gWidth <= sizeof (FbStip) * 8 && - fbGlyphIn (fbGetCompositeClip(pGC), gx, gy, gWidth, gHeight)) - { - (*glyph) (dst + (gy + dstYoff) * dstStride, - dstStride, - dstBpp, - (FbStip *) pglyph, - pPriv->fg, - gx + dstXoff, - gHeight); - exaDrawableDirty (pDrawable, gx, gy, gx + gWidth, gy + gHeight); - } - else - { - RegionPtr pClip = fbGetCompositeClip(pGC); - int nbox; - BoxPtr pbox; - - gStride = GLYPHWIDTHBYTESPADDED(pci) / sizeof (FbStip); - fbPutXYImage (pDrawable, - pClip, - pPriv->fg, - pPriv->bg, - pPriv->pm, - GXcopy, - opaque, - - gx, - gy, - gWidth, gHeight, - - (FbStip *) pglyph, - gStride, - 0); - - for (nbox = REGION_NUM_RECTS(pClip), pbox = REGION_RECTS(pClip); - nbox--; pbox++) { - int x1 = max(gx, pbox->x1), x2 = min(gx + gWidth, pbox->x2); - int y1 = max(gy, pbox->y1), y2 = min(gy + gHeight, pbox->y2); - - if (x1 >= x2 || y1 >= y2) - continue; - - exaDrawableDirty (pDrawable, gx, gy, gx + gWidth, - gy + gHeight); - } - } + (*glyph) (dst + (gy + dstYoff) * dstStride, dstStride, dstBpp, + (FbStip *) pglyph, pPriv->fg, gx + dstXoff, gHeight); + } + else + { + RegionPtr pClip = fbGetCompositeClip(pGC); + + gStride = GLYPHWIDTHBYTESPADDED(pci) / sizeof (FbStip); + fbPutXYImage (pDrawable, pClip, pPriv->fg, pPriv->bg, pPriv->pm, + GXcopy, opaque, gx, gy, gWidth, gHeight, + (FbStip *) pglyph, gStride, 0); } - x += pci->metrics.characterWidth; } exaFinishAccessGC (pGC); exaFinishAccess (pDrawable, EXA_PREPARE_DEST); + +damage: + exaGetDrawableDeltas(pDrawable, pPixmap, &dstXoff, &dstYoff); + exaPixmapDirty(pPixmap, xBack + dstXoff, yBack + dstYoff, + xBack + dstXoff + widthBack, yBack + dstYoff + heightBack); } const GCOps exaOps = { @@ -1043,10 +1066,12 @@ exaCopyWindow(WindowPtr pWin, DDXPointRec ptOldOrg, RegionPtr prgnSrc) REGION_UNINIT(pWin->drawable.pScreen, &rgnDst); } -static void +static Bool exaFillRegionSolid (DrawablePtr pDrawable, RegionPtr pRegion, - Pixel pixel) + Pixel pixel, + CARD32 planemask, + CARD32 alu) { ExaScreenPriv(pDrawable->pScreen); PixmapPtr pPixmap; @@ -1062,22 +1087,19 @@ exaFillRegionSolid (DrawablePtr pDrawable, if (pPixmap->drawable.width > pExaScr->info->maxX || pPixmap->drawable.height > pExaScr->info->maxY) { - exaDoMigration (pixmaps, 1, FALSE); goto fallback; } else { exaDoMigration (pixmaps, 1, TRUE); } if ((pPixmap = exaGetOffscreenPixmap (pDrawable, &xoff, &yoff)) && - (*pExaScr->info->PrepareSolid) (pPixmap, GXcopy, FB_ALLONES, pixel)) + (*pExaScr->info->PrepareSolid) (pPixmap, alu, planemask, pixel)) { while (nbox--) { (*pExaScr->info->Solid) (pPixmap, pBox->x1 + xoff, pBox->y1 + yoff, pBox->x2 + xoff, pBox->y2 + yoff); - exaPixmapDirty (pPixmap, pBox->x1 + xoff, pBox->y1 + yoff, - pBox->x2 + xoff, pBox->y2 + yoff); pBox++; } (*pExaScr->info->DoneSolid) (pPixmap); @@ -1086,27 +1108,30 @@ exaFillRegionSolid (DrawablePtr pDrawable, else { fallback: + if (alu != GXcopy || planemask != FB_ALLONES) + return FALSE; EXA_FALLBACK(("to %p (%c)\n", pDrawable, exaDrawableLocation(pDrawable))); + exaDoMigration (pixmaps, 1, FALSE); exaPrepareAccess (pDrawable, EXA_PREPARE_DEST); fbFillRegionSolid (pDrawable, pRegion, 0, fbReplicatePixel (pixel, pDrawable->bitsPerPixel)); exaFinishAccess (pDrawable, EXA_PREPARE_DEST); - while (nbox--) - { - exaDrawableDirty (pDrawable, pBox->x1, pBox->y1, pBox->x2, pBox->y2); - pBox++; - } } + + return TRUE; } /* Try to do an accelerated tile of the pTile into pRegion of pDrawable. * Based on fbFillRegionTiled(), fbTile(). */ -static void +Bool exaFillRegionTiled (DrawablePtr pDrawable, RegionPtr pRegion, - PixmapPtr pTile) + PixmapPtr pTile, + DDXPointPtr pPatOrg, + CARD32 planemask, + CARD32 alu) { ExaScreenPriv(pDrawable->pScreen); PixmapPtr pPixmap; @@ -1122,10 +1147,10 @@ exaFillRegionTiled (DrawablePtr pDrawable, /* If we're filling with a solid color, grab it out and go to * FillRegionSolid, saving numerous copies. */ - if (tileWidth == 1 && tileHeight == 1) { - exaFillRegionSolid(pDrawable, pRegion, exaGetPixmapFirstPixel (pTile)); - return; - } + if (tileWidth == 1 && tileHeight == 1) + return exaFillRegionSolid(pDrawable, pRegion, + exaGetPixmapFirstPixel (pTile), planemask, + alu); pixmaps[0].as_dst = TRUE; pixmaps[0].as_src = FALSE; @@ -1139,7 +1164,6 @@ exaFillRegionTiled (DrawablePtr pDrawable, tileWidth > pExaScr->info->maxX || tileHeight > pExaScr->info->maxY) { - exaDoMigration (pixmaps, 2, FALSE); goto fallback; } else { exaDoMigration (pixmaps, 2, TRUE); @@ -1153,8 +1177,9 @@ exaFillRegionTiled (DrawablePtr pDrawable, if (!exaPixmapIsOffscreen(pTile)) goto fallback; - if ((*pExaScr->info->PrepareCopy) (exaGetOffscreenPixmap((DrawablePtr)pTile, &tileXoff, &tileYoff), pPixmap, 0, 0, GXcopy, - FB_ALLONES)) + if ((*pExaScr->info->PrepareCopy) (exaGetOffscreenPixmap((DrawablePtr)pTile, + &tileXoff, &tileYoff), + pPixmap, 0, 0, alu, planemask)) { while (nbox--) { @@ -1162,7 +1187,7 @@ exaFillRegionTiled (DrawablePtr pDrawable, int dstY = pBox->y1; int tileY; - tileY = (dstY - pDrawable->y) % tileHeight; + tileY = (dstY - pDrawable->y - pPatOrg->y) % tileHeight; while (height > 0) { int width = pBox->x2 - pBox->x1; int dstX = pBox->x1; @@ -1173,7 +1198,7 @@ exaFillRegionTiled (DrawablePtr pDrawable, h = height; height -= h; - tileX = (dstX - pDrawable->x) % tileWidth; + tileX = (dstX - pDrawable->x - pPatOrg->x) % tileWidth; while (width > 0) { int w = tileWidth - tileX; if (w > width) @@ -1190,38 +1215,44 @@ exaFillRegionTiled (DrawablePtr pDrawable, dstY += h; tileY = 0; } - exaPixmapDirty (pPixmap, pBox->x1 + xoff, pBox->y1 + yoff, - pBox->x2 + xoff, pBox->y2 + yoff); pBox++; } (*pExaScr->info->DoneCopy) (pPixmap); exaMarkSync(pDrawable->pScreen); - return; + return TRUE; } fallback: + if (alu != GXcopy || planemask != FB_ALLONES) + return FALSE; EXA_FALLBACK(("from %p to %p (%c,%c)\n", pTile, pDrawable, exaDrawableLocation(&pTile->drawable), exaDrawableLocation(pDrawable))); + exaDoMigration (pixmaps, 2, FALSE); exaPrepareAccess (pDrawable, EXA_PREPARE_DEST); exaPrepareAccess ((DrawablePtr)pTile, EXA_PREPARE_SRC); fbFillRegionTiled (pDrawable, pRegion, pTile); exaFinishAccess ((DrawablePtr)pTile, EXA_PREPARE_SRC); exaFinishAccess (pDrawable, EXA_PREPARE_DEST); - while (nbox--) - { - exaDrawableDirty (pDrawable, pBox->x1, pBox->y1, pBox->x2, pBox->y2); - pBox++; - } + + return TRUE; } void exaPaintWindow(WindowPtr pWin, RegionPtr pRegion, int what) { ExaScreenPriv (pWin->drawable.pScreen); - if (!REGION_NUM_RECTS(pRegion)) + PixmapPtr pPixmap = exaGetDrawablePixmap((DrawablePtr)pWin); + int xoff, yoff; + BoxPtr pBox; + int nbox = REGION_NUM_RECTS(pRegion); + + if (!nbox) return; + if (!pExaScr->swappedOut) { + DDXPointRec zeros = { 0, 0 }; + switch (what) { case PW_BACKGROUND: switch (pWin->backgroundState) { @@ -1235,25 +1266,41 @@ exaPaintWindow(WindowPtr pWin, RegionPtr pRegion, int what) what); return; case BackgroundPixel: - exaFillRegionSolid((DrawablePtr)pWin, pRegion, pWin->background.pixel); - return; + exaFillRegionSolid((DrawablePtr)pWin, pRegion, pWin->background.pixel, + FB_ALLONES, GXcopy); + goto damage; case BackgroundPixmap: - exaFillRegionTiled((DrawablePtr)pWin, pRegion, pWin->background.pixmap); - return; + exaFillRegionTiled((DrawablePtr)pWin, pRegion, pWin->background.pixmap, + &zeros, FB_ALLONES, GXcopy); + goto damage; } break; case PW_BORDER: if (pWin->borderIsPixel) { - exaFillRegionSolid((DrawablePtr)pWin, pRegion, pWin->border.pixel); - return; + exaFillRegionSolid((DrawablePtr)pWin, pRegion, pWin->border.pixel, + FB_ALLONES, GXcopy); + goto damage; } else { - exaFillRegionTiled((DrawablePtr)pWin, pRegion, pWin->border.pixmap); - return; + exaFillRegionTiled((DrawablePtr)pWin, pRegion, pWin->border.pixmap, + &zeros, FB_ALLONES, GXcopy); + goto damage; } break; } } ExaCheckPaintWindow (pWin, pRegion, what); + +damage: + exaGetDrawableDeltas((DrawablePtr)pWin, pPixmap, &xoff, &yoff); + + pBox = REGION_RECTS(pRegion); + + while (nbox--) + { + exaPixmapDirty (pPixmap, pBox->x1 + xoff, pBox->y1 + yoff, + pBox->x2 + xoff, pBox->y2 + yoff); + pBox++; + } } /** @@ -1273,27 +1320,22 @@ exaGetImage (DrawablePtr pDrawable, int x, int y, int w, int h, int xoff, yoff; Bool ok; - if (pExaScr->swappedOut || pExaScr->info->DownloadFromScreen == NULL) + if (pExaScr->swappedOut || (w == 1 && h == 1)) goto fallback; + if (pExaScr->info->DownloadFromScreen == NULL) + goto migrate_and_fallback; + /* Only cover the ZPixmap, solid copy case. */ if (format != ZPixmap || !EXA_PM_IS_SOLID(pDrawable, planeMask)) - goto fallback; + goto migrate_and_fallback; /* Only try to handle the 8bpp and up cases, since we don't want to think * about <8bpp. */ if (pDrawable->bitsPerPixel < 8) - goto fallback; + goto migrate_and_fallback; - /* Migrate, but assume that we could accelerate the download. It is up to - * the migration scheme to ensure that this case doesn't result in bad - * moving of pixmaps. - */ - pixmaps[0].as_dst = FALSE; - pixmaps[0].as_src = TRUE; - pixmaps[0].pPix = exaGetDrawablePixmap (pDrawable); - exaDoMigration (pixmaps, 1, TRUE); pPix = exaGetOffscreenPixmap (pDrawable, &xoff, &yoff); if (pPix == NULL) goto fallback; @@ -1308,12 +1350,12 @@ exaGetImage (DrawablePtr pDrawable, int x, int y, int w, int h, return; } -fallback: +migrate_and_fallback: pixmaps[0].as_dst = FALSE; pixmaps[0].as_src = TRUE; pixmaps[0].pPix = exaGetDrawablePixmap (pDrawable); exaDoMigration (pixmaps, 1, FALSE); - +fallback: ExaCheckGetImage (pDrawable, x, y, w, h, format, planeMask, d); } diff --git a/exa/exa_migration.c b/exa/exa_migration.c index eedc5fd..70d8e12 100644 --- a/exa/exa_migration.c +++ b/exa/exa_migration.c @@ -464,12 +464,10 @@ exaAssertNotDirty (PixmapPtr pPixmap) BoxPtr pBox = REGION_RECTS(pValidReg); Bool ret = TRUE; - if (pExaPixmap == NULL || pExaPixmap->fb_ptr == NULL) + if (!nbox || exaPixmapIsPinned(pPixmap) || pExaPixmap->fb_ptr == NULL) return ret; - dst = pExaPixmap->sys_ptr; dst_pitch = pExaPixmap->sys_pitch; - src = pExaPixmap->fb_ptr; src_pitch = pExaPixmap->fb_pitch; cpp = pPixmap->drawable.bitsPerPixel / 8; @@ -486,21 +484,18 @@ exaAssertNotDirty (PixmapPtr pPixmap) continue; rowbytes = (pBox->x2 - pBox->x1) * cpp; - src += pBox->y1 * src_pitch + pBox->x1 * cpp; - dst += pBox->y1 * dst_pitch + pBox->x1 * cpp; + src = pExaPixmap->fb_ptr + pBox->y1 * src_pitch + pBox->x1 * cpp; + dst = pExaPixmap->sys_ptr + pBox->y1 * dst_pitch + pBox->x1 * cpp; - for (y = pBox->y2 - pBox->y1; y; y--) { - if (memcmp(dst + pBox->y1 * dst_pitch + pBox->x1 * cpp, - src + pBox->y1 * src_pitch + pBox->x1 * cpp, - (pBox->x2 - pBox->x1) * cpp) != 0) { + for (y = pBox->y1; y < pBox->y2; + y++, src += src_pitch, dst += dst_pitch) { + if (memcmp(dst, src, rowbytes) != 0) { ret = FALSE; + exaPixmapDirty(pPixmap, pBox->x1, pBox->y1, pBox->x2, + pBox->y2); break; } - src += src_pitch; - dst += dst_pitch; } - src -= pBox->y1 * src_pitch + pBox->x1 * cpp; - dst -= pBox->y1 * dst_pitch + pBox->x1 * cpp; } exaFinishAccess(&pPixmap->drawable, EXA_PREPARE_SRC); diff --git a/exa/exa_offscreen.c b/exa/exa_offscreen.c index 7708dd7..c666b00 100644 --- a/exa/exa_offscreen.c +++ b/exa/exa_offscreen.c @@ -54,7 +54,7 @@ ExaOffscreenValidate (ScreenPtr pScreen) assert (area->offset >= area->base_offset && area->offset < (area->base_offset + area->size)); if (prev) - assert (prev->base_offset + prev->area.size == area->base_offset); + assert (prev->base_offset + prev->size == area->base_offset); prev = area; } assert (prev->base_offset + prev->size == pExaScr->info->memorySize); @@ -341,13 +341,15 @@ exaEnableDisableFBAccess (int index, Bool enable) ScreenPtr pScreen = screenInfo.screens[index]; ExaScreenPriv (pScreen); - if (!enable) { + if (!enable && pExaScr->disableFbCount++ == 0) { if (pExaScr->info->exa_minor < 1) ExaOffscreenSwapOut (pScreen); else ExaOffscreenEjectPixmaps (pScreen); pExaScr->swappedOut = TRUE; - } else { + } + + if (enable && --pExaScr->disableFbCount == 0) { if (pExaScr->info->exa_minor < 1) ExaOffscreenSwapIn (pScreen); pExaScr->swappedOut = FALSE; @@ -427,7 +429,7 @@ ExaOffscreenMarkUsed (PixmapPtr pPixmap) ExaScreenPriv (pPixmap->drawable.pScreen); static int iter = 0; - if (!pExaPixmap->area) + if (!pExaPixmap || !pExaPixmap->area) return; /* The numbers here are arbitrary. We may want to tune these. */ diff --git a/exa/exa_priv.h b/exa/exa_priv.h index 984cb66..a6d98cd 100644 --- a/exa/exa_priv.h +++ b/exa/exa_priv.h @@ -113,6 +113,7 @@ typedef struct { enum ExaMigrationHeuristic migration; Bool hideOffscreenPixmapData; Bool checkDirtyCorrectness; + unsigned disableFbCount; } ExaScreenPrivRec, *ExaScreenPrivPtr; /* @@ -287,6 +288,10 @@ exaGetPixmapFirstPixel (PixmapPtr pPixmap); void exaCopyWindow(WindowPtr pWin, DDXPointRec ptOldOrg, RegionPtr prgnSrc); +Bool +exaFillRegionTiled (DrawablePtr pDrawable, RegionPtr pRegion, PixmapPtr pTile, + DDXPointPtr pPatOrg, CARD32 planemask, CARD32 alu); + void exaPaintWindow(WindowPtr pWin, RegionPtr pRegion, int what); @@ -318,9 +323,6 @@ ExaCheckComposite (CARD8 op, /* exa_offscreen.c */ void -ExaOffscreenMarkUsed (PixmapPtr pPixmap); - -void ExaOffscreenSwapOut (ScreenPtr pScreen); void @@ -343,7 +345,8 @@ void exaPixmapDirty(PixmapPtr pPix, int x1, int y1, int x2, int y2); void -exaDrawableDirty(DrawablePtr pDrawable, int x1, int y1, int x2, int y2); +exaGetDrawableDeltas (DrawablePtr pDrawable, PixmapPtr pPixmap, + int *xp, int *yp); Bool exaDrawableIsOffscreen (DrawablePtr pDrawable); diff --git a/exa/exa_render.c b/exa/exa_render.c index b78d728..5e7c67f 100644 --- a/exa/exa_render.c +++ b/exa/exa_render.c @@ -297,15 +297,15 @@ exaTryDriverSolidFill(PicturePtr pSrc, nbox = REGION_NUM_RECTS(®ion); pbox = REGION_RECTS(®ion); + while (nbox--) { (*pExaScr->info->Solid) (pDstPix, pbox->x1 + dst_off_x, pbox->y1 + dst_off_y, pbox->x2 + dst_off_x, pbox->y2 + dst_off_y); - exaPixmapDirty (pDstPix, pbox->x1 + dst_off_x, pbox->y1 + dst_off_y, - pbox->x2 + dst_off_x, pbox->y2 + dst_off_y); pbox++; } + (*pExaScr->info->DoneSolid) (pDstPix); exaMarkSync(pDst->pDrawable->pScreen); @@ -446,8 +446,6 @@ exaTryDriverComposite(CARD8 op, pbox->y1 + dst_off_y, pbox->x2 - pbox->x1, pbox->y2 - pbox->y1); - exaPixmapDirty (pDstPix, pbox->x1 + dst_off_x, pbox->y1 + dst_off_y, - pbox->x2 + dst_off_x, pbox->y2 + dst_off_y); pbox++; } (*pExaScr->info->DoneComposite) (pDstPix); @@ -521,6 +519,9 @@ exaTryMagicTwoPassCompositeHelper(CARD8 op, CARD16 height) { ExaScreenPriv (pDst->pDrawable->pScreen); + DrawablePtr pDstDraw = pDst->pDrawable; + PixmapPtr pDstPixmap = exaGetDrawablePixmap(pDstDraw); + int xoff, yoff; assert(op == PictOpOver); @@ -539,6 +540,12 @@ exaTryMagicTwoPassCompositeHelper(CARD8 op, exaComposite(PictOpOutReverse, pSrc, pMask, pDst, xSrc, ySrc, xMask, yMask, xDst, yDst, width, height); + exaGetDrawableDeltas(pDstDraw, pDstPixmap, &xoff, &yoff); + xoff += pDstDraw->x; + yoff += pDstDraw->y; + exaPixmapDirty(pDstPixmap, xDst + xoff, yDst + yoff, xDst + xoff + width, + yDst + yoff + height); + /* Then, add in the source value times the destination alpha factors (1.0). */ exaComposite(PictOpAdd, pSrc, pMask, pDst, xSrc, ySrc, xMask, yMask, @@ -565,6 +572,28 @@ exaComposite(CARD8 op, int ret = -1; Bool saveSrcRepeat = pSrc->repeat; Bool saveMaskRepeat = pMask ? pMask->repeat : 0; + ExaMigrationRec pixmaps[3]; + int npixmaps = 1; + PixmapPtr pSrcPixmap = NULL; + + pixmaps[0].as_dst = TRUE; + pixmaps[0].as_src = exaOpReadsDestination(op); + pixmaps[0].pPix = exaGetDrawablePixmap (pDst->pDrawable); + + if (pSrc->pDrawable) { + pSrcPixmap = exaGetDrawablePixmap (pSrc->pDrawable); + pixmaps[npixmaps].as_dst = FALSE; + pixmaps[npixmaps].as_src = TRUE; + pixmaps[npixmaps].pPix = pSrcPixmap; + npixmaps++; + } + + if (pMask && pMask->pDrawable) { + pixmaps[npixmaps].as_dst = FALSE; + pixmaps[npixmaps].as_src = TRUE; + pixmaps[npixmaps].pPix = exaGetDrawablePixmap (pMask->pDrawable); + npixmaps++; + } /* We currently don't support acceleration of gradients, or other pictures * with a NULL pDrawable. @@ -583,19 +612,24 @@ exaComposite(CARD8 op, if (!pMask) { - if (op == PictOpSrc) + if ((op == PictOpSrc && + ((pSrc->format == pDst->format) || + (pSrc->format==PICT_a8r8g8b8 && pDst->format==PICT_x8r8g8b8) || + (pSrc->format==PICT_a8b8g8r8 && pDst->format==PICT_x8b8g8r8))) || + (op == PictOpOver && !pSrc->alphaMap && !pDst->alphaMap && + pSrc->format == pDst->format && + (pSrc->format==PICT_x8r8g8b8 || pSrc->format==PICT_x8b8g8r8))) { if (pSrc->pDrawable->width == 1 && - pSrc->pDrawable->height == 1 && pSrc->repeat && - pSrc->repeatType == RepeatNormal) + pSrc->pDrawable->height == 1 && + pSrc->repeat) { ret = exaTryDriverSolidFill(pSrc, pDst, xSrc, ySrc, xDst, yDst, width, height); if (ret == 1) goto done; } - else if (!pSrc->repeat && !pSrc->transform && - pSrc->format == pDst->format) + else if (pSrcPixmap && !pSrc->repeat && !pSrc->transform) { RegionRec region; @@ -617,6 +651,45 @@ exaComposite(CARD8 op, REGION_UNINIT(pDst->pDrawable->pScreen, ®ion); goto done; } + else if (pSrcPixmap && !pSrc->transform && + pSrc->repeatType == RepeatNormal) + { + RegionRec region; + DDXPointRec srcOrg; + + /* Let's see if the driver can do the repeat in one go */ + if (pExaScr->info->PrepareComposite && !pSrc->alphaMap && + !pDst->alphaMap) + { + ret = exaTryDriverComposite(op, pSrc, pMask, pDst, xSrc, + ySrc, xMask, yMask, xDst, yDst, + width, height); + if (ret == 1) + goto done; + } + + /* Now see if we can use exaFillRegionTiled() */ + xDst += pDst->pDrawable->x; + yDst += pDst->pDrawable->y; + xSrc += pSrc->pDrawable->x; + ySrc += pSrc->pDrawable->y; + + if (!miComputeCompositeRegion (®ion, pSrc, pMask, pDst, xSrc, + ySrc, xMask, yMask, xDst, yDst, + width, height)) + goto done; + + srcOrg.x = (xSrc - xDst) % pSrcPixmap->drawable.width; + srcOrg.y = (ySrc - yDst) % pSrcPixmap->drawable.height; + + ret = exaFillRegionTiled(pDst->pDrawable, ®ion, pSrcPixmap, + &srcOrg, FB_ALLONES, GXcopy); + + REGION_UNINIT(pDst->pDrawable->pScreen, ®ion); + + if (ret) + goto done; + } } } @@ -627,8 +700,8 @@ exaComposite(CARD8 op, pMask->repeat = 0; if (pExaScr->info->PrepareComposite && - (!pSrc->repeat || pSrc->repeat == RepeatNormal) && - (!pMask || !pMask->repeat || pMask->repeat == RepeatNormal) && + (!pSrc->repeat || pSrc->repeatType == RepeatNormal) && + (!pMask || !pMask->repeat || pMask->repeatType == RepeatNormal) && !pSrc->alphaMap && (!pMask || !pMask->alphaMap) && !pDst->alphaMap) { Bool isSrcSolid; @@ -660,39 +733,14 @@ exaComposite(CARD8 op, } } - if (ret != 0) { - ExaMigrationRec pixmaps[3]; - /* failure to accelerate was not due to pixmaps being in the wrong - * locations. - */ - pixmaps[0].as_dst = TRUE; - pixmaps[0].as_src = exaOpReadsDestination(op); - pixmaps[0].pPix = exaGetDrawablePixmap (pDst->pDrawable); - pixmaps[1].as_dst = FALSE; - pixmaps[1].as_src = TRUE; - pixmaps[1].pPix = exaGetDrawablePixmap (pSrc->pDrawable); - if (pMask) { - pixmaps[2].as_dst = FALSE; - pixmaps[2].as_src = TRUE; - pixmaps[2].pPix = exaGetDrawablePixmap (pMask->pDrawable); - exaDoMigration(pixmaps, 3, FALSE); - } else { - exaDoMigration(pixmaps, 2, FALSE); - } - } - fallback: #if DEBUG_TRACE_FALL exaPrintCompositeFallback (op, pSrc, pMask, pDst); #endif + exaDoMigration(pixmaps, npixmaps, FALSE); ExaCheckComposite (op, pSrc, pMask, pDst, xSrc, ySrc, xMask, yMask, xDst, yDst, width, height); - exaDrawableDirty(pDst->pDrawable, - pDst->pDrawable->x + xDst, - pDst->pDrawable->y + yDst, - pDst->pDrawable->x + xDst + width, - pDst->pDrawable->y + yDst + height); done: pSrc->repeat = saveSrcRepeat; @@ -716,6 +764,7 @@ exaRasterizeTrapezoid (PicturePtr pPicture, xTrapezoid *trap, { DrawablePtr pDraw = pPicture->pDrawable; ExaMigrationRec pixmaps[1]; + int xoff, yoff; pixmaps[0].as_dst = TRUE; pixmaps[0].as_src = TRUE; @@ -724,8 +773,10 @@ exaRasterizeTrapezoid (PicturePtr pPicture, xTrapezoid *trap, exaPrepareAccess(pDraw, EXA_PREPARE_DEST); fbRasterizeTrapezoid(pPicture, trap, x_off, y_off); - exaDrawableDirty(pDraw, pDraw->x, pDraw->y, - pDraw->x + pDraw->width, pDraw->y + pDraw->height); + exaGetDrawableDeltas(pDraw, pixmaps[0].pPix, &xoff, &yoff); + exaPixmapDirty(pixmaps[0].pPix, pDraw->x + xoff, pDraw->y + yoff, + pDraw->x + xoff + pDraw->width, + pDraw->y + yoff + pDraw->height); exaFinishAccess(pDraw, EXA_PREPARE_DEST); } @@ -739,6 +790,7 @@ exaAddTriangles (PicturePtr pPicture, INT16 x_off, INT16 y_off, int ntri, { DrawablePtr pDraw = pPicture->pDrawable; ExaMigrationRec pixmaps[1]; + int xoff, yoff; pixmaps[0].as_dst = TRUE; pixmaps[0].as_src = TRUE; @@ -747,8 +799,10 @@ exaAddTriangles (PicturePtr pPicture, INT16 x_off, INT16 y_off, int ntri, exaPrepareAccess(pDraw, EXA_PREPARE_DEST); fbAddTriangles(pPicture, x_off, y_off, ntri, tris); - exaDrawableDirty(pDraw, pDraw->x, pDraw->y, - pDraw->x + pDraw->width, pDraw->y + pDraw->height); + exaGetDrawableDeltas(pDraw, pixmaps[0].pPix, &xoff, &yoff); + exaPixmapDirty(pixmaps[0].pPix, pDraw->x + xoff, pDraw->y + yoff, + pDraw->x + xoff + pDraw->width, + pDraw->y + yoff + pDraw->height); exaFinishAccess(pDraw, EXA_PREPARE_DEST); } @@ -845,10 +899,11 @@ exaGlyphs (CARD8 op, PixmapPtr pPixmap = NULL; PicturePtr pPicture; PixmapPtr pMaskPixmap = NULL; + PixmapPtr pDstPixmap = exaGetDrawablePixmap(pDst->pDrawable); PicturePtr pMask; ScreenPtr pScreen = pDst->pDrawable->pScreen; int width = 0, height = 0; - int x, y; + int x, y, x1, y1, xoff, yoff; int xDst = list->xOff, yDst = list->yOff; int n; int error; @@ -892,7 +947,12 @@ exaGlyphs (CARD8 op, xRectangle rect; miGlyphExtents (nlist, list, glyphs, &extents); - + + extents.x1 = max(extents.x1, 0); + extents.y1 = max(extents.y1, 0); + extents.x2 = min(extents.x2, pDst->pDrawable->width); + extents.y2 = min(extents.y2, pDst->pDrawable->height); + if (extents.x2 <= extents.x1 || extents.y2 <= extents.y1) return; width = extents.x2 - extents.x1; @@ -918,6 +978,7 @@ exaGlyphs (CARD8 op, rect.width = width; rect.height = height; (*pGC->ops->PolyFillRect) (&pMaskPixmap->drawable, pGC, 1, &rect); + exaPixmapDirty(pMaskPixmap, 0, 0, width, height); FreeScratchGC (pGC); x = -extents.x1; y = -extents.y1; @@ -929,6 +990,8 @@ exaGlyphs (CARD8 op, y = 0; } + exaGetDrawableDeltas(pDst->pDrawable, pDstPixmap, &xoff, &yoff); + while (nlist--) { GCPtr pGC = NULL; @@ -983,13 +1046,21 @@ exaGlyphs (CARD8 op, pixmaps[0].as_dst = TRUE; pixmaps[0].as_src = TRUE; pixmaps[0].pPix = pPixmap; - exaDoMigration (pixmaps, 1, TRUE); + exaDoMigration (pixmaps, 1, pExaScr->info->PrepareComposite != NULL); while (n--) { GlyphPtr glyph = *glyphs++; pointer glyphdata = (pointer) (glyph + 1); - + DrawablePtr pCmpDrw = (maskFormat ? pMask : pDst)->pDrawable; + + x1 = x - glyph->info.x; + y1 = y - glyph->info.y; + + if (x1 >= pCmpDrw->width || y1 >= pCmpDrw->height || + (x1 + glyph->info.width) <= 0 || (y1 + glyph->info.height) <= 0) + goto nextglyph; + (*pScreen->ModifyPixmapHeader) (pScratchPixmap, glyph->info.width, glyph->info.height, @@ -1048,17 +1119,22 @@ exaGlyphs (CARD8 op, if (maskFormat) { exaComposite (PictOpAdd, pPicture, NULL, pMask, 0, 0, 0, 0, - x - glyph->info.x, y - glyph->info.y, - glyph->info.width, glyph->info.height); + x1, y1, glyph->info.width, glyph->info.height); + exaPixmapDirty(pMaskPixmap, x1, y1, x1 + glyph->info.width, + y1 + glyph->info.height); } else { exaComposite (op, pSrc, pPicture, pDst, - xSrc + (x - glyph->info.x) - xDst, - ySrc + (y - glyph->info.y) - yDst, - 0, 0, x - glyph->info.x, y - glyph->info.y, - glyph->info.width, glyph->info.height); + xSrc + x1 - xDst, ySrc + y1 - yDst, + 0, 0, x1, y1, glyph->info.width, + glyph->info.height); + x1 += pDst->pDrawable->x + xoff; + y1 += pDst->pDrawable->y + yoff; + exaPixmapDirty(pDstPixmap, x1, y1, x1 + glyph->info.width, + y1 + glyph->info.height); } +nextglyph: x += glyph->info.xOff; y += glyph->info.yOff; } diff --git a/exa/exa_unaccel.c b/exa/exa_unaccel.c index 7713a08..b67ea63 100644 --- a/exa/exa_unaccel.c +++ b/exa/exa_unaccel.c @@ -88,10 +88,15 @@ ExaCheckPutImage (DrawablePtr pDrawable, GCPtr pGC, int depth, int x, int y, int w, int h, int leftPad, int format, char *bits) { + PixmapPtr pPixmap = exaGetDrawablePixmap(pDrawable); + int xoff, yoff; + EXA_FALLBACK(("to %p (%c)\n", pDrawable, exaDrawableLocation(pDrawable))); exaPrepareAccess (pDrawable, EXA_PREPARE_DEST); fbPutImage (pDrawable, pGC, depth, x, y, w, h, leftPad, format, bits); exaFinishAccess (pDrawable, EXA_PREPARE_DEST); + exaGetDrawableDeltas(pDrawable, pPixmap, &xoff, &yoff); + exaPixmapDirty(pPixmap, x + xoff, y + yoff, x + xoff + w, y + yoff + h); } RegionPtr @@ -201,32 +206,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 @@ -385,31 +369,48 @@ ExaCheckComposite (CARD8 op, /** * Gets the 0,0 pixel of a pixmap. Used for doing solid fills of tiled pixmaps * that happen to be 1x1. Pixmap must be at least 8bpp. + * + * XXX This really belongs in fb, so it can be aware of tiling and etc. */ CARD32 exaGetPixmapFirstPixel (PixmapPtr pPixmap) { CARD32 pixel; + void *fb; + Bool need_finish = FALSE; + BoxRec box; ExaMigrationRec pixmaps[1]; + ExaPixmapPriv (pPixmap); + + /* Try to avoid framebuffer readbacks */ + if (exaPixmapIsOffscreen(pPixmap)) { + if (!miPointInRegion(DamageRegion(pExaPixmap->pDamage), 0, 0, &box)) { + fb = pExaPixmap->sys_ptr; + } else { + need_finish = TRUE; + fb = pPixmap->devPrivate.ptr; + pixmaps[0].as_dst = FALSE; + pixmaps[0].as_src = TRUE; + pixmaps[0].pPix = pPixmap; + exaDoMigration (pixmaps, 1, FALSE); + exaPrepareAccess(&pPixmap->drawable, EXA_PREPARE_SRC); + } + } - pixmaps[0].as_dst = FALSE; - pixmaps[0].as_src = TRUE; - pixmaps[0].pPix = pPixmap; - exaDoMigration (pixmaps, 1, FALSE); - - exaPrepareAccess(&pPixmap->drawable, EXA_PREPARE_SRC); switch (pPixmap->drawable.bitsPerPixel) { case 32: - pixel = *(CARD32 *)(pPixmap->devPrivate.ptr); + pixel = *(CARD32 *)fb; break; case 16: - pixel = *(CARD16 *)(pPixmap->devPrivate.ptr); + pixel = *(CARD16 *)fb; break; default: - pixel = *(CARD8 *)(pPixmap->devPrivate.ptr); + pixel = *(CARD8 *)fb; break; } - exaFinishAccess(&pPixmap->drawable, EXA_PREPARE_SRC); + + if (need_finish) + exaFinishAccess(&pPixmap->drawable, EXA_PREPARE_SRC); return pixel; }