3248 lines
		
	
	
		
			71 KiB
		
	
	
	
		
			C
		
	
	
	
			
		
		
	
	
			3248 lines
		
	
	
		
			71 KiB
		
	
	
	
		
			C
		
	
	
	
| /*
 | |
|  * Id: s3draw.c,v 1.1 1999/11/02 03:54:47 keithp Exp $
 | |
|  *
 | |
|  * Copyright 1999 SuSE, Inc.
 | |
|  *
 | |
|  * 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 SuSE not be used in advertising or
 | |
|  * publicity pertaining to distribution of the software without specific,
 | |
|  * written prior permission.  SuSE makes no representations about the
 | |
|  * suitability of this software for any purpose.  It is provided "as is"
 | |
|  * without express or implied warranty.
 | |
|  *
 | |
|  * SuSE DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL
 | |
|  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL SuSE
 | |
|  * 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.
 | |
|  *
 | |
|  * Author:  Keith Packard, SuSE, Inc.
 | |
|  */
 | |
| /* $RCSId: xc/programs/Xserver/hw/kdrive/savage/s3draw.c,v 1.6 2001/05/29 04:54:11 keithp Exp $ */
 | |
| 
 | |
| #ifdef HAVE_CONFIG_H
 | |
| #include <config.h>
 | |
| #endif
 | |
| #include	"s3.h"
 | |
| #include	"s3draw.h"
 | |
| 
 | |
| #include	"Xmd.h"
 | |
| #include	"gcstruct.h"
 | |
| #include	"scrnintstr.h"
 | |
| #include	"pixmapstr.h"
 | |
| #include	"regionstr.h"
 | |
| #include	"mistruct.h"
 | |
| #include	"fontstruct.h"
 | |
| #include	"dixfontstr.h"
 | |
| #include	"fb.h"
 | |
| #include	"migc.h"
 | |
| #include	"miline.h"
 | |
| 
 | |
| /*
 | |
|  * Map X rops to S3 rops
 | |
|  */
 | |
| 
 | |
| short s3alu[16] = {
 | |
|     MIX_0,
 | |
|     MIX_AND,
 | |
|     MIX_SRC_AND_NOT_DST,
 | |
|     MIX_SRC,
 | |
|     MIX_NOT_SRC_AND_DST,
 | |
|     MIX_DST,
 | |
|     MIX_XOR,
 | |
|     MIX_OR,
 | |
|     MIX_NOR,
 | |
|     MIX_XNOR,
 | |
|     MIX_NOT_DST,
 | |
|     MIX_SRC_OR_NOT_DST,
 | |
|     MIX_NOT_SRC,
 | |
|     MIX_NOT_SRC_OR_DST,
 | |
|     MIX_NAND,
 | |
|     MIX_1
 | |
| };
 | |
| 
 | |
| /*
 | |
|  * Handle pixel transfers
 | |
|  */
 | |
| 
 | |
| #define BURST
 | |
| #ifdef BURST
 | |
| #define PixTransDeclare	VOL32	*pix_trans_base = (VOL32 *) (s3c->registers),\
 | |
| 				*pix_trans = pix_trans_base
 | |
| #define PixTransStart(n)	if (pix_trans + (n) > pix_trans_base + 8192) pix_trans = pix_trans_base
 | |
| #define PixTransStore(t)	*pix_trans++ = (t)
 | |
| #else
 | |
| #define PixTransDeclare	VOL32	*pix_trans = &s3->pix_trans
 | |
| #define PixTransStart(n)	
 | |
| #define PixTransStore(t)	*pix_trans = (t)
 | |
| #endif
 | |
| 
 | |
| int	s3GCPrivateIndex;
 | |
| int	s3WindowPrivateIndex;
 | |
| int	s3Generation;
 | |
| 
 | |
| /*
 | |
|   s3DoBitBlt
 | |
|   =============
 | |
|   Bit Blit for all window to window blits.
 | |
| */
 | |
| 
 | |
| #define sourceInvarient(alu)	(((alu) & 3) == (((alu) >> 2) & 3))
 | |
| 
 | |
| void
 | |
| s3CopyNtoN (DrawablePtr	pSrcDrawable,
 | |
| 	    DrawablePtr	pDstDrawable,
 | |
| 	    GCPtr	pGC,
 | |
| 	    BoxPtr	pbox,
 | |
| 	    int		nbox,
 | |
| 	    int		dx,
 | |
| 	    int		dy,
 | |
| 	    Bool	reverse,
 | |
| 	    Bool	upsidedown,
 | |
| 	    Pixel	bitplane,
 | |
| 	    void	*closure)
 | |
| {
 | |
|     SetupS3(pDstDrawable->pScreen);
 | |
|     int	    srcX, srcY, dstX, dstY;
 | |
|     int	    w, h;
 | |
|     int	    flags;
 | |
|     
 | |
|     if (sourceInvarient (pGC->alu))
 | |
|     {
 | |
| 	s3FillBoxSolid (pDstDrawable, nbox, pbox, 0, pGC->alu, pGC->planemask);
 | |
| 	return;
 | |
|     }
 | |
|     
 | |
|     s3SetGlobalBitmap (pDstDrawable->pScreen, s3GCMap (pGC));
 | |
|     _s3SetBlt(s3,pGC->alu,pGC->planemask);
 | |
|     DRAW_DEBUG ((DEBUG_RENDER, "s3CopyNtoN alu %d planemask 0x%x",
 | |
| 		pGC->alu, pGC->planemask));
 | |
|     while (nbox--)
 | |
|     {
 | |
| 	w = pbox->x2 - pbox->x1;
 | |
| 	h = pbox->y2 - pbox->y1;
 | |
| 	flags = 0;
 | |
| 	if (reverse)
 | |
| 	{
 | |
| 	    dstX = pbox->x2 - 1;
 | |
| 	}
 | |
| 	else
 | |
| 	{
 | |
| 	    dstX = pbox->x1;
 | |
| 	    flags |= INC_X;
 | |
| 	}
 | |
| 	srcX = dstX + dx;
 | |
| 	
 | |
| 	if (upsidedown)
 | |
| 	{
 | |
| 	    dstY = pbox->y2 - 1;
 | |
| 	}
 | |
| 	else
 | |
| 	{
 | |
| 	    dstY = pbox->y1;
 | |
| 	    flags |= INC_Y;
 | |
| 	}
 | |
| 	srcY = dstY + dy;
 | |
| 	
 | |
| 	_s3Blt (s3, srcX, srcY, dstX, dstY, w, h, flags);
 | |
| 	pbox++;
 | |
|     }
 | |
|     MarkSyncS3 (pSrcDrawable->pScreen);
 | |
| }
 | |
| 
 | |
| RegionPtr
 | |
| s3CopyArea(DrawablePtr pSrcDrawable, DrawablePtr pDstDrawable, GCPtr pGC,
 | |
| 	   int srcx, int srcy, int width, int height, int dstx, int dsty)
 | |
| {
 | |
|     SetupS3(pDstDrawable->pScreen);
 | |
|     
 | |
|     if (pSrcDrawable->type == DRAWABLE_WINDOW &&
 | |
| 	pDstDrawable->type == DRAWABLE_WINDOW)
 | |
|     {
 | |
| 	return fbDoCopy (pSrcDrawable, pDstDrawable, pGC, 
 | |
| 			 srcx, srcy, width, height, 
 | |
| 			 dstx, dsty, s3CopyNtoN, 0, 0);
 | |
|     }
 | |
|     return KdCheckCopyArea (pSrcDrawable, pDstDrawable, pGC, 
 | |
| 			    srcx, srcy, width, height, dstx, dsty);
 | |
| }
 | |
| 
 | |
| typedef struct _s31toNargs {
 | |
|     unsigned long	copyPlaneFG, copyPlaneBG;
 | |
|     Bool		opaque;
 | |
| } s31toNargs;
 | |
| 
 | |
| void
 | |
| _s3Stipple (S3CardInfo	*s3c,
 | |
| 	    FbStip	*psrcBase,
 | |
| 	    FbStride	widthSrc,
 | |
| 	    int		srcx,
 | |
| 	    int		srcy,
 | |
| 	    int		dstx,
 | |
| 	    int		dsty,
 | |
| 	    int		width,
 | |
| 	    int		height)
 | |
| {
 | |
|     S3Ptr	s3 = s3c->s3;
 | |
|     FbStip	*psrcLine, *psrc;
 | |
|     FbStride	widthRest;
 | |
|     FbStip	bits, tmp, lastTmp;
 | |
|     int		leftShift, rightShift;
 | |
|     int		nl, nlMiddle;
 | |
|     int		r;
 | |
|     PixTransDeclare;
 | |
|     
 | |
|     /* Compute blt address and parameters */
 | |
|     psrc = psrcBase + srcy * widthSrc + (srcx >> 5);
 | |
|     nlMiddle = (width + 31) >> 5;
 | |
|     leftShift = srcx & 0x1f;
 | |
|     rightShift = 32 - leftShift;
 | |
|     widthRest = widthSrc - nlMiddle;
 | |
|     
 | |
|     _s3PlaneBlt(s3,dstx,dsty,width,height);
 | |
|     
 | |
|     if (leftShift == 0)
 | |
|     {
 | |
| 	while (height--)
 | |
| 	{
 | |
| 	    nl = nlMiddle;
 | |
| 	    PixTransStart(nl);
 | |
| 	    while (nl--)
 | |
| 	    {
 | |
| 		tmp = *psrc++;
 | |
| 		S3AdjustBits32 (tmp);
 | |
| 		PixTransStore (tmp);
 | |
| 	    }
 | |
| 	    psrc += widthRest;
 | |
| 	}
 | |
|     }
 | |
|     else
 | |
|     {
 | |
| 	widthRest--;
 | |
| 	while (height--)
 | |
| 	{
 | |
| 	    bits = *psrc++;
 | |
| 	    nl = nlMiddle;
 | |
| 	    PixTransStart(nl);
 | |
| 	    while (nl--)
 | |
| 	    {
 | |
| 		tmp = FbStipLeft(bits, leftShift);
 | |
| 		bits = *psrc++;
 | |
| 		tmp |= FbStipRight(bits, rightShift);
 | |
| 		S3AdjustBits32(tmp);
 | |
| 		PixTransStore (tmp);
 | |
| 	    }
 | |
| 	    psrc += widthRest;
 | |
| 	}
 | |
|     }
 | |
| }
 | |
| 	    
 | |
| void
 | |
| s3Copy1toN (DrawablePtr	pSrcDrawable,
 | |
| 	    DrawablePtr	pDstDrawable,
 | |
| 	    GCPtr	pGC,
 | |
| 	    BoxPtr	pbox,
 | |
| 	    int		nbox,
 | |
| 	    int		dx,
 | |
| 	    int		dy,
 | |
| 	    Bool	reverse,
 | |
| 	    Bool	upsidedown,
 | |
| 	    Pixel	bitplane,
 | |
| 	    void	*closure)
 | |
| {
 | |
|     SetupS3(pDstDrawable->pScreen);
 | |
|     
 | |
|     s31toNargs		*args = closure;
 | |
|     int			dstx, dsty;
 | |
|     FbStip		*psrcBase;
 | |
|     FbStride		widthSrc;
 | |
|     int			srcBpp;
 | |
|     int			srcXoff, srcYoff;
 | |
| 
 | |
|     if (args->opaque && sourceInvarient (pGC->alu))
 | |
|     {
 | |
| 	s3FillBoxSolid (pDstDrawable, nbox, pbox,
 | |
| 			pGC->bgPixel, pGC->alu, pGC->planemask);
 | |
| 	return;
 | |
|     }
 | |
|     
 | |
|     s3SetGlobalBitmap (pDstDrawable->pScreen, s3GCMap (pGC));
 | |
|     fbGetStipDrawable (pSrcDrawable, psrcBase, widthSrc, srcBpp, srcXoff, srcYoff);
 | |
|     
 | |
|     if (args->opaque)
 | |
|     {
 | |
| 	_s3SetOpaquePlaneBlt(s3,pGC->alu,pGC->planemask,args->copyPlaneFG,
 | |
| 			     args->copyPlaneBG);
 | |
|     }
 | |
|     else
 | |
|     {
 | |
| 	_s3SetTransparentPlaneBlt (s3, pGC->alu, 
 | |
| 				   pGC->planemask, args->copyPlaneFG);
 | |
|     }
 | |
|     
 | |
|     while (nbox--)
 | |
|     {
 | |
| 	dstx = pbox->x1;
 | |
| 	dsty = pbox->y1;
 | |
| 	
 | |
| 	_s3Stipple (s3c,
 | |
| 		    psrcBase, widthSrc, 
 | |
| 		    dstx + dx - srcXoff, dsty + dy - srcYoff,
 | |
| 		    dstx, dsty, 
 | |
| 		    pbox->x2 - dstx, pbox->y2 - dsty);
 | |
| 	pbox++;
 | |
|     }
 | |
|     MarkSyncS3 (pDstDrawable->pScreen);
 | |
| }
 | |
| 
 | |
| RegionPtr
 | |
| s3CopyPlane(DrawablePtr pSrcDrawable, DrawablePtr pDstDrawable, GCPtr pGC,
 | |
| 	int srcx, int srcy, int width, int height, 
 | |
| 	int dstx, int dsty, unsigned long bitPlane)
 | |
| {
 | |
|     SetupS3 (pDstDrawable->pScreen);
 | |
|     RegionPtr		ret;
 | |
|     s31toNargs		args;
 | |
| 
 | |
|     if (pDstDrawable->type == DRAWABLE_WINDOW &&
 | |
| 	pSrcDrawable->depth == 1)
 | |
|     {
 | |
| 	args.copyPlaneFG = pGC->fgPixel;
 | |
| 	args.copyPlaneBG = pGC->bgPixel;
 | |
| 	args.opaque = TRUE;
 | |
| 	return fbDoCopy (pSrcDrawable, pDstDrawable, pGC, 
 | |
| 			 srcx, srcy, width, height, 
 | |
| 			 dstx, dsty, s3Copy1toN, bitPlane, &args);
 | |
|     }
 | |
|     return KdCheckCopyPlane(pSrcDrawable, pDstDrawable, pGC, 
 | |
| 			    srcx, srcy, width, height, 
 | |
| 			    dstx, dsty, bitPlane);
 | |
| }
 | |
| 
 | |
| void
 | |
| s3PushPixels (GCPtr pGC, PixmapPtr pBitmap,
 | |
| 	      DrawablePtr pDrawable,
 | |
| 	      int w, int h, int x, int y)
 | |
| {
 | |
|     SetupS3 (pDrawable->pScreen);
 | |
|     s31toNargs		args;
 | |
|     
 | |
|     if (pDrawable->type == DRAWABLE_WINDOW && pGC->fillStyle == FillSolid)
 | |
|     {
 | |
| 	args.opaque = FALSE;
 | |
| 	args.copyPlaneFG = pGC->fgPixel;
 | |
| 	(void) fbDoCopy ((DrawablePtr) pBitmap, pDrawable, pGC,
 | |
| 			  0, 0, w, h, x, y, s3Copy1toN, 1, &args);
 | |
|     }
 | |
|     else
 | |
|     {
 | |
| 	KdCheckPushPixels (pGC, pBitmap, pDrawable, w, h, x, y);
 | |
|     }
 | |
| }
 | |
| 
 | |
| void
 | |
| s3FillBoxSolid (DrawablePtr pDrawable, int nBox, BoxPtr pBox, 
 | |
| 		unsigned long pixel, int alu, unsigned long planemask)
 | |
| {
 | |
|     SetupS3(pDrawable->pScreen);
 | |
|     register int	r;
 | |
| 
 | |
|     s3SetGlobalBitmap (pDrawable->pScreen, s3DrawMap (pDrawable));
 | |
|     _s3SetSolidFill(s3,pixel,alu,planemask);
 | |
|     
 | |
|     while (nBox--) {
 | |
| 	_s3SolidRect(s3,pBox->x1,pBox->y1,pBox->x2-pBox->x1,pBox->y2-pBox->y1);
 | |
| 	pBox++;
 | |
|     }
 | |
|     MarkSyncS3 (pDrawable->pScreen);
 | |
| }
 | |
| 
 | |
| void
 | |
| _s3SetPattern (ScreenPtr pScreen, int ma,
 | |
| 	      int alu, unsigned long planemask, s3PatternPtr pPattern)
 | |
| {
 | |
|     SetupS3(pScreen);
 | |
|     S3PatternCache  *cache;
 | |
|     
 | |
|     _s3LoadPattern (pScreen, ma, pPattern);
 | |
|     cache = pPattern->cache;
 | |
|     
 | |
|     switch (pPattern->fillStyle) {
 | |
|     case FillTiled:
 | |
| 	_s3SetTile(s3,alu,planemask);
 | |
| 	break;
 | |
|     case FillStippled:
 | |
| 	_s3SetStipple(s3,alu,planemask,pPattern->fore);
 | |
| 	break;
 | |
|     case FillOpaqueStippled:
 | |
| 	_s3SetOpaqueStipple(s3,alu,planemask,pPattern->fore,pPattern->back);
 | |
| 	break;
 | |
|     }
 | |
| }
 | |
| 
 | |
| void
 | |
| s3FillBoxPattern (DrawablePtr pDrawable, int nBox, BoxPtr pBox, 
 | |
| 		  int alu, unsigned long planemask, s3PatternPtr pPattern)
 | |
| {
 | |
|     SetupS3(pDrawable->pScreen);
 | |
|     S3PatternCache    	*cache;
 | |
|     int			patx, paty;
 | |
| 
 | |
|     s3SetGlobalBitmap (pDrawable->pScreen, s3DrawMap (pDrawable));
 | |
|     _s3SetPattern (pDrawable->pScreen, s3DrawMap(pDrawable), alu, planemask, pPattern);
 | |
|     cache = pPattern->cache;
 | |
|     while (nBox--) 
 | |
|     {
 | |
| 	_s3PatRect(s3,cache->x, cache->y,
 | |
| 		   pBox->x1, pBox->y1, 
 | |
| 		   pBox->x2-pBox->x1, pBox->y2-pBox->y1);
 | |
| 	pBox++;
 | |
|     }
 | |
|     MarkSyncS3 (pDrawable->pScreen);
 | |
| }
 | |
| 
 | |
| void
 | |
| s3FillBoxLargeStipple (DrawablePtr pDrawable, GCPtr pGC,
 | |
| 		       int nBox, BoxPtr pBox)
 | |
