/* * Copyright (c) 2009-2012 Apple Inc. All rights reserved. * * Permission is hereby granted, free of charge, to any person * obtaining a copy of this software and associated documentation files * (the "Software"), to deal in the Software without restriction, * including without limitation the rights to use, copy, modify, merge, * publish, distribute, sublicense, and/or sell copies of the Software, * and to permit persons to whom the Software is furnished to do so, * subject to the following conditions: * * The above copyright notice and this permission notice shall be * included in all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND * NONINFRINGEMENT. IN NO EVENT SHALL THE ABOVE LISTED COPYRIGHT * HOLDER(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. * * Except as contained in this notice, the name(s) of the above * copyright holders shall not be used in advertising or otherwise to * promote the sale, use or other dealings in this Software without * prior written authorization. */ #ifdef HAVE_DIX_CONFIG_H #include #endif #include #include "mi.h" #include "scrnintstr.h" #include "gcstruct.h" #include "pixmapstr.h" #include "windowstr.h" #include "dixfontstr.h" #include "mivalidate.h" #include "driWrap.h" #include "dri.h" #include typedef struct { GCOps *originalOps; } DRIGCRec; typedef struct { GCOps *originalOps; CreateGCProcPtr CreateGC; } DRIWrapScreenRec; typedef struct { Bool didSave; int devKind; DevUnion devPrivate; } DRISavedDrawableState; static DevPrivateKeyRec driGCKeyRec; #define driGCKey (&driGCKeyRec) static DevPrivateKeyRec driWrapScreenKeyRec; #define driWrapScreenKey (&driWrapScreenKeyRec) static GCOps driGCOps; #define wrap(priv, real, member, func) { \ priv->member = real->member; \ real->member = func; \ } #define unwrap(priv, real, member) { \ real->member = priv->member; \ } static DRIGCRec * DRIGetGCPriv(GCPtr pGC) { return dixLookupPrivate(&pGC->devPrivates, driGCKey); } static void DRIUnwrapGC(GCPtr pGC) { DRIGCRec *pGCPriv = DRIGetGCPriv(pGC); pGC->ops = pGCPriv->originalOps; } static void DRIWrapGC(GCPtr pGC) { pGC->ops = &driGCOps; } static void DRISurfaceSetDrawable(DrawablePtr pDraw, DRISavedDrawableState *saved) { saved->didSave = FALSE; if (pDraw->type == DRAWABLE_PIXMAP) { int pitch, width, height, bpp; void *buffer; if (DRIGetPixmapData(pDraw, &width, &height, &pitch, &bpp, &buffer)) { PixmapPtr pPix = (PixmapPtr)pDraw; saved->devKind = pPix->devKind; saved->devPrivate.ptr = pPix->devPrivate.ptr; saved->didSave = TRUE; pPix->devKind = pitch; pPix->devPrivate.ptr = buffer; } } } static void DRISurfaceRestoreDrawable(DrawablePtr pDraw, DRISavedDrawableState *saved) { PixmapPtr pPix = (PixmapPtr)pDraw; if (!saved->didSave) return; pPix->devKind = saved->devKind; pPix->devPrivate.ptr = saved->devPrivate.ptr; } static void DRIFillSpans(DrawablePtr dst, GCPtr pGC, int nInit, DDXPointPtr pptInit, int *pwidthInit, int sorted) { DRISavedDrawableState saved; DRISurfaceSetDrawable(dst, &saved); DRIUnwrapGC(pGC); pGC->ops->FillSpans(dst, pGC, nInit, pptInit, pwidthInit, sorted); DRIWrapGC(pGC); DRISurfaceRestoreDrawable(dst, &saved); } static void DRISetSpans(DrawablePtr dst, GCPtr pGC, char *pSrc, DDXPointPtr pptInit, int *pwidthInit, int nspans, int sorted) { DRISavedDrawableState saved; DRISurfaceSetDrawable(dst, &saved); DRIUnwrapGC(pGC); pGC->ops->SetSpans(dst, pGC, pSrc, pptInit, pwidthInit, nspans, sorted); DRIWrapGC(pGC); DRISurfaceRestoreDrawable(dst, &saved); } static void DRIPutImage(DrawablePtr dst, GCPtr pGC, int depth, int x, int y, int w, int h, int leftPad, int format, char *pBits) { DRISavedDrawableState saved; DRISurfaceSetDrawable(dst, &saved); DRIUnwrapGC(pGC); pGC->ops->PutImage(dst, pGC, depth, x, y, w, h, leftPad, format, pBits); DRIWrapGC(pGC); DRISurfaceRestoreDrawable(dst, &saved); } static RegionPtr DRICopyArea(DrawablePtr pSrc, DrawablePtr dst, GCPtr pGC, int srcx, int srcy, int w, int h, int dstx, int dsty) { RegionPtr pReg; DRISavedDrawableState pSrcSaved, dstSaved; DRISurfaceSetDrawable(pSrc, &pSrcSaved); DRISurfaceSetDrawable(dst, &dstSaved); DRIUnwrapGC(pGC); pReg = pGC->ops->CopyArea(pSrc, dst, pGC, srcx, srcy, w, h, dstx, dsty); DRIWrapGC(pGC); DRISurfaceRestoreDrawable(pSrc, &pSrcSaved); DRISurfaceRestoreDrawable(dst, &dstSaved); return pReg; } static RegionPtr DRICopyPlane(DrawablePtr pSrc, DrawablePtr dst, GCPtr pGC, int srcx, int srcy, int w, int h, int dstx, int dsty, unsigned long plane) { RegionPtr pReg; DRISavedDrawableState pSrcSaved, dstSaved; DRISurfaceSetDrawable(pSrc, &pSrcSaved); DRISurfaceSetDrawable(dst, &dstSaved); DRIUnwrapGC(pGC); pReg = pGC->ops->CopyPlane(pSrc, dst, pGC, srcx, srcy, w, h, dstx, dsty, plane); DRIWrapGC(pGC); DRISurfaceRestoreDrawable(pSrc, &pSrcSaved); DRISurfaceRestoreDrawable(dst, &dstSaved); return pReg; } static void DRIPolyPoint(DrawablePtr dst, GCPtr pGC, int mode, int npt, DDXPointPtr pptInit) { DRISavedDrawableState saved; DRISurfaceSetDrawable(dst, &saved); DRIUnwrapGC(pGC); pGC->ops->PolyPoint(dst, pGC, mode, npt, pptInit); DRIWrapGC(pGC); DRISurfaceRestoreDrawable(dst, &saved); } static void DRIPolylines(DrawablePtr dst, GCPtr pGC, int mode, int npt, DDXPointPtr pptInit) { DRISavedDrawableState saved; DRISurfaceSetDrawable(dst, &saved); DRIUnwrapGC(pGC); pGC->ops->Polylines(dst, pGC, mode, npt, pptInit); DRIWrapGC(pGC); DRISurfaceRestoreDrawable(dst, &saved); } static void DRIPolySegment(DrawablePtr dst, GCPtr pGC, int nseg, xSegment *pSeg) { DRISavedDrawableState saved; DRISurfaceSetDrawable(dst, &saved); DRIUnwrapGC(pGC); pGC->ops->PolySegment(dst, pGC, nseg, pSeg); DRIWrapGC(pGC); DRISurfaceRestoreDrawable(dst, &saved); } static void DRIPolyRectangle(DrawablePtr dst, GCPtr pGC, int nRects, xRectangle *pRects) { DRISavedDrawableState saved; DRISurfaceSetDrawable(dst, &saved); DRIUnwrapGC(pGC); pGC->ops->PolyRectangle(dst, pGC, nRects, pRects); DRIWrapGC(pGC); DRISurfaceRestoreDrawable(dst, &saved); } static void DRIPolyArc(DrawablePtr dst, GCPtr pGC, int narcs, xArc *parcs) { DRISavedDrawableState saved; DRISurfaceSetDrawable(dst, &saved); DRIUnwrapGC(pGC); pGC->ops->PolyArc(dst, pGC, narcs, parcs); DRIWrapGC(pGC); DRISurfaceRestoreDrawable(dst, &saved); } static void DRIFillPolygon(DrawablePtr dst, GCPtr pGC, int shape, int mode, int count, DDXPointPtr pptInit) { DRISavedDrawableState saved; DRISurfaceSetDrawable(dst, &saved); DRIUnwrapGC(pGC); pGC->ops->FillPolygon(dst, pGC, shape, mode, count, pptInit); DRIWrapGC(pGC); DRISurfaceRestoreDrawable(dst, &saved); } static void DRIPolyFillRect(DrawablePtr dst, GCPtr pGC, int nRectsInit, xRectangle *pRectsInit) { DRISavedDrawableState saved; DRISurfaceSetDrawable(dst, &saved); DRIUnwrapGC(pGC); pGC->ops->PolyFillRect(dst, pGC, nRectsInit, pRectsInit); DRIWrapGC(pGC); DRISurfaceRestoreDrawable(dst, &saved); } static void DRIPolyFillArc(DrawablePtr dst, GCPtr pGC, int narcsInit, xArc *parcsInit) { DRISavedDrawableState saved; DRISurfaceSetDrawable(dst, &saved); DRIUnwrapGC(pGC); pGC->ops->PolyFillArc(dst, pGC, narcsInit, parcsInit); DRIWrapGC(pGC); DRISurfaceRestoreDrawable(dst, &saved); } static int DRIPolyText8(DrawablePtr dst, GCPtr pGC, int x, int y, int count, char *chars) { int ret; DRISavedDrawableState saved; DRISurfaceSetDrawable(dst, &saved); DRIUnwrapGC(pGC); ret = pGC->ops->PolyText8(dst, pGC, x, y, count, chars); DRIWrapGC(pGC); DRISurfaceRestoreDrawable(dst, &saved); return ret; } static int DRIPolyText16(DrawablePtr dst, GCPtr pGC, int x, int y, int count, unsigned short *chars) { int ret; DRISavedDrawableState saved; DRISurfaceSetDrawable(dst, &saved); DRIUnwrapGC(pGC); ret = pGC->ops->PolyText16(dst, pGC, x, y, count, chars); DRIWrapGC(pGC); DRISurfaceRestoreDrawable(dst, &saved); return ret; } static void DRIImageText8(DrawablePtr dst, GCPtr pGC, int x, int y, int count, char *chars) { DRISavedDrawableState saved; DRISurfaceSetDrawable(dst, &saved); DRIUnwrapGC(pGC); pGC->ops->ImageText8(dst, pGC, x, y, count, chars); DRIWrapGC(pGC); DRISurfaceRestoreDrawable(dst, &saved); } static void DRIImageText16(DrawablePtr dst, GCPtr pGC, int x, int y, int count, unsigned short *chars) { DRISavedDrawableState saved; DRISurfaceSetDrawable(dst, &saved); DRIUnwrapGC(pGC); pGC->ops->ImageText16(dst, pGC, x, y, count, chars); DRIWrapGC(pGC); DRISurfaceRestoreDrawable(dst, &saved); } static void DRIImageGlyphBlt(DrawablePtr dst, GCPtr pGC, int x, int y, unsigned int nglyphInit, CharInfoPtr *ppciInit, void *unused) { DRISavedDrawableState saved; DRISurfaceSetDrawable(dst, &saved); DRIUnwrapGC(pGC); pGC->ops->ImageGlyphBlt(dst, pGC, x, y, nglyphInit, ppciInit, unused); DRIWrapGC(pGC); DRISurfaceRestoreDrawable(dst, &saved); } static void DRIPolyGlyphBlt(DrawablePtr dst, GCPtr pGC, int x, int y, unsigned int nglyph, CharInfoPtr *ppci, void *pglyphBase) { DRISavedDrawableState saved; DRISurfaceSetDrawable(dst, &saved); DRIUnwrapGC(pGC); pGC->ops->PolyGlyphBlt(dst, pGC, x, y, nglyph, ppci, pglyphBase); DRIWrapGC(pGC); DRISurfaceRestoreDrawable(dst, &saved); } static void DRIPushPixels(GCPtr pGC, PixmapPtr pBitMap, DrawablePtr dst, int dx, int dy, int xOrg, int yOrg) { DRISavedDrawableState bitMapSaved, dstSaved; DRISurfaceSetDrawable(&pBitMap->drawable, &bitMapSaved); DRISurfaceSetDrawable(dst, &dstSaved); DRIUnwrapGC(pGC); pGC->ops->PushPixels(pGC, pBitMap, dst, dx, dy, xOrg, yOrg); DRIWrapGC(pGC); DRISurfaceRestoreDrawable(&pBitMap->drawable, &bitMapSaved); DRISurfaceRestoreDrawable(dst, &dstSaved); } static GCOps driGCOps = { DRIFillSpans, DRISetSpans, DRIPutImage, DRICopyArea, DRICopyPlane, DRIPolyPoint, DRIPolylines, DRIPolySegment, DRIPolyRectangle, DRIPolyArc, DRIFillPolygon, DRIPolyFillRect, DRIPolyFillArc, DRIPolyText8, DRIPolyText16, DRIImageText8, DRIImageText16, DRIImageGlyphBlt, DRIPolyGlyphBlt, DRIPushPixels }; static Bool DRICreateGC(GCPtr pGC) { ScreenPtr pScreen = pGC->pScreen; DRIWrapScreenRec *pScreenPriv; DRIGCRec *pGCPriv; Bool ret; pScreenPriv = dixLookupPrivate(&pScreen->devPrivates, driWrapScreenKey); pGCPriv = DRIGetGCPriv(pGC); unwrap(pScreenPriv, pScreen, CreateGC); ret = pScreen->CreateGC(pGC); if (ret) { pGCPriv->originalOps = pGC->ops; pGC->ops = &driGCOps; } wrap(pScreenPriv, pScreen, CreateGC, DRICreateGC); return ret; } /* Return false if an error occurred. */ Bool DRIWrapInit(ScreenPtr pScreen) { DRIWrapScreenRec *pScreenPriv; if (!dixRegisterPrivateKey(&driGCKeyRec, PRIVATE_GC, sizeof(DRIGCRec))) return FALSE; if (!dixRegisterPrivateKey(&driWrapScreenKeyRec, PRIVATE_SCREEN, sizeof(DRIWrapScreenRec))) return FALSE; pScreenPriv = dixGetPrivateAddr(&pScreen->devPrivates, &driWrapScreenKeyRec); pScreenPriv->CreateGC = pScreen->CreateGC; pScreen->CreateGC = DRICreateGC; return TRUE; }