aboutsummaryrefslogtreecommitdiff
path: root/xorg-server/exa/exa_accel.c
diff options
context:
space:
mode:
Diffstat (limited to 'xorg-server/exa/exa_accel.c')
-rw-r--r--xorg-server/exa/exa_accel.c340
1 files changed, 195 insertions, 145 deletions
diff --git a/xorg-server/exa/exa_accel.c b/xorg-server/exa/exa_accel.c
index dac6e6c79..33fbb9843 100644
--- a/xorg-server/exa/exa_accel.c
+++ b/xorg-server/exa/exa_accel.c
@@ -50,12 +50,6 @@ exaFillSpans(DrawablePtr pDrawable, GCPtr pGC, int n,
int fullX1, fullX2, fullY1;
int partX1, partX2;
int off_x, off_y;
- ExaMigrationRec pixmaps[1];
-
- pixmaps[0].as_dst = TRUE;
- pixmaps[0].as_src = FALSE;
- pixmaps[0].pPix = pPixmap;
- pixmaps[0].pReg = NULL;
if (pExaScr->swappedOut ||
pGC->fillStyle != FillSolid ||
@@ -63,7 +57,16 @@ exaFillSpans(DrawablePtr pDrawable, GCPtr pGC, int n,
{
ExaCheckFillSpans (pDrawable, pGC, n, ppt, pwidth, fSorted);
return;
- } else {
+ }
+
+ if (pExaScr->do_migration) {
+ ExaMigrationRec pixmaps[1];
+
+ pixmaps[0].as_dst = TRUE;
+ pixmaps[0].as_src = FALSE;
+ pixmaps[0].pPix = pPixmap;
+ pixmaps[0].pReg = NULL;
+
exaDoMigration (pixmaps, 1, TRUE);
}
@@ -148,9 +151,9 @@ exaDoPutImage (DrawablePtr pDrawable, GCPtr pGC, int depth, int x, int y,
int nbox;
int xoff, yoff;
int bpp = pDrawable->bitsPerPixel;
- Bool access_prepared = FALSE;
+ Bool ret = TRUE;
- if (pExaPixmap->accel_blocked)
+ if (pExaPixmap->accel_blocked || !pExaScr->info->UploadToScreen)
return FALSE;
/* Don't bother with under 8bpp, XYPixmaps. */
@@ -164,10 +167,10 @@ exaDoPutImage (DrawablePtr pDrawable, GCPtr pGC, int depth, int x, int y,
if (pExaScr->swappedOut)
return FALSE;
- if (pExaPixmap->pDamage) {
+ if (pExaScr->do_migration) {
ExaMigrationRec pixmaps[1];
- pixmaps[0].as_dst = TRUE;
+ pixmaps[0].as_dst = TRUE;
pixmaps[0].as_src = FALSE;
pixmaps[0].pPix = pPix;
pixmaps[0].pReg = DamagePendingRegion(pExaPixmap->pDamage);
@@ -177,7 +180,7 @@ exaDoPutImage (DrawablePtr pDrawable, GCPtr pGC, int depth, int x, int y,
pPix = exaGetOffscreenPixmap (pDrawable, &xoff, &yoff);
- if (!pPix || !pExaScr->info->UploadToScreen)
+ if (!pPix)
return FALSE;
x += pDrawable->x;
@@ -210,42 +213,19 @@ exaDoPutImage (DrawablePtr pDrawable, GCPtr pGC, int depth, int x, int y,
src = bits + (y1 - y) * src_stride + (x1 - x) * (bpp / 8);
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.
+ /* We have to fall back completely, and ignore what has already been completed.
+ * Messing with the fb layer directly like we used to is completely unacceptable.
*/
if (!ok) {
- FbStip *dst;
- FbStride dst_stride;
- int dstBpp;
- int dstXoff, dstYoff;
-
- if (!access_prepared) {
- ExaDoPrepareAccess(pDrawable, EXA_PREPARE_DEST);
-
- access_prepared = TRUE;
- }
-
- fbGetStipDrawable(pDrawable, dst, dst_stride, dstBpp,
- dstXoff, dstYoff);
-
- fbBltStip((FbStip *)bits + (y1 - y) * (src_stride / sizeof(FbStip)),
- src_stride / sizeof(FbStip),
- (x1 - x) * dstBpp,
- dst + (y1 + dstYoff) * dst_stride,
- dst_stride,
- (x1 + dstXoff) * dstBpp,
- (x2 - x1) * dstBpp,
- y2 - y1,
- GXcopy, FB_ALLONES, dstBpp);
+ ret = FALSE;
+ break;
}
}
- if (access_prepared)
- exaFinishAccess(pDrawable, EXA_PREPARE_DEST);
- else
+ if (ret)
exaMarkSync(pDrawable->pScreen);
- return TRUE;
+ return ret;
}
static void
@@ -379,8 +359,8 @@ exaCopyNtoNTwoDir (DrawablePtr pSrcDrawable, DrawablePtr pDstDrawable,
return TRUE;
}
-void
-exaCopyNtoN (DrawablePtr pSrcDrawable,
+Bool
+exaHWCopyNtoN (DrawablePtr pSrcDrawable,
DrawablePtr pDstDrawable,
GCPtr pGC,
BoxPtr pbox,
@@ -388,22 +368,20 @@ exaCopyNtoN (DrawablePtr pSrcDrawable,
int dx,
int dy,
Bool reverse,
- Bool upsidedown,
- Pixel bitplane,
- void *closure)
+ Bool upsidedown)
{
ExaScreenPriv (pDstDrawable->pScreen);
PixmapPtr pSrcPixmap, pDstPixmap;
ExaPixmapPrivPtr pSrcExaPixmap, pDstExaPixmap;
int src_off_x, src_off_y;
int dst_off_x, dst_off_y;
- ExaMigrationRec pixmaps[2];
RegionPtr srcregion = NULL, dstregion = NULL;
xRectangle *rects;
+ Bool ret = TRUE;
/* avoid doing copy operations if no boxes */
if (nbox == 0)
- return;
+ return TRUE;
pSrcPixmap = exaGetDrawablePixmap (pSrcDrawable);
pDstPixmap = exaGetDrawablePixmap (pDstDrawable);
@@ -446,14 +424,6 @@ exaCopyNtoN (DrawablePtr pSrcDrawable,
}
}
- pixmaps[0].as_dst = TRUE;
- pixmaps[0].as_src = FALSE;
- pixmaps[0].pPix = pDstPixmap;
- pixmaps[0].pReg = dstregion;
- pixmaps[1].as_dst = FALSE;
- pixmaps[1].as_src = TRUE;
- pixmaps[1].pPix = pSrcPixmap;
- pixmaps[1].pReg = srcregion;
pSrcExaPixmap = ExaGetPixmapPriv (pSrcPixmap);
pDstExaPixmap = ExaGetPixmapPriv (pDstPixmap);
@@ -487,7 +457,20 @@ exaCopyNtoN (DrawablePtr pSrcDrawable,
}
}
- exaDoMigration (pixmaps, 2, TRUE);
+ if (pExaScr->do_migration) {
+ ExaMigrationRec pixmaps[2];
+
+ pixmaps[0].as_dst = TRUE;
+ pixmaps[0].as_src = FALSE;
+ pixmaps[0].pPix = pDstPixmap;
+ pixmaps[0].pReg = dstregion;
+ pixmaps[1].as_dst = FALSE;
+ pixmaps[1].as_src = TRUE;
+ pixmaps[1].pPix = pSrcPixmap;
+ pixmaps[1].pReg = srcregion;
+
+ exaDoMigration (pixmaps, 2, TRUE);
+ }
/* Mixed directions must be handled specially if the card is lame */
if ((pExaScr->info->flags & EXA_TWO_BITBLT_DIRECTIONS) &&
@@ -498,40 +481,64 @@ exaCopyNtoN (DrawablePtr pSrcDrawable,
goto fallback;
}
- 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)) {
- goto fallback;
- }
+ if (exaPixmapIsOffscreen(pDstPixmap)) {
+ /* Normal blitting. */
+ if (exaPixmapIsOffscreen(pSrcPixmap)) {
+ if (!(*pExaScr->info->PrepareCopy) (pSrcPixmap, pDstPixmap, reverse ? -1 : 1,
+ upsidedown ? -1 : 1,
+ pGC ? pGC->alu : GXcopy,
+ pGC ? pGC->planemask : FB_ALLONES)) {
+ goto fallback;
+ }
- while (nbox--)
- {
- (*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++;
- }
+ while (nbox--)
+ {
+ (*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++;
+ }
- (*pExaScr->info->DoneCopy) (pDstPixmap);
- exaMarkSync (pDstDrawable->pScreen);
+ (*pExaScr->info->DoneCopy) (pDstPixmap);
+ exaMarkSync (pDstDrawable->pScreen);
+ /* UTS: mainly for SHM PutImage's secondary path. */
+ } else {
+ int bpp = pSrcDrawable->bitsPerPixel;
+ int src_stride = exaGetPixmapPitch(pSrcPixmap);
+ CARD8 *src = NULL;
+
+ if (!pExaScr->info->UploadToScreen)
+ goto fallback;
+
+ if (pSrcDrawable->bitsPerPixel != pDstDrawable->bitsPerPixel)
+ goto fallback;
+
+ if (pSrcDrawable->bitsPerPixel < 8)
+ goto fallback;
+
+ if (pGC && !(pGC->alu == GXcopy && EXA_PM_IS_SOLID(pSrcDrawable, pGC->planemask)))
+ goto fallback;
+
+ while (nbox--)
+ {
+ src = pSrcExaPixmap->sys_ptr + (pbox->y1 + dy + src_off_y) * src_stride + (pbox->x1 + dx + src_off_x) * (bpp / 8);
+ if (!pExaScr->info->UploadToScreen(pDstPixmap, pbox->x1 + dst_off_x,
+ pbox->y1 + dst_off_y, pbox->x2 - pbox->x1, pbox->y2 - pbox->y1,
+ (char *) src, src_stride))
+ goto fallback;
+
+ pbox++;
+ }
+ }
+ } else
+ goto fallback;
goto out;
fallback:
- EXA_FALLBACK(("from %p to %p (%c,%c)\n", pSrcDrawable, pDstDrawable,
- exaDrawableLocation(pSrcDrawable),
- exaDrawableLocation(pDstDrawable)));
- exaPrepareAccessReg (pDstDrawable, EXA_PREPARE_DEST, dstregion);
- exaPrepareAccessReg (pSrcDrawable, EXA_PREPARE_SRC, srcregion);
- fbCopyNtoN (pSrcDrawable, pDstDrawable, pGC, pbox, nbox, dx, dy, reverse,
- upsidedown, bitplane, closure);
- exaFinishAccess (pSrcDrawable, EXA_PREPARE_SRC);
- exaFinishAccess (pDstDrawable, EXA_PREPARE_DEST);
+ ret = FALSE;
out:
if (dstregion) {
@@ -542,6 +549,39 @@ out:
REGION_UNINIT(pScreen, srcregion);
REGION_DESTROY(pScreen, srcregion);
}
+
+ return ret;
+}
+
+void
+exaCopyNtoN (DrawablePtr pSrcDrawable,
+ DrawablePtr pDstDrawable,
+ GCPtr pGC,
+ BoxPtr pbox,
+ int nbox,
+ int dx,
+ int dy,
+ Bool reverse,
+ Bool upsidedown,
+ Pixel bitplane,
+ void *closure)
+{
+ ExaScreenPriv(pDstDrawable->pScreen);
+
+ if (pExaScr->fallback_flags & EXA_FALLBACK_COPYWINDOW)
+ return;
+
+ if (exaHWCopyNtoN(pSrcDrawable, pDstDrawable, pGC, pbox, nbox, dx, dy, reverse, upsidedown))
+ return;
+
+ /* This is a CopyWindow, it's cleaner to fallback at the original call. */
+ if (pExaScr->fallback_flags & EXA_ACCEL_COPYWINDOW) {
+ pExaScr->fallback_flags |= EXA_FALLBACK_COPYWINDOW;
+ return;
+ }
+
+ /* fallback */
+ ExaCheckCopyNtoN(pSrcDrawable, pDstDrawable, pGC, pbox, nbox, dx, dy, reverse, upsidedown, bitplane, closure);
}
RegionPtr
@@ -555,7 +595,7 @@ exaCopyArea(DrawablePtr pSrcDrawable, DrawablePtr pDstDrawable, GCPtr pGC,
srcx, srcy, width, height, dstx, dsty);
}
- return fbDoCopy (pSrcDrawable, pDstDrawable, pGC,
+ return miDoCopy (pSrcDrawable, pDstDrawable, pGC,
srcx, srcy, width, height,
dstx, dsty, exaCopyNtoN, 0, NULL);
}
@@ -730,7 +770,6 @@ exaPolyFillRect(DrawablePtr pDrawable,
int xoff, yoff;
int xorg, yorg;
int n;
- ExaMigrationRec pixmaps[2];
RegionPtr pReg = RECTS_TO_REGION(pScreen, nrect, prect, CT_UNSORTED);
/* Compute intersection of rects and clip region */
@@ -741,11 +780,6 @@ exaPolyFillRect(DrawablePtr pDrawable,
goto out;
}
- 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 || pExaPixmap->accel_blocked)
@@ -778,7 +812,16 @@ exaPolyFillRect(DrawablePtr pDrawable,
goto fallback;
}
- exaDoMigration (pixmaps, 1, TRUE);
+ if (pExaScr->do_migration) {
+ ExaMigrationRec pixmaps[1];
+
+ pixmaps[0].as_dst = TRUE;
+ pixmaps[0].as_src = FALSE;
+ pixmaps[0].pPix = pPixmap;
+ pixmaps[0].pReg = NULL;
+
+ exaDoMigration (pixmaps, 1, TRUE);
+ }
if (!exaPixmapIsOffscreen (pPixmap) ||
!(*pExaScr->info->PrepareSolid) (pPixmap,
@@ -898,6 +941,7 @@ exaCopyWindow(WindowPtr pWin, DDXPointRec ptOldOrg, RegionPtr prgnSrc)
RegionRec rgnDst;
int dx, dy;
PixmapPtr pPixmap = (*pWin->drawable.pScreen->GetWindowPixmap) (pWin);
+ ExaScreenPriv(pWin->drawable.pScreen);
dx = ptOldOrg.x - pWin->drawable.x;
dy = ptOldOrg.y - pWin->drawable.y;
@@ -912,11 +956,19 @@ exaCopyWindow(WindowPtr pWin, DDXPointRec ptOldOrg, RegionPtr prgnSrc)
-pPixmap->screen_x, -pPixmap->screen_y);
#endif
- fbCopyRegion (&pPixmap->drawable, &pPixmap->drawable,
+ pExaScr->fallback_flags |= EXA_ACCEL_COPYWINDOW;
+ miCopyRegion (&pPixmap->drawable, &pPixmap->drawable,
NULL,
&rgnDst, dx, dy, exaCopyNtoN, 0, NULL);
+ pExaScr->fallback_flags &= ~EXA_ACCEL_COPYWINDOW;
REGION_UNINIT(pWin->drawable.pScreen, &rgnDst);
+
+ if (pExaScr->fallback_flags & EXA_FALLBACK_COPYWINDOW) {
+ pExaScr->fallback_flags &= ~EXA_FALLBACK_COPYWINDOW;
+ REGION_TRANSLATE(pWin->drawable.pScreen, prgnSrc, dx, dy);
+ ExaCheckCopyWindow(pWin, ptOldOrg, prgnSrc);
+ }
}
static Bool
@@ -927,23 +979,23 @@ exaFillRegionSolid (DrawablePtr pDrawable, RegionPtr pRegion, Pixel pixel,
PixmapPtr pPixmap = exaGetDrawablePixmap (pDrawable);
ExaPixmapPriv (pPixmap);
int xoff, yoff;
- ExaMigrationRec pixmaps[1];
Bool ret = FALSE;
- pixmaps[0].as_dst = TRUE;
- pixmaps[0].as_src = FALSE;
- pixmaps[0].pPix = pPixmap;
- pixmaps[0].pReg = exaGCReadsDestination(pDrawable, planemask, FillSolid,
- alu, clientClipType)
- ? NULL : pRegion;
-
exaGetDrawableDeltas(pDrawable, pPixmap, &xoff, &yoff);
REGION_TRANSLATE(pScreen, pRegion, xoff, yoff);
if (pExaPixmap->accel_blocked)
- {
goto out;
- } else {
+
+ if (pExaScr->do_migration) {
+ ExaMigrationRec pixmaps[1];
+
+ pixmaps[0].as_dst = TRUE;
+ pixmaps[0].as_src = FALSE;
+ pixmaps[0].pPix = pPixmap;
+ pixmaps[0].pReg = exaGCReadsDestination(pDrawable, planemask, FillSolid,
+ alu, clientClipType) ? NULL : pRegion;
+
exaDoMigration (pixmaps, 1, TRUE);
}
@@ -965,7 +1017,7 @@ exaFillRegionSolid (DrawablePtr pDrawable, RegionPtr pRegion, Pixel pixel,
(*pExaScr->info->DoneSolid) (pPixmap);
exaMarkSync(pDrawable->pScreen);
- if (!(pExaScr->info->flags & EXA_HANDLES_PIXMAPS) &&
+ if (pExaPixmap->pDamage &&
pDrawable->width == 1 && pDrawable->height == 1 &&
pDrawable->bitsPerPixel != 24) {
ExaPixmapPriv(pPixmap);
@@ -1008,7 +1060,6 @@ exaFillRegionTiled (DrawablePtr pDrawable, RegionPtr pRegion, PixmapPtr pTile,
ExaPixmapPrivPtr pTileExaPixmap = ExaGetPixmapPriv(pTile);
int xoff, yoff;
int tileWidth, tileHeight;
- ExaMigrationRec pixmaps[2];
int nbox = REGION_NUM_RECTS (pRegion);
BoxPtr pBox = REGION_RECTS (pRegion);
Bool ret = FALSE;
@@ -1025,23 +1076,25 @@ exaFillRegionTiled (DrawablePtr pDrawable, RegionPtr pRegion, PixmapPtr pTile,
exaGetPixmapFirstPixel (pTile), planemask,
alu, clientClipType);
- pixmaps[0].as_dst = TRUE;
- pixmaps[0].as_src = FALSE;
- pixmaps[0].pPix = pPixmap = exaGetDrawablePixmap (pDrawable);
- pixmaps[0].pReg = exaGCReadsDestination(pDrawable, planemask, FillTiled,
- alu, clientClipType)
- ? NULL : pRegion;
- pixmaps[1].as_dst = FALSE;
- pixmaps[1].as_src = TRUE;
- pixmaps[1].pPix = pTile;
- pixmaps[1].pReg = NULL;
-
+ pPixmap = exaGetDrawablePixmap (pDrawable);
pExaPixmap = ExaGetPixmapPriv (pPixmap);
if (pExaPixmap->accel_blocked || pTileExaPixmap->accel_blocked)
- {
return FALSE;
- } else {
+
+ if (pExaScr->do_migration) {
+ ExaMigrationRec pixmaps[2];
+
+ pixmaps[0].as_dst = TRUE;
+ pixmaps[0].as_src = FALSE;
+ pixmaps[0].pPix = pPixmap;
+ pixmaps[0].pReg = exaGCReadsDestination(pDrawable, planemask, FillTiled,
+ alu, clientClipType) ? NULL : pRegion;
+ pixmaps[1].as_dst = FALSE;
+ pixmaps[1].as_src = TRUE;
+ pixmaps[1].pPix = pTile;
+ pixmaps[1].pReg = NULL;
+
exaDoMigration (pixmaps, 2, TRUE);
}
@@ -1180,31 +1233,36 @@ exaGetImage (DrawablePtr pDrawable, int x, int y, int w, int h,
unsigned int format, unsigned long planeMask, char *d)
{
ExaScreenPriv (pDrawable->pScreen);
- ExaMigrationRec pixmaps[1];
- BoxRec Box;
- RegionRec Reg;
- PixmapPtr pPix;
+ PixmapPtr pPix = exaGetDrawablePixmap (pDrawable);
int xoff, yoff;
Bool ok;
- pixmaps[0].as_dst = FALSE;
- pixmaps[0].as_src = TRUE;
- pixmaps[0].pPix = pPix = exaGetDrawablePixmap (pDrawable);
- pixmaps[0].pReg = &Reg;
+ if (pExaScr->swappedOut)
+ goto fallback;
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;
+ if (pExaScr->do_migration) {
+ BoxRec Box;
+ RegionRec Reg;
+ ExaMigrationRec pixmaps[1];
- REGION_INIT(pScreen, &Reg, &Box, 1);
+ Box.x1 = pDrawable->y + x + xoff;
+ Box.y1 = pDrawable->y + y + yoff;
+ Box.x2 = Box.x1 + w;
+ Box.y2 = Box.y1 + h;
- if (pExaScr->swappedOut)
- goto fallback;
+ REGION_INIT(pScreen, &Reg, &Box, 1);
- exaDoMigration(pixmaps, 1, FALSE);
+ pixmaps[0].as_dst = FALSE;
+ pixmaps[0].as_src = TRUE;
+ pixmaps[0].pPix = pPix;
+ pixmaps[0].pReg = &Reg;
+
+ exaDoMigration(pixmaps, 1, FALSE);
+
+ REGION_UNINIT(pScreen, &Reg);
+ }
pPix = exaGetOffscreenPixmap (pDrawable, &xoff, &yoff);
@@ -1226,17 +1284,9 @@ exaGetImage (DrawablePtr pDrawable, int x, int y, int w, int h,
PixmapBytePad(w, pDrawable->depth));
if (ok) {
exaWaitSync(pDrawable->pScreen);
- goto out;
+ return;
}
fallback:
- EXA_FALLBACK(("from %p (%c)\n", pDrawable,
- exaDrawableLocation(pDrawable)));
-
- exaPrepareAccessReg (pDrawable, EXA_PREPARE_SRC, &Reg);
- fbGetImage (pDrawable, x, y, w, h, format, planeMask, d);
- exaFinishAccess (pDrawable, EXA_PREPARE_SRC);
-
-out:
- REGION_UNINIT(pScreen, &Reg);
+ ExaCheckGetImage(pDrawable, x, y, w, h, format, planeMask, d);
}