315 lines
		
	
	
		
			7.1 KiB
		
	
	
	
		
			C
		
	
	
	
			
		
		
	
	
			315 lines
		
	
	
		
			7.1 KiB
		
	
	
	
		
			C
		
	
	
	
/*
 | 
						|
 * Id: fbstipple.c,v 1.1 1999/11/02 03:54:45 keithp Exp $
 | 
						|
 *
 | 
						|
 * Copyright © 1998 Keith Packard
 | 
						|
 *
 | 
						|
 * 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 Keith Packard not be used in
 | 
						|
 * advertising or publicity pertaining to distribution of the software without
 | 
						|
 * specific, written prior permission.  Keith Packard makes no
 | 
						|
 * representations about the suitability of this software for any purpose.  It
 | 
						|
 * is provided "as is" without express or implied warranty.
 | 
						|
 *
 | 
						|
 * KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
 | 
						|
 * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
 | 
						|
 * EVENT SHALL KEITH PACKARD 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.
 | 
						|
 */
 | 
						|
 | 
						|
#ifdef HAVE_DIX_CONFIG_H
 | 
						|
#include <dix-config.h>
 | 
						|
#endif
 | 
						|
 | 
						|
#include "fb.h"
 | 
						|
 | 
						|
#ifndef FBNOPIXADDR
 | 
						|
/*
 | 
						|
 * This is a slight abuse of the preprocessor to generate repetitive
 | 
						|
 * code, the idea is to generate code for each case of a copy-mode
 | 
						|
 * transparent stipple
 | 
						|
 */
 | 
						|
#define LaneCases1(c,a)	    case c: \
 | 
						|
				while (n--) { (void)FbLaneCase(c,a); a++; } \
 | 
						|
				break
 | 
						|
#define LaneCases2(c,a)	    LaneCases1(c,a); LaneCases1(c+1,a)
 | 
						|
#define LaneCases4(c,a)	    LaneCases2(c,a); LaneCases2(c+2,a)
 | 
						|
#define LaneCases8(c,a)	    LaneCases4(c,a); LaneCases4(c+4,a)
 | 
						|
#define LaneCases16(c,a)    LaneCases8(c,a); LaneCases8(c+8,a)
 | 
						|
#define LaneCases32(c,a)    LaneCases16(c,a); LaneCases16(c+16,a)
 | 
						|
#define LaneCases64(c,a)    LaneCases32(c,a); LaneCases32(c+32,a)
 | 
						|
#define LaneCases128(c,a)   LaneCases64(c,a); LaneCases64(c+64,a)
 | 
						|
#define LaneCases256(c,a)   LaneCases128(c,a); LaneCases128(c+128,a)
 | 
						|
    
 | 
						|
#if FB_SHIFT == 6
 | 
						|
#define LaneCases(a)	    LaneCases256(0,a)
 | 
						|
#endif
 | 
						|
    
 | 
						|
#if FB_SHIFT == 5
 | 
						|
#define LaneCases(a)	    LaneCases16(0,a)
 | 
						|
#endif
 | 
						|
							   
 | 
						|
/*
 | 
						|
 * Repeat a transparent stipple across a scanline n times
 | 
						|
 */
 | 
						|
 | 
						|
void
 | 
						|
fbTransparentSpan (FbBits   *dst,
 | 
						|
		   FbBits   stip,
 | 
						|
		   FbBits   fgxor,
 | 
						|
		   int	    n)
 | 
						|
{
 | 
						|
    FbStip  s;
 | 
						|
 | 
						|
    s  = ((FbStip) (stip      ) & 0x01);
 | 
						|
    s |= ((FbStip) (stip >>  8) & 0x02);
 | 
						|
    s |= ((FbStip) (stip >> 16) & 0x04);
 | 
						|
    s |= ((FbStip) (stip >> 24) & 0x08);
 | 
						|
#if FB_SHIFT > 5
 | 
						|
    s |= ((FbStip) (stip >> 32) & 0x10);
 | 
						|
    s |= ((FbStip) (stip >> 40) & 0x20);
 | 
						|
    s |= ((FbStip) (stip >> 48) & 0x40);
 | 
						|
    s |= ((FbStip) (stip >> 56) & 0x80);
 | 
						|
#endif
 | 
						|
    switch (s) {
 | 
						|
	LaneCases(dst);
 | 
						|
    }
 | 
						|
}
 | 
						|
#endif
 | 
						|
 | 
						|
void
 | 
						|