| {
 | |
|     SetupS3(pDrawable->pScreen);
 | |
|     DrawablePtr	pStipple = &pGC->stipple->drawable;
 | |
|     int		xRot = pGC->patOrg.x + pDrawable->x;
 | |
|     int		yRot = pGC->patOrg.y + pDrawable->y;
 | |
|     FbStip	*stip;
 | |
|     FbStride	stipStride;
 | |
|     int		stipBpp;
 | |
|     int		stipXoff, stipYoff;
 | |
|     int		stipWidth, stipHeight;
 | |
|     int		dstX, dstY, width, height;
 | |
|     
 | |
|     stipWidth = pStipple->width;
 | |
|     stipHeight = pStipple->height;
 | |
|     fbGetStipDrawable (pStipple, stip, stipStride, stipBpp, stipXoff, stipYoff);
 | |
| 
 | |
|     s3SetGlobalBitmap (pDrawable->pScreen, s3DrawMap (pDrawable));
 | |
|     if (pGC->fillStyle == FillOpaqueStippled)
 | |
|     {
 | |
| 	_s3SetOpaquePlaneBlt(s3,pGC->alu,pGC->planemask,
 | |
| 			     pGC->fgPixel, pGC->bgPixel);
 | |
|     
 | |
|     }
 | |
|     else
 | |
|     {
 | |
| 	_s3SetTransparentPlaneBlt(s3,pGC->alu,pGC->planemask, pGC->fgPixel);
 | |
|     }
 | |
|     
 | |
|     while (nBox--)
 | |
|     {
 | |
| 	int		stipX, stipY, sx;
 | |
| 	int		widthTmp;
 | |
| 	int		h, w;
 | |
| 	int		x, y;
 | |
|     
 | |
| 	dstX = pBox->x1;
 | |
| 	dstY = pBox->y1;
 | |
| 	width = pBox->x2 - pBox->x1;
 | |
| 	height = pBox->y2 - pBox->y1;
 | |
| 	pBox++;
 | |
| 	modulus (dstY - yRot - stipYoff, stipHeight, stipY);
 | |
| 	modulus (dstX - xRot - stipXoff, stipWidth, stipX);
 | |
| 	y = dstY;
 | |
| 	while (height)
 | |
| 	{
 | |
| 	    h = stipHeight - stipY;
 | |
| 	    if (h > height)
 | |
| 		h = height;
 | |
| 	    height -= h;
 | |
| 	    widthTmp = width;
 | |
| 	    x = dstX;
 | |
| 	    sx = stipX;
 | |
| 	    while (widthTmp)
 | |
| 	    {
 | |
| 		w = (stipWidth - sx);
 | |
| 		if (w > widthTmp)
 | |
| 		    w = widthTmp;
 | |
| 		widthTmp -= w;
 | |
| 		_s3Stipple (s3c,
 | |
| 			    stip,
 | |
| 			    stipStride,
 | |
| 			    sx, stipY,
 | |
| 			    x, y,
 | |
| 			    w, h);
 | |
| 		x += w;
 | |
| 		sx = 0;
 | |
| 	    }
 | |
| 	    y += h;
 | |
| 	    stipY = 0;
 | |
| 	}
 | |
|     }
 | |
|     MarkSyncS3 (pDrawable->pScreen);
 | |
| }
 | |
| 
 | |
| #define NUM_STACK_RECTS	1024
 | |
| 
 | |
| void
 | |
| s3PolyFillRect (DrawablePtr pDrawable, GCPtr pGC, 
 | |
| 		int nrectFill, xRectangle *prectInit)
 | |
| {
 | |
|     s3GCPrivate(pGC);
 | |
|     xRectangle	    *prect;
 | |
|     RegionPtr	    prgnClip;
 | |
|     register BoxPtr pbox;
 | |
|     register BoxPtr pboxClipped;
 | |
|     BoxPtr	    pboxClippedBase;
 | |
|     BoxPtr	    pextent;
 | |
|     BoxRec	    stackRects[NUM_STACK_RECTS];
 | |
|     int		    numRects;
 | |
|     int		    n;
 | |
|     int		    xorg, yorg;
 | |
|     int		    x, y;
 | |
| 
 | |
|     prgnClip = fbGetCompositeClip(pGC);
 | |
|     xorg = pDrawable->x;
 | |
|     yorg = pDrawable->y;
 | |
|     
 | |
|     if (xorg || yorg)
 | |
|     {
 | |
| 	prect = prectInit;
 | |
| 	n = nrectFill;
 | |
| 	while(n--)
 | |
| 	{
 | |
| 	    prect->x += xorg;
 | |
| 	    prect->y += yorg;
 | |
| 	    prect++;
 | |
| 	}
 | |
|     }
 | |
|     
 | |
|     prect = prectInit;
 | |
| 
 | |
|     numRects = REGION_NUM_RECTS(prgnClip) * nrectFill;
 | |
|     if (numRects > NUM_STACK_RECTS)
 | |
|     {
 | |
| 	pboxClippedBase = (BoxPtr)ALLOCATE_LOCAL(numRects * sizeof(BoxRec));
 | |
| 	if (!pboxClippedBase)
 | |
| 	    return;
 | |
|     }
 | |
|     else
 | |
| 	pboxClippedBase = stackRects;
 | |
| 
 | |
|     pboxClipped = pboxClippedBase;
 | |
| 	
 | |
|     if (REGION_NUM_RECTS(prgnClip) == 1)
 | |
|     {
 | |
| 	int x1, y1, x2, y2, bx2, by2;
 | |
| 
 | |
| 	pextent = REGION_RECTS(prgnClip);
 | |
| 	x1 = pextent->x1;
 | |
| 	y1 = pextent->y1;
 | |
| 	x2 = pextent->x2;
 | |
| 	y2 = pextent->y2;
 | |
|     	while (nrectFill--)
 | |
|     	{
 | |
| 	    if ((pboxClipped->x1 = prect->x) < x1)
 | |
| 		pboxClipped->x1 = x1;
 | |
|     
 | |
| 	    if ((pboxClipped->y1 = prect->y) < y1)
 | |
| 		pboxClipped->y1 = y1;
 | |
|     
 | |
| 	    bx2 = (int) prect->x + (int) prect->width;
 | |
| 	    if (bx2 > x2)
 | |
| 		bx2 = x2;
 | |
| 	    pboxClipped->x2 = bx2;
 | |
|     
 | |
| 	    by2 = (int) prect->y + (int) prect->height;
 | |
| 	    if (by2 > y2)
 | |
| 		by2 = y2;
 | |
| 	    pboxClipped->y2 = by2;
 | |
| 
 | |
| 	    prect++;
 | |
| 	    if ((pboxClipped->x1 < pboxClipped->x2) &&
 | |
| 		(pboxClipped->y1 < pboxClipped->y2))
 | |
| 	    {
 | |
| 		pboxClipped++;
 | |
| 	    }
 | |
|     	}
 | |
|     }
 | |
|     else
 | |
|     {
 | |
| 	int x1, y1, x2, y2, bx2, by2;
 | |
| 
 | |
| 	pextent = REGION_EXTENTS(pGC->pScreen, prgnClip);
 | |
| 	x1 = pextent->x1;
 | |
| 	y1 = pextent->y1;
 | |
| 	x2 = pextent->x2;
 | |
| 	y2 = pextent->y2;
 | |
|     	while (nrectFill--)
 | |
|     	{
 | |
| 	    BoxRec box;
 | |
|     
 | |
| 	    if ((box.x1 = prect->x) < x1)
 | |
| 		box.x1 = x1;
 | |
|     
 | |
| 	    if ((box.y1 = prect->y) < y1)
 | |
| 		box.y1 = y1;
 | |
|     
 | |
| 	    bx2 = (int) prect->x + (int) prect->width;
 | |
| 	    if (bx2 > x2)
 | |
| 		bx2 = x2;
 | |
| 	    box.x2 = bx2;
 | |
|     
 | |
| 	    by2 = (int) prect->y + (int) prect->height;
 | |
| 	    if (by2 > y2)
 | |
| 		by2 = y2;
 | |
| 	    box.y2 = by2;
 | |
|     
 | |
| 	    prect++;
 | |
|     
 | |
| 	    if ((box.x1 >= box.x2) || (box.y1 >= box.y2))
 | |
| 	    	continue;
 | |
|     
 | |
| 	    n = REGION_NUM_RECTS (prgnClip);
 | |
| 	    pbox = REGION_RECTS(prgnClip);
 | |
|     
 | |
| 	    /* clip the rectangle to each box in the clip region
 | |
| 	       this is logically equivalent to calling Intersect()
 | |
| 	    */
 | |
| 	    while(n--)
 | |
| 	    {
 | |
| 		pboxClipped->x1 = max(box.x1, pbox->x1);
 | |
| 		pboxClipped->y1 = max(box.y1, pbox->y1);
 | |
| 		pboxClipped->x2 = min(box.x2, pbox->x2);
 | |
| 		pboxClipped->y2 = min(box.y2, pbox->y2);
 | |
| 		pbox++;
 | |
| 
 | |
| 		/* see if clipping left anything */
 | |
| 		if(pboxClipped->x1 < pboxClipped->x2 && 
 | |
| 		   pboxClipped->y1 < pboxClipped->y2)
 | |
| 		{
 | |
| 		    pboxClipped++;
 | |
| 		}
 | |
| 	    }
 | |
|     	}
 | |
|     }
 | |
|     if (pboxClipped != pboxClippedBase)
 | |
|     {
 | |
| 	if (pGC->fillStyle == FillSolid)
 | |
| 	    s3FillBoxSolid(pDrawable,
 | |
| 			   pboxClipped-pboxClippedBase, pboxClippedBase,
 | |
| 			   pGC->fgPixel, pGC->alu, pGC->planemask);
 | |
| 	else if (s3Priv->pPattern)
 | |
| 	    s3FillBoxPattern (pDrawable,
 | |
| 			      pboxClipped-pboxClippedBase, pboxClippedBase,
 | |
| 			      pGC->alu, pGC->planemask,
 | |
| 			      s3Priv->pPattern);
 | |
| 	else
 | |
| 	    s3FillBoxLargeStipple (pDrawable, pGC,
 | |
| 				   pboxClipped-pboxClippedBase, 
 | |
| 				   pboxClippedBase);
 | |
|     }
 | |
|     if (pboxClippedBase != stackRects)
 | |
|     	DEALLOCATE_LOCAL(pboxClippedBase);
 | |
| }
 | |
| 
 | |
| void
 | |
| _s3FillSpanLargeStipple (DrawablePtr pDrawable, GCPtr pGC,
 | |
| 			 int n, DDXPointPtr ppt, int *pwidth)
 | |
| {
 | |
|     SetupS3 (pDrawable->pScreen);
 | |
|     DrawablePtr	pStipple = &pGC->stipple->drawable;
 | |
|     int		xRot = pGC->patOrg.x + pDrawable->x;
 | |
|     int		yRot = pGC->patOrg.y + pDrawable->y;
 | |
|     FbStip	*stip;
 | |
|     FbStride	stipStride;
 | |
|     int		stipBpp;
 | |
|     int		stipXoff, stipYoff;
 | |
|     int		stipWidth, stipHeight;
 | |
|     int		dstX, dstY, width, height;
 | |
|     
 | |
|     s3SetGlobalBitmap (pDrawable->pScreen, s3GCMap (pGC));
 | |
|     stipWidth = pStipple->width;
 | |
|     stipHeight = pStipple->height;
 | |
|     fbGetStipDrawable (pStipple, stip, stipStride, stipBpp, stipXoff, stipYoff);
 | |
|     if (pGC->fillStyle == FillOpaqueStippled)
 | |
|     {
 | |
| 	_s3SetOpaquePlaneBlt(s3,pGC->alu,pGC->planemask,
 | |
| 			     pGC->fgPixel, pGC->bgPixel);
 | |
|     
 | |
|     }
 | |
|     else
 | |
|     {
 | |
| 	_s3SetTransparentPlaneBlt(s3,pGC->alu,pGC->planemask, pGC->fgPixel);
 | |
|     }
 | |
|     while (n--)
 | |
|     {
 | |
| 	int		stipX, stipY, sx;
 | |
| 	int		w;
 | |
| 	int		x, y;
 | |
|     
 | |
| 	dstX = ppt->x;
 | |
| 	dstY = ppt->y;
 | |
| 	ppt++;
 | |
| 	width = *pwidth++;
 | |
| 	modulus (dstY - yRot - stipYoff, stipHeight, stipY);
 | |
| 	modulus (dstX - xRot - stipXoff, stipWidth, stipX);
 | |
| 	y = dstY;
 | |
| 	x = dstX;
 | |
| 	sx = stipX;
 | |
| 	while (width)
 | |
| 	{
 | |
| 	    w = (stipWidth - sx);
 | |
| 	    if (w > width)
 | |
| 		w = width;
 | |
| 	    width -= w;
 | |
| 	    _s3Stipple (s3c,
 | |
| 			stip,
 | |
| 			stipStride,
 | |
| 			sx, stipY,
 | |
| 			x, y,
 | |
| 			w, 1);
 | |
| 	    x += w;
 | |
| 	    sx = 0;
 | |
| 	}
 | |
|     }
 | |
| }
 | |
| 
 | |
| void
 | |
| s3FillSpans (DrawablePtr pDrawable, GCPtr pGC, int n, 
 | |
| 	     DDXPointPtr ppt, int *pwidth, int fSorted)
 | |
| {
 | |
|     s3GCPrivate(pGC);
 | |
|     SetupS3(pDrawable->pScreen);
 | |
|     int		    x, y, x1, y1, x2, y2;
 | |
|     int		    width;
 | |
| 				/* next three parameters are post-clip */
 | |
|     int		    nTmp;
 | |
|     int		    *pwidthFree;/* copies of the pointers to free */
 | |
|     DDXPointPtr	    pptFree;
 | |
|     BoxPtr	    extents;
 | |
|     S3PatternCache  *cache;
 | |
|     RegionPtr	    pClip = fbGetCompositeClip (pGC);
 | |
| 
 | |
|     s3SetGlobalBitmap (pDrawable->pScreen, s3GCMap (pGC));
 | |
|     if (REGION_NUM_RECTS(pClip) == 1 && 
 | |
| 	(pGC->fillStyle == FillSolid  || s3Priv->pPattern))
 | |
|     {
 | |
| 	extents = REGION_RECTS(pClip);
 | |
| 	x1 = extents->x1;
 | |
| 	x2 = extents->x2;
 | |
| 	y1 = extents->y1;
 | |
| 	y2 = extents->y2;
 | |
| 	if (pGC->fillStyle == FillSolid)
 | |
| 	{
 | |
| 	    _s3SetSolidFill(s3,pGC->fgPixel,pGC->alu,pGC->planemask);
 | |
| 	    cache = 0;
 | |
| 	}
 | |
| 	else
 | |
| 	{
 | |
| 	    _s3SetPattern (pDrawable->pScreen, s3GCMap(pGC), pGC->alu, pGC->planemask,
 | |
| 			   s3Priv->pPattern);
 | |
| 	    cache = s3Priv->pPattern->cache;
 | |
| 	}
 | |
| 	while (n--)
 | |
| 	{
 | |
| 	    y = ppt->y;
 | |
| 	    if (y1 <= y && y < y2)
 | |
| 	    {
 | |
| 		x = ppt->x;
 | |
| 		width = *pwidth;
 | |
| 		if (x < x1)
 | |
| 		{
 | |
| 		    width -= (x1 - x);
 | |
| 		    x = x1;
 | |
| 		}
 | |
| 		if (x2 < x + width)
 | |
| 		    width = x2 - x;
 | |
| 		if (width > 0)
 | |
| 		{
 | |
| 		    if (cache)
 | |
| 		    {
 | |
| 			_s3PatRect(s3, cache->x, cache->y, x, y, width, 1);
 | |
| 		    }
 | |
| 		    else
 | |
| 		    {
 | |
| 			_s3SolidRect(s3,x,y,width,1);
 | |
| 		    }
 | |
| 		}
 | |
| 	    }
 | |
| 	    ppt++;
 | |
| 	    pwidth++;
 | |
| 	}
 | |
|     }
 | |
|     else
 | |
|     {
 | |
| 	nTmp = n * miFindMaxBand(pClip);
 | |
| 	pwidthFree = (int *)ALLOCATE_LOCAL(nTmp * sizeof(int));
 | |
| 	pptFree = (DDXPointRec *)ALLOCATE_LOCAL(nTmp * sizeof(DDXPointRec));
 | |
| 	if(!pptFree || !pwidthFree)
 | |
| 	{
 | |
| 	    if (pptFree) DEALLOCATE_LOCAL(pptFree);
 | |
| 	    if (pwidthFree) DEALLOCATE_LOCAL(pwidthFree);
 | |
| 	    return;
 | |
| 	}
 | |
| 	n = miClipSpans(fbGetCompositeClip(pGC),
 | |
| 			ppt, pwidth, n,
 | |
| 			pptFree, pwidthFree, fSorted);
 | |
| 	pwidth = pwidthFree;
 | |
| 	ppt = pptFree;
 | |
| 	if (pGC->fillStyle == FillSolid)
 | |
| 	{
 | |
| 	    _s3SetSolidFill(s3,pGC->fgPixel,pGC->alu,pGC->planemask);
 | |
| 	    while (n--)
 | |
| 	    {
 | |
| 		x = ppt->x;
 | |
| 		y = ppt->y;
 | |
| 		ppt++;
 | |
| 		width = *pwidth++;
 | |
| 		if (width)
 | |
| 		{
 | |
| 		    _s3SolidRect(s3,x,y,width,1);
 | |
| 		}
 | |
| 	    }
 | |
| 	}
 | |
| 	else if (s3Priv->pPattern)
 | |
| 	{
 | |
| 	    _s3SetPattern (pDrawable->pScreen, s3GCMap(pGC), pGC->alu, pGC->planemask,
 | |
| 			   s3Priv->pPattern);
 | |
| 	    cache = s3Priv->pPattern->cache;
 | |
| 	    while (n--)
 | |
| 	    {
 | |
| 		x = ppt->x;
 | |
| 		y = ppt->y;
 | |
| 		ppt++;
 | |
| 		width = *pwidth++;
 | |
| 		if (width)
 | |
| 		{
 | |
| 		    _s3PatRect(s3, cache->x, cache->y, x, y, width, 1);
 | |
| 		}
 | |
| 	    }
 | |
| 	}
 | |
| 	else
 | |
| 	{
 | |
| 	    _s3FillSpanLargeStipple (pDrawable, pGC, n, ppt, pwidth);
 | |
| 	}
 | |
| 	DEALLOCATE_LOCAL(pptFree);
 | |
| 	DEALLOCATE_LOCAL(pwidthFree);
 | |
|     }
 | |
|     MarkSyncS3 (pDrawable->pScreen);
 | |
| }
 | |
