diff options
Diffstat (limited to 'exa/exa_accel.c')
-rw-r--r-- | exa/exa_accel.c | 665 |
1 files changed, 316 insertions, 349 deletions
diff --git a/exa/exa_accel.c b/exa/exa_accel.c index feedd49a2..2acade263 100644 --- a/exa/exa_accel.c +++ b/exa/exa_accel.c @@ -55,13 +55,13 @@ exaFillSpans(DrawablePtr pDrawable, GCPtr pGC, int n, pixmaps[0].as_dst = TRUE; pixmaps[0].as_src = FALSE; pixmaps[0].pPix = pPixmap = exaGetDrawablePixmap (pDrawable); + pixmaps[0].pReg = NULL; if (pExaScr->swappedOut || pGC->fillStyle != FillSolid || pPixmap->drawable.width > pExaScr->info->maxX || pPixmap->drawable.height > pExaScr->info->maxY) { - exaDoMigration (pixmaps, 1, FALSE); ExaCheckFillSpans (pDrawable, pGC, n, ppt, pwidth, fSorted); return; } else { @@ -74,7 +74,6 @@ exaFillSpans(DrawablePtr pDrawable, GCPtr pGC, int n, pGC->planemask, pGC->fgPixel)) { - exaDoMigration (pixmaps, 1, FALSE); ExaCheckFillSpans (pDrawable, pGC, n, ppt, pwidth, fSorted); return; } @@ -140,10 +139,11 @@ exaFillSpans(DrawablePtr pDrawable, GCPtr pGC, int n, static Bool exaDoPutImage (DrawablePtr pDrawable, GCPtr pGC, int depth, int x, int y, - int w, int h, int leftPad, int format, char *bits, int src_stride) + int w, int h, int format, char *bits, int src_stride) { ExaScreenPriv (pDrawable->pScreen); - PixmapPtr pPix; + PixmapPtr pPix = exaGetDrawablePixmap (pDrawable); + ExaPixmapPriv(pPix); ExaMigrationRec pixmaps[1]; RegionPtr pClip; BoxPtr pbox; @@ -152,25 +152,28 @@ exaDoPutImage (DrawablePtr pDrawable, GCPtr pGC, int depth, int x, int y, int bpp = pDrawable->bitsPerPixel; Bool access_prepared = FALSE; - 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) - goto migrate_and_fallback; + return FALSE; /* Only accelerate copies: no rop or planemask. */ if (!EXA_PM_IS_SOLID(pDrawable, pGC->planemask) || pGC->alu != GXcopy) - goto migrate_and_fallback; + return FALSE; if (pExaScr->swappedOut) - goto fallback; + return FALSE; + pixmaps[0].as_dst = TRUE; + pixmaps[0].as_src = FALSE; + pixmaps[0].pPix = pPix; + pixmaps[0].pReg = DamagePendingRegion(pExaPixmap->pDamage); exaDoMigration (pixmaps, 1, TRUE); pPix = exaGetOffscreenPixmap (pDrawable, &xoff, &yoff); + if (!pPix || !pExaScr->info->UploadToScreen) + return FALSE; + x += pDrawable->x; y += pDrawable->y; @@ -199,10 +202,8 @@ exaDoPutImage (DrawablePtr pDrawable, GCPtr pGC, int depth, int x, int y, continue; src = bits + (y1 - y) * src_stride + (x1 - x) * (bpp / 8); - ok = (pPix && pExaScr->info->UploadToScreen) ? - pExaScr->info->UploadToScreen(pPix, x1 + xoff, y1 + yoff, - x2 - x1, y2 - y1, src, src_stride) : - FALSE; + ok = pExaScr->info->UploadToScreen(pPix, x1 + xoff, y1 + yoff, + x2 - x1, y2 - y1, src, src_stride); /* If we fail to accelerate the upload, fall back to using unaccelerated * fb calls. */ @@ -213,7 +214,7 @@ exaDoPutImage (DrawablePtr pDrawable, GCPtr pGC, int depth, int x, int y, int dstXoff, dstYoff; if (!access_prepared) { - exaPrepareAccess(pDrawable, EXA_PREPARE_DEST); + ExaDoPrepareAccess(pDrawable, EXA_PREPARE_DEST); access_prepared = TRUE; } @@ -231,54 +232,118 @@ exaDoPutImage (DrawablePtr pDrawable, GCPtr pGC, int depth, int x, int y, y2 - y1, GXcopy, FB_ALLONES, dstBpp); } - - if (access_prepared) - exaFinishAccess(pDrawable, EXA_PREPARE_DEST); - - exaPixmapDirty(pixmaps[0].pPix, x1 + xoff, y1 + yoff, x2 + xoff, y2 + yoff); } - return TRUE; - -migrate_and_fallback: - exaDoMigration (pixmaps, 1, FALSE); + if (access_prepared) + exaFinishAccess(pDrawable, EXA_PREPARE_DEST); + else + exaMarkSync(pDrawable->pScreen); -fallback: - return FALSE; + return TRUE; } -static void -exaPutImage (DrawablePtr pDrawable, GCPtr pGC, int depth, int x, int y, - int w, int h, int leftPad, int format, char *bits) +#ifdef MITSHM + +static Bool +exaDoShmPutImage(DrawablePtr pDrawable, GCPtr pGC, int depth, + unsigned int format, int w, int h, int sx, int sy, int sw, + int sh, int dx, int dy, char *data) { - if (!exaDoPutImage(pDrawable, pGC, depth, x, y, w, h, leftPad, format, bits, - PixmapBytePad(w, pDrawable->depth))) - ExaCheckPutImage(pDrawable, pGC, depth, x, y, w, h, leftPad, format, - bits); -} + int src_stride = PixmapBytePad(w, depth); -#ifdef MITSHM + if (exaDoPutImage(pDrawable, pGC, depth, dx, dy, sw, sh, format, data + + sy * src_stride + sx * BitsPerPixel(depth) / 8, + src_stride)) + return TRUE; -static void + if (format == ZPixmap) + { + PixmapPtr pPixmap; + + pPixmap = GetScratchPixmapHeader(pDrawable->pScreen, w, h, depth, + BitsPerPixel(depth), PixmapBytePad(w, depth), (pointer)data); + if (!pPixmap) + return FALSE; + + if (exaGCReadsDestination(pDrawable, pGC->planemask, pGC->fillStyle, + pGC->alu)) + exaPrepareAccess (pDrawable, EXA_PREPARE_DEST); + else + ExaDoPrepareAccess (pDrawable, EXA_PREPARE_DEST); + fbCopyArea((DrawablePtr)pPixmap, pDrawable, pGC, sx, sy, sw, sh, dx, dy); + exaFinishAccess(pDrawable, EXA_PREPARE_DEST); + + FreeScratchPixmapHeader(pPixmap); + + return TRUE; + } + + return FALSE; +} + +/* The actual ShmPutImage isn't wrapped by the damage layer, so we need to + * inform any interested parties of the damage incurred to the drawable. + * + * We also need to set the pending damage to ensure correct migration in all + * cases. + */ +void exaShmPutImage(DrawablePtr pDrawable, GCPtr pGC, int depth, unsigned int format, int w, int h, int sx, int sy, int sw, int sh, int dx, int dy, char *data) { - int src_stride = PixmapBytePad(w, depth); + PixmapPtr pPixmap = exaGetDrawablePixmap(pDrawable); + ExaPixmapPriv(pPixmap); + BoxRec box = { .x1 = pDrawable->x + dx, .y1 = pDrawable->y + dy, + .x2 = pDrawable->x + dx + sw, .y2 = pDrawable->y + dy + sh }; + RegionRec region; + int xoff, yoff; + RegionPtr pending_damage = DamagePendingRegion(pExaPixmap->pDamage); - if (exaDoPutImage(pDrawable, pGC, depth, dx, dy, sw, sh, 0, format, data + - sy * src_stride + sx * BitsPerPixel(depth) / 8, - src_stride)) - return; + REGION_INIT(pScreen, ®ion, &box, 1); + + exaGetDrawableDeltas(pDrawable, pPixmap, &xoff, &yoff); + + REGION_TRANSLATE(pScreen, ®ion, xoff, yoff); + REGION_UNION(pScreen, pending_damage, pending_damage, ®ion); + + if (!exaDoShmPutImage(pDrawable, pGC, depth, format, w, h, sx, sy, sw, sh, + dx, dy, data)) { + if (exaGCReadsDestination(pDrawable, pGC->planemask, pGC->fillStyle, + pGC->alu)) + exaPrepareAccess (pDrawable, EXA_PREPARE_DEST); + else + ExaDoPrepareAccess (pDrawable, EXA_PREPARE_DEST); + fbShmPutImage(pDrawable, pGC, depth, format, w, h, sx, sy, sw, sh, dx, dy, + data); + exaFinishAccess(pDrawable, EXA_PREPARE_DEST); + } + + REGION_TRANSLATE(pScreen, ®ion, -xoff, -yoff); + DamageDamageRegion(pDrawable, ®ion); - fbShmPutImage(pDrawable, pGC, depth, format, w, h, sx, sy, sw, sh, dx, dy, - data); + REGION_UNINIT(pScreen, ®ion); } ShmFuncs exaShmFuncs = { NULL, exaShmPutImage }; #endif +static void +exaPutImage (DrawablePtr pDrawable, GCPtr pGC, int depth, int x, int y, + int w, int h, int leftPad, int format, char *bits) +{ +#ifdef MITSHM + if (!exaDoShmPutImage(pDrawable, pGC, depth, format, w, h, 0, 0, w, h, x, y, + bits)) +#else + if (!exaDoPutImage(pDrawable, pGC, depth, x, y, w, h, format, bits, + PixmapBytePad(w, pDrawable->depth))) +#endif + ExaCheckPutImage(pDrawable, pGC, depth, x, y, w, h, leftPad, format, + bits); +} + static Bool inline exaCopyNtoNTwoDir (DrawablePtr pSrcDrawable, DrawablePtr pDstDrawable, GCPtr pGC, BoxPtr pbox, int nbox, int dx, int dy) @@ -393,8 +458,6 @@ exaCopyNtoNTwoDir (DrawablePtr pSrcDrawable, DrawablePtr pDstDrawable, dst_off_y + pbox->y1 + i, pbox->x2 - pbox->x1, 1); } - exaPixmapDirty(pDstPixmap, dst_off_x + pbox->x1, dst_off_y + pbox->y1, - dst_off_x + pbox->x2, dst_off_y + pbox->y2); } if (dirsetup != 0) pExaScr->info->DoneCopy(pDstPixmap); @@ -420,14 +483,49 @@ exaCopyNtoN (DrawablePtr pSrcDrawable, int src_off_x, src_off_y; int dst_off_x, dst_off_y; ExaMigrationRec pixmaps[2]; - Bool fallback = FALSE; + RegionPtr region = NULL; + + 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 (!pGC || !exaGCReadsDestination(pDstDrawable, pGC->planemask, + pGC->fillStyle, pGC->alu)) { + xRectangle *rects = ALLOCATE_LOCAL(nbox * sizeof(xRectangle)); + + if (rects) { + int i; + + for (i = 0; i < nbox; i++) { + rects[i].x = pbox[i].x1 + dst_off_x; + rects[i].y = pbox[i].y1 + dst_off_y; + rects[i].width = pbox[i].x2 - pbox[i].x1; + rects[i].height = pbox[i].y2 - pbox[i].y1; + } + + region = RECTS_TO_REGION(pScreen, nbox, rects, CT_YXBANDED); + DEALLOCATE_LOCAL(rects); + + if (region) { + src_off_x -= dst_off_x; + src_off_y -= dst_off_y; + dst_off_x = dst_off_y = 0; + pbox = REGION_RECTS(region); + nbox = REGION_NUM_RECTS(region); + } + } + } pixmaps[0].as_dst = TRUE; pixmaps[0].as_src = FALSE; - pixmaps[0].pPix = pDstPixmap = exaGetDrawablePixmap (pDstDrawable); + pixmaps[0].pPix = pDstPixmap; + pixmaps[0].pReg = region; pixmaps[1].as_dst = FALSE; pixmaps[1].as_src = TRUE; - pixmaps[1].pPix = pSrcPixmap = exaGetDrawablePixmap (pSrcDrawable); + pixmaps[1].pPix = pSrcPixmap; + pixmaps[1].pReg = NULL; /* Respect maxX/maxY in a trivial way: don't set up drawing when we might * violate the limits. The proper solution would be a temporary pixmap @@ -438,64 +536,60 @@ exaCopyNtoN (DrawablePtr pSrcDrawable, pDstPixmap->drawable.width > pExaScr->info->maxX || pDstPixmap->drawable.height > pExaScr->info->maxY) { - fallback = TRUE; + goto fallback; } else { exaDoMigration (pixmaps, 2, TRUE); } /* Mixed directions must be handled specially if the card is lame */ - if (!fallback && (pExaScr->info->flags & EXA_TWO_BITBLT_DIRECTIONS) && + if ((pExaScr->info->flags & EXA_TWO_BITBLT_DIRECTIONS) && reverse != upsidedown) { if (exaCopyNtoNTwoDir(pSrcDrawable, pDstDrawable, pGC, pbox, nbox, dx, dy)) - return; - fallback = TRUE; + goto out; + goto fallback; } - 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) || + if (!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); + goto fallback; } 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); + (*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); pbox++; } - if (fallback) - return; - (*pExaScr->info->DoneCopy) (pDstPixmap); exaMarkSync (pDstDrawable->pScreen); + + goto out; + +fallback: + EXA_FALLBACK(("from %p to %p (%c,%c)\n", pSrcDrawable, pDstDrawable, + exaDrawableLocation(pSrcDrawable), + exaDrawableLocation(pDstDrawable))); + exaPrepareAccessReg (pDstDrawable, EXA_PREPARE_DEST, region); + 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); + +out: + if (region) { + REGION_UNINIT(pScreen, region); + REGION_DESTROY(pScreen, region); + } } RegionPtr @@ -688,7 +782,8 @@ exaPolyFillRect(DrawablePtr pDrawable, pixmaps[0].as_dst = TRUE; pixmaps[0].as_src = FALSE; pixmaps[0].pPix = pPixmap; - + pixmaps[0].pReg = NULL; + exaGetDrawableDeltas(pDrawable, pPixmap, &xoff, &yoff); if (pExaScr->swappedOut || @@ -731,15 +826,6 @@ exaPolyFillRect(DrawablePtr pDrawable, 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); goto out; } @@ -818,101 +904,11 @@ fallback: exaMarkSync(pDrawable->pScreen); out: + REGION_UNINIT(pScreen, pReg); REGION_DESTROY(pScreen, pReg); } static void -exaSolidBoxClipped (DrawablePtr pDrawable, - RegionPtr pClip, - FbBits pm, - FbBits fg, - int x1, - int y1, - int x2, - int y2) -{ - ExaScreenPriv (pDrawable->pScreen); - PixmapPtr pPixmap; - BoxPtr pbox; - int nbox; - int xoff, yoff; - int partX1, partX2, partY1, partY2; - ExaMigrationRec pixmaps[1]; - Bool fallback = FALSE; - - pixmaps[0].as_dst = TRUE; - pixmaps[0].as_src = FALSE; - pixmaps[0].pPix = pPixmap = exaGetDrawablePixmap (pDrawable); - - if (pExaScr->swappedOut || - pPixmap->drawable.width > pExaScr->info->maxX || - pPixmap->drawable.height > pExaScr->info->maxY) - { - fallback = TRUE; - } else { - exaDoMigration (pixmaps, 1, TRUE); - } - - exaGetDrawableDeltas (pDrawable, pPixmap, &xoff, &yoff); - - if (fallback || !exaPixmapIsOffscreen(pPixmap) || - !(*pExaScr->info->PrepareSolid) (pPixmap, GXcopy, pm, fg)) - { - 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); - fbSolidBoxClipped (pDrawable, pClip, x1, y1, x2, y2, - fbAnd (GXcopy, fg, pm), - fbXor (GXcopy, fg, pm)); - exaFinishAccess (pDrawable, EXA_PREPARE_DEST); - } - for (nbox = REGION_NUM_RECTS(pClip), pbox = REGION_RECTS(pClip); - nbox--; - pbox++) - { - partX1 = pbox->x1; - if (partX1 < x1) - partX1 = x1; - - partX2 = pbox->x2; - if (partX2 > x2) - partX2 = x2; - - if (partX2 <= partX1) - continue; - - partY1 = pbox->y1; - if (partY1 < y1) - partY1 = y1; - - partY2 = pbox->y2; - if (partY2 > y2) - partY2 = y2; - - if (partY2 <= partY1) - continue; - - if (!fallback) { - (*pExaScr->info->Solid) (pPixmap, - partX1 + xoff, partY1 + yoff, - partX2 + xoff, partY2 + yoff); - } - - exaPixmapDirty (pPixmap, partX1 + xoff, partY1 + yoff, partX2 + xoff, - partY2 + yoff); - } - - if (fallback) - return; - - (*pExaScr->info->DoneSolid) (pPixmap); - exaMarkSync(pDrawable->pScreen); -} - -static void exaImageGlyphBlt (DrawablePtr pDrawable, GCPtr pGC, int x, @@ -928,7 +924,6 @@ exaImageGlyphBlt (DrawablePtr pDrawable, int gWidth, gHeight; /* width and height of glyph */ FbStride gStride; /* stride of glyph */ Bool opaque; - int n; int gx, gy; void (*glyph) (FbBits *, FbStride, @@ -942,37 +937,33 @@ exaImageGlyphBlt (DrawablePtr pDrawable, int dstBpp; int dstXoff, dstYoff; FbBits depthMask; + Bool fallback; PixmapPtr pPixmap = exaGetDrawablePixmap(pDrawable); + ExaPixmapPriv(pPixmap); 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); + RegionPtr pending_damage = DamagePendingRegion(pExaPixmap->pDamage); + BoxRec extents = *REGION_EXTENTS(pScreen, pending_damage); + int xoff, yoff; - if (xBack >= pDrawable->width || yBack >= pDrawable->height || - (xBack + widthBack) <= 0 || (yBack + heightBack) <= 0) + if (extents.x1 >= extents.x2 || extents.y1 >= extents.y2) return; + depthMask = FbFullMask(pDrawable->depth); + fallback = (pGC->planemask & depthMask) != depthMask; + pixmaps[0].as_dst = TRUE; - pixmaps[0].as_src = TRUE; + pixmaps[0].as_src = FALSE; pixmaps[0].pPix = pPixmap; + pixmaps[0].pReg = fallback ? NULL : pending_damage; - depthMask = FbFullMask(pDrawable->depth); - if ((pGC->planemask & depthMask) != depthMask) + exaDoMigration(pixmaps, 1, FALSE); + + if (fallback) { - exaDoMigration(pixmaps, 1, FALSE); ExaCheckImageGlyphBlt(pDrawable, pGC, x, y, nglyph, ppciInit, pglyphBase); - goto damage; + return; } + glyph = NULL; switch (pDrawable->bitsPerPixel) { case 8: glyph = fbGlyph8; break; @@ -983,8 +974,14 @@ exaImageGlyphBlt (DrawablePtr pDrawable, x += pDrawable->x; y += pDrawable->y; - xBack += pDrawable->x; - yBack += pDrawable->y; + + exaGetDrawableDeltas(pDrawable, pPixmap, &xoff, &yoff); + extents.x1 -= xoff; + extents.x2 -= xoff; + extents.y1 -= yoff; + extents.y2 -= yoff; + + exaPrepareAccessReg (pDrawable, EXA_PREPARE_DEST, pixmaps[0].pReg); if (TERMINALFONT (pGC->font) && !glyph) { @@ -992,20 +989,22 @@ exaImageGlyphBlt (DrawablePtr pDrawable, } else { - exaSolidBoxClipped (pDrawable, - fbGetCompositeClip(pGC), - pGC->planemask, - pGC->bgPixel, - xBack, - yBack, - xBack + widthBack, - yBack + heightBack); + FbBits fg = fbReplicatePixel (pGC->bgPixel, pDrawable->bitsPerPixel); + + fbSolidBoxClipped (pDrawable, + fbGetCompositeClip(pGC), + extents.x1, + extents.y1, + extents.x2, + extents.y2, + fbAnd (GXcopy, fg, pGC->planemask), + fbXor (GXcopy, fg, pGC->planemask)); + opaque = FALSE; } 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); @@ -1018,9 +1017,9 @@ exaImageGlyphBlt (DrawablePtr pDrawable, 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)) + if (!gWidth || !gHeight || (gx + gWidth) <= extents.x1 || + (gy + gHeight) <= extents.y1 || gx >= extents.x2 || + gy >= extents.y2) continue; pglyph = FONTGLYPHBITS(pglyphBase, pci); @@ -1043,11 +1042,6 @@ exaImageGlyphBlt (DrawablePtr pDrawable, } 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 = { @@ -1111,13 +1105,16 @@ exaFillRegionSolid (DrawablePtr pDrawable, PixmapPtr pPixmap; int xoff, yoff; ExaMigrationRec pixmaps[1]; - int nbox = REGION_NUM_RECTS (pRegion); - BoxPtr pBox = REGION_RECTS (pRegion); pixmaps[0].as_dst = TRUE; pixmaps[0].as_src = FALSE; pixmaps[0].pPix = pPixmap = exaGetDrawablePixmap (pDrawable); - + pixmaps[0].pReg = exaGCReadsDestination(pDrawable, planemask, FillSolid, + alu) ? NULL : pRegion; + + exaGetDrawableDeltas(pDrawable, pPixmap, &xoff, &yoff); + REGION_TRANSLATE(pScreen, pRegion, xoff, yoff); + if (pPixmap->drawable.width > pExaScr->info->maxX || pPixmap->drawable.height > pExaScr->info->maxY) { @@ -1129,29 +1126,56 @@ exaFillRegionSolid (DrawablePtr pDrawable, if ((pPixmap = exaGetOffscreenPixmap (pDrawable, &xoff, &yoff)) && (*pExaScr->info->PrepareSolid) (pPixmap, alu, planemask, pixel)) { + int nbox; + BoxPtr pBox; + + nbox = REGION_NUM_RECTS (pRegion); + pBox = REGION_RECTS (pRegion); + while (nbox--) { - (*pExaScr->info->Solid) (pPixmap, - pBox->x1 + xoff, pBox->y1 + yoff, - pBox->x2 + xoff, pBox->y2 + yoff); + (*pExaScr->info->Solid) (pPixmap, pBox->x1, pBox->y1, pBox->x2, + pBox->y2); pBox++; } (*pExaScr->info->DoneSolid) (pPixmap); exaMarkSync(pDrawable->pScreen); + + if (pDrawable->width == 1 && pDrawable->height == 1 && + pDrawable->bitsPerPixel != 24) { + ExaPixmapPriv(pPixmap); + + switch (pDrawable->bitsPerPixel) { + case 32: + *(CARD32*)pExaPixmap->sys_ptr = pixel; + break; + case 16: + *(CARD16*)pExaPixmap->sys_ptr = pixel; + break; + case 8: + *(CARD8*)pExaPixmap->sys_ptr = pixel; + } + + REGION_UNION(pScreen, &pExaPixmap->validSys, &pExaPixmap->validSys, + pRegion); + } + + REGION_TRANSLATE(pScreen, pRegion, -xoff, -yoff); + return TRUE; } - 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); + if (alu != GXcopy || !EXA_PM_IS_SOLID(pDrawable, planemask)) { + REGION_TRANSLATE(pScreen, pRegion, -xoff, -yoff); + return FALSE; } + EXA_FALLBACK(("to %p (%c)\n", pDrawable, + exaDrawableLocation(pDrawable))); + exaPrepareAccessReg (pDrawable, EXA_PREPARE_DEST, pixmaps[0].pReg); + REGION_TRANSLATE(pScreen, pRegion, -xoff, -yoff); + fbFillRegionSolid (pDrawable, pRegion, 0, + fbReplicatePixel (pixel, pDrawable->bitsPerPixel)); + exaFinishAccess (pDrawable, EXA_PREPARE_DEST); return TRUE; } @@ -1189,9 +1213,15 @@ exaFillRegionTiled (DrawablePtr pDrawable, pixmaps[0].as_dst = TRUE; pixmaps[0].as_src = FALSE; pixmaps[0].pPix = pPixmap = exaGetDrawablePixmap (pDrawable); + pixmaps[0].pReg = exaGCReadsDestination(pDrawable, planemask, FillTiled, + alu) ? NULL : pRegion; pixmaps[1].as_dst = FALSE; pixmaps[1].as_src = TRUE; pixmaps[1].pPix = pTile; + pixmaps[1].pReg = NULL; + + exaGetDrawableDeltas(pDrawable, pPixmap, &xoff, &yoff); + REGION_TRANSLATE(pScreen, pRegion, xoff, yoff); if (pPixmap->drawable.width > pExaScr->info->maxX || pPixmap->drawable.height > pExaScr->info->maxY || @@ -1221,7 +1251,7 @@ exaFillRegionTiled (DrawablePtr pDrawable, int dstY = pBox->y1; int tileY; - tileY = (dstY - pDrawable->y - pPatOrg->y) % tileHeight; + tileY = (dstY - yoff - pDrawable->y - pPatOrg->y) % tileHeight; while (height > 0) { int width = pBox->x2 - pBox->x1; int dstX = pBox->x1; @@ -1232,7 +1262,7 @@ exaFillRegionTiled (DrawablePtr pDrawable, h = height; height -= h; - tileX = (dstX - pDrawable->x - pPatOrg->x) % tileWidth; + tileX = (dstX - xoff - pDrawable->x - pPatOrg->x) % tileWidth; while (width > 0) { int w = tileWidth - tileX; if (w > width) @@ -1241,8 +1271,7 @@ exaFillRegionTiled (DrawablePtr pDrawable, (*pExaScr->info->Copy) (pPixmap, tileX + tileXoff, tileY + tileYoff, - dstX + xoff, dstY + yoff, - w, h); + dstX, dstY, w, h); dstX += w; tileX = 0; } @@ -1253,17 +1282,20 @@ exaFillRegionTiled (DrawablePtr pDrawable, } (*pExaScr->info->DoneCopy) (pPixmap); exaMarkSync(pDrawable->pScreen); + REGION_TRANSLATE(pScreen, pRegion, -xoff, -yoff); return TRUE; } fallback: - if (alu != GXcopy || planemask != FB_ALLONES) + if (alu != GXcopy || !EXA_PM_IS_SOLID(pDrawable, planemask)) { + REGION_TRANSLATE(pScreen, pRegion, -xoff, -yoff); 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); + exaPrepareAccessReg (pDrawable, EXA_PREPARE_DEST, pixmaps[0].pReg); + REGION_TRANSLATE(pScreen, pRegion, -xoff, -yoff); exaPrepareAccess ((DrawablePtr)pTile, EXA_PREPARE_SRC); fbFillRegionTiled (pDrawable, pRegion, pTile); exaFinishAccess ((DrawablePtr)pTile, EXA_PREPARE_SRC); @@ -1272,77 +1304,13 @@ fallback: return TRUE; } -void -exaPaintWindow(WindowPtr pWin, RegionPtr pRegion, int what) -{ - ExaScreenPriv (pWin->drawable.pScreen); - 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) { - case None: - return; - case ParentRelative: - do { - pWin = pWin->parent; - } while (pWin->backgroundState == ParentRelative); - (*pWin->drawable.pScreen->PaintWindowBackground)(pWin, pRegion, - what); - return; - case BackgroundPixel: - exaFillRegionSolid((DrawablePtr)pWin, pRegion, pWin->background.pixel, - FB_ALLONES, GXcopy); - goto damage; - case BackgroundPixmap: - 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, - FB_ALLONES, GXcopy); - goto damage; - } else { - 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++; - } -} /** * Accelerates GetImage for solid ZPixmap downloads from framebuffer memory. * * This is probably the only case we actually care about. The rest fall through - * to migration and ExaCheckGetImage, which hopefully will result in migration - * pushing the pixmap out of framebuffer. + * to migration and fbGetImage, which hopefully will result in migration pushing + * the pixmap out of framebuffer. */ void exaGetImage (DrawablePtr pDrawable, int x, int y, int w, int h, @@ -1350,63 +1318,62 @@ exaGetImage (DrawablePtr pDrawable, int x, int y, int w, int h, { ExaScreenPriv (pDrawable->pScreen); ExaMigrationRec pixmaps[1]; + BoxRec Box; + RegionRec Reg; PixmapPtr pPix; int xoff, yoff; Bool ok; - if (pExaScr->swappedOut || (w == 1 && h == 1)) + pixmaps[0].as_dst = FALSE; + pixmaps[0].as_src = TRUE; + pixmaps[0].pPix = pPix = exaGetDrawablePixmap (pDrawable); + pixmaps[0].pReg = &Reg; + + exaGetDrawableDeltas (pDrawable, pPix, &xoff, &yoff); + + Box.x1 = pDrawable->y + x + xoff; + Box.y1 = pDrawable->y + y + yoff; + Box.x2 = Box.x1 + w; + Box.y2 = Box.y1 + h; + + REGION_INIT(pScreen, &Reg, &Box, 1); + + if (pExaScr->swappedOut) goto fallback; - if (pExaScr->info->DownloadFromScreen == NULL) + exaDoMigration(pixmaps, 1, FALSE); + + pPix = exaGetOffscreenPixmap (pDrawable, &xoff, &yoff); + + if (pPix == NULL || pExaScr->info->DownloadFromScreen == NULL) goto fallback; /* Only cover the ZPixmap, solid copy case. */ if (format != ZPixmap || !EXA_PM_IS_SOLID(pDrawable, planeMask)) - goto migrate_and_fallback; + goto fallback; /* Only try to handle the 8bpp and up cases, since we don't want to think * about <8bpp. */ if (pDrawable->bitsPerPixel < 8) - goto migrate_and_fallback; - - pPix = exaGetOffscreenPixmap (pDrawable, &xoff, &yoff); - if (pPix == NULL) goto fallback; - xoff += pDrawable->x; - yoff += pDrawable->y; - - ok = pExaScr->info->DownloadFromScreen(pPix, x + xoff, y + yoff, w, h, d, + ok = pExaScr->info->DownloadFromScreen(pPix, pDrawable->x + x + xoff, + pDrawable->y + y + yoff, w, h, d, PixmapBytePad(w, pDrawable->depth)); if (ok) { exaWaitSync(pDrawable->pScreen); - return; + goto out; } -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); -} - -/** - * GetSpans isn't accelerated yet, but performs migration so that we'll - * hopefully avoid the read-from-framebuffer cost. - */ -void -exaGetSpans (DrawablePtr pDrawable, int wMax, DDXPointPtr ppt, int *pwidth, - int nspans, char *pdstStart) -{ - ExaMigrationRec pixmaps[1]; + EXA_FALLBACK(("from %p (%c)\n", pDrawable, + exaDrawableLocation(pDrawable))); - pixmaps[0].as_dst = FALSE; - pixmaps[0].as_src = TRUE; - pixmaps[0].pPix = exaGetDrawablePixmap (pDrawable); - exaDoMigration (pixmaps, 1, FALSE); + exaPrepareAccessReg (pDrawable, EXA_PREPARE_SRC, &Reg); + fbGetImage (pDrawable, x, y, w, h, format, planeMask, d); + exaFinishAccess (pDrawable, EXA_PREPARE_SRC); - ExaCheckGetSpans (pDrawable, wMax, ppt, pwidth, nspans, pdstStart); +out: + REGION_UNINIT(pScreen, &Reg); } |