502 lines
		
	
	
		
			13 KiB
		
	
	
	
		
			C
		
	
	
	
			
		
		
	
	
			502 lines
		
	
	
		
			13 KiB
		
	
	
	
		
			C
		
	
	
	
| /*
 | |
|  * Copyright © 2004 Eric Anholt
 | |
|  *
 | |
|  * Permission to use, copy, modify, distribute, and sell this software and its
 | |
|  * documentation for any purpose is hereby granted without fee, provided that
 | |
|  * the above copyright notice appear in all copies and that both that
 | |
|  * copyright notice and this permission notice appear in supporting
 | |
|  * documentation, and that the name of Eric Anholt not be used in
 | |
|  * advertising or publicity pertaining to distribution of the software without
 | |
|  * specific, written prior permission.  Eric Anholt makes no
 | |
|  * representations about the suitability of this software for any purpose.  It
 | |
|  * is provided "as is" without express or implied warranty.
 | |
|  *
 | |
|  * ERIC ANHOLT DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
 | |
|  * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
 | |
|  * EVENT SHALL ERIC ANHOLT BE LIABLE FOR ANY SPECIAL, INDIRECT OR
 | |
|  * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
 | |
|  * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
 | |
|  * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
 | |
|  * PERFORMANCE OF THIS SOFTWARE.
 | |
|  */
 | |
| /* $Header$ */
 | |
| 
 | |
| #ifdef HAVE_DIX_CONFIG_H
 | |
| #include <dix-config.h>
 | |
| #endif
 | |
| 
 | |
| #include "gcstruct.h"
 | |
| #include "windowstr.h"
 | |
| #include "cw.h"
 | |
| 
 | |
| #ifdef RENDER
 | |
| 
 | |
| #define cwPsDecl(pScreen)	\
 | |
|     PictureScreenPtr	ps = GetPictureScreen (pScreen);	\
 | |
|     cwScreenPtr		pCwScreen = getCwScreen (pScreen)
 | |
| 
 | |
| #define cwPicturePrivate					\
 | |
|     cwPicturePtr    pPicturePrivate = getCwPicture(pPicture)
 | |
| 
 | |
| #define cwSrcPictureDecl							\
 | |
|     int		    src_picture_x_off, src_picture_y_off;			\
 | |
|     PicturePtr	    pBackingSrcPicture = cwGetBackingPicture(pSrcPicture,	\
 | |
| 							     &src_picture_x_off,\
 | |
| 							     &src_picture_y_off)
 | |
| 
 | |
| #define cwDstPictureDecl							\
 | |
|     int		    dst_picture_x_off, dst_picture_y_off;			\
 | |
|     PicturePtr	    pBackingDstPicture = cwGetBackingPicture(pDstPicture,	\
 | |
| 							     &dst_picture_x_off,\
 | |
| 							     &dst_picture_y_off)
 | |
| 
 | |
| #define cwMskPictureDecl							\
 | |
|     int		    msk_picture_x_off = 0, msk_picture_y_off = 0;		\
 | |
|     PicturePtr	    pBackingMskPicture = (!pMskPicture ? 0 :	    		\
 | |
| 					  cwGetBackingPicture(pMskPicture,	\
 | |
| 							      &msk_picture_x_off,\
 | |
| 							      &msk_picture_y_off))
 | |
| 
 | |
| #define cwPsUnwrap(elt) {	\
 | |
|     ps->elt = pCwScreen->elt;	\
 | |
| }
 | |
| 
 | |
| #define cwPsWrap(elt,func) {	\
 | |
|     pCwScreen->elt = ps->elt;	\
 | |
|     ps->elt = func;		\
 | |
| }
 | |
| 
 | |
| static cwPicturePtr
 | |
| cwCreatePicturePrivate (PicturePtr pPicture)
 | |