| 
 | |
| #include "mifillarc.h"
 | |
| 
 | |
| #define FILLSPAN(s3,y,__x1,__x2) {\
 | |
|     DRAW_DEBUG ((DEBUG_ARCS, "FILLSPAN %d: %d->%d", y, __x1, __x2)); \
 | |
|     if ((__x2) >= (__x1)) {\
 | |
| 	_s3SolidRect(s3,(__x1),(y),(__x2)-(__x1)+1,1); \
 | |
|     } \
 | |
| }
 | |
| 
 | |
| #define FILLSLICESPANS(flip,__y) \
 | |
|     if (!flip) \
 | |
|     { \
 | |
| 	FILLSPAN(s3,__y,xl,xr) \
 | |
|     } \
 | |
|     else \
 | |
|     { \
 | |
| 	xc = xorg - x; \
 | |
| 	FILLSPAN(s3, __y, xc, xr) \
 | |
| 	xc += slw - 1; \
 | |
| 	FILLSPAN(s3, __y, xl, xc) \
 | |
|     }
 | |
| 
 | |
| static void
 | |
| _s3FillEllipse (DrawablePtr pDraw, S3Ptr s3, xArc *arc)
 | |
| {
 | |
|     KdScreenPriv(pDraw->pScreen);
 | |
|     int x, y, e;
 | |
|     int yk, xk, ym, xm, dx, dy, xorg, yorg;
 | |
|     int	y_top, y_bot;
 | |
|     miFillArcRec info;
 | |
|     register int xpos;
 | |
|     int	slw;
 | |
| 
 | |
|     s3SetGlobalBitmap (pDraw->pScreen, s3DrawMap (pDraw));
 | |
|     miFillArcSetup(arc, &info);
 | |
|     MIFILLARCSETUP();
 | |
|     y_top = pDraw->y + yorg - y;
 | |
|     y_bot = pDraw->y + yorg + y + dy;
 | |
|     xorg += pDraw->x;
 | |
|     while (y)
 | |
|     {
 | |
| 	y_top++;
 | |
| 	y_bot--;
 | |
| 	MIFILLARCSTEP(slw);
 | |
| 	if (!slw)
 | |
| 	    continue;
 | |
| 	xpos = xorg - x;
 | |
| 	_s3SolidRect (s3,xpos,y_top,slw,1);
 | |
| 	if (miFillArcLower(slw))
 | |
| 	    _s3SolidRect (s3,xpos,y_bot,slw,1);
 | |
|     }
 | |
| }
 | |
| 
 | |
| 
 | |
| static void
 | |
| _s3FillArcSlice (DrawablePtr pDraw, GCPtr pGC, S3Ptr s3, xArc *arc)
 | |
| {
 | |
|     KdScreenPriv(pDraw->pScreen);
 | |
|     int yk, xk, ym, xm, dx, dy, xorg, yorg, slw;
 | |
|     register int x, y, e;
 | |
|     miFillArcRec info;
 | |
|     miArcSliceRec slice;
 | |
|     int xl, xr, xc;
 | |
|     int	y_top, y_bot;
 | |
| 
 | |
|     s3SetGlobalBitmap (pDraw->pScreen, s3DrawMap (pDraw));
 | |
|     DRAW_DEBUG ((DEBUG_ARCS, "slice %dx%d+%d+%d %d->%d",
 | |
| 		 arc->width, arc->height, arc->x, arc->y,
 | |
| 		 arc->angle1, arc->angle2));
 | |
|     miFillArcSetup(arc, &info);
 | |
|     miFillArcSliceSetup(arc, &slice, pGC);
 | |
|     DRAW_DEBUG ((DEBUG_ARCS, "edge1.x %d edge2.x %d", 
 | |
| 		slice.edge1.x, slice.edge2.x));
 | |
|     MIFILLARCSETUP();
 | |
|     DRAW_DEBUG ((DEBUG_ARCS, "xorg %d yorg %d",
 | |
| 		xorg, yorg));
 | |
|     xorg += pDraw->x;
 | |
|     yorg += pDraw->y;
 | |
|     y_top = yorg - y;
 | |
|     y_bot = yorg + y + dy;
 | |
|     slice.edge1.x += pDraw->x;
 | |
|     slice.edge2.x += pDraw->x;
 | |
|     DRAW_DEBUG ((DEBUG_ARCS, "xorg %d y_top %d y_bot %d",
 | |
| 		 xorg, y_top, y_bot));
 | |
|     while (y > 0)
 | |
|     {
 | |
| 	y_top++;
 | |
| 	y_bot--;
 | |
| 	MIFILLARCSTEP(slw);
 | |
| 	MIARCSLICESTEP(slice.edge1);
 | |
| 	MIARCSLICESTEP(slice.edge2);
 | |
| 	if (miFillSliceUpper(slice))
 | |
| 	{
 | |
| 	    MIARCSLICEUPPER(xl, xr, slice, slw);
 | |
| 	    FILLSLICESPANS(slice.flip_top, y_top);
 | |
| 	}
 | |
| 	if (miFillSliceLower(slice))
 | |
| 	{
 | |
| 	    MIARCSLICELOWER(xl, xr, slice, slw);
 | |
| 	    FILLSLICESPANS(slice.flip_bot, y_bot);
 | |
| 	}
 | |
|     }
 | |
| }
 | |
| 
 | |
| void
 | |
| s3PolyFillArcSolid (DrawablePtr pDraw, GCPtr pGC, int narcs, xArc *parcs)
 | |
| {
 | |
|     SetupS3(pDraw->pScreen);
 | |
|     xArc	    *arc;
 | |
|     int		    i;
 | |
|     int		    x, y;
 | |
|     BoxRec	    box;
 | |
|     RegionPtr	    pClip = fbGetCompositeClip(pGC);
 | |
|     BOOL	    set;
 | |
| 
 | |
|     set = FALSE;
 | |
|     for (; --narcs >= 0; parcs++)
 | |
|     {
 | |
| 	if (miFillArcEmpty(parcs))
 | |
| 	    continue;
 | |
| 	if (miCanFillArc(parcs))
 | |
| 	{
 | |
| 	    box.x1 = parcs->x + pDraw->x;
 | |
| 	    box.y1 = parcs->y + pDraw->y;
 | |
| 	    box.x2 = box.x1 + (int)parcs->width + 1;
 | |
| 	    box.y2 = box.y1 + (int)parcs->height + 1;
 | |
| 	    switch (RECT_IN_REGION(pDraw->pScreen, pClip, &box))
 | |
| 	    {
 | |
| 	    case rgnIN:
 | |
| 		if (!set)
 | |
| 		{
 | |
| 		    _s3SetSolidFill (s3, pGC->fgPixel, pGC->alu, pGC->planemask);
 | |
| 		    set = TRUE;
 | |
| 		}
 | |
| 		if ((parcs->angle2 >= FULLCIRCLE) ||
 | |
| 		    (parcs->angle2 <= -FULLCIRCLE))
 | |
| 		{
 | |
| 		    DRAW_DEBUG ((DEBUG_ARCS, "Full circle ellipse %dx%d",
 | |
| 				 parcs->width, parcs->height));
 | |
| 		    _s3FillEllipse (pDraw, s3, parcs);
 | |
| 		}
 | |
| 		else
 | |
| 		{
 | |
| 		    DRAW_DEBUG ((DEBUG_ARCS, "Partial ellipse %dx%d",
 | |
| 				 parcs->width, parcs->height));
 | |
| 		    _s3FillArcSlice (pDraw, pGC, s3, parcs);
 | |
| 		}
 | |
| 		/* fall through ... */
 | |
| 	    case rgnOUT:
 | |
| 		continue;
 | |
| 	    case rgnPART:
 | |
| 		break;
 | |
| 	    }
 | |
| 	}
 | |
| 	if (set)
 | |
| 	{
 | |
| 	    MarkSyncS3 (pDraw->pScreen);
 | |
| 	    set = FALSE;
 | |
| 	}
 | |
| 	KdCheckPolyFillArc(pDraw, pGC, 1, parcs);
 | |
|     }
 | |
|     if (set)
 | |
|     {
 | |
| 	MarkSyncS3 (pDraw->pScreen);
 | |
| 	set = FALSE;
 | |
|     }
 | |
| }
 | |
| 
 | |
| void
 | |
| s3FillPoly (DrawablePtr pDrawable, GCPtr pGC, int shape, 
 | |
| 	    int mode, int countInit, DDXPointPtr ptsIn)
 | |
| {
 | |
|     SetupS3(pDrawable->pScreen);
 | |
|     int		    nwidth;
 | |
|     int		    maxy;
 | |
|     int		    origin;
 | |
|     int		    count;
 | |
|     register int    vertex1, vertex2;
 | |
|     int		    c;
 | |
|     RegionPtr	    pClip = fbGetCompositeClip(pGC);    
 | |
|     BoxPtr	    extents;
 | |
|     int		    clip;
 | |
|     int		    y, sy;
 | |
|     int		    *vertex1p, *vertex2p;
 | |
|     int		    *endp;
 | |
|     int		    x1, x2, sx;
 | |
|     int		    dx1, dx2;
 | |
|     int		    dy1, dy2;
 | |
|     int		    e1, e2;
 | |
|     int		    step1, step2;
 | |
|     int		    sign1, sign2;
 | |
|     int		    h;
 | |
|     int		    l, r;
 | |
|     int		    nmiddle;
 | |
| 
 | |
|     if (mode == CoordModePrevious || REGION_NUM_RECTS(pClip) != 1)
 | |
|     {
 | |
| 	KdCheckFillPolygon (pDrawable, pGC, shape, mode, countInit, ptsIn);
 | |
| 	return;
 | |
|     }
 | |
|     
 | |
|     s3SetGlobalBitmap (pDrawable->pScreen, s3GCMap (pGC));
 | |
|     sy = pDrawable->y;
 | |
|     sx = pDrawable->x;
 | |
|     origin = *((int *) &pDrawable->x);
 | |
|     origin -= (origin & 0x8000) << 1;
 | |
|     extents = &pClip->extents;
 | |
|     vertex1 = *((int *) &extents->x1) - origin;
 | |
|     vertex2 = *((int *) &extents->x2) - origin - 0x00010001;
 | |
|     clip = 0;
 | |
|     
 | |
|     y = 32767;
 | |
|     maxy = 0;
 | |
|     vertex2p = (int *) ptsIn;
 | |
|     endp = vertex2p + countInit;
 | |
|     if (shape == Convex)
 | |
|     {
 | |
| 	count = countInit;
 | |
|     	while (count--)
 | |
|     	{
 | |
| 	    c = *vertex2p;
 | |
| 	    clip |= (c - vertex1) | (vertex2 - c);
 | |
| 	    c = intToY(c);
 | |
| 	    DRAW_DEBUG ((DEBUG_POLYGON, "Y coordinate %d", c));
 | |
| 	    if (c < y) 
 | |
| 	    {
 | |
| 	    	y = c;
 | |
| 	    	vertex1p = vertex2p;
 | |
| 	    }
 | |
| 	    vertex2p++;
 | |
| 	    if (c > maxy)
 | |
| 	    	maxy = c;
 | |
|     	}
 | |
|     }
 | |
|     else
 | |
|     {
 | |
| 	int yFlip = 0;
 | |
| 	dx1 = 1;
 | |
| 	x2 = -1;
 | |
| 	x1 = -1;
 | |
| 	count = countInit;
 | |
|     	while (count--)
 | |
|     	{
 | |
| 	    c = *vertex2p;
 | |
| 	    clip |= (c - vertex1) | (vertex2 - c);
 | |
| 	    c = intToY(c);
 | |
| 	    DRAW_DEBUG ((DEBUG_POLYGON, "Y coordinate %d", c));
 | |
| 	    if (c < y) 
 | |
| 	    {
 | |
| 	    	y = c;
 | |
| 	    	vertex1p = vertex2p;
 | |
| 	    }
 | |
| 	    vertex2p++;
 | |
| 	    if (c > maxy)
 | |
| 	    	maxy = c;
 | |
| 	    if (c == x1)
 | |
| 		continue;
 | |
| 	    if (dx1 > 0)
 | |
| 	    {
 | |
| 		if (x2 < 0)
 | |
| 		    x2 = c;
 | |
| 		else
 | |
| 		    dx2 = dx1 = (c - x1) >> 31;
 | |
| 	    }
 | |
| 	    else
 | |
| 		if ((c - x1) >> 31 != dx1) 
 | |
| 		{
 | |
| 		    dx1 = ~dx1;
 | |
| 		    yFlip++;
 | |
| 		}
 | |
| 	    x1 = c;
 | |
|        	}
 | |
| 	x1 = (x2 - c) >> 31;
 | |
| 	if (x1 != dx1)
 | |
| 	    yFlip++;
 | |
| 	if (x1 != dx2)
 | |
| 	    yFlip++;
 | |
| 	if (yFlip != 2) 
 | |
| 	    clip = 0x8000;
 | |
|     }
 | |
|     if (y == maxy)
 | |
| 	return;
 | |
| 
 | |
|     if (clip & 0x80008000)
 | |
|     {
 | |
| 	KdCheckFillPolygon (pDrawable, pGC, shape, mode, countInit, ptsIn);
 | |
| 	return;
 | |
|     }
 | |
|     _s3SetSolidFill(s3,pGC->fgPixel,pGC->alu,pGC->planemask);
 | |
|     
 | |
|     vertex2p = vertex1p;
 | |
|     vertex2 = vertex1 = *vertex2p++;
 | |
|     if (vertex2p == endp)
 | |
| 	vertex2p = (int *) ptsIn;
 | |
| #define Setup(c,x,vertex,dx,dy,e,sign,step) {\
 | |
|     x = intToX(vertex); \
 | |
|     if (dy = intToY(c) - y) { \
 | |
|     	dx = intToX(c) - x; \
 | |
| 	step = 0; \
 | |
|     	if (dx >= 0) \
 | |
|     	{ \
 | |
| 	    e = 0; \
 | |
| 	    sign = 1; \
 | |
| 	    if (dx >= dy) {\
 | |
| 	    	step = dx / dy; \
 | |
| 	    	dx = dx % dy; \
 | |
| 	    } \
 | |
|     	} \
 | |
|     	else \
 | |
|     	{ \
 | |
| 	    e = 1 - dy; \
 | |
| 	    sign = -1; \
 | |
| 	    dx = -dx; \
 | |
| 	    if (dx >= dy) { \
 | |
| 		step = - (dx / dy); \
 | |
| 		dx = dx % dy; \
 | |
| 	    } \
 | |
|     	} \
 | |
|     } \
 | |
|     x += sx; \
 | |
|     vertex = c; \
 | |
| }
 | |
| 
 | |
| #define Step(x,dx,dy,e,sign,step) {\
 | |
|     x += step; \
 | |
|     if ((e += dx) > 0) \
 | |
|     { \
 | |
| 	x += sign; \
 | |
| 	e -= dy; \
 | |
|     } \
 | |
| }
 | |
|     sy += y;
 | |
|     DRAW_DEBUG ((DEBUG_POLYGON, "Starting polygon at %d", sy));
 | |
|     for (;;)
 | |
|     {
 | |
| 	DRAW_DEBUG ((DEBUG_POLYGON, "vertex1 0x%x vertex2 0x%x y %d vy1 %d vy2 %d",
 | |
| 		     vertex1, vertex2,
 | |
| 		     y, intToY(vertex1), intToY (vertex2)));
 | |
| 	if (y == intToY(vertex1))
 | |
| 	{
 | |
| 	    DRAW_DEBUG ((DEBUG_POLYGON, "Find next -- vertext"));
 | |
| 	    do
 | |
| 	    {
 | |
| 	    	if (vertex1p == (int *) ptsIn)
 | |
| 		    vertex1p = endp;
 | |
| 	    	c = *--vertex1p;
 | |
| 	    	Setup (c,x1,vertex1,dx1,dy1,e1,sign1,step1);
 | |
| 		DRAW_DEBUG ((DEBUG_POLYGON, "-- vertex 0x%x y %d",
 | |
| 			     vertex1, intToY(vertex1)));
 | |
| 	    } while (y >= intToY(vertex1));
 | |
| 	    h = dy1;
 | |
| 	}
 | |
| 	else
 | |
| 	{
 | |
| 	    Step(x1,dx1,dy1,e1,sign1,step1)
 | |
| 	    h = intToY(vertex1) - y;
 | |
| 	}
 | |
| 	if (y == intToY(vertex2))
 | |
| 	{
 | |
| 	    DRAW_DEBUG ((DEBUG_POLYGON, "Find next ++ vertext"));
 | |
| 	    do
 | |
| 	    {
 | |
| 	    	c = *vertex2p++;
 | |
| 	    	if (vertex2p == endp)
 | |
| 		    vertex2p = (int *) ptsIn;
 | |
| 	    	Setup (c,x2,vertex2,dx2,dy2,e2,sign2,step2)
 | |
| 		DRAW_DEBUG ((DEBUG_POLYGON, "++ vertex 0x%x y %d",
 | |
| 			     vertex1, intToY(vertex1)));
 | |
| 	    } while (y >= intToY(vertex2));
 | |
| 	    if (dy2 < h)
 | |
| 		h = dy2;
 | |
| 	}
 | |
| 	else
 | |
| 	{
 | |
| 	    Step(x2,dx2,dy2,e2,sign2,step2)
 | |
| 	    if ((c = (intToY(vertex2) - y)) < h)
 | |
| 		h = c;
 | |
| 	}
 | |
| 	DRAW_DEBUG ((DEBUG_POLYGON, "This band %d", h));
 | |
| 	/* fill spans for this segment */
 | |
| 	for (;;)
 | |
| 	{
 | |
| 	    nmiddle = x2 - x1;
 | |
| 	    DRAW_DEBUG ((DEBUG_POLYGON, "This span %d->%d", x1, x2));
 | |
| 	    if (nmiddle)
 | |
| 	    {
 | |
| 		l = x1;
 | |
| 		if (nmiddle < 0)
 | |
| 		{
 | |
| 		    nmiddle = -nmiddle;
 | |
| 		    l = x2;
 | |
| 		}
 | |
| 		_s3SolidRect(s3,l,sy,nmiddle,1);
 | |
| 	    }
 | |
| 	    y++;
 | |
| 	    sy++;
 | |
| 	    if (!--h)
 | |
| 		break;
 | |
| 	    Step(x1,dx1,dy1,e1,sign1,step1)
 | |
| 	    Step(x2,dx2,dy2,e2,sign2,step2)
 | |
| 	}
 | |
| 	if (y == maxy)
 | |
| 	    break;
 | |
|     }
 | |
