265 lines
		
	
	
		
			7.7 KiB
		
	
	
	
		
			C
		
	
	
	
			
		
		
	
	
			265 lines
		
	
	
		
			7.7 KiB
		
	
	
	
		
			C
		
	
	
	
/*
 | 
						|
 * 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"
 | 
						|
 | 
						|
/*
 | 
						|
 * 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--) { 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);
 | 
						|
    }
 | 
						|
}
 | 
						|
 | 
						|
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);
 | 
						|
 | 
						|
        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 {
 | 
						|
            /*
 | 
						|
             * 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);
 | 
						|
}
 |