diff options
author | Maarten Maathuis <madman2003@gmail.com> | 2009-01-31 18:53:52 +0100 |
---|---|---|
committer | Maarten Maathuis <madman2003@gmail.com> | 2009-02-06 18:42:38 +0100 |
commit | 015c99a4ad572f5a1b68054efb070e1ffee1fed0 (patch) | |
tree | 0a44591380387f5a856917884a5b5277022188be /exa | |
parent | 5e6a06fe691db63ccf2dc7161a1f6c71c09741b7 (diff) |
exa: properly wrap GC functions
Diffstat (limited to 'exa')
-rw-r--r-- | exa/exa.c | 233 | ||||
-rw-r--r-- | exa/exa_priv.h | 33 | ||||
-rw-r--r-- | exa/exa_unaccel.c | 98 |
3 files changed, 248 insertions, 116 deletions
@@ -575,86 +575,178 @@ exaFinishAccess(DrawablePtr pDrawable, int index) } /** - * exaValidateGC() sets the ops to EXA's implementations, which may be - * accelerated or may sync the card and fall back to fb. + * Here begins EXA's GC code. + * Do not ever access the fb/mi layer directly. */ + +static void +exaValidateGC(GCPtr pGC, + unsigned long changes, + DrawablePtr pDrawable); + +static void +exaDestroyGC(GCPtr pGC); + +static void +exaChangeGC (GCPtr pGC, + unsigned long mask); + +static void +exaCopyGC (GCPtr pGCSrc, + unsigned long mask, + GCPtr pGCDst); + +static void +exaChangeClip (GCPtr pGC, + int type, + pointer pvalue, + int nrects); + static void -exaValidateGC (GCPtr pGC, unsigned long changes, DrawablePtr pDrawable) +exaCopyClip(GCPtr pGCDst, GCPtr pGCSrc); + +static void +exaCopyClip(GCPtr pGCDst, GCPtr pGCSrc); + +static void +exaDestroyClip(GCPtr pGC); + +const GCFuncs exaGCFuncs = { + exaValidateGC, + exaChangeGC, + exaCopyGC, + exaDestroyGC, + exaChangeClip, + exaDestroyClip, + exaCopyClip +}; + +/* + * This wrapper exists to allow fbValidateGC to work. + */ +static PixmapPtr +exaCreatePixmapWithPrepare(ScreenPtr pScreen, int w, int h, int depth, + unsigned usage_hint) +{ + PixmapPtr pPixmap; + ExaScreenPriv(pScreen); + + /* This swaps between this function and the real upper layer function. + * Normally this would swap to the fb layer pointer, this is a very special case. + */ + swap(pExaScr, pScreen, CreatePixmap); + pPixmap = pScreen->CreatePixmap(pScreen, w, h, depth, usage_hint); + swap(pExaScr, pScreen, CreatePixmap); + + if (!pPixmap) + return NULL; + + /* We use MASK, because SRC is already taken. */ + exaPrepareAccess(&pPixmap->drawable, EXA_PREPARE_MASK); + + return pPixmap; +} + +static void +exaValidateGC(GCPtr pGC, + unsigned long changes, + DrawablePtr pDrawable) { /* fbValidateGC will do direct access to pixmaps if the tiling has changed. - * Preempt fbValidateGC by doing its work and masking the change out, so - * that we can do the Prepare/FinishAccess. + * Do a few smart things so fbValidateGC can do it's work. */ -#ifdef FB_24_32BIT - if ((changes & GCTile) && fbGetRotatedPixmap(pGC)) { - (*pGC->pScreen->DestroyPixmap) (fbGetRotatedPixmap(pGC)); - fbGetRotatedPixmap(pGC) = 0; - } - - if (pGC->fillStyle == FillTiled) { - PixmapPtr pOldTile, pNewTile; - pOldTile = pGC->tile.pixmap; - if (pOldTile->drawable.bitsPerPixel != pDrawable->bitsPerPixel) - { - pNewTile = fbGetRotatedPixmap(pGC); - if (!pNewTile || - pNewTile ->drawable.bitsPerPixel != pDrawable->bitsPerPixel) - { - if (pNewTile) - (*pGC->pScreen->DestroyPixmap) (pNewTile); - /* fb24_32ReformatTile will do direct access of a newly- - * allocated pixmap. This isn't a problem yet, since we don't - * put pixmaps in FB until at least one accelerated EXA op. - */ - exaPrepareAccess(&pOldTile->drawable, EXA_PREPARE_SRC); - pNewTile = fb24_32ReformatTile (pOldTile, - pDrawable->bitsPerPixel); - exaPixmapDirty(pNewTile, 0, 0, pNewTile->drawable.width, pNewTile->drawable.height); - exaFinishAccess(&pOldTile->drawable, EXA_PREPARE_SRC); - } - if (pNewTile) - { - fbGetRotatedPixmap(pGC) = pOldTile; - pGC->tile.pixmap = pNewTile; - changes |= GCTile; - } - } + ScreenPtr pScreen = pDrawable->pScreen; + ExaScreenPriv(pScreen); + CreatePixmapProcPtr old_ptr = NULL; + PixmapPtr pTile = NULL; + EXA_GC_PROLOGUE(pGC); + if (changes & GCTile) { + /* save the "fb" pointer. */ + old_ptr = pExaScr->SavedCreatePixmap; + /* create a new upper layer pointer. */ + wrap(pExaScr, pScreen, CreatePixmap, exaCreatePixmapWithPrepare); + if (pGC->fillStyle == FillTiled) + pTile = pGC->tile.pixmap; + if (pTile) + exaPrepareAccess(&pTile->drawable, EXA_PREPARE_SRC); } -#endif + exaPrepareAccessGC(pGC); + (*pGC->funcs->ValidateGC)(pGC, changes, pDrawable); + exaFinishAccessGC(pGC); if (changes & GCTile) { - if (!pGC->tileIsPixel && FbEvenTile (pGC->tile.pixmap->drawable.width * - pDrawable->bitsPerPixel)) - { - exaPrepareAccess(&pGC->tile.pixmap->drawable, EXA_PREPARE_SRC); - fbPadPixmap (pGC->tile.pixmap); - exaFinishAccess(&pGC->tile.pixmap->drawable, EXA_PREPARE_SRC); + /* switch back to the normal upper layer. */ + unwrap(pExaScr, pScreen, CreatePixmap); + /* restore copy of fb layer pointer. */ + pExaScr->SavedCreatePixmap = old_ptr; + if (pTile) + exaFinishAccess(&pTile->drawable, EXA_PREPARE_SRC); + + /* A new tile pixmap was created. */ + if (pGC->tile.pixmap != pTile && pGC->fillStyle == FillTiled) { + exaFinishAccess(&pGC->tile.pixmap->drawable, EXA_PREPARE_MASK); exaPixmapDirty(pGC->tile.pixmap, 0, 0, pGC->tile.pixmap->drawable.width, pGC->tile.pixmap->drawable.height); } - /* Mask out the GCTile change notification, now that we've done FB's - * job for it. - */ - changes &= ~GCTile; } + EXA_GC_EPILOGUE(pGC); +} - exaPrepareAccessGC(pGC); - fbValidateGC (pGC, changes, pDrawable); - exaFinishAccessGC(pGC); +/* Is exaPrepareAccessGC() needed? */ +static void +exaDestroyGC(GCPtr pGC) +{ + EXA_GC_PROLOGUE (pGC); + (*pGC->funcs->DestroyGC)(pGC); + EXA_GC_EPILOGUE (pGC); +} - pGC->ops = (GCOps *) &exaOps; +static void +exaChangeGC (GCPtr pGC, + unsigned long mask) +{ + EXA_GC_PROLOGUE (pGC); + (*pGC->funcs->ChangeGC) (pGC, mask); + EXA_GC_EPILOGUE (pGC); } -static GCFuncs exaGCFuncs = { - exaValidateGC, - miChangeGC, - miCopyGC, - miDestroyGC, - miChangeClip, - miDestroyClip, - miCopyClip -}; +static void +exaCopyGC (GCPtr pGCSrc, + unsigned long mask, + GCPtr pGCDst) +{ + EXA_GC_PROLOGUE (pGCDst); + (*pGCDst->funcs->CopyGC) (pGCSrc, mask, pGCDst); + EXA_GC_EPILOGUE (pGCDst); +} + +static void +exaChangeClip (GCPtr pGC, + int type, + pointer pvalue, + int nrects) +{ + EXA_GC_PROLOGUE (pGC); + (*pGC->funcs->ChangeClip) (pGC, type, pvalue, nrects); + EXA_GC_EPILOGUE (pGC); +} + +static void +exaCopyClip(GCPtr pGCDst, GCPtr pGCSrc) +{ + EXA_GC_PROLOGUE (pGCDst); + (*pGCDst->funcs->CopyClip)(pGCDst, pGCSrc); + EXA_GC_EPILOGUE (pGCDst); +} + +static void +exaDestroyClip(GCPtr pGC) +{ + EXA_GC_PROLOGUE (pGC); + (*pGC->funcs->DestroyClip)(pGC); + EXA_GC_EPILOGUE (pGC); +} /** * exaCreateGC makes a new GC and hooks up its funcs handler, so that @@ -663,14 +755,19 @@ static GCFuncs exaGCFuncs = { static int exaCreateGC (GCPtr pGC) { + ScreenPtr pScreen = pGC->pScreen; + ExaScreenPriv(pScreen); ExaGCPriv(pGC); + Bool ret; - if (!fbCreateGC (pGC)) - return FALSE; - - pGC->funcs = &exaGCFuncs; + swap(pExaScr, pScreen, CreateGC); + if ((ret = (*pScreen->CreateGC) (pGC))) { + wrap(pExaGC, pGC, funcs, (GCFuncs *) &exaGCFuncs); + wrap(pExaGC, pGC, ops, (GCOps *) &exaOps); + } + swap(pExaScr, pScreen, CreateGC); - return TRUE; + return ret; } static Bool diff --git a/exa/exa_priv.h b/exa/exa_priv.h index 3b589488e..a41e5fe00 100644 --- a/exa/exa_priv.h +++ b/exa/exa_priv.h @@ -180,6 +180,33 @@ extern DevPrivateKey exaGCPrivateKey; #define ExaGetGCPriv(gc) ((ExaGCPrivPtr)dixLookupPrivate(&(gc)->devPrivates, exaGCPrivateKey)) #define ExaGCPriv(gc) ExaGCPrivPtr pExaGC = ExaGetGCPriv(gc) +/* + * Some macros to deal with function wrapping. + */ +#define wrap(priv, real, mem, func) {\ + priv->Saved##mem = real->mem; \ + real->mem = func; \ +} + +#define unwrap(priv, real, mem) {\ + real->mem = priv->Saved##mem; \ +} + +#define swap(priv, real, mem) {\ + void *tmp = priv->Saved##mem; \ + priv->Saved##mem = real->mem; \ + real->mem = tmp; \ +} + +#define EXA_GC_PROLOGUE(_gc_) \ + ExaGCPriv(_gc_); \ + swap(pExaGC, _gc_, funcs); \ + swap(pExaGC, _gc_, ops); + +#define EXA_GC_EPILOGUE(_gc_) \ + swap(pExaGC, _gc_, funcs); \ + swap(pExaGC, _gc_, ops); + /** Align an offset to an arbitrary alignment */ #define EXA_ALIGN(offset, align) (((offset) + (align) - 1) - \ (((offset) + (align) - 1) % (align))) @@ -243,8 +270,8 @@ typedef struct { typedef struct { /* GC values from the layer below. */ - GCOps *ops; - GCFuncs *funcs; + GCOps *Savedops; + GCFuncs *Savedfuncs; } ExaGCPrivRec, *ExaGCPrivPtr; typedef struct _ExaMigrationRec { @@ -447,6 +474,8 @@ exaCopyNtoN (DrawablePtr pSrcDrawable, Pixel bitplane, void *closure); +extern const GCFuncs exaGCFuncs; + /* exa_render.c */ Bool exaOpReadsDestination (CARD8 op); diff --git a/exa/exa_unaccel.c b/exa/exa_unaccel.c index c03048602..d56f589c1 100644 --- a/exa/exa_unaccel.c +++ b/exa/exa_unaccel.c @@ -74,22 +74,26 @@ void ExaCheckFillSpans (DrawablePtr pDrawable, GCPtr pGC, int nspans, DDXPointPtr ppt, int *pwidth, int fSorted) { + EXA_GC_PROLOGUE(pGC); EXA_FALLBACK(("to %p (%c)\n", pDrawable, exaDrawableLocation(pDrawable))); exaPrepareAccess (pDrawable, EXA_PREPARE_DEST); exaPrepareAccessGC (pGC); - fbFillSpans (pDrawable, pGC, nspans, ppt, pwidth, fSorted); + pGC->ops->FillSpans (pDrawable, pGC, nspans, ppt, pwidth, fSorted); exaFinishAccessGC (pGC); exaFinishAccess (pDrawable, EXA_PREPARE_DEST); + EXA_GC_EPILOGUE(pGC); } void ExaCheckSetSpans (DrawablePtr pDrawable, GCPtr pGC, char *psrc, DDXPointPtr ppt, int *pwidth, int nspans, int fSorted) { + EXA_GC_PROLOGUE(pGC); EXA_FALLBACK(("to %p (%c)\n", pDrawable, exaDrawableLocation(pDrawable))); exaPrepareAccess (pDrawable, EXA_PREPARE_DEST); - fbSetSpans (pDrawable, pGC, psrc, ppt, pwidth, nspans, fSorted); + pGC->ops->SetSpans (pDrawable, pGC, psrc, ppt, pwidth, nspans, fSorted); exaFinishAccess (pDrawable, EXA_PREPARE_DEST); + EXA_GC_EPILOGUE(pGC); } void @@ -99,6 +103,7 @@ ExaCheckPutImage (DrawablePtr pDrawable, GCPtr pGC, int depth, { ExaPixmapPriv(exaGetDrawablePixmap(pDrawable)); + EXA_GC_PROLOGUE(pGC); EXA_FALLBACK(("to %p (%c)\n", pDrawable, exaDrawableLocation(pDrawable))); if (exaGCReadsDestination(pDrawable, pGC->planemask, pGC->fillStyle, pGC->alu)) @@ -106,8 +111,9 @@ ExaCheckPutImage (DrawablePtr pDrawable, GCPtr pGC, int depth, else exaPrepareAccessReg (pDrawable, EXA_PREPARE_DEST, pExaPixmap->pDamage ? DamagePendingRegion(pExaPixmap->pDamage) : NULL); - fbPutImage (pDrawable, pGC, depth, x, y, w, h, leftPad, format, bits); + pGC->ops->PutImage (pDrawable, pGC, depth, x, y, w, h, leftPad, format, bits); exaFinishAccess (pDrawable, EXA_PREPARE_DEST); + EXA_GC_EPILOGUE(pGC); } RegionPtr @@ -116,13 +122,15 @@ ExaCheckCopyArea (DrawablePtr pSrc, DrawablePtr pDst, GCPtr pGC, { RegionPtr ret; + 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); - ret = fbCopyArea (pSrc, pDst, pGC, srcx, srcy, w, h, dstx, dsty); + ret = pGC->ops->CopyArea (pSrc, pDst, pGC, srcx, srcy, w, h, dstx, dsty); exaFinishAccess (pSrc, EXA_PREPARE_SRC); exaFinishAccess (pDst, EXA_PREPARE_DEST); + EXA_GC_EPILOGUE(pGC); return ret; } @@ -134,14 +142,16 @@ ExaCheckCopyPlane (DrawablePtr pSrc, DrawablePtr pDst, GCPtr pGC, { RegionPtr ret; + 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); - ret = fbCopyPlane (pSrc, pDst, pGC, srcx, srcy, w, h, dstx, dsty, + ret = pGC->ops->CopyPlane (pSrc, pDst, pGC, srcx, srcy, w, h, dstx, dsty, bitPlane); exaFinishAccess (pSrc, EXA_PREPARE_SRC); exaFinishAccess (pDst, EXA_PREPARE_DEST); + EXA_GC_EPILOGUE(pGC); return ret; } @@ -150,85 +160,75 @@ void ExaCheckPolyPoint (DrawablePtr pDrawable, GCPtr pGC, int mode, int npt, DDXPointPtr pptInit) { + EXA_GC_PROLOGUE(pGC); EXA_FALLBACK(("to %p (%c)\n", pDrawable, exaDrawableLocation(pDrawable))); exaPrepareAccess (pDrawable, EXA_PREPARE_DEST); - fbPolyPoint (pDrawable, pGC, mode, npt, pptInit); + pGC->ops->PolyPoint (pDrawable, pGC, mode, npt, pptInit); exaFinishAccess (pDrawable, EXA_PREPARE_DEST); + EXA_GC_EPILOGUE(pGC); } void ExaCheckPolylines (DrawablePtr pDrawable, GCPtr pGC, int mode, int npt, DDXPointPtr ppt) { + EXA_GC_PROLOGUE(pGC); EXA_FALLBACK(("to %p (%c), width %d, mode %d, count %d\n", pDrawable, exaDrawableLocation(pDrawable), pGC->lineWidth, mode, npt)); - if (pGC->lineWidth == 0) { - exaPrepareAccess (pDrawable, EXA_PREPARE_DEST); - exaPrepareAccessGC (pGC); - fbPolyLine (pDrawable, pGC, mode, npt, ppt); - exaFinishAccessGC (pGC); - exaFinishAccess (pDrawable, EXA_PREPARE_DEST); - return; - } - /* fb calls mi functions in the lineWidth != 0 case. */ - fbPolyLine (pDrawable, pGC, mode, npt, ppt); + exaPrepareAccess (pDrawable, EXA_PREPARE_DEST); + exaPrepareAccessGC (pGC); + pGC->ops->Polylines (pDrawable, pGC, mode, npt, ppt); + exaFinishAccessGC (pGC); + exaFinishAccess (pDrawable, EXA_PREPARE_DEST); + EXA_GC_EPILOGUE(pGC); } void ExaCheckPolySegment (DrawablePtr pDrawable, GCPtr pGC, int nsegInit, xSegment *pSegInit) { + EXA_GC_PROLOGUE(pGC); EXA_FALLBACK(("to %p (%c) width %d, count %d\n", pDrawable, exaDrawableLocation(pDrawable), pGC->lineWidth, nsegInit)); - if (pGC->lineWidth == 0) { - exaPrepareAccess (pDrawable, EXA_PREPARE_DEST); - exaPrepareAccessGC (pGC); - fbPolySegment (pDrawable, pGC, nsegInit, pSegInit); - exaFinishAccessGC (pGC); - exaFinishAccess (pDrawable, EXA_PREPARE_DEST); - return; - } - /* fb calls mi functions in the lineWidth != 0 case. */ - fbPolySegment (pDrawable, pGC, nsegInit, pSegInit); + + exaPrepareAccess (pDrawable, EXA_PREPARE_DEST); + exaPrepareAccessGC (pGC); + pGC->ops->PolySegment (pDrawable, pGC, nsegInit, pSegInit); + exaFinishAccessGC (pGC); + exaFinishAccess (pDrawable, EXA_PREPARE_DEST); + EXA_GC_EPILOGUE(pGC); } void ExaCheckPolyArc (DrawablePtr pDrawable, GCPtr pGC, int narcs, xArc *pArcs) { + EXA_GC_PROLOGUE(pGC); EXA_FALLBACK(("to %p (%c)\n", pDrawable, exaDrawableLocation(pDrawable))); - /* Disable this as fbPolyArc can call miZeroPolyArc which in turn - * can call accelerated functions, that as yet, haven't been notified - * with exaFinishAccess(). - */ -#if 0 - if (pGC->lineWidth == 0) - { - exaPrepareAccess (pDrawable, EXA_PREPARE_DEST); - exaPrepareAccessGC (pGC); - fbPolyArc (pDrawable, pGC, narcs, pArcs); - exaFinishAccessGC (pGC); - exaFinishAccess (pDrawable, EXA_PREPARE_DEST); - return; - } -#endif - miPolyArc (pDrawable, pGC, narcs, pArcs); + exaPrepareAccess (pDrawable, EXA_PREPARE_DEST); + exaPrepareAccessGC (pGC); + pGC->ops->PolyArc (pDrawable, pGC, narcs, pArcs); + exaFinishAccessGC (pGC); + exaFinishAccess (pDrawable, EXA_PREPARE_DEST); + EXA_GC_EPILOGUE(pGC); } void ExaCheckPolyFillRect (DrawablePtr pDrawable, GCPtr pGC, int nrect, xRectangle *prect) { + EXA_GC_PROLOGUE(pGC); EXA_FALLBACK(("to %p (%c)\n", pDrawable, exaDrawableLocation(pDrawable))); exaPrepareAccess (pDrawable, EXA_PREPARE_DEST); exaPrepareAccessGC (pGC); - fbPolyFillRect (pDrawable, pGC, nrect, prect); + pGC->ops->PolyFillRect (pDrawable, pGC, nrect, prect); exaFinishAccessGC (pGC); exaFinishAccess (pDrawable, EXA_PREPARE_DEST); + EXA_GC_EPILOGUE(pGC); } void @@ -236,13 +236,15 @@ ExaCheckImageGlyphBlt (DrawablePtr pDrawable, GCPtr pGC, int x, int y, unsigned int nglyph, CharInfoPtr *ppci, pointer pglyphBase) { + EXA_GC_PROLOGUE(pGC); EXA_FALLBACK(("to %p (%c)\n", pDrawable, exaDrawableLocation(pDrawable))); exaPrepareAccess (pDrawable, EXA_PREPARE_DEST); exaPrepareAccessGC (pGC); - fbImageGlyphBlt (pDrawable, pGC, x, y, nglyph, ppci, pglyphBase); + pGC->ops->ImageGlyphBlt (pDrawable, pGC, x, y, nglyph, ppci, pglyphBase); exaFinishAccessGC (pGC); exaFinishAccess (pDrawable, EXA_PREPARE_DEST); + EXA_GC_EPILOGUE(pGC); } void @@ -250,13 +252,15 @@ ExaCheckPolyGlyphBlt (DrawablePtr pDrawable, GCPtr pGC, int x, int y, unsigned int nglyph, CharInfoPtr *ppci, pointer pglyphBase) { + EXA_GC_PROLOGUE(pGC); EXA_FALLBACK(("to %p (%c), style %d alu %d\n", pDrawable, exaDrawableLocation(pDrawable), pGC->fillStyle, pGC->alu)); exaPrepareAccess (pDrawable, EXA_PREPARE_DEST); exaPrepareAccessGC (pGC); - fbPolyGlyphBlt (pDrawable, pGC, x, y, nglyph, ppci, pglyphBase); + pGC->ops->PolyGlyphBlt (pDrawable, pGC, x, y, nglyph, ppci, pglyphBase); exaFinishAccessGC (pGC); exaFinishAccess (pDrawable, EXA_PREPARE_DEST); + EXA_GC_EPILOGUE(pGC); } void @@ -264,16 +268,18 @@ ExaCheckPushPixels (GCPtr pGC, PixmapPtr pBitmap, DrawablePtr pDrawable, int w, int h, int x, int y) { + EXA_GC_PROLOGUE(pGC); EXA_FALLBACK(("from %p to %p (%c,%c)\n", pBitmap, pDrawable, exaDrawableLocation(&pBitmap->drawable), exaDrawableLocation(pDrawable))); exaPrepareAccess (pDrawable, EXA_PREPARE_DEST); exaPrepareAccess (&pBitmap->drawable, EXA_PREPARE_SRC); exaPrepareAccessGC (pGC); - fbPushPixels (pGC, pBitmap, pDrawable, w, h, x, y); + pGC->ops->PushPixels (pGC, pBitmap, pDrawable, w, h, x, y); exaFinishAccessGC (pGC); exaFinishAccess (&pBitmap->drawable, EXA_PREPARE_SRC); exaFinishAccess (pDrawable, EXA_PREPARE_DEST); + EXA_GC_EPILOGUE(pGC); } void |