|     MarkSyncS3 (pDrawable->pScreen);
 | |
| }
 | |
| 
 | |
| void
 | |
| s3PolyGlyphBltClipped (DrawablePtr pDrawable,
 | |
| 		       GCPtr pGC,
 | |
| 		       int x, int y, 
 | |
| 		       unsigned int nglyph,
 | |
| 		       CharInfoPtr *ppciInit, 
 | |
| 		       pointer pglyphBase)
 | |
| {
 | |
|     SetupS3(pDrawable->pScreen);
 | |
|     int		    h;
 | |
|     int		    w;
 | |
|     int		    xBack, yBack;
 | |
|     int		    hBack, wBack;
 | |
|     int		    lw;
 | |
|     FontPtr	    pfont = pGC->font;
 | |
|     CharInfoPtr	    pci;
 | |
|     unsigned long   *bits;
 | |
|     BoxPtr	    extents;
 | |
|     BoxRec	    bbox;
 | |
|     CARD32	    b;
 | |
|     CharInfoPtr	    *ppci;
 | |
|     FbGCPrivPtr	    fbPriv = fbGetGCPrivate(pGC);
 | |
|     RegionPtr	    pClip = fbGetCompositeClip(pGC);
 | |
|     BoxPtr	    pBox;
 | |
|     int		    nbox;
 | |
|     int		    x1, y1, x2, y2;
 | |
|     unsigned char   alu;
 | |
|     Bool	    set;
 | |
|     PixTransDeclare;
 | |
| 
 | |
|     s3SetGlobalBitmap (pDrawable->pScreen, s3GCMap (pGC));
 | |
|     x += pDrawable->x;
 | |
|     y += pDrawable->y;
 | |
| 
 | |
|     if (pglyphBase == (pointer) 1)
 | |
|     {
 | |
| 	xBack = x;
 | |
| 	yBack = y - FONTASCENT(pGC->font);
 | |
| 	wBack = 0;
 | |
| 	hBack = FONTASCENT(pGC->font) + FONTDESCENT(pGC->font);
 | |
| 	if (hBack)
 | |
| 	{
 | |
| 	    h = nglyph;
 | |
| 	    ppci = ppciInit;
 | |
| 	    while (h--)
 | |
| 		wBack += (*ppci++)->metrics.characterWidth;
 | |
| 	}
 | |
| 	if (wBack < 0)
 | |
| 	{
 | |
| 	    xBack = xBack + wBack;
 | |
| 	    wBack = -wBack;
 | |
| 	}
 | |
| 	if (hBack < 0)
 | |
| 	{
 | |
| 	    yBack = yBack + hBack;
 | |
| 	    hBack = -hBack;
 | |
| 	}
 | |
| 	alu = GXcopy;
 | |
|     }
 | |
|     else
 | |
|     {
 | |
| 	wBack = 0;
 | |
| 	alu = pGC->alu;
 | |
|     }
 | |
|     
 | |
|     if (wBack)
 | |
|     {
 | |
| 	_s3SetSolidFill (s3, pGC->bgPixel, GXcopy, pGC->planemask);
 | |
| 	for (nbox = REGION_NUM_RECTS (pClip),
 | |
| 	     pBox = REGION_RECTS (pClip);
 | |
| 	     nbox--;
 | |
| 	     pBox++)
 | |
| 	{
 | |
| 	    x1 = xBack;
 | |
| 	    x2 = xBack + wBack;
 | |
| 	    y1 = yBack;
 | |
| 	    y2 = yBack + hBack;
 | |
| 	    if (x1 < pBox->x1) x1 = pBox->x1;
 | |
| 	    if (x2 > pBox->x2) x2 = pBox->x2;
 | |
| 	    if (y1 < pBox->y1) y1 = pBox->y1;
 | |
| 	    if (y2 > pBox->y2) y2 = pBox->y2;
 | |
| 	    if (x1 < x2 && y1 < y2)
 | |
| 	    {
 | |
| 		_s3SolidRect (s3, x1, y1, x2 - x1, y2 - y1);
 | |
| 	    }
 | |
| 	}
 | |
| 	MarkSyncS3 (pDrawable->pScreen);
 | |
|     }
 | |
|     ppci = ppciInit;
 | |
|     set = FALSE;
 | |
|     while (nglyph--)
 | |
|     {
 | |
| 	pci = *ppci++;
 | |
| 	h = pci->metrics.ascent + pci->metrics.descent;
 | |
| 	w = pci->metrics.rightSideBearing - pci->metrics.leftSideBearing;
 | |
| 	x1 = x + pci->metrics.leftSideBearing;
 | |
| 	y1 = y - pci->metrics.ascent;
 | |
| 	bbox.x1 = x1;
 | |
| 	bbox.y1 = y1;
 | |
| 	bbox.x2 = x1 + w;
 | |
| 	bbox.y2 = y1 + h;
 | |
| 	switch (RECT_IN_REGION(pGC->pScreen, pClip, &bbox))
 | |
| 	{
 | |
| 	case rgnIN:
 | |
| #if 1
 | |
| 	    lw = h * ((w + 31) >> 5);
 | |
| 	    if (lw)
 | |
| 	    {
 | |
| 		if (!set)
 | |
| 		{
 | |
| 		    _s3SetTransparentPlaneBlt (s3, alu, pGC->planemask, pGC->fgPixel);
 | |
| 		    set = TRUE;
 | |
| 		}
 | |
| 		_s3PlaneBlt(s3,
 | |
| 			    x + pci->metrics.leftSideBearing,
 | |
| 			    y - pci->metrics.ascent,
 | |
| 			    w, h);
 | |
| 		bits = (unsigned long *) pci->bits;
 | |
| 		PixTransStart (lw);
 | |
| 		while (lw--) 
 | |
| 		{
 | |
| 		    b = *bits++;
 | |
| 		    S3AdjustBits32 (b);
 | |
| 		    PixTransStore(b);
 | |
| 		}
 | |
| 		MarkSyncS3 (pDrawable->pScreen);
 | |
| 	    }
 | |
| 	    break;
 | |
| #endif
 | |
| 	case rgnPART:
 | |
| 	    set = FALSE;
 | |
| 	    CheckSyncS3 (pDrawable->pScreen);
 | |
| 	    fbPutXYImage (pDrawable,
 | |
| 			  pClip,
 | |
| 			  fbPriv->fg,
 | |
| 			  fbPriv->bg,
 | |
| 			  fbPriv->pm,
 | |
| 			  alu,
 | |
| 			  FALSE,
 | |
| 			  x1, y1,
 | |
| 			  w, h,
 | |
| 			  (FbStip *) pci->bits,
 | |
| 			  (w + 31) >> 5,
 | |
| 			  0);
 | |
| 	    break;
 | |
| 	case rgnOUT:
 | |
| 	    break;
 | |
| 	}
 | |
| 	x += pci->metrics.characterWidth;
 | |
|     }
 | |
| }
 | |
| 		       
 | |
| /*
 | |
|  * Blt glyphs using S3 image transfer register, this does both
 | |
|  * poly glyph blt and image glyph blt (when pglyphBase == 1)
 | |
|  */
 | |
| 
 | |
| void
 | |
| s3PolyGlyphBlt (DrawablePtr pDrawable, 
 | |
| 		GCPtr pGC, 
 | |
| 		int x, int y, 
 | |
| 		unsigned int nglyph,
 | |
| 		CharInfoPtr *ppciInit, 
 | |
| 		pointer pglyphBase)
 | |
| {
 | |
|     SetupS3(pDrawable->pScreen);
 | |
|     int		    h;
 | |
|     int		    w;
 | |
|     int		    xBack, yBack;
 | |
|     int		    hBack, wBack;
 | |
|     int		    lw;
 | |
|     FontPtr	    pfont = pGC->font;
 | |
|     CharInfoPtr	    pci;
 | |
|     unsigned long   *bits;
 | |
|     BoxPtr	    extents;
 | |
|     BoxRec	    bbox;
 | |
|     CARD32	    b;
 | |
|     CharInfoPtr	    *ppci;
 | |
|     unsigned char   alu;
 | |
|     PixTransDeclare;
 | |
| 
 | |
|     s3SetGlobalBitmap (pDrawable->pScreen, s3GCMap (pGC));
 | |
|     x += pDrawable->x;
 | |
|     y += pDrawable->y;
 | |
| 
 | |
|     /* compute an approximate (but covering) bounding box */
 | |
|     ppci = ppciInit;
 | |
|     w = 0;
 | |
|     h = nglyph;
 | |
|     while (h--)
 | |
| 	w += (*ppci++)->metrics.characterWidth;
 | |
|     if (w < 0)
 | |
|     {
 | |
| 	bbox.x1 = x + w;
 | |
| 	bbox.x2 = x;
 | |
|     }
 | |
|     else
 | |
|     {
 | |
| 	bbox.x1 = x;
 | |
| 	bbox.x2 = x + w;
 | |
|     }
 | |
|     w = FONTMINBOUNDS(pfont,leftSideBearing);
 | |
|     if (w < 0)
 | |
| 	bbox.x1 += w;
 | |
|     w = FONTMAXBOUNDS(pfont, rightSideBearing) - FONTMINBOUNDS(pfont, characterWidth);
 | |
|     if (w > 0)
 | |
| 	bbox.x2 += w;
 | |
|     bbox.y1 = y - FONTMAXBOUNDS(pfont,ascent);
 | |
|     bbox.y2 = y + FONTMAXBOUNDS(pfont,descent);
 | |
|     
 | |
|     DRAW_DEBUG ((DEBUG_TEXT, "PolyGlyphBlt %d box is %d %d", nglyph,
 | |
| 		 bbox.x1, bbox.x2));
 | |
|     switch (RECT_IN_REGION(pGC->pScreen, fbGetCompositeClip(pGC), &bbox))
 | |
|     {
 | |
|     case rgnIN:
 | |
| 	break;
 | |
|     case rgnPART:
 | |
| 	s3PolyGlyphBltClipped(pDrawable, pGC, x - pDrawable->x,
 | |
| 			      y - pDrawable->y,
 | |
| 			      nglyph, ppciInit, pglyphBase);
 | |
|     case rgnOUT:
 | |
| 	return;
 | |
|     }
 | |
|     
 | |
|     if (pglyphBase == (pointer) 1)
 | |
|     {
 | |
| 	xBack = x;
 | |
| 	yBack = y - FONTASCENT(pGC->font);
 | |
| 	wBack = 0;
 | |
| 	hBack = FONTASCENT(pGC->font) + FONTDESCENT(pGC->font);
 | |
| 	if (hBack)
 | |
| 	{
 | |
| 	    h = nglyph;
 | |
| 	    ppci = ppciInit;
 | |
| 	    while (h--)
 | |
| 		wBack += (*ppci++)->metrics.characterWidth;
 | |
| 	}
 | |
| 	if (wBack < 0)
 | |
| 	{
 | |
| 	    xBack = xBack + wBack;
 | |
| 	    wBack = -wBack;
 | |
| 	}
 | |
| 	if (hBack < 0)
 | |
| 	{
 | |
| 	    yBack = yBack + hBack;
 | |
| 	    hBack = -hBack;
 | |
| 	}
 | |
| 	alu = GXcopy;
 | |
|     }
 | |
|     else
 | |
|     {
 | |
| 	wBack = 0;
 | |
| 	alu = pGC->alu;
 | |
|     }
 | |
|     
 | |
|     if (wBack)
 | |
|     {
 | |
| 	_s3SetSolidFill (s3, pGC->bgPixel, GXcopy, pGC->planemask);
 | |
| 	_s3SolidRect (s3, xBack, yBack, wBack, hBack);
 | |
|     }
 | |
|     _s3SetTransparentPlaneBlt (s3, alu, pGC->planemask, pGC->fgPixel);
 | |
|     ppci = ppciInit;
 | |
|     while (nglyph--)
 | |
|     {
 | |
| 	pci = *ppci++;
 | |
| 	h = pci->metrics.ascent + pci->metrics.descent;
 | |
| 	w = pci->metrics.rightSideBearing - pci->metrics.leftSideBearing;
 | |
| 	lw = h * ((w + 31) >> 5);
 | |
| 	if (lw)
 | |
| 	{
 | |
| 	    _s3PlaneBlt(s3,
 | |
| 			x + pci->metrics.leftSideBearing,
 | |
| 			y - pci->metrics.ascent,
 | |
| 			w, h);
 | |
| 	    bits = (unsigned long *) pci->bits;
 | |
| 	    PixTransStart(lw);
 | |
| 	    while (lw--) 
 | |
| 	    {
 | |
| 		b = *bits++;
 | |
| 		S3AdjustBits32 (b);
 | |
| 		PixTransStore(b);
 | |
| 	    }
 | |
| 	}
 | |
| 	x += pci->metrics.characterWidth;
 | |
|     }
 | |
|     MarkSyncS3 (pDrawable->pScreen);
 | |
| }
 | |
| 
 | |
| void
 | |
| s3ImageGlyphBlt (DrawablePtr pDrawable, 
 | |
| 		GCPtr pGC, 
 | |
| 		int x, int y, 
 | |
| 		unsigned int nglyph, 
 | |
| 		CharInfoPtr *ppci, 
 | |
| 		pointer pglyphBase)
 | |
| {
 | |
|     s3PolyGlyphBlt (pDrawable, pGC, x, y, nglyph, ppci, (pointer) 1);
 | |
| }
 | |
| 
 | |
| /*
 | |
|  * Blt TE fonts using S3 image transfer.  Differs from
 | |
|  * above in that it doesn't need to fill a solid rect for
 | |
|  * the background and it can draw multiple characters at a time
 | |
|  */
 | |
| 
 | |
| void
 | |
| s3ImageTEGlyphBlt (DrawablePtr pDrawable, GCPtr pGC,
 | |
| 		   int xInit, int yInit,
 | |
| 		   unsigned int nglyph,
 | |
| 		   CharInfoPtr *ppci,
 | |
| 		   pointer pglyphBase)
 | |
| {
 | |
|     SetupS3(pDrawable->pScreen);
 | |
|     int		    x, y;
 | |
|     int		    h, lw, lwTmp;
 | |
|     int		    w;
 | |
|     FontPtr	    pfont = pGC->font;
 | |
|     unsigned long   *char1, *char2, *char3, *char4;
 | |
|     int		    widthGlyphs, widthGlyph;
 | |
|     BoxRec	    bbox;
 | |
|     CARD32	    tmp;
 | |
|     PixTransDeclare;
 | |
| 
 | |
|     s3SetGlobalBitmap (pDrawable->pScreen, s3GCMap (pGC));
 | |
|     widthGlyph = FONTMAXBOUNDS(pfont,characterWidth);
 | |
|     if (!widthGlyph)
 | |
| 	return;
 | |
|     
 | |
|     h = FONTASCENT(pfont) + FONTDESCENT(pfont);
 | |
|     if (!h)
 | |
| 	return;
 | |
|     
 | |
|     DRAW_DEBUG ((DEBUG_TEXT, "ImageTEGlyphBlt chars are %d %d",
 | |
| 		 widthGlyph, h));
 | |
|     
 | |
|     x = xInit + FONTMAXBOUNDS(pfont,leftSideBearing) + pDrawable->x;
 | |
|     y = yInit - FONTASCENT(pfont) + pDrawable->y;
 | |
|     
 | |
|     bbox.x1 = x;
 | |
|     bbox.x2 = x + (widthGlyph * nglyph);
 | |
|     bbox.y1 = y;
 | |
|     bbox.y2 = y + h;
 | |
| 
 | |
|     switch (RECT_IN_REGION(pGC->pScreen, fbGetCompositeClip(pGC), &bbox))
 | |
|     {
 | |
|       case rgnIN:
 | |
| 	break;
 | |
|       case rgnPART:
 | |
| 	if (pglyphBase == (pointer) 1)
 | |
| 	    pglyphBase = 0;
 | |
| 	else
 | |
| 	    pglyphBase = (pointer) 1;
 | |
| 	s3PolyGlyphBltClipped(pDrawable, pGC, 
 | |
| 			      xInit,
 | |
| 			      yInit,
 | |
| 			      nglyph, ppci, 
 | |
| 			      pglyphBase);
 | |
|       case rgnOUT:
 | |
| 	return;
 | |
|     }
 | |
| 
 | |
|     if (pglyphBase == (pointer) 1)
 | |
|     {
 | |
| 	_s3SetTransparentPlaneBlt (s3, pGC->alu, pGC->planemask, pGC->fgPixel);
 | |
|     }
 | |
|     else
 | |
|     {
 | |
| 	_s3SetOpaquePlaneBlt (s3, GXcopy, pGC->planemask, pGC->fgPixel, pGC->bgPixel);
 | |
|     }
 | |
| 
 | |
| #if BITMAP_BIT_ORDER == LSBFirst
 | |
| #define SHIFT	<<
 | |
| #else
 | |
| #define SHIFT	>>
 | |
| #endif
 | |
|     
 | |
| #define LoopIt(count, w, loadup, fetch) \
 | |
|     while (nglyph >= count) \
 | |
|     { \
 | |
| 	nglyph -= count; \
 | |
| 	_s3PlaneBlt (s3, x, y, w, h); \
 | |
| 	x += w; \
 | |
| 	loadup \
 | |
| 	lwTmp = h; \
 | |
| 	PixTransStart(h); \
 | |
| 	while (lwTmp--) { \
 | |
| 	    tmp = fetch; \
 | |
| 	    S3AdjustBits32(tmp); \
 | |
| 	    PixTransStore(tmp); \
 | |
| 	} \
 | |
|     }
 | |
| 
 | |
|     if (widthGlyph <= 8)
 | |
|     {
 | |
| 	widthGlyphs = widthGlyph << 2;
 | |
| 	LoopIt(4, widthGlyphs,
 | |
| 	       char1 = (unsigned long *) (*ppci++)->bits;
 | |
| 	       char2 = (unsigned long *) (*ppci++)->bits;
 | |
| 	       char3 = (unsigned long *) (*ppci++)->bits;
 | |
| 	       char4 = (unsigned long *) (*ppci++)->bits;,
 | |
| 	       (*char1++ | ((*char2++ | ((*char3++ | (*char4++
 | |
| 						      SHIFT widthGlyph))
 | |
| 					 SHIFT widthGlyph))
 | |
| 			    SHIFT widthGlyph)))
 | |
|     }
 | |
|     else if (widthGlyph <= 10)
 | |
|     {
 | |
| 	widthGlyphs = (widthGlyph << 1) + widthGlyph;
 | |
| 	LoopIt(3, widthGlyphs,
 | |
| 	       char1 = (unsigned long *) (*ppci++)->bits;
 | |
| 	       char2 = (unsigned long *) (*ppci++)->bits;
 | |
| 	       char3 = (unsigned long *) (*ppci++)->bits;,
 | |
| 	       (*char1++ | ((*char2++ | (*char3++ SHIFT widthGlyph)) SHIFT widthGlyph)))
 | |
|     }
 | |
|     else if (widthGlyph <= 16)
 | |
|     {
 | |
| 	widthGlyphs = widthGlyph << 1;
 | |
| 	LoopIt(2, widthGlyphs,
 | |
| 	       char1 = (unsigned long *) (*ppci++)->bits;
 | |
| 	       char2 = (unsigned long *) (*ppci++)->bits;,
 | |
| 	       (*char1++ | (*char2++ SHIFT widthGlyph)))
 | |
|     }
 | |
|     lw = h * ((widthGlyph + 31) >> 5);
 | |
|     while (nglyph--) 
 | |
|     {
 | |
| 	_s3PlaneBlt (s3, x, y, widthGlyph, h);
 | |
| 	x += widthGlyph;
 | |
| 	char1 = (unsigned long *) (*ppci++)->bits;
 | |
| 	lwTmp = lw;
 | |
| 	PixTransStart(lw);
 | |
| 	while (lwTmp--)
 | |
| 	{
 | |
| 	    tmp = *char1++;
 | |
| 	    S3AdjustBits32(tmp);
 | |
| 	    PixTransStore(tmp);
 | |
| 	}
 | |
|     }
 | |
|     MarkSyncS3 (pDrawable->pScreen);
 | |
| }
 | |
