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);
 | 
						|
}
 |