| {
 | |
|     WindowPtr	    pWindow = (WindowPtr) pPicture->pDrawable;
 | |
|     PixmapPtr	    pPixmap = getCwPixmap (pWindow);
 | |
|     int		    error;
 | |
|     cwPicturePtr    pPicturePrivate;
 | |
| 
 | |
|     pPicturePrivate = xalloc (sizeof (cwPictureRec));
 | |
|     if (!pPicturePrivate)
 | |
| 	return NULL;
 | |
|     
 | |
|     pPicturePrivate->pBackingPicture = CreatePicture (0, &pPixmap->drawable, 
 | |
| 						      pPicture->pFormat,
 | |
| 						      0, 0, serverClient,
 | |
| 						      &error);
 | |
|     if (!pPicturePrivate->pBackingPicture)
 | |
|     {
 | |
| 	xfree (pPicturePrivate);
 | |
| 	return NULL;
 | |
|     }
 | |
| 
 | |
|     /*
 | |
|      * Ensure that this serial number does not match the window's
 | |
|      */
 | |
|     pPicturePrivate->serialNumber = pPixmap->drawable.serialNumber;
 | |
|     pPicturePrivate->stateChanges = (1 << (CPLastBit + 1)) - 1;
 | |
|     
 | |
|     setCwPicture(pPicture, pPicturePrivate);
 | |
| 
 | |
|     return pPicturePrivate;
 | |
| }
 | |
| 
 | |
| static void
 | |
| cwDestroyPicturePrivate (PicturePtr pPicture)
 | |
| {
 | |
|     cwPicturePrivate;
 | |
| 
 | |
|     if (pPicturePrivate)
 | |
|     {
 | |
| 	if (pPicturePrivate->pBackingPicture)
 | |
| 	    FreePicture (pPicturePrivate->pBackingPicture, 0);
 | |
| 	xfree (pPicturePrivate);
 | |
| 	setCwPicture(pPicture, NULL);
 | |
|     }
 | |
| }
 | |
| 
 | |
| static PicturePtr
 | |
| cwGetBackingPicture (PicturePtr pPicture, int *x_off, int *y_off)
 | |
| {
 | |
|     cwPicturePrivate;
 | |
| 
 | |
|     if (pPicturePrivate)
 | |
|     {
 | |
| 	DrawablePtr pDrawable = pPicture->pDrawable;
 | |
| 	WindowPtr   pWindow = (WindowPtr) pDrawable;
 | |
| 	PixmapPtr   pPixmap = getCwPixmap (pWindow);
 | |
| 
 | |
| 	*x_off = pDrawable->x - pPixmap->screen_x;
 | |
| 	*y_off = pDrawable->y - pPixmap->screen_y;
 | |
| 
 | |
| 	return pPicturePrivate->pBackingPicture;
 | |
|     }
 | |
|     else
 | |
|     {
 | |
| 	*x_off = *y_off = 0;
 | |
| 	return pPicture;
 | |
|     }
 | |
| }
 | |
|     
 | |
| static void
 | |
| cwDestroyPicture (PicturePtr pPicture)
 | |
| {
 | |
|     ScreenPtr		pScreen = pPicture->pDrawable->pScreen;
 | |
|     cwPsDecl(pScreen);
 | |
|     
 | |
|     cwPsUnwrap(DestroyPicture);
 | |
|     cwDestroyPicturePrivate (pPicture);
 | |
|     (*ps->DestroyPicture) (pPicture);
 | |
|     cwPsWrap(DestroyPicture, cwDestroyPicture);
 | |
| }
 | |
| 
 | |
| static void
 | |
| cwChangePicture (PicturePtr pPicture, Mask mask)
 | |
| {
 | |
|     ScreenPtr		pScreen = pPicture->pDrawable->pScreen;
 | |
|     cwPsDecl(pScreen);
 | |
|     cwPicturePtr	pPicturePrivate = getCwPicture(pPicture);
 | |
|     
 | |
|     cwPsUnwrap(ChangePicture);
 | |
|     (*ps->ChangePicture) (pPicture, mask);
 | |
|     if (pPicturePrivate)
 | |
| 	pPicturePrivate->stateChanges |= mask;
 | |
|     cwPsWrap(ChangePicture, cwChangePicture);
 | |
| }
 | |
| 
 | |
| 
 | |
| static void
 | |
| cwValidatePicture (PicturePtr pPicture,
 | |
| 		   Mask       mask)
 | |