| 
 | |
| void
 | |
| s3PolyTEGlyphBlt (DrawablePtr pDrawable, GCPtr pGC, 
 | |
| 		  int x, int y, 
 | |
| 		  unsigned int nglyph, CharInfoPtr *ppci, 
 | |
| 		  pointer pglyphBase)
 | |
| {
 | |
|     s3ImageTEGlyphBlt (pDrawable, pGC, x, y, nglyph, ppci, (pointer) 1);
 | |
| }
 | |
| 
 | |
| Bool
 | |
| _s3Segment (DrawablePtr	pDrawable,
 | |
| 	    GCPtr	pGC,
 | |
| 	    int		x1,
 | |
| 	    int		y1,
 | |
| 	    int		x2,
 | |
| 	    int		y2,
 | |
| 	    Bool	drawLast,
 | |
| 	    Bool	s3Set)
 | |
| {
 | |
|     SetupS3(pDrawable->pScreen);
 | |
|     FbGCPrivPtr	pPriv = fbGetGCPrivate(pGC);
 | |
|     RegionPtr	pClip = fbGetCompositeClip(pGC);
 | |
|     BoxPtr	pBox;
 | |
|     int		nBox;
 | |
|     int		adx;		/* abs values of dx and dy */
 | |
|     int		ady;
 | |
|     int		signdx;		/* sign of dx and dy */
 | |
|     int		signdy;
 | |
|     int		e, e1, e2;		/* bresenham error and increments */
 | |
|     int		len;			/* length of segment */
 | |
|     int		axis;			/* major axis */
 | |
|     int		octant;
 | |
|     int		cmd;
 | |
|     unsigned int bias = miGetZeroLineBias(pDrawable->pScreen);
 | |
|     unsigned int oc1;	/* outcode of point 1 */
 | |
|     unsigned int oc2;	/* outcode of point 2 */
 | |
| 
 | |
|     CalcLineDeltas(x1, y1, x2, y2, adx, ady, signdx, signdy,
 | |
| 		   1, 1, octant);
 | |
|     
 | |
|     cmd = LASTPIX;
 | |
|     
 | |
|     if (adx > ady)
 | |
|     {
 | |
| 	axis = X_AXIS;
 | |
| 	e1 = ady << 1;
 | |
| 	e2 = e1 - (adx << 1);
 | |
| 	e = e1 - adx;
 | |
| 	len = adx;
 | |
|     }
 | |
|     else
 | |
|     {
 | |
| 	cmd |= YMAJAXIS;
 | |
| 	axis = Y_AXIS;
 | |
| 	e1 = adx << 1;
 | |
| 	e2 = e1 - (ady << 1);
 | |
| 	e = e1 - ady;
 | |
| 	SetYMajorOctant(octant);
 | |
| 	len = ady;
 | |
|     }
 | |
| 
 | |
|     /* S3 line drawing hardware has limited resolution for error terms */
 | |
|     if (len >= 4096)
 | |
|     {
 | |
| 	int dashOff = 0;
 | |
| 	
 | |
| 	KdCheckSync (pDrawable->pScreen);
 | |
| 	fbSegment (pDrawable, pGC, x1, y1, x2, y2, drawLast, &dashOff);
 | |
| 	return FALSE;
 | |
|     }
 | |
| 
 | |
|     FIXUP_ERROR (e, octant, bias);
 | |
|     
 | |
|     nBox = REGION_NUM_RECTS (pClip);
 | |
|     pBox = REGION_RECTS (pClip);
 | |
| 
 | |
|     if (signdx > 0)
 | |
| 	cmd |= INC_X;
 | |
|     if (signdy > 0)
 | |
| 	cmd |= INC_Y;
 | |
| 	
 | |
|     /* we have bresenham parameters and two points.
 | |
|        all we have to do now is clip and draw.
 | |
|     */
 | |
| 
 | |
|     if (drawLast)
 | |
| 	len++;
 | |
|     while(nBox--)
 | |
|     {
 | |
| 	oc1 = 0;
 | |
| 	oc2 = 0;
 | |
| 	OUTCODES(oc1, x1, y1, pBox);
 | |
| 	OUTCODES(oc2, x2, y2, pBox);
 | |
| 	if ((oc1 | oc2) == 0)
 | |
| 	{
 | |
| 	    if (!s3Set)
 | |
| 	    {
 | |
| 		s3SetGlobalBitmap (pDrawable->pScreen, s3GCMap (pGC));
 | |
| 		_s3SetSolidFill (s3, pGC->fgPixel, pGC->alu, pGC->planemask);
 | |
| 		s3Set = TRUE;
 | |
| 	    }
 | |
| 	    _s3SetCur (s3, x1, y1);
 | |
| 	    _s3ClipLine (s3, cmd, e1, e2, e, len);
 | |
| 	    break;
 | |
| 	}
 | |
| 	else if (oc1 & oc2)
 | |
| 	{
 | |
| 	    pBox++;
 | |
| 	}
 | |
| 	else
 | |
| 	{
 | |
| 	    int new_x1 = x1, new_y1 = y1, new_x2 = x2, new_y2 = y2;
 | |
| 	    int clip1 = 0, clip2 = 0;
 | |
| 	    int clipdx, clipdy;
 | |
| 	    int err;
 | |
| 	    
 | |
| 	    if (miZeroClipLine(pBox->x1, pBox->y1, pBox->x2-1,
 | |
| 			       pBox->y2-1,
 | |
| 			       &new_x1, &new_y1, &new_x2, &new_y2,
 | |
| 			       adx, ady, &clip1, &clip2,
 | |
| 			       octant, bias, oc1, oc2) == -1)
 | |
| 	    {
 | |
| 		pBox++;
 | |
| 		continue;
 | |
| 	    }
 | |
| 
 | |
| 	    if (axis == X_AXIS)
 | |
| 		len = abs(new_x2 - new_x1);
 | |
| 	    else
 | |
| 		len = abs(new_y2 - new_y1);
 | |
| 	    if (clip2 != 0 || drawLast)
 | |
| 		len++;
 | |
| 	    if (len)
 | |
| 	    {
 | |
| 		/* unwind bresenham error term to first point */
 | |
| 		err = e;
 | |
| 		if (clip1)
 | |
| 		{
 | |
| 		    clipdx = abs(new_x1 - x1);
 | |
| 		    clipdy = abs(new_y1 - y1);
 | |
| 		    if (axis == X_AXIS)
 | |
| 			err  += (e2 - e1) * clipdy + e1 * clipdx;
 | |
| 		    else
 | |
| 			err  += (e2 - e1) * clipdx + e1 * clipdy;
 | |
| 		}
 | |
| 		if (!s3Set)
 | |
| 		{
 | |
| 		    s3SetGlobalBitmap (pDrawable->pScreen, s3GCMap (pGC));
 | |
| 		    _s3SetSolidFill (s3, pGC->fgPixel, pGC->alu, pGC->planemask);
 | |
| 		    s3Set = TRUE;
 | |
| 		}
 | |
| 		_s3SetCur (s3, new_x1, new_y1);
 | |
| 		_s3ClipLine (s3, cmd, e1, e2, err, len);
 | |
| 	    }
 | |
| 	    pBox++;
 | |
| 	}
 | |
|     } /* while (nBox--) */
 | |
|     return s3Set;
 | |
| }
 | |
| 
 | |
| void
 | |
| s3Polylines (DrawablePtr pDrawable, GCPtr pGC,
 | |
| 	     int mode, int npt, DDXPointPtr ppt)
 | |
| {
 | |
|     SetupS3(pDrawable->pScreen);
 | |
|     int		x, y, nx, ny;
 | |
|     int		ox = pDrawable->x, oy = pDrawable->y;
 | |
|     Bool	s3Set = FALSE;
 | |
|     
 | |
|     if (!npt)
 | |
| 	return;
 | |
|     
 | |
|     x = ppt->x + ox;
 | |
|     y = ppt->y + oy;
 | |
|     while (--npt)
 | |
|     {
 | |
| 	++ppt;
 | |
| 	if (mode == CoordModePrevious)
 | |
| 	{
 | |
| 	    nx = x + ppt->x;
 | |
| 	    ny = y + ppt->y;
 | |
| 	}
 | |
| 	else
 | |
| 	{
 | |
| 	    nx = ppt->x + ox;
 | |
| 	    ny = ppt->y + oy;
 | |
| 	}
 | |
| 	s3Set = _s3Segment (pDrawable, pGC, x, y, nx, ny,
 | |
| 			    npt == 1 && pGC->capStyle != CapNotLast, 
 | |
| 			    s3Set);
 | |
| 	x = nx;
 | |
| 	y = ny;
 | |
|     }
 | |
|     if (s3Set)
 | |
| 	MarkSyncS3 (pDrawable->pScreen);
 | |
| }
 | |
| 
 | |
| void
 | |
| s3PolySegment (DrawablePtr pDrawable, GCPtr pGC, 
 | |
| 	       int nsegInit, xSegment *pSegInit)
 | |
| {
 | |
|     SetupS3(pDrawable->pScreen);
 | |
|     int		x, y;
 | |
|     int		ox = pDrawable->x, oy = pDrawable->y;
 | |
|     RegionPtr	pClip = fbGetCompositeClip (pGC);
 | |
|     BoxPtr	pBox;
 | |
|     int		nbox;
 | |
|     int		nseg;
 | |
|     xSegment	*pSeg;
 | |
|     int		dx, dy;
 | |
|     int		maj, min, len, inc;
 | |
|     int		t;
 | |
|     CARD32	cmd;
 | |
|     CARD32	init_cmd;
 | |
|     Bool	drawLast;
 | |
|     Bool	s3Set = FALSE;
 | |
|     
 | |
|     drawLast = pGC->capStyle != CapNotLast;
 | |
|     
 | |
|     for (nseg = nsegInit, pSeg = pSegInit; nseg--; pSeg++)
 | |
|     {
 | |
| 	s3Set = _s3Segment (pDrawable, pGC, pSeg->x1 + ox, pSeg->y1 + oy,
 | |
| 			    pSeg->x2 + ox, pSeg->y2 + oy, drawLast, s3Set);
 | |
| 		    
 | |
|     }
 | |
|     if (s3Set)
 | |
| 	MarkSyncS3 (pDrawable->pScreen);
 | |
| }
 | |
| 
 | |
| /*
 | |
|  * Check to see if a pattern can be painted with the S3
 | |
|  */
 | |
| 
 | |
| #define _s3CheckPatternSize(s)	((s) <= S3_TILE_SIZE && ((s) & ((s) - 1)) == 0)
 | |
| #define s3CheckPattern(w,h) (_s3CheckPatternSize(w) && _s3CheckPatternSize(h))
 | |
| 			     
 | |
| Bool
 | |
| s3AllocPattern (ScreenPtr pScreen,
 | |
| 		int ma,
 | |
| 		PixmapPtr pPixmap, 
 | |
| 		int xorg, int yorg,
 | |
| 		int fillStyle, Pixel fg, Pixel bg,
 | |
| 		s3PatternPtr *ppPattern)
 | |
| {
 | |
|     KdScreenPriv(pScreen);
 | |
|     s3ScreenInfo(pScreenPriv);
 | |
|     s3PatternPtr    pPattern;
 | |
|     
 | |
|     if (s3s->fb[ma].patterns.cache && fillStyle != FillSolid &&
 | |
| 	s3CheckPattern (pPixmap->drawable.width, pPixmap->drawable.height))
 | |
|     {
 | |
| 	if (!(pPattern = *ppPattern))
 | |
| 	{
 | |
| 	    pPattern = (s3PatternPtr) xalloc (sizeof (s3PatternRec));
 | |
| 	    if (!pPattern)
 | |
| 		return FALSE;
 | |
| 	    *ppPattern = pPattern;
 | |
| 	}
 | |
| 	
 | |
| 	pPattern->cache = 0;
 | |
| 	pPattern->id = 0;
 | |
| 	pPattern->pPixmap = pPixmap;
 | |
| 	pPattern->fillStyle = fillStyle;
 | |
| 	pPattern->xrot = (-xorg) & (S3_TILE_SIZE-1);
 | |
| 	pPattern->yrot = (-yorg) & (S3_TILE_SIZE-1);
 | |
| 	pPattern->fore = fg;
 | |
| 	pPattern->back = bg;
 | |
| 	return TRUE;
 | |
|     }
 | |
|     else
 | |
|     {
 | |
| 	if (*ppPattern)
 | |
| 	{
 | |
| 	    xfree (*ppPattern);
 | |
| 	    *ppPattern = 0;
 | |
| 	}
 | |
| 	return FALSE;
 | |
|     }
 | |
| }
 | |
| 
 | |
| void
 | |
| s3CheckGCFill (GCPtr pGC)
 | |
| {
 | |
|     s3PrivGCPtr	    s3Priv = s3GetGCPrivate (pGC);
 | |
|     PixmapPtr	    pPixmap;
 | |
| 
 | |
|     switch (pGC->fillStyle) {
 | |
|     case FillSolid:
 | |
| 	pPixmap = 0;
 | |
| 	break;
 | |
|     case FillOpaqueStippled:
 | |
|     case FillStippled:
 | |
| 	pPixmap = pGC->stipple;
 | |
| 	break;
 | |
|     case FillTiled:
 | |
| 	pPixmap = pGC->tile.pixmap;
 | |
| 	break;
 | |
|     }
 | |
|     s3AllocPattern (pGC->pScreen,
 | |
| 		    s3GCMap(pGC),
 | |
| 		    pPixmap,
 | |
| 		    pGC->patOrg.x + pGC->lastWinOrg.x,
 | |
| 		    pGC->patOrg.y + pGC->lastWinOrg.y,
 | |
| 		    pGC->fillStyle, pGC->fgPixel, pGC->bgPixel,
 | |
| 		    &s3Priv->pPattern);
 | |
| }
 | |
| 
 | |
| void
 | |
| s3MoveGCFill (GCPtr pGC)
 | |
| {
 | |
|     s3PrivGCPtr	    s3Priv = s3GetGCPrivate (pGC);
 | |
|     int		    xorg, yorg;
 | |
|     s3PatternPtr    pPattern;
 | |
|     
 | |
|     if (pPattern = s3Priv->pPattern)
 | |
|     {
 | |
| 	/*
 | |
| 	 * Reset origin
 | |
| 	 */
 | |
| 	xorg = pGC->patOrg.x + pGC->lastWinOrg.x;
 | |
| 	yorg = pGC->patOrg.y + pGC->lastWinOrg.y;
 | |
| 	pPattern->xrot = (-xorg) & (S3_TILE_SIZE - 1);
 | |
| 	pPattern->yrot = (-yorg) & (S3_TILE_SIZE - 1);
 | |
| 	/*
 | |
| 	 * Invalidate cache entry
 | |
| 	 */
 | |
| 	pPattern->id = 0;
 | |
| 	pPattern->cache = 0;
 | |
|     }
 | |
| }
 | |
| 
 | |
| /*
 | |
|  * S3 Patterns.  These are always full-depth images, stored in off-screen
 | |
|  * memory.
 | |
|  */
 | |
| 
 | |
| Pixel
 | |
| s3FetchPatternPixel (s3PatternPtr pPattern, int x, int y)
 | |
| {
 | |
|     CARD8	*src;
 | |
|     CARD16	*src16;
 | |
|     CARD32	*src32;
 | |
|     PixmapPtr	pPixmap = pPattern->pPixmap;
 | |
|     
 | |
|     x = (x + pPattern->xrot) % pPixmap->drawable.width;
 | |
|     y = (y + pPattern->yrot) % pPixmap->drawable.height;
 | |
|     src = (CARD8 *) pPixmap->devPrivate.ptr + y * pPixmap->devKind;
 | |
|     switch (pPixmap->drawable.bitsPerPixel) {
 | |
|     case 1:
 | |
| 	return (src[x>>3] >> (x & 7)) & 1 ? 0xffffffff : 0x00;
 | |
|     case 4:
 | |
| 	if (x & 1)
 | |
| 	    return src[x>>1] >> 4;
 | |
| 	else
 | |
| 	    return src[x>>1] & 0xf;
 | |
|     case 8:
 | |
| 	return src[x];
 | |
|     case 16:
 | |
| 	src16 = (CARD16 *) src;
 | |
| 	return src16[x];
 | |
|     case 32:
 | |
| 	src32 = (CARD32 *) src;
 | |
| 	return src32[x];
 | |
|     }
 | |
| }
 | |
| 
 | |
| /*
 | |
|  * Place pattern image on screen; done with S3 locked
 | |
|  */
 | |
| void
 | |
| _s3PutPattern (ScreenPtr pScreen, int ma, s3PatternPtr pPattern)
 | |