fbEvenStipple (FbBits	*dst,
 | 
						|
	       FbStride	dstStride,
 | 
						|
	       int	dstX,
 | 
						|
	       int	dstBpp,
 | 
						|
 | 
						|
	       int	width,
 | 
						|
	       int	height,
 | 
						|
 | 
						|
	       FbStip	*stip,
 | 
						|
	       FbStride	stipStride,
 | 
						|
	       int	stipHeight,
 | 
						|
 | 
						|
	       FbBits	fgand,
 | 
						|
	       FbBits	fgxor,
 | 
						|
	       FbBits	bgand,
 | 
						|
	       FbBits	bgxor,
 | 
						|
 | 
						|
	       int	xRot,
 | 
						|
	       int	yRot)
 | 
						|
{
 | 
						|
    FbBits	startmask, endmask;
 | 
						|
    FbBits	mask, and, xor;
 | 
						|
    int		nmiddle, n;
 | 
						|
    FbStip	*s, *stipEnd, bits;
 | 
						|
    int		rot, stipX, stipY;
 | 
						|
    int		pixelsPerDst;
 | 
						|
    const FbBits    *fbBits;
 | 
						|
    Bool	transparent;
 | 
						|
    int		startbyte, endbyte;
 | 
						|
    
 | 
						|
    /*
 | 
						|
     * Check for a transparent stipple (stencil)
 | 
						|
     */
 | 
						|
    transparent = FALSE;
 | 
						|
    if (dstBpp >= 8 &&
 | 
						|
	fgand == 0 && bgand == FB_ALLONES && bgxor == 0)
 | 
						|
	transparent = TRUE;
 | 
						|
    
 | 
						|
    pixelsPerDst = FB_UNIT / dstBpp;
 | 
						|
    /*
 | 
						|
     * Adjust dest pointers
 | 
						|
     */
 | 
						|
    dst += dstX >> FB_SHIFT;
 | 
						|
    dstX &= FB_MASK;
 | 
						|
    FbMaskBitsBytes (dstX, width, fgand == 0 && bgand == 0,
 | 
						|
		     startmask, startbyte, nmiddle, endmask, endbyte);
 | 
						|
		     
 | 
						|
    if (startmask)
 | 
						|
	dstStride--;
 | 
						|
    dstStride -= nmiddle;
 | 
						|
    
 | 
						|
    xRot *= dstBpp;
 | 
						|
    /*
 | 
						|
     * Compute stip start scanline and rotation parameters
 | 
						|
     */
 | 
						|
    stipEnd = stip + stipStride * stipHeight;
 | 
						|
    modulus (- yRot, stipHeight, stipY);
 | 
						|
    s = stip + stipStride * stipY;
 | 
						|
    modulus (- xRot, FB_UNIT, stipX);
 | 
						|
    rot = stipX;
 | 
						|
    
 | 
						|
    /*
 | 
						|
     * Get pointer to stipple mask array for this depth
 | 
						|
     */
 | 
						|
    /* fbStippleTable covers all valid bpp (4,8,16,32) */
 | 
						|
    fbBits = fbStippleTable[pixelsPerDst];
 | 
						|
    
 | 
						|
    while (height--)
 | 
						|
    {
 | 
						|
	/*
 | 
						|
	 * Extract stipple bits for this scanline;
 | 
						|
	 */
 | 
						|
	bits = READ(s);
 | 
						|
	s += stipStride;
 | 
						|
	if (s == stipEnd)
 | 
						|
	    s = stip;
 | 
						|
#if FB_UNIT > 32
 | 
						|
	if (pixelsPerDst == 16)
 | 
						|
	    mask = FbStipple16Bits(FbLeftStipBits(bits,16));
 | 
						|
	else
 | 
						|
#endif
 | 
						|
	    mask = fbBits[FbLeftStipBits(bits,pixelsPerDst)];
 | 
						|
	/*
 | 
						|
	 * Rotate into position and compute reduced rop values
 | 
						|
	 */
 | 
						|
	mask = FbRotLeft(mask, rot);
 | 
						|
	and = (fgand & mask) | (bgand & ~mask);
 | 
						|
	xor = (fgxor & mask) | (bgxor & ~mask);
 | 
						|
	
 | 
						|
#ifndef FBNOPIXADDR
 | 
						|
	if (transparent)
 | 
						|
	{
 | 
						|
	    if (startmask)
 | 
						|
	    {
 | 
						|
		fbTransparentSpan(dst, mask&startmask, fgxor, 1);
 | 
						|
		dst++;
 | 
						|
	    }
 | 
						|
	    fbTransparentSpan (dst, mask, fgxor, nmiddle);
 | 
						|
	    dst += nmiddle;
 | 
						|
	    if (endmask)
 | 
						|
		fbTransparentSpan(dst, mask&endmask, fgxor, 1);
 | 
						|
	}
 | 
						|
	else
 | 
						|
#endif
 | 
						|
	{
 | 
						|
	    /*
 | 
						|
	     * Fill scanline
 | 
						|
	     */
 | 
						|
	    if (startmask)
 | 
						|
	    {
 | 
						|
		FbDoLeftMaskByteRRop (dst, startbyte, startmask, and, xor);
 | 
						|
		dst++;
 | 
						|
	    }
 | 
						|
	    n = nmiddle;
 | 
						|
	    if (!and)
 | 
						|
		while (n--)
 | 
						|
		    WRITE(dst++, xor);
 | 
						|
	    else
 | 
						|
	    {
 | 
						|
		while (n--)
 | 
						|
		{
 | 
						|
		    WRITE(dst, FbDoRRop (READ(dst), and, xor));
 | 
						|
		    dst++;
 | 
						|
		}
 | 
						|
	    }
 | 
						|
	    if (endmask)
 | 
						|
		FbDoRightMaskByteRRop(dst, endbyte, endmask, and, xor);
 | 
						|
	}
 | 
						|
	dst += dstStride;
 | 
						|
    }
 | 
						|
}
 | 
						|
 | 
						|