| {
 | |
|     DrawablePtr		pDrawable = pPicture->pDrawable;
 | |
|     ScreenPtr		pScreen = pDrawable->pScreen;
 | |
|     cwPsDecl(pScreen);
 | |
|     cwPicturePrivate;
 | |
|     
 | |
|     cwPsUnwrap(ValidatePicture);
 | |
| 
 | |
|     /*
 | |
|      * Must call ValidatePicture to ensure pPicture->pCompositeClip is valid
 | |
|      */
 | |
|     (*ps->ValidatePicture) (pPicture, mask);
 | |
|     
 | |
|     if (!cwDrawableIsRedirWindow (pDrawable))
 | |
|     {
 | |
| 	if (pPicturePrivate)
 | |
| 	    cwDestroyPicturePrivate (pPicture);
 | |
|     }
 | |
|     else
 | |
|     {
 | |
| 	PicturePtr  pBackingPicture;
 | |
| 	DrawablePtr pBackingDrawable;
 | |
| 	int	    x_off, y_off;
 | |
| 	
 | |
| 	pBackingDrawable = cwGetBackingDrawable(pDrawable, &x_off, &y_off);
 | |
| 
 | |
| 	if (pPicturePrivate && 
 | |
| 	    pPicturePrivate->pBackingPicture->pDrawable != pBackingDrawable)
 | |
| 	{
 | |
| 	    cwDestroyPicturePrivate (pPicture);
 | |
| 	    pPicturePrivate = 0;
 | |
| 	}
 | |
| 
 | |
| 	if (!pPicturePrivate)
 | |
| 	{
 | |
| 	    pPicturePrivate = cwCreatePicturePrivate (pPicture);
 | |
| 	    if (!pPicturePrivate)
 | |
| 	    {
 | |
| 		cwPsWrap(ValidatePicture, cwValidatePicture);
 | |
| 		return;
 | |
| 	    }
 | |
| 	}
 | |
| 
 | |
| 	pBackingPicture = pPicturePrivate->pBackingPicture;
 | |
| 
 | |
| 	/*
 | |
| 	 * Always copy transform and filters because there's no
 | |
| 	 * indication of when they've changed
 | |
| 	 */
 | |
| 	SetPictureTransform(pBackingPicture, pPicture->transform);
 | |
| 	
 | |
| 	if (pBackingPicture->filter != pPicture->filter ||
 | |
| 	    pPicture->filter_nparams > 0)
 | |
| 	{
 | |
| 	    char    *filter = PictureGetFilterName (pPicture->filter);
 | |
| 	    
 | |
| 	    SetPictureFilter(pBackingPicture,
 | |
| 			     filter, strlen (filter),
 | |
| 			     pPicture->filter_params,
 | |
| 			     pPicture->filter_nparams);
 | |
| 	}
 | |
| 
 | |
| 	pPicturePrivate->stateChanges |= mask;
 | |
| 
 | |
| 	if (pPicturePrivate->serialNumber != pDrawable->serialNumber ||
 | |
| 	    (pPicturePrivate->stateChanges & (CPClipXOrigin|CPClipYOrigin|CPClipMask)))
 | |
| 	{
 | |
| 	    SetPictureClipRegion (pBackingPicture, 
 | |
| 				  x_off - pDrawable->x,
 | |
| 				  y_off - pDrawable->y,
 | |
| 				  pPicture->pCompositeClip);
 | |
|     
 | |
| 	    pPicturePrivate->serialNumber = pDrawable->serialNumber;
 | |
| 	    pPicturePrivate->stateChanges &= ~(CPClipXOrigin | CPClipYOrigin | CPClipMask);
 | |
| 	}
 | |
| 
 | |
| 	CopyPicture(pPicture, pPicturePrivate->stateChanges, pBackingPicture);
 | |
| 
 | |
| 	ValidatePicture (pBackingPicture);
 | |
|     }
 | |
|     cwPsWrap(ValidatePicture, cwValidatePicture);
 | |
| }
 | |
| 
 | |
| static void
 | |
| cwComposite (CARD8	op,
 | |
| 	     PicturePtr pSrcPicture,
 | |
| 	     PicturePtr pMskPicture,
 | |
| 	     PicturePtr pDstPicture,
 | |
| 	     INT16	xSrc,
 | |
| 	     INT16	ySrc,
 | |
| 	     INT16	xMsk,
 | |
| 	     INT16	yMsk,
 | |
| 	     INT16	xDst,
 | |
| 	     INT16	yDst,
 | |
| 	     CARD16	width,
 | |
| 	     CARD16	height)
 | |