| {
 | |
|     SetupS3(pScreen);
 | |
|     s3ScreenInfo(pScreenPriv);
 | |
|     int		    x, y;
 | |
|     CARD8	    *dstLine, *dst8;
 | |
|     CARD16	    *dst16;
 | |
|     CARD32	    *dst32;
 | |
|     S3PatternCache  *cache = pPattern->cache;
 | |
| #ifdef S3_TRIO
 | |
|     int		    fb = 0;
 | |
| #else
 | |
|     int		    fb = s3s->fbmap[ma];
 | |
| #endif
 | |
|     
 | |
|     DRAW_DEBUG ((DEBUG_PATTERN, "_s3PutPattern 0x%x id %d to %d %d",
 | |
| 		pPattern, pPattern->id, cache->x, cache->y));
 | |
|     
 | |
|     dstLine = (pScreenPriv->screen->fb[fb].frameBuffer + 
 | |
| 	       cache->y * pScreenPriv->screen->fb[fb].byteStride + 
 | |
| 	       cache->x * pScreenPriv->bytesPerPixel[fb]);
 | |
|     
 | |
|     CheckSyncS3 (pScreen);
 | |
|     
 | |
|     for (y = 0; y < S3_TILE_SIZE; y++)
 | |
|     {
 | |
| 	switch (pScreenPriv->screen->fb[fb].bitsPerPixel) {
 | |
| 	case 8:
 | |
| 	    dst8 = dstLine;
 | |
| 	    for (x = 0; x < S3_TILE_SIZE; x++)
 | |
| 		*dst8++ = s3FetchPatternPixel (pPattern, x, y);
 | |
| 	    DRAW_DEBUG ((DEBUG_PATTERN, "%c%c%c%c%c%c%c%c",
 | |
| 			 dstLine[0] ? 'X' : ' ',
 | |
| 			 dstLine[1] ? 'X' : ' ',
 | |
| 			 dstLine[2] ? 'X' : ' ',
 | |
| 			 dstLine[3] ? 'X' : ' ',
 | |
| 			 dstLine[4] ? 'X' : ' ',
 | |
| 			 dstLine[5] ? 'X' : ' ',
 | |
| 			 dstLine[6] ? 'X' : ' ',
 | |
| 			 dstLine[7] ? 'X' : ' '));
 | |
| 	    break;
 | |
| 	case 16:
 | |
| 	    dst16 = (CARD16 *) dstLine;
 | |
| 	    for (x = 0; x < S3_TILE_SIZE; x++)
 | |
| 		*dst16++ = s3FetchPatternPixel (pPattern, x, y);
 | |
| 	    break;
 | |
| 	case 32:
 | |
| 	    dst32 = (CARD32 *) dstLine;
 | |
| 	    for (x = 0; x < S3_TILE_SIZE; x++)
 | |
| 		*dst32++ = s3FetchPatternPixel (pPattern, x, y);
 | |
| 	    break;
 | |
| 	}
 | |
| 	dstLine += pScreenPriv->screen->fb[fb].byteStride;
 | |
|     }
 | |
| }
 | |
| 
 | |
| /*
 | |
|  * Load a stipple to off-screen memory; done with S3 locked
 | |
|  */
 | |
| void
 | |
| _s3LoadPattern (ScreenPtr pScreen, int ma, s3PatternPtr pPattern)
 | |
| {
 | |
|     SetupS3(pScreen);
 | |
|     s3ScreenInfo(pScreenPriv);
 | |
|     S3PatternCache  *cache;
 | |
| 
 | |
|     DRAW_DEBUG((DEBUG_PATTERN,
 | |
| 	       "s3LoadPattern 0x%x id %d cache 0x%x cacheid %d",
 | |
| 	       pPattern, pPattern->id, pPattern->cache, 
 | |
| 	       pPattern->cache ? pPattern->cache->id : -1));
 | |
|     /*
 | |
|      * Check to see if its still loaded
 | |
|      */
 | |
|     cache = pPattern->cache;
 | |
|     if (cache && cache->id == pPattern->id)
 | |
| 	return;
 | |
|     /*
 | |
|      * Lame replacement strategy; assume we'll have plenty of room.
 | |
|      */
 | |
|     cache = &s3s->fb[ma].patterns.cache[s3s->fb[ma].patterns.last_used];
 | |
|     if (++s3s->fb[ma].patterns.last_used == s3s->fb[ma].patterns.ncache)
 | |
| 	s3s->fb[ma].patterns.last_used = 0;
 | |
|     cache->id = ++s3s->fb[ma].patterns.last_id;
 | |
|     pPattern->id = cache->id;
 | |
|     pPattern->cache = cache;
 | |
|     _s3PutPattern (pScreen, ma, pPattern);
 | |
| }
 | |
| 
 | |
| void
 | |
| s3DestroyGC (GCPtr pGC)
 | |
| {
 | |
|     s3PrivGCPtr	    s3Priv = s3GetGCPrivate (pGC);
 | |
| 
 | |
|     if (s3Priv->pPattern)
 | |
| 	xfree (s3Priv->pPattern);
 | |
|     miDestroyGC (pGC);
 | |
| }
 | |
| 
 | |
| GCFuncs	s3GCFuncs = {
 | |
|     s3ValidateGC,
 | |
|     miChangeGC,
 | |
|     miCopyGC,
 | |
|     s3DestroyGC,
 | |
|     miChangeClip,
 | |
|     miDestroyClip,
 | |
|     miCopyClip
 | |
| };
 | |
| 
 | |
| int
 | |
| s3CreateGC (GCPtr pGC)
 | |
| {
 | |
|     KdScreenPriv(pGC->pScreen);
 | |
|     s3ScreenInfo(pScreenPriv);
 | |
|     s3PrivGCPtr  s3Priv;
 | |
|     
 | |
|     if (!fbCreateGC (pGC))
 | |
| 	return FALSE;
 | |
| 
 | |
|     if (pGC->depth != 1)
 | |
| 	pGC->funcs = &s3GCFuncs;
 | |
|     
 | |
|     s3Priv = s3GetGCPrivate(pGC);
 | |
|     s3Priv->type = DRAWABLE_PIXMAP;
 | |
|     s3Priv->pPattern = 0;
 | |
| #ifndef S3_TRIO
 | |
|     if (pGC->depth == s3s->primary_depth)
 | |
| 	s3Priv->ma = 0;
 | |
|     else
 | |
| 	s3Priv->ma = 1;
 | |
| #endif
 | |
|     return TRUE;
 | |
| }
 | |
| 
 | |
| Bool
 | |
| s3CreateWindow (WindowPtr pWin)
 | |
| {
 | |
|     KdScreenPriv(pWin->drawable.pScreen);
 | |
|     s3ScreenInfo(pScreenPriv);
 | |
|     
 | |
|     pWin->devPrivates[s3WindowPrivateIndex].ptr = 0;
 | |
|     return KdCreateWindow (pWin);
 | |
| }
 | |
| 
 | |
| Bool
 | |
| s3DestroyWindow (WindowPtr pWin)
 | |
| {
 | |
|     s3PatternPtr pPattern;
 | |
|     if (pPattern = s3GetWindowPrivate(pWin))
 | |
| 	xfree (pPattern);
 | |
|     return fbDestroyWindow (pWin);
 | |
| }
 | |
| 
 | |
| Bool
 | |
| s3ChangeWindowAttributes (WindowPtr pWin, Mask mask)
 | |
| {
 | |
|     KdScreenPriv(pWin->drawable.pScreen);
 | |
|     Bool	    ret;
 | |
|     s3PatternPtr    pPattern;
 | |
|     PixmapPtr	    pPixmap;
 | |
|     int		    fillStyle;
 | |
| 
 | |
|     ret = fbChangeWindowAttributes (pWin, mask);
 | |
|     if (mask & CWBackPixmap)
 | |
|     {
 | |
| 	if (pWin->backgroundState == BackgroundPixmap)
 | |
| 	{
 | |
| 	    pPixmap = pWin->background.pixmap;
 | |
| 	    fillStyle = FillTiled;
 | |
| 	}
 | |
| 	else
 | |
| 	{
 | |
| 	    pPixmap = 0;
 | |
| 	    fillStyle = FillSolid;
 | |
| 	}
 | |
| 	pPattern = s3GetWindowPrivate(pWin);
 | |
| 	s3AllocPattern (pWin->drawable.pScreen,
 | |
| 			s3DrawMap (&pWin->drawable),
 | |
| 			pPixmap, 
 | |
| 			pWin->drawable.x, pWin->drawable.y,
 | |
| 			fillStyle, 0, 0, &pPattern);
 | |
| 	DRAW_DEBUG ((DEBUG_PAINT_WINDOW, "Background pattern 0x%x pixmap 0x%x style %d",
 | |
| 		    pPattern, pPixmap, fillStyle));
 | |
| 	s3SetWindowPrivate (pWin, pPattern);
 | |
|     }
 | |
|     return ret;
 | |
| }
 | |
| 
 | |
| 
 | |
| #ifndef S3_TRIO
 | |
| void
 | |
| s3PaintKey (DrawablePtr	pDrawable,
 | |
| 	    RegionPtr	pRegion,
 | |
| 	    CARD32	pixel,
 | |
| 	    int		fb)
 | |
| {
 | |
|     SetupS3 (pDrawable->pScreen);
 | |
|     s3ScreenInfo (pScreenPriv);
 | |
|     int	    nBox = REGION_NUM_RECTS(pRegion);
 | |
|     BoxPtr  pBox = REGION_RECTS(pRegion);
 | |
|     int	    ma;
 | |
|     
 | |
|     if (!nBox)
 | |
| 	return;
 | |
|     
 | |
|     for (ma = 0; s3s->fbmap[ma] >= 0; ma++)
 | |
| 	if (s3s->fbmap[ma] == fb)
 | |
| 	    break;
 | |
|     s3SetGlobalBitmap (pDrawable->pScreen, ma);
 | |
|     _s3SetSolidFill (s3, pixel, GXcopy, 0xffffffff);
 | |
|     while (nBox--) 
 | |
|     {
 | |
| 	_s3SolidRect(s3,pBox->x1,pBox->y1,pBox->x2-pBox->x1,pBox->y2-pBox->y1);
 | |
| 	pBox++;
 | |
|     }
 | |
|     MarkSyncS3 (pDrawable->pScreen);
 | |
| }
 | |
| #endif
 | |
| 
 | |
| void
 | |
| s3PaintWindow(WindowPtr pWin, RegionPtr pRegion, int what)
 | |
| {
 | |
|     SetupS3(pWin->drawable.pScreen);
 | |
|     s3ScreenInfo(pScreenPriv);
 | |
|     s3PatternPtr    pPattern;
 | |
| 
 | |
|     DRAW_DEBUG ((DEBUG_PAINT_WINDOW, "s3PaintWindow 0x%x extents %d %d %d %d n %d",
 | |
| 		 pWin->drawable.id,
 | |
| 		 pRegion->extents.x1, pRegion->extents.y1,
 | |
| 		 pRegion->extents.x2, pRegion->extents.y2,
 | |
| 		 REGION_NUM_RECTS(pRegion)));
 | |
|     if (!REGION_NUM_RECTS(pRegion)) 
 | |
| 	return;
 | |
|     switch (what) {
 | |
|     case PW_BACKGROUND:
 | |
| 	switch (pWin->backgroundState) {
 | |
| 	case None:
 | |
| 	    return;
 | |
| 	case ParentRelative:
 | |
| 	    do {
 | |
| 		pWin = pWin->parent;
 | |
| 	    } while (pWin->backgroundState == ParentRelative);
 | |
| 	    (*pWin->drawable.pScreen->PaintWindowBackground)(pWin, pRegion,
 | |
| 							     what);
 | |
| 	    return;
 | |
| 	case BackgroundPixmap:
 | |
| 	    pPattern = s3GetWindowPrivate(pWin);
 | |
| 	    if (pPattern)
 | |
| 	    {
 | |
| 		s3FillBoxPattern ((DrawablePtr)pWin,
 | |
| 				  (int)REGION_NUM_RECTS(pRegion),
 | |
| 				  REGION_RECTS(pRegion),
 | |
| 				  GXcopy, ~0, pPattern);
 | |
| 		return;
 | |
| 	    }
 | |
| 	    break;
 | |
| 	case BackgroundPixel:
 | |
| 	    s3FillBoxSolid((DrawablePtr)pWin,
 | |
| 			     (int)REGION_NUM_RECTS(pRegion),
 | |
| 			     REGION_RECTS(pRegion),
 | |
| 			     pWin->background.pixel, GXcopy, ~0);
 | |
| 	    return;
 | |
|     	}
 | |
|     	break;
 | |
|     case PW_BORDER:
 | |
| #ifndef S3_TRIO
 | |
| 	if (s3s->fbmap[1] >= 0)
 | |
| 	    fbOverlayUpdateLayerRegion (pWin->drawable.pScreen,
 | |
| 					fbOverlayWindowLayer (pWin),
 | |
| 					pRegion);
 | |
| #endif
 | |
| 	if (pWin->borderIsPixel)
 | |
| 	{
 | |
| 	    s3FillBoxSolid((DrawablePtr)pWin,
 | |
| 			     (int)REGION_NUM_RECTS(pRegion),
 | |
| 			     REGION_RECTS(pRegion),
 | |
| 			     pWin->border.pixel, GXcopy, ~0);
 | |
| 	    return;
 | |
| 	}
 | |
| 	break;
 | |
|     }
 | |
|     KdCheckPaintWindow (pWin, pRegion, what);
 | |
| }
 | |
| 
 | |
| void
 | |
| s3CopyWindowProc (DrawablePtr pSrcDrawable,
 | |
| 		  DrawablePtr pDstDrawable,
 | |
| 		  GCPtr       pGC,
 | |
| 		  BoxPtr      pboxOrig,
 | |
| 		  int         nboxOrig,
 | |
| 		  int         dx,
 | |
| 		  int         dy,
 | |
| 		  Bool        reverse,
 | |
| 		  Bool        upsidedown,
 | |
| 		  Pixel       bitplane,
 | |
| 		  void        *closure)
 | |
| {
 | |
|     SetupS3(pDstDrawable->pScreen);
 | |
|     s3ScreenInfo(pScreenPriv);
 | |
|     KdScreenInfo    *screen = pScreenPriv->screen;
 | |
|     int		    srcX, srcY, dstX, dstY;
 | |
|     int		    x1, x2;
 | |
|     int		    w, h;
 | |
|     int		    flags;
 | |
|     int		    fb = (int) closure;
 | |
|     int		    ma;
 | |
|     BoxPtr	    pbox;
 | |
|     int		    nbox;
 | |
|     int		    bitsPerPixel;
 | |
|     
 | |
| #ifdef S3_TRIO
 | |
|     ma = 0;
 | |
| #else
 | |
|     for (ma = 0; s3s->fbmap[ma] >= 0; ma++)
 | |
| 	if (s3s->fbmap[ma] == fb)
 | |
| 	    break;
 | |
| #endif
 | |
|     bitsPerPixel = screen->fb[fb].bitsPerPixel;
 | |
|     if (bitsPerPixel == 24)
 | |
| 	dx *= 3;
 | |
|     nbox = nboxOrig;
 | |
|     pbox = pboxOrig;
 | |
|     s3SetGlobalBitmap (pDstDrawable->pScreen, ma);
 | |
|     _s3SetBlt(s3,GXcopy,~0);
 | |
|     while (nbox--)
 | |
|     {
 | |
| 	x1 = pbox->x1;
 | |
| 	x2 = pbox->x2;
 | |
| 	if (bitsPerPixel == 24)
 | |
| 	{
 | |
| 	    x1 *= 3;
 | |
| 	    x2 *= 3;
 | |
| 	}
 | |
| 	
 | |
| 	w = x2 - x1;
 | |
| 	h = pbox->y2 - pbox->y1;
 | |
| 	flags = 0;
 | |
| 	if (reverse)
 | |
| 	{
 | |
| 	    dstX = x2 - 1;
 | |
| 	}
 | |
| 	else
 | |
| 	{
 | |
| 	    dstX = x1;
 | |
| 	    flags |= INC_X;
 | |
| 	}
 | |
| 	srcX = dstX + dx;
 | |
| 	
 | |
| 	if (upsidedown)
 | |
| 	{
 | |
| 	    dstY = pbox->y2 - 1;
 | |
| 	}
 | |
| 	else
 | |
| 	{
 | |
| 	    dstY = pbox->y1;
 | |
| 	    flags |= INC_Y;
 | |
| 	}
 | |
| 	srcY = dstY + dy;
 | |
| 	
 | |
| 	_s3Blt (s3, srcX, srcY, dstX, dstY, w, h, flags);
 | |
| 	pbox++;
 | |
|     }
 | |
|     MarkSyncS3 (pDstDrawable->pScreen);
 | |
| }
 | |
| 
 | |
| void 
 | |
| s3CopyWindow(WindowPtr pWin, DDXPointRec ptOldOrg, RegionPtr prgnSrc)
 | |
| {
 | |
|     ScreenPtr	    pScreen = pWin->drawable.pScreen;
 | |
|     KdScreenPriv (pScreen);
 | |
|     s3ScreenInfo (pScreenPriv);
 | |
|     KdScreenInfo    *screen = pScreenPriv->screen;
 | |
|     RegionRec	    rgnDst;
 | |
|     int		    dx, dy;
 | |
|     WindowPtr	    pwinRoot;
 | |
| 
 | |
|     pwinRoot = WindowTable[pWin->drawable.pScreen->myNum];
 | |
| 
 | |
|     dx = ptOldOrg.x - pWin->drawable.x;
 | |
|     dy = ptOldOrg.y - pWin->drawable.y;
 | |
| 
 | |
|     REGION_TRANSLATE(pWin->drawable.pScreen, prgnSrc, -dx, -dy);
 | |
| 
 | |
|     REGION_INIT (pWin->drawable.pScreen, &rgnDst, NullBox, 0);
 | |
| 
 | |
|     REGION_INTERSECT(pWin->drawable.pScreen, &rgnDst,
 | |
| 		     &pWin->borderClip, prgnSrc);
 | |
| 
 | |
|     fbCopyRegion ((DrawablePtr)pwinRoot, (DrawablePtr)pwinRoot,
 | |
| 		  0,
 | |
| 		  &rgnDst, dx, dy, s3CopyWindowProc, 0, 0);
 | |
|     
 | |
|     REGION_UNINIT(pWin->drawable.pScreen, &rgnDst);
 | |
| }
 | |
