summaryrefslogtreecommitdiff
path: root/exa
diff options
context:
space:
mode:
Diffstat (limited to 'exa')
-rw-r--r--exa/exa_accel.c76
-rw-r--r--exa/exa_priv.h25
-rw-r--r--exa/exa_render.c17
-rw-r--r--exa/exa_unaccel.c50
4 files changed, 149 insertions, 19 deletions
diff --git a/exa/exa_accel.c b/exa/exa_accel.c
index cc5dd18f2..326720f9f 100644
--- a/exa/exa_accel.c
+++ b/exa/exa_accel.c
@@ -359,8 +359,8 @@ exaCopyNtoNTwoDir (DrawablePtr pSrcDrawable, DrawablePtr pDstDrawable,
return TRUE;
}
-void
-exaCopyNtoN (DrawablePtr pSrcDrawable,
+Bool
+exaHWCopyNtoN (DrawablePtr pSrcDrawable,
DrawablePtr pDstDrawable,
GCPtr pGC,
BoxPtr pbox,
@@ -368,9 +368,7 @@ exaCopyNtoN (DrawablePtr pSrcDrawable,
int dx,
int dy,
Bool reverse,
- Bool upsidedown,
- Pixel bitplane,
- void *closure)
+ Bool upsidedown)
{
ExaScreenPriv (pDstDrawable->pScreen);
PixmapPtr pSrcPixmap, pDstPixmap;
@@ -380,10 +378,11 @@ exaCopyNtoN (DrawablePtr pSrcDrawable,
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);
@@ -492,15 +491,7 @@ exaCopyNtoN (DrawablePtr pSrcDrawable,
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) {
@@ -511,6 +502,52 @@ 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;
+ }
+
+ /* We need a pGC to call our fallback. */
+ if (!pGC) {
+ pExaScr->fallback_flags |= EXA_FALLBACK_NOGC;
+ pGC = CreateScratchGC(pDstDrawable->pScreen, pDstDrawable->depth);
+ if (!pGC)
+ return;
+ }
+
+ /* fallback */
+ ExaCheckCopyNtoN(pSrcDrawable, pDstDrawable, pGC, pbox, nbox, dx, dy, reverse, upsidedown, bitplane, closure);
+
+ if (pExaScr->fallback_flags & EXA_FALLBACK_NOGC) {
+ pExaScr->fallback_flags &= ~EXA_FALLBACK_NOGC;
+ FreeScratchGC(pGC);
+ }
}
RegionPtr
@@ -865,6 +902,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;
@@ -879,11 +917,19 @@ exaCopyWindow(WindowPtr pWin, DDXPointRec ptOldOrg, RegionPtr prgnSrc)
-pPixmap->screen_x, -pPixmap->screen_y);
#endif
+ 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
diff --git a/exa/exa_priv.h b/exa/exa_priv.h
index 6d7c1dd63..588fdec54 100644
--- a/exa/exa_priv.h
+++ b/exa/exa_priv.h
@@ -127,6 +127,10 @@ typedef struct {
#define EXA_NUM_GLYPH_CACHES 4
+#define EXA_FALLBACK_COPYWINDOW (1 << 0)
+#define EXA_ACCEL_COPYWINDOW (1 << 1)
+#define EXA_FALLBACK_NOGC (1 << 2)
+
typedef void (*EnableDisableFBAccessProcPtr)(int, Bool);
typedef struct {
ExaDriverPtr info;
@@ -155,6 +159,8 @@ typedef struct {
unsigned disableFbCount;
Bool optimize_migration;
unsigned offScreenCounter;
+ /* Holds information on fallbacks that cannot be relayed otherwise. */
+ unsigned int fallback_flags;
ExaGlyphCacheRec glyphCaches[EXA_NUM_GLYPH_CACHES];
} ExaScreenPrivRec, *ExaScreenPrivPtr;
@@ -316,6 +322,11 @@ ExaCheckPutImage (DrawablePtr pDrawable, GCPtr pGC, int depth,
int x, int y, int w, int h, int leftPad, int format,
char *bits);
+void
+ExaCheckCopyNtoN (DrawablePtr pSrc, DrawablePtr pDst, GCPtr pGC,
+ BoxPtr pbox, int nbox, int dx, int dy, Bool reverse,
+ Bool upsidedown, Pixel bitplane, void *closure);
+
RegionPtr
ExaCheckCopyArea (DrawablePtr pSrc, DrawablePtr pDst, GCPtr pGC,
int srcx, int srcy, int w, int h, int dstx, int dsty);
@@ -361,6 +372,9 @@ ExaCheckPushPixels (GCPtr pGC, PixmapPtr pBitmap,
int w, int h, int x, int y);
void
+ExaCheckCopyWindow(WindowPtr pWin, DDXPointRec ptOldOrg, RegionPtr prgnSrc);
+
+void
ExaCheckGetImage(DrawablePtr pDrawable, int x, int y, int w, int h,
unsigned int format, unsigned long planeMask, char *d);
@@ -465,6 +479,17 @@ RegionPtr
exaCopyArea(DrawablePtr pSrcDrawable, DrawablePtr pDstDrawable, GCPtr pGC,
int srcx, int srcy, int width, int height, int dstx, int dsty);
+Bool
+exaHWCopyNtoN (DrawablePtr pSrcDrawable,
+ DrawablePtr pDstDrawable,
+ GCPtr pGC,
+ BoxPtr pbox,
+ int nbox,
+ int dx,
+ int dy,
+ Bool reverse,
+ Bool upsidedown);
+
void
exaCopyNtoN (DrawablePtr pSrcDrawable,
DrawablePtr pDstDrawable,
diff --git a/exa/exa_render.c b/exa/exa_render.c
index 63ea5c158..17885317f 100644
--- a/exa/exa_render.c
+++ b/exa/exa_render.c
@@ -851,6 +851,7 @@ exaComposite(CARD8 op,
!pSrc->repeat &&
!pSrc->transform)
{
+ Bool ret;
xDst += pDst->pDrawable->x;
yDst += pDst->pDrawable->y;
xSrc += pSrc->pDrawable->x;
@@ -861,12 +862,20 @@ exaComposite(CARD8 op,
yDst, width, height))
goto done;
-
- exaCopyNtoN (pSrc->pDrawable, pDst->pDrawable, NULL,
+ ret = exaHWCopyNtoN(pSrc->pDrawable, pDst->pDrawable, NULL,
REGION_RECTS(&region), REGION_NUM_RECTS(&region),
- xSrc - xDst, ySrc - yDst,
- FALSE, FALSE, 0, NULL);
+ xSrc - xDst, ySrc - yDst, FALSE, FALSE);
REGION_UNINIT(pDst->pDrawable->pScreen, &region);
+
+ /* Reset values to their original values. */
+ xDst -= pDst->pDrawable->x;
+ yDst -= pDst->pDrawable->y;
+ xSrc -= pSrc->pDrawable->x;
+ ySrc -= pSrc->pDrawable->y;
+
+ if (!ret)
+ goto fallback;
+
goto done;
}
else if (pSrc->pDrawable != NULL &&
diff --git a/exa/exa_unaccel.c b/exa/exa_unaccel.c
index e0f2ae9a9..978a32f59 100644
--- a/exa/exa_unaccel.c
+++ b/exa/exa_unaccel.c
@@ -116,6 +116,40 @@ ExaCheckPutImage (DrawablePtr pDrawable, GCPtr pGC, int depth,
EXA_GC_EPILOGUE(pGC);
}
+/* Sometimes we need a pGC to call a function, but don't actually want the lower
+ * layer to do something with the contents of this fake GC. */
+static inline GCPtr
+ExaCheckWantGC(DrawablePtr pDrawable, GCPtr pGC)
+{
+ ExaScreenPriv(pDrawable->pScreen);
+
+ if (pExaScr->fallback_flags & EXA_FALLBACK_NOGC)
+ return NULL;
+
+ return pGC;
+}
+
+void
+ExaCheckCopyNtoN (DrawablePtr pSrc, DrawablePtr pDst, GCPtr pGC,
+ BoxPtr pbox, int nbox, int dx, int dy, Bool reverse,
+ Bool upsidedown, Pixel bitplane, void *closure)
+{
+ EXA_GC_PROLOGUE(pGC);
+ EXA_FALLBACK(("from %p to %p (%c,%c)\n", pSrc, pDst,
+ exaDrawableLocation(pSrc), exaDrawableLocation(pDst)));
+ exaPrepareAccess (pDst, EXA_PREPARE_DEST);
+ exaPrepareAccess (pSrc, EXA_PREPARE_SRC);
+ /* This will eventually call fbCopyNtoN, with some calculation overhead. */
+ while (nbox--) {
+ pGC->ops->CopyArea (pSrc, pDst, ExaCheckWantGC(pDst, pGC), pbox->x1 - pSrc->x + dx, pbox->y1 - pSrc->y + dy,
+ pbox->x2 - pbox->x1, pbox->y2 - pbox->y1, pbox->x1 - pDst->x, pbox->y1 - pDst->y);
+ pbox++;
+ }
+ exaFinishAccess (pSrc, EXA_PREPARE_SRC);
+ exaFinishAccess (pDst, EXA_PREPARE_DEST);
+ EXA_GC_EPILOGUE(pGC);
+}
+
RegionPtr
ExaCheckCopyArea (DrawablePtr pSrc, DrawablePtr pDst, GCPtr pGC,
int srcx, int srcy, int w, int h, int dstx, int dsty)
@@ -283,6 +317,22 @@ ExaCheckPushPixels (GCPtr pGC, PixmapPtr pBitmap,
}
void
+ExaCheckCopyWindow(WindowPtr pWin, DDXPointRec ptOldOrg, RegionPtr prgnSrc)
+{
+ DrawablePtr pDrawable = &pWin->drawable;
+ ScreenPtr pScreen = pDrawable->pScreen;
+ ExaScreenPriv(pScreen);
+ EXA_FALLBACK(("from %p\n", pWin));
+
+ /* being both src and dest, src is safest. */
+ exaPrepareAccess(pDrawable, EXA_PREPARE_SRC);
+ swap(pExaScr, pScreen, CopyWindow);
+ pScreen->CopyWindow (pWin, ptOldOrg, prgnSrc);
+ swap(pExaScr, pScreen, CopyWindow);
+ exaFinishAccess (pDrawable, EXA_PREPARE_SRC);
+}
+
+void
ExaCheckGetImage(DrawablePtr pDrawable, int x, int y, int w, int h,
unsigned int format, unsigned long planeMask, char *d)
{