548 lines
		
	
	
		
			12 KiB
		
	
	
	
		
			C
		
	
	
	
			
		
		
	
	
			548 lines
		
	
	
		
			12 KiB
		
	
	
	
		
			C
		
	
	
	
| /*
 | |
| Copyright (c) 2009 Apple Computer, 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, sub license, 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 (including the
 | |
| next paragraph) 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 NON-INFRINGEMENT.
 | |
| IN NO EVENT SHALL PRECISION INSIGHT AND/OR ITS SUPPLIERS 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.
 | |
| */
 | |
| #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 *originalOps;
 | |
|     GCOps *driOps;
 | |
| } DRIGCRec;
 | |
| 
 | |
| typedef struct {
 | |
|     GCOps *originalOps;
 | |
|     CreateGCProcPtr CreateGC;
 | |
| } DRIWrapScreenRec;
 | |
| 
 | |
| typedef struct {
 | |
|     Bool didSave;
 | |
|     int devKind;
 | |
|     DevUnion devPrivate;
 | |
| } DRISavedDrawableState;
 | |
| 
 | |
| static int driGCKeyIndex;
 | |
| static DevPrivateKey driGCKey = &driGCKeyIndex;
 | |
| 
 | |
| static int driWrapScreenKeyIndex;
 | |
| static DevPrivateKey driWrapScreenKey = &driWrapScreenKeyIndex;
 | |
| 
 | |
| 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) {
 | |
|     DRIGCRec *pGCPriv = DRIGetGCPriv(pGC);
 | |
|     
 | |
|     pGC->ops = pGCPriv->driOps;
 | |
| }
 | |
| 
 | |
| 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, pointer 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, pointer 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;
 | |
| 	pGCPriv->driOps = &driGCOps;
 | |
|     }
 | |
| 
 | |
|     wrap(pScreenPriv, pScreen, CreateGC, DRICreateGC);
 | |
|     
 | |
|     return ret;
 | |
| }
 | |
| 
 | |
| 
 | |
| /* Return false if an error occurred. */
 | |
| Bool 
 | |
| DRIWrapInit(ScreenPtr pScreen) {
 | |
|     DRIWrapScreenRec *pScreenPriv;
 | |
| 
 | |
|     if(!dixRequestPrivate(driGCKey, sizeof(DRIGCRec)))
 | |
| 	return FALSE;
 | |
| 
 | |
|     if(!dixRequestPrivate(driWrapScreenKey, sizeof(DRIWrapScreenRec)))
 | |
| 	return FALSE;
 | |
|     
 | |
|     pScreenPriv = xalloc(sizeof(*pScreenPriv));
 | |
| 
 | |
|     if(NULL == pScreenPriv)
 | |
| 	return FALSE;
 | |
| 
 | |
|     pScreenPriv->CreateGC = pScreen->CreateGC;
 | |
|     pScreen->CreateGC = DRICreateGC;
 | |
|     
 | |
|     dixSetPrivate(&pScreen->devPrivates, driWrapScreenKey, pScreenPriv);
 | |
|         
 | |
|     return TRUE;
 | |
| }
 |