| 
 | |
| void
 | |
| s3_24FillBoxSolid (DrawablePtr pDrawable, int nBox, BoxPtr pBox, 
 | |
| 		  unsigned long pixel, int alu, unsigned long planemask)
 | |
| {
 | |
|     SetupS3(pDrawable->pScreen);
 | |
|     register int	r;
 | |
|     int			x1, x2;
 | |
| 
 | |
|     s3SetGlobalBitmap (pDrawable->pScreen, s3DrawMap (pDrawable));
 | |
|     _s3SetSolidFill(s3,pixel,alu,planemask);
 | |
|     
 | |
|     while (nBox--) {
 | |
| 	x1 = pBox->x1 * 3;
 | |
| 	x2 = pBox->x2 * 3;
 | |
| 	_s3SolidRect(s3,x1,pBox->y1,x2-x1,pBox->y2-pBox->y1);
 | |
| 	pBox++;
 | |
|     }
 | |
|     MarkSyncS3 (pDrawable->pScreen);
 | |
| }
 | |
| 
 | |
| #define ok24(p)	(((p) & 0xffffff) == ((((p) & 0xff) << 16) | (((p) >> 8) & 0xffff)))
 | |
| 
 | |
| void
 | |
| s3_24FillSpans (DrawablePtr pDrawable, GCPtr pGC, int n, 
 | |
| 		 DDXPointPtr ppt, int *pwidth, int fSorted)
 | |
| {
 | |
|     SetupS3(pDrawable->pScreen);
 | |
|     int		    x, y, x1, y1, x2, y2;
 | |
|     int		    width;
 | |
| 				/* next three parameters are post-clip */
 | |
|     int		    nTmp;
 | |
|     int		    *pwidthFree;/* copies of the pointers to free */
 | |
|     DDXPointPtr	    pptFree;
 | |
|     BoxPtr	    extents;
 | |
|     RegionPtr	    pClip = fbGetCompositeClip (pGC);
 | |
| 
 | |
|     if (pGC->fillStyle != FillSolid || !ok24 (pGC->fgPixel) || !ok24(pGC->planemask))
 | |
|     {
 | |
| 	KdCheckFillSpans (pDrawable,  pGC, n, ppt, pwidth, fSorted);
 | |
| 	return;
 | |
|     }
 | |
|     
 | |
|     s3SetGlobalBitmap (pDrawable->pScreen, s3GCMap (pGC));
 | |
|     if (REGION_NUM_RECTS(pClip) == 1)
 | |
|     {
 | |
| 	extents = REGION_RECTS(pClip);
 | |
| 	x1 = extents->x1;
 | |
| 	x2 = extents->x2;
 | |
| 	y1 = extents->y1;
 | |
| 	y2 = extents->y2;
 | |
| 	_s3SetSolidFill(s3,pGC->fgPixel,pGC->alu,pGC->planemask);
 | |
| 	while (n--)
 | |
| 	{
 | |
| 	    y = ppt->y;
 | |
| 	    if (y1 <= y && y < y2)
 | |
| 	    {
 | |
| 		x = ppt->x;
 | |
| 		width = *pwidth;
 | |
| 		if (x < x1)
 | |
| 		{
 | |
| 		    width -= (x1 - x);
 | |
| 		    x = x1;
 | |
| 		}
 | |
| 		if (x2 < x + width)
 | |
| 		    width = x2 - x;
 | |
| 		if (width > 0)
 | |
| 		{
 | |
| 		    _s3SolidRect(s3,x*3,y,width*3,1);
 | |
| 		}
 | |
| 	    }
 | |
| 	    ppt++;
 | |
| 	    pwidth++;
 | |
| 	}
 | |
|     }
 | |
|     else
 | |
|     {
 | |
| 	nTmp = n * miFindMaxBand(pClip);
 | |
| 	pwidthFree = (int *)ALLOCATE_LOCAL(nTmp * sizeof(int));
 | |
| 	pptFree = (DDXPointRec *)ALLOCATE_LOCAL(nTmp * sizeof(DDXPointRec));
 | |
| 	if(!pptFree || !pwidthFree)
 | |
| 	{
 | |
| 	    if (pptFree) DEALLOCATE_LOCAL(pptFree);
 | |
| 	    if (pwidthFree) DEALLOCATE_LOCAL(pwidthFree);
 | |
| 	    return;
 | |
| 	}
 | |
| 	n = miClipSpans(fbGetCompositeClip(pGC),
 | |
| 			ppt, pwidth, n,
 | |
| 			pptFree, pwidthFree, fSorted);
 | |
| 	pwidth = pwidthFree;
 | |
| 	ppt = pptFree;
 | |
| 	_s3SetSolidFill(s3,pGC->fgPixel,pGC->alu,pGC->planemask);
 | |
| 	while (n--)
 | |
| 	{
 | |
| 	    x = ppt->x;
 | |
| 	    y = ppt->y;
 | |
| 	    ppt++;
 | |
| 	    width = *pwidth++;
 | |
| 	    if (width)
 | |
| 	    {
 | |
| 		_s3SolidRect(s3,x*3,y,width*3,1);
 | |
| 	    }
 | |
| 	}
 | |
| 	DEALLOCATE_LOCAL(pptFree);
 | |
| 	DEALLOCATE_LOCAL(pwidthFree);
 | |
|     }
 | |
|     MarkSyncS3 (pDrawable->pScreen);
 | |
| }
 | |
| 
 | |
| void
 | |
| s3_24CopyNtoN (DrawablePtr  pSrcDrawable,
 | |
| 	       DrawablePtr  pDstDrawable,
 | |
| 	       GCPtr	    pGC,
 | |
| 	       BoxPtr	    pbox,
 | |
| 	       int	    nbox,
 | |
| 	       int	    dx,
 | |
| 	       int	    dy,
 | |
| 	       Bool	    reverse,
 | |
| 	       Bool	    upsidedown,
 | |
| 	       Pixel	    bitplane,
 | |
| 	       void	    *closure)
 | |
| {
 | |
|     SetupS3(pDstDrawable->pScreen);
 | |
|     int	    srcX, srcY, dstX, dstY;
 | |
|     int	    w, h;
 | |
|     int	    flags;
 | |
|     int	    x1, x2;
 | |
|     
 | |
|     if (sourceInvarient (pGC->alu))
 | |
|     {
 | |
| 	s3_24FillBoxSolid (pDstDrawable, nbox, pbox, 0, pGC->alu, pGC->planemask);
 | |
| 	return;
 | |
|     }
 | |
|     
 | |
|     s3SetGlobalBitmap (pDstDrawable->pScreen, s3GCMap (pGC));
 | |
|     _s3SetBlt(s3,pGC->alu,pGC->planemask);
 | |
|     DRAW_DEBUG ((DEBUG_RENDER, "s3CopyNtoN alu %d planemask 0x%x",
 | |
| 		 pGC->alu, pGC->planemask));
 | |
|     dx *= 3;
 | |
|     while (nbox--)
 | |
|     {
 | |
| 	x1 = pbox->x1 * 3;
 | |
| 	x2 = pbox->x2 * 3;
 | |
| 	w = x2 - x1;
 | |
| 	h = pbox->y2 - pbox->y1;
 | |
| 	flags = 0;
 | |
| 	if (reverse)
 | |
| 	{
 | |
| 	    dstX = x2 - 1;
 | |
| 	}
 | |
| 	else
 | |
| 	{
 | |
| 	    dstX = x1;
 | |
| 	    flags |= INC_X;
 | |
| 	}
 | |
| 	srcX = dstX + dx;
 | |
| 	
 | |
| 	if (upsidedown)
 | |
| 	{
 | |
| 	    dstY = pbox->y2 - 1;
 | |
| 	}
 | |
| 	else
 | |
| 	{
 | |
| 	    dstY = pbox->y1;
 | |
| 	    flags |= INC_Y;
 | |
| 	}
 | |
| 	srcY = dstY + dy;
 | |
| 	
 | |
| 	_s3Blt (s3, srcX, srcY, dstX, dstY, w, h, flags);
 | |
| 	pbox++;
 | |
|     }
 | |
|     MarkSyncS3 (pSrcDrawable->pScreen);
 | |
| }
 | |
| 
 | |
| RegionPtr
 | |
| s3_24CopyArea(DrawablePtr pSrcDrawable, DrawablePtr pDstDrawable, GCPtr pGC,
 | |
| 	   int srcx, int srcy, int width, int height, int dstx, int dsty)
 | |
| {
 | |
|     SetupS3(pDstDrawable->pScreen);
 | |
|     
 | |
|     if (pSrcDrawable->type == DRAWABLE_WINDOW &&
 | |
| 	pDstDrawable->type == DRAWABLE_WINDOW &&
 | |
| 	ok24(pGC->planemask))
 | |
|     {
 | |
| 	return fbDoCopy (pSrcDrawable, pDstDrawable, pGC, 
 | |
| 			 srcx, srcy, width, height, 
 | |
| 			 dstx, dsty, s3_24CopyNtoN, 0, 0);
 | |
|     }
 | |
|     return KdCheckCopyArea (pSrcDrawable, pDstDrawable, pGC, 
 | |
| 			    srcx, srcy, width, height, dstx, dsty);
 | |
| }
 | |
| 
 | |
| 
 | |
| #define NUM_STACK_RECTS	1024
 | |
| 
 | |
| void
 | |
| s3_24PolyFillRect (DrawablePtr pDrawable, GCPtr pGC, 
 | |
| 		   int nrectFill, xRectangle *prectInit)
 | |
| {
 | |
|     s3GCPrivate(pGC);
 | |
|     xRectangle	    *prect;
 | |
|     RegionPtr	    prgnClip;
 | |
|     register BoxPtr pbox;
 | |
|     register BoxPtr pboxClipped;
 | |
|     BoxPtr	    pboxClippedBase;
 | |
|     BoxPtr	    pextent;
 | |
|     BoxRec	    stackRects[NUM_STACK_RECTS];
 | |
|     int		    numRects;
 | |
|     int		    n;
 | |
|     int		    xorg, yorg;
 | |
|     int		    x, y;
 | |
| 
 | |
|     if (pGC->fillStyle != FillSolid || !ok24 (pGC->fgPixel) || !ok24(pGC->planemask))
 | |
|     {
 | |
| 	KdCheckPolyFillRect (pDrawable, pGC, nrectFill, prectInit);
 | |
| 	return;
 | |
|     }
 | |
|     
 | |
|     prgnClip = fbGetCompositeClip(pGC);
 | |
|     xorg = pDrawable->x;
 | |
|     yorg = pDrawable->y;
 | |
|     
 | |
|     if (xorg || yorg)
 | |
|     {
 | |
| 	prect = prectInit;
 | |
| 	n = nrectFill;
 | |
| 	while(n--)
 | |
| 	{
 | |
| 	    prect->x += xorg;
 | |
| 	    prect->y += yorg;
 | |
| 	    prect++;
 | |
| 	}
 | |
|     }
 | |
|     
 | |
|     prect = prectInit;
 | |
| 
 | |
|     numRects = REGION_NUM_RECTS(prgnClip) * nrectFill;
 | |
|     if (numRects > NUM_STACK_RECTS)
 | |
|     {
 | |
| 	pboxClippedBase = (BoxPtr)ALLOCATE_LOCAL(numRects * sizeof(BoxRec));
 | |
| 	if (!pboxClippedBase)
 | |
| 	    return;
 | |
|     }
 | |
|     else
 | |
| 	pboxClippedBase = stackRects;
 | |
| 
 | |
|     pboxClipped = pboxClippedBase;
 | |
| 	
 | |
|     if (REGION_NUM_RECTS(prgnClip) == 1)
 | |
|     {
 | |
| 	int x1, y1, x2, y2, bx2, by2;
 | |
| 
 | |
| 	pextent = REGION_RECTS(prgnClip);
 | |
| 	x1 = pextent->x1;
 | |
| 	y1 = pextent->y1;
 | |
| 	x2 = pextent->x2;
 | |
| 	y2 = pextent->y2;
 | |
|     	while (nrectFill--)
 | |
|     	{
 | |
| 	    if ((pboxClipped->x1 = prect->x) < x1)
 | |
| 		pboxClipped->x1 = x1;
 | |
|     
 | |
| 	    if ((pboxClipped->y1 = prect->y) < y1)
 | |
| 		pboxClipped->y1 = y1;
 | |
|     
 | |
| 	    bx2 = (int) prect->x + (int) prect->width;
 | |
| 	    if (bx2 > x2)
 | |
| 		bx2 = x2;
 | |
| 	    pboxClipped->x2 = bx2;
 | |
|     
 | |
| 	    by2 = (int) prect->y + (int) prect->height;
 | |
| 	    if (by2 > y2)
 | |
| 		by2 = y2;
 | |
| 	    pboxClipped->y2 = by2;
 | |
| 
 | |
| 	    prect++;
 | |
| 	    if ((pboxClipped->x1 < pboxClipped->x2) &&
 | |
| 		(pboxClipped->y1 < pboxClipped->y2))
 | |
| 	    {
 | |
| 		pboxClipped++;
 | |
| 	    }
 | |
|     	}
 | |
|     }
 | |
|     else
 | |
|     {
 | |
| 	int x1, y1, x2, y2, bx2, by2;
 | |
| 
 | |
| 	pextent = REGION_EXTENTS(pGC->pScreen, prgnClip);
 | |
| 	x1 = pextent->x1;
 | |
| 	y1 = pextent->y1;
 | |
| 	x2 = pextent->x2;
 | |
| 	y2 = pextent->y2;
 | |
|     	while (nrectFill--)
 | |
|     	{
 | |
| 	    BoxRec box;
 | |
|     
 | |
| 	    if ((box.x1 = prect->x) < x1)
 | |
| 		box.x1 = x1;
 | |
|     
 | |
| 	    if ((box.y1 = prect->y) < y1)
 | |
| 		box.y1 = y1;
 | |
|     
 | |
| 	    bx2 = (int) prect->x + (int) prect->width;
 | |
| 	    if (bx2 > x2)
 | |
| 		bx2 = x2;
 | |
| 	    box.x2 = bx2;
 | |
|     
 | |
| 	    by2 = (int) prect->y + (int) prect->height;
 | |
| 	    if (by2 > y2)
 | |
| 		by2 = y2;
 | |
| 	    box.y2 = by2;
 | |
|     
 | |
| 	    prect++;
 | |
|     
 | |
| 	    if ((box.x1 >= box.x2) || (box.y1 >= box.y2))
 | |
| 	    	continue;
 | |
|     
 | |
| 	    n = REGION_NUM_RECTS (prgnClip);
 | |
| 	    pbox = REGION_RECTS(prgnClip);
 | |
|     
 | |
| 	    /* clip the rectangle to each box in the clip region
 | |
| 	       this is logically equivalent to calling Intersect()
 | |
| 	    */
 | |
| 	    while(n--)
 | |
| 	    {
 | |
| 		pboxClipped->x1 = max(box.x1, pbox->x1);
 | |
| 		pboxClipped->y1 = max(box.y1, pbox->y1);
 | |
| 		pboxClipped->x2 = min(box.x2, pbox->x2);
 | |
| 		pboxClipped->y2 = min(box.y2, pbox->y2);
 | |
| 		pbox++;
 | |
| 
 | |
| 		/* see if clipping left anything */
 | |
| 		if(pboxClipped->x1 < pboxClipped->x2 && 
 | |
| 		   pboxClipped->y1 < pboxClipped->y2)
 | |
| 		{
 | |
| 		    pboxClipped++;
 | |
| 		}
 | |
| 	    }
 | |
|     	}
 | |
|     }
 | |
|     if (pboxClipped != pboxClippedBase)
 | |
|     {
 | |
| 	s3_24FillBoxSolid(pDrawable,
 | |
| 			  pboxClipped-pboxClippedBase, pboxClippedBase,
 | |
| 			  pGC->fgPixel, pGC->alu, pGC->planemask);
 | |
|     }
 | |
|     if (pboxClippedBase != stackRects)
 | |
|     	DEALLOCATE_LOCAL(pboxClippedBase);
 | |
| }
 | |
| 
 | |
| void
 | |
| s3_24SolidBoxClipped (DrawablePtr	pDrawable,
 | |
| 		      RegionPtr		pClip,
 | |
| 		      int		x1,
 | |
| 		      int		y1,
 | |
| 		      int		x2,
 | |
| 		      int		y2,
 | |
| 		      FbBits		fg)
 | |
| {
 | |
|     SetupS3 (pDrawable->pScreen);
 | |
|     BoxPtr	pbox;
 | |
|     int		nbox;
 | |
|     int		partX1, partX2, partY1, partY2;
 | |
|     
 | |
|     s3SetGlobalBitmap (pDrawable->pScreen, s3DrawMap (pDrawable));
 | |
|     _s3SetSolidFill(s3,fg,GXcopy,~0);
 | |
|     
 | |
|     for (nbox = REGION_NUM_RECTS(pClip), pbox = REGION_RECTS(pClip); 
 | |
| 	 nbox--; 
 | |
| 	 pbox++)
 | |
|     {
 | |
| 	partX1 = pbox->x1;
 | |
| 	if (partX1 < x1)
 | |
| 	    partX1 = x1;
 | |
| 	
 | |
| 	partX2 = pbox->x2;
 | |
| 	if (partX2 > x2)
 | |
| 	    partX2 = x2;
 | |
| 	
 | |
| 	if (partX2 <= partX1)
 | |
| 	    continue;
 | |
| 	
 | |
| 	partY1 = pbox->y1;
 | |
| 	if (partY1 < y1)
 | |
| 	    partY1 = y1;
 | |
| 	
 | |
| 	partY2 = pbox->y2;
 | |
| 	if (partY2 > y2)
 | |
| 	    partY2 = y2;
 | |
| 	
 | |
| 	if (partY2 <= partY1)
 | |
| 	    continue;
 | |
| 	
 | |
| 	partX1 *= 3;
 | |
| 	partX2 *= 3;
 | |
| 	_s3SolidRect(s3,partX1, partY1, partX2-partX1, partY2-partY1);
 | |
|     }
 | |
|     MarkSyncS3(pDrawable->pScreen);
 | |
| }
 | |
| 
 | |
| void
 | |
| s3_24ImageGlyphBlt (DrawablePtr	pDrawable,
 | |
| 		    GCPtr		pGC,
 | |
| 		    int		x, 
 | |
| 		    int		y,
 | |
| 		    unsigned int	nglyph,
 | |
| 		    CharInfoPtr	*ppciInit,
 | |
| 		    pointer	pglyphBase)
 | |
