570 lines
		
	
	
		
			12 KiB
		
	
	
	
		
			C
		
	
	
	
			
		
		
	
	
			570 lines
		
	
	
		
			12 KiB
		
	
	
	
		
			C
		
	
	
	
| /*
 | |
|  * 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 <dix-config.h>
 | |
| #endif
 | |
| 
 | |
| #include <stddef.h>
 | |
| #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 <OpenGL/OpenGL.h>
 | |
| 
 | |
| typedef struct {
 | |
|     GCOps const *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;
 | |
| }
 |