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