| {
 | |
|     FbGCPrivPtr	    pPriv = fbGetGCPrivate(pGC);
 | |
|     CharInfoPtr	    *ppci;
 | |
|     CharInfoPtr	    pci;
 | |
|     unsigned char   *pglyph;		/* pointer bits in glyph */
 | |
|     int		    gWidth, gHeight;	/* width and height of glyph */
 | |
|     FbStride	    gStride;		/* stride of glyph */
 | |
|     Bool	    opaque;
 | |
|     int		    n;
 | |
|     int		    gx, gy;
 | |
|     FbBits	    *dst;
 | |
|     FbStride	    dstStride;
 | |
|     int		    dstBpp;
 | |
|     int		    dstXoff, dstYoff;
 | |
|     FbBits	    depthMask;
 | |
|     int		    xBack, widthBack;
 | |
|     int		    yBack, heightBack;
 | |
|     
 | |
|     depthMask = FbFullMask(pDrawable->depth);
 | |
|     if (!ok24 (pGC->fgPixel) || 
 | |
| 	!ok24(pGC->bgPixel) || 
 | |
| 	!ok24(pGC->planemask))
 | |
|     {
 | |
| 	KdCheckImageGlyphBlt(pDrawable, pGC, x, y, nglyph, ppciInit, pglyphBase);
 | |
| 	return;
 | |
|     }
 | |
|     fbGetDrawable (pDrawable, dst, dstStride, dstBpp, dstXoff, dstYoff);
 | |
|     
 | |
|     x += pDrawable->x;
 | |
|     y += pDrawable->y;
 | |
| 
 | |
|     ppci = ppciInit;
 | |
|     n = nglyph;
 | |
|     widthBack = 0;
 | |
|     while (n--)
 | |
| 	widthBack += (*ppci++)->metrics.characterWidth;
 | |
|     
 | |
|     xBack = x;
 | |
|     if (widthBack < 0)
 | |
|     {
 | |
| 	xBack += widthBack;
 | |
| 	widthBack = -widthBack;
 | |
|     }
 | |
|     yBack = y - FONTASCENT(pGC->font);
 | |
|     heightBack = FONTASCENT(pGC->font) + FONTDESCENT(pGC->font);
 | |
|     s3_24SolidBoxClipped (pDrawable,
 | |
| 			  fbGetCompositeClip(pGC),
 | |
| 			  xBack,
 | |
| 			  yBack,
 | |
| 			  xBack + widthBack,
 | |
| 			  yBack + heightBack,
 | |
| 			  pPriv->bg);
 | |
| 
 | |
|     KdCheckSync (pDrawable->pScreen);
 | |
|     
 | |
|     ppci = ppciInit;
 | |
|     while (nglyph--)
 | |
|     {
 | |
| 	pci = *ppci++;
 | |
| 	pglyph = FONTGLYPHBITS(pglyphBase, pci);
 | |
| 	gWidth = GLYPHWIDTHPIXELS(pci);
 | |
| 	gHeight = GLYPHHEIGHTPIXELS(pci);
 | |
| 	if (gWidth && gHeight)
 | |
| 	{
 | |
| 	    gx = x + pci->metrics.leftSideBearing;
 | |
| 	    gy = y - pci->metrics.ascent; 
 | |
| 	    if (gWidth <= sizeof (FbStip) * 8 &&
 | |
| 		fbGlyphIn (fbGetCompositeClip(pGC), gx, gy, gWidth, gHeight))
 | |
| 	    {
 | |
| 		fbGlyph24 (dst + (gy - dstYoff) * dstStride,
 | |
| 			  dstStride,
 | |
| 			  dstBpp,
 | |
| 			  (FbStip *) pglyph,
 | |
| 			  pPriv->fg,
 | |
| 			  gx - dstXoff,
 | |
| 			  gHeight);
 | |
| 	    }
 | |
| 	    else
 | |
| 	    {
 | |
| 		gStride = GLYPHWIDTHBYTESPADDED(pci) / sizeof (FbStip);
 | |
| 		fbPutXYImage (pDrawable,
 | |
| 			      fbGetCompositeClip(pGC),
 | |
| 			      pPriv->fg,
 | |
| 			      pPriv->bg,
 | |
| 			      pPriv->pm,
 | |
| 			      GXcopy,
 | |
| 			      FALSE,
 | |
|     
 | |
| 			      gx,
 | |
| 			      gy,
 | |
| 			      gWidth, gHeight,
 | |
|     
 | |
| 			      (FbStip *) pglyph,
 | |
| 			      gStride,
 | |
| 			      0);
 | |
| 	    }
 | |
| 	}
 | |
| 	x += pci->metrics.characterWidth;
 | |
|     }
 | |
| }
 | |
| 
 | |
| static const GCOps	s3_24GCOps = {
 | |
|     s3_24FillSpans,
 | |
|     KdCheckSetSpans,
 | |
|     KdCheckPutImage,
 | |
|     KdCheckCopyArea,
 | |
|     KdCheckCopyPlane,
 | |
|     KdCheckPolyPoint,
 | |
|     KdCheckPolylines,
 | |
|     KdCheckPolySegment,
 | |
|     KdCheckPolyRectangle,
 | |
|     KdCheckPolyArc,
 | |
|     KdCheckFillPolygon,
 | |
|     s3_24PolyFillRect,
 | |
|     KdCheckPolyFillArc,
 | |
|     miPolyText8,
 | |
|     miPolyText16,
 | |
|     miImageText8,
 | |
|     miImageText16,
 | |
|     s3_24ImageGlyphBlt,
 | |
|     KdCheckPolyGlyphBlt,
 | |
|     KdCheckPushPixels,
 | |
| #ifdef NEED_LINEHELPER
 | |
|     ,NULL
 | |
| #endif
 | |
| };
 | |
| 
 | |
| void
 | |
| s3_24ValidateGC (GCPtr pGC, Mask changes, DrawablePtr pDrawable)
 | |
| {
 | |
|     if (pDrawable->type != DRAWABLE_WINDOW)
 | |
| 	pGC->ops = (GCOps *) &kdAsyncPixmapGCOps;
 | |
|     else
 | |
| 	pGC->ops = (GCOps *) &s3_24GCOps;
 | |
|     fbValidateGC (pGC, changes, pDrawable);
 | |
| }
 | |
| 
 | |
| GCFuncs	s3_24GCFuncs = {
 | |
|     s3_24ValidateGC,
 | |
|     miChangeGC,
 | |
|     miCopyGC,
 | |
|     miDestroyGC,
 | |
|     miChangeClip,
 | |
|     miDestroyClip,
 | |
|     miCopyClip
 | |
| };
 | |
| 
 | |
| Bool
 | |
| s3_24CreateGC (GCPtr pGC)
 | |
| {
 | |
|     if (!fbCreateGC (pGC))
 | |
| 	return FALSE;
 | |
| 
 | |
|     if (pGC->depth != 1)
 | |
| 	pGC->funcs = &s3_24GCFuncs;
 | |
|     
 | |
|     return TRUE;
 | |
| }
 | |
| 
 | |
| Bool
 | |
| s3_24CreateWindow(WindowPtr pWin)
 | |
| {
 | |
|     return fbCreateWindow (pWin);
 | |
| }
 | |
| 
 | |
| void
 | |
| s3_24PaintWindow(WindowPtr pWin, RegionPtr pRegion, int what)
 | |
| {
 | |
|     SetupS3(pWin->drawable.pScreen);
 | |
|     s3PatternPtr    pPattern;
 | |
| 
 | |
|     DRAW_DEBUG ((DEBUG_PAINT_WINDOW, "s3PaintWindow 0x%x extents %d %d %d %d n %d",
 | |
| 		 pWin->drawable.id,
 | |
| 		 pRegion->extents.x1, pRegion->extents.y1,
 | |
| 		 pRegion->extents.x2, pRegion->extents.y2,
 | |
| 		 REGION_NUM_RECTS(pRegion)));
 | |
|     if (!REGION_NUM_RECTS(pRegion)) 
 | |
| 	return;
 | |
|     switch (what) {
 | |
|     case PW_BACKGROUND:
 | |
| 	switch (pWin->backgroundState) {
 | |
| 	case None:
 | |
| 	    return;
 | |
| 	case ParentRelative:
 | |
| 	    do {
 | |
| 		pWin = pWin->parent;
 | |
| 	    } while (pWin->backgroundState == ParentRelative);
 | |
| 	    (*pWin->drawable.pScreen->PaintWindowBackground)(pWin, pRegion,
 | |
| 							     what);
 | |
| 	    return;
 | |
| 	case BackgroundPixel:
 | |
| 	    if (ok24(pWin->background.pixel))
 | |
| 	    {
 | |
| 		s3_24FillBoxSolid((DrawablePtr)pWin,
 | |
| 				  (int)REGION_NUM_RECTS(pRegion),
 | |
| 				  REGION_RECTS(pRegion),
 | |
| 				  pWin->background.pixel, GXcopy, ~0);
 | |
| 		return;
 | |
| 	    }
 | |
|     	}
 | |
|     	break;
 | |
|     case PW_BORDER:
 | |
| 	if (pWin->borderIsPixel && ok24(pWin->border.pixel))
 | |
| 	{
 | |
| 	    s3_24FillBoxSolid((DrawablePtr)pWin,
 | |
| 			      (int)REGION_NUM_RECTS(pRegion),
 | |
| 			      REGION_RECTS(pRegion),
 | |
| 			      pWin->border.pixel, GXcopy, ~0);
 | |
| 	    return;
 | |
| 	}
 | |
| 	break;
 | |
|     }
 | |
|     KdCheckPaintWindow (pWin, pRegion, what);
 | |
| }
 | |
| 
 | |
| Bool
 | |
| s3DrawInit (ScreenPtr pScreen)
 | |
| {
 | |
|     KdScreenPriv(pScreen);
 | |
|     s3ScreenInfo(pScreenPriv);
 | |
|     int		    ncache_w, ncache_h, ncache;
 | |
|     int		    px, py;
 | |
|     S3PatternCache  *cache;
 | |
|     Bool	    dumb = FALSE;
 | |
|     int		    ma;
 | |
| 
 | |
|     switch (pScreenPriv->screen->fb[0].bitsPerPixel) {
 | |
|     case 8:
 | |
|     case 16:
 | |
|     case 32:
 | |
| 	break;
 | |
|     case 24:
 | |
| 	dumb = TRUE;
 | |
| 	break;
 | |
|     default:
 | |
| 	return FALSE;
 | |
|     }
 | |
|     /*
 | |
|      * Hook up asynchronous drawing
 | |
|      */
 | |
|     RegisterSync (pScreen);
 | |
|     /*
 | |
|      * Replace various fb screen functions
 | |
|      */
 | |
|     if (dumb)
 | |
|     {
 | |
| 	pScreen->CreateGC = s3_24CreateGC;
 | |
| 	pScreen->CreateWindow = s3_24CreateWindow;
 | |
| 	pScreen->PaintWindowBackground = s3_24PaintWindow;
 | |
| 	pScreen->PaintWindowBorder = s3_24PaintWindow;
 | |
| 	pScreen->CopyWindow = s3CopyWindow;
 | |
|     }
 | |
|     else
 | |
|     {
 | |
| 	if (serverGeneration != s3Generation)
 | |
| 	{
 | |
| 	    s3GCPrivateIndex = AllocateGCPrivateIndex ();
 | |
| 	    s3WindowPrivateIndex = AllocateWindowPrivateIndex ();
 | |
| 	    s3Generation = serverGeneration;
 | |
| 	}
 | |
| 	if (!AllocateWindowPrivate(pScreen, s3WindowPrivateIndex, 0))
 | |
| 	    return FALSE;
 | |
| 	if (!AllocateGCPrivate(pScreen, s3GCPrivateIndex, sizeof (s3PrivGCRec)))
 | |
| 	    return FALSE;
 | |
| 	pScreen->CreateGC = s3CreateGC;
 | |
| 	pScreen->CreateWindow = s3CreateWindow;
 | |
| 	pScreen->ChangeWindowAttributes = s3ChangeWindowAttributes;
 | |
| 	pScreen->DestroyWindow = s3DestroyWindow;
 | |
| 	pScreen->PaintWindowBackground = s3PaintWindow;
 | |
| 	pScreen->PaintWindowBorder = s3PaintWindow;
 | |
| #ifndef S3_TRIO
 | |
| 	if (pScreenPriv->screen->fb[1].depth)
 | |
| 	{
 | |
| 	    FbOverlayScrPrivPtr pScrPriv = fbOverlayGetScrPriv(pScreen);
 | |
| 
 | |
| 	    pScrPriv->PaintKey = s3PaintKey;
 | |
| 	    pScrPriv->CopyWindow = s3CopyWindowProc;
 | |
| 	    pScreen->CopyWindow = fbOverlayCopyWindow;
 | |
| 	}
 | |
| 	else
 | |
| #endif
 | |
| 	    pScreen->CopyWindow = s3CopyWindow;
 | |
| 	
 | |
| 	/*
 | |
| 	 * Initialize patterns
 | |
| 	 */
 | |
| #ifdef S3_TRIO
 | |
| 	ma = 0;
 | |
| #else
 | |
| 	for (ma = 0; s3s->fbmap[ma] >= 0; ma++)
 | |
| #endif
 | |
| 	{
 | |
| 	    ncache_w = s3s->fb[ma].offscreen_width / S3_TILE_SIZE;
 | |
| 	    ncache_h = s3s->fb[ma].offscreen_height / S3_TILE_SIZE;
 | |
| 	    ncache = ncache_w * ncache_h;
 | |
| 	    if (ncache > 64)
 | |
| 		ncache = 64;
 | |
| 	    DRAW_DEBUG ((DEBUG_S3INIT, "ncache_w %d ncache_h %d ncache %d",
 | |
| 			 ncache_w, ncache_h, ncache));
 | |
| 	    s3s->fb[ma].patterns.cache = (S3PatternCache *) xalloc (ncache * sizeof (S3PatternCache));
 | |
| 	    if (s3s->fb[ma].patterns.cache)
 | |
| 	    {
 | |
| 		DRAW_DEBUG ((DEBUG_S3INIT, "Have pattern cache"));
 | |
| 		s3s->fb[ma].patterns.ncache = ncache;
 | |
| 		s3s->fb[ma].patterns.last_used = 0;
 | |
| 		s3s->fb[ma].patterns.last_id = 0;
 | |
| 		cache = s3s->fb[ma].patterns.cache;
 | |
| 		for (py = 0; py < ncache_h && ncache; py++)
 | |
| 		    for (px = 0; px < ncache_w && ncache; px++)
 | |
| 		    {
 | |
| 			cache->id = 0;
 | |
| 			cache->x = s3s->fb[ma].offscreen_x + px * S3_TILE_SIZE;
 | |
| 			cache->y = s3s->fb[ma].offscreen_y + py * S3_TILE_SIZE;
 | |
| 			cache++;
 | |
| 			ncache--;
 | |
| 		    }
 | |
| 	    }
 | |
| 	}
 | |
|     }
 | |
|     return TRUE;
 | |
| }
 | |
| 
 | |
| void
 | |
| s3DrawEnable (ScreenPtr pScreen)
 | |
| {
 | |
|     SetupS3(pScreen);
 | |
|     s3ScreenInfo(pScreenPriv);
 | |
|     int	    c;
 | |
|     int	    ma;
 | |
|     
 | |
|     s3SetGlobalBitmap (pScreen, 0);
 | |
|     _s3WaitIdleEmpty (s3);
 | |
|     if (pScreenPriv->screen->fb[0].bitsPerPixel == 24)
 | |
|     {
 | |
| 	_s3SetScissorsTl(s3, 0, 0);
 | |
| 	_s3SetScissorsBr(s3, pScreenPriv->screen->width*3 - 1, pScreenPriv->screen->height - 1);
 | |
| 	_s3SetSolidFill(s3, pScreen->whitePixel, GXcopy, ~0);
 | |
| 	_s3SolidRect (s3, 0, 0, pScreenPriv->screen->width*3, pScreenPriv->screen->height);
 | |
|     }
 | |
|     else
 | |
|     {
 | |
| 	/*
 | |
| 	 * Flush pattern cache
 | |
| 	 */
 | |
| #ifdef S3_TRIO
 | |
| 	ma = 0;
 | |
| #else
 | |
| 	for (ma = 0; s3s->fbmap[ma] >= 0; ma++)
 | |
| #endif
 | |
| 	{
 | |
| 	    for (c = 0; c < s3s->fb[ma].patterns.ncache; c++)
 | |
| 		s3s->fb[ma].patterns.cache[c].id = 0;
 | |
| 	}
 | |
| 
 | |
| 	_s3SetScissorsTl(s3, 0, 0);
 | |
| 	_s3SetScissorsBr(s3, pScreenPriv->screen->width - 1, pScreenPriv->screen->height - 1);
 | |
| 	_s3SetSolidFill(s3, pScreen->blackPixel, GXcopy, ~0);
 | |
| 	_s3SolidRect (s3, 0, 0, pScreenPriv->screen->width, pScreenPriv->screen->height);
 | |
|     }
 | |
|     MarkSyncS3 (pScreen);
 | |
| }
 | |
| 
 | |
| void
 | |
| s3DrawDisable (ScreenPtr pScreen)
 | |
| {
 | |
|     SetupS3 (pScreen);
 | |
|     _s3WaitIdleEmpty (s3);
 | |
| }
 | |
| 
 | |
| void
 | |
| s3DrawFini (ScreenPtr pScreen)
 | |
| {
 | |
|     SetupS3(pScreen);
 | |
|     s3ScreenInfo(pScreenPriv);
 | |
|     int	    ma;
 | |
|     
 | |
| #ifdef S3_TRIO
 | |
|     ma = 0;
 | |
| #else
 | |
|     for (ma = 0; s3s->fbmap[ma] >= 0; ma++)
 | |
| #endif
 | |
|     {
 | |
| 	if (s3s->fb[ma].patterns.cache)
 | |
| 	{
 | |
| 	    xfree (s3s->fb[ma].patterns.cache);
 | |
| 	    s3s->fb[ma].patterns.cache = 0;
 | |
| 	    s3s->fb[ma].patterns.ncache = 0;
 | |
| 	}
 | |
|     }
 | |
| }
 | |
| 
 | |
| void
 | |
| s3DrawSync (ScreenPtr pScreen)
 | |
| {
 | |
|     SetupS3(pScreen);
 | |
|     
 | |
|     _s3WaitIdleEmpty(s3c->s3);
 | |
| }
 |