| {
 | |
|     ScreenPtr	pScreen = pDstPicture->pDrawable->pScreen;
 | |
|     cwPsDecl(pScreen);
 | |
|     cwSrcPictureDecl;
 | |
|     cwMskPictureDecl;
 | |
|     cwDstPictureDecl;
 | |
|     
 | |
|     cwPsUnwrap(Composite);
 | |
|     (*ps->Composite) (op, pBackingSrcPicture, pBackingMskPicture, pBackingDstPicture,
 | |
| 		      xSrc + src_picture_x_off, ySrc + src_picture_y_off,
 | |
| 		      xMsk + msk_picture_x_off, yMsk + msk_picture_y_off,
 | |
| 		      xDst + dst_picture_x_off, yDst + dst_picture_y_off,
 | |
| 		      width, height);
 | |
|     cwPsWrap(Composite, cwComposite);
 | |
| }
 | |
| 
 | |
| static void
 | |
| cwGlyphs (CARD8      op,
 | |
| 	  PicturePtr pSrcPicture,
 | |
| 	  PicturePtr pDstPicture,
 | |
| 	  PictFormatPtr  maskFormat,
 | |
| 	  INT16      xSrc,
 | |
| 	  INT16      ySrc,
 | |
| 	  int	nlists,
 | |
| 	  GlyphListPtr   lists,
 | |
| 	  GlyphPtr	*glyphs)
 | |
| {
 | |
|     ScreenPtr	pScreen = pDstPicture->pDrawable->pScreen;
 | |
|     cwPsDecl(pScreen);
 | |
|     cwSrcPictureDecl;
 | |
|     cwDstPictureDecl;
 | |
|     
 | |
|     cwPsUnwrap(Glyphs);
 | |
|     if (nlists)
 | |
|     {
 | |
| 	lists->xOff += dst_picture_x_off;
 | |
| 	lists->yOff += dst_picture_y_off;
 | |
|     }
 | |
|     (*ps->Glyphs) (op, pBackingSrcPicture, pBackingDstPicture, maskFormat,
 | |
| 		   xSrc + src_picture_x_off, ySrc + src_picture_y_off,
 | |
| 		   nlists, lists, glyphs);
 | |
|     cwPsWrap(Glyphs, cwGlyphs);
 | |
| }
 | |
| 
 | |
| static void
 | |
| cwCompositeRects (CARD8		op,
 | |
| 		  PicturePtr	pDstPicture,
 | |
| 		  xRenderColor  *color,
 | |
| 		  int		nRect,
 | |
| 		  xRectangle	*rects)
 | |
| {
 | |
|     ScreenPtr	pScreen = pDstPicture->pDrawable->pScreen;
 | |
|     cwPsDecl(pScreen);
 | |
|     cwDstPictureDecl;
 | |
|     int i;
 | |
|     
 | |
|     cwPsUnwrap(CompositeRects);
 | |
|     for (i = 0; i < nRect; i++)
 | |
|     {
 | |
| 	rects[i].x += dst_picture_x_off;
 | |
| 	rects[i].y += dst_picture_y_off;
 | |
|     }
 | |
|     (*ps->CompositeRects) (op, pBackingDstPicture, color, nRect, rects);
 | |
|     cwPsWrap(CompositeRects, cwCompositeRects);
 | |
| }
 | |
| 
 | |
| static void
 | |
| cwTrapezoids (CARD8	    op,
 | |
| 	      PicturePtr    pSrcPicture,
 | |
| 	      PicturePtr    pDstPicture,
 | |
| 	      PictFormatPtr maskFormat,
 | |
| 	      INT16	    xSrc,
 | |
| 	      INT16	    ySrc,
 | |
| 	      int	    ntrap,
 | |
| 	      xTrapezoid    *traps)
 | |