void
 | 
						|
fbOddStipple (FbBits	*dst,
 | 
						|
	      FbStride	dstStride,
 | 
						|
	      int	dstX,
 | 
						|
	      int	dstBpp,
 | 
						|
 | 
						|
	      int	width,
 | 
						|
	      int	height,
 | 
						|
 | 
						|
	      FbStip	*stip,
 | 
						|
	      FbStride	stipStride,
 | 
						|
	      int	stipWidth,
 | 
						|
	      int	stipHeight,
 | 
						|
 | 
						|
	      FbBits	fgand,
 | 
						|
	      FbBits	fgxor,
 | 
						|
	      FbBits	bgand,
 | 
						|
	      FbBits	bgxor,
 | 
						|
 | 
						|
	      int	xRot,
 | 
						|
	      int	yRot)
 | 
						|
{
 | 
						|
    int		stipX, stipY, sx;
 | 
						|
    int		widthTmp;
 | 
						|
    int		h, w;
 | 
						|
    int		x, y;
 | 
						|
 | 
						|
    modulus (- yRot, stipHeight, stipY);
 | 
						|
    modulus (dstX / dstBpp - xRot, stipWidth, stipX);
 | 
						|
    y = 0;
 | 
						|
    while (height)
 | 
						|
    {
 | 
						|
	h = stipHeight - stipY;
 | 
						|
	if (h > height)
 | 
						|
	    h = height;
 | 
						|
	height -= h;
 | 
						|
	widthTmp = width;
 | 
						|
	x = dstX;
 | 
						|
	sx = stipX;
 | 
						|
	while (widthTmp)
 | 
						|
	{
 | 
						|
	    w = (stipWidth - sx) * dstBpp;
 | 
						|
	    if (w > widthTmp)
 | 
						|
		w = widthTmp;
 | 
						|
	    widthTmp -= w;
 | 
						|
	    fbBltOne (stip + stipY * stipStride,
 | 
						|
		      stipStride,
 | 
						|
		      sx,
 | 
						|
 | 
						|
		      dst + y * dstStride,
 | 
						|
		      dstStride,
 | 
						|
		      x,
 | 
						|
		      dstBpp,
 | 
						|
 | 
						|
		      w, h,
 | 
						|
 | 
						|
		      fgand, fgxor, bgand, bgxor);
 | 
						|
	    x += w;
 | 
						|
	    sx = 0;
 | 
						|
	}
 | 
						|
	y += h;
 | 
						|
	stipY = 0;
 | 
						|
    }
 | 
						|
}
 | 
						|
 | 
						|
void
 | 
						|
fbStipple (FbBits	*dst,
 | 
						|
	   FbStride	dstStride,
 | 
						|
	   int		dstX,
 | 
						|
	   int		dstBpp,
 | 
						|
 | 
						|
	   int		width,
 | 
						|
	   int		height,
 | 
						|
 | 
						|
	   FbStip	*stip,
 | 
						|
	   FbStride	stipStride,
 | 
						|
	   int		stipWidth,
 | 
						|
	   int		stipHeight,
 | 
						|
	   Bool		even,
 | 
						|
 | 
						|
	   FbBits	fgand,
 | 
						|
	   FbBits	fgxor,
 | 
						|
	   FbBits	bgand,
 | 
						|
	   FbBits	bgxor,
 | 
						|
 | 
						|
	   int		xRot,
 | 
						|
	   int		yRot)
 | 
						|
{
 | 
						|
    if (even)
 | 
						|
	fbEvenStipple (dst, dstStride, dstX, dstBpp, width, height,
 | 
						|
		       stip, stipStride, stipHeight,
 | 
						|
		       fgand, fgxor, bgand, bgxor, xRot, yRot);
 | 
						|
    else
 | 
						|
	fbOddStipple (dst, dstStride, dstX, dstBpp, width, height,
 | 
						|
		      stip, stipStride, stipWidth, stipHeight,
 | 
						|
		      fgand, fgxor, bgand, bgxor, xRot, yRot);
 | 
						|
}
 |