| {
 | |
|     ScreenPtr	pScreen = pDstPicture->pDrawable->pScreen;
 | |
|     cwPsDecl(pScreen);
 | |
|     cwSrcPictureDecl;
 | |
|     cwDstPictureDecl;
 | |
|     int i;
 | |
|     
 | |
|     cwPsUnwrap(Trapezoids);
 | |
|     if (dst_picture_x_off || dst_picture_y_off) {
 | |
| 	for (i = 0; i < ntrap; i++)
 | |
| 	{
 | |
| 	    traps[i].top += dst_picture_y_off << 16;
 | |
| 	    traps[i].bottom += dst_picture_y_off << 16;
 | |
| 	    traps[i].left.p1.x += dst_picture_x_off << 16;
 | |
| 	    traps[i].left.p1.y += dst_picture_y_off << 16;
 | |
| 	    traps[i].left.p2.x += dst_picture_x_off << 16;
 | |
| 	    traps[i].left.p2.y += dst_picture_y_off << 16;
 | |
| 	    traps[i].right.p1.x += dst_picture_x_off << 16;
 | |
| 	    traps[i].right.p1.y += dst_picture_y_off << 16;
 | |
| 	    traps[i].right.p2.x += dst_picture_x_off << 16;
 | |
| 	    traps[i].right.p2.y += dst_picture_y_off << 16;
 | |
| 	}
 | |
|     }
 | |
|     (*ps->Trapezoids) (op, pBackingSrcPicture, pBackingDstPicture, maskFormat,
 | |
| 		       xSrc + src_picture_x_off, ySrc + src_picture_y_off,
 | |
| 		       ntrap, traps);
 | |
|     cwPsWrap(Trapezoids, cwTrapezoids);
 | |
| }
 | |
| 
 | |
| static void
 | |
| cwTriangles (CARD8	    op,
 | |
| 	     PicturePtr	    pSrcPicture,
 | |
| 	     PicturePtr	    pDstPicture,
 | |
| 	     PictFormatPtr  maskFormat,
 | |
| 	     INT16	    xSrc,
 | |
| 	     INT16	    ySrc,
 | |
| 	     int	    ntri,
 | |
| 	     xTriangle	   *tris)
 | |
| {
 | |
|     ScreenPtr	pScreen = pDstPicture->pDrawable->pScreen;
 | |
|     cwPsDecl(pScreen);
 | |
|     cwSrcPictureDecl;
 | |
|     cwDstPictureDecl;
 | |
|     int i;
 | |
|     
 | |
|     cwPsUnwrap(Triangles);
 | |
|     if (dst_picture_x_off || dst_picture_y_off) {
 | |
| 	for (i = 0; i < ntri; i++)
 | |
| 	{
 | |
| 	    tris[i].p1.x += dst_picture_x_off << 16;
 | |
| 	    tris[i].p1.y += dst_picture_y_off << 16;
 | |
| 	    tris[i].p2.x += dst_picture_x_off << 16;
 | |
| 	    tris[i].p2.y += dst_picture_y_off << 16;
 | |
| 	    tris[i].p3.x += dst_picture_x_off << 16;
 | |
| 	    tris[i].p3.y += dst_picture_y_off << 16;
 | |
| 	}
 | |
|     }
 | |
|     (*ps->Triangles) (op, pBackingSrcPicture, pBackingDstPicture, maskFormat,
 | |
| 		      xSrc + src_picture_x_off, ySrc + src_picture_y_off,
 | |
| 		      ntri, tris);
 | |
|     cwPsWrap(Triangles, cwTriangles);
 | |
| }
 | |
| 
 | |
| static void
 | |
| cwTriStrip (CARD8	    op,
 | |
| 	    PicturePtr	    pSrcPicture,
 | |
| 	    PicturePtr	    pDstPicture,
 | |
| 	    PictFormatPtr   maskFormat,
 | |
| 	    INT16	    xSrc,
 | |
| 	    INT16	    ySrc,
 | |
| 	    int		    npoint,
 | |
| 	    xPointFixed    *points)
 | |
| {
 | |
|     ScreenPtr	pScreen = pDstPicture->pDrawable->pScreen;
 | |
|     cwPsDecl(pScreen);
 | |
|     cwSrcPictureDecl;
 | |
|     cwDstPictureDecl;
 | |
|     int i;
 | |
| 
 | |
|     cwPsUnwrap(TriStrip);
 | |
|     if (dst_picture_x_off || dst_picture_y_off) {
 | |
| 	for (i = 0; i < npoint; i++)
 | |
| 	{
 | |
| 	    points[i].x += dst_picture_x_off << 16;
 | |
| 	    points[i].y += dst_picture_y_off << 16;
 | |
| 	}
 | |
|     }
 | |
|     (*ps->TriStrip) (op, pBackingSrcPicture, pBackingDstPicture, maskFormat,
 | |
| 		     xSrc + src_picture_x_off, ySrc + src_picture_y_off,
 | |
| 		     npoint, points);
 | |
|     cwPsWrap(TriStrip, cwTriStrip);
 | |
| }
 | |
| 
 | |
| static void
 | |
| cwTriFan (CARD8		 op,
 | |
| 	  PicturePtr	 pSrcPicture,
 | |
| 	  PicturePtr	 pDstPicture,
 | |
| 	  PictFormatPtr  maskFormat,
 | |
| 	  INT16		 xSrc,
 | |
| 	  INT16		 ySrc,
 | |
| 	  int		 npoint,
 | |
| 	  xPointFixed   *points)
 | |
| {
 | |
|     ScreenPtr	pScreen = pDstPicture->pDrawable->pScreen;
 | |
|     cwPsDecl(pScreen);
 | |
|     cwSrcPictureDecl;
 | |
|     cwDstPictureDecl;
 | |
|     int i;
 | |
| 
 | |
|     cwPsUnwrap(TriFan);
 | |
|     if (dst_picture_x_off || dst_picture_y_off) {
 | |
| 	for (i = 0; i < npoint; i++)
 | |
| 	{
 | |
| 	    points[i].x += dst_picture_x_off << 16;
 | |
| 	    points[i].y += dst_picture_y_off << 16;
 | |
| 	}
 | |
|     }
 | |
|     (*ps->TriFan) (op, pBackingSrcPicture, pBackingDstPicture, maskFormat,
 | |
| 		   xSrc + src_picture_x_off, ySrc + src_picture_y_off,
 | |
| 		   npoint, points);
 | |
|     cwPsWrap(TriFan, cwTriFan);
 | |
| }
 | |
| 
 | |
| void
 | |
| cwInitializeRender (ScreenPtr pScreen)
 | |
| {
 | |
|     cwPsDecl (pScreen);
 | |
| 
 | |
|     cwPsWrap(DestroyPicture, cwDestroyPicture);
 | |
|     cwPsWrap(ChangePicture, cwChangePicture);
 | |
|     cwPsWrap(ValidatePicture, cwValidatePicture);
 | |
|     cwPsWrap(Composite, cwComposite);
 | |
|     cwPsWrap(Glyphs, cwGlyphs);
 | |
|     cwPsWrap(CompositeRects, cwCompositeRects);
 | |
|     cwPsWrap(Trapezoids, cwTrapezoids);
 | |
|     cwPsWrap(Triangles, cwTriangles);
 | |
|     cwPsWrap(TriStrip, cwTriStrip);
 | |
|     cwPsWrap(TriFan, cwTriFan);
 | |
|     /* There is no need to wrap AddTraps as far as we can tell.  AddTraps can
 | |
|      * only be done on alpha-only pictures, and we won't be getting
 | |
|      * alpha-only window pictures, so there's no need to translate.
 | |
|      */
 | |
| }
 | |
| 
 | |
| void
 | |
| cwFiniRender (ScreenPtr pScreen)
 | |
| {
 | |
|     cwPsDecl (pScreen);
 | |
| 
 | |
|     cwPsUnwrap(DestroyPicture);
 | |
|     cwPsUnwrap(ChangePicture);
 | |
|     cwPsUnwrap(ValidatePicture);
 | |
|     cwPsUnwrap(Composite);
 | |
|     cwPsUnwrap(Glyphs);
 | |
|     cwPsUnwrap(CompositeRects);
 | |
|     cwPsUnwrap(Trapezoids);
 | |
|     cwPsUnwrap(Triangles);
 | |
|     cwPsUnwrap(TriStrip);
 | |
|     cwPsUnwrap(TriFan);
 | |
| }
 | |
| 
 | |
| #endif /* RENDER */
 |